summaryrefslogtreecommitdiff
path: root/emu
diff options
context:
space:
mode:
Diffstat (limited to 'emu')
-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
12 files changed, 297 insertions, 34 deletions
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