diff --git a/cores/arbalest/cfg/files.yaml b/cores/arbalest/cfg/files.yaml new file mode 100644 index 000000000..5b68969ab --- /dev/null +++ b/cores/arbalest/cfg/files.yaml @@ -0,0 +1,35 @@ +arbalest: + - get: [ "*.v" ] +cal50: + - get: + - jtcal50_video.v + - jtcal50_colmix.v + - jtx1012.v +kiwi: + - get: + - jtkiwi_gfx.v + - jtkiwi_obj.v + - jtkiwi_draw.v + - jtkiwi_tilemap.v +jtframe: + - get: + - jtframe_ff.v + - jtframe_8bit_reg.v + - jtframe_edge.v + - from: ram + get: + - jtframe_ram.v + - jtframe_dual_ram16.v + - jtframe_obj_buffer.v + - jtframe_prom.v + - from: video + get: + - jtframe_vtimer.v + - jtframe_scroll.yaml + - from: cpu + get: + - jtframe_m68k.yaml +jt680x: + - get: + - jt65c02.yaml # I/O / protection sub-CPU (not sound, unlike cal50) +jtx1010: # X1-010 PCM — driven by the main 68000 here diff --git a/cores/arbalest/cfg/macros.def b/cores/arbalest/cfg/macros.def new file mode 100644 index 000000000..1a5f230b0 --- /dev/null +++ b/cores/arbalest/cfg/macros.def @@ -0,0 +1,33 @@ +CORENAME=JTARBALEST +JTFRAME_RATE=57.45 + +JTFRAME_JOY_RLDU +JTFRAME_BUTTONS=2 + +# Video +JTFRAME_COLORW=5 +JTFRAME_PXLCLK=8 +JTFRAME_WIDTH=384 +JTFRAME_HEIGHT=224 +JTFRAME_VERTICAL + +# MRA +# Header byte 0 selects the game (0=metafox, 1=arbalest) for the shared bitstream +JTFRAME_HEADER=16 +JTFRAME_BA1_START=0xA0000 +PCM_START=0xE0000 +JTFRAME_BA2_START=0x1E0000 +JTFRAME_BA3_START=0x3E0000 + +# Saves video RAM for debug compilations +debug JTFRAME_IOCTL_RD+=12288 +debug JTFRAME_IOCTL_RD+=8 +# X1-001 configuration registers +debug JTFRAME_IOCTL_RD+=4 +debug JTFRAME_IOCTL_RD+=1024 +debug JTFRAME_IOCTL_RD+=1024 +debug JTFRAME_IOCTL_RD+=8192 + +[mist|sidi] +# not enough BRAM for M68K RAM +JTFRAME_SKIP diff --git a/cores/arbalest/cfg/mame2mra.toml b/cores/arbalest/cfg/mame2mra.toml new file mode 100644 index 000000000..6681550a2 --- /dev/null +++ b/cores/arbalest/cfg/mame2mra.toml @@ -0,0 +1,46 @@ +[global] +author=["jotego"] + +[parse] +sourcefile=[ "downtown.cpp" ] +# This core ships the metafox-class members of downtown.cpp (sub = I/O CPU, +# X1-010 on the main 68000 bus). calibr50 is the cal50 core; the others differ. +skip.Machines=[ + "tndrcade","tndrcadej", + "twineagl","twineagl1", + "downtown","downtown2","downtownj","downtownp", + "usclssic", + "calibr50", +] + +[header] +info="""Seta downtown.cpp (metafox-class) family header, decoded in jtarbalest_game.v. + byte 0 = game_id (0=metafox, 1=arbalest). Bytes 1..15 reserved.""" +data=[ + { setnames=["metafox"], data="00" }, + { setnames=["arbalest"], data="01" }, +] + +[buttons] +names = [ + { names="Shot,Bomb" }, +] + +[dipsw] +delete= [ + { names=["Copyright / License", "Licensed To", "Licensor Option", "Coinage Type"] }, +] + +[ROM] +regions = [ + { name="maincpu", width=16, reverse=true, no_offset=true }, + + { name="sub", start="JTFRAME_BA1_START", no_offset=true }, + { name="x1snd", start="PCM_START" }, + + { name="tiles", width=16, start="JTFRAME_BA2_START", no_offset=true }, + { name="sprites", width=32, start="JTFRAME_BA3_START", no_offset=true }, + { name="proms", skip=true } +] + +order=["maincpu","sub","x1snd","tiles","sprites"] diff --git a/cores/arbalest/cfg/mem.yaml b/cores/arbalest/cfg/mem.yaml new file mode 100644 index 000000000..b96932c6f --- /dev/null +++ b/cores/arbalest/cfg/mem.yaml @@ -0,0 +1,116 @@ +params: + - { name: PCM_OFFSET, value: "(`PCM_START-`JTFRAME_BA1_START)>>1" } +clocks: + clk48: + - freq: 8 MHz + gate: [ snd ] + outputs: + - cen8 + - freq: 16 MHz + outputs: + - cen_pcm +audio: + mute: true + channels: + # Same dual 4k/8k anti-alias filtering as cal50 (X1-010 left/right mono mix) + - { name: pcm_4k, data_width: 16, rsum: 47k, fir: fir_192k_4k.csv } + - { name: pcm_8k, data_width: 16, rsum: 47k, fir: fir_192k_8k.csv } +sdram: + banks: + - buses: + - name: main + addr_width: 20 + data_width: 16 + - buses: + - name: snd # 65C02 I/O sub-CPU program ROM (region "sub") + addr_width: 18 + data_width: 8 + - name: pcm # X1-010 samples (region "x1snd") + addr_width: 20 + data_width: 8 + offset: PCM_OFFSET + - buses: + - name: tile + addr_width: 21 + data_width: 32 + gfx_sort: hvvvx + - buses: + - name: scr + addr_width: 21 + data_width: 32 + - name: obj + addr_width: 21 + data_width: 32 +bram: + - name: ram # M68K work RAM (0xf00000-) + addr_width: 16 + data_width: 16 + din: cpu_dout + rw: true + # Shared RAM between the main 68000 (0xb00000, byte) and the I/O 65C02 (0x5000) + - name: shram + addr_width: 11 + data_width: 8 + din: cpu_dout[7:0] + addr: main_addr[11:1] + rw: true + dual_port: + name: subsh + din: subsh_din + dout: subsh_dout + rw: true + we: subsh_we + # X1-012 Video RAM + - name: tlv + addr_width: 14 + data_width: 16 + din: cpu_dout + addr: main_addr[13:1] + rw: true + ioctl: + save: true + order: 0 + unless: [ JTFRAME_RELEASE ] + dual_port: + name: tlrd + dout: tlrd_data + # Palette RAM + - name: pal + addr_width: 10 + data_width: 16 + din: cpu_dout + addr: main_addr[9:1] + rw: true + ioctl: + save: true + order: 1 + unless: [ JTFRAME_RELEASE ] + dual_port: + name: palrd + dout: pal_data + # X1-001 internal RAM + - name: yram + addr_width: 10 + data_width: 8 + din: cpu_dout[7:0] + addr: main_addr[10:1] + rw: true + ioctl: + save: true + order: 2 + unless: [ JTFRAME_RELEASE ] + dual_port: + name: col + dout: col_data + # X1-001 external video RAM. metafox is 16 KB (0xe00000-0xe03fff): two 8 KB sprite buffers + - name: dma + addr_width: 14 + data_width: 16 + rw: true + ioctl: + save: true + order: 3 + unless: [ JTFRAME_RELEASE ] + dual_port: + name: code + dout: code_dout diff --git a/cores/arbalest/cfg/mmr.yaml b/cores/arbalest/cfg/mmr.yaml new file mode 100644 index 000000000..b23d8867c --- /dev/null +++ b/cores/arbalest/cfg/mmr.yaml @@ -0,0 +1,15 @@ +- name: x1012 + no_core_name: true + size: 8 + dw: 16 + regs: + - name: hpos + dw: 16 + at: "1,0" + - name: vpos + dw: 16 + at: "3,2" + # vctrl[2]: bit3 (0x08)=tilemap bank (vram 0 / 0x1000), bit4 (0x10)=color/gfx mode (MAME x1_012.cpp) + - name: bank + dw: 1 + at: "4[3]" diff --git a/cores/arbalest/cfg/msg b/cores/arbalest/cfg/msg new file mode 100644 index 000000000..c5f8e0bcf --- /dev/null +++ b/cores/arbalest/cfg/msg @@ -0,0 +1,7 @@ +\BArbalester - Metafox\W FPGA core + + by \GAndr\Wea Bog\Razzi\W + on the \RJTCORES\W framework + by JOTEGO + community + + Reviewed by Jose Tejada \ No newline at end of file diff --git a/cores/arbalest/hdl/jtarbalest_game.v b/cores/arbalest/hdl/jtarbalest_game.v new file mode 100644 index 000000000..262d5c18d --- /dev/null +++ b/cores/arbalest/hdl/jtarbalest_game.v @@ -0,0 +1,230 @@ +/* This file is part of JTCORES. + JTCORES 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. + + JTCORES 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 JTCORES. If not, see . + + Author: Andrea Bogazzi. andreabogazzi79@gmail.com + Version: 1.0 + Date: 17-06-2026 */ + +// Seta downtown.cpp (metafox-class) top. +// Reuses the cal50 video pipeline (jtcal50_video = single X1-012 layer + X1-001 +// sprites + direct xRGB-555 colmix) IMPORTED via cfg/files.yaml. Only the bus +// topology differs, so main/sub/sound are local to this core. +module jtarbalest_game( + `include "jtframe_game_ports.inc" // see $JTFRAME/hdl/inc/jtframe_game_ports.inc +); + +wire [13:1] cpu_addr; +wire [ 1:0] cpu_dsn; +wire [ 8:0] hdump; +wire [ 7:0] st_main, st_sub, st_video, x1_dout, slatch0, slatch1; +wire [15:0] vram_dout; +wire flip, cpu_rnw, sub_rst, + vram_cs, vctrl_cs, vflag_cs, tctrl_cs, + x1_cs, shram_cs; + +// MRA header byte 0 = game_id (0=metafox, 1=arbalest) +`ifdef JTFRAME_SIM_GAMEID +reg [3:0] game_id = `JTFRAME_SIM_GAMEID; +`else +reg [3:0] game_id = 4'd0; +`endif +always @(posedge clk) if( prog_we && header ) case( prog_addr[3:0] ) + 4'd0: game_id <= prog_data[3:0]; + default:; +endcase + +assign debug_view = st_video; +assign dip_flip = ~flip; +assign mute = 0; + +/* verilator tracing_on */ +jtarbalest_main u_main( + .rst ( rst ), + .clk ( clk ), + .cen8 ( cen8 ), + .lvbl ( LVBL ), + + .rom_addr ( main_addr ), + .ram_addr ( ram_addr ), + .cpu_addr ( cpu_addr ), + .cpu_dsn ( cpu_dsn ), + .ram_we ( ram_we ), + .cpu_dout ( cpu_dout ), + .cpu_rnw ( cpu_rnw ), + + .rom_cs ( main_cs ), + .rom_data ( main_data ), + .rom_ok ( main_ok ), + .ram_dout ( ram_dout ), + + // X1-010 sound (main bus) + .x1_cs ( x1_cs ), + .x1_dout ( x1_dout ), + + // I/O sub-CPU (sub_ctrl_w decoded in main) + .slatch0 ( slatch0 ), + .slatch1 ( slatch1 ), + .sub_rst ( sub_rst ), + .shram_cs ( shram_cs ), + .shram_we ( shram_we ), + .shram_dout ( shram_dout ), + + // video + .pal_we ( pal_we ), + .pal_dout ( pal_dout ), + .tctrl_cs ( tctrl_cs ), + .tlv_we ( tlv_we ), + .tlv_dout ( tlv_dout ), + .vram_cs ( vram_cs ), + .vflag_cs ( vflag_cs ), + .vctrl_cs ( vctrl_cs ), + .vram_dout ( vram_dout ), + + // cabinet + .game_id ( game_id ), + .dipsw ( dipsw[15:0] ), + .dip_pause ( dip_pause ), + .st_dout ( st_main ), + .debug_bus ( debug_bus ) +); + +/* verilator tracing_on */ +jtarbalest_sub u_sub( + .rst ( sub_rst ), + .clk ( clk ), + .cen ( cen8 ), // 8 MHz crystal cen -> ~2 MHz E (jt65c02 /4) + .joystick1 ( joystick1[5:0]), + .joystick2 ( joystick2[5:0]), + .cab_1p ( cab_1p[1:0] ), + .coin ( coin[1:0] ), + .service ( service ), + .tilt ( tilt ), + .slatch0 ( slatch0 ), + .slatch1 ( slatch1 ), + + .rom_addr ( snd_addr ), + .rom_cs ( snd_cs ), + .rom_data ( snd_data ), + .rom_ok ( snd_ok ), + + .subsh_addr ( subsh_addr ), + .subsh_din ( subsh_din ), + .subsh_dout ( subsh_dout ), + .subsh_we ( subsh_we ), + + .hs ( HS ), + .lvbl ( LVBL ), + .st_dout ( st_sub ) +); + +/* verilator tracing_on */ +jtarbalest_sound u_sound( + .rst ( rst ), + .clk ( clk ), + .cen_pcm ( cen_pcm ), + + .cs ( x1_cs ), + .addr ( cpu_addr ), + .din ( cpu_dout[7:0] ), + .dout ( x1_dout ), + .we (~cpu_rnw ), + + .pcm_addr ( pcm_addr ), + .pcm_data ( pcm_data ), + .pcm_cs ( pcm_cs ), + + .snd_left ( pcm_8k ), + .snd_right ( pcm_4k ) +); + +/* verilator tracing_on */ +jtcal50_video #( + .OBJAW ( 13 ), // 16kB sprite RAM + setac bank + .SCR_EN( 1 ), // X1-001 background layer (draw_background) draws the attract scenery + .OBJ_LIMIT( 9'h1ff ), + // MAME visarea rows 16..239 (224 lines) -> vdump 8..231, VS stays centred + .VB_END ( 9'd8 ), + .VB_START( 9'd232 ), + // set_fg_xoffsets noflip: calibr50 -1, metafox/arbalest 0 -> one count right + .OBJ_XOFF( 9'h1ff ) +) u_video( + .rst ( rst ), + // MAME x1_012 set_xoffsets noflip: metafox 16 -> 0x00, arbalest -2 -> 0x12 + .thoffs ( game_id==4'd1 ? 16'h1f : 16'h0d ), + .clk ( clk ), + .clk_cpu ( clk ), + .cen244 ( ), + .pxl2_cen ( pxl2_cen ), + .pxl_cen ( pxl_cen ), + .LHBL ( LHBL ), + .LVBL ( LVBL ), + .HS ( HS ), + .VS ( VS ), + .hdump ( hdump ), + .flip ( flip ), + + .cpu_rnw ( cpu_rnw ), + .cpu_dsn ( cpu_dsn ), + .cpu_addr ( cpu_addr ), + .cpu_dout ( cpu_dout ), + .vram_cs ( vram_cs ), + .vctrl_cs ( vctrl_cs ), + .vflag_cs ( vflag_cs ), + .vram_dout ( vram_dout ), + + .col_addr ( col_addr ), + .col_data ( col_data ), + .yram_dout ( yram_dout ), + .yram_we ( yram_we ), + + .dma_addr ( dma_addr ), + .dma_din ( dma_din ), + .dma_we ( dma_we ), + .dma_dout ( dma_dout ), + .code_dout ( code_dout ), + .code_addr ( code_addr ), + + .tctrl_cs ( tctrl_cs ), + .tvram_addr ( tlrd_addr ), + .tvram_dout ( tlrd_data ), + .tile_addr ( tile_addr ), + .tile_data ( tile_data ), + .tile_cs ( tile_cs ), + .tile_ok ( tile_ok ), + + .pal_addr ( palrd_addr ), + .pal_data ( pal_data ), + + .scr_addr ( scr_addr ), + .scr_data ( scr_data ), + .scr_ok ( scr_ok ), + .scr_cs ( scr_cs ), + + .obj_addr ( obj_addr ), + .obj_data ( obj_data ), + .obj_ok ( obj_ok ), + .obj_cs ( obj_cs ), + + .red ( red ), + .green ( green ), + .blue ( blue ), + + .ioctl_addr (ioctl_addr[3:0]), + .ioctl_din ( ioctl_din ), + .gfx_en ( gfx_en ), + .debug_bus ( debug_bus ), + .st_dout ( st_video ) +); + +endmodule diff --git a/cores/arbalest/hdl/jtarbalest_main.v b/cores/arbalest/hdl/jtarbalest_main.v new file mode 100644 index 000000000..dfbd7345c --- /dev/null +++ b/cores/arbalest/hdl/jtarbalest_main.v @@ -0,0 +1,257 @@ +/* This file is part of JTCORES. + JTCORES 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. + + JTCORES 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 JTCORES. If not, see . + + Author: Andrea Bogazzi. andreabogazzi79@gmail.com + Version: 1.0 + Date: 17-06-2026 */ + +// Seta downtown.cpp (metafox-class) main 68000. +// Unlike calibr50 (cal50): the X1-010 lives on THIS bus (0x100000) and the +// 65C02 is an I/O / protection coprocessor reached through shared RAM (0xb00000). +// +// downtown_map nibble decode (A[23:20]): +// 0 ROM 1 X1-010 sound 2 protection 3 ipl1-ack 4 (unused: twineagl-only) +// 5 ctrl/coin 6 DSW 7 palette 8 X1-012 ctrl 9 X1-012 VRAM +// A sub-ctrl B shared RAM C X1-001 bg-flag D X1-001 spr-ctrl +// E X1-001 spr-code F work RAM +module jtarbalest_main( + input rst, clk, cen8, + input lvbl, + + output [19:1] rom_addr, + output [15:1] ram_addr, + output [12:0] cpu_addr, + output [ 1:0] cpu_dsn, + output [ 1:0] ram_we, + output [15:0] cpu_dout, + output cpu_rnw, + + output reg rom_cs, + input [15:0] rom_data, + input rom_ok, + input [15:0] ram_dout, + + // X1-010 sound (on the main bus) + output reg x1_cs, + input [ 7:0] x1_dout, + + // I/O / protection sub-CPU (65C02). sub_ctrl_w (0xa00000) is decoded here: + output reg [ 7:0] slatch0, slatch1, // soundlatches, read by the sub @0x0800/1 + output sub_rst, // 0xa00000 bit0 rising -> stretched sub reset + output reg shram_cs, // 0xb00000 shared RAM + output shram_we, + input [ 7:0] shram_dout, + + // X1-012 tilemap + palette + output [ 1:0] pal_we, + input [15:0] pal_dout, + output reg tctrl_cs, // X1-012 control + output [ 1:0] tlv_we, + input [15:0] tlv_dout, + + // X1-001 sprites (same regions as cal50) + output reg vram_cs, vflag_cs, vctrl_cs, + input [15:0] vram_dout, + + // Game select (0=metafox, 1=arbalest) + input [ 3:0] game_id, + // Cabinet (DSW read by main; joysticks/coins are read by the sub) + input [15:0] dipsw, + input dip_pause, + output [ 7:0] st_dout, + input [ 7:0] debug_bus +); +`ifndef NOMAIN +wire [23:1] A; +reg [15:0] cpu_din; +reg [ 2:0] IPLn; +reg ram_cs, prot_cs, ipl1_cs, dips_cs, tlv_cs, pal_cs, subctrl_cs; +wire int16ms, + cpu_cen, cpu_cenb, dtackn, VPAn, vgfx_cs, + UDSn, LDSn, RnW, ASn, BUSn, bus_busy, bus_cs; +reg HALTn; + +assign cpu_addr = A[13:1]; +assign rom_addr = A[19:1]; +assign ram_addr = A[15:1]; +// VPAn (6800-style sync) asserted on the upper half so the level-3 vblank IRQ +// autovectors: the IACK address is all 1s -> A[23]=1. Same idiom as cal50. +// MAME: screen_vblank -> set_inputline(maincpu,3) with no vector cb = autovector. +assign VPAn = ~&{A[23],~ASn}; +assign cpu_dsn = {UDSn, LDSn}; +assign bus_cs = rom_cs | vgfx_cs; +// X1-001/X1-012 RAM is dual-port BRAM (CPU + engine on separate ports), so the +// CPU needs NO access-arbitration stall. cal50's hdump-gated vgfx_bsy wait, when +// imported here, desynced the fx68k dtack on the POST's back-to-back sprite-RAM +// writes and corrupted an ALU result (e1c7+0f0f -> 1289 instead of f0d6), +// failing the sprite-RAM self-test. Dropping the stall fixes it. +assign bus_busy = rom_cs & ~rom_ok; +assign BUSn = ASn | (LDSn & UDSn); +assign cpu_rnw = RnW; +assign ram_we = ~cpu_dsn & {2{ram_cs & ~RnW}}; +assign pal_we = ~cpu_dsn & {2{pal_cs & ~RnW}}; +assign tlv_we = ~cpu_dsn & {2{tlv_cs & ~RnW}}; +assign shram_we = shram_cs & ~RnW & ~LDSn; // 8-bit shared RAM, low byte +assign st_dout = 0; +assign vgfx_cs = vram_cs | vflag_cs | vctrl_cs; + +always @* begin + rom_cs = !BUSn && A[23:20]==0; + x1_cs = !ASn && A[23:20]==1; // X1-010 + prot_cs = !ASn && A[23:20]==2; // protection / debug stub + ipl1_cs = !ASn && A[23:20]==3; +// ctrl/coin = !ASn && A[23:20]==5; + dips_cs = !ASn && A[23:20]==6; + pal_cs = !ASn && A[23:20]==7; + tctrl_cs = !ASn && A[23:20]==8 && !RnW; + tlv_cs = !ASn && A[23:20]==9 && !A[14]; + subctrl_cs = !ASn && A[23:20]==4'hA; + shram_cs = !BUSn && A[23:20]==4'hB; + // SETA X1-001 chip + vflag_cs = !ASn && A[23:20]==4'hC; + vctrl_cs = !ASn && A[23:20]==4'hD && (A[9:8]!=3 || !LDSn); + vram_cs = !ASn && A[23:20]==4'hE; + ram_cs = !BUSn && A[23:20]==4'hF; +end + +reg [7:0] dipsw_mx; +always @* dipsw_mx = A[1] ? dipsw[7:0] : dipsw[15:8]; + +// metafox X1-017 protection (game_id==0). MAME metafox_protection_r returns +// offset*0x1f (word offset within 0x21c000-0x21ffff) with three special words. +// The boot self-tests this readback sequence; arbalest has no 0x21c000 protection. +wire prot_meta = prot_cs && game_id==4'd0 && A[19:14]==6'd7; +wire [12:0] prot_off = A[13:1]; +reg [15:0] prot_dout; +always @* begin + case( prot_off ) + 13'h000: prot_dout = 16'h003d; + 13'h800: prot_dout = 16'h0076; + 13'h1000: prot_dout = 16'h0010; + default: prot_dout = prot_off * 16'd31; // offset*0x1f + endcase +end + +// metafox main = a single level-3 IRQ on vblank (downtown.cpp: +// screen_vblank().set_inputline(maincpu, 3)). Acked by the 0x300000 write +// (ipl1_ack_w). NO timer/scanline IRQ on the main (that is calibr50-only). +always @* begin + IPLn = 3'b111; // level 0 (idle) + if( int16ms ) IPLn = 3'b100; // level 3 vblank IRQ +end + +always @(posedge clk) begin + HALTn <= dip_pause & ~rst; + cpu_din <= rom_cs ? rom_data : + ram_cs ? ram_dout : + (vram_cs | vctrl_cs) ? vram_dout : + pal_cs ? pal_dout : + tlv_cs ? tlv_dout : + x1_cs ? {8'd0, x1_dout} : + shram_cs ? {8'd0, shram_dout}: + dips_cs ? {8'hff, dipsw_mx} : + prot_meta? prot_dout : + prot_cs ? 16'hffff : 16'h0; +end + +// sub_ctrl_w (0xa00000-7, umask 0x00ff): off0 bit0 rising -> stretched sub reset; +// off4/off6 -> soundlatch0/1 (read by the sub at 0x0800/1). A[2:1] = sub_ctrl offset. +reg subctrl0_b0; +reg [ 4:0] subrst_cnt; // stretch the reset pulse over a few cen8 ticks +wire subctrl_we = subctrl_cs & ~RnW & ~LDSn; +assign sub_rst = rst | (subrst_cnt!=0); +always @(posedge clk) begin + if( rst ) begin + slatch0 <= 0; slatch1 <= 0; subctrl0_b0 <= 0; subrst_cnt <= 0; + end else begin + if( subctrl_we ) case( A[2:1] ) + 2'd0: begin + subctrl0_b0 <= cpu_dout[0]; + if( cpu_dout[0] & ~subctrl0_b0 ) subrst_cnt <= 5'h1f; // bit0 rising + end + 2'd2: slatch0 <= cpu_dout[7:0]; + 2'd3: slatch1 <= cpu_dout[7:0]; + default:; + endcase + if( subrst_cnt!=0 && cen8 ) subrst_cnt <= subrst_cnt - 5'd1; + end +end + +jtframe_edge u_16ms( + .rst ( rst ), + .clk ( clk ), + .edgeof (~lvbl ), // vblank (LVBL falling) -> level-3 IRQ + .clr ( ipl1_cs ), // acked by the 0x300000 write + .q ( int16ms ) +); + +jtframe_68kdtack_cen #(.W(6),.RECOVERY(1)) u_bus_dtack( + .rst ( rst ), + .clk ( clk ), + .cpu_cen ( cpu_cen ), + .cpu_cenb ( cpu_cenb ), + .bus_cs ( bus_cs ), + .bus_busy ( bus_busy ), + .bus_legit ( 1'b0 ), + .bus_ack ( 1'b0 ), + .ASn ( ASn ), + .DSn ({UDSn,LDSn}), + .num ( 5'd1 ), + .den ( 6'd6 ), + .DTACKn ( dtackn ), + .wait2 ( 1'b0 ), + .wait3 ( 1'b0 ), + .fave ( ), + .fworst ( ) +); + +jtframe_m68k u_cpu( + .clk ( clk ), + .rst ( rst ), + .RESETn ( ), + .cpu_cen ( cpu_cen ), + .cpu_cenb ( cpu_cenb ), + + .eab ( A ), + .iEdb ( cpu_din ), + .oEdb ( cpu_dout ), + + .eRWn ( RnW ), + .LDSn ( LDSn ), + .UDSn ( UDSn ), + .ASn ( ASn ), + .VPAn ( VPAn ), + .FC ( ), + + .BERRn ( 1'b1 ), + .HALTn ( HALTn ), + .BRn ( 1'b1 ), + .BGACKn ( 1'b1 ), + .BGn ( ), + + .DTACKn ( dtackn ), + .IPLn ( IPLn ) +); +`else + initial rom_cs = 0; + assign rom_addr = 0, ram_addr = 0, cpu_addr = 0, cpu_dsn = 3, + ram_we = 0, cpu_dout = 0, cpu_rnw = 1, + pal_we = 0, tlv_we = 0, shram_we = 0, sub_rst = rst, + st_dout = 0; + initial begin + x1_cs=0; subctrl_cs=0; shram_cs=0; tctrl_cs=0; + vram_cs=0; vflag_cs=0; vctrl_cs=0; slatch0=0; slatch1=0; + end +`endif +endmodule diff --git a/cores/arbalest/hdl/jtarbalest_sound.v b/cores/arbalest/hdl/jtarbalest_sound.v new file mode 100644 index 000000000..a96f01bd2 --- /dev/null +++ b/cores/arbalest/hdl/jtarbalest_sound.v @@ -0,0 +1,62 @@ +/* This file is part of JTCORES. + JTCORES 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. + + JTCORES 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 JTCORES. If not, see . + + Author: Andrea Bogazzi. andreabogazzi79@gmail.com + Version: 1.0 + Date: 17-06-2026 */ + +module jtarbalest_sound( + input clk, + input rst, + input cen_pcm, + + // Main-bus CPU interface + input cs, + input [12:0] addr, // main cpu_addr = A[13:1] + input [ 7:0] din, + output [ 7:0] dout, + input we, + + // PCM sample ROM (SDRAM pcm bank) + output [19:0] pcm_addr, + input [ 7:0] pcm_data, + output pcm_cs, + + // Sound output: left = music (8kHz AA), right = bass/sfx (4kHz AA) + output signed [15:0] snd_left, snd_right +); +`ifndef NOSOUND +jtx1010 u_pcm( + .rst ( rst ), + .clk ( clk ), + .cen ( cen_pcm ), + + .addr ( addr ), + .din ( din ), + .dout ( dout ), + .we ( we & cs ), + .cs ( cs ), + + .rom_addr ( pcm_addr ), + .rom_data ( pcm_data ), + .rom_cs ( pcm_cs ), + + .left ( snd_left ), + .right ( snd_right ), + .sample ( ) +); +`else + assign dout=0, pcm_addr=0, pcm_cs=0, snd_left=0, snd_right=0; +`endif +endmodule diff --git a/cores/arbalest/hdl/jtarbalest_sub.v b/cores/arbalest/hdl/jtarbalest_sub.v new file mode 100644 index 000000000..c720fa207 --- /dev/null +++ b/cores/arbalest/hdl/jtarbalest_sub.v @@ -0,0 +1,157 @@ +/* This file is part of JTCORES. + JTCORES 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. + + JTCORES 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 JTCORES. If not, see . + + Author: Andrea Bogazzi. andreabogazzi79@gmail.com + Version: 1.0 + Date: 17-06-2026 */ + +// metafox / arbalest I/O - protection sub-CPU (65C02 @ 2 MHz). +// It reads the cabinet inputs and exchanges them with the main 68000 through +// the shared RAM, plus does bankswitch + coin lockout. +// +// metafox_sub_map: +// 0x0000-0x01ff internal RAM 0x0800/0x0801 soundlatch 0/1 (main comm) +// 0x1000 COINS r / bank+lockout w 0x1002 P1 0x1006 P2 +// 0x5000-0x57ff shared RAM 0x7000-0x7fff ROM +// 0x8000-0xbfff banked ROM 0xc000-0xffff ROM +module jtarbalest_sub( + input rst, clk, + input cen, // 2 MHz enable + + // Cabinet inputs (read here, shared to main via shram) + input [ 5:0] joystick1, joystick2, + input [ 1:0] cab_1p, // start buttons + input [ 1:0] coin, + input service, tilt, + + // main->sub command latches (sub_ctrl_w 0xa00004/0xa00006), read at 0x0800/0x0801 + input [ 7:0] slatch0, slatch1, + + // Program ROM (snd SDRAM bank) + output [17:0] rom_addr, + output reg rom_cs, + input [ 7:0] rom_data, + input rom_ok, + + // Shared RAM (subsh side of the shram dual-port BRAM) + output [10:0] subsh_addr, + output [ 7:0] subsh_din, + input [ 7:0] subsh_dout, + output subsh_we, + + // Screen timing — the metafox sub_interrupt is generated from it below. + input hs, + input lvbl, + output [ 7:0] st_dout +); +`ifndef NOSUB +wire [15:0] A; +wire [ 7:0] cpu_dout, ram_dout; +reg [ 7:0] cpu_din, cab_dout; +wire cpu_wr; +reg ram_cs, sh_cs, in_cs, lat_cs; + +assign st_dout = 0; +// metafox sub ROM is an 8 KB EPROM that MAME ROM_RELOADs across 0x6000-0xffff. +// mame2mra packs it once at region offset 0 and drops the reloads, so mirror it +// here: index the 8 KB image by A[12:0]. (Reset vector 0xfffc -> ROM[0x1ffc].) +assign rom_addr = {5'd0, A[12:0]}; +assign subsh_addr = A[10:0]; +assign subsh_din = cpu_dout; +assign subsh_we = sh_cs & cpu_wr; // byte writes from the sub + +always @* begin + ram_cs = A[15:9]==0; // 0x0000-0x01ff + in_cs = A[15:12]==4'h1; // 0x1000 region (inputs / bank) + sh_cs = A[15:12]==4'h5; // 0x5000-0x57ff shared RAM + rom_cs = A[15] | (A[15:13]==3'b011); // 0x6000-0xffff (8KB ROM, mirrored) + lat_cs = A[15:11]==5'h01; // 0x0800 soundlatch (stub) +end + +always @* begin + case(A[2:1]) + 2'd0: cab_dout = {coin[0],coin[1],service,tilt,4'hf}; // 0x1000 COINS + 2'd1: cab_dout = {cab_1p[0],1'b1,joystick1}; // 0x1002 P1 + 2'd2: cab_dout = 8'h00; // 0x1004 status port: reads 0 + // (arbalest sub boot checks 0x1004==0; MAME nopr=0) + 2'd3: cab_dout = {cab_1p[1],1'b1,joystick2}; // 0x1006 P2 + default: cab_dout = 8'hff; + endcase +end + +always @* begin + cpu_din = ram_cs ? ram_dout : + sh_cs ? subsh_dout : + in_cs ? cab_dout : + lat_cs ? (A[0] ? slatch1 : slatch0) : // soundlatch 0x0800/0x0801 (main->sub) + rom_cs ? rom_data : 8'hff; +end + +// The 0x1000 write is the ROM-bank + coin-lockout register. Banking is not +// implemented (the 8 KB sub ROM is mirrored across 0x6000-0xffff, see rom_addr) +// and coin-lockout is a no-op here, so the latch is omitted. The write's only +// live effect is acking the sub IRQ below (in_cs & cpu_wr -> u_irq.clr). + +jtframe_ram #(.AW(9)) u_ram( // 0x0000-0x01ff internal RAM + .clk ( clk ), + .cen ( 1'b1 ), + .addr ( A[8:0] ), + .data ( cpu_dout ), + .we ( ram_cs & cpu_wr ), + .q ( ram_dout ) +); + +// metafox sub_interrupt from the screen scanline (MAME line 0 = LVBL rising): +// IRQ (level) asserted entering line 112, NMI (edge) high during vblank (line>=240). +reg [ 8:0] vline; +reg hs_q, lvbl_q, irq_set, nmi; +always @(posedge clk) begin + hs_q <= hs; + lvbl_q <= lvbl; + irq_set <= 0; + if( lvbl & ~lvbl_q ) vline <= 0; + else if( hs & ~hs_q ) begin + vline <= vline + 9'd1; + if( vline==9'd111 ) irq_set <= 1; + end + nmi <= vline >= 9'd240; +end + +// IRQ latch: set at scanline 112, cleared by the 0x1000 bank/lockout write. +wire irq; +jtframe_edge u_irq( + .rst ( rst ), + .clk ( clk ), + .edgeof ( irq_set ), + .clr ( in_cs & cpu_wr ), // sub_bankswitch_lockout_w acks the IRQ + .q ( irq ) +); + +jt65c02 u_cpu( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), + .irq ( irq ), + .nmi ( nmi ), + .rd ( ), + .wr ( cpu_wr ), + .addr ( A ), + .din ( cpu_din ), + .dout ( cpu_dout ) +); +`else + initial rom_cs = 0; + assign rom_addr=0, subsh_addr=0, subsh_din=0, subsh_we=0, st_dout=0; +`endif +endmodule diff --git a/cores/cal50/hdl/jtcal50_colmix.v b/cores/cal50/hdl/jtcal50_colmix.v index 2e9d75420..ac1590361 100644 --- a/cores/cal50/hdl/jtcal50_colmix.v +++ b/cores/cal50/hdl/jtcal50_colmix.v @@ -16,14 +16,16 @@ Version: 1.0 Date: 15-11-2025 */ -module jtcal50_colmix( +module jtcal50_colmix #( + parameter SCR_EN = 0 // 1: blend the X1-001 background layer (metafox/arbalest) +)( input clk, input clk_cpu, input pxl_cen, input LHBL, input LVBL, - input [ 8:0] scr_pxl, // unused ? + input [ 8:0] scr_pxl, // X1-001 draw_background (column-scrolled sprite BG) input [ 8:0] obj_pxl, tiles_pxl, output reg [ 9:1] pal_addr, @@ -38,21 +40,28 @@ module jtcal50_colmix( reg [ 8:0] col_addr; reg [14:0] rgb; -wire [ 8:0] obj_srt; -wire blank; +wire [ 8:0] obj_srt, scr_srt, bg; +wire blank, scr_sel; reg obj_sel; assign blank = ~(LVBL & LHBL); assign {red,green,blue} = blank ? 15'd0 : rgb; +// X1-001 pen-bit order (same for foreground sprites and the background layer) assign obj_srt = {obj_pxl[8:4],obj_pxl[1],obj_pxl[3],obj_pxl[0],obj_pxl[2]}; +assign scr_srt = {scr_pxl[8:4],scr_pxl[1],scr_pxl[3],scr_pxl[0],scr_pxl[2]}; +// X1-001 background (draw_background) masks the X1-012 tiles where opaque. Only +// for SCR_EN cores; calibr50 (SCR_EN=0) keeps bg==tiles_pxl, so the mux below is +// byte-identical to before. +assign scr_sel = SCR_EN & gfx_en[1] & (scr_srt[3:0]!=4'h0); +assign bg = scr_sel ? scr_srt : tiles_pxl; always @* begin obj_sel = obj_srt[3:0] != 4'h0; case( {gfx_en[3],gfx_en[0]}) 2'b00: col_addr = 0; - 2'b01: col_addr = tiles_pxl; + 2'b01: col_addr = bg; 2'b10: col_addr = obj_srt; - 2'b11: col_addr = obj_sel ? obj_srt : tiles_pxl; // simple priority for now. + 2'b11: col_addr = obj_sel ? obj_srt : bg; endcase end diff --git a/cores/cal50/hdl/jtcal50_game.v b/cores/cal50/hdl/jtcal50_game.v index 086487f3d..67f0899a0 100644 --- a/cores/cal50/hdl/jtcal50_game.v +++ b/cores/cal50/hdl/jtcal50_game.v @@ -122,6 +122,7 @@ jtcal50_sound u_sound( /* verilator tracing_on */ jtcal50_video u_video( .rst ( rst ), + .thoffs ( 16'h20 ), .clk ( clk ), .clk_cpu ( clk ), .cen244 ( cen244 ), diff --git a/cores/cal50/hdl/jtcal50_video.v b/cores/cal50/hdl/jtcal50_video.v index 7c5d51d3f..a5742de72 100644 --- a/cores/cal50/hdl/jtcal50_video.v +++ b/cores/cal50/hdl/jtcal50_video.v @@ -16,7 +16,18 @@ Version: 1.0 Date: 15-11-2025 */ -module jtcal50_video( +module jtcal50_video #( + // 12 = 8kB sprite RAM (calibr50), 13 = 16kB + setac bank (metafox/arbalest) + parameter OBJAW = 12, + // 1: blend the X1-001 background layer (metafox/arbalest) + parameter SCR_EN = 0, + // Caliber 50 only populates object entries 0-200; a shorter scan leaves + // line time for the sprites that wrap through Y=0 + parameter [ 8:0] OBJ_LIMIT = 9'd200, + parameter [ 8:0] VB_END = 9'd0, + parameter [ 8:0] VB_START = 9'd240, + parameter [ 8:0] OBJ_XOFF = 9'h1fe +)( input rst, input clk, input clk_cpu, @@ -30,6 +41,10 @@ module jtcal50_video( output VS, output flip, output [ 8:0] hdump, + // X1-012 tilemap scroll origin. Per game, so it cannot be a parameter on a + // shared bitstream. MAME x1_012 update_scroll: x += 0x10-xoffsets[0], and our + // origin sits 0x0d above MAME's -> calibr50 0x20, metafox 0x0d, arbalest 0x1f + input [15:0] thoffs, // Palette output [ 9:1] pal_addr, input [15:0] pal_data, @@ -56,11 +71,11 @@ module jtcal50_video( input [ 7:0] col_data, yram_dout, output yram_we, // X1-001 External VRAM (defined in mem.yaml) - output [12:1] dma_addr, + output [OBJAW:1] dma_addr, output [15:0] dma_din, output [ 1:0] dma_we, input [15:0] dma_dout, code_dout, - output [11:0] code_addr, + output [OBJAW-1:0] code_addr, // SDRAM interface output [20:2] scr_addr, input [31:0] scr_data, @@ -95,6 +110,7 @@ wire [6:0] nx_244 = {1'b0,cnt244} + 6'd1; wire [8:0] hdump_gfx = hdump - 9'd7; wire [8:0] vdump_gfx = vdump - 9'd1, vrender_gfx = vrender - 9'd1; +wire [8:0] vdump_tile = vdump_gfx - VB_END; assign ioctl_din = ioctl_addr[3] ? x1001_ioctl_din : x1012_ioctl_din; @@ -120,8 +136,8 @@ jtframe_vtimer #( .V_START ( 9'd000 ), .VS_START( 9'd253 ), .VS_END ( 9'd261 ), - .VB_START( 9'd240 ), - .VB_END ( 9'd000 ), + .VB_START( VB_START ), + .VB_END ( VB_END ), .VCNT_END( 9'd271 ) ) u_timer( .clk ( clk ), @@ -140,6 +156,7 @@ jtframe_vtimer #( /* verilator tracing_off */ jtx1012 u_tiles( .rst ( rst ), + .hoffs ( thoffs ), .clk ( clk ), .pxl_cen ( pxl_cen ), @@ -151,7 +168,7 @@ jtx1012 u_tiles( .hs ( HS ), .flip ( flip ), - .vdump ( vdump_gfx ), + .vdump ( vdump_tile ), .hdump ( hdump_gfx ), // Video RAM .vram_addr ( tvram_addr ), @@ -183,10 +200,11 @@ wire [8:0] vdump_adj = vdump_gfx + VADJ, // range leaves enough line time for sprites that wrap through Y=0. jtkiwi_gfx #( .CPUW ( 16 ), - .OBJ_XOFF( 9'h1fe ), + .OBJ_XOFF( OBJ_XOFF ), .OBJ_YOFF( 8'hf5 ), .OBJ_YWRAP( 1'b1 ), - .OBJ_LIMIT( 9'd200 ) + .OBJ_LIMIT( OBJ_LIMIT ), + .OBJAW ( OBJAW ) ) u_gfx( .rst ( rst ), .clk ( clk ), @@ -245,7 +263,7 @@ jtkiwi_gfx #( .st_dout ( st_kiwi ) ); /* verilator tracing_on */ -jtcal50_colmix u_colmix( +jtcal50_colmix #(.SCR_EN(SCR_EN)) u_colmix( .clk ( clk ), .clk_cpu ( clk_cpu ), .pxl_cen ( pxl_cen ), diff --git a/cores/cal50/hdl/jtx1012.v b/cores/cal50/hdl/jtx1012.v index 3d55e80ca..20c61648d 100644 --- a/cores/cal50/hdl/jtx1012.v +++ b/cores/cal50/hdl/jtx1012.v @@ -33,6 +33,8 @@ module jtx1012( input hs, flip, input [8:0] vdump, input [8:0] hdump, + // tilemap scroll origin, per game (jtframe_scroll: scrx left) + input [15:0] hoffs, // Video RAM output [13:1] vram_addr, input [15:0] vram_dout, @@ -69,9 +71,10 @@ assign rom_addr = {pre_addr[20:7],pre_addr[5],~flip^pre_addr[6], }; always @(posedge clk) begin - hpos <= pre_hpos+16'h20; + hpos <= pre_hpos+hoffs; end + always @(posedge clk) begin attr <= ~attr; if(attr) begin diff --git a/cores/kiwi/hdl/jtkiwi_gfx.v b/cores/kiwi/hdl/jtkiwi_gfx.v index 47d47a67f..f6675bd05 100644 --- a/cores/kiwi/hdl/jtkiwi_gfx.v +++ b/cores/kiwi/hdl/jtkiwi_gfx.v @@ -28,7 +28,10 @@ module jtkiwi_gfx #( parameter [8:0] OBJ_XOFF=0, parameter [7:0] OBJ_YOFF=0, parameter OBJ_YWRAP=0, - parameter [8:0] OBJ_LIMIT=9'h1ff + parameter [8:0] OBJ_LIMIT=9'h1ff, + // 12 = 8kB sprite RAM, page selects the 0x800 half (tnzs/calibr50) + // 13 = 16kB, page selects the 0x1000 buffer (metafox/arbalest, MAME seta001 setac) + parameter OBJAW=12 )( input rst, input clk, @@ -65,11 +68,11 @@ module jtkiwi_gfx #( input [ 7:0] col_data, yram_dout, output yram_we, // External VRAM (defined in mem.yaml) - output [12:1] dma_addr, + output [OBJAW:1] dma_addr, output [15:0] dma_din, output [ 1:0] dma_we, input [15:0] dma_dout, code_dout, - output reg [12:1] code_addr, + output reg [OBJAW:1] code_addr, // SDRAM interface output [20:2] scr_addr, input [31:0] scr_data, @@ -87,10 +90,15 @@ module jtkiwi_gfx #( output reg [ 7:0] st_dout ); +localparam SETAC = OBJAW==13; + wire video_en; wire [ 1:0] vram_we; wire [11:0] tm_addr; -wire [12:1] lut_addr, dma_txa; +wire [OBJAW:1] lut_addr; +wire [12:1] dma_txa; +wire [13:1] dma_txa_pad, tm_addr_pad; +wire setac_bank; wire [ 7:0] scol_addr; reg [ 7:0] attr, xpos, ypos; reg [ 7:0] cfg[0:3], flag; @@ -125,8 +133,12 @@ assign obj_page = obj_pg_en ? tm_page ^ ~obj_bufb : 1'b1; assign dma_src = obj_pg_en ? tm_page ^ dma_tm : 1'b0; assign col_cfg = cfg[1][3:0]; assign col_xmsb = { cfg[3], cfg[2] }; -assign dma_addr = dma_bsy ? dma_txa : cpu_addr[11:0]; +assign dma_addr = dma_bsy ? dma_txa_pad[OBJAW:1] : cpu_addr[OBJAW-1:0]; assign dma_txa ={dma_src ^ dma_st, dma_tm, dma_cnt}; +assign dma_txa_pad = { 1'b0, dma_txa }; +// 16kB sprite RAM: cfg[1] carries the buffer bank (MAME seta001 setac_eof) +assign setac_bank = ((cfg[1] ^ (~cfg[1]<<1)) & 8'h40)!=0; +assign tm_addr_pad = { setac_bank, tm_addr }; assign dma_din = dma_bsy ? dma_data : vram_d16; assign dma_we = dma_bsy ? dma_bsy_we : vram_we; @@ -211,7 +223,7 @@ always @* begin case( cen_cnt ) 0,1: begin col_addr = { 2'b10, scol_addr }; - code_addr = tm_addr; + code_addr = tm_addr_pad[OBJAW:1]; end 2,3: begin // objects col_addr = { 1'b0, y_addr }; @@ -228,7 +240,8 @@ jtkiwi_tilemap u_tilemap( .hs ( hs ), .flip ( flip ), - .page ( tm_page ), + // SETAC: no 0x800 page split, the bank is the code_addr MSB + .page ( SETAC ? 1'b0 : tm_page ), .drtoppel ( drtoppel ), .col_xmsb ( col_xmsb ), @@ -257,7 +270,8 @@ jtkiwi_obj #( .XOFF( OBJ_XOFF ), .YOFF( OBJ_YOFF ), .YWRAP( OBJ_YWRAP ), - .LIMIT( OBJ_LIMIT ) + .LIMIT( OBJ_LIMIT ), + .OBJAW( OBJAW ) ) u_obj( .rst ( rst ), .clk ( clk ), @@ -266,7 +280,7 @@ jtkiwi_obj #( .hs ( hs ), .flip ( flip ), - .page ( obj_page ), + .page ( SETAC ? setac_bank : obj_page ), .lut_addr ( lut_addr ), .lut_data ( code_dout ), diff --git a/cores/kiwi/hdl/jtkiwi_obj.v b/cores/kiwi/hdl/jtkiwi_obj.v index 4025aa062..62d3fc050 100644 --- a/cores/kiwi/hdl/jtkiwi_obj.v +++ b/cores/kiwi/hdl/jtkiwi_obj.v @@ -22,7 +22,10 @@ module jtkiwi_obj #( parameter [8:0] XOFF=0, parameter [7:0] YOFF=0, parameter YWRAP=0, - parameter [8:0] LIMIT=9'h1ff + parameter [8:0] LIMIT=9'h1ff, + // 12 = 8kB sprite RAM, page selects the 0x800 half (tnzs/calibr50) + // 13 = 16kB, page selects the 0x1000 buffer (metafox/arbalest, MAME seta001 setac) + parameter OBJAW=12 )( input rst, input clk, @@ -33,7 +36,7 @@ module jtkiwi_obj #( input flip, input page, - output [12:1] lut_addr, + output [OBJAW:1] lut_addr, input [15:0] lut_data, output [ 8:0] y_addr, @@ -68,7 +71,10 @@ wire dr_busy; wire [ 8:0] buf_din, buf_addr; wire buf_we; -assign lut_addr = { page, 1'b0, ~st[1], objcnt }; // 1 + 1 + 1 + 9 = 12 +generate + if( OBJAW==13 ) assign lut_addr = { page, 2'b00, ~st[1], objcnt }; // 1 + 2 + 1 + 9 = 13 + else assign lut_addr = { page, 1'b0, ~st[1], objcnt }; // 1 + 1 + 1 + 9 = 12 +endgenerate assign y_addr = objcnt; assign vf = {9{flip}} ^ (vdump-9'd1); assign ypos = y_data + YOFF;