mirror of
https://github.com/parasyte/alt64
synced 2024-12-26 09:08:54 -05:00
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:
parent
3ba0910535
commit
90fb4e39a5
4
Makefile
4
Makefile
@ -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
|
||||
|
26
README.md
26
README.md
@ -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
572
menu.c
@ -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
21
menu.h
@ -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))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
44
utils.h
44
utils.h
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user