ctr_Repair/branches/1stNUP_7/CardSaveData/ToSD/Imp/source/main.cpp
N2614 d725e929a9 DSiWare上限個数の修正のためのブランチ
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
2011-10-07 06:11:18 +00:00

483 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*---------------------------------------------------------------------------*
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);
}