2012-12-19 09:30:18 +00:00
/****************************************************************************
* *
2015-11-10 05:21:49 +00:00
* Project64 - A Nintendo 64 emulator . *
2012-12-19 09:30:18 +00:00
* 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-22 20:36:28 +00:00
# include "stdafx.h"
2015-12-06 09:59:58 +00:00
# include "FlashRam.h"
# include <Project64-core/N64System/SystemGlobals.h>
2015-12-21 07:35:22 +00:00
# include <Project64-core/N64System/Mips/MemoryVirtualMem.h>
2015-12-06 09:59:58 +00:00
# include <Common/path.h>
# include <Windows.h>
2010-06-22 20:36:28 +00:00
2015-12-13 07:10:40 +00:00
CFlashram : : CFlashram ( bool ReadOnly ) :
m_FlashRamPointer ( NULL ) ,
m_FlashFlag ( FLASHRAM_MODE_NOPES ) ,
m_FlashStatus ( 0 ) ,
m_FlashRAM_Offset ( 0 ) ,
m_ReadOnly ( ReadOnly ) ,
m_hFile ( NULL )
2010-06-22 20:36:28 +00:00
{
}
2015-04-28 22:19:02 +00:00
CFlashram : : ~ CFlashram ( )
2015-03-29 17:19:28 +00:00
{
2015-12-13 07:10:40 +00:00
if ( m_hFile )
{
CloseHandle ( m_hFile ) ;
m_hFile = NULL ;
}
2010-06-22 20:36:28 +00:00
}
2015-12-13 07:10:40 +00:00
void CFlashram : : DmaFromFlashram ( uint8_t * dest , int StartOffset , int len )
2010-06-22 20:36:28 +00:00
{
2015-12-06 09:59:58 +00:00
uint8_t FlipBuffer [ 0x10000 ] ;
uint32_t count ;
2010-06-22 20:36:28 +00:00
2015-12-13 07:10:40 +00:00
switch ( m_FlashFlag )
{
case FLASHRAM_MODE_READ :
if ( m_hFile = = NULL )
{
if ( ! LoadFlashram ( ) )
{
return ;
}
}
if ( len > 0x10000 )
{
if ( bHaveDebugger ( ) )
{
g_Notify - > DisplayError ( stdstr_f ( __FUNCTION__ " : DmaFromFlashram FlipBuffer to small (len: %d) " , len ) . ToUTF16 ( ) . c_str ( ) ) ;
}
len = 0x10000 ;
}
if ( ( len & 3 ) ! = 0 )
{
if ( bHaveDebugger ( ) )
{
g_Notify - > DisplayError ( __FUNCTIONW__ L " : Unaligned flash ram read ??? " ) ;
}
return ;
}
memset ( FlipBuffer , 0 , sizeof ( FlipBuffer ) ) ;
StartOffset = StartOffset < < 1 ;
SetFilePointer ( m_hFile , StartOffset , NULL , FILE_BEGIN ) ;
2015-12-06 09:59:58 +00:00
DWORD dwRead ;
2015-12-13 07:10:40 +00:00
ReadFile ( m_hFile , FlipBuffer , len , & dwRead , NULL ) ;
for ( count = dwRead ; ( int ) count < len ; count + + )
{
FlipBuffer [ count ] = 0xFF ;
}
for ( count = 0 ; ( int ) count < len ; count + = 4 )
{
2015-12-06 09:59:58 +00:00
register uint32_t eax ;
2015-09-15 22:55:27 +00:00
2015-12-06 09:59:58 +00:00
eax = * ( uint32_t * ) & FlipBuffer [ count ] ;
2015-12-13 07:10:40 +00:00
// eax = swap32by8(eax); // ; bswap eax
2015-12-06 09:59:58 +00:00
* ( uint32_t * ) ( dest + count ) = eax ;
2015-12-13 07:10:40 +00:00
}
break ;
case FLASHRAM_MODE_STATUS :
if ( StartOffset ! = 0 & & len ! = 8 )
{
if ( bHaveDebugger ( ) )
{
g_Notify - > DisplayError ( stdstr_f ( __FUNCTION__ " : Reading m_FlashStatus not being handled correctly \n Start: %X len: %X " , StartOffset , len ) . ToUTF16 ( ) . c_str ( ) ) ;
}
}
2015-12-06 09:59:58 +00:00
* ( ( uint32_t * ) ( dest ) ) = ( uint32_t ) ( ( m_FlashStatus > > 32 ) & 0xFFFFFFFF ) ;
* ( ( uint32_t * ) ( dest ) + 1 ) = ( uint32_t ) ( m_FlashStatus & 0xFFFFFFFF ) ;
2015-12-13 07:10:40 +00:00
break ;
default :
if ( bHaveDebugger ( ) )
{
g_Notify - > DisplayError ( stdstr_f ( __FUNCTION__ " : Start: %X, Offset: %X len: %X " , dest - g_MMU - > Rdram ( ) , StartOffset , len ) . ToUTF16 ( ) . c_str ( ) ) ;
}
}
2010-06-22 20:36:28 +00:00
}
2015-12-06 09:59:58 +00:00
void CFlashram : : DmaToFlashram ( uint8_t * Source , int StartOffset , int len )
2015-03-29 17:19:28 +00:00
{
2015-12-13 07:10:40 +00:00
switch ( m_FlashFlag )
{
case FLASHRAM_MODE_WRITE :
m_FlashRamPointer = Source ;
break ;
default :
if ( bHaveDebugger ( ) )
{
g_Notify - > DisplayError ( stdstr_f ( __FUNCTION__ " : Start: %X, Offset: %X len: %X " , Source - g_MMU - > Rdram ( ) , StartOffset , len ) . ToUTF16 ( ) . c_str ( ) ) ;
}
}
2010-06-22 20:36:28 +00:00
}
2015-12-06 09:59:58 +00:00
uint32_t CFlashram : : ReadFromFlashStatus ( uint32_t PAddr )
2010-06-22 20:36:28 +00:00
{
2015-12-13 07:10:40 +00:00
switch ( PAddr )
{
2015-12-06 09:59:58 +00:00
case 0x08000000 : return ( uint32_t ) ( m_FlashStatus > > 32 ) ;
2015-12-13 07:10:40 +00:00
default :
if ( bHaveDebugger ( ) )
{
g_Notify - > DisplayError ( stdstr_f ( __FUNCTION__ " : PAddr (%X) " , PAddr ) . ToUTF16 ( ) . c_str ( ) ) ;
}
break ;
}
2015-12-06 09:59:58 +00:00
return ( uint32_t ) ( m_FlashStatus > > 32 ) ;
2010-06-22 20:36:28 +00:00
}
2015-04-28 22:19:02 +00:00
bool CFlashram : : LoadFlashram ( )
2015-03-29 17:19:28 +00:00
{
2015-12-13 07:10:40 +00:00
CPath FileName ;
FileName . SetDriveDirectory ( g_Settings - > LoadStringVal ( Directory_NativeSave ) . c_str ( ) ) ;
FileName . SetName ( g_Settings - > LoadStringVal ( Game_GameName ) . c_str ( ) ) ;
FileName . SetExtension ( " fla " ) ;
if ( ! FileName . DirectoryExists ( ) )
{
FileName . DirectoryCreate ( ) ;
}
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 )
{
2015-12-14 10:51:33 +00:00
WriteTrace ( TraceN64System , TraceError , " Failed to open (%s), ReadOnly = %d, LastError = %X " , ( LPCTSTR ) FileName , m_ReadOnly , GetLastError ( ) ) ;
2015-12-13 07:10:40 +00:00
g_Notify - > DisplayError ( GS ( MSG_FAIL_OPEN_FLASH ) ) ;
return false ;
}
SetFilePointer ( m_hFile , 0 , NULL , FILE_BEGIN ) ;
return true ;
2010-06-22 20:36:28 +00:00
}
2015-12-06 09:59:58 +00:00
void CFlashram : : WriteToFlashCommand ( uint32_t FlashRAM_Command )
2015-03-29 17:19:28 +00:00
{
2015-12-06 09:59:58 +00:00
uint8_t EmptyBlock [ 128 ] ;
2015-12-13 07:10:40 +00:00
DWORD dwWritten ;
switch ( FlashRAM_Command & 0xFF000000 )
{
case 0xD2000000 :
switch ( m_FlashFlag )
{
case FLASHRAM_MODE_NOPES : break ;
case FLASHRAM_MODE_READ : break ;
case FLASHRAM_MODE_STATUS : break ;
case FLASHRAM_MODE_ERASE :
memset ( EmptyBlock , 0xFF , sizeof ( EmptyBlock ) ) ;
if ( m_hFile = = NULL ) {
if ( ! LoadFlashram ( ) )
{
return ;
}
}
SetFilePointer ( m_hFile , m_FlashRAM_Offset , NULL , FILE_BEGIN ) ;
WriteFile ( m_hFile , EmptyBlock , 128 , & dwWritten , NULL ) ;
break ;
case FLASHRAM_MODE_WRITE :
if ( m_hFile = = NULL ) {
if ( ! LoadFlashram ( ) )
{
return ;
}
}
{
uint8_t FlipBuffer [ 128 ] ;
register size_t edx ;
2015-12-06 09:59:58 +00:00
uint8_t * FlashRamPointer = m_FlashRamPointer ;
2015-09-15 22:55:27 +00:00
2015-12-13 07:10:40 +00:00
memset ( FlipBuffer , 0 , sizeof ( FlipBuffer ) ) ;
for ( edx = 0 ; edx < 128 ; edx + = 4 )
{
2015-12-06 09:59:58 +00:00
register uint32_t eax ;
2015-09-15 22:55:27 +00:00
2015-12-13 07:10:40 +00:00
eax = * ( unsigned __int32 * ) & FlashRamPointer [ edx ] ;
// eax = swap32by8(eax); // ; bswap eax
* ( unsigned __int32 * ) ( FlipBuffer + edx ) = eax ;
}
SetFilePointer ( m_hFile , m_FlashRAM_Offset , NULL , FILE_BEGIN ) ;
WriteFile ( m_hFile , FlipBuffer , 128 , & dwWritten , NULL ) ;
}
break ;
default :
g_Notify - > DisplayError ( stdstr_f ( " Writing %X to flash ram command register \n m_FlashFlag: %d " , FlashRAM_Command , m_FlashFlag ) . ToUTF16 ( ) . c_str ( ) ) ;
}
m_FlashFlag = FLASHRAM_MODE_NOPES ;
break ;
case 0xE1000000 :
m_FlashFlag = FLASHRAM_MODE_STATUS ;
m_FlashStatus = 0x1111800100C2001E ;
break ;
case 0xF0000000 :
m_FlashFlag = FLASHRAM_MODE_READ ;
m_FlashStatus = 0x11118004F0000000 ;
break ;
case 0x4B000000 :
m_FlashRAM_Offset = ( FlashRAM_Command & 0xffff ) * 128 ;
break ;
case 0x78000000 :
m_FlashFlag = FLASHRAM_MODE_ERASE ;
m_FlashStatus = 0x1111800800C2001E ;
break ;
case 0xB4000000 :
m_FlashFlag = FLASHRAM_MODE_WRITE ; //????
break ;
case 0xA5000000 :
m_FlashRAM_Offset = ( FlashRAM_Command & 0xffff ) * 128 ;
m_FlashStatus = 0x1111800400C2001E ;
break ;
default :
if ( bHaveDebugger ( ) )
{
g_Notify - > DisplayError ( stdstr_f ( " Writing %X to flash ram command register " , FlashRAM_Command ) . ToUTF16 ( ) . c_str ( ) ) ;
}
}
}