diff --git a/.gitattributes b/.gitattributes
index e4df589bace..a3015e04339 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -476,6 +476,15 @@ src/emu/bus/a2bus/laser128.c svneol=native#text/plain
src/emu/bus/a2bus/laser128.h svneol=native#text/plain
src/emu/bus/a2bus/timemasterho.c svneol=native#text/plain
src/emu/bus/a2bus/timemasterho.h svneol=native#text/plain
+src/emu/bus/a7800/a78_carts.h svneol=native#text/plain
+src/emu/bus/a7800/a78_slot.c svneol=native#text/plain
+src/emu/bus/a7800/a78_slot.h svneol=native#text/plain
+src/emu/bus/a7800/hiscore.c svneol=native#text/plain
+src/emu/bus/a7800/hiscore.h svneol=native#text/plain
+src/emu/bus/a7800/rom.c svneol=native#text/plain
+src/emu/bus/a7800/rom.h svneol=native#text/plain
+src/emu/bus/a7800/xboard.c svneol=native#text/plain
+src/emu/bus/a7800/xboard.h svneol=native#text/plain
src/emu/bus/abcbus/abc890.c svneol=native#text/plain
src/emu/bus/abcbus/abc890.h svneol=native#text/plain
src/emu/bus/abcbus/abcbus.c svneol=native#text/plain
@@ -8844,7 +8853,6 @@ src/mess/layout/z80netb.lay svneol=native#text/xml
src/mess/layout/z80netf.lay svneol=native#text/xml
src/mess/machine/6883sam.c svneol=native#text/plain
src/mess/machine/6883sam.h svneol=native#text/plain
-src/mess/machine/a7800.c svneol=native#text/plain
src/mess/machine/abc1600mac.c svneol=native#text/plain
src/mess/machine/abc1600mac.h svneol=native#text/plain
src/mess/machine/abc80kb.c svneol=native#text/plain
diff --git a/hash/a7800.xml b/hash/a7800.xml
index 3fb60d20272..641934c513f 100644
--- a/hash/a7800.xml
+++ b/hash/a7800.xml
@@ -194,18 +194,20 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
-
+
7800 Pro System Diagnostic Test (v1.0)
198?
Atari
+
@@ -220,6 +222,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -234,6 +237,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -248,6 +252,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -263,6 +268,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -280,6 +286,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -294,6 +301,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -308,6 +316,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -322,6 +331,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -336,6 +346,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -370,6 +381,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -385,6 +397,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -399,6 +412,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -413,6 +427,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -427,6 +442,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -441,6 +457,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -455,6 +472,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -469,6 +487,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -483,6 +502,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -497,6 +517,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -511,6 +532,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -525,6 +547,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -539,6 +562,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -553,6 +577,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -567,6 +592,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -582,6 +608,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -597,6 +624,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -611,6 +639,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -629,6 +658,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -643,6 +673,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -657,6 +688,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -674,6 +706,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -688,6 +721,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -702,6 +736,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -716,6 +751,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -730,6 +766,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -744,6 +781,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -758,6 +796,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -772,6 +811,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -786,6 +826,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -800,6 +841,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -814,6 +856,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -828,6 +871,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -842,6 +886,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -856,6 +901,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -870,6 +916,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -884,6 +931,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -898,6 +946,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -912,6 +961,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -926,6 +976,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -940,6 +991,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -954,6 +1006,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -968,6 +1021,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -982,6 +1036,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -996,6 +1051,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -1011,6 +1067,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -1025,6 +1082,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -1038,6 +1096,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -1056,6 +1115,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -1070,24 +1130,13 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
-
- High Score Cartridge
- 198?
- Atari
-
-
-
-
-
-
-
-
Ikari Warriors (NTSC)
1990
@@ -1096,6 +1145,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -1110,6 +1160,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -1124,6 +1175,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -1138,6 +1190,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -1152,6 +1205,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -1166,6 +1220,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -1179,6 +1234,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -1193,6 +1249,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -1207,6 +1264,7 @@ type of rom dumps. Effort will be made at a later date to split them and docume
+
@@ -1228,6 +1286,7 @@ the buttons not work in emulators.
+
@@ -1242,6 +1301,7 @@ the buttons not work in emulators.
+
@@ -1256,6 +1316,7 @@ the buttons not work in emulators.
+
@@ -1270,6 +1331,7 @@ the buttons not work in emulators.
+
@@ -1284,6 +1346,7 @@ the buttons not work in emulators.
+
@@ -1298,6 +1361,7 @@ the buttons not work in emulators.
+
@@ -1312,6 +1376,7 @@ the buttons not work in emulators.
+
@@ -1326,6 +1391,7 @@ the buttons not work in emulators.
+
@@ -1340,6 +1406,7 @@ the buttons not work in emulators.
+
@@ -1354,6 +1421,7 @@ the buttons not work in emulators.
+
@@ -1368,6 +1436,7 @@ the buttons not work in emulators.
+
@@ -1412,6 +1481,7 @@ the buttons not work in emulators.
+
@@ -1426,6 +1496,7 @@ the buttons not work in emulators.
+
@@ -1440,6 +1511,7 @@ the buttons not work in emulators.
+
@@ -1463,6 +1535,7 @@ almost nothing like the prototype.
+
@@ -1477,6 +1550,7 @@ almost nothing like the prototype.
+
@@ -1490,6 +1564,7 @@ almost nothing like the prototype.
+
@@ -1504,6 +1579,7 @@ almost nothing like the prototype.
+
@@ -1518,6 +1594,7 @@ almost nothing like the prototype.
+
@@ -1532,6 +1609,7 @@ almost nothing like the prototype.
+
@@ -1546,6 +1624,7 @@ almost nothing like the prototype.
+
@@ -1561,6 +1640,7 @@ almost nothing like the prototype.
+
@@ -1576,6 +1656,7 @@ almost nothing like the prototype.
+
@@ -1590,6 +1671,7 @@ almost nothing like the prototype.
+
@@ -1603,6 +1685,7 @@ almost nothing like the prototype.
+
@@ -1616,6 +1699,7 @@ almost nothing like the prototype.
+
@@ -1629,6 +1713,7 @@ almost nothing like the prototype.
+
@@ -1642,6 +1727,7 @@ almost nothing like the prototype.
+
@@ -1655,6 +1741,7 @@ almost nothing like the prototype.
+
@@ -1668,6 +1755,7 @@ almost nothing like the prototype.
+
@@ -1681,6 +1769,7 @@ almost nothing like the prototype.
+
@@ -1695,6 +1784,7 @@ almost nothing like the prototype.
+
@@ -1709,6 +1799,7 @@ almost nothing like the prototype.
+
@@ -1721,6 +1812,7 @@ almost nothing like the prototype.
Tynesoft
+
@@ -1735,6 +1827,7 @@ almost nothing like the prototype.
+
@@ -1749,6 +1842,7 @@ almost nothing like the prototype.
+
@@ -1763,6 +1857,7 @@ almost nothing like the prototype.
+
@@ -1777,6 +1872,7 @@ almost nothing like the prototype.
+
@@ -1792,6 +1888,7 @@ almost nothing like the prototype.
+
@@ -1806,6 +1903,7 @@ almost nothing like the prototype.
+
@@ -1820,6 +1918,7 @@ almost nothing like the prototype.
+
@@ -1833,6 +1932,7 @@ almost nothing like the prototype.
+
@@ -1847,6 +1947,7 @@ almost nothing like the prototype.
+
@@ -1861,6 +1962,7 @@ almost nothing like the prototype.
+
@@ -1903,6 +2005,7 @@ almost nothing like the prototype.
Tynesoft
+
@@ -1915,6 +2018,7 @@ almost nothing like the prototype.
Atari Interactive
+
@@ -1928,6 +2032,7 @@ almost nothing like the prototype.
+
@@ -1941,6 +2046,7 @@ almost nothing like the prototype.
+
@@ -1954,6 +2060,7 @@ almost nothing like the prototype.
+
@@ -1967,6 +2074,7 @@ almost nothing like the prototype.
+
@@ -1980,6 +2088,7 @@ almost nothing like the prototype.
+
@@ -1994,6 +2103,7 @@ almost nothing like the prototype.
+
@@ -2008,6 +2118,7 @@ almost nothing like the prototype.
+
@@ -2022,6 +2133,7 @@ almost nothing like the prototype.
+
@@ -2036,6 +2148,7 @@ almost nothing like the prototype.
+
@@ -2050,6 +2163,7 @@ almost nothing like the prototype.
+
@@ -2064,6 +2178,7 @@ almost nothing like the prototype.
+
@@ -2078,6 +2193,7 @@ almost nothing like the prototype.
+
@@ -2092,6 +2208,7 @@ almost nothing like the prototype.
+
@@ -2106,6 +2223,7 @@ almost nothing like the prototype.
+
@@ -2120,6 +2238,7 @@ almost nothing like the prototype.
+
@@ -2133,6 +2252,7 @@ almost nothing like the prototype.
+
@@ -2147,6 +2267,7 @@ almost nothing like the prototype.
+
@@ -2161,6 +2282,7 @@ almost nothing like the prototype.
+
@@ -2174,6 +2296,7 @@ almost nothing like the prototype.
+
@@ -2188,6 +2311,7 @@ almost nothing like the prototype.
+
@@ -2202,6 +2326,7 @@ almost nothing like the prototype.
+
@@ -2216,6 +2341,7 @@ almost nothing like the prototype.
+
@@ -2230,6 +2356,7 @@ almost nothing like the prototype.
+
@@ -2244,6 +2371,7 @@ almost nothing like the prototype.
+
@@ -2258,12 +2386,54 @@ almost nothing like the prototype.
+
+
+
+
+ High Score Cartridge
+ 198?
+ Atari
+
+
+
+
+
+
+
+
+
+
+
+ XBoarD Expansion
+ 2005
+ <homebrew>
+
+
+
+
+
+
+
+
+
+
+ XM Expansion Module
+ 2015?
+ <homebrew>
+
+
+
+
+
+
+
+
@@ -2272,10 +2442,11 @@ almost nothing like the prototype.
Donkey Kong (homebrew, XM enhanced, HSC support) (Demo)
2012
- <homebrew>
+ <homebrew>
+
@@ -2285,10 +2456,11 @@ almost nothing like the prototype.
Donkey Kong (homebrew, XM enhanced, HSC support) (Demo) (NTSC)
2012
- <homebrew>
+ <homebrew>
+
@@ -2298,10 +2470,11 @@ almost nothing like the prototype.
Donkey Kong (homebrew, XM enhanced) (Demo)
2012
- <homebrew>
+ <homebrew>
+
@@ -2311,10 +2484,11 @@ almost nothing like the prototype.
Donkey Kong (homebrew, XM enhanced) (Demo) (NTSC)
2012
- <homebrew>
+ <homebrew>
+
diff --git a/src/emu/bus/a7800/a78_carts.h b/src/emu/bus/a7800/a78_carts.h
new file mode 100644
index 00000000000..fc463d76967
--- /dev/null
+++ b/src/emu/bus/a7800/a78_carts.h
@@ -0,0 +1,32 @@
+#ifndef __A78_CARTS_H
+#define __A78_CARTS_H
+
+
+#include "emu.h"
+
+#include "rom.h"
+#include "xboard.h"
+#include "hiscore.h"
+
+static SLOT_INTERFACE_START(a7800_cart)
+ SLOT_INTERFACE_INTERNAL("a78_rom", A78_ROM)
+ SLOT_INTERFACE_INTERNAL("a78_pokey", A78_ROM_POKEY)
+ SLOT_INTERFACE_INTERNAL("a78_sg", A78_ROM_SG)
+ SLOT_INTERFACE_INTERNAL("a78_sg_pokey", A78_ROM_SG_POKEY)
+ SLOT_INTERFACE_INTERNAL("a78_sg_ram", A78_ROM_SG_RAM)
+ // not sure which dev cart support banked ram, nor whether there shall be a 9banks or a non-sg version of this...
+ SLOT_INTERFACE_INTERNAL("a78_bankram", A78_ROM_BANKRAM)
+ SLOT_INTERFACE_INTERNAL("a78_sg9", A78_ROM_SG_9BANKS)
+ SLOT_INTERFACE_INTERNAL("a78_xmc", A78_ROM_XM) // carts compatible with the expansions below (basically a 9Banks+POKEY)
+ SLOT_INTERFACE_INTERNAL("a78_abs", A78_ROM_ABSOLUTE)
+ SLOT_INTERFACE_INTERNAL("a78_act", A78_ROM_ACTIVISION)
+ SLOT_INTERFACE_INTERNAL("a78_hsc", A78_HISCORE)
+ SLOT_INTERFACE_INTERNAL("a78_xboard", A78_XBOARD) // the actual XBoarD expansion (as passthru)
+ SLOT_INTERFACE_INTERNAL("a78_xm", A78_XM) // the actual XM expansion (as passthru)
+SLOT_INTERFACE_END
+
+
+// supported devices
+SLOT_INTERFACE_EXTERN(a78_cart);
+
+#endif
diff --git a/src/emu/bus/a7800/a78_slot.c b/src/emu/bus/a7800/a78_slot.c
new file mode 100644
index 00000000000..23429ef66a2
--- /dev/null
+++ b/src/emu/bus/a7800/a78_slot.c
@@ -0,0 +1,514 @@
+/***********************************************************************************************************
+
+
+ Atari 7800 cart emulation
+ (through slot devices)
+
+ Emulation of the cartslot for Atari 7800
+
+ Quoting "ATARI 7800 BANKSWITCHING GUIDE" (by Eckhard Stolberg):
+ 7800 games can use the memory from $0400 to $047f, from $0500
+ to $17ff and from $2800 to $ffff, but only the High-Score cart
+ uses anything below $4000. It has 4KB of ROM at $3000-$3fff
+ and 2KB of battery-backed RAM at $1000-$17ff.
+
+ Accordingly, we use the following handlers:
+ - read_04xx/write_04xx for accesses in the $0400 to $047f range
+ - read_10xx/write_10xx for accesses in the $1000 to $17ff range
+ - read_30xx/write_30xx for accesses in the $3000 to $3fff range
+ - read_40xx/write_40xx for accesses in the $4000 to $ffff range
+ even if not all carts use all of them (in particular no cart type
+ seems to use access to the ranges $0500 to $0fff and $2800 to $2fff)
+
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "a78_slot.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type A78_CART_SLOT = &device_creator;
+
+
+//-------------------------------------------------
+// device_vcs_cart_interface - constructor
+//-------------------------------------------------
+
+device_a78_cart_interface::device_a78_cart_interface (const machine_config &mconfig, device_t &device)
+ : device_slot_card_interface(mconfig, device)
+{
+}
+
+
+//-------------------------------------------------
+// ~device_a78_cart_interface - destructor
+//-------------------------------------------------
+
+device_a78_cart_interface::~device_a78_cart_interface ()
+{
+}
+
+//-------------------------------------------------
+// rom_alloc - alloc the space for the cart
+//-------------------------------------------------
+
+void device_a78_cart_interface::rom_alloc(UINT32 size)
+{
+ if (m_rom == NULL)
+ {
+ // allocate rom
+ m_rom.resize(size);
+
+ // setup other helpers
+ if ((size / 0x4000) & 1) // compensate for SuperGame carts with 9 x 16K banks (to my knowledge no other cart has m_bank_mask != power of 2)
+ m_bank_mask = (size / 0x4000) - 2;
+ else
+ m_bank_mask = (size / 0x4000) - 1;
+
+ // the rom is mapped to the top of the memory area
+ // so we store the starting point of data to simplify
+ // the access handling
+ m_base_rom = 0x10000 - size;
+ }
+}
+
+//-------------------------------------------------
+// ram_alloc - alloc the space for the on-cart RAM
+//-------------------------------------------------
+
+void device_a78_cart_interface::ram_alloc(UINT32 size)
+{
+ if (m_ram == NULL)
+ {
+ m_ram.resize(size);
+ device().save_item(NAME(m_ram));
+ }
+}
+
+
+//-------------------------------------------------
+// ram_alloc - alloc the space for the on-cart RAM
+//-------------------------------------------------
+
+void device_a78_cart_interface::nvram_alloc(UINT32 size)
+{
+ if (m_nvram == NULL)
+ {
+ m_nvram.resize(size);
+ device().save_item(NAME(m_nvram));
+ }
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// a78_cart_slot_device - constructor
+//-------------------------------------------------
+a78_cart_slot_device::a78_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, A78_CART_SLOT, "Atari 7800 Cartridge Slot", tag, owner, clock, "a78_cart_slot", __FILE__),
+ device_image_interface(mconfig, *this),
+ device_slot_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// a78_cart_slot_device - destructor
+//-------------------------------------------------
+
+a78_cart_slot_device::~a78_cart_slot_device()
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void a78_cart_slot_device::device_start()
+{
+ m_cart = dynamic_cast(get_card_device());
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void a78_cart_slot_device::device_config_complete()
+{
+ // set brief and instance name
+ update_names();
+}
+
+
+
+/*-------------------------------------------------
+ call load
+ -------------------------------------------------*/
+
+//-------------------------------------------------
+// A78 PCBs
+//-------------------------------------------------
+
+struct a78_slot
+{
+ int pcb_id;
+ const char *slot_option;
+};
+
+// Here, we take the feature attribute from .xml (i.e. the PCB name) and we assign a unique ID to it
+static const a78_slot slot_list[] =
+{
+ { A78_TYPE0, "a78_rom" },
+ { A78_TYPE1, "a78_pokey" },
+ { A78_TYPE2, "a78_sg" },
+ { A78_TYPE3, "a78_sg_pokey" },
+ { A78_TYPE6, "a78_sg_ram" },
+ { A78_TYPEA, "a78_sg9" },
+ { A78_TYPEB, "a78_xmc" },
+ { A78_ABSOLUTE, "a78_abs" },
+ { A78_ACTIVISION, "a78_act" },
+ { A78_HSC, "a78_hsc" },
+ { A78_BANKRAM, "a78_bankram" },
+ { A78_XB_BOARD, "a78_xboard" },
+ { A78_XM_BOARD, "a78_xm" },
+};
+
+static int a78_get_pcb_id(const char *slot)
+{
+ for (int i = 0; i < ARRAY_LENGTH(slot_list); i++)
+ {
+ if (!core_stricmp(slot_list[i].slot_option, slot))
+ return slot_list[i].pcb_id;
+ }
+
+ return 0;
+}
+
+static const char *a78_get_slot(int type)
+{
+ for (int i = 0; i < ARRAY_LENGTH(slot_list); i++)
+ {
+ if (slot_list[i].pcb_id == type)
+ return slot_list[i].slot_option;
+ }
+
+ return "a78_rom";
+}
+
+bool a78_cart_slot_device::call_load()
+{
+ UINT8 *ROM;
+ UINT32 len;
+
+ if (software_entry() != NULL)
+ {
+ const char *pcb_name;
+ len = get_software_region_length("rom");
+
+ m_cart->rom_alloc(len);
+ ROM = m_cart->get_rom_base();
+ memcpy(ROM, get_software_region("rom"), len);
+
+ if ((pcb_name = get_feature("slot")) != NULL)
+ m_type = a78_get_pcb_id(pcb_name);
+ else
+ m_type = A78_TYPE0;
+ }
+ else
+ {
+ // Load and check the header
+ char head[128];
+ fread(head, 128);
+
+ if (verify_header((char *)head) == IMAGE_VERIFY_FAIL)
+ return IMAGE_INIT_FAIL;
+
+ len = (head[49] << 24) |(head[50] << 16) |(head[51] << 8) | head[52];
+ if (len + 128 > length())
+ {
+ logerror("Invalid length in the header. The game might be corrupted.\n");
+ len = length() - 128;
+ }
+
+ switch ((head[53] << 8) | head[54])
+ {
+ case 0x0000:
+ m_type = A78_TYPE0;
+ break;
+ case 0x0001:
+ m_type = A78_TYPE1;
+ break;
+ case 0x0002:
+ m_type = A78_TYPE2;
+ break;
+ case 0x0003:
+ m_type = A78_TYPE3;
+ break;
+ case 0x0006:
+ m_type = A78_TYPE6;
+ break;
+ case 0x000a:
+ m_type = A78_TYPEA;
+ break;
+ case 0x000b:
+ m_type = A78_TYPEB;
+ break;
+ case 0x0020:
+ m_type = A78_BANKRAM;
+ break;
+ case 0x0100:
+ m_type = A78_ABSOLUTE;
+ break;
+ case 0x0200:
+ m_type = A78_ACTIVISION;
+ break;
+ }
+ logerror("Cart type: %x\n", m_type);
+
+ // This field is currently only used for logging
+ m_stick_type = head[55];
+
+ m_cart->rom_alloc(len);
+ ROM = m_cart->get_rom_base();
+ fread(ROM, len);
+ }
+
+ //printf("Type: %s\n", a78_get_slot(m_type));
+
+ if (m_type == A78_TYPE6)
+ m_cart->ram_alloc(0x4000);
+ if (m_type == A78_BANKRAM)
+ m_cart->ram_alloc(0x8000);
+ if (m_type == A78_XB_BOARD || m_type == A78_XM_BOARD)
+ m_cart->ram_alloc(0x20000);
+ if (m_type == A78_HSC || m_type == A78_XM_BOARD)
+ {
+ m_cart->nvram_alloc(0x800);
+ battery_load(m_cart->get_nvram_base(), 0x800, 0xff);
+ }
+
+ return IMAGE_INIT_PASS;
+}
+
+
+void a78_partialhash(hash_collection &dest, const unsigned char *data,
+ unsigned long length, const char *functions)
+{
+ if (length <= 128)
+ return;
+ dest.compute(&data[128], length - 128, functions);
+}
+
+
+/*-------------------------------------------------
+ call_unload
+ -------------------------------------------------*/
+
+void a78_cart_slot_device::call_unload()
+{
+ if (m_cart && m_cart->get_nvram_size())
+ battery_save(m_cart->get_nvram_base(), 0x800);
+}
+
+
+
+/*-------------------------------------------------
+ call softlist load
+ -------------------------------------------------*/
+
+bool a78_cart_slot_device::call_softlist_load(software_list_device &swlist, const char *swname, const rom_entry *start_entry)
+{
+ load_software_part_region(*this, swlist, swname, start_entry );
+ return TRUE;
+}
+
+/*-------------------------------------------------
+ identify_cart_type - code to detect cart type from
+ fullpath
+ -------------------------------------------------*/
+
+int a78_cart_slot_device::verify_header(char *header)
+{
+ const char *magic = "ATARI7800";
+
+ if (strncmp(magic, header + 1, 9))
+ {
+ logerror("Not a valid A7800 image\n");
+ return IMAGE_VERIFY_FAIL;
+ }
+
+ logerror("returning ID_OK\n");
+ return IMAGE_VERIFY_PASS;
+}
+
+
+/*-------------------------------------------------
+ get default card software
+ -------------------------------------------------*/
+
+void a78_cart_slot_device::get_default_card_software(astring &result)
+{
+ if (open_image_file(mconfig().options()))
+ {
+ const char *slot_string = "a78_rom";
+ dynamic_buffer head(128);
+ int type = A78_TYPE0;
+
+ // Load and check the header
+ core_fread(m_file, head, 128);
+ switch ((head[53] << 8) | head[54])
+ {
+ case 0x0000:
+ type = A78_TYPE0;
+ break;
+ case 0x0001:
+ type = A78_TYPE1;
+ break;
+ case 0x0002:
+ type = A78_TYPE2;
+ break;
+ case 0x0003:
+ type = A78_TYPE3;
+ break;
+ case 0x0004:
+ type = A78_TYPE6;
+ break;
+ case 0x000a:
+ type = A78_TYPEA;
+ break;
+ case 0x000b:
+ type = A78_TYPEB;
+ break;
+ case 0x0020:
+ m_type = A78_BANKRAM;
+ break;
+ case 0x0100:
+ type = A78_ABSOLUTE;
+ break;
+ case 0x0200:
+ type = A78_ACTIVISION;
+ break;
+ }
+ logerror("Cart type: %x\n", type);
+ slot_string = a78_get_slot(type);
+
+ clear();
+
+ result.cpy(slot_string);
+ }
+ else
+ software_get_default_slot(result, "a78_rom");
+}
+
+
+/*-------------------------------------------------
+ read
+ -------------------------------------------------*/
+
+READ8_MEMBER(a78_cart_slot_device::read_04xx)
+{
+ if (m_cart)
+ return m_cart->read_04xx(space, offset, mem_mask);
+ else
+ return 0xff;
+}
+
+READ8_MEMBER(a78_cart_slot_device::read_10xx)
+{
+ if (m_cart)
+ return m_cart->read_10xx(space, offset, mem_mask);
+ else
+ return 0xff;
+}
+
+READ8_MEMBER(a78_cart_slot_device::read_30xx)
+{
+ if (m_cart)
+ return m_cart->read_30xx(space, offset, mem_mask);
+ else
+ return 0xff;
+}
+
+READ8_MEMBER(a78_cart_slot_device::read_40xx)
+{
+ if (m_cart)
+ return m_cart->read_40xx(space, offset, mem_mask);
+ else
+ return 0xff;
+}
+
+
+/*-------------------------------------------------
+ write
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(a78_cart_slot_device::write_04xx)
+{
+ if (m_cart)
+ m_cart->write_04xx(space, offset, data, mem_mask);
+}
+
+WRITE8_MEMBER(a78_cart_slot_device::write_10xx)
+{
+ if (m_cart)
+ m_cart->write_10xx(space, offset, data, mem_mask);
+}
+
+WRITE8_MEMBER(a78_cart_slot_device::write_30xx)
+{
+ if (m_cart)
+ m_cart->write_30xx(space, offset, data, mem_mask);
+}
+
+WRITE8_MEMBER(a78_cart_slot_device::write_40xx)
+{
+ if (m_cart)
+ m_cart->write_40xx(space, offset, data, mem_mask);
+}
+
+
+/* Header format
+ 0 Header version - 1 byte
+ 1..16 "ATARI7800 " - 16 bytes
+ 17..48 Cart title - 32 bytes
+ 49..52 data length - 4 bytes
+ 53..54 cart type - 2 bytes
+ bit 0 0x01 - pokey cart
+ bit 1 0x02 - supercart bank switched
+ bit 2 0x04 - supercart RAM at $4000
+ bit 3 0x08 - additional ROM at $4000
+ bit 4 0x10 - bank 6 at $4000
+ bit 5 0x20 - supercart banked RAM
+
+ bit 8-15 - Special
+ 0 = Normal cart
+ 1 = Absolute (F18 Hornet)
+ 2 = Activision
+
+ 55 controller 1 type - 1 byte
+ 56 controller 2 type - 1 byte
+ 0 = None
+ 1 = Joystick
+ 2 = Light Gun
+ 57 0 = NTSC/1 = PAL
+
+ 100..127 "ACTUAL CART DATA STARTS HERE" - 28 bytes
+
+ Versions:
+ Version 0: Initial release
+ Version 1: Added PAL/NTSC bit. Added Special cart byte.
+ Changed 53 bit 2, added bit 3
+
+ */
+
+// TODO: log all properties from the header
\ No newline at end of file
diff --git a/src/emu/bus/a7800/a78_slot.h b/src/emu/bus/a7800/a78_slot.h
new file mode 100644
index 00000000000..3d54dddd993
--- /dev/null
+++ b/src/emu/bus/a7800/a78_slot.h
@@ -0,0 +1,142 @@
+#ifndef __A78_SLOT_H
+#define __A78_SLOT_H
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+ ***************************************************************************/
+
+
+/* PCB */
+enum
+{
+ A78_TYPE0 = 0, // standard 8K/16K/32K games, no bankswitch
+ A78_TYPE1, // as TYPE0 + POKEY chip on the PCB
+ A78_TYPE2, // Atari SuperGame pcb (8x16K banks with bankswitch)
+ A78_TYPE3, // as TYPE1 + POKEY chip on the PCB
+ A78_TYPE6, // as TYPE1 + RAM IC on the PCB
+ A78_TYPEA, // Alien Brigade, Crossbow (9x16K banks with diff bankswitch)
+ A78_ABSOLUTE, // F18 Hornet
+ A78_ACTIVISION, // Double Dragon, Rampage
+ A78_HSC, // Atari HighScore cart
+ A78_BANKRAM, // SuperGame + 32K RAM banked (untested)
+ A78_XB_BOARD, // A7800 Expansion Board (it shall more or less apply to the Expansion Module too, but this is not officially released yet)
+ A78_XM_BOARD, // A7800 XM Expansion Module (theoretical specs only, since this is not officially released yet)
+ A78_TYPEB // Cart exploiting the XB board, but possibly also compatible with non-expanded A7800
+};
+
+
+// ======================> device_a78_cart_interface
+
+class device_a78_cart_interface : public device_slot_card_interface
+{
+public:
+ // construction/destruction
+ device_a78_cart_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_a78_cart_interface();
+
+ // memory accessor
+ virtual DECLARE_READ8_MEMBER(read_04xx) { return 0xff; }
+ virtual DECLARE_READ8_MEMBER(read_10xx) { return 0xff; }
+ virtual DECLARE_READ8_MEMBER(read_30xx) { return 0xff; }
+ virtual DECLARE_READ8_MEMBER(read_40xx) { return 0xff; }
+ virtual DECLARE_WRITE8_MEMBER(write_04xx) {}
+ virtual DECLARE_WRITE8_MEMBER(write_10xx) {}
+ virtual DECLARE_WRITE8_MEMBER(write_30xx) {}
+ virtual DECLARE_WRITE8_MEMBER(write_40xx) {}
+
+ void rom_alloc(UINT32 size);
+ void ram_alloc(UINT32 size);
+ void nvram_alloc(UINT32 size);
+ UINT8* get_rom_base() { return m_rom; }
+ UINT8* get_ram_base() { return m_ram; }
+ UINT8* get_nvram_base() { return m_nvram; }
+ UINT32 get_rom_size() { return m_rom.bytes(); }
+ UINT32 get_ram_size() { return m_ram.bytes(); }
+ UINT32 get_nvram_size() { return m_nvram.bytes(); }
+
+protected:
+ // internal state
+ dynamic_buffer m_rom;
+ dynamic_buffer m_ram;
+ dynamic_buffer m_nvram; // HiScore cart can save scores!
+ // helpers
+ UINT32 m_base_rom;
+ int m_bank_mask;
+};
+
+
+void a78_partialhash(hash_collection &dest, const unsigned char *data, unsigned long length, const char *functions);
+
+
+// ======================> a78_cart_slot_device
+
+class a78_cart_slot_device : public device_t,
+ public device_image_interface,
+ public device_slot_interface
+{
+public:
+ // construction/destruction
+ a78_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual ~a78_cart_slot_device();
+
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_config_complete();
+
+ // image-level overrides
+ virtual bool call_load();
+ virtual void call_unload();
+ virtual bool call_softlist_load(software_list_device &swlist, const char *swname, const rom_entry *start_entry);
+
+ int get_cart_type() { return m_type; };
+ int identify_cart_type(UINT8 *ROM, UINT32 len);
+ bool has_cart() { return m_cart != NULL; }
+
+ virtual iodevice_t image_type() const { return IO_CARTSLOT; }
+ virtual bool is_readable() const { return 1; }
+ virtual bool is_writeable() const { return 0; }
+ virtual bool is_creatable() const { return 0; }
+ virtual bool must_be_loaded() const { return 0; }
+ virtual bool is_reset_on_load() const { return 1; }
+ virtual const option_guide *create_option_guide() const { return NULL; }
+ virtual const char *image_interface() const { return "a7800_cart"; }
+ virtual const char *file_extensions() const { return "bin,a78"; }
+ virtual device_image_partialhash_func get_partial_hash() const { return &a78_partialhash; }
+
+ // slot interface overrides
+ virtual void get_default_card_software(astring &result);
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_04xx);
+ virtual DECLARE_READ8_MEMBER(read_10xx);
+ virtual DECLARE_READ8_MEMBER(read_30xx);
+ virtual DECLARE_READ8_MEMBER(read_40xx);
+ virtual DECLARE_WRITE8_MEMBER(write_04xx);
+ virtual DECLARE_WRITE8_MEMBER(write_10xx);
+ virtual DECLARE_WRITE8_MEMBER(write_30xx);
+ virtual DECLARE_WRITE8_MEMBER(write_40xx);
+
+private:
+ device_a78_cart_interface* m_cart;
+ int m_type;
+ int m_stick_type;
+
+ int verify_header(char *header);
+};
+
+
+// device type definition
+extern const device_type A78_CART_SLOT;
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+ ***************************************************************************/
+
+#define MCFG_A78_CARTRIDGE_ADD(_tag,_slot_intf,_def_slot) \
+ MCFG_DEVICE_ADD(_tag, A78_CART_SLOT, 0) \
+ MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false)
+
+
+#endif
diff --git a/src/emu/bus/a7800/hiscore.c b/src/emu/bus/a7800/hiscore.c
new file mode 100644
index 00000000000..434799cb3ee
--- /dev/null
+++ b/src/emu/bus/a7800/hiscore.c
@@ -0,0 +1,76 @@
+/***********************************************************************************************************
+
+ A7800 HighScore passthrough cart emulation
+
+
+***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "hiscore.h"
+#include "a78_carts.h"
+
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+const device_type A78_HISCORE = &device_creator;
+
+
+a78_hiscore_device::a78_hiscore_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : a78_rom_device(mconfig, A78_HISCORE, "Atari 7800 High Score Cart", tag, owner, clock, "a78_highscore", __FILE__),
+ m_hscslot(*this, "hsc_slot")
+{
+}
+
+
+static MACHINE_CONFIG_FRAGMENT( a78_highscore )
+ MCFG_A78_CARTRIDGE_ADD("hsc_slot", a7800_cart, NULL)
+MACHINE_CONFIG_END
+
+machine_config_constructor a78_hiscore_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( a78_highscore );
+}
+
+
+/*-------------------------------------------------
+ mapper specific handlers
+ -------------------------------------------------*/
+
+READ8_MEMBER(a78_hiscore_device::read_10xx)
+{
+ return m_nvram[offset];
+}
+
+WRITE8_MEMBER(a78_hiscore_device::write_10xx)
+{
+ m_nvram[offset] = data;
+}
+
+READ8_MEMBER(a78_hiscore_device::read_30xx)
+{
+ return m_rom[offset];
+}
+
+READ8_MEMBER(a78_hiscore_device::read_04xx)
+{
+ return m_hscslot->read_04xx(space, offset);
+}
+
+WRITE8_MEMBER(a78_hiscore_device::write_04xx)
+{
+ m_hscslot->write_04xx(space, offset, data);
+}
+
+READ8_MEMBER(a78_hiscore_device::read_40xx)
+{
+ return m_hscslot->read_40xx(space, offset);
+}
+
+WRITE8_MEMBER(a78_hiscore_device::write_40xx)
+{
+ m_hscslot->write_40xx(space, offset, data);
+}
+
diff --git a/src/emu/bus/a7800/hiscore.h b/src/emu/bus/a7800/hiscore.h
new file mode 100644
index 00000000000..2848a144eaa
--- /dev/null
+++ b/src/emu/bus/a7800/hiscore.h
@@ -0,0 +1,38 @@
+#ifndef __A78_HISCORE_H
+#define __A78_HISCORE_H
+
+#include "a78_slot.h"
+#include "rom.h"
+
+
+// ======================> a78_hiscore_device
+
+class a78_hiscore_device : public a78_rom_device
+{
+public:
+ // construction/destruction
+ a78_hiscore_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_04xx);
+ virtual DECLARE_WRITE8_MEMBER(write_04xx);
+ virtual DECLARE_READ8_MEMBER(read_10xx);
+ virtual DECLARE_WRITE8_MEMBER(write_10xx);
+ virtual DECLARE_READ8_MEMBER(read_30xx);
+ virtual DECLARE_READ8_MEMBER(read_40xx);
+ virtual DECLARE_WRITE8_MEMBER(write_40xx);
+
+protected:
+ required_device m_hscslot;
+};
+
+
+
+// device type definition
+extern const device_type A78_HISCORE;
+
+
+#endif
diff --git a/src/emu/bus/a7800/rom.c b/src/emu/bus/a7800/rom.c
new file mode 100644
index 00000000000..2bec42385e5
--- /dev/null
+++ b/src/emu/bus/a7800/rom.c
@@ -0,0 +1,512 @@
+/***********************************************************************************************************
+
+ A7800 ROM cart emulation
+
+ For the moment we use separate devices for each combination of hardware
+ - bankswitch or not
+ - pokey or not
+ - 9 banks or not
+ etc...
+ But we might merge many of these if they become too many (e.g. could there be banked 32L RAM also
+ in a 9banks cart or in a cart with no bankswitch?)
+
+***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "rom.h"
+
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+const device_type A78_ROM = &device_creator;
+const device_type A78_ROM_SG = &device_creator;
+const device_type A78_ROM_POKEY = &device_creator;
+const device_type A78_ROM_SG_POKEY = &device_creator;
+const device_type A78_ROM_SG_RAM = &device_creator;
+const device_type A78_ROM_BANKRAM = &device_creator;
+const device_type A78_ROM_SG_9BANKS = &device_creator;
+const device_type A78_ROM_XM = &device_creator;
+const device_type A78_ROM_ABSOLUTE = &device_creator;
+const device_type A78_ROM_ACTIVISION = &device_creator;
+
+
+a78_rom_device::a78_rom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
+ : device_t(mconfig, type, name, tag, owner, clock, shortname, source),
+ device_a78_cart_interface( mconfig, *this )
+{
+}
+
+a78_rom_device::a78_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, A78_ROM, "Atari 7800 ROM Carts w/no Bankswitch", tag, owner, clock, "a78_rom", __FILE__),
+ device_a78_cart_interface( mconfig, *this )
+{
+}
+
+a78_rom_pokey_device::a78_rom_pokey_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : a78_rom_device(mconfig, A78_ROM_POKEY, "Atari 7800 ROM Carts w/no Bankswitch + POKEY", tag, owner, clock, "a78_rom_pok", __FILE__),
+ m_pokey(*this, "pokey")
+{
+}
+
+
+a78_rom_sg_device::a78_rom_sg_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
+ : a78_rom_device(mconfig, type, name, tag, owner, clock, shortname, source)
+{
+}
+
+a78_rom_sg_device::a78_rom_sg_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : a78_rom_device(mconfig, A78_ROM_SG, "Atari 7800 ROM Carts w/SuperGame Bankswitch", tag, owner, clock, "a78_rom_sg", __FILE__)
+{
+}
+
+a78_rom_sg_pokey_device::a78_rom_sg_pokey_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : a78_rom_sg_device(mconfig, A78_ROM_SG_POKEY, "Atari 7800 ROM Carts w/SuperGame Bankswitch + POKEY", tag, owner, clock, "a78_rom_sgp", __FILE__),
+ m_pokey(*this, "pokey")
+{
+}
+
+
+a78_rom_sg_ram_device::a78_rom_sg_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : a78_rom_sg_device(mconfig, A78_ROM_SG_RAM, "Atari 7800 ROM Carts w/SuperGame Bankswitch + RAM", tag, owner, clock, "a78_rom_sgr", __FILE__)
+{
+}
+
+
+a78_rom_bankram_device::a78_rom_bankram_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : a78_rom_sg_device(mconfig, A78_ROM_BANKRAM, "Atari 7800 ROM Carts w/SuperGame Bankswitch + Banked RAM", tag, owner, clock, "a78_rom_bankram", __FILE__)
+{
+}
+
+
+a78_rom_sg_9banks_device::a78_rom_sg_9banks_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
+ : a78_rom_sg_device(mconfig, type, name, tag, owner, clock, shortname, source)
+{
+}
+
+a78_rom_sg_9banks_device::a78_rom_sg_9banks_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : a78_rom_sg_device(mconfig, A78_ROM_SG_9BANKS, "Atari 7800 ROM Carts w/SuperGame 9Banks", tag, owner, clock, "a78_rom_sg9", __FILE__)
+{
+}
+
+
+a78_rom_xm_device::a78_rom_xm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : a78_rom_sg_9banks_device(mconfig, A78_ROM_XM, "Atari 7800 ROM Carts w/SuperGame 9Banks + POKEY (XM demo)", tag, owner, clock, "a78_rom_xm", __FILE__),
+ m_pokey(*this, "pokey")
+{
+}
+
+
+a78_rom_abs_device::a78_rom_abs_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : a78_rom_device(mconfig, A78_ROM_ABSOLUTE, "Atari 7800 ROM Carts w/Absolute Bankswitch", tag, owner, clock, "a78_rom_abs", __FILE__)
+{
+}
+
+
+a78_rom_act_device::a78_rom_act_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : a78_rom_device(mconfig, A78_ROM_ACTIVISION, "Atari 7800 ROM Carts w/Activision Bankswitch", tag, owner, clock, "a78_rom_act", __FILE__)
+{
+}
+
+
+
+void a78_rom_device::device_start()
+{
+}
+
+void a78_rom_device::device_reset()
+{
+}
+
+void a78_rom_sg_device::device_start()
+{
+ save_item(NAME(m_bank));
+}
+
+void a78_rom_sg_device::device_reset()
+{
+ m_bank = 0;
+}
+
+void a78_rom_bankram_device::device_start()
+{
+ save_item(NAME(m_bank));
+ save_item(NAME(m_ram_bank));
+}
+
+void a78_rom_bankram_device::device_reset()
+{
+ m_bank = 0;
+ m_ram_bank = 0;
+}
+
+void a78_rom_abs_device::device_start()
+{
+ save_item(NAME(m_bank));
+}
+
+void a78_rom_abs_device::device_reset()
+{
+ m_bank = 0;
+}
+
+void a78_rom_act_device::device_start()
+{
+ save_item(NAME(m_bank));
+}
+
+void a78_rom_act_device::device_reset()
+{
+ m_bank = 0;
+}
+
+// TO DO: do we need a PAL variant?!?
+static MACHINE_CONFIG_FRAGMENT( a78_pokey )
+ MCFG_SPEAKER_STANDARD_MONO("addon")
+
+ MCFG_SOUND_ADD("pokey", POKEY, XTAL_14_31818MHz/8)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "addon", 1.00)
+MACHINE_CONFIG_END
+
+
+/*-------------------------------------------------
+ mapper specific handlers
+ -------------------------------------------------*/
+
+/*-------------------------------------------------
+
+ Carts with no bankswitch (8K to 48K)
+
+ GAMES:
+
+ -------------------------------------------------*/
+
+READ8_MEMBER(a78_rom_device::read_40xx)
+{
+ if (offset + 0x4000 < m_base_rom)
+ return 0xff;
+ else
+ return m_rom[offset + 0x4000 - m_base_rom];
+}
+
+/*-------------------------------------------------
+
+ Carts with no bankswitch + POKEY chip
+ The Pokey chips is accessed at 0x0450-0x045f or
+ by writing at 0x4000-0x7fff in some games.
+
+ GAMES:
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(a78_rom_pokey_device::write_40xx)
+{
+ if (offset < 0x4000)
+ m_pokey->write(space, offset & 0x0f, data);
+}
+
+READ8_MEMBER(a78_rom_pokey_device::read_04xx)
+{
+ if (offset >= 0x50 && offset < 0x60)
+ return m_pokey->read(space, offset & 0x0f);
+ else
+ return 0xff;
+}
+
+WRITE8_MEMBER(a78_rom_pokey_device::write_04xx)
+{
+ if (offset >= 0x50 && offset < 0x60)
+ m_pokey->write(space, offset & 0x0f, data);
+}
+
+machine_config_constructor a78_rom_pokey_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( a78_pokey );
+}
+
+
+/*-------------------------------------------------
+
+ Carts with SuperGame bankswitch:
+ 8 x 16K banks mappable in 0x8000-0xbfff
+ bank 7 is always mapped in 0xc000-0xffff
+ range 0x4000-0x7fff is not clear: some games
+ expect bank 6 to be mapped there, others
+ have open bus (we assume the former until
+ a game requires more precise behavior or
+ some test is run)
+ Note that the code is written so that also
+ homebrew games with larger ROMs work!
+
+ GAMES:
+
+ -------------------------------------------------*/
+
+READ8_MEMBER(a78_rom_sg_device::read_40xx)
+{
+ if (offset < 0x4000)
+ return m_rom[(offset & 0x3fff) + ((m_bank_mask - 1) * 0x4000)]; // second to last bank (is this always ok?!?)
+ else if (offset < 0x8000)
+ return m_rom[(offset & 0x3fff) + (m_bank * 0x4000)];
+ else
+ return m_rom[(offset & 0x3fff) + (m_bank_mask * 0x4000)]; // last bank
+}
+
+WRITE8_MEMBER(a78_rom_sg_device::write_40xx)
+{
+ if (offset >= 0x4000 && offset < 0x8000)
+ m_bank = data & m_bank_mask;
+}
+
+
+/*-------------------------------------------------
+
+ Carts with SuperGame bankswitch + POKEY chip
+ As above, the Pokey chips is accessed at
+
+ GAMES:
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(a78_rom_sg_pokey_device::write_40xx)
+{
+ if (offset < 0x4000)
+ m_pokey->write(space, offset & 0x0f, data);
+ else if (offset < 0x8000)
+ m_bank = data & m_bank_mask;
+}
+
+READ8_MEMBER(a78_rom_sg_pokey_device::read_04xx)
+{
+ if (offset >= 0x50 && offset < 0x60)
+ return m_pokey->read(space, offset & 0x0f);
+ else
+ return 0xff;
+}
+
+WRITE8_MEMBER(a78_rom_sg_pokey_device::write_04xx)
+{
+ if (offset >= 0x50 && offset < 0x60)
+ m_pokey->write(space, offset & 0x0f, data);
+}
+
+machine_config_constructor a78_rom_sg_pokey_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( a78_pokey );
+}
+
+
+/*-------------------------------------------------
+
+ Carts with SuperGame bankswitch + 16K RAM
+ FIXME: Some games contained only 8K of RAM, but
+ for the moment we treat all as 16K of RAM even if
+ from softlist we shall differentiate between them.
+
+ GAMES:
+
+ -------------------------------------------------*/
+
+READ8_MEMBER(a78_rom_sg_ram_device::read_40xx)
+{
+ if (offset < 0x4000)
+ return m_ram[offset];
+ else if (offset < 0x8000)
+ return m_rom[(offset & 0x3fff) + (m_bank * 0x4000)];
+ else
+ return m_rom[(offset & 0x3fff) + (m_bank_mask * 0x4000)]; // last bank
+}
+
+WRITE8_MEMBER(a78_rom_sg_ram_device::write_40xx)
+{
+ if (offset < 0x4000)
+ m_ram[offset] = data;
+ else if (offset < 0x8000)
+ m_bank = data & m_bank_mask;
+}
+
+
+/*-------------------------------------------------
+
+ Carts with SuperGame bankswitch + 32K RAM:
+ RAM bank is selected by writing with bit5 enabled
+ in 0x4000-0x7fff range (bit0-bit4 give the ROM bank)
+
+ GAMES:
+
+ -------------------------------------------------*/
+
+READ8_MEMBER(a78_rom_bankram_device::read_40xx)
+{
+ if (offset < 0x4000)
+ return m_ram[offset + (m_ram_bank * 0x4000)];
+ else if (offset < 0x8000)
+ return m_rom[(offset & 0x3fff) + (m_bank * 0x4000)];
+ else
+ return m_rom[(offset & 0x3fff) + (m_bank_mask * 0x4000)]; // last bank
+}
+
+WRITE8_MEMBER(a78_rom_bankram_device::write_40xx)
+{
+ if (offset < 0x4000)
+ m_ram[offset] = data;
+ else if (offset < 0x8000)
+ {
+ m_bank = data & m_bank_mask;
+ m_ram_bank = BIT(data, 5);
+ }
+}
+
+
+/*-------------------------------------------------
+
+ Carts with SuperGame bankswitch 9banks:
+ 9 x 16K banks mappable in 0x8000-0xbfff
+ bank 7 is always mapped in 0xc000-0xffff
+
+ GAMES:
+
+ -------------------------------------------------*/
+
+READ8_MEMBER(a78_rom_sg_9banks_device::read_40xx)
+{
+ if (offset < 0x4000)
+ return m_rom[(offset & 0x3fff)];
+ else if (offset < 0x8000)
+ return m_rom[(offset & 0x3fff) + (m_bank * 0x4000)];
+ else
+ return m_rom[(offset & 0x3fff) + ((m_bank_mask + 1) * 0x4000)]; // last bank
+}
+
+WRITE8_MEMBER(a78_rom_sg_9banks_device::write_40xx)
+{
+ if (offset >= 0x4000 && offset < 0x8000)
+ m_bank = (data & m_bank_mask) + 1;
+}
+
+/*-------------------------------------------------
+
+ Carts using XM expansion module or XBoarD expansion
+ The only game using this (Donkey Kong XM demo) is
+ 144K + POKEY, so that it's like the above with the
+ addition of the POKEY.
+
+ GAMES: Donkey Kong XM demo
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(a78_rom_xm_device::write_40xx)
+{
+ if (offset < 0x4000)
+ m_pokey->write(space, offset & 0x0f, data);
+ else if (offset < 0x8000)
+ m_bank = (data & m_bank_mask) + 1;
+}
+
+READ8_MEMBER(a78_rom_xm_device::read_04xx)
+{
+ if (offset >= 0x50 && offset < 0x60)
+ return m_pokey->read(space, offset & 0x0f);
+ else
+ return 0xff;
+}
+
+WRITE8_MEMBER(a78_rom_xm_device::write_04xx)
+{
+ if (offset >= 0x50 && offset < 0x60)
+ m_pokey->write(space, offset & 0x0f, data);
+}
+
+machine_config_constructor a78_rom_xm_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( a78_pokey );
+}
+
+
+/*-------------------------------------------------
+
+ Carts with Absolute bankswitch:
+ 64K games. Lower 32K are 2 banks of 16K to be mapped
+ in 0x4000-0x7fff, depending on the value written
+ at 0x8000. Higher 32K are fixed in 0x8000-0xffff
+
+ GAMES: F-18 Hornet
+
+ -------------------------------------------------*/
+
+READ8_MEMBER(a78_rom_abs_device::read_40xx)
+{
+ if (offset < 0x4000)
+ return m_rom[(offset & 0x3fff) + (m_bank * 0x4000)];
+ else
+ {
+ offset -= 0x4000;
+ return m_rom[offset + 0x8000];
+ }
+}
+
+WRITE8_MEMBER(a78_rom_abs_device::write_40xx)
+{
+ if (offset == 0x4000)
+ {
+ if (data & 1)
+ m_bank = 0;
+ else if (data & 2)
+ m_bank = 1;
+ }
+}
+
+/*-------------------------------------------------
+
+ Carts with Activision bankswitch:
+ 128K games. 8 x 16K banks (0-7) to be mapped at
+ 0xa000-0xdfff. Bank is selected depending on the
+ address written in 0xff80-0xff87.
+ The rest of the memory is as follows:
+ 0x4000-0x5fff second 8kb of bank 6
+ 0x6000-0x7fff first 8kb of bank 6
+ 0x8000-0x9fff second 8kb of bank 7
+ 0xe000-0xffff first 8kb of bank 7
+
+ GAMES: Double Dragon, Rampage.
+
+ -------------------------------------------------*/
+
+READ8_MEMBER(a78_rom_act_device::read_40xx)
+{
+ UINT8 data = 0xff;
+ UINT16 addr = offset & 0x1fff;
+
+ // offset goes from 0 to 0xc000
+ switch (offset & 0xe000)
+ {
+ case 0x0000:
+ data = m_rom[addr + 0x1a000];
+ break;
+ case 0x2000:
+ data = m_rom[addr + 0x18000];
+ break;
+ case 0x4000:
+ data = m_rom[addr + 0x1e000];
+ break;
+ case 0x6000:
+ data = m_rom[addr + (m_bank * 0x4000)];
+ break;
+ case 0x8000:
+ data = m_rom[addr + (m_bank * 0x4000) + 0x2000];
+ break;
+ case 0xa000:
+ data = m_rom[addr + 0x1c000];
+ break;
+ }
+
+ return data;
+}
+
+WRITE8_MEMBER(a78_rom_act_device::write_40xx)
+{
+ if (offset >= 0xbf80 && offset <= 0xbf87)
+ m_bank = offset & 7;
+}
diff --git a/src/emu/bus/a7800/rom.h b/src/emu/bus/a7800/rom.h
new file mode 100644
index 00000000000..62764df81f3
--- /dev/null
+++ b/src/emu/bus/a7800/rom.h
@@ -0,0 +1,217 @@
+#ifndef __A78_ROM_H
+#define __A78_ROM_H
+
+#include "a78_slot.h"
+#include "sound/pokey.h"
+
+
+// ======================> a78_rom_device
+
+class a78_rom_device : public device_t,
+ public device_a78_cart_interface
+{
+public:
+ // construction/destruction
+ a78_rom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+ a78_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_40xx);
+};
+
+
+// ======================> a78_rom_pokey_device
+
+class a78_rom_pokey_device : public a78_rom_device
+{
+public:
+ // construction/destruction
+ a78_rom_pokey_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_04xx);
+ virtual DECLARE_WRITE8_MEMBER(write_04xx);
+ virtual DECLARE_WRITE8_MEMBER(write_40xx);
+
+protected:
+ required_device m_pokey;
+};
+
+
+// ======================> a78_rom_sg_device
+
+class a78_rom_sg_device : public a78_rom_device
+{
+public:
+ // construction/destruction
+ a78_rom_sg_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+ a78_rom_sg_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_40xx);
+ virtual DECLARE_WRITE8_MEMBER(write_40xx);
+
+protected:
+ int m_bank;
+};
+
+
+// ======================> a78_rom_sg_pokey_device
+
+class a78_rom_sg_pokey_device : public a78_rom_sg_device
+{
+public:
+ // construction/destruction
+ a78_rom_sg_pokey_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_04xx);
+ virtual DECLARE_WRITE8_MEMBER(write_04xx);
+ virtual DECLARE_WRITE8_MEMBER(write_40xx);
+
+protected:
+ required_device m_pokey;
+};
+
+
+// ======================> a78_rom_sg_ram_device
+
+class a78_rom_sg_ram_device : public a78_rom_sg_device
+{
+public:
+ // construction/destruction
+ a78_rom_sg_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_40xx);
+ virtual DECLARE_WRITE8_MEMBER(write_40xx);
+};
+
+
+// ======================> a78_rom_bankram_device
+
+class a78_rom_bankram_device : public a78_rom_sg_device
+{
+public:
+ // construction/destruction
+ a78_rom_bankram_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_40xx);
+ virtual DECLARE_WRITE8_MEMBER(write_40xx);
+
+protected:
+ int m_ram_bank;
+};
+
+
+// ======================> a78_rom_sg_9banks_device
+
+class a78_rom_sg_9banks_device : public a78_rom_sg_device
+{
+public:
+ // construction/destruction
+ a78_rom_sg_9banks_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+ a78_rom_sg_9banks_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_40xx);
+ virtual DECLARE_WRITE8_MEMBER(write_40xx);
+};
+
+
+// ======================> a78_rom_xm_device
+
+class a78_rom_xm_device : public a78_rom_sg_9banks_device
+{
+public:
+ // construction/destruction
+ a78_rom_xm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_04xx);
+ virtual DECLARE_WRITE8_MEMBER(write_04xx);
+ virtual DECLARE_WRITE8_MEMBER(write_40xx);
+
+protected:
+ required_device m_pokey;
+};
+
+
+// ======================> a78_rom_abs_device
+
+class a78_rom_abs_device : public a78_rom_device
+{
+public:
+ // construction/destruction
+ a78_rom_abs_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_40xx);
+ virtual DECLARE_WRITE8_MEMBER(write_40xx);
+
+protected:
+ int m_bank;
+};
+
+
+// ======================> a78_rom_act_device
+
+class a78_rom_act_device : public a78_rom_device
+{
+public:
+ // construction/destruction
+ a78_rom_act_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_40xx);
+ virtual DECLARE_WRITE8_MEMBER(write_40xx);
+
+protected:
+ int m_bank;
+};
+
+
+// device type definition
+extern const device_type A78_ROM;
+extern const device_type A78_ROM_SG;
+extern const device_type A78_ROM_POKEY;
+extern const device_type A78_ROM_SG_POKEY;
+extern const device_type A78_ROM_SG_RAM;
+extern const device_type A78_ROM_BANKRAM;
+extern const device_type A78_ROM_SG_9BANKS;
+extern const device_type A78_ROM_XM;
+extern const device_type A78_ROM_ABSOLUTE;
+extern const device_type A78_ROM_ACTIVISION;
+
+
+#endif
diff --git a/src/emu/bus/a7800/xboard.c b/src/emu/bus/a7800/xboard.c
new file mode 100644
index 00000000000..46840e18e20
--- /dev/null
+++ b/src/emu/bus/a7800/xboard.c
@@ -0,0 +1,178 @@
+/***********************************************************************************************************
+
+ A7800 XBoarD & XM expansions emulation
+
+ The XBoarD should be socketed in the A7800 pcb in place of the Maria chip.
+ It adds to the system additional 128K of RAM and an onboard pokey.
+ The XM seems to work the same as XBoarD, but it also features HighScore savings
+ (using the same ROM as Atari HighScore cart)
+
+
+ Currently, we emulate both of these as a passthru cart, even if not 100% accurate for the XBoarD
+
+
+ Memory map:
+
+ POKEY1 $0450 $045F 16 bytes
+ POKEY2* $0460 $046F 16 bytes
+ XCTRL $0470 $047F 1 byte
+ RAM $4000 $7FFF 16384 bytes
+
+ XCTRL Bit Description
+
+ +-------------------------------+
+ | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ +-------------------------------+
+ | | | | | | | |
+ | | | | | | | +-- Bank select bit 0 \
+ | | | | | | +------ Bank select bit 1 | Totally 128 KByte in 16 KByte banks
+ | | | | | +---------- Bank select bit 2 /
+ | | | | +-------------- Enable memory bit** (1 = Memory enabled, 0 after power on)
+ | | | +------------------ Enable POKEY bit (1 = POKEY enabled, 0 after power on)
+ | | |
+ NA NA NA = Not Available or Not Used
+
+ * = Can be mounted piggy back on the first POKEY. Description how to do this will come when i have tried it out.
+ ** This bit controls both POKEY chip select signals.
+
+ TODO:
+ - verify what happens when 2 POKEYs are present
+ - verify whether high score works fine with XM
+
+***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "xboard.h"
+#include "a78_carts.h"
+
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+const device_type A78_XBOARD = &device_creator;
+const device_type A78_XM = &device_creator;
+
+
+a78_xboard_device::a78_xboard_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
+ : a78_rom_device(mconfig, type, name, tag, owner, clock, shortname, source),
+ m_xbslot(*this, "xb_slot"),
+ m_pokey(*this, "xb_pokey")
+{
+}
+
+
+a78_xboard_device::a78_xboard_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : a78_rom_device(mconfig, A78_XBOARD, "Atari 7800 XBoarD expansion", tag, owner, clock, "a78_xboard", __FILE__),
+ m_xbslot(*this, "xb_slot"),
+ m_pokey(*this, "xb_pokey")
+{
+}
+
+
+a78_xm_device::a78_xm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : a78_xboard_device(mconfig, A78_XM, "Atari 7800 XM expansion module", tag, owner, clock, "a78_xm", __FILE__)
+{
+}
+
+
+void a78_xboard_device::device_start()
+{
+ save_item(NAME(m_reg));
+ save_item(NAME(m_ram_bank));
+}
+
+void a78_xboard_device::device_reset()
+{
+ m_reg = 0;
+ m_ram_bank = 0;
+}
+
+
+static MACHINE_CONFIG_FRAGMENT( a78_xb )
+ MCFG_A78_CARTRIDGE_ADD("xb_slot", a7800_cart, NULL)
+
+ MCFG_SPEAKER_STANDARD_MONO("xb_speaker")
+
+ MCFG_SOUND_ADD("xb_pokey", POKEY, XTAL_14_31818MHz/8)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "xb_speaker", 1.00)
+MACHINE_CONFIG_END
+
+machine_config_constructor a78_xboard_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( a78_xb );
+}
+
+
+/*-------------------------------------------------
+ mapper specific handlers
+ -------------------------------------------------*/
+
+/*-------------------------------------------------
+
+ XBoarD: passthru + 128K RAM + POKEY
+
+ -------------------------------------------------*/
+
+READ8_MEMBER(a78_xboard_device::read_40xx)
+{
+ if (BIT(m_reg, 3) && offset < 0x4000)
+ return m_ram[offset + (m_ram_bank * 0x4000)];
+ else
+ return m_xbslot->read_40xx(space, offset);
+}
+
+WRITE8_MEMBER(a78_xboard_device::write_40xx)
+{
+ if (BIT(m_reg, 3) && offset < 0x4000)
+ m_ram[offset + (m_ram_bank * 0x4000)] = data;
+ else
+ m_xbslot->write_40xx(space, offset, data);
+}
+
+READ8_MEMBER(a78_xboard_device::read_04xx)
+{
+ if (BIT(m_reg, 4) && offset >= 0x50 && offset < 0x60)
+ return m_pokey->read(space, offset & 0x0f);
+ else if (BIT(m_reg, 4) && offset >= 0x60 && offset < 0x70)
+ return m_xbslot->read_04xx(space, offset - 0x10); // access second POKEY
+ else
+ return 0xff;
+}
+
+WRITE8_MEMBER(a78_xboard_device::write_04xx)
+{
+ if (BIT(m_reg, 4) && offset >= 0x50 && offset < 0x60)
+ m_pokey->write(space, offset & 0x0f, data);
+ else if (BIT(m_reg, 4) && offset >= 0x60 && offset < 0x70)
+ m_xbslot->write_04xx(space, offset - 0x10, data); // access second POKEY
+ else if (offset >= 0x70 && offset < 0x80)
+ {
+ m_reg = data;
+ m_ram_bank = m_reg & 7;
+ }
+}
+
+
+/*-------------------------------------------------
+
+ XM: Same as above but also featuring High Score savings
+
+ -------------------------------------------------*/
+
+READ8_MEMBER(a78_xm_device::read_10xx)
+{
+ return m_nvram[offset];
+}
+
+WRITE8_MEMBER(a78_xm_device::write_10xx)
+{
+ m_nvram[offset] = data;
+}
+
+READ8_MEMBER(a78_xm_device::read_30xx)
+{
+ return m_rom[offset];
+}
+
diff --git a/src/emu/bus/a7800/xboard.h b/src/emu/bus/a7800/xboard.h
new file mode 100644
index 00000000000..011894b56ef
--- /dev/null
+++ b/src/emu/bus/a7800/xboard.h
@@ -0,0 +1,57 @@
+#ifndef __A78_XBOARD_H
+#define __A78_XBOARD_H
+
+#include "a78_slot.h"
+#include "rom.h"
+#include "sound/pokey.h"
+
+
+// ======================> a78_xboard_device
+
+class a78_xboard_device : public a78_rom_device
+{
+public:
+ // construction/destruction
+ a78_xboard_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+ a78_xboard_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+ virtual void device_start();
+ virtual machine_config_constructor device_mconfig_additions() const;
+ virtual void device_reset();
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_04xx);
+ virtual DECLARE_WRITE8_MEMBER(write_04xx);
+ virtual DECLARE_READ8_MEMBER(read_40xx);
+ virtual DECLARE_WRITE8_MEMBER(write_40xx);
+
+protected:
+ required_device m_xbslot;
+ required_device m_pokey;
+ int m_reg, m_ram_bank;
+};
+
+
+// ======================> a78_xm_device
+
+class a78_xm_device : public a78_xboard_device
+{
+public:
+ // construction/destruction
+ a78_xm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_10xx);
+ virtual DECLARE_WRITE8_MEMBER(write_10xx);
+ virtual DECLARE_READ8_MEMBER(read_30xx);
+};
+
+
+
+// device type definition
+extern const device_type A78_XBOARD;
+extern const device_type A78_XM;
+
+
+#endif
diff --git a/src/emu/bus/bus.mak b/src/emu/bus/bus.mak
index 9fa91b00075..04205197c69 100644
--- a/src/emu/bus/bus.mak
+++ b/src/emu/bus/bus.mak
@@ -14,6 +14,20 @@ BUSSRC = $(EMUSRC)/bus
BUSOBJ = $(EMUOBJ)/bus
+#-------------------------------------------------
+#
+#@src/emu/bus/a7800/a78_slot.h,BUSES += A7800
+#-------------------------------------------------
+
+ifneq ($(filter A7800,$(BUSES)),)
+OBJDIRS += $(BUSOBJ)/a7800
+BUSOBJS += $(BUSOBJ)/a7800/a78_slot.o
+BUSOBJS += $(BUSOBJ)/a7800/rom.o
+BUSOBJS += $(BUSOBJ)/a7800/hiscore.o
+BUSOBJS += $(BUSOBJ)/a7800/xboard.o
+endif
+
+
#-------------------------------------------------
#
#@src/emu/bus/abcbus/abcbus.h,BUSES += ABCBUS
diff --git a/src/mess/drivers/a7800.c b/src/mess/drivers/a7800.c
index 745ff35c87c..2af68e471a3 100644
--- a/src/mess/drivers/a7800.c
+++ b/src/mess/drivers/a7800.c
@@ -7,8 +7,9 @@
Dan Boris
2002/05/13 kubecj added more banks for bankswitching
- added PAL machine description
- changed clock to be precise
+ added PAL machine description
+ changed clock to be precise
+ improved cart emulation (in machine/)
2012/10/25 Robert Tuccitto NTSC Color Generator utilized for
color palette with hue shift/start
@@ -83,15 +84,20 @@
2014/03/25 Mike Saarna Fixed Riot Timer
+ 2014/04/04 Mike Saarna Fix to controller button RIOT behavior
+
2014/05/06 Mike Saarna/Robert Tuccitto Brought initial Maria cycle counts
-+ inline from measurements taken with logic analyzer and tests.
+ inline from measurements taken with logic analyzer and tests.
+
+ 2014/08/25 Fabio Priuli Converted carts to be slot devices and cleaned
+ up the driver (removed the pokey, cleaned up rom regions, etc.)
+
***************************************************************************/
#include "emu.h"
#include "cpu/m6502/m6502.h"
-#include "sound/pokey.h"
#include "sound/tiaintf.h"
-#include "imagedev/cartslot.h"
+#include "bus/a7800/a78_carts.h"
#include "machine/6532riot.h"
#include "includes/a7800.h"
@@ -100,32 +106,122 @@
#define CLK_PAL 1773447
+/***************************************************************************
+ MEMORY HANDLERS
+ ***************************************************************************/
+
+// RIOT
+READ8_MEMBER(a7800_state::riot_joystick_r)
+{
+ return m_io_joysticks->read();
+}
+
+READ8_MEMBER(a7800_state::riot_console_button_r)
+{
+ return m_io_console_buttons->read();
+}
+
+WRITE8_MEMBER(a7800_state::riot_button_pullup_w)
+{
+ if(m_maincpu->space(AS_PROGRAM).read_byte(0x283) & 0x04)
+ m_p1_one_button = data & 0x04; // pin 6 of the controller port is held high by the riot chip when reading two-button controllers (from schematic)
+ if(m_maincpu->space(AS_PROGRAM).read_byte(0x283) & 0x10)
+ m_p2_one_button = data & 0x10;
+}
+
+READ8_MEMBER(a7800_state::tia_r)
+{
+ switch (offset & 0x0f)
+ {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ /* Even though the 7800 doesn't use the TIA graphics the collision registers should
+ still return a reasonable value */
+ return 0x00;
+ case 0x08:
+ return ((m_io_buttons->read() & 0x02) << 6);
+ case 0x09:
+ return ((m_io_buttons->read() & 0x08) << 4);
+ case 0x0a:
+ return ((m_io_buttons->read() & 0x01) << 7);
+ case 0x0b:
+ return ((m_io_buttons->read() & 0x04) << 5);
+ case 0x0c:
+ if (((m_io_buttons->read() & 0x08) ||(m_io_buttons->read() & 0x02)) && m_p1_one_button)
+ return 0x00;
+ else
+ return 0x80;
+ case 0x0d:
+ if (((m_io_buttons->read() & 0x01) ||(m_io_buttons->read() & 0x04)) && m_p2_one_button)
+ return 0x00;
+ else
+ return 0x80;
+ default:
+ logerror("undefined TIA read %x\n",offset);
+
+ }
+ return 0xff;
+}
+
+// TIA
+WRITE8_MEMBER(a7800_state::tia_w)
+{
+ if (offset < 0x20)
+ { //INPTCTRL covers TIA registers 0x00-0x1F until locked
+ if (data & 0x01)
+ {
+ if (m_ctrl_lock && offset == 0x01)
+ m_maria_flag = 1;
+ else if (!m_ctrl_lock)
+ m_maria_flag = 1;
+ }
+ if (!m_ctrl_lock)
+ {
+ m_ctrl_lock = data & 0x01;
+ m_ctrl_reg = data;
+ }
+ }
+ m_tia->tia_sound_w(space, offset, data);
+}
+
+
+// ROM
+READ8_MEMBER(a7800_state::bios_or_cart_r)
+{
+ if (!(m_ctrl_reg & 0x04))
+ return m_bios[offset];
+ else
+ return m_cartslot->read_40xx(space, offset + 0x8000);
+}
+
/***************************************************************************
ADDRESS MAPS
***************************************************************************/
static ADDRESS_MAP_START( a7800_mem, AS_PROGRAM, 8, a7800_state )
- AM_RANGE(0x0000, 0x001f) AM_MIRROR(0x300) AM_READWRITE(a7800_TIA_r, a7800_TIA_w)
- AM_RANGE(0x0020, 0x003f) AM_MIRROR(0x300) AM_READWRITE(a7800_MARIA_r, a7800_MARIA_w)
- AM_RANGE(0x0040, 0x00ff) AM_READ_BANK("bank5") AM_WRITE(a7800_RAM0_w) /* RAM (6116 block 0) */
- AM_RANGE(0x0140, 0x01ff) AM_RAMBANK("bank6") /* RAM (6116 block 1) */
+ AM_RANGE(0x0000, 0x001f) AM_MIRROR(0x300) AM_READWRITE(tia_r, tia_w)
+ AM_RANGE(0x0020, 0x003f) AM_MIRROR(0x300) AM_READWRITE(maria_r, maria_w)
+ AM_RANGE(0x0040, 0x00ff) AM_RAMBANK("ram0") // RAM (6116 block 0)
+ AM_RANGE(0x0140, 0x01ff) AM_RAMBANK("ram1") // RAM (6116 block 1)
AM_RANGE(0x0280, 0x02ff) AM_DEVREADWRITE("riot", riot6532_device, read, write)
- AM_RANGE(0x0450, 0x045f) /* XBOARD POKEY1 */
- AM_RANGE(0x0460, 0x046f) /* XBOARD POKEY2 */
- AM_RANGE(0x0470, 0x047f) /* XBOARD CTRL */
- AM_RANGE(0x0480, 0x04ff) AM_MIRROR(0x100) AM_RAM /* RIOT RAM */
- AM_RANGE(0x1000, 0x17ff) AM_RAM /* hs SRAM */
- AM_RANGE(0x1800, 0x27ff) AM_RAM
- AM_RANGE(0x2800, 0x2fff) AM_RAMBANK("bank7") /* MAINRAM */
- AM_RANGE(0x3000, 0x37ff) AM_RAMBANK("bank7") /* MAINRAM */
- AM_RANGE(0x3800, 0x3fff) AM_RAMBANK("bank7") /* MAINRAM */
- AM_RANGE(0x3000, 0x3fff) AM_ROM /* hs ROM space */
- AM_RANGE(0x4000, 0x7fff) AM_ROMBANK("bank1") /* f18 hornet */
- AM_RANGE(0x4000, 0xffff) AM_WRITE(a7800_cart_w) /* XBOARD SRAM */
- AM_RANGE(0x8000, 0x9fff) AM_ROMBANK("bank2") /* sc */
- AM_RANGE(0xa000, 0xbfff) AM_ROMBANK("bank3") /* sc + ac */
- AM_RANGE(0xc000, 0xdfff) AM_ROMBANK("bank4") /* ac */
- AM_RANGE(0xe000, 0xffff) AM_ROM
+ AM_RANGE(0x0480, 0x04ff) AM_MIRROR(0x100) AM_RAMBANK("riot_ram")
+ AM_RANGE(0x1800, 0x27ff) AM_RAMBANK("main_ram")
+
+ AM_RANGE(0x2040, 0x20ff) AM_RAMBANK("ram0") // mirror (6116 block 0)
+ AM_RANGE(0x2140, 0x21ff) AM_RAMBANK("ram1") // mirror (6116 block 1)
+
+ AM_RANGE(0x2800, 0x2fff) AM_RAMBANK("mirror") // these should mirror "main_ram" (according to docs)
+ AM_RANGE(0x3000, 0x37ff) AM_RAMBANK("mirror") // but system have issues in such case...
+ AM_RANGE(0x3800, 0x3fff) AM_RAMBANK("mirror")
+ AM_RANGE(0x4000, 0xffff) AM_DEVWRITE("cartslot", a78_cart_slot_device, write_40xx)
+ AM_RANGE(0x4000, 0xbfff) AM_DEVREAD("cartslot", a78_cart_slot_device, read_40xx)
+ AM_RANGE(0xc000, 0xffff) AM_READ(bios_or_cart_r) // here also the BIOS can be accessed
ADDRESS_MAP_END
@@ -134,7 +230,7 @@ ADDRESS_MAP_END
***************************************************************************/
static INPUT_PORTS_START( a7800 )
- PORT_START("joysticks") /* IN0 */
+ PORT_START("joysticks")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_PLAYER(2) PORT_8WAY
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_PLAYER(2) PORT_8WAY
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_PLAYER(2) PORT_8WAY
@@ -144,18 +240,18 @@ static INPUT_PORTS_START( a7800 )
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_PLAYER(1) PORT_8WAY
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_PLAYER(1) PORT_8WAY
- PORT_START("buttons") /* IN1 */
+ PORT_START("buttons")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_PLAYER(2)
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_PLAYER(1)
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(2)
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(1)
PORT_BIT(0xF0, IP_ACTIVE_LOW, IPT_UNUSED)
- PORT_START("vblank") /* IN2 */
+ PORT_START("vblank")
PORT_BIT(0x7F, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_VBLANK("screen")
- PORT_START("console_buttons") /* IN3 */
+ PORT_START("console_buttons")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Reset") PORT_CODE(KEYCODE_R)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Select") PORT_CODE(KEYCODE_S)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED)
@@ -1133,13 +1229,51 @@ PALETTE_INIT_MEMBER(a7800_state,a7800p)
MACHINE DRIVERS
***************************************************************************/
+void a7800_state::machine_start()
+{
+ m_bios = machine().root_device().memregion("maincpu")->base() + 0xc000;
+ save_item(NAME(m_p1_one_button));
+ save_item(NAME(m_p2_one_button));
+ save_item(NAME(m_bios_enabled));
+ save_item(NAME(m_ctrl_lock));
+ save_item(NAME(m_ctrl_reg));
+ save_item(NAME(m_maria_flag));
+
+ // install additional POKEY handlers
+ switch (m_cartslot->get_cart_type())
+ {
+ case A78_TYPE1:
+ case A78_TYPE3:
+ case A78_TYPEB:
+ case A78_XB_BOARD:
+ m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x0400, 0x047f, read8_delegate(FUNC(a78_cart_slot_device::read_04xx),(a78_cart_slot_device*)m_cartslot), write8_delegate(FUNC(a78_cart_slot_device::write_04xx),(a78_cart_slot_device*)m_cartslot));
+ break;
+ case A78_HSC:
+ m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x1000, 0x17ff, read8_delegate(FUNC(a78_cart_slot_device::read_10xx),(a78_cart_slot_device*)m_cartslot), write8_delegate(FUNC(a78_cart_slot_device::write_10xx),(a78_cart_slot_device*)m_cartslot));
+ m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x3000, 0x3fff, read8_delegate(FUNC(a78_cart_slot_device::read_30xx),(a78_cart_slot_device*)m_cartslot), write8_delegate(FUNC(a78_cart_slot_device::write_30xx),(a78_cart_slot_device*)m_cartslot));
+ break;
+ case A78_XM_BOARD:
+ m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x0400, 0x047f, read8_delegate(FUNC(a78_cart_slot_device::read_04xx),(a78_cart_slot_device*)m_cartslot), write8_delegate(FUNC(a78_cart_slot_device::write_04xx),(a78_cart_slot_device*)m_cartslot));
+ m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x1000, 0x17ff, read8_delegate(FUNC(a78_cart_slot_device::read_10xx),(a78_cart_slot_device*)m_cartslot), write8_delegate(FUNC(a78_cart_slot_device::write_10xx),(a78_cart_slot_device*)m_cartslot));
+ m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x3000, 0x3fff, read8_delegate(FUNC(a78_cart_slot_device::read_30xx),(a78_cart_slot_device*)m_cartslot), write8_delegate(FUNC(a78_cart_slot_device::write_30xx),(a78_cart_slot_device*)m_cartslot));
+ break;
+ }
+}
+
+void a7800_state::machine_reset()
+{
+ m_ctrl_lock = 0;
+ m_ctrl_reg = 0;
+ m_maria_flag = 0;
+ m_bios_enabled = 0;
+}
+
static MACHINE_CONFIG_START( a7800_ntsc, a7800_state )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu", M6502, A7800_NTSC_Y1/8) /* 1.79 MHz (switches to 1.19 MHz on TIA or RIOT access) */
MCFG_CPU_PROGRAM_MAP(a7800_mem)
MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", a7800_state, a7800_interrupt, "screen", 0, 1)
-
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_RAW_PARAMS( 7159090, 454, 0, 320, 263, 27, 27 + 192 + 32 )
@@ -1149,13 +1283,10 @@ static MACHINE_CONFIG_START( a7800_ntsc, a7800_state )
MCFG_PALETTE_ADD("palette", ARRAY_LENGTH(a7800_palette) / 3)
MCFG_PALETTE_INIT_OWNER(a7800_state, a7800)
-
/* sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_TIA_ADD("tia", 31400)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
- MCFG_SOUND_ADD("pokey", POKEY, A7800_NTSC_Y1/8)
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
/* devices */
MCFG_DEVICE_ADD("riot", RIOT6532, A7800_NTSC_Y1/8)
@@ -1163,12 +1294,7 @@ static MACHINE_CONFIG_START( a7800_ntsc, a7800_state )
MCFG_RIOT6532_IN_PB_CB(READ8(a7800_state, riot_console_button_r))
MCFG_RIOT6532_OUT_PB_CB(WRITE8(a7800_state, riot_button_pullup_w))
- MCFG_CARTSLOT_ADD("cart")
- MCFG_CARTSLOT_EXTENSION_LIST("bin,a78")
- MCFG_CARTSLOT_NOT_MANDATORY
- MCFG_CARTSLOT_LOAD(a7800_state,a7800_cart)
- MCFG_CARTSLOT_PARTIALHASH(a7800_partialhash)
- MCFG_CARTSLOT_INTERFACE("a7800_cart")
+ MCFG_A78_CARTRIDGE_ADD("cartslot", a7800_cart, NULL)
/* software lists */
MCFG_SOFTWARE_LIST_ADD("cart_list","a7800")
@@ -1177,7 +1303,6 @@ MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( a7800_pal, a7800_ntsc )
-
/* basic machine hardware */
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_CLOCK(CLK_PAL)
@@ -1189,11 +1314,6 @@ static MACHINE_CONFIG_DERIVED( a7800_pal, a7800_ntsc )
MCFG_PALETTE_MODIFY("palette")
MCFG_PALETTE_INIT_OWNER(a7800_state, a7800p )
- /* sound hardware */
- MCFG_SOUND_MODIFY("pokey")
- MCFG_SOUND_CLOCK(CLK_PAL)
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
-
/* devices */
MCFG_DEVICE_REMOVE("riot")
MCFG_DEVICE_ADD("riot", RIOT6532, CLK_PAL)
@@ -1213,8 +1333,7 @@ MACHINE_CONFIG_END
***************************************************************************/
ROM_START( a7800 )
- ROM_REGION(0x100000, "maincpu", 0)
- ROM_FILL(0x0000, 0x100000, 0xff)
+ ROM_REGION(0x10000, "maincpu", ROMREGION_ERASEFF)
ROM_SYSTEM_BIOS( 0, "a7800", "Atari 7800" )
ROMX_LOAD("7800.u7", 0xf000, 0x1000, CRC(5d13730c) SHA1(d9d134bb6b36907c615a594cc7688f7bfcef5b43), ROM_BIOS(1))
ROM_SYSTEM_BIOS( 1, "a7800pr", "Atari 7800 (prototype with Asteroids)" )
@@ -1222,12 +1341,33 @@ ROM_START( a7800 )
ROM_END
ROM_START( a7800p )
- ROM_REGION(0x100000, "maincpu", 0)
- ROM_FILL(0x0000, 0x100000, 0xff)
+ ROM_REGION(0x10000, "maincpu", ROMREGION_ERASEFF)
ROM_LOAD("7800pal.rom", 0xc000, 0x4000, CRC(d5b61170) SHA1(5a140136a16d1d83e4ff32a19409ca376a8df874))
ROM_END
+/***************************************************************************
+ DRIVER INIT
+ ***************************************************************************/
+
+DRIVER_INIT_MEMBER(a7800_state,a7800_ntsc)
+{
+ m_ispal = FALSE;
+ m_lines = 263;
+ m_p1_one_button = 1;
+ m_p2_one_button = 1;
+}
+
+
+DRIVER_INIT_MEMBER(a7800_state,a7800_pal)
+{
+ m_ispal = TRUE;
+ m_lines = 313;
+ m_p1_one_button = 1;
+ m_p2_one_button = 1;
+}
+
+
/***************************************************************************
GAME DRIVERS
***************************************************************************/
diff --git a/src/mess/includes/a7800.h b/src/mess/includes/a7800.h
index d37adeaf488..b8754be5f05 100644
--- a/src/mess/includes/a7800.h
+++ b/src/mess/includes/a7800.h
@@ -8,9 +8,9 @@
#define A7800_H_
#include "machine/6532riot.h"
-#include "sound/pokey.h"
#include "sound/tiasound.h"
#include "sound/tiaintf.h"
+#include "bus/a7800/a78_slot.h"
class a7800_state : public driver_device
@@ -19,36 +19,26 @@ public:
a7800_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
- m_pokey(*this, "pokey"),
m_tia(*this, "tia"),
- m_region_maincpu(*this, "maincpu"),
- m_bank1(*this, "bank1"),
- m_bank2(*this, "bank2"),
- m_bank3(*this, "bank3"),
- m_bank4(*this, "bank4"),
- m_bank5(*this, "bank5"),
- m_bank6(*this, "bank6"),
- m_bank7(*this, "bank7"),
m_io_joysticks(*this, "joysticks"),
m_io_buttons(*this, "buttons"),
m_io_vblank(*this, "vblank"),
m_io_console_buttons(*this, "console_buttons"),
- m_bank10(NULL),
- m_bank11(NULL),
+ m_cartslot(*this, "cartslot"),
m_screen(*this, "screen") { }
int m_lines;
int m_ispal;
- unsigned char *m_cart_bkup;
- unsigned char *m_bios_bkup;
+
int m_ctrl_lock;
int m_ctrl_reg;
int m_maria_flag;
- unsigned char *m_cartridge_rom;
- UINT16 m_cart_type;
- UINT32 m_cart_size;
- unsigned char m_stick_type;
- UINT8 *m_ROM;
+ int m_p1_one_button;
+ int m_p2_one_button;
+ int m_bios_enabled;
+
+ UINT8 *m_bios;
+
int m_maria_palette[32];
int m_line_ram[2][160];
int m_active_buffer;
@@ -71,18 +61,16 @@ public:
int m_maria_nmi;
unsigned int m_maria_charbase;
bitmap_ind16 m_bitmap;
- int m_p1_one_button;
- int m_p2_one_button;
- DECLARE_WRITE8_MEMBER(a7800_RAM0_w);
- DECLARE_WRITE8_MEMBER(a7800_cart_w);
- DECLARE_READ8_MEMBER(a7800_TIA_r);
- DECLARE_WRITE8_MEMBER(a7800_TIA_w);
- DECLARE_READ8_MEMBER(a7800_MARIA_r);
- DECLARE_WRITE8_MEMBER(a7800_MARIA_w);
- void a7800_driver_init(int ispal, int lines);
+ DECLARE_READ8_MEMBER(bios_or_cart_r);
+ DECLARE_WRITE8_MEMBER(ram0_w);
+ DECLARE_READ8_MEMBER(tia_r);
+ DECLARE_WRITE8_MEMBER(tia_w);
+ DECLARE_READ8_MEMBER(maria_r);
+ DECLARE_WRITE8_MEMBER(maria_w);
DECLARE_DRIVER_INIT(a7800_pal);
DECLARE_DRIVER_INIT(a7800_ntsc);
+ virtual void machine_start();
virtual void machine_reset();
virtual void video_start();
DECLARE_PALETTE_INIT(a7800);
@@ -94,37 +82,19 @@ public:
DECLARE_READ8_MEMBER(riot_console_button_r);
DECLARE_WRITE8_MEMBER(riot_button_pullup_w);
- DECLARE_DEVICE_IMAGE_LOAD_MEMBER( a7800_cart );
-
protected:
required_device m_maincpu;
- required_device m_pokey;
required_device m_tia;
- required_memory_region m_region_maincpu;
- required_memory_bank m_bank1;
- required_memory_bank m_bank2;
- required_memory_bank m_bank3;
- required_memory_bank m_bank4;
- required_memory_bank m_bank5;
- required_memory_bank m_bank6;
- required_memory_bank m_bank7;
required_ioport m_io_joysticks;
required_ioport m_io_buttons;
required_ioport m_io_vblank;
required_ioport m_io_console_buttons;
- memory_bank *m_bank10;
- memory_bank *m_bank11;
+ required_device m_cartslot;
required_device m_screen;
void maria_draw_scanline();
int is_holey(unsigned int addr);
int write_line_ram(int addr, UINT8 offset, int pal);
- int a7800_verify_cart(char header[128]);
- UINT16 a7800_get_pcb_id(const char *pcb);
};
-/*----------- defined in machine/a7800.c -----------*/
-
-void a7800_partialhash(hash_collection &dest, const unsigned char *data, unsigned long length, const char *functions);
-
-#endif /* A7800_H_ */
+#endif
diff --git a/src/mess/machine/a7800.c b/src/mess/machine/a7800.c
deleted file mode 100644
index 6fd3e5a22c5..00000000000
--- a/src/mess/machine/a7800.c
+++ /dev/null
@@ -1,539 +0,0 @@
-/***************************************************************************
-
- a7800.c
-
- Machine file to handle emulation of the Atari 7800.
-
- 5-Nov-2003 npwoods Cleanups
-
- 14-May-2002 kubecj Fixed Fatal Run - adding simple riot timer helped.
- maybe someone with knowledge should add full fledged
- riot emulation?
-
- 13-May-2002 kubecj Fixed a7800_cart_type not to be too short ;-D
- fixed for loading of bank6 cart (uh, I hope)
- fixed for loading 64k supercarts
- fixed for using PAL bios
- cart not needed when in PAL mode
- added F18 Hornet bank select type
- added Activision bank select type
- 19-Feb-2010 DanB Added return values for TIA collision registers
-
- 04-Apr-2014 Mike Saarna Fix to controller button RIOT behavior and
- expanded cart handling (bit 05).
-***************************************************************************/
-
-#include "emu.h"
-#include "includes/a7800.h"
-#include "cpu/m6502/m6502.h"
-
-
-
-/* local */
-
-
-
-/***************************************************************************
- 6532 RIOT
-***************************************************************************/
-
-READ8_MEMBER(a7800_state::riot_joystick_r)
-{
- return m_io_joysticks->read();
-}
-
-READ8_MEMBER(a7800_state::riot_console_button_r)
-{
- return m_io_console_buttons->read();
-}
-
-WRITE8_MEMBER(a7800_state::riot_button_pullup_w)
-{
- if(m_maincpu->space(AS_PROGRAM).read_byte(0x283) & 0x04)
- m_p1_one_button = data & 0x04; // pin 6 of the controller port is held high by the riot chip when reading two-button controllers (from schematic)
- if(m_maincpu->space(AS_PROGRAM).read_byte(0x283) & 0x10)
- m_p2_one_button = data & 0x10;
-}
-
-/***************************************************************************
- DRIVER INIT
-***************************************************************************/
-
-void a7800_state::a7800_driver_init(int ispal, int lines)
-{
- address_space& space = m_maincpu->space(AS_PROGRAM);
- m_ROM = m_region_maincpu->base();
- m_ispal = ispal;
- m_lines = lines;
- m_p1_one_button = 1;
- m_p2_one_button = 1;
-
- /* standard banks */
- m_bank5->set_base(&m_ROM[0x2040]); /* RAM0 */
- m_bank6->set_base(&m_ROM[0x2140]); /* RAM1 */
- m_bank7->set_base(&m_ROM[0x2000]); /* MAINRAM */
-
- /* Brutal hack put in as a consequence of new memory system; fix this */
- space.install_readwrite_bank(0x0480, 0x04FF,"bank10");
- m_bank10 = membank("bank10");
- m_bank10->set_base(m_ROM + 0x0480);
- space.install_readwrite_bank(0x1800, 0x27FF, "bank11");
- m_bank11 = membank("bank11");
- m_bank11->set_base(m_ROM + 0x1800);
-
- m_bios_bkup = NULL;
- m_cart_bkup = NULL;
-
- /* Allocate memory for BIOS bank switching */
- m_bios_bkup = auto_alloc_array_clear(machine(), UINT8, 0x4000);
- m_cart_bkup = auto_alloc_array(machine(), UINT8, 0x4000);
-
- /* save the BIOS so we can switch it in and out */
- memcpy( m_bios_bkup, m_ROM + 0xC000, 0x4000 );
-
- /* Initialize cart area to "no data" */
- memset( m_cart_bkup, 0xFF, 0x4000 );
-
- /* defaults for PAL bios without cart */
- m_cart_type = 0;
- m_stick_type = 1;
-}
-
-
-DRIVER_INIT_MEMBER(a7800_state,a7800_ntsc)
-{
- a7800_driver_init(FALSE, 263);
-}
-
-
-DRIVER_INIT_MEMBER(a7800_state,a7800_pal)
-{
- a7800_driver_init(TRUE, 313);
-}
-
-
-void a7800_state::machine_reset()
-{
- UINT8 *memory;
- address_space& space = m_maincpu->space(AS_PROGRAM);
-
- m_ctrl_lock = 0;
- m_ctrl_reg = 0;
- m_maria_flag = 0;
-
- /* set banks to default states */
- memory = m_region_maincpu->base();
- if(m_cart_type & 0x20) //supercart bankram
- m_bank1->set_base(memory + 0xf0000 );
- else
- m_bank1->set_base(memory + 0x4000 );
- m_bank2->set_base(memory + 0x8000 );
- m_bank3->set_base(memory + 0xA000 );
- m_bank4->set_base(memory + 0xC000 );
-
- /* pokey cartridge */
- if (m_cart_type & 0x01)
- {
- space.install_readwrite_handler(0x0450, 0x045F, read8_delegate(FUNC(pokey_device::read),(pokey_device*)m_pokey), write8_delegate(FUNC(pokey_device::write),(pokey_device*)m_pokey));
- }
-}
-
-
-/***************************************************************************
- CARTRIDGE HANDLING
-***************************************************************************/
-
-#define MBANK_TYPE_ATARI 0x0000
-#define MBANK_TYPE_ACTIVISION 0x0100
-#define MBANK_TYPE_ABSOLUTE 0x0200
-
-/* Header format
-0 Header version - 1 byte
-1..16 "ATARI7800 " - 16 bytes
-17..48 Cart title - 32 bytes
-49..52 data length - 4 bytes
-53..54 cart type - 2 bytes
- bit 0 0x01 - pokey cart
- bit 1 0x02 - supercart bank switched
- bit 2 0x04 - supercart RAM at $4000
- bit 3 0x08 - additional state->m_ROM at $4000
- bit 4 0x10 - bank 6 at $4000
- bit 5 0x20 - supercart banked RAM
-
- bit 8-15 - Special
- 0 = Normal cart
- 1 = Absolute (F18 Hornet)
- 2 = Activision
-
-55 controller 1 type - 1 byte
-56 controller 2 type - 1 byte
- 0 = None
- 1 = Joystick
- 2 = Light Gun
-57 0 = NTSC/1 = PAL
-
-100..127 "ACTUAL CART DATA STARTS HERE" - 28 bytes
-
-Versions:
- Version 0: Initial release
- Version 1: Added PAL/NTSC bit. Added Special cart byte.
- Changed 53 bit 2, added bit 3
-
-*/
-void a7800_partialhash(hash_collection &dest, const unsigned char *data,
- unsigned long length, const char *functions)
-{
- if (length <= 128)
- return;
- dest.compute(&data[128], length - 128, functions);
-}
-
-
-int a7800_state::a7800_verify_cart(char header[128])
-{
- const char* tag = "ATARI7800";
-
- if( strncmp( tag, header + 1, 9 ) )
- {
- logerror("Not a valid A7800 image\n");
- return IMAGE_VERIFY_FAIL;
- }
-
- logerror("returning ID_OK\n");
- return IMAGE_VERIFY_PASS;
-}
-
-
-struct a7800_pcb
-{
- const char *pcb_name;
- UINT16 type;
-};
-
-// sketchy support for a7800 cart types
-// TODO: proper emulation of the banking based on xml
-// (and on the real cart layout!)
-static const a7800_pcb pcb_list[] =
-{
- { "ABSOLUTE", MBANK_TYPE_ABSOLUTE },
- { "ACTIVISION", MBANK_TYPE_ACTIVISION },
- { "TYPE-0", 0x0 },
- { "TYPE-1", 0x1 },
- { "TYPE-2", 0x2 },
- { "TYPE-3", 0x3 },
- { "TYPE-6", 0x6 },
- { "TYPE-A", 0xa },
- { "TYPE-XM", 0xb }, /* XM cart? (dkongxm) */
- { 0 }
-};
-
-UINT16 a7800_state::a7800_get_pcb_id(const char *pcb)
-{
- int i;
-
- for (i = 0; i < ARRAY_LENGTH(pcb_list); i++)
- {
- if (!core_stricmp(pcb_list[i].pcb_name, pcb))
- return pcb_list[i].type;
- }
-
- return 0;
-}
-
-DEVICE_IMAGE_LOAD_MEMBER( a7800_state, a7800_cart )
-{
- UINT32 len = 0, start = 0;
- unsigned char header[128];
- UINT8 *memory = m_region_maincpu->base();
- const char *pcb_name;
-
- // detect cart type either from xml or from header
- if (image.software_entry() == NULL)
- {
- /* Load and decode the header */
- image.fread(header, 128);
-
- /* Check the cart */
- if( a7800_verify_cart((char *)header) == IMAGE_VERIFY_FAIL)
- return IMAGE_INIT_FAIL;
-
- len =(header[49] << 24) |(header[50] << 16) |(header[51] << 8) | header[52];
- m_cart_size = len;
-
- m_cart_type =(header[53] << 8) | header[54];
- m_stick_type = header[55];
- logerror("Cart type: %x\n", m_cart_type);
-
- /* For now, if game support stick and gun, set it to stick */
- if (m_stick_type == 3)
- m_stick_type = 1;
- }
- else
- {
- len = image.get_software_region_length("rom");
- m_cart_size = len;
- // TODO: add stick/gun support to xml!
- m_stick_type = 1;
- if ((pcb_name = image.get_feature("pcb_type")) == NULL)
- m_cart_type = 0;
- else
- m_cart_type = a7800_get_pcb_id(pcb_name);
- }
-
- if (m_cart_type == 0 || m_cart_type == 1)
- {
- /* Normal Cart */
- start = 0x10000 - len;
- m_cartridge_rom = memory + start;
- if (image.software_entry() == NULL)
- image.fread(m_cartridge_rom, len);
- else
- memcpy(m_cartridge_rom, image.get_software_region("rom"), len);
- }
- else if (m_cart_type & 0x02)
- {
- /* Super Cart */
- /* Extra ROM at $4000 */
- if (m_cart_type & 0x08)
- {
- if (image.software_entry() == NULL)
- image.fread(memory + 0x4000, 0x4000);
- else
- memcpy(memory + 0x4000, image.get_software_region("rom"), 0x4000);
- len -= 0x4000;
- start = 0x4000;
- }
-
- m_cartridge_rom = memory + 0x10000;
- if (image.software_entry() == NULL)
- image.fread(m_cartridge_rom, len);
- else
- memcpy(m_cartridge_rom, image.get_software_region("rom") + start, len);
-
- /* bank 0 */
- memcpy(memory + 0x8000, memory + 0x10000, 0x4000);
-
- /* last bank */
- memcpy(memory + 0xC000, memory + 0x10000 + len - 0x4000, 0x4000);
-
- /* fixed 2002/05/13 kubecj
- there was 0x08, I added also two other cases.
- Now, it loads bank n-2 to $4000 if it's empty.
- */
-
- /* bank n-2 */
- if (!(m_cart_type & 0x0d))
- {
- memcpy(memory + 0x4000, memory + 0x10000 + len - 0x8000, 0x4000);
- }
- }
- else if (m_cart_type == MBANK_TYPE_ABSOLUTE)
- {
- /* F18 Hornet */
-
- logerror("Cart type: %x Absolute\n",m_cart_type);
-
- m_cartridge_rom = memory + 0x10000;
- if (image.software_entry() == NULL)
- image.fread(m_cartridge_rom, len);
- else
- memcpy(m_cartridge_rom, image.get_software_region("rom") + start, len);
-
- /* bank 0 */
- memcpy(memory + 0x4000, memory + 0x10000, 0x4000);
-
- /* last bank */
- memcpy(memory + 0x8000, memory + 0x18000, 0x8000);
- }
- else if (m_cart_type == MBANK_TYPE_ACTIVISION)
- {
- /* Activision */
-
- logerror("Cart type: %x Activision\n",m_cart_type);
-
- m_cartridge_rom = memory + 0x10000;
- if (image.software_entry() == NULL)
- image.fread(m_cartridge_rom, len);
- else
- memcpy(m_cartridge_rom, image.get_software_region("rom") + start, len);
-
- /* bank 0 */
- memcpy(memory + 0xa000, memory + 0x10000, 0x4000);
-
- /* bank6 hi */
- memcpy(memory + 0x4000, memory + 0x2a000, 0x2000);
-
- /* bank6 lo */
- memcpy(memory + 0x6000, memory + 0x28000, 0x2000);
-
- /* bank7 hi */
- memcpy(memory + 0x8000, memory + 0x2e000, 0x2000);
-
- /* bank7 lo */
- memcpy(memory + 0xe000, memory + 0x2c000, 0x2000);
-
- }
-
- memcpy(m_cart_bkup, memory + 0xc000, 0x4000);
- memcpy(memory + 0xc000, m_bios_bkup, 0x4000);
- return IMAGE_INIT_PASS;
-}
-
-
-WRITE8_MEMBER(a7800_state::a7800_RAM0_w)
-{
- m_ROM[0x2040 + offset] = data;
- m_ROM[0x40 + offset] = data;
-}
-
-
-WRITE8_MEMBER(a7800_state::a7800_cart_w)
-{
- UINT8 *memory = m_region_maincpu->base();
-
- if(offset < 0x4000)
- {
- if(m_cart_type & 0x04)
- {
- //adjust write location if supercart bankram is in use
- if(m_cart_type & 0x20)
- {
- UINT8 *currentbank1 = (UINT8 *)m_bank1->base();
- currentbank1[offset] = data;
- }
- else
- m_ROM[0x4000 + offset] = data;
- }
- else if(m_cart_type & 0x01)
- {
- m_pokey->write(space, offset, data);
- }
- else
- {
- logerror("Undefined write A: %x",offset + 0x4000);
- }
- }
-
- if(( m_cart_type & 0x02 ) &&( offset >= 0x4000 ) )
- {
- /* check if bankram is used */
- if( m_cart_type & 0x20 )
- {
- m_bank1->set_base(memory + 0xf0000+((data & 0x20)<<9));
- }
- /* fix for 64kb supercart */
- if( m_cart_size == 0x10000 )
- {
- data &= 0x03;
- }
- else if( m_cart_size == 0x40000 )
- {
- data &= 0x0f;
- }
- else if( m_cart_size == 0x80000 )
- {
- data &= 0x1f;
- }
- else
- {
- data &= 0x07;
- }
- m_bank2->set_base(memory + 0x10000 + (data << 14));
- m_bank3->set_base(memory + 0x12000 + (data << 14));
- /* logerror("BANK SEL: %d\n",data); */
- }
- else if(( m_cart_type == MBANK_TYPE_ABSOLUTE ) &&( offset == 0x4000 ) )
- {
- /* F18 Hornet */
- /*logerror( "F18 BANK SEL: %d\n", data );*/
- if( data & 1 )
- {
- m_bank1->set_base(memory + 0x10000 );
- }
- else if( data & 2 )
- {
- m_bank1->set_base(memory + 0x14000 );
- }
- }
- else if(( m_cart_type == MBANK_TYPE_ACTIVISION ) &&( offset >= 0xBF80 ) )
- {
- /* Activision */
- data = offset & 7;
-
- /*logerror( "Activision BANK SEL: %d\n", data );*/
-
- m_bank3->set_base(memory + 0x10000 + ( data << 14 ) );
- m_bank4->set_base(memory + 0x12000 + ( data << 14 ) );
- }
-}
-
-
-/***************************************************************************
- TIA
-***************************************************************************/
-
-READ8_MEMBER(a7800_state::a7800_TIA_r)
-{
- switch(offset & 0x0f)
- {
- case 0x00:
- case 0x01:
- case 0x02:
- case 0x03:
- case 0x04:
- case 0x05:
- case 0x06:
- case 0x07:
- /* Even though the 7800 doesn't use the TIA graphics the collision registers should
- still return a reasonable value */
- return 0x00;
- case 0x08:
- return((m_io_buttons->read() & 0x02) << 6);
- case 0x09:
- return((m_io_buttons->read() & 0x08) << 4);
- case 0x0A:
- return((m_io_buttons->read() & 0x01) << 7);
- case 0x0B:
- return((m_io_buttons->read() & 0x04) << 5);
- case 0x0c:
- if(((m_io_buttons->read() & 0x08) ||(m_io_buttons->read() & 0x02)) && m_p1_one_button)
- return 0x00;
- else
- return 0x80;
- case 0x0d:
- if(((m_io_buttons->read() & 0x01) ||(m_io_buttons->read() & 0x04)) && m_p2_one_button)
- return 0x00;
- else
- return 0x80;
- default:
- logerror("undefined TIA read %x\n",offset);
-
- }
- return 0xFF;
-}
-
-
-WRITE8_MEMBER(a7800_state::a7800_TIA_w)
-{
- if (offset<0x20) { //INPTCTRL covers TIA registers 0x00-0x1F until locked
- if(data & 0x01)
- {
- if ((m_ctrl_lock)&&(offset==0x01))
- m_maria_flag=1;
- else if (!m_ctrl_lock)
- m_maria_flag=1;
- }
- if(!m_ctrl_lock)
- {
- m_ctrl_lock = data & 0x01;
- m_ctrl_reg = data;
-
- if (data & 0x04)
- memcpy( m_ROM + 0xC000, m_cart_bkup, 0x4000 );
- else
- memcpy( m_ROM + 0xC000, m_bios_bkup, 0x4000 );
- }
- }
- m_tia->tia_sound_w(space, offset, data);
- m_ROM[offset] = data;
-}
diff --git a/src/mess/mess.mak b/src/mess/mess.mak
index 55df245aeb1..b1c259278bc 100644
--- a/src/mess/mess.mak
+++ b/src/mess/mess.mak
@@ -560,6 +560,7 @@ MACHINES += DIABLO_HD
BUSES += A1BUS
BUSES += A2BUS
+BUSES += A7800
BUSES += ABCBUS
BUSES += ABCKB
BUSES += ADAM
@@ -1023,7 +1024,6 @@ $(MESSOBJ)/at.a: \
$(MESSOBJ)/atari.a: \
$(MESS_MACHINE)/atarifdc.o \
$(MESS_DRIVERS)/atari400.o \
- $(MESS_MACHINE)/a7800.o \
$(MESS_DRIVERS)/a7800.o \
$(MESS_VIDEO)/a7800.o \
$(MESS_DRIVERS)/a2600.o \
diff --git a/src/mess/video/a7800.c b/src/mess/video/a7800.c
index c3480460d8f..4edd2091b39 100644
--- a/src/mess/video/a7800.c
+++ b/src/mess/video/a7800.c
@@ -28,7 +28,6 @@
#include "emu.h"
#include "cpu/m6502/m6502.h"
-
#include "includes/a7800.h"
@@ -345,7 +344,7 @@ UINT32 a7800_state::screen_update_a7800(screen_device &screen, bitmap_ind16 &bit
/****** MARIA ***************************************/
-READ8_MEMBER(a7800_state::a7800_MARIA_r)
+READ8_MEMBER(a7800_state::maria_r)
{
switch (offset)
{
@@ -358,7 +357,7 @@ READ8_MEMBER(a7800_state::a7800_MARIA_r)
}
}
-WRITE8_MEMBER(a7800_state::a7800_MARIA_w)
+WRITE8_MEMBER(a7800_state::maria_w)
{
int i;