summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2020-12-05 20:25:38 +0100
committerAndreas Baumann <mail@andreasbaumann.cc>2020-12-05 20:25:38 +0100
commit655ee84ba2304b2fe85b28290580338d29a68c3c (patch)
treefaf435242895bd75affdf206dd1c7538e85b3d0d
parentc40499b83f238de9b1a88a080261546149784586 (diff)
download6502-655ee84ba2304b2fe85b28290580338d29a68c3c.tar.gz
6502-655ee84ba2304b2fe85b28290580338d29a68c3c.tar.bz2
- have some emulation modes for single stepping, breaking, changing emulation speed
- started to make a better CPU state output with opcode mnemonics
-rw-r--r--README3
-rw-r--r--emu/6502.c63
-rw-r--r--emu/6502.h11
-rw-r--r--emu/emu.c4
-rw-r--r--emu/emul.c55
-rw-r--r--emu/emul.h2
-rw-r--r--emu/options.ggo6
-rw-r--r--emu/options.ggo.in6
8 files changed, 133 insertions, 17 deletions
diff --git a/README b/README
index da96843..29cf2cf 100644
--- a/README
+++ b/README
@@ -121,6 +121,9 @@ devices (ROM, RAM, VIA) to the bus
29.11.2020
work on 7-segment display in emulator
+5.12.2020
+work on emulator (disassembly and single-stepping)
+
commands
--------
diff --git a/emu/6502.c b/emu/6502.c
index 877f3f5..c52373f 100644
--- a/emu/6502.c
+++ b/emu/6502.c
@@ -150,10 +150,62 @@ static bool is_carry( cpu_6502_t *cpu )
{
return cpu->PS & PS_C;
}
+
+static const char mnemonic[NOF_OPCODES][MAX_MENMONIC_LENGTH] = {
+ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+ /* 0 */ "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???",
+ /* 1 */ "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???",
+ /* 2 */ "JSR", "???", "???", "???", "???", "???", "???", "???", "???", "???", "ROL", "???", "???", "???", "???", "???",
+ /* 3 */ "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???",
+ /* 4 */ "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "JMP", "???", "???", "???",
+ /* 5 */ "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???",
+ /* 6 */ "RTS", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???",
+ /* 7 */ "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???",
+ /* 8 */ "???", "???", "???", "???", "???", "???", "STX", "???", "DEY", "???", "???", "???", "???", "???", "STX", "???",
+ /* 9 */ "BCC", "???", "???", "???", "???", "???", "???", "???", "???", "???", "TXS", "???", "???", "???", "???", "???",
+ /* A */ "LDY", "???", "LDX", "???", "LDY", "LDA", "LDX", "???", "???", "LDA", "???", "???", "???", "???", "???", "???",
+ /* B */ "BCS", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???",
+ /* C */ "???", "???", "???", "???", "???", "???", "???", "???", "INY", "???", "DEX", "???", "???", "???", "???", "???",
+ /* D */ "BNE", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???",
+ /* E */ "CPX", "???", "???", "???", "???", "???", "INC", "???", "???", "SBC", "NOP", "???", "???", "???", "???", "???",
+ /* F */ "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???"
+
+/*
+ "BRK", "ORA", "" , "", "TSB", "ORA", "ASL", "RMB0", "PHP", "ORA", "ASL", "" , "TSB", "ORA", "ASL", "BBR0",
+ "BPL", "ORA", "ORA", "", "TRB", "ORA", "ASL", "RMB1", "CLC", "ORA", "INC", "" , "TRB", "ORA", "ASL", "BBR1",
+ "JSR", "AND", "" , "", "BIT", "AND", "ROL", "RMB2", "PLP", "AND", "ROL", "" , "BIT", "AND", "ROL", "BBR2",
+ "BMI", "AND", "AND", "", "BIT", "AND", "ROL", "RMB3", "SEC", "AND", "DEC", "" , "BIT", "AND", "ROL", "BBR3",
+ "RTI", "EOR", "" , "", "" , "EOR", "LSR", "RMB4", "PHA", "EOR", "LSR", "" , "JMP", "EOR", "LSR", "BBR4",
+ "BVC", "EOR", "EOR", "", "" , "EOR", "LSR", "RMB5", "CLI", "EOR", "PHY", "" , "" , "EOR", "LSR", "BBR5",
+ "RTS", "ADC", "" , "", "STZ", "ADC", "ROR", "RMB6", "PLA", "ADC", "ROR", "" , "JMP", "ADC", "ROR", "BBR6",
+ "BVS", "ADC", "ADC", "", "STZ", "ADC", "ROR", "RMB7", "SEI", "ADC", "PLY", "" , "JMP", "ADC", "ROR", "BBR7",
+ "BRA", "STA", "" , "", "STY", "STA", "STX", "SMB0", "DEY", "BIT", "TXA", "" , "STY", "STA", "STX", "BBS0",
+ "BCC", "STA", "STA", "", "STY", "STA", "STX", "SMB1", "TYA", "STA", "TXS", "" , "STZ", "STA", "STZ", "BBS1",
+ "LDY", "LDA", "LDX", "", "LDY", "LDA", "LDX", "SMB2", "TAY", "LDA", "TAX", "" , "LDY", "LDA", "LDX", "BBS2",
+ "BCS", "LDA", "LDA", "", "LDY", "LDA", "LDX", "SMB3", "CLV", "LDA", "TSX", "" , "LDY", "LDA", "LDX", "BBS3",
+ "CPY", "CMP", "" , "", "CPY", "CMP", "DEC", "SMB4", "INY", "CMP", "DEX", "WAI", "CPY", "CMP", "DEC", "BBS4",
+ "BNE", "CMP", "CMP", "", "" , "CMP", "DEC", "SMB5", "CLD", "CMP", "PHX", "STP", "" , "CMP", "DEC", "BBS5",
+ "CPX", "SBC", "" , "", "CPX", "SBC", "INC", "SMB6", "INX", "SBC", "NOP", "" , "CPX", "SBC", "INC", "BBS6",
+ "BEQ", "SBC", "SBC", "", "" , "SBC", "INC", "SMB7", "SED", "SBC", "PLX", "" , "" , "SBC", "INC", "BBS7"
+*/
+};
+
+void cpu_6502_get_opcode_mnemonic( cpu_6502_t *cpu, char *buf, int buflen, uint16_t addr )
+{
+ uint8_t opcode;
+
+ opcode = cpu_6502_read_byte( cpu, addr );
-void cpu_6502_print_state( cpu_6502_t *cpu, uint8_t opcode )
+ snprintf( buf, buflen, "%s (%02X)", mnemonic[opcode], opcode );
+}
+
+void cpu_6502_print_state( cpu_6502_t *cpu, uint16_t addr )
{
- fprintf( stderr, "PC: %04X SP: 01%02X PS: %02X %c%c-%c%c%c%c%c A: %02X X: %02X Y: %02X OP: %02X steps: %d\n",
+ char opcode_str[MAX_OPCODE_MNEMONIC_STRING_LENGTH];
+
+ cpu_6502_get_opcode_mnemonic( cpu, opcode_str, MAX_OPCODE_MNEMONIC_STRING_LENGTH, addr );
+
+ fprintf( stderr, "PC: %04X SP: 01%02X PS: %02X %c%c-%c%c%c%c%c A: %02X X: %02X Y: %02X steps: %d OP: %s\n",
cpu->PC, cpu->SP, cpu->PS,
is_negative( cpu ) ? 'N' : 'n',
is_overflow( cpu ) ? 'V' : 'v',
@@ -162,7 +214,8 @@ void cpu_6502_print_state( cpu_6502_t *cpu, uint8_t opcode )
is_interrupt( cpu ) ? 'I' : 'i',
is_zero( cpu ) ? 'Z' : 'z',
is_carry( cpu ) ? 'C' : 'c',
- cpu->A, cpu->X, cpu->Y, opcode, cpu->steps );
+ cpu->A, cpu->X, cpu->Y, cpu->steps,
+ opcode_str );
}
static void update_negative_and_sign( cpu_6502_t *cpu, uint8_t x )
@@ -200,7 +253,7 @@ void cpu_6502_step( cpu_6502_t *cpu )
cpu->PC++;
if( cpu->debug_flags & DEBUG_STATUS ) {
- cpu_6502_print_state( cpu, opcode );
+ cpu_6502_print_state( cpu, cpu->PC-1 );
}
if( cpu->debug_flags & DEBUG_STACK ) {
cpu_6502_print_stack( cpu );
@@ -279,7 +332,7 @@ void cpu_6502_step( cpu_6502_t *cpu )
update_negative_and_sign( cpu, cpu->Y );
break;
- case INC_IMPL:
+ case INC_ZERO:
operand8 = cpu_6502_read_byte( cpu, cpu->PC );
cpu->PC++;
tmp = cpu_6502_read_byte( cpu, operand8 );
diff --git a/emu/6502.h b/emu/6502.h
index bfc8314..1880c90 100644
--- a/emu/6502.h
+++ b/emu/6502.h
@@ -53,7 +53,7 @@ enum {
DEX_IMPL = 0xCA,
DEY_IMPL = 0x88,
INY_IMPL = 0xC8,
- INC_IMPL = 0xE6,
+ INC_ZERO = 0xE6,
ROL_ACC = 0x2A,
BNE_REL = 0xD0,
BCC_REL = 0x90,
@@ -67,6 +67,12 @@ enum {
NOP_IMPL = 0xEA
};
+enum {
+ MAX_OPCODE_MNEMONIC_STRING_LENGTH = 20,
+ MAX_MENMONIC_LENGTH = 5,
+ NOF_OPCODES = 256
+};
+
void cpu_6502_init( cpu_6502_t *cpu, bus_t *bus, bool initialize );
void cpu_6502_reset( cpu_6502_t *cpu );
uint8_t cpu_6502_read_byte( cpu_6502_t *cpu, uint16_t addr );
@@ -78,7 +84,8 @@ uint8_t cpu_6502_pop_byte( cpu_6502_t *cpu );
uint16_t cpu_6502_pop_word( cpu_6502_t *cpu );
void cpu_6502_run( cpu_6502_t *cpu, int steps );
void cpu_6502_step( cpu_6502_t *cpu );
-void cpu_6502_print_state( cpu_6502_t *cpu, uint8_t opcode );
+void cpu_6502_get_opcode_mnemonic( cpu_6502_t *cpu, char *buf, int buflen, uint16_t addr );
+void cpu_6502_print_state( cpu_6502_t *cpu, uint16_t addr );
void cpu_6502_print_memory( cpu_6502_t *cpu, uint16_t base, uint8_t size );
void cpu_6502_print_stack( cpu_6502_t *cpu );
void cpu_6502_print_zerop_page( cpu_6502_t *cpu );
diff --git a/emu/emu.c b/emu/emu.c
index 539c89b..421d4cc 100644
--- a/emu/emu.c
+++ b/emu/emu.c
@@ -73,6 +73,10 @@ int main( int argc, char *argv[] )
if( args_info.debug_given ) {
emul.debug = true;
}
+ if( args_info.start_paused_given ) {
+ emul.paused = true;
+ emul.speed = 25;
+ }
emul_start( &emul );
cpu_6502_reset( &cpu );
diff --git a/emu/emul.c b/emu/emul.c
index bf64d13..0399d33 100644
--- a/emu/emul.c
+++ b/emu/emul.c
@@ -11,6 +11,8 @@ void emul_init( emul_t *emul, cpu_6502_t *cpu, bus_t *bus, int width, int height
emul->width = width;
emul->height = height;
emul->debug = false;
+ emul->paused = false;
+ emul->speed = CPU_FREQUENCY;
}
void emul_start( emul_t *emul )
@@ -78,31 +80,68 @@ void emul_run( emul_t *emul, int nof_steps )
if( emul->gui ) {
SDL_Event event;
bool done = false;
+
+ if( emul->paused ) {
+ fprintf( stderr, "CPU is paused, press\n"
+ "(s) for single step\n"
+ "(c) for continue running\n"
+ "(b) break to single stepping\n"
+ "(+) speed up\n"
+ "(-) speed down\n"
+ "(q) or (ESC) for shutting down\n" );
+ }
+
while( !done ) {
uint32_t frame_start = SDL_GetTicks( );
-
+
SDL_PollEvent( &event );
switch( event.type ) {
case SDL_KEYDOWN:
switch( event.key.keysym.sym ) {
case SDLK_ESCAPE:
+ case SDLK_q:
done = true;
break;
+ case SDLK_c:
+ fprintf( stderr, "continuing at normal speed %1.6f MHz\n", ( (double)emul->speed / 1000000 ) );
+ emul->paused = false;
+ break;
+ case SDLK_b:
+ fprintf( stderr, "CPU paused (in single step mode)\n" );
+ emul->paused = true;
+ break;
+ case SDLK_s:
+ cpu_6502_run( emul->cpu, 1 );
+ break;
+ case SDLK_PLUS:
+ case SDLK_KP_PLUS:
+ emul->speed *= 10;
+ if( emul->speed > CPU_FREQUENCY ) {
+ emul->speed = CPU_FREQUENCY;
+ }
+ fprintf( stderr, "CPU speed is %1.6f MHz now\n", ( (double)emul->speed / 1000000 ) );
+ break;
+ case SDLK_MINUS:
+ case SDLK_KP_MINUS:
+ emul->speed /= 10;
+ if( emul->speed < 25 ) {
+ emul->speed = 25;
+ }
+ fprintf( stderr, "CPU speed is %1.6f MHz now\n", ( (double)emul->speed / 1000000 ) );
+ break;
}
break;
-
+
case SDL_QUIT:
done = true;
- break;
+ break;
}
- cpu_6502_run( emul->cpu, CPU_FREQUENCY / DISPLAY_FPS );
-
- if( emul->debug ) {
- cpu_6502_print_state( emul->cpu, 0 );
+ if( !emul->paused ) {
+ cpu_6502_run( emul->cpu, emul->speed / DISPLAY_FPS );
}
-
+
SDL_RenderCopy( emul->renderer, emul->background_texture, NULL, NULL );
for( int i = 0; i < emul->bus->nof_devices; i++ ) {
diff --git a/emu/emul.h b/emu/emul.h
index a0e6b5f..fa443a0 100644
--- a/emu/emul.h
+++ b/emu/emul.h
@@ -34,6 +34,8 @@ typedef struct emul_t {
int width;
int height;
bool debug;
+ bool paused;
+ int speed;
#ifdef WITH_GUI
SDL_Window *window;
SDL_Renderer *renderer;
diff --git a/emu/options.ggo b/emu/options.ggo
index 5a93897..90bb5c1 100644
--- a/emu/options.ggo
+++ b/emu/options.ggo
@@ -51,7 +51,7 @@ section "Debug Options"
option "print-7seg" -
"Print what the 7-segment display on the VIA is doing"
optional
-
+
section "GUI Options"
option "width" -
@@ -65,3 +65,7 @@ section "GUI Options"
int typestr="pixel"
default="250"
optional
+
+ option "start-paused" -
+ "Start the CPU in paused mode"
+ optional
diff --git a/emu/options.ggo.in b/emu/options.ggo.in
index 9e54009..ccec63e 100644
--- a/emu/options.ggo.in
+++ b/emu/options.ggo.in
@@ -51,7 +51,7 @@ section "Debug Options"
option "print-7seg" -
"Print what the 7-segment display on the VIA is doing"
optional
-
+
section "GUI Options"
option "width" -
@@ -65,3 +65,7 @@ section "GUI Options"
int typestr="pixel"
default="250"
optional
+
+ option "start-paused" -
+ "Start the CPU in paused mode"
+ optional