mirror of
https://github.com/trudnai/Steve2.git
synced 2024-06-13 09:29:36 +00:00
Much better sound system
Paddle functions placed to C code MMIO functions placed to C code Disassembler fixed
This commit is contained in:
parent
058124bf2d
commit
aec319fac2
|
@ -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)",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#ifndef disassembler_h
|
||||
#define disassembler_h
|
||||
|
||||
#undef DISASSEMBLER
|
||||
|
||||
#ifdef DISASSEMBLER
|
||||
|
||||
//extern unsigned long long int clktime;
|
||||
|
|
Loading…
Reference in New Issue
Block a user