summaryrefslogtreecommitdiff
path: root/emu
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2020-11-27 20:04:18 +0100
committerAndreas Baumann <mail@andreasbaumann.cc>2020-11-27 20:04:18 +0100
commitf829f6893d94ed52044bf007bc447526c9d5e653 (patch)
treec1c98d8b9240b4507719aa8b78eb3ee03dd64ab5 /emu
parent3d77f3f5ad41e931117425f58c74f49c9503bf7b (diff)
download6502-f829f6893d94ed52044bf007bc447526c9d5e653.tar.gz
6502-f829f6893d94ed52044bf007bc447526c9d5e653.tar.bz2
emulator uses a bus now in the cpu, ROM, RAM and VIA (7-seg) are devices connected to the bus
Diffstat (limited to 'emu')
-rw-r--r--emu/6502.c12
-rw-r--r--emu/6502.h6
-rw-r--r--emu/7seg.c27
-rw-r--r--emu/7seg.h18
-rw-r--r--emu/CMakeLists.txt4
-rw-r--r--emu/bus.c75
-rw-r--r--emu/bus.h28
-rw-r--r--emu/device.c44
-rw-r--r--emu/device.h24
-rw-r--r--emu/emu.c26
-rw-r--r--emu/emul.c4
-rw-r--r--emu/emul.h20
-rw-r--r--emu/memory.c75
-rw-r--r--emu/memory.h29
14 files changed, 314 insertions, 78 deletions
diff --git a/emu/6502.c b/emu/6502.c
index ce1f0d3..dbdf5a1 100644
--- a/emu/6502.c
+++ b/emu/6502.c
@@ -8,9 +8,9 @@ static const uint16_t reset_vector = 0xFFFC;
static const uint16_t ZP_base = 0x0;
static const uint16_t SP_base = 0x100;
-void cpu_6502_init( cpu_6502_t *cpu, struct memory_t *memory )
+void cpu_6502_init( cpu_6502_t *cpu, bus_t *bus )
{
- cpu->memory = memory;
+ cpu->bus = bus;
cpu->debug_flags = 0;
}
@@ -62,18 +62,18 @@ void cpu_6502_reset( cpu_6502_t *cpu )
uint8_t cpu_6502_read_byte( cpu_6502_t *cpu, uint16_t addr )
{
- return cpu->memory->read( cpu->memory, addr );
+ return cpu->bus->base.vtable->read( cpu->bus, addr );
}
void cpu_6502_write_byte( cpu_6502_t *cpu, uint16_t addr, uint8_t data )
{
- cpu->memory->write( cpu->memory, addr, data );
+ cpu->bus->base.vtable->write( cpu->bus, addr, data );
}
void cpu_6502_write_word( cpu_6502_t *cpu, uint16_t addr, uint16_t data )
{
- cpu->memory->write( cpu->memory, addr, ( data && 0x00FF ) );
- cpu->memory->write( cpu->memory, addr + 1, ( data && 0x00FF ) );
+ cpu->bus->base.vtable->write( cpu->bus, addr, ( data && 0x00FF ) );
+ cpu->bus->base.vtable->write( cpu->bus, addr + 1, ( data && 0x00FF ) );
}
void cpu_6502_run( cpu_6502_t *cpu, int steps )
diff --git a/emu/6502.h b/emu/6502.h
index 20574c3..22da89f 100644
--- a/emu/6502.h
+++ b/emu/6502.h
@@ -4,6 +4,8 @@
#include <inttypes.h>
#include <stdbool.h>
+#include "bus.h"
+
typedef struct
{
uint8_t A;
@@ -13,7 +15,7 @@ typedef struct
uint16_t PC;
uint8_t PS;
- struct memory_t *memory;
+ bus_t *bus;
int debug_flags;
@@ -57,7 +59,7 @@ enum {
TXS_IMPL = 0x9A
};
-void cpu_6502_init( cpu_6502_t *cpu, struct memory_t *memory );
+void cpu_6502_init( cpu_6502_t *cpu, bus_t *bus );
void cpu_6502_reset( cpu_6502_t *cpu );
uint8_t cpu_6502_read_byte( cpu_6502_t *cpu, uint16_t addr );
uint16_t cpu_6502_read_word( cpu_6502_t *cpu, uint16_t addr );
diff --git a/emu/7seg.c b/emu/7seg.c
index 1aaf5f9..04a37f5 100644
--- a/emu/7seg.c
+++ b/emu/7seg.c
@@ -2,19 +2,31 @@
#include <stdio.h>
-void seg7_init( seg7_t *seg )
+static device_vtable_t const seg7_vtable = {
+ seg7_read,
+ seg7_write,
+ seg7_deinit
+};
+
+void seg7_init( seg7_t *seg, uint16_t addr )
{
+ device_init( &seg->base, "seg7" );
+ seg->base.vtable = (device_vtable_t *)&seg7_vtable;
+
+ seg->addr = addr;
seg->debug = false;
}
-uint8_t seg7_read( seg7_t *seg, uint16_t addr )
+uint8_t seg7_read( void *obj, uint16_t addr )
{
return 0;
}
-void seg7_write( seg7_t *seg, uint16_t addr, uint8_t data )
+void seg7_write( void *obj, uint16_t addr, uint8_t data )
{
- switch( addr ) {
+ seg7_t *seg = (seg7_t *)obj;
+
+ switch( addr - seg->addr ) {
case DDRA:
seg->ddr = data;
break;
@@ -41,3 +53,10 @@ void seg7_write( seg7_t *seg, uint16_t addr, uint8_t data )
// ignore writes to other addresses
}
}
+
+void seg7_deinit( void *obj )
+{
+ seg7_t *seg = (seg7_t *)obj;
+
+ device_deinit( &seg->base );
+}
diff --git a/emu/7seg.h b/emu/7seg.h
index 0cd585f..3953c70 100644
--- a/emu/7seg.h
+++ b/emu/7seg.h
@@ -1,6 +1,8 @@
#ifndef SEG7_H
#define SEG7_H
+#include "device.h"
+
#ifdef WITH_GUI
#include <SDL.h>
#endif
@@ -18,8 +20,8 @@
// +---- RCLK
// +----- SRCLK
enum {
- PORTA = 0x6001,
- DDRA = 0x6003,
+ PORTA = 0x01,
+ DDRA = 0x03,
SER = 0x01,
RCLK = 0x02,
@@ -28,6 +30,10 @@ enum {
typedef struct seg7_t
{
+ device_t base;
+
+ uint16_t addr;
+
uint8_t ddr;
uint16_t shift;
uint16_t latch;
@@ -35,8 +41,10 @@ typedef struct seg7_t
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 );
+void seg7_init( seg7_t *seg, uint16_t addr );
+
+uint8_t seg7_read( void *obj, uint16_t addr );
+void seg7_write( void *obj, uint16_t addr, uint8_t data );
+void seg7_deinit( void *obj );
#endif
diff --git a/emu/CMakeLists.txt b/emu/CMakeLists.txt
index e1fe6c9..04b1788 100644
--- a/emu/CMakeLists.txt
+++ b/emu/CMakeLists.txt
@@ -8,7 +8,7 @@ project(emu C)
set( EMU_VERSION 0.0.1 )
-set(CMAKE_C_FLAGS "-g -O0 -std=c99 -Wall -DWITH_GUI")
+set(CMAKE_C_FLAGS "-g -O0 -std=c99 -Wall -DWITH_GUI -D_POSIX_C_SOURCE=200809L")
add_custom_target(distclean
COMMAND make clean
@@ -21,6 +21,8 @@ configure_file( "${PROJECT_SOURCE_DIR}/version.h.in"
"${PROJECT_SOURCE_DIR}/version.h" @ONLY )
set(SRC
+ device.c
+ bus.c
6502.c
memory.c
7seg.c
diff --git a/emu/bus.c b/emu/bus.c
new file mode 100644
index 0000000..5bbbcb1
--- /dev/null
+++ b/emu/bus.c
@@ -0,0 +1,75 @@
+#include "bus.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static device_vtable_t const bus_vtable = {
+ bus_read,
+ bus_write,
+ bus_deinit
+};
+
+void bus_init( bus_t *bus )
+{
+ device_init( &bus->base, "bus" );
+ ((device_t *)bus)->vtable = (device_vtable_t *)&bus_vtable;
+
+ bus->nof_devices = 0;
+}
+
+void bus_register( bus_t *bus, device_t *device, uint16_t from, uint16_t to )
+{
+ if( bus->nof_devices < MAX_NOF_DEVICES ) {
+ registered_device_t *reg = &bus->devices[bus->nof_devices];
+ reg->device = device;
+ reg->from = from;
+ reg->to = to;
+ bus->nof_devices++;
+ } else {
+ fprintf( stderr, "ERROR: too many devices on bus\n" );
+ exit( EXIT_FAILURE );
+ }
+}
+
+uint8_t bus_read( void *obj, uint16_t addr )
+{
+ bus_t *bus = (bus_t *)obj;
+
+ for( int i = 0; i < bus->nof_devices; i++ ) {
+ registered_device_t *reg = &bus->devices[i];
+ if( reg->from <= addr && addr <= reg->to ) {
+ return reg->device->vtable->read( reg->device, addr );
+ }
+ }
+
+ fprintf( stderr, "ERROR: illegal bus access reading from address %04X\n", addr );
+
+ return 0;
+}
+
+void bus_write( void *obj, uint16_t addr, uint8_t data )
+{
+ bus_t *bus = (bus_t *)obj;
+
+ for( int i = 0; i < bus->nof_devices; i++ ) {
+ registered_device_t *reg = &bus->devices[i];
+ if( reg->from <= addr && addr <= reg->to ) {
+ return reg->device->vtable->write( reg->device, addr, data );
+ }
+ }
+
+ fprintf( stderr, "ERROR: illegal bus access writing from address %04X\n", addr );
+}
+
+void bus_deinit( void *obj )
+{
+ bus_t *bus = (bus_t *)obj;
+
+ for( int i = bus->nof_devices - 1; i >= 0; i-- ) {
+ registered_device_t *reg = &bus->devices[i];
+ reg->device->vtable->deinit( reg->device );
+ }
+ bus->nof_devices = 0;
+
+ device_deinit( &bus->base );
+}
diff --git a/emu/bus.h b/emu/bus.h
new file mode 100644
index 0000000..baa2fe2
--- /dev/null
+++ b/emu/bus.h
@@ -0,0 +1,28 @@
+#ifndef BUS_H
+#define BUS_H
+
+#include "device.h"
+
+enum {
+ MAX_NOF_DEVICES = 5
+};
+
+typedef struct registered_device_t {
+ device_t *device;
+ uint16_t from;
+ uint16_t to;
+} registered_device_t;
+
+typedef struct bus_t {
+ device_t base;
+ int nof_devices;
+ registered_device_t devices[MAX_NOF_DEVICES];
+} bus_t;
+
+void bus_init( bus_t *bus );
+void bus_register( bus_t *bus, device_t *device, uint16_t from, uint16_t to );
+uint8_t bus_read( void *obj, uint16_t addr );
+void bus_write( void *obj, uint16_t addr, uint8_t data );
+void bus_deinit( void *obj );
+
+#endif
diff --git a/emu/device.c b/emu/device.c
new file mode 100644
index 0000000..ecf3d2d
--- /dev/null
+++ b/emu/device.c
@@ -0,0 +1,44 @@
+#include "device.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static device_vtable_t const device_vtable = {
+ device_read,
+ device_write,
+ device_deinit
+};
+
+void device_init( device_t *device, const char *name )
+{
+ device->name = strdup( name );
+
+ device->vtable = &device_vtable;
+}
+
+uint8_t device_read( void *obj, uint16_t addr )
+{
+ device_t *device = (device_t *)obj;
+
+ fprintf( stderr, "WARN: read access on abstract device '%s' on address %04X\n",
+ device->name, addr );
+
+ return 0;
+}
+
+void device_write( void *obj, uint16_t addr, uint8_t data )
+{
+ device_t *device = (device_t *)obj;
+
+ fprintf( stderr, "WARN: write access on abstract device '%s' on address %04X\n",
+ device->name, addr );
+}
+
+void device_deinit( void *obj )
+{
+ device_t *device = (device_t *)obj;
+
+ free( device->name );
+}
+
diff --git a/emu/device.h b/emu/device.h
new file mode 100644
index 0000000..ce2abad
--- /dev/null
+++ b/emu/device.h
@@ -0,0 +1,24 @@
+#ifndef DEVICE_H
+#define DEVICE_H
+
+#include <stdint.h>
+
+struct device_t;
+
+typedef struct device_vtable_t {
+ uint8_t (*read)( void *obj, uint16_t addr );
+ void (*write)( void *obj, uint16_t addr, uint8_t data );
+ void (*deinit)( void *obj );
+} device_vtable_t;
+
+typedef struct device_t {
+ device_vtable_t const *vtable;
+ char *name;
+} device_t;
+
+void device_init( device_t *device, const char *name );
+uint8_t device_read( void *obj, uint16_t addr );
+void device_write( void *obj, uint16_t addr, uint8_t data );
+void device_deinit( void *obj );
+
+#endif
diff --git a/emu/emu.c b/emu/emu.c
index 2723880..95bc5cb 100644
--- a/emu/emu.c
+++ b/emu/emu.c
@@ -23,9 +23,11 @@ int main( int argc, char *argv[] )
{
struct gengetopt_args_info args_info;
emul_t emul;
- cpu_6502_t cpu;
- memory_t memory;
+ bus_t bus;
+ memory_t rom;
+ memory_t ram;
seg7_t seg7;
+ cpu_6502_t cpu;
if( parse_options_and_arguments( argc, argv, &args_info ) != 0 ) {
exit( EXIT_FAILURE );
@@ -36,12 +38,19 @@ int main( int argc, char *argv[] )
exit( EXIT_SUCCESS );
}
- seg7_init( &seg7 );
-
- memory_init( &memory, &seg7 );
- memory_load( &memory, ROM_START, ROM_SIZE, args_info.rom_arg );
+ bus_init( &bus );
+
+ memory_init( &rom, MEMORY_ROM, ROM_START, ROM_SIZE );
+ memory_load( &rom, args_info.rom_arg );
+ bus_register( &bus, &rom.base, ROM_START, ROM_END );
+
+ memory_init( &ram, MEMORY_RAM, RAM_START, RAM_SIZE );
+ bus_register( &bus, &ram.base, RAM_START, RAM_END );
+
+ seg7_init( &seg7, VIA_START );
+ bus_register( &bus, &seg7.base, VIA_START, VIA_END );
- cpu_6502_init( &cpu, &memory );
+ cpu_6502_init( &cpu, &bus );
if( args_info.debug_given ) {
if( args_info.print_cpu_given ) {
cpu.debug_flags |= DEBUG_STATUS;
@@ -58,7 +67,7 @@ int main( int argc, char *argv[] )
}
cpu_6502_reset( &cpu );
- emul_init( &emul, &cpu, &memory, args_info.width_arg, args_info.height_arg );
+ emul_init( &emul, &cpu, &bus, 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" );
@@ -70,6 +79,7 @@ int main( int argc, char *argv[] )
emul_run( &emul, args_info.steps_arg );
+ bus_deinit( &bus );
emul_free( &emul );
exit( EXIT_SUCCESS );
}
diff --git a/emu/emul.c b/emu/emul.c
index 930f112..602ce33 100644
--- a/emu/emul.c
+++ b/emu/emul.c
@@ -3,10 +3,10 @@
#include <stdio.h>
#include <stdlib.h>
-void emul_init( emul_t *emul, cpu_6502_t *cpu, memory_t *memory, int width, int height )
+void emul_init( emul_t *emul, cpu_6502_t *cpu, bus_t *bus, int width, int height )
{
emul->cpu = cpu;
- emul->memory = memory;
+ emul->bus = bus;
emul->gui = false;
emul->width = width;
emul->height = height;
diff --git a/emu/emul.h b/emu/emul.h
index 6012309..6945143 100644
--- a/emu/emul.h
+++ b/emu/emul.h
@@ -2,7 +2,7 @@
#define EMUL_H
#include "6502.h"
-#include "memory.h"
+#include "bus.h"
#include <stdbool.h>
@@ -11,15 +11,25 @@
#endif
enum {
- ROM_START = 0xF800,
- ROM_SIZE = 2048,
+ ROM_START = 0xf800,
+ ROM_END = 0xffff,
+ ROM_SIZE = 2048,
+
+ RAM_START = 0x0000,
+ RAM_END = 0x01ff,
+ RAM_SIZE = 512,
+
+ VIA_START = 0x6000,
+ VIA_END = 0x600f,
+
CPU_FREQUENCY = 1000000,
+
DISPLAY_FPS = 25
};
typedef struct emul_t {
cpu_6502_t *cpu;
- memory_t *memory;
+ bus_t *bus;
bool gui;
int width;
int height;
@@ -31,7 +41,7 @@ typedef struct emul_t {
#endif
} emul_t;
-void emul_init( emul_t *emul, cpu_6502_t *cpu, memory_t *memory, int width, int height );
+void emul_init( emul_t *emul, cpu_6502_t *cpu, bus_t *bus, int width, int height );
void emul_start( emul_t *emul );
void emul_run( emul_t *emul, int nof_steps );
void emul_free( emul_t *emul );
diff --git a/emu/memory.c b/emu/memory.c
index 408e621..52332e3 100644
--- a/emu/memory.c
+++ b/emu/memory.c
@@ -1,52 +1,63 @@
#include "memory.h"
#include <stdio.h>
+#include <stdlib.h>
-void memory_init( memory_t *memory, seg7_t *seg )
-{
- memory->read = memory_read;
- memory->write = memory_write;
- memory->seg = seg;
-}
+static device_vtable_t const memory_vtable = {
+ memory_read,
+ memory_write,
+ memory_deinit
+};
-uint8_t memory_read( memory_t *memory, uint16_t addr )
+void memory_init( memory_t *memory, memory_type_t type, uint16_t addr, uint16_t size )
{
- 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];
- }
-}
+ device_init( &memory->base, ( type == MEMORY_ROM ) ? "ROM" : "RAM" );
-void memory_write( memory_t *memory, uint16_t addr, uint8_t 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
- }
+ memory->type = type;
+ memory->addr = addr;
+ memory->size = size;
+ memory->cell = malloc( memory->size );
+ memory->base.vtable = (device_vtable_t *)&memory_vtable;
}
-void memory_load( memory_t *memory, uint16_t addr, uint16_t size, const char *filename )
+void memory_load( memory_t *memory, const char *filename )
{
- if( addr >= 0x8000 ) {
+ if( memory->type == MEMORY_ROM ) {
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 );
+ fread( &memory->cell[0], memory->size, 1, f );
fclose( f );
fprintf( stderr, "INFO: Loaded firware from '%s' of size %d starting on address %04X\n",
- filename, size, addr );
+ filename, memory->size, memory->addr );
} else {
- fprintf( stderr, "ERROR: Cannot load firmware into RAM at address %04X\n", addr );
+ fprintf( stderr, "ERROR: Cannot load firmware into RAM at address %04X\n", memory->addr );
}
}
+
+uint8_t memory_read( void *obj, uint16_t addr )
+{
+ memory_t *memory = (memory_t *)obj;
+
+ return memory->cell[addr-memory->addr];
+}
+
+void memory_write( void *obj, uint16_t addr, uint8_t data )
+{
+ memory_t *memory = (memory_t *)obj;
+
+ if( memory->type && MEMORY_ROM ) {
+ // ignore writes to ROM
+ } else {
+ memory->cell[addr-memory->addr] = data;
+ }
+}
+
+void memory_deinit( void *obj )
+{
+ memory_t *memory = (memory_t *)obj;
+
+ device_deinit( &memory->base );
+}
diff --git a/emu/memory.h b/emu/memory.h
index b2abfee..a0d45b9 100644
--- a/emu/memory.h
+++ b/emu/memory.h
@@ -1,27 +1,30 @@
#ifndef MEMORY_H
#define MEMORY_H
-#include "7seg.h"
+#include "device.h"
#include <stdint.h>
-enum {
- MEMORY_SIZE = 65535
-};
+typedef enum memory_type_t {
+ MEMORY_ROM = 1,
+ MEMORY_RAM = 2
+} memory_type_t;
typedef struct memory_t
{
- uint8_t cell[MEMORY_SIZE];
+ device_t base;
- 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_type_t type;
+ uint16_t addr;
+ int size;
+ uint8_t *cell;
} memory_t;
-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 );
+void memory_init( memory_t *memory, memory_type_t type, uint16_t addr, uint16_t size );
+void memory_load( memory_t *memory, const char *filename );
+
+uint8_t memory_read( void *obj, uint16_t addr );
+void memory_write( void *obj, uint16_t addr, uint8_t data );
+void memory_deinit( void *obj );
#endif