diff options
Diffstat (limited to 'src/mame/drivers/neogeo.cpp')
-rw-r--r-- | src/mame/drivers/neogeo.cpp | 1532 |
1 files changed, 1532 insertions, 0 deletions
diff --git a/src/mame/drivers/neogeo.cpp b/src/mame/drivers/neogeo.cpp new file mode 100644 index 00000000000..0e9813edbb4 --- /dev/null +++ b/src/mame/drivers/neogeo.cpp @@ -0,0 +1,1532 @@ +// license:??? +// copyright-holders:Bryan McPhail,Fuzz,Ernesto Corvi,Andrew Prime,Zsolt Vasvari +/*************************************************************************** + + Neo-Geo hardware + + Credits: + * This driver was made possible by the research done by + Charles MacDonald. For a detailed description of the Neo-Geo + hardware, please visit his page at: + http://cgfm2.emuviews.com/txt/mvstech.txt + * Presented to you by the Shin Emu Keikaku team. + * The following people have all spent probably far + too much time on this: + AVDB + Bryan McPhail + Fuzz + Ernesto Corvi + Andrew Prime + Zsolt Vasvari + + + Known driver issues/to-do's: + ============================ + + * Fatal Fury 3 crashes during the ending - this doesn't occur if + the language is set to Japanese, maybe the English endings + are incomplete / buggy? + * Graphical Glitches caused by incorrect timing? + - Some raster effects are imperfect (off by a couple of lines) + * Multi-cart support not implemented - the MVS can take up to + 6 cartridges depending on the board being used + * 68000 waitstates on ROM region access, determined by jumpers on cart + (garou train stage 3 background bug is probably related to this) + + + Confirmed non-bugs: + + * Bad zooming in the Kof2003 bootlegs - this is what happens + if you try and use the normal bios with a pcb set, it + looks like the bootleggers didn't care. + * Glitches at the edges of the screen - the real hardware + can display 320x224 but most of the games seem designed + to work with a width of 304, some less. + * Distorted jumping sound in Nightmare in the Dark + * Ninja Combat sometimes glitches + + +***************************************************************************** + + The Neo-Geo Multi Video System (MVS), is an arcade system board, being + the first product in the Neo-Geo family, designed by Alpha Denshi(ADK) + and released in 1990 by SNK. It was known to the coin-op industry, and + offered arcade operators the ability to put up to 6 different arcade + titles into a single cabinet, a key economic consideration for operators + with limited floorspace (games for the Neo-Geo are cartridge based and are + easily exchangeable). It comes in many different cabinets but basically + consists of an add on board that can be linked to a standard Jamma system. + The system was discontinued in 2004. + Source (modified): http://en.wikipedia.org/wiki/Neo_Geo + + + MVS motherboards were produced in 1 / 2 / 4 and 6 Slot versions. + + Known motherboards: + =================== + + 1 Slot: + NEO-MVH MV1 + NEO-MVH MV1-1 + NEO-MVH MV1A + . NEO-MVH MV1A CHX ?? + NEO-MVH MV1B (1996.1.19) + . NEO-MVH MV1B CHX (1996.1.19) ?? + NEO-MVH MV1B1 (1998.6.17) + NEO-MVH MV1C (1999.4.30) + NEO-MVH MV1F + NEO-MVH MV1FS + NEO-MVH MV1FT + NEO-MVH MV1FZ + NEO-MVH MV1FZS + + 2 Slot: + NEO-MVH MV2 + NEO-MVH MV2F + NEO-MVH MV2F-01 + + 4 Slot: + NEO-MVH MV4 + NEO-MVH MV4F + NEO-MVH MV4FS + NEO-MVH MV4FT + NEO-MVH MV4FT2 + + 6 Slot: + NEO-MVH MV6 + NEO-MVH MV6F + + + Neo-Geo Motherboard (info - courtesy of Guru): + + NEO-MVH MV1 + |---------------------------------------------------------------------| + | 4558 | + | HC04 HC32 | + | SP-S2.SP1 NEO-E0 000-L0.L0 LS244 AS04 | + | YM2610 | + | 4558 | + | 4558 5814 HC259 SFIX.SFIX | + | NEO-I0 | + | HA13001 YM3016 5814 | + --| | + | 4558 | + --| SM1.SM1 LS32 | + | | + | LSPC-A0 PRO-C0 LS244 | + | | + |J 68000 | + |A | + |M | + |M NEO-ZMC2 | + |A | + | LS273 NEO-G0 58256 58256 Z80A | + | 58256 58256 58256 58256 6116 | + | LS273 5864 | + --| LS05 5864 PRO-B0 | + | | + --| LS06 HC32 D4990A NEO-F0 24.000MHz | + | DSW1 BATT3.6V 32.768kHz NEO-D0 | + | 2003 2003 | + |---------------------------------------------------------------------| + + +***************************************************************************** + + Neo-Geo game PCB infos: + ======================= + + The Neo-Geo games for AES (home) and MVS (arcade) systems are cartridge based. + + Each cartridge consists of two PCBs: CHA and PROG. + .CHA PCB contains gfx data ('C' - rom), text layer data ('S' - rom) and sound driver ('M' - rom). + .PROG PCB contains sample data ('V' - rom) and program code ('P' - rom). + + On most PCBs various custom/protection chips can also be found: + (Custom chip detail information (modified) from: http://wiki.neogeodev.org) + + CHA: + . NEO-273 (C and S-ROM address latch) + . NEO-CMC 90G06CF7042 (NEO-273 logic / NEO-ZMC logic / C-ROM decryption / C and S-ROM multiplexer / S-ROM bankswitching) + . NEO-CMC 90G06CF7050 (NEO-273 logic / NEO-ZMC logic / C-ROM decryption / M-ROM decryption / C and S-ROM multiplexer / S-ROM bankswitching) + . NEO-ZMC (Z80 memory controller) + . NEO-ZMC2 (Z80 memory controller / Tile serializer) + . PRO-CT0 (C-ROM serializer and multiplexer?; used on early AES-CHA boards) + . SNK-9201 (C-ROM serializer and multiplexer?; used on early AES-CHA boards) + + PROG: + . 0103 (QFP144) (Only found on Metal Slug X NEO-MVS PROGEOP board; function unknown) + . ALTERA (EPM7128SQC100-15) (P-ROM protection chip used for KOF98 NEO-MVS PROGSF1 board and Metal Slug X NEO-MVS PROGEOP board) + . NEO-COMA (Microcontroller; used for MULTI PLAY MODE, boards and sets see below) + . NEO-PCM2 (SNK 1999) (PCM functionality / V-ROM decryption / P-ROM decoding and bankswitching) + . NEO-PCM2 (PLAYMORE 2002) (PCM functionality / V-ROM decryption / P-ROM decoding and bankswitching) + . NEO-PVC (P-ROM decryption and bankswitching) / RAM + . NEO-SMA (P-ROM decryption and bankswitching / RNG / Storage of 256kb game data) + . PCM (ADPCM bus latches / V-ROM multiplexer) + . PRO-CT0 (On PROG board used for P-ROM protection -> Fatal Fury 2) + . SNK-9201 (On PROG board used for P-ROM protection -> Fatal Fury 2) + + + + Known PCBs: + ============ + + MVS CHA: + -- SNK -- + . NEO-MVS CHA-32 + . NEO-MVS CHA-8M + . NEO-MVS CHA42G + . NEO-MVS CHA42G-1 + . NEO-MVS CHA 42G-2 + . NEO-MVS CHA 42G-3 + . NEO-MVS CHA42G-3B + . NEO-MVS CHA256 + . NEO-MVS CHA256B + . NEO-MVS CHA512Y + . NEO-MVS CHAFIO (1999.6.14) - used with NEO-CMC 90G06C7042 or NEO-CMC 90G06C7050 + . MVS CHAFIO REV1.0 (KOF-2001) + . NEO-MVS CHAFIO (SNK 2002) - MADE IN KOREA + -- SNKPLAYMORE -- + . NEO-MVS CHAFIO (2003.7.24) - used only with NEO-CMC 90G06C7050 + + -- SNK development boards -- + . NEO-MVS CHAMC2 + + MVS PROG: + -- SNK -- + . NEO-MVS PROG-NAM + . NEO-MVS PROG-HERO + . NEO-MVS PROG-EP + . NEO-MVS PROG-8MB + . NEO-MVS PROGEP8M + . NEO-MVS PROG8M42 + . NEO-MVS PROG16 + . NEO-MVS PROG42G + . NEO-MVS PROG42G-COM + . NEO-MVS PROG42G-1 + . NEO-MVS PROG-G2 + . NEO-MVS PROG 4096 + . NEO-MVS PROG 4096 B + . NEO-MVS PROGGSC + . NEO-MVS PROGSM + . NEO-MVS PROGSS3 + . NEO-MVS PROGTOP + . NEO-MVS PROGSF1 (1998.6.17) + . NEO-MVS PROGSF1E (1998.6.18) + . NEO-MVS PROGEOP (1999.2.2) + . NEO-MVS PROGLBA (1999.4.12) - LBA-SUB (2000.2.24) + . NEO-MVS PROGBK1 (1994) + . NEO-MVS PROGBK1 (2001) + . NEO-MVS PROGBK2 (2000.3.21) - used with NEO-PCM2 (1999 SNK) or NEO-PCM2 (2002 PLAYMORE) + . MVS PROGBK2 REV1.0 (KOF-2001) + . NEO-MVS PROGBK2 (SNK 2002) - MADE IN KOREA + -- SNKPLAYMORE -- + . NEO-MVS PROGBK2R (2003.8.26) - NEO-HYCS (2003.9.29) + . NEO-MVS PROGBK3R (2003.9.2) - NEO-HYCS (2003.9.29) + . NEO-MVS PROGBK3S (2003.10.1) + . NEO-MVS PROGBK2S (2003.10.18) + + -- SNK development boards -- + . NEO-MVS PROGMC2 + + + AES CHA: + -- SNK -- + . NEO-AEG CHA-32 + . NEO-AEG CHA-8M + . NEO-AEG CHA42G + . NEO-AEG CHA42G-1 + . NEO-AEG CHA42G-2B + . NEO-AEG CHA42G-3 + . NEO-AEG CHA42G-4 + . NEO-AEG CHA256 + . NEO-AEG CHA256 B + . NEO-AEG CHA256[B] + . NEO-AEG CHA256BY + . NEO-AEG CHA256RY + . NEO-AEG CHA512Y + . NEO-AEG CHAFIO (1999.8.10) - used with NEO-CMC 90G06C7042 or NEO-CMC 90G06C7050 + -- SNKPLAYMORE -- + . NEO-AEG CHAFIO (2003.7.24) - used only with NEO-CMC 90G06C7050 + + AES PROG: + -- SNK -- + . NEO-AEG PROG-NAM + . NEO-AEG PROG-HERO + . NEO-AEG PROG-4A + . NEO-AEG PROG-4B + . NEO-AEG PROG 8M42 + . NEO-AEG PROG B + . NEO-AEG PROG16 + . NEO-AEG PROG42G + . NEO-AEG PROG42G-COM + . NEO-AEG PROG42G-1 + . NEO-AEG PROG-G2 + . NEO-AEG PROG4096 B + . NEO-AEG PROGGS + . NEO-AEG PROGTOP2 + . NEO-AEG PROGTOP2Y + . NEO-AEG PROGEOP (1999.4.2) + . NEO-AEG PROGLBA (1999.7.6) + . NEO-AEG PROGRK + . NEO-AEG PROGRKB + . NEO-AEG PROGBK1Y + . NEO-AEG PROGBK1F + -- PLAYMORE -- + . NEO-AEG PROGBK2 (2002.4.1) - used with NEO-PCM2 (1999 SNK) or NEO-PCM2 (2002 PLAYMORE) + -- SNKPLAYMORE -- + . NEO-AEG PROGBK3R (2003.8.29) - NEO-HYCS (2003.9.29) + . NEO-AEG PROGBK3S (2003.10.6) + . NEO-AEG PROGBK2S (2003.10.16) + + + + Cartridge colours: + ================== + + MVS cartridges were produced in different colours. + + Known cartridge colours: + . Black + . Blue + . Green + . Grey + . Red + . Transparent + . Transparent Blue + . Transparent Green + . White + . Yellow + + The above listed only covers SNK / PLAYMORE / SNKPLAYMORE PCBs. There also exists a + wide range of 'bootleg' PCBs. + + + Unofficial pcb's from NG:DEV.TEAM: + + MVS CHA: + GIGA CHAR Board 1.0 + GIGA CHAR Board 1.5 + + MVS PROG: + GIGA PROG Board 1.0 + GIGA PROG Board 1.5 + + + Unofficial pcb's from NEOBITZ: + + MVS CHA: + CHARBITZ1 2013.12.01 + + MVS PROG: + PROGBITZ1 2013.12.01 + + + Neo-Geo game PCB infos by Johnboy + + + + MVS cart pinout: + ================ + + Kindly submitted by Apollo69 (apollo69@columbus.rr.com) + ================================================================= + CTRG1 CTRG2 + ================================================================= + GND = 01A | 01B = GND GND = 01A | 01B = GND + GND = 02A | 02B = GND GND = 02A | 02B = GND + P0 = 03A | 03B = P1 GND = 03A | 03B = GND + P2 = 04A | 04B = P3 GND = 04A | 04B = GND + P4 = 05A | 05B = P5 D0 = 05A | 05B = A1 + P6 = 06A | 06B = P7 D1 = 06A | 06B = A2 + P8 = 07A | 07B = P9 D2 = 07A | 07B = A3 + P10 = 08A | 08B = P11 D3 = 08A | 08B = A4 + P12 = 09A | 09B = P13 D4 = 09A | 09B = A5 + P14 = 10A | 10B = P15 D5 = 10A | 10B = A6 + P16 = 11A | 11B = P17 D6 = 11A | 11B = A7 + P18 = 12A | 12B = P19 D7 = 12A | 12B = A8 + P20 = 13A | 13B = P21 D8 = 13A | 13B = A9 + P22 = 14A | 14B = P23 D9 = 14A | 14B = A10 + PCK1B = 15A | 15B = 24M D10 = 15A | 15B = A11 + PCK2B = 16A | 16B = 12M D11 = 16A | 16B = A12 + 2H1 = 17A | 17B = 8M D12 = 17A | 17B = A13 + CA4 = 18A | 18B = RESET D13 = 18A | 18B = A14 + CR0 = 19A | 19B = CR1 D14 = 19A | 19B = A15 + CR2 = 20A | 20B = CR3 D15 = 20A | 20B = A16 + CR4 = 21A | 21B = CR5 R/W = 21A | 21B = A17 + CR6 = 22A | 22B = CR7 AS = 22A | 22B = A18 + CR8 = 23A | 23B = CR9 ROMOEU = 23A | 23B = A19 + CR10 = 24A | 24B = CR11 ROMOEL = 24A | 24B = 68KCLKB + CR12 = 25A | 25B = CR13 PORTOEU = 25A | 25B = ROMWAIT + CR14 = 26A | 26B = CR15 PORTOEL = 26A | 26B = PWAIT0 + CR16 = 27A | 27B = CR17 PORTWEU = 27A | 27B = PWAIT1 + CR18 = 28A | 28B = CR19 PORTWEL = 28A | 28B = PDTACT + VCC = 29A | 29B = VCC VCC = 29A | 29B = VCC + VCC = 30A | 30B = VCC VCC = 30A | 30B = VCC + VCC = 31A | 31B = VCC VCC = 31A | 31B = VCC + VCC = 32A | 32B = VCC VCC = 32A | 32B = VCC + CR20 = 33A | 33B = CR21 PORTADRS = 33A | 33B = 4MB + CR22 = 34A | 34B = CR23 NC = 34A | 34B = ROMOE + CR24 = 35A | 35B = CR25 NC = 35A | 35B = RESET + CR26 = 36A | 36B = CR27 NC = 36A | 36B = NC + CR28 = 37A | 37B = CR29 NC = 37A | 37B = NC + CR30 = 38A | 38B = CR31 NC = 38A | 38B = NC + NC = 39A | 39B = FIX00 NC = 39A | 39B = NC + NC = 40A | 40B = FIX01 NC = 40A | 40B = NC + NC = 41A | 41B = FIX02 NC = 41A | 41B = SDPAD0 + SYSTEMB = 42A | 42B = FIX03 SYSTEMB = 42A | 42B = SDPAD1 + SDA0 = 43A | 43B = FIX04 SDPA8 = 43A | 43B = SDPAD2 + SDA1 = 44A | 44B = FIX05 SDPA9 = 44A | 44B = SDPAD3 + SDA2 = 45A | 45B = FIX06 SDPA10 = 45A | 45B = SDPAD4 + SDA3 = 46A | 46B = FIX07 SDPA11 = 46A | 46B = SDPAD5 + SDA4 = 47A | 47B = SDRD0 SDPMPX = 47A | 47B = SDPAD6 + SDA5 = 48A | 48B = SDRD1 SDPOE = 48A | 48B = SDPAD7 + SDA6 = 49A | 49B = SDROM SDRA8 = 49A | 49B = SDRA00 + SDA7 = 50A | 50B = SDMRD SDRA9 = 50A | 50B = SDRA01 + SDA8 = 51A | 51B = SDDO SDRA20 = 51A | 51B = SDRA02 + SDA9 = 52A | 52B = SDD1 SDRA21 = 52A | 52B = SDRA03 + SDA10 = 53A | 53B = SDD2 SDRA22 = 53A | 53B = SDRA04 + SDA11 = 54A | 54B = SDD3 SDRA23 = 54A | 54B = SDRA05 + SDA12 = 55A | 55B = SDD4 SDRMPX = 55A | 55B = SDRA06 + SDA13 = 56A | 56B = SDD5 SDROE = 56A | 56B = SDRA07 + SDA14 = 57A | 57B = SDD6 GND = 57A | 57B = GND + SDA15 = 58A | 58B = SDD7 GND = 58A | 58B = GND + GND = 59A | 59B = GND GND = 59A | 59B = GND + GND = 60A | 60B = GND GND = 60A | 60B = GND + + CTRG1 (CHA) = Contains gfx data ('C' - rom), text layer data ('S' - rom) and sound driver ('M' - rom) + CTRG2 (PROG) = Contains sample data ('V' - rom) and program code ('P' - rom) + + NOTE: On CTRG2-B, The "A" lines start at "A1". If you trace this on an + actual cart, you will see that this is actually "A0" (A0 - A18). + + These are from a very hard to read copy of the schematics, so + I hope that I got the pin names correct. + + Apollo69 10/19/99 + + +***************************************************************************** + + Watchdog: + ========= + + The watchdog timer will reset the system after ~0.13 seconds. + By cgfm's research, exactly 3,244,030 cycles (based on 24MHz clock). + + Newer games force a reset using the following code (this from kof99): + 009CDA 203C 0003 0D40 MOVE.L #0x30D40,D0 + 009CE0 5380 SUBQ.L #1,D0 + 009CE2 64FC BCC.S *-0x2 [0x9CE0] + Note however that there is a valid code path after this loop. + + The watchdog is used as a form of protection on a number of games, + previously this was implemented as a specific hack which locked a single + address of SRAM. + + What actually happens is if the game doesn't find valid data in the + backup ram it will initialize it, then sit in a loop. The watchdog + should then reset the system while it is in this loop. If the watchdog + fails to reset the system the code will continue and set a value in + backup ram to indiate that the protection check has failed. + + + Mahjong Panel notes (2009-03 FP): + ================================= + + * In Service Mode menu with mahjong panel active, controls are as + follows: + + A = select / up (for options) + B = down (for options) + C = go to previous menu + E = up (for menu entries) + F = down (for menu entries) + G = left (for options) + H = right (for options) + + * These only work with Japanese BIOS, but I think it's not a bug: I + doubt other BIOS were programmed to be compatible with mahjong panels + +****************************************************************************/ + +#include "emu.h" +#include "cpu/m68000/m68000.h" +#include "includes/neogeo.h" +#include "machine/nvram.h" +#include "cpu/z80/z80.h" +#include "sound/2610intf.h" +#include "softlist.h" +#include "neogeo.lh" + + +#define LOG_VIDEO_SYSTEM (0) +#define LOG_MAIN_CPU_BANKING (0) +#define LOG_AUDIO_CPU_BANKING (0) + + +/************************************* + * + * Main CPU interrupt generation + * + *************************************/ + + + +// The display counter is automatically reloaded with the load register contents on scanline 224, +// 1146 mclks from the rising edge of /HSYNC. +#define NEOGEO_VBLANK_RELOAD_HTIM (attotime::from_ticks(1146, NEOGEO_MASTER_CLOCK)) + +#define IRQ2CTRL_ENABLE (0x10) +#define IRQ2CTRL_LOAD_RELATIVE (0x20) +#define IRQ2CTRL_AUTOLOAD_VBLANK (0x40) +#define IRQ2CTRL_AUTOLOAD_REPEAT (0x80) + + +void neogeo_state::adjust_display_position_interrupt_timer() +{ + attotime period = attotime::from_ticks((UINT64)m_display_counter + 1, NEOGEO_PIXEL_CLOCK); + if (LOG_VIDEO_SYSTEM) logerror("adjust_display_position_interrupt_timer current y: %02x current x: %02x target y: %x target x: %x\n", m_screen->vpos(), m_screen->hpos(), (m_display_counter + 1) / NEOGEO_HTOTAL, (m_display_counter + 1) % NEOGEO_HTOTAL); + + m_display_position_interrupt_timer->adjust(period); +} + + +void neogeo_state::neogeo_set_display_position_interrupt_control( UINT16 data ) +{ + m_display_position_interrupt_control = data; +} + + +void neogeo_state::neogeo_set_display_counter_msb( UINT16 data ) +{ + m_display_counter = (m_display_counter & 0x0000ffff) | ((UINT32)data << 16); + + if (LOG_VIDEO_SYSTEM) logerror("PC %06x: set_display_counter %08x\n", m_maincpu->pc(), m_display_counter); +} + + +void neogeo_state::neogeo_set_display_counter_lsb( UINT16 data ) +{ + m_display_counter = (m_display_counter & 0xffff0000) | data; + + if (LOG_VIDEO_SYSTEM) logerror("PC %06x: set_display_counter %08x\n", m_maincpu->pc(), m_display_counter); + + if (m_display_position_interrupt_control & IRQ2CTRL_LOAD_RELATIVE) + { + if (LOG_VIDEO_SYSTEM) logerror("AUTOLOAD_RELATIVE "); + adjust_display_position_interrupt_timer(); + } +} + + +void neogeo_state::update_interrupts() +{ + m_maincpu->set_input_line(3, m_irq3_pending ? ASSERT_LINE : CLEAR_LINE); + m_maincpu->set_input_line(m_raster_level, m_display_position_interrupt_pending ? ASSERT_LINE : CLEAR_LINE); + m_maincpu->set_input_line(m_vblank_level, m_vblank_interrupt_pending ? ASSERT_LINE : CLEAR_LINE); +} + + +void neogeo_state::neogeo_acknowledge_interrupt( UINT16 data ) +{ + if (data & 0x01) + m_irq3_pending = 0; + if (data & 0x02) + m_display_position_interrupt_pending = 0; + if (data & 0x04) + m_vblank_interrupt_pending = 0; + + update_interrupts(); +} + + +TIMER_CALLBACK_MEMBER(neogeo_state::display_position_interrupt_callback) +{ + if (LOG_VIDEO_SYSTEM) logerror("--- Scanline @ %d,%d\n", m_screen->vpos(), m_screen->hpos()); + + if (m_display_position_interrupt_control & IRQ2CTRL_ENABLE) + { + if (LOG_VIDEO_SYSTEM) logerror("*** Scanline interrupt (IRQ2) *** y: %02x x: %02x\n", m_screen->vpos(), m_screen->hpos()); + m_display_position_interrupt_pending = 1; + + update_interrupts(); + } + + if (m_display_position_interrupt_control & IRQ2CTRL_AUTOLOAD_REPEAT) + { + if (LOG_VIDEO_SYSTEM) logerror("AUTOLOAD_REPEAT "); + adjust_display_position_interrupt_timer(); + } +} + + +TIMER_CALLBACK_MEMBER(neogeo_state::display_position_vblank_callback) +{ + if (m_display_position_interrupt_control & IRQ2CTRL_AUTOLOAD_VBLANK) + { + if (LOG_VIDEO_SYSTEM) logerror("AUTOLOAD_VBLANK "); + adjust_display_position_interrupt_timer(); + } + + /* set timer for next screen */ + m_display_position_vblank_timer->adjust(m_screen->time_until_pos(NEOGEO_VBSTART) + NEOGEO_VBLANK_RELOAD_HTIM); +} + + +TIMER_CALLBACK_MEMBER(neogeo_state::vblank_interrupt_callback) +{ + if (LOG_VIDEO_SYSTEM) logerror("+++ VBLANK @ %d,%d\n", m_screen->vpos(), m_screen->hpos()); + + m_vblank_interrupt_pending = 1; + update_interrupts(); + + /* set timer for next screen */ + m_vblank_interrupt_timer->adjust(m_screen->time_until_pos(NEOGEO_VBSTART) + NEOGEO_VBLANK_IRQ_HTIM); +} + + +void neogeo_state::create_interrupt_timers() +{ + m_display_position_interrupt_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(neogeo_state::display_position_interrupt_callback),this)); + m_display_position_vblank_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(neogeo_state::display_position_vblank_callback),this)); + m_vblank_interrupt_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(neogeo_state::vblank_interrupt_callback),this)); +} + + +void neogeo_state::start_interrupt_timers() +{ + m_vblank_interrupt_timer->adjust(m_screen->time_until_pos(NEOGEO_VBSTART) + NEOGEO_VBLANK_IRQ_HTIM); + m_display_position_vblank_timer->adjust(m_screen->time_until_pos(NEOGEO_VBSTART) + NEOGEO_VBLANK_RELOAD_HTIM); +} + + + +/************************************* + * + * Audio CPU interrupt generation + * + *************************************/ + +void neogeo_state::audio_cpu_check_nmi() +{ + m_audiocpu->set_input_line(INPUT_LINE_NMI, (m_audio_cpu_nmi_enabled && m_audio_cpu_nmi_pending) ? ASSERT_LINE : CLEAR_LINE); +} + +WRITE8_MEMBER(neogeo_state::audio_cpu_enable_nmi_w) +{ + // out ($08) enables the nmi, out ($18) disables it + m_audio_cpu_nmi_enabled = !(offset & 0x10); + audio_cpu_check_nmi(); +} + + + +/************************************* + * + * Input ports / Controllers + * + *************************************/ + +void neogeo_state::select_controller( UINT8 data ) +{ + m_controller_select = data; +} + + +CUSTOM_INPUT_MEMBER(neogeo_state::multiplexed_controller_r) +{ + int port = (FPTR)param; + + static const char *const cntrl[2][2] = + { + { "IN0-0", "IN0-1" }, { "IN1-0", "IN1-1" } + }; + + return read_safe(ioport(cntrl[port][m_controller_select & 0x01]), 0x00); +} + +CUSTOM_INPUT_MEMBER(neogeo_state::kizuna4p_controller_r) +{ + int port = (FPTR)param; + + static const char *const cntrl[2][2] = + { + { "IN0-0", "IN0-1" }, { "IN1-0", "IN1-1" } + }; + + int ret = read_safe(ioport(cntrl[port][m_controller_select & 0x01]), 0x00); + if (m_controller_select & 0x04) ret &= ((m_controller_select & 0x01) ? ~0x20 : ~0x10); + + return ret; +} + +CUSTOM_INPUT_MEMBER(neogeo_state::kizuna4p_start_r) +{ + return (ioport("START")->read() >> (m_controller_select & 0x01)) | ~0x05; +} + +#if 1 // this needs to be added dynamically somehow +CUSTOM_INPUT_MEMBER(neogeo_state::mahjong_controller_r) +{ + UINT32 ret; + +/* +cpu #0 (PC=00C18B9A): unmapped memory word write to 00380000 = 0012 & 00FF +cpu #0 (PC=00C18BB6): unmapped memory word write to 00380000 = 001B & 00FF +cpu #0 (PC=00C18D54): unmapped memory word write to 00380000 = 0024 & 00FF +cpu #0 (PC=00C18D6C): unmapped memory word write to 00380000 = 0009 & 00FF +cpu #0 (PC=00C18C40): unmapped memory word write to 00380000 = 0000 & 00FF +*/ + switch (m_controller_select) + { + default: + case 0x00: ret = 0x0000; break; /* nothing? */ + case 0x09: ret = ioport("MAHJONG1")->read(); break; + case 0x12: ret = ioport("MAHJONG2")->read(); break; + case 0x1b: ret = ioport("MAHJONG3")->read(); break; /* player 1 normal inputs? */ + case 0x24: ret = ioport("MAHJONG4")->read(); break; + } + + return ret; +} +#endif + +WRITE8_MEMBER(neogeo_state::io_control_w) +{ + switch (offset) + { + case 0x00: + select_controller(data); + break; + + case 0x10: + if (m_type == NEOGEO_MVS) + if (m_cartslots[0]) set_slot_number(data); + break; + + case 0x18: + if (m_type == NEOGEO_MVS) + set_output_latch(data); + break; + + case 0x20: + if (m_type == NEOGEO_MVS) + set_output_data(data); + break; + + case 0x28: + if (m_type == NEOGEO_MVS) + { + m_upd4990a->data_in_w(data >> 0 & 1); + m_upd4990a->clk_w(data >> 1 & 1); + m_upd4990a->stb_w(data >> 2 & 1); + } + break; + +// case 0x30: break; // coin counters +// case 0x31: break; // coin counters +// case 0x32: break; // coin lockout +// case 0x33: break; // coin lockout + + default: + logerror("PC: %x Unmapped I/O control write. Offset: %x Data: %x\n", space.device().safe_pc(), offset, data); + break; + } +} + + +/************************************* + * + * Unmapped memory access + * + *************************************/ + +READ16_MEMBER(neogeo_state::neogeo_unmapped_r) +{ + UINT16 ret; + + /* unmapped memory returns the last word on the data bus, which is almost always the opcode + of the next instruction due to prefetch */ + + /* prevent recursion */ + if (m_recurse) + ret = 0xffff; + else + { + m_recurse = true; + ret = space.read_word(space.device().safe_pc()); + m_recurse = false; + } + return ret; +} + + + +/************************************* + * + * NVRAM (Save RAM) + * + *************************************/ + +void neogeo_state::set_save_ram_unlock( UINT8 data ) +{ + m_save_ram_unlocked = data; +} + + +WRITE16_MEMBER(neogeo_state::save_ram_w) +{ + if (m_save_ram_unlocked) + COMBINE_DATA(&m_save_ram[offset]); +} + + + +/************************************* + * + * Memory card + * + *************************************/ + +CUSTOM_INPUT_MEMBER(neogeo_state::get_memcard_status) +{ + // D0 and D1 are memcard 1 and 2 presence indicators, D2 indicates memcard + // write protect status (we are always write enabled) + return (m_memcard->present() == -1) ? 0x07 : 0x00; +} + + +READ16_MEMBER(neogeo_state::memcard_r) +{ + m_maincpu->eat_cycles(2); // insert waitstate + + UINT16 ret; + + if (m_memcard->present() != -1) + ret = m_memcard->read(space, offset) | 0xff00; + else + ret = 0xffff; + + return ret; +} + + +WRITE16_MEMBER(neogeo_state::memcard_w) +{ + m_maincpu->eat_cycles(2); // insert waitstate + + if (ACCESSING_BITS_0_7) + { + if (m_memcard->present() != -1) + m_memcard->write(space, offset, data); + } +} + +/************************************* + * + * Inter-CPU communications + * + *************************************/ + +WRITE8_MEMBER(neogeo_state::audio_command_w) +{ + soundlatch_write(data); + + m_audio_cpu_nmi_pending = true; + audio_cpu_check_nmi(); + + /* boost the interleave to let the audio CPU read the command */ + machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(50)); +} + + +READ8_MEMBER(neogeo_state::audio_command_r) +{ + UINT8 ret = soundlatch_read(); + + m_audio_cpu_nmi_pending = false; + audio_cpu_check_nmi(); + + return ret; +} + + +CUSTOM_INPUT_MEMBER(neogeo_state::get_audio_result) +{ + UINT8 ret = soundlatch_read(1); // soundlatch2_byte_r + + return ret; +} + + + + +void neogeo_state::neogeo_main_cpu_banking_init() +{ + /* create vector banks */ +// m_bank_vectors->configure_entry(1, m_region_maincpu->base()); +// m_bank_vectors->configure_entry(0, memregion("mainbios")->base()); +// m_bank_vectors->set_entry(0); + m_use_cart_vectors = 0; + + if (m_type != NEOGEO_CD) + { + if (!m_cartslots[0]) m_banked_cart->init_banks(); + } +} + + +/************************************* + * + * Audio CPU banking + * + *************************************/ + +READ8_MEMBER(neogeo_state::audio_cpu_bank_select_r) +{ + m_bank_audio_cart[offset & 3]->set_entry(offset >> 8); + + return 0; +} + + +void neogeo_state::neogeo_audio_cpu_banking_init(int set_entry) +{ + if (m_type == NEOGEO_CD) return; + + int region; + int bank; + UINT8 *rgn; + UINT32 address_mask; + + rgn = memregion("audiocpu")->base(); + + /* audio bios/cartridge selection */ + m_bank_audio_main->configure_entry(1, memregion("audiocpu")->base()); + if (memregion("audiobios")) + m_bank_audio_main->configure_entry(0, memregion("audiobios")->base()); + else /* on hardware with no SM1 ROM, the cart ROM is always enabled */ + m_bank_audio_main->configure_entry(0, memregion("audiocpu")->base()); + + m_bank_audio_main->set_entry(m_use_cart_audio); + + /* audio banking */ + m_bank_audio_cart[0] = membank("audio_f000"); + m_bank_audio_cart[1] = membank("audio_e000"); + m_bank_audio_cart[2] = membank("audio_c000"); + m_bank_audio_cart[3] = membank("audio_8000"); + + address_mask = (memregion("audiocpu")->bytes() - 0x10000 - 1) & 0x3ffff; + + + for (region = 0; region < 4; region++) + { + for (bank = 0xff; bank >= 0; bank--) + { + UINT32 bank_address = 0x10000 + ((bank << (11 + region)) & address_mask); + m_bank_audio_cart[region]->configure_entry(bank, &rgn[bank_address]); + } + } + + // set initial audio banks - THIS IS A HACK + // Z80 banking is handled by the NEO-ZMC chip in the cartridge + // (in later cartridges, by multifunction banking/protection chips that implement the same bank scheme) + // On the real chip, initial banks are all 0. + // However, early cartridges with less than 64KB of Z80 code and data don't have ROM banking at all. + // These initial bank settings are required so non-banked games will work until we identify them + // and use a different Z80 address map for them. + m_bank_audio_cart[0]->set_entry(0x1e); + m_bank_audio_cart[1]->set_entry(0x0e); + m_bank_audio_cart[2]->set_entry(0x06); + m_bank_audio_cart[3]->set_entry(0x02); +} + + + +/************************************* + * + * System control register + * + *************************************/ + +WRITE8_MEMBER(neogeo_state::system_control_w) +{ + UINT8 bit = (offset >> 3) & 0x01; + + switch (offset & 0x07) + { + default: + case 0x00: + neogeo_set_screen_shadow(bit); + break; + + case 0x01: + if (m_type == NEOGEO_CD) + printf("NeoCD: write to regular vector change address? %d\n", bit); // what IS going on with "neocdz doubledr" and why do games write here if it's hooked up to nothing? + else + //m_bank_vectors->set_entry(bit); + m_use_cart_vectors = bit; + break; + + case 0x05: + if (m_type == NEOGEO_MVS) + { + m_use_cart_audio = bit; + m_sprgen->neogeo_set_fixed_layer_source(bit); + m_bank_audio_main->set_entry(m_use_cart_audio); + } + break; + + case 0x06: + if (m_type == NEOGEO_MVS) + set_save_ram_unlock(bit); + break; + + case 0x07: + neogeo_set_palette_bank(bit); + break; + + case 0x02: // memory card 1: write enable/disable + case 0x03: // memory card 2: write disable/enable + case 0x04: // memory card: register select enable/set to normal (what does it mean?) + logerror("PC: %x Unmapped system control write. Offset: %x Data: %x\n", space.device().safe_pc(), offset & 0x07, bit); + break; + } + + if (LOG_VIDEO_SYSTEM && ((offset & 0x07) != 0x06)) logerror("PC: %x System control write. Offset: %x Data: %x\n", space.device().safe_pc(), offset & 0x07, bit); +} + + + +/************************************* + * + * LEDs + * + *************************************/ + +void neogeo_state::set_outputs( ) +{ + static const UINT8 led_map[0x10] = + { 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x58,0x4c,0x62,0x69,0x78,0x00 }; + + /* EL */ + output_set_digit_value(0, led_map[m_el_value]); + + /* LED1 */ + output_set_digit_value(1, led_map[m_led1_value >> 4]); + output_set_digit_value(2, led_map[m_led1_value & 0x0f]); + + /* LED2 */ + output_set_digit_value(3, led_map[m_led2_value >> 4]); + output_set_digit_value(4, led_map[m_led2_value & 0x0f]); +} + + +void neogeo_state::set_output_latch( UINT8 data ) +{ + /* looks like the LEDs are set on the + falling edge */ + UINT8 falling_bits = m_output_latch & ~data; + + if (falling_bits & 0x08) + m_el_value = 16 - (m_output_data & 0x0f); + + if (falling_bits & 0x10) + m_led1_value = ~m_output_data; + + if (falling_bits & 0x20) + m_led2_value = ~m_output_data; + + if (falling_bits & 0xc7) + logerror("%s Unmaped LED write. Data: %x\n", machine().describe_context(), falling_bits); + + m_output_latch = data; + + set_outputs(); +} + + +void neogeo_state::set_output_data( UINT8 data ) +{ + m_output_data = data; +} + + + +/************************************* + * + * Machine initialization + * + *************************************/ + +DRIVER_INIT_MEMBER(neogeo_state,neogeo) +{ + if (!m_cartslots[0]) m_banked_cart->install_banks(machine(), m_maincpu, m_region_maincpu->base(), m_region_maincpu->bytes()); + + m_sprgen->m_fixed_layer_bank_type = 0; +} + + +void neogeo_state::neogeo_postload() +{ + m_bank_audio_main->set_entry(m_use_cart_audio); + + if (m_type == NEOGEO_MVS) set_outputs(); +} + + +void neogeo_state::machine_start() +{ + m_type = NEOGEO_MVS; + + + /* set the initial main CPU bank */ + neogeo_main_cpu_banking_init(); + + /* set the initial audio CPU ROM banks */ + neogeo_audio_cpu_banking_init(1); + + create_interrupt_timers(); + + /* irq levels for MVS / AES */ + m_vblank_level = 1; + m_raster_level = 2; + + /* start with an IRQ3 - but NOT on a reset */ + m_irq3_pending = 1; + + // enable rtc and serial mode + m_upd4990a->cs_w(1); + m_upd4990a->oe_w(1); + m_upd4990a->c0_w(1); + m_upd4990a->c1_w(1); + m_upd4990a->c2_w(1); + + /* register state save */ + save_item(NAME(m_display_position_interrupt_control)); + save_item(NAME(m_display_counter)); + save_item(NAME(m_vblank_interrupt_pending)); + save_item(NAME(m_display_position_interrupt_pending)); + save_item(NAME(m_irq3_pending)); + save_item(NAME(m_audio_cpu_nmi_enabled)); + save_item(NAME(m_audio_cpu_nmi_pending)); + save_item(NAME(m_controller_select)); + save_item(NAME(m_save_ram_unlocked)); + save_item(NAME(m_output_data)); + save_item(NAME(m_output_latch)); + save_item(NAME(m_el_value)); + save_item(NAME(m_led1_value)); + save_item(NAME(m_led2_value)); + + save_item(NAME(m_use_cart_vectors)); + save_item(NAME(m_use_cart_audio)); + + machine().save().register_postload(save_prepost_delegate(FUNC(neogeo_state::neogeo_postload), this)); + + + m_cartslots[0] = m_cartslot1; + m_cartslots[1] = m_cartslot2; + m_cartslots[2] = m_cartslot3; + m_cartslots[3] = m_cartslot4; + m_cartslots[4] = m_cartslot5; + m_cartslots[5] = m_cartslot6; + + + m_sprgen->set_screen(m_screen); + m_sprgen->set_sprite_region(m_region_sprites->base(), m_region_sprites->bytes()); + m_sprgen->set_fixed_regions(m_region_fixed->base(), m_region_fixed->bytes(), m_region_fixedbios); + +} + + + +/************************************* + * + * Machine reset + * + *************************************/ + +void neogeo_state::set_slot_number(int slot) +{ + if (slot != m_currentslot) + { + m_currentslot = slot; + + address_space &space = m_maincpu->space(AS_PROGRAM); + + // unmap old handlers, some carts will have installed overlays on them, we need them to be cleared + space.unmap_readwrite(0x000080, 0x0fffff); + space.unmap_readwrite(0x200000, 0x2fffff); + + + if (m_cartslots[m_currentslot]->get_sprites_size() == 0) + return; + + // give the sprite chip pointers to the graphics for this slot from the slot device + m_sprgen->set_sprite_region(m_cartslots[m_currentslot]->get_sprites_base(), m_cartslots[m_currentslot]->get_sprites_size()); + m_sprgen->set_fixed_regions(m_cartslots[m_currentslot]->get_fixed_base(), m_cartslots[m_currentslot]->get_fixed_size(), m_region_fixedbios); + m_sprgen->set_optimized_sprite_data(m_cartslots[m_currentslot]->get_sprites_optimized(), m_cartslots[m_currentslot]->get_sprites_addrmask()); + m_sprgen->m_fixed_layer_bank_type = m_cartslots[m_currentslot]->get_fixed_bank_type(); + /* + Resetting a sound device causes the core to update() it and generate samples if it's not up to date. + Thus we preemptively reset it here while the old pointers are still valid so it's up to date and + doesn't generate samples below when we reset it for the new pointers. + */ + device_t* ym = machine().device("ymsnd"); + ym->reset(); + + m_cartslots[m_currentslot]->setup_memory_banks(machine()); // setup basic pointers + + ym->reset(); // reset it again to get the new pointers + + // these could have changed, ensure the pointers are valid + m_region_maincpu.findit(); + m_region_sprites.findit(); + m_region_fixed.findit(); + + space.install_rom(0x000080, 0x0fffff, m_region_maincpu->base()+0x80); // reinstall the base program rom handler + + m_cartslots[m_currentslot]->activate_cart(machine(), m_maincpu, m_region_maincpu->base(), m_region_maincpu->bytes(), m_cartslots[m_currentslot]->get_fixed_base(), m_cartslots[m_currentslot]->get_fixed_size()); + //memcpy((UINT8*)m_cartslots[m_currentslot]->get_rom_base(),m_region_maincpu->base(), m_region_maincpu->bytes()); // hack- copy back any mods activate made (eh cthd2003)c + + neogeo_audio_cpu_banking_init(0); // should probably be responsibility of the cart + m_audiocpu->reset(); // or some games like svc have no sounnd if in higher slots? + + } +} + +void neogeo_state::machine_reset() +{ + offs_t offs; + address_space &space = m_maincpu->space(AS_PROGRAM); + + /* reset system control registers */ + for (offs = 0; offs < 8; offs++) + system_control_w(space, offs, 0); + + // disable audiocpu nmi + m_audio_cpu_nmi_enabled = false; + m_audio_cpu_nmi_pending = false; + audio_cpu_check_nmi(); + + m_maincpu->reset(); + + start_interrupt_timers(); + + /* trigger the IRQ3 that was set by MACHINE_START */ + update_interrupts(); + + m_recurse = false; + + if (m_cartslots[0]) // if thie system has cart slots then do some extra initialization + { + set_slot_number(0); + } + +} + +READ16_MEMBER(neogeo_state::banked_vectors_r) +{ + if (!m_use_cart_vectors) + { + UINT16* bios = (UINT16*)memregion("mainbios")->base(); + return bios[offset]; + } + else + { + UINT16* game = (UINT16*)m_region_maincpu->base(); + return game[offset]; + } + +} + +READ16_MEMBER(neogeo_state::neogeo_slot_rom_low_r) +{ + return m_cartslots[m_currentslot]->read_rom(space, offset+(0x80/2), mem_mask); +} + +READ16_MEMBER(neogeo_state::neogeo_slot_rom_low_bectors_r) +{ + if (!m_use_cart_vectors) + { + UINT16* bios = (UINT16*)memregion("mainbios")->base(); + return bios[offset]; + } + else + { + return m_cartslots[m_currentslot]->read_rom(space, offset, mem_mask); + } + +} + + +/************************************* + * + * Main CPU memory handlers + * + *************************************/ + +ADDRESS_MAP_START( neogeo_main_map, AS_PROGRAM, 16, neogeo_state ) + + AM_RANGE(0x100000, 0x10ffff) AM_MIRROR(0x0f0000) AM_RAM + /* some games have protection devices in the 0x200000 region, it appears to map to cart space, not surprising, the ROM is read here too */ + AM_RANGE(0x300000, 0x300001) AM_MIRROR(0x01ff7e) AM_READ_PORT("P1/DSW") + AM_RANGE(0x300080, 0x300081) AM_MIRROR(0x01ff7e) AM_READ_PORT("TEST") + AM_RANGE(0x300000, 0x300001) AM_MIRROR(0x01fffe) AM_WRITE8(watchdog_reset_w, 0x00ff) + AM_RANGE(0x320000, 0x320001) AM_MIRROR(0x01fffe) AM_READ_PORT("AUDIO/COIN") AM_WRITE8(audio_command_w, 0xff00) + AM_RANGE(0x340000, 0x340001) AM_MIRROR(0x01fffe) AM_READ_PORT("P2") + AM_RANGE(0x360000, 0x37ffff) AM_READ(neogeo_unmapped_r) + AM_RANGE(0x380000, 0x380001) AM_MIRROR(0x01fffe) AM_READ_PORT("SYSTEM") + AM_RANGE(0x380000, 0x38007f) AM_MIRROR(0x01ff80) AM_WRITE8(io_control_w, 0x00ff) + AM_RANGE(0x3a0000, 0x3a001f) AM_MIRROR(0x01ffe0) AM_READ(neogeo_unmapped_r) AM_WRITE8(system_control_w, 0x00ff) + AM_RANGE(0x3c0000, 0x3c0007) AM_MIRROR(0x01fff8) AM_READ(neogeo_video_register_r) + AM_RANGE(0x3c0000, 0x3c000f) AM_MIRROR(0x01fff0) AM_WRITE(neogeo_video_register_w) + AM_RANGE(0x3e0000, 0x3fffff) AM_READ(neogeo_unmapped_r) + AM_RANGE(0x400000, 0x401fff) AM_MIRROR(0x3fe000) AM_READWRITE(neogeo_paletteram_r, neogeo_paletteram_w) + AM_RANGE(0x800000, 0x800fff) AM_READWRITE(memcard_r, memcard_w) + AM_RANGE(0xc00000, 0xc1ffff) AM_MIRROR(0x0e0000) AM_ROM AM_REGION("mainbios", 0) + AM_RANGE(0xd00000, 0xd0ffff) AM_MIRROR(0x0f0000) AM_RAM_WRITE(save_ram_w) AM_SHARE("saveram") + AM_RANGE(0xe00000, 0xffffff) AM_READ(neogeo_unmapped_r) +ADDRESS_MAP_END + + + + +static ADDRESS_MAP_START( main_map_slot, AS_PROGRAM, 16, neogeo_state ) + AM_RANGE(0x000000, 0x00007f) AM_READ(neogeo_slot_rom_low_bectors_r) + AM_RANGE(0x000080, 0x0fffff) AM_READ(neogeo_slot_rom_low_r) + AM_RANGE(0x200000, 0x2fffff) AM_ROMBANK("cartridge") +// AM_RANGE(0x2ffff0, 0x2fffff) AM_WRITE(main_cpu_bank_select_w) + AM_IMPORT_FROM( neogeo_main_map ) +ADDRESS_MAP_END + +/************************************* + * + * Audio CPU memory handlers + * + *************************************/ + +static ADDRESS_MAP_START( audio_map, AS_PROGRAM, 8, neogeo_state ) + AM_RANGE(0x0000, 0x7fff) AM_ROMBANK("audio_main") + AM_RANGE(0x8000, 0xbfff) AM_ROMBANK("audio_8000") + AM_RANGE(0xc000, 0xdfff) AM_ROMBANK("audio_c000") + AM_RANGE(0xe000, 0xefff) AM_ROMBANK("audio_e000") + AM_RANGE(0xf000, 0xf7ff) AM_ROMBANK("audio_f000") + AM_RANGE(0xf800, 0xffff) AM_RAM +ADDRESS_MAP_END + + + +/************************************* + * + * Audio CPU port handlers + * + *************************************/ + +static ADDRESS_MAP_START( audio_io_map, AS_IO, 8, neogeo_state ) + AM_RANGE(0x00, 0x00) AM_MIRROR(0xff00) AM_READWRITE(audio_command_r, soundlatch_clear_byte_w) + AM_RANGE(0x04, 0x07) AM_MIRROR(0xff00) AM_DEVREADWRITE("ymsnd", ym2610_device, read, write) + AM_RANGE(0x08, 0x08) AM_MIRROR(0xff10) AM_MASK(0x0010) AM_WRITE(audio_cpu_enable_nmi_w) + AM_RANGE(0x08, 0x0b) AM_MIRROR(0xfff0) AM_MASK(0xff03) AM_READ(audio_cpu_bank_select_r) + AM_RANGE(0x0c, 0x0c) AM_MIRROR(0xff00) AM_WRITE(soundlatch2_byte_w) +ADDRESS_MAP_END + + + +/************************************* + * + * Standard Neo-Geo DIPs and + * input port definition + * + *************************************/ + +INPUT_PORTS_START( neogeo ) + PORT_START("P1/DSW") + PORT_DIPNAME( 0x0001, 0x0001, "Setting Mode" ) PORT_DIPLOCATION("SW:1") + PORT_DIPSETTING( 0x0001, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x0002, 0x0002, DEF_STR( Cabinet ) ) PORT_DIPLOCATION("SW:2") + PORT_DIPSETTING( 0x0002, DEF_STR( Normal ) ) + PORT_DIPSETTING( 0x0000, "VS Mode" ) + PORT_DIPNAME( 0x0004, 0x0004, DEF_STR( Controller ) ) PORT_DIPLOCATION("SW:3") + PORT_DIPSETTING( 0x0004, DEF_STR( Joystick ) ) + PORT_DIPSETTING( 0x0000, "Mahjong Panel" ) + PORT_DIPNAME( 0x0018, 0x0018, "COMM Setting (Cabinet No.)" ) PORT_DIPLOCATION("SW:4,5") + PORT_DIPSETTING( 0x0018, "1" ) + PORT_DIPSETTING( 0x0010, "2" ) + PORT_DIPSETTING( 0x0008, "3" ) + PORT_DIPSETTING( 0x0000, "4" ) + PORT_DIPNAME( 0x0020, 0x0020, "COMM Setting (Link Enable)" ) PORT_DIPLOCATION("SW:6") + PORT_DIPSETTING( 0x0020, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x0040, 0x0040, DEF_STR( Free_Play ) ) PORT_DIPLOCATION("SW:7") + PORT_DIPSETTING( 0x0040, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x0080, 0x0080, "Freeze" ) PORT_DIPLOCATION("SW:8") + PORT_DIPSETTING( 0x0080, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) + PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) + PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) + PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) + PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 ) + PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON2 ) + PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON3 ) + PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_BUTTON4 ) + + PORT_START("P2") + PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) + PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) + PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) + PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) + PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) + PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) + PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) + PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) + + PORT_START("SYSTEM") + PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_START1 ) + PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Next Game") PORT_CODE(KEYCODE_3) + PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_START2 ) + PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Previous Game") PORT_CODE(KEYCODE_4) + PORT_BIT( 0x7000, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(DEVICE_SELF, neogeo_state, get_memcard_status, NULL) + PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_SPECIAL ) /* Hardware type (AES=0, MVS=1). Some games check this and show a piracy warning screen if the hardware and BIOS don't match */ + + PORT_START("AUDIO/COIN") + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_COIN1 ) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_COIN2 ) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_SERVICE1 ) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_COIN3 ) /* What is this? "us-e" BIOS uses it as a coin input; Universe BIOS uses it to detect MVS or AES hardware */ + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_COIN4 ) /* What is this? "us-e" BIOS uses it as a coin input; Universe BIOS uses it to detect MVS or AES hardware */ + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_SPECIAL ) /* what is this? When ACTIVE_HIGH + IN4 bit 6 ACTIVE_LOW MVS-4 slot is detected */ + PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_READ_LINE_DEVICE_MEMBER("upd4990a", upd1990a_device, tp_r) + PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_READ_LINE_DEVICE_MEMBER("upd4990a", upd1990a_device, data_out_r) + PORT_BIT( 0xff00, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(DEVICE_SELF, neogeo_state,get_audio_result, NULL) + + PORT_START("TEST") + PORT_BIT( 0x003f, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_SPECIAL ) /* what is this? If ACTIVE_LOW, MVS-6 slot detected, when ACTIVE_HIGH MVS-1 slot (AES) detected */ + PORT_SERVICE_NO_TOGGLE( 0x0080, IP_ACTIVE_LOW ) + PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED ) +INPUT_PORTS_END + +static INPUT_PORTS_START( neogeo_6slot ) + PORT_INCLUDE( neogeo ) + + PORT_MODIFY("TEST") + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_SPECIAL ) +INPUT_PORTS_END + + + + +DRIVER_INIT_MEMBER(neogeo_state,mvs) +{ + DRIVER_INIT_CALL(neogeo); +} + + + + +/************************************* + * + * Machine driver + * + *************************************/ + +MACHINE_CONFIG_START( neogeo_base, neogeo_state ) + + /* basic machine hardware */ + MCFG_CPU_ADD("maincpu", M68000, NEOGEO_MAIN_CPU_CLOCK) + MCFG_CPU_PROGRAM_MAP(neogeo_main_map) + + MCFG_CPU_ADD("audiocpu", Z80, NEOGEO_AUDIO_CPU_CLOCK) + MCFG_CPU_PROGRAM_MAP(audio_map) + MCFG_CPU_IO_MAP(audio_io_map) + + /* video hardware */ + MCFG_DEFAULT_LAYOUT(layout_neogeo) + + MCFG_SCREEN_ADD("screen", RASTER) + MCFG_SCREEN_RAW_PARAMS(NEOGEO_PIXEL_CLOCK, NEOGEO_HTOTAL, NEOGEO_HBEND, NEOGEO_HBSTART, NEOGEO_VTOTAL, NEOGEO_VBEND, NEOGEO_VBSTART) + MCFG_SCREEN_UPDATE_DRIVER(neogeo_state, screen_update_neogeo) + + /* 4096 colors * two banks * normal and shadow */ + MCFG_PALETTE_ADD_INIT_BLACK("palette", 4096*2*2) + + MCFG_DEVICE_ADD("spritegen", NEOGEO_SPRITE_OPTIMZIED, 0) + + /* audio hardware */ + MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") + + MCFG_SOUND_ADD("ymsnd", YM2610, NEOGEO_YM2610_CLOCK) + MCFG_YM2610_IRQ_HANDLER(INPUTLINE("audiocpu", 0)) + MCFG_SOUND_ROUTE(0, "lspeaker", 0.28) + MCFG_SOUND_ROUTE(0, "rspeaker", 0.28) + MCFG_SOUND_ROUTE(1, "lspeaker", 0.98) + MCFG_SOUND_ROUTE(2, "rspeaker", 0.98) + MCFG_NEOGEO_BANKED_CART_ADD("banked_cart") + +MACHINE_CONFIG_END + + +MACHINE_CONFIG_DERIVED( neogeo_arcade, neogeo_base ) + MCFG_WATCHDOG_TIME_INIT(attotime::from_ticks(3244030, NEOGEO_MASTER_CLOCK)) + MCFG_UPD4990A_ADD("upd4990a", XTAL_32_768kHz, NULL, NULL) + MCFG_NVRAM_ADD_0FILL("saveram") + MCFG_NEOGEO_MEMCARD_ADD("memcard") +MACHINE_CONFIG_END + + +static MACHINE_CONFIG_DERIVED( mvs, neogeo_arcade ) + MCFG_CPU_MODIFY("maincpu") + MCFG_CPU_PROGRAM_MAP(main_map_slot) + + MCFG_NEOGEO_CARTRIDGE_ADD("cartslot1", neogeo_cart, NULL) + MCFG_NEOGEO_CARTRIDGE_ADD("cartslot2", neogeo_cart, NULL) + MCFG_NEOGEO_CARTRIDGE_ADD("cartslot3", neogeo_cart, NULL) + MCFG_NEOGEO_CARTRIDGE_ADD("cartslot4", neogeo_cart, NULL) + MCFG_NEOGEO_CARTRIDGE_ADD("cartslot5", neogeo_cart, NULL) + MCFG_NEOGEO_CARTRIDGE_ADD("cartslot6", neogeo_cart, NULL) + + MCFG_SOFTWARE_LIST_ADD("cart_list","neogeo") +MACHINE_CONFIG_END + + + + + + + +/* dummy entry for the dummy bios driver */ +ROM_START( neogeo ) + NEOGEO_BIOS + + ROM_REGION( 0x100000, "maincpu", ROMREGION_ERASEFF ) + + ROM_REGION( 0x20000, "audiobios", 0 ) + ROM_LOAD( "sm1.sm1", 0x00000, 0x20000, CRC(94416d67) SHA1(42f9d7ddd6c0931fd64226a60dc73602b2819dcf) ) + + ROM_REGION( 0x50000, "audiocpu", 0 ) + ROM_LOAD( "sm1.sm1", 0x00000, 0x20000, CRC(94416d67) SHA1(42f9d7ddd6c0931fd64226a60dc73602b2819dcf) ) + + ROM_Y_ZOOM + + ROM_REGION( 0x20000, "fixed", ROMREGION_ERASEFF ) + + ROM_REGION( 0x20000, "fixedbios", 0 ) + ROM_LOAD( "sfix.sfix", 0x000000, 0x20000, CRC(c2ea0cfd) SHA1(fd4a618cdcdbf849374f0a50dd8efe9dbab706c3) ) + + ROM_REGION( 0x10000, "ymsnd", ROMREGION_ERASEFF ) + + NO_DELTAT_REGION + + ROM_REGION( 0x100000, "sprites", ROMREGION_ERASEFF ) +ROM_END + + +/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT */ +CONS( 1990, neogeo, 0, 0, mvs, neogeo_6slot, neogeo_state, mvs, "SNK", "Neo-Geo", MACHINE_IS_BIOS_ROOT | MACHINE_SUPPORTS_SAVE ) |