summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--cards.c73
1 files changed, 44 insertions, 29 deletions
diff --git a/cards.c b/cards.c
index dac93fe..c6403b9 100644
--- a/cards.c
+++ b/cards.c
@@ -143,32 +143,11 @@ static int setBlackBorders(struct Cards *cards) {
 	return 0;
 }
 
-struct Cards *Cards_Load(SDL_RWops *rw, enum Cards_Flags flags) {
-	struct Cards *cards = calloc(1, sizeof(*cards));
-	if (!cards) {
-		SDL_SetError("calloc error: %s", strerror(errno));
-		return NULL;
-	}
-
-	if (SDL_RWseek(rw, 0, RW_SEEK_SET) < 0) goto fail;
-	if (SDL_ReadU8(rw) != 'M' || SDL_ReadU8(rw) != 'Z') {
-		SDL_SetError("invalid MZ signature");
-		goto fail;
-	}
-
-	if (SDL_RWseek(rw, 0x3C, RW_SEEK_SET) < 0) goto fail;
-	Uint16 neOffset = SDL_ReadLE16(rw);
-
-	if (SDL_RWseek(rw, neOffset, RW_SEEK_SET) < 0) goto fail;
-	if (SDL_ReadU8(rw) != 'N' || SDL_ReadU8(rw) != 'E') {
-		SDL_SetError("invalid NE signature");
-		goto fail;
-	}
-
-	if (SDL_RWseek(rw, neOffset + 0x24, RW_SEEK_SET) < 0) goto fail;
+static int loadNE(struct Cards *cards, SDL_RWops *rw, Uint16 neOffset) {
+	if (SDL_RWseek(rw, neOffset + 0x24, RW_SEEK_SET) < 0) return -1;
 	Uint16 resourceTableOffset = neOffset + SDL_ReadLE16(rw);
 
-	if (SDL_RWseek(rw, resourceTableOffset, RW_SEEK_SET) < 0) goto fail;
+	if (SDL_RWseek(rw, resourceTableOffset, RW_SEEK_SET) < 0) return -1;
 	Uint16 alignmentShift = SDL_ReadLE16(rw);
 
 	Uint16 resourceCount;
@@ -179,11 +158,11 @@ struct Cards *Cards_Load(SDL_RWops *rw, enum Cards_Flags flags) {
 
 		if (!typeID) {
 			SDL_SetError("no bitmap resources");
-			goto fail;
+			return -1;
 		}
 		if (typeID == 0x8002) break;
 
-		if (SDL_RWseek(rw, 0x0C * resourceCount, RW_SEEK_CUR) < 0) goto fail;
+		if (SDL_RWseek(rw, 0x0C * resourceCount, RW_SEEK_CUR) < 0) return -1;
 	}
 
 	for (Uint16 i = 0; i < resourceCount; ++i) {
@@ -197,16 +176,52 @@ struct Cards *Cards_Load(SDL_RWops *rw, enum Cards_Flags flags) {
 		if (id >= Cards_Count) continue;
 
 		Sint64 next = SDL_RWtell(rw);
-		if (next < 0) goto fail;
+		if (next < 0) return -1;
 
 		cards->surfaces[id] = dibSurface(
 			rw,
 			(Uint32)offset << alignmentShift,
 			(Uint32)length << alignmentShift
 		);
-		if (!cards->surfaces[id]) goto fail;
+		if (!cards->surfaces[id]) return -1;
+
+		if (SDL_RWseek(rw, next, RW_SEEK_SET) < 0) return -1;
+	}
+
+	return 0;
+}
 
-		if (SDL_RWseek(rw, next, RW_SEEK_SET) < 0) goto fail;
+static int loadPE(struct Cards *cards, SDL_RWops *rw, Uint16 peOffset) {
+	SDL_SetError("loadPE unimplemented");
+	return -1;
+}
+
+struct Cards *Cards_Load(SDL_RWops *rw, enum Cards_Flags flags) {
+	struct Cards *cards = calloc(1, sizeof(*cards));
+	if (!cards) {
+		SDL_SetError("calloc error: %s", strerror(errno));
+		return NULL;
+	}
+
+	if (SDL_RWseek(rw, 0, RW_SEEK_SET) < 0) goto fail;
+	if (SDL_ReadU8(rw) != 'M' || SDL_ReadU8(rw) != 'Z') {
+		SDL_SetError("invalid MZ signature");
+		goto fail;
+	}
+
+	if (SDL_RWseek(rw, 0x3C, RW_SEEK_SET) < 0) goto fail;
+	Uint16 offset = SDL_ReadLE16(rw);
+
+	if (SDL_RWseek(rw, offset, RW_SEEK_SET) < 0) goto fail;
+	Uint8 sig[] = { SDL_ReadU8(rw), SDL_ReadU8(rw) };
+
+	if (sig[0] == 'N' && sig[1] == 'E') {
+		if (loadNE(cards, rw, offset) < 0) goto fail;
+	} else if (sig[0] == 'P' && sig[1] == 'E') {
+		if (loadPE(cards, rw, offset) < 0) goto fail;
+	} else {
+		SDL_SetError("invalid NE/PE signature");
+		goto fail;
 	}
 
 	for (int i = Cards_Club + Cards_A; i <= Cards_Spade + Cards_K; ++i) {