diff --git a/Makefile b/Makefile index cc91bc264..0ea54ce82 100644 --- a/Makefile +++ b/Makefile @@ -58,7 +58,7 @@ endif DEFINES += NO_ERRNO_H=1 NO_GZIP=1 COMPRESS ?= yay0 -$(eval $(call validate-option,COMPRESS,yay0 gzip rnc1 rnc2)) +$(eval $(call validate-option,COMPRESS,mio0 yay0 gzip rnc1 rnc2)) ifeq ($(COMPRESS),gzip) DEFINES += GZIP=1 else ifeq ($(COMPRESS),rnc1) @@ -67,6 +67,8 @@ else ifeq ($(COMPRESS),rnc2) DEFINES += RNC2=1 else ifeq ($(COMPRESS),yay0) DEFINES += YAY0=1 +else ifeq ($(COMPRESS),mio0) + DEFINES += MIO0=1 endif GZIPVER ?= std @@ -379,6 +381,7 @@ CPPFLAGS := -P -Wno-trigraphs $(DEF_INC_CFLAGS) # N64 tools YAY0TOOL := $(TOOLS_DIR)/slienc +MIO0TOOL := $(TOOLS_DIR)/mio0 RNCPACK := $(TOOLS_DIR)/rncpack ROMALIGN := $(TOOLS_DIR)/romalign FILESIZER := $(TOOLS_DIR)/filesizer @@ -566,6 +569,8 @@ else ifeq ($(COMPRESS),rnc2) include rnc2rules.mk else ifeq ($(COMPRESS),yay0) include yay0rules.mk +else ifeq ($(COMPRESS),mio0) +include mio0rules.mk endif #==============================================================================# diff --git a/asm/decompress.s b/asm/decompress.s new file mode 100644 index 000000000..1399179de --- /dev/null +++ b/asm/decompress.s @@ -0,0 +1,149 @@ +# assembler directives +.set noat # allow manual use of $at +.set noreorder # don't insert nops after branches +.set gp=64 + +.include "macros.inc" + + +.section .text, "ax" + +# This file is handwritten. + +glabel decompress +.if VERSION_SH == 1 + lw $a3, 8($a0) + lw $t9, 0xc($a0) + lw $t8, 4($a0) + add $a3, $a3, $a0 + add $t9, $t9, $a0 + move $a2, $zero + addi $a0, $a0, 0x10 + add $t8, $t8, $a1 +.L802772C0: + bnel $a2, $zero, .L802772D8 + slt $t1, $t0, $zero + lw $t0, ($a0) + li $a2, 32 + addi $a0, $a0, 4 + slt $t1, $t0, $zero +.L802772D8: + beql $t1, $zero, .L802772F8 + lhu $t2, ($a3) + lb $t2, ($t9) + addi $t9, $t9, 1 + addi $a1, $a1, 1 + b .L80277324 + sb $t2, -1($a1) + lhu $t2, ($a3) +.L802772F8: + addi $a3, $a3, 2 + srl $t3, $t2, 0xc + andi $t2, $t2, 0xfff + sub $t1, $a1, $t2 + addi $t3, $t3, 3 +.L8027730C: + lb $t2, -1($t1) + addi $t3, $t3, -1 + addi $t1, $t1, 1 + addi $a1, $a1, 1 + bnez $t3, .L8027730C + sb $t2, -1($a1) +.L80277324: + sll $t0, $t0, 1 + bne $a1, $t8, .L802772C0 + addi $a2, $a2, -1 + jr $ra + nop +.elseif VERSION_EU == 1 + lw $a3, 8($a0) + lw $t9, 0xc($a0) + lw $t8, 4($a0) + add $a3, $a3, $a0 + add $t9, $t9, $a0 + move $a2, $zero + addi $a0, $a0, 0x10 + add $t8, $t8, $a1 +.L8026ED80: + bnezl $a2, .L8026ED98 + slt $t1, $t0, $zero + lw $t0, ($a0) + li $a2, 32 + addi $a0, $a0, 4 + slt $t1, $t0, $zero +.L8026ED98: + beql $t1, $zero, .L8026EDB8 + lhu $t2, ($a3) + lb $t2, ($t9) + addi $t9, $t9, 1 + addi $a1, $a1, 1 + b .L8026EDE4 + sb $t2, -1($a1) + lhu $t2, ($a3) +.L8026EDB8: + addi $a3, $a3, 2 + srl $t3, $t2, 0xc + andi $t2, $t2, 0xfff + sub $t1, $a1, $t2 + addi $t3, $t3, 3 +.L8026EDCC: + lb $t2, -1($t1) + addi $t3, $t3, -1 + addi $t1, $t1, 1 + addi $a1, $a1, 1 + bnez $t3, .L8026EDCC + sb $t2, -1($a1) +.L8026EDE4: + sll $t0, $t0, 1 + bne $a1, $t8, .L8026ED80 + addi $a2, $a2, -1 + jr $ra + nop +.else + lw $t8, 4($a0) + lw $a3, 8($a0) + lw $t9, 0xc($a0) + move $a2, $zero + add $t8, $t8, $a1 + add $a3, $a3, $a0 + add $t9, $t9, $a0 + addi $a0, $a0, 0x10 +.L8027EF50: + bnez $a2, .L8027EF64 + nop + lw $t0, ($a0) + li $a2, 32 + addi $a0, $a0, 4 +.L8027EF64: + slt $t1, $t0, $zero + beqz $t1, .L8027EF88 + nop + lb $t2, ($t9) + addi $t9, $t9, 1 + sb $t2, ($a1) + addi $a1, $a1, 1 + b .L8027EFBC + nop +.L8027EF88: + lhu $t2, ($a3) + addi $a3, $a3, 2 + srl $t3, $t2, 0xc + andi $t2, $t2, 0xfff + sub $t1, $a1, $t2 + addi $t3, $t3, 3 +.L8027EFA0: + lb $t2, -1($t1) + addi $t3, $t3, -1 + addi $t1, $t1, 1 + sb $t2, ($a1) + addi $a1, $a1, 1 + bnez $t3, .L8027EFA0 + nop +.L8027EFBC: + sll $t0, $t0, 1 + addi $a2, $a2, -1 + bne $a1, $t8, .L8027EF50 + nop + jr $ra + nop +.endif diff --git a/mio0rules.mk b/mio0rules.mk new file mode 100644 index 000000000..123c3c0bb --- /dev/null +++ b/mio0rules.mk @@ -0,0 +1,9 @@ +# Compress binary file +$(BUILD_DIR)/%.szp: $(BUILD_DIR)/%.bin + $(call print,Compressing:,$<,$@) + $(V)$(MIO0TOOL) $< $@ + +# convert binary szp to object file +$(BUILD_DIR)/%.szp.o: $(BUILD_DIR)/%.szp + $(call print,Converting MIO0 to ELF:,$<,$@) + $(V)printf ".section .data\n\n.incbin \"$<\"\n" | $(AS) $(ASFLAGS) -o $@ \ No newline at end of file diff --git a/sm64.ld b/sm64.ld index 885d76775..ad0cb77ec 100755 --- a/sm64.ld +++ b/sm64.ld @@ -137,6 +137,9 @@ SECTIONS #ifdef YAY0 BUILD_DIR/asm/slidec.o(.text); #endif +#ifdef MIO0 + BUILD_DIR/asm/decompress.o(.text); +#endif #ifdef RNC1 BUILD_DIR/asm/rnc1.o(.text); #endif diff --git a/src/game/memory.c b/src/game/memory.c index 783154c00..5dc82ad44 100644 --- a/src/game/memory.c +++ b/src/game/memory.c @@ -354,6 +354,8 @@ void *load_segment_decompress(s32 segment, u8 *srcStart, u8 *srcEnd) { Propack_UnpackM2(compressed, dest); #elif YAY0 slidstart(compressed, dest); +#elif MIO0 + decompress(compressed, dest); #endif set_segment_base_addr(segment, dest); main_pool_free(compressed); @@ -387,6 +389,8 @@ void *load_segment_decompress_heap(u32 segment, u8 *srcStart, u8 *srcEnd) { Propack_UnpackM2(compressed, gDecompressionHeap); #elif YAY0 slidstart(compressed, gDecompressionHeap); +#elif MIO0 + decompress(compressed, gDecompressionHeap); #endif set_segment_base_addr(segment, gDecompressionHeap); main_pool_free(compressed); diff --git a/src/game/slidec.h b/src/game/slidec.h index ae05384e2..74d7c1fd6 100644 --- a/src/game/slidec.h +++ b/src/game/slidec.h @@ -3,4 +3,6 @@ void slidstart(unsigned char*, unsigned char *); +void decompress(void *mio0, void *dest); + #endif // SLIDEC_H