6502-sim/present.c
2023-06-15 17:08:20 +00:00

368 lines
8.8 KiB
C

#include <stdint.h>
#include <assert.h>
#include <stdbool.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <SDL.h>
#include <SDL_events.h>
#include <SDL_rect.h>
#include <SDL_render.h>
#include <SDL_surface.h>
#include "text.h"
#include "cpu.h"
#include "instruction.h"
#include "mneumonic.h"
void render_memory(SDL_Renderer * renderer, int origin_col, int origin_row)
{
int col = 0;
int row = 0;
uint8_t mem_s[2];
int row_length = 8;
#define MEM_COLOR 0xc8, 0xc8, 0xc9
col += 5;
for (int i = 0; i < row_length; i++) {
ull_base16(mem_s, 2, i);
render_text(renderer, origin_col + col, origin_row + row,
mem_s, 2,
MEM_COLOR);
col += 3;
}
row += 1;
col = 0;
#define MEM_COLOR_2 0xff, 0xff, 0xff
for (int ix = 0xee; ix < 0x100; ix++) {
if (col == 0) {
uint8_t mem_addr_s[4];
ull_base16(mem_addr_s, 4, ix);
render_text(renderer, origin_col + col, origin_row + row,
mem_addr_s, 4,
MEM_COLOR);
col += 5;
}
ull_base16(mem_s, 2, cpu_memory[ix]);
render_text(renderer, origin_col + col, origin_row + row,
mem_s, 2,
MEM_COLOR_2);
col += 3;
if ((ix & 0x7) == 0x7) {
row += 1;
col = 0;
}
}
row += 1;
for (int ix = 0; ix < 64; ix++) {
if (col == 0) {
uint8_t mem_addr_s[4];
ull_base16(mem_addr_s, 4, 0x02dd + ix);
render_text(renderer, origin_col + col, origin_row + row,
mem_addr_s, 4,
MEM_COLOR);
col += 5;
}
ull_base16(mem_s, 2, cpu_memory[0x02dd + ix]);
render_text(renderer, origin_col + col, origin_row + row,
mem_s, 2,
MEM_COLOR_2);
col += 3;
if ((ix & 0x7) == 0x7) {
row += 1;
col = 0;
}
}
}
void render_instruction(SDL_Renderer * renderer, int origin_col, int origin_row,
uint16_t pc, uint8_t * mem, uint16_t value)
{
int col = 0;
instruction_t instruction = decode_ins[mem[0]];
uint8_t pc_s[4];
ull_base16(pc_s, 4, pc);
render_text(renderer, origin_col + col, origin_row,
pc_s, 4,
MEM_COLOR);
col += 6;
uint8_t mem_s[2];
for (int ix = 0; ix < 3; ix++) {
if (addressing_modes[instruction.mode].alen >= ix) {
ull_base16(mem_s, 2, mem[ix]);
render_text(renderer, origin_col + col, origin_row,
mem_s, 2,
MEM_COLOR);
}
col += 3;
}
col += 1;
#define INS_COLOR 0xf0, 0xdf, 0xaf
const char * opcode = opcode_string[instruction.opcode];
const char * mode = mode_string[instruction.mode];
int opcode_len = strlen(opcode);
int mode_len = strlen(mode);
render_text(renderer, origin_col + col, origin_row,
opcode, opcode_len,
INS_COLOR);
col += opcode_len + 1;
render_text(renderer, origin_col + col, origin_row,
mode, mode_len,
INS_COLOR);
col += mode_len + 1;
#define EFF_COLOR 0x7c, 0xb8, 0xbb
int value_len = 2 * addressing_modes[instruction.mode].olen;
if (value_len) {
uint8_t value_s[value_len];
ull_base16(value_s, value_len, value);
render_text(renderer, origin_col + col, origin_row,
value_s, value_len,
EFF_COLOR);
col += value_len + 1;
}
}
void render_history(SDL_Renderer * renderer, int origin_col, int origin_row)
{
#define HISTORY_COLOR 0xbb, 0x7c, 0xb8
int row = 0;
render_text(renderer, origin_col - 2, origin_row + row,
"history", 7,
HISTORY_COLOR);
row++;
for (int i = 0; i < cpu_history_len; i++) {
int ix = (cpu_history_ix - (1 + i)) & 0xffff;
render_instruction(renderer, origin_col, origin_row + row++,
cpu_history[ix].state.pc,
cpu_history[ix].pc_mem,
cpu_history[ix].value);
if (row > 15)
break;
}
}
void render_state(SDL_Renderer * renderer, int origin_col, int origin_row)
{
uint8_t pc_s[4];
uint8_t sp_s[2];
uint8_t a_s[2];
uint8_t x_s[2];
uint8_t y_s[2];
uint8_t status_s[8];
cpu_state_t state;
cpu_get_state(&state);
ull_base16(pc_s, 4, state.pc);
ull_base16(sp_s, 2, state.sp);
ull_base16(a_s, 2, state.a);
ull_base16(x_s, 2, state.x);
ull_base16(y_s, 2, state.y);
for (int i = 0; i < 8; i++) {
status_s[i] = (((state.status) >> (7 - i)) & 1) ? '1' : '0';
}
int col = 0;
#define HEADER_COLOR 0x77, 0xdd, 0x11
#define VALUE_COLOR 0xff, 0xff, 0xff
render_text(renderer, origin_col + col, origin_row,
"PC", 2,
HEADER_COLOR);
render_text(renderer, origin_col + col, origin_row + 1,
pc_s, 4,
VALUE_COLOR);
col += 2 + 3;
render_text(renderer, origin_col + col, origin_row,
"A", 1,
HEADER_COLOR);
render_text(renderer, origin_col + col, origin_row + 1,
a_s, 2,
VALUE_COLOR);
col += 2 + 1;
render_text(renderer, origin_col + col, origin_row,
"X", 1,
HEADER_COLOR);
render_text(renderer, origin_col + col, origin_row + 1,
x_s, 2,
VALUE_COLOR);
col += 2 + 1;
render_text(renderer, origin_col + col, origin_row,
"Y", 1,
HEADER_COLOR);
render_text(renderer, origin_col + col, origin_row + 1,
y_s, 2,
VALUE_COLOR);
col += 2 + 1;
render_text(renderer, origin_col + col, origin_row,
"SP", 2,
HEADER_COLOR);
render_text(renderer, origin_col + col, origin_row + 1,
sp_s, 2,
VALUE_COLOR);
col += 2 + 2;
render_text(renderer, origin_col + col, origin_row,
"NV-BDIZC", 8,
HEADER_COLOR);
render_text(renderer, origin_col + col, origin_row + 1,
status_s, 8,
VALUE_COLOR);
col += 8;
instruction_t instruction = decode_ins[cpu_memory[state.pc]];
addressing_mode_t addressing_mode = addressing_modes[instruction.mode];
uint16_t value = (addressing_mode.func)(state.pc);
render_instruction(renderer, origin_row + 2, origin_col,
state.pc,
&cpu_memory[state.pc],
value);
render_history(renderer, origin_col, origin_row + 4);
}
void render(SDL_Renderer * renderer)
{
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
render_state(renderer, 5, 3);
render_memory(renderer, 5 + 35, 3);
SDL_RenderPresent(renderer);
}
int present_main()
{
SDL_Window * window;
SDL_Renderer * renderer;
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
window = SDL_CreateWindow("cpu",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
1500,
1000,
SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
int ret = create_instruction_textures(renderer);
if (ret == -1)
return -1;
SDL_Event event;
int got_event = 1;
int freerun = 0;
uint64_t ticks;
uint64_t ins_count;
uint64_t clocks;
extern uint64_t clockticks6502;
while (1) {
SDL_PumpEvents();
while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT) != 0) {
switch (event.type) {
case SDL_QUIT:
goto quit;
break;
case SDL_KEYDOWN:
got_event = 1;
if (event.key.keysym.scancode == SDL_SCANCODE_Q)
goto quit;
if (event.key.keysym.scancode == SDL_SCANCODE_SPACE) {
freerun = 0;
cpu_step();
}
if (event.key.keysym.scancode == SDL_SCANCODE_RETURN) {
if (freerun == 0) {
ticks = SDL_GetTicks64();
ins_count = 0;
clocks = clockticks6502;
freerun = 1;
}
}
break;
case SDL_MOUSEBUTTONDOWN:
got_event = 1;
break;
case SDL_WINDOWEVENT:
got_event = 1;
break;
default:
break;
}
}
while (freerun == 1) {
cpu_state_t last_state;
cpu_get_state(&last_state);
cpu_step();
ins_count++;
cpu_state_t state;
cpu_get_state(&state);
if (last_state.pc == state.pc) {
freerun = 0;
printf("time %ju\n", SDL_GetTicks64() - ticks);
printf("ins %ju\n", ins_count);
printf("clocks %ld\n", clockticks6502 - clocks);
FILE * f = fopen("memdump.bin", "w");
assert (f != NULL);
int ret = fwrite(cpu_memory, 1, 0x10000, f);
assert (ret != -1);
fclose(f);
}
got_event = 1;
if ((ins_count % 160000) == 0)
break;
}
if (got_event) {
render(renderer);
got_event = 0;
}
//if (freerun == 1)
// SDL_Delay(1);
}
quit:
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}