Sega System C/C2 as in current MAME: segac2.c only C/C2, the Mega Drive part in machine/megadriv.c, 25 new sets (#2181)

- machine/megadriv.c / includes/megadriv.h: the Mega Drive part shared by
  the Mega-Tech, Mega Play, bootleg, Y-BOX and Sun Mixing boards (the VDP
  interrupts, also used by System C/C2, the sound Z80 and its bus, the I/O,
  the machine drivers), moved out of segac2.c; the Mega-Tech / Mega Play
  BIOS VDP ports go to megatech.c, its interrupt to megaplay.c; dead code
  removed (the unused cart maps, inputs and I/O init)
- segac2.c: only System C/C2, with the sets, ROMs, titles, inputs and DIP
  switches of current MAME (57 sets instead of 32; puyopuyo/puyopuya/puyopuyb are now
  puyoj/puyoja/puyobl, columns2 and stkclmns (Japan) are now column2j and
  stkclmnsj, with the World sets as parents)
- the protection chip as the EPM5032 logic of each game of current MAME
  (identical to the old tables where they were real; Ribbit!, Poto Poto and
  Puyo Puyo 2 had fake tables and workarounds)
- the alternate palette mode of Ribbit! and Twin Squash (control bit 2),
  through palette lookups in the VDP, instead of watching Ribbit! ROM reads
- the 68000 at XL2/6 (8.95 MHz) and the refresh at 59.92 Hz as in current
  MAME (it was XL2/7 and 60 Hz); V-INT and H-INT held until the 68000
  acknowledges them, as on the board
- YM2612/YM3438 (shared): the busy flag for 192 clocks after a data write,
  and a timer started long after its last overflow runs a whole period, as
  in current MAME
- Mega Play: the BIOS VDP V-INT about 12 lines after the Mega Drive VBLANK,
  as in current MAME (Tecmo World Cup could stay on a black screen)
- Mega Play / System E: the BIOS VDP tile lines read byte by byte (wrong
  colours on big-endian hosts)
- the address mirrors, the battery-backed work RAM (0xff filled), the coin
  meters on the I/O chip, the Waku Waku Marine / Anpanman wheel
- save states: the alternate palette mode and the Bloxeed YM3438 kludge
- metadata/mame2003-plus.xml, CHANGELOG.md


Claude-Session: https://claude.ai/code/session_01N3fzdsnzkQVtgYtYzqepjX

Co-authored-by: Claude <[email protected]>
This commit is contained in:
zanacandClaude authored and GitHub committed 2026-10-30 03:39:39 -04:00
1 parent d7117cdcdc
commit a1fb5c7993
19 files changed
+6364 -3411

No files matched your search

+23
View File
@@ -54,6 +54,7 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
* Choky! Choky!
* Choutetsu Brikin'ger - iron clad
* Clockwork Aquario
* Columns II: The Voyage Through Time (World) - Romset `columns2`; the old `columns2` (Japan) is now its clone `column2j`, as in current MAME
* Combat Hawk
* Come Back Toto
* Cookie & Bibi
@@ -200,6 +201,7 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
* Power Up Baseball
* Progear
* Puckman Pockimon Genie 2000 - Romset `puckpkmn` - the set of current MAME; the old `puckpkmn` set is now its clone `puckpkmnb`, as in current MAME
* Puyo Puyo (World) - Romset `puyo`; the old `puyopuyo`, `puyopuya` and `puyopuyb` are now its clones `puyoj`, `puyoja` and `puyobl`, as in current MAME
* Puzz Loop 2 (All Sets)
* Puzzle Break
* Puzzle Star
@@ -230,6 +232,8 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
* Sega Megaplay : Streets Of Rage II
* Sega Megaplay : Tecmo World Cup
* Sega Sonic Bros (Japan, Prototype)
* SegaSonic Cosmo Fighter (World and Japan) - Romsets `sonicfgt`, `sonicfgtj`
* SegaSonic Popcorn Shop (Rev B) - Romset `sonicpop` - the popcorn machine itself isn't emulated, as in current MAME
* Sengoku 3
* Shuihu Feng Yun Zhuan
* Skater (Deco Cassette)
@@ -242,11 +246,13 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
* Sonic Boom
* Sonic The Hedgehog 2 (Bootleg Of Megadrive Version)
* Sonic The Hedgehog 3 (Bootleg Of Megadrive Version)
* Soreike! Anpanman Popcorn Koujou (Rev B and Rev A) - Romsets `anpanman`, `anpanmana` - the popcorn machine itself isn't emulated, as in current MAME
* Space Fever High Splitter
* Space Launcher
* Space Raider
* Spectrum 2000 (Euro)
* Squash
* Stack Columns (World) - Romset `stkclmns`; the old `stkclmns` (Japan) is now its clone `stkclmnsj`, as in current MAME
* Stadium Cross (World, linkable) and (US) - Romsets `scrossa`, `scrossu`; `scross` now uses the ROM names of current MAME
* Star Fire 2
* Steel Worker
@@ -287,6 +293,7 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
* Turkey Hunting
* Twin Cobra 2
* Twin Action
* Twin Squash - Romset `twinsqua`
* Twinkle
* Twinkle Tale (Bootleg Of Megadrive Version)
* TX-1 (World, Japan rev. B and C)
@@ -296,6 +303,11 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
* Vasara 2
* Virtua Bowling
* Virtua Fighter
* Waku Waku Anpanman (Rev A and original) - Romsets `wwanpanm`, `wwanpanmo`
* Waku Waku Jumbo (Rev A) - Romset `wwjumbo`
* Waku Waku Marine - Romset `wwmarine`
* Waku Waku Pajero - Romset `wwpajero`
* Waku Waku Sonic Patrol Car - Romset `soniccar`
* Wheels Runner
* Wing Force
* Wing Shooting Championship
@@ -315,6 +327,13 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
* Asura Buster - Eternal Warriors (USA), (Japan, set 2) and (Japan) (ARCADIA review build) - Romsets `asurabus`, `asurabusja`, `asurabusjr`; the Japan set 1 is now `asurabusj`, as in current MAME
* Bare Knuckle III (bootleg of Mega Drive version, alt set, the PIC simulated) - Romset `barek3mba` - not working, as in current MAME
* Bare Knuckle III / Sunset Riders (scrambled bootleg of Mega Drive versions) - Romset `bk3ssrmb` - not working, as in current MAME (only Bare Knuckle III boots)
* Bloxeed (US, C System, Rev A) - Romset `bloxeedu`
* Borench (set 2) and (Japan) - Romsets `borencha`, `borenchj`
* Columns (US, cocktail, Rev A) - Romset `columnsu`
* Print Club (World) and (Japan Vol.3) - Romsets `pclub`, `pclubjv3` - not working (camera and printer), as in current MAME
* Puzzle & Action: Ichidant-R (World) (bootleg) - Romset `ichirbl`
* Puzzle & Action: Tant-R (Japan) (bootleg set 3 and set 4) - Romsets `tantrbl3`, `tantrbl4`
* Ribbit! (Japan) - Romset `ribbitj`
* Sunset Riders / Super Street Fighter II - The New Challengers (scrambled bootleg of Mega Drive versions) - Romset `srssf2mb` - not working, as in current MAME (the order of the ROMs is not known)
* Battle Shark (Japan, Joystick)
* Bloxeed (bootleg) - Romset `bloxeedd`
@@ -850,6 +869,10 @@ Notes on this option:
* Sega Mega Play: the BIOS overlay is transparent on colour 0 of both its palettes and covers its borders, as in current MAME (the boot logo screen was hidden behind a green background)
* Sega Mega Drive based bootlegs: their own driver (`drivers/megadriv_acbl.c`, as in current MAME), with the board variants of current MAME (the 6 button pads, the DIP switches at 0x770070 of the scrambled boards, the 3rd I/O port coins, the PIC16C57 of `barek2mb`); the new sets take their V-INT / H-INT through the VDP interrupt enables as on the real hardware (Mortal Kombat 3 crashed at boot), the descrambling of the bootlegs and the PIC of `barek2mb` now also work on big-endian hosts
* Genie / Y-BOX and Sun Mixing boards: their own drivers (`drivers/megadriv_ybox.c`, `drivers/megadriv_sunmix.c`, as in current MAME); the Y-BOX games run on the Mega Drive machine as in MAME (Z80, I/O, the VDP interrupts and HBLANK as on the real hardware), with the protection read back latches and the ROM address remapping of Shuihu Feng Yun Zhuan of current MAME
* Sega System C/C2: `drivers/segac2.c` now has only System C/C2, the Mega Drive part shared by the other boards is in `machine/megadriv.c` (as `megadriv.cpp` in current MAME); the sets, ROMs, titles, inputs and DIP switches as in current MAME; the protection chip as the EPM5032 logic of each game of current MAME (no more Ribbit! and Puyo Puyo 2 workarounds and fake tables, Print Club Vol.2, 4 and 5 now get past the protection); the alternate palette mode of Ribbit! and Twin Squash (instead of the palette address watching of Ribbit!); the 68000 at 8.95 MHz and the 59.92 Hz refresh as in current MAME (it ran at 7.67 MHz and 60 Hz: the games now follow the timing of MAME frame for frame), the V-INT and H-INT held until the 68000 takes them as on the board, the address mirrors, the battery-backed work RAM (high scores kept, as in current MAME) and the coin meters on the I/O chip
* YM2612 / YM3438: the busy flag after a data write (192 clocks, as in current MAME), and a timer started long after its last overflow runs a whole period instead of firing at once (Thunder Force AC, Bloxeed and the other System C2 games follow MAME again)
* Sega Mega Play: the V-INT of the BIOS VDP comes about 12 lines after the Mega Drive VBLANK, as in current MAME (it came ~80 lines early, and the BIOS/game handshake on port C could miss: Tecmo World Cup stayed on a black screen)
* Sega Mega Play / System E: the tiles of the SMS-type VDP are read byte by byte, so they are drawn right on big-endian hosts (the Mega Play BIOS screen had the wrong colours)
* Sega Mega Drive VDP: in H32 mode the sprite table base uses bit 0 of register 5, as on the real VDP (the fighters of Super Street Fighter II were missing, the sprites of Bonanza Bros. on Mega-Tech were garbled)
* PIC16C5x CPU core: the program counter wraps at the end of the program memory (the 2K parts start at 0x7ff and ran past the ROM), and the save states no longer register the ports and STATUS through a NULL pointer (the save of a game with a PIC crashed); these are in the data RAM, saved with the CPU memory
* Save states (netplay, RunAhead with a second instance) of the Mega Drive based boards: the Z80 RAM and bus state and the Mega-Tech / Mega Play BIOS registers and RAM are saved (Gunstar Heroes and Mazin Wars Mega Play went out of sync after loading a state in a new instance); the SN76496 PSG is saved, and the YM2612 DAC enable is restored from its own register (0x2b, it was read from 0x2d)
+1 -1
View File
@@ -529,7 +529,7 @@ SOURCES_C += \
$(CORE_DIR)/drivers/system24.c $(CORE_DIR)/machine/system24_machine.c $(CORE_DIR)/vidhrdw/system24_vidhrdw.c \
$(CORE_DIR)/vidhrdw/segaic24.c $(CORE_DIR)/vidhrdw/segas18.c \
$(CORE_DIR)/drivers/segas32.c $(CORE_DIR)/machine/segas32.c $(CORE_DIR)/vidhrdw/segas32.c \
$(CORE_DIR)/vidhrdw/segavdp.c $(CORE_DIR)/vidhrdw/segac2_vidhrdw.c $(CORE_DIR)/drivers/segac2.c $(CORE_DIR)/drivers/megaplay.c $(CORE_DIR)/drivers/megatech.c $(CORE_DIR)/drivers/megadriv_acbl.c $(CORE_DIR)/drivers/megadriv_ybox.c $(CORE_DIR)/drivers/megadriv_sunmix.c \
$(CORE_DIR)/vidhrdw/segavdp.c $(CORE_DIR)/vidhrdw/segac2_vidhrdw.c $(CORE_DIR)/machine/megadriv.c $(CORE_DIR)/drivers/segac2.c $(CORE_DIR)/drivers/megaplay.c $(CORE_DIR)/drivers/megatech.c $(CORE_DIR)/drivers/megadriv_acbl.c $(CORE_DIR)/drivers/megadriv_ybox.c $(CORE_DIR)/drivers/megadriv_sunmix.c \
$(CORE_DIR)/drivers/stv.c $(CORE_DIR)/drivers/stvhacks.c $(CORE_DIR)/machine/stvcd.c \
$(CORE_DIR)/machine/scudsp.c \
$(CORE_DIR)/vidhrdw/stvvdp1_vidhrdw.c $(CORE_DIR)/vidhrdw/stvvdp2_vidhrdw.c \
+2599 -570
View File
File diff suppressed because it is too large. Load diff
+53 -32
View File
@@ -3608,43 +3608,64 @@ Propose deniam-16c 1997/06/21
BOMULEUL CHAJARA SEGA ST-V 1997/04/11
*/
/* System C games */
DRIVER( bloxeedc ) /* (c) 1989 Sega / Elorg*/
DRIVER( columns ) /* (c) 1990 Sega */
/* System C / C-2 (drivers/segac2.c) */
DRIVER( bloxeedc ) /* (c) 1989 Sega / Elorg */
DRIVER( bloxeedu ) /* (c) 1989 Sega / Elorg */
DRIVER( columns ) /* (c) 1990 Sega */
DRIVER( columnsu ) /* (c) 1990 Sega */
DRIVER( columnsj ) /* (c) 1990 Sega */
DRIVER( columns2 ) /* (c) 1990 Sega */
/* System C-2 games */
DRIVER( ssonicbr ) /* Sega, Unreleased */
DRIVER( borench ) /* (c) 1990 Sega */
DRIVER( tfrceac ) /* (c) 1990 Sega / Technosoft */
DRIVER( tfrceacj ) /* (c) 1990 Sega / Technosoft */
DRIVER( tfrceacb ) /* bootleg */
DRIVER( tfrceacjpb ) /* Prototype Bootleg */
DRIVER( ribbit ) /* (c) 1991 Sega */
DRIVER( column2j ) /* (c) 1990 Sega */
DRIVER( tfrceac ) /* (c) 1990 Technosoft / Sega */
DRIVER( tfrceacj ) /* (c) 1990 Technosoft / Sega */
DRIVER( tfrceacb ) /* (c) 1990 bootleg */
DRIVER( tfrceacjpb ) /* (c) 1990 bootleg */
DRIVER( borench ) /* (c) 1990 Sega */
DRIVER( borencha ) /* (c) 1990 Sega */
DRIVER( borenchj ) /* (c) 1990 Sega */
DRIVER( ribbit ) /* (c) 1991 Sega */
DRIVER( ribbitj ) /* (c) 1991 Sega */
DRIVER( twinsqua ) /* (c) 1991 Sega */
DRIVER( soniccar ) /* (c) 1991 Sega */
DRIVER( ssonicbr ) /* (c) 1992 hack */
DRIVER( ooparts ) /* (c) 1992 hack */
DRIVER( puyo ) /* (c) 1992 Compile / Sega */
DRIVER( puyobl ) /* (c) 1992 bootleg */
DRIVER( puyoj ) /* (c) 1992 Compile / Sega */
DRIVER( puyoja ) /* (c) 1992 Compile / Sega */
DRIVER( tantr ) /* (c) 1992 Sega */
DRIVER( tantrkor ) /* (c) 1993 Sega */
DRIVER( tantrbl ) /* bootleg */
DRIVER( tantrbl2 ) /* bootleg */
DRIVER( puyopuyo ) /* (c) 1992 Sega / Compile */
DRIVER( puyopuya ) /* (c) 1992 Sega / Compile */
DRIVER( puyopuyb ) /* bootleg */
DRIVER( ichir ) /* (c) 1994 Sega */
DRIVER( ichirk ) /* (c) 1994 Sega */
DRIVER( ichirj ) /* (c) 1994 Sega */
DRIVER( ichirjbl ) /* bootleg */
DRIVER( stkclmns ) /* (c) 1994 Sega */
DRIVER( puyopuy2 ) /* (c) 1994 Compile + Sega license */
DRIVER( tantrbl ) /* (c) 1992 bootleg */
DRIVER( tantrbl4 ) /* (c) 1992 bootleg */
DRIVER( tantrbl2 ) /* (c) 1994 bootleg */
DRIVER( tantrbl3 ) /* (c) 1994 bootleg */
DRIVER( wwanpanm ) /* (c) 1992 Sega */
DRIVER( wwanpanmo ) /* (c) 1992 Sega */
DRIVER( wwjumbo ) /* (c) 1990 Sega */
DRIVER( wwmarine ) /* (c) 1992 Sega */
DRIVER( wwpajero ) /* (c) 1990 Sega */
DRIVER( anpanman ) /* (c) 1992 Sega */
DRIVER( anpanmana ) /* (c) 1992 Sega */
DRIVER( sonicpop ) /* (c) 1993 Sega */
DRIVER( sonicfgt ) /* (c) 1993 Sega */
DRIVER( sonicfgtj ) /* (c) 1993 Sega */
DRIVER( potopoto ) /* (c) 1994 Sega */
DRIVER( zunkyou ) /* (c) 1994 Sega */
DRIVER( headonch ) /* Sega Unreleased */
DRIVER( ooparts ) /* Sega Unreleased */
/* Atlus Print Club 'Games' C-2 board */
DRIVER( pclubj )
DRIVER( pclubjv2 )
DRIVER( pclubjv4 )
DRIVER( pclubjv5 )
DRIVER( stkclmns ) /* (c) 1994 Sega */
DRIVER( stkclmnsj ) /* (c) 1994 Sega */
DRIVER( ichir ) /* (c) 1994 Sega */
DRIVER( ichirbl ) /* (c) 1994 bootleg */
DRIVER( ichirk ) /* (c) 1994 Sega */
DRIVER( ichirj ) /* (c) 1994 Sega */
DRIVER( ichirjbl ) /* (c) 1994 bootleg */
DRIVER( puyopuy2 ) /* (c) 1994 Compile (Sega license) */
DRIVER( zunkyou ) /* (c) 1994 Sega */
DRIVER( headonch ) /* (c) 1994 hack */
DRIVER( pclubj ) /* (c) 1995 Atlus */
DRIVER( pclubjv2 ) /* (c) 1995 Atlus */
DRIVER( pclub ) /* (c) 1995 Atlus */
DRIVER( pclubjv3 ) /* (c) 1995 Atlus */
DRIVER( pclubjv4 ) /* (c) 1996 Atlus */
DRIVER( pclubjv5 ) /* (c) 1996 Atlus */
/* Genie / Y-BOX hardware (drivers/megadriv_ybox.c) */
DRIVER( puckpkmn ) /* (c) 2000 Sun Mixing */
+2 -18
View File
@@ -5,7 +5,7 @@
The coin-op bootlegs of Mega Drive games, as in current MAME
(megadriv_acbl.cpp). Moved here from drivers/segac2.c; the Mega Drive
part (68000, sound Z80, I/O, interrupts) is shared with the other Mega
Drive based boards (includes/segac2.h), the VDP is in vidhrdw/segavdp.c.
Drive based boards (machine/megadriv.c), the VDP is in vidhrdw/segavdp.c.
With a PIC16C57 for the coins and the DIP switches:
Aladdin, Bare Knuckle II (barek2mb), Bare Knuckle III (barek3mba),
@@ -27,7 +27,7 @@
#include "driver.h"
#include "state.h"
#include "segac2.h"
#include "megadriv.h"
#include "cpu/pic16c5x/pic16c5x.h"
/******************************************************************************
@@ -1322,7 +1322,6 @@ Game does a check @ 1afc00 with work ram fff57c that makes it play like it was i
install_mem_read16_handler(0, 0x330000, 0x330001, aladbl_r);
acbl_config(0x20, 0, -1, 0);
init_segac2();
}
static DRIVER_INIT( barek2ch )
@@ -1343,7 +1342,6 @@ static DRIVER_INIT( barek2ch )
cpu_setbank(4, &genesis_68k_ram[0]);
acbl_config(0x20, 0, -1, 0);
init_segac2();
}
static DRIVER_INIT( barek3 )
@@ -1360,7 +1358,6 @@ static DRIVER_INIT( barek3 )
install_mem_read16_handler(0, 0x380078, 0x380079, input_port_3_word_r );
acbl_config(0x20, 0, -1, 0);
init_segac2();
}
static DRIVER_INIT( sonic2mb )
@@ -1373,7 +1370,6 @@ static DRIVER_INIT( sonic2mb )
cpu_setbank(4, &genesis_68k_ram[0]);
acbl_config(0x20, 0, -1, 0);
init_segac2();
}
static UINT8 prot_cmd;
@@ -1428,7 +1424,6 @@ static DRIVER_INIT( sonic3mb )
cpu_setbank(4, &genesis_68k_ram[0]);
acbl_config(0x20, 0, -1, 0);
init_segac2();
}
static READ16_HANDLER( jparkmb_r )
@@ -1450,7 +1445,6 @@ static DRIVER_INIT( jparkmb )
cpu_setbank(4, &genesis_68k_ram[0]);
acbl_config(0x20, 0, -1, 0);
init_segac2();
}
static READ16_HANDLER( twinktmb_r )
@@ -1483,7 +1477,6 @@ static DRIVER_INIT( twinktmb )
cpu_setbank(4, &genesis_68k_ram[0]);
acbl_config(0x20, 0, -1, 0);
init_segac2();
}
@@ -1533,14 +1526,12 @@ static DRIVER_INIT( mk3mdb )
acbl_install_dsw();
acbl_config(0xa0, 1, 2, 6);
acbl_iack = 1;
init_segac2();
}
static DRIVER_INIT( ssf2mdb )
{
acbl_config(0x20, 1, 2, 6);
acbl_iack = 1;
init_segac2();
}
static DRIVER_INIT( srmdb )
@@ -1566,7 +1557,6 @@ static DRIVER_INIT( srmdb )
acbl_install_dsw();
acbl_config(0xa0, 0, 2, 0);
acbl_iack = 1;
init_segac2();
}
static DRIVER_INIT( barekch )
@@ -1580,7 +1570,6 @@ static DRIVER_INIT( barekch )
acbl_install_dsw();
acbl_config(0x20, 1, 2, 6);
acbl_iack = 1;
init_segac2();
}
static DRIVER_INIT( bk3ssrmb )
@@ -1603,7 +1592,6 @@ static DRIVER_INIT( bk3ssrmb )
acbl_install_dsw();
acbl_config(0x20, 1, 2, 6);
acbl_iack = 1;
init_segac2();
}
static DRIVER_INIT( srssf2mb )
@@ -1626,7 +1614,6 @@ static DRIVER_INIT( srssf2mb )
acbl_install_dsw();
acbl_config(0x20, 1, 2, 6);
acbl_iack = 1;
init_segac2();
}
/* the coins of biohzdmb at 0x770078 */
@@ -1656,7 +1643,6 @@ static DRIVER_INIT( biohzdmb )
install_mem_read16_handler(0, 0x770078, 0x770079, biohzdmb_coins_r);
acbl_config(0x20, 0, -1, 0);
acbl_iack = 1;
init_segac2();
}
static DRIVER_INIT( barek2mb )
@@ -1678,7 +1664,6 @@ static DRIVER_INIT( barek2mb )
acbl_config(0x20, 0, -1, 0);
acbl_iack = 1;
init_segac2();
}
/* missing PIC dump, simulated as in MAME */
@@ -1703,7 +1688,6 @@ static DRIVER_INIT( barek3a )
acbl_config(0x20, 0, -1, 0);
acbl_iack = 1;
init_segac2();
}
/******************************************************************************
+1 -2
View File
@@ -17,7 +17,7 @@
***************************************************************************/
#include "driver.h"
#include "segac2.h"
#include "megadriv.h"
/******************************************************************************
Memory maps
@@ -205,7 +205,6 @@ static DRIVER_INIT( topshoot )
cpu_setbank(3, memory_region(REGION_CPU1));
cpu_setbank(4, &genesis_68k_ram[0]);
init_segac2();
}
+1 -2
View File
@@ -101,7 +101,7 @@ Screenshots available on my site at http://unemulated.emuunlim.com (under PCB Sh
#include "driver.h"
#include "state.h"
#include "segac2.h"
#include "megadriv.h"
/******************************************************************************
The Mega Drive part (as MAME's md_ntsc: 68000, Z80, YM2612, PSG, VDP)
@@ -648,7 +648,6 @@ static DRIVER_INIT( puckpkmn )
for (i = 0; i < len; i++)
rom[i] = BITSWAP8(rom[i], 1, 4, 2, 0, 7, 5, 3, 6);
init_segac2();
}
static DRIVER_INIT( jzth )
+61 -4
View File
@@ -8,7 +8,7 @@
Moved here from drivers/segac2.c, as in current MAME (megaplay.cpp);
the Mega Drive part (68000, sound Z80, I/O, interrupts) is shared with
the other Mega Drive based boards (includes/segac2.h), the VDP is in
the other Mega Drive based boards (machine/megadriv.c), the VDP is in
vidhrdw/segavdp.c and the video glue in vidhrdw/segac2_vidhrdw.c.
Set names as in current MAME (mp_twc is now mp_twcup).
@@ -17,7 +17,7 @@
#include "driver.h"
#include "state.h"
#include "segac2.h"
#include "megadriv.h"
/******************************************************************************
The BIOS
@@ -38,6 +38,61 @@ static unsigned char ic37_ram[0x8000];
static unsigned int readpos = 1; /* serial bank selection position (9-bit) */
static data16_t *ic36_ram; /* the BIOS RAM, also seen by the 68000 at 0xa02000 */
/******************************************************************************
The BIOS VDP interrupts, from drivers/segasyse.c
******************************************************************************/
/* in drivers/segasyse.c */
extern UINT8 vintpending;
extern UINT8 hintpending;
extern UINT8 *segae_vdp_regs[]; /* pointer to vdp's registers */
static UINT8 hintcount; /* line interrupt counter, decreased each scanline */
static INTERRUPT_GEN( megaplay_bios_irq )
{
int sline;
/* the 262 calls start at the Mega Drive VBLANK (line 224); the BIOS
VDP shares the screen and raises its V-INT (its line 193) about
12 lines later, as in current MAME. Counting from the VBLANK put it
~80 lines early, and the BIOS/game handshake on port C could miss. */
sline = (261 - cpu_getiloops() + 181) % 262;
if (sline ==0) {
hintcount = segae_vdp_regs[0][10];
}
if (sline <= 192) {
/* if (sline != 192) segae_drawscanline(sline,1,1);*/
if (sline == 192)
vintpending = 1;
if (hintcount == 0) {
hintcount = segae_vdp_regs[0][10];
hintpending = 1;
if ((segae_vdp_regs[0][0] & 0x10)) {
cpu_set_irq_line(2, 0, HOLD_LINE);
return;
}
} else {
hintcount--;
}
}
if (sline > 192) {
hintcount = segae_vdp_regs[0][10];
if ( (sline<0xe0) && (vintpending) ) {
cpu_set_irq_line(2, 0, HOLD_LINE);
}
}
}
static void megaplay_state_register(void)
{
state_save_register_UINT32("megaplay", 0, "bios_bank", (UINT32 *)&bios_bank, 1);
@@ -49,6 +104,9 @@ static void megaplay_state_register(void)
state_save_register_UINT8 ("megaplay", 0, "bios_6403", &bios_6403, 1);
state_save_register_UINT8 ("megaplay", 0, "bios_6404", &bios_6404, 1);
state_save_register_UINT8 ("megaplay", 0, "ic37_ram", ic37_ram, 0x8000);
state_save_register_UINT8 ("megatech", 0, "hintcount", &hintcount, 1);
state_save_register_UINT8 ("megatech", 0, "vintpending", &vintpending, 1);
state_save_register_UINT8 ("megatech", 0, "hintpending", &hintpending, 1);
}
/* the 68000 side of the Z80 area and of the I/O chip */
@@ -886,7 +944,7 @@ static MACHINE_DRIVER_START( megaplay )
MDRV_CPU_MEMORY(megaplay_bios_readmem, megaplay_bios_writemem)
MDRV_CPU_PORTS(megaplay_bios_readport,megaplay_bios_writeport)
MDRV_SOUND_ADD(SN76496, megatech_sn76489_intf)
MDRV_CPU_VBLANK_INT(megatech_irq, 262)
MDRV_CPU_VBLANK_INT(megaplay_bios_irq, 262)
MACHINE_DRIVER_END
/* The BIOS keeps its credits, bookkeeping and each slot's 256-byte game
@@ -1146,7 +1204,6 @@ static DRIVER_INIT (megaplay)
}
init_segac2();
}
+47 -9
View File
@@ -9,7 +9,7 @@
Moved here from drivers/segac2.c, as in current MAME (megatech.cpp);
the Mega Drive part (68000, sound Z80, I/O, interrupts) is shared with
the other Mega Drive based boards (includes/segac2.h), the VDP is in
the other Mega Drive based boards (machine/megadriv.c), the VDP is in
vidhrdw/segavdp.c and the video glue in vidhrdw/segac2_vidhrdw.c.
As in current MAME:
@@ -25,13 +25,21 @@
#include "driver.h"
#include "state.h"
#include "segac2.h"
#include "megadriv.h"
/* the BIOS VDP, in vidhrdw/segasyse_vidhrdw.c */
extern UINT8 *segae_vdp_vram[];
extern UINT8 *segae_vdp_regs[];
extern UINT8 *segae_vdp_cram[];
extern UINT8 segae_vdp_vrambank[];
unsigned char segae_vdp_ctrl_r ( UINT8 chip );
unsigned char segae_vdp_data_r ( UINT8 chip );
void segae_vdp_ctrl_w ( UINT8 chip, UINT8 data );
void segae_vdp_data_w ( UINT8 chip, UINT8 data );
/* the BIOS VDP interrupts, in drivers/segasyse.c */
extern UINT8 vintpending;
extern UINT8 hintpending;
/******************************************************************************
The BIOS
@@ -160,6 +168,40 @@ static WRITE_HANDLER( bios_ctrl_w )
bios_ctrl[offset] = data;
}
/* the BIOS VDP ports (also used by drivers/megaplay.c), from drivers/segasyse.c */
READ_HANDLER (megatech_bios_port_be_bf_r)
{
UINT8 temp = 0;
switch (offset)
{
case 0: /* port 0xbe, VDP 1 DATA Read */
temp = segae_vdp_data_r(0); break ;
case 1: /* port 0xbf, VDP 1 CTRL Read */
temp = segae_vdp_ctrl_r(0); break ;
}
return temp;
}
WRITE_HANDLER (megatech_bios_port_be_bf_w)
{
switch (offset)
{
case 0: /* port 0xbe, VDP 1 DATA Write */
segae_vdp_data_w(0, data); break;
case 1: /* port 0xbf, VDP 1 CTRL Write */
segae_vdp_ctrl_w(0, data); break;
}
}
/* two SN76489: one in the Mega Drive VDP and one in the BIOS VDP
(also used by drivers/megaplay.c) */
struct SN76496interface megatech_sn76489_intf =
{
2,
{ 53693100/15, 53693100/15 }, /* Clock: 3.58 MHz */
{ 50, 50 } /* Volume */
};
static void megatech_state_register(void)
{
state_save_register_UINT8 ("megatech", 0, "bios_hintcount", &bios_hintcount, 1);
@@ -171,6 +213,8 @@ static void megatech_state_register(void)
state_save_register_UINT32("megatech", 0, "bios_port_ctrl", (UINT32 *)&bios_port_ctrl, 1);
state_save_register_UINT32("megatech", 0, "bios_ctrl_inputs", (UINT32 *)&bios_ctrl_inputs, 1);
state_save_register_UINT8 ("megatech", 0, "bios_ctrl", bios_ctrl, 6);
state_save_register_UINT8 ("megatech", 0, "vintpending", &vintpending, 1);
state_save_register_UINT8 ("megatech", 0, "hintpending", &hintpending, 1);
}
@@ -988,17 +1032,13 @@ INPUT_PORTS_END
The BIOS VDP lines
*******************************************************************************
As drivers/segac2.c megatech_irq, with the 224 line mode the menu
As the Mega Play BIOS interrupt (drivers/megaplay.c), with the 224 line mode the menu
uses: the line counter and the VINT follow the active height, and each
line is drawn when it's reached, so the scroll and colour changes made
during the frame are seen where they happen.
******************************************************************************/
/* in drivers/segasyse.c */
extern UINT8 vintpending;
extern UINT8 hintpending;
static int megatech_bios_height(void)
{
@@ -1531,7 +1571,6 @@ ROM_END
static DRIVER_INIT( megatech )
{
mt_sms_cart = 0;
init_segac2();
}
static DRIVER_INIT( mt_sms )
@@ -1546,7 +1585,6 @@ static DRIVER_INIT( mt_sms )
sms_rom[i] = rom[BYTE_XOR_LE(i)];
mt_sms_cart = 1;
init_segac2();
}
/* nn */ /* nn is part of the instruction rom name, should there be a game for each number? */
+2394 -2676
View File
File diff suppressed because it is too large. Load diff
+107
View File
@@ -0,0 +1,107 @@
/*************************************************************************
Sega Mega Drive (Genesis) based boards
Shared by System C/C2, Mega-Tech, Mega Play, the Mega Drive bootlegs,
Genie / Y-BOX and Sun Mixing.
**************************************************************************/
#ifndef MEGADRIV_H
#define MEGADRIV_H
#include "vidhrdw/segavdp.h"
/*----------- defined in machine/megadriv.c -----------*/
/* the 68000 interrupts from the VDP (and the YM3438 on System C/C2) */
INTERRUPT_GEN( genesis_vblank_interrupt );
void megadriv_ym3438_irq(int state);
void megadriv_vdp_irq_update(void);
void megadriv_irq_init(const UINT8 *hint_mask);
void megadriv_irq_state_register(void);
void genesis_enable_iack(void);
extern data16_t *genesis_68k_ram;
extern unsigned char *genesis_z80_ram;
extern data16_t *genesis_io_ram;
MACHINE_DRIVER_EXTERN( genesis_base );
MACHINE_DRIVER_EXTERN( genesis ); /* genesis_base and the PSG */
MACHINE_INIT( genesis );
READ16_HANDLER( genesis_68k_to_z80_r );
WRITE16_HANDLER( genesis_68k_to_z80_w );
READ16_HANDLER( genesis_68000_io_r );
WRITE16_HANDLER( genesis_68000_io_w );
READ16_HANDLER( genesis_ctrl_r );
WRITE16_HANDLER( genesis_ctrl_w );
WRITE16_HANDLER( genesis_io_w );
WRITE16_HANDLER( sn76489_w );
READ_HANDLER( genesis_z80_r );
WRITE_HANDLER( genesis_z80_w );
READ_HANDLER( genesis_z80_bank_r );
extern struct YM2612interface gen_ym3438_intf;
/*----------- defined in drivers/megatech.c -----------*/
/* the Master System VDP of the Mega-Tech and Mega Play BIOS */
READ_HANDLER( megatech_bios_port_be_bf_r );
WRITE_HANDLER( megatech_bios_port_be_bf_w );
extern struct SN76496interface megatech_sn76489_intf;
/*----------- defined in vidhrdw/segac2_vidhrdw.c -----------*/
VIDEO_START( megadriv );
VIDEO_START( megatech );
VIDEO_START( megaplay );
VIDEO_EOF( segac2 );
VIDEO_UPDATE( segac2 );
VIDEO_UPDATE( megaplay );
/* the two Mega Drive pads */
#define GENESIS_PORTS \
PORT_START \
\
PORT_START /* Player 1 Controls - part 1 */ \
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) \
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) \
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) \
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) \
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 ) \
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 ) \
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) \
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) \
\
PORT_START /* Player 1 Controls - part 2 */ \
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) \
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) \
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) \
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) \
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) \
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START1 ) \
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) \
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) \
\
PORT_START /* Player 2 Controls - part 1 */ \
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_PLAYER2 ) \
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_PLAYER2 ) \
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_PLAYER2 ) \
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_PLAYER2 ) \
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 | IPF_PLAYER2 ) \
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 | IPF_PLAYER2 ) \
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) \
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) \
\
PORT_START /* Player 2 Controls - part 2 */ \
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) \
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) \
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) \
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) \
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER2 ) \
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START2 ) \
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) \
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) \
#endif
+1 -89
View File
@@ -4,96 +4,8 @@
**************************************************************************/
#include "vidhrdw/segavdp.h"
/*----------- defined in drivers/segac2.c -----------*/
void segac2_vdp_irq_update(void);
DRIVER_INIT( segac2 );
/* the Mega Drive based boards, shared with drivers/megaplay.c */
extern data16_t *genesis_68k_ram;
extern unsigned char *genesis_z80_ram;
extern data16_t *genesis_io_ram;
MACHINE_DRIVER_EXTERN( genesis_base );
MACHINE_DRIVER_EXTERN( genesis ); /* genesis_base and the PSG */
MACHINE_INIT( genesis );
INTERRUPT_GEN( genesis_vblank_interrupt );
INTERRUPT_GEN( megatech_irq );
void genesis_enable_iack(void);
READ16_HANDLER( genesis_68k_to_z80_r );
READ16_HANDLER( genesis_68000_io_r );
WRITE16_HANDLER( genesis_68000_io_w );
READ16_HANDLER( genesis_ctrl_r );
WRITE16_HANDLER( genesis_ctrl_w );
WRITE16_HANDLER( genesis_io_w );
WRITE16_HANDLER( genesis_68k_to_z80_w );
WRITE16_HANDLER( sn76489_w );
READ_HANDLER( genesis_z80_r );
WRITE_HANDLER( genesis_z80_w );
READ_HANDLER( genesis_z80_bank_r );
READ_HANDLER( megatech_bios_port_be_bf_r );
WRITE_HANDLER( megatech_bios_port_be_bf_w );
extern struct YM2612interface gen_ym3438_intf;
extern struct SN76496interface megatech_sn76489_intf;
/* the two Mega Drive pads */
#define GENESIS_PORTS \
PORT_START \
\
PORT_START /* Player 1 Controls - part 1 */ \
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) \
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) \
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) \
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) \
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 ) \
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 ) \
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) \
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) \
\
PORT_START /* Player 1 Controls - part 2 */ \
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) \
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) \
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) \
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) \
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) \
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START1 ) \
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) \
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) \
\
PORT_START /* Player 2 Controls - part 1 */ \
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_PLAYER2 ) \
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_PLAYER2 ) \
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_PLAYER2 ) \
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_PLAYER2 ) \
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 | IPF_PLAYER2 ) \
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 | IPF_PLAYER2 ) \
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) \
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) \
\
PORT_START /* Player 2 Controls - part 2 */ \
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) \
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) \
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) \
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) \
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER2 ) \
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START2 ) \
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) \
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) \
#include "megadriv.h"
/*----------- defined in vidhrdw/segac2_vidhrdw.c -----------*/
VIDEO_START( puckpkmn );
VIDEO_START( megatech );
VIDEO_START( megaplay );
VIDEO_START( segac2 );
VIDEO_EOF( segac2 );
VIDEO_UPDATE( segac2 );
VIDEO_UPDATE( megaplay );
+986
View File
@@ -0,0 +1,986 @@
/***************************************************************************
Sega Mega Drive (Genesis) based boards
The Mega Drive part shared by the Mega-Tech, Mega Play, bootleg, Genie /
Y-BOX and Sun Mixing boards, as megadriv.cpp in current MAME: the 68000
interrupts from the VDP (also used by System C/C2), the sound Z80 and
its bus, the Mega Drive I/O and the machine drivers. Moved here from
drivers/segac2.c; the VDP is in vidhrdw/segavdp.c and the video glue in
vidhrdw/segac2_vidhrdw.c.
***************************************************************************/
#include "driver.h"
#include "cpu/m68000/m68000.h"
#include "state.h"
#include "megadriv.h"
#define MASTER_CLOCK 53693100
/* interrupt states */
static UINT8 ym3438_int; /* INT2 - from YM3438 */
static UINT8 scanline_int; /* INT4 - programmable */
static UINT8 vblank_int; /* INT6 - on every VBLANK */
/* System C/C2: bit 4 of I/O port H masks the H-INT (NULL on the other boards) */
static const UINT8 *hint_mask_reg;
/* the sound Z80 */
static unsigned int z80_68000_latch;
static unsigned int z80_latch_bitcount;
static int z80running;
data16_t *genesis_68k_ram;
unsigned char *genesis_z80_ram;
/******************************************************************************
Interrupt handling
*******************************************************************************
The C/C2 System and the Mega Drive use 3 Different Interrupts, IRQ2, IRQ4
and IRQ6 (IRQ2 is only connected on System C/C2).
IRQ6 = Vblank, this happens after the last visible line of the display has
been drawn (after line 224)
IRQ4 = H-Int, this happens based upon the value in H-Int Counter. If the
Horizontal Interrupt is enabled and the Counter Value = 0 there
will be a Level 4 Interrupt Triggered
IRQ2 = sound int, generated by the YM3438
--------
More H-Counter Information:
Providing Horizontal Interrupts are active the H-Counter will be loaded
with the value stored in register #10 (0x0A) at the following times:
(1) At the top of the display, before drawing the first line
(2) When the counter has expired
(3) During the VBlank Period (lines 224-261)
The Counter is decreased by 1 after every line.
******************************************************************************/
/* Mega Play: H-INT/V-INT are cleared by the 68000 interrupt acknowledge
(see genesis_irq_ack_callback) instead of timing out; also selects the
corrected HBLANK status bit of the VDP (segavdp_set_iack_mode) */
static int genesis_vdp_iack;
/* System C/C2: V-INT comes from the line that drives the Z80 interrupt on a
Mega Drive (not masked by the VDP register 1 enable, the usual V-INT line
isn't connected), H-INT as usual; both stay asserted until the 68000 takes
them, as in current MAME */
static int c2_iack;
static int genesis_irq_ack_callback(int irqline);
/* call this whenever the interrupt state has changed */
static void update_interrupts(void)
{
int level = 0;
/* determine which interrupt is active */
if (ym3438_int) level = 2;
if (c2_iack)
{
if (scanline_int) level = 4;
if (vblank_int) level = 6;
}
else if (genesis_vdp_iack)
{
/* Mega Play: a pending H-INT/V-INT only drives the line while it is
enabled in VDP register 0/1, as on the real 315-5313 (Mazin Wars masks
H-INT this way while its V-INT handler borrows a5/a6, which its H-INT
handler jumps through) */
if (scanline_int && (segavdp_get_reg(0) & 0x10)) level = 4;
if (vblank_int && (segavdp_get_reg(1) & 0x20)) level = 6;
}
else
{
if (scanline_int) level = 4;
if (vblank_int) level = 6;
}
/* either set or clear the appropriate lines */
if (level)
cpu_set_irq_line(0, level, ASSERT_LINE);
else
cpu_set_irq_line(0, 7, CLEAR_LINE);
}
/* timer callback to turn off the IRQ4 signal after a short while */
static void vdp_int4_off(int param)
{
scanline_int = 0;
update_interrupts();
}
/* timer callback to handle reloading the H counter and generate IRQ4 */
static void vdp_reload_counter(int scanline)
{
/* generate an int if they're enabled */
if ((segavdp_get_reg(0) & 0x10) && !(hint_mask_reg && (*hint_mask_reg & 0x10)))
if (scanline != 0 || segavdp_get_reg(10) == 0)
{
scanline_int = 1;
update_interrupts();
/* with IACK emulation the line stays asserted until the 68000 takes it */
if (!genesis_vdp_iack && !c2_iack)
timer_set(segavdp_scanlinetime(scanline + 1), 0, vdp_int4_off);
}
/* advance to the next scanline */
/* behavior 2: 0 count means interrupt after one scanline */
/* (this behavior matches the Sega C2 emulator) */
/* (in this case the vidhrdw ichidant kludge should be -2) */
scanline += segavdp_get_reg(10) + 1;
if (scanline >= 224)
scanline = 0;
/* set a timer */
timer_set(segavdp_scanlinetime(scanline) + segavdp_scanlineperiod() * (320. / 342.), scanline, vdp_reload_counter);
}
/* timer callback to turn off the IRQ6 signal after a short while */
static void vdp_int6_off(int param)
{
vblank_int = 0;
update_interrupts();
}
/* interrupt callback to generate the VBLANK interrupt */
/* Mega Play: V-INT raised shortly after the VBLANK status bit */
static void genesis_vint_delayed(int param)
{
/* the pending flag is always set; update_interrupts() gates it with R1 */
vblank_int = 1;
update_interrupts();
}
/* called by the VDP after a write to R0/R1 (Mega Play only) */
void megadriv_vdp_irq_update(void)
{
if (genesis_vdp_iack)
update_interrupts();
}
INTERRUPT_GEN( genesis_vblank_interrupt )
{
/* with IACK emulation V-INT stays pending until the 68000 takes it, so it
is not lost while an H-INT handler has the interrupts masked; as on the
real 315-5313 it only drives the 68000 while enabled in VDP register 1 */
if (genesis_vdp_iack)
{
/* the VBLANK status bit rises first and V-INT follows about 788 master
clocks later (~112 68000 cycles): code polling the status bit gets to
see VBLANK before the interrupt takes over. Mazin Wars depends on it:
its V-INT handler outlasts the blanking period, so without the gap its
main loop never sees VBLANK and hangs in a fade loop after coin-up. */
segavdp_set_vblank();
timer_set(TIME_IN_USEC(788.0 * 1000000.0 / 53693100.0), 0, genesis_vint_delayed);
return;
}
/* generate the interrupt */
vblank_int = 1;
update_interrupts();
if (c2_iack)
return;
/* set a timer to turn it off */
timer_set(segavdp_scanlineperiod() * (22. / 342.), 0, vdp_int6_off);
}
/* interrupt callback to generate the YM3438 interrupt */
void megadriv_ym3438_irq(int state)
{
ym3438_int = state;
update_interrupts();
}
/* System C/C2: the interrupts of the board at reset */
void megadriv_irq_init(const UINT8 *hint_mask)
{
/* the Mega Play interrupt acknowledge is not used here */
genesis_vdp_iack = 0;
segavdp_set_iack_mode(0);
hint_mask_reg = hint_mask;
c2_iack = 1;
scanline_int = vblank_int = 0;
cpu_set_irq_callback(0, genesis_irq_ack_callback);
/* set the first scanline 0 timer to go off */
timer_set(segavdp_scanlinetime(0) + segavdp_scanlineperiod() * (320. / 342.), 0, vdp_reload_counter);
}
/* the interrupt states, saved by every board */
void megadriv_irq_state_register(void)
{
state_save_register_UINT8 ("C2_main", 0, "Int 2 Status", &ym3438_int, 1);
state_save_register_UINT8 ("C2_main", 0, "Int 4 Status", &scanline_int, 1);
state_save_register_UINT8 ("C2_main", 0, "Int 6 Status", &vblank_int, 1);
}
static void genesis_state_register(void);
MACHINE_INIT( genesis )
{
genesis_vdp_iack = 0;
c2_iack = 0;
segavdp_set_iack_mode(0);
hint_mask_reg = NULL;
/* the Mega Drive, Mega-Tech and Mega Play state (repeated registrations are ignored) */
genesis_state_register();
/* the following ensures that the Z80 begins without running away from 0 */
/* 0x76 is just a forced 'halt' as soon as the CPU is initially run */
genesis_z80_ram[0] = 0x76;
genesis_z80_ram[0x38] = 0x76;
cpu_set_halt_line(1, ASSERT_LINE);
z80running = 0;
log_cb(RETRO_LOG_DEBUG, LOGPRE "Machine init\n");
timer_set(segavdp_scanlinetime(0) + segavdp_scanlineperiod() * (320. / 342.), 0, vdp_reload_counter);
}
/* On the real 315-5313 VDP the H-INT (level 4) and V-INT (level 6) pending
flags are cleared when the 68000 acknowledges the interrupt.
The old timed pulses break games that use H-INT on every line:
- IRQ4 held for a whole scanline re-enters a short H-INT handler over and
over and the main program starves;
- IRQ6 dropped after 22 pixels is lost when the H-INT handler of line 223
still has the interrupts masked, so the game never sees V-INT again.
Gunstar Heroes hits both (68000 stuck at $FFEE04, its H-INT handler in RAM). */
static int genesis_irq_ack_callback(int irqline)
{
int level = 0;
if (irqline == 4)
scanline_int = 0;
else if (irqline == 6)
vblank_int = 0;
if (ym3438_int) level = 2;
if (c2_iack)
{
if (scanline_int) level = 4;
if (vblank_int) level = 6;
}
else
{
if (scanline_int && (segavdp_get_reg(0) & 0x10)) level = 4;
if (vblank_int && (segavdp_get_reg(1) & 0x20)) level = 6;
}
/* drop the line now (an immediate clear cannot re-enter the CPU core),
then re-assert whatever is still pending */
activecpu_set_irq_line(7, INTERNAL_CLEAR_LINE);
if (level)
cpu_set_irq_line(0, level, ASSERT_LINE);
return MC68000_INT_ACK_AUTOVECTOR;
}
/* Mega Play: the H-INT/V-INT are acknowledged by the 68000 (machine init) */
void genesis_enable_iack(void)
{
genesis_vdp_iack = 1;
segavdp_set_iack_mode(1);
scanline_int = vblank_int = 0;
cpu_set_irq_callback(0, genesis_irq_ack_callback);
}
/* handle writes to the SN764896 */
WRITE16_HANDLER( sn76489_w )
{
/* only works if we're accessing the low byte */
if (ACCESSING_LSB)
SN76496_0_w(0, data & 0xff);
}
/******************** Sega Genesis ******************************/
/* from MESS */
READ16_HANDLER(genesis_ctrl_r)
{
/* int returnval; */
/* log_cb(RETRO_LOG_DEBUG, LOGPRE "genesis_ctrl_r %x\n", offset); */
switch (offset)
{
case 0: /* DRAM mode is write only */
return 0xffff;
break;
case 0x80: /* return Z80 CPU Function Stop Accessible or not */
/* log_cb(RETRO_LOG_DEBUG, LOGPRE "Returning z80 state\n"); */
return (z80running ? 0x0100 : 0x0);
break;
case 0x100: /* Z80 CPU Reset - write only */
return 0xffff;
break;
}
return 0x00;
}
/* from MESS */
WRITE16_HANDLER(genesis_ctrl_w)
{
data &= ~mem_mask;
/* log_cb(RETRO_LOG_DEBUG, LOGPRE "genesis_ctrl_w %x, %x\n", offset, data); */
switch (offset)
{
case 0: /* set DRAM mode... we have to ignore this for production cartridges */
return;
break;
case 0x80: /* Z80 BusReq */
if (data == 0x100)
{
z80running = 0;
cpu_set_halt_line(1, ASSERT_LINE); /* halt Z80 */
/* log_cb(RETRO_LOG_DEBUG, LOGPRE "z80 stopped by 68k BusReq\n"); */
}
else
{
z80running = 1;
cpu_setbank(1, &genesis_z80_ram[0]);
cpu_set_halt_line(1, CLEAR_LINE);
/* log_cb(RETRO_LOG_DEBUG, LOGPRE "z80 started, BusReq ends\n"); */
}
return;
break;
case 0x100: /* Z80 CPU Reset */
if (data == 0x00)
{
cpu_set_halt_line(1, ASSERT_LINE);
cpu_set_reset_line(1, PULSE_LINE);
cpu_set_halt_line(1, ASSERT_LINE);
/* log_cb(RETRO_LOG_DEBUG, LOGPRE "z80 reset, ram is %p\n", &genesis_z80_ram[0]); */
z80running = 0;
return;
}
else
{
/* log_cb(RETRO_LOG_DEBUG, LOGPRE "z80 out of reset\n"); */
}
return;
break;
}
}
READ16_HANDLER ( genesis_68k_to_z80_r )
{
offset *= 2;
offset &= 0x7fff;
/* Shared Ram */
if ((offset >= 0x0000) && (offset <= 0x3fff))
{
offset &=0x1fff;
/* log_cb(RETRO_LOG_DEBUG, LOGPRE "soundram_r returning %x\n",(gen_z80_shared[offset] << 8) + gen_z80_shared[offset+1]);*/
return (genesis_z80_ram[offset] << 8) + genesis_z80_ram[offset+1];
}
/* YM2610 */
if ((offset >= 0x4000) && (offset <= 0x5fff))
{
switch (offset & 3)
{
case 0:
if (ACCESSING_MSB) return YM2612_status_port_0_A_r(0) << 8;
else return YM2612_read_port_0_r(0);
break;
case 2:
if (ACCESSING_MSB) return YM2612_status_port_0_B_r(0) << 8;
else return 0;
break;
}
}
/* Bank Register */
if ((offset >= 0x6000) && (offset <= 0x60ff))
{
}
/* Unused / Illegal */
if ((offset >= 0x6100) && (offset <= 0x7eff))
{
/* nothing */
}
/* VDP */
if ((offset >= 0x7f00) && (offset <= 0x7fff))
{
}
return 0x0000;
}
WRITE16_HANDLER ( genesis_68k_to_z80_w )
{
offset *= 2;
offset &= 0x7fff;
/* Shared Ram */
if ((offset >= 0x0000) && (offset <= 0x3fff))
{
offset &=0x1fff;
if (ACCESSING_LSB) genesis_z80_ram[offset+1] = data & 0xff;
if (ACCESSING_MSB) genesis_z80_ram[offset] = (data >> 8) & 0xff;
}
/* YM2610 */
if ((offset >= 0x4000) && (offset <= 0x5fff))
{
switch (offset & 3)
{
case 0:
if (ACCESSING_MSB) YM2612_control_port_0_A_w (0, (data >> 8) & 0xff);
else YM2612_data_port_0_A_w (0, (data >> 0) & 0xff);
break;
case 2:
if (ACCESSING_MSB) YM2612_control_port_0_B_w (0, (data >> 8) & 0xff);
else YM2612_data_port_0_B_w (0, (data >> 0) & 0xff);
break;
}
}
/* Bank Register */
if ((offset >= 0x6000) && (offset <= 0x60ff))
{
}
/* Unused / Illegal */
if ((offset >= 0x6100) && (offset <= 0x7eff))
{
/* nothing */
}
/* VDP */
if ((offset >= 0x7f00) && (offset <= 0x7fff))
{
offset &= 0x1f;
if ( (offset >= 0x10) && (offset <=0x17) )
{
if (ACCESSING_LSB) SN76496_0_w(0, data & 0xff);
if (ACCESSING_MSB) SN76496_0_w(0, (data >>8) & 0xff);
}
}
}
/* Gen I/O */
/*
cgfm info
$A10001 Version
$A10003 Port A data
$A10005 Port B data
$A10007 Port C data
$A10009 Port A control
$A1000B Port B control
$A1000D Port C control
$A1000F Port A TxData
$A10011 Port A RxData
$A10013 Port A serial control
$A10015 Port B TxData
$A10017 Port B RxData
$A10019 Port B serial control
$A1001B Port C TxData
$A1001D Port C RxData
$A1001F Port C serial control
*/
data16_t *genesis_io_ram;
WRITE16_HANDLER ( genesis_io_w )
{
/* log_cb(RETRO_LOG_DEBUG, LOGPRE "write io offset :%02x data %04x PC: 0x%06x\n",offset,data,activecpu_get_previouspc()); */
switch (offset)
{
case 0x00:
/*??*/
break;
case 0x01:/* port A data */
genesis_io_ram[offset] = (data & (genesis_io_ram[0x04])) | (genesis_io_ram[offset] & ~(genesis_io_ram[0x04]));
break;
case 0x02: /* port B data */
genesis_io_ram[offset] = (data & (genesis_io_ram[0x05])) | (genesis_io_ram[offset] & ~(genesis_io_ram[0x05]));
break;
case 0x03: /* port C data */
genesis_io_ram[offset] = (data & (genesis_io_ram[0x06])) | (genesis_io_ram[offset] & ~(genesis_io_ram[0x06]));
break;
case 0x04: /* port A control */
genesis_io_ram[offset] = data;
break;
case 0x05: /* port B control */
genesis_io_ram[offset] = data;
break;
case 0x06: /* port C control */
genesis_io_ram[offset] = data;
break;
case 0x07: /* port A TxData */
genesis_io_ram[offset] = data;
break;
default:
genesis_io_ram[offset] = data;
}
}
READ16_HANDLER ( genesis_68000_io_r )
{
int paddata,p;
int inlines, outlines;
/*printf("I/O read .. offset %02x data %02x\n",offset,genesis_io_ram[offset]); */
switch (offset)
{
case 0x00: /* version register */
return genesis_io_ram[offset];
case 0x01:
/* printf("I/O Data A read \n"); */
/*
When TH=0 When TH=1
D6 : (TH) 0 1
D5 : (TR) Start button Button C
D4 : (TL) Button A Button B
D3 : (D3) 0 D-pad Right
D2 : (D2) 0 D-pad Left
D1 : (D1) D-pad Down D-pad Down
D0 : (D0) D-pad Up D-pad Up
*/
/* process pad input for std 3 button pad */
p = readinputport(0);
if (genesis_io_ram[offset]&0x40)
{
paddata = ((p&0x0f)>>0) | ((p&0xc0)>>2) | 0x40;
}
else
{
paddata = ((p&0x03)>>0) | ((p&0x30)>>0) | 0x00;
}
inlines = (genesis_io_ram[0x04]^0xff)&0x7f;
outlines = (genesis_io_ram[0x04] | 0x80);
/* printf ("ioram %02x inlines %02x paddata %02x outlines %02x othdata %02x\n",genesis_io_ram[0x04], inlines, paddata, outlines, genesis_io_ram[0x01]); */
p = (paddata & inlines) | (genesis_io_ram[0x01] & outlines);
return p | p << 8;
return genesis_io_ram[offset];
case 0x02:
/* printf("I/O Data B read \n"); */
p = readinputport(1);
if (genesis_io_ram[offset]&0x40)
{
paddata = ((p&0x0f)>>0) | ((p&0xc0)>>2) | 0x40;
}
else
{
paddata = ((p&0x03)>>0) | ((p&0x30)>>0) | 0x00;
}
inlines = (genesis_io_ram[0x05]^0xff)&0x7f;
outlines = (genesis_io_ram[0x05] | 0x80);
p = (paddata & inlines) | (genesis_io_ram[0x02] & outlines);
return p | p <<8;
case 0x03:
/* printf("I/O Data C read \n"); */
return genesis_io_ram[offset];
case 0x04:
case 0x05:
case 0x06:
case 0x07:
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0c:
case 0x0d:
case 0x0e:
case 0x0f:
default:
printf("Unhandled I/O read \n");
return genesis_io_ram[offset];
}
return genesis_io_ram[offset];
/*
D7 : Console is 1= Export (USA, Europe, etc.) 0= Domestic (Japan)
D6 : Video type is 1= PAL, 0= NTSC
D5 : Sega CD unit is 1= not present, 0= connected.
D4 : Unused (always returns zero)
D3 : Bit 3 of version number
D2 : Bit 2 of version number
D1 : Bit 1 of version number
D0 : Bit 0 of version number
*/
/* return 0x30; */
/* return mame_rand(); */
/* return 0xff; */
}
/*
The I/O chip is mapped to $A10000-$A1001F in the 68000/VDP/Z80 banked address space.
It is normally read and written in byte units at odd addresses. The chip gets /LWR only,
so writing to even addresses has no effect. Reading even addresses returns the same data
ou'd get from an odd address. If a word-sized write is done, the LSB is sent to the I/O chip
and the MSB is ignored.
*/
/*
$A10001 Version
$A10003 Port A data
$A10005 Port B data
$A10007 Port C data
$A10009 Port A control
$A1000B Port B control
$A1000D Port C control
$A1000F Port A TxData
$A10011 Port A RxData
$A10013 Port A serial control
$A10015 Port B TxData
$A10017 Port B RxData
$A10019 Port B serial control
$A1001B Port C TxData
$A1001D Port C RxData
$A1001F Port C serial contro
*/
WRITE16_HANDLER ( genesis_68000_io_w )
{
/* printf("I/O write offset %02x data %04x\n",offset,data); */
switch (offset)
{
case 0x00: /* Version (read only?) */
printf("attempted write to version register?!\n");
break;
case 0x01: /* Port A data */
/* printf("write to data port A with control register A %02x step1 %02x step2 %02x\n", genesis_io_ram[0x04], (genesis_io_ram[0x01] & !((genesis_io_ram[0x04]&0x7f)|0x80)), (data & ((genesis_io_ram[0x04]&0x7f)|0x80)) ); */
genesis_io_ram[0x01] = (genesis_io_ram[0x01] & ((genesis_io_ram[0x04]^0xff)|0x80)) | (data & ((genesis_io_ram[0x04]&0x7f)|0x80));
break;
case 0x02: /* Port B data */
/* printf("write to data port B with control register B %02x\n", genesis_io_ram[0x05]); */
genesis_io_ram[0x02] = (genesis_io_ram[0x02] & ((genesis_io_ram[0x05]^0xff)|0x80)) | (data & ((genesis_io_ram[0x05]&0x7f)|0x80));
break;
case 0x03: /* Port C data */
/* printf("write to data port C with control register C %02x\n", genesis_io_ram[0x06]); */
genesis_io_ram[0x03] = (genesis_io_ram[0x03] & ((genesis_io_ram[0x06]^0xff)|0x80)) | (data & ((genesis_io_ram[0x06]&0x7f)|0x80));
break;
case 0x04: /* Port A control */
genesis_io_ram[offset]=data;
break;
case 0x05: /* Port B control */
genesis_io_ram[offset]=data;
break;
case 0x06: /* Port C control */
genesis_io_ram[offset]=data;
break;
/* unhandled */
case 0x07:
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0c:
case 0x0d:
case 0x0e:
case 0x0f:
default:
genesis_io_ram[offset]=data;
printf("unhandled IO write (offset %02x data %02x)\n",offset,data);
break;
}
}
/* Z80 Sound Hardware - based on MESS code, to be improved, it can do some strange things */
#ifdef MSB_FIRST
#define BYTE_XOR(a) (a)
#else
#define BYTE_XOR(a) ((a) ^ 1)
#endif
static WRITE_HANDLER ( genesis_bank_select_w ) /* note value will be meaningless unless all bits are correctly set in */
{
if (offset !=0 ) return;
/* if (!z80running) log_cb(RETRO_LOG_DEBUG, LOGPRE "undead Z80 latch write!\n");*/
if (z80_latch_bitcount == 0) z80_68000_latch = 0;
z80_68000_latch = z80_68000_latch | ((( ((unsigned char)data) & 0x01) << (15+z80_latch_bitcount)));
log_cb(RETRO_LOG_DEBUG, LOGPRE "value %x written to latch\n", data);
z80_latch_bitcount++;
if (z80_latch_bitcount == 9)
{
z80_latch_bitcount = 0;
log_cb(RETRO_LOG_DEBUG, LOGPRE "latch set, value %x\n", z80_68000_latch);
}
}
READ_HANDLER ( genesis_z80_r )
{
offset += 0x4000;
/* YM2610 */
if ((offset >= 0x4000) && (offset <= 0x5fff))
{
switch (offset & 3)
{
case 0: return YM2612_status_port_0_A_r(0);
case 1: return YM2612_read_port_0_r(0);
case 2: return YM2612_status_port_0_B_r(0);
case 3: return 0;
}
}
/* Bank Register */
if ((offset >= 0x6000) && (offset <= 0x60ff))
{
}
/* Unused / Illegal */
if ((offset >= 0x6100) && (offset <= 0x7eff))
{
/* nothing */
}
/* VDP */
if ((offset >= 0x7f00) && (offset <= 0x7fff))
{
}
return 0x00;
}
WRITE_HANDLER ( genesis_z80_w )
{
offset += 0x4000;
/* YM2610 */
if ((offset >= 0x4000) && (offset <= 0x5fff))
{
switch (offset & 3)
{
case 0: YM2612_control_port_0_A_w (0, data);
break;
case 1: YM2612_data_port_0_A_w (0, data);
break;
case 2: YM2612_control_port_0_B_w (0, data);
break;
case 3: YM2612_data_port_0_B_w (0, data);
break;
}
}
/* Bank Register */
if ((offset >= 0x6000) && (offset <= 0x60ff))
{
genesis_bank_select_w(offset & 0xff, data);
}
/* Unused / Illegal */
if ((offset >= 0x6100) && (offset <= 0x7eff))
{
/* nothing */
}
/* VDP */
if ((offset >= 0x7f00) && (offset <= 0x7fff))
{
offset &= 0x1f;
if ( (offset >= 0x10) && (offset <=0x17) )
{
SN76496_0_w(0, data & 0xff);
}
}
}
READ_HANDLER ( genesis_z80_bank_r )
{
int address = (z80_68000_latch) + (offset & 0x7fff);
if (!z80running) log_cb(RETRO_LOG_DEBUG, LOGPRE "undead Z80->68000 read!\n");
if (z80_latch_bitcount != 0) log_cb(RETRO_LOG_DEBUG, LOGPRE "reading whilst latch being set!\n");
log_cb(RETRO_LOG_DEBUG, LOGPRE "z80 read from address %x\n", address);
/* Read the data out of the 68k ROM */
if (address < 0x400000) return memory_region(REGION_CPU1)[BYTE_XOR(address)];
/* else read the data out of the 68k RAM */
/* else if (address > 0xff0000) return genesis_68k_ram[BYTE_XOR(offset)];*/
return -1;
}
static MEMORY_READ_START(genesis_z80_readmem)
{ 0x0000, 0x1fff, MRA_BANK1 },
{ 0x2000, 0x3fff, MRA_BANK2 }, /* mirror */
{ 0x4000, 0x7fff, genesis_z80_r },
{ 0x8000, 0xffff, genesis_z80_bank_r },
MEMORY_END
static MEMORY_WRITE_START(genesis_z80_writemem)
{ 0x0000, 0x1fff, MWA_BANK1, &genesis_z80_ram },
{ 0x2000, 0x3fff, MWA_BANK2 }, /* mirror */
{ 0x4000, 0x7fff, genesis_z80_w },
/* { 0x8000, 0xffff, genesis_z80_bank_w },*/
MEMORY_END
/******************************************************************************
Sound interfaces
******************************************************************************/
struct YM2612interface gen_ym3438_intf =
{
1, /* One chip */
MASTER_CLOCK/7, /* Clock: 7.67 MHz */
{ YM3012_VOL(50,MIXER_PAN_CENTER,50,MIXER_PAN_CENTER) }, /* Volume */
{ 0 }, /* port I/O */
{ 0 }, /* port I/O */
{ 0 }, /* port I/O */
{ 0 }, /* port I/O */
/* no IRQ: the YM3438 interrupt line isn't connected on the Mega Drive */
};
static struct SN76496interface sn76489_intf =
{
1, /* One chip */
{ MASTER_CLOCK/15 }, /* Clock: 3.58 MHz */
{ 50 } /* Volume */
};
/******************************************************************************
Machine drivers
******************************************************************************/
MACHINE_DRIVER_START( genesis_base )
/*basic machine hardware */
MDRV_CPU_ADD_TAG("main", M68000, 53693100 / 7)
/* each board sets its own memory map */
MDRV_CPU_VBLANK_INT(genesis_vblank_interrupt,1)
MDRV_CPU_ADD_TAG("sound", Z80, 53693100 / 15)
MDRV_CPU_MEMORY(genesis_z80_readmem, genesis_z80_writemem)
MDRV_CPU_VBLANK_INT(irq0_line_hold, 1) /* from vdp at scanline 0xe0 */
MDRV_FRAMES_PER_SECOND(60)
MDRV_VBLANK_DURATION((int)(((262. - 224.) / 262.) * 1000000. / 60.))
MDRV_INTERLEAVE(100)
MDRV_MACHINE_INIT(genesis)
/* video hardware */
MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER | VIDEO_HAS_SHADOWS | VIDEO_HAS_HIGHLIGHTS)
MDRV_SCREEN_SIZE(320,224)
MDRV_VISIBLE_AREA(0, 319, 0, 223)
MDRV_PALETTE_LENGTH(2048)
MDRV_VIDEO_START(megadriv)
MDRV_VIDEO_EOF(segac2)
MDRV_VIDEO_UPDATE(segac2)
/* sound hardware */
MDRV_SOUND_ADD(YM2612, gen_ym3438_intf )
MACHINE_DRIVER_END
MACHINE_DRIVER_START( genesis )
MDRV_IMPORT_FROM( genesis_base )
MDRV_SOUND_ADD(SN76496, sn76489_intf)
MACHINE_DRIVER_END
/******************************************************************************
Save states of the Mega Drive based boards: the interrupts, the Z80 RAM
and bus state, so that a state loaded in a new instance (netplay,
RunAhead with a second instance) continues exactly as the one that
saved it
******************************************************************************/
static void genesis_state_register(void)
{
megadriv_irq_state_register();
state_save_register_int ("genesis", 0, "z80running", &z80running);
state_save_register_UINT32("genesis", 0, "z80_68000_latch", (UINT32 *)&z80_68000_latch, 1);
state_save_register_UINT32("genesis", 0, "z80_latch_bitcount", (UINT32 *)&z80_latch_bitcount, 1);
if (genesis_z80_ram)
state_save_register_UINT8("genesis", 0, "z80_ram", genesis_z80_ram, 0x2000);
}
+3
View File
@@ -65,6 +65,9 @@ static void TimerHandler(int n,int c,int count,double stepTime)
/* hackish way to make bstars intro sync without */
/* breaking sonicwi2 command 0x35 */
if (slack < 0.000050) slack = 0;
/* a timer started long after its last overflow (or never fired)
runs a whole period, as in current MAME: it fired at once */
if (slack >= timeSec) slack = 0;
if (!timer_enable(Timer[n][c], 1))
timer_adjust(Timer[n][c], timeSec - slack, (c<<7)|n, 0);
+11
View File
@@ -5091,6 +5091,15 @@ void YM2612ResetChip(int num)
/* n = number */
/* a = address */
/* v = value */
/* the chip is busy for 32 internal cycles (32 x 6 input clocks) after a data
write, as in current MAME (ymfm): games that wait on the BUSY bit of the
status before each write (e.g. the System C/C2 sound drivers) take that long */
#if FM_BUSY_FLAG_SUPPORT
#define YM2612_BUSY_SET(F) ((F)->OPN.ST.BusyExpire = FM_GET_TIME_NOW() + (32.0 * 6.0) / (double)(F)->OPN.ST.clock)
#else
#define YM2612_BUSY_SET(F) do { } while (0)
#endif
int YM2612Write(int n, int a, UINT8 v)
{
YM2612 *F2612 = &(FM2612[n]);
@@ -5135,6 +5144,7 @@ int YM2612Write(int n, int a, UINT8 v)
/* write register */
OPNWriteReg(&(F2612->OPN),addr,v);
}
YM2612_BUSY_SET(F2612);
break;
case 2: /* address port 1 */
@@ -5150,6 +5160,7 @@ int YM2612Write(int n, int a, UINT8 v)
F2612->REGS[addr | 0x100] = v;
YM2612UpdateReq(n);
OPNWriteReg(&(F2612->OPN),addr | 0x100,v);
YM2612_BUSY_SET(F2612);
break;
}
return F2612->OPN.ST.irq;
+4 -2
View File
@@ -42,19 +42,21 @@ static int start_vdp(int sp_palbase, int display_enable, int scanbase, int line_
intf.line_scale = line_scale;
intf.display_enable = display_enable;
intf.set_visible_area = set_visible_area;
intf.irq_update = segac2_vdp_irq_update;
intf.irq_update = megadriv_vdp_irq_update;
return segavdp_start(&intf);
}
VIDEO_START( segac2 )
{
paletteram16 = auto_malloc(0x800 * sizeof(data16_t));
/* the display is enabled by the board (control_w) */
return start_vdp(0x100, 0, 0, 1, 1);
}
VIDEO_START( puckpkmn )
VIDEO_START( megadriv )
{
paletteram16 = auto_malloc(0x800 * sizeof(data16_t));
+10 -3
View File
@@ -55,6 +55,13 @@ void segae_drawtilesline(UINT8 *dest, int line, UINT8 chip, UINT8 pri);
void segae_drawspriteline(UINT8 *dest, UINT8 chip, UINT8 line);
void segae_drawscanline(int line, int chips, int blank);
/* the 4 bitplane bytes of a tile line, in VRAM order: read byte by byte,
so that the bit layout is the same on big endian hosts */
static INLINE UINT32 segae_tile_line(const UINT8 *p)
{
return p[0] | (p[1] << 8) | (p[2] << 16) | ((UINT32)p[3] << 24);
}
static void segae_draw8pix_solid16(UINT8 *dest, UINT8 chip, UINT16 tile, UINT8 line, UINT8 flipx, UINT8 col);
static void segae_draw8pix(UINT8 *dest, UINT8 chip, UINT16 tile, UINT8 line, UINT8 flipx, UINT8 col);
static void segae_draw8pixsprite(UINT8 *dest, UINT8 chip, UINT16 tile, UINT8 line);
@@ -619,7 +626,7 @@ void segae_drawspriteline(UINT8 *dest, UINT8 chip, UINT8 line)
static void segae_draw8pix_solid16(UINT8 *dest, UINT8 chip, UINT16 tile, UINT8 line, UINT8 flipx, UINT8 col)
{
UINT32 pix8 = *(UINT32 *)&segae_vdp_vram[chip][(32)*tile + (4)*line + (0x4000) * segae_vdp_vrambank[chip]];
UINT32 pix8 = segae_tile_line(&segae_vdp_vram[chip][(32)*tile + (4)*line + (0x4000) * segae_vdp_vrambank[chip]]);
UINT8 pix, coladd;
if (!pix8 && !col) return; /*note only the colour 0 of each vdp is transparent NOT colour 16???, fixes sky in HangonJr */
@@ -650,7 +657,7 @@ static void segae_draw8pix_solid16(UINT8 *dest, UINT8 chip, UINT16 tile, UINT8 l
static void segae_draw8pix(UINT8 *dest, UINT8 chip, UINT16 tile, UINT8 line, UINT8 flipx, UINT8 col)
{
UINT32 pix8 = *(UINT32 *)&segae_vdp_vram[chip][(32)*tile + (4)*line + (0x4000) * segae_vdp_vrambank[chip]];
UINT32 pix8 = segae_tile_line(&segae_vdp_vram[chip][(32)*tile + (4)*line + (0x4000) * segae_vdp_vrambank[chip]]);
UINT8 pix, coladd;
if (!pix8) return;
@@ -681,7 +688,7 @@ static void segae_draw8pix(UINT8 *dest, UINT8 chip, UINT16 tile, UINT8 line, UIN
static void segae_draw8pixsprite(UINT8 *dest, UINT8 chip, UINT16 tile, UINT8 line)
{
UINT32 pix8 = *(UINT32 *)&segae_vdp_vram[chip][(((32)*tile + (4)*line)&0x3fff) + (0x4000) * segae_vdp_vrambank[chip]];
UINT32 pix8 = segae_tile_line(&segae_vdp_vram[chip][(((32)*tile + (4)*line)&0x3fff) + (0x4000) * segae_vdp_vrambank[chip]]);
UINT8 pix;
if (!pix8) return; /*note only the colour 0 of each vdp is transparent NOT colour 16, fixes sky in HangonJr */
+59 -3
View File
@@ -77,6 +77,10 @@ static struct
int bg_palbase; /* base of background palette */
int sp_palbase; /* base of sprite palette */
int palbank; /* global palette bank */
UINT8 alt_palette; /* System C/C2 alternate palette mode */
int bg_pal_lookup[4]; /* palette of each of the 4 bg palettes */
int sp_pal_lookup[4]; /* palette of each of the 4 sprite palettes */
int bd_pal_lookup[4]; /* the backdrop: without the background base */
UINT8 display_enable; /* is the display enabled (board control)? */
UINT8 internal_vblank; /* state of the VBLANK line */
UINT8 iack_mode; /* Mega Play interrupt acknowledge / HBLANK mode */
@@ -109,6 +113,46 @@ static struct
/******************************************************************************
Palette lookups
*******************************************************************************
The palette entry of a pixel is the global palette bank, the base of the
background or sprite palettes and the 4 palettes of the VDP. On System
C/C2 the EPM5032 can also swizzle the colour RAM address bits (the
alternate palette mode of Ribbit! and Twin Squash), as in current MAME.
The backdrop colour doesn't take the background base (the title screen
of Borench is black in MAME too).
******************************************************************************/
static void recompute_palette_lookups(void)
{
int i;
for (i = 0; i < 4; i++)
{
int bgpal = vdp.bg_palbase + i * 0x10;
int sppal = vdp.sp_palbase + i * 0x10;
int bdpal = i * 0x10;
if (!vdp.alt_palette)
{
vdp.bg_pal_lookup[i] = vdp.palbank + bgpal;
vdp.sp_pal_lookup[i] = vdp.palbank + sppal;
vdp.bd_pal_lookup[i] = vdp.palbank + bdpal;
}
else
{
vdp.bg_pal_lookup[i] = vdp.palbank + ((bgpal << 1) & 0x180) + ((~bgpal >> 2) & 0x40) + (bgpal & 0x30);
vdp.sp_pal_lookup[i] = vdp.palbank + ((~sppal << 2) & 0x100) + ((sppal << 2) & 0x80) + ((~sppal >> 2) & 0x40) + ((sppal >> 2) & 0x20) + (sppal & 0x10);
vdp.bd_pal_lookup[i] = vdp.palbank + ((bdpal << 1) & 0x180) + ((~bdpal >> 2) & 0x40) + (bdpal & 0x30);
}
}
}
/******************************************************************************
Start
*******************************************************************************
@@ -167,6 +211,8 @@ int segavdp_start(const struct segavdp_interface *intf)
vdp.bg_palbase = intf->bg_palbase;
vdp.sp_palbase = intf->sp_palbase;
vdp.palbank = 0;
vdp.alt_palette = 0;
recompute_palette_lookups();
vdp.display_enable = intf->display_enable;
/* reset VDP (no interrupt callbacks yet: the board is not running) */
@@ -209,6 +255,8 @@ int segavdp_start(const struct segavdp_interface *intf)
state_save_register_UINT32("C2_Video", 0, "Window HPos", &vdp.window_hpos, 1);
state_save_register_UINT8("C2_Video", 0, "Window Width", &vdp.window_width, 1);
state_save_register_UINT8("C2_VDP", 0, "VBLANK", &vdp.internal_vblank, 1);
state_save_register_UINT8("C2_Video", 0, "Alt Palette", &vdp.alt_palette, 1);
state_save_register_func_postload(recompute_palette_lookups);
return 0;
}
@@ -275,6 +323,7 @@ void segavdp_set_palbases(int bg_palbase, int sp_palbase)
{
vdp.bg_palbase = bg_palbase;
vdp.sp_palbase = sp_palbase;
recompute_palette_lookups();
}
int segavdp_get_bg_palbase(void) { return vdp.bg_palbase; }
@@ -283,6 +332,13 @@ int segavdp_get_sp_palbase(void) { return vdp.sp_palbase; }
void segavdp_set_palbank(int palbank)
{
vdp.palbank = palbank;
recompute_palette_lookups();
}
void segavdp_set_alt_palette(int enable)
{
vdp.alt_palette = enable;
recompute_palette_lookups();
}
int segavdp_get_palbank(void) { return vdp.palbank; }
@@ -894,7 +950,7 @@ static void drawline(UINT16 *bitmap, int line, int bgfill)
UINT32 scrolla_tiles[41], scrollb_tiles[41], window_tiles[41];
int scrolla_offset, scrollb_offset;
UINT8 *lowlist[81], *highlist[81];
int bgcolor = bgfill ? bgfill : (vdp.bgcol + vdp.palbank);
int bgcolor = bgfill ? bgfill : ((vdp.bgcol & 0x0f) | vdp.bd_pal_lookup[(vdp.bgcol >> 4) & 3]);
int window_lclip, window_rclip;
int scrolla_lclip, scrolla_rclip;
int column, sprite;
@@ -1055,7 +1111,7 @@ static void drawline_tiles(UINT32 *tiles, UINT16 *bmap, int pri, int offset, int
/* if the tile is the correct priority, draw it */
if (((tile >> 15) & 1) == pri && offset < BITMAP_WIDTH)
{
int colbase = 16 * ((tile & 0x6000) >> 13) + vdp.bg_palbase + vdp.palbank;
int colbase = vdp.bg_pal_lookup[(tile >> 13) & 3];
UINT32 *tp = (UINT32 *)&VDP_VRAM_BYTE((tile & 0x7ff) * 32);
UINT32 mytile;
int col;
@@ -1320,7 +1376,7 @@ static void drawline_sprite(int line, UINT16 *bmap, int priority, UINT8 *spriteb
patline = line - spriteypos;
/* determine the color base */
colbase = 16 * ((spriteattr & 0x6000) >> 13) + vdp.sp_palbase + vdp.palbank;
colbase = vdp.sp_pal_lookup[(spriteattr >> 13) & 3];
/* adjust for the X position */
spritewidth >>= 3;
+1
View File
@@ -53,6 +53,7 @@ int segavdp_get_bg_palbase(void);
int segavdp_get_sp_palbase(void);
void segavdp_set_palbank(int palbank);
int segavdp_get_palbank(void);
void segavdp_set_alt_palette(int enable);
int segavdp_get_reg(int regnum);
int segavdp_get_scanbase(void);