summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2020-11-26 19:55:02 +0100
committerAndreas Baumann <mail@andreasbaumann.cc>2020-11-26 19:55:02 +0100
commit3d77f3f5ad41e931117425f58c74f49c9503bf7b (patch)
tree8165c8f10a1b3b3cec27cfb283ee218e7af3a519
parent394c9fbb6cc243e46b32aa9e7221b0e6cadd4c13 (diff)
download6502-3d77f3f5ad41e931117425f58c74f49c9503bf7b.tar.gz
6502-3d77f3f5ad41e931117425f58c74f49c9503bf7b.tar.bz2
more work on emulator, mainly debug and 7seg stuff
-rw-r--r--README4
-rw-r--r--emu/6502.c20
-rw-r--r--emu/6502.h11
-rw-r--r--emu/7seg.c43
-rw-r--r--emu/7seg.h38
-rw-r--r--emu/README3
-rw-r--r--emu/emu.c39
-rw-r--r--emu/emul.c17
-rw-r--r--emu/emul.h6
-rw-r--r--emu/memory.c40
-rw-r--r--emu/memory.h6
-rw-r--r--emu/options.ggo63
-rw-r--r--emu/options.ggo.in45
13 files changed, 300 insertions, 35 deletions
diff --git a/README b/README
index cce7efd..3ed34eb 100644
--- a/README
+++ b/README
@@ -70,7 +70,6 @@ address lines on RAM (again!), IRQ on VIA has to be acknowledged,
otherwise it triggers constantly (so the counter seems to stop).
playing with delays to make counter work correctly (somewhat).
-
8.11.2020:
using via timer1 for 10ms ticks, time counter increment instead of delay
weird issue with TICK on $1 and COUNTER on $0, works fine with TICK $10,
@@ -111,6 +110,9 @@ more work on emulator
25.11.2020:
more work on emulator
+26.11.2020:
+more work on emulator
+
commands
--------
diff --git a/emu/6502.c b/emu/6502.c
index 5baaf32..ce1f0d3 100644
--- a/emu/6502.c
+++ b/emu/6502.c
@@ -11,7 +11,7 @@ static const uint16_t SP_base = 0x100;
void cpu_6502_init( cpu_6502_t *cpu, struct memory_t *memory )
{
cpu->memory = memory;
- cpu->debug = false;
+ cpu->debug_flags = 0;
}
uint16_t cpu_6502_read_word( cpu_6502_t *cpu, uint16_t addr )
@@ -78,8 +78,14 @@ void cpu_6502_write_word( cpu_6502_t *cpu, uint16_t addr, uint16_t data )
void cpu_6502_run( cpu_6502_t *cpu, int steps )
{
- for( int i = 0; i < steps; i++ ) {
- cpu_6502_step( cpu );
+ if( steps != -1 ) {
+ for( int i = 0; i < steps; i++ ) {
+ cpu_6502_step( cpu );
+ }
+ } else {
+ while( true ) {
+ cpu_6502_step( cpu );
+ }
}
}
@@ -184,9 +190,13 @@ void cpu_6502_step( cpu_6502_t *cpu )
opcode = cpu_6502_read_byte( cpu, cpu->PC );
cpu->PC++;
- if( cpu->debug ) {
+ if( cpu->debug_flags & DEBUG_STATUS ) {
cpu_6502_print_state( cpu, opcode );
+ }
+ if( cpu->debug_flags & DEBUG_STACK ) {
cpu_6502_print_stack( cpu );
+ }
+ if( cpu->debug_flags & DEBUG_ZERO_PAGE ) {
cpu_6502_print_zerop_page( cpu );
}
@@ -236,7 +246,7 @@ void cpu_6502_step( cpu_6502_t *cpu )
case STX_ABS:
operand16 = cpu_6502_read_word( cpu, cpu->PC );
cpu->PC += 2;
- cpu_6502_write_word( cpu, operand16, cpu->X );
+ cpu_6502_write_byte( cpu, operand16, cpu->X );
break;
case DEY_IMPL:
diff --git a/emu/6502.h b/emu/6502.h
index dac07a1..20574c3 100644
--- a/emu/6502.h
+++ b/emu/6502.h
@@ -15,11 +15,19 @@ typedef struct
struct memory_t *memory;
- bool debug;
+ int debug_flags;
int steps;
} cpu_6502_t;
+// debug flags
+enum {
+ DEBUG_STATUS = 0x01,
+ DEBUG_ZERO_PAGE = 0x02,
+ DEBUG_STACK = 0x04
+};
+
+// processor state bits
enum {
PS_N = 0x80,
PS_V = 0x40,
@@ -30,6 +38,7 @@ enum {
PS_C = 0x01
};
+// opcodes
enum {
LDX_IMM = 0xA2,
LDX_ZERO = 0xA6,
diff --git a/emu/7seg.c b/emu/7seg.c
index e69de29..1aaf5f9 100644
--- a/emu/7seg.c
+++ b/emu/7seg.c
@@ -0,0 +1,43 @@
+#include "7seg.h"
+
+#include <stdio.h>
+
+void seg7_init( seg7_t *seg )
+{
+ seg->debug = false;
+}
+
+uint8_t seg7_read( seg7_t *seg, uint16_t addr )
+{
+ return 0;
+}
+
+void seg7_write( seg7_t *seg, uint16_t addr, uint8_t data )
+{
+ switch( addr ) {
+ case DDRA:
+ seg->ddr = data;
+ break;
+
+ case PORTA:
+ // write bits from SER into shift register on positive SRCLK
+ if( ( seg->ddr | ( SRCLK & SER ) ) && ( data & SRCLK ) ) {
+ seg->shift = ( seg->shift << 1 ) | ( data & SER );
+ if( seg->debug ) {
+ fprintf( stderr, "7seg shifting data, data is now %02X\n", seg->shift );
+ }
+ }
+
+ // copy shift to latch register on positive RCLK
+ if( ( seg->ddr | RCLK ) && ( data & RCLK ) ) {
+ seg->latch = seg->shift;
+ if( seg->debug ) {
+ fprintf( stderr, "7seg copying %02X from shift to latch\n", seg->latch );
+ }
+ }
+
+ break;
+
+ // ignore writes to other addresses
+ }
+}
diff --git a/emu/7seg.h b/emu/7seg.h
index c49a8a1..0cd585f 100644
--- a/emu/7seg.h
+++ b/emu/7seg.h
@@ -1,12 +1,42 @@
-#ifndef 7_SEG_H
-#define 7_SEG_H
+#ifndef SEG7_H
+#define SEG7_H
#ifdef WITH_GUI
#include <SDL.h>
#endif
-typedef struct 7seg_t
+#include <stdint.h>
+#include <stdbool.h>
+
+// VIA connected on PORTA to 3 wires leading to the 3 coupled 74HC595
+// shift register which enable the ROM address lines to read the LED
+// segment data (cells 0-15 contain the encoded 7 segments of 16 hexdigits)
+//
+// PORTA connected as follows:
+// xxxxx111
+// +--- SER
+// +---- RCLK
+// +----- SRCLK
+enum {
+ PORTA = 0x6001,
+ DDRA = 0x6003,
+
+ SER = 0x01,
+ RCLK = 0x02,
+ SRCLK = 0x04
+};
+
+typedef struct seg7_t
{
-} 7seg_t;
+ uint8_t ddr;
+ uint16_t shift;
+ uint16_t latch;
+
+ bool debug;
+} seg7_t;
+
+void seg7_init( seg7_t *seg );
+uint8_t seg7_read( seg7_t *seg, uint16_t addr );
+void seg7_write( seg7_t *seg, uint16_t addr, uint8_t data );
#endif
diff --git a/emu/README b/emu/README
index fc23a5d..37ccacb 100644
--- a/emu/README
+++ b/emu/README
@@ -1,4 +1,5 @@
emulator for homebrew 6502 based on ben eater ben6502
-gcc -DWITH_GUI -I/usr/include/SDL2 -lSDL2 -g -Wall -Os -o emu emu.c 6502.c memory.c emul.c
+cmake .
+make
diff --git a/emu/emu.c b/emu/emu.c
index 7c8f041..2723880 100644
--- a/emu/emu.c
+++ b/emu/emu.c
@@ -1,6 +1,7 @@
#include "emul.h"
#include "6502.h"
#include "memory.h"
+#include "7seg.h"
#include <stdlib.h>
@@ -24,6 +25,7 @@ int main( int argc, char *argv[] )
emul_t emul;
cpu_6502_t cpu;
memory_t memory;
+ seg7_t seg7;
if( parse_options_and_arguments( argc, argv, &args_info ) != 0 ) {
exit( EXIT_FAILURE );
@@ -33,19 +35,40 @@ int main( int argc, char *argv[] )
printf( "emu version: %s, Copyright (c) 2020, LGPLv3, Andreas Baumann <mail at andreasbaumann dot cc>\n", EMU_VERSION );
exit( EXIT_SUCCESS );
}
+
+ seg7_init( &seg7 );
+
+ memory_init( &memory, &seg7 );
+ memory_load( &memory, ROM_START, ROM_SIZE, args_info.rom_arg );
- memory_init( &memory );
- memory_load( &memory, ROM_START, ROM_SIZE, "./rom.bin" );
-
cpu_6502_init( &cpu, &memory );
- //cpu.debug = true;
+ if( args_info.debug_given ) {
+ if( args_info.print_cpu_given ) {
+ cpu.debug_flags |= DEBUG_STATUS;
+ }
+ if( args_info.print_zero_page_given ) {
+ cpu.debug_flags |= DEBUG_ZERO_PAGE;
+ }
+ if( args_info.print_stack_given ) {
+ cpu.debug_flags |= DEBUG_STACK;
+ }
+ if( args_info.print_7seg_given ) {
+ seg7.debug = true;
+ }
+ }
cpu_6502_reset( &cpu );
-
- emul_init( &emul, &cpu, &memory );
- emul.gui = true;
+
+ emul_init( &emul, &cpu, &memory, args_info.width_arg, args_info.height_arg );
+ if( args_info.gui_given ) {
+ if( args_info.debug_given ) {
+ fprintf( stderr, "ERROR: don't run debug and GUI together! Uses too many resources!\n" );
+ exit( EXIT_SUCCESS );
+ }
+ emul.gui = true;
+ }
emul_start( &emul );
- emul_run( &emul );
+ emul_run( &emul, args_info.steps_arg );
emul_free( &emul );
exit( EXIT_SUCCESS );
diff --git a/emu/emul.c b/emu/emul.c
index 70a1144..930f112 100644
--- a/emu/emul.c
+++ b/emu/emul.c
@@ -3,11 +3,13 @@
#include <stdio.h>
#include <stdlib.h>
-void emul_init( emul_t *emul, cpu_6502_t *cpu, memory_t *memory )
+void emul_init( emul_t *emul, cpu_6502_t *cpu, memory_t *memory, int width, int height )
{
emul->cpu = cpu;
emul->memory = memory;
emul->gui = false;
+ emul->width = width;
+ emul->height = height;
}
void emul_start( emul_t *emul )
@@ -42,7 +44,7 @@ void emul_start( emul_t *emul )
emul->window = SDL_CreateWindow( "6502 emu",
SDL_WINDOWPOS_UNDEFINED_DISPLAY( display ),
SDL_WINDOWPOS_UNDEFINED_DISPLAY( display ),
- 600, 250, 0 );
+ emul->width, emul->height, 0 );
if( emul->window == NULL ) {
fprintf( stderr, "ERROR: SDL_CreateWindow failed: %s\n", SDL_GetError( ) );
exit( EXIT_FAILURE );
@@ -69,7 +71,7 @@ void emul_start( emul_t *emul )
}
}
-void emul_run( emul_t *emul )
+void emul_run( emul_t *emul, int nof_steps )
{
#ifdef WITH_GUI
if( emul->gui ) {
@@ -97,12 +99,17 @@ void emul_run( emul_t *emul )
if( delay > 0 ) {
SDL_Delay( delay );
}
+
+ if( nof_steps != -1 && emul->cpu->steps > nof_steps ) {
+ fprintf( stderr, "INFO: final number of steps reached (%d), terminating now\n", emul->cpu->steps );
+ done = true;
+ }
}
} else {
- cpu_6502_run( emul->cpu, 100 );
+ cpu_6502_run( emul->cpu, nof_steps );
}
#else
- cpu_6502_run( emul->cpu, 100 );
+ cpu_6502_run( emul->cpu, nof_steps );
#endif
}
diff --git a/emu/emul.h b/emu/emul.h
index 131cd4c..6012309 100644
--- a/emu/emul.h
+++ b/emu/emul.h
@@ -21,6 +21,8 @@ typedef struct emul_t {
cpu_6502_t *cpu;
memory_t *memory;
bool gui;
+ int width;
+ int height;
#ifdef WITH_GUI
SDL_Window *window;
SDL_Renderer *renderer;
@@ -29,9 +31,9 @@ typedef struct emul_t {
#endif
} emul_t;
-void emul_init( emul_t *emul, cpu_6502_t *cpu, memory_t *memory );
+void emul_init( emul_t *emul, cpu_6502_t *cpu, memory_t *memory, int width, int height );
void emul_start( emul_t *emul );
-void emul_run( emul_t *emul );
+void emul_run( emul_t *emul, int nof_steps );
void emul_free( emul_t *emul );
#endif
diff --git a/emu/memory.c b/emu/memory.c
index c9d953b..408e621 100644
--- a/emu/memory.c
+++ b/emu/memory.c
@@ -2,25 +2,51 @@
#include <stdio.h>
-void memory_init( memory_t *memory )
+void memory_init( memory_t *memory, seg7_t *seg )
{
memory->read = memory_read;
memory->write = memory_write;
+ memory->seg = seg;
}
uint8_t memory_read( memory_t *memory, uint16_t addr )
{
- return memory->cell[addr];
+ if( addr <= 0x3FFF ) {
+ // RAM access
+ return memory->cell[addr];
+ } else if( addr <= 0x8000 ) {
+ return seg7_read( memory->seg, addr );
+ } else {
+ // ROM access
+ return memory->cell[addr];
+ }
}
void memory_write( memory_t *memory, uint16_t addr, uint8_t data )
-{
- memory->cell[addr] = data;
+{
+ if( addr <= 0x3FFF ) {
+ // RAM access
+ memory->cell[addr] = data;
+ } else if( addr <= 0x8000 ) {
+ seg7_write( memory->seg, addr, data );
+ } else {
+ // ignore writes to ROM
+ }
}
void memory_load( memory_t *memory, uint16_t addr, uint16_t size, const char *filename )
{
- FILE *f = fopen( filename, "rb" );
- fread( &memory->cell[addr], size, 1, f );
- fclose( f );
+ if( addr >= 0x8000 ) {
+ FILE *f = fopen( filename, "rb" );
+ if( f == NULL ) {
+ fprintf( stderr, "ERROR: Unable to open ROM file '%s'\n", filename );
+ exit( EXIT_FAILURE );
+ }
+ fread( &memory->cell[addr], size, 1, f );
+ fclose( f );
+ fprintf( stderr, "INFO: Loaded firware from '%s' of size %d starting on address %04X\n",
+ filename, size, addr );
+ } else {
+ fprintf( stderr, "ERROR: Cannot load firmware into RAM at address %04X\n", addr );
+ }
}
diff --git a/emu/memory.h b/emu/memory.h
index 35fd0ef..b2abfee 100644
--- a/emu/memory.h
+++ b/emu/memory.h
@@ -1,6 +1,8 @@
#ifndef MEMORY_H
#define MEMORY_H
+#include "7seg.h"
+
#include <stdint.h>
enum {
@@ -11,11 +13,13 @@ typedef struct memory_t
{
uint8_t cell[MEMORY_SIZE];
+ seg7_t *seg;
+
uint8_t (*read)( struct memory_t *memory, uint16_t addr );
void (*write)( struct memory_t *memory, uint16_t addr, uint8_t data );
} memory_t;
-void memory_init( memory_t *memory );
+void memory_init( memory_t *memory, seg7_t *seg );
uint8_t memory_read( memory_t *memory, uint16_t addr );
void memory_write( memory_t *memory, uint16_t addr, uint8_t data );
void memory_load( memory_t *memory, uint16_t addr, uint16_t size, const char *filename );
diff --git a/emu/options.ggo b/emu/options.ggo
new file mode 100644
index 0000000..2f97ea1
--- /dev/null
+++ b/emu/options.ggo
@@ -0,0 +1,63 @@
+package "emu"
+version "0.0.1"
+usage "emu [options]"
+description "6502 emulator"
+
+section "Main Options"
+ option "long-version" -
+ "Full version and credentials"
+ optional
+
+ option "gui" g
+ "Enable GUI"
+ optional
+
+ option "debug" d
+ "Enable debugging output"
+ optional
+
+section "Run Options"
+
+ option "rom" r
+ "The code to load into ROM"
+ string typestr="filename"
+ default="rom.bin"
+ optional
+
+ option "steps" s
+ "Run at most 'steps' number of instructions (-1 means 'run forever')"
+ int typestr="steps"
+ default="-1"
+ optional
+
+section "Debug Options"
+
+ option "print-cpu" -
+ "Print status of CPU (registers, status register)"
+ optional
+
+ option "print-zero-page" -
+ "Print zero page of memory"
+ optional
+
+ option "print-stack" -
+ "Print stack area of memory"
+ optional
+
+ option "print-7seg" -
+ "Print what the 7-segment display on the VIA is doing"
+ optional
+
+section "GUI Options"
+
+ option "width" -
+ "Manually set width of the gui to x"
+ int typestr="pixel"
+ default="600"
+ optional
+
+ option "height" -
+ "Manually set height of the gui to y"
+ int typestr="pixel"
+ default="250"
+ optional
diff --git a/emu/options.ggo.in b/emu/options.ggo.in
index 61fb1d4..9cfbff9 100644
--- a/emu/options.ggo.in
+++ b/emu/options.ggo.in
@@ -16,3 +16,48 @@ section "Main Options"
"Enable debugging output"
optional
+section "Run Options"
+
+ option "rom" r
+ "The code to load into ROM"
+ string typestr="filename"
+ default="rom.bin"
+ optional
+
+ option "steps" s
+ "Run at most 'steps' number of instructions (-1 means 'run forever')"
+ int typestr="steps"
+ default="-1"
+ optional
+
+section "Debug Options"
+
+ option "print-cpu" -
+ "Print status of CPU (registers, status register)"
+ optional
+
+ option "print-zero-page" -
+ "Print zero page of memory"
+ optional
+
+ option "print-stack" -
+ "Print stack area of memory"
+ optional
+
+ option "print-7seg" -
+ "Print what the 7-segment display on the VIA is doing"
+ optional
+
+section "GUI Options"
+
+ option "width" -
+ "Manually set width of the gui to x"
+ int typestr="pixel"
+ default="600"
+ optional
+
+ option "height" -
+ "Manually set height of the gui to y"
+ int typestr="pixel"
+ default="250"
+ optional