diff --git a/A2Mac.xcodeproj/project.pbxproj b/A2Mac.xcodeproj/project.pbxproj index 1bd2246..e12e3b5 100644 --- a/A2Mac.xcodeproj/project.pbxproj +++ b/A2Mac.xcodeproj/project.pbxproj @@ -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)", diff --git a/src/dev/audio/speaker.c b/src/dev/audio/speaker.c index 52c0c74..1532d82 100644 --- a/src/dev/audio/speaker.c +++ b/src/dev/audio/speaker.c @@ -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; diff --git a/src/dev/game/paddle.c b/src/dev/game/paddle.c index ed25f22..cec244d 100644 --- a/src/dev/game/paddle.c +++ b/src/dev/game/paddle.c @@ -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 +} + diff --git a/src/dev/game/paddle.h b/src/dev/game/paddle.h index b44efb9..062d14f 100644 --- a/src/dev/game/paddle.h +++ b/src/dev/game/paddle.h @@ -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__ */ diff --git a/src/dev/mem/mmio.c b/src/dev/mem/mmio.c index 1472e59..849ff8b 100644 --- a/src/dev/mem/mmio.c +++ b/src/dev/mem/mmio.c @@ -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; diff --git a/src/dev/mem/mmio.h b/src/dev/mem/mmio.h index b6b178c..957a7b2 100644 --- a/src/dev/mem/mmio.h +++ b/src/dev/mem/mmio.h @@ -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__ diff --git a/src/util/common.h b/src/util/common.h index 17147e4..b19e3b3 100644 --- a/src/util/common.h +++ b/src/util/common.h @@ -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 diff --git a/src/util/disassembler.h b/src/util/disassembler.h index 94ba9ef..d187280 100644 --- a/src/util/disassembler.h +++ b/src/util/disassembler.h @@ -24,6 +24,8 @@ #ifndef disassembler_h #define disassembler_h +#undef DISASSEMBLER + #ifdef DISASSEMBLER //extern unsigned long long int clktime;