ironed out all broken stuff

This commit is contained in:
Polprzewodnikowy 2022-01-11 20:22:24 +01:00
parent dafa515e4f
commit dc71f45df6
20 changed files with 354 additions and 267 deletions

View File

@ -6,7 +6,7 @@ OBJDUMP = $(TOOLCHAIN)objdump
SIZE = $(TOOLCHAIN)size
FLAGS = -march=vr4300 -mtune=vr4300 -falign-functions=32 $(USER_FLAGS)
CFLAGS = -O2 -Wall -ffunction-sections -fdata-sections -ffreestanding -MMD -MP
CFLAGS = -Os -Wall -ffunction-sections -fdata-sections -ffreestanding -MMD -MP
ASFLAGS = -Wa,-I$(N64_INST)/mips64-elf/lib
LDFLAGS = -lc -nostartfiles -Wl,--gc-sections
@ -18,8 +18,11 @@ SRC_FILES = \
exception.S \
boot.c \
crc32.c \
error.c \
exception.c \
font.c \
init.c \
interrupt.c \
main.c \
sc64.c \
storage.c \

View File

@ -12,7 +12,6 @@ SECTIONS {
.flash : {
KEEP(*(.text.rom_header));
KEEP(*(.text.ipl3));
__ipl3_font = LOADADDR(.flash) + 0xB70;
} > flash
.text : {

View File

@ -93,8 +93,6 @@ bool boot_get_cic_seed_version (boot_info_t *info) {
}
void boot (boot_info_t *info) {
c0_set_status(C0_SR_CU1 | C0_SR_CU0 | C0_SR_FR);
OS_INFO->mem_size_6105 = OS_INFO->mem_size;
while (!(io_read(&SP->SR) & SP_SR_HALT));
@ -154,8 +152,10 @@ void boot (boot_info_t *info) {
stack_pointer = (void *) UNCACHED(&SP_MEM->IMEM[1020]);
asm volatile (
"mtc0 %[status], $12 \n"
"move $sp, %[stack_pointer] \n"
"jr %[entry_point] \n" ::
[status] "r" (C0_SR_CU1 | C0_SR_CU0 | C0_SR_FR),
[entry_point] "r" (entry_point),
[boot_device] "r" (boot_device),
[tv_type] "r" (tv_type),

View File

@ -32,23 +32,6 @@ typedef struct {
} boot_info_t;
typedef struct {
uint32_t tv_type;
uint32_t device_type;
uint32_t device_base;
uint32_t reset_type;
uint32_t cic_id;
uint32_t version;
uint32_t mem_size;
uint8_t app_nmi_buffer[64];
uint32_t __reserved_1[37];
uint32_t mem_size_6105;
} os_info_t;
#define OS_INFO_BASE (0x80000300UL)
#define OS_INFO ((os_info_t *) OS_INFO_BASE)
bool boot_get_tv_type (boot_info_t *info);
bool boot_get_cic_seed_version (boot_info_t *info);
void boot (boot_info_t *info);

8
sw/n64/src/error.c Normal file
View File

@ -0,0 +1,8 @@
#include "error.h"
#include "exception.h"
void error_display (const char *message) {
EXCEPTION_TRIGGER(TRIGGER_CODE_ERROR);
while (1);
}

8
sw/n64/src/error.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef ERROR_H__
#define ERROR_H__
void error_display (const char *message);
#endif

View File

@ -1,4 +1,62 @@
#include "exception.h"
#define VECTOR_LOCATION (0xA0000000UL)
#define VECTOR_SIZE (0x80)
#define VECTOR_NUM (4)
#define HIT_INVALIDATE_I ((4 << 2) | 0)
#define TICKS_PER_SECOND (93750000UL / 2)
#define WATCHDOG_TIMEOUT (10)
#define C0_COUNT $9
#define C0_COMPARE $11
#define C0_STATUS $12
#define C0_CAUSE $13
#define C0_EPC $14
#define INTERRUPT_ENABLE (1 << 0)
#define INTERRUPT_MASK_TIMER (1 << 15)
#define EXCEPTION_CODE_MASK (0x007C)
#define EXCEPTION_CODE_BIT (2)
#define INTERRUPT_PENDING_MASK (0xFF00)
#define INTERRUPT_PENDING_BIT (8)
#define INTERRUPT_PENDING_TIMER (1 << 7)
#define AT_OFFSET (8)
#define V0_OFFSET (16)
#define V1_OFFSET (24)
#define A0_OFFSET (32)
#define A1_OFFSET (40)
#define A2_OFFSET (48)
#define A3_OFFSET (56)
#define T0_OFFSET (64)
#define T1_OFFSET (72)
#define T2_OFFSET (80)
#define T3_OFFSET (88)
#define T4_OFFSET (96)
#define T5_OFFSET (104)
#define T6_OFFSET (112)
#define T7_OFFSET (120)
#define S0_OFFSET (128)
#define S1_OFFSET (136)
#define S2_OFFSET (144)
#define S3_OFFSET (152)
#define S4_OFFSET (160)
#define S5_OFFSET (168)
#define S6_OFFSET (176)
#define S7_OFFSET (184)
#define T8_OFFSET (192)
#define T9_OFFSET (200)
#define K0_OFFSET (208)
#define K1_OFFSET (216)
#define GP_OFFSET (224)
#define SP_OFFSET (232)
#define FP_OFFSET (240)
#define RA_OFFSET (248)
#define C0_STATUS_OFFSET (256)
#define C0_CAUSE_OFFSET (260)
#define C0_EPC_OFFSET (264)
#define SAVE_REGISTERS_SIZE (272)
.section .text.exception_handler
@ -42,9 +100,14 @@ exception_is_fatal:
mfc0 $a0, C0_CAUSE
sw $a0, C0_CAUSE_OFFSET($k0)
move $a1, $a0
andi $a1, EXCEPTION_CODE_MASK
srl $a1, $a1, EXCEPTION_CODE_BIT
beq $a1, $zero, exception_interrupt
andi $a0, EXCEPTION_CODE_MASK
srl $a0, $a0, EXCEPTION_CODE_BIT
andi $a1, INTERRUPT_PENDING_MASK
srl $a1, $a1, INTERRUPT_PENDING_BIT
move $t0, $a1
andi $t0, INTERRUPT_PENDING_TIMER
bne $t0, $zero, exception_fatal
beq $a0, $zero, exception_interrupt
exception_fatal:
sd $k0, K0_OFFSET($k0)
@ -55,14 +118,12 @@ exception_fatal:
sd $t0, C0_EPC_OFFSET($k0)
addiu $t0, 4
dmtc0 $t0, C0_EPC
move $a0, $k0
move $a2, $k0
la $t1, exception_fatal_handler
jalr $t1
j exception_restore
exception_interrupt:
andi $a0, INTERRUPT_PENDING_MASK
srl $a0, $a0, INTERRUPT_PENDING_BIT
la $t1, exception_interrupt_handler
jalr $t1
@ -133,4 +194,10 @@ exception_install:
bne $t4, $t5, 2b
addiu $t1, VECTOR_SIZE
bne $t1, $t2, 1b
li $t7, (WATCHDOG_TIMEOUT * TICKS_PER_SECOND)
mtc0 $zero, C0_COUNT
mtc0 $t7, C0_COMPARE
mfc0 $t7, C0_STATUS
ori $t7, (INTERRUPT_MASK_TIMER | INTERRUPT_ENABLE)
mtc0 $t7, C0_STATUS
jr $ra

View File

@ -1,30 +1,37 @@
#include <stdarg.h>
#include <stdio.h>
#include "boot.h"
#include "exception.h"
#include "sc64.h"
#include "font.h"
#include "sys.h"
extern io32_t __ipl3_font __attribute__((section(".data")));
typedef struct {
uint64_t gpr[32];
uint32_t sr;
uint32_t cr;
uint64_t epc;
} exception_t;
#define SCREEN_WIDTH (640)
#define SCREEN_HEIGHT (240)
#define EXCEPTION_INTERRUPT (0)
#define EXCEPTION_SYSCALL (8)
#define BACKGROUND_COLOR (0xFFFFFFFFUL)
#define FOREGROUND_COLOR (0x000000FFUL)
#define INTERRUPT_MASK_TIMER (1 << 7)
#define CHARACTER_WIDTH (13)
#define CHARACTER_HEIGHT (14)
#define CHARACTER_SIZE (23)
#define SYSCALL_CODE_MASK (0x03FF0000UL)
#define SYSCALL_CODE_BIT (16)
#define LINE_HEIGHT (22)
#define SCREEN_WIDTH (640)
#define SCREEN_HEIGHT (240)
#define BACKGROUND_COLOR (0x000000FFUL)
#define FOREGROUND_COLOR (0xFFFFFFFFUL)
#define LINE_HEIGHT (12)
static const vi_regs_t vi_config[] = {{
.CR = VI_CR_TYPE_32,
.MADDR = 0x00200000UL,
.H_WIDTH = SCREEN_WIDTH,
.V_INTR = 512,
.CURR_LINE = 0,
@ -39,7 +46,6 @@ static const vi_regs_t vi_config[] = {{
.V_SCALE = ((0x100 * SCREEN_HEIGHT) / 60),
}, {
.CR = VI_CR_TYPE_32,
.MADDR = 0x00200000UL,
.H_WIDTH = SCREEN_WIDTH,
.V_INTR = 512,
.CURR_LINE = 0,
@ -54,46 +60,17 @@ static const vi_regs_t vi_config[] = {{
.V_SCALE = ((0x100 * SCREEN_HEIGHT) / 60),
}};
static const uint8_t exception_font_mapping[96] = {
48, 36, 37, 38, 48, 48, 48, 39, 48, 48, 40, 41, 42, 43, 44, 45,
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 46, 48, 48, 47, 48, 48,
49, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 48, 48, 48, 48, 48,
48, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 48, 48, 48, 48, 48,
};
static io32_t *exception_framebuffer;
static uint32_t exception_font_buffer[288];
static io32_t *exception_framebuffer = (io32_t *) (0x00200000UL);
static void exception_init_screen (void) {
const vi_regs_t *cfg = &vi_config[OS_INFO->tv_type];
io32_t *src = &__ipl3_font;
uint32_t *dst = exception_font_buffer;
bool sdram_switched = sc64_get_config(CFG_ID_SDRAM_SWITCH);
if (sdram_switched) {
sc64_set_config(CFG_ID_SDRAM_SWITCH, false);
}
for (int i = 0; i < sizeof(exception_font_buffer); i += 4) {
*dst++ = pi_io_read(src++);
}
if (sdram_switched) {
sc64_set_config(CFG_ID_SDRAM_SWITCH, true);
}
exception_framebuffer = (io32_t *) (cfg->MADDR);
for (int i = 0; i < (SCREEN_WIDTH * SCREEN_HEIGHT); i++) {
io_write(exception_framebuffer + i, BACKGROUND_COLOR);
io_write(&exception_framebuffer[i], BACKGROUND_COLOR);
}
io_write(&VI->MADDR, cfg->MADDR);
io_write(&VI->MADDR, (uint32_t) (exception_framebuffer));
io_write(&VI->H_WIDTH, cfg->H_WIDTH);
io_write(&VI->V_INTR, cfg->V_INTR);
io_write(&VI->CURR_LINE, cfg->CURR_LINE);
@ -109,24 +86,20 @@ static void exception_init_screen (void) {
io_write(&VI->CR, cfg->CR);
}
static void exception_draw_character (int x, int y, char c) {
if ((c <= 32) || (c >= 127)) {
return;
if ((c < ' ') || (c > '~')) {
c = 127;
}
uint8_t index = exception_font_mapping[c - 32];
uint8_t *character = ((uint8_t *) (exception_font_buffer)) + (index * CHARACTER_SIZE);
for (int i = 0; i < (CHARACTER_WIDTH * CHARACTER_HEIGHT); i++) {
int c_x = x + (i % CHARACTER_WIDTH);
int c_y = y + (i / CHARACTER_WIDTH);
for (int i = 0; i < (FONT_WIDTH * FONT_HEIGHT); i++) {
int c_x = x + (i % FONT_WIDTH);
int c_y = y + (i / FONT_WIDTH);
if ((c_x >= SCREEN_WIDTH) || (c_y >= SCREEN_HEIGHT)) {
break;
}
if (character[i / 8] & (1 << (7 - (i % 8)))) {
if (font_data[c - ' '][i / 8] & (1 << (i % 8))) {
int screen_offset = c_x + (c_y * SCREEN_WIDTH);
io_write(&exception_framebuffer[screen_offset], FOREGROUND_COLOR);
}
@ -136,12 +109,12 @@ static void exception_draw_character (int x, int y, char c) {
static void exception_print_string (int x, int y, const char *s) {
while (*s != '\0') {
exception_draw_character(x, y, *s++);
x += CHARACTER_WIDTH;
x += FONT_WIDTH;
}
}
static void exception_print (int *x, int *y, const char* fmt, ...) {
char line[64];
char line[128];
va_list args;
va_start(args, fmt);
@ -155,6 +128,7 @@ static void exception_print (int *x, int *y, const char* fmt, ...) {
static const char *exception_get_description (uint8_t exception_code) {
switch (exception_code) {
case 0: return "Interrupt";
case 1: return "TLB Modification exception";
case 2: return "TLB Miss exception (load or instruction fetch)";
case 3: return "TLB Miss exception (store)";
@ -176,59 +150,55 @@ static const char *exception_get_description (uint8_t exception_code) {
}
typedef struct {
uint64_t gpr[32];
uint32_t sr;
uint32_t cr;
uint64_t epc;
} exception_t;
void exception_fatal_handler (exception_t *e) {
uint8_t exception_code = (uint8_t) ((e->cr & EXCEPTION_CODE_MASK) >> EXCEPTION_CODE_BIT);
const char *exception_description = exception_get_description(exception_code);
exception_init_screen();
void exception_fatal_handler (uint32_t exception_code, uint32_t interrupt_mask, exception_t *e) {
uint32_t sc64_version = pi_io_read(&SC64->VERSION);
uint32_t *instruction_address = (uint32_t *) ((uint32_t) (e->epc));
uint32_t gpr32[32];
int x = 12;
int y = 8;
if (e->cr & C0_CR_BD) {
instruction_address += 1;
}
for (int i = 0; i < 32; i++) {
gpr32[i] = (uint32_t) (e->gpr[i]);
}
int x = 12;
int y = 8;
exception_init_screen();
exception_print(&x, &y, "%s", exception_description);
exception_print(&x, &y, "pc %08lX sr %08lX cr %08lX", (uint32_t) (e->epc), e->sr, e->cr);
exception_print(&x, &y, "zr %08lX at %08lX v0 %08lX v1 %08lX", gpr32[0], gpr32[1], gpr32[2], gpr32[3]);
exception_print(&x, &y, "a0 %08lX a1 %08lX a2 %08lX a3 %08lX", gpr32[4], gpr32[5], gpr32[6], gpr32[7]);
exception_print(&x, &y, "t0 %08lX t1 %08lX t2 %08lX t3 %08lX", gpr32[8], gpr32[9], gpr32[10], gpr32[11]);
exception_print(&x, &y, "t4 %08lX t5 %08lX t6 %08lX t7 %08lX", gpr32[12], gpr32[13], gpr32[14], gpr32[15]);
exception_print(&x, &y, "s0 %08lX s1 %08lX s2 %08lX s3 %08lX", gpr32[16], gpr32[17], gpr32[18], gpr32[19]);
exception_print(&x, &y, "s4 %08lX s5 %08lX s6 %08lX s7 %08lX", gpr32[20], gpr32[21], gpr32[22], gpr32[23]);
exception_print(&x, &y, "t8 %08lX t9 %08lX k0 %08lX k1 %08lX", gpr32[24], gpr32[25], gpr32[26], gpr32[27]);
exception_print(&x, &y, "gp %08lX sp %08lX fp %08lX ra %08lX", gpr32[28], gpr32[29], gpr32[30], gpr32[31]);
exception_print(&x, &y, "SC64 VERSION: 0x%08lX (%4s)", sc64_version, (char *) (&sc64_version));
exception_print(&x, &y, "%s at pc: 0x%08lX", exception_get_description(exception_code), (uint32_t) (e->epc));
exception_print(&x, &y, "sr: 0x%08lX, cr: 0x%08lX", e->sr, e->cr);
exception_print(&x, &y, "zr: 0x%08lX, at: 0x%08lX, v0: 0x%08lX, v1: 0x%08lX", gpr32[0], gpr32[1], gpr32[2], gpr32[3]);
exception_print(&x, &y, "a0: 0x%08lX, a1: 0x%08lX, a2: 0x%08lX, a3: 0x%08lX", gpr32[4], gpr32[5], gpr32[6], gpr32[7]);
exception_print(&x, &y, "t0: 0x%08lX, t1: 0x%08lX, t2: 0x%08lX, t3: 0x%08lX", gpr32[8], gpr32[9], gpr32[10], gpr32[11]);
exception_print(&x, &y, "t4: 0x%08lX, t5: 0x%08lX, t6: 0x%08lX, t7: 0x%08lX", gpr32[12], gpr32[13], gpr32[14], gpr32[15]);
exception_print(&x, &y, "s0: 0x%08lX, s1: 0x%08lX, s2: 0x%08lX, s3: 0x%08lX", gpr32[16], gpr32[17], gpr32[18], gpr32[19]);
exception_print(&x, &y, "s4: 0x%08lX, s5: 0x%08lX, s6: 0x%08lX, s7: 0x%08lX", gpr32[20], gpr32[21], gpr32[22], gpr32[23]);
exception_print(&x, &y, "t8: 0x%08lX, t9: 0x%08lX, k0: 0x%08lX, k1: 0x%08lX", gpr32[24], gpr32[25], gpr32[26], gpr32[27]);
exception_print(&x, &y, "gp: 0x%08lX, sp: 0x%08lX, fp: 0x%08lX, ra: 0x%08lX", gpr32[28], gpr32[29], gpr32[30], gpr32[31]);
LOG_E("%s\r\n", exception_description);
LOG_E("pc: 0x%08lX, sr: 0x%08lX, cr: 0x%08lX\r\n", (uint32_t) (e->epc), e->sr, e->cr);
LOG_E("zr: 0x%08lX, at: 0x%08lX, v0: 0x%08lX, v1: 0x%08lX\r\n", gpr32[0], gpr32[1], gpr32[2], gpr32[3]);
LOG_E("a0: 0x%08lX, a1: 0x%08lX, a2: 0x%08lX, a3: 0x%08lX\r\n", gpr32[4], gpr32[5], gpr32[6], gpr32[7]);
LOG_E("t0: 0x%08lX, t1: 0x%08lX, t2: 0x%08lX, t3: 0x%08lX\r\n", gpr32[8], gpr32[9], gpr32[10], gpr32[11]);
LOG_E("t4: 0x%08lX, t5: 0x%08lX, t6: 0x%08lX, t7: 0x%08lX\r\n", gpr32[12], gpr32[13], gpr32[14], gpr32[15]);
LOG_E("s0: 0x%08lX, s1: 0x%08lX, s2: 0x%08lX, s3: 0x%08lX\r\n", gpr32[16], gpr32[17], gpr32[18], gpr32[19]);
LOG_E("s4: 0x%08lX, s5: 0x%08lX, s6: 0x%08lX, s7: 0x%08lX\r\n", gpr32[20], gpr32[21], gpr32[22], gpr32[23]);
LOG_E("t8: 0x%08lX, t9: 0x%08lX, k0: 0x%08lX, k1: 0x%08lX\r\n", gpr32[24], gpr32[25], gpr32[26], gpr32[27]);
LOG_E("gp: 0x%08lX, sp: 0x%08lX, fp: 0x%08lX, ra: 0x%08lX\r\n", gpr32[28], gpr32[29], gpr32[30], gpr32[31]);
LOG_FLUSH();
while (1);
}
void exception_interrupt_handler (uint32_t interrupt) {
LOG_I("Unimplemented interrupt, mask: 0x%08lX\r\n", interrupt);
LOG_FLUSH();
if (exception_code == EXCEPTION_INTERRUPT) {
if (interrupt_mask & INTERRUPT_MASK_TIMER) {
exception_print(&x, &y, "Bootloader did not finish within 10 seconds limit");
}
} else if (exception_code == EXCEPTION_SYSCALL) {
uint32_t code = (((*instruction_address) & SYSCALL_CODE_MASK) >> SYSCALL_CODE_BIT);
if (code == TRIGGER_CODE_ERROR) {
const char *message = (const char *) (gpr32[4]);
exception_print(&x, &y, "%s", message);
} else if (code == TRIGGER_CODE_ASSERT) {
const char *file = (const char *) (gpr32[4]);
int line = (int) (gpr32[5]);
const char *func = (const char *) (gpr32[6]);
const char *failedexpr = (const char *) (gpr32[7]);
exception_print(&x, &y, "assertion \"%s\" failed:", failedexpr);
exception_print(&x, &y, " file \"%s\", line %d, %s%s", file, line, func ? "function: " : "", func);
}
}
while (1);
}

View File

@ -2,56 +2,10 @@
#define EXCEPTION_H__
#define VECTOR_LOCATION (0xA0000000)
#define VECTOR_SIZE (0x80)
#define VECTOR_NUM (4)
#define EXCEPTION_TRIGGER(code) { asm volatile ("syscall %[c]\n" :: [c] "i" (code)); }
#define HIT_INVALIDATE_I ((4 << 2) | 0)
#define C0_STATUS $12
#define C0_CAUSE $13
#define C0_EPC $14
#define EXCEPTION_CODE_BIT (2)
#define EXCEPTION_CODE_MASK (0x007C)
#define INTERRUPT_PENDING_BIT (8)
#define INTERRUPT_PENDING_MASK (0xFF00)
#define AT_OFFSET (8)
#define V0_OFFSET (16)
#define V1_OFFSET (24)
#define A0_OFFSET (32)
#define A1_OFFSET (40)
#define A2_OFFSET (48)
#define A3_OFFSET (56)
#define T0_OFFSET (64)
#define T1_OFFSET (72)
#define T2_OFFSET (80)
#define T3_OFFSET (88)
#define T4_OFFSET (96)
#define T5_OFFSET (104)
#define T6_OFFSET (112)
#define T7_OFFSET (120)
#define S0_OFFSET (128)
#define S1_OFFSET (136)
#define S2_OFFSET (144)
#define S3_OFFSET (152)
#define S4_OFFSET (160)
#define S5_OFFSET (168)
#define S6_OFFSET (176)
#define S7_OFFSET (184)
#define T8_OFFSET (192)
#define T9_OFFSET (200)
#define K0_OFFSET (208)
#define K1_OFFSET (216)
#define GP_OFFSET (224)
#define SP_OFFSET (232)
#define FP_OFFSET (240)
#define RA_OFFSET (248)
#define C0_STATUS_OFFSET (256)
#define C0_CAUSE_OFFSET (260)
#define C0_EPC_OFFSET (264)
#define SAVE_REGISTERS_SIZE (272)
#define TRIGGER_CODE_ERROR (0)
#define TRIGGER_CODE_ASSERT (1)
#endif

View File

@ -15,7 +15,7 @@
/ and optional writing functions as well. */
#define FF_FS_MINIMIZE 1
#define FF_FS_MINIMIZE 2
/* This option defines minimization level to remove some basic API functions.
/
/ 0: Basic functions are fully enabled.
@ -34,7 +34,7 @@
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
#define FF_USE_FASTSEEK 1
#define FF_USE_FASTSEEK 0
/* This option switches fast seek function. (0:Disable or 1:Enable) */
@ -113,7 +113,7 @@
*/
#define FF_USE_LFN 2
#define FF_USE_LFN 1
#define FF_MAX_LFN 255
/* The FF_USE_LFN switches the support for LFN (long file name).
/
@ -153,7 +153,7 @@
/ on character encoding. When LFN is not enabled, these options have no effect. */
#define FF_FS_RPATH 2
#define FF_FS_RPATH 1
/* This option configures support for relative path.
/
/ 0: Disable relative path and remove related functions.

103
sw/n64/src/font.c Normal file
View File

@ -0,0 +1,103 @@
// Manually converted font "Dogica" from https://www.dafont.com/dogica.font
#include "font.h"
const uint8_t font_data[96][FONT_CHAR_BYTES] = {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x00, },
{ 0x00, 0x6C, 0x6C, 0x36, 0x00, 0x00, 0x00, 0x00, },
{ 0x00, 0x6C, 0xFE, 0x6C, 0x6C, 0xFE, 0x6C, 0x00, },
{ 0x00, 0x7C, 0xD6, 0x16, 0x7C, 0xD0, 0xD6, 0x7C, },
{ 0x62, 0x35, 0x37, 0x1A, 0x58, 0xAC, 0xEC, 0x46, },
{ 0x1C, 0x36, 0x36, 0x1C, 0xF6, 0x66, 0xFC, 0x00, },
{ 0x00, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, },
{ 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x00, },
{ 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x00, },
{ 0x00, 0x18, 0x7E, 0x3C, 0x7E, 0x18, 0x00, 0x00, },
{ 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x18, },
{ 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, },
{ 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0C, 0x0C, },
{ 0x3C, 0x66, 0x6E, 0x7E, 0x76, 0x66, 0x3C, 0x00, },
{ 0x18, 0x1E, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, },
{ 0x3C, 0x66, 0x60, 0x30, 0x18, 0x0C, 0x7E, 0x00, },
{ 0x3E, 0x60, 0x60, 0x3C, 0x60, 0x60, 0x3E, 0x00, },
{ 0x30, 0x38, 0x3C, 0x36, 0x7E, 0x30, 0x30, 0x00, },
{ 0x7E, 0x06, 0x3E, 0x60, 0x60, 0x66, 0x3C, 0x00, },
{ 0x3C, 0x66, 0x06, 0x3E, 0x66, 0x66, 0x3C, 0x00, },
{ 0x7E, 0x66, 0x60, 0x30, 0x18, 0x0C, 0x0C, 0x00, },
{ 0x3C, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0x00, },
{ 0x3C, 0x66, 0x66, 0x7C, 0x60, 0x30, 0x1C, 0x00, },
{ 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, },
{ 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x30, 0x18, },
{ 0x00, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x00, 0x00, },
{ 0x00, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0x00, 0x00, },
{ 0x00, 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0x00, },
{ 0x3C, 0x66, 0x60, 0x38, 0x0C, 0x00, 0x18, 0x00, },
{ 0x3E, 0x63, 0x7F, 0x7B, 0x3F, 0xC3, 0x7E, 0x00, },
{ 0x3C, 0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x00, },
{ 0x3E, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3E, 0x00, },
{ 0x3C, 0x66, 0x06, 0x06, 0x06, 0x66, 0x3C, 0x00, },
{ 0x3F, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x00, },
{ 0x7E, 0x06, 0x06, 0x3E, 0x06, 0x06, 0x7E, 0x00, },
{ 0x7E, 0x06, 0x06, 0x3E, 0x06, 0x06, 0x06, 0x00, },
{ 0x7C, 0x06, 0x06, 0x76, 0x66, 0x66, 0x7C, 0x00, },
{ 0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, },
{ 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, },
{ 0x3E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0E, 0x00, },
{ 0x66, 0x36, 0x1E, 0x1E, 0x36, 0x36, 0x66, 0x00, },
{ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x7C, 0x00, },
{ 0xC6, 0xC6, 0xEE, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, },
{ 0x66, 0x6E, 0x7E, 0x76, 0x66, 0x66, 0x66, 0x00, },
{ 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, },
{ 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x06, 0x00, },
{ 0x3C, 0x66, 0x66, 0x66, 0x6E, 0x36, 0x7C, 0x00, },
{ 0x3E, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x66, 0x00, },
{ 0x3C, 0x66, 0x06, 0x3C, 0x60, 0x66, 0x3C, 0x00, },
{ 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, },
{ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, },
{ 0x66, 0x66, 0x66, 0x66, 0x3C, 0x3C, 0x18, 0x00, },
{ 0xC3, 0xC3, 0xDB, 0xDB, 0xDB, 0xFF, 0x66, 0x00, },
{ 0x66, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x66, 0x00, },
{ 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x00, },
{ 0x7E, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x7E, 0x00, },
{ 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x38, 0x00, },
{ 0x0C, 0x0C, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, },
{ 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x00, },
{ 0x00, 0x38, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, },
{ 0x00, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, },
{ 0x00, 0x3C, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x00, },
{ 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x3E, 0x00, },
{ 0x00, 0x3C, 0x66, 0x06, 0x06, 0x06, 0x7C, 0x00, },
{ 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x00, },
{ 0x00, 0x3C, 0x66, 0x7E, 0x06, 0x06, 0x7C, 0x00, },
{ 0x78, 0x0C, 0x0C, 0x3E, 0x0C, 0x0C, 0x0C, 0x00, },
{ 0x00, 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x3C, },
{ 0x06, 0x06, 0x3E, 0x6E, 0x66, 0x66, 0x66, 0x00, },
{ 0x18, 0x00, 0x1C, 0x18, 0x18, 0x18, 0x3C, 0x00, },
{ 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0C, },
{ 0x00, 0x66, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x00, },
{ 0x00, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x38, 0x00, },
{ 0x00, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x00, },
{ 0x00, 0x38, 0x6E, 0x66, 0x66, 0x66, 0x66, 0x00, },
{ 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, },
{ 0x00, 0x3E, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x06, },
{ 0x00, 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, },
{ 0x00, 0x78, 0x1C, 0x0C, 0x0C, 0x0C, 0x0C, 0x00, },
{ 0x00, 0x3C, 0x06, 0x3C, 0x60, 0x66, 0x3C, 0x00, },
{ 0x0C, 0x0C, 0x7C, 0x0C, 0x0C, 0x0C, 0x78, 0x00, },
{ 0x00, 0x66, 0x66, 0x66, 0x66, 0x76, 0x7C, 0x00, },
{ 0x00, 0x66, 0x66, 0x66, 0x3C, 0x3C, 0x18, 0x00, },
{ 0x00, 0xC0, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x00, },
{ 0x00, 0x66, 0x3C, 0x18, 0x18, 0x3C, 0x66, 0x00, },
{ 0x00, 0x6C, 0x6C, 0x6C, 0x38, 0x30, 0x1C, 0x00, },
{ 0x00, 0x7C, 0x60, 0x30, 0x18, 0x0C, 0x7C, 0x00, },
{ 0x30, 0x58, 0x08, 0x0C, 0x0C, 0x08, 0x58, 0x30, },
{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, },
{ 0x18, 0x34, 0x20, 0x60, 0x60, 0x20, 0x34, 0x18, },
{ 0x00, 0x00, 0x00, 0xDC, 0x76, 0x00, 0x00, 0x00, },
{ 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, },
};

16
sw/n64/src/font.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef FONT_H__
#define FONT_H__
#include <stdint.h>
#define FONT_WIDTH (8)
#define FONT_HEIGHT (8)
#define FONT_CHAR_BYTES (8)
extern const uint8_t font_data[96][FONT_CHAR_BYTES];
#endif

View File

@ -7,6 +7,4 @@ void init (void) {
si_io_write((io32_t *) (&PIFRAM[0x3C]), pifram | 0x08);
sc64_init();
LOG_I("Initialized\r\n");
}

9
sw/n64/src/interrupt.c Normal file
View File

@ -0,0 +1,9 @@
#include "sc64.h"
void exception_interrupt_handler (uint32_t exception_code, uint32_t interrupt_mask) {
LOG_I("Unimplemented interrupt, mask: 0x%08lX\r\n", interrupt_mask);
LOG_FLUSH();
while (1);
}

View File

@ -1,4 +1,5 @@
#include "boot.h"
#include "error.h"
#include "sc64.h"
#include "storage.h"
@ -11,67 +12,45 @@ void main (void) {
sc64_get_info(&sc64_info);
LOG_I("Bootloader version: %.32s\r\n", sc64_info.bootloader_version);
switch (sc64_info.boot_mode) {
case BOOT_MODE_MENU:
LOG_I("Running menu from SD card\r\n");
storage_run_menu(STORAGE_BACKEND_SD, &boot_info, &sc64_info);
break;
case BOOT_MODE_ROM:
LOG_I("Running ROM from SDRAM\r\n");
boot_info.device_type = BOOT_DEVICE_TYPE_ROM;
break;
case BOOT_MODE_DDIPL:
LOG_I("Running DDIPL from SDRAM\r\n");
boot_info.device_type = BOOT_DEVICE_TYPE_DD;
break;
case BOOT_MODE_DIRECT:
LOG_I("Running menu from USB\r\n");
storage_run_menu(STORAGE_BACKEND_USB, &boot_info, &sc64_info);
break;
default:
LOG_E("Unknown boot mode! - %d\r\n", sc64_info.boot_mode);
while (1);
error_display("Unknown boot mode selected");
break;
}
if (sc64_info.tv_type != TV_TYPE_UNKNOWN) {
boot_info.tv_type = sc64_info.tv_type;
LOG_I("Using provided TV type: %d\r\n", boot_info.tv_type);
} else {
if (boot_get_tv_type(&boot_info)) {
LOG_I("Using TV type guessed from ROM header: %d\r\n", boot_info.tv_type);
} else {
if (!boot_get_tv_type(&boot_info)) {
boot_info.tv_type = OS_INFO->tv_type;
LOG_I("Using console TV type: %d\r\n", boot_info.tv_type);
}
}
if (sc64_info.cic_seed != 0xFFFF) {
boot_info.cic_seed = sc64_info.cic_seed & 0xFF;
boot_info.version = (sc64_info.cic_seed >> 8) & 0x01;
LOG_I("Using provided CIC seed and version: 0x%02X.%d\r\n", boot_info.cic_seed, boot_info.version);
} else {
if (boot_get_cic_seed_version(&boot_info)) {
LOG_I("Using CIC seed and version guessed from IPL3: 0x%02X.%d\r\n", boot_info.cic_seed, boot_info.version);
} else {
if (!boot_get_cic_seed_version(&boot_info)) {
boot_info.cic_seed = 0x3F;
boot_info.version = 0;
LOG_I("Using 6102/7101 CIC seed and version: 0x%02X.%d\r\n", boot_info.cic_seed, boot_info.version);
}
}
if (sc64_info.is_viewer_enabled) {
LOG_I("Initializing IS-Viewer 64\r\n");
sc64_init_is_viewer();
}
LOG_I("Booting IPL3\r\n\r\n");
LOG_FLUSH();
boot(&boot_info);
}

View File

@ -51,28 +51,6 @@ void sc64_set_config (cfg_id_t id, uint32_t value) {
}
void sc64_get_info (sc64_info_t *info) {
uint32_t tmp;
io32_t *src = (io32_t *) UNCACHED(&header_text_info);
char *dst = info->bootloader_version;
bool sdram_switched = sc64_get_config(CFG_ID_SDRAM_SWITCH);
if (sdram_switched) {
sc64_set_config(CFG_ID_SDRAM_SWITCH, false);
}
for (int i = 0; i < sizeof(info->bootloader_version); i += sizeof(uint32_t)) {
tmp = pi_io_read(src++);
*dst++ = (tmp >> 24);
*dst++ = (tmp >> 16);
*dst++ = (tmp >> 8);
*dst++ = (tmp & 0xFF);
}
if (sdram_switched) {
sc64_set_config(CFG_ID_SDRAM_SWITCH, true);
}
info->dd_enabled = (bool) sc64_get_config(CFG_ID_DD_ENABLE);
info->is_viewer_enabled = (bool) sc64_get_config(CFG_ID_IS_VIEWER_ENABLE);
info->save_type = (save_type_t) sc64_get_config(CFG_ID_SAVE_TYPE);

View File

@ -21,19 +21,6 @@
#endif
typedef struct {
io32_t SR_CMD;
io32_t DATA[2];
io32_t VERSION;
} sc64_regs_t;
#define SC64_BASE (0x1FFF0000)
#define SC64 ((sc64_regs_t *) SC64_BASE)
#define SC64_SR_CMD_ERROR (1 << 28)
#define SC64_SR_CPU_BUSY (1 << 30)
#define SC64_SR_CPU_READY (1 << 31)
#define SC64_CMD_CONFIG ('C')
#define SC64_CMD_QUERY ('Q')
#define SC64_CMD_DEBUG_RX_DATA ('E')
@ -101,14 +88,13 @@ typedef enum {
typedef struct {
bool dd_enabled;
bool is_viewer_enabled;
save_type_t save_type;
uint16_t cic_seed;
tv_type_t tv_type;
io32_t *save_location;
io32_t *ddipl_location;
boot_mode_t boot_mode;
bool is_viewer_enabled;
char bootloader_version[32];
} sc64_info_t;

View File

@ -1,29 +1,15 @@
#include "sys.h"
void c0_set_status (uint32_t status) {
asm volatile (
".set noat \n"
".set noreorder \n"
"mtc0 %[status], $12 \n"
"nop \n" ::
[status] "r" (status)
);
}
uint32_t io_read (io32_t *address) {
io32_t *uncached = UNCACHED(address);
asm volatile ("" ::: "memory");
uint32_t value = *uncached;
asm volatile ("" ::: "memory");
return value;
}
void io_write (io32_t *address, uint32_t value) {
io32_t *uncached = UNCACHED(address);
asm volatile ("" ::: "memory");
*uncached = value;
asm volatile ("" ::: "memory");
}
uint32_t pi_busy (void) {

View File

@ -46,6 +46,15 @@ typedef volatile uint32_t io32_t;
#define C0_SR_CU2 (1 << 30)
#define C0_SR_CU3 (1 << 31)
#define C0_CR_IP0 (1 << 8)
#define C0_CR_IP1 (1 << 9)
#define C0_CR_IP2 (1 << 9)
#define C0_CR_IP3 (1 << 9)
#define C0_CR_IP4 (1 << 9)
#define C0_CR_IP5 (1 << 9)
#define C0_CR_IP6 (1 << 9)
#define C0_CR_IP7 (1 << 9)
#define C0_CR_BD (1 << 31)
typedef struct {
io32_t DMEM[1024];
@ -243,6 +252,8 @@ typedef struct {
#define ROM_DDIPL_BASE (0x06000000UL)
#define ROM_DDIPL ((io32_t *) ROM_DDIPL_BASE)
#define ROM_CART_BASE (0x10000000UL)
#define ROM_CART ((io32_t *) ROM_CART_BASE)
@ -263,9 +274,37 @@ typedef struct {
#define PIFRAM ((io8_t *) PIFRAM_BASE)
void c0_set_status (uint32_t status);
uint32_t c0_get_count (void);
void wait_ms (uint32_t ms);
typedef struct {
io32_t SR_CMD;
io32_t DATA[2];
io32_t VERSION;
} sc64_regs_t;
#define SC64_BASE (0x1FFF0000)
#define SC64 ((sc64_regs_t *) SC64_BASE)
#define SC64_SR_CMD_ERROR (1 << 28)
#define SC64_SR_CPU_BUSY (1 << 30)
#define SC64_SR_CPU_READY (1 << 31)
typedef struct {
uint32_t tv_type;
uint32_t device_type;
uint32_t device_base;
uint32_t reset_type;
uint32_t cic_id;
uint32_t version;
uint32_t mem_size;
uint8_t app_nmi_buffer[64];
uint32_t __reserved_1[37];
uint32_t mem_size_6105;
} os_info_t;
#define OS_INFO_BASE (0x80000300UL)
#define OS_INFO ((os_info_t *) OS_INFO_BASE)
uint32_t io_read (io32_t *address);
void io_write (io32_t *address, uint32_t value);
uint32_t pi_busy (void);

View File

@ -3,6 +3,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "exception.h"
#include "sc64.h"
@ -21,7 +22,7 @@ int _fstat_r (struct _reent *prt, int fd, struct stat *pstat) {
}
int _isatty_r (struct _reent *prt, int fd) {
if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO){
if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) {
return 1;
}
errno = EBADF;
@ -66,6 +67,6 @@ ssize_t _write_r (struct _reent *prt, int fd, const void *buf, size_t cnt) {
}
void __assert_func (const char *file, int line, const char *func, const char *failedexpr) {
LOG_E("\r\nassertion \"%s\" failed: file \"%s\", line %d%s%s\r\n", failedexpr, file, line, func ? ", function: " : "", func ? func : "");
EXCEPTION_TRIGGER(TRIGGER_CODE_ASSERT);
while (1);
}