diff --git a/hash/nes.xml b/hash/nes.xml index 19f76149901..16b47f6b28e 100644 --- a/hash/nes.xml +++ b/hash/nes.xml @@ -79008,4 +79008,25 @@ that the real dumps might surface --> + + + Family Computer Disk System (Jpn) + 1986 + Nintendo + + + + + + + + + + + + + + + + diff --git a/src/emu/bus/bus.mak b/src/emu/bus/bus.mak index 004a965e1ce..700e82a046a 100644 --- a/src/emu/bus/bus.mak +++ b/src/emu/bus/bus.mak @@ -878,6 +878,7 @@ BUSOBJS += $(BUSOBJ)/nes/cne.o BUSOBJS += $(BUSOBJ)/nes/cony.o BUSOBJS += $(BUSOBJ)/nes/datach.o BUSOBJS += $(BUSOBJ)/nes/discrete.o +BUSOBJS += $(BUSOBJ)/nes/disksys.o BUSOBJS += $(BUSOBJ)/nes/event.o BUSOBJS += $(BUSOBJ)/nes/ggenie.o BUSOBJS += $(BUSOBJ)/nes/henggedianzi.o diff --git a/src/emu/bus/nes/nes_carts.c b/src/emu/bus/nes/nes_carts.c index 36fcc76c0e4..d932ac8b567 100644 --- a/src/emu/bus/nes/nes_carts.c +++ b/src/emu/bus/nes/nes_carts.c @@ -51,6 +51,8 @@ SLOT_INTERFACE_START(nes_cart) SLOT_INTERFACE_INTERNAL("txsrom", NES_TXSROM) // ExROM SLOT_INTERFACE_INTERNAL("exrom", NES_EXROM) +// RAM expansion + Disk System add-on + SLOT_INTERFACE_INTERNAL("disksys", NES_DISKSYS) // Nintendo Custom boards SLOT_INTERFACE_INTERNAL("pal_zz", NES_ZZ_PCB) SLOT_INTERFACE_INTERNAL("nes_qj", NES_QJ_PCB) @@ -355,3 +357,8 @@ SLOT_INTERFACE_START(nes_cart) // SLOT_INTERFACE_INTERNAL("unknown", NES_NROM) // a few pirate dumps uses the wrong mapper... SLOT_INTERFACE_END + +SLOT_INTERFACE_START(disksys_only) + // RAM expansion + Disk System add-on + SLOT_INTERFACE("disksys", NES_DISKSYS) +SLOT_INTERFACE_END diff --git a/src/emu/bus/nes/nes_carts.h b/src/emu/bus/nes/nes_carts.h index 1c434b72d64..c4e35e0e5a1 100644 --- a/src/emu/bus/nes/nes_carts.h +++ b/src/emu/bus/nes/nes_carts.h @@ -20,6 +20,7 @@ #include "bandai.h" #include "datach.h" #include "discrete.h" +#include "disksys.h" #include "event.h" #include "irem.h" #include "jaleco.h" @@ -65,5 +66,6 @@ // supported devices SLOT_INTERFACE_EXTERN(nes_cart); +SLOT_INTERFACE_EXTERN(disksys_only); #endif // __NES_CARTS_H__ diff --git a/src/emu/bus/nes/nes_pcb.inc b/src/emu/bus/nes/nes_pcb.inc index 11d14d96042..aed2e7c6209 100644 --- a/src/emu/bus/nes/nes_pcb.inc +++ b/src/emu/bus/nes/nes_pcb.inc @@ -37,6 +37,7 @@ static const nes_pcb pcb_list[] = { "tqrom", STD_TQROM }, { "txsrom", STD_TXSROM }, { "exrom", STD_EXROM }, + { "disksys", STD_DISKSYS }, { "pal_zz", PAL_ZZ }, { "nes_qj", NES_QJ }, { "nes_event", STD_EVENT }, diff --git a/src/emu/bus/nes/nes_slot.c b/src/emu/bus/nes/nes_slot.c index 58b8345cf29..f2bf1255b86 100644 --- a/src/emu/bus/nes/nes_slot.c +++ b/src/emu/bus/nes/nes_slot.c @@ -663,24 +663,30 @@ WRITE8_MEMBER(device_nes_cart_interface::write_h) } -void device_nes_cart_interface::pcb_start(running_machine &machine, UINT8 *ciram_ptr) +void device_nes_cart_interface::pcb_start(running_machine &machine, UINT8 *ciram_ptr, bool cart_mounted) { - // Setup PRG - m_prg_bank_mem[0] = machine.root_device().membank("prg0"); - m_prg_bank_mem[1] = machine.root_device().membank("prg1"); - m_prg_bank_mem[2] = machine.root_device().membank("prg2"); - m_prg_bank_mem[3] = machine.root_device().membank("prg3"); - for (int i = 0; i < 4; i++) + if (cart_mounted) // disksys expansion can arrive here without the memory banks! { - m_prg_bank_mem[i]->configure_entries(0, m_prg.count() / 0x2000, m_prg, 0x2000); - m_prg_bank_mem[i]->set_entry(i); - m_prg_bank[i] = i; + // Setup PRG + m_prg_bank_mem[0] = machine.root_device().membank("prg0"); + m_prg_bank_mem[1] = machine.root_device().membank("prg1"); + m_prg_bank_mem[2] = machine.root_device().membank("prg2"); + m_prg_bank_mem[3] = machine.root_device().membank("prg3"); + for (int i = 0; i < 4; i++) + { + if (m_prg_bank_mem[i]) + { + m_prg_bank_mem[i]->configure_entries(0, m_prg.count() / 0x2000, m_prg, 0x2000); + m_prg_bank_mem[i]->set_entry(i); + m_prg_bank[i] = i; + } + } + + // Setup CHR + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + chr8(0, m_chr_source); } - // Setup CHR - m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; - chr8(0, m_chr_source); - // Setup NT m_ciram = ciram_ptr; @@ -733,7 +739,8 @@ nes_cart_slot_device::nes_cart_slot_device(const machine_config &mconfig, const device_slot_interface(mconfig, *this), m_crc_hack(0), m_pcb_id(NO_BOARD), - m_must_be_loaded(1) + m_must_be_loaded(1), + m_empty(TRUE) { } @@ -770,7 +777,7 @@ void nes_cart_slot_device::device_config_complete() void nes_cart_slot_device::pcb_start(UINT8 *ciram_ptr) { if (m_cart) - m_cart->pcb_start(machine(), ciram_ptr); + m_cart->pcb_start(machine(), ciram_ptr, cart_mounted()); } void nes_cart_slot_device::pcb_reset() @@ -835,6 +842,7 @@ bool nes_cart_slot_device::call_load() } call_load_ines(); + m_empty = FALSE; } else if ((magic[0] == 'U') && (magic[1] == 'N') && (magic[2] == 'I') && (magic[3] == 'F')) /* If header starts with 'UNIF' it is UNIF */ { @@ -845,6 +853,7 @@ bool nes_cart_slot_device::call_load() } call_load_unif(); + m_empty = FALSE; } else { @@ -853,7 +862,10 @@ bool nes_cart_slot_device::call_load() } } else + { call_load_pcb(); + m_empty = FALSE; + } } return IMAGE_INIT_PASS; diff --git a/src/emu/bus/nes/nes_slot.h b/src/emu/bus/nes/nes_slot.h index d8407cf7af3..5327933d910 100644 --- a/src/emu/bus/nes/nes_slot.h +++ b/src/emu/bus/nes/nes_slot.h @@ -21,6 +21,7 @@ enum STD_UXROM, STD_UN1ROM, UXROM_CC, HVC_FAMBASIC, NES_QJ, PAL_ZZ, STD_EVENT, STD_SXROM_A, STD_SOROM, STD_SOROM_A, + STD_DISKSYS, STD_NROM368,//homebrew extension of NROM! /* Discrete components boards (by various manufacturer) */ DIS_74X161X138, DIS_74X139X74, @@ -172,6 +173,9 @@ public: virtual DECLARE_READ8_MEMBER(nt_r); virtual DECLARE_WRITE8_MEMBER(nt_w); + // hack until disk system is made modern! + virtual void disk_flip_side() { } + void prg_alloc(size_t size); void prgram_alloc(size_t size); void vrom_alloc(size_t size); @@ -212,7 +216,7 @@ public: virtual void scanline_irq(int scanline, int vblank, int blanked) {} virtual void pcb_reset() {} // many pcb expect specific PRG/CHR banking at start - void pcb_start(running_machine &machine, UINT8 *ciram_ptr); + void pcb_start(running_machine &machine, UINT8 *ciram_ptr, bool cart_mounted); void pcb_reg_postload(running_machine &machine); void nes_banks_restore(); @@ -356,6 +360,7 @@ public: const char * get_default_card_unif(UINT8 *ROM, UINT32 len); const char * nes_get_slot(int pcb_id); int nes_get_pcb_id(const char *slot); + bool cart_mounted() { return !m_empty; } // reading and writing virtual DECLARE_READ8_MEMBER(read_l); @@ -366,7 +371,10 @@ public: virtual DECLARE_WRITE8_MEMBER(write_m); virtual DECLARE_WRITE8_MEMBER(write_h); virtual DECLARE_WRITE8_MEMBER(write_ex); - + + // hack until disk system is made modern! + virtual void disk_flip_side() { if (m_cart) m_cart->disk_flip_side(); } + int get_pcb_id() { return m_pcb_id; }; void pcb_start(UINT8 *ciram_ptr); @@ -384,6 +392,7 @@ public: device_nes_cart_interface* m_cart; int m_pcb_id; bool m_must_be_loaded; + bool m_empty; }; // device type definition @@ -401,4 +410,10 @@ extern const device_type NES_CART_SLOT; #define MCFG_NES_CARTRIDGE_NOT_MANDATORY \ static_cast(device)->set_must_be_loaded(FALSE); +// Hacky configuration to add a slot with fixed disksys interface +#define MCFG_DISKSYS_ADD(_tag, _slot_intf, _def_slot) \ + MCFG_DEVICE_ADD(_tag, NES_CART_SLOT, 0) \ + MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, true) \ + MCFG_NES_CARTRIDGE_NOT_MANDATORY + #endif diff --git a/src/mess/drivers/nes.c b/src/mess/drivers/nes.c index 9c3183e24ca..dec3a77ff1d 100644 --- a/src/mess/drivers/nes.c +++ b/src/mess/drivers/nes.c @@ -13,8 +13,6 @@ #include "emu.h" #include "includes/nes.h" #include "cpu/m6502/n2a03.h" -#include "imagedev/flopdrv.h" -#include "formats/nes_dsk.h" READ8_MEMBER(nes_state::psg_4015_r) { @@ -646,14 +644,6 @@ void nes_state::ppu_nmi(int *ppu_regs) } -static const floppy_interface nes_floppy_interface = -{ - FLOPPY_STANDARD_5_25_DSHD, - LEGACY_FLOPPY_OPTIONS_NAME(nes_only), - "floppy_5_25" -}; - - static MACHINE_CONFIG_START( nes, nes_state ) /* basic machine hardware */ MCFG_CPU_ADD("maincpu", N2A03, NTSC_CLOCK) @@ -739,22 +729,108 @@ static MACHINE_CONFIG_DERIVED( dendy, nes ) MACHINE_CONFIG_END static MACHINE_CONFIG_DERIVED( famicom, nes ) - MCFG_DEVICE_REMOVE("nes_slot") - MCFG_NES_CARTRIDGE_ADD("nes_slot", nes_cart, NULL) - MCFG_NES_CARTRIDGE_NOT_MANDATORY - - MCFG_LEGACY_FLOPPY_DRIVE_ADD(FLOPPY_0, nes_floppy_interface) - MCFG_SOFTWARE_LIST_ADD("flop_list", "famicom_flop") - MCFG_CASSETTE_ADD( "tape" ) MCFG_CASSETTE_DEFAULT_STATE(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED) MCFG_CASSETTE_INTERFACE("fc_cass") + MCFG_SOFTWARE_LIST_ADD("flop_list", "famicom_flop") MCFG_SOFTWARE_LIST_ADD("cass_list", "famicom_cass") MACHINE_CONFIG_END +void nes_state::setup_disk(nes_cart_slot_device *slot) +{ + address_space &space = m_maincpu->space(AS_PROGRAM); + + if (slot) + { + // Set up memory handlers + space.install_read_handler(0x4020, 0x40ff, read8_delegate(FUNC(nes_cart_slot_device::read_ex), (nes_cart_slot_device *)slot)); + space.install_write_handler(0x4020, 0x40ff, write8_delegate(FUNC(nes_cart_slot_device::write_ex), (nes_cart_slot_device *)slot)); + space.install_read_handler(0x4100, 0x5fff, read8_delegate(FUNC(nes_cart_slot_device::read_l), (nes_cart_slot_device *)slot)); + space.install_write_handler(0x4100, 0x5fff, write8_delegate(FUNC(nes_cart_slot_device::write_l), (nes_cart_slot_device *)slot)); + space.install_read_handler(0x6000, 0x7fff, read8_delegate(FUNC(nes_cart_slot_device::read_m), (nes_cart_slot_device *)slot)); + space.install_write_handler(0x6000, 0x7fff, write8_delegate(FUNC(nes_cart_slot_device::write_m), (nes_cart_slot_device *)slot)); + space.install_read_handler(0x8000, 0xffff, read8_delegate(FUNC(nes_cart_slot_device::read_h), (nes_cart_slot_device *)slot)); + space.install_write_handler(0x8000, 0xffff, write8_delegate(FUNC(nes_cart_slot_device::write_h), (nes_cart_slot_device *)slot)); + + slot->m_cart->vram_alloc(0x2000); + slot->m_cart->prgram_alloc(0x8000); + + slot->pcb_start(m_ciram); + slot->m_cart->pcb_reg_postload(machine()); + m_ppu->space(AS_PROGRAM).install_readwrite_handler(0, 0x1fff, read8_delegate(FUNC(device_nes_cart_interface::chr_r),slot->m_cart), write8_delegate(FUNC(device_nes_cart_interface::chr_w),slot->m_cart)); + m_ppu->space(AS_PROGRAM).install_readwrite_handler(0x2000, 0x3eff, read8_delegate(FUNC(device_nes_cart_interface::nt_r),slot->m_cart), write8_delegate(FUNC(device_nes_cart_interface::nt_w),slot->m_cart)); + m_ppu->set_scanline_callback(ppu2c0x_scanline_delegate(FUNC(device_nes_cart_interface::scanline_irq),slot->m_cart)); + m_ppu->set_hblank_callback(ppu2c0x_hblank_delegate(FUNC(device_nes_cart_interface::hblank_irq),slot->m_cart)); + m_ppu->set_latch(ppu2c0x_latch_delegate(FUNC(device_nes_cart_interface::ppu_latch),slot->m_cart)); + } +} + + +MACHINE_START_MEMBER( nes_state, fds ) +{ + m_ciram = auto_alloc_array(machine(), UINT8, 0x800); + setup_ioports(); + // setup the disk expansion instead + setup_disk(m_cartslot); +} + +static MACHINE_CONFIG_DERIVED( fds, famicom ) + MCFG_MACHINE_START_OVERRIDE( nes_state, fds ) + MCFG_DEVICE_REMOVE("tape") + + MCFG_DEVICE_REMOVE("nes_slot") + MCFG_DISKSYS_ADD("nes_slot", disksys_only, "disksys") + + MCFG_DEVICE_REMOVE("cart_list") + MCFG_DEVICE_REMOVE("cass_list") +MACHINE_CONFIG_END + + +MACHINE_START_MEMBER( nes_state, famitwin ) +{ + // start the base nes stuff + machine_start(); + + // if there is no cart inserted, setup the disk expansion instead + if (!m_cartslot->m_cart) + setup_disk(m_cartslot2); +} + +MACHINE_RESET_MEMBER( nes_state, famitwin ) +{ + // Reset the mapper variables. Will also mark the char-gen ram as dirty + m_cartslot->pcb_reset(); + // if there is no cart inserted, initialize the disk expansion instead + if (!m_cartslot->m_cart) + m_cartslot2->pcb_reset(); + + // the rest is the same as for nes/famicom/dendy + m_maincpu->reset(); + + memset(m_pad_latch, 0, sizeof(m_pad_latch)); + memset(m_zapper_latch, 0, sizeof(m_zapper_latch)); + m_paddle_latch = 0; + m_paddle_btn_latch = 0; +} + +static MACHINE_CONFIG_DERIVED( famitwin, famicom ) + + MCFG_MACHINE_START_OVERRIDE( nes_state, famitwin ) + MCFG_MACHINE_RESET_OVERRIDE( nes_state, famitwin ) + + MCFG_SCREEN_MODIFY("screen") + MCFG_SCREEN_UPDATE_DRIVER(nes_state, screen_update_famitwin) + + MCFG_DEVICE_REMOVE("nes_slot") + MCFG_NES_CARTRIDGE_ADD("nes_slot", nes_cart, NULL) + MCFG_NES_CARTRIDGE_NOT_MANDATORY + + MCFG_DISKSYS_ADD("disk_slot", disksys_only, "disksys") +MACHINE_CONFIG_END + + -/* rom regions are just place-holders: they get removed and re-allocated when a cart is loaded */ ROM_START( nes ) ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASE00 ) /* Main RAM */ ROM_END @@ -764,13 +840,11 @@ ROM_START( nespal ) ROM_END ROM_START( famicom ) - ROM_REGION( 0x10000, "maincpu", 0 ) /* Main RAM */ - ROM_SYSTEM_BIOS( 0, "2c33a-01a", "Famicom Disk System Bios") - ROMX_LOAD( "rp2c33a-01a.bin", 0xe000, 0x2000, CRC(5e607dcf) SHA1(57fe1bdee955bb48d357e463ccbf129496930b62), ROM_BIOS(1)) // newer, Nintendo logo has no shadow - ROM_SYSTEM_BIOS( 1, "2c33-01", "Famicom Disk System Bios, older") - ROMX_LOAD( "rp2c33-01.bin", 0xe000, 0x2000, CRC(1c7ae5d5) SHA1(af5af53f66982e749643fdf8b2acbb7d4d3ed229), ROM_BIOS(2)) // older, Nintendo logo has shadow + ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASE00 ) /* Main RAM */ ROM_END +#define rom_fds rom_famicom + ROM_START( famitwin ) ROM_REGION( 0x10000, "maincpu", 0 ) /* Main RAM */ ROM_LOAD( "rp2c33a-02.bin", 0xe000, 0x2000, CRC(4df24a6c) SHA1(e4e41472c454f928e53eb10e0509bf7d1146ecc1) ) // "Famicom" logo instead of Nintendo logo @@ -799,7 +873,6 @@ ROM_END ROM_START( gchinatv ) ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASE00 ) /* Main RAM */ - ROM_REGION( 0x800, "ciram", ROMREGION_ERASE00 ) /* CI RAM */ ROM_END /*************************************************************************** @@ -809,11 +882,12 @@ ROM_END ***************************************************************************/ /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */ -CONS( 1985, nes, 0, 0, nes, nes, driver_device, 0, "Nintendo", "Nintendo Entertainment System / Famicom (NTSC)", GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) -CONS( 1987, nespal, nes, 0, nespal, nes, driver_device, 0, "Nintendo", "Nintendo Entertainment System (PAL)", GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) -CONS( 1983, famicom, nes, 0, famicom, famicom, nes_state, famicom, "Nintendo", "Famicom (w/ Disk System add-on)", GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) -CONS( 1986, famitwin, nes, 0, famicom, famicom, nes_state, famicom, "Sharp", "Famicom Twin", GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) -CONS( 198?, m82, nes, 0, nes, nes, driver_device, 0, "Nintendo", "M82 Display Unit", GAME_IMPERFECT_GRAPHICS | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) -CONS( 1996, drpcjr, nes, 0, famicom, famicom, nes_state, famicom, "Bung", "Doctor PC Jr", GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) -CONS( 1992, dendy, nes, 0, dendy, nes, driver_device, 0, "Steepler", "Dendy Classic", GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) -CONS( 198?, gchinatv, nes, 0, nespal, nes, driver_device, 0, "Golden China", "Golden China TV Game", GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) +CONS( 1985, nes, 0, 0, nes, nes, driver_device, 0, "Nintendo", "Nintendo Entertainment System / Famicom (NTSC)", GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) +CONS( 1987, nespal, nes, 0, nespal, nes, driver_device, 0, "Nintendo", "Nintendo Entertainment System (PAL)", GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) +CONS( 1983, famicom, nes, 0, famicom, famicom, nes_state, famicom, "Nintendo", "Famicom (NTSC)", GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) +CONS( 1983, fds, nes, 0, fds, famicom, nes_state, famicom, "Nintendo", "Famicom (w/ Disk System add-on)", GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) +CONS( 1986, famitwin, nes, 0, famitwin, famicom, nes_state, famicom, "Sharp", "Famicom Twin", GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) +CONS( 198?, m82, nes, 0, nes, nes, driver_device, 0, "Nintendo", "M82 Display Unit", GAME_IMPERFECT_GRAPHICS | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) +CONS( 1996, drpcjr, nes, 0, famicom, famicom, nes_state, famicom, "Bung", "Doctor PC Jr", GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) +CONS( 1992, dendy, nes, 0, dendy, nes, driver_device, 0, "Steepler", "Dendy Classic", GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) +CONS( 198?, gchinatv, nes, 0, nespal, nes, driver_device, 0, "Golden China", "Golden China TV Game", GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) diff --git a/src/mess/includes/nes.h b/src/mess/includes/nes.h index e6d606e000f..5a602d5024e 100644 --- a/src/mess/includes/nes.h +++ b/src/mess/includes/nes.h @@ -69,6 +69,7 @@ public: m_ppu(*this, "ppu"), m_sound(*this, "nessound"), m_cartslot(*this, "nes_slot"), + m_cartslot2(*this, "disk_slot"), // temp hack for famitwin m_cassette(*this, "tape") { } @@ -76,7 +77,6 @@ public: int m_last_frame_flip; /* misc */ - ioport_port *m_io_ctrlsel; ioport_port *m_io_fckey[9]; ioport_port *m_io_subkey[13]; @@ -95,6 +95,7 @@ public: ioport_port *m_io_paddle; ioport_port *m_io_paddle_btn; ioport_port *m_io_exp; + ioport_port *m_io_disksel; UINT8 *m_vram; UINT8 *m_ciram; //PPU nametable RAM - external to PPU! @@ -103,6 +104,7 @@ public: required_device m_ppu; required_device m_sound; optional_device m_cartslot; + optional_device m_cartslot2; optional_device m_cassette; int nes_ppu_vidaccess(int address, int data); @@ -122,48 +124,20 @@ public: virtual void video_reset(); DECLARE_PALETTE_INIT(nes); UINT32 screen_update_nes(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + UINT32 screen_update_famitwin(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); DECLARE_READ8_MEMBER(psg_4015_r); DECLARE_WRITE8_MEMBER(psg_4015_w); DECLARE_WRITE8_MEMBER(psg_4017_w); void state_register(); + void setup_ioports(); - /***** FDS-floppy related *****/ - - DECLARE_WRITE8_MEMBER(fds_chr_w); - DECLARE_READ8_MEMBER(fds_chr_r); - DECLARE_WRITE8_MEMBER(fds_nt_w); - DECLARE_READ8_MEMBER(fds_nt_r); - - int m_disk_expansion; - - UINT8 m_fds_sides; - UINT8 *m_fds_data; // here, we store a copy of the disk - UINT8 *m_fds_ram; // here, we emulate the RAM adapter - - /* Variables which can change */ - UINT8 m_fds_motor_on; - UINT8 m_fds_door_closed; - UINT8 m_fds_current_side; - UINT32 m_fds_head_position; - UINT8 m_fds_status0; - UINT8 m_fds_read_mode; - UINT8 m_fds_write_reg; - int m_fds_mirroring; - - int m_IRQ_enable, m_IRQ_enable_latch; - UINT16 m_IRQ_count, m_IRQ_count_latch; - - /* these are used in the mapper 20 handlers */ - int m_fds_last_side; - int m_fds_count; - DECLARE_READ8_MEMBER(nes_fds_r); - DECLARE_WRITE8_MEMBER(nes_fds_w); DECLARE_DRIVER_INIT(famicom); - DECLARE_DEVICE_IMAGE_LOAD_MEMBER(nes_disk); - DECLARE_DEVICE_IMAGE_UNLOAD_MEMBER(nes_disk); - - void fds_irq(int scanline, int vblank, int blanked); + // these are needed until we modernize the FDS controller + DECLARE_MACHINE_START(fds); + DECLARE_MACHINE_START(famitwin); + DECLARE_MACHINE_RESET(famitwin); + void setup_disk(nes_cart_slot_device *slot); // input related UINT32 m_pad_latch[4]; diff --git a/src/mess/machine/nes.c b/src/mess/machine/nes.c index dbbe249cb24..3a27501a357 100644 --- a/src/mess/machine/nes.c +++ b/src/mess/machine/nes.c @@ -34,12 +34,14 @@ int nes_state::nes_ppu_vidaccess( int address, int data ) return data; } +//------------------------------------------------- +// machine_reset +//------------------------------------------------- + void nes_state::machine_reset() { - /* Reset the mapper variables. Will also mark the char-gen ram as dirty */ - if (m_disk_expansion && m_cartslot && !m_cartslot->m_cart) - m_ppu->set_hblank_callback(ppu2c0x_hblank_delegate(FUNC(nes_state::fds_irq),this)); - else if (m_cartslot) + // Reset the mapper variables. Will also mark the char-gen ram as dirty + if (m_cartslot) m_cartslot->pcb_reset(); m_maincpu->reset(); @@ -50,26 +52,16 @@ void nes_state::machine_reset() m_paddle_btn_latch = 0; } +//------------------------------------------------- +// machine_start +//------------------------------------------------- + void nes_state::state_register() { save_item(NAME(m_last_frame_flip)); - save_item(NAME(m_fds_motor_on)); - save_item(NAME(m_fds_door_closed)); - save_item(NAME(m_fds_current_side)); - save_item(NAME(m_fds_head_position)); - save_item(NAME(m_fds_status0)); - save_item(NAME(m_fds_read_mode)); - save_item(NAME(m_fds_write_reg)); - save_item(NAME(m_fds_last_side)); - save_item(NAME(m_fds_count)); - save_item(NAME(m_fds_mirroring)); - save_pointer(NAME(m_ciram), 0x800); - if (m_disk_expansion) - save_pointer(NAME(m_vram), 0x2000); - save_item(NAME(m_pad_latch)); save_item(NAME(m_zapper_latch)); save_item(NAME(m_paddle_latch)); @@ -80,18 +72,9 @@ void nes_state::state_register() save_item(NAME(m_mic_obstruct)); save_item(NAME(m_powerpad_latch)); save_item(NAME(m_ftrainer_scan)); - save_item(NAME(m_IRQ_enable)); - save_item(NAME(m_IRQ_enable_latch)); - save_item(NAME(m_IRQ_count)); - save_item(NAME(m_IRQ_count_latch)); } - -//------------------------------------------------- -// machine_start -//------------------------------------------------- - -void nes_state::machine_start() +void nes_state::setup_ioports() { for (int i = 0; i < 9; i++) { @@ -115,7 +98,7 @@ void nes_state::machine_start() sprintf(str, "FT_COL%i", i); m_io_ftrainer[i] = ioport(str); } - + m_io_ctrlsel = ioport("CTRLSEL"); m_io_exp = ioport("EXP"); m_io_paddle = ioport("PADDLE"); @@ -130,7 +113,11 @@ void nes_state::machine_start() m_io_zapper2_y = ioport("ZAPPER2_Y"); m_io_powerpad[0] = ioport("POWERPAD1"); m_io_powerpad[1] = ioport("POWERPAD2"); + m_io_disksel = ioport("FLIPDISK"); +} +void nes_state::machine_start() +{ address_space &space = m_maincpu->space(AS_PROGRAM); // CIRAM (Character Internal RAM) @@ -140,6 +127,8 @@ void nes_state::machine_start() m_ciram = auto_alloc_array(machine(), UINT8, 0x800); // other pointers got set in the loading routine, because they 'belong' to the cart itself + setup_ioports(); + if (m_cartslot && m_cartslot->m_cart) { // Set up memory handlers @@ -153,8 +142,6 @@ void nes_state::machine_start() space.install_read_bank(0xe000, 0xffff, "prg3"); space.install_write_handler(0x8000, 0xffff, write8_delegate(FUNC(nes_cart_slot_device::write_h), (nes_cart_slot_device *)m_cartslot)); - m_cartslot->pcb_start(m_ciram); - m_cartslot->m_cart->pcb_reg_postload(machine()); m_ppu->space(AS_PROGRAM).install_readwrite_handler(0, 0x1fff, read8_delegate(FUNC(device_nes_cart_interface::chr_r),m_cartslot->m_cart), write8_delegate(FUNC(device_nes_cart_interface::chr_w),m_cartslot->m_cart)); m_ppu->space(AS_PROGRAM).install_readwrite_handler(0x2000, 0x3eff, read8_delegate(FUNC(device_nes_cart_interface::nt_r),m_cartslot->m_cart), write8_delegate(FUNC(device_nes_cart_interface::nt_w),m_cartslot->m_cart)); m_ppu->set_scanline_callback(ppu2c0x_scanline_delegate(FUNC(device_nes_cart_interface::scanline_irq),m_cartslot->m_cart)); @@ -162,7 +149,7 @@ void nes_state::machine_start() m_ppu->set_latch(ppu2c0x_latch_delegate(FUNC(device_nes_cart_interface::ppu_latch),m_cartslot->m_cart)); // install additional handlers (read_h, read_ex, write_ex) - if (m_cartslot->get_pcb_id() == STD_EXROM || m_cartslot->get_pcb_id() == STD_NROM368 + if (m_cartslot->get_pcb_id() == STD_EXROM || m_cartslot->get_pcb_id() == STD_NROM368 || m_cartslot->get_pcb_id() == STD_DISKSYS || m_cartslot->get_pcb_id() == GG_NROM || m_cartslot->get_pcb_id() == CAMERICA_ALADDIN || m_cartslot->get_pcb_id() == SUNSOFT_DCS || m_cartslot->get_pcb_id() == BANDAI_DATACH || m_cartslot->get_pcb_id() == BANDAI_KARAOKE || m_cartslot->get_pcb_id() == BTL_2A03_PURITANS || m_cartslot->get_pcb_id() == AVE_MAXI15 || m_cartslot->get_pcb_id() == KAISER_KS7022 || m_cartslot->get_pcb_id() == KAISER_KS7031 || m_cartslot->get_pcb_id() == BMC_VT5201 @@ -181,32 +168,15 @@ void nes_state::machine_start() space.install_write_handler(0x4020, 0x40ff, write8_delegate(FUNC(nes_cart_slot_device::write_ex), (nes_cart_slot_device *)m_cartslot)); } - if (m_cartslot->get_pcb_id() == KAISER_KS7017 || m_cartslot->get_pcb_id() == UNL_603_5052) + if (m_cartslot->get_pcb_id() == KAISER_KS7017 || m_cartslot->get_pcb_id() == UNL_603_5052 || m_cartslot->get_pcb_id() == STD_DISKSYS) { logerror("write_ex & read_ex installed!\n"); space.install_read_handler(0x4020, 0x40ff, read8_delegate(FUNC(nes_cart_slot_device::read_ex), (nes_cart_slot_device *)m_cartslot)); space.install_write_handler(0x4020, 0x40ff, write8_delegate(FUNC(nes_cart_slot_device::write_ex), (nes_cart_slot_device *)m_cartslot)); } - } - else if (m_disk_expansion) // if there is Disk Expansion and no cart has been loaded, setup memory accordingly - { - m_ppu->space(AS_PROGRAM).install_readwrite_handler(0, 0x1fff, read8_delegate(FUNC(nes_state::fds_chr_r),this), write8_delegate(FUNC(nes_state::fds_chr_w),this)); - m_ppu->space(AS_PROGRAM).install_readwrite_handler(0x2000, 0x3eff, read8_delegate(FUNC(nes_state::fds_nt_r),this), write8_delegate(FUNC(nes_state::fds_nt_w),this)); - if (!m_fds_ram) - m_fds_ram = auto_alloc_array(machine(), UINT8, 0x8000); - if (!m_vram) - m_vram = auto_alloc_array(machine(), UINT8, 0x2000); - - space.install_read_handler(0x4030, 0x403f, read8_delegate(FUNC(nes_state::nes_fds_r),this)); - space.install_read_bank(0x6000, 0xdfff, "fdsram"); - space.install_read_bank(0xe000, 0xffff, "bank1"); - - space.install_write_handler(0x4020, 0x402f, write8_delegate(FUNC(nes_state::nes_fds_w),this)); - space.install_write_bank(0x6000, 0xdfff, "fdsram"); - - membank("bank1")->set_base(machine().root_device().memregion("maincpu")->base() + 0xe000); - membank("fdsram")->set_base(m_fds_ram); + m_cartslot->pcb_start(m_ciram); + m_cartslot->m_cart->pcb_reg_postload(machine()); } state_register(); @@ -734,242 +704,8 @@ void nes_state::device_timer(emu_timer &timer, device_timer_id id, int param, vo } -/************************** - - Disk System emulation - -**************************/ - -void nes_state::fds_irq( int scanline, int vblank, int blanked ) -{ - if (m_IRQ_enable_latch) - m_maincpu->set_input_line(M6502_IRQ_LINE, HOLD_LINE); - - if (m_IRQ_enable) - { - if (m_IRQ_count <= 114) - { - m_maincpu->set_input_line(M6502_IRQ_LINE, HOLD_LINE); - m_IRQ_enable = 0; - m_fds_status0 |= 0x01; - } - else - m_IRQ_count -= 114; - } -} - -READ8_MEMBER(nes_state::nes_fds_r) -{ - UINT8 ret = 0x00; - - switch (offset) - { - case 0x00: /* $4030 - disk status 0 */ - ret = m_fds_status0; - /* clear the disk IRQ detect flag */ - m_fds_status0 &= ~0x01; - break; - case 0x01: /* $4031 - data latch */ - /* don't read data if disk is unloaded */ - if (!m_fds_data) - ret = 0; - else if (m_fds_current_side) - { - // a bunch of games (e.g. bshashsc and fairypin) keep reading beyond the last track - // what is the expected behavior? - if (m_fds_head_position > 65500) - m_fds_head_position = 0; - ret = m_fds_data[(m_fds_current_side - 1) * 65500 + m_fds_head_position++]; - } - else - ret = 0; - break; - case 0x02: /* $4032 - disk status 1 */ - /* return "no disk" status if disk is unloaded */ - if (!m_fds_data) - ret = 1; - else if (m_fds_last_side != m_fds_current_side) - { - /* If we've switched disks, report "no disk" for a few reads */ - ret = 1; - m_fds_count++; - if (m_fds_count == 50) - { - m_fds_last_side = m_fds_current_side; - m_fds_count = 0; - } - } - else - ret = (m_fds_current_side == 0); /* 0 if a disk is inserted */ - break; - case 0x03: /* $4033 */ - ret = 0x80; - break; - default: - ret = 0x00; - break; - } - - return ret; -} - -WRITE8_MEMBER(nes_state::nes_fds_w) -{ - switch (offset) - { - case 0x00: - m_IRQ_count_latch = (m_IRQ_count_latch & 0xff00) | data; - break; - case 0x01: - m_IRQ_count_latch = (m_IRQ_count_latch & 0x00ff) | (data << 8); - break; - case 0x02: - m_IRQ_count = m_IRQ_count_latch; - m_IRQ_enable = data; - break; - case 0x03: - // d0 = sound io (1 = enable) - // d1 = disk io (1 = enable) - break; - case 0x04: - /* write data out to disk */ - break; - case 0x05: - m_fds_motor_on = BIT(data, 0); - - if (BIT(data, 1)) - m_fds_head_position = 0; - - m_fds_read_mode = BIT(data, 2); - if (BIT(data, 3)) - m_fds_mirroring = PPU_MIRROR_HORZ; - else - m_fds_mirroring = PPU_MIRROR_VERT; - - if ((!(data & 0x40)) && (m_fds_write_reg & 0x40)) - m_fds_head_position -= 2; // ??? - - m_IRQ_enable_latch = BIT(data, 7); - m_fds_write_reg = data; - break; - } -} - -WRITE8_MEMBER(nes_state::fds_chr_w) -{ - m_vram[offset] = data; -} - -READ8_MEMBER(nes_state::fds_chr_r) -{ - return m_vram[offset]; -} - -WRITE8_MEMBER(nes_state::fds_nt_w) -{ - int page = ((offset & 0xc00) >> 10); - int bank; - - switch (page) - { - case 0: - bank = 0; - break; - case 1: - bank = (m_fds_mirroring == PPU_MIRROR_VERT) ? 1 : 0; - break; - case 2: - bank = (m_fds_mirroring == PPU_MIRROR_VERT) ? 0 : 1; - break; - case 3: - default: - bank = 1; - break; - } - - m_ciram[(bank * 0x400) + (offset & 0x3ff)] = data; -} - -READ8_MEMBER(nes_state::fds_nt_r) -{ - int page = ((offset & 0xc00) >> 10); - int bank; - - switch (page) - { - case 0: - bank = 0; - break; - case 1: - bank = (m_fds_mirroring == PPU_MIRROR_VERT) ? 1 : 0; - break; - case 2: - bank = (m_fds_mirroring == PPU_MIRROR_VERT) ? 0 : 1; - break; - case 3: - default: - bank = 1; - break; - } - - return m_ciram[(bank * 0x400) + (offset & 0x3ff)]; -} - - -// Disk interface - -static void nes_load_proc( device_image_interface &image ) -{ - nes_state *state = image.device().machine().driver_data(); - int header = 0; - state->m_fds_sides = 0; - - if (image.length() % 65500) - header = 0x10; - - state->m_fds_sides = (image.length() - header) / 65500; - - if (!state->m_fds_data) - state->m_fds_data = auto_alloc_array(image.device().machine(),UINT8,state->m_fds_sides * 65500); // I don't think we can arrive here ever, probably it can be removed... - - /* if there is an header, skip it */ - image.fseek(header, SEEK_SET); - - image.fread(state->m_fds_data, 65500 * state->m_fds_sides); - return; -} - -static void nes_unload_proc( device_image_interface &image ) -{ - nes_state *state = image.device().machine().driver_data(); - - /* TODO: should write out changes here as well */ - state->m_fds_sides = 0; -} - DRIVER_INIT_MEMBER(nes_state,famicom) { - /* initialize the disk system */ - m_disk_expansion = 1; - - m_fds_sides = 0; - m_fds_last_side = 0; - m_fds_count = 0; - m_fds_motor_on = 0; - m_fds_door_closed = 0; - m_fds_current_side = 1; - m_fds_head_position = 0; - m_fds_status0 = 0; - m_fds_read_mode = m_fds_write_reg = 0; - - m_fds_mirroring = PPU_MIRROR_VERT; // correct? - - m_fds_ram = auto_alloc_array_clear(machine(), UINT8, 0x8000); - save_pointer(NAME(m_fds_ram), 0x8000); - - floppy_get_device(machine(), 0)->floppy_install_load_proc(nes_load_proc); - floppy_get_device(machine(), 0)->floppy_install_unload_proc(nes_unload_proc); - // setup alt input handlers for additional FC input devices address_space &space = machine().device("maincpu")->space(AS_PROGRAM); space.install_read_handler(0x4016, 0x4016, read8_delegate(FUNC(nes_state::fc_in0_r), this)); diff --git a/src/mess/mess.lst b/src/mess/mess.lst index ff7d9e35834..779200eeac4 100644 --- a/src/mess/mess.lst +++ b/src/mess/mess.lst @@ -56,12 +56,14 @@ jaguarcd // Atari Jaguar CD // Nintendo nes // Nintendo Entertainment System -nespal // Nintendo Entertainment System PAL +nespal // Nintendo Entertainment System PAL m82 // Nintendo M82 Display Unit -famicom // Nintendo Family Computer (a.k.a. Famicom) + Disk System add-on +famicom // Nintendo Family Computer (a.k.a. Famicom) +fds // Nintendo Family Computer (a.k.a. Famicom) + Disk System add-on famitwin // Sharp Famicom Twin System drpcjr // Bung Doctor PC Jr dendy // Dendy (Classic russian famiclone) +gchinatv // Golden China TV Game Centre (Chinese famiclone) gameboy // Nintendo Game Boy Handheld supergb // Nintendo Super Game Boy SNES Cartridge gbpocket // Nintendo Game Boy Pocket Handheld @@ -72,7 +74,6 @@ snespal // Nintendo Super Nintendo PAL n64 // Nintendo N64 n64dd // Nintendo N64 (64DD Attachment) pokemini // Nintendo Pokemon Mini -gchinatv // Golden China TV Game Centre megaduck // Megaduck diff --git a/src/mess/video/nes.c b/src/mess/video/nes.c index a9a855bf774..956c7effe27 100644 --- a/src/mess/video/nes.c +++ b/src/mess/video/nes.c @@ -33,27 +33,43 @@ PALETTE_INIT_MEMBER(nes_state, nes) UINT32 nes_state::screen_update_nes(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { - /* render the ppu */ + // render the ppu m_ppu->render(bitmap, 0, 0, 0, 0); - /* if this is a disk system game, check for the flip-disk key */ - if (m_disk_expansion && m_cartslot && !m_cartslot->m_cart) + // if this is a disk system game, check for the flip-disk key + if (m_cartslot && + (m_cartslot->get_pcb_id() == STD_DISKSYS // first scenario = disksys in m_cartslot (= famicom) + || !m_cartslot->cart_mounted())) // second scenario = disk via fixed internal option (= fds) { // latch this input so it doesn't go at warp speed - if ((ioport("FLIPDISK")->read() & 0x01) && (!m_last_frame_flip)) + if ((m_io_disksel->read_safe(0) & 0x01) && (!m_last_frame_flip)) { + m_cartslot->disk_flip_side(); m_last_frame_flip = 1; - m_fds_current_side++; - if (m_fds_current_side > m_fds_sides) - m_fds_current_side = 0; - - if (m_fds_current_side == 0) - popmessage("No disk inserted."); - else - popmessage("Disk set to side %d", m_fds_current_side); } - if (!(ioport("FLIPDISK")->read() & 0x01)) + if (!m_io_disksel->read_safe(1) & 0x01) + m_last_frame_flip = 0; + } + return 0; +} + +// Alternative version to support "Disk flip hack" also in the Famicom Twin System (to be removed soonish!) +UINT32 nes_state::screen_update_famitwin(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + // render the ppu + m_ppu->render(bitmap, 0, 0, 0, 0); + + if (m_cartslot2 && !m_cartslot2->cart_mounted()) + { + // latch this input so it doesn't go at warp speed + if ((m_io_disksel->read_safe(0) & 0x01) && (!m_last_frame_flip)) + { + m_cartslot2->disk_flip_side(); + m_last_frame_flip = 1; + } + + if (!m_io_disksel->read_safe(1) & 0x01) m_last_frame_flip = 0; } return 0;