;******************************************************************** ; IRIS-SUBPモニタプログラム サブルーチン群 ;******************************************************************** AREA IrisSubpCrt0Sub, CODE, READONLY INCLUDE IrisSubpDefineArm.s INCLUDE IrisSubpMemoryMapArm.s INCLUDE IrisSubpMonDefineArm.s INCLUDE IrisSubpMonMemoryMapArm.s MON_ONLY NDEBUG2 ;-------------------------------------------------------------------- ; 割り込み分岐処理 ;-------------------------------------------------------------------- ; IF :DEF: SYSCALL_ASM GLOBAL intr_main EXTERN intrTable ALIGN CODE32 intr_main mov r12, #REG_BASE ; IE/IF チェック add r3, r12, #OFFSET_REG_IE ; r3: REG_IE ldmia r3, {r1-r2} and r1, r1, r2 ; r1: IE & IF mov r2, #0 ands r0, r1, #CARD_DATA_INTR_FLAG ; カードデータ転送終了 割り込み bne jump_intr add r2, r2, #4 ands r0, r1, #TIMER3_INTR_FLAG ; カードタイマー 割り込み bne jump_intr add r2, r2, #4 ands r0, r1, #V_BLANK_INTR_FLAG ; Vブランク 割り込み jump_intr str r0, [r3, #REG_IF - REG_IE] ; IF クリア ldr r1, =intrTable ; ユーザIRQ処理へジャンプ add r1, r1, r2 ldr r0, [r1] bx r0 ;----------------------------------------------------------------------- ; ループ待ち(r0=loopCount) ;----------------------------------------------------------------------- GLOBAL WaitByLoop ALIGN CODE16 WaitByLoop sub r0, #1 bgt WaitByLoop bx lr ;-------------------------------------------------------------------- ;- Vブランク割り込みウェイト - ;-------------------------------------------------------------------- GLOBAL WaitVBlankIntr ALIGN CODE32 WaitVBlankIntr mov r0, #1 mov r1, #V_BLANK_INTR_FLAG ;-------------------------------------------------------------------- ; 割り込みウェイト(r0=initCheckClear, r1=intrFlag) ;-------------------------------------------------------------------- GLOBAL WaitIntr CODE32 WaitIntr stmfd sp!, {lr} cmp r0, #0 blne WaitIntr_sub ; IfCheck クリア 0 mov lr, #0x80 strb lr, [r12,#REG_PAUSE+1 - REG_BASE] ; SVC_Halt() REG_PAUSE = 0x80 nop nop bl WaitIntr_sub beq %b0 ; while (!(IfCheck & IfFlags)) ldmfd sp!, {lr} bx lr WaitIntr_sub IF :DEF: BB_MON ldr r12,=CPU_WRAM_END ELSE mov r12,#REG_BASE ; r12: #REG_BASE ENDIF str r12,[r12,#REG_IME - REG_BASE] ; IME = 0 ldr r2, [r12, #INTR_CHECK_BUF - CPU_WRAM_END] ands r0, r1, r2 ; IfCheck 判定 eorne r2, r2, r0 ; IfCheck クリア strne r2, [r12, #INTR_CHECK_BUF - CPU_WRAM_END] mov r0, #1 str r0, [r12,#REG_IME - REG_BASE] ; IME = 1 bx lr ;-------------------------------------------------------------------- ; サウンドBIAS 変更 (r0=up_down, r1=stepLoops) ;-------------------------------------------------------------------- ; IF :DEF: SYSCALL_ASM GLOBAL ChangeSoundBias16 CODE16 ChangeSoundBias16 1 mov r2, #2 ; r12: 0x200 lsl r2, #8 mov r12, r2 ldr r3, =REG_SOUNDBIAS ; r3: soundBiasp = REG_SOUNDBIAS ldrh r2, [r3, #0] ; r2: *soundBiasp ldr r3, =REG_SOUNDBIAS cmp r0, #0 ; if (up_down) beq %f2 cmp r2, r12 ; if (*soundBiasp >= 0x200) break; bge %f5 add r2, #1 ; *soundBiasp += 1 b %f3 2 cmp r2, #0 ; if (*soundBiasp <= 0) break; ble %f5 sub r2, #1 ; *soundBiasp -= 1 3 strh r2, [r3, #0] mov r2, r1 ; for (i=stepLoops; --i>=0; ) ; 4 sub r2,#1 bpl %b4 b %b1 5 bx lr ; ENDIF ;-------------------------------------------------------------------- ; BIOS領域専用コピー (r0=srcp, r1=destp, r2=size) ;-------------------------------------------------------------------- EXTERN SecureAreaEndp GLOBAL CopyBiosArea CopyBiosArea add r2, r1 1 ldr r3, =SecureAreaEndp cmp r0, r3 bge %b2 ldmia r0!, {r3} ; *((vu32 *)(destp))++ = *((vu32 *)(srcp))++ stmia r1!, {r3} cmp r1, r2 blt %b1 2 mov pc, lr ;-------------------------------------------------------------------- ; セキュリティ・キー解除 & Nintendoロゴ コピー ;-------------------------------------------------------------------- IF :DEF: TEST_AGB_MODE KEY_START_BLOCK_NO * 3 ; キー・スタート ブロックNo EXTERN NinLogoBak ; EXTERN NinLogoCopy EXTERN DacsCheck GLOBAL key_unlock__nin_logo_copy CODE16 key_unlock__nin_logo_copy push {r3, r4-r6, lr} mov r6, #0x8 ; r6: ROM_BANK0 lsl r6, #24 mov r5, #MON_KEY_GROUP_NO - CARTRIDGE add r5, r6 ; r5: MON_KEY_GROUP_NO sub r0, r5, #1 ; r4: キー No オフセット 算出 mov r1, #27 ; Srcp=MON_KEY_GROUP_NO-1,Count=27 bl GetKeyNo ; mov r0, #2 ; ダミー キー No mov r4, #2*6 mul r4, r0 ldrb r3, [r5] ; r3: キーグループ No(0-3) * 48 ; lsl r3, #32-2 ;(r2: キーグループ オフセット固定 ダミー読み込み) ; lsr r3, #32-2 ; mov r2, #2*6*4 ; mul r2, r3 ; add r4, r2 ; r4: キー No 算出 (キーグループ オフセット加算無し) adr r5, key_addr ; r5: キー・アドレス add r5, r4 mov r4, #0 nin_copy mov r0, r4 bl NinLogoCopy ; Nintendoロゴ コピー (20*10Byte) cmp r4, #KEY_START_BLOCK_NO blt key_unlock_end cmp r4, #KEY_START_BLOCK_NO + 6 bge key_unlock_end key_unlock ldrh r1, [r5] ; r1: キー・アドレス 読み込み lsl r1, #1 orr r1, r6 ldrh r0, [r1] add r5, #2 key_unlock_end add r4, #1 cmp r4, #11 bne nin_copy pop {r3, r4-r6, pc} INCLUDE crt0KeyAddr.s ENDIF ;-------------------------------------------------------------------- ; キーNo 算出 (r0=Srcp, r1=Count → r0=KeyNo:2) ;-------------------------------------------------------------------- IF :DEF: TEST_AGB_MODE GLOBAL GetKeyNo CODE16 GetKeyNo push {r4, r5, lr} mov r4, #3 ; r4: Ror mov r3, #0 ; r3: KeyNo GetKeyNo_10 ldrb r2, [r0, #0] ; r2: *Srcp ror r3, r4 mov r5, #4 ; r5: RorCount GetKeyNo_20 eor r3, r2 lsl r2, #8 sub r5, #1 ; while (--RorCount > 0) bgt GetKeyNo_20 add r0, #1 sub r1, #1 ; while (--Count > 0) bgt GetKeyNo_10 mov r0, r3 lsl r0, #32-5 lsr r0, #32-2 pop {r4, r5, pc} ENDIF ;-------------------------------------------------------------------- ; NINTENDOロゴ コピー (r0=BlockNo) ;-------------------------------------------------------------------- IF :DEF: TEST_AGB_MODE GLOBAL NinLogoCopy CODE16 NinLogoCopy push {r4, lr} mov r4, #20 ; r4: BlockOffset = BlockNo * 20 mul r4, r0 mov r3, #0x8 ; r3: ROM_BANK0 lsl r3, #24 add r0, r3, #4 ; r0: &((u8 *)ROM_BANK0)[BlockOffset + OFFSET_MON_NINLOGO] add r0, r4 ldr r1, =NinLogoBak+36 ; r1: &NinLogoBak[BlockOffset + 36] add r1, r4 mov r2, #10 ; r2: 0x0000000A (16bit転送10回) bl CpuSet16_32 ; CpuCopy16_32() pop {r4, pc} ENDIF LTORG ;-------------------------------------------------------------------- ; 汎用符号付き割り算(r0/r1→r0',r0%r1→r1',|r0'|→r3') ;-------------------------------------------------------------------- ; IF :DEF: SYSCALL_ASM GLOBAL DivS32 ALIGN CODE32 DivS32 ands r3, r1, #0x80000000 ; r1: 除数の絶対値 rsbmi r1, r1, #0 eors r12,r3, r0, asr #32 ; r12: d31=結果の符合,d30=被除数の符号 rsbcs r0, r0, #0 ; r0: 被除数の絶対値 movs r2, r1 ; r2: コントロール・ビット ; beq devide_by_zero divide_just_l cmp r2, r0, lsr #1 movls r2, r2, lsl #1 blo divide_just_l divide_div_l cmp r0, r2 ; 減算できるかチェック adc r3, r3, r3 ; r3*2 + キャリー subcs r0, r0, r2 ; 減算可能なら減算 teq r2, r1 ; 終了チェック movne r2, r2, lsr #1 ; 終了でなければ2で割り再チェック bne divide_div_l mov r1, r0 mov r0, r3 movs r12,r12,lsl #1 rsbcs r0, r0, #0 rsbmi r1, r1, #0 bx lr ; ENDIF ;-------------------------------------------------------------------- ; 平方根算出(r0=param) ;-------------------------------------------------------------------- ; IF :DEF: SYSCALL_ASM GLOBAL SqrtU32 ALIGN CODE32 SqrtU32 stmfd sp!, {r4} mov r12,r0 ; r12: ParamBak mov r1, #1 1 cmp r0, r1 movhi r0, r0, lsr #1 movhi r1, r1, lsl #1 bhi %b1 2 mov r0, r12 ; r0: 被除数 mov r4, r1 ; r1: 除数 mov r3, #0 ; r3: 商 mov r2, r1 ; r2: コントロール・ビット 3 cmp r2, r0, lsr #1 movls r2, r2, lsl #1 blo %b3 4 cmp r0, r2 ; 減算できるかチェック adc r3, r3, r3 ; r3*2 + キャリー subcs r0, r0, r2 ; 減算可能なら減算 teq r2, r1 ; 終了チェック movne r2, r2, lsr #1 ; 終了でなければ2で割り再チェック bne %b4 add r1, r1, r3 movs r1, r1, lsr #1 cmp r1, r4 bcc %b2 mov r0, r4 ldmfd sp!, {r4} bx lr ; ENDIF ;-------------------------------------------------------------------- ; CPU セット (r0=srcp, r1=destp, r2=dmaCntData) ;-------------------------------------------------------------------- ; IF :DEF: SYSCALL_ASM GLOBAL CpuSet16_32 CODE16 CpuSet16_32 push {r4, r5, lr} lsl r4, r2, #11 ; r4: size = (dmaCntData & 0x1fffff)*4 lsr r4, #11-2 bl CheckSrcp16_32 ; ソースアドレス チェック IF :DEF: CHECK_PROT_ADDR ELSE beq %f6 ENDIF 0 mov r5, #0 ; r5: i = 0 lsr r3, r2, #27 ; if ((dmaCntData) & DMA_32BIT_BUS) bcc %f3 add r5, r1, r4 ; r5: destEndp = destp + size lsr r3, r2, #25 ; if ((dmaCntData) & DMA_SRC_FIX) bcc %f2 ldmia r0!, {r3} 1 cmp r1, r5 ; while (destp < destEndp) bge %f6 stmia r1!, {r3} ; *((vu32 *)(destp))++ = *((vu32 *)(srcp)) b %b1 2 cmp r1, r5 ; while (destp < destEndp) bge %f6 ldmia r0!, {r3} ; *((vu32 *)(destp))++ = *((vu32 *)(srcp))++ stmia r1!, {r3} b %b2 3 lsr r4, #1 lsr r3, r2, #25 ; if ((dmaCntData) & DMA_SRC_FIX) bcc %f5 ldrh r3, [r0, #0] 4 cmp r5, r4 ; for ( ; isrcNum movs r12, r7 ; r12: srcCount bl CheckSrcp ; ソースアドレス チェック beq %f6 0 ldrb r6, [r2, #2] ; r6: srcBitNum = unPackBitsParamp->srcBitNum rsb r10, r6, #8 ; r10: srcBitNumInv = 8 - srcBitNum mov r14, #0 ; r14: destBak = 0 ldr r11, [r2, #4] ; r8: destOffset0_On mov r8, r11, lsr #31 ; = unPackBitsParamp->destOffset0_On ldr r11,[r2, #4] ; destOffset = unPackBitsParamp->destOffset mov r11,r11, lsl #1 mov r11,r11, lsr #1 str r11,[sp, #0] ldrb r2, [r2, #3] ; r2: destBitNum = unPackBitsParamp->destBitNum mov r3, #0 ; r3: destBitCount = 0 1 subs r7, r7, #1 ; while (--srcNum >= 0) blt %f6 mov r11, #0xff ; r5: srcMask = 0xff >> srcBitNumInv mov r5, r11, asr r10 ldrb r9, [r0], #1 ; r9: srcTmp = *srcp++ mov r4, #0 ; r4: srcBitCount = 0 2 cmp r4, #8 ; while (srcBitCount < 8) bge %b1 and r11, r9, r5 ; r12: destTmp = ((srcTmp&srcMask) >>srcBitCount) movs r12, r11, lsr r4 cmpeq r8, #0 beq %f4 3 ldr r11, [sp, #0] ; destTmp += destOffset add r12, r12, r11 4 orr r14, r14, r12, lsl r3 ; destBak |= destTmp << destBitCount add r3, r3, r2 ; destBitCount += destBitNum cmp r3, #0x20 ; if (destBitCount >= 32) blt %f5 str r14, [r1], #4 ; *destp++ = destBak mov r14, #0 ; destBak = 0 mov r3, #0 ; destBitCount = 0 5 mov r5, r5, lsl r6 ; srcMask <<= srcBitNum add r4, r4, r6 ; srcBitCount += srcBitNum b %b2 6 add sp, sp, #4 ldmfd sp!, {r4-r11, lr} bx lr ; ENDIF ;-------------------------------------------------------------------- ; LZ77データ展開(8Bit→8Bit)(r0=srcp, r1=destp) ;-------------------------------------------------------------------- ; IF :DEF: SYSCALL_ASM GLOBAL UnCompLZ77Byte ALIGN CODE32 UnCompLZ77Byte stmfd sp!, {r4-r6, lr} ldr r5, [r0], #4 ; r2: destCount = *(u32 *)srcp >> 8 mov r2, r5, lsr #8 ; r0: srcp += 4 movs r12, r2 ; r12: srcCount bl CheckSrcp ; ソースアドレス チェック beq %f6 1 cmp r2, #0 ; while (destCount > 0) ble %f6 ldrb r14, [r0], #1 ; r14: flags = *srcp++ mov r4, #8 ; for (i=8; --i>=0; ) 2 subs r4, r4, #1 blt %b1 tst r14, #0x80 ; if (!(flags & 0x80)) bne %f3 ldrb r6, [r0], #1 ; *srcp++ strb r6, [r1], #1 ; r1: *destp++ sub r2, r2, #1 ; destCount-- b %f5 3 ldrb r5, [r0, #0] ; r3: length = (*srcp >> 4) + 3 mov r6, #3 add r3, r6, r5, asr #4 ldrb r6, [r0], #1 ; r12: offset = (*srcp++ & 0x0f) << 8 and r5, r6, #0xf mov r12,r5, lsl #8 ldrb r6, [r0], #1 ; offset = (offset | *srcp++) + 1 orr r5, r6, r12 add r12, r5, #1 sub r2, r2, r3 ; destCount -= length 4 ldrb r5, [r1, -r12] ; *destp++ = destp[-offset] strb r5, [r1], #1 subs r3, r3, #1 ; while (--length > 0) bgt %b4 5 cmp r2, #0 ; if (destCount <= 0) break; movgt r14, r14, lsl #1 ; flags <<= 1 bgt %b2 b %b1 6 ldmfd sp!, {r4-r6, lr} bx lr ; ENDIF ;-------------------------------------------------------------------- ; ランレングスデータ展開(8Bit→8Bit)(r0=srcp, r1=destp) ;-------------------------------------------------------------------- ; IF :DEF: SYSCALL_ASM GLOBAL UnCompRLByte CODE16 UnCompRLByte push {r4-r7, lr} ldmia r0!, {r3} ; r7: destCount = *(u32 *)srcp >> 8 lsr r7, r3, #8 ; r0: srcp += 4 mov r4, r7 ; r4: count bl CheckSrcp16_32 ; ソースアドレス チェック beq %f5 1 cmp r7, #0 ; while (destCount > 0) ble %f5 ldrb r4, [r0, #0] ; r4: flags = *srcp++ add r0, #1 lsl r2, r4, #25 ; r2: length = flags & 0x7f lsr r2, #25 lsr r3, r4, #8 ; if (!(flags & 0x80)) bcs %f3 add r2, #1 ; length++ sub r7, r2 ; destCount -= length 2 ldrb r3, [r0, #0] ; *destp++ = *srcp++ strb r3, [r1, #0] add r0, #1 add r1, #1 sub r2, r2, #1 ; while (--length > 0) bgt %b2 b %b1 3 add r2, #3 ; length += 3 sub r7, r2 ; destCount -= length ldrb r5, [r0, #0] ; srcTmp = *srcp++ add r0, #1 4 strb r5, [r1, #0] ; *destp++ = srcTmp add r1, #1 sub r2, r2, #1 ; while (--length > 0) bgt %b4 b %b1 5 pop {r4-r7} pop {r0} ; ENDIF ;-------------------------------------------------------------------- ; r0レジスタによるルーチン呼び出し ;-------------------------------------------------------------------- GLOBAL __call_via_r0 CODE16 __call_via_r0 bx r0 ;-------------------------------------------------------------------- ; r1レジスタによるルーチン呼び出し ;-------------------------------------------------------------------- GLOBAL __call_via_r1 CODE16 __call_via_r1 bx r1 ;-------------------------------------------------------------------- ; r2レジスタによるルーチン呼び出し ;-------------------------------------------------------------------- GLOBAL __call_via_r2 CODE16 __call_via_r2 bx r2 ;-------------------------------------------------------------------- ; r3レジスタによるルーチン呼び出し ;-------------------------------------------------------------------- GLOBAL __call_via_r3 CODE16 __call_via_r3 bx r3 ;-------------------------------------------------------------------- ; r4レジスタによるルーチン呼び出し ;-------------------------------------------------------------------- GLOBAL __call_via_r4 CODE16 __call_via_r4 bx r4 ;-------------------------------------------------------------------- ; r5レジスタによるルーチン呼び出し ;-------------------------------------------------------------------- GLOBAL __call_via_r5 CODE16 __call_via_r5 bx r5 END