#include "boot.h"
|
|
#include "cpu.h"
|
|
#include "insn.h"
|
|
#include "log.h"
|
|
#include "psx.h"
|
|
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
static const uint8_t MAGIC[0x10] = "PS-X EXE";
|
|
static const uint8_t RESERVED[0x10] = {0};
|
|
|
|
psx_header_t parse_psx_header(byte_arr_t *prgm)
|
|
{
|
|
psx_header_t header;
|
|
|
|
// TODO: Convert asserts into recoverable error
|
|
debug("Checking header struct size");
|
|
assert(sizeof header == 0x38 - 0x10);
|
|
|
|
debug("Checking program size is greater than header");
|
|
assert(prgm->size >= 0x800);
|
|
|
|
debug("Checking magic number in header");
|
|
assert(memcmp(MAGIC, prgm->data, sizeof MAGIC) == 0);
|
|
|
|
memcpy(&header, &prgm->data[sizeof MAGIC], sizeof header);
|
|
|
|
debug("Checking file size in header matches program size");
|
|
assert(header.size_file == prgm->size - 0x800);
|
|
|
|
debug("Checking A34h region is zero");
|
|
assert(memcmp(RESERVED, &prgm->data[0x38], sizeof RESERVED) == 0);
|
|
|
|
return header;
|
|
}
|
|
|
|
uint32_t translate_addr(uint32_t addr)
|
|
{
|
|
if (addr >= 0xA0000000)
|
|
{
|
|
addr = addr - 0xA0000000;
|
|
}
|
|
else if (addr >= 0x80000000)
|
|
{
|
|
addr = addr - 0x80000000;
|
|
}
|
|
|
|
return addr;
|
|
}
|
|
|
|
void boot_psx_prgm(byte_arr_t *prgm)
|
|
{
|
|
debug("Parsing program header");
|
|
|
|
psx_header_t header = parse_psx_header(prgm);
|
|
|
|
debug("Program header");
|
|
debug("size=%u bytes", header.size_file);
|
|
debug("pc=%08x, gp=%08x, sp=%08x, fp=%08x", header.pc, header.gp, header.sp, header.fp);
|
|
debug("data=%08x (%u bytes)", header.addr_data, header.size_data);
|
|
debug("bss=%08x (%u bytes)", header.addr_bss, header.size_bss);
|
|
debug("dest=%08x", header.addr_dest);
|
|
|
|
cpu_t *cpu = malloc(sizeof *cpu);
|
|
|
|
uint32_t start = translate_addr(header.addr_dest);
|
|
assert(start + header.size_file < MAIN_RAM_SIZE);
|
|
memcpy(&cpu->main_ram[start], &prgm->data[0x800], header.size_file);
|
|
|
|
cpu->pc = header.pc;
|
|
cpu->regs[REG_GP] = header.gp;
|
|
cpu->regs[REG_SP] = header.sp;
|
|
cpu->regs[REG_FP] = header.fp;
|
|
|
|
psx_t psx = {header, cpu};
|
|
|
|
while (1)
|
|
{
|
|
debug("Executing instruction at %08x", psx.cpu->pc);
|
|
|
|
const uint32_t insn = cpu_read32(cpu, psx.cpu->pc);
|
|
insn_execute(cpu, insn);
|
|
|
|
psx.cpu->pc += 1;
|
|
}
|
|
}
|