#define WINDOW_WIDTH (PADDED_WIDTH * WINDOW_X_SCALE)
#define WINDOW_HEIGHT (PADDED_HEIGHT * WINDOW_Y_SCALE)
-#define INSTRS_PER_UPDATE 1500
+#define CYCLES_PER_SAMPLE 34 // 44100 Hz @ 1.5 MHz
+#define SAMPLES_PER_UPDATE 500
#define IO_PAGE 0xc000
#define HW_KBD 0xc000 // R last key pressed + 128
#define HW_RDTEXT 0xc01a // R bit 7: using text mode?
#define HW_RDPAGE2 0xc01c // R bit 7: using page 2?
#define HW_RD80VID 0xc01f // R bit 7: using 80 columns?
+#define HW_TAPEOUT 0xc020 // RW toggle cassette output
#define HW_SPKR 0xc030 // RW toggle speaker
#define HW_TXTCLR 0xc050 // RW
#define HW_TXTSET 0xc051 // RW
uint8_t c00x_soft_switches = 0;
#endif
+#define C0X0_SOFT_SWITCH_TAPEOUT 4
+#define C0X0_SOFT_SWITCH_SPKR 8
+uint8_t c0x0_soft_switches = 0;
+
+// every n cycles, sample the tape and speaker outputs to here
+#define C0X0_SOFT_SWITCHES_BUF_SIZE 0x400 // next power of 2 >= 441 * 2
+int c0x0_soft_switches_buf_head;
+int c0x0_soft_switches_buf_count;
+uint8_t c0x0_soft_switches_buf[C0X0_SOFT_SWITCHES_BUF_SIZE];
+
#define C05X_SOFT_SWITCH_TEXT 1
#define C05X_SOFT_SWITCH_MIXED 2
#define C05X_SOFT_SWITCH_PAGE2 4
case HW_RD80VID:
return ((c00x_soft_switches & C00X_SOFT_SWITCH_80VID) != 0) << 7;
#endif
+ case HW_TAPEOUT: // 0xc020
+ case HW_SPKR: // 0xc030
+ c0x0_soft_switches ^= 1 << ((addr >> 4) & 7);
+ break;
case HW_TXTCLR: // 0xc050
case HW_MIXCLR: // 0xc052
case HW_PAGE1: // 0xc054
c00x_soft_switches |= 1 << ((addr >> 1) & 7);
break;
#endif
+ case HW_TAPEOUT: // 0xc020
+ case HW_SPKR: // 0xc030
+ c0x0_soft_switches ^= 1 << ((addr >> 4) & 7);
+ break;
case HW_TXTCLR: // 0xc050
case HW_MIXCLR: // 0xc052
case HW_PAGE1: // 0xc054
}
}
- if (SDL_Init(SDL_INIT_VIDEO) < 0) {
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
fprintf(stderr, "SDL_Init(): %s\n\n", SDL_GetError());
exit(EXIT_FAILURE);
}
exit(EXIT_FAILURE);
}
+ SDL_AudioSpec audio_spec;
+ memset(&audio_spec, 0, sizeof(SDL_AudioSpec));
+ audio_spec.freq = 44100;
+ audio_spec.format = AUDIO_S16SYS;
+ audio_spec.channels = 1;
+ audio_spec.silence = 0;
+ audio_spec.samples = 0x200; // next power of 2 >= 441
+ //SDL_AudioSpec audio_spec_obtained;
+ SDL_AudioDeviceID audio_device_id = SDL_OpenAudioDevice(
+ NULL,
+ 0,
+ &audio_spec,
+ NULL, //&audio_spec_obtained,
+ 0
+ );
+ if (audio_device_id == 0) {
+ fprintf(stderr, "SDL_OpenAudioDevice(): %s\n", SDL_GetError());
+ exit(EXIT_FAILURE);
+ }
+ //fprintf(
+ // stderr,
+ // "freq %d format %d channels %d silence %d samples %d\r\n",
+ // audio_spec_obtained.freq,
+ // audio_spec_obtained.format,
+ // audio_spec_obtained.channels,
+ // audio_spec_obtained.silence,
+ // audio_spec_obtained.samples
+ //);
+ SDL_PauseAudioDevice(audio_device_id, 0);
+
cpu = vrEmu6502New(CPU_65C02, mem_read, mem_write);
if (cpu == NULL) {
perror("malloc()");
// main loop
long nb_instructions = 0, nb_cycles = 0;
+ int update_count = 0;
+ float spkr_rc = 0.f;
while (true) {
SDL_Event event;
while (SDL_PollEvent(&event))
break;
}
- SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xff);
- SDL_RenderClear(renderer);
+ // video update
+ if (++update_count >= SAMPLES_PER_UPDATE) {
+ update_count = 0;
- // draw
- struct timespec timeval;
- clock_gettime(CLOCK_MONOTONIC, &timeval);
- bool flash_state = timeval.tv_nsec >= 500000000;
+ SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xff);
+ SDL_RenderClear(renderer);
- // video ROM does inverse/flash by manipulating base address
- int flash_base[4] = {
- 0,
+ struct timespec timeval;
+ clock_gettime(CLOCK_MONOTONIC, &timeval);
+ bool flash_state = timeval.tv_nsec >= 500000000;
+
+ // video ROM does inverse/flash by manipulating base address
+ int flash_base[4] = {
+ 0,
#if APPLE_IIE
- // in alternate character mode, use video ROM directly (mousetext)
- (c00x_soft_switches & C00X_SOFT_SWITCH_ALTCHAR) ?
- 0x200 :
+ // in alternate character mode, use video ROM directly (mousetext)
+ (c00x_soft_switches & C00X_SOFT_SWITCH_ALTCHAR) ?
+ 0x200 :
#endif
- flash_state ? 0 : 0x400,
- 0x400,
- 0x600
- };
-
- // CG ROM does inverse/flash by XORing onto the value from ROM
- int flash_xor[4] = {0x7f, flash_state ? 0x7f : 0, 0, 0};
-
- memset(frame, 0, WINDOW_HEIGHT * WINDOW_WIDTH * sizeof(uint32_t));
- for (int i = 0; i < APPLE_HEIGHT; ++i) {
- int base = (i >> 6) * 40 | ((i & 0x38) << 4);
- int row = i & 7;
- uint32_t buf[PADDED_WORDS];
- memset(buf, 0, PADDED_WORDS * sizeof(uint32_t));
-
- if (c05x_soft_switches & C05X_SOFT_SWITCH_HIRES) {
- // hires
+ flash_state ? 0 : 0x400,
+ 0x400,
+ 0x600
+ };
+
+ // CG ROM does inverse/flash by XORing onto the value from ROM
+ int flash_xor[4] = {0x7f, flash_state ? 0x7f : 0, 0, 0};
+
+ memset(frame, 0, WINDOW_HEIGHT * WINDOW_WIDTH * sizeof(uint32_t));
+ for (int i = 0; i < APPLE_HEIGHT; ++i) {
+ int base = (i >> 6) * 40 | ((i & 0x38) << 4);
+ int row = i & 7;
+ uint32_t buf[PADDED_WORDS];
+ memset(buf, 0, PADDED_WORDS * sizeof(uint32_t));
+
+ if (c05x_soft_switches & C05X_SOFT_SWITCH_HIRES) {
+ // hires
#if APPLE_IIE
- int line = (
- (c05x_soft_switches & C05X_SOFT_SWITCH_PAGE2) &&
- (c00x_soft_switches & C00X_SOFT_SWITCH_80COL) == 0 ?
- APPLE_HIRES2 :
- APPLE_HIRES1
- ) | base | (row << 10);
+ int line = (
+ (c05x_soft_switches & C05X_SOFT_SWITCH_PAGE2) &&
+ (c00x_soft_switches & C00X_SOFT_SWITCH_80COL) == 0 ?
+ APPLE_HIRES2 :
+ APPLE_HIRES1
+ ) | base | (row << 10);
#else
- int line = (
- (c05x_soft_switches & C05X_SOFT_SWITCH_PAGE2) ?
- APPLE_HIRES2 :
- APPLE_HIRES1
- ) | base | (row << 10);
+ int line = (
+ (c05x_soft_switches & C05X_SOFT_SWITCH_PAGE2) ?
+ APPLE_HIRES2 :
+ APPLE_HIRES1
+ ) | base | (row << 10);
#endif
#if APPLE_IIE
- if (c00x_soft_switches & C00X_SOFT_SWITCH_80VID) {
- // dhgr -- no support for SETDHIRES soft switch yet
- int aux_line = line | 0x10000;
- int l = 1; // 1 pixel delay, similar to hgr with hi-bit set
+ if (c00x_soft_switches & C00X_SOFT_SWITCH_80VID) {
+ // dhgr -- no support for SETDHIRES soft switch yet
+ int aux_line = line | 0x10000;
+ int l = 1; // 1 pixel delay, similar to hgr with hi-bit set
+ for (int j = 0; j < 40; ++j) {
+ int data = mem[aux_line + j];
+ for (int k = 0; k < 7; ++k) {
+ if (data & 1)
+ buf[l >> 5] |= 1 << (l & 0x1f);
+ ++l;
+ data >>= 1;
+ }
+ /*int*/ data = mem[line + j];
+ for (int k = 0; k < 7; ++k) {
+ if (data & 1)
+ buf[l >> 5] |= 1 << (l & 0x1f);
+ ++l;
+ data >>= 1;
+ }
+ }
+ }
+ else
+#endif
for (int j = 0; j < 40; ++j) {
- int data = mem[aux_line + j];
+ int data = mem[line + j];
+ int hibit = data >> 7;
for (int k = 0; k < 7; ++k) {
- if (data & 1)
+ if (data & 1) {
+ int l = ((j * 7 + k) << 1) + hibit;
buf[l >> 5] |= 1 << (l & 0x1f);
- ++l;
- data >>= 1;
- }
- /*int*/ data = mem[line + j];
- for (int k = 0; k < 7; ++k) {
- if (data & 1)
+ ++l;
buf[l >> 5] |= 1 << (l & 0x1f);
- ++l;
+ }
data >>= 1;
}
}
}
- else
-#endif
- for (int j = 0; j < 40; ++j) {
- int data = mem[line + j];
- int hibit = data >> 7;
- for (int k = 0; k < 7; ++k) {
- if (data & 1) {
- int l = ((j * 7 + k) << 1) + hibit;
- buf[l >> 5] |= 1 << (l & 0x1f);
- ++l;
- buf[l >> 5] |= 1 << (l & 0x1f);
- }
- data >>= 1;
- }
- }
- }
- else {
- // text or gr (only text for now)
+ else {
+ // text or gr (only text for now)
#if APPLE_IIE
- int line = (
- (c05x_soft_switches & C05X_SOFT_SWITCH_PAGE2) &&
- (c00x_soft_switches & C00X_SOFT_SWITCH_80COL) == 0 ?
- APPLE_TEXT2 :
- APPLE_TEXT1
- ) | base;
+ int line = (
+ (c05x_soft_switches & C05X_SOFT_SWITCH_PAGE2) &&
+ (c00x_soft_switches & C00X_SOFT_SWITCH_80COL) == 0 ?
+ APPLE_TEXT2 :
+ APPLE_TEXT1
+ ) | base;
#else
- int line = (
- (c05x_soft_switches & C05X_SOFT_SWITCH_PAGE2) ?
- APPLE_TEXT2 :
- APPLE_TEXT1
- ) | base;
+ int line = (
+ (c05x_soft_switches & C05X_SOFT_SWITCH_PAGE2) ?
+ APPLE_TEXT2 :
+ APPLE_TEXT1
+ ) | base;
#endif
- for (int j = 0; j < 40; ++j) {
- int glyph = mem[line + j];
- if (video_rom) { // inverted, LSB first
- int data = video_rom[
- row | ((glyph & 0x3f) << 3) | flash_base[glyph >> 6]
- ];
- for (int k = 0; k < 7; ++k) {
- if ((data & 1) == 0) {
- int l = (j * 7 + k) << 1;
- buf[l >> 5] |= 1 << (l & 0x1f);
- ++l;
- buf[l >> 5] |= 1 << (l & 0x1f);
+ for (int j = 0; j < 40; ++j) {
+ int glyph = mem[line + j];
+ if (video_rom) { // inverted, LSB first
+ int data = video_rom[
+ row | ((glyph & 0x3f) << 3) | flash_base[glyph >> 6]
+ ];
+ for (int k = 0; k < 7; ++k) {
+ if ((data & 1) == 0) {
+ int l = (j * 7 + k) << 1;
+ buf[l >> 5] |= 1 << (l & 0x1f);
+ ++l;
+ buf[l >> 5] |= 1 << (l & 0x1f);
+ }
+ data >>= 1;
}
- data >>= 1;
}
- }
- else { // MSB first
- int data = cg_rom[row | (glyph << 3)] ^ flash_xor[glyph >> 6];
- for (int k = 0; k < 7; ++k) {
- if (data & 0x40) {
- int l = (j * 7 + k) << 1;
- buf[l >> 5] |= 1 << (l & 0x1f);
- ++l;
- buf[l >> 5] |= 1 << (l & 0x1f);
+ else { // MSB first
+ int data = cg_rom[row | (glyph << 3)] ^ flash_xor[glyph >> 6];
+ for (int k = 0; k < 7; ++k) {
+ if (data & 0x40) {
+ int l = (j * 7 + k) << 1;
+ buf[l >> 5] |= 1 << (l & 0x1f);
+ ++l;
+ buf[l >> 5] |= 1 << (l & 0x1f);
+ }
+ data <<= 1;
}
- data <<= 1;
}
}
}
- }
-
- if (c05x_soft_switches & C05X_SOFT_SWITCH_TEXT) {
- // text (no colour burst)
- int x = 3 * WINDOW_X_SCALE / 2, y = i * WINDOW_Y_SCALE;
- for (int j = 0; j < APPLE_WIDTH; ++j) {
- uint32_t v = mono_palette[(buf[j >> 5] >> (j & 0x1f)) & 1];
- for (int l = 0; l < WINDOW_X_SCALE; ++l) {
- for (int m = 0; m < WINDOW_Y_SCALE; ++m)
- frame[y + m][x] = v;
- ++x;
+
+ if (c05x_soft_switches & C05X_SOFT_SWITCH_TEXT) {
+ // text (no colour burst)
+ int x = 3 * WINDOW_X_SCALE / 2, y = i * WINDOW_Y_SCALE;
+ for (int j = 0; j < APPLE_WIDTH; ++j) {
+ uint32_t v = mono_palette[(buf[j >> 5] >> (j & 0x1f)) & 1];
+ for (int l = 0; l < WINDOW_X_SCALE; ++l) {
+ for (int m = 0; m < WINDOW_Y_SCALE; ++m)
+ frame[y + m][x] = v;
+ ++x;
+ }
}
}
- }
- else {
- // hires or gr (colour burst)
- int k = 0, x = 0, y = i * WINDOW_Y_SCALE;
- for (int j = 0; j < PADDED_WIDTH; ++j) {
- int mask = 1 << (j & 3);
- k = (k & ~mask) | ((buf[j >> 5] >> (j & 0x1c)) & mask);
- uint32_t v = palette[k];
- for (int l = 0; l < WINDOW_X_SCALE; ++l) {
- for (int m = 0; m < WINDOW_Y_SCALE; ++m)
- frame[y + m][x] = v;
- ++x;
+ else {
+ // hires or gr (colour burst)
+ int k = 0, x = 0, y = i * WINDOW_Y_SCALE;
+ for (int j = 0; j < PADDED_WIDTH; ++j) {
+ int mask = 1 << (j & 3);
+ k = (k & ~mask) | ((buf[j >> 5] >> (j & 0x1c)) & mask);
+ uint32_t v = palette[k];
+ for (int l = 0; l < WINDOW_X_SCALE; ++l) {
+ for (int m = 0; m < WINDOW_Y_SCALE; ++m)
+ frame[y + m][x] = v;
+ ++x;
+ }
}
}
}
+ SDL_UpdateTexture(texture, NULL, frame, WINDOW_WIDTH * sizeof(uint32_t));
+ SDL_RenderCopy(renderer, texture, NULL, NULL);
+ SDL_RenderPresent(renderer);
+ }
+
+ // audio update
+ if (c0x0_soft_switches_buf_count >= 0x100) {
+ int queue_level = SDL_GetQueuedAudioSize(audio_device_id);
+ // queue level should not fall to 0, if it does increase SAMPLES_PER_UPDATE
+ //fprintf(stderr, "%d %d\r\n", c0x0_soft_switches_buf_count, queue_level);
+ if (queue_level < 0x400) {
+ int16_t audio_buf[0x100];
+ for (int i = 0; i < 0x100; ++i) {
+ float spkr = (
+ c0x0_soft_switches_buf[c0x0_soft_switches_buf_head] &
+ C0X0_SOFT_SWITCH_SPKR
+ ) != 0;
+ c0x0_soft_switches_buf_head =
+ (c0x0_soft_switches_buf_head + 1) &
+ (C0X0_SOFT_SWITCHES_BUF_SIZE - 1);
+ --c0x0_soft_switches_buf_count;
+
+ spkr -= spkr_rc;
+ spkr_rc += spkr * (1.f / 220.5f); // 200 Hz high pass
+ audio_buf[i] = (int16_t)roundf(spkr * 0x3fff);
+ }
+
+ if (
+ SDL_QueueAudio(
+ audio_device_id,
+ audio_buf,
+ 0x100 * sizeof(int16_t)
+ )
+ ) {
+ fprintf(stderr, "SDL_QueueAudio(): %s\n", SDL_GetError());
+ exit(EXIT_FAILURE);
+ }
+ }
}
- SDL_UpdateTexture(texture, NULL, frame, WINDOW_WIDTH * sizeof(uint32_t));
- SDL_RenderCopy(renderer, texture, NULL, NULL);
- SDL_RenderPresent(renderer);
+ // cpu update
+ if (c0x0_soft_switches_buf_count >= C0X0_SOFT_SWITCHES_BUF_SIZE) {
#if 1 // for star blazer game which doesn't do usleep
- SDL_Delay(1);
+ //fprintf(stderr, "sleep\r\n");
+ SDL_Delay(1);
#else
- if (usleep_count) {
+ if (usleep_count) {
#if 1 // hack to avoid lagginess in ribbit game
- struct pollfd fd = {fd_in, POLLIN | POLLPRI, 0};
- if (poll(&fd, 1, (usleep_count + 999) / 1000) == -1) {
- perror("poll()");
- exit(EXIT_FAILURE);
- }
+ struct pollfd fd = {fd_in, POLLIN | POLLPRI, 0};
+ if (poll(&fd, 1, (usleep_count + 999) / 1000) == -1) {
+ perror("poll()");
+ exit(EXIT_FAILURE);
+ }
#else
- usleep(usleep_count);
+ usleep(usleep_count);
#endif
- }
+ }
#endif
-
- int i, j;
+ }
+ else {
+ int i, j;
#if TRACE
- struct pc_pair pc_pair = {vrEmu6502GetPC(cpu), 0};
- for (int k = 0; k < INSTRS_PER_UPDATE; ++k) {
- i = vrEmu6502Run(cpu, 1, &j);
- nb_instructions += i;
- nb_cycles += j;
- if (i == 0)
- goto jam; //break;
-
- pc_pair.pc1 = vrEmu6502GetPC(cpu);
- bool show_trace = false;
-
- int hash = (19 * pc_pair.pc0 + 37 * pc_pair.pc1) % N_PC_PAIRS;
- for (int i = 0; i < N_PC_PAIRS; ++i) {
- if (
- pc_pairs[hash].pc0 == pc_pair.pc0 &&
- pc_pairs[hash].pc1 == pc_pair.pc1
- )
- break;
- if (
- pc_pairs[hash].pc0 == 0xffff &&
- pc_pairs[hash].pc1 == 0xffff
- ) {
- pc_pairs[hash] = pc_pair;
- show_trace = true;
- break;
+ struct pc_pair pc_pair = {vrEmu6502GetPC(cpu), 0};
+ for (int k = 0; k < CYCLES_PER_SAMPLE; k += j) {
+ i = vrEmu6502RunInstrs(cpu, 1, &j);
+ nb_instructions += i;
+ nb_cycles += j;
+ if (i == 0)
+ goto jam; //break;
+
+ pc_pair.pc1 = vrEmu6502GetPC(cpu);
+ bool show_trace = false;
+
+ int hash = (19 * pc_pair.pc0 + 37 * pc_pair.pc1) % N_PC_PAIRS;
+ for (int i = 0; i < N_PC_PAIRS; ++i) {
+ if (
+ pc_pairs[hash].pc0 == pc_pair.pc0 &&
+ pc_pairs[hash].pc1 == pc_pair.pc1
+ )
+ break;
+ if (
+ pc_pairs[hash].pc0 == 0xffff &&
+ pc_pairs[hash].pc1 == 0xffff
+ ) {
+ pc_pairs[hash] = pc_pair;
+ show_trace = true;
+ break;
+ }
+ ++hash;
+ if (hash >= N_PC_PAIRS)
+ hash = 0;
}
- ++hash;
- if (hash >= N_PC_PAIRS)
- hash = 0;
- }
- uint8_t regs[N_TRACE_REGS] = {
- vrEmu6502GetAcc(cpu),
- vrEmu6502GetX(cpu),
- vrEmu6502GetY(cpu),
- vrEmu6502GetStackPointer(cpu),
- vrEmu6502GetStatus(cpu)
- };
- for (int i = 0; i < N_TRACE_REGS; ++i) {
- if (regs[i] < trace[pc_pair.pc1][i].min_unsigned) {
- trace[pc_pair.pc1][i].min_unsigned = regs[i];
- show_trace = true;
- }
- if ((int8_t)regs[i] < trace[pc_pair.pc1][i].min_signed) {
- trace[pc_pair.pc1][i].min_signed = (int8_t)regs[i];
- show_trace = true;
- }
- if (~regs[i] & trace[pc_pair.pc1][i].min_bitwise) {
- trace[pc_pair.pc1][i].min_bitwise &= regs[i];
- show_trace = true;
- }
- if (regs[i] > trace[pc_pair.pc1][i].max_unsigned) {
- trace[pc_pair.pc1][i].max_unsigned = regs[i];
- show_trace = true;
- }
- if ((int8_t)regs[i] > trace[pc_pair.pc1][i].max_signed) {
- trace[pc_pair.pc1][i].max_signed = (int8_t)regs[i];
- show_trace = true;
- }
- if (regs[i] & ~trace[pc_pair.pc1][i].max_bitwise) {
- trace[pc_pair.pc1][i].max_bitwise |= regs[i];
- show_trace = true;
+ uint8_t regs[N_TRACE_REGS] = {
+ vrEmu6502GetAcc(cpu),
+ vrEmu6502GetX(cpu),
+ vrEmu6502GetY(cpu),
+ vrEmu6502GetStackPointer(cpu),
+ vrEmu6502GetStatus(cpu)
+ };
+ for (int i = 0; i < N_TRACE_REGS; ++i) {
+ if (regs[i] < trace[pc_pair.pc1][i].min_unsigned) {
+ trace[pc_pair.pc1][i].min_unsigned = regs[i];
+ show_trace = true;
+ }
+ if ((int8_t)regs[i] < trace[pc_pair.pc1][i].min_signed) {
+ trace[pc_pair.pc1][i].min_signed = (int8_t)regs[i];
+ show_trace = true;
+ }
+ if (~regs[i] & trace[pc_pair.pc1][i].min_bitwise) {
+ trace[pc_pair.pc1][i].min_bitwise &= regs[i];
+ show_trace = true;
+ }
+ if (regs[i] > trace[pc_pair.pc1][i].max_unsigned) {
+ trace[pc_pair.pc1][i].max_unsigned = regs[i];
+ show_trace = true;
+ }
+ if ((int8_t)regs[i] > trace[pc_pair.pc1][i].max_signed) {
+ trace[pc_pair.pc1][i].max_signed = (int8_t)regs[i];
+ show_trace = true;
+ }
+ if (regs[i] & ~trace[pc_pair.pc1][i].max_bitwise) {
+ trace[pc_pair.pc1][i].max_bitwise |= regs[i];
+ show_trace = true;
+ }
}
- }
- if (show_trace)
- fprintf(
- stderr,
- "pc=%04x,%04x a=%02x%02x%02x,%02x%02x%02x x=%02x%02x%02x,%02x%02x%02x y=%02x%02x%02x,%02x%02x%02x s=%02x%02x%02x,%02x%02x%02x p=%02x%02x%02x,%02x%02x%02x\n",
- pc_pair.pc0,
- pc_pair.pc1,
- trace[pc_pair.pc1][TRACE_REG_A].min_unsigned,
- (uint8_t)trace[pc_pair.pc1][TRACE_REG_A].min_signed,
- trace[pc_pair.pc1][TRACE_REG_A].min_bitwise,
- trace[pc_pair.pc1][TRACE_REG_A].max_unsigned,
- (uint8_t)trace[pc_pair.pc1][TRACE_REG_A].max_signed,
- trace[pc_pair.pc1][TRACE_REG_A].max_bitwise,
- trace[pc_pair.pc1][TRACE_REG_X].min_unsigned,
- (uint8_t)trace[pc_pair.pc1][TRACE_REG_X].min_signed,
- trace[pc_pair.pc1][TRACE_REG_X].min_bitwise,
- trace[pc_pair.pc1][TRACE_REG_X].max_unsigned,
- (uint8_t)trace[pc_pair.pc1][TRACE_REG_X].max_signed,
- trace[pc_pair.pc1][TRACE_REG_X].max_bitwise,
- trace[pc_pair.pc1][TRACE_REG_Y].min_unsigned,
- (uint8_t)trace[pc_pair.pc1][TRACE_REG_Y].min_signed,
- trace[pc_pair.pc1][TRACE_REG_Y].min_bitwise,
- trace[pc_pair.pc1][TRACE_REG_Y].max_unsigned,
- (uint8_t)trace[pc_pair.pc1][TRACE_REG_Y].max_signed,
- trace[pc_pair.pc1][TRACE_REG_Y].max_bitwise,
- trace[pc_pair.pc1][TRACE_REG_S].min_unsigned,
- (uint8_t)trace[pc_pair.pc1][TRACE_REG_S].min_signed,
- trace[pc_pair.pc1][TRACE_REG_S].min_bitwise,
- trace[pc_pair.pc1][TRACE_REG_S].max_unsigned,
- (uint8_t)trace[pc_pair.pc1][TRACE_REG_S].max_signed,
- trace[pc_pair.pc1][TRACE_REG_S].max_bitwise,
- trace[pc_pair.pc1][TRACE_REG_P].min_unsigned,
- (uint8_t)trace[pc_pair.pc1][TRACE_REG_P].min_signed,
- trace[pc_pair.pc1][TRACE_REG_P].min_bitwise,
- trace[pc_pair.pc1][TRACE_REG_P].max_unsigned,
- (uint8_t)trace[pc_pair.pc1][TRACE_REG_P].max_signed,
- trace[pc_pair.pc1][TRACE_REG_P].max_bitwise
- );
- pc_pair.pc0 = pc_pair.pc1;
- }
+ if (show_trace)
+ fprintf(
+ stderr,
+ "pc=%04x,%04x a=%02x%02x%02x,%02x%02x%02x x=%02x%02x%02x,%02x%02x%02x y=%02x%02x%02x,%02x%02x%02x s=%02x%02x%02x,%02x%02x%02x p=%02x%02x%02x,%02x%02x%02x\n",
+ pc_pair.pc0,
+ pc_pair.pc1,
+ trace[pc_pair.pc1][TRACE_REG_A].min_unsigned,
+ (uint8_t)trace[pc_pair.pc1][TRACE_REG_A].min_signed,
+ trace[pc_pair.pc1][TRACE_REG_A].min_bitwise,
+ trace[pc_pair.pc1][TRACE_REG_A].max_unsigned,
+ (uint8_t)trace[pc_pair.pc1][TRACE_REG_A].max_signed,
+ trace[pc_pair.pc1][TRACE_REG_A].max_bitwise,
+ trace[pc_pair.pc1][TRACE_REG_X].min_unsigned,
+ (uint8_t)trace[pc_pair.pc1][TRACE_REG_X].min_signed,
+ trace[pc_pair.pc1][TRACE_REG_X].min_bitwise,
+ trace[pc_pair.pc1][TRACE_REG_X].max_unsigned,
+ (uint8_t)trace[pc_pair.pc1][TRACE_REG_X].max_signed,
+ trace[pc_pair.pc1][TRACE_REG_X].max_bitwise,
+ trace[pc_pair.pc1][TRACE_REG_Y].min_unsigned,
+ (uint8_t)trace[pc_pair.pc1][TRACE_REG_Y].min_signed,
+ trace[pc_pair.pc1][TRACE_REG_Y].min_bitwise,
+ trace[pc_pair.pc1][TRACE_REG_Y].max_unsigned,
+ (uint8_t)trace[pc_pair.pc1][TRACE_REG_Y].max_signed,
+ trace[pc_pair.pc1][TRACE_REG_Y].max_bitwise,
+ trace[pc_pair.pc1][TRACE_REG_S].min_unsigned,
+ (uint8_t)trace[pc_pair.pc1][TRACE_REG_S].min_signed,
+ trace[pc_pair.pc1][TRACE_REG_S].min_bitwise,
+ trace[pc_pair.pc1][TRACE_REG_S].max_unsigned,
+ (uint8_t)trace[pc_pair.pc1][TRACE_REG_S].max_signed,
+ trace[pc_pair.pc1][TRACE_REG_S].max_bitwise,
+ trace[pc_pair.pc1][TRACE_REG_P].min_unsigned,
+ (uint8_t)trace[pc_pair.pc1][TRACE_REG_P].min_signed,
+ trace[pc_pair.pc1][TRACE_REG_P].min_bitwise,
+ trace[pc_pair.pc1][TRACE_REG_P].max_unsigned,
+ (uint8_t)trace[pc_pair.pc1][TRACE_REG_P].max_signed,
+ trace[pc_pair.pc1][TRACE_REG_P].max_bitwise
+ );
+ pc_pair.pc0 = pc_pair.pc1;
+ }
jam:
#else
- i = vrEmu6502Run(cpu, INSTRS_PER_UPDATE, &j);
- nb_instructions += i;
- nb_cycles += j;
- //if (i < INSTRS_PER_UPDATE)
- // break;
+ i = vrEmu6502RunCycles(cpu, CYCLES_PER_SAMPLE, &j);
+ nb_instructions += i;
+ nb_cycles += j;
+ //if (j < CYCLES_PER_UPDATE)
+ // break;
#endif
- if (exit_flag)
- break;
- vrEmu6502Unjam(cpu);
+ if (exit_flag)
+ break;
+ vrEmu6502Unjam(cpu);
+
+ // sample tape and speaker outputs at CYCLES_PER_SAMPLE rate
+#if 0
+ if (c0x0_soft_switches_buf_count >= C0X0_SOFT_SWITCHES_BUF_SIZE) {
+ // buffer full, drop oldest sample
+ c0x0_soft_switches_buf_head =
+ (c0x0_soft_switches_buf_head + 1) &
+ (C0X0_SOFT_SWITCHES_BUF_SIZE - 1);
+ --c0x0_soft_switches_buf_count;
+ }
+#endif
+ c0x0_soft_switches_buf[
+ (c0x0_soft_switches_buf_head + c0x0_soft_switches_buf_count++) &
+ (C0X0_SOFT_SWITCHES_BUF_SIZE - 1)
+ ] = c0x0_soft_switches;
+ }
}
quit:
vrEmu6502Destroy(cpu);
+ SDL_CloseAudioDevice(audio_device_id);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();