summary refs log tree commit diff
path: root/cards
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--cards.3217
-rw-r--r--cards.c428
-rw-r--r--cards.h80
3 files changed, 0 insertions, 725 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