From 6c3401b8a2ce7a2dfe21a253f840f286088b1921 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 22 Nov 2020 20:38:51 +0100 Subject: more work on emulator --- emu/6502.c | 10 +++--- emu/6502.h | 6 ++-- emu/README | 4 +++ emu/emu.c | 13 +++++-- emu/emul.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ emu/emul.h | 30 +++++++++++++++- 6 files changed, 170 insertions(+), 10 deletions(-) create mode 100644 emu/README create mode 100644 emu/emul.c (limited to 'emu') diff --git a/emu/6502.c b/emu/6502.c index 0bb1993..8b24901 100644 --- a/emu/6502.c +++ b/emu/6502.c @@ -76,9 +76,9 @@ void cpu_6502_write_word( cpu_6502_t *cpu, uint16_t addr, uint16_t data ) cpu->memory->write( cpu->memory, addr + 1, ( data && 0x00FF ) ); } -void cpu_6502_run( cpu_6502_t *cpu ) +void cpu_6502_run( cpu_6502_t *cpu, int steps ) { - while( true ) { + for( int i = 0; i < steps; i++ ) { cpu_6502_step( cpu ); } } @@ -138,7 +138,7 @@ static bool is_carry( cpu_6502_t *cpu ) void cpu_6502_print_state( cpu_6502_t *cpu, uint8_t opcode ) { - fprintf( stderr, "PC: %04X SP: 01%02X PS: %02X %c%c-%c%c%c%c%c A: %02X X: %02X Y: %02X OP: %02X\n", + 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", cpu->PC, cpu->SP, cpu->PS, is_negative( cpu ) ? 'N' : 'n', is_overflow( cpu ) ? 'V' : 'v', @@ -147,7 +147,7 @@ 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->A, cpu->X, cpu->Y, opcode, cpu->steps ); } static void update_negative_and_sign( cpu_6502_t *cpu, uint8_t x ) @@ -253,4 +253,6 @@ void cpu_6502_step( cpu_6502_t *cpu ) fprintf( stderr, "ERROR: Illegal opcode %02X at PC %04X\n", opcode, cpu->PC ); exit( EXIT_FAILURE ); } + + cpu->steps++; } diff --git a/emu/6502.h b/emu/6502.h index 1af25bc..b5ab14a 100644 --- a/emu/6502.h +++ b/emu/6502.h @@ -16,6 +16,8 @@ typedef struct struct memory_t *memory; bool debug; + + int steps; } cpu_6502_t; enum { @@ -50,11 +52,11 @@ void cpu_6502_push_byte( cpu_6502_t *cpu, uint8_t data ); void cpu_6502_push_word( cpu_6502_t *cpu, uint16_t data ); 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 ); +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_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 ); -void cpu_6502_step( cpu_6502_t *cpu ); #endif diff --git a/emu/README b/emu/README new file mode 100644 index 0000000..fc23a5d --- /dev/null +++ b/emu/README @@ -0,0 +1,4 @@ +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 + diff --git a/emu/emu.c b/emu/emu.c index fbd9bb7..7d5c37c 100644 --- a/emu/emu.c +++ b/emu/emu.c @@ -6,16 +6,23 @@ int main( int argc, char *argv[] ) { + emul_t emul; cpu_6502_t cpu; memory_t memory; - + memory_init( &memory ); memory_load( &memory, ROM_START, ROM_SIZE, "./rom.bin" ); cpu_6502_init( &cpu, &memory ); - cpu.debug = true; + //cpu.debug = true; cpu_6502_reset( &cpu ); - cpu_6502_run( &cpu ); + emul_init( &emul, &cpu, &memory ); + emul.gui = true; + emul_start( &emul ); + + emul_run( &emul ); + + emul_free( &emul ); exit( EXIT_SUCCESS ); } diff --git a/emu/emul.c b/emu/emul.c new file mode 100644 index 0000000..dc7453b --- /dev/null +++ b/emu/emul.c @@ -0,0 +1,117 @@ +#include "emul.h" + +#include +#include + +void emul_init( emul_t *emul, cpu_6502_t *cpu, memory_t *memory ) +{ + emul->cpu = cpu; + emul->memory = memory; + emul->gui = false; +} + +void emul_start( emul_t *emul ) +{ + if( emul->gui ) { +#ifdef WITH_GUI + int rt = SDL_Init( SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO ); + if( rt < 0 ) { + fprintf( stderr, "ERROR: SDL_Init failed: %s\n", SDL_GetError( ) ); + exit( EXIT_FAILURE ); + } + atexit( SDL_Quit ); + SDL_ShowCursor( SDL_ENABLE ); + + int display = -1; + SDL_Rect display_rect; + for( int i = 0; i < SDL_GetNumVideoDisplays( ); i++ ) { + SDL_Rect rect; + if( SDL_GetDisplayBounds( i, &rect ) == 0 ) { + fprintf( stderr, "INFO: display %d has dimensions %dx%d\n", + i, rect.w, rect.h ); + display = i; + display_rect = rect; + } else { + fprintf( stderr, "ERROR: SDL_GetDisplayBounds failed: %s\n", SDL_GetError( ) ); + exit( EXIT_FAILURE ); + } + } + if( display < 0 ) { + fprintf( stderr, "ERROR: no video display found\n" ); + exit( EXIT_FAILURE ); + } + + emul->window = SDL_CreateWindow( "6502 emu", + SDL_WINDOWPOS_UNDEFINED_DISPLAY( display ), + SDL_WINDOWPOS_UNDEFINED_DISPLAY( display ), + 600, 250, 0 ); + if( emul->window == NULL ) { + fprintf( stderr, "ERROR: SDL_CreateWindow failed: %s\n", SDL_GetError( ) ); + exit( EXIT_FAILURE ); + } + + emul->renderer = SDL_CreateRenderer( emul->window, -1, 0 ); + if( emul->renderer == NULL ) { + fprintf( stderr, "ERROR: SDL_Renderer failed: %s\n", SDL_GetError( ) ); + exit( EXIT_FAILURE ); + } + + SDL_ShowWindow( emul->window ); + SDL_SetRenderDrawColor( emul->renderer, 0, 0, 0, 255 ); + SDL_RenderClear( emul->renderer ); + + emul->background_image = SDL_LoadBMP( "../other/breadboard.bmp" ); + emul->background_texture = SDL_CreateTextureFromSurface( emul->renderer, emul->background_image ); + SDL_RenderCopy( emul->renderer, emul->background_texture, NULL, NULL ); + + SDL_RenderPresent( emul->renderer ); +#else + fprintf( stderr, "WARN: gui enabled and not compiled with WITH_GUI (SDL2)\n" ); +#endif + } +} + +void emul_run( emul_t *emul ) +{ +#ifdef WITH_GUI + if( emul->gui ) { + SDL_Event event; + bool done = false; + while( !done ) { + uint32_t frame_start = SDL_GetTicks( ); + + SDL_PollEvent( &event ); + + switch( event.type ) { + case SDL_QUIT: + done = true; + break; + } + + cpu_6502_run( emul->cpu, CPU_FREQUENCY / DISPLAY_FPS ); + + cpu_6502_print_state( emul->cpu, 0 ); + SDL_RenderCopy( emul->renderer, emul->background_texture, NULL, NULL ); + SDL_RenderPresent( emul->renderer ); + + uint32_t frame_end = SDL_GetTicks( ); + int delay = frame_start + 1000 / DISPLAY_FPS - frame_end; + if( delay > 0 ) { + SDL_Delay( delay ); + } + } + } else { + cpu_6502_run( emul->cpu, 100 ); + } +#else + cpu_6502_run( emul->cpu, 100 ); +#endif +} + +void emul_free( emul_t *emul ) +{ + SDL_DestroyTexture( emul->background_texture ); + SDL_FreeSurface( emul->background_image ); + SDL_DestroyRenderer( emul->renderer ); + SDL_DestroyWindow( emul->window ); +} diff --git a/emu/emul.h b/emu/emul.h index cefa020..131cd4c 100644 --- a/emu/emul.h +++ b/emu/emul.h @@ -1,9 +1,37 @@ #ifndef EMUL_H #define EMUL_H +#include "6502.h" +#include "memory.h" + +#include + +#ifdef WITH_GUI +#include +#endif + enum { ROM_START = 0xF800, - ROM_SIZE = 2048 + ROM_SIZE = 2048, + CPU_FREQUENCY = 1000000, + DISPLAY_FPS = 25 }; +typedef struct emul_t { + cpu_6502_t *cpu; + memory_t *memory; + bool gui; +#ifdef WITH_GUI + SDL_Window *window; + SDL_Renderer *renderer; + SDL_Surface *background_image; + SDL_Texture *background_texture; +#endif +} emul_t; + +void emul_init( emul_t *emul, cpu_6502_t *cpu, memory_t *memory ); +void emul_start( emul_t *emul ); +void emul_run( emul_t *emul ); +void emul_free( emul_t *emul ); + #endif -- cgit v1.2.3-54-g00ecf