Skip to content

Implement the zp,x version of BIT that's present on 65C02s #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
4 changes: 3 additions & 1 deletion src/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ cpu * new_cpu() {
m->l = new_lcd();
m->k = new_keys();
m->cycle = 0;
m->run_to_nop = false;
m->run_to_ret = 0;
return m;
}

Expand All @@ -26,4 +28,4 @@ void destroy_cpu(cpu* m) {
destroy_lcd(m->l);
destroy_keys(m->k);
free(m);
}
}
13 changes: 10 additions & 3 deletions src/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@
#define EMU_FLAG_WAIT_FOR_INTERRUPT 0x02

#define CLOCK_SPRINT 0x00
#define CLOCK_FAST 0x01
#define CLOCK_SLOW 0x02
#define CLOCK_STEP 0x04
#define CLOCK_TURBO 0x01
#define CLOCK_FAST 0x02
#define CLOCK_SLOW 0x04
#define CLOCK_STEP 0x08

typedef struct {
// clock mode
Expand Down Expand Up @@ -65,6 +66,12 @@ typedef struct {
lcd* l;
// keys
keys* k;
// whether we should switch to clock mode STEP when the next NOP is encountered
bool run_to_nop;
// if >0, will be incremented/decremented when encountering JSR/RTS respectively and we'll switch to
// STEP when it's decremented to zero, allowing "run until return"
int run_to_ret;

} cpu;

cpu * new_cpu();
Expand Down
51 changes: 49 additions & 2 deletions src/gui.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,21 @@ void update_gui(cpu *m) {

// start by populating the monitor
mvwprintw(wnd_monitor_content, 0, 0, "PC: %04x, OP: %02x (%s)", m->pc_actual, m->opcode, translate_opcode(m->opcode));
if (m->run_to_nop && m->opcode == 0xea) {
// 0xea is NOP - we use this as a breakpoint
m->clock_mode = CLOCK_STEP;
m->run_to_nop = false;
} else if (m->run_to_ret && m->opcode == 0x60) {
// 0x60 is RTS
m->run_to_ret--;
if (!m->run_to_ret) {
// We're returning from the frame where run-to-ret was requested
m->clock_mode = CLOCK_STEP;
}
} else if (m->run_to_ret && m->opcode == 0x20) {
// 0x20 is JSR. We want to see an additional return after this, then.
m->run_to_ret++;
}
mvwprintw(wnd_monitor_content, 1, 0, "ACC: %02x, X: %02x, Y: %02x, SP: %02x", m->ac, m->x, m->y, m->sp);
mvwprintw(wnd_monitor_content, 2, 0, "SR: %c%c-%c%c%c%c%c, cycle: %08x",
m->sr & 0x80 ? 'N' : '-',
Expand All @@ -180,7 +195,17 @@ void update_gui(cpu *m) {
m->sr & 0x02 ? 'Z' : '-',
m->sr & 0x01 ? 'C' : '-',
m->cycle);
mvwprintw(wnd_monitor_content, 3, 0, "Clock mode: %s", m->clock_mode == CLOCK_FAST ? "FAST" : m->clock_mode == CLOCK_SLOW ? "SLOW" : "STEP");
mvwprintw(wnd_monitor_content, 3, 0, "Clock mode: %s", m->clock_mode == CLOCK_TURBO ? "TURBO" : m->clock_mode == CLOCK_FAST ? "FAST " : m->clock_mode == CLOCK_SLOW ? "SLOW " : "STEP ");
if (m->run_to_nop) {
mvwprintw(wnd_monitor_content, 3, 18, "RTN");
} else {
mvwprintw(wnd_monitor_content, 3, 18, " ");
}
if (m->run_to_ret) {
mvwprintw(wnd_monitor_content, 3, 22, "RTR %d", m->run_to_ret);
} else {
mvwprintw(wnd_monitor_content, 3, 22, " ");
}
wrefresh(wnd_monitor_content);

// populate memory monitor
Expand Down Expand Up @@ -224,6 +249,11 @@ void update_gui(cpu *m) {

switch (m->clock_mode) {
case CLOCK_SPRINT:
case CLOCK_TURBO:
cbreak();
read = getch();
keep_going = true;
break;
case CLOCK_FAST:
halfdelay(1);
read = getch();
Expand Down Expand Up @@ -260,6 +290,11 @@ void update_gui(cpu *m) {
m->clock_mode = CLOCK_FAST;
}
break;
case KEY_F(9): // F9
if (!(m->clock_mode == CLOCK_SPRINT)) {
m->clock_mode = CLOCK_TURBO;
}
break;
case 10:
m->k->key_enter = true;
keep_going = true;
Expand Down Expand Up @@ -304,7 +339,19 @@ void update_gui(cpu *m) {
memory_start = 0xfe;
}
break;
case 'n':
if (!(m->clock_mode == CLOCK_SPRINT)) {
m->clock_mode = CLOCK_TURBO;
m->run_to_nop = true;
}
break;
case 'r':
if (!(m->clock_mode == CLOCK_SPRINT)) {
m->clock_mode = CLOCK_TURBO;
m->run_to_ret = 1;
}
break;
}
}
} while (!keep_going && m->clock_mode != CLOCK_SPRINT);
}
}
5 changes: 5 additions & 0 deletions src/lcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ void process_input(lcd* l, bool enable, bool rwb, bool data, uint8_t input)
if (enable && !l->enable_latch) { // rising edge on enable
l->enable_latch = true;
trace_emu("LCD rising edge on enable\n");
if (rwb && !data) {
// There's no command to check - this is read busy flag
trace_emu("LCD read busy\n");
process_command(l, rwb, l->data);
}
if (!l->initialized && !(input & 0xc0) && (input & CMD_FUNCTION_SET) && !rwb) {
trace_emu("LCD initializing \n");
l->initialized = true;
Expand Down
7 changes: 7 additions & 0 deletions src/opcode_handlers/logical.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,13 @@ case BIT_ZP:
set_flag(m, FLAG_NEGATIVE, t1 & 0x80);
break;

case BIT_ZPX:
t1 = read_byte(m, ZP(NEXT_BYTE(m) + m->x)); //m->mem[ZP(NEXT_BYTE(m) + m->x)];
set_flag(m, FLAG_ZERO, !(t1 & m->ac));
set_flag(m, FLAG_OVERFLOW, t1 & 0x40);
set_flag(m, FLAG_NEGATIVE, t1 & 0x80);
break;

case RMB0:
r1 = ZP(NEXT_BYTE(m));
//m->mem[r1] &= ~0x01;
Expand Down
2 changes: 1 addition & 1 deletion src/opcode_handlers/store.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ case STA_INZP:

case STX_ZP:
r1 = ZP(NEXT_BYTE(m));
write_byte(m, r1, m->ac); //m->mem[r1] = m->x;
write_byte(m, r1, m->x); //m->mem[r1] = m->x;
mark_dirty(m, r1);
break;

Expand Down
1 change: 1 addition & 0 deletions src/opcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@

#define BIT_AB 0x2C
#define BIT_ZP 0x24
#define BIT_ZPX 0x34

#define BMI_REL 0x30
#define BNE_REL 0xD0
Expand Down