mirror of
https://github.com/rvtr/ctr_Repair.git
synced 2025-10-31 13:51:08 -04:00
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_Repair@449 385bec56-5757-e545-9c3a-d8741f4650f1
483 lines
16 KiB
C++
483 lines
16 KiB
C++
/*---------------------------------------------------------------------------*
|
||
Project: Horizon
|
||
File: main.cpp
|
||
|
||
Copyright (C)2009 Nintendo Co., Ltd. All rights reserved.
|
||
|
||
These coded instructions, statements, and computer programs contain
|
||
proprietary information of Nintendo of America Inc. and/or Nintendo
|
||
Company Ltd., and are protected by Federal copyright law. They may
|
||
not be disclosed to third parties or copied or duplicated in any form,
|
||
in whole or in part, without the prior written consent of Nintendo.
|
||
|
||
$Rev$
|
||
*---------------------------------------------------------------------------*/
|
||
|
||
#include <nn.h>
|
||
#include <nn/fs.h>
|
||
#include <nn/cfg/CTR/cfg_ApiSys.h>
|
||
#include <nn/cfg/CTR/cfg_ApiInit.h>
|
||
#include <nn/am/am_ApiLocalImporter.h>
|
||
#include <nn/am/am_ApiSystemMenu.h>
|
||
#include <nn/applet.h>
|
||
#include <nn/ndm.h>
|
||
#include <nn/ndm/ndm_DebugControl.h>
|
||
#include <nn/crypto/crypto_RsaKey.h>
|
||
#include <nn/ps/ctr/ps_Api.h>
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include "demo.h"
|
||
#include "../../body/ver.h"
|
||
#include "../common/sleep.h"
|
||
#include "../common/common.h"
|
||
#include "../common/shfnt.h"
|
||
#include "../common/test_data.h"
|
||
|
||
#define INF_FILE "sdmc:/cts_inf.txt"
|
||
|
||
#define KEY_LENGTH 2048
|
||
#define LIST_FILE "sdmc:/cts_list.txt"
|
||
#define SIGN_FILE "sdmc:/cts_sign.dat"
|
||
|
||
|
||
extern "C" {
|
||
extern u8* PUBLIC_KEY_BEGIN[];
|
||
extern u8* PUBLIC_KEY_END[];
|
||
|
||
const void* PUBLIC_KEY = PUBLIC_KEY_BEGIN;
|
||
}
|
||
|
||
demo::RenderSystemDrawing s_RenderSystem;
|
||
nn::fnd::ExpHeap appHeap;
|
||
uptr heapForGx;
|
||
void ErrorStop(char *s);
|
||
void ErrorPOff(char *s);
|
||
|
||
const size_t ROMFS_BUFFER_SIZE = 64*1024;//ROMマウント用
|
||
const size_t READ_BUFFER_SIZE = 64*1024;
|
||
|
||
#define SDK_SER_LEN nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN
|
||
|
||
namespace
|
||
{
|
||
u8* readBuf;
|
||
u8* romfsBuf;
|
||
|
||
}
|
||
nn::Result result;
|
||
|
||
|
||
bool ImportFile(nn::fs::MediaType mediaType, wchar_t* filename)
|
||
{
|
||
//nn::Result result;
|
||
|
||
nn::fs::FileOutputStream* stream;
|
||
result = nn::am::BeginImportProgram(&stream, mediaType);
|
||
if (result.IsSuccess())
|
||
{
|
||
//NN_LOG("Importing: %ls...", filename);
|
||
nn::fs::FileInputStream in(filename);
|
||
|
||
while(s32 read = in.Read(readBuf, READ_BUFFER_SIZE))
|
||
{
|
||
stream->Write(readBuf, read);
|
||
}
|
||
result = nn::am::EndImportProgram(stream);
|
||
}
|
||
return result.IsSuccess();
|
||
}
|
||
|
||
#define LIST_MAX 4000
|
||
#define LIST_LENGTH (LIST_MAX * (nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN+1))
|
||
u8 s_list[LIST_MAX][nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN+1];//シリアルリスト
|
||
u8 sign[256];//署名
|
||
u8 serialNo[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN+1];
|
||
|
||
//本体シリアル取得
|
||
int GettedSerLen;
|
||
bool GetSerial(){
|
||
nn::cfg::CTR::init::Initialize();
|
||
nn::cfg::CTR::system::Initialize();
|
||
result = nn::cfg::CTR::system::GetSerialNo(serialNo);
|
||
nn::cfg::CTR::system::Finalize();
|
||
nn::cfg::CTR::init::Finalize();
|
||
serialNo[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN] = 0;
|
||
GettedSerLen = strlen((char*)serialNo);
|
||
return result.IsSuccess();
|
||
}
|
||
|
||
|
||
|
||
//#define setColor(r,g,b,a) s_RenderSystem.SetColor(r,g,b,a)
|
||
void setColor(f32 r,f32 g,f32 b,f32 a){ shf_SetColor(r,g,b,a);}
|
||
//#define setText(x,y,s) s_RenderSystem.DrawText(x,y,s)
|
||
void drawText(u16 x,u16 y,char *s){ shf_DrawText_0( x,y,s);}
|
||
//上はASCIIのみ対応したTextWriterへのラッパ
|
||
//日本語表示の場合、WideTextWriterを使う(要sft_側の関数追加)
|
||
|
||
|
||
nn::hid::PadReader *hpr;
|
||
//入力待ち
|
||
nn::hid::PadStatus padStatus;
|
||
u32 WaitKey(u32 mask)
|
||
{
|
||
|
||
while(1){
|
||
hpr->ReadLatest(&padStatus);
|
||
if(padStatus.trigger & mask)return padStatus.trigger;
|
||
CheckSysBreak();
|
||
}
|
||
}
|
||
|
||
//終了
|
||
void endfunc()
|
||
{
|
||
appHeap.Free(reinterpret_cast<void*>(readBuf));
|
||
appHeap.Free(reinterpret_cast<void*>(romfsBuf));
|
||
nn::hid::Finalize();
|
||
SharedFontFinalize();
|
||
nngxWaitVSync(NN_GX_DISPLAY_BOTH);//SDK2.0以降では不要?
|
||
s_RenderSystem.Finalize();
|
||
}
|
||
|
||
//署名検証
|
||
bool VeriRsa(u8* src,size_t sz,u8* sig)
|
||
{
|
||
nn::crypto::RsaKey key;
|
||
//nn::crypto::Initialize();
|
||
nn::ps::CTR::Initialize();
|
||
result = key.InitializePublicKey(PUBLIC_KEY_BEGIN,KEY_LENGTH);
|
||
if (result.IsSuccess())
|
||
{
|
||
result = nn::ps::CTR::VerifyRsaSha256(src,sz,sig,key);
|
||
}
|
||
//nn::crypto::Finalize();
|
||
nn::ps::CTR::Finalize();
|
||
return result.IsSuccess();
|
||
}
|
||
|
||
//エラー
|
||
void ErrorCommon(char *s,char *ss)
|
||
{
|
||
char str[128];
|
||
nn::am::FinalizeForLocalImporter();
|
||
nn::fs::Unmount("sdmc:");
|
||
nn::fs::Unmount("rom:");
|
||
NN_LOG(s);
|
||
NN_LOG(" result = %d\n",result.GetDescription());
|
||
shf_SetScale(0.7,0.7);
|
||
setColor(1.0, 0.0, 0.0,1.0);
|
||
strcpy(str,"Error: ");
|
||
strcat(str,s);
|
||
drawText(10,100,str);
|
||
drawText(10,140,ss);
|
||
}
|
||
|
||
|
||
void ErrorStop(char *s)
|
||
{
|
||
ErrorCommon(s,"Push Home Button & end");
|
||
s_RenderSystem.SwapBuffers();
|
||
WaitKey(0);
|
||
}
|
||
|
||
void ErrorPoff(char *s)
|
||
{
|
||
ErrorCommon(s,"Push Power Button & Power Off");
|
||
drawText(10,160,"Home Button is invalid");
|
||
s_RenderSystem.SwapBuffers();
|
||
WaitKey(0);
|
||
}
|
||
|
||
|
||
//改行後の位置を返す、0=見つからなかった
|
||
int CrLf(int n,int max)
|
||
{
|
||
u8 d;
|
||
while(n < max)
|
||
{
|
||
d = readBuf[n];
|
||
if (d==0x0a)return n+1;//LF
|
||
if (d==0x0d)//CR
|
||
{
|
||
if (n == max-1)return 0;//終端
|
||
n++;
|
||
if (readBuf[n]==0x0a)return n+1;//CR+LF
|
||
ErrorStop("list broken");//CRのみは異常、署名時にファイル壊れてた?
|
||
}
|
||
n++;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
nn::fs::FileInputStream fi;
|
||
//ファイルリード
|
||
s32 FileRead(char* fname)
|
||
{
|
||
s32 size;
|
||
result = fi.TryInitialize(fname);
|
||
if (result.IsFailure()){//open error
|
||
//NN_LOG("desc= %d\n",result.GetDescription());
|
||
return 0;
|
||
}
|
||
result = fi.TryRead(&size,readBuf,READ_BUFFER_SIZE);
|
||
fi.Finalize();
|
||
if (result.IsFailure()){
|
||
//NN_LOG("desc= %d\n",result.GetDescription());
|
||
return 0;
|
||
}
|
||
return size;
|
||
}
|
||
|
||
|
||
char ver[16];
|
||
char seri[32];
|
||
void nnMain( void )
|
||
{
|
||
//nn::Result result;
|
||
bool flg_applove=false;
|
||
bool flg_test=false;
|
||
extern bool prohibitHome;// HOME ボタン禁止
|
||
|
||
nn::os::Initialize();
|
||
nn::fs::Initialize();
|
||
|
||
//DEA-SUPにて推奨のフリーズ暫定対策:無線デーモンを停止 (2011.3.1 現在)
|
||
//ただし、スリープに入ると再開
|
||
//無線は使わないので本体横スイッチ切っとくのが確実
|
||
nn::ndm::Initialize();
|
||
nn::ndm::SuspendScheduler();
|
||
|
||
//中断処理の準備
|
||
InitSysBreak((uptr)endfunc);
|
||
// グラフィックスライブラリの初期化は、以降で行わなければならない
|
||
// 他、アプリケーションの初期化処理
|
||
|
||
nn::hid::Initialize();
|
||
nn::hid::PadReader padReader;
|
||
hpr = &padReader;
|
||
|
||
//result = nn::ns::CTR::InitializeForShell();
|
||
//if (result.IsSuccess())
|
||
result = nn::am::InitializeForLocalImporter();
|
||
|
||
nn::applet::DisableSleep();//スリープ非対応 .. 無線対策
|
||
|
||
// ヒープの確保
|
||
appHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR);
|
||
|
||
const u32 s_GxHeapSize = 0x800000;
|
||
// RenderSystem の準備
|
||
heapForGx = reinterpret_cast<uptr>(appHeap.Allocate(s_GxHeapSize));
|
||
s_RenderSystem.Initialize(heapForGx, s_GxHeapSize);
|
||
SharedFontInit();
|
||
|
||
// 共有フォントの種類を取得
|
||
//nn::pl::SharedFontType sftype = nn::pl::GetSharedFontType();
|
||
|
||
// スリープ要求に対する返答を有効にする
|
||
// また、蓋の状態チェックを行い蓋が閉じられているならスリープ要求が発生する
|
||
// nn::applet::EnableSleep(true);
|
||
|
||
s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
|
||
s_RenderSystem.Clear();
|
||
// s_RenderSystem.SetFontSize(12);
|
||
shf_SetScale(0.8,0.6);
|
||
setColor(1.0,1.0,1.0,1.0);
|
||
drawText(20,20,"CTR Card Savedata Exporter Setup");
|
||
s_RenderSystem.SwapBuffers();
|
||
|
||
shf_SetScale(0.5,0.5);
|
||
sprintf(ver,"version %.2f",VERSION);
|
||
drawText(250,40,ver);
|
||
|
||
shf_SetScale(0.7,0.7);
|
||
if (result.IsFailure())ErrorStop("Initialize");//初期化に失敗
|
||
if (READ_BUFFER_SIZE < LIST_LENGTH)ErrorStop("buffer size");//バッファサイズのチェック
|
||
|
||
//ファイルバッファ
|
||
//SDKで4倍数サイズ、4アライン推奨
|
||
if (READ_BUFFER_SIZE > appHeap.GetTotalFreeSize())ErrorStop("memory alloc");
|
||
readBuf = reinterpret_cast<u8*>(appHeap.Allocate(READ_BUFFER_SIZE,32));
|
||
if (ROMFS_BUFFER_SIZE > appHeap.GetTotalFreeSize())ErrorStop("memory alloc");
|
||
romfsBuf = reinterpret_cast<u8*>(appHeap.Allocate(ROMFS_BUFFER_SIZE,32));
|
||
|
||
if (nn::os::CTR::GetRunningTargetHardware() != nn::os::TARGET_HARDWARE_PRODUCT)
|
||
{//デバッガ
|
||
flg_test=true;
|
||
flg_applove=true;
|
||
}else{//実機ならシリアルチェック
|
||
int i,j,n;
|
||
s32 fsize;
|
||
if( GetSerial() == false)ErrorStop("Get Serial");//本体シリの取得に失敗
|
||
|
||
result = nn::fs::MountSdmc();//ダイレクトでマウント..マスタリング時にワーニング
|
||
if (result.IsFailure())ErrorStop("Mount SD");
|
||
fsize = FileRead(INF_FILE);//設定ファイルがあるか
|
||
if((fsize < 1024) && (fsize > 0))//サイズチェック,増えても1Kは超えない
|
||
{//不具合調査時に状況にあわせて現場で作成&変更を想定したオプション
|
||
//通常は不要なので無しでも動くようしとく
|
||
n = 0;
|
||
while(n < fsize)
|
||
{
|
||
if (readBuf[n] == '-'){
|
||
if (n == fsize-1)break;//終端
|
||
n++;
|
||
switch (readBuf[n]){
|
||
case 'p':// -p .. 本体シリアル表示
|
||
strcpy(seri,"s/n: ");
|
||
strcat(seri,(char *)serialNo);
|
||
shf_SetScale(0.5,0.5);
|
||
drawText(10,40,(char*)seri);
|
||
shf_SetScale(0.7,0.7);
|
||
break;
|
||
case 't':// -t .. テストメニュー有効
|
||
flg_test = true;
|
||
break;
|
||
}
|
||
}
|
||
n++;
|
||
}
|
||
}
|
||
|
||
//シリアル表示(オプション)後にチェック
|
||
//デバッガ=15,実機=11
|
||
if (GettedSerLen < 11)ErrorStop("invalid Serial");
|
||
|
||
fsize = FileRead(SIGN_FILE);//署名リード
|
||
if(fsize != 256)ErrorStop("sign file");//鍵のbit長は2046固定
|
||
memcpy(sign,readBuf,256);//readBuf -> sign
|
||
fsize = FileRead(LIST_FILE);//リストリード
|
||
if((fsize > LIST_LENGTH ) || (fsize == 0))ErrorStop("list file");
|
||
|
||
nn::fs::Unmount("sdmc:"); //検証後はSDから読まないでメモリバッファ上のデータを使う: 差替え対策
|
||
if (VeriRsa(readBuf,fsize,sign) == false)ErrorStop("sign verify");
|
||
|
||
//署名検証OK
|
||
int list_ct = 0;
|
||
n=0;
|
||
while(n < fsize)//リスト作成
|
||
{
|
||
if (readBuf[n] == '#')//コメント行を無視、ワイド文字非対応
|
||
{
|
||
i = CrLf(n,fsize);//コメントの次行
|
||
if (i == 0)break;//ファイル終わりまで改行が見つからない
|
||
}else
|
||
{
|
||
//改行さがし
|
||
if ((fsize-n) > (SDK_SER_LEN+2))
|
||
{//シリアルは改行つける
|
||
i = CrLf(n,n+SDK_SER_LEN+2);
|
||
if (i == 0)ErrorStop("list broken");//改行が見つからない
|
||
}else{
|
||
i = CrLf(n,fsize);
|
||
if (i ==0)i = fsize;//改行以外でファイル終
|
||
}
|
||
if ((i-n) > GettedSerLen)//シリアルをリスト化
|
||
{
|
||
j = 0;
|
||
while(n<i)
|
||
{
|
||
if ((readBuf[n] == 0x0d) || (readBuf[n] == 0x0a))break;
|
||
s_list[list_ct][j] = readBuf[n];
|
||
j++;n++;
|
||
}
|
||
s_list[list_ct][j] = 0;//終端
|
||
list_ct++;
|
||
if (list_ct>=LIST_MAX)ErrorStop("List too Long");
|
||
}
|
||
}
|
||
if ((fsize-i) < GettedSerLen)break;//ファイル終
|
||
n=i;//ポインタを改行の次へ
|
||
}
|
||
|
||
//文字数チェック
|
||
//開発初期のファームアップで空ID本体が発生してたので念の為
|
||
//2011.5現在、製品で報告はない
|
||
if (GettedSerLen < 11)ErrorStop("invalid Serial");
|
||
|
||
//本体シリアルがリストにあるかチェック
|
||
n =0;
|
||
while(n<list_ct)
|
||
{
|
||
if (GettedSerLen == strlen((char*)s_list[n]))
|
||
{
|
||
for(i=0;i<GettedSerLen;i++)
|
||
{
|
||
if (serialNo[i] != s_list[n][i])break;
|
||
}
|
||
if (i == GettedSerLen)
|
||
{
|
||
flg_applove = true;
|
||
break;
|
||
}
|
||
}
|
||
n++;
|
||
}
|
||
}
|
||
|
||
u32 mask = 0;
|
||
|
||
//メニュー表示
|
||
if (flg_applove)//インポート許可本体
|
||
{
|
||
drawText(80,100,"Push X : Import");
|
||
drawText(80,140,"Push Y : Delete"); //本体機能で消せるようなったら、そっち使う
|
||
mask |= nn::hid::BUTTON_X | nn::hid::BUTTON_Y;
|
||
}
|
||
|
||
|
||
if (flg_test)//テストメニュー
|
||
{
|
||
drawText(80,160,"Push R : Test Data");
|
||
mask |= nn::hid::BUTTON_R;
|
||
}
|
||
s_RenderSystem.SwapBuffers();
|
||
|
||
if (mask == 0)ErrorStop("Serial Check");//実行できるメニューないときトラップ
|
||
|
||
u32 trg = WaitKey(mask);
|
||
if (trg & nn::hid::BUTTON_R){
|
||
shf_SetScale(0.6,0.6);
|
||
TestMain();//テストデータへ
|
||
}
|
||
|
||
nn::fs::MountRom(16, 16, romfsBuf, ROMFS_BUFFER_SIZE);
|
||
|
||
shf_SetScale(0.8,0.8);
|
||
// CIA のプログラム ID を取得する。
|
||
nn::am::ProgramInfo programInfo;
|
||
if (nn::am::GetProgramInfoFromCia(&programInfo, ROMFS_IMPORTEE_PATH).IsFailure())ErrorStop("cia infomation");
|
||
|
||
// Imprting/Delete 表示
|
||
s_RenderSystem.Clear();
|
||
if(trg & nn::hid::BUTTON_X) drawText(10,120,"Importing");
|
||
else drawText(10,120,"Delete");
|
||
s_RenderSystem.SwapBuffers();
|
||
|
||
// HOME ボタン禁止
|
||
//Homeで中断するとアイコンが更新されない、電源OFF画面からHomeは問題なし
|
||
prohibitHome = true;
|
||
|
||
// 既に存在するものをインポートするとエラーが返ってくるので、あらかじめ消しておく。
|
||
nn::am::DeleteProgram(nn::fs::MEDIA_TYPE_NAND, programInfo.id);
|
||
// タイトル鍵が違うケースに対応するために、チケットも消しておく。
|
||
nn::am::DeleteTicket(programInfo.id);
|
||
|
||
if(trg & nn::hid::BUTTON_X)
|
||
{
|
||
// CIA をインポート
|
||
if (ImportFile(nn::fs::MEDIA_TYPE_NAND, ROMFS_IMPORTEE_PATH)==false)ErrorPoff("Import");
|
||
}
|
||
nn::fs::Unmount("rom:");
|
||
|
||
s_RenderSystem.Clear();
|
||
drawText(10,50,"Complate");
|
||
drawText(10,120,"Push Power Button & Power Off");
|
||
drawText(10,140,"Home Button is invalid");
|
||
s_RenderSystem.SwapBuffers();
|
||
WaitKey(0);
|
||
|
||
}
|
||
|