Code Monkey home page Code Monkey logo

apollo-lib's Introduction

bucanero's GitHub Stats stats

You can ping me on Twitter

apollo-lib's People

Contributors

bucanero avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

illusion0001

apollo-lib's Issues

Proper endian support for custom decryption/hashes

custom decryption and hashing code assumes a big-endian platform. This should be addressed to be platform-independent.

Decrypt

  • silent_hill3
  • FF13
  • mgs_pw

Hashes

  • sha1_xor64
  • ffx_checksum
  • ff13_checksum
  • kh25_checksum

Code Type D skipping multiple line breaks patch

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

Implement missing SaveWizard code types

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:

  • Code Type 3: increase/decrease write
  • Code Type B: Backward Byte Search
  • Code Type C: Address Byte Search
  • Code Type D: 2 Byte Test Commands

Incomplete:

  • Code Type 9: Pointer Manipulator
  • Code Type A: Mass write

Conflicts:

  • Code Type 7: No More / No Less than Write

Code Type C needs to be tweaked

@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)

Add "Borderlands 3" custom save decryption

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);
}

Improve SW types 9, D

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)

Add Range (1-10 etc) Support

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

Improve SW Code Types 8,B,C - move onto the next if match not found

@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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.