diff options
author | June McEnroe <june@causal.agency> | 2019-08-25 13:21:48 -0400 |
---|---|---|
committer | June McEnroe <june@causal.agency> | 2019-08-25 13:21:48 -0400 |
commit | 4a54edfcd4b964a94b7c7f4fb7a8d30dd2272b7f (patch) | |
tree | b5a8455f75f1763fa08f781272689860c2a4da4d | |
parent | Mark card functions inline (diff) | |
download | wep-4a54edfcd4b964a94b7c7f4fb7a8d30dd2272b7f.tar.gz wep-4a54edfcd4b964a94b7c7f4fb7a8d30dd2272b7f.zip |
Remove files from cards repo
Diffstat (limited to '')
-rw-r--r-- | cards.3 | 217 | ||||
-rw-r--r-- | cards.c | 428 | ||||
-rw-r--r-- | cards.h | 80 | ||||
-rw-r--r-- | dump.1 | 48 | ||||
-rw-r--r-- | dump.c | 82 | ||||
-rw-r--r-- | exefmt.txt | 593 |
6 files changed, 0 insertions, 1448 deletions
diff --git a/cards.3 b/cards.3 deleted file mode 100644 index 7882756..0000000 --- a/cards.3 +++ /dev/null @@ -1,217 +0,0 @@ -.Dd March 28, 2019 -.Dt CARDS 3 -.Os -. -.Sh NAME -.Nm Cards_LoadCards , -.Nm Cards_LoadFreeCell , -.Nm Cards_InvertSurface -.Nd bitmap resource loader -. -.Sh SYNOPSIS -.In cards.h -. -.Ft int -.Fo Cards_LoadCards -.Fa "SDL_Surface *surfaces[]" -.Fa "size_t count" -.Fa "SDL_RWops *rw" -.Fa "enum Cards_Flag flags" -.Fc -. -.Ft int -.Fo Cards_LoadFreeCell -.Fa "SDL_Surface *surfaces[]" -.Fa "size_t count" -.Fa "SDL_RWops *rw" -.Fa "enum Cards_Flag flags" -.Fc -. -.Ft int -.Fn Cards_InvertSurface "SDL_Surface *surface" -. -.Sh DESCRIPTION -.Fn Cards_LoadCards -and -.Fn Cards_LoadFreeCell -load bitmap resources -into an array of -.Fa count -surfaces. -Resources can be loaded -from 16-bit NE executables -or from 32-bit PE executables. -. -.Pp -.Fn Cards_LoadCards -loads card bitmaps from a -.Pa CARDS.DLL -or Windows 3.0 -.Pa SOL.EXE -file -.Fa rw . -. -.Pp -Indices of loaded surfaces -are defined by the following: -.Bl -tag -width Ds -offset indent -.It Suit -.Dv Cards_Club , -.Dv Cards_Diamond , -.Dv Cards_Heart , -.Dv Cards_Spade . -.It Rank -.Dv Cards_A , -.Dv Cards_2 , -.Dv Cards_3 , -.Dv Cards_4 , -.Dv Cards_5 , -.Dv Cards_6 , -.Dv Cards_7 , -.Dv Cards_8 , -.Dv Cards_9 , -.Dv Cards_10 , -.Dv Cards_J , -.Dv Cards_Q , -.Dv Cards_K . -.It Back -.Dv Cards_Back1 , -.Dv Cards_Back2 , -.Dv Cards_Back3 , -.Dv Cards_Back4 , -.Dv Cards_Back5 , -.Dv Cards_Back6 , -.Dv Cards_Back7 , -.Dv Cards_Back8 , -.Dv Cards_Back9 , -.Dv Cards_Back10 , -.Dv Cards_Back11 , -.Dv Cards_Back12 . -.It Other -.Dv Cards_Empty , -.Dv Cards_X , -.Dv Cards_O . -.El -. -.Pp -Where suit and rank constants -are added together to form an index. -Note that there are gaps in the indices -and some surface pointers will be set to -.Dv NULL . -The maximum number of surfaces -is defined by -.Dv Cards_CardCount . -. -.Pp -The dimensions of the loaded surfaces -are defined by -.Dv Cards_CardWidth -and -.Dv Cards_CardHeight . -. -.Pp -.Fn Cards_LoadCards -accepts the following flags: -.Bl -tag -width "Cards_BlackBorders" -offset indent -.It Dv Cards_ColorKey -Use color key transparency for the -.Dv Cards_Empty , -.Dv Cards_X -and -.Dv Cards_O -surfaces. -.It Dv Cards_AlphaCorners -Make the rounded card corners transparent. -.It Dv Cards_BlackBorders -Make all card borders black. -.El -. -.Pp -.Fn Cards_LoadFreeCell -loads bitmaps from a -.Pa FREECELL.EXE -file -.Fa rw . -. -.Pp -Indices of loaded surfaces -are defined by -.Dv Cards_KingRight , -.Dv Cards_KingLeft -and -.Dv Cards_KingWin . -Note that there are gaps in the indices -and some surface pointers will be set to -.Dv NULL . -The maximum number of surfaces -is defined by -.Dv Cards_FreeCellCount . -. -.Pp -The dimensions of the loaded surfaces -are defined by -.Dv Cards_KingWidth -and -.Dv Cards_KingHeight . -. -.Pp -.Fn Cards_LoadFreeCell -accepts the following flags: -.Bl -tag -width "Cards_ColorKey" -offset indent -.It Dv Cards_ColorKey -Use color key transparency. -.El -. -.Pp -.Fn Cards_InvertSurface -inverts the colors of a surface loaded by -.Fn Cards_LoadCards . -. -.Sh RETURN VALUES -Upon successful completion, -the value 0 is returned; -otherwise the value -1 is returned. -. -.Sh ERRORS -Error messages are set with -.Fn SDL_SetError -and can be retrieved with -.Fn SDL_GetError . -. -.Pp -.Fn Cards_LoadCards -and -.Fn Cards_LoadFreeCell -may fail for the following reasons: -any -.Vt SDL_RWops -or -.Vt SDL_Surface -error; -invalid MZ, NE or PE signatures; -missing resource table; -invalid resource hierarchy; -missing resource. -. -.Pp -.Fn Cards_InvertSurface -may fail for any -.Vt SDL_Surface -error -or if the surface format is not supported. -. -.Sh STANDARDS -.Bl -item -.It -The New Executable format, -documented in -.Pa exefmt.txt . -.It -The Portable Executable format, -documented at -.Lk https://docs.microsoft.com/en-us/windows/desktop/Debug/pe-format . -.El -. -.Sh AUTHORS -.An C. McEnroe Aq Mt june@causal.agency diff --git a/cards.c b/cards.c deleted file mode 100644 index ddc5b86..0000000 --- a/cards.c +++ /dev/null @@ -1,428 +0,0 @@ -/* Copyright (C) 2019 C. McEnroe <june@causal.agency> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <errno.h> -#include <stdlib.h> -#include <string.h> - -#include "cards.h" - -static SDL_Surface * -dibSurface(SDL_RWops *rw, Uint32 offset, Uint32 length) { - Uint32 bitmapLength = 0x0E + length; - - Uint8 *buffer = malloc(bitmapLength); - if (!buffer) { - SDL_SetError("malloc error: %s", strerror(errno)); - return NULL; - } - - SDL_RWops *bitmap = SDL_RWFromMem(buffer, bitmapLength); - if (!bitmap) { - free(buffer); - return NULL; - } - - if (SDL_RWseek(rw, offset, RW_SEEK_SET) < 0) goto fail; - Uint32 dibHeaderLength = SDL_ReadLE32(rw); - Uint32 bitmapDataOffset = 0x0E + dibHeaderLength; - - if (dibHeaderLength == 0x0C) { - if (SDL_RWseek(rw, 0x06, RW_SEEK_CUR) < 0) goto fail; - Uint16 bitsPerPixel = SDL_ReadLE16(rw); - bitmapDataOffset += 3 * (1 << bitsPerPixel); - - } else if (dibHeaderLength == 0x28) { - if (SDL_RWseek(rw, 0x0A, RW_SEEK_CUR) < 0) goto fail; - Uint16 bitsPerPixel = SDL_ReadLE16(rw); - if (SDL_RWseek(rw, 0x10, RW_SEEK_CUR) < 0) goto fail; - Uint32 paletteLength = SDL_ReadLE32(rw); - - if (!paletteLength && bitsPerPixel < 16) { - paletteLength = 1 << bitsPerPixel; - } - bitmapDataOffset += 4 * paletteLength; - - } else { - SDL_SetError("unrecognized DIB header length %u", dibHeaderLength); - goto fail; - } - - SDL_WriteU8(bitmap, 'B'); - SDL_WriteU8(bitmap, 'M'); - SDL_WriteLE32(bitmap, bitmapLength); - SDL_WriteLE16(bitmap, 0); // reserved - SDL_WriteLE16(bitmap, 0); // reserved - SDL_WriteLE32(bitmap, bitmapDataOffset); - - if (SDL_RWseek(rw, offset, RW_SEEK_SET) < 0) goto fail; - if (SDL_RWread(rw, &buffer[SDL_RWtell(bitmap)], length, 1) < 1) goto fail; - - SDL_RWseek(bitmap, 0, RW_SEEK_SET); - SDL_Surface *surface = SDL_LoadBMP_RW(bitmap, 1); - free(buffer); - return surface; - -fail: - SDL_RWclose(bitmap); - free(buffer); - return NULL; -} - -// exefmt.txt -static int -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); - - if (SDL_RWseek(rw, resourceTableOffset, RW_SEEK_SET) < 0) return -1; - Uint16 alignmentShift = SDL_ReadLE16(rw); - - Uint16 resourceCount; - for (;;) { - Uint16 typeID = SDL_ReadLE16(rw); - resourceCount = SDL_ReadLE16(rw); - SDL_ReadLE32(rw); // reserved - - if (!typeID) { - SDL_SetError("no bitmap resources"); - return -1; - } - if (typeID == 0x8002) break; - - if (SDL_RWseek(rw, 0x0C * resourceCount, RW_SEEK_CUR) < 0) return -1; - } - - for (Uint16 i = 0; i < resourceCount; ++i) { - Uint16 dataOffset = SDL_ReadLE16(rw); - Uint16 dataLength = SDL_ReadLE16(rw); - /* Uint16 flags = */ SDL_ReadLE16(rw); - Uint16 resourceID = SDL_ReadLE16(rw); - SDL_ReadLE32(rw); // reserved - - resourceID &= 0x7FFF; - if (resourceID >= idSkip) resourceID -= idSkip; - if (resourceID >= count) continue; - - Sint64 nextResource = SDL_RWtell(rw); - if (nextResource < 0) return -1; - - surfaces[resourceID] = dibSurface( - rw, - (Uint32)dataOffset << alignmentShift, - (Uint32)dataLength << alignmentShift - ); - if (!surfaces[resourceID]) return -1; - - if (SDL_RWseek(rw, nextResource, RW_SEEK_SET) < 0) return -1; - } - - return 0; -} - -// <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, Uint32 idSkip -) { - if (SDL_RWseek(rw, peOffset + 0x04 + 0x02, RW_SEEK_SET) < 0) return -1; - Uint16 sectionCount = SDL_ReadLE16(rw); - - if (SDL_RWseek(rw, peOffset + 0x04 + 0x10, RW_SEEK_SET) < 0) return -1; - Uint16 optionalHeaderLength = SDL_ReadLE16(rw); - Uint16 sectionTableOffset = peOffset + 0x04 + 0x14 + optionalHeaderLength; - - Uint32 resourceTableOffset = 0; - Uint32 resourceTableVirtual = 0; - for (Uint16 i = 0; i < sectionCount; ++i) { - Uint16 headerOffset = sectionTableOffset + 0x28 * i; - - if (SDL_RWseek(rw, headerOffset, RW_SEEK_SET) < 0) return -1; - char name[8]; - if (!SDL_RWread(rw, name, sizeof(name), 1)) return -1; - if (strncmp(".rsrc", name, sizeof(name))) continue; - - if (SDL_RWseek(rw, headerOffset + 0x0C, RW_SEEK_SET) < 0) return -1; - resourceTableVirtual = SDL_ReadLE32(rw); - - if (SDL_RWseek(rw, headerOffset + 0x14, RW_SEEK_SET) < 0) return -1; - resourceTableOffset = SDL_ReadLE32(rw); - - break; - } - if (!resourceTableOffset) { - SDL_SetError("no resource table"); - return -1; - } - - if (SDL_RWseek(rw, resourceTableOffset + 0x0C, RW_SEEK_SET) < 0) return -1; - Uint16 typeNameCount = SDL_ReadLE16(rw); - Uint16 typeIDCount = SDL_ReadLE16(rw); - - if (SDL_RWseek(rw, 0x08 * typeNameCount, RW_SEEK_CUR) < 0) return -1; - - Uint32 bitmapTableOffset = 0; - for (Uint16 i = 0; i < typeIDCount; ++i) { - Uint32 typeID = SDL_ReadLE32(rw); - Uint32 subdirOffset = SDL_ReadLE32(rw); - if (typeID != 0x02) continue; - if (!(subdirOffset & (1 << 31))) { - SDL_SetError("bitmap type entry does not point to table"); - return -1; - } - bitmapTableOffset = resourceTableOffset + (subdirOffset & ~(1 << 31)); - break; - } - - if (SDL_RWseek(rw, bitmapTableOffset + 0x0C, RW_SEEK_SET) < 0) return -1; - Uint16 nameNameCount = SDL_ReadLE16(rw); - Uint16 nameIDCount = SDL_ReadLE16(rw); - - if (SDL_RWseek(rw, 0x08 * nameNameCount, RW_SEEK_CUR) < 0) return -1; - - for (Uint16 i = 0; i < nameIDCount; ++i) { - Uint32 nameID = 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; - } - - Sint64 nextName = SDL_RWtell(rw); - if (nextName < 0) return -1; - - Uint32 langTableOffset = - resourceTableOffset + (subdirOffset & ~(1 << 31)); - - if (SDL_RWseek(rw, langTableOffset + 0x0C, RW_SEEK_SET) < 0) return -1; - Uint16 langNameCount = SDL_ReadLE16(rw); - Uint16 langIDCount = SDL_ReadLE16(rw); - if (langNameCount != 0 || langIDCount != 1) { - SDL_SetError("language table contains more than one entry"); - return -1; - } - - /* Uint32 langID = */ SDL_ReadLE32(rw); - Uint32 dataEntryOffset = SDL_ReadLE32(rw); - if (dataEntryOffset & (1 << 31)) { - SDL_SetError("language entry does not point to data"); - return -1; - } - dataEntryOffset += resourceTableOffset; - - if (SDL_RWseek(rw, dataEntryOffset, RW_SEEK_SET) < 0) return -1; - Uint32 dataVirtual = SDL_ReadLE32(rw); - Uint32 dataLength = SDL_ReadLE32(rw); - Uint32 dataOffset = - dataVirtual - (resourceTableVirtual - resourceTableOffset); - - surfaces[nameID] = dibSurface(rw, dataOffset, dataLength); - if (!surfaces[nameID]) return -1; - - if (SDL_RWseek(rw, nextName, RW_SEEK_SET) < 0) return -1; - } - - return 0; -} - -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"); - return -1; - } - - 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) return -1; - Uint8 sig[2] = { SDL_ReadU8(rw), SDL_ReadU8(rw) }; - - if (sig[0] == 'N' && sig[1] == 'E') { - return loadNE(surfaces, count, rw, offset, idSkip); - } else if (sig[0] == 'P' && sig[1] == 'E') { - return loadPE(surfaces, count, rw, offset, idSkip); - } else { - SDL_SetError("invalid NE/PE signature"); - return -1; - } -} - -static int setColorKey(SDL_Surface **surfaces, size_t count) { - size_t i = Cards_Empty; - if (i < count) { - if (SDL_SetColorKey(surfaces[i], SDL_TRUE, 1) < 0) return -1; - } - for (i = Cards_X; i <= Cards_O; ++i) { - if (i >= count) break; - if (SDL_SetColorKey(surfaces[i], SDL_TRUE, 12) < 0) return -1; - } - return 0; -} - -static int setAlphaCorners(SDL_Surface **surfaces, size_t count) { - SDL_Surface *alpha = NULL; - for (size_t i = 0; i < count; ++i) { - if (!surfaces[i]) continue; - - alpha = SDL_ConvertSurfaceFormat(surfaces[i], SDL_PIXELFORMAT_RGBA32, 0); - if (!alpha) return -1; - - if (SDL_SetSurfaceBlendMode(alpha, SDL_BLENDMODE_BLEND) < 0) goto fail; - - SDL_Rect rects[8] = { - { 0, 0, 2, 1 }, - { 0, 1, 1, 1 }, - { Cards_CardWidth - 2, 0, 2, 1 }, - { Cards_CardWidth - 1, 1, 1, 1 }, - { 0, Cards_CardHeight - 1, 2, 1 }, - { 0, Cards_CardHeight - 2, 1, 1 }, - { Cards_CardWidth - 2, Cards_CardHeight - 1, 2, 1 }, - { Cards_CardWidth - 1, Cards_CardHeight - 2, 1, 1 }, - }; - Uint32 trans = SDL_MapRGBA(alpha->format, 0x00, 0x00, 0x00, 0x00); - if (SDL_FillRects(alpha, rects, 8, trans) < 0) goto fail; - - SDL_FreeSurface(surfaces[i]); - surfaces[i] = alpha; - } - return 0; - -fail: - SDL_FreeSurface(alpha); - return -1; -} - -static int setBlackBorders(SDL_Surface **surfaces, size_t count) { - for (size_t i = Cards_Diamond + Cards_A; i <= Cards_Heart + Cards_K; ++i) { - if (i >= count) break; - if (!surfaces[i]) continue; - SDL_Rect rects[8] = { - { 2, 0, Cards_CardWidth - 4, 1 }, - { 2, Cards_CardHeight - 1, Cards_CardWidth - 4, 1 }, - { 0, 2, 1, Cards_CardHeight - 4 }, - { Cards_CardWidth - 1, 2, 1, Cards_CardHeight - 4 }, - { 1, 1, 1, 1 }, - { Cards_CardWidth - 2, 1, 1, 1 }, - { 1, Cards_CardHeight - 2, 1, 1 }, - { Cards_CardWidth - 2, Cards_CardHeight - 2, 1, 1 }, - }; - Uint32 black = SDL_MapRGB(surfaces[i]->format, 0x00, 0x00, 0x00); - if (SDL_FillRects(surfaces[i], rects, 8, black) < 0) return -1; - } - return 0; -} - -static int -checkRange(SDL_Surface **surfaces, size_t count, size_t a, size_t b) { - for (size_t i = a; i <= b; ++i) { - if (i >= count) break; - if (surfaces[i]) continue; - SDL_SetError("missing resource %zu", i); - return -1; - } - return 0; -} - -int -Cards_LoadCards( - SDL_Surface *surfaces[], size_t count, - SDL_RWops *rw, enum Cards_Flag flags -) { - memset(surfaces, 0, sizeof(*surfaces) * count); - 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) { - if (setColorKey(surfaces, count) < 0) return -1; - } - if (flags & Cards_AlphaCorners) { - if (setAlphaCorners(surfaces, count) < 0) return -1; - } - if (flags & Cards_BlackBorders) { - if (setBlackBorders(surfaces, count) < 0) return -1; - } - return 0; -} - -int -Cards_LoadFreeCell( - SDL_Surface *surfaces[], size_t count, - SDL_RWops *rw, enum Cards_Flag flags -) { - memset(surfaces, 0, sizeof(*surfaces) * count); - if (loadEXE(surfaces, count, rw, 402) < 0) return -1; - if (checkRange(surfaces, count, Cards_KingRight, Cards_KingWin) < 0) { - return -1; - } - if (flags & Cards_ColorKey) { - for (size_t i = Cards_KingRight; i <= Cards_KingWin; ++i) { - if (i >= count) break; - if (SDL_SetColorKey(surfaces[i], SDL_TRUE, 2) < 0) return -1; - } - } - return 0; -} - -static int invertPalette(SDL_Surface *surface) { - const SDL_Palette *palette = surface->format->palette; - SDL_Palette *invert = SDL_AllocPalette(palette->ncolors); - if (!invert) return -1; - for (int i = 0; i < invert->ncolors; ++i) { - invert->colors[i].r = ~palette->colors[i].r; - invert->colors[i].g = ~palette->colors[i].g; - invert->colors[i].b = ~palette->colors[i].b; - invert->colors[i].a = palette->colors[i].a; - } - if (SDL_SetSurfacePalette(surface, invert) < 0) return -1; - SDL_FreePalette(invert); - return 0; -} - -static int invertPixels(SDL_Surface *surface) { - if (SDL_LockSurface(surface) < 0) return -1; - Uint8 *pixels = surface->pixels; - for (int y = 0; y < surface->h; ++y) { - Uint32 *row = (Uint32 *)&pixels[y * surface->pitch]; - for (int x = 0; x < surface->w; ++x) { - Uint32 color = ~row[x] & ~surface->format->Amask; - Uint32 alpha = row[x] & surface->format->Amask; - row[x] = color | alpha; - } - } - SDL_UnlockSurface(surface); - return 0; -} - -int Cards_InvertSurface(SDL_Surface *surface) { - if (surface->format->palette) { - if (invertPalette(surface) < 0) return -1; - } else if (surface->format->BytesPerPixel == 4) { - if (invertPixels(surface) < 0) return -1; - } else { - SDL_SetError("cannot invert surface format"); - return -1; - } - return 0; -} diff --git a/cards.h b/cards.h deleted file mode 100644 index 9625cb8..0000000 --- a/cards.h +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright (C) 2019 C. McEnroe <june@causal.agency> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef CARDS_H -#define CARDS_H - -#include <SDL_rwops.h> -#include <SDL_surface.h> -#include <stddef.h> - -enum { - Cards_CardWidth = 71, - Cards_CardHeight = 96, - Cards_KingWidth = 32, - Cards_KingHeight = 32, -}; - -enum Cards_Card { - Cards_Club, - Cards_Diamond = 13, - Cards_Heart = 26, - Cards_Spade = 39, - - // Add rank to suit to obtain card index. - Cards_A = 1, - Cards_2, Cards_3, Cards_4, Cards_5, Cards_6, Cards_7, Cards_8, Cards_9, - Cards_10, Cards_J, Cards_Q, Cards_K, - - Cards_Empty = 53, - Cards_Back1, Cards_Back2, Cards_Back3, Cards_Back4, - Cards_Back5, Cards_Back6, Cards_Back7, Cards_Back8, - Cards_Back9, Cards_Back10, Cards_Back11, Cards_Back12, - - Cards_X = 67, - Cards_O, - - Cards_CardCount, -}; - -enum Cards_FreeCell { - Cards_KingRight = 1, - Cards_KingLeft, - Cards_KingWin, - Cards_FreeCellCount, -}; - -enum Cards_Flag { - Cards_ColorKey = 1 << 0, - Cards_AlphaCorners = 1 << 1, - Cards_BlackBorders = 1 << 2, -}; - -int -Cards_LoadCards( - SDL_Surface *surfaces[], size_t count, - SDL_RWops *rw, enum Cards_Flag flags -); - -int -Cards_LoadFreeCell( - SDL_Surface *surfaces[], size_t count, - SDL_RWops *rw, enum Cards_Flag flags -); - -int Cards_InvertSurface(SDL_Surface *surface); - -#endif diff --git a/dump.1 b/dump.1 deleted file mode 100644 index a7fc3db..0000000 --- a/dump.1 +++ /dev/null @@ -1,48 +0,0 @@ -.Dd March 29, 2019 -.Dt DUMP 1 -.Os -. -.Sh NAME -.Nm dump -.Nd dump bitmap resources -. -.Sh SYNOPSIS -.Nm -.Op Fl abfik -.Op Ar file -. -.Sh DESCRIPTION -.Nm -dumps bitmap resources from -.Pa CARDS.DLL , -.Pa SOL.EXE -or -.Pa FREECELL.EXE -files. -Bitmaps are written to the current directory -starting with -.Pa 01.bmp . -. -.Pp -The arguments are as follows: -.Bl -tag -width Ds -.It Fl a -Set the -.Xr cards 3 -.Dv Cards_AlphaCorners -flag. -.It Fl b -Set the -.Xr cards 3 -.Dv Cards_BlackBorders -flag. -.It Fl f -Dump FreeCell bitmaps. -.It Fl i -Invert the colors of the bitmaps -.It Fl k -Set the -.Xr cards 3 -.Dv Cards_ColorKey -flag. -.El diff --git a/dump.c b/dump.c deleted file mode 100644 index 127d6b1..0000000 --- a/dump.c +++ /dev/null @@ -1,82 +0,0 @@ -/* Copyright (C) 2019 C. McEnroe <june@causal.agency> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#define _XOPEN_SOURCE - -#include <err.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <sysexits.h> -#include <unistd.h> - -#include <SDL.h> - -#include "cards.h" - -int main(int argc, char *argv[]) { - bool freecell = false; - enum Cards_Flag flags = 0; - bool invert = false; - - int opt; - while (0 < (opt = getopt(argc, argv, "abfik"))) { - switch (opt) { - break; case 'a': flags |= Cards_AlphaCorners; - break; case 'b': flags |= Cards_BlackBorders; - break; case 'f': freecell = true; - break; case 'i': invert = true; - break; case 'k': flags |= Cards_ColorKey; - break; default: return EX_USAGE; - } - } - - struct SDL_RWops *rw; - if (optind < argc) { - rw = SDL_RWFromFile(argv[optind], "rb"); - } else { - rw = SDL_RWFromFP(stdin, SDL_FALSE); - } - if (!rw) errx(EX_NOINPUT, "SDL_RWFromFile: %s", SDL_GetError()); - - SDL_Surface *surfaces[Cards_CardCount]; - if (freecell) { - int error = Cards_LoadFreeCell( - surfaces, Cards_CardCount, rw, flags - ); - if (error) errx(EX_DATAERR, "Cards_LoadFreeCell: %s", SDL_GetError()); - } else { - int error = Cards_LoadCards(surfaces, Cards_CardCount, rw, flags); - if (error) errx(EX_DATAERR, "Cards_LoadCards: %s", SDL_GetError()); - } - SDL_RWclose(rw); - - for (size_t i = 0; i < Cards_CardCount; ++i) { - if (!surfaces[i]) continue; - - if (invert) { - int error = Cards_InvertSurface(surfaces[i]); - if (error) { - errx(EX_DATAERR, "Cards_InvertSurface: %s", SDL_GetError()); - } - } - - char name[sizeof("00.bmp")]; - snprintf(name, sizeof(name), "%02zu.bmp", i); - int error = SDL_SaveBMP(surfaces[i], name); - if (error) errx(EX_CANTCREAT, "SDL_SaveBMP: %s", SDL_GetError()); - } -} diff --git a/exefmt.txt b/exefmt.txt deleted file mode 100644 index 51fa9a7..0000000 --- a/exefmt.txt +++ /dev/null @@ -1,593 +0,0 @@ -INF: Executable-File Header Format [P_WinSDK] - -3.00 -WINDOWS -PSSONLY | Windows 3 Developers Notes softlib ENDUSER - -Summary: - -Note: This article is part of a set of seven articles, collectively -called the "Windows 3.00 Developer's Notes." More information about -the contents of the other articles, and procedures for ordering a -hard-copy set, can be found in the knowledge base article titled "INF: -The Windows 3.00 Developer's Notes" (Q65260). - -This article can be found in the Software/Data Library by searching on -the word EXEFMT or S12688. EXEFMT was archived using the PKware -file-compression utility. - -More Information: - -Microsoft defined the segmented executable file format for Windows -applications and dynamic-link libraries (DLLs). This file format is -also referred to as the New Executable Format. This new format is an -extension of the existing MS-DOS .EXE format (old-style format). The -purpose of the segmented executable format is to provide the -information needed to support the dynamic linking and segmentation -capabilities of the Windows environment. - -An executable file contains Microsoft Windows code and data, or -Windows code, data, and resources. Specific fields have been added to -the old-style .EXE format header to indicate the existence of the -segmented file format. The old-style header may contain a valid -executable program, called a stub program, that will be executed if -the program is run on MS-DOS (without Windows). This stub program -usually prints a message indicating that Microsoft Windows is required -to run the program. The segmented executable format extensions also -begin with a header that describes the contents and location of the -executable image in the file. The loader uses this header information -when it loads the executable segments in memory. - - -====================================================================== - OLD-STYLE HEADER EXTENSIONS -====================================================================== - -The old-style header contains information the loader expects for a DOS -executable file. It describes a stub program (WINSTUB) the loader can -place in memory when necessary, it points to the new-style header, and -it contains the stub programs relocation table. - -The following illustrates the distinct parts of the old-style -executable format: - - +-------------------------+ - 00h | Old-style header info | - +-------------------------+ - 20h | Reserved | - +-------------------------+ - 3Ch | Offset to segmented | - | .EXE header | - +-------------------------+ - 40h | Relocation table and | - | DOS stub program | - +-------------------------+ - | Segmented .EXE Header | - | . | - | . | - | . | - -The word at offset 18h in the old-style .EXE header contains the -relative byte offset to the stub program's relocation table. If this -offset is 40h, then the double word at offset 3Ch is assumed to be the -relative byte offset from the beginning of the file to the beginning -of the segmented executable header. A new-format .EXE file is -identified if the segmented executable header contains a valid -signature. If the signature is not valid, the file is assumed to be an -old-style format .EXE file. The remainder of the old-style format -header will describe a DOS program, the stub. The stub may be any -valid program but will typically be a program that displays an error -message. - -====================================================================== - SEGMENTED EXE FORMAT -====================================================================== - -Because Windows executable files are often larger than one segment -(64K), additional information (that does not appear in the old-style -header) is required so that the loader can load each segment properly. -The segmented EXE format was developed to provide the loader with this -information. - -The segmented .EXE file has the following format: - - +-----------------+ - 00h | Old-style EXE | - | Header | - +-----------------+ - 20h | Reserved | - +-----------------+ - 3Ch | Offset to | ---+ - | Segmented Header| | - +-----------------+ | - 40h | Relocation Table| | - | & Stub Program | | - +-----------------+ | - | | | - +-----------------+ | - xxh | Segmented EXE | <--+ - | Header | - +-----------------+ - | Segment Table | - +-----------------+ - | Resource Table | - +-----------------+ - | Resident Name | - | Table | - +-----------------+ - | Module Reference| - | Table | - +-----------------+ - | Imported Names | - | Table | - +-----------------+ - | Entry Table | - +-----------------+ - | Non-Resident | - | Name Table | - +-----------------+ - | Seg #1 Data | - | Seg #1 Info | - +-----------------+ - . - . - . - +-----------------+ - | Seg #n Data | - | Seg #n Info | - +-----------------+ - - -The following sections describe each of the components that make up -the segmented EXE format. Each section contains a description of the -component and the fields in the structures that make up that -component. - -Note: All unused fields and flag bits are reserved for future use and -must contain 0 (zero) values. - -====================================================================== - SEGMENTED EXE HEADER -====================================================================== - -The segmented EXE header contains general information about the EXE -file and contains information on the location and size of the other -sections. The Windows loader copies this section, along with other -data, into the module table in the system data. The module table is -internal data used by the loader to manage the loaded executable -modules in the system and to support dynamic linking. - -The following describes the format of the segmented executable header. -For each field, the offset is given relative to the beginning of the -segmented header, the size of the field is defined, and a description -is given. - - Offset Size Description - ------ ---- ----------- - - 00h DW Signature word. - "N" is low-order byte. - "E" is high-order byte. - - 02h DB Version number of the linker. - - 03h DB Revision number of the linker. - - 04h DW Entry Table file offset, relative to the beginning of - the segmented EXE header. - 06h DW Number of bytes in the entry table. - - 08h DD 32-bit CRC of entire contents of file. - These words are taken as 00 during the calculation. - - 0Ch DW Flag word. - 0000h = NOAUTODATA - 0001h = SINGLEDATA (Shared automatic data segment) - 0002h = MULTIPLEDATA (Instanced automatic data - segment) - 2000h = Errors detected at link time, module will not - load. - 8000h = Library module. - The SS:SP information is invalid, CS:IP points - to an initialization procedure that is called - with AX equal to the module handle. This - initialization procedure must perform a far - return to the caller, with AX not equal to - zero to indicate success, or AX equal to zero - to indicate failure to initialize. DS is set - to the library's data segment if the - SINGLEDATA flag is set. Otherwise, DS is set - to the caller's data segment. - - A program or DLL can only contain dynamic - links to executable files that have this - library module flag set. One program cannot - dynamic-link to another program. - - 0Eh DW Segment number of automatic data segment. - This value is set to zero if SINGLEDATA and - MULTIPLEDATA flag bits are clear, NOAUTODATA is - indicated in the flags word. - - A Segment number is an index into the module's segment - table. The first entry in the segment table is segment - number 1. - - 10h DW Initial size, in bytes, of dynamic heap added to the - data segment. This value is zero if no initial local - heap is allocated. - - 12h DW Initial size, in bytes, of stack added to the data - segment. This value is zero to indicate no initial - stack allocation, or when SS is not equal to DS. - - 14h DD Segment number:offset of CS:IP. - - 18h DD Segment number:offset of SS:SP. - If SS equals the automatic data segment and SP equals - zero, the stack pointer is set to the top of the - automatic data segment just below the additional heap - area. - - +--------------------------+ - | additional dynamic heap | - +--------------------------+ <- SP - | additional stack | - +--------------------------+ - | loaded auto data segment | - +--------------------------+ <- DS, SS - - 1Ch DW Number of entries in the Segment Table. - - 1Eh DW Number of entries in the Module Reference Table. - 20h DW Number of bytes in the Non-Resident Name Table. - - 22h DW Segment Table file offset, relative to the beginning - of the segmented EXE header. - - 24h DW Resource Table file offset, relative to the beginning - of the segmented EXE header. - - 26h DW Resident Name Table file offset, relative to the - beginning of the segmented EXE header. - - 28h DW Module Reference Table file offset, relative to the - beginning of the segmented EXE header. - - 2Ah DW Imported Names Table file offset, relative to the - beginning of the segmented EXE header. - - 2Ch DD Non-Resident Name Table offset, relative to the - beginning of the file. - - 30h DW Number of movable entries in the Entry Table. - - 32h DW Logical sector alignment shift count, log(base 2) of - the segment sector size (default 9). - - 34h DW Number of resource entries. - - 36h DB Executable type, used by loader. - 02h = WINDOWS - - 37h-3Fh DB Reserved, currently 0's. - - -====================================================================== - SEGMENT TABLE -====================================================================== - -The segment table contains an entry for each segment in the executable -file. The number of segment table entries are defined in the segmented -EXE header. The first entry in the segment table is segment number 1. -The following is the structure of a segment table entry. - - Size Description - ---- ----------- - - DW Logical-sector offset (n byte) to the contents of the segment - data, relative to the beginning of the file. Zero means no - file data. - - DW Length of the segment in the file, in bytes. Zero means 64K. - - DW Flag word. - 0007h = TYPE_MASK Segment-type field. - 0000h = CODE Code-segment type. - 0001h = DATA Data-segment type. - 0010h = MOVEABLE Segment is not fixed. - 0040h = PRELOAD Segment will be preloaded; read-only if - this is a data segment. - 0100h = RELOCINFO Set if segment has relocation records. - F000h = DISCARD Discard priority. - - DW Minimum allocation size of the segment, in bytes. Total size - of the segment. Zero means 64K. - - -====================================================================== - RESOURCE TABLE -====================================================================== - -The resource table follows the segment table and contains entries for -each resource in the executable file. The resource table consists of -an alignment shift count, followed by a table of resource records. The -resource records define the type ID for a set of resources. Each -resource record contains a table of resource entries of the defined -type. The resource entry defines the resource ID or name ID for the -resource. It also defines the location and size of the resource. The -following describes the contents of each of these structures: - - Size Description - ---- ----------- - - DW Alignment shift count for resource data. - - A table of resource type information blocks follows. The following - is the format of each type information block: - - DW Type ID. This is an integer type if the high-order bit is - set (8000h); otherwise, it is an offset to the type string, - the offset is relative to the beginning of the resource - table. A zero type ID marks the end of the resource type - information blocks. - - DW Number of resources for this type. - - DD Reserved. - - A table of resources for this type follows. The following is - the format of each resource (8 bytes each): - - DW File offset to the contents of the resource data, - relative to beginning of file. The offset is in terms - of the alignment shift count value specified at - beginning of the resource table. - - DW Length of the resource in the file (in bytes). - - DW Flag word. - 0010h = MOVEABLE Resource is not fixed. - 0020h = PURE Resource can be shared. - 0040h = PRELOAD Resource is preloaded. - - DW Resource ID. This is an integer type if the high-order - bit is set (8000h), otherwise it is the offset to the - resource string, the offset is relative to the - beginning of the resource table. - - DD Reserved. - - Resource type and name strings are stored at the end of the - resource table. Note that these strings are NOT null terminated and - are case sensitive. - - DB Length of the type or name string that follows. A zero value - indicates the end of the resource type and name string, also - the end of the resource table. - - DB ASCII text of the type or name string. - - -====================================================================== - RESIDENT-NAME TABLE -====================================================================== - -The resident-name table follows the resource table, and contains this -module's name string and resident exported procedure name strings. The -first string in this table is this module's name. These name strings -are case-sensitive and are not null-terminated. The following -describes the format of the name strings: - - Size Description - ---- ----------- - - DB Length of the name string that follows. A zero value indicates - the end of the name table. - - DB ASCII text of the name string. - - DW Ordinal number (index into entry table). This value is ignored - for the module name. - - -====================================================================== - MODULE-REFERENCE TABLE -====================================================================== - -The module-reference table follows the resident-name table. Each entry -contains an offset for the module-name string within the imported- -names table; each entry is 2 bytes long. - - Size Description - ---- ----------- - - DW Offset within Imported Names Table to referenced module name - string. - - -====================================================================== - IMPORTED-NAME TABLE -====================================================================== - -The imported-name table follows the module-reference table. This table -contains the names of modules and procedures that are imported by the -executable file. Each entry is composed of a 1-byte field that -contains the length of the string, followed by any number of -characters. The strings are not null-terminated and are case -sensitive. - - Size Description - ---- ----------- - - DB Length of the name string that follows. - - DB ASCII text of the name string. - - -====================================================================== - ENTRY TABLE -====================================================================== - -The entry table follows the imported-name table. This table contains -bundles of entry-point definitions. Bundling is done to save space in -the entry table. The entry table is accessed by an ordinal value. -Ordinal number one is defined to index the first entry in the entry -table. To find an entry point, the bundles are scanned searching for a -specific entry point using an ordinal number. The ordinal number is -adjusted as each bundle is checked. When the bundle that contains the -entry point is found, the ordinal number is multiplied by the size of -the bundle's entries to index the proper entry. - -The linker forms bundles in the most dense manner it can, under the -restriction that it cannot reorder entry points to improve bundling. -The reason for this restriction is that other .EXE files may refer to -entry points within this bundle by their ordinal number. The following -describes the format of the entry table bundles. - - Size Description - ---- ----------- - - DB Number of entries in this bundle. All records in one bundle - are either moveable or refer to the same fixed segment. A zero - value in this field indicates the end of the entry table. - - DB Segment indicator for this bundle. This defines the type of - entry table entry data within the bundle. There are three - types of entries that are defined. - - 000h = Unused entries. There is no entry data in an unused - bundle. The next bundle follows this field. This is - used by the linker to skip ordinal numbers. - - 001h-0FEh = Segment number for fixed segment entries. A fixed - segment entry is 3 bytes long and has the following - format. - - DB Flag word. - 01h = Set if the entry is exported. - 02h = Set if the entry uses a global (shared) data - segments. - The first assembly-language instruction in the - entry point prologue must be "MOV AX,data - segment number". This may be set only for - SINGLEDATA library modules. - - DW Offset within segment to entry point. - - 0FFH = Moveable segment entries. The entry data contains the - segment number for the entry points. A moveable segment - entry is 6 bytes long and has the following format. - - DB Flag word. - 01h = Set if the entry is exported. - 02h = Set if the entry uses a global (shared) data - segments. - - INT 3FH. - - DB Segment number. - - DW Offset within segment to entry point. - - -====================================================================== - NONRESIDENT-NAME TABLE -====================================================================== - -The nonresident-name table follows the entry table, and contains a -module description and nonresident exported procedure name strings. -The first string in this table is a module description. These name -strings are case-sensitive and are not null-terminated. The name -strings follow the same format as those defined in the resident name -table. - - -====================================================================== - PER SEGMENT DATA -====================================================================== - -The location and size of the per-segment data is defined in the -segment table entry for the segment. If the segment has relocation -fixups, as defined in the segment table entry flags, they directly -follow the segment data in the file. The relocation fixup information -is defined as follows: - - - Size Description - ---- ----------- - - DW Number of relocation records that follow. - - A table of relocation records follows. The following is the format - of each relocation record. - - DB Source type. - 0Fh = SOURCE_MASK - 00h = LOBYTE - 02h = SEGMENT - 03h = FAR_ADDR (32-bit pointer) - 05h = OFFSET (16-bit offset) - - DB Flags byte. - 03h = TARGET_MASK - 00h = INTERNALREF - 01h = IMPORTORDINAL - 02h = IMPORTNAME - 03h = OSFIXUP - 04h = ADDITIVE - - DW Offset within this segment of the source chain. - If the ADDITIVE flag is set, then target value is added to - the source contents, instead of replacing the source and - following the chain. The source chain is an 0FFFFh - terminated linked list within this segment of all - references to the target. - - The target value has four types that are defined in the flag - byte field. The following are the formats for each target - type: - - INTERNALREF - - DB Segment number for a fixed segment, or 0FFh for a - movable segment. - - DB 0 - - DW Offset into segment if fixed segment, or ordinal - number index into Entry Table if movable segment. - - IMPORTNAME - - DW Index into module reference table for the imported - module. - - DW Offset within Imported Names Table to procedure name - string. - - IMPORTORDINAL - - DW Index into module reference table for the imported - module. - DW Procedure ordinal number. - - OSFIXUP - - DW Operating system fixup type. - Floating-point fixups. - 0001h = FIARQQ, FJARQQ - 0002h = FISRQQ, FJSRQQ - 0003h = FICRQQ, FJCRQQ - 0004h = FIERQQ - 0005h = FIDRQQ - 0006h = FIWRQQ - - DW 0 - -====================================================================== - -Microsoft is a registered trademark and Windows is a trademark of -Microsoft Corporation. - -Additional reference words: 3.0 |