summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/mame/drivers/famibox.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/mame/drivers/famibox.c')
-rw-r--r--trunk/src/mame/drivers/famibox.c645
1 files changed, 645 insertions, 0 deletions
diff --git a/trunk/src/mame/drivers/famibox.c b/trunk/src/mame/drivers/famibox.c
new file mode 100644
index 00000000000..6927dcb9525
--- /dev/null
+++ b/trunk/src/mame/drivers/famibox.c
@@ -0,0 +1,645 @@
+/***************************************************************************
+
+ Nintendo FamicomBox
+ Driver by Mariusz Wojcieszek
+ Thanks for Kevin Horton for hardware docs
+
+In 1986, Nintendo Co., Ltd. began distributing the FamicomBox (SSS-CDS) which
+allowed gamers to test out and play up to 15 different Famicom games which
+could be installed in the unit itself. Like it's sequel, the Super Famicom Box,
+it was found in hotels often set up to accept 100 yen coins giving you an
+adjusted amount of gametime (10 or 20 minutes - DIP selectable). Sharp also
+produced a version of the FamicomBox called FamicomStation which was more
+of a consumer (non-coin accept) unit. Besides that, the equipment and
+capabilities between the two are thought to be virtually identical - save the
+case style and cartridge/case color: (FamicomBox = Black, FamicomStation = Gray).
+
+
+
+Specific Hardware information
+-----------------------------
+The unit had 3 controllers - 2 standard NES controllers and a NES Zapper light
+gun. The cartridges are shaped and appear to be idential to NES 72-pin
+cartridges. Unfortunately, it was made to play only the games specifically
+released for it. Why?
+
+- The FamicomBox will not run mmc3 games and many other advanced mappers
+- There a special lockout chip, but the lockout chip connects to different pins on
+ a FamicomBox cartridge's connector than a regular cart
+- The lockout chips in the system and the games have to 'talk' before the system will
+ load any games into its menu.
+
+Here's a list of some of the games known to have come with the FamicomBox:
+1943; Baseball; Bomber Man; Devil World; Donkey Kong; Donkey Kong Jr.; Duck Hunt;
+Excite Bike; F1 Race; Fighting Golf; Golf; Gradius; Hogan?s Alley; Ice Climbers;
+Ice Hockey; Knight Rider; Makaimura: Ghosts ?n Goblins; McKids; Mah-Jong; Mario Bros.;
+Mike Tyson?s Punch-Out!!; Ninja Ryukenden; Operation Wolf (?); Punch-Out!!; Rock Man;
+Rygar; Senjou no Ookami; Soccer League Winner?s Cup; Super Chinese 2; Super Mario Bros;
+Tag Team Pro Wrestling; Takahashi Meijin no Boukenjima; Tennis; Twin Bee;
+Volleyball; Wild Gunman; Wrecking Crew.
+
+Here's a list of some of the games known to have come with the FamicomStation:
+1943; Baseball; Donkey Kong; Duck Hunt; F1 Race; Golf; Kame no Ongaeshi:
+Urashima Densetsu; Mah-Jong; Mario Bros.; Night Raider; Senjou no Ookami;
+Soccer League Winner?s Cup; Super Chinese 2; Super Mario Bros; Tag Team Pro Wrestling;
+Takahashi Meijin no Boukenjima; Tennis; Wild Gunman; Wrecking Crew.
+
+FamicomBox menu code maintains internal database of games (rom checksums and game names
+in ASCII). When checking game cartidges, it scans roms and tries to find matching game
+in its internal database. Additionaly, games having standard Nintendo header are accepted too.
+Current selection of games in driver is based on menu internal database.
+
+Notes/ToDo:
+- coin insertion sound is not emulated
+- coin beep (before time out) is not emulated
+- screen modulation (before time out) is not emulated
+- zapper is not emulated
+- self test fails on controller and zapper test
+***************************************************************************/
+
+#include "emu.h"
+#include "video/ppu2c0x.h"
+#include "cpu/m6502/m6502.h"
+#include "imagedev/cartslot.h"
+#include "sound/nes_apu.h"
+#include "sound/dac.h"
+#include "debugger.h"
+
+
+class famibox_state : public driver_device
+{
+public:
+ famibox_state(const machine_config &mconfig, device_type type, const char *tag)
+ : driver_device(mconfig, type, tag) { }
+
+ UINT8* m_nt_ram;
+ UINT8* m_nt_page[4];
+
+ UINT32 m_in_0;
+ UINT32 m_in_1;
+ UINT32 m_in_0_shift;
+ UINT32 m_in_1_shift;
+
+ UINT8 m_exception_mask;
+ UINT8 m_exception_cause;
+
+ emu_timer* m_attract_timer;
+ UINT8 m_attract_timer_period;
+
+ UINT32 m_coins;
+
+ emu_timer* m_gameplay_timer;
+ UINT8 m_money_reg;
+
+ DECLARE_WRITE8_MEMBER(famibox_nt_w);
+ DECLARE_READ8_MEMBER(famibox_nt_r);
+ DECLARE_WRITE8_MEMBER(sprite_dma_w);
+ DECLARE_READ8_MEMBER(famibox_IN0_r);
+ DECLARE_WRITE8_MEMBER(famibox_IN0_w);
+ DECLARE_READ8_MEMBER(famibox_IN1_r);
+ DECLARE_READ8_MEMBER(famibox_system_r);
+ DECLARE_WRITE8_MEMBER(famibox_system_w);
+ DECLARE_CUSTOM_INPUT_MEMBER(famibox_coin_r);
+ DECLARE_INPUT_CHANGED_MEMBER(famibox_keyswitch_changed);
+ DECLARE_INPUT_CHANGED_MEMBER(coin_inserted);
+};
+
+/******************************************************
+
+ PPU external bus interface
+
+*******************************************************/
+
+#if 0
+static void set_mirroring(famibox_state *state, int mirroring)
+{
+ switch(mirroring)
+ {
+ case PPU_MIRROR_LOW:
+ state->m_nt_page[0] = state->m_nt_page[1] = state->m_nt_page[2] = state->m_nt_page[3] = state->m_nt_ram;
+ break;
+ case PPU_MIRROR_HIGH:
+ state->m_nt_page[0] = state->m_nt_page[1] = state->m_nt_page[2] = state->m_nt_page[3] = state->m_nt_ram + 0x400;
+ break;
+ case PPU_MIRROR_HORZ:
+ state->m_nt_page[0] = state->m_nt_ram;
+ state->m_nt_page[1] = state->m_nt_ram;
+ state->m_nt_page[2] = state->m_nt_ram + 0x400;
+ state->m_nt_page[3] = state->m_nt_ram + 0x400;
+ break;
+ case PPU_MIRROR_VERT:
+ state->m_nt_page[0] = state->m_nt_ram;
+ state->m_nt_page[1] = state->m_nt_ram + 0x400;
+ state->m_nt_page[2] = state->m_nt_ram;
+ state->m_nt_page[3] = state->m_nt_ram + 0x400;
+ break;
+ case PPU_MIRROR_NONE:
+ default:
+ state->m_nt_page[0] = state->m_nt_ram;
+ state->m_nt_page[1] = state->m_nt_ram + 0x400;
+ state->m_nt_page[2] = state->m_nt_ram + 0x800;
+ state->m_nt_page[3] = state->m_nt_ram + 0xc00;
+ break;
+ }
+}
+#endif
+
+WRITE8_MEMBER(famibox_state::famibox_nt_w)
+{
+ int page = ((offset & 0xc00) >> 10);
+ m_nt_page[page][offset & 0x3ff] = data;
+}
+
+
+READ8_MEMBER(famibox_state::famibox_nt_r)
+{
+ int page = ((offset & 0xc00) >> 10);
+ return m_nt_page[page][offset & 0x3ff];
+}
+
+/******************************************************
+
+ NES interface
+
+*******************************************************/
+
+WRITE8_MEMBER(famibox_state::sprite_dma_w)
+{
+ ppu2c0x_device *ppu = machine().device<ppu2c0x_device>("ppu");
+ int source = (data & 7);
+ ppu->spriteram_dma(&space, source);
+}
+
+static READ8_DEVICE_HANDLER( psg_4015_r )
+{
+ return nes_psg_r(device, 0x15);
+}
+
+static WRITE8_DEVICE_HANDLER( psg_4015_w )
+{
+ nes_psg_w(device, 0x15, data);
+}
+
+static WRITE8_DEVICE_HANDLER( psg_4017_w )
+{
+ nes_psg_w(device, 0x17, data);
+}
+
+/******************************************************
+
+ Inputs
+
+*******************************************************/
+
+
+READ8_MEMBER(famibox_state::famibox_IN0_r)
+{
+ return ((m_in_0 >> m_in_0_shift++) & 0x01) | 0x40;
+}
+
+WRITE8_MEMBER(famibox_state::famibox_IN0_w)
+{
+ if (data & 0x01)
+ {
+ return;
+ }
+
+ m_in_0_shift = 0;
+ m_in_1_shift = 0;
+
+ m_in_0 = ioport("P1")->read();
+ m_in_1 = ioport("P2")->read();
+}
+
+READ8_MEMBER(famibox_state::famibox_IN1_r)
+{
+ return ((m_in_1 >> m_in_1_shift++) & 0x01) | 0x40;
+}
+
+/******************************************************
+
+ System
+
+*******************************************************/
+static void famicombox_bankswitch(running_machine &machine, UINT8 bank)
+{
+ struct
+ {
+ UINT8 bank;
+ const char* memory_region;
+ offs_t bank1_offset;
+ offs_t bank2_offset;
+ offs_t ppubank_offset;
+ } famicombox_banks[] =
+ {
+ { 0x11, "donkeykong", 0, 0, 0x4000 },
+ { 0x12, "donkeykongjr", 0, 0, 0x4000 },
+ { 0x13, "popeye", 0, 0, 0x4000 },
+ { 0x14, "eigoasobi", 0, 0, 0x4000 },
+ { 0x15, "mahjong", 0, 0, 0x4000 },
+ { 0x26, "gomokunarabe", 0, 0, 0x4000 },
+ { 0x27, "baseball", 0, 0, 0x4000 },
+ { 0x28, "empty", 0, 0, 0x4000 },
+ { 0x29, "empty", 0, 0, 0x4000 },
+ { 0x2a, "empty", 0, 0, 0x4000 },
+ { 0x3b, "empty", 0, 0, 0x4000 },
+ { 0x3c, "empty", 0, 0, 0x4000 },
+ { 0x3d, "empty", 0, 0, 0x4000 },
+ { 0x3e, "empty", 0, 0, 0x4000 },
+ { 0x3f, "empty", 0, 0, 0x4000 },
+ { 0x00, "menu", 0, 0x4000, 0x8000 },
+ };
+
+// famibox_state *state = machine.driver_data<famibox_state>();
+
+ for (int i = 0; i < sizeof(famicombox_banks)/sizeof(famicombox_banks[0]); i++ )
+ {
+ if ( bank == famicombox_banks[i].bank ||
+ famicombox_banks[i].bank == 0 )
+ {
+ machine.root_device().membank("cpubank1")->set_base(machine.root_device().memregion(famicombox_banks[i].memory_region)->base() + famicombox_banks[i].bank1_offset);
+ machine.root_device().membank("cpubank2")->set_base(machine.root_device().memregion(famicombox_banks[i].memory_region)->base() + famicombox_banks[i].bank2_offset);
+ machine.root_device().membank("ppubank1")->set_base(machine.root_device().memregion(famicombox_banks[i].memory_region)->base() + famicombox_banks[i].ppubank_offset);
+ break;
+ }
+ }
+}
+
+static void famicombox_reset(running_machine &machine)
+{
+ famicombox_bankswitch(machine, 0);
+ machine.device("maincpu")->reset();
+}
+
+static TIMER_CALLBACK(famicombox_attract_timer_callback)
+{
+ famibox_state *state = machine.driver_data<famibox_state>();
+
+ state->m_attract_timer->adjust(attotime::never, 0, attotime::never);
+ if ( BIT(state->m_exception_mask,1) )
+ {
+ state->m_exception_cause &= ~0x02;
+ famicombox_reset(machine);
+ }
+}
+
+static TIMER_CALLBACK(famicombox_gameplay_timer_callback)
+{
+ famibox_state *state = machine.driver_data<famibox_state>();
+
+ if (state->m_coins > 0)
+ state->m_coins--;
+
+ if (state->m_coins == 0)
+ {
+ state->m_gameplay_timer->adjust(attotime::never, 0, attotime::never);
+ if ( BIT(state->m_exception_mask,4) )
+ {
+ state->m_exception_cause &= ~0x10;
+ famicombox_reset(machine);
+ }
+ }
+}
+
+READ8_MEMBER(famibox_state::famibox_system_r)
+{
+ switch( offset & 0x07 )
+ {
+ case 0: /* device which caused exception */
+ {
+ UINT8 ret = m_exception_cause;
+ m_exception_cause = 0xff;
+ return ret;
+ }
+ case 2:
+ return ioport("DSW")->read();
+ case 3:
+ return ioport("KEYSWITCH")->read();
+ case 7:
+ return 0x02;
+ default:
+ logerror("%s: Unhandled famibox_system_r(%x)\n", machine().describe_context(), offset );
+ return 0;
+ }
+}
+
+WRITE8_MEMBER(famibox_state::famibox_system_w)
+{
+ switch( offset & 0x07 )
+ {
+ case 0:
+ logerror("%s: Interrupt enable\n", machine().describe_context());
+ logerror("6.82Hz interrupt source (0 = enable): %d\n", BIT(data,0));
+ logerror("8 bit timer expiration @ 5003W (1 = enable): %d\n", BIT(data,1));
+ logerror("controller reads (1 = enable): %d\n", BIT(data,2));
+ logerror("keyswitch rotation (1 = enable): %d\n", BIT(data,3));
+ logerror("money insertion (1 = enable): %d\n", BIT(data,4));
+ logerror("reset button (1 = enable): %d\n", BIT(data,5));
+ logerror("\"CATV connector\" pin 4 detection (1 = enable): %d\n", BIT(data,7));
+ m_exception_mask = data;
+ if ( BIT(m_exception_mask,1) && ( m_attract_timer_period != 0 ) )
+ {
+ if (m_attract_timer->start() != attotime::never)
+ {
+ m_attract_timer->adjust(attotime::from_seconds((INT32)((double)1.0/6.8274*m_attract_timer_period)), 0, attotime::never);
+ }
+ }
+ break;
+ case 1:
+ m_money_reg = data;
+ logerror("%s: Money handling register: %02x\n", machine().describe_context(), data);
+ break;
+ case 2:
+ logerror("%s: LED & memory protect register: %02x\n", machine().describe_context(), data);
+ break;
+ case 3:
+ logerror("%s: 8 bit down counter, for attract mode timing: %02x\n", machine().describe_context(), data);
+ m_attract_timer_period = data;
+ if ( BIT(m_exception_mask,1) && ( data != 0 ) )
+ {
+ m_attract_timer->adjust(attotime::from_hz(6.8274/m_attract_timer_period), 0, attotime::never);
+ }
+ break;
+ case 4:
+ logerror("%s: bankswitch %x\n", machine().describe_context(), data );
+ famicombox_bankswitch(machine(), data & 0x3f);
+ break;
+ default:
+ logerror("%s: Unhandled famibox_system_w(%x,%02x)\n", machine().describe_context(), offset, data );
+ }
+}
+
+/******************************************************
+
+ Memory map
+
+*******************************************************/
+
+
+static ADDRESS_MAP_START( famibox_map, AS_PROGRAM, 8, famibox_state )
+ AM_RANGE(0x0000, 0x1fff) AM_RAM
+ AM_RANGE(0x2000, 0x3fff) AM_DEVREADWRITE("ppu", ppu2c0x_device, read, write)
+ AM_RANGE(0x4000, 0x4013) AM_DEVREADWRITE_LEGACY("nes", nes_psg_r, nes_psg_w) /* PSG primary registers */
+ AM_RANGE(0x4014, 0x4014) AM_WRITE(sprite_dma_w)
+ AM_RANGE(0x4015, 0x4015) AM_DEVREADWRITE_LEGACY("nes", psg_4015_r, psg_4015_w) /* PSG status / first control register */
+ AM_RANGE(0x4016, 0x4016) AM_READWRITE(famibox_IN0_r, famibox_IN0_w) /* IN0 - input port 1 */
+ AM_RANGE(0x4017, 0x4017) AM_READ(famibox_IN1_r) AM_DEVWRITE_LEGACY("nes", psg_4017_w) /* IN1 - input port 2 / PSG second control register */
+ AM_RANGE(0x5000, 0x5fff) AM_READWRITE(famibox_system_r, famibox_system_w)
+ AM_RANGE(0x6000, 0x7fff) AM_RAM
+ AM_RANGE(0x8000, 0xbfff) AM_ROMBANK("cpubank1")
+ AM_RANGE(0xc000, 0xffff) AM_ROMBANK("cpubank2")
+ADDRESS_MAP_END
+
+/******************************************************
+
+ Inputs
+
+*******************************************************/
+
+INPUT_CHANGED_MEMBER(famibox_state::famibox_keyswitch_changed)
+{
+
+ if ( BIT(m_exception_mask, 3) )
+ {
+ m_exception_cause &= ~0x08;
+ famicombox_reset(machine());
+ }
+}
+
+INPUT_CHANGED_MEMBER(famibox_state::coin_inserted)
+{
+
+ if ( newval )
+ {
+ m_coins++;
+ if (m_attract_timer->start() != attotime::never)
+ {
+ m_gameplay_timer->adjust(attotime::from_seconds(60*(m_money_reg == 0x22 ? 20 : 10)), 0, attotime::never);
+ }
+
+ if ( BIT(m_exception_mask,4) && (m_coins == 1) )
+ {
+ m_exception_cause &= ~0x10;
+ famicombox_reset(machine());
+ }
+ }
+}
+
+CUSTOM_INPUT_MEMBER(famibox_state::famibox_coin_r)
+{
+ return m_coins > 0;
+}
+
+static INPUT_PORTS_START( famibox )
+ PORT_START("P1")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(1)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(1)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(1) /* Select */
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START1 ) PORT_PLAYER(1)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(1)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1)
+
+ PORT_START("P2")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(2)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(2)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(2) /* Select */
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START2 ) PORT_PLAYER(2)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(2)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
+
+ PORT_START("DSW")
+ PORT_DIPNAME( 0x01, 0x00, "Self Test" )
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x01, DEF_STR( On ) )
+ PORT_DIPNAME( 0x02, 0x00, "Coin timeout period" )
+ PORT_DIPSETTING( 0x00, "10 min" )
+ PORT_DIPSETTING( 0x02, "20 min" )
+ PORT_DIPNAME( 0x04, 0x00, DEF_STR( Unused ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x04, DEF_STR( On ) )
+ PORT_DIPNAME( 0x08, 0x00, "Famicombox menu time" )
+ PORT_DIPSETTING( 0x00, "7 sec" )
+ PORT_DIPSETTING( 0x08, "12 sec" )
+ PORT_DIPNAME( 0x30, 0x00, "Attract time" )
+ PORT_DIPSETTING( 0x00, "12 sec" )
+ PORT_DIPSETTING( 0x10, "23 sec" )
+ PORT_DIPSETTING( 0x20, "17 sec" )
+ PORT_DIPSETTING( 0x30, "7 sec" )
+ PORT_DIPNAME( 0xc0, 0x80, "Operational mode" )
+ PORT_DIPSETTING( 0x00, "KEY MODE" )
+ PORT_DIPSETTING( 0x40, "CATV MODE" )
+ PORT_DIPSETTING( 0x80, "COIN MODE" )
+ PORT_DIPSETTING( 0xc0, "FREEPLAY" )
+
+
+ PORT_START("KEYSWITCH")
+ PORT_DIPNAME( 0x3f, 0x01, "Key switch" ) PORT_CHANGED_MEMBER(DEVICE_SELF, famibox_state,famibox_keyswitch_changed, 0)
+ PORT_DIPSETTING( 0x01, "Key position 1" )
+ PORT_DIPSETTING( 0x02, "Key position 2" )
+ PORT_DIPSETTING( 0x04, "Key position 3" )
+ PORT_DIPSETTING( 0x08, "Key position 4" )
+ PORT_DIPSETTING( 0x10, "Key position 5" )
+ PORT_DIPSETTING( 0x20, "Key position 6" )
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, famibox_state,famibox_coin_r, NULL)
+
+ PORT_START("COIN")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, famibox_state,coin_inserted, 0)
+
+INPUT_PORTS_END
+
+/******************************************************
+
+ PPU/Video interface
+
+*******************************************************/
+
+static const nes_interface famibox_interface_1 =
+{
+ "maincpu"
+};
+
+static PALETTE_INIT( famibox )
+{
+ ppu2c0x_device *ppu = machine.device<ppu2c0x_device>("ppu");
+ ppu->init_palette(machine, 0);
+}
+
+static void ppu_irq( device_t *device, int *ppu_regs )
+{
+ cputag_set_input_line(device->machine(), "maincpu", INPUT_LINE_NMI, PULSE_LINE);
+}
+
+/* our ppu interface */
+static const ppu2c0x_interface ppu_interface =
+{
+ "maincpu",
+ "screen",
+ 0, /* gfxlayout num */
+ 0, /* color base */
+ PPU_MIRROR_NONE, /* mirroring */
+ ppu_irq /* irq */
+};
+
+static VIDEO_START( famibox )
+{
+}
+
+static SCREEN_UPDATE_IND16( famibox )
+{
+ /* render the ppu */
+ ppu2c0x_device *ppu = screen.machine().device<ppu2c0x_device>("ppu");
+ ppu->render(bitmap, 0, 0, 0, 0);
+ return 0;
+}
+
+static GFXDECODE_START( famibox )
+ /* none, the ppu generates one */
+GFXDECODE_END
+
+static MACHINE_RESET( famibox )
+{
+ famicombox_bankswitch(machine, 0);
+}
+
+static MACHINE_START( famibox )
+{
+ famibox_state *state = machine.driver_data<famibox_state>();
+ state->m_nt_ram = auto_alloc_array(machine, UINT8, 0x1000);
+ state->m_nt_page[0] = state->m_nt_ram;
+ state->m_nt_page[1] = state->m_nt_ram + 0x400;
+ state->m_nt_page[2] = state->m_nt_ram + 0x800;
+ state->m_nt_page[3] = state->m_nt_ram + 0xc00;
+
+ machine.device("ppu")->memory().space(AS_PROGRAM)->install_readwrite_handler(0x2000, 0x3eff, read8_delegate(FUNC(famibox_state::famibox_nt_r), state), write8_delegate(FUNC(famibox_state::famibox_nt_w), state));
+ machine.device("ppu")->memory().space(AS_PROGRAM)->install_read_bank(0x0000, 0x1fff, "ppubank1");
+
+ famicombox_bankswitch(machine, 0);
+
+
+ state->m_attract_timer = machine.scheduler().timer_alloc(FUNC(famicombox_attract_timer_callback));
+ state->m_gameplay_timer = machine.scheduler().timer_alloc(FUNC(famicombox_gameplay_timer_callback));
+ state->m_exception_cause = 0xff;
+ state->m_exception_mask = 0;
+ state->m_attract_timer_period = 0;
+ state->m_money_reg = 0;
+ state->m_coins = 0;
+}
+
+static MACHINE_CONFIG_START( famibox, famibox_state )
+ /* basic machine hardware */
+ MCFG_CPU_ADD("maincpu", N2A03, N2A03_DEFAULTCLOCK)
+ MCFG_CPU_PROGRAM_MAP(famibox_map)
+
+ MCFG_MACHINE_START( famibox )
+ MCFG_MACHINE_RESET( famibox )
+
+ /* video hardware */
+ MCFG_SCREEN_ADD("screen", RASTER)
+ MCFG_SCREEN_REFRESH_RATE(60)
+ MCFG_SCREEN_SIZE(32*8, 262)
+ MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 0*8, 30*8-1)
+ MCFG_SCREEN_UPDATE_STATIC(famibox)
+
+ MCFG_GFXDECODE(famibox)
+ MCFG_PALETTE_LENGTH(8*4*16)
+
+ MCFG_PALETTE_INIT(famibox)
+ MCFG_VIDEO_START(famibox)
+
+ MCFG_PPU2C04_ADD("ppu", ppu_interface)
+
+ /* sound hardware */
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+
+ MCFG_SOUND_ADD("nes", NES, N2A03_DEFAULTCLOCK)
+ MCFG_SOUND_CONFIG(famibox_interface_1)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+
+ MCFG_SOUND_ADD("dac", DAC, 0)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+MACHINE_CONFIG_END
+
+
+ROM_START(famibox)
+ ROM_REGION(0xa000, "menu", 0)
+ ROM_LOAD("sss_menu.prg", 0x0000, 0x8000, CRC(da1eb8d2) SHA1(943e3b0edfbf9bd3ee87dc5f298621b9ddc98db8))
+ ROM_LOAD("sss_menu.chr", 0x8000, 0x2000, CRC(a43d4435) SHA1(ee56b4d2110aff394bf2c8cd3414ca175ace01bd))
+
+ ROM_REGION(0x6000, "donkeykong", 0)
+ ROM_LOAD("0.prg", 0x0000, 0x4000, CRC(06d1a012) SHA1(a6f92ae0a991c532e6377db2b3ab7f5c13d27675) )
+ ROM_LOAD("0.chr", 0x4000, 0x2000, CRC(a21d7c2e) SHA1(97c16cd6b1f3656428b682a23e6e4248c1ca3607) )
+
+ ROM_REGION(0x6000, "donkeykongjr", 0)
+ ROM_LOAD("hvc-jr-1 prg", 0x0000, 0x4000, CRC(cf6c88b6) SHA1(cefc276e7601d14c6a20e545f334281b7a9fe8db) )
+ ROM_LOAD("hvc-jr-0 chr", 0x4000, 0x2000, CRC(852778ab) SHA1(307f2245cce164491012f75897eb984af0c3f456) )
+
+ ROM_REGION(0x6000, "popeye", 0)
+ ROM_LOAD("hvc-pp-1 prg", 0x0000, 0x4000, CRC(0fa63a45) SHA1(50c594a6d8dcbeee2d83bca8c54c42cf57093aba) )
+ ROM_LOAD("hvc-pp-0 chr", 0x4000, 0x2000, CRC(a5fd8d98) SHA1(09d229404babb6c89b417ac541bab80fb06d2ba9) )
+
+ ROM_REGION(0x6000, "eigoasobi", 0)
+ ROM_LOAD("hvc-en-0 prg", 0x0000, 0x4000, CRC(2dbfa36a) SHA1(0f4301d78d3dfa163239e7b7b7c4dff8a7e21bac) )
+ ROM_LOAD("hvc-en-0 chr", 0x4000, 0x2000, CRC(fccc0f36) SHA1(3566709c3c74960ce2ee1e60a85d026e70d7fd2c) )
+
+ ROM_REGION(0x6000, "mahjong", 0)
+ ROM_LOAD("mahjong.prg", 0x0000, 0x4000, CRC(f86d8d8a) SHA1(2904137a030ae2370a8cd3e068078a1d59a4f229) )
+ ROM_LOAD("mahjong.chr", 0x4000, 0x2000, CRC(6bb45576) SHA1(5974787496dfa27a4b7fe6023473fae930ea41dc) )
+
+ ROM_REGION(0x6000, "gomokunarabe", 0)
+ ROM_LOAD("hvc-go-0 prg", 0x0000, 0x4000, CRC(5603f579) SHA1(f2b007e3b13a777f9f88ff58f87ead6ae8f26327) )
+ ROM_LOAD("hvc-go-0 chr", 0x4000, 0x2000, CRC(97ea7144) SHA1(47d354c654285275d0a9420cc6eb3564f0453eb0) )
+
+ ROM_REGION(0x6000, "baseball", 0)
+ ROM_LOAD("hvc-ba-0 prg", 0x0000, 0x4000, CRC(d18a3dde) SHA1(91f7d3e4c9d18c1969ca1fffdc811b763508a0a2) )
+ ROM_LOAD("hvc-ba-0 chr", 0x4000, 0x2000, CRC(c27eef20) SHA1(d5bd643b3ba98846e520b4d3f38aae45a29cf250) )
+
+ ROM_REGION(0x6000, "empty", ROMREGION_ERASEFF)
+
+ROM_END
+
+GAME( 1986, famibox, 0, famibox, famibox, 0, ROT0, "Nintendo", "FamicomBox", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND)
+