Added E-Reader scan support by CaitSith2.

One thing it does, is correct any raw files scanned, if they are correctable. (usually, uncorrectable raw files come up with a read error.)  There is also bin support included as well. (Note, if you open a valid dotcode bin, it will encode it to raw, and save the freshly encoded raw file if it has been set in the menu. If the dotcode save file has not been set, the bin will still load.)

Currently, part of the GBA emulation breaks the E-Reader scan code. The reader always returns a Region Error.
This commit is contained in:
skidau 2015-03-27 22:50:11 +00:00
parent efd5c1b483
commit a65204d54f
20 changed files with 857 additions and 6 deletions

View File

@ -200,6 +200,7 @@ SET(SRC_GBA
src/gba/Cheats.cpp
src/gba/CheatSearch.cpp
src/gba/EEprom.cpp
src/gba/ereader.cpp
src/gba/Flash.cpp
src/gba/GBA.cpp
src/gba/GBAGfx.cpp

View File

@ -430,6 +430,14 @@
RelativePath="..\..\src\gba\agbprint.h"
>
</File>
<File
RelativePath="..\..\src\gba\ereader.cpp"
>
</File>
<File
RelativePath="..\..\src\gba\ereader.h"
>
</File>
<File
RelativePath="..\..\src\gba\bios.cpp"
>

View File

@ -6,7 +6,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VisualBoyAdvance-M", "VBA20
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\..\..\dependencies\zlib\project\vs2010\zlib.vcxproj", "{3E03C179-8251-46E4-81F4-466F114BAC63}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SFML_Network", "..\..\..\dependencies\SFML\build\vc2010\sfml-network.vcxproj", "{823DDC98-42D5-4A38-88CF-9DC06C788AE4}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SFML", "..\..\..\dependencies\SFML\build\vc2010\sfml-network.vcxproj", "{823DDC98-42D5-4A38-88CF-9DC06C788AE4}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpng", "..\..\..\dependencies\libpng\project\vs2010\libpng.vcxproj", "{0008960E-E0DD-41A6-8265-00B31DDB4C21}"
EndProject

View File

@ -110,7 +110,7 @@
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>..\..\src;..\..\fex;..\..\..\dependencies\libpng;..\..\..\dependencies\msvc;..\..\..\dependencies\SFML\include;..\..\..\dependencies\SubWCRev;..\..\..\dependencies\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;GBA_LOGGING;OEMRESOURCE;MMX;ASM;FINAL_VERSION;BKPT_SUPPORT;_CRT_SECURE_NO_DEPRECATE;HAS_FILE_EXTRACTOR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;_WINDOWS;NO_OAL;NDEBUG;GBA_LOGGING;OEMRESOURCE;MMX;ASM;FINAL_VERSION;BKPT_SUPPORT;_CRT_SECURE_NO_DEPRECATE;HAS_FILE_EXTRACTOR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
<FloatingPointModel>Fast</FloatingPointModel>
@ -166,6 +166,7 @@
<ClInclude Include="..\..\src\apu\Gb_Oscs.h" />
<ClInclude Include="..\..\src\apu\Multi_Buffer.h" />
<ClInclude Include="..\..\src\gba\agbprint.h" />
<ClInclude Include="..\..\src\gba\ereader.h" />
<ClInclude Include="..\..\src\gba\bios.h" />
<ClInclude Include="..\..\src\gba\EEprom.h" />
<ClInclude Include="..\..\src\gba\elf.h" />
@ -296,6 +297,7 @@
<ClCompile Include="..\..\src\gba\bios.cpp" />
<ClCompile Include="..\..\src\gba\EEprom.cpp" />
<ClCompile Include="..\..\src\gba\elf.cpp" />
<ClCompile Include="..\..\src\gba\ereader.cpp" />
<ClCompile Include="..\..\src\gba\Flash.cpp" />
<ClCompile Include="..\..\src\gba\gba-arm.cpp" />
<ClCompile Include="..\..\src\gba\gba-thumb.cpp" />

View File

@ -109,6 +109,9 @@
<ClInclude Include="..\..\src\gba\agbprint.h">
<Filter>Core\GBA</Filter>
</ClInclude>
<ClInclude Include="..\..\src\gba\ereader.h">
<Filter>Core\GBA</Filter>
</ClInclude>
<ClInclude Include="..\..\src\gba\bios.h">
<Filter>Core\GBA</Filter>
</ClInclude>
@ -487,6 +490,9 @@
<ClCompile Include="..\..\src\gba\elf.cpp">
<Filter>Core\GBA</Filter>
</ClCompile>
<ClCompile Include="..\..\src\gba\ereader.cpp">
<Filter>Core\GBA</Filter>
</ClCompile>
<ClCompile Include="..\..\src\gba\Flash.cpp">
<Filter>Core\GBA</Filter>
</ClCompile>

View File

@ -176,6 +176,7 @@
<ClInclude Include="..\..\src\gba\bios.h" />
<ClInclude Include="..\..\src\gba\EEprom.h" />
<ClInclude Include="..\..\src\gba\elf.h" />
<ClInclude Include="..\..\src\gba\ereader.h" />
<ClInclude Include="..\..\src\gba\Flash.h" />
<ClInclude Include="..\..\src\gba\gba.h" />
<ClInclude Include="..\..\src\gba\GBAcpu.h" />
@ -303,6 +304,7 @@
<ClCompile Include="..\..\src\gba\bios.cpp" />
<ClCompile Include="..\..\src\gba\EEprom.cpp" />
<ClCompile Include="..\..\src\gba\elf.cpp" />
<ClCompile Include="..\..\src\gba\ereader.cpp" />
<ClCompile Include="..\..\src\gba\Flash.cpp" />
<ClCompile Include="..\..\src\gba\gba-arm.cpp" />
<ClCompile Include="..\..\src\gba\gba-thumb.cpp" />

View File

@ -118,6 +118,9 @@
<ClInclude Include="..\..\src\gba\elf.h">
<Filter>Core\GBA</Filter>
</ClInclude>
<ClInclude Include="..\..\src\gba\ereader.h">
<Filter>Core\GBA</Filter>
</ClInclude>
<ClInclude Include="..\..\src\gba\Flash.h">
<Filter>Core\GBA</Filter>
</ClInclude>
@ -487,6 +490,9 @@
<ClCompile Include="..\..\src\gba\elf.cpp">
<Filter>Core\GBA</Filter>
</ClCompile>
<ClCompile Include="..\..\src\gba\ereader.cpp">
<Filter>Core\GBA</Filter>
</ClCompile>
<ClCompile Include="..\..\src\gba\Flash.cpp">
<Filter>Core\GBA</Filter>
</ClCompile>

View File

@ -20,6 +20,7 @@
#include "../common/Port.h"
#include "../System.h"
#include "agbprint.h"
#include "ereader.h"
#include "GBALink.h"
#ifdef PROFILING
@ -159,6 +160,9 @@ u8 memoryWaitSeq32[16] =
u8 biosProtected[4];
const char *loadDotCodeFile;
const char *saveDotCodeFile;
#ifdef WORDS_BIGENDIAN
bool cpuBiosSwapped = false;
#endif
@ -1616,6 +1620,26 @@ void doMirroring (bool b)
}
}
const char* GetLoadDotCodeFile()
{
return loadDotCodeFile;
}
const char* GetSaveDotCodeFile()
{
return saveDotCodeFile;
}
void SetLoadDotCodeFile(const char *szFile)
{
loadDotCodeFile = szFile;
}
void SetSaveDotCodeFile(const char *szFile)
{
saveDotCodeFile = szFile;
}
void CPUUpdateRender()
{
switch(DISPCNT & 7) {
@ -1931,8 +1955,19 @@ void CPUSoftwareInterrupt(int comment)
VCOUNT);
}
#endif
CPUSoftwareInterrupt();
return;
if ((comment & 0xF8) != 0xE0)
{
CPUSoftwareInterrupt();
return;
}
else
{
if (CheckEReaderRegion())
BIOS_EReader_ScanCard(comment);
else
CPUSoftwareInterrupt();
return;
}
}
// This would be correct, but it causes problems if uncommented
// else {
@ -2160,6 +2195,17 @@ void CPUSoftwareInterrupt(int comment)
case 0x1F:
BIOS_MidiKey2Freq();
break;
case 0xE0:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
if (CheckEReaderRegion())
BIOS_EReader_ScanCard(comment);
break;
case 0x2A:
BIOS_SndDriverJmpTableCopy();
// let it go, because we don't really emulate this function
@ -3271,6 +3317,18 @@ void CPUReset()
break;
}
}
switch (CheckEReaderRegion())
{
case 1: //US
EReaderWriteMemory(0x8009134, 0x46C0DFE0);
break;
case 2:
EReaderWriteMemory(0x8008A8C, 0x46C0DFE0);
break;
case 3:
EReaderWriteMemory(0x80091A8, 0x46C0DFE0);
break;
}
rtcReset();
// clean registers
memset(&reg[0], 0, sizeof(reg));

View File

@ -114,6 +114,11 @@ extern void cpuProfil(profile_segment *seg);
extern void cpuEnableProfiling(int hz);
#endif
const char* GetLoadDotCodeFile();
const char* GetSaveDotCodeFile();
void SetLoadDotCodeFile(const char *szFile);
void SetSaveDotCodeFile(const char *szFile);
extern struct EmulatedSystem GBASystem;
#define R13_IRQ 18

670
src/gba/ereader.cpp Normal file
View File

@ -0,0 +1,670 @@
#include <stdio.h>
#include <locale>
#include <malloc.h>
#include <string.h>
#include "GBA.h"
#include "GBAinline.h"
#include "Globals.h"
#include "ereader.h"
//#include "win32/stdafx.h"
//#include "win32/vba.h"
//#include "win32/MainWnd.h"
//#include "win32/FileDlg.h"
//#include "win32/WinResUtil.h"
//#include "win32/MainWnd.h"
int eReaderSaveRAW = 1;
char US_Ereader[19] = "CARDE READERPSAE01";
char JAP_Ereader[19] = "CARDE READERPEAJ01";
char JAP_Ereader_plus[19] = "CARDEREADER+PSAJ01";
char rom_info[19];
char Signature[0x29] = "E-Reader Dotcode -Created- by CaitSith2";
unsigned char ShortDotCodeHeader[0x30] = {
0x00, 0x30, 0x01, 0x01,
0x00, 0x01, 0x05, 0x10,
0x00, 0x00, 0x10, 0x12, //Constant data
0x00, 0x00, //Header First 2 bytes
0x02, 0x00, //Constant data
0x00, 0x00, //Header Second 2 bytes
0x10, 0x47, 0xEF, //Global Checksum 1
0x19, 0x00, 0x00, 0x00, 0x08, 0x4E, 0x49,
0x4E, 0x54, 0x45, 0x4E, 0x44, 0x4F, 0x00, 0x22,
0x00, 0x09, //Constant data
0x00, 0x00, //Header, last 8 bytes
0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
0x00, //Header Checksum
0x57 //Global Checksum 2
};
unsigned char LongDotCodeHeader[0x30] = {
0x00, 0x30, 0x01, 0x02,
0x00, 0x01, 0x08, 0x10,
0x00, 0x00, 0x10, 0x12, //Constant Data
0x00, 0x00, //Header, first 2 bytes
0x01, 0x00, //Constant data
0x00, 0x00, //Header, second 2 bytes
0x10, 0x9A, 0x99, //Global Checksum 1
0x19, 0x00, 0x00, 0x00, 0x08, 0x4E, 0x49,
0x4E, 0x54, 0x45, 0x4E, 0x44, 0x4F, 0x00, 0x22,
0x00, 0x09, //Constant data
0x00, 0x00, //Header, last 8 bytes
0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
0x00, //Header Checksum
0x57 //Global Checksum 2
};
unsigned char shortheader[0x18] = {
0x00, 0x02, 0x00, 0x01, 0x40, 0x10, 0x00, 0x1C,
0x10, 0x6F, 0x40, 0xDA, 0x39, 0x25, 0x8E, 0xE0,
0x7B, 0xB5, 0x98, 0xB6, 0x5B, 0xCF, 0x7F, 0x72
};
unsigned char longheader[0x18] = {
0x00, 0x03, 0x00, 0x19, 0x40, 0x10, 0x00, 0x2C,
0x0E, 0x88, 0xED, 0x82, 0x50, 0x67, 0xFB, 0xD1,
0x43, 0xEE, 0x03, 0xC6, 0xC6, 0x2B, 0x2C, 0x93
};
unsigned char dotcodeheader[0x48];
unsigned char dotcodedata[0xB38];
unsigned char dotcodetemp[0xB00];
int dotcodepointer;
int dotcodeinterleave;
int decodestate;
u32 GFpow;
unsigned char *DotCodeData;
char filebuffer[2048];
int dotcodesize;
int CheckEReaderRegion(void) //US = 1, JAP = 2, JAP+ = 3
{
int i;
for(i=0;i<18;i++)
rom_info[i] = rom[0xA0+i];
rom_info[i] = 0;
if (std::tolower(*rom_info, std::locale()) == std::tolower(*US_Ereader, std::locale()))
return 1;
if (std::tolower(*rom_info, std::locale()) == std::tolower(*JAP_Ereader, std::locale()))
return 2;
if (std::tolower(*rom_info, std::locale()) == std::tolower(*JAP_Ereader_plus, std::locale()))
return 3;
return 0;
}
int LoadDotCodeData(int size, u32* DCdata, unsigned long MEM1, unsigned long MEM2, int loadraw)
{
u32 temp1;
int i,j;
unsigned char scanmap[28];
int scantotal=0;
for(i=0;i<28;i++)
scanmap[i] = 0;
unsigned char longdotcodescan[28] = {
0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
0xF1, 0xF2, 0xB1, 0xB1
};
unsigned char shortdotcodescan[18] = {
0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
0xF1, 0xF1, 0xF1, 0xF2, 0xB1, 0xB1
};
temp1 = CPUReadMemory(MEM1-4);
for(i=0;i<0x60;i+=4)
CPUWriteMemory((MEM2-8)+i,0);
for(i=0;i<0x1860;i+=4)
CPUWriteMemory(temp1+i,0);
if(DCdata != NULL)
{
if(size==0xB60)
{
for(i=0;i<28;i++)
{
for(j=0,scantotal=0;j<0x68;j+=4)
{
scantotal += DCdata[((i*0x68)+j)>>2];
}
if(scantotal)
scanmap[i] = longdotcodescan[i];
}
for(i=0;i<size;i+=4)
{
CPUWriteMemory(temp1+i+0x9C0,DCdata[i>>2]);
}
}
else if (size==0x750)
{
for(i=0;i<18;i++)
{
if((DCdata[0] == 0x02011394) && (DCdata[1] == 0x0203E110) && (i == 0))
continue;
for(j=0,scantotal=0;j<0x68;j+=4)
{
scantotal += DCdata[((i*0x68)+j)>>2];
}
if(scantotal)
scanmap[i] = longdotcodescan[i];
}
for(i=0;i<size;i+=4)
{
CPUWriteMemory(temp1+i,DCdata[i>>2]);
}
}
}
CPUWriteMemory(MEM2-8,0x1860);
CPUWriteMemory(MEM2-4,temp1);
if(size==0xB60)
{
if(loadraw)
{
for(i=0;i<28;i++)
CPUWriteByte(MEM2+0x18+i,scanmap[i]);
}
else
{
CPUWriteMemory(MEM2+0x18,0xF1F1F1F1);
CPUWriteMemory(MEM2+0x18+4,0xF1F1F1F1);
CPUWriteMemory(MEM2+0x18+8,0xF1F1F1F1);
CPUWriteMemory(MEM2+0x18+12,0xF1F1F1F1);
CPUWriteMemory(MEM2+0x18+16,0xF1F1F1F1);
CPUWriteMemory(MEM2+0x18+20,0xF1F1F1F1);
CPUWriteMemory(MEM2+0x18+24,0xB1B1F2F1);
}
CPUWriteMemory(MEM2+0x40,0x19);
CPUWriteMemory(MEM2+0x44,0x34);
}
else if (size==0x750)
{
if(loadraw)
{
for(i=0;i<18;i++)
CPUWriteByte(MEM2+i,scanmap[i]);
}
else
{
CPUWriteMemory(MEM2,0xF1F1F1F1);
CPUWriteMemory(MEM2+4,0xF1F1F1F1);
CPUWriteMemory(MEM2+8,0xF1F1F1F1);
CPUWriteMemory(MEM2+12,0xF2F1F1F1);
CPUWriteMemory(MEM2+16,0xB1B1);
}
CPUWriteMemory(MEM2+0x40,0x01);
CPUWriteMemory(MEM2+0x44,0x12);
}
CPUWriteMemory(MEM2+0x48,0x3C);
CPUWriteMemory(MEM2+0x4C,MEM2);
return 0;
}
void EReaderWriteMemory(u32 address, u32 value)
{
switch(address >> 24)
{
case 2:
WRITE32LE(((u32 *)&workRAM[address & 0x3FFFF]), value);
break;
case 3:
WRITE32LE(((u32 *)&internalRAM[address & 0x7FFF]), value);
break;
default:
WRITE32LE(((u32 *)&rom[address & 0x1FFFFFF]), value);
//rom[address & 0x1FFFFFF] = data;
break;
}
}
void BIOS_EReader_ScanCard(int swi_num)
{
int i,j,k;
int dotcodetype;
int global1, global2;
FILE *f;
//Open dotcode bin/raw
if(swi_num == 0xE0)
{
dotcodepointer = 0;
dotcodeinterleave = 0;
decodestate = 0;
const char* loadDotCodeFile = GetLoadDotCodeFile();
if (loadDotCodeFile == 0)
{
reg[0].I = 0x301;
return;
}
f=fopen(loadDotCodeFile,"rb");
//f=fopen(filebuffer,"rb");
//f=fopen("dotcode4.raw","rb");
if(f==NULL)
{
reg[0].I = 0x303;
return;
}
fseek(f,0,SEEK_END);
i=ftell(f);
fseek(f,0,SEEK_SET);
if((i==0xB60) || (i==0x750))
{
dotcodetype = 0;
}
else if ((i==0x81C) || (i==0x51C))
{
dotcodetype = 1;
}
else
{
fclose(f);
reg[0].I = 0x303;
return;
}
DotCodeData = (unsigned char*)malloc(i);
if(DotCodeData == NULL)
{
reg[0].I = 0x303;
return;
}
fread(DotCodeData,1,i,f);
fclose(f);
if(dotcodetype == 0)
{
switch(CheckEReaderRegion())
{
case 1: //US
LoadDotCodeData(i,(u32 *)DotCodeData,0x2032D14,0x2028B28,1);
EReaderWriteMemory(0x80091BA,0x46C0DFE2);
break;
case 2:
LoadDotCodeData(i,(u32 *)DotCodeData,0x2006EC4,0x2002478,1);
EReaderWriteMemory(0x8008B12,0x46C0DFE2);
break;
case 3:
LoadDotCodeData(i,(u32 *)DotCodeData,0x202F8A4,0x2031034,1);
EReaderWriteMemory(0x800922E,0x46C0DFE2);
break;
}
reg[0].I = 0;
free(DotCodeData);
}
else
{
//dotcodesize = i;
if(i==0x81C)
dotcodesize = 0xB60;
else
dotcodesize = 0x750;
switch(CheckEReaderRegion())
{
case 1: //US
LoadDotCodeData(dotcodesize,(u32 *)NULL,0x2032D14,0x2028B28,0);
EReaderWriteMemory(0x80091BA,0x46C0DFE1);
break;
case 2:
LoadDotCodeData(dotcodesize,(u32 *)NULL,0x2006EC4,0x2002478,0);
EReaderWriteMemory(0x8008B12,0x46C0DFE1);
break;
case 3:
LoadDotCodeData(dotcodesize,(u32 *)NULL,0x202F8A4,0x2031034,0);
EReaderWriteMemory(0x800922E,0x46C0DFE1);
break;
}
reg[0].I = 0;
dotcodesize = i;
}
}
else if (swi_num == 0xE1)
{
switch(CheckEReaderRegion())
{
case 1: //US
EReaderWriteMemory(0x80091BA,0xF8A5F03B);
EReaderWriteMemory(0x3002F7C,0xEFE40000); //Beginning of Reed-Solomon decoder
EReaderWriteMemory(0x3003144,0xCA00002F); //Fix required to Correct 16 "Erasures"
EReaderWriteMemory(0x300338C,0xEFE50000); //End of Reed-Solomon decoder
GFpow = 0x3000A6C;
break;
case 2:
EReaderWriteMemory(0x8008B12,0xFB0BF035);
EReaderWriteMemory(0x3002F88,0xEFE40000);
EReaderWriteMemory(0x3003150,0xCA00002F);
EReaderWriteMemory(0x3003398,0xEFE50000);
GFpow = 0x3000A78;
break;
case 3:
EReaderWriteMemory(0x800922E,0xF94BF04B);
EReaderWriteMemory(0x3002F7C,0xEFE40000);
EReaderWriteMemory(0x3003144,0xCA00002F);
EReaderWriteMemory(0x300338C,0xEFE50000);
GFpow = 0x3000A6C;
break;
}
armNextPC -= 2;
reg[15].I -= 2;
for(i=0,j=0;i<12;i++)
j ^= DotCodeData[i];
if(dotcodesize == 0x81C)
{
LongDotCodeHeader[0x2E] = j;
LongDotCodeHeader[0x0D] = DotCodeData[0];
LongDotCodeHeader[0x0C] = DotCodeData[1];
LongDotCodeHeader[0x11] = DotCodeData[2];
LongDotCodeHeader[0x10] = DotCodeData[3];
LongDotCodeHeader[0x26] = DotCodeData[4];
LongDotCodeHeader[0x27] = DotCodeData[5];
LongDotCodeHeader[0x28] = DotCodeData[6];
LongDotCodeHeader[0x29] = DotCodeData[7];
LongDotCodeHeader[0x2A] = DotCodeData[8];
LongDotCodeHeader[0x2B] = DotCodeData[9];
LongDotCodeHeader[0x2C] = DotCodeData[10];
LongDotCodeHeader[0x2D] = DotCodeData[11];
LongDotCodeHeader[0x12] = 0x10; //calculate Global Checksum 1
LongDotCodeHeader[0x02] = 1; //Do not calculate Global Checksum 2
for(i=0x0C,j=0;i<0x81C;i++)
{
if(i&1)
j += DotCodeData[i];
else
j += (DotCodeData[i] << 8);
}
j &= 0xFFFF;
j ^= 0xFFFF;
LongDotCodeHeader[0x13] = (j & 0xFF00) >> 8;
LongDotCodeHeader[0x14] = (j & 0x00FF);
for(i=0,j=0;i<0x2F;i++)
j+=LongDotCodeHeader[i];
j &= 0xFF;
for(i=1,global2=0;i<0x2C;i++)
{
for(k=0,global1=0;k<0x30;k++)
{
global1 ^= DotCodeData[((i-1)*0x30)+k+0x0C];
}
global2 += global1;
}
global2 += j;
global2 &= 0xFF;
global2 ^= 0xFF;
LongDotCodeHeader[0x2F] = global2;
}
else
{
ShortDotCodeHeader[0x2E] = j;
ShortDotCodeHeader[0x0D] = DotCodeData[0];
ShortDotCodeHeader[0x0C] = DotCodeData[1];
ShortDotCodeHeader[0x11] = DotCodeData[2];
ShortDotCodeHeader[0x10] = DotCodeData[3];
ShortDotCodeHeader[0x26] = DotCodeData[4];
ShortDotCodeHeader[0x27] = DotCodeData[5];
ShortDotCodeHeader[0x28] = DotCodeData[6];
ShortDotCodeHeader[0x29] = DotCodeData[7];
ShortDotCodeHeader[0x2A] = DotCodeData[8];
ShortDotCodeHeader[0x2B] = DotCodeData[9];
ShortDotCodeHeader[0x2C] = DotCodeData[10];
ShortDotCodeHeader[0x2D] = DotCodeData[11];
ShortDotCodeHeader[0x12] = 0x10; //calculate Global Checksum 1
ShortDotCodeHeader[0x02] = 1; //Do not calculate Global Checksum 2
for(i=0x0C,j=0;i<0x51C;i++)
{
if(i&1)
j += DotCodeData[i];
else
j += (DotCodeData[i] << 8);
}
j &= 0xFFFF;
j ^= 0xFFFF;
ShortDotCodeHeader[0x13] = (j & 0xFF00) >> 8;
ShortDotCodeHeader[0x14] = (j & 0x00FF);
for(i=0,j=0;i<0x2F;i++)
j+=ShortDotCodeHeader[i];
j &= 0xFF;
for(i=1,global2=0;i<0x1C;i++)
{
for(k=0,global1=0;k<0x30;k++)
{
global1 ^= DotCodeData[((i-1)*0x30)+k+0x0C];
}
global2 += global1;
}
global2 += j;
global2 &= 0xFF;
global2 ^= 0xFF;
ShortDotCodeHeader[0x2F] = global2;
}
}
else if (swi_num == 0xE2) //Header
{
switch(CheckEReaderRegion())
{
case 1: //US
EReaderWriteMemory(0x80091BA,0xF8A5F03B);
EReaderWriteMemory(0x300338C,0xEFE30000);
GFpow = 0x3000A6C;
break;
case 2:
EReaderWriteMemory(0x8008B12,0xFB0BF035);
EReaderWriteMemory(0x3003398,0xEFE30000);
GFpow = 0x3000A78;
break;
case 3:
EReaderWriteMemory(0x800922E,0xF94BF04B);
EReaderWriteMemory(0x300338C,0xEFE30000);
GFpow = 0x3000A6C;
break;
}
armNextPC -= 2;
reg[15].I -= 2;
}
else if ((swi_num == 0xE3) || (swi_num == 0xE5)) //Dotcode data
{
if((reg[0].I >= 0) && (reg[0].I <= 0x10))
{
if(decodestate == 0)
{
for(i=0x17;i>=0;i--)
{
if((0x17 - i) < 8)
j=CPUReadByte(GFpow + CPUReadByte(GFpow+0x200+i));
else
j=CPUReadByte(GFpow + CPUReadByte(GFpow+0x200+i)) ^ 0xFF;
dotcodeheader[(0x17-i)] = j;
dotcodeheader[(0x17-i)+0x18] = j;
dotcodeheader[(0x17-i)+0x30] = j;
}
for(i=0;i<28;i++)
for(j=0;j<2;j++)
dotcodedata[(i*0x68)+j] = dotcodeheader[(i*2)+j];
dotcodeinterleave = dotcodeheader[7];
decodestate = 1;
}
else
{
for(i=0x3F;i>=0;i--)
{
if((0x3F - i) < 0x30)
j=CPUReadByte(GFpow + CPUReadByte(GFpow+0x200+i));
else
j=CPUReadByte(GFpow + CPUReadByte(GFpow+0x200+i)) ^ 0xFF;
dotcodetemp[((0x3F-i)*dotcodeinterleave)+dotcodepointer] = j;
}
dotcodepointer++;
if((dotcodepointer == dotcodeinterleave))
{
switch(dotcodeinterleave)
{
case 0x1C:
j = 0x724;
k = 0x750 - j;
break;
case 0x2C:
j = 0xB38;
k = 0xB60 - j;
break;
}
dotcodepointer = 0;
for(i=2;i<j;i++)
{
if((i % 0x68) == 0)
i+=2;
dotcodedata[i] = dotcodetemp[dotcodepointer++];
}
if(swi_num == 0xE3)
{
const char* loadDotCodeFile = GetLoadDotCodeFile();
f = fopen(loadDotCodeFile, "rb+");
if(f!=NULL)
{
fwrite(dotcodedata,1,j,f);
fclose(f);
}
}
else
{
const char* saveDotCodeFile = GetSaveDotCodeFile();
if (saveDotCodeFile)
{
f = fopen(saveDotCodeFile, "wb");
if(f!=NULL)
{
fwrite(dotcodedata,1,j,f);
fwrite(Signature,1,0x28,f);
if(j==0x724)
{
fputc(0x65,f);
fputc(0x02,f);
fputc(0x71,f);
fputc(0x10,f);
}
fclose(f);
}
}
free(DotCodeData);
}
}
}
}
int base = 14;
armState = reg[base].I & 1 ? false : true;
if(armState) {
reg[15].I = reg[base].I & 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
} else {
reg[15].I = reg[base].I & 0xFFFFFFFE;
armNextPC = reg[15].I;
reg[15].I += 2;
}
}
else if (swi_num == 0xE4)
{
reg[12].I = reg[13].I;
if(decodestate == 0)
{
for(i=0;i<0x18;i++)
{
if(dotcodesize == 0x81C)
j=longheader[i];
else
j=shortheader[i];
if(i<8)
j=CPUReadByte(GFpow + 0x100 + j);
else
j=CPUReadByte(GFpow + 0x100 + (j ^ 0xFF));
CPUWriteByte(GFpow + 0x200 + (0x17 - i),j);
}
}
else
{
if(dotcodepointer == 0)
{
for(i=0;i<0x30;i++)
{
if(dotcodesize == 0x81C)
j=LongDotCodeHeader[i];
else
j=ShortDotCodeHeader[i];
j=CPUReadByte(GFpow + 0x100 + j);
CPUWriteByte(GFpow + 0x200 + (0x3F - i),j);
}
}
else
{
for(i=0;i<0x30;i++)
{
j=DotCodeData[((dotcodepointer-1)*0x30)+0x0C+i];
j=CPUReadByte(GFpow + 0x100 + j);
CPUWriteByte(GFpow + 0x200 + (0x3F - i),j);
}
}
for(i=0;i<16;i++)
CPUWriteByte(GFpow + 0x258 + i,1); //16 Erasures on the parity bytes, to have them calculated.
}
}
}

11
src/gba/ereader.h Normal file
View File

@ -0,0 +1,11 @@
extern unsigned char *DotCodeData;
extern char filebuffer[];
extern int eReaderSaveRAW;
int OpenDotCodeFile(void);
int CheckEReaderRegion(void);
int LoadDotCodeData(int size, u32* DCdata, unsigned long MEM1, unsigned long MEM2);
void EReaderWriteMemory(u32 address, u32 value);
void BIOS_EReader_ScanCard(int swi_num);

View File

@ -25,6 +25,7 @@ LOCAL_SRC_FILES = $(VBADIR)/gba/agbprint.cpp \
$(VBADIR)/gba/CheatSearch.cpp \
$(VBADIR)/gba/EEprom.cpp \
$(VBADIR)/gba/elf.cpp \
$(VBADIR)/gba/ereader.cpp \
$(VBADIR)/gba/Flash.cpp \
$(VBADIR)/gba/GBA-arm.cpp \
$(VBADIR)/gba/GBA.cpp \

View File

@ -18,6 +18,8 @@ struct {
{ "FileOpenGBA", ID_FILE_OPEN_GBA },
{ "FileOpenGBC", ID_FILE_OPEN_GBC },
{ "FileOpenGB", ID_FILE_OPEN_GB },
{ "FileLoadDotCode", ID_FILE_LOAD_DOTCODE },
{ "FileSaveDotCode", ID_FILE_SAVE_DOTCODE },
{ "FileLoad", ID_FILE_LOAD },
{ "FileSave", ID_FILE_SAVE },
{ "FileLoadGame01", ID_FILE_LOADGAME_SLOT1 },

View File

@ -63,6 +63,8 @@ BEGIN_MESSAGE_MAP(MainWnd, CWnd)
ON_COMMAND(ID_FILE_OPEN_GBA, OnFileOpenGBA)
ON_COMMAND(ID_FILE_OPEN_GBC, OnFileOpenGBC)
ON_COMMAND(ID_FILE_OPEN_GB, OnFileOpenGB)
ON_COMMAND(ID_FILE_LOAD_DOTCODE, OnFileLoadDotCode)
ON_COMMAND(ID_FILE_SAVE_DOTCODE, OnFileSaveDotCode)
ON_WM_INITMENUPOPUP()
ON_COMMAND(ID_FILE_PAUSE, OnFilePause)
ON_UPDATE_COMMAND_UI(ID_FILE_PAUSE, OnUpdateFilePause)
@ -168,6 +170,8 @@ BEGIN_MESSAGE_MAP(MainWnd, CWnd)
ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_AUTOMATICALLYAPPLYPATCHFILES, OnUpdateOptionsEmulatorAutomaticallyipspatch)
ON_COMMAND(ID_OPTIONS_EMULATOR_AGBPRINT, OnOptionsEmulatorAgbprint)
ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_AGBPRINT, OnUpdateOptionsEmulatorAgbprint)
ON_COMMAND(ID_OPTIONS_EMULATOR_EREADER, OnOptionsEmulatorEreader)
ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_EREADER, OnUpdateOptionsEmulatorEreader)
ON_COMMAND(ID_OPTIONS_EMULATOR_REALTIMECLOCK, OnOptionsEmulatorRealtimeclock)
ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_REALTIMECLOCK, OnUpdateOptionsEmulatorRealtimeclock)
ON_COMMAND(ID_OPTIONS_EMULATOR_REWINDINTERVAL, OnOptionsEmulatorRewindinterval)
@ -1024,7 +1028,6 @@ void MainWnd::OnSystemMinimize()
ShowWindow(SW_SHOWMINIMIZED);
}
bool MainWnd::fileOpenSelect( int system )
{
theApp.dir = _T("");
@ -1097,6 +1100,50 @@ bool MainWnd::fileOpenSelect( int system )
return false;
}
// EReader
void MainWnd::OnFileLoadDotCode()
{
// ereaderDotCode();
char *exts[] = { ".raw;*.bin", ".*" };
//getHandle()
FileDlg file(0, //Get the proper handle somehow, and put it here.
"",
"E-Reader dot code (*.bin, *.raw)|*.bin;*.raw|All Files (*.*)|*.*||",
0,
"RAW",
(LPCTSTR *)exts,
NULL,
"Load Nintendo E-Reader Dotcode",
FALSE);
if (file.DoModal() == IDOK)
{
theApp.loadDotCodeFile = file.GetPathName();
SetLoadDotCodeFile(theApp.loadDotCodeFile);
}
}
void MainWnd::OnFileSaveDotCode()
{
char *exts[] = { ".raw", ".*" };
//getHandle()
FileDlg file(0, //Get the proper handle somehow, and put it here.
"",
"E-Reader dot code (*.raw)|*.raw|All Files (*.*)|*.*||",
0,
"RAW",
(LPCTSTR *)exts,
NULL,
"Save Nintendo E-Reader Dotcode",
TRUE);
if (file.DoModal() == IDOK)
{
theApp.saveDotCodeFile = file.GetPathName();
SetLoadDotCodeFile(theApp.saveDotCodeFile);
}
}
void MainWnd::OnPaint()
{

View File

@ -68,6 +68,8 @@ protected:
afx_msg void OnFileOpenGBA();
afx_msg void OnFileOpenGBC();
afx_msg void OnFileOpenGB();
afx_msg void OnFileLoadDotCode();
afx_msg void OnFileSaveDotCode();
afx_msg void OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu);
afx_msg void OnFilePause();
afx_msg void OnUpdateFilePause(CCmdUI* pCmdUI);
@ -172,6 +174,8 @@ protected:
afx_msg void OnUpdateOptionsEmulatorAutomaticallyipspatch(CCmdUI* pCmdUI);
afx_msg void OnOptionsEmulatorAgbprint();
afx_msg void OnUpdateOptionsEmulatorAgbprint(CCmdUI* pCmdUI);
afx_msg void OnOptionsEmulatorEreader();
afx_msg void OnUpdateOptionsEmulatorEreader(CCmdUI* pCmdUI);
afx_msg void OnOptionsEmulatorRealtimeclock();
afx_msg void OnUpdateOptionsEmulatorRealtimeclock(CCmdUI* pCmdUI);
afx_msg void OnOptionsEmulatorRewindinterval();

View File

@ -22,6 +22,7 @@
#include "../System.h"
#include "../gba/agbprint.h"
#include "../gba/ereader.h"
#include "../gba/GBA.h"
#include "../gba/Globals.h"
#include "../gba/Sound.h"
@ -633,6 +634,16 @@ void MainWnd::OnUpdateOptionsEmulatorAgbprint(CCmdUI* pCmdUI)
pCmdUI->SetCheck(agbPrintIsEnabled());
}
void MainWnd::OnOptionsEmulatorEreader()
{
eReaderSaveRAW = !eReaderSaveRAW;
}
void MainWnd::OnUpdateOptionsEmulatorEreader(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(eReaderSaveRAW == 1);
}
void MainWnd::OnOptionsEmulatorRealtimeclock()
{
theApp.winRtcEnable = !theApp.winRtcEnable;

View File

@ -25,6 +25,7 @@
#include "../System.h"
#include "../gba/agbprint.h"
#include "../gba/ereader.h"
#include "../gba/cheatSearch.h"
#include "../gba/GBA.h"
#include "../gba/Globals.h"
@ -1413,6 +1414,10 @@ void VBA::loadSettings()
{
CString buffer;
eReaderSaveRAW = regQueryDwordValue("eReaderSaveRAW", 1);
if (eReaderSaveRAW < 0 || eReaderSaveRAW > 1)
eReaderSaveRAW = 1;
lastFullscreen = (VIDEO_SIZE)regQueryDwordValue("lastFullscreen", VIDEO_1024x768);
languageOption = regQueryDwordValue("language", 1);
@ -2512,6 +2517,8 @@ void VBA::movieReadNext()
void VBA::saveSettings()
{
regSetDwordValue("eReaderSaveRAW", eReaderSaveRAW);
regSetDwordValue("language", languageOption);
regSetStringValue("languageName", languageName);

View File

@ -206,6 +206,9 @@ class VBA : public CWinApp
CString filename;
CString dir;
CString loadDotCodeFile;
CString saveDotCodeFile;
CString wndClass;
int linkTimeout;

View File

@ -1600,7 +1600,10 @@ BEGIN
MENUITEM "Open GBC...", ID_FILE_OPEN_GBC
MENUITEM "Open GB...", ID_FILE_OPEN_GB
MENUITEM "Close", ID_FILE_CLOSE
MENUITEM SEPARATOR
MENUITEM SEPARATOR
MENUITEM "Load E-Reader DotCode...", ID_FILE_LOAD_DOTCODE
MENUITEM "Save E-Reader DotCode...", ID_FILE_SAVE_DOTCODE
MENUITEM SEPARATOR
MENUITEM "&Link with...", ID_OPTIONS_LINK_OPTIONS
MENUITEM SEPARATOR
POPUP "Recent"
@ -1872,6 +1875,7 @@ BEGIN
MENUITEM "Auto-apply IPS/UPS/PPF", ID_OPTIONS_EMULATOR_AUTOMATICALLYAPPLYPATCHFILES
MENUITEM "Pause when inactive", ID_OPTIONS_EMULATOR_PAUSEWHENINACTIVE
MENUITEM "AGB Print", ID_OPTIONS_EMULATOR_AGBPRINT
MENUITEM "E-Reader", ID_OPTIONS_EMULATOR_EREADER
MENUITEM "Real Time Clock", ID_OPTIONS_EMULATOR_REALTIMECLOCK
MENUITEM "&Game Overrides...", ID_OPTIONS_EMULATOR_GAMEOVERRIDES
POPUP "Show speed"

View File

@ -779,6 +779,7 @@
#define ID_OPTIONS_VIDEO_RENDEROPTIONS_GLTRIANGLE 40239
#define ID_OPTIONS_VIDEO_RENDEROPTIONS_GLQUADS 40240
#define ID_OPTIONS_EMULATOR_AGBPRINT 40247
#define ID_OPTIONS_EMULATOR_EREADER 40280
#define ID_OPTIONS_EMULATOR_REALTIMECLOCK 40248
#define ID_OPTIONS_GAMEBOY_SGB2 40249
#define ID_SYSTEM_MINIMIZE 40250
@ -874,6 +875,8 @@
#define ID_AUDIO_CORE_SETTINGS 40365
#define ID_FILE_OPEN_GBA 40366
#define ID_OPTIONS_VIDEO_LAYERS_RESET 40367
#define ID_FILE_LOAD_DOTCODE 40368
#define ID_FILE_SAVE_DOTCODE 40369
#define ID_LOADGAME_DONOTCHANGECHEATLIST 40371
#define ID_OPTIONS_EMULATOR_SAVETYPE_DETECTNOW 40372
#define ID_FILE_PAUSE 40373