mirror of
https://github.com/st3fan/ewm.git
synced 2024-12-28 00:29:49 +00:00
Fixes #86 Create a BIOS
This commit is contained in:
parent
2557b2b1d0
commit
5cc4fe6c25
@ -25,7 +25,7 @@ CFLAGS=-std=c11 -O0 -Wpedantic -Wall -Wshadow -Werror -Wshadow -Wno-gnu-binary-
|
||||
LDFLAGS=-g -L/usr/local/lib
|
||||
|
||||
EWM_EXECUTABLE=ewm
|
||||
EWM_SOURCES=cpu.c ins.c pia.c mem.c ewm.c fmt.c two.c scr.c dsk.c chr.c alc.c one.c tty.c
|
||||
EWM_SOURCES=cpu.c ins.c pia.c mem.c ewm.c fmt.c two.c scr.c dsk.c chr.c alc.c one.c tty.c sma.c
|
||||
EWM_OBJECTS=$(EWM_SOURCES:.c=.o)
|
||||
EWM_LIBS=-lSDL2
|
||||
|
||||
|
@ -56,6 +56,15 @@ struct cpu_t {
|
||||
uint64_t counter;
|
||||
};
|
||||
|
||||
#define EWM_CPU_VECTORS_BASE (0xfffa)
|
||||
#define EWM_CPU_VECTORS_SIZE (6)
|
||||
|
||||
struct cpu_vectors_t {
|
||||
uint16_t rst;
|
||||
uint16_t nmi;
|
||||
uint16_t irq;
|
||||
};
|
||||
|
||||
#define MEM_FLAGS_READ 0x01
|
||||
#define MEM_FLAGS_WRITE 0x02
|
||||
|
||||
|
16
src/ewm.c
16
src/ewm.c
@ -22,13 +22,17 @@
|
||||
|
||||
#include "one.h"
|
||||
#include "two.h"
|
||||
#include "sma.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (strcmp(argv[1], "one") == 0) {
|
||||
return ewm_one_main(argc-1, &argv[1]);
|
||||
if (argc > 1) {
|
||||
if (strcmp(argv[1], "one") == 0) {
|
||||
return ewm_one_main(argc-1, &argv[1]);
|
||||
}
|
||||
if (strcmp(argv[1], "two") == 0) {
|
||||
return ewm_two_main(argc-1, &argv[1]);
|
||||
}
|
||||
} else {
|
||||
return ewm_sma_main(argc-1, &argv[1]);
|
||||
}
|
||||
if (strcmp(argv[1], "two") == 0) {
|
||||
return ewm_two_main(argc-1, &argv[1]);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
62
src/scr.c
62
src/scr.c
@ -39,8 +39,8 @@ static int txt_line_offsets[24] = {
|
||||
};
|
||||
|
||||
static inline void scr_render_character(struct scr_t *scr, int row, int column) {
|
||||
uint16_t base = (scr->two->screen_page == EWM_A2P_SCREEN_PAGE1) ? 0x0400 : 0x0800;
|
||||
uint8_t c = scr->two->screen_txt_data[((txt_line_offsets[row] + base) + column) - 0x0400];
|
||||
uint16_t base = (scr->screen_page == EWM_A2P_SCREEN_PAGE1) ? 0x0400 : 0x0800;
|
||||
uint8_t c = scr->screen_txt_data[((txt_line_offsets[row] + base) + column) - 0x0400];
|
||||
if (scr->chr->characters[c] != NULL) {
|
||||
SDL_Rect dst;
|
||||
dst.x = column * 21;
|
||||
@ -86,8 +86,8 @@ static SDL_Color lores_colors[16] = {
|
||||
};
|
||||
|
||||
static inline void scr_render_lores_block(struct scr_t *scr, int row, int column) {
|
||||
uint16_t base = (scr->two->screen_page == EWM_A2P_SCREEN_PAGE1) ? 0x0400 : 0x0800;
|
||||
uint8_t block = scr->two->screen_txt_data[((txt_line_offsets[row] + base) + column) - 0x0400];
|
||||
uint16_t base = (scr->screen_page == EWM_A2P_SCREEN_PAGE1) ? 0x0400 : 0x0800;
|
||||
uint8_t block = scr->screen_txt_data[((txt_line_offsets[row] + base) + column) - 0x0400];
|
||||
if (block != 0) {
|
||||
SDL_Rect dst;
|
||||
dst.x = column * 21;
|
||||
@ -111,7 +111,7 @@ static inline void scr_render_lores_block(struct scr_t *scr, int row, int column
|
||||
}
|
||||
|
||||
static inline void scr_render_lgr_screen(struct scr_t *scr) {
|
||||
bool mixed = (scr->two->screen_graphics_style == EWM_A2P_SCREEN_GRAPHICS_STYLE_MIXED);
|
||||
bool mixed = (scr->screen_graphics_style == EWM_A2P_SCREEN_GRAPHICS_STYLE_MIXED);
|
||||
|
||||
// Render graphics
|
||||
int rows = mixed ? 20 : 24;
|
||||
@ -178,7 +178,7 @@ static SDL_Color hgr_colors[16] = {
|
||||
static void inline scr_render_hgr_line_green(struct scr_t *scr, int line, uint16_t line_base) {
|
||||
int x = 0;
|
||||
for (int i = 0; i < 40; i++) {
|
||||
uint8_t c = scr->two->screen_hgr_data[line_base + i];
|
||||
uint8_t c = scr->screen_hgr_data[line_base + i];
|
||||
for (int j = 0; j < 7; j++) {
|
||||
SDL_Rect dst;
|
||||
dst.x = x * 3;
|
||||
@ -202,7 +202,7 @@ static void inline scr_render_hgr_line_color(struct scr_t *scr, int line, uint16
|
||||
|
||||
int pixels[280], x = 0;
|
||||
for (int i = 0; i < 40; i++) {
|
||||
uint8_t c = scr->two->screen_hgr_data[line_base + i];
|
||||
uint8_t c = scr->screen_hgr_data[line_base + i];
|
||||
for (int j = 0; j < 7; j++) {
|
||||
if (c & (1 << j)) {
|
||||
if (x % 2 == 0) {
|
||||
@ -250,8 +250,8 @@ static void inline scr_render_hgr_line_color(struct scr_t *scr, int line, uint16
|
||||
|
||||
static void inline scr_render_hgr_screen(struct scr_t *scr) {
|
||||
// Render graphics
|
||||
int lines = (scr->two->screen_graphics_style == EWM_A2P_SCREEN_GRAPHICS_STYLE_MIXED) ? 160 : 192;
|
||||
uint16_t hgr_base = hgr_page_offsets[scr->two->screen_page];
|
||||
int lines = (scr->screen_graphics_style == EWM_A2P_SCREEN_GRAPHICS_STYLE_MIXED) ? 160 : 192;
|
||||
uint16_t hgr_base = hgr_page_offsets[scr->screen_page];
|
||||
for (int line = 0; line < lines; line++) {
|
||||
uint16_t line_base = hgr_base + hgr_line_offsets[line];
|
||||
if (scr->color_scheme == EWM_SCR_COLOR_SCHEME_COLOR) {
|
||||
@ -262,7 +262,7 @@ static void inline scr_render_hgr_screen(struct scr_t *scr) {
|
||||
}
|
||||
|
||||
// Render bottom 4 lines of text
|
||||
if (scr->two->screen_graphics_style == EWM_A2P_SCREEN_GRAPHICS_STYLE_MIXED) {
|
||||
if (scr->screen_graphics_style == EWM_A2P_SCREEN_GRAPHICS_STYLE_MIXED) {
|
||||
for (int row = 20; row < 24; row++) {
|
||||
for (int column = 0; column < 40; column++) {
|
||||
scr_render_character(scr, row, column);
|
||||
@ -271,23 +271,53 @@ static void inline scr_render_hgr_screen(struct scr_t *scr) {
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t ewm_scr_screen_txt_read(struct cpu_t *cpu, struct mem_t *mem, uint16_t addr) {
|
||||
struct scr_t *scr = (struct scr_t*) mem->obj;
|
||||
return scr->screen_txt_data[addr - mem->start];
|
||||
}
|
||||
|
||||
static void ewm_scr_screen_txt_write(struct cpu_t *cpu, struct mem_t *mem, uint16_t addr, uint8_t b) {
|
||||
struct scr_t *scr = (struct scr_t*) mem->obj;
|
||||
scr->screen_txt_data[addr - mem->start] = b;
|
||||
scr->screen_dirty = true;
|
||||
}
|
||||
|
||||
static uint8_t ewm_scr_screen_hgr_read(struct cpu_t *cpu, struct mem_t *mem, uint16_t addr) {
|
||||
struct scr_t *scr = (struct scr_t*) mem->obj;
|
||||
return scr->screen_hgr_data[addr - mem->start];
|
||||
}
|
||||
|
||||
static void ewm_scr_screen_hgr_write(struct cpu_t *cpu, struct mem_t *mem, uint16_t addr, uint8_t b) {
|
||||
struct scr_t *scr = (struct scr_t*) mem->obj;
|
||||
scr->screen_hgr_data[addr - mem->start] = b;
|
||||
scr->screen_dirty = true;
|
||||
}
|
||||
|
||||
// TODO This is the only actual API exposed
|
||||
|
||||
int ewm_scr_init(struct scr_t *scr, struct ewm_two_t *two, SDL_Renderer *renderer) {
|
||||
static int ewm_scr_init(struct scr_t *scr, struct cpu_t *cpu, SDL_Renderer *renderer) {
|
||||
memset(scr, 0x00, sizeof(struct scr_t));
|
||||
scr->two = two;
|
||||
|
||||
scr->renderer = renderer;
|
||||
|
||||
scr->chr = ewm_chr_create("rom/3410036.bin", EWM_CHR_ROM_TYPE_2716, renderer);
|
||||
if (scr->chr == NULL) {
|
||||
fprintf(stderr, "[SCR] Failed to initialize character generator\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
scr->screen_txt_data = malloc(2 * 1024);
|
||||
scr->screen_txt_iom = cpu_add_iom(cpu, 0x0400, 0x0bff, scr, ewm_scr_screen_txt_read, ewm_scr_screen_txt_write);
|
||||
|
||||
scr->screen_hgr_data = malloc(16 * 1024);
|
||||
scr->screen_hgr_iom = cpu_add_iom(cpu, 0x2000, 0x5fff, scr, ewm_scr_screen_hgr_read, ewm_scr_screen_hgr_write);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct scr_t *ewm_scr_create(struct ewm_two_t *two, SDL_Renderer *renderer) {
|
||||
struct scr_t *ewm_scr_create(struct cpu_t *cpu, SDL_Renderer *renderer) {
|
||||
struct scr_t *scr = malloc(sizeof(struct scr_t));
|
||||
if (ewm_scr_init(scr, two, renderer) != 0) {
|
||||
if (ewm_scr_init(scr, cpu, renderer) != 0) {
|
||||
free(scr);
|
||||
scr = NULL;
|
||||
}
|
||||
@ -302,12 +332,12 @@ void ewm_scr_update(struct scr_t *scr) {
|
||||
SDL_SetRenderDrawColor(scr->renderer, 0, 0, 0, 255);
|
||||
SDL_RenderClear(scr->renderer);
|
||||
|
||||
switch (scr->two->screen_mode) {
|
||||
switch (scr->screen_mode) {
|
||||
case EWM_A2P_SCREEN_MODE_TEXT:
|
||||
scr_render_txt_screen(scr);
|
||||
break;
|
||||
case EWM_A2P_SCREEN_MODE_GRAPHICS:
|
||||
switch (scr->two->screen_graphics_mode) {
|
||||
switch (scr->screen_graphics_mode) {
|
||||
case EWM_A2P_SCREEN_GRAPHICS_MODE_LGR:
|
||||
scr_render_lgr_screen(scr);
|
||||
break;
|
||||
|
20
src/scr.h
20
src/scr.h
@ -32,18 +32,28 @@
|
||||
struct ewm_two_t;
|
||||
struct ewm_chr_t;
|
||||
|
||||
// The 'scr' object represents the screen. It renders the contents of
|
||||
// the machine. It has pluggable renders.
|
||||
// The 'scr' object represents the Apple ][ screen. It renders the
|
||||
// contents of the machine.
|
||||
|
||||
struct scr_t {
|
||||
struct ewm_two_t *two;
|
||||
SDL_Renderer *renderer;
|
||||
struct ewm_chr_t *chr;
|
||||
int color_scheme;
|
||||
|
||||
uint8_t *screen_txt_data;
|
||||
struct mem_t *screen_txt_iom;
|
||||
|
||||
uint8_t *screen_hgr_data;
|
||||
struct mem_t *screen_hgr_iom;
|
||||
|
||||
int screen_mode;
|
||||
int screen_graphics_mode;
|
||||
int screen_graphics_style;
|
||||
int screen_page;
|
||||
int screen_dirty;
|
||||
};
|
||||
|
||||
struct scr_t *ewm_scr_create(struct ewm_two_t *two, SDL_Renderer *renderer);
|
||||
int ewm_scr_init(struct scr_t *scr, struct ewm_two_t *two, SDL_Renderer *renderer);
|
||||
struct scr_t *ewm_scr_create(struct cpu_t *cpu, SDL_Renderer *renderer);
|
||||
void ewm_scr_destroy(struct scr_t *scr);
|
||||
void ewm_scr_update(struct scr_t *scr);
|
||||
void ewm_scr_set_color_scheme(struct scr_t *scr, int color_scheme);
|
||||
|
@ -28,62 +28,62 @@
|
||||
#include "two.h"
|
||||
#include "scr.h"
|
||||
|
||||
typedef void (*test_setup_t)(struct scr_t *scr);
|
||||
typedef void (*test_run_t)(struct scr_t *scr);
|
||||
typedef void (*test_setup_t)(struct ewm_two_t *two);
|
||||
typedef void (*test_run_t)(struct ewm_two_t *two);
|
||||
|
||||
|
||||
void txt_full_refresh_setup(struct scr_t *scr) {
|
||||
scr->two->screen_mode = EWM_A2P_SCREEN_MODE_TEXT;
|
||||
scr->two->screen_page = EWM_A2P_SCREEN_PAGE1;
|
||||
void txt_full_refresh_setup(struct ewm_two_t *two) {
|
||||
two->scr->screen_mode = EWM_A2P_SCREEN_MODE_TEXT;
|
||||
two->scr->screen_page = EWM_A2P_SCREEN_PAGE1;
|
||||
|
||||
for (uint16_t a = 0x0400; a <= 0x0bff; a++) {
|
||||
uint8_t v = 0xa0 + (random() % 64);
|
||||
mem_set_byte(scr->two->cpu, a, v);
|
||||
mem_set_byte(two->cpu, a, v);
|
||||
}
|
||||
}
|
||||
|
||||
void txt_full_refresh_test(struct scr_t *scr) {
|
||||
ewm_scr_update(scr);
|
||||
void txt_full_refresh_test(struct ewm_two_t *two) {
|
||||
ewm_scr_update(two->scr);
|
||||
}
|
||||
|
||||
void lgr_full_refresh_setup(struct scr_t *scr) {
|
||||
scr->two->screen_mode = EWM_A2P_SCREEN_MODE_GRAPHICS;
|
||||
scr->two->screen_page = EWM_A2P_SCREEN_PAGE1;
|
||||
scr->two->screen_graphics_mode = EWM_A2P_SCREEN_GRAPHICS_MODE_LGR;
|
||||
scr->two->screen_graphics_style = EWM_A2P_SCREEN_GRAPHICS_STYLE_FULL;
|
||||
void lgr_full_refresh_setup(struct ewm_two_t *two) {
|
||||
two->scr->screen_mode = EWM_A2P_SCREEN_MODE_GRAPHICS;
|
||||
two->scr->screen_page = EWM_A2P_SCREEN_PAGE1;
|
||||
two->scr->screen_graphics_mode = EWM_A2P_SCREEN_GRAPHICS_MODE_LGR;
|
||||
two->scr->screen_graphics_style = EWM_A2P_SCREEN_GRAPHICS_STYLE_FULL;
|
||||
|
||||
for (uint16_t a = 0x0400; a <= 0x0bff; a++) {
|
||||
uint8_t v = ((random() % 16) << 4) | (random() % 16);
|
||||
mem_set_byte(scr->two->cpu, a, v);
|
||||
mem_set_byte(two->cpu, a, v);
|
||||
}
|
||||
}
|
||||
|
||||
void lgr_full_refresh_test(struct scr_t *scr) {
|
||||
ewm_scr_update(scr);
|
||||
void lgr_full_refresh_test(struct ewm_two_t *two) {
|
||||
ewm_scr_update(two->scr);
|
||||
}
|
||||
|
||||
void hgr_full_refresh_setup(struct scr_t *scr) {
|
||||
scr->two->screen_mode = EWM_A2P_SCREEN_MODE_GRAPHICS;
|
||||
scr->two->screen_page = EWM_A2P_SCREEN_PAGE1;
|
||||
scr->two->screen_graphics_mode = EWM_A2P_SCREEN_GRAPHICS_MODE_HGR;
|
||||
scr->two->screen_graphics_style = EWM_A2P_SCREEN_GRAPHICS_STYLE_FULL;
|
||||
void hgr_full_refresh_setup(struct ewm_two_t *two) {
|
||||
two->scr->screen_mode = EWM_A2P_SCREEN_MODE_GRAPHICS;
|
||||
two->scr->screen_page = EWM_A2P_SCREEN_PAGE1;
|
||||
two->scr->screen_graphics_mode = EWM_A2P_SCREEN_GRAPHICS_MODE_HGR;
|
||||
two->scr->screen_graphics_style = EWM_A2P_SCREEN_GRAPHICS_STYLE_FULL;
|
||||
|
||||
for (uint16_t a = 0x2000; a <= 0x5fff; a++) {
|
||||
mem_set_byte(scr->two->cpu, a, random());
|
||||
mem_set_byte(two->cpu, a, random());
|
||||
}
|
||||
}
|
||||
|
||||
void hgr_full_refresh_test(struct scr_t *scr) {
|
||||
ewm_scr_update(scr);
|
||||
void hgr_full_refresh_test(struct ewm_two_t *two) {
|
||||
ewm_scr_update(two->scr);
|
||||
}
|
||||
|
||||
void test(struct scr_t *scr, char *name, test_setup_t test_setup, test_run_t test_run) {
|
||||
test_setup(scr);
|
||||
void test(struct ewm_two_t *two, char *name, test_setup_t test_setup, test_run_t test_run) {
|
||||
test_setup(two);
|
||||
|
||||
Uint64 start = SDL_GetPerformanceCounter();
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
test_run(scr);
|
||||
SDL_RenderPresent(scr->renderer);
|
||||
test_run(two);
|
||||
SDL_RenderPresent(two->scr->renderer);
|
||||
}
|
||||
Uint64 now = SDL_GetPerformanceCounter();
|
||||
double total = (double)((now - start)*1000) / SDL_GetPerformanceFrequency();
|
||||
@ -118,9 +118,9 @@ int main() {
|
||||
|
||||
struct ewm_two_t *two = ewm_two_create(EWM_TWO_TYPE_APPLE2PLUS, renderer, NULL);
|
||||
|
||||
test(two->scr, "txt_full_refresh", txt_full_refresh_setup, txt_full_refresh_test);
|
||||
test(two->scr, "lgr_full_refresh", lgr_full_refresh_setup, lgr_full_refresh_test);
|
||||
test(two->scr, "hgr_full_refresh", hgr_full_refresh_setup, hgr_full_refresh_test);
|
||||
test(two, "txt_full_refresh", txt_full_refresh_setup, txt_full_refresh_test);
|
||||
test(two, "lgr_full_refresh", lgr_full_refresh_setup, lgr_full_refresh_test);
|
||||
test(two, "hgr_full_refresh", hgr_full_refresh_setup, hgr_full_refresh_test);
|
||||
|
||||
// Destroy DSL things
|
||||
|
||||
|
207
src/sma.c
Normal file
207
src/sma.c
Normal file
@ -0,0 +1,207 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2015 Stefan Arentz - http://github.com/st3fan/ewm
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "mem.h"
|
||||
#include "tty.h"
|
||||
#include "sma.h"
|
||||
|
||||
#define EWM_SMA_RAM_BASE (0)
|
||||
#define EWM_SMA_RAM_SIZE (16 * 1024)
|
||||
#define EWM_SMA_ROM_BASE (EWM_SMA_RAM_BASE + EWM_SMA_RAM_SIZE - 1)
|
||||
#define EWM_SMA_ROM_SIZE (4 * 1024)
|
||||
#define EWM_SMA_TTY_BASE (EWM_SMA_ROM_BASE + EWM_SMA_ROM_SIZE - 1)
|
||||
#define EWM_SMA_TTY_SIZE (1 * 1024)
|
||||
|
||||
static bool ewm_sma_poll_event(struct ewm_sma_t *sma, SDL_Window *window) {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event) != 0) {
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
return false;
|
||||
|
||||
case SDL_WINDOWEVENT:
|
||||
sma->tty->screen_dirty = true;
|
||||
break;
|
||||
|
||||
case SDL_KEYDOWN:
|
||||
if (event.key.keysym.mod & KMOD_GUI) {
|
||||
switch (event.key.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
fprintf(stderr, "[SDL] Reset\n");
|
||||
cpu_reset(sma->cpu);
|
||||
break;
|
||||
case SDLK_RETURN:
|
||||
if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) {
|
||||
SDL_SetWindowFullscreen(window, 0);
|
||||
} else {
|
||||
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL_TEXTINPUT:
|
||||
if (strlen(event.text.text) == 1) {
|
||||
sma->key = toupper(event.text.text[0]) | 0x80;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ewm_sma_step_cpu(struct ewm_sma_t *sma, int cycles) {
|
||||
while (true) {
|
||||
int ret = cpu_step(sma->cpu);
|
||||
if (ret < 0) {
|
||||
switch (ret) {
|
||||
case EWM_CPU_ERR_UNIMPLEMENTED_INSTRUCTION:
|
||||
fprintf(stderr, "CPU: Exited because of unimplemented instructions 0x%.2x at 0x%.4x\n",
|
||||
mem_get_byte(sma->cpu, sma->cpu->state.pc), sma->cpu->state.pc);
|
||||
break;
|
||||
case EWM_CPU_ERR_STACK_OVERFLOW:
|
||||
fprintf(stderr, "CPU: Exited because of stack overflow at 0x%.4x\n", sma->cpu->state.pc);
|
||||
break;
|
||||
case EWM_CPU_ERR_STACK_UNDERFLOW:
|
||||
fprintf(stderr, "CPU: Exited because of stack underflow at 0x%.4x\n", sma->cpu->state.pc);
|
||||
break;
|
||||
}
|
||||
cpu_nmi(sma->cpu);
|
||||
}
|
||||
cycles -= ret;
|
||||
if (cycles <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint8_t ewm_sma_tty_buffer_read(struct cpu_t *cpu, struct mem_t *mem, uint16_t addr) {
|
||||
struct ewm_sma_t *sma = (struct ewm_sma_t*) mem->obj;
|
||||
return sma->tty->screen_buffer[addr - mem->start];
|
||||
}
|
||||
|
||||
static void ewm_sma_tty_buffer_write(struct cpu_t *cpu, struct mem_t *mem, uint16_t addr, uint8_t b) {
|
||||
struct ewm_sma_t *sma = (struct ewm_sma_t*) mem->obj;
|
||||
sma->tty->screen_buffer[addr - mem->start] = b;
|
||||
sma->tty->screen_dirty = true;
|
||||
}
|
||||
|
||||
static struct cpu_vectors_t ewm_sma_cpu_vectors = { 0, 0, 0 };
|
||||
|
||||
static int ewm_sma_init(struct ewm_sma_t *sma, SDL_Renderer *renderer) {
|
||||
memset(sma, 0, sizeof(struct ewm_sma_t));
|
||||
|
||||
sma->cpu = cpu_create(EWM_CPU_MODEL_6502);
|
||||
|
||||
sma->ram = cpu_add_ram(sma->cpu, EWM_SMA_RAM_BASE, EWM_SMA_RAM_BASE + EWM_SMA_RAM_SIZE - 1);
|
||||
sma->rom = cpu_add_rom_file(sma->cpu, EWM_SMA_ROM_BASE, "rom/sma.bin");
|
||||
sma->rom = cpu_add_rom_data(sma->cpu, EWM_CPU_VECTORS_BASE, EWM_CPU_VECTORS_BASE + EWM_CPU_VECTORS_SIZE - 1,
|
||||
(uint8_t*) &ewm_sma_cpu_vectors);
|
||||
sma->tty = ewm_tty_create(renderer);
|
||||
if (sma->tty == NULL) {
|
||||
fprintf(stderr, "[SMA] Could not create TTY\n");
|
||||
return -1;
|
||||
}
|
||||
sma->tty_iom = cpu_add_iom(sma->cpu, EWM_SMA_TTY_BASE, EWM_SMA_TTY_BASE + EWM_SMA_TTY_SIZE - 1,
|
||||
sma->tty, ewm_sma_tty_buffer_read, ewm_sma_tty_buffer_write);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ewm_sma_t *ewm_sma_create(SDL_Renderer *renderer) {
|
||||
struct ewm_sma_t *sma = malloc(sizeof(struct ewm_sma_t));
|
||||
if (ewm_sma_init(sma, renderer) != 0) {
|
||||
free(sma);
|
||||
sma = NULL;
|
||||
}
|
||||
return sma;
|
||||
}
|
||||
|
||||
int ewm_sma_main(int argc, char **argv) {
|
||||
// Initialize SDL
|
||||
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER) < 0) {
|
||||
fprintf(stderr, "Failed to initialize SDL: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
SDL_Window *window = SDL_CreateWindow("EWM v0.1 / System Management Agent", 400, 60, 280*3, 192*3, SDL_WINDOW_SHOWN);
|
||||
if (window == NULL) {
|
||||
fprintf(stderr, "Failed create window: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
||||
if (renderer == NULL) {
|
||||
fprintf(stderr, "Failed to create renderer: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
SDL_RenderSetLogicalSize(renderer, 280*3, 192*3);
|
||||
|
||||
// Create the System Management Agent
|
||||
|
||||
struct ewm_sma_t *sma = ewm_sma_create(renderer);
|
||||
cpu_reset(sma->cpu);
|
||||
|
||||
//
|
||||
|
||||
SDL_StartTextInput();
|
||||
|
||||
Uint32 ticks = SDL_GetTicks();
|
||||
|
||||
while (true) {
|
||||
if (!ewm_sma_poll_event(sma, window)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((SDL_GetTicks() - ticks) >= (1000 / 50)) {
|
||||
if (!ewm_sma_step_cpu(sma, 1000000 / 50)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (sma->tty->screen_dirty) {
|
||||
ewm_tty_refresh(sma->tty);
|
||||
sma->tty->screen_dirty = false;
|
||||
SDL_RenderPresent(sma->tty->renderer);
|
||||
}
|
||||
|
||||
ticks = SDL_GetTicks();
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy SDL
|
||||
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
|
||||
return 0;
|
||||
}
|
44
src/sma.h
Normal file
44
src/sma.h
Normal file
@ -0,0 +1,44 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2015 Stefan Arentz - http://github.com/st3fan/ewm
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#ifndef EWM_SMA_H
|
||||
#define EWM_SMA_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct cpu_t;
|
||||
struct scr_t;
|
||||
struct mem_t;
|
||||
|
||||
struct ewm_sma_t {
|
||||
struct cpu_t *cpu;
|
||||
struct mem_t *ram;
|
||||
struct mem_t *rom;
|
||||
struct ewm_tty_t *tty;
|
||||
struct mem_t *tty_iom;
|
||||
uint8_t key;
|
||||
};
|
||||
|
||||
int ewm_sma_main(int argc, char **argv);
|
||||
|
||||
#endif // EWM_SMA_H
|
100
src/two.c
100
src/two.c
@ -79,39 +79,39 @@ static uint8_t ewm_two_iom_read(struct cpu_t *cpu, struct mem_t *mem, uint16_t a
|
||||
return 0x00;
|
||||
|
||||
case EWM_A2P_SS_SCREEN_MODE_GRAPHICS:
|
||||
two->screen_mode = EWM_A2P_SCREEN_MODE_GRAPHICS;
|
||||
two->screen_dirty = true;
|
||||
two->scr->screen_mode = EWM_A2P_SCREEN_MODE_GRAPHICS;
|
||||
two->scr->screen_dirty = true;
|
||||
break;
|
||||
case EWM_A2P_SS_SCREEN_MODE_TEXT:
|
||||
two->screen_mode = EWM_A2P_SCREEN_MODE_TEXT;
|
||||
two->screen_dirty = true;
|
||||
two->scr->screen_mode = EWM_A2P_SCREEN_MODE_TEXT;
|
||||
two->scr->screen_dirty = true;
|
||||
break;
|
||||
|
||||
case EWM_A2P_SS_GRAPHICS_MODE_LGR:
|
||||
two->screen_graphics_mode = EWM_A2P_SCREEN_GRAPHICS_MODE_LGR;
|
||||
two->screen_dirty = true;
|
||||
two->scr->screen_graphics_mode = EWM_A2P_SCREEN_GRAPHICS_MODE_LGR;
|
||||
two->scr->screen_dirty = true;
|
||||
break;
|
||||
case EWM_A2P_SS_GRAPHICS_MODE_HGR:
|
||||
two->screen_graphics_mode = EWM_A2P_SCREEN_GRAPHICS_MODE_HGR;
|
||||
two->screen_dirty = true;
|
||||
two->scr->screen_graphics_mode = EWM_A2P_SCREEN_GRAPHICS_MODE_HGR;
|
||||
two->scr->screen_dirty = true;
|
||||
break;
|
||||
|
||||
case EWM_A2P_SS_GRAPHICS_STYLE_FULL:
|
||||
two->screen_graphics_style = EWM_A2P_SCREEN_GRAPHICS_STYLE_FULL;
|
||||
two->screen_dirty = true;
|
||||
two->scr->screen_graphics_style = EWM_A2P_SCREEN_GRAPHICS_STYLE_FULL;
|
||||
two->scr->screen_dirty = true;
|
||||
break;
|
||||
case EWM_A2P_SS_GRAPHICS_STYLE_MIXED:
|
||||
two->screen_graphics_style = EWM_A2P_SCREEN_GRAPHICS_STYLE_MIXED;
|
||||
two->screen_dirty = true;
|
||||
two->scr->screen_graphics_style = EWM_A2P_SCREEN_GRAPHICS_STYLE_MIXED;
|
||||
two->scr->screen_dirty = true;
|
||||
break;
|
||||
|
||||
case EWM_A2P_SS_SCREEN_PAGE1:
|
||||
two->screen_page = EWM_A2P_SCREEN_PAGE1;
|
||||
two->screen_dirty = true;
|
||||
two->scr->screen_page = EWM_A2P_SCREEN_PAGE1;
|
||||
two->scr->screen_dirty = true;
|
||||
break;
|
||||
case EWM_A2P_SS_SCREEN_PAGE2:
|
||||
two->screen_page = EWM_A2P_SCREEN_PAGE2;
|
||||
two->screen_dirty = true;
|
||||
two->scr->screen_page = EWM_A2P_SCREEN_PAGE2;
|
||||
two->scr->screen_dirty = true;
|
||||
break;
|
||||
|
||||
case EWM_A2P_SS_SPKR:
|
||||
@ -190,39 +190,39 @@ static void ewm_two_iom_write(struct cpu_t *cpu, struct mem_t *mem, uint16_t add
|
||||
break;
|
||||
|
||||
case EWM_A2P_SS_SCREEN_MODE_GRAPHICS:
|
||||
two->screen_mode = EWM_A2P_SCREEN_MODE_GRAPHICS;
|
||||
two->screen_dirty = true;
|
||||
two->scr->screen_mode = EWM_A2P_SCREEN_MODE_GRAPHICS;
|
||||
two->scr->screen_dirty = true;
|
||||
break;
|
||||
case EWM_A2P_SS_SCREEN_MODE_TEXT:
|
||||
two->screen_mode = EWM_A2P_SCREEN_MODE_TEXT;
|
||||
two->screen_dirty = true;
|
||||
two->scr->screen_mode = EWM_A2P_SCREEN_MODE_TEXT;
|
||||
two->scr->screen_dirty = true;
|
||||
break;
|
||||
|
||||
case EWM_A2P_SS_GRAPHICS_MODE_LGR:
|
||||
two->screen_graphics_mode = EWM_A2P_SCREEN_GRAPHICS_MODE_LGR;
|
||||
two->screen_dirty = true;
|
||||
two->scr->screen_graphics_mode = EWM_A2P_SCREEN_GRAPHICS_MODE_LGR;
|
||||
two->scr->screen_dirty = true;
|
||||
break;
|
||||
case EWM_A2P_SS_GRAPHICS_MODE_HGR:
|
||||
two->screen_graphics_mode = EWM_A2P_SCREEN_GRAPHICS_MODE_HGR;
|
||||
two->screen_dirty = true;
|
||||
two->scr->screen_graphics_mode = EWM_A2P_SCREEN_GRAPHICS_MODE_HGR;
|
||||
two->scr->screen_dirty = true;
|
||||
break;
|
||||
|
||||
case EWM_A2P_SS_GRAPHICS_STYLE_FULL:
|
||||
two->screen_graphics_style = EWM_A2P_SCREEN_GRAPHICS_STYLE_FULL;
|
||||
two->screen_dirty = true;
|
||||
two->scr->screen_graphics_style = EWM_A2P_SCREEN_GRAPHICS_STYLE_FULL;
|
||||
two->scr->screen_dirty = true;
|
||||
break;
|
||||
case EWM_A2P_SS_GRAPHICS_STYLE_MIXED:
|
||||
two->screen_graphics_style = EWM_A2P_SCREEN_GRAPHICS_STYLE_MIXED;
|
||||
two->screen_dirty = true;
|
||||
two->scr->screen_graphics_style = EWM_A2P_SCREEN_GRAPHICS_STYLE_MIXED;
|
||||
two->scr->screen_dirty = true;
|
||||
break;
|
||||
|
||||
case EWM_A2P_SS_SCREEN_PAGE1:
|
||||
two->screen_page = EWM_A2P_SCREEN_PAGE1;
|
||||
two->screen_dirty = true;
|
||||
two->scr->screen_page = EWM_A2P_SCREEN_PAGE1;
|
||||
two->scr->screen_dirty = true;
|
||||
break;
|
||||
case EWM_A2P_SS_SCREEN_PAGE2:
|
||||
two->screen_page = EWM_A2P_SCREEN_PAGE2;
|
||||
two->screen_dirty = true;
|
||||
two->scr->screen_page = EWM_A2P_SCREEN_PAGE2;
|
||||
two->scr->screen_dirty = true;
|
||||
break;
|
||||
|
||||
case EWM_A2P_SS_SETAN0:
|
||||
@ -249,28 +249,6 @@ static void ewm_two_iom_write(struct cpu_t *cpu, struct mem_t *mem, uint16_t add
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t ewm_two_screen_txt_read(struct cpu_t *cpu, struct mem_t *mem, uint16_t addr) {
|
||||
struct ewm_two_t *two = (struct ewm_two_t*) mem->obj;
|
||||
return two->screen_txt_data[addr - mem->start];
|
||||
}
|
||||
|
||||
static void ewm_two_screen_txt_write(struct cpu_t *cpu, struct mem_t *mem, uint16_t addr, uint8_t b) {
|
||||
struct ewm_two_t *two = (struct ewm_two_t*) mem->obj;
|
||||
two->screen_txt_data[addr - mem->start] = b;
|
||||
two->screen_dirty = true;
|
||||
}
|
||||
|
||||
static uint8_t ewm_two_screen_hgr_read(struct cpu_t *cpu, struct mem_t *mem, uint16_t addr) {
|
||||
struct ewm_two_t *two = (struct ewm_two_t*) mem->obj;
|
||||
return two->screen_hgr_data[addr - mem->start];
|
||||
}
|
||||
|
||||
static void ewm_two_screen_hgr_write(struct cpu_t *cpu, struct mem_t *mem, uint16_t addr, uint8_t b) {
|
||||
struct ewm_two_t *two = (struct ewm_two_t*) mem->obj;
|
||||
two->screen_hgr_data[addr - mem->start] = b;
|
||||
two->screen_dirty = true;
|
||||
}
|
||||
|
||||
static int ewm_two_init(struct ewm_two_t *two, int type, SDL_Renderer *renderer, SDL_Joystick *joystick) {
|
||||
memset(two, 0, sizeof(struct ewm_two_t));
|
||||
|
||||
@ -306,7 +284,7 @@ static int ewm_two_init(struct ewm_two_t *two, int type, SDL_Renderer *renderer,
|
||||
return -1;
|
||||
}
|
||||
|
||||
two->scr = ewm_scr_create(two, renderer);
|
||||
two->scr = ewm_scr_create(two->cpu, renderer);
|
||||
if (two->scr == NULL) {
|
||||
fprintf(stderr, "[TWO] Could not create Screen\n");
|
||||
return -1;
|
||||
@ -323,12 +301,6 @@ static int ewm_two_init(struct ewm_two_t *two, int type, SDL_Renderer *renderer,
|
||||
|
||||
// TODO Introduce ewm_scr_t that captures everything related to the apple 2 screen so that it can be re-used?
|
||||
|
||||
two->screen_txt_data = malloc(2 * 1024);
|
||||
two->screen_txt_iom = cpu_add_iom(two->cpu, 0x0400, 0x0bff, two, ewm_two_screen_txt_read, ewm_two_screen_txt_write);
|
||||
|
||||
two->screen_hgr_data = malloc(16 * 1024);
|
||||
two->screen_hgr_iom = cpu_add_iom(two->cpu, 0x2000, 0x5fff, two, ewm_two_screen_hgr_read, ewm_two_screen_hgr_write);
|
||||
|
||||
two->joystick = joystick;
|
||||
|
||||
return 0;
|
||||
@ -361,7 +333,7 @@ static bool ewm_two_poll_event(struct ewm_two_t *two, SDL_Window *window) { // T
|
||||
return false;
|
||||
|
||||
case SDL_WINDOWEVENT:
|
||||
two->screen_dirty = true;
|
||||
two->scr->screen_dirty = true;
|
||||
break;
|
||||
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
@ -595,9 +567,9 @@ int ewm_two_main(int argc, char **argv) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (two->screen_dirty) {
|
||||
if (two->scr->screen_dirty) {
|
||||
ewm_scr_update(two->scr);
|
||||
two->screen_dirty = false;
|
||||
two->scr->screen_dirty = false;
|
||||
SDL_RenderPresent(two->scr->renderer);
|
||||
}
|
||||
|
||||
|
14
src/two.h
14
src/two.h
@ -64,20 +64,6 @@ struct ewm_two_t {
|
||||
struct mem_t *roms[6];
|
||||
struct mem_t *iom;
|
||||
|
||||
// TODO Should all this move into scr_t
|
||||
uint8_t *screen_txt_data;
|
||||
struct mem_t *screen_txt_iom;
|
||||
|
||||
uint8_t *screen_hgr_data;
|
||||
struct mem_t *screen_hgr_iom;
|
||||
int screen_hgr_page;
|
||||
|
||||
int screen_mode;
|
||||
int screen_graphics_mode;
|
||||
int screen_graphics_style;
|
||||
int screen_page;
|
||||
int screen_dirty;
|
||||
|
||||
uint8_t key;
|
||||
uint8_t buttons[EWM_A2P_BUTTON_COUNT];
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user