(MESS) famicom: converted the disk system add-on to be a cart

in the softlist. The official syntax to launch disk games is now
  mess famicom -cart disksys -flop gamename
which corresponds to inserting the RAM expansion cart with
connected the disk drive into the cartslot and the desired disk
in the disk drive (exactly like you would have done with the
real thing). In this way, you cannot mount anymore both a cart and 
a disk in the Family Computer (as in a real unit). 
Users that cannot cope with this limitation and/or with the new 
syntax can still use the famitwin driver (which offers both cart and 
disk options) or the newly added driver fds which emulates a
famicom with the expansion always inserted: in both latter cases
the old syntax
  mess famitwin -flop gamename
will launch the game, as previously. [Fabio Priuli]

(MESS) famicom: fixed disk system IRQ latch clear in Kaettekita
Mario Bros. based on investigations by FHorse. [Fabio Priuli]


Out of whatsnew: For the moment I gave up the original plan to 
also modernize the floppy drive and the disk format. If anyone 
wants to look into these, be my guest :-)
This commit is contained in:
Fabio Priuli 2014-09-11 21:01:45 +00:00
parent a7ca0bbba2
commit af7242fcb4
12 changed files with 248 additions and 388 deletions

View File

@ -79008,4 +79008,25 @@ that the real dumps might surface -->
</part>
</software>
<!-- Romless cart for the RAM expansion + Disk System drive (drive ROM is included in the drive device) -->
<software name="disksys">
<description>Family Computer Disk System (Jpn)</description>
<year>1986</year>
<publisher>Nintendo</publisher>
<info name="usage" value="This only is only supported by Famicom"/>
<part name="cart" interface="nes_cart">
<feature name="slot" value="disksys" />
<!-- This is a fake and unused PRG dataarea to avoid changing the loading routines for the moment-->
<dataarea name="prg" size="32768">
<rom value="0xff" size="32768" offset="0" loadflag="fill" />
</dataarea>
<!-- 8k VRAM on cartridge -->
<dataarea name="vram" size="8192">
</dataarea>
<!-- 32k WRAM on cartridge -->
<dataarea name="wram" size="32768">
</dataarea>
</part>
</software>
</softwarelist>

View File

@ -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

View File

@ -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

View File

@ -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__

View File

@ -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 },

View File

@ -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;

View File

@ -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<nes_cart_slot_device *>(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

View File

@ -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 )

View File

@ -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<ppu2c0x_device> m_ppu;
required_device<nesapu_device> m_sound;
optional_device<nes_cart_slot_device> m_cartslot;
optional_device<nes_cart_slot_device> m_cartslot2;
optional_device<cassette_image_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];

View File

@ -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<nes_state>();
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<nes_state>();
/* 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<cpu_device>("maincpu")->space(AS_PROGRAM);
space.install_read_handler(0x4016, 0x4016, read8_delegate(FUNC(nes_state::fc_in0_r), this));

View File

@ -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

View File

@ -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;