(MESS) a7800.c progress: [Fabio Priuli]

- Rewritten cart emulation to use slot devices
- Removed POKEY chip from the main unit since it was inside
  the carts (of course it gets enabled when you launch a game
  who contained it in its cart)
- Added support for the High Score cart as a passthru cart: when 
  you mount hiscore, a -cart2 switch will become available to mount
  the game you want to play
- Properly implemented XBoarD and XM expansions as
  passthru carts as well, so that new syntax to run dkxm.a78 is
  "mess a7800 -cart xm -cart2 path\to\games\dkxm.a78"
  High Score support for XM shall work as well.
- Big clean up of the driver, simplifying memory map, removing
  writes to ROM, etc.


Out of whatsnew: In conclusion, a7800.c has been brought into the new millennium ;-)
This commit is contained in:
Fabio Priuli 2014-08-25 11:15:32 +00:00
parent fb3575054e
commit a16673b284
17 changed files with 2190 additions and 658 deletions

10
.gitattributes vendored
View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -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<a78_cart_slot_device>;
//-------------------------------------------------
// 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<device_a78_cart_interface *>(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

View File

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

View File

@ -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::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);
}

View File

@ -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<a78_cart_slot_device> m_hscslot;
};
// device type definition
extern const device_type A78_HISCORE;
#endif

512
src/emu/bus/a7800/rom.c Normal file
View File

@ -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<a78_rom_device>;
const device_type A78_ROM_SG = &device_creator<a78_rom_sg_device>;
const device_type A78_ROM_POKEY = &device_creator<a78_rom_pokey_device>;
const device_type A78_ROM_SG_POKEY = &device_creator<a78_rom_sg_pokey_device>;
const device_type A78_ROM_SG_RAM = &device_creator<a78_rom_sg_ram_device>;
const device_type A78_ROM_BANKRAM = &device_creator<a78_rom_bankram_device>;
const device_type A78_ROM_SG_9BANKS = &device_creator<a78_rom_sg_9banks_device>;
const device_type A78_ROM_XM = &device_creator<a78_rom_xm_device>;
const device_type A78_ROM_ABSOLUTE = &device_creator<a78_rom_abs_device>;
const device_type A78_ROM_ACTIVISION = &device_creator<a78_rom_act_device>;
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;
}

217
src/emu/bus/a7800/rom.h Normal file
View File

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

178
src/emu/bus/a7800/xboard.c Normal file
View File

@ -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<a78_xboard_device>;
const device_type A78_XM = &device_creator<a78_xm_device>;
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];
}

View File

@ -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<a78_cart_slot_device> m_xbslot;
required_device<pokey_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

View File

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

View File

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

View File

@ -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<cpu_device> m_maincpu;
required_device<pokey_device> m_pokey;
required_device<tia_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<a78_cart_slot_device> m_cartslot;
required_device<screen_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

View File

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

View File

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

View File

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