mirror of
https://github.com/sanni/cartreader.git
synced 2024-11-15 01:15:06 +01:00
GBA: Add option to dump F0088H0 repro
This commit is contained in:
parent
8cf9bc6a99
commit
d25b98ddfd
@ -18,7 +18,7 @@ boolean audioWE = 0;
|
|||||||
// GBx start menu
|
// GBx start menu
|
||||||
static const char gbxMenuItem1[] PROGMEM = "Game Boy (Color)";
|
static const char gbxMenuItem1[] PROGMEM = "Game Boy (Color)";
|
||||||
static const char gbxMenuItem2[] PROGMEM = "GB Advance (3V)";
|
static const char gbxMenuItem2[] PROGMEM = "GB Advance (3V)";
|
||||||
static const char gbxMenuItem3[] PROGMEM = "Flash GBC Cart";
|
static const char gbxMenuItem3[] PROGMEM = "Flash Repro";
|
||||||
static const char gbxMenuItem4[] PROGMEM = "NPower GB Memory";
|
static const char gbxMenuItem4[] PROGMEM = "NPower GB Memory";
|
||||||
static const char gbxMenuItem5[] PROGMEM = "Flash Codebreaker";
|
static const char gbxMenuItem5[] PROGMEM = "Flash Codebreaker";
|
||||||
static const char gbxMenuItem6[] PROGMEM = "Flash Datel Device";
|
static const char gbxMenuItem6[] PROGMEM = "Flash Datel Device";
|
||||||
@ -28,11 +28,13 @@ static const char* const menuOptionsGBx[] PROGMEM = { gbxMenuItem1, gbxMenuItem2
|
|||||||
static const char* const menuOptionsGB[] PROGMEM = { FSTRING_READ_ROM, FSTRING_READ_SAVE, FSTRING_WRITE_SAVE, FSTRING_RESET };
|
static const char* const menuOptionsGB[] PROGMEM = { FSTRING_READ_ROM, FSTRING_READ_SAVE, FSTRING_WRITE_SAVE, FSTRING_RESET };
|
||||||
|
|
||||||
// GB Flash items
|
// GB Flash items
|
||||||
static const char GBFlashItem1[] PROGMEM = "29F016/32/33 Cart";
|
static const char GBFlashItem1[] PROGMEM = "GB 29F Repro";
|
||||||
static const char GBFlashItem2[] PROGMEM = "CFI Cart";
|
static const char GBFlashItem2[] PROGMEM = "GB CFI Repro";
|
||||||
static const char GBFlashItem3[] PROGMEM = "CFI Cart and Save";
|
static const char GBFlashItem3[] PROGMEM = "GB CFI and Save";
|
||||||
static const char GBFlashItem4[] PROGMEM = "GB Smart";
|
static const char GBFlashItem4[] PROGMEM = "GB Smart";
|
||||||
static const char* const menuOptionsGBFlash[] PROGMEM = { GBFlashItem1, GBFlashItem2, GBFlashItem3, GBFlashItem4, FSTRING_RESET };
|
static const char GBFlashItem5[] PROGMEM = "GBA Repro (3V)";
|
||||||
|
static const char GBFlashItem6[] PROGMEM = "GBA 369-in-1 (3V)";
|
||||||
|
static const char* const menuOptionsGBFlash[] PROGMEM = { GBFlashItem1, GBFlashItem2, GBFlashItem3, GBFlashItem4, GBFlashItem5, GBFlashItem6, FSTRING_RESET };
|
||||||
|
|
||||||
// 29F Flash items
|
// 29F Flash items
|
||||||
static const char GBFlash29Item1[] PROGMEM = "DIY MBC3 (WR)";
|
static const char GBFlash29Item1[] PROGMEM = "DIY MBC3 (WR)";
|
||||||
@ -112,11 +114,11 @@ void gbxMenu() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
// create submenu with title and 5 options to choose from
|
// create submenu with title and 7 options to choose from
|
||||||
unsigned char gbFlash;
|
unsigned char gbFlash;
|
||||||
// Copy menuOptions out of progmem
|
// Copy menuOptions out of progmem
|
||||||
convertPgm(menuOptionsGBFlash, 5);
|
convertPgm(menuOptionsGBFlash, 7);
|
||||||
gbFlash = question_box(F("Select type"), menuOptions, 5, 0);
|
gbFlash = question_box(F("Select type"), menuOptions, 7, 0);
|
||||||
|
|
||||||
// wait for user choice to come back from the question box menu
|
// wait for user choice to come back from the question box menu
|
||||||
switch (gbFlash) {
|
switch (gbFlash) {
|
||||||
@ -298,6 +300,16 @@ void gbxMenu() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
|
// Flash GBA Repro
|
||||||
|
GBAReproMenu();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
// Read/Write GBA 369-in-1 Repro
|
||||||
|
repro369in1Menu();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
resetArduino();
|
resetArduino();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,14 @@
|
|||||||
*****************************************/
|
*****************************************/
|
||||||
// GBA menu items
|
// GBA menu items
|
||||||
static const char GBAMenuItem4[] PROGMEM = "Force Savetype";
|
static const char GBAMenuItem4[] PROGMEM = "Force Savetype";
|
||||||
static const char GBAMenuItem5[] PROGMEM = "Flash Repro";
|
static const char* const menuOptionsGBA[] PROGMEM = { FSTRING_READ_ROM, FSTRING_READ_SAVE, FSTRING_WRITE_SAVE, GBAMenuItem4, FSTRING_RESET };
|
||||||
static const char* const menuOptionsGBA[] PROGMEM = { FSTRING_READ_ROM, FSTRING_READ_SAVE, FSTRING_WRITE_SAVE, GBAMenuItem4, GBAMenuItem5, FSTRING_RESET };
|
|
||||||
|
// 369-in-1 menu items
|
||||||
|
static const char Menu369Item1[] PROGMEM = "Read 256MB";
|
||||||
|
static const char Menu369Item2[] PROGMEM = "Write 256MB";
|
||||||
|
static const char Menu369Item3[] PROGMEM = "Read Offset";
|
||||||
|
static const char Menu369Item4[] PROGMEM = "Write Offset";
|
||||||
|
static const char* const Options369GBA[] PROGMEM = { Menu369Item1, Menu369Item2, Menu369Item3, Menu369Item4, FSTRING_RESET };
|
||||||
|
|
||||||
// Rom menu
|
// Rom menu
|
||||||
static const char GBARomItem1[] PROGMEM = "1 MB";
|
static const char GBARomItem1[] PROGMEM = "1 MB";
|
||||||
@ -30,11 +36,11 @@ static const char GBASaveItem6[] PROGMEM = "1M FLASH";
|
|||||||
static const char* const saveOptionsGBA[] PROGMEM = { GBASaveItem1, GBASaveItem2, GBASaveItem3, GBASaveItem4, GBASaveItem5, GBASaveItem6 };
|
static const char* const saveOptionsGBA[] PROGMEM = { GBASaveItem1, GBASaveItem2, GBASaveItem3, GBASaveItem4, GBASaveItem5, GBASaveItem6 };
|
||||||
|
|
||||||
void gbaMenu() {
|
void gbaMenu() {
|
||||||
// create menu with title and 4 options to choose from
|
// create menu with title and 5 options to choose from
|
||||||
unsigned char mainMenu;
|
unsigned char mainMenu;
|
||||||
// Copy menuOptions out of progmem
|
// Copy menuOptions out of progmem
|
||||||
convertPgm(menuOptionsGBA, 6);
|
convertPgm(menuOptionsGBA, 5);
|
||||||
mainMenu = question_box(F("GBA Cart Reader"), menuOptions, 6, 0);
|
mainMenu = question_box(F("GBA Cart Reader"), menuOptions, 5, 0);
|
||||||
|
|
||||||
// wait for user choice to come back from the question box menu
|
// wait for user choice to come back from the question box menu
|
||||||
switch (mainMenu) {
|
switch (mainMenu) {
|
||||||
@ -222,20 +228,79 @@ void gbaMenu() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
display_Clear();
|
resetArduino();
|
||||||
flashRepro_GBA();
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flash GBA Repro
|
||||||
|
void GBAReproMenu() {
|
||||||
|
setup_GBA_Repro();
|
||||||
|
|
||||||
|
flashRepro_GBA(0);
|
||||||
println_Msg(FS(FSTRING_EMPTY));
|
println_Msg(FS(FSTRING_EMPTY));
|
||||||
// Prints string out of the common strings array either with or without newline
|
// Prints string out of the common strings array either with or without newline
|
||||||
print_STR(press_button_STR, 1);
|
print_STR(press_button_STR, 1);
|
||||||
display_Update();
|
display_Update();
|
||||||
wait();
|
wait();
|
||||||
resetArduino();
|
resetArduino();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read/Write GBA 369-in-1 Repro
|
||||||
|
void repro369in1Menu() {
|
||||||
|
setup_GBA_Repro();
|
||||||
|
|
||||||
|
println_Msg(F("WARNING!!!"));
|
||||||
|
println_Msg(FS(FSTRING_EMPTY));
|
||||||
|
println_Msg(F("This will overwrite SRAM"));
|
||||||
|
println_Msg(FS(FSTRING_EMPTY));
|
||||||
|
println_Msg(F("(Ignore if no battery)"));
|
||||||
|
println_Msg(FS(FSTRING_EMPTY));
|
||||||
|
print_STR(press_button_STR, 1);
|
||||||
|
display_Update();
|
||||||
|
wait();
|
||||||
|
|
||||||
|
// create menu with title and 5 options to choose from
|
||||||
|
unsigned char menu369;
|
||||||
|
// Copy menuOptions out of progmem
|
||||||
|
convertPgm(Options369GBA, 2);
|
||||||
|
menu369 = question_box(F("369-in-1 Multicart"), menuOptions, 2, 0);
|
||||||
|
|
||||||
|
// wait for user choice to come back from the question box menu
|
||||||
|
switch (menu369) {
|
||||||
|
case 0:
|
||||||
|
display_Clear();
|
||||||
|
sd.chdir("/");
|
||||||
|
read369in1(0, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 1:
|
||||||
|
display_Clear();
|
||||||
|
sd.chdir("/");
|
||||||
|
flashRepro_GBA(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
display_Clear();
|
||||||
|
sd.chdir("/");
|
||||||
|
read369in1(selectBlockNumber(1), selectBlockNumber(0));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
display_Clear();
|
||||||
|
sd.chdir("/");
|
||||||
|
flashRepro_GBA(1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
resetArduino();
|
resetArduino();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
println_Msg(FS(FSTRING_EMPTY));
|
||||||
|
print_STR(press_button_STR, 1);
|
||||||
|
display_Update();
|
||||||
|
wait();
|
||||||
|
resetArduino();
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
@ -302,6 +367,13 @@ void setup_GBA() {
|
|||||||
wait();
|
wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setup_GBA_Repro() {
|
||||||
|
// Request 3.3V
|
||||||
|
setVoltage(VOLTS_SET_3V3);
|
||||||
|
setROM_GBA();
|
||||||
|
display_Clear();
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
Low level functions
|
Low level functions
|
||||||
*****************************************/
|
*****************************************/
|
||||||
@ -1940,10 +2012,6 @@ void resetIntel_GBA(unsigned long partitionSize) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetF0088H0_GBA() {
|
|
||||||
writeWord_GBA(0, 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
void resetMX29GL128E_GBA() {
|
void resetMX29GL128E_GBA() {
|
||||||
writeWord_GAB(0, 0xF0);
|
writeWord_GAB(0, 0xF0);
|
||||||
}
|
}
|
||||||
@ -2206,40 +2274,6 @@ void eraseIntel4400_GBA() {
|
|||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void eraseF0088H0_GBA() {
|
|
||||||
//Initialize progress bar
|
|
||||||
uint32_t processedProgressBar = 0;
|
|
||||||
uint32_t totalProgressBar = (uint32_t)fileSize;
|
|
||||||
draw_progressbar(0, totalProgressBar);
|
|
||||||
|
|
||||||
// 4MB repro block size
|
|
||||||
for (unsigned long currBlock = 0; currBlock < fileSize; currBlock += 0x400000) {
|
|
||||||
mapBlockF0088H0_GBA(currBlock / 1024 / 1024);
|
|
||||||
|
|
||||||
// 256KB flashrom sector size
|
|
||||||
for (unsigned long currSector = 0; currSector < 0x400000; currSector += 0x40000) {
|
|
||||||
// Unlock Sector
|
|
||||||
writeWord_GBA(currBlock + currSector, 0x60);
|
|
||||||
writeWord_GBA(currBlock + currSector, 0xD0);
|
|
||||||
|
|
||||||
// Erase Command
|
|
||||||
writeWord_GBA(currBlock + currSector, 0x20);
|
|
||||||
writeWord_GBA(currBlock + currSector, 0xD0);
|
|
||||||
|
|
||||||
// Read the status register
|
|
||||||
word statusReg = readWord_GBA(currBlock + currSector);
|
|
||||||
while ((statusReg | 0xFF7F) != 0xFFFF) {
|
|
||||||
statusReg = readWord_GBA(currBlock + currSector);
|
|
||||||
}
|
|
||||||
// Blink led
|
|
||||||
blinkLED();
|
|
||||||
}
|
|
||||||
// update progress bar
|
|
||||||
processedProgressBar += 0x400000;
|
|
||||||
draw_progressbar(processedProgressBar, totalProgressBar);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void sectorEraseMSP55LV128_GBA() {
|
void sectorEraseMSP55LV128_GBA() {
|
||||||
unsigned long lastSector = 0xFFFFFF;
|
unsigned long lastSector = 0xFFFFFF;
|
||||||
|
|
||||||
@ -2334,91 +2368,6 @@ void writeIntel4000_GBA() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mapBlockF0088H0_GBA(u32 offset) {
|
|
||||||
// Taken from gbabf
|
|
||||||
u32 chipAddr = (offset / 32 * 0x10000000) + (0x4000C0 + (offset & 31) * 0x20202);
|
|
||||||
union {
|
|
||||||
u32 addr;
|
|
||||||
u8 byte[4];
|
|
||||||
} addr;
|
|
||||||
addr.addr = chipAddr;
|
|
||||||
|
|
||||||
writeByte_GBA(0x2, addr.byte[3]);
|
|
||||||
writeByte_GBA(0x3, addr.byte[2]);
|
|
||||||
writeByte_GBA(0x4, addr.byte[1]);
|
|
||||||
delay(100);
|
|
||||||
setROM_GBA();
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeF0088H0_GBA() {
|
|
||||||
byte writeBuffer[1024];
|
|
||||||
|
|
||||||
//Initialize progress bar
|
|
||||||
uint32_t processedProgressBar = 0;
|
|
||||||
uint32_t totalProgressBar = fileSize;
|
|
||||||
draw_progressbar(0, totalProgressBar);
|
|
||||||
|
|
||||||
unsigned long lastBlock = 0x2000000;
|
|
||||||
if (fileSize < lastBlock)
|
|
||||||
lastBlock = fileSize;
|
|
||||||
|
|
||||||
// 32MB max GBA bank size
|
|
||||||
for (unsigned long currBank = 0; currBank < fileSize; currBank += 0x2000000) {
|
|
||||||
|
|
||||||
// 4MB minimum repro block size
|
|
||||||
for (unsigned long currBlock = 0; currBlock < lastBlock; currBlock += 0x400000) {
|
|
||||||
// Set-up 369-in-1 mapper
|
|
||||||
mapBlockF0088H0_GBA((currBank + currBlock) / 1024 / 1024);
|
|
||||||
|
|
||||||
// 256KB flashrom sector size
|
|
||||||
for (unsigned long currSector = 0; currSector < 0x400000; currSector += 0x40000) {
|
|
||||||
// Unlock Sector
|
|
||||||
//writeWord_GBA(currBlock + currSector, 0x60);
|
|
||||||
//writeWord_GBA(currBlock + currSector, 0xD0);
|
|
||||||
|
|
||||||
// Blink led
|
|
||||||
blinkLED();
|
|
||||||
|
|
||||||
// 1024B writeBuffer
|
|
||||||
for (unsigned long currWriteBuffer = 0; currWriteBuffer < 0x40000; currWriteBuffer += 1024) {
|
|
||||||
// Fill writeBuffer from SD card
|
|
||||||
myFile.read(writeBuffer, 1024);
|
|
||||||
|
|
||||||
// Buffered program command
|
|
||||||
writeWord_GBA(currBlock + currSector + currWriteBuffer, 0xEA);
|
|
||||||
|
|
||||||
// Check Status register
|
|
||||||
word statusReg = readWord_GBA(currBlock + currSector + currWriteBuffer);
|
|
||||||
while ((statusReg | 0xFF7F) != 0xFFFF) {
|
|
||||||
statusReg = readWord_GBA(currBlock + currSector + currWriteBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write word count (minus 1)
|
|
||||||
writeWord_GBA(currBlock + currSector + currWriteBuffer, 0x1FF);
|
|
||||||
|
|
||||||
// Send writeBuffer to flashrom
|
|
||||||
for (word currByte = 0; currByte < 1024; currByte += 2) {
|
|
||||||
// Join two bytes into one word
|
|
||||||
word currWord = ((writeBuffer[currByte + 1] & 0xFF) << 8) | (writeBuffer[currByte] & 0xFF);
|
|
||||||
writeWord_GBA(currBlock + currSector + currWriteBuffer + currByte, currWord);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write buffer to flash
|
|
||||||
writeWord_GBA(currBlock + currSector + currWriteBuffer + 1022, 0xD0);
|
|
||||||
|
|
||||||
// Read the status register at last written address
|
|
||||||
statusReg = readWord_GBA(currBlock + currSector + currWriteBuffer + 1022);
|
|
||||||
while ((statusReg | 0xFF7F) != 0xFFFF) {
|
|
||||||
statusReg = readWord_GBA(currBlock + currSector + currWriteBuffer + 1022);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
processedProgressBar += 0x40000;
|
|
||||||
draw_progressbar(processedProgressBar, totalProgressBar);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeMSP55LV128_GBA() {
|
void writeMSP55LV128_GBA() {
|
||||||
for (unsigned long currSector = 0; currSector < fileSize; currSector += 0x10000) {
|
for (unsigned long currSector = 0; currSector < fileSize; currSector += 0x10000) {
|
||||||
// Blink led
|
// Blink led
|
||||||
@ -2541,7 +2490,231 @@ boolean verifyFlashrom_GBA() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void flashRepro_GBA() {
|
//******************************************
|
||||||
|
// 369in1 Repro functions
|
||||||
|
//******************************************
|
||||||
|
void reset369in1() {
|
||||||
|
writeWord_GBA(0, 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mapBlock369in1(u32 offset) {
|
||||||
|
// Taken from gbabf
|
||||||
|
u32 chipAddr = (offset / 32 * 0x10000000) + (0x4000C0 + (offset & 31) * 0x20202);
|
||||||
|
union {
|
||||||
|
u32 addr;
|
||||||
|
u8 byte[4];
|
||||||
|
} addr;
|
||||||
|
addr.addr = chipAddr;
|
||||||
|
|
||||||
|
writeByte_GBA(0x2, addr.byte[3]);
|
||||||
|
writeByte_GBA(0x3, addr.byte[2]);
|
||||||
|
writeByte_GBA(0x4, addr.byte[1]);
|
||||||
|
delay(100);
|
||||||
|
setROM_GBA();
|
||||||
|
}
|
||||||
|
|
||||||
|
void printblockNumber(int index) {
|
||||||
|
display_Clear();
|
||||||
|
print_Msg(F("Block Number: "));
|
||||||
|
println_Msg(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printFileSize(int index) {
|
||||||
|
display_Clear();
|
||||||
|
print_Msg(F("Filesize: "));
|
||||||
|
print_Msg(index);
|
||||||
|
println_Msg(F("MB"));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte selectBlockNumber(boolean option) {
|
||||||
|
byte blockNumber;
|
||||||
|
if (option)
|
||||||
|
blockNumber = navigateMenu(0, 63, &printblockNumber);
|
||||||
|
else
|
||||||
|
blockNumber = navigateMenu(0, 32, &printFileSize);
|
||||||
|
display.setCursor(0, 56); // Display selection at bottom
|
||||||
|
if (option) {
|
||||||
|
print_Msg(F("Block Number: "));
|
||||||
|
println_Msg(blockNumber);
|
||||||
|
} else {
|
||||||
|
print_Msg(F("Filesize: "));
|
||||||
|
print_Msg(blockNumber);
|
||||||
|
println_Msg(F("MB"));
|
||||||
|
}
|
||||||
|
display_Update();
|
||||||
|
delay(500);
|
||||||
|
return blockNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read 369-in-1 repro
|
||||||
|
void read369in1(byte blockNumber, unsigned long fileSize) {
|
||||||
|
byte readBuffer[1024];
|
||||||
|
strcpy(romName, "369in1");
|
||||||
|
|
||||||
|
if (blockNumber != 0) {
|
||||||
|
char ext[4];
|
||||||
|
sprintf(ext, "B%d", blockNumber);
|
||||||
|
createFolderAndOpenFile("GBA", "ROM", romName, ext);
|
||||||
|
} else
|
||||||
|
createFolderAndOpenFile("GBA", "ROM", romName, "gba");
|
||||||
|
|
||||||
|
if (fileSize == 0)
|
||||||
|
fileSize = 0x10000000;
|
||||||
|
else
|
||||||
|
fileSize = fileSize * 1024 * 1024;
|
||||||
|
|
||||||
|
// 64 blocks at 4MB each
|
||||||
|
unsigned long startBank = (((unsigned long)blockNumber * 4) / 32) * 0x2000000;
|
||||||
|
unsigned long startBlock = ((unsigned long)blockNumber * 4 * 1024 * 1024) - startBank;
|
||||||
|
|
||||||
|
//Initialize progress bar
|
||||||
|
uint32_t processedProgressBar = 0;
|
||||||
|
uint32_t totalProgressBar = fileSize;
|
||||||
|
draw_progressbar(0, totalProgressBar);
|
||||||
|
|
||||||
|
// 256MB repro size
|
||||||
|
for (unsigned long currBank = startBank; currBank < startBank + fileSize; currBank += 0x2000000) {
|
||||||
|
// 32MB bank
|
||||||
|
for (unsigned long currBlock = startBlock; currBlock < 0x2000000; currBlock += 0x400000) {
|
||||||
|
// Set-up 369-in-1 mapper
|
||||||
|
mapBlock369in1((currBank + currBlock) / 1024 / 1024);
|
||||||
|
// 4MB Block
|
||||||
|
for (unsigned long currBuffer = 0; currBuffer < 0x400000; currBuffer += 1024) {
|
||||||
|
// 1024 byte readBuffer
|
||||||
|
for (int currWord = 0; currWord < 1024; currWord += 2) {
|
||||||
|
word tempWord = readWord_GBA(currBlock + currBuffer + currWord);
|
||||||
|
readBuffer[currWord] = tempWord & 0xFF;
|
||||||
|
readBuffer[currWord + 1] = (tempWord >> 8) & 0xFF;
|
||||||
|
}
|
||||||
|
// Write to SD
|
||||||
|
myFile.write(readBuffer, 1024);
|
||||||
|
}
|
||||||
|
processedProgressBar += 0x400000;
|
||||||
|
draw_progressbar(processedProgressBar, totalProgressBar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Close the file:
|
||||||
|
myFile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Erase 369-in-1 repro
|
||||||
|
void erase369in1(byte blockNumber) {
|
||||||
|
// 64 blocks at 4MB each
|
||||||
|
unsigned long startBank = (((unsigned long)blockNumber * 4) / 32) * 0x2000000;
|
||||||
|
unsigned long startBlock = ((unsigned long)blockNumber * 4 * 1024 * 1024) - startBank;
|
||||||
|
|
||||||
|
//Initialize progress bar
|
||||||
|
uint32_t processedProgressBar = 0;
|
||||||
|
uint32_t totalProgressBar = (uint32_t)fileSize;
|
||||||
|
draw_progressbar(0, totalProgressBar);
|
||||||
|
|
||||||
|
// 256MB repro size
|
||||||
|
for (unsigned long currBank = startBank; currBank < startBank + fileSize; currBank += 0x2000000) {
|
||||||
|
// 32MB bank
|
||||||
|
for (unsigned long currBlock = startBlock; currBlock < 0x2000000; currBlock += 0x400000) {
|
||||||
|
// Set-up 369-in-1 mapper
|
||||||
|
mapBlock369in1((currBank + currBlock) / 1024 / 1024);
|
||||||
|
// 256KB flashrom sector size
|
||||||
|
for (unsigned long currSector = 0; currSector < 0x400000; currSector += 0x40000) {
|
||||||
|
// Unlock Sector
|
||||||
|
writeWord_GBA(currBlock + currSector, 0x60);
|
||||||
|
writeWord_GBA(currBlock + currSector, 0xD0);
|
||||||
|
|
||||||
|
// Erase Command
|
||||||
|
writeWord_GBA(currBlock + currSector, 0x20);
|
||||||
|
writeWord_GBA(currBlock + currSector, 0xD0);
|
||||||
|
|
||||||
|
// Read the status register
|
||||||
|
word statusReg = readWord_GBA(currBlock + currSector);
|
||||||
|
while ((statusReg | 0xFF7F) != 0xFFFF) {
|
||||||
|
statusReg = readWord_GBA(currBlock + currSector);
|
||||||
|
}
|
||||||
|
// Blink led
|
||||||
|
blinkLED();
|
||||||
|
// update progress bar
|
||||||
|
processedProgressBar += 0x40000;
|
||||||
|
draw_progressbar(processedProgressBar, totalProgressBar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void write369in1(byte blockNumber) {
|
||||||
|
byte writeBuffer[1024];
|
||||||
|
|
||||||
|
// 64 blocks at 4MB each
|
||||||
|
unsigned long startBank = (((unsigned long)blockNumber * 4) / 32) * 0x2000000;
|
||||||
|
unsigned long startBlock = ((unsigned long)blockNumber * 4 * 1024 * 1024) - startBank;
|
||||||
|
unsigned long lastBlock = 0x2000000;
|
||||||
|
if (fileSize < lastBlock)
|
||||||
|
lastBlock = fileSize;
|
||||||
|
|
||||||
|
//Initialize progress bar
|
||||||
|
uint32_t processedProgressBar = 0;
|
||||||
|
uint32_t totalProgressBar = fileSize;
|
||||||
|
draw_progressbar(0, totalProgressBar);
|
||||||
|
|
||||||
|
// 32MB max GBA bank size
|
||||||
|
for (unsigned long currBank = startBank; currBank < startBank + fileSize; currBank += 0x2000000) {
|
||||||
|
|
||||||
|
// 4MB minimum repro block size
|
||||||
|
for (unsigned long currBlock = startBlock; currBlock < lastBlock; currBlock += 0x400000) {
|
||||||
|
// Set-up 369-in-1 mapper
|
||||||
|
mapBlock369in1((currBank + currBlock) / 1024 / 1024);
|
||||||
|
|
||||||
|
// 256KB flashrom sector size
|
||||||
|
for (unsigned long currSector = 0; currSector < 0x400000; currSector += 0x40000) {
|
||||||
|
// Unlock Sector
|
||||||
|
//writeWord_GBA(currBlock + currSector, 0x60);
|
||||||
|
//writeWord_GBA(currBlock + currSector, 0xD0);
|
||||||
|
|
||||||
|
// Blink led
|
||||||
|
blinkLED();
|
||||||
|
|
||||||
|
// 1024B writeBuffer
|
||||||
|
for (unsigned long currWriteBuffer = 0; currWriteBuffer < 0x40000; currWriteBuffer += 1024) {
|
||||||
|
// Fill writeBuffer from SD card
|
||||||
|
myFile.read(writeBuffer, 1024);
|
||||||
|
|
||||||
|
// Buffered program command
|
||||||
|
writeWord_GBA(currBlock + currSector + currWriteBuffer, 0xEA);
|
||||||
|
|
||||||
|
// Check Status register
|
||||||
|
word statusReg = readWord_GBA(currBlock + currSector + currWriteBuffer);
|
||||||
|
while ((statusReg | 0xFF7F) != 0xFFFF) {
|
||||||
|
statusReg = readWord_GBA(currBlock + currSector + currWriteBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write word count (minus 1)
|
||||||
|
writeWord_GBA(currBlock + currSector + currWriteBuffer, 0x1FF);
|
||||||
|
|
||||||
|
// Send writeBuffer to flashrom
|
||||||
|
for (word currByte = 0; currByte < 1024; currByte += 2) {
|
||||||
|
// Join two bytes into one word
|
||||||
|
word currWord = ((writeBuffer[currByte + 1] & 0xFF) << 8) | (writeBuffer[currByte] & 0xFF);
|
||||||
|
writeWord_GBA(currBlock + currSector + currWriteBuffer + currByte, currWord);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write buffer to flash
|
||||||
|
writeWord_GBA(currBlock + currSector + currWriteBuffer + 1022, 0xD0);
|
||||||
|
|
||||||
|
// Read the status register at last written address
|
||||||
|
statusReg = readWord_GBA(currBlock + currSector + currWriteBuffer + 1022);
|
||||||
|
while ((statusReg | 0xFF7F) != 0xFFFF) {
|
||||||
|
statusReg = readWord_GBA(currBlock + currSector + currWriteBuffer + 1022);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
processedProgressBar += 0x40000;
|
||||||
|
draw_progressbar(processedProgressBar, totalProgressBar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//******************************************
|
||||||
|
// Flash Repro function
|
||||||
|
//******************************************
|
||||||
|
void flashRepro_GBA(boolean option) {
|
||||||
// Check flashrom ID's
|
// Check flashrom ID's
|
||||||
idFlashrom_GBA();
|
idFlashrom_GBA();
|
||||||
|
|
||||||
@ -2623,9 +2796,12 @@ void flashRepro_GBA() {
|
|||||||
} else if (flashid == 0x8812) {
|
} else if (flashid == 0x8812) {
|
||||||
println_Msg(F("Erasing..."));
|
println_Msg(F("Erasing..."));
|
||||||
display_Update();
|
display_Update();
|
||||||
eraseF0088H0_GBA();
|
if (option)
|
||||||
|
erase369in1(selectBlockNumber(1));
|
||||||
|
else
|
||||||
|
erase369in1(0);
|
||||||
// Reset or blankcheck will fail
|
// Reset or blankcheck will fail
|
||||||
resetF0088H0_GBA();
|
reset369in1();
|
||||||
} else if (flashid == 0x227E) {
|
} else if (flashid == 0x227E) {
|
||||||
//if (sectorCheckMX29GL128E_GBA()) {
|
//if (sectorCheckMX29GL128E_GBA()) {
|
||||||
//print_FatalError(F("Sector Protected"));
|
//print_FatalError(F("Sector Protected"));
|
||||||
@ -2656,7 +2832,12 @@ void flashRepro_GBA() {
|
|||||||
if ((flashid == 0x8802) || (flashid == 0x8816)) {
|
if ((flashid == 0x8802) || (flashid == 0x8816)) {
|
||||||
writeIntel4000_GBA();
|
writeIntel4000_GBA();
|
||||||
} else if (flashid == 0x8812) {
|
} else if (flashid == 0x8812) {
|
||||||
writeF0088H0_GBA();
|
if (option) {
|
||||||
|
write369in1(selectBlockNumber(1));
|
||||||
|
} else {
|
||||||
|
write369in1(0);
|
||||||
|
reset369in1();
|
||||||
|
}
|
||||||
} else if (flashid == 0x227E) {
|
} else if (flashid == 0x227E) {
|
||||||
if ((romType == 0xC2) || (romType == 0x89) || (romType == 0x20)) {
|
if ((romType == 0xC2) || (romType == 0x89) || (romType == 0x20)) {
|
||||||
//MX29GL128E (0xC2)
|
//MX29GL128E (0xC2)
|
||||||
@ -2686,7 +2867,7 @@ void flashRepro_GBA() {
|
|||||||
resetIntel_GBA(0x200000);
|
resetIntel_GBA(0x200000);
|
||||||
delay(1000);
|
delay(1000);
|
||||||
} else if (flashid == 0x8812) {
|
} else if (flashid == 0x8812) {
|
||||||
resetF0088H0_GBA();
|
reset369in1();
|
||||||
delay(1000);
|
delay(1000);
|
||||||
} else if (flashid == 0x227E) {
|
} else if (flashid == 0x227E) {
|
||||||
resetMX29GL128E_GBA();
|
resetMX29GL128E_GBA();
|
||||||
|
Loading…
Reference in New Issue
Block a user