bucanero / apollo-lib Goto Github PK
View Code? Open in Web Editor NEWHome Page: http://www.bucanero.com.ar/
License: GNU General Public License v3.0
Home Page: http://www.bucanero.com.ar/
License: GNU General Public License v3.0
custom decryption and hashing code assumes a big-endian platform. This should be addressed to be platform-independent.
I noticed an issue with Code Type D on Windows 11.
When using multiple Lines of code to skip if test fails
and inserting a final new line
at the end of the .savepatch
file, the patch breaks and is not applied at all.
Update:
The issue only occurs if End of Line
of the file is set to Windows (CRLF)
. If set to Unix (LF)
the patch is applied.
This line breaks the patch when skipping 02 lines:
D8000000 020130FF
Using this code:
[Isz Glitch Cure]
80010004 07001300 - Searches for 4 bytes of 07 00 13 00 once using Default Offset
92000000 00000DB3 - Adjusts the pointer offset by adding a value of 338 + 3169 = 3507 dec = DB3 hex to the pointer
D8000000 020130FF - Tests if 2 bytes from pointer not equal `FF 30`, skips the following two code lines if operation fails
D8000000 0103C0FF - Tests if 2 bytes from pointer equal less than `FF C0`, skips the following code line if operation fails
08000001 00000030 - Writes 1 byte with 1 offset from pointer, replacing a value less than `C0` with `30` (partial Isz glitch fix)
D8000000 0100C0FF - Tests if 2 bytes from pointer equal `FF C0`, skips the following code line if operation fails
08000001 000000FF - Writes 1 byte with 1 offset from pointer, replacing `C0` with `FF` (fully maxed out Isz glitch fix)
Without final newline every operation is performed successfully, in every condition:
D:\PS4\quick-code-test\3>patcher userdata0000.savepatch 1 userdata0000
Apollo cheat patcher v0.6.0 - (c) 2022 by Bucanero
[i] Applying codes [1] to userdata0000...
[+] Applying code #1...
- Game Genie Code
- Applying [Isz Glitch Cure] to 'userdata0000'...
- Searching (len=4 count=1) ...
- ----- Search 4 bytes -----
- 000000: 07 00 13 00 | ....
- ----- Search 4 bytes -----
- Search pointer = 152750 (0x254AE)
- Pointer set to offset 0x26261 (156257)
- Byte Test (00026261) C0FF != 30FF
- Byte Test (00026261) C0FF < C0FF
- Skipping 1 lines...
- Byte Test (00026261) C0FF = C0FF
- Wrote 1 bytes (FF) to 0x26262
- OK
Patching completed: 1 codes applied
With a final newline it does not apply the patch and outputs:
Apollo cheat patcher v0.6.0 - (c) 2022 by Bucanero
[i] Applying codes [1] to userdata0000...
[+] Applying code #1...
- Bruteforce Save Data Code
- Applying [Isz Glitch Cure] to 'userdata0000'...
- OK
Patching completed: 1 codes applied
Here you can get the savegame and patch:
userdata0000.zip
bug was introduced when adding support for little-endian in #9
Based on user feedback and details from @aldostools , MD5_XOR needs to be stored/written in little-endian to match the original BSD definition.
There are some SaveWizard (ps4) code types that are not supported and could be added to apollo-lib
See detailed information by Dynamite: https://playersquared.com/forums/81-save-wizard-quick-codes/3012-save-wizard-custom-quick-code-formats.html
Save Wizard Custom Quick Code Formats.pdf
Missing types:
Incomplete:
Conflicts:
@bucanero
I just noticed that code type C does not work like how SW has implemented it in your build.
this is for operations 0 & 8.
I noticed this when I was writing an experimental code for death stranding
this is the code I'm just using to write the string --TEST--
8001000A D5988217
05F1C489 55290000
C8250029 00000071
A8000029 00000008
2D2D5445 53542D2D
now your's stops on the 37'th search result, however when running it via SW it stops on the 38th result.
which is intended.
I think you misunderstood how C works, for code type C when doing C0
or C8
It doesn’t include the reference bytes its using as a search result.
what I mean by "reference bytes" I mean the bytes it is told to search with from the address.
so the 1st search result should match the 2nd set of bytes it finds not the 1st set that's included at the address of where it grabs the bytes that it needs to search with.
here is a test code I used for apollo & SW on a test save to show you the difference:
8001000A D5988217
05F1C489 55290000
C8010029 00000071
A8000029 00000008
2D2D5445 53542D2D
same code not modified, yours edits the 1st result which is wrong, SW edits the 2nd result which is what the 1st result is in this case.
Code Type C DS Saves Test.zip
so for operations 0 & 8, set it so it ignores the result from the pointer or addresses it's grabbing the bytes to search with. (it should not match itself.)
Operators C4
& CC
are working as intended (the search ends at the address/pointer)
Checksum, encryption, and offzip methods should be exported too, as part of the apollo.h
library header
See https://github.com/HackerSmacker/CSave/blob/master/FileTranslator.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "FileTranslator.h"
size_t read_buffer(int max_length, uint8_t* out, FILE* f) {
size_t cur_len = 0;
size_t nread;
while ((nread = fread(out + cur_len, 1, max_length - cur_len, f)) != 0) {
cur_len += nread;
if (cur_len == max_length) {
fprintf(stderr, "CSAVAB100B Buffer exceeded!\n");
exit(1);
}
}
return cur_len;
}
char PrefixMagic[] = {
0x71, 0x34, 0x36, 0xB3, 0x56, 0x63, 0x25, 0x5F,
0xEA, 0xE2, 0x83, 0x73, 0xF4, 0x98, 0xB8, 0x18,
0x2E, 0xE5, 0x42, 0x2E, 0x50, 0xA2, 0x0F, 0x49,
0x87, 0x24, 0xE6, 0x65, 0x9A, 0xF0, 0x7C, 0xD7
};
char XorMagic[] = {
0x7C, 0x07, 0x69, 0x83, 0x31, 0x7E, 0x0C, 0x82,
0x5F, 0x2E, 0x36, 0x7F, 0x76, 0xB4, 0xA2, 0x71,
0x38, 0x2B, 0x6E, 0x87, 0x39, 0x05, 0x02, 0xC6,
0xCD, 0xD8, 0xB1, 0xCC, 0xA1, 0x33, 0xF9, 0xB6
};
char ProfilePrefixMagic[] = {
0xD8, 0x04, 0xB9, 0x08, 0x5C, 0x4E, 0x2B, 0xC0,
0x61, 0x9F, 0x7C, 0x8D, 0x5D, 0x34, 0x00, 0x56,
0xE7, 0x7B, 0x4E, 0xC0, 0xA4, 0xD6, 0xA7, 0x01,
0x14, 0x15, 0xA9, 0x93, 0x1F, 0x27, 0x2C, 0x8F
};
char ProfileXorMagic[] = {
0xE8, 0xDC, 0x3A, 0x66, 0xF7, 0xEF, 0x85, 0xE0,
0xBD, 0x4A, 0xA9, 0x73, 0x57, 0x99, 0x30, 0x8C,
0x94, 0x63, 0x59, 0xA8, 0xC9, 0xAE, 0xD9, 0x58,
0x7D, 0x51, 0xB0, 0x1E, 0xBE, 0xD0, 0x77, 0x43
};
char ProfilePrefixMagic_PS4[] = {
0xad, 0x1e, 0x60, 0x4e, 0x42, 0x9e, 0xa9, 0x33, 0xb2, 0xf5, 0x01, 0xe1, 0x02, 0x4d, 0x08, 0x75,
0xb1, 0xad, 0x1a, 0x3d, 0xa1, 0x03, 0x6b, 0x1a, 0x17, 0xe6, 0xec, 0x0f, 0x60, 0x8d, 0xb4, 0xf9
};
char ProfileXorMagic_PS4[] = {
0xba, 0x0e, 0x86, 0x1d, 0x58, 0xe1, 0x92, 0x21, 0x30, 0xd6, 0xcb, 0xf0, 0xd0, 0x82, 0xd5, 0x58,
0x36, 0x12, 0xe1, 0xf6, 0x39, 0x44, 0x88, 0xea, 0x4e, 0xfb, 0x04, 0x74, 0x07, 0x95, 0x3a, 0xa2
};
char PrefixMagic_PS4[] = {
0xd1, 0x7b, 0xbf, 0x75, 0x4c, 0xc1, 0x80, 0x30, 0x37, 0x92, 0xbd, 0xd0, 0x18, 0x3e, 0x4a, 0x5f, 0x43,
0xa2, 0x46, 0xa0, 0xed, 0xdb, 0x2d, 0x9f, 0x56, 0x5f, 0x8b, 0x3d, 0x6e, 0x73, 0xe6, 0xb8
};
char XorMagic_PS4[] = {
0xfb, 0xfd, 0xfd, 0x51, 0x3a, 0x5c, 0xdb, 0x20, 0xbb, 0x5e, 0xc7, 0xaf, 0x66, 0x6f, 0xb6, 0x9a, 0x9a,
0x52, 0x67, 0x0f, 0x19, 0x5d, 0xd3, 0x84, 0x15, 0x19, 0xc9, 0x4a, 0x79, 0x67, 0xda, 0x6d
};
size_t decryptSave(uint8_t* buffer, int offset, int length) {
int i;
char b;
for(i = length - 1; i >= 0; i--) {
if(i < 32) {
b = PrefixMagic[i];
}
else {
b = buffer[i - 32];
}
b ^= XorMagic[i % 32];
buffer[i] ^= b;
}
return length;
}
size_t encryptSave(uint8_t* buffer, int offset, int length) {
int i;
char b;
for(i = 0; i < length; i++) {
if(i < 32) {
b = PrefixMagic[i];
}
else {
b = buffer[i - 32];
}
b ^= XorMagic[i % 32];
buffer[i] ^= b;
}
return length;
}
size_t decryptProfile(uint8_t* buffer, int offset, int length) {
int i;
char b;
for(i = length - 1; i >= 0; i--) {
if(i < 32) {
b = ProfilePrefixMagic[i];
}
else {
b = buffer[i - 32];
}
b ^= ProfileXorMagic[i % 32];
buffer[i] ^= b;
}
return length;
}
size_t encryptProfile(uint8_t* buffer, int offset, int length) {
int i;
char b;
for(i = 0; i < length; i++) {
if(i < 32) {
b = ProfilePrefixMagic[i];
}
else {
b = buffer[i - 32];
}
b ^= ProfileXorMagic[i % 32];
buffer[i] ^= b;
}
return length;
}
size_t decryptSave_PS4(uint8_t* buffer, int offset, int length) {
int i;
char b;
for(i = length - 1; i >= 0; i--) {
if(i < 32) {
b = PrefixMagic_PS4[i];
}
else {
b = buffer[i - 32];
}
b ^= XorMagic_PS4[i % 32];
buffer[i] ^= b;
}
return length;
}
size_t encryptSave_PS4(uint8_t* buffer, int offset, int length) {
int i;
char b;
for(i = 0; i < length; i++) {
if(i < 32) {
b = PrefixMagic_PS4[i];
}
else {
b = buffer[i - 32];
}
b ^= XorMagic_PS4[i % 32];
buffer[i] ^= b;
}
return length;
}
size_t decryptProfile_PS4(uint8_t* buffer, int offset, int length) {
int i;
char b;
for(i = length - 1; i >= 0; i--) {
if(i < 32) {
b = ProfilePrefixMagic_PS4[i];
}
else {
b = buffer[i - 32];
}
b ^= ProfileXorMagic_PS4[i % 32];
buffer[i] ^= b;
}
return length;
}
size_t encryptProfile_PS4(uint8_t* buffer, int offset, int length) {
int i;
char b;
for(i = 0; i < length; i++) {
if(i < 32) {
b = ProfilePrefixMagic_PS4[i];
}
else {
b = buffer[i - 32];
}
b ^= ProfileXorMagic_PS4[i % 32];
buffer[i] ^= b;
}
return length;
}
// KLUDGE TO GET THIS TO COMPILE WITH THE WATCOM C COMPILER
struct Save save_t;
struct keyValuePair* kvp_t;
int payloadStart;
int processedLen;
void readSave(FILE* file, int fileType) {
int i;
printf("CSAV001RWS Reading file...\n");
// The actual save.
// Read it byte by byte.
save_t.header = malloc(4);
fread(save_t.header, sizeof(char), 4, file);
fread(&save_t.sg_version, sizeof(int32_t), 1, file);
fread(&save_t.pkg_version, sizeof(int32_t), 1, file);
fread(&save_t.engine_major, sizeof(int16_t), 1, file);
fread(&save_t.engine_minor, sizeof(int16_t), 1, file);
fread(&save_t.engine_patch, sizeof(int16_t), 1, file);
fread(&save_t.engine_build, sizeof(uint32_t), 1, file);
fread(&save_t.build_id_length, sizeof(int32_t), 1, file);
save_t.build_id = malloc(save_t.build_id_length);
fread(save_t.build_id, sizeof(char), save_t.build_id_length, file);
fread(&save_t.fmt_version, sizeof(int32_t), 1, file);
fread(&save_t.fmt_count, sizeof(int32_t), 1, file);
kvp_t = malloc(save_t.fmt_count * sizeof(struct keyValuePair));
for(i = 0; i < save_t.fmt_count; i++) {
kvp_t[i].guid = malloc(16);
fread(kvp_t[i].guid, sizeof(char), 16, file);
//printf("%d, ", ftell(file));
fread(&kvp_t[i].entry, sizeof(int32_t), 1, file);
//printf("%d, ", ftell(file));
}
//printf("%d, ", ftell(file));
fread(&save_t.sg_type_len, sizeof(int32_t), 1, file);
save_t.sg_type = malloc(save_t.sg_type_len);
fread(save_t.sg_type, sizeof(char), save_t.sg_type_len, file);
fread(&save_t.remaining_data_len, sizeof(int32_t), 1, file);
payloadStart = ftell(file);
save_t.remaining_data = malloc(save_t.remaining_data_len);
fread(save_t.remaining_data, sizeof(char), save_t.remaining_data_len, file);
printf("CSAV001RWS Save information:\n");
printf("Header: %s\n", save_t.header);
printf("SG version: %d\n", save_t.sg_version);
printf("Package version: %d\n", save_t.pkg_version);
printf("Engine version: %d.%d.%d\n", save_t.engine_major, save_t.engine_minor, save_t.engine_patch);
printf("Build ID length: %d\n", save_t.build_id_length);
printf("Build ID: %s\n", save_t.build_id);
printf("Custom format version: %d\n", save_t.fmt_version);
printf("Custom format count: %d\n", save_t.fmt_count);
//for(i = 0; i < save_t.fmt_count; i++) {
// printf("Custom format %d: GUID: %x, entry %d\n", i, kvp_t[i].guid, kvp_t[i].entry);
//}
printf("Save type length: %d\n", save_t.sg_type_len);
printf("Save type: %s\n", save_t.sg_type);
printf("Payload start position: %d\n", payloadStart);
printf("Payload length: %d\n", save_t.remaining_data_len);
if(fileType == 1) {
processedLen = decryptSave(save_t.remaining_data, 0, save_t.remaining_data_len);
}
else if(fileType == 2) {
processedLen = decryptProfile(save_t.remaining_data, 0, save_t.remaining_data_len);
}
else if(fileType == 3) {
processedLen = decryptSave_PS4(save_t.remaining_data, 0, save_t.remaining_data_len);
}
else if(fileType == 4) {
processedLen = decryptProfile_PS4(save_t.remaining_data, 0, save_t.remaining_data_len);
}
}
void writeSave(FILE* file, FILE* outFile, char* data, int32_t dataLen, int fileType) {
int i;
// 1. Load in an existing file as a template
printf("CSAV001RWS Loading existing file...\n");
save_t.header = malloc(4);
fread(save_t.header, sizeof(char), 4, file);
fread(&save_t.sg_version, sizeof(int32_t), 1, file);
fread(&save_t.pkg_version, sizeof(int32_t), 1, file);
fread(&save_t.engine_major, sizeof(int16_t), 1, file);
fread(&save_t.engine_minor, sizeof(int16_t), 1, file);
fread(&save_t.engine_patch, sizeof(int16_t), 1, file);
fread(&save_t.engine_build, sizeof(uint32_t), 1, file);
fread(&save_t.build_id_length, sizeof(int32_t), 1, file);
save_t.build_id = malloc(save_t.build_id_length);
fread(save_t.build_id, sizeof(char), save_t.build_id_length, file);
fread(&save_t.fmt_version, sizeof(int32_t), 1, file);
fread(&save_t.fmt_count, sizeof(int32_t), 1, file);
kvp_t = malloc(save_t.fmt_count * sizeof(struct keyValuePair));
for(i = 0; i < save_t.fmt_count; i++) {
kvp_t[i].guid = malloc(16);
fread(kvp_t[i].guid, sizeof(char), 16, file);
fread(&kvp_t[i].entry, sizeof(int32_t), 1, file);
}
fread(&save_t.sg_type_len, sizeof(int32_t), 1, file);
save_t.sg_type = malloc(save_t.sg_type_len);
fread(save_t.sg_type, sizeof(char), save_t.sg_type_len, file);
fread(&save_t.remaining_data_len, sizeof(int32_t), 1, file);
payloadStart = ftell(file);
save_t.remaining_data = malloc(save_t.remaining_data_len);
fread(save_t.remaining_data, sizeof(char), save_t.remaining_data_len, file);
// 3. Encrypt it
if(fileType == 1) {
processedLen = encryptSave(data, 0, dataLen);
}
else if(fileType == 2) {
processedLen = encryptProfile(data, 0, dataLen);
}
else if(fileType == 3) {
processedLen = encryptSave_PS4(data, 0, dataLen);
}
else if(fileType == 4) {
processedLen = encryptProfile_PS4(data, 0, dataLen);
}
//printf("CSAV001RWS Encrypted payload length: %d\n", processedLen);
printf("CSAV001RWS Original save information:\n");
printf("Header: %s\n", save_t.header);
printf("SG version: %d\n", save_t.sg_version);
printf("Package version: %d\n", save_t.pkg_version);
printf("Engine version: %d.%d.%d\n", save_t.engine_major, save_t.engine_minor, save_t.engine_patch);
printf("Build ID length: %d\n", save_t.build_id_length);
printf("Build ID: %s\n", save_t.build_id);
printf("Custom format version: %d\n", save_t.fmt_version);
printf("Custom format count: %d\n", save_t.fmt_count);
//for(i = 0; i < save_t.fmt_count; i++) {
// printf("Custom format %d: GUID: %x, entry %d\n", i, kvp_t[i].guid, kvp_t[i].entry);
//}
printf("Save type length: %d\n", save_t.sg_type_len);
printf("Save type: %s\n", save_t.sg_type);
printf("Payload start position: %d\n", payloadStart);
printf("Payload length: %d\n", save_t.remaining_data_len);
// 4. Crank it out to a file and hope for the best! Protip: It's not the best!
printf("CSAV001CNV Writing new file...\n");
fwrite(save_t.header, sizeof(char), 4, outFile);
fwrite(&save_t.sg_version, sizeof(int32_t), 1, outFile);
fwrite(&save_t.pkg_version, sizeof(int32_t), 1, outFile);
fwrite(&save_t.engine_major, sizeof(int16_t), 1, outFile);
fwrite(&save_t.engine_minor, sizeof(int16_t), 1, outFile);
fwrite(&save_t.engine_patch, sizeof(int16_t), 1, outFile);
fwrite(&save_t.engine_build, sizeof(uint32_t), 1, outFile);
fwrite(&save_t.build_id_length, sizeof(int32_t), 1, outFile);
fwrite(save_t.build_id, sizeof(char), save_t.build_id_length, outFile);
fwrite(&save_t.fmt_version, sizeof(int32_t), 1, outFile);
fwrite(&save_t.fmt_count, sizeof(int32_t), 1, outFile);
for(i = 0; i < save_t.fmt_count; i++) {
fwrite(kvp_t[i].guid, sizeof(char), 16, outFile);
fwrite(&kvp_t[i].entry, sizeof(int32_t), 1, outFile);
}
fwrite(&save_t.sg_type_len, sizeof(int32_t), 1, outFile);
fwrite(save_t.sg_type, sizeof(char), save_t.sg_type_len, outFile);
fwrite(&dataLen, sizeof(int32_t), 1, outFile);
fwrite(data, sizeof(char), dataLen, outFile);
}
void readSaveHeader(FILE* file) {
int i;
printf("CSAV001RWS Reading file...\n");
// The actual save.
// Read it byte by byte.
save_t.header = malloc(4);
fread(save_t.header, sizeof(char), 4, file);
fread(&save_t.sg_version, sizeof(int32_t), 1, file);
fread(&save_t.pkg_version, sizeof(int32_t), 1, file);
fread(&save_t.engine_major, sizeof(int16_t), 1, file);
fread(&save_t.engine_minor, sizeof(int16_t), 1, file);
fread(&save_t.engine_patch, sizeof(int16_t), 1, file);
fread(&save_t.engine_build, sizeof(uint32_t), 1, file);
fread(&save_t.build_id_length, sizeof(int32_t), 1, file);
save_t.build_id = malloc(save_t.build_id_length);
fread(save_t.build_id, sizeof(char), save_t.build_id_length, file);
fread(&save_t.fmt_version, sizeof(int32_t), 1, file);
fread(&save_t.fmt_count, sizeof(int32_t), 1, file);
kvp_t = malloc(save_t.fmt_count * sizeof(struct keyValuePair));
for(i = 0; i < save_t.fmt_count; i++) {
kvp_t[i].guid = malloc(16);
fread(kvp_t[i].guid, sizeof(char), 16, file);
//printf("%d, ", ftell(file));
fread(&kvp_t[i].entry, sizeof(int32_t), 1, file);
//printf("%d, ", ftell(file));
}
//printf("%d, ", ftell(file));
fread(&save_t.sg_type_len, sizeof(int32_t), 1, file);
save_t.sg_type = malloc(save_t.sg_type_len);
fread(save_t.sg_type, sizeof(char), save_t.sg_type_len, file);
fread(&save_t.remaining_data_len, sizeof(int32_t), 1, file);
payloadStart = ftell(file);
save_t.remaining_data = malloc(save_t.remaining_data_len);
fread(save_t.remaining_data, sizeof(char), save_t.remaining_data_len, file);
printf("CSAV001RWS Save information:\n");
printf("Header: %s\n", save_t.header);
printf("SG version: %d\n", save_t.sg_version);
printf("Package version: %d\n", save_t.pkg_version);
printf("Engine version: %d.%d.%d\n", save_t.engine_major, save_t.engine_minor, save_t.engine_patch);
printf("Build ID length: %d\n", save_t.build_id_length);
printf("Build ID: %s\n", save_t.build_id);
printf("Custom format version: %d\n", save_t.fmt_version);
printf("Custom format count: %d\n", save_t.fmt_count);
//for(i = 0; i < save_t.fmt_count; i++) {
// printf("Custom format %d: GUID: %x, entry %d\n", i, kvp_t[i].guid, kvp_t[i].entry);
//}
printf("Save type length: %d\n", save_t.sg_type_len);
printf("Save type: %s\n", save_t.sg_type);
printf("Payload start position: %d\n", payloadStart);
printf("Payload length: %d\n", save_t.remaining_data_len);
}
Based on updates from https://docs.google.com/spreadsheets/d/1pln64WRA8QhhrW1QBDEn97HEbp4gdvBNd3GnrC4Bg5c/edit#gid=770416068
9Y000000 XXXXXXXX
| Y = Operator
| | D = Set End Address = to X
| | E = Set End Address From Pointer + X
DBYYYYYY CCMMXXXX
| M = Test Operation
| | 10 = 8bit Equal
| | 11 = 8bit Not Equal
| | 12 = 8bit Greater Than (Value at the Address is greater than the tested value)
| | 13 = 8bit Less Than (Value at the Address is less than the tested value)
Hey @bucanero would it be possible to add the option to allow for selecting a set amount of cheats in one go rather than typing every value like this 1,2,3,4,5,6,7,8,9,10
like say, if I wanted all cheats from 5 to 20, I could do 5-20
and all cheats from 5 to 20 would get applied.
since I tend to make long cheat lists or groups with like reset all starts for the 1st 10, next 10 some other values, next 10 other values etc..
so example my current usage: patcher Hades-Stats.savepatch 1,3,5,7,9,11,13,15,17,19,21,23 Profile1.sav
would be nice if I could do patcher Hades-Stats.savepatch 1-23 Profile1.sav
or a combination like this
patcher Hades-Stats.savepatch 1-5,10,20-23 Profile1.sav
just some QOL stuff, would get really annoying with over 100+ cheat list file typing every value with comma's
On PS4, Save Wizard writing codes should write values as little-endian (reversed).
Apollo-PS4 is not handling this properly. (see #1 )
@bucanero
can we have it so it does not fail when it does not find something & simply move onto the next segment of the code block.
[i] Applying codes [1] to GOWRSAVE12...
[+] Applying code bucanero/apollo-ps4#1...
- Game Genie Code
- Applying [Key Items - 2147400000] to 'GOWRSAVE12'...
- Searching (len=8 count=1) ...
- ----- Search 8 bytes -----
- 000000: CB 8B 5C CF C1 7F 4E 15
- ----- Search 8 bytes -----
- SEARCH PATTERN NOT FOUND
- ERROR!
Example:
[Key Items - 2147400000]
80010008 CB8B5CCF
C17F4E15 00000000
28000008 7FFEB940
80010008 3832900B <-- say it fails here (Cant Find)
4A8A614B 00000000 <-- skip
28000008 7FFEB940 <-- skip
80010008 0F293CEC <-- resume here
4D3EDEEE 00000000
28000008 7FFEB940
80010008 28D9B3C5
D702057B 00000000
28000008 7FFEB940
by default SW just skips anything it can't find & moves down the code block & adjusts the save for any matches.
like for all resources codeblock there would be multiple searches one after the other. the player may not have all items for the code to be fully effective. However, it still should match anything it can find and adjust accordingly.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.