From e59ca61c98b9e4ea32ca4c257dda00dbb9e1a1a3 Mon Sep 17 00:00:00 2001 From: Gwenhael Le Moine Date: Sun, 26 Jul 2015 11:16:05 +0200 Subject: [PATCH] import of sources from latest release found on Sourceforge Signed-off-by: Gwenhael Le Moine --- AUTHORS | 4 + ChangeLog | 40 + INSTALL | 9 + MANIFEST | 75 + Makefile.am | 17 + NEWS | 1 + README | 356 +++ autogen.sh | 9 + configure.ac | 139 ++ debian/README.Debian | 9 + debian/changelog | 66 + debian/compat | 1 + debian/control | 13 + debian/copyright | 27 + debian/dirs | 1 + debian/docs | 1 + debian/menu | 2 + debian/rules | 89 + debian/watch | 6 + doc/CARDS.doc | 16 + doc/COPYING | 339 +++ doc/ChangeLog | 190 ++ doc/INSTALLING | 34 + doc/ROMDump.doc | 36 + doc/TODO | 35 + romdump/Makefile.am | 4 + romdump/README | 63 + romdump/ROMDump | Bin 0 -> 561 bytes romdump/ROMDump.s | 464 ++++ rpm/x48.spec.in | 45 + src/Makefile.am | 68 + src/X48.ad | 68 + src/X48.ad.h | 24 + src/actions.c | 1087 +++++++++ src/annunc.h | 55 + src/append.h | 45 + src/bitmaps/A.h | 5 + src/bitmaps/B.h | 5 + src/bitmaps/C.h | 5 + src/bitmaps/D.h | 5 + src/bitmaps/E.h | 5 + src/bitmaps/F.h | 5 + src/bitmaps/G.h | 5 + src/bitmaps/H.h | 5 + src/bitmaps/I.h | 5 + src/bitmaps/J.h | 5 + src/bitmaps/K.h | 5 + src/bitmaps/L.h | 5 + src/bitmaps/M.h | 5 + src/bitmaps/N.h | 5 + src/bitmaps/O.h | 5 + src/bitmaps/P.h | 5 + src/bitmaps/Q.h | 5 + src/bitmaps/R.h | 5 + src/bitmaps/S.h | 5 + src/bitmaps/T.h | 5 + src/bitmaps/U.h | 5 + src/bitmaps/V.h | 5 + src/bitmaps/W.h | 5 + src/bitmaps/X.h | 5 + src/bitmaps/Y.h | 5 + src/bitmaps/Z.h | 5 + src/bitmaps/alpha.h | 6 + src/bitmaps/angle.h | 5 + src/bitmaps/angle_gx.h | 6 + src/bitmaps/ann_alpha.h | 6 + src/bitmaps/ann_battery.h | 6 + src/bitmaps/ann_busy.h | 6 + src/bitmaps/ann_io.h | 6 + src/bitmaps/ann_left.h | 6 + src/bitmaps/ann_right.h | 6 + src/bitmaps/arrow.h | 5 + src/bitmaps/arrow_gx.h | 7 + src/bitmaps/blank.h | 5 + src/bitmaps/bracket_gx.h | 6 + src/bitmaps/bs.h | 6 + src/bitmaps/colon.h | 5 + src/bitmaps/colon_gx.h | 5 + src/bitmaps/comma.h | 5 + src/bitmaps/comma_gx.h | 5 + src/bitmaps/curly_gx.h | 6 + src/bitmaps/diff.h | 5 + src/bitmaps/div.h | 6 + src/bitmaps/down.h | 6 + src/bitmaps/equal.h | 5 + src/bitmaps/equal_gx.h | 5 + src/bitmaps/exp.h | 6 + src/bitmaps/exp_gx.h | 5 + src/bitmaps/gx_128K_ram.h | 20 + src/bitmaps/gx_green.h | 14 + src/bitmaps/gx_silver.h | 13 + src/bitmaps/hash.h | 5 + src/bitmaps/hash_gx.h | 5 + src/bitmaps/hp.h | 28 + src/bitmaps/hp48_blue.h | 9 + src/bitmaps/hp48_bottom.h | 26 + src/bitmaps/hp48_disp.h | 11 + src/bitmaps/hp48_green_gx.h | 23 + src/bitmaps/hp48_icon.h | 26 + src/bitmaps/hp48_keys.h | 25 + src/bitmaps/hp48_logo.h | 5 + src/bitmaps/hp48_logo_gx.h | 5 + src/bitmaps/hp48_on.h | 11 + src/bitmaps/hp48_orange.h | 9 + src/bitmaps/hp48_text.h | 7 + src/bitmaps/hp48_text_gx.h | 7 + src/bitmaps/hp48_top.h | 14 + src/bitmaps/hp48_top_gx.h | 14 + src/bitmaps/hp48gx.h | 11 + src/bitmaps/hp48sx.h | 9 + src/bitmaps/integral.h | 5 + src/bitmaps/inv.h | 8 + src/bitmaps/last.h | 12 + src/bitmaps/lbrace.h | 5 + src/bitmaps/lbracket.h | 5 + src/bitmaps/lcurly.h | 5 + src/bitmaps/left.h | 6 + src/bitmaps/menu_label.h | 7 + src/bitmaps/minus.h | 6 + src/bitmaps/mul.h | 6 + src/bitmaps/neg.h | 7 + src/bitmaps/nl.h | 5 + src/bitmaps/nl_gx.h | 7 + src/bitmaps/parens_gx.h | 7 + src/bitmaps/pi.h | 5 + src/bitmaps/pi_gx.h | 6 + src/bitmaps/plus.h | 6 + src/bitmaps/pow10.h | 6 + src/bitmaps/pow10_gx.h | 6 + src/bitmaps/power.h | 8 + src/bitmaps/prog.h | 6 + src/bitmaps/prog_gx.h | 7 + src/bitmaps/quote_gx.h | 6 + src/bitmaps/rbrace.h | 5 + src/bitmaps/rbracket.h | 5 + src/bitmaps/rcurly.h | 5 + src/bitmaps/right.h | 6 + src/bitmaps/root.h | 8 + src/bitmaps/root_gx.h | 8 + src/bitmaps/science.h | 16 + src/bitmaps/shl.h | 8 + src/bitmaps/shr.h | 8 + src/bitmaps/sigma.h | 5 + src/bitmaps/slash.h | 5 + src/bitmaps/small_colon.h | 5 + src/bitmaps/sqr.h | 6 + src/bitmaps/sqr_gx.h | 7 + src/bitmaps/sqrt.h | 7 + src/bitmaps/string.h | 6 + src/bitmaps/three.h | 5 + src/bitmaps/two.h | 5 + src/bitmaps/under.h | 5 + src/bitmaps/under_gx.h | 6 + src/bitmaps/up.h | 6 + src/buttons.h | 84 + src/checkrom.c | 144 ++ src/constants.h | 48 + src/debugger.c | 2060 ++++++++++++++++ src/debugger.h | 66 + src/device.c | 209 ++ src/device.h | 131 + src/disasm.c | 1965 +++++++++++++++ src/disasm.h | 51 + src/dump2rom.c | 226 ++ src/emulate.c | 2491 +++++++++++++++++++ src/errors.c | 61 + src/errors.h | 37 + src/global.h | 154 ++ src/hp.h | 63 + src/hp48.h | 293 +++ src/hp48_emu.h | 202 ++ src/hp48char.h | 308 +++ src/icon.h | 74 + src/init.c | 1818 ++++++++++++++ src/lcd.c | 567 +++++ src/main.c | 265 +++ src/memory.c | 1535 ++++++++++++ src/mkcard.c | 130 + src/mmu.h | 53 + src/options.c | 178 ++ src/options.h | 121 + src/register.c | 799 +++++++ src/resources.c | 419 ++++ src/resources.h | 99 + src/romio.c | 242 ++ src/romio.h | 43 + src/rpl.c | 1556 ++++++++++++ src/rpl.h | 132 ++ src/serial.c | 727 ++++++ src/small.h | 329 +++ src/timer.c | 543 +++++ src/timer.h | 62 + src/version.h | 44 + src/x48.man.in | 289 +++ src/x48_x11.c | 4468 +++++++++++++++++++++++++++++++++++ src/x48_x11.h | 149 ++ utils/ad2c | 38 + utils/makeversion | 14 + version.m4 | 6 + x48-0.6.4.tar.bz2 | Bin 0 -> 109001 bytes 200 files changed, 27588 insertions(+) create mode 100644 AUTHORS create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 MANIFEST create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 README create mode 100755 autogen.sh create mode 100644 configure.ac create mode 100644 debian/README.Debian create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/dirs create mode 100644 debian/docs create mode 100644 debian/menu create mode 100755 debian/rules create mode 100644 debian/watch create mode 100644 doc/CARDS.doc create mode 100644 doc/COPYING create mode 100644 doc/ChangeLog create mode 100644 doc/INSTALLING create mode 100644 doc/ROMDump.doc create mode 100644 doc/TODO create mode 100644 romdump/Makefile.am create mode 100644 romdump/README create mode 100644 romdump/ROMDump create mode 100644 romdump/ROMDump.s create mode 100644 rpm/x48.spec.in create mode 100644 src/Makefile.am create mode 100644 src/X48.ad create mode 100644 src/X48.ad.h create mode 100644 src/actions.c create mode 100644 src/annunc.h create mode 100644 src/append.h create mode 100644 src/bitmaps/A.h create mode 100644 src/bitmaps/B.h create mode 100644 src/bitmaps/C.h create mode 100644 src/bitmaps/D.h create mode 100644 src/bitmaps/E.h create mode 100644 src/bitmaps/F.h create mode 100644 src/bitmaps/G.h create mode 100644 src/bitmaps/H.h create mode 100644 src/bitmaps/I.h create mode 100644 src/bitmaps/J.h create mode 100644 src/bitmaps/K.h create mode 100644 src/bitmaps/L.h create mode 100644 src/bitmaps/M.h create mode 100644 src/bitmaps/N.h create mode 100644 src/bitmaps/O.h create mode 100644 src/bitmaps/P.h create mode 100644 src/bitmaps/Q.h create mode 100644 src/bitmaps/R.h create mode 100644 src/bitmaps/S.h create mode 100644 src/bitmaps/T.h create mode 100644 src/bitmaps/U.h create mode 100644 src/bitmaps/V.h create mode 100644 src/bitmaps/W.h create mode 100644 src/bitmaps/X.h create mode 100644 src/bitmaps/Y.h create mode 100644 src/bitmaps/Z.h create mode 100644 src/bitmaps/alpha.h create mode 100644 src/bitmaps/angle.h create mode 100644 src/bitmaps/angle_gx.h create mode 100644 src/bitmaps/ann_alpha.h create mode 100644 src/bitmaps/ann_battery.h create mode 100644 src/bitmaps/ann_busy.h create mode 100644 src/bitmaps/ann_io.h create mode 100644 src/bitmaps/ann_left.h create mode 100644 src/bitmaps/ann_right.h create mode 100644 src/bitmaps/arrow.h create mode 100644 src/bitmaps/arrow_gx.h create mode 100644 src/bitmaps/blank.h create mode 100644 src/bitmaps/bracket_gx.h create mode 100644 src/bitmaps/bs.h create mode 100644 src/bitmaps/colon.h create mode 100644 src/bitmaps/colon_gx.h create mode 100644 src/bitmaps/comma.h create mode 100644 src/bitmaps/comma_gx.h create mode 100644 src/bitmaps/curly_gx.h create mode 100644 src/bitmaps/diff.h create mode 100644 src/bitmaps/div.h create mode 100644 src/bitmaps/down.h create mode 100644 src/bitmaps/equal.h create mode 100644 src/bitmaps/equal_gx.h create mode 100644 src/bitmaps/exp.h create mode 100644 src/bitmaps/exp_gx.h create mode 100644 src/bitmaps/gx_128K_ram.h create mode 100644 src/bitmaps/gx_green.h create mode 100644 src/bitmaps/gx_silver.h create mode 100644 src/bitmaps/hash.h create mode 100644 src/bitmaps/hash_gx.h create mode 100644 src/bitmaps/hp.h create mode 100644 src/bitmaps/hp48_blue.h create mode 100644 src/bitmaps/hp48_bottom.h create mode 100644 src/bitmaps/hp48_disp.h create mode 100644 src/bitmaps/hp48_green_gx.h create mode 100644 src/bitmaps/hp48_icon.h create mode 100644 src/bitmaps/hp48_keys.h create mode 100644 src/bitmaps/hp48_logo.h create mode 100644 src/bitmaps/hp48_logo_gx.h create mode 100644 src/bitmaps/hp48_on.h create mode 100644 src/bitmaps/hp48_orange.h create mode 100644 src/bitmaps/hp48_text.h create mode 100644 src/bitmaps/hp48_text_gx.h create mode 100644 src/bitmaps/hp48_top.h create mode 100644 src/bitmaps/hp48_top_gx.h create mode 100644 src/bitmaps/hp48gx.h create mode 100644 src/bitmaps/hp48sx.h create mode 100644 src/bitmaps/integral.h create mode 100644 src/bitmaps/inv.h create mode 100644 src/bitmaps/last.h create mode 100644 src/bitmaps/lbrace.h create mode 100644 src/bitmaps/lbracket.h create mode 100644 src/bitmaps/lcurly.h create mode 100644 src/bitmaps/left.h create mode 100644 src/bitmaps/menu_label.h create mode 100644 src/bitmaps/minus.h create mode 100644 src/bitmaps/mul.h create mode 100644 src/bitmaps/neg.h create mode 100644 src/bitmaps/nl.h create mode 100644 src/bitmaps/nl_gx.h create mode 100644 src/bitmaps/parens_gx.h create mode 100644 src/bitmaps/pi.h create mode 100644 src/bitmaps/pi_gx.h create mode 100644 src/bitmaps/plus.h create mode 100644 src/bitmaps/pow10.h create mode 100644 src/bitmaps/pow10_gx.h create mode 100644 src/bitmaps/power.h create mode 100644 src/bitmaps/prog.h create mode 100644 src/bitmaps/prog_gx.h create mode 100644 src/bitmaps/quote_gx.h create mode 100644 src/bitmaps/rbrace.h create mode 100644 src/bitmaps/rbracket.h create mode 100644 src/bitmaps/rcurly.h create mode 100644 src/bitmaps/right.h create mode 100644 src/bitmaps/root.h create mode 100644 src/bitmaps/root_gx.h create mode 100644 src/bitmaps/science.h create mode 100644 src/bitmaps/shl.h create mode 100644 src/bitmaps/shr.h create mode 100644 src/bitmaps/sigma.h create mode 100644 src/bitmaps/slash.h create mode 100644 src/bitmaps/small_colon.h create mode 100644 src/bitmaps/sqr.h create mode 100644 src/bitmaps/sqr_gx.h create mode 100644 src/bitmaps/sqrt.h create mode 100644 src/bitmaps/string.h create mode 100644 src/bitmaps/three.h create mode 100644 src/bitmaps/two.h create mode 100644 src/bitmaps/under.h create mode 100644 src/bitmaps/under_gx.h create mode 100644 src/bitmaps/up.h create mode 100644 src/buttons.h create mode 100644 src/checkrom.c create mode 100644 src/constants.h create mode 100644 src/debugger.c create mode 100644 src/debugger.h create mode 100644 src/device.c create mode 100644 src/device.h create mode 100644 src/disasm.c create mode 100644 src/disasm.h create mode 100644 src/dump2rom.c create mode 100644 src/emulate.c create mode 100644 src/errors.c create mode 100644 src/errors.h create mode 100644 src/global.h create mode 100644 src/hp.h create mode 100644 src/hp48.h create mode 100644 src/hp48_emu.h create mode 100644 src/hp48char.h create mode 100644 src/icon.h create mode 100644 src/init.c create mode 100644 src/lcd.c create mode 100644 src/main.c create mode 100644 src/memory.c create mode 100644 src/mkcard.c create mode 100644 src/mmu.h create mode 100644 src/options.c create mode 100644 src/options.h create mode 100644 src/register.c create mode 100644 src/resources.c create mode 100644 src/resources.h create mode 100644 src/romio.c create mode 100644 src/romio.h create mode 100644 src/rpl.c create mode 100644 src/rpl.h create mode 100644 src/serial.c create mode 100644 src/small.h create mode 100644 src/timer.c create mode 100644 src/timer.h create mode 100644 src/version.h create mode 100644 src/x48.man.in create mode 100644 src/x48_x11.c create mode 100644 src/x48_x11.h create mode 100755 utils/ad2c create mode 100755 utils/makeversion create mode 100644 version.m4 create mode 100644 x48-0.6.4.tar.bz2 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 0000000000000000000000000000000000000000..a8f101e8bdd865ed9df3153cede34712af7fa54a GIT binary patch literal 561 zcmeYW@CY!m&<&cadtrsdrhdVROuHE_++>=a88`t0M}3t(XdPqsG;IOp|+t2|A!y@)e0mNzZ$SG)N`1yFw}9B1R1h0{O2$Q z2>=N&tB#|!!HI#PV@dvuoYpIi004`VP()U zY+>j9_>m!Kqlow={_@yZEi@}{;*y=cMU|BlrbI!#6h4KxJ{qdJFHW~xn$I%)9 zL=gQQQ2iSnfJO@ZGX1!q?iiEdB{5|Ve-3^iw&#%Nu#XjHd9_@xt5SADd{+E>0b$h6eWU7sVWT85tm8gAlW}Ap-z>#>f-^ literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..d61ce02d7d34a86b603cfc5890d77d32179c2cfb GIT binary patch literal 109001 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 literal 0 HcmV?d00001