Initial GS code engine implementation

- Replaced the cheat file format with YAML
- Replaced the simulate_boot function with a small bit of C, and a loader in assembly
- The loader is fairly well-documented, and points out which register states are required for CICs
- Also includes a giant patcher function (relocatable assembly) which can patch the exception handler and run the code engine
- The code engine is GS Pro 3.30-compatible, and supports all code types
This commit is contained in:
Jay Oster 2014-08-22 17:10:06 -07:00
parent 3ba0910535
commit 90fb4e39a5
6 changed files with 701 additions and 1328 deletions

View File

@ -7,9 +7,9 @@ N64TOOL = $(ROOTDIR)/bin/n64tool
HEADERNAME = header
LINK_FLAGS = -G4 -L$(ROOTDIR)/lib -L$(ROOTDIR)/mips64-elf/lib -ldragon -lmikmod -lmad -lc -lm -ldragonsys -lnosys $(LIBS) -Tn64ld.x
LINK_FLAGS = -O1 -L$(ROOTDIR)/lib -L$(ROOTDIR)/mips64-elf/lib -ldragon -lmikmod -lmad -lyaml -lc -lm -ldragonsys -lnosys $(LIBS) -Tn64ld.x
PROG_NAME = menu
CFLAGS = -std=gnu99 -march=vr4300 -mtune=vr4300 -G4 -I$(ROOTDIR)/include -I$(ROOTDIR)/mips64-elf/include -lpthread -lrt -D_REENTRANT -DUSE_TRUETYPE
CFLAGS = -std=gnu99 -march=vr4300 -mtune=vr4300 -O1 -I$(ROOTDIR)/include -I$(ROOTDIR)/mips64-elf/include -lpthread -lrt -D_REENTRANT -DUSE_TRUETYPE
ASFLAGS = -mtune=vr4300 -march=vr4300
CC = $(GCCN64PREFIX)gcc
AS = $(GCCN64PREFIX)as

View File

@ -33,6 +33,7 @@ toolchain recommended by libdragon, with some updated versions.
* [libdragon](https://github.com/parasyte/libdragon)
* [libmikmod-n64](https://github.com/parasyte/libmikmod-n64)
* [libmad-n64](https://github.com/parasyte/libmad-n64)
* [libyaml](http://pyyaml.org/wiki/LibYAML)
### Build the Toolchain
@ -98,11 +99,30 @@ toolchain installation path:
```bash
$ git clone https://github.com/parasyte/libmad-n64.git
$ cd libmad-n64
$ export PATH=$PATH:/usr/local/mips64-elf/bin
$ export PATH=$PATH:$(N64_INST)/bin
$ CFLAGS="-march=vr4300 -mtune=vr4300 -mno-extern-sdata" \
LDFLAGS="-L/usr/local/mips64-elf/lib" LIBS="-lc -lnosys" \
LDFLAGS="-L$(N64_INST)/lib" LIBS="-lc -lnosys" \
./configure --host=mips64-elf --disable-shared \
--prefix=/usr/local/mips64-elf --enable-speed --enable-fpm=mips
--prefix=$(N64_INST) --enable-speed --enable-fpm=mips
$ make
$ make install
```
### Build `libyaml`
Download libyaml 0.1.6 and build, be sure to set the path according to your
toolchain installation path:
```bash
$ hg clone https://bitbucket.org/xi/libyaml
$ cd libyaml
$ hg update 0.1.6
$ ./bootstrap
$ export PATH=$PATH:$(N64_INST)/bin
$ CFLAGS="-std=gnu99 -march=vr4300 -mtune=vr4300" \
LDFLAGS="-L$(N64_INST)/lib -Tn64ld.x" \
LIBS="-ldragon -lc -ldragonsys -lnosys" \
./configure --host=mips64-elf --prefix=$(N64_INST)
$ make
$ make install
```

572
menu.c
View File

@ -39,18 +39,8 @@
#include <mikmod.h>
#include "mp3.h"
//cheats
struct gscEntry {
char *description;
char *gscodes;
u16 count;
u16 state;
u16 mask;
u16 value;
};
typedef struct gscEntry gscEntry_t;
gscEntry_t gGSCodes[256];
// YAML parser
#include <yaml.h>
#ifdef USE_TRUETYPE
#define STB_TRUETYPE_IMPLEMENTATION
@ -649,7 +639,7 @@ void drawBoxNumber(display_context_t disp, int box){
switch(box){
case 1: drawBox(20, 24, 277, 193, disp); break; //filebrowser
case 2: drawBox(60, 64, 197, 114, disp); break; //info screen
case 2: drawBox(60, 56, 200, 128, disp); break; //info screen
case 3:
box_color= graphics_make_color(0x00, 0x00, 0x60, 0xC9);
drawBox(79, 29, 161, 180, disp);
@ -1251,7 +1241,6 @@ void loadrom(display_context_t disp, u8 *buff, int fast){
// cart was found, use CIC and SaveRAM type
}
if (debug) {
sprintf(tmp, "Info: cic=%i save=%i",cic,save);
printText(tmp, 3, -1, disp);
@ -1317,7 +1306,6 @@ void loadrom(display_context_t disp, u8 *buff, int fast){
}
else{
resp = diskRead(begin_sector, (void *)0xb0000000, lower_half);
sleep(10);
resp = diskRead(begin_sector+lower_half, (void *)0xb2000000, file_sectors-lower_half);
}
@ -2149,376 +2137,185 @@ void readSDcard(display_context_t disp, char *directory){
display_dir(list, cursor, page, MAX_LIST, count, disp);
}
//void readCheatFile(char *filename, display_context_t disp){
int readCheatFile(char *filename){
//var file readin
u8 tmp[32];
u8 ok=0;
u8 firstr=1;
/*
* Returns two cheat lists:
* - One for the "at boot" cheats
* - Another for the "in-game" cheats
*/
int readCheatFile(char *filename, u32 *cheat_lists[2]) {
// YAML parser
yaml_parser_t parser;
yaml_event_t event;
char *cp, *vp, *dp;
char buffer[512];
char temp[42];
char buff[512];
// State for YAML parser
int is_code = 0;
int code_on = 1;
int done = 0;
u32 *list1;
u32 *list2;
char *next;
int i = 0, j, type, offset = 0;
int repeater = 0;
u32 address;
u32 value;
int curr_cheat = -1;
yaml_parser_initialize(&parser);
FatRecord rec_tmpf;
ok = fatFindRecord(filename, &rec_tmpf, 0);
if(ok!=0){
int ok = fatFindRecord(filename, &rec_tmpf, 0);
if (ok != 0) {
return -1; //err file not found
}
else{
u8 resp = 0;
resp = fatOpenFileByeName(filename, 0);
//filesize of the opend file -> is the readfile / 512
int fsize= file.sec_available*512;
char cheatfile_rawdata[fsize];
resp = fatReadFile(&cheatfile_rawdata, fsize / 512); //1 cluster
int line_chr=0;
long c=0;
for(c=0;c<fsize;c++){
buff[line_chr++]=cheatfile_rawdata[c];
if(cheatfile_rawdata[c]=='\n'){
i = 0;
// process GameShark Code line
cp = vp = dp = NULL;
while ((buff[i] == ' ') || (buff[i] == '\t'))
i++; // skip initial whitespace
// check for blank line
if ((buff[i] == '\n') || (buff[i] == '\r')) //carriage return
{
line_chr=0;
continue; // skip
int fsize = file.sec_available * 512;
char *cheatfile = malloc(fsize);
if (!cheatfile) {
return -2; // Out of memory
}
if ((buff[i] == '#') || (buff[i] == ';')) {
line_chr=0;
continue; // skip
/*
* Size of the cheat list can never be more than half the size of the YAML
* Minimum YAML example:
* A:-80001234 FFFF
* Which is exactly 16 bytes.
* The cheat list in this case fits into exactly 8 bytes (2 words):
* 0x80001234, 0x0000FFFF
*/
list1 = calloc(1, fsize + 2); // Plus 2 words to be safe
if (!list1) {
// Free
free(cheatfile);
return -2; // Out of memory
}
list2 = &list1[fsize / sizeof(u32) / 2];
cheat_lists[0] = list1;
cheat_lists[1] = list2;
resp = fatReadFile(cheatfile, fsize / 512); //1 cluster
yaml_parser_set_input_string(&parser, cheatfile, strlen(cheatfile));
do {
if (!yaml_parser_parse(&parser, &event)) {
// Free
yaml_parser_delete(&parser);
yaml_event_delete(&event);
free(cheatfile);
free(cheat_lists[0]);
cheat_lists[0] = 0;
cheat_lists[1] = 0;
return -3; // Parse error
}
cp = &buff[i];
while ((buff[i] != ' ') && (buff[i] != '\t') && (buff[i] != '\n') && (buff[i] != '\r'))
i++;
buff[i] = 0;
i++;
while ((buff[i] == ' ') || (buff[i] == '\t'))
i++; // skip whitespace
vp = &buff[i];
while ((buff[i] != ' ') && (buff[i] != '\t') && (buff[i] != '\n') && (buff[i] != '\r'))
i++; // find end of GameShark code value
if ((buff[i] == ' ') || (buff[i] == '\t')) {
buff[i] =0;
i++;
while ((buff[i] == ' ') || (buff[i] == '\t'))
i++; // skip whitespace
if ((buff[i] != '\n') && (buff[i] != '\r') && (buff[i] != '#') && (buff[i] != ';')) {
dp = &buff[i];
while ((buff[i] != '\n') && (buff[i] != '\r'))
i++; // find end of GameShark code description
buff[i] =0;
}
}
else {
buff[i] =0;
}
if (dp) {
// starting new cheat
curr_cheat++;
gGSCodes[curr_cheat].description= strdup(dp);
gGSCodes[curr_cheat].gscodes = NULL;
gGSCodes[curr_cheat].count = 0;
gGSCodes[curr_cheat].state = 1;
gGSCodes[curr_cheat].mask = 0;
if (!ishexchar(vp[3]))
gGSCodes[curr_cheat].mask |= 0x000F;
if (!ishexchar(vp[2]))
gGSCodes[curr_cheat].mask |= 0x00F0;
if (!ishexchar(vp[1]))
gGSCodes[curr_cheat].mask |= 0x0F00;
if (!ishexchar(vp[0]))
gGSCodes[curr_cheat].mask |= 0xF000;
gGSCodes[curr_cheat].value = 0;
offset = 0;
}
if (curr_cheat < 0)
continue; // safety check
temp[0] = cp[0];
temp[1] = cp[1];
temp[2] = 0;
type = strtol(temp, (char **)NULL, 16);
switch (type) {
case 0x50:
// patch codes - unimplemented, also skips next line
// 5000XXYY 00ZZ
// TTTTTTTT VVVV
//skip next line missing
// Process YAML
switch (event.type) {
case YAML_MAPPING_START_EVENT:
// Begin code block
is_code = 0;
break;
case 0x80:
// write 8-bit value to (cached) ram continuously
// 80XXYYYY 00ZZ
if (gGSCodes[curr_cheat].gscodes)
gGSCodes[curr_cheat].gscodes = realloc(gGSCodes[curr_cheat].gscodes, offset + 16);
else
gGSCodes[curr_cheat].gscodes = malloc(16);
memcpy(&gGSCodes[curr_cheat].gscodes[offset], cp, 9);
memcpy(&gGSCodes[curr_cheat].gscodes[offset+9], vp, 5);
gGSCodes[curr_cheat].count++;
offset += 16;
case YAML_SEQUENCE_START_EVENT:
// Begin code lines
is_code = 1;
code_on = (event.data.sequence_start.tag ?
!!strcasecmp(event.data.sequence_start.tag, "!off") :
1
);
break;
case 0x81:
// write 16-bit value to (cached) ram continuously
// 81XXYYYY ZZZZ
if (gGSCodes[curr_cheat].gscodes)
gGSCodes[curr_cheat].gscodes = realloc(gGSCodes[curr_cheat].gscodes, offset + 16);
else
gGSCodes[curr_cheat].gscodes = malloc(16);
memcpy(&gGSCodes[curr_cheat].gscodes[offset], cp, 9);
memcpy(&gGSCodes[curr_cheat].gscodes[offset+9], vp, 5);
gGSCodes[curr_cheat].count++;
offset += 16;
case YAML_SEQUENCE_END_EVENT:
// End code lines
is_code = 0;
code_on = 1;
repeater = 0;
break;
case 0x88:
// write 8-bit value to (cached) ram on GS button pressed - unimplemented
// 88XXYYYY 00ZZ
break;
case 0x89:
// write 16-bit value to (cached) ram on GS button pressed - unimplemented
// 89XXYYYY ZZZZ
break;
case 0xA0:
// write 8-bit value to (uncached) ram continuously
// A0XXYYYY 00ZZ => 3C1A A0XX 375A YYYY 241B 00ZZ A35B 0000
if (gGSCodes[curr_cheat].gscodes)
gGSCodes[curr_cheat].gscodes = realloc(gGSCodes[curr_cheat].gscodes, offset + 16);
else
gGSCodes[curr_cheat].gscodes = malloc(16);
memcpy(&gGSCodes[curr_cheat].gscodes[offset], cp, 9);
memcpy(&gGSCodes[curr_cheat].gscodes[offset+9], vp, 5);
gGSCodes[curr_cheat].count++;
offset += 16;
break;
case 0xA1:
// write 16-bit value to (uncached) ram continuously
// A1XXYYYY ZZZZ => 3C1A A0XX 375A YYYY 241B ZZZZ A75B 0000
if (gGSCodes[curr_cheat].gscodes)
gGSCodes[curr_cheat].gscodes = realloc(gGSCodes[curr_cheat].gscodes, offset + 16);
else
gGSCodes[curr_cheat].gscodes = malloc(16);
memcpy(&gGSCodes[curr_cheat].gscodes[offset], cp, 9);
memcpy(&gGSCodes[curr_cheat].gscodes[offset+9], vp, 5);
gGSCodes[curr_cheat].count++;
offset += 16;
break;
case 0xCC:
// deactivate expansion ram using 3rd method
// CC000000 0000
if (gGSCodes[curr_cheat].gscodes)
gGSCodes[curr_cheat].gscodes = realloc(gGSCodes[curr_cheat].gscodes, offset + 16);
else
gGSCodes[curr_cheat].gscodes = malloc(16);
memcpy(&gGSCodes[curr_cheat].gscodes[offset], cp, 9);
memcpy(&gGSCodes[curr_cheat].gscodes[offset+9], vp, 5);
gGSCodes[curr_cheat].count++;
offset += 16;
break;
case 0xD0:
// do next gs code if ram location is equal to 8-bit value
// D0XXYYYY 00ZZ
if (gGSCodes[curr_cheat].gscodes)
gGSCodes[curr_cheat].gscodes = realloc(gGSCodes[curr_cheat].gscodes, offset + 16);
else
gGSCodes[curr_cheat].gscodes = malloc(16);
memcpy(&gGSCodes[curr_cheat].gscodes[offset], cp, 9);
memcpy(&gGSCodes[curr_cheat].gscodes[offset+9], vp, 5);
gGSCodes[curr_cheat].count++;
offset += 16;
break;
case 0xD1:
// do next gs code if ram location is equal to 16-bit value
// D1XXYYYY ZZZZ
if (gGSCodes[curr_cheat].gscodes)
gGSCodes[curr_cheat].gscodes = realloc(gGSCodes[curr_cheat].gscodes, offset + 16);
else
gGSCodes[curr_cheat].gscodes = malloc(16);
memcpy(&gGSCodes[curr_cheat].gscodes[offset], cp, 9);
memcpy(&gGSCodes[curr_cheat].gscodes[offset+9], vp, 5);
gGSCodes[curr_cheat].count++;
offset += 16;
break;
case 0xD2:
// do next gs code if ram location is not equal to 8-bit value
// D2XXYYYY 00ZZ
if (gGSCodes[curr_cheat].gscodes)
gGSCodes[curr_cheat].gscodes = realloc(gGSCodes[curr_cheat].gscodes, offset + 16);
else
gGSCodes[curr_cheat].gscodes = malloc(16);
memcpy(&gGSCodes[curr_cheat].gscodes[offset], cp, 9);
memcpy(&gGSCodes[curr_cheat].gscodes[offset+9], vp, 5);
gGSCodes[curr_cheat].count++;
offset += 16;
break;
case 0xD3:
// do next gs code if ram location is not equal to 16-bit value
// D1XXYYYY ZZZZ
if (gGSCodes[curr_cheat].gscodes)
gGSCodes[curr_cheat].gscodes = realloc(gGSCodes[curr_cheat].gscodes, offset + 16);
else
gGSCodes[curr_cheat].gscodes = malloc(16);
memcpy(&gGSCodes[curr_cheat].gscodes[offset], cp, 9);
memcpy(&gGSCodes[curr_cheat].gscodes[offset+9], vp, 5);
gGSCodes[curr_cheat].count++;
offset += 16;
break;
case 0xDD:
// deactivate expansion ram using 2nd method
// DD000000 0000
if (gGSCodes[curr_cheat].gscodes)
gGSCodes[curr_cheat].gscodes = realloc(gGSCodes[curr_cheat].gscodes, offset + 16);
else
gGSCodes[curr_cheat].gscodes = malloc(16);
memcpy(&gGSCodes[curr_cheat].gscodes[offset], cp, 9);
memcpy(&gGSCodes[curr_cheat].gscodes[offset+9], vp, 5);
gGSCodes[curr_cheat].count++;
offset += 16;
break;
case 0xDE:
// set game boot address
// DEXXXXXX 0000
if (gGSCodes[curr_cheat].gscodes)
gGSCodes[curr_cheat].gscodes = realloc(gGSCodes[curr_cheat].gscodes, offset + 16);
else
gGSCodes[curr_cheat].gscodes = malloc(16);
memcpy(&gGSCodes[curr_cheat].gscodes[offset], cp, 9);
memcpy(&gGSCodes[curr_cheat].gscodes[offset+9], vp, 5);
gGSCodes[curr_cheat].count++;
offset += 16;
break;
case 0xEE:
// deactivate expansion ram using 1st method
// EE000000 0000
if (gGSCodes[curr_cheat].gscodes)
gGSCodes[curr_cheat].gscodes = realloc(gGSCodes[curr_cheat].gscodes, offset + 16);
else
gGSCodes[curr_cheat].gscodes = malloc(16);
memcpy(&gGSCodes[curr_cheat].gscodes[offset], cp, 9);
memcpy(&gGSCodes[curr_cheat].gscodes[offset+9], vp, 5);
gGSCodes[curr_cheat].count++;
offset += 16;
break;
case 0xF0:
// write 8-bit value to (cached) ram before boot
// F0XXXXXX 00YY
if (gGSCodes[curr_cheat].gscodes)
gGSCodes[curr_cheat].gscodes = realloc(gGSCodes[curr_cheat].gscodes, offset + 16);
else
gGSCodes[curr_cheat].gscodes = malloc(16);
memcpy(&gGSCodes[curr_cheat].gscodes[offset], cp, 9);
memcpy(&gGSCodes[curr_cheat].gscodes[offset+9], vp, 5);
gGSCodes[curr_cheat].count++;
offset += 16;
break;
case 0xF1:
// write 16-bit value to (cached) ram before boot
// F1XXXXXX YYYY
if (gGSCodes[curr_cheat].gscodes)
gGSCodes[curr_cheat].gscodes = realloc(gGSCodes[curr_cheat].gscodes, offset + 16);
else
gGSCodes[curr_cheat].gscodes = malloc(16);
memcpy(&gGSCodes[curr_cheat].gscodes[offset], cp, 9);
memcpy(&gGSCodes[curr_cheat].gscodes[offset+9], vp, 5);
gGSCodes[curr_cheat].count++;
offset += 16;
break;
case 0xFF:
// set code base
// FFXXXXXX 0000
if (gGSCodes[curr_cheat].gscodes)
gGSCodes[curr_cheat].gscodes = realloc(gGSCodes[curr_cheat].gscodes, offset + 16);
else
gGSCodes[curr_cheat].gscodes = malloc(16);
memcpy(&gGSCodes[curr_cheat].gscodes[offset], cp, 9);
memcpy(&gGSCodes[curr_cheat].gscodes[offset+9], vp, 5);
gGSCodes[curr_cheat].count++;
offset += 16;
case YAML_SCALAR_EVENT:
// Code line
if (!is_code || !code_on) {
break;
}
line_chr=0;
}
address = strtoul(event.data.scalar.value, &next, 16);
value = strtoul(next, NULL, 16);
// Do not check code types within "repeater data"
if (repeater) {
repeater--;
*list2++ = address;
*list2++ = value;
break;
}
curr_cheat++;
gGSCodes[curr_cheat].count = 0xFFFF; // end of table
gGSCodes[curr_cheat].gscodes = NULL;
gGSCodes[curr_cheat].state = 0;
// Determine destination cheat_list for the code type
switch (address >> 24) {
// Uncessary code types
case 0x20: // Clear code list
case 0xCC: // Exception Handler Selection
case 0xDE: // Entry Point
break;
// Boot-time cheats
case 0xEE: // Disable Expansion Pak
case 0xF0: // 8-bit Boot-Time Write
case 0xF1: // 16-bit Boot-Time Write
case 0xFF: // Cheat Engine Location
*list1++ = address;
*list1++ = value;
break;
// In-game cheats
case 0x50: // Repeater/Patch
// Validate repeater count
if (address & 0x0000FF00) {
repeater = 1;
*list2++ = address;
*list2++ = value;
}
break;
// Everything else
default:
if (!address) {
// TODO: Support special code types! :)
}
// Fall-through!
case 0xD0: // 8-bit Equal-To Conditional
case 0xD1: // 16-bit Equal-To Conditional
case 0xD2: // 8-bit Not-Equal-To Conditional
case 0xD3: // 16-bit Not-Equal-To Conditional
// Validate 16-bit codes
if ((address & 0x01000001) == 0x01000001) {
break;
}
return 0; //ok
*list2++ = address;
*list2++ = value;
break;
}
break;
case YAML_STREAM_END_EVENT:
// And we're outta here!
done = 1;
break;
}
yaml_event_delete(&event);
} while (!done);
// Free
yaml_parser_delete(&parser);
free(cheatfile);
return repeater; // Ok or repeater error
}
void timing(display_context_t disp){
@ -2536,33 +2333,34 @@ void timing(display_context_t disp){
printText(tmp, 3, -1, disp);
}
void bootRom(display_context_t disp, int silent){
if(boot_cic!=0){
if(boot_save!=0){
void bootRom(display_context_t disp, int silent) {
if (boot_cic != 0) {
if (boot_save != 0){
u8 cfg_file[32];
u8 found=0;
u8 resp=0;
u8 tmp[32];
//set cfg file with last loaded cart info and save-type
sprintf(cfg_file, "/ED64/%s/LAST.CRT",save_path);
sprintf(cfg_file, "/ED64/%s/LAST.CRT", save_path);
resp = fatCreateRecIfNotExist(cfg_file, 0);
resp = fatOpenFileByeName(cfg_file, 1); //512 bytes fix one cluster
static uint8_t cfg_file_data[512] = { 0 };
cfg_file_data[0]=boot_save;
cfg_file_data[1]=boot_cic;
scopy(rom_filename, cfg_file_data+2);
cfg_file_data[0] = boot_save;
cfg_file_data[1] = boot_cic;
scopy(rom_filename, cfg_file_data + 2);
fatWriteFile(&cfg_file_data, 1);
sleep(500);
//set the fpga cart-save tpye
//set the fpga cart-save type
evd_setSaveType(boot_save);
if (debug) printText("try to restore save from sd", 3, -1, disp);
if (debug) {
printText("try to restore save from sd", 3, -1, disp);
}
resp = saveTypeFromSd(disp, rom_filename, boot_save);
if (debug) {
@ -2583,43 +2381,35 @@ void bootRom(display_context_t disp, int silent){
cart = info >> 16;
country = (info >> 8) & 0xFF;
if(cheats_on){
gCheats=1;
u32 *cheat_lists[2] = { NULL, NULL };
if (cheats_on) {
gCheats = 1;
printText("try to load cheat-file...", 3, -1, disp);
char cheat_filename[64];
sprintf(cheat_filename,"/ED64/CHEATS/%s.cht",rom_filename);
sprintf(cheat_filename, "/ED64/CHEATS/%s.yml", rom_filename);
int ok = readCheatFile(cheat_filename);
if(ok==0) {
if(!silent)
int ok = readCheatFile(cheat_filename, cheat_lists);
if (ok == 0) {
printText("cheats found...", 3, -1, disp);
sleep(600);
}
else {
if(!silent)
printText("cheats not found...", 3, -1, disp);
gCheats=0;
sleep(2000);
gCheats = 0;
}
}
else {
gCheats=0;
gCheats = 0;
}
disable_interrupts();
if(!silent){
if(gCheats)
printText("cheat boot", 3, -1, disp);
else
printText("normal boot", 3, -1, disp);
}
int bios_cic=getCicType(1);
int bios_cic = getCicType(1);
if(checksum_fix_on)
if (checksum_fix_on) {
checksum_sdram();
}
evd_lockRegs();
sleep(1000);
@ -2630,7 +2420,7 @@ void bootRom(display_context_t disp, int silent){
graphics_fill_screen(disp, 0x000000FF);
display_show(disp);
simulate_boot(boot_cic, bios_cic); // boot_cic
simulate_boot(boot_cic, bios_cic, cheat_lists); // boot_cic
}
}
@ -4176,13 +3966,17 @@ int main(void) {
drawBoxNumber(disp,2);
display_show(disp);
printText("About: ", 9, 9, disp);
printText("About: ", 9, 8, disp);
printText(" ", 9, -1, disp);
printText("ALT64: v0.1.8.6", 9, -1, disp);
printText("ALT64: v0.1.8.6-cheat", 9, -1, disp);
printText("by saturnu", 9, -1, disp);
printText(" ", 9, -1, disp);
printText("Code engine by:", 9, -1, disp);
printText("Jay Oster", 9, -1, disp);
printText(" ", 9, -1, disp);
printText("thanks to:", 9, -1, disp);
printText("Krikzz", 9, -1, disp);
printText("Richard Weick", 9, -1, disp);
printText("ChillyWilly", 9, -1, disp);
printText("ShaunTaylor", 9, -1, disp);
printText("Conle", 9, -1, disp);

21
menu.h
View File

@ -25,7 +25,7 @@ void dma_read_s(void * ram_address, unsigned long pi_address, unsigned long len)
void readSDcard(display_context_t disp, char *directory);
int readConfigFile(void);
//void readCheatFile(display_context_t disp);
int readCheatFile(char *filename);
int readCheatFile(char *filename, u32 *cheat_lists[2]);
static int configHandler(void* user, const char* section, const char* name, const char* value);
int saveTypeToSd(display_context_t disp, char* save_filename ,int tpye);
int saveTypeFromSd(display_context_t disp, char* rom_name, int stype);
@ -87,22 +87,3 @@ void drawRomConfigBox(display_context_t disp,int line);
* @return An aligned address guaranteed to be >= the unaligned address
*/
#define ALIGN_16BYTE(x) ((void *)(((uint32_t)(x)+15) & 0xFFFFFFF0))

1308
utils.c

File diff suppressed because it is too large Load Diff

44
utils.h
View File

@ -31,6 +31,8 @@
0040h - 0FFFh (1008 dwords): Boot code
*/
#define DP_BASE_REG 0x04100000
#define VI_BASE_REG 0x04400000
#define PI_BASE_REG 0x04600000
#define PIF_RAM_START 0x1FC007C0
@ -92,6 +94,29 @@
#define PI_STATUS_IO_BUSY 0x02
#define PI_STATUS_DMA_BUSY 0x01
#define DPC_START (DP_BASE_REG + 0x00)
#define DPC_END (DP_BASE_REG + 0x04)
#define DPC_CURRENT (DP_BASE_REG + 0x08)
#define DPC_STATUS (DP_BASE_REG + 0x0C)
#define DPC_CLOCK (DP_BASE_REG + 0x10)
#define DPC_BUFBUSY (DP_BASE_REG + 0x14)
#define DPC_PIPEBUSY (DP_BASE_REG + 0x18)
#define DPC_TMEM (DP_BASE_REG + 0x1C)
#define VI_CONTROL (VI_BASE_REG + 0x00)
#define VI_FRAMEBUFFER (VI_BASE_REG + 0x04)
#define VI_WIDTH (VI_BASE_REG + 0x08)
#define VI_V_INT (VI_BASE_REG + 0x0C)
#define VI_CUR_LINE (VI_BASE_REG + 0x10)
#define VI_TIMING (VI_BASE_REG + 0x14)
#define VI_V_SYNC (VI_BASE_REG + 0x18)
#define VI_H_SYNC (VI_BASE_REG + 0x1C)
#define VI_H_SYNC2 (VI_BASE_REG + 0x20)
#define VI_H_LIMITS (VI_BASE_REG + 0x24)
#define VI_COLOR_BURST (VI_BASE_REG + 0x28)
#define VI_H_SCALE (VI_BASE_REG + 0x2C)
#define VI_VSCALE (VI_BASE_REG + 0x30)
#define PHYS_TO_K0(x) ((u32)(x)|0x80000000) /* physical to kseg0 */
#define K0_TO_PHYS(x) ((u32)(x)&0x1FFFFFFF) /* kseg0 to physical */
#define PHYS_TO_K1(x) ((u32)(x)|0xA0000000) /* physical to kseg1 */
@ -128,6 +153,22 @@
#define CIC_6105 5
#define CIC_6106 6
#if !defined(MIN)
#define MIN(a, b) ({ \
__typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; \
})
#endif
#if !defined(MAX)
#define MAX(a, b) ({ \
__typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; \
})
#endif
sprite_t *loadImage32DFS(char *fname);
sprite_t *loadImageDFS(char *fname);
sprite_t *loadImage32(u8 *tbuf, int size);
@ -142,8 +183,7 @@ void swap_header(unsigned char* header, int loadlength);
void restoreTiming(void);
void simulate_boot(u32 boot_cic, u8 bios_cic);
void globalTest(void);
void simulate_boot(u32 boot_cic, u8 bios_cic, u32 *cheat_list[2]);
u8 getCicType(u8 bios_cic);