├── LICENSE ├── Makefile ├── README.md ├── buildtcc.bat ├── loader.bat ├── res └── images │ ├── dge_lbig.bmp │ ├── ghosts.bmp │ └── rocket.bmp ├── runtimes ├── djgpp │ ├── bin │ │ └── CWSDPMI.EXE │ ├── copying │ ├── copying.dj │ ├── copying.lib │ └── djgpp.env └── dos32a │ ├── dos32a.exe │ └── license.txt ├── screenshots ├── screenshot_1.png ├── screenshot_2.png ├── screenshot_3.png ├── screenshot_4.png ├── screenshot_5.png ├── screenshot_6.png ├── screenshot_7.png └── screenshot_8.png ├── src ├── dge.c ├── dge.h ├── dge_bmp.c ├── dge_bmp.h ├── dge_gfx.c ├── dge_gfx.h ├── dge_inpt.c ├── dge_inpt.h ├── dge_snd.c ├── dge_snd.h ├── libkb │ ├── _handler.h │ ├── _kb.h │ ├── _kbmsdos.h │ ├── _kbname.hh │ ├── _kbtable.hh │ ├── kb.h │ ├── kbhandle.c │ ├── kbmlock.c │ ├── kbmlock.h │ ├── kbos.c │ ├── kbsignal.c │ └── kbtables.c ├── splash.c ├── test_gfx.c ├── test_snd.c └── tst_inpt.c └── todo.txt /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 dimecoin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # This is Makefile for building OpenWatcom and DJGPP executables. 2 | 3 | ##################################################### 4 | # This needs openwatcom installed. 5 | # http://openwatcom.org/ 6 | 7 | # Just setting WATCOM should work in most cases. 8 | export WATCOM:=${HOME}/opt/openwatcom/ 9 | export EDPATH:=${WATCOM}/eddat 10 | export WIPFC:=${WATCOM}/wipfc 11 | export INCLUDE:=${WATCOM}/h:src/libkb 12 | export LIB:=${WATCOM}/lib386/dos/:${WATCOM}/lib386:. 13 | 14 | ##################################################### 15 | # This is needs djgpp installed. 16 | # https://github.com/andrewwutw/build-djgpp 17 | 18 | # Just setting DJGPP_PREFIX should work in most cases. 19 | export DJGPP_PREFIX=${HOME}/opt/djgpp 20 | export BASE_DIR=${DJGPP_PREFIX} 21 | 22 | export PATH:=${WATCOM}/binl:${DJGPP_PREFIX}/bin:${PATH} 23 | 24 | ##################################################### 25 | # Envoriment setup 26 | 27 | SRC=src 28 | INCS=$(SRC)/dge.c $(SRC)/dge_gfx.c $(SRC)/dge_bmp.c $(SRC)/dge_snd.c $(SRC)/dge_inpt.c $(SRC)/libkb/kb.h 29 | #$(SRC)/libkb/kb.c 30 | PRG=test_gfx 31 | 32 | #comment out for asserts 33 | DJDFLAGS=-DNDEBUG 34 | OWDFLAGS=-dNDEBUG 35 | 36 | default: clean setup both 37 | 38 | setup: 39 | mkdir -p build/ow 40 | mkdir -p build/dj 41 | 42 | cp -Rp res/ build/ow/res 43 | cp -Rp res/ build/dj/res 44 | 45 | both: dj ow 46 | 47 | ow: 48 | # # flat memory model, no stack overflow checks, optimize, all warnings 49 | # CFLAGS = -mf -s -ox -wx -zq -I. 50 | 51 | wcl386 -l=dos4g -d0 -lr -4 -4r -4s -ox -ot -om -ob -ol -oh -oi -lr $(OWDFLAGS) $(SRC)/$(PRG).c $(INCS) $(SRC)/libkb/*.c -I$(SRC)/libkb 52 | cp *.exe build/ow; 53 | rm *.o 54 | ls -l build/ow/*.exe; 55 | 56 | dj: 57 | i586-pc-msdosdjgpp-gcc -pipe -O3 -fomit-frame-pointer -funroll-loops -ffast-math $(DJDFLAGS) \ 58 | -Isrc/libkb/ \ 59 | $(SRC)/$(PRG).c $(INCS) $(SRC)/libkb/*.c -o build/dj/$(PRG).exe 60 | ls -l build/dj/*.exe 61 | 62 | clean: 63 | rm -rf *.o *.err *.exe *~ build/ow/* build/dj/* $(SRC)/libkb/*~ 2> /dev/null || true 64 | rm $(SRC)/*.err $(SRC)/*~ 2> /dev/null || true 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DGEngine 2 | 3 | ![DGEngine Logo](https://github.com/dimecoin/dge/blob/master/res/images/dge_lbig.bmp "DGEngine Logo") 4 | 5 | A "modern" **D**OS **G**ame **E**ngine written in C that is fast, flexiable and has clean API. 6 | 7 | ## Screen shots 8 | 9 | ![screenshot_3](https://github.com/dimecoin/dge/blob/master/screenshots/screenshot_3.png "screen_shot3") 10 | ![screenshot_4](https://github.com/dimecoin/dge/blob/master/screenshots/screenshot_4.png "screen_shot4") 11 | ![screenshot_5](https://github.com/dimecoin/dge/blob/master/screenshots/screenshot_5.png "screen_shot5") 12 | 13 | More screenshots in [Screen Shots Directory](https://github.com/dimecoin/dge/tree/master/screenshots) 14 | 15 | ## Feature List 16 | 17 | * Runs on most DOS versions and emulators. (see Compatiablity below). 18 | * Compiles cleanly in most DOS compilers. (see Compatiablity below). 19 | * No assembly required, easy to use C API that abstracts BIOS/System calls, etc. 20 | * mode 13h: VGA 320x200 @ 256 colors (ie, Classic "Chunky Graphics") 21 | * Rendering systems: Direct BIOS writes, Memory Map and Double Buffer. Can easily create "retro" effects using BIOS/MEMMAP or get smooth graphics from DOUBLEBUFF. 22 | * Primative shapes (points, lines, rectangles, polys, circles and fill/color modes). 23 | * FPS/Delta counters. 24 | * PC Speaker sounds. 25 | * Text mode fonts for debugging. 26 | 27 | **More features to come!** 28 | Please see [todo.txt](https://github.com/dimecoin/dge/blob/master/todo.txt) for details. 29 | 30 | 31 | ## Compatiablity 32 | 33 | Operating Systems: 34 | * MS DOS 35 | * FreeDOS 36 | * DOS Box 37 | * Probably many others! 38 | 39 | Compilers: 40 | 41 | * DJGpp 6.3.0 (cross compile and native) 42 | * OpenWatcom 1.9 (cross compile and native) 43 | 44 | CPUs 45 | * 486 46 | * Pentium and above! 47 | * maybe others! 48 | 49 | ## Usage 50 | 51 | Please see [wiki pages](https://github.com/dimecoin/dge/wiki) for details. 52 | 53 | 54 | 55 | ## Credits 56 | 57 | Lots of code is taken from Dave Brackken's awesome [VGA tutorial](http://www.brackeen.com/vga/) . This game engine won't have been possiable without this great resource. 58 | 59 | Logo font is from [DOS VGA 437](http://www.dafont.com/perfect-dos-vga-437.font) 60 | 61 | 62 | ## License 63 | 64 | **Rendering Code** 65 | 66 | A lot of the rendering code is taken from Dave Breckeen. His license is as follows: 67 | * From source files: _"Please feel free to copy this source code."_ 68 | * From private email: _"Feel free to do whatever you want with it, no need for credit. Consider it public domain."_ 69 | * His tutorials are marked as [CC BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/) 70 | * Please check out this site at : http://www.brackeen.com/vga/ 71 | 72 | **DOS/32 Advanced** 73 | 74 | _"This product uses DOS/32 Advanced DOS Extender technology."_ 75 | 76 | **libkb** 77 | 78 | This product uses libkb Version 1.01, 03 Jun 1998. Please see [kb.h](https://github.com/dimecoin/dge/blob/master/src/libkb/kb.h) for more details. (A very small modification was made to kb.h and \_handler.h to get OpenWatcom 1.9 to compile.) 79 | 80 | **Runtimes** 81 | 82 | Please see runtimes directory for 3rd party licenses for DJGPP and OpenWatcom (DOS32/A). 83 | 84 | **DOSEngine license :** 85 | 86 | * MIT License (see license file) 87 | * We ask that you include "Made with DGEngine" in splash screen or credits, but this is 100% optional and NOT required. 88 | 89 | (**TLDR:** do whatever you want with it, no warranty) 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /buildtcc.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | REM This is the build script for Turbo C. 4 | REM Needs to run in DOSBox, VM or a real DOS machine. 5 | REM Turbo C 3.2 download: https://turboc.codeplex.com/ 6 | 7 | if "%1"=="" goto :HELP 8 | 9 | echo --------------------------------------------------- 10 | 11 | REM In most cases, you just need to point to your TURBOC directory 12 | set TURBOC_DIR=c:\TURBOC3 13 | set DGE_DIR=C:\dge 14 | 15 | set LIB=%TURBOC_DIR%\lib 16 | set INCLUDE=%TURBOC_DIR%\include 17 | set PATH=%TURBOC_DIR%;%TURBOC_DIR%\bin;C:\vim\vim73;%PATH% 18 | 19 | set 20 | echo --------------------------------------------------- 21 | 22 | 23 | REM requires Large memory model in most cases (-ml) 24 | REM http://www.digitalmars.com/ctg/ctgMemoryModel.html 25 | 26 | 27 | 28 | cd %DGE_DIR%\src\libkb 29 | tcc.exe -ml -y -G -O -C -j1 -I%INCLUDE% -I%DGE_DIR%\src\libkb -L%LIB% kb*.c 30 | copy %DGE_DIR%\src\libkb\*.OBJ %DGE_DIR%\src\ 31 | 32 | cd %DGE_DIR%\src 33 | tcc.exe -ml -y -G -O -C -j1 -I%INCLUDE% -I%DGE_DIR%\src\libkb -L%LIB% tst_inpt.c dge*.c 34 | REM libkb\*.c 35 | REM dge_bmp.c dge_gfx.c dge_snd.c 36 | REM kbhandle.c kblinux.c kbmlock.c kbos.c kbsignal.c kbtables.c 37 | 38 | 39 | mkdir %DGE_DIR%\build\tc 40 | copy *.exe %DGE_DIR%\build\tc 41 | 42 | mkdir %DGE_DIR%\build\tc\res 43 | mkdir %DGE_DIR%\build\tc\res\images 44 | 45 | copy %DGE_DIR%\res\images\*.bmp %DGE_DIR%\build\tc\res\images 46 | 47 | goto :END 48 | 49 | :HELP 50 | echo ################################################## 51 | echo Usage: buildtcc.bat [program name] (without ext) 52 | echo example: buildtcc.bat test_gfx 53 | echo ################################################## 54 | goto :END 55 | 56 | 57 | :END 58 | 59 | -------------------------------------------------------------------------------- /loader.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | REM This is a loader for DGEngine 4 | REM both DJGPP and OpenWatcom have deps 5 | REM Turbo C build does not. 6 | 7 | set DRIVE=%1: 8 | set BUILD=%2 9 | set PROG=%3 10 | 11 | if "%DRIVE%"=="" goto :HELP 12 | if "%BUILD%"=="" goto :HELP 13 | if "%PROG%"=="" goto :HELP 14 | 15 | echo Starting [ %BUILD% :: %PROG% ] 16 | 17 | set RUNTIMES=%DRIVE%\dge\runtimes 18 | 19 | echo --------------------------------------------------- 20 | set DJGPP=%RUNTIMES%\DJGPP\DJGPP.ENV 21 | set PATH=%RUNTIMES%\DJGPP\bin\;%RUNTIMES%\dos32a\ 22 | PATH %RUNTIMES%\DJGPP\bin\;%RUNTIMES%\dos32a\ 23 | set 24 | echo --------------------------------------------------- 25 | 26 | set BUILDDIR=%DRIVE%\dge\build\%BUILD% 27 | %DRIVE% 28 | cd %BUILDDIR% 29 | 30 | REM dos32a is required for OpenWatcom. 31 | if "%BUILD%"=="ow" dos32a.exe %BUILDDIR%\%PROG% 32 | 33 | REM DJGPP needs to be set for DJGPP build 34 | if "%BUILD%"=="dj" %BUILDDIR%\%PROG% 35 | 36 | REM Turbo C requires nothing 37 | if "%BUILD%"=="tc" %BUILDDIR%\%PROG% 38 | 39 | 40 | goto :END 41 | 42 | :HELP 43 | echo #################################################### 44 | echo Usage: [DRIVE LETTER] [BUILD] [PROGRAM] 45 | echo #################################################### 46 | goto :END 47 | 48 | :END 49 | 50 | -------------------------------------------------------------------------------- /res/images/dge_lbig.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dimecoin/dge/a94095d45cd98dfd50489a4e6a800850aa44b71a/res/images/dge_lbig.bmp -------------------------------------------------------------------------------- /res/images/ghosts.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dimecoin/dge/a94095d45cd98dfd50489a4e6a800850aa44b71a/res/images/ghosts.bmp -------------------------------------------------------------------------------- /res/images/rocket.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dimecoin/dge/a94095d45cd98dfd50489a4e6a800850aa44b71a/res/images/rocket.bmp -------------------------------------------------------------------------------- /runtimes/djgpp/bin/CWSDPMI.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dimecoin/dge/a94095d45cd98dfd50489a4e6a800850aa44b71a/runtimes/djgpp/bin/CWSDPMI.EXE -------------------------------------------------------------------------------- /runtimes/djgpp/copying: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /runtimes/djgpp/copying.dj: -------------------------------------------------------------------------------- 1 | This is the file "copying.dj". It does NOT apply to any sources or 2 | binaries copyrighted by UCB Berkeley, the Free Software Foundation, or 3 | any other agency besides DJ Delorie and others who have agreed to 4 | allow their sources to be distributed under these terms. 5 | 6 | Copyright Information for sources and executables that are marked 7 | Copyright (C) DJ Delorie 8 | 334 North Rd 9 | Deerfield NH 03037-1110 10 | 11 | This document is Copyright (C) DJ Delorie and may be distributed 12 | verbatim, but changing it is not allowed. 13 | 14 | Source code copyright DJ Delorie is distributed under the terms of the 15 | GNU General Public Licence, with the following exceptions: 16 | 17 | * Sources used to build crt0.o, gcrt0.o, libc.a, libdbg.a, and 18 | libemu.a are distributed under the terms of the GNU Library General 19 | Public License, rather than the GNU GPL. 20 | 21 | * Any existing copyright or authorship information in any given source 22 | file must remain intact. If you modify a source file, a notice to that 23 | effect must be added to the authorship information in the source file. 24 | 25 | * Runtime binaries, as provided by DJ in DJGPP, may be distributed 26 | without sources ONLY if the recipient is given sufficient information 27 | to obtain a copy of djgpp themselves. This primarily applies to 28 | go32-v2.exe, emu387.dxe, and stubedit.exe. 29 | 30 | * Runtime objects and libraries, as provided by DJ in DJGPP, when 31 | linked into an application, may be distributed without sources ONLY 32 | if the recipient is given sufficient information to obtain a copy of 33 | djgpp themselves. This primarily applies to crt0.o and libc.a. 34 | 35 | ----- 36 | 37 | Changes to source code copyright BSD, FSF, or others, by DJ Delorie 38 | fall under the terms of the original copyright. Such files usually 39 | have multiple copyright notices in them. 40 | 41 | A copy of the files "COPYING" and "COPYING.LIB" are included with this 42 | document. If you did not receive a copy of these files, you may 43 | obtain one from whence this document was obtained, or by writing: 44 | 45 | Free Software Foundation 46 | 51 Franklin Street, Fifth Floor 47 | Boston, MA 02110-1301 48 | USA 49 | -------------------------------------------------------------------------------- /runtimes/djgpp/copying.lib: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 489 | 490 | Also add information on how to contact you by electronic and paper mail. 491 | 492 | You should also get your employer (if you work as a programmer) or your 493 | school, if any, to sign a "copyright disclaimer" for the library, if 494 | necessary. Here is a sample; alter the names: 495 | 496 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 497 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 498 | 499 | , 1 April 1990 500 | Ty Coon, President of Vice 501 | 502 | That's all there is to it! 503 | -------------------------------------------------------------------------------- /runtimes/djgpp/djgpp.env: -------------------------------------------------------------------------------- 1 | #= Don't edit this line unless you move djgpp.env outside 2 | #= of the djgpp installation directory. If you do move 3 | #= it, set DJDIR to the directory you installed DJGPP in. 4 | #= 5 | DJDIR=%:/>DJGPP% 6 | 7 | +USER=dosuser 8 | +GROUP=root 9 | +TMPDIR=%DJDIR%/tmp 10 | +EMU387=%DJDIR%/bin/emu387.dxe 11 | +LFN=y 12 | +TEXMFMAIN=%DJDIR%/share/texmf 13 | +GO32STUB=%DJDIR%/bin/stubify.exe 14 | +LD_LIBRARY_PATH=%DJDIR%/lib;%DJDIR%/bin 15 | SYSTEM_DXE_PATH=%DJDIR%/lib;%DJDIR%/bin 16 | 17 | [bison] 18 | +BISON_HAIRY=%DJDIR%/lib/bison.hai 19 | +BISON_SIMPLE=%DJDIR%/lib/bison.sim 20 | 21 | [cpp] 22 | CPLUS_INCLUDE_PATH=%/>;CPLUS_INCLUDE_PATH%%DJDIR%/lang/cxx;%DJDIR%/include 23 | C_INCLUDE_PATH=%/>;C_INCLUDE_PATH%%DJDIR%/include 24 | OBJCPLUS_INCLUDE_PATH=%/>;OBJCPLUS_INCLUDE_PATH%%DJDIR%/include;%DJDIR%/lang/objc 25 | OBJC_INCLUDE_PATH=%/>;OBJC_INCLUDE_PATH%%DJDIR%/include;%DJDIR%/lang/objc 26 | 27 | [gcc] 28 | LIBRARY_PATH=%/>;LIBRARY_PATH%%DJDIR%/lib 29 | 30 | [info] 31 | INFOPATH=%/>;INFOPATH%%DJDIR%/share/info;%DJDIR%/info;%DJDIR%/gnu/emacs/info 32 | +INFO_COLORS=0x1f.0x31 33 | +INFO_LINES=40 34 | 35 | [emacs] 36 | INFOPATH=%/>;INFOPATH%%DJDIR%/share/info;%DJDIR%/info;%DJDIR%/gnu/emacs/info 37 | 38 | [less] 39 | +LESSBINFMT=*k<%%X> 40 | +LESSCHARDEF=8bcccbcc12bc5b95.b127.b 41 | LESS=-Rh5$y5$Dd2.0$Du14.0$Ds4.7$Dk9.0$%LESS% 42 | +LESSSEPARATOR=/ 43 | 44 | [ispell] 45 | +ISPELL_HOME=%DJDIR%/lib 46 | +ISPELL_DICTDIR=%DJDIR%/lib 47 | +ISPELL_COLORS=0x1e.0x74 48 | +LINES=40 49 | 50 | [locate] 51 | +LOCATE_PATH=%DJDIR%/lib/locatedb.dat 52 | 53 | [ls] 54 | +LS_COLORS=no=00:fi=00:di=36:ln=01;36:lb=37;07:cd=40;33;01:or=41;37;01:ex=32:*.cmd=32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.deb=01;31:*.jpg=01;34:*.gif=01;34:*.bmp=01;34:*.ppm=01;34:*.tga=01;34:*.xbm=01;34:*.xpm=01;34:*.tif=01;34:*.mpg=01;37:*.avi=01;37:*.gl=01;37:*.dl=01;37:*~=08:*.bak=08: 55 | [dir] 56 | +LS_COLORS=no=00:fi=00:di=36:ln=01;36:lb=37;07:cd=40;33;01:or=41;37;01:ex=32:*.cmd=32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.deb=01;31:*.jpg=01;34:*.gif=01;34:*.bmp=01;34:*.ppm=01;34:*.tga=01;34:*.xbm=01;34:*.xpm=01;34:*.tif=01;34:*.mpg=01;37:*.avi=01;37:*.gl=01;37:*.dl=01;37:*~=08:*.bak=08: 57 | [vdir] 58 | +LS_COLORS=no=00:fi=00:di=36:ln=01;36:lb=37;07:cd=40;33;01:or=41;37;01:ex=32:*.cmd=32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.deb=01;31:*.jpg=01;34:*.gif=01;34:*.bmp=01;34:*.ppm=01;34:*.tga=01;34:*.xbm=01;34:*.xpm=01;34:*.tif=01;34:*.mpg=01;37:*.avi=01;37:*.gl=01;37:*.dl=01;37:*~=08:*.bak=08: 59 | 60 | [enscript] 61 | +ENSCRIPT_LIBRARY=%DJDIR%/share/enscript 62 | 63 | [bash] 64 | PATH=%/>PATH% 65 | +CONFIG_SITE=%DJDIR%/share/config.site 66 | 67 | [sh] 68 | PATH=%/>PATH% 69 | +CONFIG_SITE=%DJDIR%/share/config.site 70 | 71 | [groff] 72 | +GROFF_TMAC_PATH=.;%DJDIR%/share/groff/site-tmac 73 | +GROFF_TYPESETTER=ascii 74 | +GROFF_FONT_PATH=.;%DJDIR%/share/groff/site-font 75 | 76 | [eqn] 77 | +GROFF_TMAC_PATH=.;%DJDIR%/share/groff/site-tmac 78 | +GROFF_TYPESETTER=ascii 79 | 80 | [grodvi] 81 | +GROFF_FONT_PATH=.;%DJDIR%/share/groff/site-font 82 | 83 | [grolj4] 84 | +GROFF_FONT_PATH=.;%DJDIR%/share/groff/site-font 85 | 86 | [grops] 87 | +GROFF_FONT_PATH=.;%DJDIR%/share/groff/site-font 88 | +GROFF_TMPDIR=%TMPDIR% 89 | 90 | [grotty] 91 | +GROFF_FONT_PATH=.;%DJDIR%/share/groff/site-font 92 | +GROFF_NO_SGR=1 93 | 94 | [indxbib] 95 | +GROFF_EIGN=%DJDIR%/share/groff/eign 96 | 97 | [lkbib] 98 | +REFER=%DJDIR%/share/Ind 99 | 100 | [refer] 101 | +REFER=%DJDIR%/share/Ind 102 | +GROFF_TMPDIR=%TMPDIR% 103 | 104 | [troff] 105 | +GROFF_TMAC_PATH=.;%DJDIR%/share/groff/site-tmac 106 | +GROFF_TYPESETTER=ascii 107 | +GROFF_FONT_PATH=.;%DJDIR%/share/groff/site-font 108 | 109 | [gawk] 110 | +AWKPATH=.;%DJDIR%/share/awk 111 | 112 | [awk] 113 | +AWKPATH=.;%DJDIR%/share/awk 114 | 115 | [man] 116 | MANPATH=%/>;MANPATH%%DJDIR%/share/man;%DJDIR%/man;%DJDIR%/info 117 | +PAGER=%DJDIR%/bin/less.exe 118 | 119 | [rhide] 120 | +RHIDE_TYPED_LIBS_DJGPP.cc=stdcxx m 121 | +RHIDE_TYPED_LIBS_DJGPP.cxx=stdcxx m 122 | +RHIDE_TYPED_LIBS_DJGPP.cpp=stdcxx m 123 | +RHIDE_TYPED_LIBS.f=g2c m 124 | -------------------------------------------------------------------------------- /runtimes/dos32a/dos32a.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dimecoin/dge/a94095d45cd98dfd50489a4e6a800850aa44b71a/runtimes/dos32a/dos32a.exe -------------------------------------------------------------------------------- /runtimes/dos32a/license.txt: -------------------------------------------------------------------------------- 1 | Please see: http://dos32a.narechk.net/index_en.html 2 | 3 | ------------------- 4 | 5 | DOS/32 Advanced DOS Extender Software License 6 | 7 | Copyright © 1996-2006 by Narech K. All rights reserved. 8 | 9 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 10 | 11 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 12 | 13 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 14 | 15 | 3. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: 16 | 17 | "This product uses DOS/32 Advanced DOS Extender technology." 18 | 19 | Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments normally appear. 20 | 21 | 4. Products derived from this software may not be called "DOS/32A" or "DOS/32 Advanced". 22 | 23 | THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | -------------------------------------------------------------------------------- /screenshots/screenshot_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dimecoin/dge/a94095d45cd98dfd50489a4e6a800850aa44b71a/screenshots/screenshot_1.png -------------------------------------------------------------------------------- /screenshots/screenshot_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dimecoin/dge/a94095d45cd98dfd50489a4e6a800850aa44b71a/screenshots/screenshot_2.png -------------------------------------------------------------------------------- /screenshots/screenshot_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dimecoin/dge/a94095d45cd98dfd50489a4e6a800850aa44b71a/screenshots/screenshot_3.png -------------------------------------------------------------------------------- /screenshots/screenshot_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dimecoin/dge/a94095d45cd98dfd50489a4e6a800850aa44b71a/screenshots/screenshot_4.png -------------------------------------------------------------------------------- /screenshots/screenshot_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dimecoin/dge/a94095d45cd98dfd50489a4e6a800850aa44b71a/screenshots/screenshot_5.png -------------------------------------------------------------------------------- /screenshots/screenshot_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dimecoin/dge/a94095d45cd98dfd50489a4e6a800850aa44b71a/screenshots/screenshot_6.png -------------------------------------------------------------------------------- /screenshots/screenshot_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dimecoin/dge/a94095d45cd98dfd50489a4e6a800850aa44b71a/screenshots/screenshot_7.png -------------------------------------------------------------------------------- /screenshots/screenshot_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dimecoin/dge/a94095d45cd98dfd50489a4e6a800850aa44b71a/screenshots/screenshot_8.png -------------------------------------------------------------------------------- /src/dge.c: -------------------------------------------------------------------------------- 1 | #include "dge.h" 2 | #include "dge_gfx.h" 3 | #include "dge_snd.h" 4 | #include "dge_inpt.h" 5 | 6 | #ifdef __WATCOMC__ 7 | int round(float num) { 8 | return num < 0 ? num - 0.5 : num + 0.5; 9 | } 10 | #endif 11 | 12 | 13 | /* this points to the 18.2hz system clock */ 14 | #ifdef __WATCOMC__ 15 | word *my_clock = (word *) 0x0000046C; 16 | #elif __DJGPP__ 17 | word *my_clock = (word *) 0x046C; 18 | #else 19 | // Borland C or Turbo C 20 | word *my_clock = (word *) 0x0000046C; 21 | #endif 22 | 23 | bool init_once = false; 24 | 25 | void dge_init(enum RENDER_MODE mode, int width, int height) { 26 | 27 | #ifdef __DJGPP__ 28 | 29 | if (!init_once) { 30 | 31 | if (__djgpp_nearptr_enable() == 0) { 32 | printf("Could get access to first 640K of memory.\n"); 33 | exit(-1); 34 | } 35 | 36 | my_clock = (void *)my_clock + __djgpp_conventional_base; 37 | } 38 | #endif 39 | 40 | srand(*my_clock); 41 | 42 | dge_graphics_init(mode, width, height); 43 | 44 | dge_input_init(); 45 | 46 | init_once = true; 47 | 48 | } 49 | 50 | void dge_shutdown() { 51 | 52 | #ifdef __DJGPP__ 53 | __djgpp_nearptr_disable(); 54 | #endif 55 | 56 | stop_all_sounds(); 57 | 58 | dge_input_shutdown(); 59 | 60 | dge_graphics_shutdown(); 61 | 62 | exit(0); 63 | } 64 | 65 | 66 | -------------------------------------------------------------------------------- /src/dge.h: -------------------------------------------------------------------------------- 1 | #ifndef DGE_H 2 | #define DGE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #ifdef __WATCOMC__ 15 | #define BUILD_TYPE "OpenWatcom" 16 | #elif __DJGPP__ 17 | #define BUILD_TYPE "djgpp" 18 | #elif __TURBOC__ 19 | #define BUILD_TYPE "TurboC" 20 | #elif __BORLANDC__ 21 | #define BUILD_TYPE "BorlandC" 22 | #else 23 | #define BUILD_TYPE "Unknown" 24 | #endif 25 | 26 | #if defined (__DJGPP__) || defined (__WATCOMC__) 27 | #include 28 | #endif 29 | 30 | #ifdef __DJGPP__ 31 | #include 32 | #endif 33 | 34 | /* macro to return the sign of a number */ 35 | #define sgn(x) ((x<0)?-1:((x>0)?1:0)) 36 | 37 | /* macro to write a word to a port */ 38 | #define word_out(port,register,value) \ 39 | outpw(port,(((word)value<<8) + register)) 40 | 41 | #define MAX(a,b) ((a) > (b) ? a : b) 42 | #define MIN(a,b) ((a) < (b) ? a : b) 43 | 44 | #ifdef __WATCOMC__ 45 | int round(float num); 46 | #endif 47 | 48 | 49 | // If this is defined, it will do bound checks on screen writes. 50 | // Can be disabled to speed things up. 51 | // But will crash if you write outside of screen in DJGPP/DOUBLEBUFF 52 | #define BOUND_CHECKS 1 53 | 54 | typedef enum { false, true } bool; 55 | typedef unsigned char byte; 56 | typedef unsigned short word; 57 | typedef unsigned long dword; 58 | typedef long fixed16_16; 59 | 60 | enum RENDER_MODE { 61 | NONE, // Not setup yet. 62 | TEXT, // normal text mode 63 | BIOS, // direct to bios, slow 64 | MEMMAP, // memory map 65 | DOUBLEBUFF, // memory map with double buffer 66 | MODEX // unchained mode 67 | }; 68 | 69 | /* this points to the 18.2hz system clock */ 70 | extern word *my_clock; 71 | #define CLOCK_SPEED 18.2 72 | 73 | extern bool init_once; 74 | 75 | void dge_init(enum RENDER_MODE mode, int width, int height); 76 | 77 | void dge_shutdown(); 78 | 79 | 80 | 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /src/dge_bmp.c: -------------------------------------------------------------------------------- 1 | #include "dge_bmp.h" 2 | 3 | void fskip(FILE * fp, int num_bytes) { 4 | int i; 5 | for (i = 0; i < num_bytes; i++) 6 | fgetc(fp); 7 | } 8 | 9 | void load_bmp(char *file, BITMAP * b) { 10 | 11 | FILE *fp; 12 | long index; 13 | word num_colors; 14 | int x; 15 | 16 | /* open the file */ 17 | if ((fp = fopen(file, "rb")) == NULL) { 18 | printf("Error opening file %s.\n", file); 19 | exit(1); 20 | } 21 | 22 | /* check to see if it is a valid bitmap file */ 23 | if (fgetc(fp) != 'B' || fgetc(fp) != 'M') { 24 | fclose(fp); 25 | printf("%s is not a bitmap file.\n", file); 26 | exit(1); 27 | } 28 | 29 | /* read in the width and height of the image, and the 30 | * number of colors used; ignore the rest */ 31 | fskip(fp, 16); 32 | fread(&b->width, sizeof(word), 1, fp); 33 | fskip(fp, 2); 34 | fread(&b->height, sizeof(word), 1, fp); 35 | fskip(fp, 22); 36 | fread(&num_colors, sizeof(word), 1, fp); 37 | fskip(fp, 6); 38 | 39 | /* assume we are working with an 8-bit file */ 40 | if (num_colors == 0) 41 | num_colors = 256; 42 | 43 | /* try to allocate memory */ 44 | if ((b->data = (byte *) malloc((word) (b->width * b->height))) == NULL) { 45 | fclose(fp); 46 | printf("Error allocating memory for file %s.\n", file); 47 | exit(1); 48 | } 49 | 50 | /* read the palette information */ 51 | for (index = 0; index < num_colors; index++) { 52 | b->palette[(int)(index * 3 + 2)] = fgetc(fp) >> 2; 53 | b->palette[(int)(index * 3 + 1)] = fgetc(fp) >> 2; 54 | b->palette[(int)(index * 3 + 0)] = fgetc(fp) >> 2; 55 | x = fgetc(fp); 56 | } 57 | 58 | /* read the bitmap */ 59 | for (index = (b->height - 1) * b->width; index >= 0; index -= b->width) 60 | for (x = 0; x < b->width; x++) 61 | b->data[(word) index + x] = (byte) fgetc(fp); 62 | 63 | fclose(fp); 64 | } 65 | 66 | void draw_bitmap(BITMAP * bmp, int x, int y) { 67 | 68 | int j; 69 | 70 | word screen_offset = (y << 8) + (y << 6) + x; 71 | word bitmap_offset = 0; 72 | 73 | for (j = 0; j < bmp->height; j++) { 74 | 75 | memcpy(&screen[screen_offset], &bmp->data[bitmap_offset], bmp->width); 76 | 77 | bitmap_offset += bmp->width; 78 | screen_offset += screen_width; 79 | 80 | } 81 | } 82 | 83 | void draw_transparent_bitmap(BITMAP * bmp, int x, int y) { 84 | int i, j; 85 | word screen_offset = (y << 8) + (y << 6); 86 | word bitmap_offset = 0; 87 | byte data; 88 | 89 | for (j = 0; j < bmp->height; j++) { 90 | for (i = 0; i < bmp->width; i++, bitmap_offset++) { 91 | data = bmp->data[bitmap_offset]; 92 | if (data) 93 | screen[screen_offset + x + i] = data; 94 | } 95 | screen_offset += screen_width; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/dge_bmp.h: -------------------------------------------------------------------------------- 1 | #ifndef DGE_BMP_H 2 | #define DGE_BMP_H 3 | 4 | #include "dge.h" 5 | #include "dge_gfx.h" 6 | 7 | typedef struct tagBITMAP { 8 | word width; 9 | word height; 10 | byte palette[256 * 3]; 11 | byte *data; 12 | } BITMAP; 13 | 14 | void fskip(FILE * fp, int num_bytes); 15 | void load_bmp(char *file, BITMAP * b); 16 | void draw_bitmap(BITMAP * bmp, int x, int y); 17 | void draw_transparent_bitmap(BITMAP * bmp, int x, int y); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/dge_gfx.c: -------------------------------------------------------------------------------- 1 | #include "dge_gfx.h" 2 | 3 | int screen_width = -1; 4 | int screen_height = -1; 5 | int screen_size = -1; 6 | int num_colors = -1; 7 | enum RENDER_MODE render_mode = NONE; 8 | 9 | /* this points to video memory. */ 10 | #ifdef __WATCOMC__ 11 | byte *VGA = (byte *) 0xA0000L; 12 | #elif __DJGPP__ 13 | byte *VGA = (byte *) 0xA0000; 14 | #else 15 | // Borland C or Turbo C 16 | byte *VGA = (byte *) 0xA0000000L; 17 | #endif 18 | 19 | byte *double_buffer = NULL; 20 | 21 | byte *screen; 22 | 23 | fixed16_16 SIN_ACOS[1024]; 24 | 25 | bool vsync = true; 26 | 27 | bool continuous_rendering = false; 28 | 29 | byte background_color = 0; 30 | 31 | bool show_fps = true; 32 | 33 | short fps_counter, fps_avg; 34 | word clock_start_time; 35 | float clock_cum_time, delta; 36 | 37 | void dge_graphics_init(enum RENDER_MODE mode, int width, int height) { 38 | 39 | screen_width = width; 40 | screen_height = height; 41 | screen_size = screen_width * screen_height; 42 | num_colors = 256; 43 | 44 | render_mode = mode; 45 | 46 | // Free our double buffer 47 | if (mode != DOUBLEBUFF && double_buffer != NULL) { 48 | free(double_buffer); 49 | double_buffer = NULL; 50 | } 51 | 52 | if (!init_once) { 53 | 54 | // Cache our trig values for faster circle drawing. 55 | { 56 | int i; 57 | for (i = 0; i < 1024; i++) { 58 | SIN_ACOS[i] = sin(acos((float)i / 1024)) * 0x10000L; 59 | } 60 | } 61 | 62 | #ifdef __DJGPP__ 63 | VGA += __djgpp_conventional_base; 64 | #endif 65 | 66 | } 67 | // Finally switch our mode. 68 | set_mode(VGA_256_COLOR_MODE); 69 | 70 | 71 | switch (mode) { 72 | case BIOS: 73 | case MEMMAP: 74 | screen = VGA; 75 | break; 76 | case DOUBLEBUFF: 77 | 78 | if (double_buffer == NULL) { 79 | if ((double_buffer = (byte *) malloc(screen_size)) == NULL) { 80 | printf("Not enough memory for double buffer.\n"); 81 | exit(1); 82 | } 83 | } 84 | 85 | screen = double_buffer; 86 | break; 87 | } 88 | 89 | } 90 | 91 | void set_palette(byte * palette) { 92 | int i; 93 | 94 | outp(PALETTE_INDEX, 0); /* tell the VGA that palette data is coming. */ 95 | for (i = 0; i < 256 * 3; i++) { 96 | outp(PALETTE_DATA, palette[i]); /* write the data */ 97 | } 98 | } 99 | 100 | void dge_graphics_shutdown() { 101 | 102 | if (double_buffer != NULL) { 103 | free(double_buffer); 104 | double_buffer = NULL; 105 | } 106 | 107 | set_mode(TEXT_MODE); 108 | } 109 | 110 | void set_mode(byte mode) { 111 | union REGS regs; 112 | 113 | regs.h.ah = SET_MODE; 114 | regs.h.al = mode; 115 | 116 | #ifdef __WATCOMC__ 117 | int386(VIDEO_INT, ®s, ®s); 118 | #else 119 | int86(VIDEO_INT, ®s, ®s); 120 | #endif 121 | 122 | } 123 | 124 | void show_buffer(byte * buffer) { 125 | memcpy(VGA, buffer, screen_size); 126 | } 127 | 128 | void graphics_begin() { 129 | 130 | clock_start_time = *my_clock; 131 | 132 | if (vsync && render_mode != DOUBLEBUFF) { 133 | wait_for_retrace(); 134 | } 135 | 136 | if (!continuous_rendering) { 137 | clear_screen(background_color); 138 | } 139 | 140 | } 141 | 142 | char fps_text[9]; 143 | char delta_text[13]; 144 | void graphics_end() { 145 | 146 | if (render_mode == DOUBLEBUFF) { 147 | 148 | if (vsync) { 149 | wait_for_retrace(); 150 | } 151 | 152 | show_buffer(double_buffer); 153 | } 154 | 155 | delta = (*my_clock - clock_start_time) / CLOCK_SPEED; 156 | if (delta >= 100) { 157 | delta = 99.999; 158 | } 159 | 160 | if (show_fps) { 161 | 162 | sprintf(fps_text, "FPS: %d", fps_avg); 163 | print_text(1, 1, PFC_GREEN, fps_text); 164 | 165 | sprintf(delta_text, "delta: %.3f", delta); 166 | print_text(1, 2, PFC_LIME, delta_text); 167 | 168 | fps_counter++; 169 | clock_cum_time += delta; 170 | if (clock_cum_time >= 1.0f || clock_cum_time < 0) { 171 | fps_avg = fps_counter; 172 | 173 | if (fps_avg > 999 || fps_avg < 0) { 174 | fps_avg = 999; 175 | } 176 | 177 | fps_counter = 0; 178 | clock_cum_time = 0; 179 | } 180 | } 181 | 182 | } 183 | 184 | void wait_for_retrace(void) { 185 | /* wait until done with vertical retrace */ 186 | while ((inp(INPUT_STATUS) & VRETRACE)) ; 187 | /* wait until done refreshing */ 188 | while (!(inp(INPUT_STATUS) & VRETRACE)) ; 189 | } 190 | 191 | void draw_pixel(int x, int y, byte color) { 192 | 193 | if (render_mode == BIOS) { 194 | union REGS regs; 195 | 196 | regs.h.ah = WRITE_DOT; 197 | regs.h.al = color; 198 | 199 | #ifdef __WATCOMC__ 200 | regs.w.cx = x; 201 | regs.w.dx = y; 202 | 203 | int386(VIDEO_INT, ®s, ®s); 204 | #else 205 | regs.x.cx = x; 206 | regs.x.dx = y; 207 | 208 | int86(VIDEO_INT, ®s, ®s); 209 | #endif 210 | 211 | return; 212 | } 213 | 214 | if (render_mode == MEMMAP || render_mode == DOUBLEBUFF) { 215 | screen_update(y * screen_width + x, color); 216 | return; 217 | } 218 | 219 | } 220 | 221 | void draw_line(int x1, int y1, int x2, int y2, byte color) { 222 | 223 | int i, dx, dy, sdx, sdy, dxabs, dyabs, x, y, px, py; 224 | 225 | dx = x2 - x1; /* the horizontal distance of the line */ 226 | dy = y2 - y1; /* the vertical distance of the line */ 227 | dxabs = abs(dx); 228 | dyabs = abs(dy); 229 | sdx = sgn(dx); 230 | sdy = sgn(dy); 231 | x = dyabs >> 1; 232 | y = dxabs >> 1; 233 | px = x1; 234 | py = y1; 235 | 236 | draw_pixel(px, py, color); 237 | 238 | if (dxabs >= dyabs) { /* the line is more horizontal than vertical */ 239 | for (i = 0; i < dxabs; i++) { 240 | y += dyabs; 241 | if (y >= dxabs) { 242 | y -= dxabs; 243 | py += sdy; 244 | } 245 | px += sdx; 246 | draw_pixel(px, py, color); 247 | } 248 | } else { /* the line is more vertical than horizontal */ 249 | 250 | for (i = 0; i < dyabs; i++) { 251 | x += dxabs; 252 | if (x >= dyabs) { 253 | x -= dyabs; 254 | px += sdx; 255 | } 256 | py += sdy; 257 | draw_pixel(px, py, color); 258 | } 259 | } 260 | } 261 | 262 | void draw_rect(int left, int top, int right, int bottom, byte color) { 263 | 264 | if (render_mode == BIOS) { 265 | 266 | draw_line(left, top, right, top, color); 267 | draw_line(left, top, left, bottom, color); 268 | draw_line(right, top, right, bottom, color); 269 | draw_line(left, bottom, right, bottom, color); 270 | 271 | return; 272 | } 273 | // Should be much faster 274 | if (render_mode == MEMMAP || render_mode == DOUBLEBUFF) { 275 | 276 | word top_offset, bottom_offset, i, temp; 277 | 278 | if (top > bottom) { 279 | temp = top; 280 | top = bottom; 281 | bottom = temp; 282 | } 283 | if (left > right) { 284 | temp = left; 285 | left = right; 286 | right = temp; 287 | } 288 | 289 | top_offset = (top << 8) + (top << 6); 290 | bottom_offset = (bottom << 8) + (bottom << 6); 291 | 292 | for (i = left; i <= right; i++) { 293 | screen_update(top_offset + i, color); 294 | screen_update(bottom_offset + i, color); 295 | } 296 | for (i = top_offset; i <= bottom_offset; i += screen_width) { 297 | screen_update(left + i, color); 298 | screen_update(right + i, color); 299 | } 300 | 301 | return; 302 | } 303 | 304 | } 305 | 306 | void fill_rect(int left, int top, int right, int bottom, byte color) { 307 | 308 | word top_offset, bottom_offset, i, temp, width; 309 | 310 | if (top > bottom) { 311 | temp = top; 312 | top = bottom; 313 | bottom = temp; 314 | } 315 | 316 | if (left > right) { 317 | temp = left; 318 | left = right; 319 | right = temp; 320 | } 321 | 322 | if (render_mode == BIOS) { 323 | 324 | int x = left; 325 | int y = bottom; 326 | 327 | for (; x < right; x++) { 328 | // bottom and top are reversed. 329 | for (y = bottom; y > top; y--) { 330 | draw_pixel(x, y, color); 331 | } 332 | } 333 | 334 | return; 335 | } 336 | 337 | if (render_mode == MEMMAP || render_mode == DOUBLEBUFF) { 338 | 339 | top_offset = (top << 8) + (top << 6) + left; 340 | bottom_offset = (bottom << 8) + (bottom << 6) + left; 341 | width = right - left + 1; 342 | 343 | for (i = top_offset; i <= bottom_offset; i += screen_width) { 344 | memset(&screen[i], color, width); 345 | } 346 | 347 | return; 348 | } 349 | 350 | } 351 | 352 | // TODO: could be optimized? 353 | void draw_polygon(int num_vertices, int *vertices, byte color) { 354 | 355 | int i; 356 | 357 | for (i = 0; i < num_vertices - 1; i++) { 358 | draw_line(vertices[(i << 1) + 0], vertices[(i << 1) + 1], 359 | vertices[(i << 1) + 2], vertices[(i << 1) + 3], color); 360 | } 361 | 362 | draw_line(vertices[0], vertices[1], vertices[(num_vertices << 1) - 2], 363 | vertices[(num_vertices << 1) - 1], color); 364 | 365 | } 366 | 367 | // TODO: need to implement 368 | void fill_polygon(int num_vertices, int *vertices, byte color) { 369 | draw_polygon(num_vertices, vertices, color); 370 | } 371 | 372 | void clear_screen(byte color) { 373 | 374 | if (render_mode == BIOS) { 375 | 376 | if (color == 0) { 377 | // This si a quick way to clear screen using default color. 378 | set_mode(VGA_256_COLOR_MODE); 379 | return; 380 | 381 | } else { 382 | int x, y; 383 | 384 | for (x = 0; x < screen_width; x++) { 385 | for (y = 0; y < screen_height; y++) { 386 | draw_pixel(x, y, color); 387 | } 388 | } 389 | return; 390 | } 391 | } 392 | 393 | if (render_mode == MEMMAP || render_mode == DOUBLEBUFF) { 394 | memset(screen, color, screen_size); 395 | return; 396 | } 397 | 398 | } 399 | 400 | #if defined (__DJGPP__) || defined (__WATCOMC__) 401 | inline 402 | #endif 403 | // Should this be defined as macro? Might be slow for Turbo C 404 | void screen_update(int value, byte color) { 405 | 406 | #ifdef BOUND_CHECKS 407 | if (value < 0 || value >= screen_size) { 408 | return; 409 | } 410 | #endif 411 | 412 | screen[value] = color; 413 | } 414 | 415 | // TODO: draw in BIOS mode, using draw_pixel instead 416 | void draw_circle(int x, int y, int radius, byte color) { 417 | 418 | fixed16_16 n = 0, invradius = (1 / (float)radius) * 0x10000L; 419 | int dx = 0, dy = radius - 1; 420 | word dxoffset, dyoffset, offset = (y << 8) + (y << 6) + x; 421 | 422 | while (dx <= dy) { 423 | dxoffset = (dx << 8) + (dx << 6); 424 | dyoffset = (dy << 8) + (dy << 6); 425 | 426 | screen_update(offset + dy - dxoffset, color); 427 | screen_update(offset + dx - dyoffset, color); /* octant 1 */ 428 | screen_update(offset - dx - dyoffset, color); /* octant 2 */ 429 | screen_update(offset - dy - dxoffset, color); /* octant 3 */ 430 | screen_update(offset - dy + dxoffset, color); /* octant 4 */ 431 | screen_update(offset - dx + dyoffset, color); /* octant 5 */ 432 | screen_update(offset + dx + dyoffset, color); /* octant 6 */ 433 | screen_update(offset + dy + dxoffset, color); /* octant 7 */ 434 | 435 | dx++; 436 | n += invradius; 437 | dy = (int)((radius * SIN_ACOS[(int)(n >> 6)]) >> 16); 438 | } 439 | 440 | } 441 | 442 | // TODO: draw in BIOS mode, using draw_pixel instead 443 | void fill_circle(int x, int y, int radius, byte color) { 444 | 445 | fixed16_16 n = 0, invradius = (1 / (float)radius) * 0x10000L; 446 | int dx = 0, dy = radius - 1, i; 447 | word dxoffset, dyoffset, offset = (y << 8) + (y << 6) + x; 448 | 449 | while (dx <= dy) { 450 | 451 | dxoffset = (dx << 8) + (dx << 6); 452 | dyoffset = (dy << 8) + (dy << 6); 453 | 454 | for (i = dy; i >= dx; i--, dyoffset -= screen_width) { 455 | 456 | screen_update(offset + i - dxoffset, color); 457 | screen_update(offset + dx - dyoffset, color); 458 | screen_update(offset - dx - dyoffset, color); 459 | screen_update(offset - i - dxoffset, color); 460 | screen_update(offset - i + dxoffset, color); 461 | screen_update(offset - dx + dyoffset, color); 462 | screen_update(offset + dx + dyoffset, color); 463 | screen_update(offset + i + dxoffset, color); 464 | 465 | } 466 | 467 | dx++; 468 | n += invradius; 469 | dy = (int)((radius * SIN_ACOS[(int)(n >> 6)]) >> 16); 470 | } 471 | } 472 | 473 | void set_cursor_pos(int x, int y) { 474 | 475 | union REGS iregs, oregs; 476 | 477 | iregs.h.ah = 0x0f; /* get video page */ 478 | 479 | #ifdef __WATCOMC__ 480 | int386(0x10, &iregs, &oregs); 481 | #else 482 | int86(0x10, &iregs, &oregs); 483 | #endif 484 | 485 | iregs.h.ah = 0x02; /* set cursor pos */ 486 | iregs.h.bh = oregs.h.bh; 487 | 488 | iregs.h.dl = (char)x - 1; 489 | iregs.h.dh = (char)y - 1; 490 | 491 | #ifdef __WATCOMC__ 492 | int386(0x10, &iregs, &oregs); 493 | #else 494 | int86(0x10, &iregs, &oregs); 495 | #endif 496 | } 497 | 498 | void print_text(int x, int y, int color, const char *string) { 499 | 500 | // gotoxy is not support under OpenWatcom. 501 | // gotoxy(x,y) 502 | 503 | set_cursor_pos(x, y); 504 | printf("\033[1;%dm%s\033[0m\n", color, string); 505 | } 506 | -------------------------------------------------------------------------------- /src/dge_gfx.h: -------------------------------------------------------------------------------- 1 | #ifndef DGE_GFX_H 2 | #define DGE_GFX_H 3 | 4 | #include "dge.h" 5 | 6 | #ifdef __WATCOMC__ 7 | #include 8 | #endif 9 | 10 | #define VIDEO_INT 0x10 /* the BIOS video interrupt. */ 11 | #define WRITE_DOT 0x0C /* BIOS func to plot a pixel. */ 12 | #define SET_MODE 0x00 /* BIOS func to set the video mode. */ 13 | 14 | #define VGA_256_COLOR_MODE 0x13 /* use to set 256-color mode. */ 15 | 16 | #define TEXT_MODE 0x03 /* use to set 80x25 text mode. */ 17 | 18 | #define INPUT_STATUS 0x03da 19 | #define VRETRACE 0x08 20 | 21 | // double buffer 22 | #define DISPLAY_ENABLE 0x01 /* VGA input status bits */ 23 | 24 | // palette data 25 | #define PALETTE_INDEX 0x03c8 26 | #define PALETTE_DATA 0x03c9 27 | 28 | // PFC = Primative Font Color. L=Light 29 | // These are used with print_text 30 | #define PFC_RED 31 31 | #define PFC_LIGHTGREEN 32 32 | #define PFC_YELLOW 33 33 | #define PFC_PURPLE 34 34 | #define PFC_BOLDPINK 35 35 | #define PFC_LBLUE 36 36 | #define PFC_WHITE 37 37 | #define PFC_GREEN 42 38 | #define PFC_BRICKRED 43 39 | #define PFC_LIME 45 40 | #define PFC_PINK 46 41 | #define PFC_BLUE 47 42 | 43 | extern int screen_width, screen_height, screen_size; 44 | extern int num_colors; 45 | extern enum RENDER_MODE render_mode; 46 | 47 | // A poor man's vsync. This still causes screen tearing with BIOS or MEMMAP. 48 | // TODO: could be done better? See wait_for_sync 49 | extern bool vsync; 50 | 51 | // If true, then it won't clear screen each cycle. 52 | // This can save cpu if background doesn't change much, but have to do manually. 53 | extern bool continuous_rendering; 54 | 55 | // Used as clear_screen's defaut 56 | extern byte background_color; 57 | 58 | // Our direct memory buffer 59 | extern byte *VGA; 60 | 61 | // Our double buffer 62 | extern byte *double_buffer; 63 | 64 | // You should write to screen, it's either VGA memmap OR the buffer, depending on rendering mode 65 | extern byte *screen; 66 | 67 | extern fixed16_16 SIN_ACOS[1024]; 68 | 69 | extern bool show_fps; 70 | extern short fps_counter, fps_avg; 71 | extern word clock_start_time; 72 | extern float clock_cum_time, delta; 73 | 74 | void dge_graphics_init(enum RENDER_MODE mode, int width, int height); 75 | void set_palette(byte * palette); 76 | 77 | void dge_graphics_shutdown(); 78 | 79 | void graphics_begin(); 80 | void graphics_end(); 81 | void wait_for_retrace(void); 82 | 83 | // This is used internally to bound check our double_buffer, because you can crash if written outside of it. 84 | // It is only really a problem for DJGPP builds with DOUBLEBUFF... 85 | // In dge.h you can disable BOUND_CHECK 86 | void screen_update(int value, byte color); 87 | 88 | void set_mode(byte mode); 89 | 90 | void draw_pixel(int x, int y, byte color); 91 | void draw_line(int x1, int y1, int x2, int y2, byte color); 92 | 93 | void draw_rect(int left, int top, int right, int bottom, byte color); 94 | void fill_rect(int left, int top, int right, int bottom, byte color); 95 | 96 | void draw_polygon(int num_vertices, int *vertices, byte color); 97 | void fill_polygon(int num_vertices, int *vertices, byte color); 98 | 99 | void draw_circle(int x, int y, int radius, byte color); 100 | void fill_circle(int x, int y, int radius, byte color); 101 | 102 | void show_buffer(byte * buffer); 103 | 104 | // Used by print_text to position. 105 | void set_cursor_pos(int x, int y); 106 | 107 | /* 108 | * This is a very primative way to print text in graphics mode. 109 | * It's pretty ulgy, probably only for debugging. 110 | * x/y are in cursor position (like text mode), not pixel locations. 111 | * use PFC_X for colors 112 | */ 113 | void print_text(int x, int y, int color, const char *string); 114 | 115 | void clear_screen(byte color); 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /src/dge_inpt.c: -------------------------------------------------------------------------------- 1 | #include "dge.h" 2 | #include "dge_inpt.h" 3 | 4 | void dge_input_init() { 5 | kb_install(0); 6 | } 7 | 8 | bool key_pressed(int key) { 9 | kb_update(); 10 | return (kb_key(key)); 11 | 12 | } 13 | 14 | void dge_input_shutdown() { 15 | kb_remove(); 16 | } 17 | -------------------------------------------------------------------------------- /src/dge_inpt.h: -------------------------------------------------------------------------------- 1 | #ifndef DGE_INPT_H 2 | #define DGE_INPT_H 3 | 4 | #include "dge.h" 5 | #include "libkb/kb.h" 6 | 7 | 8 | 9 | void dge_input_init(); 10 | 11 | bool key_pressed(int key); 12 | 13 | 14 | 15 | void dge_input_shutdown(); 16 | 17 | 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/dge_snd.c: -------------------------------------------------------------------------------- 1 | #include "dge.h" 2 | #include "dge_snd.h" 3 | 4 | void pc_sound(int note) { 5 | sound(note); 6 | } 7 | 8 | void stop_all_sounds() { 9 | nosound(); 10 | } 11 | -------------------------------------------------------------------------------- /src/dge_snd.h: -------------------------------------------------------------------------------- 1 | #ifndef DGE_SND_H 2 | #define DGE_SND_H 3 | 4 | #include "dge.h" 5 | 6 | void pc_sound(int note); 7 | 8 | void stop_all_sounds(); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /src/libkb/_handler.h: -------------------------------------------------------------------------------- 1 | /* _handler.h -- keyboard handler 2 | * Copyright (C) 1995-1998 Markus F.X.J. Oberhumer 3 | * For conditions of distribution and use, see copyright notice in kb.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the keyboard library and is 8 | subject to change. Applications should only use kb.h. 9 | */ 10 | 11 | /*********************************************************************** 12 | // int9 keyboard interrupt handler (IRQ1 keyboard data ready) 13 | // 14 | // IMPORTANT NOTE: check your compiler flags so that no 15 | // stack overflow checks will be inserted here ! 16 | // 17 | // Most of this code should be quite obvious. 18 | // Prefixed keys (E0) are mapped to unique scancodes. 19 | // 20 | // The Pause key requires some extra handling: 21 | // I have observed the following: 22 | // Pressing Pause generates these 3 codes: E1 1D 45 23 | // Pressing Control+Pause (== Break) generates E0 46 which is 24 | // mapped to an unique virtual scancode. 25 | // Pressing both Control keys + Pause generates Pause and not E0 46. 26 | // The release codes for Pause (E1 80+1D 80+45) and Control+Pause 27 | // (E0 80+46) are always generated after the press codes ! 28 | // Releasing Pause or Control+Pause generates nothing - this is the 29 | // reason that there is no scancode for these, only the shift toggles. 30 | // The Pause key is the only key that generates E1. 31 | // Implementation: 32 | // The only thing to care for is the code 1D (KB_SCAN_LCONTROL) 33 | // in combination with the prefix count. 34 | // This code is mapped to a special virtual key so that the 35 | // current shift status won't get touched. 36 | // Fortunately E0 45 is never generated, so 37 | // the E1 1D 45 conversion works fine. 38 | // 39 | // The Print key is also somewhat unusual: 40 | // normally it generates E0 37, but when Alt is pressed then 54 41 | ************************************************************************/ 42 | 43 | #if ( defined(__BORLANDC__) || defined(__TURBOC__) ) && defined(__KB_MSDOS16) 44 | static void interrupt far _my_keyint() { 45 | unsigned char _t_scan; 46 | unsigned short _t_shift; 47 | 48 | #elif defined(_MSC_VER) && defined(__KB_MSDOS16) 49 | static void __cdecl __interrupt __far _my_keyint() { 50 | unsigned char _t_scan; 51 | unsigned short _t_shift; 52 | 53 | #elif defined(__EMX__) && defined(__KB_MSDOS) 54 | static void _my_keyint() { 55 | unsigned char _t_scan; 56 | unsigned short _t_shift; 57 | 58 | #elif defined(__DJGPP__) && defined(__KB_MSDOS) 59 | static void _my_keyint(_go32_dpmi_registers * regs) { 60 | unsigned char _t_scan; 61 | unsigned short _t_shift; 62 | 63 | UNUSED(regs); 64 | 65 | #elif defined(__GO32__) && defined(__KB_MSDOS) 66 | /* stop djgpp v1 messing up with stack reads */ 67 | static unsigned char _t_scan; 68 | static unsigned short _t_shift; 69 | static void _my_keyint(_go32_dpmi_registers * regs) { 70 | UNUSED(regs); 71 | 72 | #elif defined(__WATCOMC__) && defined(__KB_MSDOS) 73 | static void __interrupt __far _my_keyint(union INTPACK regs) { 74 | unsigned char _t_scan; 75 | unsigned short _t_shift; 76 | 77 | #elif defined(__KB_LINUX) 78 | 79 | /* note: this is NOT an interrupt handler */ 80 | #if defined(KB_LINUX_MEDIUMRAW) 81 | static void _my_mediumraw_handler(unsigned char _t_scan) 82 | #else 83 | static void _my_raw_handler(unsigned char _t_scan) 84 | #endif 85 | { 86 | unsigned short _t_shift; 87 | 88 | #else 89 | #error unsupported compiler 90 | #endif 91 | 92 | #if defined(__KB_MSDOS) 93 | /* read keyboard byte */ 94 | _t_scan = KB_INP8(0x60); 95 | 96 | /* tell the XT keyboard controller to clear the key */ 97 | /* this is only necessary on XT's */ 98 | #if defined(__KB_MSDOS16) 99 | { 100 | /* TODO: do we have to care about slow I/O on fast machines ? */ 101 | unsigned char _t_tmp = KB_INP8(0x61); 102 | KB_OUTP8(0x61, _t_tmp | 0x80); 103 | KB_OUTP8(0x61, _t_tmp & 0x7f); 104 | } 105 | #endif 106 | #endif 107 | 108 | #if !defined(KB_LINUX_MEDIUMRAW) 109 | if (kb_handler_callback) 110 | kb_handler_callback(_t_scan); 111 | #endif 112 | 113 | #if defined(KB_DEBUG) 114 | /* store port value in buffer */ 115 | *_kb_port_buffer_head++ = _t_scan; 116 | if (_kb_port_buffer_head >= _kb_port_buffer_end) 117 | _kb_port_buffer_head = _kb_port_buffer_start; 118 | #endif 119 | 120 | #if !defined(KB_LINUX_MEDIUMRAW) 121 | if (_t_scan >= 0xe0) { 122 | if (_t_scan <= 0xe1) { /* E0, E1: key prefix */ 123 | _t_prefix = _t_scan - (0xe0 - 1); /* prefix count */ 124 | } else if (_t_scan == 0xff) { /* handle overflow */ 125 | /* try it: press a lot of keys */ 126 | _t_prefix = 0; 127 | _kb_shift |= KB_SHIFT_OVERFLOW; 128 | } else { 129 | /* ignore unknown keys */ 130 | _t_prefix = 0; 131 | _kb_shift |= KB_SHIFT_UNKNOWN; 132 | } 133 | } else 134 | #endif 135 | 136 | if (_t_scan & 0x80) { /* key was released */ 137 | _t_scan &= 0x7f; 138 | #if !defined(KB_LINUX_MEDIUMRAW) 139 | if (_t_scan > KB_SCAN_MAX_RAW) { 140 | _t_scan = KB_SCAN_UNKNOWN; 141 | _t_prefix = 0; 142 | } else if (_t_prefix > 0) { /* convert scancode */ 143 | if (--_t_prefix > 0) 144 | _t_scan = (_t_scan == KB_SCAN_LCONTROL) ? KB_SCAN_UNUSED_VIRTUAL : KB_SCAN_UNKNOWN; 145 | else 146 | _t_scan = _kb_prefix_scancode[_t_scan]; 147 | } 148 | #endif 149 | 150 | if (kb_handler_mediumraw_callback) 151 | kb_handler_mediumraw_callback(_t_scan | 0x80); 152 | 153 | _t_shift = _kb_shift_state_table[_t_scan]; 154 | 155 | if (_t_shift & KB_SHIFT_UNKNOWN) 156 | _kb_shift |= KB_SHIFT_UNKNOWN; 157 | else if (_kb_key[_t_scan]) { 158 | _kb_key[_t_scan] = 0; 159 | _t_shift &= KB_SHIFT_MASK_SHIFT; 160 | _kb_shift &= ~_t_shift; /* clear bit */ 161 | --_kb_keys_pressed; 162 | } 163 | } 164 | 165 | else { /* key was pressed */ 166 | 167 | #if !defined(KB_LINUX_MEDIUMRAW) 168 | if (_t_scan > KB_SCAN_MAX_RAW) { 169 | _t_scan = KB_SCAN_UNKNOWN; 170 | _t_prefix = 0; 171 | } else if (_t_prefix > 0) { /* convert scancode */ 172 | if (--_t_prefix > 0) 173 | _t_scan = (_t_scan == KB_SCAN_LCONTROL) ? KB_SCAN_UNUSED_VIRTUAL : KB_SCAN_UNKNOWN; 174 | else 175 | _t_scan = _kb_prefix_scancode[_t_scan]; 176 | } 177 | #endif 178 | 179 | if (kb_handler_mediumraw_callback) 180 | kb_handler_mediumraw_callback(_t_scan); 181 | 182 | _t_shift = _kb_shift_state_table[_t_scan]; 183 | 184 | if (_t_shift & KB_SHIFT_UNKNOWN) 185 | _kb_shift |= KB_SHIFT_UNKNOWN; 186 | else if (!_kb_key[_t_scan]) { 187 | _kb_shift ^= _t_shift; /* toggle shift status */ 188 | if (!(_t_shift & KB_SHIFT_VIRTUAL)) { /* do not count virtual keys */ 189 | _kb_key[_t_scan] = 1; 190 | _kb_last_key = _t_scan | (_kb_shift << 8); 191 | #if (USHRT_MAX > 0xffff) 192 | _kb_last_key &= 0xffff; 193 | #endif 194 | ++_kb_keys_pressed; 195 | } 196 | } else if (_kb_flags & KB_FLAG_REPEAT_OFF) 197 | _t_shift |= KB_SHIFT_NO_PRESS; 198 | 199 | if (!(_t_shift & KB_SHIFT_NO_PRESS)) { /* if this key stores a press */ 200 | /* store keypress: scan code + low bits of shift state */ 201 | *_key_buffer_head++ = _t_scan; 202 | *_key_buffer_head++ = (unsigned char)_kb_shift; 203 | 204 | /* adjust pointers */ 205 | if (_key_buffer_head >= _key_buffer_end) 206 | _key_buffer_head = _key_buffer_start; 207 | if (_key_buffer_head == _key_buffer_tail) { /* buffer full */ 208 | _key_buffer_tail += 2; 209 | if (_key_buffer_tail >= _key_buffer_end) 210 | _key_buffer_tail = _key_buffer_start; 211 | } 212 | } 213 | 214 | /* Emergency exit. 215 | * Raising a signal or exiting within an interrupt handler is probably 216 | * no good idea. The DPMI specs also say that an application should not 217 | * terminate during an interrupt that is reflected from real-mode 218 | * to protected-mode. 219 | * But during development it could be worthwile to try it - if your 220 | * program locks, a reboot would be necessary anyway. 221 | * It seems to work with Borland C/Watcom C/djgpp though. 222 | * note: both control keys have to be pressed 223 | */ 224 | if (_kb_flags & KB_FLAG_EMERGENCY_EXIT) { 225 | if (!_emergency_done && _kb_key[KB_SCAN_C] && 226 | _kb_key[KB_SCAN_LCONTROL] && (_kb_key[KB_SCAN_RCONTROL] || _kb_key[KB_SCAN_RMENU])) { 227 | _emergency_done = 1; 228 | #if defined(__DJGPP__) 229 | /* Internal function that raises SIGINT immediately 230 | * after the end of this interrupt. 231 | * Do not ignore SIGINT when using emergency-exit ! 232 | */ 233 | __asm__ __volatile__(" movb $0x79,%%al \n" 234 | " call ___djgpp_hw_exception \n":::"%eax", "%ebx", "%ecx", "%edx", 235 | "%esi", "%edi", "memory", "cc"); 236 | #else 237 | KB_ACKINT(); /* ack. interrupt */ 238 | _kb_emergency_remove(0); 239 | #if !defined(_KB_NO_SIGNALS) 240 | raise(SIGINT); 241 | #if defined(SIGBREAK) 242 | raise(SIGBREAK); /* try this if SIGINT returns */ 243 | #endif 244 | #endif 245 | exit(EXIT_SIG(SIGINT)); /* exit if signal handlers return */ 246 | #endif 247 | } 248 | } 249 | } 250 | 251 | KB_ACKINT(); /* ack. interrupt */ 252 | } 253 | 254 | /* 255 | vi:ts=4 256 | */ 257 | -------------------------------------------------------------------------------- /src/libkb/_kb.h: -------------------------------------------------------------------------------- 1 | /* _kb.h -- include file used for building 'libkb' 2 | * Copyright (C) 1995-1998 Markus F.X.J. Oberhumer 3 | * For conditions of distribution and use, see copyright notice in kb.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the keyboard library and is 8 | subject to change. Applications should only use kb.h. 9 | */ 10 | 11 | #ifndef __LIBKB_KB_INTERNAL_H 12 | #define __LIBKB_KB_INTERNAL_H 13 | 14 | /* memory locking */ 15 | #if defined(__KB_MSDOS32) 16 | #if defined(__DJGPP__) || defined(__WATCOMC__) 17 | #include 18 | #endif 19 | #endif 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | #if !defined(__inline__) && !defined(__GNUC__) 26 | #if defined(__cplusplus) 27 | #define __inline__ inline 28 | #else 29 | #define __inline__ /* nothing */ 30 | #endif 31 | #endif 32 | 33 | /* make KB_DEBUG numeric if defined */ 34 | #if defined(KB_DEBUG) && (KB_DEBUG < 1) 35 | #undef KB_DEBUG 36 | #define KB_DEBUG 1 37 | #endif 38 | 39 | /* exit code for a signal */ 40 | #define EXIT_SIG(signum) (128 + ((signum) & 0x7f)) 41 | 42 | #ifndef HIGH 43 | #define HIGH(x) ((int)(sizeof(x)/sizeof(*(x)))) 44 | #endif 45 | 46 | #define UNUSED(parm) (parm = parm) 47 | 48 | /*********************************************************************** 49 | // virtual keys and shift-states for internal use 50 | ************************************************************************/ 51 | 52 | #define KB_SCAN_UNKNOWN 0 /* internal - must be 0 */ 53 | #define KB_SCAN_MAX_RAW 0x5d /* 0x5d -> KB_SCAN_RMENU */ 54 | 55 | #define KB_SCAN_CONTROL_BREAK_VIRTUAL 101 /* 0x65 - Linux */ 56 | #define KB_SCAN_PAUSE_VIRTUAL 119 /* 0x77 - Linux */ 57 | 58 | /* hopefully the next code doesn't exist on an exotic keyboard... */ 59 | #define KB_SCAN_UNUSED_VIRTUAL 120 /* 0x78 */ 60 | 61 | #define KB_SHIFT_NO_PRESS 0x4000 /* do not generate a key press */ 62 | #define KB_SHIFT_VIRTUAL 0x8000 /* one of the virtual keys above */ 63 | 64 | #define KB_SHIFT_MASK_SHIFT 0x003f /* mask for a 'normal' shift flag */ 65 | #define KB_SHIFT_MASK_TOGGLE 0x0fc0 /* mask for a toggle flag */ 66 | 67 | /*********************************************************************** 68 | // internal tables 69 | ************************************************************************/ 70 | 71 | extern const unsigned char _kb_prefix_scancode[128]; 72 | /**** extern const unsigned char _kb_inverse_prefix_scancode[128]; */ 73 | 74 | extern const unsigned short _kb_shift_state_table[128]; 75 | /**** extern const unsigned short _kb_unshift_state_table[128]; */ 76 | 77 | #if 0 78 | extern unsigned short _kb_plain_table[128]; 79 | extern unsigned short _kb_shift_table[128]; 80 | extern unsigned short _kb_alt_table[128]; 81 | extern unsigned short _kb_control_table[128]; 82 | #else 83 | /* these are static const tables now */ 84 | #define _kb_plain_table default_plain_table 85 | #define _kb_shift_table default_shift_table 86 | #define _kb_alt_table default_alt_table 87 | #define _kb_control_table default_control_table 88 | #endif 89 | 90 | void _kb_init_tables(void); 91 | 92 | extern const unsigned kb_version_id; 93 | extern const char kb_version_string[]; 94 | extern const char kb_version_date[]; 95 | extern const char kb_copyright[]; 96 | 97 | /*********************************************************************** 98 | // locking - this is very important under MSDOS + DPMI 99 | ************************************************************************/ 100 | 101 | /* one lock function for each source file */ 102 | int _libkb_kbhandle_lock(void); 103 | int _libkb_kbmlock_lock(void); 104 | int _libkb_kbos_lock(void); 105 | int _libkb_kbsignal_lock(void); 106 | int _libkb_kbtables_lock(void); 107 | 108 | /* main lock function */ 109 | int _kb_lock(void); 110 | void _kb_unlock(void); 111 | 112 | /*********************************************************************** 113 | // misc. 114 | ************************************************************************/ 115 | 116 | int _kb_signal_install(void); 117 | int _kb_signal_lock(void); 118 | 119 | int _kb_signal_alarm_install(void); 120 | void _kb_signal_alarm_update(void); 121 | 122 | void _kb_emergency_remove(int final); 123 | 124 | #if defined(__KB_LINUX) 125 | 126 | int _kb_linux_switch_vt(int fd, int vt); 127 | int _kb_linux_is_switch(int *vt, int vtnum1, int vtnum2); 128 | int _kb_linux_update(const unsigned char *buf, int len, void (*key_handler) (unsigned char)); 129 | 130 | #endif 131 | 132 | /*********************************************************************** 133 | // BIOS keyboard access 134 | ************************************************************************/ 135 | 136 | #if defined(__KB_MSDOS) 137 | 138 | /* cmd values for kb_bioskey() */ 139 | #define KB_KEYBRD_READ 0 /* read key */ 140 | #define KB_NKEYBRD_READ 0x10 /* read key - enhanced */ 141 | #define KB_KEYBRD_READY 1 /* check key ready */ 142 | #define KB_NKEYBRD_READY 0x11 /* check key ready - enhanced */ 143 | #define KB_KEYBRD_SHIFTSTATUS 2 /* get shift status */ 144 | #define KB_NKEYBRD_SHIFTSTATUS 0x12 /* get shift status - enhanced */ 145 | 146 | #endif 147 | 148 | int kb_bioskey(unsigned _cmd); 149 | 150 | /*********************************************************************** 151 | // low level includes and defines 152 | ************************************************************************/ 153 | 154 | #if ( ( defined(__BORLANDC__) || defined(__TURBOC__) ) && defined(__MSDOS__) ) 155 | #include 156 | #include 157 | #define KB_DISABLE() disable() 158 | #define KB_ENABLE() enable() 159 | #define KB_INP8(a) inportb(a) 160 | #define KB_OUTP8(a,b) outportb(a,b) 161 | #define KB_INT86_REGS union REGS 162 | #define KB_INT86(n,r) int86(n,r,r) 163 | #elif defined(__EMX__) 164 | #include 165 | #include 166 | #include 167 | #if 1 168 | #define KB_DISABLE() /* not allowed under emx */ 169 | #define KB_ENABLE() /* not allowed under emx */ 170 | #else 171 | #define KB_DISABLE() __asm__ __volatile__("cli \n") 172 | #define KB_ENABLE() __asm__ __volatile__("sti ; cld \n") 173 | #endif 174 | #define KB_INP8(a) _inp8(a) 175 | #define KB_OUTP8(a,b) _outp8(a,b) 176 | #define KB_INT86_REGS union REGS 177 | #define KB_INT86(n,r) _int86(n,r,r) 178 | #define KB_USE_INT86() \ 179 | (_osmode == DOS_MODE && (_emx_env & 0x0800)) /* _int86() allowed ? */ 180 | #elif defined(__DJGPP__) 181 | #if !defined(__GO32__) 182 | #error check your djgpp configuration 183 | #endif 184 | #include 185 | #include 186 | #include 187 | #include 188 | #include 189 | #include 190 | #if 1 191 | #define KB_DISABLE() __asm__ __volatile__("cli \n") 192 | #define KB_ENABLE() __asm__ __volatile__("sti ; cld \n") 193 | #else 194 | /* don't use this - makes problems in a Windows 3.1 DOS box ! */ 195 | #define KB_DISABLE() __dpmi_get_and_disable_virtual_interrupt_state() 196 | #define KB_ENABLE() __dpmi_get_and_enable_virtual_interrupt_state() 197 | #endif 198 | #define KB_INP8(a) inportb(a) 199 | #define KB_OUTP8(a,b) outportb(a,b) 200 | #define KB_INT86_REGS __dpmi_regs 201 | #define KB_INT86(n,r) __dpmi_int(n,r) 202 | #elif defined(__GO32__) 203 | #include 204 | #include 205 | #include 206 | #include 207 | #include 208 | #define _KB_NO_SIGNALS /* djgpp v1 has no useable signals */ 209 | #if 1 210 | #define KB_DISABLE() __asm__ __volatile__("cli \n") 211 | #define KB_ENABLE() __asm__ __volatile__("sti ; cld \n") 212 | #else 213 | #define KB_DISABLE() disable() 214 | #define KB_ENABLE() enable() 215 | #endif 216 | #define KB_INP8(a) inportb(a) 217 | #define KB_OUTP8(a,b) outportb(a,b) 218 | #define KB_INT86_REGS union REGS 219 | #define KB_INT86(n,r) int86(n,r,r) 220 | #elif defined(_MSC_VER) && defined(MSDOS) 221 | #include 222 | #include 223 | #define KB_DISABLE() _disable() 224 | #define KB_ENABLE() _enable() 225 | #define KB_INP8(a) inp(a) 226 | #define KB_OUTP8(a,b) outp(a,b) 227 | #define KB_INT86_REGS union REGS 228 | #define KB_INT86(n,r) int86(n,r,r) 229 | #elif defined(__WATCOMC__) // && defined(MSDOS) 230 | #include 231 | #include 232 | #include 233 | #define KB_DISABLE() _disable() 234 | #define KB_ENABLE() _enable() 235 | #define KB_INP8(a) inp(a) 236 | #define KB_OUTP8(a,b) outp(a,b) 237 | #define KB_INT86_REGS union REGPACK 238 | #define KB_INT86(n,r) intr(n,r) 239 | #elif defined(__KB_LINUX) 240 | #include 241 | #define KB_INP8(a) /* nothing */ 242 | #define KB_OUTP8(a,b) /* nothing */ 243 | #if 1 244 | #define KB_DISABLE() /* not allowed and not needed under Linux */ 245 | #define KB_ENABLE() /* not allowed and not needed under Linux */ 246 | #else 247 | #include /* probably only legal for kernel building */ 248 | #define KB_DISABLE() cli() 249 | #define KB_ENABLE() sti() 250 | #endif 251 | #define KB_SIGNAME(n) (_sys_siglist[n]) 252 | #else 253 | #error unsupported compiler 254 | #endif 255 | 256 | #if !defined(KB_DISABLE) 257 | #define KB_DISABLE() /* nothing */ 258 | #endif 259 | #if !defined(KB_ENABLE) 260 | #define KB_ENABLE() /* nothing */ 261 | #endif 262 | 263 | #if defined(KB_INT86_REGS) 264 | void _kb_int86_regs_init(KB_INT86_REGS * regs); 265 | void _kb_int86_regs_init_ax(KB_INT86_REGS * regs, unsigned short ax); 266 | #endif 267 | 268 | #ifdef __cplusplus 269 | } /* extern "C" */ 270 | #endif 271 | #endif /* already included */ 272 | /* 273 | vi:ts=4 274 | */ 275 | -------------------------------------------------------------------------------- /src/libkb/_kbmsdos.h: -------------------------------------------------------------------------------- 1 | /* _kbmsdos.h -- low-level MSDOS keyboard installaton 2 | * Copyright (C) 1995-1998 Markus F.X.J. Oberhumer 3 | * For conditions of distribution and use, see copyright notice in kb.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the keyboard library and is 8 | subject to change. Applications should only use kb.h. 9 | */ 10 | 11 | /*********************************************************************** 12 | // keyboard handler 13 | ************************************************************************/ 14 | 15 | #include "_handler.h" 16 | 17 | /*********************************************************************** 18 | // 19 | ************************************************************************/ 20 | 21 | void kb_update(void) { 22 | if (!_kb_mode) 23 | return; 24 | 25 | /* Control-C check */ 26 | if (_kb_flags & KB_FLAG_SIGINT) { 27 | if (_kb_key[KB_SCAN_C] && (_kb_key[KB_SCAN_LCONTROL] || _kb_key[KB_SCAN_RCONTROL])) { 28 | #if !defined(_KB_NO_SIGNALS) 29 | raise(SIGINT); 30 | #else 31 | kb_remove(); 32 | exit(EXIT_SIG(SIGINT)); /* sorry, but what else ? */ 33 | #endif 34 | } 35 | } 36 | #if !defined(_KB_NO_SIGNALS) && defined(SIGALRM) 37 | if (_kb_flags & KB_FLAG_EMERGENCY_SIGALRM) 38 | _kb_signal_alarm_update(); 39 | #endif 40 | } 41 | 42 | /*********************************************************************** 43 | // 44 | ************************************************************************/ 45 | 46 | #if defined(__BORLANDC__) 47 | 48 | static void (interrupt far * _oldkeyint) (void) = NULL; 49 | 50 | static int _kb_install(void) { 51 | _oldkeyint = getvect(9); 52 | setvect(9, _my_keyint); 53 | return _my_keyint == getvect(9) ? 0 : -1; 54 | } 55 | 56 | #pragma argsused 57 | static void _kb_remove(int final) { 58 | if (_oldkeyint) 59 | setvect(9, _oldkeyint); 60 | } 61 | 62 | #endif /* __BORLANDC__ */ 63 | 64 | /*********************************************************************** 65 | // 66 | ************************************************************************/ 67 | 68 | #if defined(_MSC_VER) && defined(__KB_MSDOS16) 69 | 70 | static void (__cdecl __interrupt __far * _oldkeyint) () = NULL; 71 | 72 | static int _kb_install(void) { 73 | _oldkeyint = _dos_getvect(9); 74 | _dos_setvect(9, _my_keyint); 75 | return _my_keyint == _dos_getvect(9) ? 0 : -1; 76 | } 77 | 78 | static void _kb_remove(int final) { 79 | if (_oldkeyint) 80 | _dos_setvect(9, _oldkeyint); 81 | } 82 | 83 | #endif /* _MSC_VER */ 84 | 85 | /*********************************************************************** 86 | // 87 | ************************************************************************/ 88 | 89 | #if defined(__WATCOMC__) 90 | 91 | static void (__interrupt __far * _oldkeyint) () = NULL; 92 | 93 | static int _kb_install(void) { 94 | _oldkeyint = _dos_getvect(9); 95 | _dos_setvect(9, _my_keyint); 96 | return _my_keyint == _dos_getvect(9) ? 0 : -1; 97 | } 98 | 99 | static void _kb_remove(int final) { 100 | if (_oldkeyint) 101 | _dos_setvect(9, _oldkeyint); 102 | } 103 | 104 | #endif /* __WATCOMC__ */ 105 | 106 | /*********************************************************************** 107 | // 108 | ************************************************************************/ 109 | 110 | #if defined(__EMX__) 111 | 112 | static int _kb_install(void) { 113 | if (_osmode != DOS_MODE) 114 | return -1; 115 | 116 | /* sorry, no interrupt handler possible with emx */ 117 | return -1; 118 | } 119 | 120 | static void _kb_remove(int dummy) { 121 | } 122 | 123 | #endif /* __EMX__ */ 124 | 125 | /*********************************************************************** 126 | // djgpp 127 | // 128 | // note: Under DPMI the interrupt is always passed to the 129 | // protected-mode handler first. But there have been reports about 130 | // some strange situations under which a (faulty ?) DPMI host 131 | // issued a real-mode interrupt. So we are paranoid and install 132 | // a real-mode handler under DPMI as well. It shouldn't get called 133 | // anyway, but it's there just in case. 134 | // You can comment out the 135 | // _go32_dpmi_set_protected_mode_interrupt_vector() call 136 | // to verify that the real-mode handler is working fine. 137 | // 138 | // The real-mode handler is needed for djgpp v1. Really. 139 | ************************************************************************/ 140 | 141 | #if defined(__GO32__) 142 | 143 | static unsigned long rm_count = 0; 144 | 145 | static void _my_rm_keyint(_go32_dpmi_registers * regs) { 146 | rm_count++; 147 | _my_keyint(regs); 148 | } 149 | 150 | /* See example code in djgpp2/info/libc.inf */ 151 | 152 | static _go32_dpmi_seginfo _key_pm_oldint; /* original prot-mode key IRQ */ 153 | static _go32_dpmi_seginfo _key_pm_int; /* prot-mode interrupt segment info */ 154 | static _go32_dpmi_seginfo _key_rm_oldint; /* original real mode key IRQ */ 155 | static _go32_dpmi_seginfo _key_rm_int; /* real mode interrupt segment info */ 156 | static _go32_dpmi_registers _key_rm_regs; 157 | 158 | static int _kb_install(void) { 159 | #if 0 160 | const int ino = 8 + 1; 161 | #else 162 | const int ino = _go32_info_block.master_interrupt_controller_base + 1; 163 | #endif 164 | 165 | #if !defined(__DJGPP__) 166 | _kb_flags &= ~KB_FLAG_DJGPP_NO_RM; 167 | #endif 168 | 169 | memset(&_key_pm_oldint, 0, sizeof(_key_pm_oldint)); 170 | memset(&_key_pm_int, 0, sizeof(_key_pm_int)); 171 | memset(&_key_rm_oldint, 0, sizeof(_key_rm_oldint)); 172 | memset(&_key_rm_int, 0, sizeof(_key_rm_int)); 173 | memset(&_key_rm_regs, 0, sizeof(_key_rm_regs)); 174 | 175 | /* get and allocate pm handler */ 176 | _go32_dpmi_get_protected_mode_interrupt_vector(ino, &_key_pm_oldint); 177 | _key_pm_int.pm_selector = _go32_my_cs(); 178 | _key_pm_int.pm_offset = (unsigned long)_my_keyint; 179 | if (_go32_dpmi_allocate_iret_wrapper(&_key_pm_int) != 0) 180 | goto error; 181 | 182 | /* get and allocate rm handler */ 183 | if (!(_kb_flags & KB_FLAG_DJGPP_NO_RM)) { 184 | _go32_dpmi_get_real_mode_interrupt_vector(ino, &_key_rm_oldint); 185 | _key_rm_int.pm_selector = _go32_my_cs(); 186 | _key_rm_int.pm_offset = (unsigned long)_my_rm_keyint; 187 | if (_go32_dpmi_allocate_real_mode_callback_iret(&_key_rm_int, &_key_rm_regs) != 0) 188 | goto error; 189 | } 190 | 191 | /* set pm handler */ 192 | if (_go32_dpmi_set_protected_mode_interrupt_vector(ino, &_key_pm_int) != 0) 193 | goto error; 194 | 195 | /* set rm handler */ 196 | if (!(_kb_flags & KB_FLAG_DJGPP_NO_RM)) 197 | _go32_dpmi_set_real_mode_interrupt_vector(ino, &_key_rm_int); 198 | 199 | return 0; 200 | 201 | error: 202 | memset(&_key_pm_oldint, 0, sizeof(_key_pm_oldint)); 203 | memset(&_key_pm_int, 0, sizeof(_key_pm_int)); 204 | memset(&_key_rm_oldint, 0, sizeof(_key_rm_oldint)); 205 | memset(&_key_rm_int, 0, sizeof(_key_rm_int)); 206 | memset(&_key_rm_regs, 0, sizeof(_key_rm_regs)); 207 | 208 | return -1; 209 | } 210 | 211 | static void _kb_remove(int final) { 212 | #if 0 213 | const int ino = 8 + 1; 214 | #else 215 | const int ino = _go32_info_block.master_interrupt_controller_base + 1; 216 | #endif 217 | int r = 0; 218 | 219 | if (_key_pm_oldint.pm_selector != 0 || _key_pm_oldint.pm_offset != 0) 220 | r |= _go32_dpmi_set_protected_mode_interrupt_vector(ino, &_key_pm_oldint); 221 | if (_key_rm_oldint.rm_segment != 0 || _key_rm_oldint.rm_offset != 0) 222 | r |= _go32_dpmi_set_real_mode_interrupt_vector(ino, &_key_rm_oldint); 223 | 224 | if (final && r == 0) { 225 | if (_key_pm_int.pm_selector != 0 || _key_pm_int.pm_offset != 0) 226 | _go32_dpmi_free_iret_wrapper(&_key_pm_int); 227 | if (_key_rm_int.size) 228 | _go32_dpmi_free_real_mode_callback(&_key_rm_int); 229 | 230 | #if defined(KB_DEBUG) && (KB_DEBUG >= 2) 231 | if (rm_count) 232 | fprintf(stderr, "_kb_remove: info: %lu real-mode interrupts\n", rm_count); 233 | #endif 234 | 235 | memset(&_key_pm_oldint, 0, sizeof(_key_pm_oldint)); 236 | memset(&_key_pm_int, 0, sizeof(_key_pm_int)); 237 | memset(&_key_rm_oldint, 0, sizeof(_key_rm_oldint)); 238 | memset(&_key_rm_int, 0, sizeof(_key_rm_int)); 239 | } 240 | } 241 | 242 | #endif /* __GO32__ */ 243 | 244 | /* 245 | vi:ts=4 246 | */ 247 | -------------------------------------------------------------------------------- /src/libkb/_kbname.hh: -------------------------------------------------------------------------------- 1 | /* _kbname.hh -- key names 2 | * Copyright (C) 1995-1998 Markus F.X.J. Oberhumer 3 | * For conditions of distribution and use, see copyright notice in kb.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the keyboard library and is 8 | subject to change. Applications should only use kb.h. 9 | */ 10 | 11 | /* DO NOT EDIT - this file is automatically generated by mkkbname.pl */ 12 | 13 | static const char *const _kb_key_name[128] = { 14 | "", /* 0 0x00 */ 15 | "ESC", /* 1 0x01 */ 16 | "1", /* 2 0x02 */ 17 | "2", /* 3 0x03 */ 18 | "3", /* 4 0x04 */ 19 | "4", /* 5 0x05 */ 20 | "5", /* 6 0x06 */ 21 | "6", /* 7 0x07 */ 22 | "7", /* 8 0x08 */ 23 | "8", /* 9 0x09 */ 24 | "9", /* 10 0x0a */ 25 | "0", /* 11 0x0b */ 26 | "MINUS", /* 12 0x0c */ 27 | "EQUAL", /* 13 0x0d */ 28 | "BACKSPACE", /* 14 0x0e */ 29 | "TAB", /* 15 0x0f */ 30 | "Q", /* 16 0x10 */ 31 | "W", /* 17 0x11 */ 32 | "E", /* 18 0x12 */ 33 | "R", /* 19 0x13 */ 34 | "T", /* 20 0x14 */ 35 | "Y", /* 21 0x15 */ 36 | "U", /* 22 0x16 */ 37 | "I", /* 23 0x17 */ 38 | "O", /* 24 0x18 */ 39 | "P", /* 25 0x19 */ 40 | "OPENBRACE", /* 26 0x1a */ 41 | "CLOSEBRACE", /* 27 0x1b */ 42 | "ENTER", /* 28 0x1c */ 43 | "LCONTROL", /* 29 0x1d */ 44 | "A", /* 30 0x1e */ 45 | "S", /* 31 0x1f */ 46 | "D", /* 32 0x20 */ 47 | "F", /* 33 0x21 */ 48 | "G", /* 34 0x22 */ 49 | "H", /* 35 0x23 */ 50 | "J", /* 36 0x24 */ 51 | "K", /* 37 0x25 */ 52 | "L", /* 38 0x26 */ 53 | "COLON", /* 39 0x27 */ 54 | "QUOTE", /* 40 0x28 */ 55 | "BACKQUOTE", /* 41 0x29 */ 56 | "LSHIFT", /* 42 0x2a */ 57 | "BACKSLASH", /* 43 0x2b */ 58 | "Z", /* 44 0x2c */ 59 | "X", /* 45 0x2d */ 60 | "C", /* 46 0x2e */ 61 | "V", /* 47 0x2f */ 62 | "B", /* 48 0x30 */ 63 | "N", /* 49 0x31 */ 64 | "M", /* 50 0x32 */ 65 | "COMMA", /* 51 0x33 */ 66 | "PERIOD", /* 52 0x34 */ 67 | "SLASH", /* 53 0x35 */ 68 | "RSHIFT", /* 54 0x36 */ 69 | "MULTIPLY PAD", /* 55 0x37 */ 70 | "ALT", /* 56 0x38 */ 71 | "SPACE", /* 57 0x39 */ 72 | "CAPSLOCK", /* 58 0x3a */ 73 | "F1", /* 59 0x3b */ 74 | "F2", /* 60 0x3c */ 75 | "F3", /* 61 0x3d */ 76 | "F4", /* 62 0x3e */ 77 | "F5", /* 63 0x3f */ 78 | "F6", /* 64 0x40 */ 79 | "F7", /* 65 0x41 */ 80 | "F8", /* 66 0x42 */ 81 | "F9", /* 67 0x43 */ 82 | "F10", /* 68 0x44 */ 83 | "NUMLOCK", /* 69 0x45 */ 84 | "SCRLOCK", /* 70 0x46 */ 85 | "7 PAD", /* 71 0x47 */ 86 | "8 PAD", /* 72 0x48 */ 87 | "9 PAD", /* 73 0x49 */ 88 | "MINUS PAD", /* 74 0x4a */ 89 | "4 PAD", /* 75 0x4b */ 90 | "5 PAD", /* 76 0x4c */ 91 | "6 PAD", /* 77 0x4d */ 92 | "PLUS PAD", /* 78 0x4e */ 93 | "1 PAD", /* 79 0x4f */ 94 | "2 PAD", /* 80 0x50 */ 95 | "3 PAD", /* 81 0x51 */ 96 | "0 PAD", /* 82 0x52 */ 97 | "PERIOD PAD", /* 83 0x53 */ 98 | "SYS REQ", /* 84 0x54 */ 99 | "", /* 85 0x55 */ 100 | "LESS", /* 86 0x56 */ 101 | "F11", /* 87 0x57 */ 102 | "F12", /* 88 0x58 */ 103 | "", /* 89 0x59 */ 104 | "", /* 90 0x5a */ 105 | "", /* 91 0x5b */ 106 | "", /* 92 0x5c */ 107 | "", /* 93 0x5d */ 108 | "", /* 94 0x5e */ 109 | "", /* 95 0x5f */ 110 | "ENTER PAD", /* 96 0x60 */ 111 | "RCONTROL", /* 97 0x61 */ 112 | "DIVIDE PAD", /* 98 0x62 */ 113 | "PRINT", /* 99 0x63 */ 114 | "ALTGR", /* 100 0x64 */ 115 | "", /* 101 0x65 */ 116 | "HOME", /* 102 0x66 */ 117 | "UP", /* 103 0x67 */ 118 | "PGUP", /* 104 0x68 */ 119 | "LEFT", /* 105 0x69 */ 120 | "RIGHT", /* 106 0x6a */ 121 | "END", /* 107 0x6b */ 122 | "DOWN", /* 108 0x6c */ 123 | "PGDN", /* 109 0x6d */ 124 | "INSERT", /* 110 0x6e */ 125 | "DELETE", /* 111 0x6f */ 126 | "", /* 112 0x70 */ 127 | "", /* 113 0x71 */ 128 | "", /* 114 0x72 */ 129 | "", /* 115 0x73 */ 130 | "", /* 116 0x74 */ 131 | "", /* 117 0x75 */ 132 | "", /* 118 0x76 */ 133 | "", /* 119 0x77 */ 134 | "", /* 120 0x78 */ 135 | "", /* 121 0x79 */ 136 | "", /* 122 0x7a */ 137 | "", /* 123 0x7b */ 138 | "", /* 124 0x7c */ 139 | "LBANNER", /* 125 0x7d */ 140 | "RBANNER", /* 126 0x7e */ 141 | "RMENU", /* 127 0x7f */ 142 | }; 143 | 144 | /* 145 | vi:ts=4 146 | */ 147 | -------------------------------------------------------------------------------- /src/libkb/_kbtable.hh: -------------------------------------------------------------------------------- 1 | /* _kbtable.hh -- key tables 2 | * Copyright (C) 1995-1998 Markus F.X.J. Oberhumer 3 | * For conditions of distribution and use, see copyright notice in kb.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the keyboard library and is 8 | subject to change. Applications should only use kb.h. 9 | */ 10 | 11 | /* DO NOT EDIT - this file is automatically generated */ 12 | 13 | const unsigned char _kb_prefix_scancode[128] = { 14 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 15 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 16 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 17 | 0x00, 0x00, 0x00, 0x00, 0x60, 0x61, 0x00, 0x00, 18 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 19 | 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 20 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x78, 0x63, 21 | 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 22 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x65, 0x66, 23 | 0x67, 0x68, 0x00, 0x69, 0x00, 0x6a, 0x00, 0x6b, 24 | 0x6c, 0x6d, 0x6e, 0x6f, 0x00, 0x00, 0x00, 0x00, 25 | 0x00, 0x00, 0x00, 0x7d, 0x7e, 0x7f, 0x00, 0x00, 26 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 27 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 28 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 29 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 30 | }; 31 | 32 | const unsigned short _kb_shift_state_table[128] = { 33 | 0x6000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 34 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 35 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 36 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4004, 0x0000, 0x0000, 37 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 38 | 0x0000, 0x0000, 0x4001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 39 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4002, 0x0000, 40 | 0x4010, 0x0000, 0x4040, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 41 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4080, 0x4100, 0x0000, 42 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 43 | 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x6000, 0x0000, 0x0000, 44 | 0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 45 | 0x0000, 0x4008, 0x0000, 0x0000, 0x4020, 0xc800, 0x0000, 0x0000, 46 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0000, 47 | 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0xc400, 48 | 0xc000, 0x6000, 0x6000, 0x6000, 0x6000, 0x4000, 0x4000, 0x4000 49 | }; 50 | 51 | static const unsigned short default_plain_table[128] = { 52 | 0x0000, 0x001b, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 53 | 0x0037, 0x0038, 0x0039, 0x0030, 0x002d, 0x003d, 0x0008, 0x0009, 54 | 0x0071, 0x0077, 0x0065, 0x0072, 0x0074, 0x0079, 0x0075, 0x0069, 55 | 0x006f, 0x0070, 0x005b, 0x005d, 0x000d, 0x0000, 0x0061, 0x0073, 56 | 0x0064, 0x0066, 0x0067, 0x0068, 0x006a, 0x006b, 0x006c, 0x003b, 57 | 0x0027, 0x0060, 0x0000, 0x005c, 0x007a, 0x0078, 0x0063, 0x0076, 58 | 0x0062, 0x006e, 0x006d, 0x002c, 0x002e, 0x002f, 0x0000, 0x002a, 59 | 0x0000, 0x0020, 0x0000, 0x013b, 0x013c, 0x013d, 0x013e, 0x013f, 60 | 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0000, 0x0000, 0x0037, 61 | 0x0038, 0x0039, 0x002d, 0x0034, 0x0035, 0x0036, 0x002b, 0x0031, 62 | 0x0032, 0x0033, 0x0030, 0x002e, 0x0000, 0x0000, 0x005c, 0x0185, 63 | 0x0186, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 64 | 0x000d, 0x0000, 0x002f, 0x0000, 0x0000, 0x0000, 0x0247, 0x0248, 65 | 0x0249, 0x024b, 0x024d, 0x024f, 0x0250, 0x0251, 0x0252, 0x0253, 66 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 67 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 68 | }; 69 | 70 | static const unsigned short default_shift_table[128] = { 71 | 0x0000, 0x001b, 0x0021, 0x0040, 0x0023, 0x0024, 0x0025, 0x005e, 72 | 0x0026, 0x002a, 0x0028, 0x0029, 0x005f, 0x002b, 0x0008, 0x010f, 73 | 0x0051, 0x0057, 0x0045, 0x0052, 0x0054, 0x0059, 0x0055, 0x0049, 74 | 0x004f, 0x0050, 0x007b, 0x007d, 0x000d, 0x0000, 0x0041, 0x0053, 75 | 0x0044, 0x0046, 0x0047, 0x0048, 0x004a, 0x004b, 0x004c, 0x003a, 76 | 0x0022, 0x007e, 0x0000, 0x007c, 0x005a, 0x0058, 0x0043, 0x0056, 77 | 0x0042, 0x004e, 0x004d, 0x003c, 0x003e, 0x003f, 0x0000, 0x002a, 78 | 0x0000, 0x0020, 0x0000, 0x0154, 0x0155, 0x0156, 0x0157, 0x0158, 79 | 0x0159, 0x015a, 0x015b, 0x015c, 0x015d, 0x0000, 0x0000, 0x0037, 80 | 0x0038, 0x0039, 0x002d, 0x0034, 0x0035, 0x0036, 0x002b, 0x0031, 81 | 0x0032, 0x0033, 0x0030, 0x002e, 0x0000, 0x0000, 0x007c, 0x0187, 82 | 0x0188, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 83 | 0x000d, 0x0000, 0x002f, 0x0000, 0x0000, 0x0000, 0x0247, 0x0248, 84 | 0x0249, 0x024b, 0x024d, 0x024f, 0x0250, 0x0251, 0x0252, 0x0253, 85 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 86 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 87 | }; 88 | 89 | static const unsigned short default_control_table[128] = { 90 | 0x0000, 0x001b, 0x0000, 0x0103, 0x0000, 0x0000, 0x0000, 0x001e, 91 | 0x0000, 0x0000, 0x0000, 0x0000, 0x001c, 0x0000, 0x007f, 0x0194, 92 | 0x0011, 0x0017, 0x0005, 0x0012, 0x0014, 0x0019, 0x0015, 0x0009, 93 | 0x000f, 0x0010, 0x001b, 0x001d, 0x000a, 0x0000, 0x0001, 0x0013, 94 | 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b, 0x000c, 0x0000, 95 | 0x0000, 0x0000, 0x0000, 0x0000, 0x001a, 0x0018, 0x0003, 0x0016, 96 | 0x0002, 0x000e, 0x000d, 0x0000, 0x0000, 0x001f, 0x0000, 0x0196, 97 | 0x0000, 0x0020, 0x0000, 0x015e, 0x015f, 0x0160, 0x0161, 0x0162, 98 | 0x0163, 0x0164, 0x0165, 0x0166, 0x0167, 0x0000, 0x0000, 0x0177, 99 | 0x018d, 0x0184, 0x018e, 0x0173, 0x018f, 0x0174, 0x0190, 0x0175, 100 | 0x0191, 0x0176, 0x0192, 0x0193, 0x0000, 0x0000, 0x0000, 0x0189, 101 | 0x018a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 102 | 0x000a, 0x0000, 0x0195, 0x0172, 0x0000, 0x0000, 0x0277, 0x028d, 103 | 0x0284, 0x0273, 0x0274, 0x0275, 0x0291, 0x0276, 0x0292, 0x0293, 104 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 105 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 106 | }; 107 | 108 | static const unsigned short default_alt_table[128] = { 109 | 0x0000, 0x0101, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d, 110 | 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x010e, 0x01a5, 111 | 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116, 0x0117, 112 | 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x0000, 0x011e, 0x011f, 113 | 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126, 0x0127, 114 | 0x0128, 0x0129, 0x0000, 0x012b, 0x012c, 0x012d, 0x012e, 0x012f, 115 | 0x0130, 0x0131, 0x0132, 0x0133, 0x0134, 0x0135, 0x0000, 0x0137, 116 | 0x0000, 0x0020, 0x0000, 0x0168, 0x0169, 0x016a, 0x016b, 0x016c, 117 | 0x016d, 0x016e, 0x016f, 0x0170, 0x0171, 0x0000, 0x0000, 0x0297, 118 | 0x0298, 0x0299, 0x014a, 0x029b, 0x029c, 0x029d, 0x014e, 0x029f, 119 | 0x02a0, 0x02a1, 0x02a2, 0x02a3, 0x0000, 0x0000, 0x0000, 0x018b, 120 | 0x018c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 121 | 0x01a6, 0x0000, 0x01a4, 0x0000, 0x0000, 0x0000, 0x0197, 0x0198, 122 | 0x0199, 0x019b, 0x019d, 0x019f, 0x01a0, 0x01a1, 0x01a2, 0x01a3, 123 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 124 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 125 | }; 126 | 127 | /* 128 | vi:ts=4 129 | */ 130 | -------------------------------------------------------------------------------- /src/libkb/kb.h: -------------------------------------------------------------------------------- 1 | /* kb.h -- interface of the 'libkb' keyboard library 2 | version 1.01, 03 Jun 1998. 3 | 4 | Copyright (C) 1995-1998 Markus Franz Xaver Johannes Oberhumer 5 | 6 | This software is provided 'as-is', without any express or implied 7 | warranty. In no event will the authors be held liable for any damages 8 | arising from the use of this software. 9 | 10 | Permission is granted to anyone to use this software for any purpose, 11 | including commercial applications, and to alter it and redistribute it 12 | freely, subject to the following restrictions: 13 | 14 | 1. The origin of this software must not be misrepresented; you must not 15 | claim that you wrote the original software. If you use this software 16 | in a product, an acknowledgment in the product documentation would be 17 | appreciated but is not required. 18 | 2. Altered source versions must be plainly marked as such, and must not be 19 | misrepresented as being the original software. 20 | 3. This notice may not be removed or altered from any source distribution. 21 | 22 | Markus F.X.J. Oberhumer 23 | 24 | http://wildsau.idv.uni-linz.ac.at/mfx/libkb.html 25 | */ 26 | 27 | #ifndef __LIBKB_KB_H 28 | #define __LIBKB_KB_H 29 | 30 | #define KB_LIBKB KB_VERSION_ID 31 | 32 | #define KB_VERSION_ID 0x1010 /* version + patchlevel */ 33 | #define KB_VERSION_STRING "1.01" 34 | #define KB_VERSION_DATE "03 Jun 1998" 35 | 36 | /* internal Autoconf configuration file - only used when building libkb */ 37 | #if defined(LIBKB_HAVE_CONFIG_H) 38 | #include 39 | #endif 40 | 41 | #if defined(MSDOS) || defined(__MSDOS__) || defined(__EMX__) || defined(__WATCOMC__) 42 | #define __KB_MSDOS 43 | #if defined(__32BIT__) || defined(__FLAT__) || defined(__GNUC__) || defined(__WATCOMC__) 44 | #define __KB_MSDOS32 45 | #else 46 | #define __KB_MSDOS16 47 | #endif 48 | #elif defined(__linux__) && defined(__GNUC__) 49 | #define __KB_LINUX 50 | #define __KB_UNIX 51 | #else 52 | #error unsupported compiler 53 | #endif 54 | 55 | #if defined(__KB_MSDOS) 56 | #include 57 | #endif 58 | 59 | #ifdef __cplusplus 60 | extern "C" { 61 | #endif 62 | 63 | /* utility macros for bits accessing */ 64 | #define KB_ALL_MASK(x,mask) (((x) & (mask)) == (mask)) 65 | #define KB_ANY_MASK(x,mask) (((x) & (mask)) != 0) 66 | #define KB_NO_MASK(x,mask) (((x) & (mask)) == 0) 67 | 68 | /*********************************************************************** 69 | // keyboard access 70 | ************************************************************************/ 71 | 72 | /* installation of keyboard handler */ 73 | int kb_install(unsigned long flags); /* install keyboard handler */ 74 | void kb_remove(void); /* remove keyboard handler */ 75 | #define kb_flags() ((unsigned long) _kb_flags) 76 | #define kb_mode() ((int) _kb_mode) 77 | 78 | /* update the keyboard - needed under Linux */ 79 | void kb_update(void); 80 | 81 | /* access all keys */ 82 | #define kb_key(scan) ((unsigned char) _kb_key[scan]) 83 | #define kb_keys_pressed() ((int) _kb_keys_pressed) 84 | #define kb_last_key() ((unsigned short) _kb_last_key) 85 | #define kb_shift() ((unsigned short) _kb_shift) 86 | 87 | #define kb_last_key_set(k) ((void) (_kb_last_key = (k))) 88 | #define kb_shift_off(s) ((void) (_kb_shift &= ~(s))) 89 | #define kb_shift_on(s) ((void) (_kb_shift |= (s))) 90 | 91 | /* read a single keypress */ 92 | unsigned kb_keypress(void); /* basic access function */ 93 | unsigned long kb_inkey(void); /* full info keypress */ 94 | unsigned kb_getkey(void); /* compatible to getkey() */ 95 | int kb_kbhit(void); /* compatible to kbhit() */ 96 | 97 | /* you are allowed to modify the following variables */ 98 | extern volatile unsigned short _kb_shift; /* current shift state */ 99 | extern volatile unsigned short _kb_last_key; /* last key pressed */ 100 | 101 | /* these are READ ONLY - use the access-macros above */ 102 | extern volatile unsigned char _kb_key[128]; /* the key flags */ 103 | extern volatile int _kb_keys_pressed; /* number of keys pressed */ 104 | extern unsigned long _kb_flags; /* flags after kb_install() */ 105 | extern int _kb_mode; /* do we have a keyboard handler? */ 106 | 107 | /*********************************************************************** 108 | // flags - kb_install() and kb_flags() 109 | // note: the only flag you probably need is emergency exit 110 | ************************************************************************/ 111 | 112 | /* pass these to kb_install() */ 113 | #define KB_FLAG_NO_ATEXIT 0x0001 /* do not use atexit() */ 114 | #define KB_FLAG_NO_SIGNAL 0x0002 /* do not install signal handler */ 115 | #define KB_FLAG_NO_LOCK 0x0004 /* do not lock memory */ 116 | #define KB_FLAG_SIGINT 0x0010 /* raise SIGINT on Control-C */ 117 | #define KB_FLAG_EMERGENCY_EXIT 0x0020 /* enable emergency exit */ 118 | #define KB_FLAG_EMERGENCY_SIGALRM 0x0040 /* enable SIGALRM emergency */ 119 | #define KB_FLAG_LINUX_NO_VT 0x0100 /* no virtual term switching */ 120 | #define KB_FLAG_LINUX_VT_NO_KEY 0x0200 /* release all keys after VT */ 121 | #define KB_FLAG_DJGPP_NO_RM 0x0400 /* no real-mode handler */ 122 | #define KB_FLAG_REPEAT_OFF 0x1000 /* turn off key repeat */ 123 | 124 | /* these information bits are set by kb_install() but do not cause an error */ 125 | #define KB_FLAG_ATEXIT_FAILED 0x00010000L /* error atexit() */ 126 | #define KB_FLAG_SIGNAL_FAILED 0x00020000L /* error installing signals */ 127 | #define KB_FLAG_LOCK_FAILED 0x00040000L /* error while locking memory */ 128 | 129 | /* these information bits are set by kb_install() */ 130 | #define KB_FLAG_ATEXIT_DONE 0x00100000L /* atexit() was called */ 131 | #define KB_FLAG_SIGNAL_DONE 0x00200000L /* signal handler installed */ 132 | #define KB_FLAG_LOCK_DONE 0x00400000L /* memory was locked */ 133 | 134 | /*********************************************************************** 135 | // keyboard scan codes - kb_key() 136 | // 1-88,96-111 are fairly standard and should probably not be changed 137 | ************************************************************************/ 138 | 139 | /* get the name of a key */ 140 | const char *kb_keyname(int scan); 141 | 142 | /* raw keys 1-88, 87 keys */ 143 | #define KB_SCAN_ESC 1 144 | #define KB_SCAN_1 2 145 | #define KB_SCAN_2 3 146 | #define KB_SCAN_3 4 147 | #define KB_SCAN_4 5 148 | #define KB_SCAN_5 6 149 | #define KB_SCAN_6 7 150 | #define KB_SCAN_7 8 151 | #define KB_SCAN_8 9 152 | #define KB_SCAN_9 10 153 | #define KB_SCAN_0 11 154 | #define KB_SCAN_MINUS 12 155 | #define KB_SCAN_EQUAL 13 156 | #define KB_SCAN_BACKSPACE 14 157 | #define KB_SCAN_TAB 15 158 | #define KB_SCAN_Q 16 159 | #define KB_SCAN_W 17 160 | #define KB_SCAN_E 18 161 | #define KB_SCAN_R 19 162 | #define KB_SCAN_T 20 163 | #define KB_SCAN_Y 21 164 | #define KB_SCAN_U 22 165 | #define KB_SCAN_I 23 166 | #define KB_SCAN_O 24 167 | #define KB_SCAN_P 25 168 | #define KB_SCAN_OPENBRACE 26 169 | #define KB_SCAN_CLOSEBRACE 27 170 | #define KB_SCAN_ENTER 28 171 | #define KB_SCAN_LCONTROL 29 /* Left Control */ 172 | #define KB_SCAN_A 30 173 | #define KB_SCAN_S 31 174 | #define KB_SCAN_D 32 175 | #define KB_SCAN_F 33 176 | #define KB_SCAN_G 34 177 | #define KB_SCAN_H 35 178 | #define KB_SCAN_J 36 179 | #define KB_SCAN_K 37 180 | #define KB_SCAN_L 38 181 | #define KB_SCAN_COLON 39 182 | #define KB_SCAN_QUOTE 40 183 | #define KB_SCAN_BACKQUOTE 41 184 | #define KB_SCAN_LSHIFT 42 /* Left Shift */ 185 | #define KB_SCAN_BACKSLASH 43 186 | #define KB_SCAN_Z 44 187 | #define KB_SCAN_X 45 188 | #define KB_SCAN_C 46 189 | #define KB_SCAN_V 47 190 | #define KB_SCAN_B 48 191 | #define KB_SCAN_N 49 192 | #define KB_SCAN_M 50 193 | #define KB_SCAN_COMMA 51 194 | #define KB_SCAN_PERIOD 52 195 | #define KB_SCAN_SLASH 53 196 | #define KB_SCAN_RSHIFT 54 /* Right Shift */ 197 | #define KB_SCAN_MULTIPLY_PAD 55 198 | #define KB_SCAN_ALT 56 /* Left Alt */ 199 | #define KB_SCAN_LALT KB_SCAN_ALT 200 | #define KB_SCAN_SPACE 57 201 | #define KB_SCAN_CAPSLOCK 58 202 | #define KB_SCAN_F1 59 203 | #define KB_SCAN_F2 60 204 | #define KB_SCAN_F3 61 205 | #define KB_SCAN_F4 62 206 | #define KB_SCAN_F5 63 207 | #define KB_SCAN_F6 64 208 | #define KB_SCAN_F7 65 209 | #define KB_SCAN_F8 66 210 | #define KB_SCAN_F9 67 211 | #define KB_SCAN_F10 68 212 | #define KB_SCAN_NUMLOCK 69 213 | #define KB_SCAN_SCRLOCK 70 214 | #define KB_SCAN_7_PAD 71 215 | #define KB_SCAN_8_PAD 72 216 | #define KB_SCAN_9_PAD 73 217 | #define KB_SCAN_MINUS_PAD 74 218 | #define KB_SCAN_4_PAD 75 219 | #define KB_SCAN_5_PAD 76 220 | #define KB_SCAN_6_PAD 77 221 | #define KB_SCAN_PLUS_PAD 78 222 | #define KB_SCAN_1_PAD 79 223 | #define KB_SCAN_2_PAD 80 224 | #define KB_SCAN_3_PAD 81 225 | #define KB_SCAN_0_PAD 82 226 | #define KB_SCAN_PERIOD_PAD 83 227 | #define KB_SCAN_SYS_REQ 84 /* Alt+Print */ 228 | #define KB_SCAN_ALT_PRINT KB_SCAN_SYS_REQ 229 | #define KB_SCAN_LAST_CONSOLE KB_SCAN_SYS_REQ 230 | /* 85 is not used */ 231 | #define KB_SCAN_LESS 86 /* '<' on my German keyboard */ 232 | #define KB_SCAN_F11 87 233 | #define KB_SCAN_F12 88 234 | 235 | /* prefixed keys mapped to unique scancodes, 5 keys */ 236 | #define KB_SCAN_ENTER_PAD 96 /* on keypad */ 237 | #define KB_SCAN_RCONTROL 97 /* Right Control */ 238 | #define KB_SCAN_DIVIDE_PAD 98 /* on keypad */ 239 | #define KB_SCAN_PRINT 99 240 | #define KB_SCAN_ALTGR 100 /* Alt Graphics = Right Alt */ 241 | #define KB_SCAN_RALT KB_SCAN_ALTGR 242 | /* 101 is used internally */ 243 | 244 | /* prefixed cursor keys mapped to unique scancodes, 10 keys */ 245 | #define KB_SCAN_HOME 102 /* KB_SCAN_7_PAD */ 246 | #define KB_SCAN_UP 103 /* KB_SCAN_8_PAD */ 247 | #define KB_SCAN_PGUP 104 /* KB_SCAN_9_PAD */ 248 | #define KB_SCAN_LEFT 105 /* KB_SCAN_4_PAD */ 249 | #define KB_SCAN_RIGHT 106 /* KB_SCAN_6_PAD */ 250 | #define KB_SCAN_END 107 /* KB_SCAN_1_PAD */ 251 | #define KB_SCAN_DOWN 108 /* KB_SCAN_2_PAD */ 252 | #define KB_SCAN_PGDN 109 /* KB_SCAN_3_PAD */ 253 | #define KB_SCAN_INSERT 110 /* KB_SCAN_0_PAD */ 254 | #define KB_SCAN_DELETE 111 /* KB_SCAN_PERIOD_PAD */ 255 | 256 | /* prefixed keys of new Windows95 keyboard, 3 keys */ 257 | #define KB_SCAN_LBANNER 125 /* left window button */ 258 | #define KB_SCAN_RBANNER 126 /* right window button */ 259 | #define KB_SCAN_RMENU 127 /* menu button */ 260 | 261 | /*********************************************************************** 262 | // keyboard shift states - kb_shift() 263 | ************************************************************************/ 264 | 265 | /* shift flags */ 266 | #define KB_SHIFT_LSHIFT 0x0001 267 | #define KB_SHIFT_RSHIFT 0x0002 268 | #define KB_SHIFT_LCONTROL 0x0004 269 | #define KB_SHIFT_RCONTROL 0x0008 270 | #define KB_SHIFT_ALT 0x0010 271 | #define KB_SHIFT_ALTGR 0x0020 272 | #define KB_SHIFT_LALT KB_SHIFT_ALT 273 | #define KB_SHIFT_RALT KB_SHIFT_ALTGR 274 | 275 | /* these are toggles - they only change when the key is pressed */ 276 | #define KB_SHIFT_CAPSLOCK 0x0040 277 | #define KB_SHIFT_NUMLOCK 0x0080 278 | #define KB_SHIFT_SCRLOCK 0x0100 279 | #define KB_SHIFT_INSERT 0x0200 280 | #define KB_SHIFT_PAUSE 0x0400 /* this key has no scan code */ 281 | #define KB_SHIFT_CONTROL_BREAK 0x0800 /* this key has no scan code */ 282 | 283 | /* flags for masking multiple shift keys */ 284 | #define KB_SHIFT_ANY 0x0fff 285 | #define KB_SHIFT_ANY_SHIFT (KB_SHIFT_LSHIFT | KB_SHIFT_RSHIFT) 286 | #define KB_SHIFT_ANY_CONTROL (KB_SHIFT_LCONTROL | KB_SHIFT_RCONTROL) 287 | #define KB_SHIFT_ANY_ALT (KB_SHIFT_ALT | KB_SHIFT_ALTGR) 288 | 289 | /* internal information, not very useful */ 290 | #define KB_SHIFT_OVERFLOW 0x1000 /* overflow occurred */ 291 | #define KB_SHIFT_UNKNOWN 0x2000 /* an unknown key was pressed */ 292 | 293 | /*********************************************************************** 294 | // advanced features: signals, keycodes and misc 295 | ************************************************************************/ 296 | 297 | typedef void (*kb_sighandler_t) (int); /* signal handler function type */ 298 | 299 | extern const kb_sighandler_t kb_signal_handler; /* libkb signal handler */ 300 | 301 | /* use this to install the libkb handler for additional signals */ 302 | kb_sighandler_t kb_signal(int signum, kb_sighandler_t handler); 303 | 304 | /* look at source code for more information */ 305 | kb_sighandler_t kb_get_chained_signal(int signum); 306 | kb_sighandler_t kb_set_chained_signal(int signum, kb_sighandler_t handler); 307 | extern const int _kb_nsig, _kb_sigmin, _kb_sigmax; 308 | 309 | /* when using KB_FLAG_EMERGENCY_SIGALRM */ 310 | int _kb_signal_alarm_pause(void); 311 | int _kb_signal_alarm_resume(void); 312 | 313 | /* callback function that can be called from within keyboard handler */ 314 | typedef void (*kb_handler_callback_t) (int); 315 | extern kb_handler_callback_t kb_handler_callback; 316 | extern kb_handler_callback_t kb_handler_mediumraw_callback; 317 | 318 | /* keycode conversion */ 319 | unsigned kb_keycode(unsigned k); 320 | unsigned kb_os_keycode(unsigned k1, unsigned k2); 321 | unsigned kb_bios_keycode(unsigned k); 322 | 323 | /* single keypress access */ 324 | unsigned kb_keypeek(void); /* peek for a keypress */ 325 | unsigned kb_waitkey(void); /* wait for a keypress */ 326 | void kb_clearkeys(void); /* clear keypress buffer */ 327 | 328 | /* single keypress access without interrupt disabling */ 329 | unsigned kb_keypress_i(void); 330 | unsigned long kb_inkey_i(void); 331 | unsigned kb_getkey_i(void); 332 | int kb_kbhit_i(void); 333 | unsigned kb_keypeek_i(void); 334 | unsigned kb_waitkey_i(void); 335 | void kb_clearkeys_i(void); 336 | 337 | /* set additional cleanup functions - look at source code */ 338 | void kb_set_cleanup(void (*before) (void), void (*after) (void)); 339 | void kb_set_emergency_cleanup(void (*before) (void), void (*after) (void)); 340 | 341 | /* misc. utility */ 342 | int kb_init(void); /* init keycode tables and internal vars */ 343 | int _kb_iswin(void); /* check if we are running in a Windows DOS box */ 344 | void _kb_usleep(unsigned long usec); /* sleep for a very short time */ 345 | 346 | /* debugging */ 347 | void _kb_port_debug(void); 348 | 349 | /*********************************************************************** 350 | // Portability wrappers for standard system functions. 351 | // Operating system and (if applicable) BIOS keyboard access 352 | // 353 | // Don't get confused, these have absolutely nothing to do with the 354 | // keyboard handler and are only here for your convenience. 355 | ************************************************************************/ 356 | 357 | int kb_os_kbhit(void); 358 | unsigned kb_os_getkey(void); 359 | unsigned kb_os_waitkey(void); /* wait for a keypress */ 360 | 361 | int kb_bios_kbhit(void); 362 | unsigned kb_bios_getkey(void); 363 | 364 | /* a compatible kbhit()/getch() implementation for emx+gcc */ 365 | #if defined(__EMX__) 366 | #undef kbhit 367 | #undef getch 368 | int kbhit(void); 369 | int getch(void); 370 | #endif 371 | 372 | #ifdef __cplusplus 373 | } /* extern "C" */ 374 | #endif 375 | #endif /* already included */ 376 | /* 377 | vi:ts=4 378 | */ 379 | -------------------------------------------------------------------------------- /src/libkb/kbhandle.c: -------------------------------------------------------------------------------- 1 | /* kbhandle.c -- MSDOS keyboard interrupt handler / Linux keyboard handler 2 | * Copyright (C) 1995-1998 Markus F.X.J. Oberhumer 3 | * For conditions of distribution and use, see copyright notice in kb.h 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include "_kb.h" 14 | 15 | #if defined(KB_LOCK_ALL_START) 16 | KB_LOCK_ALL_START(_libkb_kbhandle) 17 | #endif 18 | #if defined(__KB_MSDOS) 19 | #define KB_ACKINT() KB_OUTP8(0x20, 0x20) /* ack. interrupt */ 20 | #else 21 | #define KB_ACKINT() /* no interrupt */ 22 | #endif 23 | /*********************************************************************** 24 | // globals 25 | ************************************************************************/ 26 | volatile unsigned char _kb_key[128]; /* the key flags */ 27 | volatile unsigned short _kb_shift = 0; /* shift state */ 28 | volatile int _kb_keys_pressed = 0; /* number of keys pressed */ 29 | volatile unsigned short _kb_last_key = 0; /* last key pressed */ 30 | 31 | int _kb_mode = 0; /* do we have a keyboard handler? */ 32 | unsigned long _kb_flags = 0; /* flags from kb_install() */ 33 | 34 | kb_handler_callback_t kb_handler_callback = NULL; 35 | kb_handler_callback_t kb_handler_mediumraw_callback = NULL; 36 | 37 | /*********************************************************************** 38 | // static variables 39 | // These are not volatile because all access outside the 40 | // interrupt handler uses KB_DISABLE(). 41 | ************************************************************************/ 42 | 43 | static unsigned char _t_prefix = 0; 44 | static char _emergency_done = 0; /* don't recurse here */ 45 | 46 | #define KEY_BUFFER_SIZE 256 /* store up to 256 keys for kb_keypress() */ 47 | 48 | static unsigned char _key_buffer[2 * KEY_BUFFER_SIZE]; 49 | #define _key_buffer_start (&_key_buffer[0]) 50 | #define _key_buffer_end (&_key_buffer[HIGH(_key_buffer)]) 51 | 52 | static unsigned char *_key_buffer_head = _key_buffer_start; 53 | static unsigned char *_key_buffer_tail = _key_buffer_start; 54 | 55 | /* debugging and error reporting */ 56 | 57 | #if defined(KB_DEBUG) 58 | static unsigned char _kb_port_buffer[128]; 59 | #define _kb_port_buffer_start (&_kb_port_buffer[0]) 60 | #define _kb_port_buffer_end (&_kb_port_buffer[sizeof(_kb_port_buffer)]) 61 | static unsigned char *_kb_port_buffer_head = _kb_port_buffer_start; 62 | #endif 63 | 64 | /* I've just (07 Jan 1996) taken a look at the Linux kernel source 65 | * and come to the conclusion that reporting all unknown scan-codes 66 | * as a bug is probably counterproductive. 67 | * It seems that there exist lots of keyboards that produce lots 68 | * of codes we are simply not interested in. 69 | * I have removed all error reporting, the port values give us 70 | * enough information if we want to add something new. 71 | */ 72 | 73 | /*********************************************************************** 74 | // reset all vars except _kb_flags 75 | ************************************************************************/ 76 | 77 | static void _kb_clear(void) { 78 | KB_DISABLE(); 79 | memset((void *)_kb_key, 0, sizeof(_kb_key)); /* cast away volatile */ 80 | _kb_shift = 0; 81 | _kb_keys_pressed = 0; 82 | _kb_last_key = 0; 83 | kb_handler_callback = NULL; 84 | kb_handler_mediumraw_callback = NULL; 85 | 86 | _t_prefix = 0; 87 | 88 | _key_buffer_head = _key_buffer_tail = _key_buffer_start; 89 | KB_ENABLE(); 90 | } 91 | 92 | /*********************************************************************** 93 | // 94 | ************************************************************************/ 95 | 96 | int kb_kbhit() { 97 | int c; 98 | 99 | if (!_kb_mode) 100 | return kb_os_kbhit(); 101 | 102 | kb_update(); 103 | KB_DISABLE(); 104 | c = (_key_buffer_head != _key_buffer_tail); 105 | KB_ENABLE(); 106 | 107 | return c; 108 | } 109 | 110 | int kb_kbhit_i() { 111 | if (!_kb_mode) 112 | return kb_os_kbhit(); 113 | kb_update(); 114 | return (_key_buffer_head != _key_buffer_tail); 115 | } 116 | 117 | void kb_clearkeys(void) { 118 | kb_update(); 119 | KB_DISABLE(); 120 | _key_buffer_tail = _key_buffer_head; 121 | KB_ENABLE(); 122 | } 123 | 124 | void kb_clearkeys_i(void) { 125 | kb_update(); 126 | _key_buffer_tail = _key_buffer_head; 127 | } 128 | 129 | /*********************************************************************** 130 | // basic keypress access. 131 | // this function returns all relevant information: 132 | // the scancode and the low bits of the shift status 133 | // kb_getkey() and kb_inkey() sit on top of this function. 134 | ************************************************************************/ 135 | 136 | unsigned kb_keypress(void) { 137 | unsigned char scan, shift; 138 | unsigned k; 139 | 140 | if (!_kb_mode) 141 | return 0; 142 | 143 | kb_update(); 144 | 145 | KB_DISABLE(); 146 | if (_key_buffer_head == _key_buffer_tail) { 147 | KB_ENABLE(); 148 | return 0; 149 | } 150 | 151 | scan = *_key_buffer_tail++; /* get scan code */ 152 | shift = *_key_buffer_tail++; /* get shift code */ 153 | if (_key_buffer_tail >= _key_buffer_end) 154 | _key_buffer_tail = _key_buffer_start; 155 | KB_ENABLE(); 156 | 157 | k = scan | ((unsigned)shift << 8); 158 | return k; 159 | } 160 | 161 | unsigned kb_keypress_i(void) { 162 | unsigned char scan, shift; 163 | unsigned k; 164 | 165 | if (!_kb_mode) 166 | return 0; 167 | 168 | kb_update(); 169 | 170 | if (_key_buffer_head == _key_buffer_tail) 171 | return 0; 172 | scan = *_key_buffer_tail++; /* get scan code */ 173 | shift = *_key_buffer_tail++; /* get shift code */ 174 | if (_key_buffer_tail >= _key_buffer_end) 175 | _key_buffer_tail = _key_buffer_start; 176 | 177 | k = scan | ((unsigned)shift << 8); 178 | return k; 179 | } 180 | 181 | unsigned kb_keypeek(void) { 182 | unsigned char scan, shift; 183 | unsigned k; 184 | 185 | if (!_kb_mode) 186 | return 0; 187 | 188 | kb_update(); 189 | 190 | KB_DISABLE(); 191 | if (_key_buffer_head == _key_buffer_tail) { 192 | KB_ENABLE(); 193 | return 0; 194 | } 195 | 196 | scan = *_key_buffer_tail; /* get scan code */ 197 | shift = *(_key_buffer_tail + 1); /* get shift code */ 198 | KB_ENABLE(); 199 | 200 | k = scan | ((unsigned)shift << 8); 201 | return k; 202 | } 203 | 204 | unsigned kb_keypeek_i(void) { 205 | unsigned char scan, shift; 206 | unsigned k; 207 | 208 | if (!_kb_mode) 209 | return 0; 210 | 211 | kb_update(); 212 | 213 | if (_key_buffer_head == _key_buffer_tail) 214 | return 0; 215 | scan = *_key_buffer_tail; /* get scan code */ 216 | shift = *(_key_buffer_tail + 1); /* get shift code */ 217 | 218 | k = scan | ((unsigned)shift << 8); 219 | return k; 220 | } 221 | 222 | /*********************************************************************** 223 | // low level stuff 224 | ************************************************************************/ 225 | 226 | #if defined(__KB_MSDOS) 227 | #include "_kbmsdos.h" 228 | #elif defined(__KB_LINUX) 229 | #include "_kblinux.h" 230 | #endif 231 | 232 | /*********************************************************************** 233 | // high level installation 234 | ************************************************************************/ 235 | 236 | int kb_init(void) { 237 | _kb_init_tables(); 238 | if (!_kb_mode) 239 | _kb_clear(); 240 | return 0; 241 | } 242 | 243 | int kb_install(unsigned long flags) { 244 | if (_kb_mode) 245 | return 0; 246 | 247 | _kb_flags = flags; 248 | _kb_flags &= 0xffff; 249 | #if defined(KB_DEBUG) 250 | fprintf(stderr, "kb_install 1: 0x%08lx\n", _kb_flags); 251 | #endif 252 | 253 | if (!(_kb_flags & KB_FLAG_NO_ATEXIT)) { 254 | static unsigned char atexit_done = 0; 255 | 256 | if (atexit_done) 257 | _kb_flags |= KB_FLAG_ATEXIT_DONE; 258 | else if (atexit(kb_remove) == 0) { 259 | _kb_flags |= KB_FLAG_ATEXIT_DONE; 260 | atexit_done = 1; 261 | } else 262 | _kb_flags |= KB_FLAG_ATEXIT_FAILED; 263 | } 264 | 265 | if (!(_kb_flags & KB_FLAG_NO_LOCK)) 266 | if (_kb_lock() == 0) 267 | _kb_flags |= KB_FLAG_LOCK_DONE; 268 | else 269 | _kb_flags |= KB_FLAG_LOCK_FAILED; 270 | 271 | /* link version information into executeable */ 272 | _kb_shift |= (kb_version_string[0] & kb_version_date[0] & kb_copyright[0]); 273 | kb_init(); 274 | KB_DISABLE(); 275 | if (_kb_install() == 0) 276 | _kb_mode = 1; 277 | KB_ENABLE(); 278 | 279 | #if !defined(_KB_NO_SIGNALS) 280 | /* install signals only if handler could be installed */ 281 | if (_kb_mode) 282 | if (!(_kb_flags & KB_FLAG_NO_SIGNAL)) 283 | if (_kb_signal_install() == 0) 284 | _kb_flags |= KB_FLAG_SIGNAL_DONE; 285 | else 286 | _kb_flags |= KB_FLAG_SIGNAL_FAILED; 287 | #endif 288 | 289 | #if !defined(_KB_NO_SIGNALS) && defined(SIGALRM) 290 | if (_kb_mode) 291 | if (_kb_flags & KB_FLAG_EMERGENCY_SIGALRM) 292 | if (_kb_signal_alarm_install() != 0) 293 | _kb_flags &= ~(KB_FLAG_EMERGENCY_SIGALRM); /* failed */ 294 | #else 295 | _kb_flags &= ~(KB_FLAG_EMERGENCY_SIGALRM); 296 | #endif 297 | 298 | #if defined(KB_DEBUG) 299 | fflush(stdout); 300 | fprintf(stderr, "kb_install 2: 0x%08lx, %s\n", _kb_flags, _kb_mode ? "ok" : "FAILED"); 301 | fflush(stderr); 302 | #endif 303 | 304 | return _kb_mode ? 0 : -1; 305 | } 306 | 307 | /*********************************************************************** 308 | // high level removal 309 | ************************************************************************/ 310 | 311 | typedef void (*kb_cleanup_t) (void); 312 | static kb_cleanup_t kb_cleanup_func1 = NULL, kb_cleanup_func2 = NULL; 313 | static kb_cleanup_t kb_emergency_cleanup_func1 = NULL, kb_emergency_cleanup_func2 = NULL; 314 | 315 | void kb_set_cleanup(void (*before) (void), void (*after) (void)) { 316 | kb_cleanup_func1 = before; 317 | kb_cleanup_func2 = after; 318 | } 319 | 320 | void kb_set_emergency_cleanup(void (*before) (void), void (*after) (void)) { 321 | kb_emergency_cleanup_func1 = before; 322 | kb_emergency_cleanup_func2 = after; 323 | } 324 | 325 | static __inline__ void kb_call_cleanup(kb_cleanup_t * k) { 326 | if (k != NULL && *k != NULL) { 327 | kb_cleanup_t c = *k; 328 | *k = NULL; 329 | (*c) (); /* <-- call the cleanup function */ 330 | } 331 | } 332 | 333 | void kb_remove(void) { 334 | if (!_kb_mode) 335 | return; 336 | 337 | if (_kb_flags & KB_FLAG_EMERGENCY_SIGALRM) 338 | _kb_signal_alarm_pause(); 339 | 340 | kb_call_cleanup(&kb_cleanup_func1); 341 | 342 | #if defined(KB_DEBUG) && (KB_DEBUG >= 2) 343 | fprintf(stderr, "kb_remove 1\n"); 344 | #endif 345 | 346 | if (_kb_mode) { 347 | KB_DISABLE(); 348 | _kb_mode = 0; 349 | _kb_remove(1); 350 | KB_ENABLE(); 351 | _kb_clear(); 352 | _kb_unlock(); 353 | #if defined(KB_DEBUG) && (KB_DEBUG >= 2) 354 | fprintf(stderr, "kb_remove 2: keyboard removed\n"); 355 | fflush(stderr); 356 | #endif 357 | } 358 | 359 | kb_call_cleanup(&kb_cleanup_func2); 360 | } 361 | 362 | /* Note: this is called within an interrupt during emergency exit 363 | * or from our signal handler. 364 | * If final is true, the call is assumed to conform to a 365 | * Last In First Out (LIFO) resource allocation policy. 366 | * If final is false, the remove routine will be called a second time. 367 | * There may be multiple non-final calls, we are really paranoid 368 | * about resetting the keyboard because other libraries might 369 | * restore the keyboard as well and ignore any LIFO strategies 370 | * like signal chaining. 371 | */ 372 | void _kb_emergency_remove(int final) { 373 | if (!_kb_mode) 374 | return; 375 | 376 | if (_kb_flags & KB_FLAG_EMERGENCY_SIGALRM) 377 | _kb_signal_alarm_pause(); 378 | 379 | if (!final) { 380 | /* we are in a dangerous situation and just want to make sure 381 | * the keyboard is useable. We're expecting another call, 382 | * the 'official' final remove, to happen soon afterwards. 383 | */ 384 | KB_DISABLE(); 385 | _kb_remove(final); 386 | KB_ENABLE(); 387 | #if defined(KB_DEBUG) && (KB_DEBUG >= 2) 388 | fprintf(stderr, "_kb_emergency_remove non FINAL: keyboard removed\n"); 389 | fflush(stderr); 390 | #endif 391 | return; 392 | } 393 | 394 | kb_call_cleanup(&kb_emergency_cleanup_func1); 395 | 396 | if (_kb_mode) { 397 | KB_DISABLE(); 398 | _kb_mode = 0; 399 | _kb_remove(final); 400 | KB_ENABLE(); 401 | #if defined(KB_DEBUG) && (KB_DEBUG >= 2) 402 | fprintf(stderr, "_kb_emergency_remove: keyboard removed\n"); 403 | fflush(stderr); 404 | #endif 405 | } 406 | 407 | kb_call_cleanup(&kb_emergency_cleanup_func2); 408 | } 409 | 410 | /*********************************************************************** 411 | // lock ANY addresses which may be seen by the keyboard interrupt 412 | ************************************************************************/ 413 | 414 | static int _kb_locked = 0; 415 | 416 | int _kb_lock(void) { 417 | int x = 0; 418 | 419 | if (_kb_locked) 420 | return 0; 421 | 422 | /* lock all modules */ 423 | x |= _libkb_kbhandle_lock(); 424 | x |= _libkb_kbmlock_lock(); 425 | x |= _libkb_kbos_lock(); 426 | x |= _libkb_kbsignal_lock(); 427 | x |= _libkb_kbtables_lock(); 428 | 429 | if (x == 0) 430 | _kb_locked = 1; 431 | return _kb_locked ? 0 : -1; 432 | } 433 | 434 | void _kb_unlock(void) { 435 | if (!_kb_locked) 436 | return; 437 | 438 | /* do nothing - memory will be unlocked by the OS or extender 439 | * when the program terminates. */ 440 | 441 | /* _kb_locked = 0; */ 442 | } 443 | 444 | /*********************************************************************** 445 | // debugging and error reporting 446 | ************************************************************************/ 447 | 448 | void _kb_port_debug(void) { 449 | #if defined(KB_DEBUG) 450 | unsigned char *p; 451 | /* we'd better go volatile here */ 452 | unsigned char **volatile bh = &_kb_port_buffer_head; 453 | 454 | if (!_kb_mode) 455 | return; 456 | 457 | for (p = _kb_port_buffer_start; p < *bh; p++) { 458 | unsigned c = *p; 459 | static unsigned prefix = 0; 460 | 461 | if (c >= 0xe0 && c <= 0xe1) 462 | prefix = c - (0xe0 - 1); 463 | else { 464 | if (prefix) { 465 | printf("%02x+", prefix + (0xe0 - 1)); 466 | prefix--; 467 | } 468 | 469 | if (c < 0xe0 && (c & 0x80)) 470 | printf("80+%02x ", c & 0x7f); 471 | else 472 | printf("%02x ", c); 473 | } 474 | } 475 | 476 | /* reset buffer pointer */ 477 | _kb_port_buffer_head = _kb_port_buffer_start; 478 | #endif 479 | } 480 | 481 | /*********************************************************************** 482 | // locking 483 | ************************************************************************/ 484 | 485 | #if defined(KB_LOCK_ALL_END) 486 | KB_LOCK_ALL_END(_libkb_kbhandle) 487 | #endif 488 | int _libkb_kbhandle_lock(void) { 489 | int x = 0; 490 | 491 | #if defined(KB_LOCK_ALL) 492 | KB_LOCK_ALL(_libkb_kbhandle, x); 493 | #endif 494 | 495 | return x; 496 | } 497 | 498 | /* 499 | vi:ts=4 500 | */ 501 | -------------------------------------------------------------------------------- /src/libkb/kbmlock.c: -------------------------------------------------------------------------------- 1 | /* kbmlock.c -- memory locking 2 | * Copyright (C) 1995-1998 Markus F.X.J. Oberhumer 3 | * For conditions of distribution and use, see copyright notice in kb.h 4 | */ 5 | 6 | /* memory locking is currently implemented for djgpp v2 and Watcom C32 */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "_kb.h" 14 | 15 | /* see also: DPMI specification 16 | * djgpp2/src/libc/go32/gopint.c 17 | * djgpp2/src/libc/dpmi/api/d0600.s 18 | */ 19 | 20 | #if defined(KB_LOCK_ALL_START) 21 | KB_LOCK_ALL_START(_libkb_kbmlock) 22 | #endif 23 | typedef struct { 24 | int selector; 25 | unsigned long address; 26 | long size; 27 | unsigned long linear_address; 28 | } kb_lockaddr_t; 29 | 30 | /*********************************************************************** 31 | // DPMI support for Watcom C32 (djgpp v2 compatible) 32 | ************************************************************************/ 33 | 34 | #if defined(__WATCOMC__) && defined(__KB_MSDOS32) 35 | 36 | typedef struct { 37 | unsigned long handle; /* 0, 2 */ 38 | unsigned long size; /* or count *//* 4, 6 */ 39 | unsigned long address; /* 8, 10 */ 40 | } __dpmi_meminfo; 41 | 42 | /* it looks like every base address is 0 under DOS/4GW and PMODE/W */ 43 | 44 | /* DPMI 0.9 AX=0006 */ 45 | static 46 | int __dpmi_get_segment_base_address(int _selector, unsigned long *_addr) { 47 | KB_INT86_REGS regs; 48 | _kb_int86_regs_init_ax(®s, 0x0006); 49 | 50 | regs.w.bx = (unsigned short)_selector; 51 | regs.w.flags = 0x01; /* be paranoid */ 52 | KB_INT86(0x31, ®s); 53 | if (regs.w.flags & 0x01) /* error if carry flag set */ 54 | return -1; 55 | *_addr = ((unsigned long)regs.w.cx << 16) | regs.w.dx; 56 | return 0; 57 | } 58 | 59 | static 60 | int watcom_c32_do_lock(__dpmi_meminfo * _info, unsigned short ax) { 61 | KB_INT86_REGS regs; 62 | _kb_int86_regs_init_ax(®s, ax); 63 | 64 | regs.w.bx = (unsigned short)(_info->address >> 16); 65 | regs.w.cx = (unsigned short)(_info->address); 66 | regs.w.si = (unsigned short)(_info->size >> 16); 67 | regs.w.di = (unsigned short)(_info->size); 68 | 69 | regs.w.flags = 0x01; /* be paranoid */ 70 | KB_INT86(0x31, ®s); 71 | return (regs.w.flags & 0x01 ? -1 : 0); /* error if carry flag set */ 72 | } 73 | 74 | /* DPMI 0.9 AX=0600 */ 75 | static 76 | int __dpmi_lock_linear_region(__dpmi_meminfo * _info) { 77 | return watcom_c32_do_lock(_info, 0x0600); 78 | } 79 | 80 | /* DPMI 0.9 AX=0601 */ 81 | static 82 | int __dpmi_unlock_linear_region(__dpmi_meminfo * _info) { 83 | return watcom_c32_do_lock(_info, 0x0601); 84 | } 85 | 86 | #endif /* __WATCOMC__ */ 87 | 88 | /*********************************************************************** 89 | // low level locking - djgpp v2, Watcom C32 90 | ************************************************************************/ 91 | 92 | #if defined(__KB_MSDOS32) 93 | #if defined(__DJGPP__) || defined(__WATCOMC__) 94 | 95 | #define KB_HAVE_LOCK 96 | 97 | static int _kb_lock_lockaddr(const kb_lockaddr_t * l, int do_lock) { 98 | int r; 99 | __dpmi_meminfo memregion; 100 | 101 | memregion.handle = 0; 102 | memregion.address = l->linear_address; 103 | memregion.size = l->size; 104 | 105 | if (l->size <= 0) 106 | r = -1; 107 | else if (do_lock) 108 | r = __dpmi_lock_linear_region(&memregion); 109 | else 110 | r = __dpmi_unlock_linear_region(&memregion); 111 | 112 | #if defined(KB_DEBUG) && (KB_DEBUG >= 3) 113 | fprintf(stderr, "libkb lockinfo: %-6s %04x:%08lx (0x%08lx), " 114 | "%6ld bytes: %d\n", do_lock ? "lock" : "unlock", 115 | l->selector, l->address, l->linear_address, l->size, r); 116 | #endif 117 | 118 | return r; 119 | } 120 | 121 | static 122 | int _kb_init_lockaddr(kb_lockaddr_t * l, int seg, unsigned long lockaddr, long locksize, int code) { 123 | int r; 124 | 125 | l->selector = seg; 126 | #if defined(__DJGPP__) 127 | if (l->selector == -1) 128 | l->selector = code ? _go32_my_cs() : _go32_my_ds(); 129 | #endif 130 | l->address = lockaddr; 131 | l->size = locksize; 132 | l->linear_address = 0; 133 | 134 | r = __dpmi_get_segment_base_address(l->selector, &l->linear_address); 135 | if (r == 0) 136 | l->linear_address += l->address; 137 | else 138 | l->linear_address = 0; 139 | 140 | #if defined(KB_DEBUG) && (KB_DEBUG >= 4) 141 | fprintf(stderr, "libkb lockinfo: %-6s %04x:%08lx (0x%08lx), " 142 | "%6ld bytes\n", "", l->selector, l->address, l->linear_address, l->size); 143 | #endif 144 | 145 | if (r != 0) 146 | l->size = -1; 147 | return l->size > 0 ? 0 : -1; 148 | } 149 | 150 | #if defined(__DJGPP__) 151 | #define KB_INIT_LOCKADDR(l,addr,size,code) \ 152 | _kb_init_lockaddr(l,-1,(unsigned long)(addr),size,code) 153 | #elif defined(__WATCOMC__) 154 | #define KB_INIT_LOCKADDR(l,addr,size,code) \ 155 | _kb_init_lockaddr(l,FP_SEG(addr),FP_OFF(addr),size,code) 156 | #endif 157 | 158 | #endif 159 | #endif /* __KB_MSDOS32 */ 160 | 161 | /*********************************************************************** 162 | // init a kb_lockaddr_t 163 | ************************************************************************/ 164 | 165 | static 166 | int _kb_init_lock_code(kb_lockaddr_t * l, void (*start) (void), void (*end) (void)) { 167 | l->size = -1; 168 | if (start == NULL || end == NULL || start == end) 169 | return -1; 170 | 171 | #if defined(KB_INIT_LOCKADDR) 172 | /* warning: ANSI C forbids ordered comparisons of pointers to functions */ 173 | { 174 | unsigned long s = (unsigned long)start; 175 | unsigned long e = (unsigned long)end; 176 | if (e > s) 177 | return KB_INIT_LOCKADDR(l, start, e - s, 1); 178 | else if (s > e) 179 | return KB_INIT_LOCKADDR(l, end, s - e, 1); 180 | else 181 | return -1; 182 | } 183 | #else 184 | l->size = 0; 185 | return 0; 186 | #endif 187 | } 188 | 189 | static 190 | int _kb_init_lock_data(kb_lockaddr_t * l, const void *start, const void *end) { 191 | l->size = -1; 192 | if (start == NULL || end == NULL || start == end) 193 | return -1; 194 | 195 | #if defined(KB_INIT_LOCKADDR) 196 | if (end > start) 197 | return KB_INIT_LOCKADDR(l, start, (const char *)end - (const char *)start, 0); 198 | else if (start > end) 199 | return KB_INIT_LOCKADDR(l, end, (const char *)start - (const char *)end, 0); 200 | else 201 | return -1; 202 | #else 203 | l->size = 0; 204 | return 0; 205 | #endif 206 | } 207 | 208 | /*********************************************************************** 209 | // high level locking 210 | ************************************************************************/ 211 | 212 | int kb_lock_code(void (*start) (void), void (*end) (void)) { 213 | kb_lockaddr_t l; 214 | 215 | if (_kb_init_lock_code(&l, start, end) != 0) 216 | return -1; 217 | #if defined(KB_HAVE_LOCK) 218 | return _kb_lock_lockaddr(&l, 1); 219 | #else 220 | return 0; 221 | #endif 222 | } 223 | 224 | int kb_lock_data(const void *start, const void *end) { 225 | kb_lockaddr_t l; 226 | 227 | if (_kb_init_lock_data(&l, start, end) != 0) 228 | return -1; 229 | #if defined(KB_HAVE_LOCK) 230 | return _kb_lock_lockaddr(&l, 1); 231 | #else 232 | return 0; 233 | #endif 234 | } 235 | 236 | int kb_lock_var(const void *addr, unsigned size) { 237 | return kb_lock_data(addr, (const char *)addr + size); 238 | } 239 | 240 | /*********************************************************************** 241 | // high level unlocking 242 | ************************************************************************/ 243 | 244 | int kb_unlock_code(void (*start) (void), void (*end) (void)) { 245 | kb_lockaddr_t l; 246 | 247 | if (_kb_init_lock_code(&l, start, end) != 0) 248 | return -1; 249 | #if defined(KB_HAVE_LOCK) 250 | return _kb_lock_lockaddr(&l, 0); 251 | #else 252 | return 0; 253 | #endif 254 | } 255 | 256 | int kb_unlock_data(const void *start, const void *end) { 257 | kb_lockaddr_t l; 258 | 259 | if (_kb_init_lock_data(&l, start, end) != 0) 260 | return -1; 261 | #if defined(KB_HAVE_LOCK) 262 | return _kb_lock_lockaddr(&l, 0); 263 | #else 264 | return 0; 265 | #endif 266 | } 267 | 268 | int kb_unlock_var(const void *addr, unsigned size) { 269 | return kb_unlock_data(addr, (const char *)addr + size); 270 | } 271 | 272 | /*********************************************************************** 273 | // merge overlapping regions 274 | // 275 | // We try to lock as few different regions as possible. 276 | ************************************************************************/ 277 | 278 | #if defined(KB_HAVE_LOCK) 279 | 280 | static int _kb_merge2(kb_lockaddr_t * l1, kb_lockaddr_t * l2) { 281 | unsigned long end1, end2; 282 | 283 | if (l1->size <= 0 || l2->size <= 0) 284 | return 0; 285 | 286 | end1 = l1->linear_address + l1->size; 287 | end2 = l2->linear_address + l2->size; 288 | 289 | /* try to merge l2 into l1 */ 290 | if (l1->linear_address <= l2->linear_address && end1 + 1 >= l2->linear_address) { 291 | if (end2 > end1) 292 | l1->size = end2 - l1->linear_address; 293 | l2->size = 0; 294 | return 1; 295 | } 296 | 297 | /* try to merge l1 into l2 */ 298 | if (l2->linear_address <= l1->linear_address && end2 + 1 >= l1->linear_address) { 299 | if (end1 > end2) 300 | l2->size = end1 - l2->linear_address; 301 | l1->size = 0; 302 | return 1; 303 | } 304 | 305 | return 0; 306 | } 307 | 308 | static 309 | int _kb_merge_lockaddr(kb_lockaddr_t l[], int n) { 310 | int i, j; 311 | int found; 312 | 313 | /* a simple 'bubblemerge' (like bubblesort) */ 314 | 315 | do { 316 | found = 0; 317 | 318 | for (i = 0; i < n - 1; i++) 319 | for (j = i + 1; j < n; j++) 320 | if (_kb_merge2(&l[i], &l[j])) 321 | found = 1; 322 | 323 | } while (found); 324 | 325 | return 0; 326 | } 327 | 328 | #if defined(KB_DEBUG) && (KB_DEBUG >= 4) 329 | static 330 | void _kb_print_lockaddr(const kb_lockaddr_t ll[], int n, const char *s) { 331 | int i; 332 | const kb_lockaddr_t *l = ll; 333 | 334 | for (i = 0; i < n; i++, l++) 335 | if (l->size > 0) 336 | fprintf(stderr, "libkb lockinfo: %-6s %04x:%08lx (0x%08lx), " 337 | "%6ld bytes\n", s, l->selector, l->address, l->linear_address, l->size); 338 | } 339 | #endif 340 | 341 | #endif /* KB_HAVE_LOCK */ 342 | 343 | /*********************************************************************** 344 | // lock a module, merge overlapping regions 345 | ************************************************************************/ 346 | 347 | #if defined(KB_HAVE_LOCK) 348 | 349 | static 350 | int __kb_lock_module(int do_lock, int cn, int dn, void (*code[])(void), const void *data[], kb_lockaddr_t l[]) { 351 | int x = 0; 352 | int i, n = 0; 353 | 354 | for (i = 0; i < cn + dn; i++) 355 | l[i].size = -1; 356 | 357 | for (i = 0; i < 2 * cn; i += 2) 358 | if (code[i] != NULL || code[i + 1] != NULL) 359 | x |= _kb_init_lock_code(&l[n++], code[i], code[i + 1]); 360 | 361 | for (i = 0; i < 2 * dn; i += 2) 362 | if (data[i] != NULL || data[i + 1] != NULL) 363 | x |= _kb_init_lock_data(&l[n++], data[i], data[i + 1]); 364 | 365 | if (x != 0) 366 | return -1; 367 | 368 | for (i = 0; i < n; i++) 369 | if (l[i].size < 0) 370 | return -1; 371 | 372 | #if defined(KB_DEBUG) && (KB_DEBUG >= 4) 373 | _kb_print_lockaddr(l, n, "1"); 374 | #endif 375 | _kb_merge_lockaddr(l, n); 376 | #if defined(KB_DEBUG) && (KB_DEBUG >= 4) 377 | _kb_print_lockaddr(l, n, "2"); 378 | #endif 379 | 380 | for (i = 0; i < n; i++) 381 | if (l[i].size > 0) 382 | x |= _kb_lock_lockaddr(&l[i], do_lock); 383 | 384 | return x == 0 ? 0 : -1; 385 | } 386 | 387 | #endif /* KB_HAVE_LOCK */ 388 | 389 | #if defined(__BORLANDC__) && !defined(KB_HAVE_LOCK) 390 | #pragma argsused 391 | #endif 392 | int _kb_lock_module(int do_lock, 393 | void (*cs1) (void), void (*ce1) (void), 394 | void (*cs2) (void), void (*ce2) (void), 395 | const void *ds1, const void *de1, 396 | const void *ds2, const void *de2, 397 | const void *ds3, const void *de3, 398 | const void *ds4, const void *de4, 399 | const void *ds5, const void *de5, 400 | const void *ds6, const void *de6, 401 | const void *ds7, const void *de7, const void *ds8, const void *de8) { 402 | #if defined(KB_HAVE_LOCK) 403 | void (*code[2 * 2]) (void); 404 | const void *data[8 * 2]; 405 | kb_lockaddr_t l[2 + 8]; 406 | int i; 407 | 408 | i = 0; 409 | code[i++] = cs1; 410 | code[i++] = ce1; 411 | code[i++] = cs2; 412 | code[i++] = ce2; 413 | 414 | i = 0; 415 | data[i++] = ds1; 416 | data[i++] = de1; 417 | data[i++] = ds2; 418 | data[i++] = de2; 419 | data[i++] = ds3; 420 | data[i++] = de3; 421 | data[i++] = ds4; 422 | data[i++] = de4; 423 | data[i++] = ds5; 424 | data[i++] = de5; 425 | data[i++] = ds6; 426 | data[i++] = de6; 427 | data[i++] = ds7; 428 | data[i++] = de7; 429 | data[i++] = ds8; 430 | data[i++] = de8; 431 | 432 | return __kb_lock_module(do_lock, 2, 8, code, data, l); 433 | #else 434 | return 0; 435 | #endif 436 | } 437 | 438 | /*********************************************************************** 439 | // locking (lock the locking code :-) 440 | ************************************************************************/ 441 | 442 | #if defined(KB_LOCK_ALL_END) 443 | KB_LOCK_ALL_END(_libkb_kbmlock) 444 | #endif 445 | int _libkb_kbmlock_lock(void) { 446 | int x = 0; 447 | 448 | #if defined(KB_LOCK_ALL) 449 | KB_LOCK_ALL(_libkb_kbmlock, x); 450 | #endif 451 | 452 | return x; 453 | } 454 | 455 | /* 456 | vi:ts=4 457 | */ 458 | -------------------------------------------------------------------------------- /src/libkb/kbmlock.h: -------------------------------------------------------------------------------- 1 | /* kbmlock.h -- memory locking interface of the 'libkb' keyboard library 2 | * Copyright (C) 1995-1998 Markus F.X.J. Oberhumer 3 | * For conditions of distribution and use, see copyright notice in kb.h 4 | */ 5 | 6 | /* locking can be used independently from the rest of the library */ 7 | 8 | #ifndef __LIBKB_KBMLOCK_H 9 | #define __LIBKB_KBMLOCK_H 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | int kb_lock_code(void (*start) (void), void (*end) (void)); 16 | int kb_lock_data(const void *start, const void *end); 17 | int kb_lock_var(const void *addr, unsigned size); 18 | 19 | int kb_unlock_code(void (*start) (void), void (*end) (void)); 20 | int kb_unlock_data(const void *start, const void *end); 21 | int kb_unlock_var(const void *addr, unsigned size); 22 | 23 | int _kb_lock_module(int do_lock, 24 | void (*cs1) (void), void (*ce1) (void), 25 | void (*cs2) (void), void (*ce2) (void), 26 | const void *ds1, const void *de1, 27 | const void *ds2, const void *de2, 28 | const void *ds3, const void *de3, 29 | const void *ds4, const void *de4, 30 | const void *ds5, const void *de5, 31 | const void *ds6, const void *de6, 32 | const void *ds7, const void *de7, const void *ds8, const void *de8); 33 | 34 | /*********************************************************************** 35 | // lock code: static + extern 36 | ************************************************************************/ 37 | 38 | #define ___KB_LOCK_ALL_CODE_WITH_SUFFIX(id,suffix) \ 39 | static void id ## _c_static ## suffix (void) { } \ 40 | extern void id ## _c_extern ## suffix (void); \ 41 | void id ## _c_extern ## suffix (void) { } 42 | 43 | #define KB_LOCK_ALL_CODE_START(id) \ 44 | ___KB_LOCK_ALL_CODE_WITH_SUFFIX(id,_s) 45 | 46 | #define KB_LOCK_ALL_CODE_END(id) \ 47 | ___KB_LOCK_ALL_CODE_WITH_SUFFIX(id,_e) 48 | 49 | #define KB_LOCK_ALL_CODE(id,x) \ 50 | x |= kb_lock_code(id ## _c_static_s, id ## _c_static_e); \ 51 | x |= kb_lock_code(id ## _c_extern_s, id ## _c_extern_e); 52 | 53 | /*********************************************************************** 54 | // data: static + extern, unconst + const, initialized + not initialized 55 | ************************************************************************/ 56 | 57 | #define ___KB_LOCK_ALL_DATA_WITH_SUFFIX(id,suffix) \ 58 | static char id ## _d_static ## suffix; \ 59 | extern char id ## _d_extern ## suffix; \ 60 | char id ## _d_extern ## suffix; \ 61 | static char id ## _i_static ## suffix = 1; \ 62 | extern char id ## _i_extern ## suffix; \ 63 | char id ## _i_extern ## suffix = 1; \ 64 | static const char id ## _o_static ## suffix; \ 65 | extern const char id ## _o_extern ## suffix; \ 66 | const char id ## _o_extern ## suffix; \ 67 | static const char id ## _p_static ## suffix = 1; \ 68 | extern const char id ## _p_extern ## suffix; \ 69 | const char id ## _p_extern ## suffix = 1; 70 | 71 | #define KB_LOCK_ALL_DATA_START(id) \ 72 | ___KB_LOCK_ALL_DATA_WITH_SUFFIX(id,_s) 73 | 74 | #define KB_LOCK_ALL_DATA_END(id) \ 75 | ___KB_LOCK_ALL_DATA_WITH_SUFFIX(id,_e) 76 | 77 | #define KB_LOCK_ALL_DATA(id,x) \ 78 | x |= kb_lock_data(& id ## _d_static_s, & id ## _d_static_e); \ 79 | x |= kb_lock_data(& id ## _d_extern_s, & id ## _d_extern_e); \ 80 | x |= kb_lock_data(& id ## _i_static_s, & id ## _i_static_e); \ 81 | x |= kb_lock_data(& id ## _i_extern_s, & id ## _i_extern_e); \ 82 | x |= kb_lock_data(& id ## _o_static_s, & id ## _o_static_e); \ 83 | x |= kb_lock_data(& id ## _o_extern_s, & id ## _o_extern_e); \ 84 | x |= kb_lock_data(& id ## _p_static_s, & id ## _p_static_e); \ 85 | x |= kb_lock_data(& id ## _p_extern_s, & id ## _p_extern_e); 86 | 87 | /*********************************************************************** 88 | // lock code + data 89 | ************************************************************************/ 90 | 91 | #define KB_LOCK_ALL_START(id) \ 92 | KB_LOCK_ALL_CODE_START(id) \ 93 | KB_LOCK_ALL_DATA_START(id) 94 | 95 | #define KB_LOCK_ALL_END(id) \ 96 | KB_LOCK_ALL_CODE_END(id) \ 97 | KB_LOCK_ALL_DATA_END(id) 98 | 99 | #if 0 100 | #define KB_LOCK_ALL(id,x) \ 101 | KB_LOCK_ALL_CODE(id,x) \ 102 | KB_LOCK_ALL_DATA(id,x) 103 | #else 104 | #define KB_LOCK_ALL(id,x) \ 105 | x |= _kb_lock_module(1, id ## _c_static_s, id ## _c_static_e, \ 106 | id ## _c_extern_s, id ## _c_extern_e, \ 107 | & id ## _d_static_s, & id ## _d_static_e, \ 108 | & id ## _d_extern_s, & id ## _d_extern_e, \ 109 | & id ## _i_static_s, & id ## _i_static_e, \ 110 | & id ## _i_extern_s, & id ## _i_extern_e, \ 111 | & id ## _o_static_s, & id ## _o_static_e, \ 112 | & id ## _o_extern_s, & id ## _o_extern_e, \ 113 | & id ## _p_static_s, & id ## _p_static_e, \ 114 | & id ## _p_extern_s, & id ## _p_extern_e); 115 | #endif 116 | 117 | #ifdef __cplusplus 118 | } /* extern "C" */ 119 | #endif 120 | #endif /* already included */ 121 | /* 122 | vi:ts=4 123 | */ 124 | -------------------------------------------------------------------------------- /src/libkb/kbos.c: -------------------------------------------------------------------------------- 1 | /* kbos.c -- operating system and BIOS keyboard access 2 | * Copyright (C) 1995-1998 Markus F.X.J. Oberhumer 3 | * For conditions of distribution and use, see copyright notice in kb.h 4 | */ 5 | 6 | #if 0 && defined(__EMX__) 7 | #include /* must be first include file */ 8 | #endif 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "_kb.h" 15 | #if defined(__GO32__) 16 | #include 17 | #undef kbhit /* want to be able to call kbhit from libc */ 18 | int kbhit(void); /* djgpp v2 */ 19 | #endif 20 | 21 | #if defined(KB_LOCK_ALL_START) 22 | KB_LOCK_ALL_START(_libkb_kbos) 23 | #endif 24 | /* this file contains lots of #if ... */ 25 | /*********************************************************************** 26 | // utility functions 27 | ************************************************************************/ 28 | #if defined(KB_INT86_REGS) 29 | __inline__ void _kb_int86_regs_init(KB_INT86_REGS * regs) { 30 | memset(regs, 0, sizeof(KB_INT86_REGS)); 31 | #if defined(__WATCOMC__) 32 | regs->w.ds = FP_SEG(regs); 33 | #if defined(__386__) && !defined(__WINDOWS_386__) 34 | regs->w.fs = regs->w.gs = FP_SEG(regs); 35 | #endif 36 | #endif 37 | } 38 | 39 | __inline__ void _kb_int86_regs_init_ax(KB_INT86_REGS * regs, unsigned short ax) { 40 | _kb_int86_regs_init(regs); 41 | #if defined(__WATCOMC__) 42 | regs->w.ax = ax; 43 | #else 44 | regs->x.ax = ax; 45 | #endif 46 | } 47 | 48 | #endif /* KB_INT86_REGS */ 49 | 50 | /* check if we are running in a Windows DOS box */ 51 | int _kb_iswin(void) { 52 | #if !defined(KB_INT86_REGS) 53 | return 0; 54 | #elif defined(__GO32__) && !defined(__DJGPP__) 55 | /* go32 doesn't support INT 0x2f, AX=0x1600 */ 56 | return -1; 57 | #else 58 | KB_INT86_REGS regs; 59 | #if defined(__EMX__) 60 | if (_osmode != DOS_MODE) 61 | return 0; 62 | if ((_emx_env & 0x1000) == 0) /* if RSX not found */ 63 | return 0; 64 | if (!KB_USE_INT86()) /* _int86() not allowed */ 65 | return -1; 66 | #endif 67 | _kb_int86_regs_init_ax(®s, 0x1600); 68 | KB_INT86(0x2f, ®s); 69 | if (regs.h.al == 0 || regs.h.al == 1 || regs.h.al == 0x80 || regs.h.al == 0xff) 70 | return 0; 71 | /* return major-version in high byte, minor-version in low byte */ 72 | return (regs.h.al << 8) | regs.h.ah; 73 | #endif /* KB_INT86_REGS */ 74 | } 75 | 76 | /* sleep for a very short time */ 77 | __inline__ void _kb_usleep(unsigned long usec) { 78 | if (usec < 1024) 79 | return; 80 | #if defined(__KB_LINUX) || defined(__DJGPP__) 81 | usleep(usec); 82 | #elif defined(__EMX__) 83 | _sleep2(usec / 1000); 84 | #elif defined(_MSC_VER) && defined(__KB_MSDOS16) 85 | /* FIXME */ 86 | #elif defined(__KB_MSDOS) 87 | delay((int)(usec / 1000)); 88 | #endif 89 | } 90 | 91 | /*********************************************************************** 92 | // BIOS wrapper 93 | // some documentation can be found in djgpp2/src/libc/bios/ 94 | ************************************************************************/ 95 | 96 | #if defined(__EMX__) || defined(__GO32__) || defined(__WATCOMC__) 97 | 98 | static __inline__ int _my_bioskey(unsigned cmd) { 99 | KB_INT86_REGS regs; 100 | 101 | #if defined(__EMX__) 102 | /* ((_emx_env & 0x0800) == 0) || "emx: -ac not enabled for _int86()" */ 103 | if (!KB_USE_INT86()) 104 | return 0; 105 | #endif /* __EMX__ */ 106 | 107 | _kb_int86_regs_init(®s); 108 | regs.h.ah = cmd; 109 | KB_INT86(0x16, ®s); 110 | 111 | #if defined(__WATCOMC__) 112 | #define x w /* regs.x.AA -> regs.w.AA */ 113 | #endif 114 | 115 | switch (cmd) { 116 | case KB_KEYBRD_READY: 117 | case KB_NKEYBRD_READY: 118 | if (regs.x.flags & 0x40) /* zero flag set -> no key is waiting */ 119 | return 0; 120 | else if (regs.x.ax == 0) 121 | return -1; /* Control-Break */ 122 | else 123 | return regs.x.ax; 124 | case KB_KEYBRD_SHIFTSTATUS: 125 | return regs.h.al; 126 | case KB_KEYBRD_READ: 127 | case KB_NKEYBRD_READ: 128 | case KB_NKEYBRD_SHIFTSTATUS: 129 | return regs.x.ax; 130 | } 131 | return 0; 132 | 133 | #if defined(__WATCOMC__) 134 | #undef x 135 | #endif 136 | } 137 | 138 | #define _KB_BIOSKEY(x) _my_bioskey(x) 139 | 140 | #endif 141 | 142 | #if defined(__KB_MSDOS) 143 | #if defined(__BORLANDC__) || defined(__TURBOC__) || defined(__GO32__) 144 | #ifndef _KB_BIOSKEY 145 | #define _KB_BIOSKEY(x) bioskey(x) 146 | #endif 147 | #endif 148 | #if defined(_MSC_VER) || defined(__WATCOMC__) 149 | #ifndef _KB_BIOSKEY 150 | #define _KB_BIOSKEY(x) _bios_keybrd(x) 151 | #endif 152 | #endif 153 | #endif 154 | 155 | /*********************************************************************** 156 | // BIOS level - lowest and (hopefully) fastest access level 157 | // If not applicable, OS level is used 158 | ************************************************************************/ 159 | 160 | __inline__ int kb_bioskey(unsigned cmd) { 161 | #if defined(_KB_BIOSKEY) 162 | return _KB_BIOSKEY(cmd); 163 | #else 164 | return 0; 165 | #endif 166 | } 167 | 168 | int kb_bios_kbhit(void) { 169 | if (_kb_mode) 170 | return kb_kbhit(); 171 | 172 | #if !defined(_KB_BIOSKEY) 173 | return kb_os_kbhit(); 174 | #elif defined(__GO32__) 175 | return kbhit(); /* this uses BIOS and is damned fast */ 176 | #else 177 | #if defined(__EMX__) 178 | if (!KB_USE_INT86()) 179 | return kb_os_kbhit(); /* _int86() not allowed */ 180 | #endif 181 | return (_KB_BIOSKEY(KB_NKEYBRD_READY) != 0); 182 | #endif 183 | } 184 | 185 | unsigned kb_bios_getkey(void) { 186 | if (_kb_mode) 187 | return kb_getkey(); 188 | 189 | if (!kb_bios_kbhit()) 190 | return 0; 191 | 192 | #if !defined(_KB_BIOSKEY) 193 | return kb_os_getkey(); 194 | #elif defined(__GO32__) 195 | return getxkey(); /* this uses BIOS */ 196 | #else 197 | #if defined(__EMX__) 198 | if (!KB_USE_INT86()) 199 | return kb_os_getkey(); /* _int86() not allowed */ 200 | #endif 201 | return kb_bios_keycode(_KB_BIOSKEY(KB_NKEYBRD_READ)); 202 | #endif 203 | } 204 | 205 | /*********************************************************************** 206 | // emx getch() wrapper 207 | // returns 0 if no key is available 208 | ************************************************************************/ 209 | 210 | #if defined(__EMX__) 211 | 212 | static int _last_key = -1; 213 | 214 | static __inline__ int _my_read_kbd(int eat) { 215 | if (_last_key == -1) 216 | _last_key = _read_kbd(0, 0, 0); /* echo, wait, sig */ 217 | if (_last_key == -1) 218 | return 0; /* no key available */ 219 | if (eat) { 220 | int k = _last_key; 221 | _last_key = -1; 222 | return k; 223 | } else 224 | return 1; 225 | } 226 | 227 | #define _my_kbhit() _my_read_kbd(0) 228 | #define _my_getch() _my_read_kbd(1) 229 | 230 | #endif /* __EMX__ */ 231 | 232 | /*********************************************************************** 233 | // Linux getch() wrapper 234 | // returns 0 if no key is available 235 | // 236 | // adapted from code written by Tommy Frandsen and Harm Hanemaayer 237 | // see svgalib 1.2.x: src/vgamisc.c 238 | // 239 | // This code is slow and doesn't work very well because stdin 240 | // is only temporary changed for each attempt to read a key. 241 | // It works better if you use kb_os_waitkey(). 242 | ************************************************************************/ 243 | 244 | #if defined(__KB_LINUX) 245 | 246 | #include 247 | #include 248 | #include 249 | #include 250 | #include 251 | #include 252 | 253 | /* use a buffer for keys, this works better */ 254 | static unsigned char _key_buffer[128]; 255 | static const int _key_size = HIGH(_key_buffer); 256 | static int _key_index = 0; 257 | 258 | /* read keyboard file, fill buffer */ 259 | static __inline__ void _my_read_kbd(int fd) { 260 | if (_key_index < _key_size) { 261 | int n = read(fd, &_key_buffer[_key_index], _key_size - _key_index); 262 | if (n > 0) 263 | _key_index += n; 264 | } 265 | } 266 | 267 | /* wait for a key, fill buffer */ 268 | static __inline__ void _my_read_kbd_and_wait(int fd, unsigned long usec) { 269 | struct timeval tv, *tvp; 270 | fd_set fds; 271 | 272 | FD_ZERO(&fds); 273 | FD_SET(fd, &fds); 274 | if (usec == (unsigned long)-1) 275 | tvp = NULL; /* wait forever */ 276 | else { 277 | tv.tv_sec = usec / 1000000; 278 | tv.tv_usec = usec % 1000000; 279 | tvp = &tv; 280 | } 281 | if (select(fd + 1, &fds, NULL, NULL, tvp) > 0) 282 | _my_read_kbd(fd); 283 | } 284 | 285 | /* read keyboard, fill buffer */ 286 | static __inline__ void _my_read_a_key(unsigned long wait) { 287 | struct termio zap, original; 288 | int fd = fileno(stdin); 289 | 290 | if (ioctl(fd, TCGETA, &original) != 0) /* Get termio */ 291 | return; 292 | zap = original; 293 | zap.c_cc[VMIN] = 0; /* Modify termio */ 294 | zap.c_cc[VTIME] = 0; 295 | zap.c_lflag = 0; 296 | if (ioctl(fd, TCSETA, &zap) != 0) /* Set new termio */ 297 | return; 298 | if (wait) 299 | _my_read_kbd_and_wait(fd, wait); 300 | else 301 | _my_read_kbd(fd); 302 | ioctl(fd, TCSETA, &original); /* Restore termio */ 303 | } 304 | 305 | /* get a key from the keyboard buffer or read from file */ 306 | static unsigned _my_get_key(int eat, unsigned long wait) { 307 | unsigned k; 308 | 309 | if (_key_index <= 0) { 310 | _my_read_a_key(wait); 311 | if (_key_index <= 0) 312 | return 0; /* no key available */ 313 | } 314 | k = _key_buffer[0]; 315 | if (eat) { 316 | _key_index--; 317 | if (_key_index > 0) 318 | memmove(&_key_buffer[0], &_key_buffer[1], _key_index); 319 | } 320 | return k; 321 | } 322 | 323 | /* this is the 'public' entry point */ 324 | static unsigned _linux_getkey(int eat, unsigned long wait) { 325 | unsigned k = _my_get_key(eat, wait); 326 | 327 | #if 0 328 | /* TODO: convert Esc sequences to our portable keycode. 329 | * how can this be done in a way that works on all terminals ? 330 | */ 331 | if (eat && k == 27) { 332 | unsigned k1 = _my_get_key(eat, wait); 333 | unsigned k2 = _my_get_key(eat, wait); 334 | 335 | if (k2 == 68) /* cursor left */ 336 | k = 0x24b; 337 | else if (k2 == 67) /* cursor right */ 338 | k = 0x24d; 339 | else if (k2 == 65) /* cursor up */ 340 | k = 0x248; 341 | else if (k2 == 66) /* cursor down */ 342 | k = 0x250; 343 | else 344 | k = 0x200 | k2; 345 | } 346 | #endif 347 | 348 | return k; 349 | } 350 | 351 | #define _my_kbhit() _linux_getkey(0,0) 352 | #define _my_getch() _linux_getkey(1,0) 353 | 354 | unsigned kb_os_waitkey(void) { 355 | return _linux_getkey(1, (unsigned long)-1); 356 | } 357 | 358 | #endif /* __KB_LINUX */ 359 | 360 | /*********************************************************************** 361 | // OS level 362 | ************************************************************************/ 363 | 364 | int kb_os_kbhit(void) { 365 | if (_kb_mode) 366 | return kb_kbhit(); 367 | 368 | #if defined(__EMX__) 369 | /* use BIOS if possible, cause it's much faster */ 370 | if (KB_USE_INT86()) 371 | return kb_bios_kbhit(); 372 | return _my_kbhit() != 0; 373 | #elif defined(__KB_LINUX) 374 | return _my_kbhit() != 0; 375 | #else 376 | return kbhit() != 0; 377 | #endif 378 | } 379 | 380 | /* do NOT use BIOS, but be compatible */ 381 | 382 | #if !defined(_my_getch) 383 | #define _my_getch() getch() 384 | #endif 385 | 386 | unsigned kb_os_getkey(void) { 387 | unsigned k; 388 | 389 | if (_kb_mode) 390 | return kb_getkey(); 391 | 392 | if (!kb_os_kbhit()) 393 | return 0; 394 | 395 | k = _my_getch(); 396 | #if defined(__KB_MSDOS) 397 | if (k != 0) 398 | return kb_os_keycode(k, 0); 399 | k = _my_getch(); /* read again */ 400 | return kb_os_keycode(0, k); 401 | #elif defined(__KB_LINUX) 402 | return k; 403 | #endif 404 | } 405 | 406 | /*********************************************************************** 407 | // emx+gcc lacks a real kbhit() and getch() 408 | ************************************************************************/ 409 | 410 | #if defined(__EMX__) 411 | 412 | int kbhit(void) { 413 | return kb_os_kbhit(); 414 | } 415 | 416 | int getch(void) { 417 | if (_kb_mode) { 418 | int k = kb_getkey(); 419 | return k == 0 ? -1 : k; 420 | } 421 | return _my_getch(); 422 | } 423 | 424 | #endif /* __EMX__ */ 425 | 426 | /*********************************************************************** 427 | // wait for a key 428 | ************************************************************************/ 429 | 430 | #if defined(__KB_MSDOS) 431 | 432 | unsigned kb_os_waitkey(void) { 433 | while (!kb_os_kbhit()) 434 | _kb_usleep(5 * 1024u); 435 | return kb_os_getkey(); 436 | } 437 | 438 | #endif 439 | 440 | /*********************************************************************** 441 | // locking 442 | ************************************************************************/ 443 | 444 | #if defined(KB_LOCK_ALL_END) 445 | KB_LOCK_ALL_END(_libkb_kbos) 446 | #endif 447 | int _libkb_kbos_lock(void) { 448 | int x = 0; 449 | 450 | #if defined(KB_LOCK_ALL) 451 | KB_LOCK_ALL(_libkb_kbos, x); 452 | #endif 453 | 454 | return x; 455 | } 456 | 457 | /* 458 | vi:ts=4 459 | */ 460 | -------------------------------------------------------------------------------- /src/libkb/kbsignal.c: -------------------------------------------------------------------------------- 1 | /* kbsignal.c -- signal handling 2 | * Copyright (C) 1995-1998 Markus F.X.J. Oberhumer 3 | * For conditions of distribution and use, see copyright notice in kb.h 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include "_kb.h" 13 | 14 | #if defined(KB_LOCK_ALL_START) 15 | KB_LOCK_ALL_START(_libkb_kbsignal) 16 | #endif 17 | /*********************************************************************** 18 | // wrapper for djgpp v1 19 | ************************************************************************/ 20 | #if defined(_KB_NO_SIGNALS) 21 | const int _kb_nsig = 0; 22 | const int _kb_sigmin = 0; 23 | const int _kb_sigmax = -1; 24 | 25 | #if !defined(SIG_ERR) 26 | #define SIG_ERR NULL 27 | #endif 28 | 29 | int _kb_signal_install(void) { 30 | return 0; /* installation ok */ 31 | } 32 | 33 | static void _my_signal_handler(int signum) { 34 | _kb_emergency_remove(1); 35 | exit(EXIT_SIG(signum)); 36 | } 37 | 38 | const kb_sighandler_t kb_signal_handler = _my_signal_handler; 39 | 40 | kb_sighandler_t kb_signal(int signum, kb_sighandler_t handler) { 41 | return SIG_ERR; 42 | } 43 | 44 | kb_sighandler_t kb_get_chained_signal(int signum) { 45 | return SIG_ERR; 46 | } 47 | 48 | kb_sighandler_t kb_set_chained_signal(int signum, kb_sighandler_t h) { 49 | return SIG_ERR; 50 | } 51 | 52 | #endif /* _KB_NO_SIGNALS */ 53 | 54 | /*********************************************************************** 55 | // IMPORTANT NOTE: check your compiler flags so that no 56 | // stack overflow checks will be inserted here ! 57 | ************************************************************************/ 58 | 59 | #if !defined(_KB_NO_SIGNALS) 60 | 61 | /* don't waste memory */ 62 | #if defined(__DJGPP__) 63 | #define KB_SIGMIN 288 64 | #else 65 | #define KB_SIGMIN 0 66 | #endif 67 | 68 | /* NSIG is the highest defined signal number + 1 */ 69 | #if !defined(NSIG) 70 | #if defined(_NSIG) 71 | #define NSIG _NSIG 72 | #elif defined(SIGMAX) 73 | #define NSIG (SIGMAX+1) 74 | #elif defined(_SIGMAX) 75 | #define NSIG (_SIGMAX+1) 76 | #else 77 | #define NSIG (32 + KB_SIGMIN) 78 | #endif 79 | #endif 80 | 81 | const int _kb_nsig = NSIG; 82 | const int _kb_sigmin = KB_SIGMIN; 83 | const int _kb_sigmax = NSIG - 1; 84 | 85 | /* sigaction() gives us more control than signal() */ 86 | #if defined(__KB_LINUX) 87 | #define _KB_USE_SIGACTION_GET 88 | #elif defined(__EMX__) 89 | #define _KB_USE_SIGACTION_GET 90 | #define _KB_USE_SIGACTION_SET 91 | #endif 92 | 93 | /*********************************************************************** 94 | // wrappers for sigaction/signal 95 | ************************************************************************/ 96 | 97 | #if defined(_KB_USE_SIGACTION_GET) 98 | static kb_sighandler_t kb_signal_get_sa(int signum, struct sigaction *sa) { 99 | if (sa == NULL) 100 | return SIG_ERR; 101 | if (sigaction(signum, NULL, sa) != 0) 102 | return SIG_ERR; 103 | return sa->sa_handler; 104 | } 105 | #endif 106 | 107 | #if defined(_KB_USE_SIGACTION_SET) 108 | static kb_sighandler_t kb_signal_set_sa(int signum, kb_sighandler_t h, struct sigaction *sa) { 109 | kb_sighandler_t oldh; 110 | 111 | if (sa == NULL) 112 | return SIG_ERR; 113 | if (sigaction(signum, NULL, sa) != 0) 114 | return SIG_ERR; 115 | oldh = sa->sa_handler; 116 | if (oldh == SIG_ERR || h == SIG_ERR) 117 | return SIG_ERR; 118 | sa->sa_handler = h; 119 | #if defined(__EMX__) /* use the emx signal processing model */ 120 | sa->sa_flags &= ~(SA_SYSV); 121 | sa->sa_flags |= (SA_ACK); 122 | #endif 123 | if (sigaction(signum, sa, NULL) != 0) 124 | return SIG_ERR; 125 | return oldh; 126 | } 127 | #endif 128 | 129 | static kb_sighandler_t kb_signal_get(int signum) { 130 | #if defined(_KB_USE_SIGACTION_GET) 131 | struct sigaction sa; 132 | return kb_signal_get_sa(signum, &sa); 133 | #else 134 | kb_sighandler_t h, n; 135 | 136 | n = SIG_DFL; 137 | h = signal(signum, n); /* get and set handler */ 138 | if (h == SIG_ERR) /* error in signal() call */ 139 | return SIG_ERR; 140 | if (h != n) 141 | if (signal(signum, h) == SIG_ERR) /* restore handler */ 142 | return SIG_ERR; 143 | return h; 144 | #endif 145 | } 146 | 147 | static kb_sighandler_t kb_signal_set(int signum, kb_sighandler_t h) { 148 | #if defined(_KB_USE_SIGACTION_SET) 149 | struct sigaction sa; 150 | return kb_signal_set_sa(signum, h, &sa); 151 | #else 152 | return signal(signum, h); 153 | #endif 154 | } 155 | 156 | /*********************************************************************** 157 | // vars for the old (chained) signal handlers 158 | ************************************************************************/ 159 | 160 | /* don't waste memory */ 161 | #define old_sigh (__old_sigh - KB_SIGMIN) 162 | #define sig_installed (__sig_installed - KB_SIGMIN) 163 | 164 | #if defined(_KB_USE_SIGACTION_GET) 165 | static struct sigaction __old_sigh[NSIG - KB_SIGMIN]; 166 | #define OLD_SIGH(signum) (old_sigh[signum].sa_handler) 167 | #else 168 | static kb_sighandler_t __old_sigh[NSIG - KB_SIGMIN]; 169 | #define OLD_SIGH(signum) (old_sigh[signum]) 170 | #endif 171 | 172 | static unsigned char __sig_installed[NSIG - KB_SIGMIN]; 173 | 174 | /*********************************************************************** 175 | // our signal handler 176 | ************************************************************************/ 177 | 178 | static void _my_signal_handler(int signum) { 179 | int err; 180 | 181 | #if defined(KB_DEBUG) && (KB_DEBUG >= 2) 182 | /* remove keyboard handler before doing anything else */ 183 | _kb_emergency_remove(0); 184 | 185 | /* file I/O is somewhat dangerous within a signal handler ... */ 186 | fprintf(stderr, "libkb: received signal %d%s\n", signum, 187 | (signum < KB_SIGMIN || signum >= NSIG) ? " STRANGE !!!" : ""); 188 | fflush(stderr); 189 | #endif 190 | 191 | /* remove keyboard handler */ 192 | _kb_emergency_remove(1); 193 | 194 | /* sanity check */ 195 | if (signum < KB_SIGMIN || signum >= NSIG) 196 | return; 197 | 198 | /* restore old signal handler */ 199 | if (sig_installed[signum] != 0x01) { /* should not happen */ 200 | err = (signal(signum, SIG_DFL) == SIG_ERR); 201 | #if defined(KB_DEBUG) && (KB_DEBUG >= 2) 202 | fprintf(stderr, "libkb: signal %d not expected !!!\n", signum); 203 | fflush(stderr); 204 | #endif 205 | } 206 | #if defined(_KB_USE_SIGACTION_GET) 207 | else if (sigaction(signum, &old_sigh[signum], NULL) != 0) 208 | err = 1; 209 | #else 210 | else if (signal(signum, old_sigh[signum]) == SIG_ERR) 211 | err = 1; 212 | #endif 213 | else 214 | err = 0; 215 | 216 | #if defined(__EMX__) /* emx signal processing model */ 217 | signal(signum, SIG_ACK); /* ack. signal */ 218 | #endif 219 | 220 | /* chain old signal handler - this should terminate the program */ 221 | if (!err) { 222 | sig_installed[signum] = 0; /* no longer active */ 223 | #if defined(KB_DEBUG) && (KB_DEBUG >= 2) 224 | fprintf(stderr, "libkb: chaining signal %d\n", signum); 225 | fflush(stderr); 226 | #endif 227 | raise(signum); 228 | } 229 | 230 | /* if we return from here, the application should be aware 231 | * that the keyboard handler was removed. 232 | */ 233 | } 234 | 235 | /* improve source code readability (at least a little bit :-) */ 236 | #define MY_HANDLER _my_signal_handler 237 | 238 | /* make accessible */ 239 | const kb_sighandler_t kb_signal_handler = MY_HANDLER; 240 | 241 | /*********************************************************************** 242 | // install a signal handler (compatible to signal()) 243 | ************************************************************************/ 244 | 245 | kb_sighandler_t kb_signal(int signum, kb_sighandler_t handler) { 246 | kb_sighandler_t h; 247 | 248 | if (signum < KB_SIGMIN || signum >= NSIG || handler == SIG_ERR) 249 | return SIG_ERR; 250 | h = kb_signal_get(signum); 251 | if (h == SIG_ERR) { 252 | sig_installed[signum] = 0x81; 253 | return SIG_ERR; 254 | } 255 | 256 | if (h == MY_HANDLER && sig_installed[signum] != 0x01) { 257 | /* strange: someone installed my handler without my knowledge */ 258 | sig_installed[signum] = 0x01; 259 | } 260 | 261 | if (h == handler) /* no change */ 262 | return h; 263 | 264 | if (handler != MY_HANDLER) { /* not my handler */ 265 | if (kb_signal_set(signum, handler) != h) 266 | return SIG_ERR; 267 | if (handler == SIG_IGN) 268 | sig_installed[signum] = 0x20; 269 | else 270 | sig_installed[signum] = 0x10; 271 | return h; 272 | } 273 | 274 | /* are you still here ? :-) */ 275 | /* assert(handler == MY_HANDLER); */ 276 | 277 | /* store current signal information */ 278 | #if defined(_KB_USE_SIGACTION_GET) 279 | if (kb_signal_get_sa(signum, &old_sigh[signum]) != h) 280 | return SIG_ERR; 281 | #else 282 | old_sigh[signum] = h; 283 | #endif 284 | 285 | /* if the signal is ignored, we ignore it as well */ 286 | if (h == SIG_IGN) { 287 | sig_installed[signum] = 0x02; 288 | return h; 289 | } 290 | 291 | /* now the time has come to install our handler */ 292 | if (kb_signal_set(signum, handler) != h) { 293 | sig_installed[signum] = 0x82; 294 | return SIG_ERR; 295 | } 296 | 297 | /* everything ok */ 298 | sig_installed[signum] = 0x01; 299 | return h; 300 | } 301 | 302 | /*********************************************************************** 303 | // install all signal handlers 304 | // note: a handler cannot be installed for SIGKILL, so 305 | // don't "kill -9" as this will not restore the keyboard 306 | ************************************************************************/ 307 | 308 | /* FIXME: which signals ? */ 309 | /* We catch all signals that cause an exit by default (aka almost all) */ 310 | static const short signals_to_catch[] = { 311 | SIGABRT, /* ANSI */ 312 | #if defined(SIGALRM) 313 | SIGALRM, /* POSIX.1 */ 314 | #endif 315 | #if defined(SIGBREAK) 316 | SIGBREAK, 317 | #endif 318 | #if defined(SIGBUS) 319 | SIGBUS, 320 | #endif 321 | SIGFPE, /* ANSI */ 322 | #if defined(SIGHUP) 323 | SIGHUP, /* POSIX.1 */ 324 | #endif 325 | SIGILL, /* ANSI */ 326 | SIGINT, /* ANSI */ 327 | #if defined(SIGIOT) 328 | SIGIOT, 329 | #endif 330 | #if defined(SIGKILL) 331 | SIGKILL, /* we can set a handler for djgpp v2 */ 332 | #endif 333 | #if defined(SIGPIPE) 334 | SIGPIPE, /* POSIX.1 */ 335 | #endif 336 | #if defined(SIGPROF) 337 | SIGPROF, 338 | #endif 339 | #if defined(SIGPWR) 340 | SIGPWR, 341 | #endif 342 | #if defined(SIGQUIT) 343 | SIGQUIT, /* POSIX.1 */ 344 | #endif 345 | SIGSEGV, /* ANSI */ 346 | #if defined(SIGTERM) 347 | SIGTERM, /* ANSI */ 348 | #endif 349 | #if defined(SIGTRAP) 350 | SIGTRAP, 351 | #endif 352 | #if defined(SIGXCPU) 353 | SIGXCPU, 354 | #endif 355 | #if defined(SIGXFSZ) 356 | SIGXFSZ, 357 | #endif 358 | #if defined(SIGVTALRM) 359 | SIGVTALRM, 360 | #endif 361 | }; 362 | 363 | int _kb_signal_install(void) { 364 | int i; 365 | int saved_errno; 366 | 367 | saved_errno = errno; 368 | 369 | for (i = 0; i < HIGH(signals_to_catch); i++) { 370 | int signum; 371 | kb_sighandler_t h; 372 | 373 | signum = signals_to_catch[i]; 374 | h = kb_signal(signum, MY_HANDLER); 375 | 376 | #if defined(KB_DEBUG) && (KB_DEBUG >= 3) 377 | fprintf(stderr, "libkb info: handler for signal %2d", signum); 378 | fprintf(stderr, ": 0x%02x, %s", sig_installed[signum], h == SIG_ERR ? "FAILED" : "ok"); 379 | #if defined(KB_SIGNAME) 380 | fprintf(stderr, " (%s)", KB_SIGNAME(signum)); 381 | #endif 382 | fprintf(stderr, "\n"); 383 | #endif 384 | h = h; 385 | } 386 | 387 | #if defined(KB_DEBUG) 388 | fprintf(stderr, "libkb info: installed a signal handler for these signals:\n"); 389 | for (i = KB_SIGMIN; i < NSIG; i++) 390 | if (sig_installed[i] == 0x01) 391 | fprintf(stderr, "%d ", i); 392 | fprintf(stderr, "\n"); 393 | fflush(stderr); 394 | #endif 395 | 396 | errno = saved_errno; 397 | 398 | /* return ok */ 399 | return 0; 400 | } 401 | 402 | /*********************************************************************** 403 | // signal chaining 404 | ************************************************************************/ 405 | 406 | kb_sighandler_t kb_get_chained_signal(int signum) { 407 | kb_sighandler_t h; 408 | 409 | if (signum < KB_SIGMIN || signum >= NSIG) 410 | return SIG_ERR; 411 | if (sig_installed[signum] != 0x01) 412 | return SIG_ERR; 413 | 414 | h = OLD_SIGH(signum); 415 | /* sanity check - may not happen */ 416 | if (h == SIG_IGN || h == SIG_ERR || h == MY_HANDLER) 417 | return SIG_ERR; 418 | return h; 419 | } 420 | 421 | kb_sighandler_t kb_set_chained_signal(int signum, kb_sighandler_t handler) { 422 | kb_sighandler_t h; 423 | 424 | /* cannot chain to SIG_IGN */ 425 | if (handler == SIG_IGN || handler == SIG_ERR) 426 | return SIG_ERR; 427 | /* cannot chain to the signal handler itself */ 428 | if (handler == MY_HANDLER) 429 | return SIG_ERR; 430 | 431 | h = kb_get_chained_signal(signum); 432 | if (h == SIG_ERR) 433 | return SIG_ERR; 434 | 435 | OLD_SIGH(signum) = handler; 436 | return h; 437 | } 438 | 439 | #endif /* !_KB_NO_SIGNALS */ 440 | 441 | /*********************************************************************** 442 | // emergency SIGALRM 443 | ************************************************************************/ 444 | 445 | #if !defined(_KB_NO_SIGNALS) && defined(SIGALRM) 446 | 447 | static int running = 0; 448 | 449 | int _kb_signal_alarm_install(void) { 450 | if (sig_installed[SIGALRM] != 0x01) 451 | return -1; 452 | if (_kb_signal_alarm_resume() < 0) 453 | return -1; 454 | return 0; 455 | } 456 | 457 | void _kb_signal_alarm_update(void) { 458 | if (running) 459 | alarm(30); 460 | } 461 | 462 | int _kb_signal_alarm_pause(void) { 463 | int old_running = running; 464 | 465 | if (!(_kb_mode && (_kb_flags & KB_FLAG_EMERGENCY_SIGALRM))) 466 | return -1; 467 | 468 | alarm(0); 469 | running = 0; 470 | return old_running; 471 | } 472 | 473 | int _kb_signal_alarm_resume(void) { 474 | int old_running = running; 475 | 476 | if (!(_kb_mode && (_kb_flags & KB_FLAG_EMERGENCY_SIGALRM))) 477 | return -1; 478 | 479 | running = 1; 480 | _kb_signal_alarm_update(); 481 | return old_running; 482 | } 483 | 484 | #else 485 | 486 | int _kb_signal_alarm_pause(void) { 487 | return -1; 488 | } 489 | 490 | int _kb_signal_alarm_resume(void) { 491 | return -1; 492 | } 493 | 494 | #endif 495 | 496 | /*********************************************************************** 497 | // locking 498 | ************************************************************************/ 499 | 500 | #if defined(KB_LOCK_ALL_END) 501 | KB_LOCK_ALL_END(_libkb_kbsignal) 502 | #endif 503 | int _libkb_kbsignal_lock(void) { 504 | int x = 0; 505 | 506 | #if defined(KB_LOCK_ALL) 507 | KB_LOCK_ALL(_libkb_kbsignal, x); 508 | #endif 509 | 510 | return x; 511 | } 512 | 513 | /* 514 | vi:ts=4 515 | */ 516 | -------------------------------------------------------------------------------- /src/libkb/kbtables.c: -------------------------------------------------------------------------------- 1 | /* kbtables.c -- keyboard tables and high level access functions 2 | * Copyright (C) 1995-1998 Markus F.X.J. Oberhumer 3 | * For conditions of distribution and use, see copyright notice in kb.h 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include "_kb.h" 10 | #include "_kbtable.hh" 11 | #include "_kbname.hh" 12 | 13 | #if defined(KB_LOCK_ALL_START) 14 | KB_LOCK_ALL_START(_libkb_kbtables) 15 | #endif 16 | /* If you use the libkb library in a product, you *must* keep these 17 | * copyright strings in the executable of your product. 18 | */ 19 | const unsigned kb_version_id = KB_VERSION_ID; 20 | const char kb_version_string[] = KB_VERSION_STRING; 21 | const char kb_version_date[] = KB_VERSION_DATE; 22 | const char kb_copyright[] = 23 | "\n\n\n" 24 | "libkb -- a free, advanced and portable low-level keyboard library\n" 25 | "Copyright (C) 1995-1998 Markus Franz Xaver Johannes Oberhumer\n" 26 | "\n" 27 | "\n" 28 | "libkb version: v" KB_VERSION_STRING ", " KB_VERSION_DATE "\n" 29 | "libkb build date: " __DATE__ " " __TIME__ "\n" "\n\n"; 30 | 31 | /* Once again (17 Jan 1996) the Linux kernel sources have stopped 32 | * me from making things too complicate. As this is a keyboard 33 | * library and not a re-write of an operating system, I have 34 | * simplified the tables to suit the basic needs. 35 | * There are 4 tables that are set up for American keyboards. 36 | * If you really want to do use local key mappings while the 37 | * keyboard handler is active, use kb_keypress() and 38 | * convert the code yourself. 39 | */ 40 | 41 | #if !defined(_kb_plain_table) 42 | unsigned short _kb_plain_table[128]; 43 | #endif 44 | #if !defined(_kb_shift_table) 45 | unsigned short _kb_shift_table[128]; 46 | #endif 47 | #if !defined(_kb_control_table) 48 | unsigned short _kb_control_table[128]; 49 | #endif 50 | #if !defined(_kb_alt_table) 51 | unsigned short _kb_alt_table[128]; 52 | #endif 53 | 54 | /*********************************************************************** 55 | // convert kb_keypress() to a keycode 56 | // 57 | // see comments for keycode() in mktables.c 58 | ************************************************************************/ 59 | 60 | unsigned kb_keycode(unsigned k) { 61 | unsigned scan = k & 0x7f; 62 | 63 | if (KB_ANY_MASK(k, KB_SHIFT_ANY_ALT << 8)) 64 | return _kb_alt_table[scan]; 65 | else if (KB_ANY_MASK(k, KB_SHIFT_ANY_CONTROL << 8)) 66 | return _kb_control_table[scan]; 67 | else if (KB_ANY_MASK(k, KB_SHIFT_ANY_SHIFT << 8)) 68 | return _kb_shift_table[scan]; 69 | else 70 | return _kb_plain_table[scan]; 71 | } 72 | 73 | /*********************************************************************** 74 | // 75 | ************************************************************************/ 76 | 77 | static unsigned long kb_inkey_keycode(unsigned key) { 78 | if (key) 79 | return kb_keycode(key) | ((unsigned long)key << 16); 80 | else 81 | return 0; 82 | } 83 | 84 | static unsigned kb_getkey_keycode(unsigned key) { 85 | if (key) 86 | return kb_keycode(key); 87 | else 88 | return 0; 89 | } 90 | 91 | /*********************************************************************** 92 | // 93 | ************************************************************************/ 94 | 95 | unsigned long kb_inkey(void) { 96 | unsigned key; 97 | unsigned long code; 98 | 99 | if (!_kb_mode) 100 | return kb_os_getkey(); 101 | while ((key = kb_keypress()) != 0) { 102 | code = kb_inkey_keycode(key); 103 | if (code != 0) 104 | return code; 105 | } 106 | return 0; 107 | } 108 | 109 | unsigned long kb_inkey_i(void) { 110 | unsigned key; 111 | unsigned long code; 112 | 113 | if (!_kb_mode) 114 | return kb_os_getkey(); 115 | while ((key = kb_keypress_i()) != 0) { 116 | code = kb_inkey_keycode(key); 117 | if (code != 0) 118 | return code; 119 | } 120 | return 0; 121 | } 122 | 123 | unsigned kb_getkey(void) { 124 | unsigned key, code; 125 | 126 | if (!_kb_mode) 127 | return kb_os_getkey(); 128 | while ((key = kb_keypress()) != 0) { 129 | code = kb_getkey_keycode(key); 130 | if (code != 0) 131 | return code; 132 | } 133 | return 0; 134 | } 135 | 136 | unsigned kb_getkey_i(void) { 137 | unsigned key, code; 138 | 139 | if (!_kb_mode) 140 | return kb_os_getkey(); 141 | while ((key = kb_keypress_i()) != 0) { 142 | code = kb_getkey_keycode(key); 143 | if (code != 0) 144 | return code; 145 | } 146 | return 0; 147 | } 148 | 149 | unsigned kb_waitkey(void) { 150 | if (!_kb_mode) 151 | return kb_os_waitkey(); 152 | 153 | while (!kb_kbhit()) 154 | _kb_usleep(1024); 155 | return kb_getkey(); 156 | } 157 | 158 | unsigned kb_waitkey_i(void) { 159 | if (!_kb_mode) 160 | return kb_os_waitkey(); 161 | 162 | while (!kb_kbhit_i()) 163 | _kb_usleep(1024); 164 | return kb_getkey_i(); 165 | } 166 | 167 | /*********************************************************************** 168 | // kb_keycode, kb_bios_keycode and kb_os_keycode should return 169 | // the same values - and this on all platforms 170 | ************************************************************************/ 171 | 172 | /* convert a BIOS keycode */ 173 | /* see: djgpp1/libsrc/c/dos/getkey.s */ 174 | /* see: djgpp2/src/libc/pc_hw/kb */ 175 | 176 | unsigned kb_bios_keycode(unsigned k) { 177 | unsigned key = k & 0xff; 178 | unsigned x = (k >> 8) & 0xff; 179 | 180 | if (key == 0) 181 | key = 0x100 | x; 182 | else if (key == 0xe0 && x != 0) 183 | key = 0x200 | x; 184 | 185 | return key; 186 | } 187 | 188 | /* convert a getch() keycode */ 189 | unsigned kb_os_keycode(unsigned k1, unsigned k2) { 190 | if (k2 == 0) 191 | return k1; 192 | 193 | /* we cannot distinguish between keypad and cursor keys, 194 | * so let's assume cursor keys */ 195 | if (k2 >= KB_SCAN_7_PAD && k2 <= KB_SCAN_PERIOD_PAD && _kb_prefix_scancode[k2]) 196 | k2 |= 0x200; 197 | else 198 | k2 |= 0x100; 199 | 200 | return k2; 201 | } 202 | 203 | /*********************************************************************** 204 | // 205 | ************************************************************************/ 206 | 207 | void _kb_init_tables(void) { 208 | #if !defined(_kb_plain_table) 209 | memcpy(_kb_plain_table, default_plain_table, sizeof(_kb_plain_table)); 210 | #endif 211 | #if !defined(_kb_shift_table) 212 | memcpy(_kb_shift_table, default_shift_table, sizeof(_kb_shift_table)); 213 | #endif 214 | #if !defined(_kb_control_table) 215 | memcpy(_kb_control_table, default_control_table, sizeof(_kb_control_table)); 216 | #endif 217 | #if !defined(_kb_alt_table) 218 | memcpy(_kb_alt_table, default_alt_table, sizeof(_kb_alt_table)); 219 | #endif 220 | } 221 | 222 | /*********************************************************************** 223 | // 224 | ************************************************************************/ 225 | 226 | const char *kb_keyname(int scan) { 227 | return _kb_key_name[scan & 0x7f]; 228 | } 229 | 230 | /*********************************************************************** 231 | // locking 232 | ************************************************************************/ 233 | 234 | #if defined(KB_LOCK_ALL_END) 235 | KB_LOCK_ALL_END(_libkb_kbtables) 236 | #endif 237 | int _libkb_kbtables_lock(void) { 238 | int x = 0; 239 | 240 | #if defined(KB_LOCK_ALL) 241 | KB_LOCK_ALL(_libkb_kbtables, x); 242 | #endif 243 | 244 | return x; 245 | } 246 | 247 | /* 248 | vi:ts=4 249 | */ 250 | -------------------------------------------------------------------------------- /src/splash.c: -------------------------------------------------------------------------------- 1 | #include "dge.h" 2 | #include "dge_gfx.h" 3 | #include "dge_bmp.h" 4 | 5 | void render(); 6 | 7 | BITMAP bmp_logo; 8 | BITMAP bmp_rocket; 9 | 10 | 11 | int rocketx, rockety; 12 | byte bgcolor = 0; 13 | 14 | void main(int argc, char *argv[]) { 15 | 16 | int i, x, y; 17 | 18 | load_bmp("res/images/dge_lbig.bmp", &bmp_logo); 19 | load_bmp("res/images/rocket.bmp", &bmp_rocket); 20 | 21 | // dge_init(BIOS, 320, 200); 22 | // dge_init(MEMMAP, 320, 200); 23 | dge_init(DOUBLEBUFF, 320, 200); 24 | 25 | set_palette(bmp_logo.palette); 26 | 27 | rocketx=(screen_width/2)-(bmp_rocket.width/2); 28 | rockety=(screen_height/2)-(bmp_rocket.height/2); 29 | 30 | 31 | while (true) { 32 | render(); 33 | if (getchar()) { 34 | dge_shutdown(); 35 | exit(1); 36 | } 37 | } 38 | 39 | dge_shutdown(); 40 | 41 | } 42 | 43 | void render() { 44 | 45 | graphics_begin(); 46 | 47 | clear_screen(bgcolor); 48 | //bgcolor++; 49 | 50 | draw_transparent_bitmap(&bmp_logo, 0, 0); 51 | 52 | draw_transparent_bitmap(&bmp_rocket, rocketx, rockety); 53 | 54 | graphics_end(); 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/test_gfx.c: -------------------------------------------------------------------------------- 1 | #include "dge.h" 2 | #include "dge_gfx.h" 3 | 4 | void runAllTests(enum RENDER_MODE mode); 5 | void screenBreaker(enum RENDER_MODE mode); 6 | void runPixelTest(enum RENDER_MODE mode); 7 | void runLineTest(enum RENDER_MODE mode); 8 | void runRectTest(enum RENDER_MODE mode); 9 | void runRectFillTest(enum RENDER_MODE mode); 10 | void runPolyTest(enum RENDER_MODE mode, bool fill); 11 | void runCircleTest(enum RENDER_MODE mode, bool fill); 12 | 13 | void fontColorTest(); 14 | 15 | float sleep_time = 0; 16 | long object_count = 200L; 17 | 18 | void main(int argc, char *argv[]) { 19 | 20 | enum RENDER_MODE mode; 21 | int count = 0; 22 | int i = 30; 23 | int y = 0; 24 | 25 | mode = DOUBLEBUFF; 26 | //mode = MEMMAP; 27 | 28 | continuous_rendering = true; 29 | vsync = true; 30 | show_fps=true; 31 | 32 | dge_init(mode, 320, 200); 33 | 34 | while (1) { 35 | runAllTests(mode); 36 | 37 | 38 | } 39 | 40 | dge_shutdown(); 41 | 42 | return; 43 | } 44 | 45 | void runAllTests(enum RENDER_MODE mode) { 46 | 47 | runPixelTest(mode); 48 | sleep(sleep_time); 49 | 50 | runLineTest(mode); 51 | sleep(sleep_time); 52 | 53 | runRectTest(mode); 54 | sleep(sleep_time); 55 | 56 | runRectFillTest(mode); 57 | sleep(sleep_time); 58 | 59 | runPolyTest(mode, false); 60 | sleep(sleep_time); 61 | 62 | runPolyTest(mode, true); 63 | sleep(sleep_time); 64 | 65 | runCircleTest(mode, false); 66 | sleep(sleep_time); 67 | 68 | runCircleTest(mode, true); 69 | sleep(sleep_time); 70 | 71 | screenBreaker(mode); 72 | sleep(sleep_time); 73 | 74 | } 75 | 76 | void screenBreaker(enum RENDER_MODE mode) { 77 | 78 | //dge_init(mode, 320, 200); 79 | graphics_begin(); 80 | 81 | draw_pixel(-1, -1, 128); 82 | draw_pixel(screen_width + 1, screen_height + 1, 128); 83 | 84 | draw_line(-1, -1, -1, -1, 128); 85 | draw_line(0, 0, screen_width + 1, screen_height + 1, 128); 86 | 87 | draw_circle(-1, -1, 100, 128); 88 | fill_circle(-1, -1, 100, 128); 89 | 90 | graphics_end(); 91 | } 92 | 93 | void runPixelTest(enum RENDER_MODE mode) { 94 | 95 | int x, y, color; 96 | float time; 97 | word i, start; 98 | 99 | //dge_init(mode, 320, 200); 100 | graphics_begin(); 101 | 102 | srand(*my_clock); 103 | start = *my_clock; 104 | 105 | for (i = 0; i < object_count; i++) { 106 | x = rand() % screen_width; 107 | y = rand() % screen_height; 108 | color = rand() % num_colors; 109 | draw_pixel(x, y, color); 110 | } 111 | 112 | graphics_end(); 113 | 114 | time = (*my_clock - start) / 18.2; 115 | 116 | } 117 | 118 | void runLineTest(enum RENDER_MODE mode) { 119 | 120 | int x1, y1, x2, y2, color; 121 | float time; 122 | word i, start; 123 | 124 | //dge_init(mode, 320, 200); 125 | graphics_begin(); 126 | 127 | srand(*my_clock); 128 | start = *my_clock; 129 | for (i = 0; i < object_count; i++) { 130 | 131 | x1 = rand() % screen_width; 132 | y1 = rand() % screen_height; 133 | x2 = rand() % screen_width; 134 | y2 = rand() % screen_height; 135 | color = rand() % num_colors; 136 | draw_line(x1, y1, x2, y2, color); 137 | } 138 | 139 | graphics_end(); 140 | 141 | time = (*my_clock - start) / 18.2; 142 | } 143 | 144 | void runRectTest(enum RENDER_MODE mode) { 145 | 146 | int x1, y1, x2, y2, color; 147 | float time; 148 | word i, start; 149 | 150 | //dge_init(mode, 320, 200); 151 | graphics_begin(); 152 | 153 | srand(*my_clock); 154 | start = *my_clock; 155 | 156 | for (i = 0; i < object_count; i++) { 157 | 158 | x1 = rand() % screen_width; 159 | y1 = rand() % screen_height; 160 | x2 = rand() % screen_width; 161 | y2 = rand() % screen_height; 162 | color = rand() % num_colors; 163 | 164 | draw_rect(x1, y1, x2, y2, color); 165 | } 166 | 167 | graphics_end(); 168 | 169 | time = (*my_clock - start) / 18.2; 170 | 171 | } 172 | 173 | void runRectFillTest(enum RENDER_MODE mode) { 174 | 175 | int x1, y1, x2, y2, color; 176 | float time; 177 | word i, start; 178 | 179 | //dge_init(mode, 320, 200); 180 | graphics_begin(); 181 | 182 | srand(*my_clock); 183 | start = *my_clock; 184 | 185 | for (i = 0; i < object_count; i++) { 186 | 187 | x1 = rand() % screen_width; 188 | y1 = rand() % screen_height; 189 | x2 = rand() % screen_width; 190 | y2 = rand() % screen_height; 191 | color = rand() % num_colors; 192 | 193 | fill_rect(x1, y1, x2, y2, color); 194 | } 195 | 196 | graphics_end(); 197 | 198 | time = (*my_clock - start) / 18.2; 199 | } 200 | 201 | void runPolyTest(enum RENDER_MODE mode, bool fill) { 202 | 203 | int x1, y1, x2, y2, x3, y3, color; 204 | float time; 205 | word i, start; 206 | int vertices[6]; 207 | 208 | //dge_init(mode, 320, 200); 209 | graphics_begin(); 210 | 211 | srand(*my_clock); 212 | start = *my_clock; 213 | 214 | for (i = 0; i < object_count; i++) { 215 | 216 | vertices[0] = rand() % screen_width; 217 | vertices[1] = rand() % screen_height; 218 | 219 | vertices[2] = rand() % screen_width; 220 | vertices[3] = rand() % screen_height; 221 | 222 | vertices[4] = rand() % screen_width; 223 | vertices[5] = rand() % screen_height; 224 | 225 | color = rand() % num_colors; 226 | 227 | if (fill) { 228 | draw_polygon(3, vertices, color); 229 | } else { 230 | fill_polygon(3, vertices, color); 231 | } 232 | 233 | } 234 | 235 | graphics_end(); 236 | 237 | time = (*my_clock - start) / 18.2; 238 | } 239 | 240 | void runCircleTest(enum RENDER_MODE mode, bool fill) { 241 | 242 | int x, y, radius, color; 243 | float time; 244 | word i, start; 245 | 246 | //dge_init(mode, 320, 200); 247 | graphics_begin(); 248 | 249 | srand(*my_clock); 250 | start = *my_clock; 251 | 252 | for (i = 0; i < object_count; i++) { 253 | radius = rand() % 90 + 1; 254 | x = rand() % (screen_width - radius * 2) + radius; 255 | y = rand() % (screen_height - radius * 2) + radius; 256 | color = rand() % num_colors; 257 | if (fill) { 258 | fill_circle(x, y, radius, color); 259 | } else { 260 | draw_circle(x, y, radius, color); 261 | } 262 | } 263 | 264 | graphics_end(); 265 | 266 | time = (*my_clock - start) / 18.2; 267 | 268 | } 269 | 270 | void fontColorTest() { 271 | 272 | graphics_begin(); 273 | 274 | 275 | print_text( 5, 5, PFC_RED, "PFC_RED"); 276 | print_text( 5, 6, PFC_LIGHTGREEN, "PFC_LIGHTGREEN"); 277 | print_text( 5, 7, PFC_YELLOW, "PFC_YELLOW"); 278 | print_text( 5, 8, PFC_PURPLE, "PFC_PURPLE"); 279 | print_text( 5, 9, PFC_BOLDPINK, "PFC_BOLDPINK"); 280 | print_text( 5, 10, PFC_LBLUE, "PFC_LBLUE"); 281 | print_text( 5, 11, PFC_WHITE, "PFC_WHITE"); 282 | print_text( 5, 12, PFC_GREEN, "PFC_GREEN"); 283 | print_text( 5, 13, PFC_BRICKRED, "PFC_BRICKRED"); 284 | print_text( 5, 14, PFC_LIME, "PFC_LIME"); 285 | print_text( 5, 15, PFC_PINK, "PFC_PINK"); 286 | print_text( 5, 16, PFC_BLUE, "PFC_BLUE"); 287 | 288 | 289 | graphics_end(); 290 | 291 | } 292 | -------------------------------------------------------------------------------- /src/test_snd.c: -------------------------------------------------------------------------------- 1 | #include "dge.h" 2 | #include "dge_gfx.h" 3 | #include "dge_snd.h" 4 | 5 | int note = 0; 6 | bool direction = true; 7 | void test_song(); 8 | void random_song(); 9 | void up_song(); 10 | 11 | void main(int argc, char *argv[]) { 12 | 13 | 14 | enum RENDER_MODE mode=DOUBLEBUFF; 15 | 16 | dge_init(mode, 320, 200); 17 | 18 | 19 | while (true) { 20 | graphics_begin(); 21 | 22 | //testt_song(); 23 | //random_song(); 24 | 25 | up_song(); 26 | 27 | graphics_end(); 28 | } 29 | 30 | sleep(1); 31 | dge_shutdown(); 32 | 33 | } 34 | 35 | 36 | void test_song() { 37 | 38 | int i=0; 39 | int j=0; 40 | 41 | for (j=0; i<2; j++) { 42 | 43 | for (i=0; i<8; i++) { 44 | 45 | pc_sound(20); 46 | delay(25); 47 | // nosound(); 48 | 49 | delay(50); 50 | pc_sound(note); 51 | delay(50); 52 | note++; 53 | } 54 | 55 | pc_sound(20); 56 | delay(200); 57 | //nosound(); 58 | delay(100); 59 | pc_sound(20); 60 | delay(200); 61 | 62 | pc_sound(note); 63 | delay(50); 64 | note++; 65 | } 66 | 67 | pc_sound(note%500); 68 | delay(100); 69 | 70 | pc_sound(2500); 71 | delay(100); 72 | //nosound(); 73 | 74 | pc_sound(note); 75 | delay(50); 76 | 77 | note+=20; 78 | if(note>4000) { 79 | note=0; 80 | } 81 | 82 | } 83 | 84 | void random_song() { 85 | pc_sound(rand()%4000); 86 | } 87 | 88 | 89 | void up_song() { 90 | 91 | char text[50]; 92 | 93 | if (note >= 500) { 94 | direction = false; 95 | } 96 | if (note <= 0) { 97 | direction = true; 98 | } 99 | 100 | if (direction) { 101 | note++; 102 | print_text(8, 8, PFC_LBLUE, "UP UP UP"); 103 | } else { 104 | note--; 105 | print_text(12, 12, PFC_BLUE, "DROP THE BASS"); 106 | } 107 | 108 | sprintf(text, "Direction : %d NOTE: %d", direction, note); 109 | print_text(10, 10, PFC_PURPLE, text); 110 | 111 | 112 | pc_sound(note); 113 | } 114 | -------------------------------------------------------------------------------- /src/tst_inpt.c: -------------------------------------------------------------------------------- 1 | #include "dge.h" 2 | #include "dge_gfx.h" 3 | #include "dge_snd.h" 4 | #include "dge_inpt.h" 5 | 6 | #include "libkb/kb.h" 7 | 8 | 9 | #define KEY_UP KB_SCAN_W 10 | #define KEY_DOWN KB_SCAN_S 11 | #define KEY_LEFT KB_SCAN_A 12 | #define KEY_RIGHT KB_SCAN_D 13 | 14 | int main() { 15 | 16 | enum RENDER_MODE mode = DOUBLEBUFF; 17 | float x, y; 18 | int ix, iy; 19 | int i=0; 20 | int ii=0; 21 | int xs[100]; 22 | int ys[100]; 23 | char key; 24 | int value=0; 25 | 26 | // pixels per second 27 | int speed = 100; 28 | int half_size = 20; 29 | byte color = 0; 30 | 31 | char coords_text[50]; 32 | 33 | for (i=0; i<100; i++) { 34 | xs[i] = 0; 35 | ys[i] = 0; 36 | } 37 | 38 | continuous_rendering = false; 39 | vsync = true; 40 | show_fps=true; 41 | 42 | dge_init(mode, 320, 200); 43 | 44 | x = screen_width/2; 45 | y = screen_height/2; 46 | 47 | 48 | 49 | 50 | while (1) { 51 | 52 | kb_update(); 53 | if (kb_kbhit()) { 54 | key = kb_getkey(); 55 | 56 | if (key == 'i') { 57 | value++; 58 | } 59 | if (key == 'k') { 60 | value--; 61 | } 62 | 63 | } 64 | 65 | char key = kb_keycode(kb_last_key()); 66 | //printf("C:%c", key); 67 | fflush(NULL); 68 | 69 | 70 | if (key_pressed(KEY_UP)) { 71 | y = y + -(delta * speed); 72 | } 73 | if (key_pressed (KEY_DOWN)) { 74 | y = y + (delta * speed); 75 | } 76 | 77 | if (key_pressed(KEY_LEFT)) { 78 | x = x + -(delta * speed); 79 | } 80 | 81 | if (key_pressed(KEY_RIGHT)) { 82 | x = x + (delta * speed); 83 | } 84 | 85 | x = MAX(0+half_size, x); 86 | x = MIN(screen_width-half_size, x); 87 | 88 | y = MAX(0+half_size, y); 89 | y = MIN(screen_height-half_size, y); 90 | 91 | ix=round(x); 92 | iy=round(y); 93 | 94 | graphics_begin(); 95 | 96 | xs[ii] = ix; 97 | ys[ii] = iy; 98 | for (i=0;i<100; i++) { 99 | if (xs[i] != 0) { 100 | /* 101 | draw_rect(xs[i]-half_size, ys[i]-half_size, xs[i]+half_size-1, ys[i]+half_size-1, color); 102 | draw_line(xs[i], ys[i], ix, iy, color+1); 103 | draw_line(xs[i]-half_size, ys[i]-half_size, ix, iy, color+9); 104 | draw_line(xs[i]+half_size, ys[i]+half_size, ix, iy, color+9); 105 | draw_line(xs[i], ys[i]+half_size, ix, iy, color+9); 106 | draw_line(xs[i]+half_size, ys[i], ix, iy, color+9); 107 | draw_line(xs[i], ys[i]-half_size, ix, iy, color+9); 108 | draw_line(xs[i]-half_size, ys[i], ix, iy, color+9); 109 | */ 110 | } 111 | } 112 | 113 | print_text(1,4, PFC_GREEN, BUILD_TYPE); 114 | 115 | sprintf(coords_text, "[%.2fx%.2f]", x, y); 116 | print_text(1,5, PFC_GREEN, coords_text); 117 | 118 | sprintf(coords_text, "[%dx%d]", ix, iy); 119 | print_text(1,6, PFC_RED, coords_text); 120 | 121 | fill_rect(ix-half_size, iy-half_size, ix+half_size-1, iy+half_size-1, color); 122 | 123 | draw_rect(ix-half_size, iy-half_size, ix+half_size-1, iy+half_size-1, 2); 124 | 125 | draw_line(0,0, ix, iy, color); 126 | draw_line(screen_width, 0, ix, iy, color); 127 | draw_line(screen_width, screen_height, ix, iy, color); 128 | draw_line(0, screen_height, ix, iy, color); 129 | 130 | graphics_end(); 131 | 132 | sprintf(coords_text, "Value: %d", value); 133 | print_text(2,10, PFC_WHITE, coords_text); 134 | 135 | 136 | color++; 137 | ii++; 138 | if (ii>99) { 139 | ii=0; 140 | } 141 | 142 | 143 | } 144 | 145 | 146 | dge_shutdown(); 147 | return 0; 148 | } 149 | -------------------------------------------------------------------------------- /todo.txt: -------------------------------------------------------------------------------- 1 | 2 | Build 3 | build under bcc 4 | 5 | Graphics 6 | allow differant modes 7 | save orignal palette 8 | animations 9 | xmode/unchained. 10 | 11 | Input 12 | keyboard input 13 | mouse input 14 | 15 | Sound 16 | soundblaster 17 | 18 | Other 19 | add build type 20 | add splash screen 21 | 22 | Config 23 | Readable config 24 | Setup menu/Writeable config. 25 | 26 | bugs: 27 | rect draw 1 pixel to wide on right and bottom? 28 | 29 | DONE 30 | Add mclock variable/macro 31 | pc speaker 32 | clean up all warnings. 33 | load and display bitmaps 34 | build under tcc 35 | build under djgpp 36 | 37 | 38 | --------------------------------------------------------------------------------