mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-28 00:14:14 +01:00
open source IPL3 support
This commit is contained in:
parent
e91adcdb59
commit
92e53fd3e5
@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
BUILDER_IMAGE="ghcr.io/polprzewodnikowy/sc64env:v1.6"
|
||||
BUILDER_IMAGE="ghcr.io/polprzewodnikowy/sc64env:v1.7"
|
||||
|
||||
pushd $(dirname $0) > /dev/null
|
||||
|
||||
|
@ -1,9 +1,14 @@
|
||||
TOOLCHAIN = $(N64_INST)/bin/mips64-elf-
|
||||
N64_BINDIR = $(N64_INST)/bin
|
||||
|
||||
TOOLCHAIN = $(N64_BINDIR)/mips64-elf-
|
||||
CC = $(TOOLCHAIN)gcc
|
||||
CXX = $(TOOLCHAIN)g++
|
||||
OBJCOPY = $(TOOLCHAIN)objcopy
|
||||
OBJDUMP = $(TOOLCHAIN)objdump
|
||||
STRIP = $(TOOLCHAIN)strip
|
||||
SIZE = $(TOOLCHAIN)size
|
||||
N64_ELFCOMPRESS = $(N64_BINDIR)/n64elfcompress
|
||||
N64_TOOL = $(N64_BINDIR)/n64tool
|
||||
PYTHON = python3
|
||||
|
||||
FLAGS = -march=vr4300 -mtune=vr4300 $(USER_FLAGS)
|
||||
@ -69,19 +74,18 @@ $(BUILD_DIR)/%.asset.o: $(BUILD_DIR)/%.asset $(ASSET_DIR)/assets.S
|
||||
|
||||
$(BUILD_DIR)/bootloader.elf: $(OBJS) N64.ld
|
||||
$(CXX) $(FLAGS) $(LDFLAGS) -TN64.ld $(OBJS) -o $@
|
||||
@$(OBJDUMP) -S $@ > $(BUILD_DIR)/bootloader.lst
|
||||
|
||||
$(BUILD_DIR)/bootloader.bin: $(BUILD_DIR)/bootloader.elf tools/finalize.py
|
||||
@$(OBJCOPY) -O binary $< $@
|
||||
@$(PYTHON) tools/finalize.py $@ > /dev/null
|
||||
|
||||
print_size: $(BUILD_DIR)/bootloader.elf
|
||||
@echo 'Size of modules:'
|
||||
@$(SIZE) -B -d -t --common $(OBJS)
|
||||
@echo 'Size of bootloader:'
|
||||
@$(SIZE) -B -d $<
|
||||
@$(SIZE) -B -d $@
|
||||
@$(OBJDUMP) -S $@ > $(BUILD_DIR)/bootloader.lst
|
||||
|
||||
all: $(BUILD_DIR)/bootloader.bin print_size
|
||||
$(BUILD_DIR)/bootloader.bin: $(BUILD_DIR)/bootloader.elf
|
||||
@$(STRIP) -s $<
|
||||
@$(N64_ELFCOMPRESS) -c 2 -o $(dir $<) $<
|
||||
@$(N64_TOOL) --title "SC64 bootloader" --output $@ --align 256 $<
|
||||
|
||||
all: $(BUILD_DIR)/bootloader.bin
|
||||
|
||||
clean:
|
||||
@rm -rf ./$(BUILD_DIR)/*
|
||||
|
@ -1,7 +1,6 @@
|
||||
MEMORY {
|
||||
ram (rwx) : org = 0x80000400, len = 1M
|
||||
framebuffer (rw) : org = 0x8026A000, len = 600k
|
||||
ram (rwx) : org = 0x80300000, len = 1M
|
||||
rom (r) : org = 0xB0000000, len = 1028k
|
||||
}
|
||||
|
||||
ENTRY(entry_handler)
|
||||
@ -10,16 +9,6 @@ __exception_stack_size = 8k;
|
||||
__stack_size = 16k;
|
||||
|
||||
SECTIONS {
|
||||
.boot : {
|
||||
KEEP(*(.text.rom_header));
|
||||
KEEP(*(.text.ipl3));
|
||||
. = ALIGN(4k);
|
||||
} > rom
|
||||
|
||||
.framebuffer (NOLOAD) : SUBALIGN(64) {
|
||||
*(.framebuffer .framebuffer.*)
|
||||
} > framebuffer
|
||||
|
||||
.text : SUBALIGN(8) {
|
||||
*(.text.entry_handler)
|
||||
*(.text .text.* .gnu.linkonce.t.*)
|
||||
@ -30,17 +19,15 @@ SECTIONS {
|
||||
_gp = . + 0x8000;
|
||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
*(.lit8 .lit4)
|
||||
} > ram AT > rom
|
||||
} > ram
|
||||
|
||||
.bss : {
|
||||
. = ALIGN(8);
|
||||
_sbss = .;
|
||||
*(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||
*(.scommon .scommon.*)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(8);
|
||||
_ebss = .;
|
||||
} > ram
|
||||
|
||||
_sheap = .;
|
||||
@ -53,6 +40,10 @@ SECTIONS {
|
||||
. += __stack_size;
|
||||
_sp = .;
|
||||
|
||||
.framebuffer (NOLOAD) : SUBALIGN(64) {
|
||||
*(.framebuffer .framebuffer.*)
|
||||
} > framebuffer
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.MIPS.*)
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "boot.h"
|
||||
#include "cic.h"
|
||||
#include "init.h"
|
||||
#include "io.h"
|
||||
#include "vr4300.h"
|
||||
|
||||
@ -29,7 +30,20 @@ static void boot_detect_cic_seed (boot_params_t *params) {
|
||||
|
||||
void boot (boot_params_t *params) {
|
||||
if (params->tv_type == BOOT_TV_TYPE_PASSTHROUGH) {
|
||||
params->tv_type = OS_INFO->tv_type;
|
||||
switch (__tv_type) {
|
||||
case INIT_TV_TYPE_PAL:
|
||||
params->tv_type = BOOT_TV_TYPE_PAL;
|
||||
break;
|
||||
case INIT_TV_TYPE_NTSC:
|
||||
params->tv_type = BOOT_TV_TYPE_NTSC;
|
||||
break;
|
||||
case INIT_TV_TYPE_MPAL:
|
||||
params->tv_type = BOOT_TV_TYPE_MPAL;
|
||||
break;
|
||||
default:
|
||||
params->tv_type = BOOT_TV_TYPE_NTSC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (params->detect_cic_seed) {
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <stdio.h>
|
||||
#include "display.h"
|
||||
#include "font.h"
|
||||
#include "init.h"
|
||||
#include "io.h"
|
||||
|
||||
|
||||
@ -163,7 +164,7 @@ void display_init (uint32_t *background) {
|
||||
if (!vi_configured) {
|
||||
vi_configured = true;
|
||||
|
||||
const vi_regs_t *cfg = &vi_config[OS_INFO->tv_type];
|
||||
const vi_regs_t *cfg = &vi_config[__tv_type];
|
||||
|
||||
cpu_io_write(&VI->MADDR, (uint32_t) (display_framebuffer));
|
||||
cpu_io_write(&VI->H_WIDTH, cfg->H_WIDTH);
|
||||
|
@ -1,15 +1,20 @@
|
||||
#include "error.h"
|
||||
#include "exception.h"
|
||||
#include "init.h"
|
||||
#include "io.h"
|
||||
#include "sc64.h"
|
||||
#include "test.h"
|
||||
|
||||
|
||||
void init (void) {
|
||||
init_tv_type_t __tv_type;
|
||||
init_reset_type_t __reset_type;
|
||||
|
||||
|
||||
void init (init_tv_type_t tv_type, init_reset_type_t reset_type) {
|
||||
sc64_error_t error;
|
||||
|
||||
uint32_t pifram = si_io_read((io32_t *) (PIFRAM_STATUS));
|
||||
si_io_write((io32_t *) (PIFRAM_STATUS), pifram | PIFRAM_TERMINATE_BOOT);
|
||||
__tv_type = tv_type;
|
||||
__reset_type = reset_type;
|
||||
|
||||
exception_install();
|
||||
|
||||
|
@ -2,7 +2,23 @@
|
||||
#define INIT_H__
|
||||
|
||||
|
||||
void init (void);
|
||||
typedef enum {
|
||||
INIT_TV_TYPE_PAL = 0,
|
||||
INIT_TV_TYPE_NTSC = 1,
|
||||
INIT_TV_TYPE_MPAL = 2,
|
||||
} init_tv_type_t;
|
||||
|
||||
typedef enum {
|
||||
INIT_RESET_TYPE_COLD = 0,
|
||||
INIT_RESET_TYPE_WARM = 1,
|
||||
} init_reset_type_t;
|
||||
|
||||
|
||||
extern init_tv_type_t __tv_type;
|
||||
extern init_reset_type_t __reset_type;
|
||||
|
||||
|
||||
void init (init_tv_type_t tv_type, init_reset_type_t reset_type);
|
||||
void deinit (void);
|
||||
|
||||
|
||||
|
@ -95,16 +95,3 @@ void pi_dma_write (io32_t *address, void *buffer, size_t length) {
|
||||
cpu_io_write(&PI->RDMA, length - 1);
|
||||
while (pi_busy());
|
||||
}
|
||||
|
||||
uint32_t si_busy (void) {
|
||||
return (cpu_io_read(&SI->SR) & (SI_SR_IO_BUSY | SI_SR_DMA_BUSY));
|
||||
}
|
||||
|
||||
uint32_t si_io_read (io32_t *address) {
|
||||
return cpu_io_read(address);
|
||||
}
|
||||
|
||||
void si_io_write (io32_t *address, uint32_t value) {
|
||||
cpu_io_write(address, value);
|
||||
while (si_busy());
|
||||
}
|
||||
|
@ -202,26 +202,6 @@ typedef struct {
|
||||
#define PI_SR_CLR_INTR (1 << 1)
|
||||
|
||||
|
||||
typedef struct {
|
||||
io32_t MADDR;
|
||||
io32_t RDMA;
|
||||
io32_t __reserved_1;
|
||||
io32_t __reserved_2;
|
||||
io32_t WDMA;
|
||||
io32_t __reserved_3;
|
||||
io32_t SR;
|
||||
} si_regs_t;
|
||||
|
||||
#define SI_BASE (0x04800000UL)
|
||||
#define SI ((si_regs_t *) SI_BASE)
|
||||
|
||||
#define SI_SR_DMA_BUSY (1 << 0)
|
||||
#define SI_SR_IO_BUSY (1 << 1)
|
||||
#define SI_SR_DMA_ERROR (1 << 3)
|
||||
#define SI_SR_INTERRUPT (1 << 12)
|
||||
#define SI_SR_CLEAR_INTERRUPT (0)
|
||||
|
||||
|
||||
#define ROM_DDIPL_BASE (0x06000000UL)
|
||||
#define ROM_DDIPL ((io32_t *) ROM_DDIPL_BASE)
|
||||
|
||||
@ -230,32 +210,6 @@ typedef struct {
|
||||
#define ROM_CART ((io32_t *) ROM_CART_BASE)
|
||||
|
||||
|
||||
#define PIFRAM_BASE (0x1FC007C0UL)
|
||||
#define PIFRAM ((io8_t *) PIFRAM_BASE)
|
||||
|
||||
#define PIFRAM_STATUS (&PIFRAM[0x3C])
|
||||
|
||||
#define PIFRAM_TERMINATE_BOOT (1 << 3)
|
||||
|
||||
|
||||
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];
|
||||
} os_info_t;
|
||||
|
||||
#define OS_INFO_BASE (0x80000300UL)
|
||||
#define OS_INFO ((os_info_t *) OS_INFO_BASE)
|
||||
|
||||
#define OS_INFO_RESET_TYPE_COLD (0)
|
||||
#define OS_INFO_RESET_TYPE_NMI (1)
|
||||
|
||||
|
||||
uint32_t c0_count (void);
|
||||
void delay_ms (int ms);
|
||||
uint32_t cpu_io_read (io32_t *address);
|
||||
@ -266,9 +220,6 @@ uint32_t pi_io_read (io32_t *address);
|
||||
void pi_io_write (io32_t *address, uint32_t value);
|
||||
void pi_dma_read (io32_t *address, void *buffer, size_t length);
|
||||
void pi_dma_write (io32_t *address, void *buffer, size_t length);
|
||||
uint32_t si_busy (void);
|
||||
uint32_t si_io_read (io32_t *address);
|
||||
void si_io_write (io32_t *address, uint32_t value);
|
||||
void cache_data_hit_writeback_invalidate (void *address, size_t length);
|
||||
void cache_data_hit_writeback (void *address, size_t length);
|
||||
void cache_inst_hit_invalidate (void *address, size_t length);
|
||||
|
@ -26,6 +26,8 @@ void main (void) {
|
||||
menu_load();
|
||||
boot_params.device_type = BOOT_DEVICE_TYPE_ROM;
|
||||
boot_params.reset_type = BOOT_RESET_TYPE_NMI;
|
||||
boot_params.cic_seed = 0x3F;
|
||||
boot_params.detect_cic_seed = false;
|
||||
break;
|
||||
|
||||
case BOOT_MODE_ROM:
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
|
||||
#define ROM_ADDRESS (0x10000000)
|
||||
#define FILL_SIZE (0x101000)
|
||||
|
||||
|
||||
static const char *fatfs_error_codes[] = {
|
||||
@ -45,43 +44,6 @@ static void fix_menu_file_size (FIL *fil) {
|
||||
fil->obj.objsize = ALIGN(f_size(fil), FF_MAX_SS);
|
||||
}
|
||||
|
||||
static void fill_remaining_menu_space (size_t menu_file_size) {
|
||||
if (menu_file_size >= FILL_SIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
sc64_error_t error;
|
||||
uint32_t rom_write_enable_restore;
|
||||
|
||||
if ((error = sc64_get_config(CFG_ID_ROM_WRITE_ENABLE, &rom_write_enable_restore)) != SC64_OK) {
|
||||
error_display("Command CONFIG_GET [CFG_ID_ROM_WRITE_ENABLE] failed: %d", error);
|
||||
}
|
||||
|
||||
if ((error = sc64_set_config(CFG_ID_ROM_WRITE_ENABLE, true)) != SC64_OK) {
|
||||
error_display("Command CONFIG_SET [CFG_ID_ROM_WRITE_ENABLE] failed: %d", error);
|
||||
}
|
||||
|
||||
uint8_t fill_buffer[4096] __attribute__((aligned(8)));
|
||||
|
||||
for (int i = 0; i < sizeof(fill_buffer); i++) {
|
||||
fill_buffer[i] = 0;
|
||||
}
|
||||
|
||||
uint32_t address = (ROM_ADDRESS + menu_file_size);
|
||||
uint32_t left = (FILL_SIZE - menu_file_size);
|
||||
|
||||
while (left > 0) {
|
||||
size_t block = (left > sizeof(fill_buffer)) ? sizeof(fill_buffer) : left;
|
||||
pi_dma_write((io32_t *) (address), fill_buffer, block);
|
||||
address += block;
|
||||
left -= block;
|
||||
}
|
||||
|
||||
if ((error = sc64_set_config(CFG_ID_ROM_WRITE_ENABLE, rom_write_enable_restore)) != SC64_OK) {
|
||||
error_display("Command CONFIG_SET [CFG_ID_ROM_WRITE_ENABLE] failed: %d", error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void menu_load (void) {
|
||||
sc64_error_t error;
|
||||
@ -106,7 +68,6 @@ void menu_load (void) {
|
||||
fix_menu_file_size(&fil);
|
||||
FF_CHECK(f_read(&fil, (void *) (ROM_ADDRESS), f_size(&fil), &bytes_read), "Could not read menu file");
|
||||
FF_CHECK((bytes_read != f_size(&fil)) ? FR_INT_ERR : FR_OK, "Read size is different than expected");
|
||||
fill_remaining_menu_space(f_size(&fil));
|
||||
FF_CHECK(f_close(&fil), "Could not close menu file");
|
||||
FF_CHECK(f_unmount(""), "Could not unmount drive");
|
||||
}
|
||||
|
@ -1,39 +1,3 @@
|
||||
#include "vr4300.h"
|
||||
|
||||
|
||||
.section .text.rom_header, "a", %progbits
|
||||
|
||||
rom_header:
|
||||
.type rom_header, %object
|
||||
|
||||
header_pi_config:
|
||||
.word 0x80371240
|
||||
|
||||
header_clock_rate:
|
||||
.word 0x0000000F
|
||||
|
||||
header_load_addr:
|
||||
.word entry_handler
|
||||
|
||||
header_sdk_version:
|
||||
.word 0x00000000
|
||||
|
||||
header_crc:
|
||||
.fill 2, 4, 0
|
||||
|
||||
.org 0x20, 0x00
|
||||
header_text_info:
|
||||
.ascii "SC64 bootloader"
|
||||
.org 0x40, 0x00
|
||||
|
||||
|
||||
.section .text.ipl3, "ax", %progbits
|
||||
|
||||
ipl3:
|
||||
.type ipl3, %function
|
||||
.incbin "header", 0x40
|
||||
|
||||
|
||||
.section .text.entry_handler, "ax", %progbits
|
||||
|
||||
entry_handler:
|
||||
@ -43,13 +7,9 @@ entry_handler:
|
||||
la $gp, _gp
|
||||
la $sp, _sp
|
||||
|
||||
bss_init:
|
||||
la $a0, _sbss
|
||||
la $a1, _ebss
|
||||
1:
|
||||
sd $zero, 0($a0)
|
||||
addiu $a0, 8
|
||||
bltu $a0, $a1, 1b
|
||||
lui $t0, 0xA400
|
||||
lbu $a0, 9($t0) # TV type
|
||||
lbu $a1, 10($t0) # Reset type
|
||||
|
||||
la $t0, init
|
||||
jalr $t0
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <stdlib.h>
|
||||
#include "display.h"
|
||||
#include "error.h"
|
||||
#include "init.h"
|
||||
#include "io.h"
|
||||
#include "sc64.h"
|
||||
#include "test.h"
|
||||
@ -224,7 +225,7 @@ bool test_check (void) {
|
||||
sc64_error_t error;
|
||||
uint32_t button_state;
|
||||
|
||||
if (OS_INFO->reset_type != OS_INFO_RESET_TYPE_COLD) {
|
||||
if (__reset_type == INIT_RESET_TYPE_WARM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1,50 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if (len(sys.argv) != 2):
|
||||
print(f'Usage: python {sys.argv[0]} file_path')
|
||||
sys.exit(1)
|
||||
|
||||
ALIGN = 1024
|
||||
CHECKSUM_SIZE = 0x101000
|
||||
|
||||
bin_file = sys.argv[1]
|
||||
|
||||
try:
|
||||
bin_data = b''
|
||||
|
||||
with open(bin_file, 'rb') as f:
|
||||
bin_data = f.read()
|
||||
|
||||
pad_size = CHECKSUM_SIZE - len(bin_data)
|
||||
|
||||
if (pad_size > 0):
|
||||
bin_data += b'\xFF' * pad_size
|
||||
with open(bin_file, 'wb') as f:
|
||||
f.write(bin_data)
|
||||
|
||||
subprocess.run(['chksum64', bin_file])
|
||||
|
||||
with open(bin_file, 'rb') as f:
|
||||
bin_data = f.read()
|
||||
|
||||
bin_data = bin_data.strip(b'\xFF')
|
||||
modulo = len(bin_data) % ALIGN
|
||||
if (modulo > 0):
|
||||
bin_data += b'\xFF' * (ALIGN - modulo)
|
||||
|
||||
with open(bin_file, 'wb') as f:
|
||||
f.write(bin_data)
|
||||
|
||||
except FileNotFoundError as e:
|
||||
print(f'Couldn\'t open file "{bin_file}" {e}')
|
||||
sys.exit(2)
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
sys.exit(3)
|
Loading…
Reference in New Issue
Block a user