fx9860-emulator-playground/fx9860-emulator/utils.c

105 lines
3.5 KiB
C

#include "headers/utils.h"
#define STB_IMAGE_IMPLEMENTATION
#include "headers/stb_image.h"
// Prints an error (same argument format as printf)
// And stops the execution of the program
void critical_error(const char* format, ...) {
va_list args;
va_start(args, format);
printf("[Error] ");
vprintf(format, args);
va_end(args);
#ifdef USE_EMSCRIPT
emscripten_cancel_main_loop();
#endif
exit(EXIT_FAILURE);
}
// Prints the binary representation of a number
void print_binary(uint32_t x, int n) {
printf(" ");
for (int i = n - 1; i >= 0; i--) {
printf("%d", (x >> i) & 1);
}
}
// Load a character set from an image
uint8_t* load_character_set(const char* path) {
// Load the PNG image using stb_image
int width, height, channels;
unsigned char* image_data = stbi_load(path, &width, &height, &channels, STBI_rgb);
if (image_data == NULL) {
critical_error("Could not load character set %s: %s\n", path, stbi_failure_reason());
}
uint8_t* packed_data = malloc(width * height * sizeof(uint8_t));
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int index = (y * width + x);
int indexRGB = (y * width + x) * channels;
unsigned char red = image_data[indexRGB];
if (index >= width * height) critical_error("error %d", index);
packed_data[index] = red ? 0 : 1;
//printf(packed_data[index] ? "X" : " ");
}
//printf("\n");
}
// Free the allocated memory for the image data
stbi_image_free(image_data);
printf("Loaded character set %s: %dx%dx%d\n", path, width, height, channels);
return packed_data;
}
// Prints the current state of the CPU
void cpu_debug(cpu_t* cpu) {
if (cpu->pc != 0x80010070) {
uint16_t instruction = (mem_read(cpu, cpu->pc, 1) << 8) | mem_read(cpu, cpu->pc + 1, 1);
uint8_t high = (instruction >> 12) & 0x0F;
uint8_t high8 = instruction >> 8;
uint8_t low = instruction & 0x0F;
uint8_t low8 = instruction & 0xFF;
printf("[%d][0x%08X] instruction: 0x%04X -", cpu->instruction_count, cpu->pc, instruction);
print_binary(instruction, 16);
print_binary(high, 4);
print_binary(low, 4);
printf("\n");
}
else printf("[%d][0x%08X] instruction: syscall\n", cpu->instruction_count, cpu->pc);
for (int i = 0; i < 16; i++) {
int r = cpu->r[i];
if (r != 0)
printf("r%d: 0x%08X, ", i, r);
}
printf("pr: 0x%08X, cursor: %d-%d, T: %d\n", cpu->pr, cpu->disp->cursor.col, cpu->disp->cursor.row, (cpu->sr >> 31) & 1);
// printf("pr: 0x%08X, macl: 0x%08X, gbr: 0x%08X, T: %d\n", cpu->pr, cpu->macl, cpu->gbr, cpu->disp->cursor.col, cpu->disp->cursor.row, (cpu->sr >> 31) & 1);
// printf("mem: 0x%02X 0x%02X 0x%02X 0x%02X\n", mem_read(cpu, 0x00300670, 1), mem_read(cpu, 0x00300670 + 1, 1), mem_read(cpu, 0x00300670 + 2, 1), mem_read(cpu, 0x00300670 + 3, 1));
}
// Prints the current state of the VRAM
void vram_debug(cpu_t* cpu) {
for (int y = 0; y < 64; y++) {
for (int x = 0; x < 16; x++) {
for (int b = 7; b >= 0; b--) {
int id = x + y * 16;
if (id < 0 || id >= VRAM_SIZE) critical_error("error %d", id);
int bit = ((cpu->disp->vram[id] >> b) & 1) || y == 0 || y == 63 || (x == 0 && b == 7) || (x == 15 && b == 0);
printf(bit ? "_" : "X");
}
}
printf("\n");
}
printf("\n");
}