Refactor VM initialization and shutdown

This commit is contained in:
Aaron Culliney 2015-09-11 00:00:04 -07:00
parent bc5559c1b0
commit ed60b2ea73
21 changed files with 670 additions and 913 deletions

View File

@ -295,7 +295,7 @@ static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
#endif
// shut down common OpenGL stuff AFTER display link has been released
video_backend->shutdown();
emulator_shutdown();
[super dealloc];
}

View File

@ -9,7 +9,7 @@ AM_LFLAGS = -i
###############################################################################
# No install
noinst_HEADERS = src/common.h src/cpu.h src/disk.h src/glue.h \
noinst_HEADERS = src/common.h src/cpu.h src/disk.h src/glue.h src/vm.h \
src/interface.h src/joystick.h src/keys.h src/misc.h src/prefs.h \
src/timing.h src/uthash.h src/video/video.h src/zlib-helpers.h \
\
@ -81,7 +81,7 @@ src/font.c: src/font.txt genfont
src/rom.c: genrom
./genrom src/rom/apple_IIe.rom src/rom/slot6.rom > $@
src/x86/glue.S: src/disk.c src/misc.c src/display.c src/vm.c src/cpu-supp.c @AUDIO_GLUE_C@
src/x86/glue.S: src/disk.c src/vm.c src/display.c src/vm.c src/cpu-supp.c @AUDIO_GLUE_C@
./src/x86/genglue $^ > $@
###############################################################################

View File

@ -14,7 +14,7 @@
*/
#include "cpu-regs.h"
#include "misc.h"
#include "vm.h"
#define DecodeFlags \

View File

@ -9,9 +9,11 @@
*
*/
#include "misc.h"
#include "vm.h"
#include "cpu-regs.h"
#define GLUE_EXTERN_C_READ(func)
#define GLUE_BANK_MAYBEREAD(func,pointer) \
ENTRY(func) ldr r1, SYM(softswitches); \
ldr r0, [r1]; \

View File

@ -2040,11 +2040,6 @@ void MB_InitializeIO(char *unused_pCxRomPeripheral, unsigned int uSlot4, unsigne
// Phasor : Slot 4
// <other> : Slot 4 & 5
#ifdef APPLE2IX
extern void MB_Read();
extern void MB_Write();
extern void PhasorIO();
#endif
if (g_Slot4 != CT_MockingboardC && g_Slot4 != CT_Phasor)
{
MB_SetSoundcardType(CT_Empty);

View File

@ -51,6 +51,7 @@
#include <sys/stat.h>
#include "misc.h"
#include "vm.h"
#include "timing.h"
#include "cpu.h"
#include "video/video.h"

View File

@ -653,7 +653,6 @@ void cpu65_reboot(void) {
video_reset();
joy_button0 = 0xff; // OpenApple
cpu65_interrupt(ResetSig);
c_initialize_sound_hooks();
}
#if CPU_TRACING

View File

@ -96,18 +96,18 @@ uint8_t video__dhires2[256] = {
// forward decls of VM entry points
void video__write_2e_text0(void);
void video__write_2e_text0_mixed(void);
void video__write_2e_text1(void);
void video__write_2e_text1_mixed(void);
void video__write_2e_odd0(void);
void video__write_2e_even0(void);
void video__write_2e_odd0_mixed(void);
void video__write_2e_even0_mixed(void);
void video__write_2e_odd1(void);
void video__write_2e_even1(void);
void video__write_2e_odd1_mixed(void);
void video__write_2e_even1_mixed(void);
void video__write_2e_text0(uint16_t, uint8_t);
void video__write_2e_text0_mixed(uint16_t, uint8_t);
void video__write_2e_text1(uint16_t, uint8_t);
void video__write_2e_text1_mixed(uint16_t, uint8_t);
void video__write_2e_odd0(uint16_t, uint8_t);
void video__write_2e_even0(uint16_t, uint8_t);
void video__write_2e_odd0_mixed(uint16_t, uint8_t);
void video__write_2e_even0_mixed(uint16_t, uint8_t);
void video__write_2e_odd1(uint16_t, uint8_t);
void video__write_2e_even1(uint16_t, uint8_t);
void video__write_2e_odd1_mixed(uint16_t, uint8_t);
void video__write_2e_even1_mixed(uint16_t, uint8_t);
// ----------------------------------------------------------------------------
// Initialization routines

View File

@ -14,15 +14,21 @@
*
*/
#define GLUE_BANK_READ(func,pointer)
#define GLUE_BANK_MAYBEREAD(func,pointer)
#define GLUE_BANK_WRITE(func,pointer)
#define GLUE_BANK_MAYBEWRITE(func,pointer)
#if defined(__ASSEMBLER__)
# error assembler-specific glue code should be in the arch-specific area
#endif
#define GLUE_BANK_READ(func,pointer) extern void func(void)
#define GLUE_BANK_MAYBEREAD(func,pointer) extern void func(void)
#define GLUE_BANK_WRITE(func,pointer) extern void func(void)
#define GLUE_BANK_MAYBEWRITE(func,pointer) extern void func(void)
#define GLUE_EXTERN_C_READ(func) extern uint8_t func(uint16_t)
#if VM_TRACING
#define GLUE_C_WRITE(func) \
extern void func(void); \
extern void func(uint16_t, uint8_t); \
void c__##func(uint16_t ea, uint8_t b); \
void c_##func(uint16_t ea, uint8_t b) { \
c__##func(ea, b); \
@ -35,7 +41,7 @@
void c__##func(uint16_t ea, uint8_t b)
#define GLUE_C_READ(func) \
extern void func(void); \
extern uint8_t func(uint16_t); \
uint8_t c__##func(uint16_t ea); \
uint8_t c_##func(uint16_t ea) { \
uint8_t b = c__##func(ea); \
@ -51,11 +57,11 @@
#else
#define GLUE_C_WRITE(func) \
extern void func(void); \
extern void func(uint16_t, uint8_t); \
void c_##func(uint16_t ea, uint8_t b)
#define GLUE_C_READ(func) \
extern void func(void); \
extern uint8_t func(uint16_t); \
uint8_t c_##func(uint16_t ea)
#endif

View File

@ -1160,7 +1160,7 @@ void c_interface_parameters()
{
timing_initialize();
video_reset();
c_initialize_sound_hooks();
vm_reinitializeAudio();
c_joystick_reset();
c_interface_exit(ch);
return;

View File

@ -448,10 +448,6 @@ int c_mygetch(int block)
{
int retval;
if (emulator_shutting_down) {
next_key = kESC;
}
while (next_key == -1 && block)
{
static struct timespec ts = { .tv_sec=0, .tv_nsec=33333333 };

View File

@ -16,19 +16,13 @@
#include "common.h"
/* ----------------------------------
internal apple2 variables
---------------------------------- */
extern uint8_t apple_iie_rom[32768];
bool emulator_shutting_down = false;
bool do_logging = true; // also controlled by NDEBUG
FILE *error_log = NULL;
int sound_volume = 2;
color_mode_t color_mode = COLOR;
const char *data_dir = NULL;
char **argv = NULL;
int argc = 0;
__attribute__((constructor(CTOR_PRIORITY_FIRST)))
static void _init_common() {
@ -36,544 +30,18 @@ static void _init_common() {
#if defined(CONFIG_DATADIR)
data_dir = strdup(CONFIG_DATADIR PATH_SEPARATOR PACKAGE_NAME);
#elif defined(ANDROID)
// data_dir is set up in JNI nativeOnCreate()
// data_dir is set up in JNI
#elif !defined(__APPLE__)
#error "Specify a CONFIG_DATADIR and PACKAGE_NAME"
# error "Specify a CONFIG_DATADIR and PACKAGE_NAME"
#endif
}
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_default,base_ramrd)
GLUE_BANK_WRITE(iie_write_ram_default,base_ramwrt)
GLUE_BANK_READ(iie_read_ram_text_page0,base_textrd)
GLUE_BANK_WRITE(iie_write_screen_hole_text_page0,base_textwrt)
GLUE_BANK_READ(iie_read_ram_hires_page0,base_hgrrd)
GLUE_BANK_WRITE(iie_write_screen_hole_hires_page0,base_hgrwrt)
GLUE_BANK_READ(iie_read_ram_zpage_and_stack,base_stackzp)
GLUE_BANK_WRITE(iie_write_ram_zpage_and_stack,base_stackzp)
GLUE_BANK_READ(iie_read_slot3,base_c3rom)
GLUE_BANK_MAYBEREAD(iie_read_slot4,base_c4rom)
GLUE_BANK_MAYBEREAD(iie_read_slot5,base_c5rom)
GLUE_BANK_READ(iie_read_slotx,base_cxrom)
uint32_t softswitches;
const uint8_t *base_vmem = apple_ii_64k[0];
uint8_t *base_ramrd;
uint8_t *base_ramwrt;
uint8_t *base_textrd;
uint8_t *base_textwrt;
uint8_t *base_hgrrd;
uint8_t *base_hgrwrt;
uint8_t *base_stackzp;
uint8_t *base_d000_rd;
uint8_t *base_e000_rd;
uint8_t *base_d000_wrt;
uint8_t *base_e000_wrt;
uint8_t *base_c3rom;
uint8_t *base_c4rom;
uint8_t *base_c5rom;
uint8_t *base_cxrom;
/* -------------------------------------------------------------------------
c_debug_illegal_bcd - illegal BCD (decimal mode) computation
------------------------------------------------------------------------- */
GLUE_C_READ(debug_illegal_bcd)
{
RELEASE_LOG("Illegal/undefined BCD operation encountered, debug break on c_debug_illegal_bcd to debug...");
return 0;
}
/* -------------------------------------------------------------------------
c_set_altchar() - set alternate character set
------------------------------------------------------------------------- */
void c_set_altchar()
{
video_loadfont(0x40,0x20,mousetext_glyphs,1);
video_loadfont(0x60,0x20,lcase_glyphs,2);
video_redraw();
}
/* -------------------------------------------------------------------------
c_set_primary_char() - set primary character set
------------------------------------------------------------------------- */
void c_set_primary_char()
{
video_loadfont(0x40,0x40,ucase_glyphs,3);
video_redraw();
}
/* -------------------------------------------------------------------------
c_initialize_font(): Initialize ROM character table to primary char set
------------------------------------------------------------------------- */
void c_initialize_font()
{
video_loadfont(0x00,0x40,ucase_glyphs,2);
video_loadfont(0x40,0x40,ucase_glyphs,3);
video_loadfont(0x80,0x40,ucase_glyphs,0);
video_loadfont(0xC0,0x20,ucase_glyphs,0);
video_loadfont(0xE0,0x20,lcase_glyphs,0);
video_redraw();
}
/* -------------------------------------------------------------------------
c_initialize_tables()
------------------------------------------------------------------------- */
void c_initialize_tables() {
int i;
/* reset everything */
for (i = 0; i < 0x10000; i++)
{
cpu65_vmem_r[i] = iie_read_ram_default;
cpu65_vmem_w[i] = iie_write_ram_default;
}
/* language card read/write area */
for (i = 0xD000; i < 0xE000; i++)
{
{
cpu65_vmem_w[i] =
write_ram_bank;
cpu65_vmem_r[i] =
read_ram_bank;
}
}
for (i = 0xE000; i < 0x10000; i++)
{
{
cpu65_vmem_w[i] =
write_ram_lc;
cpu65_vmem_r[i] =
read_ram_lc;
}
}
/* done common initialization */
/* initialize zero-page, //e specific */
for (i = 0; i < 0x200; i++)
{
cpu65_vmem_r[i] =
iie_read_ram_zpage_and_stack;
cpu65_vmem_w[i] =
iie_write_ram_zpage_and_stack;
}
/* initialize first text & hires page, which are specially bank switched
*
* video_reset() substitutes it's own hooks for all visible write locations
* affect the display, leaving our write-functions in place only at the
* `screen holes', hence the name.
*/
for (i = 0x400; i < 0x800; i++)
{
cpu65_vmem_r[i] =
iie_read_ram_text_page0;
cpu65_vmem_w[i] =
iie_write_screen_hole_text_page0;
}
for (i = 0x2000; i < 0x4000; i++)
{
cpu65_vmem_r[i] =
iie_read_ram_hires_page0;
cpu65_vmem_w[i] =
iie_write_screen_hole_hires_page0;
}
/* softswich rom */
for (i = 0xC000; i < 0xC100; i++)
{
cpu65_vmem_r[i] =
read_unmapped_softswitch;
cpu65_vmem_w[i] =
write_unmapped_softswitch;
}
/* slot rom defaults */
for (i = 0xC100; i < 0xD000; i++)
{
cpu65_vmem_r[i] =
iie_read_ram_default;
cpu65_vmem_w[i] =
ram_nop;
}
/* keyboard data and strobe (READ) */
for (i = 0xC000; i < 0xC010; i++)
{
cpu65_vmem_r[i] =
read_keyboard;
}
for (i = 0xC010; i < 0xC020; i++)
{
cpu65_vmem_r[i] =
cpu65_vmem_w[i] =
read_keyboard_strobe;
}
/* RDBNK2 switch */
cpu65_vmem_r[0xC011] =
iie_check_bank;
/* RDLCRAM switch */
cpu65_vmem_r[0xC012] =
iie_check_lcram;
/* 80STORE switch */
cpu65_vmem_w[0xC000] = iie_80store_off;
cpu65_vmem_w[0xC001] = iie_80store_on;
cpu65_vmem_r[0xC018] = iie_check_80store;
/* RAMRD switch */
cpu65_vmem_w[0xC002] = iie_ramrd_main;
cpu65_vmem_w[0xC003] = iie_ramrd_aux;
cpu65_vmem_r[0xC013] = iie_check_ramrd;
/* RAMWRT switch */
cpu65_vmem_w[0xC004] = iie_ramwrt_main;
cpu65_vmem_w[0xC005] = iie_ramwrt_aux;
cpu65_vmem_r[0xC014] = iie_check_ramwrt;
/* ALTZP switch */
cpu65_vmem_w[0xC008] = iie_altzp_main;
cpu65_vmem_w[0xC009] = iie_altzp_aux;
cpu65_vmem_r[0xC016] = iie_check_altzp;
/* 80COL switch */
cpu65_vmem_w[0xC00C] = iie_80col_off;
cpu65_vmem_w[0xC00D] = iie_80col_on;
cpu65_vmem_r[0xC01F] = iie_check_80col;
/* ALTCHAR switch */
cpu65_vmem_w[0xC00E] = iie_altchar_off;
cpu65_vmem_w[0xC00F] = iie_altchar_on;
cpu65_vmem_r[0xC01E] = iie_check_altchar;
/* SLOTC3ROM switch */
cpu65_vmem_w[0xC00A] = iie_c3rom_internal;
cpu65_vmem_w[0xC00B] = iie_c3rom_peripheral;
cpu65_vmem_r[0xC017] = iie_check_c3rom;
/* SLOTCXROM switch */
cpu65_vmem_w[0xC006] = iie_cxrom_peripheral;
cpu65_vmem_w[0xC007] = iie_cxrom_internal;
cpu65_vmem_r[0xC015] = iie_check_cxrom;
/* RDVBLBAR switch */
cpu65_vmem_r[0xC019] = iie_check_vbl;
/* TEXT switch */
cpu65_vmem_r[0xC050] =
cpu65_vmem_w[0xC050] =
read_switch_graphics;
cpu65_vmem_r[0xC051] =
cpu65_vmem_w[0xC051] =
read_switch_text;
cpu65_vmem_r[0xC01A] =
iie_check_text;
/* MIXED switch */
cpu65_vmem_r[0xC052] =
cpu65_vmem_w[0xC052] =
read_switch_no_mixed;
cpu65_vmem_r[0xC053] =
cpu65_vmem_w[0xC053] =
read_switch_mixed;
cpu65_vmem_r[0xC01B] =
iie_check_mixed;
/* PAGE2 switch */
cpu65_vmem_r[0xC054] =
cpu65_vmem_w[0xC054] =
iie_page2_off;
cpu65_vmem_r[0xC01C] =
iie_check_page2;
/* PAGE2 switch */
cpu65_vmem_r[0xC055] =
cpu65_vmem_w[0xC055] =
iie_page2_on;
/* HIRES switch */
cpu65_vmem_r[0xC01D] =
iie_check_hires;
cpu65_vmem_r[0xC056] =
cpu65_vmem_w[0xC056] =
iie_hires_off;
cpu65_vmem_r[0xC057] =
cpu65_vmem_w[0xC057] =
iie_hires_on;
/* game I/O switches */
cpu65_vmem_r[0xC061] =
cpu65_vmem_r[0xC069] =
read_button0;
cpu65_vmem_r[0xC062] =
cpu65_vmem_r[0xC06A] =
read_button1;
cpu65_vmem_r[0xC063] =
cpu65_vmem_r[0xC06B] =
read_button2;
cpu65_vmem_r[0xC064] =
cpu65_vmem_r[0xC06C] =
read_gc0;
cpu65_vmem_r[0xC065] =
cpu65_vmem_r[0xC06D] =
read_gc1;
cpu65_vmem_r[0xC066] =
iie_read_gc2;
cpu65_vmem_r[0xC067] =
iie_read_gc3;
for (i = 0xC070; i < 0xC080; i++)
{
cpu65_vmem_r[i] =
cpu65_vmem_w[i] =
read_gc_strobe;
}
/* IOUDIS switch & read_gc_strobe */
cpu65_vmem_w[0xC07E] =
iie_ioudis_on;
cpu65_vmem_w[0xC07F] =
iie_ioudis_off; // HACK FIXME TODO : double-check this stuff against AWin...
cpu65_vmem_r[0xC07E] =
iie_check_ioudis;
cpu65_vmem_r[0xC07F] =
iie_check_dhires;
/* Annunciator */
for (i = 0xC058; i <= 0xC05D; i++) {
cpu65_vmem_w[i] = cpu65_vmem_r[i] = iie_annunciator;
}
/* DHIRES */
cpu65_vmem_w[0xC05E] =
cpu65_vmem_r[0xC05E] =
iie_dhires_on;
cpu65_vmem_w[0xC05F] =
cpu65_vmem_r[0xC05F] =
iie_dhires_off;
/* language card softswitches */
cpu65_vmem_r[0xC080] = cpu65_vmem_w[0xC080] =
cpu65_vmem_r[0xC084] = cpu65_vmem_w[0xC084] = iie_c080;
cpu65_vmem_r[0xC081] = cpu65_vmem_w[0xC081] =
cpu65_vmem_r[0xC085] = cpu65_vmem_w[0xC085] = iie_c081;
cpu65_vmem_r[0xC082] = cpu65_vmem_w[0xC082] =
cpu65_vmem_r[0xC086] = cpu65_vmem_w[0xC086] = lc_c082;
cpu65_vmem_r[0xC083] = cpu65_vmem_w[0xC083] =
cpu65_vmem_r[0xC087] = cpu65_vmem_w[0xC087] = iie_c083;
cpu65_vmem_r[0xC088] = cpu65_vmem_w[0xC088] =
cpu65_vmem_r[0xC08C] = cpu65_vmem_w[0xC08C] = iie_c088;
cpu65_vmem_r[0xC089] = cpu65_vmem_w[0xC089] =
cpu65_vmem_r[0xC08D] = cpu65_vmem_w[0xC08D] = iie_c089;
cpu65_vmem_r[0xC08A] = cpu65_vmem_w[0xC08A] =
cpu65_vmem_r[0xC08E] = cpu65_vmem_w[0xC08E] = lc_c08a;
cpu65_vmem_r[0xC08B] = cpu65_vmem_w[0xC08B] =
cpu65_vmem_r[0xC08F] = cpu65_vmem_w[0xC08F] = iie_c08b;
/* slot i/o area */
for (i = 0xC100; i < 0xC300; i++)
{
cpu65_vmem_r[i] =
iie_read_slotx; /* slots 1 & 2 (x) */
}
for (i = 0xC300; i < 0xC400; i++)
{
cpu65_vmem_r[i] =
iie_read_slot3; /* slot 3 (80col) */
}
for (i = 0xC400; i < 0xC500; i++)
{
cpu65_vmem_r[i] =
iie_read_slot4; /* slot 4 - MB or Phasor */
}
for (i = 0xC500; i < 0xC600; i++)
{
cpu65_vmem_r[i] =
iie_read_slot5; /* slot 5 - MB #2 */
}
for (i = 0xC600; i < 0xC800; i++)
{
cpu65_vmem_r[i] =
iie_read_slotx; /* slots 6 - 7 (x) */
}
for (i = 0xC800; i < 0xD000; i++)
{
cpu65_vmem_r[i] = iie_read_slot_expansion;
}
cpu65_vmem_w[0xCFFF] = iie_read_slot_expansion;
video_reset();
// Peripheral card slot initializations ...
// HACK TODO FIXME : this needs to be tied to the UI/configuration system (once we have more/conflicting options)
#ifdef AUDIO_ENABLED
mb_io_initialize(4, 5); /* Mockingboard(s) and/or Phasor in slots 4 & 5 */
#endif
disk_io_initialize(6); /* Put a Disk ][ Controller in slot 6 */
}
/* -------------------------------------------------------------------------
c_initialize_apple_ii_memory()
------------------------------------------------------------------------- */
void c_initialize_apple_ii_memory()
{
int i;
for (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 J---- will lock up without this
for (i = 0; i < 0xC000;) {
apple_ii_64k[0][i++] = 0xFF;
apple_ii_64k[0][i++] = 0xFF;
i += 2;
}
for (i = 0; i < 8192; i++)
{
language_card[0][i] = language_card[1][i] = 0;
}
for (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 (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 (i = 0; i < 0x1000; i++)
{
language_banks[0][i] = apple_iie_rom[i + 0x1000];
language_banks[1][i] = apple_iie_rom[i + 0x5000];
}
for (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;
}
/* -------------------------------------------------------------------------
void c_initialize_sound_hooks()
------------------------------------------------------------------------- */
void c_initialize_sound_hooks()
{
#ifdef AUDIO_ENABLED
speaker_setVolumeZeroToTen(sound_volume);
MB_SetVolumeZeroToTen(sound_volume);
#endif
for (int i = 0xC030; i < 0xC040; i++)
{
cpu65_vmem_r[i] = cpu65_vmem_w[i] =
#ifdef AUDIO_ENABLED
(sound_volume > 0) ? speaker_toggle :
#endif
ram_nop;
}
}
void c_disable_sound_hooks()
{
for (int i = 0xC030; i < 0xC040; i++)
{
cpu65_vmem_r[i] = ram_nop;
}
}
/* -------------------------------------------------------------------------
c_initialize_iie_switches
------------------------------------------------------------------------- */
void c_initialize_iie_switches() {
base_stackzp = apple_ii_64k[0];
base_d000_rd = apple_ii_64k[0];
base_d000_wrt = language_banks[0] - 0xD000;
base_e000_rd = apple_ii_64k[0];
base_e000_wrt = language_card[0] - 0xE000;
base_ramrd = apple_ii_64k[0];
base_ramwrt = apple_ii_64k[0];
base_textrd = apple_ii_64k[0];
base_textwrt = apple_ii_64k[0];
base_hgrrd = apple_ii_64k[0];
base_hgrwrt= apple_ii_64k[0];
base_c3rom = apple_ii_64k[1]; /* c3rom internal */
base_c4rom = apple_ii_64k[1]; /* c4rom internal */
base_c5rom = apple_ii_64k[1]; /* c5rom internal */
base_cxrom = apple_ii_64k[0]; /* cxrom peripheral */
}
/* -------------------------------------------------------------------------
void c_initialize_vm()
------------------------------------------------------------------------- */
void c_initialize_vm() {
c_initialize_font(); /* font already read in */
c_initialize_apple_ii_memory(); /* read in rom memory */
c_initialize_tables(); /* read/write memory jump tables */
c_initialize_sound_hooks(); /* sound system */
c_init_6(); /* drive ][, slot 6 */
c_initialize_iie_switches(); /* set the //e softswitches */
c_joystick_reset(); /* reset joystick */
}
#if !TESTING && !defined(__APPLE__) && !defined(ANDROID)
extern void *cpu_thread(void *dummyptr);
static void _shutdown_threads(void) {
#if !TESTING
LOG("Emulator waiting for other threads to clean up...");
#if !__linux__
#warning FIXME TODO ideally we have a more deterministic thread waiting routine ...
sleep(2); // =P
#else
# if !__linux__
# error FIXME TODO on Darwin ...
# else
do {
DIR *dir = opendir("/proc/self/task");
if (!dir) {
@ -603,29 +71,33 @@ static void _shutdown_threads(void) {
static struct timespec ts = { .tv_sec=0, .tv_nsec=33333333 };
nanosleep(&ts, NULL); // 30Hz framerate
} while (1);
# endif
#endif
}
void emulator_start(void) {
#ifdef INTERFACE_CLASSIC
load_settings(); // user prefs
c_keys_set_key(kF8); // show credits before emulation start
#endif
timing_startCPU();
video_main_loop();
}
void emulator_shutdown(void) {
video_shutdown();
timing_stopCPU();
_shutdown_threads();
}
#if !TESTING && !defined(__APPLE__) && !defined(ANDROID)
int main(int _argc, char **_argv) {
argc = _argc;
argv = _argv;
load_settings(); // user prefs
#ifdef INTERFACE_CLASSIC
c_keys_set_key(kF8); // show credits before emulation start
#endif
timing_startCPU();
emulator_start();
video_main_loop();
assert(emulator_shutting_down && "emulator is properly shutting down");
LOG("Emulator waiting for CPU thread clean up...");
if (pthread_join(cpu_thread_id, NULL)) {
ERRLOG("OOPS: pthread_join of CPU thread ...");
}
_shutdown_threads();
emulator_shutdown();
return 0;
}

View File

@ -14,211 +14,20 @@
*
*/
#ifndef MISC_H
#define MISC_H
#ifndef __ASSEMBLER__
#ifndef _MISC_H_
#define _MISC_H_
// top installation directory
extern const char *data_dir;
/* Text characters */
extern const unsigned char ucase_glyphs[0x200];
extern const unsigned char lcase_glyphs[0x100];
extern const unsigned char mousetext_glyphs[0x100];
extern const unsigned char interface_glyphs[88];
// global ref to CLI args
extern char **argv;
extern int argc;
uint8_t apple_ii_64k[2][65536]; /* 128k memory */
// start emulator (CPU, audio, and video)
void emulator_start(void);
/* language card memory and settings */
uint8_t language_card[2][8192], language_banks[2][8192];
/* global ref to commandline args */
char **argv;
int argc;
extern uint8_t *base_ramrd;
extern uint8_t *base_ramwrt;
extern uint8_t *base_textrd;
extern uint8_t *base_textwrt;
extern uint8_t *base_hgrrd;
extern uint8_t *base_hgrwrt;
extern uint8_t *base_stackzp;
extern uint8_t *base_d000_rd;
extern uint8_t *base_e000_rd;
extern uint8_t *base_d000_wrt;
extern uint8_t *base_e000_wrt;
extern uint8_t *base_c3rom;
extern uint8_t *base_c4rom; // points to function or memory vector
extern uint8_t *base_c5rom; // points to function or memory vector
extern uint8_t *base_cxrom;
/* softswitches */
extern uint32_t softswitches;
#endif /* !__ASSEMBLER__ */
#define SS_TEXT 0x00000001
#define SS_MIXED 0x00000002
#define SS_HIRES 0x00000004
#define SS_PAGE2 0x00000008
#define SS_BANK2 0x00000010
#define SS_LCRAM 0x00000020
#define SS_LCSEC 0x00000040 /* Pseudo-softswitch : enabled if 2+ reads have occurred */
#define SS_LCWRT 0x00000080 /* Pseudo-softswitch : LC write enable */
#define SS_80STORE 0x00000100
#define SS_80COL 0x00000200
#define SS_RAMRD 0x00000400
#define SS_RAMWRT 0x00000800
#define SS_ALTZP 0x00001000
#define SS_DHIRES 0x00002000
#define SS_IOUDIS 0x00004000
#define SS_CXROM 0x00008000
#define SS_C3ROM 0x00010000
#define SS_ALTCHAR 0x00020000
/* Pseudo soft switches. These are actually functions of other SSes, but are
* tiresome to calculate as needed.
*
*/
#define SS_SCREEN 0x00040000 /* PAGE2 && !80STORE */
#define SS_TEXTRD 0x00080000 /* (PAGE2 && 80STORE) ||
(RAMRD && !80STORE) */
#define SS_TEXTWRT 0x00100000 /* (PAGE2 && 80STORE) ||
(RAMWRT && !80STORE) */
#define SS_HGRRD 0x00200000 /* (PAGE2 && 80STORE && HIRES) ||
(RAMRD && !(80STORE && HIRES) */
#define SS_HGRWRT 0x00400000 /* (PAGE2 && 80STORE && HIRES) ||
(RAMWRT && !(80STORE && HIRES)) */
#ifndef __ASSEMBLER__
/* -------------------------------------------------------------------------
misc.c functions
------------------------------------------------------------------------- */
extern bool emulator_shutting_down;
void c_initialize_sound_hooks();
void c_disable_sound_hooks();
void c_set_primary_char();
void c_set_altchar();
void c_initialize_font();
void c_initialize_vm();
/* vm hooks */
#if VM_TRACING
void vm_trace_begin(const char *vm_file);
void vm_trace_end(void);
void vm_trace_toggle(const char *vm_file);
bool vm_trace_is_ignored(uint16_t ea);
#endif
void ram_nop(),
write_unmapped_softswitch(),
read_rand(),
read_unmapped_softswitch(),
read_keyboard(),
read_keyboard_strobe(),
speaker_toggle(),
read_switch_graphics(),
read_switch_text(),
read_switch_no_mixed(),
read_switch_mixed(),
read_button0(),
read_button1(),
read_button2(),
read_gc0(),
read_gc1(),
read_gc_strobe(),
lc_c082(),
lc_c08a(),
write_ram_bank(),
read_ram_bank(),
write_ram_lc(),
read_ram_lc();
void iie_write_ram_default(),
iie_read_ram_default(),
/* //e text pages */
iie_read_ram_text_page0(),
iie_write_screen_hole_text_page0(),
/* //e hires page 0 */
iie_read_ram_hires_page0(),
iie_write_screen_hole_hires_page0(),
/* //e zpage,stack, ram banks */
iie_read_ram_zpage_and_stack(),
iie_write_ram_zpage_and_stack(),
iie_read_slot3(),
iie_read_slot4(),
iie_read_slot5(),
iie_read_slotx(),
iie_read_slot_expansion(),
iie_disable_slot_expansion(),
iie_read_gc2(),
iie_read_gc3(),
iie_c080(),
iie_c081(),
iie_c083(),
iie_c088(),
iie_c089(),
iie_c08b(),
/* //e toggle softswitches */
iie_ramrd_main(),
iie_ramrd_aux(),
iie_ramwrt_main(),
iie_ramwrt_aux(),
iie_80store_off(),
iie_80store_on(),
iie_altzp_main(),
iie_altzp_aux(),
iie_80col_off(),
iie_80col_on(),
iie_altchar_off(),
iie_altchar_on(),
iie_c3rom_peripheral(),
iie_c3rom_internal(),
iie_cxrom_peripheral(),
iie_cxrom_internal(),
iie_ioudis_on(),
iie_ioudis_off(),
iie_annunciator(),
iie_dhires_on(),
iie_dhires_off(),
iie_hires_off(),
iie_hires_on(),
iie_page2_on(),
iie_page2_off(),
/* //e check softswitche settings */
iie_check_80store(),
iie_check_bank(),
iie_check_lcram(),
iie_check_ramrd(),
iie_check_ramwrt(),
iie_check_altzp(),
iie_check_c3rom(),
iie_check_cxrom(),
iie_check_80col(),
iie_check_altchar(),
iie_check_text(),
iie_check_mixed(),
iie_check_hires(),
iie_check_page2(),
iie_check_ioudis(),
iie_check_dhires(),
iie_check_vbl();
#endif /* !__ASSEMBLER__ */
// shutdown emulator in preparation for app exit
void emulator_shutdown(void);
#endif

View File

@ -87,6 +87,7 @@ bool emul_reinitialize_audio = true;
#if MOBILE_DEVICE
static bool emul_reinitialize_background = true;
#endif
static bool cpu_shutting_down = false;
pthread_t cpu_thread_id = 0;
pthread_mutex_t interface_mutex = { 0 };
pthread_cond_t dbg_thread_cond = PTHREAD_COND_INITIALIZER;
@ -169,7 +170,7 @@ void reinitialize(void) {
cycles_count_total = 0;
c_initialize_vm();
vm_initialize();
softswitches = SS_TEXT | SS_IOUDIS | SS_C3ROM | SS_LCWRT | SS_LCSEC;
@ -542,12 +543,12 @@ static void *cpu_thread(void *dummyptr) {
}
#endif
if (UNLIKELY(emulator_shutting_down)) {
if (UNLIKELY(cpu_shutting_down)) {
break;
}
} while (1);
if (UNLIKELY(emulator_shutting_down)) {
if (UNLIKELY(cpu_shutting_down)) {
break;
}
} while (1);
@ -562,10 +563,20 @@ static void *cpu_thread(void *dummyptr) {
}
void timing_startCPU(void) {
cpu_shutting_down = false;
video_init();
pthread_create(&cpu_thread_id, NULL, (void *)&cpu_thread, (void *)NULL);
}
void timing_stopCPU(void) {
cpu_shutting_down = true;
LOG("Emulator waiting for CPU thread clean up...");
if (pthread_join(cpu_thread_id, NULL)) {
ERRLOG("OOPS: pthread_join of CPU thread ...");
}
}
unsigned int CpuGetCyclesThisVideoFrame(void) {
timing_checkpoint_cycles();
return g_dwCyclesThisFrame + cycles_checkpoint_count;

View File

@ -70,10 +70,15 @@ extern READONLY pthread_t cpu_thread_id;
struct timespec timespec_diff(struct timespec start, struct timespec end, bool *negative);
/*
* Start CPU thread
* start CPU thread
*/
void timing_startCPU(void);
/*
* stop CPU thread
*/
void timing_stopCPU(void);
/*
* toggles CPU speed between configured values
*/

View File

@ -631,15 +631,9 @@ static void _gldriver_shutdown(void) {
static void gldriver_shutdown(void) {
#if USE_GLUT
glutLeaveMainLoop();
#else
# if MOBILE_DEVICE
#endif
renderer_shutting_down = true;
_gldriver_shutdown();
# else
# error this codepath untested ...
emulator_shutting_down = true;
# endif
#endif
}
//----------------------------------------------------------------------------
@ -677,11 +671,9 @@ static void gldriver_render(void) {
return;
}
#if MOBILE_DEVICE
if (UNLIKELY(renderer_shutting_down)) {
return;
}
#endif
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
#if MOBILE_DEVICE
@ -893,8 +885,6 @@ static void gldriver_main_loop(void) {
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
glutMainLoop();
LOG("GLUT main loop finished...");
emulator_shutting_down = true;
_gldriver_shutdown();
#endif
// fall through if not GLUT
}

View File

@ -283,5 +283,13 @@ extern uint8_t *video__fb2;
*/
extern READONLY int video__current_page;
/*
* font glyph data
*/
extern const unsigned char ucase_glyphs[0x200];
extern const unsigned char lcase_glyphs[0x100];
extern const unsigned char mousetext_glyphs[0x100];
extern const unsigned char interface_glyphs[88];
#endif /* !A2_VIDEO_H */

478
src/vm.c
View File

@ -9,110 +9,35 @@
*
*/
/* ----------------------------------------------------------------------------
Apple //e 64K VM
(Two byte addresses are represented with least significant
byte first, e.g. address FA59 is represented as 59 FA)
This is not meant to be definitive.
Verify against _Understanding the Apple IIe_ by Jim Sather
Address Description
----------- -----------
0000 - 00FF Zero page RAM
0100 - 01FF Stack
0200 - 03EF RAM
03F0 - 03F1 Address for BRK instruction (normally 59 FA = FA59)
03F2 - 03F3 Soft entry vector (normally BF 9D = 9DBF)
03F4 Power-up byte
03F5 - 03F7 Jump instruction to the subroutine which handles
Applesoft II &-commands (normally 4C 58 FF = JMP FF58)
03F8 - 03FA Jump instruction to the subroutine which handles User
CTRL-Y commands (normally 4C 65 FF = JMP FF65)
03FB - 03FD Jump instruction to the subroutine which handles
Non-Maskable Interrupts (NMI) (normally 4C 65 FF = JMP FF65)
03FE - 03FF Address of the subroutine which handles Interrupt
ReQuests (IRQ) (normally 65 FF = FF65)
0400 - 07FF Basically primary video text page
0478 - 047F I/O Scratchpad RAM Addresses for Slot 0 - 7
04F8 - 04FF - " " -
0578 - 057F - " " -
05F8 - 05FF - " " -
0678 - 067F - " " -
06F8 - 06FF - " " -
0778 - 077F - " " -
07F8 - 07FF - " " -
05F8 Holds the slot number of the disk controller card from
which DOS was booted. ??? VERIFY...
07F8 Holds the slot number (CX, X = Slot #) of the slot that
is currently active. ??? VERIFY...
0800 - 0BFF Secondary video text page
0C00 - 1FFF Plain RAM
2000 - 3FFF Primary video hires page (RAM)
4000 - 5FFF Secondary video hires page (RAM)
6000 - BFFF Plain RAM (Normally the OS is loaded into ~9C00 - BFFF)
C000 - C00F Keyboard data (C00X contains the character ASCII code of
the pressed key. The value is available at any C00X address)
C010 - C01F Clear Keyboard strobe
C020 - C02F Cassette output toggle
C030 - C03F Speaker toggle
C040 - C04F Utility strobe
C050 Set graphics mode
C051 Set text mode
C052 Set all text or graphics
C053 Mix text and graphics
C054 Display primary page
C055 Display secondary page
C056 Display low-res graphics
C057 Display hi-res graphics
C058 - C05F Annunciator outputs
C060 Cassette input
C061 - C063 Pushbutton inputs (button 1, 2 and 3)
C064 - C067 Game controller inputs
C068 - C06F Same as C060 - C067
C070 - C07F Game controller strobe
C080 - C08F Slot 0 I/O space (usually a language card)
C080 Reset language card
* Read enabled
* Write disabled
* Read from language card
C081 --- First access
* Read mode disabled
* Read from ROM
--- On second+ access
* Write mode enabled
* Write to language card
C082 --- (Disable language card)
* Read mode disabled
* Write mode disabled
* Read from ROM
C083 --- First access
* Read mode enabled
* Read from language card
--- On second+ access
* Write mode enabled
* Write to language card
C088 - C08B Same as C080 - C083, but switch to second bank, i.e.
map addresses D000-DFFF to other 4K area.
C100 - C1FF Slot 1 PROM
C200 - C2FF Slot 2 PROM
C300 - C3FF Slot 3 PROM
C400 - C4FF Slot 4 PROM
C500 - C5FF Slot 5 PROM
C600 - C6FF Slot 6 PROM
C700 - C7FF Slot 7 PROM
C800 - CFFF Expansion ROM (for peripheral cards)
CFFF Disable access to expansion ROM for
ALL peripheral cards.
D000 - DFFF ROM or 4K RAM if language card is enabled. However,
there are TWO 4K banks that can be mapped onto addresses
D000 - DFFF. See C088 - C08B.
E000 - FFFF ROM or 8K RAM if language card is enabled.
---------------------------------------------------------------------------- */
#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 } };
uint32_t softswitches = 0x0;
const uint8_t *base_vmem = apple_ii_64k[0];
uint8_t *base_ramrd = NULL;
uint8_t *base_ramwrt = NULL;
uint8_t *base_textrd = NULL;
uint8_t *base_textwrt = NULL;
uint8_t *base_hgrrd = NULL;
uint8_t *base_hgrwrt = NULL;
uint8_t *base_stackzp = NULL;
uint8_t *base_d000_rd = NULL;
uint8_t *base_e000_rd = NULL;
uint8_t *base_d000_wrt = NULL;
uint8_t *base_e000_wrt = NULL;
uint8_t *base_c3rom = NULL;
uint8_t *base_c4rom = NULL;
uint8_t *base_c5rom = NULL;
uint8_t *base_cxrom = NULL;
// joystick timer values
int gc_cycles_timer_0 = 0;
int gc_cycles_timer_1 = 0;
@ -126,6 +51,33 @@ typedef struct vm_trace_range_t {
} 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_WRITE(iie_write_screen_hole_text_page0,base_textwrt);
GLUE_BANK_READ(iie_read_ram_hires_page0,base_hgrrd);
GLUE_BANK_WRITE(iie_write_screen_hole_hires_page0,base_hgrwrt);
GLUE_BANK_READ(iie_read_ram_zpage_and_stack,base_stackzp);
GLUE_BANK_WRITE(iie_write_ram_zpage_and_stack,base_stackzp);
GLUE_BANK_READ(iie_read_slot3,base_c3rom);
GLUE_BANK_MAYBEREAD(iie_read_slot4,base_c4rom);
GLUE_BANK_MAYBEREAD(iie_read_slot5,base_c5rom);
GLUE_BANK_READ(iie_read_slotx,base_cxrom);
GLUE_EXTERN_C_READ(speaker_toggle);
GLUE_C_READ(ram_nop)
{
return (cpu65_rw&MEM_WRITE_FLAG) ? 0x0 : floating_bus();
@ -818,7 +770,8 @@ GLUE_C_READ(iie_altchar_off)
{
if (softswitches & SS_ALTCHAR) {
softswitches &= ~SS_ALTCHAR;
c_set_primary_char();
video_loadfont(0x40,0x40,ucase_glyphs,3);
video_redraw();
}
return floating_bus();
}
@ -827,7 +780,9 @@ GLUE_C_READ(iie_altchar_on)
{
if (!(softswitches & SS_ALTCHAR)) {
softswitches |= SS_ALTCHAR;
c_set_altchar();
video_loadfont(0x40,0x20,mousetext_glyphs,1);
video_loadfont(0x60,0x20,lcase_glyphs,2);
video_redraw();
}
return floating_bus();
}
@ -953,8 +908,323 @@ GLUE_C_READ(iie_read_slot_expansion)
return apple_ii_64k[1][ea];
}
GLUE_C_READ(debug_illegal_bcd)
{
RELEASE_LOG("Illegal/undefined BCD operation encountered, debug break on c_debug_illegal_bcd to debug...");
return 0;
}
// ----------------------------------------------------------------------------
static void _initialize_iie_switches(void) {
base_stackzp = apple_ii_64k[0];
base_d000_rd = apple_ii_64k[0];
base_d000_wrt = language_banks[0] - 0xD000;
base_e000_rd = apple_ii_64k[0];
base_e000_wrt = language_card[0] - 0xE000;
base_ramrd = apple_ii_64k[0];
base_ramwrt = apple_ii_64k[0];
base_textrd = apple_ii_64k[0];
base_textwrt = apple_ii_64k[0];
base_hgrrd = apple_ii_64k[0];
base_hgrwrt= apple_ii_64k[0];
base_c3rom = apple_ii_64k[1]; // c3rom internal
base_c4rom = apple_ii_64k[1]; // c4rom internal
base_c5rom = apple_ii_64k[1]; // c5rom internal
base_cxrom = apple_ii_64k[0]; // cxrom peripheral
}
static void _initialize_font(void) {
video_loadfont(0x00,0x40,ucase_glyphs,2);
video_loadfont(0x40,0x40,ucase_glyphs,3);
video_loadfont(0x80,0x40,ucase_glyphs,0);
video_loadfont(0xC0,0x20,ucase_glyphs,0);
video_loadfont(0xE0,0x20,lcase_glyphs,0);
video_redraw();
}
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 J---- 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;
}
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 < 0x10000; i++) {
cpu65_vmem_r[i] = iie_read_ram_default;
cpu65_vmem_w[i] = iie_write_ram_default;
}
// language card read/write area
for (unsigned int i = 0xD000; i < 0xE000; i++) {
cpu65_vmem_w[i] = write_ram_bank;
cpu65_vmem_r[i] = read_ram_bank;
}
for (unsigned int i = 0xE000; i < 0x10000; i++) {
cpu65_vmem_w[i] = write_ram_lc;
cpu65_vmem_r[i] = read_ram_lc;
}
// done common initialization
// initialize zero-page, //e specific
for (unsigned int i = 0; i < 0x200; i++) {
cpu65_vmem_r[i] = iie_read_ram_zpage_and_stack;
cpu65_vmem_w[i] = iie_write_ram_zpage_and_stack;
}
// initialize first text & hires page, which are specially bank switched
//
// video_reset() below substitutes it's own hooks for all visible write locations affect the display, leaving our
// write-functions in place only at the `screen holes', hence the name.
for (unsigned int i = 0x400; i < 0x800; i++) {
cpu65_vmem_r[i] = iie_read_ram_text_page0;
cpu65_vmem_w[i] = iie_write_screen_hole_text_page0;
}
for (unsigned int i = 0x2000; i < 0x4000; i++) {
cpu65_vmem_r[i] = iie_read_ram_hires_page0;
cpu65_vmem_w[i] = iie_write_screen_hole_hires_page0;
}
// softswich rom
for (unsigned int i = 0xC000; i < 0xC100; i++) {
cpu65_vmem_r[i] = read_unmapped_softswitch;
cpu65_vmem_w[i] = write_unmapped_softswitch;
}
// slot rom defaults
for (unsigned int i = 0xC100; i < 0xD000; i++) {
cpu65_vmem_r[i] = iie_read_ram_default;
cpu65_vmem_w[i] = ram_nop;
}
// keyboard data and strobe (READ)
for (unsigned int i = 0xC000; i < 0xC010; i++) {
cpu65_vmem_r[i] = read_keyboard;
}
for (unsigned int i = 0xC010; i < 0xC020; i++) {
cpu65_vmem_r[i] = cpu65_vmem_w[i] = read_keyboard_strobe;
}
// RDBNK2 switch
cpu65_vmem_r[0xC011] = iie_check_bank;
// RDLCRAM switch
cpu65_vmem_r[0xC012] = iie_check_lcram;
// 80STORE switch
cpu65_vmem_w[0xC000] = iie_80store_off;
cpu65_vmem_w[0xC001] = iie_80store_on;
cpu65_vmem_r[0xC018] = iie_check_80store;
// RAMRD switch
cpu65_vmem_w[0xC002] = iie_ramrd_main;
cpu65_vmem_w[0xC003] = iie_ramrd_aux;
cpu65_vmem_r[0xC013] = iie_check_ramrd;
// RAMWRT switch
cpu65_vmem_w[0xC004] = iie_ramwrt_main;
cpu65_vmem_w[0xC005] = iie_ramwrt_aux;
cpu65_vmem_r[0xC014] = iie_check_ramwrt;
// ALTZP switch
cpu65_vmem_w[0xC008] = iie_altzp_main;
cpu65_vmem_w[0xC009] = iie_altzp_aux;
cpu65_vmem_r[0xC016] = iie_check_altzp;
// 80COL switch
cpu65_vmem_w[0xC00C] = iie_80col_off;
cpu65_vmem_w[0xC00D] = iie_80col_on;
cpu65_vmem_r[0xC01F] = iie_check_80col;
// ALTCHAR switch
cpu65_vmem_w[0xC00E] = iie_altchar_off;
cpu65_vmem_w[0xC00F] = iie_altchar_on;
cpu65_vmem_r[0xC01E] = iie_check_altchar;
// SLOTC3ROM switch
cpu65_vmem_w[0xC00A] = iie_c3rom_internal;
cpu65_vmem_w[0xC00B] = iie_c3rom_peripheral;
cpu65_vmem_r[0xC017] = iie_check_c3rom;
// SLOTCXROM switch
cpu65_vmem_w[0xC006] = iie_cxrom_peripheral;
cpu65_vmem_w[0xC007] = iie_cxrom_internal;
cpu65_vmem_r[0xC015] = iie_check_cxrom;
// RDVBLBAR switch
cpu65_vmem_r[0xC019] = iie_check_vbl;
// TEXT switch
cpu65_vmem_r[0xC050] = cpu65_vmem_w[0xC050] = read_switch_graphics;
cpu65_vmem_r[0xC051] = cpu65_vmem_w[0xC051] = read_switch_text;
cpu65_vmem_r[0xC01A] = iie_check_text;
// MIXED switch
cpu65_vmem_r[0xC052] = cpu65_vmem_w[0xC052] = read_switch_no_mixed;
cpu65_vmem_r[0xC053] = cpu65_vmem_w[0xC053] = read_switch_mixed;
cpu65_vmem_r[0xC01B] = iie_check_mixed;
// PAGE2 switch
cpu65_vmem_r[0xC054] = cpu65_vmem_w[0xC054] = iie_page2_off;
cpu65_vmem_r[0xC01C] = iie_check_page2;
cpu65_vmem_r[0xC055] = cpu65_vmem_w[0xC055] = iie_page2_on;
// HIRES switch
cpu65_vmem_r[0xC01D] = iie_check_hires;
cpu65_vmem_r[0xC056] = cpu65_vmem_w[0xC056] = iie_hires_off;
cpu65_vmem_r[0xC057] = cpu65_vmem_w[0xC057] = iie_hires_on;
// game I/O switches
cpu65_vmem_r[0xC061] = cpu65_vmem_r[0xC069] = read_button0;
cpu65_vmem_r[0xC062] = cpu65_vmem_r[0xC06A] = read_button1;
cpu65_vmem_r[0xC063] = cpu65_vmem_r[0xC06B] = read_button2;
cpu65_vmem_r[0xC064] = cpu65_vmem_r[0xC06C] = read_gc0;
cpu65_vmem_r[0xC065] = cpu65_vmem_r[0xC06D] = read_gc1;
cpu65_vmem_r[0xC066] = iie_read_gc2;
cpu65_vmem_r[0xC067] = iie_read_gc3;
for (unsigned int i = 0xC070; i < 0xC080; i++) {
cpu65_vmem_r[i] = cpu65_vmem_w[i] = read_gc_strobe;
}
// IOUDIS switch & read_gc_strobe
cpu65_vmem_w[0xC07E] = iie_ioudis_on;
cpu65_vmem_w[0xC07F] = iie_ioudis_off; // HACK FIXME TODO : double-check this stuff against AWin...
cpu65_vmem_r[0xC07E] = iie_check_ioudis;
cpu65_vmem_r[0xC07F] = iie_check_dhires;
// Annunciator
for (unsigned int i = 0xC058; i <= 0xC05D; i++) {
cpu65_vmem_w[i] = cpu65_vmem_r[i] = iie_annunciator;
}
// DHIRES
cpu65_vmem_w[0xC05E] = cpu65_vmem_r[0xC05E] = iie_dhires_on;
cpu65_vmem_w[0xC05F] = cpu65_vmem_r[0xC05F] = iie_dhires_off;
// language card softswitches
cpu65_vmem_r[0xC080] = cpu65_vmem_w[0xC080] = cpu65_vmem_r[0xC084] = cpu65_vmem_w[0xC084] = iie_c080;
cpu65_vmem_r[0xC081] = cpu65_vmem_w[0xC081] = cpu65_vmem_r[0xC085] = cpu65_vmem_w[0xC085] = iie_c081;
cpu65_vmem_r[0xC082] = cpu65_vmem_w[0xC082] = cpu65_vmem_r[0xC086] = cpu65_vmem_w[0xC086] = lc_c082;
cpu65_vmem_r[0xC083] = cpu65_vmem_w[0xC083] = cpu65_vmem_r[0xC087] = cpu65_vmem_w[0xC087] = iie_c083;
cpu65_vmem_r[0xC088] = cpu65_vmem_w[0xC088] = cpu65_vmem_r[0xC08C] = cpu65_vmem_w[0xC08C] = iie_c088;
cpu65_vmem_r[0xC089] = cpu65_vmem_w[0xC089] = cpu65_vmem_r[0xC08D] = cpu65_vmem_w[0xC08D] = iie_c089;
cpu65_vmem_r[0xC08A] = cpu65_vmem_w[0xC08A] = cpu65_vmem_r[0xC08E] = cpu65_vmem_w[0xC08E] = lc_c08a;
cpu65_vmem_r[0xC08B] = cpu65_vmem_w[0xC08B] = cpu65_vmem_r[0xC08F] = cpu65_vmem_w[0xC08F] = iie_c08b;
// slot i/o area
for (unsigned int i = 0xC100; i < 0xC300; i++) {
cpu65_vmem_r[i] = iie_read_slotx; // slots 1 & 2 (x)
}
for (unsigned int i = 0xC300; i < 0xC400; i++) {
cpu65_vmem_r[i] = iie_read_slot3; // slot 3 (80col)
}
for (unsigned int i = 0xC400; i < 0xC500; i++) {
cpu65_vmem_r[i] = iie_read_slot4; // slot 4 - MB or Phasor
}
for (unsigned int i = 0xC500; i < 0xC600; i++) {
cpu65_vmem_r[i] = iie_read_slot5; // slot 5 - MB #2
}
for (unsigned int i = 0xC600; i < 0xC800; i++) {
cpu65_vmem_r[i] = iie_read_slotx; // slots 6 - 7 (x)
}
for (unsigned int i = 0xC800; i < 0xD000; i++) {
cpu65_vmem_r[i] = iie_read_slot_expansion;
}
cpu65_vmem_w[0xCFFF] = iie_read_slot_expansion;
video_reset();
// Peripheral card slot initializations ...
// HACK TODO FIXME : this needs to be tied to the UI/configuration system (once we have more/conflicting options)
#ifdef AUDIO_ENABLED
mb_io_initialize(4, 5); /* Mockingboard(s) and/or Phasor in slots 4 & 5 */
#endif
disk_io_initialize(6); /* Put a Disk ][ Controller in slot 6 */
}
// ----------------------------------------------------------------------------
void vm_initialize(void) {
_initialize_font();
_initialize_apple_ii_memory();
_initialize_tables();
vm_reinitializeAudio();
c_init_6();
_initialize_iie_switches();
c_joystick_reset();
}
void vm_reinitializeAudio(void) {
#ifdef AUDIO_ENABLED
speaker_setVolumeZeroToTen(sound_volume);
MB_SetVolumeZeroToTen(sound_volume);
#endif
for (unsigned int i = 0xC030; i < 0xC040; i++) {
cpu65_vmem_r[i] = cpu65_vmem_w[i] =
#ifdef AUDIO_ENABLED
(sound_volume > 0) ? speaker_toggle :
#endif
ram_nop;
}
#warning TODO FIXME ... should unset MB/Phasor hooks if volume is zero ...
}
void debug_print_softwitches(void) {
// useful from GDB ...

191
src/vm.h Normal file
View File

@ -0,0 +1,191 @@
/*
* Apple // emulator for *nix
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#ifndef _VM_H_
#define _VM_H_
/* ----------------------------------------------------------------------------
Apple //e 64K VM
(Two byte addresses are represented with least significant
byte first, e.g. address FA59 is represented as 59 FA)
This is not meant to be definitive.
Verify against _Understanding the Apple IIe_ by Jim Sather
Address Description
----------- -----------
0000 - 00FF Zero page RAM
0100 - 01FF Stack
0200 - 03EF RAM
03F0 - 03F1 Address for BRK instruction (normally 59 FA = FA59)
03F2 - 03F3 Soft entry vector (normally BF 9D = 9DBF)
03F4 Power-up byte
03F5 - 03F7 Jump instruction to the subroutine which handles
Applesoft II &-commands (normally 4C 58 FF = JMP FF58)
03F8 - 03FA Jump instruction to the subroutine which handles User
CTRL-Y commands (normally 4C 65 FF = JMP FF65)
03FB - 03FD Jump instruction to the subroutine which handles
Non-Maskable Interrupts (NMI) (normally 4C 65 FF = JMP FF65)
03FE - 03FF Address of the subroutine which handles Interrupt
ReQuests (IRQ) (normally 65 FF = FF65)
0400 - 07FF Basically primary video text page
0478 - 047F I/O Scratchpad RAM Addresses for Slot 0 - 7
04F8 - 04FF - " " -
0578 - 057F - " " -
05F8 - 05FF - " " -
0678 - 067F - " " -
06F8 - 06FF - " " -
0778 - 077F - " " -
07F8 - 07FF - " " -
05F8 Holds the slot number of the disk controller card from
which DOS was booted. ??? VERIFY...
07F8 Holds the slot number (CX, X = Slot #) of the slot that
is currently active. ??? VERIFY...
0800 - 0BFF Secondary video text page
0C00 - 1FFF Plain RAM
2000 - 3FFF Primary video hires page (RAM)
4000 - 5FFF Secondary video hires page (RAM)
6000 - BFFF Plain RAM (Normally the OS is loaded into ~9C00 - BFFF)
C000 - C00F Keyboard data (C00X contains the character ASCII code of
the pressed key. The value is available at any C00X address)
C010 - C01F Clear Keyboard strobe
C020 - C02F Cassette output toggle
C030 - C03F Speaker toggle
C040 - C04F Utility strobe
C050 Set graphics mode
C051 Set text mode
C052 Set all text or graphics
C053 Mix text and graphics
C054 Display primary page
C055 Display secondary page
C056 Display low-res graphics
C057 Display hi-res graphics
C058 - C05F Annunciator outputs
C060 Cassette input
C061 - C063 Pushbutton inputs (button 1, 2 and 3)
C064 - C067 Game controller inputs
C068 - C06F Same as C060 - C067
C070 - C07F Game controller strobe
C080 - C08F Slot 0 I/O space (usually a language card)
C080 Reset language card
* Read enabled
* Write disabled
* Read from language card
C081 --- First access
* Read mode disabled
* Read from ROM
--- On second+ access
* Write mode enabled
* Write to language card
C082 --- (Disable language card)
* Read mode disabled
* Write mode disabled
* Read from ROM
C083 --- First access
* Read mode enabled
* Read from language card
--- On second+ access
* Write mode enabled
* Write to language card
C088 - C08B Same as C080 - C083, but switch to second bank, i.e.
map addresses D000-DFFF to other 4K area.
C100 - C1FF Slot 1 PROM
C200 - C2FF Slot 2 PROM
C300 - C3FF Slot 3 PROM
C400 - C4FF Slot 4 PROM
C500 - C5FF Slot 5 PROM
C600 - C6FF Slot 6 PROM
C700 - C7FF Slot 7 PROM
C800 - CFFF Expansion ROM (for peripheral cards)
CFFF Disable access to expansion ROM for
ALL peripheral cards.
D000 - DFFF ROM or 4K RAM if language card is enabled. However,
there are TWO 4K banks that can be mapped onto addresses
D000 - DFFF. See C088 - C08B.
E000 - FFFF ROM or 8K RAM if language card is enabled.
---------------------------------------------------------------------------- */
#if !defined(__ASSEMBLER__)
// 128k bank-switched main memory
extern uint8_t apple_ii_64k[2][65536];
// language card memory and settings
extern uint8_t language_card[2][8192];
extern uint8_t language_banks[2][8192];
extern uint32_t softswitches;
extern uint8_t *base_ramrd;
extern uint8_t *base_ramwrt;
extern uint8_t *base_textrd;
extern uint8_t *base_textwrt;
extern uint8_t *base_hgrrd;
extern uint8_t *base_hgrwrt;
extern uint8_t *base_stackzp;
extern uint8_t *base_d000_rd;
extern uint8_t *base_e000_rd;
extern uint8_t *base_d000_wrt;
extern uint8_t *base_e000_wrt;
extern uint8_t *base_c3rom;
extern uint8_t *base_c4rom; // points to function or memory vector
extern uint8_t *base_c5rom; // points to function or memory vector
extern uint8_t *base_cxrom;
void vm_initialize(void);
void vm_reinitializeAudio(void);
#if VM_TRACING
void vm_trace_begin(const char *vm_file);
void vm_trace_end(void);
void vm_trace_toggle(const char *vm_file);
bool vm_trace_is_ignored(uint16_t ea);
#endif
#endif // !defined(__ASSEMBLER__)
// softswitch flag bits
#define SS_TEXT 0x00000001
#define SS_MIXED 0x00000002
#define SS_HIRES 0x00000004
#define SS_PAGE2 0x00000008
#define SS_BANK2 0x00000010
#define SS_LCRAM 0x00000020
#define SS_LCSEC 0x00000040 // Pseudo-softswitch : enabled if 2+ reads have occurred
#define SS_LCWRT 0x00000080 // Pseudo-softswitch : LC write enable
#define SS_80STORE 0x00000100
#define SS_80COL 0x00000200
#define SS_RAMRD 0x00000400
#define SS_RAMWRT 0x00000800
#define SS_ALTZP 0x00001000
#define SS_DHIRES 0x00002000
#define SS_IOUDIS 0x00004000
#define SS_CXROM 0x00008000
#define SS_C3ROM 0x00010000
#define SS_ALTCHAR 0x00020000
// Pseudo soft switches. These are actually functions of other SSes, but are tiresome to calculate as needed.
#define SS_SCREEN 0x00040000 /* PAGE2 && !80STORE */
#define SS_TEXTRD 0x00080000 /* (PAGE2 && 80STORE) ||
(RAMRD && !80STORE) */
#define SS_TEXTWRT 0x00100000 /* (PAGE2 && 80STORE) ||
(RAMWRT && !80STORE) */
#define SS_HGRRD 0x00200000 /* (PAGE2 && 80STORE && HIRES) ||
(RAMRD && !(80STORE && HIRES) */
#define SS_HGRWRT 0x00400000 /* (PAGE2 && 80STORE && HIRES) ||
(RAMWRT && !(80STORE && HIRES)) */
#endif // whole file

View File

@ -15,7 +15,7 @@
*/
#include "cpu-regs.h"
#include "misc.h"
#include "vm.h"
#define CommonSaveCPUState \
movw EffectiveAddr, SYM(cpu65_ea); \

View File

@ -14,9 +14,11 @@
*
*/
#include "misc.h"
#include "vm.h"
#include "cpu-regs.h"
#define GLUE_EXTERN_C_READ(func)
#define GLUE_BANK_MAYBEREAD(func,pointer) \
ENTRY(func) testLQ $SS_CXROM, SYM(softswitches); \
jnz 1f; \