From beba76119fbc8e29bf22093bfa54316ad2591d30 Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Thu, 22 Aug 2019 15:43:24 -0400 Subject: Remove games --- .gitignore | 3 +- Makefile | 14 +- asset.h | 72 --------- freecell.c | 484 ------------------------------------------------------------- layout.h | 110 -------------- sol.c | 393 ------------------------------------------------- stack.h | 108 -------------- 7 files changed, 7 insertions(+), 1177 deletions(-) delete mode 100644 asset.h delete mode 100644 freecell.c delete mode 100644 layout.h delete mode 100644 sol.c delete mode 100644 stack.h diff --git a/.gitignore b/.gitignore index c15f5a2..0ca9d1f 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,4 @@ FREECELL.EXE SOL.EXE config.mk dump -freecell -sol +example diff --git a/Makefile b/Makefile index 073f0be..8990dd0 100644 --- a/Makefile +++ b/Makefile @@ -2,18 +2,16 @@ CFLAGS += -std=c99 -Wall -Wextra -Wpedantic include config.mk -BINS = dump freecell sol +BINS = dump -all: $(BINS) +all: ${BINS} -$(BINS): cards.o +${BINS}: cards.o .o: - $(CC) $(LDFLAGS) $< cards.o $(LDLIBS) -o $@ + ${CC} ${LDFLAGS} $< cards.o ${LDLIBS} -o $@ -cards.o dump.o freecell.o sol.o: cards.h - -freecell.o sol.o: asset.h layout.h stack.h +cards.o dump.o: cards.h clean: - rm -f $(BINS) *.o *.bmp + rm -f ${BINS} *.o *.bmp diff --git a/asset.h b/asset.h deleted file mode 100644 index cc37709..0000000 --- a/asset.h +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright (C) 2019 C. McEnroe - * - * 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 . - */ - -#ifndef ASSET_H -#define ASSET_H - -#include -#include -#include -#include - -struct Paths { - char *base; - char *pref; -}; - -static inline int assetPaths(struct Paths *paths) { - paths->base = SDL_GetBasePath(); - if (!paths->base) return -1; - paths->pref = SDL_GetPrefPath("Causal Agency", "Entertainment Pack"); - if (!paths->pref) return -1; - return 0; -} - -static inline SDL_RWops * -assetOpen(const struct Paths *paths, const char *names[], size_t len) { - const char *dirs[3] = { paths->pref, paths->base, "" }; - for (size_t i = 0; i < 3; ++i) { - for (size_t j = 0; j < len; ++j) { - char path[1024]; - snprintf(path, sizeof(path), "%s%s", dirs[i], names[j]); - SDL_RWops *rw = SDL_RWFromFile(path, "rb"); - if (rw) return rw; - } - } - return NULL; -} - -static inline SDL_RWops *assetOpenCards(const struct Paths *paths) { - const char *names[3] = { "CARDS.DLL", "SOL.EXE", "cards.dll" }; - SDL_RWops *rw = assetOpen(paths, names, 3); - if (rw) return rw; - char msg[4096]; - snprintf( - msg, sizeof(msg), "%s or %s not found in:\n%s\n%s", - names[0], names[1], paths->pref, paths->base - ); - SDL_ShowSimpleMessageBox( - SDL_MESSAGEBOX_ERROR, "Entertainment Pack", msg, NULL - ); - return NULL; -} - -static inline SDL_RWops *assetOpenFreeCell(const struct Paths *paths) { - const char *names[2] = { "FREECELL.EXE", "freecell.exe" }; - return assetOpen(paths, names, 2); -} - -#endif diff --git a/freecell.c b/freecell.c deleted file mode 100644 index b7f6378..0000000 --- a/freecell.c +++ /dev/null @@ -1,484 +0,0 @@ -/* Copyright (C) 2019 C. McEnroe - * - * 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 . - */ - -#include -#include -#include -#include -#include - -#include "asset.h" -#include "cards.h" -#include "layout.h" -#include "stack.h" - -enum { - Foundation1, - Foundation2, - Foundation3, - Foundation4, - Cell1, - Cell2, - Cell3, - Cell4, - Tableau1, - Tableau2, - Tableau3, - Tableau4, - Tableau5, - Tableau6, - Tableau7, - Tableau8, - StacksLen, -}; - -static struct Stack stacks[StacksLen]; - -static struct { - bool avail; - uint dst; - uint src; -} undo; - -static uint kingFace = Cards_KingRight; - -static void gameDeal(void) { - for (uint i = 0; i < StacksLen; ++i) { - stackClear(&stacks[i]); - } - struct Stack deck = {0}; - for (Card i = 1; i <= 52; ++i) { - stackPush(&deck, i); - } - stackShuffle(&deck); - for (uint i = Tableau1; i <= Tableau8; ++i) { - stackMoveTo(&stacks[i], &deck, (i < Tableau5 ? 7 : 6)); - } - undo.avail = false; - kingFace = Cards_KingRight; -} - -static bool gameWin(void) { - for (uint i = Foundation1; i <= Foundation4; ++i) { - if (stacks[i].len != 13) return false; - } - return true; -} - -static bool gameFind(uint *stack, Card card) { - for (*stack = 0; *stack < StacksLen; ++*stack) { - for (uint i = 0; i < stacks[*stack].len; ++i) { - if (stacks[*stack].cards[i] == card) return true; - } - } - return false; -} - -static bool gameAvail(Card card) { - uint stack; - assert(gameFind(&stack, card)); - if (stack <= Foundation4) return false; - return card == stackTop(&stacks[stack]); -} - -static bool gameMove(uint dst, Card card) { - uint src; - assert(gameFind(&src, card)); - Card top = stackTop(&stacks[dst]); - - if (src == dst) return false; - if (dst >= Cell1 && dst <= Cell4) { - if (stacks[dst].len) return false; - kingFace = Cards_KingLeft; - } - if (dst >= Foundation1 && dst <= Foundation4) { - if (!top && cardRank(card) != Cards_A) return false; - if (top && cardSuit(card) != cardSuit(top)) return false; - if (top && cardRank(card) != cardRank(top) + 1) return false; - kingFace = Cards_KingRight; - } - if (dst >= Tableau1 && dst <= Tableau8) { - if (top && cardColor(card) == cardColor(top)) return false; - if (top && cardRank(card) != cardRank(top) - 1) return false; - } - - undo.dst = src; - undo.src = dst; - undo.avail = true; - stackPush(&stacks[dst], stackPop(&stacks[src])); - return true; -} - -static bool gameUndo(void) { - if (!undo.avail) return false; - stackPush(&stacks[undo.dst], stackPop(&stacks[undo.src])); - undo.avail = false; - return true; -} - -static bool gameAuto(void) { - Card min[2] = { Cards_K, Cards_K }; - for (uint i = Cell1; i <= Tableau8; ++i) { - for (uint j = 0; j < stacks[i].len; ++j) { - Card card = stacks[i].cards[j]; - if (cardRank(card) < min[cardColor(card)]) { - min[cardColor(card)] = cardRank(card); - } - } - } - for (uint i = Cell1; i <= Tableau8; ++i) { - Card card = stackTop(&stacks[i]); - if (!card) continue; - if (cardRank(card) > Cards_2) { - if (min[!cardColor(card)] < cardRank(card)) continue; - } - for (uint dst = Foundation1; dst <= Foundation4; ++dst) { - if (gameMove(dst, card)) return true; - } - } - return false; -} - -enum { - CardWidth = Cards_CardWidth, - CardHeight = Cards_CardHeight, - - CellX = 0, - CellY = 0, - - KingMarginX = 13, - KingX = CellX + 4 * CardWidth + KingMarginX, - KingY = 18, - KingPadX = 3, - KingPadY = 3, - KingWidth = Cards_KingWidth + 2 * KingPadX, - KingHeight = Cards_KingHeight + 2 * KingPadY, - - FoundationX = KingX + KingWidth + KingMarginX, - FoundationY = CellY, - - StackMarginX = 7, - StackMarginY = 10, - - TableauX = StackMarginX, - TableauY = CellY + CardHeight + StackMarginY, - FanDownDeltaY = 17, - - KingWinMarginX = 10, - KingWinMarginY = 10, - KingWinX = KingWinMarginX, - KingWinY = CellY + CardHeight + KingWinMarginY, - KingWinWidth = 320, - KingWinHeight = 320, - - WindowWidth = 8 * CardWidth + 9 * StackMarginX + 1, - WindowHeight = KingWinY + KingWinHeight + KingWinMarginY, -}; - -static const struct Style FanDown = { 1, 0, 0, 0, FanDownDeltaY }; - -static struct SDL_Rect stackRects[StacksLen]; -static struct Layout layout; -static struct List reveal; - -static void updateLayout(void) { - layoutClear(&layout); - - SDL_Rect cell = { CellX, CellY, CardWidth, CardHeight }; - for (uint i = Cell1; i <= Cell4; ++i) { - stackRects[i] = cell; - layoutStack(&layout, &cell, &stacks[i], &Flat); - cell.x += CardWidth; - } - - SDL_Rect found = { FoundationX, FoundationY, CardWidth, CardHeight }; - for (uint i = Foundation1; i <= Foundation4; ++i) { - stackRects[i] = found; - layoutStack(&layout, &found, &stacks[i], &Flat); - found.x += CardWidth; - } - - SDL_Rect table = { TableauX, TableauY, CardWidth, CardHeight }; - for (uint i = Tableau1; i <= Tableau8; ++i) { - stackRects[i] = table; - stackRects[i].h = WindowHeight; - SDL_Rect rect = table; - layoutStack(&layout, &rect, &stacks[i], &FanDown); - table.x += CardWidth + StackMarginX; - } -} - -static void revealRank(Card rank) { - for (uint i = 0; i < layout.main.len; ++i) { - struct Item item = layout.main.items[i]; - if (cardRank(item.card) != rank) continue; - listPush(&reveal, &item.rect, item.card); - } -} - -static bool keyDown(SDL_KeyboardEvent key) { - switch (key.keysym.sym) { - case SDLK_F2: gameDeal(); return true; - case SDLK_BACKSPACE: return gameUndo(); - } - if (key.repeat) return false; - switch (key.keysym.sym) { - break; case SDLK_a: revealRank(Cards_A); - break; case SDLK_2: revealRank(Cards_2); - break; case SDLK_3: revealRank(Cards_3); - break; case SDLK_4: revealRank(Cards_4); - break; case SDLK_5: revealRank(Cards_5); - break; case SDLK_6: revealRank(Cards_6); - break; case SDLK_7: revealRank(Cards_7); - break; case SDLK_8: revealRank(Cards_8); - break; case SDLK_9: revealRank(Cards_9); - break; case SDLK_1: revealRank(Cards_10); - break; case SDLK_0: revealRank(Cards_10); - break; case SDLK_j: revealRank(Cards_J); - break; case SDLK_q: revealRank(Cards_Q); - break; case SDLK_k: revealRank(Cards_K); - break; default: return false; - } - return true; -} - -static bool keyUp(SDL_KeyboardEvent key) { - (void)key; - if (!reveal.len) return false; - listClear(&reveal); - return true; -} - -static bool mouseButtonDown(SDL_MouseButtonEvent button) { - if (button.button != SDL_BUTTON_RIGHT) return false; - struct SDL_Point point = { button.x, button.y }; - struct Item *item = listFind(&layout.main, &point); - if (!item) return false; - listPush(&reveal, &item->rect, item->card); - return true; -} - -static bool mouseButtonUp(SDL_MouseButtonEvent button) { - struct SDL_Point point = { button.x, button.y }; - - if (button.button == SDL_BUTTON_RIGHT) { - if (!reveal.len) return false; - listClear(&reveal); - return true; - } - - if (button.clicks % 2 == 0) { - Card card = layout.dragItem.card; - if (!card) { - struct Item *item = listFind(&layout.main, &point); - if (!item) return false; - card = item->card; - } - if (!gameAvail(card)) return false; - for (uint dst = Cell1; dst <= Cell4; ++dst) { - if (gameMove(dst, card)) break; - } - layout.dragItem.card = 0; - return true; - } - - if (layout.dragItem.card) { - for (uint dst = 0; dst < StacksLen; ++dst) { - if (SDL_PointInRect(&point, &stackRects[dst])) { - if (gameMove(dst, layout.dragItem.card)) break; - } - } - layout.dragItem.card = 0; - return true; - } - - struct Item *item = listFind(&layout.main, &point); - if (!item) return false; - if (!gameAvail(item->card)) return false; - layout.dragItem = *item; - return true; -} - -static SDL_Renderer *render; - -static void renderOutline(SDL_Rect rect, bool out) { - int right = rect.x + rect.w - 1; - int bottom = rect.y + rect.h - 1; - SDL_Point topLeft[3] = { - { rect.x, bottom - 1 }, - { rect.x, rect.y }, - { right - 1, rect.y }, - }; - SDL_Point bottomRight[3] = { - { rect.x + 1, bottom }, - { right, bottom }, - { right, rect.y + 1 }, - }; - SDL_SetRenderDrawColor(render, 0x00, 0x00, 0x00, 0xFF); - SDL_RenderDrawLines(render, out ? bottomRight : topLeft, 3); - SDL_SetRenderDrawColor(render, 0x00, 0xFF, 0x00, 0xFF); - SDL_RenderDrawLines(render, out ? topLeft : bottomRight, 3); -} - -static void renderOutlines(void) { - for (uint i = Foundation1; i <= Cell4; ++i) { - renderOutline(stackRects[i], false); - } -} - -static void renderKing(SDL_Texture *textures[]) { - SDL_Rect box = { KingX, KingY, KingWidth, KingHeight }; - renderOutline(box, true); - if (gameWin()) { - SDL_Rect king = { KingWinX, KingWinY, KingWinWidth, KingWinHeight }; - SDL_RenderCopy(render, textures[Cards_KingWin], NULL, &king); - } else { - SDL_Rect king = { - KingX + KingPadX, KingY + KingPadY, - Cards_KingWidth, Cards_KingHeight, - }; - SDL_RenderCopy(render, textures[kingFace], NULL, &king); - } -} - -static void renderList(SDL_Texture *textures[], const struct List *list) { - for (uint i = 0; i < list->len; ++i) { - SDL_RenderCopy( - render, textures[list->items[i].card], - NULL, &list->items[i].rect - ); - } -} - -static void err(const char *title) { - int error = SDL_ShowSimpleMessageBox( - SDL_MESSAGEBOX_ERROR, title, SDL_GetError(), NULL - ); - if (error) fprintf(stderr, "%s\n", SDL_GetError()); - exit(EXIT_FAILURE); -} - -int main(void) { - if (SDL_Init(SDL_INIT_VIDEO) < 0) err("SDL_Init"); - atexit(SDL_Quit); - - struct Paths paths; - if (assetPaths(&paths) < 0) err("SDL_GetPrefPath"); - - bool kings = false; - struct { - SDL_Surface *cards[Cards_Empty]; - SDL_Surface *kings[Cards_FreeCellCount]; - } surfaces; - - SDL_RWops *rw = assetOpenCards(&paths); - if (!rw) return EXIT_FAILURE; - int error = Cards_LoadCards( - surfaces.cards, Cards_Empty, - rw, Cards_AlphaCorners | Cards_BlackBorders - ); - if (error) err("Cards_LoadCards"); - SDL_RWclose(rw); - - rw = assetOpenFreeCell(&paths); - if (rw) { - kings = true; - int error = Cards_LoadFreeCell( - surfaces.kings, Cards_FreeCellCount, - rw, Cards_ColorKey - ); - if (error) err("Cards_LoadFreeCell"); - SDL_RWclose(rw); - } - - SDL_Window *window; - error = SDL_CreateWindowAndRenderer( - WindowWidth, WindowHeight, SDL_WINDOW_ALLOW_HIGHDPI, - &window, &render - ); - if (error) err("SDL_CreateWindowAndRenderer"); - SDL_SetWindowTitle(window, "FreeCell"); - - SDL_RenderSetIntegerScale(render, SDL_TRUE); - SDL_RenderSetLogicalSize(render, WindowWidth, WindowHeight); - - SDL_Texture *textures[Cards_Empty] = {0}; - SDL_Texture *inverted[Cards_Empty] = {0}; - SDL_Texture *kingTextures[Cards_FreeCellCount] = {0}; - - for (uint i = 0; i < Cards_Empty; ++i) { - if (!surfaces.cards[i]) continue; - - textures[i] = SDL_CreateTextureFromSurface(render, surfaces.cards[i]); - if (!textures[i]) err("SDL_CreateTextureFromSurface"); - - error = Cards_InvertSurface(surfaces.cards[i]); - if (error) err("Cards_InvertSurface"); - - inverted[i] = SDL_CreateTextureFromSurface(render, surfaces.cards[i]); - if (!inverted[i]) err("SDL_CreateTextureFromSurface"); - - SDL_FreeSurface(surfaces.cards[i]); - } - - if (kings) { - for (uint i = 0; i < Cards_FreeCellCount; ++i) { - if (!surfaces.kings[i]) continue; - kingTextures[i] = - SDL_CreateTextureFromSurface(render, surfaces.kings[i]); - if (!kingTextures[i]) err("SDL_CreateTextureFromSurface"); - SDL_FreeSurface(surfaces.kings[i]); - } - } - - srand(time(NULL)); - gameDeal(); - - for (;;) { - updateLayout(); - - SDL_SetRenderDrawColor(render, 0x00, 0xAA, 0x55, 0xFF); - SDL_RenderClear(render); - renderOutlines(); - if (kings) renderKing(kingTextures); - renderList(textures, &layout.main); - renderList(inverted, &layout.drag); - renderList(textures, &reveal); - SDL_RenderPresent(render); - - // TODO: Add more than a frame delay between automatic moves? - if (gameAuto()) continue; - - SDL_Event event; - for (;;) { - SDL_WaitEvent(&event); - if (event.type == SDL_QUIT) { - goto quit; - } else if (event.type == SDL_KEYDOWN) { - if (keyDown(event.key)) break; - } else if (event.type == SDL_KEYUP) { - if (keyUp(event.key)) break; - } else if (event.type == SDL_MOUSEBUTTONDOWN) { - if (mouseButtonDown(event.button)) break; - } else if (event.type == SDL_MOUSEBUTTONUP) { - if (mouseButtonUp(event.button)) break; - } - } - } - -quit: - SDL_Quit(); -} diff --git a/layout.h b/layout.h deleted file mode 100644 index cbff6df..0000000 --- a/layout.h +++ /dev/null @@ -1,110 +0,0 @@ -/* Copyright (C) 2019 C. McEnroe - * - * 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 . - */ - -#ifndef LAYOUT_H -#define LAYOUT_H - -#include -#include - -#include "stack.h" - -#ifndef LAYOUT_CAP -#define LAYOUT_CAP 64 -#endif - -typedef unsigned uint; - -struct Item { - SDL_Rect rect; - Card card; -}; - -struct List { - uint len; - struct Item items[LAYOUT_CAP]; -}; - -static inline void listClear(struct List *list) { - list->len = 0; -} - -static inline void -listPush(struct List *list, const struct SDL_Rect *rect, Card card) { - assert(list->len < LAYOUT_CAP); - struct Item item = { *rect, card }; - list->items[list->len++] = item; -} - -static inline struct Item *listFind(struct List *list, const SDL_Point *point) { - for (uint i = list->len - 1; i < list->len; --i) { - if (SDL_PointInRect(point, &list->items[i].rect)) { - return &list->items[i]; - } - } - return NULL; -} - -struct Layout { - struct List main; - struct List drag; - struct Item dragItem; -}; - -static inline void layoutClear(struct Layout *layout) { - listClear(&layout->main); - listClear(&layout->drag); -} - -struct Style { - uint increment; - int deltaXBack; - int deltaYBack; - int deltaXFront; - int deltaYFront; -}; - -enum { - SquareIncrement = 24 / 3, - SquareDeltaX = 2, - SquareDeltaY = 1, -}; -static const struct Style Flat = { 1, 0, 0, 0, 0 }; -static const struct Style Square = { - SquareIncrement, SquareDeltaX, SquareDeltaY, SquareDeltaX, SquareDeltaY, -}; - -static inline void -layoutStack( - struct Layout *layout, SDL_Rect *rect, - const struct Stack *stack, const struct Style *style -) { - struct List *list = &layout->main; - for (uint i = 0; i < stack->len; ++i) { - Card card = stack->cards[i]; - if (card == layout->dragItem.card) { - list = &layout->drag; - *rect = layout->dragItem.rect; - } - listPush(list, rect, card); - if ((i + 1) % style->increment == 0) { - rect->x += (card > 0 ? style->deltaXFront : style->deltaXBack); - rect->y += (card > 0 ? style->deltaYFront : style->deltaYBack); - } - } -} - -#endif diff --git a/sol.c b/sol.c deleted file mode 100644 index cf643f2..0000000 --- a/sol.c +++ /dev/null @@ -1,393 +0,0 @@ -/* Copyright (C) 2019 C. McEnroe - * - * 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 . - */ - -#include -#include -#include -#include -#include - -#include "asset.h" -#include "cards.h" -#include "layout.h" -#include "stack.h" - -#define ARRAY_LEN(a) (sizeof(a) / sizeof((a)[0])) - -enum { - Stock, - Waste1, - Waste3, - Foundation1, - Foundation2, - Foundation3, - Foundation4, - Tableau1, - Tableau2, - Tableau3, - Tableau4, - Tableau5, - Tableau6, - Tableau7, - StacksLen, -}; - -static struct Stack stacks[StacksLen]; - -// TODO: Scoring method, score, time. -static struct { - uint draw; -} game = { - .draw = 3, -}; - -typedef void StackFn(struct Stack *dst, struct Stack *src, Uint8 len); - -static struct { - StackFn *fn; - uint dst; - uint src; - uint len; -} undo; - -static void gameDo(StackFn *fn, uint dst, uint src, uint len) { - undo.fn = fn; - undo.dst = src; - undo.src = dst; - undo.len = len; - fn(&stacks[dst], &stacks[src], len); -} - -static bool gameUndo(void) { - if (!undo.fn) return false; - undo.fn(&stacks[undo.dst], &stacks[undo.src], undo.len); - undo.fn = NULL; - return true; -} - -static void gameDeal(void) { - undo.fn = NULL; - for (uint i = 0; i < StacksLen; ++i) { - stackClear(&stacks[i]); - } - for (Card i = 1; i <= 52; ++i) { - stackPush(&stacks[Stock], -i); - } - stackShuffle(&stacks[Stock]); - for (uint i = Tableau1; i <= Tableau7; ++i) { - stackMoveTo(&stacks[i], &stacks[Stock], i - Tableau1); - stackFlipTo(&stacks[i], &stacks[Stock], 1); - } -} - -static void gameDraw(void) { - stackMoveTo(&stacks[Waste1], &stacks[Waste3], stacks[Waste3].len); - if (stacks[Stock].len) { - if (game.draw > 1) { - gameDo(stackFlipTo, Waste3, Stock, game.draw); - } else { - gameDo(stackFlipTo, Waste1, Stock, 1); - } - } else { - gameDo(stackFlipTo, Stock, Waste1, stacks[Waste1].len); - } -} - -static bool gameFind(uint *stack, uint *index, Card card) { - for (*stack = 0; *stack < StacksLen; ++*stack) { - for (*index = 0; *index < stacks[*stack].len; ++*index) { - if (stacks[*stack].cards[*index] == card) return true; - } - } - return false; -} - -static bool gameAvail(Card card) { - uint stack, index; - if (card < 0) return false; - if (!gameFind(&stack, &index, card)) return false; - - bool top = (card == stackTop(&stacks[stack])); - if (stack == Waste1) { - return top && !stacks[Waste3].len; - } else if (stack == Waste3) { - return top; - } else if (stack >= Foundation1 && stack <= Foundation4) { - return top; - } else if (stack >= Tableau1 && stack <= Tableau7) { - return true; - } else { - return false; - } -} - -static bool gameReveal(Card card) { - uint stack, index; - if (!gameFind(&stack, &index, card)) return false; - if (stack < Tableau1 || stack > Tableau7) return false; - if (card != stackTop(&stacks[stack])) return false; - if (card > 0) return false; - gameDo(stackFlipTo, stack, stack, 1); - return true; -} - -static bool gameMove(uint dest, Card card) { - uint source, index; - if (!gameFind(&source, &index, card)) return false; - if (source == dest) return false; - - uint count = stacks[source].len - index; - Card destTop = stackTop(&stacks[dest]); - - if (dest >= Foundation1 && dest <= Foundation4) { - if (count > 1) return false; - if (!destTop && cardRank(card) != Cards_A) return false; - if (destTop && cardSuit(card) != cardSuit(destTop)) return false; - if (destTop && cardRank(card) != cardRank(destTop) + 1) return false; - gameDo(stackMoveTo, dest, source, 1); - return true; - } - - if (dest >= Tableau1 && dest <= Tableau7) { - if (!destTop && cardRank(card) != Cards_K) return false; - if (destTop && cardColor(card) == cardColor(destTop)) return false; - if (destTop && cardRank(card) != cardRank(destTop) - 1) return false; - gameDo(stackMoveTo, dest, source, count); - return true; - } - - return false; -} - -enum { - CardWidth = Cards_CardWidth, - CardHeight = Cards_CardHeight, - - StackMarginX = 11, - StackMarginY = 6, - - StockX = StackMarginX, - StockY = StackMarginY, - - WasteX = StockX + CardWidth + StackMarginX, - WasteY = StackMarginY, - - FoundationX = WasteX + 2 * (CardWidth + StackMarginX), - FoundationY = StackMarginY, - - TableauX = StackMarginX, - TableauY = StockY + CardHeight + StackMarginY, - - FanRightDeltaX = 14, - FanDownDeltaYBack = 3, - FanDownDeltaYFront = 15, - - WindowWidth = 7 * CardWidth + 8 * StackMarginX, - WindowHeight = 2 * (StackMarginY + CardHeight) - + 6 * FanDownDeltaYBack - + 12 * FanDownDeltaYFront - + StackMarginY, -}; - -static const struct Style FanRight = { - 1, 0, 0, FanRightDeltaX, SquareDeltaY -}; -static const struct Style FanDown = { - 1, 0, FanDownDeltaYBack, 0, FanDownDeltaYFront -}; - -static struct SDL_Rect stackRects[StacksLen]; -static struct Layout layout; -static uint backTexture = Cards_Back1; - -static void updateLayout(void) { - layoutClear(&layout); - - SDL_Rect stock = { StockX, StockY, CardWidth, CardHeight }; - stackRects[Stock] = stock; - listPush(&layout.main, &stock, Cards_O); - layoutStack(&layout, &stock, &stacks[Stock], &Square); - - SDL_Rect waste = { WasteX, WasteY, CardWidth, CardHeight }; - layoutStack(&layout, &waste, &stacks[Waste1], &Square); - layoutStack(&layout, &waste, &stacks[Waste3], &FanRight); - - SDL_Rect found = { FoundationX, FoundationY, CardWidth, CardHeight }; - for (uint i = Foundation1; i <= Foundation4; ++i) { - stackRects[i] = found; - listPush(&layout.main, &found, Cards_Empty); - SDL_Rect rect = found; - layoutStack(&layout, &rect, &stacks[i], &Square); - found.x += CardWidth + StackMarginX; - } - - SDL_Rect table = { TableauX, TableauY, CardWidth, CardHeight }; - for (uint i = Tableau1; i <= Tableau7; ++i) { - stackRects[i] = table; - stackRects[i].h = WindowHeight; - SDL_Rect rect = table; - layoutStack(&layout, &rect, &stacks[i], &FanDown); - table.x += CardWidth + StackMarginX; - } -} - -static bool keyDown(SDL_KeyboardEvent key) { - switch (key.keysym.sym) { - case SDLK_F2: gameDeal(); return true; - case SDLK_BACKSPACE: return gameUndo(); - case SDLK_b: { - backTexture -= Cards_Back1; - backTexture += 1; - backTexture %= 12; - backTexture += Cards_Back1; - return true; - } - case SDLK_d: { - game.draw = (game.draw == 1 ? 3 : 1); - gameDeal(); - return true; - } - default: return false; - } -} - -static bool mouseButtonDown(SDL_MouseButtonEvent button) { - struct SDL_Point point = { button.x, button.y }; - if (SDL_PointInRect(&point, &stackRects[Stock])) { - gameDraw(); - return true; - } - struct Item *item = listFind(&layout.main, &point); - if (!item) return false; - if (!gameAvail(item->card)) return gameReveal(item->card); - if (button.clicks % 2 == 0) { - for (uint dest = Foundation1; dest <= Foundation4; ++dest) { - if (gameMove(dest, item->card)) return true; - } - return false; - } - layout.dragItem = *item; - return true; -} - -static bool mouseButtonUp(SDL_MouseButtonEvent button) { - (void)button; - if (!layout.dragItem.card) return false; - for (uint dest = 0; dest < StacksLen; ++dest) { - if (SDL_HasIntersection(&layout.dragItem.rect, &stackRects[dest])) { - if (gameMove(dest, layout.dragItem.card)) break; - } - } - layout.dragItem.card = 0; - return true; -} - -static bool mouseMotion(SDL_MouseMotionEvent motion) { - if (!motion.state) return false; - layout.dragItem.rect.x += motion.xrel; - layout.dragItem.rect.y += motion.yrel; - return true; -} - -static SDL_Renderer *render; -static SDL_Texture *textures[Cards_CardCount]; - -static void renderList(const struct List *list) { - for (uint i = 0; i < list->len; ++i) { - int tex = list->items[i].card; - if (tex < 0) tex = backTexture; - SDL_RenderCopy(render, textures[tex], NULL, &list->items[i].rect); - } -} - -static void err(const char *title) { - int error = SDL_ShowSimpleMessageBox( - SDL_MESSAGEBOX_ERROR, title, SDL_GetError(), NULL - ); - if (error) fprintf(stderr, "%s\n", SDL_GetError()); - exit(EXIT_FAILURE); -} - -int main(void) { - if (SDL_Init(SDL_INIT_VIDEO) < 0) err("SDL_Init"); - atexit(SDL_Quit); - - struct Paths paths; - if (assetPaths(&paths) < 0) err("SDL_GetPrefPath"); - - SDL_RWops *rw = assetOpenCards(&paths); - if (!rw) return EXIT_FAILURE; - - SDL_Surface *surfaces[Cards_CardCount]; - int error = Cards_LoadCards( - surfaces, Cards_CardCount, - rw, Cards_ColorKey | Cards_AlphaCorners | Cards_BlackBorders - ); - if (error) err("Cards_LoadCards"); - SDL_RWclose(rw); - - SDL_Window *window; - error = SDL_CreateWindowAndRenderer( - WindowWidth, WindowHeight, SDL_WINDOW_ALLOW_HIGHDPI, - &window, &render - ); - if (error) err("SDL_CreateWindowAndRenderer"); - SDL_SetWindowTitle(window, "Solitaire"); - - SDL_RenderSetIntegerScale(render, SDL_TRUE); - SDL_RenderSetLogicalSize(render, WindowWidth, WindowHeight); - - for (uint i = 0; i < Cards_CardCount; ++i) { - textures[i] = NULL; - if (!surfaces[i]) continue; - textures[i] = SDL_CreateTextureFromSurface(render, surfaces[i]); - if (!textures[i]) err("SDL_CreateTextureFromSurface"); - SDL_FreeSurface(surfaces[i]); - } - - srand(time(NULL)); - backTexture = Cards_Back1 + randUniform(12); - gameDeal(); - - for (;;) { - updateLayout(); - - SDL_SetRenderDrawColor(render, 0x00, 0xAA, 0x55, 0xFF); - SDL_RenderClear(render); - renderList(&layout.main); - renderList(&layout.drag); - SDL_RenderPresent(render); - - SDL_Event event; - for (;;) { - SDL_WaitEvent(&event); - if (event.type == SDL_QUIT) { - goto quit; - } else if (event.type == SDL_KEYDOWN) { - if (keyDown(event.key)) break; - } else if (event.type == SDL_MOUSEBUTTONDOWN) { - if (mouseButtonDown(event.button)) break; - } else if (event.type == SDL_MOUSEBUTTONUP) { - if (mouseButtonUp(event.button)) break; - } else if (event.type == SDL_MOUSEMOTION) { - if (mouseMotion(event.motion)) break; - } - } - } - -quit: - SDL_Quit(); -} diff --git a/stack.h b/stack.h deleted file mode 100644 index f5140df..0000000 --- a/stack.h +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright (C) 2019 C. McEnroe - * - * 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 . - */ - -#ifndef STACK_H -#define STACK_H - -#include -#include -#include - -#include "cards.h" - -#ifndef STACK_CAP -#define STACK_CAP 52 -#endif - -typedef Sint8 Card; - -static inline int cardSuit(Card card) { - card = abs(card); - if (card > Cards_Spade) { - return Cards_Spade; - } else if (card > Cards_Heart) { - return Cards_Heart; - } else if (card > Cards_Diamond) { - return Cards_Diamond; - } else { - return Cards_Club; - } -} - -static inline int cardColor(Card card) { - return cardSuit(card) == Cards_Diamond || cardSuit(card) == Cards_Heart; -} - -static inline int cardRank(Card card) { - return abs(card) - cardSuit(card); -} - -struct Stack { - Uint8 len; - Card cards[STACK_CAP]; -}; - -static inline void stackClear(struct Stack *stack) { - stack->len = 0; -} - -static inline void stackPush(struct Stack *stack, Card card) { - assert(stack->len < STACK_CAP); - stack->cards[stack->len++] = card; -} - -static inline Card stackPop(struct Stack *stack) { - if (!stack->len) return 0; - return stack->cards[--stack->len]; -} - -static inline Card stackTop(const struct Stack *stack) { - if (!stack->len) return 0; - return stack->cards[stack->len - 1]; -} - -static inline void stackFlipTo(struct Stack *dst, struct Stack *src, Uint8 n) { - if (n > src->len) n = src->len; - for (Uint8 i = 0; i < n; ++i) { - stackPush(dst, -stackPop(src)); - } -} - -static inline void stackMoveTo(struct Stack *dst, struct Stack *src, Uint8 n) { - if (n > src->len) n = src->len; - for (Uint8 i = 0; i < n; ++i) { - stackPush(dst, src->cards[src->len - n + i]); - } - src->len -= n; -} - -static inline int randUniform(int bound) { - for (;;) { - int r = rand(); - if (r >= RAND_MAX % bound) return r % bound; - } -} - -static inline void stackShuffle(struct Stack *stack) { - for (Uint8 i = stack->len - 1; i > 0; --i) { - Uint8 j = randUniform(i + 1); - Card x = stack->cards[i]; - stack->cards[i] = stack->cards[j]; - stack->cards[j] = x; - } -} - -#endif -- cgit 1.4.1 From 1088b1b132a779bae6816e0e01795d4edd923ddc Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Thu, 22 Aug 2019 15:54:24 -0400 Subject: Add FILES section --- cards.3 | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/cards.3 b/cards.3 index 7882756..b4dd61d 100644 --- a/cards.3 +++ b/cards.3 @@ -1,4 +1,4 @@ -.Dd March 28, 2019 +.Dd August 22, 2019 .Dt CARDS 3 .Os . @@ -173,6 +173,16 @@ Upon successful completion, the value 0 is returned; otherwise the value -1 is returned. . +.Sh FILES +The +.Lk https://code.causal.agency/june/cards.dll "cards.dll repository" +contains various versions +of the files +.Pa CARDS.DLL , +.Pa FREECELL.EXE +and +.Pa SOL.EXE . +. .Sh ERRORS Error messages are set with .Fn SDL_SetError -- cgit 1.4.1 From 6c49f0bd549c3b6db2b047e5e7e19f0d26cff9f4 Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Thu, 22 Aug 2019 19:46:13 -0400 Subject: Add example --- Makefile | 4 +-- cards.3 | 4 +++ example.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 example.c diff --git a/Makefile b/Makefile index 8990dd0..488245d 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CFLAGS += -std=c99 -Wall -Wextra -Wpedantic include config.mk -BINS = dump +BINS = dump example all: ${BINS} @@ -11,7 +11,7 @@ ${BINS}: cards.o .o: ${CC} ${LDFLAGS} $< cards.o ${LDLIBS} -o $@ -cards.o dump.o: cards.h +cards.o dump.o example.o: cards.h clean: rm -f ${BINS} *.o *.bmp diff --git a/cards.3 b/cards.3 index b4dd61d..26c142c 100644 --- a/cards.3 +++ b/cards.3 @@ -183,6 +183,10 @@ of the files and .Pa SOL.EXE . . +.Sh EXAMPLES +See +.Pa example.c . +. .Sh ERRORS Error messages are set with .Fn SDL_SetError diff --git a/example.c b/example.c new file mode 100644 index 0000000..8790d65 --- /dev/null +++ b/example.c @@ -0,0 +1,103 @@ +/* Copyright (C) 2019 C. McEnroe + * + * 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 . + */ + +#include +#include + +#include + +#include "cards.h" + +static void err(const char *title) { + int error = SDL_ShowSimpleMessageBox( + SDL_MESSAGEBOX_ERROR, title, SDL_GetError(), NULL + ); + if (error) fprintf(stderr, "%s\n", SDL_GetError()); + SDL_Quit(); + exit(EXIT_FAILURE); +} + +enum { + MarginX = 11, + MarginY = 6, + DeltaX = 14, + DeltaY = 6 + Cards_CardHeight, + WindowWidth = MarginX + 12 * DeltaX + Cards_CardWidth + MarginX, + WindowHeight = MarginY + 4 * DeltaY, +}; + +int main(void) { + if (SDL_Init(SDL_INIT_VIDEO) < 0) err("SDL_Init"); + + struct SDL_RWops *rw = SDL_RWFromFile("CARDS.DLL", "rb"); + if (!rw) err("SDL_RWFromFile"); + + SDL_Surface *surfaces[Cards_CardCount]; + int error = Cards_LoadCards( + surfaces, Cards_CardCount, + rw, Cards_ColorKey | Cards_AlphaCorners | Cards_BlackBorders + ); + if (error) err("Cards_LoadCards"); + SDL_RWclose(rw); + + SDL_Window *window; + SDL_Renderer *render; + error = SDL_CreateWindowAndRenderer( + WindowWidth, WindowHeight, SDL_WINDOW_ALLOW_HIGHDPI, + &window, &render + ); + if (error) err("SDL_CreateWindowAndRenderer"); + SDL_SetWindowTitle(window, "Cards Example"); + + SDL_RenderSetIntegerScale(render, SDL_TRUE); + SDL_RenderSetLogicalSize(render, WindowWidth, WindowHeight); + + SDL_Texture *textures[Cards_CardCount]; + for (int i = 0; i < Cards_CardCount; ++i) { + textures[i] = NULL; + if (!surfaces[i]) continue; + textures[i] = SDL_CreateTextureFromSurface(render, surfaces[i]); + if (!textures[i]) err("SDL_CreateTextureFromSurface"); + SDL_FreeSurface(surfaces[i]); + } + + SDL_Rect rects[Cards_CardCount] = {0}; + for (int i = 1; i <= 52; ++i) { + rects[i].x = MarginX + (i - 1) % 13 * DeltaX; + rects[i].y = MarginY + (i - 1) / 13 * DeltaY; + rects[i].w = Cards_CardWidth; + rects[i].h = Cards_CardHeight; + } + + for (;;) { + SDL_SetRenderDrawColor(render, 0x00, 0xAA, 0x55, 0xFF); + SDL_RenderClear(render); + for (int i = 0; i < Cards_CardCount; ++i) { + if (!rects[i].w) continue; + SDL_RenderCopy(render, textures[i], NULL, &rects[i]); + } + SDL_RenderPresent(render); + + SDL_Event event; + for (;;) { + SDL_WaitEvent(&event); + if (event.type == SDL_QUIT) goto quit; + } + } + +quit: + SDL_Quit(); +} -- cgit 1.4.1 From aefea3071a519c96ee57e2461cc316df0fe193f1 Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Thu, 22 Aug 2019 19:54:24 -0400 Subject: Add README --- Makefile | 3 + README.3 | 231 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 234 insertions(+) create mode 100644 README.3 diff --git a/Makefile b/Makefile index 488245d..b8db2fb 100644 --- a/Makefile +++ b/Makefile @@ -15,3 +15,6 @@ cards.o dump.o example.o: cards.h clean: rm -f ${BINS} *.o *.bmp + +README.3: cards.3 + ln cards.3 README.3 diff --git a/README.3 b/README.3 new file mode 100644 index 0000000..26c142c --- /dev/null +++ b/README.3 @@ -0,0 +1,231 @@ +.Dd August 22, 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 FILES +The +.Lk https://code.causal.agency/june/cards.dll "cards.dll repository" +contains various versions +of the files +.Pa CARDS.DLL , +.Pa FREECELL.EXE +and +.Pa SOL.EXE . +. +.Sh EXAMPLES +See +.Pa example.c . +. +.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 -- cgit 1.4.1 From 4d897ab0fb6ea2162d7c7d946e7b70b9259a349b Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Sun, 15 Dec 2019 16:51:18 -0500 Subject: Use symlink for README.3 --- Makefile | 3 - README.3 | 232 +-------------------------------------------------------------- 2 files changed, 1 insertion(+), 234 deletions(-) mode change 100644 => 120000 README.3 diff --git a/Makefile b/Makefile index b8db2fb..488245d 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,3 @@ cards.o dump.o example.o: cards.h clean: rm -f ${BINS} *.o *.bmp - -README.3: cards.3 - ln cards.3 README.3 diff --git a/README.3 b/README.3 deleted file mode 100644 index 26c142c..0000000 --- a/README.3 +++ /dev/null @@ -1,231 +0,0 @@ -.Dd August 22, 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 FILES -The -.Lk https://code.causal.agency/june/cards.dll "cards.dll repository" -contains various versions -of the files -.Pa CARDS.DLL , -.Pa FREECELL.EXE -and -.Pa SOL.EXE . -. -.Sh EXAMPLES -See -.Pa example.c . -. -.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/README.3 b/README.3 new file mode 120000 index 0000000..d57bc52 --- /dev/null +++ b/README.3 @@ -0,0 +1 @@ +cards.3 \ No newline at end of file -- cgit 1.4.1 From daf6fd1d716aad3c03b6dadbbd7a4b724acbfece Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Thu, 19 Dec 2019 02:12:01 -0500 Subject: Remove README --- README.3 | 1 - 1 file changed, 1 deletion(-) delete mode 120000 README.3 diff --git a/README.3 b/README.3 deleted file mode 120000 index d57bc52..0000000 --- a/README.3 +++ /dev/null @@ -1 +0,0 @@ -cards.3 \ No newline at end of file -- cgit 1.4.1