diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..0ff422a --- /dev/null +++ b/AUTHORS @@ -0,0 +1,4 @@ + +Eddie C. Dost -- Original Author + +G. Allen Morris III -- Maintainer diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..b9e3f85 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,40 @@ +2011-08-08 "G. Allen Morris III" release 0.6.4 + * Default to throttling speed only when key-pressed + * Add throttle switch for speed emulation + * Fix buffer overflow bug + * release keys on loss of focus + * typo in access_time adjust + +2010-02-01 "G. Allen Morris III" release 0.6.3 + * made updates to x48.spec + * put debian directory in dist file + * install X48 app data in correct place + using pkg-config appdefaultdir xt + * removed more debugging messages + * added 'netbook' look for small/short screens + use +netbook on the command line + +2010-01-30 "G. Allen Morris III" release 0.6.2 + * remove setlocal code that was causing a bug. + * removed some debugging code. + +2009-06-31 "G. Allen Morris III" release 0.6.1 + * Fix to XShm to solve the 'LCD' Scramble problem. + +2006-04-20 "G. Allen Morris III" + * Added simple paste feature + * Repaired debugger non-readline input + * Changed from building with Imakefile to using GNU autoconfig + +2005-03-20 "G. Allen Morris III" + * added equal key for + and Meta Keys for Alpha + * applied a different fix for the arrow repeat key bug + * fixed a bug in the timer one logic. The cursor now flashes on input. + +2005-03-20 "G. Allen Morris III" + * added patch [000390] time.h compile bug + * added patch [000391] Arrow key repeat patch + * added ChangeLog file + +2005-03-18 "G. Allen Morris III" + * starting from x48 0.4.0. diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..7c3fad5 --- /dev/null +++ b/INSTALL @@ -0,0 +1,9 @@ + +You will only need readline support if you are planning to use the +x48 debugger. So ignore + + With ReadLine sup. in Debuger? no + +unless you want readline support in the x48 debugger. + + diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..d8c1576 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,75 @@ +README +Imakefile +config.h +MANIFEST +ChangeLog +utils/Imakefile +utils/ad2c +utils/makeversion +src/Imakefile +src/X48.ad +src/actions.c +src/debugger.c +src/device.c +src/disasm.c +src/emulate.c +src/init.c +src/lcd.c +src/main.c +src/memory.c +src/options.c +src/register.c +src/resources.c +src/rpl.c +src/serial.c +src/timer.c +src/x48_x11.c +src/dump2rom.c +src/checkrom.c +src/annunc.h +src/append.h +src/buttons.h +src/constants.h +src/debugger.h +src/defaults.h +src/device.h +src/disasm.h +src/global.h +src/hp.h +src/hp48.h +src/hp48_emu.h +src/hp48char.h +src/icon.h +src/options.h +src/resources.h +src/rpl.h +src/small.h +src/timer.h +src/version.h +src/x48.man +src/x48_x11.h +romdump/Imakefile +romdump/ROMDump +romdump/README +romdump/ReadRom.s +romdump/Dump +doc/Imakefile +doc/ChangeLog +doc/COPYING +doc/INSTALLING +doc/TODO +doc/CARDS.doc +doc/ROMDump.doc +rpm/x48.spec.in +rpm/x48.spec +debian/README.Debian +debian/changelog +debian/compat +debian/control +debian/copyright +debian/dirs +debian/docs +debian/menu +debian/quit +debian/rules +debian/watch diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..70335a4 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,17 @@ + + +AUTOMAKE_OPTIONS = dejagnu + +SUBDIRS = src romdump + +EXTRA_DIST=rpm/x48.spec \ + debian/changelog debian/compat debian/control debian/copyright \ + debian/dirs debian/docs debian/menu debian/README.Debian debian/rules + +X48 : src/X48.ad + cp $< $@ + +appdefault_DATA = X48 + +DISTCHECK_CONFIGURE_FLAGS = --with-appdefaultdir='$${datadir}/X11/app-defaults' + diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/NEWS @@ -0,0 +1 @@ + diff --git a/README b/README new file mode 100644 index 0000000..9af7f61 --- /dev/null +++ b/README @@ -0,0 +1,356 @@ +x48 -- HP48 CPU emulator +======================== + +This is x48, an HP48 CPU emulator. This is Version 0.6.1 + +if the 'LCD' is scrambled, you might try running x48 in one of the 3 ways below +to see if that will solve the problem. + +1. run 'x48 +shm' +2. put 'x48*useXShm: False' in you .Xdefaults file (man xrdb) +3. run './configure --disable-shm' to build x48 without the Shared memory extention. + +If it does please leave a bug report at https://developer.berlios.de/bugs/?group_id=3335 + +====== + +for version 0.4.0 + +What's new: + + - Implemented CONFIG/UNCNFG more exactly. + + - Added support for different RAM or ROM cards. + + - Added G/GX support (lost of changes) + new colors, new labels, ... + + - Rewrote ROMDump for both S/SX and G/GX. Lots faster now. + Thanks go to Robert Tiismus + + - Corrected handling of Display and Menu images, fixed number + of lines in init_display(), to avoid XShmError on virgin + startup + + - Catch SIGPIPE and save state, so everything is saved, when + x48 gets terminated by xkill or the window manager + + +NOTE (from EM48 README by Paul Fox) +=================================== + +This emulator is capable of providing a faithful replication of the +HP48. In order to do so, it requires a copy of the ROM software +from YOUR calculator. In order to avoid breaking copyright laws, +and upsetting HP, you MUST BE THE PROUD OWNER OF AN HP48 before +running this program. Of course you can run this program without a +copy of the ROM software in order to write trivial machine code +programs but you will not be able to access any of the calculator +functionality. + +Instructions on how to download a copy of the ROM are provided +later in this document. + + +CREDITS +======= + + +I would like to thank Robert Tiismus +for his help with ROMDump for the G/GX. The ROMDump utility gained +a lot of speed and works for both S/SX and G/GX now. + + +I used SADHP to disassemble parts of the 48's ROM and some other +programs to test x48, also I very closely looked at SADHP while +writing code for RPL debugging. So here go sincere thanks: + +-- Jan Brittenson +-- Mika Heiskanen + +Latest version of SADHP is available from + wuarchive.wust.edu:/systems/hp/hp48Uploads/ +Get it to look deeper into your HP48. + + +I would like to thank Lutz Vieweg for his +outstanding bug reports. Must be the crazyness of porting gcc to +the 48, and of writing code in assembler, that digs out all the +bugs in x48. Go on like this Lutz. + + +I must thank Joe Ervin for his article on keyboard handling. + + +I also must thank Paul Fox, Author of EM48, for his work on his +emulator, the source code was a great help for solving some problems, +specially the memory bank switching. Thanks Paul. + + +I would also like to thank Alonzo Gariepy for his contribution to +the world on how the HP28/HP48 works. + + +I would sincerely like to ask HP about giving me a 48 GX, so the world +could receive more complete x48, also I could use some ROM cards, like +the EQ-LIB to implement an easy use of these. Well, I credited HP in +the last releases, but now x48 really gets running and I still haven't +heard a word from them... +Just remember, x48 comes under the terms and conditions of the GPL. + + +HACKERS PLEA +============ + +I will continue to work on this product and support it where I have +the time, and would therefore appreciate any patches or bug fixes, +etc which any of you make so that I can keep control of the software. + +Information in the form of loose english, context diffs, or +suggestions are welcome so that we can all make this product a +little better. + + +INSTALLATION +============ + +I improved handling of differences in Solaris, SunOS, HP/UX, and Linux. +Things are not perfect, anyway. + +To configure some things for the Makefiles, edit 'config.h' in the +directory 'x48-0.4.0'. There you can set the compiler, flags to +pass to the compiler, and some other stuff. + +To build the emulator do the following in the directory 'x48-0.4.0': + + 1. xmkmf + 2. make + +This should give you the programs 'x48', 'dump2rom', 'checkrom', and +'mkcard' in the directory 'x48-0.4.0/bin'. + +To get the serial line working, you should set up your .Xdefaults for +x48. The resources concerning the serial line are: + +x48*useSerial: True +x48*serialLine: /dev/ttyS0 ; your serial device here, this + ; looks good for Linux. + +Run 'x48 -help' for a list of command line options. + +Look at 'x48-0.4.0/src/X48.ad' for the whole set of Xresources the +program uses. + + +HOW TO DOWNLOAD A COPY OF THE ROM +================================= + +The emulator works by executing an image of the HP48s ROM. In order +to run the emulator you must have a version of your ROM on the system. + +********************************************************************** +* This includes the HIDDEN ROM. Please don't use DUMP programs, that * +* don't dump the HIDDEN ROM. The emulator won't run. * +********************************************************************** + + +To get a memory dump you need to do the following: + + +- Download the file 'romdump/ROMDump' to your HP. + +- To capture a complete ROM, start kermit on your computer, set the + line so it fits your HP, set the speed to 9600 baud and type + 'log session', then 'connect'. + +- On a HP48 S/SX type '#0h #7FFFFh ROMDump', + on a HP48 G/GX type '#0h #FFFFFh ROMDump'. + This will take about 15 minutes on the S/SX, 30 minutes on the G/GX. + +- When done, type the kermit-Escape (usually CTRL-\) followed + by 'C' on your Computer. Say 'quit' to the kermit. + +Your ROM should now be in the file 'session.log'. + + + +Now you have a file containing lines like + +#00000:2369B108DADF1008 +... + +This has to be converted to a binary ROM for x48. + +Run the command: `dump2rom session.log` +This will convert your dump into a rom file readable by the emulator +called 'rom.dump'. + +CHECK the file with the program 'checkrom'. +Type: `checkrom rom.dump`. It should say: + + ROM Version is HP48-A + ROM CRC reads 0xcb76 (for Rev. A, will be different for other ROMs) + IROM OK: ROM CRC test passed. + +or + + ROM Version is HP48-R + ROM CRC 1 reads 0xdfed (for Rev. R, will be different for other ROMs) + ROM CRC 2 reads 0xf0b1 ( --- " --- ) + IROM OK: ROM CRC test passed. + +If the test failed, something went wrong transfering the ROM. Don't +start thinking about the size or the nibbles in 'rom.dump'. That's +all correct. Do the Transfer again. + +If you know how to do it, you could of course only transfer the +'broken' part of the dump, using e.g. '#60000h #60080h ROMDump' +and fix these lines in 'session.log'. + + +USING THE EMULATOR +================== + +Go into the directory, where your ROM dump resides and type 'x48', or +type 'x48 -rom ', where is the file containing your +ROM dump. + +On the first start the emulator will read the ROM dump. +It will start running at the addr 00000. This will result in the +question 'Try to recover memory?' Answer 'NO'. + +To use the emulator, click your mouse at the buttons +on the emulator. You have to press the button down long enough, so +the HP-48 will considder it a keypress. Well, this should work. + +To do something like ON-E, or ON-A-F, one would use the middle mouse +button to press ON, then the middle mouse button to press A. These +keys should stay depressed. Now use the left mouse button to press F. +This should release all three keys and yield the desired results. + +You can check your ROM dump by pressing ON-E. This enters the selftest +of the HP-48. If it says IROM OK after some time, your ROM CRC has +been calculated correctly. + +The SX emulator has 32K RAM and two 128K RAM cards, both read/write. +To access all memory you have to do: 1 MERGE 2 MERGE +The GX emulator has 128K RAM and no RAM cards, yet. +To access all memory you have to do: 1 MERGE 2 MERGE + +When you hit the 'quit' button of the window frame (under ol(v)wm), +the emulator saves its state, RAM, ROM, and the ports to files in +the directory '$HOME/.hp48/', so the next time it is started, all +your stuff should be still there. + +If the emulator gets messed up, or crashes, enter the debugger +by typing CTRL-C in the shell you started x48. At the prompt type +`reset`, confirm with `y`. Then type `cont`. + +If this does not help, enter the debugger again, and type +`exit`, confirm with `y`. This will NOT save the stuff, so the next +time you use x48, it should be in the same state as on the last run. + +Another way to achive this, is to send SIGTERM or SIGKILL to x48. + + +USING RAM CARDS +=============== + +To get a RAM card, use the program 'mkcard' to build the card, and +copy the resulting file to $HOME/.hp48/port1 or $HOME/.hp48/port2. +On the next start of the emulator, the card should be detected and +usable. (Maybe you have to turn it off, and on again...) + + +KEYBOARD SUPPORT +================ + +I have added simple keyboard support: + +The keys 'A' - 'Z', '0' - '9', '+', '-', '*', '/', 'RETURN', '.', 'SPACE', +'DELETE', and 'BACKSPACE' are mapped to the according keys on the HP-48's +keyboard. The SHIFT keys give you the Orange and Blue shifts. 'ALT' gives +you the `alpha' key, and 'ESC' the `ON' key. +The keys 'F1' - 'F2' also access the menu labels on the HP. The cursor keys +give you the HP-48 keys 'K', 'P', 'Q', and 'R'. + +Note that the key 'A' doesn't give you the letter "A" on the HP, but the +button in Row 1, Column 1 on the HP keyboard. The function executed depends +on the Shift State of the HP. + +To do something like 'ON-A-F', press and hold `ESC', then press and hold +`A', then press `F' and release all buttons. + + +TALKING TO THE OUTSIDE WORLD +============================ + +The emulator shows one line similar to: + + wire:/dev/ttyp2 IR:/dev/ttyS0 + +right below it's display. + +If you have a backup off your real HP-48 on your computer, you +could restore it using kermit: + +On the emulator enter the IO menu, hit SETUP, configure to + wire, binary, 9600, none, 1, 3. + +'wire' is the local computer connection, 'IR' talks to the serial +line of your computer. This is strange, but the other way around +it does not work, yet. + +Go to the IO menu again. Hit SERVER. The emulator says: + Awaiting Server Command + +On your computer take an unused xterm, go to the directory where +you keep your backups, and start kermit. Configure the line: + +type 'set line /dev/ttyp2' <---- use the number from the line + below the display !!! + +This should be the pseudo terminal connected to your emulator. + +At the kermit prompt type: 'send backup18.08.1994', or however your +backup was called. There should be communication going. + +After the transfer you should have a VAR 'backup18.08.1994'. Hit +the menu key for it. It says BackupHOMEDIR. Type RESTORE. That's +all. + + +Talking to the serial line, to e.g. another real HP-48 works the +same, just configure the IO to IR. + +!!! Note that the communcication speed is 2400 Baud here, + because the emulator, or better the HP48, thinks he is + doing IR transfer. + + +KNOWN BUGS +========== + +Very slow, especially the GX compared to a real GX. + +Lots of guesses in the devices section of the emulator. I could realy +use the 'SATURN HARDWARE SPECIFICATION' from HP. If anyone has access +to it, send a copy, or tell me where to get it. + +Documentation is missing. There should be a file 'x48.texinfo' to +describe the various options and flags of x48. + + +ACCESS TO THE AUTHOR +==================== + +Please send any bug reports, context-diffs or suggestions to + +ecd@dressler.de + +Eddie C. Dost +61, Rue de la Chapelle +4850 Moresnet-Chapelle +Belgium + +Have Fun. diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..2977411 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,9 @@ +#! /bin/sh + +set -x +aclocal +#libtoolize --force --copy +autoheader +automake --add-missing --copy -Wno-portability +autoconf + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..22818c3 --- /dev/null +++ b/configure.ac @@ -0,0 +1,139 @@ + +m4_include([version.m4]) +AC_INIT([x48],[VERSION_NUMBER],[x48-bugs@gam3.net]) + +AC_COPYRIGHT([Copyright (c) 2006-2010 G. Allen Morris III]) +AC_CANONICAL_TARGET + +AC_PREREQ(2.59) + +AC_CONFIG_SRCDIR([config.h.in]) +AC_CONFIG_HEADER([config.h]) + +# Checks for programs. +AC_PROG_CC +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_CPP + +AC_PATH_XTRA +if test x"$no_x" = xyes ; then + AC_MSG_ERROR([X development libraries not found]) +fi +X_LIBS="$X_LIBS -lX11" +AC_SUBST(X_LIBS) + +PKG_PROG_PKG_CONFIG([0.20]) + +# ********* readline library +AC_ARG_ENABLE(readline, + [ --disable-readline disable readline support], + [ if test x"$enableval" = xyes; then + with_readline="yes, check" + else + with_readline="no" + problem_readline=": Explicitly disabled" + fi ], + [ with_readline="not specified, check" ] +) + +AH_TEMPLATE([HAVE_READLINE],[Define if Readline is used.]) +if test x"$with_readline" != xno; then + AC_CHECK_LIB(readline, readline, + with_readline=yes; + LIBS="$LIBS -lreadline"; + AC_DEFINE(HAVE_READLINE), + with_readline=no; + problem_readline=": Can't detect readline library.", + []) + AC_CHECK_LIB(history, add_history) + AC_CHECK_HEADERS([readline/readline.h]) + AC_CHECK_HEADERS([readline/history.h]) +fi + +# ********* MIT Shared Memory Extension +AC_ARG_ENABLE(shm, + [ --disable-shm disable MIT Shared Memory Extension], + [ if test x"$enableval" = xyes; then + with_shm="yes, check" + else + with_shm="no" + problem_shm=": Explicitly disabled" + fi ], + [ with_shm="not specified, check" ] +) + +AH_TEMPLATE([HAVE_XSHM],[Define if MIT Shared Memory extension is used.]) +if test x"$with_shm" != xno; then +AC_CHECK_HEADER(X11/extensions/XShm.h, [ + AC_CHECK_LIB(Xext, XShmQueryExtension, + with_shm=yes; AC_DEFINE(HAVE_XSHM), + with_shm=no; + problem_shm=": Can't detect MIT Shared Memory ext.", + [$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS]) + ],problem_shm=": Can't detect MIT Shared Memory headers.",[#include ]) +fi +if test x"$with_shm" = xyes ; then +X_LIBS="$X_LIBS -lXext" +fi + +# Checks for libraries. +AC_CHECK_LIB([GL], [XCloseDisplay]) + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([fcntl.h memory.h stdlib.h string.h sys/ioctl.h sys/time.h termios.h unistd.h stdint.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_C_INLINE +AC_TYPE_SIZE_T +AC_HEADER_TIME +AC_STRUCT_TM + +AC_DEFINE([VERSION_MAJOR], _VERSION_MAJOR, [The major version number]) +AC_DEFINE([VERSION_MINOR], _VERSION_MINOR, [The minor version number]) +AC_DEFINE([PATCHLEVEL], _PATCHLEVEL, [The patch level]) + + +AC_DEFINE_UNQUOTED([COMPILE_TIME], "`date`", [Date program was compiled]) +AC_DEFINE([COMPILE_BY], ["G. Allen Morris III"], [Name of person that compiled this program]) +AC_DEFINE([COMPILE_VERSION], [0], [description]) + +# Checks for library functions. +AC_PROG_GCC_TRADITIONAL +AC_FUNC_MALLOC +AC_FUNC_SELECT_ARGTYPES +AC_FUNC_STAT +AC_CHECK_FUNCS([bzero gethostname gettimeofday memset mkdir select strdup strrchr uname]) + +PKG_CHECK_MODULES(APPDEFS, xt) +AC_ARG_WITH([appdefaultdir], + [AC_HELP_STRING([--with-appdefaultdir=DIR], + [Xt app-defaults directory (default: from pkg-config)])], + [appdefaultdir="$withval"], + [appdefaultdir=`$PKG_CONFIG --variable=appdefaultdir xt`]) +AC_SUBST(appdefaultdir) + +AM_INIT_AUTOMAKE + +AC_CONFIG_FILES([Makefile + romdump/Makefile + src/x48.man + rpm/x48.spec + src/Makefile]) +AC_OUTPUT + +echo " +X48 Configuration: + + Version: $VERSION$VERSIONINFO + + Executables: $bindir + Man pages: $mandir + + With ReadLine sup. in Debuger? $with_readline$problem_readline + With Shared memory for XImage? $with_shm$problem_shm + +# See INSTALL for the description of what this may mean." + diff --git a/debian/README.Debian b/debian/README.Debian new file mode 100644 index 0000000..bcb8285 --- /dev/null +++ b/debian/README.Debian @@ -0,0 +1,9 @@ +x48 for Debian +-------------- + +This program requires you to create a .hp48 directory in your home +directory, and put a rom dump into that directory. + +Rom dumps are available from http://developer.berlios.de/projects/x48/ + + -- G. Allen Morris III , Wed, 5 Jan 2005 14:54:21 -0500 diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..dd1518b --- /dev/null +++ b/debian/changelog @@ -0,0 +1,66 @@ +x48 (0.6.4) unstable; urgency=low + + * Default to throttling speed only when key-pressed + * Add throttle switch for speed emulation + * Fix buffer overflow bug + * release keys on loss of focus + * typo in access_time adjust + + -- G. Allen Morris III Tue, 09 Aug 2011 22:43:23 -0700 + +x48 (0.6.3) unstable; urgency=low + + * update to x48.spec + * put debian directory in dist file + * install X48 app data in correct place + using pkg-config appdefaultdir xt + * removed more debugging messages + + -- G. Allen Morris III Sat, 30 Jan 2010 18:16:00 -0500 + +x48 (0.6.2) unstable; urgency=low + * Remove some Local code that was causing bug 016244, 016778 + * Removed some debugging code + + -- G. Allen Morris III Sat, 30 Jan 2010 10:15:43 -0500 + +x48 (0.6.1) unstable; urgency=low + + * Cleaned up the configure.ac file + it now fails if X is missing and includes X11 and Xext in X_LIBS + * Applied patch for bug ID 015996 (berlios) this should solve the + scrambled 'LCD' problem. + + -- G. Allen Morris III Fri, 31 Jul 2009 22:32:55 -0400 + +x48 (0.6.0) unstable; urgency=low + + * Added simple paste feature + * Repaired debugger non-readline input + * Changed from building with Imakefile to using GNU autoconfig + + -- G. Allen Morris III Thu, 20 Apr 2006 08:09:01 -0400 + +x48 (0.4.3) unstable; urgency=low + + * Imporved mouse and refresh + + * Unix98 PTY (Preferred) + + * Fix to clock + + -- G. Allen Morris III Fri, 22 Apr 2005 13:00:14 -0400 + +x48 (0.4.2) unstable; urgency=low + + * Cursor Flashing + * Auto repeat on movement and del keys. + + -- G. Allen Morris III Fri, 22 Apr 2005 13:00:14 -0400 + +x48 (0.4.0) unstable; urgency=low + + * Initial Release. + + -- G. Allen Morris III Wed, 5 Jan 2005 14:54:21 -0500 + diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..abce6b3 --- /dev/null +++ b/debian/control @@ -0,0 +1,13 @@ +Source: x48 +Section: x11 +Priority: optional +Maintainer: G. Allen Morris III +Build-Depends: debhelper (>= 5.0.0), libx11-dev, libxext-dev, pkg-config, libxt-dev, autoconf +Standards-Version: 3.8.2 + +Package: x48 +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: a HP48 calculator emulator + This is an emulator of the HP 48 SX and GX calculator. + You will need a ROM dump to use it. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..6a996d6 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,27 @@ +This package was debianized by G. Allen Morris III on +Wed, 5 Jan 2005 14:54:21 -0500. + +It was downloaded from http://developer.berlios.de/projects/x48/ + +Copyright: 1994 Eddie C. Dost + +Upstream Author: Eddie C. Dost + +License: + +This software is Copyright (C) 1994 Eddie C. Dost + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License Version 2, found on Debian systems +in the file /usr/share/common-licenses/GPL . + diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 0000000..e772481 --- /dev/null +++ b/debian/dirs @@ -0,0 +1 @@ +usr/bin diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..e845566 --- /dev/null +++ b/debian/docs @@ -0,0 +1 @@ +README diff --git a/debian/menu b/debian/menu new file mode 100644 index 0000000..e3550f6 --- /dev/null +++ b/debian/menu @@ -0,0 +1,2 @@ +?package(x48):needs="X11|text|vc|wm" section="Apps/Math"\ + title="x48" command="/usr/bin/x48" diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..6ddc9bc --- /dev/null +++ b/debian/rules @@ -0,0 +1,89 @@ +#!/usr/bin/make -f +# -*- makefile -*- + +#export DH_VERBOSE=1 + +CFLAGS = -Wall -g + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif + +configure: configure-stamp +configure-stamp: + dh_testdir + + autoreconf + ./configure --prefix=/usr + + touch configure-stamp + + +build: build-stamp + +build-stamp: configure-stamp + dh_testdir + + $(MAKE) + + touch build-stamp + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + + # Add here commands to clean up after the build process. + [ ! -f Makefile ] || $(MAKE) distclean + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/x48. + $(MAKE) install DESTDIR=$(CURDIR)/debian/x48 + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs + dh_installdocs + dh_installexamples +# dh_install +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip + dh_compress + dh_fixperms +# dh_perl +# dh_python +# dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/debian/watch b/debian/watch new file mode 100644 index 0000000..3e157b6 --- /dev/null +++ b/debian/watch @@ -0,0 +1,6 @@ +# Example watch control file for uscan +# Rename this file to "watch" and then you can run the "uscan" command +# to check for upstream updates and more. +# Site Directory Pattern Version Script +version=2 +http://www.hpcalc.org/hp48/pc/emulators/x48-(.*)\.tgz diff --git a/doc/CARDS.doc b/doc/CARDS.doc new file mode 100644 index 0000000..09b0b79 --- /dev/null +++ b/doc/CARDS.doc @@ -0,0 +1,16 @@ +Q: How do you dump the Equation Lib? + +A: Well, I guess you would have to use some sort of Card copying + program from the HP48. This should give you an Image of the card. + + You should convert it into an x48 rom-file. Look at dump2rom.c. + There should be changes for the size of the Card!!! + + Then you should copy this to "$HOME/.hp48/port1" or "$HOME/.hp48/port2". + + Change the file to read only, use 'chmod 444 $HOME/.hp48/port1'. + The emulator will notice, this is a ROM. + + You are mainly on your own here, I don't have such a card, so I can't + try, but I hope it helps. + diff --git a/doc/COPYING b/doc/COPYING new file mode 100644 index 0000000..a43ea21 --- /dev/null +++ b/doc/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/doc/ChangeLog b/doc/ChangeLog new file mode 100644 index 0000000..27e7590 --- /dev/null +++ b/doc/ChangeLog @@ -0,0 +1,190 @@ +1995/01/16 Version 0.4.0 On the net + + - Implemented CONFIG/UNCNFG more exactly. + + - Added support for different RAM or ROM cards. + + - Added G/GX support (lost of changes) + new colors, new labels, ... + + - Rewrote ROMDump for both S/SX and G/GX. Lots faster now. + Thanks go to Robert Tiismus + + - Corrected handling of Display and Menu images, fixed number + of lines in init_display(), to avoid XShmError on virgin + startup + + - Catch SIGPIPE and save state, so everything is saved, when + x48 gets terminated by xkill or the window manager + + +********************************************************************** + +1994/12/07 Version 0.3.5 On the net + + - Serial and terminal lines now have the baudrate set + correctly. + + . Watch out for the IR (serial) connection: speed is + always set to 2400 Baud by the HP + . On the wire (terminal) connection speed is set to the + selected value + + - Removed stupid rounding in adjtime routine + + . This caused missing of some part of a second when + adjusting the time on the HP + + - Suppress adjusting timer2 if this would cause an + increase of the timer, slow down the timer instead. + + . Thanks go to Lutz Vieweg (he spotted this bug, while + trying to use QED. (lkv@mania.robin.de) + + - Support for contrast control (ON_+, ON_-) added + + + - Started command line parsing... (see below) + + Changes to the X11 Interface + ---------------------------- + + - Implemented color-icon. Show state of HP48 in icon: + + . if 'x48' is displayed, calculator is on. + . if 'x48' is blinking, calculator is transfering data. + + - Implemented use of the WM_SAVE_YOURSELF protocol. + + - x48 now uses Xrm...() functions to parse and use + Xresources and the command line. + + - Better handling of ButtonPresses and KeyPresses + + - The program now sets the WM_COMMAND property + + - Now colors look well on monochrome and gray + + - A new Colormap is allocated if the standard Colormap is full + + - All possible visuals are supported by the color allocation + modell (at least on Linux, I don't really know how to handle + DirectColor ...) + + +********************************************************************** + +1994/11/02 Version 0.3.4 On the net + + - Real time support mostly works (uses system time) + + - Stores ROM, RAM, and Ports in 'compressed' format + + - tty lines work on HPUX + Thanks go to Lutz Vieweg (lkv@mania.robin.de) + + - debugger now works on operating systems, where timers interrupt + the read system call. + + - Debugger now uses Class instruction set + + - Disassembler completed (at least hope so) + + +********************************************************************** + +1994/10/06 Version 0.3.3 On the net + + + - checkrom, a program to test the ROM CRC included + + - tty lines work on IRIX + Thanks go to !!!LOOK AT THE MAIL!!! + + - faster X11 interface + Uses Pixmaps now to update changed nibbles. + Whenever possible uses XSHM Extension to update + the display. + + - Start of debugger implementation + + - Disassembler started (HP & Alonzo) + + - SHUTDN bug fixed (didn't wake on received chars) + Thanks go to Lutz Vieweg (lkv@mania.robin.de) + + - Display bit offset implemented + + +********************************************************************** + +1994/10/02 Version 0.3.2 not published + + - Major speed improvement due to scheduling of emulator + specific events (timers, adjtime, receive, ...) + This *really* speeds up the main emulator loop. + + +********************************************************************** + +1994/09/30 Version 0.3.1 not published + + - Added MAGIC number to ~/.hp48/hp48 file + + - Minor optimizations + + +********************************************************************** + +1994/09/18 Second Release (Version 0.2) + + - Pure X11 interface + + - Start of real time support + + - SHUTDN implemented + + - Keyboard support + + - Compiles better (less warnings) on SunOS, Solaris + + +********************************************************************** + +1994/08/26 Initial Release (Version 0.1) + + - Emulates the HP48sx fairly + + - Compiles well only on Linux + + - Uses XView Panel and Canvas + + - Must be started in source directory + + - No SHUTDN + + - No real time + + - Misses HP48 keyboard interrupts + + - Slow + + +********************************************************************** + +1994/07 Look at em48 by Paul Fox + + - Starts to run like a HP48 + + +********************************************************************** + +1994/05 First Versions + + - No Display at all, merely debugging output + + +********************************************************************** + +1994/04 Fed up with stupid Desktop Calculators + diff --git a/doc/INSTALLING b/doc/INSTALLING new file mode 100644 index 0000000..f2321c6 --- /dev/null +++ b/doc/INSTALLING @@ -0,0 +1,34 @@ +INSTALLATION +============ + +I improved handling of differences in Solaris, SunOS, HP/UX, and Linux. +Things are not perfect, anyway. + +To configure some things for the Makefiles, edit 'config.h' in the +directory 'x48-0.4.0'. There you can set the compiler, flags to +pass to the compiler, and some other stuff. + +To build the emulator do the following in the directory 'x48-0.4.0': + + 1. xmkmf + 2. make + +This should give you the programs 'x48', 'dump2rom', and 'checkrom' +'mkcard' in the directory 'x48-0.4.0/bin'. + +To get the serial line working, you should set up your .Xdefaults for +x48. The resources concerning the serial line are: + +x48*useSerial: True +x48*serialLine: /dev/ttyS0 ; your serial device here, this + ; looks good for Linux. + +Run 'x48 -help' for a list of command line options. + +Look at 'x48-0.4.0/src/X48.ad' for the whole set of Xresources the +program uses. + +To use RAM cards (128K or 32K on the SX, up to 4M on the GX), use the +program 'mkcard', and put the resulting file in the directory ~/.hp48/ +in a file called 'port1' or 'port2'. + diff --git a/doc/ROMDump.doc b/doc/ROMDump.doc new file mode 100644 index 0000000..88bc124 --- /dev/null +++ b/doc/ROMDump.doc @@ -0,0 +1,36 @@ +This is ROMDump, a utility to dump the ROM of ANY HP48 +====================================================== + + +Usage: (2:hxs, 1:hxs --> ) pop start address from level 2, + pop end address from level 1, and dump + ROM to the serial at 9600 baud using + lines of form "aaaaa:hhhhhhhhhhhhhhhh\n\r" + with 16 nibbles ROM data hhhhhhhhhhhhhhhh + at address aaaaa. + + +- Download the file ROMDump to your HP. + +- To capture a complete ROM, start kermit on your computer, + set the line so that it fits your HP (use speed == 9600) + and type 'log session', then 'connect'. + +- On your HP48 S/SX type '#0h #7FFF0h ROMDump' or on the G/GX + '#0h #FFFF0h ROMDump'. This will give you a complete ROM dump. + This will take about 15 minutes on the S/SX, 30 minutes on the G/GX. + +- When done, type the kermit-Escape (usually CTRL-\) followed + by 'C' on your Computer. Say 'quit' to the kermit. + +- Your ROM should now be in the file 'session.log'. + + + +- To dump a certain range of ROM, enter the start-address in hex + and the end address in hex, and press 'ROMDump'. + + (For example: '#7FFF0h #7FFFFh' ROMDump will output + "7FFF0:84054383D21467BC\n\r" on a Version A S/SX.) + + diff --git a/doc/TODO b/doc/TODO new file mode 100644 index 0000000..79d6f60 --- /dev/null +++ b/doc/TODO @@ -0,0 +1,35 @@ +TODO -- HP48sx Emulator x48 +=========================== + +Write an MMU. Will increase speed significantly. + +Contact Eric Bryntse: + - ask for description of his Gateway-48 library + to trace down the following bug: + When an alarm wakes up x48, it is not starting + the exec without being given a password. + +Find a way to handle NumLock on those Solaris OpenWindows machines... +(take a look at xterm source) + +There should be a menu popping up when the HP Logo in the top left is +hit. It should contain some useful things like + + - RESET BUTTON + - Configuration (Serial, start kermit automatically, ...) + - Port configuration (pull card, insert ROM/RAM card, etc.) + - Pop up a window with debug outputs (speed, cpu usage, PC, ...) + - The 'About x48' field + +!!! Implement an Instruction Cache ... !!! <- SPEED + +Speed up register arithmetic. +- SPEED + +Implement a function "load file (filename)": + + - Read a file starting with "HPHP48-%c" + - try putting it on the stack as HP Object + - should not be hard to store it in a variable called 'filename' then + + --> Here we got a fast bypass to the kermit protocol. + diff --git a/romdump/Makefile.am b/romdump/Makefile.am new file mode 100644 index 0000000..2b821bf --- /dev/null +++ b/romdump/Makefile.am @@ -0,0 +1,4 @@ + +EXTRA_DIST = ROMDump.s ROMDump + + diff --git a/romdump/README b/romdump/README new file mode 100644 index 0000000..ff312c1 --- /dev/null +++ b/romdump/README @@ -0,0 +1,63 @@ +This file is part of ROMDump, a ROM dump utilty for the HP48sx Calculator. +Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + + +This is ROMDump, a utility to dump the ROM of ANY HP48 +====================================================== + + + +Usage: (2:hxs, 1:hxs --> ) pop start address from level 2, + pop end address from level 1, and dump + ROM to the serial at 9600 baud using + lines of form "aaaaa:hhhhhhhhhhhhhhhh\n\r" + with 16 nibbles ROM data hhhhhhhhhhhhhhhh + at address aaaaa. + + + +- Download the file ROMDump to your HP. + +- To capture a complete ROM, start kermit on your computer, + set the line so that it fits your HP (use speed == 9600) + and type 'log session', then 'connect'. + +- On your HP48 S/SX type '#0h #7FFF0h ROMDump' or on the G/GX + '#0h #FFFF0h ROMDump'. This will give you a complete ROM dump. + This will take about 15 minutes on the S/SX, 30 minutes on the G/GX. + +- When done, type the kermit-Escape (usually CTRL-\) followed + by 'C' on your Computer. Say 'quit' to the kermit. + +- Your ROM should now be in the file 'session.log'. + + + +- To dump a certain range of ROM, enter the start-address in hex + and the end address in hex, and press 'ROMDump'. + + (For example: '#7FFF0h #7FFFFh' ROMDump will output + "7FFF0:84054383D21467BC\n\r" on a Version A S/SX.) + + +I have included the assembler source (class version) for those +interested in fiddling with the hidden ROM... + + + +Eddie C. Dost (ecd@dressler.de) diff --git a/romdump/ROMDump b/romdump/ROMDump new file mode 100644 index 0000000..a8f101e Binary files /dev/null and b/romdump/ROMDump differ diff --git a/romdump/ROMDump.s b/romdump/ROMDump.s new file mode 100644 index 0000000..ccfe250 --- /dev/null +++ b/romdump/ROMDump.s @@ -0,0 +1,464 @@ +; +; $Id: ROMDump.s,v 1.4 1995/01/11 18:21:36 ecd Exp ecd $ +; +; This file is part of ROMDump, a ROM dump utility for the HP48 Calculator. +; Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) +; +; This program is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 2 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, write to the Free Software +; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +; +; Usage: +; +; (2: hxs, 1: hxs --> ) pop start address from level 2, +; pop end address from level 1, and dump +; ROM to the serial at 9600 baud using +; lines of form "aaaaa:hhhhhhhhhhhhhhhh\n\r" +; with 16 nibbles ROM data hhhhhhhhhhhhhhhh +; at address aaaaa. +; +; machine independent addresses (supported by HP) +; +AllowIntr equ $010e5 +DisableIntr equ $01115 +DOBINT equ $02911 +DOCOL equ $02d9d +DOCODE equ $02dcc +SEMI equ $0312b +GETPTRLOOP equ $05143 +SAVPTR equ $0679b +GETPTR equ $067d2 +CK2NOLASTWD equ $18a8d +CKandDISPATCH1 equ $18fb2 +VERSTRING equ $30794 +PopASavptr equ $3251c +; +; machine independent addresses (NOT supported by HP) +; +POPHXS equ $53f8d + +; +; machine dependent addresses +; +sx_GosubHidC equ $026bf +sx_prog_low equ $700f1 ; IRAMBUFF +sx_prog_high equ $f00f1 ; IRAMBUFF when RAM configured high + +gx_GosubHidC equ $026ca +gx_prog_low equ $800f5 ; IRAMBUFF +gx_prog_high equ $c00f5 ; IRAMBUFF when RAM configured high +gx_LINECOUNT equ $8069a + +; +; flags used +; +sGX equ 0 +sHIGH equ 1 + +; +; begin off assembler code +; + textr "HPHP48-R" + + dcr.5 DOCOL + dcr.5 CK2NOLASTWD + dcr.5 CKandDISPATCH1 + dcr.5 DOBINT + dcr.5 $000bb + + ; + ; only executed when (2: hxs, 1: hxs) + ; + dcr.5 DOCOL + dcr.5 VERSTRING + + dcr.5 DOCODE +code_start + dcr.5 code_end-code_start + + jsr DisableIntr + + ; + ; figure out version + ; + jsr PopASavptr + move.1 #0, p + move.5 #24, c.p + add.a c, a + move.a a, d1 + move.b (d1), a + move.2 #$4a, c.p ; 'J' == last version for S/SX + bclr #sGX, st + ble.b a, c, got_version + bset #sGX, st +got_version + bclr #sHIGH, st + + ; + ; get arguments + ; + jsr GETPTR + jsr POPHXS + move.1 #0, p + move.5 #$ffff0, c.p + and.a c, a + move.a a, r4 + + jsr GETPTR + jsr POPHXS + move.1 #0, p + move.5 #$ffff0, c.p + and.a c, a + move.a a, r3 + + ; + ; open IO + ; + move.5 #$00110, d1 + move.1 #8, a.p + move.1 a, (d1) + + ; + ; set speed to 9600 baud + ; + move.2 #$0d, d1 + move.1 #6, a.p + move.1 a, (d1) + + ; + ; dump ROM $00000 - $6ffff + ; +dump_rom_0 + move.a r3, a + move.5 #$6fff0, c.p + bgt.a a, c, dump_rom_7 + move.a a, r1 + + move.a r4, c + move.a c, b + move.5 #$6fff0, c.p + ble.a b, c, end_addr_0 + move.a c, b +end_addr_0 + subr.a b, a + bcc continue_0 + bra.3 dump_done +continue_0 + move.a a, r2 + + bsr.3 prog_start + + move.5 #$70000, a.p + move.a a, r3 + + ; + ; dump ROM $70000 - $7ffff + ; +dump_rom_7 + move.a r3, a + move.5 #$7fff0, c.p + bgt.a a, c, dump_done_7 + bra.3 continue_7 +dump_done_7 + bbs #sGX, st, continue_8 + bra.3 dump_done +continue_8 + bra.3 dump_rom_8 +continue_7 + move.a a, r1 + + move.a r4, c + move.a c, b + move.5 #$7fff0, c.p + ble.a b, c, end_addr_7 + move.a c, b +end_addr_7 + subr.a b, a + bcc continue_7_2 + bra.3 dump_done +continue_7_2 + move.a a, r2 + + bbs #sGX, st, gx_dump_rom_7 + bsr.3 copy_prog + move.5 #sx_prog_high, c.p + jsr sx_GosubHidC + bsr.3 copy_prog + bra.3 dump_done + +gx_dump_rom_7 + ; + ; unconfigure devices at 7e000 - 7ffff + ; + move.5 #$7f000, c.p + uncnfg + move.5 #$7e000, c.p + uncnfg + + bsr.3 prog_start + + ; + ; reconfigure devices at 7e000 - 7ffff + ; + move.5 #$ff000, c.p + config + move.5 #$7f000, c.p + config + move.5 #$ff000, c.p + config + move.5 #$7e000, c.p + config + + move.5 #$80000, a.p + move.a a, r3 + + ; + ; dump ROM $80000 - $bffff + ; +dump_rom_8 + move.a r3, a + move.5 #$bfff0, c.p + bgt.a a, c, dump_rom_c + move.a a, r1 + + move.a r4, c + move.a c, b + move.5 #$bfff0, c.p + ble.a b, c, end_addr_8 + move.a c, b +end_addr_8 + subr.a b, a + bcc continue_8_2 + bra.3 dump_done +continue_8_2 + move.a a, r2 + + bsr.3 copy_prog + move.5 #gx_prog_high, c.p + jsr gx_GosubHidC + bsr.3 copy_prog + + move.5 #$c0000, a.p + move.a a, r3 + + ; + ; dump ROM $c0000 - $fffff + ; +dump_rom_c + move.a r3, a + move.a a, r1 + + move.a r4, c + move.a c, b + move.5 #$ffff0, c.p + ble.a b, c, end_addr_c + move.a c, b +end_addr_c + subr.a b, a + bcs dump_done + move.a a, r2 + + bsr.3 copy_prog + bset #sHIGH, st + jsr gx_prog_low + bsr.3 copy_prog + +dump_done + ; + ; close IO + ; + bsr.3 send_crnl + move.5 #$00110, d1 + move.1 #0, a.p + move.1 a, (d1) + + ; + ; back to RPL + ; + jsr AllowIntr + jmp GETPTRLOOP + +; +; exchange program with memory at address prog_low +; +copy_prog + move.a pc, c +prog_offset + move.5 #prog_start-prog_offset, a.p + add.a a, c + move.a c, d0 + bbs #sGX, st, gx_addr + move.5 #sx_prog_low, d1 + bra.3 sx_addr +gx_addr + move.5 #gx_prog_low, d1 +sx_addr + move.5 #prog_end-prog_start, a.p + lsr.a #4, a + move.a a, b + +copy_word + move.w (d0), a + move.w (d1), c + move.w c, (d0) + move.w a, (d1) + add.a #16, d0 + add.a #16, d1 + dec.a b + bcc copy_word + rtn + +; +; this is the start of the actual dump routine +; +prog_start + bbc #sHIGH, st, skip_uncover_c + ; + ; uncover ROM at c0000 - fffff + ; + move.5 #$7f000, d0 + move.b (d0), c + move.5 #gx_LINECOUNT, d0 + move.b (d0), c + bset #7, c + move.b c, (d0) + move.5 #$00128, d0 + move.b c, (d0) + move.5 #$c0000, c.p + uncnfg + uncnfg + +skip_uncover_c + ; + ; get start address and number of words + ; + move.a r1, a + move.a a, d0 + move.a r2, a + + ; + ; dump the ROM + ; +loop + move.a a, r0 + bsr.3 send_addr + move.2 #$3a, c.p + bsr.3 send_char + move.w (d0), c + bsr.3 send_data + bsr.3 send_crnl + + add.a #16, d0 + move.a r0, a + sub.a #16, a + bcc loop + + bbc #sHIGH, st, skip_cover_c + ; + ; reconfigure memory ports at c0000 + ; + move.5 #$c0000, c.p + config + config + config + config + move.5 #gx_LINECOUNT, d0 + move.b (d0), c + bclr #7, c + move.b c, (d0) + move.5 #$00128, d0 + move.b c, (d0) + move.5 #$7f040, d0 + move.b (d0), c + +skip_cover_c + rtn + +; +; send data in C.W as hex characters +; +send_data + move.w c, b + move.2 #$0f, c.p + move.b c, d + bra.3 send_all + +; +; send addr in D0 as hex characters +; +send_addr + exg.a a, d0 + move.a a, c + exg.a a, d0 + exg.1 p, c.4 + exg.1 p, c.0 + exg.1 p, c.4 + exg.1 p, c.3 + exg.1 p, c.1 + exg.1 p, c.3 + move.a c, b + move.2 #$04, c.p + move.b c, d + +; +; send D.B many nibbles from B.W +; +send_all + clr.b c + move.p b, c + bsr.3 send_hex_nib + lsr.w #4, b + dec.b d + bcc send_all + rtn + +; +; send "\n\r" +; +send_crnl + move.2 #$0d, c.p + bsr.3 send_char + move.2 #$0a, c.p + bsr.3 send_char + rtn + +; +; send nibble in C.B as hex character +; +send_hex_nib + move.2 #$30, a.p + add.b a, c + move.2 #$39, a.p + ble.b c, a, send_char + move.2 #$07, a.p + add.b a, c +; +; send character in C.B +; +send_char + move.5 #$00112, d1 +xmtrdy + move.1 (d1), a + bbs #0, a, xmtrdy + move.2 #$16, d1 + move.b c, (d1) + rtn + +prog_end + dcr.8 $00000000 + dcr.8 $00000000 + +code_end + + dcr.5 SEMI ; end of DISPATCH + dcr.5 SEMI ; end of program object diff --git a/rpm/x48.spec.in b/rpm/x48.spec.in new file mode 100644 index 0000000..a81a182 --- /dev/null +++ b/rpm/x48.spec.in @@ -0,0 +1,45 @@ +Summary: x48 is an HP 48 GX emulator +Name: x48 +Version: @VERSION@ +Release: 1 +License: GPL +Group: Applications/Math +URL: http://developer.berlios.de/projects/x48/ +BuildRoot: %{_tmppath}/%{name}-%{version}-root +Requires: libX11 libXext readline +BuildRequires: autoconf libX11-devel libXext-devel readline-devel +BuildRequires: libXt-devel + +Source: http://download.berlios.de/x48/%{name}-%{version}.tar.gz + +%description + This is an emulator of the HP 48 SX and GX calculator. + Romdumps are available from http://x48.berlios.de/ + +%define x11_app_defaults_dir %(pkg-config --variable appdefaultdir xt) + +%prep +%setup -q + +%build +%configure \ + --prefix=/usr +make %{?_smp_mflags} + +%install +make DESTDIR=$RPM_BUILD_ROOT install + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root,-) +%doc README +%{_bindir}/x48 +%{_bindir}/dump2rom +%{_bindir}/checkrom +%{_bindir}/mkcard +%{_mandir}/man1/* +%{x11_app_defaults_dir}/X48 + + diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..09037e1 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,68 @@ + +## Process this file with automake to produce Makefile.in + +bin_PROGRAMS = x48 dump2rom mkcard checkrom + +BITMAPS = bitmaps/A.h bitmaps/B.h bitmaps/C.h bitmaps/D.h bitmaps/E.h bitmaps/F.h \ + bitmaps/G.h bitmaps/H.h bitmaps/I.h bitmaps/J.h bitmaps/K.h \ + bitmaps/L.h bitmaps/M.h bitmaps/N.h bitmaps/O.h bitmaps/P.h \ + bitmaps/Q.h bitmaps/R.h bitmaps/S.h bitmaps/T.h bitmaps/U.h \ + bitmaps/V.h bitmaps/W.h bitmaps/X.h bitmaps/Y.h bitmaps/Z.h \ + bitmaps/alpha.h bitmaps/angle.h bitmaps/angle_gx.h \ + bitmaps/ann_alpha.h bitmaps/ann_battery.h bitmaps/ann_busy.h \ + bitmaps/ann_io.h bitmaps/ann_left.h bitmaps/ann_right.h \ + bitmaps/arrow.h bitmaps/arrow_gx.h bitmaps/blank.h \ + bitmaps/bracket_gx.h bitmaps/bs.h bitmaps/colon.h \ + bitmaps/colon_gx.h bitmaps/comma.h bitmaps/comma_gx.h \ + bitmaps/curly_gx.h bitmaps/diff.h bitmaps/div.h bitmaps/down.h \ + bitmaps/equal.h bitmaps/equal_gx.h bitmaps/exp.h \ + bitmaps/exp_gx.h bitmaps/gx_128K_ram.h bitmaps/gx_green.h \ + bitmaps/gx_silver.h bitmaps/hash.h bitmaps/hash_gx.h \ + bitmaps/hp.h bitmaps/hp48_blue.h bitmaps/hp48_bottom.h \ + bitmaps/hp48_disp.h bitmaps/hp48_green_gx.h \ + bitmaps/hp48_icon.h bitmaps/hp48_keys.h bitmaps/hp48_logo.h \ + bitmaps/hp48_logo_gx.h bitmaps/hp48_on.h bitmaps/hp48_orange.h \ + bitmaps/hp48_text.h bitmaps/hp48_text_gx.h bitmaps/hp48_top.h \ + bitmaps/hp48_top_gx.h bitmaps/hp48gx.h bitmaps/hp48sx.h \ + bitmaps/integral.h bitmaps/inv.h bitmaps/last.h \ + bitmaps/lbrace.h bitmaps/lbracket.h bitmaps/lcurly.h \ + bitmaps/left.h bitmaps/menu_label.h bitmaps/minus.h \ + bitmaps/mul.h bitmaps/neg.h bitmaps/nl.h bitmaps/nl_gx.h \ + bitmaps/parens_gx.h bitmaps/pi.h bitmaps/pi_gx.h \ + bitmaps/plus.h bitmaps/pow10.h bitmaps/pow10_gx.h \ + bitmaps/power.h bitmaps/prog.h bitmaps/prog_gx.h \ + bitmaps/quote_gx.h bitmaps/rbrace.h bitmaps/rbracket.h \ + bitmaps/rcurly.h bitmaps/right.h bitmaps/root.h \ + bitmaps/root_gx.h bitmaps/science.h bitmaps/shl.h \ + bitmaps/shr.h bitmaps/sigma.h bitmaps/slash.h \ + bitmaps/small_colon.h bitmaps/sqr.h bitmaps/sqr_gx.h \ + bitmaps/sqrt.h bitmaps/string.h bitmaps/three.h bitmaps/two.h \ + bitmaps/under.h bitmaps/under_gx.h bitmaps/up.h + +x48_SOURCES = actions.c debugger.c device.c \ + disasm.c emulate.c errors.c init.c \ + lcd.c main.c memory.c options.c register.c \ + resources.c romio.c rpl.c serial.c timer.c \ + x48_x11.c \ + annunc.h append.h buttons.h constants.h debugger.h \ + device.h disasm.h errors.h global.h hp48char.h hp48_emu.h \ + hp48.h hp.h icon.h mmu.h options.h resources.h romio.h rpl.h \ + small.h timer.h version.h X48.ad.h x48_x11.h \ + $(BITMAPS) + + +dump2rom_SOURCES = dump2rom.c + +mkcard_SOURCES = mkcard.c + +checkrom_SOURCES = checkrom.c romio.c + +man1_MANS = x48.man + +EXTRA_DIST = $(man1_MANS) X48.ad + +INCLUDES = $(X_CFLAGS) + +x48_LDADD = $(X_LIBS) + + diff --git a/src/X48.ad b/src/X48.ad new file mode 100644 index 0000000..c245ea4 --- /dev/null +++ b/src/X48.ad @@ -0,0 +1,68 @@ +! +! This file is part of x48, an emulator of the HP-48sx Calculator. +! Copyright (C) 1994 Eddie C. Dost . +! +! This program is free software; you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation; either version 2 of the License, or +! (at your option) any later version. +! +! This program is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with this program; if not, write to the Free Software +! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +! +! $Id: X48.ad,v 1.2 1994/12/07 20:27:35 ecd Exp ecd $ +! + +! +! X11 related stuff +! +*iconic: False +*visual: Default +*mono: False +*gray: False +*monoIcon: False + +*useXShm: True + +*smallLabelFont: -*-fixed-bold-r-normal-*-14-*-*-*-*-*-iso8859-1 +*mediumLabelFont: -*-fixed-bold-r-normal-*-15-*-*-*-*-*-iso8859-1 +*largeLabelFont: -*-fixed-medium-r-normal-*-20-*-*-*-*-*-iso8859-1 +*connectionFont: -*-helvetica-medium-r-normal-*-12-*-*-*-*-*-iso8859-1 + +! +! informative stuff +! +*verbose: False +*quiet: False + +*printVersion: False +*printCopyright: False +*printWarranty: False + +! +! resources controlling the connections +! +*useTerminal: True +*useSerial: False +*serialLine: /dev/ttyS0 + +! +! stuff controlling initialization +! +*completeInitialize: False +*resetOnStartup: False +*romFileName: rom.dump +*homeDirectory: .hp48 + +! +! resources controlling the debugger +! +*useDebugger: True +*disassemblerMnemonics: class + diff --git a/src/X48.ad.h b/src/X48.ad.h new file mode 100644 index 0000000..f097d94 --- /dev/null +++ b/src/X48.ad.h @@ -0,0 +1,24 @@ +"*iconic: False", +"*visual: Default", +"*mono: False", +"*gray: False", +"*monoIcon: False", +"*useXShm: True", +"*smallLabelFont: -*-fixed-bold-r-normal-*-14-*-*-*-*-*-iso8859-1", +"*mediumLabelFont: -*-fixed-bold-r-normal-*-15-*-*-*-*-*-iso8859-1", +"*largeLabelFont: -*-fixed-medium-r-normal-*-20-*-*-*-*-*-iso8859-1", +"*connectionFont: -*-helvetica-medium-r-normal-*-12-*-*-*-*-*-iso8859-1", +"*verbose: False", +"*quiet: False", +"*printVersion: False", +"*printCopyright: False", +"*printWarranty: False", +"*useTerminal: True", +"*useSerial: False", +"*serialLine: /dev/ttyS0", +"*completeInitialize: False", +"*resetOnStartup: False", +"*romFileName: rom.dump", +"*homeDirectory: .hp48", +"*useDebugger: True", +"*disassemblerMnemonics: class", diff --git a/src/actions.c b/src/actions.c new file mode 100644 index 0000000..43fdf29 --- /dev/null +++ b/src/actions.c @@ -0,0 +1,1087 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: actions.c,v $ + * Revision 1.15 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.14 1994/12/07 20:20:50 ecd + * changed shutdown again: wake on TIMER1CTRL & XTRA + * + * Revision 1.14 1994/12/07 20:20:50 ecd + * changed shutdown again: wake on TIMER1CTRL & XTRA + * + * Revision 1.13 1994/11/28 02:00:51 ecd + * changed do_configure for internal debugging + * + * Revision 1.12 1994/11/02 14:40:38 ecd + * removed call to debug in do_shutdown() + * + * Revision 1.11 1994/10/09 20:29:47 ecd + * no real change, was just fiddling around with the display. + * + * Revision 1.10 1994/10/06 16:30:05 ecd + * added refresh_display() + * + * Revision 1.9 1994/10/05 08:36:44 ecd + * changed shutdown + * + * Revision 1.8 1994/10/01 10:12:53 ecd + * fixed bug in shutdown + * + * Revision 1.7 1994/09/30 12:37:09 ecd + * changed shutdown instruction + * + * Revision 1.6 1994/09/18 22:47:20 ecd + * fixed bug with overflow in timerdiff + * + * Revision 1.5 1994/09/18 15:29:22 ecd + * added SHUTDN implementation, + * started Real Time support. + * + * Revision 1.4 1994/09/13 16:57:00 ecd + * changed to plain X11 + * + * Revision 1.3 1994/08/31 18:23:21 ecd + * changed memory read routines. + * + * Revision 1.2 1994/08/27 11:28:59 ecd + * changed keyboard interrupt handling. + * + * Revision 1.1 1994/08/26 11:09:02 ecd + * Initial revision + * + * + * $Id: actions.c,v 1.15 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +/* #define DEBUG_INTERRUPT 1 */ +/* #define DEBUG_KBD_INT 1 */ +/* #define DEBUG_SHUTDOWN 1 */ +/* #define DEBUG_CONFIG 1 */ +/* #define DEBUG_ID 1 */ + +#include "global.h" + +#include +#include +#include + +#include "hp48.h" +#include "hp48_emu.h" +#include "device.h" +#include "x48_x11.h" +#include "timer.h" +#include "debugger.h" +#include "romio.h" + +static int interrupt_called = 0; +extern long nibble_masks[16]; + +int got_alarm; + +int conf_bank1 = 0x00000; +int conf_bank2 = 0x00000; + +void +#ifdef __FunctionProto__ +do_in(void) +#else +do_in() +#endif +{ + int i, in, out; + + out = 0; + for (i = 2; i >= 0; i--) { + out <<= 4; + out |= saturn.OUT[i]; + } + in = 0; + for (i = 0; i < 9; i++) + if (out & (1 << i)) + in |= saturn.keybuf.rows[i]; +#ifdef DEBUG_INOUT + fprintf(stderr, "saturn.OUT=%.3x, saturn.IN=%.4x\n", out, in); +#endif + + for (i = 0; i < 4; i++) { + saturn.IN[i] = in & 0xf; + in >>= 4; + } +} + +void +#ifdef __FunctionProto__ +clear_program_stat(int n) +#else +clear_program_stat(n) +int n; +#endif +{ + saturn.PSTAT[n] = 0; +} + +void +#ifdef __FunctionProto__ +set_program_stat(int n) +#else +set_program_stat(n) +int n; +#endif +{ + saturn.PSTAT[n] = 1; +} + +int +#ifdef __FunctionProto__ +get_program_stat(int n) +#else +get_program_stat(n) +int n; +#endif +{ + return saturn.PSTAT[n]; +} + +void +#ifdef __FunctionProto__ +register_to_status(unsigned char *r) +#else +register_to_status(r) +unsigned char *r; +#endif +{ + int i; + + for (i = 0; i < 12; i++) { + saturn.PSTAT[i] = (r[i / 4] >> (i % 4)) & 1; + } +} + +void +#ifdef __FunctionProto__ +status_to_register(unsigned char *r) +#else +status_to_register(r) +unsigned char *r; +#endif +{ + int i; + + for (i = 0; i < 12; i++) { + if (saturn.PSTAT[i]) { + r[i / 4] |= 1 << (i % 4); + } else { + r[i / 4] &= ~(1 << (i % 4)) & 0xf; + } + } +} + +void +#ifdef __FunctionProto__ +swap_register_status(unsigned char *r) +#else +swap_register_status(r) +unsigned char *r; +#endif +{ + int i, tmp; + + for (i = 0; i < 12; i++) { + tmp = saturn.PSTAT[i]; + saturn.PSTAT[i] = (r[i / 4] >> (i % 4)) & 1; + if (tmp) { + r[i / 4] |= 1 << (i % 4); + } else { + r[i / 4] &= ~(1 << (i % 4)) & 0xf; + } + } +} + +void +#ifdef __FunctionProto__ +clear_status(void) +#else +clear_status() +#endif +{ + int i; + + for (i = 0; i < 12; i++) { + saturn.PSTAT[i] = 0; + } +} + +void +#ifdef __FunctionProto__ +set_register_nibble(unsigned char *reg, int n, unsigned char val) +#else +set_register_nibble(reg, n, val) +unsigned char *reg; +int n; +unsigned char val; +#endif +{ + reg[n] = val; +} + +unsigned char +#ifdef __FunctionProto__ +get_register_nibble(unsigned char *reg, int n) +#else +get_register_nibble(reg, n) +unsigned char *reg; +int n; +#endif +{ + return reg[n]; +} + +void +#ifdef __FunctionProto__ +set_register_bit(unsigned char *reg, int n) +#else +set_register_bit(reg, n) +unsigned char *reg; +int n; +#endif +{ + reg[n/4] |= (1 << (n%4)); +} + +void +#ifdef __FunctionProto__ +clear_register_bit(unsigned char *reg, int n) +#else +clear_register_bit(reg, n) +unsigned char *reg; +int n; +#endif +{ + reg[n/4] &= ~(1 << (n%4)); +} + +int +#ifdef __FunctionProto__ +get_register_bit(unsigned char *reg, int n) +#else +get_register_bit(reg, n) +unsigned char *reg; +int n; +#endif +{ + return ((int)(reg[n/4] & (1 << (n%4))) > 0)?1:0; +} + +short conf_tab_sx[] = { 1, 2, 2, 2, 2, 0 }; +short conf_tab_gx[] = { 1, 2, 2, 2, 2, 0 }; + +void +#ifdef __FunctionProto__ +do_reset(void) +#else +do_reset() +#endif +{ + int i; + + for (i = 0; i < 6; i++) + { + if (opt_gx) + saturn.mem_cntl[i].unconfigured = conf_tab_gx[i]; + else + saturn.mem_cntl[i].unconfigured = conf_tab_sx[i]; + saturn.mem_cntl[i].config[0] = 0x0; + saturn.mem_cntl[i].config[1] = 0x0; + } + +#ifdef DEBUG_CONFIG + fprintf(stderr, "%.5lx: RESET\n", saturn.PC); + for (i = 0; i < 6; i++) + { + if (saturn.mem_cntl[i].unconfigured) + fprintf(stderr, "MEMORY CONTROLLER %d is unconfigured\n", i); + else + fprintf(stderr, "MEMORY CONTROLLER %d is configured to %.5lx, %.5lx\n", + i, saturn.mem_cntl[i].config[0], saturn.mem_cntl[i].config[1]); + } +#endif +} + +void +#ifdef __FunctionProto__ +do_inton(void) +#else +do_inton() +#endif +{ + saturn.kbd_ien = 1; +} + +void +#ifdef __FunctionProto__ +do_intoff(void) +#else +do_intoff() +#endif +{ + saturn.kbd_ien = 0; +} + +void +#ifdef __FunctionProto__ +do_return_interupt(void) +#else +do_return_interupt() +#endif +{ + if (saturn.int_pending) { +#ifdef DEBUG_INTERRUPT + fprintf(stderr, "PC = %.5lx: RTI SERVICE PENDING INTERRUPT\n", + saturn.PC); +#endif + saturn.int_pending = 0; + saturn.intenable = 0; + saturn.PC = 0xf; + } else { +#ifdef DEBUG_INTERRUPT + fprintf(stderr, "PC = %.5lx: RETURN INTERRUPT to ", saturn.PC); +#endif + saturn.PC = pop_return_addr(); +#ifdef DEBUG_INTERRUPT + fprintf(stderr, "%.5lx\n", saturn.PC); +#endif + saturn.intenable = 1; + + if (adj_time_pending) { + schedule_event = 0; + sched_adjtime = 0; + } + + } +} + +void +#ifdef __FunctionProto__ +do_interupt(void) +#else +do_interupt() +#endif +{ + interrupt_called = 1; + if (saturn.intenable) { +#ifdef DEBUG_INTERRUPT + fprintf(stderr, "PC = %.5lx: INTERRUPT\n", saturn.PC); +#endif + push_return_addr(saturn.PC); + saturn.PC = 0xf; + saturn.intenable = 0; + } +} + +void +#ifdef __FunctionProto__ +do_kbd_int(void) +#else +do_kbd_int() +#endif +{ + interrupt_called = 1; + if (saturn.intenable) { +#ifdef DEBUG_KBD_INT + fprintf(stderr, "PC = %.5lx: KBD INT\n", saturn.PC); +#endif + push_return_addr(saturn.PC); + saturn.PC = 0xf; + saturn.intenable = 0; + } else { +#ifdef DEBUG_KBD_INT + fprintf(stderr, "PC = %.5lx: KBD INT PENDING\n", saturn.PC); +#endif + saturn.int_pending = 1; + } +} + +void +#ifdef __FunctionProto__ +do_reset_interrupt_system(void) +#else +do_reset_interrupt_system() +#endif +{ + int i, gen_intr; + + saturn.kbd_ien = 1; + gen_intr = 0; + for (i = 0; i < 9; i++) { + if (saturn.keybuf.rows[i] != 0) { + gen_intr = 1; + break; + } + } + if (gen_intr) { + do_kbd_int(); + } +} + +void +#ifdef __FunctionProto__ +do_unconfigure(void) +#else +do_unconfigure() +#endif +{ + int i; + unsigned int conf; + + conf = 0; + for (i = 4; i >= 0; i--) { + conf <<= 4; + conf |= saturn.C[i]; + } + + for (i = 0; i < 6; i++) + { + if (saturn.mem_cntl[i].config[0] == conf) + { + if (opt_gx) + saturn.mem_cntl[i].unconfigured = conf_tab_gx[i]; + else + saturn.mem_cntl[i].unconfigured = conf_tab_sx[i]; + saturn.mem_cntl[i].config[0] = 0x0; + saturn.mem_cntl[i].config[1] = 0x0; + break; + } + } + +#ifdef DEBUG_CONFIG + fprintf(stderr, "%.5lx: UNCNFG %.5x:\n", saturn.PC, conf); + for (i = 0; i < 6; i++) + { + if (saturn.mem_cntl[i].unconfigured) + fprintf(stderr, "MEMORY CONTROLLER %d is unconfigured\n", i); + else + fprintf(stderr, "MEMORY CONTROLLER %d is configured to %.5lx, %.5lx\n", + i, saturn.mem_cntl[i].config[0], saturn.mem_cntl[i].config[1]); + } +#endif +} + +void +#ifdef __FunctionProto__ +do_configure(void) +#else +do_configure() +#endif +{ + int i; + unsigned long conf; + + conf = 0; + for (i = 4; i >= 0; i--) { + conf <<= 4; + conf |= saturn.C[i]; + } + + for (i = 0; i < 6; i++) + { + if (saturn.mem_cntl[i].unconfigured) + { + saturn.mem_cntl[i].unconfigured--; + saturn.mem_cntl[i].config[saturn.mem_cntl[i].unconfigured] = conf; + break; + } + } + +#ifdef DEBUG_CONFIG + fprintf(stderr, "%.5lx: CONFIG %.5lx:\n", saturn.PC, conf); + for (i = 0; i < 6; i++) + { + if (saturn.mem_cntl[i].unconfigured) + fprintf(stderr, "MEMORY CONTROLLER %d is unconfigured\n", i); + else + fprintf(stderr, "MEMORY CONTROLLER %d at %.5lx, %.5lx\n", + i, saturn.mem_cntl[i].config[0], saturn.mem_cntl[i].config[1]); + } +#endif +} + +int +#ifdef __FunctionProto__ +get_identification(void) +#else +get_identification() +#endif +{ + int i; + static int chip_id[] + = { 0, 0, 0, 0, 0x05, 0xf6, 0x07, 0xf8, 0x01, 0xf2, 0, 0 }; + int id; + + for (i = 0; i < 6; i++) + { + if (saturn.mem_cntl[i].unconfigured) + break; + } + if (i < 6) + id = chip_id[2 * i + (2 - saturn.mem_cntl[i].unconfigured)]; + else + id = 0; + +#ifdef DEBUG_ID + fprintf(stderr, "%.5lx: C=ID, returning: %x\n", saturn.PC, id); + for (i = 0; i < 6; i++) + { + if (saturn.mem_cntl[i].unconfigured == 2) + fprintf(stderr, "MEMORY CONTROLLER %d is unconfigured\n", i); + else if (saturn.mem_cntl[i].unconfigured == 1) + { + if (i == 0) + fprintf(stderr, "MEMORY CONTROLLER %d unconfigured\n", i); + else + fprintf(stderr, "MEMORY CONTROLLER %d configured to ????? %.5lx\n", + i, saturn.mem_cntl[i].config[1]); + } + else + fprintf(stderr, "MEMORY CONTROLLER %d configured to %.5lx, %.5lx\n", + i, saturn.mem_cntl[i].config[0], saturn.mem_cntl[i].config[1]); + } +#endif + + for (i = 0; i < 3; i++) + { + saturn.C[i] = id & 0x0f; + id >>= 4; + } + return 0; +} + +void +#ifdef __FunctionProto__ +do_shutdown(void) +#else +do_shutdown() +#endif +{ + int wake, alarms; + t1_t2_ticks ticks; + + if (device.display_touched) { + device.display_touched = 0; + update_display(); +#ifdef HAVE_XSHM + if (disp.display_update) refresh_display(); +#endif + } + + stop_timer(RUN_TIMER); + start_timer(IDLE_TIMER); + + if (is_zero_register(saturn.OUT, OUT_FIELD)) { +#ifdef DEBUG_SHUTDOWN + fprintf(stderr, "%.5lx: SHUTDN: PC = 0\n", saturn.PC); +#endif + saturn.intenable = 1; + saturn.int_pending = 0; + } + +#ifdef DEBUG_SHUTDOWN + fprintf(stderr, "%.5lx:\tSHUTDN: Timer 1 Control = %x, Timer 1 = %d\n", + saturn.PC, saturn.t1_ctrl, saturn.timer1); + fprintf(stderr, "%.5lx:\tSHUTDN: Timer 2 Control = %x, Timer 2 = %ld\n", + saturn.PC, saturn.t2_ctrl, saturn.timer2); +#endif + + if (in_debugger) + wake = 1; + else + wake = 0; + + alarms = 0; + + do { + + pause(); + + if (got_alarm) { + got_alarm = 0; + +#ifdef HAVE_XSHM + if (disp.display_update) refresh_display(); +#endif + + ticks = get_t1_t2(); + if (saturn.t2_ctrl & 0x01) { + saturn.timer2 = ticks.t2_ticks; + } + saturn.timer1 = set_t1 - ticks.t1_ticks; + set_t1 = ticks.t1_ticks; + + interrupt_called = 0; + if (GetEvent()) { + if (interrupt_called) + wake = 1; + } + + if (saturn.timer2 <= 0) + { + if (saturn.t2_ctrl & 0x04) + { + wake = 1; + } + if (saturn.t2_ctrl & 0x02) + { + wake = 1; + saturn.t2_ctrl |= 0x08; + do_interupt(); + } + } + + if (saturn.timer1 <= 0) + { + saturn.timer1 &= 0x0f; + if (saturn.t1_ctrl & 0x04) + { + wake = 1; + } + if (saturn.t1_ctrl & 0x03) + { + wake = 1; + saturn.t1_ctrl |= 0x08; + do_interupt(); + } + } + + if (wake == 0) { + interrupt_called = 0; + receive_char(); + if (interrupt_called) + wake = 1; + } + + alarms++; + } + + if (enter_debugger) + { + wake = 1; + } + } while (wake == 0); + + stop_timer(IDLE_TIMER); + start_timer(RUN_TIMER); +} + +void +#ifdef __FunctionProto__ +set_hardware_stat(int op) +#else +set_hardware_stat(op) +int op; +#endif +{ + if (op & 1) saturn.XM = 1; + if (op & 2) saturn.SB = 1; + if (op & 4) saturn.SR = 1; + if (op & 8) saturn.MP = 1; +} + +void +#ifdef __FunctionProto__ +clear_hardware_stat(int op) +#else +clear_hardware_stat(op) +int op; +#endif +{ + if (op & 1) saturn.XM = 0; + if (op & 2) saturn.SB = 0; + if (op & 4) saturn.SR = 0; + if (op & 8) saturn.MP = 0; +} + +int +#ifdef __FunctionProto__ +is_zero_hardware_stat(int op) +#else +is_zero_hardware_stat(op) +int op; +#endif +{ + if (op & 1) if (saturn.XM != 0) return 0; + if (op & 2) if (saturn.SB != 0) return 0; + if (op & 4) if (saturn.SR != 0) return 0; + if (op & 8) if (saturn.MP != 0) return 0; + return 1; +} + +void +#ifdef __FunctionProto__ +push_return_addr(long addr) +#else +push_return_addr(addr) +long addr; +#endif +{ + int i; + + if (++saturn.rstkp >= NR_RSTK) { +#if 0 + fprintf(stderr, "%.5lx: RSTK overflow !!!\n", saturn.PC); + for (i = saturn.rstkp - 1; i >= 0; i--) { + fprintf(stderr, "\tRSTK[%d] %.5lx\n", i, saturn.rstk[i]); + } +#endif + for (i = 1; i < NR_RSTK; i++) + saturn.rstk[i-1] = saturn.rstk[i]; + saturn.rstkp--; + } + saturn.rstk[saturn.rstkp] = addr; +#ifdef DEBUG_RSTK + fprintf(stderr, "PUSH %.5x:\n", addr); + for (i = saturn.rstkp; i >= 0; i--) { + fprintf(stderr, "RSTK[%d] %.5x\n", i, saturn.rstk[i]); + } +#endif +} + +long +#ifdef __FunctionProto__ +pop_return_addr(void) +#else +pop_return_addr() +#endif +{ +#ifdef DEBUG_RSTK + int i; + + for (i = saturn.rstkp; i >= 0; i--) { + fprintf(stderr, "RSTK[%d] %.5x\n", i, saturn.rstk[i]); + } + fprintf(stderr, "POP %.5x:\n", + (saturn.rstkp >= 0) ? saturn.rstk[saturn.rstkp]:0); +#endif + if (saturn.rstkp < 0) + return 0; + return saturn.rstk[saturn.rstkp--]; +} + +char * +#ifdef __FunctionProto__ +make_hexstr(long addr, int n) +#else +make_hexstr(addr, n) +long addr; +int n; +#endif +{ + static char str[44]; + int i, t, trunc; + + trunc = 0; + if (n > 40) { + n = 40; + trunc = 1; + } + for (i = 0; i < n; i++) { + t = read_nibble(addr+i); + if (t <= 9) + str[i] = '0' + t; + else + str[i] = 'a' + (t - 10); + } + str[n] = '\0'; + if (trunc) { + str[n] = '.'; + str[n+1] = '.'; + str[n+2] = '.'; + str[n+3] = '\0'; + } + return str; +} + +void +#ifdef __FunctionProto__ +load_constant(unsigned char *reg, int n, long addr) +#else +load_constant(reg, n, addr) +unsigned char *reg; +int n; +long addr; +#endif +{ + int i, p; + + p = saturn.P; + for (i = 0; i < n; i++) { + reg[p] = read_nibble(addr + i); + p = (p + 1) & 0xf; + } +} + +void +#ifdef __FunctionProto__ +load_addr(word_20 *dat, long addr, int n) +#else +load_addr(dat, addr, n) +word_20 *dat; +long addr; +int n; +#endif +{ + int i; + + for (i = 0; i < n; i++) { + *dat &= ~nibble_masks[i]; + *dat |= read_nibble(addr + i) << (i * 4); + } +} + +void +#ifdef __FunctionProto__ +load_address(unsigned char *reg, long addr, int n) +#else +load_address(reg, addr, n) +unsigned char *reg; +long addr; +int n; +#endif +{ + int i; + + for (i = 0; i < n; i++) { + reg[i] = read_nibble(addr + i); + } +} + +void +#ifdef __FunctionProto__ +register_to_address(unsigned char *reg, word_20 *dat, int s) +#else +register_to_address(reg, dat, s) +unsigned char *reg; +word_20 *dat; +int s; +#endif +{ + int i, n; + + if (s) + n = 4; + else + n = 5; + for (i = 0; i < n; i++) { + *dat &= ~nibble_masks[i]; + *dat |= (reg[i] & 0x0f) << (i * 4); + } +} + +void +#ifdef __FunctionProto__ +address_to_register(word_20 dat, unsigned char *reg, int s) +#else +address_to_register(dat, reg, s) +word_20 dat; +unsigned char *reg; +int s; +#endif +{ + int i, n; + + if (s) + n = 4; + else + n = 5; + for (i = 0; i < n; i++) { + reg[i] = dat & 0x0f; + dat >>= 4; + } +} + +long +#ifdef __FunctionProto__ +dat_to_addr(unsigned char *dat) +#else +dat_to_addr(dat) +unsigned char *dat; +#endif +{ + int i; + long addr; + + addr = 0; + for (i = 4; i >= 0; i--) { + addr <<= 4; + addr |= (dat[i] & 0xf); + } + return addr; +} + +void +#ifdef __FunctionProto__ +addr_to_dat(long addr, unsigned char *dat) +#else +addr_to_dat(addr, dat) +long addr; +unsigned char *dat; +#endif +{ + int i; + + for (i = 0; i < 5; i++) { + dat[i] = (addr & 0xf); + addr >>= 4; + } +} + +void +#ifdef __FunctionProto__ +add_address(word_20 *dat, int add) +#else +add_address(dat, add) +word_20 *dat; +int add; +#endif +{ + *dat += add; + if (*dat & (word_20)0xfff00000) { + saturn.CARRY = 1; + } else { + saturn.CARRY = 0; + } + *dat &= 0xfffff; +} + +static int start_fields[] = { + -1, 0, 2, 0, 15, 3, 0, 0, + -1, 0, 2, 0, 15, 3, 0, 0, + 0, 0, 0 +}; + +static int end_fields[] = { + -1, -1, 2, 2, 15, 14, 1, 15, + -1, -1, 2, 2, 15, 14, 1, 4, + 3, 2, 0 +}; + +static inline int +#ifdef __FunctionProto__ +get_start(int code) +#else +get_start(code) +int code; +#endif +{ + int s; + + if ((s = start_fields[code]) == -1) { + s = saturn.P; + } + return s; +} + +static inline int +#ifdef __FuntionProto__ +get_end(int code) +#else +get_end(code) +int code; +#endif +{ + int e; + + if ((e = end_fields[code]) == -1) { + e = saturn.P; + } + return e; +} + +void +#ifdef __FunctionProto__ +store(word_20 dat, unsigned char *reg, int code) +#else +store(dat, reg, code) +word_20 dat; +unsigned char *reg; +int code; +#endif +{ + int i, s, e; + + s = get_start(code); + e = get_end(code); + for (i = s; i <= e; i++) { + write_nibble(dat++, reg[i]); + } +} + +void +#ifdef __FunctionProto__ +store_n(word_20 dat, unsigned char *reg, int n) +#else +store_n(dat, reg, n) +word_20 dat; +unsigned char *reg; +int n; +#endif +{ + int i; + + for (i = 0; i < n; i++) { + write_nibble(dat++, reg[i]); + } +} + +void +#ifdef __FunctionProto__ +recall(unsigned char *reg, word_20 dat, int code) +#else +recall(reg, dat, code) +unsigned char *reg; +word_20 dat; +int code; +#endif +{ + int i, s, e; + + s = get_start(code); + e = get_end(code); + for (i = s; i <= e; i++) { + reg[i] = read_nibble_crc(dat++); + } +} + +void +#ifdef __FunctionProto__ +recall_n(unsigned char *reg, word_20 dat, int n) +#else +recall_n(reg, dat, n) +unsigned char *reg; +word_20 dat; +int n; +#endif +{ + int i; + + for (i = 0; i < n; i++) { + reg[i] = read_nibble_crc(dat++); + } +} + diff --git a/src/annunc.h b/src/annunc.h new file mode 100644 index 0000000..bd00d0f --- /dev/null +++ b/src/annunc.h @@ -0,0 +1,55 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: annunc.h,v $ + * Revision 1.4 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.3 1994/11/02 14:51:27 ecd + * minor fix + * + * Revision 1.3 1994/11/02 14:51:27 ecd + * minor fix + * + * Revision 1.2 1994/10/06 16:28:03 ecd + * changed char to unsigned + * + * Revision 1.1 1994/09/07 12:53:20 ecd + * Initial revision + * + * + * $Id: annunc.h,v 1.4 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#ifndef _ANNUNC_H +#define _ANNUNC_H 1 + +#include "bitmaps/ann_alpha.h" + +#include "bitmaps/ann_battery.h" + +#include "bitmaps/ann_busy.h" + +#include "bitmaps/ann_io.h" + +#include "bitmaps/ann_left.h" + +#include "bitmaps/ann_right.h" + +#endif /* !_ANNUNC_H */ diff --git a/src/append.h b/src/append.h new file mode 100644 index 0000000..a871d2c --- /dev/null +++ b/src/append.h @@ -0,0 +1,45 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: append.h,v $ + * Revision 1.3 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.2 1994/12/07 20:16:41 ecd + * deleted empty line at top of file + * + * Revision 1.2 1994/12/07 20:16:41 ecd + * deleted empty line at top of file + * + * Revision 1.1 1994/12/07 10:16:15 ecd + * Initial revision + * + * + * $Id: append.h,v 1.3 1995/01/11 18:20:01 ecd Exp ecd $ + */ +#ifndef _APPEND_H +#define _APPEND_H 1 + +#include "global.h" + +extern char * append_str __ProtoType__((char *buf, char *string)); +extern char * append_tab __ProtoType__((char *buf)); +extern char * append_tab_16 __ProtoType__((char *buf)); + +#endif /* !_APPEND_H */ diff --git a/src/bitmaps/A.h b/src/bitmaps/A.h new file mode 100644 index 0000000..0438537 --- /dev/null +++ b/src/bitmaps/A.h @@ -0,0 +1,5 @@ +#define A_width 5 +#define A_height 7 +static unsigned char A_bits[] = { + 0x0e, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11}; + diff --git a/src/bitmaps/B.h b/src/bitmaps/B.h new file mode 100644 index 0000000..9280b66 --- /dev/null +++ b/src/bitmaps/B.h @@ -0,0 +1,5 @@ +#define B_width 5 +#define B_height 7 +static unsigned char B_bits[] = { + 0x0f, 0x11, 0x11, 0x0f, 0x11, 0x11, 0x0f}; + diff --git a/src/bitmaps/C.h b/src/bitmaps/C.h new file mode 100644 index 0000000..59128b6 --- /dev/null +++ b/src/bitmaps/C.h @@ -0,0 +1,5 @@ +#define C_width 5 +#define C_height 7 +static unsigned char C_bits[] = { + 0x0e, 0x11, 0x01, 0x01, 0x01, 0x11, 0x0e}; + diff --git a/src/bitmaps/D.h b/src/bitmaps/D.h new file mode 100644 index 0000000..6c602d2 --- /dev/null +++ b/src/bitmaps/D.h @@ -0,0 +1,5 @@ +#define D_width 5 +#define D_height 7 +static unsigned char D_bits[] = { + 0x0f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0f}; + diff --git a/src/bitmaps/E.h b/src/bitmaps/E.h new file mode 100644 index 0000000..dfc2dd0 --- /dev/null +++ b/src/bitmaps/E.h @@ -0,0 +1,5 @@ +#define E_width 5 +#define E_height 7 +static unsigned char E_bits[] = { + 0x1f, 0x01, 0x01, 0x0f, 0x01, 0x01, 0x1f}; + diff --git a/src/bitmaps/F.h b/src/bitmaps/F.h new file mode 100644 index 0000000..8eaccfe --- /dev/null +++ b/src/bitmaps/F.h @@ -0,0 +1,5 @@ +#define F_width 5 +#define F_height 7 +static unsigned char F_bits[] = { + 0x1f, 0x01, 0x01, 0x0f, 0x01, 0x01, 0x01}; + diff --git a/src/bitmaps/G.h b/src/bitmaps/G.h new file mode 100644 index 0000000..74e8ef7 --- /dev/null +++ b/src/bitmaps/G.h @@ -0,0 +1,5 @@ +#define G_width 5 +#define G_height 7 +static unsigned char G_bits[] = { + 0x0e, 0x11, 0x01, 0x01, 0x19, 0x11, 0x0e}; + diff --git a/src/bitmaps/H.h b/src/bitmaps/H.h new file mode 100644 index 0000000..33b2903 --- /dev/null +++ b/src/bitmaps/H.h @@ -0,0 +1,5 @@ +#define H_width 5 +#define H_height 7 +static unsigned char H_bits[] = { + 0x11, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11}; + diff --git a/src/bitmaps/I.h b/src/bitmaps/I.h new file mode 100644 index 0000000..b979934 --- /dev/null +++ b/src/bitmaps/I.h @@ -0,0 +1,5 @@ +#define I_width 1 +#define I_height 7 +static unsigned char I_bits[] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; + diff --git a/src/bitmaps/J.h b/src/bitmaps/J.h new file mode 100644 index 0000000..16aab65 --- /dev/null +++ b/src/bitmaps/J.h @@ -0,0 +1,5 @@ +#define J_width 4 +#define J_height 7 +static unsigned char J_bits[] = { + 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x06}; + diff --git a/src/bitmaps/K.h b/src/bitmaps/K.h new file mode 100644 index 0000000..3dc9472 --- /dev/null +++ b/src/bitmaps/K.h @@ -0,0 +1,5 @@ +#define K_width 5 +#define K_height 7 +static unsigned char K_bits[] = { + 0x11, 0x09, 0x05, 0x03, 0x05, 0x09, 0x11}; + diff --git a/src/bitmaps/L.h b/src/bitmaps/L.h new file mode 100644 index 0000000..e9a38f1 --- /dev/null +++ b/src/bitmaps/L.h @@ -0,0 +1,5 @@ +#define L_width 4 +#define L_height 7 +static unsigned char L_bits[] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0f}; + diff --git a/src/bitmaps/M.h b/src/bitmaps/M.h new file mode 100644 index 0000000..d390971 --- /dev/null +++ b/src/bitmaps/M.h @@ -0,0 +1,5 @@ +#define M_width 5 +#define M_height 7 +static unsigned char M_bits[] = { + 0x11, 0x1b, 0x15, 0x11, 0x11, 0x11, 0x11}; + diff --git a/src/bitmaps/N.h b/src/bitmaps/N.h new file mode 100644 index 0000000..e210790 --- /dev/null +++ b/src/bitmaps/N.h @@ -0,0 +1,5 @@ +#define N_width 5 +#define N_height 7 +static unsigned char N_bits[] = { + 0x11, 0x11, 0x13, 0x15, 0x19, 0x11, 0x11}; + diff --git a/src/bitmaps/O.h b/src/bitmaps/O.h new file mode 100644 index 0000000..fd29036 --- /dev/null +++ b/src/bitmaps/O.h @@ -0,0 +1,5 @@ +#define O_width 5 +#define O_height 7 +static unsigned char O_bits[] = { + 0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e}; + diff --git a/src/bitmaps/P.h b/src/bitmaps/P.h new file mode 100644 index 0000000..0ec8db1 --- /dev/null +++ b/src/bitmaps/P.h @@ -0,0 +1,5 @@ +#define P_width 5 +#define P_height 7 +static unsigned char P_bits[] = { + 0x0f, 0x11, 0x11, 0x0f, 0x01, 0x01, 0x01}; + diff --git a/src/bitmaps/Q.h b/src/bitmaps/Q.h new file mode 100644 index 0000000..11f23c1 --- /dev/null +++ b/src/bitmaps/Q.h @@ -0,0 +1,5 @@ +#define Q_width 5 +#define Q_height 7 +static unsigned char Q_bits[] = { + 0x0e, 0x11, 0x11, 0x11, 0x15, 0x09, 0x16}; + diff --git a/src/bitmaps/R.h b/src/bitmaps/R.h new file mode 100644 index 0000000..a36f088 --- /dev/null +++ b/src/bitmaps/R.h @@ -0,0 +1,5 @@ +#define R_width 5 +#define R_height 7 +static unsigned char R_bits[] = { + 0x0f, 0x11, 0x11, 0x0f, 0x05, 0x09, 0x11}; + diff --git a/src/bitmaps/S.h b/src/bitmaps/S.h new file mode 100644 index 0000000..e75f1b3 --- /dev/null +++ b/src/bitmaps/S.h @@ -0,0 +1,5 @@ +#define S_width 5 +#define S_height 7 +static unsigned char S_bits[] = { + 0x0e, 0x11, 0x01, 0x0e, 0x10, 0x11, 0x0e}; + diff --git a/src/bitmaps/T.h b/src/bitmaps/T.h new file mode 100644 index 0000000..2be3707 --- /dev/null +++ b/src/bitmaps/T.h @@ -0,0 +1,5 @@ +#define T_width 5 +#define T_height 7 +static unsigned char T_bits[] = { + 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04}; + diff --git a/src/bitmaps/U.h b/src/bitmaps/U.h new file mode 100644 index 0000000..0f91bff --- /dev/null +++ b/src/bitmaps/U.h @@ -0,0 +1,5 @@ +#define U_width 5 +#define U_height 7 +static unsigned char U_bits[] = { + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e}; + diff --git a/src/bitmaps/V.h b/src/bitmaps/V.h new file mode 100644 index 0000000..8750cf3 --- /dev/null +++ b/src/bitmaps/V.h @@ -0,0 +1,5 @@ +#define V_width 5 +#define V_height 7 +static unsigned char V_bits[] = { + 0x11, 0x11, 0x11, 0x11, 0x0a, 0x0a, 0x04}; + diff --git a/src/bitmaps/W.h b/src/bitmaps/W.h new file mode 100644 index 0000000..ef468c0 --- /dev/null +++ b/src/bitmaps/W.h @@ -0,0 +1,5 @@ +#define W_width 5 +#define W_height 7 +static unsigned char W_bits[] = { + 0x11, 0x11, 0x11, 0x11, 0x15, 0x1b, 0x11}; + diff --git a/src/bitmaps/X.h b/src/bitmaps/X.h new file mode 100644 index 0000000..791aea0 --- /dev/null +++ b/src/bitmaps/X.h @@ -0,0 +1,5 @@ +#define X_width 5 +#define X_height 7 +static unsigned char X_bits[] = { + 0x11, 0x11, 0x0a, 0x04, 0x0a, 0x11, 0x11}; + diff --git a/src/bitmaps/Y.h b/src/bitmaps/Y.h new file mode 100644 index 0000000..72cd5ff --- /dev/null +++ b/src/bitmaps/Y.h @@ -0,0 +1,5 @@ +#define Y_width 5 +#define Y_height 7 +static unsigned char Y_bits[] = { + 0x11, 0x11, 0x0a, 0x04, 0x04, 0x04, 0x04}; + diff --git a/src/bitmaps/Z.h b/src/bitmaps/Z.h new file mode 100644 index 0000000..fc44dac --- /dev/null +++ b/src/bitmaps/Z.h @@ -0,0 +1,5 @@ +#define Z_width 5 +#define Z_height 7 +static unsigned char Z_bits[] = { + 0x1f, 0x10, 0x08, 0x04, 0x02, 0x01, 0x1f}; + diff --git a/src/bitmaps/alpha.h b/src/bitmaps/alpha.h new file mode 100644 index 0000000..362ea67 --- /dev/null +++ b/src/bitmaps/alpha.h @@ -0,0 +1,6 @@ +#define alpha_width 12 +#define alpha_height 10 +static unsigned char alpha_bits[] = { + 0x78, 0x00, 0x84, 0x08, 0x82, 0x09, 0x83, 0x05, 0x83, 0x05, 0x83, 0x03, + 0x83, 0x01, 0x83, 0x01, 0x46, 0x09, 0x3c, 0x06}; + diff --git a/src/bitmaps/angle.h b/src/bitmaps/angle.h new file mode 100644 index 0000000..38323b6 --- /dev/null +++ b/src/bitmaps/angle.h @@ -0,0 +1,5 @@ +#define angle_width 8 +#define angle_height 7 +static unsigned char angle_bits[] = { + 0x40, 0x20, 0x10, 0x28, 0x44, 0x42, 0xff}; + diff --git a/src/bitmaps/angle_gx.h b/src/bitmaps/angle_gx.h new file mode 100644 index 0000000..1e5626a --- /dev/null +++ b/src/bitmaps/angle_gx.h @@ -0,0 +1,6 @@ +#define angle_gx_width 12 +#define angle_gx_height 12 +static unsigned char angle_gx_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0xe0, 0x01, + 0xb0, 0x03, 0x18, 0x03, 0x0c, 0x03, 0x06, 0x03, 0xff, 0x0f, 0xff, 0x0f}; + diff --git a/src/bitmaps/ann_alpha.h b/src/bitmaps/ann_alpha.h new file mode 100644 index 0000000..3dbff5c --- /dev/null +++ b/src/bitmaps/ann_alpha.h @@ -0,0 +1,6 @@ +#define ann_alpha_width 15 +#define ann_alpha_height 12 +static unsigned char ann_alpha_bits[] = { + 0xe0, 0x03, 0x18, 0x44, 0x0c, 0x4c, 0x06, 0x2c, 0x07, 0x2c, 0x07, 0x1c, + 0x07, 0x0c, 0x07, 0x0c, 0x07, 0x0e, 0x0e, 0x4d, 0xf8, 0x38, 0x00, 0x00}; + diff --git a/src/bitmaps/ann_battery.h b/src/bitmaps/ann_battery.h new file mode 100644 index 0000000..7a906c6 --- /dev/null +++ b/src/bitmaps/ann_battery.h @@ -0,0 +1,6 @@ +#define ann_battery_width 15 +#define ann_battery_height 12 +static unsigned char ann_battery_bits[] = { + 0x04, 0x10, 0x02, 0x20, 0x12, 0x24, 0x09, 0x48, 0xc9, 0x49, 0xc9, 0x49, + 0xc9, 0x49, 0x09, 0x48, 0x12, 0x24, 0x02, 0x20, 0x04, 0x10, 0x00, 0x00}; + diff --git a/src/bitmaps/ann_busy.h b/src/bitmaps/ann_busy.h new file mode 100644 index 0000000..083238b --- /dev/null +++ b/src/bitmaps/ann_busy.h @@ -0,0 +1,6 @@ +#define ann_busy_width 15 +#define ann_busy_height 12 +static unsigned char ann_busy_bits[] = { + 0xfc, 0x1f, 0x08, 0x08, 0x08, 0x08, 0xf0, 0x07, 0xe0, 0x03, 0xc0, 0x01, + 0x40, 0x01, 0x20, 0x02, 0x10, 0x04, 0xc8, 0x09, 0xe8, 0x0b, 0xfc, 0x1f}; + diff --git a/src/bitmaps/ann_io.h b/src/bitmaps/ann_io.h new file mode 100644 index 0000000..0db7383 --- /dev/null +++ b/src/bitmaps/ann_io.h @@ -0,0 +1,6 @@ +#define ann_io_width 15 +#define ann_io_height 12 +static unsigned char ann_io_bits[] = { + 0x0c, 0x00, 0x1e, 0x00, 0x33, 0x0c, 0x61, 0x18, 0xcc, 0x30, 0xfe, 0x7f, + 0xfe, 0x7f, 0xcc, 0x30, 0x61, 0x18, 0x33, 0x0c, 0x1e, 0x00, 0x0c, 0x00}; + diff --git a/src/bitmaps/ann_left.h b/src/bitmaps/ann_left.h new file mode 100644 index 0000000..e0d86c3 --- /dev/null +++ b/src/bitmaps/ann_left.h @@ -0,0 +1,6 @@ +#define ann_left_width 15 +#define ann_left_height 12 +static unsigned char ann_left_bits[] = { + 0xfe, 0x3f, 0xff, 0x7f, 0x9f, 0x7f, 0xcf, 0x7f, 0xe7, 0x7f, 0x03, 0x78, + 0x03, 0x70, 0xe7, 0x73, 0xcf, 0x73, 0x9f, 0x73, 0xff, 0x73, 0xfe, 0x33}; + diff --git a/src/bitmaps/ann_right.h b/src/bitmaps/ann_right.h new file mode 100644 index 0000000..55213df --- /dev/null +++ b/src/bitmaps/ann_right.h @@ -0,0 +1,6 @@ +#define ann_right_width 15 +#define ann_right_height 12 +static unsigned char ann_right_bits[] = { + 0xfe, 0x3f, 0xff, 0x7f, 0xff, 0x7c, 0xff, 0x79, 0xff, 0x73, 0x0f, 0x60, + 0x07, 0x60, 0xe7, 0x73, 0xe7, 0x79, 0xe7, 0x7c, 0xe7, 0x7f, 0xe6, 0x3f}; + diff --git a/src/bitmaps/arrow.h b/src/bitmaps/arrow.h new file mode 100644 index 0000000..25b6f49 --- /dev/null +++ b/src/bitmaps/arrow.h @@ -0,0 +1,5 @@ +#define arrow_width 7 +#define arrow_height 7 +static unsigned char arrow_bits[] = { + 0x00, 0x08, 0x18, 0x3f, 0x18, 0x08, 0x00}; + diff --git a/src/bitmaps/arrow_gx.h b/src/bitmaps/arrow_gx.h new file mode 100644 index 0000000..9e05981 --- /dev/null +++ b/src/bitmaps/arrow_gx.h @@ -0,0 +1,7 @@ +#define arrow_gx_width 18 +#define arrow_gx_height 12 +static unsigned char arrow_gx_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x3c, 0x00, + 0x00, 0xfc, 0x00, 0xff, 0xff, 0x03, 0xff, 0xff, 0x03, 0x00, 0xfc, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + diff --git a/src/bitmaps/blank.h b/src/bitmaps/blank.h new file mode 100644 index 0000000..a506de3 --- /dev/null +++ b/src/bitmaps/blank.h @@ -0,0 +1,5 @@ +#define blank_width 4 +#define blank_height 7 +static unsigned char blank_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + diff --git a/src/bitmaps/bracket_gx.h b/src/bitmaps/bracket_gx.h new file mode 100644 index 0000000..6b07e93 --- /dev/null +++ b/src/bitmaps/bracket_gx.h @@ -0,0 +1,6 @@ +#define bracket_gx_width 12 +#define bracket_gx_height 12 +static unsigned char bracket_gx_bits[] = { + 0x0f, 0x0f, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, + 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x0f, 0x0f}; + diff --git a/src/bitmaps/bs.h b/src/bitmaps/bs.h new file mode 100644 index 0000000..bdf9838 --- /dev/null +++ b/src/bitmaps/bs.h @@ -0,0 +1,6 @@ +#define bs_width 11 +#define bs_height 11 +static unsigned char bs_bits[] = { + 0x20, 0x00, 0x30, 0x00, 0x38, 0x00, 0xfc, 0x07, 0xfe, 0x07, 0xff, 0x07, + 0xfe, 0x07, 0xfc, 0x07, 0x38, 0x00, 0x30, 0x00, 0x20, 0x00}; + diff --git a/src/bitmaps/colon.h b/src/bitmaps/colon.h new file mode 100644 index 0000000..955c22c --- /dev/null +++ b/src/bitmaps/colon.h @@ -0,0 +1,5 @@ +#define colon_width 2 +#define colon_height 10 +static unsigned char colon_bits[] = { + 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + diff --git a/src/bitmaps/colon_gx.h b/src/bitmaps/colon_gx.h new file mode 100644 index 0000000..67d639e --- /dev/null +++ b/src/bitmaps/colon_gx.h @@ -0,0 +1,5 @@ +#define colon_gx_width 8 +#define colon_gx_height 12 +static unsigned char colon_gx_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x00, 0x00, 0xc3, 0xc3, 0x00}; + diff --git a/src/bitmaps/comma.h b/src/bitmaps/comma.h new file mode 100644 index 0000000..3886ff7 --- /dev/null +++ b/src/bitmaps/comma.h @@ -0,0 +1,5 @@ +#define comma_width 3 +#define comma_height 7 +static unsigned char comma_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x03}; + diff --git a/src/bitmaps/comma_gx.h b/src/bitmaps/comma_gx.h new file mode 100644 index 0000000..810cca7 --- /dev/null +++ b/src/bitmaps/comma_gx.h @@ -0,0 +1,5 @@ +#define comma_gx_width 3 +#define comma_gx_height 12 +static unsigned char comma_gx_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x04, 0x04, 0x02}; + diff --git a/src/bitmaps/curly_gx.h b/src/bitmaps/curly_gx.h new file mode 100644 index 0000000..134eda3 --- /dev/null +++ b/src/bitmaps/curly_gx.h @@ -0,0 +1,6 @@ +#define curly_gx_width 14 +#define curly_gx_height 12 +static unsigned char curly_gx_bits[] = { + 0x0c, 0x0c, 0x06, 0x18, 0x06, 0x18, 0x06, 0x18, 0x06, 0x18, 0x03, 0x30, + 0x06, 0x18, 0x06, 0x18, 0x06, 0x18, 0x06, 0x18, 0x06, 0x18, 0x0c, 0x0c}; + diff --git a/src/bitmaps/diff.h b/src/bitmaps/diff.h new file mode 100644 index 0000000..19f8d88 --- /dev/null +++ b/src/bitmaps/diff.h @@ -0,0 +1,5 @@ +#define diff_width 5 +#define diff_height 7 +static unsigned char diff_bits[] = { + 0x0e, 0x10, 0x10, 0x1e, 0x11, 0x11, 0x0e}; + diff --git a/src/bitmaps/div.h b/src/bitmaps/div.h new file mode 100644 index 0000000..be7c0f7 --- /dev/null +++ b/src/bitmaps/div.h @@ -0,0 +1,6 @@ +#define div_width 10 +#define div_height 10 +static unsigned char div_bits[] = { + 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xff, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00}; + diff --git a/src/bitmaps/down.h b/src/bitmaps/down.h new file mode 100644 index 0000000..139aeb8 --- /dev/null +++ b/src/bitmaps/down.h @@ -0,0 +1,6 @@ +#define down_width 11 +#define down_height 11 +static unsigned char down_bits[] = { + 0xff, 0x07, 0xfe, 0x03, 0xfe, 0x03, 0xfc, 0x01, 0xfc, 0x01, 0xf8, 0x00, + 0xf8, 0x00, 0x70, 0x00, 0x70, 0x00, 0x20, 0x00, 0x20, 0x00}; + diff --git a/src/bitmaps/equal.h b/src/bitmaps/equal.h new file mode 100644 index 0000000..d7b9768 --- /dev/null +++ b/src/bitmaps/equal.h @@ -0,0 +1,5 @@ +#define equal_width 5 +#define equal_height 7 +static unsigned char equal_bits[] = { + 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00}; + diff --git a/src/bitmaps/equal_gx.h b/src/bitmaps/equal_gx.h new file mode 100644 index 0000000..cf64a72 --- /dev/null +++ b/src/bitmaps/equal_gx.h @@ -0,0 +1,5 @@ +#define equal_gx_width 8 +#define equal_gx_height 12 +static unsigned char equal_gx_bits[] = { + 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00}; + diff --git a/src/bitmaps/exp.h b/src/bitmaps/exp.h new file mode 100644 index 0000000..06333cd --- /dev/null +++ b/src/bitmaps/exp.h @@ -0,0 +1,6 @@ +#define exp_width 11 +#define exp_height 9 +static unsigned char exp_bits[] = { + 0x80, 0x04, 0x00, 0x03, 0x00, 0x01, 0x8c, 0x02, 0x52, 0x02, 0x09, 0x00, + 0x07, 0x00, 0x21, 0x00, 0x1e, 0x00}; + diff --git a/src/bitmaps/exp_gx.h b/src/bitmaps/exp_gx.h new file mode 100644 index 0000000..7242017 --- /dev/null +++ b/src/bitmaps/exp_gx.h @@ -0,0 +1,5 @@ +#define exp_gx_width 13 +#define exp_gx_height 12 +static unsigned char exp_gx_bits[] = { + 0x00, 0xfb, 0x00, 0xf6, 0x00, 0xe6, 0x00, 0xf6, 0x80, 0xed, 0x18, 0xe0, + 0x36, 0xe0, 0x36, 0xe0, 0x1f, 0xe0, 0x03, 0xe0, 0x13, 0xe0, 0x0e, 0xe0}; diff --git a/src/bitmaps/gx_128K_ram.h b/src/bitmaps/gx_128K_ram.h new file mode 100644 index 0000000..a98cfdf --- /dev/null +++ b/src/bitmaps/gx_128K_ram.h @@ -0,0 +1,20 @@ +#define gx_128K_ram_width 43 +#define gx_128K_ram_height 31 +static unsigned char gx_128K_ram_bits[] = { + 0xfe, 0xdf, 0xff, 0xff, 0x03, 0x00, 0xfe, 0xdf, 0xff, 0xff, 0x03, 0x00, + 0xfe, 0xdf, 0xff, 0xff, 0x03, 0x00, 0xe2, 0xdf, 0xff, 0xff, 0x03, 0x00, + 0x9c, 0xdf, 0xff, 0xff, 0x03, 0x00, 0x7e, 0xdf, 0xff, 0xff, 0x01, 0x00, + 0x7e, 0xdf, 0xff, 0xff, 0x01, 0x00, 0xfe, 0xde, 0xff, 0xff, 0x02, 0x00, + 0xfe, 0xde, 0xff, 0xff, 0x02, 0x00, 0xfe, 0xdd, 0xff, 0x7f, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xdd, 0xff, 0xbf, 0x03, 0x00, + 0xfe, 0xdb, 0xff, 0xdf, 0x03, 0x00, 0xfe, 0xdb, 0xff, 0xef, 0x03, 0x00, + 0xfe, 0xd7, 0xff, 0xf7, 0x03, 0x00, 0xfe, 0xcf, 0xff, 0xfb, 0x03, 0x00, + 0xfe, 0xcf, 0xff, 0xfc, 0x03, 0x00, 0xfe, 0x1f, 0x3f, 0xff, 0x03, 0x00, + 0xfe, 0xdf, 0xc0, 0xff, 0x03, 0x00, 0xfe, 0xdf, 0xff, 0xff, 0x03, 0x00, + 0xfe, 0xdf, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x30, 0x12, 0x1c, 0x44, 0x04, + 0x27, 0x49, 0x0a, 0x24, 0x46, 0x04, 0x84, 0x39, 0x06, 0x24, 0xc9, 0x06, + 0x62, 0x24, 0x07, 0x9e, 0xaf, 0x06, 0x12, 0x24, 0x09, 0x92, 0xa8, 0x05, + 0xf2, 0x18, 0x11, 0x52, 0x28, 0x05}; + diff --git a/src/bitmaps/gx_green.h b/src/bitmaps/gx_green.h new file mode 100644 index 0000000..28e5b01 --- /dev/null +++ b/src/bitmaps/gx_green.h @@ -0,0 +1,14 @@ +#define gx_green_width 34 +#define gx_green_height 22 +static unsigned char gx_green_bits[] = { + 0xff, 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, + 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, + 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, + 0xf0, 0x03, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0xf0, 0x03, + 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, + 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0xf0, + 0x03, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, + 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, + 0xf0, 0x03}; + diff --git a/src/bitmaps/gx_silver.h b/src/bitmaps/gx_silver.h new file mode 100644 index 0000000..20879f8 --- /dev/null +++ b/src/bitmaps/gx_silver.h @@ -0,0 +1,13 @@ +#define gx_silver_width 35 +#define gx_silver_height 21 +static unsigned char gx_silver_bits[] = { + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x38, 0x40, 0x00, 0x00, 0x00, 0xc4, 0x40, 0x00, 0x00, + 0x00, 0x02, 0x41, 0x00, 0x00, 0x04, 0x02, 0x41, 0x00, 0x00, 0x04, 0x02, + 0x42, 0x00, 0x00, 0x02, 0x01, 0x42, 0x00, 0x00, 0x02, 0x01, 0x44, 0x00, + 0x00, 0x01, 0xfd, 0xff, 0xff, 0xff, 0x07, 0x01, 0x44, 0x00, 0x80, 0x00, + 0x01, 0x48, 0x00, 0x40, 0x00, 0x01, 0x48, 0x00, 0x20, 0x00, 0x00, 0x50, + 0x00, 0x10, 0x00, 0x00, 0x60, 0x00, 0x08, 0x00, 0x00, 0x60, 0x00, 0x06, + 0x00, 0x00, 0xc0, 0x81, 0x01, 0x00, 0x00, 0x40, 0x7e, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00}; + diff --git a/src/bitmaps/hash.h b/src/bitmaps/hash.h new file mode 100644 index 0000000..56ce3b8 --- /dev/null +++ b/src/bitmaps/hash.h @@ -0,0 +1,5 @@ +#define hash_width 5 +#define hash_height 7 +static unsigned char hash_bits[] = { + 0x00, 0x0a, 0x1f, 0x0a, 0x0a, 0x1f, 0x0a}; + diff --git a/src/bitmaps/hash_gx.h b/src/bitmaps/hash_gx.h new file mode 100644 index 0000000..0481048 --- /dev/null +++ b/src/bitmaps/hash_gx.h @@ -0,0 +1,5 @@ +#define hash_gx_width 8 +#define hash_gx_height 12 +static unsigned char hash_gx_bits[] = { + 0x00, 0x00, 0x48, 0x48, 0xfe, 0x24, 0x24, 0x7f, 0x12, 0x12, 0x00, 0x00}; + diff --git a/src/bitmaps/hp.h b/src/bitmaps/hp.h new file mode 100644 index 0000000..4c849d8 --- /dev/null +++ b/src/bitmaps/hp.h @@ -0,0 +1,28 @@ +#define hp_width 96 +#define hp_height 24 +static unsigned char hp_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0x9f, 0xfd, 0x3f, 0x60, 0xcc, 0x6f, 0x66, 0x83, 0xdf, 0xff, 0x3f, + 0xfc, 0x9f, 0xf1, 0x7f, 0x60, 0xcc, 0x60, 0x66, 0x83, 0x01, 0x06, 0x06, + 0xfc, 0xc7, 0xc0, 0x7f, 0x60, 0xcc, 0x60, 0x66, 0x83, 0x01, 0x06, 0x06, + 0xfc, 0xc3, 0x80, 0x7f, 0x60, 0xcc, 0x40, 0x26, 0x83, 0x01, 0x06, 0x06, + 0xfc, 0x61, 0x00, 0x7f, 0xe0, 0xcf, 0xcf, 0x36, 0x83, 0x1f, 0x06, 0x06, + 0xfc, 0x60, 0x00, 0x7e, 0x60, 0xcc, 0xc0, 0x36, 0x83, 0x01, 0x06, 0x06, + 0xfc, 0x30, 0x00, 0x7e, 0x60, 0xcc, 0x80, 0x19, 0x83, 0x01, 0x06, 0x06, + 0x7c, 0xb0, 0x68, 0x7c, 0x60, 0xcc, 0x80, 0x19, 0x83, 0x01, 0x06, 0x06, + 0x7c, 0xf8, 0xf9, 0x7c, 0x60, 0xcc, 0x8f, 0x19, 0xbf, 0x1f, 0x06, 0x06, + 0x7c, 0x98, 0xcd, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7c, 0xcc, 0xcc, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7c, 0xcc, 0x66, 0x7c, 0xe0, 0x87, 0x81, 0x67, 0x0c, 0xc3, 0xcf, 0x0f, + 0x7c, 0x66, 0x66, 0x7c, 0x60, 0xcc, 0xc3, 0x6c, 0x86, 0xc7, 0xd8, 0x18, + 0x7c, 0x66, 0x3f, 0x7e, 0x60, 0x4c, 0x62, 0x60, 0x83, 0xc4, 0xd8, 0x30, + 0xfc, 0x00, 0x03, 0x7e, 0x60, 0x6c, 0x66, 0xe0, 0xc1, 0xcc, 0xd8, 0x30, + 0xfc, 0x80, 0x01, 0x7f, 0xe0, 0x67, 0x66, 0xe0, 0xc1, 0xcc, 0xcf, 0x30, + 0xfc, 0x81, 0x81, 0x7f, 0x60, 0xe0, 0x67, 0x60, 0xc3, 0xcf, 0xcc, 0x30, + 0xfc, 0xc3, 0xc0, 0x7f, 0x60, 0x30, 0x6c, 0x60, 0x66, 0xd8, 0xd8, 0x30, + 0xfc, 0xcf, 0xf0, 0x7f, 0x60, 0x30, 0xcc, 0x6c, 0x6c, 0xd8, 0xd8, 0x18, + 0xf8, 0x6f, 0xfe, 0x3f, 0x60, 0x30, 0x8c, 0x67, 0x78, 0xd8, 0xd8, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + diff --git a/src/bitmaps/hp48_blue.h b/src/bitmaps/hp48_blue.h new file mode 100644 index 0000000..1704f55 --- /dev/null +++ b/src/bitmaps/hp48_blue.h @@ -0,0 +1,9 @@ +#define hp48_blue_width 5 +#define hp48_blue_height 57 +static unsigned char hp48_blue_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1c}; + diff --git a/src/bitmaps/hp48_bottom.h b/src/bitmaps/hp48_bottom.h new file mode 100644 index 0000000..f7e970f --- /dev/null +++ b/src/bitmaps/hp48_bottom.h @@ -0,0 +1,26 @@ +#define hp48_bottom_width 32 +#define hp48_bottom_height 64 +static unsigned char hp48_bottom_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x63, 0x8c, 0x31, 0xc6, 0x63, 0x8c, 0x31, 0xc6, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x63, 0x8c, 0x31, 0xc6, + 0x63, 0x8c, 0x31, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x63, 0x8c, 0x31, 0xc6, 0x63, 0x8c, 0x31, 0xc6, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x03, 0x8c, 0x31, 0xc6, 0x03, 0x8c, 0x31, 0xc6, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x30, 0x0c, 0xc3, + 0xe3, 0x30, 0x0c, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xe3, 0x30, 0x0c, 0xc3, 0xe3, 0x30, 0x0c, 0xc3, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xe3, 0x30, 0x0c, 0xc3, 0xe3, 0x30, 0x0c, 0xc3, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x30, 0x0c, 0xc3, + 0xe3, 0x30, 0x0c, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff}; + diff --git a/src/bitmaps/hp48_disp.h b/src/bitmaps/hp48_disp.h new file mode 100644 index 0000000..274fa98 --- /dev/null +++ b/src/bitmaps/hp48_disp.h @@ -0,0 +1,11 @@ +#define hp48_disp_width 29 +#define hp48_disp_height 21 +static unsigned char hp48_disp_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x1f, + 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f, + 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f, + 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f, + 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f}; + diff --git a/src/bitmaps/hp48_green_gx.h b/src/bitmaps/hp48_green_gx.h new file mode 100644 index 0000000..1cae195 --- /dev/null +++ b/src/bitmaps/hp48_green_gx.h @@ -0,0 +1,23 @@ +#define hp48_green_gx_width 29 +#define hp48_green_gx_height 57 +static unsigned char hp48_green_gx_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00}; + diff --git a/src/bitmaps/hp48_icon.h b/src/bitmaps/hp48_icon.h new file mode 100644 index 0000000..150bba6 --- /dev/null +++ b/src/bitmaps/hp48_icon.h @@ -0,0 +1,26 @@ +#define hp48_icon_width 32 +#define hp48_icon_height 64 +static unsigned char hp48_icon_bits[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, + 0x07, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x07, 0xff, 0x01, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xe0, + 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, + 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, + 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, + 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x63, 0x8c, 0x31, 0xc6, 0x63, 0x8c, 0x31, 0xc6, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x63, 0x8c, 0x31, 0xc6, 0x63, 0x8c, 0x31, 0xc6, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x63, 0x8c, 0x31, 0xc6, + 0x63, 0x8c, 0x31, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x63, 0x8c, 0x31, 0xc6, 0x63, 0x8c, 0x31, 0xc6, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x03, 0x8c, 0x31, 0xc6, 0x03, 0x8c, 0x31, 0xc6, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x30, 0x0c, 0xc3, + 0xe3, 0x30, 0x0c, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xe3, 0x30, 0x0c, 0xc3, 0xe3, 0x30, 0x0c, 0xc3, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xe3, 0x30, 0x0c, 0xc3, 0xe3, 0x30, 0x0c, 0xc3, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x30, 0x0c, 0xc3, + 0xe3, 0x30, 0x0c, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff}; + diff --git a/src/bitmaps/hp48_keys.h b/src/bitmaps/hp48_keys.h new file mode 100644 index 0000000..dc2ae29 --- /dev/null +++ b/src/bitmaps/hp48_keys.h @@ -0,0 +1,25 @@ +#define hp48_keys_width 30 +#define hp48_keys_height 61 +static unsigned char hp48_keys_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x73, 0xce, 0x39, 0x9c, 0x73, 0xce, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9c, 0x73, 0xce, 0x39, 0x9c, 0x73, 0xce, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x73, 0xce, 0x39, + 0x9c, 0x73, 0xce, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x73, 0xce, 0x39, 0x9c, 0x73, 0xce, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfc, 0x73, 0xce, 0x39, 0xfc, 0x73, 0xce, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xcf, 0xf3, 0x3c, + 0x1c, 0xcf, 0xf3, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xcf, 0xf3, 0x3c, 0x00, 0xcf, 0xf3, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0xf3, 0x3c, 0x00, 0xcf, 0xf3, 0x3c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xcf, 0xf3, 0x3c, + 0x1c, 0xcf, 0xf3, 0x3c}; + diff --git a/src/bitmaps/hp48_logo.h b/src/bitmaps/hp48_logo.h new file mode 100644 index 0000000..8ab9c21 --- /dev/null +++ b/src/bitmaps/hp48_logo.h @@ -0,0 +1,5 @@ +#define hp48_logo_width 13 +#define hp48_logo_height 4 +static unsigned char hp48_logo_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0xf8, 0x1f}; + diff --git a/src/bitmaps/hp48_logo_gx.h b/src/bitmaps/hp48_logo_gx.h new file mode 100644 index 0000000..46a2010 --- /dev/null +++ b/src/bitmaps/hp48_logo_gx.h @@ -0,0 +1,5 @@ +#define hp48_logo_gx_width 16 +#define hp48_logo_gx_height 4 +static unsigned char hp48_logo_gx_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0xf8, 0xf7, 0xf8, 0xf7}; + diff --git a/src/bitmaps/hp48_on.h b/src/bitmaps/hp48_on.h new file mode 100644 index 0000000..226c029 --- /dev/null +++ b/src/bitmaps/hp48_on.h @@ -0,0 +1,11 @@ +#define hp48_on_width 25 +#define hp48_on_height 19 +static unsigned char hp48_on_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x13, 0x01, + 0x00, 0x80, 0x12, 0x01, 0x80, 0x48, 0x12, 0x01, 0x80, 0xc8, 0xe7, 0x00, + 0x00, 0x05, 0x12, 0x01, 0x00, 0x02, 0x12, 0x01, 0x00, 0x05, 0x12, 0x01, + 0x80, 0x08, 0xe2, 0x00}; + diff --git a/src/bitmaps/hp48_orange.h b/src/bitmaps/hp48_orange.h new file mode 100644 index 0000000..c2100dc --- /dev/null +++ b/src/bitmaps/hp48_orange.h @@ -0,0 +1,9 @@ +#define hp48_orange_width 5 +#define hp48_orange_height 53 +static unsigned char hp48_orange_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1c, 0x1c}; + diff --git a/src/bitmaps/hp48_text.h b/src/bitmaps/hp48_text.h new file mode 100644 index 0000000..a375d83 --- /dev/null +++ b/src/bitmaps/hp48_text.h @@ -0,0 +1,7 @@ +#define hp48_text_width 29 +#define hp48_text_height 7 +static unsigned char hp48_text_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0x00, 0xfe, 0x1f}; + diff --git a/src/bitmaps/hp48_text_gx.h b/src/bitmaps/hp48_text_gx.h new file mode 100644 index 0000000..bcc2a41 --- /dev/null +++ b/src/bitmaps/hp48_text_gx.h @@ -0,0 +1,7 @@ +#define hp48_text_gx_width 29 +#define hp48_text_gx_height 7 +static unsigned char hp48_text_gx_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f}; + diff --git a/src/bitmaps/hp48_top.h b/src/bitmaps/hp48_top.h new file mode 100644 index 0000000..3f7c38e --- /dev/null +++ b/src/bitmaps/hp48_top.h @@ -0,0 +1,14 @@ +#define hp48_top_width 32 +#define hp48_top_height 30 +static unsigned char hp48_top_bits[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, + 0x07, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x07, 0xff, 0x01, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xe0, + 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, + 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, + 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, + 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x63, 0x8c, 0x31, 0xc6, 0x63, 0x8c, 0x31, 0xc6, 0xff, 0xff, 0xff, 0xff}; + diff --git a/src/bitmaps/hp48_top_gx.h b/src/bitmaps/hp48_top_gx.h new file mode 100644 index 0000000..f2735e8 --- /dev/null +++ b/src/bitmaps/hp48_top_gx.h @@ -0,0 +1,14 @@ +#define hp48_top_gx_width 32 +#define hp48_top_gx_height 30 +static unsigned char hp48_top_gx_bits[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x08, 0xff, 0xe1, + 0x07, 0x08, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xe0, + 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, + 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, + 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, + 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x63, 0x8c, 0x31, 0xc6, 0x63, 0x8c, 0x31, 0xc6, 0xff, 0xff, 0xff, 0xff}; + diff --git a/src/bitmaps/hp48gx.h b/src/bitmaps/hp48gx.h new file mode 100644 index 0000000..e1b6aba --- /dev/null +++ b/src/bitmaps/hp48gx.h @@ -0,0 +1,11 @@ +#define hp48gx_width 44 +#define hp48gx_height 14 +static unsigned char hp48gx_bits[] = { + 0x00, 0xc3, 0x03, 0x7c, 0x0c, 0x0c, 0x80, 0xe3, 0x07, 0xff, 0x0c, 0x0e, + 0xc0, 0x33, 0x86, 0xc3, 0x1c, 0x06, 0xe0, 0x31, 0xc6, 0xc0, 0x18, 0x03, + 0xb0, 0x31, 0xe6, 0x00, 0xb0, 0x01, 0x98, 0x31, 0x63, 0x00, 0xf0, 0x01, + 0x8c, 0xe1, 0x61, 0x00, 0xe0, 0x00, 0xc6, 0xb8, 0x31, 0xfc, 0x70, 0x00, + 0xc7, 0x18, 0x33, 0xfc, 0xf8, 0x00, 0xff, 0x0d, 0x33, 0x60, 0xd8, 0x00, + 0xff, 0x0d, 0x73, 0x60, 0x8c, 0x01, 0x60, 0x8c, 0x63, 0x30, 0x86, 0x03, + 0x60, 0xfc, 0xe1, 0x3f, 0x07, 0x03, 0x60, 0xf8, 0x80, 0x37, 0x03, 0x03}; + diff --git a/src/bitmaps/hp48sx.h b/src/bitmaps/hp48sx.h new file mode 100644 index 0000000..f60539e --- /dev/null +++ b/src/bitmaps/hp48sx.h @@ -0,0 +1,9 @@ +#define hp48sx_width 42 +#define hp48sx_height 10 +static unsigned char hp48sx_bits[] = { + 0xe0, 0xf1, 0xc3, 0x3f, 0x87, 0x03, 0xf0, 0xf9, 0xe7, 0x7f, 0xc7, 0x01, + 0xf8, 0x39, 0xe7, 0x70, 0xee, 0x00, 0xdc, 0x39, 0xe7, 0x00, 0x7e, 0x00, + 0xee, 0xf0, 0xe3, 0x0f, 0x3c, 0x00, 0xe7, 0xf8, 0xc1, 0x1f, 0x1c, 0x00, + 0xff, 0x9d, 0x03, 0x1c, 0x3e, 0x00, 0xff, 0x9d, 0x3b, 0x1c, 0x3f, 0x00, + 0x70, 0xfc, 0xfb, 0x9f, 0x73, 0x00, 0x70, 0xf8, 0xf1, 0xcf, 0x71, 0x00}; + diff --git a/src/bitmaps/integral.h b/src/bitmaps/integral.h new file mode 100644 index 0000000..bb82d19 --- /dev/null +++ b/src/bitmaps/integral.h @@ -0,0 +1,5 @@ +#define integral_width 5 +#define integral_height 8 +static unsigned char integral_bits[] = { + 0x0c, 0x12, 0x02, 0x04, 0x04, 0x08, 0x09, 0x06}; + diff --git a/src/bitmaps/inv.h b/src/bitmaps/inv.h new file mode 100644 index 0000000..40e49bc --- /dev/null +++ b/src/bitmaps/inv.h @@ -0,0 +1,8 @@ +#define inv_width 18 +#define inv_height 13 +static unsigned char inv_bits[] = { + 0x0c, 0x04, 0x00, 0x0f, 0x06, 0x00, 0x0c, 0x02, 0x00, 0x0c, 0x03, 0x00, + 0x0c, 0x01, 0x00, 0x8c, 0x19, 0x03, 0x8c, 0xb0, 0x02, 0xcc, 0x70, 0x00, + 0x40, 0x60, 0x00, 0x60, 0x60, 0x00, 0x20, 0xf0, 0x00, 0x30, 0xd4, 0x02, + 0x10, 0x8c, 0x01}; + diff --git a/src/bitmaps/last.h b/src/bitmaps/last.h new file mode 100644 index 0000000..a9e2050 --- /dev/null +++ b/src/bitmaps/last.h @@ -0,0 +1,12 @@ +#define last_width 120 +#define last_height 6 +static unsigned char last_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xc6, 0x1c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x29, 0x09, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x11, 0x49, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x8f, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x29, 0x09, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xc9, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}; + diff --git a/src/bitmaps/lbrace.h b/src/bitmaps/lbrace.h new file mode 100644 index 0000000..abc6290 --- /dev/null +++ b/src/bitmaps/lbrace.h @@ -0,0 +1,5 @@ +#define lbrace_width 3 +#define lbrace_height 7 +static unsigned char lbrace_bits[] = { + 0x04, 0x02, 0x01, 0x01, 0x01, 0x02, 0x04}; + diff --git a/src/bitmaps/lbracket.h b/src/bitmaps/lbracket.h new file mode 100644 index 0000000..c89473c --- /dev/null +++ b/src/bitmaps/lbracket.h @@ -0,0 +1,5 @@ +#define lbracket_width 3 +#define lbracket_height 7 +static unsigned char lbracket_bits[] = { + 0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07}; + diff --git a/src/bitmaps/lcurly.h b/src/bitmaps/lcurly.h new file mode 100644 index 0000000..17b19cf --- /dev/null +++ b/src/bitmaps/lcurly.h @@ -0,0 +1,5 @@ +#define lcurly_width 5 +#define lcurly_height 7 +static unsigned char lcurly_bits[] = { + 0x18, 0x04, 0x04, 0x02, 0x04, 0x04, 0x18}; + diff --git a/src/bitmaps/left.h b/src/bitmaps/left.h new file mode 100644 index 0000000..2d213ed --- /dev/null +++ b/src/bitmaps/left.h @@ -0,0 +1,6 @@ +#define left_width 11 +#define left_height 11 +static unsigned char left_bits[] = { + 0x00, 0x04, 0x00, 0x07, 0xc0, 0x07, 0xf0, 0x07, 0xfc, 0x07, 0xff, 0x07, + 0xfc, 0x07, 0xf0, 0x07, 0xc0, 0x07, 0x00, 0x07, 0x00, 0x04}; + diff --git a/src/bitmaps/menu_label.h b/src/bitmaps/menu_label.h new file mode 100644 index 0000000..27abbc9 --- /dev/null +++ b/src/bitmaps/menu_label.h @@ -0,0 +1,7 @@ +#define menu_label_width 24 +#define menu_label_height 11 +static unsigned char menu_label_bits[] = { + 0xfe, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0x7f}; + diff --git a/src/bitmaps/minus.h b/src/bitmaps/minus.h new file mode 100644 index 0000000..521f66d --- /dev/null +++ b/src/bitmaps/minus.h @@ -0,0 +1,6 @@ +#define minus_width 10 +#define minus_height 10 +static unsigned char minus_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xff, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + diff --git a/src/bitmaps/mul.h b/src/bitmaps/mul.h new file mode 100644 index 0000000..9f3542c --- /dev/null +++ b/src/bitmaps/mul.h @@ -0,0 +1,6 @@ +#define mul_width 10 +#define mul_height 10 +static unsigned char mul_bits[] = { + 0x03, 0x03, 0x87, 0x03, 0xce, 0x01, 0xfc, 0x00, 0x78, 0x00, 0x78, 0x00, + 0xfc, 0x00, 0xce, 0x01, 0x87, 0x03, 0x03, 0x03}; + diff --git a/src/bitmaps/neg.h b/src/bitmaps/neg.h new file mode 100644 index 0000000..6c49f9b --- /dev/null +++ b/src/bitmaps/neg.h @@ -0,0 +1,7 @@ +#define neg_width 21 +#define neg_height 11 +static unsigned char neg_bits[] = { + 0x18, 0x00, 0x00, 0x18, 0x30, 0x00, 0x18, 0x30, 0x00, 0xff, 0x18, 0x00, + 0xff, 0x18, 0x00, 0x18, 0x0c, 0x00, 0x18, 0x0c, 0x00, 0x18, 0xc6, 0x1f, + 0x00, 0xc6, 0x1f, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00}; + diff --git a/src/bitmaps/nl.h b/src/bitmaps/nl.h new file mode 100644 index 0000000..7b7e1e4 --- /dev/null +++ b/src/bitmaps/nl.h @@ -0,0 +1,5 @@ +#define nl_width 8 +#define nl_height 7 +static unsigned char nl_bits[] = { + 0x00, 0x84, 0x86, 0xff, 0x06, 0x04, 0x00}; + diff --git a/src/bitmaps/nl_gx.h b/src/bitmaps/nl_gx.h new file mode 100644 index 0000000..ced50dd --- /dev/null +++ b/src/bitmaps/nl_gx.h @@ -0,0 +1,7 @@ +#define nl_gx_width 18 +#define nl_gx_height 12 +static unsigned char nl_gx_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x03, 0xf0, 0x00, 0x03, + 0xfc, 0x00, 0x03, 0xff, 0xff, 0x03, 0xff, 0xff, 0x03, 0xfc, 0x00, 0x00, + 0xf0, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + diff --git a/src/bitmaps/parens_gx.h b/src/bitmaps/parens_gx.h new file mode 100644 index 0000000..f1661fa --- /dev/null +++ b/src/bitmaps/parens_gx.h @@ -0,0 +1,7 @@ +#define parens_gx_width 20 +#define parens_gx_height 12 +static unsigned char parens_gx_bits[] = { + 0x0c, 0x00, 0x03, 0x06, 0x00, 0x06, 0x06, 0x00, 0x06, 0x03, 0x00, 0x0c, + 0x03, 0x00, 0x0c, 0x03, 0x00, 0x0c, 0x03, 0x00, 0x0c, 0x03, 0x00, 0x0c, + 0x03, 0x00, 0x0c, 0x06, 0x00, 0x06, 0x06, 0x00, 0x06, 0x0c, 0x00, 0x03}; + diff --git a/src/bitmaps/pi.h b/src/bitmaps/pi.h new file mode 100644 index 0000000..9fcaa44 --- /dev/null +++ b/src/bitmaps/pi.h @@ -0,0 +1,5 @@ +#define pi_width 6 +#define pi_height 7 +static unsigned char pi_bits[] = { + 0x20, 0x1f, 0x12, 0x12, 0x12, 0x12, 0x12}; + diff --git a/src/bitmaps/pi_gx.h b/src/bitmaps/pi_gx.h new file mode 100644 index 0000000..144db5e --- /dev/null +++ b/src/bitmaps/pi_gx.h @@ -0,0 +1,6 @@ +#define pi_gx_width 10 +#define pi_gx_height 12 +static unsigned char pi_gx_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0x03, 0xff, 0x01, + 0xcc, 0x00, 0xcc, 0x00, 0xcc, 0x00, 0xcc, 0x00, 0xcc, 0x00, 0xcc, 0x00}; + diff --git a/src/bitmaps/plus.h b/src/bitmaps/plus.h new file mode 100644 index 0000000..4c3de62 --- /dev/null +++ b/src/bitmaps/plus.h @@ -0,0 +1,6 @@ +#define plus_width 10 +#define plus_height 10 +static unsigned char plus_bits[] = { + 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0xff, 0x03, 0xff, 0x03, + 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00}; + diff --git a/src/bitmaps/pow10.h b/src/bitmaps/pow10.h new file mode 100644 index 0000000..72b6f41 --- /dev/null +++ b/src/bitmaps/pow10.h @@ -0,0 +1,6 @@ +#define pow10_width 13 +#define pow10_height 9 +static unsigned char pow10_bits[] = { + 0x00, 0x12, 0x00, 0x0c, 0x32, 0x04, 0x4b, 0x0a, 0x4a, 0x09, 0x4a, 0x00, + 0x4a, 0x00, 0x4a, 0x00, 0x32, 0x00}; + diff --git a/src/bitmaps/pow10_gx.h b/src/bitmaps/pow10_gx.h new file mode 100644 index 0000000..76f20b1 --- /dev/null +++ b/src/bitmaps/pow10_gx.h @@ -0,0 +1,6 @@ +#define pow10_gx_width 13 +#define pow10_gx_height 12 +static unsigned char pow10_gx_bits[] = { + 0x00, 0x12, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x09, 0x32, 0x00, + 0x4b, 0x00, 0x4a, 0x00, 0x4a, 0x00, 0x4a, 0x00, 0x4a, 0x00, 0x32, 0x00}; + diff --git a/src/bitmaps/power.h b/src/bitmaps/power.h new file mode 100644 index 0000000..13f4365 --- /dev/null +++ b/src/bitmaps/power.h @@ -0,0 +1,8 @@ +#define power_width 17 +#define power_height 14 +static unsigned char power_bits[] = { + 0x00, 0x8c, 0x01, 0x00, 0x58, 0x01, 0x00, 0x38, 0x00, 0xc8, 0x30, 0x00, + 0x9c, 0x30, 0x00, 0x98, 0x78, 0x00, 0x58, 0x6a, 0x01, 0x58, 0xc6, 0x00, + 0x38, 0x00, 0x00, 0x30, 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x03, 0x00, 0x00}; + diff --git a/src/bitmaps/prog.h b/src/bitmaps/prog.h new file mode 100644 index 0000000..3c9d0ee --- /dev/null +++ b/src/bitmaps/prog.h @@ -0,0 +1,6 @@ +#define prog_width 16 +#define prog_height 7 +static unsigned char prog_bits[] = { + 0x48, 0x12, 0x24, 0x24, 0x12, 0x48, 0x09, 0x90, 0x12, 0x48, 0x24, 0x24, + 0x48, 0x12}; + diff --git a/src/bitmaps/prog_gx.h b/src/bitmaps/prog_gx.h new file mode 100644 index 0000000..9653654 --- /dev/null +++ b/src/bitmaps/prog_gx.h @@ -0,0 +1,7 @@ +#define prog_gx_width 24 +#define prog_gx_height 12 +static unsigned char prog_gx_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xc3, 0x18, + 0x8c, 0x81, 0x31, 0xc6, 0x00, 0x63, 0x63, 0x00, 0xc6, 0xc6, 0x00, 0x63, + 0x8c, 0x81, 0x31, 0x18, 0xc3, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + diff --git a/src/bitmaps/quote_gx.h b/src/bitmaps/quote_gx.h new file mode 100644 index 0000000..1f1888c --- /dev/null +++ b/src/bitmaps/quote_gx.h @@ -0,0 +1,6 @@ +#define quote_gx_width 12 +#define quote_gx_height 12 +static unsigned char quote_gx_bits[] = { + 0x05, 0x0a, 0x05, 0x0a, 0x05, 0x0a, 0x05, 0x0a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + diff --git a/src/bitmaps/rbrace.h b/src/bitmaps/rbrace.h new file mode 100644 index 0000000..6426067 --- /dev/null +++ b/src/bitmaps/rbrace.h @@ -0,0 +1,5 @@ +#define rbrace_width 3 +#define rbrace_height 7 +static unsigned char rbrace_bits[] = { + 0x01, 0x02, 0x04, 0x04, 0x04, 0x02, 0x01}; + diff --git a/src/bitmaps/rbracket.h b/src/bitmaps/rbracket.h new file mode 100644 index 0000000..fb8300e --- /dev/null +++ b/src/bitmaps/rbracket.h @@ -0,0 +1,5 @@ +#define rbracket_width 3 +#define rbracket_height 7 +static unsigned char rbracket_bits[] = { + 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07}; + diff --git a/src/bitmaps/rcurly.h b/src/bitmaps/rcurly.h new file mode 100644 index 0000000..ddfc65f --- /dev/null +++ b/src/bitmaps/rcurly.h @@ -0,0 +1,5 @@ +#define rcurly_width 5 +#define rcurly_height 7 +static unsigned char rcurly_bits[] = { + 0x03, 0x04, 0x04, 0x08, 0x04, 0x04, 0x03}; + diff --git a/src/bitmaps/right.h b/src/bitmaps/right.h new file mode 100644 index 0000000..e62057d --- /dev/null +++ b/src/bitmaps/right.h @@ -0,0 +1,6 @@ +#define right_width 11 +#define right_height 11 +static unsigned char right_bits[] = { + 0x01, 0x00, 0x07, 0x00, 0x1f, 0x00, 0x7f, 0x00, 0xff, 0x01, 0xff, 0x07, + 0xff, 0x01, 0x7f, 0x00, 0x1f, 0x00, 0x07, 0x00, 0x01, 0x00}; + diff --git a/src/bitmaps/root.h b/src/bitmaps/root.h new file mode 100644 index 0000000..fc334fd --- /dev/null +++ b/src/bitmaps/root.h @@ -0,0 +1,8 @@ +#define root_width 18 +#define root_height 13 +static unsigned char root_bits[] = { + 0x26, 0x00, 0x00, 0x14, 0x00, 0x00, 0x08, 0xfe, 0x03, 0x14, 0x02, 0x02, + 0x53, 0x02, 0x00, 0x21, 0x99, 0x00, 0x00, 0x91, 0x00, 0x10, 0x91, 0x00, + 0xa0, 0x50, 0x00, 0xc0, 0x60, 0x00, 0x80, 0x20, 0x00, 0x00, 0x14, 0x00, + 0x00, 0x0c, 0x00}; + diff --git a/src/bitmaps/root_gx.h b/src/bitmaps/root_gx.h new file mode 100644 index 0000000..e2deba7 --- /dev/null +++ b/src/bitmaps/root_gx.h @@ -0,0 +1,8 @@ +#define root_gx_width 18 +#define root_gx_height 15 +static unsigned char root_gx_bits[] = { + 0x66, 0x00, 0x00, 0x14, 0x00, 0x00, 0x08, 0x00, 0x00, 0x14, 0x00, 0x00, + 0x53, 0xfe, 0x03, 0x21, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x99, 0x00, + 0x00, 0x91, 0x00, 0x10, 0x91, 0x00, 0xa0, 0x50, 0x00, 0xc0, 0x60, 0x00, + 0x80, 0x20, 0x00, 0x00, 0x14, 0x00, 0x00, 0x0c, 0x00}; + diff --git a/src/bitmaps/science.h b/src/bitmaps/science.h new file mode 100644 index 0000000..20750c2 --- /dev/null +++ b/src/bitmaps/science.h @@ -0,0 +1,16 @@ +#define science_width 131 +#define science_height 8 +static unsigned char science_bits[] = { + 0x38, 0x1c, 0xf2, 0x09, 0x7d, 0x79, 0xe2, 0x80, 0x2f, 0xe4, 0x41, 0x08, + 0x79, 0x20, 0x3c, 0xc2, 0x07, 0x44, 0x22, 0x12, 0x08, 0x11, 0x09, 0x12, + 0x81, 0x20, 0x22, 0x62, 0x08, 0x89, 0x30, 0x44, 0x42, 0x00, 0x02, 0x01, + 0x09, 0x94, 0x88, 0x04, 0x09, 0x40, 0x40, 0x11, 0x52, 0x94, 0x88, 0x28, + 0x42, 0x21, 0x00, 0x1c, 0x01, 0xf9, 0x94, 0x88, 0x3c, 0x09, 0xc0, 0xc7, + 0xf0, 0x51, 0x94, 0x84, 0x28, 0x3e, 0xe1, 0x03, 0xa0, 0x00, 0x09, 0x94, + 0x88, 0x04, 0x05, 0x40, 0xc0, 0x10, 0x48, 0x94, 0x44, 0x24, 0x22, 0x21, + 0x00, 0xa1, 0xa0, 0x04, 0xa2, 0x44, 0x82, 0x04, 0x21, 0xa0, 0x08, 0xfc, + 0xa2, 0x42, 0x7e, 0xa1, 0x10, 0x00, 0x91, 0x90, 0x04, 0x42, 0x44, 0x82, + 0x84, 0x20, 0x10, 0x09, 0x84, 0x42, 0x22, 0x42, 0xb1, 0x10, 0x00, 0x0e, + 0x8f, 0x7c, 0x42, 0x44, 0x82, 0x78, 0xe0, 0x0b, 0x09, 0x82, 0x42, 0x1e, + 0x41, 0x9f, 0xf7, 0x01}; + diff --git a/src/bitmaps/shl.h b/src/bitmaps/shl.h new file mode 100644 index 0000000..7b08ee0 --- /dev/null +++ b/src/bitmaps/shl.h @@ -0,0 +1,8 @@ +#define shl_width 24 +#define shl_height 14 +static unsigned char shl_bits[] = { + 0xfe, 0xff, 0x7f, 0xff, 0xfc, 0xff, 0x7f, 0xfc, 0xff, 0x3f, 0xfe, 0xff, + 0x1f, 0xff, 0xff, 0x0f, 0x00, 0xfc, 0x07, 0x00, 0xf8, 0x0f, 0x00, 0xf0, + 0x1f, 0xff, 0xf1, 0x3f, 0xfe, 0xf1, 0x7f, 0xfc, 0xf1, 0xff, 0xfc, 0xf1, + 0xff, 0xff, 0xf1, 0xfe, 0xff, 0x71}; + diff --git a/src/bitmaps/shr.h b/src/bitmaps/shr.h new file mode 100644 index 0000000..e67e991 --- /dev/null +++ b/src/bitmaps/shr.h @@ -0,0 +1,8 @@ +#define shr_width 24 +#define shr_height 14 +static unsigned char shr_bits[] = { + 0xfe, 0xff, 0x7f, 0xff, 0x3f, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0x7f, 0xfc, + 0xff, 0xff, 0xf8, 0x3f, 0x00, 0xf0, 0x1f, 0x00, 0xe0, 0x0f, 0x00, 0xf0, + 0x8f, 0xff, 0xf8, 0x8f, 0x7f, 0xfc, 0x8f, 0x3f, 0xfe, 0x8f, 0x3f, 0xff, + 0x8f, 0xff, 0xff, 0x8e, 0xff, 0x7f}; + diff --git a/src/bitmaps/sigma.h b/src/bitmaps/sigma.h new file mode 100644 index 0000000..4cb47ee --- /dev/null +++ b/src/bitmaps/sigma.h @@ -0,0 +1,5 @@ +#define sigma_width 6 +#define sigma_height 9 +static unsigned char sigma_bits[] = { + 0x3f, 0x21, 0x02, 0x04, 0x08, 0x04, 0x02, 0x21, 0x3f}; + diff --git a/src/bitmaps/slash.h b/src/bitmaps/slash.h new file mode 100644 index 0000000..4c1e502 --- /dev/null +++ b/src/bitmaps/slash.h @@ -0,0 +1,5 @@ +#define slash_width 3 +#define slash_height 7 +static unsigned char slash_bits[] = { + 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01}; + diff --git a/src/bitmaps/small_colon.h b/src/bitmaps/small_colon.h new file mode 100644 index 0000000..12ee42e --- /dev/null +++ b/src/bitmaps/small_colon.h @@ -0,0 +1,5 @@ +#define small_colon_width 2 +#define small_colon_height 7 +static unsigned char small_colon_bits[] = { + 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x00}; + diff --git a/src/bitmaps/sqr.h b/src/bitmaps/sqr.h new file mode 100644 index 0000000..6c0045d --- /dev/null +++ b/src/bitmaps/sqr.h @@ -0,0 +1,6 @@ +#define sqr_width 11 +#define sqr_height 10 +static unsigned char sqr_bits[] = { + 0x00, 0x03, 0x80, 0x04, 0x00, 0x04, 0x00, 0x02, 0x26, 0x01, 0x94, 0x07, + 0x08, 0x00, 0x14, 0x00, 0x53, 0x00, 0x21, 0x00}; + diff --git a/src/bitmaps/sqr_gx.h b/src/bitmaps/sqr_gx.h new file mode 100644 index 0000000..02a652e --- /dev/null +++ b/src/bitmaps/sqr_gx.h @@ -0,0 +1,7 @@ +#define sqr_gx_width 11 +#define sqr_gx_height 13 +static unsigned char sqr_gx_bits[] = { + 0x00, 0x03, 0x80, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, 0x80, 0x07, + 0x00, 0x00, 0x66, 0x00, 0x14, 0x00, 0x08, 0x00, 0x14, 0x00, 0x53, 0x00, + 0x21, 0x00}; + diff --git a/src/bitmaps/sqrt.h b/src/bitmaps/sqrt.h new file mode 100644 index 0000000..80e213e --- /dev/null +++ b/src/bitmaps/sqrt.h @@ -0,0 +1,7 @@ +#define sqrt_width 20 +#define sqrt_height 11 +static unsigned char sqrt_bits[] = { + 0x00, 0xff, 0x0f, 0x00, 0x01, 0x08, 0x00, 0x01, 0x08, 0x80, 0x8c, 0x01, + 0x80, 0x58, 0x01, 0x80, 0x38, 0x00, 0x47, 0x30, 0x00, 0x4c, 0x30, 0x00, + 0x58, 0x78, 0x00, 0x30, 0x6a, 0x01, 0x20, 0xc6, 0x00}; + diff --git a/src/bitmaps/string.h b/src/bitmaps/string.h new file mode 100644 index 0000000..ff22901 --- /dev/null +++ b/src/bitmaps/string.h @@ -0,0 +1,6 @@ +#define string_width 10 +#define string_height 7 +static unsigned char string_bits[] = { + 0x85, 0x02, 0x85, 0x02, 0x85, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00}; + diff --git a/src/bitmaps/three.h b/src/bitmaps/three.h new file mode 100644 index 0000000..ca76550 --- /dev/null +++ b/src/bitmaps/three.h @@ -0,0 +1,5 @@ +#define three_width 5 +#define three_height 7 +static unsigned char three_bits[] = { + 0x0e, 0x11, 0x10, 0x0c, 0x10, 0x11, 0x0e}; + diff --git a/src/bitmaps/two.h b/src/bitmaps/two.h new file mode 100644 index 0000000..485e69f --- /dev/null +++ b/src/bitmaps/two.h @@ -0,0 +1,5 @@ +#define two_width 5 +#define two_height 7 +static unsigned char two_bits[] = { + 0x0e, 0x11, 0x10, 0x08, 0x04, 0x02, 0x1f}; + diff --git a/src/bitmaps/under.h b/src/bitmaps/under.h new file mode 100644 index 0000000..9319334 --- /dev/null +++ b/src/bitmaps/under.h @@ -0,0 +1,5 @@ +#define under_width 6 +#define under_height 7 +static unsigned char under_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f}; + diff --git a/src/bitmaps/under_gx.h b/src/bitmaps/under_gx.h new file mode 100644 index 0000000..0ba4753 --- /dev/null +++ b/src/bitmaps/under_gx.h @@ -0,0 +1,6 @@ +#define under_gx_width 10 +#define under_gx_height 12 +static unsigned char under_gx_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xff, 0x03}; + diff --git a/src/bitmaps/up.h b/src/bitmaps/up.h new file mode 100644 index 0000000..483cc74 --- /dev/null +++ b/src/bitmaps/up.h @@ -0,0 +1,6 @@ +#define up_width 11 +#define up_height 11 +static unsigned char up_bits[] = { + 0x20, 0x00, 0x20, 0x00, 0x70, 0x00, 0x70, 0x00, 0xf8, 0x00, 0xf8, 0x00, + 0xfc, 0x01, 0xfc, 0x01, 0xfe, 0x03, 0xfe, 0x03, 0xff, 0x07}; + diff --git a/src/buttons.h b/src/buttons.h new file mode 100644 index 0000000..7600870 --- /dev/null +++ b/src/buttons.h @@ -0,0 +1,84 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: buttons.h,v $ + * Revision 1.5 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.4 1994/12/07 20:16:41 ecd + * added some newlines + * + * Revision 1.4 1994/12/07 20:16:41 ecd + * added some newlines + * + * Revision 1.3 1994/11/02 14:51:27 ecd + * minor fix + * + * Revision 1.2 1994/10/06 16:28:03 ecd + * changed char to unsigned + * + * Revision 1.1 1994/09/13 15:05:11 ecd + * Initial revision + * + * + * $Id: buttons.h,v 1.5 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#ifndef _BUTTONS_H +#define _BUTTONS_H 1 + +#include "bitmaps/menu_label.h" + +#include "bitmaps/up.h" + +#include "bitmaps/down.h" + +#include "bitmaps/left.h" + +#include "bitmaps/right.h" + +#include "bitmaps/sqrt.h" + +#include "bitmaps/power.h" + +#include "bitmaps/inv.h" + +#include "bitmaps/neg.h" + +#include "bitmaps/bs.h" + +#include "bitmaps/alpha.h" + +#include "bitmaps/div.h" + +#include "bitmaps/shl.h" + +#include "bitmaps/mul.h" + +#include "bitmaps/shr.h" + +#include "bitmaps/minus.h" + +#include "bitmaps/plus.h" + +#include "bitmaps/last.h" + +#include "bitmaps/colon.h" + +#endif /* !_BUTTONS_H */ diff --git a/src/checkrom.c b/src/checkrom.c new file mode 100644 index 0000000..fc9ce11 --- /dev/null +++ b/src/checkrom.c @@ -0,0 +1,144 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: checkrom.c,v $ + * Revision 1.4 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.3 1994/11/02 14:40:38 ecd + * support for "compressed" rom files added + * + * Revision 1.3 1994/11/02 14:40:38 ecd + * support for "compressed" rom files added + * + * Revision 1.2 1994/10/06 16:30:05 ecd + * changed char to unsigned + * + * Revision 1.1 1994/10/01 10:12:53 ecd + * Initial revision + * + * + * $Id: checkrom.c,v 1.4 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#include +#include +#include +#include + +#include "global.h" +#include "romio.h" + +unsigned char *rom; +unsigned short rom_crc, crc; + +int verbose = 0; +char *progname; + +#define calc_crc(n) (crc = ((crc >> 4) ^ (((crc ^ n) & 0xf) * 0x1081))) + +int +#ifdef __FunctionProto__ +main(int argc, char **argv) +#else +main(argc, argv) +int argc; +char **argv; +#endif +{ + unsigned char version[7]; + long ver_addr; + int i, a, c, d, d0, d1, D0, D1; + int fail; + + if (argc < 2) { + fprintf(stderr, "usage: %s rom-file\n", argv[0]); + exit (1); + } + + if (!read_rom_file(argv[1], &rom, &rom_size)) + { + fprintf(stderr, "%s: can\'t read ROM from %s\n", argv[0], argv[1]); + exit (1); + } + + if (opt_gx != 0) + ver_addr = 0x7ffbf; + else + ver_addr = 0x7fff0; + + for (i = 0; i < 6; i++) { + version[i] = rom[ver_addr + 2 * i + 1] << 4; + version[i] |= rom[ver_addr + 2 * i]; + } + version[6] = '\0'; + printf("ROM Version is %s\n", version); + + + for (i = 0x100; i < 0x140; i++) { + rom[i] = 0x0; + } + + fail = a = 0; + D0 = 0x00000; + D1 = 0x40000; + for (d = 1; d <= rom_size / 0x80000; d++) { + + crc = 0x0000; + rom_crc = 0; + for (i = 0; i < 4; i++) { + rom_crc <<= 4; + rom_crc |= (rom[0x80000 * d - i - 1] & 0x0f); + } + + if (opt_gx) + printf("ROM CRC %d reads 0x%.4x\n", d, rom_crc); + else + printf("ROM CRC reads 0x%.4x\n", rom_crc); + + d0 = D0; + d1 = D1; + for (c = 0x3fff; c >= 0x0000; c--) { + for (i = 0; i < 16; i++) { + calc_crc(rom[d0 + i]); + } + d0 += 16; + for (i = 0; i < 16; i++) { + calc_crc(rom[d1 + i]); + } + d1 += 16; + } + D0 += 0x80000; + D1 += 0x80000; + a = crc; + a = ((a | 0xf0000) + 1) & 0xfffff; + + if (a != 0x00000) { + fail++; + } + } + + if (fail != 0) + printf("IROM %.4x: ROM CRC test FAILED !!!\n", a & 0xffff); + else + printf("IROM OK: ROM CRC test passed.\n"); + + return 0; +} + diff --git a/src/constants.h b/src/constants.h new file mode 100644 index 0000000..bc84b07 --- /dev/null +++ b/src/constants.h @@ -0,0 +1,48 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: constants.h,v $ + * Revision 1.3 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.2 1994/11/28 02:19:22 ecd + * simplified: no more GRAY_16, GRAY_256, etc. + * + * Revision 1.2 1994/11/28 02:19:22 ecd + * simplified: no more GRAY_16, GRAY_256, etc. + * + * Revision 1.1 1994/11/04 03:44:47 ecd + * Initial revision + * + * + * $Id: constants.h,v 1.3 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#ifndef _CONSTANTS_H +#define _CONSTANTS_H 1 + +/* + * Color modes this program can cope with + */ +#define COLOR_MODE_MONO 1 +#define COLOR_MODE_GRAY 2 +#define COLOR_MODE_COLOR 3 + +#endif /* !_CONSTANTS_H */ + diff --git a/src/debugger.c b/src/debugger.c new file mode 100644 index 0000000..b87ba43 --- /dev/null +++ b/src/debugger.c @@ -0,0 +1,2060 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: debugger.c,v $ + * Revision 1.8 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.7 1994/12/07 20:20:50 ecd + * more functions + * + * Revision 1.7 1994/12/07 20:20:50 ecd + * more functions + * + * Revision 1.6 1994/11/28 02:00:51 ecd + * new functions: do_ram, do_stack + * + * Revision 1.5 1994/11/02 14:40:38 ecd + * more functions + * + * Revision 1.4 1994/10/09 20:29:47 ecd + * start of disassembler implementation. + * + * Revision 1.3 1994/10/06 16:30:05 ecd + * added refresh_display() + * + * Revision 1.2 1994/10/05 08:36:44 ecd + * more functions + * + * Revision 1.1 1994/10/04 15:12:21 ecd + * Initial revision + * + * + * $Id: debugger.c,v 1.8 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#include "global.h" + +#include +#ifdef HAVE_READLINE +# include +# include +#endif +#include +#include +#include +#include +#include +#ifdef SUNOS +#include +#endif +#include + +#include "hp48.h" +#include "device.h" +#include "timer.h" +#include "x48_x11.h" +#include "debugger.h" +#include "disasm.h" +#include "rpl.h" +#include "romio.h" +#include "resources.h" + +#define MAX_ARGS 16 + +int enter_debugger = 0; +int in_debugger = 0; +int exec_flags = 0; + +static int continue_flag; +static char instr[100]; + +/* + * Pointers in the HP48sx ROM + */ +#define DSKTOP_SX 0x70579 +#define DSKBOT_SX 0x7057e +/* + * Pointers in the HP48gx ROM + */ +#define DSKTOP_GX 0x806f8 +#define DSKBOT_GX 0x806fd + +/* + * Breakpoint related stuff + */ +#define BP_EXEC 1 +#define BP_READ 2 +#define BP_WRITE 4 +#define BP_RANGE 8 + +#define MAX_BREAKPOINTS 32 +int num_bkpts; + +struct breakpoint + { + word_20 addr; + word_20 end_addr; + int flags; + } + +bkpt_tbl[MAX_BREAKPOINTS + 1]; + +/* + * command functions + */ +static void do_break __ProtoType__ ((int, char **)); +static void do_continue __ProtoType__ ((int, char **)); +static void do_delete __ProtoType__ ((int, char **)); +static void do_exit __ProtoType__ ((int, char **)); +static void do_go __ProtoType__ ((int, char **)); +static void do_help __ProtoType__ ((int, char **)); +static void do_load __ProtoType__ ((int, char **)); +static void do_mode __ProtoType__ ((int, char **)); +static void do_quit __ProtoType__ ((int, char **)); +static void do_regs __ProtoType__ ((int, char **)); +static void do_save __ProtoType__ ((int, char **)); +static void do_stack __ProtoType__ ((int, char **)); +static void do_stat __ProtoType__ ((int, char **)); +static void do_step __ProtoType__ ((int, char **)); +static void do_ram __ProtoType__ ((int, char **)); +static void do_reset __ProtoType__ ((int, char **)); +static void do_rstk __ProtoType__ ((int, char **)); + +struct cmd + { + char *name; + void (*func) __ProtoType__ ((int, char **)); + char *help; + } + +cmd_tbl[] = +{ + { + "break", do_break, + "break [address] Set breakpoint at `address\' or show breakpoints" + } + , + { + "b", do_break, 0 + } + , + + { + "cont", do_continue, + "cont Continue execution" + } + , + { + "c", do_continue, 0 + } + , + + { + "delete", do_delete, + "delete [all | n] Delete breakpoint or watchpoint number `n\',\n all breakpoints, or current breakpoint" + } + , + { + "d", do_delete, 0 + } + , + + { + "exit", do_exit, + "exit Exit the emulator without saving" + } + , + + { + "go", do_go, + "go address Set PC to `address\'" + } + , + + { + "help", do_help, + "help Display this information" + } + , + { + "h", do_help, 0 + } + , + { + "?", do_help, 0 + } + , + + { + "load", do_load, + "load Load emulator-state from files" + } + , + + { + "mode", do_mode, + "mode [hp | class] Show or set disassembler mode" + } + , + + { + "quit", do_quit, + "quit Exit the emulator after saving its state" + } + , + { + "q", do_quit, 0 + } + , + + { + "ram", do_ram, + "ram Show RAM layout" + } + , + + { + "reg", do_regs, + "reg [register [hexvalue]] Display or set register value" + } + , + { + "r", do_regs, 0 + } + , + + { + "reset", do_reset, + "reset Set the HP48\'s PC to ZERO" + } + , + + { + "save", do_save, + "save Save emulator-state to files" + } + , + + { + "stack", do_stack, + "stack Display RPL stack" + } + , + + { + "stat", do_stat, + "stat Display statistics for the emulator" + } + , + + { + "step", do_step, + "step [n] Step one or n Instruction(s)" + } + , + { + "s", do_step, 0 + } + , + + { + "where", do_rstk, + "where Show ML return stack" + } + , + + { + 0, 0, 0 + } +}; + +void +#ifdef __FunctionProto__ +init_debugger (void) +#else +init_debugger () +#endif +{ + int i; + + num_bkpts = 0; + for (i = 0; i < MAX_BREAKPOINTS; i++) + bkpt_tbl[i].flags = 0; + exec_flags = 0; +} + +int +#ifdef __FunctionProto__ +check_breakpoint (int type, word_20 addr) +#else +check_breakpoint (type, addr) + int type; + word_20 addr; +#endif +{ + struct breakpoint *bp; + int i, n; + + bp = bkpt_tbl; + n = num_bkpts; + i = 0; + for (; n > 0; bp++) + { + i++; + if (bp->flags == 0) + continue; + n--; + if (bp->flags & BP_RANGE && addr >= bp->addr && addr <= bp->end_addr) + { + goto hit_it; + } + if (bp->flags & type && addr == bp->addr) + { + hit_it: + if (type == BP_READ) + { + printf ("%.5lX: Read watchpoint %d hit at %.5lX\n", saturn.PC, + i, addr); + } + else if (type == BP_WRITE) + { + printf ("%.5lX: Write watchpoint %d hit at %.5lX\n", saturn.PC, + i, addr); + } + else + { + printf ("Breakpoint %d hit at %.5lX\n", i, addr); + } + return 1; + } + } + return 0; +} + +char * +#ifdef __FunctionProto__ +read_str(char *str, int n, int fp) +#else +read_str(str, n, fp) + char *str; + int n; + int fp; +#endif +{ + int cc; + int flags; + + while (1) + { + cc = read(fp, str, n); + if (cc > 0) + { + str[cc] = '\0'; + return str; + } + if (cc == 0) + return NULL; + + if (errno == EINTR) + continue; + + if (errno == EAGAIN) + { + flags = fcntl(fp, F_GETFL, 0); + flags &= ~ O_NONBLOCK; + fcntl(fp, F_SETFL, flags); + continue; + } + return NULL; + } + /* not reached */ +} + +#ifndef HAVE_READLINE +char * +#ifdef __FunctionProto__ +readline(char *prompt) +#else +readline(prompt) + char *prompt; +#endif +{ + char rl[81]; + char *nrl; + if (prompt) + { + printf("%s", prompt); + fflush(stdout); + } + nrl = read_str(rl, 80, 0); + if (nrl) + { + int len; + char *str; + + len = strlen(nrl); + str = malloc(len + 1); + + if (nrl[len-1] == '\n') + { + nrl[len-1] = '\0'; + } + if (NULL == str) + { + fprintf(stderr, "Out of memory\n"); + exit(-1); + } + + strcpy(str, nrl); + nrl = str; + } + return nrl; +} +#endif + +static inline void +#ifdef __FunctionProto__ +str_to_upper (char *arg) +#else +str_to_upper (arg) + char *arg; +#endif +{ + int i; + + for (i = 0; i < strlen (arg); i++) + { + if ('a' <= arg[i] && arg[i] <= 'z') + { + arg[i] = (char) ((int) arg[i] - (int) 'a' + (int) 'A'); + } + } +} + +static int +#ifdef __FunctionProto__ +decode_dec (int *num, char *arg) +#else +decode_dec (num, arg) + int *num; + char *arg; +#endif +{ + int i; + + if (arg == (char *) 0) + { + printf ("Command requires an argument.\n"); + return 0; + } + + *num = 0; + for (i = 0; i < strlen (arg); i++) + { + *num *= 10; + if ('0' <= arg[i] && arg[i] <= '9') + { + *num += ((int) arg[i] - (int) '0'); + } + else + { + *num = 0; + printf ("Not a number: %s.\n", arg); + return 0; + } + } + return 1; +} + +static int +#ifdef __FunctionProto__ +decode_20 (word_20 * addr, char *arg) +#else +decode_20 (addr, arg) + word_20 *addr; + char *arg; +#endif +{ + int i; + + if (arg == (char *) 0) + { + printf ("Command requires an argument.\n"); + return 0; + } + + *addr = 0; + for (i = 0; i < strlen (arg); i++) + { + *addr <<= 4; + if ('0' <= arg[i] && arg[i] <= '9') + { + *addr |= ((int) arg[i] - (int) '0'); + } + else if ('A' <= arg[i] && arg[i] <= 'F') + { + *addr |= ((int) arg[i] - (int) 'A' + 10); + } + else + { + *addr = 0; + printf ("Not a number: %s.\n", arg); + return 0; + } + *addr &= 0xfffff; + } + return 1; +} + +static int +#ifdef __FunctionProto__ +decode_32 (word_32 * addr, char *arg) +#else +decode_32 (addr, arg) + word_32 *addr; + char *arg; +#endif +{ + int i; + + if (arg == (char *) 0) + { + printf ("Command requires an argument.\n"); + return 0; + } + + *addr = 0; + for (i = 0; i < strlen (arg); i++) + { + *addr <<= 4; + if ('0' <= arg[i] && arg[i] <= '9') + { + *addr |= ((int) arg[i] - (int) '0'); + } + else if ('A' <= arg[i] && arg[i] <= 'F') + { + *addr |= ((int) arg[i] - (int) 'A' + 10); + } + else + { + *addr = 0; + printf ("Not a number: %s.\n", arg); + return 0; + } + } + return 1; +} + +static int +#ifdef __FunctionProto__ +decode_64 (word_64 * addr, char *arg) +#else +decode_64 (addr, arg) + word_64 *addr; + char *arg; +#endif +{ + int i; + + if (arg == (char *) 0) + { + printf ("Command requires an argument.\n"); + return 0; + } +#ifdef SIMPLE_64 + *addr = 0; + for (i = 0; i < strlen (arg); i++) + { + *addr <<= 4; + if ('0' <= arg[i] && arg[i] <= '9') + { + *addr |= ((int) arg[i] - (int) '0'); + } + else if ('A' <= arg[i] && arg[i] <= 'F') + { + *addr |= ((int) arg[i] - (int) 'A' + 10); + } + else + { + *addr = 0; + printf ("Not a number: %s.\n", arg); + return 0; + } + } +#else + addr->lo = addr->hi = 0; + for (i = 0; i < strlen (arg); i++) + { + addr->hi <<= 4; + addr->hi |= ((addr->lo >> 28) & 0x0f); + addr->lo <<= 4; + if ('0' <= arg[i] && arg[i] <= '9') + { + addr->lo |= ((int) arg[i] - (int) '0'); + } + else if ('A' <= arg[i] && arg[i] <= 'F') + { + addr->lo |= ((int) arg[i] - (int) 'A' + 10); + } + else + { + addr->hi = addr->lo = 0; + printf ("Not a number: %s.\n", arg); + return 0; + } + } +#endif + return 1; +} + +char * +#ifdef __FunctionProto__ +str_nibbles (word_20 addr, int n) +#else +str_nibbles (addr, n) + word_20 addr; + int n; +#endif +{ + static char str[1025]; + char *cp; + int i; + + if (n > 1024) + { + str[0] = '\0'; + return str; + } + + for (cp = str, i = 0; i < n; i++) + { + sprintf (cp, "%.1X", read_nibble (addr + i)); + cp++; + } + *cp = '\0'; + + return str; +} + +static int +#ifdef __FunctionProto__ +confirm (const char *prompt) +#else +confirm (prompt) + const char *prompt; +#endif +{ + char ans[80]; + + printf ("%s (y or n) ", prompt); + fflush (stdout); + read_str (ans, sizeof (ans), 0); + while (ans[0] != 'y' && ans[0] != 'Y' && ans[0] != 'n' && ans[0] != 'N') + { + printf ("Please answer y or n.\n"); + printf ("%s (y or n) ", prompt); + fflush (stdout); + read_str (ans, sizeof (ans), 0); + } + if (ans[0] == 'y' || ans[0] == 'Y') + { + return 1; + } + else + { + printf ("Not confirmed.\n"); + return 0; + } +} + +static void +#ifdef __FunctionProto__ +do_break (int argc, char **argv) +#else +do_break (argc, argv) + int argc; + char *argv; +#endif +{ + int i; + word_20 addr; + + if (argc == 1) + { + for (i = 0; i < MAX_BREAKPOINTS; i++) + { + if (bkpt_tbl[i].flags == 0) + continue; + if (bkpt_tbl[i].flags == BP_EXEC) + { + printf ("Breakpoint %d at 0x%.5lX\n", i + 1, bkpt_tbl[i].addr); + } + else if (bkpt_tbl[i].flags == BP_RANGE) + { + printf ("Range watchpoint %d at 0x%.5lX - 0x%.5lX\n", i + 1, + bkpt_tbl[i].addr, bkpt_tbl[i].end_addr); + } + else + { + printf ("Watchpoint %d at 0x%.5lX\n", i + 1, bkpt_tbl[i].addr); + } + } + } + else + { + str_to_upper (argv[1]); + if (!decode_20 (&addr, argv[1])) + { + return; + } + for (i = 0; i < MAX_BREAKPOINTS; i++) + { + if (bkpt_tbl[i].flags == 0) + { + bkpt_tbl[i].flags = BP_EXEC; + bkpt_tbl[i].addr = addr; + printf ("Breakpoint %d at 0x%.5lX\n", i + 1, bkpt_tbl[i].addr); + num_bkpts++; + return; + } + } + printf ("Breakpoint table full\n"); + } +} + +static void +#ifdef __FunctionProto__ +do_continue (int argc, char **argv) +#else +do_continue (argc, argv) + int argc; + char *argv; +#endif +{ + continue_flag = 1; +} + +static void +#ifdef __FunctionProto__ +do_delete (int argc, char **argv) +#else +do_delete (argc, argv) + int argc; + char *argv; +#endif +{ + int num; + + if (argc == 1) + { + for (num = 0; num < MAX_BREAKPOINTS; num++) + { + if (bkpt_tbl[num].addr == saturn.PC) + { + if (bkpt_tbl[num].flags == BP_EXEC) + { + printf ("Breakpoint %d at 0x%.5lX deleted.\n", + num + 1, bkpt_tbl[num].addr); + } + else if (bkpt_tbl[num].flags == BP_RANGE) + { + printf ("Range watchpoint %d at 0x%.5lX - 0x%.5lX deleted.\n", + num + 1, bkpt_tbl[num].addr, bkpt_tbl[num].end_addr); + } + else if (bkpt_tbl[num].flags) + { + printf ("Watchpoint %d at 0x%.5lX deleted.\n", + num + 1, bkpt_tbl[num].addr); + } + num_bkpts--; + bkpt_tbl[num].addr = 0; + bkpt_tbl[num].flags = 0; + } + } + } + else + { + str_to_upper (argv[1]); + if (!strcmp ("ALL", argv[1])) + { + for (num = 0; num < MAX_BREAKPOINTS; num++) + { + bkpt_tbl[num].addr = 0; + bkpt_tbl[num].flags = 0; + } + num_bkpts = 0; + printf ("All breakpoints deleted.\n"); + } + else + { + if (decode_dec (&num, argv[1])) + { + if (num < 1 || num > MAX_BREAKPOINTS) + { + printf ("Breakpoint %d out of range.\n", num); + return; + } + num -= 1; + if (bkpt_tbl[num].flags == BP_EXEC) + { + printf ("Breakpoint %d at 0x%.5lX deleted.\n", + num + 1, bkpt_tbl[num].addr); + } + else if (bkpt_tbl[num].flags == BP_RANGE) + { + printf ("Range watchpoint %d at 0x%.5lX - 0x%.5lX deleted.\n", + num + 1, bkpt_tbl[num].addr, bkpt_tbl[num].end_addr); + } + else if (bkpt_tbl[num].flags) + { + printf ("Watchpoint %d at 0x%.5lX deleted.\n", + num + 1, bkpt_tbl[num].addr); + } + num_bkpts--; + bkpt_tbl[num].addr = 0; + bkpt_tbl[num].flags = 0; + } + } + } +} + +static void +#ifdef __FunctionProto__ +do_exit (int argc, char **argv) +#else +do_exit (argc, argv) + int argc; + char *argv; +#endif +{ + if (confirm ("Exit the emulator WITHOUT saving its state?")) + { + printf ("Exit.\n"); + XCloseDisplay(dpy); + exit (0); + } +} + +static void +#ifdef __FunctionProto__ +do_go (int argc, char **argv) +#else +do_go (argc, argv) + int argc; + char *argv; +#endif +{ + word_20 addr; + + str_to_upper (argv[1]); + if (decode_20 (&addr, argv[1])) + { + saturn.PC = addr; + enter_debugger &= ~ILLEGAL_INSTRUCTION; + } +} + +static void +#ifdef __FunctionProto__ +do_help (int argc, char **argv) +#else +do_help (argc, argv) + int argc; + char *argv; +#endif +{ + int i; + + for (i = 0; cmd_tbl[i].name; i++) + { + if (cmd_tbl[i].help) + { + printf ("%s.\n", cmd_tbl[i].help); + } + } +} + +static void +#ifdef __FunctionProto__ +do_load (int argc, char **argv) +#else +do_load (argc, argv) + int argc; + char *argv; +#endif +{ + saturn_t tmp_saturn; + device_t tmp_device; + + if (confirm ("Load emulator-state from files?")) + { + memcpy (&tmp_saturn, &saturn, sizeof (saturn)); + memcpy (&tmp_device, &device, sizeof (device)); + memset (&saturn, 0, sizeof (saturn)); + if (read_files ()) + { + printf ("Loading done.\n"); + enter_debugger &= ~ILLEGAL_INSTRUCTION; + if (tmp_saturn.rom) + { + free (tmp_saturn.rom); + } + if (tmp_saturn.ram) + { + free (tmp_saturn.ram); + } + if (tmp_saturn.port1) + { + free (tmp_saturn.port1); + } + if (tmp_saturn.port2) + { + free (tmp_saturn.port2); + } + init_display (); + update_display (); +#ifdef HAVE_XSHM + if (disp.display_update) + refresh_display (); +#endif + } + else + { + printf ("Loading emulator-state from files failed.\n"); + if (saturn.rom) + { + free (saturn.rom); + } + if (saturn.ram) + { + free (saturn.ram); + } + if (saturn.port1) + { + free (saturn.port1); + } + if (saturn.port2) + { + free (saturn.port2); + } + memcpy (&saturn, &tmp_saturn, sizeof (saturn)); + memcpy (&device, &tmp_device, sizeof (device)); + } + } +} + +static void +#ifdef __FunctionProto__ +do_mode (int argc, char **argv) +#else +do_mode (argc, argv) + int argc; + char *argv; +#endif +{ + if (argc < 2) + { + printf ("Disassembler uses %s mnemonics.\n", mode_name[disassembler_mode]); + } + else + { + str_to_upper (argv[1]); + if (!strcmp ("HP", argv[1])) + { + disassembler_mode = HP_MNEMONICS; + } + else if (!strcmp ("CLASS", argv[1])) + { + disassembler_mode = CLASS_MNEMONICS; + } + else + { + printf ("Unknown disassembler mode %s. Try \"help\".\n", argv[1]); + } + } +} + +static void +#ifdef __FunctionProto__ +do_quit (int argc, char **argv) +#else +do_quit (argc, argv) + int argc; + char *argv; +#endif +{ + if (confirm ("Quit the emulator and save its state?")) + { + printf ("Exit.\n"); + exit_emulator (); + XCloseDisplay(dpy); + exit (0); + } +} + +static void +#ifdef __FunctionProto__ +set_reg (word_64 val, int n, unsigned char *r) +#else +set_reg (val, n, r) + word_64 val; + int n; + unsigned char *r; +#endif +{ + int i; + + for (i = 0; i < n; i++) + { +#ifdef SIMPLE_64 + r[i] = (unsigned char) ((val & (0xf << (4 * i))) >> (4 * i)); +#else + r[i] = (unsigned char) (((i < 8?val.lo:val.hi) & (0xf << (4 * i))) >> (4 * i)); +#endif + } +} + +static void +#ifdef __FunctionProto__ +dump_reg (const char *reg, int n, unsigned char *r) +#else +dump_reg (reg, n, r) + const char *reg; + int n; + unsigned char *r; +#endif +{ + int i; + + printf ("%s:\t", reg); + for (i = n - 1; i >= 0; i--) + { + printf ("%.1X", r[i] & 0xf); + } + printf ("\n"); +} + + +static void +#ifdef __FunctionProto__ +set_st (word_64 val) +#else +set_st (val) + word_64 val; +#endif +{ + int i; + + for (i = 0; i < 16; i++) +#ifdef SIMPLE_64 + saturn.PSTAT[i] = (val & (1 << i)) ? 1 : 0; +#else + saturn.PSTAT[i] = (val.lo & (1 << i)) ? 1 : 0; +#endif +} + +static void +#ifdef __FunctionProto__ +dump_st (void) +#else +dump_st () +#endif +{ + int i; + int val; + + val = 0; + for (i = NR_PSTAT - 1; i >= 0; i--) + { + val <<= 1; + val |= saturn.PSTAT[i] ? 1 : 0; + } + printf (" ST:\t%.4X (", val); + for (i = NR_PSTAT - 1; i > 0; i--) + { + if (saturn.PSTAT[i]) + { + printf ("%.1X ", i); + } + else + { + printf ("- "); + } + } + if (saturn.PSTAT[0]) + { + printf ("%.1X)\n", 0); + } + else + { + printf ("-)\n"); + } +} + +static void +#ifdef __FunctionProto__ +set_hst (word_64 val) +#else +set_hst (val) + word_64 val; +#endif +{ + saturn.XM = 0; + saturn.SB = 0; + saturn.SR = 0; + saturn.MP = 0; +#ifdef SIMPLE_64 + if (val & 1) + saturn.XM = 1; + if (val & 2) + saturn.SB = 1; + if (val & 4) + saturn.SR = 1; + if (val & 8) + saturn.MP = 1; +#else + if (val.lo & 1) + saturn.XM = 1; + if (val.lo & 2) + saturn.SB = 1; + if (val.lo & 4) + saturn.SR = 1; + if (val.lo & 8) + saturn.MP = 1; +#endif +} + +static void +#ifdef __FunctionProto__ +dump_hst (void) +#else +dump_hst () +#endif +{ + short hst = 0; + if (saturn.XM != 0) + hst |= 1; + if (saturn.SB != 0) + hst |= 2; + if (saturn.SR != 0) + hst |= 3; + if (saturn.MP != 0) + hst |= 4; + printf (" HST:\t%.1X (%s%s%s%s)\n", hst, + saturn.MP ? "MP " : "-- ", saturn.SR ? "SR " : "-- ", + saturn.SB ? "SB " : "-- ", saturn.XM ? "XM" : "--"); +} + +static char *mctl_str_gx[] = { + "MMIO ", + "SysRAM ", + "Bank Switch", + "Port 1 ", + "Port 2 ", + "SysROM " +}; + +static char *mctl_str_sx[] = { + "MMIO ", + "SysRAM", + "Port 1", + "Port 2", + "Extra ", + "SysROM" +}; + +static void +#ifdef __FunctionProto__ +do_ram (int argc, char **argv) +#else +do_ram (argc, argv) + int argc; + char *argv; +#endif +{ + int i; + + for (i = 0; i < 5; i++) + { + printf("%s ", opt_gx ? mctl_str_gx[i] : mctl_str_sx[i]); + if (saturn.mem_cntl[i].unconfigured) + printf("unconfigured\n"); + else + if (i == 0) + printf("configured to 0x%.5lx\n", saturn.mem_cntl[i].config[0]); + else + printf("configured to 0x%.5lX - 0x%.5lX\n", + saturn.mem_cntl[i].config[0], + (saturn.mem_cntl[i].config[0] | ~saturn.mem_cntl[i].config[1]) + & 0xfffff); + } + if (opt_gx) + printf("Port 2 switched to bank %d\n", saturn.bank_switch); +} + +static void +#ifdef __FunctionProto__ +do_regs (int argc, char **argv) +#else +do_regs (argc, argv) + int argc; + char *argv; +#endif +{ + int i; + word_64 val; + + if (argc < 2) + { + /* + * dump all registers + */ + printf ("CPU is in %s mode. Registers:\n", + saturn.hexmode == HEX ? "HEX" : "DEC"); + dump_reg (" A", 16, saturn.A); + dump_reg (" B", 16, saturn.B); + dump_reg (" C", 16, saturn.C); + dump_reg (" D", 16, saturn.D); + printf (" D0:\t%.5lX ->", saturn.D0); + for (i = 0; i < 20; i += 5) + { + printf (" %s", str_nibbles (saturn.D0 + i, 5)); + } + printf ("\n"); + printf (" D1:\t%.5lX ->", saturn.D1); + for (i = 0; i < 20; i += 5) + { + printf (" %s", str_nibbles (saturn.D1 + i, 5)); + } + printf ("\n"); + printf (" P:\t%.1X\n", saturn.P); + disassemble (saturn.PC, instr); + printf (" PC:\t%.5lX -> %s\n", saturn.PC, instr); + dump_reg (" R0", 16, saturn.R0); + dump_reg (" R1", 16, saturn.R1); + dump_reg (" R2", 16, saturn.R2); + dump_reg (" R3", 16, saturn.R3); + dump_reg (" R4", 16, saturn.R4); + dump_reg (" IN", 4, saturn.IN); + dump_reg (" OUT", 3, saturn.OUT); + printf (" CARRY:\t%.1d\n", saturn.CARRY); + dump_st (); + dump_hst (); + } + else if (argc == 2) + { + /* + * dump specified register + */ + str_to_upper (argv[1]); + if (!strcmp ("A", argv[1])) + { + dump_reg (" A", 16, saturn.A); + } + else if (!strcmp ("B", argv[1])) + { + dump_reg (" B", 16, saturn.B); + } + else if (!strcmp ("C", argv[1])) + { + dump_reg (" C", 16, saturn.C); + } + else if (!strcmp ("D", argv[1])) + { + dump_reg (" D", 16, saturn.D); + } + else if (!strcmp ("D0", argv[1])) + { + printf (" D0:\t%.5lX ->", saturn.D0); + for (i = 0; i < 20; i += 5) + { + printf (" %s", str_nibbles (saturn.D0 + i, 5)); + } + printf ("\n"); + } + else if (!strcmp ("D1", argv[1])) + { + printf (" D1:\t%.5lX ->", saturn.D1); + for (i = 0; i < 20; i += 5) + { + printf (" %s", str_nibbles (saturn.D1 + i, 5)); + } + printf ("\n"); + } + else if (!strcmp ("P", argv[1])) + { + printf (" P:\t%.1X\n", saturn.P); + } + else if (!strcmp ("PC", argv[1])) + { + disassemble (saturn.PC, instr); + printf (" PC:\t%.5lX -> %s\n", saturn.PC, instr); + } + else if (!strcmp ("R0", argv[1])) + { + dump_reg (" R0", 16, saturn.R0); + } + else if (!strcmp ("R1", argv[1])) + { + dump_reg (" R1", 16, saturn.R1); + } + else if (!strcmp ("R2", argv[1])) + { + dump_reg (" R2", 16, saturn.R2); + } + else if (!strcmp ("R3", argv[1])) + { + dump_reg (" R3", 16, saturn.R3); + } + else if (!strcmp ("R4", argv[1])) + { + dump_reg (" R4", 16, saturn.R4); + } + else if (!strcmp ("IN", argv[1])) + { + dump_reg (" IN", 4, saturn.IN); + } + else if (!strcmp ("OUT", argv[1])) + { + dump_reg (" OUT", 3, saturn.OUT); + } + else if (!strcmp ("CARRY", argv[1])) + { + printf (" CARRY:\t%.1d\n", saturn.CARRY); + } + else if (!strcmp ("CY", argv[1])) + { + printf (" CARRY:\t%.1d\n", saturn.CARRY); + } + else if (!strcmp ("ST", argv[1])) + { + dump_st (); + } + else if (!strcmp ("HST", argv[1])) + { + dump_hst (); + } + else + { + printf ("No Register %s in CPU.\n", argv[1]); + } + } + else + { + /* + * set specified register + */ + str_to_upper (argv[1]); + str_to_upper (argv[2]); + if (decode_64 (&val, argv[2])) + { + if (!strcmp ("A", argv[1])) + { + set_reg (val, 16, saturn.A); + dump_reg (" A", 16, saturn.A); + } + else if (!strcmp ("B", argv[1])) + { + set_reg (val, 16, saturn.B); + dump_reg (" B", 16, saturn.B); + } + else if (!strcmp ("C", argv[1])) + { + set_reg (val, 16, saturn.C); + dump_reg (" C", 16, saturn.C); + } + else if (!strcmp ("D", argv[1])) + { + set_reg (val, 16, saturn.D); + dump_reg (" D", 16, saturn.D); + } + else if (!strcmp ("D0", argv[1])) + { +#ifdef SIMPLE_64 + saturn.D0 = (word_20)(val & 0xfffff); +#else + saturn.D0 = (word_20)(val.lo & 0xfffff); +#endif + printf (" D0:\t%.5lX ->", saturn.D0); + for (i = 0; i < 20; i += 5) + { + printf (" %s", str_nibbles (saturn.D0 + i, 5)); + } + printf ("\n"); + } + else if (!strcmp ("D1", argv[1])) + { +#ifdef SIMPLE_64 + saturn.D1 = (word_20)(val & 0xfffff); +#else + saturn.D1 = (word_20)(val.lo & 0xfffff); +#endif + printf (" D1:\t%.5lX ->", saturn.D1); + for (i = 0; i < 20; i += 5) + { + printf (" %s", str_nibbles (saturn.D1 + i, 5)); + } + printf ("\n"); + } + else if (!strcmp ("P", argv[1])) + { +#ifdef SIMPLE_64 + saturn.P = (word_4)(val & 0xf); +#else + saturn.P = (word_4)(val.lo & 0xf); +#endif + printf (" P:\t%.1X\n", saturn.P); + } + else if (!strcmp ("PC", argv[1])) + { +#ifdef SIMPLE_64 + saturn.PC = (word_20)(val & 0xfffff); +#else + saturn.PC = (word_20)(val.lo & 0xfffff); +#endif + disassemble (saturn.PC, instr); + printf (" PC:\t%.5lX -> %s\n", saturn.PC, instr); + } + else if (!strcmp ("R0", argv[1])) + { + set_reg (val, 16, saturn.R0); + dump_reg (" R0", 16, saturn.R0); + } + else if (!strcmp ("R1", argv[1])) + { + set_reg (val, 16, saturn.R1); + dump_reg (" R1", 16, saturn.R1); + } + else if (!strcmp ("R2", argv[1])) + { + set_reg (val, 16, saturn.R2); + dump_reg (" R2", 16, saturn.R2); + } + else if (!strcmp ("R3", argv[1])) + { + set_reg (val, 16, saturn.R3); + dump_reg (" R3", 16, saturn.R3); + } + else if (!strcmp ("R4", argv[1])) + { + set_reg (val, 16, saturn.R4); + dump_reg (" R4", 16, saturn.R4); + } + else if (!strcmp ("IN", argv[1])) + { + set_reg (val, 4, saturn.IN); + dump_reg (" IN", 4, saturn.IN); + } + else if (!strcmp ("OUT", argv[1])) + { + set_reg (val, 3, saturn.OUT); + dump_reg (" OUT", 3, saturn.OUT); + } + else if (!strcmp ("CARRY", argv[1])) + { +#ifdef SIMPLE_64 + saturn.CARRY = (word_1)(val & 0x1); +#else + saturn.CARRY = (word_1)(val.lo & 0x1); +#endif + printf (" CARRY:\t%.1d\n", saturn.CARRY); + } + else if (!strcmp ("CY", argv[1])) + { +#ifdef SIMPLE_64 + saturn.CARRY = (word_1)(val & 0x1); +#else + saturn.CARRY = (word_1)(val.lo & 0x1); +#endif + printf (" CARRY:\t%.1d\n", saturn.CARRY); + } + else if (!strcmp ("ST", argv[1])) + { + set_st (val); + dump_st (); + } + else if (!strcmp ("HST", argv[1])) + { + set_hst (val); + dump_hst (); + } + else + { + printf ("No Register %s in CPU.\n", argv[1]); + } + } + } +} + +static void +#ifdef __FunctionProto__ +do_save (int argc, char **argv) +#else +do_save (argc, argv) + int argc; + char *argv; +#endif +{ + if (write_files ()) + { + printf ("Saving done.\n"); + } + else + { + printf ("Saving emulator-state failed.\n"); + } +} + +struct se { + int se_n; + word_20 se_p; + struct se *se_next; +}; + +char * +#ifdef __FunctionProto__ +get_stack (void) +#else +get_stack () +#endif +{ + word_20 dsktop, dskbot; + word_20 sp = 0, end = 0, ent = 0; + word_20 ram_base, ram_mask; + char dat[65536]; + char typ[256]; + int i, n; + + ram_base = saturn.mem_cntl[1].config[0]; + ram_mask = saturn.mem_cntl[1].config[1]; + if (opt_gx) + { + saturn.mem_cntl[1].config[0] = 0x80000; + saturn.mem_cntl[1].config[1] = 0xc0000; + dsktop = DSKTOP_GX; + dskbot = DSKBOT_GX; + } + else + { + saturn.mem_cntl[1].config[0] = 0x70000; + saturn.mem_cntl[1].config[1] = 0xf0000; + dsktop = DSKTOP_SX; + dskbot = DSKBOT_SX; + } + + load_addr(&sp, dsktop, 5); + load_addr(&end, dskbot, 5); + + n = (end - sp) / 5 - 1; /* end never matches sp */ + + printf("n = %d\n", n); + + //TODO Get the top of the stack in the buffer. + //TODO create a window and put the complete stack into it! + if (n) + { + load_addr(&ent, sp, 5); + decode_rpl_obj_2(ent, typ, dat); + printf("%d %p -> [%s] %s\n", i, ent, typ, dat); + } + + for (i = 0; i < n; i++) + { + load_addr(&ent, sp + (5 * i), 5); + decode_rpl_obj_2(ent, typ, dat); + printf("%d %p -> [%s] %s\n", i, ent, typ, dat); + } + + saturn.mem_cntl[1].config[0] = ram_base; + saturn.mem_cntl[1].config[1] = ram_mask; + + return; +} + +static void +#ifdef __FunctionProto__ +do_stack (int argc, char **argv) +#else +do_stack (argc, argv) + int argc; + char *argv; +#endif +{ + word_20 dsktop, dskbot; + word_20 sp = 0, end = 0, ent = 0; + word_20 ram_base, ram_mask; + char buf[65536]; + struct se *stack, *se; + int n; + + ram_base = saturn.mem_cntl[1].config[0]; + ram_mask = saturn.mem_cntl[1].config[1]; + if (opt_gx) + { + saturn.mem_cntl[1].config[0] = 0x80000; + saturn.mem_cntl[1].config[1] = 0xc0000; + dsktop = DSKTOP_GX; + dskbot = DSKBOT_GX; + } + else + { + saturn.mem_cntl[1].config[0] = 0x70000; + saturn.mem_cntl[1].config[1] = 0xf0000; + dsktop = DSKTOP_SX; + dskbot = DSKBOT_SX; + } + + load_addr(&sp, dsktop, 5); + load_addr(&end, dskbot, 5); + + stack = (struct se *)0; + n = 0; + do + { + load_addr(&ent, sp, 5); + if (ent == 0) + break; + n++; + sp += 5; + se = (struct se *)malloc(sizeof(struct se)); + if (se == 0) + { + fprintf(stderr, "Out off memory.\n"); + break; + } + se->se_n = n; + se->se_p = ent; + se->se_next = stack; + stack = se; + } + while (sp <= end); + + if (n == 0) + printf("Empty stack.\n"); + + se = stack; + while (se) + { + decode_rpl_obj(se->se_p, buf); + if (se->se_n != 1) + if (strlen(buf) > 63) + { + sprintf(&buf[60], "..."); + buf[63] = '\0'; + } + printf("%5d: %.5lX -> %s\n", se->se_n, se->se_p, buf); + se = se->se_next; + } + + se = stack; + while (se) + { + stack = se; + se = se->se_next; + free(stack); + } + + saturn.mem_cntl[1].config[0] = ram_base; + saturn.mem_cntl[1].config[1] = ram_mask; +} + +static void +#ifdef __FunctionProto__ +do_stat (int argc, char **argv) +#else +do_stat (argc, argv) + int argc; + char *argv; +#endif +{ + printf ("Instructions/s: %ld\n", saturn.i_per_s); + printf ("Timer 1 I/TICK: %d\n", saturn.t1_tick); + printf ("Timer 2 I/TICK: %d\n", saturn.t2_tick); +} + +static void +#ifdef __FunctionProto__ +do_step (int argc, char **argv) +#else +do_step (argc, argv) + int argc; + char *argv; +#endif +{ + word_20 next_instr; + word_32 n; + int leave; + + if (enter_debugger & ILLEGAL_INSTRUCTION) + { + printf ("Can\'t step into an illegal instruction."); + return; + } + + n = 1; + if (argc > 1) + if (!decode_32 (&n, argv[1])) + return; + + if (n <= 0) + return; + + in_debugger = 1; + step_instruction (); + + if (exec_flags & EXEC_BKPT) + { + if (check_breakpoint (BP_EXEC, saturn.PC)) + { + enter_debugger |= BREAKPOINT_HIT; + return; + } + } + + next_instr = saturn.PC; + + sched_adjtime = 0; + schedule (); + + enter_debugger = 0; + while (1) + { + if (enter_debugger) + break; + + leave = 0; + + if (saturn.PC == next_instr) + { + n--; + leave = 1; + if (n == 0) + break; + } + + step_instruction (); + + if (exec_flags & EXEC_BKPT) + { + if (check_breakpoint (BP_EXEC, saturn.PC)) + { + enter_debugger |= BREAKPOINT_HIT; + break; + } + } + + if (leave) + next_instr = saturn.PC; + + schedule (); + } +} + +static void +#ifdef __FunctionProto__ +do_reset (int argc, char **argv) +#else +do_reset (argc, argv) + int argc; + char *argv; +#endif +{ + if (confirm ("Do a RESET (PC = 00000)?")) + { + saturn.PC = 0; + enter_debugger &= ~ILLEGAL_INSTRUCTION; + } +} + +static void +#ifdef __FunctionProto__ +do_rstk (int argc, char **argv) +#else +do_rstk (argc, argv) + int argc; + char *argv; +#endif +{ + int i, j; + + disassemble (saturn.PC, instr); + printf ("PC: %.5lX: %s\n", saturn.PC, instr); + if (saturn.rstkp < 0) + { + printf ("Empty return stack.\n"); + } + else + { + j = 0; + for (i = saturn.rstkp; i >= 0; i--) + { + disassemble (saturn.rstk[i], instr); + printf ("%2d: %.5lX: %s\n", j, saturn.rstk[i], instr); + j++; + } + } +} + +int +#ifdef __FunctionProto__ +debug (void) +#else +debug () +#endif +{ + t1_t2_ticks ticks; + struct cmd *cmdp; + char *cp; + int argc; + char *argv[MAX_ARGS]; + char *rl = NULL; + static char *cl = (char *) 0; + static char *old_line = (char *) 0; + int i; + + /* + * do we want to debug ??? + */ + if (!useDebugger) + { + if (enter_debugger & ILLEGAL_INSTRUCTION) + { + if (!quiet) + fprintf (stderr, "%s: reset (illegal instruction at 0x%.5lX)\n", + progname, saturn.PC); + saturn.PC = 0; + } + if (enter_debugger & USER_INTERRUPT) + if (verbose) + printf ("%s: user interrupt (SIGINT) ignored\n", progname); + exit_x48(1); + if (enter_debugger & BREAKPOINT_HIT) + if (verbose) + printf ("%s: breakpoint hit at 0x%.5lX ignored\n", + progname, saturn.PC); + if (enter_debugger & TRAP_INSTRUCTION) + if (verbose) + printf ("%s: trap instruction at 0x%.5lX ignored\n", + progname, saturn.PC); + enter_debugger = 0; + return 0; + } + + /* + * update the lcd if necessary + */ + if (device.display_touched) + { + device.display_touched = 0; + update_display (); +#ifdef HAVE_XSHM + if (disp.display_update) + refresh_display (); +#endif + } + + /* + * debugging is counted as idle time + */ + stop_timer (RUN_TIMER); + start_timer (IDLE_TIMER); + + continue_flag = 0; + + if (enter_debugger & ILLEGAL_INSTRUCTION) + { + printf ("ILLEGAL INSTRUCTION at %.5lX : %s\n", + saturn.PC, str_nibbles (saturn.PC, 16)); + } + + if (enter_debugger & TRAP_INSTRUCTION) + { + printf ("TRAP at %.5lX : %s\n", + saturn.PC - 5, str_nibbles (saturn.PC - 5, 16)); + enter_debugger &= ~TRAP_INSTRUCTION; + } + + do + { + + /* + * print current instruction + */ + disassemble (saturn.PC, instr); + printf ("%.5lX: %s\n", saturn.PC, instr); + + /* + * read a command + */ + rl = readline ("x48-debug> "); + + if (rl == (char *) 0) + { + continue_flag = 1; + continue; + } + if (*rl == '\0') + { + free (rl); + rl = (char *) 0; + if (cl) + { + free (cl); + cl = (char *) 0; + } + cl = strdup (old_line == NULL ? "(null)" : old_line); + } + else + { + if (cl) + { + free (cl); + cl = (char *) 0; + } + if (old_line) + { + free (old_line); + old_line = (char *) 0; + } + cl = strdup (rl); + old_line = strdup (rl); +#ifdef HAVE_READLINE + add_history (rl); +#endif + free (rl); + rl = (char *) 0; + } + + /* + * decode the commandline + */ + cp = strtok (cl, " \t"); + for (cmdp = cmd_tbl; cmdp->name; cmdp++) + { + if (strcmp (cp, cmdp->name) == 0) + { + break; + } + } + + argc = 0; + argv[argc++] = cp; + while ((cp = strtok ((char *) 0, " \t")) != (char *) 0) + { + argv[argc++] = cp; + if (argc == MAX_ARGS) + break; + } + for (i = argc; i < MAX_ARGS; i++) + argv[i] = (char *) NULL; + + /* + * execute the command, if valid + */ + if (cmdp->func) + { + (*cmdp->func) (argc, argv); + } + else + { + printf ("Undefined command \"%s\". Try \"help\".\n", argv[0]); + } + in_debugger = 0; + + } + while (!continue_flag); + + /* + * adjust the hp48's timers + */ + in_debugger = 1; + ticks = get_t1_t2 (); + in_debugger = 0; + + if (saturn.t2_ctrl & 0x01) + { + saturn.timer2 = ticks.t2_ticks; + } + + saturn.timer1 = (set_t1 - ticks.t1_ticks) & 0xf; + + sched_adjtime = 0; + + /* + * restart timers + */ + stop_timer (IDLE_TIMER); + start_timer (RUN_TIMER); + + set_accesstime(); + + if (enter_debugger & ILLEGAL_INSTRUCTION) + { + printf ("Reset (ILLEGAL INSTRUCTION)\n"); + saturn.PC = 0; + } + else + { + printf ("Continue.\n"); + } + + enter_debugger = 0; + + /* + * Set exec_flags according to breakpoints, etc. + */ + exec_flags = 0; + if (num_bkpts) + exec_flags |= EXEC_BKPT; + + return 0; +} + +int +#ifdef __FunctionProto__ +emulate_debug (void) +#else +emulate_debug () +#endif +{ + do + { + + step_instruction (); + + if (exec_flags & EXEC_BKPT) + { + if (check_breakpoint (BP_EXEC, saturn.PC)) + { + enter_debugger |= BREAKPOINT_HIT; + break; + } + } + + if (schedule_event-- == 0) + { + schedule (); + } + + } + while (!enter_debugger); + + return 0; +} diff --git a/src/debugger.h b/src/debugger.h new file mode 100644 index 0000000..1044543 --- /dev/null +++ b/src/debugger.h @@ -0,0 +1,66 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: debugger.h,v $ + * Revision 1.4 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.3 1994/11/28 02:19:22 ecd + * catch TRAP instructions + * + * Revision 1.3 1994/11/28 02:19:22 ecd + * catch TRAP instructions + * + * Revision 1.2 1994/11/02 14:51:27 ecd + * added breakpoint related stuff + * + * Revision 1.1 1994/10/04 15:12:38 ecd + * Initial revision + * + * + * $Id: debugger.h,v 1.4 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#ifndef _DEBUGGER_H +#define _DEBUGGER_H 1 + +#include "global.h" +#include "hp48.h" + +#define USER_INTERRUPT 1 +#define ILLEGAL_INSTRUCTION 2 +#define BREAKPOINT_HIT 4 +#define TRAP_INSTRUCTION 8 + +/* + * exec_flags values + */ +#define EXEC_BKPT 1 + +extern int enter_debugger; +extern int in_debugger; +extern int exec_flags; + +extern void init_debugger __ProtoType__((void)); +extern int debug __ProtoType__((void)); +extern int emulate_debug __ProtoType__((void)); + +extern char *str_nibbles __ProtoType__((word_20 addr, int n)); + +#endif /* !_DEBUGGER_H */ diff --git a/src/device.c b/src/device.c new file mode 100644 index 0000000..391e2f0 --- /dev/null +++ b/src/device.c @@ -0,0 +1,209 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: device.c,v $ + * Revision 1.8 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.7 1994/11/28 02:00:51 ecd + * played around with sound stuff + * + * Revision 1.7 1994/11/28 02:00:51 ecd + * played around with sound stuff + * + * Revision 1.6 1994/11/02 14:40:38 ecd + * adapted to new timer 2 stuff from timer.c + * + * Revision 1.5 1994/10/05 08:36:44 ecd + * removed addr queue + * + * Revision 1.4 1994/09/30 12:37:09 ecd + * new and FASTER display handling + * + * Revision 1.3 1994/09/18 15:29:22 ecd + * started Real Time support + * + * Revision 1.2 1994/09/13 16:57:00 ecd + * changed to plain X11 + * + * Revision 1.1 1994/08/26 11:09:02 ecd + * Initial revision + * + * + * $Id: device.c,v 1.8 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#include "global.h" + +#include + +#include "hp48.h" +#include "hp48_emu.h" +#include "device.h" +#include "timer.h" +#include "x48_x11.h" + +extern int device_check; + +device_t device; + +void +#ifdef __FunctionProto__ +check_devices(void) +#else +check_devices() +#endif +{ + if (device.display_touched > 0 && device.display_touched-- == 1) { + device.display_touched = 0; + update_display(); + } + if (device.display_touched > 0) { + device_check = 1; + } + if (device.contrast_touched) { + device.contrast_touched = 0; + adjust_contrast(display.contrast); + } + if (device.ann_touched) { + device.ann_touched = 0; + draw_annunc(); + } + if (device.baud_touched) { + device.baud_touched = 0; + serial_baud(saturn.baud); + } + if (device.ioc_touched) { + device.ioc_touched = 0; + if ((saturn.io_ctrl & 0x02) && (saturn.rcs & 0x01)) { + do_interupt(); + } + } + if (device.rbr_touched) { + device.rbr_touched = 0; + receive_char(); + } + if (device.tbr_touched) { + device.tbr_touched = 0; + transmit_char(); + } + if (device.t1_touched) { + saturn.t1_instr = 0; + sched_timer1 = saturn.t1_tick; + restart_timer(T1_TIMER); + set_t1 = saturn.timer1; + device.t1_touched = 0; + } + if (device.t2_touched) { + saturn.t2_instr = 0; + sched_timer2 = saturn.t2_tick; + device.t2_touched = 0; + } +#if 0 + if (device.disp_test_touched) { + device.disp_test_touched = 0; + } + if (device.crc_touched) { + device.crc_touched = 0; + } + if (device.power_status_touched) { + device.power_status_touched = 0; + } + if (device.power_ctrl_touched) { + device.power_ctrl_touched = 0; + } + if (device.mode_touched) { + device.mode_touched = 0; + } + if (device.card_ctrl_touched) { + device.card_ctrl_touched = 0; + } + if (device.card_status_touched) { + device.card_status_touched = 0; + } + if (device.tcs_touched) { + device.tcs_touched = 0; + } + if (device.rcs_touched) { + device.rcs_touched = 0; + } + if (device.sreq_touched) { + device.sreq_touched = 0; + } + if (device.ir_ctrl_touched) { + device.ir_ctrl_touched = 0; + } + if (device.base_off_touched) { + device.base_off_touched = 0; + } + if (device.lcr_touched) { + device.lcr_touched = 0; + } + if (device.lbr_touched) { + device.lbr_touched = 0; + } + if (device.scratch_touched) { + device.scratch_touched = 0; + } + if (device.base_nibble_touched) { + device.base_nibble_touched = 0; + } + if (device.unknown_touched) { + device.unknown_touched = 0; + } + if (device.t1_ctrl_touched) { + device.t1_ctrl_touched = 0; + } + if (device.t2_ctrl_touched) { + device.t2_ctrl_touched = 0; + } + if (device.unknown2_touched) { + device.unknown2_touched = 0; + } +#endif +} + +#if 0 + +#include +#include +#include +#include + +void +#ifdef __FunctionProto__ +check_out_register(void) +#else +check_out_register() +#endif +{ + static int au = -2; + unsigned char c[] = { 0xff, 0x00 }; + + if (au == -2) + if ((au = open("/dev/audio", O_WRONLY)) < 0) + if (au < 0) + return; + if (saturn.OUT[2] & 0x8) + write(au, c, 1); + else + write(au, &c[1], 1); +} + +#endif diff --git a/src/device.h b/src/device.h new file mode 100644 index 0000000..34fa31d --- /dev/null +++ b/src/device.h @@ -0,0 +1,131 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: device.h,v $ + * Revision 1.7 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.6 1994/11/28 02:19:22 ecd + * played with the out register + * + * Revision 1.6 1994/11/28 02:19:22 ecd + * played with the out register + * + * Revision 1.5 1994/11/02 14:51:27 ecd + * added some function declarations + * + * Revision 1.4 1994/10/05 08:33:22 ecd + * remove addr queue + * + * Revision 1.3 1994/09/30 12:32:49 ecd + * added DISP_INSTR_OFF for faster and better display + * + * Revision 1.2 1994/09/13 16:58:42 ecd + * changed to plain X11 + * + * Revision 1.1 1994/08/26 11:09:18 ecd + * Initial revision + * + * + * + * $Id: device.h,v 1.7 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#ifndef _DEVICE_H +#define _DEVICE_H 1 + +#include "global.h" + +#define DISP_INSTR_OFF 0x10 + +#define ANN_LEFT 0x81 +#define ANN_RIGHT 0x82 +#define ANN_ALPHA 0x84 +#define ANN_BATTERY 0x88 +#define ANN_BUSY 0x90 +#define ANN_IO 0xa0 + +typedef struct device_t { + + int display_touched; + + char contrast_touched; + + char disp_test_touched; + + char crc_touched; + + char power_status_touched; + char power_ctrl_touched; + + char mode_touched; + + char ann_touched; + + char baud_touched; + + char card_ctrl_touched; + char card_status_touched; + + char ioc_touched; + + char tcs_touched; + char rcs_touched; + + char rbr_touched; + char tbr_touched; + + char sreq_touched; + + char ir_ctrl_touched; + + char base_off_touched; + + char lcr_touched; + char lbr_touched; + + char scratch_touched; + char base_nibble_touched; + + char unknown_touched; + + char t1_ctrl_touched; + char t2_ctrl_touched; + + char unknown2_touched; + + char t1_touched; + char t2_touched; + +} device_t; + +extern device_t device; +extern void check_devices __ProtoType__((void)); +#if 0 +extern void check_out_register __ProtoType__((void)); +#endif + +extern void update_display __ProtoType__((void)); +extern void redraw_display __ProtoType__((void)); +extern void disp_draw_nibble __ProtoType__((word_20 addr, word_4 val)); +extern void menu_draw_nibble __ProtoType__((word_20 addr, word_4 val)); +extern void draw_annunc __ProtoType__((void)); +extern void redraw_annunc __ProtoType__((void)); + +#endif /* !_DEVICE_H */ diff --git a/src/disasm.c b/src/disasm.c new file mode 100644 index 0000000..554c155 --- /dev/null +++ b/src/disasm.c @@ -0,0 +1,1965 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: disasm.c,v $ + * Revision 1.6 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.5 1994/12/07 20:20:50 ecd + * some minor fixes + * + * Revision 1.5 1994/12/07 20:20:50 ecd + * some minor fixes + * + * Revision 1.4 1994/11/28 02:00:51 ecd + * enlarged field_tbl further + * + * Revision 1.3 1994/11/04 03:42:34 ecd + * fixed bug in field_tbl + * + * Revision 1.2 1994/11/02 14:40:38 ecd + * completed disassembler + * + * Revision 1.1 1994/10/09 20:29:47 ecd + * Initial revision + * + * + * $Id: disasm.c,v 1.6 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#include "global.h" + +#include +#include +#include + +#include "hp48.h" +#include "disasm.h" + +#define TAB_SKIP 8 + +int disassembler_mode = CLASS_MNEMONICS; + +char *mode_name[] = +{ + "HP", + "class" +}; + +static char *hex[] = +{ + "0123456789ABCDEF", + "0123456789abcdef", +}; + +static char *opcode_0_tbl[32] = +{ +/* + * HP Mnemonics + */ + "RTNSXM", "RTN", "RTNSC", "RTNCC", + "SETHEX", "SETDEC", "RSTK=C", "C=RSTK", + "CLRST", "C=ST", "ST=C", "CSTEX", + "P=P+1", "P=P-1", "(NULL)", "RTI", +/* + * Class Mnemonics + */ + "rtnsxm", "rtn", "rtnsc", "rtncc", + "sethex", "setdec", "push", "pop", + "clr.3 st", "move.3 st, c", "move.3 c, st", "exg.3 c, st", + "inc.1 p", "dec.1 p", "(null)", "rti" +}; + +static char *op_str_0[16] = +{ +/* + * HP Mnemonics + */ + "A=A%cB", "B=B%cC", "C=C%cA", "D=D%cC", + "B=B%cA", "C=C%cB", "A=A%cC", "C=C%cD", +/* + * Class Mnemonics + */ + "b, a", "c, b", "a, c", "c, d", + "a, b", "b, c", "c, a", "d, c" +}; + +static char *op_str_1[16] = +{ +/* + * HP Mnemonics + */ + "DAT0=A", "DAT1=A", "A=DAT0", "A=DAT1", + "DAT0=C", "DAT1=C", "C=DAT0", "C=DAT1", +/* + * Class Mnemonics + */ + "a, (d0)", "a, (d1)", "(d0), a", "(d1), a", + "c, (d0)", "c, (d1)", "(d0), c", "(d1), c" +}; + +static char *in_str_80[32] = +{ +/* + * HP Mnemonics + */ + "OUT=CS", "OUT=C", "A=IN", "C=IN", + "UNCNFG", "CONFIG", "C=ID", "SHUTDN", + NULL, "C+P+1", "RESET", "BUSCC", + NULL, NULL, "SREQ?", NULL, +/* + * Class Mnemonics + */ + "move.s c, out", "move.3 c, out", "move.4 in, a", "move.4 in, c", + "uncnfg", "config", "c=id", "shutdn", + NULL, "add.a p+1, c", "reset", "buscc", + NULL, NULL, "sreq?", NULL +}; + +static char *in_str_808[32] = +{ +/* + * HP Mnemonics + */ + "INTON", NULL, NULL, "BUSCB", + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + "PC=(A)", "BUSCD", "PC=(C)", "INTOFF", +/* + * Class Mnemonics + */ + "inton", NULL, NULL, "buscb", + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + "jmp (a)", "buscd", "jmp (c)", "intoff" +}; + +static char *op_str_81[8] = +{ +/* + * HP Mnemonics + */ + "A", "B", "C", "D", +/* + * Class Mnemonics + */ + "a", "b", "c", "d", +}; + +static char *in_str_81b[32] = +{ +/* + * HP Mnemonics + */ + NULL, NULL, "PC=A", "PC=C", + "A=PC", "C=PC", "APCEX", "CPCEX", + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +/* + * Class Mnemonics + */ + NULL, NULL, "jmp a", "jmp c", + "move.a pc, a", "move.a pc, c", "exg.a a, pc", "exg.a c, pc", + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +}; + +static char *in_str_9[16] = +{ +/* + * HP Mnemonics + */ + "=", "#", "=", "#", + ">", "<", ">=", "<=", +/* + * Class Mnemonics + */ + "eq", "ne", "eq", "ne", + "gt", "lt", "ge", "le" +}; + +static char *op_str_9[16] = +{ +/* + * HP Mnemonics + */ + "?A%sB", "?B%sC", "?C%sA", "?D%sC", + "?A%s0", "?B%s0", "?C%s0", "?D%s0", +/* + * Class Mnemonics + */ + "a, b", "b, c", "c, a", "d, c", + "a, 0", "b, 0", "c, 0", "d, 0" +}; + +static char *op_str_af[32] = +{ +/* + * HP Mnemonics + */ + "A=A%sB", "B=B%sC", "C=C%sA", "D=D%sC", + "A=A%sA", "B=B%sB", "C=C%sC", "D=D%sD", + "B=B%sA", "C=C%sB", "A=A%sC", "C=C%sD", + "A=B%sA", "B=C%sB", "C=A%sC", "D=C%sD", +/* + * Class Mnemonics + */ + "b, a", "c, b", "a, c", "c, d", + "a, a", "b, b", "c, c", "d, d", + "a, b", "b, c", "c, a", "d, c", + "b, a", "c, b", "a, c", "c, d" +}; + +static char hp_reg_1_af[] = "ABCDABCDBCACABAC"; +static char hp_reg_2_af[] = "0000BCACABCDBCCD"; + +static char *field_tbl[32] = +{ +/* + * HP Mnemonics + */ + "P", "WP", "XS", "X", + "S", "M", "B", "W", + "P", "WP", "XS", "X", + "S", "M", "B", "A", +/* + * Class Mnemonics + */ + ".p", ".wp", ".xs", ".x", + ".s", ".m", ".b", ".w", + ".p", ".wp", ".xs", ".x", + ".s", ".m", ".b", ".a", +}; + +static char *hst_bits[8] = +{ +/* + * HP Mnemonics + */ + "XM", "SB", "SR", "MP", +/* + * Class Mnemonics + */ + "xm", "sb", "sr", "mp", +}; + +int +#ifdef __FunctionProto__ +read_int (word_20 * addr, int n) +#else +read_int (addr, n) + word_20 *addr; + int n; +#endif +{ + int i, t; + + for (i = 0, t = 0; i < n; i++) + t |= read_nibble ((*addr)++) << (i * 4); + return t; +} + +char * +#ifdef __FunctionProto__ +append_str (char *buf, char *str) +#else +append_str (buf, str) + char *buf; + char *str; +#endif +{ + while ((*buf = *str++)) + buf++; + return buf; +} + +char * +#ifdef __FunctionProto__ +append_tab_16 (char *buf) +#else +append_tab_16 (buf) + char *buf; +#endif +{ + int n; + char *p; + + n = 16 - (strlen (buf) % 16); + p = &buf[strlen (buf)]; + while (n--) + *p++ = ' '; + *p = '\0'; + return p; +} + +char * +#ifdef __FunctionProto__ +append_tab (char *buf) +#else +append_tab (buf) + char *buf; +#endif +{ + int n; + char *p; + + n = TAB_SKIP - (strlen (buf) % TAB_SKIP); + p = &buf[strlen (buf)]; + while (n--) + *p++ = ' '; + *p = '\0'; + return p; +} + +char * +#ifdef __FunctionProto__ +append_field (char *buf, word_4 fn) +#else +append_field (buf, fn) + char *buf; + word_4 fn; +#endif +{ + buf = append_str (buf, field_tbl[fn + 16 * disassembler_mode]); + return buf; +} + +char * +#ifdef __FunctionProto__ +append_imm_nibble (char *buf, word_20 * addr, int n) +#else +append_imm_nibble (buf, addr, n) + char *buf; + word_20 *addr; + int n; +#endif +{ + int i; + char t[16]; + + if (disassembler_mode == CLASS_MNEMONICS) + { + *buf++ = '#'; + if (n > 1) + *buf++ = '$'; + } + if (n > 1) + { + for (i = 0; i < n; i++) + t[i] = hex[disassembler_mode][read_nibble ((*addr)++)]; + for (i = n - 1; i >= 0; i--) + { + *buf++ = t[i]; + } + *buf = '\0'; + } + else + { + sprintf (t, "%d", read_nibble ((*addr)++)); + buf = append_str (buf, t); + } + return buf; +} + +char * +#ifdef __FunctionProto__ +append_addr (char *buf, word_20 addr) +#else +append_addr (buf, addr) + char *buf; + word_20 addr; +#endif +{ + int shift; + long mask; + + if (disassembler_mode == CLASS_MNEMONICS) + { + *buf++ = '$'; + } + for (mask = 0xf0000, shift = 16; mask != 0; mask >>= 4, shift -= 4) + *buf++ = hex[disassembler_mode][(addr & mask) >> shift]; + *buf = '\0'; + return buf; +} + +char * +#ifdef __FunctionProto__ +append_r_addr (char *buf, word_20 * pc, long disp, int n, int offset) +#else +append_r_addr (buf, pc, disp, n, offset) + char *buf; + word_20 *pc; + long disp; + int n; + int offset; +#endif +{ + long sign; + + sign = 1 << (n * 4 - 1); + if (disp & sign) + disp |= ~(sign - 1); + *pc += disp; + + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (disp < 0) + { + buf = append_str (buf, "-"); + disp = -disp - offset; + } + else + { + buf = append_str (buf, "+"); + disp += offset; + } + buf = append_addr (buf, disp); + break; + case CLASS_MNEMONICS: + if (disp < 0) + { + buf = append_str (buf, "-"); + disp = -disp - offset; + } + else + { + buf = append_str (buf, "+"); + disp += offset; + } + buf = append_addr (buf, disp); + break; + default: + buf = append_str (buf, "Unknown disassembler mode"); + break; + } + return buf; +} + +char * +#ifdef __FunctionProto__ +append_pc_comment (char *buf, word_20 pc) +#else +append_pc_comment (buf, pc) + char *buf; + word_20 pc; +#endif +{ + char *p = buf; + + while (strlen (buf) < 4 * TAB_SKIP) + p = append_tab (buf); + + switch (disassembler_mode) + { + case HP_MNEMONICS: + p = append_str (p, "# Address: "); + p = append_addr (p, pc); + break; + case CLASS_MNEMONICS: + p = append_str (p, "; address: "); + p = append_addr (p, pc); + break; + default: + p = append_str (p, "Unknown disassembler mode"); + break; + } + return p; +} + + +char * +#ifdef __FunctionProto__ +append_hst_bits (char *buf, int n) +#else +append_hst_bits (buf, n) + char *buf; + int n; +#endif +{ + int i; + char *p = buf; + + switch (disassembler_mode) + { + case HP_MNEMONICS: + for (i = 0; i < 4; i++) + if (n & (1 << i)) + { + if (p != buf) + p = append_str (p, "="); + p = append_str (p, hst_bits[i + 4 * disassembler_mode]); + } + break; + + case CLASS_MNEMONICS: + while (strlen (buf) < 4 * TAB_SKIP) + p = append_tab (buf); + p = &buf[strlen (buf)]; + p = append_str (p, "; hst bits: "); + + for (buf = p, i = 0; i < 4; i++) + if (n & (1 << i)) + { + if (p != buf) + p = append_str (p, ", "); + p = append_str (p, hst_bits[i + 4 * disassembler_mode]); + } + break; + + default: + p = append_str (p, "Unknown disassembler mode"); + break; + } + + return p; +} + +char * +#ifdef __FunctionProto__ +disasm_1 (word_20 * addr, char *out) +#else +disasm_1 (addr, out) + word_20 *addr; + char *out; +#endif +{ + word_4 n; + word_4 fn; + char *p; + char buf[20]; + char c; + + p = out; + switch ((n = read_nibble ((*addr)++))) + { + case 0: + case 1: + fn = read_nibble ((*addr)++); + fn = (fn & 7); + if (fn > 4) + fn -= 4; + switch (disassembler_mode) + { + case HP_MNEMONICS: + c = (char) ((fn < 8) ? 'A' : 'C'); + if (n == 0) + sprintf (buf, "R%d=%c", fn, c); + else + sprintf (buf, "%c=R%d", c, fn); + p = append_str (out, buf); + break; + case CLASS_MNEMONICS: + p = append_str (out, "move.w"); + p = append_tab (out); + c = (char) ((fn < 8) ? 'a' : 'c'); + if (n == 0) + sprintf (buf, "%c, r%d", c, fn); + else + sprintf (buf, "r%d, %c", fn, c); + p = append_str (p, buf); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 2: + fn = read_nibble ((*addr)++); + fn = (fn & 7); + if (fn > 4) + fn -= 4; + switch (disassembler_mode) + { + case HP_MNEMONICS: + c = (char) ((fn < 8) ? 'A' : 'C'); + sprintf (buf, "%cR%dEX", c, fn); + p = append_str (out, buf); + break; + case CLASS_MNEMONICS: + p = append_str (out, "exg.w"); + p = append_tab (out); + c = (char) ((fn < 8) ? 'a' : 'c'); + sprintf (buf, "%c, r%d", c, fn); + p = append_str (p, buf); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 3: + n = read_nibble ((*addr)++); + switch (disassembler_mode) + { + case HP_MNEMONICS: + c = (n & 4) ? 'C' : 'A'; + if (n & 2) + { + if (n < 8) + { + sprintf (buf, "%cD%dEX", c, (n & 1)); + } + else + { + sprintf (buf, "%cD%dXS", c, (n & 1)); + } + } + else + { + if (n < 8) + { + sprintf (buf, "D%d=%c", (n & 1), c); + } + else + { + sprintf (buf, "D%d=%cS", (n & 1), c); + } + } + p = append_str (out, buf); + break; + case CLASS_MNEMONICS: + p = append_str (out, (n & 2) ? "exg." : "move."); + p = append_str (p, (n < 8) ? "a" : "4"); + p = append_tab (out); + c = (n & 4) ? 'c' : 'a'; + sprintf (buf, "%c, d%d", c, (n & 1)); + p = append_str (p, buf); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 4: + case 5: + fn = read_nibble ((*addr)++); + switch (disassembler_mode) + { + case HP_MNEMONICS: + p = append_str (out, op_str_1[(fn & 7) + 8 * disassembler_mode]); + p = append_tab (out); + if (n == 4) + { + p = append_str (p, (fn < 8) ? "A" : "B"); + } + else + { + n = read_nibble ((*addr)++); + if (fn < 8) + { + p = append_field (p, n); + } + else + { + sprintf (buf, "%d", n + 1); + p = append_str (p, buf); + } + } + break; + case CLASS_MNEMONICS: + p = append_str (out, "move"); + if (n == 4) + { + p = append_str (p, "."); + p = append_str (p, (fn < 8) ? "a" : "b"); + } + else + { + n = read_nibble ((*addr)++); + if (fn < 8) + { + p = append_field (p, n); + } + else + { + sprintf (buf, ".%d", n + 1); + p = append_str (p, buf); + } + } + p = append_tab (out); + p = append_str (p, op_str_1[(fn & 7) + 8 * disassembler_mode]); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 6: + case 7: + case 8: + case 0xc: + fn = read_nibble (*addr++); + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (n == 6 || n == 8) + p = append_str (out, "D0=D0"); + else + p = append_str (out, "D1=D1"); + if (n < 8) + p = append_str (p, "+"); + else + p = append_str (p, "-"); + p = append_tab (out); + sprintf (buf, "%d", fn + 1); + p = append_str (p, buf); + break; + case CLASS_MNEMONICS: + if (n < 8) + p = append_str (out, "add.a"); + else + p = append_str (out, "sub.a"); + p = append_tab (out); + sprintf (buf, "#%d, ", fn + 1); + p = append_str (p, buf); + if (n == 6 || n == 8) + p = append_str (p, "d0"); + else + p = append_str (p, "d1"); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 9: + case 0xa: + case 0xb: + case 0xd: + case 0xe: + case 0xf: + c = (char) ((n < 0xd) ? '0' : '1'); + switch (n & 3) + { + case 1: + n = 2; + break; + case 2: + n = 4; + break; + case 3: + n = 5; + break; + } + switch (disassembler_mode) + { + case HP_MNEMONICS: + sprintf (buf, "D%c=(%d)", c, n); + p = append_str (out, buf); + p = append_tab (out); + p = append_imm_nibble (p, addr, n); + break; + case CLASS_MNEMONICS: + if (n == 5) + { + sprintf (buf, "move.a"); + } + else if (n == 4) + { + sprintf (buf, "move.as"); + } + else + { + sprintf (buf, "move.b"); + } + p = append_str (out, buf); + p = append_tab (out); + p = append_imm_nibble (p, addr, n); + sprintf (buf, ", d%c", c); + p = append_str (p, buf); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + default: + break; + } + return p; +} + + +char * +#ifdef __FunctionProto__ +disasm_8 (word_20 * addr, char *out) +#else +disasm_8 (addr, out) + word_20 *addr; + char *out; +#endif +{ + word_4 n; + word_4 fn; + char *p = out; + char c; + char buf[20]; + word_20 disp, pc; + + fn = read_nibble ((*addr)++); + switch (fn) + { + case 0: + n = read_nibble ((*addr)++); + if (NULL != (p = in_str_80[n + 16 * disassembler_mode])) + { + p = append_str (out, p); + return p; + } + switch (n) + { + case 8: + fn = read_nibble ((*addr)++); + if (NULL != (p = in_str_808[fn + 16 * disassembler_mode])) + { + p = append_str (out, p); + return p; + } + switch (fn) + { + case 1: + n = read_nibble ((*addr)++); + if (n == 0) + { + switch (disassembler_mode) + { + case HP_MNEMONICS: + p = append_str (out, "RSI"); + break; + case CLASS_MNEMONICS: + p = append_str (out, "rsi"); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + } + break; + case 2: + n = read_nibble ((*addr)++); + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (n < 5) + { + sprintf (buf, "LA(%d)", n + 1); + } + else + { + sprintf (buf, "LAHEX"); + } + p = append_str (out, buf); + p = append_tab (out); + p = append_imm_nibble (p, addr, n + 1); + break; + case CLASS_MNEMONICS: + sprintf (buf, "move.%d", n + 1); + p = append_str (out, buf); + p = append_tab (out); + p = append_imm_nibble (p, addr, n + 1); + sprintf (buf, ", a.p"); + p = append_str (p, buf); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 4: + case 5: + case 8: + case 9: + + switch (disassembler_mode) + { + case HP_MNEMONICS: + sprintf (buf, "%cBIT=%d", (fn & 8) ? 'C' : 'A', + (fn & 1) ? 1 : 0); + p = append_str (out, buf); + p = append_tab (out); + p = append_imm_nibble (p, addr, 1); + break; + case CLASS_MNEMONICS: + p = append_str (out, (fn & 1) ? "bset" : "bclr"); + p = append_tab (out); + p = append_imm_nibble (p, addr, 1); + p = append_str (p, (fn & 8) ? ", c" : ", a"); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 6: + case 7: + case 0xa: + case 0xb: + + n = read_nibble ((*addr)++); + pc = *addr; + disp = read_int (addr, 2); + + switch (disassembler_mode) + { + case HP_MNEMONICS: + c = (char) ((fn < 0xa) ? 'A' : 'C'); + sprintf (buf, "?%cBIT=%d", c, (fn & 1) ? 1 : 0); + p = append_str (out, buf); + p = append_tab (out); + sprintf (buf, "%d", n); + p = append_str (p, buf); + if (disp != 0) + { + p = append_str (p, ", GOYES "); + p = append_r_addr (p, &pc, disp, 2, 5); + p = append_pc_comment (out, pc); + } + else + p = append_str (p, ", RTNYES"); + break; + case CLASS_MNEMONICS: + c = (char) ((fn < 0xa) ? 'a' : 'c'); + p = append_str (out, (disp == 0) ? "rt" : "b"); + p = append_str (p, (fn & 1) ? "bs" : "bc"); + p = append_tab (out); + sprintf (buf, "#%d, %c", n, c); + p = append_str (p, buf); + if (disp != 0) + { + p = append_str (p, ", "); + p = append_r_addr (p, &pc, disp, 2, 5); + p = append_pc_comment (out, pc); + } + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + default: + break; + } + break; + + case 0xc: + case 0xd: + case 0xf: + fn = read_nibble ((*addr)++); + switch (disassembler_mode) + { + case HP_MNEMONICS: + sprintf (buf, (n == 0xf) ? "%c%cEX" : "%c=%c", + (n == 0xd) ? 'P' : 'C', (n == 0xd) ? 'C' : 'P'); + p = append_str (out, buf); + p = append_tab (out); + sprintf (buf, "%d", fn); + p = append_str (p, buf); + break; + case CLASS_MNEMONICS: + p = append_str (out, (n == 0xf) ? "exg.1" : "move.1"); + p = append_tab (out); + sprintf (buf, (n == 0xd) ? "p, c.%d" : "c.%d, p", fn); + p = append_str (p, buf); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + default: + break; + + } + break; + + case 1: + switch (n = read_nibble ((*addr)++)) + { + case 0: + case 1: + case 2: + case 3: + switch (disassembler_mode) + { + case HP_MNEMONICS: + sprintf (buf, "%sSLC", op_str_81[(n & 3) + 4 * disassembler_mode]); + p = append_str (out, buf); + break; + case CLASS_MNEMONICS: + p = append_str (out, "rol.w"); + p = append_tab (out); + p = append_str (p, "#4, "); + p = append_str (p, op_str_81[(n & 3) + 4 * disassembler_mode]); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 4: + case 5: + case 6: + case 7: + switch (disassembler_mode) + { + case HP_MNEMONICS: + sprintf (buf, "%sSRC", op_str_81[(n & 3) + 4 * disassembler_mode]); + p = append_str (out, buf); + break; + case CLASS_MNEMONICS: + p = append_str (out, "ror.w"); + p = append_tab (out); + p = append_str (p, "#4, "); + p = append_str (p, op_str_81[(n & 3) + 4 * disassembler_mode]); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 8: + fn = read_nibble ((*addr)++); + n = read_nibble ((*addr)++); + switch (disassembler_mode) + { + case HP_MNEMONICS: + sprintf (buf, "%s=%s%cCON", + op_str_81[(n & 3) + 4 * disassembler_mode], + op_str_81[(n & 3) + 4 * disassembler_mode], + (n < 8) ? '+' : '-'); + p = append_str (out, buf); + p = append_tab (out); + p = append_field (p, fn); + fn = read_nibble ((*addr)++); + sprintf (buf, ", %d", fn + 1); + p = append_str (p, buf); + break; + case CLASS_MNEMONICS: + p = append_str (out, (n < 8) ? "add" : "sub"); + p = append_field (p, fn); + p = append_tab (out); + fn = read_nibble ((*addr)++); + sprintf (buf, "#%d, ", fn + 1); + p = append_str (p, buf); + p = append_str (p, op_str_81[(n & 3) + 4 * disassembler_mode]); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 9: + switch (disassembler_mode) + { + case HP_MNEMONICS: + sprintf (buf, "%sSRB.F", + op_str_81[(n & 3) + 4 * disassembler_mode]); + p = append_str (out, buf); + p = append_tab (out); + p = append_field (p, read_nibble ((*addr)++)); + break; + case CLASS_MNEMONICS: + p = append_str (out, "lsr"); + p = append_field (p, read_nibble ((*addr)++)); + p = append_tab (out); + p = append_str (p, "#1, "); + p = append_str (p, op_str_81[(n & 3) + 4 * disassembler_mode]); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 0xa: + fn = read_nibble ((*addr)++); + n = read_nibble ((*addr)++); + if (n > 2) + break; + c = (char) read_nibble ((*addr)++); + if (((int) c & 7) > 4) + break; + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (n == 2) + { + sprintf (buf, "%cR%dEX.F", ((int) c < 8) ? 'A' : 'C', + (int) c & 7); + } + else if (n == 1) + { + sprintf (buf, "%c=R%d.F", ((int) c < 8) ? 'A' : 'C', + (int) c & 7); + } + else + { + sprintf (buf, "R%d=%c.F", (int) c & 7, + ((int) c < 8) ? 'A' : 'C'); + } + p = append_str (out, buf); + p = append_tab (out); + p = append_field (p, fn); + break; + case CLASS_MNEMONICS: + p = append_str (out, (n == 2) ? "exg" : "move"); + p = append_field (p, fn); + p = append_tab (out); + if (n == 1) + { + sprintf (buf, "r%d", (int) c & 7); + p = append_str (p, buf); + } + else + p = append_str (p, ((int) c < 8) ? "a" : "c"); + p = append_str (p, ", "); + if (n == 1) + p = append_str (p, ((int) c < 8) ? "a" : "c"); + else + { + sprintf (buf, "r%d", (int) c & 7); + p = append_str (p, buf); + } + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 0xb: + n = read_nibble ((*addr)++); + if ((n < 2) || (n > 7)) + break; + + p = append_str (out, in_str_81b[n + 16 * disassembler_mode]); + break; + + case 0xc: + case 0xd: + case 0xe: + case 0xf: + switch (disassembler_mode) + { + case HP_MNEMONICS: + sprintf (buf, "%sSRB", op_str_81[(n & 3) + 4 * disassembler_mode]); + p = append_str (out, buf); + break; + case CLASS_MNEMONICS: + p = append_str (out, "lsr.w"); + p = append_tab (out); + p = append_str (p, "#1, "); + p = append_str (p, op_str_81[(n & 3) + 4 * disassembler_mode]); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + default: + break; + } + break; + + case 2: + n = read_nibble ((*addr)++); + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (n == 0xf) + { + p = append_str (out, "CLRHST"); + } + else + { + p = append_hst_bits (out, n); + p = append_str (p, "=0"); + } + break; + case CLASS_MNEMONICS: + p = append_str (out, "clr.1"); + p = append_tab (out); + sprintf (buf, "#%d, hst", n); + p = append_str (p, buf); + p = append_hst_bits (out, n); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 3: + n = read_nibble ((*addr)++); + pc = *addr; + disp = read_int (addr, 2); + switch (disassembler_mode) + { + case HP_MNEMONICS: + p = append_str (out, "?"); + p = append_hst_bits (p, n); + p = append_str (p, "=0"); + p = append_tab (out); + if (disp != 0) + { + p = append_str (p, "GOYES "); + p = append_r_addr (p, &pc, disp, 2, 3); + p = append_pc_comment (out, pc); + } + else + p = append_str (p, "RTNYES"); + break; + case CLASS_MNEMONICS: + p = append_str (out, (disp == 0) ? "rt" : "b"); + p = append_str (p, "eq.1"); + p = append_tab (out); + sprintf (buf, "#%d, hst", n); + p = append_str (p, buf); + if (disp != 0) + { + p = append_str (p, ", "); + p = append_r_addr (p, &pc, disp, 2, 3); + p = append_pc_comment (out, pc); + } + p = append_hst_bits (out, n); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 4: + case 5: + switch (disassembler_mode) + { + case HP_MNEMONICS: + sprintf (buf, "ST=%d", (fn == 4) ? 0 : 1); + p = append_str (out, buf); + p = append_tab (out); + p = append_imm_nibble (p, addr, 1); + break; + case CLASS_MNEMONICS: + p = append_str (out, (fn == 4) ? "bclr" : "bset"); + p = append_tab (out); + p = append_imm_nibble (p, addr, 1); + p = append_str (p, ", st"); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 6: + case 7: + n = read_nibble ((*addr)++); + pc = *addr; + disp = read_int (addr, 2); + switch (disassembler_mode) + { + case HP_MNEMONICS: + sprintf (buf, "?ST=%d", (fn == 6) ? 0 : 1); + p = append_str (out, buf); + p = append_tab (out); + sprintf (buf, "%d", n); + p = append_str (p, buf); + if (disp != 0) + { + p = append_str (p, ", GOYES "); + p = append_r_addr (p, &pc, disp, 2, 3); + p = append_pc_comment (out, pc); + } + else + p = append_str (p, ", RTNYES"); + break; + case CLASS_MNEMONICS: + p = append_str (out, (disp == 0) ? "rt" : "b"); + p = append_str (p, (fn == 6) ? "bc" : "bs"); + p = append_tab (out); + sprintf (buf, "#%d, st", n); + p = append_str (p, buf); + if (disp != 0) + { + p = append_str (p, ", "); + p = append_r_addr (p, &pc, disp, 2, 3); + p = append_pc_comment (out, pc); + } + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 8: + case 9: + n = read_nibble ((*addr)++); + pc = *addr; + disp = read_int (addr, 2); + switch (disassembler_mode) + { + case HP_MNEMONICS: + sprintf (buf, "?P%c", (fn == 8) ? '#' : '='); + p = append_str (out, buf); + p = append_tab (out); + sprintf (buf, "%d", n); + p = append_str (p, buf); + if (disp != 0) + { + p = append_str (p, ", GOYES "); + p = append_r_addr (p, &pc, disp, 2, 3); + p = append_pc_comment (out, pc); + } + else + p = append_str (p, ", RTNYES"); + break; + case CLASS_MNEMONICS: + p = append_str (out, (disp == 0) ? "rt" : "b"); + p = append_str (p, (fn == 8) ? "ne.1" : "eq.1"); + p = append_tab (out); + sprintf (buf, "#%d, p", n); + p = append_str (p, buf); + if (disp != 0) + { + p = append_str (p, ", "); + p = append_r_addr (p, &pc, disp, 2, 3); + p = append_pc_comment (out, pc); + } + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 0xc: + case 0xe: + pc = *addr; + if (fn == 0xe) + pc += 4; + disp = read_int (addr, 4); + switch (disassembler_mode) + { + case HP_MNEMONICS: + p = append_str (out, (fn == 0xc) ? "GOLONG" : "GOSUBL"); + p = append_tab (out); + p = append_r_addr (p, &pc, disp, 4, (fn == 0xc) ? 2 : 6); + p = append_pc_comment (out, pc); + break; + case CLASS_MNEMONICS: + p = append_str (out, (fn == 0xc) ? "bra.4" : "bsr.4"); + p = append_tab (out); + p = append_r_addr (p, &pc, disp, 4, (fn == 0xc) ? 2 : 6); + p = append_pc_comment (out, pc); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 0xd: + case 0xf: + pc = read_int (addr, 5); + switch (disassembler_mode) + { + case HP_MNEMONICS: + p = append_str (out, (fn == 0xc) ? "GOVLNG" : "GOSBVL"); + p = append_tab (out); + p = append_addr (p, pc); + break; + case CLASS_MNEMONICS: + p = append_str (out, (fn == 0xc) ? "jmp" : "jsr"); + p = append_tab (out); + p = append_addr (p, pc); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + default: + break; + + } + return p; +} + + +word_20 +#ifdef __FunctionProto__ +disassemble (word_20 addr, char *out) +#else +disassemble (addr, out) + word_20 addr; + char *out; +#endif +{ + word_4 n; + word_4 fn; + char *p = out; + char c; + char buf[20]; + word_20 disp, pc; + + switch (n = read_nibble (addr++)) + { + case 0: + if ((n = read_nibble (addr++)) != 0xe) + { + p = append_str (out, opcode_0_tbl[n + 16 * disassembler_mode]); + break; + } + fn = read_nibble (addr++); + n = read_nibble (addr++); + switch (disassembler_mode) + { + case HP_MNEMONICS: + sprintf (buf, op_str_0[(n & 7) + 8 * HP_MNEMONICS], + (n < 8) ? '&' : '!'); + p = append_str (out, buf); + p = append_tab (out); + p = append_field (p, fn); + break; + case CLASS_MNEMONICS: + p = append_str (out, (n < 8) ? "and" : "or"); + p = append_field (p, fn); + p = append_tab (out); + p = append_str (p, op_str_0[(n & 7) + 8 * CLASS_MNEMONICS]); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 1: + p = disasm_1 (&addr, out); + break; + + case 2: + n = read_nibble (addr++); + switch (disassembler_mode) + { + case HP_MNEMONICS: + sprintf (buf, "P=%d", n); + p = append_str (out, buf); + break; + case CLASS_MNEMONICS: + sprintf (buf, "move.1 #%d, p", n); + p = append_str (out, buf); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 3: + fn = read_nibble (addr++); + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (fn < 5) + { + sprintf (buf, "LC(%d)", fn + 1); + } + else + { + sprintf (buf, "LCHEX"); + } + p = append_str (out, buf); + p = append_tab (out); + p = append_imm_nibble (p, &addr, fn + 1); + break; + case CLASS_MNEMONICS: + sprintf (buf, "move.%d", fn + 1); + p = append_str (out, buf); + p = append_tab (out); + p = append_imm_nibble (p, &addr, fn + 1); + sprintf (buf, ", c.p"); + p = append_str (p, buf); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 4: + case 5: + pc = addr; + disp = read_int (&addr, 2); + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (disp == 2) + { + p = append_str (out, "NOP3"); + break; + } + sprintf (buf, (disp == 0) ? "RTN%sC" : "GO%sC", (n == 4) ? "" : "N"); + p = append_str (out, buf); + if (disp != 0) + { + p = append_tab (out); + p = append_r_addr (p, &pc, disp, 2, 1); + p = append_pc_comment (out, pc); + } + break; + + case CLASS_MNEMONICS: + if (disp == 2) + { + p = append_str (out, "nop3"); + break; + } + p = append_str (out, (disp == 0) ? "rtc" : "bc"); + p = append_str (p, (n == 4) ? "s" : "c"); + if (disp != 0) + { + p = append_tab (out); + p = append_r_addr (p, &pc, disp, 2, 1); + p = append_pc_comment (out, pc); + } + break; + + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 6: + pc = addr; + disp = read_int (&addr, 3); + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (disp == 3) + { + p = append_str (out, "NOP4"); + break; + } + if (disp == 4) + { + p = append_str (out, "NOP5"); + break; + } + p = append_str (out, "GOTO"); + p = append_tab (out); + p = append_r_addr (p, &pc, disp, 3, 1); + p = append_pc_comment (out, pc); + break; + + case CLASS_MNEMONICS: + if (disp == 3) + { + p = append_str (out, "nop4"); + break; + } + if (disp == 4) + { + p = append_str (out, "nop5"); + break; + } + p = append_str (out, "bra.3"); + p = append_tab (out); + p = append_r_addr (p, &pc, disp, 3, 1); + p = append_pc_comment (out, pc); + break; + + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 7: + pc = addr + 3; + disp = read_int (&addr, 3); + switch (disassembler_mode) + { + case HP_MNEMONICS: + p = append_str (out, "GOSUB"); + p = append_tab (out); + p = append_r_addr (p, &pc, disp, 3, 4); + p = append_pc_comment (out, pc); + break; + + case CLASS_MNEMONICS: + p = append_str (out, "bsr.3"); + p = append_tab (out); + p = append_r_addr (p, &pc, disp, 3, 4); + p = append_pc_comment (out, pc); + break; + + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 8: + fn = read_nibble (addr); /* PEEK */ + if (fn != 0xa && fn != 0xb) + { + p = disasm_8 (&addr, out); + break; + } + /* Fall through */ + + case 9: + fn = read_nibble (addr++); + if (n == 8) + { + c = (char) ((fn == 0xa) ? 0 : 1); + fn = 0xf; + } + else + { + c = (char) ((fn < 8) ? 0 : 1); + fn &= 7; + } + + n = read_nibble (addr++); + pc = addr; + disp = read_int (&addr, 2); + + switch (disassembler_mode) + { + case HP_MNEMONICS: + if ((c == 0) && (n >= 8)) + sprintf (buf, op_str_9[(n & 3) + 8 * HP_MNEMONICS + 4], + in_str_9[((n >> 2) & 3) + 4 * c + 8 * HP_MNEMONICS]); + else + sprintf (buf, op_str_9[(n & 3) + 8 * HP_MNEMONICS], + in_str_9[((n >> 2) & 3) + 4 * c + 8 * HP_MNEMONICS]); + p = append_str (out, buf); + p = append_tab (out); + p = append_field (p, fn); + p = append_str (p, ", "); + p = append_str (p, (disp == 0) ? "RTNYES" : "GOYES "); + if (disp != 0) + { + p = append_r_addr (p, &pc, disp, 2, 3); + p = append_pc_comment (out, pc); + } + break; + + case CLASS_MNEMONICS: + p = append_str (out, (disp == 0) ? "rt" : "b"); + p = append_str (p, in_str_9[((n >> 2) & 3) + 4 * c + 8 * CLASS_MNEMONICS]); + p = append_field (p, fn); + p = append_tab (out); + if ((c == 0) && (n >= 8)) + p = append_str (p, op_str_9[(n & 3) + 8 * CLASS_MNEMONICS + 4]); + else + p = append_str (p, op_str_9[(n & 3) + 8 * CLASS_MNEMONICS]); + if (disp != 0) + { + p = append_str (p, ", "); + p = append_r_addr (p, &pc, disp, 2, 3); + p = append_pc_comment (out, pc); + } + break; + + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + default: + switch (n) + { + case 0xa: + fn = read_nibble (addr++); + c = (char) ((fn < 8) ? 0 : 1); + fn &= 7; + disp = 0xa; + break; + case 0xb: + fn = read_nibble (addr++); + c = (char) ((fn < 8) ? 0 : 1); + fn &= 7; + disp = 0xb; + break; + case 0xc: + case 0xd: + fn = 0xf; + c = (char) (n & 1); + disp = 0xa; + break; + case 0xe: + case 0xf: + fn = 0xf; + c = (char) (n & 1); + disp = 0xb; + break; + default: + fn = 0; + disp = 0; + c = 0; + break; + } + + n = read_nibble (addr++); + pc = 0; + + switch (disp) + { + case 0xa: + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (c == 0) + { + if (n < 0xc) + { + p = "+"; + } + else + { + p = "%c=%c-1"; + pc = 2; + } + } + else + { + if (n < 4) + { + p = "%c=0"; + pc = 1; + } + else if (n >= 0xc) + { + p = "%c%cEX"; + pc = 3; + } + else + { + p = "%c=%c"; + pc = 3; + } + } + break; + + case CLASS_MNEMONICS: + if (c == 0) + { + if (n < 0xc) + { + p = "add"; + } + else + { + p = "dec"; + pc = 1; + } + } + else + { + if (n < 4) + { + p = "clr"; + pc = 1; + } + else if (n >= 0xc) + { + p = "exg"; + } + else + { + p = "move"; + if (n < 8) + n -= 4; + } + } + break; + + default: + p = append_str (out, "Unknown disassembler mode"); + return addr; + } + break; + + case 0xb: + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (c == 0) + { + if (n >= 0xc) + { + p = "-"; + } + else if ((n >= 4) && (n <= 7)) + { + p = "%c=%c+1"; + pc = 2; + n -= 4; + } + else + { + p = "-"; + } + } + else + { + if (n < 4) + { + p = "%cSL"; + pc = 1; + } + else if (n < 8) + { + p = "%cSR"; + pc = 1; + } + else if (n < 0xc) + { + p = "%c=%c-1"; + pc = 2; + } + else + { + p = "%c=-%c-1"; + pc = 2; + } + } + break; + + case CLASS_MNEMONICS: + if (c == 0) + { + if (n >= 0xc) + { + p = "subr"; + } + else if ((n >= 4) && (n <= 7)) + { + p = "inc"; + pc = 1; + n -= 4; + } + else + { + p = "sub"; + } + } + else + { + pc = 1; + if (n < 4) + { + p = "lsl"; + } + else if (n < 8) + { + p = "lsr"; + } + else if (n < 0xc) + { + p = "neg"; + } + else + { + p = "not"; + } + } + break; + + default: + p = append_str (out, "Unknown disassembler mode"); + return addr; + } + break; + + } + + switch (disassembler_mode) + { + case HP_MNEMONICS: + + if (pc == 0) + { + sprintf (buf, op_str_af[n + 16 * HP_MNEMONICS], p); + } + else if (pc == 1) + { + sprintf (buf, p, (n & 3) + 'A'); + } + else if (pc == 2) + { + sprintf (buf, p, (n & 3) + 'A', (n & 3) + 'A'); + } + else + { + sprintf (buf, p, hp_reg_1_af[n], hp_reg_2_af[n]); + } + p = append_str (out, buf); + p = append_tab (out); + p = append_field (p, fn); + break; + + case CLASS_MNEMONICS: + + p = append_str (out, p); + p = append_field (p, fn); + p = append_tab (out); + if (pc == 1) + { + sprintf (buf, "%c", (n & 3) + 'a'); + p = append_str (p, buf); + } + else + { + p = append_str (p, op_str_af[n + 16 * CLASS_MNEMONICS]); + } + break; + + default: + p = append_str (p, "Unknown disassembler mode"); + break; + } + + break; + } + *p = '\0'; + return addr; +} diff --git a/src/disasm.h b/src/disasm.h new file mode 100644 index 0000000..bd0ed4d --- /dev/null +++ b/src/disasm.h @@ -0,0 +1,51 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: disasm.h,v $ + * Revision 1.3 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.2 1994/11/02 14:51:27 ecd + * changed ALONZO to CLASS + * + * Revision 1.2 1994/11/02 14:51:27 ecd + * changed ALONZO to CLASS + * + * Revision 1.1 1994/10/09 20:26:35 ecd + * Initial revision + * + * + * $Id: disasm.h,v 1.3 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#ifndef _DISASM_H +#define _DISASM_H 1 + +#include "global.h" +#include "hp48.h" + +#define HP_MNEMONICS 0 +#define CLASS_MNEMONICS 1 + +extern int disassembler_mode; +extern char *mode_name[]; + +extern word_20 disassemble __ProtoType__((word_20 addr, char *out)); + +#endif /* !_DISASM_H */ diff --git a/src/dump2rom.c b/src/dump2rom.c new file mode 100644 index 0000000..0e6ed01 --- /dev/null +++ b/src/dump2rom.c @@ -0,0 +1,226 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: dump2rom.c,v $ + * Revision 1.7 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.6 1994/12/07 20:20:50 ecd + * minor changes + * + * Revision 1.6 1994/12/07 20:20:50 ecd + * minor changes + * + * Revision 1.5 1994/11/28 02:00:51 ecd + * improved trapping of EOF + * + * Revision 1.4 1994/11/02 14:40:38 ecd + * support for "compressed" rom files added + * + * Revision 1.3 1994/09/18 15:29:22 ecd + * turned off unused rcsid message + * + * Revision 1.2 1994/09/13 16:57:00 ecd + * changed to plain X11 + * + * Revision 1.1 1994/09/07 12:57:36 ecd + * Initial revision + * + * $Id: dump2rom.c,v 1.7 1995/01/11 18:20:01 ecd Exp ecd $ + */ + + +#include "global.h" + +#include +#include +#include +#include +#ifdef SUNOS +#include +#endif +#include + +unsigned char *core; + +#define DEFAULT_ROM_FILE "rom.dump" + +int +#ifdef __FunctionProto__ +write_mem_file(char *name, unsigned char *mem, int size) +#else +write_mem_file(name, mem, size) +char *name; +unsigned char *mem; +int size; +#endif +{ + FILE *fp; + unsigned char *tmp_mem; + unsigned char byte; + int i, j; + + if (NULL == (fp = fopen(name, "w"))) + { + fprintf(stderr, "can\'t open %s\n", name); + return 0; + } + + if (NULL == (tmp_mem = (unsigned char *)malloc((size_t)size / 2))) + { + for (i = 0, j = 0; i < size / 2; i++) + { + byte = (mem[j++] & 0x0f); + byte |= (mem[j++] << 4) & 0xf0; + if (1 != fwrite(&byte, 1, 1, fp)) + { + fprintf(stderr, "can\'t write %s\n", name); + fclose(fp); + return 0; + } + } + } + else + { + for (i = 0, j = 0; i < size / 2; i++) + { + tmp_mem[i] = (mem[j++] & 0x0f); + tmp_mem[i] |= (mem[j++] << 4) & 0xf0; + } + + if (fwrite(tmp_mem, 1, (size_t)size / 2, fp) != size / 2) + { + fprintf(stderr, "can\'t write %s\n", name); + fclose(fp); + free(tmp_mem); + return 0; + } + + free(tmp_mem); + } + + fclose(fp); + return 1; +} + +int +#ifdef __FunctionProto__ +main(int argc, char **argv) +#else +main(argc, argv) +int argc; +char **argv; +#endif +{ + FILE *dump; + long addr, size; + int ch, i, gx, error; + + if (argc < 2) { + fprintf(stderr, "usage: %s hp48-dump-file\n", argv[0]); + exit (1); + } + + if ((dump = fopen(argv[1], "r")) == NULL) { + fprintf(stderr, "%s: can\'t open %s\n", argv[0], argv[1]); + exit (1); + } + + if ((core = (unsigned char *)malloc(0x100000)) == NULL) { + fprintf(stderr, "%s: can\'t malloc %d bytes\n", argv[0], 0x100000); + exit (1); + } + memset(core, 0, 0x100000); + + gx = 0; + error = 0; + while (1) { + addr = 0; + for (i = 0; i < 5; i++) { + addr <<= 4; + if ((ch = fgetc(dump)) < 0) { + error = 1; + break; + } + if (ch >= '0' && ch <= '9') { + addr |= ch - '0'; + } else if (ch >= 'A' && ch <= 'F') { + addr |= ch - 'A' + 10; + } else { + fprintf(stderr, "%s: Illegal char %c at %lx\n", argv[0], ch, addr); + error = 1; + break; + } + } + if (error) + break; + if (addr >= 0x80000) + gx = 1; + if ((ch = fgetc(dump)) < 0) { + fprintf(stderr, "%s: Unexpected EOF at %lx\n", argv[0], addr); + break; + } + if (ch != ':') { + fprintf(stderr, "%s: Illegal char %c, expected \':\' at %lx\n", + argv[0], ch, addr); + break; + } + for (i = 0; i < 16; i++) { + if ((ch = fgetc(dump)) < 0) { + fprintf(stderr, "%s: Unexpected EOF at %lx\n", argv[0], addr); + error = 1; + break; + } + if (ch >= '0' && ch <= '9') { + core[addr++] = ch - '0'; + } else if (ch >= 'A' && ch <= 'F') { + core[addr++] = ch - 'A' + 10; + } else { + fprintf(stderr, "%s: Illegal char %c at %lx\n", argv[0], ch, addr); + error = 1; + break; + } + } + if (error) + break; + if ((ch = fgetc(dump)) < 0) + break; + if (ch != '\n') { + fprintf(stderr, "%s: Illegal char %c, expected \'\\n\' at %lx\n", + argv[0], ch, addr); + break; + } + } + + if (!gx) + if (core[0x29] == 0x0) + gx = 1; + if (gx) + size = 0x100000; + else + size = 0x80000; + if (!write_mem_file(DEFAULT_ROM_FILE, core, size)) + { + fprintf(stderr, "%s: can\'t write to %s\n", argv[0], DEFAULT_ROM_FILE); + exit (1); + } + + exit (0); +} + diff --git a/src/emulate.c b/src/emulate.c new file mode 100644 index 0000000..f72f5d5 --- /dev/null +++ b/src/emulate.c @@ -0,0 +1,2491 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * $Log: emulate.c,v $ + * Revision 1.16 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.15 1994/12/07 20:20:50 ecd + * fiddled around with sound + * + * Revision 1.15 1994/12/07 20:20:50 ecd + * fiddled around with sound + * + * Revision 1.14 1994/11/28 02:00:51 ecd + * added TRAP instruction 64001 + * played with output register ... + * removed some unused switch statements + * + * Revision 1.13 1994/11/04 03:42:34 ecd + * changed includes + * + * Revision 1.12 1994/11/02 19:13:04 ecd + * fixed missing log + * + * + * $Id: emulate.c,v 1.16 1995/01/11 18:20:01 ecd Exp ecd $ + */ + + +#include "global.h" + +#include + +#include "hp48.h" +#include "hp48_emu.h" +#include "device.h" +#include "timer.h" +#include "x48_x11.h" +#include "debugger.h" + +extern int throttle; + +#if 0 +#define DEBUG_TIMER +#define DEBUG_SCHED 1 +#define DEBUG_DISP_SCHED +#endif + +static long jumpaddr; + +unsigned long instructions = 0; +unsigned long old_instr = 0; + +int rece_instr = 0; +int device_check = 0; + +int adj_time_pending = 0; + +int set_t1; + +long schedule_event = 0; + +#define SrvcIoStart 0x3c0 +#define SrvcIoEnd 0x5ec + +#define SCHED_INSTR_ROLLOVER 0x3fffffff +#define SCHED_RECEIVE 0x7ff +#define SCHED_ADJTIME 0x1ffe +#define SCHED_TIMER1 0x1e00 +#define SCHED_TIMER2 0xf +#define SCHED_STATISTICS 0x7ffff +#define SCHED_NEVER 0x7fffffff + +#define NR_SAMPLES 10 + +long sched_instr_rollover = SCHED_INSTR_ROLLOVER; +long sched_receive = SCHED_RECEIVE; +long sched_adjtime = SCHED_ADJTIME; +long sched_timer1 = SCHED_TIMER1; +long sched_timer2 = SCHED_TIMER2; +long sched_statistics = SCHED_STATISTICS; +long sched_display = SCHED_NEVER; + +unsigned long t1_i_per_tick; +unsigned long t2_i_per_tick; +unsigned long s_1; +unsigned long s_16; +unsigned long old_s_1; +unsigned long old_s_16; +unsigned long delta_t_1; +unsigned long delta_t_16; +unsigned long delta_i; +word_64 run; + +static word_20 jumpmasks[] = { + 0xffffffff, 0xfffffff0, 0xffffff00, 0xfffff000, + 0xffff0000, 0xfff00000, 0xff000000, 0xf0000000 +}; + +int +#ifdef __FunctionProto__ +decode_group_80(void) +#else +decode_group_80() +#endif +{ + int t, op3, op4, op5, op6; + unsigned char *REG; + long addr; + op3 = read_nibble(saturn.PC + 2); + switch (op3) { + case 0: /* OUT=CS */ + saturn.PC += 3; + copy_register(saturn.OUT, saturn.C, OUTS_FIELD); +#if 0 + check_out_register(); +#endif + return 0; + case 1: /* OUT=C */ + saturn.PC += 3; + copy_register(saturn.OUT, saturn.C, OUT_FIELD); +#if 0 + check_out_register(); +#endif + return 0; + case 2: /* A=IN */ + saturn.PC += 3; + do_in(); + copy_register(saturn.A, saturn.IN, IN_FIELD); + return 0; + case 3: /* C=IN */ + saturn.PC += 3; + do_in(); + copy_register(saturn.C, saturn.IN, IN_FIELD); + return 0; + case 4: /* UNCNFG */ + saturn.PC += 3; + do_unconfigure(); + return 0; + case 5: /* CONFIG */ + saturn.PC += 3; + do_configure(); + return 0; + case 6: /* C=ID */ + saturn.PC += 3; + return get_identification(); + case 7: /* SHUTDN */ + saturn.PC += 3; + do_shutdown(); + return 0; + case 8: + op4 = read_nibble(saturn.PC + 3); + switch (op4) { + case 0: /* INTON */ + saturn.PC += 4; + do_inton(); + return 0; + case 1: /* RSI... */ + op5 = read_nibble(saturn.PC + 4); + saturn.PC += 5; + do_reset_interrupt_system(); + return 0; + case 2: /* LA... */ + op5 = read_nibble(saturn.PC + 4); + load_constant(saturn.A, op5 + 1, saturn.PC + 5); + saturn.PC += 6 + op5; + return 0; + case 3: /* BUSCB */ + saturn.PC += 4; + return 0; + case 4: /* ABIT=0 */ + op5 = read_nibble(saturn.PC + 4); + saturn.PC += 5; + clear_register_bit(saturn.A, op5); + return 0; + case 5: /* ABIT=1 */ + op5 = read_nibble(saturn.PC + 4); + saturn.PC += 5; + set_register_bit(saturn.A, op5); + return 0; + case 8: /* CBIT=0 */ + op5 = read_nibble(saturn.PC + 4); + saturn.PC += 5; + clear_register_bit(saturn.C, op5); + return 0; + case 9: /* CBIT=1 */ + op5 = read_nibble(saturn.PC + 4); + saturn.PC += 5; + set_register_bit(saturn.C, op5); + return 0; + case 6: /* ?ABIT=0 */ + case 7: /* ?ABIT=1 */ + case 0xa: /* ?CBIT=0 */ + case 0xb: /* ?CBIT=1 */ + op5 = read_nibble(saturn.PC + 4); + if (op4 < 8) + REG = saturn.A; + else + REG = saturn.C; + if (op4 == 6 || op4 == 0xa) + t = 0; + else + t = 1; + saturn.CARRY = (get_register_bit(REG, op5) == t)?1:0; + if (saturn.CARRY) { + saturn.PC += 5; + op6 = read_nibbles(saturn.PC, 2); + if (op6) { + if (op6 & 0x80) + op6 |= jumpmasks[2]; + jumpaddr = (saturn.PC + op6) & 0xfffff; + saturn.PC = jumpaddr; + } else { + saturn.PC = pop_return_addr(); + } + } else { + saturn.PC += 7; + } + return 0; + case 0xc: /* PC=(A) */ + addr = dat_to_addr(saturn.A); + jumpaddr = read_nibbles(addr, 5); + saturn.PC = jumpaddr; + return 0; + case 0xd: /* BUSCD */ + saturn.PC += 4; + return 0; + case 0xe: /* PC=(C) */ + addr = dat_to_addr(saturn.C); + jumpaddr = read_nibbles(addr, 5); + saturn.PC = jumpaddr; + return 0; + case 0xf: /* INTOFF */ + saturn.PC += 4; + do_intoff(); + return 0; + default: + return 1; + } + case 9: /* C+P+1 */ + saturn.PC += 3; + add_p_plus_one(saturn.C); + return 0; + case 0xa: /* RESET */ + saturn.PC += 3; + do_reset(); + return 0; + case 0xb: /* BUSCC */ + saturn.PC += 3; + return 0; + case 0xc: /* C=P n */ + op4 = read_nibble(saturn.PC + 3); + saturn.PC += 4; + set_register_nibble(saturn.C, op4, saturn.P); + return 0; + case 0xd: /* P=C n */ + op4 = read_nibble(saturn.PC + 3); + saturn.PC += 4; + saturn.P = get_register_nibble(saturn.C, op4); + return 0; + case 0xe: /* SREQ? */ + saturn.PC += 3; + saturn.C[0] = 0; + saturn.SR = 0; + return 0; + case 0xf: /* CPEX n */ + op4 = read_nibble(saturn.PC + 3); + saturn.PC += 4; + t = get_register_nibble(saturn.C, op4); + set_register_nibble(saturn.C, op4, saturn.P); + saturn.P = t; + return 0; + default: + return 1; + } +} + +int +#ifdef __FunctionProto__ +decode_group_1(void) +#else +decode_group_1() +#endif +{ + int op, op2, op3, op4; + + op2 = read_nibble(saturn.PC + 1); + switch (op2) { + case 0: + op3 = read_nibble(saturn.PC + 2); + switch (op3) { + case 0: /* saturn.R0=A */ + saturn.PC += 3; + copy_register(saturn.R0, saturn.A, W_FIELD); + return 0; + case 1: /* saturn.R1=A */ + case 5: + saturn.PC += 3; + copy_register(saturn.R1, saturn.A, W_FIELD); + return 0; + case 2: /* saturn.R2=A */ + case 6: + saturn.PC += 3; + copy_register(saturn.R2, saturn.A, W_FIELD); + return 0; + case 3: /* saturn.R3=A */ + case 7: + saturn.PC += 3; + copy_register(saturn.R3, saturn.A, W_FIELD); + return 0; + case 4: /* saturn.R4=A */ + saturn.PC += 3; + copy_register(saturn.R4, saturn.A, W_FIELD); + return 0; + case 8: /* saturn.R0=C */ + saturn.PC += 3; + copy_register(saturn.R0, saturn.C, W_FIELD); + return 0; + case 9: /* saturn.R1=C */ + case 0xd: + saturn.PC += 3; + copy_register(saturn.R1, saturn.C, W_FIELD); + return 0; + case 0xa: /* saturn.R2=C */ + case 0xe: + saturn.PC += 3; + copy_register(saturn.R2, saturn.C, W_FIELD); + return 0; + case 0xb: /* saturn.R3=C */ + case 0xf: + saturn.PC += 3; + copy_register(saturn.R3, saturn.C, W_FIELD); + return 0; + case 0xc: /* saturn.R4=C */ + saturn.PC += 3; + copy_register(saturn.R4, saturn.C, W_FIELD); + return 0; + default: + return 1; + } + case 1: + op3 = read_nibble(saturn.PC + 2); + switch (op3) { + case 0: /* A=R0 */ + saturn.PC += 3; + copy_register(saturn.A, saturn.R0, W_FIELD); + return 0; + case 1: /* A=R1 */ + case 5: + saturn.PC += 3; + copy_register(saturn.A, saturn.R1, W_FIELD); + return 0; + case 2: /* A=R2 */ + case 6: + saturn.PC += 3; + copy_register(saturn.A, saturn.R2, W_FIELD); + return 0; + case 3: /* A=R3 */ + case 7: + saturn.PC += 3; + copy_register(saturn.A, saturn.R3, W_FIELD); + return 0; + case 4: /* A=R4 */ + saturn.PC += 3; + copy_register(saturn.A, saturn.R4, W_FIELD); + return 0; + case 8: /* C=R0 */ + saturn.PC += 3; + copy_register(saturn.C, saturn.R0, W_FIELD); + return 0; + case 9: /* C=R1 */ + case 0xd: + saturn.PC += 3; + copy_register(saturn.C, saturn.R1, W_FIELD); + return 0; + case 0xa: /* C=R2 */ + case 0xe: + saturn.PC += 3; + copy_register(saturn.C, saturn.R2, W_FIELD); + return 0; + case 0xb: /* C=R3 */ + case 0xf: + saturn.PC += 3; + copy_register(saturn.C, saturn.R3, W_FIELD); + return 0; + case 0xc: /* C=R4 */ + saturn.PC += 3; + copy_register(saturn.C, saturn.R4, W_FIELD); + return 0; + default: + return 1; + } + case 2: + op3 = read_nibble(saturn.PC + 2); + switch (op3) { + case 0: /* AR0EX */ + saturn.PC += 3; + exchange_register(saturn.A, saturn.R0, W_FIELD); + return 0; + case 1: /* AR1EX */ + case 5: + saturn.PC += 3; + exchange_register(saturn.A, saturn.R1, W_FIELD); + return 0; + case 2: /* AR2EX */ + case 6: + saturn.PC += 3; + exchange_register(saturn.A, saturn.R2, W_FIELD); + return 0; + case 3: /* AR3EX */ + case 7: + saturn.PC += 3; + exchange_register(saturn.A, saturn.R3, W_FIELD); + return 0; + case 4: /* AR4EX */ + saturn.PC += 3; + exchange_register(saturn.A, saturn.R4, W_FIELD); + return 0; + case 8: /* CR0EX */ + saturn.PC += 3; + exchange_register(saturn.C, saturn.R0, W_FIELD); + return 0; + case 9: /* CR1EX */ + case 0xd: + saturn.PC += 3; + exchange_register(saturn.C, saturn.R1, W_FIELD); + return 0; + case 0xa: /* CR2EX */ + case 0xe: + saturn.PC += 3; + exchange_register(saturn.C, saturn.R2, W_FIELD); + return 0; + case 0xb: /* CR3EX */ + case 0xf: + saturn.PC += 3; + exchange_register(saturn.C, saturn.R3, W_FIELD); + return 0; + case 0xc: /* CR4EX */ + saturn.PC += 3; + exchange_register(saturn.C, saturn.R4, W_FIELD); + return 0; + default: + return 1; + } + case 3: + op3 = read_nibble(saturn.PC + 2); + switch (op3) { + case 0: /* D0=A */ + saturn.PC += 3; + register_to_address(saturn.A, &saturn.D0, 0); + return 0; + case 1: /* D1=A */ + saturn.PC += 3; + register_to_address(saturn.A, &saturn.D1, 0); + return 0; + case 2: /* AD0EX */ + saturn.PC += 3; + exchange_reg(saturn.A, &saturn.D0, A_FIELD); + return 0; + case 3: /* AD1EX */ + saturn.PC += 3; + exchange_reg(saturn.A, &saturn.D1, A_FIELD); + return 0; + case 4: /* D0=C */ + saturn.PC += 3; + register_to_address(saturn.C, &saturn.D0, 0); + return 0; + case 5: /* D1=C */ + saturn.PC += 3; + register_to_address(saturn.C, &saturn.D1, 0); + return 0; + case 6: /* CD0EX */ + saturn.PC += 3; + exchange_reg(saturn.C, &saturn.D0, A_FIELD); + return 0; + case 7: /* CD1EX */ + saturn.PC += 3; + exchange_reg(saturn.C, &saturn.D1, A_FIELD); + return 0; + case 8: /* D0=AS */ + saturn.PC += 3; + register_to_address(saturn.A, &saturn.D0, 1); + return 0; + case 9: /* saturn.D1=AS */ + saturn.PC += 3; + register_to_address(saturn.A, &saturn.D1, 1); + return 0; + case 0xa: /* AD0XS */ + saturn.PC += 3; + exchange_reg(saturn.A, &saturn.D0, IN_FIELD); + return 0; + case 0xb: /* AD1XS */ + saturn.PC += 3; + exchange_reg(saturn.A, &saturn.D1, IN_FIELD); + return 0; + case 0xc: /* D0=CS */ + saturn.PC += 3; + register_to_address(saturn.C, &saturn.D0, 1); + return 0; + case 0xd: /* D1=CS */ + saturn.PC += 3; + register_to_address(saturn.C, &saturn.D1, 1); + return 0; + case 0xe: /* CD0XS */ + saturn.PC += 3; + exchange_reg(saturn.C, &saturn.D0, IN_FIELD); + return 0; + case 0xf: /* CD1XS */ + saturn.PC += 3; + exchange_reg(saturn.C, &saturn.D1, IN_FIELD); + return 0; + default: + return 1; + } + case 4: + op3 = read_nibble(saturn.PC + 2); + op = op3 < 8 ? 0xf : 6; + switch(op3 & 7) { + case 0: /* DAT0=A */ + saturn.PC += 3; + store(saturn.D0, saturn.A, op); + return 0; + case 1: /* DAT1=A */ + saturn.PC += 3; + store(saturn.D1, saturn.A, op); + return 0; + case 2: /* A=DAT0 */ + saturn.PC += 3; + recall(saturn.A, saturn.D0, op); + return 0; + case 3: /* A=DAT1 */ + saturn.PC += 3; + recall(saturn.A, saturn.D1, op); + return 0; + case 4: /* DAT0=C */ + saturn.PC += 3; + store(saturn.D0, saturn.C, op); + return 0; + case 5: /* DAT1=C */ + saturn.PC += 3; + store(saturn.D1, saturn.C, op); + return 0; + case 6: /* C=DAT0 */ + saturn.PC += 3; + recall(saturn.C, saturn.D0, op); + return 0; + case 7: /* C=DAT1 */ + saturn.PC += 3; + recall(saturn.C, saturn.D1, op); + return 0; + default: + return 1; + } + case 5: + op3 = read_nibble(saturn.PC + 2); + op4 = read_nibble(saturn.PC + 3); + if (op3 >= 8) { + switch(op3 & 7) { + case 0: /* DAT0=A */ + saturn.PC += 4; + store_n(saturn.D0, saturn.A, op4+1); + return 0; + case 1: /* DAT1=A */ + saturn.PC += 4; + store_n(saturn.D1, saturn.A, op4+1); + return 0; + case 2: /* A=DAT0 */ + saturn.PC += 4; + recall_n(saturn.A, saturn.D0, op4+1); + return 0; + case 3: /* A=DAT1 */ + saturn.PC += 4; + recall_n(saturn.A, saturn.D1, op4+1); + return 0; + case 4: /* DAT0=C */ + saturn.PC += 4; + store_n(saturn.D0, saturn.C, op4+1); + return 0; + case 5: /* DAT1=C */ + saturn.PC += 4; + store_n(saturn.D1, saturn.C, op4+1); + return 0; + case 6: /* C=DAT0 */ + saturn.PC += 4; + recall_n(saturn.C, saturn.D0, op4+1); + return 0; + case 7: /* C=DAT1 */ + saturn.PC += 4; + recall_n(saturn.C, saturn.D1, op4+1); + return 0; + default: + return 1; + } + } else { + switch(op3) { + case 0: /* DAT0=A */ + saturn.PC += 4; + store(saturn.D0, saturn.A, op4); + return 0; + case 1: /* DAT1=A */ + saturn.PC += 4; + store(saturn.D1, saturn.A, op4); + return 0; + case 2: /* A=DAT0 */ + saturn.PC += 4; + recall(saturn.A, saturn.D0, op4); + return 0; + case 3: /* A=DAT1 */ + saturn.PC += 4; + recall(saturn.A, saturn.D1, op4); + return 0; + case 4: /* DAT0=C */ + saturn.PC += 4; + store(saturn.D0, saturn.C, op4); + return 0; + case 5: /* DAT1=C */ + saturn.PC += 4; + store(saturn.D1, saturn.C, op4); + return 0; + case 6: /* C=DAT0 */ + saturn.PC += 4; + recall(saturn.C, saturn.D0, op4); + return 0; + case 7: /* C=DAT1 */ + saturn.PC += 4; + recall(saturn.C, saturn.D1, op4); + return 0; + default: + return 1; + } + } + case 6: + op3 = read_nibble(saturn.PC + 2); + saturn.PC += 3; + add_address(&saturn.D0, op3+1); + return 0; + case 7: + op3 = read_nibble(saturn.PC + 2); + saturn.PC += 3; + add_address(&saturn.D1, op3+1); + return 0; + case 8: + op3 = read_nibble(saturn.PC + 2); + saturn.PC += 3; + add_address(&saturn.D0, -(op3+1)); + return 0; + case 9: + load_addr(&saturn.D0, saturn.PC+2, 2); + saturn.PC += 4; + return 0; + case 0xa: + load_addr(&saturn.D0, saturn.PC+2, 4); + saturn.PC += 6; + return 0; + case 0xb: + load_addr(&saturn.D0, saturn.PC+2, 5); + saturn.PC += 7; + return 0; + case 0xc: + op3 = read_nibble(saturn.PC + 2); + saturn.PC += 3; + add_address(&saturn.D1, -(op3+1)); + return 0; + case 0xd: + load_addr(&saturn.D1, saturn.PC+2, 2); + saturn.PC += 4; + return 0; + case 0xe: + load_addr(&saturn.D1, saturn.PC+2, 4); + saturn.PC += 6; + return 0; + case 0xf: + load_addr(&saturn.D1, saturn.PC+2, 5); + saturn.PC += 7; + return 0; + default: + return 1; + } +} + +inline int +#ifdef __FunctionProto__ +decode_8_thru_f(int op1) +#else +decode_8_thru_f(op1) +int op1; +#endif +{ + int op2, op3, op4, op5, op6; + + op2 = read_nibble(saturn.PC + 1); + switch (op1) { + case 8: + switch (op2) { + case 0: + return decode_group_80(); + case 1: + op3 = read_nibble(saturn.PC + 2); + switch (op3) { + case 0: /* ASLC */ + saturn.PC += 3; + shift_left_circ_register(saturn.A, W_FIELD); + return 0; + case 1: /* BSLC */ + saturn.PC += 3; + shift_left_circ_register(saturn.B, W_FIELD); + return 0; + case 2: /* CSLC */ + saturn.PC += 3; + shift_left_circ_register(saturn.C, W_FIELD); + return 0; + case 3: /* DSLC */ + saturn.PC += 3; + shift_left_circ_register(saturn.D, W_FIELD); + return 0; + case 4: /* ASRC */ + saturn.PC += 3; + shift_right_circ_register(saturn.A, W_FIELD); + return 0; + case 5: /* BSRC */ + saturn.PC += 3; + shift_right_circ_register(saturn.B, W_FIELD); + return 0; + case 6: /* CSRC */ + saturn.PC += 3; + shift_right_circ_register(saturn.C, W_FIELD); + return 0; + case 7: /* DSRC */ + saturn.PC += 3; + shift_right_circ_register(saturn.D, W_FIELD); + return 0; + case 8: /* R = R +/- CON */ + op4 = read_nibble(saturn.PC + 3); + op5 = read_nibble(saturn.PC + 4); + op6 = read_nibble(saturn.PC + 5); + if (op5 < 8) { /* PLUS */ + switch (op5 & 3) { + case 0: /* A=A+CON */ + saturn.PC += 6; + add_register_constant(saturn.A, op4, op6+1); + return 0; + case 1: /* B=B+CON */ + saturn.PC += 6; + add_register_constant(saturn.B, op4, op6+1); + return 0; + case 2: /* C=C+CON */ + saturn.PC += 6; + add_register_constant(saturn.C, op4, op6+1); + return 0; + case 3: /* D=D+CON */ + saturn.PC += 6; + add_register_constant(saturn.D, op4, op6+1); + return 0; + default: + return 1; + } + } else { /* MINUS */ + switch (op5 & 3) { + case 0: /* A=A-CON */ + saturn.PC += 6; + sub_register_constant(saturn.A, op4, op6+1); + return 0; + case 1: /* B=B-CON */ + saturn.PC += 6; + sub_register_constant(saturn.B, op4, op6+1); + return 0; + case 2: /* C=C-CON */ + saturn.PC += 6; + sub_register_constant(saturn.C, op4, op6+1); + return 0; + case 3: /* D=D-CON */ + saturn.PC += 6; + sub_register_constant(saturn.D, op4, op6+1); + return 0; + default: + return 1; + } + } + case 9: /* R SRB FIELD */ + op4 = read_nibble(saturn.PC + 3); + op5 = read_nibble(saturn.PC + 4); + switch (op5 & 3) { + case 0: + saturn.PC += 5; + shift_right_bit_register(saturn.A, op4); + return 0; + case 1: + saturn.PC += 5; + shift_right_bit_register(saturn.B, op4); + return 0; + case 2: + saturn.PC += 5; + shift_right_bit_register(saturn.C, op4); + return 0; + case 3: + saturn.PC += 5; + shift_right_bit_register(saturn.D, op4); + return 0; + default: + return 1; + } + case 0xa: /* R = R FIELD, etc. */ + op4 = read_nibble(saturn.PC + 3); + op5 = read_nibble(saturn.PC + 4); + op6 = read_nibble(saturn.PC + 5); + switch (op5) { + case 0: + switch (op6) { + case 0: /* saturn.R0=A */ + saturn.PC += 6; + copy_register(saturn.R0, saturn.A, op4); + return 0; + case 1: /* saturn.R1=A */ + case 5: + saturn.PC += 6; + copy_register(saturn.R1, saturn.A, op4); + return 0; + case 2: /* saturn.R2=A */ + case 6: + saturn.PC += 6; + copy_register(saturn.R2, saturn.A, op4); + return 0; + case 3: /* saturn.R3=A */ + case 7: + saturn.PC += 6; + copy_register(saturn.R3, saturn.A, op4); + return 0; + case 4: /* saturn.R4=A */ + saturn.PC += 6; + copy_register(saturn.R4, saturn.A, op4); + return 0; + case 8: /* saturn.R0=C */ + saturn.PC += 6; + copy_register(saturn.R0, saturn.C, op4); + return 0; + case 9: /* saturn.R1=C */ + case 0xd: + saturn.PC += 6; + copy_register(saturn.R1, saturn.C, op4); + return 0; + case 0xa: /* saturn.R2=C */ + case 0xe: + saturn.PC += 6; + copy_register(saturn.R2, saturn.C, op4); + return 0; + case 0xb: /* saturn.R3=C */ + case 0xf: + saturn.PC += 6; + copy_register(saturn.R3, saturn.C, op4); + return 0; + case 0xc: /* saturn.R4=C */ + saturn.PC += 6; + copy_register(saturn.R4, saturn.C, op4); + return 0; + default: + return 1; + } + case 1: + switch (op6) { + case 0: /* A=R0 */ + saturn.PC += 6; + copy_register(saturn.A, saturn.R0, op4); + return 0; + case 1: /* A=R1 */ + case 5: + saturn.PC += 6; + copy_register(saturn.A, saturn.R1, op4); + return 0; + case 2: /* A=R2 */ + case 6: + saturn.PC += 6; + copy_register(saturn.A, saturn.R2, op4); + return 0; + case 3: /* A=R3 */ + case 7: + saturn.PC += 6; + copy_register(saturn.A, saturn.R3, op4); + return 0; + case 4: /* A=R4 */ + saturn.PC += 6; + copy_register(saturn.A, saturn.R4, op4); + return 0; + case 8: /* C=R0 */ + saturn.PC += 6; + copy_register(saturn.C, saturn.R0, op4); + return 0; + case 9: /* C=R1 */ + case 0xd: + saturn.PC += 6; + copy_register(saturn.C, saturn.R1, op4); + return 0; + case 0xa: /* C=R2 */ + case 0xe: + saturn.PC += 6; + copy_register(saturn.C, saturn.R2, op4); + return 0; + case 0xb: /* C=R3 */ + case 0xf: + saturn.PC += 6; + copy_register(saturn.C, saturn.R3, op4); + return 0; + case 0xc: /* C=R4 */ + saturn.PC += 6; + copy_register(saturn.C, saturn.R4, op4); + return 0; + default: + return 1; + } + case 2: + switch (op6) { + case 0: /* AR0EX */ + saturn.PC += 6; + exchange_register(saturn.A, saturn.R0, op4); + return 0; + case 1: /* AR1EX */ + case 5: + saturn.PC += 6; + exchange_register(saturn.A, saturn.R1, op4); + return 0; + case 2: /* AR2EX */ + case 6: + saturn.PC += 6; + exchange_register(saturn.A, saturn.R2, op4); + return 0; + case 3: /* AR3EX */ + case 7: + saturn.PC += 6; + exchange_register(saturn.A, saturn.R3, op4); + return 0; + case 4: /* AR4EX */ + saturn.PC += 6; + exchange_register(saturn.A, saturn.R4, op4); + return 0; + case 8: /* CR0EX */ + saturn.PC += 6; + exchange_register(saturn.C, saturn.R0, op4); + return 0; + case 9: /* CR1EX */ + case 0xd: + saturn.PC += 6; + exchange_register(saturn.C, saturn.R1, op4); + return 0; + case 0xa: /* CR2EX */ + case 0xe: + saturn.PC += 6; + exchange_register(saturn.C, saturn.R2, op4); + return 0; + case 0xb: /* CR3EX */ + case 0xf: + saturn.PC += 6; + exchange_register(saturn.C, saturn.R3, op4); + return 0; + case 0xc: /* CR4EX */ + saturn.PC += 6; + exchange_register(saturn.C, saturn.R4, op4); + return 0; + default: + return 1; + } + default: + return 1; + } + case 0xb: + op4 = read_nibble(saturn.PC + 3); + switch(op4) { + case 2: /* PC=A */ + jumpaddr = dat_to_addr(saturn.A); + saturn.PC = jumpaddr; + return 0; + case 3: /* PC=C */ + jumpaddr = dat_to_addr(saturn.C); + saturn.PC = jumpaddr; + return 0; + case 4: /* A=PC */ + saturn.PC += 4; + addr_to_dat(saturn.PC, saturn.A); + return 0; + case 5: /* C=PC */ + saturn.PC += 4; + addr_to_dat(saturn.PC, saturn.C); + return 0; + case 6: /* APCEX */ + saturn.PC += 4; + jumpaddr = dat_to_addr(saturn.A); + addr_to_dat(saturn.PC, saturn.A); + saturn.PC = jumpaddr; + return 0; + case 7: /* CPCEX */ + saturn.PC += 4; + jumpaddr = dat_to_addr(saturn.C); + addr_to_dat(saturn.PC, saturn.C); + saturn.PC = jumpaddr; + return 0; + default: + return 1; + } + case 0xc: /* ASRB */ + saturn.PC += 3; + shift_right_bit_register(saturn.A, W_FIELD); + return 0; + case 0xd: /* BSRB */ + saturn.PC += 3; + shift_right_bit_register(saturn.B, W_FIELD); + return 0; + case 0xe: /* CSRB */ + saturn.PC += 3; + shift_right_bit_register(saturn.C, W_FIELD); + return 0; + case 0xf: /* DSRB */ + saturn.PC += 3; + shift_right_bit_register(saturn.D, W_FIELD); + return 0; + default: + return 1; + } + case 2: + op3 = read_nibble(saturn.PC + 2); + saturn.PC += 3; + clear_hardware_stat(op3); + return 0; + case 3: + op3 = read_nibble(saturn.PC + 2); + saturn.CARRY = is_zero_hardware_stat(op3); + if (saturn.CARRY) { + saturn.PC += 3; + op4 = read_nibbles(saturn.PC, 2); + if (op4) { + if (op4 & 0x80) + op4 |= jumpmasks[2]; + jumpaddr = (saturn.PC + op4) & 0xfffff; + saturn.PC = jumpaddr; + } else { + saturn.PC = pop_return_addr(); + } + } else { + saturn.PC += 5; + } + return 0; + case 4: + case 5: + op3 = read_nibble(saturn.PC + 2); + if (op2 == 4) { + saturn.PC += 3; + clear_program_stat(op3); + } else { + saturn.PC += 3; + set_program_stat(op3); + } + return 0; + case 6: + case 7: + op3 = read_nibble(saturn.PC + 2); + if (op2 == 6) + saturn.CARRY = (get_program_stat(op3) == 0)?1:0; + else + saturn.CARRY = (get_program_stat(op3) != 0)?1:0; + if (saturn.CARRY) { + saturn.PC += 3; + op4 = read_nibbles(saturn.PC, 2); + if (op4) { + if (op4 & 0x80) + op4 |= jumpmasks[2]; + jumpaddr = (saturn.PC + op4) & 0xfffff; + saturn.PC = jumpaddr; + } else { + saturn.PC = pop_return_addr(); + } + } else { + saturn.PC += 5; + } + return 0; + case 8: + case 9: + op3 = read_nibble(saturn.PC + 2); + if (op2 == 8) + saturn.CARRY = (saturn.P != op3)?1:0; + else + saturn.CARRY = (saturn.P == op3)?1:0; + if (saturn.CARRY) { + saturn.PC += 3; + op4 = read_nibbles(saturn.PC, 2); + if (op4) { + if (op4 & 0x80) + op4 |= jumpmasks[2]; + jumpaddr = (saturn.PC + op4) & 0xfffff; + saturn.PC = jumpaddr; + } else { + saturn.PC = pop_return_addr(); + } + } else { + saturn.PC += 5; + } + return 0; + case 0xa: + op3 = read_nibble(saturn.PC + 2); + switch(op3) { + case 0: /* ?A=B */ + saturn.CARRY = is_equal_register(saturn.A, saturn.B, A_FIELD); + break; + case 1: /* ?B=C */ + saturn.CARRY = is_equal_register(saturn.B, saturn.C, A_FIELD); + break; + case 2: /* ?A=C */ + saturn.CARRY = is_equal_register(saturn.A, saturn.C, A_FIELD); + break; + case 3: /* ?C=D */ + saturn.CARRY = is_equal_register(saturn.C, saturn.D, A_FIELD); + break; + case 4: /* ?A#B */ + saturn.CARRY = is_not_equal_register(saturn.A, saturn.B, A_FIELD); + break; + case 5: /* ?B#C */ + saturn.CARRY = is_not_equal_register(saturn.B, saturn.C, A_FIELD); + break; + case 6: /* ?A#C */ + saturn.CARRY = is_not_equal_register(saturn.A, saturn.C, A_FIELD); + break; + case 7: /* ?C#D */ + saturn.CARRY = is_not_equal_register(saturn.C, saturn.D, A_FIELD); + break; + case 8: /* ?A=0 */ + saturn.CARRY = is_zero_register(saturn.A, A_FIELD); + break; + case 9: /* ?B=0 */ + saturn.CARRY = is_zero_register(saturn.B, A_FIELD); + break; + case 0xa: /* ?C=0 */ + saturn.CARRY = is_zero_register(saturn.C, A_FIELD); + break; + case 0xb: /* ?D=0 */ + saturn.CARRY = is_zero_register(saturn.D, A_FIELD); + break; + case 0xc: /* ?A#0 */ + saturn.CARRY = is_not_zero_register(saturn.A, A_FIELD); + break; + case 0xd: /* ?B#0 */ + saturn.CARRY = is_not_zero_register(saturn.B, A_FIELD); + break; + case 0xe: /* ?C#0 */ + saturn.CARRY = is_not_zero_register(saturn.C, A_FIELD); + break; + case 0xf: /* ?D#0 */ + saturn.CARRY = is_not_zero_register(saturn.D, A_FIELD); + break; + default: + return 1; + } + if (saturn.CARRY) { + saturn.PC += 3; + op4 = read_nibbles(saturn.PC, 2); + if (op4) { + if (op4 & 0x80) + op4 |= jumpmasks[2]; + jumpaddr = (saturn.PC + op4) & 0xfffff; + saturn.PC = jumpaddr; + } else { + saturn.PC = pop_return_addr(); + } + } else { + saturn.PC += 5; + } + return 0; + case 0xb: + op3 = read_nibble(saturn.PC + 2); + switch (op3) { + case 0: /* ?A>B */ + saturn.CARRY = is_greater_register(saturn.A, saturn.B, A_FIELD); + break; + case 1: /* ?B>C */ + saturn.CARRY = is_greater_register(saturn.B, saturn.C, A_FIELD); + break; + case 2: /* ?C>A */ + saturn.CARRY = is_greater_register(saturn.C, saturn.A, A_FIELD); + break; + case 3: /* ?D>C */ + saturn.CARRY = is_greater_register(saturn.D, saturn.C, A_FIELD); + break; + case 4: /* ?A=B */ + saturn.CARRY = is_greater_or_equal_register(saturn.A, saturn.B, A_FIELD); + break; + case 9: /* ?B>=C */ + saturn.CARRY = is_greater_or_equal_register(saturn.B, saturn.C, A_FIELD); + break; + case 0xa: /* ?C>=A */ + saturn.CARRY = is_greater_or_equal_register(saturn.C, saturn.A, A_FIELD); + break; + case 0xb: /* ?D>=C */ + saturn.CARRY = is_greater_or_equal_register(saturn.D, saturn.C, A_FIELD); + break; + case 0xc: /* ?A<=B */ + saturn.CARRY = is_less_or_equal_register(saturn.A, saturn.B, A_FIELD); + break; + case 0xd: /* ?B<=C */ + saturn.CARRY = is_less_or_equal_register(saturn.B, saturn.C, A_FIELD); + break; + case 0xe: /* ?C<=A */ + saturn.CARRY = is_less_or_equal_register(saturn.C, saturn.A, A_FIELD); + break; + case 0xf: /* ?D<=C */ + saturn.CARRY = is_less_or_equal_register(saturn.D, saturn.C, A_FIELD); + break; + default: + return 1; + } + if (saturn.CARRY) { + saturn.PC += 3; + op4 = read_nibbles(saturn.PC, 2); + if (op4) { + if (op4 & 0x80) + op4 |= jumpmasks[2]; + jumpaddr = (saturn.PC + op4) & 0xfffff; + saturn.PC = jumpaddr; + } else { + saturn.PC = pop_return_addr(); + } + } else { + saturn.PC += 5; + } + return 0; + case 0xc: + op3 = read_nibbles(saturn.PC + 2, 4); + if (op3 & 0x8000) + op3 |= jumpmasks[4]; + jumpaddr = (saturn.PC + op3 + 2) & 0xfffff; + saturn.PC = jumpaddr; + return 0; + case 0xd: + op3 = read_nibbles(saturn.PC + 2, 5); + jumpaddr = op3; + saturn.PC = jumpaddr; + return 0; + case 0xe: + op3 = read_nibbles(saturn.PC + 2, 4); + if (op3 & 0x8000) + op3 |= jumpmasks[4]; + jumpaddr = (saturn.PC + op3 + 6) & 0xfffff; + push_return_addr(saturn.PC + 6); + saturn.PC = jumpaddr; + return 0; + case 0xf: + op3 = read_nibbles(saturn.PC + 2, 5); + jumpaddr = op3; + push_return_addr(saturn.PC + 7); + saturn.PC = jumpaddr; + return 0; + default: + return 1; + } + case 9: + op3 = read_nibble(saturn.PC + 2); + if (op2 < 8) { + switch(op3) { + case 0: /* ?A=B */ + saturn.CARRY = is_equal_register(saturn.A, saturn.B, op2); + break; + case 1: /* ?B=C */ + saturn.CARRY = is_equal_register(saturn.B, saturn.C, op2); + break; + case 2: /* ?A=C */ + saturn.CARRY = is_equal_register(saturn.A, saturn.C, op2); + break; + case 3: /* ?C=D */ + saturn.CARRY = is_equal_register(saturn.C, saturn.D, op2); + break; + case 4: /* ?A#B */ + saturn.CARRY = is_not_equal_register(saturn.A, saturn.B, op2); + break; + case 5: /* ?B#C */ + saturn.CARRY = is_not_equal_register(saturn.B, saturn.C, op2); + break; + case 6: /* ?A#C */ + saturn.CARRY = is_not_equal_register(saturn.A, saturn.C, op2); + break; + case 7: /* ?C#D */ + saturn.CARRY = is_not_equal_register(saturn.C, saturn.D, op2); + break; + case 8: /* ?A=0 */ + saturn.CARRY = is_zero_register(saturn.A, op2); + break; + case 9: /* ?B=0 */ + saturn.CARRY = is_zero_register(saturn.B, op2); + break; + case 0xa: /* ?C=0 */ + saturn.CARRY = is_zero_register(saturn.C, op2); + break; + case 0xb: /* ?D=0 */ + saturn.CARRY = is_zero_register(saturn.D, op2); + break; + case 0xc: /* ?A#0 */ + saturn.CARRY = is_not_zero_register(saturn.A, op2); + break; + case 0xd: /* ?B#0 */ + saturn.CARRY = is_not_zero_register(saturn.B, op2); + break; + case 0xe: /* ?C#0 */ + saturn.CARRY = is_not_zero_register(saturn.C, op2); + break; + case 0xf: /* ?D#0 */ + saturn.CARRY = is_not_zero_register(saturn.D, op2); + break; + default: + return 1; + } + } else { + op2 &= 7; + switch (op3) { + case 0: /* ?A>B */ + saturn.CARRY = is_greater_register(saturn.A, saturn.B, op2); + break; + case 1: /* ?B>C */ + saturn.CARRY = is_greater_register(saturn.B, saturn.C, op2); + break; + case 2: /* ?C>A */ + saturn.CARRY = is_greater_register(saturn.C, saturn.A, op2); + break; + case 3: /* ?D>C */ + saturn.CARRY = is_greater_register(saturn.D, saturn.C, op2); + break; + case 4: /* ?A=B */ + saturn.CARRY = is_greater_or_equal_register(saturn.A, saturn.B, op2); + break; + case 9: /* ?B>=C */ + saturn.CARRY = is_greater_or_equal_register(saturn.B, saturn.C, op2); + break; + case 0xa: /* ?C>=A */ + saturn.CARRY = is_greater_or_equal_register(saturn.C, saturn.A, op2); + break; + case 0xb: /* ?D>=C */ + saturn.CARRY = is_greater_or_equal_register(saturn.D, saturn.C, op2); + break; + case 0xc: /* ?A<=B */ + saturn.CARRY = is_less_or_equal_register(saturn.A, saturn.B, op2); + break; + case 0xd: /* ?B<=C */ + saturn.CARRY = is_less_or_equal_register(saturn.B, saturn.C, op2); + break; + case 0xe: /* ?C<=A */ + saturn.CARRY = is_less_or_equal_register(saturn.C, saturn.A, op2); + break; + case 0xf: /* ?D<=C */ + saturn.CARRY = is_less_or_equal_register(saturn.D, saturn.C, op2); + break; + default: + return 1; + } + } + if (saturn.CARRY) { + saturn.PC += 3; + op4 = read_nibbles(saturn.PC, 2); + if (op4) { + if (op4 & 0x80) + op4 |= jumpmasks[2]; + jumpaddr = (saturn.PC + op4) & 0xfffff; + saturn.PC = jumpaddr; + } else { + saturn.PC = pop_return_addr(); + } + } else { + saturn.PC += 5; + } + return 0; + case 0xa: + op3 = read_nibble(saturn.PC + 2); + if (op2 < 8) { + switch(op3) { + case 0: /* A=A+B */ + saturn.PC += 3; + add_register(saturn.A, saturn.A, saturn.B, op2); + return 0; + case 1: /* B=B+C */ + saturn.PC += 3; + add_register(saturn.B, saturn.B, saturn.C, op2); + return 0; + case 2: /* C=C+A */ + saturn.PC += 3; + add_register(saturn.C, saturn.C, saturn.A, op2); + return 0; + case 3: /* D=D+C */ + saturn.PC += 3; + add_register(saturn.D, saturn.D, saturn.C, op2); + return 0; + case 4: /* A=A+A */ + saturn.PC += 3; + add_register(saturn.A, saturn.A, saturn.A, op2); + return 0; + case 5: /* B=B+B */ + saturn.PC += 3; + add_register(saturn.B, saturn.B, saturn.B, op2); + return 0; + case 6: /* C=C+C */ + saturn.PC += 3; + add_register(saturn.C, saturn.C, saturn.C, op2); + return 0; + case 7: /* D=D+D */ + saturn.PC += 3; + add_register(saturn.D, saturn.D, saturn.D, op2); + return 0; + case 8: /* B=B+A */ + saturn.PC += 3; + add_register(saturn.B, saturn.B, saturn.A, op2); + return 0; + case 9: /* C=C+B */ + saturn.PC += 3; + add_register(saturn.C, saturn.C, saturn.B, op2); + return 0; + case 0xa: /* A=A+C */ + saturn.PC += 3; + add_register(saturn.A, saturn.A, saturn.C, op2); + return 0; + case 0xb: /* C=C+D */ + saturn.PC += 3; + add_register(saturn.C, saturn.C, saturn.D, op2); + return 0; + case 0xc: /* A=A-1 */ + saturn.PC += 3; + dec_register(saturn.A, op2); + return 0; + case 0xd: /* B=B-1 */ + saturn.PC += 3; + dec_register(saturn.B, op2); + return 0; + case 0xe: /* C=C-1 */ + saturn.PC += 3; + dec_register(saturn.C, op2); + return 0; + case 0xf: /* D=D-1 */ + saturn.PC += 3; + dec_register(saturn.D, op2); + return 0; + default: + return 1; + } + } else { + op2 &= 7; + switch(op3) { + case 0: /* A=0 */ + saturn.PC += 3; + zero_register(saturn.A, op2); + return 0; + case 1: /* B=0 */ + saturn.PC += 3; + zero_register(saturn.B, op2); + return 0; + case 2: /* C=0 */ + saturn.PC += 3; + zero_register(saturn.C, op2); + return 0; + case 3: /* D=0 */ + saturn.PC += 3; + zero_register(saturn.D, op2); + return 0; + case 4: /* A=B */ + saturn.PC += 3; + copy_register(saturn.A, saturn.B, op2); + return 0; + case 5: /* B=C */ + saturn.PC += 3; + copy_register(saturn.B, saturn.C, op2); + return 0; + case 6: /* C=A */ + saturn.PC += 3; + copy_register(saturn.C, saturn.A, op2); + return 0; + case 7: /* D=C */ + saturn.PC += 3; + copy_register(saturn.D, saturn.C, op2); + return 0; + case 8: /* B=A */ + saturn.PC += 3; + copy_register(saturn.B, saturn.A, op2); + return 0; + case 9: /* C=B */ + saturn.PC += 3; + copy_register(saturn.C, saturn.B, op2); + return 0; + case 0xa: /* A=C */ + saturn.PC += 3; + copy_register(saturn.A, saturn.C, op2); + return 0; + case 0xb: /* C=D */ + saturn.PC += 3; + copy_register(saturn.C, saturn.D, op2); + return 0; + case 0xc: /* ABEX */ + saturn.PC += 3; + exchange_register(saturn.A, saturn.B, op2); + return 0; + case 0xd: /* BCEX */ + saturn.PC += 3; + exchange_register(saturn.B, saturn.C, op2); + return 0; + case 0xe: /* ACEX */ + saturn.PC += 3; + exchange_register(saturn.A, saturn.C, op2); + return 0; + case 0xf: /* CDEX */ + saturn.PC += 3; + exchange_register(saturn.C, saturn.D, op2); + return 0; + default: + return 1; + } + } + case 0xb: + op3 = read_nibble(saturn.PC + 2); + if (op2 < 8) { + switch (op3) { + case 0: /* A=A-B */ + saturn.PC += 3; + sub_register(saturn.A, saturn.A, saturn.B, op2); + return 0; + case 1: /* B=B-C */ + saturn.PC += 3; + sub_register(saturn.B, saturn.B, saturn.C, op2); + return 0; + case 2: /* C=C-A */ + saturn.PC += 3; + sub_register(saturn.C, saturn.C, saturn.A, op2); + return 0; + case 3: /* D=D-C */ + saturn.PC += 3; + sub_register(saturn.D, saturn.D, saturn.C, op2); + return 0; + case 4: /* A=A+1 */ + saturn.PC += 3; + inc_register(saturn.A, op2); + return 0; + case 5: /* B=B+1 */ + saturn.PC += 3; + inc_register(saturn.B, op2); + return 0; + case 6: /* C=C+1 */ + saturn.PC += 3; + inc_register(saturn.C, op2); + return 0; + case 7: /* D=D+1 */ + saturn.PC += 3; + inc_register(saturn.D, op2); + return 0; + case 8: /* B=B-A */ + saturn.PC += 3; + sub_register(saturn.B, saturn.B, saturn.A, op2); + return 0; + case 9: /* C=C-B */ + saturn.PC += 3; + sub_register(saturn.C, saturn.C, saturn.B, op2); + return 0; + case 0xa: /* A=A-C */ + saturn.PC += 3; + sub_register(saturn.A, saturn.A, saturn.C, op2); + return 0; + case 0xb: /* C=C-D */ + saturn.PC += 3; + sub_register(saturn.C, saturn.C, saturn.D, op2); + return 0; + case 0xc: /* A=B-A */ + saturn.PC += 3; + sub_register(saturn.A, saturn.B, saturn.A, op2); + return 0; + case 0xd: /* B=C-B */ + saturn.PC += 3; + sub_register(saturn.B, saturn.C, saturn.B, op2); + return 0; + case 0xe: /* C=A-C */ + saturn.PC += 3; + sub_register(saturn.C, saturn.A, saturn.C, op2); + return 0; + case 0xf: /* D=C-D */ + saturn.PC += 3; + sub_register(saturn.D, saturn.C, saturn.D, op2); + return 0; + default: + return 1; + } + } else { + op2 &= 7; + switch (op3) { + case 0: /* ASL */ + saturn.PC += 3; + shift_left_register(saturn.A, op2); + return 0; + case 1: /* BSL */ + saturn.PC += 3; + shift_left_register(saturn.B, op2); + return 0; + case 2: /* CSL */ + saturn.PC += 3; + shift_left_register(saturn.C, op2); + return 0; + case 3: /* DSL */ + saturn.PC += 3; + shift_left_register(saturn.D, op2); + return 0; + case 4: /* ASR */ + saturn.PC += 3; + shift_right_register(saturn.A, op2); + return 0; + case 5: /* BSR */ + saturn.PC += 3; + shift_right_register(saturn.B, op2); + return 0; + case 6: /* CSR */ + saturn.PC += 3; + shift_right_register(saturn.C, op2); + return 0; + case 7: /* DSR */ + saturn.PC += 3; + shift_right_register(saturn.D, op2); + return 0; + case 8: /* A=-A */ + saturn.PC += 3; + complement_2_register(saturn.A, op2); + return 0; + case 9: /* B=-B */ + saturn.PC += 3; + complement_2_register(saturn.B, op2); + return 0; + case 0xa: /* C=-C */ + saturn.PC += 3; + complement_2_register(saturn.C, op2); + return 0; + case 0xb: /* D=-D */ + saturn.PC += 3; + complement_2_register(saturn.D, op2); + return 0; + case 0xc: /* A=-A-1 */ + saturn.PC += 3; + complement_1_register(saturn.A, op2); + return 0; + case 0xd: /* B=-B-1 */ + saturn.PC += 3; + complement_1_register(saturn.B, op2); + return 0; + case 0xe: /* C=-C-1 */ + saturn.PC += 3; + complement_1_register(saturn.C, op2); + return 0; + case 0xf: /* D=-D-1 */ + saturn.PC += 3; + complement_1_register(saturn.D, op2); + return 0; + default: + return 1; + } + } + case 0xc: + switch(op2) { + case 0: /* A=A+B */ + saturn.PC += 2; + add_register(saturn.A, saturn.A, saturn.B, A_FIELD); + return 0; + case 1: /* B=B+C */ + saturn.PC += 2; + add_register(saturn.B, saturn.B, saturn.C, A_FIELD); + return 0; + case 2: /* C=C+A */ + saturn.PC += 2; + add_register(saturn.C, saturn.C, saturn.A, A_FIELD); + return 0; + case 3: /* D=D+C */ + saturn.PC += 2; + add_register(saturn.D, saturn.D, saturn.C, A_FIELD); + return 0; + case 4: /* A=A+A */ + saturn.PC += 2; + add_register(saturn.A, saturn.A, saturn.A, A_FIELD); + return 0; + case 5: /* B=B+B */ + saturn.PC += 2; + add_register(saturn.B, saturn.B, saturn.B, A_FIELD); + return 0; + case 6: /* C=C+C */ + saturn.PC += 2; + add_register(saturn.C, saturn.C, saturn.C, A_FIELD); + return 0; + case 7: /* D=D+D */ + saturn.PC += 2; + add_register(saturn.D, saturn.D, saturn.D, A_FIELD); + return 0; + case 8: /* B=B+A */ + saturn.PC += 2; + add_register(saturn.B, saturn.B, saturn.A, A_FIELD); + return 0; + case 9: /* C=C+B */ + saturn.PC += 2; + add_register(saturn.C, saturn.C, saturn.B, A_FIELD); + return 0; + case 0xa: /* A=A+C */ + saturn.PC += 2; + add_register(saturn.A, saturn.A, saturn.C, A_FIELD); + return 0; + case 0xb: /* C=C+D */ + saturn.PC += 2; + add_register(saturn.C, saturn.C, saturn.D, A_FIELD); + return 0; + case 0xc: /* A=A-1 */ + saturn.PC += 2; + dec_register(saturn.A, A_FIELD); + return 0; + case 0xd: /* B=B-1 */ + saturn.PC += 2; + dec_register(saturn.B, A_FIELD); + return 0; + case 0xe: /* C=C-1 */ + saturn.PC += 2; + dec_register(saturn.C, A_FIELD); + return 0; + case 0xf: /* D=D-1 */ + saturn.PC += 2; + dec_register(saturn.D, A_FIELD); + return 0; + default: + return 1; + } + case 0xd: + switch(op2) { + case 0: /* A=0 */ + saturn.PC += 2; + zero_register(saturn.A, A_FIELD); + return 0; + case 1: /* B=0 */ + saturn.PC += 2; + zero_register(saturn.B, A_FIELD); + return 0; + case 2: /* C=0 */ + saturn.PC += 2; + zero_register(saturn.C, A_FIELD); + return 0; + case 3: /* D=0 */ + saturn.PC += 2; + zero_register(saturn.D, A_FIELD); + return 0; + case 4: /* A=B */ + saturn.PC += 2; + copy_register(saturn.A, saturn.B, A_FIELD); + return 0; + case 5: /* B=C */ + saturn.PC += 2; + copy_register(saturn.B, saturn.C, A_FIELD); + return 0; + case 6: /* C=A */ + saturn.PC += 2; + copy_register(saturn.C, saturn.A, A_FIELD); + return 0; + case 7: /* D=C */ + saturn.PC += 2; + copy_register(saturn.D, saturn.C, A_FIELD); + return 0; + case 8: /* B=A */ + saturn.PC += 2; + copy_register(saturn.B, saturn.A, A_FIELD); + return 0; + case 9: /* C=B */ + saturn.PC += 2; + copy_register(saturn.C, saturn.B, A_FIELD); + return 0; + case 0xa: /* A=C */ + saturn.PC += 2; + copy_register(saturn.A, saturn.C, A_FIELD); + return 0; + case 0xb: /* C=D */ + saturn.PC += 2; + copy_register(saturn.C, saturn.D, A_FIELD); + return 0; + case 0xc: /* ABEX */ + saturn.PC += 2; + exchange_register(saturn.A, saturn.B, A_FIELD); + return 0; + case 0xd: /* BCEX */ + saturn.PC += 2; + exchange_register(saturn.B, saturn.C, A_FIELD); + return 0; + case 0xe: /* ACEX */ + saturn.PC += 2; + exchange_register(saturn.A, saturn.C, A_FIELD); + return 0; + case 0xf: /* CDEX */ + saturn.PC += 2; + exchange_register(saturn.C, saturn.D, A_FIELD); + return 0; + default: + return 1; + } + case 0xe: + switch (op2) { + case 0: /* A=A-B */ + saturn.PC += 2; + sub_register(saturn.A, saturn.A, saturn.B, A_FIELD); + return 0; + case 1: /* B=B-C */ + saturn.PC += 2; + sub_register(saturn.B, saturn.B, saturn.C, A_FIELD); + return 0; + case 2: /* C=C-A */ + saturn.PC += 2; + sub_register(saturn.C, saturn.C, saturn.A, A_FIELD); + return 0; + case 3: /* D=D-C */ + saturn.PC += 2; + sub_register(saturn.D, saturn.D, saturn.C, A_FIELD); + return 0; + case 4: /* A=A+1 */ + saturn.PC += 2; + inc_register(saturn.A, A_FIELD); + return 0; + case 5: /* B=B+1 */ + saturn.PC += 2; + inc_register(saturn.B, A_FIELD); + return 0; + case 6: /* C=C+1 */ + saturn.PC += 2; + inc_register(saturn.C, A_FIELD); + return 0; + case 7: /* D=D+1 */ + saturn.PC += 2; + inc_register(saturn.D, A_FIELD); + return 0; + case 8: /* B=B-A */ + saturn.PC += 2; + sub_register(saturn.B, saturn.B, saturn.A, A_FIELD); + return 0; + case 9: /* C=C-B */ + saturn.PC += 2; + sub_register(saturn.C, saturn.C, saturn.B, A_FIELD); + return 0; + case 0xa: /* A=A-C */ + saturn.PC += 2; + sub_register(saturn.A, saturn.A, saturn.C, A_FIELD); + return 0; + case 0xb: /* C=C-D */ + saturn.PC += 2; + sub_register(saturn.C, saturn.C, saturn.D, A_FIELD); + return 0; + case 0xc: /* A=B-A */ + saturn.PC += 2; + sub_register(saturn.A, saturn.B, saturn.A, A_FIELD); + return 0; + case 0xd: /* B=C-B */ + saturn.PC += 2; + sub_register(saturn.B, saturn.C, saturn.B, A_FIELD); + return 0; + case 0xe: /* C=A-C */ + saturn.PC += 2; + sub_register(saturn.C, saturn.A, saturn.C, A_FIELD); + return 0; + case 0xf: /* D=C-D */ + saturn.PC += 2; + sub_register(saturn.D, saturn.C, saturn.D, A_FIELD); + return 0; + default: + return 1; + } + case 0xf: + switch (op2) { + case 0: /* ASL */ + saturn.PC += 2; + shift_left_register(saturn.A, A_FIELD); + return 0; + case 1: /* BSL */ + saturn.PC += 2; + shift_left_register(saturn.B, A_FIELD); + return 0; + case 2: /* CSL */ + saturn.PC += 2; + shift_left_register(saturn.C, A_FIELD); + return 0; + case 3: /* DSL */ + saturn.PC += 2; + shift_left_register(saturn.D, A_FIELD); + return 0; + case 4: /* ASR */ + saturn.PC += 2; + shift_right_register(saturn.A, A_FIELD); + return 0; + case 5: /* BSR */ + saturn.PC += 2; + shift_right_register(saturn.B, A_FIELD); + return 0; + case 6: /* CSR */ + saturn.PC += 2; + shift_right_register(saturn.C, A_FIELD); + return 0; + case 7: /* DSR */ + saturn.PC += 2; + shift_right_register(saturn.D, A_FIELD); + return 0; + case 8: /* A=-A */ + saturn.PC += 2; + complement_2_register(saturn.A, A_FIELD); + return 0; + case 9: /* B=-B */ + saturn.PC += 2; + complement_2_register(saturn.B, A_FIELD); + return 0; + case 0xa: /* C=-C */ + saturn.PC += 2; + complement_2_register(saturn.C, A_FIELD); + return 0; + case 0xb: /* D=-D */ + saturn.PC += 2; + complement_2_register(saturn.D, A_FIELD); + return 0; + case 0xc: /* A=-A-1 */ + saturn.PC += 2; + complement_1_register(saturn.A, A_FIELD); + return 0; + case 0xd: /* B=-B-1 */ + saturn.PC += 2; + complement_1_register(saturn.B, A_FIELD); + return 0; + case 0xe: /* C=-C-1 */ + saturn.PC += 2; + complement_1_register(saturn.C, A_FIELD); + return 0; + case 0xf: /* D=-D-1 */ + saturn.PC += 2; + complement_1_register(saturn.D, A_FIELD); + return 0; + default: + return 1; + } + default: + return 1; + } +} + +inline int +#ifdef __FunctionProto__ +step_instruction(void) +#else +step_instruction() +#endif +{ + int op0, op1, op2, op3; + int stop = 0; + + jumpaddr = 0; + + op0 = read_nibble(saturn.PC); + switch (op0) { + case 0: + op1 = read_nibble(saturn.PC + 1); + switch (op1) { + case 0: /* RTNSXM */ + saturn.XM = 1; + saturn.PC = pop_return_addr(); + break; + case 1: /* RTN */ + saturn.PC = pop_return_addr(); + break; + case 2: /* RTNSC */ + saturn.CARRY = 1; + saturn.PC = pop_return_addr(); + break; + case 3: /* RTNCC */ + saturn.CARRY = 0; + saturn.PC = pop_return_addr(); + break; + case 4: /* SETHEX */ + saturn.PC += 2; + saturn.hexmode = HEX; + break; + case 5: /* SETDEC */ + saturn.PC += 2; + saturn.hexmode = DEC; + break; + case 6: /* RSTK=C */ + jumpaddr = dat_to_addr(saturn.C); + push_return_addr(jumpaddr); + saturn.PC += 2; + break; + case 7: /* C=RSTK */ + saturn.PC += 2; + jumpaddr = pop_return_addr(); + addr_to_dat(jumpaddr, saturn.C); + break; + case 8: /* CLRST */ + saturn.PC += 2; + clear_status(); + break; + case 9: /* C=ST */ + saturn.PC += 2; + status_to_register(saturn.C); + break; + case 0xa: /* ST=C */ + saturn.PC += 2; + register_to_status(saturn.C); + break; + case 0xb: /* CSTEX */ + saturn.PC += 2; + swap_register_status(saturn.C); + break; + case 0xc: /* P=P+1 */ + saturn.PC += 2; + if (saturn.P == 0xf) { + saturn.P = 0; + saturn.CARRY = 1; + } else { + saturn.P += 1; + saturn.CARRY = 0; + } + break; + case 0xd: /* P=P-1 */ + saturn.PC += 2; + if (saturn.P == 0) { + saturn.P = 0xf; + saturn.CARRY = 1; + } else { + saturn.P -= 1; + saturn.CARRY = 0; + } + break; + case 0xe: + op2 = read_nibble(saturn.PC + 2); + op3 = read_nibble(saturn.PC + 3); + switch(op3) { + case 0: /* A=A&B */ + saturn.PC += 4; + and_register(saturn.A, saturn.A, saturn.B, op2); + break; + case 1: /* B=B&C */ + saturn.PC += 4; + and_register(saturn.B, saturn.B, saturn.C, op2); + break; + case 2: /* C=C&A */ + saturn.PC += 4; + and_register(saturn.C, saturn.C, saturn.A, op2); + break; + case 3: /* D=D&C */ + saturn.PC += 4; + and_register(saturn.D, saturn.D, saturn.C, op2); + break; + case 4: /* B=B&A */ + saturn.PC += 4; + and_register(saturn.B, saturn.B, saturn.A, op2); + break; + case 5: /* C=C&B */ + saturn.PC += 4; + and_register(saturn.C, saturn.C, saturn.B, op2); + break; + case 6: /* A=A&C */ + saturn.PC += 4; + and_register(saturn.A, saturn.A, saturn.C, op2); + break; + case 7: /* C=C&D */ + saturn.PC += 4; + and_register(saturn.C, saturn.C, saturn.D, op2); + break; + case 8: /* A=A!B */ + saturn.PC += 4; + or_register(saturn.A, saturn.A, saturn.B, op2); + break; + case 9: /* B=B!C */ + saturn.PC += 4; + or_register(saturn.B, saturn.B, saturn.C, op2); + break; + case 0xa: /* C=C!A */ + saturn.PC += 4; + or_register(saturn.C, saturn.C, saturn.A, op2); + break; + case 0xb: /* D=D!C */ + saturn.PC += 4; + or_register(saturn.D, saturn.D, saturn.C, op2); + break; + case 0xc: /* B=B!A */ + saturn.PC += 4; + or_register(saturn.B, saturn.B, saturn.A, op2); + break; + case 0xd: /* C=C!B */ + saturn.PC += 4; + or_register(saturn.C, saturn.C, saturn.B, op2); + break; + case 0xe: /* A=A!C */ + saturn.PC += 4; + or_register(saturn.A, saturn.A, saturn.C, op2); + break; + case 0xf: /* C=C!D */ + saturn.PC += 4; + or_register(saturn.C, saturn.C, saturn.D, op2); + break; + default: + stop = 1; + break; + } + break; + case 0xf: /* RTI */ + do_return_interupt(); + break; + default: + stop = 1; + break; + } + break; + case 1: + stop = decode_group_1(); + break; + case 2: + op2 = read_nibble(saturn.PC + 1); + saturn.PC += 2; + saturn.P = op2; + break; + case 3: + op2 = read_nibble(saturn.PC + 1); + load_constant(saturn.C, op2 + 1, saturn.PC + 2); + saturn.PC += 3 + op2; + break; + case 4: + op2 = read_nibbles(saturn.PC + 1, 2); + if (op2 == 0x02) { + saturn.PC += 3; + } else if (saturn.CARRY != 0) { + if (op2) { + if (op2 & 0x80) + op2 |= jumpmasks[2]; + jumpaddr = (saturn.PC + op2 + 1) & 0xfffff; + saturn.PC = jumpaddr; + } else { + saturn.PC = pop_return_addr(); + } + } else { + saturn.PC += 3; + } + break; + case 5: + if (saturn.CARRY == 0) { + op2 = read_nibbles(saturn.PC + 1, 2); + if (op2) { + if (op2 & 0x80) + op2 |= jumpmasks[2]; + jumpaddr = (saturn.PC + op2 + 1) & 0xfffff; + saturn.PC = jumpaddr; + } else { + saturn.PC = pop_return_addr(); + } + } else { + saturn.PC += 3; + } + break; + case 6: + op2 = read_nibbles(saturn.PC + 1, 3); + if (op2 == 0x003) { + saturn.PC += 4; + } else if(op2 == 0x004) { + op3 = read_nibbles(saturn.PC + 4, 1); + saturn.PC += 5; + if (op3 != 0) { + enter_debugger |= TRAP_INSTRUCTION; + return 1; + } + } else { + if (op2 & 0x800) + op2 |= jumpmasks[3]; + jumpaddr = (op2 + saturn.PC + 1) & 0xfffff; + saturn.PC = jumpaddr; + } + break; + case 7: + op2 = read_nibbles(saturn.PC + 1, 3); + if (op2 & 0x800) + op2 |= jumpmasks[3]; + jumpaddr = (op2 + saturn.PC + 4) & 0xfffff; + push_return_addr(saturn.PC+4); + saturn.PC = jumpaddr; + break; + default: + stop = decode_8_thru_f(op0); + break; + } + instructions++; + if (stop) { + enter_debugger |= ILLEGAL_INSTRUCTION; + } + return stop; +} + +inline void +#ifdef __FunctionProto__ +schedule(void) +#else +schedule() +#endif +{ + t1_t2_ticks ticks; + unsigned long steps; + static unsigned long old_stat_instr; + static unsigned long old_sched_instr; + + steps = instructions - old_sched_instr; + old_sched_instr = instructions; + +#ifdef DEBUG_SCHED + fprintf(stderr, "schedule called after %ld instructions\n", steps); +#endif + + if ((sched_timer2 -= steps) <= 0) { + if (!saturn.intenable) { + sched_timer2 = SCHED_TIMER2; + } else { + sched_timer2 = saturn.t2_tick; + } + saturn.t2_instr += steps; + if (saturn.t2_ctrl & 0x01) { + saturn.timer2--; + } + if (saturn.timer2 == 0 && (saturn.t2_ctrl & 0x02)) { + saturn.t2_ctrl |= 0x08; + do_interupt(); + } + } + schedule_event = sched_timer2; + +#ifdef DEBUG_SCHED + fprintf(stderr, "next timer 2 step: %ld, event: %ld\n", + sched_timer2, schedule_event); +#endif + + if (device_check) { + device_check = 0; + if ((sched_display -= steps) <= 0) { + if (device.display_touched) device.display_touched -= steps; + if (device.display_touched < 0) device.display_touched = 1; +#ifdef DEBUG_DISP_SCHED + fprintf(stderr, "check_device: disp_when %d, disp_touched %d\n", + sched_display, device.display_touched); +#endif + } + check_devices(); + sched_display = SCHED_NEVER; + if (device.display_touched) { + if (device.display_touched < sched_display) + sched_display = device.display_touched - 1; + if (sched_display < schedule_event) schedule_event = sched_display; + } + } + + if ((sched_receive -= steps) <= 0) { + sched_receive = SCHED_RECEIVE; + if ((saturn.rcs & 0x01) == 0) { + receive_char(); + } + } + if (sched_receive < schedule_event) schedule_event = sched_receive; + +#ifdef DEBUG_SCHED + fprintf(stderr, "next receive: %ld, event: %ld\n", + sched_receive, schedule_event); +#endif + + if ((sched_adjtime -= steps) <= 0) { + + sched_adjtime = SCHED_ADJTIME; + + if (saturn.PC < SrvcIoStart || saturn.PC > SrvcIoEnd) { + + ticks = get_t1_t2(); + if (saturn.t2_ctrl & 0x01) { + saturn.timer2 = ticks.t2_ticks; + } + + if ((saturn.t2_ctrl & 0x08) == 0 && saturn.timer2 <= 0) { + if (saturn.t2_ctrl & 0x02) { + saturn.t2_ctrl |= 0x08; + do_interupt(); + } + } + + adj_time_pending = 0; + + saturn.timer1 = set_t1 - ticks.t1_ticks; + if ((saturn.t1_ctrl & 0x08) == 0 && saturn.timer1 <= 0) { + if (saturn.t1_ctrl & 0x02) { + saturn.t1_ctrl |= 0x08; + do_interupt(); + } + } + saturn.timer1 &= 0x0f; + + } else { + + adj_time_pending = 1; + + } + } + if (sched_adjtime < schedule_event) schedule_event = sched_adjtime; + +#ifdef DEBUG_SCHED + fprintf(stderr, "next adjtime: %ld, event: %ld\n", + sched_adjtime, schedule_event); +#endif + + if ((sched_timer1 -= steps) <= 0) { + if (!saturn.intenable) { + sched_timer1 = SCHED_TIMER1; + } else { + sched_timer1 = saturn.t1_tick; + } + saturn.t1_instr += steps; + saturn.timer1 = (saturn.timer1 - 1) & 0xf; + if (saturn.timer1 == 0 && (saturn.t1_ctrl & 0x02)) { + saturn.t1_ctrl |= 0x08; + do_interupt(); + } + } + if (sched_timer1 < schedule_event) schedule_event = sched_timer1; + +#ifdef DEBUG_SCHED + fprintf(stderr, "next timer 1 step: %ld, event: %ld\n", + sched_timer1, schedule_event); +#endif + + if ((sched_statistics -= steps) <= 0) { + sched_statistics = SCHED_STATISTICS; + run = get_timer(RUN_TIMER); +#ifndef SIMPLE_64 + s_1 = (run.hi << 19) | (run.lo >> 13); + s_16 = (run.hi << 23) | (run.lo >> 9); +#endif + delta_t_1 = s_1 - old_s_1; + delta_t_16 = s_16 - old_s_16; + old_s_1 = s_1; + old_s_16 = s_16; + delta_i = instructions - old_stat_instr; + old_stat_instr = instructions; + if (delta_t_1 > 0) { + t1_i_per_tick = ((NR_SAMPLES - 1) * t1_i_per_tick + + (delta_i / delta_t_16)) / NR_SAMPLES; + t2_i_per_tick = t1_i_per_tick / 512; + saturn.i_per_s = ((NR_SAMPLES - 1) * saturn.i_per_s + + (delta_i / delta_t_1)) / NR_SAMPLES; + } else { + t1_i_per_tick = 8192; + t2_i_per_tick = 16; + } + saturn.t1_tick = t1_i_per_tick; + saturn.t2_tick = t2_i_per_tick; + +#ifdef DEBUG_TIMER + if (delta_t_1 > 0) { +#if 0 + fprintf(stderr, "I/s = %ld, T1 I/TICK = %d (%ld), T2 I/TICK = %d (%ld)\n", + saturn.i_per_s, saturn.t1_tick, t1_i_per_tick, + saturn.t2_tick, t2_i_per_tick); +#else + fprintf(stderr, "I/s = %ld, T1 I/TICK = %d, T2 I/TICK = %d (%ld)\n", + saturn.i_per_s, saturn.t1_tick, saturn.t2_tick, t2_i_per_tick); +#endif + } +#endif + } + if (sched_statistics < schedule_event) + schedule_event = sched_statistics; + +#ifdef DEBUG_SCHED + fprintf(stderr, "next statistics: %ld, event: %ld\n", + sched_statistics, schedule_event); +#endif + + if ((sched_instr_rollover -= steps) <= 0) { + sched_instr_rollover = SCHED_INSTR_ROLLOVER; + instructions = 1; + old_sched_instr = 1; + reset_timer(RUN_TIMER); + reset_timer(IDLE_TIMER); + start_timer(RUN_TIMER); + } + if (sched_instr_rollover < schedule_event) + schedule_event = sched_instr_rollover; + +#ifdef DEBUG_SCHED + fprintf(stderr, "next instruction rollover: %ld, event: %ld\n", + sched_instr_rollover, schedule_event); +#endif + + schedule_event--; + + if (got_alarm) { + got_alarm = 0; +#ifdef HAVE_XSHM + if (disp.display_update) refresh_display(); +#endif + GetEvent(); + } +} + +int +#ifdef __FunctionProto__ +emulate(void) +#else +emulate() +#endif +{ + struct timeval tv; + struct timeval tv2; +#ifndef SOLARIS + struct timezone tz; +#endif + + reset_timer(T1_TIMER); + reset_timer(RUN_TIMER); + reset_timer(IDLE_TIMER); + + set_accesstime(); + start_timer(T1_TIMER); + + start_timer(RUN_TIMER); + + sched_timer1 = t1_i_per_tick = saturn.t1_tick; + sched_timer2 = t2_i_per_tick = saturn.t2_tick; + + set_t1 = saturn.timer1; + + do { + step_instruction(); + + { + int i; + for (i=0; + i < sizeof(saturn.keybuf.rows)/sizeof(saturn.keybuf.rows[0]); + i++) { + if (saturn.keybuf.rows[i] || throttle) { +#ifdef SOLARIS + gettimeofday(&tv); +#else + gettimeofday(&tv, &tz); +#endif + while ((tv.tv_sec == tv2.tv_sec) && ((tv.tv_usec - tv2.tv_usec) < 2)) { + gettimeofday(&tv, &tz); + } + + tv2.tv_usec = tv.tv_usec; + tv2.tv_sec = tv.tv_sec; + break; + } + } + } + +/* We need to throttle the speed here. */ + + if (schedule_event < 0) { +//puts("bug"); +// schedule_event = 0; + } + if (schedule_event-- <= 0) + { + schedule(); + } + } while (!enter_debugger); + + return 0; +} diff --git a/src/errors.c b/src/errors.c new file mode 100644 index 0000000..80757f1 --- /dev/null +++ b/src/errors.c @@ -0,0 +1,61 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: errors.c,v $ + * Revision 1.1 1994/12/07 10:15:47 ecd + * Initial revision + * + * + * $Id: errors.c,v 1.1 1994/12/07 10:15:47 ecd Exp ecd $ + */ + +#include +#include + +#include "global.h" +#include "resources.h" + +char errbuf[1024] = { 0, }; +char fixbuf[1024] = { 0, }; + +void +#ifdef __FunctionProto__ +fatal_exit(void) +#else +fatal_exit() +#endif +{ + if (quiet) + exit (1); + + if (errbuf[0] == '\0') + { + fprintf(stderr, "%s: FATAL ERROR, exit.\n", progname); + exit (1); + } + + fprintf(stderr, "%s: FATAL ERROR, exit.\n - %s\n", progname, errbuf); + + if (fixbuf[0] != '\0') + fprintf(stderr, " - %s\n", fixbuf); + + exit (1); +} + + diff --git a/src/errors.h b/src/errors.h new file mode 100644 index 0000000..77770ce --- /dev/null +++ b/src/errors.h @@ -0,0 +1,37 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: errors.h,v $ + * Revision 1.1 1994/12/07 10:16:15 ecd + * Initial revision + * + * + * $Id: errors.h,v 1.1 1994/12/07 10:16:15 ecd Exp ecd $ + */ +#ifndef _ERRORS_H +#define _ERRORS_H + +#include "global.h" + +extern char errbuf[1024]; +extern char fixbuf[1024]; + +extern void fatal_exit __ProtoType__ ((void)); + +#endif /* !_ERRORS_H */ diff --git a/src/global.h b/src/global.h new file mode 100644 index 0000000..badf88d --- /dev/null +++ b/src/global.h @@ -0,0 +1,154 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: global.h,v $ + * Revision 1.5 1994/12/08 22:28:39 ecd + * added generic define for SYSV_TIME if SYSV is defined + * + * Revision 1.4 1994/12/07 20:16:41 ecd + * added more functions missing in SunOS includes + * + * Revision 1.4 1994/12/07 20:16:41 ecd + * added more functions missing in SunOS includes + * + * Revision 1.3 1994/11/02 14:51:27 ecd + * new define for SYSV_TIME + * + * Revision 1.2 1994/10/06 16:28:03 ecd + * added #define USE_SHM + * + * Revision 1.1 1994/09/07 12:53:20 ecd + * Initial revision + * + * + * $Id: global.h,v 1.5 1994/12/08 22:28:39 ecd Exp ecd $ + */ + +#ifndef _GLOBAL_H +#define _GLOBAL_H 1 + +#include "config.h" + +#ifdef __ProtoType__ +#undef __ProtoType__ +#endif + +#ifdef __FunctionProto__ +#undef __FunctionProto__ +#endif + +#if defined(__STDC__) || defined(__cplusplus) +#define __ProtoType__(x) x +#define __FunctionProto__ 1 +#else +#define __ProtoType__(x) () +#undef __FunctionProto__ +#endif + +#if !defined(__GNUC__) || defined(__STRICT_ANSI__) +#define inline +#if !defined(__STDC__) +#define const +#endif +#endif + +/* + * If we are running Linux, `linux' will be defined by gcc. + */ +#if defined(linux) + +#ifndef LINUX +#define LINUX 1 +#endif + +#define SYSV_TIME 1 + +#else /* Not Linux */ + +#if defined(sun) && defined(unix) + +#if defined(__svr4__) || defined(SVR4) || defined(SYSV) + +#ifndef SOLARIS +#define SOLARIS 1 +#endif + +#define SYSV_TIME 1 + +#else /* Not Solaris */ + +#if defined(hpux) + +#ifndef HPUX +#define HPUX 1 +#endif + +#else /* Not HP-UX */ + +#ifndef SUNOS +#define SUNOS 1 +#endif + +#endif /* Not HP-UX */ +#endif /* Not Solaris */ +#endif /* Sun && Unix */ +#endif /* Not Linux */ + +#ifdef SYSV +#ifndef SYSV_TIME +#define SYSV_TIME 1 +#endif +#endif + +#ifdef SUNOS +#undef HAVE_STDIO +#else +#define HAVE_STDIO 1 +#endif + +#ifndef HAVE_STDIO +#include +#include +#include +extern int printf __ProtoType__((char *, ...)); +extern int fprintf __ProtoType__((FILE *, char *, ...)); +extern int sscanf __ProtoType__((char *, char *, ...)); +extern void fflush __ProtoType__((FILE *)); +extern int fseek __ProtoType__((FILE *, long, int)); +extern int fread __ProtoType__((void *, int, int, FILE*)); +extern int fwrite __ProtoType__((void *, int, int, FILE*)); +extern void fclose __ProtoType__((FILE *)); +extern int fgetc __ProtoType__((FILE *)); +extern void bzero __ProtoType__((void *, int)); +extern time_t time __ProtoType__((time_t *)); +extern int select __ProtoType__((int, fd_set *, fd_set *, + fd_set *, struct timeval *)); +extern int setitimer __ProtoType__((int, struct itimerval *, + struct itimerval *)); +extern int gethostname __ProtoType__((char *, int)); +#ifdef HAVE_XSHM +#include +#include +extern int shmget __ProtoType__((key_t, int, int)); +extern int shmat __ProtoType__((int, void *, int)); +extern int shmctl __ProtoType__((int, int, struct shmid_ds *)); +#endif +#endif + +#endif /* !_GLOBAL_H */ diff --git a/src/hp.h b/src/hp.h new file mode 100644 index 0000000..40139e5 --- /dev/null +++ b/src/hp.h @@ -0,0 +1,63 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: hp.h,v $ + * Revision 1.4 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.3 1994/11/02 14:51:27 ecd + * minor fix + * + * Revision 1.3 1994/11/02 14:51:27 ecd + * minor fix + * + * Revision 1.2 1994/10/06 16:28:03 ecd + * changed char to unsigned + * + * Revision 1.1 1994/09/13 15:05:11 ecd + * Initial revision + * + * + * $Id: hp.h,v 1.4 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#ifndef _HP_H +#define _HP_H 1 + +#include "bitmaps/hp.h" + +#include "bitmaps/hp48sx.h" + +#include "bitmaps/hp48gx.h" + +#include "bitmaps/science.h" + +#define gx_128K_ram_x_hot 1 +#define gx_128K_ram_y_hot 8 +#include "bitmaps/gx_128K_ram.h" + +#define gx_silver_x_hot 0 +#define gx_silver_y_hot 8 +#include "bitmaps/gx_silver.h" + +#define gx_green_x_hot 11 +#define gx_green_y_hot 0 +#include "bitmaps/gx_green.h" + +#endif /* !_HP_H */ diff --git a/src/hp48.h b/src/hp48.h new file mode 100644 index 0000000..e2b89b9 --- /dev/null +++ b/src/hp48.h @@ -0,0 +1,293 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: hp48.h,v $ + * Revision 1.11 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.10 1994/11/28 02:19:22 ecd + * added function serial_baud() + * + * Revision 1.10 1994/11/28 02:19:22 ecd + * added function serial_baud() + * + * Revision 1.9 1994/11/02 14:51:27 ecd + * minor changes + * + * Revision 1.8 1994/10/09 20:26:35 ecd + * changed display_t: display.skip --> display.nibs_per_line + * + * Revision 1.7 1994/10/05 08:33:22 ecd + * added do_interupt definition + * + * Revision 1.6 1994/09/30 12:32:49 ecd + * added some fields for REALTIME support, + * added Scheduler stuff + * + * Revision 1.5 1994/09/18 15:31:58 ecd + * started Real Time support + * + * Revision 1.4 1994/09/13 16:58:42 ecd + * changed to plain X11 + * + * Revision 1.3 1994/08/31 18:25:23 ecd + * added read_nibble_crc + * + * Revision 1.2 1994/08/27 11:29:48 ecd + * changed keyboard interrupt handling. + * + * Revision 1.1 1994/08/26 11:09:18 ecd + * Initial revision + * + * + * + * $Id: hp48.h,v 1.11 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#ifndef _HP48_H +#define _HP48_H 1 + +#include "global.h" + +#include + +#include "mmu.h" +#ifdef HAVE_STDINT_H +# include +#endif + +#define RAM_SIZE_SX 0x10000 +#define RAM_SIZE_GX 0x40000 + +#define P_FIELD 0 +#define WP_FIELD 1 +#define XS_FIELD 2 +#define X_FIELD 3 +#define S_FIELD 4 +#define M_FIELD 5 +#define B_FIELD 6 +#define W_FIELD 7 +#define A_FIELD 15 +#define IN_FIELD 16 +#define OUT_FIELD 17 +#define OUTS_FIELD 18 + +#define DEC 10 +#define HEX 16 + +#define NR_RSTK 8 +#define NR_PSTAT 16 + +typedef unsigned char word_1; +typedef unsigned char word_4; +typedef unsigned char word_8; +typedef unsigned short word_12; +typedef unsigned short word_16; +typedef long word_20; +typedef long word_32; + +#ifdef HAVE_STDINT_H +#define SIMPLE_64 +typedef int64_t word_64; +#else +typedef struct word_64 { + unsigned long hi, lo; +} word_64; +#endif + +typedef struct keystate_t { + short rows[9]; +} keystate_t; + +typedef struct display_t { + + int on; + + long disp_start; + long disp_end; + + int offset; + int lines; + int nibs_per_line; + + int contrast; + + long menu_start; + long menu_end; + + int annunc; + +} display_t; + +typedef struct mem_cntl_t { + unsigned short unconfigured; + word_20 config[2]; +} mem_cntl_t; + +typedef struct saturn_t { + + unsigned long magic; + char version[4]; + + unsigned char A[16], B[16], C[16], D[16]; + + word_20 d[2]; + +#define D0 d[0] +#define D1 d[1] + + word_4 P; + word_20 PC; + + unsigned char R0[16], R1[16], R2[16], R3[16], R4[16]; + unsigned char IN[4]; + unsigned char OUT[3]; + + word_1 CARRY; + + unsigned char PSTAT[NR_PSTAT]; + unsigned char XM, SB, SR, MP; + + word_4 hexmode; + + word_20 rstk[NR_RSTK]; + short rstkp; + + keystate_t keybuf; + + unsigned char intenable; + unsigned char int_pending; + unsigned char kbd_ien; + + word_4 disp_io; + + word_4 contrast_ctrl; + word_8 disp_test; + + word_16 crc; + + word_4 power_status; + word_4 power_ctrl; + + word_4 mode; + + word_8 annunc; + + word_4 baud; + + word_4 card_ctrl; + word_4 card_status; + + word_4 io_ctrl; + word_4 rcs; + word_4 tcs; + + word_8 rbr; + word_8 tbr; + + word_8 sreq; + + word_4 ir_ctrl; + + word_4 base_off; + + word_4 lcr; + word_4 lbr; + + word_4 scratch; + + word_4 base_nibble; + + word_20 disp_addr; + word_12 line_offset; + word_8 line_count; + + word_16 unknown; + + word_4 t1_ctrl; + word_4 t2_ctrl; + + word_20 menu_addr; + + word_8 unknown2; + + char timer1; /* may NOT be unsigned !!! */ + word_32 timer2; + + long t1_instr; + long t2_instr; + + short t1_tick; + short t2_tick; + long i_per_s; + + short bank_switch; + mem_cntl_t mem_cntl[NR_MCTL]; + + unsigned char *rom; + unsigned char *ram; + unsigned char *port1; + unsigned char *port2; + +} saturn_t; + +#define NIBBLES_PER_ROW 0x22 + +extern int got_alarm; + +extern int set_t1; +extern long sched_timer1; +extern long sched_timer2; + +extern int adj_time_pending; +extern long sched_adjtime; +extern long schedule_event; + +extern display_t display; +extern void init_display __ProtoType__((void)); + +extern saturn_t saturn; + +extern int exit_emulator __ProtoType__((void)); +extern int init_emulator __ProtoType__((void)); +extern void init_active_stuff __ProtoType__((void)); + +extern int serial_init __ProtoType__((void)); +extern void serial_baud __ProtoType__((int baud)); +extern void transmit_char __ProtoType__((void)); +extern void receive_char __ProtoType__((void)); + +extern void do_kbd_int __ProtoType__((void)); +extern void do_interupt __ProtoType__((void)); + +extern void (*write_nibble) __ProtoType__((long addr, int val)); +extern int (*read_nibble) __ProtoType__((long addr)); +extern int (*read_nibble_crc) __ProtoType__((long addr)); + +extern int emulate __ProtoType__((void)); +extern int step_instruction __ProtoType__((void)); +extern void schedule __ProtoType__((void)); + +extern int read_rom __ProtoType__((const char *fname)); +extern int read_files __ProtoType__((void)); +extern int write_files __ProtoType__((void)); + +extern void load_addr __ProtoType__((word_20 *dat, long addr, + int n)); +#endif /* !_HP48_H */ diff --git a/src/hp48_emu.h b/src/hp48_emu.h new file mode 100644 index 0000000..1ad82bd --- /dev/null +++ b/src/hp48_emu.h @@ -0,0 +1,202 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: hp48_emu.h,v $ + * Revision 1.10 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.9 1994/11/28 02:19:22 ecd + * removed progname declaration + * + * Revision 1.9 1994/11/28 02:19:22 ecd + * removed progname declaration + * + * Revision 1.8 1994/11/04 03:44:47 ecd + * wrxl + * + * Revision 1.7 1994/11/02 14:51:27 ecd + * minor changes + * + * Revision 1.6 1994/10/05 08:33:22 ecd + * deleted do_interupt definition + * + * Revision 1.5 1994/10/01 10:12:24 ecd + * deleted get_start and get_end functions + * + * Revision 1.4 1994/09/30 12:32:49 ecd + * changed display* routines + * + * Revision 1.3 1994/09/13 16:58:42 ecd + * changed to plain X11 + * + * Revision 1.2 1994/08/31 18:25:23 ecd + * some cleanup + * + * Revision 1.1 1994/08/26 11:09:18 ecd + * Initial revision + * + * + * + * $Id: hp48_emu.h,v 1.10 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#ifndef _HP48_EMU_H +#define _HP48_EMU_H 1 + +#include "global.h" + +#include + +#include "hp48.h" +extern Display *dpy; +extern Window dispW; +extern GC gc; + +extern void push_return_addr __ProtoType__((long addr)); +extern long pop_return_addr __ProtoType__((void)); + +extern void init_annunc __ProtoType__((void)); + +extern void init_saturn __ProtoType__((void)); + +extern void check_timer __ProtoType__((void)); + +extern void register_to_status __ProtoType__((unsigned char *r)); +extern void status_to_register __ProtoType__((unsigned char *r)); +extern void swap_register_status __ProtoType__((unsigned char *r)); +extern void clear_status __ProtoType__((void)); + +extern long read_nibbles __ProtoType__((long addr, int len)); +extern void write_nibbles __ProtoType__((long addr, long val, int len)); +extern void dev_memory_init __ProtoType__((void)); + +extern void set_program_stat __ProtoType__((int n)); +extern void clear_program_stat __ProtoType__((int n)); +extern int get_program_stat __ProtoType__((int n)); + +extern void set_hardware_stat __ProtoType__((int op)); +extern void clear_hardware_stat __ProtoType__((int op)); +extern int is_zero_hardware_stat __ProtoType__((int op)); + +extern void set_register_bit __ProtoType__((unsigned char *reg, int n)); +extern void clear_register_bit __ProtoType__((unsigned char *reg, int n)); +extern int get_register_bit __ProtoType__((unsigned char *reg, int n)); + +extern void set_register_nibble __ProtoType__((unsigned char *reg, int n, + unsigned char val)); +extern unsigned char get_register_nibble __ProtoType__((unsigned char *reg, int n)); + + +extern void register_to_address __ProtoType__((unsigned char *reg, + word_20 *dat, int s)); +extern void address_to_register __ProtoType__((word_20 dat, + unsigned char *reg, int s)); +extern void add_address __ProtoType__((word_20 *dat, int add)); + +extern char * make_hexstr __ProtoType__((long addr, int n)); +extern void load_constant __ProtoType__((unsigned char *reg, int n, + long addr)); +extern void load_address __ProtoType__((unsigned char *reg, long addr, + int n)); + +extern void store __ProtoType__((word_20 dat, unsigned char *reg, + int code)); +extern void store_n __ProtoType__((word_20 dat, unsigned char *reg, + int n)); +extern void recall __ProtoType__((unsigned char *reg, word_20 dat, + int code)); +extern void recall_n __ProtoType__((unsigned char *reg, word_20 dat, + int n)); + +extern long dat_to_addr __ProtoType__((unsigned char *dat)); +extern void addr_to_dat __ProtoType__((long addr, unsigned char *dat)); + +extern void do_in __ProtoType__((void)); +extern void do_reset __ProtoType__((void)); +extern void do_configure __ProtoType__((void)); +extern void do_unconfigure __ProtoType__((void)); +extern void do_inton __ProtoType__((void)); +extern void do_intoff __ProtoType__((void)); +extern void do_return_interupt __ProtoType__((void)); +extern void do_reset_interrupt_system __ProtoType__((void)); +extern void do_shutdown __ProtoType__((void)); +extern int get_identification __ProtoType__((void)); + +extern void add_p_plus_one __ProtoType__((unsigned char *r)); +extern void add_register_constant __ProtoType__((unsigned char *res, + int code, int val)); +extern void sub_register_constant __ProtoType__((unsigned char *res, + int code, int val)); +extern void add_register __ProtoType__((unsigned char *res, unsigned char *r1, + unsigned char *r2, int code)); +extern void sub_register __ProtoType__((unsigned char *res, unsigned char *r1, + unsigned char *r2, int code)); +extern void complement_2_register __ProtoType__((unsigned char *r, int code)); +extern void complement_1_register __ProtoType__((unsigned char *r, int code)); +extern void inc_register __ProtoType__((unsigned char *r, int code)); +extern void dec_register __ProtoType__((unsigned char *r, int code)); +extern void zero_register __ProtoType__((unsigned char *r, int code)); +extern void or_register __ProtoType__((unsigned char *res, unsigned char *r1, + unsigned char *r2, int code)); +extern void and_register __ProtoType__((unsigned char *res, unsigned char *r1, + unsigned char *r2, int code)); +extern void copy_register __ProtoType__((unsigned char *to, unsigned char *from, + int code)); +extern void exchange_register __ProtoType__((unsigned char *r1, unsigned char *r2, + int code)); + +extern void exchange_reg __ProtoType__((unsigned char *r, word_20 *d, int code)); + +extern void shift_left_register __ProtoType__((unsigned char *r, int code)); +extern void shift_left_circ_register __ProtoType__((unsigned char *r, int code)); +extern void shift_right_register __ProtoType__((unsigned char *r, int code)); +extern void shift_right_circ_register __ProtoType__((unsigned char *r, int code)); +extern void shift_right_bit_register __ProtoType__((unsigned char *r, int code)); +extern int is_zero_register __ProtoType__(( + unsigned char *r, + int code)); +extern int is_not_zero_register __ProtoType__(( + unsigned char *r, + int code)); +extern int is_equal_register __ProtoType__(( + unsigned char *r1, + unsigned char *r2, + int code)); +extern int is_not_equal_register __ProtoType__(( + unsigned char *r1, + unsigned char *r2, + int code)); +extern int is_less_register __ProtoType__(( + unsigned char *r1, + unsigned char *r2, + int code)); +extern int is_less_or_equal_register __ProtoType__(( + unsigned char *r1, + unsigned char *r2, + int code)); +extern int is_greater_register __ProtoType__(( + unsigned char *r1, + unsigned char *r2, + int code)); +extern int is_greater_or_equal_register __ProtoType__(( + unsigned char *r1, + unsigned char *r2, + int code)); + +#endif /* !_HP48_EMU_H */ diff --git a/src/hp48char.h b/src/hp48char.h new file mode 100644 index 0000000..b3b5efb --- /dev/null +++ b/src/hp48char.h @@ -0,0 +1,308 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: hp48char.h,v $ + * Revision 1.3 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.2 1994/12/07 20:16:41 ecd + * added comment at top of file + * + * Revision 1.2 1994/12/07 20:16:41 ecd + * added comment at top of file + * + * Revision 1.1 1994/12/07 10:16:15 ecd + * Initial revision + * + * + * $Id: hp48char.h,v 1.3 1995/01/11 18:20:01 ecd Exp ecd $ + */ +#ifndef _HP48CHAR_H +#define _HP48CHAR_H 1 + +typedef struct trans_tbl_t { + unsigned char hp48_char; + char *trans; +} trans_tbl_t; + +#ifndef DEFINE_TRANS_TABLE +extern trans_tbl_t hp48_trans_tbl[256]; +#else +trans_tbl_t hp48_trans_tbl[256] = +{ + { 0, "\\0" }, + { 1, "\\001" }, + { 2, "\\002" }, + { 3, "\\003" }, + { 4, "\\004" }, + { 5, "\\005" }, + { 6, "\\006" }, + { 7, "\\007" }, + { 8, "\\b" }, + { 9, "\\t" }, + { 10, "\\n" }, + { 11, "\\011" }, + { 12, "\\f" }, + { 13, "\\r" }, + { 14, "\\014" }, + { 15, "\\015" }, + { 16, "\\016" }, + { 17, "\\017" }, + { 18, "\\018" }, + { 19, "\\019" }, + { 20, "\\020" }, + { 21, "\\021" }, + { 22, "\\022" }, + { 23, "\\023" }, + { 24, "\\024" }, + { 25, "\\025" }, + { 26, "\\026" }, + { 27, "\\027" }, + { 28, "\\028" }, + { 29, "\\029" }, + { 30, "\\030" }, + { 31, "\\031" }, + { ' ', 0 }, + { '!', 0 }, + { '"', 0 }, + { '#', 0 }, + { '$', 0 }, + { '%', 0 }, + { '&', 0 }, + { '\'', 0 }, + { '(', 0 }, + { ')', 0 }, + { '*', 0 }, + { '+', 0 }, + { ',', 0 }, + { '-', 0 }, + { '.', 0 }, + { '/', 0 }, + { '0', 0 }, + { '1', 0 }, + { '2', 0 }, + { '3', 0 }, + { '4', 0 }, + { '5', 0 }, + { '6', 0 }, + { '7', 0 }, + { '8', 0 }, + { '9', 0 }, + { ':', 0 }, + { ';', 0 }, + { '<', 0 }, + { '=', 0 }, + { '>', 0 }, + { '?', 0 }, + { '@', 0 }, + { 'A', 0 }, + { 'B', 0 }, + { 'C', 0 }, + { 'D', 0 }, + { 'E', 0 }, + { 'F', 0 }, + { 'G', 0 }, + { 'H', 0 }, + { 'I', 0 }, + { 'J', 0 }, + { 'K', 0 }, + { 'L', 0 }, + { 'M', 0 }, + { 'N', 0 }, + { 'O', 0 }, + { 'P', 0 }, + { 'Q', 0 }, + { 'R', 0 }, + { 'S', 0 }, + { 'T', 0 }, + { 'U', 0 }, + { 'V', 0 }, + { 'W', 0 }, + { 'X', 0 }, + { 'Y', 0 }, + { 'Z', 0 }, + { '[', 0 }, + { '\\', 0 }, + { ']', 0 }, + { '^', 0 }, + { '_', 0 }, + { '`', 0 }, + { 'a', 0 }, + { 'b', 0 }, + { 'c', 0 }, + { 'd', 0 }, + { 'e', 0 }, + { 'f', 0 }, + { 'g', 0 }, + { 'h', 0 }, + { 'i', 0 }, + { 'j', 0 }, + { 'k', 0 }, + { 'l', 0 }, + { 'm', 0 }, + { 'n', 0 }, + { 'o', 0 }, + { 'p', 0 }, + { 'q', 0 }, + { 'r', 0 }, + { 's', 0 }, + { 't', 0 }, + { 'u', 0 }, + { 'v', 0 }, + { 'w', 0 }, + { 'x', 0 }, + { 'y', 0 }, + { 'z', 0 }, + { '{', 0 }, + { '|', 0 }, + { '}', 0 }, + { '~', 0 }, + { 127, "\\127" }, + { 128, "\\<)" }, + { 129, "\\x-" }, + { 130, "\\.V" }, + { 131, "\\v/" }, + { 132, "\\.S" }, + { 133, "\\GS" }, + { 134, "\\|>" }, + { 135, "\\pi" }, + { 136, "\\.d" }, + { 137, "\\<=" }, + { 138, "\\>=" }, + { 139, "\\=/" }, + { 140, "\\Ga" }, + { 141, "\\->" }, + { 142, "\\<-" }, + { 143, "\\|v" }, + { 144, "\\|^" }, + { 145, "\\Gg" }, + { 146, "\\Gd" }, + { 147, "\\Ge" }, + { 148, "\\Gn" }, + { 149, "\\Gh" }, + { 150, "\\Gl" }, + { 151, "\\Gr" }, + { 152, "\\Gs" }, + { 153, "\\Gt" }, + { 154, "\\Gw" }, + { 155, "\\GD" }, + { 156, "\\PI" }, + { 157, "\\GW" }, + { 158, "\\[]" }, + { 159, "\\oo" }, + { 160, "\\160" }, + { 161, "\\161" }, + { 162, "\\162" }, + { 163, "\\163" }, + { 164, "\\164" }, + { 165, "\\165" }, + { 166, "\\166" }, + { 167, "\\167" }, + { 168, "\\168" }, + { 169, "\\169" }, + { 170, "\\170" }, + { 171, "\\<<" }, + { 172, "\\172" }, + { 173, "\\173" }, + { 174, "\\174" }, + { 175, "\\175" }, + { 176, "\\^o" }, + { 177, "\\177" }, + { 178, "\\178" }, + { 179, "\\179" }, + { 180, "\\180" }, + { 181, "\\Gm" }, + { 182, "\\182" }, + { 183, "\\183" }, + { 184, "\\184" }, + { 185, "\\185" }, + { 186, "\\186" }, + { 187, "\\>>" }, + { 188, "\\188" }, + { 189, "\\189" }, + { 190, "\\190" }, + { 191, "\\191" }, + { 192, "\\192" }, + { 193, "\\193" }, + { 194, "\\194" }, + { 195, "\\195" }, + { 196, "\\196" }, + { 197, "\\197" }, + { 198, "\\198" }, + { 199, "\\199" }, + { 200, "\\200" }, + { 201, "\\201" }, + { 202, "\\202" }, + { 203, "\\203" }, + { 204, "\\204" }, + { 205, "\\205" }, + { 206, "\\206" }, + { 207, "\\207" }, + { 208, "\\208" }, + { 209, "\\209" }, + { 210, "\\210" }, + { 211, "\\211" }, + { 212, "\\212" }, + { 213, "\\213" }, + { 214, "\\214" }, + { 215, "\\.x" }, + { 216, "\\O/" }, + { 217, "\\217" }, + { 218, "\\218" }, + { 219, "\\219" }, + { 220, "\\220" }, + { 221, "\\221" }, + { 222, "\\222" }, + { 223, "\\223" }, + { 224, "\\224" }, + { 225, "\\225" }, + { 226, "\\226" }, + { 227, "\\227" }, + { 228, "\\228" }, + { 229, "\\229" }, + { 230, "\\230" }, + { 231, "\\231" }, + { 232, "\\232" }, + { 233, "\\233" }, + { 234, "\\234" }, + { 235, "\\235" }, + { 236, "\\236" }, + { 237, "\\237" }, + { 238, "\\238" }, + { 239, "\\239" }, + { 240, "\\240" }, + { 241, "\\241" }, + { 242, "\\242" }, + { 243, "\\243" }, + { 244, "\\244" }, + { 245, "\\245" }, + { 246, "\\246" }, + { 247, "\\:-" }, + { 248, "\\248" }, + { 249, "\\249" }, + { 250, "\\250" }, + { 251, "\\251" }, + { 252, "\\252" }, + { 253, "\\253" }, + { 254, "\\254" }, + { 255, "\\255" } +}; +#endif /* DEFINE_TRANS_TABLE */ + +#endif /* !_HP48CHAR_H */ diff --git a/src/icon.h b/src/icon.h new file mode 100644 index 0000000..426f869 --- /dev/null +++ b/src/icon.h @@ -0,0 +1,74 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: icon.h,v $ + * Revision 1.5 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.4 1994/11/28 02:19:22 ecd + * added stuff for color icon + * + * Revision 1.4 1994/11/28 02:19:22 ecd + * added stuff for color icon + * + * Revision 1.3 1994/11/02 14:51:27 ecd + * minor changes + * + * Revision 1.2 1994/10/06 16:28:03 ecd + * changed char to unsigned + * + * Revision 1.1 1994/09/07 12:53:20 ecd + * Initial revision + * + * + * $Id: icon.h,v 1.5 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#ifndef _ICON_H +#define _ICON_H 1 + +#include "bitmaps/hp48_icon.h" + +#include "bitmaps/hp48_top.h" + +#include "bitmaps/hp48_bottom.h" + +#include "bitmaps/hp48_logo.h" + +#include "bitmaps/hp48_text.h" + +#include "bitmaps/hp48_disp.h" + +#include "bitmaps/hp48_keys.h" + +#include "bitmaps/hp48_orange.h" + +#include "bitmaps/hp48_blue.h" + +#include "bitmaps/hp48_on.h" + +#include "bitmaps/hp48_top_gx.h" + +#include "bitmaps/hp48_logo_gx.h" + +#include "bitmaps/hp48_text_gx.h" + +#include "bitmaps/hp48_green_gx.h" + +#endif /* !_ICON_H */ diff --git a/src/init.c b/src/init.c new file mode 100644 index 0000000..f4308a4 --- /dev/null +++ b/src/init.c @@ -0,0 +1,1818 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: init.c,v $ + * Revision 1.13 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.12 1994/12/07 20:20:50 ecd + * minor fixes + * + * Revision 1.12 1994/12/07 20:20:50 ecd + * minor fixes + * + * Revision 1.11 1994/11/28 02:00:51 ecd + * deleted serial_init() from init_emulator + * changed handling of version numbers + * + * Revision 1.10 1994/11/04 03:42:34 ecd + * changed includes, doesn't depend on FILE_VERSION anymore + * + * Revision 1.9 1994/11/02 14:44:28 ecd + * support for "compressed" files added. + * + * Revision 1.8 1994/10/09 20:32:02 ecd + * deleted extern char lcd_buffer reference. + * + * Revision 1.7 1994/10/06 16:30:05 ecd + * changed char to unsigned + * + * Revision 1.6 1994/10/05 08:36:44 ecd + * changed saturn_config_init() + * + * Revision 1.5 1994/09/30 12:37:09 ecd + * the file ~/.hp48/hp48 now contains a MAGIC and version info, so + * backward compatibility can be achived + * + * Revision 1.4 1994/09/18 15:29:22 ecd + * turned off unused rcsid message + * + * Revision 1.3 1994/09/13 16:57:00 ecd + * changed to plain X11 + * + * Revision 1.2 1994/08/31 18:23:21 ecd + * changed display initialization. + * + * Revision 1.1 1994/08/26 11:09:02 ecd + * Initial revision + * + * $Id: init.c,v 1.13 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SUNOS +#include +#endif + +#include "hp48.h" +#include "hp48_emu.h" +#include "device.h" +#include "resources.h" +#include "romio.h" + +#define X48_MAGIC 0x48503438 +#define NR_CONFIG 8 + +short rom_is_new = 1; +long ram_size; +long port1_size; +long port1_mask; +short port1_is_ram; +long port2_size; +long port2_mask; +short port2_is_ram; + +typedef struct old_keystate_t { + int rows[9]; +} old_keystate_t; + +typedef struct old_saturn_t { + unsigned char A[16], B[16], C[16], D[16]; + long d[2]; + int P; + long PC; + unsigned char R0[16], R1[16], R2[16], R3[16], R4[16]; + unsigned char IN[4]; + unsigned char OUT[3]; + int CARRY; + unsigned char PSTAT[NR_PSTAT]; + unsigned char XM, SB, SR, MP; + unsigned char hexmode; + long rstk[NR_RSTK]; + short rstkp; + old_keystate_t keybuf; + unsigned char intenable; + unsigned char int_pending; + unsigned char kbd_ien; + long configs[NR_CONFIG]; + short daisy_state; + long ram32k; + long devices; + unsigned char disp_io; + unsigned char contrast_ctrl; + unsigned char disp_test; + unsigned int crc; + unsigned char power_status; + unsigned char power_ctrl; + unsigned char mode; + unsigned char annunc; + unsigned char baud; + unsigned char card_ctrl; + unsigned char card_status; + unsigned char io_ctrl; + unsigned char rcs; + unsigned char tcs; + unsigned char rbr; + unsigned char tbr; + unsigned char sreq; + unsigned char ir_ctrl; + unsigned char base_off; + unsigned char lcr; + unsigned char lbr; + unsigned char scratch; + unsigned char base_nibble; + long disp_addr; + long line_offset; + long line_count; + long unknown; + unsigned char t1_ctrl; + unsigned char t2_ctrl; + long menu_addr; + long unknown2; + int timer1; + long timer2; + long t1_instr; + long t2_instr; + unsigned char *rom; + unsigned char *ram; + unsigned char *port1; + unsigned char *port2; +} old_saturn_t; + +old_saturn_t old_saturn; + +typedef struct saturn_0_3_0_t { + unsigned long magic; + char version[4]; + unsigned char A[16], B[16], C[16], D[16]; + word_20 d[2]; + word_4 P; + word_20 PC; + unsigned char R0[16], R1[16], R2[16], R3[16], R4[16]; + unsigned char IN[4]; + unsigned char OUT[3]; + word_1 CARRY; + unsigned char PSTAT[NR_PSTAT]; + unsigned char XM, SB, SR, MP; + word_4 hexmode; + word_20 rstk[NR_RSTK]; + short rstkp; + keystate_t keybuf; + unsigned char intenable; + unsigned char int_pending; + unsigned char kbd_ien; + word_20 configs[NR_CONFIG]; + word_16 daisy_state; + word_20 ram32k; + word_20 devices; + word_4 disp_io; + word_4 contrast_ctrl; + word_8 disp_test; + word_16 crc; + word_4 power_status; + word_4 power_ctrl; + word_4 mode; + word_8 annunc; + word_4 baud; + word_4 card_ctrl; + word_4 card_status; + word_4 io_ctrl; + word_4 rcs; + word_4 tcs; + word_8 rbr; + word_8 tbr; + word_8 sreq; + word_4 ir_ctrl; + word_4 base_off; + word_4 lcr; + word_4 lbr; + word_4 scratch; + word_4 base_nibble; + word_20 disp_addr; + word_12 line_offset; + word_8 line_count; + word_16 unknown; + word_4 t1_ctrl; + word_4 t2_ctrl; + word_20 menu_addr; + word_8 unknown2; + char timer1; + word_32 timer2; + long t1_instr; + long t2_instr; + short t1_tick; + short t2_tick; + long i_per_s; + unsigned char *rom; + unsigned char *ram; + unsigned char *port1; + unsigned char *port2; +} saturn_0_3_0_t; + +saturn_0_3_0_t saturn_0_3_0; + +#include "config.h" + +void +#ifdef __FunctionProto__ +saturn_config_init(void) +#else +saturn_config_init() +#endif +{ + saturn.version[0] = VERSION_MAJOR; + saturn.version[1] = VERSION_MINOR; + saturn.version[2] = PATCHLEVEL; + saturn.version[3] = COMPILE_VERSION; + memset(&device, 0, sizeof(device)); + device.display_touched = 1; + device.contrast_touched = 1; + device.baud_touched = 1; + device.ann_touched = 1; + saturn.rcs = 0x0; + saturn.tcs = 0x0; + saturn.lbr = 0x0; +} + +void +#ifdef __FunctionProto__ +init_saturn(void) +#else +init_saturn() +#endif +{ + int i; + + memset(&saturn, 0, sizeof(saturn) - 4 * sizeof(unsigned char *)); + saturn.PC = 0x00000; + saturn.magic = X48_MAGIC; + saturn.t1_tick = 8192; + saturn.t2_tick = 16; + saturn.i_per_s = 0; + saturn.version[0] = VERSION_MAJOR; + saturn.version[1] = VERSION_MINOR; + saturn.version[2] = PATCHLEVEL; + saturn.version[3] = COMPILE_VERSION; + saturn.hexmode = HEX; + saturn.rstkp = -1; + saturn.intenable = 1; + saturn.int_pending = 0; + saturn.kbd_ien = 1; + saturn.timer1 = 0; + saturn.timer2 = 0x2000; + saturn.bank_switch = 0; + for (i = 0; i < NR_MCTL; i++) + { + if (i == 0) + saturn.mem_cntl[i].unconfigured = 1; + else if (i == 5) + saturn.mem_cntl[i].unconfigured = 0; + else + saturn.mem_cntl[i].unconfigured = 2; + saturn.mem_cntl[i].config[0] = 0; + saturn.mem_cntl[i].config[1] = 0; + } + dev_memory_init(); +} + +void +#ifdef __FunctionProto__ +copy_old_saturn(old_saturn_t *old, saturn_t *new) +#else +copy_old_saturn(old, new) +old_saturn_t *old; +saturn_t *new; +#endif +{ + int i; + + memcpy(&(new->A[0]), &(old->A[0]), 16); + memcpy(&(new->B[0]), &(old->B[0]), 16); + memcpy(&(new->C[0]), &(old->C[0]), 16); + memcpy(&(new->D[0]), &(old->D[0]), 16); + new->d[0] = old->d[0]; + new->d[1] = old->d[1]; + new->P = old->P; + new->PC = old->PC; + memcpy(&(new->R0[0]), &(old->R0[0]), 16); + memcpy(&(new->R1[0]), &(old->R1[0]), 16); + memcpy(&(new->R2[0]), &(old->R2[0]), 16); + memcpy(&(new->R3[0]), &(old->R3[0]), 16); + memcpy(&(new->R4[0]), &(old->R4[0]), 16); + memcpy(&(new->IN[0]), &(old->IN[0]), 4); + memcpy(&(new->OUT[0]), &(old->OUT[0]), 3); + new->CARRY = old->CARRY; + memcpy(&(new->PSTAT[0]), &(old->PSTAT[0]), NR_PSTAT); + new->XM = old->XM; + new->SB = old->SB; + new->SR = old->SR; + new->MP = old->MP; + new->hexmode = old->hexmode; + memcpy(&(new->rstk[0]), &(old->rstk[0]), NR_RSTK * sizeof(word_20)); + new->rstkp = old->rstkp; + for (i = 0; i < 9; i++) { + new->keybuf.rows[i] = old->keybuf.rows[i]; + } + new->intenable = old->intenable; + new->int_pending = old->int_pending; + new->kbd_ien = old->kbd_ien; + new->disp_io = old->disp_io; + new->contrast_ctrl = old->contrast_ctrl; + new->disp_test = old->disp_test; + new->crc = old->crc; + new->power_status = old->power_status; + new->power_ctrl = old->power_ctrl; + new->mode = old->mode; + new->annunc = old->annunc; + new->baud = old->baud; + new->card_ctrl = old->card_ctrl; + new->card_status = old->card_status; + new->io_ctrl = old->io_ctrl; + new->rcs = old->rcs; + new->tcs = old->tcs; + new->rbr = old->rbr; + new->tbr = old->tbr; + new->sreq = old->sreq; + new->ir_ctrl = old->ir_ctrl; + new->base_off = old->base_off; + new->lcr = old->lcr; + new->lbr = old->lbr; + new->scratch = old->scratch; + new->base_nibble = old->base_nibble; + new->disp_addr = old->disp_addr; + new->line_offset = old->line_offset; + new->line_count = old->line_count; + new->unknown = old->unknown; + new->t1_ctrl = old->t1_ctrl; + new->t2_ctrl = old->t2_ctrl; + new->menu_addr = old->menu_addr; + new->unknown2 = old->unknown2; + new->timer1 = old->timer1; + new->timer2 = old->timer2; + new->t1_instr = old->t1_instr; + new->t2_instr = old->t2_instr; + new->bank_switch = 0; + if (opt_gx) + { + new->mem_cntl[0].unconfigured = 0; + new->mem_cntl[0].config[0] = 0x00100; + new->mem_cntl[1].unconfigured = 0; + new->mem_cntl[1].config[0] = 0x80000; + new->mem_cntl[1].config[1] = 0xc0000; + new->mem_cntl[2].unconfigured = 0; + new->mem_cntl[2].config[0] = 0x7f000; + new->mem_cntl[2].config[1] = 0xff000; + new->mem_cntl[3].unconfigured = 0; + new->mem_cntl[3].config[0] = 0xc0000; + new->mem_cntl[3].config[1] = 0xc0000; + new->mem_cntl[4].unconfigured = 0; + new->mem_cntl[4].config[0] = 0xc0000; + new->mem_cntl[4].config[1] = 0xc0000; + new->mem_cntl[5].unconfigured = 0; + new->mem_cntl[5].config[0] = 0x00000; + new->mem_cntl[5].config[1] = 0x00000; + } + else + { + if (old->devices == 0x100) + { + new->mem_cntl[0].unconfigured = 0; + new->mem_cntl[0].config[0] = old->devices; + } + else + { + new->mem_cntl[0].unconfigured = 1; + new->mem_cntl[0].config[0] = 0x00000; + } + if (old->ram32k == 0x70000) + { + new->mem_cntl[1].unconfigured = 0; + new->mem_cntl[1].config[0] = 0x70000; + new->mem_cntl[1].config[1] = 0xf0000; + } + else if (old->ram32k == 0xf0000) + { + new->mem_cntl[1].unconfigured = 0; + new->mem_cntl[1].config[0] = 0xf0000; + new->mem_cntl[1].config[1] = 0xf0000; + } + else if (old->ram32k == 0xfc000) + { + new->mem_cntl[1].unconfigured = 0; + new->mem_cntl[1].config[0] = 0x70000; + new->mem_cntl[1].config[1] = 0xfc000; + } + else if (old->ram32k == 0xfe000) + { + new->mem_cntl[1].unconfigured = 0; + new->mem_cntl[1].config[0] = 0x70000; + new->mem_cntl[1].config[1] = 0xfe000; + } + else + { + new->mem_cntl[1].unconfigured = 2; + new->mem_cntl[1].config[0] = 0x00000; + new->mem_cntl[1].config[1] = 0x00000; + } + new->mem_cntl[2].unconfigured = 0; + new->mem_cntl[2].config[0] = 0x80000; + new->mem_cntl[2].config[1] = 0xc0000; + new->mem_cntl[3].unconfigured = 0; + new->mem_cntl[3].config[0] = 0xc0000; + new->mem_cntl[3].config[1] = 0xc0000; + new->mem_cntl[4].unconfigured = 0; + new->mem_cntl[4].config[0] = 0xd0000; + new->mem_cntl[4].config[1] = 0xff000; + new->mem_cntl[5].unconfigured = 0; + new->mem_cntl[5].config[0] = 0x00000; + new->mem_cntl[5].config[1] = 0x80000; + } +} + +void +#ifdef __FunctionProto__ +copy_0_3_0_saturn(saturn_0_3_0_t *old, saturn_t *new) +#else +copy_0_3_0_saturn(old, new) +saturn_0_3_0_t *old; +saturn_t *new; +#endif +{ + int i; + + memcpy(&(new->A[0]), &(old->A[0]), 16); + memcpy(&(new->B[0]), &(old->B[0]), 16); + memcpy(&(new->C[0]), &(old->C[0]), 16); + memcpy(&(new->D[0]), &(old->D[0]), 16); + new->d[0] = old->d[0]; + new->d[1] = old->d[1]; + new->P = old->P; + new->PC = old->PC; + memcpy(&(new->R0[0]), &(old->R0[0]), 16); + memcpy(&(new->R1[0]), &(old->R1[0]), 16); + memcpy(&(new->R2[0]), &(old->R2[0]), 16); + memcpy(&(new->R3[0]), &(old->R3[0]), 16); + memcpy(&(new->R4[0]), &(old->R4[0]), 16); + memcpy(&(new->IN[0]), &(old->IN[0]), 4); + memcpy(&(new->OUT[0]), &(old->OUT[0]), 3); + new->CARRY = old->CARRY; + memcpy(&(new->PSTAT[0]), &(old->PSTAT[0]), NR_PSTAT); + new->XM = old->XM; + new->SB = old->SB; + new->SR = old->SR; + new->MP = old->MP; + new->hexmode = old->hexmode; + memcpy(&(new->rstk[0]), &(old->rstk[0]), NR_RSTK * sizeof(word_20)); + new->rstkp = old->rstkp; + for (i = 0; i < 9; i++) { + new->keybuf.rows[i] = old->keybuf.rows[i]; + } + new->intenable = old->intenable; + new->int_pending = old->int_pending; + new->kbd_ien = old->kbd_ien; + new->disp_io = old->disp_io; + new->contrast_ctrl = old->contrast_ctrl; + new->disp_test = old->disp_test; + new->crc = old->crc; + new->power_status = old->power_status; + new->power_ctrl = old->power_ctrl; + new->mode = old->mode; + new->annunc = old->annunc; + new->baud = old->baud; + new->card_ctrl = old->card_ctrl; + new->card_status = old->card_status; + new->io_ctrl = old->io_ctrl; + new->rcs = old->rcs; + new->tcs = old->tcs; + new->rbr = old->rbr; + new->tbr = old->tbr; + new->sreq = old->sreq; + new->ir_ctrl = old->ir_ctrl; + new->base_off = old->base_off; + new->lcr = old->lcr; + new->lbr = old->lbr; + new->scratch = old->scratch; + new->base_nibble = old->base_nibble; + new->disp_addr = old->disp_addr; + new->line_offset = old->line_offset; + new->line_count = old->line_count; + new->unknown = old->unknown; + new->t1_ctrl = old->t1_ctrl; + new->t2_ctrl = old->t2_ctrl; + new->menu_addr = old->menu_addr; + new->unknown2 = old->unknown2; + new->timer1 = old->timer1; + new->timer2 = old->timer2; + new->t1_instr = old->t1_instr; + new->t2_instr = old->t2_instr; + new->t1_tick = old->t1_tick; + new->t2_tick = old->t2_tick; + new->i_per_s = old->i_per_s; + new->bank_switch = 0; + if (opt_gx) + { + new->mem_cntl[0].unconfigured = 0; + new->mem_cntl[0].config[0] = 0x00100; + new->mem_cntl[1].unconfigured = 0; + new->mem_cntl[1].config[0] = 0x80000; + new->mem_cntl[1].config[1] = 0xc0000; + new->mem_cntl[2].unconfigured = 0; + new->mem_cntl[2].config[0] = 0x7f000; + new->mem_cntl[2].config[1] = 0xff000; + new->mem_cntl[3].unconfigured = 0; + new->mem_cntl[3].config[0] = 0xc0000; + new->mem_cntl[3].config[1] = 0xc0000; + new->mem_cntl[4].unconfigured = 0; + new->mem_cntl[4].config[0] = 0xc0000; + new->mem_cntl[4].config[1] = 0xc0000; + new->mem_cntl[5].unconfigured = 0; + new->mem_cntl[5].config[0] = 0x00000; + new->mem_cntl[5].config[1] = 0x00000; + } + else + { + if (old->devices == 0x100) + { + new->mem_cntl[0].unconfigured = 0; + new->mem_cntl[0].config[0] = old->devices; + } + else + { + new->mem_cntl[0].unconfigured = 1; + new->mem_cntl[0].config[0] = 0x00000; + } + if (old->ram32k == 0x70000) + { + new->mem_cntl[1].unconfigured = 0; + new->mem_cntl[1].config[0] = 0x70000; + new->mem_cntl[1].config[1] = 0xf0000; + } + else if (old->ram32k == 0xf0000) + { + new->mem_cntl[1].unconfigured = 0; + new->mem_cntl[1].config[0] = 0xf0000; + new->mem_cntl[1].config[1] = 0xf0000; + } + else if (old->ram32k == 0xfc000) + { + new->mem_cntl[1].unconfigured = 0; + new->mem_cntl[1].config[0] = 0x70000; + new->mem_cntl[1].config[1] = 0xfc000; + } + else if (old->ram32k == 0xfe000) + { + new->mem_cntl[1].unconfigured = 0; + new->mem_cntl[1].config[0] = 0x70000; + new->mem_cntl[1].config[1] = 0xfe000; + } + else + { + new->mem_cntl[1].unconfigured = 2; + new->mem_cntl[1].config[0] = 0x00000; + new->mem_cntl[1].config[1] = 0x00000; + } + new->mem_cntl[2].unconfigured = 0; + new->mem_cntl[2].config[0] = 0x80000; + new->mem_cntl[2].config[1] = 0xc0000; + new->mem_cntl[3].unconfigured = 0; + new->mem_cntl[3].config[0] = 0xc0000; + new->mem_cntl[3].config[1] = 0xc0000; + new->mem_cntl[4].unconfigured = 0; + new->mem_cntl[4].config[0] = 0xd0000; + new->mem_cntl[4].config[1] = 0xff000; + new->mem_cntl[5].unconfigured = 0; + new->mem_cntl[5].config[0] = 0x00000; + new->mem_cntl[5].config[1] = 0x80000; + } +} + +int +#ifdef __FunctionProto__ +read_8(FILE *fp, word_8 *var) +#else +read_8(fp, var) +FILE *fp; +word_8 *var; +#endif +{ + unsigned char tmp; + + if (fread(&tmp, 1, 1, fp) != 1) { + if (!quiet) + fprintf(stderr, "%s: can\'t read word_8\n", progname); + return 0; + } + *var = tmp; + return 1; +} + +int +#ifdef __FunctionProto__ +read_char(FILE *fp, char *var) +#else +read_char(fp, var) +FILE *fp; +char *var; +#endif +{ + char tmp; + + if (fread(&tmp, 1, 1, fp) != 1) { + if (!quiet) + fprintf(stderr, "%s: can\'t read char\n", progname); + return 0; + } + *var = tmp; + return 1; +} + +int +#ifdef __FunctionProto__ +read_16(FILE *fp, word_16 *var) +#else +read_16(fp, var) +FILE *fp; +word_16 *var; +#endif +{ + unsigned char tmp[2]; + + if (fread(&tmp[0], 1, 2, fp) != 2) { + if (!quiet) + fprintf(stderr, "%s: can\'t read word_16\n", progname); + return 0; + } + *var = tmp[0] << 8; + *var |= tmp[1]; + return 1; +} + +int +#ifdef __FunctionProto__ +read_32(FILE *fp, word_32 *var) +#else +read_32(fp, var) +FILE *fp; +word_32 *var; +#endif +{ + unsigned char tmp[4]; + + if (fread(&tmp[0], 1, 4, fp) != 4) { + if (!quiet) + fprintf(stderr, "%s: can\'t read word_32\n", progname); + return 0; + } + *var = tmp[0] << 24; + *var |= tmp[1] << 16; + *var |= tmp[2] << 8; + *var |= tmp[3]; + return 1; +} + +int +#ifdef __FunctionProto__ +read_u_long(FILE *fp, unsigned long *var) +#else +read_u_long(fp, var) +FILE *fp; +unsigned long*var; +#endif +{ + unsigned char tmp[4]; + + if (fread(&tmp[0], 1, 4, fp) != 4) { + if (!quiet) + fprintf(stderr, "%s: can\'t read unsigned long\n", progname); + return 0; + } + *var = tmp[0] << 24; + *var |= tmp[1] << 16; + *var |= tmp[2] << 8; + *var |= tmp[3]; + return 1; +} + +int +#ifdef __FunctionProto__ +read_version_0_3_0_file(FILE *fp) +#else +read_version_0_3_0_file(fp) +FILE *fp; +#endif +{ + int i; + + /* + * version 0.3.x, read in the saturn_0_3_0_t struct + */ + for (i = 0; i < 16; i++) + if(!read_8(fp, &saturn_0_3_0.A[i])) + return 0; + for (i = 0; i < 16; i++) + if (!read_8(fp, &saturn_0_3_0.B[i])) + return 0; + for (i = 0; i < 16; i++) + if (!read_8(fp, &saturn_0_3_0.C[i])) + return 0; + for (i = 0; i < 16; i++) + if (!read_8(fp, &saturn_0_3_0.D[i])) + return 0; + if (!read_32(fp, &saturn_0_3_0.d[0])) return 0; + if (!read_32(fp, &saturn_0_3_0.d[1])) return 0; + if (!read_8(fp, &saturn_0_3_0.P)) return 0; + if (!read_32(fp, &saturn_0_3_0.PC)) return 0; + for (i = 0; i < 16; i++) + if (!read_8(fp, &saturn_0_3_0.R0[i])) + return 0; + for (i = 0; i < 16; i++) + if (!read_8(fp, &saturn_0_3_0.R1[i])) + return 0; + for (i = 0; i < 16; i++) + if (!read_8(fp, &saturn_0_3_0.R2[i])) + return 0; + for (i = 0; i < 16; i++) + if (!read_8(fp, &saturn_0_3_0.R3[i])) + return 0; + for (i = 0; i < 16; i++) + if (!read_8(fp, &saturn_0_3_0.R4[i])) + return 0; + for (i = 0; i < 4; i++) + if (!read_8(fp, &saturn_0_3_0.IN[i])) + return 0; + for (i = 0; i < 3; i++) + if (!read_8(fp, &saturn_0_3_0.OUT[i])) + return 0; + if (!read_8(fp, &saturn_0_3_0.CARRY)) + return 0; + for (i = 0; i < NR_PSTAT; i++) + if (!read_8(fp, &saturn_0_3_0.PSTAT[i])) + return 0; + if (!read_8(fp, &saturn_0_3_0.XM)) return 0; + if (!read_8(fp, &saturn_0_3_0.SB)) return 0; + if (!read_8(fp, &saturn_0_3_0.SR)) return 0; + if (!read_8(fp, &saturn_0_3_0.MP)) return 0; + if (!read_8(fp, &saturn_0_3_0.hexmode)) return 0; + for (i = 0; i < NR_RSTK; i++) + if (!read_32(fp, &saturn_0_3_0.rstk[i])) + return 0; + if (!read_16(fp, (word_16 *)&saturn_0_3_0.rstkp)) return 0; + for (i = 0; i < 9; i++) + if (!read_16(fp, (word_16 *)&saturn_0_3_0.keybuf.rows[i])) + return 0; + if (!read_8(fp, &saturn_0_3_0.intenable)) return 0; + if (!read_8(fp, &saturn_0_3_0.int_pending)) return 0; + if (!read_8(fp, &saturn_0_3_0.kbd_ien)) return 0; + for (i = 0; i < NR_CONFIG; i++) + if (!read_32(fp, &saturn_0_3_0.configs[i])) + return 0; + if (!read_16(fp, (word_16 *)&saturn_0_3_0.daisy_state)) return 0; + if (!read_32(fp, &saturn_0_3_0.ram32k)) return 0; + if (!read_32(fp, &saturn_0_3_0.devices)) return 0; + if (!read_8(fp, &saturn_0_3_0.disp_io)) return 0; + if (!read_8(fp, &saturn_0_3_0.contrast_ctrl)) return 0; + if (!read_8(fp, &saturn_0_3_0.disp_test)) return 0; + if (!read_16(fp, &saturn_0_3_0.crc)) return 0; + if (!read_8(fp, &saturn_0_3_0.power_status)) return 0; + if (!read_8(fp, &saturn_0_3_0.power_ctrl)) return 0; + if (!read_8(fp, &saturn_0_3_0.mode)) return 0; + if (!read_8(fp, &saturn_0_3_0.annunc)) return 0; + if (!read_8(fp, &saturn_0_3_0.baud)) return 0; + if (!read_8(fp, &saturn_0_3_0.card_ctrl)) return 0; + if (!read_8(fp, &saturn_0_3_0.card_status)) return 0; + if (!read_8(fp, &saturn_0_3_0.io_ctrl)) return 0; + if (!read_8(fp, &saturn_0_3_0.rcs)) return 0; + if (!read_8(fp, &saturn_0_3_0.tcs)) return 0; + if (!read_8(fp, &saturn_0_3_0.rbr)) return 0; + if (!read_8(fp, &saturn_0_3_0.tbr)) return 0; + if (!read_8(fp, &saturn_0_3_0.sreq)) return 0; + if (!read_8(fp, &saturn_0_3_0.ir_ctrl)) return 0; + if (!read_8(fp, &saturn_0_3_0.base_off)) return 0; + if (!read_8(fp, &saturn_0_3_0.lcr)) return 0; + if (!read_8(fp, &saturn_0_3_0.lbr)) return 0; + if (!read_8(fp, &saturn_0_3_0.scratch)) return 0; + if (!read_8(fp, &saturn_0_3_0.base_nibble)) return 0; + if (!read_32(fp, &saturn_0_3_0.disp_addr)) return 0; + if (!read_16(fp, &saturn_0_3_0.line_offset)) return 0; + if (!read_8(fp, &saturn_0_3_0.line_count)) return 0; + if (!read_16(fp, &saturn_0_3_0.unknown)) return 0; + if (!read_8(fp, &saturn_0_3_0.t1_ctrl)) return 0; + if (!read_8(fp, &saturn_0_3_0.t2_ctrl)) return 0; + if (!read_32(fp, &saturn_0_3_0.menu_addr)) return 0; + if (!read_8(fp, &saturn_0_3_0.unknown2)) return 0; + if (!read_char(fp, &saturn_0_3_0.timer1)) return 0; + if (!read_32(fp, &saturn_0_3_0.timer2)) return 0; + if (!read_32(fp, &saturn_0_3_0.t1_instr)) return 0; + if (!read_32(fp, &saturn_0_3_0.t2_instr)) return 0; + if (!read_16(fp, (word_16 *)&saturn_0_3_0.t1_tick)) return 0; + if (!read_16(fp, (word_16 *)&saturn_0_3_0.t2_tick)) return 0; + if (!read_32(fp, &saturn_0_3_0.i_per_s)) return 0; + return 1; +} + +int +#ifdef __FunctionProto__ +read_version_0_4_0_file(FILE *fp) +#else +read_version_0_4_0_file(fp) +FILE *fp; +#endif +{ + int i; + + /* + * version 0.4.x, read in the saturn_t struct + */ + for (i = 0; i < 16; i++) + if(!read_8(fp, &saturn.A[i])) + return 0; + for (i = 0; i < 16; i++) + if (!read_8(fp, &saturn.B[i])) + return 0; + for (i = 0; i < 16; i++) + if (!read_8(fp, &saturn.C[i])) + return 0; + for (i = 0; i < 16; i++) + if (!read_8(fp, &saturn.D[i])) + return 0; + if (!read_32(fp, &saturn.d[0])) return 0; + if (!read_32(fp, &saturn.d[1])) return 0; + if (!read_8(fp, &saturn.P)) return 0; + if (!read_32(fp, &saturn.PC)) return 0; + for (i = 0; i < 16; i++) + if (!read_8(fp, &saturn.R0[i])) + return 0; + for (i = 0; i < 16; i++) + if (!read_8(fp, &saturn.R1[i])) + return 0; + for (i = 0; i < 16; i++) + if (!read_8(fp, &saturn.R2[i])) + return 0; + for (i = 0; i < 16; i++) + if (!read_8(fp, &saturn.R3[i])) + return 0; + for (i = 0; i < 16; i++) + if (!read_8(fp, &saturn.R4[i])) + return 0; + for (i = 0; i < 4; i++) + if (!read_8(fp, &saturn.IN[i])) + return 0; + for (i = 0; i < 3; i++) + if (!read_8(fp, &saturn.OUT[i])) + return 0; + if (!read_8(fp, &saturn.CARRY)) + return 0; + for (i = 0; i < NR_PSTAT; i++) + if (!read_8(fp, &saturn.PSTAT[i])) + return 0; + if (!read_8(fp, &saturn.XM)) return 0; + if (!read_8(fp, &saturn.SB)) return 0; + if (!read_8(fp, &saturn.SR)) return 0; + if (!read_8(fp, &saturn.MP)) return 0; + if (!read_8(fp, &saturn.hexmode)) return 0; + for (i = 0; i < NR_RSTK; i++) + if (!read_32(fp, &saturn.rstk[i])) + return 0; + if (!read_16(fp, (word_16 *)&saturn.rstkp)) return 0; + for (i = 0; i < 9; i++) + if (!read_16(fp, (word_16 *)&saturn.keybuf.rows[i])) + return 0; + if (!read_8(fp, &saturn.intenable)) return 0; + if (!read_8(fp, &saturn.int_pending)) return 0; + if (!read_8(fp, &saturn.kbd_ien)) return 0; + if (!read_8(fp, &saturn.disp_io)) return 0; + if (!read_8(fp, &saturn.contrast_ctrl)) return 0; + if (!read_8(fp, &saturn.disp_test)) return 0; + if (!read_16(fp, &saturn.crc)) return 0; + if (!read_8(fp, &saturn.power_status)) return 0; + if (!read_8(fp, &saturn.power_ctrl)) return 0; + if (!read_8(fp, &saturn.mode)) return 0; + if (!read_8(fp, &saturn.annunc)) return 0; + if (!read_8(fp, &saturn.baud)) return 0; + if (!read_8(fp, &saturn.card_ctrl)) return 0; + if (!read_8(fp, &saturn.card_status)) return 0; + if (!read_8(fp, &saturn.io_ctrl)) return 0; + if (!read_8(fp, &saturn.rcs)) return 0; + if (!read_8(fp, &saturn.tcs)) return 0; + if (!read_8(fp, &saturn.rbr)) return 0; + if (!read_8(fp, &saturn.tbr)) return 0; + if (!read_8(fp, &saturn.sreq)) return 0; + if (!read_8(fp, &saturn.ir_ctrl)) return 0; + if (!read_8(fp, &saturn.base_off)) return 0; + if (!read_8(fp, &saturn.lcr)) return 0; + if (!read_8(fp, &saturn.lbr)) return 0; + if (!read_8(fp, &saturn.scratch)) return 0; + if (!read_8(fp, &saturn.base_nibble)) return 0; + if (!read_32(fp, &saturn.disp_addr)) return 0; + if (!read_16(fp, &saturn.line_offset)) return 0; + if (!read_8(fp, &saturn.line_count)) return 0; + if (!read_16(fp, &saturn.unknown)) return 0; + if (!read_8(fp, &saturn.t1_ctrl)) return 0; + if (!read_8(fp, &saturn.t2_ctrl)) return 0; + if (!read_32(fp, &saturn.menu_addr)) return 0; + if (!read_8(fp, &saturn.unknown2)) return 0; + if (!read_char(fp, &saturn.timer1)) return 0; + if (!read_32(fp, &saturn.timer2)) return 0; + if (!read_32(fp, &saturn.t1_instr)) return 0; + if (!read_32(fp, &saturn.t2_instr)) return 0; + if (!read_16(fp, (word_16 *)&saturn.t1_tick)) return 0; + if (!read_16(fp, (word_16 *)&saturn.t2_tick)) return 0; + if (!read_32(fp, &saturn.i_per_s)) return 0; + if (!read_16(fp, (word_16 *)&saturn.bank_switch)) return 0; + for (i = 0; i < NR_MCTL; i++) + { + if (!read_16(fp, &saturn.mem_cntl[i].unconfigured)) return 0; + if (!read_32(fp, &saturn.mem_cntl[i].config[0])) return 0; + if (!read_32(fp, &saturn.mem_cntl[i].config[1])) return 0; + } + return 1; +} + +int +#ifdef __FunctionProto__ +read_mem_file(char *name, word_4 *mem, int size) +#else +read_mem_file(name, mem, size) +char *name; +word_4 *mem; +int size; +#endif +{ + struct stat st; + FILE *fp; + word_8 *tmp_mem; + word_8 byte; + int i, j; + + if (NULL == (fp = fopen(name, "r"))) + { + if (!quiet) + fprintf(stderr, "%s: can\'t open %s\n", progname, name); + return 0; + } + + if (stat(name, &st) < 0) + { + if (!quiet) + fprintf(stderr, "%s: can\'t stat %s\n", progname, name); + return 0; + } + + if (st.st_size == size) + { + /* + * size is same as memory size, old version file + */ + if (fread(mem, 1, (size_t)size, fp) != size) + { + if (!quiet) + fprintf(stderr, "%s: can\'t read %s\n", progname, name); + fclose(fp); + return 0; + } + } + else + { + /* + * size is different, check size and decompress memory + */ + + if (st.st_size != size / 2) + { + if (!quiet) + fprintf(stderr, "%s: strange size %s, expected %d, found %ld\n", + progname, name, size / 2, st.st_size); + fclose(fp); + return 0; + } + + if (NULL == (tmp_mem = (word_8 *)malloc((size_t)st.st_size))) + { + for (i = 0, j = 0; i < size / 2; i++) + { + if (1 != fread(&byte, 1, 1, fp)) + { + if (!quiet) + fprintf(stderr, "%s: can\'t read %s\n", progname, name); + fclose(fp); + return 0; + } + mem[j++] = (word_4)((int)byte & 0xf); + mem[j++] = (word_4)(((int)byte >> 4) & 0xf); + } + } + else + { + if (fread(tmp_mem, 1, (size_t)size / 2, fp) != size / 2) + { + if (!quiet) + fprintf(stderr, "%s: can\'t read %s\n", progname, name); + fclose(fp); + free(tmp_mem); + return 0; + } + + for (i = 0, j = 0; i < size / 2; i++) + { + mem[j++] = (word_4)((int)tmp_mem[i] & 0xf); + mem[j++] = (word_4)(((int)tmp_mem[i] >> 4) & 0xf); + } + + free(tmp_mem); + } + } + + fclose(fp); + + if (verbose) + printf("%s: read %s\n", progname, name); + + return 1; +} + +int +#ifdef __FunctionProto__ +read_rom(const char *fname) +#else +read_rom(fname) +const char *fname; +#endif +{ + int ram_size; + + if (!read_rom_file(romFileName, &saturn.rom, &rom_size)) + return 0; + dev_memory_init(); + + if (opt_gx) + ram_size = RAM_SIZE_GX; + else + ram_size = RAM_SIZE_SX; + + if (NULL == (saturn.ram = (word_4 *)malloc(ram_size))) + { + if (!quiet) + fprintf(stderr, "%s: can\'t malloc RAM\n", progname); + return 0; + } + + memset(saturn.ram, 0, ram_size); + + port1_size = 0; + port1_mask = 0; + port1_is_ram = 0; + saturn.port1 = (unsigned char *)0; + + port2_size = 0; + port2_mask = 0; + port2_is_ram = 0; + saturn.port2 = (unsigned char *)0; + + saturn.card_status = 0; + + return 1; +} + +void +#ifdef __FunctionProto__ +get_home_directory(char *path) +#else +get_home_directory(path) +char *path; +#endif +{ + char *p; + struct passwd *pwd; + + if (homeDirectory[0] == '/') + { + strcpy(path, homeDirectory); + } + else + { + p = getenv("HOME"); + if (p) + { + strcpy(path, p); + strcat(path, "/"); + } + else + { + pwd = getpwuid(getuid()); + if (pwd) + { + strcpy(path, pwd->pw_dir); + strcat(path, "/"); + } + else + { + if (!quiet) + fprintf(stderr, + "%s: can\'t figure out your home directory, trying /tmp\n", + progname); + strcpy(path, "/tmp"); + } + } + strcat(path, homeDirectory); + } +} + +int +#ifdef __FunctionProto__ +read_files(void) +#else +read_files() +#endif +{ + char path[1024]; + char fnam[1024]; + unsigned long v1, v2; + int i, read_version; + int ram_size; + struct stat st; + FILE *fp; + + get_home_directory(path); + strcat(path, "/"); + + saturn.rom = (word_4 *)NULL; + strcpy(fnam, path); + strcat(fnam, "rom"); + if (!read_rom_file(fnam, &saturn.rom, &rom_size)) + return 0; + + rom_is_new = 0; + + strcpy(fnam, path); + strcat(fnam, "hp48"); + if (NULL == (fp = fopen(fnam, "r"))) + { + if (!quiet) + fprintf(stderr, "%s: can\'t open %s\n", progname, fnam); + return 0; + } + + /* + * ok, file is open, try to read the MAGIC number + */ + read_u_long(fp, &saturn.magic); + + if (X48_MAGIC != saturn.magic) + { + /* + * no MAGIC number, try to read old format file + */ + fseek(fp, 0, SEEK_SET); + if (fread((char *)&old_saturn, 1, sizeof(old_saturn), fp) + == sizeof(old_saturn)) { + /* + * seems to work + */ + copy_old_saturn(&old_saturn, &saturn); + if (!quiet) + fprintf(stderr, "%s: %s seems to be an old version file\n", + progname, fnam); + saturn.magic = X48_MAGIC; + saturn.t1_tick = 8192; + saturn.t2_tick = 16; + saturn.i_per_s = 0; + saturn.version[0] = VERSION_MAJOR; + saturn.version[1] = VERSION_MINOR; + saturn.version[2] = PATCHLEVEL; + saturn.version[3] = COMPILE_VERSION; + } else { + /* + * no, initialize + */ + if (!quiet) + fprintf(stderr, "%s: can\'t handle %s\n", progname, fnam); + init_saturn(); + } + } else { + /* + * MAGIC ok, read and compare the version + */ + read_version = 1; + for (i = 0; i < 4; i++) { + if (!read_char(fp, &saturn.version[i])) { + if (!quiet) + fprintf(stderr, "%s: can\'t read version\n", progname); + read_version = 0; + } + } + + if (read_version) { + v1 = ((int)saturn.version[0] & 0xff) << 24; + v1 |= ((int)saturn.version[1] & 0xff) << 16; + v1 |= ((int)saturn.version[2] & 0xff) << 8; + v1 |= ((int)saturn.version[3] & 0xff); + v2 = ((int)VERSION_MAJOR & 0xff) << 24; + v2 |= ((int)VERSION_MINOR & 0xff) << 16; + v2 |= ((int)PATCHLEVEL & 0xff) << 8; + v2 |= ((int)COMPILE_VERSION & 0xff); + + if ((v1 & 0xffffff00) < (v2 & 0xffffff00)) { + if (!quiet) + fprintf(stderr, "%s: %s is a version %d.%d.%d file, converting\n", + progname, fnam, + saturn.version[0], saturn.version[1], saturn.version[2]); + } else if ((v2 & 0xffffff00) < (v1 & 0xffffff00)) { + if (!quiet) + fprintf(stderr, "%s: %s is a version %d.%d.%d file, trying ...\n", + progname, fnam, + saturn.version[0], saturn.version[1], saturn.version[2]); + } + + if (v1 < 0x00040000) + { + /* + * read version < 0.4 file + */ + if (!read_version_0_3_0_file(fp)) + { + if (!quiet) + fprintf(stderr, "%s: can\'t handle %s\n", progname, fnam); + init_saturn(); + } + else + { + copy_0_3_0_saturn(&saturn_0_3_0, &saturn); + if (verbose) + printf("%s: read %s\n", progname, fnam); + } + } + else if (v1 <= v2) { + /* + * read latest version file + */ + if (!read_version_0_4_0_file(fp)) + { + if (!quiet) + fprintf(stderr, "%s: can\'t handle %s\n", progname, fnam); + init_saturn(); + } + else if (verbose) + { + printf("%s: read %s\n", progname, fnam); + } + } else { + /* + * try to read latest version file + */ + if (!read_version_0_4_0_file(fp)) + { + if (!quiet) + fprintf(stderr, "%s: can\'t handle %s\n", progname, fnam); + init_saturn(); + } + else if (verbose) + { + printf("%s: read %s\n", progname, fnam); + } + } + } + } + fclose(fp); + + dev_memory_init(); + + saturn_config_init(); + + if (opt_gx) + ram_size = RAM_SIZE_GX; + else + ram_size = RAM_SIZE_SX; + + saturn.ram = (word_4 *)NULL; + if (NULL == (saturn.ram = (word_4 *)malloc(ram_size))) + { + if (!quiet) + fprintf(stderr, "%s: can\'t malloc RAM[%d]\n", + progname, ram_size); + exit (1); + } + + strcpy(fnam, path); + strcat(fnam, "ram"); + if ((fp = fopen(fnam, "r")) == NULL) { + if (!quiet) + fprintf(stderr, "%s: can\'t open %s\n", progname, fnam); + return 0; + } + if (!read_mem_file(fnam, saturn.ram, ram_size)) + return 0; + + saturn.card_status = 0; + + port1_size = 0; + port1_mask = 0; + port1_is_ram = 0; + saturn.port1 = (unsigned char *)0; + + strcpy(fnam, path); + strcat(fnam, "port1"); + if (stat(fnam, &st) >= 0) + { + port1_size = 2 * st.st_size; + if ((port1_size == 0x10000) || (port1_size == 0x40000)) + { + if (NULL == (saturn.port1 = (word_4 *)malloc(port1_size))) + { + if (!quiet) + fprintf(stderr, "%s: can\'t malloc PORT1[%ld]\n", + progname, port1_size); + } + else if (!read_mem_file(fnam, saturn.port1, port1_size)) + { + port1_size = 0; + port1_is_ram = 0; + } + else + { + port1_is_ram = (st.st_mode & S_IWUSR) ? 1 : 0; + port1_mask = port1_size - 1; + } + } + } + + if (opt_gx) + { + saturn.card_status |= (port1_size > 0) ? 2 : 0; + saturn.card_status |= port1_is_ram ? 8 : 0; + } + else + { + saturn.card_status |= (port1_size > 0) ? 1 : 0; + saturn.card_status |= port1_is_ram ? 4 : 0; + } + + port2_size = 0; + port2_mask = 0; + port2_is_ram = 0; + saturn.port2 = (unsigned char *)0; + + strcpy(fnam, path); + strcat(fnam, "port2"); + if (stat(fnam, &st) >= 0) + { + port2_size = 2 * st.st_size; + if ((opt_gx && ((port2_size % 0x40000) == 0)) || + (!opt_gx && ((port2_size == 0x10000) || (port2_size == 0x40000)))) + { + if (NULL == (saturn.port2 = (word_4 *)malloc(port2_size))) + { + if (!quiet) + fprintf(stderr, "%s: can\'t malloc PORT2[%ld]\n", + progname, port2_size); + } + else if (!read_mem_file(fnam, saturn.port2, port2_size)) + { + port2_size = 0; + port2_is_ram = 0; + } + else + { + port2_is_ram = (st.st_mode & S_IWUSR) ? 1 : 0; + port2_mask = port2_size - 1; + } + } + } + + if (opt_gx) + { + saturn.card_status |= (port2_size > 0) ? 1 : 0; + saturn.card_status |= port2_is_ram ? 4 : 0; + } + else + { + saturn.card_status |= (port2_size > 0) ? 2 : 0; + saturn.card_status |= port2_is_ram ? 8 : 0; + } + + return 1; +} + +int +#ifdef __FunctionProto__ +write_8(FILE *fp, word_8 *var) +#else +write_8(fp, var) +FILE *fp; +word_8 *var; +#endif +{ + unsigned char tmp; + + tmp = *var; + if (fwrite(&tmp, 1, 1, fp) != 1) { + if (!quiet) + fprintf(stderr, "%s: can\'t write word_8\n", progname); + return 0; + } + return 1; +} + +int +#ifdef __FunctionProto__ +write_char(FILE *fp, char *var) +#else +write_char(fp, var) +FILE *fp; +char *var; +#endif +{ + char tmp; + + tmp = *var; + if (fwrite(&tmp, 1, 1, fp) != 1) { + if (!quiet) + fprintf(stderr, "%s: can\'t write char\n", progname); + return 0; + } + return 1; +} + +int +#ifdef __FunctionProto__ +write_16(FILE *fp, word_16 *var) +#else +write_16(fp, var) +FILE *fp; +word_16 *var; +#endif +{ + unsigned char tmp[2]; + + tmp[0] = (*var >> 8) & 0xff; + tmp[1] = *var & 0xff; + if (fwrite(&tmp[0], 1, 2, fp) != 2) { + if (!quiet) + fprintf(stderr, "%s: can\'t write word_16\n", progname); + return 0; + } + return 1; +} + +int +#ifdef __FunctionProto__ +write_32(FILE *fp, word_32 *var) +#else +write_32(fp, var) +FILE *fp; +word_32 *var; +#endif +{ + unsigned char tmp[4]; + + tmp[0] = (*var >> 24) & 0xff; + tmp[1] = (*var >> 16) & 0xff; + tmp[2] = (*var >> 8) & 0xff; + tmp[3] = *var & 0xff; + if (fwrite(&tmp[0], 1, 4, fp) != 4) { + if (!quiet) + fprintf(stderr, "%s: can\'t write word_32\n", progname); + return 0; + } + return 1; +} + +int +#ifdef __FunctionProto__ +write_u_long(FILE *fp, unsigned long *var) +#else +write_u_long(fp, var) +FILE *fp; +unsigned long*var; +#endif +{ + unsigned char tmp[4]; + + tmp[0] = (*var >> 24) & 0xff; + tmp[1] = (*var >> 16) & 0xff; + tmp[2] = (*var >> 8) & 0xff; + tmp[3] = *var & 0xff; + if (fwrite(&tmp[0], 1, 4, fp) != 4) { + if (!quiet) + fprintf(stderr, "%s: can\'t write unsigned long\n", progname); + return 0; + } + return 1; +} + +int +#ifdef __FunctionProto__ +write_mem_file(char *name, word_4 *mem, int size) +#else +write_mem_file(name, mem, size) +char *name; +word_4 *mem; +int size; +#endif +{ + FILE *fp; + word_8 *tmp_mem; + word_8 byte; + int i, j; + + if (NULL == (fp = fopen(name, "w"))) + { + if (!quiet) + fprintf(stderr, "%s: can\'t open %s\n", progname, name); + return 0; + } + + if (NULL == (tmp_mem = (word_8 *)malloc((size_t)size / 2))) + { + for (i = 0, j = 0; i < size / 2; i++) + { + byte = (mem[j++] & 0x0f); + byte |= (mem[j++] << 4) & 0xf0; + if (1 != fwrite(&byte, 1, 1, fp)) + { + if (!quiet) + fprintf(stderr, "%s: can\'t write %s\n", progname, name); + fclose(fp); + return 0; + } + } + } + else + { + for (i = 0, j = 0; i < size / 2; i++) + { + tmp_mem[i] = (mem[j++] & 0x0f); + tmp_mem[i] |= (mem[j++] << 4) & 0xf0; + } + + if (fwrite(tmp_mem, 1, (size_t)size / 2, fp) != size / 2) + { + if (!quiet) + fprintf(stderr, "%s: can\'t write %s\n", progname, name); + fclose(fp); + free(tmp_mem); + return 0; + } + + free(tmp_mem); + } + + fclose(fp); + + if (verbose) + printf("%s: wrote %s\n", progname, name); + + return 1; +} + + +int +#ifdef __FunctionProto__ +write_files(void) +#else +write_files() +#endif +{ + char path[1024]; + char fnam[1024]; + struct stat st; + int i, make_dir; + int ram_size; + FILE *fp; + + make_dir = 0; + get_home_directory(path); + + if (stat(path, &st) == -1) + { + if (errno == ENOENT) + { + make_dir = 1; + } + else + { + if (!quiet) + fprintf(stderr, "%s: can\'t stat %s, saving to /tmp\n", + progname, path); + strcpy(path, "/tmp"); + } + } + else + { + if (!S_ISDIR(st.st_mode)) + { + if (!quiet) + fprintf(stderr, "%s: %s is no directory, saving to /tmp\n", + progname, path); + strcpy(path, "/tmp"); + } + } + + if (make_dir) + { + if (mkdir(path, 0777) == -1) + { + if (!quiet) + fprintf(stderr, "%s: can\'t mkdir %s, saving to /tmp\n", + progname, path); + strcpy(path, "/tmp"); + } + } + + strcat(path, "/"); + + strcpy(fnam, path); + strcat(fnam, "hp48"); + if ((fp = fopen(fnam, "w")) == NULL) { + if (!quiet) + fprintf(stderr, "%s: can\'t open %s, no saving done\n", + progname, fnam); + return 0; + } + + /* + * write the hp48 config file + */ + write_32(fp, (word_32 *)&saturn.magic); + for (i = 0; i < 4; i++) write_char(fp, &saturn.version[i]); + for (i = 0; i < 16; i++) write_8(fp, &saturn.A[i]); + for (i = 0; i < 16; i++) write_8(fp, &saturn.B[i]); + for (i = 0; i < 16; i++) write_8(fp, &saturn.C[i]); + for (i = 0; i < 16; i++) write_8(fp, &saturn.D[i]); + write_32(fp, &saturn.d[0]); + write_32(fp, &saturn.d[1]); + write_8(fp, &saturn.P); + write_32(fp, &saturn.PC); + for (i = 0; i < 16; i++) write_8(fp, &saturn.R0[i]); + for (i = 0; i < 16; i++) write_8(fp, &saturn.R1[i]); + for (i = 0; i < 16; i++) write_8(fp, &saturn.R2[i]); + for (i = 0; i < 16; i++) write_8(fp, &saturn.R3[i]); + for (i = 0; i < 16; i++) write_8(fp, &saturn.R4[i]); + for (i = 0; i < 4; i++) write_8(fp, &saturn.IN[i]); + for (i = 0; i < 3; i++) write_8(fp, &saturn.OUT[i]); + write_8(fp, &saturn.CARRY); + for (i = 0; i < NR_PSTAT; i++) write_8(fp, &saturn.PSTAT[i]); + write_8(fp, &saturn.XM); + write_8(fp, &saturn.SB); + write_8(fp, &saturn.SR); + write_8(fp, &saturn.MP); + write_8(fp, &saturn.hexmode); + for (i = 0; i < NR_RSTK; i++) write_32(fp, &saturn.rstk[i]); + write_16(fp, (word_16 *)&saturn.rstkp); + for (i = 0; i < 9; i++) write_16(fp, (word_16 *)&saturn.keybuf.rows[i]); + write_8(fp, &saturn.intenable); + write_8(fp, &saturn.int_pending); + write_8(fp, &saturn.kbd_ien); + write_8(fp, &saturn.disp_io); + write_8(fp, &saturn.contrast_ctrl); + write_8(fp, &saturn.disp_test); + write_16(fp, &saturn.crc); + write_8(fp, &saturn.power_status); + write_8(fp, &saturn.power_ctrl); + write_8(fp, &saturn.mode); + write_8(fp, &saturn.annunc); + write_8(fp, &saturn.baud); + write_8(fp, &saturn.card_ctrl); + write_8(fp, &saturn.card_status); + write_8(fp, &saturn.io_ctrl); + write_8(fp, &saturn.rcs); + write_8(fp, &saturn.tcs); + write_8(fp, &saturn.rbr); + write_8(fp, &saturn.tbr); + write_8(fp, &saturn.sreq); + write_8(fp, &saturn.ir_ctrl); + write_8(fp, &saturn.base_off); + write_8(fp, &saturn.lcr); + write_8(fp, &saturn.lbr); + write_8(fp, &saturn.scratch); + write_8(fp, &saturn.base_nibble); + write_32(fp, &saturn.disp_addr); + write_16(fp, &saturn.line_offset); + write_8(fp, &saturn.line_count); + write_16(fp, &saturn.unknown); + write_8(fp, &saturn.t1_ctrl); + write_8(fp, &saturn.t2_ctrl); + write_32(fp, &saturn.menu_addr); + write_8(fp, &saturn.unknown2); + write_char(fp, &saturn.timer1); + write_32(fp, &saturn.timer2); + write_32(fp, &saturn.t1_instr); + write_32(fp, &saturn.t2_instr); + write_16(fp, (word_16 *)&saturn.t1_tick); + write_16(fp, (word_16 *)&saturn.t2_tick); + write_32(fp, &saturn.i_per_s); + write_16(fp, &saturn.bank_switch); + for (i = 0; i < NR_MCTL; i++) + { + write_16(fp, &saturn.mem_cntl[i].unconfigured); + write_32(fp, &saturn.mem_cntl[i].config[0]); + write_32(fp, &saturn.mem_cntl[i].config[1]); + } + fclose(fp); + if (verbose) + printf("%s: wrote %s\n", progname, fnam); + + if (rom_is_new) + { + strcpy(fnam, path); + strcat(fnam, "rom"); + if (!write_mem_file(fnam, saturn.rom, rom_size)) + return 0; + } + + if (opt_gx) + ram_size = RAM_SIZE_GX; + else + ram_size = RAM_SIZE_SX; + + strcpy(fnam, path); + strcat(fnam, "ram"); + if (!write_mem_file(fnam, saturn.ram, ram_size)) + return 0; + + if ((port1_size > 0) && port1_is_ram) + { + strcpy(fnam, path); + strcat(fnam, "port1"); + if (!write_mem_file(fnam, saturn.port1, port1_size)) + return 0; + } + + if ((port2_size > 0) && port2_is_ram) + { + strcpy(fnam, path); + strcat(fnam, "port2"); + if (!write_mem_file(fnam, saturn.port2, port2_size)) + return 0; + } + + return 1; +} + +int +#ifdef __FunctionProto__ +init_emulator(void) +#else +init_emulator() +#endif +{ + if (!initialize) + if (read_files()) + { + if (resetOnStartup) + saturn.PC = 0x00000; + return 0; + } + + init_saturn(); + if (!read_rom(romFileName)) + exit(1); + + return 0; +} + +void +#ifdef __FunctionProto__ +init_active_stuff(void) +#else +init_active_stuff() +#endif +{ + serial_init(); + init_annunc(); + init_display(); +} + +int +#ifdef __FunctionProto__ +exit_emulator(void) +#else +exit_emulator() +#endif +{ + write_files(); + return 1; +} + diff --git a/src/lcd.c b/src/lcd.c new file mode 100644 index 0000000..33ad293 --- /dev/null +++ b/src/lcd.c @@ -0,0 +1,567 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: lcd.c,v $ + * Revision 1.13 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.12 1994/12/08 22:14:50 ecd + * fixed bug with XShmPutImage causing errors in init_display + * + * Revision 1.11 1994/12/07 20:20:50 ecd + * added support for icon colors + * + * Revision 1.10 1994/11/28 02:00:51 ecd + * added support for colors on icon + * + * Revision 1.9 1994/11/02 14:44:28 ecd + * minor fixes + * + * Revision 1.8 1994/10/09 20:32:02 ecd + * implemented bit offset stuff. + * + * Revision 1.7 1994/10/06 16:30:05 ecd + * added Shared Memory stuff + * + * Revision 1.6 1994/10/05 08:36:44 ecd + * pixmaps for nibble updates + * + * Revision 1.5 1994/09/30 12:37:09 ecd + * new display code makes x48 a lot faster + * + * Revision 1.4 1994/09/18 15:29:22 ecd + * turned off unused rcsid message + * + * Revision 1.3 1994/09/13 16:57:00 ecd + * changed to plain X11 + * + * Revision 1.2 1994/08/31 18:23:21 ecd + * changed display initialization. + * + * Revision 1.1 1994/08/26 11:09:02 ecd + * Initial revision + * + * $Id: lcd.c,v 1.13 1995/01/11 18:20:01 ecd Exp ecd $ + */ + + +#include "global.h" + +#include +#include +#include +#ifdef SUNOS +#include +#endif +#include +#include + +#include "hp48.h" +#include "hp48_emu.h" +#include "x48_x11.h" +#include "annunc.h" +#include "device.h" + +static int last_annunc_state = -1; + +display_t display; + +#define DISP_ROWS 64 + +#define NIBS_PER_BUFFER_ROW (NIBBLES_PER_ROW + 2) + +unsigned char disp_buf[DISP_ROWS][NIBS_PER_BUFFER_ROW]; +unsigned char lcd_buffer[DISP_ROWS][NIBS_PER_BUFFER_ROW]; + +Pixmap nibble_maps[16]; + +unsigned char nibbles[16][2] = +{ + { 0x00, 0x00 }, /* ---- */ + { 0x03, 0x03 }, /* *--- */ + { 0x0c, 0x0c }, /* -*-- */ + { 0x0f, 0x0f }, /* **-- */ + { 0x30, 0x30 }, /* --*- */ + { 0x33, 0x33 }, /* *-*- */ + { 0x3c, 0x3c }, /* -**- */ + { 0x3f, 0x3f }, /* ***- */ + { 0xc0, 0xc0 }, /* ---* */ + { 0xc3, 0xc3 }, /* *--* */ + { 0xcc, 0xcc }, /* -*-* */ + { 0xcf, 0xcf }, /* **-* */ + { 0xf0, 0xf0 }, /* --** */ + { 0xf3, 0xf3 }, /* *-** */ + { 0xfc, 0xfc }, /* -*** */ + { 0xff, 0xff } /* **** */ +}; + +static unsigned char nibble_bits[16]; + +void +#ifdef __FunctionProto__ +init_nibble_maps(void) +#else +init_nibble_maps() +#endif +{ + int i; + + for (i = 0; i < 16; i++) { + nibble_maps[i] = XCreateBitmapFromData(dpy, disp.win, + (char *)nibbles[i], 8, 2); + } +#ifdef HAVE_XSHM + if (shm_flag) { + if (disp.disp_image->bitmap_bit_order == MSBFirst) { + nibble_bits[0x0] = 0x00; /* ---- */ + nibble_bits[0x1] = 0xc0; /* *--- */ + nibble_bits[0x2] = 0x30; /* -*-- */ + nibble_bits[0x3] = 0xf0; /* **-- */ + nibble_bits[0x4] = 0x0c; /* --*- */ + nibble_bits[0x5] = 0xcc; /* *-*- */ + nibble_bits[0x6] = 0x3c; /* -**- */ + nibble_bits[0x7] = 0xfc; /* ***- */ + nibble_bits[0x8] = 0x03; /* ---* */ + nibble_bits[0x9] = 0xc3; /* *--* */ + nibble_bits[0xa] = 0x33; /* -*-* */ + nibble_bits[0xb] = 0xf3; /* **-* */ + nibble_bits[0xc] = 0x0f; /* --** */ + nibble_bits[0xd] = 0xcf; /* *-** */ + nibble_bits[0xe] = 0x3f; /* -*** */ + nibble_bits[0xf] = 0xff; /* **** */ + } else { + nibble_bits[0x0] = 0x00; /* ---- */ + nibble_bits[0x1] = 0x03; /* *--- */ + nibble_bits[0x2] = 0x0c; /* -*-- */ + nibble_bits[0x3] = 0x0f; /* **-- */ + nibble_bits[0x4] = 0x30; /* --*- */ + nibble_bits[0x5] = 0x33; /* *-*- */ + nibble_bits[0x6] = 0x3c; /* -**- */ + nibble_bits[0x7] = 0x3f; /* ***- */ + nibble_bits[0x8] = 0xc0; /* ---* */ + nibble_bits[0x9] = 0xc3; /* *--* */ + nibble_bits[0xa] = 0xcc; /* -*-* */ + nibble_bits[0xb] = 0xcf; /* **-* */ + nibble_bits[0xc] = 0xf0; /* --** */ + nibble_bits[0xd] = 0xf3; /* *-** */ + nibble_bits[0xe] = 0xfc; /* -*** */ + nibble_bits[0xf] = 0xff; /* **** */ + } + } +#endif +} + +void +#ifdef __FunctionProto__ +init_display(void) +#else +init_display() +#endif +{ + display.on = (int)(saturn.disp_io & 0x8) >> 3; + + display.disp_start = (saturn.disp_addr & 0xffffe); + display.offset = (saturn.disp_io & 0x7); + disp.offset = 2 * display.offset; + + display.lines = (saturn.line_count & 0x3f); + if (display.lines == 0) + display.lines = 63; + disp.lines = 2 * display.lines; + if (disp.lines < 110) + disp.lines = 110; + + if (display.offset > 3) + display.nibs_per_line = (NIBBLES_PER_ROW+saturn.line_offset+2) & 0xfff; + else + display.nibs_per_line = (NIBBLES_PER_ROW+saturn.line_offset) & 0xfff; + + display.disp_end = display.disp_start + + (display.nibs_per_line * (display.lines + 1)); + + display.menu_start = saturn.menu_addr; + display.menu_end = saturn.menu_addr + 0x110; + + display.contrast = saturn.contrast_ctrl; + display.contrast |= ((saturn.disp_test & 0x1) << 4); + + display.annunc = saturn.annunc; + + memset(disp_buf, 0xf0, sizeof(disp_buf)); + memset(lcd_buffer, 0xf0, sizeof(lcd_buffer)); + + init_nibble_maps(); +} + +static inline void +#ifdef __FunctionProto__ +draw_nibble(int c, int r, int val) +#else +draw_nibble(c, r, val) +int c; +int r; +int val; +#endif +{ + int x, y; + + x = (c * 8) + 5; + if (r <= display.lines) + x -= disp.offset; + y = (r * 2) + 20; + val &= 0x0f; + if (val != lcd_buffer[r][c]) { + XCopyPlane(dpy, nibble_maps[val], disp.win, disp.gc, 0, 0, 8, 2, x, y, 1); + lcd_buffer[r][c] = val; + } +} + +static inline void +#ifdef __FunctionProto__ +draw_row(long addr, int row) +#else +draw_row(addr, row) +long addr; +int row; +#endif +{ + int i, v; + int line_length; + + line_length = NIBBLES_PER_ROW; + if ((display.offset > 3) && (row <= display.lines)) + line_length += 2; + for (i = 0; i < line_length; i++) { + v = read_nibble(addr + i); + if (v != disp_buf[row][i]) { + disp_buf[row][i] = v; + draw_nibble(i, row, v); + } + } +} + +void +#ifdef __FunctionProto__ +update_display(void) +#else +update_display() +#endif +{ + int i, j; + long addr; + static int old_offset = -1; + static int old_lines = -1; +#ifdef HAVE_XSHM + int addr_pad; + int val, line_pad, line_length; + word_20 data_addr, data_addr_2; +#endif + + if (!disp.mapped) + { + refresh_icon(); + return; + } + if (display.on) { + addr = display.disp_start; +#ifdef HAVE_XSHM + if (shm_flag) { + data_addr = 0; + data_addr_2 = disp.disp_image->bytes_per_line; + line_length = NIBBLES_PER_ROW; + if (display.offset > 3) + line_length += 2; + line_pad = 2 * disp.disp_image->bytes_per_line - line_length; + addr_pad = display.nibs_per_line - line_length; + for (i = 0; i <= display.lines; i++) { + for (j = 0; j < line_length; j++) { + val = read_nibble(addr++); + disp.disp_image->data[data_addr++] = nibble_bits[val]; + disp.disp_image->data[data_addr_2++] = nibble_bits[val]; + } + addr += addr_pad; + data_addr += line_pad; + data_addr_2 += line_pad; + } + disp.display_update |= UPDATE_DISP; + } else { +#endif + if (display.offset != old_offset) { + memset(disp_buf, 0xf0, + (size_t)((display.lines+1) * NIBS_PER_BUFFER_ROW)); + memset(lcd_buffer, 0xf0, + (size_t)((display.lines+1) * NIBS_PER_BUFFER_ROW)); + old_offset = display.offset; + } + if (display.lines != old_lines) { + memset(&disp_buf[56][0], 0xf0, (size_t)(8 * NIBS_PER_BUFFER_ROW)); + memset(&lcd_buffer[56][0], 0xf0, (size_t)(8 * NIBS_PER_BUFFER_ROW)); + old_lines = display.lines; + } + for (i = 0; i <= display.lines; i++) { + draw_row(addr, i); + addr += display.nibs_per_line; + } +#ifdef HAVE_XSHM + } +#endif + if (i < DISP_ROWS) { + addr = display.menu_start; +#ifdef HAVE_XSHM + if (shm_flag) { + data_addr = 0; + data_addr_2 = disp.menu_image->bytes_per_line; + line_pad = 2 * disp.menu_image->bytes_per_line - NIBBLES_PER_ROW; + for (; i < DISP_ROWS; i++) { + for (j = 0; j < NIBBLES_PER_ROW; j++) { + val = read_nibble(addr++); + disp.menu_image->data[data_addr++] = nibble_bits[val]; + disp.menu_image->data[data_addr_2++] = nibble_bits[val]; + } + data_addr += line_pad; + data_addr_2 += line_pad; + } + disp.display_update |= UPDATE_MENU; + } else { +#endif + for (; i < DISP_ROWS; i++) { + draw_row(addr, i); + addr += NIBBLES_PER_ROW; + } +#ifdef HAVE_XSHM + } +#endif + } + } else { +#ifdef HAVE_XSHM + if (shm_flag) { + memset(disp.disp_image->data, 0, + (size_t)(disp.disp_image->bytes_per_line * disp.disp_image->height)); + memset(disp.menu_image->data, 0, + (size_t)(disp.menu_image->bytes_per_line * disp.menu_image->height)); + disp.display_update = UPDATE_DISP | UPDATE_MENU; + } else { +#endif + memset(disp_buf, 0xf0, sizeof(disp_buf)); + for (i = 0; i < 64; i++) { + for (j = 0; j < NIBBLES_PER_ROW; j++) { + draw_nibble(j, i, 0x00); + } + } +#ifdef HAVE_XSHM + } +#endif + } +} + +void +#ifdef __FunctionProto__ +redraw_display(void) +#else +redraw_display() +#endif +{ + XClearWindow(dpy, disp.win); + memset(disp_buf, 0, sizeof(disp_buf)); + memset(lcd_buffer, 0, sizeof(lcd_buffer)); + update_display(); +} + +void +#ifdef __FunctionProto__ +disp_draw_nibble(word_20 addr, word_4 val) +#else +disp_draw_nibble(addr, val) +word_20 addr; +word_4 val; +#endif +{ + long offset; +#ifdef HAVE_XSHM + int shm_addr; +#endif + int x, y; + + offset = (addr - display.disp_start); + x = offset % display.nibs_per_line; + if (x < 0 || x > 35) + return; + if (display.nibs_per_line != 0) { + y = offset / display.nibs_per_line; + if (y < 0 || y > 63) + return; +#ifdef HAVE_XSHM + if (shm_flag) { + shm_addr = (2 * y * disp.disp_image->bytes_per_line) + x; + disp.disp_image->data[shm_addr] = nibble_bits[val]; + disp.disp_image->data[shm_addr+disp.disp_image->bytes_per_line] = + nibble_bits[val]; + disp.display_update |= UPDATE_DISP; + } else { +#endif + if (val != disp_buf[y][x]) { + disp_buf[y][x] = val; + draw_nibble(x, y, val); + } +#ifdef HAVE_XSHM + } +#endif + } else { +#ifdef HAVE_XSHM + if (shm_flag) { + shm_addr = x; + for (y = 0; y < display.lines; y++) { + disp.disp_image->data[shm_addr] = nibble_bits[val]; + shm_addr += disp.disp_image->bytes_per_line; + disp.disp_image->data[shm_addr] + = nibble_bits[val]; + shm_addr += disp.disp_image->bytes_per_line; + } + disp.display_update |= UPDATE_DISP; + } else { +#endif + for (y = 0; y < display.lines; y++) { + if (val != disp_buf[y][x]) { + disp_buf[y][x] = val; + draw_nibble(x, y, val); + } + } +#ifdef HAVE_XSHM + } +#endif + } +} + +void +#ifdef __FunctionProto__ +menu_draw_nibble(word_20 addr, word_4 val) +#else +menu_draw_nibble(addr, val) +word_20 addr; +word_4 val; +#endif +{ + long offset; +#ifdef HAVE_XSHM + int shm_addr; +#endif + int x, y; + + offset = (addr - display.menu_start); +#ifdef HAVE_XSHM + if (shm_flag) { + shm_addr = 2 * (offset / NIBBLES_PER_ROW) * disp.menu_image->bytes_per_line + + (offset % NIBBLES_PER_ROW); + disp.menu_image->data[shm_addr] = nibble_bits[val]; + disp.menu_image->data[shm_addr+disp.menu_image->bytes_per_line] = + nibble_bits[val]; + disp.display_update |= UPDATE_MENU; + } else { +#endif + x = offset % NIBBLES_PER_ROW; + y = display.lines + (offset / NIBBLES_PER_ROW) + 1; + if (val != disp_buf[y][x]) { + disp_buf[y][x] = val; + draw_nibble(x, y, val); + } +#ifdef HAVE_XSHM + } +#endif +} + + +struct ann_struct { + int bit; + int x; + int y; + unsigned int width; + unsigned int height; + unsigned char *bits; + Pixmap pixmap; +} ann_tbl[] = { + { ANN_LEFT, 16, 4, ann_left_width, ann_left_height, ann_left_bits }, + { ANN_RIGHT, 61, 4, ann_right_width, ann_right_height, ann_right_bits }, + { ANN_ALPHA, 106, 4, ann_alpha_width, ann_alpha_height, ann_alpha_bits }, + { ANN_BATTERY, 151, 4, ann_battery_width, ann_battery_height, + ann_battery_bits }, + { ANN_BUSY, 196, 4, ann_busy_width, ann_busy_height, ann_busy_bits }, + { ANN_IO, 241, 4, ann_io_width, ann_io_height, ann_io_bits }, + { 0 } +}; + +void +#ifdef __FunctionProto__ +draw_annunc(void) +#else +draw_annunc() +#endif +{ + int val; + int i; + + val = display.annunc; + + if (val == last_annunc_state) + return; + last_annunc_state = val; + for (i = 0; ann_tbl[i].bit; i++) + { + if ((ann_tbl[i].bit & val) == ann_tbl[i].bit) + { + XCopyPlane(dpy, ann_tbl[i].pixmap, disp.win, disp.gc, 0, 0, + ann_tbl[i].width, ann_tbl[i].height, + ann_tbl[i].x, ann_tbl[i].y, 1); + } + else + { + XClearArea(dpy, disp.win, ann_tbl[i].x, ann_tbl[i].y, + ann_tbl[i].width, ann_tbl[i].height, False); + } + } + refresh_icon(); +} + +void +#ifdef __FunctionProto__ +redraw_annunc(void) +#else +redraw_annunc() +#endif +{ + last_annunc_state = -1; + draw_annunc(); +} + +void +#ifdef __FunctionProto__ +init_annunc(void) +#else +init_annunc() +#endif +{ + int i; + + for (i = 0; ann_tbl[i].bit; i++) { + ann_tbl[i].pixmap = XCreateBitmapFromData(dpy, disp.win, + (char *)ann_tbl[i].bits, + ann_tbl[i].width, + ann_tbl[i].height); + } +} + diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..839e171 --- /dev/null +++ b/src/main.c @@ -0,0 +1,265 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: main.c,v $ + * Revision 1.11 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.10 1994/12/07 20:20:50 ecd + * changed initialization + * + * Revision 1.10 1994/12/07 20:20:50 ecd + * changed initialization + * + * Revision 1.9 1994/11/28 02:00:51 ecd + * reordered initialization. serial_init() is called after x11 init. + * + * Revision 1.8 1994/11/04 03:42:34 ecd + * added call to parse_options() + * + * Revision 1.7 1994/11/02 14:44:28 ecd + * call to emulate_debug() added + * + * Revision 1.6 1994/10/05 08:36:44 ecd + * new function call to init_nibble_maps() + * + * Revision 1.5 1994/09/30 12:37:09 ecd + * deleted saturn.intenable = 1; statement + * + * Revision 1.4 1994/09/18 22:47:20 ecd + * fixed typo + * + * Revision 1.3 1994/09/18 15:29:22 ecd + * turned off unused rcsid message + * + * Revision 1.2 1994/09/13 16:57:00 ecd + * changed to plain X11 + * + * Revision 1.1 1994/09/13 15:05:05 ecd + * Initial revision + * + * $Id: main.c,v 1.11 1995/01/11 18:20:01 ecd Exp ecd $ + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "x48_x11.h" +#include "hp48.h" +#include "debugger.h" + +#include +#include + +char *progname; +char *res_name; +char *res_class; + +int saved_argc; +char **saved_argv; + +saturn_t saturn; + +void +#ifdef __FunctionProto__ +signal_handler(int sig) +#else +signal_handler(sig) +int sig; +#endif +{ + switch (sig) { + case SIGINT: + enter_debugger |= USER_INTERRUPT; + break; + case SIGALRM: + got_alarm = 1; + break; + case SIGPIPE: + exit_x48(0); + exit (0); + default: + break; + } +} + +void +#ifdef __FunctionProto__ +save_options(int argc, char **argv) +#else +save_options(argc, argv) +int argc; +char **argv; +#endif +{ + int l; + + saved_argc = argc; + saved_argv = (char **)malloc((argc + 2) * sizeof(char *)); + if (saved_argv == (char **)0) + { + fprintf(stderr, "%s: malloc failed in save_options(), exit\n", progname); + exit (1); + } + saved_argv[argc] = (char *)0; + while (argc--) + { + l = strlen(argv[argc]) + 1; + saved_argv[argc] = (char *)malloc(l); + if (saved_argv[argc] == (char *)0) + { + fprintf(stderr, "%s: malloc failed in save_options(), exit\n", + progname); + exit (1); + } + memcpy(saved_argv[argc], argv[argc], l); + } +} + +int +#ifdef __FunctionProto__ +main(int argc, char **argv) +#else +main(argc, argv) +int argc; +char **argv; +#endif +{ + char *name; + sigset_t set; + struct sigaction sa; + long flags; + struct itimerval it; + + setlocale(LC_ALL, "C"); + + name = (char *)0; + /* + * Get the name we are called. + */ + progname = strrchr(argv[0], '/'); + if (progname == NULL) + progname = argv[0]; + else + progname++; + + /* + * save command line options + */ + save_options(argc, argv); + + /* + * Open up the display + */ + if (InitDisplay(argc, argv) < 0) { + exit (1); + } + + /* + * initialize emulator stuff + */ + init_emulator(); + + /* + * Create the HP-48 window + */ + if (CreateWindows(saved_argc, saved_argv) < 0) { + fprintf(stderr, "%s: can\'t create window\n", progname); + exit (1); + } + + /* + * can't be done before windows exist + */ + init_active_stuff(); + + /* + * install a handler for SIGALRM + */ + sigemptyset(&set); + sigaddset(&set, SIGALRM); + sa.sa_handler = signal_handler; + sa.sa_mask = set; +#ifdef SA_RESTART + sa.sa_flags = SA_RESTART; +#endif + sigaction(SIGALRM, &sa, (struct sigaction *)0); + + /* + * install a handler for SIGINT + */ + sigemptyset(&set); + sigaddset(&set, SIGINT); + sa.sa_handler = signal_handler; + sa.sa_mask = set; +#ifdef SA_RESTART + sa.sa_flags = SA_RESTART; +#endif + sigaction(SIGINT, &sa, (struct sigaction *)0); + + /* + * install a handler for SIGPIPE + */ + sigemptyset(&set); + sigaddset(&set, SIGPIPE); + sa.sa_handler = signal_handler; + sa.sa_mask = set; +#ifdef SA_RESTART + sa.sa_flags = SA_RESTART; +#endif + sigaction(SIGPIPE, &sa, (struct sigaction *)0); + + /* + * set the real time interval timer + */ + it.it_interval.tv_sec = 0; + it.it_interval.tv_usec = 20000; + it.it_value.tv_sec = 0; + it.it_value.tv_usec = 20000; + setitimer(ITIMER_REAL, &it, (struct itimerval *)0); + + /* + * Set stdin flags to not include O_NDELAY and O_NONBLOCK + */ + flags = fcntl(STDIN_FILENO, F_GETFL, 0); + flags &= ~O_NDELAY; + flags &= ~O_NONBLOCK; + fcntl(STDIN_FILENO, F_SETFL, flags); + + do { + + if (!exec_flags) + emulate (); + else + emulate_debug (); + + debug(); + + } while (1); + + return 0; +} + diff --git a/src/memory.c b/src/memory.c new file mode 100644 index 0000000..9f39c6d --- /dev/null +++ b/src/memory.c @@ -0,0 +1,1535 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: memory.c,v $ + * Revision 1.15 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.14 1994/12/08 22:14:50 ecd + * corrected setting of display.lines + * + * Revision 1.13 1994/12/07 20:20:50 ecd + * minor fixes + * + * Revision 1.12 1994/11/28 02:00:51 ecd + * corrected setting of display.contrast + * + * Revision 1.11 1994/11/02 15:07:54 ecd + * deleted trailing NULL characters + * + * Revision 1.10 1994/11/02 14:44:28 ecd + * minor changes + * + * Revision 1.9 1994/10/09 20:32:02 ecd + * added support for bit offset, changed handling of display_t + * variables. + * + * Revision 1.8 1994/10/06 16:30:05 ecd + * changed char to unsigned + * + * Revision 1.7 1994/10/05 08:36:44 ecd + * removed display addr queue + * + * Revision 1.6 1994/10/01 10:12:53 ecd + * added schedule_event = 0 for any display touch + * + * Revision 1.5 1994/09/30 12:37:09 ecd + * support for faster display and scheduler + * + * Revision 1.4 1994/09/18 15:29:22 ecd + * turned off unused rcsid message + * + * Revision 1.3 1994/09/13 16:57:00 ecd + * changed to plain X11 + * + * Revision 1.2 1994/08/31 18:23:21 ecd + * changed memory access routines. + * + * Revision 1.1 1994/08/26 11:09:02 ecd + * Initial revision + * + * $Id: memory.c,v 1.15 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#include "global.h" + +#include +#include +#include +#include +#include +#ifdef SUNOS +#include +#endif + +#include "hp48.h" +#include "device.h" +#include "hp48_emu.h" +#include "x48_x11.h" +#include "romio.h" +#include "resources.h" +#include "mmu.h" + +extern int device_check; +extern short port1_is_ram; +extern long port1_mask; +extern short port2_is_ram; +extern long port2_mask; + +#define DEBUG_UNKNOWN 1 +/* #define DEBUG_SERIAL 1 */ +/* #define DEBUG_SERIALb 1 */ +/* #define DEBUG_DISPLAY 1 */ +/* #define DEBUG_IR 1 */ +/* #define DEBUG_CONTRAST 1 */ +/* #define DEBUG_CARDS 1 */ +/* #define DEBUG_BAD_MEM 1 */ +/* #define DEBUG_BASE_NIBBLE 1 */ +/* #define DEBUG_BANK_SWITCH 1 */ + +long nibble_masks[16] = { + 0x0000000f, + 0x000000f0, + 0x00000f00, + 0x0000f000, + 0x000f0000, + 0x00f00000, + 0x0f000000, + 0xf0000000, + 0x0000000f, + 0x000000f0, + 0x00000f00, + 0x0000f000, + 0x000f0000, + 0x00f00000, + 0x0f000000, + 0xf0000000 +}; + +void (*write_nibble) __ProtoType__((long addr, int val)); +int (*read_nibble) __ProtoType__((long addr)); +int (*read_nibble_crc) __ProtoType__((long addr)); + +static int line_counter = -1; + +static inline int +#ifdef __FunctionProto__ +calc_crc(int nib) +#else +calc_crc(nib) +int nib; +#endif +{ + saturn.crc = (saturn.crc >> 4) ^ (((saturn.crc ^ nib) & 0xf) * 0x1081); + return nib; +} + +void +#ifdef __FunctionProto__ +write_dev_mem(long addr, int val) +#else +write_dev_mem(addr, val) +long addr; +int val; +#endif +{ + static int old_line_offset = -1; + + device_check = 1; + schedule_event = 0; + switch ((int)addr) { + case 0x100: /* DISPIO */ + if (val != saturn.disp_io) { + saturn.disp_io = val; + display.on = (val & 0x8) >> 3; + display.offset = val & 0x7; + disp.offset = 2 * display.offset; + if (display.offset > 3) + display.nibs_per_line = + (NIBBLES_PER_ROW+saturn.line_offset+2) & 0xfff; + else + display.nibs_per_line = + (NIBBLES_PER_ROW+saturn.line_offset) & 0xfff; + display.disp_end = display.disp_start + + (display.nibs_per_line * (display.lines + 1)); + device.display_touched = DISP_INSTR_OFF; + } +#ifdef DEBUG_DISPLAY + fprintf(stderr, "%.5lx: DISP ON: %x\n", saturn.PC, display.on); +#endif + return; + case 0x101: /* CONTRAST CONTROL */ + saturn.contrast_ctrl = val; + display.contrast &= ~0x0f; + display.contrast |= val; +#ifdef DEBUG_CONTRAST + fprintf(stderr, "%.5lx: Contrast: 0x%x\n", saturn.PC, display.contrast); +#endif + device.contrast_touched = 1; + return; + case 0x102: /* DISPLAY TEST */ + display.contrast &= ~0xf0; + display.contrast |= ((val & 0x1) << 4); +#ifdef DEBUG_CONTRAST + fprintf(stderr, "%.5lx: Contrast: 0x%x\n", saturn.PC, display.contrast); +#endif + device.contrast_touched = 1; + /* Fall through */ + case 0x103: /* DISPLAY TEST */ + saturn.disp_test &= ~nibble_masks[addr - 0x102]; + saturn.disp_test |= val << ((addr - 0x102) * 4); +#ifdef DEBUG_DISPLAY + fprintf(stderr, "%.5lx: DISP TEST: %x\n", saturn.PC, saturn.disp_test); +#endif + device.disp_test_touched = 1; + return; + case 0x104: case 0x105: case 0x106: case 0x107: /* CRC */ + saturn.crc &= ~nibble_masks[addr - 0x104]; + saturn.crc |= val << ((addr - 0x104) * 4); + return; + case 0x108: /* POWER STATUS */ + saturn.power_status = val; + device.power_status_touched = 1; + return; + case 0x109: /* POWER CONTROL */ + saturn.power_ctrl = val; + device.power_ctrl_touched = 1; + return; + case 0x10a: /* MODE */ + saturn.mode = val; + device.mode_touched = 1; + return; + case 0x10b: case 0x10c: /* ANNUNC */ + saturn.annunc &= ~nibble_masks[addr - 0x10b]; + saturn.annunc |= val << ((addr - 0x10b) * 4); + display.annunc = saturn.annunc; + device.ann_touched = 1; + return; + case 0x10d: /* BAUD */ + saturn.baud = val; + device.baud_touched = 1; +#ifdef DEBUG_SERIALb + fprintf(stderr, "%.5lx: BAUD write: %x\n", saturn.PC, saturn.baud); +#endif + return; + case 0x10e: /* CARD CONTROL */ + saturn.card_ctrl = val; + if (saturn.card_ctrl & 0x02) + saturn.MP = 1; + if (saturn.card_ctrl & 0x01) + do_interupt(); + device.card_ctrl_touched = 1; +#ifdef DEBUG_CARDS + fprintf(stderr, "%.5lx: CardControl write: %x\n", + saturn.PC, saturn.card_ctrl); +#endif + return; + case 0x10f: /* CARD STATUS */ +#ifdef DEBUG_CARDS + fprintf(stderr, "%.5lx: CardStatus write: %x\n", + saturn.PC, saturn.card_status); +#endif + return; + case 0x110: /* IO CONTROL */ + saturn.io_ctrl = val; + device.ioc_touched = 1; +#ifdef DEBUG_SERIAL + fprintf(stderr, "%.5lx: IOC write: %x\n", saturn.PC, saturn.io_ctrl); +#endif + return; + case 0x111: /* RCS */ + saturn.rcs = val; +#ifdef DEBUG_SERIAL + fprintf(stderr, "%.5lx: RCS: %x\n", saturn.PC, saturn.rcs); +#endif + return; + case 0x112: /* TCS */ + saturn.tcs = val; +#ifdef DEBUG_SERIAL + fprintf(stderr, "%.5lx: TCS: %x\n", saturn.PC, saturn.tcs); +#endif + return; + case 0x113: /* CRER */ + saturn.rcs &= 0x0b; +#ifdef DEBUG_SERIAL + fprintf(stderr, "%.5lx: CRER, RCS: %x\n", saturn.PC, saturn.rcs); +#endif + return; + case 0x114: case 0x115: /* RBR */ + return; + case 0x116: case 0x117: /* TBR */ + saturn.tbr &= ~nibble_masks[addr - 0x116]; + saturn.tbr |= val << ((addr - 0x116) * 4); + saturn.tcs |= 0x01; + device.tbr_touched = 1; + return; + case 0x118: case 0x119: /* SERVICE REQ */ + saturn.sreq &= ~nibble_masks[addr - 0x118]; + saturn.sreq |= val << ((addr - 0x118) * 4); + device.sreq_touched = 1; +#ifdef DEBUG_SERIAL + fprintf(stderr, "%.5lx: SREQ? write: %x\n", saturn.PC, saturn.sreq); +#endif + return; + case 0x11a: /* IR CONTROL */ + saturn.ir_ctrl = val; + device.ir_ctrl_touched = 1; +#ifdef DEBUG_IR + fprintf(stderr, "%.5lx: IRC write: %x\n", saturn.PC, saturn.ir_ctrl); +#endif + return; + case 0x11b: /* BASE NIB OFFSET */ + saturn.base_off = val; + device.base_off_touched = 1; + return; + case 0x11c: /* LED CONTROL */ + saturn.lcr = val; + device.lcr_touched = 1; +#ifdef DEBUG_IR + fprintf(stderr, "%.5lx: LCR write: %x\n", saturn.PC, saturn.lcr); +#endif + return; + case 0x11d: /* LED BUFFER */ + saturn.lbr = val; + device.lbr_touched = 1; +#ifdef DEBUG_IR + fprintf(stderr, "%.5lx: LBR write: %x\n", saturn.PC, saturn.lbr); +#endif + return; + case 0x11e: /* SCRATCH PAD */ + saturn.scratch = val; + device.scratch_touched = 1; + return; + case 0x11f: /* BASENIBBLE */ + saturn.base_nibble = val; + device.base_nibble_touched = 1; +#ifdef DEBUG_BASE_NIBBLE + if (opt_gx) + fprintf(stderr, "%.5lx: BASENIB: %x\n", saturn.PC, saturn.base_nibble); +#endif + return; + case 0x120: case 0x121: case 0x122: case 0x123: /* DISP_ADDR */ + case 0x124: + saturn.disp_addr &= ~nibble_masks[addr - 0x120]; + saturn.disp_addr |= val << ((addr - 0x120) * 4); + if (display.disp_start != (saturn.disp_addr & 0xffffe)) { + display.disp_start = saturn.disp_addr & 0xffffe; + display.disp_end = display.disp_start + + (display.nibs_per_line * (display.lines + 1)); + device.display_touched = DISP_INSTR_OFF; + } +#ifdef DEBUG_DISPLAY + fprintf(stderr, "%.5lx: DISPLAY: %lx\n", saturn.PC, display.disp_start); + fprintf(stderr, "%.5lx: DISP END: %lx\n", saturn.PC, display.disp_end); +#endif + return; + case 0x125: case 0x126: case 0x127: /* LINE_OFFSET */ + saturn.line_offset &= ~nibble_masks[addr - 0x125]; + saturn.line_offset |= val << ((addr - 0x125) * 4); + if (saturn.line_offset != old_line_offset) { + old_line_offset = saturn.line_offset; + if (display.offset > 3) + display.nibs_per_line = + (NIBBLES_PER_ROW+saturn.line_offset+2) & 0xfff; + else + display.nibs_per_line = + (NIBBLES_PER_ROW+saturn.line_offset) & 0xfff; + display.disp_end = display.disp_start + + (display.nibs_per_line * (display.lines + 1)); + device.display_touched = DISP_INSTR_OFF; + } +#ifdef DEBUG_DISPLAY + fprintf(stderr, "%.5lx: DISP LINE SIZE: %x\n", + saturn.PC, display.nibs_per_line); + fprintf(stderr, "%.5lx: DISP END: %lx\n", saturn.PC, display.disp_end); +#endif + return; + case 0x128: case 0x129: /* LINE_COUNT */ + saturn.line_count &= ~nibble_masks[addr - 0x128]; + saturn.line_count |= val << ((addr - 0x128) * 4); + line_counter = -1; + if (display.lines != (saturn.line_count & 0x3f)) { + display.lines = saturn.line_count & 0x3f; + if (display.lines == 0) + display.lines = 63; + disp.lines = 2 * display.lines; + display.disp_end = display.disp_start + + (display.nibs_per_line * (display.lines + 1)); + device.display_touched = DISP_INSTR_OFF; + } +#ifdef DEBUG_DISPLAY + fprintf(stderr, "%.5lx: DISP LINES: %x\n", saturn.PC, display.lines); + fprintf(stderr, "%.5lx: DISP END: %lx\n", saturn.PC, display.disp_end); +#endif + return; + case 0x12a: case 0x12b: case 0x12c: case 0x12d: /* Dont know yet */ + saturn.unknown &= ~nibble_masks[addr - 0x12a]; + saturn.unknown |= val << ((addr - 0x12a) * 4); +#ifdef DEBUG_UNKNOWN + fprintf(stderr, "Unknown device @0x%ld: %.4x\n", addr, saturn.unknown); +#endif + device.unknown_touched = 1; + return; + case 0x12e: /* TIMER 1 CONTROL */ + saturn.t1_ctrl = val; + device.t1_ctrl_touched = 1; + return; + case 0x12f: /* TIMER 2 CONTROL */ + saturn.t2_ctrl = val; + device.t2_ctrl_touched = 1; + return; + case 0x130: case 0x131: case 0x132: case 0x133: /* MENU_ADDR */ + case 0x134: + saturn.menu_addr &= ~nibble_masks[addr - 0x130]; + saturn.menu_addr |= val << ((addr - 0x130) * 4); + if (display.menu_start != saturn.menu_addr) { + display.menu_start = saturn.menu_addr; + display.menu_end = display.menu_start + 0x110; + device.display_touched = DISP_INSTR_OFF; + } + return; + case 0x135: case 0x136: /* Dont know yet 2 */ + saturn.unknown2 &= ~nibble_masks[addr - 0x135]; + saturn.unknown2 |= val << ((addr - 0x135) * 4); +#ifdef DEBUG_UNKNOWN + fprintf(stderr, "Unknown device @0x%ld: %.2x\n", addr, saturn.unknown2); +#endif + device.unknown2_touched = 1; + return; + case 0x137: /* TIMER1 */ + saturn.timer1 = val; + device.t1_touched = 1; + return; + case 0x138: case 0x139: case 0x13a: case 0x13b: + case 0x13c: case 0x13d: case 0x13e: case 0x13f: /* TIMER2 */ + saturn.timer2 &= ~nibble_masks[addr - 0x138]; + saturn.timer2 |= val << ((addr - 0x138) * 4); + device.t2_touched = 1; + return; + default: + if (!quiet) + fprintf(stderr, "%.5lx: UNKNOWN DEVICE WRITE AT 0x%lx !!!\n", + saturn.PC, addr); + return; + } +} + +int +#ifdef __FunctionProto__ +read_dev_mem(long addr) +#else +read_dev_mem(addr) +long addr; +#endif +{ + switch ((int)addr) { + case 0x100: /* DISPLAY IO */ + return saturn.disp_io & 0x0f; + case 0x101: /* CONTRAST CONTROL */ + return saturn.contrast_ctrl & 0x0f; + case 0x102: case 0x103: /* DISPLAY TEST */ + return (saturn.disp_test >> ((addr - 0x102) * 4)) & 0x0f; + case 0x104: case 0x105: case 0x106: case 0x107: /* CRC */ + return (saturn.crc >> ((addr - 0x104) * 4)) & 0x0f; + case 0x108: /* POWER STATUS */ + return saturn.power_status & 0x0f; + case 0x109: /* POWER CONTROL */ + return saturn.power_ctrl & 0x0f; + case 0x10a: /* MODE */ + return saturn.mode & 0x0f; + case 0x10b: case 0x10c: /* ANNUNC */ + return (saturn.annunc >> ((addr - 0x10b) * 4)) & 0x0f; + case 0x10d: /* BAUD */ +#ifdef DEBUG_SERIALb + fprintf(stderr, "%.5lx: BAUD read: %x\n", saturn.PC, saturn.baud); +#endif + return saturn.baud & 0x0f; + case 0x10e: /* CARD CONTROL */ + return saturn.card_ctrl & 0x0f; + case 0x10f: /* CARD STATUS */ + return saturn.card_status & 0x0f; + case 0x110: /* IO CONTROL */ +#ifdef DEBUG_SERIAL + fprintf(stderr, "%.5lx: IOC read: %x\n", saturn.PC, saturn.io_ctrl); +#endif + return saturn.io_ctrl & 0x0f; + case 0x111: /* RCS */ +#ifdef DEBUG_SERIAL + fprintf(stderr, "%.5lx: RCS read: %x\n", saturn.PC, saturn.rcs); +#endif + return saturn.rcs & 0x0f; + case 0x112: /* TCS */ +#ifdef DEBUG_SERIAL + fprintf(stderr, "%.5lx: TCS read: %x\n", saturn.PC, saturn.tcs); +#endif + return saturn.tcs & 0x0f; + case 0x113: /* CRER */ + return 0x00; + case 0x114: case 0x115: /* RBR */ + saturn.rcs &= 0x0e; + device.rbr_touched = 1; + device_check = 1; + schedule_event = 0; + return (saturn.rbr >> ((addr - 0x114) * 4)) & 0x0f; + case 0x116: case 0x117: /* TBR */ + return 0x00; + case 0x118: case 0x119: /* SERVICE REQ */ +#ifdef DEBUG_SERIAL + fprintf(stderr, "%.5lx: SREQ? read: %x\n", saturn.PC, saturn.sreq); +#endif + return (saturn.sreq >> ((addr - 0x118) * 4)) & 0x0f; + case 0x11a: /* IR CONTROL */ +#ifdef DEBUG_IR + fprintf(stderr, "%.5lx: IRC read: %x\n", saturn.PC, saturn.ir_ctrl); +#endif + return saturn.ir_ctrl & 0x0f; + case 0x11b: /* BASE NIB OFFSET */ + return saturn.base_off & 0x0f; + case 0x11c: /* LED CONTROL */ +#if 0 +#ifdef DEBUG_IR + fprintf(stderr, "%.5lx: LCR read: %x\n", saturn.PC, saturn.lcr); +#endif +#endif + return saturn.lcr & 0x0f; + case 0x11d: /* LED BUFFER */ +#if 0 +#ifdef DEBUG_IR + fprintf(stderr, "%.5lx: LBR read: %x\n", saturn.PC, saturn.lbr); +#endif +#endif + return saturn.lbr & 0x0f; + case 0x11e: /* SCRATCH PAD */ + return saturn.scratch & 0x0f; + case 0x11f: /* BASENIBBLE */ + return saturn.base_nibble & 0x0f; + case 0x120: case 0x121: case 0x122: case 0x123: /* DISP_ADDR */ + case 0x124: + return (saturn.disp_addr >> ((addr - 0x120) * 4)) & 0x0f; + case 0x125: case 0x126: case 0x127: /* LINE_OFFSET */ + return (saturn.line_offset >> ((addr - 0x125) * 4)) & 0x0f; + case 0x128: case 0x129: /* LINE_COUNT */ + line_counter++; + if (line_counter > 0x3f) + line_counter = -1; + return (((saturn.line_count & 0xc0) | (line_counter & 0x3f)) >> + ((addr - 0x128) * 4)) & 0x0f; + case 0x12a: case 0x12b: case 0x12c: case 0x12d: /* Dont know yet */ + return (saturn.unknown >> ((addr - 0x12a) * 4)) & 0x0f; + case 0x12e: /* TIMER 1 CONTROL */ + return saturn.t1_ctrl & 0x0f; + case 0x12f: /* TIMER 2 CONTROL */ + return saturn.t2_ctrl & 0x0f; + case 0x130: case 0x131: case 0x132: case 0x133: /* MENU_ADDR */ + case 0x134: + return (saturn.menu_addr >> ((addr - 0x130) * 4)) & 0x0f; + case 0x135: case 0x136: /* Dont know yet 2 */ + return (saturn.unknown2 >> ((addr - 0x135) * 4)) & 0x0f; + case 0x137: + return saturn.timer1 & 0xf; + case 0x138: case 0x139: case 0x13a: case 0x13b: + case 0x13c: case 0x13d: case 0x13e: case 0x13f: + return (saturn.timer2 >> ((addr - 0x138) * 4)) & 0xf; + default: + if (!quiet) + fprintf(stderr, "%.5lx: UNKNOWN DEVICE READ AT 0x%lx !!!\n", + saturn.PC, addr); + return 0x00; + } +} + +void +#ifdef __FunctionProto__ +write_nibble_sx(long addr, int val) +#else +write_nibble_sx(addr, val) +long addr; +int val; +#endif +{ + addr &= 0xfffff; + val &= 0x0f; + switch ((int)(addr >> 16) & 0x0f) { + case 0: + if (addr < 0x140 && addr >= 0x100 && + saturn.mem_cntl[MCTL_MMIO_SX].config[0] == 0x100) + { + write_dev_mem(addr, val); + return; + } +#ifdef DEBUG_BAD_MEM + fprintf(stderr, "%.5lx: write to ROM at %.5lx\n", + saturn.PC, addr); +#endif + return; + case 1: case 2: case 3: case 4: case 5: case 6: +#ifdef DEBUG_BAD_MEM + fprintf(stderr, "%.5lx: write to ROM at %.5lx\n", + saturn.PC, addr); +#endif + return; + case 7: + if (saturn.mem_cntl[MCTL_SysRAM_SX].config[0] == 0x70000) + { + if (saturn.mem_cntl[MCTL_SysRAM_SX].config[1] == 0xfc000 + && addr < 0x74000) + { + saturn.ram[addr - 0x70000] = val; + break; + } + if (saturn.mem_cntl[MCTL_SysRAM_SX].config[1] == 0xfe000 + && addr < 0x72000) + { + saturn.ram[addr - 0x70000] = val; + break; + } + if (saturn.mem_cntl[MCTL_SysRAM_SX].config[1] == 0xf0000) + { + saturn.ram[addr - 0x70000] = val; + break; + } + } +#ifdef DEBUG_BAD_MEM + fprintf(stderr, "%.5lx: write to ROM at %.5lx\n", + saturn.PC, addr); +#endif + return; + case 8: case 9: case 0xa: case 0xb: + if (saturn.mem_cntl[MCTL_PORT1_SX].config[0] == 0x80000) + { + if (port1_is_ram) + saturn.port1[(addr - 0x80000) & port1_mask] = val; + return; + } + if (saturn.mem_cntl[MCTL_PORT2_SX].config[0] == 0x80000) + { + if (port2_is_ram) + saturn.port2[(addr - 0x80000) & port2_mask] = val; + return; + } +#ifdef DEBUG_BAD_MEM + fprintf(stderr, "%.5lx: write to NULL at %.5lx\n", + saturn.PC, addr); +#endif + return; + case 0xc: case 0xd: case 0xe: + if (saturn.mem_cntl[MCTL_PORT1_SX].config[0] == 0xc0000) + { + if (port1_is_ram) + saturn.port1[(addr - 0xc0000) & port1_mask] = val; + return; + } + if (saturn.mem_cntl[MCTL_PORT2_SX].config[0] == 0xc0000) + { + if (port2_is_ram) + saturn.port2[(addr - 0xc0000) & port2_mask] = val; + return; + } +#ifdef DEBUG_BAD_MEM + fprintf(stderr, "%.5lx: write to NULL at %.5lx\n", + saturn.PC, addr); +#endif + return; + case 0xf: + if (saturn.mem_cntl[MCTL_SysRAM_SX].config[0] == 0xf0000) + { + saturn.ram[addr - 0xf0000] = val; + break; + } + if (saturn.mem_cntl[MCTL_PORT1_SX].config[0] == 0xc0000) + { + if (port1_is_ram) + saturn.port1[(addr - 0xc0000) & port1_mask] = val; + return; + } + if (saturn.mem_cntl[MCTL_PORT2_SX].config[0] == 0xc0000) + { + if (port2_is_ram) + saturn.port2[(addr - 0xc0000) & port2_mask] = val; + return; + } +#ifdef DEBUG_BAD_MEM + fprintf(stderr, "%.5lx: write to NULL at %.5lx\n", + saturn.PC, addr); +#endif + return; + } + if (device.display_touched || !disp.mapped) + return; + if (addr >= display.disp_start && addr < display.disp_end) + { + disp_draw_nibble(addr, val); + } + if (display.lines == 63) + return; + if (addr >= display.menu_start && addr < display.menu_end) + { + menu_draw_nibble(addr, val); + } +} + +void +#ifdef __FunctionProto__ +write_nibble_gx(long addr, int val) +#else +write_nibble_gx(addr, val) +long addr; +int val; +#endif +{ + addr &= 0xfffff; + val &= 0x0f; + switch ((int)(addr >> 16) & 0x0f) + { + case 0: + if (addr < 0x140 && addr >= 0x100 && + saturn.mem_cntl[MCTL_MMIO_GX].config[0] == 0x100) + { + write_dev_mem(addr, val); + return; + } +#ifdef DEBUG_BAD_MEM + fprintf(stderr, "%.5lx: write to ROM at %.5lx\n", + saturn.PC, addr); +#endif + return; + case 1: case 2: case 3: case 5: case 6: +#ifdef DEBUG_BAD_MEM + fprintf(stderr, "%.5lx: BAD WRITE TO ROM AT ADDRESS %.5lx\n", + saturn.PC, addr); +#endif + return; + case 4: + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x40000) + { + saturn.ram[addr - 0x40000] = val; + break; + } +#ifdef DEBUG_BAD_MEM + fprintf(stderr, "%.5lx: BAD WRITE TO ROM AT ADDRESS %.5lx\n", + saturn.PC, addr); +#endif + return; + case 7: + if (addr >= 0x7f000 && + saturn.mem_cntl[MCTL_BANK_GX].config[0] == 0x7f000) + { +#ifdef DEBUG_BANK_SWITCH + fprintf(stderr, "%.5lx: write to bank switch at %.5lx\n", + saturn.PC, addr); +#endif + return; + } + if (addr >= 0x7e000 && addr < 0x7f000 && + saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0x7e000) + { +#ifdef DEBUG_PORTS + fprintf(stderr, "%.5lx: write to port 1 at %.5lx\n", + saturn.PC, addr); +#endif + return; + } + if (addr >= 0x7e000 && addr < 0x7f000 && + saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0x7e000) + { +#ifdef DEBUG_PORTS + fprintf(stderr, "%.5lx: write to port 2 at %.5lx\n", + saturn.PC, addr); +#endif + return; + } +#ifdef DEBUG_BAD_MEM + fprintf(stderr, "%.5lx: write to ROM at %.5lx\n", + saturn.PC, addr); +#endif + return; + case 8: + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000) + { + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfc000 + && addr < 0x84000) + { + saturn.ram[addr - 0x80000] = val; + break; + } + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfe000 + && addr < 0x82000) + { + saturn.ram[addr - 0x80000] = val; + break; + } + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xf0000) + { + saturn.ram[addr - 0x80000] = val; + break; + } + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000) + { + saturn.ram[addr - 0x80000] = val; + break; + } + } +#ifdef DEBUG_BAD_MEM + fprintf(stderr, "%.5lx: write to ROM at %.5lx\n", + saturn.PC, addr); +#endif + return; + case 9: + if (saturn.mem_cntl[MCTL_BANK_GX].config[0] == 0x90000) + { + if (addr < 0x91000) + { +#ifdef DEBUG_BANK_SWITCH + fprintf(stderr, "%.5lx: write to bank switch at %.5lx\n", + saturn.PC, addr); +#endif + return; + } + } + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000) + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000) + { + saturn.ram[addr - 0x80000] = val; + break; + } +#ifdef DEBUG_BAD_MEM + fprintf(stderr, "%.5lx: write to ROM at %.5lx\n", + saturn.PC, addr); +#endif + return; + case 0xa: + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000) + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000) + { + saturn.ram[addr - 0x80000] = val; + break; + } + if (saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0xa0000) + { + if (port1_is_ram) + saturn.port1[(addr - 0xa0000) & port1_mask] = val; + return; + } +#ifdef DEBUG_BAD_MEM + fprintf(stderr, "%.5lx: write to ROM at %.5lx\n", + saturn.PC, addr); +#endif + return; + case 0xb: + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000) + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000) + { + saturn.ram[addr - 0x80000] = val; + break; + } + if (saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0xb0000) + { + if (port2_is_ram) + saturn.port2[((saturn.bank_switch << 18) + (addr - 0xb0000)) + & port2_mask] = val; +/* + if (port2_size > (saturn.bank_switch << 18)) + { + if (port2_is_ram) + saturn.port2[(saturn.bank_switch << 18) + + (addr - 0xb0000)] = val; + } +*/ + return; + } +#ifdef DEBUG_BAD_MEM + fprintf(stderr, "%.5lx: write to ROM at %.5lx\n", + saturn.PC, addr); +#endif + return; + case 0xc: + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0xc0000) + { + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfc000 + && addr < 0xc4000) + { + saturn.ram[addr - 0xc0000] = val; + break; + } + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfe000 + && addr < 0xc2000) + { + saturn.ram[addr - 0xc0000] = val; + break; + } + saturn.ram[addr - 0xc0000] = val; + break; + } + if (saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0xc0000) + { + if (port1_is_ram) + saturn.port1[(addr - 0xc0000) & port1_mask] = val; + return; + } + if (saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0xc0000) + { + if (port2_is_ram) + saturn.port2[((saturn.bank_switch << 18) + (addr - 0xc0000)) + & port2_mask] = val; +/* + if (port2_size > (saturn.bank_switch << 18)) + { + if (port2_is_ram) + saturn.port2[(saturn.bank_switch << 18) + + (addr - 0xc0000)] = val; + } +*/ + return; + } +#ifdef DEBUG_BAD_MEM + fprintf(stderr, "%.5lx: write to ROM at %.5lx\n", + saturn.PC, addr); +#endif + return; + case 0xd: case 0xe: case 0xf: + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0xc0000) + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000) + { + saturn.ram[addr - 0xc0000] = val; + break; + } + if (saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0xc0000) + if (saturn.mem_cntl[MCTL_PORT1_GX].config[1] == 0xc0000) + { + if (port1_is_ram) + saturn.port1[(addr - 0xc0000) & port1_mask] = val; + return; + } + if (saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0xc0000) + if (saturn.mem_cntl[MCTL_PORT2_GX].config[1] == 0xc0000) + { + if (port2_is_ram) + saturn.port2[((saturn.bank_switch << 18) + (addr - 0xc0000)) + & port2_mask] = val; +/* + if (port2_size > (saturn.bank_switch << 18)) + { + if (port2_is_ram) + saturn.port2[(saturn.bank_switch << 18) + + (addr - 0xc0000)] = val; + } +*/ + return; + } +#ifdef DEBUG_BAD_MEM + fprintf(stderr, "%.5lx: write to ROM at %.5lx\n", + saturn.PC, addr); +#endif + return; + } + if (device.display_touched || !disp.mapped) + return; + if (addr >= display.disp_start && addr < display.disp_end) + { + disp_draw_nibble(addr, val); + } + if (display.lines == 63) + return; + if (addr >= display.menu_start && addr < display.menu_end) + { + menu_draw_nibble(addr, val); + } + return; +} + +int +#ifdef __FunctionProto__ +read_nibble_sx(long addr) +#else +read_nibble_sx(addr) +long addr; +#endif +{ + addr &= 0xfffff; + switch ((int)(addr >> 16) & 0x0f) { + case 0: + if (addr < 0x140 && addr >= 0x100) + { + if (saturn.mem_cntl[MCTL_MMIO_SX].config[0] == 0x100) + return read_dev_mem(addr); + else + return 0x00; + } + return saturn.rom[addr]; + case 1: case 2: case 3: case 4: case 5: case 6: + return saturn.rom[addr]; + case 7: + if (saturn.mem_cntl[MCTL_SysRAM_SX].config[0] == 0x70000) + { + if (saturn.mem_cntl[MCTL_SysRAM_SX].config[1] == 0xfc000 + && addr < 0x74000) + return saturn.ram[addr - 0x70000]; + if (saturn.mem_cntl[MCTL_SysRAM_SX].config[1] == 0xfe000 + && addr < 0x72000) + return saturn.ram[addr - 0x70000]; + if (saturn.mem_cntl[MCTL_SysRAM_SX].config[1] == 0xf0000) + return saturn.ram[addr - 0x70000]; + } + return saturn.rom[addr]; + case 8: case 9: case 0xa: case 0xb: + if (saturn.mem_cntl[MCTL_PORT1_SX].config[0] == 0x80000) + { + return saturn.port1[(addr - 0x80000) & port1_mask]; + } + if (saturn.mem_cntl[MCTL_PORT2_SX].config[0] == 0x80000) + { + return saturn.port2[(addr - 0x80000) & port2_mask]; + } + return 0x00; + case 0xc: case 0xd: case 0xe: + if (saturn.mem_cntl[MCTL_PORT1_SX].config[0] == 0xc0000) + { + return saturn.port1[(addr - 0xc0000) & port1_mask]; + } + if (saturn.mem_cntl[MCTL_PORT2_SX].config[0] == 0xc0000) + { + return saturn.port2[(addr - 0xc0000) & port2_mask]; + } + return 0x00; + case 0xf: + if (saturn.mem_cntl[MCTL_SysRAM_SX].config[0] == 0xf0000) + return saturn.ram[addr - 0xf0000]; + if (saturn.mem_cntl[MCTL_PORT1_SX].config[0] == 0xc0000) + { + return saturn.port1[(addr - 0xc0000) & port1_mask]; + } + if (saturn.mem_cntl[MCTL_PORT2_SX].config[0] == 0xc0000) + { + return saturn.port2[(addr - 0xc0000) & port2_mask]; + } + return 0x00; + } + return 0x00; +} + +int +#ifdef __FunctionProto__ +read_nibble_gx(long addr) +#else +read_nibble_gx(addr) +long addr; +#endif +{ + addr &= 0xfffff; + switch ((int)(addr >> 16) & 0x0f) + { + case 0: + if (addr < 0x140 && addr >= 0x100) + { + if (saturn.mem_cntl[0].config[0] == 0x100) + return read_dev_mem(addr); + else + return 0x00; + } + return saturn.rom[addr]; + case 1: case 2: case 3: case 5: case 6: + return saturn.rom[addr]; + case 4: + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x40000) + return saturn.ram[addr - 0x40000]; + return saturn.rom[addr]; + case 7: + if (addr >= 0x7f000 && + saturn.mem_cntl[MCTL_BANK_GX].config[0] == 0x7f000) + { + if (addr == 0x7f000) + { + saturn.bank_switch = 0; +#ifdef DEBUG_BANK_SWITCH + fprintf(stderr, "%.5lx: disable bank switch\n", saturn.PC); +#endif + } + if (addr >= 0x7f040 && addr < 0x7f080) + { + saturn.bank_switch = (addr - 0x7f040) / 2; +#ifdef DEBUG_BANK_SWITCH + fprintf(stderr, "%.5lx: switch to bank %d\n", + saturn.PC, saturn.bank_switch); +#endif + } + return 0x7; + } + if (addr >= 0x7e000 && addr < 0x7f000 && + saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0x7e000) + { +#ifdef DEBUG_PORTS + fprintf(stderr, "%.5lx: read from port 1 at %.5lx\n", + saturn.PC, addr); +#endif + return 0x7; + } + if (addr >= 0x7e000 && addr < 0x7f000 && + saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0x7e000) + { +#ifdef DEBUG_PORTS + fprintf(stderr, "%.5lx: read from port 2 at %.5lx\n", + saturn.PC, addr); +#endif + return 0x7; + } + return saturn.rom[addr]; + case 8: + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000) + { + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfc000 + && addr < 0x84000) + return saturn.ram[addr - 0x80000]; + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfe000 + && addr < 0x82000) + return saturn.ram[addr - 0x80000]; + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xf0000) + return saturn.ram[addr - 0x80000]; + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000) + return saturn.ram[addr - 0x80000]; + } + return saturn.rom[addr]; + case 9: + if (saturn.mem_cntl[0].config[0] == 0x90000) + { + if (addr < 0x91000) + { + if (addr == 0x90000) + { + saturn.bank_switch = 0; +#ifdef DEBUG_BANK_SWITCH + fprintf(stderr, "%.5lx: disable bank switch\n", saturn.PC); +#endif + } + if (addr >= 0x90040 && addr < 0x90080) + { + saturn.bank_switch = (addr - 0x90040) / 2; +#ifdef DEBUG_BANK_SWITCH + fprintf(stderr, "%.5lx: switch to bank %d\n", + saturn.PC, saturn.bank_switch); +#endif + } + return 0x7; + } + } + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000) + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000) + return saturn.ram[addr - 0x80000]; + return saturn.rom[addr]; + case 0xa: + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000) + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000) + return saturn.ram[addr - 0x80000]; + if (saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0xa0000) + { + return saturn.port1[(addr - 0xa0000) & port1_mask]; + } + return saturn.rom[addr]; + case 0xb: + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000) + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000) + return saturn.ram[addr - 0x80000]; + if (saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0xb0000) + { + return saturn.port2[((saturn.bank_switch << 18) + (addr - 0xb0000)) + & port2_mask]; +/* + if (port2_size > (saturn.bank_switch << 18)) + { + return saturn.port2[(saturn.bank_switch << 18) + + (addr - 0xb0000)]; + } + return 0x00; +*/ + } + return saturn.rom[addr]; + case 0xc: + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0xc0000) + { + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfc000 + && addr < 0xc4000) + return saturn.ram[addr - 0xc0000]; + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfe000 + && addr < 0xc2000) + return saturn.ram[addr - 0xc0000]; + return saturn.ram[addr - 0xc0000]; + } + if (saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0xc0000) + { + return saturn.port1[(addr - 0xc0000) & port1_mask]; + } + if (saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0xc0000) + { + return saturn.port2[((saturn.bank_switch << 18) + (addr - 0xc0000)) + & port2_mask]; +/* + if (port2_size > (saturn.bank_switch << 18)) + { + return saturn.port2[(saturn.bank_switch << 18) + + (addr - 0xc0000)]; + } + return 0x00; +*/ + } + return saturn.rom[addr]; + case 0xd: case 0xe: case 0xf: + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0xc0000) + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000) + return saturn.ram[addr - 0xc0000]; + if (saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0xc0000) + if (saturn.mem_cntl[MCTL_PORT1_GX].config[1] == 0xc0000) + { + return saturn.port1[(addr - 0xc0000) & port1_mask]; + } + if (saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0xc0000) + if (saturn.mem_cntl[MCTL_PORT2_GX].config[1] == 0xc0000) + { + return saturn.port2[((saturn.bank_switch << 18) + + (addr - 0xc0000)) & port2_mask]; +/* + if (port2_size > (saturn.bank_switch << 18)) + { + return saturn.port2[(saturn.bank_switch << 18) + + (addr - 0xc0000)]; + } + return 0x00; +*/ + } + return saturn.rom[addr]; + } + return 0x00; +} + +int +#ifdef __FunctionProto__ +read_nibble_crc_sx(long addr) +#else +read_nibble_crc_sx(addr) +long addr; +#endif +{ + addr &= 0xfffff; + switch ((int)(addr >> 16) & 0x0f) { + case 0: + if (addr < 0x140 && addr >= 0x100) + { + if (saturn.mem_cntl[MCTL_MMIO_SX].config[0] == 0x100) + return read_dev_mem(addr); + else + return calc_crc(0x00); + } + return calc_crc(saturn.rom[addr]); + case 1: case 2: case 3: case 4: case 5: case 6: + return calc_crc(saturn.rom[addr]); + case 7: + if (saturn.mem_cntl[MCTL_SysRAM_SX].config[0] == 0x70000) + { + if (saturn.mem_cntl[MCTL_SysRAM_SX].config[1] == 0xfc000 + && addr < 0x74000) + return calc_crc(saturn.ram[addr - 0x70000]); + if (saturn.mem_cntl[MCTL_SysRAM_SX].config[1] == 0xfe000 + && addr < 0x72000) + return calc_crc(saturn.ram[addr - 0x70000]); + if (saturn.mem_cntl[MCTL_SysRAM_SX].config[1] == 0xf0000) + return calc_crc(saturn.ram[addr - 0x70000]); + } + return calc_crc(saturn.rom[addr]); + case 8: case 9: case 0xa: case 0xb: + if (saturn.mem_cntl[MCTL_PORT1_SX].config[0] == 0x80000) + { + return calc_crc(saturn.port1[(addr - 0x80000) & port1_mask]); + } + if (saturn.mem_cntl[MCTL_PORT2_SX].config[0] == 0x80000) + { + return calc_crc(saturn.port2[(addr - 0x80000) & port2_mask]); + } + return 0x00; + case 0xc: case 0xd: case 0xe: + if (saturn.mem_cntl[MCTL_PORT1_SX].config[0] == 0xc0000) + { + return calc_crc(saturn.port1[(addr - 0xc0000) & port1_mask]); + } + if (saturn.mem_cntl[MCTL_PORT2_SX].config[0] == 0xc0000) + { + return calc_crc(saturn.port2[(addr - 0xc0000) & port2_mask]); + } + return 0x00; + case 0xf: + if (saturn.mem_cntl[MCTL_SysRAM_SX].config[0] == 0xf0000) + return calc_crc(saturn.ram[addr - 0xf0000]); + if (saturn.mem_cntl[MCTL_PORT1_SX].config[0] == 0xc0000) + { + return calc_crc(saturn.port1[(addr - 0xc0000) & port1_mask]); + } + if (saturn.mem_cntl[MCTL_PORT2_SX].config[0] == 0xc0000) + { + return calc_crc(saturn.port2[(addr - 0xc0000) & port2_mask]); + } + return 0x00; + } + return 0x00; +} + +int +#ifdef __FunctionProto__ +read_nibble_crc_gx(long addr) +#else +read_nibble_crc_gx(addr) +long addr; +#endif +{ + addr &= 0xfffff; + switch ((int)(addr >> 16) & 0x0f) + { + case 0: + if (addr < 0x140 && addr >= 0x100) + { + if (saturn.mem_cntl[MCTL_MMIO_GX].config[0] == 0x100) + return read_dev_mem(addr); + else + return calc_crc(0x00); + } + return calc_crc(saturn.rom[addr]); + case 1: case 2: case 3: case 5: case 6: + return calc_crc(saturn.rom[addr]); + case 4: + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x40000) + return calc_crc(saturn.ram[addr - 0x40000]); + return calc_crc(saturn.rom[addr]); + case 7: + if (addr >= 0x7f000 && + saturn.mem_cntl[MCTL_BANK_GX].config[0] == 0x7f000) + { + if (addr == 0x7f000) + { + saturn.bank_switch = 0; +#ifdef DEBUG_BANK_SWITCH + fprintf(stderr, "%.5lx: disable bank switch\n", saturn.PC); +#endif + } + if (addr >= 0x7f040 && addr < 0x7f080) + { + saturn.bank_switch = (addr - 0x7f040) / 2; +#ifdef DEBUG_BANK_SWITCH + fprintf(stderr, "%.5lx: switch to bank %d\n", + saturn.PC, saturn.bank_switch); +#endif + } + return 0x7; + } + if (addr >= 0x7e000 && addr < 0x7f000 && + saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0x7e000) + { +#ifdef DEBUG_PORTS + fprintf(stderr, "%.5lx: read from port 1 at %.5lx\n", + saturn.PC, addr); +#endif + return 0x7; + } + if (addr >= 0x7e000 && addr < 0x7f000 && + saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0x7e000) + { +#ifdef DEBUG_PORTS + fprintf(stderr, "%.5lx: read from port 2 at %.5lx\n", + saturn.PC, addr); +#endif + return 0x7; + } + return calc_crc(saturn.rom[addr]); + case 8: + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000) + { + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfc000 + && addr < 0x84000) + return calc_crc(saturn.ram[addr - 0x80000]); + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfe000 + && addr < 0x82000) + return calc_crc(saturn.ram[addr - 0x80000]); + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xf0000) + return calc_crc(saturn.ram[addr - 0x80000]); + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000) + return calc_crc(saturn.ram[addr - 0x80000]); + } + return calc_crc(saturn.rom[addr]); + case 9: + if (saturn.mem_cntl[0].config[0] == 0x90000) + { + if (addr < 0x91000) + { + if (addr == 0x90000) + { + saturn.bank_switch = 0; +#ifdef DEBUG_BANK_SWITCH + fprintf(stderr, "%.5lx: disable bank switch\n", saturn.PC); +#endif + } + if (addr >= 0x90040 && addr < 0x90080) + { + saturn.bank_switch = (addr - 0x90040) / 2; +#ifdef DEBUG_BANK_SWITCH + fprintf(stderr, "%.5lx: switch to bank %d\n", + saturn.PC, saturn.bank_switch); +#endif + } + return 0x7; + } + } + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000) + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000) + return calc_crc(saturn.ram[addr - 0x80000]); + return calc_crc(saturn.rom[addr]); + case 0xa: + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000) + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000) + return calc_crc(saturn.ram[addr - 0x80000]); + if (saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0xa0000) + { + return calc_crc(saturn.port1[(addr - 0xa0000) & port1_mask]); + } + return calc_crc(saturn.rom[addr]); + case 0xb: + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000) + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000) + return calc_crc(saturn.ram[addr - 0x80000]); + if (saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0xb0000) + { + return calc_crc(saturn.port2[((saturn.bank_switch << 18) + + (addr - 0xb0000)) & port2_mask]); +/* + if (port2_size > (saturn.bank_switch << 18)) + { + return calc_crc(saturn.port2[(saturn.bank_switch << 18) + + (addr - 0xb0000)]); + } + return 0x00; +*/ + } + return calc_crc(saturn.rom[addr]); + case 0xc: + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0xc0000) + { + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfc000 + && addr < 0xc4000) + return calc_crc(saturn.ram[addr - 0xc0000]); + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfe000 + && addr < 0xc2000) + return calc_crc(saturn.ram[addr - 0xc0000]); + return calc_crc(saturn.ram[addr - 0xc0000]); + } + if (saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0xc0000) + { + return calc_crc(saturn.port1[(addr - 0xc0000) & port1_mask]); + } + if (saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0xc0000) + { + return calc_crc(saturn.port2[((saturn.bank_switch << 18) + + (addr - 0xc0000)) & port2_mask]); +/* + if (port2_size > (saturn.bank_switch << 18)) + { + return calc_crc(saturn.port2[(saturn.bank_switch << 18) + + (addr - 0xc0000)]); + } + return 0x00; +*/ + } + return calc_crc(saturn.rom[addr]); + case 0xd: case 0xe: case 0xf: + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0xc0000) + if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000) + return calc_crc(saturn.ram[addr - 0xc0000]); + if (saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0xc0000) + if (saturn.mem_cntl[MCTL_PORT1_GX].config[1] == 0xc0000) + { + return calc_crc(saturn.port1[(addr - 0xc0000) & port1_mask]); + } + if (saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0xc0000) + if (saturn.mem_cntl[MCTL_PORT2_GX].config[1] == 0xc0000) + { + return calc_crc(saturn.port2[((saturn.bank_switch << 18) + + (addr - 0xc0000)) & port2_mask]); +/* + if (port2_size > (saturn.bank_switch << 18)) + { + return calc_crc(saturn.port2[(saturn.bank_switch << 18) + + (addr - 0xc0000)]); + } + return 0x00; +*/ + } + return calc_crc(saturn.rom[addr]); + } + return 0x00; +} + +long +#ifdef __FunctionProto__ +read_nibbles(long addr, int len) +#else +read_nibbles(addr, len) +long addr; +int len; +#endif +{ + long val = 0; + + addr += len; + while (len-- > 0) { + val = (val << 4) | read_nibble(--addr); + } + return val; +} + +void +#ifdef __FunctionProto__ +write_nibbles(long addr, long val, int len) +#else +write_nibbles(addr, val, len) +long addr; +long val; +int len; +#endif +{ + while (len-- > 0) { + write_nibble(addr++, val); + val >>= 4; + } +} + +void +#ifdef __FunctionProto__ +dev_memory_init(void) +#else +dev_memory_init() +#endif +{ + if (opt_gx) + { + read_nibble = read_nibble_gx; + read_nibble_crc = read_nibble_crc_gx; + write_nibble = write_nibble_gx; + } + else + { + read_nibble = read_nibble_sx; + read_nibble_crc = read_nibble_crc_sx; + write_nibble = write_nibble_sx; + } + memset(&device, 0, sizeof(device)); +} + diff --git a/src/mkcard.c b/src/mkcard.c new file mode 100644 index 0000000..ecf0700 --- /dev/null +++ b/src/mkcard.c @@ -0,0 +1,130 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: mkcard.c,v $ + * Revision 1.1 1995/01/11 18:11:25 ecd + * Initial revision + * + * + * $Id: mkcard.c,v 1.1 1995/01/11 18:11:25 ecd Exp ecd $ + */ + + +#include "global.h" + +#include +#include +#include +#include +#ifdef SUNOS +#include +#endif +#include + +unsigned char *mem; + +int +#ifdef __FunctionProto__ +write_mem_file(char *name, unsigned char *mem, int size) +#else +write_mem_file(name, mem, size) +char *name; +unsigned char *mem; +int size; +#endif +{ + FILE *fp; + + if (NULL == (fp = fopen(name, "w"))) + { + fprintf(stderr, "can\'t open %s\n", name); + return 0; + } + + if (fwrite(mem, 1, (size_t)size, fp) != size) + { + fprintf(stderr, "can\'t write %s\n", name); + fclose(fp); + return 0; + } + + fclose(fp); + return 1; +} + +int +#ifdef __FunctionProto__ +main(int argc, char **argv) +#else +main(argc, argv) +int argc; +char **argv; +#endif +{ + long size; + char *name; + char *asize; + unsigned char *core; + + if (argc < 2) + { + fprintf(stderr, "usage: %s [32K | 128K | 1M | 2M | 4M] file-name\n", + argv[0]); + exit (1); + } + + name = argv[2]; + asize = argv[1]; + if (!strcmp(asize, "32K")) + size = 0x8000; + else if (!strcmp(asize, "128K")) + size = 0x20000; + else if (!strcmp(asize, "256K")) + size = 0x40000; + else if (!strcmp(asize, "512K")) + size = 0x80000; + else if (!strcmp(asize, "1M")) + size = 0x100000; + else if (!strcmp(asize, "2M")) + size = 0x200000; + else if (!strcmp(asize, "4M")) + size = 0x400000; + else + { + fprintf(stderr, + "%s: size must be one of 32K, 128K, 256K, 512K, 1M, 2M, or 4M\n", + argv[0]); + exit (1); + } + + if ((core = (unsigned char *)malloc(size)) == NULL) { + fprintf(stderr, "%s: can\'t malloc %ld bytes\n", argv[0], size); + exit (1); + } + memset(core, 0, size); + + if (!write_mem_file(name, core, size)) + { + fprintf(stderr, "%s: can\'t write to %s\n", argv[0], name); + exit (1); + } + + exit (0); +} + diff --git a/src/mmu.h b/src/mmu.h new file mode 100644 index 0000000..6d54564 --- /dev/null +++ b/src/mmu.h @@ -0,0 +1,53 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: mmu.h,v $ + * Revision 1.1 1995/01/11 18:11:25 ecd + * Initial revision + * + * + * $Id: mmu.h,v 1.1 1995/01/11 18:11:25 ecd Exp ecd $ + */ +#ifndef _MMU_H +#define _MMU_H 1 + + +#define NR_MCTL 6 + +#define MCTL_MMIO_SX 0 +#define MCTL_SysRAM_SX 1 +#define MCTL_PORT1_SX 2 +#define MCTL_PORT2_SX 3 +#define MCTL_EXTRA_SX 4 +#define MCTL_SysROM_SX 5 + +#define MCTL_MMIO_GX 0 +#define MCTL_SysRAM_GX 1 +#define MCTL_BANK_GX 2 +#define MCTL_PORT1_GX 3 +#define MCTL_PORT2_GX 4 +#define MCTL_SysROM_GX 5 + + +#if 0 +extern void init_mmu __ProtoType__((void)); +extern void reset_mmu __ProtoType__((void)); +#endif + +#endif /* !_MMU_H */ diff --git a/src/options.c b/src/options.c new file mode 100644 index 0000000..f702235 --- /dev/null +++ b/src/options.c @@ -0,0 +1,178 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: options.c,v $ + * Revision 1.5 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.4 1994/12/07 20:20:50 ecd + * more options + * + * Revision 1.4 1994/12/07 20:20:50 ecd + * more options + * + * Revision 1.3 1994/11/28 02:00:51 ecd + * complete rewrite + * + * Revision 1.2 1994/11/04 03:42:34 ecd + * finally implemented the first options + * + * Revision 1.1 1994/11/02 14:44:28 ecd + * Initial revision + * + * + * $Id: options.c,v 1.5 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#include "global.h" + +#include +#include +#include +#include + +#include "constants.h" +#include "resources.h" + +void +#ifdef __FunctionProto__ +usage(void) +#else +usage() +#endif +{ + fprintf(stdout, "\n\ +x48 Version %d.%d.%d, Copyright (c) 1994-2005 by Eddie C. Dost .\n\ +\n\ +usage:\n\t%s [-options ...]\n\ +\n\ +where options include:\n\ + -help print out this message\n\ + -display X server to contact\n\ + -name set application name to \n\ + -title set window title to \n\ + -geometry position of window\n\ + -iconGeom position of icon window\n\ + -iconic start iconic\n\ + -visual use visual \n\ + -mono force monochrome\n\ + -gray force grayscale\n\ + -monoIcon force monochrome icon\n\ + -smallFont to draw small labels (MTH - DEL)\n\ + -mediumFont to draw medium label (ENTER)\n\ + -largeFont to draw large labels (Numbers)\n\ + -connFont to display wire & IR connections\n\ + -/+xshm turn on/off XShm extension\n\ + -version print out version information\n\ + -copyright print out copyright information\n\ + -warranty print out warranty information\n\ + -verbose run verbosive\n\ + -quiet run quietly\n\ + -/+terminal turn on/off pseudo terminal interface\n\ + -/+serial turn on/off serial interface\n\ + -line use serial line for IR connection\n\ + -/+debug turn on/off debugger\n\ + -disasm use (\'HP\' or \'class\') mnemonics\n\ + -reset perform a reset (PC = 0) on startup\n\ + -initialize force initialization x48 from ROM-dump\n\ + -rom if initializing, read ROM from \n\ + -home use directory ~/ to save x48 files\n\ + -xrm set Xresource \n\ + -/+throttle turn off/on speed emulation\n\ + -/+netbook turn off/on netbook layout\n\ +\n", VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL, progname); + + fflush(stdout); + exit (1); +} + +void +#ifdef __FunctionProto__ +show_version(void) +#else +show_version() +#endif +{ + fprintf(stdout, "\n\ +%s Version %d.%d.%d, x48 is Copyright (c) 1994-2005 by Eddie C. Dost .\n\ +Compiled on %s by <%s> #%d\n\n", + progname, VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL, + COMPILE_TIME, COMPILE_BY, COMPILE_VERSION); +} + +void +#ifdef __FunctionProto__ +show_copyright(void) +#else +show_copyright() +#endif +{ + fprintf(stdout, "\n\ + COPYRIGHT\n\ +\n\ +X48 is an Emulator/Debugger for the HP-48 Handheld Calculator.\n\ +Copyright (C) 1994 by Eddie C. Dost .\n\ +\n\ +This program is free software; you can redistribute it and/or modify\n\ +it under the terms of the GNU General Public License as published by\n\ +the Free Software Foundation; either version 2 of the License, or\n\ +(at your option) any later version.\n\ +\n\ +This program is distributed in the hope that it will be useful,\n\ +but WITHOUT ANY WARRANTY; without even the implied warranty of\n\ +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\ +GNU General Public License for more details.\n\ +\n\ +You should have received a copy of the GNU General Public License\n\ +along with this program; if not, write to the Free Software\n\ +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n"); +} + +void +#ifdef __FunctionProto__ +show_warranty(void) +#else +show_warranty() +#endif +{ + fprintf(stdout, "\n\ + NO WARRANTY\n\ +\n\ + BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n\ +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n\ +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n\ +PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n\ +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n\ +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n\ +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n\ +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n\ +REPAIR OR CORRECTION.\n\ +\n\ + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n\ +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n\ +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n\ +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n\ +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n\ +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n\ +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n\ +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n\ +POSSIBILITY OF SUCH DAMAGES.\n\n"); +} + + diff --git a/src/options.h b/src/options.h new file mode 100644 index 0000000..efbbb21 --- /dev/null +++ b/src/options.h @@ -0,0 +1,121 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: options.h,v $ + * Revision 1.5 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.4 1994/12/07 20:16:41 ecd + * added more options + * + * Revision 1.4 1994/12/07 20:16:41 ecd + * added more options + * + * Revision 1.3 1994/11/28 02:19:22 ecd + * complete rewrite + * + * Revision 1.2 1994/11/04 03:44:47 ecd + * added first options + * + * Revision 1.1 1994/11/02 14:51:27 ecd + * Initial revision + * + * + * $Id: options.h,v 1.5 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#ifndef _OPTIONS_H +#define _OPTIONS_H 1 + +#include "global.h" + +#include +#include + +static XrmOptionDescRec options[] = { + { "-display", ".display", XrmoptionSepArg, (void *) 0 }, + { "-geometry", "*geometry", XrmoptionSepArg, (void *) 0 }, + { "-iconGeom", "*iconGeom", XrmoptionSepArg, (void *) 0 }, + { "-iconName", "*iconName", XrmoptionSepArg, (void *) 0 }, + { "-iconic", "*iconic", XrmoptionNoArg, (void *) "True" }, + { "-name", (char *) 0, XrmoptionSepArg, (void *) 0 }, + { "-title", "*title", XrmoptionSepArg, (void *) 0 }, + + { "-xshm", "*useXShm", XrmoptionNoArg, (void *) "True" }, + { "+xshm", "*useXShm", XrmoptionNoArg, (void *)"False" }, + + { "-visual", "*visual", XrmoptionSepArg, (void *) 0 }, + { "-mono", "*mono", XrmoptionNoArg, (void *) "True" }, + { "-gray", "*gray", XrmoptionNoArg, (void *) "True" }, + { "-monoIcon", "*monoIcon", XrmoptionNoArg, (void *) "True" }, + + { "-version", "*printVersion", XrmoptionNoArg, (void *) "True" }, + { "-copyright", "*printCopyright",XrmoptionNoArg, (void *) "True" }, + { "-warranty", "*printWarranty", XrmoptionNoArg, (void *) "True" }, + + { "-smallFont", "*smallLabelFont",XrmoptionSepArg, (void *) 0 }, + { "-mediumFont", "*mediumLabelFont",XrmoptionSepArg, (void *) 0 }, + { "-largeFont", "*largeLabelFont",XrmoptionSepArg, (void *) 0 }, + { "-connFont", "*connectionFont",XrmoptionSepArg, (void *) 0 }, + + { "-verbose", "*verbose", XrmoptionNoArg, (void *) "True" }, + { "-quiet", "*quiet", XrmoptionNoArg, (void *) "True" }, + + { "-terminal", "*useTerminal", XrmoptionNoArg, (void *) "True" }, + { "+terminal", "*useTerminal", XrmoptionNoArg, (void *)"False" }, + { "-serial", "*useSerial", XrmoptionNoArg, (void *) "True" }, + { "+serial", "*useSerial", XrmoptionNoArg, (void *)"False" }, + { "-line", "*serialLine", XrmoptionSepArg, (void *) 0 }, + + { "-initialize", "*completeInitialize",XrmoptionNoArg,(void *) "True" }, + { "-reset", "*resetOnStartup",XrmoptionNoArg, (void *) "True" }, + { "-rom", "*romFileName", XrmoptionSepArg, (void *) 0 }, + { "-home", "*homeDirectory", XrmoptionSepArg, (void *) 0 }, + + { "-debug", "*useDebugger", XrmoptionNoArg, (void *)"False" }, + { "+debug", "*useDebugger", XrmoptionNoArg, (void *) "True" }, + { "-disasm", "*disassemblerMnemonics",XrmoptionSepArg,(void *) 0 }, + + { "-xrm", (char *) 0, XrmoptionResArg, (void *) 0 }, + { "-netbook", "*netbook", XrmoptionNoArg, (void *)"False" }, + { "+netbook", "*netbook", XrmoptionNoArg, (void *) "True" }, + + { "-throttle", "*throttle", XrmoptionNoArg, (void *)"False" }, + { "+throttle", "*throttle", XrmoptionNoArg, (void *) "True" }, + + /* + * these are parsed for compatibility, but not used yet. + */ + { "-bg", "*background", XrmoptionSepArg, (void *) 0 }, + { "-background", "*background", XrmoptionSepArg, (void *) 0 }, + { "-bd", "*borderColor", XrmoptionSepArg, (void *) 0 }, + { "-bordercolor", "*borderColor", XrmoptionSepArg, (void *) 0 }, + { "-bw", "*borderWidth", XrmoptionSepArg, (void *) 0 }, + { "-borderwidth", "*borderWidth", XrmoptionSepArg, (void *) 0 }, + { "-fg", "*foreground", XrmoptionSepArg, (void *) 0 }, + { "-foreground", "*foreground", XrmoptionSepArg, (void *) 0 }, + { "-fn", "*fontName", XrmoptionSepArg, (void *) 0 }, + { "-font", "*fontName", XrmoptionSepArg, (void *) 0 }, + { "-rv", "*reverseVideo", XrmoptionNoArg, (void *) "True" }, + { "+rv", "*reverseVideo", XrmoptionNoArg, (void *)"False" }, + { "-reverse", "*reverseVideo", XrmoptionNoArg, (void *) "True" }, + +}; + +#endif /* _OPTIONS_H */ diff --git a/src/register.c b/src/register.c new file mode 100644 index 0000000..d83948b --- /dev/null +++ b/src/register.c @@ -0,0 +1,799 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: register.c,v $ + * Revision 1.6 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.5 1994/10/06 16:30:05 ecd + * changed char to unsigned + * + * Revision 1.5 1994/10/06 16:30:05 ecd + * changed char to unsigned + * + * Revision 1.4 1994/10/01 10:12:53 ecd + * changed get_start and get_end to be inline functions + * + * Revision 1.3 1994/09/18 15:29:22 ecd + * turned off unused rcsid message + * + * Revision 1.2 1994/09/13 16:57:00 ecd + * changed to plain X11 + * + * Revision 1.1 1994/08/26 11:09:02 ecd + * Initial revision + * + * $Id: register.c,v 1.6 1995/01/11 18:20:01 ecd Exp ecd $ + */ + + +#include "global.h" + +#include +#include + +#include "hp48.h" +#include "hp48_emu.h" + +extern long nibble_masks[16]; + +static int start_fields[] = { + -1, 0, 2, 0, 15, 3, 0, 0, + -1, 0, 2, 0, 15, 3, 0, 0, + 0, 0, 0 +}; + +static int end_fields[] = { + -1, -1, 2, 2, 15, 14, 1, 15, + -1, -1, 2, 2, 15, 14, 1, 4, + 3, 2, 0 +}; + +static inline int +#ifdef __FunctionProto__ +get_start(int code) +#else +get_start(code) +int code; +#endif +{ + int s; + + if ((s = start_fields[code]) == -1) { + s = saturn.P; + } + return s; +} + +static inline int +#ifdef __FuntionProto__ +get_end(int code) +#else +get_end(code) +int code; +#endif +{ + int e; + + if ((e = end_fields[code]) == -1) { + e = saturn.P; + } + return e; +} + +void +#ifdef __FunctionProto__ +add_register(unsigned char *res, unsigned char *r1, + unsigned char *r2, int code) +#else +add_register(res, r1, r2, code) +unsigned char *res; +unsigned char *r1; +unsigned char *r2; +int code; +#endif +{ + int t, c, i, s, e; + + s = get_start(code); + e = get_end(code); + c = 0; + for (i = s; i <= e; i++) { + t = r1[i] + r2[i] + c; + if (t < (int)saturn.hexmode) { + res[i] = t & 0xf; + c = 0; + } else { + res[i] = (t - saturn.hexmode) & 0xf; + c = 1; + } + } + if (c) + saturn.CARRY = 1; + else + saturn.CARRY = 0; +} + +void +#ifdef __FunctionProto__ +add_p_plus_one(unsigned char *r) +#else +add_p_plus_one(r) +unsigned char *r; +#endif +{ + int t, c, i, s, e; + + s = 0; + e = 4; + c = saturn.P + 1; + for (i = s; i <= e; i++) { + t = r[i] + c; + if (t < 16) { + r[i] = t & 0xf; + c = 0; + } else { + r[i] = (t - 16) & 0xf; + c = 1; + } + } + if (c) + saturn.CARRY = 1; + else + saturn.CARRY = 0; +} + +void +#ifdef __FunctionProto__ +sub_register(unsigned char *res, unsigned char *r1, + unsigned char *r2, int code) +#else +sub_register(res, r1, r2, code) +unsigned char *res; +unsigned char *r1; +unsigned char *r2; +int code; +#endif +{ + int t, c, i, s, e; + + s = get_start(code); + e = get_end(code); + c = 0; + for (i = s; i <= e; i++) { + t = r1[i] - r2[i] - c; + if (t >= 0) { + res[i] = t & 0xf; + c = 0; + } else { + res[i] = (t + saturn.hexmode) & 0xf; + c = 1; + } + } + if (c) + saturn.CARRY = 1; + else + saturn.CARRY = 0; +} + +void +#ifdef __FunctionProto__ +complement_2_register(unsigned char *r, int code) +#else +complement_2_register(r, code) +unsigned char *r; +int code; +#endif +{ + int t, c, carry, i, s, e; + + s = get_start(code); + e = get_end(code); + c = 1; + carry = 0; + for (i = s; i <= e; i++) { + t = (saturn.hexmode - 1) - r[i] + c; + if (t < (int)saturn.hexmode) { + r[i] = t & 0xf; + c = 0; + } else { + r[i] = (t - saturn.hexmode) & 0xf; + c = 1; + } + carry += r[i]; + } + if (carry) + saturn.CARRY = 1; + else + saturn.CARRY = 0; +} + +void +#ifdef __FunctionProto__ +complement_1_register(unsigned char *r, int code) +#else +complement_1_register(r, code) +unsigned char *r; +int code; +#endif +{ + int t, i, s, e; + + s = get_start(code); + e = get_end(code); + for (i = s; i <= e; i++) { + t = (saturn.hexmode - 1) - r[i]; + r[i] = t & 0xf; + } + saturn.CARRY = 0; +} + +void +#ifdef __FunctionProto__ +inc_register(unsigned char *r, int code) +#else +inc_register(r, code) +unsigned char *r; +int code; +#endif +{ + int t, c, i, s, e; + + s = get_start(code); + e = get_end(code); + c = 1; + for (i = s; i <= e; i++) { + t = r[i] + c; + if (t < (int)saturn.hexmode) { + r[i] = t & 0xf; + c = 0; + break; + } else { + r[i] = (t - saturn.hexmode) & 0xf; + c = 1; + } + } + if (c) + saturn.CARRY = 1; + else + saturn.CARRY = 0; +} + +void +#ifdef __FunctionProto__ +add_register_constant(unsigned char *r, int code, int val) +#else +add_register_constant(r, code, val) +unsigned char *r; +int code; +int val; +#endif +{ + int t, c, i, s, e; + + s = get_start(code); + e = get_end(code); + c = val; + for (i = s; i <= e; i++) { + t = r[i] + c; + if (t < 16) { + r[i] = t & 0xf; + c = 0; + break; + } else { + r[i] = (t - 16) & 0xf; + c = 1; + } + } + if (c) + saturn.CARRY = 1; + else + saturn.CARRY = 0; +} + +void +#ifdef __FunctionProto__ +dec_register(unsigned char *r, int code) +#else +dec_register(r, code) +unsigned char *r; +int code; +#endif +{ + int t, c, i, s, e; + + s = get_start(code); + e = get_end(code); + c = 1; + for (i = s; i <= e; i++) { + t = r[i] - c; + if (t >= 0) { + r[i] = t & 0xf; + c = 0; + break; + } else { + r[i] = (t + saturn.hexmode) & 0xf; + c = 1; + } + } + if (c) + saturn.CARRY = 1; + else + saturn.CARRY = 0; +} + +void +#ifdef __FunctionProto__ +sub_register_constant(unsigned char *r, int code, int val) +#else +sub_register_constant(r, code, val) +unsigned char *r; +int code; +int val; +#endif +{ + int t, c, i, s, e; + + s = get_start(code); + e = get_end(code); + c = val; + for (i = s; i <= e; i++) { + t = r[i] - c; + if (t >= 0) { + r[i] = t & 0xf; + c = 0; + break; + } else { + r[i] = (t + 16) & 0xf; + c = 1; + } + } + if (c) + saturn.CARRY = 1; + else + saturn.CARRY = 0; +} + +void +#ifdef __FunctionProto__ +zero_register(unsigned char *r, int code) +#else +zero_register(r, code) +unsigned char *r; +int code; +#endif +{ + int i, s, e; + + s = get_start(code); + e = get_end(code); + for (i = s; i <= e; i++) + r[i] = 0; +} + +void +#ifdef __FunctionProto__ +or_register(unsigned char *res, unsigned char *r1, + unsigned char *r2, int code) +#else +or_register(res, r1, r2, code) +unsigned char *res; +unsigned char *r1; +unsigned char *r2; +int code; +#endif +{ + int i, s, e; + + s = get_start(code); + e = get_end(code); + for (i = s; i <= e; i++) { + res[i] = (r1[i] | r2[i]) & 0xf; + } +} + +void +#ifdef __FunctionProto__ +and_register(unsigned char *res, unsigned char *r1, + unsigned char *r2, int code) +#else +and_register(res, r1, r2, code) +unsigned char *res; +unsigned char *r1; +unsigned char *r2; +int code; +#endif +{ + int i, s, e; + + s = get_start(code); + e = get_end(code); + for (i = s; i <= e; i++) { + res[i] = (r1[i] & r2[i]) & 0xf; + } +} + +void +#ifdef __FunctionProto__ +copy_register(unsigned char *to, unsigned char *from, int code) +#else +copy_register(to, from, code) +unsigned char *to; +unsigned char *from; +int code; +#endif +{ + int i, s, e; + + s = get_start(code); + e = get_end(code); + for (i = s; i <= e; i++) + to[i] = from[i]; +} + +void +#ifdef __FunctionProto__ +exchange_register(unsigned char *r1, unsigned char *r2, int code) +#else +exchange_register(r1, r2, code) +unsigned char *r1; +unsigned char *r2; +int code; +#endif +{ + int t, i, s, e; + + s = get_start(code); + e = get_end(code); + for (i = s; i <= e; i++) { + t = r1[i]; + r1[i] = r2[i]; + r2[i] = t; + } +} + +void +#ifdef __FunctionProto__ +exchange_reg(unsigned char *r, word_20 *d, int code) +#else +exchange_reg(r, d, code) +unsigned char *r; +word_20 *d; +int code; +#endif +{ + int t, i, s, e; + + s = get_start(code); + e = get_end(code); + for (i = s; i <= e; i++) { + t = r[i]; + r[i] = (*d >> (i * 4)) & 0x0f; + *d &= ~nibble_masks[i]; + *d |= t << (i * 4); + } +} + +void +#ifdef __FunctionProto__ +shift_left_register(unsigned char *r, int code) +#else +shift_left_register(r, code) +unsigned char *r; +int code; +#endif +{ + int i, s, e; + + s = get_start(code); + e = get_end(code); + for (i = e; i > s; i--) { + r[i] = r[i-1] & 0x0f; + } + r[s] = 0; +} + +void +#ifdef __FunctionProto__ +shift_left_circ_register(unsigned char *r, int code) +#else +shift_left_circ_register(r, code) +unsigned char *r; +int code; +#endif +{ + int t, i, s, e; + + s = get_start(code); + e = get_end(code); + t = r[e] & 0x0f; + for (i = e; i > s; i--) { + r[i] = r[i-1] & 0x0f; + } + r[s] = t; +} + +void +#ifdef __FunctionProto__ +shift_right_register(unsigned char *r, int code) +#else +shift_right_register(r, code) +unsigned char *r; +int code; +#endif +{ + int i, s, e; + + s = get_start(code); + e = get_end(code); + if (r[s] & 0x0f) + saturn.SB = 1; + for (i = s; i < e; i++) { + r[i] = r[i+1] & 0x0f; + } + r[e] = 0; +} + +void +#ifdef __FunctionProto__ +shift_right_circ_register(unsigned char *r, int code) +#else +shift_right_circ_register(r, code) +unsigned char *r; +int code; +#endif +{ + int t, i, s, e; + + s = get_start(code); + e = get_end(code); + t = r[s] & 0x0f; + for (i = s; i < e; i++) { + r[i] = r[i+1] & 0x0f; + } + r[e] = t; + if (t) + saturn.SB = 1; +} + +void +#ifdef __FunctionProto__ +shift_right_bit_register(unsigned char *r, int code) +#else +shift_right_bit_register(r, code) +unsigned char *r; +int code; +#endif +{ + int t, i, s, e, sb; + + s = get_start(code); + e = get_end(code); + sb = 0; + for (i = e; i >= s; i--) { + t = (((r[i] >> 1) & 7) | (sb << 3)) & 0x0f; + sb = r[i] & 1; + r[i] = t; + } + if (sb) + saturn.SB = 1; +} + +int +#ifdef __FunctionProto__ +is_zero_register(unsigned char *r, int code) +#else +is_zero_register(r, code) +unsigned char *r; +int code; +#endif +{ + int z, i, s, e; + + s = get_start(code); + e = get_end(code); + z = 1; + for (i = s; i <= e; i++) + if ((r[i] & 0xf) != 0) { + z = 0; + break; + } + return z; +} + +int +#ifdef __FunctionProto__ +is_not_zero_register(unsigned char *r, int code) +#else +is_not_zero_register(r, code) +unsigned char *r; +int code; +#endif +{ + int z, i, s, e; + + s = get_start(code); + e = get_end(code); + z = 0; + for (i = s; i <= e; i++) + if ((r[i] & 0xf) != 0) { + z = 1; + break; + } + return z; +} + +int +#ifdef __FunctionProto__ +is_equal_register(unsigned char *r1, unsigned char *r2, int code) +#else +is_equal_register(r1, r2, code) +unsigned char *r1; +unsigned char *r2; +int code; +#endif +{ + int z, i, s, e; + + s = get_start(code); + e = get_end(code); + z = 1; + for (i = s; i <= e; i++) + if ((r1[i] & 0xf) != (r2[i] & 0xf)) { + z = 0; + break; + } + return z; +} + +int +#ifdef __FunctionProto__ +is_not_equal_register(unsigned char *r1, unsigned char *r2, int code) +#else +is_not_equal_register(r1, r2, code) +unsigned char *r1; +unsigned char *r2; +int code; +#endif +{ + int z, i, s, e; + + s = get_start(code); + e = get_end(code); + z = 0; + for (i = s; i <= e; i++) + if ((r1[i] & 0xf) != (r2[i] & 0xf)) { + z = 1; + break; + } + return z; +} + +int +#ifdef __FunctionProto__ +is_less_register(unsigned char *r1, unsigned char *r2, int code) +#else +is_less_register(r1, r2, code) +unsigned char *r1; +unsigned char *r2; +int code; +#endif +{ + int z, i, s, e; + + s = get_start(code); + e = get_end(code); + z = 0; + for (i = e; i >= s; i--) { + if ((int)(r1[i] & 0xf) < (int)(r2[i] & 0xf)) { + z = 1; + break; + } + if ((int)(r1[i] & 0xf) > (int)(r2[i] & 0xf)) { + z = 0; + break; + } + } + return z; +} + +int +#ifdef __FunctionProto__ +is_less_or_equal_register(unsigned char *r1, unsigned char *r2, int code) +#else +is_less_or_equal_register(r1, r2, code) +unsigned char *r1; +unsigned char *r2; +int code; +#endif +{ + int z, i, s, e; + + s = get_start(code); + e = get_end(code); + z = 1; + for (i = e; i >= s; i--) { + if ((int)(r1[i] & 0xf) < (int)(r2[i] & 0xf)) { + z = 1; + break; + } + if ((int)(r1[i] & 0xf) > (int)(r2[i] & 0xf)) { + z = 0; + break; + } + } + return z; +} + +int +#ifdef __FunctionProto__ +is_greater_register(unsigned char *r1, unsigned char *r2, int code) +#else +is_greater_register(r1, r2, code) +unsigned char *r1; +unsigned char *r2; +int code; +#endif +{ + int z, i, s, e; + + s = get_start(code); + e = get_end(code); + z = 0; + for (i = e; i >= s; i--) { + if ((int)(r1[i] & 0xf) > (int)(r2[i] & 0xf)) { + z = 1; + break; + } + if ((int)(r1[i] & 0xf) < (int)(r2[i] & 0xf)) { + z = 0; + break; + } + } + return z; +} + +int +#ifdef __FunctionProto__ +is_greater_or_equal_register(unsigned char *r1, unsigned char *r2, int code) +#else +is_greater_or_equal_register(r1, r2, code) +unsigned char *r1; +unsigned char *r2; +int code; +#endif +{ + int z, i, s, e; + + s = get_start(code); + e = get_end(code); + z = 1; + for (i = e; i >= s; i--) { + if ((int)(r1[i] & 0xf) < (int)(r2[i] & 0xf)) { + z = 0; + break; + } + if ((int)(r1[i] & 0xf) > (int)(r2[i] & 0xf)) { + z = 1; + break; + } + } + return z; +} + diff --git a/src/resources.c b/src/resources.c new file mode 100644 index 0000000..c735899 --- /dev/null +++ b/src/resources.c @@ -0,0 +1,419 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: resources.c,v $ + * Revision 1.3 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.2 1994/12/07 20:20:50 ecd + * more resource get functions + * + * Revision 1.2 1994/12/07 20:20:50 ecd + * more resource get functions + * + * Revision 1.1 1994/12/07 10:15:47 ecd + * Initial revision + * + * + * $Id: resources.c,v 1.3 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +/* xscreensaver, Copyright (c) 1992 Jamie Zawinski + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + */ + +#include "global.h" + +#include +#include + +#include +#include +#include +#include + +#include "resources.h" +#include "disasm.h" +#include "errors.h" + +XrmDatabase rdb = (XrmDatabase)0; + +int verbose; +int quiet; +int useTerminal; +int useSerial; +char *serialLine; +int useXShm; +int useDebugger; +int netbook; +int throttle; +int initialize; +int resetOnStartup; +char *romFileName; +char *homeDirectory; + +void +#ifdef __FunctionProto__ +get_resources(void) +#else +get_resources() +#endif +{ + if (get_boolean_resource("printVersion", "PrintVersion")) + show_version(); + if (get_boolean_resource("printCopyright", "PrintCopyright")) + show_copyright(); + if (get_boolean_resource("printWarranty", "PrintWarranty")) + show_warranty(); + + verbose = get_boolean_resource("verbose", "Verbose"); + quiet = get_boolean_resource("quiet", "Quiet"); + + useXShm = get_boolean_resource("useXShm", "UseXShm"); + + useTerminal = get_boolean_resource("useTerminal", "UseTerminal"); + useSerial = get_boolean_resource("useSerial", "UseSerial"); + serialLine = get_string_resource("serialLine", "SerialLine"); + + initialize = get_boolean_resource("completeInitialize", + "CompleteInitialize"); + resetOnStartup = get_boolean_resource("resetOnStartup", + "ResetOnStartup"); + romFileName = get_string_resource("romFileName", "RomFileName"); + homeDirectory = get_string_resource("homeDirectory", "HomeDirectory"); + + useDebugger = get_boolean_resource("useDebugger", "UseDebugger"); + disassembler_mode = get_mnemonic_resource("disassemblerMnemonics", + "DisassemblerMnemonics"); + + netbook = get_boolean_resource("netbook", "Netbook"); + + throttle = get_boolean_resource("throttle", "Throttle"); +} + +char * +#ifdef __FunctionProto__ +get_string_resource_from_db (XrmDatabase db, char *name, char *class) +#else +get_string_resource_from_db (db, name, class) +XrmDatabase db; +char *name; +char *class; +#endif +{ + XrmValue value; + char *type; + char full_name [1024], full_class [1024]; + + strcpy (full_name, res_name); + strcat (full_name, "."); + strcat (full_name, name); + strcpy (full_class, res_class); + strcat (full_class, "."); + strcat (full_class, class); + if (XrmGetResource (db, full_name, full_class, &type, &value)) + { + char *str = (char *) malloc (value.size + 1); + strncpy (str, (char *) value.addr, value.size); + str [value.size] = 0; + return str; + } + return (char *)0; +} + +char * +#ifdef __FunctionProto__ +get_string_resource (char *name, char *class) +#else +get_string_resource (name, class) +char *name; +char *class; +#endif +{ + return get_string_resource_from_db(rdb, name, class); +} + +int +#ifdef __FunctionProto__ +get_mnemonic_resource (char *name, char *class) +#else +get_mnemonic_resource (name, class) +char *name; +char *class; +#endif +{ + char *tmp, buf [100]; + char *s = get_string_resource (name, class); + char *os = s; + + if (! s) return CLASS_MNEMONICS; + for (tmp = buf; *s; s++) + *tmp++ = isupper (*s) ? _tolower (*s) : *s; + *tmp = 0; + free (os); + + if (!strcmp (buf, "hp")) + return HP_MNEMONICS; + if (!strcmp (buf, "class")) + return CLASS_MNEMONICS; + fprintf (stderr, "%s: %s must be one of \'HP\' or \'class\', not %s.\n", + progname, name, buf); + return CLASS_MNEMONICS; +} + +int +#ifdef __FunctionProto__ +get_boolean_resource (char *name, char *class) +#else +get_boolean_resource (name, class) +char *name; +char *class; +#endif +{ + char *tmp, buf [100]; + char *s = get_string_resource (name, class); + char *os = s; + if (! s) return 0; + for (tmp = buf; *s; s++) + *tmp++ = isupper (*s) ? _tolower (*s) : *s; + *tmp = 0; + free (os); + + if (!strcmp (buf, "on") || !strcmp (buf, "true") || !strcmp (buf, "yes")) + return 1; + if (!strcmp (buf, "off") || !strcmp (buf, "false") || !strcmp (buf, "no")) + return 0; + fprintf (stderr, "%s: %s must be boolean, not %s.\n", + progname, name, buf); + return 0; +} + +int +#ifdef __FunctionProto__ +get_integer_resource (char *name, char *class) +#else +get_integer_resource (name, class) +char *name; +char *class; +#endif +{ + int val; + char c, *s = get_string_resource (name, class); + if (!s) return 0; + if (1 == sscanf (s, " %d %c", &val, &c)) + { + free (s); + return val; + } + fprintf (stderr, "%s: %s must be an integer, not %s.\n", + progname, name, s); + free (s); + return 0; +} + +unsigned int +#ifdef __FunctionProto__ +get_pixel_resource (char *name, char *class, Display *dpy, + Colormap cmap) +#else +get_pixel_resource (name, class, dpy, cmap) +char *name; +char *class; +Display *dpy; +Colormap cmap; +#endif +{ + XColor color; + char *s = get_string_resource (name, class); + if (!s) goto DEFAULT; + + if (! XParseColor (dpy, cmap, s, &color)) + { + fprintf (stderr, "%s: can't parse color %s\n", progname, s); + goto DEFAULT; + } + if (! XAllocColor (dpy, cmap, &color)) + { + fprintf (stderr, "%s: couldn't allocate color %s\n", progname, s); + goto DEFAULT; + } + free (s); + return color.pixel; + DEFAULT: + if (s) free (s); + return (strcmp (class, "Background") + ? WhitePixel (dpy, DefaultScreen (dpy)) + : BlackPixel (dpy, DefaultScreen (dpy))); +} + +static Visual * +#ifdef __FunctionProto__ +pick_visual_of_class (Display *dpy, int visual_class, unsigned int *depth) +#else +pick_visual_of_class (dpy, visual_class, depth) +Display *dpy; +int visual_class; +unsigned int *depth; +#endif +{ + XVisualInfo vi_in, *vi_out; + int out_count; + + vi_in.class = visual_class; + vi_in.screen = DefaultScreen(dpy); + vi_out = XGetVisualInfo(dpy, VisualClassMask|VisualScreenMask, + &vi_in, &out_count); + if (vi_out) + { /* choose the 'best' one, if multiple */ + int i, best; + Visual *visual; + for (i = 0, best = 0; i < out_count; i++) + if (vi_out[i].depth > vi_out[best].depth) + best = i; + visual = vi_out[best].visual; + *depth = vi_out[best].depth; + XFree ((char *)vi_out); + return visual; + } + else + { + *depth = DefaultDepth(dpy, DefaultScreen(dpy)); + return DefaultVisual(dpy, DefaultScreen(dpy)); + } +} + +static Visual * +#ifdef __FunctionProto__ +id_to_visual (Display *dpy, int id, unsigned int *depth) +#else +id_to_visual (dpy, id, depth) +Display *dpy; +int id; +unsigned int *depth; +#endif +{ + XVisualInfo vi_in, *vi_out; + int out_count; + + vi_in.screen = DefaultScreen(dpy); + vi_in.visualid = id; + vi_out = XGetVisualInfo(dpy, VisualScreenMask|VisualIDMask, + &vi_in, &out_count); + if (vi_out) + { + Visual *v = vi_out[0].visual; + *depth = vi_out[0].depth; + XFree((char *)vi_out); + return v; + } + return 0; +} + +Visual * +#ifdef __FunctionProto__ +get_visual_resource(Display *dpy, char *name, char *class, unsigned int *depth) +#else +get_visual_resource(dpy, name, class, depth) +Display *dpy; +char *name; +char *class; +unsigned int *depth; +#endif +{ + char c; + char *tmp, *s; + int vclass; + int id; + + s = get_string_resource(name, class); + if (s) + for (tmp = s; *tmp; tmp++) + if (isupper(*tmp)) *tmp = _tolower(*tmp); + + if (!s || !strcmp(s, "default")) vclass = -1; + else if (!strcmp (s, "staticgray")) vclass = StaticGray; + else if (!strcmp (s, "staticcolor")) vclass = StaticColor; + else if (!strcmp (s, "truecolor")) vclass = TrueColor; + else if (!strcmp (s, "grayscale")) vclass = GrayScale; + else if (!strcmp (s, "pseudocolor")) vclass = PseudoColor; + else if (!strcmp (s, "directcolor")) vclass = DirectColor; + else if (1 == sscanf (s, " %d %c", &id, &c)) vclass = -2; + else if (1 == sscanf (s, " 0x%x %c", &id, &c)) vclass = -2; + else + { + fprintf (stderr, "%s: unrecognized visual \"%s\".\n", progname, s); + vclass = -1; + } + if (s) free (s); + + if (vclass == -1) + { + *depth = DefaultDepth(dpy, DefaultScreen(dpy)); + return DefaultVisual(dpy, DefaultScreen(dpy)); + } + else if (vclass == -2) + { + Visual *v = id_to_visual (dpy, id, depth); + if (v) return v; + fprintf (stderr, "%s: no visual with id 0x%x.\n", progname, id); + *depth = DefaultDepth(dpy, DefaultScreen(dpy)); + return DefaultVisual(dpy, DefaultScreen(dpy)); + } + else + return pick_visual_of_class(dpy, vclass, depth); +} + +XFontStruct * +#ifdef __FunctionProto__ +get_font_resource(Display *dpy, char *name, char *class) +#else +get_font_resource(dpy, name, class) +Display *dpy; +char *name; +char *class; +#endif +{ + char *s; + XFontStruct *f = (XFontStruct *)0; + + s = get_string_resource(name, class); + + if (s) + f = XLoadQueryFont(dpy, s); + else + { + sprintf(errbuf, "can\'t get resource \'%s\'", name); + fatal_exit(); + } + if (f == (XFontStruct *)0) + { + sprintf(errbuf, "can\'t load font \'%s\'", s); + sprintf(fixbuf, "Please change resource \'%s\'", name); + fatal_exit(); + } + return f; +} + diff --git a/src/resources.h b/src/resources.h new file mode 100644 index 0000000..d7f18bd --- /dev/null +++ b/src/resources.h @@ -0,0 +1,99 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: resources.h,v $ + * Revision 1.3 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.2 1994/12/07 20:16:41 ecd + * added more resource get functions + * + * Revision 1.2 1994/12/07 20:16:41 ecd + * added more resource get functions + * + * Revision 1.1 1994/12/07 10:16:15 ecd + * Initial revision + * + * + * $Id: resources.h,v 1.3 1995/01/11 18:20:01 ecd Exp ecd $ + */ +#ifndef _RESOURCES_H +#define _RESOURCES_H 1 + +#include "global.h" + +#include +#include + +extern int verbose; +extern int quiet; +extern int useTerminal; +extern int useSerial; +extern int useXShm; +extern int useDebugger; +extern int netbook; +extern int throttle; +extern char *serialLine; +extern int initialize; +extern int resetOnStartup; +extern char *romFileName; +extern char *homeDirectory; + +extern char *progname; +extern char *res_name; +extern char *res_class; + +extern XrmDatabase rdb; + +extern void usage __ProtoType__ ((void)); +extern void show_version __ProtoType__ ((void)); +extern void show_copyright __ProtoType__ ((void)); +extern void show_warranty __ProtoType__ ((void)); +extern void get_resources __ProtoType__ ((void)); +extern char * get_string_resource_from_db __ProtoType__ ((XrmDatabase db, + char *name, + char *class)); +extern char * get_string_resource __ProtoType__ ((char *name, + char *class)); +extern int get_boolean_resource __ProtoType__ ((char *name, + char *class)); +extern int get_mnemonic_resource __ProtoType__ ((char *name, + char *class)); +extern Visual * get_visual_resource __ProtoType__ ((Display *dpy, + char *name, + char *class, + unsigned int *depth)); +extern XFontStruct * get_font_resource __ProtoType__ ((Display *dpy, + char *res_name, + char *res_class)); + +#ifndef isupper +# define isupper(c) ((c) >= 'A' && (c) <= 'Z') +#endif +#ifndef islower +# define islower(c) ((c) >= 'a' && (c) <= 'z') +#endif +#ifndef _tolower +# define _tolower(c) ((c) - 'A' + 'a') +#endif +#ifndef _toupper +# define _toupper(c) ((c) - 'a' + 'A') +#endif + +#endif /* !_RESOURCES_H */ diff --git a/src/romio.c b/src/romio.c new file mode 100644 index 0000000..6c0d1a7 --- /dev/null +++ b/src/romio.c @@ -0,0 +1,242 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: romio.c,v $ + * Revision 1.1 1995/01/11 18:11:25 ecd + * Initial revision + * + * + * $Id: romio.c,v 1.1 1995/01/11 18:11:25 ecd Exp ecd $ + */ + +#include +#include +#include +#include + +#include "global.h" +#include "resources.h" +#include "romio.h" + +unsigned int opt_gx = 0; +unsigned int rom_size = 0; + +int +#ifdef __FunctionProto__ +read_rom_file(char *name, unsigned char **mem, int *size) +#else +read_rom_file(name, mem, size) +char *name; +unsigned char **mem; +int *size; +#endif +{ + struct stat st; + FILE *fp; + unsigned char *tmp_mem; + unsigned char byte; + unsigned char four[4]; + int i, j; + + *mem = NULL; + *size = 0; + if (NULL == (fp = fopen(name, "r"))) + { + fprintf(stderr, "can\'t open %s\n", name); + return 0; + } + + if (stat(name, &st) < 0) + { + fprintf(stderr, "can\'t stat %s\n", name); + fclose(fp); + return 0; + } + + if (fread(four, 1, 4, fp) != 4) + { + fprintf(stderr, "can\'t read first 4 bytes of %s\n", name); + fclose(fp); + return 0; + } + + if (four[0] == 0x02 && four[1] == 0x03 && + four[2] == 0x06 && four[3] == 0x09) + { + *size = st.st_size; + } + else if (four[0] == 0x32 && four[1] == 0x96 && + four[2] == 0x1b && four[3] == 0x80) + { + *size = 2 * st.st_size; + } + else if (four[1] = 0x49) + { + fprintf(stderr, "%s is an HP49 ROM\n", name); + *size = 2 * st.st_size; + } + else if (four[0]) + { + printf("%d\n", st.st_size); + *size = st.st_size; + } + else + { + fprintf(stderr, "%s is not a HP48 ROM\n", name); + fclose(fp); + return 0; + } + + if (fseek(fp, 0, 0) < 0) + { + fprintf(stderr, "can\'t fseek to position 0 in %s\n", name); + *size = 0; + fclose(fp); + return 0; + } + + *mem = (unsigned char *)malloc(*size); + + if (st.st_size == *size) + { + /* + * size is same as memory size, old version file + */ + if (fread(*mem, 1, (size_t)*size, fp) != *size) + { + fprintf(stderr, "can\'t read %s\n", name); + free(*mem); + *mem = NULL; + *size = 0; + fclose(fp); + return 0; + } + } + else + { + /* + * size is different, check size and decompress memory + */ + + if (st.st_size != *size / 2) + { + fprintf(stderr, "strange size %s, expected %d, found %ld\n", + name, *size / 2, st.st_size); + free(*mem); + *mem = NULL; + *size = 0; + fclose(fp); + return 0; + } + + if (NULL == (tmp_mem = (unsigned char *)malloc((size_t)st.st_size))) + { + for (i = 0, j = 0; i < *size / 2; i++) + { + if (1 != fread(&byte, 1, 1, fp)) + { + fprintf(stderr, "can\'t read %s\n", name); + free(*mem); + *mem = NULL; + *size = 0; + fclose(fp); + return 0; + } + (*mem)[j++] = byte & 0xf; + (*mem)[j++] = (byte >> 4) & 0xf; + } + } + else + { + if (fread(tmp_mem, 1, (size_t)*size / 2, fp) != *size / 2) + { + fprintf(stderr, "can\'t read %s\n", name); + free(*mem); + *mem = NULL; + *size = 0; + fclose(fp); + free(tmp_mem); + return 0; + } + + for (i = 0, j = 0; i < *size / 2; i++) + { + (*mem)[j++] = tmp_mem[i] & 0xf; + (*mem)[j++] = (tmp_mem[i] >> 4) & 0xf; + } + + free(tmp_mem); + } + } + + fclose(fp); + + if ((*mem)[0x29] == 0x00) + { + if (*size == ROM_SIZE_GX) + { + opt_gx = 1; + } + else + if (*size == 4 * ROM_SIZE_GX) + { + fprintf(stderr, "%s seems to be HP49 ROM, but size is 0x%x\n", + name, *size); + opt_gx = 2; + } + else + if (*size == 8 * ROM_SIZE_GX) + { + fprintf(stderr, "%s seems to be HP49 ROM, but size is 0x%x\n", + name, *size); + opt_gx = 2; + } + else + { + fprintf(stderr, "%s seems to be G/GX ROM, but size is 0x%x\n", + name, *size); + free(*mem); + *mem = NULL; + *size = 0; + return 0; + } + } + else + { + if (*size == ROM_SIZE_SX) + { + opt_gx = 0; + } + else + { + fprintf(stderr, "%s seems to be S/SX ROM, but size is 0x%x\n", + name, *size); + free(*mem); + *mem = NULL; + *size = 0; + return 0; + } + } + + if (verbose) + printf("%s: read %s\n", progname, name); + + return 1; +} + diff --git a/src/romio.h b/src/romio.h new file mode 100644 index 0000000..3e1421d --- /dev/null +++ b/src/romio.h @@ -0,0 +1,43 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: romio.h,v $ + * Revision 1.1 1995/01/11 18:11:25 ecd + * Initial revision + * + * + * $Id: romio.h,v 1.1 1995/01/11 18:11:25 ecd Exp ecd $ + */ + +#ifndef _ROMIO_H +#define _ROMIO_H 1 + +#include "global.h" + +#define ROM_SIZE_SX 0x080000 +#define ROM_SIZE_GX 0x100000 + +extern unsigned int opt_gx; +extern unsigned int rom_size; + +extern int read_rom_file __ProtoType__((char *name, + unsigned char **mem, + int *size)); + +#endif /* !_ROMIO_H */ diff --git a/src/rpl.c b/src/rpl.c new file mode 100644 index 0000000..e19dc53 --- /dev/null +++ b/src/rpl.c @@ -0,0 +1,1556 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: rpl.c,v $ + * Revision 1.3 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.2 1994/12/07 20:20:50 ecd + * lots of more functions + * + * Revision 1.2 1994/12/07 20:20:50 ecd + * lots of more functions + * + * Revision 1.1 1994/12/07 10:15:47 ecd + * Initial revision + * + * + * $Id: rpl.c,v 1.3 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#include "global.h" + +#include +#include +#include +#include + +#include "hp48.h" +#include "hp48_emu.h" +#include "rpl.h" +#include "debugger.h" +#include "append.h" +#include "disasm.h" +#include "romio.h" +#define DEFINE_TRANS_TABLE 1 +#include "hp48char.h" +#undef DEFINE_TRANS_TABLE + +struct objfunc { + char *name; + short length; + word_20 prolog; + char *(*func) __ProtoType__((word_20 *addr, char *string)); +} objects[] = { + { "System Binary", 0, DOBINT, dec_bin_int }, + { "Real", 0, DOREAL, dec_real }, + { "Long Real", 0, DOEREL, dec_long_real }, + { "Complex", 0, DOCMP, dec_complex }, + { "Long Complex", 0, DOECMP, dec_long_complex }, + { "Character", 0, DOCHAR, dec_char }, + { "Array", 0, DOARRY, dec_array }, + { "Linked Array", 0, DOLNKARRY, dec_lnk_array }, + { "String", 2, DOCSTR, dec_string }, + { "Hex String", 1, DOHSTR, dec_hex_string }, + { "List", 0, DOLIST, dec_list }, + { "Directory", 0, DORRP, skip_ob }, + { "Symbolic", 0, DOSYMB, dec_symb }, + { "Unit", 0, DOEXT, dec_unit }, + { "Tagged", 0, DOTAG, skip_ob }, + { "Graphic", 0, DOGROB, skip_ob }, + { "Library", 0, DOLIB, dec_library }, + { "Backup", 0, DOBAK, skip_ob }, + { "Library Data", 0, DOEXT0, dec_library_data }, + { "ACPTR", 0, DOACPTR, dec_acptr }, + { "External 2", 0, DOEXT2, skip_ob }, + { "External 3", 0, DOEXT3, skip_ob }, + { "External 4", 0, DOEXT4, skip_ob }, + { "Program", 0, DOCOL, dec_prog }, + { "Code", 1, DOCODE, dec_code }, + { "Global Ident", 0, DOIDNT, dec_global_ident }, + { "Local Ident", 0, DOLAM, dec_local_ident }, + { "XLib Name", 0, DOROMP, dec_xlib_name }, + { "*", 0, UM_MUL, dec_unit_op }, + { "/", 0, UM_DIV, dec_unit_op }, + { "^", 0, UM_POW, dec_unit_op }, + { " ", 0, UM_PRE, dec_unit_op }, + { "_", 0, UM_END, dec_unit_op }, + { 0, 0, 0 } +}; + +char * +#ifdef __FunctionProto__ +skip_ob(word_20 *addr, char *string) +#else +skip_ob(addr, string) +word_20 *addr; +char *string; +#endif +{ + word_20 size, type; + char *p = string; + struct objfunc *op; + + type = read_nibbles(*addr - 5, 5); + for (op = objects; op->prolog != 0; op++) + { + if (op->prolog == type) + break; + } + + if (op->prolog) + { + sprintf(p, "%s", op->name); + p += strlen(p); + } + + size = read_nibbles(*addr, 5); + *addr += size; + + *p = '\0'; + return p; +} + +long +#ifdef __FunctionProto__ +hxs2real(long hxs) +#else +hxs2real(hxs) +long hxs; +#endif +{ + int n = 0, c = 1; + + while (hxs) + { + n += (hxs & 0xf) * c; + c *= 10; + hxs >>= 4; + } + return n; +} + +char * +#ifdef __FunctionProto__ +dec_bin_int(word_20 *addr, char *string) +#else +dec_bin_int(addr, string) +word_20 *addr; +char *string; +#endif +{ + char *p = string; + word_20 n = 0; + + n = read_nibbles(*addr, 5); + *addr += 5; + sprintf(p, "<%lXh>", (long)n); + p += strlen(p); + return p; +} + +char * +#ifdef __FunctionProto__ +real_number(word_20 *addr, char *string, int ml, int xl) +#else +real_number(addr, string, ml, xl) +word_20 *addr; +char *string; +int ml; +int xl; +#endif +{ + hp_real r; + long re, xs; + int i; + char fmt[20]; + char m[16]; + char *p = string; + + /* + * Read the number + */ + r.x = read_nibbles(*addr, xl); + *addr += xl; + r.ml = read_nibbles(*addr, ml - 8); + *addr += ml - 8; + r.mh = read_nibbles(*addr, 8); + *addr += 8; + r.m = read_nibbles(*addr, 1); + (*addr)++; + r.s = read_nibbles(*addr, 1); + (*addr)++; + + /* + * Figure out the exponent + */ + xs = 5; + while (--xl) xs *= 10; + re = hxs2real(r.x); + if (re >= xs) + re = re - 2 * xs; + + + if ((re >= 0) && (re < ml + 1)) + { + if (r.s >= 5) + *p++ = '-'; + + sprintf(fmt, "%%.1X%%.8lX%%.%dlX", ml - 8); + sprintf(m, fmt, r.m, r.mh, r.ml); + + for (i = 0; i <= re; i++) + *p++ = m[i]; + *p++ = '.'; + for ( ; i < ml + 1; i++) + *p++ = m[i]; + p--; + while(*p == '0') p--; + if (*p == '.') p--; + *++p = '\0'; + + return p; + } + + if ((re < 0) && (re >= -ml - 1)) + { + sprintf(fmt, "%%.1X%%.8lX%%.%dlX", ml - 8); + sprintf(m, fmt, r.m, r.mh, r.ml); + + for (i = ml; m[i] == '0'; i--) ; + + if (-re <= ml - i + 1) + { + if (r.s >= 5) + *p++ = '-'; + + *p++ = '.'; + + for (i = 1; i < -re; i++) + *p++ = '0'; + + for (i = 0; i < ml + 1; i++) + *p++ = m[i]; + p--; + while(*p == '0') p--; + *++p = '\0'; + + return p; + } + } + + sprintf(fmt, "%%s%%X.%%.8lX%%.%dlX", ml - 8); + sprintf(p, fmt, (r.s >= 5) ? "-" : "", r.m, r.mh, r.ml); + + p += strlen(p) - 1; + + while(*p == '0') p--; + *++p = '\0'; + + if (re) + { + sprintf(p, "E%ld", re); + p += strlen(p); + *p = '\0'; + } + + return p; +} + +char * +#ifdef __FunctionProto__ +dec_real(word_20 *addr, char *string) +#else +dec_real(addr, string) +word_20 *addr; +char *string; +#endif +{ + return real_number(addr, string, 11, 3); +} + +char * +#ifdef __FunctionProto__ +dec_long_real(word_20 *addr, char *string) +#else +dec_long_real(addr, string) +word_20 *addr; +char *string; +#endif +{ + return real_number(addr, string, 14, 5); +} + +char * +#ifdef __FunctionProto__ +dec_complex(word_20 *addr, char *string) +#else +dec_complex(addr, string) +word_20 *addr; +char *string; +#endif +{ + char *p = string; + + *p++ = '('; + p = real_number(addr, p, 11, 3); + *p++ = ','; + p = real_number(addr, p, 11, 3); + *p++ = ')'; + *p = '\0'; + return p; +} + +char * +#ifdef __FunctionProto__ +dec_long_complex(word_20 *addr, char *string) +#else +dec_long_complex(addr, string) +word_20 *addr; +char *string; +#endif +{ + char *p = string; + + *p++ = '('; + p = real_number(addr, p, 14, 5); + *p++ = ','; + p = real_number(addr, p, 14, 5); + *p++ = ')'; + *p = '\0'; + return p; +} + +char * +#ifdef __FunctionProto__ +dec_string(word_20 *addr, char *string) +#else +dec_string(addr, string) +word_20 *addr; +char *string; +#endif +{ + word_20 len; + unsigned char c; + char *p = string; + int i, n; + + len = read_nibbles(*addr, 5); + *addr += 5; + len -= 5; + len /= 2; + + n = len; + if (len > 1000) + n = 1000; + + *p++ = '\"'; + for (i = 0; i < n; i++) + { + c = read_nibbles(*addr, 2); + *addr += 2; + if (hp48_trans_tbl[c].trans) + { + sprintf(p, hp48_trans_tbl[c].trans); + p += strlen(p); + } + else + *p++ = c; + } + + if (n != len) + { + *p++ = '.'; + *p++ = '.'; + *p++ = '.'; + } + + *p++ = '\"'; + *p = '\0'; + return p; +} + +char * +#ifdef __FunctionProto__ +dec_hex_string(word_20 *addr, char *string) +#else +dec_hex_string(addr, string) +word_20 *addr; +char *string; +#endif +{ + int len, lead, i, n; + static char hex[] = "0123456789ABCDEF"; + char *p = string; + + len = read_nibbles(*addr, 5); + *addr += 5; + len -= 5; + + if (len <= 16) + { + *p++ = '#'; + *p++ = ' '; + lead = 1; + for (i = len - 1; i >= 0; i--) + { + *p = hex[read_nibble(*addr + i)]; + if (lead) + if ((i != 0) && (*p == '0')) + p--; + else + lead = 0; + p++; + } + + *p++ = 'h'; + } + else + { + *p++ = 'C'; + *p++ = '#'; + *p++ = ' '; + + sprintf(p, "%d", len); + p += strlen(p); + + *p++ = ' '; + + n = len; + if (len > 1000) + n = 1000; + + for (i = 0; i < n; i++) + *p++ = hex[read_nibble(*addr + i)]; + + if (n != len) + { + *p++ = '.'; + *p++ = '.'; + *p++ = '.'; + } + } + + *addr += len; + + *p = '\0'; + return p; +} + +char * +#ifdef __FunctionProto__ +dec_list(word_20 *addr, char *string) +#else +dec_list(addr, string) +word_20 *addr; +char *string; +#endif +{ + word_20 semi; + char *p = string; + + *p++ = '{'; + *p++ = ' '; + semi = read_nibbles(*addr, 5); + while (semi != SEMI) + { + p = dec_rpl_obj(addr, p); + semi = read_nibbles(*addr, 5); + if (semi != SEMI) + { + *p++ = ' '; + *p = '\0'; + } + } + *p++ = ' '; + *p++ = '}'; + *p = '\0'; + + *addr += 5; + return p; +} + +char * +#ifdef __FunctionProto__ +dec_symb(word_20 *addr, char *string) +#else +dec_symb(addr, string) +word_20 *addr; +char *string; +#endif +{ + word_20 semi; + char *p = string; + + semi = read_nibbles(*addr, 5); + *p++ = '\''; + while (semi != SEMI) + { + p = dec_rpl_obj(addr, p); + semi = read_nibbles(*addr, 5); + if (semi != SEMI) + { + *p++ = ' '; + *p = '\0'; + } + } + *addr += 5; + + *p++ = '\''; + *p = '\0'; + return p; +} + +char * +#ifdef __FunctionProto__ +dec_unit(word_20 *addr, char *string) +#else +dec_unit(addr, string) +word_20 *addr; +char *string; +#endif +{ + word_20 semi; + char *p = string; + + semi = read_nibbles(*addr, 5); + while (semi != SEMI) + { + p = dec_rpl_obj(addr, p); + semi = read_nibbles(*addr, 5); + if (semi != SEMI) + { + *p++ = ' '; + *p = '\0'; + } + } + *addr += 5; + return p; +} + +char * +#ifdef __FunctionProto__ +dec_unit_op(word_20 *addr, char *string) +#else +dec_unit_op(addr, string) +word_20 *addr; +char *string; +#endif +{ + word_20 op; + char *p = string; + + op = read_nibbles(*addr - 5, 5); + switch (op) + { + case UM_MUL: + *p++ = '*'; + break; + case UM_DIV: + *p++ = '/'; + break; + case UM_POW: + *p++ = '^'; + break; + case UM_END: + *p++ = '_'; + break; + case UM_PRE: + p--; + break; + default: + break; + } + *p = '\0'; + return p; +} + +char * +#ifdef __FunctionProto__ +dec_library(word_20 *addr, char *string) +#else +dec_library(addr, string) +word_20 *addr; +char *string; +#endif +{ + word_20 libsize, libidsize; +/* + word_20 hashoff, mesgoff, linkoff, cfgoff; + word_20 mesgloc, cfgloc; +*/ + int i, libnum; + unsigned char c; + char *p = string; + + libsize = read_nibbles(*addr, 5); + libidsize = read_nibbles(*addr + 5, 2); + libnum = read_nibbles(*addr + 2 * libidsize + 9, 3); + + sprintf(p, "Library %d: ", libnum); + p += strlen(p); + + for (i = 0; i < libidsize; i++) + { + c = read_nibbles(*addr + 2 * i + 7, 2); + if (hp48_trans_tbl[c].trans) + { + sprintf(p, hp48_trans_tbl[c].trans); + p += strlen(p); + } + else + *p++ = c; + } + + *addr += libsize; + + *p = '\0'; + return p; +} + +char * +#ifdef __FunctionProto__ +dec_library_data(word_20 *addr, char *string) +#else +dec_library_data(addr, string) +word_20 *addr; +char *string; +#endif +{ + word_20 size; + char *p = string; + + size = read_nibbles(*addr, 5); + + sprintf(p, "Library Data"); + p += strlen(p); + + *addr += size; + + *p = '\0'; + return p; +} + +char * +#ifdef __FunctionProto__ +dec_acptr(word_20 *addr, char *string) +#else +dec_acptr(addr, string) +word_20 *addr; +char *string; +#endif +{ + word_20 size; + char *p = string; + int i; + static char hex[] = "0123456789ABCDEF"; + + if (opt_gx) + { + size = 10; + sprintf(p, "ACPTR "); + p += strlen(p); + for (i = 0; i < 5; i++) + *p++ = hex[read_nibble(*addr + i)]; + *p++ = ' '; + for (i = 5; i < 10; i++) + *p++ = hex[read_nibble(*addr + i)]; + } + else + { + size = read_nibbles(*addr, 5); + sprintf(p, "Ext 1"); + p += strlen(p); + } + + *addr += size; + + *p = '\0'; + return p; +} + +char * +#ifdef __FunctionProto__ +dec_prog(word_20 *addr, char *string) +#else +dec_prog(addr, string) +word_20 *addr; +char *string; +#endif +{ + word_20 semi; + char *p = string; + + semi = read_nibbles(*addr, 5); + while (semi != SEMI) + { + p = dec_rpl_obj(addr, p); + semi = read_nibbles(*addr, 5); + if (semi != SEMI) + { + *p++ = ' '; + *p = '\0'; + } + } + *addr += 5; + return p; +} + +char * +#ifdef __FunctionProto__ +dec_code(word_20 *addr, char *string) +#else +dec_code(addr, string) +word_20 *addr; +char *string; +#endif +{ + char *p = string; + word_20 n, len; + + len = read_nibbles(*addr, 5); + sprintf(p, "Code"); + p += strlen(p); + + n = 0; + while (n < len) + { +/* + *addr = disassemble(*addr, p); +*/ + n += len; + } + + *addr += len; + return p; +} + +char * +#ifdef __FunctionProto__ +dec_local_ident(word_20 *addr, char *string) +#else +dec_local_ident(addr, string) +word_20 *addr; +char *string; +#endif +{ + int len, i, n; + char *p = string; + unsigned char c; + + len = read_nibbles(*addr, 2); + *addr += 2; + + n = len; + if (len > 1000) + n = 1000; + + for (i = 0; i < n; i++) + { + c = read_nibbles(*addr, 2); + *addr += 2; + if (hp48_trans_tbl[c].trans) + { + sprintf(p, hp48_trans_tbl[c].trans); + p += strlen(p); + } + else + *p++ = c; + } + + if (n != len) + { + *p++ = '.'; + *p++ = '.'; + *p++ = '.'; + } + + *p = '\0'; + return p; +} + +char * +#ifdef __FunctionProto__ +dec_global_ident(word_20 *addr, char *string) +#else +dec_global_ident(addr, string) +word_20 *addr; +char *string; +#endif +{ + int len, i, n; + char *p = string; + unsigned char c; + + len = read_nibbles(*addr, 2); + *addr += 2; + + n = len; + if (len > 1000) + n = 1000; + + for (i = 0; i < n; i++) + { + c = read_nibbles(*addr, 2); + *addr += 2; + if (hp48_trans_tbl[c].trans) + { + sprintf(p, hp48_trans_tbl[c].trans); + p += strlen(p); + } + else + *p++ = c; + } + + if (n != len) + { + *p++ = '.'; + *p++ = '.'; + *p++ = '.'; + } + + *p = '\0'; + return p; +} + +char * +#ifdef __FunctionProto__ +xlib_name(int lib, int command, char *string) +#else +xlib_name(lib, command, string) +int lib; +int command; +char *string; +#endif +{ + int n, len; + int i, lib_n = 0; + unsigned char c; + word_20 romptab, acptr; + word_20 offset, hash_end; + word_20 lib_addr, name_addr; + word_20 type, ram_base, ram_mask; + short present = 0; + char *p = string; + + /* + * Configure RAM to address 0x70000 + */ + ram_base = saturn.mem_cntl[1].config[0]; + ram_mask = saturn.mem_cntl[1].config[1]; + if (opt_gx) + { + saturn.mem_cntl[1].config[0] = 0x80000; + saturn.mem_cntl[1].config[1] = 0xc0000; + romptab = ROMPTAB_GX; + } + else + { + saturn.mem_cntl[1].config[0] = 0x70000; + saturn.mem_cntl[1].config[1] = 0xf0000; + romptab = ROMPTAB_SX; + } + + /* + * look up number of installed libs in romptab + */ + n = read_nibbles(romptab, 3); + romptab += 3; + + if (n > 0) + { + /* + * look up lib number in romptab + */ + while (n--) + { + lib_n = read_nibbles(romptab, 3); + romptab += 3; + if (lib_n == lib) + break; + romptab += 5; + if (opt_gx) + romptab += 8; + } + if (lib_n == lib) + { + /* + * look at hash table pointer + */ + lib_addr = read_nibbles(romptab, 5); + if (opt_gx) + { + romptab += 5; + acptr = read_nibbles(romptab, 5); + if (acptr != 0x00000) + { + saturn.mem_cntl[1].config[0] = ram_base; + saturn.mem_cntl[1].config[1] = ram_mask; + sprintf(p, "XLIB %d %d", lib, command); + p += strlen(p); + return p; + } + } + lib_addr += 3; + offset = read_nibbles(lib_addr, 5); + if (offset > 0) + { + /* + * look at the hash table + */ + lib_addr += offset; + + /* + * check if library is in ROM + */ + if (!opt_gx) + if (lib_addr < 0x70000) + saturn.mem_cntl[1].config[0] = 0xf0000; + + /* + * check pointer type + */ + type = read_nibbles(lib_addr, 5); + if (type == DOBINT) + { + /* + * follow pointer to real address + */ + lib_addr += 5; + lib_addr = read_nibbles(lib_addr, 5); + } + else if (type == DOACPTR) + { + /* + * follow pointer to real address + */ + lib_addr += 5; + acptr = lib_addr + 5; + lib_addr = read_nibbles(lib_addr, 5); + acptr = read_nibbles(acptr, 5); + if (acptr != 0x00000) + { + saturn.mem_cntl[1].config[0] = ram_base; + saturn.mem_cntl[1].config[1] = ram_mask; + sprintf(p, "XLIB %d %d", lib, command); + p += strlen(p); + return p; + } + } + + /* + * get length of hash table + */ + lib_addr += 5; + hash_end = read_nibbles(lib_addr, 5); + hash_end += lib_addr; + + /* + * go into real name table + */ + lib_addr += 85; + offset = read_nibbles(lib_addr, 5); + lib_addr += offset; + + /* + * look at library name number 'command' + */ + offset = 5 * command; + lib_addr += offset; + if (lib_addr < hash_end) + { + offset = read_nibbles(lib_addr, 5); + if (offset > 0) + { + name_addr = lib_addr - offset; + len = read_nibbles(name_addr, 2); + name_addr += 2; + present = 1; + for (i = 0; i < len; i++) + { + c = read_nibbles(name_addr, 2); + name_addr += 2; + if (hp48_trans_tbl[c].trans) + { + sprintf(p, hp48_trans_tbl[c].trans); + p += strlen(p); + } + else + *p++ = c; + } + *p = '\0'; + } + } + } + } + } + + /* + * Reconfigure RAM + */ + saturn.mem_cntl[1].config[0] = ram_base; + saturn.mem_cntl[1].config[1] = ram_mask; + + if (!present) + { + sprintf(p, "XLIB %d %d", lib, command); + p += strlen(p); + } + return p; +} + +char * +#ifdef __FunctionProto__ +dec_xlib_name(word_20 *addr, char *string) +#else +dec_xlib_name(addr, string) +word_20 *addr; +char *string; +#endif +{ + int lib, command; + + lib = read_nibbles(*addr, 3); + *addr += 3; + command = read_nibbles(*addr, 3); + *addr += 3; + + return xlib_name(lib, command, string); +} + +char * +#ifdef __FunctionProto__ +any_array(word_20 *addr, char *string, short lnk_flag) +#else +any_array(addr, string, lnk_flag) +word_20 *addr; +char *string; +short lnk_flag; +#endif +{ + word_20 len, type, dim; + word_20 *dim_lens, *dims; + word_20 array_addr, elem_addr; + long elems; + int d, i; + char *p = string; + struct objfunc *op; + + array_addr = *addr; + len = read_nibbles(*addr, 5); + *addr += 5; + type = read_nibbles(*addr, 5); + *addr += 5; + dim = read_nibbles(*addr, 5); + *addr += 5; + + for (op = objects; op->prolog != 0; op++) + { + if (op->prolog == type) + break; + } + + dim_lens = (word_20 *)malloc(dim * sizeof(word_20)); + dims = (word_20 *)malloc(dim * sizeof(word_20)); + elems = 1; + for (i = 0; i < dim; i++) + { + dim_lens[i] = read_nibbles(*addr, 5); + dims[i] = dim_lens[i]; + elems *= dim_lens[i]; + *addr += 5; + } + + if (op->prolog == 0) + { + sprintf(p, "of Type %.5lX, Dim %ld, Size ", type, (long)dim); + p += strlen(p); + for (i = 0; i < dim; i++) + { + sprintf(p, "%ld", (long)dim_lens[i]); + p += strlen(p); + if (i < dim - 1) + { + sprintf(p, " x "); + p += strlen(p); + } + } + *p = '\0'; + *addr = array_addr + len; + free(dim_lens); + free(dims); + return p; + } + + d = -1; + while (elems--) + { + if (d < dim - 1) + { + for ( ; d < dim - 1; d++) + { + *p++ = '['; + } + d = dim - 1; + } + if (lnk_flag) + { + elem_addr = read_nibbles(*addr, 5); + elem_addr += *addr; + *addr += 5; + p = (*op->func)(&elem_addr, p); + } + else + p = (*op->func)(addr, p); + *p = '\0'; + dims[d]--; + if (dims[d]) + *p++ = ' '; + while (dims[d] == 0) + { + dims[d] = dim_lens[d]; + d--; + dims[d]--; + *p++ = ']'; + } + } + + free(dim_lens); + free(dims); + *addr = array_addr + len; + + *p = '\0'; + return p; +} + +char * +#ifdef __FunctionProto__ +dec_array(word_20 *addr, char *string) +#else +dec_array(addr, string) +word_20 *addr; +char *string; +#endif +{ + return any_array(addr, string, 0); +} + +char * +#ifdef __FunctionProto__ +dec_lnk_array(word_20 *addr, char *string) +#else +dec_lnk_array(addr, string) +word_20 *addr; +char *string; +#endif +{ + return any_array(addr, string, 1); +} + +char * +#ifdef __FunctionProto__ +dec_char(word_20 *addr, char *string) +#else +dec_char(addr, string) +word_20 *addr; +char *string; +#endif +{ + char *p = string; + unsigned char c; + + c = read_nibbles(*addr, 2); + *addr += 2; + + *p++ = '\''; + if (hp48_trans_tbl[c].trans) + { + sprintf(p, hp48_trans_tbl[c].trans); + p += strlen(p); + } + else + *p++ = c; + *p++ = '\''; + + *p = 0; + return p; +} + +short +#ifdef __FunctionProto__ +check_xlib(word_20 addr, char *string) +#else +check_xlib(addr, string) +word_20 addr; +char *string; +#endif +{ + int n, lib, command; + word_20 romptab; + word_20 offset, link_end; + word_20 acptr; + word_20 lib_addr; + word_20 type, ram_base, ram_mask; + char *p = string; + + /* + * Configure RAM to address 0x70000 + */ + ram_base = saturn.mem_cntl[1].config[0]; + ram_mask = saturn.mem_cntl[1].config[1]; + if (opt_gx) + { + saturn.mem_cntl[1].config[0] = 0x80000; + saturn.mem_cntl[1].config[1] = 0xc0000; + romptab = ROMPTAB_GX; + } + else + { + saturn.mem_cntl[1].config[0] = 0x70000; + saturn.mem_cntl[1].config[1] = 0xf0000; + romptab = ROMPTAB_SX; + } + + /* + * look up number of installed libs in romptab + */ + n = read_nibbles(romptab, 3); + romptab += 3; + +/* +fprintf(stderr, "Number of Libraries = %d\n", n); +fflush(stderr); +*/ + + if (n > 0) + { + /* + * look up lib number in romptab + */ + while (n--) + { + lib = read_nibbles(romptab, 3); + romptab += 3; +/* +fprintf(stderr, "Library num = %d\n", lib); +fflush(stderr); +*/ + /* + * look at link table pointer + */ + lib_addr = read_nibbles(romptab, 5); +/* +fprintf(stderr, "Library addr = %.5lx\n", lib_addr); +fflush(stderr); +*/ + romptab += 5; + + if (opt_gx) + { + acptr = read_nibbles(romptab, 5); + romptab += 8; + if (acptr != 0x00000) + continue; + } + + lib_addr += 13; + offset = read_nibbles(lib_addr, 5); + if (offset > 0) + { + /* + * look at the link table + */ + lib_addr += offset; +/* +fprintf(stderr, "Link table addr = %.5lx\n", lib_addr); +fflush(stderr); +*/ + /* + * check if library is in ROM + */ + if (!opt_gx) + if (lib_addr < 0x70000) + saturn.mem_cntl[1].config[0] = 0xf0000; + + /* + * check pointer type + */ + type = read_nibbles(lib_addr, 5); + if (type == DOBINT) + { + /* + * follow pointer to real address + */ + lib_addr += 5; + lib_addr = read_nibbles(lib_addr, 5); + } +/* +fprintf(stderr, "Link table addr (2) = %.5lx\n", lib_addr); +fflush(stderr); +*/ + /* + * get length of link table + */ + lib_addr += 5; + link_end = read_nibbles(lib_addr, 5); + link_end += lib_addr; +/* +fprintf(stderr, "Link table end = %.5lx\n", link_end); +fflush(stderr); +*/ + /* + * look at library commands + */ + lib_addr += 5; + command = 0; + while (lib_addr < link_end) + { + offset = read_nibbles(lib_addr, 5); + if (offset > 0) + { + if (addr == ((lib_addr + offset) & 0xfffff)) + { + p = xlib_name(lib, command, p); + saturn.mem_cntl[1].config[0] = ram_base; + saturn.mem_cntl[1].config[1] = ram_mask; + return 1; + } + } + lib_addr += 5; + command++; + } + if (opt_gx) + saturn.mem_cntl[1].config[0] = 0x80000; + else + saturn.mem_cntl[1].config[0] = 0x70000; + } + } + } + + /* + * Reconfigure RAM + */ + saturn.mem_cntl[1].config[0] = ram_base; + saturn.mem_cntl[1].config[1] = ram_mask; + + return 0; +} + + +char * +#ifdef __FunctionProto__ +dec_rpl_obj(word_20 *addr, char *string) +#else +dec_rpl_obj(addr, string) +word_20 *addr; +char *string; +#endif +{ + word_20 prolog = 0; + word_20 prolog_2; + char *p = string; + char tmp_str[80]; + struct objfunc *op; + + prolog = read_nibbles(*addr, 5); + + for (op = objects; op->prolog != 0; op++) + { + if (op->prolog == prolog) + break; + } + + if (op->prolog == 0) + { + if (check_xlib(prolog, tmp_str)) + { + p = append_str(p, tmp_str); + } + else + { + prolog_2 = read_nibbles(prolog, 5); + for (op = objects; op->prolog != 0; op++) + { + if (op->prolog == prolog_2) + break; + } + if (op->prolog) + p = dec_rpl_obj(&prolog, p); + else + p = append_str(p, "External"); + } + *addr += 5; + return p; + } + + *addr += 5; + p = (*op->func)(addr, p); + + return p; +} + +void +#ifdef __FunctionProto__ +decode_rpl_obj_2(word_20 addr, char *typ, char *dat) +#else +decode_rpl_obj_2(addr, typ, dat) +word_20 addr; +char *typ; +char *dat; +#endif +{ + word_20 prolog = 0; + int len; + char tmp_str[80]; + struct objfunc *op; + + typ[0] = '\0'; + dat[0] = '\0'; + + prolog = read_nibbles(addr, 5); + + for (op = objects; op->prolog != 0; op++) + { + if (op->prolog == prolog) + break; + } + + if (op->prolog == 0) + { + if (addr == SEMI) + { + append_str(typ, "Primitive Code"); + append_str(dat, "SEMI"); + } + else if (addr + 5 == prolog) + { + append_str(typ, "Primitive Code"); + sprintf(dat, "at %.5lX", prolog); + } + else + { + append_str(typ, "PTR"); + sprintf(dat, "%.5lX", prolog); + } + return; + } + + if (op->prolog == DOCOL) + { + if (check_xlib(addr, tmp_str)) + { + append_str(typ, "XLib Call"); + append_str(dat, tmp_str); + return; + } + } + + if (op->length) + { + len = (read_nibbles(addr + 5, 5) - 5) / op->length; + sprintf(typ, "%s %d", op->name, len); + } + else + { + append_str(typ, op->name); + } + + addr += 5; + (*op->func)(&addr, dat); + + return; +} + +char * +#ifdef __FunctionProto__ +decode_rpl_obj(word_20 addr, char *buf) +#else +decode_rpl_obj(addr, buf) +word_20 addr; +char *buf; +#endif +{ + word_20 prolog = 0; + int len; + char *p = buf; + char tmp_str[80]; + struct objfunc *op; + + prolog = read_nibbles(addr, 5); + + for (op = objects; op->prolog != 0; op++) + { + if (op->prolog == prolog) + break; + } + + if (op->prolog == 0) + { + if (addr == SEMI) + { + p = append_str(buf, "Primitive Code"); + p = append_tab_16(buf); + p = append_str(p, "SEMI"); + } + else if (addr + 5 == prolog) + { + p = append_str(buf, "Primitive Code"); + p = append_tab_16(buf); + sprintf(p, "at %.5lX", prolog); + p += strlen(p); + *p = '\0'; + } + else + { + p = append_str(buf, "PTR"); + p = append_tab_16(buf); + sprintf(p, "%.5lX", prolog); + p += strlen(p); + *p = '\0'; + } + return p; + } + + if (op->prolog == DOCOL) + { + if (check_xlib(addr, tmp_str)) + { + p = append_str(buf, "XLib Call"); + p = append_tab_16(buf); + p = append_str(p, tmp_str); + return p; + } + } + + p = append_str(buf, op->name); + + if (op->length) + { + len = (read_nibbles(addr + 5, 5) - 5) / op->length; + sprintf(p, " %d", len); + p += strlen(p); + } + + p = append_tab_16(buf); + addr += 5; + p = (*op->func)(&addr, p); + + return p; +} + diff --git a/src/rpl.h b/src/rpl.h new file mode 100644 index 0000000..dd6a9b3 --- /dev/null +++ b/src/rpl.h @@ -0,0 +1,132 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: rpl.h,v $ + * Revision 1.3 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.2 1994/12/07 20:16:41 ecd + * more functions added + * + * Revision 1.2 1994/12/07 20:16:41 ecd + * more functions added + * + * Revision 1.1 1994/12/07 10:16:15 ecd + * Initial revision + * + * + * $Id: rpl.h,v 1.3 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#ifndef _RPL_H +#define _RPL_H 1 + +#include "global.h" +#include "hp48.h" + +/* + * Addresses in SX ROM + */ +#define ROMPTAB_SX 0x707d9 +#define ROMPTAB_GX 0x809a3 + + +/* + * Object Prologs + */ +#define DOBINT 0x02911 /* System Binary */ +#define DOREAL 0x02933 /* Real */ +#define DOEREL 0x02955 /* Extended Real */ +#define DOCMP 0x02977 /* Complex */ +#define DOECMP 0x0299d /* Extended Complex */ +#define DOCHAR 0x029bf /* Character */ +#define DOARRY 0x029e8 /* Array */ +#define DOLNKARRY 0x02a0a /* Linked Array */ +#define DOCSTR 0x02a2c /* String */ +#define DOHSTR 0x02a4e /* Binary Integer */ +#define DOLIST 0x02a74 /* List */ +#define DORRP 0x02a96 /* Directory */ +#define DOSYMB 0x02ab8 /* Algebraic */ +#define DOEXT 0x02ada /* Unit */ +#define DOTAG 0x02afc /* Tagged */ +#define DOGROB 0x02b1e /* Graphic Object */ +#define DOLIB 0x02b40 /* Library */ +#define DOBAK 0x02b62 /* Backup */ +#define DOEXT0 0x02b88 /* Library Data */ +#define DOACPTR 0x02baa /* */ +#define DOEXT2 0x02bcc /* */ +#define DOEXT3 0x02bee /* */ +#define DOEXT4 0x02c10 /* */ +#define DOCOL 0x02d9d /* Program */ +#define DOCODE 0x02dcc /* Code */ +#define DOIDNT 0x02e48 /* Global Name */ +#define DOLAM 0x02e6d /* Local Name */ +#define DOROMP 0x02e92 /* XLib Name */ + +/* + * Terminates composite objects + */ +#define SEMI 0x0312b /* Semi */ + +/* + * Unit Operators + */ +#define UM_MUL 0x10b5e /* Unit Operator * */ +#define UM_DIV 0x10b68 /* Unit Operator / */ +#define UM_POW 0x10b72 /* Unit Operator ^ */ +#define UM_PRE 0x10b7c /* Unit Operator prefix */ +#define UM_END 0x10b86 /* Unit Operator _ */ + +typedef struct hp_real { + word_20 x; + word_32 ml; + word_32 mh; + word_4 m; + word_1 s; +} hp_real; + +extern char *decode_rpl_obj __ProtoType__((word_20 addr, char *buf)); +extern void decode_rpl_obj_2 __ProtoType__((word_20 addr, char *typ, char *dat)); + +extern char *skip_ob __ProtoType__((word_20 *addr, char *string)); +extern char *dec_rpl_obj __ProtoType__((word_20 *addr, char *string)); +extern char *dec_bin_int __ProtoType__((word_20 *addr, char *string)); +extern char *dec_real __ProtoType__((word_20 *addr, char *string)); +extern char *dec_long_real __ProtoType__((word_20 *addr, char *string)); +extern char *dec_complex __ProtoType__((word_20 *addr, char *string)); +extern char *dec_long_complex __ProtoType__((word_20 *addr, char *string)); +extern char *dec_char __ProtoType__((word_20 *addr, char *string)); +extern char *dec_array __ProtoType__((word_20 *addr, char *string)); +extern char *dec_lnk_array __ProtoType__((word_20 *addr, char *string)); +extern char *dec_string __ProtoType__((word_20 *addr, char *string)); +extern char *dec_hex_string __ProtoType__((word_20 *addr, char *string)); +extern char *dec_list __ProtoType__((word_20 *addr, char *string)); +extern char *dec_symb __ProtoType__((word_20 *addr, char *string)); +extern char *dec_unit __ProtoType__((word_20 *addr, char *string)); +extern char *dec_library __ProtoType__((word_20 *addr, char *string)); +extern char *dec_library_data __ProtoType__((word_20 *addr, char *string)); +extern char *dec_acptr __ProtoType__((word_20 *addr, char *string)); +extern char *dec_prog __ProtoType__((word_20 *addr, char *string)); +extern char *dec_code __ProtoType__((word_20 *addr, char *string)); +extern char *dec_global_ident __ProtoType__((word_20 *addr, char *string)); +extern char *dec_local_ident __ProtoType__((word_20 *addr, char *string)); +extern char *dec_xlib_name __ProtoType__((word_20 *addr, char *string)); +extern char *dec_unit_op __ProtoType__((word_20 *addr, char *string)); + +#endif /* !_RPL_H */ diff --git a/src/serial.c b/src/serial.c new file mode 100644 index 0000000..eb86ad7 --- /dev/null +++ b/src/serial.c @@ -0,0 +1,727 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: serial.c,v $ + * Revision 1.11 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.10 1994/12/07 20:20:50 ecd + * complete change in handling of serial line, + * lines can be turned off now + * + * Revision 1.10 1994/12/07 20:20:50 ecd + * complete change in handling of serial line, + * lines can be turned off now + * + * Revision 1.9 1994/11/28 02:00:51 ecd + * added support for drawing the connections in the window title + * + * Revision 1.8 1994/11/02 14:44:28 ecd + * support for HPUX added + * + * Revision 1.7 1994/10/06 16:30:05 ecd + * new init for IRIX + * added CREAD for serial line + * + * Revision 1.6 1994/10/05 08:49:59 ecd + * changed printf() to print the correct /dev/ttyp? + * + * Revision 1.5 1994/09/30 12:37:09 ecd + * check if serial device is opened by OPENIO + * + * Revision 1.4 1994/09/18 15:29:22 ecd + * turned off unused rcsid message + * + * Revision 1.3 1994/09/13 16:57:00 ecd + * changed to plain X11 + * + * Revision 1.2 1994/08/31 18:23:21 ecd + * changed IR and wire definitions. + * + * Revision 1.1 1994/08/26 11:09:02 ecd + * Initial revision + * + * $Id: serial.c,v 1.11 1995/01/11 18:20:01 ecd Exp ecd $ + */ + + +#include "global.h" + +#include +#include +#include +#include +#include +#include +#if defined(HPUX) || defined(CSRG_BASED) +# include +#endif +#include +#include +#ifdef SOLARIS +# include +# include +# include +#endif + +#include "hp48.h" +#include "device.h" +#include "hp48_emu.h" +#include "resources.h" +#include "x48_x11.h" + +static int wire_fd; +static int ir_fd; +static int ttyp; + +extern int rece_instr; + +static char *wire_name = (char *)0; +static char *ir_name = (char *)0; + +/* #define DEBUG_SERIAL */ + +void +#ifdef __FunctionProto__ +update_connection_display(void) +#else +update_connection_display() +#endif +{ + if (wire_fd == -1) + { + if (wire_name) free(wire_name); + wire_name = (char *)0; + } + if (ir_fd == -1) + { + if (ir_name) free(ir_name); + ir_name = (char *)0; + } + ShowConnections(wire_name, ir_name); +} + +int +#ifdef __FunctionProto__ +serial_init(void) +#else +serial_init() +#endif +{ + char *p; + int c; + int n; + char tty_dev_name[128]; + struct termios ttybuf; + + wire_fd = -1; + ttyp = -1; + if (useTerminal) + { +#if defined(IRIX) + if ((p = _getpty(&wire_fd, O_RDWR | O_EXCL | O_NDELAY, 0666, 0)) == NULL) + { + wire_fd = -1; + ttyp = -1; + } + else + { + if ((ttyp = open(p, O_RDWR | O_NDELAY, 0666)) < 0) + { + close(wire_fd); + wire_fd = -1; + ttyp = -1; + } + else + { + if (verbose) + printf("%s: wire connection on %s\n", progname, p); + wire_name = strdup(p); + } + } +#elif defined(SOLARIS) + if ((wire_fd = open("/dev/ptmx", O_RDWR | O_NONBLOCK, 0666)) >= 0) + { + grantpt(wire_fd); + unlockpt(wire_fd); + p = ptsname(wire_fd); + strcpy(tty_dev_name, p); + if ((ttyp = open(tty_dev_name, O_RDWR | O_NDELAY, 0666)) >= 0) + { + ioctl(ttyp, I_PUSH, "ptem"); + ioctl(ttyp, I_PUSH, "ldterm"); + if (verbose) + printf("%s: wire connection on %s\n", progname, + tty_dev_name); + wire_name = strdup(tty_dev_name); + } + } +#elif defined(LINUX) + /* Unix98 PTY (Preferred) */ + if ((wire_fd = open("/dev/ptmx", O_RDWR | O_NONBLOCK, 0666)) >= 0) + { + grantpt(wire_fd); + unlockpt(wire_fd); + if (ptsname_r(wire_fd, tty_dev_name, 128)) { + perror("Could not get the name of the wire device."); + exit(-1); + } + if ((ttyp = open(tty_dev_name, O_RDWR | O_NDELAY, 0666)) >= 0) + { + if (verbose) + printf("%s: wire connection on %s\n", progname, + tty_dev_name); + wire_name = strdup(tty_dev_name); + } + } + /* BSD PTY (Legacy) */ + else + { + c = 'p'; + do + { + for (n = 0; n < 16; n++) + { + sprintf(tty_dev_name, "/dev/pty%c%x", c, n); + if ((wire_fd = open(tty_dev_name, + O_RDWR | O_EXCL | O_NDELAY, 0666)) >= 0) + { + ttyp = wire_fd; + sprintf(tty_dev_name, "/dev/tty%c%x", c, n); + if (verbose) + printf("%s: wire connection on %s\n", progname, + tty_dev_name); + wire_name = strdup(tty_dev_name); + break; + } + } + c++; + } + while ((wire_fd < 0) && (errno != ENOENT)); + } +#else + /* + * Here we go for SUNOS, HPUX + */ + c = 'p'; + do + { + for (n = 0; n < 16; n++) + { + sprintf(tty_dev_name, "/dev/ptyp%x", n); + if ((wire_fd = open(tty_dev_name, + O_RDWR | O_EXCL | O_NDELAY, 0666)) >= 0) + { + sprintf(tty_dev_name, "/dev/tty%c%x", c, n); + if ((ttyp = open(tty_dev_name, O_RDWR | O_NDELAY, 0666)) < 0) + { + wire_fd = -1; + ttyp = -1; + } + else + { + if (verbose) + printf("%s: wire connection on %s\n", progname, + tty_dev_name); + wire_name = strdup(tty_dev_name); + break; + } + } + } + c++; + } + while ((wire_fd < 0) && (errno != ENOENT)); +#endif + } + + if (ttyp >= 0) + { +#if defined(TCSANOW) + if (tcgetattr(ttyp, &ttybuf) < 0) +#else + if (ioctl(ttyp, TCGETS, (char *)&ttybuf) < 0) +#endif + { + if (!quiet) + fprintf(stderr, "%s: ioctl(wire, TCGETS) failed, errno = %d\n", + progname, errno); + wire_fd = -1; + ttyp = -1; + } + } + + ttybuf.c_lflag = 0; + ttybuf.c_iflag = 0; + ttybuf.c_oflag = 0; + ttybuf.c_cflag = B9600 | CS8 | CLOCAL | CREAD; + for (n = 0; n < NCCS; n++) + ttybuf.c_cc[n] = 0; + ttybuf.c_cc[VTIME] = 0; + ttybuf.c_cc[VMIN] = 1; + + if (ttyp >= 0) + { +#if defined(TCSANOW) + if (tcsetattr(ttyp, TCSANOW, &ttybuf) < 0) +#else + if (ioctl(ttyp, TCSETS, (char *)&ttybuf) < 0) +#endif + { + if (!quiet) + fprintf(stderr, "%s: ioctl(wire, TCSETS) failed, errno = %d\n", + progname, errno); + wire_fd = -1; + ttyp = -1; + } + } + + ir_fd = -1; + if (useSerial) + { + sprintf(tty_dev_name, serialLine); + if ((ir_fd = open(tty_dev_name, O_RDWR | O_NDELAY)) >= 0) + { + if (verbose) + printf("%s: IR connection on %s\n", progname, tty_dev_name); + ir_name = strdup(tty_dev_name); + } + } + + if (ir_fd >= 0) + { +#if defined(TCSANOW) + if (tcgetattr(ir_fd, &ttybuf) < 0) +#else + if (ioctl(ir_fd, TCGETS, (char *)&ttybuf) < 0) +#endif + { + if (!quiet) + fprintf(stderr, "%s: ioctl(IR, TCGETS) failed, errno = %d\n", + progname, errno); + ir_fd = -1; + } + } + + ttybuf.c_lflag = 0; + ttybuf.c_iflag = 0; + ttybuf.c_oflag = 0; + ttybuf.c_cflag = B9600 | CS8 | CLOCAL | CREAD; + for (n = 0; n < NCCS; n++) + ttybuf.c_cc[n] = 0; + ttybuf.c_cc[VTIME] = 0; + ttybuf.c_cc[VMIN] = 1; + + if (ir_fd >= 0) + { +#if defined(TCSANOW) + if (tcsetattr(ir_fd, TCSANOW, &ttybuf) < 0) +#else + if (ioctl(ir_fd, TCSETS, (char *)&ttybuf) < 0) +#endif + { + if (!quiet) + fprintf(stderr, "%s: ioctl(IR, TCSETS) failed, errno = %d\n", + progname, errno); + ir_fd = -1; + } + } + update_connection_display(); + return 1; +} + +void +#ifdef __FunctionProto__ +serial_baud(int baud) +#else +serial_baud(baud) +int baud; +#endif +{ + int error = 0; + struct termios ttybuf; + + if (ir_fd >= 0) + { +#if defined(TCSANOW) + if (tcgetattr(ir_fd, &ttybuf) < 0) +#else + if (ioctl(ir_fd, TCGETS, (char *)&ttybuf) < 0) +#endif + { + if (!quiet) + fprintf(stderr, "%s: ioctl(IR, TCGETS) failed, errno = %d\n", + progname, errno); + ir_fd = -1; + error = 1; + } + } + +#if defined(__APPLE__) + baud &= 0x7; + switch (baud) + { + case 0: /* 1200 */ + ttybuf.c_cflag |= B1200; + break; + case 1: /* 1920 */ +# ifdef B1920 + ttybuf.c_cflag |= B1920; +# endif + break; + case 2: /* 2400 */ + ttybuf.c_cflag |= B2400; + break; + case 3: /* 3840 */ +# ifdef B3840 + ttybuf.c_cflag |= B3840; +# endif + break; + case 4: /* 4800 */ + ttybuf.c_cflag |= B4800; + break; + case 5: /* 7680 */ +# ifdef B7680 + ttybuf.c_cflag |= B7680; +# endif + break; + case 6: /* 9600 */ + ttybuf.c_cflag |= B9600; + break; + case 7: /* 15360 */ +# ifdef B15360 + ttybuf.c_cflag |= B15360; +# endif + break; + } + + if ((ir_fd >= 0) && ((ttybuf.c_ospeed) == 0)) + { + if (!quiet) + fprintf(stderr, "%s: can\'t set baud rate, using 9600\n", progname); + ttybuf.c_cflag |= B9600; + } +#else + ttybuf.c_cflag &= ~CBAUD; + + baud &= 0x7; + switch (baud) + { + case 0: /* 1200 */ + ttybuf.c_cflag |= B1200; + break; + case 1: /* 1920 */ +# ifdef B1920 + ttybuf.c_cflag |= B1920; +# endif + break; + case 2: /* 2400 */ + ttybuf.c_cflag |= B2400; + break; + case 3: /* 3840 */ +# ifdef B3840 + ttybuf.c_cflag |= B3840; +# endif + break; + case 4: /* 4800 */ + ttybuf.c_cflag |= B4800; + break; + case 5: /* 7680 */ +# ifdef B7680 + ttybuf.c_cflag |= B7680; +# endif + break; + case 6: /* 9600 */ + ttybuf.c_cflag |= B9600; + break; + case 7: /* 15360 */ +# ifdef B15360 + ttybuf.c_cflag |= B15360; +# endif + break; + } + + if ((ir_fd >= 0) && ((ttybuf.c_cflag & CBAUD) == 0)) + { + if (!quiet) + fprintf(stderr, "%s: can\'t set baud rate, using 9600\n", progname); + ttybuf.c_cflag |= B9600; + } +#endif + if (ir_fd >= 0) + { +#if defined(TCSANOW) + if (tcsetattr(ir_fd, TCSANOW, &ttybuf) < 0) +#else + if (ioctl(ir_fd, TCSETS, (char *)&ttybuf) < 0) +#endif + { + if (!quiet) + fprintf(stderr, "%s: ioctl(IR, TCSETS) failed, errno = %d\n", + progname, errno); + ir_fd = -1; + error = 1; + } + } + + if (ttyp >= 0) + { +#if defined(TCSANOW) + if (tcgetattr(ttyp, &ttybuf) < 0) +#else + if (ioctl(ttyp, TCGETS, (char *)&ttybuf) < 0) +#endif + { + if (!quiet) + fprintf(stderr, "%s: ioctl(wire, TCGETS) failed, errno = %d\n", + progname, errno); + wire_fd = -1; + ttyp = -1; + error = 1; + } + } + +#if defined(__APPLE__) +#else + ttybuf.c_cflag &= ~CBAUD; + + baud &= 0x7; + switch (baud) + { + case 0: /* 1200 */ + ttybuf.c_cflag |= B1200; + break; + case 1: /* 1920 */ +# ifdef B1920 + ttybuf.c_cflag |= B1920; +# endif + break; + case 2: /* 2400 */ + ttybuf.c_cflag |= B2400; + break; + case 3: /* 3840 */ +# ifdef B3840 + ttybuf.c_cflag |= B3840; +# endif + break; + case 4: /* 4800 */ + ttybuf.c_cflag |= B4800; + break; + case 5: /* 7680 */ +# ifdef B7680 + ttybuf.c_cflag |= B7680; +# endif + break; + case 6: /* 9600 */ + ttybuf.c_cflag |= B9600; + break; + case 7: /* 15360 */ +# ifdef B15360 + ttybuf.c_cflag |= B15360; +# endif + break; + } + + if ((ttyp >= 0) && ((ttybuf.c_cflag & CBAUD) == 0)) + { + if (!quiet) + fprintf(stderr, "%s: can\'t set baud rate, using 9600\n", progname); + ttybuf.c_cflag |= B9600; + } +#endif + if (ttyp >= 0) + { +#if defined(TCSANOW) + if (tcsetattr(ttyp, TCSANOW, &ttybuf) < 0) +#else + if (ioctl(ttyp, TCSETS, (char *)&ttybuf) < 0) +#endif + { + if (!quiet) + fprintf(stderr, "%s: ioctl(wire, TCSETS) failed, errno = %d\n", + progname, errno); + wire_fd = -1; + ttyp = -1; + error = 1; + } + } + if (error) + update_connection_display(); +} + + +void +#ifdef __FunctionProto__ +transmit_char(void) +#else +transmit_char() +#endif +{ +#ifdef DEBUG_SERIALx + fprintf(stderr, "XMT %s\n", (saturn.ir_ctrl & 0x04) ? "IR" : "wire"); +#endif + + if (saturn.ir_ctrl & 0x04) { + if (ir_fd == -1) { + saturn.tcs &= 0x0e; + if (saturn.io_ctrl & 0x04) { + do_interupt(); + } + return; + } + } else { + if (wire_fd == -1) { + saturn.tcs &= 0x0e; + if (saturn.io_ctrl & 0x04) { + do_interupt(); + } + return; + } + } + +#ifdef DEBUG_SERIAL + if (isprint(saturn.tbr)) { + fprintf(stderr, "-> \'%c\'\n", saturn.tbr); + } else { + fprintf(stderr, "-> %x\n", saturn.tbr); + } +#endif + if (saturn.ir_ctrl & 0x04) { + if (write(ir_fd, &saturn.tbr, 1) == 1) { + saturn.tcs &= 0x0e; + if (saturn.io_ctrl & 0x04) { + do_interupt(); + } + } else { + if (errno != EAGAIN) { + fprintf(stderr, "%s: serial write error: %d\n", progname, errno); + } + saturn.tcs &= 0x0e; + if (saturn.io_ctrl & 0x04) { + do_interupt(); + } + } + } else { + if (write(wire_fd, &saturn.tbr, 1) == 1) { + saturn.tcs &= 0x0e; + if (saturn.io_ctrl & 0x04) { + do_interupt(); + } + } else { + if (errno != EAGAIN) { + if (!quiet) + fprintf(stderr, "%s: serial write error: %d\n", progname, errno); + } + saturn.tcs &= 0x0e; + if (saturn.io_ctrl & 0x04) { + do_interupt(); + } + } + } +} + +#define NR_BUFFER 256 + +void +#ifdef __FunctionProto__ +receive_char() +#else +receive_char() +#endif +{ + struct timeval tout; + fd_set rfds; + int nfd; + static unsigned char buf[NR_BUFFER + 1]; + static int nrd = 0, bp = 0; + +#ifdef DEBUG_SERIALx + fprintf(stderr, "RCV %s\n", (saturn.ir_ctrl & 0x04) ? "IR" : "wire"); +#endif + + rece_instr = 0; + + if (saturn.ir_ctrl & 0x04) { + if (ir_fd == -1) + return; + } else { + if (wire_fd == -1) + return; + } + + if (saturn.rcs & 0x01) { + return; + } + + if (nrd == 0) { + tout.tv_sec = 0; + tout.tv_usec = 0; + FD_ZERO(&rfds); + if (saturn.ir_ctrl & 0x04) { + FD_SET(ir_fd, &rfds); + nfd = ir_fd + 1; + } else { + FD_SET(wire_fd, &rfds); + nfd = wire_fd + 1; + } + if ((nfd = select(nfd, &rfds, (fd_set *)0, (fd_set *)0, &tout)) > 0) { +#ifdef DEBUG_SERIAL + fprintf(stderr, "select = %d\n", nfd); +#endif + if (saturn.ir_ctrl & 0x04) { + if (FD_ISSET(ir_fd, &rfds)) { + nrd = read(ir_fd, buf, NR_BUFFER); + if (nrd < 0) { + nrd = 0; + return; + } + bp = 0; + } else { + return; + } + } else { + if (FD_ISSET(wire_fd, &rfds)) { + nrd = read(wire_fd, buf, NR_BUFFER); + if (nrd < 0) { + nrd = 0; + return; + } + bp = 0; + } else { + return; + } + } + } else { + return; + } + } + if (nrd == 0) { + return; + } + if (!(saturn.io_ctrl & 0x08)) { + nrd = 0; + return; + } + saturn.rbr = buf[bp++]; + nrd--; + saturn.rcs |= 0x01; + if (saturn.io_ctrl & 0x02) { + do_interupt(); + } +} + diff --git a/src/small.h b/src/small.h new file mode 100644 index 0000000..22dce44 --- /dev/null +++ b/src/small.h @@ -0,0 +1,329 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: small.h,v $ + * Revision 1.5 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.4 1994/12/07 20:16:41 ecd + * completed small font + * + * Revision 1.4 1994/12/07 20:16:41 ecd + * completed small font + * + * Revision 1.3 1994/11/02 14:51:27 ecd + * minor changes + * + * Revision 1.2 1994/10/06 16:28:03 ecd + * changed char to unsigned + * + * Revision 1.1 1994/09/13 15:05:11 ecd + * Initial revision + * + * + * $Id: small.h,v 1.5 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#ifndef _SMALL_H +#define _SMALL_H 1 + +#define small_ascent 8 +#define small_descent 4 + +#include "bitmaps/blank.h" + +#include "bitmaps/hash.h" + +#include "bitmaps/lbrace.h" + +#include "bitmaps/rbrace.h" + +#include "bitmaps/comma.h" + +#include "bitmaps/slash.h" + +#include "bitmaps/two.h" + +#include "bitmaps/three.h" + +#include "bitmaps/small_colon.h" + +#include "bitmaps/A.h" + +#include "bitmaps/B.h" + +#include "bitmaps/C.h" + +#include "bitmaps/D.h" + +#include "bitmaps/E.h" + +#include "bitmaps/F.h" + +#include "bitmaps/G.h" + +#include "bitmaps/H.h" + +#include "bitmaps/I.h" + +#include "bitmaps/J.h" + +#include "bitmaps/K.h" + +#include "bitmaps/L.h" + +#include "bitmaps/M.h" + +#include "bitmaps/N.h" + +#include "bitmaps/O.h" + +#include "bitmaps/P.h" + +#include "bitmaps/Q.h" + +#include "bitmaps/R.h" + +#include "bitmaps/S.h" + +#include "bitmaps/T.h" + +#include "bitmaps/U.h" + +#include "bitmaps/V.h" + +#include "bitmaps/W.h" + +#include "bitmaps/X.h" + +#include "bitmaps/Y.h" + +#include "bitmaps/Z.h" + +#include "bitmaps/lbracket.h" + +#include "bitmaps/rbracket.h" + +#include "bitmaps/arrow.h" + +#include "bitmaps/diff.h" + +#include "bitmaps/integral.h" + +#include "bitmaps/sigma.h" + +#include "bitmaps/sqr.h" + +#include "bitmaps/root.h" + +#include "bitmaps/pow10.h" + +#include "bitmaps/exp.h" + +#include "bitmaps/under.h" + +#include "bitmaps/prog.h" + +#include "bitmaps/string.h" + +#include "bitmaps/equal.h" + +#include "bitmaps/nl.h" + +#include "bitmaps/pi.h" + +#include "bitmaps/angle.h" + +#include "bitmaps/lcurly.h" + +#include "bitmaps/rcurly.h" + +#include "bitmaps/sqr_gx.h" + +#include "bitmaps/root_gx.h" + +#include "bitmaps/pow10_gx.h" + +#include "bitmaps/exp_gx.h" + +#include "bitmaps/parens_gx.h" + +#include "bitmaps/hash_gx.h" + +#include "bitmaps/bracket_gx.h" + +#include "bitmaps/under_gx.h" + +#include "bitmaps/prog_gx.h" + +#include "bitmaps/quote_gx.h" + +#include "bitmaps/curly_gx.h" + +#include "bitmaps/colon_gx.h" + +#include "bitmaps/angle_gx.h" + +#include "bitmaps/pi_gx.h" + +#include "bitmaps/nl_gx.h" + +#include "bitmaps/comma_gx.h" + +#include "bitmaps/arrow_gx.h" + +#include "bitmaps/equal_gx.h" + +typedef struct letter_t { + unsigned int w, h; + unsigned char *bits; +} letter_t; + +letter_t small_font[] = { + { 0, 0, 0 }, + { nl_gx_width, nl_gx_height, nl_gx_bits }, /* \001 == \n gx */ + { comma_gx_width, comma_gx_height, comma_gx_bits }, /* \002 == comma gx */ + { arrow_gx_width, arrow_gx_height, arrow_gx_bits }, /* \003 == \-> gx */ + { equal_gx_width, equal_gx_height, equal_gx_bits }, /* \004 == equal gx */ + { pi_gx_width, pi_gx_height, pi_gx_bits }, /* \005 == pi gx */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, /* # 16 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { blank_width, blank_height, blank_bits }, /* # 32 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { hash_width, hash_height, hash_bits }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { lbrace_width, lbrace_height, lbrace_bits }, + { rbrace_width, rbrace_height, rbrace_bits }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { comma_width, comma_height, comma_bits }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { slash_width, slash_height, slash_bits }, + { 0, 0, 0 }, /* # 48 */ + { 0, 0, 0 }, + { two_width, two_height, two_bits }, + { three_width, three_height, three_bits }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { small_colon_width, small_colon_height, small_colon_bits }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { equal_width, equal_height, equal_bits }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, /* # 64 */ + { A_width, A_height, A_bits }, + { B_width, B_height, B_bits }, + { C_width, C_height, C_bits }, + { D_width, D_height, D_bits }, + { E_width, E_height, E_bits }, + { F_width, F_height, F_bits }, + { G_width, G_height, G_bits }, + { H_width, H_height, H_bits }, + { I_width, I_height, I_bits }, + { J_width, J_height, J_bits }, + { K_width, K_height, K_bits }, + { L_width, L_height, L_bits }, + { M_width, M_height, M_bits }, + { N_width, N_height, N_bits }, + { O_width, O_height, O_bits }, + { P_width, P_height, P_bits }, /* # 80 */ + { Q_width, Q_height, Q_bits }, + { R_width, R_height, R_bits }, + { S_width, S_height, S_bits }, + { T_width, T_height, T_bits }, + { U_width, U_height, U_bits }, + { V_width, V_height, V_bits }, + { W_width, W_height, W_bits }, + { X_width, X_height, X_bits }, + { Y_width, Y_height, Y_bits }, + { Z_width, Z_height, Z_bits }, + { lbracket_width, lbracket_height, lbracket_bits }, + { 0, 0, 0 }, + { rbracket_width, rbracket_height, rbracket_bits }, + { 0, 0, 0 }, + { under_width, under_height, under_bits }, + { 0, 0, 0 }, /* # 96 */ + { arrow_width, arrow_height, arrow_bits }, /* a == left arrow */ + { diff_width, diff_height, diff_bits }, /* b == differential */ + { integral_width, integral_height, integral_bits }, /* c == integral */ + { sigma_width, sigma_height, sigma_bits }, /* d == sigma */ + { sqr_width, sqr_height, sqr_bits }, /* e == sqr */ + { root_width, root_height, root_bits }, /* f == root */ + { pow10_width, pow10_height, pow10_bits }, /* g == pow10 */ + { exp_width, exp_height, exp_bits }, /* h == exp */ + { prog_width, prog_height, prog_bits }, /* i == << >> */ + { string_width, string_height, string_bits }, /* j == " " */ + { nl_width, nl_height, nl_bits }, /* k == New Line */ + { pi_width, pi_height, pi_bits }, /* l == pi */ + { angle_width, angle_height, angle_bits }, /* m == angle */ + { sqr_gx_width, sqr_gx_height, sqr_gx_bits }, /* n == sqr gx */ + { root_gx_width, root_gx_height, root_gx_bits }, /* o == root gx */ + { pow10_gx_width, pow10_gx_height, pow10_gx_bits }, /* p == pow10 gx */ + { exp_gx_width, exp_gx_height, exp_gx_bits }, /* q == exp gx */ + { parens_gx_width, parens_gx_height, parens_gx_bits },/* r == ( ) gx */ + { hash_gx_width, hash_gx_height, hash_gx_bits }, /* s == # gx */ + { bracket_gx_width, bracket_gx_height, bracket_gx_bits }, /* t == [] gx */ + { under_gx_width, under_gx_height, under_gx_bits }, /* u == _ gx */ + { prog_gx_width, prog_gx_height, prog_gx_bits }, /* v == << >> gx */ + { quote_gx_width, quote_gx_height, quote_gx_bits }, /* w == " " gx */ + { curly_gx_width, curly_gx_height, curly_gx_bits }, /* x == {} gx */ + { colon_gx_width, colon_gx_height, colon_gx_bits }, /* y == :: gx */ + { angle_gx_width, angle_gx_height, angle_gx_bits }, /* z == angle gx */ + { lcurly_width, lcurly_height, lcurly_bits }, + { 0, 0, 0 }, + { rcurly_width, rcurly_height, rcurly_bits }, + { 0, 0, 0 }, + { 0, 0, 0 } +}; + +#endif /* !_SMALL_H */ diff --git a/src/timer.c b/src/timer.c new file mode 100644 index 0000000..6142480 --- /dev/null +++ b/src/timer.c @@ -0,0 +1,543 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: timer.c,v $ + * Revision 1.7 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.6 1994/12/07 20:20:50 ecd + * minor fix + * + * Revision 1.6 1994/12/07 20:20:50 ecd + * minor fix + * + * Revision 1.5 1994/11/28 02:00:51 ecd + * removed stupid bug that caused negative time on call + * to adjtime() + * + * Revision 1.4 1994/11/02 14:44:28 ecd + * real time support completed + * + * + * $Id: timer.c,v 1.7 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#include "global.h" + +#include +#include +#include +#include + +#include "timer.h" +#include "debugger.h" +#include "romio.h" + +#include + +/* #define DEBUG_TIMER 1 */ +/* #define DEBUG_TIMER_ADJUST 1 */ + +#ifdef SOLARIS +extern int gettimeofday __ProtoType__((struct timeval *tp)); +#endif +#ifdef SUNOS +extern int gettimeofday __ProtoType__((struct timeval *, struct timezone *)); +#endif + +typedef struct x48_timer_t { + word_1 run; + word_64 start; + word_64 stop; + word_64 value; +} x48_timer_t; + +static x48_timer_t timers[NR_TIMERS]; + +static long systime_offset = 0; + +/* + * Ticks for THU 01.01.1970 00:00:00 + */ +word_64 unix_0_time = 0x1CF2E8F800000L; +word_64 ticks_10_min = 0x00b40000L; + +/* + * Will be in saturn_t in the future + */ +word_64 set_0_time = 0x0; + +/* + * Calculated as (unix_0_time + set_0_time) + */ +word_64 time_offset = 0x0; + +#define RAM_BASE_SX 0x70000 +#define ACCESSTIME_SX (0x70052 - RAM_BASE_SX) +#define ACCESSCRC_SX (0x7005F - RAM_BASE_SX) +#define TIMEOUT_SX (0x70063 - RAM_BASE_SX) +#define TIMEOUTCLK_SX (0x70070 - RAM_BASE_SX) + +#define RAM_BASE_GX 0x80000 +#define ACCESSTIME_GX (0x80058 - RAM_BASE_GX) +#define ACCESSCRC_GX (0x80065 - RAM_BASE_GX) +#define TIMEOUT_GX (0x80069 - RAM_BASE_GX) +#define TIMEOUTCLK_GX (0x80076 - RAM_BASE_GX) + +#define calc_crc(nib) (crc = (crc >> 4) ^ (((crc ^ (nib)) & 0xf) * 0x1081)) + +/* + * Set ACCESSTIME: (on startup) + * + * 1. TICKS = 8192 * gettimeofday() (UNIX System Time) + * 2. TICKS += unix_0_time (TICKS for 1.1.1970, 0:00) + * 3. TICKS += set_0_time (Time adjustment from User) + * 4. TICKS += saturn.timer2 (Timer 2 from last run) + * 5. Write this into ACCESSTIME + * 6. Calculate CRC for 13 Nibbles + * 7. Write this into ACCESSCRC + * 8. Prevent AutoOff by setting TIMEOUT + * + */ +void +#ifdef __FunctionProto__ +set_accesstime(void) +#else +set_accesstime() +#endif +{ + struct timeval tv; +#ifndef SOLARIS + struct timezone tz; +#endif + word_64 ticks, timeout, timer2; + word_20 accesstime_loc, timeout_loc; + word_20 accesscrc_loc, timeoutclk_loc; + word_16 crc; + word_4 val; + int i; + time_t gmt; + struct tm *ltm; + + /* + * This is done to set the variable 'timezone' on SYSV systems + */ + (void)time(&gmt); + ltm = localtime(&gmt); +#if defined(SYSV_TIME) || defined(__sgi) + systime_offset = timezone; + if( ltm->tm_isdst ) + systime_offset -= 3600; +#else + systime_offset = -ltm->tm_gmtoff; +#endif + +#ifdef SOLARIS + gettimeofday(&tv); +#else + gettimeofday(&tv, &tz); +#endif + tv.tv_sec -= systime_offset; + + ticks = tv.tv_sec; + ticks <<= 13; + ticks += (tv.tv_usec << 7) / 15625; + + time_offset = unix_0_time + set_0_time; + ticks += time_offset; + + timer2 = saturn.timer2; + if (saturn.timer2 & 0x80000000) + { + assert(timer2 < 0); + } + + ticks += timer2; + + timeout = ticks; + + crc = 0x0; + + if (opt_gx) + { + accesstime_loc = ACCESSTIME_GX; + accesscrc_loc = ACCESSCRC_GX; + timeout_loc = TIMEOUT_GX; + timeoutclk_loc = TIMEOUTCLK_GX; + } + else + { + accesstime_loc = ACCESSTIME_SX; + accesscrc_loc = ACCESSCRC_SX; + timeout_loc = TIMEOUT_SX; + timeoutclk_loc = TIMEOUTCLK_SX; + } + + for (i = 0; i < 13; i++) + { + val = ticks & 0xf; + calc_crc(val); + saturn.ram[accesstime_loc + i] = val; + ticks >>= 4; + } + + for (i = 0; i < 4; i++) + { + saturn.ram[accesscrc_loc + i] = crc & 0xf; + crc >>= 4; + } + + timeout += ticks_10_min; + + for (i = 0; i < 13; i++) + { + val = timeout & 0xf; + calc_crc(val); + saturn.ram[timeout_loc + i] = val; + timeout >>= 4; + } + + saturn.ram[timeoutclk_loc] = 0xf; +} + +void +#ifdef __FunctionProto__ +start_timer(int timer) +#else +start_timer(timer) +int timer; +#endif +{ + struct timeval tv; +#ifndef SOLARIS + struct timezone tz; +#endif + assert(timer <= NR_TIMERS); + + if (timers[timer].run == 1) + return; + +#ifdef SOLARIS + gettimeofday(&tv); +#else + gettimeofday(&tv, &tz); +#endif + tv.tv_sec -= systime_offset; + + timers[timer].run = 1; + if (timer == T1_TIMER) { + timers[timer].start = (tv.tv_sec << 9); + timers[timer].start += (tv.tv_usec / 15625) >> 3; + } else { + timers[timer].start = tv.tv_sec; + timers[timer].start <<= 13; + timers[timer].start += (tv.tv_usec << 7) / 15625; + } +#ifdef DEBUG_TIMER + fprintf(stderr, "Timer%c[%d] start at 0x%lx\n", timer == T1_TIMER?'*':' ', timer, timers[timer].start); +#endif +} + +void +#ifdef __FunctionProto__ +restart_timer(int timer) +#else +restart_timer(timer) +int timer; +#endif +{ + struct timeval tv; +#ifndef SOLARIS + struct timezone tz; +#endif + + if (timer > NR_TIMERS) + return; + + timers[timer].start = 0; + timers[timer].stop = 0; + timers[timer].value = 0; + +#ifdef SOLARIS + gettimeofday(&tv); +#else + gettimeofday(&tv, &tz); +#endif + tv.tv_sec -= systime_offset; + + timers[timer].run = 1; + if (timer == T1_TIMER) { + timers[timer].start = (tv.tv_sec << 9); + timers[timer].start += (tv.tv_usec / 15625) >> 3; + } else { + timers[timer].start = tv.tv_sec; + timers[timer].start <<= 13; + timers[timer].start += (tv.tv_usec << 7) / 15625; + } +#ifdef DEBUG_TIMER + fprintf(stderr, "Timer[%d] restart at 0x%lx\n", timer, + timers[timer].start); +#endif +} + +void +#ifdef __FunctionProto__ +stop_timer(int timer) +#else +stop_timer(timer) +int timer; +#endif +{ + struct timeval tv; +#ifndef SOLARIS + struct timezone tz; +#endif + + if (timer > NR_TIMERS) + return; + + if (timers[timer].run == 0) + return; + +#ifdef SOLARIS + gettimeofday(&tv); +#else + gettimeofday(&tv, &tz); +#endif + tv.tv_sec -= systime_offset; + + timers[timer].run = 0; + if (timer == T1_TIMER) { + timers[timer].stop = (tv.tv_sec << 9); + timers[timer].stop += (tv.tv_usec / 15625) >> 3; + } else { + timers[timer].stop = tv.tv_sec; + timers[timer].stop <<= 13; + timers[timer].stop += (tv.tv_usec << 7) / 15625; + } + + timers[timer].value += timers[timer].stop - timers[timer].start; +// add_sub_64(&timers[timer].stop, &timers[timer].start, &timers[timer].value); + +#ifdef DEBUG_TIMER + fprintf(stderr, "Timer[%d] stop at 0x%llx, value 0x%llx\n", + timer, timers[timer].stop, timers[timer].value); +#endif +} + +void +#ifdef __FunctionProto__ +reset_timer(int timer) +#else +reset_timer(timer) +int timer; +#endif +{ + if (timer > NR_TIMERS) + return; + timers[timer].run = 0; + timers[timer].start = 0; + timers[timer].stop = 0; + timers[timer].value = 0; +#ifdef DEBUG_TIMER + fprintf(stderr, "Timer[%d] reset\n", timer); +#endif +} + +static word_64 zero = 0; + +word_64 +#ifdef __FunctionProto__ +get_timer(int timer) +#else +get_timer(timer) +int timer; +#endif +{ + struct timeval tv; +#ifndef SOLARIS + struct timezone tz; +#endif + word_64 stop; + + if (timer > NR_TIMERS) + return zero; + + if (timers[timer].run) { + +#ifdef SOLARIS + gettimeofday(&tv); +#else + gettimeofday(&tv, &tz); +#endif + tv.tv_sec -= systime_offset; + + if (timer == T1_TIMER) { + stop = (tv.tv_sec << 9); + stop += (tv.tv_usec / 15625) >> 3; + } else { + stop = tv.tv_sec; + stop <<= 13; + stop += (tv.tv_usec << 7) / 15625; + } + timers[timer].value += stop - timers[timer].start; + } + + return timers[timer].value; +} + +/* + * Calculate TIMER 2 Ticks: + * + * 1. TICKS = 8192 * gettimeofday() (UNIX System Time) + * 2. TICKS += unix_0_time (TICKS for 1.1.1970, 0:00) + * 3. TICKS += set_0_time (Time adjustment from User) + * 4. Get value of ACCESSTIME + * 5. Return (ACCESSTIME - TICKS) + * + */ + +t1_t2_ticks +#ifdef __FunctionProto__ +get_t1_t2(void) +#else +get_t1_t2() +#endif +{ + struct timeval tv; +#ifndef SOLARIS + struct timezone tz; +#endif + word_64 stop; + t1_t2_ticks ticks; + word_64 access_time; + word_64 adj_time; + word_64 diff_time; + word_64 delta; + word_20 accesstime_loc; + int i; + +#ifdef SOLARIS + gettimeofday(&tv); +#else + gettimeofday(&tv, &tz); +#endif + tv.tv_sec -= systime_offset; + + if (timers[T1_TIMER].run) + { + stop = (tv.tv_sec << 9); + stop += (tv.tv_usec / 15625) >> 3; + if (timers[T1_TIMER].start <= stop) + { + timers[T1_TIMER].value += stop - timers[T1_TIMER].start; + } else { + fprintf(stderr, "clock running backwards\n"); + } + } + ticks.t1_ticks = timers[T1_TIMER].value; + + stop = tv.tv_sec; + stop <<= 13; + stop += (tv.tv_usec << 7) / 15625; + + stop += time_offset; + + accesstime_loc = opt_gx ? ACCESSTIME_GX : ACCESSTIME_SX; + + access_time = 0x0; + + for (i = 13 - 1; i >= 0; i--) + { + access_time <<= 4; + access_time |= ((int)saturn.ram[accesstime_loc + i] & 0xf); + } + + access_time -= stop; + + if (adj_time_pending || in_debugger) + { + /* + * We have been inside an interrupt for very long, maybe + * or we are sleeping in the debugger. + * Don't adjust the time, can't come from user, anyhow. + */ + + if ((saturn.timer2 >= 0 && access_time < 0) + || ((unsigned long)saturn.timer2 > access_time)) + { + /* + * check OK, return calculated time + */ + ticks.t2_ticks = access_time; + } + else + { + /* + * Don't increment timer2, return old value and + * slow down timer2. + */ + ticks.t2_ticks = saturn.timer2; + saturn.t2_tick++; + } + + return ticks; + } + + diff_time = saturn.timer2; + + adj_time = access_time - diff_time; + delta = abs(adj_time); + + if (delta > 0x3c000) /* Half a minute */ + { + set_0_time += adj_time; + time_offset += adj_time; + access_time -= adj_time; + +#ifdef DEBUG_TIMER_ADJUST + fprintf(stderr, "Time adjusted by "); + fprintf(stderr, "%lX", adj_time); + fprintf(stderr, " TICKS, Total offset "); + fprintf(stderr, "%lX", set_0_time); + fprintf(stderr, " TICKS\n"); +#endif + } + + if ((saturn.timer2 >= 0 && (access_time < 0)) + || ((unsigned long)saturn.timer2 > access_time)) + { + /* + * check OK, return calculated time + */ + ticks.t2_ticks = access_time; + } + else + { + /* + * Don't increment timer2, return old value and + * slow down timer2. + */ + ticks.t2_ticks = saturn.timer2; + saturn.t2_tick++; + } + + return ticks; +} + diff --git a/src/timer.h b/src/timer.h new file mode 100644 index 0000000..b487daa --- /dev/null +++ b/src/timer.h @@ -0,0 +1,62 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: timer.h,v $ + * Revision 1.3 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.2 1994/11/02 14:51:27 ecd + * new functions: set_accesstime() + * + * Revision 1.2 1994/11/02 14:51:27 ecd + * new functions: set_accesstime() + * + * + * $Id: timer.h,v 1.3 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#ifndef _TIMER_H +#define _TIMER_H 1 + +#include "global.h" +#include "hp48.h" + +#define NR_TIMERS 4 + +#define T1_TIMER 0 +#define T2_TIMER 1 +#define RUN_TIMER 2 +#define IDLE_TIMER 3 + +typedef struct t1_t2_ticks { + unsigned long t1_ticks; + unsigned long t2_ticks; +} t1_t2_ticks; + +extern void reset_timer __ProtoType__((int timer)); +extern void start_timer __ProtoType__((int timer)); +extern void restart_timer __ProtoType__((int timer)); +extern void stop_timer __ProtoType__((int timer)); +extern word_64 get_timer __ProtoType__((int timer)); +extern long diff_timer __ProtoType__((word_64 *t1, word_64 *t2)); + +extern t1_t2_ticks get_t1_t2 __ProtoType__((void)); +extern void set_accesstime __ProtoType__((void)); + +#endif /* !_TIMER_H */ diff --git a/src/version.h b/src/version.h new file mode 100644 index 0000000..db6d47f --- /dev/null +++ b/src/version.h @@ -0,0 +1,44 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: version.h,v $ + * Revision 1.2 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.1 1994/11/28 02:27:59 ecd + * Initial revision + * + * Revision 1.1 1994/11/28 02:27:59 ecd + * Initial revision + * + * + * $Id: version.h,v 1.2 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#ifndef _VERSION_H +#define _VERSION_H 1 + +extern int VERSION_MAJOR; +extern int VERSION_MINOR; +extern int PATCHLEVEL; +extern int COMPILE_VERSION; +extern char *COMPILE_TIME; +extern char *COMPILE_BY; + +#endif /* !_VERSION_H */ diff --git a/src/x48.man.in b/src/x48.man.in new file mode 100644 index 0000000..646e291 --- /dev/null +++ b/src/x48.man.in @@ -0,0 +1,289 @@ +.\" # @configure_input@ +.\" +.\" $Id$ +.\" Copyright (c) 2005 G. Allen Morris III +.\" +.\" Permission is hereby granted, free of charge, to any person obtaining +.\" a copy of this software and associated documentation files (the +.\" "Software"), to deal in the Software without restriction, including +.\" without limitation the rights to use, copy, modify, merge, publish, +.\" distribute, sublicense, and/or sell copies of the Software, and to +.\" permit persons to whom the Software is furnished to do so, subject to +.\" the following conditions: +.\" +.\" The above copyright notice and this permission notice shall be included +.\" in all copies or substantial portions of the Software. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +.\" IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR +.\" OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +.\" ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +.\" OTHER DEALINGS IN THE SOFTWARE. +.\" +.\" Except as contained in this notice, the name of the X Consortium shall +.\" not be used in advertising or otherwise to promote the sale, use or +.\" other dealings in this Software without prior written authorization +.\" from the X Consortium. +.\" +.\" $XFree86: xc/programs/xcalc/xcalc.man,v 1.5 2003/03/19 01:49:28 dawes Exp $ +.\" +.de EX \"Begin example +.ne 5 +.if n .sp 1 +.if t .sp .5 +.nf +.in +.5i +.. +.de EE +.fi +.in -.5i +.if n .sp 1 +.if t .sp .5 +.. +.TH X48 1 "20 April 2006" "Version @VERSION@" "X48 Manual Pages" +.SH NAME +x48 \- scientific calculator for X and an HP 48 emulator +.SH SYNOPSIS +.B x48 +[\-options ...] + +where options include: +.br + [\-help] print out this message +.br + [\-display ] X server to contact +.br + [\-name ] set application name to +.br + [\-title ] set window title to +.br + [\-geometry ] position of window +.br + [\-iconGeom ] position of icon window +.br + [\-iconic] start iconic +.br + [\-visual ] use visual +.br + [\-mono] force monochrome +.br + [\-gray] force grayscale +.br + [\-monoIcon] force monochrome icon +.br + [\-smallFont ] to draw small labels (MTH - DEL) +.br + [\-mediumFont ] to draw medium label (ENTER) +.br + [\-largeFont ] to draw large labels (Numbers) +.br + [\-connFont ] to display wire & IR connections +.br + [\-/+xshm] turn on/off XShm extension +.br + [\-version] print out version information +.br + [\-copyright] print out copyright information +.br + [\-warranty] print out warranty information +.br + [\-verbose] run verbosive +.br + [\-quiet] run quietly +.br + [\-/+terminal] turn on/off pseudo terminal interface +.br + [\-/+serial] turn on/off serial interface +.br + [\-line ] use serial line for IR connection +.br + [\-/+debug turn on/off debugger +.br + [\-disasm use ('HP' or 'class') mnemonics +.br + [\-reset perform a reset (PC = 0) on startup +.br + [\-initialize force initialization x48 from ROM-dump +.br + [\-rom if initializing, read ROM from +.br + [\-home use directory ~/ to save x48 files +.br + [\-xrm set Xresource +.br + [\-/+netbook Enable/Disable netbook look + + +.SH DESCRIPTION +.I x48 +is a scientific calculator desktop accessory that emulate an HP\-48 SX +or an HP\-48 GX. +.SH OPTIONS +.PP +\fIx48\fP accepts all of the standard toolkit command line options along +with several additional options: +.PP +.TP 8 +.B \-help +Show a list of options. +.PP +.TP 8 +.B \-version +This causes x48 to print a version number to the standard output. +.PP +.TP 8 +.B \-iconic +Start iconic +.SH OPERATION + +.PP +x48 emulates an HP 48 calculator. This manual does not attempt to +describe the operation of the HP calulator, but only the user interface +to the emulator. + +.I Pointer Usage: +When mouse button one is press on an x48 key the key is depress until +the mouse button is released. If you wish to have more than one key +press at a time mouse button 3 may be used. Button pressed with mouse +button 3 will remain pressed until mouse button 1 is used. For example +to reset the calulator you can press the A key and the F key with mouse +button 3 and then press the on button with mouse button 1. + +Mouse button 2 will paste the text in the cut buffer to the calculator +if it is press in the display area of the calculator. See notes on +pasting text into the calculator below. + +Use of mouse elsewhere on the image of the calculator is undefined. + +.SH ACCELERATORS + +The keyboard may be used to input data into the x48. +The number keys on the keyboard coresponds to the number buttons on +the calaculator, and the alphbetic keys on the keyboard control the +buttons on the top half of the calculator and the @code{+/-} and +@code{EXX} keys. + +The @code{ENTER} button is attached to the Enter key, the delete key +to the <-/DROP button and Divide, multiply, subtract and add buttons to +the /, *, -, and + keys on the key board. + +Note that only the DELETE key will auto repeat just like on the HP48 +calculator. + +.SH CUSTOMIZATION +.SH WIDGET HIERARCHY +.SH APPLICATION RESOURCES +The program understands all of the core X Toolkit resource names and +classes. Application specific resources (e.g., "\fBX48\fR.\fINAME\fR") follow: +.TP +.B .display: +Specifies the display to use. +.TP +.B *geometry: {+|-}x{+|-}y +You can not change the size of \fIx48\fR, but you can set the location of \fIx48\fR. +.TP +.B *iconGeom: + +.TP +.B *iconName: + +.TP +.B *iconic: + +.TP +.B *title: + +.TP +.B *useXShm: + +.TP +.B *visual: + +.TP +.B *mono: + +.TP +.B *gray: + +.TP +.B *monoIcon: + +.TP +.B *printVersion: + +.TP +.B *printCopyright: + +.TP +.B *printWarranty: + +.TP +.B *smallLabelFont: + +.TP +.B *mediumLabelFont: + +.TP +.B *largeLabelFont: + +.TP +.B *connectionFont: + +.TP +.B *verbose: + +.TP +.B *quiet: + +.TP +.B *useTerminal: + +.TP +.B *useSerial: + +.TP +.B *serialLine: + +.TP +.B *completeInitialize: + +.TP +.B *resetOnStartup: + +.TP +.B *romFileName: + +.TP +.B *homeDirectory: + +.TP +.B *useDebugger: + +.TP +.B *disassemblerMnemonics: + +.TP +.B *Netbook: + +.SH COLORS +The x48 is trying to look like a particular device. +The colors are therefore not selectable. +.br +.SH "ENVIRONMENT" +XUSERFILESEARCHPATH +.SH "SEE ALSO" +X(7x), xrdb(1) +.SH BUGS +.PP +Bugs can be found and reported at: http://developer.berlios.de/bugs/?group_id=3335 +.SH COPYRIGHT +Copyright \(co 1994-2005 Eddie C. Dost +.br +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +.SH AUTHORS +Eddie C. Dost +.br +G. Allen Morris III diff --git a/src/x48_x11.c b/src/x48_x11.c new file mode 100644 index 0000000..4a41af2 --- /dev/null +++ b/src/x48_x11.c @@ -0,0 +1,4468 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: x48_x11.c,v $ + * Revision 1.13 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.12 1994/12/08 22:17:24 ecd + * display and menu images now correctly drawn according to disp.lines + * + * Revision 1.11 1994/12/07 20:20:50 ecd + * better handling of resources + * + * Revision 1.10 1994/11/28 02:00:51 ecd + * implemented WM_SAVE_YOURSELF protocol. + * added support for mono and gray in color_t. + * added support for all possible Visualclasses. + * changed handling of KeyPress and KeyRelease. + * added color icon stuff. + * added support for contrast changes (ON_-, ON_+) + * read in all those Xresources before running off. + * use own icon window, no name-decor on icon. + * show state of x48 in the icon's display + * added support for setting the window title with the connections. + * + * Revision 1.9 1994/11/04 03:42:34 ecd + * changed includes + * + * Revision 1.8 1994/11/02 14:44:28 ecd + * works on machines that don't support backing store + * + * Revision 1.7 1994/10/09 20:32:02 ecd + * changed refresh_display to support bit offset. + * + * Revision 1.6 1994/10/06 16:30:05 ecd + * added XShm - Extension stuff + * + * Revision 1.5 1994/10/05 08:36:44 ecd + * added backing_store = Always for subwindows + * + * Revision 1.4 1994/09/30 12:37:09 ecd + * added support for interrupt detection in GetEvent, + * faster display updates, + * update display window only when mapped. + * + * Revision 1.3 1994/09/18 22:47:20 ecd + * added version information + * + * Revision 1.2 1994/09/18 15:29:22 ecd + * started Real Time support + * + * Revision 1.1 1994/09/13 15:05:05 ecd + * Initial revision + * + * $Id: x48_x11.c,v 1.13 1995/01/11 18:20:01 ecd Exp ecd $ + */ + + +#include "global.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SYSV +#include +#endif +#ifdef SUNOS +#include +#endif + +#include +#include +#include +#include + +#include "x48_x11.h" +#include "icon.h" +#include "small.h" +#include "buttons.h" +#include "hp.h" + +#include "hp48.h" +#include "device.h" +#include "constants.h" +#include "options.h" +#include "resources.h" +#include "errors.h" +#include "romio.h" + +static char *defaults[] = { +#include "X48.ad.h" + 0 +}; + +#ifdef HAVE_XSHM +extern int XShmQueryExtension __ProtoType__((Display *)); +extern int XShmGetEventBase __ProtoType__((Display *)); +static int CompletionType = -1; +#endif + +extern int saved_argc; +extern char **saved_argv; + +Display *dpy; +int screen; +unsigned int depth; +Colormap cmap; +GC gc; +Window mainW; +Window iconW = 0; +disp_t disp; +Atom wm_delete_window, wm_save_yourself, wm_protocols; +Atom ol_decor_del, ol_decor_icon_name; +Atom atom_type; +Visual *visual; +Pixmap icon_pix; +Pixmap icon_text_pix; +Pixmap icon_disp_pix; +static int last_icon_state = -1; + +#ifdef HAVE_XSHM +int shm_flag; +int xerror_flag; +#endif + +int dynamic_color; +int direct_color; +int does_backing_store; +int color_mode; +int icon_color_mode; + +#if 0 +# define DEBUG_XEVENT 1 +# define DEBUG_BUTTONS 1 +# define DEBUG_FOCUS 1 +# define DEBUG_BACKING_STORE 1 +# define DEBUG_SHM 1 +#endif + +typedef struct keypad_t { + unsigned int width; + unsigned int height; + Pixmap pixmap; +} keypad_t; + +keypad_t keypad; +color_t *colors; + +color_t colors_sx[] = { + { "white", 255, 255, 255, 255, 255, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "left", 255, 166, 0, 255, 230, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "right", 0, 210, 255, 255, 169, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "but_top", 109, 93, 93, 0, 91, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "button", 90, 77, 77, 0, 81, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "but_bot", 76, 65, 65, 0, 69, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "lcd_col", 202, 221, 92, 255, 205, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "pix_col", 0, 0, 128, 0, 20, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "pad_top", 109, 78, 78, 0, 88, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "pad", 90, 64, 64, 0, 73, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "pad_bot", 76, 54, 54, 0, 60, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "disp_pad_top", 155, 118, 84, 0, 124, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "disp_pad", 124, 94, 67, 0, 99, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "disp_pad_bot", 100, 75, 53, 0, 79, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "logo", 204, 169, 107, 255, 172, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "logo_back", 64, 64, 64, 0, 65, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "label", 202, 184, 144, 255, 185, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "frame", 0, 0, 0, 255, 0, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "underlay", 60, 42, 42, 0, 48, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "black", 0, 0, 0, 0, 0, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { 0 } +}; + +color_t colors_gx[] = { + { "white", 255, 255, 255, 255, 255, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "left", 255, 186, 255, 255, 220, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "right", 0, 255, 204, 255, 169, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "but_top", 104, 104, 104, 0, 104, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "button", 88, 88, 88, 0, 88, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "but_bot", 74, 74, 74, 0, 74, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "lcd_col", 202, 221, 92, 255, 205, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "pix_col", 0, 0, 128, 0, 20, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "pad_top", 88, 88, 88, 0, 88, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "pad", 74, 74, 74, 0, 74, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "pad_bot", 64, 64, 64, 0, 64, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "disp_pad_top", 128, 128, 138, 0, 128, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "disp_pad", 104, 104, 110, 0, 104, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "disp_pad_bot", 84, 84, 90, 0, 84, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "logo", 176, 176, 184, 255, 176, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "logo_back", 104, 104, 110, 0, 104, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "label", 240, 240, 240, 255, 240, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "frame", 0, 0, 0, 255, 0, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "underlay", 104, 104, 110, 0, 104, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { "black", 0, 0, 0, 0, 0, + { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } }, + { 0 } +}; + +typedef struct button_t { + + char *name; + short pressed; + short extra; + + int code; + int x, y; + unsigned int w, h; + + int lc; + char *label; + short font_size; + unsigned int lw, lh; + unsigned char *lb; + + char *letter; + + char *left; + short is_menu; + char *right; + char *sub; + + Pixmap map; + Pixmap down; + Window xwin; + +} button_t; + +#define BUTTON_A 0 +#define BUTTON_B 1 +#define BUTTON_C 2 +#define BUTTON_D 3 +#define BUTTON_E 4 +#define BUTTON_F 5 + +#define BUTTON_MTH 6 +#define BUTTON_PRG 7 +#define BUTTON_CST 8 +#define BUTTON_VAR 9 +#define BUTTON_UP 10 +#define BUTTON_NXT 11 + +#define BUTTON_COLON 12 +#define BUTTON_STO 13 +#define BUTTON_EVAL 14 +#define BUTTON_LEFT 15 +#define BUTTON_DOWN 16 +#define BUTTON_RIGHT 17 + +#define BUTTON_SIN 18 +#define BUTTON_COS 19 +#define BUTTON_TAN 20 +#define BUTTON_SQRT 21 +#define BUTTON_POWER 22 +#define BUTTON_INV 23 + +#define BUTTON_ENTER 24 +#define BUTTON_NEG 25 +#define BUTTON_EEX 26 +#define BUTTON_DEL 27 +#define BUTTON_BS 28 + +#define BUTTON_ALPHA 29 +#define BUTTON_7 30 +#define BUTTON_8 31 +#define BUTTON_9 32 +#define BUTTON_DIV 33 + +#define BUTTON_SHL 34 +#define BUTTON_4 35 +#define BUTTON_5 36 +#define BUTTON_6 37 +#define BUTTON_MUL 38 + +#define BUTTON_SHR 39 +#define BUTTON_1 40 +#define BUTTON_2 41 +#define BUTTON_3 42 +#define BUTTON_MINUS 43 + +#define BUTTON_ON 44 +#define BUTTON_0 45 +#define BUTTON_PERIOD 46 +#define BUTTON_SPC 47 +#define BUTTON_PLUS 48 + +#define LAST_BUTTON 48 + +button_t *buttons; + +button_t buttons_sx[] = { + { "A", 0, 0, 0x14, 0, 0, 36, 23, WHITE, + 0, 0, menu_label_width, menu_label_height, menu_label_bits, + "A", 0, 0, 0, 0, 0 }, + { "B", 0, 0, 0x84, 50, 0, 36, 23, WHITE, + 0, 0, menu_label_width, menu_label_height, menu_label_bits, + "B", 0, 0, 0, 0, 0 }, + { "C", 0, 0, 0x83, 100, 0, 36, 23, WHITE, + 0, 0, menu_label_width, menu_label_height, menu_label_bits, + "C", 0, 0, 0, 0, 0 }, + { "D", 0, 0, 0x82, 150, 0, 36, 23, WHITE, + 0, 0, menu_label_width, menu_label_height, menu_label_bits, + "D", 0, 0, 0, 0, 0 }, + { "E", 0, 0, 0x81, 200, 0, 36, 23, WHITE, + 0, 0, menu_label_width, menu_label_height, menu_label_bits, + "E", 0, 0, 0, 0, 0 }, + { "F", 0, 0, 0x80, 250, 0, 36, 23, WHITE, + 0, 0, menu_label_width, menu_label_height, menu_label_bits, + "F", 0, 0, 0, 0, 0 }, + + { "MTH", 0, 0, 0x24, 0, 50, 36, 26, WHITE, "MTH", 0, 0, 0, 0, + "G", "PRINT", 1, 0, 0, 0 }, + { "PRG", 0, 0, 0x74, 50, 50, 36, 26, WHITE, "PRG", 0, 0, 0, 0, + "H", "I/O", 1, 0, 0, 0 }, + { "CST", 0, 0, 0x73, 100, 50, 36, 26, WHITE, "CST", 0, 0, 0, 0, + "I", "MODES", 1, 0, 0, 0 }, + { "VAR", 0, 0, 0x72, 150, 50, 36, 26, WHITE, "VAR", 0, 0, 0, 0, + "J", "MEMORY", 1, 0, 0, 0 }, + { "UP", 0, 0, 0x71, 200, 50, 36, 26, WHITE, + 0, 0, up_width, up_height, up_bits, + "K", "LIBRARY", 1, 0, 0, 0 }, + { "NXT", 0, 0, 0x70, 250, 50, 36, 26, WHITE, "NXT", 0, 0, 0, 0, + "L", "PREV", 0, 0, 0, 0 }, + + { "COLON", 0, 0, 0x04, 0, 100, 36, 26, WHITE, + 0, 0, colon_width, colon_height, colon_bits, + "M", "UP", 0, "HOME", 0, 0 }, + { "STO", 0, 0, 0x64, 50, 100, 36, 26, WHITE, "STO", 0, 0, 0, 0, + "N", "DEF", 0, "RCL", 0, 0 }, + { "EVAL", 0, 0, 0x63, 100, 100, 36, 26, WHITE, "EVAL", 0, 0, 0, 0, + "O", "aQ", 0, "aNUM", 0, 0 }, + { "LEFT", 0, 0, 0x62, 150, 100, 36, 26, WHITE, + 0, 0, left_width, left_height, left_bits, + "P", "GRAPH", 0, 0, 0, 0 }, + { "DOWN", 0, 0, 0x61, 200, 100, 36, 26, WHITE, + 0, 0, down_width, down_height, down_bits, + "Q", "REVIEW", 0, 0, 0, 0 }, + { "RIGHT", 0, 0, 0x60, 250, 100, 36, 26, WHITE, + 0, 0, right_width, right_height, right_bits, + "R", "SWAP", 0, 0, 0, 0 }, + + { "SIN", 0, 0, 0x34, 0, 150, 36, 26, WHITE, "SIN", 0, 0, 0, 0, + "S", "ASIN", 0, "b", 0, 0 }, + { "COS", 0, 0, 0x54, 50, 150, 36, 26, WHITE, "COS", 0, 0, 0, 0, + "T", "ACOS", 0, "c", 0, 0 }, + { "TAN", 0, 0, 0x53, 100, 150, 36, 26, WHITE, "TAN", 0, 0, 0, 0, + "U", "ATAN", 0, "d", 0, 0 }, + { "SQRT", 0, 0, 0x52, 150, 150, 36, 26, WHITE, + 0, 0, sqrt_width, sqrt_height, sqrt_bits, + "V", "e", 0, "f", 0, 0 }, + { "POWER", 0, 0, 0x51, 200, 150, 36, 26, WHITE, + 0, 0, power_width, power_height, power_bits, + "W", "g", 0, "LOG", 0, 0 }, + { "INV", 0, 0, 0x50, 250, 150, 36, 26, WHITE, + 0, 0, inv_width, inv_height, inv_bits, + "X", "h", 0, "LN", 0, 0 }, + + { "ENTER", 0, 0, 0x44, 0, 200, 86, 26, WHITE, "ENTER", 2, 0, 0, 0, + 0, "EQUATION", 0, "MATRIX", 0, 0 }, + { "NEG", 0, 0, 0x43, 100, 200, 36, 26, WHITE, + 0, 0, neg_width, neg_height, neg_bits, + "Y", "EDIT", 0, "VISIT", 0, 0 }, + { "EEX", 0, 0, 0x42, 150, 200, 36, 26, WHITE, "EEX", 0, 0, 0, 0, + "Z", "2D", 0, "3D", 0, 0 }, + { "DEL", 0, 0, 0x41, 200, 200, 36, 26, WHITE, "DEL", 0, 0, 0, 0, + 0, "PURGE", 0, 0, 0, 0 }, + { "BS", 0, 0, 0x40, 250, 200, 36, 26, WHITE, + 0, 0, bs_width, bs_height, bs_bits, + 0, "DROP", 0, "CLR", 0, 0 }, + + { "ALPHA", 0, 0, 0x35, 0, 250, 36, 26, WHITE, + 0, 0, alpha_width, alpha_height, alpha_bits, + 0, "USR", 0, "ENTRY", 0, 0 }, + { "7", 0, 0, 0x33, 60, 250, 46, 26, WHITE, "7", 1, 0, 0, 0, + 0, "SOLVE", 1, 0, 0, 0 }, + { "8", 0, 0, 0x32, 120, 250, 46, 26, WHITE, "8", 1, 0, 0, 0, + 0, "PLOT", 1, 0, 0, 0 }, + { "9", 0, 0, 0x31, 180, 250, 46, 26, WHITE, "9", 1, 0, 0, 0, + 0, "ALGEBRA", 1, 0, 0, 0 }, + { "DIV", 0, 0, 0x30, 240, 250, 46, 26, WHITE, + 0, 0, div_width, div_height, div_bits, + 0, "( )", 0, "#", 0, 0 }, + + { "SHL", 0, 0, 0x25, 0, 300, 36, 26, LEFT, + 0, 0, shl_width, shl_height, shl_bits, + 0, 0, 0, 0, 0, 0 }, + { "4", 0, 0, 0x23, 60, 300, 46, 26, WHITE, "4", 1, 0, 0, 0, + 0, "TIME", 1, 0, 0, 0 }, + { "5", 0, 0, 0x22, 120, 300, 46, 26, WHITE, "5", 1, 0, 0, 0, + 0, "STAT", 1, 0, 0, 0 }, + { "6", 0, 0, 0x21, 180, 300, 46, 26, WHITE, "6", 1, 0, 0, 0, + 0, "UNITS", 1, 0, 0, 0 }, + { "MUL", 0, 0, 0x20, 240, 300, 46, 26, WHITE, + 0, 0, mul_width, mul_height, mul_bits, + 0, "[ ]", 0, "_", 0, 0 }, + + { "SHR", 0, 0, 0x15, 0, 350, 36, 26, RIGHT, + 0, 0, shr_width, shr_height, shr_bits, + 0, 0, 0, 0, 0, 0 }, + { "1", 0, 0, 0x13, 60, 350, 46, 26, WHITE, "1", 1, 0, 0, 0, + 0, "RAD", 0, "POLAR", 0, 0 }, + { "2", 0, 0, 0x12, 120, 350, 46, 26, WHITE, "2", 1, 0, 0, 0, + 0, "STACK", 0, "ARG", 0, 0 }, + { "3", 0, 0, 0x11, 180, 350, 46, 26, WHITE, "3", 1, 0, 0, 0, + 0, "CMD", 0, "MENU", 0, 0 }, + { "MINUS", 0, 0, 0x10, 240, 350, 46, 26, WHITE, + 0, 0, minus_width, minus_height, minus_bits, + 0, "i", 0, "j", 0, 0 }, + + { "ON", 0, 0, 0x8000, 0, 400, 36, 26, WHITE, "ON", 0, 0, 0, 0, + 0, "CONT", 0, "OFF", "ATTN", 0 }, + { "0", 0, 0, 0x03, 60, 400, 46, 26, WHITE, "0", 1, 0, 0, 0, + 0, "= ", 0, " a", 0, 0 }, + { "PERIOD", 0, 0, 0x02, 120, 400, 46, 26, WHITE, ".", 1, 0, 0, 0, + 0, ", ", 0, " k", 0, 0 }, + { "SPC", 0, 0, 0x01, 180, 400, 46, 26, WHITE, "SPC", 0, 0, 0, 0, + 0, "l ", 0, " m", 0, 0 }, + { "PLUS", 0, 0, 0x00, 240, 400, 46, 26, WHITE, + 0, 0, plus_width, plus_height, plus_bits, + 0, "{ }", 0, ": :", 0, 0 }, + + { 0 } +}; + +button_t buttons_gx[] = { + { "A", 0, 0, 0x14, 0, 0, 36, 23, WHITE, + 0, 0, menu_label_width, menu_label_height, menu_label_bits, + "A", 0, 0, 0, 0, 0 }, + { "B", 0, 0, 0x84, 50, 0, 36, 23, WHITE, + 0, 0, menu_label_width, menu_label_height, menu_label_bits, + "B", 0, 0, 0, 0, 0 }, + { "C", 0, 0, 0x83, 100, 0, 36, 23, WHITE, + 0, 0, menu_label_width, menu_label_height, menu_label_bits, + "C", 0, 0, 0, 0, 0 }, + { "D", 0, 0, 0x82, 150, 0, 36, 23, WHITE, + 0, 0, menu_label_width, menu_label_height, menu_label_bits, + "D", 0, 0, 0, 0, 0 }, + { "E", 0, 0, 0x81, 200, 0, 36, 23, WHITE, + 0, 0, menu_label_width, menu_label_height, menu_label_bits, + "E", 0, 0, 0, 0, 0 }, + { "F", 0, 0, 0x80, 250, 0, 36, 23, WHITE, + 0, 0, menu_label_width, menu_label_height, menu_label_bits, + "F", 0, 0, 0, 0, 0 }, + + { "MTH", 0, 0, 0x24, 0, 50, 36, 26, WHITE, "MTH", 0, 0, 0, 0, + "G", "RAD", 0, "POLAR", 0, 0 }, + { "PRG", 0, 0, 0x74, 50, 50, 36, 26, WHITE, "PRG", 0, 0, 0, 0, + "H", 0, 0, "CHARS", 0, 0 }, + { "CST", 0, 0, 0x73, 100, 50, 36, 26, WHITE, "CST", 0, 0, 0, 0, + "I", 0, 0, "MODES", 0, 0 }, + { "VAR", 0, 0, 0x72, 150, 50, 36, 26, WHITE, "VAR", 0, 0, 0, 0, + "J", 0, 0, "MEMORY", 0, 0 }, + { "UP", 0, 0, 0x71, 200, 50, 36, 26, WHITE, + 0, 0, up_width, up_height, up_bits, + "K", 0, 0, "STACK", 0, 0 }, + { "NXT", 0, 0, 0x70, 250, 50, 36, 26, WHITE, "NXT", 0, 0, 0, 0, + "L", "PREV", 0, "MENU", 0, 0 }, + + { "COLON", 0, 0, 0x04, 0, 100, 36, 26, WHITE, + 0, 0, colon_width, colon_height, colon_bits, + "M", "UP", 0, "HOME", 0, 0 }, + { "STO", 0, 0, 0x64, 50, 100, 36, 26, WHITE, "STO", 0, 0, 0, 0, + "N", "DEF", 0, "RCL", 0, 0 }, + { "EVAL", 0, 0, 0x63, 100, 100, 36, 26, WHITE, "EVAL", 0, 0, 0, 0, + "O", "aNUM", 0, "UNDO", 0, 0 }, + { "LEFT", 0, 0, 0x62, 150, 100, 36, 26, WHITE, + 0, 0, left_width, left_height, left_bits, + "P", "PICTURE", 0, 0, 0, 0 }, + { "DOWN", 0, 0, 0x61, 200, 100, 36, 26, WHITE, + 0, 0, down_width, down_height, down_bits, + "Q", "VIEW", 0, 0, 0, 0 }, + { "RIGHT", 0, 0, 0x60, 250, 100, 36, 26, WHITE, + 0, 0, right_width, right_height, right_bits, + "R", "SWAP", 0, 0, 0, 0 }, + + { "SIN", 0, 0, 0x34, 0, 150, 36, 26, WHITE, "SIN", 0, 0, 0, 0, + "S", "ASIN", 0, "b", 0, 0 }, + { "COS", 0, 0, 0x54, 50, 150, 36, 26, WHITE, "COS", 0, 0, 0, 0, + "T", "ACOS", 0, "c", 0, 0 }, + { "TAN", 0, 0, 0x53, 100, 150, 36, 26, WHITE, "TAN", 0, 0, 0, 0, + "U", "ATAN", 0, "d", 0, 0 }, + { "SQRT", 0, 0, 0x52, 150, 150, 36, 26, WHITE, + 0, 0, sqrt_width, sqrt_height, sqrt_bits, + "V", "n", 0, "o", 0, 0 }, + { "POWER", 0, 0, 0x51, 200, 150, 36, 26, WHITE, + 0, 0, power_width, power_height, power_bits, + "W", "p", 0, "LOG", 0, 0 }, + { "INV", 0, 0, 0x50, 250, 150, 36, 26, WHITE, + 0, 0, inv_width, inv_height, inv_bits, + "X", "q", 0, "LN", 0, 0 }, + + { "ENTER", 0, 0, 0x44, 0, 200, 86, 26, WHITE, "ENTER", 2, 0, 0, 0, + 0, "EQUATION", 0, "MATRIX", 0, 0 }, + { "NEG", 0, 0, 0x43, 100, 200, 36, 26, WHITE, + 0, 0, neg_width, neg_height, neg_bits, + "Y", "EDIT", 0, "CMD", 0, 0 }, + { "EEX", 0, 0, 0x42, 150, 200, 36, 26, WHITE, "EEX", 0, 0, 0, 0, + "Z", "PURG", 0, "ARG", 0, 0 }, + { "DEL", 0, 0, 0x41, 200, 200, 36, 26, WHITE, "DEL", 0, 0, 0, 0, + 0, "CLEAR", 0, 0, 0, 0 }, + { "BS", 0, 0, 0x40, 250, 200, 36, 26, WHITE, + 0, 0, bs_width, bs_height, bs_bits, + 0, "DROP", 0, 0, 0, 0 }, + + { "ALPHA", 0, 0, 0x35, 0, 250, 36, 26, WHITE, + 0, 0, alpha_width, alpha_height, alpha_bits, + 0, "USER", 0, "ENTRY", 0, 0 }, + { "7", 0, 0, 0x33, 60, 250, 46, 26, WHITE, "7", 1, 0, 0, 0, + 0, 0, 1, "SOLVE", 0, 0 }, + { "8", 0, 0, 0x32, 120, 250, 46, 26, WHITE, "8", 1, 0, 0, 0, + 0, 0, 1, "PLOT", 0, 0 }, + { "9", 0, 0, 0x31, 180, 250, 46, 26, WHITE, "9", 1, 0, 0, 0, + 0, 0, 1, "SYMBOLIC", 0, 0 }, + { "DIV", 0, 0, 0x30, 240, 250, 46, 26, WHITE, + 0, 0, div_width, div_height, div_bits, + 0, "r ", 0, "s", 0, 0 }, + + { "SHL", 0, 0, 0x25, 0, 300, 36, 26, LEFT, + 0, 0, shl_width, shl_height, shl_bits, + 0, 0, 0, 0, 0, 0 }, + { "4", 0, 0, 0x23, 60, 300, 46, 26, WHITE, "4", 1, 0, 0, 0, + 0, 0, 1, "TIME", 0, 0 }, + { "5", 0, 0, 0x22, 120, 300, 46, 26, WHITE, "5", 1, 0, 0, 0, + 0, 0, 1, "STAT", 0, 0 }, + { "6", 0, 0, 0x21, 180, 300, 46, 26, WHITE, "6", 1, 0, 0, 0, + 0, 0, 1, "UNITS", 0, 0 }, + { "MUL", 0, 0, 0x20, 240, 300, 46, 26, WHITE, + 0, 0, mul_width, mul_height, mul_bits, + 0, "t ", 0, "u", 0, 0 }, + + { "SHR", 0, 0, 0x15, 0, 350, 36, 26, RIGHT, + 0, 0, shr_width, shr_height, shr_bits, + 0, 0, 1, " ", 0, 0 }, + { "1", 0, 0, 0x13, 60, 350, 46, 26, WHITE, "1", 1, 0, 0, 0, + 0, 0, 1, "I/O", 0, 0 }, + { "2", 0, 0, 0x12, 120, 350, 46, 26, WHITE, "2", 1, 0, 0, 0, + 0, 0, 1, "LIBRARY", 0, 0 }, + { "3", 0, 0, 0x11, 180, 350, 46, 26, WHITE, "3", 1, 0, 0, 0, + 0, 0, 1, "EQ LIB", 0, 0 }, + { "MINUS", 0, 0, 0x10, 240, 350, 46, 26, WHITE, + 0, 0, minus_width, minus_height, minus_bits, + 0, "v ", 0, "w", 0, 0 }, + + { "ON", 0, 0, 0x8000, 0, 400, 36, 26, WHITE, "ON", 0, 0, 0, 0, + 0, "CONT", 0, "OFF", "CANCEL", 0 }, + { "0", 0, 0, 0x03, 60, 400, 46, 26, WHITE, "0", 1, 0, 0, 0, + 0, "\004 ", 0, "\003", 0, 0 }, + { "PERIOD", 0, 0, 0x02, 120, 400, 46, 26, WHITE, ".", 1, 0, 0, 0, + 0, "\002 ", 0, "\001", 0, 0 }, + { "SPC", 0, 0, 0x01, 180, 400, 46, 26, WHITE, "SPC", 0, 0, 0, 0, + 0, "\005 ", 0, "z", 0, 0 }, + { "PLUS", 0, 0, 0x00, 240, 400, 46, 26, WHITE, + 0, 0, plus_width, plus_height, plus_bits, + 0, "x ", 0, "y", 0, 0 }, + + { 0 } +}; + +typedef struct icon_t { + unsigned int w; + unsigned int h; + int c; + unsigned char *bits; +} icon_map_t; + +#define ICON_MAP 0 +#define ON_MAP 1 +#define DISP_MAP 2 +#define FIRST_MAP 3 +#define LAST_MAP 9 + +icon_map_t *icon_maps; + +icon_map_t icon_maps_sx[] = { + { hp48_icon_width, hp48_icon_height, BLACK, hp48_icon_bits }, + { hp48_on_width, hp48_on_height, PIXEL, hp48_on_bits }, + { hp48_disp_width, hp48_disp_height, LCD, hp48_disp_bits }, + { hp48_top_width, hp48_top_height, DISP_PAD, hp48_top_bits }, + { hp48_bottom_width, hp48_bottom_height, PAD, hp48_bottom_bits }, + { hp48_logo_width, hp48_logo_height, LOGO, hp48_logo_bits }, + { hp48_text_width, hp48_text_height, LABEL, hp48_text_bits }, + { hp48_keys_width, hp48_keys_height, BLACK, hp48_keys_bits }, + { hp48_orange_width, hp48_orange_height, LEFT, hp48_orange_bits }, + { hp48_blue_width, hp48_blue_height, RIGHT, hp48_blue_bits } +}; + +icon_map_t icon_maps_gx[] = { + { hp48_icon_width, hp48_icon_height, BLACK, hp48_icon_bits }, + { hp48_on_width, hp48_on_height, PIXEL, hp48_on_bits }, + { hp48_disp_width, hp48_disp_height, LCD, hp48_disp_bits }, + { hp48_top_gx_width, hp48_top_gx_height, DISP_PAD, hp48_top_gx_bits }, + { hp48_bottom_width, hp48_bottom_height, PAD, hp48_bottom_bits }, + { hp48_logo_gx_width, hp48_logo_gx_height, LOGO, hp48_logo_gx_bits }, + { hp48_text_gx_width, hp48_text_gx_height, LABEL, hp48_text_gx_bits }, + { hp48_keys_width, hp48_keys_height, BLACK, hp48_keys_bits }, + { hp48_orange_width, hp48_orange_height, LEFT, hp48_orange_bits }, + { hp48_green_gx_width, hp48_green_gx_height, RIGHT, hp48_green_gx_bits } +}; + +#define KEYBOARD_HEIGHT (buttons[LAST_BUTTON].y + buttons[LAST_BUTTON].h) +#define KEYBOARD_WIDTH (buttons[LAST_BUTTON].x + buttons[LAST_BUTTON].w) + +#define TOP_SKIP 65 +#define SIDE_SKIP 20 +#define BOTTOM_SKIP 25 +#define DISP_KBD_SKIP 65 + +#define DISPLAY_WIDTH (264 + 8) +#define DISPLAY_HEIGHT (128 + 16 + 8) +#define DISPLAY_OFFSET_X (SIDE_SKIP+(286-DISPLAY_WIDTH)/2) +#define DISPLAY_OFFSET_Y TOP_SKIP + +#define DISP_FRAME 8 + +#define KEYBOARD_OFFSET_X SIDE_SKIP +#define KEYBOARD_OFFSET_Y (TOP_SKIP + DISPLAY_HEIGHT + DISP_KBD_SKIP) + +int +#ifdef __FunctionProto__ +AllocColors(void) +#else +AllocColors() +#endif +{ + int c, error, dyn; + int r_shift = 0, g_shift = 0, b_shift = 0; + XSetWindowAttributes xswa; + + error = -1; + dyn = dynamic_color; + + if (direct_color) + { + while (!(visual->red_mask & (1 << r_shift))) + r_shift++; + while (visual->red_mask & (1 << r_shift)) + r_shift++; + r_shift = 16 - r_shift; + while (!(visual->green_mask & (1 << g_shift))) + g_shift++; + while ((visual->green_mask & (1 << g_shift))) + g_shift++; + g_shift = 16 - g_shift; + while (!(visual->blue_mask & (1 << b_shift))) + b_shift++; + while ((visual->blue_mask & (1 << b_shift))) + b_shift++; + b_shift = 16 - b_shift; + } + + for (c = WHITE; c <= BLACK; c++) { + switch (color_mode) + { + case COLOR_MODE_MONO: + colors[c].xcolor.red = colors[c].mono_rgb << 8; + colors[c].xcolor.green = colors[c].mono_rgb << 8; + colors[c].xcolor.blue = colors[c].mono_rgb << 8; + break; + case COLOR_MODE_GRAY: + colors[c].xcolor.red = colors[c].gray_rgb << 8; + colors[c].xcolor.green = colors[c].gray_rgb << 8; + colors[c].xcolor.blue = colors[c].gray_rgb << 8; + break; + default: + colors[c].xcolor.red = colors[c].r << 8; + colors[c].xcolor.green = colors[c].g << 8; + colors[c].xcolor.blue = colors[c].b << 8; + break; + } + if (direct_color) + { + colors[c].xcolor.pixel = + ((colors[c].xcolor.red >> r_shift) & visual->red_mask) | + ((colors[c].xcolor.green >> g_shift) & visual->green_mask) | + ((colors[c].xcolor.blue >> b_shift) & visual->blue_mask); + XStoreColor(dpy, cmap, &colors[c].xcolor); + } + else + { + if (dynamic_color && c == PIXEL) + { + if (XAllocColorCells(dpy, cmap, True, (unsigned long *)0, 0, + &colors[c].xcolor.pixel, 1) == 0) + { + dyn = 0; + if (XAllocColor(dpy, cmap, &colors[c].xcolor) == 0) + { + if (!quiet) + fprintf(stderr, "%s: XAllocColor failed.\n", progname); + error = c; + break; + } + } + else if (colors[c].xcolor.pixel >= visual->map_entries) + { + dyn = 0; + if (XAllocColor(dpy, cmap, &colors[c].xcolor) == 0) + { + if (!quiet) + fprintf(stderr, "%s: XAllocColor failed.\n", progname); + error = c; + break; + } + } + else + { + XStoreColor(dpy, cmap, &colors[c].xcolor); + } + } + else { + if (XAllocColor(dpy, cmap, &colors[c].xcolor) == 0) + { + if (!quiet) + fprintf(stderr, "%s: XAllocColor failed.\n", progname); + error = c; + break; + } + } + } + } + + /* + * Can't be reached when visual->class == DirectColor + */ + + if (error != -1) + { + if (!quiet) + fprintf(stderr, "%s: Using own Colormap.\n", progname); + /* + * free colors so far allocated + */ + for (c = WHITE; c < error; c++) + { + XFreeColors(dpy, cmap, &colors[c].xcolor.pixel, 1, 0); + } + + /* + * Create my own Colormap + */ + cmap = XCreateColormap(dpy, mainW, visual, AllocNone); + if (cmap == (Colormap)0) + { + sprintf(errbuf, "can\'t alloc Colormap.\n"); + fatal_exit(); + } + xswa.colormap = cmap; + XChangeWindowAttributes(dpy, mainW, CWColormap, &xswa); + if (iconW) + XChangeWindowAttributes(dpy, iconW, CWColormap, &xswa); + + /* + * Try to allocate colors again + */ + dyn = dynamic_color; + for (c = WHITE; c <= BLACK; c++) { + switch (color_mode) + { + case COLOR_MODE_MONO: + colors[c].xcolor.red = colors[c].mono_rgb << 8; + colors[c].xcolor.green = colors[c].mono_rgb << 8; + colors[c].xcolor.blue = colors[c].mono_rgb << 8; + break; + case COLOR_MODE_GRAY: + colors[c].xcolor.red = colors[c].gray_rgb << 8; + colors[c].xcolor.green = colors[c].gray_rgb << 8; + colors[c].xcolor.blue = colors[c].gray_rgb << 8; + break; + default: + colors[c].xcolor.red = colors[c].r << 8; + colors[c].xcolor.green = colors[c].g << 8; + colors[c].xcolor.blue = colors[c].b << 8; + break; + } + if (dynamic_color && c == PIXEL) { + if (XAllocColorCells(dpy, cmap, True, (unsigned long *)0, 0, + &colors[c].xcolor.pixel, 1) == 0) + { + dyn = 0; + if (XAllocColor(dpy, cmap, &colors[c].xcolor) == 0) + { + sprintf(errbuf, "can\'t alloc Color.\n"); + fatal_exit(); + } + } + else if (colors[c].xcolor.pixel >= visual->map_entries) + { + dyn = 0; + if (XAllocColor(dpy, cmap, &colors[c].xcolor) == 0) + { + sprintf(errbuf, "can\'t alloc Color.\n"); + fatal_exit(); + } + } + else + { + XStoreColor(dpy, cmap, &colors[c].xcolor); + } + } else { + if (XAllocColor(dpy, cmap, &colors[c].xcolor) == 0) + { + sprintf(errbuf, "can\'t alloc Color.\n"); + fatal_exit(); + } + } + } + } + + dynamic_color = dyn; + return 0; +} + +void +#ifdef __FunctionProto__ +adjust_contrast(int contrast) +#else +adjust_contrast(contrast) +int contrast; +#endif +{ + int gray = 0; + int r = 0, g = 0, b = 0; + unsigned long old; + + if (contrast < 0x3) contrast = 0x3; + if (contrast > 0x13) contrast = 0x13; + + old = colors[PIXEL].xcolor.pixel; + switch (color_mode) + { + case COLOR_MODE_MONO: + return; + case COLOR_MODE_GRAY: + gray = (0x13 - contrast) * (colors[LCD].gray_rgb / 0x10); + colors[PIXEL].xcolor.red = gray << 8; + colors[PIXEL].xcolor.green = gray << 8; + colors[PIXEL].xcolor.blue = gray << 8; + break; + default: + r = (0x13 - contrast) * (colors[LCD].r / 0x10); + g = (0x13 - contrast) * (colors[LCD].g / 0x10); + b = 128 - ((0x13 - contrast) * ((128 - colors[LCD].b) / 0x10)); + colors[PIXEL].xcolor.red = r << 8; + colors[PIXEL].xcolor.green = g << 8; + colors[PIXEL].xcolor.blue = b << 8; + break; + } + if (direct_color) + { + colors[PIXEL].gray_rgb = gray; + colors[PIXEL].r = r; + colors[PIXEL].g = g; + colors[PIXEL].b = b; + AllocColors(); + XSetForeground(dpy, disp.gc, COLOR(PIXEL)); +#ifdef HAVE_XSHM + disp.display_update = UPDATE_DISP | UPDATE_MENU; + refresh_display(); +#else + redraw_display(); +#endif + redraw_annunc(); + last_icon_state = -1; + refresh_icon(); + } + else if (dynamic_color) + { + XStoreColor(dpy, cmap, &colors[PIXEL].xcolor); + } + else + { + if (XAllocColor(dpy, cmap, &colors[PIXEL].xcolor) == 0) + { + colors[PIXEL].xcolor.pixel = old; + if (!quiet) + fprintf(stderr, "%s: warning: can\'t alloc new pixel color.\n", + progname); + } + else + { + XFreeColors(dpy, cmap, &old, 1, 0); + XSetForeground(dpy, disp.gc, COLOR(PIXEL)); +#ifdef HAVE_XSHM + disp.display_update = UPDATE_DISP | UPDATE_MENU; + refresh_display(); +#else + redraw_display(); +#endif + redraw_annunc(); + last_icon_state = -1; + refresh_icon(); + } + } +} + +int +#ifdef __FunctionProto__ +merge_app_defaults(char *path, XrmDatabase *db) +#else +merge_app_defaults(path, db) +char *path; +XrmDatabase *db; +#endif +{ + char file[1024]; + XrmDatabase tmp; + + if (path == (char *)0) + return 0; + + sprintf(file, "%s/%s", path, res_class); + + tmp = XrmGetFileDatabase(file); + if (tmp == (XrmDatabase)0) + return 0; + + XrmMergeDatabases(tmp, db); + + return 1; +} + +int +#ifdef __FunctionProto__ +InitDisplay(int argc, char **argv) +#else +InitDisplay(argc, argv) +int argc; +char **argv; +#endif +{ + XrmDatabase cmd = NULL, tmp = NULL; + char *res, *s; + char buf[1024], home[1024]; + int def, i; + struct passwd *pwd; +#ifdef SYSV + struct utsname uts; +#else + char hostname[128]; +#endif + + /* + * Parse the command line + */ + XrmInitialize(); + XrmParseCommand(&cmd, options, sizeof(options)/sizeof(*options), + progname, &argc, argv); + + if ((argc == 2) && !strcmp(argv[1], "-help")) + usage(); + else if (argc > 1) + { + fprintf(stderr, "%s: unknown option %s or missing argument\n", + progname, argv[1]); + usage(); + } + + res_name = progname; + res_class = strdup(res_name); + *res_class = islower(*res_class) ? _toupper(*res_class) : *res_class; + + /* + * look for argument -name + */ + res = get_string_resource_from_db(cmd, "name", "Name"); + if (res) + { + if (!(res_name = strdup(res))) + { + sprintf(errbuf, "out of memory in InitDisplay()\n"); + fatal_exit(); + } + + for (s = res_name; *s; s++) + *s = isupper(*s) ? _tolower(*s) : *s; + + free(res_class); + res_class = strdup(res_name); + *res_class = islower(*res_class) ? _toupper(*res_class) : *res_class; + + argc = saved_argc; + argv = (char **)malloc((argc + 1) * sizeof(char *)); + if (argv == (char **)0) + { + sprintf(errbuf, "out of memory in InitDisplay()\n"); + fatal_exit(); + } + argv[argc] = (char *)0; + for (i = 0; i < argc; i++) + argv[i] = saved_argv[i]; + + XrmParseCommand(&cmd, options, sizeof(options)/sizeof(*options), + res_name, &argc, argv); + } + + /* + * Open the display + */ + res = get_string_resource_from_db(cmd, "display", "Display"); + + dpy = XOpenDisplay(res); + if (dpy == (Display *)0) + { + if (res) + { + if (!quiet) + fprintf(stderr, "%s: can\'t open display %s\n", progname, res); + } + else + { + if (!quiet) + fprintf(stderr, "%s: can\'t open display\n", progname); + } + return -1; + } + + /* + * Load all those Resources. + * + * 1. Hardcoded Defaults + * + * 2. /usr/lib/X11/app-defaults/X48 + * + * 3. Values in $XUSERFILESEARCHPATH/X48 or, if not set, + * $XAPPLRESDIR/X48 + * + * 4. Values from XResourceManagerString() or, if empty, + * ~/.Xdefaults + * + * 5. Values in $XENVIRONMENT or, if not set, + * ~/.Xdefaults-hostname + * + * 6. Command line arguments + */ + + /* 1. Hardcoded Defaults */ + + for (def = 0; defaults[def]; def++) + { + if ((tmp = XrmGetStringDatabase(defaults[def]))) + XrmMergeDatabases(tmp, &rdb); + } + + /* 2. /usr/lib/X11/app-defaults/X48 */ + + merge_app_defaults("/usr/lib/X11/app-defaults", &rdb); + + /* 3. Values in $XUSERFILESEARCHPATH/X48, or $XAPPLRESDIR/X48 */ + + if (!merge_app_defaults(getenv("XUSERFILESEARCHPATH"), &rdb)) + merge_app_defaults(getenv("XAPPLRESDIR"), &rdb); + + /* 4. Values from XResourceManagerString() or ~/.Xdefaults */ + + res = XResourceManagerString(dpy); + if (res) + { + if ((tmp = XrmGetStringDatabase(res))) + XrmMergeDatabases(tmp, &rdb); + } + else + { + res = getenv("HOME"); + if (res) + strcpy(home, res); + else + { + pwd = getpwuid(getuid()); + if (pwd) + strcpy(home, pwd->pw_dir); + } + sprintf(buf, "%s/.Xdefaults", home); + if ((tmp = XrmGetFileDatabase(buf))) + XrmMergeDatabases(tmp, &rdb); + } + + /* 5. Values in $XENVIRONMENT or ~/.Xdefaults-hostname */ + + res = getenv("XENVIRONMENT"); + if (res) + { + if ((tmp = XrmGetFileDatabase(res))) + XrmMergeDatabases(tmp, &rdb); + } + else + { + res = getenv("HOME"); + if (res) + strcpy(home, res); + else + { + pwd = getpwuid(getuid()); + if (pwd) + strcpy(home, pwd->pw_dir); + } + tmp = (XrmDatabase)0; +#ifdef SYSV + if (uname(&uts) >= 0) + { + sprintf(buf, "%s/.Xdefaults-%s", home, uts.nodename); + tmp = XrmGetFileDatabase(buf); + } +#else + if (gethostname(hostname, 128) >= 0) + { + sprintf(buf, "%s/.Xdefaults-%s", home, hostname); + tmp = XrmGetFileDatabase(buf); + } +#endif + if (tmp) + XrmMergeDatabases(tmp, &rdb); + } + + /* 6. Command line arguments */ + + if (cmd) + XrmMergeDatabases(cmd, &rdb); + + get_resources(); + + /* + * Get the default screen + */ + screen = DefaultScreen(dpy); + + /* + * Does the Xserver do backing-store? + */ + does_backing_store = XDoesBackingStore(XScreenOfDisplay(dpy, screen)); +#ifdef DEBUG_BACKING_STORE + fprintf(stderr, "XServer does%sBackingStore\n", + does_backing_store ? " " : " not do "); +#endif + +#ifdef HAVE_XSHM + /* + * Try to use XShm-Extension + */ + shm_flag = useXShm; + + if (!XShmQueryExtension(dpy)) { + shm_flag = 0; + if (!quiet) + fprintf(stderr, "%s: Xserver does not support XShm extension.\n", + progname); + } + if (shm_flag) + fprintf(stderr, "%s: using XShm extension.\n", progname); +#else + if (useXShm) + { + if (!quiet) + fprintf(stderr, "%s: not compiled to use XShm extension.\n", + progname); + } +#endif + + return 0; +} + +int +#ifdef __FunctionProto__ +SmallTextWidth(const char *string, unsigned int length) +#else +SmallTextWidth(string, length) +const char *string; +unsigned int length; +#endif +{ + int i, w; + + w = 0; + for (i = 0; i < length; i++) { + if (small_font[(int)string[i]].h != 0) { + w += small_font[(int)string[i]].w + 1; + } else { + if (!quiet) + fprintf(stderr, "Unknown small letter 0x00%x\n", (int)string[i]); + w += 5; + } + } + return w; +} + +int +#ifdef __FunctionProto__ +DrawSmallString(Display *the_dpy, Drawable d, GC the_gc, + int x, int y, const char *string, unsigned int length) +#else +DrawSmallString(the_dpy, d, the_gc, x, y, string, length) +Display *the_dpy; +Drawable d; +GC the_gc; +int x; +int y; +const char *string; +unsigned int length; +#endif +{ + int i; + Pixmap pix; + + for (i = 0; i < length; i++) { + if (small_font[(int)string[i]].h != 0) { + pix = XCreateBitmapFromData(the_dpy, d, + (char *)small_font[(int)string[i]].bits, + small_font[(int)string[i]].w, small_font[(int)string[i]].h); + XCopyPlane(the_dpy, pix, d, the_gc, 0, 0, small_font[(int)string[i]].w, + small_font[(int)string[i]].h, x, + (int)(y - small_font[(int)string[i]].h), 1); + XFreePixmap(the_dpy, pix); + } + x += SmallTextWidth(&string[i], 1); + } + return 0; +} + +#include + +void +#ifdef __FunctionProto__ +CreateButton(int i, int off_x, int off_y, XFontStruct *f_small, XFontStruct *f_med, XFontStruct *f_big ) +#else +CreateButton(i, off_x, off_y, f_small, f_med, f_big ) +int i, off_x, off_y; +XFontStruct *f_small, *f_med, *f_big; +#endif +{ + int x, y; + XSetWindowAttributes xswa; + XFontStruct *finfo; + XGCValues val; + unsigned long gc_mask; + Pixmap pix; + XCharStruct xchar; + int dir, fa, fd; + unsigned long pixel; + + { + if (i < BUTTON_MTH) + pixel = COLOR(DISP_PAD); + else + { + if (opt_gx && buttons[i].is_menu) + pixel = COLOR(UNDERLAY); + else + pixel = COLOR(PAD); + } + + /* + * create the buttons subwindows + */ + buttons[i].xwin = XCreateSimpleWindow(dpy, mainW, + off_x + buttons[i].x, + off_y + buttons[i].y, + buttons[i].w, buttons[i].h, 0, + COLOR(BLACK), pixel); + + XDefineCursor(dpy, buttons[i].xwin, XCreateFontCursor(dpy, XC_hand1)); + + xswa.event_mask = LeaveWindowMask | ExposureMask | StructureNotifyMask; + xswa.backing_store = Always; + + XChangeWindowAttributes(dpy, buttons[i].xwin, + CWEventMask|CWBackingStore, &xswa); + + /* + * draw the released button + */ + buttons[i].map = XCreatePixmap(dpy, buttons[i].xwin, buttons[i].w, + buttons[i].h, depth); + + XSetForeground(dpy, gc, pixel); + XFillRectangle(dpy, buttons[i].map, gc, 0, 0, buttons[i].w, + buttons[i].h); + + XSetForeground(dpy, gc, COLOR(BUTTON)); + XFillRectangle(dpy, buttons[i].map, gc, 1, 1, buttons[i].w - 2, + buttons[i].h - 2); + + if (buttons[i].label != (char *)0) { + + /* + * set font size in gc + */ + switch (buttons[i].font_size) { + case 0: + finfo = f_small; + break; + case 1: + finfo = f_big; + break; + case 2: + finfo = f_med; + break; + default: + finfo = f_small; + break; + } + val.font = finfo->fid; + gc_mask = GCFont; + XChangeGC(dpy, gc, gc_mask, &val); + + /* + * draw string centered in button + */ + XSetBackground(dpy, gc, COLOR(BUTTON)); + XSetForeground(dpy, gc, COLOR(buttons[i].lc)); + + XTextExtents(finfo, buttons[i].label, (int)strlen(buttons[i].label), + &dir, &fa, &fd, &xchar); + x = (buttons[i].w - xchar.width) / 2; + y = (1 + buttons[i].h - + (xchar.ascent + xchar.descent)) / 2 + xchar.ascent + 1; + XDrawImageString(dpy, buttons[i].map, gc, x, y, + buttons[i].label, (int)strlen(buttons[i].label)); + + XSetBackground(dpy, gc, COLOR(BLACK)); + + } else if (buttons[i].lw != 0) { + + /* + * draw pixmap centered in button + */ + XSetBackground(dpy, gc, COLOR(BUTTON)); + XSetForeground(dpy, gc, COLOR(buttons[i].lc)); + + pix = XCreateBitmapFromData(dpy, buttons[i].xwin, (char *)buttons[i].lb, + buttons[i].lw, buttons[i].lh); + + x = (1 + buttons[i].w - buttons[i].lw) / 2; + y = (1 + buttons[i].h - buttons[i].lh) / 2 + 1; + + XCopyPlane(dpy, pix, buttons[i].map, gc, 0, 0, buttons[i].lw, + buttons[i].lh, x, y, 1); + + XFreePixmap(dpy, pix); + + XSetBackground(dpy, gc, COLOR(BLACK)); + + } + + /* + * draw edge of button + */ + XSetForeground(dpy, gc, COLOR(BUT_TOP)); + + XDrawLine(dpy, buttons[i].map, gc, 1, (int)(buttons[i].h - 2), 1, 1); + XDrawLine(dpy, buttons[i].map, gc, 2, (int)(buttons[i].h - 3), 2, 2); + XDrawLine(dpy, buttons[i].map, gc, 3, (int)(buttons[i].h - 4), 3, 3); + + XDrawLine(dpy, buttons[i].map, gc, 1, 1, (int)(buttons[i].w - 2), 1); + XDrawLine(dpy, buttons[i].map, gc, 2, 2, (int)(buttons[i].w - 3), 2); + XDrawLine(dpy, buttons[i].map, gc, 3, 3, (int)(buttons[i].w - 4), 3); + XDrawLine(dpy, buttons[i].map, gc, 4, 4, (int)(buttons[i].w - 5), 4); + + XDrawPoint(dpy, buttons[i].map, gc, 4, 5); + + XSetForeground(dpy, gc, COLOR(BUT_BOT)); + + XDrawLine(dpy, buttons[i].map, gc, 3, (int)(buttons[i].h - 2), + (int)(buttons[i].w - 2), (int)(buttons[i].h - 2)); + XDrawLine(dpy, buttons[i].map, gc, 4, (int)(buttons[i].h - 3), + (int)(buttons[i].w - 3), (int)(buttons[i].h - 3)); + + XDrawLine(dpy, buttons[i].map, gc, (int)(buttons[i].w - 2), + (int)(buttons[i].h - 2), (int)(buttons[i].w - 2), 3); + XDrawLine(dpy, buttons[i].map, gc, (int)(buttons[i].w - 3), + (int)(buttons[i].h - 3), (int)(buttons[i].w - 3), 4); + XDrawLine(dpy, buttons[i].map, gc, (int)(buttons[i].w - 4), + (int)(buttons[i].h - 4), (int)(buttons[i].w - 4), 5); + + XDrawPoint(dpy, buttons[i].map, gc, (int)(buttons[i].w - 5), + (int)(buttons[i].h - 4)); + + /* + * draw frame around button + */ + XSetForeground(dpy, gc, COLOR(FRAME)); + + XDrawLine(dpy, buttons[i].map, gc, 0, (int)(buttons[i].h - 3), 0, 2); + XDrawLine(dpy, buttons[i].map, gc, 2, 0, (int)(buttons[i].w - 3), 0); + XDrawLine(dpy, buttons[i].map, gc, 2, (int)(buttons[i].h - 1), + (int)(buttons[i].w - 3), (int)(buttons[i].h - 1)); + XDrawLine(dpy, buttons[i].map, gc, (int)(buttons[i].w - 1), + (int)(buttons[i].h - 3), (int)(buttons[i].w - 1), 2); + + if (i == BUTTON_ON) + { + XDrawLine(dpy, buttons[i].map, gc, 1, 1, (int)(buttons[i].w - 2), 1); + XDrawPoint(dpy, buttons[i].map, gc, 1, 2); + XDrawPoint(dpy, buttons[i].map, gc, (int)(buttons[i].w - 2), 2); + } + else + { + XDrawPoint(dpy, buttons[i].map, gc, 1, 1); + XDrawPoint(dpy, buttons[i].map, gc, (int)(buttons[i].w - 2), 1); + } + XDrawPoint(dpy, buttons[i].map, gc, 1, (int)(buttons[i].h - 2)); + XDrawPoint(dpy, buttons[i].map, gc, (int)(buttons[i].w - 2), + (int)(buttons[i].h - 2)); + + /* + * draw the depressed button + */ + buttons[i].down = XCreatePixmap(dpy, buttons[i].xwin, buttons[i].w, + buttons[i].h, depth); + + XSetForeground(dpy, gc, pixel); + XFillRectangle(dpy, buttons[i].down, gc, 0, 0, buttons[i].w, + buttons[i].h); + + XSetForeground(dpy, gc, COLOR(BUTTON)); + XFillRectangle(dpy, buttons[i].down, gc, 1, 1, buttons[i].w - 2, + buttons[i].h - 2); + + if (buttons[i].label != (char *)0) { + + /* + * set small or big font in gc + */ + switch (buttons[i].font_size) { + case 0: + finfo = f_small; + break; + case 1: + finfo = f_big; + break; + case 2: + finfo = f_med; + break; + default: + finfo = f_small; + break; + } + val.font = finfo->fid; + gc_mask = GCFont; + XChangeGC(dpy, gc, gc_mask, &val); + + /* + * draw string centered in button + */ + XSetBackground(dpy, gc, COLOR(BUTTON)); + XSetForeground(dpy, gc, COLOR(buttons[i].lc)); + + XTextExtents(finfo, buttons[i].label, (int)strlen(buttons[i].label), + &dir, &fa, &fd, &xchar); + x = (buttons[i].w - xchar.width) / 2; + y = (1 + buttons[i].h - + (xchar.ascent + xchar.descent)) / 2 + xchar.ascent; + XDrawImageString(dpy, buttons[i].down, gc, x, y, + buttons[i].label, (int)strlen(buttons[i].label)); + + XSetBackground(dpy, gc, COLOR(BLACK)); + + } else { + + /* + * draw pixmap centered in button + */ + XSetBackground(dpy, gc, COLOR(BUTTON)); + XSetForeground(dpy, gc, COLOR(buttons[i].lc)); + + pix = XCreateBitmapFromData(dpy, buttons[i].xwin, (char *)buttons[i].lb, + buttons[i].lw, buttons[i].lh); + + x = (1 + buttons[i].w - buttons[i].lw) / 2; + y = (1 + buttons[i].h - buttons[i].lh) / 2; + + XCopyPlane(dpy, pix, buttons[i].down, gc, 0, 0, buttons[i].lw, + buttons[i].lh, x, y, 1); + + XFreePixmap(dpy, pix); + + XSetBackground(dpy, gc, COLOR(BLACK)); + + } + + /* + * draw edge of button + */ + XSetForeground(dpy, gc, COLOR(BUT_TOP)); + + XDrawLine(dpy, buttons[i].down, gc, 2, (int)(buttons[i].h - 4), 2, 2); + XDrawLine(dpy, buttons[i].down, gc, 3, (int)(buttons[i].h - 5), 3, 3); + + XDrawLine(dpy, buttons[i].down, gc, 2, 2, (int)(buttons[i].w - 4), 2); + XDrawLine(dpy, buttons[i].down, gc, 3, 3, (int)(buttons[i].w - 5), 3); + + XDrawPoint(dpy, buttons[i].down, gc, 4, 4); + + XSetForeground(dpy, gc, COLOR(BUT_BOT)); + + XDrawLine(dpy, buttons[i].down, gc, 3, (int)(buttons[i].h - 3), + (int)(buttons[i].w - 3), (int)(buttons[i].h - 3)); + XDrawLine(dpy, buttons[i].down, gc, 4, (int)(buttons[i].h - 4), + (int)(buttons[i].w - 4), (int)(buttons[i].h - 4)); + + XDrawLine(dpy, buttons[i].down, gc, (int)(buttons[i].w - 3), + (int)(buttons[i].h - 3), (int)(buttons[i].w - 3), 3); + XDrawLine(dpy, buttons[i].down, gc, (int)(buttons[i].w - 4), + (int)(buttons[i].h - 4), (int)(buttons[i].w - 4), 4); + + XDrawPoint(dpy, buttons[i].down, gc, (int)(buttons[i].w - 5), + (int)(buttons[i].h - 5)); + + /* + * draw frame around button + */ + XSetForeground(dpy, gc, COLOR(FRAME)); + + XDrawLine(dpy, buttons[i].down, gc, 0, (int)(buttons[i].h - 3), 0, 2); + XDrawLine(dpy, buttons[i].down, gc, 2, 0, (int)(buttons[i].w - 3), 0); + XDrawLine(dpy, buttons[i].down, gc, 2, (int)(buttons[i].h - 1), + (int)(buttons[i].w - 3), (int)(buttons[i].h - 1)); + XDrawLine(dpy, buttons[i].down, gc, (int)(buttons[i].w - 1), + (int)(buttons[i].h - 3), (int)(buttons[i].w - 1), 2); + + if (i == BUTTON_ON) + { + XDrawLine(dpy, buttons[i].down, gc, 1, 1, (int)(buttons[i].w - 2), 1); + XDrawPoint(dpy, buttons[i].down, gc, 1, 2); + XDrawPoint(dpy, buttons[i].down, gc, (int)(buttons[i].w - 2), 2); + } + else + { + XDrawPoint(dpy, buttons[i].down, gc, 1, 1); + XDrawPoint(dpy, buttons[i].down, gc, (int)(buttons[i].w - 2), 1); + } + XDrawPoint(dpy, buttons[i].down, gc, 1, (int)(buttons[i].h - 2)); + XDrawPoint(dpy, buttons[i].down, gc, (int)(buttons[i].w - 2), + (int)(buttons[i].h - 2)); + + if (i == BUTTON_ON) + { + XDrawRectangle(dpy, buttons[i].down, gc, 1, 2, buttons[i].w - 3, + buttons[i].h - 4); + XDrawPoint(dpy, buttons[i].down, gc, 2, 3); + XDrawPoint(dpy, buttons[i].down, gc, (int)(buttons[i].w - 3), 3); + } + else + { + XDrawRectangle(dpy, buttons[i].down, gc, 1, 1, buttons[i].w - 3, + buttons[i].h - 3); + XDrawPoint(dpy, buttons[i].down, gc, 2, 2); + XDrawPoint(dpy, buttons[i].down, gc, (int)(buttons[i].w - 3), 2); + } + XDrawPoint(dpy, buttons[i].down, gc, 2, (int)(buttons[i].h - 3)); + XDrawPoint(dpy, buttons[i].down, gc, (int)(buttons[i].w - 3), + (int)(buttons[i].h - 3)); + + } + + return; +} + +void +#ifdef __FunctionProto__ +DrawButtons(void) +#else +DrawButtons() +#endif +{ + int i; + + for (i = BUTTON_A; i <= LAST_BUTTON; i++) { + if (buttons[i].pressed) { + XCopyArea(dpy, buttons[i].down, buttons[i].xwin, gc, 0, 0, buttons[i].w, + buttons[i].h, 0, 0); + } else { + XCopyArea(dpy, buttons[i].map, buttons[i].xwin, gc, 0, 0, buttons[i].w, + buttons[i].h, 0, 0); + } + } + return; +} + +int +#ifdef __FunctionProto__ +DrawButton(int i) +#else +DrawButton(i) +int i; +#endif +{ + if (buttons[i].pressed) { + XCopyArea(dpy, buttons[i].down, buttons[i].xwin, gc, 0, 0, buttons[i].w, + buttons[i].h, 0, 0); + } else { + XCopyArea(dpy, buttons[i].map, buttons[i].xwin, gc, 0, 0, buttons[i].w, + buttons[i].h, 0, 0); + } + return 0; +} + +void CreateBackground(int width, int height, int w_top, int h_top, keypad_t *keypad) +{ + XSetBackground(dpy, gc, COLOR(PAD)); + XSetForeground(dpy, gc, COLOR(PAD)); + + XFillRectangle(dpy, keypad->pixmap, gc, 0, 0, w_top, h_top); + + XSetBackground(dpy, gc, COLOR(DISP_PAD)); + XSetForeground(dpy, gc, COLOR(DISP_PAD)); + + XFillRectangle(dpy, keypad->pixmap, gc, 0, 0, width, height); + + return; +} + +void +#ifdef __FunctionProto__ +CreateKeypad(unsigned int w, unsigned int h, unsigned int offset_y, unsigned int offset_x, keypad_t *keypad) +#else +CreateKeypad(w, h, offset_y, offset_x) +unsigned int w; +unsigned int h; +unsigned int offset_y; +unsigned int offset_x; +keypad_t *keypad; +#endif +{ + int i, x, y; + int wl, wr, ws; + Pixmap pix; + unsigned long pixel; + unsigned int pw, ph; + XFontStruct *f_small, *f_med, *f_big; + + + f_small = get_font_resource(dpy, "smallLabelFont", "SmallLabelFont"); + f_med = get_font_resource(dpy, "mediumLabelFont", "MediumLabelFont"); + f_big = get_font_resource(dpy, "largeLabelFont", "LargeLabelFont"); + + /* + * draw the character labels + */ + for (i = BUTTON_A; i <= LAST_BUTTON; i++) { + + CreateButton(i, offset_x, offset_y, f_small, f_med, f_big); + + if (i < BUTTON_MTH) + pixel = COLOR(DISP_PAD); + else + pixel = COLOR(PAD); + + if (buttons[i].letter != (char *)0) { + + XSetBackground(dpy, gc, pixel); + XSetForeground(dpy, gc, COLOR(WHITE)); + + if (opt_gx) + { + x = offset_x + buttons[i].x + buttons[i].w + 3; + y = offset_y + buttons[i].y + buttons[i].h + 1; + } + else + { + x = offset_x + buttons[i].x + buttons[i].w - + SmallTextWidth(buttons[i].letter, 1) / 2 + 5; + y = offset_y + buttons[i].y + buttons[i].h - 2; + } + + DrawSmallString(dpy, keypad->pixmap, gc, x, y, + buttons[i].letter, 1); + } + } + + XFreeFont(dpy, f_big); + XFreeFont(dpy, f_med); + XFreeFont(dpy, f_small); + + /* + * draw the bottom labels + */ + for (i = BUTTON_A; i <= LAST_BUTTON; i++) { + + if (buttons[i].sub != (char *)0) { + + XSetBackground(dpy, gc, pixel); + XSetForeground(dpy, gc, COLOR(WHITE)); + + x = offset_x + buttons[i].x + (1 + buttons[i].w - + SmallTextWidth(buttons[i].sub, strlen(buttons[i].sub))) / 2; + y = offset_y + buttons[i].y + buttons[i].h + small_ascent + 2; + + DrawSmallString(dpy, keypad->pixmap, gc, x, y, + buttons[i].sub, strlen(buttons[i].sub)); + } + } + + /* + * draw the left labels + */ + for (i = BUTTON_A; i <= LAST_BUTTON; i++) { + + if (buttons[i].left != (char *)0) { + + if (buttons[i].is_menu) { + + /* + * draw the dark shade under the label + */ + if (opt_gx) + { + pw = 58; + ph = 48; + } + else + { + pw = 46; + ph = 11; + } + + pix = XCreatePixmap(dpy, keypad->pixmap, pw, ph, depth); + + XSetForeground(dpy, gc, COLOR(UNDERLAY)); + + XFillRectangle(dpy, pix, gc, 0, 0, pw, ph); + + XSetBackground(dpy, gc, COLOR(UNDERLAY)); + XSetForeground(dpy, gc, COLOR(LEFT)); + + x = (pw + 1 - SmallTextWidth(buttons[i].left, + strlen(buttons[i].left))) / 2; + if (opt_gx) + y = 14; + else + y = 9; + + DrawSmallString(dpy, pix, gc, x, y, + buttons[i].left, strlen(buttons[i].left)); + + XSetForeground(dpy, gc, pixel); + + if (!opt_gx) + { + XDrawPoint(dpy, pix, gc, 0, 0); + XDrawPoint(dpy, pix, gc, 0, ph - 1); + XDrawPoint(dpy, pix, gc, pw - 1, 0); + XDrawPoint(dpy, pix, gc, pw - 1, ph - 1); + } + + if (opt_gx) + { + x = offset_x + buttons[i].x - 6; + y = offset_y + buttons[i].y + - small_ascent - small_descent - 6; + } + else + { + x = offset_x + buttons[i].x + (buttons[i].w - pw) / 2; + y = offset_y + buttons[i].y + - small_ascent - small_descent; + } + + XCopyArea(dpy, pix, keypad->pixmap, gc, 0, 0, pw, ph, x, y); + + XFreePixmap(dpy, pix); + + } else { + + XSetBackground(dpy, gc, pixel); + XSetForeground(dpy, gc, COLOR(LEFT)); + + if (buttons[i].right == (char *)0) { /* centered label */ + + x = offset_x + buttons[i].x + (1 + buttons[i].w - + SmallTextWidth(buttons[i].left, + strlen(buttons[i].left))) / 2; + + } else { /* label to the left */ + + wl = SmallTextWidth(buttons[i].left, strlen(buttons[i].left)); + wr = SmallTextWidth(buttons[i].right, strlen(buttons[i].right)); + ws = SmallTextWidth(" ", 1); + + x = offset_x + buttons[i].x + (1 + buttons[i].w - + (wl + wr + ws)) / 2; + + } + + y = offset_y + buttons[i].y - small_descent; + + DrawSmallString(dpy, keypad->pixmap, gc, x, y, + buttons[i].left, strlen(buttons[i].left)); + } + } + } + + /* + * draw the right labels + */ + for (i = BUTTON_A; i <= LAST_BUTTON; i++) { + + if (i < BUTTON_MTH) + pixel = COLOR(DISP_PAD); + else + pixel = COLOR(PAD); + + if (buttons[i].right != (char *)0) { + + if (buttons[i].is_menu) { + + /* + * draw the dark shade under the label + */ + if (opt_gx) + { + pw = 58; + ph = 48; + } + else + { + pw = 44; + ph = 9; + } + + pix = XCreatePixmap(dpy, keypad->pixmap, pw, ph, depth); + + XSetForeground(dpy, gc, COLOR(UNDERLAY)); + + XFillRectangle(dpy, pix, gc, 0, 0, pw, ph); + + XSetBackground(dpy, gc, COLOR(UNDERLAY)); + XSetForeground(dpy, gc, COLOR(RIGHT)); + + x = (pw + 1 - SmallTextWidth(buttons[i].right, + strlen(buttons[i].right))) / 2; + if (opt_gx) + y = 14; + else + y = 8; + + DrawSmallString(dpy, pix, gc, x, y, + buttons[i].right, strlen(buttons[i].right)); + + XSetForeground(dpy, gc, pixel); + + if (!opt_gx) + { + XDrawPoint(dpy, pix, gc, 0, 0); + XDrawPoint(dpy, pix, gc, 0, ph - 1); + XDrawPoint(dpy, pix, gc, pw - 1, 0); + XDrawPoint(dpy, pix, gc, pw - 1, ph - 1); + } + + if (opt_gx) + { + x = offset_x + buttons[i].x - 6; + y = offset_y + buttons[i].y + - small_ascent - small_descent - 6; + } + else + { + x = offset_x + buttons[i].x + (buttons[i].w - pw) / 2; + y = offset_y + buttons[i].y + - small_ascent - small_descent; + } + + XCopyArea(dpy, pix, keypad->pixmap, gc, 0, 0, pw, ph, x, y); + + XFreePixmap(dpy, pix); + + } else { + + XSetBackground(dpy, gc, pixel); + XSetForeground(dpy, gc, COLOR(RIGHT)); + + if (buttons[i].left == (char *)0) { /* centered label */ + + x = offset_x + buttons[i].x + (1 + buttons[i].w - + SmallTextWidth(buttons[i].right, + strlen(buttons[i].right))) / 2; + + } else { /* label to the right */ + + wl = SmallTextWidth(buttons[i].left, strlen(buttons[i].left)); + wr = SmallTextWidth(buttons[i].right, strlen(buttons[i].right)); + ws = SmallTextWidth(" ", 1); + + x = offset_x + buttons[i].x + (1 + buttons[i].w - + (wl + wr + ws)) / 2 + wl + ws; + + } + + y = offset_y + buttons[i].y - small_descent; + + DrawSmallString(dpy, keypad->pixmap, gc, x, y, + buttons[i].right, strlen(buttons[i].right)); + } + } + } + + /* + * at last draw the v--- LAST ---v thing + */ + + if (!opt_gx) + { + XSetBackground(dpy, gc, COLOR(PAD)); + XSetForeground(dpy, gc, COLOR(WHITE)); + + pix = XCreateBitmapFromData(dpy, keypad->pixmap, (char *)last_bits, + last_width, last_height); + + x = offset_x + buttons[BUTTON_1].x + buttons[BUTTON_1].w + + (buttons[BUTTON_2].x - buttons[BUTTON_1].x - buttons[BUTTON_1].w) / 2; + y = offset_y + buttons[BUTTON_5].y + buttons[BUTTON_5].h + 2; + + XCopyPlane(dpy, pix, keypad->pixmap, gc, 0, 0, last_width, last_height, + x, y, 1); + + XFreePixmap(dpy, pix); + } + + return; +} + +void +CreateBezel(unsigned int width, unsigned int height, unsigned int offset_y, unsigned int offset_x, keypad_t *keypad) +{ + int i, x, y; + Pixmap pix; + int display_height = DISPLAY_HEIGHT; + int display_width = DISPLAY_WIDTH; + + /* + * draw the frame around the display + */ + XSetForeground(dpy, gc, COLOR(DISP_PAD_TOP)); + + for (i = 0; i < DISP_FRAME; i++) { + XDrawLine(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X - i), + (int)(DISPLAY_OFFSET_Y + display_height + 2 * i), + (int)(DISPLAY_OFFSET_X + display_width + i), + (int)(DISPLAY_OFFSET_Y + display_height + 2 * i)); + XDrawLine(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X - i), + (int)(DISPLAY_OFFSET_Y + display_height + 2 * i + 1), + (int)(DISPLAY_OFFSET_X + display_width + i), + (int)(DISPLAY_OFFSET_Y + display_height + 2 * i + 1)); + XDrawLine(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X + display_width + i), + (int)(DISPLAY_OFFSET_Y - i), + (int)(DISPLAY_OFFSET_X + display_width + i), + (int)(DISPLAY_OFFSET_Y + display_height + 2 * i)); + } + + XSetForeground(dpy, gc, COLOR(DISP_PAD_BOT)); + + for (i = 0; i < DISP_FRAME; i++) { + XDrawLine(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X - i - 1), + (int)(DISPLAY_OFFSET_Y - i - 1), + (int)(DISPLAY_OFFSET_X + display_width + i - 1), + (int)(DISPLAY_OFFSET_Y - i - 1)); + XDrawLine(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X - i - 1), + (int)(DISPLAY_OFFSET_Y - i - 1), + (int)(DISPLAY_OFFSET_X - i - 1), + (int)(DISPLAY_OFFSET_Y + display_height + 2 * i - 1)); + } + + /* + * round off corners + */ + XSetForeground(dpy, gc, COLOR(DISP_PAD)); + + XDrawLine(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X - DISP_FRAME), + (int)(DISPLAY_OFFSET_Y - DISP_FRAME), + (int)(DISPLAY_OFFSET_X - DISP_FRAME + 3), + (int)(DISPLAY_OFFSET_Y - DISP_FRAME)); + XDrawLine(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X - DISP_FRAME), + (int)(DISPLAY_OFFSET_Y - DISP_FRAME), + (int)(DISPLAY_OFFSET_X - DISP_FRAME), + (int)(DISPLAY_OFFSET_Y - DISP_FRAME + 3)); + XDrawPoint(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X - DISP_FRAME + 1), + (int)(DISPLAY_OFFSET_Y - DISP_FRAME + 1)); + + XDrawLine(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X + display_width + DISP_FRAME - 4), + (int)(DISPLAY_OFFSET_Y - DISP_FRAME), + (int)(DISPLAY_OFFSET_X + display_width + DISP_FRAME - 1), + (int)(DISPLAY_OFFSET_Y - DISP_FRAME)); + XDrawLine(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X + display_width + DISP_FRAME - 1), + (int)(DISPLAY_OFFSET_Y - DISP_FRAME), + (int)(DISPLAY_OFFSET_X + display_width + DISP_FRAME - 1), + (int)(DISPLAY_OFFSET_Y - DISP_FRAME + 3)); + XDrawPoint(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X + display_width + DISP_FRAME - 2), + (int)(DISPLAY_OFFSET_Y - DISP_FRAME + 1)); + + XDrawLine(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X - DISP_FRAME), + (int)(DISPLAY_OFFSET_Y + display_height + 2 * DISP_FRAME - 4), + (int)(DISPLAY_OFFSET_X - DISP_FRAME), + (int)(DISPLAY_OFFSET_Y + display_height + 2 * DISP_FRAME - 1)); + XDrawLine(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X - DISP_FRAME), + (int)(DISPLAY_OFFSET_Y + display_height + 2 * DISP_FRAME - 1), + (int)(DISPLAY_OFFSET_X - DISP_FRAME + 3), + (int)(DISPLAY_OFFSET_Y + display_height + 2 * DISP_FRAME - 1)); + XDrawPoint(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X - DISP_FRAME + 1), + (int)(DISPLAY_OFFSET_Y + display_height + 2 * DISP_FRAME - 2)); + + XDrawLine(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X + display_width + DISP_FRAME - 1), + (int)(DISPLAY_OFFSET_Y + display_height + 2 * DISP_FRAME - 4), + (int)(DISPLAY_OFFSET_X + display_width + DISP_FRAME - 1), + (int)(DISPLAY_OFFSET_Y + display_height + 2 * DISP_FRAME - 1)); + XDrawLine(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X + display_width + DISP_FRAME - 4), + (int)(DISPLAY_OFFSET_Y + display_height + 2 * DISP_FRAME - 1), + (int)(DISPLAY_OFFSET_X + display_width + DISP_FRAME - 1), + (int)(DISPLAY_OFFSET_Y + display_height + 2 * DISP_FRAME - 1)); + XDrawPoint(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X + display_width + DISP_FRAME - 2), + (int)(DISPLAY_OFFSET_Y + display_height + 2 * DISP_FRAME - 2)); + + /* + * simulate rounded lcd corners + */ + XSetForeground(dpy, gc, COLOR(LCD)); + + XDrawLine(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X - 1), + (int)(DISPLAY_OFFSET_Y + 1), + (int)(DISPLAY_OFFSET_X - 1), + (int)(DISPLAY_OFFSET_Y + display_height - 2)); + XDrawLine(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X + 1), + (int)(DISPLAY_OFFSET_Y - 1), + (int)(DISPLAY_OFFSET_X + display_width - 2), + (int)(DISPLAY_OFFSET_Y - 1)); + XDrawLine(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X + 1), + (int)(DISPLAY_OFFSET_Y + display_height), + (int)(DISPLAY_OFFSET_X + display_width - 2), + (int)(DISPLAY_OFFSET_Y + display_height)); + XDrawLine(dpy, keypad->pixmap, gc, + (int)(DISPLAY_OFFSET_X + display_width), + (int)(DISPLAY_OFFSET_Y + 1), + (int)(DISPLAY_OFFSET_X + display_width), + (int)(DISPLAY_OFFSET_Y + display_height - 2)); + + return; +} + +void +DrawMore(unsigned int w, unsigned int h, unsigned int offset_y, unsigned int offset_x, keypad_t *keypad) +{ + Pixmap pix; + int cut; + int x, y; + + int display_height = DISPLAY_HEIGHT; + int display_width = DISPLAY_WIDTH; + /* + * lower the whole thing + */ + XSetForeground(dpy, gc, COLOR(PAD_TOP)); + + /* bottom lines */ + int keypad_width = keypad->width; + XDrawLine(dpy, keypad->pixmap, gc, 1, (int)(keypad->height - 1), + (int)(keypad_width - 1), (int)(keypad->height - 1)); + XDrawLine(dpy, keypad->pixmap, gc, 2, (int)(keypad->height - 2), + (int)(keypad_width - 2), (int)(keypad->height - 2)); + + /* right lines */ + XDrawLine(dpy, keypad->pixmap, gc, (int)(keypad->width - 1), + (int)(keypad->height - 1), (int)(keypad->width - 1), cut); + XDrawLine(dpy, keypad->pixmap, gc, (int)(keypad->width - 2), + (int)(keypad->height - 2), (int)(keypad->width - 2), cut); + + XSetForeground(dpy, gc, COLOR(DISP_PAD_TOP)); + + /* right lines */ + XDrawLine(dpy, keypad->pixmap, gc, (int)(keypad->width - 1), + cut - 1, (int)(keypad->width - 1), 1); + XDrawLine(dpy, keypad->pixmap, gc, (int)(keypad->width - 2), + cut - 1, (int)(keypad->width - 2), 2); + + XSetForeground(dpy, gc, COLOR(DISP_PAD_BOT)); + + /* top lines */ + XDrawLine(dpy, keypad->pixmap, gc, 0, 0, (int)(keypad->width - 2), 0); + XDrawLine(dpy, keypad->pixmap, gc, 1, 1, (int)(keypad->width - 3), 1); + + /* left lines */ + XDrawLine(dpy, keypad->pixmap, gc, 0, cut - 1, 0, 0); + XDrawLine(dpy, keypad->pixmap, gc, 1, cut - 1, 1, 1); + + XSetForeground(dpy, gc, COLOR(PAD_BOT)); + + /* left lines */ + XDrawLine(dpy, keypad->pixmap, gc, 0, (int)(keypad->height - 2), 0, cut); + XDrawLine(dpy, keypad->pixmap, gc, 1, (int)(keypad->height - 3), 1, cut); + + /* + * lower the menu buttons + */ + XSetForeground(dpy, gc, COLOR(PAD_TOP)); + + /* bottom lines */ + XDrawLine(dpy, keypad->pixmap, gc, 3, (int)(keypad->height - 3), + (int)(keypad->width - 3), (int)(keypad->height - 3)); + XDrawLine(dpy, keypad->pixmap, gc, 4, (int)(keypad->height - 4), + (int)(keypad->width - 4), (int)(keypad->height - 4)); + + /* right lines */ + XDrawLine(dpy, keypad->pixmap, gc, (int)(keypad->width - 3), + (int)(keypad->height - 3), (int)(keypad->width - 3), cut); + XDrawLine(dpy, keypad->pixmap, gc, (int)(keypad->width - 4), + (int)(keypad->height - 4), (int)(keypad->width - 4), cut); + + XSetForeground(dpy, gc, COLOR(DISP_PAD_TOP)); + + /* right lines */ + XDrawLine(dpy, keypad->pixmap, gc, (int)(keypad->width - 3), + cut - 1, (int)(keypad->width - 3), offset_y - 24); + XDrawLine(dpy, keypad->pixmap, gc, (int)(keypad->width - 4), + cut - 1, (int)(keypad->width - 4), offset_y - 23); + + XSetForeground(dpy, gc, COLOR(DISP_PAD_BOT)); + + /* top lines */ + XDrawLine(dpy, keypad->pixmap, gc, 2, offset_y - 25, + (int)(keypad->width - 4), offset_y - 25); + XDrawLine(dpy, keypad->pixmap, gc, 3, offset_y - 24, + (int)(keypad->width - 5), offset_y - 24); + + /* left lines */ + XDrawLine(dpy, keypad->pixmap, gc, 2, cut - 1, 2, offset_y - 24); + XDrawLine(dpy, keypad->pixmap, gc, 3, cut - 1, 3, offset_y - 23); + + XSetForeground(dpy, gc, COLOR(PAD_BOT)); + + /* left lines */ + XDrawLine(dpy, keypad->pixmap, gc, 2, (int)(keypad->height - 4), 2, cut); + XDrawLine(dpy, keypad->pixmap, gc, 3, (int)(keypad->height - 5), 3, cut); + + /* + * lower the keyboard + */ + XSetForeground(dpy, gc, COLOR(PAD_TOP)); + + /* bottom lines */ + XDrawLine(dpy, keypad->pixmap, gc, 5, (int)(keypad->height - 5), + (int)(keypad->width - 3), (int)(keypad->height - 5)); + XDrawLine(dpy, keypad->pixmap, gc, 6, (int)(keypad->height - 6), + (int)(keypad->width - 4), (int)(keypad->height - 6)); + + /* right lines */ + XDrawLine(dpy, keypad->pixmap, gc, (int)(keypad->width - 5), + (int)(keypad->height - 5), (int)(keypad->width - 5), cut + 1); + XDrawLine(dpy, keypad->pixmap, gc, (int)(keypad->width - 6), + (int)(keypad->height - 6), (int)(keypad->width - 6), cut + 2); + + XSetForeground(dpy, gc, COLOR(DISP_PAD_BOT)); + + /* top lines */ + XDrawLine(dpy, keypad->pixmap, gc, 4, cut, + (int)(keypad->width - 6), cut); + XDrawLine(dpy, keypad->pixmap, gc, 5, cut + 1, + (int)(keypad->width - 7), cut + 1); + + XSetForeground(dpy, gc, COLOR(PAD_BOT)); + + /* left lines */ + XDrawLine(dpy, keypad->pixmap, gc, 4, (int)(keypad->height - 6), 4, cut + 1); + XDrawLine(dpy, keypad->pixmap, gc, 5, (int)(keypad->height - 7), 5, cut + 2); + + /* + * round off the bottom edge + */ + XSetForeground(dpy, gc, COLOR(PAD_TOP)); + + XDrawLine(dpy, keypad->pixmap, gc, (int)(keypad->width - 7), + (int)(keypad->height - 7), (int)(keypad->width - 7), + (int)(keypad->height - 14)); + XDrawLine(dpy, keypad->pixmap, gc, (int)(keypad->width - 8), + (int)(keypad->height - 8), (int)(keypad->width - 8), + (int)(keypad->height - 11)); + XDrawLine(dpy, keypad->pixmap, gc, (int)(keypad->width - 7), + (int)(keypad->height - 7), (int)(keypad->width - 14), + (int)(keypad->height - 7)); + XDrawLine(dpy, keypad->pixmap, gc, (int)(keypad->width - 7), + (int)(keypad->height - 8), (int)(keypad->width - 11), + (int)(keypad->height - 8)); + XDrawPoint(dpy, keypad->pixmap, gc, + (int)(keypad->width - 9), (int)(keypad->height - 9)); + + XDrawLine(dpy, keypad->pixmap, gc, 7, (int)(keypad->height - 7), 13, + (int)(keypad->height - 7)); + XDrawLine(dpy, keypad->pixmap, gc, 8, (int)(keypad->height - 8), 10, + (int)(keypad->height - 8)); + XSetForeground(dpy, gc, COLOR(PAD_BOT)); + XDrawLine(dpy, keypad->pixmap, gc, 6, (int)(keypad->height - 8), 6, + (int)(keypad->height - 14)); + XDrawLine(dpy, keypad->pixmap, gc, 7, (int)(keypad->height - 9), 7, + (int)(keypad->height - 11)); + + /* + * insert the HP Logo + */ + + XSetBackground(dpy, gc, COLOR(LOGO_BACK)); + XSetForeground(dpy, gc, COLOR(LOGO)); + + pix = XCreateBitmapFromData(dpy, keypad->pixmap, (char *)hp_bits, + hp_width, hp_height); + + if (opt_gx) + x = DISPLAY_OFFSET_X - 6; + else + x = DISPLAY_OFFSET_X; + + XCopyPlane(dpy, pix, keypad->pixmap, gc, 0, 0, hp_width, hp_height, + x, 10, 1); + + XFreePixmap(dpy, pix); + + if (!opt_gx) + { + XSetForeground(dpy, gc, COLOR(FRAME)); + + XDrawLine(dpy, keypad->pixmap, gc, (int)DISPLAY_OFFSET_X, 9, + (int)(DISPLAY_OFFSET_X + hp_width - 1), 9); + XDrawLine(dpy, keypad->pixmap, gc, (int)(DISPLAY_OFFSET_X - 1), 10, + (int)(DISPLAY_OFFSET_X - 1), 10 + hp_height - 1); + XDrawLine(dpy, keypad->pixmap, gc, (int)DISPLAY_OFFSET_X, 10 + hp_height, + (int)(DISPLAY_OFFSET_X + hp_width - 1), 10 + hp_height); + XDrawLine(dpy, keypad->pixmap, gc, (int)(DISPLAY_OFFSET_X + hp_width), 10, + (int)(DISPLAY_OFFSET_X + hp_width), 10 + hp_height - 1); + } + + /* + * write the name of it + */ + XSetBackground(dpy, gc, COLOR(DISP_PAD)); + XSetForeground(dpy, gc, COLOR(LABEL)); + + if (opt_gx) + { + x = DISPLAY_OFFSET_X + display_width - gx_128K_ram_width + + gx_128K_ram_x_hot + 2; + y = 10 + gx_128K_ram_y_hot; + pix = XCreateBitmapFromData(dpy, keypad->pixmap, (char *)gx_128K_ram_bits, + gx_128K_ram_width, gx_128K_ram_height); + XCopyPlane(dpy, pix, keypad->pixmap, gc, 0, 0, gx_128K_ram_width, + gx_128K_ram_height, x, y, 1); + XFreePixmap(dpy, pix); + + XSetForeground(dpy, gc, COLOR(LOGO)); + x = DISPLAY_OFFSET_X + hp_width; + y = hp_height + 8 - hp48gx_height; + pix = XCreateBitmapFromData(dpy, keypad->pixmap, (char *)hp48gx_bits, + hp48gx_width, hp48gx_height); + XCopyPlane(dpy, pix, keypad->pixmap, gc, 0, 0, hp48gx_width, + hp48gx_height, x, y, 1); + XFreePixmap(dpy, pix); + + XSetFillStyle(dpy, gc, FillStippled); + x = DISPLAY_OFFSET_X + DISPLAY_WIDTH - gx_128K_ram_width + + gx_silver_x_hot + 2; + y = 10 + gx_silver_y_hot; + pix = XCreateBitmapFromData(dpy, keypad->pixmap, (char *)gx_silver_bits, + gx_silver_width, gx_silver_height); + XSetStipple(dpy, gc, pix); + XSetTSOrigin(dpy, gc, x, y); + XFillRectangle(dpy, keypad->pixmap, gc, x, y, gx_silver_width, + gx_silver_height); + XFreePixmap(dpy, pix); + + XSetForeground(dpy, gc, COLOR(RIGHT)); + x = DISPLAY_OFFSET_X + display_width - gx_128K_ram_width + + gx_green_x_hot + 2; + y = 10 + gx_green_y_hot; + pix = XCreateBitmapFromData(dpy, keypad->pixmap, (char *)gx_green_bits, + gx_green_width, gx_green_height); + XSetStipple(dpy, gc, pix); + XSetTSOrigin(dpy, gc, x, y); + XFillRectangle(dpy, keypad->pixmap, gc, x, y, gx_green_width, + gx_green_height); + XFreePixmap(dpy, pix); + + XSetTSOrigin(dpy, gc, 0, 0); + XSetFillStyle(dpy, gc, FillSolid); + } + else + { + x = DISPLAY_OFFSET_X; + y = TOP_SKIP - DISP_FRAME - hp48sx_height - 3; + + pix = XCreateBitmapFromData(dpy, keypad->pixmap, (char *)hp48sx_bits, + hp48sx_width, hp48sx_height); + + XCopyPlane(dpy, pix, keypad->pixmap, gc, 0, 0, hp48sx_width, + hp48sx_height, x, y, 1); + + XFreePixmap(dpy, pix); + + x = DISPLAY_OFFSET_X + display_width - 1 - science_width; + y = TOP_SKIP - DISP_FRAME - science_height - 4; + + pix = XCreateBitmapFromData(dpy, keypad->pixmap, (char *)science_bits, + science_width, science_height); + + XCopyPlane(dpy, pix, keypad->pixmap, gc, 0, 0, science_width, + science_height, x, y, 1); + } + + /* + * that's it. Ooph. + */ + return; +} + +void +#ifdef __FunctionProto__ +DrawKeypad(keypad_t *keypad) +#else +DrawKeypad() +keypad_t *keypad; +#endif +{ + XCopyArea(dpy, keypad->pixmap, mainW, gc, 0, 0, keypad->width, + keypad->height, 0, 0); + return; +} + +void +#ifdef __FunctionProto__ +CreateIcon(void) +#else +CreateIcon() +#endif +{ + XSetWindowAttributes xswa; + XWindowAttributes xwa; + Pixmap tmp_pix; + int p; + + XGetWindowAttributes(dpy, iconW, &xwa); + xswa.event_mask = xwa.your_event_mask | ExposureMask; + xswa.backing_store = Always; + XChangeWindowAttributes(dpy, iconW, CWEventMask|CWBackingStore, &xswa); + + icon_pix = XCreatePixmap(dpy, iconW, hp48_icon_width, + hp48_icon_height, depth); + + /* + * draw the icon pixmap + */ + if (icon_color_mode == COLOR_MODE_MONO) + { + tmp_pix = XCreateBitmapFromData(dpy, iconW, + (char *)icon_maps[ICON_MAP].bits, + icon_maps[ICON_MAP].w, + icon_maps[ICON_MAP].h); + XSetForeground(dpy, gc, COLOR(BLACK)); + XSetBackground(dpy, gc, COLOR(WHITE)); + XCopyPlane(dpy, tmp_pix, icon_pix, gc, 0, 0, + icon_maps[ICON_MAP].w, icon_maps[ICON_MAP].h, 0, 0, 1); + XFreePixmap(dpy, tmp_pix); + } + else + { + XSetFillStyle(dpy, gc, FillStippled); + for (p = FIRST_MAP; p <= LAST_MAP; p++) + { + tmp_pix = XCreateBitmapFromData(dpy, iconW, + (char *)icon_maps[p].bits, + icon_maps[p].w, + icon_maps[p].h); + XSetStipple(dpy, gc, tmp_pix); + XSetForeground(dpy, gc, COLOR(icon_maps[p].c)); + XFillRectangle(dpy, icon_pix, gc, 0, 0, + icon_maps[p].w, icon_maps[p].h); + XFreePixmap(dpy, tmp_pix); + } + XSetFillStyle(dpy, gc, FillSolid); + + /* + * draw frame around icon + */ + XSetForeground(dpy, gc, COLOR(BLACK)); + XDrawRectangle(dpy, icon_pix, gc, 0, 0, icon_maps[ICON_MAP].w - 1, + icon_maps[ICON_MAP].h - 1); + } + + /* + * draw the display + */ + XSetFillStyle(dpy, gc, FillStippled); + icon_disp_pix = XCreateBitmapFromData(dpy, iconW, + (char *)icon_maps[DISP_MAP].bits, + icon_maps[DISP_MAP].w, + icon_maps[DISP_MAP].h); + XSetStipple(dpy, gc, icon_disp_pix); + if (icon_color_mode == COLOR_MODE_MONO) + XSetForeground(dpy, gc, COLOR(WHITE)); + else + XSetForeground(dpy, gc, COLOR(icon_maps[DISP_MAP].c)); + XFillRectangle(dpy, icon_pix, gc, 0, 0, + icon_maps[DISP_MAP].w, icon_maps[DISP_MAP].h); + + /* + * draw the 'x48' string + */ + icon_text_pix = XCreateBitmapFromData(dpy, iconW, + (char *)icon_maps[ON_MAP].bits, + icon_maps[ON_MAP].w, + icon_maps[ON_MAP].h); + XSetStipple(dpy, gc, icon_text_pix); + if (icon_color_mode == COLOR_MODE_MONO) + XSetForeground(dpy, gc, COLOR(BLACK)); + else + XSetForeground(dpy, gc, COLOR(icon_maps[ON_MAP].c)); + XFillRectangle(dpy, icon_pix, gc, 0, 0, + icon_maps[ON_MAP].w, icon_maps[ON_MAP].h); + XSetFillStyle(dpy, gc, FillSolid); + + return; +} + +void +#ifdef __FunctionProto__ +refresh_icon(void) +#else +refresh_icon() +#endif +{ + int icon_state; + + icon_state = ((display.on && !((ANN_IO & display.annunc) == ANN_IO)) || + (display.on && !((ANN_ALPHA & display.annunc) == ANN_ALPHA))); + if (icon_state == last_icon_state) + return; + + last_icon_state = icon_state; + XSetFillStyle(dpy, gc, FillStippled); + if (icon_state) + { + /* + * draw the 'x48' string + */ + XSetStipple(dpy, gc, icon_text_pix); + if (icon_color_mode == COLOR_MODE_MONO) + XSetForeground(dpy, gc, COLOR(BLACK)); + else + XSetForeground(dpy, gc, COLOR(icon_maps[ON_MAP].c)); + XFillRectangle(dpy, icon_pix, gc, 0, 0, + icon_maps[ON_MAP].w, icon_maps[ON_MAP].h); + } + else + { + /* + * clear the display + */ + XSetFillStyle(dpy, gc, FillStippled); + XSetStipple(dpy, gc, icon_disp_pix); + if (icon_color_mode == COLOR_MODE_MONO) + XSetForeground(dpy, gc, COLOR(WHITE)); + else + XSetForeground(dpy, gc, COLOR(icon_maps[DISP_MAP].c)); + XFillRectangle(dpy, icon_pix, gc, 0, 0, + icon_maps[DISP_MAP].w, icon_maps[DISP_MAP].h); + } + XSetFillStyle(dpy, gc, FillSolid); + if (iconW) + { + XCopyArea(dpy, icon_pix, iconW, gc, 0, 0, + hp48_icon_width, hp48_icon_height, 0, 0); + } +} + +void +#ifdef __FunctionProto__ +DrawIcon(void) +#else +DrawIcon() +#endif +{ + XCopyArea(dpy, icon_pix, iconW, gc, 0, 0, + hp48_icon_width, hp48_icon_height, 0, 0); + return; +} + +#ifdef HAVE_XSHM +int +#ifdef __FunctionProto__ +handle_xerror(Display *the_dpy, XErrorEvent *eev) +#else +handle_xerror(the_dpy, eev) +Display *the_dpy; +XErrorEvent *eev; +#endif +{ + xerror_flag = 1; + return 0; +} +#endif + +void +#ifdef __FunctionProto__ +CreateDispWindow(void) +#else +CreateDispWindow() +#endif +{ + XSetWindowAttributes xswa; + XGCValues val; + unsigned long gc_mask; + static XRectangle rect; + + /* + * create the display subwindow + */ + disp.w = DISPLAY_WIDTH; + disp.h = DISPLAY_HEIGHT; + + disp.win = XCreateSimpleWindow(dpy, mainW, + (int)DISPLAY_OFFSET_X, (int)DISPLAY_OFFSET_Y, + disp.w, disp.h, 0, + COLOR(BLACK), COLOR(LCD)); + + disp.mapped = 1; + + xswa.event_mask = ExposureMask | StructureNotifyMask; + xswa.backing_store = Always; + + XChangeWindowAttributes(dpy, disp.win, CWEventMask|CWBackingStore, &xswa); + + /* + * set up the gc + */ + val.foreground = COLOR(LCD); + val.background = COLOR(LCD); + val.function = GXcopy; + gc_mask = GCForeground | GCBackground | GCFunction; + disp.gc = XCreateGC(dpy, mainW, gc_mask, &val); + + XSetForeground(dpy, disp.gc, COLOR(PIXEL)); + +#ifdef HAVE_XSHM + + disp.display_update = UPDATE_DISP | UPDATE_MENU; + + xerror_flag = 0; + XSetErrorHandler(handle_xerror); + XFlush(dpy); + + disp.disp_image = NULL; + disp.menu_image = NULL; + if (shm_flag) { + + /* + * create XShmImage for DISP + */ + disp.disp_image = XShmCreateImage(dpy, None, 1, XYBitmap, NULL, + &disp.disp_info, 262, 128); + if (disp.disp_image == NULL) { + shm_flag = 0; + if (!quiet) + fprintf(stderr, "%s: XShm error in CreateImage(DISP), disabling.\n", + progname); + goto shm_error; + } + + /* + * get ID of shared memory block for DISP + */ + disp.disp_info.shmid = shmget(IPC_PRIVATE, + (disp.disp_image->bytes_per_line * disp.disp_image->height), + IPC_CREAT | 0777); + if (disp.disp_info.shmid < 0) { + XDestroyImage(disp.disp_image); + disp.disp_image = NULL; + shm_flag = 0; + if (!quiet) + fprintf(stderr, "%s: XShm error in shmget(DISP), disabling.\n", + progname); + goto shm_error; + } + + /* + * get address of shared memory block for DISP + */ + disp.disp_info.shmaddr = (char *)shmat(disp.disp_info.shmid, 0, 0); + if (disp.disp_info.shmaddr == ((char *)-1)) { + XDestroyImage(disp.disp_image); + disp.disp_image = NULL; + shm_flag = 0; + if (!quiet) + fprintf(stderr, "%s: XShm error in shmat(DISP), disabling.\n", + progname); + goto shm_error; + } + disp.disp_image->data = disp.disp_info.shmaddr; + disp.disp_info.readOnly = False; + XShmAttach(dpy, &disp.disp_info); + + /* + * create XShmImage for MENU + */ + disp.menu_image = XShmCreateImage(dpy, None, 1, XYBitmap, NULL, + &disp.menu_info, 262, 128); + if (disp.menu_image == NULL) { + XDestroyImage(disp.disp_image); + disp.disp_image = NULL; + shm_flag = 0; + if (!quiet) + fprintf(stderr, "%s: XShm error in CreateImage(MENU), disabling.\n", + progname); + goto shm_error; + } + + /* + * get ID of shared memory block for MENU + */ + disp.menu_info.shmid = shmget(IPC_PRIVATE, + (disp.menu_image->bytes_per_line * disp.menu_image->height), + IPC_CREAT | 0777); + if (disp.menu_info.shmid < 0) { + XDestroyImage(disp.disp_image); + disp.disp_image = NULL; + XDestroyImage(disp.menu_image); + disp.menu_image = NULL; + shm_flag = 0; + if (!quiet) + fprintf(stderr, "%s: XShm error in shmget(MENU), disabling.\n", + progname); + goto shm_error; + } + + /* + * get address of shared memory block for MENU + */ + disp.menu_info.shmaddr = (char *)shmat(disp.menu_info.shmid, 0, 0); + if (disp.menu_info.shmaddr == ((char *)-1)) { + XDestroyImage(disp.disp_image); + disp.disp_image = NULL; + XDestroyImage(disp.menu_image); + disp.menu_image = NULL; + shm_flag = 0; + if (!quiet) + fprintf(stderr, "%s: XShm error in shmat(MENU), disabling.\n", + progname); + goto shm_error; + } + disp.menu_image->data = disp.menu_info.shmaddr; + disp.menu_info.readOnly = False; + XShmAttach(dpy, &disp.menu_info); + + XFlush(dpy); + XSync(dpy, 0); + sleep(1); + + if (xerror_flag) { + XDestroyImage(disp.disp_image); + disp.disp_image = NULL; + XDestroyImage(disp.menu_image); + disp.menu_image = NULL; + shm_flag = 0; + if (!quiet) + fprintf(stderr, "%s: XShm error in shmget(MENU), disabling.\n", + progname); + goto shm_error; + } else { + shmctl(disp.disp_info.shmid, IPC_RMID, 0); + shmctl(disp.menu_info.shmid, IPC_RMID, 0); + } + + memset(disp.disp_image->data, 0, + (size_t)(disp.disp_image->bytes_per_line * disp.disp_image->height)); + memset(disp.menu_image->data, 0, + (size_t)(disp.menu_image->bytes_per_line * disp.menu_image->height)); + + if (verbose) + printf("%s: using XShm extension.\n", progname); + + CompletionType = XShmGetEventBase(dpy) + ShmCompletion; + } + shm_error: + + XSetErrorHandler(NULL); + XFlush(dpy); + + if (!shm_flag) { +#endif + rect.x = 5; + rect.y = 0; + rect.width = 262; + rect.height = disp.h; + XSetClipRectangles(dpy, disp.gc, 0, 0, &rect, 1, Unsorted); +#ifdef HAVE_XSHM + } +#endif + + return; +} + +int +#ifdef __FunctionProto__ +CreateWindows(int argc, char **argv) +#else +CreateWindows(argc, argv) +int argc; +char **argv; +#endif +{ + XSizeHints hint, ih; + XWMHints wmh; + XClassHint clh; + unsigned int class; + XGCValues val; + unsigned long gc_mask; + unsigned int mask; + XSetWindowAttributes xswa; + XTextProperty wname, iname; + Atom protocols[2]; + char *name, *user_geom, def_geom[40]; + int info, x, y, w, h; + unsigned int width, height; + + if (opt_gx) + { + buttons = buttons_gx; + colors = colors_gx; + icon_maps = icon_maps_gx; + } + else + { + buttons = buttons_sx; + colors = colors_sx; + icon_maps = icon_maps_sx; + } + + if (netbook) { + int i; + for (i = 0; i < 6; i++) { + buttons[i].x -= 3; + buttons[i].y += 300; + } + for (; i <= LAST_BUTTON; i++) { + buttons[i].x += 317; + buttons[i].y -= 3; + } + } + + class = InputOutput; + visual = get_visual_resource(dpy, "visual", "Visual", &depth); + if (visual != DefaultVisual(dpy, screen)) + { + if (visual->class == DirectColor) + cmap = XCreateColormap(dpy, RootWindow(dpy, screen), visual, AllocAll); + else + cmap = XCreateColormap(dpy, RootWindow(dpy, screen), visual, AllocNone); + } + else + cmap = DefaultColormap(dpy, screen); + + direct_color = 0; + switch (visual->class) + { + case DirectColor: + direct_color = 1; + case GrayScale: + case PseudoColor: + dynamic_color = 1; + break; + case StaticGray: + case StaticColor: + case TrueColor: + default: + dynamic_color = 0; + break; + } + + if ((visual->class == StaticGray) || (visual->class == GrayScale)) + color_mode = COLOR_MODE_GRAY; + else + color_mode = COLOR_MODE_COLOR; + if (get_boolean_resource("gray", "Gray")) + color_mode = COLOR_MODE_GRAY; + + if (get_boolean_resource("mono", "Mono")) + color_mode = COLOR_MODE_MONO; + if (depth == 1) + color_mode = COLOR_MODE_MONO; + + icon_color_mode = color_mode; + if (get_boolean_resource("monoIcon", "Mono")) + icon_color_mode = COLOR_MODE_MONO; + + + clh.res_name = res_name; + clh.res_class = res_class; + if(!XStringListToTextProperty(&progname, 1, &iname)) + return -1; + + if ((name = get_string_resource("title", "Title")) == (char *)0) + { + name = (char *)malloc(128); + if (name == (char *)0) { + sprintf(errbuf, "malloc failed.\n"); + fatal_exit(); + } + sprintf(name, "%s-%d.%d.%d", progname, saturn.version[0], + saturn.version[1], saturn.version[2]); + } + + if(!XStringListToTextProperty(&name, 1, &wname)) + return -1; + + /* + * Set some Window Attributes + */ + xswa.colormap = cmap; + mask = CWColormap; + + /* + * create the window + */ + width = KEYBOARD_WIDTH + 2 * SIDE_SKIP; + if (netbook) { + height = KEYBOARD_HEIGHT; + } else { + height = DISPLAY_OFFSET_Y + DISPLAY_HEIGHT + DISP_KBD_SKIP + KEYBOARD_HEIGHT + BOTTOM_SKIP; + } + + mainW = XCreateWindow(dpy, RootWindow(dpy, screen), + 0, 0, width, height, + 0, (int)depth, class, + visual, mask, &xswa); + + if (mainW == 0) + return -1; + + /* + * allocate my colors + */ + AllocColors(); + + /* + * parse -geometry ... + */ + hint.x = hint.y = 0; + hint.min_width = hint.max_width = hint.base_width = hint.width = width; + hint.min_height = hint.max_height = hint.base_height = hint.height = height; + hint.win_gravity = NorthWestGravity; + hint.flags = PSize | PMinSize | PMaxSize | PBaseSize | PWinGravity; + + sprintf(def_geom, "%ux%u", width, height); + user_geom = get_string_resource("geometry", "Geometry"); + + info = XWMGeometry(dpy, screen, user_geom, def_geom, 0, &hint, + &x, &y, &w, &h, &hint.win_gravity); + + if (info & (XValue | YValue)) + { + if (info & XValue) + hint.x = x; + if (info & YValue) + hint.y = y; + hint.flags |= USPosition; + } + + /* + * check if we start iconic + */ + if (get_boolean_resource("iconic", "Iconic")) + wmh.initial_state = IconicState; + else + wmh.initial_state = NormalState; + wmh.input = True; + wmh.flags = StateHint | InputHint; + + /* + * Set some more Window Attributes + */ + xswa.background_pixel = COLOR(PAD); + xswa.border_pixel = COLOR(BLACK); + xswa.backing_store = Always; + xswa.win_gravity = hint.win_gravity; + xswa.bit_gravity = NorthWestGravity; + xswa.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | + ButtonReleaseMask | ExposureMask | KeymapStateMask | + EnterWindowMask | StructureNotifyMask | FocusChangeMask; + mask = CWBackPixel | CWBorderPixel | CWBackingStore | CWEventMask | + CWBitGravity | CWWinGravity; + XChangeWindowAttributes(dpy, mainW, mask, &xswa); + XMoveWindow(dpy, mainW, hint.x, hint.y); + + /* + * create the icon + */ + xswa.colormap = cmap; + mask = CWColormap; + iconW = XCreateWindow(dpy, RootWindow(dpy, screen), + 0, 0, hp48_icon_width, hp48_icon_height, + 0, (int)depth, class, + visual, mask, &xswa); + + if (iconW == 0) + return -1; + + wmh.icon_window = iconW; + wmh.window_group = mainW; + wmh.flags |= (IconWindowHint | WindowGroupHint); + + /* + * set icon position if requested + */ + ih.x = ih.y = 0; + ih.min_width = ih.max_width = ih.base_width = ih.width = hp48_icon_width; + ih.min_height = ih.max_height = ih.base_height = ih.height = hp48_icon_height; + ih.win_gravity = NorthWestGravity; + ih.flags = PSize | PMinSize | PMaxSize | PBaseSize | PWinGravity; + + user_geom = get_string_resource("iconGeom", "IconGeom"); + info = XWMGeometry(dpy, screen, user_geom, (char *)0, 0, &ih, + &x, &y, &w, &h, &ih.win_gravity); + + if ((info & XValue) && (info & YValue)) + { + wmh.icon_x = x; + wmh.icon_y = y; + wmh.flags |= IconPositionHint; + } + + /* + * set some more attributes of icon window + */ + xswa.background_pixel = COLOR(BLACK); + xswa.border_pixel = COLOR(BLACK); + xswa.backing_store = NotUseful; + xswa.win_gravity = ih.win_gravity; + xswa.bit_gravity = NorthWestGravity; + mask = CWBackPixel | CWBorderPixel | CWBackingStore | CWBitGravity | + CWWinGravity; + XChangeWindowAttributes(dpy, iconW, mask, &xswa); + + /* + * tell window manager all the stuff we dug out + */ + XSetWMProperties(dpy, mainW, &wname, &iname, argv, argc, &hint, &wmh, &clh); + + /* + * turn on WM_DELETE_WINDOW + */ + wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", 0); + wm_save_yourself = XInternAtom(dpy, "WM_SAVE_YOURSELF", 0); + wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", 0); + protocols[0] = wm_delete_window; + protocols[1] = wm_save_yourself; + XSetWMProtocols(dpy, mainW, protocols, 2); + + /* + * turn off icon name for olwm, olvwm + */ + ol_decor_icon_name = XInternAtom(dpy, "_OL_DECOR_ICON_NAME", 0); + ol_decor_del = XInternAtom(dpy, "_OL_DECOR_DEL", 0); + atom_type = XInternAtom(dpy, "ATOM", 0); + XChangeProperty(dpy, mainW, ol_decor_del, atom_type, 32, PropModeReplace, + (unsigned char *)&ol_decor_icon_name, 1); + + /* + * set up the GC's + */ + val.foreground = COLOR(WHITE); + val.background = COLOR(BLACK); + val.function = GXcopy; + gc_mask = GCForeground | GCBackground | GCFunction; + gc = XCreateGC(dpy, mainW, gc_mask, &val); + + /* + * create the icon pixmap for desktops + */ + CreateIcon(); + + /* + * create the display + */ + CreateDispWindow(); + + /* + * create the keypad + */ + /* + * draw the nice labels around the buttons + */ + keypad.width = width; + keypad.height = height; + + keypad.pixmap = XCreatePixmap(dpy, mainW, width, height, depth); + + + if (netbook) { + int cut = buttons[BUTTON_MTH].y - (small_ascent + small_descent + 6 + 4); + CreateBackground(width/2, height, width, height, &keypad); + DrawMore(width, height, KEYBOARD_OFFSET_Y, KEYBOARD_OFFSET_X, &keypad); + CreateBezel(width/2, height, KEYBOARD_OFFSET_Y, KEYBOARD_OFFSET_X, &keypad); + CreateKeypad(width, height, -cut, KEYBOARD_OFFSET_X, &keypad); + } else { + int cut = buttons[BUTTON_MTH].y + KEYBOARD_OFFSET_Y - 19; + CreateBackground(width, cut, width, height, &keypad); + DrawMore(width, height, KEYBOARD_OFFSET_Y, KEYBOARD_OFFSET_X, &keypad); + CreateBezel(width, cut, KEYBOARD_OFFSET_Y, KEYBOARD_OFFSET_X, &keypad); + CreateKeypad(width, height, KEYBOARD_OFFSET_Y, KEYBOARD_OFFSET_X, &keypad); + } + + /* + * map the window + */ + XMapWindow(dpy, mainW); + XMapSubwindows(dpy, mainW); + + DrawKeypad(&keypad); + DrawButtons(); + DrawIcon(); + +#ifdef HAVE_XSHM + if (shm_flag) { + XSetForeground(dpy, disp.gc, COLOR(PIXEL)); + XFillRectangle(dpy, disp.win, disp.gc, 5, 20, 262, 128); + } +#endif + + return 0; +} + +void +#ifdef __FunctionProto__ +ShowConnections(char *wire, char *ir) +#else +ShowConnections(wire, ir) +char *wire; +char *ir; +#endif +{ + int x, y, w, h; + int conn_top; + XFontStruct *finfo; + char name[128]; + XGCValues val; + unsigned long gc_mask; + XCharStruct xchar; + int dir, fa, fd; + Pixmap pix; + + finfo = get_font_resource(dpy, "connectionFont", "ConnectionFont"); + val.font = finfo->fid; + gc_mask = GCFont; + XChangeGC(dpy, gc, gc_mask, &val); + + conn_top = DISPLAY_OFFSET_Y + DISPLAY_HEIGHT + 18; + + XTextExtents(finfo, "TEST", (int)strlen("TEST"), &dir, &fa, &fd, &xchar); + w = DISPLAY_WIDTH; + h = fa + fd; + + pix = XCreatePixmap(dpy, keypad.pixmap, w, h, depth); /* FIXME keypad? */ + XSetForeground(dpy, gc, COLOR(DISP_PAD)); + XFillRectangle(dpy, pix, gc, 0, 0, w, h); + + XSetBackground(dpy, gc, COLOR(DISP_PAD)); + XSetForeground(dpy, gc, COLOR(LABEL)); + + sprintf(name, "wire: %s", wire ? wire : "none"); + XTextExtents(finfo, name, (int)strlen(name), &dir, &fa, &fd, &xchar); + x = 0; + y = fa; + XDrawImageString(dpy, pix, gc, x, y, name, (int)strlen(name)); + + sprintf(name, "IR: %s", ir ? ir : "none"); + XTextExtents(finfo, name, (int)strlen(name), &dir, &fa, &fd, &xchar); + x = w - xchar.width - 1; + y = fa; + XDrawImageString(dpy, pix, gc, x, y, name, (int)strlen(name)); + + x = DISPLAY_OFFSET_X; + y = conn_top; + XCopyArea(dpy, pix, keypad.pixmap, gc, 0, 0, w, h, x, y); /* FIXME keypad? */ + + DrawKeypad(&keypad); + + XFreePixmap(dpy, pix); + XFreeFont(dpy, finfo); +} + +int +#ifdef __FunctionProto__ +button_pressed(int b) +#else +button_pressed(b) +int b; +#endif +{ + int code; + int i, r, c; + + code = buttons[b].code; + buttons[b].pressed = 1; + if (code == 0x8000) { + for (i = 0; i < 9; i++) + saturn.keybuf.rows[i] |= 0x8000; + do_kbd_int(); + } else { + r = code >> 4; + c = 1 << (code & 0xf); + if ((saturn.keybuf.rows[r] & c) == 0) { + if (saturn.kbd_ien) { + do_kbd_int(); + } + if ((saturn.keybuf.rows[r] & c)) { +fprintf(stderr, "bug\n"); + } + saturn.keybuf.rows[r] |= c; + } + } +#ifdef DEBUG_BUTTONS + fprintf(stderr, "Button pressed %d (%s)\n", + buttons[b].code, buttons[b].name); +#endif + return 0; +} + +int +#ifdef __FunctionProto__ +button_released(int b) +#else +button_released(b) +int b; +#endif +{ + int code; + + code = buttons[b].code; + buttons[b].pressed = 0; + if (code == 0x8000) { + int i; + for (i = 0; i < 9; i++) + saturn.keybuf.rows[i] &= ~0x8000; + } else { + int r, c; + r = code >> 4; + c = 1 << (code & 0xf); + saturn.keybuf.rows[r] &= ~c; + } +#ifdef DEBUG_BUTTONS + fprintf(stderr, "Button released %d (%s)\n", + buttons[b].code, buttons[b].name); +#endif + return 0; +} + +static +int +#ifdef __FunctionProto__ +button_release_all(void) +#else +button_release_all() +#endif +{ + int code; + int b; + +#ifdef DEBUG_BUTTONS + fprintf(stderr, "Buttons released "); +#endif + for (b = BUTTON_A; b <= LAST_BUTTON; b++) + { + if (buttons[b].pressed) + { +#ifdef DEBUG_BUTTONS + fprintf(stderr, "%d (%s) ", + buttons[b].code, buttons[b].name); +#endif + code = buttons[b].code; + if (code == 0x8000) { + int i; + for (i = 0; i < 9; i++) + saturn.keybuf.rows[i] &= ~0x8000; + } else { + int r, c; + r = code >> 4; + c = 1 << (code & 0xf); + saturn.keybuf.rows[r] &= ~c; + } + buttons[b].pressed = 0; + DrawButton(b); + } + } +#ifdef DEBUG_BUTTONS + fprintf(stderr, "\n"); +#endif + return 0; +} + +int +#ifdef __FunctionProto__ +key_event(int b, XEvent *xev) +#else +key_event(b, xev) +int b; +XEvent *xev; +#endif +{ + int code; + int i, r, c; + int all_up; + + code = buttons[b].code; + if (xev->type == KeyPress) { + buttons[b].pressed = 1; + DrawButton(b); + if (code == 0x8000) { + for (i = 0; i < 9; i++) + saturn.keybuf.rows[i] |= 0x8000; + do_kbd_int(); + } else { + r = code >> 4; + c = 1 << (code & 0xf); + if ((saturn.keybuf.rows[r] & c) == 0) { + if (saturn.kbd_ien) { + do_kbd_int(); + } + saturn.keybuf.rows[r] |= c; + } + } +#ifdef DEBUG_BUTTONS + fprintf(stderr, "Key pressed %d (%s) %x\n", + buttons[b].code, buttons[b].name), c; +#endif + } else { + if (code == 0x8000) { + for (i = 0; i < 9; i++) + saturn.keybuf.rows[i] &= ~0x8000; + memset (&saturn.keybuf, 0, sizeof (saturn.keybuf)); + } else { + r = code >> 4; + c = 1 << (code & 0xf); + saturn.keybuf.rows[r] &= ~c; + } + buttons[b].pressed = 0; + DrawButton(b); +#ifdef DEBUG_BUTTONS + fprintf(stderr, "Key released %d (%s)\n", + buttons[b].code, buttons[b].name); +#endif + } + return 0; +} + +#ifdef HAVE_XSHM +void +#ifdef __FunctionProto__ +refresh_display(void) +#else +refresh_display() +#endif +{ + if (shm_flag) { + if (disp.display_update & UPDATE_DISP) { + XShmPutImage(dpy, disp.win, disp.gc, disp.disp_image, disp.offset, 0, + 5, 20, 262, (unsigned int)(disp.lines + 2), 0); + } + if ((disp.lines < 126) && (disp.display_update & UPDATE_MENU)) { + XShmPutImage(dpy, disp.win, disp.gc, disp.menu_image, + 0, 0, 5, (int)(disp.lines + 22), + 262, (unsigned int)(126 - disp.lines), 0); + } + disp.display_update = 0; + } +} +#endif + +void +#ifdef __FunctionProto__ +DrawDisp(void) +#else +DrawDisp() +#endif +{ +#ifdef HAVE_XSHM + if (shm_flag) { + XShmPutImage(dpy, disp.win, disp.gc, disp.disp_image, disp.offset, 0, + 5, 20, 262, (unsigned int)(disp.lines + 2), 0); + if (display.lines < 63) { + XShmPutImage(dpy, disp.win, disp.gc, disp.menu_image, + 0, disp.lines - 110, 5, 22 + disp.lines, + 262, (unsigned int)(126 - disp.lines), 0); + } + disp.display_update = 0; + } else { +#endif + redraw_display(); +#ifdef HAVE_XSHM + } +#endif + redraw_annunc(); +} + +void +#ifdef __FunctionProto__ +get_geometry_string(Window win, char *s, int allow_off_screen) +#else +get_geometry_string(win, s, allow_off_screen) +Window win; +char *s; +int allow_off_screen; +#endif +{ + XWindowAttributes xwa; + Window root, parent, window; + Window *children = (Window *)0; + unsigned int rw, rh, rbw, rd; + unsigned int w, h, bw, d; + unsigned int nc; + int rx, ry, x, y; + int x_pos, x_neg, x_s, y_pos, y_neg, y_s; + + window = win; + nc = 0; + XQueryTree(dpy, window, &root, &parent, &children, &nc); + XFree((char *)children); + while (parent != root) + { + window = parent; + nc = 0; + XQueryTree(dpy, window, &root, &parent, &children, &nc); + XFree((char *)children); + } + XGetGeometry(dpy, window, &root, &x, &y, &w, &h, &bw, &d); + XGetGeometry(dpy, root, &root, &rx, &ry, &rw, &rh, &rbw, &rd); + + x_s = 1; + x_pos = x; + x_neg = rw - (x + w); + if (abs(x_pos) > abs(x_neg)) + { + x = x_neg; + x_s = -1; + } + y_s = 1; + y_pos = y; + y_neg = rh - (y + h); + if (abs(y_pos) > abs(y_neg)) + { + y = y_neg; + y_s = -1; + } + + if (!allow_off_screen) + { + if (x < 0) x = 0; + if (y < 0) y = 0; + } + + XGetWindowAttributes(dpy, win, &xwa); + sprintf(s, "%ux%u%s%d%s%d", xwa.width, xwa.height, + (x_s > 0) ? "+" : "-", x, (y_s > 0) ? "+" : "-", y); +} + +void +#ifdef __FunctionProto__ +save_command_line(void) +#else +save_command_line() +#endif +{ + XWindowAttributes xwa; + int wm_argc, ac; + char **wm_argv, geom[128], icon_geom[128]; + + ac = wm_argc = 0; + + wm_argv = (char **)malloc((saved_argc + 5) * sizeof(char *)); + if (wm_argv == (char **)0) + { + if (!quiet) + fprintf(stderr, "%s: warning: malloc failed in wm_save_yourself.\n", + progname); + XSetCommand(dpy, mainW, saved_argv, saved_argc); + return; + } + + while (saved_argv[ac]) + { + if (!strcmp(saved_argv[ac], "-geometry")) + { + ac += 2; + continue; + } + if (!strcmp(saved_argv[ac], "-iconGeom")) + { + ac += 2; + continue; + } + if (!strcmp(saved_argv[ac], "-iconic")) + { + ac++; + continue; + } + wm_argv[wm_argc++] = saved_argv[ac++]; + } + + wm_argv[wm_argc++] = "-geometry"; + get_geometry_string(mainW, geom, 1); + wm_argv[wm_argc++] = geom; + + wm_argv[wm_argc++] = "-iconGeom"; + get_geometry_string(iconW, icon_geom, 0); + wm_argv[wm_argc++] = icon_geom; + + XGetWindowAttributes(dpy, mainW, &xwa); + if (xwa.map_state == IsUnmapped) + { + wm_argv[wm_argc++] = "-iconic"; + } + wm_argv[wm_argc] = (char *)0; + + XSetCommand(dpy, mainW, wm_argv, wm_argc); +} + +void +#ifdef __FunctionProto__ +exit_x48(int tell_x11) +#else +exit_x48(tell_x11) +int tell_x11; +#endif +{ + exit_emulator(); + if (tell_x11) + XCloseDisplay(dpy); + exit (0); +} + +int +#ifdef __FunctionProto__ +decode_key(XEvent *xev, KeySym sym, char *buf, int buflen) +#else +decode_key(xev, sym, buf, buflen) +XEvent *xev; +KeySym sym; +char *buf; +int buflen; +#endif +{ + int wake; + + wake = 0; + if (buflen == 1) + switch (buf[0]) { + case '0': + sym = XK_0; + break; + case '1': + sym = XK_1; + break; + case '2': + sym = XK_2; + break; + case '3': + sym = XK_3; + break; + case '4': + sym = XK_4; + break; + case '5': + sym = XK_5; + break; + case '6': + sym = XK_6; + break; + case '7': + sym = XK_7; + break; + case '8': + sym = XK_8; + break; + case '9': + sym = XK_9; + break; + default: + break; + } + + switch ((int)sym) { + case XK_KP_0: + case XK_0: + key_event(BUTTON_0, xev); + wake = 1; + break; + case XK_KP_1: + case XK_1: + key_event(BUTTON_1, xev); + wake = 1; + break; + case XK_KP_2: + case XK_2: + key_event(BUTTON_2, xev); + wake = 1; + break; + case XK_KP_3: + case XK_3: + key_event(BUTTON_3, xev); + wake = 1; + break; + case XK_KP_4: + case XK_4: + key_event(BUTTON_4, xev); + wake = 1; + break; + case XK_KP_5: + case XK_5: + key_event(BUTTON_5, xev); + wake = 1; + break; + case XK_KP_6: + case XK_6: + key_event(BUTTON_6, xev); + wake = 1; + break; + case XK_KP_7: + case XK_7: + key_event(BUTTON_7, xev); + wake = 1; + break; + case XK_KP_8: + case XK_8: + key_event(BUTTON_8, xev); + wake = 1; + break; + case XK_KP_9: + case XK_9: + key_event(BUTTON_9, xev); + wake = 1; + break; + case XK_KP_Add: + case XK_plus: + case XK_equal: + key_event(BUTTON_PLUS, xev); + wake = 1; + break; + case XK_KP_Subtract: + case XK_minus: + key_event(BUTTON_MINUS, xev); + wake = 1; + break; +#ifdef XK_F25 + case XK_F25: +#endif + case XK_KP_Divide: + case XK_slash: + key_event(BUTTON_DIV, xev); + wake = 1; + break; +#ifdef XK_F26 + case XK_F26: +#endif + case XK_KP_Multiply: + case XK_asterisk: + key_event(BUTTON_MUL, xev); + wake = 1; + break; + case XK_KP_Enter: + case XK_Return: + key_event(BUTTON_ENTER, xev); + wake = 1; + break; + case XK_KP_Decimal: + case XK_KP_Separator: + case XK_period: + key_event(BUTTON_PERIOD, xev); + wake = 1; + break; + case XK_space: + key_event(BUTTON_SPC, xev); + wake = 1; + break; + case XK_Delete: + key_event(BUTTON_DEL, xev); + wake = 1; + break; + case XK_BackSpace: + key_event(BUTTON_BS, xev); + wake = 1; + break; + case XK_Escape: + key_event(BUTTON_ON, xev); + wake = 1; + break; + case XK_Shift_L: + case XK_Control_R: + key_event(BUTTON_SHL, xev); + wake = 1; + break; + case XK_Shift_R: + case XK_Control_L: + key_event(BUTTON_SHR, xev); + wake = 1; + break; + case XK_Alt_L: + case XK_Alt_R: + case XK_Meta_L: + case XK_Meta_R: + key_event(BUTTON_ALPHA, xev); + wake = 1; + break; + case XK_a: + case XK_A: + case XK_F1: + key_event(BUTTON_A, xev); + wake = 1; + break; + case XK_b: + case XK_B: + case XK_F2: + key_event(BUTTON_B, xev); + wake = 1; + break; + case XK_c: + case XK_C: + case XK_F3: + key_event(BUTTON_C, xev); + wake = 1; + break; + case XK_d: + case XK_D: + case XK_F4: + key_event(BUTTON_D, xev); + wake = 1; + break; + case XK_e: + case XK_E: + case XK_F5: + key_event(BUTTON_E, xev); + wake = 1; + break; + case XK_f: + case XK_F: + case XK_F6: + key_event(BUTTON_F, xev); + wake = 1; + break; + case XK_g: + case XK_G: + key_event(BUTTON_MTH, xev); + wake = 1; + break; + case XK_h: + case XK_H: + key_event(BUTTON_PRG, xev); + wake = 1; + break; + case XK_i: + case XK_I: + key_event(BUTTON_CST, xev); + wake = 1; + break; + case XK_j: + case XK_J: + key_event(BUTTON_VAR, xev); + wake = 1; + break; + case XK_k: + case XK_K: + case XK_Up: + key_event(BUTTON_UP, xev); + wake = 1; + break; + case XK_l: + case XK_L: + key_event(BUTTON_NXT, xev); + wake = 1; + break; + case XK_m: + case XK_M: + key_event(BUTTON_COLON, xev); + wake = 1; + break; + case XK_n: + case XK_N: + key_event(BUTTON_STO, xev); + wake = 1; + break; + case XK_o: + case XK_O: + key_event(BUTTON_EVAL, xev); + wake = 1; + break; + case XK_p: + case XK_P: + case XK_Left: + key_event(BUTTON_LEFT, xev); + wake = 1; + break; + case XK_q: + case XK_Q: + case XK_Down: + key_event(BUTTON_DOWN, xev); + wake = 1; + break; + case XK_r: + case XK_R: + case XK_Right: + key_event(BUTTON_RIGHT, xev); + wake = 1; + break; + case XK_s: + case XK_S: + key_event(BUTTON_SIN, xev); + wake = 1; + break; + case XK_t: + case XK_T: + key_event(BUTTON_COS, xev); + wake = 1; + break; + case XK_u: + case XK_U: + key_event(BUTTON_TAN, xev); + wake = 1; + break; + case XK_v: + case XK_V: + key_event(BUTTON_SQRT, xev); + wake = 1; + break; + case XK_w: + case XK_W: + key_event(BUTTON_POWER, xev); + wake = 1; + break; + case XK_x: + case XK_X: + key_event(BUTTON_INV, xev); + wake = 1; + break; + case XK_y: + case XK_Y: + key_event(BUTTON_NEG, xev); + wake = 1; + break; + case XK_z: + case XK_Z: + key_event(BUTTON_EEX, xev); + wake = 1; + break; + default: + break; + } + return wake; +} + +#define MAX_PASTE 128 +int paste[MAX_PASTE*3]; +int paste_count = 0; +int paste_size = 0; +int paste_last_key = 0; + +int first_key = 0; + +int last_button = -1; + +extern char *get_stack(void); + +int +#ifdef __FunctionProto__ +GetEvent(void) +#else +GetEvent() +#endif +{ + XEvent xev; + XClientMessageEvent *cm; + int i, wake, bufs = 2; + char buf[2]; + KeySym sym; + int button_expose; + static int button_leave = -1; + static int release_pending = 0; + static XKeyEvent release_event; + static Time last_release_time = 0; + + wake = 0; + if (paste_last_key) + { + button_released (paste[paste_count - 1]); + paste_last_key = 0; + return 1; + } + else if (paste_count < paste_size) + { + button_pressed (paste[paste_count]); + paste_last_key = 1; + paste_count++; + return 1; + } + + if (release_pending) + { + i = XLookupString (&release_event, buf, bufs, &sym, NULL); + wake = decode_key ((XEvent *) & release_event, sym, buf, i); + release_pending = 0; + return wake; + } + + do + { + while (XPending (dpy) > 0) + { + + XNextEvent (dpy, &xev); + + switch ((int) xev.type) + { + + case KeyPress: + + if (0 && release_pending) + { + printf ("xxx release_pending\n"); + } + release_pending = 0; + if ((xev.xkey.time - last_release_time) <= 1) + { + release_pending = 0; + break; + } + + i = XLookupString (&xev.xkey, buf, bufs, &sym, NULL); + wake = decode_key (&xev, sym, buf, i); + first_key = 1; + break; + + case KeyRelease: + + i = XLookupString (&xev.xkey, buf, bufs, &sym, NULL); + first_key = 0; + release_pending = 1; + last_release_time = xev.xkey.time; + memcpy (&release_event, &xev, sizeof (XKeyEvent)); + break; + + case NoExpose: + + break; + + case Expose: + + if (xev.xexpose.count == 0) + { + if (xev.xexpose.window == disp.win) + { + DrawDisp (); + } + else if (xev.xexpose.window == iconW) + { + DrawIcon (); + } + else if (xev.xexpose.window == mainW) + { + DrawKeypad(&keypad); + } + else + for (i = BUTTON_A; i <= LAST_BUTTON; i++) + { + if (xev.xexpose.window == buttons[i].xwin) + { + DrawButton (i); + break; + } + } + } + break; + case UnmapNotify: + + disp.mapped = 0; + break; + + case MapNotify: + + if (!disp.mapped) + { + disp.mapped = 1; + update_display (); + redraw_annunc (); + } + break; + + case ButtonPress: + + if (xev.xbutton.subwindow == disp.win) + { + if (xev.xbutton.button == Button2) + { + if (xev.xbutton.subwindow == disp.win) + { + int x; + int flag = 0; + char *paste_in = XFetchBuffer (dpy, &x, 0); + + char *p = paste_in; + if (x > MAX_PASTE) + { + x = 0; + printf ("input too long. limit is %d characters\n", + MAX_PASTE); + } + paste_count = 0; + paste_size = 0; + while (x--) + { + char c = *p++; + switch (c) + { + case '.': + paste[paste_size++] = BUTTON_PERIOD; + break; + case '0': + paste[paste_size++] = BUTTON_0; + break; + case '1': + paste[paste_size++] = BUTTON_1; + break; + case '2': + paste[paste_size++] = BUTTON_2; + break; + case '3': + paste[paste_size++] = BUTTON_3; + break; + case '4': + paste[paste_size++] = BUTTON_4; + break; + case '5': + paste[paste_size++] = BUTTON_5; + break; + case '6': + paste[paste_size++] = BUTTON_6; + break; + case '7': + paste[paste_size++] = BUTTON_7; + break; + case '8': + paste[paste_size++] = BUTTON_8; + break; + case '9': + paste[paste_size++] = BUTTON_9; + break; + case '\n': + paste[paste_size++] = BUTTON_SHR; + paste[paste_size++] = BUTTON_PERIOD; + break; + case '!': + paste[paste_size++] = BUTTON_ALPHA; + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_DEL; + break; + case '+': + paste[paste_size++] = BUTTON_ALPHA; + paste[paste_size++] = BUTTON_PLUS; + break; + case '-': + paste[paste_size++] = BUTTON_ALPHA; + paste[paste_size++] = BUTTON_MINUS; + break; + case '*': + paste[paste_size++] = BUTTON_ALPHA; + paste[paste_size++] = BUTTON_MUL; + break; + case '/': + paste[paste_size++] = BUTTON_ALPHA; + paste[paste_size++] = BUTTON_DIV; + break; + case ' ': + paste[paste_size++] = 47; + break; + case '(': + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_DIV; + break; + case '[': + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_MUL; + break; + case '<': + if (x > 1 && *p == '<') + { + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_MINUS; + x--; + p++; + } + else + { + paste[paste_size++] = BUTTON_ALPHA; + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_2; + } + break; + case '{': + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_PLUS; + break; + case ')': + case ']': + case '}': + paste[paste_size++] = BUTTON_RIGHT; + break; + case '>': + if (x > 1 && *p == '>') + { + paste[paste_size++] = BUTTON_RIGHT; + paste[paste_size++] = BUTTON_RIGHT; + paste[paste_size++] = BUTTON_RIGHT; + x--; + p++; + } + else + { + paste[paste_size++] = BUTTON_ALPHA; + paste[paste_size++] = BUTTON_SHR; + paste[paste_size++] = BUTTON_2; + } + break; + case '#': + paste[paste_size++] = BUTTON_SHR; + paste[paste_size++] = BUTTON_DIV; + break; + case '_': + paste[paste_size++] = BUTTON_SHR; + paste[paste_size++] = BUTTON_MUL; + break; + case '"': + if (flag & 1) + { + flag &= ~1; + paste[paste_size++] = BUTTON_RIGHT; + } + else + { + flag |= 1; + paste[paste_size++] = BUTTON_SHR; + paste[paste_size++] = BUTTON_MINUS; + } + break; + case ':': + if (flag & 2) + { + flag &= ~2; + paste[paste_size++] = BUTTON_RIGHT; + } + else + { + flag |= 2; + paste[paste_size++] = BUTTON_SHR; + paste[paste_size++] = BUTTON_PLUS; + } + break; + case '\'': + if (flag & 4) + { + flag &= ~4; + paste[paste_size++] = BUTTON_RIGHT; + } + else + { + flag |= 4; + paste[paste_size++] = BUTTON_COLON; + } + break; + case 'a': + case 'A': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_A; + break; + case 'b': + case 'B': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_B; + break; + case 'c': + case 'C': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_C; + break; + case 'd': + case 'D': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_D; + break; + case 'e': + case 'E': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_E; + break; + case 'f': + case 'F': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_F; + break; + case 'g': + case 'G': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_MTH; + break; + case 'h': + case 'H': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_PRG; + break; + case 'i': + case 'I': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_CST; + break; + case 'j': + case 'J': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_VAR; + break; + case 'k': + case 'K': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_UP; + break; + case 'l': + case 'L': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_NXT; + break; + + case 'm': + case 'M': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_COLON; + break; + case 'n': + case 'N': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_STO; + break; + case 'o': + case 'O': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_EVAL; + break; + case 'p': + case 'P': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_LEFT; + break; + case 'q': + case 'Q': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_DOWN; + break; + case 'r': + case 'R': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_RIGHT; + break; + case 's': + case 'S': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_SIN; + break; + case 't': + case 'T': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_COS; + break; + case 'u': + case 'U': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_TAN; + break; + case 'v': + case 'V': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_SQRT; + break; + case 'w': + case 'W': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_POWER; + break; + case 'x': + case 'X': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_INV; + break; + case 'y': + case 'Y': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_NEG; + break; + case 'z': + case 'Z': + paste[paste_size++] = BUTTON_ALPHA; + if (islower (c)) + paste[paste_size++] = BUTTON_SHL; + paste[paste_size++] = BUTTON_EEX; + break; + default: + printf ("unknown %c %d\n", c, *p); + break; + } + } + if (paste_in) + XFree (paste_in); + if (paste_size) + { + return 1; + } + } + } + else if (xev.xbutton.button == Button3) + { + /* TODO Make cut from the screen work. */ + get_stack(); + } + else + { +/* printf("In display %d\n", xev.xbutton.button); */ + } + } + else + { + if (xev.xbutton.button == Button1 + || xev.xbutton.button == Button2 + || xev.xbutton.button == Button3 + ) + { + for (i = BUTTON_A; i <= LAST_BUTTON; i++) + { + if (xev.xbutton.subwindow == buttons[i].xwin) + { + if (buttons[i].pressed) + { + if (xev.xbutton.button == Button3 + ) + { + button_released (i); + DrawButton (i); + } + } + else + { + last_button = i; + button_pressed (i); + wake = 1; + first_key = 1; + DrawButton (i); + } + break; + } + } + } + } + break; + + case ButtonRelease: + + first_key = 0; + if (xev.xbutton.button == Button1) + { + button_release_all (); + } + if (xev.xbutton.button == Button2) + { + if (last_button >= 0) + { + button_released (last_button); + DrawButton (last_button); + } + last_button = -1; + } + break; + + case FocusOut: + first_key = 0; + button_release_all(); + break; + + case MappingNotify: + + switch (xev.xmapping.request) + { + case MappingModifier: + case MappingKeyboard: + XRefreshKeyboardMapping (&xev.xmapping); + break; + case MappingPointer: + default: + break; + } + break; + + case EnterNotify: + case LeaveNotify: + + break; + + case ClientMessage: + + cm = (XClientMessageEvent *) & xev; + + if (cm->message_type == wm_protocols) + { + if (cm->data.l[0] == wm_delete_window) + { + /* + * Quit selected from window managers menu + */ + exit_x48 (1); + } + + if (cm->data.l[0] == wm_save_yourself) + { + save_command_line (); + } + } + break; + + default: + +#ifdef DEBUG_XEVENT + printf ("Event: %d\n", xev.type); +#endif + case KeymapNotify: + case ConfigureNotify: + case ReparentNotify: + break; + + } + } + } + while (first_key > 1); + if (first_key) + { + first_key++; + } + return wake; +} + +/* eof */ diff --git a/src/x48_x11.h b/src/x48_x11.h new file mode 100644 index 0000000..b14a0fb --- /dev/null +++ b/src/x48_x11.h @@ -0,0 +1,149 @@ +/* + * This file is part of x48, an emulator of the HP-48sx Calculator. + * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Log: x48_x11.h,v $ + * Revision 1.11 1995/01/11 18:20:01 ecd + * major update to support HP48 G/GX + * + * Revision 1.10 1994/12/07 20:16:41 ecd + * added "refresh_icon" + * + * Revision 1.10 1994/12/07 20:16:41 ecd + * added "refresh_icon" + * + * Revision 1.9 1994/11/28 02:19:22 ecd + * added support for contrast adjustment + * + * Revision 1.8 1994/11/04 03:44:47 ecd + * added support for mono and gray displays + * + * Revision 1.7 1994/11/02 14:51:27 ecd + * minor fix + * + * Revision 1.6 1994/10/09 20:26:35 ecd + * changed disp_t + * + * Revision 1.5 1994/10/06 16:29:28 ecd + * added XShm - Extension stuff + * + * Revision 1.4 1994/10/05 08:33:22 ecd + * changed disp_t: removed Pixmap + * + * Revision 1.3 1994/09/30 12:32:49 ecd + * changed display stuff, added detection of interrupts in GetEvent + * + * Revision 1.2 1994/09/18 15:31:58 ecd + * started Real Time support + * + * Revision 1.1 1994/09/13 15:05:11 ecd + * Initial revision + * + * + * $Id: x48_x11.h,v 1.11 1995/01/11 18:20:01 ecd Exp ecd $ + */ + +#ifndef _X48_X11_H +#define _X48_X11_H 1 + +#include "global.h" + +#include +#ifdef HAVE_XSHM +#include +#include +#include +#endif + +#define WHITE 0 +#define LEFT 1 +#define RIGHT 2 +#define BUT_TOP 3 +#define BUTTON 4 +#define BUT_BOT 5 +#define LCD 6 +#define PIXEL 7 +#define PAD_TOP 8 +#define PAD 9 +#define PAD_BOT 10 +#define DISP_PAD_TOP 11 +#define DISP_PAD 12 +#define DISP_PAD_BOT 13 +#define LOGO 14 +#define LOGO_BACK 15 +#define LABEL 16 +#define FRAME 17 +#define UNDERLAY 18 +#define BLACK 19 + +typedef struct color_t { + char *name; + int r, g, b; + int mono_rgb; + int gray_rgb; + XColor xcolor; +} color_t; + +extern color_t *colors; + +#define COLOR(c) (colors[(c)].xcolor.pixel) + +#define UPDATE_MENU 1 +#define UPDATE_DISP 2 + +typedef struct disp_t { + unsigned int w, h; + Window win; + GC gc; + short mapped; + int offset; + int lines; +#ifdef HAVE_XSHM + int display_update; + XShmSegmentInfo disp_info; + XImage *disp_image; + XShmSegmentInfo menu_info; + XImage *menu_image; +#endif +} disp_t; + +extern disp_t disp; + +#ifdef HAVE_XSHM +extern int shm_flag; +#endif + +extern Display *dpy; +extern int screen; + +extern int InitDisplay __ProtoType__((int argc, char **argv)); +extern int CreateWindows __ProtoType__((int argc, char **argv)); +extern int GetEvent __ProtoType__((void)); + +extern void adjust_contrast __ProtoType__((int contrast)); +extern void refresh_icon __ProtoType__((void)); + +extern void ShowConnections __ProtoType__((char *w, char *i)); + +extern void exit_x48 __ProtoType__((int tell_x11)); + +#ifdef HAVE_XSHM +extern void refresh_display __ProtoType__((void)); +#endif + +#endif /* !_X48_X11_H */ diff --git a/utils/ad2c b/utils/ad2c new file mode 100755 index 0000000..1435e55 --- /dev/null +++ b/utils/ad2c @@ -0,0 +1,38 @@ +#!/bin/sh +# +# ad2c : Convert app-defaults file to C strings decls. +# +# George Ferguson, ferguson@cs.rcohester.edu, 12 Nov 1990. +# 19 Mar 1991 : gf +# Made it self-contained. +# 6 Jan 1992 : mycroft@gnu.ai.mit.edu (Charles Hannum) +# Removed use of "-n" and ":read" label since Gnu and +# IBM sed print pattern space on "n" command. Still works +# with Sun sed, of course. +# 7 Jan 1992: matthew@sunpix.East.Sun.COM (Matthew Stier) +# Escape quotes after escaping backslashes. +# + +sed ' +/^!/d +/^$/d +s/\\/\\\\/g +s/\\$//g +s/"/\\"/g +s/^/"/ +: test +/\\$/b slash +s/$/",/ +p +d +: slash +n +/^!/d +/^$/d +s/"/\\"/g +s/\\\\/\\/g +s/\\n/\\\\n/g +s/\\t/\\\\t/g +s/\\f/\\\\f/g +s/\\b/\\\\b/g +b test' "$@" diff --git a/utils/makeversion b/utils/makeversion new file mode 100755 index 0000000..5c7696d --- /dev/null +++ b/utils/makeversion @@ -0,0 +1,14 @@ +#! /bin/sh + +if [ ! -f .version ] +then + echo 0 > .version +fi +cycle=`cat .version` +cycle=`expr $cycle + 1` +if [ $cycle -gt 255 ] +then + cycle=0 +fi +echo $cycle > .version + diff --git a/version.m4 b/version.m4 new file mode 100644 index 0000000..ea2102f --- /dev/null +++ b/version.m4 @@ -0,0 +1,6 @@ + +m4_define(_VERSION_MAJOR, [0]) +m4_define(_VERSION_MINOR, [6]) +m4_define(_PATCHLEVEL, [4]) + +m4_define(VERSION_NUMBER, [_VERSION_MAJOR._VERSION_MINOR._PATCHLEVEL]) diff --git a/x48-0.6.4.tar.bz2 b/x48-0.6.4.tar.bz2 new file mode 100644 index 0000000..d61ce02 Binary files /dev/null and b/x48-0.6.4.tar.bz2 differ