From 58bfa35d2159c8866a5cb74fbd7c432664efc924 Mon Sep 17 00:00:00 2001 From: Alex Brown Date: Mon, 1 May 2023 14:42:21 +0100 Subject: [PATCH] First commit --- .gitignore | 39 +++ LICENSE | 325 ++++++++++++++++++++ README.md | 75 +++++ src/PYRAMID.RSG | 9 + src/games.pr | 32 ++ src/global.h | 52 ++++ src/mkgame.bat | 10 + src/pyramid.afl | 4 + src/pyramid.c | 723 ++++++++++++++++++++++++++++++++++++++++++++ src/pyramid.h | 9 + src/pyramid.ms | 4 + src/pyramid.pic | Bin 0 -> 404 bytes src/pyramid.rc | 110 +++++++ src/utils/utils.c | 604 ++++++++++++++++++++++++++++++++++++ src/utils/utils.h | 138 +++++++++ src/utils/utils.lib | Bin 0 -> 6027 bytes src/utils/utils.pr | 13 + 17 files changed, 2147 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 src/PYRAMID.RSG create mode 100644 src/games.pr create mode 100644 src/global.h create mode 100644 src/mkgame.bat create mode 100644 src/pyramid.afl create mode 100644 src/pyramid.c create mode 100644 src/pyramid.h create mode 100644 src/pyramid.ms create mode 100644 src/pyramid.pic create mode 100644 src/pyramid.rc create mode 100644 src/utils/utils.c create mode 100644 src/utils/utils.h create mode 100644 src/utils/utils.lib create mode 100644 src/utils/utils.pr diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..05c6b1a --- /dev/null +++ b/.gitignore @@ -0,0 +1,39 @@ +# Psion SIBO C SDK Compiled and Generated Files +**/*.APP +**/*.app +**/*.IMG +**/*.img +**/*.EXE +**/*.exe +**/*.RSC +**/*.rsc +**/*.RZC +**/*.rzc +#**/*.RSG +#**/*.rsg +**/*.SHD +**/*.shd + +# Psion Debug/Symbol Files +**/*.DBD +**/*.dbd +**/*.SYM +**/*.sym + +# Standard C Compilation Objects and Files +**/*.MAP +**/*.map +**/*.OBJ +**/*.obj + +# Installation Path +INSTALL/** + +# SSD Images +**/*.fat12 +**/*.rom +**/*.ssd + +# Pyramid Specifics +**/*.ZIP +**/*.zip \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a2eb7fe --- /dev/null +++ b/LICENSE @@ -0,0 +1,325 @@ +The GNU General Public License (GPL-2.0) +Version 2, June 1991 +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to share +and change it. By contrast, the GNU General Public License is intended to +guarantee your freedom to share and change free software--to make sure the +software is free for all its users. This General Public License applies to +most of the Free Software Foundation's software and to any other program whose +authors commit to using it. (Some other Free Software Foundation software is +covered by the GNU Library General Public License instead.) You can apply +it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. +Our General Public Licenses are designed to make sure that you have the +freedom to distribute copies of free software (and charge for this service +if you wish), that you receive source code or can get it if you want it, +that you can change the software or use pieces of it in new free programs; +and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to +deny you these rights or to ask you to surrender the rights. These restrictions +translate to certain responsibilities for you if you distribute copies of the +software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or +for a fee, you must give the recipients all the rights that you have. +You must make sure that they, too, receive or can get the source code. +And you must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that +everyone understands that there is no warranty for this free software. +If the software is modified by someone else and passed on, we want its +recipients to know that what they have is not the original, so that any +problems introduced by others will not reflect on the +original authors' reputations. + +Finally, any free program is threatened constantly by software patents. +We wish to avoid the danger that redistributors of a free program will +individually obtain patent licenses, in effect making the program proprietary. +To prevent this, we have made it clear that any patent must be licensed for +everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution +and modification follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice +placed by the copyright holder saying it may be distributed under the terms +of this General Public License. The "Program", below, refers to any such +program or work, and a "work based on the Program" means either the Program +or any derivative work under copyright law: that is to say, a work containing +the Program or a portion of it, either verbatim or with modifications and/or +translated into another language. (Hereinafter, translation is included +without limitation in the term "modification".) +Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not covered +by this License; they are outside its scope. The act of running the Program +is not restricted, and the output from the Program is covered only if its +contents constitute a work based on the Program (independent of having been +made by running the Program). Whether that is true depends on +what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code +as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this +License and to the absence of any warranty; and give any other recipients +of the Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you +may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, +thus forming a work based on the Program, and copy and distribute such +modifications or work under the terms of Section 1 above, provided that you +also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices stating + that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in whole + or in part contains or is derived from the Program or any part thereof, + to be licensed as a whole at no charge to all third parties under + the terms of this License. + + c) If the modified program normally reads commands interactively when run, + you must cause it, when started running for such interactive use in the + most ordinary way, to print or display an announcement including an + appropriate copyright notice and a notice that there is no warranty + (or else, saying that you provide a warranty) and that users may + redistribute the program under these conditions, and telling the user how + to view a copy of this License. (Exception: if the Program itself is + interactive but does not normally print such an announcement, your work + based on the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If identifiable +sections of that work are not derived from the Program, and can be reasonably +considered independent and separate works in themselves, then this License, +and its terms, do not apply to those sections when you distribute them as +separate works. But when you distribute the same sections as part of a whole +which is a work based on the Program, the distribution of the whole must be +on the terms of this License, whose permissions for other licensees extend +to the entire whole, and thus to each and every part +regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your +rights to work written entirely by you; rather, the intent is to exercise +the right to control the distribution of derivative or collective +works based on the Program. + +In addition, mere aggregation of another work not based on the Program with +the Program (or with a work based on the Program) on a volume of a storage +or distribution medium does not bring the other work under +the scope of this License. + +3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable source + code, which must be distributed under the terms of Sections 1 and 2 above + on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three years, to + give any third party, for a charge no more than your cost of physically + performing source distribution, a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of + Sections 1 and 2 above on a medium customarily used + for software interchange; or, + + c) Accompany it with the information you received as to the offer to + distribute corresponding source code. (This alternative is allowed only + for noncommercial distribution and only if you received the program in + object code or executable form with such an offer, in accord + with Subsection b above.) + +The source code for a work means the preferred form of the work for making +modifications to it. For an executable work, complete source code means all +the source code for all modules it contains, plus any associated interface +definition files, plus the scripts used to control compilation and +installation of the executable. However, as a special exception, the source +code distributed need not include anything that is normally distributed +(in either source or binary form) with the major components (compiler, kernel, +and so on) of the operating system on which the executable runs, unless that +component itself accompanies the executable. + +If distribution of executable or object code is made by offering access to +copy from a designated place, then offering equivalent access to copy the +source code from the same place counts as distribution of the source code, +even though third parties are not compelled to copy the source +along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as +expressly provided under this License. Any attempt otherwise to copy, modify, +sublicense or distribute the Program is void, and will automatically terminate +your rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. +However, nothing else grants you permission to modify or distribute the +Program or its derivative works. These actions are prohibited by law if you +do not accept this License. Therefore, by modifying or distributing the Program +(or any work based on the Program), you indicate your acceptance of this +License to do so, and all its terms and conditions for copying, distributing +or modifying the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), +the recipient automatically receives a license from the original licensor +to copy, distribute or modify the Program subject to these terms +and conditions. You may not impose any further restrictions on the recipients' +exercise of the rights granted herein. You are not responsible for enforcing +compliance by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or otherwise) +that contradict the conditions of this License, they do not excuse you from +the conditions of this License. If you cannot distribute so as to satisfy +simultaneously your obligations under this License and any other pertinent +obligations, then as a consequence you may not distribute the Program at all. +For example, if a patent license would not permit royalty-free redistribution +of the Program by all those who receive copies directly or indirectly +through you, then the only way you could satisfy both it and this License +would be to refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents +or other property right claims or to contest validity of any such claims; +this section has the sole purpose of protecting the integrity of the free +software distribution system, which is implemented by public license practices. +Many people have made generous contributions to the wide range of software +distributed through that system in reliance on consistent application of +that system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee +cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a +consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain +countries either by patents or by copyrighted interfaces, the original +copyright holder who places the Program under this License may add an explicit +geographical distribution limitation excluding those countries, so that +distribution is permitted only in or among countries not thus excluded. +In such case, this License incorporates the limitation as if written +in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the +General Public License from time to time. Such new versions will be similar +in spirit to the present version, but may differ in detail to address +new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and conditions +either of that version or of any later version published by the +Free Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published +by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs +whose distribution conditions are different, write to the author to ask for +permission. For software which is copyrighted by the Free Software Foundation, +write to the Free Software Foundation; we sometimes make exceptions for this. +Our decision will be guided by the two goals of preserving the free status of +all derivatives of our free software and of promoting the sharing +and reuse of software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR +THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE +STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE +PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND +PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, +YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL +ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE +OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA +OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES +OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible +use to the public, the best way to achieve this is to make it free software +which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach +them to the start of each source file to most effectively convey the exclusion +of warranty; and each file should have at least the "copyright" line and a +pointer to where the full notice is found. + + One line to give the program's name and a brief idea of what it does. + Copyright (C) {{ year }} {{ organization }} + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when +it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author Gnomovision + comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is + free software, and you are welcome to redistribute it under certain + conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may be +called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + signature of Ty Coon, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..bb3e0e8 --- /dev/null +++ b/README.md @@ -0,0 +1,75 @@ +# Pyramid + +Pyramid, a Patience Card Game for the Psion Series 3 + +©1993 J Cade Roux + +Released under the GNU General Public License v2. + +## Installation + +To install Pyramid, copy `PYRAMID.APP` it to any directory (like `\APP\`) and +install it from the system screen. Alternatively, rename it +`PYRAMID.IMG`, and copy it to the `\IMG\` directory, or any other directory +(such as a games alias) referenced by an alias of RunImg. + +## Rules + +This is the Pyramid patience card game. The tableau is in the form of +a pyramid with seven rows. The object of the game is to remove as many +cards from the pyramid as possible. + +Only those cards which are not overlapped by other cards can be removed. +A pair of cards which total 13 in value, or a singleton King may be removed. + +The face down pile is the hand which is turned up one card at a time onto +the talon pile, of which the top card may also be used to make a match. + +The talon pile is not recycled. The Kings and pairs are discarded. + +## Playing + +The keys used to control Pyramid are as follows: + +**Left** and **Right** arrow keys move the pointer to the card to be lifted +(the arrow point diagonally up from the left of the card). The **space +bar** is pressed, and the card is picked up (unless it is a King, in +which case it is immediately discarded). Then the card is moved to the +destination and the space bar is pressed to attempt to match the card. + +If a match is made the two cards will be discarded. + +**Return** draws a single card from the face down hand if the player is +currently not holding a card. **Escape** aborts a move before dropping. + +The rules are simply as described above. Pressing the **space bar** when +on the face down pile flips a card onto the talon pile. The talon pile +may not be recycled. + +## Compiling + +Development tools used included: + +On the PC: + +- The **Psion SIBO SDK** with **TopSpeed C** compiler + +On the Amiga: + +- **DeluxePaint IV** - the only paint program I've ever used which is worth +running. Certainly light years ahead of Paintbrush - the only other +development tool I have used to make graphics for Psion games. + +Pyramid was written completely with PLIB, HWIF, and WLIB functions, +and, as such, is not portable (even to older SIBO machines, unless you +want to rewrite all the HWIF sections) in any way. + +It will run fine on later SIBO/EPOC16 machines, such as the Series 3a/c/mx and Siena. + +## Problems/Bugs + +Currently no undo other than cancelling the current move. + +## Revisions + +1.0a: Initial release diff --git a/src/PYRAMID.RSG b/src/PYRAMID.RSG new file mode 100644 index 0000000..0b96aa6 --- /dev/null +++ b/src/PYRAMID.RSG @@ -0,0 +1,9 @@ +#define RS_QUIT 1 +#define RS_NEW_GAME 2 +#define RS_NO 3 +#define RS_YES 4 +#define RH_MAIN 5 +#define RT_MAIN 6 +#define RH_RULES 7 +#define RH_CONTROLS 8 +#define RH_ABOUT 9 diff --git a/src/games.pr b/src/games.pr new file mode 100644 index 0000000..5b16dba --- /dev/null +++ b/src/games.pr @@ -0,0 +1,32 @@ +#noedit +#abort on +#system epoc img +#set epocinit=iplib +#model small jpi + +#declare_compiler rc= +'#split %%obj + #set obj = %%name.rsc + #set make=%%remake + #if %%make #then #run "RCOMP %%src" #endif' + +#declare_compiler ms= +'#split %%obj + #set obj = %%name.shd + #set make=%%remake + #if %%make #then #run "MAKESHD %%src" #endif' + +#pragma optimize(speed=>off) +#pragma debug(vid=>off) + +#compile %prjname.rc +#compile %prjname.ms +#compile %prjname.c + +#pragma link(hwif.lib) +#pragma link(utils\utils.lib) +#link %prjname + +#file delete %prjname.exe +#file delete %prjname.app +#file move %prjname.img %prjname.app diff --git a/src/global.h b/src/global.h new file mode 100644 index 0000000..97f4ca0 --- /dev/null +++ b/src/global.h @@ -0,0 +1,52 @@ +/* global.h - some definitions required by both the .rs and the .c files + */ + +/* + Pyramid, a Patience Game for the Psion Series 3 + Version 1.0a + Copyright (C) 1993 J Cade Roux + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + * See the file COPYING for the GNU General Public License. + * Mail: Cade Roux + * c/o Dubroca + * Box 513 + * Boutte, LA 70039 + * USA + */ + +#ifndef BOOL + #define BOOL INT +#endif + +#ifndef TRUE + #define TRUE 1 +#endif + +#ifndef FALSE + #define FALSE 0 +#endif + +#ifndef MIN + #define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef MAX + #define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +#define VERSION_STRING "1.0a" + \ No newline at end of file diff --git a/src/mkgame.bat b/src/mkgame.bat new file mode 100644 index 0000000..10e44e0 --- /dev/null +++ b/src/mkgame.bat @@ -0,0 +1,10 @@ +@echo off +if "%1" == "" goto usage + +tsc /m games /sprjname=%1 +goto quit + +:usage +echo "Usage MKGAME " + +:quit diff --git a/src/pyramid.afl b/src/pyramid.afl new file mode 100644 index 0000000..48da850 --- /dev/null +++ b/src/pyramid.afl @@ -0,0 +1,4 @@ +pyramid.pic +pyramid.rsc +pyramid.shd + \ No newline at end of file diff --git a/src/pyramid.c b/src/pyramid.c new file mode 100644 index 0000000..c439a64 --- /dev/null +++ b/src/pyramid.c @@ -0,0 +1,723 @@ +/* pyramid.c - the main source code for the game + */ + +/* + Pyramid, a Patience Game for the Psion Series 3 + Version 1.0a + Copyright (C) 1993 J Cade Roux + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + * See the file COPYING for the GNU General Public License. + * Mail: Cade Roux + * c/o Dubroca + * Box 513 + * Boutte, LA 70039 + * USA + */ + +#include +#include +#include + +#include "utils/utils.h" + +#include "global.h" /* global definitions such as the version */ +#include "pyramid.h" /* resource ids */ + +/* Parameters of deck/game */ +#define N_RANKS 13 +#define N_CARDS 52 +#define N_ROWS 7 + +/* Card positioning */ +#define GFX_CARD_WID 18 +#define GFX_CARD_HGT 24 + +#define GFX_RANK_WID 6 +#define GFX_RANK_HGT 6 + +#define GFX_SUIT_S_WID 7 +#define GFX_SUIT_S_HGT 7 +#define GFX_SUIT_L_WID 13 +#define GFX_SUIT_L_HGT 13 + +#define GFX_CARD_X(row, pos) (112 - (row) * ((GFX_CARD_WID + 6) / 2) + (pos) * (6 + GFX_CARD_WID)) +#define GFX_CARD_Y(row) ((row) * 10) + +#define GFX_ARROW_WID 4 +#define GFX_ARROW_HGT 4 + +/* Offsets of design on card */ +#define GFX_RANK_TOP 2 +#define GFX_RANK_LEFT 2 + +#define GFX_SUIT_S_TOP 2 +#define GFX_SUIT_S_LEFT 9 +#define GFX_SUIT_L_TOP 9 +#define GFX_SUIT_L_LEFT 3 + +/* Offsets in graphics data bitmap */ +#define ICON_X 0 +#define ICON_Y 0 + +#define GFX_BACK_X 23 +#define GFX_BACK_Y 0 + +#define GFX_RANK_X(rank) (41 + (rank) * GFX_RANK_WID) +#define GFX_RANK_Y 0 + +#define GFX_ARROW_X 41 +#define GFX_ARROW_Y 19 + +#define GFX_SUIT_L_X(suit) (41 + (suit) * GFX_SUIT_L_WID) +#define GFX_SUIT_S_X(suit) (93 + (suit) * GFX_SUIT_S_WID) +#define GFX_SUIT_Y 6 + +/* Offsets of cards on screen */ +#define GFX_HAND_X (GFX_ARROW_WID + 2) +#define GFX_HAND_Y 0 + +#define GFX_TALON_X (GFX_HAND_X + GFX_CARD_WID + GFX_ARROW_WID + 2) +#define GFX_TALON_Y GFX_HAND_Y + +/* Two formats: + index = suit * N_RANKS + rank + rank = index % N_RANKS + suit = index / N_RANKS + + Rank and Suit: Suit: 0, 1, 2, 3: Hearts, Diamonds, Clubs, Spades resp. + Rank: 0-12: Ace-King resp. + + Index: 0-51: Ace-King Hearts, Ace-King Diamonds, + Ace-King Clubs, Ace-King Spades +*/ + +/* The definition of a card */ +typedef struct CARD_TAG { + struct CARD_TAG * pnext ; /* Pointer to next card */ + BYTE index ; /* high bit indicates if it's been dealt */ + BYTE fill ; +} CARD ; + +/* Masks for cards */ +#define DEALT_MASK 0x80 /* high bit */ +#define INDEX_MASK 0x7F /* low 7 bits */ +#define DEALT(card) (((card).index & DEALT_MASK) != 0) +#define INDEX(pcard) ((pcard)->index & INDEX_MASK) + +#define RANK(pcard) (INDEX(pcard) % N_RANKS) +#define SUIT(pcard) (INDEX(pcard) / N_RANKS) + +LOCAL_D H_MENU_DATA mdata[] = { "Pyramid", 2, + NULL } ; + +LOCAL_D TEXT * cmds[] = { "nNew Game", + "xExit", + NULL } ; + +GLREF_D WSERV_SPEC * wserv_channel ; +GLREF_D TEXT * DatCommandPtr ; +GLDEF_D TEXT ** _cmds = cmds ; +GLDEF_D H_MENU_DATA * _mdata = mdata ; + +/* Cards in tableau etc. */ +LOCAL_D struct { + CARD * deck ; + CARD * pyramid[N_ROWS][N_ROWS] ; + CARD * hand ; + CARD * talon ; + CARD * hold ; + INT removables_row[N_ROWS] ; + INT removables_pos[N_ROWS] ; + INT n_removables ; +} cards ; + +#define HOLDING (cards.hold != NULL) +#define REMOVABLE(r,p) ( r >= 0 &&\ + p >= 0 &&\ + r < N_ROWS &&\ + p <= r &&\ + !( HOLDING &&\ + LPILE == POS_PYRAMID &&\ + r == LROW - 1 &&\ + ( p == LPOS ||\ + p == LPOS - 1 ) ) &&\ + cards.pyramid[r][p] != NULL &&\ + ( r == N_ROWS - 1 ||\ + ( cards.pyramid[r + 1][p] == NULL &&\ + cards.pyramid[r + 1][p + 1] == NULL ) ) ) + +enum { POS_HAND = 0, + POS_TALON, + POS_PYRAMID } ; + +LOCAL_D struct { + ULONG seedl ; /* random number seed */ + BOOL quit ; /* player requested quit */ + BOOL new_game ; /* player requested a new game */ + + INT cpile ; /* current pile */ + INT curr_pos ; /* current position on pyramid */ + INT lpile ; /* pile of last play */ + INT lrow ; /* last play row/pos coords */ + INT lpos ; + + INT num_dealt ; /* number of cards dealt */ +} status = { 0L, FALSE, FALSE } ; + +#define ON_PYRAMID (CPILE == POS_PYRAMID) +#define ON_TALON (CPILE == POS_TALON) + +#define CPILE status.cpile +#define CROW cards.removables_row[status.curr_pos] +#define CPOS cards.removables_pos[status.curr_pos] + +#define LPILE status.lpile +#define LROW status.lrow +#define LPOS status.lpos + +#define MATCH(pcard1,pcard2) (RANK(pcard1) + RANK(pcard2) == 11) + +LOCAL_D struct { + UINT win ; /* main window id */ + INT gc ; /* permanent gc for main window */ + UINT ptr ; /* pointer window id */ + UINT bmp ; /* gfx bitmap id */ +} gfx ; + +/* Deal a single card */ +LOCAL_C INT DealCard(VOID) { + INT iLp = -1 ; + INT count = 0 ; + INT index ; + + /* Deal one of the remaining slots, and count down to that undealt card */ + for ( index = Random(&status.seedl, 0, N_CARDS - status.num_dealt - 1) ; + count <= index ; + count += !DEALT(cards.deck[++iLp]) ) ; + + /* Mark it dealt */ + cards.deck[iLp].index |= DEALT_MASK ; + status.num_dealt++ ; + return(iLp) ; +} + +/* Clear a card-sized rectangle at x, y */ +LOCAL_C VOID ClrCard(INT x, INT y) { + P_RECT rect = { {0, 0}, + {GFX_CARD_WID, GFX_CARD_HGT} } ; + + p_offrec(&rect, x, y) ; + gClrRect(&rect, G_TRMODE_CLR) ; +} + +/* Draw Rank and Suit of *pcard whose tl is at x, y */ +LOCAL_C VOID DrawRankandSuit(BOOL large, CARD *pcard, INT x, INT y) { + static P_RECT RECT_RANK = { {0, 0}, {GFX_RANK_WID, GFX_RANK_HGT} } ; + static P_RECT RECT_SML = { {0, 0}, {GFX_SUIT_S_WID, GFX_SUIT_S_HGT} } ; + static P_RECT RECT_LRG = { {0, 0}, {GFX_SUIT_L_WID, GFX_SUIT_L_HGT} } ; + P_RECT rect ; + P_POINT pos ; + + rect = RECT_RANK ; + pos.x = x + GFX_RANK_LEFT ; + pos.y = y + GFX_RANK_TOP ; + p_offrec(&rect, GFX_RANK_X(RANK(pcard)), GFX_RANK_Y) ; + gCopyBit(&pos, gfx.bmp, &rect, G_TRMODE_SET) ; + + rect = (large ? RECT_LRG : RECT_SML) ; + pos.x = x + (large ? GFX_SUIT_L_LEFT : GFX_SUIT_S_LEFT) ; + pos.y = y + (large ? GFX_SUIT_L_TOP : GFX_SUIT_S_TOP) ; + p_offrec( &rect, + large ? GFX_SUIT_L_X(SUIT(pcard)) : GFX_SUIT_S_X(SUIT(pcard)), + GFX_SUIT_Y ) ; + gCopyBit(&pos, gfx.bmp, &rect, G_TRMODE_SET) ; +} + +/* Draw Card Outline at x, y */ +LOCAL_C VOID DrawCardOutline(INT x, INT y) { + P_RECT rect = { {0, 0}, {GFX_CARD_WID, GFX_CARD_HGT} } ; + + p_offrec(&rect, x, y) ; + gDrawBox(&rect) ; +} + +/* Draw card *pcard at x, y */ +LOCAL_C VOID DrawCard(BOOL large, CARD *pcard, INT x, INT y) { + if ( pcard == NULL ) + return ; + + ClrCard(x, y) ; + + /* Draw Whole Face Up Card */ + DrawCardOutline(x, y) ; + + /* Draw Rank and Large Suit */ + DrawRankandSuit(large, pcard, x, y) ; +} + +/* Draw a card back at x, y */ +LOCAL_C VOID DrawBack(INT x, INT y) { + static P_RECT RECT_BACK = { {GFX_BACK_X, GFX_BACK_Y}, + {GFX_BACK_X + GFX_CARD_WID, GFX_BACK_Y + GFX_CARD_HGT} } ; + P_POINT pos ; + + pos.x = x ; + pos.y = y ; + gCopyBit(&pos, gfx.bmp, &RECT_BACK, G_TRMODE_SET) ; +} + +/* Draw a Pyramid, from row srow and position spos */ +LOCAL_C VOID DrawPyramid(INT srow, INT spos) { + INT row ; + INT pos ; + + srow = MIN(MAX(srow, 0), N_ROWS - 1) ; + spos = MIN(MAX(spos, 0), srow) ; + + for ( row = srow ; row < N_ROWS ; row++ ) + for ( pos = spos ; pos - spos <= row - srow ; pos++ ) + DrawCard( REMOVABLE(row, pos), + cards.pyramid[row][pos], + GFX_CARD_X(row, pos), + GFX_CARD_Y(row) ) ; +} + +/* Draw pile */ +LOCAL_C VOID DrawPile(INT pile) { + if ( pile == POS_HAND ) { + ClrCard(GFX_HAND_X, GFX_HAND_Y) ; + if ( cards.hand == NULL ) + DrawCardOutline(GFX_HAND_X, GFX_HAND_Y) ; + else + DrawBack(GFX_HAND_X, GFX_HAND_Y) ; + } + else if ( pile == POS_TALON ) { + ClrCard(GFX_TALON_X, GFX_TALON_Y) ; + if ( cards.talon == NULL ) + DrawCardOutline(GFX_TALON_X, GFX_TALON_Y) ; + else + DrawCard(TRUE, cards.talon, GFX_TALON_X, GFX_TALON_Y) ; + } +} + +/* Update the array of the positions of removable cards */ +LOCAL_C VOID UpdateRemovables(VOID) { + INT row ; + INT pos ; + + for ( cards.n_removables = 0, pos = 0 ; pos < N_ROWS ; pos++ ) + for ( row = N_ROWS - 1 ; row >= pos ; row-- ) + if ( REMOVABLE(row, pos) ) { + cards.removables_row[cards.n_removables] = row ; + cards.removables_pos[cards.n_removables] = pos ; + cards.n_removables++ ; + DrawCard(TRUE, cards.pyramid[row][pos], GFX_CARD_X(row,pos), GFX_CARD_Y(row)) ; + break ; + } +} + +/* Return card to pile it was taken from */ +LOCAL_C VOID CancelPlay(VOID) { + if ( LPILE == POS_PYRAMID ) { + cards.pyramid[LROW][LPOS] = cards.hold ; + cards.hold = NULL ; + LPILE = POS_HAND ; + DrawPyramid(LROW - 2, LPOS - 1) ; + UpdateRemovables() ; + } + else if ( LPILE == POS_TALON ) { + cards.hold->pnext = cards.talon ; + cards.talon = cards.hold ; + cards.hold = NULL ; + DrawPile(LPILE) ; + LPILE = POS_HAND ; + } +} + +/* Draw a card from the hand */ +LOCAL_C VOID HandDraw(VOID) { + CARD * pcard ; + + if ( cards.hand != NULL ) { + LPILE = POS_HAND ; + pcard = cards.hand ; + cards.hand = cards.hand->pnext ; + pcard->pnext = cards.talon ; + cards.talon = pcard ; + + DrawPile(POS_HAND) ; + DrawPile(POS_TALON) ; + } +} + +/* Pick up card from the current position */ +LOCAL_C VOID PickUpCard(VOID) { + if ( ON_PYRAMID ) { + if ( RANK(cards.pyramid[CROW][CPOS]) == 12 ) { + cards.hold = NULL ; + cards.pyramid[CROW][CPOS] = NULL ; + LPILE = POS_HAND ; + } + else { + cards.hold = cards.pyramid[CROW][CPOS] ; + cards.pyramid[CROW][CPOS] = NULL ; + cards.hold->pnext = NULL ; + LPILE = CPILE ; + LROW = CROW ; + LPOS = CPOS ; + } + ClrCard(GFX_CARD_X(CROW, CPOS), GFX_CARD_Y(CROW)) ; + DrawPyramid(CROW - 2, CPOS - 1) ; + UpdateRemovables() ; + } + else if ( ON_TALON && + cards.talon != NULL ) { + if ( RANK(cards.talon) == 12 ) { + cards.hold = NULL ; + cards.talon = cards.talon->pnext ; + LPILE = POS_HAND ; + } + else { + cards.hold = cards.talon ; + cards.talon = cards.talon->pnext ; + cards.hold->pnext = NULL ; + LPILE = CPILE ; + } + DrawPile(POS_TALON) ; + } + else if ( ON_TALON && + cards.talon == NULL ) + HandDraw() ; +} + +/* Try to match the currently held card on the current card under the + and remove them both if they add up to a King */ +LOCAL_C VOID PutDownCard(VOID) { + BOOL match = FALSE ; + + if ( ON_PYRAMID && + MATCH(cards.hold, cards.pyramid[CROW][CPOS]) ) { + match = TRUE ; + cards.pyramid[CROW][CPOS] = NULL ; + cards.hold = NULL ; + ClrCard(GFX_CARD_X(CROW, CPOS), GFX_CARD_Y(CROW)) ; + DrawPyramid(CROW - 2, CPOS - 1) ; + UpdateRemovables() ; + } + else if ( ON_TALON && + cards.talon != NULL && + MATCH(cards.hold, cards.talon) ) { + match = TRUE ; + cards.hold = NULL ; + cards.talon = cards.talon->pnext ; + DrawPile(POS_TALON) ; + } + + if ( match ) { + if ( LPILE == POS_PYRAMID ) + DrawPyramid(LROW - 2, LPOS - 1) ; + LPILE = POS_HAND ; + UpdateRemovables() ; + } +} + +/* Execute menu command */ +LOCAL_C VOID ExecuteCommand(INT keycode) { + if ( (keycode = uLocateCommand(keycode)) < 0 ) + return ; + + switch(keycode) { + + case 0 : /* New Game */ + Check( p_enter5(Query, RS_NEW_GAME, RS_YES, RS_NO, &status.new_game) ) ; + break ; + + case 1 : /* Exit */ + Check( p_enter5(Query, RS_QUIT, RS_YES, RS_NO, &status.quit) ) ; + break ; + + default : + break ; + } +} + +/* Modify the pointer to take account of the game status */ +LOCAL_C VOID UpdatePointer(BOOL drawflag) { + static P_RECT RECT_PTR = { {GFX_ARROW_X, GFX_ARROW_Y}, + {GFX_ARROW_X + GFX_ARROW_WID, GFX_ARROW_Y + GFX_ARROW_HGT} } ; + W_WINDATA windata ; + P_POINT pos = { 0, 0 } ; + + status.curr_pos = MAX(0, MIN(cards.n_removables - 1, status.curr_pos)) ; + + if ( CPILE == POS_TALON ) { + windata.extent.tl.x = GFX_TALON_X ; + windata.extent.tl.y = GFX_TALON_Y ; + } + else { + /* On pyramid */ + windata.extent.tl.x = GFX_CARD_X(CROW, CPOS) ; + windata.extent.tl.y = GFX_CARD_Y(CROW) ; + } + + windata.extent.tl.x -= (!HOLDING ? 5 : 6) ; + windata.extent.tl.y += (!HOLDING ? 2 : 9) ; + windata.extent.width = (!HOLDING ? GFX_ARROW_WID : GFX_CARD_WID) ; + windata.extent.height = (!HOLDING ? GFX_ARROW_HGT : GFX_CARD_HGT) ; + + wSetWindow(gfx.ptr, W_WIN_EXTENT, &windata) ; + if ( drawflag ) { + gCreateTempGC0(gfx.ptr) ; + if ( HOLDING ) { + ClrCard(0, 0) ; + DrawCard(TRUE, cards.hold, 0, 0) ; + } + else + gCopyBit(&pos, gfx.bmp, &RECT_PTR, G_TRMODE_REPL) ; + gFreeTempGC() ; + } +} + +/* Are there any plays possible */ +LOCAL_C BOOL PlayPossible(VOID) { + CARD * picard ; + CARD * pjcard ; + INT icard ; + INT jcard ; + + if ( cards.hand != NULL || + HOLDING ) + return(TRUE) ; + + for ( icard = 0 ; icard < cards.n_removables + 1 ; icard++ ) { + picard = icard < cards.n_removables ? + cards.pyramid[cards.removables_row[icard]][cards.removables_pos[icard]] : + cards.talon ; + if ( picard == NULL ) + continue ; + + for ( jcard = icard + 1 ; jcard < cards.n_removables + 1 ; jcard++ ) { + pjcard = jcard < cards.n_removables ? + cards.pyramid[cards.removables_row[jcard]][cards.removables_pos[jcard]] : + cards.talon ; + if ( pjcard == NULL ) + continue ; + + if ( RANK(picard) == 12 || + RANK(pjcard) == 12 || + MATCH(picard, pjcard) ) + return(TRUE) ; + } + } + + return(FALSE) ; +} + +#pragma save, ENTER_CALL + +/* Deal a new game */ +LOCAL_C INT Deal(VOID) { + INT iLp ; + INT row ; + INT pos ; + + CPILE = POS_TALON ; + LPILE = POS_HAND ; + status.seedl = p_date() ; + status.num_dealt = 0 ; + + /* Clear Deck */ + for ( iLp = 0 ; + iLp < N_CARDS ; + iLp++ ) { + cards.deck[iLp].pnext = NULL ; + cards.deck[iLp].index = iLp ; + } + + /* Deal Pyramid */ + for ( row = 0 ; + row < N_ROWS ; + row++ ) { + for ( pos = 0 ; + pos <= row ; + pos++ ) { + cards.pyramid[row][pos] = &cards.deck[DealCard()] ; + cards.pyramid[row][pos]->pnext = NULL ; + } + } + + /* Deal remaining cards to hand */ + for ( cards.hand = NULL ; status.num_dealt < N_CARDS ; ) { + CARD * pcard ; + + pcard = cards.hand ; + cards.hand = &cards.deck[DealCard()] ; + cards.hand->pnext = pcard ; + } + cards.talon = cards.hold = NULL ; + + UpdateRemovables() ; + DrawPyramid(0, 0) ; + DrawPile(POS_HAND) ; + DrawPile(POS_TALON) ; + + UpdatePointer(TRUE) ; + + return(E_APP_NONE) ; +} + +/* Play a single game until the player quits, or a new game is requested */ +LOCAL_C INT PlayGame(VOID) { + WMSG_KEY key ; + INT ret ; + + status.new_game = FALSE ; + + do { + + uGetKey(&key) ; + + if ( key.keycode == CONS_EVENT_COMMAND ) + status.quit = TRUE ; + else if ( key.keycode & W_SPECIAL_KEY ) + ExecuteCommand(key.keycode & ~W_SPECIAL_KEY) ; + else switch( key.keycode ) { + + case W_KEY_HELP : + if ( key.modifiers == W_CTRL_MODIFIER ) + SystemHelp() ; + else + Help(RH_MAIN, RH_MAIN) ; + break ; + + case W_KEY_MENU : + if ( (ret = uPresentMenus()) > 0 ) + ExecuteCommand(ret) ; + break ; + + case W_KEY_RIGHT : + if ( ON_TALON ) { + CPILE++ ; + status.curr_pos = 0 ; + } + else if ( status.curr_pos < cards.n_removables - 1 ) + status.curr_pos++ ; + break ; + + case W_KEY_LEFT : + if ( ON_PYRAMID ) + if ( status.curr_pos == 0 ) + CPILE-- ; + else + status.curr_pos-- ; + break ; + + case W_KEY_UP : + case W_KEY_HOME : + CPILE = POS_TALON ; + break ; + + case W_KEY_DOWN : + case W_KEY_END : + CPILE = POS_PYRAMID ; + status.curr_pos = cards.n_removables - 1 ; + break ; + + case ' ' : + if ( HOLDING ) + PutDownCard() ; + else + PickUpCard() ; + + UpdatePointer(TRUE) ; + break ; + + case W_KEY_RETURN : + if ( !HOLDING ) + HandDraw() ; + break ; + + case W_KEY_ESCAPE : + if ( HOLDING && + LPILE != POS_HAND ) { + CancelPlay() ; + UpdatePointer(TRUE) ; + } + break ; + + default : + break ; + } + + if ( key.keycode >= W_KEY_UP && key.keycode <= W_KEY_END ) + UpdatePointer(FALSE) ; + + if ( !PlayPossible() ) { + Check( p_enter5(Query, RS_NEW_GAME, RS_YES, RS_NO, &status.new_game) ) ; + status.quit = !status.new_game ; + } + + } while ( !(status.new_game || status.quit) ) ; + + return(E_APP_NONE) ; +} + +/* General initialization of global variables etc. */ +LOCAL_C INT SpecificInit(VOID) { + P_POINT bit_size ; + W_WINDATA windata = { W_WIN_NO_REDRAW, + { {0, 0}, GFX_ARROW_WID, GFX_ARROW_HGT }, + W_WIN_NO_MOUSE, + W_WIN_BACK_BITMAP } ; + + hCrackCommandLine() ; + p_unmarka() ; + + OpenResource(DatCommandPtr) ; + + /* Gfx init */ + gfx.win = uFindMainWid() ; + gfx.bmp = gOpenBit(DatCommandPtr, 0, 0, &bit_size) ; + gfx.gc = gCreateGC0(gfx.win) ; + gfx.ptr = wCreateWindow( gfx.win, + W_WIN_NO_REDRAW | W_WIN_EXTENT | W_WIN_BACKGROUND, + &windata, (UWORD) &gfx) ; + wInitialiseWindowTree(gfx.ptr) ; + wMakeVisible(gfx.ptr) ; + + /* Mem alloc */ + cards.deck = f_alloc(N_CARDS * sizeof(CARD)) ; + + /* About message */ + Help(RH_ABOUT, RH_MAIN) ; + + return(E_APP_NONE) ; +} + +#pragma restore + +GLDEF_C VOID main(VOID) { + uCommonInit() ; + wDisableLeaves(FALSE) ; + Check( p_enter1(SpecificInit) ) ; + do { + Check( p_enter1(Deal) ) ; + Check( p_enter1(PlayGame) ) ; + } while ( !status.quit ) ; + p_exit(E_APP_NONE) ; +} + \ No newline at end of file diff --git a/src/pyramid.h b/src/pyramid.h new file mode 100644 index 0000000..0b96aa6 --- /dev/null +++ b/src/pyramid.h @@ -0,0 +1,9 @@ +#define RS_QUIT 1 +#define RS_NEW_GAME 2 +#define RS_NO 3 +#define RS_YES 4 +#define RH_MAIN 5 +#define RT_MAIN 6 +#define RH_RULES 7 +#define RH_CONTROLS 8 +#define RH_ABOUT 9 diff --git a/src/pyramid.ms b/src/pyramid.ms new file mode 100644 index 0000000..d82bbf3 --- /dev/null +++ b/src/pyramid.ms @@ -0,0 +1,4 @@ +Pyramid + +0 + \ No newline at end of file diff --git a/src/pyramid.pic b/src/pyramid.pic new file mode 100644 index 0000000000000000000000000000000000000000..a860eb6bbf5ab6d7d6a0a432254ae0278bf1c0e1 GIT binary patch literal 404 zcmWIWbiQL?z{s%qL=}SsLjxlN5c~&$xzD@po)_=oDNNGdQL- zS;mH&u4>@_u{i4Qe?}l5Bp=Gi{>Oc3)PKg0|NAXt!ndv}D*D&&^xp^H*nu z{{8h|zVSf;1CamGKXmG +#define UP_ARROW <0x18> +#define DOWN_ARROW <0x19> +#define RIGHT_ARROW <0x1A> +#define LEFT_ARROW <0x1B> + +STRUCT STRING { + TEXT str ; +} + +STRUCT TOPIC_ARRAY { + LEN BYTE LINK id_lst[] ; +} + +STRUCT HELP_ARRAY { + LINK topic_id = 0 ; + TEXT topic ; + LEN BYTE STRUCT strlst[] ; +} + +RESOURCE STRING rs_quit { str = "Quit?" ; } +RESOURCE STRING rs_new_game { str = "New Game?" ; } +RESOURCE STRING rs_no { str = "No" ; } +RESOURCE STRING rs_yes { str = "Yes" ; } + +RESOURCE HELP_ARRAY rh_main { + topic = "Index" ; + topic_id = rt_main ; +} + +RESOURCE TOPIC_ARRAY rt_main { + id_lst = { rh_rules, + rh_controls, + rh_about + } ; +} + +RESOURCE HELP_ARRAY rh_rules { + topic = "Pyramid Rules" ; + strlst = { STRING { str = "The tableau is in the form of a pyramid." ; }, + STRING { str = "The object of the game is to remove as" ; }, + STRING { str = "many cards from the pyramid as possible." ; }, + STRING { str = "" ; }, + STRING { str = "Only those cards which are not overlapped" ; }, + STRING { str = "by other cards can be removed. A pair of" ; }, + STRING { str = "cards which total 13 in value, or a" ; }, + STRING { str = "singleton King may be removed." ; }, + STRING { str = "" ; }, + STRING { str = "The face down pile is the hand which is" ; }, + STRING { str = "turned up one card at a time onto the talon" ; }, + STRING { str = "pile, of which the top card may also be used" ; }, + STRING { str = "to make a match." ; }, + STRING { str = "" ; }, + STRING { str = "The Kings and pairs are discarded." ; } + } ; +} + +RESOURCE HELP_ARRAY rh_controls { + topic = "Pyramid Controls" ; + strlst = { STRING { str = LEFT_ARROW", "RIGHT_ARROW" keys move cursor," ; }, + STRING { str = " picks up/places card" ; }, + STRING { str = " cancels pick up" ; }, + STRING { str = " draws from hand" ; } + } ; +} + +RESOURCE HELP_ARRAY rh_about { + topic = "About Pyramid" ; + strlst = { STRING { str = "Pyramid: " VERSION_STRING ; }, + STRING { str = "Copyright (C) 1993 J Cade Roux" ; }, + STRING { str = "Free software under the terms of the" ; }, + STRING { str = "GNU General Public License." ; }, + STRING { str = "" ; }, + STRING { str = "Press - for index." ; } + } ; +} + + \ No newline at end of file diff --git a/src/utils/utils.c b/src/utils/utils.c new file mode 100644 index 0000000..43cc443 --- /dev/null +++ b/src/utils/utils.c @@ -0,0 +1,604 @@ +/* utils.c - miscellaneous S3 routines - mainly dealing with resources + */ + +#include +#include + +LOCAL_D VOID * u_rcb ; /* ptr to utils resource control block */ +LOCAL_D TEXT * u_resname ; /* name of resource file */ +LOCAL_D REMEMBER_LLIST u_rem = { NULL, NULL } ; /* remember struct for resources */ +LOCAL_D BOOL u_leaves = TRUE ; /* leaves on by default */ + +LOCAL_D TEXT * ReplaceDisk = "Please replace SSD" ; + +GLDEF_C BOOL uDisableLeaves(BOOL disable) { + BOOL oleaves ; + + oleaves = u_leaves ; + u_leaves = !disable ; + return(oleaves) ; +} + +/* Returns TRUE if file exists */ +GLDEF_C BOOL Exists(TEXT *filename) { + P_INFO pinfo ; + + return( !p_finfo(filename, &pinfo) ) ; +} + +/* Check a negative error and quit */ +GLDEF_C INT Check(INT ret) { + if ( ret < -128 ) { + /* App error */ + p_notify("Fatal Application Error:", NULL, NULL, NULL, NULL) ; + p_exit(E_APP_NONE) ; + } + else if ( ret < 0 && ret != E_FILE_EOF ) { + p_notifyerr(ret, "Error:", NULL, NULL, NULL) ; + p_exit(ret) ; + } + else + return(ret) ; +} + +/* Exit with error index from the resource file */ +GLDEF_C VOID Exit_Error(INT index) { + TEXT * str = NULL ; + + uDisableLeaves(TRUE) ; + ReadResource(index, &str) ; + if ( str != NULL ) { + uErrorString(str) ; + p_free(str) ; + } + + p_exit(E_APP_NONE) ; +} + +/* Produces a random INT between low and high inclusive */ +GLDEF_C INT Random(ULONG *pseed, INT low, INT high) { + return( low + (INT) ( p_randl(pseed) % (high - low + 1) ) ) ; +} + +GLDEF_C VOID SystemHelp(VOID) { + hHelpSubSystem(-112, 0) ; +} + +GLDEF_C VOID Help(INT help, INT index) { + hHelpSubSystem(help, index) ; +} + +/* Notify the user of out of memory error */ +GLDEF_C VOID TellNoMemory(VOID) { + TEXT buf[40] ; + + p_errs(buf, E_GEN_NOMEMORY) ; + wsAlertW(WS_ALERT_CLIENT, 0, buf, 0) ; +} + +GLDEF_C VOID OpenResource(TEXT *name) { + /* Open resource file for help */ + u_resname = name ; + u_rcb = f_new(1, C_RSCFILE) ; + f_send3(u_rcb, O_RS_INIT, u_resname) ; + hDeclareAppRcb(u_rcb); +} + +LOCAL_C VOID *u_ReadResource(INT index, BOOL remember) { + INT ret ; + VOID * pcell = NULL ; + REMEMBER * pt ; + + FOREVER { + ret = p_entersend4(u_rcb, O_RS_READ, index, &pcell) ; + if ( ret >= 0 ) { + + if ( remember ) { + pt = p_adjust(pcell, 0, sizeof(REMEMBER)) ; + + if ( pt == NULL ) { + p_free(pcell) ; + pcell = NULL ; + FreeRemember(&u_rem) ; + if ( u_leaves ) + p_leave(E_UTILS_READ_RES) ; + else + return(pcell) ; + } + else { + u_rem.ptail->pnext = pt ; + pt->pnext = NULL ; + u_rem.ptail = pt ; + return(((BYTE *) pt) + sizeof(REMEMBER)) ; + } + } + else { + return(pcell) ; + } + } + while ( ret < 0 ) { + if ( ret == E_GEN_NOMEMORY ) { + TellNoMemory() ; + if ( remember ) + FreeRemember(&u_rem) ; + if ( u_leaves ) + p_leave(E_UTILS_READ_RES) ; + else + return(NULL) ; + } + wsAlertW(WS_ALERT_CLIENT, 0, ReplaceDisk, 0) ; + p_send2(u_rcb, 0) ; /* destroy object */ + FOREVER { + u_rcb = p_new(1, C_RSCFILE) ; + if ( u_rcb ) + break ; + TellNoMemory() ; + } + ret = p_entersend3(u_rcb, O_RS_INIT, u_resname) ; + if ( ret >= 0 ) + hDeclareAppRcb(u_rcb) ; + } + } +} + +GLDEF_C VOID *ReadResource(INT index, VOID **ppcell) { + if ( *ppcell != NULL ) + p_free(*ppcell) ; + + return( *ppcell = u_ReadResource(index, FALSE) ) ; +} + +/* Read resource into *pcell */ +GLDEF_C VOID ReadResource_buf(INT index, VOID *pcell) { + INT ret ; + + if ( pcell == NULL ) + return ; + + FOREVER { + ret = p_entersend4(u_rcb, O_RS_READ_BUF, index, pcell) ; + if ( ret >= 0 ) + return ; + while ( ret < 0 ) { + wsAlertW(WS_ALERT_CLIENT, 0, ReplaceDisk, 0) ; + p_send2(u_rcb, 0) ; /* destroy object */ + FOREVER { + u_rcb = p_new(1, C_RSCFILE) ; + if ( u_rcb ) + break ; + TellNoMemory() ; + } + ret = p_entersend3(u_rcb, O_RS_INIT, u_resname) ; + if ( ret >= 0 ) + hDeclareAppRcb(u_rcb) ; + } + } +} + +#pragma save, ENTER_CALL + +GLDEF_C INT Query(INT res_title, INT res_pos, INT res_neg, BOOL *answer) { + BOOL ret = TRUE ; + + *answer = TRUE ; + + Res_OpenDialog(res_title) ; + Res_Add2ButtonList( res_neg, -W_KEY_ESCAPE, + res_pos, W_KEY_RETURN ) ; + ret = Res_RunDialog() ; + + *answer = ret ; + + return(E_APP_NONE) ; +} + +GLDEF_C INT QueryStr(TEXT *ptitle, INT res_pos, INT res_neg, BOOL *answer) { + BOOL ret = TRUE ; + + *answer = TRUE ; + + if ( uOpenDialog(ptitle) ) + p_leave(E_UTILS_DIALOG) ; + + Res_Add2ButtonList( res_neg, -W_KEY_ESCAPE, + res_pos, W_KEY_RETURN ) ; + ret = Res_RunDialog() ; + + *answer = ret ; + + return(E_APP_NONE) ; +} + +GLDEF_C INT ThreeQuery(INT res_title, INT res_pos, INT res_neg, INT res_maybe, INT *answer) { + INT ret ; + + Res_OpenDialog(res_title) ; + ret = uAddButtonList( (TEXT *) u_ReadResource(res_neg, TRUE), -W_KEY_ESCAPE, + (TEXT *) u_ReadResource(res_pos, TRUE), W_KEY_RETURN, + (TEXT *) u_ReadResource(res_maybe, TRUE), W_KEY_TAB, + NULL) ; + Res_FreeMem() ; + + if ( ret ) { + *answer = 0 ; + return(E_UTILS_DIALOG) ; + } + + ret = Res_RunDialog() ; + + if ( ret == W_KEY_RETURN ) + *answer = 2 ; + else if ( ret == W_KEY_TAB ) + *answer = 1 ; + else + *answer = 0 ; + + return(E_APP_NONE) ; +} + +#pragma restore + +/* Display a resource message */ +GLDEF_C VOID InfoMsg(INT index) { + TEXT * buf = NULL ; + BOOL oleaves ; + + oleaves = uDisableLeaves(TRUE) ; + ReadResource(index, &buf) ; + if ( buf != NULL ) { + wInfoMsg(buf) ; + p_free(buf) ; + } + uDisableLeaves(oleaves) ; +} + +/* Display a resource message */ +GLDEF_C VOID InfoMsgCorner(INT index) { + TEXT * buf = NULL ; + BOOL oleaves ; + + oleaves = uDisableLeaves(TRUE) ; + ReadResource(index, &buf) ; + if ( buf != NULL ) { + wInfoMsgCorner(buf, W_CORNER_BOTTOM_LEFT) ; + p_free(buf) ; + } + uDisableLeaves(oleaves) ; +} + +/* Allocate and remember - if fail, free all memory in the remember + structure and call p_leave */ +GLDEF_C VOID *AllocRemember(REMEMBER_LLIST *prem, INT size) { + if ( prem == NULL ) + return(NULL) ; + + prem->ptail->pnext = p_alloc(size + sizeof(REMEMBER)) ; + + if ( prem->ptail->pnext == NULL ) { + FreeRemember(prem) ; + if ( u_leaves ) + p_leave(E_GEN_NOMEMORY) ; + else + return(NULL) ; + } + + prem->ptail = prem->ptail->pnext ; + prem->ptail->pnext = NULL ; + + return( ((BYTE *) prem->ptail) + sizeof(REMEMBER) ) ; +} + +GLDEF_C VOID FreeRemember(REMEMBER_LLIST *prem) { + REMEMBER * pcell = NULL ; + REMEMBER * pnext = NULL ; + + for ( pcell = prem->phead ; pcell != NULL ; ) { + pnext = pcell->pnext ; + p_free(pcell) ; + pcell = pnext ; + } + + prem->phead = NULL ; + prem->ptail = NULL ; +} + +GLDEF_C INT Res_OpenDialog(INT rs_title) { + INT ret ; + + ret = uOpenDialog((TEXT *) u_ReadResource(rs_title, TRUE)) ; + Res_FreeMem() ; + + if ( ret && u_leaves ) + p_leave(E_UTILS_DIALOG) ; + else + return(ret) ; +} + +GLDEF_C INT Res_RunDialog(VOID) { + INT ret ; + + ret = uRunDialog() ; + + if ( ret < 0 && u_leaves ) + p_leave(E_UTILS_DIALOG) ; + else + return(ret) ; +} + +GLDEF_C INT Res_AddChoiceList(INT rs_prompt, INT rs_1, INT rs_2, UWORD *psel) { + INT ret ; + + ret = uAddChoiceList( (TEXT *) u_ReadResource(rs_prompt, TRUE), + psel, + (TEXT *) u_ReadResource(rs_1, TRUE), + (TEXT *) u_ReadResource(rs_2, TRUE), + NULL) ; + Res_FreeMem() ; + + if ( ret && u_leaves ) + p_leave(E_UTILS_DIALOG) ; + else + return(ret) ; +} + +GLDEF_C INT Res_Add2ButtonList(INT rs_1, INT code_1, INT rs_2, INT code_2) { + INT ret ; + + ret = uAddButtonList( (TEXT *) u_ReadResource(rs_1, TRUE), + code_1, + (TEXT *) u_ReadResource(rs_2, TRUE), + code_2, + NULL) ; + Res_FreeMem() ; + + if ( ret && u_leaves ) + p_leave(E_UTILS_DIALOG) ; + else + return(ret) ; +} + +GLDEF_C INT Res_AddDialogItem(INT type, INT rs_prompt, VOID *pdata) { + INT ret ; + + ret = uAddDialogItem( type, + (TEXT *) u_ReadResource(rs_prompt, TRUE), + pdata) ; + Res_FreeMem() ; + + if ( ret && u_leaves ) + p_leave(E_UTILS_DIALOG) ; + else + return(ret) ; +} + +GLDEF_C INT Res_AddDCL(INT rs_prompt, UWORD *psel, H_DI_CHOICE *pch) { + INT ret ; + + ret = uAddDCL( (TEXT *) u_ReadResource(rs_prompt, TRUE), + psel, + pch) ; + Res_FreeMem() ; + + if ( ret && u_leaves ) + p_leave(E_UTILS_DIALOG) ; + else + return(ret) ; +} + +GLDEF_C VOID Res_FreeMem(VOID) { + FreeRemember(&u_rem) ; +} + +/* Converts a BCS string at str to a ZTS string */ +GLDEF_C TEXT *BCStoZTS(TEXT *str) { + *p_bcpy(&str[0], &str[1], str[0])= '\x0' ; + + return(str) ; +} + +GLDEF_C TEXT *ZTStoBCS(TEXT *str) { + TEXT len ; + + p_bcpy(&str[1], str, len = p_slen(str)) ; + str[0] = len ; + + return(str) ; +} + +GLDEF_C VOID Res_ErrorString(INT index) { + TEXT * str = NULL ; + BOOL oleaves ; + + oleaves = uDisableLeaves(TRUE) ; + + ReadResource(index, &str) ; + if ( str != NULL ) { + uErrorString(str) ; + p_free(str) ; + } + uDisableLeaves(oleaves) ; +} + +#define BAR_SCROLL 0 +#define BAR_STATUS 1 + +GLDEF_C VOID ShowBar(BAR_OBJ *pbar) { + W_WINDATA windata = { W_WIN_NO_REDRAW, + {{0, 0}, 0, 0}, + 0, + W_WIN_BACK_BITMAP } ; + UINT oleaves ; + + if ( pbar->open ) + return ; + + windata.extent = pbar->extent ; + + oleaves = wDisableLeaves(TRUE) ; + pbar->win_id = wCreateWindow( 0, + W_WIN_EXTENT | W_WIN_BACKGROUND | W_WIN_NO_REDRAW, + &windata, + (UWORD) pbar ) ; + + if (pbar->win_id == E_GEN_NOMEMORY ) + pbar->open = FALSE ; + else { + wInitialiseWindowTree(pbar->win_id) ; + pbar->open = TRUE ; + } + + wDisableLeaves(oleaves) ; +} + +GLDEF_C VOID HideBar(BAR_OBJ *pbar) { + UINT oleaves ; + + if ( !pbar->open ) + return ; + + oleaves = wDisableLeaves(TRUE) ; + + wCloseWindowTree(pbar->win_id) ; + pbar->win_id = 0 ; + pbar->open = FALSE ; + wDisableLeaves(oleaves) ; +} + +GLDEF_C VOID ToggleBar(BAR_OBJ *pbar) { + (pbar->open ? HideBar : ShowBar)(pbar) ; +} + +GLDEF_C VOID GetBarExtent(BAR_OBJ *pbar, P_EXTENT *pextent) { + *pextent = pbar->extent ; +} + +GLDEF_C VOID MakeStatusBar( BAR_OBJ *pbar, + UINT font_id, + UINT style, + P_POINT *pscreen_size ) { + G_FONT_INFO font_info ; + + gFontInfo(font_id, style, &font_info) ; + + pbar->data.status.font_id = font_id ; + pbar->data.status.style = style ; + pbar->data.status.ascent = font_info.ascent ; + + pbar->extent.height = 4 + font_info.height ; + pbar->extent.width = pscreen_size->x ; + pbar->extent.tl.x = 0 ; + pbar->extent.tl.y = pscreen_size->y - pbar->extent.height ; + + pbar->open = FALSE ; + pbar->win_id = 0 ; + pbar->type = BAR_STATUS ; +} + +LOCAL_C VOID UpdateStatusBar(BAR_OBJ *pbar, TEXT *str) { + G_GC g_gc ; + P_RECT rect = { {0, 0} } ; + + if ( !pbar->open || + pbar->type != BAR_STATUS ) + return ; + + g_gc.style = pbar->data.status.style ; + g_gc.font = pbar->data.status.font_id ; + gCreateTempGC(pbar->win_id, G_GC_MASK_STYLE | G_GC_MASK_FONT, &g_gc) ; + + rect.br.x = pbar->extent.width ; + rect.br.y = pbar->extent.height ; + gBorderRect(&rect, W_BORD_CORNER_1) ; + + p_insrec(&rect, 2, 2) ; + + gPrintBoxText( &rect, + pbar->data.status.ascent, + G_TEXT_ALIGN_LEFT, + 0, + str, p_slen(str) ) ; + + gFreeTempGC() ; +} + +#define SCROLL_BORD_WID 1 +#define SCROLL_MIN 4 + +GLDEF_C VOID MakeScrollBar( BAR_OBJ *pbar, + WORD tl_x, + WORD tl_y, + WORD length, + BOOL horz) { + + pbar->data.scroll.state.start = 0L ; + pbar->data.scroll.state.size = 0L ; + pbar->data.scroll.state.total = 0L ; + pbar->data.scroll.horz = horz ; + + pbar->extent.tl.x = tl_x ; + pbar->extent.tl.y = tl_y ; + pbar->extent.width = (horz ? length : SCROLL_WID) ; + pbar->extent.height = (horz ? SCROLL_WID : length) ; + + pbar->open = FALSE ; + pbar->win_id = 0 ; + pbar->type = BAR_SCROLL ; +} + +LOCAL_C VOID UpdateScrollBar(BAR_OBJ *pbar, SCROLL_BAR_STATE *pstate) { + P_RECT rect = { {0, 0} } ; + ULONG bar_total_pixels ; + UINT oleaves ; + + if ( pbar->type != BAR_SCROLL ) + return ; + + if ( pstate != NULL ) + pbar->data.scroll.state = *pstate ; + + if ( !pbar->open ) + return ; + + rect.br.x = pbar->extent.width ; + rect.br.y = pbar->extent.height ; + + oleaves = wDisableLeaves(TRUE) ; + + gCreateTempGC0(pbar->win_id) ; + + if ( pbar->data.scroll.state.size >= pbar->data.scroll.state.total ) + gClrRect(&rect, G_TRMODE_CLR) ; + else { + gBorderRect(&rect, W_BORD_CORNER_1) ; + p_insrec(&rect, SCROLL_BORD_WID, SCROLL_BORD_WID) ; + gFillPattern(&rect, WS_BITMAP_GREY, G_TRMODE_REPL) ; + + if ( pbar->data.scroll.horz ) { + bar_total_pixels = rect.br.x - rect.tl.x ; + rect.tl.x += (pbar->data.scroll.state.start * bar_total_pixels) / pbar->data.scroll.state.total ; + rect.br.x = rect.tl.x + MAX((pbar->data.scroll.state.size * bar_total_pixels) / pbar->data.scroll.state.total, SCROLL_MIN) ; + } + else { + bar_total_pixels = rect.br.y - rect.tl.y ; + rect.tl.y += (pbar->data.scroll.state.start * bar_total_pixels) / pbar->data.scroll.state.total ; + rect.br.y = rect.tl.y + MAX((pbar->data.scroll.state.size * bar_total_pixels) / pbar->data.scroll.state.total, SCROLL_MIN) ; + } + + gClrRect(&rect, G_TRMODE_SET) ; + } + + gFreeTempGC() ; + + wDisableLeaves(oleaves) ; +} + +GLDEF_C VOID UpdateBar(BAR_OBJ *pbar, VOID *pdata) { + if ( pbar->type == BAR_STATUS ) { + UpdateStatusBar(pbar, pdata) ; + } + else if ( pbar->type == BAR_SCROLL ) { + UpdateScrollBar(pbar, pdata) ; + } +} + + \ No newline at end of file diff --git a/src/utils/utils.h b/src/utils/utils.h new file mode 100644 index 0000000..b1a3d9a --- /dev/null +++ b/src/utils/utils.h @@ -0,0 +1,138 @@ +/* utils.h - some miscellaneous S3 utils + */ + +#ifndef UTILS_H + #define UTILS_H + +#ifndef PLIB_H + #include +#endif + +#ifndef WLIB_H + #include +#endif + +#ifndef HWIF_H + #include +#endif + +#ifndef BOOL + #define BOOL INT +#endif + +#ifndef TRUE + #define TRUE 1 +#endif + +#ifndef FALSE + #define FALSE 0 +#endif + +#ifndef MIN + #define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef MAX + #define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +#define E_APP_NONE 0 +#define E_UTILS_READ_RES -129 +#define E_UTILS_DIALOG -130 +#define E_APP_START -256 + +GLREF_C INT Check(INT ret) ; +GLREF_C VOID Exit_Error(INT index) ; +GLREF_C INT Random(ULONG *pseed, INT low, INT high) ; + +GLREF_C TEXT *BCStoZTS(TEXT *str) ; +GLREF_C TEXT *ZTStoBCS(TEXT *str) ; + +GLREF_C BOOL Exists(TEXT *filename) ; +GLREF_C VOID SystemHelp(VOID) ; +GLREF_C VOID Help(INT help, INT index) ; + +GLREF_C VOID TellNoMemory(VOID) ; + +GLREF_C BOOL uDisableLeaves(BOOL disable) ; +GLREF_C VOID OpenResource(TEXT *name) ; +GLREF_C VOID *ReadResource(INT index, VOID **ppcell) ; +GLREF_C VOID ReadResource_buf(INT index, VOID *pcell) ; + +#pragma save, ENTER_CALL +GLREF_C INT Query(INT res_title, INT res_pos, INT res_neg, BOOL *answer) ; +GLREF_C INT QueryStr(TEXT *ptitle, INT res_pos, INT res_neg, BOOL *answer) ; +GLREF_C INT ThreeQuery(INT res_title, INT res_pos, INT res_neg, INT res_maybe, INT *answer) ; +#pragma restore + +GLREF_C INT Res_OpenDialog(INT rs_title) ; +GLREF_C INT Res_RunDialog(VOID); +GLREF_C INT Res_AddChoiceList(INT rs_prompt, INT rs_1, INT rs2, UWORD *psel) ; +GLREF_C INT Res_AddDialogItem(INT type, INT rs_prompt, VOID *pdata) ; +GLREF_C INT Res_AddDCL(INT rs_prompt, UWORD *psel, H_DI_CHOICE *pch) ; +GLREF_C INT Res_Add2ButtonList(INT rs_1, INT code_1, INT rs_2, INT code_2) ; +GLREF_C VOID Res_FreeMem(VOID) ; + +GLREF_C VOID InfoMsg(INT index) ; +GLREF_C VOID InfoMsgCorner(INT index) ; +GLREF_C VOID Res_ErrorString(INT index) ; + +/* Allocation remember routines */ + +typedef struct REMEMBER_TAG { + struct REMEMBER_TAG * pnext ; +} REMEMBER ; + +typedef struct REMEMBER_LLIST_TAG { + REMEMBER * phead ; + REMEMBER * ptail ; +} REMEMBER_LLIST ; + +GLREF_C VOID *AllocRemember(REMEMBER_LLIST *prem, INT size) ; +GLREF_C VOID FreeRemember(REMEMBER_LLIST *prem) ; + +/* Scroll and status bar routines */ + +#define SCROLL_WID 4 + +typedef struct SCROLL_BAR_STATE_TAG { + ULONG start, + size, + total ; +} SCROLL_BAR_STATE ; + +typedef struct SCROLL_BAR_TAG { + SCROLL_BAR_STATE state ; /* State of scroll bar */ + BOOL horz ; /* Orientation */ +} SCROLL_BAR ; + +typedef struct STATUS_BAR_TAG { + UINT font_id ; + UINT style ; + UINT ascent ; +} STATUS_BAR ; + +typedef union BAR_DATA_TAG { + SCROLL_BAR scroll ; + STATUS_BAR status ; +} BAR_DATA ; + +typedef struct BAR_OBJ_TAG { + UINT type ; /* Type of bar object - BAR_STATUS or BAR_SCROLL */ + P_EXTENT extent ; /* Extent of window */ + BOOL open ; /* Window open */ + UINT win_id ; /* Id of window */ + BAR_DATA data ; /* type-specific data */ +} BAR_OBJ ; + +GLREF_C VOID MakeScrollBar(BAR_OBJ *pbar, WORD tl_x, WORD tl_y, WORD length, BOOL horz) ; + +GLREF_C VOID MakeStatusBar(BAR_OBJ *pbar, UINT font_id, UINT style, P_POINT *pscreen_size) ; + +GLREF_C VOID UpdateBar(BAR_OBJ *pbar, VOID *pdata) ; +GLREF_C VOID ShowBar(BAR_OBJ *pbar) ; +GLREF_C VOID HideBar(BAR_OBJ *pbar) ; +GLREF_C VOID ToggleBar(BAR_OBJ *pbar) ; +GLREF_C VOID GetBarExtent(BAR_OBJ *pbar, P_EXTENT *pextent) ; + +#endif \ No newline at end of file diff --git a/src/utils/utils.lib b/src/utils/utils.lib new file mode 100644 index 0000000000000000000000000000000000000000..b0d4550461f13ac3cc296489f741adf76d6c67df GIT binary patch literal 6027 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 JHLO~~e*+Tc>45+M literal 0 HcmV?d00001 diff --git a/src/utils/utils.pr b/src/utils/utils.pr new file mode 100644 index 0000000..2749874 --- /dev/null +++ b/src/utils/utils.pr @@ -0,0 +1,13 @@ +#noedit +#abort on +#system epoc img +#model small jpi + +#pragma optimize(speed=>off) +#pragma debug(vid=>off) +#pragma define(EPOC=>1,JPIC=>1) + +#compile utils.c + +#dolink utils.lib +