/**************************************************************************** * * * Project64 - A Nintendo 64 emulator. * * http://www.pj64-emu.com/ * * Copyright (C) 2012 Project64. All rights reserved. * * * * License: * * GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html * * * ****************************************************************************/ #include "stdafx.h" #include #include #include #include CEeprom::CEeprom(bool ReadOnly) : m_ReadOnly(ReadOnly) { memset(m_EEPROM, 0xFF, sizeof(m_EEPROM)); } CEeprom::~CEeprom() { } uint8_t byte2bcd(int32_t n) { n %= 100; return (uint8_t)(((n / 10) << 4) | (n % 10)); } void CEeprom::EepromCommand(uint8_t * Command) { time_t curtime_time; struct tm curtime; if (g_System->m_SaveUsing == SaveChip_Auto) { g_System->m_SaveUsing = SaveChip_Eeprom_4K; } switch (Command[2]) { case 0: // check if (g_System->m_SaveUsing != SaveChip_Eeprom_4K && g_System->m_SaveUsing != SaveChip_Eeprom_16K) { Command[1] |= 0x80; break; } if (Command[1] != 3) { Command[1] |= 0x40; if ((Command[1] & 3) > 0) { Command[3] = 0x00; } if ((Command[1] & 3) > 1) { Command[4] = (g_System->m_SaveUsing == SaveChip_Eeprom_4K) ? 0x80 : 0xC0; } if ((Command[1] & 3) > 2) { Command[5] = 0x00; } } else { Command[3] = 0x00; Command[4] = g_System->m_SaveUsing == SaveChip_Eeprom_4K ? 0x80 : 0xC0; Command[5] = 0x00; } break; case 4: // Read from Eeprom if (Command[0] != 2 && bHaveDebugger()) { g_Notify->DisplayError("What am I meant to do with this Eeprom Command"); } if (Command[1] != 8 && bHaveDebugger()) { g_Notify->DisplayError("What am I meant to do with this Eeprom Command"); } ReadFrom(&Command[4], Command[3]); break; case 5: //Write to Eeprom if (Command[0] != 10 && bHaveDebugger()) { g_Notify->DisplayError("What am I meant to do with this Eeprom Command"); } if (Command[1] != 1 && bHaveDebugger()) { g_Notify->DisplayError("What am I meant to do with this Eeprom Command"); } WriteTo(&Command[4], Command[3]); break; case 6: //RTC Status query Command[3] = 0x00; Command[4] = 0x10; Command[5] = 0x00; break; case 7: //Read RTC block switch (Command[3]) { case 0: //Block number Command[4] = 0x00; Command[5] = 0x02; Command[12] = 0x00; break; case 1: //read block, Command[2], Unimplemented break; case 2: //Set RTC Time time(&curtime_time); memcpy(&curtime, localtime(&curtime_time), sizeof(curtime)); // fd's fix Command[4] = byte2bcd(curtime.tm_sec); Command[5] = byte2bcd(curtime.tm_min); Command[6] = 0x80 + byte2bcd(curtime.tm_hour); Command[7] = byte2bcd(curtime.tm_mday); Command[8] = byte2bcd(curtime.tm_wday); Command[9] = byte2bcd(curtime.tm_mon + 1); Command[10] = byte2bcd(curtime.tm_year); Command[11] = byte2bcd(curtime.tm_year / 100); Command[12] = 0x00; // status break; } break; case 8: //Write RTC, unimplemented if (g_Settings->LoadDword(Debugger_ShowPifErrors)) { g_Notify->DisplayError("Write RTC, unimplemented"); } break; default: if (g_Settings->LoadDword(Debugger_ShowPifErrors)) { g_Notify->DisplayError(stdstr_f("Unknown EepromCommand %d", Command[2]).c_str()); } } } void CEeprom::LoadEeprom() { memset(m_EEPROM, 0xFF, sizeof(m_EEPROM)); CPath FileName(g_Settings->LoadStringVal(Directory_NativeSave).c_str(), stdstr_f("%s.eep", g_Settings->LoadStringVal(Game_GameName).c_str()).c_str()); if (g_Settings->LoadBool(Setting_UniqueSaveDir)) { FileName.AppendDirectory(g_Settings->LoadStringVal(Game_UniqueSaveDir).c_str()); } if (!FileName.DirectoryExists()) { FileName.DirectoryCreate(); } if (!m_File.Open(FileName, (m_ReadOnly ? CFileBase::modeRead : CFileBase::modeReadWrite) | CFileBase::modeNoTruncate | CFileBase::modeCreate)) { #ifdef _WIN32 WriteTrace(TraceN64System, TraceError, "Failed to open (%s), ReadOnly = %d, LastError = %X", (const char *)FileName, m_ReadOnly, GetLastError()); #else WriteTrace(TraceN64System, TraceError, "Failed to open (%s), ReadOnly = %d", (const char *)FileName, m_ReadOnly); #endif g_Notify->DisplayError(GS(MSG_FAIL_OPEN_EEPROM)); return; } m_File.SeekToBegin(); m_File.Read(m_EEPROM, sizeof(m_EEPROM)); } void CEeprom::ReadFrom(uint8_t * Buffer, int32_t line) { int32_t i; if (!m_File.IsOpen()) { LoadEeprom(); } for (i = 0; i < 8; i++) { Buffer[i] = m_EEPROM[line * 8 + i]; } } void CEeprom::WriteTo(uint8_t * Buffer, int32_t line) { if (m_ReadOnly) { return; } int32_t i; if (!m_File.IsOpen()) { LoadEeprom(); } for (i = 0; i < 8; i++) { m_EEPROM[line * 8 + i] = Buffer[i]; } m_File.Seek(line * 8, CFile::begin); m_File.Write(Buffer, 8); }