/*---------------------------------------------------------------------------* Project: Horizon File: savedata.cpp Copyright (C)2009-2012 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: 46365 $ *---------------------------------------------------------------------------*/ #include #include #include "savedata.h" #include "applet.h" const char* SaveDataDemo::SAVEDATA_ARCHIVE = "data:"; const char* SaveDataDemo::SAVEDATA_FILENAME = "data:/test.txt"; void SaveDataDemo::Initialize(demo::RenderSystemDrawing* p_RenderSystem, nn::fnd::ExpHeap*) { Device::Initialize(p_RenderSystem); const size_t maxFiles = 8; const size_t maxDirectories = 8; const bool isDuplicateAll = true; // Duplicates the entire save data region m_IsFormatted = false; m_IsMounted = true; // Mount and format save data nn::Result result = nn::fs::MountSaveData(); if(result.IsFailure()) { if((result <= nn::fs::ResultNotFormatted()) || (result <= nn::fs::ResultBadFormat()) || (result <= nn::fs::ResultVerificationFailed())) { // Save data needs to be formatted NN_LOG("Format save data.\n"); m_IsFormatted = true; result = nn::fs::FormatSaveData(maxFiles, maxDirectories, isDuplicateAll); if(result.IsFailure()) { NN_LOG("Cannot format save data!\n"); NN_ERR_THROW_FATAL_ALL(result); } } else { // Unexpected error NN_ERR_THROW_FATAL_ALL(result); } // If mounting fails here, the save data cannot be used result = nn::fs::MountSaveData(); if(result.IsFailure()) { NN_LOG("Cannot use save data!\n"); NN_ERR_THROW_FATAL_ALL(result); m_IsMounted = false; } } } void SaveDataDemo::Finalize(void) { if (m_IsMounted) { // Since it is duplicated, commit the save data region nn::Result result = nn::fs::CommitSaveData(); if(result.IsFailure()) { NN_LOG("Cannot commit save data!\n"); } // Unmount save data result = nn::fs::Unmount(SAVEDATA_ARCHIVE); if(result.IsFailure()) { NN_LOG("Cannot unmount save data!\n"); } } Device::Finalize(); } void SaveDataDemo::Start(void) { Device::Start(); m_ExitEvent.Initialize(false); // Simple program to create, open, write to, and load a file for save data // Open file (creates one if one does not exist) nn::Result result = m_SaveDataFile.TryInitialize( SAVEDATA_FILENAME, nn::fs::OPEN_MODE_READ | nn::fs::OPEN_MODE_WRITE | nn::fs::OPEN_MODE_CREATE ); m_IsAvailable = result.IsSuccess(); if ( m_IsAvailable ) { // After creating with TryInitialize, performs SetSize since the size is 0 result = m_SaveDataFile.TrySetSize(SAVEDATA_SIZE); if(result.IsFailure()) { return; } // Load the content of the saved save data to the display buffer result = m_SaveDataFile.TrySeek(0, nn::fs::POSITION_BASE_BEGIN); if(result.IsFailure()) { NN_LOG("TrySeek error\n"); NN_DBG_PRINT_RESULT(result); return; } // Sometimes, verification failure occurs with the first Read s32 readSize; result = m_SaveDataFile.TryRead(&readSize, m_SaveDataBuffer, SAVEDATA_SIZE); if(result.IsFailure() && !(result <= nn::fs::ResultVerificationFailed())) { NN_LOG("TryRead error\n"); NN_DBG_PRINT_RESULT(result); return; } // Prepare data to write for ( s32 i = 0; i < SAVEDATA_SIZE; i++ ) { m_WriteFileBuffer[i] = static_cast(i); } // Write to data result = m_SaveDataFile.TrySeek(0, nn::fs::POSITION_BASE_BEGIN); if(result.IsFailure()) { return; } s32 writeSize; result = m_SaveDataFile.TryWrite(&writeSize, m_WriteFileBuffer, SAVEDATA_SIZE, true); if(result.IsFailure()) { return; } // Commit written content result = nn::fs::CommitSaveData(); if(result.IsFailure()) { return; } // Load data result = m_SaveDataFile.TrySeek(0, nn::fs::POSITION_BASE_BEGIN); if(result.IsFailure()) { return; } result = m_SaveDataFile.TryRead(&readSize, m_ReadFileBuffer, SAVEDATA_SIZE); if(result.IsFailure()) { return; } for ( s32 i = 0; i < SAVEDATA_SIZE; i++ ) { NN_ASSERT(m_WriteFileBuffer[i] == m_ReadFileBuffer[i]); } m_Thread.Start(SaveDataDemo::ThreadFunc, this, m_Stack); } else { NN_LOG("[DEMO1] Failed to open '%s'.\n",SAVEDATA_FILENAME); } } void SaveDataDemo::End(void) { if ( m_IsAvailable ) { m_ExitEvent.Signal(); m_Thread.Join(); // Close the file m_SaveDataFile.Finalize(); } Device::End(); } void SaveDataDemo::DrawFrame(void) { mp_RenderSystem->SetRenderTarget(NN_GX_DISPLAY0); mp_RenderSystem->DrawText(10, 220, "Savedata %s", m_IsFormatted ? "is formatted" : "already exists"); mp_RenderSystem->DrawText(10, 230, "data:%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", m_SaveDataBuffer[0], m_SaveDataBuffer[1], m_SaveDataBuffer[2], m_SaveDataBuffer[3], m_SaveDataBuffer[4], m_SaveDataBuffer[5], m_SaveDataBuffer[6], m_SaveDataBuffer[7], m_SaveDataBuffer[8], m_SaveDataBuffer[9], m_SaveDataBuffer[10], m_SaveDataBuffer[11], m_SaveDataBuffer[12], m_SaveDataBuffer[13], m_SaveDataBuffer[14], m_SaveDataBuffer[15]); } void SaveDataDemo::ThreadFuncImpl() { nn::Result result; while ( !m_ExitEvent.TryWait() ) { TransitionHandler::Lock(); { // Load save data // Because processing automatically stops in Sleep Mode, we do not need an exclusive lock of some kind. result = m_SaveDataFile.TrySeek(0, nn::fs::POSITION_BASE_BEGIN); if(result.IsFailure()) { return; } s32 readSize; result = m_SaveDataFile.TryRead(&readSize, m_ReadFileBuffer, SAVEDATA_SIZE); for ( s32 i = 0; i < SAVEDATA_SIZE; i++ ) { NN_ASSERT(m_WriteFileBuffer[i] == m_ReadFileBuffer[i]); } } TransitionHandler::Unlock(); nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(100)); // Write save data // The application must explicitly get an exclusive lock of some kind in Sleep Mode TransitionHandler::Lock(); TransitionHandler::LockForSleep(); { result = m_SaveDataFile.TrySeek(0, nn::fs::POSITION_BASE_BEGIN); if(result.IsFailure()) { return; } s32 writeSize; result = m_SaveDataFile.TryWrite(&writeSize, m_WriteFileBuffer, SAVEDATA_SIZE, true); if(result.IsFailure()) { return; } // Commit written content result = nn::fs::CommitSaveData(); if(result.IsFailure()) { return; } } TransitionHandler::UnlockForSleep(); TransitionHandler::Unlock(); nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(100)); } } void SaveDataDemo::ThreadFunc(SaveDataDemo* saveDataDemo) { saveDataDemo->ThreadFuncImpl(); } /*---------------------------------------------------------------------------* End of file *---------------------------------------------------------------------------*/