diff --git a/Arcade_MiST/Konami Jackal/Jackal.qpf b/Arcade_MiST/Konami Jackal/Jackal.qpf
new file mode 100644
index 00000000..45443300
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/Jackal.qpf
@@ -0,0 +1,31 @@
+# -------------------------------------------------------------------------- #
+#
+# Copyright (C) 1991-2013 Altera Corporation
+# Your use of Altera Corporation's design tools, logic functions
+# and other software and tools, and its AMPP partner logic
+# functions, and any output files from any of the foregoing
+# (including device programming or simulation files), and any
+# associated documentation or information are expressly subject
+# to the terms and conditions of the Altera Program License
+# Subscription Agreement, Altera MegaCore Function License
+# Agreement, or other applicable license agreement, including,
+# without limitation, that your use is for the sole purpose of
+# programming logic devices manufactured by Altera and sold by
+# Altera or its authorized distributors. Please refer to the
+# applicable agreement for further details.
+#
+# -------------------------------------------------------------------------- #
+#
+# Quartus II 64-Bit
+# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition
+# Date created = 00:21:03 December 03, 2019
+#
+# -------------------------------------------------------------------------- #
+
+QUARTUS_VERSION = "13.1"
+DATE = "00:21:03 December 03, 2019"
+
+# Revisions
+
+PROJECT_REVISION = "Jackal"
+
diff --git a/Arcade_MiST/Konami Jackal/Jackal.qsf b/Arcade_MiST/Konami Jackal/Jackal.qsf
new file mode 100644
index 00000000..6bcbe867
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/Jackal.qsf
@@ -0,0 +1,249 @@
+# -------------------------------------------------------------------------- #
+#
+# Copyright (C) 1991-2014 Altera Corporation
+# Your use of Altera Corporation's design tools, logic functions
+# and other software and tools, and its AMPP partner logic
+# functions, and any output files from any of the foregoing
+# (including device programming or simulation files), and any
+# associated documentation or information are expressly subject
+# to the terms and conditions of the Altera Program License
+# Subscription Agreement, Altera MegaCore Function License
+# Agreement, or other applicable license agreement, including,
+# without limitation, that your use is for the sole purpose of
+# programming logic devices manufactured by Altera and sold by
+# Altera or its authorized distributors. Please refer to the
+# applicable agreement for further details.
+#
+# -------------------------------------------------------------------------- #
+#
+# Quartus II 64-Bit
+# Version 13.1.4 Build 182 03/12/2014 SJ Full Version
+# Date created = 19:54:12 November 22, 2020
+#
+# -------------------------------------------------------------------------- #
+#
+# Notes:
+#
+# 1) The default values for assignments are stored in the file:
+# Jackal_assignment_defaults.qdf
+# If this file doesn't exist, see file:
+# assignment_defaults.qdf
+#
+# 2) Altera recommends that you do not modify this file. This
+# file is updated automatically by the Quartus II software
+# and any changes you make may be lost or overwritten.
+#
+# -------------------------------------------------------------------------- #
+
+
+
+# Project-Wide Assignments
+# ========================
+set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
+set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
+set_global_assignment -name LAST_QUARTUS_VERSION "13.1 SP4.26"
+set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:rtl/build_id.tcl"
+
+# Pin & Location Assignments
+# ==========================
+set_location_assignment PIN_7 -to LED
+set_location_assignment PIN_54 -to CLOCK_27
+set_location_assignment PIN_144 -to VGA_R[5]
+set_location_assignment PIN_143 -to VGA_R[4]
+set_location_assignment PIN_142 -to VGA_R[3]
+set_location_assignment PIN_141 -to VGA_R[2]
+set_location_assignment PIN_137 -to VGA_R[1]
+set_location_assignment PIN_135 -to VGA_R[0]
+set_location_assignment PIN_133 -to VGA_B[5]
+set_location_assignment PIN_132 -to VGA_B[4]
+set_location_assignment PIN_125 -to VGA_B[3]
+set_location_assignment PIN_121 -to VGA_B[2]
+set_location_assignment PIN_120 -to VGA_B[1]
+set_location_assignment PIN_115 -to VGA_B[0]
+set_location_assignment PIN_114 -to VGA_G[5]
+set_location_assignment PIN_113 -to VGA_G[4]
+set_location_assignment PIN_112 -to VGA_G[3]
+set_location_assignment PIN_111 -to VGA_G[2]
+set_location_assignment PIN_110 -to VGA_G[1]
+set_location_assignment PIN_106 -to VGA_G[0]
+set_location_assignment PIN_136 -to VGA_VS
+set_location_assignment PIN_119 -to VGA_HS
+set_location_assignment PIN_65 -to AUDIO_L
+set_location_assignment PIN_80 -to AUDIO_R
+set_location_assignment PIN_105 -to SPI_DO
+set_location_assignment PIN_88 -to SPI_DI
+set_location_assignment PIN_126 -to SPI_SCK
+set_location_assignment PIN_127 -to SPI_SS2
+set_location_assignment PIN_91 -to SPI_SS3
+set_location_assignment PIN_13 -to CONF_DATA0
+set_location_assignment PIN_49 -to SDRAM_A[0]
+set_location_assignment PIN_44 -to SDRAM_A[1]
+set_location_assignment PIN_42 -to SDRAM_A[2]
+set_location_assignment PIN_39 -to SDRAM_A[3]
+set_location_assignment PIN_4 -to SDRAM_A[4]
+set_location_assignment PIN_6 -to SDRAM_A[5]
+set_location_assignment PIN_8 -to SDRAM_A[6]
+set_location_assignment PIN_10 -to SDRAM_A[7]
+set_location_assignment PIN_11 -to SDRAM_A[8]
+set_location_assignment PIN_28 -to SDRAM_A[9]
+set_location_assignment PIN_50 -to SDRAM_A[10]
+set_location_assignment PIN_30 -to SDRAM_A[11]
+set_location_assignment PIN_32 -to SDRAM_A[12]
+set_location_assignment PIN_83 -to SDRAM_DQ[0]
+set_location_assignment PIN_79 -to SDRAM_DQ[1]
+set_location_assignment PIN_77 -to SDRAM_DQ[2]
+set_location_assignment PIN_76 -to SDRAM_DQ[3]
+set_location_assignment PIN_72 -to SDRAM_DQ[4]
+set_location_assignment PIN_71 -to SDRAM_DQ[5]
+set_location_assignment PIN_69 -to SDRAM_DQ[6]
+set_location_assignment PIN_68 -to SDRAM_DQ[7]
+set_location_assignment PIN_86 -to SDRAM_DQ[8]
+set_location_assignment PIN_87 -to SDRAM_DQ[9]
+set_location_assignment PIN_98 -to SDRAM_DQ[10]
+set_location_assignment PIN_99 -to SDRAM_DQ[11]
+set_location_assignment PIN_100 -to SDRAM_DQ[12]
+set_location_assignment PIN_101 -to SDRAM_DQ[13]
+set_location_assignment PIN_103 -to SDRAM_DQ[14]
+set_location_assignment PIN_104 -to SDRAM_DQ[15]
+set_location_assignment PIN_58 -to SDRAM_BA[0]
+set_location_assignment PIN_51 -to SDRAM_BA[1]
+set_location_assignment PIN_85 -to SDRAM_DQMH
+set_location_assignment PIN_67 -to SDRAM_DQML
+set_location_assignment PIN_60 -to SDRAM_nRAS
+set_location_assignment PIN_64 -to SDRAM_nCAS
+set_location_assignment PIN_66 -to SDRAM_nWE
+set_location_assignment PIN_59 -to SDRAM_nCS
+set_location_assignment PIN_33 -to SDRAM_CKE
+set_location_assignment PIN_43 -to SDRAM_CLK
+set_location_assignment PLL_1 -to "pll:pll|altpll:altpll_component"
+
+# Classic Timing Assignments
+# ==========================
+set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
+set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
+
+# Analysis & Synthesis Assignments
+# ================================
+set_global_assignment -name FAMILY "Cyclone III"
+set_global_assignment -name TOP_LEVEL_ENTITY Jackal_MiST
+set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144
+set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8
+set_global_assignment -name DEVICE_FILTER_PACKAGE TQFP
+
+# Fitter Assignments
+# ==================
+set_global_assignment -name DEVICE EP3C25E144C8
+set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF
+set_global_assignment -name ENABLE_NCE_PIN OFF
+set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF
+set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL"
+set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF
+set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON
+set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
+set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"
+set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO"
+set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO"
+set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO"
+set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO"
+
+# Assembler Assignments
+# =====================
+set_global_assignment -name GENERATE_RBF_FILE ON
+set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
+
+# SignalTap II Assignments
+# ========================
+set_global_assignment -name ENABLE_SIGNALTAP OFF
+set_global_assignment -name USE_SIGNALTAP_FILE output_files/jackal.stp
+
+# Power Estimation Assignments
+# ============================
+set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW"
+set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
+
+# Advanced I/O Timing Assignments
+# ===============================
+set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise
+set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall
+set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise
+set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall
+
+# ------------------------------
+# start ENTITY(Jackal_MiST)
+
+ # Pin & Location Assignments
+ # ==========================
+
+ # Fitter Assignments
+ # ==================
+
+ # start DESIGN_PARTITION(Top)
+ # ---------------------------
+
+ # Incremental Compilation Assignments
+ # ===================================
+
+ # end DESIGN_PARTITION(Top)
+ # -------------------------
+
+# end ENTITY(Jackal_MiST)
+# ----------------------------
+set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS ON
+set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON
+set_global_assignment -name SMART_RECOMPILE ON
+set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
+set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
+set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
+set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[*]
+set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[*]
+set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[0]
+set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[1]
+set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQMH
+set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQML
+set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nRAS
+set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCAS
+set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nWE
+set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCS
+set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[*]
+set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[*]
+set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[*]
+set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[*]
+set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_BA[*]
+set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQML
+set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQMH
+set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nRAS
+set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCAS
+set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nWE
+set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCS
+set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CKE
+set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CLK
+set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_R[*]
+set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_G[*]
+set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_B[*]
+set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_HS
+set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_VS
+set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_L
+set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_R
+set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SPI_DO
+set_global_assignment -name ALLOW_POWER_UP_DONT_CARE ON
+set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING ON
+set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON
+set_global_assignment -name CYCLONEII_OPTIMIZATION_TECHNIQUE SPEED
+set_global_assignment -name OPTIMIZE_HOLD_TIMING "ALL PATHS"
+set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING ON
+set_global_assignment -name FITTER_EFFORT "STANDARD FIT"
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/Jackal_MiST.sv
+set_global_assignment -name QIP_FILE rtl/pll.qip
+set_global_assignment -name VERILOG_FILE rtl/jtframe_frac_cen.v
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/Jackal.sv
+set_global_assignment -name VERILOG_FILE rtl/hiscore.v
+set_global_assignment -name VHDL_FILE rtl/spram.vhd
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv
+set_global_assignment -name VHDL_FILE rtl/dpram_dc.vhd
+set_global_assignment -name QIP_FILE rtl/custom/jackal_custom.qip
+set_global_assignment -name QIP_FILE rtl/sound/jackal_sound.qip
+set_global_assignment -name QIP_FILE ../../common/mist/mist.qip
+set_global_assignment -name VERILOG_FILE ../../common/CPU/MC6809/mc6809is.v
+set_global_assignment -name QIP_FILE ../../common/Sound/jt51/jt51.qip
+set_global_assignment -name SIGNALTAP_FILE output_files/jackal.stp
+set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
\ No newline at end of file
diff --git a/Arcade_MiST/Konami Jackal/Jackal.sdc b/Arcade_MiST/Konami Jackal/Jackal.sdc
new file mode 100644
index 00000000..4a373c09
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/Jackal.sdc
@@ -0,0 +1,134 @@
+## Generated SDC file "vectrex_MiST.out.sdc"
+
+## Copyright (C) 1991-2013 Altera Corporation
+## Your use of Altera Corporation's design tools, logic functions
+## and other software and tools, and its AMPP partner logic
+## functions, and any output files from any of the foregoing
+## (including device programming or simulation files), and any
+## associated documentation or information are expressly subject
+## to the terms and conditions of the Altera Program License
+## Subscription Agreement, Altera MegaCore Function License
+## Agreement, or other applicable license agreement, including,
+## without limitation, that your use is for the sole purpose of
+## programming logic devices manufactured by Altera and sold by
+## Altera or its authorized distributors. Please refer to the
+## applicable agreement for further details.
+
+
+## VENDOR "Altera"
+## PROGRAM "Quartus II"
+## VERSION "Version 13.1.0 Build 162 10/23/2013 SJ Web Edition"
+
+## DATE "Sun Jun 24 12:53:00 2018"
+
+##
+## DEVICE "EP3C25E144C8"
+##
+
+# Clock constraints
+
+# Automatically constrain PLL and other generated clocks
+derive_pll_clocks -create_base_clocks
+
+# Automatically calculate clock uncertainty to jitter and other effects.
+derive_clock_uncertainty
+
+# tsu/th constraints
+
+# tco constraints
+
+# tpd constraints
+
+#**************************************************************
+# Time Information
+#**************************************************************
+
+set_time_format -unit ns -decimal_places 3
+
+
+
+#**************************************************************
+# Create Clock
+#**************************************************************
+
+create_clock -name {SPI_SCK} -period 41.666 -waveform { 20.8 41.666 } [get_ports {SPI_SCK}]
+
+set sdram_clk "pll|altpll_component|auto_generated|pll1|clk[0]"
+set sys_clk "pll|altpll_component|auto_generated|pll1|clk[1]"
+#**************************************************************
+# Create Generated Clock
+#**************************************************************
+
+
+#**************************************************************
+# Set Clock Latency
+#**************************************************************
+
+
+
+#**************************************************************
+# Set Clock Uncertainty
+#**************************************************************
+
+#**************************************************************
+# Set Input Delay
+#**************************************************************
+
+set_input_delay -add_delay -clock_fall -clock [get_clocks {CLOCK_27}] 1.000 [get_ports {CLOCK_27}]
+set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {CONF_DATA0}]
+set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DI}]
+set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SCK}]
+set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS2}]
+set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS3}]
+
+set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 6.6 [get_ports SDRAM_DQ[*]]
+set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min 3.5 [get_ports SDRAM_DQ[*]]
+
+#**************************************************************
+# Set Output Delay
+#**************************************************************
+
+set_output_delay -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DO}]
+set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {AUDIO_L}]
+set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {AUDIO_R}]
+set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {LED}]
+set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {VGA_*}]
+
+set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 1.5 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}]
+set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min -0.8 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}]
+
+#**************************************************************
+# Set Clock Groups
+#**************************************************************
+
+set_clock_groups -asynchronous -group [get_clocks {SPI_SCK}] -group [get_clocks {pll|altpll_component|auto_generated|pll1|clk[*]}]
+
+#**************************************************************
+# Set False Path
+#**************************************************************
+
+
+
+#**************************************************************
+# Set Multicycle Path
+#**************************************************************
+
+set_multicycle_path -to {VGA_*[*]} -setup 2
+set_multicycle_path -to {VGA_*[*]} -hold 1
+
+#**************************************************************
+# Set Maximum Delay
+#**************************************************************
+
+
+
+#**************************************************************
+# Set Minimum Delay
+#**************************************************************
+
+
+
+#**************************************************************
+# Set Input Transition
+#**************************************************************
+
diff --git a/Arcade_MiST/Konami Jackal/README.md b/Arcade_MiST/Konami Jackal/README.md
new file mode 100644
index 00000000..c4895a92
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/README.md
@@ -0,0 +1,11 @@
+# MiST port of Konami Jackal by ACE
+
+https://github.com/MiSTer-devel/Arcade-Jackal_MiSTer
+
+## Usage
+
+- Create ROM and ARC files from the MRA files using the MRA utility.
+ Example: mra -A -z /path/to/mame/roms "Jackal.mra"
+- Copy the ROM files to the root of the SD Card
+- Copy the RBF and ARC files to the same folder on the SD Card
+- MRA utility: https://github.com/sebdel/mra-tools-c/
\ No newline at end of file
diff --git a/Arcade_MiST/Konami Jackal/meta/Jackal (W) [bl].mra b/Arcade_MiST/Konami Jackal/meta/Jackal (W) [bl].mra
new file mode 100644
index 00000000..069494b0
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/meta/Jackal (W) [bl].mra
@@ -0,0 +1,75 @@
+
+ Jackal (bootleg)
+ World
+ no
+ yes
+
+
+
+
+ 1986
+ Konami
+ Shooter - Multidirectional
+
+ jackalbl
+ jackal
+ 0224
+ Jackal
+
+
+ 15kHz
+ vertical (cw)
+ no
+
+ 2 (simultaneous)
+ 8-way
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 01
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0E 00 00 00 00 FF 00 02
+ 00 02 00 01 00 FF 00 00
+ 00 00 72 F8 00 27 00 1D
+ 00 00 73 40 00 03 00 00
+ 00 00 73 41 00 01 02 02
+
+
+
+
+
+
+
+
+ 20210708094853
+
diff --git a/Arcade_MiST/Konami Jackal/meta/Jackal (W).mra b/Arcade_MiST/Konami Jackal/meta/Jackal (W).mra
new file mode 100644
index 00000000..2dcff8db
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/meta/Jackal (W).mra
@@ -0,0 +1,74 @@
+
+ Jackal
+ World
+ no
+ no
+ 8-Way Joystick
+
+
+
+ 1986
+ Konami
+ Shooter - Multidirectional
+
+ jackal
+ jackal
+ 0224
+ Jackal
+
+
+ 15kHz
+ vertical (cw)
+ no
+
+ 2 (simultaneous)
+ 8-way
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 00
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 11 90 00 00 00 FF 00 02
+ 00 02 00 01 00 FF 00 00
+ 00 00 72 F8 00 27 00 1D
+ 00 00 73 40 00 03 00 00
+ 00 00 73 41 00 01 02 02
+
+
+
+
+
+
+
+
+ 20210708094853
+
diff --git a/Arcade_MiST/Konami Jackal/meta/Jackal (W, Rotary).mra b/Arcade_MiST/Konami Jackal/meta/Jackal (W, Rotary).mra
new file mode 100644
index 00000000..05014911
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/meta/Jackal (W, Rotary).mra
@@ -0,0 +1,74 @@
+
+ Jackal (Rotary Joystick)
+ World
+ no
+ no
+ Rotary Joystick
+
+
+
+ 1986
+ Konami
+ Shooter - Multidirectional
+
+ jackalr
+ jackal
+ 0224
+ Jackal
+
+
+ 15kHz
+ vertical (cw)
+ no
+
+ 2 (simultaneous)
+ 8-way
+ Rotary
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 10
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 11 90 00 00 00 FF 00 02
+ 00 02 00 01 00 FF 00 00
+ 00 00 72 F8 00 27 00 1D
+ 00 00 73 40 00 03 00 00
+ 00 00 73 41 00 01 02 02
+
+
+
+
+
+
+
+
+ 20210708094853
+
diff --git a/Arcade_MiST/Konami Jackal/meta/Tokushu Butai Jackal (JP).mra b/Arcade_MiST/Konami Jackal/meta/Tokushu Butai Jackal (JP).mra
new file mode 100644
index 00000000..691a3170
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/meta/Tokushu Butai Jackal (JP).mra
@@ -0,0 +1,74 @@
+
+ Tokushu Butai Jackal
+ Japan
+ no
+ no
+
+
+
+
+ 1986
+ Konami
+ Shooter - Multidirectional
+
+ jackalj
+ jackal
+ 0224
+ Jackal
+
+
+ 15kHz
+ vertical (cw)
+ no
+
+ 2 (simultaneous)
+ 8-way
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 00
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 11 90 00 00 00 FF 00 02
+ 00 02 00 01 00 FF 00 00
+ 00 00 72 F8 00 27 00 1D
+ 00 00 73 40 00 03 00 00
+ 00 00 73 41 00 01 02 02
+
+
+
+
+
+
+
+
+ 20210708094853
+
diff --git a/Arcade_MiST/Konami Jackal/meta/Top Gunner (US) [bl].mra b/Arcade_MiST/Konami Jackal/meta/Top Gunner (US) [bl].mra
new file mode 100644
index 00000000..a031b7de
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/meta/Top Gunner (US) [bl].mra
@@ -0,0 +1,75 @@
+
+ Top Gunner (bootleg)
+ US
+ no
+ yes
+
+
+
+
+ 1986
+ Konami
+ Shooter - Multidirectional
+
+ topgunbl
+ jackal
+ 0224
+ Jackal
+
+
+ 15kHz
+ vertical (cw)
+ no
+
+ 2 (simultaneous)
+ 8-way
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 01
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0E 00 00 00 00 FF 00 02
+ 00 02 00 01 00 FF 00 00
+ 00 00 72 F8 00 27 00 1D
+ 00 00 73 40 00 03 00 00
+ 00 00 73 41 00 01 02 02
+
+
+
+
+
+
+
+
+ 20210708094853
+
diff --git a/Arcade_MiST/Konami Jackal/meta/Top Gunner (US).mra b/Arcade_MiST/Konami Jackal/meta/Top Gunner (US).mra
new file mode 100644
index 00000000..33b51aaa
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/meta/Top Gunner (US).mra
@@ -0,0 +1,74 @@
+
+ Top Gunner
+ US
+ no
+ no
+
+
+
+
+ 1986
+ Konami
+ Shooter - Multidirectional
+
+ topgunr
+ jackal
+ 0224
+ Jackal
+
+
+ 15kHz
+ vertical (cw)
+ no
+
+ 2 (simultaneous)
+ 8-way
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 00
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 11 90 00 00 00 FF 00 02
+ 00 02 00 01 00 FF 00 00
+ 00 00 72 F8 00 27 00 1D
+ 00 00 73 40 00 03 00 00
+ 00 00 73 41 00 01 02 02
+
+
+
+
+
+
+
+
+ 20210708094853
+
diff --git a/Arcade_MiST/Konami Jackal/rtl/Jackal.sv b/Arcade_MiST/Konami Jackal/rtl/Jackal.sv
new file mode 100644
index 00000000..4feecdc9
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/rtl/Jackal.sv
@@ -0,0 +1,566 @@
+//============================================================================
+//
+// Jackal PCB model
+// Copyright (C) 2020, 2021 Ace, brknglass, Ash Evans (aka ElectronAsh/OzOnE),
+// Shane Lynch, JimmyStones and Kitrinx (aka Rysha)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+//============================================================================
+
+//Module declaration, I/O ports
+module Jackal
+(
+ input reset,
+ input clk_49m, //Actual frequency: 49.152MHz
+ input [1:0] coins,
+ input btn_service,
+ input [1:0] btn_start, //1 = Player 2, 0 = Player 1
+ input [3:0] p1_joystick, p2_joystick, //3 = down, 2 = up, 1 = right, 0 = left
+ input [7:0] p1_rotary, p2_rotary,
+ input [1:0] p1_buttons, p2_buttons, //2 buttons per player
+
+ input [19:0] dipsw,
+
+ //The following flag is used to reconfigure the 005885s' video timings, logic for drawing sprites and audio
+ //filtering to reproduce the errors found on bootleg Jackal PCBs (this is a 2-bit signal to reconfigure the
+ //005885s depending on which game's bootleg ROM sets are loaded)
+ input [1:0] is_bootleg,
+
+ //Screen centering (alters HSync and VSync timing in the primary Konami 005885 to reposition the video output)
+ input [3:0] h_center, v_center,
+
+ output signed [15:0] sound_l, sound_r,
+ output video_hsync, video_vsync,
+ output video_csync, //CSync not needed for MiSTer
+ output video_vblank, video_hblank,
+ output [4:0] video_r, video_g, video_b,
+
+ input ioctl_clk,
+ input [24:0] ioctl_addr,
+ input [7:0] ioctl_data,
+ input ioctl_wr,
+
+ input pause,
+
+ input [12:0] hs_address,
+ input [7:0] hs_data_in,
+ output [7:0] hs_data_out,
+ input hs_write,
+ input hs_access,
+
+ //SDRAM signals
+ output reg [16:0] main_cpu_rom_addr,
+ input [7:0] main_cpu_rom_do,
+ output reg [14:0] sub_cpu_rom_addr,
+ input [7:0] sub_cpu_rom_do,
+ output reg [16:1] char1_rom_addr,
+ input [15:0] char1_rom_do,
+ output reg [16:1] char2_rom_addr,
+ input [15:0] char2_rom_do,
+ output sp1_req,
+ input sp1_ack,
+ output [16:1] sp1_rom_addr,
+ input [15:0] sp1_rom_do,
+ output sp2_req,
+ input sp2_ack,
+ output [16:1] sp2_rom_addr,
+ input [15:0] sp2_rom_do
+);
+
+//------------------------------------------------------- Clock division -------------------------------------------------------//
+
+//Generate 6.144MHz and 3.072MHz clock enables (clock division is normally handled inside the primary Konami 005885)
+reg [3:0] div = 4'd0;
+always_ff @(posedge clk_49m) begin
+ div <= div + 4'd1;
+end
+
+wire cen_6m = !div[2:0];
+wire n_cen_6m = div[2:0] == 3'b100;
+wire cen_3m = !div;
+
+//Phase generator for MC6809E (taken from MiSTer Vectrex core)
+//Normally handled internally on the primary Konami 005885
+reg mE = 0;
+reg mQ = 0;
+reg sE = 0;
+reg sQ = 0;
+always_ff @(posedge clk_49m) begin
+ reg [1:0] clk_phase = 0;
+ mE <= 0;
+ mQ <= 0;
+ sE <= 0;
+ sQ <= 0;
+ if(cen_6m) begin
+ clk_phase <= clk_phase + 1'd1;
+ case(clk_phase)
+ 2'b00: sE <= 1;
+ 2'b01: mE <= 1;
+ 2'b10: sQ <= 1;
+ 2'b11: mQ <= 1;
+ endcase
+ end
+end
+
+//Fractional divider to obtain sound clock (implementation by Jotego as part of JTFRAME)
+//The PCB uses a 3.579545MHz oscillator directly connected to its YM2151 - this fractional divider replaces it as 3.579545MHz is
+//not divisible by any integer factor of the main clock
+//Also use this divider to generate a clock enable for jt49_dcrm2 to high-pass filter the YM2151's sound for original Jackal ROM
+//sets
+wire cen_3m58, cen_1m79;
+wire cen_dcrm;
+jtframe_frac_cen #(4) jt51_cen
+(
+ .clk(clk_49m),
+ .n(10'd60),
+ .m(10'd824),
+ .cen({cen_dcrm, 1'bZ, cen_1m79, cen_3m58})
+);
+
+//------------------------------------------------------------ CPUs ------------------------------------------------------------//
+
+//Main CPU (Motorola MC6809E - uses synchronous version of Greg Miller's cycle-accurate MC6809E made by Sorgelig)
+wire maincpu_rw;
+wire [15:0] maincpu_A;
+wire [7:0] maincpu_Din, maincpu_Dout;
+
+mc6809is u16A
+(
+ .CLK(clk_49m),
+ .fallE_en(mE),
+ .fallQ_en(mQ),
+ .D(maincpu_Din),
+ .DOut(maincpu_Dout),
+ .ADDR(maincpu_A),
+ .RnW(maincpu_rw),
+ .nIRQ(irq),
+ .nFIRQ(1),
+ .nNMI(1),
+ .nHALT(pause),
+ .nRESET(reset),
+ .nDMABREQ(1)
+);
+//Address decoding for data inputs to Main CPU
+wire cs_controls_dip1_dip3 = ~n_iocs & (maincpu_A[3:2] == 2'b00) & maincpu_rw;
+wire cs_rotary = ~n_iocs & (maincpu_A[3:2] == 2'b01) & maincpu_rw;
+wire cs_dip2 = ~n_iocs & (maincpu_A[3:2] == 2'b10) & maincpu_rw;
+wire cs_bankswitch = ~n_iocs & (maincpu_A[3:2] == 2'b11) & ~maincpu_rw;
+wire cs_mainsharedram = (maincpu_A >= 16'h0060 & maincpu_A <= 16'h1FFF);
+wire cs_eprom1 = (maincpu_A[15:14] == 2'b01 | maincpu_A[15:14] == 2'b10) & maincpu_rw;
+wire cs_eprom2 = (maincpu_A[15:14] == 2'b11 & maincpu_rw);
+//Some of Jackal's address decoding logic is implemented in a PAL chip marked by Konami as the 007343 - instantiate an
+//implementation of this IC here
+wire n_cs_main_k005885, n_cs_sec_k005885, n_iocs;
+k007343 u12D
+(
+ .A4(maincpu_A[4]),
+ .A5(maincpu_A[5]),
+ .A6(maincpu_A[6]),
+ .A7(maincpu_A[7]),
+ .A8_9(maincpu_A[8] | maincpu_A[9]),
+ .A10(maincpu_A[10]),
+ .A11(maincpu_A[11]),
+ .A12(maincpu_A[12]),
+ .A13(maincpu_A[13]),
+ .WR(maincpu_rw),
+ .OBJB(vram_bank),
+ .GATEB(zram_bank),
+ .GATECS(maincpu_A[15:14] != 2'b00),
+ .MGCS(n_cs_main_k005885),
+ .SGCS(n_cs_sec_k005885),
+ .IOCS(n_iocs)
+ //.CRCS
+);
+//Multiplex data inputs to main CPU
+assign maincpu_Din = (~n_cs_main_k005885 & maincpu_rw) ? main_k005885_Dout:
+ (~n_cs_sec_k005885 & maincpu_rw) ? sec_k005885_Dout:
+ cs_controls_dip1_dip3 ? controls_dip1_dip3:
+ cs_rotary ? rotary:
+ cs_dip2 ? dipsw[15:8]:
+ (cs_mainsharedram & maincpu_rw) ? m_sharedram_D:
+ cs_eprom1 ? eprom1_D:
+ cs_eprom2 ? eprom2_D:
+ 8'hFF;
+
+//Primary game ROM
+always @(posedge clk_49m)
+ if (|maincpu_A[15:14] & maincpu_rw)
+ main_cpu_rom_addr <= {maincpu_A[15:14] == 2'b11, maincpu_A[15:14] != 2'b11 & eprom1_bank, ~maincpu_A[14], maincpu_A[13:0]};
+
+wire [7:0] eprom1_D = main_cpu_rom_do;
+//Secondary game ROM
+wire [7:0] eprom2_D = main_cpu_rom_do;
+
+//Bankswitching for primary game ROM, ZRAM + VRAM and sprite RAM
+reg eprom1_bank = 0;
+reg zram_bank = 0;
+reg vram_bank = 0;
+always_ff @(posedge clk_49m) begin
+ if(!reset) begin
+ eprom1_bank <= 0;
+ zram_bank <= 0;
+ vram_bank <= 0;
+ end
+ else if(cen_3m) begin
+ if(cs_bankswitch) begin
+ eprom1_bank <= maincpu_Dout[5];
+ zram_bank <= maincpu_Dout[4];
+ vram_bank <= maincpu_Dout[3];
+ end
+ end
+end
+
+// Hiscore mux
+wire [12:0] u14B_addr = hs_access ? hs_address[12:0] : maincpu_A[12:0];
+wire [7:0] u14B_din = hs_access ? hs_data_in : maincpu_Dout;
+wire u14B_wren = hs_access ? hs_write : (cs_mainsharedram & ~maincpu_rw);
+wire [7:0] u14B_dout;
+assign m_sharedram_D = hs_access ? 8'h00 : u14B_dout;
+assign hs_data_out = hs_access ? u14B_dout : 8'h00;
+
+//Shared RAM
+wire [7:0] m_sharedram_D, s_sharedram_D;
+dpram_dc #(.widthad_a(13)) u14B
+(
+ .clock_a(clk_49m),
+ .address_a(u14B_addr),
+ .data_a(u14B_din),
+ .q_a(u14B_dout),
+ .wren_a(u14B_wren),
+
+ .clock_b(clk_49m),
+ .address_b(soundcpu_A[12:0]),
+ .data_b(soundcpu_Dout),
+ .q_b(s_sharedram_D),
+ .wren_b(cs_soundsharedram & ~soundcpu_rw)
+);
+
+//Secondary CPU (Motorola MC6809E - uses synchronous version of Greg Miller's cycle-accurate MC6809E made by Sorgelig)
+wire soundcpu_rw;
+wire [15:0] soundcpu_A;
+wire [7:0] soundcpu_Din, soundcpu_Dout;
+
+mc6809is u11A
+(
+ .CLK(clk_49m),
+ .fallE_en(sE),
+ .fallQ_en(sQ),
+ .D(soundcpu_Din),
+ .DOut(soundcpu_Dout),
+ .ADDR(soundcpu_A),
+ .RnW(soundcpu_rw),
+ .nIRQ(1),
+ .nFIRQ(1),
+ .nNMI(irq),
+ .nHALT(1),
+ .nRESET(reset),
+ .nDMABREQ(1)
+);
+//Address decoding for data inputs to sound CPU
+wire cs_ym2151 = (soundcpu_A[15:13] == 3'b001);
+wire cs_k007327 = (soundcpu_A[15:13] == 3'b010);
+wire cs_soundsharedram = (soundcpu_A[15:13] == 3'b011);
+wire cs_eprom3 = (soundcpu_A[15] & soundcpu_rw);
+//Multiplex data inputs to sound CPU
+assign soundcpu_Din = (cs_ym2151 & soundcpu_rw) ? ym2151_Dout:
+ (cs_k007327 & soundcpu_rw) ? k007327_D:
+ (cs_soundsharedram & soundcpu_rw) ? s_sharedram_D:
+ cs_eprom3 ? eprom3_D:
+ 8'hFF;
+
+//Sound ROM
+always @(posedge clk_49m)
+ if (cs_eprom3) sub_cpu_rom_addr <= soundcpu_A[14:0];
+
+wire [7:0] eprom3_D = sub_cpu_rom_do;
+//--------------------------------------------------- Controls & DIP switches --------------------------------------------------//
+
+//Multiplex player inputs with DIP switch banks 1 and 3
+wire [7:0] controls_dip1_dip3 = maincpu_A[1:0] == 2'b00 ? dipsw[7:0]:
+ maincpu_A[1:0] == 2'b01 ? {dipsw[19], 1'b1, p1_buttons, p1_joystick}:
+ maincpu_A[1:0] == 2'b10 ? {2'b1, p2_buttons, p2_joystick}:
+ maincpu_A[1:0] == 2'b11 ? {dipsw[18:16], btn_start[1:0], btn_service, coins}:
+ 8'hFF;
+
+//Multiplex rotary controls for supported ROM sets
+wire [7:0] rotary = maincpu_A[1:0] == 2'b00 ? p1_rotary:
+ maincpu_A[1:0] == 2'b01 ? p2_rotary:
+ 8'hFF;
+
+//--------------------------------------------------- Video timing & graphics --------------------------------------------------//
+
+//Konami 005885 custom chip - this is a large ceramic pin-grid array IC responsible for the majority of Jackal's critical
+//functions: IRQ generation, clock dividers and all video logic for generating tilemaps and sprites
+//Jackal contains two of these in parallel - this instance is the primary tilemap generator
+wire [15:0] gfxrom0_Atile, gfxrom0_Asprite;
+wire [7:0] main_k005885_Dout;
+wire [4:0] main_color;
+wire [3:0] main_tile_data; //Jackal does not use a lookup table for tiles; tile data is fed back to the 005885 directly
+wire [3:0] ocf0, ocb0;
+wire tile_attrib_D4, tile_attrib_D5;
+wire e, q, irq;
+k005885 u11F
+(
+ .CK49(clk_49m),
+ .NRD(~maincpu_rw),
+ .A(maincpu_A[13:0]),
+ .DBi(maincpu_Dout),
+ .DBo(main_k005885_Dout),
+ .R(gfxrom0_Atile),
+ .RDU(gfxrom0_Dtile[15:8]),
+ .RDL(gfxrom0_Dtile[7:0]),
+ .S(gfxrom0_Asprite),
+ .S_req(sp1_req),
+ .S_ack(sp1_ack),
+ .SDU(gfxrom0_Dsprite[15:8]),
+ .SDL(gfxrom0_Dsprite[7:0]),
+ .VCB(main_tile_data),
+ .VCD(main_tile_data),
+ .OCF(ocf0),
+ .OCB(ocb0),
+ .OCD(prom1_D),
+ .COL(main_color),
+ .NEXR(reset),
+ .NXCS(n_cs_main_k005885),
+ .NCSY(video_csync),
+ .NHSY(video_hsync),
+ .NVSY(video_vsync),
+ .HBLK(video_hblank),
+ .VBLK(video_vblank),
+ .NCPE(e),
+ .NCPQ(q),
+ .NIRQ(irq),
+ .ATR4(tile_attrib_D4),
+ .ATR5(tile_attrib_D5),
+ .HCTR(h_center),
+ .VCTR(v_center),
+ .BTLG(is_bootleg)
+);
+
+//Graphics ROMs for primary 005885 tilemap generator (sprites only)
+assign sp1_rom_addr = gfxrom0_Asprite[15:0];
+wire [15:0] gfxrom0_Dsprite = sp1_rom_do;
+//Sprite LUT PROM for primary 005885 tilemap generator
+wire [3:0] prom1_D;
+wire prom1_cs_i = ioctl_addr[24:8] == 16'h0A00;
+dpram_dc #(.widthad_a(8)) u9H
+(
+ .clock_a(clk_49m),
+ .address_a({ocf0, ocb0}),
+ .q_a(prom1_D),
+
+ .clock_b(ioctl_clk),
+ .address_b(ioctl_addr[7:0]),
+ .data_b(ioctl_data),
+ .wren_b(prom1_cs_i & ioctl_wr)
+);
+
+//Konami 005885 custom chip - this is a large ceramic pin-grid array IC responsible for the majority of Jackal's critical
+//functions: IRQ generation, clock dividers and all video logic for generating tilemaps and sprites
+//Jackal contains two of these in parallel - this instance is the secondary tilemap generator
+wire [15:0] gfxrom1_Atile, gfxrom1_Asprite;
+wire [7:0] sec_k005885_Dout;
+wire [4:0] sec_color;
+wire [3:0] sec_tile_data; //Jackal does not use a lookup table for tiles; tile data is fed back to the 005885 directly
+wire [3:0] ocf1, ocb1;
+k005885 u14F
+(
+ .CK49(clk_49m),
+ .NRD(~maincpu_rw),
+ .A(maincpu_A[13:0]),
+ .DBi(maincpu_Dout),
+ .DBo(sec_k005885_Dout),
+ .R(gfxrom1_Atile),
+ .RDU(gfxrom1_Dtile[15:8]),
+ .RDL(gfxrom1_Dtile[7:0]),
+ .S(gfxrom1_Asprite),
+ .S_req(sp2_req),
+ .S_ack(sp2_ack),
+ .SDU(gfxrom1_Dsprite[15:8]),
+ .SDL(gfxrom1_Dsprite[7:0]),
+ .VCB(sec_tile_data),
+ .VCD(sec_tile_data),
+ .OCF(ocf1),
+ .OCB(ocb1),
+ .OCD(prom2_D),
+ .COL(sec_color),
+ .NEXR(reset),
+ .NXCS(n_cs_sec_k005885),
+ .BTLG(is_bootleg)
+);
+
+//Graphics ROMs for secondary 005885 tilemap generator (sprites only)
+assign sp2_rom_addr = gfxrom1_Asprite[15:0];
+wire [15:0] gfxrom1_Dsprite = sp2_rom_do;
+
+//Graphics ROMs (tilemaps only) for both 005885 tilemap generators (accessed externally from SDRAM)
+wire [15:0] gfxrom0_Dtile, gfxrom1_Dtile;
+
+always_ff @(posedge clk_49m) begin
+ char1_rom_addr <= {tile_attrib_D5, tile_attrib_D4, gfxrom0_Atile[13:0]};
+ char2_rom_addr <= {tile_attrib_D5, tile_attrib_D4, gfxrom1_Atile[13:0]};
+end
+
+assign gfxrom0_Dtile = char1_rom_do;
+assign gfxrom1_Dtile = char2_rom_do;
+
+//Sprite LUT PROM for secondary 005885 tilemap generator
+wire [3:0] prom2_D;
+wire prom2_cs_i = ioctl_addr[24:8] == 16'h0A01;
+dpram_dc #(.widthad_a(8)) u14H
+(
+ .clock_a(clk_49m),
+ .address_a({ocf1, ocb1}),
+ .q_a(prom2_D),
+
+ .clock_b(ioctl_clk),
+ .address_b(ioctl_addr[7:0]),
+ .data_b(ioctl_data),
+ .wren_b(prom2_cs_i & ioctl_wr)
+);
+
+//--------------------------------------------------------- Sound chip ---------------------------------------------------------//
+
+//Sound chip - Yamaha YM2151 (uses JT51 implementation by Jotego)
+wire [7:0] ym2151_Dout;
+wire signed [15:0] sound_l_raw, sound_r_raw;
+wire [15:0] unsgined_sound_l_raw, unsgined_sound_r_raw;
+jt51 u8C
+(
+ .rst(~reset),
+ .clk(clk_49m),
+ .cen(cen_3m58),
+ .cen_p1(cen_1m79),
+ .cs_n(~cs_ym2151),
+ .wr_n(soundcpu_rw),
+ .a0(soundcpu_A[0]),
+ .din(soundcpu_Dout),
+ .dout(ym2151_Dout),
+ .xleft(sound_l_raw),
+ .xright(sound_r_raw),
+ .dacleft(unsgined_sound_l_raw),
+ .dacright(unsgined_sound_r_raw)
+);
+
+//----------------------------------------------------- Final video output -----------------------------------------------------//
+
+//Multiplex color data from tilemap generators for color RAM
+wire color_sel = (main_color[4] & sec_color[4]);
+wire [3:0] color_mux = main_color[4] ? sec_color[3:0] : main_color[3:0];
+wire [7:0] color_bus = color_sel ? {main_color[3:0], sec_color[3:0]} : {3'b000, main_color[4], color_mux};
+
+//Write enable logic for palette RAM
+reg n_sQ_lat = 1;
+wire n_sQlat_clr = (e & ~soundcpu_rw);
+always_ff @(posedge clk_49m or negedge n_sQlat_clr) begin
+ if(!n_sQlat_clr)
+ n_sQ_lat <= 1;
+ else if(cen_6m)
+ n_sQ_lat <= ~q;
+end
+wire n_k007327_we = (~cs_k007327 | n_sQ_lat);
+
+//Multiplex the upper 4 address lines of palette RAM
+wire [11:8] ra = cs_k007327 ? soundcpu_A[11:8] : {2'b00, color_sel, color_bus[7]};
+
+//Blank input to palette RAM (black out the signal when all but the uppermost bit of each 005885's color outputs
+//are all set to 0)
+//This signal does not exist on bootleg Jackal PCBs
+wire blank = (is_bootleg == 2'b01) ? 1'b1 : ((|main_color[3:0]) | (|sec_color[3:0]));
+
+//Konami 007327 custom module - integrates palette RAM along with its multiplexing and write enable logic (multiplexing
+//logic only covers bits [7:0], the others are generated externally)
+//This module normally is analog-only as it also integrates the video DAC - for this FPGA implementation of Jackal,
+//the digital video data can be tapped directly
+wire [7:0] k007327_D;
+k007327 u1H
+(
+ .CLK(clk_49m),
+ .CEN(n_cen_6m),
+ .RA(ra),
+ .A(soundcpu_A[7:0]),
+ .NA0(~soundcpu_A[0]),
+ .CB(color_bus[6:0]),
+ .Di(soundcpu_Dout),
+ .RW(~soundcpu_rw),
+ .SEL(~cs_k007327),
+ .CCS(~cs_k007327),
+ .CWR(n_k007327_we),
+ .BLK(blank),
+ .R(video_r),
+ .G(video_g),
+ .B(video_b),
+ .Do(k007327_D)
+);
+
+//----------------------------------------------------- Final audio output -----------------------------------------------------//
+
+//The original Jackal PCB applies high-pass filtering at around 80Hz - use Jotego's jt49_dcrm2 module to apply this high-pass
+//filtering with JT51's unsigned output
+//TODO: Replace this with a proper high-pass filter
+wire signed [15:0] sound_l_hpf, sound_r_hpf;
+jt49_dcrm2 #(16) hpf_left
+(
+ .clk(clk_49m),
+ .cen(cen_dcrm),
+ .rst(~reset),
+ .din(unsigned_sound_l_atten),
+ .dout(sound_l_hpf)
+);
+jt49_dcrm2 #(16) hpf_right
+(
+ .clk(clk_49m),
+ .cen(cen_dcrm),
+ .rst(~reset),
+ .din(unsigned_sound_r_atten),
+ .dout(sound_r_hpf)
+);
+
+//Jackal produces sound out of the YM2151 at a significantly higher volume than most other games on the MiSTer platform - apply
+//6dB attenuation for better balance with other cores
+wire [15:0] unsigned_sound_l_atten = unsgined_sound_l_raw >> 1;
+wire [15:0] unsigned_sound_r_atten = unsgined_sound_r_raw >> 1;
+wire signed [15:0] sound_l_atten = sound_l_raw >>> 1;
+wire signed [15:0] sound_r_atten = sound_r_raw >>> 1;
+
+//Jackal employs a 4.823KHz low-pass filter for its YM2151 - filter the audio accordingly here and output the end result
+//The original PCB also has a variable low-pass filter that applies heavier filtering the higher the volume is set - apply this
+//extra low-pass filter when original ROMs are used (controlled by the is_bootleg flag - this filter and the 80Hz high-pass filter
+//are absent on bootleg ROM sets)
+jackal_lpf lpf_left
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .select(is_bootleg[0]),
+ .in1(sound_l_atten),
+ .in2(sound_l_hpf),
+ .out(sound_l)
+);
+jackal_lpf lpf_right
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .select(is_bootleg[0]),
+ .in1(sound_r_atten),
+ .in2(sound_r_hpf),
+ .out(sound_r)
+);
+
+endmodule
diff --git a/Arcade_MiST/Konami Jackal/rtl/Jackal_MiST.sv b/Arcade_MiST/Konami Jackal/rtl/Jackal_MiST.sv
new file mode 100644
index 00000000..4bd94dab
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/rtl/Jackal_MiST.sv
@@ -0,0 +1,360 @@
+module Jackal_MiST (
+ output LED,
+ output [5:0] VGA_R,
+ output [5:0] VGA_G,
+ output [5:0] VGA_B,
+ output VGA_HS,
+ output VGA_VS,
+ output AUDIO_L,
+ output AUDIO_R,
+ input SPI_SCK,
+ output SPI_DO,
+ input SPI_DI,
+ input SPI_SS2,
+ input SPI_SS3,
+ input CONF_DATA0,
+ input CLOCK_27,
+ output [12:0] SDRAM_A,
+ inout [15:0] SDRAM_DQ,
+ output SDRAM_DQML,
+ output SDRAM_DQMH,
+ output SDRAM_nWE,
+ output SDRAM_nCAS,
+ output SDRAM_nRAS,
+ output SDRAM_nCS,
+ output [1:0] SDRAM_BA,
+ output SDRAM_CLK,
+ output SDRAM_CKE
+
+);
+
+`include "rtl\build_id.v"
+
+localparam CONF_STR = {
+ "JACKAL;;",
+ "O2,Rotate Controls,Off,On;",
+ "O34,Scanlines,Off,25%,50%,75%;",
+ "O5,Blend,Off,On;",
+ "O6,Joystick Swap,Off,On;",
+ "O7,Service,Off,On;",
+ "O1,Rotary speed,Normal,Fast;",
+ "DIP;",
+ "T0,Reset;",
+ "V,v1.00.",`BUILD_DATE
+};
+
+wire rotate = status[2];
+wire [1:0] scanlines = status[4:3];
+wire blend = status[5];
+wire joyswap = status[6];
+wire service = status[7];
+wire rotary_speed = status[1];
+
+wire [1:0] orientation = 2'b11;
+wire [23:0] dip_sw = ~status[31:8];
+
+wire [1:0] is_bootleg = core_mod[1:0];
+
+assign LED = ~ioctl_downl;
+assign SDRAM_CLK = clock_98;
+assign SDRAM_CKE = 1;
+
+wire clock_98, clock_49, pll_locked;
+pll pll(
+ .inclk0(CLOCK_27),
+ .c0(clock_98),
+ .c1(clock_49),//49.152MHz
+ .locked(pll_locked)
+ );
+
+wire [31:0] status;
+wire [1:0] buttons;
+wire [1:0] switches;
+wire [7:0] joystick_0;
+wire [7:0] joystick_1;
+wire scandoublerD;
+wire ypbpr;
+wire no_csync;
+wire [6:0] core_mod;
+wire [15:0] audio_l, audio_r;
+wire hs, vs, cs;
+wire hb, vb;
+wire blankn = ~(hb | vb);
+wire [4:0] r, g, b;
+wire key_strobe;
+wire key_pressed;
+wire [7:0] key_code;
+
+wire [16:0] main_rom_addr;
+wire [15:0] main_rom_do;
+wire [14:0] sub_rom_addr;
+wire [15:0] sub_rom_do;
+wire [15:0] ch1_addr;
+wire [15:0] ch1_do;
+wire [15:0] ch2_addr;
+wire [15:0] ch2_do;
+wire sp1_req, sp1_ack;
+wire [15:0] sp1_addr;
+wire [15:0] sp1_do;
+wire sp2_req, sp2_ack;
+wire [15:0] sp2_addr;
+wire [15:0] sp2_do;
+
+wire ioctl_downl;
+wire [7:0] ioctl_index;
+wire ioctl_wr;
+wire [24:0] ioctl_addr;
+wire [7:0] ioctl_dout;
+
+data_io data_io(
+ .clk_sys ( clock_98 ),
+ .SPI_SCK ( SPI_SCK ),
+ .SPI_SS2 ( SPI_SS2 ),
+ .SPI_DI ( SPI_DI ),
+ .ioctl_download( ioctl_downl ),
+ .ioctl_index ( ioctl_index ),
+ .ioctl_wr ( ioctl_wr ),
+ .ioctl_addr ( ioctl_addr ),
+ .ioctl_dout ( ioctl_dout )
+);
+wire [24:0] bg_ioctl_addr = ioctl_addr - 18'h20000;
+
+reg port1_req, port2_req;
+sdram #(98) sdram(
+ .*,
+ .init_n ( pll_locked ),
+ .clk ( clock_98 ),
+
+ // port1 for CPUs
+ .port1_req ( port1_req ),
+ .port1_ack ( ),
+ .port1_a ( ioctl_addr[23:1] ),
+ .port1_ds ( {ioctl_addr[0], ~ioctl_addr[0]} ),
+ .port1_we ( ioctl_downl ),
+ .port1_d ( {ioctl_dout, ioctl_dout} ),
+ .port1_q ( ),
+
+ .cpu1_addr ( ioctl_downl ? 16'h0000 : main_rom_addr[16:1] ),
+ .cpu1_q ( main_rom_do ),
+ .cpu2_addr ( ioctl_downl ? 16'h0000 : sub_rom_addr[14:1] + 16'hc000 ),
+ .cpu2_q ( sub_rom_do ),
+
+ // port2 for graphics
+ .port2_req ( port2_req ),
+ .port2_ack ( ),
+ .port2_a ( {bg_ioctl_addr[23:18], bg_ioctl_addr[16:0]} ), // merge gfx roms to 16-bit wide words
+ .port2_ds ( {~bg_ioctl_addr[17], bg_ioctl_addr[17]} ),
+ .port2_we ( ioctl_downl ),
+ .port2_d ( {ioctl_dout, ioctl_dout} ),
+ .port2_q ( ),
+
+ .ch1_addr ( ioctl_downl ? 16'hffff : ch1_addr ),
+ .ch1_q ( ch1_do ),
+ .ch2_addr ( ioctl_downl ? 16'hffff : ch2_addr ),
+ .ch2_q ( ch2_do ),
+ .sp1_req ( sp1_req ),
+ .sp1_ack ( sp1_ack ),
+ .sp1_addr ( ioctl_downl ? 16'hffff : sp1_addr ),
+ .sp1_q ( sp1_do ),
+ .sp2_req ( sp2_req ),
+ .sp2_ack ( sp2_ack ),
+ .sp2_addr ( ioctl_downl ? 16'hffff : sp2_addr ),
+ .sp2_q ( sp2_do )
+);
+
+// ROM download controller
+always @(posedge clock_98) begin
+ reg ioctl_wr_last = 0;
+
+ ioctl_wr_last <= ioctl_wr;
+ if (ioctl_downl) begin
+ if (~ioctl_wr_last && ioctl_wr) begin
+ port1_req <= ~port1_req;
+ port2_req <= ~port2_req;
+ end
+ end
+end
+
+reg reset = 1;
+reg rom_loaded = 0;
+always @(posedge clock_49) begin
+ reg ioctl_downlD;
+ ioctl_downlD <= ioctl_downl;
+
+ if (ioctl_downlD & ~ioctl_downl) rom_loaded <= 1;
+ reset <= status[0] | buttons[1] | ~rom_loaded;
+end
+
+Jackal Jackal(
+ .reset(~reset),
+ .clk_49m(clock_49),
+ .coins({~m_coin2,~m_coin1}),
+ .btn_start({~m_two_players,~m_one_player}),
+ .p1_joystick({~m_down, ~m_up, ~m_right, ~m_left}),
+ .p2_joystick({~m_down2, ~m_up2, ~m_right2, ~m_left2}),
+ .p1_rotary(~p1_rotary),
+ .p2_rotary(~p2_rotary),
+ .p1_buttons({~m_fireB, ~m_fireA}),
+ .p2_buttons({~m_fire2B, ~m_fire2A}),
+ .btn_service(~service),
+ .dipsw(dip_sw),
+ .is_bootleg(is_bootleg),
+ .video_hsync(hs),
+ .video_vsync(vs),
+ .video_csync(cs),
+ .video_hblank(hb),
+ .video_vblank(vb),
+ .video_r(r),
+ .video_g(g),
+ .video_b(b),
+ .sound_l(audio_l),
+ .sound_r(audio_r),
+ .pause(1'b1),
+ .ioctl_clk(clock_98),
+ .ioctl_addr(ioctl_addr),
+ .ioctl_data(ioctl_dout),
+ .ioctl_wr(ioctl_wr),
+
+ .main_cpu_rom_addr(main_rom_addr),
+ .main_cpu_rom_do(main_rom_addr[0] ? main_rom_do[15:8] : main_rom_do[7:0]),
+ .sub_cpu_rom_addr(sub_rom_addr),
+ .sub_cpu_rom_do(sub_rom_addr[0] ? sub_rom_do[15:8] : sub_rom_do[7:0]),
+ .char1_rom_addr(ch1_addr),
+ .char1_rom_do(ch1_do),
+ .char2_rom_addr(ch2_addr),
+ .char2_rom_do(ch2_do),
+ .sp1_req(sp1_req),
+ .sp1_ack(sp1_ack),
+ .sp1_rom_addr(sp1_addr),
+ .sp1_rom_do(sp1_do),
+ .sp2_req(sp2_req),
+ .sp2_ack(sp2_ack),
+ .sp2_rom_addr(sp2_addr),
+ .sp2_rom_do(sp2_do)
+);
+
+mist_video #(.COLOR_DEPTH(5), .SD_HCNT_WIDTH(10)) mist_video(
+ .clk_sys ( clock_49 ),
+ .SPI_SCK ( SPI_SCK ),
+ .SPI_SS3 ( SPI_SS3 ),
+ .SPI_DI ( SPI_DI ),
+ .R ( blankn ? r : 0 ),
+ .G ( blankn ? g : 0 ),
+ .B ( blankn ? b : 0 ),
+ .HSync ( hs ),
+ .VSync ( vs ),
+ .VGA_R ( VGA_R ),
+ .VGA_G ( VGA_G ),
+ .VGA_B ( VGA_B ),
+ .VGA_VS ( VGA_VS ),
+ .VGA_HS ( VGA_HS ),
+ .ce_divider ( 0 ),
+ .rotate ( { orientation[1], rotate } ),
+ .blend ( blend ),
+ .scandoubler_disable( scandoublerD ),
+ .scanlines ( scanlines ),
+ .ypbpr ( ypbpr ),
+ .no_csync ( no_csync )
+ );
+
+user_io #(.STRLEN(($size(CONF_STR)>>3)))user_io(
+ .clk_sys (clock_49 ),
+ .conf_str (CONF_STR ),
+ .SPI_CLK (SPI_SCK ),
+ .SPI_SS_IO (CONF_DATA0 ),
+ .SPI_MISO (SPI_DO ),
+ .SPI_MOSI (SPI_DI ),
+ .buttons (buttons ),
+ .switches (switches ),
+ .scandoubler_disable (scandoublerD),
+ .ypbpr (ypbpr ),
+ .no_csync (no_csync ),
+ .core_mod (core_mod ),
+ .key_strobe (key_strobe ),
+ .key_pressed (key_pressed ),
+ .key_code (key_code ),
+ .joystick_0 (joystick_0 ),
+ .joystick_1 (joystick_1 ),
+ .status (status )
+ );
+
+dac #(.C_bits(16))dac_l(
+ .clk_i(clock_49),
+ .res_n_i(1'b1),
+ .dac_i({~audio_l[15], audio_l[14:0]}),
+ .dac_o(AUDIO_L)
+ );
+
+dac #(.C_bits(16))dac_r(
+ .clk_i(clock_49),
+ .res_n_i(1'b1),
+ .dac_i({~audio_r[15], audio_r[14:0]}),
+ .dac_o(AUDIO_R)
+ );
+
+//Rotary controls (disable for bootleg ROM sets as although these support rotary controls, bootleg PCBs
+//have no means of supporting rotary controls as there are no footprints for the required hardware)
+//TODO: Map the inputs to absolute inputs using an analog stick (Jackal ignores out-of-order inputs)
+reg [22:0] rotary_div = 23'd0;
+reg [7:0] rotary1 = 8'h01;
+reg [7:0] rotary2 = 8'h01;
+wire m_rotary1_l = m_fireC;
+wire m_rotary1_r = m_fireD;
+wire m_rotary2_l = m_fire2C;
+wire m_rotary2_r = m_fire2D;
+
+wire rotary_en = rotary_speed ? !rotary_div[21:0] : !rotary_div;
+always_ff @(posedge clock_49) begin
+ rotary_div <= rotary_div + 23'd1;
+ if(rotary_en) begin
+ if(m_rotary1_l) begin
+ if(rotary1 != 8'h80)
+ rotary1 <= rotary1 << 1;
+ else
+ rotary1 <= 8'h01;
+ end
+ else if(m_rotary1_r) begin
+ if(rotary1 != 8'h01)
+ rotary1 <= rotary1 >> 1;
+ else
+ rotary1 <= 8'h80;
+ end
+
+ if(m_rotary2_l) begin
+ if(rotary2 != 8'h80)
+ rotary2 <= rotary2 << 1;
+ else
+ rotary2 <= 8'h01;
+ end
+ else if(m_rotary2_r) begin
+ if(rotary2 != 8'h01)
+ rotary2 <= rotary2 >> 1;
+ else
+ rotary2 <= 8'h80;
+ end
+ end
+end
+wire [7:0] p1_rotary = (is_bootleg == 2'b01) ? 8'hFF : rotary1;
+wire [7:0] p2_rotary = (is_bootleg == 2'b01) ? 8'hFF : rotary2;
+
+wire m_up, m_down, m_left, m_right, m_fireA, m_fireB, m_fireC, m_fireD, m_fireE, m_fireF;
+wire m_up2, m_down2, m_left2, m_right2, m_fire2A, m_fire2B, m_fire2C, m_fire2D, m_fire2E, m_fire2F;
+wire m_tilt, m_coin1, m_coin2, m_coin3, m_coin4, m_one_player, m_two_players, m_three_players, m_four_players;
+
+arcade_inputs inputs (
+ .clk ( clock_49 ),
+ .key_strobe ( key_strobe ),
+ .key_pressed ( key_pressed ),
+ .key_code ( key_code ),
+ .joystick_0 ( joystick_0 ),
+ .joystick_1 ( joystick_1 ),
+ .rotate ( rotate ),
+ .orientation ( orientation ),
+ .joyswap ( joyswap ),
+ .oneplayer ( 1'b0 ),
+ .controls ( {m_tilt, m_coin4, m_coin3, m_coin2, m_coin1, m_four_players, m_three_players, m_two_players, m_one_player} ),
+ .player1 ( {m_fireF, m_fireE, m_fireD, m_fireC, m_fireB, m_fireA, m_up, m_down, m_left, m_right} ),
+ .player2 ( {m_fire2F, m_fire2E, m_fire2D, m_fire2C, m_fire2B, m_fire2A, m_up2, m_down2, m_left2, m_right2} )
+);
+
+endmodule
diff --git a/Arcade_MiST/Konami Jackal/rtl/build_id.tcl b/Arcade_MiST/Konami Jackal/rtl/build_id.tcl
new file mode 100644
index 00000000..938515d8
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/rtl/build_id.tcl
@@ -0,0 +1,35 @@
+# ================================================================================
+#
+# Build ID Verilog Module Script
+# Jeff Wiencrot - 8/1/2011
+#
+# Generates a Verilog module that contains a timestamp,
+# from the current build. These values are available from the build_date, build_time,
+# physical_address, and host_name output ports of the build_id module in the build_id.v
+# Verilog source file.
+#
+# ================================================================================
+
+proc generateBuildID_Verilog {} {
+
+ # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html)
+ set buildDate [ clock format [ clock seconds ] -format %y%m%d ]
+ set buildTime [ clock format [ clock seconds ] -format %H%M%S ]
+
+ # Create a Verilog file for output
+ set outputFileName "rtl/build_id.v"
+ set outputFile [open $outputFileName "w"]
+
+ # Output the Verilog source
+ puts $outputFile "`define BUILD_DATE \"$buildDate\""
+ puts $outputFile "`define BUILD_TIME \"$buildTime\""
+ close $outputFile
+
+ # Send confirmation message to the Messages window
+ post_message "Generated build identification Verilog module: [pwd]/$outputFileName"
+ post_message "Date: $buildDate"
+ post_message "Time: $buildTime"
+}
+
+# Comment out this line to prevent the process from automatically executing when the file is sourced:
+generateBuildID_Verilog
\ No newline at end of file
diff --git a/Arcade_MiST/Konami Jackal/rtl/custom/jackal_custom.qip b/Arcade_MiST/Konami Jackal/rtl/custom/jackal_custom.qip
new file mode 100644
index 00000000..a122369d
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/rtl/custom/jackal_custom.qip
@@ -0,0 +1,3 @@
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/custom/k005885.sv
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/custom/k007327.sv
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/custom/k007343.sv
diff --git a/Arcade_MiST/Konami Jackal/rtl/custom/k005885.sv b/Arcade_MiST/Konami Jackal/rtl/custom/k005885.sv
new file mode 100644
index 00000000..f49fe4a5
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/rtl/custom/k005885.sv
@@ -0,0 +1,902 @@
+//============================================================================
+//
+// SystemVerilog implementation of the Konami 005885 custom tilemap
+// generator
+// Graphics logic based on the video section of the Green Beret core for
+// MiSTer by MiSTer-X
+// Copyright (C) 2020, 2021 Ace
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+//============================================================================
+
+//Note: This model of the 005885 cannot be used as-is to replace an original 005885.
+
+module k005885
+(
+ input CK49, //49.152MHz clock input
+ output NCK2, //6.144MHz clock output
+ output H1O, //3.072MHz clock output
+ output NCPE, //E clock for MC6809E
+ output NCPQ, //Q clock for MC6809E
+ output NEQ, //AND of E and Q clocks for MC6809E
+ input NRD, //Read enable (active low)
+ output NRES, //Reset passthrough
+ input [13:0] A, //Address bus from CPU
+ input [7:0] DBi, //Data bus input from CPU
+ output [7:0] DBo, //Data output to CPU
+ output [3:0] VCF, //Color address to tilemap LUT PROM
+ output [3:0] VCB, //Tile index to tilemap LUT PROM
+ input [3:0] VCD, //Data input from tilemap LUT PROM
+ output [3:0] OCF, //Color address to sprite LUT PROM
+ output [3:0] OCB, //Sprite index to sprite LUT PROM
+ input [3:0] OCD, //Data input from sprite LUT PROM
+ output [4:0] COL, //Color data output from color mixer
+ input NEXR, //Reset input (active low)
+ input NXCS, //Chip select (active low)
+ output NCSY, //Composite sync (active low)
+ output NHSY, //HSync (active low) - Not exposed on the original chip
+ output NVSY, //VSync (active low)
+ output HBLK, //HBlank (active high) - Not exposed on the original chip
+ output VBLK, //VBlank (active high) - Not exposed on the original chip
+ input NBUE, //Unknown
+ output NFIR, //Fast IRQ (FIRQ) output for MC6809E
+ output NIRQ, //IRQ output for MC6809E (VBlank IRQ)
+ output NNMI, //Non-maskable IRQ (NMI) for MC6809E
+ output NIOC, //Inverse of address line A11 for external address decoding logic
+ output NRMW,
+
+ //Split I/O for tile and sprite data
+ output [15:0] R, //Address output to graphics ROMs (tiles)
+ input [7:0] RDU, //Upper 8 bits of graphics ROM data (tiles)
+ input [7:0] RDL, //Lower 8 bits of graphics ROM data (tiles)
+ output [15:0] S, //Address output to graphics ROMs (sprites)
+ output reg S_req = 0,
+ input S_ack,
+ input [7:0] SDU, //Upper 8 bits of graphics ROM data (sprites)
+ input [7:0] SDL, //Lower 8 bits of graphics ROM data (sprites)
+
+ //Extra inputs for screen centering (alters HSync and VSync timing to reposition the video output)
+ input [3:0] HCTR, VCTR,
+
+ //Special flag for reconfiguring the chip to mimic the anomalies found on bootlegs of games that use the 005885
+ //Valid values:
+ //-00: Original behavior
+ //-01: Jackal bootleg (faster video timings, missing 4 lines from the video signal, misplaced HBlank, altered screen
+ // centering, sprite layer is missing one line per sprite, sprite layer is misplaced by one line when the screen is
+ // flipped)
+ //-10: Iron Horse bootleg (10 extra vertical lines resulting in slower VSync, altered screen centering, sprite layer is
+ // offset vertically by 1 line, sprite limit significantly lower than normal)
+ input [1:0] BTLG,
+
+ //Extra data outputs for graphics ROMs
+ output ATR4, //Tilemap attribute bit 4
+ output ATR5, //Tilemap attribute bit 5
+
+ //MiSTer high score system I/O (to be used only with Iron Horse)
+ input [11:0] hs_address,
+ input [7:0] hs_data_in,
+ output [7:0] hs_data_out,
+ input hs_write,
+ input hs_access
+);
+
+//------------------------------------------------------- Signal outputs -------------------------------------------------------//
+
+//Reset line passthrough
+assign NRES = NEXR;
+
+//Generate NIOC output (active low)
+assign NIOC = ~(~NXCS & (A[13:11] == 3'b001));
+
+//TODO: The timing of the NRMW output is currently unknown - set to 1 for now
+assign NRMW = 1;
+
+//Output bits 4 and 5 of tilemap attributes for graphics ROM addressing
+assign ATR4 = tileram_attrib_D[4];
+assign ATR5 = tileram_attrib_D[5];
+
+//Data output to CPU
+assign DBo = (ram_cs & ~NRD) ? ram_Dout:
+ (zram0_cs & ~NRD) ? zram0_Dout:
+ (zram1_cs & ~NRD) ? zram1_Dout:
+ (zram2_cs & ~NRD) ? zram2_Dout:
+ (tile_attrib_cs & ~NRD) ? tileram_attrib_Dout:
+ (tile_cs & ~NRD) ? tileram_Dout:
+ (tile1_attrib_cs & ~NRD) ? tileram1_attrib_Dout:
+ (tile1_cs & ~NRD) ? tileram1_Dout:
+ (spriteram_cs & ~NRD) ? spriteram_Dout:
+ 8'hFF;
+
+//------------------------------------------------------- Clock division -------------------------------------------------------//
+
+//Divide the incoming 49.152MHz clock to 6.144MHz and 3.072MHz
+reg [3:0] div = 4'd0;
+always_ff @(posedge CK49) begin
+ div <= div + 4'd1;
+end
+reg [2:0] n_div = 3'd0;
+always_ff @(negedge CK49) begin
+ n_div <= n_div + 3'd1;
+end
+wire cen_6m = !div[2:0];
+wire n_cen_6m = !n_div;
+wire cen_3m = !div;
+assign NCK2 = div[2];
+assign H1O = div[3];
+
+//The MC6809E requires two identical clocks with a 90-degree offset - assign these here
+reg mc6809e_E = 0;
+reg mc6809e_Q = 0;
+always_ff @(posedge CK49) begin
+ reg [1:0] clk_phase = 0;
+ if(cen_6m) begin
+ clk_phase <= clk_phase + 1'd1;
+ case(clk_phase)
+ 2'b00: mc6809e_E <= 0;
+ 2'b01: mc6809e_Q <= 1;
+ 2'b10: mc6809e_E <= 1;
+ 2'b11: mc6809e_Q <= 0;
+ endcase
+ end
+end
+assign NCPQ = mc6809e_Q;
+assign NCPE = mc6809e_E;
+
+//Output NEQ combines NCPE and NCPQ together via an AND gate - assign this here
+assign NEQ = NCPE & NCPQ;
+
+//-------------------------------------------------------- Video timings -------------------------------------------------------//
+
+//The 005885's video output has 384 horziontal lines and 262 vertical lines with an active resolution of 240x224. Declare both
+//counters as 9-bit registers.
+reg [8:0] h_cnt = 9'd0;
+reg [8:0] v_cnt = 9'd0;
+
+//Increment horizontal counter on every falling edge of the pixel clock and increment vertical counter when horizontal counter
+//rolls over
+reg hblank = 0;
+reg vblank = 0;
+reg vblank_irq_en = 0;
+reg frame_odd_even = 0;
+//Add an extra 10 lines to the vertical counter if a bootleg Iron Horse ROM set is loaded or remove 9 lines from the vertical
+//counter if a bootleg Jackal ROM set is loaded
+reg [8:0] vcnt_end = 0;
+always_ff @(posedge CK49) begin
+ if(cen_6m) begin
+ if(BTLG == 2'b01)
+ vcnt_end <= 9'd252;
+ else if(BTLG == 2'b10)
+ vcnt_end <= 9'd271;
+ else
+ vcnt_end <= 9'd261;
+ end
+end
+//Reposition HSync and VSync if a bootleg Iron Horse or Jackal ROM set is loaded
+reg [8:0] hsync_start = 9'd0;
+reg [8:0] hsync_end = 9'd0;
+reg [8:0] vsync_start = 9'd0;
+reg [8:0] vsync_end = 9'd0;
+always_ff @(posedge CK49) begin
+ if(BTLG == 2'b01) begin
+ hsync_start <= HCTR[3] ? 9'd287 : 9'd295;
+ hsync_end <= HCTR[3] ? 9'd318 : 9'd326;
+ vsync_start <= 9'd244;
+ vsync_end <= 9'd251;
+ end
+ else if(BTLG == 2'b10) begin
+ hsync_start <= HCTR[3] ? 9'd290 : 9'd310;
+ hsync_end <= HCTR[3] ? 9'd321 : 9'd341;
+ vsync_start <= 9'd255;
+ vsync_end <= 9'd262;
+ end
+ else begin
+ hsync_start <= HCTR[3] ? 9'd288 : 9'd296;
+ hsync_end <= HCTR[3] ? 9'd319 : 9'd327;
+ vsync_start <= 9'd254;
+ vsync_end <= 9'd261;
+ end
+end
+always_ff @(posedge CK49) begin
+ if(cen_6m) begin
+ case(h_cnt)
+ 0: begin
+ vblank_irq_en <= 0;
+ h_cnt <= h_cnt + 9'd1;
+ end
+ //HBlank ends two lines earlier than normal on bootleg Jackal PCBs
+ 11: begin
+ if(BTLG == 2'b01)
+ hblank <= 0;
+ h_cnt <= h_cnt + 9'd1;
+ end
+ 13: begin
+ if(BTLG != 2'b01)
+ hblank <= 0;
+ h_cnt <= h_cnt + 9'd1;
+ end
+ //Shift the start of HBlank two lines earlier when bootleg Jackal ROMs are loaded
+ 251: begin
+ if(BTLG == 2'b01)
+ hblank <= 1;
+ h_cnt <= h_cnt + 9'd1;
+ end
+ 253: begin
+ if(BTLG != 2'b01)
+ hblank <= 1;
+ h_cnt <= h_cnt + 9'd1;
+ end
+ 383: begin
+ h_cnt <= 0;
+ case(v_cnt)
+ 15: begin
+ vblank <= 0;
+ v_cnt <= v_cnt + 9'd1;
+ end
+ 239: begin
+ vblank <= 1;
+ vblank_irq_en <= 1;
+ frame_odd_even <= ~frame_odd_even;
+ v_cnt <= v_cnt + 9'd1;
+ end
+ vcnt_end: begin
+ v_cnt <= 9'd0;
+ end
+ default: v_cnt <= v_cnt + 9'd1;
+ endcase
+ end
+ default: h_cnt <= h_cnt + 9'd1;
+ endcase
+ end
+end
+
+//Output HBlank and VBlank (both active high)
+assign HBLK = hblank;
+assign VBLK = vblank;
+
+//Generate horizontal sync and vertical sync (both active low)
+assign NHSY = HCTR[3] ? ~(h_cnt >= hsync_start - ~HCTR[2:0] && h_cnt <= hsync_end - ~HCTR[2:0]):
+ ~(h_cnt >= hsync_start + HCTR[2:0] && h_cnt <= hsync_end + HCTR[2:0]);
+assign NVSY = ~(v_cnt >= vsync_start - VCTR && v_cnt <= vsync_end - VCTR);
+assign NCSY = NHSY ^ NVSY;
+
+//------------------------------------------------------------- IRQs -----------------------------------------------------------//
+
+//IRQ (triggers every VBlank)
+reg vblank_irq = 1;
+always_ff @(posedge CK49 or negedge NEXR) begin
+ if(!NEXR)
+ vblank_irq <= 1;
+ else if(cen_6m) begin
+ if(!irq_mask)
+ vblank_irq <= 1;
+ else if(vblank_irq_en)
+ vblank_irq <= 0;
+ end
+end
+assign NIRQ = vblank_irq;
+
+//NMI (triggers every 64 scanlines starting from scanline 48)
+reg nmi = 1;
+always_ff @(posedge CK49 or negedge NEXR) begin
+ if(!NEXR)
+ nmi <= 1;
+ else if(cen_3m) begin
+ if(!nmi_mask)
+ nmi <= 1;
+ else if((v_cnt[7:0] + 9'd16) % 9'd64 == 0)
+ nmi <= 0;
+ end
+end
+assign NNMI = nmi;
+
+//FIRQ (triggers every second VBlank)
+reg firq = 1;
+always_ff @(posedge CK49 or negedge NEXR) begin
+ if(!NEXR)
+ firq <= 1;
+ else if(cen_3m) begin
+ if(!firq_mask)
+ firq <= 1;
+ else if(!frame_odd_even && v_cnt == 9'd239)
+ firq <= 0;
+ end
+end
+assign NFIR = firq;
+
+//----------------------------------------------------- Internal registers -----------------------------------------------------//
+
+//The 005885 has five 8-bit registers set up as follows according to information in konamiic.txt found in MAME's source code:
+/*
+control registers
+000: scroll y
+001: scroll x (low 8 bits)
+002: -------x scroll x (high bit)
+ ----xxx- row/colscroll control
+ 000 = solid scroll (finalizr, ddribble bg)
+ 100 = solid scroll (jackal)
+ 001 = ? (ddribble fg)
+ 011 = colscroll (jackal high scores)
+ 101 = rowscroll (ironhors, jackal map)
+003: ------xx high bits of the tile code
+ -----x-- unknown (finalizr)
+ ----x--- selects sprite buffer (and makes a copy to a private buffer?)
+ --x----- unknown (ironhors)
+ -x------ unknown (ironhors)
+ x------- unknown (ironhors, jackal)
+004: -------x nmi enable
+ ------x- irq enable
+ -----x-- firq enable
+ ----x--- flip screen
+*/
+
+wire regs_cs = ~NXCS & (A[13:11] == 2'b00) & (A[6:3] == 4'd0);
+
+reg [7:0] scroll_y, scroll_x, scroll_ctrl, tile_ctrl;
+reg nmi_mask = 0;
+reg irq_mask = 0;
+reg firq_mask = 0;
+reg flipscreen = 0;
+
+//Write to the appropriate register
+always_ff @(posedge CK49, negedge NEXR) begin
+ if(!NEXR) begin
+ nmi_mask <= 1;
+ irq_mask <= 1;
+ firq_mask <= 1;
+ flipscreen <= 0;
+ end else if(cen_3m) begin
+ if(regs_cs && NRD)
+ case(A[2:0])
+ 3'b000: scroll_y <= DBi;
+ 3'b001: scroll_x <= DBi;
+ 3'b010: scroll_ctrl <= DBi;
+ 3'b011: tile_ctrl <= DBi;
+ 3'b100: begin
+ nmi_mask <= DBi[0];
+ irq_mask <= DBi[1];
+ firq_mask <= DBi[2];
+ flipscreen <= DBi[3];
+ end
+ default;
+ endcase
+ end
+end
+
+//--------------------------------------------------------- Unknown RAM --------------------------------------------------------//
+
+wire ram_cs = ~NXCS & (A >= 14'h0005 && A <= 14'h001F);
+
+wire [7:0] ram_Dout;
+spram #(8, 5) RAM
+(
+ .clk(CK49),
+ .we(ram_cs & NRD),
+ .addr(A[4:0]),
+ .data(DBi),
+ .q(ram_Dout)
+);
+
+//-------------------------------------------------------- Internal ZRAM -------------------------------------------------------//
+
+wire zram0_cs = ~NXCS & (A >= 16'h0020 && A <= 16'h003F);
+wire zram1_cs = ~NXCS & (A >= 16'h0040 && A <= 16'h005F);
+wire zram2_cs = ~NXCS & (A >= 16'h0060 && A <= 16'h00DF);
+
+//The 005885 addresses ZRAM with either horizontal or vertical position bits depending on whether its scroll mode is set to
+//line scroll or column scroll - use vertical position bits for line scroll and horizontal position bits for column scroll,
+//otherwise don't address it
+wire [4:0] zram_A = (scroll_ctrl[3:1] == 3'b101) ? tilemap_vpos[7:3]:
+ (scroll_ctrl[3:1] == 3'b011) ? tilemap_hpos[7:3]:
+ 5'h00;
+wire [7:0] zram0_D, zram1_D, zram2_D, zram0_Dout, zram1_Dout, zram2_Dout;
+dpram_dc #(.widthad_a(5)) ZRAM0
+(
+ .clock_a(CK49),
+ .address_a(A[4:0]),
+ .data_a(DBi),
+ .q_a(zram0_Dout),
+ .wren_a(zram0_cs & NRD),
+
+ .clock_b(CK49),
+ .address_b(zram_A),
+ .q_b(zram0_D)
+);
+spram #(8, 5) ZRAM1
+(
+ .clk(CK49),
+ .we(zram1_cs & NRD),
+ .addr(A[4:0]),
+ .data(DBi),
+ .q(zram1_Dout)
+);
+spram #(8, 5) ZRAM2
+(
+ .clk(CK49),
+ .we(zram2_cs & NRD),
+ .addr(A[4:0]),
+ .data(DBi),
+ .q(zram2_Dout)
+);
+
+//------------------------------------------------------------ VRAM ------------------------------------------------------------//
+
+//VRAM is external to the 005885 and combines multiple banks into a single 8KB RAM chip for tile attributes and data (two layers),
+//and two sprite banks. For simplicity, this RAM has been made internal to the 005885 implementation and split into its
+//constituent components.
+wire tile_attrib_cs = ~NXCS & (A[13:10] == 4'b1000);
+wire tile_cs = ~NXCS & (A[13:10] == 4'b1001);
+wire tile1_attrib_cs = ~NXCS & (A[13:10] == 4'b1010);
+wire tile1_cs = ~NXCS & (A[13:10] == 4'b1011);
+wire spriteram_cs = ~NXCS & (A[13:12] == 2'b11);
+
+wire [7:0] tileram_attrib_Dout, tileram_Dout, tileram1_attrib_Dout, tileram1_Dout, spriteram_Dout;
+wire [7:0] tileram_attrib_D, tileram_D, tileram1_attrib_D, tileram1_D, spriteram_D;
+//Tilemap layer 0
+dpram_dc #(.widthad_a(10)) VRAM_TILEATTRIB0
+(
+ .clock_a(CK49),
+ .address_a(A[9:0]),
+ .data_a(DBi),
+ .q_a(tileram_attrib_Dout),
+ .wren_a(tile_attrib_cs & NRD),
+
+ .clock_b(CK49),
+ .address_b(vram_A),
+ .q_b(tileram_attrib_D)
+);
+dpram_dc #(.widthad_a(10)) VRAM_TILECODE0
+(
+ .clock_a(CK49),
+ .address_a(A[9:0]),
+ .data_a(DBi),
+ .q_a(tileram_Dout),
+ .wren_a(tile_cs & NRD),
+
+ .clock_b(CK49),
+ .address_b(vram_A),
+ .q_b(tileram_D)
+);
+//Tilemap layer 1
+dpram_dc #(.widthad_a(10)) VRAM_TILEATTRIB1
+(
+ .clock_a(CK49),
+ .address_a(A[9:0]),
+ .data_a(DBi),
+ .q_a(tileram1_attrib_Dout),
+ .wren_a(tile1_attrib_cs & NRD),
+
+ .clock_b(CK49),
+ .address_b(vram_A),
+ .q_b(tileram1_attrib_D)
+);
+dpram_dc #(.widthad_a(10)) VRAM_TILECODE1
+(
+ .clock_a(CK49),
+ .address_a(A[9:0]),
+ .data_a(DBi),
+ .q_a(tileram1_Dout),
+ .wren_a(tile1_cs & NRD),
+
+ .clock_b(CK49),
+ .address_b(vram_A),
+ .q_b(tileram1_D)
+);
+
+// Hiscore mux (this is only to be used with Iron Horse as its high scores are stored in sprite RAM)
+wire [11:0] VRAM_SPR_AD = hs_access ? hs_address : A[11:0];
+wire [7:0] VRAM_SPR_DIN = hs_access ? hs_data_in : DBi;
+wire VRAM_SPR_WE = hs_access ? hs_write : (spriteram_cs & NRD);
+wire [7:0] VRAM_SPR_DOUT;
+
+assign hs_data_out = hs_access ? VRAM_SPR_DOUT : 8'h00;
+assign spriteram_Dout = hs_access ? 8'h00 : VRAM_SPR_DOUT;
+
+//Sprites
+dpram_dc #(.widthad_a(12)) VRAM_SPR
+(
+ .clock_a(CK49),
+ .address_a(VRAM_SPR_AD),
+ .data_a(VRAM_SPR_DIN),
+ .q_a(VRAM_SPR_DOUT),
+ .wren_a(VRAM_SPR_WE),
+
+ .clock_b(~CK49),
+ .address_b(spriteram_A),
+ .q_b(spriteram_D)
+);
+
+//-------------------------------------------------------- Tilemap layer -------------------------------------------------------//
+
+//TODO: The current implementation only handles one of the 005885's two tilemap layers - add logic to handle both layers
+
+//XOR horizontal and vertical counter bits with flipscreen bit
+wire [8:0] hcnt_x = h_cnt ^ {9{flipscreen}};
+wire [8:0] vcnt_x = v_cnt ^ {9{flipscreen}};
+
+//Generate tilemap position by summing the XORed counter bits with their respective scroll registers or ZRAM bank 0 based on
+//whether row scroll or column scroll is enabled
+wire [8:0] row_scroll = (scroll_ctrl[3:1] == 3'b101) ? zram0_D : {scroll_ctrl[0], scroll_x};
+wire [8:0] col_scroll = (scroll_ctrl[3:1] == 3'b011) ? zram0_D : scroll_y;
+wire [8:0] tilemap_hpos = hcnt_x + row_scroll;
+wire [8:0] tilemap_vpos = vcnt_x + col_scroll;
+
+//Address output to tilemap section of VRAM
+wire [9:0] vram_A = {tilemap_vpos[7:3], tilemap_hpos[7:3]};
+
+//Assign tile index as bits 5 and 6 of tilemap attributes and the tile code
+wire [9:0] tile_index = {tileram_attrib_D[7:6], tileram_D};
+
+//XOR tile H/V flip bits with the flipscreen bit
+wire tile_hflip = tileram_attrib_D[4];
+wire tile_vflip = tileram_attrib_D[5];
+
+//Address output to graphics ROMs
+assign R = {tile_ctrl[1:0], tile_index, (tilemap_vpos[2:0] ^ {3{tile_vflip}}), (tilemap_hpos[2] ^ tile_hflip)};
+
+//Latch tile data from graphics ROMs, tile colors and tile H flip bit from VRAM on the falling edge of tilemap horizontal position
+//bit 1
+reg [15:0] RD_lat = 16'd0;
+reg [3:0] tile_color = 4'd0;
+reg tile_hflip_lat = 0;
+reg old_tilehpos1;
+always_ff @(posedge CK49) begin
+ old_tilehpos1 <= tilemap_hpos[1];
+ if(old_tilehpos1 && !tilemap_hpos[1]) begin
+ tile_color <= tileram_attrib_D[3:0];
+ RD_lat <= flipscreen ? {RDL, RDU} : {RDU, RDL};
+ tile_hflip_lat <= tileram_attrib_D[4];
+ end
+end
+
+//Multiplex graphics ROM data down from 16 bits to 8 using bit 1 of the horizontal position
+wire [7:0] RD = (tilemap_hpos[1] ^ tile_hflip_lat) ? RD_lat[7:0] : RD_lat[15:8];
+
+//Further multiplex graphics ROM data down from 8 bits to 4 using bit 0 of the horizontal position
+wire [3:0] tile_pixel = (tilemap_hpos[0] ^ tile_hflip_lat) ? RD[3:0] : RD[7:4];
+
+//Retrieve tilemap select bit from bit 1 of the tile control register XORed with bit 5 of the same register
+wire tile_sel = tile_ctrl[1] ^ tile_ctrl[5];
+reg tilemap_en = 0;
+always_ff @(posedge CK49) begin
+ if(n_cen_6m) begin
+ tilemap_en <= tile_sel;
+ end
+end
+
+//Address output to tilemap LUT PROM
+assign VCF = tile_color;
+assign VCB = tile_pixel;
+
+//Shift the tilemap layer left by two lines when the screen is flipped
+reg [7:0] tilemap_shift;
+always_ff @(posedge CK49) begin
+ if(cen_6m)
+ tilemap_shift <= {VCD, tilemap_shift[7:4]};
+end
+wire [3:0] tilemap_D = flipscreen ? tilemap_shift[3:0] : VCD;
+
+//-------------------------------------------------------- Sprite layer --------------------------------------------------------//
+
+//The following code is an adaptation of the sprite renderer from MiSTer-X's Green Beret core tweaked for the 005885's sprite format
+reg [8:0] sprite_hpos = 9'd0;
+reg [8:0] sprite_vpos = 9'd0;
+always_ff @(posedge CK49) begin
+ if(cen_6m) begin
+ sprite_hpos <= h_cnt;
+ //If a bootleg Iron Horse ROM set is loaded, apply a vertical offset of 65 lines (66 when flipped) to recreate the
+ //bootleg hardware's 1-line downward vertical offset between the sprite and tilemap layers, otherwise apply a
+ //vertical offset of 66 lines (65 lines when flipped)
+ if(BTLG == 2'b10)
+ if(flipscreen)
+ sprite_vpos <= v_cnt + 9'd66;
+ else
+ sprite_vpos <= v_cnt + 9'd65;
+ else
+ if(flipscreen)
+ sprite_vpos <= v_cnt + 9'd65;
+ else
+ sprite_vpos <= v_cnt + 9'd66;
+ end
+end
+
+//Sprite state machine
+reg [8:0] sprite_index;
+reg [2:0] sprite_offset;
+reg [7:0] sprite_attrib0, sprite_attrib1, sprite_attrib2, sprite_attrib3, sprite_attrib4;
+reg [2:0] sprite_fsm_state;
+reg [5:0] sprite_width;
+//Bootleg Iron Horse PCBs have a lower-than-normal sprite limit causing noticeable sprite flickering - reduce the sprite limit
+//to 32 sprites (0 - 155 in increments of 5) if one such ROM set is loaded (render 96 sprites at once, 0 - 485 in increments of
+//5, otherwise)
+wire [8:0] sprite_limit = (BTLG == 2'b10) ? 9'd155 : 9'd485;
+always_ff @(posedge CK49) begin
+ //Reset the sprite state machine whenever the sprite horizontal postion, and in turn the horziontal counter, returns to 0
+ //Also hold the sprite state machine in this initial state for the first line while drawing sprites for bootleg Iron Horse
+ //ROM sets to prevent graphical garbage from occurring on the top-most line
+ if(sprite_hpos == 9'd0 || (BTLG == 2'b10 && (!flipscreen && sprite_vpos <= 9'd80) || (flipscreen && sprite_vpos >= 9'd304))) begin
+ sprite_width <= 0;
+ sprite_index <= 0;
+ sprite_offset <= 3'd4;
+ sprite_fsm_state <= 1;
+ end
+ else
+ case(sprite_fsm_state)
+ 0: /* empty */ ;
+ 1: begin
+ if(sprite_index > sprite_limit)
+ sprite_fsm_state <= 0;
+ else begin
+ sprite_attrib4 <= spriteram_D;
+ sprite_offset <= 3'd3;
+ sprite_fsm_state <= sprite_fsm_state + 3'd1;
+ end
+ end
+ 2: begin
+ sprite_attrib3 <= spriteram_D;
+ sprite_offset <= 3'd2;
+ sprite_fsm_state <= sprite_fsm_state + 3'd1;
+ end
+ 3: begin
+ //Skip the current sprite if it's inactive, otherwise obtain the sprite Y attribute and continue
+ //scanning out the rest of the sprite attributes
+ if(sprite_active) begin
+ sprite_attrib2 <= spriteram_D;
+ sprite_offset <= 3'd1;
+ sprite_fsm_state <= sprite_fsm_state + 3'd1;
+ end
+ else begin
+ sprite_index <= sprite_index + 9'd5;
+ sprite_offset <= 3'd4;
+ sprite_fsm_state <= 3'd1;
+ end
+ end
+ 4: begin
+ sprite_attrib1 <= spriteram_D;
+ sprite_offset <= 3'd0;
+ sprite_fsm_state <= sprite_fsm_state + 3'd1;
+ end
+ 5: begin
+ sprite_attrib0 <= spriteram_D;
+ sprite_offset <= 3'd4;
+ sprite_index <= sprite_index + 9'd5;
+ case(sprite_size)
+ 3'b000: sprite_width <= 6'b110000 + (BTLG == 2'b01 && flipscreen);
+ 3'b001: sprite_width <= 6'b110000 + (BTLG == 2'b01 && flipscreen);
+ 3'b010: sprite_width <= 6'b111000 + (BTLG == 2'b01 && flipscreen);
+ 3'b011: sprite_width <= 6'b111000 + (BTLG == 2'b01 && flipscreen);
+ 3'b100: sprite_width <= 6'b100000 + (BTLG == 2'b01 && flipscreen);
+ default: sprite_width <= 6'b100000 + (BTLG == 2'b01 && flipscreen);
+ endcase
+ sprite_fsm_state <= sprite_fsm_state + 3'd1;
+ S_req <= !S_req;
+ end
+ 6: if (S_req == S_ack) begin
+ //Skip the last line of a sprite if a bootleg Jackal ROM set is loaded (the hardware on such bootlegs fails
+ //to render the last line of sprites), otherwise write sprites as normal
+ if(BTLG == 2'b01 && !flipscreen)
+ if(sprite_width == 6'b111110)
+ sprite_width <= sprite_width + 6'd2;
+ else
+ sprite_width <= sprite_width + 6'd1;
+ else
+ sprite_width <= sprite_width + 6'd1;
+ sprite_fsm_state <= wre ? sprite_fsm_state : 3'd1;
+ S_req <= (wre & sprite_width[1:0] == 2'b11) ? !S_req : S_req;
+
+ end
+ default:;
+ endcase
+end
+
+//Obtain sprite X position from sprite attribute byte 3 - append a 9th bit based on the state of bit 1 sprite attribute byte 4,
+//bit 0 of sprite attribute byte 4 if high or the AND of the upper 5 bits of the horizontal position if low
+reg sprite_x8;
+always_ff @(posedge CK49) begin
+ if(sprite_attrib4[1])
+ sprite_x8 <= sprite_attrib4[0];
+ else
+ sprite_x8 <= &sprite_attrib3[7:3];
+end
+wire [8:0] sprite_x = {sprite_x8 ^ flipscreen, sprite_attrib3 ^ {8{flipscreen}}};
+
+//If the sprite state machine is in state 3, obtain sprite Y position directly from sprite RAM, otherwise obtain it from
+//sprite attribute byte 2
+wire [7:0] sprite_y = (sprite_fsm_state == 3'd3) ? spriteram_D : sprite_attrib2;
+
+//Sprite flip attributes are stored in bits 5 (horizontal) and 6 (vertical) of sprite attribute byte 4
+//Also XOR these attributes with the flipscreen bit (XOR with the inverse for vertical flip)
+wire sprite_hflip = sprite_attrib4[5] ^ flipscreen;
+wire sprite_vflip = sprite_attrib4[6] ^ ~flipscreen;
+
+//Sprite code is sprite attribute byte 0 sandwiched between bits 1 and 0 and bits 3 and 2 of sprite attribute byte 1
+wire [11:0] sprite_code = {sprite_attrib1[1:0], sprite_attrib0, sprite_attrib1[3:2]};
+
+//Sprite color is the upper 4 bits of sprite attribute byte 1
+wire [3:0] sprite_color = sprite_attrib1[7:4];
+
+//The 005885 supports 5 different sprite sizes: 8x8, 8x16, 16x8, 16x16 and 32x32. Retrieve this attribute from bits [4:2] of
+//sprite attribute byte 4
+wire [2:0] sprite_size = sprite_attrib4[4:2];
+
+//Adjust sprite code based on sprite size
+wire [11:0] sprite_code_sized = sprite_size == 3'b000 ? {sprite_code[11:2], ly[3], lx[3]}: //16x16
+ sprite_size == 3'b001 ? {sprite_code[11:1], lx[3]}: //16x8
+ sprite_size == 3'b010 ? {sprite_code[11:2], ly[3], sprite_code[0]}: //8x16
+ sprite_size == 3'b011 ? sprite_code: //8x8
+ {sprite_code[11:2] + {ly[4], lx[4]}, ly[3], lx[3]}; //32x32
+
+//Subtract vertical sprite position from sprite Y parameter to obtain sprite height
+wire [8:0] sprite_height = {(sprite_y[7:4] == 4'hF), sprite_y ^ {8{flipscreen}}} - sprite_vpos;
+
+//Set when a sprite is active depending on whether it is 8, 16 or 32 pixels tall
+reg sprite_active;
+always @(*) begin
+ case(sprite_size)
+ 3'b000: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen)
+ & (sprite_height[4] ^ flipscreen);
+ 3'b001: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen)
+ & (sprite_height[4] ^ flipscreen) & (sprite_height[3] ^ flipscreen);
+ 3'b010: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen)
+ & (sprite_height[4] ^ flipscreen);
+ 3'b011: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen)
+ & (sprite_height[4] ^ flipscreen) & (sprite_height[3] ^ flipscreen);
+ 3'b100: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen);
+ default: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen);
+ endcase
+end
+
+wire [4:0] lx = sprite_width[4:0] ^ {5{sprite_hflip}};
+wire [4:0] ly = sprite_height[4:0] ^ {5{sprite_vflip}};
+
+//Assign address outputs to sprite ROMs
+assign S = {sprite_code_sized, ly[2:0], lx[2]};
+
+//Multiplex sprite ROM data down from 16 bits to 8 using bit 1 of the horizontal position
+wire [7:0] SD = lx[1] ? SDL : SDU;
+
+//Further multiplex sprite ROM data down from 8 bits to 4 using bit 0 of the horizontal position
+wire [3:0] sprite_pixel = lx[0] ? SD[3:0] : SD[7:4];
+
+//Sum the sprite index with the sprite offset and address sprite RAM with it along with tile control register bit 3
+wire [8:0] sprite_address = (sprite_index + sprite_offset);
+reg sprite_bank = 0;
+reg old_vsync;
+//Normally, the 005885 latches the sprite bank from bit 3 of the tile control register on the rising edge of VSync, though this causes
+//jerky scrolling with sprites for bootleg Jackal ROM sets - bypass this latch if such ROM sets are loaded
+always_ff @(posedge CK49) begin
+ old_vsync <= NVSY;
+ if(!NEXR)
+ sprite_bank <= 0;
+ else if(!old_vsync && NVSY)
+ sprite_bank <= tile_ctrl[3];
+end
+wire [11:0] spriteram_A = {(BTLG == 2'b01) ? tile_ctrl[3] : sprite_bank, 2'b00, sprite_address};
+
+//Address output to sprite LUT PROM
+assign OCF = sprite_color;
+assign OCB = sprite_pixel;
+
+//----------------------------------------------------- Sprite line buffer -----------------------------------------------------//
+
+//The sprite line buffer is external to the 005885 and consists of two 4464 DRAM chips. For simplicity, both the logic for the
+//sprite line buffer and the sprite line buffer itself are internal to the 005885 implementation.
+
+//Enable writing to sprite line buffer when bit 5 of the sprite width is 1
+wire wre = sprite_width[5];
+
+//Set sprite line buffer bank as bit 0 of the sprite vertical position
+wire sprite_lbuff_bank = sprite_vpos[0];
+
+//Sum sprite X position with the following bits of the sprite width to address the sprite line buffer based on sprite size:
+//32 pixels wide: bits [4:0]
+//16 pixels wide: bits [3:0]
+//8 pixels wide: bits [2:0]
+//XOR the upper bits for screen flipping on 16 pixel and 8 pixel wide sprites
+reg [4:0] final_sprite_width;
+always @(*) begin
+ case(sprite_size)
+ 3'b000: final_sprite_width = {sprite_width[4] ^ ~flipscreen, sprite_width[3:0]};
+ 3'b001: final_sprite_width = {sprite_width[4] ^ ~flipscreen, sprite_width[3:0]};
+ 3'b010: final_sprite_width = {sprite_width[4:3] ^ {2{~flipscreen}}, sprite_width[2:0]};
+ 3'b011: final_sprite_width = {sprite_width[4:3] ^ {2{~flipscreen}}, sprite_width[2:0]};
+ 3'b100: final_sprite_width = sprite_width[4:0];
+ default: final_sprite_width = sprite_width[4:0];
+ endcase
+end
+wire [8:0] wpx = sprite_x + final_sprite_width;
+
+//Generate sprite line buffer write addresses
+reg [9:0] lbuff_A;
+reg lbuff_we;
+wire [3:0] lbuff_Din = OCD;
+always_ff @(posedge CK49) begin
+ lbuff_A <= {~sprite_lbuff_bank, wpx};
+ lbuff_we <= wre & S_req == S_ack;
+end
+
+//Generate read address for sprite line buffer on the rising edge of the pixel clock (apply a -225 offset when the screen
+//is flipped)
+reg [9:0] radr0 = 10'd0;
+reg [9:0] radr1 = 10'd1;
+always_ff @(posedge CK49) begin
+ if(cen_6m)
+ radr0 <= {sprite_lbuff_bank, flipscreen ? sprite_hpos - 9'd225 : sprite_hpos};
+end
+
+//Sprite line buffer
+wire [3:0] lbuff_Dout;
+dpram_dc #(.widthad_a(10)) LBUFF
+(
+ .clock_a(CK49),
+ .address_a(lbuff_A),
+ .data_a({4'd0, lbuff_Din}),
+ .wren_a(lbuff_we & (lbuff_Din != 0)),
+
+ .clock_b(CK49),
+ .address_b(radr0),
+ .data_b(8'h0),
+ .wren_b(radr0 == radr1),
+ .q_b({4'bZZZZ, lbuff_Dout})
+);
+
+//Latch sprite data from the sprite line buffer
+wire lbuff_read_en = (div[2:0] == 3'b100);
+reg [3:0] lbuff_read = 4'd0;
+always_ff @(posedge CK49) begin
+ if(lbuff_read_en) begin
+ if(radr0 != radr1)
+ lbuff_read <= lbuff_Dout;
+ radr1 <= radr0;
+ end
+end
+
+//Delay sprite layer by 2 horizontal lines (1 line if a bootleg Jackal ROM set is loaded and the screen is flipped)
+reg [7:0] sprite_dly = 8'd0;
+always_ff @(posedge CK49) begin
+ if(cen_6m) begin
+ if(BTLG == 2'b01 && flipscreen)
+ sprite_dly <= {4'd0, lbuff_read};
+ else
+ sprite_dly <= {lbuff_read, sprite_dly[7:4]};
+ end
+end
+//Jackal bootlegs fail to render the last two vertical lines of the sprite layer - model this behavior here
+wire [3:0] sprite_D = (BTLG == 2'b01 && ((h_cnt >= 244 && ~flipscreen) || (h_cnt >= 248 && flipscreen))) ? 4'd0 : sprite_dly[3:0];
+
+//--------------------------------------------------------- Color mixer --------------------------------------------------------//
+
+//Multiplex tile and sprite data, then output the final result
+wire tile_sprite_sel = (tilemap_en | ~(|sprite_D));
+wire [3:0] tile_sprite_D = tile_sprite_sel ? tilemap_D : sprite_D;
+
+//Latch and output pixel data
+reg [4:0] pixel_D;
+always_ff @(posedge CK49) begin
+ if(cen_6m)
+ pixel_D <= {tile_sprite_sel, tile_sprite_D};
+end
+assign COL = (BTLG == 2'b01 && ((h_cnt >= 247 && ~flipscreen) || (h_cnt <= 14 && flipscreen))) ||
+ (BTLG == 2'b10 && ((h_cnt <= 20 && ~flipscreen) || ((h_cnt <= 18 || h_cnt >= 251) && flipscreen))) ? 5'd0 : pixel_D;
+//The above condition blacks out the last 4 lines on the right side of the screen (left when flipped) when a bootleg Jackal ROM set
+//is loaded and blacks out the left-most 8 lines (7 when flipped plus an extra 2 lines on the right side) when a bootleg Iron Horse
+//ROM set is loaded - this simulates the earlier-than-normal start of HBlank for Jackal bootlegs and later-than-normal end of
+//HBlank for Iron Horse bootlegs while maintaining the usual 240x224 display area
+
+endmodule
diff --git a/Arcade_MiST/Konami Jackal/rtl/custom/k005885.sv.bakk b/Arcade_MiST/Konami Jackal/rtl/custom/k005885.sv.bakk
new file mode 100644
index 00000000..243cd8eb
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/rtl/custom/k005885.sv.bakk
@@ -0,0 +1,911 @@
+//============================================================================
+//
+// SystemVerilog implementation of the Konami 005885 custom tilemap
+// generator
+// Graphics logic based on the video section of the Green Beret core for
+// MiSTer by MiSTer-X
+// Copyright (C) 2020, 2021 Ace
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+//============================================================================
+
+//Note: This model of the 005885 cannot be used as-is to replace an original 005885.
+
+module k005885
+(
+ input CK49, //49.152MHz clock input
+ output NCK2, //6.144MHz clock output
+ output H1O, //3.072MHz clock output
+ output NCPE, //E clock for MC6809E
+ output NCPQ, //Q clock for MC6809E
+ output NEQ, //AND of E and Q clocks for MC6809E
+ input NRD, //Read enable (active low)
+ output NRES, //Reset passthrough
+ input [13:0] A, //Address bus from CPU
+ input [7:0] DBi, //Data bus input from CPU
+ output [7:0] DBo, //Data output to CPU
+ output [3:0] VCF, //Color address to tilemap LUT PROM
+ output [3:0] VCB, //Tile index to tilemap LUT PROM
+ input [3:0] VCD, //Data input from tilemap LUT PROM
+ output [3:0] OCF, //Color address to sprite LUT PROM
+ output [3:0] OCB, //Sprite index to sprite LUT PROM
+ input [3:0] OCD, //Data input from sprite LUT PROM
+ output [4:0] COL, //Color data output from color mixer
+ input NEXR, //Reset input (active low)
+ input NXCS, //Chip select (active low)
+ output NCSY, //Composite sync (active low)
+ output NHSY, //HSync (active low) - Not exposed on the original chip
+ output NVSY, //VSync (active low)
+ output HBLK, //HBlank (active high) - Not exposed on the original chip
+ output VBLK, //VBlank (active high) - Not exposed on the original chip
+ input NBUE, //Unknown
+ output NFIR, //Fast IRQ (FIRQ) output for MC6809E
+ output NIRQ, //IRQ output for MC6809E (VBlank IRQ)
+ output NNMI, //Non-maskable IRQ (NMI) for MC6809E
+ output NIOC, //Inverse of address line A11 for external address decoding logic
+ output NRMW,
+
+ //Split I/O for tile and sprite data
+ output [15:0] R, //Address output to graphics ROMs (tiles)
+ input [7:0] RDU, //Upper 8 bits of graphics ROM data (tiles)
+ input [7:0] RDL, //Lower 8 bits of graphics ROM data (tiles)
+ output [15:0] S, //Address output to graphics ROMs (sprites)
+ input [7:0] SDU, //Upper 8 bits of graphics ROM data (sprites)
+ input [7:0] SDL, //Lower 8 bits of graphics ROM data (sprites)
+
+ //Extra inputs for screen centering (alters HSync and VSync timing to reposition the video output)
+ input [3:0] HCTR, VCTR,
+
+ //Special flag for reconfiguring the chip to mimic the anomalies found on bootlegs of games that use the 005885
+ //Valid values:
+ //-00: Original behavior
+ //-01: Jackal bootleg (faster video timings, missing 4 lines from the video signal, misplaced HBlank, altered screen
+ // centering, sprite layer is missing one line per sprite, sprite layer is misplaced by one line when the screen is
+ // flipped)
+ //-10: Iron Horse bootleg (10 extra vertical lines resulting in slower VSync, altered screen centering, sprite layer is
+ // offset vertically by 1 line, sprite limit significantly lower than normal)
+ input [1:0] BTLG,
+
+ //Extra data outputs for graphics ROMs
+ output ATR4, //Tilemap attribute bit 4
+ output ATR5, //Tilemap attribute bit 5
+
+ //MiSTer high score system I/O (to be used only with Iron Horse)
+ input [11:0] hs_address,
+ input [7:0] hs_data_in,
+ output [7:0] hs_data_out,
+ input hs_write,
+ input hs_access
+);
+
+//------------------------------------------------------- Signal outputs -------------------------------------------------------//
+
+//Reset line passthrough
+assign NRES = NEXR;
+
+//Generate NIOC output (active low)
+assign NIOC = ~(~NXCS & (A[13:11] == 3'b001));
+
+//TODO: The timing of the NRMW output is currently unknown - set to 1 for now
+assign NRMW = 1;
+
+//Output bits 4 and 5 of tilemap attributes for graphics ROM addressing
+assign ATR4 = tileram_attrib_D[4];
+assign ATR5 = tileram_attrib_D[5];
+
+//Data output to CPU
+assign DBo = (ram_cs & ~NRD) ? ram_Dout:
+ (zram0_cs & ~NRD) ? zram0_Dout:
+ (zram1_cs & ~NRD) ? zram1_Dout:
+ (zram2_cs & ~NRD) ? zram2_Dout:
+ (tile_attrib_cs & ~NRD) ? tileram_attrib_Dout:
+ (tile_cs & ~NRD) ? tileram_Dout:
+ (tile1_attrib_cs & ~NRD) ? tileram1_attrib_Dout:
+ (tile1_cs & ~NRD) ? tileram1_Dout:
+ (spriteram_cs & ~NRD) ? spriteram_Dout:
+ 8'hFF;
+
+//------------------------------------------------------- Clock division -------------------------------------------------------//
+
+//Divide the incoming 49.152MHz clock to 6.144MHz and 3.072MHz
+reg [3:0] div = 4'd0;
+always_ff @(posedge CK49) begin
+ div <= div + 4'd1;
+end
+reg [2:0] n_div = 3'd0;
+always_ff @(negedge CK49) begin
+ n_div <= n_div + 3'd1;
+end
+wire cen_6m = !div[2:0];
+wire n_cen_6m = !n_div;
+wire cen_3m = !div;
+assign NCK2 = div[2];
+assign H1O = div[3];
+
+//The MC6809E requires two identical clocks with a 90-degree offset - assign these here
+reg mc6809e_E = 0;
+reg mc6809e_Q = 0;
+always_ff @(posedge CK49) begin
+ reg [1:0] clk_phase = 0;
+ if(cen_6m) begin
+ clk_phase <= clk_phase + 1'd1;
+ case(clk_phase)
+ 2'b00: mc6809e_E <= 0;
+ 2'b01: mc6809e_Q <= 1;
+ 2'b10: mc6809e_E <= 1;
+ 2'b11: mc6809e_Q <= 0;
+ endcase
+ end
+end
+assign NCPQ = mc6809e_Q;
+assign NCPE = mc6809e_E;
+
+//Output NEQ combines NCPE and NCPQ together via an AND gate - assign this here
+assign NEQ = NCPE & NCPQ;
+
+//-------------------------------------------------------- Video timings -------------------------------------------------------//
+
+//The 005885's video output has 384 horziontal lines and 262 vertical lines with an active resolution of 240x224. Declare both
+//counters as 9-bit registers.
+reg [8:0] h_cnt = 9'd0;
+reg [8:0] v_cnt = 9'd0;
+
+//Increment horizontal counter on every falling edge of the pixel clock and increment vertical counter when horizontal counter
+//rolls over
+reg hblank = 0;
+reg vblank = 0;
+reg vblank_irq_en = 0;
+reg frame_odd_even = 0;
+//Add an extra 10 lines to the vertical counter if a bootleg Iron Horse ROM set is loaded or remove 9 lines from the vertical
+//counter if a bootleg Jackal ROM set is loaded
+reg [8:0] vcnt_end = 0;
+always_ff @(posedge CK49) begin
+ if(cen_6m) begin
+ if(BTLG == 2'b01)
+ vcnt_end <= 9'd252;
+ else if(BTLG == 2'b10)
+ vcnt_end <= 9'd271;
+ else
+ vcnt_end <= 9'd261;
+ end
+end
+//Reposition HSync and VSync if a bootleg Iron Horse or Jackal ROM set is loaded
+reg [8:0] hsync_start = 9'd0;
+reg [8:0] hsync_end = 9'd0;
+reg [8:0] vsync_start = 9'd0;
+reg [8:0] vsync_end = 9'd0;
+always_ff @(posedge CK49) begin
+ if(BTLG == 2'b01) begin
+ hsync_start <= HCTR[3] ? 9'd287 : 9'd295;
+ hsync_end <= HCTR[3] ? 9'd318 : 9'd326;
+ vsync_start <= 9'd244;
+ vsync_end <= 9'd251;
+ end
+ else if(BTLG == 2'b10) begin
+ hsync_start <= HCTR[3] ? 9'd290 : 9'd310;
+ hsync_end <= HCTR[3] ? 9'd321 : 9'd341;
+ vsync_start <= 9'd255;
+ vsync_end <= 9'd262;
+ end
+ else begin
+ hsync_start <= HCTR[3] ? 9'd288 : 9'd296;
+ hsync_end <= HCTR[3] ? 9'd319 : 9'd327;
+ vsync_start <= 9'd254;
+ vsync_end <= 9'd261;
+ end
+end
+always_ff @(posedge CK49) begin
+ if(cen_6m) begin
+ case(h_cnt)
+ 0: begin
+ vblank_irq_en <= 0;
+ h_cnt <= h_cnt + 9'd1;
+ end
+ //HBlank ends two lines earlier than normal on bootleg Jackal PCBs
+ 11: begin
+ if(BTLG == 2'b01)
+ hblank <= 0;
+ h_cnt <= h_cnt + 9'd1;
+ end
+ 13: begin
+ if(BTLG != 2'b01)
+ hblank <= 0;
+ h_cnt <= h_cnt + 9'd1;
+ end
+ //Shift the start of HBlank two lines earlier when bootleg Jackal ROMs are loaded
+ 251: begin
+ if(BTLG == 2'b01)
+ hblank <= 1;
+ h_cnt <= h_cnt + 9'd1;
+ end
+ 253: begin
+ if(BTLG != 2'b01)
+ hblank <= 1;
+ h_cnt <= h_cnt + 9'd1;
+ end
+ 383: begin
+ h_cnt <= 0;
+ case(v_cnt)
+ 15: begin
+ vblank <= 0;
+ v_cnt <= v_cnt + 9'd1;
+ end
+ 239: begin
+ vblank <= 1;
+ vblank_irq_en <= 1;
+ frame_odd_even <= ~frame_odd_even;
+ v_cnt <= v_cnt + 9'd1;
+ end
+ vcnt_end: begin
+ v_cnt <= 9'd0;
+ end
+ default: v_cnt <= v_cnt + 9'd1;
+ endcase
+ end
+ default: h_cnt <= h_cnt + 9'd1;
+ endcase
+ end
+end
+
+//Output HBlank and VBlank (both active high)
+assign HBLK = hblank;
+assign VBLK = vblank;
+
+//Generate horizontal sync and vertical sync (both active low)
+assign NHSY = HCTR[3] ? ~(h_cnt >= hsync_start - ~HCTR[2:0] && h_cnt <= hsync_end - ~HCTR[2:0]):
+ ~(h_cnt >= hsync_start + HCTR[2:0] && h_cnt <= hsync_end + HCTR[2:0]);
+assign NVSY = ~(v_cnt >= vsync_start - VCTR && v_cnt <= vsync_end - VCTR);
+assign NCSY = NHSY ^ NVSY;
+
+//------------------------------------------------------------- IRQs -----------------------------------------------------------//
+
+//IRQ (triggers every VBlank)
+reg vblank_irq = 1;
+always_ff @(posedge CK49 or negedge NEXR) begin
+ if(!NEXR)
+ vblank_irq <= 1;
+ else if(cen_6m) begin
+ if(!irq_mask)
+ vblank_irq <= 1;
+ else if(vblank_irq_en)
+ vblank_irq <= 0;
+ end
+end
+assign NIRQ = vblank_irq;
+
+//NMI (triggers every 64 scanlines starting from scanline 48)
+reg nmi = 1;
+always_ff @(posedge CK49 or negedge NEXR) begin
+ if(!NEXR)
+ nmi <= 1;
+ else if(cen_3m) begin
+ if(!nmi_mask)
+ nmi <= 1;
+ else if((v_cnt[7:0] + 9'd16) % 9'd64 == 0)
+ nmi <= 0;
+ end
+end
+assign NNMI = nmi;
+
+//FIRQ (triggers every second VBlank)
+reg firq = 1;
+always_ff @(posedge CK49 or negedge NEXR) begin
+ if(!NEXR)
+ firq <= 1;
+ else if(cen_3m) begin
+ if(!firq_mask)
+ firq <= 1;
+ else if(!frame_odd_even && v_cnt == 9'd239)
+ firq <= 0;
+ end
+end
+assign NFIR = firq;
+
+//----------------------------------------------------- Internal registers -----------------------------------------------------//
+
+//The 005885 has five 8-bit registers set up as follows according to information in konamiic.txt found in MAME's source code:
+/*
+control registers
+000: scroll y
+001: scroll x (low 8 bits)
+002: -------x scroll x (high bit)
+ ----xxx- row/colscroll control
+ 000 = solid scroll (finalizr, ddribble bg)
+ 100 = solid scroll (jackal)
+ 001 = ? (ddribble fg)
+ 011 = colscroll (jackal high scores)
+ 101 = rowscroll (ironhors, jackal map)
+003: ------xx high bits of the tile code
+ -----x-- unknown (finalizr)
+ ----x--- selects sprite buffer (and makes a copy to a private buffer?)
+ --x----- unknown (ironhors)
+ -x------ unknown (ironhors)
+ x------- unknown (ironhors, jackal)
+004: -------x nmi enable
+ ------x- irq enable
+ -----x-- firq enable
+ ----x--- flip screen
+*/
+
+wire regs_cs = ~NXCS & (A[13:11] == 2'b00) & (A[6:3] == 4'd0);
+
+reg [7:0] scroll_y, scroll_x, scroll_ctrl, tile_ctrl;
+reg nmi_mask = 0;
+reg irq_mask = 0;
+reg firq_mask = 0;
+reg flipscreen = 0;
+
+//Write to the appropriate register
+always_ff @(posedge CK49) begin
+ if(cen_3m) begin
+ if(regs_cs && NRD)
+ case(A[2:0])
+ 3'b000: scroll_y <= DBi;
+ 3'b001: scroll_x <= DBi;
+ 3'b010: scroll_ctrl <= DBi;
+ 3'b011: tile_ctrl <= DBi;
+ 3'b100: begin
+ nmi_mask <= DBi[0];
+ irq_mask <= DBi[1];
+ firq_mask <= DBi[2];
+ flipscreen <= DBi[3];
+ end
+ default;
+ endcase
+ end
+end
+
+//--------------------------------------------------------- Unknown RAM --------------------------------------------------------//
+
+wire ram_cs = ~NXCS & (A >= 14'h0005 && A <= 14'h001F);
+
+wire [7:0] ram_Dout;
+spram #(8, 5) RAM
+(
+ .clk(CK49),
+ .we(ram_cs & NRD),
+ .addr(A[4:0]),
+ .data(DBi),
+ .q(ram_Dout)
+);
+
+//-------------------------------------------------------- Internal ZRAM -------------------------------------------------------//
+
+wire zram0_cs = ~NXCS & (A >= 16'h0020 && A <= 16'h003F);
+wire zram1_cs = ~NXCS & (A >= 16'h0040 && A <= 16'h005F);
+wire zram2_cs = ~NXCS & (A >= 16'h0060 && A <= 16'h00DF);
+
+//The 005885 addresses ZRAM with either horizontal or vertical position bits depending on whether its scroll mode is set to
+//line scroll or column scroll - use vertical position bits for line scroll and horizontal position bits for column scroll,
+//otherwise don't address it
+wire [4:0] zram_A = (scroll_ctrl[3:1] == 3'b101) ? tilemap_vpos[7:3]:
+ (scroll_ctrl[3:1] == 3'b011) ? tilemap_hpos[7:3]:
+ 5'h00;
+wire [7:0] zram0_D, zram1_D, zram2_D, zram0_Dout, zram1_Dout, zram2_Dout;
+dpram_dc #(.widthad_a(5)) ZRAM0
+(
+ .clock_a(CK49),
+ .address_a(A[4:0]),
+ .data_a(DBi),
+ .q_a(zram0_Dout),
+ .wren_a(zram0_cs & NRD),
+
+ .clock_b(CK49),
+ .address_b(zram_A),
+ .q_b(zram0_D)
+);
+spram #(8, 5) ZRAM1
+(
+ .clk(CK49),
+ .we(zram1_cs & NRD),
+ .addr(A[4:0]),
+ .data(DBi),
+ .q(zram1_Dout)
+);
+spram #(8, 5) ZRAM2
+(
+ .clk(CK49),
+ .we(zram2_cs & NRD),
+ .addr(A[4:0]),
+ .data(DBi),
+ .q(zram2_Dout)
+);
+
+//------------------------------------------------------------ VRAM ------------------------------------------------------------//
+
+//VRAM is external to the 005885 and combines multiple banks into a single 8KB RAM chip for tile attributes and data (two layers),
+//and two sprite banks. For simplicity, this RAM has been made internal to the 005885 implementation and split into its
+//constituent components.
+wire tile_attrib_cs = ~NXCS & (A[13:10] == 4'b1000);
+wire tile_cs = ~NXCS & (A[13:10] == 4'b1001);
+wire tile1_attrib_cs = ~NXCS & (A[13:10] == 4'b1010);
+wire tile1_cs = ~NXCS & (A[13:10] == 4'b1011);
+wire spriteram_cs = ~NXCS & (A[13:12] == 2'b11);
+
+wire [7:0] tileram_attrib_Dout, tileram_Dout, tileram1_attrib_Dout, tileram1_Dout, spriteram_Dout;
+wire [7:0] tileram_attrib_D, tileram_D, tileram1_attrib_D, tileram1_D, spriteram_D;
+//Tilemap layer 0
+dpram_dc #(.widthad_a(10)) VRAM_TILEATTRIB0
+(
+ .clock_a(CK49),
+ .address_a(A[9:0]),
+ .data_a(DBi),
+ .q_a(tileram_attrib_Dout),
+ .wren_a(tile_attrib_cs & NRD),
+
+ .clock_b(CK49),
+ .address_b(vram_A),
+ .q_b(tileram_attrib_D)
+);
+dpram_dc #(.widthad_a(10)) VRAM_TILECODE0
+(
+ .clock_a(CK49),
+ .address_a(A[9:0]),
+ .data_a(DBi),
+ .q_a(tileram_Dout),
+ .wren_a(tile_cs & NRD),
+
+ .clock_b(CK49),
+ .address_b(vram_A),
+ .q_b(tileram_D)
+);
+//Tilemap layer 1
+dpram_dc #(.widthad_a(10)) VRAM_TILEATTRIB1
+(
+ .clock_a(CK49),
+ .address_a(A[9:0]),
+ .data_a(DBi),
+ .q_a(tileram1_attrib_Dout),
+ .wren_a(tile1_attrib_cs & NRD),
+
+ .clock_b(CK49),
+ .address_b(vram_A),
+ .q_b(tileram1_attrib_D)
+);
+dpram_dc #(.widthad_a(10)) VRAM_TILECODE1
+(
+ .clock_a(CK49),
+ .address_a(A[9:0]),
+ .data_a(DBi),
+ .q_a(tileram1_Dout),
+ .wren_a(tile1_cs & NRD),
+
+ .clock_b(CK49),
+ .address_b(vram_A),
+ .q_b(tileram1_D)
+);
+
+// Hiscore mux (this is only to be used with Iron Horse as its high scores are stored in sprite RAM)
+wire [11:0] VRAM_SPR_AD = hs_access ? hs_address : A[11:0];
+wire [7:0] VRAM_SPR_DIN = hs_access ? hs_data_in : DBi;
+wire VRAM_SPR_WE = hs_access ? hs_write : (spriteram_cs & NRD);
+wire [7:0] VRAM_SPR_DOUT;
+
+assign hs_data_out = hs_access ? VRAM_SPR_DOUT : 8'h00;
+assign spriteram_Dout = hs_access ? 8'h00 : VRAM_SPR_DOUT;
+
+//Sprites
+dpram_dc #(.widthad_a(12)) VRAM_SPR
+(
+ .clock_a(CK49),
+ .address_a(VRAM_SPR_AD),
+ .data_a(VRAM_SPR_DIN),
+ .q_a(VRAM_SPR_DOUT),
+ .wren_a(VRAM_SPR_WE),
+
+ .clock_b(~CK49),
+ .address_b(spriteram_A),
+ .q_b(spriteram_D)
+);
+
+//-------------------------------------------------------- Tilemap layer -------------------------------------------------------//
+
+//TODO: The current implementation only handles one of the 005885's two tilemap layers - add logic to handle both layers
+
+//XOR horizontal and vertical counter bits with flipscreen bit
+wire [8:0] hcnt_x = h_cnt ^ {9{flipscreen}};
+wire [8:0] vcnt_x = v_cnt ^ {9{flipscreen}};
+
+//Generate tilemap position by summing the XORed counter bits with their respective scroll registers or ZRAM bank 0 based on
+//whether row scroll or column scroll is enabled
+wire [8:0] row_scroll = (scroll_ctrl[3:1] == 3'b101) ? zram0_D : {scroll_ctrl[0], scroll_x};
+wire [8:0] col_scroll = (scroll_ctrl[3:1] == 3'b011) ? zram0_D : scroll_y;
+wire [8:0] tilemap_hpos = hcnt_x + row_scroll;
+wire [8:0] tilemap_vpos = vcnt_x + col_scroll;
+
+//Address output to tilemap section of VRAM
+wire [9:0] vram_A = {tilemap_vpos[7:3], tilemap_hpos[7:3]};
+
+//Assign tile index as bits 5 and 6 of tilemap attributes and the tile code
+wire [9:0] tile_index = {tileram_attrib_D[7:6], tileram_D};
+
+//XOR tile H/V flip bits with the flipscreen bit
+wire tile_hflip = tileram_attrib_D[4];
+wire tile_vflip = tileram_attrib_D[5];
+
+//Address output to graphics ROMs
+assign R = {tile_ctrl[1:0], tile_index, (tilemap_vpos[2:0] ^ {3{tile_vflip}}), (tilemap_hpos[2] ^ tile_hflip)};
+
+//Latch tile data from graphics ROMs, tile colors and tile H flip bit from VRAM on the falling edge of tilemap horizontal position
+//bit 1
+reg [15:0] RD_lat = 16'd0;
+reg [3:0] tile_color = 4'd0;
+reg tile_hflip_lat = 0;
+reg old_tilehpos1;
+always_ff @(posedge CK49) begin
+ old_tilehpos1 <= tilemap_hpos[1];
+ if(old_tilehpos1 && !tilemap_hpos[1]) begin
+ tile_color <= tileram_attrib_D[3:0];
+ RD_lat <= flipscreen ? {RDL, RDU} : {RDU, RDL};
+ tile_hflip_lat <= tileram_attrib_D[4];
+ end
+end
+
+//Multiplex graphics ROM data down from 16 bits to 8 using bit 1 of the horizontal position
+wire [7:0] RD = (tilemap_hpos[1] ^ tile_hflip_lat) ? RD_lat[7:0] : RD_lat[15:8];
+
+//Further multiplex graphics ROM data down from 8 bits to 4 using bit 0 of the horizontal position
+wire [3:0] tile_pixel = (tilemap_hpos[0] ^ tile_hflip_lat) ? RD[3:0] : RD[7:4];
+
+//Retrieve tilemap select bit from bit 1 of the tile control register XORed with bit 5 of the same register
+wire tile_sel = tile_ctrl[1] ^ tile_ctrl[5];
+reg tilemap_en = 0;
+always_ff @(posedge CK49) begin
+ if(n_cen_6m) begin
+ tilemap_en <= tile_sel;
+ end
+end
+
+//Address output to tilemap LUT PROM
+assign VCF = tile_color;
+assign VCB = tile_pixel;
+
+//Shift the tilemap layer left by two lines when the screen is flipped
+reg [7:0] tilemap_shift;
+always_ff @(posedge CK49) begin
+ if(cen_6m)
+ tilemap_shift <= {VCD, tilemap_shift[7:4]};
+end
+wire [3:0] tilemap_D = flipscreen ? tilemap_shift[3:0] : VCD;
+
+//-------------------------------------------------------- Sprite layer --------------------------------------------------------//
+
+//The following code is an adaptation of the sprite renderer from MiSTer-X's Green Beret core tweaked for the 005885's sprite format
+reg [8:0] sprite_hpos = 9'd0;
+reg [8:0] sprite_vpos = 9'd0;
+always_ff @(posedge CK49) begin
+ if(cen_6m) begin
+ sprite_hpos <= h_cnt;
+ //If a bootleg Iron Horse ROM set is loaded, apply a vertical offset of 65 lines (66 when flipped) to recreate the
+ //bootleg hardware's 1-line downward vertical offset between the sprite and tilemap layers, otherwise apply a
+ //vertical offset of 66 lines (65 lines when flipped)
+ if(BTLG == 2'b10)
+ if(flipscreen)
+ sprite_vpos <= v_cnt + 9'd66;
+ else
+ sprite_vpos <= v_cnt + 9'd65;
+ else
+ if(flipscreen)
+ sprite_vpos <= v_cnt + 9'd65;
+ else
+ sprite_vpos <= v_cnt + 9'd66;
+ end
+end
+
+//Sprite state machine
+reg [8:0] sprite_index;
+reg [2:0] sprite_offset;
+reg [7:0] sprite_attrib0, sprite_attrib1, sprite_attrib2, sprite_attrib3, sprite_attrib4;
+reg [2:0] sprite_fsm_state;
+reg [5:0] sprite_width;
+reg [15:0] sprite_rom_addr;
+//Bootleg Iron Horse PCBs have a lower-than-normal sprite limit causing noticeable sprite flickering - reduce the sprite limit
+//to 32 sprites (0 - 155 in increments of 5) if one such ROM set is loaded (render 96 sprites at once, 0 - 485 in increments of
+//5, otherwise)
+wire [8:0] sprite_limit = (BTLG == 2'b10) ? 9'd155 : 9'd485;
+reg [3:0] waitstate;
+
+always_ff @(posedge CK49) begin
+ //Reset the sprite state machine whenever the sprite horizontal postion, and in turn the horziontal counter, returns to 0
+ //Also hold the sprite state machine in this initial state for the first line while drawing sprites for bootleg Iron Horse
+ //ROM sets to prevent graphical garbage from occurring on the top-most line
+ if(sprite_hpos == 9'd0 || (BTLG == 2'b10 && (!flipscreen && sprite_vpos <= 9'd80) || (flipscreen && sprite_vpos >= 9'd304))) begin
+ sprite_width <= 0;
+ sprite_index <= 0;
+ sprite_offset <= 3'd4;
+ sprite_fsm_state <= 1;
+ waitstate <= 0;
+ end
+ else
+ case(sprite_fsm_state)
+ 0: /* empty */ ;
+ 1: begin
+ waitstate <= 0;
+ if(sprite_index > sprite_limit)
+ sprite_fsm_state <= 0;
+ else begin
+ sprite_attrib4 <= spriteram_D;
+ sprite_offset <= 3'd3;
+ sprite_fsm_state <= sprite_fsm_state + 3'd1;
+ end
+ end
+ 2: begin
+ sprite_attrib3 <= spriteram_D;
+ sprite_offset <= 3'd2;
+ sprite_fsm_state <= sprite_fsm_state + 3'd1;
+ end
+ 3: begin
+ //Skip the current sprite if it's inactive, otherwise obtain the sprite Y attribute and continue
+ //scanning out the rest of the sprite attributes
+ if(sprite_active) begin
+ sprite_attrib2 <= spriteram_D;
+ sprite_offset <= 3'd1;
+ sprite_fsm_state <= sprite_fsm_state + 3'd1;
+ end
+ else begin
+ sprite_index <= sprite_index + 9'd5;
+ sprite_offset <= 3'd4;
+ sprite_fsm_state <= 3'd1;
+ end
+ end
+ 4: begin
+ sprite_attrib1 <= spriteram_D;
+ sprite_offset <= 3'd0;
+ sprite_fsm_state <= sprite_fsm_state + 3'd1;
+ end
+ 5: begin
+ sprite_attrib0 <= spriteram_D;
+ sprite_offset <= 3'd4;
+ sprite_index <= sprite_index + 9'd5;
+ case(sprite_size)
+ 3'b000: sprite_width <= 6'b110000 + (BTLG == 2'b01 && flipscreen);
+ 3'b001: sprite_width <= 6'b110000 + (BTLG == 2'b01 && flipscreen);
+ 3'b010: sprite_width <= 6'b111000 + (BTLG == 2'b01 && flipscreen);
+ 3'b011: sprite_width <= 6'b111000 + (BTLG == 2'b01 && flipscreen);
+ 3'b100: sprite_width <= 6'b100000 + (BTLG == 2'b01 && flipscreen);
+ default: sprite_width <= 6'b100000 + (BTLG == 2'b01 && flipscreen);
+ endcase
+ sprite_fsm_state <= sprite_fsm_state + 3'd1;
+ waitstate <= 4'd14;
+ end
+ 6: if (waitstate == 0) begin
+ //Skip the last line of a sprite if a bootleg Jackal ROM set is loaded (the hardware on such bootlegs fails
+ //to render the last line of sprites), otherwise write sprites as normal
+ if(BTLG == 2'b01 && !flipscreen)
+ if(sprite_width == 6'b111110)
+ sprite_width <= sprite_width + 6'd2;
+ else
+ sprite_width <= sprite_width + 6'd1;
+ else
+ sprite_width <= sprite_width + 6'd1;
+
+ if (sprite_width[1:0] == 2'b11) waitstate <= 4'd14;
+ sprite_fsm_state <= wre ? sprite_fsm_state : 3'd1;
+ end
+ else begin
+ sprite_rom_addr <= {sprite_code_sized, ly[2:0], lx[2]};
+ waitstate <= waitstate - 1'd1;
+ end
+ default:;
+ endcase
+end
+
+//Obtain sprite X position from sprite attribute byte 3 - append a 9th bit based on the state of bit 1 sprite attribute byte 4,
+//bit 0 of sprite attribute byte 4 if high or the AND of the upper 5 bits of the horizontal position if low
+reg sprite_x8;
+always_ff @(posedge CK49) begin
+ if(sprite_attrib4[1])
+ sprite_x8 <= sprite_attrib4[0];
+ else
+ sprite_x8 <= &sprite_attrib3[7:3];
+end
+wire [8:0] sprite_x = {sprite_x8 ^ flipscreen, sprite_attrib3 ^ {8{flipscreen}}};
+
+//If the sprite state machine is in state 3, obtain sprite Y position directly from sprite RAM, otherwise obtain it from
+//sprite attribute byte 2
+wire [7:0] sprite_y = (sprite_fsm_state == 3'd3) ? spriteram_D : sprite_attrib2;
+
+//Sprite flip attributes are stored in bits 5 (horizontal) and 6 (vertical) of sprite attribute byte 4
+//Also XOR these attributes with the flipscreen bit (XOR with the inverse for vertical flip)
+wire sprite_hflip = sprite_attrib4[5] ^ flipscreen;
+wire sprite_vflip = sprite_attrib4[6] ^ ~flipscreen;
+
+//Sprite code is sprite attribute byte 0 sandwiched between bits 1 and 0 and bits 3 and 2 of sprite attribute byte 1
+wire [11:0] sprite_code = {sprite_attrib1[1:0], sprite_fsm_state == 5 ? spriteram_D : sprite_attrib0, sprite_attrib1[3:2]};
+
+//Sprite color is the upper 4 bits of sprite attribute byte 1
+wire [3:0] sprite_color = sprite_attrib1[7:4];
+
+//The 005885 supports 5 different sprite sizes: 8x8, 8x16, 16x8, 16x16 and 32x32. Retrieve this attribute from bits [4:2] of
+//sprite attribute byte 4
+wire [2:0] sprite_size = sprite_attrib4[4:2];
+
+//Adjust sprite code based on sprite size
+wire [11:0] sprite_code_sized = sprite_size == 3'b000 ? {sprite_code[11:2], ly[3], lx[3]}: //16x16
+ sprite_size == 3'b001 ? {sprite_code[11:1], lx[3]}: //16x8
+ sprite_size == 3'b010 ? {sprite_code[11:2], ly[3], sprite_code[0]}: //8x16
+ sprite_size == 3'b011 ? sprite_code: //8x8
+ {sprite_code[11:2] + {ly[4], lx[4]}, ly[3], lx[3]}; //32x32
+
+//Subtract vertical sprite position from sprite Y parameter to obtain sprite height
+wire [8:0] sprite_height = {(sprite_y[7:4] == 4'hF), sprite_y ^ {8{flipscreen}}} - sprite_vpos;
+
+//Set when a sprite is active depending on whether it is 8, 16 or 32 pixels tall
+reg sprite_active;
+always @(*) begin
+ case(sprite_size)
+ 3'b000: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen)
+ & (sprite_height[4] ^ flipscreen);
+ 3'b001: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen)
+ & (sprite_height[4] ^ flipscreen) & (sprite_height[3] ^ flipscreen);
+ 3'b010: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen)
+ & (sprite_height[4] ^ flipscreen);
+ 3'b011: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen)
+ & (sprite_height[4] ^ flipscreen) & (sprite_height[3] ^ flipscreen);
+ 3'b100: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen);
+ default: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen);
+ endcase
+end
+
+wire [4:0] lx = sprite_width[4:0] ^ {5{sprite_hflip}};
+wire [4:0] ly = sprite_height[4:0] ^ {5{sprite_vflip}};
+
+//Assign address outputs to sprite ROMs
+assign S = sprite_rom_addr;
+
+
+//Multiplex sprite ROM data down from 16 bits to 8 using bit 1 of the horizontal position
+wire [7:0] SD = lx[1] ? SDL : SDU;
+
+//Further multiplex sprite ROM data down from 8 bits to 4 using bit 0 of the horizontal position
+wire [3:0] sprite_pixel = lx[0] ? SD[3:0] : SD[7:4];
+
+//Sum the sprite index with the sprite offset and address sprite RAM with it along with tile control register bit 3
+wire [8:0] sprite_address = (sprite_index + sprite_offset);
+reg sprite_bank = 0;
+reg old_vsync;
+//Normally, the 005885 latches the sprite bank from bit 3 of the tile control register on the rising edge of VSync, though this causes
+//jerky scrolling with sprites for bootleg Jackal ROM sets - bypass this latch if such ROM sets are loaded
+always_ff @(posedge CK49) begin
+ old_vsync <= NVSY;
+ if(!NEXR)
+ sprite_bank <= 0;
+ else if(!old_vsync && NVSY)
+ sprite_bank <= tile_ctrl[3];
+end
+wire [11:0] spriteram_A = {(BTLG == 2'b01) ? tile_ctrl[3] : sprite_bank, 2'b00, sprite_address};
+
+//Address output to sprite LUT PROM
+assign OCF = sprite_color;
+assign OCB = sprite_pixel;
+
+//----------------------------------------------------- Sprite line buffer -----------------------------------------------------//
+
+//The sprite line buffer is external to the 005885 and consists of two 4464 DRAM chips. For simplicity, both the logic for the
+//sprite line buffer and the sprite line buffer itself are internal to the 005885 implementation.
+
+//Enable writing to sprite line buffer when bit 5 of the sprite width is 1
+wire wre = sprite_width[5];
+
+//Set sprite line buffer bank as bit 0 of the sprite vertical position
+wire sprite_lbuff_bank = sprite_vpos[0];
+
+//Sum sprite X position with the following bits of the sprite width to address the sprite line buffer based on sprite size:
+//32 pixels wide: bits [4:0]
+//16 pixels wide: bits [3:0]
+//8 pixels wide: bits [2:0]
+//XOR the upper bits for screen flipping on 16 pixel and 8 pixel wide sprites
+reg [4:0] final_sprite_width;
+always @(*) begin
+ case(sprite_size)
+ 3'b000: final_sprite_width <= {sprite_width[4] ^ ~flipscreen, sprite_width[3:0]};
+ 3'b001: final_sprite_width <= {sprite_width[4] ^ ~flipscreen, sprite_width[3:0]};
+ 3'b010: final_sprite_width <= {sprite_width[4:3] ^ {2{~flipscreen}}, sprite_width[2:0]};
+ 3'b011: final_sprite_width <= {sprite_width[4:3] ^ {2{~flipscreen}}, sprite_width[2:0]};
+ 3'b100: final_sprite_width <= sprite_width[4:0];
+ default: final_sprite_width <= sprite_width[4:0];
+ endcase
+end
+wire [8:0] wpx = sprite_x + final_sprite_width;
+
+//Generate sprite line buffer write addresses
+reg [9:0] lbuff_A;
+reg lbuff_we;
+always_ff @(posedge CK49) begin
+ lbuff_A <= {~sprite_lbuff_bank, wpx};
+ lbuff_we <= wre & (waitstate == 0);
+ //lbuff_Din <= OCD;
+end
+
+//Latch sprite LUT PROM data on the falling edge of the main clock
+wire [3:0] lbuff_Din = OCD;
+//always_ff @(negedge CK49) begin
+// lbuff_Din <= OCD;
+//end
+
+//Generate read address for sprite line buffer on the rising edge of the pixel clock (apply a -225 offset when the screen
+//is flipped)
+reg [9:0] radr0 = 10'd0;
+reg [9:0] radr1 = 10'd1;
+always_ff @(posedge CK49) begin
+ if(cen_6m)
+ radr0 <= {sprite_lbuff_bank, flipscreen ? sprite_hpos - 9'd225 : sprite_hpos};
+end
+
+//Sprite line buffer
+wire [3:0] lbuff_Dout;
+dpram_dc #(.widthad_a(10)) LBUFF
+(
+ .clock_a(CK49),
+ .address_a(lbuff_A),
+ .data_a({4'd0, lbuff_Din}),
+ .wren_a(lbuff_we & (lbuff_Din != 0)),
+
+ .clock_b(CK49),
+ .address_b(radr0),
+ .data_b(8'h0),
+ .wren_b(radr0 == radr1),
+ .q_b({4'bZZZZ, lbuff_Dout})
+);
+
+//Latch sprite data from the sprite line buffer
+wire lbuff_read_en = (div[2:0] == 3'b100);
+reg [3:0] lbuff_read = 4'd0;
+always_ff @(posedge CK49) begin
+ if(lbuff_read_en) begin
+ if(radr0 != radr1)
+ lbuff_read <= lbuff_Dout;
+ radr1 <= radr0;
+ end
+end
+
+//Delay sprite layer by 2 horizontal lines (1 line if a bootleg Jackal ROM set is loaded and the screen is flipped)
+reg [7:0] sprite_dly = 8'd0;
+always_ff @(posedge CK49) begin
+ if(cen_6m) begin
+ if(BTLG == 2'b01 && flipscreen)
+ sprite_dly <= {4'd0, lbuff_read};
+ else
+ sprite_dly <= {lbuff_read, sprite_dly[7:4]};
+ end
+end
+//Jackal bootlegs fail to render the last two vertical lines of the sprite layer - model this behavior here
+wire [3:0] sprite_D = (BTLG == 2'b01 && ((h_cnt >= 244 && ~flipscreen) || (h_cnt >= 248 && flipscreen))) ? 4'd0 : sprite_dly[3:0];
+
+//--------------------------------------------------------- Color mixer --------------------------------------------------------//
+
+//Multiplex tile and sprite data, then output the final result
+wire tile_sprite_sel = (tilemap_en | ~(|sprite_D));
+wire [3:0] tile_sprite_D = tile_sprite_sel ? tilemap_D : sprite_D;
+
+//Latch and output pixel data
+reg [4:0] pixel_D;
+always_ff @(posedge CK49) begin
+ if(cen_6m)
+ pixel_D <= {tile_sprite_sel, tile_sprite_D};
+end
+assign COL = (BTLG == 2'b01 && ((h_cnt >= 247 && ~flipscreen) || (h_cnt <= 14 && flipscreen))) ||
+ (BTLG == 2'b10 && ((h_cnt <= 20 && ~flipscreen) || ((h_cnt <= 18 || h_cnt >= 251) && flipscreen))) ? 5'd0 : pixel_D;
+//The above condition blacks out the last 4 lines on the right side of the screen (left when flipped) when a bootleg Jackal ROM set
+//is loaded and blacks out the left-most 8 lines (7 when flipped plus an extra 2 lines on the right side) when a bootleg Iron Horse
+//ROM set is loaded - this simulates the earlier-than-normal start of HBlank for Jackal bootlegs and later-than-normal end of
+//HBlank for Iron Horse bootlegs while maintaining the usual 240x224 display area
+
+endmodule
diff --git a/Arcade_MiST/Konami Jackal/rtl/custom/k007327.sv b/Arcade_MiST/Konami Jackal/rtl/custom/k007327.sv
new file mode 100644
index 00000000..6fce8edd
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/rtl/custom/k007327.sv
@@ -0,0 +1,149 @@
+//============================================================================
+//
+// SystemVerilog implementation of the Konami 007327 custom palette RAM +
+// video DAC module
+// Copyright (C) 2021 Ace & SnakeGrunger
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+//============================================================================
+
+//Module pinout:
+/* _______________________
+ _| |_
+CCS |_|1 40|_| CLK
+ _| |_
+CWR |_|2 39|_| BLK
+ _| |_
+D[7] |_|3 38|_| RW
+ _| |_
+D[6] |_|4 37|_| A[0]
+ _| |_
+D[5] |_|5 36|_| NA0
+ _| |_
+D[4] |_|6 35|_| A[1]
+ _| |_
+D[3] |_|7 34|_| A[2]
+ _| |_
+D[2] |_|8 33|_| A[3]
+ _| |_
+D[1] |_|9 32|_| A[4]
+ _| |_
+D[0] |_|10 31|_| A[5]
+ _| |_
+GND |_|11 30|_| A[6]
+ _| |_
+VCC |_|12 29|_| A[7]
+ _| |_
+B |_|13 28|_| CB[0]
+ _| |_
+G |_|14 27|_| CB[1]
+ _| |_
+R |_|15 26|_| CB[2]
+ _| |_
+GND |_|16 25|_| CB[3]
+ _| |_
+RA[8] |_|17 24|_| CB[4]
+ _| |_
+RA[9] |_|18 23|_| CB[5]
+ _| |_
+RA[10] |_|19 22|_| CB[6]
+ _| |_
+RA[11] |_|20 21|_| SEL
+ |_______________________|
+*/
+
+module k007327
+(
+ input CLK, //Clock input
+ input CEN, //Clock enable input (set to 1 if replacing an actual 007327)
+ input [11:8] RA, //External address inputs to palette RAM's upper 4 address bits
+ input [7:0] A, //Address bus from CPU
+ input NA0, //Inverse of address bit A0
+ input [6:0] CB, //7-bit Color bus input
+ input [7:0] Di, //CPU data input
+ input RW, //Read/write input
+ input SEL, //Color/CPU data select input
+ input CCS, //Chip select input (active low)
+ input CWR, //Color write enable (active low)
+ input BLK, //Blank input
+ output [4:0] R, G, B, //15-bit RGB color output, 5 bits per color
+ output [7:0] Do //CPU data output
+);
+
+//Multiplex address lines A[6:0] for palette RAM
+wire [10:0] paletteram_A;
+assign paletteram_A[10:7] = RA[11:8];
+assign paletteram_A[6:0] = SEL ? CB : A[7:1];
+
+//Generate read and write enable signals for palette RAM
+wire n_paletteram0_cs = (CCS | NA0);
+wire n_paletteram1_cs = (CCS | A[0]);
+wire n_paletteram0_wr = (n_paletteram0_cs | CWR);
+wire n_paletteram1_wr = (n_paletteram1_cs | CWR);
+
+//Palette RAM
+wire [15:0] paletteram_D;
+spram #(8, 11) PALRAM_L
+(
+ .clk(CLK),
+ .addr(paletteram_A),
+ .data(Di),
+ .q(paletteram_D[7:0]),
+ .we(~n_paletteram0_wr & RW)
+);
+spram #(8, 11) PALRAM_H
+(
+ .clk(CLK),
+ .addr(paletteram_A),
+ .data(Di),
+ .q(paletteram_D[15:8]),
+ .we(~n_paletteram1_wr & RW)
+);
+
+//Output palette RAM data to CPU
+assign Do = (~n_paletteram0_cs & ~RW) ? paletteram_D[7:0]:
+ (~n_paletteram1_cs & ~RW) ? paletteram_D[15:8]:
+ 8'hFF;
+
+//Latch blank input at every positive edge of the incoming clock
+reg blank = 1;
+always_ff @(posedge CLK) begin
+ if(CEN)
+ blank <= BLK;
+end
+
+//Latch pixel data
+reg [4:0] pixel_red = 0;
+reg [4:0] pixel_green = 0;
+reg [4:0] pixel_blue = 0;
+always_ff @(posedge CLK) begin
+ if(CEN) begin
+ pixel_red <= paletteram_D[12:8];
+ pixel_green <= {paletteram_D[1:0], paletteram_D[15:13]};
+ pixel_blue <= paletteram_D[6:2];
+ end
+end
+
+//Generate final RGB output
+assign R = blank ? pixel_red : 5'd0;
+assign G = blank ? pixel_green : 5'd0;
+assign B = blank ? pixel_blue : 5'd0;
+
+endmodule
diff --git a/Arcade_MiST/Konami Jackal/rtl/custom/k007343.sv b/Arcade_MiST/Konami Jackal/rtl/custom/k007343.sv
new file mode 100644
index 00000000..14a8f85b
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/rtl/custom/k007343.sv
@@ -0,0 +1,92 @@
+//============================================================================
+//
+// SystemVerilog implementation of the Konami K007343, a PAL16L8 used as part
+// of the address decoding hardware on Jackal/Top Gunner arcade PCBs
+// Converted from dump available at the PLD Archive
+// http://wiki.pldarchive.co.uk/index.php?title=Jackal
+// Copyright (C) 2021 Ace
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+//============================================================================
+
+//Chip pinout:
+/* _____________
+ _| |_
+A13 |_|1 20|_| VCC
+ _| |_
+A12 |_|2 19|_| MGCS
+ _| |_
+A11 |_|3 18|_| NC
+ _| |_
+A10 |_|4 17|_| CRCS
+ _| |_
+A8_9 |_|5 16|_| IOCS
+ _| |_
+A7 |_|6 15|_| GATEB
+ _| |_
+A6 |_|7 14|_| WR
+ _| |_
+A5 |_|8 13|_| OBJB
+ _| |_
+A4 |_|9 12|_| SGCS
+ _| |_
+GND |_|10 11|_| GATECS
+ |_____________|
+*/
+
+module k007343
+(
+ input A4,
+ input A5,
+ input A6,
+ input A7,
+ input A8_9,
+ input A10,
+ input A11,
+ input A12,
+ input A13,
+ input WR,
+ input OBJB,
+ input GATEB,
+ input GATECS,
+ output MGCS,
+ output SGCS,
+ output IOCS,
+ output CRCS
+);
+
+wire o18 = ~(A13 & A12 & ~A10 & ~GATECS |
+ A13 & A12 & ~A8_9 & ~GATECS);
+
+assign MGCS = ~(~GATECS & ~OBJB & ~GATEB & IOCS & CRCS |
+ ~GATECS & ~GATEB & IOCS & CRCS & o18);
+assign CRCS = ~(~A13 & A12 & ~GATECS |
+ ~A13 & ~A12 & A11 & ~GATECS |
+ ~A13 & ~A12 & A8_9 & ~GATECS |
+ ~A13 & ~A12 & A7 & ~GATECS |
+ ~A13 & ~A12 & A6 & A5 & ~GATECS |
+ ~A13 & ~A12 & A10 & ~GATECS);
+assign IOCS = ~(~A13 & ~A12 & ~A11 & ~A10 & ~A8_9 & ~A7 & ~A6 & ~A5 & A4 & ~GATECS);
+assign SGCS = ~(~GATECS & GATEB & IOCS & CRCS |
+ ~GATECS & OBJB & ~WR & IOCS & CRCS |
+ ~GATECS & OBJB & IOCS & CRCS & ~o18 |
+ ~GATECS & ~WR & IOCS & CRCS & o18);
+
+endmodule
diff --git a/Arcade_MiST/Konami Jackal/rtl/dpram_dc.vhd b/Arcade_MiST/Konami Jackal/rtl/dpram_dc.vhd
new file mode 100644
index 00000000..69d4c5fb
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/rtl/dpram_dc.vhd
@@ -0,0 +1,136 @@
+LIBRARY ieee;
+USE ieee.std_logic_1164.all;
+
+LIBRARY altera_mf;
+USE altera_mf.all;
+
+ENTITY dpram_dc IS
+ GENERIC
+ (
+ init_file : string := " ";
+ widthad_a : natural;
+ width_a : natural := 8;
+ outdata_reg_a : string := "UNREGISTERED";
+ outdata_reg_b : string := "UNREGISTERED"
+ );
+ PORT
+ (
+ address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
+ address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0) := (others => '0');
+ clock_a : IN STD_LOGIC ;
+ clock_b : IN STD_LOGIC ;
+ data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) := (others => '0');
+ data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) := (others => '0');
+ wren_a : IN STD_LOGIC := '0';
+ wren_b : IN STD_LOGIC := '0';
+ byteena_a : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) := (others => '1');
+ byteena_b : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) := (others => '1');
+ q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
+ q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0)
+ );
+END dpram_dc;
+
+
+ARCHITECTURE SYN OF dpram_dc IS
+
+ SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
+ SIGNAL sub_wire1 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
+
+
+
+ COMPONENT altsyncram
+ GENERIC (
+ address_reg_b : STRING;
+ clock_enable_input_a : STRING;
+ clock_enable_input_b : STRING;
+ clock_enable_output_a : STRING;
+ clock_enable_output_b : STRING;
+ indata_reg_b : STRING;
+ init_file : STRING;
+ intended_device_family : STRING;
+ lpm_type : STRING;
+ numwords_a : NATURAL;
+ numwords_b : NATURAL;
+ operation_mode : STRING;
+ outdata_aclr_a : STRING;
+ outdata_aclr_b : STRING;
+ outdata_reg_a : STRING;
+ outdata_reg_b : STRING;
+ power_up_uninitialized : STRING;
+ read_during_write_mode_port_a : STRING;
+ read_during_write_mode_port_b : STRING;
+ widthad_a : NATURAL;
+ widthad_b : NATURAL;
+ width_a : NATURAL;
+ width_b : NATURAL;
+ width_byteena_a : NATURAL;
+ width_byteena_b : NATURAL;
+ wrcontrol_wraddress_reg_b : STRING
+ );
+ PORT (
+ wren_a : IN STD_LOGIC ;
+ clock0 : IN STD_LOGIC ;
+ wren_b : IN STD_LOGIC ;
+ clock1 : IN STD_LOGIC ;
+ address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
+ address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
+ q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
+ q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
+ byteena_a : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) ;
+ byteena_b : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) ;
+ data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
+ data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0)
+ );
+ END COMPONENT;
+
+BEGIN
+ q_a <= sub_wire0(width_a-1 DOWNTO 0);
+ q_b <= sub_wire1(width_a-1 DOWNTO 0);
+
+ altsyncram_component : altsyncram
+ GENERIC MAP (
+ address_reg_b => "CLOCK1",
+ clock_enable_input_a => "BYPASS",
+ clock_enable_input_b => "BYPASS",
+ clock_enable_output_a => "BYPASS",
+ clock_enable_output_b => "BYPASS",
+ indata_reg_b => "CLOCK1",
+ init_file => init_file,
+ intended_device_family => "Cyclone III",
+ lpm_type => "altsyncram",
+ numwords_a => 2**widthad_a,
+ numwords_b => 2**widthad_a,
+ operation_mode => "BIDIR_DUAL_PORT",
+ outdata_aclr_a => "NONE",
+ outdata_aclr_b => "NONE",
+ outdata_reg_a => outdata_reg_a,
+ outdata_reg_b => outdata_reg_a,
+ power_up_uninitialized => "FALSE",
+ read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ",
+ read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ",
+ widthad_a => widthad_a,
+ widthad_b => widthad_a,
+ width_a => width_a,
+ width_b => width_a,
+ width_byteena_a => width_a/8,
+ width_byteena_b => width_a/8,
+ wrcontrol_wraddress_reg_b => "CLOCK1"
+ )
+ PORT MAP (
+ wren_a => wren_a,
+ clock0 => clock_a,
+ wren_b => wren_b,
+ clock1 => clock_b,
+ address_a => address_a,
+ address_b => address_b,
+ data_a => data_a,
+ data_b => data_b,
+ q_a => sub_wire0,
+ q_b => sub_wire1,
+ byteena_a => byteena_a,
+ byteena_b => byteena_b
+ );
+
+
+
+END SYN;
diff --git a/Arcade_MiST/Konami Jackal/rtl/hiscore.v b/Arcade_MiST/Konami Jackal/rtl/hiscore.v
new file mode 100644
index 00000000..0fd1ef66
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/rtl/hiscore.v
@@ -0,0 +1,602 @@
+//============================================================================
+// MAME hiscore.dat support for MiSTer arcade cores.
+//
+// https://github.com/JimmyStones/Hiscores_MiSTer
+//
+// Copyright (c) 2021 Alan Steremberg
+// Copyright (c) 2021 Jim Gregory
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//============================================================================
+/*
+ Version history:
+ 0001 - 2021-03-06 - First marked release
+ 0002 - 2021-03-06 - Added HS_DUMPFORMAT localparam to identify dump version (for future use)
+ Add HS_CONFIGINDEX and HS_DUMPINDEX parameters to configure ioctl_indexes
+ 0003 - 2021-03-10 - Added WRITE_REPEATCOUNT and WRITE_REPEATWAIT to handle tricky write situations
+ 0004 - 2021-03-15 - Fix ram_access assignment
+ 0005 - 2021-03-18 - Add configurable score table width, clean up some stupid mistakes
+ 0006 - 2021-03-27 - Move 'tweakable' parameters into MRA data header
+ 0007 - 2021-04-15 - Improve state machine maintainability, add new 'pause padding' states
+ 0008 - 2021-05-12 - Feed back core-level pause to halt startup timer
+============================================================================
+*/
+
+module hiscore
+#(
+ parameter HS_ADDRESSWIDTH=10, // Max size of game RAM address for highscores
+ parameter HS_SCOREWIDTH=8, // Max size of capture RAM For highscore data (default 8 = 256 bytes max)
+ parameter HS_CONFIGINDEX=3, // ioctl_index for config transfer
+ parameter HS_DUMPINDEX=4, // ioctl_index for dump transfer
+ parameter CFG_ADDRESSWIDTH=4, // Max size of RAM address for highscore.dat entries (default 4 = 16 entries max)
+ parameter CFG_LENGTHWIDTH=1 // Max size of length for each highscore.dat entries (default 1 = 256 bytes max)
+)
+(
+ input clk,
+ input paused, // Signal from core confirming CPU is paused
+ input reset,
+
+ input ioctl_upload,
+ input ioctl_download,
+ input ioctl_wr,
+ input [24:0] ioctl_addr,
+ input [7:0] ioctl_dout,
+ input [7:0] ioctl_din,
+ input [7:0] ioctl_index,
+
+ output [HS_ADDRESSWIDTH-1:0] ram_address, // Address in game RAM to read/write score data
+ output [7:0] data_to_ram, // Data to write to game RAM
+ output reg ram_write, // Write to game RAM (active high)
+ output ram_access, // RAM read or write required (active high)
+ output reg pause_cpu // Pause core CPU to prepare for/relax after RAM access
+);
+
+// Parameters read from config header
+reg [31:0] START_WAIT =32'd0; // Delay before beginning check process
+reg [15:0] CHECK_WAIT =16'hFF; // Delay between start/end check attempts
+reg [15:0] CHECK_HOLD =16'd2; // Hold time for start/end check reads
+reg [15:0] WRITE_HOLD =16'd2; // Hold time for game RAM writes
+reg [15:0] WRITE_REPEATCOUNT =16'b1; // Number of times to write score to game RAM
+reg [15:0] WRITE_REPEATWAIT =16'b1111; // Delay between subsequent write attempts to game RAM
+reg [7:0] ACCESS_PAUSEPAD =8'd4; // Cycles to wait with paused CPU before and after RAM access
+
+
+// State machine constants
+localparam SM_STATEWIDTH = 4; // Width of state machine net
+
+localparam SM_INIT = 0;
+localparam SM_TIMER = 1;
+
+localparam SM_CHECKPREP = 2;
+localparam SM_CHECKBEGIN = 3;
+localparam SM_CHECKSTARTVAL = 4;
+localparam SM_CHECKENDVAL = 5;
+localparam SM_CHECKCANCEL = 6;
+
+localparam SM_WRITEPREP = 7;
+localparam SM_WRITEBEGIN = 8;
+localparam SM_WRITEREADY = 9;
+localparam SM_WRITEDONE = 10;
+localparam SM_WRITECOMPLETE = 11;
+localparam SM_WRITERETRY = 12;
+
+localparam SM_STOPPED = 13;
+
+/*
+Hiscore config data structure (version 1)
+-----------------------------------------
+[16 byte header]
+[8 byte * no. of entries]
+
+- Header format
+00 00 FF FF 00 FF 00 02 00 02 00 01 11 11 00 00
+[ SW ] [ CW] [ CH] [ WH] [WRC] [WRW] [PAD]
+4 byte START_WAIT
+2 byte CHECK_WAIT
+2 byte CHECK_HOLD
+2 byte WRITE_HOLD
+2 byte WRITE_REPEATCOUNT
+2 byte WRITE_REPEATWAIT
+2 byte (padding/future use)
+
+- Entry format (when CFG_LENGTHWIDTH=1)
+00 00 43 0b 0f 10 01 00
+00 00 40 23 02 04 12 00
+[ ADDR ] LEN START END PAD
+
+4 bytes Address of ram entry (in core memory map)
+1 byte Length of ram entry in bytes
+1 byte Start value to check for at start of address range before proceeding
+1 byte End value to check for at end of address range before proceeding
+1 byte (padding)
+
+- Entry format (when CFG_LENGTHWIDTH=2)
+00 00 43 0b 00 0f 10 01
+00 00 40 23 00 02 04 12
+[ ADDR ] [LEN ] START END
+
+4 bytes Address of ram entry (in core memory map)
+2 bytes Length of ram entry in bytes
+1 byte Start value to check for at start of address range before proceeding
+1 byte End value to check for at end of address range before proceeding
+
+*/
+
+localparam HS_VERSION =8; // Version identifier for module
+localparam HS_DUMPFORMAT =1; // Version identifier for dump format
+localparam HS_HEADERLENGTH =16; // Size of header chunk (default=16 bytes)
+
+// HS_DUMPFORMAT = 1 --> No header, just the extracted hiscore data
+
+// Hiscore config and dump status
+wire downloading_config;
+wire parsing_header;
+wire downloading_dump;
+wire uploading_dump;
+reg downloaded_config = 1'b0;
+reg downloaded_dump = 1'b0;
+reg uploaded_dump = 1'b0;
+reg [3:0] initialised;
+reg writing_scores = 1'b0;
+reg checking_scores = 1'b0;
+
+assign downloading_config = ioctl_download && (ioctl_index==HS_CONFIGINDEX);
+assign parsing_header = downloading_config && (ioctl_addr<=HS_HEADERLENGTH);
+assign downloading_dump = ioctl_download && (ioctl_index==HS_DUMPINDEX);
+assign uploading_dump = ioctl_upload && (ioctl_index==HS_DUMPINDEX);
+assign ram_access = uploading_dump | writing_scores | checking_scores;
+assign ram_address = ram_addr[HS_ADDRESSWIDTH-1:0];
+
+reg [(SM_STATEWIDTH-1):0] state = SM_INIT; // Current state machine index
+reg [(SM_STATEWIDTH-1):0] next_state = SM_INIT; // Next state machine index to move to after wait timer expires
+reg [31:0] wait_timer; // Wait timer for inital/read/write delays
+
+reg [CFG_ADDRESSWIDTH-1:0] counter = 1'b0; // Index for current config table entry
+reg [CFG_ADDRESSWIDTH-1:0] total_entries = 1'b0; // Total count of config table entries
+reg reset_last = 1'b0; // Last cycle reset
+reg [7:0] write_counter = 1'b0; // Index of current game RAM write attempt
+
+reg [7:0] last_ioctl_index; // Last cycle HPS IO index
+reg last_ioctl_download = 0;// Last cycle HPS IO download
+reg last_ioctl_upload = 0; // Last cycle HPS IO upload
+reg [7:0] last_ioctl_dout; // Last cycle HPS IO data out
+reg [7:0] last_ioctl_dout2; // Last cycle +1 HPS IO data out
+reg [7:0] last_ioctl_dout3; // Last cycle +2 HPS IO data out
+
+reg [24:0] ram_addr; // Target RAM address for hiscore read/write
+reg [24:0] old_io_addr;
+reg [24:0] base_io_addr;
+wire [23:0] addr_base;
+wire [(CFG_LENGTHWIDTH*8)-1:0] length;
+wire [24:0] end_addr = (addr_base + length - 1'b1);
+reg [HS_SCOREWIDTH-1:0] local_addr;
+wire [7:0] start_val;
+wire [7:0] end_val;
+
+wire [23:0] address_data_in;
+wire [(CFG_LENGTHWIDTH*8)-1:0] length_data_in;
+
+assign address_data_in = {last_ioctl_dout2, last_ioctl_dout, ioctl_dout};
+assign length_data_in = (CFG_LENGTHWIDTH == 1'b1) ? ioctl_dout : {last_ioctl_dout, ioctl_dout};
+
+wire address_we = downloading_config & ~parsing_header & (ioctl_addr[2:0] == 3'd3);
+wire length_we = downloading_config & ~parsing_header & (ioctl_addr[2:0] == 3'd3 + CFG_LENGTHWIDTH);
+wire startdata_we = downloading_config & ~parsing_header & (ioctl_addr[2:0] == 3'd4 + CFG_LENGTHWIDTH);
+wire enddata_we = downloading_config & ~parsing_header & (ioctl_addr[2:0] == 3'd5 + CFG_LENGTHWIDTH);
+
+// RAM chunks used to store configuration data
+// - address_table
+// - length_table
+// - startdata_table
+// - enddata_table
+dpram_hs #(.aWidth(CFG_ADDRESSWIDTH),.dWidth(24))
+address_table(
+ .clk(clk),
+ .addr_a(ioctl_addr[CFG_ADDRESSWIDTH+2:3] - 2'd2),
+ .we_a(address_we & ioctl_wr),
+ .d_a(address_data_in),
+ .addr_b(counter),
+ .q_b(addr_base)
+);
+// Length table - variable width depending on CFG_LENGTHWIDTH
+dpram_hs #(.aWidth(CFG_ADDRESSWIDTH),.dWidth(CFG_LENGTHWIDTH*8))
+length_table(
+ .clk(clk),
+ .addr_a(ioctl_addr[CFG_ADDRESSWIDTH+2:3] - 2'd2),
+ .we_a(length_we & ioctl_wr),
+ .d_a(length_data_in),
+ .addr_b(counter),
+ .q_b(length)
+);
+dpram_hs #(.aWidth(CFG_ADDRESSWIDTH),.dWidth(8))
+startdata_table(
+ .clk(clk),
+ .addr_a(ioctl_addr[CFG_ADDRESSWIDTH+2:3] - 2'd2),
+ .we_a(startdata_we & ioctl_wr),
+ .d_a(ioctl_dout),
+ .addr_b(counter),
+ .q_b(start_val)
+);
+dpram_hs #(.aWidth(CFG_ADDRESSWIDTH),.dWidth(8))
+enddata_table(
+ .clk(clk),
+ .addr_a(ioctl_addr[CFG_ADDRESSWIDTH+2:3] - 2'd2),
+ .we_a(enddata_we & ioctl_wr),
+ .d_a(ioctl_dout),
+ .addr_b(counter),
+ .q_b(end_val)
+);
+
+// RAM chunk used to store hiscore data
+dpram_hs #(.aWidth(HS_SCOREWIDTH),.dWidth(8))
+hiscoredata (
+ .clk(clk),
+ .addr_a(ioctl_addr[(HS_SCOREWIDTH-1):0]),
+ .we_a(downloading_dump),
+ .d_a(ioctl_dout),
+ .addr_b(local_addr),
+ .we_b(ioctl_upload),
+ .d_b(ioctl_din),
+ .q_b(data_to_ram)
+);
+
+wire [3:0] header_chunk = ioctl_addr[3:0];
+
+always @(posedge clk)
+begin
+
+ if (downloading_config)
+ begin
+ // Get header chunk data
+ if(parsing_header)
+ begin
+ if(ioctl_wr)
+ begin
+ if(header_chunk == 4'd3) START_WAIT <= { last_ioctl_dout3, last_ioctl_dout2, last_ioctl_dout, ioctl_dout };
+ if(header_chunk == 4'd5) CHECK_WAIT <= { last_ioctl_dout, ioctl_dout };
+ if(header_chunk == 4'd7) CHECK_HOLD <= { last_ioctl_dout, ioctl_dout };
+ if(header_chunk == 4'd9) WRITE_HOLD <= { last_ioctl_dout, ioctl_dout };
+ if(header_chunk == 4'd11) WRITE_REPEATCOUNT <= { last_ioctl_dout, ioctl_dout };
+ if(header_chunk == 4'd13) WRITE_REPEATWAIT <= { last_ioctl_dout, ioctl_dout };
+ if(header_chunk == 4'd14) ACCESS_PAUSEPAD <= ioctl_dout;
+ end
+ end
+ else
+ begin
+ // Keep track of the largest entry during config download
+ total_entries <= ioctl_addr[CFG_ADDRESSWIDTH+2:3] - 2'd2;
+ end
+ end
+
+ // Track completion of configuration and dump download
+ if ((last_ioctl_download != ioctl_download) && (ioctl_download == 1'b0))
+ begin
+ if (last_ioctl_index==HS_CONFIGINDEX) downloaded_config <= 1'b1;
+ if (last_ioctl_index==HS_DUMPINDEX) downloaded_dump <= 1'b1;
+ end
+
+ // Track completion of dump upload
+ if ((last_ioctl_upload != ioctl_upload) && (ioctl_upload == 1'b0))
+ begin
+ if (last_ioctl_index==HS_DUMPINDEX)
+ begin
+ uploaded_dump <= 1'b1;
+ // Mark uploaded dump as readable in case of reset
+ downloaded_dump <= 1'b1;
+ end
+ end
+
+ // Track last ioctl values
+ last_ioctl_download <= ioctl_download;
+ last_ioctl_upload <= ioctl_upload;
+ last_ioctl_index <= ioctl_index;
+ if(ioctl_download && ioctl_wr)
+ begin
+ last_ioctl_dout3 = last_ioctl_dout2;
+ last_ioctl_dout2 = last_ioctl_dout;
+ last_ioctl_dout = ioctl_dout;
+ end
+
+ if(downloaded_config)
+ begin
+ // Check for end of state machine reset to initialise state machine
+ reset_last <= reset;
+ if (reset_last == 1'b1 && reset == 1'b0)
+ begin
+ wait_timer <= START_WAIT;
+ next_state <= SM_INIT;
+ state <= SM_TIMER;
+ counter <= 1'b0;
+ initialised <= initialised + 1'b1;
+ end
+ else
+ begin
+ // Upload scores to HPS
+ if (uploading_dump == 1'b1)
+ begin
+ // generate addresses to read high score from game memory. Base addresses off ioctl_address
+ if (ioctl_addr == 25'b0) begin
+ local_addr <= 0;
+ base_io_addr <= 25'b0;
+ counter <= 1'b0000;
+ end
+ // Move to next entry when last address is reached
+ if (old_io_addr!=ioctl_addr && ram_addr==end_addr[24:0])
+ begin
+ counter <= counter + 1'b1;
+ base_io_addr <= ioctl_addr;
+ end
+ // Set game ram address for reading back to HPS
+ ram_addr <= addr_base + (ioctl_addr - base_io_addr);
+ // Set local addresses to update cached dump in case of reset
+ local_addr <= ioctl_addr[HS_SCOREWIDTH-1:0];
+ end
+
+ if (ioctl_upload == 1'b0 && downloaded_dump == 1'b1 && reset == 1'b0)
+ begin
+ // State machine to write data to game RAM
+ case (state)
+ SM_INIT: // Start state machine
+ begin
+ // Setup base addresses
+ local_addr <= 0;
+ base_io_addr <= 25'b0;
+ // Reset entry counter and states
+ counter <= 0;
+ writing_scores <= 1'b0;
+ checking_scores <= 1'b0;
+ pause_cpu <= 1'b0;
+ state <= SM_CHECKPREP;
+ end
+
+ // Start/end check states
+ // ----------------------
+ SM_CHECKPREP: // Prepare start/end check run - pause CPU in readiness for RAM access
+ begin
+ state <= SM_TIMER;
+ next_state <= SM_CHECKBEGIN;
+ pause_cpu <= 1'b1;
+ wait_timer <= ACCESS_PAUSEPAD;
+ end
+
+ SM_CHECKBEGIN: // Begin start/end check run - enable RAM access
+ begin
+ checking_scores <= 1'b1;
+ ram_addr <= {1'b0, addr_base};
+ state <= SM_CHECKSTARTVAL;
+ wait_timer <= CHECK_HOLD;
+ end
+
+ SM_CHECKSTARTVAL: // Start check
+ begin
+ // Check for matching start value
+ if(wait_timer != CHECK_HOLD & ioctl_din == start_val)
+ begin
+ // Prepare end check
+ ram_addr <= end_addr;
+ state <= SM_CHECKENDVAL;
+ wait_timer <= CHECK_HOLD;
+ end
+ else
+ begin
+ ram_addr <= {1'b0, addr_base};
+ if (wait_timer > 1'b0)
+ begin
+ wait_timer <= wait_timer - 1'b1;
+ end
+ else
+ begin
+ // - If no match after read wait then stop check run and schedule restart of state machine
+ next_state <= SM_CHECKCANCEL;
+ state <= SM_TIMER;
+ checking_scores <= 1'b0;
+ wait_timer <= ACCESS_PAUSEPAD;
+ end
+ end
+ end
+
+ SM_CHECKENDVAL: // End check
+ begin
+ // Check for matching end value
+ if (wait_timer != CHECK_HOLD & ioctl_din == end_val)
+ begin
+ if (counter == total_entries)
+ begin
+ // If this was the last entry then move on to writing scores to game ram
+ checking_scores <= 1'b0;
+ state <= SM_WRITEBEGIN; // Bypass SM_WRITEPREP as we are already paused
+ counter <= 1'b0;
+ write_counter <= 1'b0;
+ ram_write <= 1'b0;
+ ram_addr <= {1'b0, addr_base};
+ end
+ else
+ begin
+ // Increment counter and restart state machine to check next entry
+ counter <= counter + 1'b1;
+ state <= SM_CHECKBEGIN;
+ end
+ end
+ else
+ begin
+ ram_addr <= end_addr;
+ if (wait_timer > 1'b0)
+ begin
+ wait_timer <= wait_timer - 1'b1;
+ end
+ else
+ begin
+ // - If no match after read wait then stop check run and schedule restart of state machine
+ next_state <= SM_CHECKCANCEL;
+ state <= SM_TIMER;
+ checking_scores <= 1'b0;
+ wait_timer <= ACCESS_PAUSEPAD;
+ end
+ end
+ end
+
+ SM_CHECKCANCEL: // Cancel start/end check run - disable RAM access and keep CPU paused
+ begin
+ pause_cpu <= 1'b0;
+ next_state <= SM_INIT;
+ state <= SM_TIMER;
+ wait_timer <= CHECK_WAIT;
+ end
+
+ // Write to game RAM states
+ // ----------------------
+ SM_WRITEPREP: // Prepare to write scores - pause CPU in readiness for RAM access (only used on subsequent write attempts)
+ begin
+ state <= SM_TIMER;
+ next_state <= SM_WRITEBEGIN;
+ pause_cpu <= 1'b1;
+ wait_timer <= ACCESS_PAUSEPAD;
+ end
+
+ SM_WRITEBEGIN: // Writing scores to game RAM begins
+ begin
+ writing_scores <= 1'b1; // Enable muxes if necessary
+ write_counter <= write_counter + 1'b1;
+ state <= SM_WRITEREADY;
+ end
+
+ SM_WRITEREADY: // local ram should be correct, start write to game RAM
+ begin
+ ram_addr <= addr_base + (local_addr - base_io_addr);
+ state <= SM_TIMER;
+ next_state <= SM_WRITEDONE;
+ wait_timer <= WRITE_HOLD;
+ ram_write <= 1'b1;
+ end
+
+ SM_WRITEDONE:
+ begin
+ local_addr <= local_addr + 1'b1; // Increment to next byte of entry
+ if (ram_addr == end_addr)
+ begin
+ // End of entry reached
+ if (counter == total_entries)
+ begin
+ state <= SM_WRITECOMPLETE;
+ end
+ else
+ begin
+ // Move to next entry
+ counter <= counter + 1'b1;
+ write_counter <= 1'b0;
+ base_io_addr <= local_addr + 1'b1;
+ state <= SM_WRITEBEGIN;
+ end
+ end
+ else
+ begin
+ state <= SM_WRITEREADY;
+ end
+ ram_write <= 1'b0;
+ end
+
+ SM_WRITECOMPLETE: // Hiscore write to RAM completed
+ begin
+ ram_write <= 1'b0;
+ writing_scores <= 1'b0;
+ state <= SM_TIMER;
+ if(write_counter < WRITE_REPEATCOUNT)
+ begin
+ // Schedule next write
+ next_state <= SM_WRITERETRY;
+ local_addr <= 0;
+ wait_timer <= WRITE_REPEATWAIT;
+ end
+ else
+ begin
+ next_state <= SM_STOPPED;
+ wait_timer <= ACCESS_PAUSEPAD;
+ end
+ end
+
+ SM_WRITERETRY: // Stop pause and schedule next write
+ begin
+ pause_cpu <= 1'b0;
+ state <= SM_TIMER;
+ next_state <= SM_WRITEPREP;
+ wait_timer <= WRITE_REPEATWAIT;
+ end
+
+ SM_STOPPED:
+ begin
+ pause_cpu <= 1'b0;
+ end
+
+ SM_TIMER: // timer wait state
+ begin
+ // Do not progress timer if CPU is paused by source other than this module
+ // - Stops initial hiscore load delay being foiled by user pausing/entering OSD
+ if (paused == 1'b0 || pause_cpu == 1'b1)
+ begin
+ if (wait_timer > 1'b0)
+ wait_timer <= wait_timer - 1'b1;
+ else
+ state <= next_state;
+ end
+ end
+ endcase
+ end
+ end
+ end
+ old_io_addr<=ioctl_addr;
+end
+
+endmodule
+
+module dpram_hs #(
+ parameter dWidth=8,
+ parameter aWidth=8
+)(
+ input clk,
+
+ input [aWidth-1:0] addr_a,
+ input [dWidth-1:0] d_a,
+ input we_a,
+ output reg [dWidth-1:0] q_a,
+
+ input [aWidth-1:0] addr_b,
+ input [dWidth-1:0] d_b,
+ input we_b,
+ output reg [dWidth-1:0] q_b
+);
+
+reg [dWidth-1:0] ram [2**aWidth-1:0];
+
+always @(posedge clk) begin
+ if (we_a) begin
+ ram[addr_a] <= d_a;
+ q_a <= d_a;
+ end
+ else
+ begin
+ q_a <= ram[addr_a];
+ end
+
+ if (we_b) begin
+ ram[addr_b] <= d_b;
+ q_b <= d_b;
+ end
+ else
+ begin
+ q_b <= ram[addr_b];
+ end
+end
+
+endmodule
\ No newline at end of file
diff --git a/Arcade_MiST/Konami Jackal/rtl/jtframe_frac_cen.v b/Arcade_MiST/Konami Jackal/rtl/jtframe_frac_cen.v
new file mode 100644
index 00000000..8707e766
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/rtl/jtframe_frac_cen.v
@@ -0,0 +1,58 @@
+///////////////////////////////////////////////////////////////////////////
+// Fractional clock enable signal
+// W refers to the number of divided down cen signals available
+// each one is divided by 2
+
+module jtframe_frac_cen #(parameter W=2)(
+ input clk,
+ input [9:0] n, // numerator
+ input [9:0] m, // denominator
+ output reg [W-1:0] cen,
+ output reg [W-1:0] cenb // 180 shifted
+);
+
+wire [10:0] step={1'b0,n};
+wire [10:0] lim ={1'b0,m};
+wire [10:0] absmax = lim+step;
+
+reg [10:0] cencnt=11'd0;
+reg [10:0] next;
+reg [10:0] next2;
+
+always @(*) begin
+ next = cencnt+step;
+ next2 = next-lim;
+end
+
+reg half = 1'b0;
+wire over = next>=lim;
+wire halfway = next >= (lim>>1) && !half;
+
+reg [W-1:0] edgecnt = {W{1'b0}};
+wire [W-1:0] next_edgecnt = edgecnt + 1'b1;
+wire [W-1:0] toggle = next_edgecnt & ~edgecnt;
+
+always @(posedge clk) begin
+ cen <= {W{1'b0}};
+ cenb <= {W{1'b0}};
+
+ if( cencnt >= absmax ) begin
+ // something went wrong: restart
+ cencnt <= 11'd0;
+ end else
+ if( halfway ) begin
+ half <= 1'b1;
+ cenb[0] <= 1'b1;
+ end
+ if( over ) begin
+ cencnt <= next2;
+ half <= 1'b0;
+ edgecnt <= next_edgecnt;
+ cen <= { toggle[W-2:0], 1'b1 };
+ end else begin
+ cencnt <= next;
+ end
+end
+
+
+endmodule
\ No newline at end of file
diff --git a/Arcade_MiST/Konami Jackal/rtl/pause.v b/Arcade_MiST/Konami Jackal/rtl/pause.v
new file mode 100644
index 00000000..4f21042b
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/rtl/pause.v
@@ -0,0 +1,93 @@
+//============================================================================
+// Generic pause handling for MiSTer cores.
+//
+// https://github.com/JimmyStones/Pause_MiSTer
+//
+// Copyright (c) 2021 Jim Gregory
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//============================================================================
+/*
+ Features:
+ - Pause can be triggered by user input, hiscore module or OSD opening (optionally controlled by setting in OSD)
+ - When paused the RGB outputs will be halved after 10 seconds to reduce burn-in (optionally controlled by setting in OSD)
+ - Reset signal will cancel user triggered pause
+
+ Version history:
+ 0001 - 2021-03-15 - First marked release
+============================================================================
+*/
+module pause #(
+ parameter RW=8, // Width of red channel
+ parameter GW=8, // Width of green channel
+ parameter BW=8, // Width of blue channel
+ parameter CLKSPD = 12 // Main clock speed in MHz
+)
+(
+ input clk_sys, // Core system clock (should match HPS module)
+ input reset, // CPU reset signal (active-high)
+ input user_button, // User pause button signal (active-high)
+ input pause_request, // Pause requested by other code (active-high)
+ input [1:0] options, // Pause options from OSD
+ // [0] = pause in OSD (active-high)
+ // [1] = dim video (active-high)
+ input OSD_STATUS, // OSD is open (active-high)
+ input [(RW-1):0] r, // Red channel
+ input [(GW-1):0] g, // Green channel
+ input [(BW-1):0] b, // Blue channel
+
+ output pause_cpu, // Pause signal to CPU (active-high)
+ output [(RW+GW+BW-1):0] rgb_out // RGB output to arcade_video module
+
+);
+
+// Option constants
+localparam pause_in_osd = 1'b0;
+localparam dim_video = 1'b1;
+
+reg pause_toggle = 1'b0; // User paused (active-high)
+reg [31:0] pause_timer = 1'b0; // Time since pause
+reg [31:0] dim_timeout = (CLKSPD*10000000); // Time until video output dim (10 seconds @ CLKSPD Mhz)
+
+assign pause_cpu = (pause_request | pause_toggle | (OSD_STATUS & options[pause_in_osd])) & !reset;
+
+always @(posedge clk_sys) begin
+
+ // Track user pause button down
+ reg user_button_last;
+ user_button_last <= user_button;
+ if(!user_button_last & user_button) pause_toggle <= ~pause_toggle;
+
+ // Clear user pause on reset
+ if(pause_toggle & reset) pause_toggle <= 0;
+
+ if(pause_cpu & options[dim_video])
+ begin
+ // Track pause duration for video dim
+ if((pause_timer= dim_timeout) ? {r >> 1,g >> 1, b >> 1} : {r,g,b};
+
+endmodule
\ No newline at end of file
diff --git a/Arcade_MiST/Konami Jackal/rtl/pll.qip b/Arcade_MiST/Konami Jackal/rtl/pll.qip
new file mode 100644
index 00000000..afd958be
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/rtl/pll.qip
@@ -0,0 +1,4 @@
+set_global_assignment -name IP_TOOL_NAME "ALTPLL"
+set_global_assignment -name IP_TOOL_VERSION "13.1"
+set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"]
+set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"]
diff --git a/Arcade_MiST/Konami Jackal/rtl/pll.v b/Arcade_MiST/Konami Jackal/rtl/pll.v
new file mode 100644
index 00000000..1960b7f8
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/rtl/pll.v
@@ -0,0 +1,348 @@
+// megafunction wizard: %ALTPLL%
+// GENERATION: STANDARD
+// VERSION: WM1.0
+// MODULE: altpll
+
+// ============================================================
+// File Name: pll.v
+// Megafunction Name(s):
+// altpll
+//
+// Simulation Library Files(s):
+// altera_mf
+// ============================================================
+// ************************************************************
+// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
+//
+// 13.1.4 Build 182 03/12/2014 Patches 4.26 SJ Web Edition
+// ************************************************************
+
+
+//Copyright (C) 1991-2014 Altera Corporation
+//Your use of Altera Corporation's design tools, logic functions
+//and other software and tools, and its AMPP partner logic
+//functions, and any output files from any of the foregoing
+//(including device programming or simulation files), and any
+//associated documentation or information are expressly subject
+//to the terms and conditions of the Altera Program License
+//Subscription Agreement, Altera MegaCore Function License
+//Agreement, or other applicable license agreement, including,
+//without limitation, that your use is for the sole purpose of
+//programming logic devices manufactured by Altera and sold by
+//Altera or its authorized distributors. Please refer to the
+//applicable agreement for further details.
+
+
+// synopsys translate_off
+`timescale 1 ps / 1 ps
+// synopsys translate_on
+module pll (
+ areset,
+ inclk0,
+ c0,
+ c1,
+ locked);
+
+ input areset;
+ input inclk0;
+ output c0;
+ output c1;
+ output locked;
+`ifndef ALTERA_RESERVED_QIS
+// synopsys translate_off
+`endif
+ tri0 areset;
+`ifndef ALTERA_RESERVED_QIS
+// synopsys translate_on
+`endif
+
+ wire [4:0] sub_wire0;
+ wire sub_wire2;
+ wire [0:0] sub_wire6 = 1'h0;
+ wire [0:0] sub_wire3 = sub_wire0[0:0];
+ wire [1:1] sub_wire1 = sub_wire0[1:1];
+ wire c1 = sub_wire1;
+ wire locked = sub_wire2;
+ wire c0 = sub_wire3;
+ wire sub_wire4 = inclk0;
+ wire [1:0] sub_wire5 = {sub_wire6, sub_wire4};
+
+ altpll altpll_component (
+ .areset (areset),
+ .inclk (sub_wire5),
+ .clk (sub_wire0),
+ .locked (sub_wire2),
+ .activeclock (),
+ .clkbad (),
+ .clkena ({6{1'b1}}),
+ .clkloss (),
+ .clkswitch (1'b0),
+ .configupdate (1'b0),
+ .enable0 (),
+ .enable1 (),
+ .extclk (),
+ .extclkena ({4{1'b1}}),
+ .fbin (1'b1),
+ .fbmimicbidir (),
+ .fbout (),
+ .fref (),
+ .icdrclk (),
+ .pfdena (1'b1),
+ .phasecounterselect ({4{1'b1}}),
+ .phasedone (),
+ .phasestep (1'b1),
+ .phaseupdown (1'b1),
+ .pllena (1'b1),
+ .scanaclr (1'b0),
+ .scanclk (1'b0),
+ .scanclkena (1'b1),
+ .scandata (1'b0),
+ .scandataout (),
+ .scandone (),
+ .scanread (1'b0),
+ .scanwrite (1'b0),
+ .sclkout0 (),
+ .sclkout1 (),
+ .vcooverrange (),
+ .vcounderrange ());
+ defparam
+ altpll_component.bandwidth_type = "AUTO",
+ altpll_component.clk0_divide_by = 105,
+ altpll_component.clk0_duty_cycle = 50,
+ altpll_component.clk0_multiply_by = 382,
+ altpll_component.clk0_phase_shift = "0",
+ altpll_component.clk1_divide_by = 105,
+ altpll_component.clk1_duty_cycle = 50,
+ altpll_component.clk1_multiply_by = 191,
+ altpll_component.clk1_phase_shift = "0",
+ altpll_component.compensate_clock = "CLK0",
+ altpll_component.inclk0_input_frequency = 37037,
+ altpll_component.intended_device_family = "Cyclone III",
+ altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll",
+ altpll_component.lpm_type = "altpll",
+ altpll_component.operation_mode = "NORMAL",
+ altpll_component.pll_type = "AUTO",
+ altpll_component.port_activeclock = "PORT_UNUSED",
+ altpll_component.port_areset = "PORT_USED",
+ altpll_component.port_clkbad0 = "PORT_UNUSED",
+ altpll_component.port_clkbad1 = "PORT_UNUSED",
+ altpll_component.port_clkloss = "PORT_UNUSED",
+ altpll_component.port_clkswitch = "PORT_UNUSED",
+ altpll_component.port_configupdate = "PORT_UNUSED",
+ altpll_component.port_fbin = "PORT_UNUSED",
+ altpll_component.port_inclk0 = "PORT_USED",
+ altpll_component.port_inclk1 = "PORT_UNUSED",
+ altpll_component.port_locked = "PORT_USED",
+ altpll_component.port_pfdena = "PORT_UNUSED",
+ altpll_component.port_phasecounterselect = "PORT_UNUSED",
+ altpll_component.port_phasedone = "PORT_UNUSED",
+ altpll_component.port_phasestep = "PORT_UNUSED",
+ altpll_component.port_phaseupdown = "PORT_UNUSED",
+ altpll_component.port_pllena = "PORT_UNUSED",
+ altpll_component.port_scanaclr = "PORT_UNUSED",
+ altpll_component.port_scanclk = "PORT_UNUSED",
+ altpll_component.port_scanclkena = "PORT_UNUSED",
+ altpll_component.port_scandata = "PORT_UNUSED",
+ altpll_component.port_scandataout = "PORT_UNUSED",
+ altpll_component.port_scandone = "PORT_UNUSED",
+ altpll_component.port_scanread = "PORT_UNUSED",
+ altpll_component.port_scanwrite = "PORT_UNUSED",
+ altpll_component.port_clk0 = "PORT_USED",
+ altpll_component.port_clk1 = "PORT_USED",
+ altpll_component.port_clk2 = "PORT_UNUSED",
+ altpll_component.port_clk3 = "PORT_UNUSED",
+ altpll_component.port_clk4 = "PORT_UNUSED",
+ altpll_component.port_clk5 = "PORT_UNUSED",
+ altpll_component.port_clkena0 = "PORT_UNUSED",
+ altpll_component.port_clkena1 = "PORT_UNUSED",
+ altpll_component.port_clkena2 = "PORT_UNUSED",
+ altpll_component.port_clkena3 = "PORT_UNUSED",
+ altpll_component.port_clkena4 = "PORT_UNUSED",
+ altpll_component.port_clkena5 = "PORT_UNUSED",
+ altpll_component.port_extclk0 = "PORT_UNUSED",
+ altpll_component.port_extclk1 = "PORT_UNUSED",
+ altpll_component.port_extclk2 = "PORT_UNUSED",
+ altpll_component.port_extclk3 = "PORT_UNUSED",
+ altpll_component.self_reset_on_loss_lock = "OFF",
+ altpll_component.width_clock = 5;
+
+
+endmodule
+
+// ============================================================
+// CNX file retrieval info
+// ============================================================
+// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
+// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
+// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1"
+// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
+// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
+// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"
+// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"
+// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
+// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
+// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0"
+// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
+// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
+// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
+// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
+// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
+// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8"
+// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "105"
+// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "105"
+// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
+// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
+// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "98.228569"
+// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "49.114285"
+// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
+// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
+// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
+// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0"
+// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
+// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
+// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
+// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000"
+// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
+// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
+// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
+// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
+// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
+// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
+// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
+// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"
+// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
+// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
+// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
+// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
+// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "ps"
+// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
+// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
+// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
+// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "382"
+// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "191"
+// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
+// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "49.15200000"
+// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "14.31818000"
+// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0"
+// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0"
+// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
+// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
+// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
+// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
+// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
+// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000"
+// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
+// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
+// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg"
+// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
+// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1"
+// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
+// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
+// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
+// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
+// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
+// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
+// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
+// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
+// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif"
+// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
+// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1"
+// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
+// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
+// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
+// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
+// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
+// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
+// Retrieval info: PRIVATE: SPREAD_USE STRING "0"
+// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
+// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
+// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"
+// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
+// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
+// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
+// Retrieval info: PRIVATE: USE_CLK0 STRING "1"
+// Retrieval info: PRIVATE: USE_CLK1 STRING "1"
+// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
+// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"
+// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
+// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
+// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
+// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO"
+// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "105"
+// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
+// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "382"
+// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
+// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "105"
+// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
+// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "191"
+// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0"
+// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
+// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037"
+// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
+// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
+// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL"
+// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO"
+// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED"
+// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
+// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED"
+// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
+// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED"
+// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF"
+// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5"
+// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
+// Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset"
+// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
+// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"
+// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
+// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked"
+// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0
+// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
+// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
+// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
+// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1
+// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0
+// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE
+// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE
+// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE
+// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE
+// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE
+// Retrieval info: LIB_FILE: altera_mf
+// Retrieval info: CBX_MODULE_PREFIX: ON
diff --git a/Arcade_MiST/Konami Jackal/rtl/sdram.sv b/Arcade_MiST/Konami Jackal/rtl/sdram.sv
new file mode 100644
index 00000000..dee76185
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/rtl/sdram.sv
@@ -0,0 +1,363 @@
+//
+// sdram.v
+//
+// sdram controller implementation for the MiST board
+// https://github.com/mist-devel/mist-board
+//
+// Copyright (c) 2013 Till Harbaum
+// Copyright (c) 2019 Gyorgy Szombathelyi
+//
+// This source file is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This source file is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+
+module sdram (
+
+ // interface to the MT48LC16M16 chip
+ inout reg [15:0] SDRAM_DQ, // 16 bit bidirectional data bus
+ output reg [12:0] SDRAM_A, // 13 bit multiplexed address bus
+ output reg SDRAM_DQML, // two byte masks
+ output reg SDRAM_DQMH, // two byte masks
+ output reg [1:0] SDRAM_BA, // two banks
+ output SDRAM_nCS, // a single chip select
+ output SDRAM_nWE, // write enable
+ output SDRAM_nRAS, // row address select
+ output SDRAM_nCAS, // columns address select
+
+ // cpu/chipset interface
+ input init_n, // init signal after FPGA config to initialize RAM
+ input clk, // sdram clock
+
+ input port1_req,
+ output reg port1_ack,
+ input port1_we,
+ input [23:1] port1_a,
+ input [1:0] port1_ds,
+ input [15:0] port1_d,
+ output reg [15:0] port1_q,
+
+ input [16:1] cpu1_addr,
+ output reg [15:0] cpu1_q,
+ input [16:1] cpu2_addr,
+ output reg [15:0] cpu2_q,
+
+ input port2_req,
+ output reg port2_ack,
+ input port2_we,
+ input [23:1] port2_a,
+ input [1:0] port2_ds,
+ input [15:0] port2_d,
+ output reg [15:0] port2_q,
+ input [16:1] ch1_addr,
+ output reg [15:0] ch1_q,
+ input [16:1] ch2_addr,
+ output reg [15:0] ch2_q,
+ input sp1_req,
+ input [16:1] sp1_addr,
+ output reg [15:0] sp1_q,
+ output reg sp1_ack,
+ input sp2_req,
+ input [16:1] sp2_addr,
+ output reg [15:0] sp2_q,
+ output reg sp2_ack
+);
+
+parameter MHZ = 16'd80; // 80 MHz default clock, set it to proper value to calculate refresh rate
+
+localparam RASCAS_DELAY = 3'd2; // tRCD=20ns -> 2 cycles@<100MHz
+localparam BURST_LENGTH = 3'b000; // 000=1, 001=2, 010=4, 011=8
+localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved
+localparam CAS_LATENCY = 3'd2; // 2/3 allowed
+localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed
+localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write
+
+localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH};
+
+// 64ms/8192 rows = 7.8us
+localparam RFRSH_CYCLES = 16'd78*MHZ/4'd10;
+
+// ---------------------------------------------------------------------
+// ------------------------ cycle state machine ------------------------
+// ---------------------------------------------------------------------
+
+/*
+ SDRAM state machine for 2 bank interleaved access
+ 1 word burst, CL2
+cmd issued registered
+ 0 RAS0 cas1
+ 1 ras0
+ 2 data1 returned
+ 3 CAS0
+ 4 RAS1 cas0
+ 5 ras1
+ 6 CAS1 data0 returned
+*/
+
+localparam STATE_RAS0 = 3'd0; // first state in cycle
+localparam STATE_RAS1 = 3'd4; // Second ACTIVE command after RAS0 + tRRD (15ns)
+localparam STATE_CAS0 = STATE_RAS0 + RASCAS_DELAY + 1'd1; // CAS phase - 3
+localparam STATE_CAS1 = STATE_RAS1 + RASCAS_DELAY; // CAS phase - 6
+localparam STATE_READ0 = 3'd0;// STATE_CAS0 + CAS_LATENCY + 2'd2; // 7
+localparam STATE_READ1 = 3'd3;
+localparam STATE_LAST = 3'd6;
+
+reg [2:0] t;
+
+always @(posedge clk) begin
+ t <= t + 1'd1;
+ if (t == STATE_LAST) t <= STATE_RAS0;
+end
+
+// ---------------------------------------------------------------------
+// --------------------------- startup/reset ---------------------------
+// ---------------------------------------------------------------------
+
+// wait 1ms (32 8Mhz cycles) after FPGA config is done before going
+// into normal operation. Initialize the ram in the last 16 reset cycles (cycles 15-0)
+reg [4:0] reset;
+reg init = 1'b1;
+always @(posedge clk, negedge init_n) begin
+ if(!init_n) begin
+ reset <= 5'h1f;
+ init <= 1'b1;
+ end else begin
+ if((t == STATE_LAST) && (reset != 0)) reset <= reset - 5'd1;
+ init <= !(reset == 0);
+ end
+end
+
+// ---------------------------------------------------------------------
+// ------------------ generate ram control signals ---------------------
+// ---------------------------------------------------------------------
+
+// all possible commands
+localparam CMD_INHIBIT = 4'b1111;
+localparam CMD_NOP = 4'b0111;
+localparam CMD_ACTIVE = 4'b0011;
+localparam CMD_READ = 4'b0101;
+localparam CMD_WRITE = 4'b0100;
+localparam CMD_BURST_TERMINATE = 4'b0110;
+localparam CMD_PRECHARGE = 4'b0010;
+localparam CMD_AUTO_REFRESH = 4'b0001;
+localparam CMD_LOAD_MODE = 4'b0000;
+
+reg [3:0] sd_cmd; // current command sent to sd ram
+reg [15:0] sd_din;
+// drive control signals according to current command
+assign SDRAM_nCS = sd_cmd[3];
+assign SDRAM_nRAS = sd_cmd[2];
+assign SDRAM_nCAS = sd_cmd[1];
+assign SDRAM_nWE = sd_cmd[0];
+
+reg [24:1] addr_latch[2];
+reg [24:1] addr_latch_next[2];
+reg [16:1] addr_last[6];
+reg [16:1] addr_last2[6];
+reg [15:0] din_latch[2];
+reg [1:0] oe_latch;
+reg [1:0] we_latch;
+reg [1:0] ds[2];
+
+reg port1_state;
+reg port2_state;
+
+localparam PORT_NONE = 3'd0;
+localparam PORT_CPU1 = 3'd1;
+localparam PORT_CPU2 = 3'd2;
+localparam PORT_CH1 = 3'd1;
+localparam PORT_CH2 = 3'd2;
+localparam PORT_SP1 = 3'd3;
+localparam PORT_SP2 = 3'd4;
+localparam PORT_REQ = 3'd5;
+
+reg [2:0] next_port[2];
+reg [2:0] port[2];
+
+reg refresh;
+reg [10:0] refresh_cnt;
+wire need_refresh = (refresh_cnt >= RFRSH_CYCLES);
+
+// PORT1: bank 0,1
+always @(*) begin
+ if (refresh) begin
+ next_port[0] = PORT_NONE;
+ addr_latch_next[0] = addr_latch[0];
+ end else if (port1_req ^ port1_state) begin
+ next_port[0] = PORT_REQ;
+ addr_latch_next[0] = { 1'b0, port1_a };
+ end else if (cpu1_addr != addr_last[PORT_CPU1]) begin
+ next_port[0] = PORT_CPU1;
+ addr_latch_next[0] = { 8'd0, cpu1_addr };
+ end else if (cpu2_addr != addr_last[PORT_CPU2]) begin
+ next_port[0] = PORT_CPU2;
+ addr_latch_next[0] = { 8'd0, cpu2_addr };
+ end else begin
+ next_port[0] = PORT_NONE;
+ addr_latch_next[0] = addr_latch[0];
+ end
+end
+
+// PORT1: bank 2,3
+always @(*) begin
+ if (port2_req ^ port2_state) begin
+ next_port[1] = PORT_REQ;
+ addr_latch_next[1] = { 1'b1, port2_a };
+ end else if (ch1_addr != addr_last2[PORT_CH1]) begin
+ next_port[1] = PORT_CH1;
+ addr_latch_next[1] = { 1'b1, 5'd0, 2'b00, ch1_addr };
+ end else if (ch2_addr != addr_last2[PORT_CH2]) begin
+ next_port[1] = PORT_CH2;
+ addr_latch_next[1] = { 1'b1, 5'd0, 2'b10, ch2_addr };
+ end else if (sp1_req != sp1_ack) begin
+ next_port[1] = PORT_SP1;
+ addr_latch_next[1] = { 1'b1, 5'd0, 2'b01, sp1_addr };
+ end else if (sp2_req != sp2_ack) begin
+ next_port[1] = PORT_SP2;
+ addr_latch_next[1] = { 1'b1, 5'd0, 2'b11, sp2_addr };
+ end else begin
+ next_port[1] = PORT_NONE;
+ addr_latch_next[1] = addr_latch[1];
+ end
+end
+
+always @(posedge clk) begin
+
+ // permanently latch ram data to reduce delays
+ sd_din <= SDRAM_DQ;
+ SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ;
+ { SDRAM_DQMH, SDRAM_DQML } <= 2'b11;
+ sd_cmd <= CMD_NOP; // default: idle
+ refresh_cnt <= refresh_cnt + 1'd1;
+
+ if(init) begin
+ // initialization takes place at the end of the reset phase
+ if(t == STATE_RAS0) begin
+
+ if(reset == 15) begin
+ sd_cmd <= CMD_PRECHARGE;
+ SDRAM_A[10] <= 1'b1; // precharge all banks
+ end
+
+ if(reset == 10 || reset == 8) begin
+ sd_cmd <= CMD_AUTO_REFRESH;
+ end
+
+ if(reset == 2) begin
+ sd_cmd <= CMD_LOAD_MODE;
+ SDRAM_A <= MODE;
+ SDRAM_BA <= 2'b00;
+ end
+ end
+ end else begin
+ // RAS phase
+ // bank 0,1
+ if(t == STATE_RAS0) begin
+ addr_latch[0] <= addr_latch_next[0];
+ port[0] <= next_port[0];
+ { oe_latch[0], we_latch[0] } <= 2'b00;
+
+ if (next_port[0] != PORT_NONE) begin
+ sd_cmd <= CMD_ACTIVE;
+ SDRAM_A <= addr_latch_next[0][22:10];
+ SDRAM_BA <= addr_latch_next[0][24:23];
+ addr_last[next_port[0]] <= addr_latch_next[0][16:1];
+ if (next_port[0] == PORT_REQ) begin
+ { oe_latch[0], we_latch[0] } <= { ~port1_we, port1_we };
+ ds[0] <= port1_ds;
+ din_latch[0] <= port1_d;
+ port1_state <= port1_req;
+ end else begin
+ { oe_latch[0], we_latch[0] } <= 2'b10;
+ ds[0] <= 2'b11;
+ end
+ end
+ end
+
+ // bank 2,3
+ if(t == STATE_RAS1) begin
+ refresh <= 1'b0;
+ addr_latch[1] <= addr_latch_next[1];
+ { oe_latch[1], we_latch[1] } <= 2'b00;
+ port[1] <= next_port[1];
+
+ if (next_port[1] != PORT_NONE) begin
+ sd_cmd <= CMD_ACTIVE;
+ SDRAM_A <= addr_latch_next[1][22:10];
+ SDRAM_BA <= addr_latch_next[1][24:23];
+ addr_last2[next_port[1]] <= addr_latch_next[1][16:1];
+ if (next_port[1] == PORT_REQ) begin
+ { oe_latch[1], we_latch[1] } <= { ~port1_we, port1_we };
+ ds[1] <= port2_ds;
+ din_latch[1] <= port2_d;
+ port2_state <= port2_req;
+ end else begin
+ { oe_latch[1], we_latch[1] } <= 2'b10;
+ ds[1] <= 2'b11;
+ end
+ end
+
+ if (next_port[1] == PORT_NONE && need_refresh && !we_latch[0] && !oe_latch[0]) begin
+ refresh <= 1'b1;
+ refresh_cnt <= 0;
+ sd_cmd <= CMD_AUTO_REFRESH;
+ end
+ end
+
+ // CAS phase
+ if(t == STATE_CAS0 && (we_latch[0] || oe_latch[0])) begin
+ sd_cmd <= we_latch[0]?CMD_WRITE:CMD_READ;
+ { SDRAM_DQMH, SDRAM_DQML } <= ~ds[0];
+ if (we_latch[0]) begin
+ SDRAM_DQ <= din_latch[0];
+ port1_ack <= port1_req;
+ end
+ SDRAM_A <= { 4'b0010, addr_latch[0][9:1] }; // auto precharge
+ SDRAM_BA <= addr_latch[0][24:23];
+ end
+
+ if(t == STATE_CAS1 && (we_latch[1] || oe_latch[1])) begin
+ sd_cmd <= we_latch[1]?CMD_WRITE:CMD_READ;
+ { SDRAM_DQMH, SDRAM_DQML } <= ~ds[1];
+ if (we_latch[1]) begin
+ SDRAM_DQ <= din_latch[1];
+ port2_ack <= port2_req;
+ end
+ SDRAM_A <= { 4'b0010, addr_latch[1][9:1] }; // auto precharge
+ SDRAM_BA <= addr_latch[1][24:23];
+ end
+
+ // Data returned
+ if(t == STATE_READ0 && oe_latch[0]) begin
+ case(port[0])
+ PORT_REQ: begin port1_q <= sd_din; port1_ack <= port1_req; end
+ PORT_CPU1: begin cpu1_q <= sd_din; end
+ PORT_CPU2: begin cpu2_q <= sd_din; end
+ default: ;
+ endcase;
+ end
+
+ if(t == STATE_READ1 && oe_latch[1]) begin
+ case(port[1])
+ PORT_REQ: begin port2_q <= sd_din; port2_ack <= port2_req; end
+ PORT_CH1 : ch1_q <= sd_din;
+ PORT_CH2 : ch2_q <= sd_din;
+ PORT_SP1 : begin sp1_q <= sd_din; sp1_ack <= sp1_req; end
+ PORT_SP2 : begin sp2_q <= sd_din; sp2_ack <= sp2_req; end
+ default: ;
+ endcase;
+ end
+
+ end
+end
+
+endmodule
diff --git a/Arcade_MiST/Konami Jackal/rtl/sound/Filter/audio_iir_filter.v b/Arcade_MiST/Konami Jackal/rtl/sound/Filter/audio_iir_filter.v
new file mode 100644
index 00000000..ad324f04
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/rtl/sound/Filter/audio_iir_filter.v
@@ -0,0 +1,173 @@
+/*MIT License
+
+Copyright (c) 2019 Gregory Hogan (Soltan_G42)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.*/
+
+module iir_1st_order
+#(
+ parameter COEFF_WIDTH = 18,
+ parameter COEFF_SCALE = 15,
+ parameter DATA_WIDTH = 16,
+ parameter COUNT_BITS = 10
+)
+(
+ input clk,
+ input reset,
+ input [COUNT_BITS - 1 : 0] div,
+ input signed [COEFF_WIDTH - 1 : 0] A2, B1, B2,
+ input signed [DATA_WIDTH - 1 :0] in,
+ output [DATA_WIDTH - 1:0] out
+);
+
+ reg signed [DATA_WIDTH-1:0] x0,x1,y0;
+ reg signed [DATA_WIDTH + COEFF_WIDTH - 1 : 0] out32;
+ reg [COUNT_BITS - 1:0] count;
+
+ // Usage:
+ // Design your 1st order iir low/high-pass with a tool that will give you the
+ // filter coefficients for the difference equation. Filter coefficients can
+ // be generated in Octave/matlab/scipy using a command similar to
+ // [B, A] = butter( 1, 3500/(106528/2), 'low') for a 3500 hz 1st order low-pass
+ // assuming 106528Hz sample rate.
+ //
+ // The Matlab output is:
+ // B = [0.093863 0.093863]
+ // A = [1.00000 -0.81227]
+ //
+ // Then scale coefficients by multiplying by 2^COEFF_SCALE and round to nearest integer
+ //
+ // B = [3076 3076]
+ // A = [32768 -26616]
+ //
+ // Discard A(1) because it is assumed 1.0 before scaling
+ //
+ // This leaves you with A2 = -26616 , B1 = 3076 , B2 = 3076
+ // B1 + B2 - A2 should sum to 2^COEFF_SCALE = 32768
+ //
+ // Sample frequency is "clk rate/div": for Genesis this is 53.69mhz/504 = 106528hz
+ //
+ // COEFF_WIDTH must be at least COEFF_SCALE+1 and must be large enough to
+ // handle temporary overflow during this computation: out32 <= (B1*x0 + B2*x1) - A2*y0
+
+ assign out = y0;
+
+ always @ (*) begin
+ out32 <= (B1*x0 + B2*x1) - A2*y0; //Previous output is y0 not y1
+ end
+
+ always @ (posedge clk) begin
+ if(reset) begin
+ count <= 0;
+ x0 <= 0;
+ x1 <= 0;
+ y0 <= 0;
+ end
+ else begin
+ count <= count + 1'd1;
+ if (count == div - 1) begin
+ count <= 0;
+ y0 <= {out32[DATA_WIDTH + COEFF_WIDTH - 1] , out32[COEFF_SCALE + DATA_WIDTH - 2 : COEFF_SCALE]};
+ x1 <= x0;
+ x0 <= in;
+ end
+ end
+ end
+
+endmodule //iir_1st_order
+
+module iir_2nd_order
+#(
+ parameter COEFF_WIDTH = 18,
+ parameter COEFF_SCALE = 14,
+ parameter DATA_WIDTH = 16,
+ parameter COUNT_BITS = 10
+)
+(
+ input clk,
+ input reset,
+ input [COUNT_BITS - 1 : 0] div,
+ input signed [COEFF_WIDTH - 1 : 0] A2, A3, B1, B2, B3,
+ input signed [DATA_WIDTH - 1 : 0] in,
+ output [DATA_WIDTH - 1 : 0] out
+);
+
+ reg signed [DATA_WIDTH-1 : 0] x0,x1,x2;
+ reg signed [DATA_WIDTH-1 : 0] y0,y1;
+ reg signed [(DATA_WIDTH + COEFF_WIDTH - 1) : 0] out32;
+ reg [COUNT_BITS : 0] count;
+
+
+ // Usage:
+ // Design your 1st order iir low/high-pass with a tool that will give you the
+ // filter coefficients for the difference equation. Filter coefficients can
+ // be generated in Octave/matlab/scipy using a command similar to
+ // [B, A] = butter( 2, 5000/(48000/2), 'low') for a 5000 hz 2nd order low-pass
+ // assuming 48000Hz sample rate.
+ //
+ // Output is:
+ // B = [ 0.072231 0.144462 0.072231]
+ // A = [1.00000 -1.10923 0.39815]
+ //
+ // Then scale coefficients by multiplying by 2^COEFF_SCALE and round to nearest integer
+ // Make sure your coefficients can be stored as a signed number with COEFF_WIDTH bits.
+ //
+ // B = [1183 2367 1183]
+ // A = [16384 -18174 6523]
+ //
+ // Discard A(1) because it is assumed 1.0 before scaling
+ //
+ // This leaves you with A2 = -18174 , A3 = 6523, B1 = 1183 , B2 = 2367 , B3 = 1183
+ // B1 + B2 + B3 - A2 - A3 should sum to 2^COEFF_SCALE = 16384
+ //
+ // Sample frequency is "clk rate/div"
+ //
+ // COEFF_WIDTH must be at least COEFF_SCALE+1 and must be large enough to
+ // handle temporary overflow during this computation:
+ // out32 <= (B1*x0 + B2*x1 + B3*x2) - (A2*y0 + A3*y1);
+
+ assign out = y0;
+
+ always @ (*) begin
+ out32 <= (B1*x0 + B2*x1 + B3*x2) - (A2*y0 + A3*y1); //Previous output is y0 not y1
+ end
+
+ always @ (posedge clk) begin
+ if(reset) begin
+ count <= 0;
+ x0 <= 0;
+ x1 <= 0;
+ x2 <= 0;
+ y0 <= 0;
+ y1 <= 0;
+ end
+ else begin
+ count <= count + 1'd1;
+ if (count == div - 1) begin
+ count <= 0;
+ y1 <= y0;
+ y0 <= {out32[DATA_WIDTH + COEFF_WIDTH - 1] , out32[(DATA_WIDTH + COEFF_SCALE - 2) : COEFF_SCALE]};
+ x2 <= x1;
+ x1 <= x0;
+ x0 <= in;
+ end
+ end
+ end
+
+endmodule //iir_2nd_order
\ No newline at end of file
diff --git a/Arcade_MiST/Konami Jackal/rtl/sound/Filter/jackal_lpf.sv b/Arcade_MiST/Konami Jackal/rtl/sound/Filter/jackal_lpf.sv
new file mode 100644
index 00000000..b9f5c51d
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/rtl/sound/Filter/jackal_lpf.sv
@@ -0,0 +1,81 @@
+/*MIT License
+
+Copyright (c) 2019 Gregory Hogan (Soltan_G42)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.*/
+
+//This is a variation of Gregory Hogan's MISTer Genesis core low-pass filter
+//tuned to low-pass filter the YM2151 on Jackal.
+
+module jackal_lpf(
+ input clk,
+ input reset,
+ input select,
+ input signed [15:0] in1,
+ input signed [15:0] in2,
+ output signed [15:0] out);
+
+ localparam div = 10'd64; //Sample at 49.152MHz/64 = 768000Hz
+
+ //Coefficients computed with Octave/Matlab/Online filter calculators.
+ //or with scipy.signal.bessel or similar tools
+
+ //0.015398864, 0.015398864
+ //1.0000000, -0.96920227
+ reg signed [17:0] lpf1_A2;
+ reg signed [17:0] lpf1_B2;
+ reg signed [17:0] lpf1_B1;
+
+ //0.018668513, 0.018668513
+ //1.0000000, -0.96266297
+ reg signed [17:0] lpf2_A2;
+ reg signed [17:0] lpf2_B2;
+ reg signed [17:0] lpf2_B1;
+
+ wire signed [15:0] audio_pre_lpf1 = select ? in1 : in2;
+ wire signed [15:0] audio_post_lpf1, audio_post_lpf2;
+
+ always @ (*) begin
+ lpf1_A2 = -18'd31758;
+ lpf1_B1 = 18'd505;
+ lpf1_B2 = 18'd505;
+ lpf2_A2 = -18'd31544;
+ lpf2_B1 = 18'd612;
+ lpf2_B2 = 18'd612;
+ end
+
+ iir_1st_order lpf1_6db(.clk(clk),
+ .reset(reset),
+ .div(div),
+ .A2(lpf1_A2),
+ .B1(lpf1_B1),
+ .B2(lpf1_B2),
+ .in(audio_pre_lpf1),
+ .out(audio_post_lpf1));
+
+ iir_1st_order lpf2_6db(.clk(clk),
+ .reset(reset),
+ .div(div),
+ .A2(lpf2_A2),
+ .B1(lpf2_B1),
+ .B2(lpf2_B2),
+ .in(audio_post_lpf1),
+ .out(audio_post_lpf2));
+
+ assign out = select ? audio_post_lpf1 : audio_post_lpf2;
+
+endmodule
diff --git a/Arcade_MiST/Konami Jackal/rtl/sound/Filter/jt49_dcrm2.v b/Arcade_MiST/Konami Jackal/rtl/sound/Filter/jt49_dcrm2.v
new file mode 100644
index 00000000..4b434aec
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/rtl/sound/Filter/jt49_dcrm2.v
@@ -0,0 +1,62 @@
+/* This file is part of JT49.
+
+ JT49 is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ JT49 is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with JT49. If not, see .
+
+ Author: Jose Tejada Gomez. Twitter: @topapate
+ Version: 1.0
+ Date: 15-Jan-2019
+
+ */
+
+// DC removal filter
+// input is unsigned
+// output is signed
+
+module jt49_dcrm2 #(parameter sw=8) (
+ input clk,
+ input cen,
+ input rst,
+ input [sw-1:0] din,
+ output signed [sw-1:0] dout
+);
+
+localparam dw=10; // widht of the decimal portion
+
+reg signed [sw+dw:0] integ, exact, error;
+//reg signed [2*(9+dw)-1:0] mult;
+// wire signed [sw+dw:0] plus1 = { {sw+dw{1'b0}},1'b1};
+reg signed [sw:0] pre_dout;
+// reg signed [sw+dw:0] dout_ext;
+reg signed [sw:0] q;
+
+always @(*) begin
+ exact = integ+error;
+ q = exact[sw+dw:dw];
+ pre_dout = { 1'b0, din } - q;
+ //dout_ext = { pre_dout, {dw{1'b0}} };
+ //mult = dout_ext;
+end
+
+assign dout = pre_dout[sw-1:0];
+
+always @(posedge clk)
+ if( rst ) begin
+ integ <= {sw+dw+1{1'b0}};
+ error <= {sw+dw+1{1'b0}};
+ end else if( cen ) begin
+ integ <= integ + pre_dout; //mult[sw+dw*2:dw];
+ error <= exact-{q, {dw{1'b0}}};
+ end
+
+endmodule
\ No newline at end of file
diff --git a/Arcade_MiST/Konami Jackal/rtl/sound/jackal_sound.qip b/Arcade_MiST/Konami Jackal/rtl/sound/jackal_sound.qip
new file mode 100644
index 00000000..a2786f02
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/rtl/sound/jackal_sound.qip
@@ -0,0 +1,3 @@
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/sound/Filter/jackal_lpf.sv
+set_global_assignment -name VERILOG_FILE rtl/sound/Filter/jt49_dcrm2.v
+set_global_assignment -name VERILOG_FILE rtl/sound/Filter/audio_iir_filter.v
diff --git a/Arcade_MiST/Konami Jackal/rtl/spram.vhd b/Arcade_MiST/Konami Jackal/rtl/spram.vhd
new file mode 100644
index 00000000..38302277
--- /dev/null
+++ b/Arcade_MiST/Konami Jackal/rtl/spram.vhd
@@ -0,0 +1,46 @@
+library ieee;
+use IEEE.std_logic_1164.all;
+use IEEE.std_logic_unsigned.ALL;
+use IEEE.numeric_std.all;
+
+entity spram is
+
+ generic
+ (
+ DATA_WIDTH : natural := 8;
+ ADDR_WIDTH : natural := 10
+ );
+
+ port
+ (
+ clk : in std_logic;
+ addr : in std_logic_vector((ADDR_WIDTH - 1) downto 0);
+ data : in std_logic_vector((DATA_WIDTH - 1) downto 0);
+ q : out std_logic_vector((DATA_WIDTH - 1) downto 0);
+ we : in std_logic := '0'
+ );
+
+end spram;
+
+architecture rtl of spram is
+
+ subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0);
+ type memory_t is array(2**ADDR_WIDTH-1 downto 0) of word_t;
+
+ shared variable ram : memory_t;
+
+begin
+
+ process(clk)
+ begin
+ if(rising_edge(clk)) then
+ if(we = '1') then
+ ram(to_integer(unsigned(addr))) := data;
+ q <= data;
+ else
+ q <= ram(to_integer(unsigned(addr)));
+ end if;
+ end if;
+ end process;
+
+end rtl;
diff --git a/common/CPU/MC6809/mc6809is.v b/common/CPU/MC6809/mc6809is.v
index d0d2086e..fdb860e6 100644
--- a/common/CPU/MC6809/mc6809is.v
+++ b/common/CPU/MC6809/mc6809is.v
@@ -535,13 +535,12 @@ endgenerate
///////////////////////////////////////////////////////////////////////
-always @(posedge CLK)
+always @(posedge CLK or posedge wNMIClear)
begin
- reg old_sample;
- old_sample <= NMISample2;
-
- if (wNMIClear == 1) NMILatched <= 1;
- else if(old_sample & ~NMISample2) NMILatched <= NMIMask;
+ if (wNMIClear == 1)
+ NMILatched <= 1;
+ else if (fallE_en && ~NMISample & NMISample2) // falling edge of NMISample2
+ NMILatched <= NMIMask;
end
//