From f8ff05c79b1caa9d6972f3b28f24911de3142939 Mon Sep 17 00:00:00 2001 From: Polprzewodnikowy Date: Tue, 30 Nov 2021 00:47:35 +0100 Subject: [PATCH] progress --- .gitignore | 1 + build.sh | 18 +++++- docker_build.sh | 6 +- fw/rtl/system/sc64.sv | 7 ++- sw/n64/.gitignore | 1 - sw/n64/Makefile | 9 +-- sw/n64/N64.ld | 32 +++++----- sw/n64/blob/ipl3.bin | Bin 4032 -> 0 bytes sw/n64/src/boot.c | 24 ++++---- sw/n64/src/boot.h | 8 ++- sw/n64/src/crc32.c | 4 +- sw/n64/src/crc32.h | 2 +- sw/n64/src/main.c | 42 ++++++++++--- sw/n64/src/platform.h | 26 -------- sw/n64/src/sc64.c | 137 ++++++++++++++++++++++++++++++++--------- sw/n64/src/sc64.h | 121 ++++++++++++++++++++++++++++-------- sw/n64/src/startup.S | 55 +++++------------ sw/n64/src/sys.c | 57 +++++++++++++++++ sw/n64/src/sys.h | 123 ++++++++++++++++++++++++++++++++++++ sw/n64/src/syscalls.c | 55 +++++++++++++++++ sw/pc/sc64.py | 109 +++++++++++++++++++++++++------- sw/riscv/src/cfg.c | 33 +++++++--- sw/riscv/src/flash.c | 8 ++- sw/riscv/src/flash.h | 3 +- sw/riscv/src/startup.S | 14 ++--- sw/riscv/src/sys.h | 3 + 26 files changed, 681 insertions(+), 217 deletions(-) delete mode 100644 sw/n64/blob/ipl3.bin delete mode 100644 sw/n64/src/platform.h create mode 100644 sw/n64/src/sys.c create mode 100644 sw/n64/src/sys.h create mode 100644 sw/n64/src/syscalls.c diff --git a/.gitignore b/.gitignore index 78839cd..233ecac 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ **/.vscode +*.bak *.zip .DS_Store diff --git a/build.sh b/build.sh index 3ae8020..05fd66b 100755 --- a/build.sh +++ b/build.sh @@ -21,6 +21,8 @@ BUILT_RELEASE=false FORCE_CLEAN=false SKIP_FPGA_REBUILD=false +DEBUG_ENABLED=false +USER_FLAGS+=" -D__SC64_VERSION=\"$__SC64_VERSION\"" build_cic () { if [ "$BUILT_CIC" = true ]; then return; fi @@ -39,7 +41,7 @@ build_n64 () { if [ "$FORCE_CLEAN" = true ]; then make clean fi - make all -j USER_FLAGS="-D__SC64_VERSION=\"$__SC64_VERSION\"" + make all -j USER_FLAGS="$USER_FLAGS" popd > /dev/null BUILT_N64=true @@ -52,7 +54,7 @@ build_riscv () { if [ "$FORCE_CLEAN" = true ]; then make clean -j fi - make all USER_FLAGS="-D__SC64_VERSION=\"$__SC64_VERSION\"" + make all USER_FLAGS="$USER_FLAGS" popd > /dev/null BUILT_RISCV=true @@ -68,7 +70,11 @@ build_fpga () { if [ "$SKIP_FPGA_REBUILD" = true ] && [ -f output_files/SummerCart64.sof ]; then quartus_cpf -c SummerCart64.cof else + if [ "$DEBUG_ENABLED" = true ]; then + quartus_sh --set VERILOG_MACRO="DEBUG" ./SummerCart64.qpf + fi quartus_sh --flow compile ./SummerCart64.qpf + quartus_sh --set -remove VERILOG_MACRO="DEBUG" ./SummerCart64.qpf fi popd > /dev/null @@ -105,7 +111,7 @@ build_release () { print_usage () { echo "builder script for SummerCart64" - echo "usage: ./build.sh [cic] [n64] [riscv] [fpga] [update] [release] [-c] [-s] [--help]" + echo "usage: ./build.sh [cic] [n64] [riscv] [fpga] [update] [release] [-c] [-s] [-d] [--help]" echo "parameters:" echo " cic - assemble UltraCIC-III software" echo " n64 - compile N64 bootloader software" @@ -117,6 +123,8 @@ print_usage () { echo " - clean software compilation result directories before build" echo " -s | --skip-fpga-rebuild" echo " - do not recompile whole FPGA design if it's already done, just update software binaries" + echo " -d | --debug" + echo " - enable debug features" echo " --help - print this guide" } @@ -160,6 +168,9 @@ while test $# -gt 0; do -s|--skip-fpga-rebuild) SKIP_FPGA_REBUILD=true ;; + -d|--debug) + DEBUG_ENABLED=true + ;; --help) print_usage exit 0 @@ -174,6 +185,7 @@ while test $# -gt 0; do shift done +if [ "$DEBUG_ENABLED" = true ]; then USER_FLAGS+=" -DDEBUG"; fi if [ "$TRIGGER_CIC" = true ]; then build_cic; fi if [ "$TRIGGER_N64" = true ]; then build_n64; fi if [ "$TRIGGER_RISCV" = true ]; then build_riscv; fi diff --git a/docker_build.sh b/docker_build.sh index 38271b1..169cea1 100755 --- a/docker_build.sh +++ b/docker_build.sh @@ -3,10 +3,10 @@ GIT_SHA=$(git rev-parse --short HEAD) GIT_TAG=$(git describe --tags --exact-match 2> /dev/null) -if [ ! -z "$GIT_TAG" ]; then - __SC64_VERSION="git tag: $GIT_TAG" +if [ ! -z $GIT_TAG ]; then + __SC64_VERSION=$(printf "%.7q\ %.7q" $GIT_SHA $GIT_TAG) else - __SC64_VERSION="git sha: $GIT_SHA" + __SC64_VERSION=$(printf "%.7q\ develop" $GIT_SHA) fi docker run \ diff --git a/fw/rtl/system/sc64.sv b/fw/rtl/system/sc64.sv index b14c128..92aa772 100644 --- a/fw/rtl/system/sc64.sv +++ b/fw/rtl/system/sc64.sv @@ -33,7 +33,12 @@ package sc64; parameter bit [31:0] SC64_VER = 32'h53437632; parameter int CLOCK_FREQUENCY = 32'd100_000_000; parameter bit [31:0] CPU_RESET_VECTOR = {4'(ID_CPU_FLASH), 28'h0035800}; - parameter bit CPU_HAS_UART = 1'b0; parameter int UART_BAUD_RATE = 32'd1_000_000; +`ifdef DEBUG + parameter bit CPU_HAS_UART = 1'b1; +`else + parameter bit CPU_HAS_UART = 1'b0; +`endif + endpackage diff --git a/sw/n64/.gitignore b/sw/n64/.gitignore index 23dcf96..796b96d 100644 --- a/sw/n64/.gitignore +++ b/sw/n64/.gitignore @@ -1,2 +1 @@ /build -*.z64 diff --git a/sw/n64/Makefile b/sw/n64/Makefile index b7b497d..834cc11 100644 --- a/sw/n64/Makefile +++ b/sw/n64/Makefile @@ -6,13 +6,14 @@ OBJDUMP = $(TOOLCHAIN)objdump SIZE = $(TOOLCHAIN)size FLAGS = -march=vr4300 -mtune=vr4300 -falign-functions=32 $(USER_FLAGS) -CFLAGS = -Os -Wall -ffunction-sections -fdata-sections -ffreestanding -MMD -MP +CFLAGS = -Os -Wall -ffunction-sections -fdata-sections -ffreestanding -G 0 -MMD -MP +ASFLAGS = -Wa,-I$(N64_INST)/mips64-elf/lib LDFLAGS = -lc -nostartfiles -Wl,--gc-sections SRC_DIR = src BUILD_DIR = build -SRC_FILES = startup.S main.c sc64.c boot.c crc32.c +SRC_FILES = startup.S main.c sys.c sc64.c syscalls.c crc32.c SRCS = $(addprefix $(SRC_DIR)/, $(SRC_FILES)) OBJS = $(addprefix $(BUILD_DIR)/, $(notdir $(patsubst %,%.o,$(SRCS)))) @@ -23,7 +24,7 @@ VPATH = $(SRC_DIR) $(@info $(shell mkdir -p ./$(BUILD_DIR) &> /dev/null)) $(BUILD_DIR)/%.S.o: %.S - $(CC) -x assembler-with-cpp $(FLAGS) $(CFLAGS) -c $< -o $@ + $(CC) -x assembler-with-cpp $(FLAGS) $(ASFLAGS) $(CFLAGS) -c $< -o $@ $(BUILD_DIR)/%.c.o: %.c $(CC) $(FLAGS) $(CFLAGS) -c $< -o $@ @@ -34,8 +35,8 @@ $(BUILD_DIR)/n64boot.elf: $(OBJS) N64.ld $(BUILD_DIR)/n64boot.bin: $(BUILD_DIR)/n64boot.elf @$(OBJCOPY) -O binary $< $@ - @truncate --size=90k $@ @chksum64 $@ > /dev/null + @truncate --size=90k $@ $(BUILD_DIR)/n64boot.hex: $(BUILD_DIR)/n64boot.bin @$(OBJCOPY) -I binary -O ihex $< $@ diff --git a/sw/n64/N64.ld b/sw/n64/N64.ld index 056d014..b0e1d0a 100644 --- a/sw/n64/N64.ld +++ b/sw/n64/N64.ld @@ -5,43 +5,43 @@ MEMORY { ENTRY(entry_handler) +__stack_size = 64k; + SECTIONS { .flash : { - KEEP(*(.text.bootcode)); + KEEP(*(.text.rom_header)); + KEEP(*(.text.ipl3)); + __ipl3_font = LOADADDR(.flash) + 0xB70; } > flash .text : { *(.text.entry_handler) *(.text .text.* .gnu.linkonce.t.*) - *(.rdata .rodata .rodata.* .gnu.linkonce.r.*) - } > rdram AT > flash - - .data : { - . = ALIGN(8); - _sdata = .; + *(.rodata .rodata.* .gnu.linkonce.r.*) *(.data .data.* .gnu.linkonce.d.*) - . = ALIGN(8); - _ssdata = .; + _gp = . + 0x8000; *(.sdata .sdata.* .gnu.linkonce.s.*) *(.lit8) *(.lit4) + . = ALIGN(4); } > rdram AT > flash .bss : { - . = ALIGN(8); - _sbss = .; *(.sbss .sbss.* .gnu.linkonce.sb.*) *(.scommon .scommon.*) *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) - . = ALIGN(8); - _ebss = .; + . = ALIGN(4); } > rdram + _sheap = .; + . = ORIGIN(rdram) + LENGTH(rdram) - __stack_size; + _eheap = .; + + . += __stack_size; + _sp = .; + /DISCARD/ : { *(.MIPS.*) } - - _gp = MIN(_ssdata + 0x8000, MAX(_sdata + 0x8000, _ebss - 0x8000)); - _sp = ORIGIN(rdram) + LENGTH(rdram); } diff --git a/sw/n64/blob/ipl3.bin b/sw/n64/blob/ipl3.bin deleted file mode 100644 index a53352e1c9fd82eefafce7d6dacc80791d1155de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4032 zcmcguTWlOx8UD`9#6Ih6@T|LbHclj;b!L1?C|V=CSZE|4J1%ldL58M^MT@izMYu#r zM&cprLo?Z0#ien^5VAXnym2`pxi?Ns(SigjM|3r2V#2be0YK)pO{u<9@6b!z_KNF+eO2q7p7k?AZ!OM_d#!dGExwfx!7Fly9 zkP^16DZ8|uzJY|Y*4LD^u&mIrqbgCFbPtTkHmACYf{{tx*%8^1t_=>cKBvUi$@KNB5O==-*@@(p zI?h*6okBK{^z#%PyS7O`7yRf&`c1B7sI$xPt&YO!A3-)+0aBZHLF|FGWcJRk8+#!| zmsZTH+tz_}QVhlysjc(_aTZrUz#Mw@&N9zzHe|NeWtwy1=Dg6H|F?X`57y=-g{!6X zr96erQRRIK0-w`|=#QToTY|QgIdpub7G%&eGI-Chc>k2o{Bsxi267oA(q@jfCnJoB z_475a+J%DgS^s5BMXaHSH59RiBGypE8X~=5d~0gX&uI9A$%YO$Sc{vuOq$5Z!+F*Y z_vxD^pE7(~m+8w}_Fekyt`y@o-~T92?371a;onc2cPCr4*A*Y0_E_^qcM|O8D4m*r zqV)?RqdoEXj2C2-?XLp%Omy*qh3$kL88)D?mj8u@Ej zd>k@p>q$oLr);rO7Kf(1iAU-)WTzvM^cnUQu;6S{_{?%jJ zOo26}eS}lKw}*KLx5JxY-sw>vdYbPH-;i&KZ`oh$rSR*8B0eJzy9yS{13u#}=SV+A<3_zlj!O+u|(pU2I`y?&O+dl9+XnS&@s3T}1mL z+L=>mVV*0m4daZL!}z!yOVj_&o2)72cCy=RHaF@i&l5Ad#?=3RS~ckK-C+DGD-QD)9O z#-2*A0Surxlp$``l-0XXL{3#qzxCL6>GQ{sb1M;XMa06MEF)rxh$SMHh*;Ra4@ATg z5lciY5wS$X5)n&8ED^CVemWu^_N@olx2D;*j-73Vh z>L8r$QBzLYn}2(WxoexeGP2ERa?4;bGKl3G{gm!C{9yrGzSo^3tLNaHeF_dom>1aa zVIQzcPe2f>-TzexQ+H-Od=8RW{sp@*(fd7AFL^#*pqKSaN`-&Ty9vLB|OpgV+f^(^DR0_0bK#`)7V%NH=>HO8@O6wIV?Qz&3=Nh$aVPwxc_iL` zh|zhB8UN*f#P5Xm4KOam(DRJ-MUl0411i|$|78axW! zzYWdY=rFQZW7cE$N-5Ut6ZIJ0=1;F%@mq#GPtc8w;n|m2_uVecnsT)Lq!8XqytolB}#+h_IygzL4zjmd;-`M|s#jKZ^Bk#s$kXXD5bsH8O z-D^pAJdsjQ3MEfjj_Zc=jvBu~O0RHbIO&YlTJbX}Lr-WPLug^i(c@?A@JTC6?nz5! zFl8~mK{h-ql@-}?%<3nRVG=d?8ZX2Hbt{k znxd5*-kb|=Ojv|fk?kRkb5+Gry+XBx$7!ev=Pf0-4;tp?Vr(nSVy;zx!dmYeAIdG9 z8F=)FQ&2TW9~61HJXz_@xeJpMy%~4l^kj>2+r`tgcglEi+6wbnlHrkTYj~<+8K+q) zC)&4~vK8LN?JiB7Cil`dckzZ)x{^BIQf|-bR0wUIy|5D@;=u4O#a^dz;pMu4XD!&mFI**_bgZ; zU9t<4TvUv!azaXy9i89y6os7H5KJJ#Ah-EB&?dy~^tw@5&!HlZ>T##FW}#%I`M?9) zE)i(QJfWHm>*lX#W1FlG&;goJOU)5%#I-h)2a}E}TC(TOG#PtN*M;s4uQ*0}gS#%I zLIFQ+an*Q}JVq>ppSsZ?X(T{{+mSk8!fbOl$*wvgHgC#K^_ui(1rMKU> zb+vO&?gl}p@!RpgzLQ0{!NM=yY;$VHu{X_sI|status & 0x03); + // ((uint32_t *)cart_header_pointer)[i] = (((uint32_t *)(CART_BASE))[i]); + } return cart_header_pointer; } @@ -74,7 +80,7 @@ tv_type_t boot_get_tv_type(cart_header_t *cart_header) { } } -void boot(cart_header_t *cart_header, uint16_t cic_seed, tv_type_t tv_type) { +__attribute__((noreturn)) void bootX(cart_header_t *cart_header, uint16_t cic_seed, tv_type_t tv_type) { uint32_t is_x105_boot = (cic_seed == crc32_to_cic_seed[5].cic_seed); uint32_t is_ddipl_boot = ( (cic_seed == crc32_to_cic_seed[7].cic_seed) || @@ -140,11 +146,7 @@ void boot(cart_header_t *cart_header, uint16_t cic_seed, tv_type_t tv_type) { gpr_regs[CPU_REG_S7] = BOOT_SEED_OS_VERSION(cic_seed); gpr_regs[CPU_REG_SP] = CPU_ADDRESS_IN_REG(SP_MEM->imem[ARRAY_ITEMS(SP_MEM->imem) - 4]); gpr_regs[CPU_REG_RA] = CPU_ADDRESS_IN_REG(SP_MEM->imem[(os_tv_type == TV_PAL) ? 341 : 340]); - - // sc64_print_debug((uint32_t) gpr_regs[CPU_REG_T3], (uint32_t) gpr_regs[CPU_REG_S3], (uint32_t) gpr_regs[CPU_REG_S4]); - // sc64_print_debug((uint32_t) gpr_regs[CPU_REG_S5], (uint32_t) gpr_regs[CPU_REG_S6], (uint32_t) gpr_regs[CPU_REG_S7]); - // sc64_print_debug((uint32_t) gpr_regs[CPU_REG_SP], (uint32_t) gpr_regs[CPU_REG_RA], 0); - + // return; __asm__ ( ".set noat \n\t" ".set noreorder \n\t" @@ -175,7 +177,7 @@ void boot(cart_header_t *cart_header, uint16_t cic_seed, tv_type_t tv_type) { "nop \n\t" "ctc1 $t0, $31 \n\t" "nop \n\t" - "add $ra, $zero, %[gpr_regs] \n\t" + "move $ra, %[gpr_regs] \n\t" "ld $at, 0x08($ra) \n\t" "ld $v0, 0x10($ra) \n\t" "ld $v1, 0x18($ra) \n\t" @@ -213,6 +215,4 @@ void boot(cart_header_t *cart_header, uint16_t cic_seed, tv_type_t tv_type) { : [gpr_regs] "r" (gpr_regs) : "t0", "ra" ); - - while (1); } diff --git a/sw/n64/src/boot.h b/sw/n64/src/boot.h index 3e2a367..cb59124 100644 --- a/sw/n64/src/boot.h +++ b/sw/n64/src/boot.h @@ -39,6 +39,12 @@ struct os_boot_config_s { typedef struct os_boot_config_s os_boot_config_t; +typedef enum { + TV_PAL = 0, + TV_NTSC = 1, + TV_MPAL = 2, +} tv_type_t; + #define OS_BOOT_CONFIG_BASE (0xA0000300) #define OS_BOOT_CONFIG ((os_boot_config_t *) OS_BOOT_CONFIG_BASE) @@ -57,7 +63,7 @@ typedef struct os_boot_config_s os_boot_config_t; cart_header_t *boot_load_cart_header(void); uint16_t boot_get_cic_seed(cart_header_t *cart_header); tv_type_t boot_get_tv_type(cart_header_t *cart_header); -void boot(cart_header_t *cart_header, uint16_t cic_seed, tv_type_t tv_type); +void bootX(cart_header_t *cart_header, uint16_t cic_seed, tv_type_t tv_type); #endif diff --git a/sw/n64/src/crc32.c b/sw/n64/src/crc32.c index 6fb338c..e4ebe28 100644 --- a/sw/n64/src/crc32.c +++ b/sw/n64/src/crc32.c @@ -1,7 +1,7 @@ #include "crc32.h" -static const uint32_t crc_table[256] = { +static const uint32_t crc32_table[256] = { 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, @@ -43,7 +43,7 @@ uint32_t crc32_calculate(void *buffer, size_t length) { uint8_t *byte_pointer = (uint8_t *) buffer; while (length--) { - crc32 = (crc32 >> 8) ^ crc_table[(crc32 & 0xFF) ^ (*byte_pointer++)]; + crc32 = (crc32 >> 8) ^ crc32_table[(crc32 & 0xFF) ^ (*byte_pointer++)]; } return ~crc32; diff --git a/sw/n64/src/crc32.h b/sw/n64/src/crc32.h index a4a2940..e79a398 100644 --- a/sw/n64/src/crc32.h +++ b/sw/n64/src/crc32.h @@ -2,7 +2,7 @@ #define CRC32_H__ -#include "platform.h" +#include "sys.h" uint32_t crc32_calculate(void *buffer, size_t length); diff --git a/sw/n64/src/main.c b/sw/n64/src/main.c index 3535426..dc4f7d7 100644 --- a/sw/n64/src/main.c +++ b/sw/n64/src/main.c @@ -1,19 +1,41 @@ #include "sc64.h" -#include "boot.h" -int main(void) { - OS_BOOT_CONFIG->tv_type = TV_NTSC; +void main(void) { + sc64_init(); - while (!sc64_check_presence()); + rom_header_t header; - sc64_wait_cpu_ready(); + io32_t *src = (io32_t *) (ROM_HEADER_CART); + uint32_t *dst = (uint32_t *) (&header); - sc64_set_config(CFG_ID_SDRAM_SWITCH, true); + for (int i = 0; i < sizeof(rom_header_t); i += 4) { + *dst++ = pi_io_read(src++); + } - cart_header_t *cart_header = boot_load_cart_header(); - uint16_t cic_seed = boot_get_cic_seed(cart_header); - tv_type_t tv_type = boot_get_tv_type(cart_header); + LOG_I("Booting ROM:\r\n"); + LOG_I(" PI Config: 0x%08lX\r\n", header.pi_config); + LOG_I(" Clock rate: 0x%08lX\r\n", header.clock_rate); + LOG_I(" Load address: 0x%08lX\r\n", header.load_addr); + LOG_I(" SDK vesrion: %d.%d%c\r\n", header.sdk_version.major / 10, header.sdk_version.major % 10, header.sdk_version.minor); + LOG_I(" 1MB CRC: 0x%08lX, 0x%08lX\r\n", header.crc[0], header.crc[1]); + LOG_I(" Name: %.20s\r\n", header.name); + LOG_I(" ID: %.4s\r\n", header.id); + LOG_I(" Mask ROM version: %d\r\n", header.version); + LOG_I("\r\n"); - boot(cart_header, cic_seed, tv_type); + info_t info; + + sc64_get_info(&info); + + LOG_I("SC64 settings:\r\n"); + LOG_I(" DD enabled: %d\r\n", info.dd_enabled); + LOG_I(" Save type: %d\r\n", info.save_type); + LOG_I(" CIC seed: 0x%02X\r\n", info.cic_seed); + LOG_I(" TV type: %d\r\n", info.tv_type); + LOG_I(" Save offset: 0x%08lX\r\n", (uint32_t) info.save_offset); + LOG_I(" DD offset: 0x%08lX\r\n", (uint32_t) info.dd_offset); + LOG_I(" Boot mode: %d\r\n", info.boot_mode); + LOG_I(" Bootloader ver: %s\r\n", info.bootloader_version); + LOG_I("\r\n"); } diff --git a/sw/n64/src/platform.h b/sw/n64/src/platform.h deleted file mode 100644 index c2a8333..0000000 --- a/sw/n64/src/platform.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef PLATFORM_H__ -#define PLATFORM_H__ - - -#include -#include - -#include - - -#define BOOTLOADER_VERSION_MAJOR (1) -#define BOOTLOADER_VERSION_MINOR (0) - -#define __IO volatile - -typedef uint32_t reg_t; - -#define platform_cache_writeback(rdram, length) data_cache_hit_writeback_invalidate(rdram, length) -#define platform_cache_invalidate(rdram, length) data_cache_hit_invalidate(rdram, length) -#define platform_pi_io_write(pi, value) io_write((uint32_t) (pi), value) -#define platform_pi_io_read(pi) io_read((uint32_t) (pi)) -#define platform_pi_dma_write(rdram, pi, length) dma_write(rdram, (uint32_t) (pi), length) -#define platform_pi_dma_read(rdram, pi, length) dma_read(rdram, (uint32_t) (pi), length) - - -#endif diff --git a/sw/n64/src/sc64.c b/sw/n64/src/sc64.c index bc2bc81..cec5b81 100644 --- a/sw/n64/src/sc64.c +++ b/sw/n64/src/sc64.c @@ -1,48 +1,127 @@ +#include #include "sc64.h" -typedef struct sc64_cart_registers { - __IO reg_t SR_CMD; - __IO reg_t DATA[2]; - __IO reg_t VERSION; -} sc64_cfg_registers_t; - -#define SC64_CFG_BASE (0x1FFF0000) -#define SC64_CFG ((__IO sc64_cfg_registers_t *) SC64_CFG_BASE) - - - bool sc64_check_presence(void) { - uint32_t version = platform_pi_io_read(&SC64_CFG->VERSION); - return (version == 0x53437632); + uint32_t version = pi_io_read(&SC64->VERSION); + return (version == SC64_VERSION_2); } void sc64_wait_cpu_ready(void) { uint32_t sr; do { - sr = platform_pi_io_read(&SC64_CFG->SR_CMD); - } while (!(sr & SC64_CFG_SCR_CPU_READY)); + sr = pi_io_read(&SC64->SR_CMD); + } while (!(sr & SC64_SR_CPU_READY)); } -void sc64_wait_cpu_busy(void) { +bool sc64_wait_cpu_busy(void) { uint32_t sr; do { - sr = platform_pi_io_read(&SC64_CFG->SR_CMD); - } while (sr & SC64_CFG_SCR_CPU_BUSY); + sr = pi_io_read(&SC64->SR_CMD); + } while (sr & SC64_SR_CPU_BUSY); + return sr & SC64_SR_CMD_ERROR; } -void sc64_perform_cmd(uint8_t cmd, uint32_t *args) { - for (int i = 0; i < 2; i++) { - platform_pi_io_write(&SC64_CFG->DATA[i], args[i]); - } - platform_pi_io_write(&SC64_CFG->SR_CMD, (uint32_t) cmd); - sc64_wait_cpu_busy(); - for (int i = 0; i < 2; i++) { - args[i] = platform_pi_io_read(&SC64_CFG->DATA[i]); +bool sc64_perform_cmd(uint8_t cmd, uint32_t *args, uint32_t *result) { + pi_io_write(&SC64->DATA[0], args[0]); + pi_io_write(&SC64->DATA[1], args[1]); + pi_io_write(&SC64->SR_CMD, (uint32_t) cmd); + bool error = sc64_wait_cpu_busy(); + if (result != NULL) { + result[0] = pi_io_read(&SC64->DATA[0]); + result[1] = pi_io_read(&SC64->DATA[1]); } + return error; } -void sc64_set_config(uint32_t type, uint32_t value) { - uint32_t args[2] = { type, value }; - sc64_perform_cmd(SC64_CMD_CONFIG, args); +uint32_t sc64_get_config(cfg_id_t id) { + uint32_t args[2] = { id, 0 }; + uint32_t result[2]; + sc64_perform_cmd(SC64_CMD_QUERY, args, result); + return result[1]; +} + +void sc64_set_config(cfg_id_t id, uint32_t value) { + uint32_t args[2] = { id, value }; + sc64_perform_cmd(SC64_CMD_CONFIG, args, NULL); +} + +void sc64_get_info(info_t *info) { + io32_t *src = UNCACHED(SC64_BL_VERSION_BASE); + uint32_t *dst = (uint32_t *) info->bootloader_version; + + sc64_set_config(CFG_ID_SDRAM_SWITCH, false); + + for (int i = 0; i < sizeof(info->bootloader_version); i += sizeof(uint32_t)) { + *dst++ = pi_io_read(src++); + } + + sc64_set_config(CFG_ID_SDRAM_SWITCH, true); + + info->dd_enabled = (bool) sc64_get_config(CFG_ID_DD_ENABLE); + info->save_type = (save_type_t) sc64_get_config(CFG_ID_SAVE_TYPE); + info->cic_seed = (uint8_t) sc64_get_config(CFG_ID_CIC_SEED); + info->tv_type = (tv_type_t) sc64_get_config(CFG_ID_TV_TYPE); + info->save_offset = (io32_t *) sc64_get_config(CFG_ID_SAVE_OFFEST); + info->dd_offset = (io32_t *) sc64_get_config(CFG_ID_DD_OFFEST); + info->boot_mode = (boot_mode_t) sc64_get_config(CFG_ID_BOOT_MODE); +} + +void sc64_wait_usb_tx_ready(void) { + uint32_t args[2] = { 0, 0 }; + uint32_t result[2]; + do { + sc64_perform_cmd(SC64_CMD_DEBUG_TX_READY, args, result); + } while (!result[0]); +} + +void sc64_usb_tx_data(io32_t *address, uint32_t length) { + uint32_t args[2] = { (uint32_t) (address), length }; + sc64_perform_cmd(SC64_CMD_DEBUG_TX_DATA, args, NULL); +} + +void sc64_debug_write(uint8_t type, const void *data, uint32_t len) { + char *dma = "DMA@"; + char *cmp = "CMPH"; + + io32_t *sdram = UNCACHED(SC64_DEBUG_WRITE_ADDRESS); + + io32_t *src = (io32_t *) (data); + io32_t *dst = sdram; + + uint32_t copy_length = ALIGN(len, 4); + uint32_t transfer_length = 4 + 4 + copy_length + 4; + + bool writable = sc64_get_config(CFG_ID_SDRAM_WRITABLE); + + sc64_wait_usb_tx_ready(); + + if (!writable) { + sc64_set_config(CFG_ID_SDRAM_WRITABLE, true); + } + + pi_io_write(dst++, *((uint32_t *) (dma))); + pi_io_write(dst++, (type << 24) | len); + + for (uint32_t i = 0; i < copy_length; i += 4) { + pi_io_write(dst++, *src++); + } + + pi_io_write(dst++, *((uint32_t *) (cmp))); + + if (!writable) { + sc64_set_config(CFG_ID_SDRAM_WRITABLE, false); + } + + sc64_usb_tx_data(sdram, transfer_length); +} + +void sc64_debug_print(const char *text) { + sc64_debug_write(SC64_DEBUG_TYPE_TEXT, text, strlen(text)); +} + +void sc64_init(void) { + while (!sc64_check_presence()); + sc64_wait_cpu_ready(); + sc64_set_config(CFG_ID_SDRAM_SWITCH, true); } diff --git a/sw/n64/src/sc64.h b/sw/n64/src/sc64.h index 6c98447..de62173 100644 --- a/sw/n64/src/sc64.h +++ b/sw/n64/src/sc64.h @@ -2,16 +2,55 @@ #define SC64_H__ -#include "platform.h" +#include +#include +#include "sys.h" -#define SC64_CFG_SCR_CPU_READY (1 << 31) -#define SC64_CFG_SCR_CPU_BUSY (1 << 30) +#ifdef DEBUG +#include +#define LOG_I(args...) {iprintf("\033[32m" args);} +#define LOG_E(args...) {iprintf("\033[31m" args);} +#else +#define LOG_I(args...) +#define LOG_E(args...) +#define assert(expr) +#endif -#define SC64_CMD_CONFIG 'C' -#define SC64_CMD_QUERY 'Q' -enum cfg_id { +extern char *header_text_info; + +#define SC64_BL_VERSION_BASE (PHYSICAL((io32_t *) (header_text_info))) + + +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_TX_DATA ('D') +#define SC64_CMD_DEBUG_TX_READY ('S') + +#define SC64_VERSION_2 (0x53437632) + +#define SC64_DEBUG_WRITE_ADDRESS (0x13BD8000UL) +#define SC64_DEBUG_READ_ADDRESS (0x13BD0000UL) +#define SC64_DEBUG_MAX_SIZE (32 * 1024) + +#define SC64_DEBUG_TYPE_TEXT (0x01) + + +typedef enum { CFG_ID_SCR, CFG_ID_SDRAM_SWITCH, CFG_ID_SDRAM_WRITABLE, @@ -21,33 +60,61 @@ enum cfg_id { CFG_ID_TV_TYPE, CFG_ID_SAVE_OFFEST, CFG_ID_DD_OFFEST, - CFG_ID_SKIP_BOOTLOADER, -}; + CFG_ID_BOOT_MODE, + CFG_ID_FLASH_SIZE, + CFG_ID_FLASH_READ, + CFG_ID_FLASH_PROGRAM, + CFG_ID_RECONFIGURE, +} cfg_id_t; +typedef enum { + SAVE_TYPE_NONE = 0, + SAVE_TYPE_EEPROM_4K = 1, + SAVE_TYPE_EEPROM_16K = 2, + SAVE_TYPE_SRAM = 3, + SAVE_TYPE_FLASHRAM = 4, + SAVE_TYPE_SRAM_BANKED = 5, + SAVE_TYPE_FLASHRAM_PKST2 = 6, +} save_type_t; -typedef struct sc64_config { - union { - uint32_t ___raw_data[2]; - struct { - uint8_t ___unused_1[2]; - uint8_t save_type; - uint8_t ___unused_2: 1; - uint8_t dd_enable: 1; - uint8_t sdram_writable: 1; - uint8_t sdram_switch: 1; - uint8_t ___unused_3; - uint8_t tv_type; - uint16_t cic_type; - }; - }; -} sc64_config_t; +typedef enum { + TV_TYPE_PAL = 0, + TV_TYPE_NTSC = 1, + TV_TYPE_MPAL = 2, + TV_TYPE_UNKNOWN = 3, +} tv_type_t; + +typedef enum { + BOOT_MODE_MENU = 0, + BOOT_MODE_ROM = 1, + BOOT_MODE_DD = 2, + BOOT_MODE_DIRECT = 3, +} boot_mode_t; + +typedef struct { + bool dd_enabled; + save_type_t save_type; + uint8_t cic_seed; + tv_type_t tv_type; + io32_t *save_offset; + io32_t *dd_offset; + boot_mode_t boot_mode; + char bootloader_version[32]; +} info_t; bool sc64_check_presence(void); void sc64_wait_cpu_ready(void); -void sc64_wait_cpu_busy(void); -void sc64_perform_cmd(uint8_t cmd, uint32_t *args); -void sc64_set_config(uint32_t type, uint32_t value); +bool sc64_wait_cpu_busy(void); +bool sc64_perform_cmd(uint8_t cmd, uint32_t *args, uint32_t *result); +uint32_t sc64_get_config(cfg_id_t id); +void sc64_set_config(cfg_id_t id, uint32_t value); +void sc64_get_info(info_t *info); +void sc64_wait_usb_tx_ready(void); +void sc64_usb_tx_data(io32_t *address, uint32_t length); +void sc64_debug_write(uint8_t type, const void *data, uint32_t len); +void sc64_debug_print(const char *text); +void sc64_init(void); #endif diff --git a/sw/n64/src/startup.S b/sw/n64/src/startup.S index 448f85a..08f0bf4 100644 --- a/sw/n64/src/startup.S +++ b/sw/n64/src/startup.S @@ -2,7 +2,8 @@ #define XSTR(s) STR(s) #define VERSION XSTR(__SC64_VERSION) -.section .text.bootcode + +.section .text.rom_header header_pi_config: .word 0x80371240 @@ -12,60 +13,38 @@ header_clock_rate: header_load_addr: .word entry_handler -header_release_addr: +header_sdk_version: .word 0x00000000 header_crc: .fill 2, 4, 0 - .org 0x18, 0x00 - + .org 0x20, 0x00 header_text_info: - .ascii "byMFinPL" - .ascii "SummerLoader64 " + .global header_text_info + .ascii "SummerLoader64 " .ascii VERSION + .org 0x40, 0x00 - .org 0x40, 0x20 +.section .text.ipl3 ipl3: - .incbin "blob/ipl3.bin" + .incbin "header", 0x40 .section .text.entry_handler -.set noreorder entry_handler: .global entry_handler - li $a0, 0x08 - sw $a0, 0xBFC007FC - la $gp, _gp la $sp, _sp -init_bss: - la $a0, _sbss - la $a1, _ebss - bge $a0, $a1, 2f - nop -1: - sd $zero, 0($a0) - addi $a0, $a0, 8 - blt $a0, $a1, 1b - nop -2: - -init_bss_cache: - la $a0, _sbss - la $a1, _ebss - bge $a0, $a1, 2f - nop -1: - cache 0x15, 0($a0) - addi $a0, $a0, 16 - blt $a0, $a1, 1b - nop -2: - run: - j main - nop + la $t0, init + jalr $t0 + + la $t0, main + jalr $t0 + +loop: + j loop diff --git a/sw/n64/src/sys.c b/sw/n64/src/sys.c new file mode 100644 index 0000000..4ff46af --- /dev/null +++ b/sw/n64/src/sys.c @@ -0,0 +1,57 @@ +#include "sys.h" + + +static uint32_t c0_get_count(void) { + uint32_t x; + asm volatile("mfc0 %0,$9" : "=r" (x)); + return x; +} + +void wait_ms(uint32_t ms) { + uint32_t start = c0_get_count(); + while (c0_get_count() - start < (ms * ((CPU_FREQUENCY / 2) / 1000))); +} + +uint32_t io_read(io32_t *address) { + asm volatile ("" : : : "memory"); + uint32_t value = *UNCACHED(address); + asm volatile ("" : : : "memory"); + return value; +} + +void io_write(io32_t *address, uint32_t value) { + asm volatile ("" : : : "memory"); + *UNCACHED(address) = value; + asm volatile ("" : : : "memory"); +} + +uint32_t pi_busy(void) { + return (io_read(&PI->SR) & (PI_SR_IO_BUSY | PI_SR_DMA_BUSY)); +} + +uint32_t pi_io_read(io32_t *address) { + return io_read(address); +} + +void pi_io_write(io32_t *address, uint32_t value) { + io_write(address, value); + while (pi_busy()); +} + +uint32_t si_busy(void) { + return (io_read(&SI->SR) & (SI_SR_IO_BUSY | SI_SR_DMA_BUSY)); +} + +uint32_t si_io_read(io32_t *address) { + return io_read(address); +} + +void si_io_write(io32_t *address, uint32_t value) { + io_write(address, value); + while (si_busy()); +} + +void init(void) { + uint32_t pifram = si_io_read((io32_t *) (&PIFRAM[0x3C])); + si_io_write((io32_t *) (&PIFRAM[0x3C]), pifram | 0x08); +} diff --git a/sw/n64/src/sys.h b/sw/n64/src/sys.h new file mode 100644 index 0000000..99a79be --- /dev/null +++ b/sw/n64/src/sys.h @@ -0,0 +1,123 @@ +#ifndef SYS_H__ +#define SYS_H__ + + +#include +#include + + +typedef volatile uint8_t io8_t; +typedef volatile uint32_t io32_t; + + +#define ALIGN(value, align) (((value) + ((typeof(value))(align) - 1)) & ~((typeof(value))(align) - 1)) + +#define PHYSICAL(address) ((io32_t *) (((io32_t) (address)) & 0x1FFFFFFFUL)) +#define CACHED(address) ((io32_t *) ((((io32_t) (address)) & 0x1FFFFFFFUL) | 0x80000000UL)) +#define UNCACHED(address) ((io32_t *) ((((io32_t) (address)) & 0x1FFFFFFFUL) | 0xA0000000UL)) + +#define CPU_FREQUENCY (93750000UL) + + +typedef struct { + uint32_t tv_type; + uint32_t rom_type; + uint32_t rom_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; +} boot_info_t; + +#define BOOT_INFO_BASE (0x00000300UL) +#define BOOT_INFO ((boot_info_t *) BOOT_INFO_BASE) + + +typedef struct { + io32_t MADDR; + io32_t PADDR; + io32_t RDMA; + io32_t WDMA; + io32_t SR; + struct { + io32_t LAT; + io32_t PWD; + io32_t PGS; + io32_t RLS; + } DOM[2]; +} pi_regs_t; + +#define PI_BASE (0x04600000UL) +#define PI ((pi_regs_t *) PI_BASE) + +#define PI_SR_DMA_BUSY (1 << 0) +#define PI_SR_IO_BUSY (1 << 1) +#define PI_SR_DMA_ERROR (1 << 2) +#define PI_SR_RESET_CONTROLLER (1 << 0) +#define PI_SR_CLEAR_INTERRUPT (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) + + +typedef struct { + uint32_t pi_config; + uint32_t clock_rate; + uint32_t load_addr; + struct { + uint16_t __reserved_1; + uint8_t major; + char minor; + } sdk_version; + uint32_t crc[2]; + uint32_t __reserved_1[2]; + char name[20]; + uint8_t ___reserved_2[7]; + char id[4]; + uint8_t version; + uint32_t ipl3[1008]; +} rom_header_t; + +#define ROM_HEADER_DDIPL_BASE (0x06000000UL) +#define ROM_HEADER_DDIPL ((rom_header_t *) ROM_HEADER_DDIPL_BASE) +#define ROM_HEADER_CART_BASE (0x10000000UL) +#define ROM_HEADER_CART ((rom_header_t *) ROM_HEADER_CART_BASE) + + +#define PIFRAM_BASE (0x1FC007C0UL) +#define PIFRAM ((io8_t *) PIFRAM_BASE) + + + +void wait_ms(uint32_t ms); +uint32_t io_read(io32_t *address); +void io_write(io32_t *address, uint32_t value); +uint32_t pi_busy(void); +uint32_t pi_io_read(io32_t *address); +void pi_io_write(io32_t *address, uint32_t value); +uint32_t si_busy(void); +uint32_t si_io_read(io32_t *address); +void si_io_write(io32_t *address, uint32_t value); + + +#endif diff --git a/sw/n64/src/syscalls.c b/sw/n64/src/syscalls.c new file mode 100644 index 0000000..db9c5cf --- /dev/null +++ b/sw/n64/src/syscalls.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include "sc64.h" + + +int _close_r(struct _reent *prt, int fd) { + return -1; +} + +int _fstat_r(struct _reent *prt, int fd, struct stat *pstat) { + pstat->st_mode = S_IFCHR; + return 0; +} + +int _isatty_r(struct _reent *prt, int fd) { + return 1; +} + +off_t _lseek_r(struct _reent *prt, int fd, off_t pos, int whence) { + return 0; +} + +ssize_t _read_r(struct _reent *prt, int fd, void *buf, size_t cnt) { + return 0; +} + +caddr_t _sbrk_r(struct _reent *prt, ptrdiff_t incr) { + extern char _sheap; + extern char _eheap; + + static char *curr_heap_end = &_sheap; + char *prev_heap_end; + + prev_heap_end = curr_heap_end; + curr_heap_end += incr; + + if (curr_heap_end > &_eheap) { + errno = ENOMEM; + return (caddr_t) -1; + } + + return (caddr_t) prev_heap_end; +} + +ssize_t _write_r(struct _reent *prt, int fd, const void *buf, size_t cnt) { + sc64_debug_write(SC64_DEBUG_TYPE_TEXT, buf, cnt); + return 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 : ""); + while (1); +} diff --git a/sw/pc/sc64.py b/sw/pc/sc64.py index 021637d..605704e 100644 --- a/sw/pc/sc64.py +++ b/sw/pc/sc64.py @@ -27,9 +27,11 @@ class SC64: __CFG_ID_TV_TYPE = 6 __CFG_ID_SAVE_OFFEST = 7 __CFG_ID_DD_OFFEST = 8 - __CFG_ID_SKIP_BOOTLOADER = 9 - __CFG_ID_FLASH_OPERATION = 10 - __CFG_ID_RECONFIGURE = 11 + __CFG_ID_BOOT_MODE = 9 + __CFG_ID_FLASH_SIZE = 10 + __CFG_ID_FLASH_READ = 11 + __CFG_ID_FLASH_PROGRAM = 12 + __CFG_ID_RECONFIGURE = 13 __SC64_VERSION_V2 = 0x53437632 @@ -40,6 +42,8 @@ class SC64: __MIN_ROM_LENGTH = 0x101000 __DDIPL_ROM_LENGTH = 0x400000 + __DEBUG_ID_TEXT = 0x01 + def __init__(self) -> None: self.__serial = None @@ -88,7 +92,14 @@ class SC64: def __write(self, data: bytes) -> None: self.__serial.write(self.__escape(data)) - + + def __read_long(self, length: int) -> bytes: + data = bytearray() + while (len(data) < length): + data += self.__read(length - len(data)) + return bytes(data) + + def __write_dummy(self, length: int) -> None: self.__write(bytes(length)) @@ -148,8 +159,8 @@ class SC64: raise SC64Exception(f"Unknown hardware version: {hex(version)}") - def __query_config(self, id: int, arg: int = 0) -> int: - self.__write_cmd("Q", id, arg) + def __query_config(self, id: int) -> int: + self.__write_cmd("Q", id, 0) value = self.__read_int() self.__read_cmd_status("Q") return value @@ -211,7 +222,8 @@ class SC64: def backup_firmware(self, file: str) -> None: - length = self.__query_config(self.__CFG_ID_FLASH_OPERATION, self.__UPDATE_OFFSET) + length = self.__query_config(self.__CFG_ID_FLASH_SIZE) + self.__change_config(self.__CFG_ID_FLASH_READ, self.__UPDATE_OFFSET) self.__read_file_from_sdram(file, self.__UPDATE_OFFSET, length) @@ -219,14 +231,28 @@ class SC64: self.__write_file_to_sdram(file, self.__UPDATE_OFFSET) saved_timeout = self.__serial.timeout self.__serial.timeout = 20.0 - self.__change_config(self.__CFG_ID_FLASH_OPERATION, self.__UPDATE_OFFSET) + self.__change_config(self.__CFG_ID_FLASH_PROGRAM, self.__UPDATE_OFFSET) self.__serial.timeout = saved_timeout self.__reconfigure() self.__find_sc64() - def set_skip_bootloader(self, enable: bool) -> None: - self.__change_config(self.__CFG_ID_SKIP_BOOTLOADER, 1 if enable else 0) + def set_boot_mode(self, mode: int) -> None: + if (mode >= 0 and mode <= 3): + self.__change_config(self.__CFG_ID_BOOT_MODE, mode) + else: + raise SC64Exception("Boot mode outside of supported values") + + + def get_boot_mode_label(self, mode: int) -> None: + if (mode < 0 or mode > 3): + return "Unknown" + return { + 0: "Load menu from SD card", + 1: "Load ROM from SDRAM through bootloader", + 2: "Load DDIPL from SDRAM", + 3: "Load ROM from SDRAM directly without bootloader" + }[mode] def set_tv_type(self, type: int = None) -> None: @@ -321,6 +347,34 @@ class SC64: self.__write_file_to_sdram(file, dd_ipl_offset, min_length=self.__DDIPL_ROM_LENGTH) + def debug_loop(self) -> None: + print("\r\nDebug server started\r\n") + + self.__serial.timeout = 0.01 + + while (True): + start_indicator = self.__read_long(4) + if (start_indicator == b"DMA@"): + header = self.__read_long(4) + id = int(header[0]) + length = int.from_bytes(header[1:4], byteorder="big") + align = self.__align(length, 4) - length + data = self.__read_long(length) + + if (id == self.__DEBUG_ID_TEXT): + print(data.decode(encoding="ascii", errors="backslashreplace"), end="") + sys.stdout.flush() + else: + print(f"Got unknown id: {id}, length: {length}") + + self.__read_long(align) + end_indicator = self.__read_long(4) + if (end_indicator != b"CMPH"): + print(f"Got unknown end indicator: {end_indicator.decode(encoding='ascii', errors='backslashreplace')}") + else: + print(f"Got unknown start indicator: {start_indicator.decode(encoding='ascii', errors='backslashreplace')}") + + class SC64ProgressBar: __LABEL_LENGTH = 30 @@ -381,17 +435,18 @@ class SC64ProgressBar: if __name__ == "__main__": parser = argparse.ArgumentParser(description="SummerCart64 one stop control center") - parser.add_argument("-b", default=False, action="store_true", required=False, help="skip internal bootloader") - parser.add_argument("-t", default="3", required=False, help="set TV type (0 - 2)") - parser.add_argument("-c", default="0xFFFF", required=False, help="set CIC seed") - parser.add_argument("-s", default="0", required=False, help="set save type (0 - 6)") + parser.add_argument("-b", metavar="boot_mode", default="1", required=False, help="set boot mode (0 - 3)") + parser.add_argument("-t", metavar="tv_type", default="3", required=False, help="set TV type (0 - 2)") + parser.add_argument("-c", metavar="cic_seed", default="0xFFFF", required=False, help="set CIC seed") + parser.add_argument("-s", metavar="save_type", default="0", required=False, help="set save type (0 - 6)") parser.add_argument("-d", default=False, action="store_true", required=False, help="enable 64DD emulation") parser.add_argument("-r", default=False, action="store_true", required=False, help="perform reading operation instead of writing") - parser.add_argument("-l", default="0x101000", required=False, help="specify ROM length to read") - parser.add_argument("-u", default=None, required=False, help="path to update file") - parser.add_argument("-e", default=None, required=False, help="path to save file") - parser.add_argument("-i", default=None, required=False, help="path to DDIPL file") - parser.add_argument("rom", default=None, help="path to ROM file", nargs="?") + parser.add_argument("-l", metavar="length", default="0x101000", required=False, help="specify ROM length to read") + parser.add_argument("-u", metavar="update_path", default=None, required=False, help="path to update file") + parser.add_argument("-e", metavar="save_path", default=None, required=False, help="path to save file") + parser.add_argument("-i", metavar="ddipl_path", default=None, required=False, help="path to DDIPL file") + parser.add_argument("-q", default=None, action="store_true", required=False, help="start debug server") + parser.add_argument("rom", metavar="rom_path", default=None, help="path to ROM file", nargs="?") args = parser.parse_args() @@ -402,7 +457,7 @@ if __name__ == "__main__": try: sc64 = SC64() - skip_bootloader = args.b + boot_mode = int(args.b) save_type = int(args.s) tv_type = int(args.t) cic_seed = int(args.c, 0) @@ -413,6 +468,7 @@ if __name__ == "__main__": save_file = args.e dd_ipl_file = args.i rom_file = args.rom + debug_server = args.q firmware_backup_file = "sc64firmware.bin.bak" @@ -430,12 +486,12 @@ if __name__ == "__main__": os.remove(firmware_backup_file) if (not is_read): + print(f"Setting boot mode to [{sc64.get_boot_mode_label(boot_mode)}]") + sc64.set_boot_mode(boot_mode) + print(f"Setting save type to [{sc64.get_save_type_label(save_type)}]") sc64.set_save_type(save_type) - print(f"Setting skip internal bootloader to [{'True' if skip_bootloader else 'False'}]") - sc64.set_skip_bootloader(skip_bootloader) - print(f"Setting TV type to [{sc64.get_tv_type_label(tv_type)}]") sc64.set_tv_type(tv_type) @@ -466,6 +522,13 @@ if __name__ == "__main__": else: sc64.upload_save(save_file) + if (debug_server): + sc64.debug_loop() + except SC64Exception as e: print(f"Error: {e}") parser.exit(1) + except KeyboardInterrupt: + pass + finally: + sys.stdout.write("\033[0m") diff --git a/sw/riscv/src/cfg.c b/sw/riscv/src/cfg.c index 8b18ea0..21ed24b 100644 --- a/sw/riscv/src/cfg.c +++ b/sw/riscv/src/cfg.c @@ -26,8 +26,10 @@ enum cfg_id { CFG_ID_TV_TYPE, CFG_ID_SAVE_OFFEST, CFG_ID_DD_OFFEST, - CFG_ID_SKIP_BOOTLOADER, - CFG_ID_FLASH_OPERATION, + CFG_ID_BOOT_MODE, + CFG_ID_FLASH_SIZE, + CFG_ID_FLASH_READ, + CFG_ID_FLASH_PROGRAM, CFG_ID_RECONFIGURE, }; @@ -41,11 +43,19 @@ enum save_type { SAVE_TYPE_FLASHRAM_PKST2 = 6, }; +enum boot_mode { + BOOT_MODE_MENU = 0, + BOOT_MODE_ROM = 1, + BOOT_MODE_DD = 2, + BOOT_MODE_DIRECT = 3, +}; + struct process { enum save_type save_type; uint16_t cic_seed; uint8_t tv_type; + enum boot_mode boot_mode; }; static struct process p; @@ -136,10 +146,14 @@ void cfg_update (uint32_t *args) { case CFG_ID_DD_OFFEST: CFG->DD_OFFSET = args[1]; break; - case CFG_ID_SKIP_BOOTLOADER: - change_scr_bits(CFG_SCR_SKIP_BOOTLOADER, args[1]); + case CFG_ID_BOOT_MODE: + p.boot_mode = args[1]; + change_scr_bits(CFG_SCR_SKIP_BOOTLOADER, args[1] == BOOT_MODE_DIRECT); break; - case CFG_ID_FLASH_OPERATION: + case CFG_ID_FLASH_READ: + flash_read(args[1]); + break; + case CFG_ID_FLASH_PROGRAM: flash_program(args[1]); break; case CFG_ID_RECONFIGURE: @@ -182,11 +196,11 @@ void cfg_query (uint32_t *args) { case CFG_ID_DD_OFFEST: args[1] = CFG->DD_OFFSET; break; - case CFG_ID_SKIP_BOOTLOADER: - args[1] = CFG->SCR & CFG_SCR_SKIP_BOOTLOADER; + case CFG_ID_BOOT_MODE: + args[1] = p.boot_mode; break; - case CFG_ID_FLASH_OPERATION: - args[1] = flash_read(args[1]); + case CFG_ID_FLASH_SIZE: + args[1] = flash_size(); break; case CFG_ID_RECONFIGURE: args[1] = CFG->RECONFIGURE; @@ -203,6 +217,7 @@ void cfg_init (void) { p.cic_seed = 0xFFFF; p.tv_type = 0x03; + p.boot_mode = BOOT_MODE_MENU; } diff --git a/sw/riscv/src/flash.c b/sw/riscv/src/flash.c index bdff2d8..4c7e957 100644 --- a/sw/riscv/src/flash.c +++ b/sw/riscv/src/flash.c @@ -1,15 +1,17 @@ #include "flash.h" -uint32_t flash_read (uint32_t sdram_offset) { +uint32_t flash_size (void) { + return FLASH_SIZE; +} + +void flash_read (uint32_t sdram_offset) { io32_t *flash = (io32_t *) (FLASH_BASE); io32_t *sdram = (io32_t *) (SDRAM_BASE + sdram_offset); for (size_t i = 0; i < FLASH_SIZE; i += 4) { *sdram++ = *flash++; } - - return FLASH_SIZE; } void flash_program (uint32_t sdram_offset) { diff --git a/sw/riscv/src/flash.h b/sw/riscv/src/flash.h index 26916c5..89de167 100644 --- a/sw/riscv/src/flash.h +++ b/sw/riscv/src/flash.h @@ -5,7 +5,8 @@ #include "sys.h" -uint32_t flash_read (uint32_t sdram_offset); +uint32_t flash_size(void); +void flash_read (uint32_t sdram_offset); void flash_program (uint32_t sdram_offset); diff --git a/sw/riscv/src/startup.S b/sw/riscv/src/startup.S index b7dd186..6d607cd 100644 --- a/sw/riscv/src/startup.S +++ b/sw/riscv/src/startup.S @@ -2,6 +2,7 @@ #define XSTR(s) STR(s) #define VERSION XSTR(__SC64_VERSION) + .section .text.reset_handler reset_handler: .global reset_handler @@ -13,16 +14,15 @@ reset_handler: la sp, __stack_pointer$ - j init_text - - .org 0x18, 0x00 + la ra, init_text + jalr zero, 0(ra) + .org 0x20, 0x00 header_text_info: - .ascii "byMFinPL" - .ascii "SummerGovernor64" + .global header_text_info + .ascii "SummerGovernor64 " .ascii VERSION - - .org 0x40, 0x20 + .org 0x40, 0x00 init_text: la a0, _sitext diff --git a/sw/riscv/src/sys.h b/sw/riscv/src/sys.h index 008f04b..7ac1960 100644 --- a/sw/riscv/src/sys.h +++ b/sw/riscv/src/sys.h @@ -189,4 +189,7 @@ typedef volatile struct joybus_regs { #define JOYBUS_SCR_TX_LENGTH_BIT (16) +void reset_handler(void); + + #endif