Started implementing the debugger.
This commit is contained in:
223
debug.cpp
Normal file
223
debug.cpp
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
#include "debug.h"
|
||||||
|
#include <SDL.h>
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "stb_image.h"
|
||||||
|
#include "parser.h"
|
||||||
|
|
||||||
|
typedef unsigned char byte;
|
||||||
|
typedef unsigned short word;
|
||||||
|
|
||||||
|
static SDL_Window* debug_window = nullptr;
|
||||||
|
static SDL_Renderer* debug_renderer = nullptr;
|
||||||
|
static SDL_Texture* debug_texture = nullptr;
|
||||||
|
static SDL_Rect src, dst;
|
||||||
|
static Uint8 ink[4];
|
||||||
|
static Uint8 paper[4];
|
||||||
|
static unsigned char* debug_mem = nullptr;
|
||||||
|
|
||||||
|
static unsigned short* rX;
|
||||||
|
static unsigned char* rY;
|
||||||
|
static unsigned char* rZ;
|
||||||
|
static unsigned short* pc;
|
||||||
|
|
||||||
|
static char* program = nullptr;
|
||||||
|
static word* lines = nullptr;
|
||||||
|
|
||||||
|
static void debug_set_ink(const unsigned char r, const unsigned char g, const unsigned char b) {
|
||||||
|
ink[0] = r; ink[1] = g; ink[2] = b; ink[3] = 255;
|
||||||
|
SDL_SetRenderDrawColor(debug_renderer, ink[0], ink[1], ink[2], ink[3]);
|
||||||
|
SDL_SetTextureColorMod(debug_texture, ink[0], ink[1], ink[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debug_set_paper(const unsigned char r, const unsigned char g, const unsigned char b) {
|
||||||
|
paper[0] = r; paper[1] = g; paper[2] = b; paper[3] = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debug_draw_char(int x, int y, int c) {
|
||||||
|
src.x = (c & 0xf) << 3; src.y = (c >> 4) << 3;
|
||||||
|
dst.x = x << 3; dst.y = y << 3;
|
||||||
|
src.w = src.h = dst.w = dst.h = 8;
|
||||||
|
SDL_RenderCopy(debug_renderer, debug_texture, &src, &dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debug_print(int x, int y, const char* text) {
|
||||||
|
while (*text != 0) {
|
||||||
|
debug_draw_char(x, y, *text);
|
||||||
|
x++;
|
||||||
|
text++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debug_print_ex(int x, int y, const unsigned char* text, int len) {
|
||||||
|
while (len != 0) {
|
||||||
|
debug_draw_char(x, y, *text);
|
||||||
|
x++; text++; len--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debug_draw_outset(int x, int y, int w, int h) {
|
||||||
|
x = (x << 3) - 1; y = (y << 3) - 1; w = (w << 3) + 2; h = (h << 3) + 2;
|
||||||
|
SDL_SetRenderDrawColor(debug_renderer, 255, 255, 255, 255);
|
||||||
|
SDL_RenderDrawLine(debug_renderer, x, y, x, y + h);
|
||||||
|
SDL_RenderDrawLine(debug_renderer, x, y, x + w, y);
|
||||||
|
SDL_SetRenderDrawColor(debug_renderer, 0, 0, 0, 255);
|
||||||
|
SDL_RenderDrawLine(debug_renderer, x + w, y, x + w, y + h);
|
||||||
|
SDL_RenderDrawLine(debug_renderer, x, y + h, x + w, y + h);
|
||||||
|
SDL_SetRenderDrawColor(debug_renderer, ink[0], ink[1], ink[2], ink[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debug_draw_inset(int x, int y, int w, int h) {
|
||||||
|
x = (x << 3) - 1; y = (y << 3) - 1; w = (w << 3) + 1; h = (h << 3) + 1;
|
||||||
|
SDL_SetRenderDrawColor(debug_renderer, 0, 0, 0, 255);
|
||||||
|
SDL_RenderDrawLine(debug_renderer, x, y, x, y + h);
|
||||||
|
SDL_RenderDrawLine(debug_renderer, x, y, x + w, y);
|
||||||
|
SDL_SetRenderDrawColor(debug_renderer, 255, 255, 255, 255);
|
||||||
|
SDL_RenderDrawLine(debug_renderer, x + w, y, x + w, y + h);
|
||||||
|
SDL_RenderDrawLine(debug_renderer, x, y + h, x + w, y + h);
|
||||||
|
SDL_SetRenderDrawColor(debug_renderer, ink[0], ink[1], ink[2], ink[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debug_draw_rect(int x, int y, int w, int h) {
|
||||||
|
dst.x = (x << 3) - 1; dst.y = (y << 3) - 1; dst.w = (w << 3) + 2; dst.h = (h << 3) + 2;
|
||||||
|
SDL_RenderDrawRect(debug_renderer, &dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debug_fill_rect(int x, int y, int w, int h) {
|
||||||
|
dst.x = x << 3; dst.y = y << 3; dst.w = w << 3; dst.h = h << 3;
|
||||||
|
SDL_RenderFillRect(debug_renderer, &dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debug_clear() {
|
||||||
|
SDL_SetRenderDrawColor(debug_renderer, paper[0], paper[1], paper[2], paper[3]);
|
||||||
|
SDL_RenderClear(debug_renderer);
|
||||||
|
SDL_SetRenderDrawColor(debug_renderer, ink[0], ink[1], ink[2], ink[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debug_draw_space(int x, int y, int w, int h, const char* title) {
|
||||||
|
debug_set_ink(64, 64, 64);
|
||||||
|
debug_fill_rect(x, y, w, h);
|
||||||
|
debug_draw_inset(x, y, w, h);
|
||||||
|
debug_set_ink(0, 0, 0);
|
||||||
|
debug_print(x, y-1, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debug_print_memory(word offset) {
|
||||||
|
debug_draw_space(1, 39, 37, 20, "MEMORY:");
|
||||||
|
debug_set_ink(255, 255, 255);
|
||||||
|
char cadena[255];
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
sprintf(cadena, "%.4X %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X", offset, debug_mem[offset], debug_mem[offset + 1], debug_mem[offset + 2], debug_mem[offset + 3], debug_mem[offset + 4], debug_mem[offset + 5], debug_mem[offset + 6], debug_mem[offset + 7]);
|
||||||
|
debug_print(1, 39+i, cadena); debug_print_ex(30, 39+i, &debug_mem[offset], 8);
|
||||||
|
offset += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debug_print_datastack(byte offset) {
|
||||||
|
debug_draw_space(72, 2, 3, 20, "DS:");
|
||||||
|
char cadena[10];
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
sprintf(cadena, "%.2X", debug_mem[0x8801 + i + offset]);
|
||||||
|
if (debug_mem[0x8800] == 1 + i + offset) debug_set_ink(255, 0, 0); else debug_set_ink(255, 255, 255);
|
||||||
|
debug_print(72, 2 + i, cadena); debug_print_ex(74, 2 + i, &debug_mem[0x8801 + i + offset], 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debug_print_callstack(byte offset) {
|
||||||
|
debug_draw_space(76, 2, 3, 20, "CS:");
|
||||||
|
char cadena[10];
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
sprintf(cadena, "%.2X", debug_mem[0x8901 + i + offset]);
|
||||||
|
if (debug_mem[0x8900] == 1 + i + offset) debug_set_ink(255, 0, 0); else debug_set_ink(255, 255, 255);
|
||||||
|
debug_print(76, 2 + i, cadena); debug_print_ex(78, 2 + i, &debug_mem[0x8901 + i + offset], 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debug_print_basic(byte offset) {
|
||||||
|
debug_draw_space(1, 2, 70, 35, "CODE:");
|
||||||
|
debug_set_ink(255, 255, 255);
|
||||||
|
int line = offset;
|
||||||
|
int row = 0;
|
||||||
|
char* prog = program;
|
||||||
|
if (lines[*pc] == line) { debug_set_ink(128, 128, 0); debug_fill_rect(1, 2 + line, 70, 1); debug_set_ink(255, 255, 0); }
|
||||||
|
else debug_set_ink(255, 255, 255);
|
||||||
|
while (line < 35 && *prog != 0) {
|
||||||
|
if (*prog == '\t') {
|
||||||
|
row += 4;
|
||||||
|
} else if (*prog == '\n') {
|
||||||
|
row = 0; line++;
|
||||||
|
if (lines[*pc] == line) { debug_set_ink(128, 128, 0); debug_fill_rect(1, 2 + line, 70, 1); debug_set_ink(255, 255, 0); }
|
||||||
|
else debug_set_ink(255, 255, 255);
|
||||||
|
} else if (*prog == 13) {
|
||||||
|
// row++;
|
||||||
|
} else {
|
||||||
|
if (row < 70) debug_draw_char(1 + row, 2 + line, *prog);
|
||||||
|
row++;
|
||||||
|
}
|
||||||
|
prog++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debug_print_registers() {
|
||||||
|
debug_draw_space(72, 23, 6, 1, "rX:");
|
||||||
|
debug_draw_space(72, 25, 3, 1, "rY:");
|
||||||
|
debug_draw_space(72, 27, 3, 1, "rZ:");
|
||||||
|
debug_set_ink(255, 255, 255);
|
||||||
|
char cadena[10];
|
||||||
|
sprintf(cadena, "%.4X", *rX);
|
||||||
|
debug_print(72, 23, cadena); debug_print_ex(76, 23, &debug_mem[0xFFFA], 2);
|
||||||
|
sprintf(cadena, "%.2X", *rY);
|
||||||
|
debug_print(72, 25, cadena); debug_print_ex(74, 25, &debug_mem[0xFFFC], 1);
|
||||||
|
sprintf(cadena, "%.2X", *rZ);
|
||||||
|
debug_print(72, 27, cadena); debug_print_ex(74, 27, &debug_mem[0xFFFD], 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void debug_init(unsigned char* mem) {
|
||||||
|
debug_mem = mem;
|
||||||
|
lines = parser_get_lines();
|
||||||
|
|
||||||
|
rX = (unsigned short*)&debug_mem[0xFFFA];
|
||||||
|
rY = &debug_mem[0xFFFC];
|
||||||
|
rZ = &debug_mem[0xFFFD];
|
||||||
|
pc = (unsigned short*)&debug_mem[0xFFFE];
|
||||||
|
|
||||||
|
debug_window = SDL_CreateWindow("Definitely PaCo Debugger", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN);
|
||||||
|
debug_renderer = SDL_CreateRenderer(debug_window, -1, SDL_RENDERER_PRESENTVSYNC);
|
||||||
|
//SDL_RenderSetLogicalSize(debug_renderer, 152, 120);
|
||||||
|
SDL_SetRenderDrawColor(debug_renderer, 128, 128, 128, 255);
|
||||||
|
|
||||||
|
FILE* f = fopen("font.png", "rb");
|
||||||
|
int x = 128, y = 128, c;
|
||||||
|
Uint8* buffer = stbi_load_from_file(f, &x, &y, &c, 4);
|
||||||
|
debug_texture = SDL_CreateTexture(debug_renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STATIC, 128, 128);
|
||||||
|
SDL_UpdateTexture(debug_texture, NULL, buffer, 128 * sizeof(Uint32));
|
||||||
|
SDL_SetTextureBlendMode(debug_texture, SDL_BLENDMODE_BLEND);
|
||||||
|
stbi_image_free(buffer);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
f = fopen("test.bas", "rb");
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
long fsize = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET); //same as rewind(f);
|
||||||
|
program = (char*)malloc(fsize + 1);
|
||||||
|
fread(program, fsize, 1, f);
|
||||||
|
fclose(f);
|
||||||
|
program[fsize] = 0;
|
||||||
|
|
||||||
|
debug_set_paper(128, 128, 128);
|
||||||
|
debug_clear();
|
||||||
|
|
||||||
|
debug_set_ink(64, 64, 64);
|
||||||
|
debug_fill_rect(39, 39, 40, 20);
|
||||||
|
debug_draw_inset(39, 39, 40, 20);
|
||||||
|
|
||||||
|
debug_set_ink(0, 0, 0);
|
||||||
|
debug_print(39, 38, "DISASSEMBLY:");
|
||||||
|
|
||||||
|
debug_print_memory(0);
|
||||||
|
debug_print_datastack(0);
|
||||||
|
debug_print_callstack(0);
|
||||||
|
debug_print_registers();
|
||||||
|
debug_print_basic(0);
|
||||||
|
|
||||||
|
SDL_RenderPresent(debug_renderer);
|
||||||
|
}
|
||||||
3
main.cpp
3
main.cpp
@@ -3,6 +3,7 @@
|
|||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
#include "vdp.h"
|
#include "vdp.h"
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
#define BTN_ANY 0
|
#define BTN_ANY 0
|
||||||
#define BTN_UP 1
|
#define BTN_UP 1
|
||||||
@@ -43,6 +44,7 @@ int main(int argc, char** argv) {
|
|||||||
vm_register_out_port(20, input_data_in);
|
vm_register_out_port(20, input_data_in);
|
||||||
vm_register_in_port(21, input_data_out);
|
vm_register_in_port(21, input_data_out);
|
||||||
|
|
||||||
|
debug_init(vm_get_memory());
|
||||||
static bool should_quit = false;
|
static bool should_quit = false;
|
||||||
static SDL_Event sdlEvent;
|
static SDL_Event sdlEvent;
|
||||||
SDL_Scancode just_pressed;
|
SDL_Scancode just_pressed;
|
||||||
@@ -51,6 +53,7 @@ int main(int argc, char** argv) {
|
|||||||
while (!should_quit) {
|
while (!should_quit) {
|
||||||
just_pressed = SDL_SCANCODE_UNKNOWN;
|
just_pressed = SDL_SCANCODE_UNKNOWN;
|
||||||
while (SDL_PollEvent(&sdlEvent)) {
|
while (SDL_PollEvent(&sdlEvent)) {
|
||||||
|
if (sdlEvent.type == SDL_WINDOWEVENT_CLOSE) { should_quit = true; break; }
|
||||||
if (sdlEvent.type == SDL_QUIT) { should_quit = true; break; }
|
if (sdlEvent.type == SDL_QUIT) { should_quit = true; break; }
|
||||||
else if (sdlEvent.type == SDL_KEYDOWN) {
|
else if (sdlEvent.type == SDL_KEYDOWN) {
|
||||||
anykey = true;
|
anykey = true;
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ struct t_constant {
|
|||||||
|
|
||||||
static byte* code; // [MAX_CODE_SIZE];
|
static byte* code; // [MAX_CODE_SIZE];
|
||||||
static word codepos = 0;
|
static word codepos = 0;
|
||||||
|
static word lines[32768];
|
||||||
|
|
||||||
static t_label known_labels[MAX_LABELS];
|
static t_label known_labels[MAX_LABELS];
|
||||||
static int num_known_labels = 0;
|
static int num_known_labels = 0;
|
||||||
@@ -85,11 +86,14 @@ static void int_to_string(int value, char* label) {
|
|||||||
/****************************************************************************************/
|
/****************************************************************************************/
|
||||||
|
|
||||||
static void emmit(const byte value) {
|
static void emmit(const byte value) {
|
||||||
|
lines[codepos] = tkn_get_line();
|
||||||
code[codepos++] = value;
|
code[codepos++] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emmit_w(const word value) {
|
static void emmit_w(const word value) {
|
||||||
|
lines[codepos] = tkn_get_line();
|
||||||
code[codepos++] = value & 255;
|
code[codepos++] = value & 255;
|
||||||
|
lines[codepos] = tkn_get_line();
|
||||||
code[codepos++] = value >> 8;
|
code[codepos++] = value >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -865,6 +869,7 @@ void parser_parse(const char* buffer, byte* mem) {
|
|||||||
|
|
||||||
const int parser_get_codesize() { return codepos; }
|
const int parser_get_codesize() { return codepos; }
|
||||||
const int parser_get_memory_usage() { return num_variables; }
|
const int parser_get_memory_usage() { return num_variables; }
|
||||||
|
unsigned short* parser_get_lines() { return lines; }
|
||||||
|
|
||||||
void parser_register_external_function(const char* name, const int num_parameters) {
|
void parser_register_external_function(const char* name, const int num_parameters) {
|
||||||
strcpy(external_functions[num_external_functions].name, name);
|
strcpy(external_functions[num_external_functions].name, name);
|
||||||
|
|||||||
2
parser.h
2
parser.h
@@ -77,5 +77,7 @@ enum OPS {
|
|||||||
void parser_parse(const char* buffer, unsigned char* mem);
|
void parser_parse(const char* buffer, unsigned char* mem);
|
||||||
const int parser_get_codesize();
|
const int parser_get_codesize();
|
||||||
const int parser_get_memory_usage();
|
const int parser_get_memory_usage();
|
||||||
|
unsigned short* parser_get_lines();
|
||||||
|
|
||||||
void parser_register_external_function(const char* name, const int num_parameters);
|
void parser_register_external_function(const char* name, const int num_parameters);
|
||||||
void parser_register_constant(const char* name, const unsigned char value);
|
void parser_register_constant(const char* name, const unsigned char value);
|
||||||
39
stack.cpp
39
stack.cpp
@@ -1,38 +1,13 @@
|
|||||||
#include "stack.h"
|
#include "stack.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
void stack_init(t_stack& stack, const int size) {
|
|
||||||
if (stack.data != nullptr) free(stack.data);
|
|
||||||
stack.data = (unsigned char*)malloc(size);
|
|
||||||
stack.max = size;
|
|
||||||
stack.top = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool stack_isempty(t_stack& stack) {
|
#define TOP stack.data[0]
|
||||||
return stack.top == -1;
|
#define PUSH(x, y) x[++x[0]] = y
|
||||||
}
|
#define POP(x) (x[x[0]--])
|
||||||
|
#define PEEK(x) (x[x[0]])
|
||||||
|
|
||||||
const bool stack_isfull(t_stack& stack) {
|
void stack_push(t_stack& stack, const unsigned char value) { stack.data[++TOP] = value; }
|
||||||
return stack.top == stack.max;
|
const unsigned char stack_pop(t_stack& stack) { return stack.data[TOP--]; }
|
||||||
}
|
const unsigned char stack_peek(t_stack& stack) { return stack.data[TOP]; }
|
||||||
|
|
||||||
void stack_push(t_stack& stack, const unsigned char value) {
|
|
||||||
if (!stack_isfull(stack)) {
|
|
||||||
stack.data[++stack.top] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned char stack_pop(t_stack& stack) {
|
|
||||||
if (!stack_isempty(stack)) {
|
|
||||||
return stack.data[stack.top--];
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned char stack_peek(t_stack& stack) {
|
|
||||||
return stack.data[stack.top];
|
|
||||||
}
|
|
||||||
|
|
||||||
void stack_delete(t_stack& stack) {
|
|
||||||
free(stack.data);
|
|
||||||
}
|
|
||||||
|
|||||||
6845
stb_image.h
Normal file
6845
stb_image.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -79,6 +79,7 @@
|
|||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="debug.cpp" />
|
||||||
<ClCompile Include="error.cpp" />
|
<ClCompile Include="error.cpp" />
|
||||||
<ClCompile Include="main.cpp" />
|
<ClCompile Include="main.cpp" />
|
||||||
<ClCompile Include="parser.cpp" />
|
<ClCompile Include="parser.cpp" />
|
||||||
@@ -89,6 +90,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="constants.h" />
|
<ClInclude Include="constants.h" />
|
||||||
|
<ClInclude Include="debug.h" />
|
||||||
<ClInclude Include="error.h" />
|
<ClInclude Include="error.h" />
|
||||||
<ClInclude Include="font.h" />
|
<ClInclude Include="font.h" />
|
||||||
<ClInclude Include="parser.h" />
|
<ClInclude Include="parser.h" />
|
||||||
|
|||||||
@@ -36,6 +36,9 @@
|
|||||||
<ClCompile Include="tokenizer.cpp">
|
<ClCompile Include="tokenizer.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="debug.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="vm.h">
|
<ClInclude Include="vm.h">
|
||||||
@@ -65,5 +68,8 @@
|
|||||||
<ClInclude Include="constants.h">
|
<ClInclude Include="constants.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="debug.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
20
vdp.cpp
20
vdp.cpp
@@ -22,19 +22,19 @@ struct t_sprite {
|
|||||||
Uint8 col = 1;
|
Uint8 col = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
SDL_Window* sdlWindow = NULL;
|
static SDL_Window* sdlWindow = NULL;
|
||||||
SDL_Renderer* sdlRenderer = NULL;
|
static SDL_Renderer* sdlRenderer = NULL;
|
||||||
SDL_Texture* sdlTexture = NULL;
|
static SDL_Texture* sdlTexture = NULL;
|
||||||
SDL_Rect src, dst;
|
static SDL_Rect src, dst;
|
||||||
const Uint8* keys = nullptr;
|
static const Uint8* keys = nullptr;
|
||||||
Uint8 just_pressed = SDL_SCANCODE_UNKNOWN;
|
static Uint8 just_pressed = SDL_SCANCODE_UNKNOWN;
|
||||||
|
|
||||||
t_sprite sprites[32];
|
static t_sprite sprites[32];
|
||||||
|
|
||||||
Uint8 screen_map[16 * 12];
|
static Uint8 screen_map[16 * 12];
|
||||||
Uint8 screen_color[16 * 12];
|
static Uint8 screen_color[16 * 12];
|
||||||
//Uint8 char_map[256 * 8];
|
//Uint8 char_map[256 * 8];
|
||||||
Uint8 screen_buffer[128 * 96 * 4];
|
static Uint8 screen_buffer[128 * 96 * 4];
|
||||||
static Uint8 cursor_x = 0;
|
static Uint8 cursor_x = 0;
|
||||||
static Uint8 cursor_y = 0;
|
static Uint8 cursor_y = 0;
|
||||||
|
|
||||||
|
|||||||
152
vm.cpp
152
vm.cpp
@@ -87,24 +87,31 @@ typedef unsigned short word;
|
|||||||
OP_SLEEP,
|
OP_SLEEP,
|
||||||
};*/
|
};*/
|
||||||
|
|
||||||
typedef void(*t_extcall)(t_stack&);
|
/*typedef void(*t_extcall)(t_stack&);
|
||||||
t_extcall external_calls[MAX_EXTERNAL_CALLS];
|
t_extcall external_calls[MAX_EXTERNAL_CALLS];
|
||||||
int numcallbacks = 0;
|
int numcallbacks = 0;*/
|
||||||
|
|
||||||
typedef void(*t_out_port)(const byte&);
|
typedef void(*t_out_port)(const byte&);
|
||||||
typedef byte(*t_in_port)();
|
typedef byte(*t_in_port)();
|
||||||
t_out_port out_ports[256];
|
static t_out_port out_ports[256];
|
||||||
t_in_port in_ports[256];
|
static t_in_port in_ports[256];
|
||||||
|
|
||||||
|
static unsigned char mem[65536];
|
||||||
|
|
||||||
|
static const unsigned char* vm_program = mem;
|
||||||
|
static unsigned char* ds = &mem[0x8800]; // data stack
|
||||||
|
static unsigned char* cs = &mem[0x8900]; // call stack
|
||||||
|
static unsigned short& rX = *(unsigned short*)&mem[0xFFFA];
|
||||||
|
static unsigned char& rY = mem[0xFFFC];
|
||||||
|
static unsigned char& rZ = mem[0xFFFD];
|
||||||
|
static unsigned short& vm_pc = *(unsigned short*)&mem[0xFFFE];
|
||||||
|
|
||||||
|
static int vm_cycles = 0;
|
||||||
|
|
||||||
|
#define PUSH(x, y) x[++x[0]] = y
|
||||||
|
#define POP(x) (x[x[0]--])
|
||||||
|
#define PEEK(x) (x[x[0]])
|
||||||
|
|
||||||
unsigned char mem[65536];
|
|
||||||
const unsigned char* vm_program = mem;
|
|
||||||
int vm_pc = 2;
|
|
||||||
int vm_cycles = 0;
|
|
||||||
t_stack vm_datastack;
|
|
||||||
t_stack vm_callstack;
|
|
||||||
unsigned short rX = 0;
|
|
||||||
unsigned char rY = 0;
|
|
||||||
unsigned char rZ = 0;
|
|
||||||
bool sleeping = false;
|
bool sleeping = false;
|
||||||
|
|
||||||
|
|
||||||
@@ -146,12 +153,7 @@ static void load_program(const char* filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void vm_init(const char* filename) {
|
void vm_init(const char* filename) {
|
||||||
vm_pc = 2; rX = rY = rZ = 0;
|
vm_pc = 2; rX = rY = rZ = 0; ds[0] = cs[0] = 0;
|
||||||
vm_datastack.data = &mem[0x8800];
|
|
||||||
vm_callstack.data = &mem[0x8900];
|
|
||||||
vm_datastack.top = vm_callstack.top = 0;
|
|
||||||
vm_datastack.max = MAX_DATA_STACK;
|
|
||||||
vm_callstack.max = MAX_CALL_STACK;
|
|
||||||
load_rom();
|
load_rom();
|
||||||
load_program(filename);
|
load_program(filename);
|
||||||
}
|
}
|
||||||
@@ -167,21 +169,21 @@ const int vm_step() {
|
|||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
|
|
||||||
case OP_NOP: vm_cycles++; break;
|
case OP_NOP: vm_cycles++; break;
|
||||||
case OP_PUSH: stack_push(vm_datastack, vm_program[vm_pc++]); vm_cycles++; break;
|
case OP_PUSH: PUSH(ds, vm_program[vm_pc++]); vm_cycles++; break;
|
||||||
case OP_POP: stack_pop(vm_datastack); vm_cycles++; break;
|
case OP_POP: POP(ds); vm_cycles++; break;
|
||||||
case OP_DUP: stack_push(vm_datastack, stack_peek(vm_datastack)); vm_cycles++; break;
|
case OP_DUP: PUSH(ds, PEEK(ds)); vm_cycles++; break;
|
||||||
case OP_SWAP: val = stack_pop(vm_datastack); val2 = stack_pop(vm_datastack); stack_push(vm_datastack, val); stack_push(vm_datastack, val2); vm_cycles++; break;
|
case OP_SWAP: val = POP(ds); val2 = POP(ds); PUSH(ds, val); PUSH(ds, val2); vm_cycles++; break;
|
||||||
case OP_LOAD: stack_push(vm_datastack, mem[WORD()]); vm_cycles++; break;
|
case OP_LOAD: PUSH(ds, mem[WORD()]); vm_cycles++; break;
|
||||||
case OP_LOADI: stack_push(vm_datastack, mem[WORD() + rY]); vm_cycles++; break;
|
case OP_LOADI: PUSH(ds, mem[WORD() + rY]); vm_cycles++; break;
|
||||||
case OP_STORE: mem[WORD()] = stack_pop(vm_datastack); vm_cycles++; break;
|
case OP_STORE: mem[WORD()] = POP(ds); vm_cycles++; break;
|
||||||
case OP_STOREI: val = stack_pop(vm_datastack); mem[WORD() + rY] = val; vm_cycles++; break;
|
case OP_STOREI: val = POP(ds); mem[WORD() + rY] = val; vm_cycles++; break;
|
||||||
case OP_LOADXY: stack_push(vm_datastack, mem[rX + rY]); vm_cycles++; break;
|
case OP_LOADXY: PUSH(ds, mem[rX + rY]); vm_cycles++; break;
|
||||||
case OP_STOREXY: mem[rX + rY] = stack_pop(vm_datastack); vm_cycles++; break;
|
case OP_STOREXY: mem[rX + rY] = POP(ds); vm_cycles++; break;
|
||||||
case OP_SETX: rX = WORD(); vm_cycles++; break;
|
case OP_SETX: rX = WORD(); vm_cycles++; break;
|
||||||
case OP_SETY: rY = stack_pop(vm_datastack); vm_cycles++; break;
|
case OP_SETY: rY = POP(ds); vm_cycles++; break;
|
||||||
case OP_SETZ: rZ = stack_pop(vm_datastack); vm_cycles++; break;
|
case OP_SETZ: rZ = POP(ds); vm_cycles++; break;
|
||||||
case OP_GETY: stack_push(vm_datastack, rY); vm_cycles++; break;
|
case OP_GETY: PUSH(ds, rY); vm_cycles++; break;
|
||||||
case OP_GETZ: stack_push(vm_datastack, rZ); vm_cycles++; break;
|
case OP_GETZ: PUSH(ds, rZ); vm_cycles++; break;
|
||||||
case OP_INCX: rX++; vm_cycles++; break;
|
case OP_INCX: rX++; vm_cycles++; break;
|
||||||
case OP_DECX: rX--; vm_cycles++; break;
|
case OP_DECX: rX--; vm_cycles++; break;
|
||||||
case OP_INCY: rY++; vm_cycles++; break;
|
case OP_INCY: rY++; vm_cycles++; break;
|
||||||
@@ -189,17 +191,17 @@ const int vm_step() {
|
|||||||
case OP_INCZ: rZ++; vm_cycles++; break;
|
case OP_INCZ: rZ++; vm_cycles++; break;
|
||||||
case OP_DECZ: rZ--; vm_cycles++; break;
|
case OP_DECZ: rZ--; vm_cycles++; break;
|
||||||
case OP_JMP: vm_pc = WORD(); vm_cycles++; break;
|
case OP_JMP: vm_pc = WORD(); vm_cycles++; break;
|
||||||
case OP_JNT: if (stack_pop(vm_datastack) == 0) { vm_pc = WORD(); } else vm_pc+=2; vm_cycles++; break;
|
case OP_JNT: if (POP(ds) == 0) { vm_pc = WORD(); } else vm_pc+=2; vm_cycles++; break;
|
||||||
case OP_JTR: if (stack_pop(vm_datastack) != 0) { vm_pc = WORD(); } else vm_pc+=2; vm_cycles++; break;
|
case OP_JTR: if (POP(ds) != 0) { vm_pc = WORD(); } else vm_pc+=2; vm_cycles++; break;
|
||||||
case OP_JSR: stack_push(vm_callstack, vm_pc + 2); stack_push(vm_callstack, rX & 255); stack_push(vm_callstack, rX >> 8); stack_push(vm_callstack, rY); stack_push(vm_callstack, rZ); vm_pc = WORD(); vm_cycles++; break;
|
case OP_JSR: PUSH(cs, vm_pc + 2); PUSH(cs, rX & 255); PUSH(cs, rX >> 8); PUSH(cs, rY); PUSH(cs, rZ); vm_pc = WORD(); vm_cycles++; break;
|
||||||
case OP_RET: rZ = stack_pop(vm_callstack); rY = stack_pop(vm_callstack); rX = (stack_pop(vm_callstack) << 8) + stack_pop(vm_callstack); vm_pc = stack_pop(vm_callstack); vm_cycles++; break;
|
case OP_RET: rZ = POP(cs); rY = POP(cs); rX = (POP(cs) << 8) + POP(cs); vm_pc = POP(cs); vm_cycles++; break;
|
||||||
case OP_CALL: external_calls[vm_program[vm_pc++]](vm_datastack); vm_cycles++; break;
|
case OP_CALL: /*external_calls[vm_program[vm_pc++]](vm_datastack); vm_cycles++;*/ break;
|
||||||
case OP_RJ: vm_pc += vm_program[vm_pc]; vm_cycles++; break;
|
case OP_RJ: vm_pc += vm_program[vm_pc]; vm_cycles++; break;
|
||||||
case OP_RB: vm_pc -= vm_program[vm_pc]+1; vm_cycles++; break;
|
case OP_RB: vm_pc -= vm_program[vm_pc]+1; vm_cycles++; break;
|
||||||
case OP_RJZ: if (stack_pop(vm_datastack) == 0) vm_pc += vm_program[vm_pc]; else vm_pc++; vm_cycles++; break;
|
case OP_RJZ: if (POP(ds) == 0) vm_pc += vm_program[vm_pc]; else vm_pc++; vm_cycles++; break;
|
||||||
case OP_RJN: if (stack_pop(vm_datastack) != 0) vm_pc += vm_program[vm_pc]; else vm_pc++; vm_cycles++; break;
|
case OP_RJN: if (POP(ds) != 0) vm_pc += vm_program[vm_pc]; else vm_pc++; vm_cycles++; break;
|
||||||
case OP_RBZ: if (stack_pop(vm_datastack) == 0) vm_pc -= vm_program[vm_pc] + 1; else vm_pc++; vm_cycles++; break;
|
case OP_RBZ: if (POP(ds) == 0) vm_pc -= vm_program[vm_pc] + 1; else vm_pc++; vm_cycles++; break;
|
||||||
case OP_RBN: if (stack_pop(vm_datastack) != 0) vm_pc -= vm_program[vm_pc] + 1; else vm_pc++; vm_cycles++; break;
|
case OP_RBN: if (POP(ds) != 0) vm_pc -= vm_program[vm_pc] + 1; else vm_pc++; vm_cycles++; break;
|
||||||
case OP_RJYZ: if (rY == 0) vm_pc += vm_program[vm_pc]; else vm_pc++; vm_cycles++; break;
|
case OP_RJYZ: if (rY == 0) vm_pc += vm_program[vm_pc]; else vm_pc++; vm_cycles++; break;
|
||||||
case OP_RJYN: if (rY != 0) vm_pc += vm_program[vm_pc]; else vm_pc++; vm_cycles++; break;
|
case OP_RJYN: if (rY != 0) vm_pc += vm_program[vm_pc]; else vm_pc++; vm_cycles++; break;
|
||||||
case OP_RBYZ: if (rY == 0) vm_pc -= vm_program[vm_pc] + 1; else vm_pc++; vm_cycles++; break;
|
case OP_RBYZ: if (rY == 0) vm_pc -= vm_program[vm_pc] + 1; else vm_pc++; vm_cycles++; break;
|
||||||
@@ -208,40 +210,40 @@ const int vm_step() {
|
|||||||
case OP_RJZN: if (rZ != 0) vm_pc += vm_program[vm_pc]; else vm_pc++; vm_cycles++; break;
|
case OP_RJZN: if (rZ != 0) vm_pc += vm_program[vm_pc]; else vm_pc++; vm_cycles++; break;
|
||||||
case OP_RBZZ: if (rZ == 0) vm_pc -= vm_program[vm_pc] + 1; else vm_pc++; vm_cycles++; break;
|
case OP_RBZZ: if (rZ == 0) vm_pc -= vm_program[vm_pc] + 1; else vm_pc++; vm_cycles++; break;
|
||||||
case OP_RBZN: if (rZ != 0) vm_pc -= vm_program[vm_pc] + 1; else vm_pc++; vm_cycles++; break;
|
case OP_RBZN: if (rZ != 0) vm_pc -= vm_program[vm_pc] + 1; else vm_pc++; vm_cycles++; break;
|
||||||
case OP_ADD: stack_push(vm_datastack, stack_pop(vm_datastack) + stack_pop(vm_datastack)); vm_cycles++; break;
|
case OP_ADD: PUSH(ds, POP(ds) + POP(ds)); vm_cycles++; break;
|
||||||
case OP_SUB: stack_push(vm_datastack, stack_pop(vm_datastack) - stack_pop(vm_datastack)); vm_cycles++; break;
|
case OP_SUB: PUSH(ds, POP(ds) - POP(ds)); vm_cycles++; break;
|
||||||
case OP_MUL: stack_push(vm_datastack, stack_pop(vm_datastack) * stack_pop(vm_datastack)); vm_cycles++; break;
|
case OP_MUL: PUSH(ds, POP(ds) * POP(ds)); vm_cycles++; break;
|
||||||
case OP_DIV: stack_push(vm_datastack, stack_pop(vm_datastack) / stack_pop(vm_datastack)); vm_cycles++; break;
|
case OP_DIV: PUSH(ds, POP(ds) / POP(ds)); vm_cycles++; break;
|
||||||
case OP_MOD: stack_push(vm_datastack, stack_pop(vm_datastack) % stack_pop(vm_datastack)); vm_cycles++; break;
|
case OP_MOD: PUSH(ds, POP(ds) % POP(ds)); vm_cycles++; break;
|
||||||
case OP_AND: stack_push(vm_datastack, stack_pop(vm_datastack) & stack_pop(vm_datastack)); vm_cycles++; break;
|
case OP_AND: PUSH(ds, POP(ds) & POP(ds)); vm_cycles++; break;
|
||||||
case OP_OR: stack_push(vm_datastack, stack_pop(vm_datastack) | stack_pop(vm_datastack)); vm_cycles++; break;
|
case OP_OR: PUSH(ds, POP(ds) | POP(ds)); vm_cycles++; break;
|
||||||
case OP_NOT: stack_push(vm_datastack, !stack_pop(vm_datastack)); vm_cycles++; break;
|
case OP_NOT: PUSH(ds, !POP(ds)); vm_cycles++; break;
|
||||||
case OP_NEG: stack_push(vm_datastack, -stack_pop(vm_datastack)); vm_cycles++; break;
|
case OP_NEG: PUSH(ds, -POP(ds)); vm_cycles++; break;
|
||||||
case OP_INC: stack_push(vm_datastack, stack_pop(vm_datastack)+1); vm_cycles++; break;
|
case OP_INC: PUSH(ds, POP(ds) + 1); vm_cycles++; break;
|
||||||
case OP_DEC: stack_push(vm_datastack, stack_pop(vm_datastack) - 1); vm_cycles++; break;
|
case OP_DEC: PUSH(ds, POP(ds) - 1); vm_cycles++; break;
|
||||||
case OP_CONCAT:
|
case OP_CONCAT:
|
||||||
val = stack_pop(vm_datastack);
|
val = POP(ds);
|
||||||
for (int i = 0; i < val; i++) stack_push(vm_callstack, stack_pop(vm_datastack));
|
for (int i = 0; i < val; i++) PUSH(cs, POP(ds));
|
||||||
val2 = stack_pop(vm_datastack);
|
val2 = POP(ds);
|
||||||
for (int i = 0; i < val; i++) stack_push(vm_datastack, stack_pop(vm_callstack));
|
for (int i = 0; i < val; i++) PUSH(ds, POP(cs));
|
||||||
stack_push(vm_datastack, val + val2);
|
PUSH(ds, val + val2);
|
||||||
vm_cycles++; break;
|
vm_cycles++; break;
|
||||||
case OP_EQ: stack_push(vm_datastack, stack_pop(vm_datastack) == stack_pop(vm_datastack)); vm_cycles++; break;
|
case OP_EQ: PUSH(ds, POP(ds) == POP(ds)); vm_cycles++; break;
|
||||||
case OP_NEQ: stack_push(vm_datastack, stack_pop(vm_datastack) != stack_pop(vm_datastack)); vm_cycles++; break;
|
case OP_NEQ: PUSH(ds, POP(ds) != POP(ds)); vm_cycles++; break;
|
||||||
case OP_LT: stack_push(vm_datastack, stack_pop(vm_datastack) < stack_pop(vm_datastack)); vm_cycles++; break;
|
case OP_LT: PUSH(ds, POP(ds) < POP(ds)); vm_cycles++; break;
|
||||||
case OP_GT: stack_push(vm_datastack, stack_pop(vm_datastack) > stack_pop(vm_datastack)); vm_cycles++; break;
|
case OP_GT: PUSH(ds, POP(ds) > POP(ds)); vm_cycles++; break;
|
||||||
case OP_LEQ: stack_push(vm_datastack, stack_pop(vm_datastack) <= stack_pop(vm_datastack)); vm_cycles++; break;
|
case OP_LEQ: PUSH(ds, POP(ds) <= POP(ds)); vm_cycles++; break;
|
||||||
case OP_GEQ: stack_push(vm_datastack, stack_pop(vm_datastack) >= stack_pop(vm_datastack)); vm_cycles++; break;
|
case OP_GEQ: PUSH(ds, POP(ds) >= POP(ds)); vm_cycles++; break;
|
||||||
case OP_IN: stack_push(vm_datastack, in_ports[vm_program[vm_pc++]]()); vm_cycles++; break;
|
case OP_IN: PUSH(ds, in_ports[vm_program[vm_pc++]]()); vm_cycles++; break;
|
||||||
case OP_OUT: out_ports[vm_program[vm_pc++]](stack_pop(vm_datastack)); vm_cycles++; break;
|
case OP_OUT: out_ports[vm_program[vm_pc++]](POP(ds)); vm_cycles++; break;
|
||||||
case OP_SLEEP: SDL_Delay(stack_pop(vm_datastack) * 1000); vm_cycles++; break;
|
case OP_SLEEP: SDL_Delay(POP(ds) * 1000); vm_cycles++; break;
|
||||||
}
|
}
|
||||||
return vm_cycles;
|
return vm_cycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_register_call(void(*callback)(t_stack&)) {
|
/*void vm_register_call(void(*callback)(t_stack&)) {
|
||||||
external_calls[numcallbacks++] = callback;
|
external_calls[numcallbacks++] = callback;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
void vm_register_in_port(const byte port, t_in_port callback) {
|
void vm_register_in_port(const byte port, t_in_port callback) {
|
||||||
in_ports[port] = callback;
|
in_ports[port] = callback;
|
||||||
@@ -253,11 +255,13 @@ void vm_register_out_port(const byte port, t_out_port callback) {
|
|||||||
|
|
||||||
void vm_call_interrupt(const char num) {
|
void vm_call_interrupt(const char num) {
|
||||||
sleeping = false;
|
sleeping = false;
|
||||||
stack_push(vm_callstack, vm_pc);
|
PUSH(cs, vm_pc);
|
||||||
stack_push(vm_callstack, rX & 255);
|
PUSH(cs, rX & 255);
|
||||||
stack_push(vm_callstack, rX >> 8);
|
PUSH(cs, rX >> 8);
|
||||||
stack_push(vm_callstack, rY);
|
PUSH(cs, rY);
|
||||||
stack_push(vm_callstack, rZ);
|
PUSH(cs, rZ);
|
||||||
vm_pc = num == 0 ? 0xFFFA : 0xFFFD;
|
vm_pc = num == 0 ? 0xFFFA : 0xFFFD;
|
||||||
vm_cycles++;
|
vm_cycles++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned char* vm_get_memory() { return mem; }
|
||||||
|
|||||||
6
vm.h
6
vm.h
@@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "stack.h"
|
//#include "stack.h"
|
||||||
|
|
||||||
void vm_init(const char* filename);
|
void vm_init(const char* filename);
|
||||||
const int vm_step();
|
const int vm_step();
|
||||||
@@ -7,4 +7,6 @@ void vm_register_in_port(const unsigned char port, unsigned char(*callback)(void
|
|||||||
void vm_register_out_port(const unsigned char port, void(*callback)(const unsigned char&));
|
void vm_register_out_port(const unsigned char port, void(*callback)(const unsigned char&));
|
||||||
void vm_call_interrupt(const char num);
|
void vm_call_interrupt(const char num);
|
||||||
|
|
||||||
void vm_register_call(void(*callback)(t_stack&));
|
unsigned char* vm_get_memory();
|
||||||
|
|
||||||
|
//void vm_register_call(void(*callback)(t_stack&));
|
||||||
|
|||||||
Reference in New Issue
Block a user