Fixes #86 Create a BIOS

This commit is contained in:
Stefan Arentz 2016-12-21 21:41:19 -05:00
parent 2557b2b1d0
commit 5cc4fe6c25
10 changed files with 399 additions and 137 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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
View 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
View 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
View File

@ -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);
}

View File

@ -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];