Much better sound system

Paddle functions placed to C code
MMIO functions placed to C code
Disassembler fixed
This commit is contained in:
tudnai 2021-11-07 23:06:44 -08:00
parent 058124bf2d
commit aec319fac2
8 changed files with 1026 additions and 1002 deletions

View File

@ -1849,6 +1849,7 @@
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_FAST_MATH = YES;
GCC_UNROLL_LOOPS = NO;
HEADER_SEARCH_PATHS = src/cpu;
INFOPLIST_FILE = "A2Mac/Debug-Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@ -1890,6 +1891,7 @@
GCC_FAST_MATH = YES;
GCC_OPTIMIZATION_LEVEL = fast;
GCC_UNROLL_LOOPS = NO;
HEADER_SEARCH_PATHS = src/cpu;
INFOPLIST_FILE = "A2Mac/Debug-Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",

View File

@ -97,7 +97,7 @@ int spkr_extra_buf = 0; // 26; // 800 / spkr_fps;
typedef int16_t spkr_sample_t;
const unsigned spkr_buf_size = spkr_seconds * spkr_sample_rate * SPKR_CHANNELS / DEFAULT_FPS; // stereo
const unsigned spkr_buf_alloc_size = spkr_buf_size * sizeof(spkr_sample_t);
spkr_sample_t spkr_samples [ spkr_buf_alloc_size * DEFAULT_FPS * BUFFER_COUNT]; // can store up to 1 sec of sound
spkr_sample_t spkr_samples [ spkr_buf_size * DEFAULT_FPS * BUFFER_COUNT]; // can store up to 1 sec of sound
unsigned spkr_sample_idx = 0;
unsigned spkr_sample_last_idx = 0;
unsigned spkr_sample_first_pwm_idx = 0;
@ -181,7 +181,7 @@ void spkr_init() {
alcMakeContextCurrent(ctx);
// Fill buffer with zeros
memset( spkr_samples, SPKR_LEVEL_ZERO, spkr_buf_alloc_size + spkr_extra_buf * sizeof(spkr_sample_t));
memset( spkr_samples, 0, spkr_buf_alloc_size + spkr_extra_buf * sizeof(spkr_sample_t));
// Create buffer to store samples
alGenBuffers(BUFFER_COUNT, spkr_buffers);
@ -356,75 +356,46 @@ void spkr_exit() {
char spkr_state = 0;
void spkr_toggle_edge_old ( const int level_max, const float initial_edge, const float fade_edge, const unsigned idx_diff ) {
float dumping = spkr_level - level_max;
dumping *= initial_edge;
if ( idx_diff <= SPKR_SAMPLE_PWM_THRESHOLD ) {
while ( spkr_sample_last_idx <= spkr_sample_idx ) {
spkr_samples[ spkr_sample_last_idx++ ] = SPKR_LEVEL_ZERO;
spkr_samples[ spkr_sample_last_idx++ ] = SPKR_LEVEL_ZERO; // stereo
}
// if ( idx_diff <= 2 ) {
// spkr_last_level = spkr_level;
// // save last index before we advance it...
// spkr_sample_last_idx = spkr_sample_idx;
// }
}
else {
spkr_last_level = spkr_level;
// save last index before we advance it...
spkr_sample_last_idx = spkr_sample_idx;
}
while ( fabsf(dumping) > 1 ) {
spkr_sample_t level = level_max + dumping;
spkr_samples[ spkr_sample_idx++ ] = level;
spkr_samples[ spkr_sample_idx++ ] = level; // stereo
// how smooth we want the speeker to decay, so we will hear no pops and crackles
dumping *= fade_edge;
}
spkr_level = level_max;
}
INLINE int ema( int val, int prev ) {
// Exponential Moving Average
INLINE int ema( int val, int prev, float ema_len ) {
static const float ema_sensitivity = 2;
static const float ema_len = 14;
static const float m = ema_sensitivity / ema_len;
static const float n = 1 - m;
// static const float ema_len = 42;
float m = ema_sensitivity / ema_len;
float n = 1 - m;
// calculate the multiplier for smoothing (weighting) the EMA,
// which typically follows the formula: [2 ÷ (number of observations + 1)].
// For a 20-day moving average, the multiplier would be [2/(20+1)]= 0.0952
return m * val + n * prev;
}
void spkr_toggle_edge ( const int level_max, const float initial_edge, const float fade_edge, const unsigned idx_diff ) {
void spkr_toggle_edge ( int level_max, const float initial_edge, const float fade_edge, const unsigned idx_diff ) {
float dumping = spkr_level - level_max;
dumping *= initial_edge;
float ema_len = 15;
if ( idx_diff <= SPKR_SAMPLE_PWM_THRESHOLD ) {
while ( spkr_sample_last_idx <= spkr_sample_idx ) {
spkr_samples[ spkr_sample_last_idx++ ] = spkr_level;
spkr_samples[ spkr_sample_last_idx++ ] = spkr_level; // stereo
spkr_level = ema(level_max / 5, spkr_level);
}
ema_len = 41;
}
spkr_level = spkr_samples[ spkr_sample_idx ];
while ( fabsf(dumping) > 1 ) {
spkr_sample_t level = level_max + dumping;
spkr_level = ema(level, spkr_level, ema_len);
spkr_samples[ spkr_sample_idx++ ] = spkr_level;
spkr_samples[ spkr_sample_idx++ ] = spkr_level; // stereo
// how smooth we want the speeker to decay, so we will hear no pops and crackles
dumping *= fade_edge;
}
while ( spkr_sample_last_idx <= spkr_sample_idx ) {
spkr_samples[ spkr_sample_last_idx++ ] = spkr_level;
spkr_samples[ spkr_sample_last_idx++ ] = spkr_level; // stereo
spkr_level = ema(level_max, spkr_level);
}
// spkr_level = level_max;
spkr_last_level = spkr_level;
// save last index before we advance it...
spkr_sample_last_idx = spkr_sample_idx;
}
float SPKR_FADE_LEADING_EDGE = 0.16;
float SPKR_FADE_TRAILING_EDGE = 0.32;
float SPKR_INITIAL_LEADING_EDGE = 0.64; // leading edge should be pretty steep to get sharp sound plus to avoid Wavy Navy high pitch sound
@ -516,7 +487,7 @@ void spkr_update() {
spkr_level = SPKR_LEVEL_ZERO;
//spkr_samples[sample_idx] = spkr_level;
memset(spkr_samples + spkr_sample_idx, SPKR_LEVEL_ZERO, spkr_extra_buf * sizeof(spkr_sample_t));
memset(spkr_samples + spkr_sample_idx, 0, spkr_extra_buf * sizeof(spkr_sample_t));
freeBuffers--;
alBufferData(spkr_buffers[freeBuffers], AL_FORMAT_STEREO16, spkr_samples, spkr_sample_idx * sizeof(spkr_sample_t), spkr_sample_rate);
@ -583,10 +554,19 @@ void spkr_update() {
break;
}
// clear the slack buffer, so we can fill it up by new data
for ( int i = 0; i < spkr_buf_size + spkr_extra_buf; i++ ) {
spkr_samples[i] = spkr_level;
int src = spkr_buf_size + spkr_extra_buf;
int dst = 0;
// copy the buffer leftover -- needed to finish wave form
while( src < spkr_sample_idx ) {
spkr_samples[dst++] = spkr_samples[src++];
}
// clear the slack buffer, so we can fill it up by new data
while( dst < spkr_buf_size + spkr_extra_buf ) {
spkr_samples[dst++] = spkr_level;
}
spkr_sample_last_idx = 0;
// spkr_samples[0] = 10000;

View File

@ -34,3 +34,15 @@ double * pdl_valarr = pdl_value;
double * pdl_prevarr = pdl_prev;
double * pdl_diffarr = pdl_diff;
INLINE uint8_t pdl_reset() {
pdl_reset_time = m6502.clktime + m6502.clkfrm;
return 0;
}
INLINE uint8_t pdl_read( uint8_t pdl ) {
pdl_current_time = m6502.clktime + m6502.clkfrm;
pdl_elapsed_time = pdl_current_time - pdl_reset_time;
double normalized_time = pdl_elapsed_time / PDL_MAX_TIME; // 0: started, >= 1 ended
return normalized_time >= pdl_value[pdl] ? 0 : 1 << 7; // TODO: better pdl value simulation, not only the bit 7
}

View File

@ -42,18 +42,8 @@ extern double * pdl_prevarr;
extern double * pdl_diffarr;
INLINE uint8_t pdl_reset() {
pdl_reset_time = m6502.clktime + m6502.clkfrm;
return 0;
}
INLINE uint8_t pdl_read( uint8_t pdl ) {
pdl_current_time = m6502.clktime + m6502.clkfrm;
pdl_elapsed_time = pdl_current_time - pdl_reset_time;
double normalized_time = pdl_elapsed_time / PDL_MAX_TIME; // 0: started, >= 1 ended
return normalized_time >= pdl_value[pdl] ? 0 : 1 << 7; // TODO: better pdl value simulation, not only the bit 7
}
INLINE uint8_t pdl_reset(void);
INLINE uint8_t pdl_read( uint8_t pdl );
#endif /* __PADDLE_H__ */

View File

@ -79,6 +79,933 @@ const uint8_t * const shadowLowMEM = Apple2_64K_MEM + 0x200;
const uint8_t * currentLowMEM = Apple2_64K_RAM + 0x200;
INLINE void io_RAM_EXP( uint16_t addr ) {
if ( MEMcfg.RAM_16K || MEMcfg.RAM_128K ) {
uint8_t * RAM_BANK = Apple2_64K_AUX + 0xC000;
// save the content of Shadow Memory in needed
if ( MEMcfg.WR_RAM ) {
// printf("Saving RAM Bank %d to %p\n", MEMcfg.RAM_BANK_2 + 1, current_RAM_bank);
memcpy(current_RAM_bank, Apple2_64K_MEM + 0xD000, 0x1000);
memcpy(Apple2_64K_AUX + 0xE000, Apple2_64K_MEM + 0xE000, 0x2000);
}
// RAM Bank 1 or 2?
switch ((uint8_t)addr) {
case (uint8_t)io_MEM_RDRAM_NOWR_2:
case (uint8_t)io_MEM_RDROM_WRAM_2:
case (uint8_t)io_MEM_RDROM_NOWR_2:
case (uint8_t)io_MEM_RDRAM_WRAM_2:
case (uint8_t)io_MEM_RDRAM_NOWR_2_:
case (uint8_t)io_MEM_RDROM_WRAM_2_:
case (uint8_t)io_MEM_RDROM_NOWR_2_:
case (uint8_t)io_MEM_RDRAM_WRAM_2_:
// printf("RAM_BANK_2\n");
MEMcfg.RAM_BANK_2 = 1;
RAM_BANK = Apple2_64K_AUX + 0xD000;
break;
default:
// printf("RAM_BANK_1\n");
MEMcfg.RAM_BANK_2 = 0;
RAM_BANK = Apple2_64K_AUX + 0xC000;
break;
}
// is RAM to read or ROM?
switch ((uint8_t)addr) {
case (uint8_t)io_MEM_RDRAM_NOWR_2:
case (uint8_t)io_MEM_RDRAM_WRAM_2:
case (uint8_t)io_MEM_RDRAM_NOWR_1:
case (uint8_t)io_MEM_RDRAM_WRAM_1:
case (uint8_t)io_MEM_RDRAM_NOWR_2_:
case (uint8_t)io_MEM_RDRAM_WRAM_2_:
case (uint8_t)io_MEM_RDRAM_NOWR_1_:
case (uint8_t)io_MEM_RDRAM_WRAM_1_:
// printf("RD_RAM\n");
MEMcfg.RD_INT_RAM = 1;
// load the content of Aux Memory
memcpy(Apple2_64K_MEM + 0xD000, RAM_BANK, 0x1000);
memcpy(Apple2_64K_MEM + 0xE000, Apple2_64K_AUX + 0xE000, 0x2000);
// set the RAM extension to read on the upper memory area
break;
default:
// printf("RD_ROM\n");
MEMcfg.RD_INT_RAM = 0;
// load the content of ROM Memory
memcpy(Apple2_64K_MEM + 0xD000, Apple2_64K_ROM + 0xD000, 0x3000);
// set the ROM to read on the upper memory area
break;
}
// is RAM Writeable?
switch ((uint8_t)addr) {
case (uint8_t)io_MEM_RDROM_WRAM_2:
case (uint8_t)io_MEM_RDROM_WRAM_1:
case (uint8_t)io_MEM_RDROM_WRAM_2_:
case (uint8_t)io_MEM_RDROM_WRAM_1_:
// printf("RD_ROM + WR_AUX\n");
// will write directly to Auxiliary RAM, and mark it as NO need to commit from Shadow RAM
MEMcfg.WR_RAM = 0;
if ( MEMcfg.RAM_BANK_2 ) {
WRD0MEM = Apple2_64K_AUX; // for Write $D000 - $DFFF (shadow memory) - BANK 2
}
else {
WRD0MEM = Apple2_64K_AUX - 0x1000; // for Write $D000 - $DFFF (shadow memory) - BANK 1
}
WRHIMEM = Apple2_64K_AUX; // for Write $E000 - $FFFF (shadow memory)
break;
case (uint8_t)io_MEM_RDRAM_WRAM_2:
case (uint8_t)io_MEM_RDRAM_WRAM_1:
case (uint8_t)io_MEM_RDRAM_WRAM_2_:
case (uint8_t)io_MEM_RDRAM_WRAM_1_:
// printf("RD_RAM + WR_RAM\n");
// will write to Shadow RAM, and mark it as need to commit from Shadow RAM
MEMcfg.WR_RAM = 1;
WRD0MEM = Apple2_64K_MEM; // for Write $D000 - $DFFF (shadow memory) - BANK X
WRHIMEM = Apple2_64K_MEM; // for Write $E000 - $FFFF (shadow memory)
break;
default:
// printf("RD_ROM + NO_WR\n");
// No writing (Readonly), and mark it as NO need to commit from Shadow RAM
MEMcfg.WR_RAM = 0;
WRD0MEM = Apple2_Dummy_RAM; // for Discarding any writes to $D000 - $DFFF - BANK X
WRHIMEM = Apple2_Dummy_RAM; // for Discarding any writes to $E000 - $FFFF
break;
}
current_RAM_bank = RAM_BANK;
// printf("Set current_RAM_bank %d to %p\n", MEMcfg.RAM_BANK_2 + 1, current_RAM_bank);
} // if there is RAM expansion card installed
}
INLINE uint8_t ioRead( uint16_t addr ) {
// if (outdev) fprintf(outdev, "ioRead:%04X\n", addr);
// printf("ioRead:%04X (PC:%04X)\n", addr, m6502.PC);
unsigned int IOframe = m6502.clkfrm - lastIO;
lastIO = m6502.clkfrm;
// TODO: This is for speed demo only, should be either removed or the entire ioRead should based on binary search, whatever is faster
if ( addr == io_KBD ) {
// clk_6502_per_frm_max = clk_6502_per_frm_max > 32768 ? clk_6502_per_frm_max - 32768 : 0; // ECO Mode!
if ( cpuMode == cpuMode_eco ) {
// check if this is a busy keyboard poll (aka waiting for user input)
if ( IOframe < 16 ) {
clk_6502_per_frm_max = 6502; // Let it run for a bit to display character -- nerd number :-)
cpuState = cpuState_halting;
}
}
return Apple2_64K_RAM[io_KBD];
}
switch ( (uint8_t)addr ) {
case (uint8_t)io_KBD:
return Apple2_64K_RAM[io_KBD];
case (uint8_t)io_KBDSTRB:
Apple2_64K_RAM[io_KBD] &= ~(1 << 7);
if ( cpuMode == cpuMode_eco ) {
// check if this is a busy keyboard poll (aka waiting for user input)
clk_6502_per_frm_max = clk_6502_per_frm; // Absolute low mode
cpuState = cpuState_running;
}
return Apple2_64K_RAM[io_KBDSTRB];
case (uint8_t)io_TAPEOUT:
case (uint8_t)io_SPKR:
spkr_toggle();
return Apple2_64K_RAM[io_SPKR];
case (uint8_t)io_VID_RDVBL:
return (m6502.clkfrm < 4550) ? 0x80 : 0;
case (uint8_t)io_VID_RDTEXT:
return videoMode.text << 7;
case (uint8_t)io_VID_ALTCHAR:
return videoMode.altChr << 7;
case (uint8_t)io_VID_RD80VID:
return videoMode.col80 << 7;
case (uint8_t)io_TAPEIN:
// TODO: this should be only on //c
return MEMcfg.txt_page_2 << 7;
case (uint8_t)io_RDCXROM:
return MEMcfg.int_Cx_ROM << 7;
case (uint8_t)io_RDLCBNK2:
return MEMcfg.RAM_BANK_2 << 7;
case (uint8_t)io_RDLCRAM:
return MEMcfg.RD_INT_RAM << 7;
case (uint8_t)io_RDRAMRD:
return MEMcfg.RD_AUX_MEM << 7;
case (uint8_t)io_RDRAMWR:
return MEMcfg.WR_AUX_MEM << 7;
case (uint8_t)io_RDALTZP:
return MEMcfg.ALT_ZP << 7;
case (uint8_t)io_RDC3ROM:
return MEMcfg.slot_C3_ROM << 7;
case (uint8_t)io_RD80STORE:
return MEMcfg.is_80STORE << 7;
case (uint8_t)io_VID_TXTPAGE1:
// printf("io_VID_TXTPAGE1\n");
MEMcfg.txt_page_2 = 0;
textPageSelect();
break;
case (uint8_t)io_VID_TXTPAGE2:
// printf("io_VID_TXTPAGE2\n");
MEMcfg.txt_page_2 = 1;
textPageSelect();
break;
case (uint8_t)io_VID_RDPAGE2:
return MEMcfg.txt_page_2 << 7;
case (uint8_t)io_VID_Text_OFF:
videoMode.text = 0;
break;
case (uint8_t)io_VID_Text_ON:
videoMode.text = 1;
break;
case (uint8_t)io_VID_Mixed_OFF:
videoMode.mixed = 0;
break;
case (uint8_t)io_VID_Mixed_ON:
videoMode.mixed = 1;
break;
case (uint8_t)io_VID_RDMIXED:
return videoMode.mixed << 7;
case (uint8_t)io_VID_Hires_OFF:
videoMode.hires = 0;
break;
case (uint8_t)io_VID_Hires_ON:
videoMode.hires = 1;
break;
case (uint8_t)io_VID_RDHIRES:
return videoMode.hires << 7;
case (uint8_t)io_PDL0:
case (uint8_t)io_PDL1:
case (uint8_t)io_PDL2:
case (uint8_t)io_PDL3:
// printf("PDL%d: %d\n", addr - io_PDL0, pdl_read( addr - io_PDL0 ));
return pdl_read( addr - io_PDL0 );
case (uint8_t)io_PDL_STROBE:
return pdl_reset();
case (uint8_t)io_RDMAINRAM:
// printf("io_RDMAINRAM\n");
newMEMcfg = MEMcfg;
newMEMcfg.RD_AUX_MEM = 0;
auxMemorySelect(newMEMcfg);
break;
case (uint8_t)io_RDCARDRAM:
// printf("io_RDCARDRAM\n");
newMEMcfg = MEMcfg;
newMEMcfg.RD_AUX_MEM = 1;
auxMemorySelect(newMEMcfg);
break;
case (uint8_t)io_WRMAINRAM:
// printf("io_WRMAINRAM\n");
newMEMcfg = MEMcfg;
newMEMcfg.WR_AUX_MEM = 0;
auxMemorySelect(newMEMcfg);
break;
case (uint8_t)io_WRCARDRAM:
// printf("io_WRCARDRAM\n");
newMEMcfg = MEMcfg;
newMEMcfg.WR_AUX_MEM = 1;
auxMemorySelect(newMEMcfg);
break;
case (uint8_t)io_MEM_RDRAM_NOWR_2:
case (uint8_t)io_MEM_RDROM_WRAM_2:
case (uint8_t)io_MEM_RDROM_NOWR_2:
case (uint8_t)io_MEM_RDRAM_WRAM_2:
case (uint8_t)io_MEM_RDRAM_NOWR_2_:
case (uint8_t)io_MEM_RDROM_WRAM_2_:
case (uint8_t)io_MEM_RDROM_NOWR_2_:
case (uint8_t)io_MEM_RDRAM_WRAM_2_:
case (uint8_t)io_MEM_RDRAM_NOWR_1:
case (uint8_t)io_MEM_RDROM_WRAM_1:
case (uint8_t)io_MEM_RDROM_NOWR_1:
case (uint8_t)io_MEM_RDRAM_WRAM_1:
case (uint8_t)io_MEM_RDRAM_NOWR_1_:
case (uint8_t)io_MEM_RDROM_WRAM_1_:
case (uint8_t)io_MEM_RDROM_NOWR_1_:
case (uint8_t)io_MEM_RDRAM_WRAM_1_:
io_RAM_EXP(addr);
break;
// TODO: Make code "card insertable to slot" / aka slot independent and dynamically add/remove
case (uint8_t)io_DISK_PHASE0_OFF + SLOT6:
case (uint8_t)io_DISK_PHASE1_OFF + SLOT6:
case (uint8_t)io_DISK_PHASE2_OFF + SLOT6:
case (uint8_t)io_DISK_PHASE3_OFF + SLOT6:
disk_phase_off( (addr - io_DISK_PHASE0_OFF - SLOT6) / 2 );
return disk_read();
case (uint8_t)io_DISK_PHASE0_ON + SLOT6:
case (uint8_t)io_DISK_PHASE1_ON + SLOT6:
case (uint8_t)io_DISK_PHASE2_ON + SLOT6:
case (uint8_t)io_DISK_PHASE3_ON + SLOT6:
disk_phase_on( (addr - io_DISK_PHASE0_ON - SLOT6) / 2 );
return disk_read();
case (uint8_t)io_DISK_POWER_OFF + SLOT6:
dbgPrintf2("io_DISK_POWER_OFF (S%u)\n", 6);
disk_motor_off();
return disk_read();
case (uint8_t)io_DISK_POWER_ON + SLOT6:
dbgPrintf2("io_DISK_POWER_ON (S%u)\n", 6);
disk_motor_on();
return disk_read();
case (uint8_t)io_DISK_SELECT_1 + SLOT6:
dbgPrintf2("io_DISK_SELECT_1 (S%u)\n", 6);
disk.drive = 0;
return disk_read();
case (uint8_t)io_DISK_SELECT_2 + SLOT6:
dbgPrintf2("io_DISK_SELECT_2 (S%u)\n", 6);
disk.drive = 1;
return disk_read();
case (uint8_t)io_DISK_READ + SLOT6:
if ( writeState ) {
writeState = 0;
woz_write( Apple2_64K_RAM[io_DISK_WRITE + SLOT6] );
return Apple2_64K_RAM[io_DISK_WRITE + SLOT6];
}
else {
return disk_read();
}
case (uint8_t)io_DISK_WRITE + SLOT6:
dbgPrintf2("io_DISK_WRITE (S%u)\n", 6);
// Apple2_64K_RAM[io_DISK_CLEAR + SLOT6] |= 1 << 7; // mark disk as write protected
WOZwrite.latch = WOZread.latch = 0;
Apple2_64K_RAM[io_DISK_CLEAR + SLOT6] &= ~(1 << 7); // mark disk as write enabled
return Apple2_64K_RAM[io_DISK_WRITE + SLOT6];
case (uint8_t)io_DISK_CLEAR + SLOT6:
dbgPrintf2("io_DISK_CLEAR (S%u)\n", 6);
return Apple2_64K_RAM[io_DISK_CLEAR + SLOT6];
case (uint8_t)io_DISK_SHIFT + SLOT6:
dbgPrintf2("io_DISK_SHIFT (S%u)\n", 6);
return disk_read();
default:
//printf("mmio read:%04X\n", addr);
break;
}
return Apple2_64K_RAM[addr];
}
INLINE void ioWrite( uint16_t addr, uint8_t val ) {
// if (outdev) fprintf(outdev, "ioWrite:%04X (A:%02X)\n", addr, m6502.A);
switch ( (uint8_t)addr ) {
case (uint8_t)io_KBDSTRB:
Apple2_64K_RAM[io_KBD] &= 0x7F;
break;
case (uint8_t)io_TAPEOUT:
case (uint8_t)io_SPKR:
spkr_toggle();
break;
case (uint8_t)io_RDMAINRAM:
// printf("io_RDMAINRAM\n");
newMEMcfg = MEMcfg;
newMEMcfg.RD_AUX_MEM = 0;
auxMemorySelect(newMEMcfg);
break;
case (uint8_t)io_RDCARDRAM:
// printf("io_RDCARDRAM\n");
newMEMcfg = MEMcfg;
newMEMcfg.RD_AUX_MEM = 1;
auxMemorySelect(newMEMcfg);
break;
case (uint8_t)io_WRMAINRAM:
// printf("io_WRMAINRAM\n");
newMEMcfg = MEMcfg;
newMEMcfg.WR_AUX_MEM = 0;
auxMemorySelect(newMEMcfg);
break;
case (uint8_t)io_WRCARDRAM:
// printf("io_WRCARDRAM\n");
newMEMcfg = MEMcfg;
newMEMcfg.WR_AUX_MEM = 1;
auxMemorySelect(newMEMcfg);
break;
case (uint8_t)io_SETSTDZP:
MEMcfg.ALT_ZP = 0;
// TODO: set zero page table to RAM
break;
case (uint8_t)io_SETALTZP:
MEMcfg.ALT_ZP = 1;
// TODO: set zero page table to AUX
break;
case (uint8_t)io_SETSLOTCXROM:
// printf("io_SETSLOTCXROM\n");
MEMcfg.int_Cx_ROM = 0;
// TODO: set Cx00 ROM area table to SLOT
break;
case (uint8_t)io_SETINTCXROM:
// printf("io_SETINTCXROM\n");
MEMcfg.int_Cx_ROM = 1;
// TODO: set Cx00 ROM area table to INT
break;
case (uint8_t)io_SETSLOTC3ROM:
// printf("io_SETSLOTC3ROM\n");
MEMcfg.slot_C3_ROM = 1;
// TODO: set C300 ROM area table to SLOT
break;
case (uint8_t)io_SETINTC3ROM:
// printf("io_SETINTC3ROM\n");
MEMcfg.slot_C3_ROM = 0;
// TODO: set C300 ROM area table to INT
break;
case (uint8_t)io_VID_CLR80VID:
// printf("io_VID_CLR80VID\n");
videoMode.col80 = 0;
break;
case (uint8_t)io_VID_SET80VID:
videoMode.col80 = 1;
break;
case (uint8_t)io_VID_CLRALTCHAR:
videoMode.altChr = 0;
break;
case (uint8_t)io_VID_SETALTCHAR:
videoMode.altChr = 1;
break;
case (uint8_t)io_80STOREOFF:
// printf("io_80STOREOFF\n");
MEMcfg.is_80STORE = 0;
textPageSelect();
break;
case (uint8_t)io_80STOREON:
// printf("io_80STOREON\n");
MEMcfg.is_80STORE = 1;
textPageSelect();
break;
case (uint8_t)io_VID_TXTPAGE1:
// printf("io_VID_TXTPAGE1\n");
MEMcfg.txt_page_2 = 0;
textPageSelect();
break;
case (uint8_t)io_VID_TXTPAGE2:
// printf("io_VID_TXTPAGE2\n");
MEMcfg.txt_page_2 = 1;
textPageSelect();
break;
case (uint8_t)io_VID_Text_OFF:
videoMode.text = 0;
break;
case (uint8_t)io_VID_Text_ON:
videoMode.text = 1;
break;
case (uint8_t)io_VID_Mixed_OFF:
videoMode.mixed = 0;
break;
case (uint8_t)io_VID_Mixed_ON:
videoMode.mixed = 1;
break;
case (uint8_t)io_VID_Hires_OFF:
videoMode.hires = 0;
break;
case (uint8_t)io_VID_Hires_ON:
videoMode.hires = 1;
break;
case (uint8_t)io_MEM_RDRAM_NOWR_2:
case (uint8_t)io_MEM_RDROM_WRAM_2:
case (uint8_t)io_MEM_RDROM_NOWR_2:
case (uint8_t)io_MEM_RDRAM_WRAM_2:
case (uint8_t)io_MEM_RDRAM_NOWR_2_:
case (uint8_t)io_MEM_RDROM_WRAM_2_:
case (uint8_t)io_MEM_RDROM_NOWR_2_:
case (uint8_t)io_MEM_RDRAM_WRAM_2_:
case (uint8_t)io_MEM_RDRAM_NOWR_1:
case (uint8_t)io_MEM_RDROM_WRAM_1:
case (uint8_t)io_MEM_RDROM_NOWR_1:
case (uint8_t)io_MEM_RDRAM_WRAM_1:
case (uint8_t)io_MEM_RDRAM_NOWR_1_:
case (uint8_t)io_MEM_RDROM_WRAM_1_:
case (uint8_t)io_MEM_RDROM_NOWR_1_:
case (uint8_t)io_MEM_RDRAM_WRAM_1_:
io_RAM_EXP(addr);
break;
// TODO: Make code "card insertable to slot" / aka slot independent and dynamically add/remove
case (uint8_t)io_DISK_PHASE0_OFF + SLOT6:
case (uint8_t)io_DISK_PHASE1_OFF + SLOT6:
case (uint8_t)io_DISK_PHASE2_OFF + SLOT6:
case (uint8_t)io_DISK_PHASE3_OFF + SLOT6:
disk_phase_off( (addr - io_DISK_PHASE0_OFF - SLOT6) / 2 );
break;
case (uint8_t)io_DISK_PHASE0_ON + SLOT6:
case (uint8_t)io_DISK_PHASE1_ON + SLOT6:
case (uint8_t)io_DISK_PHASE2_ON + SLOT6:
case (uint8_t)io_DISK_PHASE3_ON + SLOT6:
disk_phase_on( (addr - io_DISK_PHASE0_ON - SLOT6) / 2 );
break;
case (uint8_t)io_DISK_POWER_OFF + SLOT6:
dbgPrintf2("io_DISK_POWER_OFF (S%u)\n", 6);
disk_motor_off();
break;
case (uint8_t)io_DISK_POWER_ON + SLOT6:
dbgPrintf2("io_DISK_POWER_ON (S%u)\n", 6);
disk_motor_on();
break;
case (uint8_t)io_DISK_SELECT_1 + SLOT6:
dbgPrintf2("io_DISK_SELECT_1 (S%u)\n", 6);
disk.drive = 0;
break;
case (uint8_t)io_DISK_SELECT_2 + SLOT6:
dbgPrintf2("io_DISK_SELECT_2 (S%u)\n", 6);
disk.drive = 1;
break;
case (uint8_t)io_DISK_READ + SLOT6:
Apple2_64K_RAM[io_DISK_READ + SLOT6] = val;
woz_write( Apple2_64K_RAM[io_DISK_WRITE + SLOT6] );
writeState = 0;
break;
case (uint8_t)io_DISK_WRITE + SLOT6:
dbgPrintf2("io_DISK_WRITE (S%u)\n", 6);
Apple2_64K_RAM[io_DISK_WRITE + SLOT6] = val;
writeState = 1;
break;
case (uint8_t)io_DISK_CLEAR + SLOT6:
dbgPrintf2("io_DISK_CLEAR (S%u)\n", 6);
break;
case (uint8_t)io_DISK_SHIFT + SLOT6:
dbgPrintf2("io_DISK_SHIFT (S%u)\n", 6);
break;
default:
break;
}
return;
}
/**
Naive implementation of RAM read from address
**/
INLINE uint8_t memread8_low( uint16_t addr ) {
return Apple2_64K_MEM[addr];
}
INLINE uint8_t memread8_high( uint16_t addr ) {
return RDHIMEM[addr];
}
INLINE uint8_t memread8( uint16_t addr ) {
if (addr >= 0xC000) {
return memread8_high(addr);
}
return memread8_low(addr);
}
/**
Naive implementation of RAM read from address
**/
INLINE uint16_t memread16_low( uint16_t addr ) {
return * (uint16_t*) ( Apple2_64K_MEM + addr );
}
//INLINE uint16_t memread16_high( uint16_t addr ) {
// return * (uint16_t*) ( RDHIMEM + addr );
//}
INLINE uint16_t memread16( uint16_t addr ) {
// if (addr >= 0xC000) {
// return memread16_high(addr);
// }
return memread16_low(addr);
}
INLINE uint8_t memread( uint16_t addr ) {
if (addr >= 0xC000) {
if (addr < 0xC100) {
return ioRead(addr);
}
// return memread8_paged(addr);
return memread8_high(addr);
}
// return memread8_paged(addr);
return memread8_low(addr);
// return memread8(addr);
}
/**
Naive implementation of RAM read from address
**/
//INLINE uint16_t memioread16( uint16_t addr ) {
// return (uint16_t)mmio_read[ addr ](addr);
//}
/**
Naive implementation of RAM write to address
**/
//static void memwrite_zp( uint8_t addr, uint8_t byte ) {
// RAM[ addr ] = byte;
//}
/**
Naive implementation of RAM write to address
**/
INLINE void memwrite8_low( uint16_t addr, uint8_t data ) {
WRLOMEM[addr] = data;
}
INLINE void memwrite8_bank2( uint16_t addr, uint8_t data ) {
WRD0MEM[addr] = data;
}
INLINE void memwrite8_high( uint16_t addr, uint8_t data ) {
WRHIMEM[addr] = data;
}
INLINE void memwrite( uint16_t addr, uint8_t data ) {
if (addr >= 0xC000) {
if (addr < 0xC100) {
ioWrite(addr, data);
}
else if (addr < 0xD000) {
// this could be either Peripherial ROM or Internal ROM
memwrite8_high(addr, data);
}
else if (addr < 0xE000) {
// Aux RAM Bank 1 or 2
memwrite8_bank2(addr, data);
}
else {
// ROM (dummy memory to screape writings) or Aux RAM
memwrite8_high(addr, data);
}
}
else {
// RAM
memwrite8_low(addr, data);
}
}
/**
Fetching 1 byte from memory address pc (program counter)
increase pc by one
**/
INLINE uint8_t fetch() {
disHexB( disassembly.pOpcode, memread(m6502.PC) );
#ifdef CLK_ABSOLUTE_PRECISE
if ( (m6502.PC & 0xFF) >= 0xFF ) {
m6502.clktime++;
}
#endif
return memread8_low( m6502.PC++ );
}
/**
Fetching 2 bytes as a 16 bit number from memory address pc (program counter)
increase pc by one
**/
INLINE uint16_t fetch16() {
uint16_t word = memread16( m6502.PC );
// disPrintf(disassembly.comment, "fetch16:%04X", word);
#ifdef CLK_ABSOLUTE_PRECISE
if ( (m6502.PC & 0xFF) >= 0xFE ) {
m6502.clktime++;
}
#endif
m6502.PC += 2;
// disHexW( disassembly.pOpcode, word );
// Virtual ][ Style
disHexB( disassembly.pOpcode, (uint8_t)word );
disHexB( disassembly.pOpcode, (uint8_t)(word >> 8));
return word;
}
//INLINE uint8_t * dest( uint8_t * mem, uint16_t addr ) {
// return mem + addr;
//}
/**
abs .... absolute OPC $LLHH,X
operand is address; effective address is address incremented by X with carry **
**/
INLINE uint16_t addr_abs() {
dbgPrintf("abs:%04X(%02X) ", *((uint16_t*)&RAM[m6502.PC]), RAM[*((uint16_t*)&RAM[m6502.PC])]);
disPrintf(disassembly.oper, "$%04X", memread16(m6502.PC))
return fetch16();
}
INLINE uint8_t src_abs() {
return memread( addr_abs() );
}
//INLINE uint8_t * dest_abs() {
// return WRLOMEM + addr_abs();
//}
INLINE int8_t rel_addr() {
disPrintf(disassembly.oper, "$%04X", m6502.PC + 1 + (int8_t)memread8(m6502.PC))
return fetch();
}
INLINE uint16_t abs_addr() {
disPrintf(disassembly.oper, "$%04X", memread16(m6502.PC))
return fetch16();
}
INLINE uint16_t ind_addr() {
disPrintf(disassembly.oper, "($%04X)", memread16(m6502.PC))
disPrintf(disassembly.comment, "ind_addr:%04X", memread16(memread16(m6502.PC)))
return memread16( fetch16() );
}
/**
abs,X .... absolute, X-indexed OPC $LLHH,X
operand is address; effective address is address incremented by X with carry **
**/
INLINE uint16_t addr_abs_X() {
dbgPrintf("abs,X:%04X(%02X) ", *((uint16_t*)&RAM[m6502.PC]) + m6502.X, RAM[*((uint16_t*)&RAM[m6502.PC]) + m6502.X]);
disPrintf(disassembly.oper, "$%04X,X", memread16(m6502.PC));
return fetch16() + m6502.X;
}
INLINE uint8_t src_abs_X() {
return memread( addr_abs_X() );
}
//INLINE uint8_t * dest_abs_X() {
// return WRLOMEM + addr_abs_X();
//}
/**
abs,Y .... absolute, Y-indexed OPC $LLHH,Y
operand is address; effective address is address incremented by Y with carry **
**/
INLINE uint16_t addr_abs_Y() {
dbgPrintf("abs,Y:%04X(%02X) ", *((uint16_t*)&RAM[m6502.PC]) + m6502.Y, RAM[*((uint16_t*)&RAM[m6502.PC]) + m6502.Y]);
disPrintf(disassembly.oper, "$%04X,Y", memread16(m6502.PC))
return fetch16() + m6502.Y;
}
INLINE uint8_t src_abs_Y() {
return memread(addr_abs_Y());
}
//INLINE uint8_t * dest_abs_Y() {
// return WRLOMEM + addr_abs_Y();
//}
INLINE uint8_t imm() {
disPrintf(disassembly.oper, "#$%02X", memread8(m6502.PC))
return fetch();
}
/**
zpg .... zeropage OPC $LL
operand is zeropage address (hi-byte is zero, address = $00LL)
**/
INLINE uint8_t addr_zp() {
dbgPrintf("zp:%02X(%02X) ", RAM[m6502.PC], RAM[ RAM[m6502.PC]] );
disPrintf(disassembly.oper, "$%02X", memread8(m6502.PC))
return fetch();
}
INLINE uint8_t src_zp() {
return memread8_low(addr_zp());
}
//INLINE uint8_t * dest_zp() {
// return WRLOMEM + addr_zp();
//}
/**
get a 16 bit address from the zp:zp+1
**/
//INLINE uint16_t addr_zp_ind( uint8_t addr ) {
// dbgPrintf("zpi:%02X:%04X(%02X) ", RAM[m6502.PC], *((uint16_t*)&RAM[m6502.PC]), RAM[*((uint16_t*)&RAM[m6502.PC])]);
// disPrintf(disassembly.oper, "($%02X)", memread8(m6502.PC) );
// disPrintf(disassembly.comment, "ind_addr:%04X", memread16( memread8(m6502.PC) ) );
// return memread16(addr);
//}
/**
X,ind .... X-indexed, indirect OPC ($LL,X)
operand is zeropage address;
effective address is word in (LL + X, LL + X + 1), inc. without carry: C.w($00LL + X)
**/
INLINE uint16_t addr_ind_X() {
dbgPrintf("zpXi:%02X:%04X(%02X) ", RAM[m6502.PC], *((uint16_t*)&RAM[m6502.PC]) + m6502.X, RAM[*((uint16_t*)&RAM[m6502.PC]) + m6502.X]);
disPrintf(disassembly.oper, "($%02X,X)", memread8(m6502.PC) )
disPrintf(disassembly.comment, "ind_addr:%04X", memread16( memread8(m6502.PC) + m6502.X) );
return memread16( fetch() + m6502.X );
}
INLINE uint8_t src_X_ind() {
return memread( addr_ind_X() );
}
//INLINE uint8_t * dest_X_ind() {
// return WRLOMEM + addr_ind_X();
//}
/**
ind,Y .... indirect, Y-indexed OPC ($LL),Y
operand is zeropage address;
effective address is word in (LL, LL + 1) incremented by Y with carry: C.w($00LL) + Y
**/
INLINE uint16_t addr_ind_Y() {
// uint8_t a = fetch();
// dbgPrintf("addr_ind_Y: %04X + %02X = %04X ", addr_zpg_ind( a ), m6502.Y, addr_zpg_ind( a ) + m6502.Y);
disPrintf(disassembly.oper, "($%02X),Y", memread8(m6502.PC) )
disPrintf(disassembly.comment, "ind_addr:%04X", memread16( memread8(m6502.PC) ) + m6502.Y );
return memread16( fetch() ) + m6502.Y;
}
INLINE uint8_t src_ind_Y() {
return memread( addr_ind_Y() );
}
//INLINE uint8_t * dest_ind_Y() {
// return WRLOMEM + addr_ind_Y();
//}
/**
zpg,X .... zeropage, X-indexed OPC $LL,X
operand is zeropage address;
effective address is address incremented by X without carry **
**/
INLINE uint8_t addr_zp_X() {
disPrintf(disassembly.oper, "$%02X,X", memread8(m6502.PC))
return fetch() + m6502.X;
}
INLINE uint8_t src_zp_X() {
return memread8_low(addr_zp_X());
}
//INLINE uint8_t * dest_zp_X() {
// return WRLOMEM + addr_zp_X();
//}
/**
zpg,Y .... zeropage, Y-indexed OPC $LL,Y
operand is zeropage address;
effective address is address incremented by Y without carry **
**/
INLINE uint8_t addr_zp_Y() {
disPrintf(disassembly.oper, "$%02X,Y", memread8(m6502.PC))
return fetch() + m6502.Y;
}
INLINE uint8_t src_zp_Y() {
return memread8_low(addr_zp_Y());
}
//INLINE uint8_t * dest_zp_Y() {
// return WRLOMEM + addr_zp_Y();
//}
void auxMemorySelect( MEMcfg_t newMEMcfg ) {
const uint8_t * newLowMEM = currentLowMEM;

View File

@ -380,931 +380,41 @@ extern void textPageSelect(void);
extern unsigned int lastIO;
INLINE void io_RAM_EXP( uint16_t addr ) {
if ( MEMcfg.RAM_16K || MEMcfg.RAM_128K ) {
uint8_t * RAM_BANK = Apple2_64K_AUX + 0xC000;
// save the content of Shadow Memory in needed
if ( MEMcfg.WR_RAM ) {
// printf("Saving RAM Bank %d to %p\n", MEMcfg.RAM_BANK_2 + 1, current_RAM_bank);
memcpy(current_RAM_bank, Apple2_64K_MEM + 0xD000, 0x1000);
memcpy(Apple2_64K_AUX + 0xE000, Apple2_64K_MEM + 0xE000, 0x2000);
}
// RAM Bank 1 or 2?
switch ((uint8_t)addr) {
case (uint8_t)io_MEM_RDRAM_NOWR_2:
case (uint8_t)io_MEM_RDROM_WRAM_2:
case (uint8_t)io_MEM_RDROM_NOWR_2:
case (uint8_t)io_MEM_RDRAM_WRAM_2:
case (uint8_t)io_MEM_RDRAM_NOWR_2_:
case (uint8_t)io_MEM_RDROM_WRAM_2_:
case (uint8_t)io_MEM_RDROM_NOWR_2_:
case (uint8_t)io_MEM_RDRAM_WRAM_2_:
// printf("RAM_BANK_2\n");
MEMcfg.RAM_BANK_2 = 1;
RAM_BANK = Apple2_64K_AUX + 0xD000;
break;
default:
// printf("RAM_BANK_1\n");
MEMcfg.RAM_BANK_2 = 0;
RAM_BANK = Apple2_64K_AUX + 0xC000;
break;
}
// is RAM to read or ROM?
switch ((uint8_t)addr) {
case (uint8_t)io_MEM_RDRAM_NOWR_2:
case (uint8_t)io_MEM_RDRAM_WRAM_2:
case (uint8_t)io_MEM_RDRAM_NOWR_1:
case (uint8_t)io_MEM_RDRAM_WRAM_1:
case (uint8_t)io_MEM_RDRAM_NOWR_2_:
case (uint8_t)io_MEM_RDRAM_WRAM_2_:
case (uint8_t)io_MEM_RDRAM_NOWR_1_:
case (uint8_t)io_MEM_RDRAM_WRAM_1_:
// printf("RD_RAM\n");
MEMcfg.RD_INT_RAM = 1;
// load the content of Aux Memory
memcpy(Apple2_64K_MEM + 0xD000, RAM_BANK, 0x1000);
memcpy(Apple2_64K_MEM + 0xE000, Apple2_64K_AUX + 0xE000, 0x2000);
// set the RAM extension to read on the upper memory area
break;
default:
// printf("RD_ROM\n");
MEMcfg.RD_INT_RAM = 0;
// load the content of ROM Memory
memcpy(Apple2_64K_MEM + 0xD000, Apple2_64K_ROM + 0xD000, 0x3000);
// set the ROM to read on the upper memory area
break;
}
// is RAM Writeable?
switch ((uint8_t)addr) {
case (uint8_t)io_MEM_RDROM_WRAM_2:
case (uint8_t)io_MEM_RDROM_WRAM_1:
case (uint8_t)io_MEM_RDROM_WRAM_2_:
case (uint8_t)io_MEM_RDROM_WRAM_1_:
// printf("RD_ROM + WR_AUX\n");
// will write directly to Auxiliary RAM, and mark it as NO need to commit from Shadow RAM
MEMcfg.WR_RAM = 0;
if ( MEMcfg.RAM_BANK_2 ) {
WRD0MEM = Apple2_64K_AUX; // for Write $D000 - $DFFF (shadow memory) - BANK 2
}
else {
WRD0MEM = Apple2_64K_AUX - 0x1000; // for Write $D000 - $DFFF (shadow memory) - BANK 1
}
WRHIMEM = Apple2_64K_AUX; // for Write $E000 - $FFFF (shadow memory)
break;
case (uint8_t)io_MEM_RDRAM_WRAM_2:
case (uint8_t)io_MEM_RDRAM_WRAM_1:
case (uint8_t)io_MEM_RDRAM_WRAM_2_:
case (uint8_t)io_MEM_RDRAM_WRAM_1_:
// printf("RD_RAM + WR_RAM\n");
// will write to Shadow RAM, and mark it as need to commit from Shadow RAM
MEMcfg.WR_RAM = 1;
WRD0MEM = Apple2_64K_MEM; // for Write $D000 - $DFFF (shadow memory) - BANK X
WRHIMEM = Apple2_64K_MEM; // for Write $E000 - $FFFF (shadow memory)
break;
default:
// printf("RD_ROM + NO_WR\n");
// No writing (Readonly), and mark it as NO need to commit from Shadow RAM
MEMcfg.WR_RAM = 0;
WRD0MEM = Apple2_Dummy_RAM; // for Discarding any writes to $D000 - $DFFF - BANK X
WRHIMEM = Apple2_Dummy_RAM; // for Discarding any writes to $E000 - $FFFF
break;
}
current_RAM_bank = RAM_BANK;
// printf("Set current_RAM_bank %d to %p\n", MEMcfg.RAM_BANK_2 + 1, current_RAM_bank);
} // if there is RAM expansion card installed
}
INLINE uint8_t ioRead( uint16_t addr ) {
// if (outdev) fprintf(outdev, "ioRead:%04X\n", addr);
// printf("ioRead:%04X (PC:%04X)\n", addr, m6502.PC);
unsigned int IOframe = m6502.clkfrm - lastIO;
lastIO = m6502.clkfrm;
// TODO: This is for speed demo only, should be either removed or the entire ioRead should based on binary search, whatever is faster
if ( addr == io_KBD ) {
// clk_6502_per_frm_max = clk_6502_per_frm_max > 32768 ? clk_6502_per_frm_max - 32768 : 0; // ECO Mode!
if ( cpuMode == cpuMode_eco ) {
// check if this is a busy keyboard poll (aka waiting for user input)
if ( IOframe < 16 ) {
clk_6502_per_frm_max = 6502; // Let it run for a bit to display character -- nerd number :-)
cpuState = cpuState_halting;
}
}
return Apple2_64K_RAM[io_KBD];
}
switch ( (uint8_t)addr ) {
case (uint8_t)io_KBD:
return Apple2_64K_RAM[io_KBD];
case (uint8_t)io_KBDSTRB:
Apple2_64K_RAM[io_KBD] &= ~(1 << 7);
if ( cpuMode == cpuMode_eco ) {
// check if this is a busy keyboard poll (aka waiting for user input)
clk_6502_per_frm_max = clk_6502_per_frm; // Absolute low mode
cpuState = cpuState_running;
}
return Apple2_64K_RAM[io_KBDSTRB];
case (uint8_t)io_TAPEOUT:
case (uint8_t)io_SPKR:
spkr_toggle();
return Apple2_64K_RAM[io_SPKR];
case (uint8_t)io_VID_RDVBL:
return (m6502.clkfrm < 4550) ? 0x80 : 0;
case (uint8_t)io_VID_RDTEXT:
return videoMode.text << 7;
case (uint8_t)io_VID_ALTCHAR:
return videoMode.altChr << 7;
case (uint8_t)io_VID_RD80VID:
return videoMode.col80 << 7;
case (uint8_t)io_TAPEIN:
// TODO: this should be only on //c
return MEMcfg.txt_page_2 << 7;
case (uint8_t)io_RDCXROM:
return MEMcfg.int_Cx_ROM << 7;
case (uint8_t)io_RDLCBNK2:
return MEMcfg.RAM_BANK_2 << 7;
case (uint8_t)io_RDLCRAM:
return MEMcfg.RD_INT_RAM << 7;
case (uint8_t)io_RDRAMRD:
return MEMcfg.RD_AUX_MEM << 7;
case (uint8_t)io_RDRAMWR:
return MEMcfg.WR_AUX_MEM << 7;
case (uint8_t)io_RDALTZP:
return MEMcfg.ALT_ZP << 7;
case (uint8_t)io_RDC3ROM:
return MEMcfg.slot_C3_ROM << 7;
case (uint8_t)io_RD80STORE:
return MEMcfg.is_80STORE << 7;
case (uint8_t)io_VID_TXTPAGE1:
// printf("io_VID_TXTPAGE1\n");
MEMcfg.txt_page_2 = 0;
textPageSelect();
break;
case (uint8_t)io_VID_TXTPAGE2:
// printf("io_VID_TXTPAGE2\n");
MEMcfg.txt_page_2 = 1;
textPageSelect();
break;
case (uint8_t)io_VID_RDPAGE2:
return MEMcfg.txt_page_2 << 7;
case (uint8_t)io_VID_Text_OFF:
videoMode.text = 0;
break;
case (uint8_t)io_VID_Text_ON:
videoMode.text = 1;
break;
case (uint8_t)io_VID_Mixed_OFF:
videoMode.mixed = 0;
break;
case (uint8_t)io_VID_Mixed_ON:
videoMode.mixed = 1;
break;
case (uint8_t)io_VID_RDMIXED:
return videoMode.mixed << 7;
case (uint8_t)io_VID_Hires_OFF:
videoMode.hires = 0;
break;
case (uint8_t)io_VID_Hires_ON:
videoMode.hires = 1;
break;
case (uint8_t)io_VID_RDHIRES:
return videoMode.hires << 7;
case (uint8_t)io_PDL0:
case (uint8_t)io_PDL1:
case (uint8_t)io_PDL2:
case (uint8_t)io_PDL3:
// printf("PDL%d: %d\n", addr - io_PDL0, pdl_read( addr - io_PDL0 ));
return pdl_read( addr - io_PDL0 );
case (uint8_t)io_PDL_STROBE:
return pdl_reset();
case (uint8_t)io_RDMAINRAM:
// printf("io_RDMAINRAM\n");
newMEMcfg = MEMcfg;
newMEMcfg.RD_AUX_MEM = 0;
auxMemorySelect(newMEMcfg);
break;
case (uint8_t)io_RDCARDRAM:
// printf("io_RDCARDRAM\n");
newMEMcfg = MEMcfg;
newMEMcfg.RD_AUX_MEM = 1;
auxMemorySelect(newMEMcfg);
break;
case (uint8_t)io_WRMAINRAM:
// printf("io_WRMAINRAM\n");
newMEMcfg = MEMcfg;
newMEMcfg.WR_AUX_MEM = 0;
auxMemorySelect(newMEMcfg);
break;
case (uint8_t)io_WRCARDRAM:
// printf("io_WRCARDRAM\n");
newMEMcfg = MEMcfg;
newMEMcfg.WR_AUX_MEM = 1;
auxMemorySelect(newMEMcfg);
break;
case (uint8_t)io_MEM_RDRAM_NOWR_2:
case (uint8_t)io_MEM_RDROM_WRAM_2:
case (uint8_t)io_MEM_RDROM_NOWR_2:
case (uint8_t)io_MEM_RDRAM_WRAM_2:
case (uint8_t)io_MEM_RDRAM_NOWR_2_:
case (uint8_t)io_MEM_RDROM_WRAM_2_:
case (uint8_t)io_MEM_RDROM_NOWR_2_:
case (uint8_t)io_MEM_RDRAM_WRAM_2_:
case (uint8_t)io_MEM_RDRAM_NOWR_1:
case (uint8_t)io_MEM_RDROM_WRAM_1:
case (uint8_t)io_MEM_RDROM_NOWR_1:
case (uint8_t)io_MEM_RDRAM_WRAM_1:
case (uint8_t)io_MEM_RDRAM_NOWR_1_:
case (uint8_t)io_MEM_RDROM_WRAM_1_:
case (uint8_t)io_MEM_RDROM_NOWR_1_:
case (uint8_t)io_MEM_RDRAM_WRAM_1_:
io_RAM_EXP(addr);
break;
// TODO: Make code "card insertable to slot" / aka slot independent and dynamically add/remove
case (uint8_t)io_DISK_PHASE0_OFF + SLOT6:
case (uint8_t)io_DISK_PHASE1_OFF + SLOT6:
case (uint8_t)io_DISK_PHASE2_OFF + SLOT6:
case (uint8_t)io_DISK_PHASE3_OFF + SLOT6:
disk_phase_off( (addr - io_DISK_PHASE0_OFF - SLOT6) / 2 );
return disk_read();
case (uint8_t)io_DISK_PHASE0_ON + SLOT6:
case (uint8_t)io_DISK_PHASE1_ON + SLOT6:
case (uint8_t)io_DISK_PHASE2_ON + SLOT6:
case (uint8_t)io_DISK_PHASE3_ON + SLOT6:
disk_phase_on( (addr - io_DISK_PHASE0_ON - SLOT6) / 2 );
return disk_read();
case (uint8_t)io_DISK_POWER_OFF + SLOT6:
dbgPrintf2("io_DISK_POWER_OFF (S%u)\n", 6);
disk_motor_off();
return disk_read();
case (uint8_t)io_DISK_POWER_ON + SLOT6:
dbgPrintf2("io_DISK_POWER_ON (S%u)\n", 6);
disk_motor_on();
return disk_read();
case (uint8_t)io_DISK_SELECT_1 + SLOT6:
dbgPrintf2("io_DISK_SELECT_1 (S%u)\n", 6);
disk.drive = 0;
return disk_read();
case (uint8_t)io_DISK_SELECT_2 + SLOT6:
dbgPrintf2("io_DISK_SELECT_2 (S%u)\n", 6);
disk.drive = 1;
return disk_read();
case (uint8_t)io_DISK_READ + SLOT6:
if ( writeState ) {
writeState = 0;
woz_write( Apple2_64K_RAM[io_DISK_WRITE + SLOT6] );
return Apple2_64K_RAM[io_DISK_WRITE + SLOT6];
}
else {
return disk_read();
}
case (uint8_t)io_DISK_WRITE + SLOT6:
dbgPrintf2("io_DISK_WRITE (S%u)\n", 6);
// Apple2_64K_RAM[io_DISK_CLEAR + SLOT6] |= 1 << 7; // mark disk as write protected
WOZwrite.latch = WOZread.latch = 0;
Apple2_64K_RAM[io_DISK_CLEAR + SLOT6] &= ~(1 << 7); // mark disk as write enabled
return Apple2_64K_RAM[io_DISK_WRITE + SLOT6];
case (uint8_t)io_DISK_CLEAR + SLOT6:
dbgPrintf2("io_DISK_CLEAR (S%u)\n", 6);
return Apple2_64K_RAM[io_DISK_CLEAR + SLOT6];
case (uint8_t)io_DISK_SHIFT + SLOT6:
dbgPrintf2("io_DISK_SHIFT (S%u)\n", 6);
return disk_read();
default:
//printf("mmio read:%04X\n", addr);
break;
}
return Apple2_64K_RAM[addr];
}
INLINE void ioWrite( uint16_t addr, uint8_t val ) {
// if (outdev) fprintf(outdev, "ioWrite:%04X (A:%02X)\n", addr, m6502.A);
switch ( (uint8_t)addr ) {
case (uint8_t)io_KBDSTRB:
Apple2_64K_RAM[io_KBD] &= 0x7F;
break;
case (uint8_t)io_TAPEOUT:
case (uint8_t)io_SPKR:
spkr_toggle();
break;
case (uint8_t)io_RDMAINRAM:
// printf("io_RDMAINRAM\n");
newMEMcfg = MEMcfg;
newMEMcfg.RD_AUX_MEM = 0;
auxMemorySelect(newMEMcfg);
break;
case (uint8_t)io_RDCARDRAM:
// printf("io_RDCARDRAM\n");
newMEMcfg = MEMcfg;
newMEMcfg.RD_AUX_MEM = 1;
auxMemorySelect(newMEMcfg);
break;
case (uint8_t)io_WRMAINRAM:
// printf("io_WRMAINRAM\n");
newMEMcfg = MEMcfg;
newMEMcfg.WR_AUX_MEM = 0;
auxMemorySelect(newMEMcfg);
break;
case (uint8_t)io_WRCARDRAM:
// printf("io_WRCARDRAM\n");
newMEMcfg = MEMcfg;
newMEMcfg.WR_AUX_MEM = 1;
auxMemorySelect(newMEMcfg);
break;
case (uint8_t)io_SETSTDZP:
MEMcfg.ALT_ZP = 0;
// TODO: set zero page table to RAM
break;
case (uint8_t)io_SETALTZP:
MEMcfg.ALT_ZP = 1;
// TODO: set zero page table to AUX
break;
case (uint8_t)io_SETSLOTCXROM:
// printf("io_SETSLOTCXROM\n");
MEMcfg.int_Cx_ROM = 0;
// TODO: set Cx00 ROM area table to SLOT
break;
case (uint8_t)io_SETINTCXROM:
// printf("io_SETINTCXROM\n");
MEMcfg.int_Cx_ROM = 1;
// TODO: set Cx00 ROM area table to INT
break;
case (uint8_t)io_SETSLOTC3ROM:
// printf("io_SETSLOTC3ROM\n");
MEMcfg.slot_C3_ROM = 1;
// TODO: set C300 ROM area table to SLOT
break;
case (uint8_t)io_SETINTC3ROM:
// printf("io_SETINTC3ROM\n");
MEMcfg.slot_C3_ROM = 0;
// TODO: set C300 ROM area table to INT
break;
case (uint8_t)io_VID_CLR80VID:
// printf("io_VID_CLR80VID\n");
videoMode.col80 = 0;
break;
case (uint8_t)io_VID_SET80VID:
videoMode.col80 = 1;
break;
case (uint8_t)io_VID_CLRALTCHAR:
videoMode.altChr = 0;
break;
case (uint8_t)io_VID_SETALTCHAR:
videoMode.altChr = 1;
break;
case (uint8_t)io_80STOREOFF:
// printf("io_80STOREOFF\n");
MEMcfg.is_80STORE = 0;
textPageSelect();
break;
case (uint8_t)io_80STOREON:
// printf("io_80STOREON\n");
MEMcfg.is_80STORE = 1;
textPageSelect();
break;
case (uint8_t)io_VID_TXTPAGE1:
// printf("io_VID_TXTPAGE1\n");
MEMcfg.txt_page_2 = 0;
textPageSelect();
break;
case (uint8_t)io_VID_TXTPAGE2:
// printf("io_VID_TXTPAGE2\n");
MEMcfg.txt_page_2 = 1;
textPageSelect();
break;
case (uint8_t)io_VID_Text_OFF:
videoMode.text = 0;
break;
case (uint8_t)io_VID_Text_ON:
videoMode.text = 1;
break;
case (uint8_t)io_VID_Mixed_OFF:
videoMode.mixed = 0;
break;
case (uint8_t)io_VID_Mixed_ON:
videoMode.mixed = 1;
break;
case (uint8_t)io_VID_Hires_OFF:
videoMode.hires = 0;
break;
case (uint8_t)io_VID_Hires_ON:
videoMode.hires = 1;
break;
case (uint8_t)io_MEM_RDRAM_NOWR_2:
case (uint8_t)io_MEM_RDROM_WRAM_2:
case (uint8_t)io_MEM_RDROM_NOWR_2:
case (uint8_t)io_MEM_RDRAM_WRAM_2:
case (uint8_t)io_MEM_RDRAM_NOWR_2_:
case (uint8_t)io_MEM_RDROM_WRAM_2_:
case (uint8_t)io_MEM_RDROM_NOWR_2_:
case (uint8_t)io_MEM_RDRAM_WRAM_2_:
case (uint8_t)io_MEM_RDRAM_NOWR_1:
case (uint8_t)io_MEM_RDROM_WRAM_1:
case (uint8_t)io_MEM_RDROM_NOWR_1:
case (uint8_t)io_MEM_RDRAM_WRAM_1:
case (uint8_t)io_MEM_RDRAM_NOWR_1_:
case (uint8_t)io_MEM_RDROM_WRAM_1_:
case (uint8_t)io_MEM_RDROM_NOWR_1_:
case (uint8_t)io_MEM_RDRAM_WRAM_1_:
io_RAM_EXP(addr);
break;
// TODO: Make code "card insertable to slot" / aka slot independent and dynamically add/remove
case (uint8_t)io_DISK_PHASE0_OFF + SLOT6:
case (uint8_t)io_DISK_PHASE1_OFF + SLOT6:
case (uint8_t)io_DISK_PHASE2_OFF + SLOT6:
case (uint8_t)io_DISK_PHASE3_OFF + SLOT6:
disk_phase_off( (addr - io_DISK_PHASE0_OFF - SLOT6) / 2 );
break;
case (uint8_t)io_DISK_PHASE0_ON + SLOT6:
case (uint8_t)io_DISK_PHASE1_ON + SLOT6:
case (uint8_t)io_DISK_PHASE2_ON + SLOT6:
case (uint8_t)io_DISK_PHASE3_ON + SLOT6:
disk_phase_on( (addr - io_DISK_PHASE0_ON - SLOT6) / 2 );
break;
case (uint8_t)io_DISK_POWER_OFF + SLOT6:
dbgPrintf2("io_DISK_POWER_OFF (S%u)\n", 6);
disk_motor_off();
break;
case (uint8_t)io_DISK_POWER_ON + SLOT6:
dbgPrintf2("io_DISK_POWER_ON (S%u)\n", 6);
disk_motor_on();
break;
case (uint8_t)io_DISK_SELECT_1 + SLOT6:
dbgPrintf2("io_DISK_SELECT_1 (S%u)\n", 6);
disk.drive = 0;
break;
case (uint8_t)io_DISK_SELECT_2 + SLOT6:
dbgPrintf2("io_DISK_SELECT_2 (S%u)\n", 6);
disk.drive = 1;
break;
case (uint8_t)io_DISK_READ + SLOT6:
Apple2_64K_RAM[io_DISK_READ + SLOT6] = val;
woz_write( Apple2_64K_RAM[io_DISK_WRITE + SLOT6] );
writeState = 0;
break;
case (uint8_t)io_DISK_WRITE + SLOT6:
dbgPrintf2("io_DISK_WRITE (S%u)\n", 6);
Apple2_64K_RAM[io_DISK_WRITE + SLOT6] = val;
writeState = 1;
break;
case (uint8_t)io_DISK_CLEAR + SLOT6:
dbgPrintf2("io_DISK_CLEAR (S%u)\n", 6);
break;
case (uint8_t)io_DISK_SHIFT + SLOT6:
dbgPrintf2("io_DISK_SHIFT (S%u)\n", 6);
break;
default:
break;
}
return;
}
/**
Naive implementation of RAM read from address
**/
/**
Naive implementation of RAM read from address
**/
INLINE uint8_t memread8_low( uint16_t addr ) {
return Apple2_64K_MEM[addr];
}
INLINE uint8_t memread8_high( uint16_t addr ) {
return RDHIMEM[addr];
}
INLINE uint8_t memread8( uint16_t addr ) {
if (addr >= 0xC000) {
return memread8_high(addr);
}
return memread8_low(addr);
}
/**
Naive implementation of RAM read from address
**/
INLINE uint16_t memread16_low( uint16_t addr ) {
return * (uint16_t*) ( Apple2_64K_MEM + addr );
}
//INLINE uint16_t memread16_high( uint16_t addr ) {
// return * (uint16_t*) ( RDHIMEM + addr );
//}
INLINE uint16_t memread16( uint16_t addr ) {
// if (addr >= 0xC000) {
// return memread16_high(addr);
// }
return memread16_low(addr);
}
INLINE uint8_t memread( uint16_t addr ) {
if (addr >= 0xC000) {
if (addr < 0xC100) {
return ioRead(addr);
}
// return memread8_paged(addr);
return memread8_high(addr);
}
// return memread8_paged(addr);
return memread8_low(addr);
// return memread8(addr);
}
/**
Naive implementation of RAM read from address
**/
//INLINE uint16_t memioread16( uint16_t addr ) {
// return (uint16_t)mmio_read[ addr ](addr);
//}
/**
Naive implementation of RAM write to address
**/
//static void memwrite_zp( uint8_t addr, uint8_t byte ) {
// RAM[ addr ] = byte;
//}
/**
Naive implementation of RAM write to address
**/
INLINE void memwrite8_low( uint16_t addr, uint8_t data ) {
WRLOMEM[addr] = data;
}
INLINE void memwrite8_bank2( uint16_t addr, uint8_t data ) {
WRD0MEM[addr] = data;
}
INLINE void memwrite8_high( uint16_t addr, uint8_t data ) {
WRHIMEM[addr] = data;
}
INLINE void memwrite( uint16_t addr, uint8_t data ) {
if (addr >= 0xC000) {
if (addr < 0xC100) {
ioWrite(addr, data);
}
else if (addr < 0xD000) {
// this could be either Peripherial ROM or Internal ROM
memwrite8_high(addr, data);
}
else if (addr < 0xE000) {
// Aux RAM Bank 1 or 2
memwrite8_bank2(addr, data);
}
else {
// ROM (dummy memory to screape writings) or Aux RAM
memwrite8_high(addr, data);
}
}
else {
// RAM
memwrite8_low(addr, data);
}
}
/**
Fetching 1 byte from memory address pc (program counter)
increase pc by one
**/
INLINE uint8_t fetch() {
disHexB( disassembly.pOpcode, memread(m6502.PC) );
#ifdef CLK_ABSOLUTE_PRECISE
if ( (m6502.PC & 0xFF) >= 0xFF ) {
m6502.clktime++;
}
#endif
return memread8_low( m6502.PC++ );
}
/**
Fetching 2 bytes as a 16 bit number from memory address pc (program counter)
increase pc by one
**/
INLINE uint16_t fetch16() {
uint16_t word = memread16( m6502.PC );
// disPrintf(disassembly.comment, "fetch16:%04X", word);
#ifdef CLK_ABSOLUTE_PRECISE
if ( (m6502.PC & 0xFF) >= 0xFE ) {
m6502.clktime++;
}
#endif
m6502.PC += 2;
// disHexW( disassembly.pOpcode, word );
// Virtual ][ Style
disHexB( disassembly.pOpcode, (uint8_t)word );
disHexB( disassembly.pOpcode, (uint8_t)(word >> 8));
return word;
}
//INLINE uint8_t * dest( uint8_t * mem, uint16_t addr ) {
// return mem + addr;
//}
/**
abs .... absolute OPC $LLHH,X
operand is address; effective address is address incremented by X with carry **
**/
INLINE uint16_t addr_abs() {
dbgPrintf("abs:%04X(%02X) ", *((uint16_t*)&RAM[m6502.PC]), RAM[*((uint16_t*)&RAM[m6502.PC])]);
disPrintf(disassembly.oper, "$%04X", memread16(m6502.PC))
return fetch16();
}
INLINE uint8_t src_abs() {
return memread( addr_abs() );
}
//INLINE uint8_t * dest_abs() {
// return WRLOMEM + addr_abs();
//}
INLINE int8_t rel_addr() {
disPrintf(disassembly.oper, "$%04X", m6502.PC + 1 + (int8_t)memread8(m6502.PC))
return fetch();
}
INLINE uint16_t abs_addr() {
disPrintf(disassembly.oper, "$%04X", memread16(m6502.PC))
return fetch16();
}
INLINE uint16_t ind_addr() {
disPrintf(disassembly.oper, "($%04X)", memread16(m6502.PC))
disPrintf(disassembly.comment, "ind_addr:%04X", memread16(memread16(m6502.PC)))
return memread16( fetch16() );
}
/**
abs,X .... absolute, X-indexed OPC $LLHH,X
operand is address; effective address is address incremented by X with carry **
**/
INLINE uint16_t addr_abs_X() {
dbgPrintf("abs,X:%04X(%02X) ", *((uint16_t*)&RAM[m6502.PC]) + m6502.X, RAM[*((uint16_t*)&RAM[m6502.PC]) + m6502.X]);
disPrintf(disassembly.oper, "$%04X,X", memread16(m6502.PC));
return fetch16() + m6502.X;
}
INLINE uint8_t src_abs_X() {
return memread( addr_abs_X() );
}
//INLINE uint8_t * dest_abs_X() {
// return WRLOMEM + addr_abs_X();
//}
/**
abs,Y .... absolute, Y-indexed OPC $LLHH,Y
operand is address; effective address is address incremented by Y with carry **
**/
INLINE uint16_t addr_abs_Y() {
dbgPrintf("abs,Y:%04X(%02X) ", *((uint16_t*)&RAM[m6502.PC]) + m6502.Y, RAM[*((uint16_t*)&RAM[m6502.PC]) + m6502.Y]);
disPrintf(disassembly.oper, "$%04X,Y", memread16(m6502.PC))
return fetch16() + m6502.Y;
}
INLINE uint8_t src_abs_Y() {
return memread(addr_abs_Y());
}
//INLINE uint8_t * dest_abs_Y() {
// return WRLOMEM + addr_abs_Y();
//}
INLINE uint8_t imm() {
disPrintf(disassembly.oper, "#$%02X", memread8(m6502.PC))
return fetch();
}
/**
zpg .... zeropage OPC $LL
operand is zeropage address (hi-byte is zero, address = $00LL)
**/
INLINE uint8_t addr_zp() {
dbgPrintf("zp:%02X(%02X) ", RAM[m6502.PC], RAM[ RAM[m6502.PC]] );
disPrintf(disassembly.oper, "$%02X", memread8(m6502.PC))
return fetch();
}
INLINE uint8_t src_zp() {
return memread8_low(addr_zp());
}
//INLINE uint8_t * dest_zp() {
// return WRLOMEM + addr_zp();
//}
/**
get a 16 bit address from the zp:zp+1
**/
//INLINE uint16_t addr_zp_ind( uint8_t addr ) {
// dbgPrintf("zpi:%02X:%04X(%02X) ", RAM[m6502.PC], *((uint16_t*)&RAM[m6502.PC]), RAM[*((uint16_t*)&RAM[m6502.PC])]);
// disPrintf(disassembly.oper, "($%02X)", memread8(m6502.PC) );
// disPrintf(disassembly.comment, "ind_addr:%04X", memread16( memread8(m6502.PC) ) );
// return memread16(addr);
//}
/**
X,ind .... X-indexed, indirect OPC ($LL,X)
operand is zeropage address;
effective address is word in (LL + X, LL + X + 1), inc. without carry: C.w($00LL + X)
**/
INLINE uint16_t addr_ind_X() {
dbgPrintf("zpXi:%02X:%04X(%02X) ", RAM[m6502.PC], *((uint16_t*)&RAM[m6502.PC]) + m6502.X, RAM[*((uint16_t*)&RAM[m6502.PC]) + m6502.X]);
disPrintf(disassembly.oper, "($%02X,X)", memread8(m6502.PC) )
disPrintf(disassembly.comment, "ind_addr:%04X", memread16( memread8(m6502.PC) + m6502.X) );
return memread16( fetch() + m6502.X );
}
INLINE uint8_t src_X_ind() {
return memread( addr_ind_X() );
}
//INLINE uint8_t * dest_X_ind() {
// return WRLOMEM + addr_ind_X();
//}
/**
ind,Y .... indirect, Y-indexed OPC ($LL),Y
operand is zeropage address;
effective address is word in (LL, LL + 1) incremented by Y with carry: C.w($00LL) + Y
**/
INLINE uint16_t addr_ind_Y() {
// uint8_t a = fetch();
// dbgPrintf("addr_ind_Y: %04X + %02X = %04X ", addr_zpg_ind( a ), m6502.Y, addr_zpg_ind( a ) + m6502.Y);
disPrintf(disassembly.oper, "($%02X),Y", memread8(m6502.PC) )
disPrintf(disassembly.comment, "ind_addr:%04X", memread16( memread8(m6502.PC) ) + m6502.Y );
return memread16( fetch() ) + m6502.Y;
}
INLINE uint8_t src_ind_Y() {
return memread( addr_ind_Y() );
}
//INLINE uint8_t * dest_ind_Y() {
// return WRLOMEM + addr_ind_Y();
//}
/**
zpg,X .... zeropage, X-indexed OPC $LL,X
operand is zeropage address;
effective address is address incremented by X without carry **
**/
INLINE uint8_t addr_zp_X() {
disPrintf(disassembly.oper, "$%02X,X", memread8(m6502.PC))
return fetch() + m6502.X;
}
INLINE uint8_t src_zp_X() {
return memread8_low(addr_zp_X());
}
//INLINE uint8_t * dest_zp_X() {
// return WRLOMEM + addr_zp_X();
//}
/**
zpg,Y .... zeropage, Y-indexed OPC $LL,Y
operand is zeropage address;
effective address is address incremented by Y without carry **
**/
INLINE uint8_t addr_zp_Y() {
disPrintf(disassembly.oper, "$%02X,Y", memread8(m6502.PC))
return fetch() + m6502.Y;
}
INLINE uint8_t src_zp_Y() {
return memread8_low(addr_zp_Y());
}
//INLINE uint8_t * dest_zp_Y() {
// return WRLOMEM + addr_zp_Y();
//}
INLINE void io_RAM_EXP( uint16_t addr );
INLINE uint8_t ioRead( uint16_t addr );
INLINE void ioWrite( uint16_t addr, uint8_t val );
INLINE uint8_t memread8_low( uint16_t addr );
INLINE uint8_t memread8_high( uint16_t addr );
INLINE uint8_t memread8( uint16_t addr );
INLINE uint16_t memread16_low( uint16_t addr );
INLINE uint16_t memread16( uint16_t addr );
INLINE uint8_t memread( uint16_t addr );
INLINE void memwrite8_low( uint16_t addr, uint8_t data );
INLINE void memwrite8_bank2( uint16_t addr, uint8_t data );
INLINE void memwrite8_high( uint16_t addr, uint8_t data );
INLINE void memwrite( uint16_t addr, uint8_t data );
INLINE uint8_t fetch(void);
INLINE uint16_t fetch16(void);
INLINE uint16_t addr_abs(void);
INLINE uint8_t src_abs(void);
INLINE int8_t rel_addr(void);
INLINE uint16_t abs_addr(void);
INLINE uint16_t ind_addr(void);
INLINE uint16_t addr_abs_X(void);
INLINE uint8_t src_abs_X(void);
INLINE uint16_t addr_abs_Y(void);
INLINE uint8_t src_abs_Y(void);
INLINE uint8_t imm(void);
INLINE uint8_t addr_zp(void);
INLINE uint8_t src_zp(void);
INLINE uint16_t addr_ind_X(void);
INLINE uint8_t src_X_ind(void);
INLINE uint16_t addr_ind_Y(void);
INLINE uint8_t src_ind_Y(void);
INLINE uint8_t addr_zp_X(void);
INLINE uint8_t src_zp_X(void);
INLINE uint8_t addr_zp_Y(void);
INLINE uint8_t src_zp_Y(void);
#endif // __APPLE2_MMIO_H__

View File

@ -31,7 +31,8 @@
#ifdef DEBUG
#define INLINE
#else
#define INLINE static __attribute__((always_inline))
// #define INLINE static __attribute__((always_inline))
#define INLINE __attribute__((always_inline))
#endif

View File

@ -24,6 +24,8 @@
#ifndef disassembler_h
#define disassembler_h
#undef DISASSEMBLER
#ifdef DISASSEMBLER
//extern unsigned long long int clktime;