2012-12-19 09:30:18 +00:00
|
|
|
/****************************************************************************
|
|
|
|
* *
|
|
|
|
* Project 64 - 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 *
|
|
|
|
* *
|
|
|
|
****************************************************************************/
|
2010-06-14 21:14:58 +00:00
|
|
|
#include "stdafx.h"
|
2012-09-26 10:36:52 +00:00
|
|
|
#include <time.h>
|
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
CEeprom::CEeprom(bool ReadOnly):
|
2010-06-14 21:14:58 +00:00
|
|
|
m_ReadOnly(ReadOnly),
|
|
|
|
m_hFile(NULL)
|
|
|
|
{
|
2013-04-26 10:06:01 +00:00
|
|
|
memset(m_EEPROM,0xFF,sizeof(m_EEPROM));
|
2010-06-14 21:14:58 +00:00
|
|
|
}
|
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
CEeprom::~CEeprom()
|
2015-03-29 17:19:28 +00:00
|
|
|
{
|
|
|
|
if (m_hFile)
|
|
|
|
{
|
2010-06-14 21:14:58 +00:00
|
|
|
CloseHandle(m_hFile);
|
|
|
|
m_hFile = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-26 10:36:52 +00:00
|
|
|
unsigned char byte2bcd(int n)
|
|
|
|
{
|
|
|
|
n %= 100;
|
2012-10-06 04:09:17 +00:00
|
|
|
return (unsigned char)(((n / 10) << 4) | (n % 10));
|
2012-09-26 10:36:52 +00:00
|
|
|
}
|
|
|
|
|
2015-03-29 17:19:28 +00:00
|
|
|
void CEeprom::EepromCommand ( BYTE * Command)
|
|
|
|
{
|
2012-09-26 10:36:52 +00:00
|
|
|
time_t curtime_time;
|
|
|
|
struct tm curtime;
|
|
|
|
|
2015-03-29 17:19:28 +00:00
|
|
|
if (g_System->m_SaveUsing == SaveChip_Auto)
|
|
|
|
{
|
|
|
|
g_System->m_SaveUsing = SaveChip_Eeprom_4K;
|
|
|
|
}
|
2010-06-14 21:14:58 +00:00
|
|
|
|
2015-03-29 17:19:28 +00:00
|
|
|
switch (Command[2])
|
|
|
|
{
|
2010-06-14 21:14:58 +00:00
|
|
|
case 0: // check
|
2015-03-29 17:19:28 +00:00
|
|
|
if (g_System->m_SaveUsing != SaveChip_Eeprom_4K && g_System->m_SaveUsing != SaveChip_Eeprom_16K)
|
|
|
|
{
|
2010-06-14 21:14:58 +00:00
|
|
|
Command[1] |= 0x80;
|
|
|
|
break;
|
|
|
|
}
|
2012-09-26 10:36:52 +00:00
|
|
|
if (Command[1] != 3)
|
|
|
|
{
|
2010-06-14 21:14:58 +00:00
|
|
|
Command[1] |= 0x40;
|
2012-09-26 10:36:52 +00:00
|
|
|
if ((Command[1] & 3) > 0)
|
|
|
|
Command[3] = 0x00;
|
|
|
|
if ((Command[1] & 3) > 1)
|
2012-11-17 01:07:04 +00:00
|
|
|
Command[4] = (g_System->m_SaveUsing == SaveChip_Eeprom_4K) ? 0x80 : 0xC0;
|
2012-09-26 10:36:52 +00:00
|
|
|
if ((Command[1] & 3) > 2)
|
|
|
|
Command[5] = 0x00;
|
2015-03-29 17:19:28 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-06-14 21:14:58 +00:00
|
|
|
Command[3] = 0x00;
|
2012-11-17 01:07:04 +00:00
|
|
|
Command[4] = g_System->m_SaveUsing == SaveChip_Eeprom_4K?0x80:0xC0;
|
2010-06-14 21:14:58 +00:00
|
|
|
Command[5] = 0x00;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 4: // Read from Eeprom
|
2015-03-29 17:19:28 +00:00
|
|
|
if (Command[0] != 2 && bHaveDebugger())
|
|
|
|
{
|
|
|
|
g_Notify->DisplayError(L"What am I meant to do with this Eeprom Command");
|
|
|
|
}
|
|
|
|
if (Command[1] != 8 && bHaveDebugger())
|
|
|
|
{
|
|
|
|
g_Notify->DisplayError(L"What am I meant to do with this Eeprom Command");
|
|
|
|
}
|
2010-06-14 21:14:58 +00:00
|
|
|
ReadFrom(&Command[4],Command[3]);
|
|
|
|
break;
|
2015-01-26 03:58:53 +00:00
|
|
|
case 5: //Write to Eeprom
|
2015-03-29 17:19:28 +00:00
|
|
|
if (Command[0] != 10 && bHaveDebugger())
|
|
|
|
{
|
|
|
|
g_Notify->DisplayError(L"What am I meant to do with this Eeprom Command");
|
|
|
|
}
|
|
|
|
if (Command[1] != 1 && bHaveDebugger())
|
|
|
|
{
|
|
|
|
g_Notify->DisplayError(L"What am I meant to do with this Eeprom Command");
|
|
|
|
}
|
2010-06-14 21:14:58 +00:00
|
|
|
WriteTo(&Command[4],Command[3]);
|
|
|
|
break;
|
2012-09-26 10:36:52 +00:00
|
|
|
case 6: //RTC Status query
|
|
|
|
Command[3] = 0x00;
|
|
|
|
Command[4] = 0x10;
|
2015-01-26 03:58:53 +00:00
|
|
|
Command[5] = 0x00;
|
2012-09-26 10:36:52 +00:00
|
|
|
break;
|
2015-01-26 03:58:53 +00:00
|
|
|
case 7: //Read RTC block
|
2015-03-29 17:19:28 +00:00
|
|
|
switch (Command[3])
|
2012-09-26 10:36:52 +00:00
|
|
|
{
|
2015-01-26 03:58:53 +00:00
|
|
|
case 0: //Block number
|
2012-09-26 10:36:52 +00:00
|
|
|
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
|
2015-03-29 17:19:28 +00:00
|
|
|
if (g_Settings->LoadDword(Debugger_ShowPifErrors))
|
|
|
|
{
|
|
|
|
g_Notify->DisplayError(L"Write RTC, unimplemented");
|
|
|
|
}
|
2012-09-26 10:36:52 +00:00
|
|
|
break;
|
2010-06-14 21:14:58 +00:00
|
|
|
default:
|
2015-03-29 17:19:28 +00:00
|
|
|
if (g_Settings->LoadDword(Debugger_ShowPifErrors))
|
|
|
|
{
|
|
|
|
g_Notify->DisplayError(L"Unknown EepromCommand %d",Command[2]);
|
|
|
|
}
|
2010-06-14 21:14:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
void CEeprom::LoadEeprom()
|
2015-03-29 17:19:28 +00:00
|
|
|
{
|
2010-06-14 21:14:58 +00:00
|
|
|
CPath FileName;
|
|
|
|
DWORD dwRead;
|
|
|
|
|
2015-03-10 16:58:02 +00:00
|
|
|
memset(m_EEPROM,0xFF,sizeof(m_EEPROM));
|
2010-06-14 21:14:58 +00:00
|
|
|
|
2012-11-17 01:02:04 +00:00
|
|
|
FileName.SetDriveDirectory( g_Settings->LoadString(Directory_NativeSave).c_str());
|
|
|
|
FileName.SetName(g_Settings->LoadString(Game_GameName).c_str());
|
2010-06-14 21:14:58 +00:00
|
|
|
FileName.SetExtension("eep");
|
|
|
|
|
|
|
|
if (!FileName.DirectoryExists())
|
|
|
|
{
|
|
|
|
FileName.CreateDirectory();
|
|
|
|
}
|
|
|
|
|
|
|
|
m_hFile = CreateFile(FileName,m_ReadOnly ? GENERIC_READ : GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,
|
|
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL);
|
|
|
|
if (m_hFile == INVALID_HANDLE_VALUE)
|
|
|
|
{
|
2012-12-17 00:21:29 +00:00
|
|
|
WriteTraceF(TraceError,__FUNCTION__ ": Failed to open (%s), ReadOnly = %d, LastError = %X",(LPCTSTR)FileName, m_ReadOnly, GetLastError());
|
2012-11-17 00:58:31 +00:00
|
|
|
g_Notify->DisplayError(GS(MSG_FAIL_OPEN_EEPROM));
|
2010-06-14 21:14:58 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
SetFilePointer(m_hFile,0,NULL,FILE_BEGIN);
|
|
|
|
ReadFile(m_hFile,m_EEPROM,sizeof(m_EEPROM),&dwRead,NULL);
|
|
|
|
}
|
|
|
|
|
2015-03-29 17:19:28 +00:00
|
|
|
void CEeprom::ReadFrom(BYTE * Buffer, int line)
|
|
|
|
{
|
2010-06-14 21:14:58 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
if (m_hFile == NULL)
|
|
|
|
{
|
|
|
|
LoadEeprom();
|
|
|
|
}
|
|
|
|
|
2015-03-29 17:19:28 +00:00
|
|
|
for (i=0; i < 8; i++)
|
2010-06-14 21:14:58 +00:00
|
|
|
{
|
|
|
|
Buffer[i] = m_EEPROM[line*8+i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-29 17:19:28 +00:00
|
|
|
void CEeprom::WriteTo(BYTE * Buffer, int line)
|
|
|
|
{
|
2010-06-14 21:14:58 +00:00
|
|
|
DWORD dwWritten;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (m_hFile == NULL)
|
|
|
|
{
|
|
|
|
LoadEeprom();
|
|
|
|
}
|
2015-03-29 17:19:28 +00:00
|
|
|
for (i=0;i<8;i++)
|
|
|
|
{
|
|
|
|
m_EEPROM[line*8+i]=Buffer[i];
|
|
|
|
}
|
2010-06-14 21:14:58 +00:00
|
|
|
SetFilePointer(m_hFile,line*8,NULL,FILE_BEGIN);
|
|
|
|
WriteFile( m_hFile,Buffer,8,&dwWritten,NULL );
|
|
|
|
FlushFileBuffers(m_hFile);
|
|
|
|
}
|