diff --git a/Makefile b/Makefile index c3d1ffdd2..6a4dac1e9 100644 --- a/Makefile +++ b/Makefile @@ -283,6 +283,9 @@ CPP_DEFINES += -DOOT_REGION=REGION_$(REGION) CPP_DEFINES += -DBUILD_CREATOR="\"$(BUILD_CREATOR)\"" -DBUILD_DATE="\"$(BUILD_DATE)\"" -DBUILD_TIME="\"$(BUILD_TIME)\"" CPP_DEFINES += -DLIBULTRA_VERSION=LIBULTRA_VERSION_$(LIBULTRA_VERSION) CPP_DEFINES += -DLIBULTRA_PATCH=$(LIBULTRA_PATCH) +ifeq ($(PLATFORM),IQUE) + CPP_DEFINES += -DBBPLAYER +endif ifeq ($(VERSION),hackeroot-mq) CPP_DEFINES += -DENABLE_HACKEROOT=1 @@ -356,6 +359,9 @@ OBJDUMP := $(MIPS_BINUTILS_PREFIX)objdump NM := $(MIPS_BINUTILS_PREFIX)nm STRIP := $(MIPS_BINUTILS_PREFIX)strip +# Command to patch certain object files after they are built +POSTPROCESS_OBJ := @: + # The default iconv on macOS has some differences from GNU iconv, so we use the Homebrew version instead ifeq ($(UNAME_S),Darwin) ICONV := $(shell brew --prefix)/opt/libiconv/bin/iconv @@ -639,11 +645,6 @@ ifeq ($(TARGET),iso) endif endif -SET_ABI_BIT = @: -$(BUILD_DIR)/src/libultra/os/exceptasm.o: SET_ABI_BIT = $(PYTHON) tools/set_o32abi_bit.py $@ -$(BUILD_DIR)/src/libultra/libc/ll.o: SET_ABI_BIT = $(PYTHON) tools/set_o32abi_bit.py $@ -$(BUILD_DIR)/src/libultra/libc/llcvt.o: SET_ABI_BIT = $(PYTHON) tools/set_o32abi_bit.py $@ - #### Main Targets ### all: rom @@ -883,6 +884,7 @@ $(BUILD_DIR)/src/makerom/ipl3.o: $(EXTRACTED_DIR)/incbin/ipl3 $(BUILD_DIR)/src/%.o: src/%.s $(call print,Compiling:,$<,$@) $(V)$(CCAS) -c $(CCASFLAGS) $(MIPS_VERSION) $(ASOPTFLAGS) -o $@ $< + $(V)$(POSTPROCESS_OBJ) $@ $(V)$(OBJDUMP_CMD) # Incremental link to move z_message and z_game_over data into rodata @@ -914,7 +916,7 @@ ifneq ($(RUN_CC_CHECK),0) endif $(call print,Compiling:,$<,$@) $(V)$(CC) -c $(CFLAGS) $(MIPS_VERSION) $(OPTFLAGS) -o $@ $< - $(V)$(SET_ABI_BIT) + $(V)$(POSTPROCESS_OBJ) $@ $(V)$(OBJDUMP_CMD) $(BUILD_DIR)/src/audio/session_init.o: src/audio/session_init.c $(BUILD_DIR)/assets/audio/soundfont_sizes.h $(BUILD_DIR)/assets/audio/sequence_sizes.h diff --git a/include/ultra64/bcp.h b/include/ultra64/bcp.h index 7b139b3de..027fecf3f 100644 --- a/include/ultra64/bcp.h +++ b/include/ultra64/bcp.h @@ -26,4 +26,168 @@ */ #define MI_SECURE_EXCEPTION_REG (MI_BASE_REG + 0x14) +/** + * Read: + * [25] MD (active, 1 if card is currently disconnected else 0) + * [24] Power Button (active, 1 if button is currently pressed else 0) + * [13] MD (pending interrupt) + * [12] Power Button (pending interrupt) + * [11] USB1 + * [10] USB0 + * [ 9] PI_ERR + * [ 8] IDE + * [ 7] AES + * [ 6] FLASH + * [ 5] DP + * [ 4] PI + * [ 3] VI + * [ 2] AI + * [ 1] SI + * [ 0] SP + * + * Write: + * [13] Clear MD Interrupt + */ +#define MI_EX_INTR_REG (MI_BASE_REG + 0x38) + +/* + * MI_EX_INTR_REG: read bits + */ +#define MI_EX_INTR_SP (1 << 0) +#define MI_EX_INTR_SI (1 << 1) +#define MI_EX_INTR_AI (1 << 2) +#define MI_EX_INTR_VI (1 << 3) +#define MI_EX_INTR_PI (1 << 4) +#define MI_EX_INTR_DP (1 << 5) +#define MI_EX_INTR_FLASH (1 << 6) +#define MI_EX_INTR_AES (1 << 7) +#define MI_EX_INTR_IDE (1 << 8) +#define MI_EX_INTR_PI_ERR (1 << 9) +#define MI_EX_INTR_USB0 (1 << 10) +#define MI_EX_INTR_USB1 (1 << 11) +#define MI_EX_INTR_PWR_BTN (1 << 12) +#define MI_EX_INTR_MD (1 << 13) +#define MI_EX_INTR_PWR_BTN_PRESSED (1 << 24) /* updated in real-time, unrelated to interrupt */ +#define MI_EX_INTR_CARD_NOT_PRESENT (1 << 25) /* updated in real-time, unrelated to interrupt */ + +#define MI_EX_INTR_ALL \ + (MI_EX_INTR_FLASH | MI_EX_INTR_AES | MI_EX_INTR_IDE | MI_EX_INTR_PI_ERR | \ + MI_EX_INTR_USB0 | MI_EX_INTR_USB1 | MI_EX_INTR_PWR_BTN | MI_EX_INTR_MD) + +/* + * MI_EX_INTR_REG: write bits + */ +#define MI_EX_INTR_CLR_MD (1 << 13) + +/** + * Write: + * [27:26] Set/Clear MD + * [25:24] Set/Clear BUTTON + * [23:22] Set/Clear USB1 + * [21:20] Set/Clear USB0 + * [19:18] Set/Clear PI_ERR + * [17:16] Set/Clear IDE + * [15:14] Set/Clear AES + * [13:12] Set/Clear FLASH + * [11:10] Set/Clear DP + * [ 9: 8] Set/Clear PI + * [ 7: 6] Set/Clear VI + * [ 5: 4] Set/Clear AI + * [ 3: 2] Set/Clear SI + * [ 1: 0] Set/Clear SP + * + * Read: + * [13] MD + * [12] BUTTON + * [11] USB1 + * [10] USB0 + * [ 9] PI_ERR + * [ 8] IDE + * [ 7] AES + * [ 6] FLASH + * [ 5] DP + * [ 4] PI + * [ 3] VI + * [ 2] AI + * [ 1] SI + * [ 0] SP + */ +#define MI_EX_INTR_MASK_REG (MI_BASE_REG + 0x3C) + +/* + * MI_EX_INTR_MASK_REG: write bits + */ +#define MI_EX_INTR_MASK_CLR_SP (1 << 0) /* clear SP mask */ +#define MI_EX_INTR_MASK_SET_SP (1 << 1) /* set SP mask */ +#define MI_EX_INTR_MASK_CLR_SI (1 << 2) /* clear SI mask */ +#define MI_EX_INTR_MASK_SET_SI (1 << 3) /* set SI mask */ +#define MI_EX_INTR_MASK_CLR_AI (1 << 4) /* clear AI mask */ +#define MI_EX_INTR_MASK_SET_AI (1 << 5) /* set AI mask */ +#define MI_EX_INTR_MASK_CLR_VI (1 << 6) /* clear VI mask */ +#define MI_EX_INTR_MASK_SET_VI (1 << 7) /* set VI mask */ +#define MI_EX_INTR_MASK_CLR_PI (1 << 8) /* clear PI mask */ +#define MI_EX_INTR_MASK_SET_PI (1 << 9) /* set PI mask */ +#define MI_EX_INTR_MASK_CLR_DP (1 << 10) /* clear DP mask */ +#define MI_EX_INTR_MASK_SET_DP (1 << 11) /* set DP mask */ +#define MI_EX_INTR_MASK_CLR_FLASH (1 << 12) /* clear FLASH mask */ +#define MI_EX_INTR_MASK_SET_FLASH (1 << 13) /* set FLASH mask */ +#define MI_EX_INTR_MASK_CLR_AES (1 << 14) /* clear AES mask */ +#define MI_EX_INTR_MASK_SET_AES (1 << 15) /* set AES mask */ +#define MI_EX_INTR_MASK_CLR_IDE (1 << 16) /* clear IDE mask */ +#define MI_EX_INTR_MASK_SET_IDE (1 << 17) /* set IDE mask */ +#define MI_EX_INTR_MASK_CLR_PI_ERR (1 << 18) /* clear PI_ERR mask */ +#define MI_EX_INTR_MASK_SET_PI_ERR (1 << 19) /* set PI_ERR mask */ +#define MI_EX_INTR_MASK_CLR_USB0 (1 << 20) /* clear USB0 mask */ +#define MI_EX_INTR_MASK_SET_USB0 (1 << 21) /* set USB0 mask */ +#define MI_EX_INTR_MASK_CLR_USB1 (1 << 22) /* clear USB1 mask */ +#define MI_EX_INTR_MASK_SET_USB1 (1 << 23) /* set USB1 mask */ +#define MI_EX_INTR_MASK_CLR_PWR_BTN (1 << 24) /* clear PWR_BTN mask */ +#define MI_EX_INTR_MASK_SET_PWR_BTN (1 << 25) /* set PWR_BTN mask */ +#define MI_EX_INTR_MASK_CLR_MD (1 << 26) /* clear MD mask */ +#define MI_EX_INTR_MASK_SET_MD (1 << 27) /* set MD mask */ + +/* + * MI_EX_INTR_MASK_REG: read bits + */ +#define MI_EX_INTR_MASK_SP (1 << 0) /* SP intr mask */ +#define MI_EX_INTR_MASK_SI (1 << 1) /* SI intr mask */ +#define MI_EX_INTR_MASK_AI (1 << 2) /* AI intr mask */ +#define MI_EX_INTR_MASK_VI (1 << 3) /* VI intr mask */ +#define MI_EX_INTR_MASK_PI (1 << 4) /* PI intr mask */ +#define MI_EX_INTR_MASK_DP (1 << 5) /* DP intr mask */ +#define MI_EX_INTR_MASK_FLASH (1 << 6) /* FLASH intr mask */ +#define MI_EX_INTR_MASK_AES (1 << 7) /* AES intr mask */ +#define MI_EX_INTR_MASK_IDE (1 << 8) /* IDE intr mask */ +#define MI_EX_INTR_MASK_PI_ERR (1 << 9) /* PI_ERR intr mask */ +#define MI_EX_INTR_MASK_USB0 (1 << 10) /* USB0 intr mask */ +#define MI_EX_INTR_MASK_USB1 (1 << 11) /* USB1 intr mask */ +#define MI_EX_INTR_MASK_PWR_BTN (1 << 12) /* PWR_BTN intr mask */ +#define MI_EX_INTR_MASK_MD (1 << 13) /* MD intr mask */ + +/****************************************************************************** + * Additional Parallel Interface (PI) Registers + */ + +/** + * Write: + * [31] Execute command after write + * [30] Interrupt when done + * [29:24] ? + * [23:16] NAND Command + * [15] ? + * [14] Buffer Select + * [13:12] Device Select + * [11] Do Error Correction + * [10] NAND Command is Multi-Cycle + * [ 9: 0] Data Transfer Length in Bytes + * + * Writing 0 to this register clears the interrupt + * + * Read: + * [31] Busy + * [11] Single-Bit Error Corrected + * [10] Double-Bit Error Uncorrectable + */ +#define PI_NAND_CTRL_REG (PI_BASE_REG + 0x48) + #endif diff --git a/include/ultra64/message.h b/include/ultra64/message.h index 055c2e324..dc89dc48e 100644 --- a/include/ultra64/message.h +++ b/include/ultra64/message.h @@ -21,6 +21,16 @@ #define OS_EVENT_FAULT 12 /* CPU fault event: used by rmon */ #define OS_EVENT_THREADSTATUS 13 /* CPU thread status: used by rmon */ #define OS_EVENT_PRENMI 14 /* Pre NMI interrupt */ +#ifdef BBPLAYER +#define OS_EVENT_FLASH 23 /* NAND flash operation complete */ +#define OS_EVENT_AES 24 /* AES decryption complete */ +#define OS_EVENT_IDE 25 /* IDE transfer complete */ +#define OS_EVENT_PI_ERR 26 /* PI Error? */ +#define OS_EVENT_USB0 27 /* USB Controller 0 */ +#define OS_EVENT_USB1 28 /* USB Controller 1 */ +#define OS_EVENT_UNK_29 29 /* ? */ +#define OS_EVENT_MD 30 /* Memory card removed */ +#endif #ifdef _LANGUAGE_C diff --git a/src/boot/driverominit.c b/src/boot/driverominit.c index 7d1441cdd..5ed69abe0 100644 --- a/src/boot/driverominit.c +++ b/src/boot/driverominit.c @@ -3,7 +3,14 @@ OSPiHandle __DriveRomHandle; OSPiHandle* osDriveRomInit(void) { +#if PLATFORM_IQUE && defined(NON_MATCHING) + // On iQue, the compiled output of this file is patched so that the + // `!first` check is always taken. For non-matching builds, we edit the + // source code instead. + static u32 first = false; +#else static u32 first = true; +#endif register s32 status; register u32 value; register u32 prevInt; diff --git a/src/code/z_skelanime.c b/src/code/z_skelanime.c index a953bdb21..d21981510 100644 --- a/src/code/z_skelanime.c +++ b/src/code/z_skelanime.c @@ -849,7 +849,7 @@ AnimTask* AnimTaskQueue_NewTask(AnimTaskQueue* animTaskQueue, s32 type) { return task; } -#if PLATFORM_N64 +#if !PLATFORM_GC #define LINK_ANIMATION_OFFSET(addr, offset) \ (((uintptr_t)_link_animetionSegmentRomStart) + SEGMENT_OFFSET(addr) + (offset)) #else diff --git a/src/libultra/os/exceptasm.s b/src/libultra/os/exceptasm.s index ca736aee7..3a3919061 100644 --- a/src/libultra/os/exceptasm.s +++ b/src/libultra/os/exceptasm.s @@ -5,6 +5,7 @@ #include "ultra64/regdef.h" #include "ultra64/R4300.h" #include "ultra64/rcp.h" +#include "ultra64/bcp.h" #include "ultra64/message.h" #include "ultra64/thread.h" #include "ultra64/exception.h" @@ -16,6 +17,8 @@ #define true 1 #define false 0 +#define MESG(x) ((x) << 3) + .data .align 2 @@ -165,15 +168,15 @@ savecontext: /* global interrupt mask. This is however broken, see comments for osSetIntMask. */ la t0, __OSGlobalIntMask lw t0, (t0) - xor t2, t0, ~0 + xor t2, t0, 0xFFFFFFFF andi t2, t2, SR_IMASK or t4, t1, t2 and t3, k1, ~SR_IMASK - andi t0, t0, SR_IMASK or t3, t3, t4 + sw t3, THREAD_SR(k0) + andi t0, t0, SR_IMASK and t1, t1, t0 and k1, k1, ~SR_IMASK - sw t3, THREAD_SR(k0) or k1, k1, t1 savercp: /* Save the currently masked RCP interrupts. */ @@ -184,7 +187,7 @@ savercp: la t0, __OSGlobalIntMask lw t0, (t0) srl t0, t0, RCP_IMASKSHIFT - xor t0, t0, ~0 + xor t0, t0, 0xFFFFFFFF andi t0, t0, (RCP_IMASK >> RCP_IMASKSHIFT) lw t4, THREAD_RCP(k0) and t0, t0, t4 @@ -285,35 +288,146 @@ counter: MFC0( t1, C0_COMPARE) MTC0( t1, C0_COMPARE) /* Post counter message */ - li a0, OS_EVENT_COUNTER*8 + li a0, MESG(OS_EVENT_COUNTER) jal send_mesg /* Mask out interrupt and continue */ and s0, s0, ~CAUSE_IP8 b next_interrupt /** - * IP4/Cartridge Interrupt - * Signalled by the N64 Disk Drive + * N64: + * IP4/Cartridge Interrupt + * Signalled by the N64 Disk Drive + * iQue: + * IP4/BCP Interrupt + * New RCP Interrupts */ cart: - /* Load cart callback set by __osSetHWIntrRoutine */ - la t1, __osHwIntTable - lw t2, (OS_INTR_CART*HWINT_SIZE+HWINT_CALLBACK)(t1) /* Mask out interrupt */ and s0, s0, ~CAUSE_IP4 + /* Load cart callback set by __osSetHWIntrRoutine */ + la t1, __osHwIntTable + addi t1, t1, (OS_INTR_CART * HWINT_SIZE) + lw t2, HWINT_CALLBACK(t1) /* If the callback is NULL, handling is done */ - addi t1, t1, (OS_INTR_CART*HWINT_SIZE) - beqz t2, send_cart_mesg + beqz t2, 1f /* Set up a stack and run the callback */ lw sp, HWINT_SP(t1) jalr t2 - beqz v0, send_cart_mesg + beqz v0, 1f /* Redispatch immediately if the callback returned nonzero */ b redispatch -send_cart_mesg: +1: +#ifndef BBPLAYER /* Post a cart event message */ - li a0, OS_EVENT_CART*8 + li a0, MESG(OS_EVENT_CART) + jal send_mesg +#else + /* On the iQue Player the CART interrupt no longer exists. New RCP interrupts are vectored here */ + lw s1, PHYS_TO_K1(MI_EX_INTR_REG) + +flash: + /* Check for FLASH interrupt */ + andi t1, s1, MI_EX_INTR_FLASH + beqz t1, flashx + /* Mask it out */ + andi s1, s1, MI_EX_INTR_ALL & ~MI_EX_INTR_FLASH + /* Clear it */ + li t1, 0 + sw t1, PHYS_TO_K1(PI_NAND_CTRL_REG) + /* Send the event message */ + li a0, MESG(OS_EVENT_FLASH) + jal send_mesg +flashx: +md: + /* Check for MD interrupt */ + andi t1, s1, MI_EX_INTR_MD + beqz t1, mdx + /* Mask it out */ + andi s1, s1, MI_EX_INTR_ALL & ~MI_EX_INTR_MD + /* Clear it */ + li t1, MI_EX_INTR_CLR_MD + sw t1, PHYS_TO_K1(MI_EX_INTR_REG) + /* Send the event message */ + li a0, MESG(OS_EVENT_MD) + jal send_mesg +mdx: +aes: + /* Check for AES interrupt */ + andi t1, s1, MI_EX_INTR_AES + beqz t1, aesx + /* Mask it out */ + andi s1, s1, MI_EX_INTR_ALL & ~MI_EX_INTR_AES + /* Disable the interrupt, this does not clear it. + * The responsibility of clearing and re-enabling + * the interrupt is left to the handler. */ + li t1, MI_EX_INTR_MASK_CLR_AES + sw t1, PHYS_TO_K1(MI_EX_INTR_MASK_REG) + /* Send the event message */ + li a0, MESG(OS_EVENT_AES) + jal send_mesg +aesx: +ide: + /* Check for IDE interrupt */ + andi t1, s1, MI_EX_INTR_IDE + beqz t1, idex + /* Mask it out */ + andi s1, s1, MI_EX_INTR_ALL & ~MI_EX_INTR_IDE + /* Disable the interrupt, this does not clear it. + * The responsibility of clearing and re-enabling + * the interrupt is left to the handler. */ + li t1, MI_EX_INTR_MASK_CLR_IDE + sw t1, PHYS_TO_K1(MI_EX_INTR_MASK_REG) + /* Send the event message */ + li a0, MESG(OS_EVENT_IDE) + jal send_mesg +idex: +pi_err: + /* Check for PI_ERR Interrupt */ + andi t1, s1, MI_EX_INTR_PI_ERR + beqz t1, pi_errx + /* Mask it out */ + andi s1, s1, MI_EX_INTR_ALL & ~MI_EX_INTR_PI_ERR + /* Disable the interrupt, this does not clear it. + * The responsibility of clearing and re-enabling + * the interrupt is left to the handler. */ + li t1, MI_EX_INTR_MASK_CLR_PI_ERR + sw t1, PHYS_TO_K1(MI_EX_INTR_MASK_REG) + /* Send the event message */ + li a0, MESG(OS_EVENT_PI_ERR) jal send_mesg +pi_errx: +usb0: + /* Check for USB0 Interrupt */ + andi t1, s1, MI_EX_INTR_USB0 + beqz t1, usb0x + /* Mask it out */ + andi s1, s1, MI_EX_INTR_ALL & ~MI_EX_INTR_USB0 + /* Disable the interrupt, this does not clear it. + * The responsibility of clearing and re-enabling + * the interrupt is left to the handler. */ + li t1, MI_EX_INTR_MASK_CLR_USB0 + sw t1, PHYS_TO_K1(MI_EX_INTR_MASK_REG) + /* Send the event message */ + li a0, MESG(OS_EVENT_USB0) + jal send_mesg +usb0x: +usb1: + /* Check for USB1 Interrupt */ + andi t1, s1, MI_EX_INTR_USB1 + beqz t1, usb1x + /* Mask it out */ + andi s1, s1, MI_EX_INTR_ALL & ~MI_EX_INTR_USB1 + /* Disable the interrupt, this does not clear it. + * The responsibility of clearing and re-enabling + * the interrupt is left to the handler. */ + li t1, MI_EX_INTR_MASK_CLR_USB1 + sw t1, PHYS_TO_K1(MI_EX_INTR_MASK_REG) + /* Send the event message */ + li a0, MESG(OS_EVENT_USB1) + jal send_mesg +usb1x: +#endif /* Continue */ b next_interrupt @@ -326,10 +440,10 @@ rcp: /*! @bug this clobbers the t0 register which is expected to hold the value of the */ /*! C0_CAUSE register in the sw1 and sw2 handlers. If the sw1 or sw2 handler runs */ /*! after this, the interrupt will not be cleared properly. */ + lw s1, PHYS_TO_K1(MI_INTR_REG) la t0, __OSGlobalIntMask lw t0, (t0) srl t0, t0, RCP_IMASKSHIFT - lw s1, PHYS_TO_K1(MI_INTR_REG) and s1, s1, t0 /** @@ -338,17 +452,17 @@ rcp: /* Test for sp interrupt */ andi t1, s1, MI_INTR_SP beqz t1, vi - /* Test for yielded or done signals in particular */ - lw t4, PHYS_TO_K1(SP_STATUS_REG) - li t1, (SP_CLR_INTR | SP_CLR_SIG3) - andi t4, t4, (SP_STATUS_YIELDED | SP_STATUS_TASKDONE) /* Mask out SP interrupt */ andi s1, s1, (MI_INTR_SI | MI_INTR_AI | MI_INTR_VI | MI_INTR_PI | MI_INTR_DP) + lw t4, PHYS_TO_K1(SP_STATUS_REG) + /* Clear interrupt and signal 3 */ + li t1, (SP_CLR_INTR | SP_CLR_SIG3) sw t1, PHYS_TO_K1(SP_STATUS_REG) + /* Test for yielded or done signals in particular */ + andi t4, t4, (SP_STATUS_YIELDED | SP_STATUS_TASKDONE) beqz t4, sp_other_break - /* Clear interrupt and signal 3 */ /* Post an SP event message */ - li a0, OS_EVENT_SP*8 + li a0, MESG(OS_EVENT_SP) jal send_mesg beqz s1, NoMoreRcpInts /* Step over sp_other_break handler */ @@ -357,7 +471,7 @@ rcp: sp_other_break: /* An sp signal that is not due to yielding or task completion, such as */ /* an sp breakpoint. Post a different event message */ - li a0, OS_EVENT_SP_BREAK*8 + li a0, MESG(OS_EVENT_SP_BREAK) jal send_mesg beqz s1, NoMoreRcpInts @@ -373,7 +487,7 @@ vi: /* Clear interrupt */ sw zero, PHYS_TO_K1(VI_CURRENT_REG) /* Post vi event message */ - li a0, OS_EVENT_VI*8 + li a0, MESG(OS_EVENT_VI) jal send_mesg beqz s1, NoMoreRcpInts @@ -391,7 +505,7 @@ ai: li t1, 1 sw t1, PHYS_TO_K1(AI_STATUS_REG) /* Post ai event message */ - li a0, OS_EVENT_AI*8 + li a0, MESG(OS_EVENT_AI) jal send_mesg beqz s1, NoMoreRcpInts @@ -408,7 +522,7 @@ si: /* Clear interrupt */ sw zero, PHYS_TO_K1(SI_STATUS_REG) /* Post si event message */ - li a0, OS_EVENT_SI*8 + li a0, MESG(OS_EVENT_SI) jal send_mesg beqz s1, NoMoreRcpInts @@ -420,20 +534,15 @@ pi: andi t1, s1, MI_INTR_PI beqz t1, dp - /* Clear and mask the interrupt */ -#if LIBULTRA_VERSION < LIBULTRA_VERSION_J - li t1, PI_STATUS_CLR_INTR + /* Mask out pi interrupt */ andi s1, s1, (MI_INTR_SP | MI_INTR_SI | MI_INTR_AI | MI_INTR_VI | MI_INTR_DP) - sw t1, PHYS_TO_K1(PI_STATUS_REG) -#else /* Clear the interrupt */ li t1, PI_STATUS_CLR_INTR sw t1, PHYS_TO_K1(PI_STATUS_REG) +#if LIBULTRA_VERSION >= LIBULTRA_VERSION_J /* Load pi callback */ la t1, __osPiIntTable lw t2, HWINT_CALLBACK(t1) - /* Mask out pi interrupt */ - andi s1, s1, (MI_INTR_SP | MI_INTR_SI | MI_INTR_AI | MI_INTR_VI | MI_INTR_DP) /* Skip callback if NULL */ beqz t2, no_pi_callback /* Set up a stack and run the callback */ @@ -445,7 +554,7 @@ pi: #endif no_pi_callback: /* Post pi event message */ - li a0, OS_EVENT_PI*8 + li a0, MESG(OS_EVENT_PI) jal send_mesg skip_pi_mesg: beqz s1, NoMoreRcpInts @@ -464,7 +573,7 @@ dp: li t1, MI_CLR_DP_INTR sw t1, PHYS_TO_K1(MI_INIT_MODE_REG) /* Post dp event message */ - li a0, OS_EVENT_DP*8 + li a0, MESG(OS_EVENT_DP) jal send_mesg NoMoreRcpInts: @@ -494,11 +603,11 @@ firstnmi: li t2, 1 sw t2, (t1) /* Post a PreNMI event message */ - li a0, OS_EVENT_PRENMI*8 + li a0, MESG(OS_EVENT_PRENMI) jal send_mesg /* Mask out and disable IP5/PreNMI interrupt for the highest priority thread */ - lw t2, __osRunQueue and s0, s0, ~SR_IBIT5 + lw t2, __osRunQueue lw k1, THREAD_SR(t2) and k1, k1, ~SR_IBIT5 sw k1, THREAD_SR(t2) @@ -510,7 +619,7 @@ sw2: and t0, t0, ~CAUSE_SW2 MTC0( t0, C0_CAUSE) /* Post sw2 event message */ - li a0, OS_EVENT_SW2*8 + li a0, MESG(OS_EVENT_SW2) jal send_mesg /* Mask out interrupt and continue */ and s0, s0, ~CAUSE_SW2 @@ -521,7 +630,7 @@ sw1: and t0, t0, ~CAUSE_SW1 MTC0( t0, C0_CAUSE) /* Post sw1 event message */ - li a0, OS_EVENT_SW1*8 + li a0, MESG(OS_EVENT_SW1) jal send_mesg /* Mask out interrupt and continue */ and s0, s0, ~CAUSE_SW1 @@ -532,15 +641,15 @@ handle_break: li t1, OS_FLAG_CPU_BREAK sh t1, THREAD_FLAGS(k0) /* Post a cpu break event message */ - li a0, OS_EVENT_CPU_BREAK*8 + li a0, MESG(OS_EVENT_CPU_BREAK) jal send_mesg /* Redispatch */ b redispatch redispatch: - lw t2, __osRunQueue /* Get priority of previously running thread */ lw t1, THREAD_PRI(k0) + lw t2, __osRunQueue /* Get highest priority from waiting threads */ lw t3, THREAD_PRI(t2) bge t1, t3, enqueueRunning @@ -578,7 +687,7 @@ panic: MFC0( t2, C0_BADVADDR) sw t2, THREAD_BADVADDR(k0) /* Post the fault message */ - li a0, OS_EVENT_FAULT*8 + li a0, MESG(OS_EVENT_FAULT) jal send_mesg /* Dispatch next thread */ j __osDispatchThread @@ -587,12 +696,12 @@ panic: * Handles posting event messages to the listening message queue, if there is one */ send_mesg: + /* Save return address */ + move s2, ra /* Load pointer to listening message queue */ la t2, __osEventStateTab addu t2, t2, a0 lw t1, (t2) - /* Save return address */ - move s2, ra /* If there is no listening message queue, done */ beqz t1, send_done @@ -606,14 +715,13 @@ send_mesg: addu t5, t5, t3 rem t5, t5, t4 lw t4, MQ_MSG(t1) - sll t5, t5, 2 + mul t5, t5, 4 addu t4, t4, t5 - /* Fetch the message to post */ - lw t5, 4(t2) - addiu t2, t3, 1 /* Post the message to the message queue */ + lw t5, 4(t2) sw t5, (t4) /* Increment the validCount */ + addiu t2, t3, 1 sw t2, MQ_VALIDCOUNT(t1) /* If there was a thread blocked on this message queue, */ /* wake it up */ @@ -638,10 +746,10 @@ handle_CpU: li t2, 1 /* if not coprocessor 1, panic */ bne t1, t2, panic /* Mark cop1 as usable for previous thread */ - lw k1, THREAD_SR(k0) li t1, 1 - or k1, k1, SR_CU1 sw t1, THREAD_FP(k0) + lw k1, THREAD_SR(k0) + or k1, k1, SR_CU1 sw k1, THREAD_SR(k0) b enqueueRunning END(__osException) @@ -658,7 +766,6 @@ LEAF(__osEnqueueAndYield) lw a1, __osRunningThread /* Save SR */ MFC0( t0, C0_SR) - lw k1, THREAD_FP(a1) ori t0, t0, SR_EXL sw t0, THREAD_SR(a1) /* Save callee-saved registers */ @@ -676,15 +783,16 @@ LEAF(__osEnqueueAndYield) sd ra, THREAD_RA(a1) sw ra, THREAD_PC(a1) /* Save FPU callee-saved registers if the current thread has used the FPU */ + lw k1, THREAD_FP(a1) beqz k1, 1f cfc1 k1, C1_FPCSR + sw k1, THREAD_FPCSR(a1) sdc1 $f20, THREAD_FP20(a1) sdc1 $f22, THREAD_FP22(a1) sdc1 $f24, THREAD_FP24(a1) sdc1 $f26, THREAD_FP26(a1) sdc1 $f28, THREAD_FP28(a1) sdc1 $f30, THREAD_FP30(a1) - sw k1, THREAD_FPCSR(a1) 1: lw k1, THREAD_SR(a1) andi t1, k1, SR_IMASK @@ -693,7 +801,7 @@ LEAF(__osEnqueueAndYield) /* See the comment there for more about this. */ la t0, __OSGlobalIntMask lw t0, (t0) - xor t0, t0, ~0 + xor t0, t0, 0xFFFFFFFF andi t0, t0, SR_IMASK or t1, t1, t0 and k1, k1, ~SR_IMASK @@ -706,10 +814,10 @@ LEAF(__osEnqueueAndYield) /* See the comment there for more about this. */ la k0, __OSGlobalIntMask lw k0, (k0) - lw t0, THREAD_RCP(a1) srl k0, k0, RCP_IMASKSHIFT - xor k0, k0, ~0 + xor k0, k0, 0xFFFFFFFF andi k0, k0, (RCP_IMASK >> RCP_IMASKSHIFT) + lw t0, THREAD_RCP(a1) and k0, k0, t0 or k1, k1, k0 3: @@ -733,9 +841,9 @@ END(__osEnqueueAndYield) * Enqueues `thread` to the thread queue `threadQueue`, inserted by priority */ LEAF(__osEnqueueThread) + move t9, a0 lw t8, (a0) lw t7, THREAD_PRI(a1) - move t9, a0 lw t6, THREAD_PRI(t8) /* If the current highest priority thread is a lower priority than */ /* the new thread, skip searching the queue */ @@ -832,8 +940,8 @@ LEAF(__osDispatchThread) lw k1, THREAD_SR(k0) la t0, __OSGlobalIntMask lw t0, (t0) - andi t1, k1, SR_IMASK andi t0, t0, SR_IMASK + andi t1, k1, SR_IMASK and t1, t1, t0 and k1, k1, ~SR_IMASK or k1, k1, t1 @@ -866,13 +974,13 @@ LEAF(__osDispatchThread) ld t8, THREAD_T8(k0) ld t9, THREAD_T9(k0) ld gp, THREAD_GP(k0) + ld sp, THREAD_SP(k0) + ld fp, THREAD_S8(k0) + ld ra, THREAD_RA(k0) ld k1, THREAD_LO(k0) mtlo k1 ld k1, THREAD_HI(k0) mthi k1 - ld sp, THREAD_SP(k0) - ld fp, THREAD_S8(k0) - ld ra, THREAD_RA(k0) /* Move thread pc to EPC so that eret will return execution to where the thread left off */ lw k1, THREAD_PC(k0) MTC0( k1, C0_EPC) diff --git a/src/libultra/os/parameters.s b/src/libultra/os/parameters.s index 179dbcf02..8fb324d24 100644 --- a/src/libultra/os/parameters.s +++ b/src/libultra/os/parameters.s @@ -23,4 +23,26 @@ IPL_SYMBOL(osVersion, 0x80000314, 4) IPL_SYMBOL(osMemSize, 0x80000318, 4) IPL_SYMBOL(osAppNMIBuffer, 0x8000031C, 0x40) +#ifdef BBPLAYER + +IPL_SYMBOL(__osBbEepromAddress, 0x8000035C, 4) +IPL_SYMBOL(__osBbEepromSize, 0x80000360, 4) +IPL_SYMBOL(__osBbFlashAddress, 0x80000364, 4) +IPL_SYMBOL(__osBbFlashSize, 0x80000368, 4) +IPL_SYMBOL(__osBbSramAddress, 0x8000036C, 4) +IPL_SYMBOL(__osBbSramSize, 0x80000370, 4) +IPL_SYMBOL(__osBbPakAddress, 0x80000374, 0x10) +IPL_SYMBOL(__osBbPakSize, 0x80000384, 4) +IPL_SYMBOL(__osBbIsBb, 0x80000388, 4) +IPL_SYMBOL(__osBbHackFlags, 0x8000038C, 4) +IPL_SYMBOL(__osBbStashMagic, 0x80000390, 4) +IPL_SYMBOL(__osBbPakBindings, 0x80000394, 0x10) +IPL_SYMBOL(__osBbStateName, 0x800003A4, 0x10) +IPL_SYMBOL(__osBbStateDirty, 0x800003B4, 4) +IPL_SYMBOL(__osBbAuxDataLimit, 0x800003B8, 4) + +.space 0x30 + +#endif + .space 0x60 diff --git a/tools/disasm/ique-cn/files_boot.csv b/tools/disasm/ique-cn/files_boot.csv index 9a878030a..0aae45345 100644 --- a/tools/disasm/ique-cn/files_boot.csv +++ b/tools/disasm/ique-cn/files_boot.csv @@ -134,7 +134,7 @@ A7A0,8000ABF0,src/boot/boot_main B190,8000B5E0,src/boot/idle BD90,8000C1E0,src/boot/z_std_dma C500,8000C950,src/boot/zlib -FBB0,80010000,src/boot/driverominit +10310,80010760,src/boot/driverominit 10390,800107E0,src/libultra/io/vimgr 115B0,80011A00,src/libultra/io/pimgr 12940,80012D90,data/boot_common_80012D90 diff --git a/tools/patch_ique_driverominit.py b/tools/patch_ique_driverominit.py new file mode 100755 index 000000000..f7ca9daac --- /dev/null +++ b/tools/patch_ique_driverominit.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +import struct, sys, argparse + +import elftools.elf.elffile + +# Patches driverominit.o to change bnez t6,3c to nop at offset 0x20 in the .text section + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + + parser.add_argument("file", help="input file") + args = parser.parse_args() + + with open(args.file, "r+b") as f: + elf = elftools.elf.elffile.ELFFile(f) + + text_offset = 0 + for section in elf.iter_sections(): + if section.name == ".text": + text_offset = section["sh_offset"] + break + + if text_offset == 0: + print("Error: .text section not found") + sys.exit(1) + + f.seek(text_offset + 0x20) + instruction = struct.unpack(">I", f.read(4))[0] + if instruction != 0x15C00006: # bnez t6,3c + print("Error: expected instruction not found, found 0x%08X" % instruction) + sys.exit(1) + + f.seek(text_offset + 0x20) + f.write(struct.pack(">I", 0x00000000)) # nop