diff --git a/.beta.yaml b/.beta.yaml index a04277ad3..71fbac698 100644 --- a/.beta.yaml +++ b/.beta.yaml @@ -8,4 +8,5 @@ blkout: [ mister, pocket ] gals: [ mister, pocket ] pktgal: [ mister, pocket ] rastan: [ mister, pocket ] +taitox: [ mister, pocket ] vlfied: [ mister, pocket ] diff --git a/.gitignore b/.gitignore index 96697efec..5144fa37d 100644 --- a/.gitignore +++ b/.gitignore @@ -129,4 +129,7 @@ AGENTS.md .jtsandbox seed/ scenes/ -ver/ \ No newline at end of file +ver/ +# Manufacturer schematics are the maker's IP - keep them local only. +# Narrow on purpose: other cores already track theirs. +cores/taitox/doc/*.pdf 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; diff --git a/cores/taitox/README.md b/cores/taitox/README.md new file mode 100644 index 000000000..73efddab1 --- /dev/null +++ b/cores/taitox/README.md @@ -0,0 +1,120 @@ +# JTTAITOX — Taito X System FPGA core + +Core by Andrea Bogazzi, built on JTFRAME by Jose Tejada (jotego, @topapate). + +You can show your appreciation through +* [Patreon](https://patreon.com/jotego) +* [Paypal](https://paypal.me/topapate) +* [Github sponsors](https://github.com/sponsors/asturur) + +## Disclaimer + +This work is for research and historical purposes. This work itself does not +contain copyrighted software and should not be packed or distributed with +illegal copies of the copyright protected software. + +## Hardware + +The Taito X System is a Seta-designed board sold to Taito and licensed on to +East Technology. Three variants exist and the differences between the games +follow the board, not the title: + +| Board | Built by | Games | +|---|---|---| +| P0-039A | Taito Corp. | Superman | +| P0-051A | Taito Corp. | Twin Hawk, Daisenpu | +| P0-057A | East Technology | Gigandes, Last Striker, Balloon Brothers | + +A single 16 MHz oscillator feeds everything — confirmed on both the Superman +schematic (drawing W5100307A, sheet 3) and the board photo in `doc/`. The +X1-001 divides it down and emits the taps `CK`, `CK3`, `H1`, `H2`, `H3`; the +Z80 clock is `H1` and the 68000 is strapped to `CK` through a jumper box. + +| Chip | Role | Clock | +|---|---|---| +| Motorola 68000 | Main CPU | 16 / 2 = 8 MHz | +| Zilog Z80 | Sound CPU | 16 / 4 = 4 MHz | +| Yamaha YM2610 | FM + ADPCM-A + Delta-T | 16 / 2 = 8 MHz | +| Yamaha YM2151 | FM, P0-051A only | 16 / 4 = 4 MHz | +| Seta X1-001 | Sprite controller, video timing, OBJ-RAM master | 16 MHz | +| Seta X1-002 | Sprite renderer, holds spritectrl / spriteylow | 16 MHz | +| Seta X1-003 | RGB DAC, drives three R-2R ladders | — | +| Seta X1-006 | 68k ↔ palette bridge | — | +| Seta X1-004 / X1-007 | I/O | — | +| Taito TC0140SYT | 68k ↔ Z80 sound comms | — | +| Taito PC060HA | same silicon, P0-051A only | — | +| Taito TC0030CMD | C-chip, uPD78C11 MCU, P0-039A only | 16 / 2 = 8 MHz | + +There is **no tilemap chip**. MAME's single gfxdecode entry is "sprites & +playfield", and the playfield is the X1-001's background *column* mode. + +## Supported sets + +| Setname | Game | Board | State | +|---|---|---|---| +| `superman` `supermanu` `supermanj` | Superman | P0-039A | boots, renders | +| `gigandes` `gigandesa` | Gigandes | P0-057A | boots, renders | +| `ballbros` | Balloon Brothers | P0-057A | boots, renders | +| `kyustrkr` | Last Striker | P0-057A | boots, renders | +| `daisenpu` `twinhawk` `twinhawku` | Daisenpu / Twin Hawk | P0-051A | not enabled | + +Daisenpu and Twin Hawk are skipped in `cfg/mame2mra.toml` until the YM2151 +path lands. + +## Status + +**Working** + +- 68000 boot verified against MAME: the FPGA fetch stream contains every one + of MAME's 1464 distinct PCs on Superman, with no divergence. +- TC0030CMD C-chip runs the real MCU (`modules/jttc0030cmd`) and clears the + signature handshake with no HLE anywhere. +- Sprites and the background column layer render. Superman's title screen is + byte-identical to a MAME screenshot — 0 of 92160 pixels differ. +- Gigandes exercises the paths Superman never touches: the direct input port + at `900000`, the level-2 interrupt, and the ADPCM-B SDRAM bank. +- Sound: YM2610 and the TC0140SYT play correctly on hardware. + +**Not working** + +- **Sprite alignment is unverified** beyond the static title screen. +- **Scene replay does not exist yet.** `ver/superman/mame_scripts/dump_burst.lua` + captures 20 MAME scenes 300 frames apart (palette, spriteylow, spritectrl, + OBJ-RAM, plus `screen.png`), but the FPGA side still needs `rest2bin.sh`, + `simfile:` bindings in `mem.yaml` and a NOMAIN replay branch. +- **No hardware build has been attempted**; timing closure is unknown. + +## Video timing + +The X1-001 divides the 16 MHz oscillator to an 8 MHz dot clock over a +512x272 grid: 15.625 kHz horizontal, 57.4449 Hz vertical, matching the +driver's 57.43. MAME's `set_size(52*8, 32*8)` is the usual Seta +approximation — at MAME's own refresh it implies a 6.117 MHz dot clock and a +14.7 kHz line rate, which no JAMMA monitor would lock to. + +The H and V totals are **not** derivable from the schematic: the dividers are +inside the X1-001 die and the board carries no counter chain. The only +measured figures in the MAME driver (58 Hz / 15.22 kHz, line 217) belong to a +P0-057A board, not to Superman, whose value has no measurement behind it. +These numbers are due a scope check on real hardware. + +## MRA header + +One byte, three bits, carrying the board type only: + +| bit | name | sets | +|---|---|---| +| 0[0] | `p039a` | superman ×3 | +| 0[1] | `p051a` | daisenpu, twinhawk ×2 | +| 0[2] | `p057a` | gigandes ×2, ballbros, kyustrkr | + +Everything else is derived in HDL, because it all follows the board split: +the C-chip, the direct input port (`~p039a`), the interrupt level (`~p039a`) +and the sprite Y offset (`p057a ? -0x0a : -0x12`). + +## Documentation + +`doc/` holds primary sources only — the MAME driver and device sources +(`taito_x.cpp`, `seta001.cpp`, `taitosnd.cpp`, `taitocchip.cpp`) and photos of +the P0-039A and P0-057a board. The Superman schematics are the maker's IP and are kept +out of the repo. diff --git a/cores/taitox/cfg/files.yaml b/cores/taitox/cfg/files.yaml new file mode 100644 index 000000000..fafbbe054 --- /dev/null +++ b/cores/taitox/cfg/files.yaml @@ -0,0 +1,42 @@ +taitox: + - get: [ "*.v" ] + +kiwi: + - get: + - jtkiwi_gfx.v + - jtkiwi_obj.v + - jtkiwi_draw.v + - jtkiwi_tilemap.v + +rastan: + - get: + - jtrastan_pc060.v + +jttc0030cmd: + +jtframe: + - get: + - jtframe_ff.v + - jtframe_8bit_reg.v + - jtframe_edge.v + - from: ram + get: + - jtframe_ram.v + - jtframe_dual_ram.v + - jtframe_dual_ram16.v + - jtframe_obj_buffer.v + - jtframe_prom.v + - from: clocking + get: + - jtframe_sync.v + - from: video + get: + - jtframe_vtimer.v + - jtframe_blank.v + - jtframe_scroll.yaml + - from: cpu + get: + - jtframe_z80.yaml + - jtframe_m68k.yaml + +jt12: diff --git a/cores/taitox/cfg/macros.def b/cores/taitox/cfg/macros.def new file mode 100644 index 000000000..fc1c32e84 --- /dev/null +++ b/cores/taitox/cfg/macros.def @@ -0,0 +1,41 @@ +CORENAME=JTTAITOX + +JTFRAME_PXLCLK=8 +JTFRAME_RATE=57.44 +JTFRAME_WIDTH=384 +JTFRAME_HEIGHT=240 +JTFRAME_COLORW=5 + +JTFRAME_VERTICAL + + +JTFRAME_BUTTONS=3 +JTFRAME_JOY_RLDU + +RAM_START=0x080000 +JTFRAME_BA1_START=0x090000 +PCM_START=0x0A0000 +JTFRAME_BA2_START=0x200000 +JTFRAME_BA3_START=0x400000 +JTFRAME_PROM_START=0x480000 + +JTFRAME_HEADER=16 + +JTFRAME_STEREO + +# --------------------------------------------------------------------------- +# Debug +# --------------------------------------------------------------------------- +JTFRAME_STATUS +debug JTFRAME_IOCTL_RD+=4096 +debug JTFRAME_IOCTL_RD+=16384 +debug JTFRAME_IOCTL_RD+=1024 + +[mister] +JTFRAME_ARX=4 +JTFRAME_ARY=3 + +[mist] +-JTFRAME_CREDITS +NOCREDITS +JTFRAME_OSD_NOCREDITS diff --git a/cores/taitox/cfg/mame2mra.toml b/cores/taitox/cfg/mame2mra.toml new file mode 100644 index 000000000..0fa7629b0 --- /dev/null +++ b/cores/taitox/cfg/mame2mra.toml @@ -0,0 +1,60 @@ +[global] +author=["jotego","Andrea Bogazzi"] +zip.alt="cchip.zip" + +[parse] +sourcefile=[ "taito_x.cpp" ] + +[parse.skip] +setnames=[ "daisenpu", "twinhawk", "twinhawku" ] + +[buttons] +names=[ + # Superman: schematic-verified on the PCB — PA4 = Punch, PA5 = Kick + { machines=["superman","supermanu","supermanj"], names="Punch,Kick" }, + { machines=["gigandes","gigandesa"], names="Shot,Bomb" }, + { machines=["ballbros"], names="Action,-" }, + { machines=["kyustrkr"], names="Short Pass,Long Pass,Shoot" }, +] + +[dipsw] +delete=[{names=["Unused","Unknown"]}] +rename=[ + {name="Price to Continue", to="Continue" }, +] +# kyustrkr is rendered rotated by 180, so we set flip on by default to make it correct. +defaults=[ + { setname="kyustrkr", value="df,ba" }, +] + +# Board type, one bit each. +# p039a Taito Corp. superman x3 C-chip, VBL level 6 +# p051a Taito Corp. daisenpu, twinhawk x2 PC060HA + YM2151 +# p057a East Technology gigandes x2, ballbros, kyustrkr +# Derived in HDL rather than stored: +# direct_in = ~p039a taitox_state reads IN0/1/2 at 900000 +# irq2 = ~p039a only the C-chip class installs the L6 ISR +# fg_yoff = p057a ? -0x0a : -0x12 East Tech vs Taito, hardcoded in _video.v +[header] +registers=[ + { name="p039a", pos="0[0]", desc="Taito P0-039A (C-chip)", values=[{ setnames=["superman","supermanu","supermanj"], value=1 }] }, + { name="p051a", pos="0[1]", desc="Taito P0-051A (PC060HA + YM2151)", values=[{ setnames=["daisenpu","twinhawk","twinhawku"], value=1 }] }, + { name="p057a", pos="0[2]", desc="East Technology P0-057A", values=[{ setnames=["gigandes","gigandesa","ballbros","kyustrkr"], value=1 }] }, +] + +[ROM] +regions = [ + { name="maincpu", width=16, reverse=true, no_offset=true }, + { name="audiocpu", start="JTFRAME_BA1_START" }, + { name="ymsnd:adpcma", rename="adpcma", start="PCM_START" }, + { setnames=["ballbros","kyustrkr"], name="gfx1", start="JTFRAME_BA2_START", width=32, no_offset=true, sequence=[1,3,0,2] }, + { name="gfx1", start="JTFRAME_BA2_START", width=16, no_offset=true }, + { name="ymsnd:adpcmb", rename="adpcmb", start="JTFRAME_BA3_START" }, + { name="cchip_bios", setnames=["superman","supermanu","supermanj"], start="JTFRAME_PROM_START", rom_len=0x1000, files=[ { name="cchip_upd78c11.bin", crc="43021521", size=0x1000 } ] }, + { name="cchip:cchip_eprom", rename="cchip_eprom", rom_len=0x2000 }, +] + +order = [ + "maincpu", "audiocpu", "adpcma", "gfx1", "adpcmb", + "cchip_bios", "cchip_eprom" +] diff --git a/cores/taitox/cfg/mem.yaml b/cores/taitox/cfg/mem.yaml new file mode 100644 index 000000000..03965edda --- /dev/null +++ b/cores/taitox/cfg/mem.yaml @@ -0,0 +1,102 @@ +params: + - { name: PCM_OFFSET, value: "(`PCM_START-`JTFRAME_BA1_START)>>1" } + - { name: RAM_OFFSET, value: "(`RAM_START)>>1" } + +clocks: + clk: + - freq: 8 MHz + gate: [ adpcma, adpcmb ] + outputs: + - cen8 + - freq: 4 MHz + gate: [ snd ] + outputs: + - snd_cen + +audio: + rsum: 10k + channels: + - { name: fm, module: jt12, rsum: 10k } + +sdram: + banks: + - buses: + # 68000 work RAM, f00000-f03fff. In SDRAM rather than BRAM so the + # core fits the smaller MiST/SiDi devices; same trick as rastan. + - name: ram + addr_width: 14 + data_width: 16 + din: cpu_dout + rw: true + offset: RAM_OFFSET + - name: main + addr_width: 19 + data_width: 16 + - buses: + - name: snd + addr_width: 16 + data_width: 8 + - name: adpcma + addr_width: 19 + data_width: 8 + offset: PCM_OFFSET + - buses: + - name: scr + addr_width: 21 + data_width: 32 + - name: obj + addr_width: 21 + data_width: 32 + - buses: + - name: adpcmb + addr_width: 19 + data_width: 8 + +bram: + # Palette RAM behind the X1-006. The chip only receives 68k A9..A1 + # (sheet 4, block 55 pins 35-43) + - name: pal + addr_width: 10 + data_width: 16 + addr: main_addr[9:1] + din: cpu_dout + rw: true + ioctl: + save: true + order: 0 + unless: [ JTFRAME_RELEASE ] + dual_port: + name: palrd + dout: pal_data + + # X1-001 internal RAM + - name: yram + addr_width: 10 + data_width: 8 + addr: main_addr[10:1] + din: cpu_dout[7:0] + rw: true + ioctl: + save: true + order: 1 + unless: [ JTFRAME_RELEASE ] + dual_port: + name: col + dout: col_data + + # X1-001 external OBJ RAM: the two 4364 SRAMs on schematic sheet 3, + # 8K x 16 = 16 kB at e00000-e03fff. + - name: dma + addr_width: 14 + data_width: 16 + rw: true + ioctl: + save: true + order: 2 + unless: [ JTFRAME_RELEASE ] + dual_port: + name: code + dout: code_dout + + - { name: cchip_mask, addr_width: 12, data_width: 8, prom: true } + - { name: cchip_eprom, addr_width: 13, data_width: 8, prom: true } diff --git a/cores/taitox/cfg/msg b/cores/taitox/cfg/msg new file mode 100644 index 000000000..895805f8f --- /dev/null +++ b/cores/taitox/cfg/msg @@ -0,0 +1,123 @@ +\BTAITO System X\W FPGA Core +by \GANDR\WEA BOG\RAZZI\W +on the \RJTCORES\W framework +by JOTEGO + community +Based on original schematics +previous RE work on taito chips + +Reviewed by Jose Tejada + +\B______ \RDIRECTORS\B _______\W +80's spaceman Bender +Boogermann Cornelle Janse +DJ Lethal Fabio Michelin +Andrea Bogazzi Filip Kindt + Frederic Mahe + Fulvio Venturelli +Georgi Rakidov James D +Jent Ksenia Anastasia +Luis Massot M. Fornasini +Martin Birkeldh Martin Donlon +Michael Yount Skutis +Trent Reznor Tulio Adriano +edonkey2000 f3bandit +kccheng Gu Youqiang + + + \BThanks to\W +\R Alexander Facchini +\RAlfred N Alon Faifer +\RBigRedPimp Blue Abs +\RBob Gallardo Brian Sallee +\RCharles Dreiss Conor Nash +\RDaithi Dan Avedikian +\RDaniel Bauza Danny Garfield +\RDrewtoriousFGC ER +\RHalla Harper Reed +\R Henrik Nordstrom +\RIvan Perez Jacob Jewell +\RJim Sprigler Jim Weinhart +\RJo Tomiyori Joe Castle +\RKyle Mickley LaNaveRETRO +\RMatt Hayden Mom +\RMycah Mattox Nick Chapman +\RPD Lee Pelayo Marinas +\RPeter Vessenes R. Martinazzo +\RRafael Vitorio Rautz +\RRenaissance 2K RetroWilly +\RRobert Moran Sayit BELET +\RStrong Badam Tarnjeet Bhachu +\RTej Bilkhu TheJesusFish +\RZom aoalej +\Rblktiger brad +\Rdannahan oldmanoftheSEA +\Rpoppunmori qwupz + + \B_________ AND __________\W +ARCADEAGES Adam Davis +Adrian Nabarro Anders Rensberg +Andy Palmer Andyways +Ayoub Zebian Blackstar +Bryan Adams Carrboroman +Chi Wai Tran Chris Doyle +Chris Harvey Christian +DMG Dan Bayley +Dana Ross Daniel Cortes +Darren Chell Dave Sasser +David Moylan Dean Winger +Don Gafford Ed Balan +Eduardo Javier Edward Rana +Fred Jorge Gus Douboulidis + Heihachi + Hendrik Osterholz + INAKI ECHEVARRIA +Ian Court JFRoco +JPS (RetroFPGA) James Stroup +Jeffrey Haas Jo le Zef +Joe Tassone JoeAverage +Joeri van John Casey +John Silva Juan Sandoval +JuanRa Keith F. Kelly +Krycek7o2 Leslie Law + Lukas Hinterleitner +M. Ferguson MakeshiftMoney +Marcelo C. Marcus Sid +Martin DiPalma Matt_Rant + Matthew Young + Michael Blackman + Michael Ferguson + Michael Fleisher +Michael Johnson Mike Phan +Miles Morales Nima +Nunzio Mannino Oliver Jaksch +Oscar Laguna Per Sweden +PsyFX RetroGameBro +Retro_Brewz Retroludo +Richard MS Rob Jenkins +Robert MacLean Roman Buser +Shane Lynch Simon +Steven Wilson The Collector +Theodore Huber Thompson Orcino +Tony Richardson Torren Beitler +Ultrarobotninja Vitor Duarte +Younghoon Gong albertprime +amoore2600 elrobertocarlos +eskwadrat hyp36rmax +nullobject qzxcvbn +ultimatekd + +\WS\RA\GL\BA\WM\RA\GN\BD\RE\GR + ________________________ + + - Beta version - + Do not distribute + + + - MiSTer - + Place jtbeta.zip + in games/mame + do not unzip it + + - A. Pocket - + Unzip jtbeta.zip into + Assets/jtpatreon/common diff --git a/cores/taitox/doc/gigandes-back.webp b/cores/taitox/doc/gigandes-back.webp new file mode 100644 index 000000000..62645e019 Binary files /dev/null and b/cores/taitox/doc/gigandes-back.webp differ diff --git a/cores/taitox/doc/gigandes-front-2.webp b/cores/taitox/doc/gigandes-front-2.webp new file mode 100644 index 000000000..968507209 Binary files /dev/null and b/cores/taitox/doc/gigandes-front-2.webp differ diff --git a/cores/taitox/doc/gigandes-front.webp b/cores/taitox/doc/gigandes-front.webp new file mode 100644 index 000000000..1bfe509d1 Binary files /dev/null and b/cores/taitox/doc/gigandes-front.webp differ diff --git a/cores/taitox/doc/gigantes-back-2.webp b/cores/taitox/doc/gigantes-back-2.webp new file mode 100644 index 000000000..d55467801 Binary files /dev/null and b/cores/taitox/doc/gigantes-back-2.webp differ diff --git a/cores/taitox/doc/seta001.cpp b/cores/taitox/doc/seta001.cpp new file mode 100644 index 000000000..4c3caee24 --- /dev/null +++ b/cores/taitox/doc/seta001.cpp @@ -0,0 +1,502 @@ +// license:BSD-3-Clause +// copyright-holders:Luca Elia, David Haywood + /* + emulation of Seta sprite chips + X1-001A X1-002A (SDIP64) + + these always seem to be used as a pair, some board have been seen without the + 'A', so it's probably a chip revision / bugfix. + + used by: + + seta.cpp + taito_x.cpp + tnzs.cpp + srmp2.cpp + champbwl.cpp + cchance.cpp + thedealr.cpp + + note: the data bus is almost certainly 8-bit, dating back to the earliest + hardware the games were used on. the RAM arrangements changes + slightly between games depending on how the RAM is hooked up to the + main cpu. + + 'y' low bits are NEVER buffered? + + TODO: + use getter callbacks in drivers for spriterams rather than allocating memory + here, then we won't have to allocate extra memory for seta.cpp games which + appear to have 0x800 bytes of RAM that isn't connected to the sprite chip + between the banks. + + This should implement device_video_interface, since it generates the vertical + and horizontal blanking and sync signals from a master clock. + + understand sprite limits / how sprite 0 sometimes must be skipped, maybe + layers being enabled counts against limits? maybe some chip revisions skip + the first sprite? see note in device_start + + understand why we need offset kludges for some games, they can even differ + from layer to layer + + */ + +#include "emu.h" +#include "seta001.h" +#include "screen.h" + + +DEFINE_DEVICE_TYPE(SETA001_SPRITE, seta001_device, "seta001", "Seta SETA001 Sprites") + +seta001_device::seta001_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, SETA001_SPRITE, tag, owner, clock) + , device_gfx_interface(mconfig, *this) + , m_gfxbank_cb(*this) + , m_fg_flipxoffs(0) + , m_fg_noflipxoffs(0) + , m_fg_flipyoffs(0) + , m_fg_noflipyoffs(0) + , m_bg_flipyoffs(0) + , m_bg_noflipyoffs(0) + , m_bg_flipxoffs(0) + , m_bg_noflipxoffs(0) + , m_colorbase(0) + , m_spritelimit(0x1ff) + , m_transpen(0) +{ +} + +void seta001_device::device_start() +{ + m_spriteylow = std::make_unique(0x300); // 0x200 low y + 0x100 bg stuff + m_spritecodelow = std::make_unique(0x2000); + m_spritecodehigh = std::make_unique(0x2000); + + /* chukatai draws a column on the left from uninitialized RAM which causes garbage + + the reason for this is because the m_spriteylow only gets populated from 0x000 to 0x17d + with the remainder of the ram (0x17e - 0x1ff) never being written to. + + If we initialize ram to 0xff it has a single line in the top left instead, but + the PCB has no error at all, initializing to 0xf8 is better, but unlikely from a hardware + perspective. + + jjsquawk has a garbage tile in the bottom left instead, but in this case the entire + m_spriteylow is initalized (to 0), but sprite entry 0 for the other tables is never + written to, again meaning it picks up whatever we clear the RAM to as positional + values. + + we can't simply skip sprite 0 as other games (mostly tnzs.cpp ones, eg. kabukiz) rely + on it being rendered, even if a number of seta.cpp games specifically avoid it. + + maybe other components on the board determine the sprite start / end limits on a per + game basis? + + */ + + memset(m_spritectrl,0xff,4); + memset(m_spriteylow.get(),0xff,0x300); + memset(m_spritecodelow.get(),0xff,0x2000); + memset(m_spritecodehigh.get(),0xff,0x2000); + + m_bgflag = 0x00; + + m_gfxbank_cb.resolve(); + + save_item(NAME(m_bgflag)); + save_item(NAME(m_spritectrl)); + save_pointer(NAME(m_spriteylow),0x300); + save_pointer(NAME(m_spritecodelow),0x2000); + save_pointer(NAME(m_spritecodehigh),0x2000); +} + +void seta001_device::device_reset() +{ +} + +uint16_t seta001_device::spritectrl_r16(offs_t offset) +{ + return m_spritectrl[offset]; +} + +void seta001_device::spritectrl_w16(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if (ACCESSING_BITS_0_7) + { + m_spritectrl[offset] = data; + } +} + +uint8_t seta001_device::spritectrl_r8(offs_t offset) +{ + return m_spritectrl[offset]; +} + +void seta001_device::spritectrl_w8(offs_t offset, uint8_t data) +{ + m_spritectrl[offset] = data; +} + +uint16_t seta001_device::spriteylow_r16(offs_t offset) +{ + return m_spriteylow[offset]; +} + +void seta001_device::spriteylow_w16(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if (ACCESSING_BITS_0_7) + { + m_spriteylow[offset] = data; + } +} + +uint8_t seta001_device::spriteylow_r8(offs_t offset) +{ + return m_spriteylow[offset]; +} + +void seta001_device::spriteylow_w8(offs_t offset, uint8_t data) +{ + m_spriteylow[offset] = data; +} + + +uint8_t seta001_device::spritecodelow_r8(offs_t offset) +{ + return m_spritecodelow[offset]; +} + +void seta001_device::spritecodelow_w8(offs_t offset, uint8_t data) +{ + m_spritecodelow[offset] = data; +} + +uint8_t seta001_device::spritecodehigh_r8(offs_t offset) +{ + return m_spritecodehigh[offset]; +} + +void seta001_device::spritecodehigh_w8(offs_t offset, uint8_t data) +{ + m_spritecodehigh[offset] = data; +} + +uint16_t seta001_device::spritecode_r16(offs_t offset) +{ + uint16_t ret = m_spritecodelow[offset]; + ret |= m_spritecodehigh[offset] << 8; + return ret; +} + +void seta001_device::spritecode_w16(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if (ACCESSING_BITS_0_7) m_spritecodelow[offset] = data & 0x00ff; + if (ACCESSING_BITS_8_15) m_spritecodehigh[offset] = (data & 0xff00)>>8; +} + +void seta001_device::spritebgflag_w8(uint8_t data) +{ + m_bgflag = data; +} + +/*************************************************************************** + + + Sprites Drawing + + +***************************************************************************/ + +/* + +these mostly seem to be controlling the tilemap part of the chip + +twineagl: 10 2d 0f 10 (ship) +tndrcade: 58 2d 07 18 (start of game - yes, flip on!) +arbalest: 18 2d 0f 10 (logo) +metafox : 18 21 0f f0 (bomb) +zingzip : 10 2c 00 0f (bomb) +wrofaero: 10 21 00 ff (test mode) +thunderl: 10 6c 00 ff (always?) +krzybowl: 11 28 c0 ff (game) +kiwame : 16 21 7f 00 (logo) +oisipuzl: 59 20 00 00 (game - yes, flip on!) +superman: 10 21 07 38 (game) +twineagl: 00 27 00 0f (test mode) +doraemon: 19 2a 00 03 (always) +srmp2: 1e 20 xx xx +tnzs: 1a 20 xx xx + +format + byte 0 byte 1 byte 2 byte3 + -f-e uUss -Bb- cccc ---- ---- ---- ---- + + f = flipy + e = possible enable (only disabled in twineagl test mode? check if it needs sprites) + u = sometimes set + U = sometimes set (srmp2) + s = start column + B = buffering control - toggles often (kabukiz doesn't seem to use these like the other games) + b = buffering control + c = number of columns, 0x0 = disabled, 0x01 = 16 columns 0x2 = 2 coluns ... 0xf = 15 columns + + bytes 2 and 3 get set in a bitwize way in the tnzs driver games while horizontal scrolling happens, dependong on how + far we've scrolled, what they actually do is unclear. + +*/ + + + + +void seta001_device::draw_background( bitmap_ind16 &bitmap, const rectangle &cliprect, int bank_size) +{ + int transpen; + + int offs, col; + int xoffs, yoffs; + + int const total_color_codes = gfx(0)->colors(); + + int const ctrl = m_spritectrl[0]; + int const ctrl2 = m_spritectrl[1]; + + bool const flip = BIT(ctrl, 6); + int numcol = ctrl2 & 0x0f; + + int scrollx, scrolly; + + uint32_t upper; + + const uint8_t* scrollram = &m_spriteylow[0x200]; + + /* Sprites Banking and/or Sprites Buffering */ + uint16_t bank = ( ((ctrl2 ^ (~ctrl2<<1)) & 0x40) ? bank_size : 0 ); // bank_size = 0x800 + + int const max_y = 0xf0; + + int startcol = 0; + + if (ctrl & 0x01) + startcol += 0x4; + + if (ctrl & 0x02) + startcol += 0x8; + + xoffs = flip ? m_bg_flipxoffs : m_bg_noflipxoffs; + yoffs = flip ? m_bg_flipyoffs : m_bg_noflipyoffs; + + if (m_bgflag & 0x80) + transpen = -1; + else + transpen = m_transpen; + + if (numcol == 1) + numcol = 16; + + upper = m_spritectrl[2] + m_spritectrl[3] * 256; + + for (col = 0; col < numcol; col++) + { + scrollx = scrollram[col * 0x10 + 4]; + scrolly = scrollram[col * 0x10]; + + /* draw this column */ + for ( offs = 0 ; offs < 0x20; offs += 1 ) + { + int i = ((col+startcol)&0xf) * 32 + offs; + + int code = ((m_spritecodehigh[i+0x400+bank]) << 8) | m_spritecodelow[i+0x400+bank]; + int color =((m_spritecodehigh[i+0x600+bank]) << 8) | m_spritecodelow[i+0x600+bank]; + + int flipx = code & 0x8000; + int flipy = code & 0x4000; + + int sx = scrollx + xoffs + (offs & 1) * 16; + int sy = -(scrolly + yoffs) + (offs / 2) * 16; + + if (upper & (1 << col)) sx -= 256; + + if (flip) + { + sy = max_y - sy; + flipx = !flipx; + flipy = !flipy; + } + + color = ( color >> (16-5) ) % total_color_codes; + code &= 0x3fff; + + gfx(0)->transpen(bitmap,cliprect, + code, + color, + flipx,flipy, + ((sx) & 0x1ff),((sy) & 0x0ff), + transpen); + + gfx(0)->transpen(bitmap,cliprect, + code, + color, + flipx,flipy, + ((sx) & 0x1ff)-512,((sy) & 0x0ff), + transpen); + + gfx(0)->transpen(bitmap,cliprect, + code, + color, + flipx,flipy, + ((sx) & 0x1ff),((sy) & 0x0ff)-256, + transpen); + + gfx(0)->transpen(bitmap,cliprect, + code, + color, + flipx,flipy, + ((sx) & 0x1ff)-512,((sy) & 0x0ff)-256, + transpen); + + } + } +} + + +void seta001_device::draw_foreground( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int bank_size) +{ + int const screenflip = (m_spritectrl[0] & 0x40) >> 6; + int const ctrl2 = m_spritectrl[1]; + + int const total_color_codes = gfx(0)->colors(); + + uint8_t *char_pointer = &m_spritecodelow[0x0000]; + uint8_t *ctrl_pointer = &m_spritecodehigh[0x0000]; + uint8_t *x_pointer = &m_spritecodelow[0x0200]; + uint8_t *color_pointer = &m_spritecodehigh[0x0200]; + + // note that drgnunit, stg and qzkklogy run on the same board, yet they need different alignment + int xoffs = screenflip ? m_fg_flipxoffs : m_fg_noflipxoffs; + int yoffs = screenflip ? m_fg_flipyoffs : m_fg_noflipyoffs; + + if ((ctrl2 ^ (~ctrl2 << 1)) & 0x40) + { + char_pointer += bank_size; + x_pointer += bank_size; + ctrl_pointer += bank_size; + color_pointer += bank_size; + } + + int const max_y = screen.height(); + + /* Draw up to 512 sprites, mjyuugi has glitches if you draw them all.. */ + for (int i = m_spritelimit; i >= 0; i--) + { + int code, color, sx, sy, flipx, flipy; + + code = char_pointer[i] + ((ctrl_pointer[i] & 0x3f) << 8); + color = (color_pointer[i] & 0xf8) >> 3; + + sx = x_pointer[i] - ((color_pointer[i] & 1) << 8); + sy = (m_spriteylow[i] & 0xff); + flipx = ctrl_pointer[i] & 0x80; + flipy = ctrl_pointer[i] & 0x40; + + if (!m_gfxbank_cb.isnull()) code = m_gfxbank_cb(code, color_pointer[i]); + + color %= total_color_codes; + + color += m_colorbase; + + if (screenflip) + { + sy = max_y - sy + +(screen.height() - (screen.visible_area().max_y + 1)); + flipx = !flipx; + flipy = !flipy; + } + + gfx(0)->transpen(bitmap,cliprect, + code, + color, + flipx,flipy, + ((sx + xoffs)&0x1ff), + max_y - ((sy + yoffs) & 0x0ff),m_transpen); + + /* wrap around x */ + gfx(0)->transpen(bitmap,cliprect, + code, + color, + flipx,flipy, + ((sx + xoffs)&0x1ff) - 512, + max_y - ((sy + yoffs) & 0x0ff),m_transpen); + + + gfx(0)->transpen(bitmap,cliprect, + code, + color, + flipx,flipy, + ((sx + xoffs)&0x1ff), + max_y - ((sy + yoffs) & 0x0ff)-256,m_transpen); + + /* wrap around x */ + gfx(0)->transpen(bitmap,cliprect, + code, + color, + flipx,flipy, + ((sx + xoffs)&0x1ff) - 512, + max_y - ((sy + yoffs) & 0x0ff)-256,m_transpen); + + } +} + + + +void seta001_device::setac_eof() +{ + // is this handling right? + // it differs to tnzs, and thundercade has sprite flickering issues (not related to the devicification) + + int const ctrl2 = m_spritectrl[1]; + + if (~ctrl2 & 0x20) + { + if (ctrl2 & 0x40) + { + memcpy( &m_spritecodelow[0x0000], &m_spritecodelow[0x1000],0x800); + memcpy(&m_spritecodehigh[0x0000],&m_spritecodehigh[0x1000],0x800); + } + else + { + memcpy( &m_spritecodelow[0x1000], &m_spritecodelow[0x0000],0x800); + memcpy(&m_spritecodehigh[0x1000],&m_spritecodehigh[0x0000],0x800); + } + } +} + +void seta001_device::tnzs_eof( void ) +{ + int const ctrl2 = m_spritectrl[1]; + if (~ctrl2 & 0x20) + { + // note I copy sprites only. setac implementation also copies the "floating tilemap" + if (ctrl2 & 0x40) + { + memcpy( &m_spritecodelow[0x0000], &m_spritecodelow[0x0800], 0x0400); + memcpy(&m_spritecodehigh[0x0000], &m_spritecodehigh[0x0800], 0x0400); + } + else + { + memcpy( &m_spritecodelow[0x0800], &m_spritecodelow[0x0000], 0x0400); + memcpy(&m_spritecodehigh[0x0800], &m_spritecodehigh[0x0000], 0x0400); + } + + // and I copy the "floating tilemap" BACKWARDS - this fixes kabukiz + memcpy( &m_spritecodelow[0x0400], &m_spritecodelow[0x0c00], 0x0400); + memcpy(&m_spritecodehigh[0x0400], &m_spritecodehigh[0x0c00], 0x0400); + } + +} + +void seta001_device::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int bank_size) +{ + draw_background(bitmap, cliprect, bank_size); + draw_foreground(screen, bitmap, cliprect, bank_size); +} diff --git a/cores/taitox/doc/superman-back.webp b/cores/taitox/doc/superman-back.webp new file mode 100644 index 000000000..c9a13f290 Binary files /dev/null and b/cores/taitox/doc/superman-back.webp differ diff --git a/cores/taitox/doc/superman-front.webp b/cores/taitox/doc/superman-front.webp new file mode 100644 index 000000000..e71275561 Binary files /dev/null and b/cores/taitox/doc/superman-front.webp differ diff --git a/cores/taitox/doc/taito_x.cpp b/cores/taitox/doc/taito_x.cpp new file mode 100644 index 000000000..eb6b3d166 --- /dev/null +++ b/cores/taitox/doc/taito_x.cpp @@ -0,0 +1,1430 @@ +// license:BSD-3-Clause +// copyright-holders:Howie Cohen, Yochizo, Bryan McPhail, Nicola Salmoria +// thanks-to:Richard Bush +/*************************************************************************** + + +Taito X-system + +driver by Richard Bush, Howie Cohen and Yochizo + +25th Nov 2003 +video merged with video/seta.cpp + + +Supported games: +------------------------------------------------------------------------- + Name Company Year PCB ref. + Superman Taito Corp. 1988 P0-039A + Twin Hawk (World) Taito Corp. Japan 1988 P0-051A + Twin Hawk (US) Taito America Corp. 1988 P0-051A + Daisenpu (Japan) Taito Corp. 1988 P0-051A + Gigandes East Technology Corp. 1989 P0-057A + Last Striker East Technology Corp. 1989 P0-057A + P1-046A + Balloon Brothers East Technology Corp. 199? P0-057A + P1-046A + + +This file contains routines to interface with the Taito Controller Chip +(or "Command Chip") version 1. It's currently used by Superman. + +Memory map: +---------------------------------------------------- + 0x000000 - 0x07ffff : ROM + 0x300000 ?? + 0x400000 ?? + 0x500000 - 0x50000f : Dipswitches a & b, 4 bits to each word + 0x600000 ?? 0, 10, 0x4001, 0x4006 + 0x700000 ?? + 0x800000 - 0x800003 : sound chip + 0x900000 - 0x900fff : c-chip shared RAM space + 0xb00000 - 0xb00fff : palette RAM, words in the format xRRRRRGGGGGBBBBB + 0xc00000 ?? + 0xd00000 - 0xd007ff : video attribute RAM + 0000 - 03ff : sprite y coordinate + 0400 - 07ff : tile x & y scroll + 0xe00000 - 0xe00fff : object RAM bank 1 + 0000 - 03ff : sprite number (bit mask 0x3fff) + sprite y flip (bit mask 0x4000) + sprite x flip (bit mask 0x8000) + 0400 - 07ff : sprite x coordinate (bit mask 0x1ff) + sprite color (bit mask 0xf800) + 0800 - 0bff : tile number (bit mask 0x3fff) + tile y flip (bit mask 0x4000) + tile x flip (bit mask 0x8000) + 0c00 - 0fff : tile color (bit mask 0xf800) + 0xe01000 - 0xe01fff : unused(?) portion of object RAM + 0xe02000 - 0xe02fff : object RAM bank 2 + 0xe03000 - 0xe03fff : unused(?) portion of object RAM + +Interrupt: +---------------------------------------------------- + IRQ level 6 : Superman + IRQ level 2 : Daisenpu, Balloon Brothers, Gigandes + +Screen resolution: +---------------------------------------------------- + 384 x 240 : Superman, Balloon Brothers, Gigandes + 384 x 224 : Daisenpu + +Sound chip: +---------------------------------------------------- + YM2610 x 1 : Superman, Balloon Brothers, Gigandes + YM2151 x 1 : Daisenpu + + +Gigandes +-------- + + - Gigandes has background tile glitches on the demo of cave + stage (the last one before it does demo of level 1 again). + It seems to be rapidly switching between two different + background layers. This may be because the game has put + different tiles in bank 0 and bank 1 (which alternate each + frame). The other strangeness is that the background is not + scrolling. So chances are the graphics chip emulation is + flawed. + + When this cuts to hiscore screen there is flickering white + tilemap garbage beneath. These leftover tiles have not been + cleared from $e00800-bff (but they have been from $e02800). + So alternate 2 frames display the bank with garbage tiles and + the one without. + + Probably some control register should be keeping the graphics + chip in the cleared bank, so the garbage is never visible. + Separate bank control for sprite / tile layers ? + Maybe this effect is also desired during the cave stage. + + +TODO +---- + + - Fix known problems + - Any other games that worked on this board? + - What is correct date for Ballbros? Two different ones + appear in this driver! + + +Dumpers Notes +------------- + +Details of custom chip numbers on Superman would be welcome. + +Daisenpu +-------- + +(c)1989 Toaplan/Taito +Taito X System + +K1100443A MAIN PCB +J1100188A X SYSTEM +P0-051A + +CPU : 68000 (Toshiba TMP68000N-8) +Sound: Z80 (Sharp LH0080A) + YM2151+YM3012 +OSC : 16.000MHz + +B87-01 (Mask ROMs, read as 27C4200) +B87-02 +B87-03 +B87-04 +(These 4 images could be wrong) + +B87-05 (M5M27C101K) - Main PRG +B87-06 (M5M27C101K) - Main PRG +B87-07 (27C256) - Sound PRG + +This board uses SETA's custom chips. +X1-001A, X1-002A, X1-004, X1-006, X1-007. +Arkanoid II uses X1-001, X1-002, X1-003, X1-004. + +Control: 8-way Joystick + 2-buttons + + +Gigandes +-------- + +East Technology 1989 + +P0-057A + + 68000-8 1 2 51832 3 4 51832 + +6264 16MHz +5 +10 8 +11 TC0140SYT X1-001A X1-002A 7 + 9 +YM2610 6 + Z80A + X1-004 X1-006 + X1-007 + + +Balloon Brothers +---------------- + +East Technology 1992 + + 68000-8 10A 51832 5A 51832 + + 6264 2063 + 8D 2063 SWB SWA + EAST-10 16MHz + EAST-11 Taito TC0140SYT + YM2610 3 + Z80A SETA X1-001A SETA X1-002A + + SETA X1-004 2 + 1 + 0 + + +Kyuukyoku no Striker +East Technology/Taito, 1989 + +This game runs on Seta hardware and also using one Taito custom chip. + + +PCB Layout +---------- + +P0-057A +|------------------------------- | +| YM2610 IC.18D 6264 | +|YM3016 | +| Z80 TC0140SYT 68000 | +| X1-004 X1-001A PE.9A | +|J X1-002A 6264 62256 | +|A 6264 | +|M 16MHz PO.4A | +|M X1-007 DSW1 62256 | +|A X1-006 DSW2 | +| M-8-3 | +|M-8-5 M-8-4 M-8-2 | +| M-8-1 | +| M-8-0 | +|--------------------------------| + +Notes: + All M-8-x ROMs are held on a plug-in sub-board. + The sub-board has printed on it "East Technology" and has PCB Number P1-046A + + 68000 clock: 8.000MHz + Z80 clock: 4.000MHz + YM2610 clock: 8.000MHz + Vsync: 58Hz + HSync: 15.22kHz + + +Superman +Taito, 1988 + +PCB Layout +---------- + +J1100145A +K1100331A +P0-039A +|---------------------------------------------------| +| VOL B50-07.U34 DSWB DSWA | +| 4558 YM2610 Z80 62256 Z80| +| 4558 YM3014 | +| | +| B06-13 | +| (PAL) | +| | +| | +| 6264 B50-06.U3| +|J TESTSW | +|A | +|M | +|M | +|A B06-101 | +| (PAL) | +| Z80| +| X1-001A | +| | +| X1-004 | +| X1-002A 12MHz | +| | +| B50-01.U46 B50-03.U39 | +| X1-006 6264 | +|X1-007 B50-02.U43 B50-04.U35 B50-05.U1| +|---------------------------------------------------| +Notes: + All Z80 CPU's running at 6.000MHz (12/2) + YM2203 running at 3.000Mz (12/4) + VSync 60Hz + +There is another version of Superman using a sub board for the graphics ROMs. +The main program ROMs are the same as existing dumps but there are twice as many +sub board ROMs in identical pairs. They are programmed in byte mode. When read +in byte mode (by tying A-1 high and low), the 00's stripped out and both reads +interleaved together (similar to how byte mode 16Mbit/32Mbit mask ROMs are read), +the resulting ROM dumps match the existing main board ROM dumps exactly! +The byte pin on the sub board connectors is not connected to the main board and +instead, the byte pin on all the sub board ROMs is tied to ground, resulting in +the ROMs being read in byte mode (8-bit). This is in contrast to the main board +graphics ROMs where the byte pin is tied high, resulting in the ROMs being read +in word mode (16-bit). +For each of the pairs of ROMs on the sub board, the data is being read from +the ROMs like this..... + +original ROM -> 8-bit D0-D7 only (High or Low ROM) +------------------------------- +D0 -> D0 LOW ROM +D8 -> D0 HIGH ROM +D1 -> D1 LOW ROM +D9 -> D1 HIGH ROM +D2 -> D2 LOW ROM +D10 -> D2 HIGH ROM +D3 -> D3 LOW ROM +D11 -> D3 HIGH ROM +D4 -> D4 LOW ROM +D12 -> D4 HIGH ROM +D5 -> D5 LOW ROM +D13 -> D5 HIGH ROM +D6 -> D6 LOW ROM +D14 -> D6 HIGH ROM +D7 -> D7 LOW ROM +D15 -> D7 HIGH ROM + +Why this sub board was made instead of using the existing ROM data (B61-14 to -17) +is not understood. +The only explanation is that the lower ROM numbers B61-02 to 05 compared to the +main board ROMs numbers B61-14 to 17 suggests that the sub board version came +first and later Taito realised they could use the same data in 16-bit mode to +save 4 ROMs and thus save costs. + +If any of the sub board ROMs go bad (mask ROM fail often) the way to fix it is to +simply program the original main board data from ROMs B61-14 to B61-17 to AM27C400 +EPROMs and plug them into the sub board. Obviously you will need to plug in TWO +copies of each ROM, otherwise there will be graphical faults. Or just remove the +sub board and program the original ROM data from B61-14 to B61-17 to AM27C400 +EPROMs and put them into the existing 4 sockets on the main board. + + +Sub Board PCB Layout +-------------------- + +K9100202A J9100154A TAITO CORPORATION MADE IN JAPAN +M4300117A SUPER MAN (sticker) +K9100202A SUPER MAN +|-------------------------------| +| B61-02.U37-H | +| B61-02.U37-L U37-CN | +| U38-CN | +| U43-CN | +| B61-03.U38-H U45-CN | +| B61-03.U38-L | +| | +| | +| B61-04.U43-H | +| B61-04.U43-L | +| B61-05.U45-H | +| B61-05.U45-L | +| | +|-------------------------------| +Notes: + B61-xx - All ROMs are 40 pin mask ROMs type 234000, programmed in BYTE mode (8-bit) + Uxx-CN - Connectors joining to the main board where the original + B61-14 - B61-17 ROMs were on the version that does not use a sub board. + +*********************************************************************** + +C-Chip notes +------------ + +Superman seems to be the only game of the four with a c-chip. Daisenpu +appears to use a simple input device with coin counter and lockout in +its place. The East Technology games on this hardware follow Daisenpu. + + +Stephh's notes (based on the game M68000 code and some tests) : + +1) 'superman', 'supermanu' and 'supermanj' + + - Region stored at 0x07fffe.w + - Sets : + * 'superman' : region = 0x0002 + * 'supermanu' : region = 0x0001 + * 'supermanj' : region = 0x0000 + - These 2 games are 100% the same, only region differs ! + - Coinage relies on the region (code at 0x003b8a) : + * 0x0000 (Japan) uses TAITO_COINAGE_JAPAN_OLD + * 0x0001 (US) uses TAITO_COINAGE_US + * 0x0002 (World) uses TAITO_COINAGE_WORLD + - Notice screen only if region = 0x0001 + - I can't tell if it's an ingame bug or an emulation bug, + but boss are far much harder when "Difficulty" Dip Switch + is set to "Easy" : put a watch on 0xf00a76.w for level 1 boss + and you'll notice that MSB is set to 0x01 instead of 0x00 + - 'supermanu' has no Notice screen or FBI logo & statement + + +2) 'twinhawk' + + - No region + - Hard coded coinage table at 0x00b01c and is the same as TAITO_COINAGE_WORLD + - 2 simultaneous players game (player 1 is blue and player 2 is red) + - BUTTON3 is only tested in "Test Mode", not when you are playing + + +3) 'twinhawku' + + - No region + - Hard coded coinage table at 0x00b02a and is different from TAITO_COINAGE_US : + * 2 coins slots with their own coinage + * possible coinage settings : 4C_1C / 3C_1C / 2C_1C / 1C_1C + - Same other notes as for 'twinhawk' + + +4) 'daisenpu' + + - No region + - Hard coded coinage table at 0x00a44a and is the same as TAITO_COINAGE_JAPAN_OLD + - Differences with 'twinhawk' : + * notice screen + * 2 alternate players game (players 1 and 2 are green) + * additional "Cabinet" Dip Switch + * different "Bonus Life" settings + - Same other notes as for 'twinhawk' + + +5) 'gigandes' and 'gigandesa' + + - No region (not a Taito game anyway) + - No notice screen + - Constant bonus life at 50k, 250k then every 200k + - Bogus "Test Mode" in 'gigandesa' (while it is correct for 'gigandes') : + * screen is flipped while it shouldn't and it isn't flipped while it should + * displays cabinet type instead of number of controls + - DSWA bit 4 effect remains unknown but it MUST remain OFF ! + All I know is that this bit is tested in multiple places in the code + and that it hangs the game when you are hit (music continues playing though) + - DSWA bit 7 (called "Free Play" in "Test Mode") gives you infinite lives + but you will still need to insert coins as a standard game. + In a 2 players game, when this Dip Switch is ON, player doesn't change when it, + so player 2 will have to wait that player 1 has ended the game to start. + + +6) 'kyustrkr' + + - No region (not a Taito game anyway) + - No notice screen + - DSWA bit 7 (called "Free Play" in "Test Mode") has the following effects : + * in a game versus CPU, player(s) will always win regardless of the score + * in a 1UP versus 2UP game, both players will play 6 matches regardless of the score + - "Language" Dip Switch also affects game title + + +7) 'ballbros' + + - No region (not a Taito game anyway) + - No notice screen + - Do NOT trust the test mode which has nothing to do with the game ! + - "Difficulty" settings need to be confirmed as I'm not good enough + at playing this game to see any visible difference :( + They are based on the ones for other East Technology games though. + + +***************************************************************************/ + +#include "emu.h" + +#include "taitoipt.h" +#include "taitosnd.h" +#include "taitocchip.h" + +#include "cpu/m68000/m68000.h" +#include "cpu/z80/z80.h" +#include "machine/timer.h" +#include "sound/ymopm.h" +#include "sound/ymopn.h" +#include "video/x1_001.h" + +#include "emupal.h" +#include "screen.h" +#include "speaker.h" + + +namespace { + +class taitox_state : public driver_device +{ +public: + taitox_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu"), + m_audiocpu(*this, "audiocpu"), + m_spritegen(*this, "spritegen"), + m_palette(*this, "palette"), + m_z80bank(*this, "z80bank"), + m_dswa_io(*this, "DSWA"), + m_dswb_io(*this, "DSWB"), + m_in_io(*this, "IN%u", 0U) + { } + + void ballbros(machine_config &config); + void kyustrkr(machine_config &config); + void gigandes(machine_config &config); + void daisenpu(machine_config &config); + +protected: + virtual void machine_start() override ATTR_COLD; + + u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + + u16 dsw_input_r(offs_t offset); + + void taito_x_base_map(address_map &map) ATTR_COLD; + void sound_map(address_map &map) ATTR_COLD; + + required_device m_maincpu; + required_device m_audiocpu; + required_device m_spritegen; + required_device m_palette; + +private: + u16 input_r(offs_t offset); + void daisenpu_input_w(offs_t offset, u16 data); + void kyustrkr_input_w(offs_t offset, u16 data); + void sound_bankswitch_w(u8 data); + + void ballbros_map(address_map &map) ATTR_COLD; + void daisenpu_map(address_map &map) ATTR_COLD; + void daisenpu_sound_map(address_map &map) ATTR_COLD; + void gigandes_map(address_map &map) ATTR_COLD; + void kyustrkr_map(address_map &map) ATTR_COLD; + + required_memory_bank m_z80bank; + required_ioport m_dswa_io; + required_ioport m_dswb_io; + required_ioport_array<3> m_in_io; +}; + +class taitox_cchip_state : public taitox_state +{ +public: + taitox_cchip_state(const machine_config &mconfig, device_type type, const char *tag) : + taitox_state(mconfig, type, tag), + m_cchip(*this, "cchip"), + m_cchip_irq_clear(*this, "cchip_irq_clear") + { } + + void superman(machine_config &config); + +private: + void counters_w(u8 data); + + INTERRUPT_GEN_MEMBER(interrupt); + TIMER_DEVICE_CALLBACK_MEMBER(cchip_irq_clear_cb); + + void superman_map(address_map &map) ATTR_COLD; + + required_device m_cchip; + required_device m_cchip_irq_clear; +}; + +void taitox_cchip_state::counters_w(u8 data) +{ + machine().bookkeeping().coin_lockout_w(1, data & 0x08); + machine().bookkeeping().coin_lockout_w(0, data & 0x04); + machine().bookkeeping().coin_counter_w(1, data & 0x02); + machine().bookkeeping().coin_counter_w(0, data & 0x01); +} + +u16 taitox_state::dsw_input_r(offs_t offset) +{ + switch (offset) + { + case 0x00: + return m_dswa_io->read() & 0x0f; + case 0x01: + return (m_dswa_io->read() & 0xf0) >> 4; + case 0x02: + return m_dswb_io->read() & 0x0f; + case 0x03: + return (m_dswb_io->read() & 0xf0) >> 4; + default: + logerror("taitox unknown dsw read offset: %04x\n", offset); + return 0x00; + } +} + +u16 taitox_state::input_r(offs_t offset) +{ + switch (offset) + { + case 0x00: + return m_in_io[0]->read(); // Player 1 controls + START1 + case 0x01: + return m_in_io[1]->read(); // Player 2 controls + START2 + case 0x02: + return m_in_io[2]->read(); // COINn + SERVICE1 + TILT + + default: + logerror("taitox unknown input read offset: %04x\n", offset); + return 0x00; + } +} + +void taitox_state::daisenpu_input_w(offs_t offset, u16 data) +{ + switch (offset) + { + case 0x04: // coin counters and lockout + machine().bookkeeping().coin_counter_w(0, data & 0x01); + machine().bookkeeping().coin_counter_w(1, data & 0x02); + machine().bookkeeping().coin_lockout_w(0, ~data & 0x04); + machine().bookkeeping().coin_lockout_w(1, ~data & 0x08); +//logerror("taitox coin control %04x to offset %04x\n", data, offset); + break; + + default: + logerror("taitox unknown input write %04x to offset %04x\n", data, offset); + } +} + + +void taitox_state::kyustrkr_input_w(offs_t offset, u16 data) +{ + switch (offset) + { + case 0x04: // coin counters and lockout + machine().bookkeeping().coin_counter_w(0, data & 0x01); + machine().bookkeeping().coin_counter_w(1, data & 0x02); + machine().bookkeeping().coin_lockout_w(0, data & 0x04); + machine().bookkeeping().coin_lockout_w(1, data & 0x08); +//logerror("taitox coin control %04x to offset %04x\n", data, offset); + break; + + default: + logerror("taitox unknown input write %04x to offset %04x\n", data, offset); + } +} + + +/**************************************************************************/ + +void taitox_state::sound_bankswitch_w(u8 data) +{ + m_z80bank->set_entry(data & 3); +} + + +/**************************************************************************/ + +void taitox_state::taito_x_base_map(address_map &map) +{ + map(0xb00000, 0xb00fff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette"); + map(0xd00000, 0xd005ff).ram().rw(m_spritegen, FUNC(x1_001_device::spriteylow_r16), FUNC(x1_001_device::spriteylow_w16)); // Sprites Y + map(0xd00600, 0xd00607).ram().rw(m_spritegen, FUNC(x1_001_device::spritectrl_r16), FUNC(x1_001_device::spritectrl_w16)); + map(0xe00000, 0xe03fff).ram().rw(m_spritegen, FUNC(x1_001_device::spritecode_r16), FUNC(x1_001_device::spritecode_w16)); // Sprites Code + X + Attr + map(0xf00000, 0xf03fff).ram(); // Main RAM +} + +void taitox_cchip_state::superman_map(address_map &map) +{ + taito_x_base_map(map); + map(0x000000, 0x07ffff).rom(); + map(0x300000, 0x300001).nopw(); // written each frame at $3a9c, mostly 0x10 + map(0x400000, 0x400001).nopw(); // written each frame at $3aa2, mostly 0x10 + map(0x500000, 0x500007).r(FUNC(taitox_cchip_state::dsw_input_r)); + map(0x600000, 0x600001).nopw(); // written each frame at $3ab0, mostly 0x10 + map(0x800000, 0x800001).nopr(); + map(0x800001, 0x800001).w("tc0140syt", FUNC(tc0140syt_device::master_port_w)); + map(0x800003, 0x800003).rw("tc0140syt", FUNC(tc0140syt_device::master_comm_r), FUNC(tc0140syt_device::master_comm_w)); + map(0x900000, 0x9007ff).rw(m_cchip, FUNC(taito_cchip_device::mem68_r), FUNC(taito_cchip_device::mem68_w)).umask16(0x00ff); + map(0x900800, 0x900fff).rw(m_cchip, FUNC(taito_cchip_device::asic_r), FUNC(taito_cchip_device::asic68_w)).umask16(0x00ff); +} + +void taitox_state::daisenpu_map(address_map &map) +{ + taito_x_base_map(map); + map(0x000000, 0x03ffff).rom(); +// map(0x400000, 0x400001).nopw(); // written each frame at $2ac, values change + map(0x500000, 0x50000f).r(FUNC(taitox_state::dsw_input_r)); +// map(0x600000, 0x600001).nopw(); // written each frame at $2a2, values change + map(0x800000, 0x800001).nopr(); + map(0x800001, 0x800001).w("ciu", FUNC(pc060ha_device::master_port_w)); + map(0x800003, 0x800003).rw("ciu", FUNC(pc060ha_device::master_comm_r), FUNC(pc060ha_device::master_comm_w)); + map(0x900000, 0x90000f).rw(FUNC(taitox_state::input_r), FUNC(taitox_state::daisenpu_input_w)); +} + +void taitox_state::gigandes_map(address_map &map) +{ + taito_x_base_map(map); + map(0x000000, 0x07ffff).rom(); + map(0x400000, 0x400001).nopw(); // 0x1 written each frame at $d42, watchdog? + map(0x500000, 0x500007).r(FUNC(taitox_state::dsw_input_r)); + map(0x600000, 0x600001).nopw(); // 0x1 written each frame at $d3c, watchdog? + map(0x800000, 0x800001).nopr(); + map(0x800001, 0x800001).w("tc0140syt", FUNC(tc0140syt_device::master_port_w)); + map(0x800003, 0x800003).rw("tc0140syt", FUNC(tc0140syt_device::master_comm_r), FUNC(tc0140syt_device::master_comm_w)); + map(0x900000, 0x90000f).rw(FUNC(taitox_state::input_r), FUNC(taitox_state::daisenpu_input_w)); +} + +void taitox_state::ballbros_map(address_map &map) +{ + taito_x_base_map(map); + map(0x000000, 0x03ffff).rom(); + map(0x400000, 0x400001).nopw(); // 0x1 written each frame at $c56, watchdog? + map(0x500000, 0x50000f).r(FUNC(taitox_state::dsw_input_r)); + map(0x600000, 0x600001).nopw(); // 0x1 written each frame at $c4e, watchdog? + map(0x800000, 0x800001).nopr(); + map(0x800001, 0x800001).w("tc0140syt", FUNC(tc0140syt_device::master_port_w)); + map(0x800003, 0x800003).rw("tc0140syt", FUNC(tc0140syt_device::master_comm_r), FUNC(tc0140syt_device::master_comm_w)); + map(0x900000, 0x90000f).rw(FUNC(taitox_state::input_r), FUNC(taitox_state::daisenpu_input_w)); +} + +void taitox_state::kyustrkr_map(address_map &map) +{ + taito_x_base_map(map); + map(0x000000, 0x03ffff).rom(); + map(0x400000, 0x400001).nopw(); // 0x1 written each frame at $c56, watchdog? + map(0x500000, 0x50000f).r(FUNC(taitox_state::dsw_input_r)); + map(0x600000, 0x600001).nopw(); // 0x1 written each frame at $c4e, watchdog? + map(0x800000, 0x800001).nopr(); + map(0x800001, 0x800001).w("tc0140syt", FUNC(tc0140syt_device::master_port_w)); + map(0x800003, 0x800003).rw("tc0140syt", FUNC(tc0140syt_device::master_comm_r), FUNC(tc0140syt_device::master_comm_w)); + map(0x900000, 0x90000f).rw(FUNC(taitox_state::input_r), FUNC(taitox_state::kyustrkr_input_w)); +} + + +/**************************************************************************/ + +void taitox_state::sound_map(address_map &map) +{ + map(0x0000, 0x3fff).rom(); + map(0x4000, 0x7fff).bankr("z80bank"); + map(0xc000, 0xdfff).ram(); + map(0xe000, 0xe003).rw("ymsnd", FUNC(ym2610_device::read), FUNC(ym2610_device::write)); + map(0xe200, 0xe200).nopr().w("tc0140syt", FUNC(tc0140syt_device::slave_port_w)); + map(0xe201, 0xe201).rw("tc0140syt", FUNC(tc0140syt_device::slave_comm_r), FUNC(tc0140syt_device::slave_comm_w)); + map(0xe400, 0xe403).nopw(); // pan + map(0xea00, 0xea00).nopr(); + map(0xee00, 0xee00).nopw(); // ? + map(0xf000, 0xf000).nopw(); // ? + map(0xf200, 0xf200).w(FUNC(taitox_state::sound_bankswitch_w)); +} + +void taitox_state::daisenpu_sound_map(address_map &map) +{ + map(0x0000, 0x3fff).rom(); + map(0x4000, 0x7fff).bankr("z80bank"); + map(0xc000, 0xdfff).ram(); + map(0xe000, 0xe001).rw("ymsnd", FUNC(ym2151_device::read), FUNC(ym2151_device::write)); + map(0xe200, 0xe200).nopr().w("ciu", FUNC(pc060ha_device::slave_port_w)); + map(0xe201, 0xe201).rw("ciu", FUNC(pc060ha_device::slave_comm_r), FUNC(pc060ha_device::slave_comm_w)); + map(0xe400, 0xe403).nopw(); // pan + map(0xea00, 0xea00).nopr(); + map(0xee00, 0xee00).nopw(); // ? + map(0xf000, 0xf000).nopw(); + map(0xf200, 0xf200).w(FUNC(taitox_state::sound_bankswitch_w)); +} + + +/**************************************************************************/ + +static INPUT_PORTS_START( taitox_generic ) // The Dip Switches will be modified as needed for each game + + PORT_START("DSWA") + TAITO_MACHINE_NO_COCKTAIL_LOC(SW1) + TAITO_COINAGE_WORLD_LOC(SW1) + + PORT_START("DSWB") + TAITO_DIFFICULTY_LOC(SW2) + PORT_DIPUNUSED_DIPLOC( 0x04, 0x04, "SW2:3" ) + PORT_DIPUNUSED_DIPLOC( 0x08, 0x08, "SW2:4" ) + PORT_DIPUNUSED_DIPLOC( 0x10, 0x10, "SW2:5" ) + PORT_DIPUNUSED_DIPLOC( 0x20, 0x20, "SW2:6" ) + PORT_DIPUNUSED_DIPLOC( 0x40, 0x40, "SW2:7" ) + PORT_DIPUNUSED_DIPLOC( 0x80, 0x80, "SW2:8" ) + + PORT_START("IN0") + TAITO_JOY_UDLR_2_BUTTONS_START( 1 ) + + PORT_START("IN1") + TAITO_JOY_UDLR_2_BUTTONS_START( 2 ) + + PORT_START("IN2") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SERVICE1 ) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_TILT ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) +INPUT_PORTS_END + +static INPUT_PORTS_START( taitox_east_tech ) // The Dip Switches will be modified as needed for each game + + PORT_START("DSWA") + PORT_DIPNAME( 0x03, 0x03, DEF_STR( Coin_A ) ) PORT_DIPLOCATION("SW1:1,2") + PORT_DIPSETTING( 0x01, DEF_STR( 2C_1C ) ) + PORT_DIPSETTING( 0x03, DEF_STR( 1C_1C ) ) + PORT_DIPSETTING( 0x00, DEF_STR( 2C_3C ) ) + PORT_DIPSETTING( 0x02, DEF_STR( 1C_2C ) ) + PORT_DIPNAME( 0x0c, 0x0c, DEF_STR( Coin_B ) ) PORT_DIPLOCATION("SW1:3,4") + PORT_DIPSETTING( 0x04, DEF_STR( 2C_1C ) ) + PORT_DIPSETTING( 0x0c, DEF_STR( 1C_1C ) ) + PORT_DIPSETTING( 0x00, DEF_STR( 2C_3C ) ) + PORT_DIPSETTING( 0x08, DEF_STR( 1C_2C ) ) + PORT_DIPUNUSED_DIPLOC( 0x10, 0x10, "SW1:5" ) + PORT_DIPNAME( 0x60, 0x40, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SW1:6,7") + PORT_DIPSETTING( 0x60, DEF_STR( Easy ) ) + PORT_DIPSETTING( 0x40, DEF_STR( Medium ) ) + PORT_DIPSETTING( 0x20, DEF_STR( Hard ) ) + PORT_DIPSETTING( 0x00, DEF_STR( Hardest ) ) + PORT_DIPNAME( 0x80, 0x80, "Debug Mode" ) PORT_DIPLOCATION("SW1:8") + PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + + PORT_START("DSWB") + PORT_DIPNAME( 0x01, 0x00, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW2:1") + PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x00, DEF_STR( Flip_Screen ) ) PORT_DIPLOCATION("SW2:2") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x02, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x00, DEF_STR( Allow_Continue ) ) PORT_DIPLOCATION("SW2:3") + PORT_DIPSETTING( 0x04, DEF_STR( No ) ) + PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) + PORT_DIPNAME( 0x18, 0x18, DEF_STR( Lives ) ) PORT_DIPLOCATION("SW2:4,5") + PORT_DIPSETTING( 0x18, "3" ) + PORT_DIPSETTING( 0x10, "4" ) + PORT_DIPSETTING( 0x08, "5" ) + PORT_DIPSETTING( 0x00, "6" ) + PORT_DIPNAME( 0x20, 0x00, DEF_STR( Controls ) ) PORT_DIPLOCATION("SW2:6") + PORT_DIPSETTING( 0x20, DEF_STR( Single ) ) + PORT_DIPSETTING( 0x00, DEF_STR( Dual ) ) + PORT_DIPNAME( 0x40, 0x00, DEF_STR( Language ) ) PORT_DIPLOCATION("SW2:7") + PORT_DIPSETTING( 0x00, DEF_STR( English ) ) + PORT_DIPSETTING( 0x40, DEF_STR( Japanese ) ) + PORT_SERVICE_DIPLOC( 0x80, IP_ACTIVE_LOW, "SW2:8" ) + + PORT_START("IN0") + TAITO_JOY_UDLR_2_BUTTONS_START( 1 ) + + PORT_START("IN1") + TAITO_JOY_UDLR_2_BUTTONS_START( 2 ) + + PORT_START("IN2") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SERVICE1 ) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_TILT ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) +INPUT_PORTS_END + +static INPUT_PORTS_START( superman ) + // DSWA - 0x500000 (low) and 0x500002 (high) -> 0xf01c4a ($1c4a,A5) + // DSWB - 0x500004 (low) and 0x500006 (high) -> 0xf01c4c ($1c4c,A5) + PORT_INCLUDE( taitox_generic ) + + PORT_MODIFY("DSWB") + PORT_DIPNAME( 0x30, 0x30, DEF_STR( Lives ) ) PORT_DIPLOCATION("SW2:5,6") + PORT_DIPSETTING( 0x20, "2" ) + PORT_DIPSETTING( 0x30, "3" ) + PORT_DIPSETTING( 0x10, "4" ) + PORT_DIPSETTING( 0x00, "5" ) + + PORT_MODIFY("IN2") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SERVICE1 ) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_TILT ) +INPUT_PORTS_END + +static INPUT_PORTS_START( supermanu ) + PORT_INCLUDE( superman ) + + PORT_MODIFY("DSWA") + TAITO_COINAGE_US_LOC(SW1) +INPUT_PORTS_END + +static INPUT_PORTS_START( supermanj ) + PORT_INCLUDE( superman ) + + PORT_MODIFY("DSWA") + TAITO_COINAGE_JAPAN_OLD_LOC(SW1) +INPUT_PORTS_END + +static INPUT_PORTS_START( twinhawk ) + // DSWA - 0x500000 (low) and 0x500002 (high) -> 0xf001b8 + // DSWB - 0x500004 (low) and 0x500006 (high) -> 0xf001ba + PORT_INCLUDE( taitox_generic ) + + PORT_MODIFY("DSWB") + PORT_DIPNAME( 0x0c, 0x0c, DEF_STR( Bonus_Life ) ) PORT_DIPLOCATION("SW2:3,4") + PORT_DIPSETTING( 0x0c, "50k and every 150k" ) + PORT_DIPSETTING( 0x08, "70k and every 200k" ) + PORT_DIPSETTING( 0x04, "50k only" ) + PORT_DIPSETTING( 0x00, "100k only" ) + PORT_DIPNAME( 0x30, 0x30, DEF_STR( Lives ) ) PORT_DIPLOCATION("SW2:5,6") + PORT_DIPSETTING( 0x00, "2" ) + PORT_DIPSETTING( 0x30, "3" ) + PORT_DIPSETTING( 0x10, "4" ) + PORT_DIPSETTING( 0x20, "5" ) + PORT_DIPNAME( 0x80, 0x00, DEF_STR( Allow_Continue ) ) PORT_DIPLOCATION("SW2:8") + PORT_DIPSETTING( 0x80, DEF_STR( No ) ) + PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) +INPUT_PORTS_END + +static INPUT_PORTS_START( twinhawku ) + PORT_INCLUDE( twinhawk ) + + PORT_MODIFY("DSWA") + PORT_DIPNAME( 0xc0, 0xc0, DEF_STR( Coin_B ) ) PORT_DIPLOCATION("SW1:7,8") + PORT_DIPSETTING( 0x00, DEF_STR( 4C_1C ) ) + PORT_DIPSETTING( 0x40, DEF_STR( 3C_1C ) ) + PORT_DIPSETTING( 0x80, DEF_STR( 2C_1C ) ) + PORT_DIPSETTING( 0xc0, DEF_STR( 1C_1C ) ) +INPUT_PORTS_END + +static INPUT_PORTS_START( daisenpu ) + // DSWA - 0x500000 (low) and 0x500002 (high) -> 0xf001a4 + // DSWB - 0x500004 (low) and 0x500006 (high) -> 0xf001a6 + PORT_INCLUDE( twinhawk ) + + PORT_MODIFY("DSWA") + TAITO_MACHINE_COCKTAIL_LOC(SW1) + TAITO_COINAGE_JAPAN_OLD_LOC(SW1) + + PORT_MODIFY("DSWB") + PORT_DIPNAME( 0x0c, 0x0c, DEF_STR( Bonus_Life ) ) PORT_DIPLOCATION("SW2:3,4") + PORT_DIPSETTING( 0x08, "50k and every 150k" ) + PORT_DIPSETTING( 0x0c, "70k and every 200k" ) + PORT_DIPSETTING( 0x04, "100k only" ) + PORT_DIPSETTING( 0x00, DEF_STR( None ) ) +INPUT_PORTS_END + +static INPUT_PORTS_START( gigandes ) + // DSWA - 0x500000 (low) and 0x500002 (high) -> 0xf00a3c + // DSWB - 0x500004 (low) and 0x500006 (high) -> 0xf00a3e + PORT_INCLUDE( taitox_east_tech ) +INPUT_PORTS_END + +static INPUT_PORTS_START( kyustrkr ) + // DSWA - 0x500000 (low) and 0x500002 (high) -> 0xf028fe + // DSWB - 0x500004 (low) and 0x500006 (high) -> 0xf02900 + PORT_INCLUDE( taitox_east_tech ) + + PORT_MODIFY("DSWB") + PORT_DIPUNUSED_DIPLOC( 0x08, 0x08, "SW2:4" ) + PORT_DIPUNUSED_DIPLOC( 0x10, 0x10, "SW2:5" ) + PORT_DIPUNUSED_DIPLOC( 0x20, 0x20, "SW2:6" ) + + PORT_MODIFY("IN0") + TAITO_JOY_UDLR_3_BUTTONS_START( 1 ) + + PORT_MODIFY("IN1") + TAITO_JOY_UDLR_3_BUTTONS_START( 2 ) +INPUT_PORTS_END + +static INPUT_PORTS_START( ballbros ) + // DSWA - 0x500000 (low) and 0x500002 (high) -> 0xf028fe + // DSWB - 0x500004 (low) and 0x500006 (high) -> 0xf02900 + PORT_INCLUDE( taitox_east_tech ) + + PORT_MODIFY("DSWB") + PORT_DIPNAME( 0x02, 0x02, DEF_STR( Flip_Screen ) ) PORT_DIPLOCATION("SW2:2") // Opposite of the other East Technology games + PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x04, DEF_STR( Allow_Continue ) ) PORT_DIPLOCATION("SW2:3") // Opposite of the other East Technology games + PORT_DIPSETTING( 0x00, DEF_STR( No ) ) + PORT_DIPSETTING( 0x04, DEF_STR( Yes ) ) + PORT_DIPUNUSED_DIPLOC( 0x08, 0x08, "SW2:4" ) + PORT_DIPUNUSED_DIPLOC( 0x10, 0x10, "SW2:5" ) + PORT_DIPNAME( 0x20, 0x00, DEF_STR( Language ) ) PORT_DIPLOCATION("SW2:6") + PORT_DIPSETTING( 0x00, DEF_STR( English ) ) + PORT_DIPSETTING( 0x20, DEF_STR( Japanese ) ) + PORT_DIPNAME( 0x40, 0x00, "Color Change" ) PORT_DIPLOCATION("SW2:7") + PORT_DIPSETTING( 0x00, "Less" ) // each pattern + PORT_DIPSETTING( 0x40, "More" ) // every 3 times + + PORT_MODIFY("IN0") + TAITO_JOY_UDLR_1_BUTTON_START( 1 ) + + PORT_MODIFY("IN1") + TAITO_JOY_UDLR_1_BUTTON_START( 2 ) +INPUT_PORTS_END + + +/**************************************************************************/ + +static const gfx_layout tilelayout = +{ + 16,16, // 16*16 sprites + RGN_FRAC(1,1), // 16384 of them + 4, // 4 bits per pixel + { STEP4(0,8) }, + { STEP8(0,1), STEP8(8*4*8,1) }, + { STEP8(0,8*4), STEP8(8*4*8*2,8*4) }, + 16*16*4 // every sprite takes 64 consecutive bytes +}; + +static GFXDECODE_START( gfx_taito_x ) + GFXDECODE_ENTRY( "gfx1", 0x000000, tilelayout, 0, 128 ) // sprites & playfield +GFXDECODE_END + + +/**************************************************************************/ + + +void taitox_state::machine_start() +{ + int banks = memregion("audiocpu")->bytes() / 0x4000; + m_z80bank->configure_entries(0, banks, memregion("audiocpu")->base(), 0x4000); +} + +INTERRUPT_GEN_MEMBER(taitox_cchip_state::interrupt) +{ + m_maincpu->set_input_line(6, HOLD_LINE); + m_cchip->ext_interrupt(ASSERT_LINE); + m_cchip_irq_clear->adjust(attotime::zero); +} + +TIMER_DEVICE_CALLBACK_MEMBER(taitox_cchip_state::cchip_irq_clear_cb) +{ + m_cchip->ext_interrupt(CLEAR_LINE); +} + +u32 taitox_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + bitmap.fill(0x1f0, cliprect); + + m_spritegen->draw_sprites(screen, bitmap,cliprect,0x1000); + return 0; +} + + +/**************************************************************************/ + +void taitox_cchip_state::superman(machine_config &config) +{ + // basic machine hardware + M68000(config, m_maincpu, 16_MHz_XTAL / 2); // verified on PCB + m_maincpu->set_addrmap(AS_PROGRAM, &taitox_cchip_state::superman_map); + m_maincpu->set_vblank_int("screen", FUNC(taitox_cchip_state::interrupt)); + + Z80(config, m_audiocpu, 16_MHz_XTAL / 4); // verified on PCB + m_audiocpu->set_addrmap(AS_PROGRAM, &taitox_cchip_state::sound_map); + + TAITO_CCHIP(config, m_cchip, 16_MHz_XTAL / 2); // 8MHz measured on pin 20 + m_cchip->in_pa_callback().set_ioport("IN0"); + m_cchip->in_pb_callback().set_ioport("IN1"); + m_cchip->in_ad_callback().set_ioport("IN2"); + m_cchip->out_pc_callback().set(FUNC(taitox_cchip_state::counters_w)); + + TIMER(config, m_cchip_irq_clear).configure_generic(FUNC(taitox_cchip_state::cchip_irq_clear_cb)); + + config.set_maximum_quantum(attotime::from_hz(600)); // 10 CPU slices per frame - enough for the sound CPU to read all commands + + X1_001(config, m_spritegen, 16_MHz_XTAL, m_palette, gfx_taito_x); + // position kludges + m_spritegen->set_fg_yoffsets(-0x12, 0x0e); + m_spritegen->set_bg_yoffsets(0x1, -0x1); + + // video hardware + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_refresh_hz(57.43); + screen.set_vblank_time(ATTOSECONDS_IN_USEC(0)); + screen.set_size(52*8, 32*8); + screen.set_visarea(0*8, 48*8-1, 1*8, 31*8-1); + screen.set_screen_update(FUNC(taitox_cchip_state::screen_update)); + screen.set_palette(m_palette); + + PALETTE(config, m_palette).set_format(palette_device::xRGB_555, 2048); + + // sound hardware + SPEAKER(config, "speaker", 2).front(); + + ym2610_device &ymsnd(YM2610(config, "ymsnd", 16_MHz_XTAL / 2)); // verified on PCB + ymsnd.irq_handler().set_inputline(m_audiocpu, 0); + ymsnd.add_route(0, "speaker", 0.75, 0); + ymsnd.add_route(0, "speaker", 0.75, 1); + ymsnd.add_route(1, "speaker", 1.0, 0); + ymsnd.add_route(2, "speaker", 1.0, 1); + + tc0140syt_device &tc0140syt(TC0140SYT(config, "tc0140syt", 0)); + tc0140syt.nmi_callback().set_inputline(m_audiocpu, INPUT_LINE_NMI); + tc0140syt.reset_callback().set_inputline(m_audiocpu, INPUT_LINE_RESET); +} + +void taitox_state::daisenpu(machine_config &config) +{ + // basic machine hardware + M68000(config, m_maincpu, 16_MHz_XTAL / 2); // verified on PCB + m_maincpu->set_addrmap(AS_PROGRAM, &taitox_state::daisenpu_map); + m_maincpu->set_vblank_int("screen", FUNC(taitox_state::irq2_line_hold)); + + Z80(config, m_audiocpu, 16_MHz_XTAL / 4); // verified on PCB + m_audiocpu->set_addrmap(AS_PROGRAM, &taitox_state::daisenpu_sound_map); + + config.set_maximum_quantum(attotime::from_hz(600)); // 10 CPU slices per frame - enough for the sound CPU to read all commands + + X1_001(config, m_spritegen, 16_MHz_XTAL, m_palette, gfx_taito_x); + // position kludges + m_spritegen->set_fg_yoffsets(-0x12, 0x0e); + m_spritegen->set_bg_yoffsets(0x1, -0x1); + + // video hardware + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_refresh_hz(60); + screen.set_vblank_time(ATTOSECONDS_IN_USEC(0)); + screen.set_size(52*8, 32*8); + screen.set_visarea(0*8, 48*8-1, 2*8, 30*8-1); + screen.set_screen_update(FUNC(taitox_state::screen_update)); + screen.set_palette(m_palette); + + PALETTE(config, m_palette).set_format(palette_device::xRGB_555, 2048); + + // sound hardware + SPEAKER(config, "speaker", 2).front(); + + ym2151_device &ymsnd(YM2151(config, "ymsnd", 16_MHz_XTAL / 4)); // verified on PCB + ymsnd.irq_handler().set_inputline(m_audiocpu, 0); + ymsnd.add_route(0, "speaker", 0.45, 0); + ymsnd.add_route(1, "speaker", 0.45, 1); + + pc060ha_device &ciu(PC060HA(config, "ciu", 0)); + ciu.nmi_callback().set_inputline(m_audiocpu, INPUT_LINE_NMI); + ciu.reset_callback().set_inputline(m_audiocpu, INPUT_LINE_RESET); +} + +void taitox_state::gigandes(machine_config &config) +{ + // basic machine hardware + M68000(config, m_maincpu, 8000000); // 8 MHz? + m_maincpu->set_addrmap(AS_PROGRAM, &taitox_state::gigandes_map); + m_maincpu->set_vblank_int("screen", FUNC(taitox_state::irq2_line_hold)); + + Z80(config, m_audiocpu, 4000000); // 4 MHz ??? + m_audiocpu->set_addrmap(AS_PROGRAM, &taitox_state::sound_map); + + config.set_maximum_quantum(attotime::from_hz(600)); // 10 CPU slices per frame - enough for the sound CPU to read all commands + + X1_001(config, m_spritegen, 16_MHz_XTAL, m_palette, gfx_taito_x); + m_spritegen->set_fg_yoffsets(-0xa, 0xe); + m_spritegen->set_bg_yoffsets(0x1, -0x1); + + // video hardware + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_refresh_hz(60); + screen.set_vblank_time(ATTOSECONDS_IN_USEC(0)); + screen.set_size(52*8, 32*8); + screen.set_visarea(0*8, 48*8-1, 1*8, 31*8-1); + screen.set_screen_update(FUNC(taitox_state::screen_update)); + screen.set_palette(m_palette); + + PALETTE(config, m_palette).set_format(palette_device::xRGB_555, 2048); + + // sound hardware + SPEAKER(config, "speaker", 2).front(); + + ym2610_device &ymsnd(YM2610(config, "ymsnd", 8000000)); + ymsnd.irq_handler().set_inputline(m_audiocpu, 0); + ymsnd.add_route(0, "speaker", 0.75, 0); + ymsnd.add_route(0, "speaker", 0.75, 1); + ymsnd.add_route(1, "speaker", 1.0, 0); + ymsnd.add_route(2, "speaker", 1.0, 1); + + tc0140syt_device &tc0140syt(TC0140SYT(config, "tc0140syt", 0)); + tc0140syt.nmi_callback().set_inputline(m_audiocpu, INPUT_LINE_NMI); + tc0140syt.reset_callback().set_inputline(m_audiocpu, INPUT_LINE_RESET); +} + +void taitox_state::ballbros(machine_config &config) +{ + // basic machine hardware + M68000(config, m_maincpu, 8000000); // 8 MHz? + m_maincpu->set_addrmap(AS_PROGRAM, &taitox_state::ballbros_map); + m_maincpu->set_vblank_int("screen", FUNC(taitox_state::irq2_line_hold)); + + Z80(config, m_audiocpu, 4000000); // 4 MHz ??? + m_audiocpu->set_addrmap(AS_PROGRAM, &taitox_state::sound_map); + + config.set_maximum_quantum(attotime::from_hz(600)); // 10 CPU slices per frame - enough for the sound CPU to read all commands + + X1_001(config, m_spritegen, 16000000, m_palette, gfx_taito_x); + // position kludges + m_spritegen->set_fg_yoffsets(-0x0a, 0x0e); + m_spritegen->set_bg_yoffsets(0x1, -0x1); + + // video hardware + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_refresh_hz(60); + screen.set_vblank_time(ATTOSECONDS_IN_USEC(0)); + screen.set_size(52*8, 32*8); + screen.set_visarea(0*8, 48*8-1, 1*8, 31*8-1); + screen.set_screen_update(FUNC(taitox_state::screen_update)); + screen.set_palette(m_palette); + + PALETTE(config, m_palette).set_format(palette_device::xRGB_555, 2048); + + // sound hardware + SPEAKER(config, "speaker", 2).front(); + + ym2610_device &ymsnd(YM2610(config, "ymsnd", 8000000)); + ymsnd.irq_handler().set_inputline(m_audiocpu, 0); + ymsnd.add_route(0, "speaker", 0.75, 0); + ymsnd.add_route(0, "speaker", 0.75, 1); + ymsnd.add_route(1, "speaker", 1.0, 0); + ymsnd.add_route(2, "speaker", 1.0, 1); + + tc0140syt_device &tc0140syt(TC0140SYT(config, "tc0140syt", 0)); + tc0140syt.nmi_callback().set_inputline(m_audiocpu, INPUT_LINE_NMI); + tc0140syt.reset_callback().set_inputline(m_audiocpu, INPUT_LINE_RESET); +} + +void taitox_state::kyustrkr(machine_config &config) +{ + ballbros(config); + // basic machine hardware + m_maincpu->set_addrmap(AS_PROGRAM, &taitox_state::kyustrkr_map); +} + + +/*************************************************************************** + + Game driver(s) + +***************************************************************************/ + +ROM_START( superman ) + ROM_REGION( 0x80000, "maincpu", 0 ) // 512k for 68000 code + ROM_LOAD16_BYTE( "b61_09.a10", 0x00000, 0x20000, CRC(640f1d58) SHA1(e768d32eae1dba39c23189996fbd5454c8627809) ) + ROM_LOAD16_BYTE( "b61_07.a5", 0x00001, 0x20000, CRC(fddb9953) SHA1(8b562712810a5a72f4647f1ba1314a1be2e249e7) ) + ROM_LOAD16_BYTE( "b61_08.a8", 0x40000, 0x20000, CRC(79fc028e) SHA1(bf42b3f84dcad8fd9085c702a78dc895cc12d670) ) + ROM_LOAD16_BYTE( "b61_13.a3", 0x40001, 0x20000, CRC(9f446a44) SHA1(16f7cd6438e47fdaac93a368df5c093f6ff0f1f0) ) + + ROM_REGION( 0x10000, "audiocpu", 0 ) // 64k for Z80 code + ROM_LOAD( "b61_10.d18", 0x00000, 0x10000, CRC(6efe79e8) SHA1(7a76efaaeab71473f4b0b23a89141f203488ce1d) ) + + ROM_REGION( 0x200000, "gfx1", 0 ) + ROM_LOAD32_WORD_SWAP( "b61-14.f1", 0x000002, 0x80000, CRC(89368c3e) SHA1(8d227439ab321fd5d432d860544daea0e78ce588) ) // Plane 0, 1 + ROM_LOAD32_WORD_SWAP( "b61-15.h1", 0x100002, 0x80000, CRC(910cc4f9) SHA1(9ecfa84123a8f9d048f0a689647e92f25af73899) ) + ROM_LOAD32_WORD_SWAP( "b61-16.j1", 0x000000, 0x80000, CRC(3622ed2f) SHA1(03f4383f6ff8b5f1e26bc6bbef2fb1855d3bb93f) ) // Plane 2, 3 + ROM_LOAD32_WORD_SWAP( "b61-17.k1", 0x100000, 0x80000, CRC(c34f27e0) SHA1(07ee02c18ce29f35e8ae87d0c1ed80b726c246a6) ) + + ROM_REGION( 0x80000, "ymsnd:adpcma", 0 ) // ADPCM samples + ROM_LOAD( "b61-01.e18", 0x00000, 0x80000, CRC(3cf99786) SHA1(f6febf9bda87ca04f0a5890d0e8001c26dfa6c81) ) + + ROM_REGION( 0x2000, "cchip:cchip_eprom", 0 ) + ROM_LOAD( "b61_11.m11", 0x0000, 0x2000, CRC(3bc5d44b) SHA1(6ba3ba35fe313af77d732412572d91a202b50542) ) +ROM_END + +ROM_START( supermanu ) // No US copyright notice or FBI logo - Just a coinage difference, see notes above + ROM_REGION( 0x80000, "maincpu", 0 ) // 512k for 68000 code + ROM_LOAD16_BYTE( "b61_09.a10", 0x00000, 0x20000, CRC(640f1d58) SHA1(e768d32eae1dba39c23189996fbd5454c8627809) ) + ROM_LOAD16_BYTE( "b61_07.a5", 0x00001, 0x20000, CRC(fddb9953) SHA1(8b562712810a5a72f4647f1ba1314a1be2e249e7) ) + ROM_LOAD16_BYTE( "b61_08.a8", 0x40000, 0x20000, CRC(79fc028e) SHA1(bf42b3f84dcad8fd9085c702a78dc895cc12d670) ) + ROM_LOAD16_BYTE( "b61_12.a3", 0x40001, 0x20000, CRC(064d3bfe) SHA1(75abf924a6e44203169d2fa15852caa0bf57db30) ) + + ROM_REGION( 0x10000, "audiocpu", 0 ) // 64k for Z80 code + ROM_LOAD( "b61_10.d18", 0x00000, 0x10000, CRC(6efe79e8) SHA1(7a76efaaeab71473f4b0b23a89141f203488ce1d) ) + + ROM_REGION( 0x200000, "gfx1", 0 ) + ROM_LOAD32_WORD_SWAP( "b61-14.f1", 0x000002, 0x80000, CRC(89368c3e) SHA1(8d227439ab321fd5d432d860544daea0e78ce588) ) // Plane 0, 1 + ROM_LOAD32_WORD_SWAP( "b61-15.h1", 0x100002, 0x80000, CRC(910cc4f9) SHA1(9ecfa84123a8f9d048f0a689647e92f25af73899) ) + ROM_LOAD32_WORD_SWAP( "b61-16.j1", 0x000000, 0x80000, CRC(3622ed2f) SHA1(03f4383f6ff8b5f1e26bc6bbef2fb1855d3bb93f) ) // Plane 2, 3 + ROM_LOAD32_WORD_SWAP( "b61-17.k1", 0x100000, 0x80000, CRC(c34f27e0) SHA1(07ee02c18ce29f35e8ae87d0c1ed80b726c246a6) ) + + ROM_REGION( 0x80000, "ymsnd:adpcma", 0 ) // ADPCM samples + ROM_LOAD( "b61-01.e18", 0x00000, 0x80000, CRC(3cf99786) SHA1(f6febf9bda87ca04f0a5890d0e8001c26dfa6c81) ) + + ROM_REGION( 0x2000, "cchip:cchip_eprom", 0 ) + ROM_LOAD( "b61_11.m11", 0x0000, 0x2000, CRC(3bc5d44b) SHA1(6ba3ba35fe313af77d732412572d91a202b50542) ) +ROM_END + +ROM_START( supermanj ) // Shows a Japan copyright notice + ROM_REGION( 0x80000, "maincpu", 0 ) // 512k for 68000 code + ROM_LOAD16_BYTE( "b61_09.a10", 0x00000, 0x20000, CRC(640f1d58) SHA1(e768d32eae1dba39c23189996fbd5454c8627809) ) + ROM_LOAD16_BYTE( "b61_07.a5", 0x00001, 0x20000, CRC(fddb9953) SHA1(8b562712810a5a72f4647f1ba1314a1be2e249e7) ) + ROM_LOAD16_BYTE( "b61_08.a8", 0x40000, 0x20000, CRC(79fc028e) SHA1(bf42b3f84dcad8fd9085c702a78dc895cc12d670) ) + ROM_LOAD16_BYTE( "b61_06.a3", 0x40001, 0x20000, CRC(714a0b68) SHA1(b0b42c55d2404c7c193eb8cab3bd92e321947845) ) + + ROM_REGION( 0x10000, "audiocpu", 0 ) // 64k for Z80 code + ROM_LOAD( "b61_10.d18", 0x00000, 0x10000, CRC(6efe79e8) SHA1(7a76efaaeab71473f4b0b23a89141f203488ce1d) ) + + ROM_REGION( 0x200000, "gfx1", 0 ) + ROM_LOAD32_WORD_SWAP( "b61-14.f1", 0x000002, 0x80000, CRC(89368c3e) SHA1(8d227439ab321fd5d432d860544daea0e78ce588) ) // Plane 0, 1 + ROM_LOAD32_WORD_SWAP( "b61-15.h1", 0x100002, 0x80000, CRC(910cc4f9) SHA1(9ecfa84123a8f9d048f0a689647e92f25af73899) ) + ROM_LOAD32_WORD_SWAP( "b61-16.j1", 0x000000, 0x80000, CRC(3622ed2f) SHA1(03f4383f6ff8b5f1e26bc6bbef2fb1855d3bb93f) ) // Plane 2, 3 + ROM_LOAD32_WORD_SWAP( "b61-17.k1", 0x100000, 0x80000, CRC(c34f27e0) SHA1(07ee02c18ce29f35e8ae87d0c1ed80b726c246a6) ) + + ROM_REGION( 0x80000, "ymsnd:adpcma", 0 ) // ADPCM samples + ROM_LOAD( "b61-01.e18", 0x00000, 0x80000, CRC(3cf99786) SHA1(f6febf9bda87ca04f0a5890d0e8001c26dfa6c81) ) + + ROM_REGION( 0x2000, "cchip:cchip_eprom", 0 ) + ROM_LOAD( "b61_11.m11", 0x0000, 0x2000, CRC(3bc5d44b) SHA1(6ba3ba35fe313af77d732412572d91a202b50542) ) +ROM_END + +/* +Twin Hawk +Taito, 1988 + +J1100188A X SYSTEM +K1100443A MAIN PCB +P0-051A + +*/ + +ROM_START( twinhawk ) + ROM_REGION( 0x40000, "maincpu", 0 ) // 256k for 68000 code + ROM_LOAD16_BYTE( "b87-11.u7", 0x00000, 0x20000, CRC(fc84a399) SHA1(6e5552b7ee433bee74f8936a8e583b5f81b5f2b2) ) + ROM_LOAD16_BYTE( "b87-10.u5", 0x00001, 0x20000, CRC(17181706) SHA1(b7cab502b68a8f02918412538f23682120cbe1d3) ) + + ROM_REGION( 0x8000, "audiocpu", 0 ) // 32k for Z80 code + ROM_LOAD( "b87-07.13e", 0x00000, 0x8000, CRC(e2e0efa0) SHA1(4f1435ba738895996f26a64c2237e8349337df4a) ) + + ROM_REGION( 0x200000, "gfx1", 0 ) + ROM_LOAD32_WORD_SWAP( "b87-02.3h", 0x000002, 0x80000, CRC(89ad43a0) SHA1(6ff6ee085c1c06a05f4f8743d979d3552b7475a0) ) // Plane 0, 1 + ROM_LOAD32_WORD_SWAP( "b87-01.3f", 0x100002, 0x80000, CRC(81e82ae1) SHA1(d4dbdbf9ae0af69bbeccafb3cc2f67dadda72432) ) + ROM_LOAD32_WORD_SWAP( "b87-04.3k", 0x000000, 0x80000, CRC(958434b6) SHA1(cf5912c4468cb2079ff180203045a436175c037c) ) // Plane 2, 3 + ROM_LOAD32_WORD_SWAP( "b87-03.3j", 0x100000, 0x80000, CRC(ce155ae0) SHA1(7293125fc23f2411c4edd427a2576c145b3f2dd4) ) +ROM_END + +ROM_START( twinhawku ) + ROM_REGION( 0x40000, "maincpu", 0 ) // 256k for 68000 code + ROM_LOAD16_BYTE( "b87-09.u7", 0x00000, 0x20000, CRC(7e6267c7) SHA1(a623c1b740008675f36e8b63bbc17a573917db30) ) + ROM_LOAD16_BYTE( "b87-08.u5", 0x00001, 0x20000, CRC(31d9916f) SHA1(8ae491a51a4095717c6f65fe81a83902feccd54b) ) + + ROM_REGION( 0x8000, "audiocpu", 0 ) // 32k for Z80 code + ROM_LOAD( "b87-07.13e", 0x00000, 0x8000, CRC(e2e0efa0) SHA1(4f1435ba738895996f26a64c2237e8349337df4a) ) + + ROM_REGION( 0x200000, "gfx1", 0 ) + ROM_LOAD32_WORD_SWAP( "b87-02.3h", 0x000002, 0x80000, CRC(89ad43a0) SHA1(6ff6ee085c1c06a05f4f8743d979d3552b7475a0) ) // Plane 0, 1 + ROM_LOAD32_WORD_SWAP( "b87-01.3f", 0x100002, 0x80000, CRC(81e82ae1) SHA1(d4dbdbf9ae0af69bbeccafb3cc2f67dadda72432) ) + ROM_LOAD32_WORD_SWAP( "b87-04.3k", 0x000000, 0x80000, CRC(958434b6) SHA1(cf5912c4468cb2079ff180203045a436175c037c) ) // Plane 2, 3 + ROM_LOAD32_WORD_SWAP( "b87-03.3j", 0x100000, 0x80000, CRC(ce155ae0) SHA1(7293125fc23f2411c4edd427a2576c145b3f2dd4) ) +ROM_END + +ROM_START( daisenpu ) + ROM_REGION( 0x40000, "maincpu", 0 ) // 256k for 68000 code + ROM_LOAD16_BYTE( "b87-06.u7", 0x00000, 0x20000, CRC(cf236100) SHA1(7944a20950188f64c0a09edd1a4efe0270264b27) ) + ROM_LOAD16_BYTE( "b87-05.u5", 0x00001, 0x20000, CRC(7f15edc7) SHA1(3deba512f3c97f354ed4155f62058da160047bc5) ) + + ROM_REGION( 0x8000, "audiocpu", 0 ) // 32k for Z80 code + ROM_LOAD( "b87-07.13e", 0x00000, 0x8000, CRC(e2e0efa0) SHA1(4f1435ba738895996f26a64c2237e8349337df4a) ) + + ROM_REGION( 0x200000, "gfx1", 0 ) + ROM_LOAD32_WORD_SWAP( "b87-02.3h", 0x000002, 0x80000, CRC(89ad43a0) SHA1(6ff6ee085c1c06a05f4f8743d979d3552b7475a0) ) // Plane 0, 1 + ROM_LOAD32_WORD_SWAP( "b87-01.3f", 0x100002, 0x80000, CRC(81e82ae1) SHA1(d4dbdbf9ae0af69bbeccafb3cc2f67dadda72432) ) + ROM_LOAD32_WORD_SWAP( "b87-04.3k", 0x000000, 0x80000, CRC(958434b6) SHA1(cf5912c4468cb2079ff180203045a436175c037c) ) // Plane 2, 3 + ROM_LOAD32_WORD_SWAP( "b87-03.3j", 0x100000, 0x80000, CRC(ce155ae0) SHA1(7293125fc23f2411c4edd427a2576c145b3f2dd4) ) +ROM_END + +ROM_START( gigandes ) + ROM_REGION( 0x80000, "maincpu", 0 ) // 512k for 68000 code + ROM_LOAD16_BYTE( "east_1.10a", 0x00000, 0x20000, CRC(ae74e4e5) SHA1(1cac0a0e591b63142d8d249c67f803256fb28c2a) ) // 'fixed' test mode, see notes above + ROM_LOAD16_BYTE( "east_3.5a", 0x00001, 0x20000, CRC(8bcf2116) SHA1(9255d7e0ab568ad7a894421d3260fa80b8a0a5d0) ) // 'fixed' test mode, see notes above + ROM_LOAD16_BYTE( "east_2.8a", 0x40000, 0x20000, CRC(dd94b4d0) SHA1(2efff9fd51b28fd1fb46d16b359f0991af91054e) ) + ROM_LOAD16_BYTE( "east_4.3a", 0x40001, 0x20000, CRC(a647310a) SHA1(49db488a36f6c74729825bdf0214bcd30773eaf4) ) + + ROM_REGION( 0x10000, "audiocpu", 0 ) // 64k for Z80 code + ROM_LOAD( "east_5.17d", 0x00000, 0x10000, CRC(b24ab5f4) SHA1(e4730df984e9686c538df5fc626b795bda1db939) ) + + ROM_REGION( 0x200000, "gfx1", 0 ) + ROM_LOAD32_WORD_SWAP( "east_8.3f", 0x000002, 0x80000, CRC(75eece28) SHA1(7ce66cd8bca7dd214367beae067727c8735c0f7e) ) // Plane 0, 1 + ROM_LOAD32_WORD_SWAP( "east_7.3h", 0x100002, 0x80000, CRC(b179a76a) SHA1(cff2caf1eb0dda8a1b8283b9950b908b102f61de) ) + ROM_LOAD32_WORD_SWAP( "east_9.3j", 0x000000, 0x80000, CRC(5c5e6898) SHA1(f348ac752a571902c55f36e21aa3fb9ef97528e3) ) // Plane 2, 3 + ROM_LOAD32_WORD_SWAP( "east_6.3k", 0x100000, 0x80000, CRC(52db30e9) SHA1(0b6d73f2c6e6c1ad5fcb2a9edf50069cd0691483) ) + + ROM_REGION( 0x80000, "ymsnd:adpcmb", 0 ) // Delta-T samples + ROM_LOAD( "east-11.16f", 0x00000, 0x80000, CRC(92111f96) SHA1(e781f24761b7a923388f4cda64c7b31388fd64c5) ) + + ROM_REGION( 0x80000, "ymsnd:adpcma", 0 ) // ADPCM samples + ROM_LOAD( "east-10.16e", 0x00000, 0x80000, CRC(ca0ac419) SHA1(b29f30a8ff1286c65b741353b6551918a45bcafe) ) +ROM_END + +ROM_START( gigandesa ) + ROM_REGION( 0x80000, "maincpu", 0 ) // 512k for 68000 code + ROM_LOAD16_BYTE( "east-1.10a", 0x00000, 0x20000, CRC(290c50e0) SHA1(ac8008619891a5b54ba2069e4e18836976532c99) ) // 'buggy' test mode, see notes above + ROM_LOAD16_BYTE( "east-3.5a", 0x00001, 0x20000, CRC(9cef82af) SHA1(6dad850de699d40dfba54bde6baca75bb0059c83) ) // 'buggy' test mode, see notes above + ROM_LOAD16_BYTE( "east_2.8a", 0x40000, 0x20000, CRC(dd94b4d0) SHA1(2efff9fd51b28fd1fb46d16b359f0991af91054e) ) + ROM_LOAD16_BYTE( "east_4.3a", 0x40001, 0x20000, CRC(a647310a) SHA1(49db488a36f6c74729825bdf0214bcd30773eaf4) ) + + ROM_REGION( 0x10000, "audiocpu", 0 ) // 64k for Z80 code + ROM_LOAD( "east_5.17d", 0x00000, 0x10000, CRC(b24ab5f4) SHA1(e4730df984e9686c538df5fc626b795bda1db939) ) + + ROM_REGION( 0x200000, "gfx1", 0 ) + ROM_LOAD32_WORD_SWAP( "east_8.3f", 0x000002, 0x80000, CRC(75eece28) SHA1(7ce66cd8bca7dd214367beae067727c8735c0f7e) ) // Plane 0, 1 + ROM_LOAD32_WORD_SWAP( "east_7.3h", 0x100002, 0x80000, CRC(b179a76a) SHA1(cff2caf1eb0dda8a1b8283b9950b908b102f61de) ) + ROM_LOAD32_WORD_SWAP( "east_9.3j", 0x000000, 0x80000, CRC(5c5e6898) SHA1(f348ac752a571902c55f36e21aa3fb9ef97528e3) ) // Plane 2, 3 + ROM_LOAD32_WORD_SWAP( "east_6.3k", 0x100000, 0x80000, CRC(52db30e9) SHA1(0b6d73f2c6e6c1ad5fcb2a9edf50069cd0691483) ) + + ROM_REGION( 0x80000, "ymsnd:adpcmb", 0 ) // Delta-T samples + ROM_LOAD( "east-11.16f", 0x00000, 0x80000, CRC(92111f96) SHA1(e781f24761b7a923388f4cda64c7b31388fd64c5) ) + + ROM_REGION( 0x80000, "ymsnd:adpcma", 0 ) // ADPCM samples + ROM_LOAD( "east-10.16e", 0x00000, 0x80000, CRC(ca0ac419) SHA1(b29f30a8ff1286c65b741353b6551918a45bcafe) ) +ROM_END + +ROM_START( kyustrkr ) + ROM_REGION( 0x40000, "maincpu", 0 ) // 512k for 68000 code + ROM_LOAD16_BYTE( "pe.9a", 0x00000, 0x20000, CRC(082b5f96) SHA1(97c08b506b2a07d63f3323359b8564aa3621f483) ) + ROM_LOAD16_BYTE( "po.4a", 0x00001, 0x20000, CRC(0100361e) SHA1(45791f697c86309c459d0d8c3d3e967a3ece3ede) ) + + ROM_REGION( 0x10000, "audiocpu", 0 ) // 64k for Z80 code + ROM_LOAD( "ic.18d", 0x00000, 0x10000, CRC(92cfb788) SHA1(41cd5433584df05652bd0ce8c5a35dc38262d6f2) ) + + ROM_REGION( 0x80000, "gfx1", 0 ) + ROM_LOAD32_BYTE( "m-8-3.u3", 0x00003, 0x20000, CRC(1c4084e6) SHA1(addea2ba07bddb41fbe7f0fc859e744990bb9ff5) ) + ROM_LOAD32_BYTE( "m-8-2.u4", 0x00002, 0x20000, CRC(ada21c4d) SHA1(a683c8d798370c50d9bd5e67e91d7ed0f1659c20) ) + ROM_LOAD32_BYTE( "m-8-1.u5", 0x00001, 0x20000, CRC(9d95aad6) SHA1(3391b14196fea12223ab247d909791bc68fc8d56) ) + ROM_LOAD32_BYTE( "m-8-0.u6", 0x00000, 0x20000, CRC(0dfb6ed3) SHA1(0937614c8f97040d0216363bfb2bc21161128a3c) ) + + ROM_REGION( 0x80000, "ymsnd:adpcmb", 0 ) // Delta-T samples + ROM_LOAD( "m-8-5.u2", 0x00000, 0x20000, CRC(d9d90e0a) SHA1(1011548b4fb5f1a194c93ded512e74cda2c06ceb) ) + + ROM_REGION( 0x80000, "ymsnd:adpcma", 0 ) // ADPCM samples + ROM_LOAD( "m-8-4.u1", 0x00000, 0x20000, CRC(d3f6047a) SHA1(0db6d762bbe2d68cddf30e06125b904e1021b96d) ) +ROM_END + +ROM_START( ballbros ) + ROM_REGION( 0x40000, "maincpu", 0 ) // 256k for 68000 code + ROM_LOAD16_BYTE( "10a", 0x00000, 0x20000, CRC(4af0e858) SHA1(817817169aee075d52411bdbe568514511760386) ) + ROM_LOAD16_BYTE( "5a", 0x00001, 0x20000, CRC(0b983a69) SHA1(7be06761a19e1dc5d1404d1920797b406421e365) ) + + ROM_REGION( 0x10000, "audiocpu", 0 ) // 64k for Z80 code + ROM_LOAD( "8d", 0x00000, 0x10000, CRC(d1c515af) SHA1(00451991b4c793487b156f9be2b2e4688325ff24) ) + + ROM_REGION( 0x080000, "gfx1", 0 ) + ROM_LOAD32_BYTE( "3", 0x000003, 0x20000, CRC(ec3e0537) SHA1(51fe5c6ef007c188b2f51ad2225753d2b403e35a) ) // Plane 0 + ROM_LOAD32_BYTE( "2", 0x000002, 0x20000, CRC(bb441717) SHA1(205ae0aa3ded11766ae8f6fe7d08fefff17a9b73) ) // Plane 1 + ROM_LOAD32_BYTE( "1", 0x000001, 0x20000, CRC(8196d624) SHA1(c859e3b1d3b481f38cfe47576efc1dcdbe6cde28) ) // Plane 2 + ROM_LOAD32_BYTE( "0", 0x000000, 0x20000, CRC(1cc584e5) SHA1(18cf607fa06c095d088b80cea2a1e507d19c7126) ) // Plane 3 + + ROM_REGION( 0x80000, "ymsnd:adpcmb", 0 ) // Delta-T samples + ROM_LOAD( "east-11", 0x00000, 0x80000, CRC(92111f96) SHA1(e781f24761b7a923388f4cda64c7b31388fd64c5) ) + + ROM_REGION( 0x80000, "ymsnd:adpcma", 0 ) // ADPCM samples + ROM_LOAD( "east-10", 0x00000, 0x80000, CRC(ca0ac419) SHA1(b29f30a8ff1286c65b741353b6551918a45bcafe) ) +ROM_END + +} // Anonymous namespace + + +GAME( 1988, superman, 0, superman, superman, taitox_cchip_state, empty_init, ROT0, "Taito Corporation", "Superman (World)", MACHINE_SUPPORTS_SAVE ) +GAME( 1988, supermanu, superman, superman, supermanu, taitox_cchip_state, empty_init, ROT0, "Taito Corporation", "Superman (US)", MACHINE_SUPPORTS_SAVE ) +GAME( 1988, supermanj, superman, superman, supermanj, taitox_cchip_state, empty_init, ROT0, "Taito Corporation", "Superman (Japan)", MACHINE_SUPPORTS_SAVE ) +GAME( 1989, twinhawk, 0, daisenpu, twinhawk, taitox_state, empty_init, ROT270, "Taito Corporation Japan", "Twin Hawk (World)", MACHINE_SUPPORTS_SAVE ) +GAME( 1989, twinhawku, twinhawk, daisenpu, twinhawku, taitox_state, empty_init, ROT270, "Taito America Corporation", "Twin Hawk (US)", MACHINE_SUPPORTS_SAVE ) +GAME( 1989, daisenpu, twinhawk, daisenpu, daisenpu, taitox_state, empty_init, ROT270, "Taito Corporation", "Daisenpu (Japan)", MACHINE_SUPPORTS_SAVE ) +GAME( 1989, gigandes, 0, gigandes, gigandes, taitox_state, empty_init, ROT0, "East Technology", "Gigandes", MACHINE_SUPPORTS_SAVE ) +GAME( 1989, gigandesa, gigandes, gigandes, gigandes, taitox_state, empty_init, ROT0, "East Technology", "Gigandes (earlier)", MACHINE_SUPPORTS_SAVE ) +GAME( 1989, kyustrkr, 0, kyustrkr, kyustrkr, taitox_state, empty_init, ROT180, "East Technology", "Last Striker / Kyuukyoku no Striker", MACHINE_SUPPORTS_SAVE ) +GAME( 1992, ballbros, 0, ballbros, ballbros, taitox_state, empty_init, ROT0, "East Technology", "Balloon Brothers", MACHINE_SUPPORTS_SAVE ) diff --git a/cores/taitox/doc/taitocchip.cpp b/cores/taitox/doc/taitocchip.cpp new file mode 100644 index 000000000..145523b75 --- /dev/null +++ b/cores/taitox/doc/taitocchip.cpp @@ -0,0 +1,228 @@ +// license:BSD-3-Clause +// copyright-holders:Jonathan Gevaryahu, David Haywood + +/* + +TC0030CMD "C-chip" pinout: (from operation wolf schematics) +http://www.arcade-museum.com/manuals-videogames/O/Operation%20Wolf%20Schematics.pdf +http://www.jammarcade.net/partial-rainbow-islands-schematic/ + +Chip contains 4 dies: +(starting from pin 1 edge going toward pin 32 edge) +1 - uPD78C11 MCU w/ 4kx8 mask rom (assumed to be the same between games) +2 - uPD27C64 8kx8 EPROM (assumed to be different between games) +3 - uPD4464 8kx8 SRAM +4 - ASIC (NEC ULA) + + + +---------\_/---------+ + VCC -- - | 1 64 | - -- VCC + PA0 <> m | 2 63 | m <- AN7 (tied to GND externally) + PA1 <> m | 3 62 | m <- AN6 + PA2 <> m | 4 61 | m <- AN5 + PA3 <> m | 5 60 | m <- AN4 + PA4 <> m | 6 59 | m <- AN3 + PA5 <> m | 7 58 | m <- AN2 (tied to VCC externally) + PA6 <> m | 8 T 57 | m <- AN1 + PA7 <> m | 9 | 56 | m <- AN0 + PB0 <> m | 10 C ---| 55 | m <- MODE1 (MODE0 and AVSS are internally tied to GND) ** + PB1 <> m | 11 | 54 | m <- /INT1 + PB2 <> m | 12 0 --\ 53 | m <- /NMI, used on rainbow islands + PB3 <> m | 13 | > 52 | m <> PC7 + PB4 <> m | 14 0 --/ 51 | m <> PC6 + PB5 <> m | 15 50 | m <> PC5 + PB6 <> m | 16 3 ---- 49 | m <> PC4 + PB7 <> m | 17 48 | m <> PC3 + PC0 <> m | 18 0 | 47 | m <> PC2 + (tied to VCC) VPP -> e | 19 ---| 46 | m <> PC1 + CLK -> a | 20 C | 45 | a <- A10 + *ASIC_MODESEL ?> a | 21 /--\ 44 | a <- A9 + /RESET -> a | 22 M | | 43 | a <- A8 + D0 <> a | 23 \--/ 42 | a <- A7 + D1 <> a | 24 D 41 | a <- A6 + D2 <> a | 25 40 | a <- A5 + D3 <> a | 26 39 | a <- A4 + D4 <> a | 27 38 | a <- A3 + D5 <> a | 28 37 | a <- A2 + D6 <> a | 29 36 | a <- A1 + D7 <> a | 30 35 | a <- A0 + /CS -> a | 31 34 | a -> DTACK out to 68k (/CDTA) + GND -- - | 32 33 | a <- R/W + +---------------------+ +a = to asic +e = to eprom +m = to mcu +- = power pins, common + +CLK is supplied with a 12MHZ oscillator on operation wolf + +*Pin 21 goes to the ASIC and may be a mode pin. (try holding it to gnd?) Normally tied to 5v thru a 1k resistor. + +** MODE1 is normally tied high externally via a 330ohm resistor, but can be in either state. + MODE0 on the c-chip is internally tied low. + +(move below MODE notes to upd7811.cpp?) + +The four Mode0/Mode1 combinations are: + LOW/LOW 78c11 mem map is 4k external rom (i.e. the eprom inside the c-chip) from 0x0000-0x0FFF; + the low 4 bits of port F are used, to provide the high 4 address bits. + speculation: likely the eprom can be banked so the low or high half is visible here, + or possibly one fixed window and 3 variable windows, managed by the asic? + LOW/HIGH 78c11 mem map boots to internal rom (mask rom inside the 78c11 inside the c-chip) from + 0x0000-0x0fff but the memory map is under full mcu control and can select any of the + four modes (internal only, 4k external, 16k external, 64k external) +The following two modes are unusable on the c-chip: + HIGH/LOW 78c11 mem map is 16k external rom from 0x0000-0x3FFF; + the low 6 bits of port F are used, to provide the high 6 address bits. + HIGH/HIGH 78c11 mem map is 64k external rom from 0x0000-0xFFFF; + all 8 bits of port F are used to provide the high 8 address bits. +VPP is only used for programming the 27c64, do not tie it to 18v or you will probably overwrite the 27c64 with garbage. + +(see http://www.cpcwiki.eu/index.php/UPD7810/uPD7811 ) + + +C-chip EXTERNAL memory map (it acts as a device mapped to ram; dtack is asserted on /cs for a 68k): +0x000-0x3FF = RW ram window, a 1k window into the 8k byte sram inside the c-chip; the 'bank' visible is selected by 0x600 below +0x400-0x403 = "ASIC RAM", 4 bytes of ram on the asic +0x400 = unknown, no idea if /DTACK is asserted for R or W here +0x401 = RW 'test command/status register', writing a 0x02 here starts test mode, will return 0x01 set if ok/ready for + command and 0x04 set if error; this register is very likely handled by the internal rom in the upd78c11 itself rather + than the eprom, and probably tests the sram and the 78c11 internal ram, among other things. + * Current guess: 0x401 is actually attached to the high 2 bits of the PF register; bit 0 is pf6 out, bit 1 is pf6 in + (attached to pf6 thru a resistor?), bit 2 is pf7 out, bit 3 is pf7 in (attached to pf7 through a resistor). + The 78c11 (I'm guessing) reads pf6 and pf7 once per int; if pf6-in is set it reruns the startup selftest, + clears pf6-out, then re-sets it. if there is an error, it also sets pf7. + * Alternate guess: pf4 selects between rom and ram but pf5,6,7 are all mapped to 0x401. a memory mapped register in + upd78c11 space selects low vs high half of rom/ram access +0x402-0x5ff = unknown (may be mirror of 0x400 and 0x401?) no idea if /DTACK is asserted for R or W here +0x600 = ?W ram window bank select, selects one of 8 1k banks to be accessible at 0x000-0x3ff , only low 3 bits are valid on this register. not sure if readable. +0x601-0x7ff = unknown, no idea if /DTACK is asserted for R or W here + +This chip *ALWAYS* has a bypass capacitor (ceramic, 104, 0.10 uF) soldered on top of the chip between pins 1 and 32 OR between 64 and 32. + +*/ + +#include "emu.h" +#include "taitocchip.h" + +#include "cpu/upd7810/upd7810.h" + +//#define VERBOSE 1 +#include "logmacro.h" + + +DEFINE_DEVICE_TYPE(TAITO_CCHIP, taito_cchip_device, "cchip", "Taito TC0030CMD (C-Chip)") + +taito_cchip_device::taito_cchip_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + device_t(mconfig, TAITO_CCHIP, tag, owner, clock), + m_upd7811(*this, "upd7811"), + m_upd4464_bank(*this, "upd4464_bank"), + m_upd4464_bank68(*this, "upd4464_bank68"), + m_sharedram(*this, "upd4464", 0x2000, ENDIANNESS_LITTLE), + m_in_pa_cb(*this, 0), + m_in_pb_cb(*this, 0), + m_in_pc_cb(*this, 0), + m_in_ad_cb(*this, 0), + m_out_pa_cb(*this), + m_out_pb_cb(*this), + m_out_pc_cb(*this) +{ +} + +void taito_cchip_device::ext_interrupt(int state) +{ + m_upd7811->set_input_line(UPD7810_INTF1, state); +} + +ROM_START( taito_cchip ) + ROM_REGION( 0x1000, "upd7811", 0 ) + // optically extracted, the internal checksum passes, although that doesn't rule out the possibility of error + ROM_LOAD( "cchip_upd78c11.bin", 0x0000, 0x1000, CRC(43021521) SHA1(73bc4b46cd2d6805ec926f39f22af00e38a3f822) ) +ROM_END + + +u8 taito_cchip_device::asic_r(offs_t offset) +{ + if ((offset != 0x001) && (!machine().side_effects_disabled())) // prevent logerror spam for now + logerror("%s: asic_r %04x\n", machine().describe_context(), offset); + if (offset < 0x200) // 400-5ff is asic 'ram' + return m_asic_ram[offset&3]; + return 0x00; // 600-7ff is write-only(?) asic banking reg, may read as open bus or never assert /DTACK on read? +} + +void taito_cchip_device::asic_w(offs_t offset, u8 data) +{ + LOG("%s: asic_w %04x %02x\n", machine().describe_context(), offset, data); + if (offset == 0x200) + { + LOG("cchip set bank to %02x\n", data & 0x7); + m_upd4464_bank->set_entry(data & 0x7); + } + else + { + m_asic_ram[offset & 3] = data; + } +} + +void taito_cchip_device::asic68_w(offs_t offset, u8 data) +{ + LOG("%s: asic68_w %04x %02x\n", machine().describe_context(), offset, data); + if (offset == 0x200) + { + LOG("cchip (68k side) set bank to %02x\n", data & 0x7); + m_upd4464_bank68->set_entry(data & 0x7); + } + else + { + m_asic_ram[offset & 3] = data; + } +} + +void taito_cchip_device::cchip_map(address_map &map) +{ + //map(0x0000, 0x0fff).rom(); // internal ROM of uPD7811 + map(0x1000, 0x13ff).bankrw(m_upd4464_bank); + map(0x1400, 0x17ff).rw(FUNC(taito_cchip_device::asic_r), FUNC(taito_cchip_device::asic_w)); + map(0x2000, 0x3fff).rom().region("cchip_eprom", 0); +} + + + +void taito_cchip_device::device_add_mconfig(machine_config &config) +{ + upd78c11_device &upd(UPD78C11(config, m_upd7811, DERIVED_CLOCK(1, 1))); + upd.set_addrmap(AS_PROGRAM, &taito_cchip_device::cchip_map); + upd.pa_in_cb().set([this] { return m_in_pa_cb(); }); + upd.pb_in_cb().set([this] { return m_in_pb_cb(); }); + upd.pc_in_cb().set([this] { return m_in_pc_cb(); }); + upd.pa_out_cb().set([this] (u8 data) { m_out_pa_cb(data); }); + upd.pb_out_cb().set([this] (u8 data) { m_out_pb_cb(data); }); + upd.pc_out_cb().set([this] (u8 data) { m_out_pc_cb(data); }); + upd.pf_out_cb().set([this] (u8 data) { logerror("%s port F written %.2x\n", machine().describe_context(), data); }); // internal? related to locking out the 68k? + upd.an0_func().set([this] { return BIT(m_in_ad_cb(), 0) ? 0xff : 0; }); + upd.an1_func().set([this] { return BIT(m_in_ad_cb(), 1) ? 0xff : 0; }); + upd.an2_func().set([this] { return BIT(m_in_ad_cb(), 2) ? 0xff : 0; }); + upd.an3_func().set([this] { return BIT(m_in_ad_cb(), 3) ? 0xff : 0; }); + upd.an4_func().set([this] { return BIT(m_in_ad_cb(), 4) ? 0xff : 0; }); + upd.an5_func().set([this] { return BIT(m_in_ad_cb(), 5) ? 0xff : 0; }); + upd.an6_func().set([this] { return BIT(m_in_ad_cb(), 6) ? 0xff : 0; }); + upd.an7_func().set([this] { return BIT(m_in_ad_cb(), 7) ? 0xff : 0; }); +} + +void taito_cchip_device::device_start() +{ + m_upd4464_bank->configure_entries(0, m_sharedram.length() / 0x400, &m_sharedram[0], 0x400); + m_upd4464_bank->set_entry(0); + + // the 68k has a different view into the banked memory? + m_upd4464_bank68->configure_entries(0, m_sharedram.length() / 0x400, &m_sharedram[0], 0x400); + m_upd4464_bank68->set_entry(0); + + m_asic_ram[0] = m_asic_ram[1] = m_asic_ram[2] = m_asic_ram[3] = 0; + save_item(NAME(m_asic_ram)); +} + +const tiny_rom_entry *taito_cchip_device::device_rom_region() const +{ + return ROM_NAME(taito_cchip); +} diff --git a/cores/taitox/doc/taitocchip.h b/cores/taitox/doc/taitocchip.h new file mode 100644 index 000000000..1b2555d02 --- /dev/null +++ b/cores/taitox/doc/taitocchip.h @@ -0,0 +1,62 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood, Jonathan Gevaryahu +#ifndef MAME_TAITO_TAITOCCHIP_H +#define MAME_TAITO_TAITOCCHIP_H + +#pragma once + +DECLARE_DEVICE_TYPE(TAITO_CCHIP, taito_cchip_device) + + +class taito_cchip_device : public device_t +{ +public: + // construction/destruction + taito_cchip_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + auto in_pa_callback() { return m_in_pa_cb.bind(); } + auto in_pb_callback() { return m_in_pb_cb.bind(); } + auto in_pc_callback() { return m_in_pc_cb.bind(); } + auto in_ad_callback() { return m_in_ad_cb.bind(); } + auto out_pa_callback() { return m_out_pa_cb.bind(); } + auto out_pb_callback() { return m_out_pb_cb.bind(); } + auto out_pc_callback() { return m_out_pc_cb.bind(); } + + // can be accessed externally + u8 asic_r(offs_t offset); + void asic_w(offs_t offset, u8 data); + void asic68_w(offs_t offset, u8 data); + + u8 mem_r(offs_t offset) { return reinterpret_cast(m_upd4464_bank->base())[offset & 0x03ff]; } + void mem_w(offs_t offset, u8 data) { reinterpret_cast(m_upd4464_bank->base())[offset & 0x03ff] = data; } + + u8 mem68_r(offs_t offset) { return reinterpret_cast(m_upd4464_bank68->base())[offset & 0x03ff]; } + void mem68_w(offs_t offset, u8 data) { reinterpret_cast(m_upd4464_bank68->base())[offset & 0x03ff] = data; } + + void ext_interrupt(int state); + +protected: + void cchip_map(address_map &map) ATTR_COLD; + + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + virtual void device_start() override ATTR_COLD; + virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD; + +private: + u8 m_asic_ram[4]; + + required_device m_upd7811; + required_memory_bank m_upd4464_bank; + memory_bank_creator m_upd4464_bank68; + memory_share_creator m_sharedram; + + devcb_read8 m_in_pa_cb; + devcb_read8 m_in_pb_cb; + devcb_read8 m_in_pc_cb; + devcb_read8 m_in_ad_cb; + devcb_write8 m_out_pa_cb; + devcb_write8 m_out_pb_cb; + devcb_write8 m_out_pc_cb; +}; + +#endif // MAME_TAITO_TAITOCCHIP_H diff --git a/cores/taitox/doc/taitosnd.cpp b/cores/taitox/doc/taitosnd.cpp new file mode 100644 index 000000000..03d6911ed --- /dev/null +++ b/cores/taitox/doc/taitosnd.cpp @@ -0,0 +1,335 @@ +// license:BSD-3-Clause +// copyright-holders:Philip Bennett +/********************************************************************************************** + + Taito TC0140SYT + + TODO: + - Add pinout and description + - Create a separate implementation for the PC060HA + + General rule seems to be that TC0140SYT supports a YM2610, + whereas PC060HA goes with a YM2203 or YM2151. + + The PC060HA has been decapped and verified to be a ULA. + +**********************************************************************************************/ + +#include "emu.h" +#include "taitosnd.h" + +#include "cpu/z80/z80.h" + + +/********************************************************************************************** + + It seems like 1 nibble commands are only for control purposes. + 2 nibble commands are the real messages passed from one board to the other. + +**********************************************************************************************/ + +static constexpr u8 TC0140SYT_PORT01_FULL = 0x01; +static constexpr u8 TC0140SYT_PORT23_FULL = 0x02; +static constexpr u8 TC0140SYT_PORT01_FULL_MASTER = 0x04; +static constexpr u8 TC0140SYT_PORT23_FULL_MASTER = 0x08; + + +// device type definition +DEFINE_DEVICE_TYPE(TC0140SYT, tc0140syt_device, "tc0140syt", "Taito TC0140SYT") +DEFINE_DEVICE_TYPE(PC060HA, pc060ha_device, "pc060ha", "Taito PC060HA CIU") + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// tc0140syt_device - constructor +//------------------------------------------------- + +tc0140syt_device::tc0140syt_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, type, tag, owner, clock) + , m_mainmode(0) + , m_submode(0) + , m_status(0) + , m_nmi_enabled(0) + , m_nmi_cb(*this) + , m_reset_cb(*this) +{ + std::fill(std::begin(m_slavedata), std::end(m_slavedata), 0); + std::fill(std::begin(m_masterdata), std::end(m_masterdata), 0); +} + +tc0140syt_device::tc0140syt_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : tc0140syt_device(mconfig, TC0140SYT, tag, owner, clock) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void tc0140syt_device::device_start() +{ + save_item(NAME(m_mainmode)); + save_item(NAME(m_submode)); + save_item(NAME(m_status)); + save_item(NAME(m_nmi_enabled)); + save_item(NAME(m_slavedata)); + save_item(NAME(m_masterdata)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void tc0140syt_device::device_reset() +{ + m_mainmode = 0; + m_submode = 0; + m_status = 0; + m_nmi_enabled = 0; + + for (u8 i = 0; i < 4; i++) + { + m_slavedata[i] = 0; + m_masterdata[i] = 0; + } +} + + +//------------------------------------------------- +// DEVICE HANDLERS +//------------------------------------------------- + +void tc0140syt_device::update_nmi() +{ + u32 const nmi_pending = m_status & (TC0140SYT_PORT23_FULL | TC0140SYT_PORT01_FULL); + m_nmi_cb((nmi_pending && m_nmi_enabled) ? ASSERT_LINE : CLEAR_LINE); +} + + +//------------------------------------------------- +// MASTER SIDE +//------------------------------------------------- + +void tc0140syt_device::master_port_w(u8 data) +{ + data &= 0x0f; + m_mainmode = data; + + if (data > 4) + { + logerror("tc0140syt : error Master entering unknown mode[%02x]\n", data); + } +} + +void tc0140syt_device::master_comm_w(u8 data) +{ + // let slavecpu catch up (after we return and the main cpu finishes what it's doing) + machine().scheduler().synchronize(); + + data &= 0x0f; // this is important, otherwise ballbros won't work + + switch (m_mainmode) + { + case 0x00: // mode #0 + m_slavedata[m_mainmode++] = data; + break; + + case 0x01: // mode #1 + m_slavedata[m_mainmode++] = data; + m_status |= TC0140SYT_PORT01_FULL; + update_nmi(); + break; + + case 0x02: // mode #2 + m_slavedata[m_mainmode++] = data; + break; + + case 0x03: // mode #3 + m_slavedata[m_mainmode++] = data; + m_status |= TC0140SYT_PORT23_FULL; + update_nmi(); + break; + + case 0x04: // port status + /* this does a hi-lo transition to reset the sound cpu */ + m_reset_cb(data ? ASSERT_LINE : CLEAR_LINE); + break; + + default: + break; + } +} + +u8 tc0140syt_device::master_comm_r() +{ + // let slavecpu catch up (after we return and the main cpu finishes what it's doing) + if (!machine().side_effects_disabled()) + machine().scheduler().synchronize(); + + u8 res = 0; + + switch (m_mainmode) + { + case 0x00: // mode #0 + res = m_masterdata[m_mainmode]; + if (!machine().side_effects_disabled()) + m_mainmode++; + break; + + case 0x01: // mode #1 + res = m_masterdata[m_mainmode]; + if (!machine().side_effects_disabled()) + { + m_status &= ~TC0140SYT_PORT01_FULL_MASTER; + m_mainmode++; + } + break; + + case 0x02: // mode #2 + res = m_masterdata[m_mainmode]; + if (!machine().side_effects_disabled()) + m_mainmode++; + break; + + case 0x03: // mode #3 + res = m_masterdata[m_mainmode]; + if (!machine().side_effects_disabled()) + { + m_status &= ~TC0140SYT_PORT23_FULL_MASTER; + m_mainmode++; + } + break; + + case 0x04: // port status + res = m_status; + break; + + default: + break; + } + + return res; +} + + +//------------------------------------------------- +// SLAVE SIDE +//------------------------------------------------- + +void tc0140syt_device::slave_port_w(u8 data) +{ + data &= 0x0f; + m_submode = data; + + if (data > 6) + { + logerror("tc0140syt error : Slave cpu unknown mode[%02x]\n", data); + } +} + +void tc0140syt_device::slave_comm_w(u8 data) +{ + data &= 0x0f; + + switch (m_submode) + { + case 0x00: // mode #0 + m_masterdata[m_submode++] = data; + break; + + case 0x01: // mode #1 + m_masterdata[m_submode++] = data; + m_status |= TC0140SYT_PORT01_FULL_MASTER; + break; + + case 0x02: // mode #2 + m_masterdata[m_submode++] = data; + break; + + case 0x03: // mode #3 + m_masterdata[m_submode++] = data; + m_status |= TC0140SYT_PORT23_FULL_MASTER; + break; + + case 0x04: // port status + //m_status = TC0140SYT_SET_OK; + break; + + case 0x05: // NMI disable + m_nmi_enabled = 0; + update_nmi(); + break; + + case 0x06: // NMI enable + m_nmi_enabled = 1; + update_nmi(); + break; + + default: + break; + } +} + +u8 tc0140syt_device::slave_comm_r() +{ + u8 res = 0; + + switch (m_submode) + { + case 0x00: // mode #0 + res = m_slavedata[m_submode]; + if (!machine().side_effects_disabled()) + m_submode++; + break; + + case 0x01: // mode #1 + res = m_slavedata[m_submode]; + if (!machine().side_effects_disabled()) + { + m_status &= ~TC0140SYT_PORT01_FULL; + m_submode++; + update_nmi(); + } + break; + + case 0x02: // mode #2 + res = m_slavedata[m_submode]; + if (!machine().side_effects_disabled()) + m_submode++; + break; + + case 0x03: // mode #3 + res = m_slavedata[m_submode]; + if (!machine().side_effects_disabled()) + { + m_status &= ~TC0140SYT_PORT23_FULL; + m_submode++; + update_nmi(); + } + break; + + case 0x04: // port status + res = m_status; + break; + + default: + break; + } + + return res; +} + + +//------------------------------------------------- +// pc060ha_device - constructor +//------------------------------------------------- + +pc060ha_device::pc060ha_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : tc0140syt_device(mconfig, PC060HA, tag, owner, clock) +{ +} diff --git a/cores/taitox/doc/tc0140syt.sv.ref b/cores/taitox/doc/tc0140syt.sv.ref new file mode 100644 index 000000000..d7eb708e2 --- /dev/null +++ b/cores/taitox/doc/tc0140syt.sv.ref @@ -0,0 +1,283 @@ +module TC0140SYT( + input clk, + input ce_12m, + input ce_4m, + + input RESn, + + // 68000 interface + input [3:0] MDin, + output reg [3:0] MDout, + + input MA1, + + input MCSn, + input MWRn, + input MRDn, + + // Z80 interface + input MREQn, + input RDn, + input WRn, + + input [15:0] A, + input [3:0] Din, + output reg [3:0] Dout, + + output ROUTn, + output ROMCS0n, + output ROMCS1n, + output RAMCSn, + output ROMA14, + output ROMA15, + + // YM + output OPXn, + input YAOEn, // not a real signal, on F2 boards these go to the audio ROMs + input YBOEn, + input [23:0] YAA, + input [23:0] YBA, + output [7:0] YAD, + output [7:0] YBD, + + // Peripheral? + output CSAn, + output CSBn, + + output [2:0] IOA, + output IOC, + + // ROM interface + output reg [26:0] sdr_address, + input [15:0] sdr_data, + output reg sdr_req, + input sdr_ack +); + +reg [2:0] rom_bank; +reg [3:0] slave_idx, master_idx; +reg [3:0] status_reg; +reg reset_reg; +reg nmi_enabled; +reg [15:0] slave_data; +reg [15:0] master_data; + +wire bank_req = A[15:14] == 2'b01; // 0x4000-0x7fff +assign ROMCS0n = bank_req ? rom_bank[2] : A[15] | A[14]; // 0x0000 - 0x7fff +assign ROMCS1n = ~(bank_req & rom_bank[2]); // FIXME - guessing +assign RAMCSn = ~A[15] | ~A[14] | A[13]; + +assign ROMA14 = bank_req ? rom_bank[0] : 1'b0; +assign ROMA15 = bank_req ? rom_bank[1] : 1'b0; +assign OPXn = ~(A[15:8] == 8'he0); + +assign ROUTn = RESn & ~reset_reg; // FIXME: don't think this is correct, software reset out + +wire slave_access = (A[15:8] == 8'he2) & ~MREQn; +wire master_access = ~MCSn; +reg prev_slave_access; +reg prev_master_access; + +always_ff @(posedge clk) begin + prev_slave_access <= slave_access; + prev_master_access <= master_access; + if (~RESn) begin + rom_bank <= 3'b000; + status_reg <= 0; + end else begin + if (slave_access & ~prev_slave_access) begin + if (~WRn) begin + if (A[0]) begin + case(slave_idx) + 0: begin + master_data[3:0] <= Din; + slave_idx <= slave_idx + 1; + end + 1: begin + master_data[7:4] <= Din; + slave_idx <= slave_idx + 1; + status_reg[2] <= 1; + end + 2: begin + master_data[11:8] <= Din; + slave_idx <= slave_idx + 1; + end + 3: begin + master_data[15:12] <= Din; + slave_idx <= slave_idx + 1; + status_reg[3] <= 1; + end + 5: begin + nmi_enabled <= 0; + end + 6: begin + nmi_enabled <= 1; + end + + default: begin + end + endcase + end else begin + slave_idx <= Din; + end + end + + if (~RDn & A[0]) begin + case(slave_idx) + 0: begin + Dout <= slave_data[3:0]; + slave_idx <= slave_idx + 1; + end + 1: begin + Dout <= slave_data[7:4]; + slave_idx <= slave_idx + 1; + status_reg[0] <= 0; + end + 2: begin + Dout <= slave_data[11:8]; + slave_idx <= slave_idx + 1; + end + 3: begin + Dout <= slave_data[15:12]; + slave_idx <= slave_idx + 1; + status_reg[1] <= 0; + end + 4: begin + Dout <= status_reg; + end + default: begin + end + endcase + end + end + + if (A[15:8] == 8'hf2 && ~WRn && ~MREQn) begin + rom_bank <= Din[2:0]; + end + + + if (master_access & ~prev_master_access) begin + if (~MWRn & ~MA1) begin + master_idx <= MDin; + end + + if (MA1) begin + if (~MWRn) begin + case(master_idx) + 0: begin + slave_data[3:0] <= MDin; + master_idx <= master_idx + 1; + end + 1: begin + slave_data[7:4] <= MDin; + master_idx <= master_idx + 1; + status_reg[0] <= 1; + end + 2: begin + slave_data[11:8] <= MDin; + master_idx <= master_idx + 1; + end + 3: begin + slave_data[15:12] <= MDin; + master_idx <= master_idx + 1; + status_reg[1] <= 1; + end + 4: begin + reset_reg <= MDin[0]; + end + + default: begin + end + endcase + end + + if (~MRDn) begin + case(master_idx) + 0: begin + MDout <= master_data[3:0]; + master_idx <= master_idx + 1; + end + 1: begin + MDout <= master_data[7:4]; + master_idx <= master_idx + 1; + status_reg[2] <= 0; + end + 2: begin + MDout <= master_data[11:8]; + master_idx <= master_idx + 1; + end + 3: begin + MDout <= master_data[15:12]; + master_idx <= master_idx + 1; + status_reg[3] <= 0; + end + 4: begin + MDout <= status_reg; + end + default: begin + end + endcase + end + end + end + end +end + +// ROM interface + +reg [15:0] cha_data, chb_data; +reg [23:0] cha_addr, chb_addr; +reg cha_request_pending = 0; +reg chb_request_pending = 0; +reg cha_oe_n, chb_oe_n; +reg [1:0] request_active = 0; + +wire cha_oe_edge = ~YAOEn & cha_oe_n; +wire chb_oe_edge = ~YBOEn & chb_oe_n; + +assign YAD = cha_addr[0] ? cha_data[15:8] : cha_data[7:0]; +assign YBD = chb_addr[0] ? chb_data[15:8] : chb_data[7:0]; + +always_ff @(posedge clk) begin + cha_oe_n <= YAOEn; + chb_oe_n <= YBOEn; + + if (cha_oe_edge) begin + cha_addr <= YAA; + if (cha_addr[23:1] != YAA[23:1]) begin + cha_request_pending <= 1; + end + end + + if (chb_oe_edge) begin + chb_addr <= YBA; + if (chb_addr[23:1] != YBA[23:1]) begin + chb_request_pending <= 1; + end + end + + + if (sdr_req == sdr_ack) begin + if (request_active == 2) begin + chb_data <= sdr_data; + request_active <= 0; + end else if (request_active == 1) begin + cha_data <= sdr_data; + request_active <= 0; + end else begin + if (cha_request_pending) begin + cha_request_pending <= 0; + request_active <= 1; + sdr_address <= ADPCMA_ROM_SDR_BASE[26:0] + { 3'd0, cha_addr[23:1], 1'b0 }; + sdr_req <= ~sdr_req; + end else if (chb_request_pending) begin + chb_request_pending <= 0; + request_active <= 2; + sdr_address <= ADPCMB_ROM_SDR_BASE[26:0] + { 3'd0, chb_addr[23:1], 1'b0 }; + sdr_req <= ~sdr_req; + end + end + end +end + +endmodule diff --git a/cores/taitox/doc/twinhawk-back.webp b/cores/taitox/doc/twinhawk-back.webp new file mode 100644 index 000000000..bbe51ea52 Binary files /dev/null and b/cores/taitox/doc/twinhawk-back.webp differ diff --git a/cores/taitox/doc/twinhawk-front.webp b/cores/taitox/doc/twinhawk-front.webp new file mode 100644 index 000000000..b2d4b039f Binary files /dev/null and b/cores/taitox/doc/twinhawk-front.webp differ diff --git a/cores/taitox/hdl/jttaitox_cchip.v b/cores/taitox/hdl/jttaitox_cchip.v new file mode 100644 index 000000000..2c62765d8 --- /dev/null +++ b/cores/taitox/hdl/jttaitox_cchip.v @@ -0,0 +1,86 @@ +/* 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 + Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-8-2026 */ + +module jttaitox_cchip( + input rst, + input clk, + input cen, + + // 68k side, lower byte only + input cs, + input [10:0] addr, + input [ 7:0] din, + output [ 7:0] dout, + input rnw, + input LVBL, + + // cabinet inputs, active low + input [ 6:0] joystick1, + input [ 6:0] joystick2, + input [ 1:0] start_button, + input [ 1:0] coin, + input service, + input tilt, + + // coin counters / lockouts (pc_out), for the coin door + output [ 7:0] counters, + + output [11:0] cchip_mask_addr, + input [ 7:0] cchip_mask_data, + output [12:0] cchip_eprom_addr, + input [ 7:0] cchip_eprom_data +); + +reg [7:0] cc_pa, cc_pb, cc_an; + +always @(posedge clk) begin + cc_pa <= { start_button[0], joystick1[6:4], joystick1[3:0] }; + cc_pb <= { start_button[1], joystick2[6:4], joystick2[3:0] }; + cc_an <= { tilt, 4'hf, service, coin[1], coin[0] }; +end + +jttc0030cmd u_cchip( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), + .cs ( cs ), + .addr ( addr ), + .din ( din ), + .dout ( dout ), + .rnw ( rnw ), + .dtack_n ( ), + .int1 ( ~LVBL ), + .nmi_n ( 1'b1 ), + .pa_in ( cc_pa ), + .pb_in ( cc_pb ), + .pc_in ( 8'hff ), + .pa_out ( ), + .pb_out ( ), + .pc_out ( counters ), + .an ( cc_an ), + .mrom_addr ( cchip_mask_addr ), + .mrom_data ( cchip_mask_data ), + .eprom_addr ( cchip_eprom_addr ), + .eprom_data ( cchip_eprom_data ), + // debug (unused) + .dbg_pc ( ), + .dbg_fetch ( ) +); + +endmodule diff --git a/cores/taitox/hdl/jttaitox_colmix.v b/cores/taitox/hdl/jttaitox_colmix.v new file mode 100644 index 000000000..01ac928d9 --- /dev/null +++ b/cores/taitox/hdl/jttaitox_colmix.v @@ -0,0 +1,58 @@ +/* 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 + Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-8-2026 */ + +/* X1-003 / X1-006 colour stage. */ + +module jttaitox_colmix( + input clk, + input pxl_cen, + input LHBL, + input LVBL, + input [ 8:0] scr_pxl, // X1-001 background column layer + input [ 8:0] obj_pxl, // X1-001 foreground sprites + output reg [ 9:1] pal_addr, + input [15:0] pal_data, + input [ 3:0] gfx_en, + output [ 4:0] red, + output [ 4:0] green, + output [ 4:0] blue +); + +localparam [8:0] BACKDROP = 9'h1f0; // screen_update bitmap.fill(0x1f0) + +reg [ 8:0] col; +reg [14:0] rgb; +wire blank, obj_op, scr_op; + +assign blank = ~(LVBL & LHBL); +assign { red, green, blue } = blank ? 15'd0 : rgb; +// pen 0 is transparent on both layers +assign obj_op = obj_pxl[3:0]!=0 && gfx_en[3]; +assign scr_op = scr_pxl[3:0]!=0 && gfx_en[0]; + +always @* begin + col = obj_op ? obj_pxl : scr_op ? scr_pxl : BACKDROP; +end + +always @(posedge clk) if( pxl_cen ) begin + pal_addr <= col; + rgb <= pal_data[14:0]; +end + +endmodule diff --git a/cores/taitox/hdl/jttaitox_game.v b/cores/taitox/hdl/jttaitox_game.v new file mode 100644 index 000000000..590b597c7 --- /dev/null +++ b/cores/taitox/hdl/jttaitox_game.v @@ -0,0 +1,208 @@ +/* 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 + Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-8-2026 */ + +module jttaitox_game( + `include "jtframe_game_ports.inc" +); + +wire [23:1] cpu_addr; +wire [15:0] vid_dout; +wire [ 1:0] cpu_dsn; +wire [ 7:0] cchip_dout, st_video; +wire [ 3:0] syt_dout; +wire cpu_rnw, cpu_cen, flip, + oram_cs, vdcm_cs, syt_cs, cchip_cs; + +wire p039a, p057a; + +assign debug_view = st_video; +assign st_dout = st_video; +assign dip_flip = ~flip; + +jttaitox_header u_header( + .clk ( clk ), + .header ( header ), + .prog_addr ( prog_addr[3:0]), + .prog_data ( prog_data ), + .prog_we ( prog_we ), + + .p039a ( p039a ), + .p051a ( ), + .p057a ( p057a ) +); + +jttaitox_main u_main( + .rst ( rst ), + .clk ( clk ), + .LVBL ( LVBL ), + + .p039a ( p039a ), + + .cpu_cen ( cpu_cen ), + .cpu_addr ( cpu_addr ), + .cpu_dout ( cpu_dout ), + .cpu_rnw ( cpu_rnw ), + .cpu_dsn ( cpu_dsn ), + + .rom_cs ( main_cs ), + .rom_addr ( main_addr ), + .rom_data ( main_data ), + .rom_ok ( main_ok ), + + .ram_addr ( ram_addr ), + .ram_data ( ram_data ), + .ram_we ( ram_we ), + .ram_dsn ( ram_dsn ), + .ram_ok ( ram_ok ), + .ram_cs ( ram_cs ), + .pal_we ( pal_we ), + .pal_dout ( pal_dout ), + + .oram_cs ( oram_cs ), + .vdcm_cs ( vdcm_cs ), + .vid_dout ( vid_dout ), + + .syt_cs ( syt_cs ), + .syt_dout ( syt_dout ), + + .cchip_cs ( cchip_cs ), + .cchip_dout ( cchip_dout ), + + .joystick1 ( joystick1[6:0]), + .joystick2 ( joystick2[6:0]), + .start_button( cab_1p[1:0] ), + .coin ( coin[1:0] ), + .service ( service ), + .tilt ( tilt ), + .dip_pause ( dip_pause ), + .dipsw_a ( dipsw[ 7:0] ), + .dipsw_b ( dipsw[15:8] ) +); + +jttaitox_cchip u_cchip( + .rst ( rst ), + .clk ( clk ), + .cen ( cen8 ), + .cs ( cchip_cs ), + .addr ( cpu_addr[11:1]), + .din ( cpu_dout[7:0] ), + .dout ( cchip_dout ), + .rnw ( cpu_rnw ), + .LVBL ( LVBL ), + + .joystick1 ( joystick1[6:0]), + .joystick2 ( joystick2[6:0]), + .start_button( cab_1p[1:0] ), + .coin ( coin[1:0] ), + .service ( service ), + .tilt ( tilt ), + .counters ( ), + + .cchip_mask_addr ( cchip_mask_addr ), + .cchip_mask_data ( cchip_mask_data ), + .cchip_eprom_addr( cchip_eprom_addr ), + .cchip_eprom_data( cchip_eprom_data ) +); + +jttaitox_snd u_snd( + .rst ( rst ), + .clk ( clk ), + .cen8 ( cen8 ), + .snd_cen ( snd_cen ), + + .main_cen ( cpu_cen ), + .syt_cs ( syt_cs ), + .main_addr ( cpu_addr[1] ), + .main_dout ( cpu_dout[3:0] ), + .main_din ( syt_dout ), + .main_rnw ( cpu_rnw ), + + .rom_addr ( snd_addr ), + .rom_cs ( snd_cs ), + .rom_ok ( snd_ok ), + .rom_data ( snd_data ), + + .adpcma_addr( adpcma_addr ), + .adpcma_cs ( adpcma_cs ), + .adpcma_data( adpcma_data ), + .adpcmb_addr( adpcmb_addr ), + .adpcmb_cs ( adpcmb_cs ), + .adpcmb_data( adpcmb_data ), + + .fm_l ( fm_l ), + .fm_r ( fm_r ) +); + +jttaitox_video u_video( + .rst ( rst ), + .clk ( clk ), + .pxl_cen ( pxl_cen ), + .pxl2_cen ( pxl2_cen ), + + .LHBL ( LHBL ), + .LVBL ( LVBL ), + .HS ( HS ), + .VS ( VS ), + .flip ( flip ), + + .cpu_rnw ( cpu_rnw ), + .cpu_dsn ( cpu_dsn ), + .cpu_addr ( cpu_addr[13:1]), + .cpu_dout ( cpu_dout ), + .oram_cs ( oram_cs ), + .vdcm_cs ( vdcm_cs ), + .vid_dout ( vid_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 ), + + .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[1:0] ), + .ioctl_din ( ioctl_din ), + .gfx_en ( gfx_en ), + .debug_bus ( debug_bus ), + .st_dout ( st_video ) +); + +endmodule diff --git a/cores/taitox/hdl/jttaitox_main.v b/cores/taitox/hdl/jttaitox_main.v new file mode 100644 index 000000000..2144df234 --- /dev/null +++ b/cores/taitox/hdl/jttaitox_main.v @@ -0,0 +1,252 @@ +/* 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 + Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-8-2026 */ + +module jttaitox_main( + input rst, + input clk, // 48 MHz + input LVBL, + + // Board type from the MRA header. P0-039A is the only board with a + // C-chip, and it is also the only one whose class installs the level-6 + // ISR, so "reads inputs directly at 900000" and "VBL on level 2" are + // both just ~p039a and need no bits of their own. + input p039a, + + output cpu_cen, + output [23:1] cpu_addr, + output [15:0] cpu_dout, + output cpu_rnw, + output [ 1:0] cpu_dsn, + + // 68k program ROM (SDRAM bank 0) + output reg rom_cs, + output [18:1] rom_addr, + input [15:0] rom_data, + input rom_ok, + + // work RAM lives in SDRAM bank 0, palette in BRAM (see cfg/mem.yaml) + output reg ram_cs, + output [13:1] ram_addr, + input [15:0] ram_data, + output ram_we, + output [ 1:0] ram_dsn, + input ram_ok, + output [ 1:0] pal_we, + input [15:0] pal_dout, + + // X1-001 / X1-002, owned by jttaitox_video + output reg oram_cs, // e00000 ORAM CS + output reg vdcm_cs, // d00000 VDCM CS + input [15:0] vid_dout, + + // TC0140SYT + output reg syt_cs, + input [ 3:0] syt_dout, + + // TC0030CMD + output reg cchip_cs, + input [ 7:0] cchip_dout, + + + input [ 6:0] joystick1, + input [ 6:0] joystick2, + input [ 1:0] start_button, + input [ 1:0] coin, + input service, + input tilt, + input dip_pause, + input [ 7:0] dipsw_a, + input [ 7:0] dipsw_b +); + +reg pal_cs, dsw_cs, in_cs; + +`ifndef NOMAIN +wire [23:1] A; +wire cpu_cenb; +wire UDSn, LDSn, RnW, ASn, VPAn, DTACKn; +wire [ 2:0] FC, IPLn; +wire [15:0] cpu_din_w; +reg [15:0] cpu_din; +reg [ 7:0] cab_dout; +wire intn; +wire bus_cs, bus_busy, ok_dly; + +assign cpu_addr = A; +assign rom_addr = A[18:1]; +assign cpu_dsn = { UDSn, LDSn }; +assign cpu_rnw = RnW; +// Two F138s take A22,A21,A20 on C/B/A; A23 picks which one (schematic +// sheet 2). Partial decode: each region mirrors through its 1 MB slot. +always @* begin + syt_cs = 0; + cchip_cs = 0; + in_cs = 0; + pal_cs = 0; + vdcm_cs = 0; + oram_cs = 0; + ram_cs = 0; + rom_cs = 0; + dsw_cs = 0; + if( !ASn && {UDSn,LDSn}!=2'b11 && ~&FC ) begin + // F138 #17 - A23 high + syt_cs = A[23] && A[22:20]==0; + cchip_cs = A[23] && A[22:20]==1 && p039a; + in_cs = A[23] && A[22:20]==1 && !p039a; // no C-chip: direct input port + pal_cs = A[23] && A[22:20]==3; + vdcm_cs = A[23] && A[22:20]==5; + oram_cs = A[23] && A[22:20]==6; + ram_cs = A[23] && A[22:20]==7; + // F138 #18 - A23 low + rom_cs = !A[23] && A[22:19]==0; + dsw_cs = !A[23] && A[22:20]==5; + end +end + +assign ram_addr = A[13:1]; +assign ram_we = ram_cs & ~RnW; +assign ram_dsn = { UDSn, LDSn }; +assign pal_we = {2{pal_cs & ~RnW}} & ~{UDSn,LDSn}; + +// The C-chip games take the VBL interrupt on level 6, the rest on level 2 +assign IPLn = intn ? 3'b111 : (p039a ? 3'b001 : 3'b101); +assign VPAn = !(!ASn && FC==7 && A[3:1]==(p039a ? 3'd6 : 3'd2) && RnW); + +// Both SDRAM buses stall the CPU through DTACK. jtframe_okdly holds the +// busy flag until the slot has answered for the current address. +assign bus_cs = rom_cs | ram_cs; +assign bus_busy = (rom_cs | ram_cs) & ~ok_dly; + +assign cpu_din_w= rom_cs ? rom_data : + ram_cs ? ram_data : + pal_cs ? pal_dout : + (oram_cs | vdcm_cs) ? vid_dout : + cchip_cs ? { 8'hff, cchip_dout } : + // dsw_input_r splits each DIP byte into two nibbles, + // selected by A[2:1]: 0/1 = DSWA lo/hi, 2/3 = DSWB lo/hi + dsw_cs ? { 12'hfff, A[2] ? (A[1] ? dipsw_b[7:4] : dipsw_b[3:0]) + : (A[1] ? dipsw_a[7:4] : dipsw_a[3:0]) } : + in_cs ? { 8'hff, cab_dout } : + syt_cs ? { 12'hfff, syt_dout } : + 16'hffff; + +always @(posedge clk) cpu_din <= cpu_din_w; + +// input_r on the cousins: three ports selected by A[2:1] +always @(posedge clk) begin + case( A[2:1] ) + 0: cab_dout <= { start_button[0], joystick1[6:4], joystick1[3:0] }; + 1: cab_dout <= { start_button[1], joystick2[6:4], joystick2[3:0] }; + 2: cab_dout <= { tilt, 4'hf, service, coin[1], coin[0] }; + default: cab_dout <= 8'hff; + endcase +end + +jtframe_edge #(.QSET(0)) u_int( + .rst ( rst ), + .clk ( clk ), + .edgeof ( ~LVBL & dip_pause ), + .clr ( ~VPAn ), + .q ( intn ) +); + +`ifdef SIMULATION +// 68000 program-fetch dumper. The stream is a superset of MAME's PC list +// because the prefetch also fetches extension words. +integer main_tr; reg asn_q, prog_cyc; reg [23:1] pc_l; reg [15:0] op_l; +wire prog_rd = FC[1] & ~FC[0] & RnW; +initial main_tr = $fopen("taitox_main_fpga.tr","w"); +always @(posedge clk) begin + asn_q <= ASn; + if(!ASn && prog_rd) begin prog_cyc<=1; pc_l<=A; op_l<=cpu_din_w; end + if(!asn_q && ASn) begin + if(prog_cyc && main_tr!=0) $fwrite(main_tr,"%06X: %04X\n",{pc_l,1'b0},op_l); + prog_cyc<=0; + end +end +final if(main_tr!=0) $fclose(main_tr); +`endif + + +jtframe_okdly #(.W(2)) u_okdly( + .rst ( rst ), + .clk ( clk ), + .cs ( { rom_cs, ram_cs } ), + .ok ( { rom_ok, ram_ok } ), + .ok_dly ( ok_dly ) +); + +jtframe_68kdtack_cen #(.W(8)) u_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}), + // 16 MHz XTAL / 2 = 8 MHz, exactly 48/6 + .num ( 7'd1 ), + .den ( 8'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 ( FC ), + + .BERRn ( 1'b1 ), + .HALTn ( 1'b1 ), + .BRn ( 1'b1 ), + .BGACKn ( 1'b1 ), + .BGn ( ), + + .DTACKn ( DTACKn ), + .IPLn ( IPLn ) +); +`else +assign cpu_addr=0, cpu_dout=0, cpu_rnw=1, cpu_dsn=3, cpu_cen=0, + rom_addr=0, ram_addr=0, ram_we=0, ram_dsn=3, pal_we=0; +initial begin + rom_cs=0; oram_cs=0; vdcm_cs=0; syt_cs=0; cchip_cs=0; + ram_cs=0; pal_cs=0; dsw_cs=0; in_cs=0; +end +`endif + +endmodule diff --git a/cores/taitox/hdl/jttaitox_snd.v b/cores/taitox/hdl/jttaitox_snd.v new file mode 100644 index 000000000..e630ddf2d --- /dev/null +++ b/cores/taitox/hdl/jttaitox_snd.v @@ -0,0 +1,166 @@ +/* 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 + Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-8-2026 */ + +module jttaitox_snd( + input rst, + input clk, + input cen8, // YM2610 + input snd_cen, // Z80, gated on the sound-ROM wait + + // 68k side of the comm chip + input main_cen, + input syt_cs, + input main_addr, // 68k A1 + input [ 3:0] main_dout, + output [ 3:0] main_din, + input main_rnw, + + output [15:0] rom_addr, + output rom_cs, + input rom_ok, + input [ 7:0] rom_data, + + output [18:0] adpcma_addr, + output adpcma_cs, + input [ 7:0] adpcma_data, + output [18:0] adpcmb_addr, + output adpcmb_cs, + input [ 7:0] adpcmb_data, + + output signed [15:0] fm_l, fm_r +); + +`ifndef NOSOUND +wire [15:0] A; +wire [ 7:0] z80_dout, ym_dout, ram_dout; +wire [ 3:0] syt_dout; +wire mreq_n, rd_n, wr_n, iorq_n, m1_n, rfsh_n, int_n, nmi_n, cpu_cen; +wire snd_rst, rst_n; +reg [ 7:0] din; +wire ram_cs, ym_cs, syt_sel, opx_n; +wire [19:0] ym_adpcma_addr; +wire [23:0] ym_adpcmb_addr; +wire [ 4:0] ym_adpcma_bank; +wire ym_adpcma_roe_n, ym_adpcmb_roe_n; + +assign ym_cs = ~opx_n; +assign rst_n = ~(rst | snd_rst); + +assign adpcma_addr = ym_adpcma_addr[18:0]; +assign adpcma_cs = ~ym_adpcma_roe_n; +assign adpcmb_addr = ym_adpcmb_addr[18:0]; +assign adpcmb_cs = ~ym_adpcmb_roe_n; + +always @(posedge clk) begin + din <= rom_cs ? rom_data : + ram_cs ? ram_dout : + ym_cs ? ym_dout : + syt_sel ? { 4'd0, syt_dout } : 8'hff; +end + +jttaitox_tc0140syc u_syt( + .rst ( rst ), + .clk ( clk ), + .main_cen ( main_cen ), + .snd_cen ( snd_cen ), + + .main_cs ( syt_cs ), + .main_addr ( main_addr ), + .main_dout ( main_dout ), + .main_din ( main_din ), + .main_rnw ( main_rnw ), + + .a ( A ), + .din ( z80_dout ), + .dout ( syt_dout ), + .mreq_n ( mreq_n ), + .rfsh_n ( rfsh_n ), + .wr_n ( wr_n ), + .nmi_n ( nmi_n ), + .z80_rst ( snd_rst ), + + .rom_cs ( rom_cs ), + .rom_addr ( rom_addr ), + .ram_cs ( ram_cs ), + .opx_n ( opx_n ), + .syt_cs ( syt_sel ) +); + +jtframe_sysz80 #(.RECOVERY(0), .RAM_AW(13)) u_z80( + .rst_n ( rst_n ), + .clk ( clk ), + .cen ( snd_cen ), + .cpu_cen ( cpu_cen ), + .int_n ( int_n ), + .nmi_n ( nmi_n ), + .busrq_n ( 1'b1 ), + .m1_n ( m1_n ), + .mreq_n ( mreq_n ), + .iorq_n ( iorq_n ), + .rd_n ( rd_n ), + .wr_n ( wr_n ), + .rfsh_n ( rfsh_n ), + .halt_n ( ), + .busak_n ( ), + .A ( A ), + .cpu_din ( din ), + .cpu_dout ( z80_dout ), + .ram_dout ( ram_dout ), + .ram_cs ( ram_cs ), + .rom_cs ( rom_cs ), + .rom_ok ( rom_ok ) +); + +jt10 u_jt10( + .rst ( ~rst_n ), + .clk ( clk ), + .cen ( cen8 ), + .din ( z80_dout ), + .addr ( A[1:0] ), + .cs_n ( ~ym_cs ), + .wr_n ( wr_n ), + + .dout ( ym_dout ), + .irq_n ( int_n ), + + .adpcma_addr ( ym_adpcma_addr ), + .adpcma_bank ( ym_adpcma_bank ), + .adpcma_roe_n ( ym_adpcma_roe_n ), + .adpcma_data ( adpcma_data ), + .adpcmb_addr ( ym_adpcmb_addr ), + .adpcmb_roe_n ( ym_adpcmb_roe_n ), + .adpcmb_data ( adpcmb_data ), + + .psg_A ( ), + .psg_B ( ), + .psg_C ( ), + .fm_snd ( ), + .psg_snd ( ), + .snd_right ( fm_r ), + .snd_left ( fm_l ), + .snd_sample ( ), + .ch_enable ( 6'b111111 ) +); +`else +assign rom_addr=0, rom_cs=0, main_din=0, + adpcma_addr=0, adpcma_cs=0, adpcmb_addr=0, adpcmb_cs=0, + fm_l=0, fm_r=0; +`endif + +endmodule diff --git a/cores/taitox/hdl/jttaitox_tc0140syc.v b/cores/taitox/hdl/jttaitox_tc0140syc.v new file mode 100644 index 000000000..3ab70e468 --- /dev/null +++ b/cores/taitox/hdl/jttaitox_tc0140syc.v @@ -0,0 +1,98 @@ +/* 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 + Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 17-8-2026 */ + +/* Taito TC0140SYT. + + The 68000<->Z80 nibble mailbox is very similar to PC060HA + + On top of that the TC0140SYT owns the Z80 memory decode, which the + PC060HA does not: it emits the ROM and RAM chip selects and holds the + 16 kB bank latch. That is what this module adds around the mailbox. +*/ + +module jttaitox_tc0140syc( + input rst, + input clk, + input main_cen, + input snd_cen, + + // 68000 side: 800001 port, 800003 comm + input main_cs, + input main_addr, // A1 + input [ 3:0] main_dout, + output [ 3:0] main_din, + input main_rnw, + + // Z80 side + input [15:0] a, + input [ 7:0] din, + output [ 3:0] dout, + input mreq_n, + input rfsh_n, + input wr_n, + output nmi_n, + output z80_rst, // slave reset requested by the 68000 + + // Z80 memory decode + output rom_cs, + output [15:0] rom_addr, // 16 kB pages, low 64 kB of the sound ROM + output ram_cs, + output opx_n, // YM select, active low + output syt_cs // this chip's own select +); + +wire mem; +reg [1:0] bank; + +assign mem = ~mreq_n & rfsh_n; +assign rom_cs = mem & ~a[15]; +assign ram_cs = mem & a[15:13]==3'b110; +assign opx_n = ~(mem & a[15:8]==8'hE0); +assign syt_cs = mem & a[15:8]==8'hE2; +assign rom_addr = { a[14] ? bank : 2'd0, a[13:0] }; + +always @(posedge clk) begin + if( rst ) + bank <= 0; + else if( mem && a[15:8]==8'hF2 && !wr_n ) + bank <= din[1:0]; +end + +jtrastan_pc060 u_mailbox( + .rst ( rst ), + .clk ( clk ), + .main_cen ( main_cen ), + .snd_cen ( snd_cen ), + + .main_dout ( main_dout ), + .main_din ( main_din ), + .main_addr ( main_addr ), + .main_rnw ( main_rnw ), + .main_cs ( main_cs ), + + .snd_dout ( din[3:0] ), + .snd_din ( dout ), + .snd_addr ( a[0] ), + .snd_rnw ( wr_n ), + .snd_cs ( syt_cs ), + .snd_nmin ( nmi_n ), + .snd_rst ( z80_rst ) +); + +endmodule diff --git a/cores/taitox/hdl/jttaitox_video.v b/cores/taitox/hdl/jttaitox_video.v new file mode 100644 index 000000000..121c5045b --- /dev/null +++ b/cores/taitox/hdl/jttaitox_video.v @@ -0,0 +1,186 @@ +/* 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 + Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-8-2026 */ + +module jttaitox_video( + input rst, + input clk, + input pxl_cen, + input pxl2_cen, + + output LHBL, + output LVBL, + output HS, + output VS, + output flip, + + // 68k side + input cpu_rnw, + input [ 1:0] cpu_dsn, + input [12:0] cpu_addr, // A[13:1] + input [15:0] cpu_dout, + input oram_cs, // e00000 ORAM CS + input vdcm_cs, // d00000 VDCM CS + output [15:0] vid_dout, + + // X1-001 internal RAM (mem.yaml `yram`) + output [ 9:0] col_addr, + input [ 7:0] col_data, yram_dout, + output yram_we, + // OBJ RAM (mem.yaml `dma`) + output [13:1] dma_addr, + output [15:0] dma_din, + output [ 1:0] dma_we, + input [15:0] dma_dout, code_dout, + output [13:1] code_addr, + + // palette (mem.yaml `pal`) + output [ 9:1] pal_addr, + input [15:0] pal_data, + + // gfx ROMs + output [20:2] scr_addr, + input [31:0] scr_data, + input scr_ok, + output scr_cs, + output [20:2] obj_addr, + input [31:0] obj_data, + input obj_ok, + output obj_cs, + + output [ 4:0] red, green, blue, + + input [ 1:0] ioctl_addr, + output [ 7:0] ioctl_din, + input [ 3:0] gfx_en, + input [ 7:0] debug_bus, + output [ 7:0] st_dout +); + +wire [8:0] vdump, vrender, hdump; +wire [8:0] scr_pxl, obj_pxl; + +// TODO this timing needs to be verified on an original board +// mame notes have a different xtal clearly a different board +// of superman was used to measure timings, not the 039a. +jtframe_vtimer #( + .HB_END ( 9'd1 ), + .HB_START( 9'd385 ), + .HS_START( 9'd409 ), + .HS_END ( 9'd461 ), + .HCNT_END( 9'd511 ), + .V_START ( 9'd000 ), + .VS_START( 9'd253 ), + .VS_END ( 9'd261 ), + .VB_START( 9'd247 ), + .VB_END ( 9'd007 ), + .VCNT_END( 9'd271 ) +) u_timer( + .clk ( clk ), + .pxl_cen ( pxl_cen ), + .vdump ( vdump ), + .vrender ( vrender ), + .vrender1 ( ), + .H ( hdump ), + .Hinit ( ), + .Vinit ( ), + .LHBL ( LHBL ), + .LVBL ( LVBL ), + .HS ( HS ), + .VS ( VS ) +); + +jtkiwi_gfx #( + .CPUW ( 16 ), + .OBJAW( 13 ) +) u_gfx( + .rst ( rst ), + .clk ( clk ), + .clk_cpu ( clk ), + + .pxl2_cen ( pxl2_cen ), + .pxl_cen ( pxl_cen ), + + .LHBL ( LHBL ), + .LVBL ( LVBL ), + .hs ( HS ), + .vs ( VS ), + .flip ( flip ), + .drtoppel ( 1'b0 ), + + .vdump ( vdump ), + .vrender ( vrender ), + .hdump ( hdump ), + + .cpu_rnw ( cpu_rnw ), + .cpu_dsn ( cpu_dsn ), + .cpu_addr ( cpu_addr ), + .cpu_dout ( cpu_dout ), + .vram_cs ( oram_cs ), + + .vctrl_cs ( vdcm_cs ), + .vflag_cs ( 1'b0 ), // no flag register on this board + .cpu_din ( vid_dout ), + + .ioctl_addr ( ioctl_addr), + .ioctl_din ( ioctl_din ), + + .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 ), + + .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 ), + + .scr_pxl ( scr_pxl ), + .obj_pxl ( obj_pxl ), + .debug_bus ( debug_bus ), + .st_dout ( st_dout ) +); + +jttaitox_colmix u_colmix( + .clk ( clk ), + .pxl_cen ( pxl_cen ), + .LHBL ( LHBL ), + .LVBL ( LVBL ), + .scr_pxl ( scr_pxl ), + .obj_pxl ( obj_pxl ), + .pal_addr ( pal_addr ), + .pal_data ( pal_data ), + .gfx_en ( gfx_en ), + .red ( red ), + .green ( green ), + .blue ( blue ) +); + +endmodule diff --git a/cores/taitox/ver/ballbros/reg.cab b/cores/taitox/ver/ballbros/reg.cab new file mode 100644 index 000000000..a5d2a7a3a --- /dev/null +++ b/cores/taitox/ver/ballbros/reg.cab @@ -0,0 +1,12 @@ +# Regression script: boot, insert a coin, start a 1P game. +# Ballbros then shows a mode-select screen - "SELECT AND PRESS BUTTON +# ACCORDINGLY" - where the left arrow is ONE PLAYER. Hold left, then press +# the action button with it to confirm. +=560 +4 coin +40 +4 1p +60 +8 left +8 left b1 +200 diff --git a/cores/taitox/ver/gigandes/reg.cab b/cores/taitox/ver/gigandes/reg.cab new file mode 100644 index 000000000..52b1a34e7 --- /dev/null +++ b/cores/taitox/ver/gigandes/reg.cab @@ -0,0 +1,6 @@ +# Regression script: boot, insert a coin, start a 1P game. +=560 +4 coin +40 +4 1p +200 diff --git a/cores/taitox/ver/kyustrkr/reg.cab b/cores/taitox/ver/kyustrkr/reg.cab new file mode 100644 index 000000000..52b1a34e7 --- /dev/null +++ b/cores/taitox/ver/kyustrkr/reg.cab @@ -0,0 +1,6 @@ +# Regression script: boot, insert a coin, start a 1P game. +=560 +4 coin +40 +4 1p +200 diff --git a/cores/taitox/ver/superman/mame_scripts/dump_burst.lua b/cores/taitox/ver/superman/mame_scripts/dump_burst.lua new file mode 100644 index 000000000..ab1de1131 --- /dev/null +++ b/cores/taitox/ver/superman/mame_scripts/dump_burst.lua @@ -0,0 +1,40 @@ +-- Taito X burst scene dump: 20 scenes, 300 frames apart (5s..100s @ ~57.4Hz). +-- Regions are the CPU-visible views of the X1-001/X1-002/X1-006 RAMs, byte +-- order as the 68000 sees them (big-endian). The FPGA SIMFILE loader must +-- byte-swap to FPGA-native order. +-- pal b00000 0x1000 palette, only the low 0x400 is real (X1-006 sees A9..A1) +-- yram d00000 0x0600 spriteylow: 0x000-0x2ff Y, 0x200-0x2ff BG column scroll +-- ctrl d00600 0x0008 the four spritectrl words +-- oram e00000 0x4000 OBJ RAM, both setac buffers +local mem = manager.machine.devices[":maincpu"].spaces["program"] +local screen; for _,s in pairs(manager.machine.screens) do screen=s; break end + +local targets = {} +for i=1,20 do targets[i] = i*300 end +local idx = 1 + +local regions = { + { name="pal.bin", start=0xb00000, len=0x1000 }, + { name="yram.bin", start=0xd00000, len=0x0600 }, + { name="ctrl.bin", start=0xd00600, len=0x0008 }, + { name="oram.bin", start=0xe00000, len=0x4000 }, +} + +local function capture(frame) + local dir = string.format("/tmp/taitox_burst_%05d", frame) + os.execute("mkdir -p '"..dir.."'") + for _,r in ipairs(regions) do + local f = io.open(dir.."/"..r.name, "wb") + for a = r.start, r.start+r.len-1 do f:write(string.char(mem:read_u8(a, false))) end + f:close() + end + manager.machine.video:snapshot() + print(string.format("SCENE %05d dumped", frame)) +end + +emu.register_frame_done(function() + if idx <= #targets and screen:frame_number() >= targets[idx] then + capture(targets[idx]); idx = idx + 1 + if idx > #targets then manager.machine:exit() end + end +end) diff --git a/cores/taitox/ver/superman/mame_scripts/trace_main_boot.mame b/cores/taitox/ver/superman/mame_scripts/trace_main_boot.mame new file mode 100644 index 000000000..25793ff17 --- /dev/null +++ b/cores/taitox/ver/superman/mame_scripts/trace_main_boot.mame @@ -0,0 +1,4 @@ +trace /tmp/taitox_main.tr,maincpu,noloop +focus maincpu +go +quit diff --git a/cores/taitox/ver/superman/reg.cab b/cores/taitox/ver/superman/reg.cab new file mode 100644 index 000000000..240040d10 --- /dev/null +++ b/cores/taitox/ver/superman/reg.cab @@ -0,0 +1,7 @@ +# Regression script: boot to the title, insert a coin, start a 1P game. +# Superman reaches the title around frame 530 with a warm SDRAM cache. +=560 +4 coin +40 +4 1p +200 diff --git a/doc/mame.xml b/doc/mame.xml index 462a6ef64..2c47db45a 100644 --- a/doc/mame.xml +++ b/doc/mame.xml @@ -161,7 +161,7 @@ ]> - + 1941: Counter Attack (World 900227) 1990 Capcom @@ -248515,6 +248515,1170 @@ + + Superman (World) + 1988 + Taito Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Superman (US) + 1988 + Taito Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Superman (Japan) + 1988 + Taito Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Twin Hawk (World) + 1989 + Taito Corporation Japan + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Twin Hawk (US) + 1989 + Taito America Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Daisenpu (Japan) + 1989 + Taito Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Gigandes + 1989 + East Technology + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Gigandes (earlier) + 1989 + East Technology + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Last Striker / Kyuukyoku no Striker + 1989 + East Technology + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Balloon Brothers + 1992 + East Technology + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Volfied (World, rev 1) 1989