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;