#include #include #include #include #include #include #include #include #include #include #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; }