mirror of
https://github.com/sanni/cartreader.git
synced 2024-11-27 23:14:14 +01:00
V33: Add PCE support by tamanegi_taro
Many thanks to tamanegi_taro, great work.
This commit is contained in:
parent
f72f44124d
commit
b77519d104
@ -2,8 +2,8 @@
|
|||||||
Cartridge Reader for Arduino Mega2560
|
Cartridge Reader for Arduino Mega2560
|
||||||
|
|
||||||
Author: sanni
|
Author: sanni
|
||||||
Date: 2018-05-04
|
Date: 04-18-2018
|
||||||
Version: V32A
|
Version: V33
|
||||||
|
|
||||||
SD lib: https://github.com/greiman/SdFat
|
SD lib: https://github.com/greiman/SdFat
|
||||||
LCD lib: https://github.com/adafruit/Adafruit_SSD1306
|
LCD lib: https://github.com/adafruit/Adafruit_SSD1306
|
||||||
@ -25,7 +25,7 @@
|
|||||||
bryc - mempak
|
bryc - mempak
|
||||||
Shaun Taylor - N64 controller CRC functions
|
Shaun Taylor - N64 controller CRC functions
|
||||||
Angus Gratton - CRC32
|
Angus Gratton - CRC32
|
||||||
Tamanegi_taro - SA1 fix
|
Tamanegi_taro - SA1 fix and PCE support
|
||||||
Snes9x - SuperFX sram fix
|
Snes9x - SuperFX sram fix
|
||||||
zzattack - multigame pcb fix
|
zzattack - multigame pcb fix
|
||||||
Pickle - SDD1 fix
|
Pickle - SDD1 fix
|
||||||
@ -35,7 +35,7 @@
|
|||||||
infinest - help with GB Memory cart
|
infinest - help with GB Memory cart
|
||||||
|
|
||||||
**********************************************************************************/
|
**********************************************************************************/
|
||||||
char ver[5] = "V32A";
|
char ver[5] = "V33";
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
Define Starting Point
|
Define Starting Point
|
||||||
@ -135,6 +135,7 @@ SdFile myFile;
|
|||||||
#define mode_GBM 10
|
#define mode_GBM 10
|
||||||
#define mode_MD 11
|
#define mode_MD 11
|
||||||
#define mode_EPROM 12
|
#define mode_EPROM 12
|
||||||
|
#define mode_PCE 13
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
Variables
|
Variables
|
||||||
@ -327,6 +328,10 @@ static const unsigned char PROGMEM sig [] = {
|
|||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//For PC Engine
|
||||||
|
extern void pcsMenu(void);
|
||||||
|
extern void pceMenu(void);
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
Menu
|
Menu
|
||||||
*****************************************/
|
*****************************************/
|
||||||
@ -336,8 +341,9 @@ static const char modeItem2[] PROGMEM = "Super Nintendo";
|
|||||||
static const char modeItem3[] PROGMEM = "Game Boy";
|
static const char modeItem3[] PROGMEM = "Game Boy";
|
||||||
static const char modeItem4[] PROGMEM = "Mega Drive";
|
static const char modeItem4[] PROGMEM = "Mega Drive";
|
||||||
static const char modeItem5[] PROGMEM = "Flashrom Programmer";
|
static const char modeItem5[] PROGMEM = "Flashrom Programmer";
|
||||||
static const char modeItem6[] PROGMEM = "About";
|
static const char modeItem6[] PROGMEM = "PC Engine/TG16";
|
||||||
static const char* const modeOptions[] PROGMEM = {modeItem1, modeItem2, modeItem3, modeItem4, modeItem5, modeItem6};
|
static const char modeItem7[] PROGMEM = "About";
|
||||||
|
static const char* const modeOptions[] PROGMEM = {modeItem1, modeItem2, modeItem3, modeItem4, modeItem5, modeItem6, modeItem7};
|
||||||
|
|
||||||
void aboutScreen() {
|
void aboutScreen() {
|
||||||
display_Clear();
|
display_Clear();
|
||||||
@ -393,8 +399,8 @@ void mainMenu() {
|
|||||||
// create menu with title and 6 options to choose from
|
// create menu with title and 6 options to choose from
|
||||||
unsigned char modeMenu;
|
unsigned char modeMenu;
|
||||||
// Copy menuOptions out of progmem
|
// Copy menuOptions out of progmem
|
||||||
convertPgm(modeOptions, 6);
|
convertPgm(modeOptions, 7);
|
||||||
modeMenu = question_box("Cartridge Reader", menuOptions, 6, 0);
|
modeMenu = question_box("Cartridge Reader", 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 (modeMenu)
|
switch (modeMenu)
|
||||||
@ -418,8 +424,10 @@ void mainMenu() {
|
|||||||
case 4:
|
case 4:
|
||||||
flashMenu();
|
flashMenu();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
|
pcsMenu();
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
aboutScreen();
|
aboutScreen();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1311,6 +1319,9 @@ void loop() {
|
|||||||
else if (mode == mode_MD) {
|
else if (mode == mode_MD) {
|
||||||
mdMenu();
|
mdMenu();
|
||||||
}
|
}
|
||||||
|
else if (mode == mode_PCE) {
|
||||||
|
pceMenu();
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
display_Clear();
|
display_Clear();
|
||||||
println_Msg(F("Menu Error"));
|
println_Msg(F("Menu Error"));
|
||||||
|
710
Cart_Reader/PCE.ino
Normal file
710
Cart_Reader/PCE.ino
Normal file
@ -0,0 +1,710 @@
|
|||||||
|
//******************************************
|
||||||
|
// PC Engine & TurboGrafx dump code by tamanegi_taro
|
||||||
|
// Revision 1.0.1 April 18th 2018
|
||||||
|
//
|
||||||
|
// Special thanks
|
||||||
|
// sanni - Arduino cart reader
|
||||||
|
// skaman - ROM size detection
|
||||||
|
// NO-INTRO - CRC list for game name detection
|
||||||
|
//
|
||||||
|
//******************************************
|
||||||
|
|
||||||
|
/******************************************
|
||||||
|
Defines
|
||||||
|
*****************************************/
|
||||||
|
#define HUCARD 0
|
||||||
|
#define TURBOCHIP 1
|
||||||
|
|
||||||
|
#define DETECTION_SIZE 64
|
||||||
|
#define CHKSUM_SKIP 0
|
||||||
|
#define CHKSUM_OK 1
|
||||||
|
#define CHKSUM_ERROR 2
|
||||||
|
|
||||||
|
/******************************************
|
||||||
|
Prototype Declarations
|
||||||
|
*****************************************/
|
||||||
|
/* Hoping that sanni will use this progressbar function */
|
||||||
|
void draw_progressbar(uint32_t processedsize, uint32_t totalsize);
|
||||||
|
void pcsMenu(void);
|
||||||
|
void pceMenu(void);
|
||||||
|
|
||||||
|
/* Several PCE dedicated functions */
|
||||||
|
void pin_read_write_PCE(void);
|
||||||
|
void pin_init_PCE(void);
|
||||||
|
void setup_cart_PCE(void);
|
||||||
|
void reset_cart_PCE(void);
|
||||||
|
uint8_t read_byte_PCE(uint32_t address);
|
||||||
|
uint8_t write_byte_PCE(uint32_t address, uint8_t data);
|
||||||
|
uint32_t detect_rom_size_PCE(void);
|
||||||
|
void read_bank_PCE(uint32_t address_start, uint32_t address_end, uint32_t *processed_size, uint32_t total_size);
|
||||||
|
void read_rom_PCE(void);
|
||||||
|
|
||||||
|
/******************************************
|
||||||
|
Variables
|
||||||
|
*****************************************/
|
||||||
|
uint8_t pce_internal_mode; //0 - HuCARD, 1 - TurboChip
|
||||||
|
|
||||||
|
/******************************************
|
||||||
|
Menu
|
||||||
|
*****************************************/
|
||||||
|
// PCE start menu
|
||||||
|
static const char pceMenuItem1[] PROGMEM = "HuCARD";
|
||||||
|
static const char pceMenuItem2[] PROGMEM = "Turbochip";
|
||||||
|
static const char* const menuOptionspce[] PROGMEM = {pceMenuItem1, pceMenuItem2};
|
||||||
|
|
||||||
|
// PCE card menu items
|
||||||
|
static const char pceCartMenuItem1[] PROGMEM = "Read Rom";
|
||||||
|
static const char pceCartMenuItem2[] PROGMEM = "Reset";
|
||||||
|
static const char* const menuOptionspceCart[] PROGMEM = {pceCartMenuItem1, pceCartMenuItem2};
|
||||||
|
|
||||||
|
void draw_progressbar(uint32_t processedsize, uint32_t totalsize)
|
||||||
|
{
|
||||||
|
uint8_t currentstatus, i;
|
||||||
|
static uint8_t previousstatus;
|
||||||
|
|
||||||
|
//Find progressbar length and draw if processed size is not 0
|
||||||
|
if(processedsize != 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Progress bar
|
||||||
|
if (processedsize >= totalsize)
|
||||||
|
{
|
||||||
|
//if processed size is equal to total process size, finish drawing progress bar
|
||||||
|
currentstatus = 20;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//if processed size did not reach total process size, find how many "*" should be drawn
|
||||||
|
currentstatus = processedsize / (totalsize / 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Draw "*" if needed
|
||||||
|
if (currentstatus > previousstatus)
|
||||||
|
{
|
||||||
|
for (i = previousstatus; i < currentstatus; i++)
|
||||||
|
{
|
||||||
|
if (i == 19)
|
||||||
|
{
|
||||||
|
//If end of progress bar, finish progress bar by drawing "]"
|
||||||
|
print_Msg(F("]"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print_Msg(F("*"));
|
||||||
|
}
|
||||||
|
//Update display
|
||||||
|
display_Update();
|
||||||
|
}
|
||||||
|
//update previous "*" status
|
||||||
|
previousstatus = currentstatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//If processed size is 0, initialize and draw "["
|
||||||
|
previousstatus = 0;
|
||||||
|
print_Msg(F("["));
|
||||||
|
display_Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PCE start menu
|
||||||
|
void pcsMenu(void) {
|
||||||
|
// create menu with title and 3 options to choose from
|
||||||
|
unsigned char pceDev;
|
||||||
|
// Copy menuOptions out of progmem
|
||||||
|
convertPgm(menuOptionspce, 2);
|
||||||
|
pceDev = question_box("Select device", menuOptions, 2, 0);
|
||||||
|
|
||||||
|
// wait for user choice to come back from the question box menu
|
||||||
|
switch (pceDev)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
//Hucard
|
||||||
|
display_Clear();
|
||||||
|
display_Update();
|
||||||
|
pce_internal_mode = HUCARD;
|
||||||
|
setup_cart_PCE();
|
||||||
|
mode = mode_PCE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
//Turbografx
|
||||||
|
display_Clear();
|
||||||
|
display_Update();
|
||||||
|
pce_internal_mode = TURBOCHIP;
|
||||||
|
setup_cart_PCE();
|
||||||
|
mode = mode_PCE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pin_read_write_PCE(void)
|
||||||
|
{
|
||||||
|
// Set Address Pins to Output
|
||||||
|
//A0-A7
|
||||||
|
DDRF = 0xFF;
|
||||||
|
//A8-A15
|
||||||
|
DDRK = 0xFF;
|
||||||
|
//A16-A19
|
||||||
|
DDRL = (DDRL & 0xF0) | 0x0F;
|
||||||
|
|
||||||
|
//Set Control Pin to Output CS(PL4)
|
||||||
|
DDRL |= (1 << 4);
|
||||||
|
|
||||||
|
//Set CS(PL4) to HIGH
|
||||||
|
PORTL |= (1 << 4);
|
||||||
|
|
||||||
|
// Set Control Pins to Output RST(PH0) RD(PH3) WR(PH5)
|
||||||
|
DDRH |= (1 << 0) | (1 << 3) | (1 << 5);
|
||||||
|
// Switch all of above to HIGH
|
||||||
|
PORTH |= (1 << 0) | (1 << 3) | (1 << 5);
|
||||||
|
|
||||||
|
// Set IRQ(PH4) to Input
|
||||||
|
DDRH &= ~(1 << 4);
|
||||||
|
// Activate Internal Pullup Resistors
|
||||||
|
PORTH |= (1 << 4);
|
||||||
|
|
||||||
|
// Set Data Pins (D0-D7) to Input
|
||||||
|
DDRC = 0x00;
|
||||||
|
|
||||||
|
// Enable Internal Pullups
|
||||||
|
PORTC = 0xFF;
|
||||||
|
|
||||||
|
reset_cart_PCE();
|
||||||
|
}
|
||||||
|
|
||||||
|
void pin_init_PCE(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
//Set Address Pins to input and pull up
|
||||||
|
DDRF = 0x00;
|
||||||
|
PORTF = 0xFF;
|
||||||
|
DDRK = 0x00;
|
||||||
|
PORTK = 0xFF;
|
||||||
|
DDRL = 0x00;
|
||||||
|
PORTL = 0xFF;
|
||||||
|
DDRH &= ~((1 << 0) | (1 << 3) | (1 << 5) | (1 << 6));
|
||||||
|
PORTH = (1 << 0) | (1 << 3) | (1 << 5) | (1 << 6);
|
||||||
|
|
||||||
|
// Set IRQ(PH4) to Input
|
||||||
|
DDRH &= ~(1 << 4);
|
||||||
|
// Activate Internal Pullup Resistors
|
||||||
|
PORTH |= (1 << 4);
|
||||||
|
|
||||||
|
// Set Data Pins (D0-D7) to Input
|
||||||
|
DDRC = 0x00;
|
||||||
|
// Enable Internal Pullups
|
||||||
|
PORTC = 0xFF;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup_cart_PCE(void)
|
||||||
|
{
|
||||||
|
// Set cicrstPin(PG1) to Output
|
||||||
|
DDRG |= (1 << 1);
|
||||||
|
// Output a high to disable CIC
|
||||||
|
PORTG |= (1 << 1);
|
||||||
|
|
||||||
|
pin_init_PCE();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_cart_PCE(void)
|
||||||
|
{
|
||||||
|
//Set RESET as Low
|
||||||
|
PORTH &= ~(1 << 0);
|
||||||
|
delay(200);
|
||||||
|
//Set RESET as High
|
||||||
|
PORTH |= (1 << 0);
|
||||||
|
delay(200);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_address_PCE(uint32_t address)
|
||||||
|
{
|
||||||
|
//Set address
|
||||||
|
PORTF = address & 0xFF;
|
||||||
|
PORTK = (address >> 8) & 0xFF;
|
||||||
|
PORTL = (PORTL & 0xF0) | ((address >> 16) & 0x0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t read_byte_PCE(uint32_t address)
|
||||||
|
{
|
||||||
|
uint8_t ret;
|
||||||
|
uint8_t address_byte;
|
||||||
|
|
||||||
|
set_address_PCE(address);
|
||||||
|
|
||||||
|
// Arduino running at 16Mhz -> one nop = 62.5ns -> 1000ns total
|
||||||
|
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||||
|
|
||||||
|
// Set CS(PL4) and RD(PH3) as LOW
|
||||||
|
PORTL &= ~(1 << 4);
|
||||||
|
PORTH &= ~(1 << 3);
|
||||||
|
|
||||||
|
// Arduino running at 16Mhz -> one nop = 62.5ns -> 1000ns total
|
||||||
|
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||||
|
|
||||||
|
//read byte
|
||||||
|
ret = PINC;
|
||||||
|
|
||||||
|
//Swap bit order for PC Engine HuCARD
|
||||||
|
if(pce_internal_mode == HUCARD)
|
||||||
|
{
|
||||||
|
ret = ((ret & 0x01) << 7) | ((ret & 0x02) << 5) | ((ret & 0x04) << 3) | ((ret & 0x08) << 1) | ((ret & 0x10) >> 1) | ((ret & 0x20) >> 3) | ((ret & 0x40) >> 5) | ((ret & 0x80) >> 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set CS(PL4) and RD(PH3) as HIGH
|
||||||
|
PORTL |= (1 << 4);
|
||||||
|
PORTH |= (1 << 3);
|
||||||
|
|
||||||
|
//return read data
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t write_byte_PCE(uint32_t address, uint8_t data)
|
||||||
|
{
|
||||||
|
uint8_t ret;
|
||||||
|
uint8_t address_byte;
|
||||||
|
|
||||||
|
set_address_PCE(address);
|
||||||
|
|
||||||
|
// Arduino running at 16Mhz -> one nop = 62.5ns -> 1000ns total
|
||||||
|
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||||
|
|
||||||
|
//Swap bit order for PC Engine HuCARD
|
||||||
|
if(pce_internal_mode == HUCARD)
|
||||||
|
{
|
||||||
|
data = ((data & 0x01) << 7) | ((data & 0x02) << 5) | ((data & 0x04) << 3) | ((data & 0x08) << 1) | ((data & 0x10) >> 1) | ((data & 0x20) >> 3) | ((data & 0x40) >> 5) | ((data & 0x80) >> 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
//write byte
|
||||||
|
PORTC = data;
|
||||||
|
|
||||||
|
// Set Data Pins (D0-D7) to Output
|
||||||
|
DDRC = 0xFF;
|
||||||
|
|
||||||
|
// Set CS(PL4) and WR(PH5) as LOW
|
||||||
|
PORTL &= ~(1 << 4);
|
||||||
|
PORTH &= ~(1 << 5);
|
||||||
|
|
||||||
|
// Arduino running at 16Mhz -> one nop = 62.5ns -> 1000ns total
|
||||||
|
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||||
|
|
||||||
|
// Set CS(PL4) and WR(PH5) as HIGH
|
||||||
|
PORTL |= (1 << 4);
|
||||||
|
PORTH |= (1 << 5);
|
||||||
|
|
||||||
|
// Set Data Pins (D0-D7) to Input
|
||||||
|
DDRC = 0x00;
|
||||||
|
|
||||||
|
// Enable Internal Pullups
|
||||||
|
PORTC = 0xFF;
|
||||||
|
|
||||||
|
//return read data
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Confirm the size of ROM - 128Kb, 256Kb, 384Kb, 512Kb, 768Kb or 1024Kb
|
||||||
|
uint32_t detect_rom_size_PCE(void)
|
||||||
|
{
|
||||||
|
uint32_t rom_size;
|
||||||
|
uint8_t read_byte;
|
||||||
|
uint8_t current_byte;
|
||||||
|
uint8_t detect_128, detect_256, detect_512, detect_768;
|
||||||
|
|
||||||
|
//Initialize variables
|
||||||
|
detect_128 = 0;
|
||||||
|
detect_256 = 0;
|
||||||
|
detect_512 = 0;
|
||||||
|
detect_768 = 0;
|
||||||
|
|
||||||
|
//Set pins to read PC Engine cart
|
||||||
|
pin_read_write_PCE();
|
||||||
|
|
||||||
|
//Confirm where mirror address start from(128KB, 256KB, 512KB, 768, or 1024KB)
|
||||||
|
for (current_byte = 0; current_byte < DETECTION_SIZE; current_byte++) {
|
||||||
|
if((current_byte != detect_128) && (current_byte != detect_256) && (current_byte != detect_512) && (current_byte != detect_768))
|
||||||
|
{
|
||||||
|
//If none matched, it is 1024KB
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//read byte for 128KB, 256KB, 512KB detection
|
||||||
|
read_byte = read_byte_PCE(current_byte);
|
||||||
|
|
||||||
|
//128KB detection
|
||||||
|
if(current_byte == detect_128)
|
||||||
|
{
|
||||||
|
if(read_byte_PCE(current_byte + 128UL * 1024UL) == read_byte)
|
||||||
|
{
|
||||||
|
detect_128++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//256KB detection
|
||||||
|
if(current_byte == detect_256)
|
||||||
|
{
|
||||||
|
if(read_byte_PCE(current_byte + 256UL * 1024UL) == read_byte)
|
||||||
|
{
|
||||||
|
detect_256++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//512KB detection
|
||||||
|
if(current_byte == detect_512)
|
||||||
|
{
|
||||||
|
if(read_byte_PCE(current_byte + 512UL * 1024UL) == read_byte)
|
||||||
|
{
|
||||||
|
detect_512++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//768KB detection
|
||||||
|
read_byte = read_byte_PCE(current_byte + 512UL * 1024UL);
|
||||||
|
if(current_byte == detect_768)
|
||||||
|
{
|
||||||
|
if(read_byte_PCE(current_byte + 768UL * 1024UL) == read_byte)
|
||||||
|
{
|
||||||
|
detect_768++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//debug
|
||||||
|
//sprintf(fileName, "%d %d %d %d", detect_128, detect_256, detect_512, detect_768); //using filename global variable as string. Initialzed in below anyways.
|
||||||
|
//println_Msg(fileName);
|
||||||
|
|
||||||
|
//ROM size detection by result
|
||||||
|
if(detect_128 == DETECTION_SIZE)
|
||||||
|
{
|
||||||
|
rom_size = 128;
|
||||||
|
}
|
||||||
|
else if(detect_256 == DETECTION_SIZE)
|
||||||
|
{
|
||||||
|
if(detect_512 == DETECTION_SIZE)
|
||||||
|
{
|
||||||
|
rom_size = 256;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Another confirmation for 384KB because 384KB hucard has data in 0x0--0x40000 and 0x80000--0xA0000(0x40000 is mirror of 0x00000)
|
||||||
|
rom_size = 384;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(detect_512 == DETECTION_SIZE)
|
||||||
|
{
|
||||||
|
rom_size = 512;
|
||||||
|
}
|
||||||
|
else if(detect_768 == DETECTION_SIZE)
|
||||||
|
{
|
||||||
|
rom_size = 768;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rom_size = 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
//If rom size is more than or equal to 512KB, detect Street fighter II'
|
||||||
|
if(rom_size >= 512)
|
||||||
|
{
|
||||||
|
//Look for "NEC HE "
|
||||||
|
if(read_byte_PCE(0x7FFF9) == 'N' && read_byte_PCE(0x7FFFA) == 'E' && read_byte_PCE(0x7FFFB) == 'C'
|
||||||
|
&& read_byte_PCE(0x7FFFC) == ' ' && read_byte_PCE(0x7FFFD) == 'H' && read_byte_PCE(0x7FFFE) == 'E')
|
||||||
|
{
|
||||||
|
rom_size = 2560;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rom_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Must be address_start and address_end should be 512 byte aligned */
|
||||||
|
void read_bank_PCE(uint32_t address_start, uint32_t address_end, uint32_t *processed_size, uint32_t total_size)
|
||||||
|
{
|
||||||
|
uint32_t currByte;
|
||||||
|
uint16_t c;
|
||||||
|
|
||||||
|
for (currByte = address_start; currByte < address_end; currByte += 512) {
|
||||||
|
for (c = 0; c < 512; c++) {
|
||||||
|
sdBuffer[c] = read_byte_PCE(currByte + c);
|
||||||
|
}
|
||||||
|
myFile.write(sdBuffer, 512);
|
||||||
|
*processed_size += 512;
|
||||||
|
draw_progressbar(*processed_size, total_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get line from file and convert upper case to lower case
|
||||||
|
void skip_line(SdFile* readfile)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
char str_buf;
|
||||||
|
|
||||||
|
while (readfile->available())
|
||||||
|
{
|
||||||
|
//Read 1 byte from file
|
||||||
|
str_buf = readfile->read();
|
||||||
|
|
||||||
|
//if end of file or newline found, execute command
|
||||||
|
if (str_buf == '\r')
|
||||||
|
{
|
||||||
|
readfile->read(); //dispose \n because \r\n
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}//End while
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get line from file and convert upper case to lower case
|
||||||
|
void get_line(char* str_buf, SdFile* readfile, uint8_t maxi)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (readfile->available())
|
||||||
|
{
|
||||||
|
//If line size is more than maximum array, limit it.
|
||||||
|
if(i >= maxi)
|
||||||
|
{
|
||||||
|
i = maxi - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Read 1 byte from file
|
||||||
|
str_buf[i] = readfile->read();
|
||||||
|
|
||||||
|
//if end of file or newline found, execute command
|
||||||
|
if (str_buf[i] == '\r')
|
||||||
|
{
|
||||||
|
str_buf[i] = '\0';
|
||||||
|
readfile->read(); //dispose \n because \r\n
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}//End while
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t calculate_crc32(int n, unsigned char c[], uint32_t r)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
r ^= c[i];
|
||||||
|
for (j = 0; j < 8; j++)
|
||||||
|
if (r & 1) r = (r >> 1) ^ 0xEDB88320UL;
|
||||||
|
else r >>= 1;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void crc_search(char *file_p, char *folder_p, uint32_t rom_size)
|
||||||
|
{
|
||||||
|
SdFile rom, script;
|
||||||
|
uint32_t r, crc, processedsize;
|
||||||
|
char gamename[100];
|
||||||
|
char crc_file[9], crc_search[9];
|
||||||
|
uint8_t flag;
|
||||||
|
flag = CHKSUM_SKIP;
|
||||||
|
|
||||||
|
//Open list file. If no list file found, just skip
|
||||||
|
sd.chdir("/"); //Set read directry to root
|
||||||
|
if (script.open("PCE_CRC_LIST.txt", O_READ))
|
||||||
|
{
|
||||||
|
//Calculate CRC of ROM file
|
||||||
|
sd.chdir(folder_p);
|
||||||
|
if (rom.open(file_p, O_READ))
|
||||||
|
{
|
||||||
|
//Initialize flag as error
|
||||||
|
flag = CHKSUM_ERROR;
|
||||||
|
crc = 0xFFFFFFFFUL; //Initialize CRC
|
||||||
|
display_Clear();
|
||||||
|
println_Msg("Calculating chksum...");
|
||||||
|
processedsize = 0;
|
||||||
|
draw_progressbar(0, rom_size * 1024UL); //Initialize progress bar
|
||||||
|
|
||||||
|
while (rom.available())
|
||||||
|
{
|
||||||
|
r = rom.read(sdBuffer, 512);
|
||||||
|
crc = calculate_crc32(r, sdBuffer, crc);
|
||||||
|
processedsize += r;
|
||||||
|
draw_progressbar(processedsize, rom_size * 1024UL);
|
||||||
|
}
|
||||||
|
|
||||||
|
crc = crc ^ 0xFFFFFFFFUL; //Finish CRC calculation and progress bar
|
||||||
|
draw_progressbar(rom_size * 1024UL, rom_size * 1024UL);
|
||||||
|
|
||||||
|
//Display calculated CRC
|
||||||
|
sprintf(crc_file, "%08lX", crc);
|
||||||
|
|
||||||
|
//Search for same CRC in list
|
||||||
|
while (script.available()) {
|
||||||
|
//Read 2 lines (game name and CRC)
|
||||||
|
get_line(gamename, &script, 96);
|
||||||
|
get_line(crc_search, &script, 9);
|
||||||
|
skip_line(&script); //Skip every 3rd line
|
||||||
|
|
||||||
|
//if checksum search successful, rename the file and end search
|
||||||
|
if(strcmp(crc_search, crc_file) == 0)
|
||||||
|
{
|
||||||
|
print_Msg("Chksum OK ");
|
||||||
|
println_Msg(crc_file);
|
||||||
|
print_Msg(F("Saved to "));
|
||||||
|
print_Msg(folder_p);
|
||||||
|
print_Msg(F("/"));
|
||||||
|
print_Msg(gamename);
|
||||||
|
print_Msg(F(".pce"));
|
||||||
|
flag = CHKSUM_OK;
|
||||||
|
strcat(gamename, ".pce");
|
||||||
|
rom.rename(sd.vwd(), gamename);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rom.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(flag == CHKSUM_SKIP)
|
||||||
|
{
|
||||||
|
print_Msg(F("Saved to "));
|
||||||
|
print_Msg(folder_p);
|
||||||
|
print_Msg(F("/"));
|
||||||
|
print_Msg(file_p);
|
||||||
|
}
|
||||||
|
else if(flag == CHKSUM_ERROR)
|
||||||
|
{
|
||||||
|
print_Msg("Chksum Error ");
|
||||||
|
println_Msg(crc_file);
|
||||||
|
print_Msg(F("Saved to "));
|
||||||
|
print_Msg(folder_p);
|
||||||
|
print_Msg(F("/"));
|
||||||
|
print_Msg(file_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
script.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void read_rom_PCE(void)
|
||||||
|
{
|
||||||
|
uint32_t rom_size;
|
||||||
|
uint32_t processed_size = 0;
|
||||||
|
|
||||||
|
//clear the screen
|
||||||
|
display_Clear();
|
||||||
|
rom_size = detect_rom_size_PCE();
|
||||||
|
sprintf(fileName, "Detected size: %dKB", rom_size); //using filename global variable as string. Initialzed in below anyways.
|
||||||
|
println_Msg(fileName);
|
||||||
|
|
||||||
|
//debug
|
||||||
|
//return;
|
||||||
|
|
||||||
|
// Get name, add extension and convert to char array for sd lib
|
||||||
|
strcpy(fileName, "PCEROM");
|
||||||
|
strcat(fileName, ".pce");
|
||||||
|
|
||||||
|
// create a new folder for the save file
|
||||||
|
EEPROM_readAnything(10, foldern);
|
||||||
|
sprintf(folder, "PCE/ROM/%s/%d", romName, foldern);
|
||||||
|
sd.mkdir(folder, true);
|
||||||
|
sd.chdir(folder);
|
||||||
|
|
||||||
|
println_Msg(F("Saving ROM..."));
|
||||||
|
display_Update();
|
||||||
|
|
||||||
|
// write new folder number back to eeprom
|
||||||
|
foldern = foldern + 1;
|
||||||
|
EEPROM_writeAnything(10, foldern);
|
||||||
|
|
||||||
|
//open file on sd card
|
||||||
|
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||||
|
print_Error(F("Can't create file on SD"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
pin_read_write_PCE();
|
||||||
|
|
||||||
|
//Initialize progress bar by setting processed size as 0
|
||||||
|
draw_progressbar(0, rom_size * 1024UL);
|
||||||
|
|
||||||
|
if(rom_size == 384)
|
||||||
|
{
|
||||||
|
//Read two sections. 0x000000--0x040000 and 0x080000--0x0A0000 for 384KB
|
||||||
|
read_bank_PCE(0, 0x40000, &processed_size, rom_size * 1024UL);
|
||||||
|
read_bank_PCE(0x80000, 0xA0000, &processed_size, rom_size * 1024UL);
|
||||||
|
}
|
||||||
|
else if(rom_size == 2560)
|
||||||
|
{
|
||||||
|
//Dump Street fighter II' Champion Edition
|
||||||
|
read_bank_PCE(0, 0x80000, &processed_size, rom_size * 1024UL); //Read first bank
|
||||||
|
write_byte_PCE(0x1FF0, 0xFF); //Display second bank
|
||||||
|
read_bank_PCE(0x80000, 0x100000, &processed_size, rom_size * 1024UL); //Read second bank
|
||||||
|
write_byte_PCE(0x1FF1, 0xFF); //Display third bank
|
||||||
|
read_bank_PCE(0x80000, 0x100000, &processed_size, rom_size * 1024UL); //Read third bank
|
||||||
|
write_byte_PCE(0x1FF2, 0xFF); //Display forth bank
|
||||||
|
read_bank_PCE(0x80000, 0x100000, &processed_size, rom_size * 1024UL); //Read forth bank
|
||||||
|
write_byte_PCE(0x1FF3, 0xFF); //Display fifth bank
|
||||||
|
read_bank_PCE(0x80000, 0x100000, &processed_size, rom_size * 1024UL); //Read fifth bank
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Read start form 0x000000 and keep reading until end of ROM
|
||||||
|
read_bank_PCE(0, rom_size * 1024UL, &processed_size, rom_size * 1024UL);
|
||||||
|
}
|
||||||
|
|
||||||
|
pin_init_PCE();
|
||||||
|
|
||||||
|
//Close the file:
|
||||||
|
myFile.close();
|
||||||
|
|
||||||
|
//CRC search and rename ROM
|
||||||
|
crc_search(fileName, folder, rom_size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// SNES Menu
|
||||||
|
void pceMenu() {
|
||||||
|
// create menu with title and 7 options to choose from
|
||||||
|
unsigned char mainMenu;
|
||||||
|
// Copy menuOptions out of progmem
|
||||||
|
convertPgm(menuOptionspceCart, 2);
|
||||||
|
|
||||||
|
if(pce_internal_mode == HUCARD)
|
||||||
|
{
|
||||||
|
mainMenu = question_box("PCE HuCARD menu", menuOptions, 2, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mainMenu = question_box("TG TurboChip menu", menuOptions, 2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for user choice to come back from the question box menu
|
||||||
|
switch (mainMenu)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
display_Clear();
|
||||||
|
// Change working dir to root
|
||||||
|
sd.chdir("/");
|
||||||
|
read_rom_PCE();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
asm volatile (" jmp 0");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
println_Msg(F(""));
|
||||||
|
println_Msg(F("Press Button..."));
|
||||||
|
display_Update();
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************
|
||||||
|
// End of File
|
||||||
|
//******************************************
|
||||||
|
|
BIN
pinout.xls
BIN
pinout.xls
Binary file not shown.
1277
sd/PCE_CRC_LIST.txt
Normal file
1277
sd/PCE_CRC_LIST.txt
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user