1966 lines
55 KiB
C
1966 lines
55 KiB
C
/*
|
|
* Apple // emulator for *ix
|
|
*
|
|
* This software package is subject to the GNU General Public License
|
|
* version 3 or later (your choice) as published by the Free Software
|
|
* Foundation.
|
|
*
|
|
* Copyright 2013-2015 Aaron Culliney
|
|
*
|
|
*/
|
|
|
|
#include "common.h"
|
|
|
|
extern const uint8_t apple_iie_rom[32768]; // rom.c
|
|
|
|
uint8_t apple_ii_64k[2][65536] = { { 0 } };
|
|
uint8_t language_card[2][8192] = { { 0 } };
|
|
uint8_t language_banks[2][8192] = { { 0 } };
|
|
|
|
const uint8_t *base_vmem = apple_ii_64k[0];
|
|
|
|
#if VM_TRACING
|
|
FILE *test_vm_fp = NULL;
|
|
|
|
typedef struct vm_trace_range_t {
|
|
uint16_t lo;
|
|
uint16_t hi;
|
|
} vm_trace_range_t;
|
|
#endif
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
GLUE_BANK_READ(iie_read_ram_default, BASE_RAMRD);
|
|
GLUE_BANK_WRITE(iie_write_ram_default, BASE_RAMWRT);
|
|
|
|
GLUE_BANK_READ(read_ram_bank, BASE_D000_RD);
|
|
GLUE_BANK_MAYBEWRITE(write_ram_bank, BASE_D000_WRT);
|
|
|
|
GLUE_BANK_READ(read_ram_lc, BASE_E000_RD);
|
|
GLUE_BANK_MAYBEWRITE(write_ram_lc, BASE_E000_WRT);
|
|
|
|
GLUE_BANK_READ(iie_read_ram_text_page0, BASE_TEXTRD);
|
|
|
|
GLUE_BANK_READ(iie_read_ram_hires_page0, BASE_HGRRD);
|
|
|
|
GLUE_BANK_READ(iie_read_ram_zpage_and_stack, BASE_STACKZP);
|
|
GLUE_BANK_WRITE(iie_write_ram_zpage_and_stack, BASE_STACKZP);
|
|
|
|
GLUE_BANK_MAYBE_READ_C3(iie_read_slot3, BASE_C3ROM);
|
|
GLUE_BANK_MAYBE_READ_CX(iie_read_slot4, BASE_C4ROM);
|
|
GLUE_BANK_MAYBE_READ_CX(iie_read_slot5, BASE_C5ROM);
|
|
GLUE_BANK_MAYBE_READ_CX(iie_read_slotx, BASE_CXROM);
|
|
|
|
GLUE_NOP(write_ram_nop);
|
|
|
|
GLUE_C_READ(iie_read_peripheral_card)
|
|
{
|
|
assert(((ea >> 12) & 0xf) == 0xC && "should only be called for 0xC100-0xC7FF");
|
|
uint8_t slot = ((ea >> 8) & 0xf);
|
|
|
|
// TODO FIXME : route to correct peripheral card
|
|
switch (slot) {
|
|
case 0x1:
|
|
case 0x2:
|
|
case 0x3:
|
|
case 0x7:
|
|
break;
|
|
|
|
case 0x4:
|
|
case 0x5:
|
|
return mb_read(ea); // FIXME : hardcoded Mockingboards ...
|
|
break;
|
|
|
|
case 0x6:
|
|
return apple_ii_64k[0][ea];
|
|
break;
|
|
|
|
default:
|
|
assert(false && "internal configuration error!");
|
|
break;
|
|
}
|
|
|
|
// no card in slot
|
|
return floating_bus();
|
|
}
|
|
|
|
static uint8_t read_keyboard_strobe(void) {
|
|
apple_ii_64k[0][0xC000] &= 0x7F;
|
|
apple_ii_64k[1][0xC000] &= 0x7F;
|
|
return apple_ii_64k[0][0xC000];
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// graphics softswitches
|
|
|
|
static uint8_t iie_page2_off(void) {
|
|
if (!(run_args.softswitches & SS_PAGE2)) {
|
|
return floating_bus();
|
|
}
|
|
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
run_args.softswitches &= ~(SS_PAGE2|SS_SCREEN);
|
|
|
|
if (run_args.softswitches & SS_80STORE) {
|
|
run_args.softswitches &= ~(SS_TEXTRD|SS_TEXTWRT);
|
|
run_args.base_textrd = apple_ii_64k[0];
|
|
run_args.base_textwrt = apple_ii_64k[0];
|
|
if (run_args.softswitches & SS_HIRES) {
|
|
run_args.softswitches &= ~(SS_HGRRD|SS_HGRWRT);
|
|
run_args.base_hgrrd = apple_ii_64k[0];
|
|
run_args.base_hgrwrt = apple_ii_64k[0];
|
|
}
|
|
}
|
|
|
|
return floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_page2_on(void) {
|
|
if (run_args.softswitches & SS_PAGE2) {
|
|
return floating_bus();
|
|
}
|
|
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
run_args.softswitches |= SS_PAGE2;
|
|
|
|
if (run_args.softswitches & SS_80STORE) {
|
|
run_args.softswitches |= (SS_TEXTRD|SS_TEXTWRT);
|
|
run_args.base_textrd = apple_ii_64k[1];
|
|
run_args.base_textwrt = apple_ii_64k[1];
|
|
if (run_args.softswitches & SS_HIRES) {
|
|
run_args.softswitches |= (SS_HGRRD|SS_HGRWRT);
|
|
run_args.base_hgrrd = apple_ii_64k[1];
|
|
run_args.base_hgrwrt = apple_ii_64k[1];
|
|
}
|
|
} else {
|
|
run_args.softswitches |= SS_SCREEN;
|
|
}
|
|
|
|
return floating_bus();
|
|
}
|
|
|
|
static uint8_t read_switch_graphics(void) {
|
|
if (run_args.softswitches & SS_TEXT) {
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
run_args.softswitches &= ~SS_TEXT;
|
|
}
|
|
return floating_bus();
|
|
}
|
|
|
|
static uint8_t read_switch_text(void) {
|
|
if (!(run_args.softswitches & SS_TEXT)) {
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
run_args.softswitches |= SS_TEXT;
|
|
}
|
|
return floating_bus();
|
|
}
|
|
|
|
static uint8_t read_switch_no_mixed(void) {
|
|
if (run_args.softswitches & SS_MIXED) {
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
run_args.softswitches &= ~SS_MIXED;
|
|
}
|
|
return floating_bus();
|
|
}
|
|
|
|
static uint8_t read_switch_mixed(void) {
|
|
if (!(run_args.softswitches & SS_MIXED)) {
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
run_args.softswitches |= SS_MIXED;
|
|
}
|
|
return floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_annunciator(uint16_t ea)
|
|
{
|
|
if ((ea >= 0xC058) && (ea <= 0xC05B)) {
|
|
// TODO: alternate joystick management?
|
|
}
|
|
return floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_hires_off(void) {
|
|
if (!(run_args.softswitches & SS_HIRES)) {
|
|
return floating_bus();
|
|
}
|
|
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
run_args.softswitches &= ~(SS_HIRES|SS_HGRRD|SS_HGRWRT);
|
|
run_args.base_hgrrd = apple_ii_64k[0];
|
|
run_args.base_hgrwrt = apple_ii_64k[0];
|
|
|
|
if (run_args.softswitches & SS_RAMRD) {
|
|
run_args.base_hgrrd = apple_ii_64k[1];
|
|
run_args.softswitches |= SS_HGRRD;
|
|
}
|
|
|
|
if (run_args.softswitches & SS_RAMWRT) {
|
|
run_args.base_hgrwrt = apple_ii_64k[1];
|
|
run_args.softswitches |= SS_HGRWRT;
|
|
}
|
|
|
|
return floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_hires_on(void) {
|
|
if (run_args.softswitches & SS_HIRES) {
|
|
return floating_bus();
|
|
}
|
|
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
run_args.softswitches |= SS_HIRES;
|
|
|
|
if (run_args.softswitches & SS_80STORE) {
|
|
if (run_args.softswitches & SS_PAGE2) {
|
|
run_args.softswitches |= (SS_HGRRD|SS_HGRWRT);
|
|
run_args.base_hgrrd = apple_ii_64k[1];
|
|
run_args.base_hgrwrt = apple_ii_64k[1];
|
|
} else {
|
|
run_args.softswitches &= ~(SS_HGRRD|SS_HGRWRT);
|
|
run_args.base_hgrrd = apple_ii_64k[0];
|
|
run_args.base_hgrwrt = apple_ii_64k[0];
|
|
}
|
|
}
|
|
|
|
return floating_bus();
|
|
}
|
|
|
|
GLUE_C_WRITE(video__write_2e_text0)
|
|
{
|
|
do {
|
|
drawpage_mode_t mode = video_currentMainMode(run_args.softswitches);
|
|
if (mode == DRAWPAGE_HIRES) {
|
|
break;
|
|
}
|
|
if (!(run_args.softswitches & SS_PAGE2)) {
|
|
uint8_t b0 = run_args.base_textwrt[ea];
|
|
if (b0 != b) {
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
}
|
|
}
|
|
} while (0);
|
|
run_args.base_textwrt[ea] = b;
|
|
}
|
|
|
|
GLUE_C_WRITE(video__write_2e_text0_mixed)
|
|
{
|
|
do {
|
|
drawpage_mode_t mode = video_currentMixedMode(run_args.softswitches);
|
|
if (mode == DRAWPAGE_HIRES) {
|
|
break;
|
|
}
|
|
if (!(run_args.softswitches & SS_PAGE2)) {
|
|
uint8_t b0 = run_args.base_textwrt[ea];
|
|
if (b0 != b) {
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
}
|
|
}
|
|
} while (0);
|
|
run_args.base_textwrt[ea] = b;
|
|
}
|
|
|
|
GLUE_C_WRITE(video__write_2e_text1)
|
|
{
|
|
do {
|
|
drawpage_mode_t mode = video_currentMainMode(run_args.softswitches);
|
|
if (mode == DRAWPAGE_HIRES) {
|
|
break;
|
|
}
|
|
if ((run_args.softswitches & SS_PAGE2) && !(run_args.softswitches & SS_80STORE)) {
|
|
uint8_t b0 = run_args.base_ramwrt[ea];
|
|
if (b0 != b) {
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
}
|
|
}
|
|
} while (0);
|
|
run_args.base_ramwrt[ea] = b;
|
|
}
|
|
|
|
GLUE_C_WRITE(video__write_2e_text1_mixed)
|
|
{
|
|
do {
|
|
drawpage_mode_t mode = video_currentMixedMode(run_args.softswitches);
|
|
if (mode == DRAWPAGE_HIRES) {
|
|
break;
|
|
}
|
|
if ((run_args.softswitches & SS_PAGE2) && !(run_args.softswitches & SS_80STORE)) {
|
|
uint8_t b0 = run_args.base_ramwrt[ea];
|
|
if (b0 != b) {
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
}
|
|
}
|
|
} while (0);
|
|
run_args.base_ramwrt[ea] = b;
|
|
}
|
|
|
|
GLUE_C_WRITE(video__write_2e_hgr0)
|
|
{
|
|
do {
|
|
drawpage_mode_t mode = video_currentMainMode(run_args.softswitches);
|
|
if (mode == DRAWPAGE_TEXT) {
|
|
break;
|
|
}
|
|
if (!(run_args.softswitches & SS_PAGE2)) {
|
|
uint8_t b0 = run_args.base_hgrwrt[ea];
|
|
if (b0 != b) {
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
}
|
|
}
|
|
} while (0);
|
|
run_args.base_hgrwrt[ea] = b;
|
|
}
|
|
|
|
GLUE_C_WRITE(video__write_2e_hgr0_mixed)
|
|
{
|
|
do {
|
|
drawpage_mode_t mode = video_currentMixedMode(run_args.softswitches);
|
|
if (mode == DRAWPAGE_TEXT) {
|
|
break;
|
|
}
|
|
if (!(run_args.softswitches & SS_PAGE2)) {
|
|
uint8_t b0 = run_args.base_hgrwrt[ea];
|
|
if (b0 != b) {
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
}
|
|
}
|
|
} while (0);
|
|
run_args.base_hgrwrt[ea] = b;
|
|
}
|
|
|
|
GLUE_C_WRITE(video__write_2e_hgr1)
|
|
{
|
|
do {
|
|
drawpage_mode_t mode = video_currentMainMode(run_args.softswitches);
|
|
if (mode == DRAWPAGE_TEXT) {
|
|
break;
|
|
}
|
|
if ((run_args.softswitches & SS_PAGE2) && !(run_args.softswitches & SS_80STORE)) {
|
|
uint8_t b0 = run_args.base_ramwrt[ea];
|
|
if (b0 != b) {
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
}
|
|
}
|
|
} while (0);
|
|
run_args.base_ramwrt[ea] = b;
|
|
}
|
|
|
|
GLUE_C_WRITE(video__write_2e_hgr1_mixed)
|
|
{
|
|
do {
|
|
drawpage_mode_t mode = video_currentMixedMode(run_args.softswitches);
|
|
if (mode == DRAWPAGE_TEXT) {
|
|
break;
|
|
}
|
|
if ((run_args.softswitches & SS_PAGE2) && !(run_args.softswitches & SS_80STORE)) {
|
|
uint8_t b0 = run_args.base_ramwrt[ea];
|
|
if (b0 != b) {
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
}
|
|
}
|
|
} while (0);
|
|
run_args.base_ramwrt[ea] = b;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// GC softswitches : Game Controller (joystick/paddles)
|
|
#define JOY_STEP_USEC (3300.0 / 256.0)
|
|
#define CYCLES_PER_USEC (CLK_6502 / 1000000)
|
|
#define JOY_STEP_CYCLES (JOY_STEP_USEC / CYCLES_PER_USEC)
|
|
|
|
static uint8_t read_button0(void) {
|
|
uint8_t b0 = floating_bus() & (~0x80);
|
|
uint8_t b = run_args.joy_button0 & 0x80;
|
|
return b0 | b;
|
|
}
|
|
|
|
static uint8_t read_button1(void) {
|
|
uint8_t b0 = floating_bus() & (~0x80);
|
|
uint8_t b = run_args.joy_button1 & 0x80;
|
|
return b0 | b;
|
|
}
|
|
|
|
static uint8_t read_button2(void) {
|
|
uint8_t b = floating_bus() & (~0x80);
|
|
uint8_t b0 = run_args.joy_button0 & 0x80;
|
|
uint8_t b1 = run_args.joy_button1 & 0x80;
|
|
return b | b0 | b1;
|
|
}
|
|
|
|
static uint8_t read_gc_strobe(void) {
|
|
// Read Game Controller (paddle) strobe ...
|
|
// From _Understanding the Apple IIe_ :
|
|
// * 7-29, discussing PREAD : "The timer duration will vary between 2 and 3302 usecs"
|
|
// * 7-30, timer reset : "But the timer pulse may still be high from the previous [strobe access] and the timers are
|
|
// not retriggered by C07X' if they have not yet reset from the previous trigger"
|
|
if (run_args.gc_cycles_timer_0 <= 0)
|
|
{
|
|
run_args.gc_cycles_timer_0 = (int)((joy_x-5) * JOY_STEP_CYCLES);
|
|
}
|
|
if (run_args.gc_cycles_timer_1 <= 0)
|
|
{
|
|
run_args.gc_cycles_timer_1 = (int)(joy_y * JOY_STEP_CYCLES) + 2;
|
|
}
|
|
|
|
// NOTE (possible TODO FIXME): unimplemented GC2 and GC3 timers since they were not wired on the //e ...
|
|
return floating_bus();
|
|
}
|
|
|
|
static uint8_t read_gc0(void) {
|
|
if (run_args.gc_cycles_timer_0 <= 0)
|
|
{
|
|
run_args.gc_cycles_timer_0 = 0;
|
|
return 0;
|
|
}
|
|
return 0xFF;
|
|
}
|
|
|
|
static uint8_t read_gc1(void)
|
|
{
|
|
if (run_args.gc_cycles_timer_1 <= 0)
|
|
{
|
|
run_args.gc_cycles_timer_1 = 0;
|
|
return 0;
|
|
}
|
|
return 0xFF;
|
|
}
|
|
|
|
static uint8_t iie_read_gc2(void) {
|
|
return floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_read_gc3(void) {
|
|
return floating_bus();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// LC : language card routines
|
|
|
|
static inline void _lc_to_auxmem() {
|
|
if (run_args.softswitches & SS_LCRAM) {
|
|
run_args.base_d000_rd += 0x2000;
|
|
run_args.base_e000_rd = language_card[0]-0xC000;
|
|
}
|
|
|
|
if (run_args.softswitches & SS_LCWRT) {
|
|
run_args.base_d000_wrt += 0x2000;
|
|
run_args.base_e000_wrt = language_card[0]-0xC000;
|
|
}
|
|
}
|
|
|
|
static uint8_t iie_c080(void) {
|
|
run_args.softswitches |= (SS_LCRAM|SS_BANK2);
|
|
run_args.softswitches &= ~(SS_LCSEC|SS_LCWRT);
|
|
|
|
run_args.base_d000_rd = language_banks[0]-0xD000;
|
|
run_args.base_e000_rd = language_card[0]-0xE000;
|
|
|
|
run_args.base_d000_wrt = 0;
|
|
run_args.base_e000_wrt = 0;
|
|
|
|
if (run_args.softswitches & SS_ALTZP) {
|
|
_lc_to_auxmem();
|
|
}
|
|
return floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_c081(void) {
|
|
if (run_args.softswitches & SS_LCSEC) {
|
|
run_args.softswitches |= SS_LCWRT;
|
|
run_args.base_d000_wrt = language_banks[0]-0xD000;
|
|
run_args.base_e000_wrt = language_card[0]-0xE000;
|
|
}
|
|
|
|
run_args.softswitches |= (SS_LCSEC|SS_BANK2);
|
|
run_args.softswitches &= ~SS_LCRAM;
|
|
|
|
run_args.base_d000_rd = apple_ii_64k[0];
|
|
run_args.base_e000_rd = apple_ii_64k[0];
|
|
|
|
if (run_args.softswitches & SS_ALTZP) {
|
|
_lc_to_auxmem();
|
|
}
|
|
return floating_bus();
|
|
}
|
|
|
|
static uint8_t lc_c082(void) {
|
|
run_args.softswitches &= ~(SS_LCRAM|SS_LCWRT|SS_LCSEC);
|
|
run_args.softswitches |= SS_BANK2;
|
|
|
|
run_args.base_d000_rd = apple_ii_64k[0];
|
|
run_args.base_e000_rd = apple_ii_64k[0];
|
|
|
|
run_args.base_d000_wrt = 0;
|
|
run_args.base_e000_wrt = 0;
|
|
|
|
return floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_c083(void) {
|
|
if (run_args.softswitches & SS_LCSEC) {
|
|
run_args.softswitches |= SS_LCWRT;
|
|
run_args.base_d000_wrt = language_banks[0]-0xD000;
|
|
run_args.base_e000_wrt = language_card[0]-0xE000;
|
|
}
|
|
|
|
run_args.softswitches |= (SS_LCSEC|SS_LCRAM|SS_BANK2);
|
|
run_args.base_d000_rd = language_banks[0]-0xD000;
|
|
run_args.base_e000_rd = language_card[0]-0xE000;
|
|
|
|
if (run_args.softswitches & SS_ALTZP) {
|
|
_lc_to_auxmem();
|
|
}
|
|
return floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_c088(void) {
|
|
run_args.softswitches |= SS_LCRAM;
|
|
run_args.softswitches &= ~(SS_LCWRT|SS_LCSEC|SS_BANK2);
|
|
|
|
run_args.base_d000_rd = language_banks[0]-0xC000;
|
|
run_args.base_e000_rd = language_card[0]-0xE000;
|
|
|
|
run_args.base_d000_wrt = 0;
|
|
run_args.base_e000_wrt = 0;
|
|
|
|
if (run_args.softswitches & SS_ALTZP) {
|
|
_lc_to_auxmem();
|
|
}
|
|
return floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_c089(void) {
|
|
if (run_args.softswitches & SS_LCSEC) {
|
|
run_args.softswitches |= SS_LCWRT;
|
|
run_args.base_d000_wrt = language_banks[0]-0xC000;
|
|
run_args.base_e000_wrt = language_card[0]-0xE000;
|
|
}
|
|
|
|
run_args.softswitches |= SS_LCSEC;
|
|
run_args.softswitches &= ~(SS_LCRAM|SS_BANK2);
|
|
|
|
run_args.base_d000_rd = apple_ii_64k[0];
|
|
run_args.base_e000_rd = apple_ii_64k[0];
|
|
|
|
if (run_args.softswitches & SS_ALTZP) {
|
|
_lc_to_auxmem();
|
|
}
|
|
return floating_bus();
|
|
}
|
|
|
|
static uint8_t lc_c08a(void) {
|
|
run_args.softswitches &= ~(SS_LCRAM|SS_LCWRT|SS_LCSEC|SS_BANK2);
|
|
|
|
run_args.base_d000_rd = apple_ii_64k[0];
|
|
run_args.base_e000_rd = apple_ii_64k[0];
|
|
|
|
run_args.base_d000_wrt = 0;
|
|
run_args.base_e000_wrt = 0;
|
|
|
|
return floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_c08b(void) {
|
|
if (run_args.softswitches & SS_LCSEC) {
|
|
run_args.softswitches |= SS_LCWRT;
|
|
run_args.base_d000_wrt = language_banks[0]-0xC000;
|
|
run_args.base_e000_wrt = language_card[0]-0xE000;
|
|
}
|
|
|
|
run_args.softswitches |= (SS_LCRAM|SS_LCSEC);
|
|
run_args.softswitches &= ~SS_BANK2;
|
|
|
|
run_args.base_d000_rd = language_banks[0]-0xC000;
|
|
run_args.base_e000_rd = language_card[0]-0xE000;
|
|
|
|
if (run_args.softswitches & SS_ALTZP) {
|
|
_lc_to_auxmem();
|
|
}
|
|
return floating_bus();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Misc //e softswitches and vm routines
|
|
|
|
static uint8_t iie_80store_off(void) {
|
|
assert((run_args.cpu65_rw&MEM_WRITE_FLAG));
|
|
if (!(run_args.softswitches & SS_80STORE)) {
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
run_args.softswitches &= ~(SS_80STORE|SS_TEXTRD|SS_TEXTWRT|SS_HGRRD|SS_HGRWRT);
|
|
|
|
run_args.base_textrd = apple_ii_64k[0];
|
|
run_args.base_textwrt = apple_ii_64k[0];
|
|
run_args.base_hgrrd = apple_ii_64k[0];
|
|
run_args.base_hgrwrt = apple_ii_64k[0];
|
|
|
|
if (run_args.softswitches & SS_RAMRD) {
|
|
run_args.softswitches |= (SS_TEXTRD|SS_HGRRD);
|
|
run_args.base_textrd = apple_ii_64k[1];
|
|
run_args.base_hgrrd = apple_ii_64k[1];
|
|
}
|
|
|
|
if (run_args.softswitches & SS_RAMWRT) {
|
|
run_args.softswitches |= (SS_TEXTWRT|SS_HGRWRT);
|
|
run_args.base_textwrt = apple_ii_64k[1];
|
|
run_args.base_hgrwrt = apple_ii_64k[1];
|
|
}
|
|
|
|
if (run_args.softswitches & SS_PAGE2) {
|
|
run_args.softswitches |= SS_SCREEN;
|
|
}
|
|
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_80store_on(void) {
|
|
assert((run_args.cpu65_rw&MEM_WRITE_FLAG));
|
|
if (run_args.softswitches & SS_80STORE) {
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
run_args.softswitches |= SS_80STORE;
|
|
|
|
if (run_args.softswitches & SS_PAGE2) {
|
|
run_args.softswitches |= (SS_TEXTRD|SS_TEXTWRT);
|
|
run_args.base_textrd = apple_ii_64k[1];
|
|
run_args.base_textwrt = apple_ii_64k[1];
|
|
if (run_args.softswitches & SS_HIRES) {
|
|
run_args.softswitches |= (SS_HGRRD|SS_HGRWRT);
|
|
run_args.base_hgrrd = apple_ii_64k[1];
|
|
run_args.base_hgrwrt = apple_ii_64k[1];
|
|
}
|
|
} else {
|
|
run_args.softswitches &= ~(SS_TEXTRD|SS_TEXTWRT);
|
|
run_args.base_textrd = apple_ii_64k[0];
|
|
run_args.base_textwrt = apple_ii_64k[0];
|
|
if (run_args.softswitches & SS_HIRES) {
|
|
run_args.softswitches &= ~(SS_HGRRD|SS_HGRWRT);
|
|
run_args.base_hgrrd = apple_ii_64k[0];
|
|
run_args.base_hgrwrt = apple_ii_64k[0];
|
|
}
|
|
}
|
|
|
|
run_args.softswitches &= ~SS_SCREEN;
|
|
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_ramrd_main(void) {
|
|
assert((run_args.cpu65_rw&MEM_WRITE_FLAG));
|
|
if (!(run_args.softswitches & SS_RAMRD)) {
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
run_args.softswitches &= ~SS_RAMRD;
|
|
run_args.base_ramrd = apple_ii_64k[0];
|
|
|
|
if (run_args.softswitches & SS_80STORE) {
|
|
if (!(run_args.softswitches & SS_HIRES)) {
|
|
run_args.softswitches &= ~SS_HGRRD;
|
|
run_args.base_hgrrd = apple_ii_64k[0];
|
|
}
|
|
} else {
|
|
run_args.softswitches &= ~(SS_TEXTRD|SS_HGRRD);
|
|
run_args.base_textrd = apple_ii_64k[0];
|
|
run_args.base_hgrrd = apple_ii_64k[0];
|
|
}
|
|
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_ramrd_aux(void) {
|
|
assert((run_args.cpu65_rw&MEM_WRITE_FLAG));
|
|
if (run_args.softswitches & SS_RAMRD) {
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
run_args.softswitches |= SS_RAMRD;
|
|
run_args.base_ramrd = apple_ii_64k[1];
|
|
|
|
if (run_args.softswitches & SS_80STORE) {
|
|
if (!(run_args.softswitches & SS_HIRES)) {
|
|
run_args.softswitches |= SS_HGRRD;
|
|
run_args.base_hgrrd = apple_ii_64k[1];
|
|
}
|
|
} else {
|
|
run_args.softswitches |= (SS_TEXTRD|SS_HGRRD);
|
|
run_args.base_textrd = apple_ii_64k[1];
|
|
run_args.base_hgrrd = apple_ii_64k[1];
|
|
}
|
|
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_ramwrt_main(void) {
|
|
assert((run_args.cpu65_rw&MEM_WRITE_FLAG));
|
|
if (!(run_args.softswitches & SS_RAMWRT)) {
|
|
return 0x0;// floating_bus();
|
|
}
|
|
|
|
run_args.softswitches &= ~SS_RAMWRT;
|
|
run_args.base_ramwrt = apple_ii_64k[0];
|
|
|
|
if (run_args.softswitches & SS_80STORE) {
|
|
if (!(run_args.softswitches & SS_HIRES)) {
|
|
run_args.softswitches &= ~SS_HGRWRT;
|
|
run_args.base_hgrwrt = apple_ii_64k[0];
|
|
}
|
|
} else {
|
|
run_args.softswitches &= ~(SS_TEXTWRT|SS_HGRWRT);
|
|
run_args.base_textwrt = apple_ii_64k[0];
|
|
run_args.base_hgrwrt = apple_ii_64k[0];
|
|
}
|
|
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_ramwrt_aux(void) {
|
|
assert((run_args.cpu65_rw&MEM_WRITE_FLAG));
|
|
if (run_args.softswitches & SS_RAMWRT) {
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
run_args.softswitches |= SS_RAMWRT;
|
|
run_args.base_ramwrt = apple_ii_64k[1];
|
|
|
|
if (run_args.softswitches & SS_80STORE) {
|
|
if (!(run_args.softswitches & SS_HIRES)) {
|
|
run_args.softswitches |= SS_HGRWRT;
|
|
run_args.base_hgrwrt = apple_ii_64k[1];
|
|
}
|
|
} else {
|
|
run_args.softswitches |= (SS_TEXTWRT|SS_HGRWRT);
|
|
run_args.base_textwrt = apple_ii_64k[1];
|
|
run_args.base_hgrwrt = apple_ii_64k[1];
|
|
}
|
|
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_altzp_main(void) {
|
|
assert((run_args.cpu65_rw&MEM_WRITE_FLAG));
|
|
if (!(run_args.softswitches & SS_ALTZP)) {
|
|
/* NOTE : test if ALTZP already off - due to d000-bank issues it is *needed*, not just a shortcut */
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
run_args.softswitches &= ~SS_ALTZP;
|
|
run_args.base_stackzp = apple_ii_64k[0];
|
|
|
|
if (run_args.softswitches & SS_LCRAM) {
|
|
run_args.base_d000_rd -= 0x2000;
|
|
run_args.base_e000_rd = language_card[0] - 0xE000;
|
|
}
|
|
|
|
if (run_args.softswitches & SS_LCWRT) {
|
|
run_args.base_d000_wrt -= 0x2000;
|
|
run_args.base_e000_wrt = language_card[0] - 0xE000;
|
|
}
|
|
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_altzp_aux(void) {
|
|
assert((run_args.cpu65_rw&MEM_WRITE_FLAG));
|
|
if (run_args.softswitches & SS_ALTZP) {
|
|
/* NOTE : test if ALTZP already on - due to d000-bank issues it is *needed*, not just a shortcut */
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
run_args.softswitches |= SS_ALTZP;
|
|
run_args.base_stackzp = apple_ii_64k[1];
|
|
|
|
_lc_to_auxmem();
|
|
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_80col_off(void) {
|
|
assert((run_args.cpu65_rw&MEM_WRITE_FLAG));
|
|
if (!(run_args.softswitches & SS_80COL)) {
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
run_args.softswitches &= ~SS_80COL;
|
|
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_80col_on(void) {
|
|
assert((run_args.cpu65_rw&MEM_WRITE_FLAG));
|
|
if (run_args.softswitches & SS_80COL) {
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
run_args.softswitches |= SS_80COL;
|
|
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_altchar_off(void) {
|
|
assert((run_args.cpu65_rw&MEM_WRITE_FLAG));
|
|
if (run_args.softswitches & SS_ALTCHAR) {
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
run_args.softswitches &= ~SS_ALTCHAR;
|
|
display_loadFont(/*start:*/0x40, /*qty:*/0x40, /*data:*/ucase_glyphs, FONT_MODE_FLASH);
|
|
}
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_altchar_on(void) {
|
|
assert((run_args.cpu65_rw&MEM_WRITE_FLAG));
|
|
if (!(run_args.softswitches & SS_ALTCHAR)) {
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
run_args.softswitches |= SS_ALTCHAR;
|
|
display_loadFont(/*start:*/0x40, /*qty:*/0x20, /*data:*/mousetext_glyphs, FONT_MODE_MOUSETEXT);
|
|
display_loadFont(/*start:*/0x60, /*qty:*/0x20, /*data:*/lcase_glyphs, FONT_MODE_INVERSE);
|
|
}
|
|
return 0x0;//floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_dhires_on(void) {
|
|
if (!(run_args.softswitches & SS_DHIRES)) {
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
run_args.softswitches |= SS_DHIRES;
|
|
}
|
|
return floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_dhires_off(void) {
|
|
if (run_args.softswitches & SS_DHIRES) {
|
|
video_setDirty(A2_DIRTY_FLAG);
|
|
run_args.softswitches &= ~SS_DHIRES;
|
|
}
|
|
return floating_bus();
|
|
}
|
|
|
|
static uint8_t iie_check_vbl(void) {
|
|
bool isVBL = false;
|
|
video_scannerAddress(&isVBL);
|
|
uint8_t key = apple_ii_64k[0][0xC000];
|
|
return (key & ~0x80) | (isVBL ? 0x00 : 0x80);
|
|
}
|
|
|
|
static uint8_t iie_c3rom_peripheral(void) {
|
|
assert((run_args.cpu65_rw&MEM_WRITE_FLAG));
|
|
run_args.softswitches &= ~SS_C3ROM;
|
|
if (!(run_args.softswitches & SS_CXROM)) {
|
|
run_args.base_c3rom = (void *)iie_read_peripheral_card;
|
|
}
|
|
return 0x0;
|
|
}
|
|
|
|
static uint8_t iie_c3rom_internal(void) {
|
|
assert((run_args.cpu65_rw&MEM_WRITE_FLAG));
|
|
run_args.softswitches |= SS_C3ROM;
|
|
run_args.base_c3rom = apple_ii_64k[1];
|
|
return 0x0;
|
|
}
|
|
|
|
static uint8_t iie_cxrom_peripheral(void) {
|
|
assert((run_args.cpu65_rw&MEM_WRITE_FLAG));
|
|
run_args.softswitches &= ~SS_CXROM;
|
|
run_args.base_cxrom = (void *)iie_read_peripheral_card;
|
|
run_args.base_c4rom = (void *)iie_read_peripheral_card;
|
|
run_args.base_c5rom = (void *)iie_read_peripheral_card;
|
|
if (!(run_args.softswitches & SS_C3ROM)) {
|
|
run_args.base_c3rom = (void *)iie_read_peripheral_card;
|
|
}
|
|
return 0x0;
|
|
}
|
|
|
|
static uint8_t iie_cxrom_internal(void) {
|
|
assert((run_args.cpu65_rw&MEM_WRITE_FLAG));
|
|
run_args.softswitches |= SS_CXROM;
|
|
run_args.base_cxrom = apple_ii_64k[1];
|
|
run_args.base_c3rom = apple_ii_64k[1];
|
|
run_args.base_c4rom = apple_ii_64k[1];
|
|
run_args.base_c5rom = apple_ii_64k[1];
|
|
return 0x0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// C0XX softswitch handlers
|
|
|
|
GLUE_C_READ(read_softswitch)
|
|
{
|
|
uint8_t sw = ea & 0xFF;
|
|
|
|
//return cpu65_c0_r[sw](ea, b);
|
|
|
|
// keyboard data and strobe (READ)
|
|
if (sw >= 0x00 && sw < 0x10) {
|
|
return apple_ii_64k[0][0xC000];
|
|
}
|
|
if (sw == 0x10) {
|
|
return read_keyboard_strobe();
|
|
}
|
|
|
|
if (sw >= 0x11 && sw < 0x20) {
|
|
// RDBNK2 switch
|
|
if (sw == 0x11) {
|
|
return (run_args.softswitches & SS_BANK2) SS_BANK2_SHIFT;
|
|
}
|
|
|
|
// RDLCRAM switch
|
|
if (sw == 0x12) {
|
|
return (run_args.softswitches & SS_LCRAM) SS_LCRAM_SHIFT;
|
|
}
|
|
|
|
// RAMRD switch
|
|
if (sw == 0x13) {
|
|
return (run_args.softswitches & SS_RAMRD) SS_RAMRD_SHIFT;
|
|
}
|
|
|
|
// RAMWRT switch
|
|
if (sw == 0x14) {
|
|
return (run_args.softswitches & SS_RAMWRT) SS_RAMWRT_SHIFT;
|
|
}
|
|
|
|
// SLOTCXROM switch
|
|
if (sw == 0x15) {
|
|
return (run_args.softswitches & SS_CXROM) SS_CXROM_SHIFT;
|
|
}
|
|
|
|
// ALTZP switch
|
|
if (sw == 0x16) {
|
|
return (run_args.softswitches & SS_ALTZP) SS_ALTZP_SHIFT;
|
|
}
|
|
|
|
// SLOTC3ROM switch
|
|
if (sw == 0x17) {
|
|
// reversed pattern!
|
|
return (run_args.softswitches & SS_C3ROM) ? 0x00 : 0x80;
|
|
}
|
|
|
|
// 80STORE switch
|
|
if (sw == 0x18) {
|
|
return (run_args.softswitches & SS_80STORE) SS_80STORE_SHFT;
|
|
}
|
|
|
|
// RDVBLBAR switch
|
|
if (sw == 0x19) {
|
|
return iie_check_vbl();
|
|
}
|
|
|
|
// TEXT check switch
|
|
if (sw == 0x1A) {
|
|
return (run_args.softswitches & SS_TEXT) SS_TEXT_SHIFT;
|
|
}
|
|
|
|
// MIXED check switch
|
|
if (sw == 0x1B) {
|
|
return (run_args.softswitches & SS_MIXED) SS_MIXED_SHIFT;
|
|
}
|
|
|
|
// PAGE2 check switch
|
|
if (sw == 0x1C) {
|
|
return (run_args.softswitches & SS_PAGE2) SS_PAGE2_SHIFT;
|
|
}
|
|
|
|
// HIRES check switch
|
|
if (sw == 0x1D) {
|
|
return (run_args.softswitches & SS_HIRES) SS_HIRES_SHIFT;
|
|
}
|
|
|
|
// ALTCHAR switch
|
|
if (sw == 0x1E) {
|
|
return (run_args.softswitches & SS_ALTCHAR) SS_ALTCHAR_SHFT;
|
|
}
|
|
|
|
// 80COL switch
|
|
if (sw == 0x1F) {
|
|
return (run_args.softswitches & SS_80COL) SS_80COL_SHIFT;
|
|
}
|
|
}
|
|
|
|
if (sw >= 0x30 && sw < 0x40) {
|
|
return speaker_toggle();
|
|
}
|
|
|
|
// TEXT switch
|
|
if (sw == 0x50) {
|
|
return read_switch_graphics();
|
|
}
|
|
if (sw == 0x51) {
|
|
return read_switch_text();
|
|
}
|
|
|
|
// MIXED switch
|
|
if (sw == 0x52) {
|
|
return read_switch_no_mixed();
|
|
}
|
|
if (sw == 0x53) {
|
|
return read_switch_mixed();
|
|
}
|
|
|
|
// PAGE2 switch
|
|
if (sw == 0x54) {
|
|
return iie_page2_off();
|
|
}
|
|
if (sw == 0x55) {
|
|
return iie_page2_on();
|
|
}
|
|
|
|
// HIRES switch
|
|
if (sw == 0x56) {
|
|
return iie_hires_off();
|
|
}
|
|
if (sw == 0x57) {
|
|
return iie_hires_on();
|
|
}
|
|
|
|
// Annunciator
|
|
if (sw >= 0x58 && sw < 0x5E) {
|
|
return iie_annunciator(ea);
|
|
}
|
|
|
|
// DHIRES
|
|
if (sw == 0x5E) {
|
|
return iie_dhires_on();
|
|
}
|
|
if (sw == 0x5F) {
|
|
return iie_dhires_off();
|
|
}
|
|
|
|
// game I/O switches
|
|
if (sw == 0x61 || sw == 0x69) {
|
|
return read_button0();
|
|
}
|
|
if (sw == 0x62 || sw == 0x6A) {
|
|
return read_button1();
|
|
}
|
|
if (sw == 0x63 || sw == 0x6B) {
|
|
return read_button2();
|
|
}
|
|
if (sw == 0x64 || sw == 0x6C) {
|
|
return read_gc0();
|
|
}
|
|
if (sw == 0x65 || sw == 0x6D) {
|
|
return read_gc1();
|
|
}
|
|
|
|
if (sw == 0x66) {
|
|
return iie_read_gc2();
|
|
}
|
|
if (sw == 0x67) {
|
|
return iie_read_gc3();
|
|
}
|
|
|
|
if (sw >= 0x70 && sw < 0x7E) {
|
|
return read_gc_strobe();
|
|
}
|
|
|
|
// IOUDIS switch & read_gc_strobe
|
|
// HACK FIXME TODO : double-check this stuff against AWin...
|
|
if (sw == 0x7E) {
|
|
read_gc_strobe();
|
|
return (run_args.softswitches & SS_IOUDIS) SS_IOUDIS_SHIFT;
|
|
}
|
|
if (sw == 0x7F) {
|
|
read_gc_strobe(); // HACK FIXME : is this correct?
|
|
return (run_args.softswitches & SS_DHIRES) SS_DHIRES_SHIFT;
|
|
}
|
|
|
|
// language card softswitches
|
|
if (sw == 0x80 || sw == 0x84) {
|
|
return iie_c080();
|
|
}
|
|
if (sw == 0x81 || sw == 0x85) {
|
|
return iie_c081();
|
|
}
|
|
if (sw == 0x82 || sw == 0x86) {
|
|
return lc_c082();
|
|
}
|
|
if (sw == 0x83 || sw == 0x87) {
|
|
return iie_c083();
|
|
}
|
|
|
|
if (sw == 0x88 || sw == 0x8C) {
|
|
return iie_c088();
|
|
}
|
|
if (sw == 0x89 || sw == 0x8D) {
|
|
return iie_c089();
|
|
}
|
|
if (sw == 0x8A || sw == 0x8E) {
|
|
return lc_c08a();
|
|
}
|
|
if (sw == 0x8B || sw == 0x8F) {
|
|
return iie_c08b();
|
|
}
|
|
|
|
if (sw >= 0xE0 && sw < 0xF0) {
|
|
// disk softswitches
|
|
// 0xC0Xi : X = slot 0x6 + 0x8 == 0xE
|
|
return disk6_ioRead(ea);
|
|
}
|
|
|
|
return floating_bus();
|
|
}
|
|
|
|
GLUE_C_WRITE(write_softswitch)
|
|
{
|
|
uint8_t sw = ea & 0xFF;
|
|
|
|
if (sw == 0x00) {
|
|
iie_80store_off();
|
|
}
|
|
if (sw == 0x01) {
|
|
iie_80store_on();
|
|
}
|
|
|
|
// RAMRD switch
|
|
if (sw == 0x02) {
|
|
iie_ramrd_main();
|
|
}
|
|
if (sw == 0x03) {
|
|
iie_ramrd_aux();
|
|
}
|
|
|
|
// RAMWRT switch
|
|
if (sw == 0x04) {
|
|
iie_ramwrt_main();
|
|
}
|
|
if (sw == 0x05) {
|
|
iie_ramwrt_aux();
|
|
}
|
|
|
|
// SLOTCXROM switch
|
|
if (sw == 0x06) {
|
|
iie_cxrom_peripheral();
|
|
}
|
|
if (sw == 0x07) {
|
|
iie_cxrom_internal();
|
|
}
|
|
|
|
// ALTZP switch
|
|
if (sw == 0x08) {
|
|
iie_altzp_main();
|
|
}
|
|
if (sw == 0x09) {
|
|
iie_altzp_aux();
|
|
}
|
|
|
|
// SLOTC3ROM switch
|
|
if (sw == 0x0A) {
|
|
iie_c3rom_internal();
|
|
}
|
|
if (sw == 0x0B) {
|
|
iie_c3rom_peripheral();
|
|
}
|
|
|
|
// 80COL switch
|
|
if (sw == 0x0C) {
|
|
iie_80col_off();
|
|
}
|
|
if (sw == 0x0D) {
|
|
iie_80col_on();
|
|
}
|
|
|
|
// ALTCHAR switch
|
|
if (sw == 0x0E) {
|
|
iie_altchar_off();
|
|
}
|
|
if (sw == 0x0F) {
|
|
iie_altchar_on();
|
|
}
|
|
|
|
if (sw >= 0x10 && sw < 0x20) {
|
|
read_keyboard_strobe();
|
|
}
|
|
|
|
if (sw >= 0x30 && sw < 0x40) {
|
|
speaker_toggle();
|
|
}
|
|
|
|
// TEXT switch
|
|
if (sw == 0x50) {
|
|
read_switch_graphics();
|
|
}
|
|
if (sw == 0x51) {
|
|
read_switch_text();
|
|
}
|
|
|
|
// MIXED switch
|
|
if (sw == 0x52) {
|
|
read_switch_no_mixed();
|
|
}
|
|
if (sw == 0x53) {
|
|
read_switch_mixed();
|
|
}
|
|
|
|
// PAGE2 switch
|
|
if (sw == 0x54) {
|
|
iie_page2_off();
|
|
}
|
|
if (sw == 0x55) {
|
|
iie_page2_on();
|
|
}
|
|
|
|
// HIRES switch
|
|
if (sw == 0x56) {
|
|
iie_hires_off();
|
|
}
|
|
if (sw == 0x57) {
|
|
iie_hires_on();
|
|
}
|
|
|
|
// Annunciator
|
|
if (sw >= 0x58 && sw < 0x5E) {
|
|
iie_annunciator(ea);
|
|
}
|
|
|
|
// DHIRES
|
|
if (sw == 0x5E) {
|
|
iie_dhires_on();
|
|
}
|
|
if (sw == 0x5F) {
|
|
iie_dhires_off();
|
|
}
|
|
|
|
if (sw >= 0x70 && sw < 0x7E) {
|
|
read_gc_strobe();
|
|
}
|
|
|
|
// IOUDIS switch & read_gc_strobe
|
|
// HACK FIXME TODO : double-check this stuff against AWin...
|
|
if (sw == 0x7E) {
|
|
run_args.softswitches |= SS_IOUDIS;
|
|
read_gc_strobe();
|
|
}
|
|
if (sw == 0x7F) {
|
|
run_args.softswitches &= ~SS_IOUDIS;
|
|
read_gc_strobe();
|
|
}
|
|
|
|
// language card softswitches
|
|
if (sw == 0x80 || sw == 0x84) {
|
|
iie_c080();
|
|
}
|
|
if (sw == 0x81 || sw == 0x85) {
|
|
iie_c081();
|
|
}
|
|
if (sw == 0x82 || sw == 0x86) {
|
|
lc_c082();
|
|
}
|
|
if (sw == 0x83 || sw == 0x87) {
|
|
iie_c083();
|
|
}
|
|
|
|
if (sw == 0x88 || sw == 0x8C) {
|
|
iie_c088();
|
|
}
|
|
if (sw == 0x89 || sw == 0x8D) {
|
|
iie_c089();
|
|
}
|
|
if (sw == 0x8A || sw == 0x8E) {
|
|
lc_c08a();
|
|
}
|
|
if (sw == 0x8B || sw == 0x8F) {
|
|
iie_c08b();
|
|
}
|
|
|
|
if (sw >= 0xE0 && sw < 0xF0) {
|
|
disk6_ioWrite(ea, b);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// //e expansion ROM
|
|
|
|
GLUE_C_READ(iie_read_slot_expansion)
|
|
{
|
|
// HACK TODO FIXME : how does the expansion slot get referenced? Need to handle other ROMs that might use this area
|
|
// ... Also Need moar tests ...
|
|
if (ea == 0xCFFF) {
|
|
// disable expansion ROM
|
|
return floating_bus();
|
|
}
|
|
|
|
return apple_ii_64k[1][ea];
|
|
}
|
|
|
|
GLUE_C_WRITE(debug_illegal_bcd)
|
|
{
|
|
LOG("Illegal/undefined BCD operation encountered, debug break on c_debug_illegal_bcd to debug...");
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
static void _initialize_iie_switches(void) {
|
|
|
|
run_args.base_stackzp = apple_ii_64k[0];
|
|
run_args.base_d000_rd = apple_ii_64k[0];
|
|
run_args.base_d000_wrt = language_banks[0] - 0xD000;
|
|
run_args.base_e000_rd = apple_ii_64k[0];
|
|
run_args.base_e000_wrt = language_card[0] - 0xE000;
|
|
|
|
run_args.base_ramrd = apple_ii_64k[0];
|
|
run_args.base_ramwrt = apple_ii_64k[0];
|
|
run_args.base_textrd = apple_ii_64k[0];
|
|
run_args.base_textwrt = apple_ii_64k[0];
|
|
run_args.base_hgrrd = apple_ii_64k[0];
|
|
run_args.base_hgrwrt= apple_ii_64k[0];
|
|
|
|
run_args.base_c3rom = (void *)iie_read_peripheral_card; // c3rom internal
|
|
run_args.base_c4rom = (void *)iie_read_peripheral_card; // c4rom internal
|
|
run_args.base_c5rom = (void *)iie_read_peripheral_card; // c5rom internal
|
|
run_args.base_cxrom = (void *)iie_read_peripheral_card; // cxrom peripheral
|
|
|
|
run_args.softswitches = SS_TEXT | SS_BANK2;
|
|
}
|
|
|
|
static void _initialize_font(void) {
|
|
display_loadFont(/*start:*/0x00, /*qty:*/0x40, /*data:*/ucase_glyphs, FONT_MODE_INVERSE);
|
|
display_loadFont(/*start:*/0x40, /*qty:*/0x40, /*data:*/ucase_glyphs, FONT_MODE_FLASH);
|
|
display_loadFont(/*start:*/0x80, /*qty:*/0x40, /*data:*/ucase_glyphs, FONT_MODE_NORMAL);
|
|
display_loadFont(/*start:*/0xC0, /*qty:*/0x20, /*data:*/ucase_glyphs, FONT_MODE_NORMAL);
|
|
display_loadFont(/*start:*/0xE0, /*qty:*/0x20, /*data:*/lcase_glyphs, FONT_MODE_NORMAL);
|
|
}
|
|
|
|
static void _initialize_apple_ii_memory(void) {
|
|
for (unsigned int i = 0; i < 0x10000; i++) {
|
|
apple_ii_64k[0][i] = 0;
|
|
apple_ii_64k[1][i] = 0;
|
|
}
|
|
|
|
// Stripe words of main memory on machine reset ...
|
|
// NOTE: cracked version of Joust will lock up without this
|
|
for (unsigned int i = 0; i < 0xC000;) {
|
|
apple_ii_64k[0][i++] = 0xFF;
|
|
apple_ii_64k[0][i++] = 0xFF;
|
|
i += 2;
|
|
}
|
|
|
|
#if !TESTING && !CPU_TRACING && !VIDEO_TRACING
|
|
// certain memory locations randomized at cold-boot ...
|
|
for (uint16_t addr = 0x0000; addr < 0xC000; addr += 0x200)
|
|
{
|
|
uint16_t word;
|
|
|
|
word = random();
|
|
apple_ii_64k[0][addr + 0x28] = (word >> 0) & 0xFF;
|
|
apple_ii_64k[0][addr + 0x29] = (word >> 8) & 0xFF;
|
|
|
|
word = random();
|
|
apple_ii_64k[0][addr + 0x68] = (word >> 0) & 0xFF;
|
|
apple_ii_64k[0][addr + 0x69] = (word >> 8) & 0xFF;
|
|
}
|
|
|
|
// memory initialization workarounds ...
|
|
{
|
|
// https://github.com/AppleWin/AppleWin/issues/206
|
|
// work around cold-booting bug in "Pooyan" which expects RNDL and RNDH to be non-zero
|
|
// "Dung Beetles, Ms. PacMan, Pooyan, Star Cruiser, Star Thief, Invas. Force.dsk"
|
|
uint16_t word = (uint16_t)random();
|
|
apple_ii_64k[0][0x4E] = 0x20 | ((word >> 0) & 0xFF);
|
|
apple_ii_64k[0][0x4F] = 0x20 | ((word >> 8) & 0xFF);
|
|
}
|
|
#endif
|
|
|
|
for (unsigned int i = 0; i < 8192; i++) {
|
|
language_card[0][i] = language_card[1][i] = 0;
|
|
}
|
|
|
|
for (unsigned int i = 0; i < 8192; i++) {
|
|
language_banks[0][i] = language_banks[1][i] = 0;
|
|
}
|
|
|
|
// load the rom from 0xC000, slot rom main, internal rom aux
|
|
|
|
for (unsigned int i = 0xC000; i < 0x10000; i++) {
|
|
apple_ii_64k[0][i] = apple_iie_rom[i - 0xC000];
|
|
apple_ii_64k[1][i] = apple_iie_rom[i - 0x8000];
|
|
}
|
|
|
|
for (unsigned int i = 0; i < 0x1000; i++) {
|
|
language_banks[0][i] = apple_iie_rom[i + 0x1000];
|
|
language_banks[1][i] = apple_iie_rom[i + 0x5000];
|
|
}
|
|
|
|
for (unsigned int i = 0; i < 0x2000; i++) {
|
|
language_card[0][i] = apple_iie_rom[i + 0x2000];
|
|
language_card[1][i] = apple_iie_rom[i + 0x6000];
|
|
}
|
|
|
|
apple_ii_64k[0][0xC000] = 0x00;
|
|
apple_ii_64k[1][0xC000] = 0x00;
|
|
}
|
|
|
|
static void _initialize_tables(void) {
|
|
|
|
for (unsigned int i = 0; i < 0x100; i++) {
|
|
cpu65_vmem_r[i] = iie_read_ram_default;
|
|
cpu65_vmem_w[i] = iie_write_ram_default;
|
|
}
|
|
|
|
for (unsigned int i = 0xC0; i < 0xD0; i++) {
|
|
cpu65_vmem_w[i] = write_ram_nop;
|
|
}
|
|
|
|
// language card read/write area
|
|
|
|
for (unsigned int i = 0xD0; i < 0xE0; i++) {
|
|
cpu65_vmem_w[i] = write_ram_bank;
|
|
cpu65_vmem_r[i] = read_ram_bank;
|
|
}
|
|
|
|
for (unsigned int i = 0xE0; i < 0x100; i++) {
|
|
cpu65_vmem_w[i] = write_ram_lc;
|
|
cpu65_vmem_r[i] = read_ram_lc;
|
|
}
|
|
|
|
// done common initialization
|
|
|
|
// initialize zero-page, //e specific
|
|
cpu65_vmem_r[0] = iie_read_ram_zpage_and_stack;
|
|
cpu65_vmem_w[0] = iie_write_ram_zpage_and_stack;
|
|
cpu65_vmem_r[1] = iie_read_ram_zpage_and_stack;
|
|
cpu65_vmem_w[1] = iie_write_ram_zpage_and_stack;
|
|
|
|
// initialize first text & hires page, which are specially bank switched
|
|
cpu65_vmem_r[4] = iie_read_ram_text_page0;
|
|
cpu65_vmem_r[5] = iie_read_ram_text_page0;
|
|
cpu65_vmem_r[6] = iie_read_ram_text_page0;
|
|
cpu65_vmem_r[7] = iie_read_ram_text_page0;
|
|
|
|
for (unsigned int i = 0x20; i < 0x40; i++) {
|
|
cpu65_vmem_r[i] = iie_read_ram_hires_page0;
|
|
}
|
|
|
|
// initialize text/lores & hires graphics routines
|
|
for (unsigned int y = 0; y < TEXT_ROWS; y++) {
|
|
uint16_t row = display_getVideoLineOffset(y);
|
|
for (unsigned int x = 0; x < TEXT_COLS; x++) {
|
|
unsigned int idx = row + x;
|
|
|
|
// NOTE : we are doing too much work here calculating the lo_byte positions, but eh, this is just one-time setup :P
|
|
|
|
// text/lores pages
|
|
if (y < 20) {
|
|
cpu65_vmem_w[(idx+0x400)>>8] = video__write_2e_text0;
|
|
cpu65_vmem_w[(idx+0x800)>>8] = video__write_2e_text1;
|
|
} else {
|
|
cpu65_vmem_w[(idx+0x400)>>8] = video__write_2e_text0_mixed;
|
|
cpu65_vmem_w[(idx+0x800)>>8] = video__write_2e_text1_mixed;
|
|
}
|
|
|
|
// hires/dhires pages
|
|
for (unsigned int i = 0; i < 8; i++) {
|
|
idx = row + (0x400*i) + x;
|
|
if (y < 20) {
|
|
cpu65_vmem_w[(idx+0x2000)>>8] = video__write_2e_hgr0;
|
|
cpu65_vmem_w[(idx+0x4000)>>8] = video__write_2e_hgr1;
|
|
} else {
|
|
cpu65_vmem_w[(idx+0x2000)>>8] = video__write_2e_hgr0_mixed;
|
|
cpu65_vmem_w[(idx+0x4000)>>8] = video__write_2e_hgr1_mixed;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// softswich rom
|
|
cpu65_vmem_r[0xC0] = read_softswitch;
|
|
cpu65_vmem_w[0xC0] = write_softswitch;
|
|
|
|
// slot i/o area
|
|
cpu65_vmem_r[0xC1] = iie_read_slotx; // slots 1
|
|
cpu65_vmem_r[0xC2] = iie_read_slotx; // slots 2
|
|
cpu65_vmem_r[0xC3] = iie_read_slot3; // slot 3 (80col)
|
|
cpu65_vmem_r[0xC4] = iie_read_slot4; // slot 4 - MB or Phasor
|
|
cpu65_vmem_r[0xC5] = iie_read_slot5; // slot 5 - MB #2
|
|
cpu65_vmem_r[0xC6] = iie_read_slotx; // slots 6
|
|
cpu65_vmem_r[0xC7] = iie_read_slotx; // slots 7
|
|
|
|
for (unsigned int i = 0xC8; i < 0xD0; i++) {
|
|
cpu65_vmem_r[i] = iie_read_slot_expansion;
|
|
}
|
|
|
|
// Peripheral card slot initializations ...
|
|
|
|
// HACK TODO FIXME : this needs to be tied to the UI/configuration system (once we have more/conflicting options)
|
|
|
|
// FIXME TODO : implement pluggable peripheral API
|
|
//if (mockingboard_inserted) {
|
|
mb_io_initialize(4, 5); /* Mockingboard(s) and/or Phasor in slots 4 & 5 */
|
|
//}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
void vm_initialize(void) {
|
|
_initialize_font();
|
|
_initialize_apple_ii_memory();
|
|
_initialize_tables();
|
|
disk6_init();
|
|
_initialize_iie_switches();
|
|
joystick_reset();
|
|
}
|
|
|
|
bool vm_saveState(StateHelper_s *helper) {
|
|
bool saved = false;
|
|
int fd = helper->fd;
|
|
|
|
do {
|
|
uint8_t serialized[8] = { 0 };
|
|
|
|
serialized[0] = (uint8_t)((run_args.softswitches & 0xFF000000) >> 24);
|
|
serialized[1] = (uint8_t)((run_args.softswitches & 0xFF0000 ) >> 16);
|
|
serialized[2] = (uint8_t)((run_args.softswitches & 0xFF00 ) >> 8);
|
|
serialized[3] = (uint8_t)((run_args.softswitches & 0xFF ) >> 0);
|
|
if (!helper->save(fd, serialized, sizeof(run_args.softswitches))) {
|
|
break;
|
|
}
|
|
|
|
// save main/aux memory state
|
|
if (!helper->save(fd, apple_ii_64k[0], sizeof(apple_ii_64k))) {
|
|
break;
|
|
}
|
|
|
|
// save language card
|
|
if (!helper->save(fd, language_card[0], sizeof(language_card))) {
|
|
break;
|
|
}
|
|
|
|
// save language banks
|
|
if (!helper->save(fd, language_banks[0], sizeof(language_banks))) {
|
|
break;
|
|
}
|
|
|
|
// save offsets
|
|
serialized[0] = 0x0;
|
|
serialized[1] = 0x1;
|
|
serialized[2] = 0x2;
|
|
serialized[3] = 0x3;
|
|
serialized[4] = 0x4;
|
|
serialized[5] = 0x5;
|
|
if (!helper->save(fd, (run_args.base_ramrd == apple_ii_64k[0]) ? &serialized[0] : &serialized[1], 1)) {
|
|
break;
|
|
}
|
|
if (!helper->save(fd, (run_args.base_ramwrt == apple_ii_64k[0]) ? &serialized[0] : &serialized[1], 1)) {
|
|
break;
|
|
}
|
|
if (!helper->save(fd, (run_args.base_textrd == apple_ii_64k[0]) ? &serialized[0] : &serialized[1], 1)) {
|
|
break;
|
|
}
|
|
if (!helper->save(fd, (run_args.base_textwrt == apple_ii_64k[0]) ? &serialized[0] : &serialized[1], 1)) {
|
|
break;
|
|
}
|
|
if (!helper->save(fd, (run_args.base_hgrrd == apple_ii_64k[0]) ? &serialized[0] : &serialized[1], 1)) {
|
|
break;
|
|
}
|
|
if (!helper->save(fd, (run_args.base_hgrwrt == apple_ii_64k[0]) ? &serialized[0] : &serialized[1], 1)) {
|
|
break;
|
|
}
|
|
if (!helper->save(fd, (run_args.base_stackzp == apple_ii_64k[0]) ? &serialized[0] : &serialized[1], 1)) {
|
|
break;
|
|
}
|
|
if (!helper->save(fd, (run_args.base_c3rom == (void *)iie_read_peripheral_card) ? &serialized[0] : &serialized[1], 1)) {
|
|
break;
|
|
}
|
|
|
|
if (!helper->save(fd, (run_args.base_cxrom == (void *)iie_read_peripheral_card) ? &serialized[0] : &serialized[1], 1)) {
|
|
break;
|
|
}
|
|
|
|
if (run_args.base_d000_rd == apple_ii_64k[0]) {
|
|
if (!helper->save(fd, &serialized[0], 1)) { // base_d000_rd --> //e ROM
|
|
break;
|
|
}
|
|
} else if (run_args.base_d000_rd == language_banks[0] - 0xD000) {
|
|
if (!helper->save(fd, &serialized[2], 1)) { // base_d000_rd --> main LC mem
|
|
break;
|
|
}
|
|
} else if (run_args.base_d000_rd == language_banks[0] - 0xC000) {
|
|
if (!helper->save(fd, &serialized[3], 1)) { // base_d000_rd --> main LC mem
|
|
break;
|
|
}
|
|
} else if (run_args.base_d000_rd == language_banks[1] - 0xD000) {
|
|
if (!helper->save(fd, &serialized[4], 1)) { // base_d000_rd --> aux LC mem
|
|
break;
|
|
}
|
|
} else if (run_args.base_d000_rd == language_banks[1] - 0xC000) {
|
|
if (!helper->save(fd, &serialized[5], 1)) { // base_d000_rd --> aux LC mem
|
|
break;
|
|
}
|
|
} else {
|
|
LOG("OOPS ... language_banks[0] == %p base_d000_rd == %p", language_banks[0], run_args.base_d000_rd);
|
|
assert(false);
|
|
}
|
|
|
|
if (run_args.base_d000_wrt == 0) {
|
|
if (!helper->save(fd, &serialized[0], 1)) { // base_d000_wrt --> no write
|
|
break;
|
|
}
|
|
} else if (run_args.base_d000_wrt == language_banks[0] - 0xD000) {
|
|
if (!helper->save(fd, &serialized[2], 1)) { // base_d000_wrt --> main LC mem
|
|
break;
|
|
}
|
|
} else if (run_args.base_d000_wrt == language_banks[0] - 0xC000) {
|
|
if (!helper->save(fd, &serialized[3], 1)) { // base_d000_wrt --> main LC mem
|
|
break;
|
|
}
|
|
} else if (run_args.base_d000_wrt == language_banks[1] - 0xD000) {
|
|
if (!helper->save(fd, &serialized[4], 1)) { // base_d000_wrt --> aux LC mem
|
|
break;
|
|
}
|
|
} else if (run_args.base_d000_wrt == language_banks[1] - 0xC000) {
|
|
if (!helper->save(fd, &serialized[5], 1)) { // base_d000_wrt --> aux LC mem
|
|
break;
|
|
}
|
|
} else {
|
|
LOG("OOPS ... language_banks[0] == %p run_args.base_d000_wrt == %p", language_banks[0], run_args.base_d000_wrt);
|
|
assert(false);
|
|
}
|
|
|
|
if (run_args.base_e000_rd == apple_ii_64k[0]) {
|
|
if (!helper->save(fd, &serialized[0], 1)) { // base_e000_rd --> //e ROM
|
|
break;
|
|
}
|
|
} else if (run_args.base_e000_rd == language_card[0] - 0xE000) {
|
|
if (!helper->save(fd, &serialized[2], 1)) { // base_e000_rd --> main LC mem
|
|
break;
|
|
}
|
|
} else if (run_args.base_e000_rd == language_card[0] - 0xC000) {
|
|
if (!helper->save(fd, &serialized[3], 1)) { // base_e000_rd --> aux LC mem
|
|
break;
|
|
}
|
|
} else {
|
|
LOG("OOPS ... language_card[0] == %p run_args.base_e000_rd == %p", language_card[0], run_args.base_e000_rd);
|
|
assert(false);
|
|
}
|
|
|
|
if (run_args.base_e000_wrt == 0) {
|
|
if (!helper->save(fd, &serialized[0], 1)) { // base_e000_wrt --> no write
|
|
break;
|
|
}
|
|
} else if (run_args.base_e000_wrt == language_card[0] - 0xE000) {
|
|
if (!helper->save(fd, &serialized[2], 1)) { // base_e000_wrt --> main LC mem
|
|
break;
|
|
}
|
|
} else if (run_args.base_e000_wrt == language_card[0] - 0xC000) {
|
|
if (!helper->save(fd, &serialized[3], 1)) { // base_e000_wrt --> aux LC mem
|
|
break;
|
|
}
|
|
} else {
|
|
LOG("OOPS ... language_card[0] == %p run_args.base_e000_wrt == %p", language_card[0], run_args.base_e000_wrt);
|
|
assert(false);
|
|
}
|
|
|
|
saved = true;
|
|
} while (0);
|
|
|
|
return saved;
|
|
}
|
|
|
|
bool vm_loadState(StateHelper_s *helper) {
|
|
bool loaded = false;
|
|
int fd = helper->fd;
|
|
|
|
do {
|
|
|
|
uint8_t serialized[4] = { 0 };
|
|
|
|
if (!helper->load(fd, serialized, sizeof(uint32_t))) {
|
|
break;
|
|
}
|
|
run_args.softswitches = (uint32_t)(serialized[0] << 24);
|
|
run_args.softswitches |= (uint32_t)(serialized[1] << 16);
|
|
run_args.softswitches |= (uint32_t)(serialized[2] << 8);
|
|
run_args.softswitches |= (uint32_t)(serialized[3] << 0);
|
|
|
|
// load main/aux memory state
|
|
if (!helper->load(fd, apple_ii_64k[0], sizeof(apple_ii_64k))) {
|
|
break;
|
|
}
|
|
|
|
// load language card
|
|
if (!helper->load(fd, language_card[0], sizeof(language_card))) {
|
|
break;
|
|
}
|
|
|
|
// load language banks
|
|
if (!helper->load(fd, language_banks[0], sizeof(language_banks))) {
|
|
break;
|
|
}
|
|
|
|
// load offsets
|
|
uint8_t state = 0x0;
|
|
if (!helper->load(fd, &state, 1)) {
|
|
break;
|
|
}
|
|
run_args.base_ramrd = state == 0x0 ? apple_ii_64k[0] : apple_ii_64k[1];
|
|
|
|
if (!helper->load(fd, &state, 1)) {
|
|
break;
|
|
}
|
|
run_args.base_ramwrt = state == 0x0 ? apple_ii_64k[0] : apple_ii_64k[1];
|
|
|
|
if (!helper->load(fd, &state, 1)) {
|
|
break;
|
|
}
|
|
run_args.base_textrd = state == 0x0 ? apple_ii_64k[0] : apple_ii_64k[1];
|
|
|
|
if (!helper->load(fd, &state, 1)) {
|
|
break;
|
|
}
|
|
run_args.base_textwrt = state == 0x0 ? apple_ii_64k[0] : apple_ii_64k[1];
|
|
|
|
if (!helper->load(fd, &state, 1)) {
|
|
break;
|
|
}
|
|
run_args.base_hgrrd = state == 0x0 ? apple_ii_64k[0] : apple_ii_64k[1];
|
|
|
|
if (!helper->load(fd, &state, 1)) {
|
|
break;
|
|
}
|
|
run_args.base_hgrwrt = state == 0x0 ? apple_ii_64k[0] : apple_ii_64k[1];
|
|
|
|
if (!helper->load(fd, &state, 1)) {
|
|
break;
|
|
}
|
|
run_args.base_stackzp = state == 0x0 ? apple_ii_64k[0] : apple_ii_64k[1];
|
|
|
|
if (!helper->load(fd, &state, 1)) {
|
|
break;
|
|
}
|
|
run_args.base_c3rom = state == 0x0 ? (void *)iie_read_peripheral_card : apple_ii_64k[1];
|
|
|
|
if (!helper->load(fd, &state, 1)) {
|
|
break;
|
|
}
|
|
if (state == 0) {
|
|
run_args.base_cxrom = (void *)iie_read_peripheral_card;
|
|
run_args.base_c4rom = (void *)iie_read_peripheral_card;
|
|
run_args.base_c5rom = (void *)iie_read_peripheral_card;
|
|
} else {
|
|
run_args.base_cxrom = apple_ii_64k[1];
|
|
run_args.base_c4rom = apple_ii_64k[1];
|
|
run_args.base_c5rom = apple_ii_64k[1];
|
|
}
|
|
|
|
if (!helper->load(fd, &state, 1)) {
|
|
break;
|
|
}
|
|
switch (state) {
|
|
case 0:
|
|
run_args.base_d000_rd = apple_ii_64k[0];
|
|
break;
|
|
case 2:
|
|
run_args.base_d000_rd = language_banks[0] - 0xD000;
|
|
break;
|
|
case 3:
|
|
run_args.base_d000_rd = language_banks[0] - 0xC000;
|
|
break;
|
|
case 4:
|
|
run_args.base_d000_rd = language_banks[1] - 0xD000;
|
|
break;
|
|
case 5:
|
|
run_args.base_d000_rd = language_banks[1] - 0xC000;
|
|
break;
|
|
default:
|
|
LOG("Unknown state base_d000_rd %02x", state);
|
|
assert(false);
|
|
break;
|
|
}
|
|
|
|
if (!helper->load(fd, &state, 1)) {
|
|
break;
|
|
}
|
|
switch (state) {
|
|
case 0:
|
|
run_args.base_d000_wrt = 0;
|
|
break;
|
|
case 2:
|
|
run_args.base_d000_wrt = language_banks[0] - 0xD000;
|
|
break;
|
|
case 3:
|
|
run_args.base_d000_wrt = language_banks[0] - 0xC000;
|
|
break;
|
|
case 4:
|
|
run_args.base_d000_wrt = language_banks[1] - 0xD000;
|
|
break;
|
|
case 5:
|
|
run_args.base_d000_wrt = language_banks[1] - 0xC000;
|
|
break;
|
|
default:
|
|
LOG("Unknown state base_d000_wrt %02x", state);
|
|
assert(false);
|
|
break;
|
|
}
|
|
|
|
if (!helper->load(fd, &state, 1)) {
|
|
break;
|
|
}
|
|
switch (state) {
|
|
case 0:
|
|
run_args.base_e000_rd = apple_ii_64k[0];
|
|
break;
|
|
case 2:
|
|
run_args.base_e000_rd = language_card[0] - 0xE000;
|
|
break;
|
|
case 3:
|
|
run_args.base_e000_rd = language_card[0] - 0xC000;
|
|
break;
|
|
default:
|
|
LOG("Unknown state base_e000_rd %02x", state);
|
|
assert(false);
|
|
break;
|
|
}
|
|
|
|
if (!helper->load(fd, &state, 1)) {
|
|
break;
|
|
}
|
|
switch (state) {
|
|
case 0:
|
|
run_args.base_e000_wrt = 0;
|
|
break;
|
|
case 2:
|
|
run_args.base_e000_wrt = language_card[0] - 0xE000;
|
|
break;
|
|
case 3:
|
|
run_args.base_e000_wrt = language_card[0] - 0xC000;
|
|
break;
|
|
default:
|
|
LOG("Unknown state base_e000_wrt %02x", state);
|
|
assert(false);
|
|
break;
|
|
}
|
|
LOG("LOAD run_args.base_e000_wrt = %d", state);
|
|
|
|
loaded = true;
|
|
} while (0);
|
|
|
|
return loaded;
|
|
}
|
|
|
|
void vm_printSoftwitches(FILE *fp, bool output_mem, bool output_pseudo) {
|
|
|
|
fprintf(fp, "[");
|
|
if (run_args.softswitches & SS_TEXT) {
|
|
fprintf(fp, " TEXT");
|
|
}
|
|
if (run_args.softswitches & SS_MIXED) {
|
|
fprintf(fp, " MIXED");
|
|
}
|
|
if (run_args.softswitches & SS_HIRES) {
|
|
fprintf(fp, " HIRES");
|
|
}
|
|
if (run_args.softswitches & SS_PAGE2) {
|
|
fprintf(fp, " PAGE2");
|
|
}
|
|
if (run_args.softswitches & SS_80STORE) {
|
|
fprintf(fp, " 80STORE");
|
|
}
|
|
if (run_args.softswitches & SS_80COL) {
|
|
fprintf(fp, " 80COL");
|
|
}
|
|
if (run_args.softswitches & SS_DHIRES) {
|
|
fprintf(fp, " DHIRES");
|
|
}
|
|
if (run_args.softswitches & SS_ALTCHAR) {
|
|
fprintf(fp, " ALTCHAR");
|
|
}
|
|
|
|
if (output_mem) {
|
|
if (run_args.softswitches & SS_BANK2) {
|
|
fprintf(fp, " BANK2");
|
|
}
|
|
if (run_args.softswitches & SS_LCRAM) {
|
|
fprintf(fp, " LCRAM");
|
|
}
|
|
if (run_args.softswitches & SS_RAMRD) {
|
|
fprintf(fp, " RAMRD");
|
|
}
|
|
if (run_args.softswitches & SS_RAMWRT) {
|
|
fprintf(fp, " RAMWRT");
|
|
}
|
|
if (run_args.softswitches & SS_ALTZP) {
|
|
fprintf(fp, " ALTZP");
|
|
}
|
|
if (run_args.softswitches & SS_IOUDIS) {
|
|
fprintf(fp, " IOUDIS");
|
|
}
|
|
if (run_args.softswitches & SS_CXROM) {
|
|
fprintf(fp, " CXROM");
|
|
}
|
|
if (run_args.softswitches & SS_C3ROM) {
|
|
fprintf(fp, " C3ROM");
|
|
}
|
|
}
|
|
|
|
if (output_pseudo) {
|
|
// pseudo #1
|
|
if (run_args.softswitches & SS_LCSEC) {
|
|
fprintf(fp, " SS_LCSEC");
|
|
}
|
|
if (run_args.softswitches & SS_LCWRT) {
|
|
fprintf(fp, " SS_LCWRT");
|
|
}
|
|
|
|
// pseudo #2
|
|
if (run_args.softswitches & SS_SCREEN) {
|
|
fprintf(fp, " SS_SCREEN");
|
|
}
|
|
if (run_args.softswitches & SS_TEXTRD) {
|
|
fprintf(fp, " SS_TEXTRD");
|
|
}
|
|
if (run_args.softswitches & SS_TEXTWRT) {
|
|
fprintf(fp, " SS_TEXTWRT");
|
|
}
|
|
if (run_args.softswitches & SS_HGRRD) {
|
|
fprintf(fp, " SS_HGRRD");
|
|
}
|
|
if (run_args.softswitches & SS_HGRWRT) {
|
|
fprintf(fp, " SS_HGRWRT");
|
|
}
|
|
}
|
|
fprintf(fp, " ]");
|
|
}
|
|
|
|
#if VM_TRACING
|
|
void vm_trace_begin(const char *vm_file) {
|
|
if (vm_file) {
|
|
if (test_vm_fp) {
|
|
vm_trace_end();
|
|
}
|
|
test_vm_fp = fopen(vm_file, "w");
|
|
}
|
|
}
|
|
|
|
void vm_trace_end(void) {
|
|
if (test_vm_fp) {
|
|
fflush(test_vm_fp);
|
|
fclose(test_vm_fp);
|
|
test_vm_fp = NULL;
|
|
}
|
|
}
|
|
|
|
void vm_trace_toggle(const char *vm_file) {
|
|
if (test_vm_fp) {
|
|
vm_trace_end();
|
|
} else {
|
|
vm_trace_begin(vm_file);
|
|
}
|
|
}
|
|
|
|
void vm_trace_ignore(vm_trace_range_t range) {
|
|
// TODO ...
|
|
}
|
|
|
|
bool vm_trace_is_ignored(uint16_t ea) {
|
|
if ((ea < 0xC000) || (ea > 0xCFFF)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
#endif
|