mame/src/mess/machine/apple2.c
2013-06-04 07:57:44 +00:00

2323 lines
60 KiB
C

/***************************************************************************
apple2.c
Machine file to handle emulation of the Apple II series.
TODO: Verify correctness of C08X switches.
- need to do double-read before write-enable RAM
***************************************************************************/
#include "emu.h"
#include "cpu/m6502/m6502.h"
#include "includes/apple2.h"
#include "machine/a2bus.h"
#include "machine/ay3600.h"
#include "machine/applefdc.h"
#include "machine/sonydriv.h"
#include "machine/appldriv.h"
#include "imagedev/flopdrv.h"
#include "imagedev/cassette.h"
#include "sound/speaker.h"
#include "debugger.h"
#ifdef MAME_DEBUG
#define VERBOSE 1
#else
#define VERBOSE 0
#endif /* MAME_DEBUG */
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
#define PROFILER_C00X PROFILER_USER2
#define PROFILER_C01X PROFILER_USER2
#define PROFILER_C08X PROFILER_USER2
#define PROFILER_A2INT PROFILER_USER2
/* -----------------------------------------------------------------------
* New Apple II memory manager
* ----------------------------------------------------------------------- */
READ8_MEMBER(apple2_state::read_floatingbus)
{
return apple2_getfloatingbusvalue();
}
void apple2_state::apple2_setup_memory(const apple2_memmap_config *config)
{
m_mem_config = *config;
m_current_meminfo = NULL;
apple2_update_memory();
}
void apple2_state::apple2_update_memory()
{
address_space& space = m_maincpu->space(AS_PROGRAM);
int i, bank;
char rbank[10], wbank[10];
int full_update = 0;
apple2_meminfo meminfo;
read8_delegate *rh;
write8_delegate *wh;
offs_t begin, end_r, end_w;
UINT8 *rbase, *wbase;
UINT32 offset;
bank_disposition_t bank_disposition;
int wh_nop = 0;
/* need to build list of current info? */
if (!m_current_meminfo)
{
for (i = 0; m_mem_config.memmap[i].end; i++)
;
m_current_meminfo = auto_alloc_array(machine(), apple2_meminfo, i);
full_update = 1;
}
/* loop through the entire memory map */
bank = m_mem_config.first_bank;
for (i = 0; m_mem_config.memmap[i].get_meminfo; i++)
{
/* retrieve information on this entry */
memset(&meminfo, 0, sizeof(meminfo));
m_mem_config.memmap[i].get_meminfo(machine(),m_mem_config.memmap[i].begin, m_mem_config.memmap[i].end, &meminfo);
bank_disposition = m_mem_config.memmap[i].bank_disposition;
/* do we need to memory reading? */
if (full_update
|| (meminfo.read_mem != m_current_meminfo[i].read_mem)
|| (meminfo.read_handler != m_current_meminfo[i].read_handler))
{
rbase = NULL;
sprintf(rbank,"bank%d",bank);
begin = m_mem_config.memmap[i].begin;
end_r = m_mem_config.memmap[i].end;
rh = NULL;
LOG(("apple2_update_memory(): Updating RD {%06X..%06X} [#%02d] --> %08X\n",
begin, end_r, bank, meminfo.read_mem));
/* read handling */
if (meminfo.read_handler)
{
/* handler */
rh = meminfo.read_handler;
}
else if (meminfo.read_mem == APPLE2_MEM_FLOATING)
{
/* floating RAM */
rh = &read_delegates_master[0];
}
else if ((meminfo.read_mem & 0xC0000000) == APPLE2_MEM_AUX)
{
/* auxillary memory */
assert(m_mem_config.auxmem);
offset = meminfo.read_mem & APPLE2_MEM_MASK;
rbase = &m_mem_config.auxmem[offset];
}
else if ((meminfo.read_mem & 0xC0000000) == APPLE2_MEM_SLOT)
{
// slots 1-2
if ((meminfo.write_mem & APPLE2_MEM_MASK) == 0)
{
rh = &read_delegates_master[1];
}
else if ((meminfo.write_mem & APPLE2_MEM_MASK) == 0x200)
{ // slot 3
rh = &read_delegates_master[2];
}
else if ((meminfo.write_mem & APPLE2_MEM_MASK) == 0x300)
{ // slots 4-7
rh = &read_delegates_master[3];
}
else
{
printf("ERROR: Unhandled case for APPLE2_MEM_SLOT write_mem = %x!\n", (meminfo.write_mem & APPLE2_MEM_MASK));
}
}
else if ((meminfo.read_mem & 0xC0000000) == APPLE2_MEM_ROM)
{
/* ROM */
offset = meminfo.read_mem & APPLE2_MEM_MASK;
rbase = &m_rom[offset % m_rom_length];
}
else
{
/* RAM */
if (end_r >= m_ram->size())
end_r = m_ram->size() - 1;
offset = meminfo.read_mem & APPLE2_MEM_MASK;
if (end_r >= begin)
rbase = &m_ram->pointer()[offset];
}
/* install the actual handlers */
if (begin <= end_r) {
if (rh) {
space.install_read_handler(begin, end_r, *rh);
} else {
space.install_read_bank(begin, end_r, rbank);
}
}
/* did we 'go past the end?' */
if (end_r < m_mem_config.memmap[i].end)
space.nop_read(end_r + 1, m_mem_config.memmap[i].end);
/* set the memory bank */
if (rbase)
{
membank(rbank)->set_base(rbase);
}
/* record the current settings */
m_current_meminfo[i].read_mem = meminfo.read_mem;
m_current_meminfo[i].read_handler = meminfo.read_handler;
}
/* do we need to memory writing? */
if (full_update
|| (meminfo.write_mem != m_current_meminfo[i].write_mem)
|| (meminfo.write_handler != m_current_meminfo[i].write_handler))
{
wbase = NULL;
if (bank_disposition == A2MEM_MONO)
sprintf(wbank,"bank%d",bank);
else if (bank_disposition == A2MEM_DUAL)
sprintf(wbank,"bank%d",bank+1);
begin = m_mem_config.memmap[i].begin;
end_w = m_mem_config.memmap[i].end;
wh = NULL;
LOG(("apple2_update_memory(): Updating WR {%06X..%06X} [#%02d] --> %08X\n",
begin, end_w, bank, meminfo.write_mem));
/* write handling */
if (meminfo.write_handler)
{
/* handler */
wh = meminfo.write_handler;
}
else if ((meminfo.write_mem & 0xC0000000) == APPLE2_MEM_AUX)
{
/* auxillary memory */
assert(m_mem_config.auxmem);
offset = meminfo.write_mem & APPLE2_MEM_MASK;
wbase = &m_mem_config.auxmem[offset];
}
else if ((meminfo.write_mem & 0xC0000000) == APPLE2_MEM_SLOT)
{
/* slot RAM/ROM */
// slots 1-2
if ((meminfo.write_mem & APPLE2_MEM_MASK) == 0)
{
wh = &write_delegates_master[0];
}
else if ((meminfo.write_mem & APPLE2_MEM_MASK) == 0x200)
{ // slot 3
wh = &write_delegates_master[1];
}
else if ((meminfo.write_mem & APPLE2_MEM_MASK) == 0x300)
{ // slots 4-7
wh = &write_delegates_master[2];
}
}
else if ((meminfo.write_mem & 0xC0000000) == APPLE2_MEM_ROM)
{
/* ROM */
wh_nop = 1;
}
else
{
/* RAM */
if (end_w >= m_ram->size())
end_w = m_ram->size() - 1;
offset = meminfo.write_mem & APPLE2_MEM_MASK;
if (end_w >= begin)
wbase = &m_ram->pointer()[offset];
}
/* install the actual handlers */
if (begin <= end_w) {
if (wh) {
space.install_write_handler(begin, end_w, *wh);
} else {
if (wh_nop) {
space.nop_write(begin, end_w);
} else {
space.install_write_bank(begin, end_w, wbank);
}
}
}
/* did we 'go past the end?' */
if (end_w < m_mem_config.memmap[i].end)
space.nop_write(end_w + 1, m_mem_config.memmap[i].end);
/* set the memory bank */
if (wbase)
{
membank(wbank)->set_base(wbase);
}
/* record the current settings */
m_current_meminfo[i].write_mem = meminfo.write_mem;
m_current_meminfo[i].write_handler = meminfo.write_handler;
}
bank += bank_disposition;
}
}
void apple2_state::apple2_update_memory_postload()
{
apple2_update_memory();
}
/* -----------------------------------------------------------------------
* Apple II memory map
* ----------------------------------------------------------------------- */
READ8_MEMBER(apple2_state::apple2_c0xx_r)
{
if(!space.debugger_access())
{
read8_delegate handlers[] =
{
read8_delegate(FUNC(apple2_state::apple2_c00x_r), this),
read8_delegate(FUNC(apple2_state::apple2_c01x_r), this),
read8_delegate(FUNC(apple2_state::apple2_c02x_r), this),
read8_delegate(FUNC(apple2_state::apple2_c03x_r), this),
read8_delegate(FUNC(apple2_state::apple2_c03x_r), this), // not called here, handled elsewhere
read8_delegate(FUNC(apple2_state::apple2_c05x_r), this),
read8_delegate(FUNC(apple2_state::apple2_c06x_r), this),
read8_delegate(FUNC(apple2_state::apple2_c07x_r), this)
};
offset &= 0x7F;
/* normal handler */
if (offset / 0x10 != 4)
{
return handlers[offset / 0x10](space, offset % 0x10, 0);
}
}
return 0;
}
WRITE8_MEMBER(apple2_state::apple2_c0xx_w)
{
write8_delegate handlers[] =
{
write8_delegate(FUNC(apple2_state::apple2_c00x_w), this),
write8_delegate(FUNC(apple2_state::apple2_c01x_w), this),
write8_delegate(FUNC(apple2_state::apple2_c02x_w), this),
write8_delegate(FUNC(apple2_state::apple2_c03x_w), this),
write8_delegate(FUNC(apple2_state::apple2_c03x_w), this), // unused
write8_delegate(FUNC(apple2_state::apple2_c05x_w), this),
write8_delegate(FUNC(apple2_state::apple2_c05x_w), this), // unused
write8_delegate(FUNC(apple2_state::apple2_c07x_w), this)
};
offset &= 0x7F;
/* normal handler */
if (((offset / 0x10) != 4) && (offset / 0x10) != 6)
{
handlers[offset / 0x10](space, offset % 0x10, data, 0);
}
}
READ8_MEMBER(apple2_state::apple2_c080_r)
{
if(!space.debugger_access())
{
device_a2bus_card_interface *slotdevice;
offset &= 0x7F;
/* now identify the device */
slotdevice = m_a2bus->get_a2bus_card(offset / 0x10);
/* and if we can, read from the slot */
if (slotdevice != NULL)
{
return slotdevice->read_c0nx(space, offset % 0x10);
}
}
return 0;
}
WRITE8_MEMBER(apple2_state::apple2_c080_w)
{
device_a2bus_card_interface *slotdevice;
offset &= 0x7F;
/* now identify the device */
slotdevice = m_a2bus->get_a2bus_card(offset / 0x10);
/* and if we can, write to the slot */
if (slotdevice != NULL)
{
slotdevice->write_c0nx(space, offset % 0x10, data);
}
}
/* returns default CnXX slotram for a slot space */
INT8 apple2_state::apple2_slotram_r(address_space &space, int slotnum, int offset)
{
if (m_slot_ram)
{
if (!space.debugger_access())
{
// printf("slotram_r: taking cnxx_slot to -1\n");
m_a2_cnxx_slot = -1;
apple2_update_memory();
}
return m_slot_ram[offset];
}
// else fall through to floating bus
return apple2_getfloatingbusvalue();
}
READ8_MEMBER(apple2_state::apple2_c1xx_r )
{
int slotnum;
device_a2bus_card_interface *slotdevice;
slotnum = ((offset>>8) & 0xf) + 1;
slotdevice = m_a2bus->get_a2bus_card(slotnum);
if (slotdevice != NULL)
{
if (slotdevice->take_c800())
{
// printf("c1xx_r: taking cnxx_slot to %d\n", slotnum);
m_a2_cnxx_slot = slotnum;
apple2_update_memory();
}
return slotdevice->read_cnxx(space, offset&0xff);
}
else
{
return apple2_slotram_r(space, slotnum, offset);
}
// else fall through to floating bus
return apple2_getfloatingbusvalue();
}
WRITE8_MEMBER(apple2_state::apple2_c1xx_w )
{
int slotnum;
device_a2bus_card_interface *slotdevice;
slotnum = ((offset>>8) & 0xf) + 1;
slotdevice = m_a2bus->get_a2bus_card(slotnum);
if (slotdevice != NULL)
{
slotdevice->write_cnxx(space, offset&0xff, data);
}
else
{
if (m_slot_ram)
m_slot_ram[offset] = data;
}
}
READ8_MEMBER(apple2_state::apple2_c3xx_r )
{
int slotnum;
device_a2bus_card_interface *slotdevice;
slotnum = 3;
slotdevice = m_a2bus->get_a2bus_card(slotnum);
// is a card installed in this slot?
if (slotdevice != NULL)
{
if (slotdevice->take_c800())
{
// printf("c3xx_r: taking cnxx_slot to %d\n", slotnum);
m_a2_cnxx_slot = slotnum;
apple2_update_memory();
}
return slotdevice->read_cnxx(space, offset&0xff);
}
else
{
return apple2_slotram_r(space, slotnum, offset);
}
// else fall through to floating bus
return apple2_getfloatingbusvalue();
}
WRITE8_MEMBER(apple2_state::apple2_c3xx_w )
{
int slotnum;
device_a2bus_card_interface *slotdevice;
slotnum = 3;
slotdevice = m_a2bus->get_a2bus_card(slotnum);
if (slotdevice != NULL)
{
if (slotdevice->take_c800())
{
// printf("c3xx_w: taking cnxx_slot to %d\n", slotnum);
m_a2_cnxx_slot = slotnum;
apple2_update_memory();
}
slotdevice->write_cnxx(space, offset&0xff, data);
}
else
{
if (m_slot_ram)
m_slot_ram[offset] = data;
}
}
READ8_MEMBER(apple2_state::apple2_c4xx_r )
{
int slotnum;
device_a2bus_card_interface *slotdevice;
slotnum = ((offset>>8) & 0xf) + 4;
slotdevice = m_a2bus->get_a2bus_card(slotnum);
// is a card installed in this slot?
if (slotdevice != NULL)
{
if (slotdevice->take_c800() && (m_a2_cnxx_slot != slotnum))
{
m_a2_cnxx_slot = slotnum;
apple2_update_memory();
}
return slotdevice->read_cnxx(space, offset&0xff);
}
else
{
return apple2_slotram_r(space, slotnum, offset);
}
// else fall through to floating bus
return apple2_getfloatingbusvalue();
}
WRITE8_MEMBER ( apple2_state::apple2_c4xx_w )
{
int slotnum;
device_a2bus_card_interface *slotdevice;
slotnum = ((offset>>8) & 0xf) + 4;
slotdevice = m_a2bus->get_a2bus_card(slotnum);
if (slotdevice != NULL)
{
if (slotdevice->take_c800())
{
// printf("c4xx_w: taking cnxx_slot to %d\n", slotnum);
m_a2_cnxx_slot = slotnum;
apple2_update_memory();
}
slotdevice->write_cnxx(space, offset&0xff, data);
}
else
{
if (m_slot_ram)
m_slot_ram[offset] = data;
}
}
READ8_MEMBER(apple2_state::apple2_cfff_r)
{
// debugger guard
if (!space.debugger_access())
{
// printf("cfff_r: taking cnxx_slot to -1\n");
m_a2_cnxx_slot = -1;
apple2_update_memory();
}
return apple2_getfloatingbusvalue();
}
WRITE8_MEMBER(apple2_state::apple2_cfff_w)
{
if (!space.debugger_access())
{
// printf("cfff_w: taking cnxx_slot to -1\n");
m_a2_cnxx_slot = -1;
apple2_update_memory();
}
}
READ8_MEMBER(apple2_state::apple2_c800_r )
{
device_a2bus_card_interface *slotdevice;
slotdevice = m_a2bus->get_a2bus_card(m_a2_cnxx_slot);
if (slotdevice != NULL)
{
return slotdevice->read_c800(space, offset&0xfff);
}
return apple2_getfloatingbusvalue();
}
WRITE8_MEMBER(apple2_state::apple2_c800_w )
{
device_a2bus_card_interface *slotdevice;
slotdevice = m_a2bus->get_a2bus_card(m_a2_cnxx_slot);
if (slotdevice != NULL)
{
slotdevice->write_c800(space, offset&0xfff, data);
}
}
READ8_MEMBER(apple2_state::apple2_ce00_r )
{
device_a2bus_card_interface *slotdevice;
slotdevice = m_a2bus->get_a2bus_card(m_a2_cnxx_slot);
if (slotdevice != NULL)
{
return slotdevice->read_c800(space, (offset&0xfff) + 0x600);
}
return apple2_getfloatingbusvalue();
}
WRITE8_MEMBER(apple2_state::apple2_ce00_w )
{
device_a2bus_card_interface *slotdevice;
slotdevice = m_a2bus->get_a2bus_card(m_a2_cnxx_slot);
if (slotdevice != NULL)
{
slotdevice->write_c800(space, (offset&0xfff)+0x600, data);
}
}
READ8_MEMBER(apple2_state::apple2_inh_d000_r )
{
device_a2bus_card_interface *slotdevice;
slotdevice = m_a2bus->get_a2bus_card(m_inh_slot);
if (slotdevice != NULL)
{
return slotdevice->read_inh_rom(space, offset & 0xfff);
}
return apple2_getfloatingbusvalue();
}
WRITE8_MEMBER(apple2_state::apple2_inh_d000_w )
{
device_a2bus_card_interface *slotdevice;
slotdevice = m_a2bus->get_a2bus_card(m_inh_slot);
if (slotdevice != NULL)
{
return slotdevice->write_inh_rom(space, offset & 0xfff, data);
}
}
READ8_MEMBER(apple2_state::apple2_inh_e000_r )
{
device_a2bus_card_interface *slotdevice;
slotdevice = m_a2bus->get_a2bus_card(m_inh_slot);
if (slotdevice != NULL)
{
return slotdevice->read_inh_rom(space, (offset & 0x1fff) + 0x1000);
}
return apple2_getfloatingbusvalue();
}
WRITE8_MEMBER(apple2_state::apple2_inh_e000_w )
{
device_a2bus_card_interface *slotdevice;
slotdevice = m_a2bus->get_a2bus_card(m_inh_slot);
if (slotdevice != NULL)
{
slotdevice->write_inh_rom(space, (offset & 0x1fff) + 0x1000, data);
}
}
static void apple2_mem_0000(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
apple2_state *state = machine.driver_data<apple2_state>();
meminfo->read_handler = (state->m_flags & VAR_ALTZP) ? &state->read_delegates_0000[0] : &state->read_delegates_0000[1];
meminfo->write_handler = (state->m_flags & VAR_ALTZP) ? &state->write_delegates_0000[0] : &state->write_delegates_0000[1];
}
static void apple2_mem_0200(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
apple2_state *state = machine.driver_data<apple2_state>();
meminfo->read_handler = (state->m_flags & VAR_RAMRD) ? &state->read_delegates_0200[0] : &state->read_delegates_0200[1];
meminfo->write_handler = (state->m_flags & VAR_RAMWRT) ? &state->write_delegates_0200[0] : &state->write_delegates_0200[1];
}
static void apple2_mem_0400(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
apple2_state *state = machine.driver_data<apple2_state>();
if (state->m_flags & VAR_80STORE)
{
meminfo->read_handler = (state->m_flags & VAR_PAGE2) ? &state->read_delegates_0400[0] : &state->read_delegates_0400[1];
meminfo->write_handler = (state->m_flags & VAR_PAGE2) ? &state->write_delegates_0400[0] : &state->write_delegates_0400[1];
}
else
{
meminfo->read_handler = (state->m_flags & VAR_RAMRD) ? &state->read_delegates_0400[0] : &state->read_delegates_0400[1];
meminfo->write_handler = (state->m_flags & VAR_RAMWRT) ? &state->write_delegates_0400[0] : &state->write_delegates_0400[1];
}
}
static void apple2_mem_0800(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
apple2_state *state = machine.driver_data<apple2_state>();
meminfo->read_handler = (state->m_flags & VAR_RAMRD) ? &state->read_delegates_0800[0] : &state->read_delegates_0800[1];
meminfo->write_handler = (state->m_flags & VAR_RAMWRT) ? &state->write_delegates_0800[0] : &state->write_delegates_0800[1];
}
static void apple2_mem_2000(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
apple2_state *state = machine.driver_data<apple2_state>();
if ((state->m_flags & (VAR_80STORE|VAR_HIRES)) == (VAR_80STORE|VAR_HIRES))
{
meminfo->read_handler = (state->m_flags & VAR_PAGE2) ? &state->read_delegates_2000[0] : &state->read_delegates_2000[1];
meminfo->write_handler = (state->m_flags & VAR_PAGE2) ? &state->write_delegates_2000[0] : &state->write_delegates_2000[1];
}
else
{
meminfo->read_handler = (state->m_flags & VAR_RAMRD) ? &state->read_delegates_2000[0] : &state->read_delegates_2000[1];
meminfo->write_handler = (state->m_flags & VAR_RAMWRT) ? &state->write_delegates_2000[0] : &state->write_delegates_2000[1];
}
}
static void apple2_mem_4000(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
apple2_state *state = machine.driver_data<apple2_state>();
meminfo->read_handler = (state->m_flags & VAR_RAMRD) ? &state->read_delegates_4000[0] : &state->read_delegates_4000[1];
meminfo->write_handler = (state->m_flags & VAR_RAMWRT) ? &state->write_delegates_4000[0] : &state->write_delegates_4000[1];
}
static void apple2_mem_C000(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
apple2_state *state = machine.driver_data<apple2_state>();
meminfo->read_handler = &state->rd_c000;
meminfo->write_handler = &state->wd_c000;
}
static void apple2_mem_C080(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
apple2_state *state = machine.driver_data<apple2_state>();
meminfo->read_handler = &state->rd_c080;
meminfo->write_handler = &state->wd_c080;
}
static void tk2000_mem_C100(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
apple2_state *state = machine.driver_data<apple2_state>();
if (state->m_flags & VAR_TK2000RAM)
{
meminfo->read_mem = 0x00C100;
meminfo->write_mem = 0x00C100;
}
else
{
meminfo->read_mem = (begin & 0x3fff) | APPLE2_MEM_ROM;
meminfo->write_mem = 0x00C100;
}
}
static void apple2_mem_CFFF(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
apple2_state *state = machine.driver_data<apple2_state>();
meminfo->read_handler = &state->rd_cfff;
meminfo->write_handler = &state->wd_cfff;
}
static void apple2_mem_Cx00(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
apple2_state *state = machine.driver_data<apple2_state>();
if (state->m_flags & VAR_INTCXROM)
{
meminfo->read_mem = (begin & 0x0FFF) | (state->m_flags & VAR_ROMSWITCH ? 0x4000 : 0x0000) | APPLE2_MEM_ROM;
meminfo->write_mem = APPLE2_MEM_FLOATING;
}
else
{
meminfo->read_mem = ((begin & 0x0FFF) - 0x100) | APPLE2_MEM_SLOT;
meminfo->write_mem = ((begin & 0x0FFF) - 0x100) | APPLE2_MEM_SLOT;
}
}
static void apple2_mem_C300(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
apple2_state *state = machine.driver_data<apple2_state>();
if (((state->m_flags & (VAR_INTCXROM|VAR_SLOTC3ROM)) != VAR_SLOTC3ROM) && !(state->m_flags_mask & VAR_SLOTC3ROM))
{
meminfo->read_mem = (begin & 0x0FFF) | (state->m_flags & VAR_ROMSWITCH ? 0x4000 : 0x0000) | APPLE2_MEM_ROM;
meminfo->write_mem = APPLE2_MEM_FLOATING;
}
else
{
meminfo->read_mem = ((begin & 0x0FFF) - 0x100) | APPLE2_MEM_SLOT;
meminfo->write_mem = ((begin & 0x0FFF) - 0x100) | APPLE2_MEM_SLOT;
}
}
static void apple2_mem_C800(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
apple2_state *state = machine.driver_data<apple2_state>();
if ((state->m_flags & VAR_INTCXROM) || (state->m_a2_cnxx_slot == -1))
{
meminfo->read_mem = (begin & 0x0FFF) | (state->m_flags & VAR_ROMSWITCH ? 0x4000 : 0x0000) | APPLE2_MEM_ROM;
meminfo->write_mem = APPLE2_MEM_FLOATING;
}
else
{
meminfo->read_handler = &state->rd_c800;
meminfo->write_handler = &state->wd_c800;
}
}
static void apple2_mem_CE00(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
apple2_state *state = machine.driver_data<apple2_state>();
if ((state->m_flags & VAR_ROMSWITCH) && !strcmp(machine.system().name, "apple2cp"))
{
meminfo->read_mem = APPLE2_MEM_AUX;
meminfo->write_mem = APPLE2_MEM_AUX;
}
else
{
if ((state->m_flags & VAR_INTCXROM) || (state->m_a2_cnxx_slot == -1))
{
meminfo->read_mem = (begin & 0x0FFF) | (state->m_flags & VAR_ROMSWITCH ? 0x4000 : 0x0000) | APPLE2_MEM_ROM;
meminfo->write_mem = APPLE2_MEM_FLOATING;
}
else
{
meminfo->read_handler = &state->rd_ce00;
meminfo->write_handler = &state->wd_ce00;
}
}
}
static void apple2_mem_D000(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
apple2_state *state = machine.driver_data<apple2_state>();
if (state->m_inh_slot == INH_SLOT_INVALID)
{
if (state->m_flags & VAR_LCRAM)
{
if (state->m_flags & VAR_LCRAM2)
{
meminfo->read_handler = (state->m_flags & VAR_ALTZP) ? &state->read_delegates_c000[0] : &state->read_delegates_c000[1];
}
else
{
meminfo->read_handler = (state->m_flags & VAR_ALTZP) ? &state->read_delegates_d000[0] : &state->read_delegates_d000[1];
}
}
else
{
meminfo->read_mem = (state->m_flags & VAR_ROMSWITCH) ? 0x005000 : 0x001000;
meminfo->read_mem |= APPLE2_MEM_ROM;
}
if (state->m_flags & VAR_LCWRITE)
{
if (state->m_flags & VAR_LCRAM2)
{
meminfo->write_handler = (state->m_flags & VAR_ALTZP) ? &state->write_delegates_c000[0] : &state->write_delegates_c000[1];
}
else
{
meminfo->write_handler = (state->m_flags & VAR_ALTZP) ? &state->write_delegates_d000[0] : &state->write_delegates_d000[1];
}
}
else
{
meminfo->write_mem = APPLE2_MEM_FLOATING;
}
}
else
{
meminfo->read_handler = &state->rd_inh_d000;
meminfo->write_handler = &state->wd_inh_d000;
}
}
static void apple2_mem_E000(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
apple2_state *state = machine.driver_data<apple2_state>();
if (state->m_inh_slot == INH_SLOT_INVALID)
{
if (state->m_flags & VAR_LCRAM)
{
meminfo->read_handler = (state->m_flags & VAR_ALTZP) ? &state->read_delegates_e000[0] : &state->read_delegates_e000[1];
}
else
{
meminfo->read_mem = (state->m_flags & VAR_ROMSWITCH) ? 0x006000 : 0x002000;
meminfo->read_mem |= APPLE2_MEM_ROM;
}
if (state->m_flags & VAR_LCWRITE)
{
meminfo->write_handler = (state->m_flags & VAR_ALTZP) ? &state->write_delegates_e000[0] : &state->write_delegates_e000[1];
}
else
{
meminfo->write_mem = APPLE2_MEM_FLOATING;
}
}
else
{
meminfo->read_handler = &state->rd_inh_e000;
meminfo->write_handler = &state->wd_inh_e000;
}
}
static const apple2_memmap_entry apple2_memmap_entries[] =
{
{ 0x0000, 0x01FF, apple2_mem_0000, A2MEM_MONO },
{ 0x0200, 0x03FF, apple2_mem_0200, A2MEM_DUAL },
{ 0x0400, 0x07FF, apple2_mem_0400, A2MEM_DUAL },
{ 0x0800, 0x1FFF, apple2_mem_0800, A2MEM_DUAL },
{ 0x2000, 0x3FFF, apple2_mem_2000, A2MEM_DUAL },
{ 0x4000, 0xBFFF, apple2_mem_4000, A2MEM_DUAL },
{ 0xC000, 0xC07F, apple2_mem_C000, A2MEM_IO },
{ 0xC080, 0xC0FF, apple2_mem_C080, A2MEM_IO },
{ 0xC100, 0xC2FF, apple2_mem_Cx00, A2MEM_MONO },
{ 0xC300, 0xC3FF, apple2_mem_C300, A2MEM_MONO },
{ 0xC400, 0xC7FF, apple2_mem_Cx00, A2MEM_MONO },
{ 0xC800, 0xCDFF, apple2_mem_C800, A2MEM_MONO },
{ 0xCE00, 0xCFFE, apple2_mem_CE00, A2MEM_MONO },
{ 0xCFFF, 0xCFFF, apple2_mem_CFFF, A2MEM_IO },
{ 0xD000, 0xDFFF, apple2_mem_D000, A2MEM_DUAL },
{ 0xE000, 0xFFFF, apple2_mem_E000, A2MEM_DUAL },
{ 0 }
};
static const apple2_memmap_entry tk2000_memmap_entries[] =
{
{ 0x0000, 0x01FF, apple2_mem_0000, A2MEM_MONO },
{ 0x0200, 0x03FF, apple2_mem_0200, A2MEM_DUAL },
{ 0x0400, 0x07FF, apple2_mem_0400, A2MEM_DUAL },
{ 0x0800, 0x1FFF, apple2_mem_0800, A2MEM_DUAL },
{ 0x2000, 0x3FFF, apple2_mem_2000, A2MEM_DUAL },
{ 0x4000, 0xBFFF, apple2_mem_4000, A2MEM_DUAL },
{ 0xC000, 0xC07F, apple2_mem_C000, A2MEM_IO },
{ 0xC080, 0xC0FF, apple2_mem_C080, A2MEM_IO },
{ 0xC100, 0xFFFF, tk2000_mem_C100, A2MEM_DUAL },
{ 0 }
};
void apple2_state::apple2_setvar(UINT32 val, UINT32 mask)
{
LOG(("apple2_setvar(): val=0x%06x mask=0x%06x pc=0x%04x\n", val, mask,
(unsigned int) m_maincpu->pc()));
assert((val & mask) == val);
/* apply mask and set */
val &= m_a2_mask;
val |= m_a2_set;
/* change the softswitch */
m_flags &= ~mask;
m_flags |= val;
// disable flags that don't apply (INTCXROM/SLOTC3ROM on II/II+ for instance)
m_flags &= ~m_flags_mask;
apple2_update_memory();
}
/* -----------------------------------------------------------------------
* Floating bus code
*
* preliminary floating bus video scanner code - look for comments
* with FIX:
* ----------------------------------------------------------------------- */
UINT8 apple2_state::apple2_getfloatingbusvalue()
{
enum
{
// scanner types
kScannerNone = 0, kScannerApple2, kScannerApple2e,
// scanner constants
kHBurstClock = 53, // clock when Color Burst starts
kHBurstClocks = 4, // clocks per Color Burst duration
kHClock0State = 0x18, // H[543210] = 011000
kHClocks = 65, // clocks per horizontal scan (including HBL)
kHPEClock = 40, // clock when HPE (horizontal preset enable) goes low
kHPresetClock = 41, // clock when H state presets
kHSyncClock = 49, // clock when HSync starts
kHSyncClocks = 4, // clocks per HSync duration
kNTSCScanLines = 262, // total scan lines including VBL (NTSC)
kNTSCVSyncLine = 224, // line when VSync starts (NTSC)
kPALScanLines = 312, // total scan lines including VBL (PAL)
kPALVSyncLine = 264, // line when VSync starts (PAL)
kVLine0State = 0x100, // V[543210CBA] = 100000000
kVPresetLine = 256, // line when V state presets
kVSyncLines = 4, // lines per VSync duration
kClocksPerVSync = kHClocks * kNTSCScanLines // FIX: NTSC only?
};
// vars
//
int i, Hires, Mixed, Page2, _80Store, ScanLines, /* VSyncLine, ScanCycles,*/
h_clock, h_state, h_0, h_1, h_2, h_3, h_4, h_5,
v_line, v_state, v_A, v_B, v_C, v_0, v_1, v_2, v_3, v_4, /* v_5, */
_hires, addend0, addend1, addend2, sum, address;
// video scanner data
//
i = m_maincpu->total_cycles() % kClocksPerVSync; // cycles into this VSync
// machine state switches
//
Hires = (m_flags & VAR_HIRES) ? 1 : 0;
Mixed = (m_flags & VAR_MIXED) ? 1 : 0;
Page2 = (m_flags & VAR_PAGE2) ? 1 : 0;
_80Store = (m_flags & VAR_80STORE) ? 1 : 0;
// calculate video parameters according to display standard
//
ScanLines = 1 ? kNTSCScanLines : kPALScanLines; // FIX: NTSC only?
// VSyncLine = 1 ? kNTSCVSyncLine : kPALVSyncLine; // FIX: NTSC only?
// ScanCycles = ScanLines * kHClocks;
// calculate horizontal scanning state
//
h_clock = (i + kHPEClock) % kHClocks; // which horizontal scanning clock
h_state = kHClock0State + h_clock; // H state bits
if (h_clock >= kHPresetClock) // check for horizontal preset
{
h_state -= 1; // correct for state preset (two 0 states)
}
h_0 = (h_state >> 0) & 1; // get horizontal state bits
h_1 = (h_state >> 1) & 1;
h_2 = (h_state >> 2) & 1;
h_3 = (h_state >> 3) & 1;
h_4 = (h_state >> 4) & 1;
h_5 = (h_state >> 5) & 1;
// calculate vertical scanning state
//
v_line = i / kHClocks; // which vertical scanning line
v_state = kVLine0State + v_line; // V state bits
if ((v_line >= kVPresetLine)) // check for previous vertical state preset
{
v_state -= ScanLines; // compensate for preset
}
v_A = (v_state >> 0) & 1; // get vertical state bits
v_B = (v_state >> 1) & 1;
v_C = (v_state >> 2) & 1;
v_0 = (v_state >> 3) & 1;
v_1 = (v_state >> 4) & 1;
v_2 = (v_state >> 5) & 1;
v_3 = (v_state >> 6) & 1;
v_4 = (v_state >> 7) & 1;
//v_5 = (v_state >> 8) & 1;
// calculate scanning memory address
//
_hires = Hires;
if (Hires && Mixed && (v_4 & v_2))
{
_hires = 0; // (address is in text memory)
}
addend0 = 0x68; // 1 1 0 1
addend1 = (h_5 << 5) | (h_4 << 4) | (h_3 << 3);
addend2 = (v_4 << 6) | (v_3 << 5) | (v_4 << 4) | (v_3 << 3);
sum = (addend0 + addend1 + addend2) & (0x0F << 3);
address = 0;
address |= h_0 << 0; // a0
address |= h_1 << 1; // a1
address |= h_2 << 2; // a2
address |= sum; // a3 - aa6
address |= v_0 << 7; // a7
address |= v_1 << 8; // a8
address |= v_2 << 9; // a9
address |= ((_hires) ? v_A : (1 ^ (Page2 & (1 ^ _80Store)))) << 10; // a10
address |= ((_hires) ? v_B : (Page2 & (1 ^ _80Store))) << 11; // a11
if (_hires) // hires?
{
// Y: insert hires only address bits
//
address |= v_C << 12; // a12
address |= (1 ^ (Page2 & (1 ^ _80Store))) << 13; // a13
address |= (Page2 & (1 ^ _80Store)) << 14; // a14
}
else
{
// N: text, so no higher address bits unless Apple ][, not Apple //e
//
if ((1) && // Apple ][? // FIX: check for Apple ][? (FB is most useful in old games)
(kHPEClock <= h_clock) && // Y: HBL?
(h_clock <= (kHClocks - 1)))
{
address |= 1 << 12; // Y: a12 (add $1000 to address!)
}
}
// update VBL' state
//
if (v_4 & v_3) // VBL?
{
//CMemory::mState &= ~CMemory::kVBLBar; // Y: VBL' is false // FIX: MESS?
}
else
{
//CMemory::mState |= CMemory::kVBLBar; // N: VBL' is true // FIX: MESS?
}
return m_ram->pointer()[address % m_ram->size()]; // FIX: this seems to work, but is it right!?
}
/* -----------------------------------------------------------------------
* Machine reset
* ----------------------------------------------------------------------- */
void apple2_state::machine_reset()
{
int need_intcxrom;
m_rambase = m_ram->pointer();
apple2_refresh_delegates();
need_intcxrom = !strcmp(machine().system().name, "apple2c")
|| !strcmp(machine().system().name, "apple2c0")
|| !strcmp(machine().system().name, "apple2c3")
|| !strcmp(machine().system().name, "apple2c4")
|| !strcmp(machine().system().name, "prav8c")
|| !strcmp(machine().system().name, "apple2cp")
|| !strncmp(machine().system().name, "apple2g", 7);
apple2_setvar(need_intcxrom ? VAR_INTCXROM : 0, ~0);
// ROM 0 cannot boot unless language card bank 2 is write-enabled (but read ROM) on startup
if (!strncmp(machine().system().name, "apple2g", 7))
{
apple2_setvar(VAR_LCWRITE|VAR_LCRAM2, VAR_LCWRITE | VAR_LCRAM | VAR_LCRAM2);
}
m_a2_speaker_state = 0;
m_a2_cnxx_slot = -1; // bank in ROM at C800 on reset
m_joystick_x1_time = m_joystick_y1_time = 0;
m_joystick_x2_time = m_joystick_y2_time = 0;
}
/* -----------------------------------------------------------------------
* Apple II interrupt; used to force partial updates
* ----------------------------------------------------------------------- */
TIMER_DEVICE_CALLBACK_MEMBER(apple2_state::apple2_interrupt)
{
int scanline = param;
if((scanline % 8) == 0)
machine().primary_screen->update_partial(machine().primary_screen->vpos());
}
/***************************************************************************
apple2_mainramxx00_r
apple2_mainramxx00_w
apple2_auxramxx00_r
apple2_auxramxx00_w
***************************************************************************/
READ8_MEMBER ( apple2_state::apple2_mainram0000_r )
{
return m_rambase[offset];
}
READ8_MEMBER ( apple2_state::apple2_mainram0200_r )
{
offset += 0x200;
return m_rambase[offset];
}
READ8_MEMBER ( apple2_state::apple2_mainram0400_r )
{
offset += 0x400;
return m_rambase[offset];
}
READ8_MEMBER ( apple2_state::apple2_mainram0800_r )
{
offset += 0x800;
return m_rambase[offset];
}
READ8_MEMBER ( apple2_state::apple2_mainram2000_r )
{
offset += 0x2000;
return m_rambase[offset];
}
READ8_MEMBER ( apple2_state::apple2_mainram4000_r )
{
offset += 0x4000;
return m_rambase[offset];
}
READ8_MEMBER ( apple2_state::apple2_mainramc000_r )
{
offset += 0xc000;
return m_rambase[offset];
}
READ8_MEMBER ( apple2_state::apple2_mainramd000_r )
{
offset += 0xd000;
return m_rambase[offset];
}
READ8_MEMBER ( apple2_state::apple2_mainrame000_r )
{
offset += 0xe000;
return m_rambase[offset];
}
READ8_MEMBER ( apple2_state::apple2_auxram0000_r )
{
if (m_auxslotdevice)
{
return m_auxslotdevice->read_auxram(offset);
}
else if (m_machinetype == APPLE_IIE)
{
return 0xff;
}
offset += 0x10000;
return m_rambase[offset];
}
READ8_MEMBER ( apple2_state::apple2_auxram0200_r )
{
if (m_auxslotdevice)
{
return m_auxslotdevice->read_auxram(offset+0x200);
}
else if (m_machinetype == APPLE_IIE)
{
return 0xff;
}
offset += 0x10200;
return m_rambase[offset];
}
READ8_MEMBER ( apple2_state::apple2_auxram0400_r )
{
if (m_auxslotdevice)
{
return m_auxslotdevice->read_auxram(offset+0x400);
}
else if (m_machinetype == APPLE_IIE)
{
return 0xff;
}
offset += 0x10400;
return m_rambase[offset];
}
READ8_MEMBER ( apple2_state::apple2_auxram0800_r )
{
if (m_auxslotdevice)
{
return m_auxslotdevice->read_auxram(offset+0x800);
}
else if (m_machinetype == APPLE_IIE)
{
return 0xff;
}
offset += 0x10800;
return m_rambase[offset];
}
READ8_MEMBER ( apple2_state::apple2_auxram2000_r )
{
if (m_auxslotdevice)
{
return m_auxslotdevice->read_auxram(offset+0x2000);
}
else if (m_machinetype == APPLE_IIE)
{
return 0xff;
}
offset += 0x12000;
return m_rambase[offset];
}
READ8_MEMBER ( apple2_state::apple2_auxram4000_r )
{
if (m_auxslotdevice)
{
return m_auxslotdevice->read_auxram(offset+0x4000);
}
else if (m_machinetype == APPLE_IIE)
{
return 0xff;
}
offset += 0x14000;
return m_rambase[offset];
}
READ8_MEMBER ( apple2_state::apple2_auxramc000_r )
{
if (m_auxslotdevice)
{
return m_auxslotdevice->read_auxram(offset+0xc000);
}
else if (m_machinetype == APPLE_IIE)
{
return 0xff;
}
offset += 0x1c000;
return m_rambase[offset];
}
READ8_MEMBER ( apple2_state::apple2_auxramd000_r )
{
if (m_auxslotdevice)
{
return m_auxslotdevice->read_auxram(offset+0xd000);
}
else if (m_machinetype == APPLE_IIE)
{
return 0xff;
}
offset += 0x1d000;
return m_rambase[offset];
}
READ8_MEMBER ( apple2_state::apple2_auxrame000_r )
{
if (m_auxslotdevice)
{
return m_auxslotdevice->read_auxram(offset+0xe000);
}
else if (m_machinetype == APPLE_IIE)
{
return 0xff;
}
offset += 0x1e000;
return m_rambase[offset];
}
WRITE8_MEMBER ( apple2_state::apple2_mainram0000_w )
{
m_rambase[offset] = data;
}
WRITE8_MEMBER ( apple2_state::apple2_mainram0200_w )
{
offset += 0x200;
m_rambase[offset] = data;
}
WRITE8_MEMBER ( apple2_state::apple2_mainram0400_w )
{
offset += 0x400;
m_rambase[offset] = data;
}
WRITE8_MEMBER ( apple2_state::apple2_mainram0800_w )
{
offset += 0x800;
m_rambase[offset] = data;
}
WRITE8_MEMBER ( apple2_state::apple2_mainram2000_w )
{
offset += 0x2000;
m_rambase[offset] = data;
}
WRITE8_MEMBER ( apple2_state::apple2_mainram4000_w )
{
offset += 0x4000;
m_rambase[offset] = data;
}
WRITE8_MEMBER ( apple2_state::apple2_mainramc000_w )
{
offset += 0xc000;
m_rambase[offset] = data;
}
WRITE8_MEMBER ( apple2_state::apple2_mainramd000_w )
{
offset += 0xd000;
m_rambase[offset] = data;
}
WRITE8_MEMBER ( apple2_state::apple2_mainrame000_w )
{
offset += 0xe000;
m_rambase[offset] = data;
}
WRITE8_MEMBER ( apple2_state::apple2_auxram0000_w )
{
if (m_auxslotdevice)
{
m_auxslotdevice->write_auxram(offset, data);
return;
}
else if (m_machinetype == APPLE_IIE)
{
return;
}
offset += 0x10000;
m_rambase[offset] = data;
}
WRITE8_MEMBER ( apple2_state::apple2_auxram0200_w )
{
if (m_auxslotdevice)
{
m_auxslotdevice->write_auxram(offset+0x200, data);
return;
}
else if (m_machinetype == APPLE_IIE)
{
return;
}
offset += 0x10200;
m_rambase[offset] = data;
}
WRITE8_MEMBER ( apple2_state::apple2_auxram0400_w )
{
if (m_auxslotdevice)
{
m_auxslotdevice->write_auxram(offset+0x400, data);
return;
}
else if (m_machinetype == APPLE_IIE)
{
return;
}
offset += 0x10400;
m_rambase[offset] = data;
}
WRITE8_MEMBER ( apple2_state::apple2_auxram0800_w )
{
if (m_auxslotdevice)
{
m_auxslotdevice->write_auxram(offset+0x800, data);
return;
}
else if (m_machinetype == APPLE_IIE)
{
return;
}
offset += 0x10800;
m_rambase[offset] = data;
}
WRITE8_MEMBER ( apple2_state::apple2_auxram2000_w )
{
if (m_auxslotdevice)
{
m_auxslotdevice->write_auxram(offset+0x2000, data);
return;
}
else if (m_machinetype == APPLE_IIE)
{
return;
}
offset += 0x12000;
m_rambase[offset] = data;
}
WRITE8_MEMBER ( apple2_state::apple2_auxram4000_w )
{
if (m_auxslotdevice)
{
m_auxslotdevice->write_auxram(offset+0x4000, data);
return;
}
else if (m_machinetype == APPLE_IIE)
{
return;
}
offset += 0x14000;
m_rambase[offset] = data;
}
WRITE8_MEMBER ( apple2_state::apple2_auxramc000_w )
{
if (m_auxslotdevice)
{
m_auxslotdevice->write_auxram(offset+0xc000, data);
return;
}
else if (m_machinetype == APPLE_IIE)
{
return;
}
offset += 0x1c000;
m_rambase[offset] = data;
}
WRITE8_MEMBER ( apple2_state::apple2_auxramd000_w )
{
if (m_auxslotdevice)
{
m_auxslotdevice->write_auxram(offset+0xd000, data);
return;
}
else if (m_machinetype == APPLE_IIE)
{
return;
}
offset += 0x1d000;
m_rambase[offset] = data;
}
WRITE8_MEMBER ( apple2_state::apple2_auxrame000_w )
{
if (m_auxslotdevice)
{
m_auxslotdevice->write_auxram(offset+0xe000, data);
return;
}
else if (m_machinetype == APPLE_IIE)
{
return;
}
offset += 0x1e000;
m_rambase[offset] = data;
}
/***************************************************************************
apple2_c00x_r
***************************************************************************/
READ8_MEMBER ( apple2_state::apple2_c00x_r )
{
UINT8 result = 0;
if(!space.debugger_access())
{
/* Read the keyboard data and strobe */
g_profiler.start(PROFILER_C00X);
result = AY3600_keydata_strobe_r(space.machine());
g_profiler.stop();
}
return result;
}
/***************************************************************************
apple2_c00x_w
C000 80STOREOFF
C001 80STOREON - use 80-column memory mapping
C002 RAMRDOFF
C003 RAMRDON - read from aux 48k
C004 RAMWRTOFF
C005 RAMWRTON - write to aux 48k
C006 INTCXROMOFF
C007 INTCXROMON
C008 ALTZPOFF
C009 ALTZPON - use aux ZP, stack and language card area
C00A SLOTC3ROMOFF
C00B SLOTC3ROMON - use external slot 3 ROM
C00C 80COLOFF
C00D 80COLON - use 80-column display mode
C00E ALTCHARSETOFF
C00F ALTCHARSETON - use alt character set
***************************************************************************/
WRITE8_MEMBER ( apple2_state::apple2_c00x_w )
{
UINT32 mask;
mask = 1 << (offset / 2);
apple2_setvar((offset & 1) ? mask : 0, mask);
}
/***************************************************************************
apple2_c01x_r
***************************************************************************/
READ8_MEMBER( apple2_state::apple2_c01x_r )
{
UINT8 result = apple2_getfloatingbusvalue() & 0x7F;
if(!space.debugger_access())
{
g_profiler.start(PROFILER_C01X);
LOG(("a2 softswitch_r: %04x\n", offset + 0xc010));
switch (offset)
{
case 0x00: result |= AY3600_anykey_clearstrobe_r(space.machine()); break;
case 0x01: result |= (m_flags & VAR_LCRAM2) ? 0x80 : 0x00; break;
case 0x02: result |= (m_flags & VAR_LCRAM) ? 0x80 : 0x00; break;
case 0x03: result |= (m_flags & VAR_RAMRD) ? 0x80 : 0x00; break;
case 0x04: result |= (m_flags & VAR_RAMWRT) ? 0x80 : 0x00; break;
case 0x05: result |= (m_flags & VAR_INTCXROM) ? 0x80 : 0x00; break;
case 0x06: result |= (m_flags & VAR_ALTZP) ? 0x80 : 0x00; break;
case 0x07: result |= (m_flags & VAR_SLOTC3ROM) ? 0x80 : 0x00; break;
case 0x08: result |= (m_flags & VAR_80STORE) ? 0x80 : 0x00; break;
case 0x09: result |= !space.machine().primary_screen->vblank() ? 0x80 : 0x00; break;
case 0x0A: result |= (m_flags & VAR_TEXT) ? 0x80 : 0x00; break;
case 0x0B: result |= (m_flags & VAR_MIXED) ? 0x80 : 0x00; break;
case 0x0C: result |= (m_flags & VAR_PAGE2) ? 0x80 : 0x00; break;
case 0x0D: result |= (m_flags & VAR_HIRES) ? 0x80 : 0x00; break;
case 0x0E: result |= (m_flags & VAR_ALTCHARSET) ? 0x80 : 0x00; break;
case 0x0F: result |= (m_flags & VAR_80COL) ? 0x80 : 0x00; break;
}
g_profiler.stop();
}
return result;
}
/***************************************************************************
apple2_c01x_w
***************************************************************************/
WRITE8_MEMBER( apple2_state::apple2_c01x_w )
{
/* Clear the keyboard strobe - ignore the returned results */
g_profiler.start(PROFILER_C01X);
AY3600_anykey_clearstrobe_r(machine());
g_profiler.stop();
}
/***************************************************************************
apple2_c02x_r
***************************************************************************/
READ8_MEMBER( apple2_state::apple2_c02x_r )
{
if(!space.debugger_access())
{
apple2_c02x_w(space, offset, 0, 0);
}
return apple2_getfloatingbusvalue();
}
/***************************************************************************
apple2_c02x_w
***************************************************************************/
WRITE8_MEMBER( apple2_state::apple2_c02x_w )
{
switch(offset)
{
case 0x08:
apple2_setvar((m_flags & VAR_ROMSWITCH) ^ VAR_ROMSWITCH, VAR_ROMSWITCH);
break;
}
}
/***************************************************************************
apple2_c03x_r
***************************************************************************/
READ8_MEMBER ( apple2_state::apple2_c03x_r )
{
if(!space.debugger_access())
{
if (!offset)
{
speaker_sound_device *speaker = space.machine().device<speaker_sound_device>("a2speaker");
if (m_a2_speaker_state == 1)
{
m_a2_speaker_state = 0;
}
else
{
m_a2_speaker_state = 1;
}
speaker->level_w(m_a2_speaker_state);
}
}
return apple2_getfloatingbusvalue();
}
/***************************************************************************
apple2_c03x_w
***************************************************************************/
WRITE8_MEMBER ( apple2_state::apple2_c03x_w )
{
apple2_c03x_r(space, offset, 0);
}
/***************************************************************************
apple2_c05x_r
***************************************************************************/
READ8_MEMBER ( apple2_state::apple2_c05x_r )
{
if(!space.debugger_access())
{
UINT32 mask;
if (m_machinetype == TK2000)
{
if (offset == 0xa) // RAM
{
apple2_setvar(VAR_TK2000RAM, ~0);
printf("TK2000: RAM (PC %x)\n", m_maincpu->pc());
}
else if (offset == 0xb) // ROM
{
apple2_setvar(0, ~VAR_TK2000RAM);
printf("TK2000: ROM (PC %x)\n", m_maincpu->pc());
}
}
/* ANx has reverse SET logic */
if (offset >= 8)
{
offset ^= 1;
}
mask = 0x100 << (offset / 2);
apple2_setvar((offset & 1) ? mask : 0, mask);
}
return apple2_getfloatingbusvalue();
}
/***************************************************************************
apple2_c05x_w
***************************************************************************/
WRITE8_MEMBER ( apple2_state::apple2_c05x_w )
{
apple2_c05x_r(space, offset, 0);
}
/***************************************************************************
apple2_c06x_r
***************************************************************************/
READ8_MEMBER ( apple2_state::apple2_c06x_r )
{
int result = 0;
if(!space.debugger_access())
{
switch (offset & 0x0F)
{
case 0x00:
/* Cassette input */
{
if (m_cassette)
{
result = m_cassette->input() > 0.0 ? 0x80 : 0;
}
else
{
result = 0;
}
}
break;
case 0x01:
/* Open-Apple/Joystick button 0 */
result = apple2_pressed_specialkey(SPECIALKEY_BUTTON0);
break;
case 0x02:
/* Closed-Apple/Joystick button 1 */
result = apple2_pressed_specialkey(SPECIALKEY_BUTTON1);
break;
case 0x03:
/* Joystick button 2. Later revision motherboards connected this to SHIFT also */
result = apple2_pressed_specialkey(SPECIALKEY_BUTTON2);
break;
case 0x04:
/* X Joystick 1 axis */
result = space.machine().time().as_double() < m_joystick_x1_time;
break;
case 0x05:
/* Y Joystick 1 axis */
result = space.machine().time().as_double() < m_joystick_y1_time;
break;
case 0x06:
/* X Joystick 2 axis */
result = space.machine().time().as_double() < m_joystick_x2_time;
break;
case 0x07:
/* Y Joystick 2 axis */
result = space.machine().time().as_double() < m_joystick_y2_time;
break;
default:
/* c060 Empty Cassette head read
* and any other non joystick c06 port returns this according to applewin
*/
return apple2_getfloatingbusvalue();
}
}
return result ? 0x80 : 0x00;
}
/***************************************************************************
apple2_c07x_r
***************************************************************************/
READ8_MEMBER ( apple2_state::apple2_c07x_r )
{
if(!space.debugger_access())
{
double x_calibration = attotime::from_usec(12).as_double();
double y_calibration = attotime::from_usec(13).as_double();
if (offset == 0)
{
m_joystick_x1_time = machine().time().as_double() + x_calibration * m_joy1x->read();
m_joystick_y1_time = machine().time().as_double() + y_calibration * m_joy1y->read();
m_joystick_x2_time = machine().time().as_double() + x_calibration * m_joy2x->read();
m_joystick_y2_time = machine().time().as_double() + y_calibration * m_joy2y->read();
}
}
return 0;
}
/***************************************************************************
apple2_c07x_w
***************************************************************************/
WRITE8_MEMBER ( apple2_state::apple2_c07x_w )
{
// this a machine with an aux slot?
if (m_auxslotdevice)
{
m_auxslotdevice->write_c07x(space, offset&0xf, data);
}
// AE RamWorks manual indicates that even if the auxslot card sees the c07x write,
// so does the motherboard and it will trigger the paddles. So always call this.
apple2_c07x_r(space, offset, 0);
}
/* -----------------------------------------------------------------------
* Floppy disk controller
* ----------------------------------------------------------------------- */
int apple2_state::apple2_fdc_has_35()
{
return (floppy_get_count(machine())); // - apple525_get_count(machine)) > 0;
}
int apple2_state::apple2_fdc_has_525()
{
return 1; //apple525_get_count(machine) > 0;
}
static void apple2_fdc_set_lines(device_t *device, UINT8 lines)
{
apple2_state *state = device->machine().driver_data<apple2_state>();
if (state->m_fdc_diskreg & 0x40)
{
if (state->apple2_fdc_has_35())
{
/* slot 5: 3.5" disks */
sony_set_lines(device,lines);
}
}
else
{
if (state->apple2_fdc_has_525())
{
/* slot 6: 5.25" disks */
apple525_set_lines(device,lines);
}
}
}
static void apple2_fdc_set_enable_lines(device_t *device,int enable_mask)
{
apple2_state *state = device->machine().driver_data<apple2_state>();
int slot5_enable_mask = 0;
int slot6_enable_mask = 0;
if (state->m_fdc_diskreg & 0x40)
slot5_enable_mask = enable_mask;
else
slot6_enable_mask = enable_mask;
if (state->apple2_fdc_has_35())
{
/* set the 3.5" enable lines */
sony_set_enable_lines(device,slot5_enable_mask);
}
if (state->apple2_fdc_has_525())
{
/* set the 5.25" enable lines */
apple525_set_enable_lines(device,slot6_enable_mask);
}
}
static UINT8 apple2_fdc_read_data(device_t *device)
{
apple2_state *state = device->machine().driver_data<apple2_state>();
UINT8 result = 0x00;
if (state->m_fdc_diskreg & 0x40)
{
if (state->apple2_fdc_has_35())
{
/* slot 5: 3.5" disks */
result = sony_read_data(device);
}
}
else
{
if (state->apple2_fdc_has_525())
{
/* slot 6: 5.25" disks */
result = apple525_read_data(device);
}
}
return result;
}
static void apple2_fdc_write_data(device_t *device, UINT8 data)
{
apple2_state *state = device->machine().driver_data<apple2_state>();
if (state->m_fdc_diskreg & 0x40)
{
if (state->apple2_fdc_has_35())
{
/* slot 5: 3.5" disks */
sony_write_data(device,data);
}
}
else
{
if (state->apple2_fdc_has_525())
{
/* slot 6: 5.25" disks */
apple525_write_data(device,data);
}
}
}
static int apple2_fdc_read_status(device_t *device)
{
apple2_state *state = device->machine().driver_data<apple2_state>();
int result = 0;
if (state->m_fdc_diskreg & 0x40)
{
if (state->apple2_fdc_has_35())
{
/* slot 5: 3.5" disks */
result = sony_read_status(device);
}
}
else
{
if (state->apple2_fdc_has_525())
{
/* slot 6: 5.25" disks */
result = apple525_read_status(device);
}
}
return result;
}
void apple2_state::apple2_iwm_setdiskreg(UINT8 data)
{
m_fdc_diskreg = data & 0xC0;
if (apple2_fdc_has_35())
sony_set_sel_line( machine().device("fdc"),m_fdc_diskreg & 0x80);
}
const applefdc_interface apple2_fdc_interface =
{
apple2_fdc_set_lines, /* set_lines */
apple2_fdc_set_enable_lines, /* set_enable_lines */
apple2_fdc_read_data, /* read_data */
apple2_fdc_write_data, /* write_data */
apple2_fdc_read_status /* read_status */
};
/* -----------------------------------------------------------------------
* Driver init
* ----------------------------------------------------------------------- */
void apple2_state::apple2_init_common()
{
m_inh_slot = INH_SLOT_INVALID;
m_flags = 0;
m_fdc_diskreg = 0;
// do these lookups once at startup
m_rom = memregion("maincpu")->base();
m_rom_length = memregion("maincpu")->bytes() & ~0xFFF;
m_slot_length = memregion("maincpu")->bytes() - m_rom_length;
m_slot_ram = (m_slot_length > 0) ? &m_rom[m_rom_length] : NULL;
m_auxslotdevice = NULL;
if (m_machinetype == APPLE_IIE)
{
m_auxslotdevice = m_a2eauxslot->get_a2eauxslot_card();
}
AY3600_init(machine());
/* state save registers */
save_item(NAME(m_flags));
machine().save().register_postload(save_prepost_delegate(FUNC(apple2_state::apple2_update_memory_postload), this));
/* --------------------------------------------- *
* set up the softswitch mask/set *
* --------------------------------------------- */
m_a2_mask = ~0;
m_a2_set = 0;
/* disable VAR_ROMSWITCH if the ROM is only 16k */
if (memregion("maincpu")->bytes() < 0x8000)
m_a2_mask &= ~VAR_ROMSWITCH;
if (m_ram->size() <= 64*1024)
m_a2_mask &= ~(VAR_RAMRD | VAR_RAMWRT | VAR_80STORE | VAR_ALTZP | VAR_80COL);
apple2_refresh_delegates();
}
MACHINE_START_MEMBER(apple2_state,apple2)
{
apple2_memmap_config mem_cfg;
void *apple2cp_ce00_ram = NULL;
m_flags_mask = 0;
/* there appears to be some hidden RAM that is swapped in on the Apple
* IIc plus; I have not found any official documentation but the BIOS
* clearly uses this area as writeable memory */
if (!strcmp(machine().system().name, "apple2cp")) {
apple2cp_ce00_ram = auto_alloc_array(machine(), UINT8, 0x200);
memset(apple2cp_ce00_ram, 0, sizeof(UINT8) * 0x200);
}
m_machinetype = APPLE_IIEPLUS;
apple2_init_common();
/* setup memory */
memset(&mem_cfg, 0, sizeof(mem_cfg));
mem_cfg.first_bank = 1;
mem_cfg.memmap = apple2_memmap_entries;
mem_cfg.auxmem = (UINT8*)apple2cp_ce00_ram;
apple2_setup_memory(&mem_cfg);
}
MACHINE_START_MEMBER(apple2_state,apple2e)
{
apple2_memmap_config mem_cfg;
void *apple2cp_ce00_ram = NULL;
m_flags_mask = 0;
/* there appears to be some hidden RAM that is swapped in on the Apple
* IIc plus; I have not found any official documentation but the BIOS
* clearly uses this area as writeable memory */
if (!strcmp(machine().system().name, "apple2cp")) {
apple2cp_ce00_ram = auto_alloc_array(machine(), UINT8, 0x200);
memset(apple2cp_ce00_ram, 0, sizeof(UINT8) * 0x200);
}
m_machinetype = APPLE_IIE;
apple2_init_common();
/* setup memory */
memset(&mem_cfg, 0, sizeof(mem_cfg));
mem_cfg.first_bank = 1;
mem_cfg.memmap = apple2_memmap_entries;
mem_cfg.auxmem = (UINT8*)apple2cp_ce00_ram;
apple2_setup_memory(&mem_cfg);
}
MACHINE_START_MEMBER(apple2_state,laser128)
{
apple2_memmap_config mem_cfg;
m_flags_mask = 0;
m_machinetype = LASER128;
apple2_init_common();
/* setup memory */
memset(&mem_cfg, 0, sizeof(mem_cfg));
mem_cfg.first_bank = 1;
mem_cfg.memmap = apple2_memmap_entries;
mem_cfg.auxmem = (UINT8*)NULL;
apple2_setup_memory(&mem_cfg);
}
MACHINE_START_MEMBER(apple2_state,apple2orig)
{
apple2_memmap_config mem_cfg;
void *apple2cp_ce00_ram = NULL;
// II and II+ have no internal ROM or internal slot 3 h/w, so don't allow these states
m_flags_mask = VAR_INTCXROM|VAR_SLOTC3ROM;
m_machinetype = APPLE_II;
apple2_init_common();
/* setup memory */
memset(&mem_cfg, 0, sizeof(mem_cfg));
mem_cfg.first_bank = 1;
mem_cfg.memmap = apple2_memmap_entries;
mem_cfg.auxmem = (UINT8*)apple2cp_ce00_ram;
apple2_setup_memory(&mem_cfg);
}
MACHINE_START_MEMBER(apple2_state,space84)
{
apple2_memmap_config mem_cfg;
void *apple2cp_ce00_ram = NULL;
// II and II+ have no internal ROM or internal slot 3 h/w, so don't allow these states
m_flags_mask = VAR_INTCXROM|VAR_SLOTC3ROM;
m_machinetype = SPACE84;
apple2_init_common();
/* setup memory */
memset(&mem_cfg, 0, sizeof(mem_cfg));
mem_cfg.first_bank = 1;
mem_cfg.memmap = apple2_memmap_entries;
mem_cfg.auxmem = (UINT8*)apple2cp_ce00_ram;
apple2_setup_memory(&mem_cfg);
}
MACHINE_START_MEMBER(apple2_state,tk2000)
{
apple2_memmap_config mem_cfg;
// II and II+ have no internal ROM or internal slot 3 h/w, so don't allow these states
m_flags_mask = VAR_INTCXROM|VAR_SLOTC3ROM;
m_machinetype = TK2000;
apple2_init_common();
/* setup memory */
memset(&mem_cfg, 0, sizeof(mem_cfg));
mem_cfg.first_bank = 1;
mem_cfg.memmap = tk2000_memmap_entries;
mem_cfg.auxmem = (UINT8*)NULL;
apple2_setup_memory(&mem_cfg);
}
int apple2_state::apple2_pressed_specialkey(UINT8 key)
{
return ((m_kbspecial ? m_kbspecial->read() : 0) & key)
|| ((m_joybuttons ? m_joybuttons->read() : 0) & key);
}
void apple2_state::apple2_refresh_delegates()
{
read_delegates_master[0] = read8_delegate(FUNC(apple2_state::read_floatingbus), this);
read_delegates_master[1] = read8_delegate(FUNC(apple2_state::apple2_c1xx_r), this);
read_delegates_master[2] = read8_delegate(FUNC(apple2_state::apple2_c3xx_r), this);
read_delegates_master[3] = read8_delegate(FUNC(apple2_state::apple2_c4xx_r), this);
write_delegates_master[0] = write8_delegate(FUNC(apple2_state::apple2_c1xx_w), this);
write_delegates_master[1] = write8_delegate(FUNC(apple2_state::apple2_c3xx_w), this);
write_delegates_master[2] = write8_delegate(FUNC(apple2_state::apple2_c4xx_w), this);
rd_c000 = read8_delegate(FUNC(apple2_state::apple2_c0xx_r), this);
wd_c000 = write8_delegate(FUNC(apple2_state::apple2_c0xx_w), this);
rd_c080 = read8_delegate(FUNC(apple2_state::apple2_c080_r), this);
wd_c080 = write8_delegate(FUNC(apple2_state::apple2_c080_w), this);
rd_cfff = read8_delegate(FUNC(apple2_state::apple2_cfff_r), this);
wd_cfff = write8_delegate(FUNC(apple2_state::apple2_cfff_w), this);
rd_c800 = read8_delegate(FUNC(apple2_state::apple2_c800_r), this);
wd_c800 = write8_delegate(FUNC(apple2_state::apple2_c800_w), this);
rd_ce00 = read8_delegate(FUNC(apple2_state::apple2_ce00_r), this);
wd_ce00 = write8_delegate(FUNC(apple2_state::apple2_ce00_w), this);
rd_inh_d000 = read8_delegate(FUNC(apple2_state::apple2_inh_d000_r), this);
wd_inh_d000 = write8_delegate(FUNC(apple2_state::apple2_inh_d000_w), this);
rd_inh_e000 = read8_delegate(FUNC(apple2_state::apple2_inh_e000_r), this);
wd_inh_e000 = write8_delegate(FUNC(apple2_state::apple2_inh_e000_w), this);
read_delegates_0000[0] = read8_delegate(FUNC(apple2_state::apple2_auxram0000_r), this);
read_delegates_0000[1] = read8_delegate(FUNC(apple2_state::apple2_mainram0000_r), this);
read_delegates_0200[0] = read8_delegate(FUNC(apple2_state::apple2_auxram0200_r), this);
read_delegates_0200[1] = read8_delegate(FUNC(apple2_state::apple2_mainram0200_r), this);
read_delegates_0400[0] = read8_delegate(FUNC(apple2_state::apple2_auxram0400_r), this);
read_delegates_0400[1] = read8_delegate(FUNC(apple2_state::apple2_mainram0400_r), this);
read_delegates_0800[0] = read8_delegate(FUNC(apple2_state::apple2_auxram0800_r), this);
read_delegates_0800[1] = read8_delegate(FUNC(apple2_state::apple2_mainram0800_r), this);
read_delegates_2000[0] = read8_delegate(FUNC(apple2_state::apple2_auxram2000_r), this);
read_delegates_2000[1] = read8_delegate(FUNC(apple2_state::apple2_mainram2000_r), this);
read_delegates_4000[0] = read8_delegate(FUNC(apple2_state::apple2_auxram4000_r), this);
read_delegates_4000[1] = read8_delegate(FUNC(apple2_state::apple2_mainram4000_r), this);
read_delegates_c000[0] = read8_delegate(FUNC(apple2_state::apple2_auxramc000_r), this);
read_delegates_c000[1] = read8_delegate(FUNC(apple2_state::apple2_mainramc000_r), this);
read_delegates_d000[0] = read8_delegate(FUNC(apple2_state::apple2_auxramd000_r), this);
read_delegates_d000[1] = read8_delegate(FUNC(apple2_state::apple2_mainramd000_r), this);
read_delegates_e000[0] = read8_delegate(FUNC(apple2_state::apple2_auxrame000_r), this);
read_delegates_e000[1] = read8_delegate(FUNC(apple2_state::apple2_mainrame000_r), this);
write_delegates_0000[0] = write8_delegate(FUNC(apple2_state::apple2_auxram0000_w), this);
write_delegates_0000[1] = write8_delegate(FUNC(apple2_state::apple2_mainram0000_w), this);
write_delegates_0200[0] = write8_delegate(FUNC(apple2_state::apple2_auxram0200_w), this);
write_delegates_0200[1] = write8_delegate(FUNC(apple2_state::apple2_mainram0200_w), this);
write_delegates_0400[0] = write8_delegate(FUNC(apple2_state::apple2_auxram0400_w), this);
write_delegates_0400[1] = write8_delegate(FUNC(apple2_state::apple2_mainram0400_w), this);
write_delegates_0800[0] = write8_delegate(FUNC(apple2_state::apple2_auxram0800_w), this);
write_delegates_0800[1] = write8_delegate(FUNC(apple2_state::apple2_mainram0800_w), this);
write_delegates_2000[0] = write8_delegate(FUNC(apple2_state::apple2_auxram2000_w), this);
write_delegates_2000[1] = write8_delegate(FUNC(apple2_state::apple2_mainram2000_w), this);
write_delegates_4000[0] = write8_delegate(FUNC(apple2_state::apple2_auxram4000_w), this);
write_delegates_4000[1] = write8_delegate(FUNC(apple2_state::apple2_mainram4000_w), this);
write_delegates_c000[0] = write8_delegate(FUNC(apple2_state::apple2_auxramc000_w), this);
write_delegates_c000[1] = write8_delegate(FUNC(apple2_state::apple2_mainramc000_w), this);
write_delegates_d000[0] = write8_delegate(FUNC(apple2_state::apple2_auxramd000_w), this);
write_delegates_d000[1] = write8_delegate(FUNC(apple2_state::apple2_mainramd000_w), this);
write_delegates_e000[0] = write8_delegate(FUNC(apple2_state::apple2_auxrame000_w), this);
write_delegates_e000[1] = write8_delegate(FUNC(apple2_state::apple2_mainrame000_w), this);
}