From f3236a4fbfbc2129729499b24f4140ade308d9f4 Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Thu, 28 Mar 2019 16:13:35 -0400 Subject: Refactor EXE/DLL loading to be more general In order to load the 3 bitmaps from FREECELL.EXE. --- cards.c | 70 +++++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/cards.c b/cards.c index 29aa7a4..b9153a5 100644 --- a/cards.c +++ b/cards.c @@ -146,7 +146,8 @@ static int setBlackBorders(struct Cards *cards) { } // exefmt.txt -static int loadNE(struct Cards *cards, SDL_RWops *rw, Uint16 neOffset) { +static int +loadNE(SDL_Surface **surfaces, size_t count, SDL_RWops *rw, Uint16 neOffset) { if (SDL_RWseek(rw, neOffset + 0x24, RW_SEEK_SET) < 0) return -1; Uint16 resourceTableOffset = neOffset + SDL_ReadLE16(rw); @@ -169,33 +170,34 @@ static int loadNE(struct Cards *cards, SDL_RWops *rw, Uint16 neOffset) { } for (Uint16 i = 0; i < resourceCount; ++i) { - Uint16 offset = SDL_ReadLE16(rw); - Uint16 length = SDL_ReadLE16(rw); + Uint16 dataOffset = SDL_ReadLE16(rw); + Uint16 dataLength = SDL_ReadLE16(rw); /* Uint16 flags = */ SDL_ReadLE16(rw); - Uint16 id = SDL_ReadLE16(rw); + Uint16 resourceID = SDL_ReadLE16(rw); SDL_ReadLE32(rw); // reserved - id &= 0x7FFF; - if (id >= Cards_Count) continue; + resourceID &= 0x7FFF; + if (resourceID >= count) continue; - Sint64 next = SDL_RWtell(rw); - if (next < 0) return -1; + Sint64 nextResource = SDL_RWtell(rw); + if (nextResource < 0) return -1; - cards->surfaces[id] = dibSurface( + surfaces[resourceID] = dibSurface( rw, - (Uint32)offset << alignmentShift, - (Uint32)length << alignmentShift + (Uint32)dataOffset << alignmentShift, + (Uint32)dataLength << alignmentShift ); - if (!cards->surfaces[id]) return -1; + if (!surfaces[resourceID]) return -1; - if (SDL_RWseek(rw, next, RW_SEEK_SET) < 0) return -1; + if (SDL_RWseek(rw, nextResource, RW_SEEK_SET) < 0) return -1; } return 0; } // -static int loadPE(struct Cards *cards, SDL_RWops *rw, Uint16 peOffset) { +static int +loadPE(SDL_Surface **surfaces, size_t count, SDL_RWops *rw, Uint16 peOffset) { if (SDL_RWseek(rw, peOffset + 0x04 + 0x02, RW_SEEK_SET) < 0) return -1; Uint16 sectionCount = SDL_ReadLE16(rw); @@ -254,7 +256,7 @@ static int loadPE(struct Cards *cards, SDL_RWops *rw, Uint16 peOffset) { for (Uint16 i = 0; i < nameIDCount; ++i) { Uint32 nameID = SDL_ReadLE32(rw); Uint32 subdirOffset = SDL_ReadLE32(rw); - if (nameID >= Cards_Count) continue; + if (nameID >= count) continue; if (!(subdirOffset & (1 << 31))) { SDL_SetError("bitmap name entry does not point to table"); return -1; @@ -288,8 +290,8 @@ static int loadPE(struct Cards *cards, SDL_RWops *rw, Uint16 peOffset) { Uint32 dataOffset = dataVirtual - (resourceTableVirtual - resourceTableOffset); - cards->surfaces[nameID] = dibSurface(rw, dataOffset, dataLength); - if (!cards->surfaces[nameID]) return -1; + surfaces[nameID] = dibSurface(rw, dataOffset, dataLength); + if (!surfaces[nameID]) return -1; if (SDL_RWseek(rw, nextName, RW_SEEK_SET) < 0) return -1; } @@ -297,34 +299,38 @@ static int loadPE(struct Cards *cards, SDL_RWops *rw, Uint16 peOffset) { 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; +static int loadEXE(SDL_Surface **surfaces, size_t count, SDL_RWops *rw) { + 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"); - goto fail; + return -1; } - if (SDL_RWseek(rw, 0x3C, RW_SEEK_SET) < 0) goto fail; + if (SDL_RWseek(rw, 0x3C, RW_SEEK_SET) < 0) return -1; 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 (SDL_RWseek(rw, offset, RW_SEEK_SET) < 0) return -1; + Uint8 sig[2] = { SDL_ReadU8(rw), SDL_ReadU8(rw) }; if (sig[0] == 'N' && sig[1] == 'E') { - if (loadNE(cards, rw, offset) < 0) goto fail; + return loadNE(surfaces, count, rw, offset); } else if (sig[0] == 'P' && sig[1] == 'E') { - if (loadPE(cards, rw, offset) < 0) goto fail; + return loadPE(surfaces, count, rw, offset); } else { SDL_SetError("invalid NE/PE signature"); - goto fail; + 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 (loadEXE(cards->surfaces, Cards_Count, rw) < 0) goto fail; + for (int i = Cards_Club + Cards_A; i <= Cards_Spade + Cards_K; ++i) { if (cards->surfaces[i]) continue; SDL_SetError("missing resource %d", i); -- cgit 1.4.1