mirror of
https://github.com/rvtr/ntr_bootrom.git
synced 2025-10-31 07:11:11 -04:00
724 lines
18 KiB
C
724 lines
18 KiB
C
//*******************************************************************
|
||
// IRIS-SUBPモニタプログラム サブルーチン
|
||
//*******************************************************************
|
||
#include "IrisSubpMon.h"
|
||
|
||
|
||
|
||
|
||
//--------------------- グローバル 変数 -------------------------------
|
||
|
||
SharedWork *sharedWorkp; // 共有ワークポインタ
|
||
SecureWork *secureWorkp; // セキュア情報ワークポインタ
|
||
|
||
IntrFuncp intrTable[4]; // 割り込みテーブル
|
||
|
||
u32 CharTmpBuf[0x200/4];
|
||
u16 NinLogoBak[256/2];
|
||
|
||
|
||
//----------------------------------------------------------------------
|
||
// レジスタ初期化
|
||
//----------------------------------------------------------------------
|
||
|
||
void InitReg(void)
|
||
{
|
||
*(vu32 *)REG_IME = 0; // IME クリア
|
||
*(vu32 *)REG_IE = 0; // IE クリア
|
||
*(vu32 *)REG_IF = -1; // IF クリア
|
||
|
||
#ifdef BOOT_FROM_CARTRIDGE
|
||
|
||
*(vu16 *)REG_POWCNT = POW_SOUND_ON; // サウンドON
|
||
ChangeSoundBias16(1, 8) ; // サウンドバイアス セット
|
||
|
||
#endif // BOOT_FROM_CARTRIDGE
|
||
|
||
}
|
||
|
||
//----------------------------------------------------------------------
|
||
// メモリ初期化
|
||
//----------------------------------------------------------------------
|
||
|
||
void PreInitRam(void)
|
||
{
|
||
CpuClearFast32(0, CPU_WRAM_END - 0x4000, 0x4000 - 512); // ARM7用ワーク領域 後半16KBクリア
|
||
}
|
||
|
||
void PostInitRam(void)
|
||
{
|
||
CpuClearFast32(0, CPU_WRAM, 0x4000); // ARM7用ワーク領域 前半16KBクリア
|
||
}
|
||
|
||
//----------------------------------------------------------------------
|
||
// メインメモリSECURE領域(先頭64KB) クリア
|
||
//----------------------------------------------------------------------
|
||
|
||
void ClearMmemSecureArea(void)
|
||
{
|
||
CpuClearFast32(0, MAIN_MEM, MROM_SECURE_SIZE * 4);
|
||
}
|
||
|
||
|
||
//----------------------------------------------------------------------
|
||
// CRC16bit 算出
|
||
//----------------------------------------------------------------------
|
||
|
||
const u16 crc16_table[16] = {
|
||
0x0000, 0xCC01, 0xD801, 0x1400,
|
||
0xF001, 0x3C00, 0x2800, 0xE401,
|
||
0xA001, 0x6C00, 0x7800, 0xB401,
|
||
0x5000, 0x9C01, 0x8801, 0x4400
|
||
};
|
||
|
||
u16 GetCRC16(u32 start, u16 *datap, u32 size)
|
||
{
|
||
u16 *dataEndp = datap + size/2;
|
||
u16 data16;
|
||
u32 shift = 0;
|
||
u16 r1, total = start;
|
||
|
||
while(datap < dataEndp) {
|
||
if (!shift) data16 = *datap;
|
||
|
||
// 4bit単位
|
||
r1 = crc16_table[total & 0xf];
|
||
total = (total >>4);
|
||
total = total ^ r1 ^ crc16_table[(data16 >>shift) & 0xf];
|
||
|
||
shift += 4;
|
||
if (shift >= 0x10) {
|
||
shift = 0;
|
||
datap++;
|
||
}
|
||
}
|
||
|
||
return total;
|
||
}
|
||
|
||
|
||
//----------------------------------------------------------------------
|
||
// メインメモリ 拡張チェック
|
||
//----------------------------------------------------------------------
|
||
|
||
const u16 mmemSizeCheckTable[] = {0x56a9, 0x695a, 0xa695, 0x96a5};
|
||
|
||
s32 IsMmem8MB(void)
|
||
{
|
||
u32 mmemExFlag = 0;
|
||
int i;
|
||
|
||
#ifdef ENABLE_DEBUGGER_ON_4MB
|
||
|
||
return 1;
|
||
|
||
#endif // ENABLE_DEBUGGER_ON_4MB
|
||
|
||
for (i=0; i<4; i++) {
|
||
*(vu16 *)MMEM_CHK_SIZE_WRITE_BUF = mmemSizeCheckTable[i];
|
||
if (*(vu16 *)MMEM_CHK_SIZE_READ_BUF != mmemSizeCheckTable[i]) mmemExFlag++;
|
||
}
|
||
*(vu16 *)MMEM_CHK_SIZE_WRITE_BUF = 0;
|
||
|
||
return (mmemExFlag >= 3);
|
||
}
|
||
|
||
|
||
//----------------------------------------------------------------------
|
||
// デバッガ上か?
|
||
//----------------------------------------------------------------------
|
||
extern u16 sio_handshake_data[];
|
||
extern u16 sio_send_code;
|
||
extern u16 sio_recv_code;
|
||
extern u16 sio_add_code;
|
||
|
||
#define SIO_SEND_CODE 0x4e54
|
||
#define SIO_RECV_CODE 0x4944
|
||
#define SIO_ADD_CODE 0x524f
|
||
#define SYSROM_VERSION 0x0100
|
||
|
||
void SendSioData(u32 data) // SIOデータ送信
|
||
{
|
||
*(vu32 *)REG_SIODATA32 = data;
|
||
|
||
StartSio();
|
||
WaitSio();
|
||
|
||
WaitByLoop(0x8000/4); // 0.97ms待ち
|
||
while (!IsSioSendEnable()) ;
|
||
}
|
||
|
||
s32 CheckSioData(u32 data, u32 checkMask) // SIO戻り値チェック
|
||
{
|
||
|
||
#ifndef DISABLE_SECURE_CODE
|
||
|
||
if ((*(vu32 *)REG_SIODATA32 & checkMask)
|
||
!= ((((data + sio_add_code) & 0xffff) | (~data & 0xffff0000)) & checkMask))
|
||
return 0;
|
||
|
||
#endif // DISABLE_SECURE_CODE
|
||
|
||
return 1;
|
||
}
|
||
|
||
void CheckDebugger(void)
|
||
{
|
||
SharedWork *shwp = GetSharedWorkAddr();
|
||
u32 sioData[2];
|
||
int i;
|
||
|
||
shwp->isOnDebugger = 0;
|
||
|
||
if (!IsMmem8MB()) return; // メインメモリが 4MB ならデバッガではない
|
||
|
||
#ifndef DISABLE_SECURE_CODE
|
||
|
||
sioData[0] = shwp->recvRtc[0] | 0x80000000;
|
||
sioData[1] = shwp->recvRtc[1] | 0x80000000;
|
||
|
||
*(vu16 *)REG_RCNT = R_SIO_MASTER_MODE; // SIOハンドシェイク
|
||
*(vu16 *)REG_SIOCNT = SIO_32BIT_MODE | SIO_IN_SCK_256K;
|
||
|
||
if (!IsSioSendEnable()) {
|
||
return; // 初めに SI が Low で無ければデバッガではない
|
||
} else {
|
||
*(vu16 *)REG_SIOCNT |= SIO_SCK_IN; // 応答が正しくなければデバッガではない
|
||
|
||
SendSioData((sio_send_code <<16) | SYSROM_VERSION);
|
||
if (!CheckSioData((~sio_recv_code <<16), 0xffff0000)) return;
|
||
SendSioData(sioData[1]);
|
||
SendSioData(sioData[0]);
|
||
if (!CheckSioData(sioData[1], -1)) return;
|
||
SendSioData(sioData[1]);
|
||
if (!CheckSioData(sioData[0], -1)) return;
|
||
}
|
||
|
||
*(vu32 *)REG_SIODATA32 = 0;
|
||
*(vu32 *)REG_SIOCNT = 0;
|
||
|
||
shwp->isOnDebugger = 1;
|
||
|
||
#endif // DISABLE_SECURE_CODE
|
||
|
||
}
|
||
|
||
|
||
//----------------------------------------------------------------------
|
||
// Blowfishテーブル生成
|
||
//----------------------------------------------------------------------
|
||
void InitBlowfishKeyAnaTableFook(BLOWFISH_CTX *tableBufp, u32 *keyBufp, u32 keyLen);
|
||
u32 ChangeEncryptKey1(u32 key);
|
||
u32 ChangeEncryptKey2(u32 key);
|
||
u32 ChangeEncryptKey3(u32 key);
|
||
u32 ChangeEncryptKey4(u32 key);
|
||
|
||
void MakeBlowfishTable(BLOWFISH_CTX *tableBufp, const u32 *keyp, u32 *keyBufp, u32 keyLen)
|
||
{
|
||
|
||
#ifndef DISABLE_SECURE_CODE
|
||
|
||
#ifndef ENABLE_TEST_BLOWFISH
|
||
|
||
const BLOWFISH_CTX *blowfishInitTablep = &blowfishInitTable;
|
||
#else
|
||
const BLOWFISH_CTX *blowfishInitTablep = &blowfishTestTable;
|
||
|
||
#endif // ENABLE_TEST_BLOWFISH
|
||
|
||
u32 keyBuf[3];
|
||
|
||
#ifndef NDEBUG
|
||
|
||
*(u32 *)REG_TM2CNT = TMR_PRESCALER_256CK | TMR_ENABLE; // タイマー スタート
|
||
|
||
#endif // NDEBUG
|
||
|
||
CopyBiosAreaFook(blowfishInitTablep, tableBufp, sizeof(BLOWFISH_CTX));
|
||
|
||
keyBufp[0] = *keyp;
|
||
keyBufp[1] = ChangeEncryptKey1(*keyp);
|
||
keyBufp[2] = ChangeEncryptKey2(*keyp);
|
||
|
||
InitBlowfishKeyAnaTableFook(tableBufp, keyBufp, keyLen);
|
||
|
||
{ SecureWork *scwp = GetSecureWorkAddr();
|
||
RomHeader *rmhp = GetRomHeaderAddr();
|
||
FlashHeader *fhp = GetFlashHeaderAddr();
|
||
u32 *blowfishedKeyp;
|
||
|
||
|
||
if (keyLen == 8) {
|
||
*(u64 *)scwp->cardNormalModeKey = *(u64 *)rmhp->romNormalModeKey;
|
||
|
||
blowfishedKeyp = scwp->cardNormalModeKey;
|
||
} else {
|
||
*(u64 *)scwp->unScrambleKey = *(u64 *)fhp->unScrambleKey;
|
||
|
||
blowfishedKeyp = scwp->unScrambleKey;
|
||
}
|
||
|
||
DecryptByBlowfishFook(tableBufp, blowfishedKeyp);
|
||
if (keyLen > 8)
|
||
scwp->isGenUnScrambleKey = 1;
|
||
}
|
||
|
||
#ifndef NDEBUG
|
||
|
||
*(u16 *)REG_TM2CNT_H = 0;
|
||
|
||
#endif // NDEBUG
|
||
|
||
InitBlowfishKeyAnaTableFook(tableBufp, keyBufp, keyLen);
|
||
|
||
#endif // DISABLE_SECURE_CODE
|
||
|
||
}
|
||
|
||
//----------------------------------------------------------------------
|
||
// Blowfishキー&テーブル単位初期化
|
||
//----------------------------------------------------------------------
|
||
|
||
void InitBlowfishKeyAnaTable(BLOWFISH_CTX *tableBufp, u32 *keyBufp, u32 keyLen)
|
||
{
|
||
|
||
#ifndef DISABLE_SECURE_CODE
|
||
|
||
EncryptByBlowfishFook2(tableBufp, keyBufp); // EncryptByBlowfish(tableBufp, &keyBufp[2], &keyBufp[1]);
|
||
EncryptByBlowfishFook1(tableBufp, keyBufp); // EncryptByBlowfish(tableBufp, &keyBufp[1], &keyBufp[0]);
|
||
InitBlowfishFook(tableBufp, (u8 *)keyBufp, keyLen);
|
||
|
||
#endif // DISABLE_SECURE_CODE
|
||
|
||
}
|
||
|
||
|
||
//----------------------------------------------------------------------
|
||
// 暗号化オブジェクトの復号
|
||
//----------------------------------------------------------------------
|
||
|
||
#ifndef DISABLE_SECURE_CODE
|
||
|
||
extern const u32 encrypt_object_key[];
|
||
#else
|
||
const u32 encrypt_object_key[2] = {0x01234567, 0x89abcdef};
|
||
|
||
#endif // DISABLE_SECURE_CODE
|
||
|
||
|
||
#define UNDEF_CODE 0xe7ffdeff
|
||
#define ENCRYPT_DEF_SIZE 0x800
|
||
|
||
void DecryptObjectFile(void)
|
||
{
|
||
SharedWork *shwp = GetSharedWorkAddr();
|
||
SecureWork *scwp = GetSecureWorkAddr();
|
||
RomHeader *rmhp = GetRomHeaderAddr();
|
||
BLOWFISH_CTX *tableBufp = &scwp->blowfishCardTable;
|
||
u32 *encBufp = (u32 *)&scwp->blowfishFlashTable;
|
||
u32 *encDestp = (u32 *)rmhp->arm9.ramAddr;
|
||
s32 size = scwp->secureSize;
|
||
s32 restSize;
|
||
|
||
if (size > ENCRYPT_DEF_SIZE) size = ENCRYPT_DEF_SIZE;
|
||
restSize = size;
|
||
|
||
if (scwp->enableReadSecure) {
|
||
CpuCopyFast32Fook(encDestp, encBufp, size); // 暗号化オブジェクト 退避
|
||
DecryptByBlowfishFook(tableBufp, encBufp); // 暗号化オブジェクトヘッダ プリ復号
|
||
}
|
||
|
||
ChangeObjectTableFook(); // Blowfishテーブル変換
|
||
|
||
if (scwp->enableReadSecure) {
|
||
DecryptByBlowfishFook(tableBufp, encBufp); // 暗号化オブジェクトヘッダ ポスト復号
|
||
|
||
#ifndef DISABLE_SECURE_CODE
|
||
|
||
if ((encBufp[0] == encrypt_object_key[0]) // 暗号化オブジェクト有効時
|
||
&& (encBufp[1] == encrypt_object_key[1])) {
|
||
u32 *bufp = encBufp;
|
||
|
||
bufp[0] = UNDEF_CODE;
|
||
bufp[1] = UNDEF_CODE;
|
||
while ((restSize -= 8) > 0) {
|
||
bufp += 2; // 復号処理
|
||
DecryptByBlowfishFook(tableBufp, bufp);
|
||
}
|
||
} else
|
||
#endif // DISABLE_SECURE_CODE
|
||
{
|
||
CpuClearFast32(UNDEF_CODE, encBufp, size); // 未定義コードでクリア
|
||
shwp->disableEncryptedCardData = 1; // 暗号化オブジェクト無効 通知
|
||
}
|
||
|
||
CpuCopyFast32Fook(encBufp, encDestp, size); // 暗号化オブジェクト 復帰
|
||
}
|
||
}
|
||
|
||
//----------------------------------------------------------------------
|
||
// 暗号化オブジェクト用Blowfishテーブル変換
|
||
//----------------------------------------------------------------------
|
||
|
||
void ChangeObjectTable(u32 keyLen)
|
||
{
|
||
|
||
#ifndef DISABLE_SECURE_CODE
|
||
|
||
SecureWork *scwp = GetSecureWorkAddr();
|
||
BLOWFISH_CTX *tableBufp = &scwp->blowfishCardTable;
|
||
u32 *keyBufp = scwp->cardKeyBuf;
|
||
|
||
keyBufp[1] = ChangeEncryptKey3(keyBufp[1]);
|
||
keyBufp[2] = ChangeEncryptKey4(keyBufp[2]);
|
||
|
||
InitBlowfishKeyAnaTableFook(tableBufp, keyBufp, keyLen);
|
||
|
||
#endif // DISABLE_SECURE_CODE
|
||
|
||
}
|
||
|
||
|
||
//----------------------------------------------------------------------
|
||
// ハフマンデータ展開(32Bit→32Bit)
|
||
//----------------------------------------------------------------------
|
||
|
||
#define TREE_END 0x80
|
||
|
||
s32 UnCompHuffman32(const u8 *srcp, u32 *destp, u8 *tableBufp, const UC_InternalFuncp *ifp)
|
||
{
|
||
u8 *treep;// = (u8 *)srcp + 4;
|
||
s32 treeSize;// = (*treep + 1) * 2;
|
||
u32 treeCheck;
|
||
u32 treeShift;
|
||
u32 srcTmp;
|
||
u32 destTmp = 0;
|
||
u32 destTmpCount = 0;
|
||
s32 srcCount;
|
||
s32 error;
|
||
int i;
|
||
|
||
s32 header = ifp->InitFuncp(srcp, destp, tableBufp); // 初期化(アドレス送信)
|
||
s32 size = header >>8;
|
||
s32 destCount = size;
|
||
s32 dataBit = header & 0x0f;
|
||
u32 destTmpDataNum = 4 + (dataBit & 0x7);
|
||
u32 destTopShift = 32 - dataBit;
|
||
|
||
if (header < 0) { size = header;
|
||
goto terminate;
|
||
}
|
||
|
||
srcp += 3;
|
||
tableBufp[0] = ifp->ByteStreamFuncp(++srcp);
|
||
treeSize = (tableBufp[0] + 1) * 2;
|
||
|
||
for (i=1; i<treeSize; i++)
|
||
tableBufp[i] = ifp->ByteStreamFuncp(++srcp);
|
||
srcp++;
|
||
|
||
treep = tableBufp + 1;
|
||
while (destCount > 0) {
|
||
srcCount = 32;
|
||
srcTmp = ifp->WordStreamFuncp(srcp);
|
||
srcp += 4;
|
||
while (--srcCount >= 0) {
|
||
treeShift = (srcTmp >> 31) & 0x1;
|
||
treeCheck = *treep;
|
||
treeCheck <<= treeShift;
|
||
treep = (u8 *)((((u32 )treep>>1) <<1) + (((*treep & 0x3f)+1) <<1) + treeShift);
|
||
if (treeCheck & TREE_END) {
|
||
destTmp >>= dataBit;
|
||
destTmp |= *treep << destTopShift;
|
||
treep = tableBufp + 1;
|
||
if (++destTmpCount == destTmpDataNum) {
|
||
*destp++ = destTmp;
|
||
destCount -= 4;
|
||
destTmpCount = 0;
|
||
}
|
||
}
|
||
if (destCount <= 0) break;
|
||
srcTmp <<= 1;
|
||
}
|
||
}
|
||
|
||
terminate:
|
||
if (ifp->TerminateFuncp) { // 終了ダミー読み込み
|
||
if ((error = ifp->TerminateFuncp(srcp)) < 0) return error;
|
||
}
|
||
|
||
return size;
|
||
}
|
||
|
||
|
||
//----------------------------------------------------------------------
|
||
// LZバイトデータ展開(8Bit→16Bit)
|
||
//----------------------------------------------------------------------
|
||
|
||
s32 UnCompLZ77Short(const u8 *srcp, u16 *destp, const void *paramp, const UC_InternalFuncp *ifp)
|
||
{
|
||
u32 destTmp = 0;
|
||
u32 flags;
|
||
s32 offset;
|
||
s32 offset0_8;
|
||
s32 length;
|
||
u32 shift = 0;
|
||
u8 src;
|
||
s32 error;
|
||
int i;
|
||
|
||
s32 header = ifp->InitFuncp(srcp, destp, paramp); // 初期化(アドレス送信)
|
||
s32 size = header >>8;
|
||
s32 destCount = size;
|
||
|
||
if (header < 0) { size = header;
|
||
goto terminate;
|
||
}
|
||
|
||
srcp += 3;
|
||
while (destCount > 0) {
|
||
flags = ifp->ByteStreamFuncp(++srcp);
|
||
for (i=8; --i>=0; ) {
|
||
if (!(flags & 0x80)){ destTmp |= ifp->ByteStreamFuncp(++srcp) <<shift;
|
||
destCount--;
|
||
if (!(shift ^= 8)){
|
||
*destp = destTmp;
|
||
destp++;
|
||
destTmp = 0;
|
||
}
|
||
} else { length = ((src = ifp->ByteStreamFuncp(++srcp)) >>4) + 3;
|
||
offset = ( src & 0x0f) << 8;
|
||
offset = (offset | ifp->ByteStreamFuncp(++srcp)) + 1;
|
||
offset0_8 = (8 - shift) ^ ((offset & 1) <<3);
|
||
destCount -= length;
|
||
while (--length >= 0) { offset0_8 ^= 8;
|
||
destTmp |= (destp[-((offset + ((8 - shift) >>3)) >>1)]
|
||
& (0xff <<offset0_8)) >>offset0_8 <<shift;
|
||
if (!(shift ^= 8)){
|
||
*destp = destTmp;
|
||
destp++;
|
||
destTmp = 0;
|
||
}
|
||
}
|
||
}
|
||
if (destCount <= 0) break;
|
||
flags <<= 1;
|
||
}
|
||
}
|
||
|
||
terminate:
|
||
if (ifp->TerminateFuncp) { // 終了ダミー読み込み
|
||
if ((error = ifp->TerminateFuncp(++srcp)) < 0) return error;
|
||
}
|
||
|
||
return size;
|
||
}
|
||
|
||
|
||
//----------------------------------------------------------------------
|
||
// ランレングスデータ展開(8Bit→16Bit)
|
||
//----------------------------------------------------------------------
|
||
|
||
s32 UnCompRLShort(const u8 *srcp, u16 *destp, const void *paramp, const UC_InternalFuncp *ifp)
|
||
{
|
||
s32 srcTmp;
|
||
s32 destTmp = 0;
|
||
u32 flags;
|
||
s32 offset;
|
||
s32 length;
|
||
u32 shift = 0;
|
||
s32 error;
|
||
|
||
s32 header = ifp->InitFuncp(srcp, destp, paramp); // 初期化(アドレス送信)
|
||
s32 size = header >>8;
|
||
s32 destCount = size;
|
||
|
||
if (header < 0) { size = header;
|
||
goto terminate;
|
||
}
|
||
|
||
srcp += 3;
|
||
while (destCount > 0) {
|
||
flags = ifp->ByteStreamFuncp(++srcp);
|
||
length = flags & 0x7f;
|
||
if (!(flags & 0x80)) { length++;
|
||
destCount -= length;
|
||
while (--length >= 0){ destTmp |= ifp->ByteStreamFuncp(++srcp) << shift;
|
||
if (!(shift ^= 8)){ *destp++ = destTmp;
|
||
destTmp = 0;
|
||
}
|
||
}
|
||
} else { length += 3;
|
||
destCount -= length;
|
||
srcTmp = ifp->ByteStreamFuncp(++srcp);
|
||
while (--length >= 0){ destTmp |= srcTmp << shift;
|
||
if (!(shift ^= 8)){ *destp++ = destTmp;
|
||
destTmp = 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
terminate:
|
||
if (ifp->TerminateFuncp) { // 終了ダミー読み込み
|
||
if ((error = ifp->TerminateFuncp(++srcp)) < 0) return error;
|
||
}
|
||
|
||
return size;
|
||
}
|
||
|
||
|
||
//----------------------------------------------------------------------
|
||
// サウンドテーブルデータ取得
|
||
//----------------------------------------------------------------------
|
||
|
||
extern s16 snd_sin_table[];
|
||
extern u16 snd_ptable[];
|
||
extern u8 snd_vtable[];
|
||
extern u8 snd_data_start[];
|
||
extern u8 snd_data_end[];
|
||
|
||
static s32 CheckSoundTablep(void *tablep)
|
||
{
|
||
if ((tablep < (void *)snd_data_start) || (tablep >= (void *)snd_data_end))
|
||
return -1;
|
||
|
||
return 0;
|
||
}
|
||
|
||
u32 GetSoundSinTable(s32 index)
|
||
{
|
||
s16 *tablep = &snd_sin_table[index];
|
||
s32 retval;
|
||
|
||
if ((retval = CheckSoundTablep(tablep)) != 0) return retval;
|
||
|
||
return *tablep;
|
||
}
|
||
|
||
u32 GetSoundPitchTable(s32 index)
|
||
{
|
||
u16 *tablep = &snd_ptable[index];
|
||
s32 retval;
|
||
|
||
if ((retval = CheckSoundTablep(tablep)) != 0) return retval;
|
||
|
||
return *tablep;
|
||
}
|
||
|
||
u32 GetSoundVolumeTable(s32 index)
|
||
{
|
||
u8 *tablep = &snd_vtable[index];
|
||
s32 retval;
|
||
|
||
if ((retval = CheckSoundTablep(tablep)) != 0) return retval;
|
||
|
||
return *tablep;
|
||
}
|
||
|
||
|
||
//----------------------------------------------------------------------
|
||
// 割り込み終了処理
|
||
//----------------------------------------------------------------------
|
||
|
||
void TerminateIntr(u32 inrtFlags)
|
||
{
|
||
u32 bakIE = *(vu32 *)REG_IME;
|
||
|
||
*(vu32 *)REG_IME = 0;
|
||
*(vu32 *)REG_IE &= ~inrtFlags;
|
||
*(vu32 *)REG_IF = inrtFlags;
|
||
*(vu32 *)REG_IME = bakIE;
|
||
}
|
||
|
||
|
||
//----------------------------------------------------------------------
|
||
// Vブランク待ち
|
||
//----------------------------------------------------------------------
|
||
|
||
#ifdef BOOT_FROM_CARTRIDGE
|
||
|
||
void WaitVBlank(s32 count)
|
||
{
|
||
int i;
|
||
|
||
for (i=0; i<count; i++) {
|
||
while (((vDispStat *)REG_DISPSTAT)->blankingV == 1) ;
|
||
while (((vDispStat *)REG_DISPSTAT)->blankingV != 1) ;
|
||
}
|
||
}
|
||
|
||
#endif // BOOT_FROM_CARTRIDGE
|
||
|
||
|
||
//----------------------------------------------------------------------
|
||
// NINTENDOロゴチェック
|
||
//----------------------------------------------------------------------
|
||
extern const u16 Nin_Char_Diff_Huff[];
|
||
|
||
#ifdef TEST_AGB_MODE
|
||
|
||
u8 CheckNintendoLogo(u16 *datap)
|
||
{
|
||
int i;
|
||
|
||
for (i=0; i<OFFSET_MON_SOFT_NAME/2; i++) {
|
||
u16 cmpMask = 0xffff;
|
||
if ( i == OFFSET_MON_FIQ_FLAG/2) cmpMask = 0x84 ^ 0xffff;
|
||
else if (i == OFFSET_MON_KEY_GROUP_NO/2) cmpMask = 0x03 ^ 0xffff;
|
||
|
||
if ((datap[i] & cmpMask) != Nin_Char_Diff_Huff[i]) return 1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
#endif // TEST_AGB_MODE
|
||
|
||
|
||
//----------------------------------------------------------------------
|
||
// AGBのNINTENDOロゴ読み込み
|
||
//----------------------------------------------------------------------
|
||
void key_unlock__nin_logo_copy(void);
|
||
|
||
#ifdef TEST_AGB_MODE
|
||
|
||
void ReadNintendoLogo4AGB(void)
|
||
{
|
||
u8 *srcp;
|
||
|
||
if (*(u8 *)(CARTRIDGE + 0xb4) & 0x80) srcp = (u8 *)AGB_DACS_KEY_REG0;
|
||
else srcp = (u8 *)AGB_DACS_KEY_REG1;
|
||
|
||
CpuCopy16_32(srcp, CharTmpBuf, 2*10, 16); // セキュリティ解除 前処理
|
||
key_unlock__nin_logo_copy(); // DACSセキュリティ解除 & ロゴ コピー
|
||
}
|
||
|
||
#endif // TEST_AGB_MODE
|
||
|
||
|
||
//----------------------------------------------------------------------
|
||
// AGBモード遷移
|
||
//----------------------------------------------------------------------
|
||
void SetPause2Agb(void);
|
||
|
||
#ifdef TEST_AGB_MODE
|
||
|
||
void Iris2Agb(void)
|
||
{
|
||
int i;
|
||
|
||
*(vu32 *)REG_IME = 0;
|
||
|
||
*(vu16 *)REG_POWCNT = 0; // サウンドOFF
|
||
|
||
NotifyMainpIntf(7); // モード遷移通知
|
||
WaitMainpIntf(7);
|
||
|
||
WaitByLoop(4096/4); // ARM9 ホールト待ち
|
||
|
||
SetPause2Agb();
|
||
}
|
||
|
||
#endif // TEST_AGB_MODE
|