about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--cards.c26
1 files changed, 18 insertions, 8 deletions
diff --git a/cards.c b/cards.c
index 9e92aa9..ddc5b86 100644
--- a/cards.c
+++ b/cards.c
@@ -84,7 +84,10 @@ fail:
 
 // exefmt.txt
 static int
-loadNE(SDL_Surface **surfaces, size_t count, SDL_RWops *rw, Uint16 neOffset) {
+loadNE(
+	SDL_Surface **surfaces, size_t count,
+	SDL_RWops *rw, Uint16 neOffset, Uint32 idSkip
+) {
 	if (SDL_RWseek(rw, neOffset + 0x24, RW_SEEK_SET) < 0) return -1;
 	Uint16 resourceTableOffset = neOffset + SDL_ReadLE16(rw);
 
@@ -114,6 +117,7 @@ loadNE(SDL_Surface **surfaces, size_t count, SDL_RWops *rw, Uint16 neOffset) {
 		SDL_ReadLE32(rw); // reserved
 
 		resourceID &= 0x7FFF;
+		if (resourceID >= idSkip) resourceID -= idSkip;
 		if (resourceID >= count) continue;
 
 		Sint64 nextResource = SDL_RWtell(rw);
@@ -134,7 +138,10 @@ loadNE(SDL_Surface **surfaces, size_t count, SDL_RWops *rw, Uint16 neOffset) {
 
 // <https://docs.microsoft.com/en-us/windows/desktop/Debug/pe-format>
 static int
-loadPE(SDL_Surface **surfaces, size_t count, SDL_RWops *rw, Uint16 peOffset) {
+loadPE(
+	SDL_Surface **surfaces, size_t count,
+	SDL_RWops *rw, Uint16 peOffset, Uint32 idSkip
+) {
 	if (SDL_RWseek(rw, peOffset + 0x04 + 0x02, RW_SEEK_SET) < 0) return -1;
 	Uint16 sectionCount = SDL_ReadLE16(rw);
 
@@ -192,8 +199,10 @@ loadPE(SDL_Surface **surfaces, size_t count, SDL_RWops *rw, Uint16 peOffset) {
 
 	for (Uint16 i = 0; i < nameIDCount; ++i) {
 		Uint32 nameID = SDL_ReadLE32(rw);
-		Uint32 subdirOffset = SDL_ReadLE32(rw);
+		if (nameID >= idSkip) nameID -= idSkip;
 		if (nameID >= count) continue;
+
+		Uint32 subdirOffset = SDL_ReadLE32(rw);
 		if (!(subdirOffset & (1 << 31))) {
 			SDL_SetError("bitmap name entry does not point to table");
 			return -1;
@@ -236,7 +245,8 @@ loadPE(SDL_Surface **surfaces, size_t count, SDL_RWops *rw, Uint16 peOffset) {
 	return 0;
 }
 
-static int loadEXE(SDL_Surface **surfaces, size_t count, SDL_RWops *rw) {
+static int
+loadEXE(SDL_Surface **surfaces, size_t count, SDL_RWops *rw, Uint32 idSkip) {
 	if (SDL_RWseek(rw, 0, RW_SEEK_SET) < 0) return -1;
 	if (SDL_ReadU8(rw) != 'M' || SDL_ReadU8(rw) != 'Z') {
 		SDL_SetError("invalid MZ signature");
@@ -250,9 +260,9 @@ static int loadEXE(SDL_Surface **surfaces, size_t count, SDL_RWops *rw) {
 	Uint8 sig[2] = { SDL_ReadU8(rw), SDL_ReadU8(rw) };
 
 	if (sig[0] == 'N' && sig[1] == 'E') {
-		return loadNE(surfaces, count, rw, offset);
+		return loadNE(surfaces, count, rw, offset, idSkip);
 	} else if (sig[0] == 'P' && sig[1] == 'E') {
-		return loadPE(surfaces, count, rw, offset);
+		return loadPE(surfaces, count, rw, offset, idSkip);
 	} else {
 		SDL_SetError("invalid NE/PE signature");
 		return -1;
@@ -341,7 +351,7 @@ Cards_LoadCards(
 	SDL_RWops *rw, enum Cards_Flag flags
 ) {
 	memset(surfaces, 0, sizeof(*surfaces) * count);
-	if (loadEXE(surfaces, count, rw) < 0) return -1;
+	if (loadEXE(surfaces, count, rw, 0) < 0) return -1;
 	if (checkRange(surfaces, count, Cards_A, Cards_Back12) < 0) return -1;
 	if (checkRange(surfaces, count, Cards_X, Cards_O) < 0) return -1;
 	if (flags & Cards_ColorKey) {
@@ -362,7 +372,7 @@ Cards_LoadFreeCell(
 	SDL_RWops *rw, enum Cards_Flag flags
 ) {
 	memset(surfaces, 0, sizeof(*surfaces) * count);
-	if (loadEXE(surfaces, count, rw) < 0) return -1;
+	if (loadEXE(surfaces, count, rw, 402) < 0) return -1;
 	if (checkRange(surfaces, count, Cards_KingRight, Cards_KingWin) < 0) {
 		return -1;
 	}