Compare commits

..

No commits in common. "main" and "develop" have entirely different histories.

109 changed files with 14585 additions and 9616 deletions

31
.gitignore vendored
View file

@ -1,5 +1,4 @@
src/*.o
src/ui4x/*.o
dist/pack
dist/saturn
@ -19,18 +18,18 @@ docs/saturn.pdf
docs/saturn.ps
docs/saturn.log
src/libChf/docs/chf.tps
src/libChf/docs/chf.tp
src/libChf/docs/chf.toc
src/libChf/docs/chf.pdf
src/libChf/docs/chf.log
src/libChf/docs/chf.info
src/libChf/docs/chf.fns
src/libChf/docs/chf.fn
src/libChf/docs/chf.cps
src/libChf/docs/chf.cp
src/libChf/docs/chf.aux
src/libChf/docs/chf.dvi
src/libChf/docs/chf.ps
src/libChf/libChf.a
src/libChf/src/*.o
libChf/docs/chf.tps
libChf/docs/chf.tp
libChf/docs/chf.toc
libChf/docs/chf.pdf
libChf/docs/chf.log
libChf/docs/chf.info
libChf/docs/chf.fns
libChf/docs/chf.fn
libChf/docs/chf.cps
libChf/docs/chf.cp
libChf/docs/chf.aux
libChf/docs/chf.dvi
libChf/docs/chf.ps
libChf/libChf.a
libChf/src/*.o

147
Makefile
View file

@ -1,4 +1,4 @@
# Simple Makefile to build saturn
# Simple Makefile to build saturn_bertolotti
#
# The cc-option function and the C{,PP}FLAGS logic were copied from the
# fsverity-utils project.
@ -6,45 +6,35 @@
# The governing license can be found in the LICENSE file or at
# https://opensource.org/license/MIT.
NAME = saturn
PREFIX = /usr
DOCDIR = $(PREFIX)/doc/saturn
VERSION_MAJOR = 5
VERSION_MINOR = 4
VERSION_MAJOR = 0
VERSION_MINOR = 0
PATCHLEVEL = 0
PREFIX ?= /usr
DOCDIR ?= $(PREFIX)/doc/$(NAME)
INFODIR ?= $(PREFIX)/info
LUA_VERSION ?= lua
PKG_CONFIG ?= pkg-config
OPTIM ?= 2
override CFLAGS := -O$(OPTIM) \
CFLAGS ?= -O$(OPTIM) \
-D_GNU_SOURCE=1 \
-DVERSION_MAJOR=$(VERSION_MAJOR) \
-DVERSION_MINOR=$(VERSION_MINOR) \
-DPATCHLEVEL=$(PATCHLEVEL) \
-I./src/ \
-I./src/libChf/src/ \
$(CFLAGS)
-I./libChf/src/
LIBS = -L./src/libChf -lChf
LIBS = -L./libChf -lChf
SDLCFLAGS = $(shell "$(PKG_CONFIG)" --cflags sdl2)
SDLLIBS = $(shell "$(PKG_CONFIG)" --libs sdl2)
SDLCFLAGS = $(shell pkg-config --cflags sdl2)
SDLLIBS = $(shell pkg-config --libs sdl2)
NCURSESCFLAGS = $(shell "$(PKG_CONFIG)" --cflags ncursesw)
NCURSESLIBS = $(shell "$(PKG_CONFIG)" --libs ncursesw)
### lua
LUACFLAGS = $(shell "$(PKG_CONFIG)" --cflags $(LUA_VERSION))
LUALIBS = $(shell "$(PKG_CONFIG)" --libs $(LUA_VERSION))
NCURSESCFLAGS = $(shell pkg-config --cflags ncursesw)
NCURSESLIBS = $(shell pkg-config --libs ncursesw)
FULL_WARNINGS = no
DOTOS = src/cpu.o \
src/debug.o \
src/dis.o \
src/disk_io.o \
src/disk_io_obj.o \
@ -58,39 +48,26 @@ DOTOS = src/cpu.o \
src/romram.o \
src/romram49.o \
src/serial.o \
src/x_func.o \
src/chf_messages.o \
src/main.o
src/x_func.o
DOTOS_UI4x = src/ui4x/config.o \
src/ui4x/fonts.o \
src/ui4x/48sx.o \
src/ui4x/48gx.o \
src/ui4x/49g.o \
src/ui4x/common.o \
src/ui4x/sdl2.o \
src/ui4x/ncurses.o \
src/ui4x/emulator.o
DOTOS_UI48 = src/ui48_config.o \
src/ui48_common.o \
src/ui48_sdl2.o \
src/ui48_ncurses.o \
src/ui48_emulator.o \
src/ui48_main.o
HEADERS = src/ui4x/bitmaps_misc.h \
src/ui4x/common.h \
src/ui4x/config.h \
src/ui4x/ncurses.h \
src/ui4x/sdl2.h \
src/ui4x/inner.h \
src/ui4x/emulator.h \
src/disk_io.h \
src/flash49.h \
src/keyb.h \
src/machdep.h \
src/modules.h \
src/monitor.h \
src/serial.h \
src/x_func.h \
src/chf_messages.h \
src/config.h \
src/cpu.h \
src/debug.h
MSFS = src/MSFs/cpu.msf \
src/MSFs/debug.msf \
src/MSFs/disk_io.msf \
src/MSFs/flash49.msf \
src/MSFs/modules.msf \
src/MSFs/saturn.msf \
src/MSFs/serial.msf \
src/MSFs/util.msf \
src/MSFs/x11.msf \
src/MSFs/x_func.msf \
libChf/src/chf.msf
MAKEFLAGS +=-j$(NUM_CORES) -l$(NUM_CORES)
@ -130,7 +107,6 @@ override CFLAGS := -std=c11 \
$(EXTRA_WARNING_FLAGS) \
$(SDLCFLAGS) \
$(NCURSESCFLAGS) \
$(LUACFLAGS) \
$(CFLAGS)
override CPPFLAGS := -I./src/ -D_GNU_SOURCE=1 \
@ -138,79 +114,88 @@ override CPPFLAGS := -I./src/ -D_GNU_SOURCE=1 \
.PHONY: all clean clean-all pretty-code install mrproper get-roms install
all: src/libChf/libChf.a dist/$(NAME) docs
all: libChf/libChf.a dist/saturn dist/saturn.cat docs
# Building
src/libChf/libChf.a:
make -C src/libChf #MT=yes
libChf/libChf.a:
make -C libChf
dist/$(NAME): $(DOTOS) $(DOTOS_UI4x) $(HEADERS) src/libChf/libChf.a
$(CC) $(DOTOS) $(DOTOS_UI4x) src/libChf/libChf.a -o $@ $(CFLAGS) $(LIBS) $(SDLLIBS) $(NCURSESLIBS) $(LUALIBS)
dist/saturn: $(DOTOS) $(DOTOS_UI48) libChf/libChf.a
$(CC) $^ -o $@ $(CFLAGS) $(LIBS) $(SDLLIBS) $(NCURSESLIBS)
dist/pack: src/pack.o src/disk_io.o src/debug.o src/libChf/libChf.a
dist/pack: src/pack.o src/disk_io.o src/debug.o libChf/libChf.a
# UNUSED
$(CC) $^ -o $@ $(CFLAGS) $(LIBS)
dist/saturn.cat: $(MSFS)
for msf in $? ; \
do gencat $@ $$msf ; \
done
doc:
make -C docs
# Cleaning
clean:
rm -f src/*.o
make -C src/libChf clean
make -C libChf clean
make -C docs clean
mrproper: clean
rm -f dist/$(NAME) dist/pack
rm -f dist/saturn dist/saturn.cat dist/pack
make -C dist/ROMs mrproper
make -C src/libChf mrproper
make -C libChf mrproper
make -C docs mrproper
clean-all: mrproper
# Formatting
pretty-code:
clang-format -i src/*.c src/*.h src/ui4x/*.c src/ui4x/*.h
make -C src/libChf pretty-code
clang-format -i src/*.c src/*.h
make -C libChf pretty-code
# Dependencies
get-roms:
make -C dist/ROMs get-roms
# Installation
install: dist/$(NAME) doc
install: dist/saturn dist/saturn.cat dist/Saturn.ad doc
install -m 755 -d -- $(DESTDIR)$(PREFIX)/bin
install -c -m 755 dist/$(NAME) $(DESTDIR)$(PREFIX)/bin/$(NAME)
install -c -m 755 dist/saturn $(DESTDIR)$(PREFIX)/bin/saturn
install -c -m 755 dist/saturn48gx $(DESTDIR)$(PREFIX)/bin/saturn48gx
install -c -m 755 dist/saturn48sx $(DESTDIR)$(PREFIX)/bin/saturn48sx
install -c -m 755 dist/saturn40g $(DESTDIR)$(PREFIX)/bin/saturn40g
install -c -m 755 dist/saturn49g $(DESTDIR)$(PREFIX)/bin/saturn49g
install -m 755 -d -- $(DESTDIR)$(PREFIX)/share/$(NAME)
install -c -m 644 dist/hplogo.png $(DESTDIR)$(PREFIX)/share/$(NAME)/hplogo.png
cp -R dist/ROMs/ $(DESTDIR)$(PREFIX)/share/$(NAME)/
install -c -m 644 dist/saturn.cat $(DESTDIR)$(PREFIX)/bin/saturn.cat #FIXME
install -m 755 -d -- $(DESTDIR)$(PREFIX)/share/locale/C/LC_MESSAGES
install -c -m 644 dist/saturn.cat $(DESTDIR)$(PREFIX)/share/locale/C/LC_MESSAGES/saturn.cat
install -m 755 -d -- $(DESTDIR)$(PREFIX)/share/saturn
install -c -m 644 dist/saturn.cat $(DESTDIR)$(PREFIX)/share/saturn.cat #FIXME
install -c -m 644 dist/hplogo.png $(DESTDIR)$(PREFIX)/share/saturn/hplogo.png
cp -R dist/ROMs/ $(DESTDIR)$(PREFIX)/share/saturn/
install -m 755 -d -- $(DESTDIR)/etc/X11/app-defaults
install -c -m 644 dist/Saturn.ad $(DESTDIR)/etc/X11/app-defaults/Saturn
install -m 755 -d -- $(DESTDIR)$(DOCDIR)
cp -R COPYING LICENSE README* ./*.png docs-4.1.1.1 docs/*.{dvi,ps,pdf} $(DESTDIR)$(DOCDIR)
install -m 755 -d -- $(DESTDIR)$(INFODIR)
cp docs/*.info $(DESTDIR)$(INFODIR)
cp -R COPYING LICENSE README* docs* docs/ $(DESTDIR)$(DOCDIR)
install -m 755 -d -- $(DESTDIR)$(PREFIX)/share/applications
sed "s|@PREFIX@|$(PREFIX)|g" dist/saturn48gx.desktop > $(DESTDIR)$(PREFIX)/share/applications/saturn48gx.desktop
sed "s|@PREFIX@|$(PREFIX)|g" dist/saturn48sx.desktop > $(DESTDIR)$(PREFIX)/share/applications/saturn48sx.desktop
sed "s|@PREFIX@|$(PREFIX)|g" dist/saturn49g.desktop > $(DESTDIR)$(PREFIX)/share/applications/saturn49g.desktop
sed "s|@PREFIX@|$(PREFIX)|g" dist/saturn40g.desktop > $(DESTDIR)$(PREFIX)/share/applications/saturn40g.desktop
uninstall:
rm -f $(DESTDIR)$(PREFIX)/bin/$(NAME)
rm -f $(DESTDIR)$(PREFIX)/bin/saturn
rm -f $(DESTDIR)$(PREFIX)/bin/saturn48gx
rm -f $(DESTDIR)$(PREFIX)/bin/saturn48sx
rm -f $(DESTDIR)$(PREFIX)/bin/saturn40g
rm -f $(DESTDIR)$(PREFIX)/bin/saturn49g
rm -fr $(DESTDIR)$(PREFIX)/share/$(NAME)
rm -f $(DESTDIR)$(PREFIX)/bin/saturn.cat
rm -f $(DESTDIR)$(PREFIX)/share/locale/C/LC_MESSAGES/saturn.cat
rm -fr $(DESTDIR)$(PREFIX)/share/saturn
rm -f $(DESTDIR)/etc/X11/app-defaults/Saturn
rm -fr $(DESTDIR)$(DOCDIR)
rm -f $(DESTDIR)$(PREFIX)/share/applications/saturn48gx.desktop
rm -f $(DESTDIR)$(PREFIX)/share/applications/saturn48sx.desktop
rm -f $(DESTDIR)$(PREFIX)/share/applications/saturn49g.desktop
rm -f $(DESTDIR)$(PREFIX)/share/applications/saturn40g.desktop

View file

@ -1,24 +1,7 @@
# Emulator of the HP 49G, HP 48 (GX & SX), and HP 40G
**This is a fork of saturn v4.1.1.1 originally by Ivan Cibrario Bertolotti.**
Original source are available at https://www.hpcalc.org/details/4382
The GUI has been replaced by a new one (taken from x48ng) in SDL2 and/or ncurses.
## Screenshots
![screenshot of saturn49g](./saturn49g.png?raw=true "screenshot of saturn49g")
![screenshot of saturn48gx](./saturn48gx.png?raw=true "screenshot of saturn48gx")
![screenshot of saturn48sx](./saturn48sx.png?raw=true "screenshot of saturn48sx")
# Emulator of the HP 48GX, HP 49, and HP 40
## Building
Dependencies:
- SDL2
- ncursesw
``` shell
make
```
@ -29,24 +12,31 @@ make install DESTDIR=/
```
## Using
The main binary is `dist/saturn` with helpers/wrappers scripts available per model as:
* `dist/saturn48gx`
* `dist/saturn48sx`
* `dist/saturn49g`
* `dist/saturn40g` (not really functional (yet))
The local data are stored under `$XDG_CONFIG_HOME/saturn<model>/`.
### locally
``` shell
./dist/run48.sh
```
The scripts will take care of creating `$XDG_CONFIG_HOME/saturn<model>/`, download an appropriate ROM from hpcalc.org and create RAM cards (for 48gx and 48sx models.)
### when installed
``` shell
saturn48gx
```
## Post-fork changelog
- replaced the build system with a basic Makefile
- updated license from GPL2-or-later to GPL3-or-later
- moved binaries and their dependencies under ./dist/
- new helper scripts run48.sh and run49.sh
- ROMs helper Makefile
## Known bugs
- some bugs in emulation:
- 48gx: ON-D A can hang because it tries to write data in ROM space
- 48gx: VERSION spouts messages in the console (hidden unless `--verbose`)
- 49g: spouts messages in the console every second (hidden unless `--verbose`)
- ncurses UI: becomes unresponsive (but still quits gracefully on F7)
- I could get neither the 49 nor the 40 ROM running yet.
## Todo
- fix emulation bugs
- 49g: find a way to enable the bigger screen (131×80)
- 40g: make emulation work
**This is a fork of saturn v4.1.1.1 originally by Ivan Cibrario Bertolotti.**
Original source are available at https://www.hpcalc.org/details/4382
Original documentation are kept in ./docs-4.1.1.1/ and ./manual/

2
dist/ROMs/Makefile vendored
View file

@ -31,7 +31,7 @@ gxrom-r:
# HP 49
rom.49g:
curl "https://www.hpcalc.org/hp49/pc/rom/hp4950emurom.zip" --output rom-49g.zip
curl "https://www.hpcalc.org/hp49/pc/rom/beta1196.zip" --output rom-49g.zip
unzip rom-49g.zip rom.49g
rm rom-49g.zip

2422
dist/Saturn.ad vendored Normal file

File diff suppressed because it is too large Load diff

21
dist/run48.sh vendored Executable file
View file

@ -0,0 +1,21 @@
#!/bin/bash -eu
cd "$(dirname "$0")" ; CWD=$(pwd)
STATEDIR=$CWD/stateDir.48
mkdir -p "$STATEDIR"
if [ ! -e "$STATEDIR"/gxrom-r ]; then
make -C .. get-roms
cp ROMs/gxrom-r "$STATEDIR"/gxrom-r
fi
RAM=''
if [ ! -e "$STATEDIR"/ram ]; then
RAM=-reset
fi
[ ! -e "$STATEDIR"/port1 ] && dd if=/dev/zero of="$STATEDIR"/port1 bs=1k count=128
[ ! -e "$STATEDIR"/port2 ] && dd if=/dev/zero of="$STATEDIR"/port2 bs=1k count=4096
./run_saturn -face hp48 -hw hp48 -stateDir "$STATEDIR" -rom gxrom-r $RAM -port1 port1 -port2 port2

22
dist/run49.sh vendored Executable file
View file

@ -0,0 +1,22 @@
#!/bin/bash -eu
cd "$(dirname "$0")" ; CWD=$(pwd)
STATEDIR=$CWD/stateDir.49
mkdir -p "$STATEDIR"
if [ ! -e "$STATEDIR"/rom.49g ]; then
( cd "$STATEDIR"
wget -c https://www.hpcalc.org/hp49/pc/rom/hp4950v210.zip -O rom.zip
# wget -c https://www.hpcalc.org/hp49/pc/rom/beta1196.zip -O rom.zip
unzip rom.zip
rm rom.zip
)
fi
RAM=''
if [ ! -e "$STATEDIR"/ram ]; then
RAM=-reset
fi
./run_saturn -face hp49 -hw hp49 -stateDir "$STATEDIR" -rom rom.49g $RAM "$@"

18
dist/run_saturn vendored Executable file
View file

@ -0,0 +1,18 @@
#!/bin/sh
#
# $Id: run_saturn,v 4.1 2000/12/11 09:54:19 cibrario Rel $
#
# This file allows you to run saturn directly from the build directory,
# without installing it; regular use is discouraged.
if [ ! -r Saturn ]; then ln -s Saturn.ad Saturn; fi
# Be sure that XUSERFILESEARCHPATH does not supersede XAPPLRESDIR (IRIX)
if [ "$XUSERFILESEARCHPATH" != "" ]; then
XUSERFILESEARCHPATH=./%L/%N:./%l/%N:./%N:$XUSERFILESEARCHPATH;
export XUSERFILESEARCHPATH;
fi
XAPPLRESDIR=.; export XAPPLRESDIR # Take resources from here
NLSPATH=./%N; export NLSPATH # Message catalog is here, too
./saturn "$@"

46
dist/saturn40g vendored
View file

@ -1,44 +1,28 @@
#!/bin/bash -eu
cd "$(dirname "$0")" || exit 1
#CWD=$(pwd)
BINNAME=$(basename "$0")
STATE_HOME=${XDG_STATE_HOME:-$HOME/.local/state}
CONFIG_HOME=${XDG_CONFIG_HOME:-$HOME/.config}
STATEDIR=$STATE_HOME/saturn/40g
mkdir -p "$STATEDIR"
CONFIGDIR=${CONFIGDIR:-$CONFIG_HOME/$BINNAME}
mkdir -p "$CONFIGDIR"
if [ ! -e "$CONFIGDIR"/rom ]; then
if [ -d ../share/saturn/ROMs/ ]; then
cp -R ../share/saturn/ROMs/ "$CONFIGDIR"/
elif [ -d ./ROMs/ ]; then
cp -R ./ROMs/ "$CONFIGDIR"/
fi
if [ ! -d "$CONFIGDIR"/ROMs ]; then
if [ ! -e "$STATEDIR"/rom.39g ]; then
if [ ! -d ../share/saturn/ROMs/ ]; then
echo "Error: No ROMs/ dir found"
exit 1
fi
echo "The next step will download a ROM from https://hpcalc.org where \"HP graciously began allowing this to be downloaded in mid-2000.\""
echo "You can hit Ctrl-C now if you do not wish to download them."
read -r
make -C "$CONFIGDIR"/ROMs rom.39g
cp "$CONFIGDIR"/ROMs/rom.39g "$CONFIGDIR"/rom
if [ ! -d "$STATEDIR"/../ROMs ]; then
cp -R ../share/saturn/ROMs/ "$STATEDIR"/../ROMs
fi
make -C "$STATEDIR"/../ROMs rom.39g
cp "$STATEDIR"/../ROMs/rom.39g "$STATEDIR"/rom.39g
fi
RESET=''
if [ ! -e "$CONFIGDIR"/ram ]; then
RESET=--reset
RAM=''
if [ ! -e "$STATEDIR"/ram ]; then
RAM=-reset
fi
if [ ! -e "$CONFIGDIR"/config.lua ]; then
./saturn --40g --state-dir "$CONFIGDIR" --print-config > "$CONFIGDIR"/config.lua
fi
if echo "$@" | grep -q "\--verbose"; then
./saturn --40g --state-dir "$CONFIGDIR" "$RESET" "$@"
else
./saturn --40g --state-dir "$CONFIGDIR" "$RESET" "$@" 2> /dev/null
fi
./saturn --hw hp40 --40g --state-dir "$STATEDIR" --rom rom.39g "$RAM" --mod mod --cpu cpu --hdw hdw "$@"

54
dist/saturn48gx vendored
View file

@ -1,47 +1,33 @@
#!/bin/bash -eu
cd "$(dirname "$0")" || exit 1
#CWD=$(pwd)
BINNAME=$(basename "$0")
STATE_HOME=${XDG_STATE_HOME:-$HOME/.local/state}
CONFIG_HOME=${XDG_CONFIG_HOME:-$HOME/.config}
STATEDIR=$STATE_HOME/saturn/48gx
mkdir -p "$STATEDIR"
CONFIGDIR=${CONFIGDIR:-$CONFIG_HOME/$BINNAME}
mkdir -p "$CONFIGDIR"
if [ ! -e "$CONFIGDIR"/rom ]; then
if [ -d ../share/saturn/ROMs/ ]; then
cp -R ../share/saturn/ROMs/ "$CONFIGDIR"/
elif [ -d ./ROMs/ ]; then
cp -R ./ROMs/ "$CONFIGDIR"/
fi
if [ ! -d "$CONFIGDIR"/ROMs ]; then
if [ ! -e "$STATEDIR"/gxrom-r ]; then
if [ ! -d ../share/saturn/ROMs/ ]; then
echo "Error: No ROMs/ dir found"
exit 1
fi
echo "The next step will download a ROM from https://hpcalc.org where \"HP graciously began allowing this to be downloaded in mid-2000.\""
echo "You can hit Ctrl-C now if you do not wish to download them."
read -r
make -C "$CONFIGDIR"/ROMs gxrom-r
cp "$CONFIGDIR"/ROMs/gxrom-r "$CONFIGDIR"/rom
if [ ! -d "$STATEDIR"/../ROMs ]; then
cp -R ../share/saturn/ROMs/ "$STATEDIR"/../ROMs
fi
make -C "$STATEDIR"/../ROMs gxrom-r
cp "$STATEDIR"/../ROMs/gxrom-r "$STATEDIR"/gxrom-r
fi
[ ! -e "$CONFIGDIR"/port1 ] && dd if=/dev/zero of="$CONFIGDIR"/port1 bs=1k count=128
[ ! -e "$CONFIGDIR"/port2 ] && dd if=/dev/zero of="$CONFIGDIR"/port2 bs=1k count=4096
RESET=''
if [ ! -e "$CONFIGDIR"/ram ]; then
RESET=--reset
fi
if [ ! -e "$CONFIGDIR"/config.lua ]; then
./saturn --48gx --state-dir "$CONFIGDIR" --print-config > "$CONFIGDIR"/config.lua
fi
if echo "$@" | grep -q "\--verbose"; then
./saturn --48gx --state-dir "$CONFIGDIR" "$RESET" "$@"
RAM=''
if [ ! -e "$STATEDIR"/ram ]; then
RAM=--reset
else
./saturn --48gx --state-dir "$CONFIGDIR" "$RESET" "$@" 2> /dev/null
RAM="--ram ram"
fi
[ ! -e "$STATEDIR"/port1 ] && dd if=/dev/zero of="$STATEDIR"/port1 bs=1k count=128
[ ! -e "$STATEDIR"/port2 ] && dd if=/dev/zero of="$STATEDIR"/port2 bs=1k count=4096
./saturn --hw hp48 --48gx --state-dir "$STATEDIR" --rom gxrom-r "$RAM" --port1 port1 --port2 port2 --mod mod --cpu cpu --hdw hdw "$@"

47
dist/saturn48sx vendored
View file

@ -1,47 +0,0 @@
#!/bin/bash -eu
cd "$(dirname "$0")" || exit 1
BINNAME=$(basename "$0")
CONFIG_HOME=${XDG_CONFIG_HOME:-$HOME/.config}
CONFIGDIR=${CONFIGDIR:-$CONFIG_HOME/$BINNAME}
mkdir -p "$CONFIGDIR"
if [ ! -e "$CONFIGDIR"/rom ]; then
if [ -d ../share/saturn/ROMs/ ]; then
cp -R ../share/saturn/ROMs/ "$CONFIGDIR"/
elif [ -d ./ROMs/ ]; then
cp -R ./ROMs/ "$CONFIGDIR"/
fi
if [ ! -d "$CONFIGDIR"/ROMs ]; then
echo "Error: No ROMs/ dir found"
exit 1
fi
echo "The next step will download a ROM from https://hpcalc.org where \"HP graciously began allowing this to be downloaded in mid-2000.\""
echo "You can hit Ctrl-C now if you do not wish to download them."
read -r
make -C "$CONFIGDIR"/ROMs sxrom-j
cp "$CONFIGDIR"/ROMs/sxrom-j "$CONFIGDIR"/rom
fi
[ ! -e "$CONFIGDIR"/port1 ] && dd if=/dev/zero of="$CONFIGDIR"/port1 bs=1k count=128
[ ! -e "$CONFIGDIR"/port2 ] && dd if=/dev/zero of="$CONFIGDIR"/port2 bs=1k count=128
RESET=''
if [ ! -e "$CONFIGDIR"/ram ]; then
RESET=--reset
fi
if [ ! -e "$CONFIGDIR"/config.lua ]; then
./saturn --48sx --state-dir "$CONFIGDIR" --print-config > "$CONFIGDIR"/config.lua
fi
if echo "$@" | grep -q "\--verbose"; then
./saturn --48sx --state-dir "$CONFIGDIR" "$RESET" "$@"
else
./saturn --48sx --state-dir "$CONFIGDIR" "$RESET" "$@" 2> /dev/null
fi

View file

@ -1,9 +0,0 @@
[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
Terminal=false
Exec=@PREFIX@/bin/saturn48sx
Name=saturn48sx
Icon=@PREFIX@/share/saturn/hplogo.png
Categories=Utility;

46
dist/saturn49g vendored
View file

@ -1,44 +1,28 @@
#!/bin/bash -eu
cd "$(dirname "$0")" || exit 1
#CWD=$(pwd)
BINNAME=$(basename "$0")
STATE_HOME=${XDG_STATE_HOME:-$HOME/.local/state}
CONFIG_HOME=${XDG_CONFIG_HOME:-$HOME/.config}
STATEDIR=$STATE_HOME/saturn/49g
mkdir -p "$STATEDIR"
CONFIGDIR=${CONFIGDIR:-$CONFIG_HOME/$BINNAME}
mkdir -p "$CONFIGDIR"
if [ ! -e "$CONFIGDIR"/rom ]; then
if [ -d ../share/saturn/ROMs/ ]; then
cp -R ../share/saturn/ROMs/ "$CONFIGDIR"/
elif [ -d ./ROMs/ ]; then
cp -R ./ROMs/ "$CONFIGDIR"/
fi
if [ ! -d "$CONFIGDIR"/ROMs ]; then
if [ ! -e "$STATEDIR"/rom.49g ]; then
if [ ! -d ../share/saturn/ROMs/ ]; then
echo "Error: No ROMs/ dir found"
exit 1
fi
echo "The next step will download a ROM from https://hpcalc.org where \"HP graciously began allowing this to be downloaded in mid-2000.\""
echo "You can hit Ctrl-C now if you do not wish to download them."
read -r
make -C "$CONFIGDIR"/ROMs rom.49g
cp "$CONFIGDIR"/ROMs/rom.49g "$CONFIGDIR"/rom
if [ ! -d "$STATEDIR"/../ROMs ]; then
cp -R ../share/saturn/ROMs/ "$STATEDIR"/../ROMs
fi
make -C "$STATEDIR"/../ROMs rom.49g
cp "$STATEDIR"/../ROMs/rom.49g "$STATEDIR"/rom.49g
fi
RESET=''
if [ ! -e "$CONFIGDIR"/ram ]; then
RESET=--reset
RAM=''
if [ ! -e "$STATEDIR"/ram ]; then
RAM=-reset
fi
if [ ! -e "$CONFIGDIR"/config.lua ]; then
./saturn --49g --state-dir "$CONFIGDIR" --print-config > "$CONFIGDIR"/config.lua
fi
if echo "$@" | grep -q "\--verbose"; then
./saturn --49g --state-dir "$CONFIGDIR" "$RESET" "$@"
else
./saturn --49g --state-dir "$CONFIGDIR" "$RESET" "$@" 2> /dev/null
fi
./saturn --hw hp49 --49g --state-dir "$STATEDIR" --rom rom.49g "$RAM" --mod mod --cpu cpu --hdw hdw "$@"

View file

@ -7,16 +7,14 @@ SRC = src/chf_init.c \
src/chf_abrt.c \
src/chf_hdlr.c \
src/chf_msgc.c \
src/chf_st.c
src/chf_st.c \
src/chf_top.c
#
# Target object files
#
OBJS = $(SRC:.c=.o)
HEADERS = src/ChfPriv.h \
src/Chf.h \
#
# Other definitions
#
@ -48,8 +46,8 @@ mrproper: clean
rm -f $(TARGET)
make -C docs mrproper
$(TARGET): $(OBJS) $(HEADERS)
$(AR) $(ARFLAGS) $@ $(OBJS)
$(TARGET): $(OBJS)
$(AR) $(ARFLAGS) $@ $?
# Formatting
pretty-code:

View file

@ -68,9 +68,10 @@ Condition generation and signal
Generating a condition
* CHF_Condition::
* ChfCondition::
* ChfEnd::
* ChfSeverity::
* ChfErrnoCondition::
Signaling a condition
@ -97,9 +98,9 @@ Structured condition handling
Chf behavior during structured condition handling
* CHF_Try::
* CHF_Catch::
* CHF_EndTry::
* ChfTry::
* ChfCatch::
* ChfEndTry::
Message retrieval
@ -176,6 +177,9 @@ this change is transparent and the documentation does not reflect it.
The reentrant flavor of the Chf library is not yet supported. Multithreaded
application must serialize Chf accesses themselves.
@item
The @code{ChfErrnoCondition} macro is not supported, and has no effect.
@item
The default condition handler does not display the condition message
on the standard error stream.
@ -263,7 +267,7 @@ Moreover, each module using the Chf library must include the header file
@node ChfInit(), ChfMsgcatInit(), Initialization and exit, Initialization and exit
@section ChfInit()
@cindex Initialization
@deftypefn Function int ChfInit (const char *app_name, const int options, void *mrs_data, ChfMrsGet mrs_get, ChfMrsExit mrs_exit, const int condition_stack_size, const int handler_stack_size, const int exit_code)
@deftypefn Function int ChfInit (const char *app_name, const ChfOptions options, void *mrs_data, ChfMrsGet mrs_get, ChfMrsExit mrs_exit, const int condition_stack_size, const int handler_stack_size, const int exit_code)
This function initializes the Chf library using a custom message retrieval
subsystem, and returns to the caller a condition code; that code will be either
@ -317,8 +321,8 @@ Size of the handler stack. This value determines the maximum number of
active condition handlers the application can have. A condition handler is
activated when a @code{ChfPushHandler()} is executed for it, and it is
deactivated when the corresponding @code{ChfPopHandler()} completes.
In addition, each execution of the @code{CHF_Try} macro also pushes
a condition handler; the handler is removed when @code{CHF_EndTry}
In addition, each execution of the @code{ChfTry} macro also pushes
a condition handler; the handler is removed when @code{ChfEndTry}
is executed.
@item exit_code
@ -364,7 +368,7 @@ must be invoked only once before starting multithreaded operation.
@section ChfMsgcatInit()
@cindex Initialization
@cindex Internationalization
@deftypefn Function int ChfMsgcatInit (const char *app_name, const int options, const char *msgcat_name, const int condition_stack_size, const int handler_stack_size, const int exit_code)
@deftypefn Function int ChfMsgcatInit (const char *app_name, const ChfOptions options, const char *msgcat_name, const int condition_stack_size, const int handler_stack_size, const int exit_code)
This function initializes the Chf library and activates the message retrieval
subsystem based on @code{catgets()}, offering support for
@ -420,7 +424,7 @@ before.
@node ChfStaticInit(), ChfWin32Init(), ChfMsgcatInit(), Initialization and exit
@section ChfStaticInit()
@cindex Initialization
@deftypefn Function int ChfStaticInit (const char *app_name, const int options, const ChfTable *table, const size_t table_size, const int condition_stack_size, const int handler_stack_size, const int exit_code)
@deftypefn Function int ChfStaticInit (const char *app_name, const ChfOptions options, const ChfTable *table, const size_t table_size, const int condition_stack_size, const int handler_stack_size, const int exit_code)
This function initializes the Chf library and activates the static
message retrieval subsystem using the message table @code{table},
@ -482,7 +486,7 @@ The message fragment or template associated with
@section ChfWin32Init()
@cindex Initialization
@cindex Internationalization
@deftypefn Function int ChfWin32Init (const char *app_name, const int options, HINSTANCE instance, const int condition_stack_size, const int handler_stack_size, const int exit_code)
@deftypefn Function int ChfWin32Init (const char *app_name, const ChfOptions options, HINSTANCE instance, const int condition_stack_size, const int handler_stack_size, const int exit_code)
This function initializes the Chf library and activates the message
retrieval subsystem based on the Win32 function @code{LoadString()},
@ -665,6 +669,12 @@ identifier. Even if this macro could in principle be redefined through the
source, it is generally inconvenient to have functions belonging to different
application's modules in the same source file, so it is discouraged.
This definition is mandatory.
@item CHF_EXTENDED_INFO
If this macro is set, all conditions generated by the source module
will include the file name and the line number as additional information
items. This can be useful for debugging purposes. This definition is
optional.
@end table
@strong{Win32:} The @code{tchar.h} system header must be included
@ -687,14 +697,15 @@ When an unusual or noteworthy condition occurs, the application may generate
a condition that describes it.
@menu
* CHF_Condition::
* ChfCondition::
* ChfEnd::
* ChfSeverity::
* ChfErrnoCondition::
@end menu
@node CHF_Condition, ChfEnd, Generating a condition, Generating a condition
@subsection CHF_Condition
@deftypefn Macro {} CHF_Condition {...}
@node ChfCondition, ChfEnd, Generating a condition, Generating a condition
@subsection ChfCondition
@deftypefn Macro {} ChfCondition {...}
This macro starts the definition of a condition using the current
application's module specifier @code{CHF_MODULE_ID}; it must be followed by
@ -748,15 +759,15 @@ there was an attempt to generate a condition while the Chf condition
@end deftypefn
@node ChfEnd, ChfSeverity, CHF_Condition, Generating a condition
@node ChfEnd, ChfSeverity, ChfCondition, Generating a condition
@subsection ChfEnd
@deftypefn Macro {} ChfEnd
This macro terminates the generation of the condition, started
with @code{CHF_Condition}; it must be followed by @code{;}. For example:
with @code{ChfCondition}; it must be followed by @code{;}. For example:
@example
CHF_Condition
ChfCondition
<condition_code>, <severity>, <additional_info>
ChfEnd;
@end example
@ -765,7 +776,7 @@ ChfEnd;
@c 2.1, cibrario, 26-May-2000
@c Expanded description of severity codes
@node ChfSeverity, ChfEnd, Generating a condition
@node ChfSeverity, ChfErrnoCondition, ChfEnd, Generating a condition
@subsection ChfSeverity
@deftp {Data type} ChfSeverity
The severity code of a condition is an enumerated type, and can assume one
@ -811,6 +822,19 @@ call. It is usually signaled immediately after generation.
@end table
@end deftp
@node ChfErrnoCondition, , ChfSeverity, Generating a condition
@subsection ChfErrnoCondition
@deftypefn Macro {} ChfErrnoCondition
This macro generates a condition from the current value of the @code{errno}
variable. The module identifier of the condition is set to the special
value @code{CHF_ERRNO_SET}. The severity is always @code{CHF_ERROR}.
@strong{Win32:} This macro is not supported and has no effect when invoked.
@end deftypefn
@node Signaling a condition, , Generating a condition, Condition generation and signal
@section Signaling a condition
@cindex Signaling a condition
@ -952,7 +976,7 @@ typedef /* Condition handler */
ChfAction (*ChfHandler)(
const ChfDescriptor *,
const ChfState,
void*
ChfPointer
);
@end example
@ -966,7 +990,7 @@ is a pointer to the condition group that is being signaled.
@item const ChfState
represents the current state of the condition handling facility.
@item void*
@item ChfPointer
is a copy of the @code{handler_context} pointer passed to the
@code{ChfPushHandler()} invocation that established the condition
handler.
@ -1000,7 +1024,7 @@ of the new condition group allows it to do so.
@subsection ChfPushHandler()
@cindex Condition handlers
@cindex Adding condition handlers
@deftypefn Function void ChfPushHandler (ChfHandler new_handler, void *unwind_context, void* handler_context)
@deftypefn Function void ChfPushHandler (ChfHandler new_handler, void *unwind_context, ChfPointer handler_context)
This function pushes the new condition handler @code{new_handler} with
its associated @code{siglongjmp()} context, pointed by
@ -1106,6 +1130,74 @@ the macros the Chf library provides for this purpose.
@end deftp
The following macros are provided to access a condition descriptor:
@deftypefn Macro {ChfDescriptor *} ChfGetNextDescriptor (Chf Descriptor *d)
@cindex Next condition descriptor
Returns to the caller the condition descriptor that hierarchically
follows @code{d} in the current condition group, or the special
value @code{CHF_NULL_DESCRIPTOR} if @code{d} is the last descriptor of the
group.
@end deftypefn
@deftypefn Macro int ChfGetModuleId (Chf Descriptor *d)
@cindex Module identifier
Returns to the caller the identifier of the module that generated
the condition @code{d}.
@end deftypefn
@deftypefn Macro int ChfGetConditionCode (Chf Descriptor *d)
@cindex Condition Code
Returns to the caller the condition code of the condition @code{d}.
@end deftypefn
@deftypefn Macro ChfSeverity ChfGetSeverity (Chf Descriptor *d)
@cindex Severity
Returns to the caller the severity level of the condition @code{d}.
@xref{ChfSeverity}.
@end deftypefn
@deftypefn Macro int ChfGetLineNumber (Chf Descriptor *d)
@cindex Line number
Returns to the caller the source line number where the condition @code{d}
was generated. This piece of information is available only if the
Chf compile-time option @code{CHF_EXTENDED_INFO} was set when the source
file that generated the condition was compiled, otherwise the special
value @code{CHF_UNKNOWN_LINE_NUMBER} is returned instead.
@end deftypefn
@deftypefn Macro {const char *} ChfGetFileName (Chf Descriptor *d)
@cindex File name
Returns to the caller the file name where the condition @code{d}
was generated. This piece of information is available only if the
Chf compile-time option @code{CHF_EXTENDED_INFO} was set when the source
file that generated the condition was compiled, otherwise the special
value @code{CHF_UNKNOWN_FILE_NAME} is returned instead.
@end deftypefn
@deftypefn Macro {char *} ChfGetPartialMessage (Chf Descriptor *d)
@cindex Partial condition message
Returns to the caller the partial condition message that was associated
with the condition @code{d} when it was generated. The partial condition
message contains the result of the execution of @code{sprintf()} using
the message template associated with the condition as format, and the
ancillary condition arguments as additional arguments.
@end deftypefn
@node Condition handling state, Handler actions, Condition descriptors, General condition handling
@ -1250,19 +1342,19 @@ the structured condition handling is layered above the general one.
The syntax establishing a structured condition handler is as follows:
@example
CHF_Try
ChfTry
@{
... body ...
@}
CHF_Catch
ChfCatch
@{
const ChfDescriptor *exc = ChfGetTopCondition();
... condition handler ...
@}
CHF_EndTry;
ChfEndTry;
@end example
The macros @code{CHF_Try}, @code{CHF_Catch} and @code{CHF_EndTry}
The macros @code{ChfTry}, @code{ChfCatch} and @code{ChfEndTry}
expand as follows:
@example
@ -1300,7 +1392,7 @@ The @code{body} is either a statement or a block of statements (a block
is shown in the example) to be protected. If an exception with severity
equal to @code{CHF_FATAL} is signaled during the execution of
@code{body}, control is transferred to the @code{condition handler}
following @code{CHF_Catch}.
following @code{ChfCatch}.
The handler can then retrieve the condition group associated with the
exception using @code{ChfGetTopCondition()}, as shown in the example,
@ -1311,12 +1403,12 @@ and must perform one of the following actions:
Handle the exception; when the condition handler completes, that is, its
last statement has been executed, the current condition group is
automatically discarded and control is transferred to the code that
follows @code{CHF_EndTry}.
follows @code{ChfEndTry}.
@item
Resignal the exception, possibly after adding one or more conditions to
it; in this case, the handler explicitly calls @code{ChfSignal()}.
In response, Chf continues to search for a handler that actually
handles the exception, in the @code{CHF_Try}/@code{CHF_Catch} blocks
handles the exception, in the @code{ChfTry}/@code{ChfCatch} blocks
enclosing the current one, in inner to outer order. The control
will never be returned to the resignaling handler.
@end itemize
@ -1338,7 +1430,7 @@ automatically signaled immediately after generation and are not reported
to the caller; they are informational conditions only, and they must not
disrupt the normal control flow of the application. Accordingly, the
structured condition handler is @strong{not} invoked when a
success/informational condition is signaled in its @code{CHF_Try} body.
success/informational condition is signaled in its @code{ChfTry} body.
@item
@code{CHF_WARNING} conditions generated by a module are usually not
signaled immediately after generation, but are reported to the
@ -1348,7 +1440,7 @@ has been at least partially successful; this usually means that
the disruption of the control flow of the application can be kept to
a minimum and handled locally. Accordingly, the structured condition
handler is @strong{not} invoked when a warning condition
is signaled in its @code{CHF_Try} body.
is signaled in its @code{ChfTry} body.
@item
@code{CHF_ERROR} conditions generated by a module indicate that the
module execution has been unsuccessful; they are usually reported to the
@ -1357,7 +1449,7 @@ indicates that a significant disruption of the control flow of the
application is required to recover, and that local handling is still
possible but could not suffice. Accordingly, the structured condition
handler is @strong{not} invoked when an error condition is signaled in
its @code{CHF_Try} body. Notice also that if the @code{CHF_Try} body is
its @code{ChfTry} body. Notice also that if the @code{ChfTry} body is
not able to locally recover the condition, it can add a @code{CHF_FATAL}
condition to the condition group and signal the modified group, thus
triggering the invocation of the structured condition handler.
@ -1365,7 +1457,7 @@ triggering the invocation of the structured condition handler.
@code{CHF_FATAL} conditions are usually signaled immediately after
generation and always require a global recovery action.
Accordingly, the structured condition handler is
invoked when a warning condition is signaled in its @code{CHF_Try} body.
invoked when a warning condition is signaled in its @code{ChfTry} body.
@end itemize
Notice also that control is transferred to the structured exception
@ -1379,7 +1471,7 @@ detailed description of its operation.
If no exceptions are raised during the execution of @code{body},
the @code{condition handler} is skipped and execution continues
immediately after @code{CHF_EndTry}.
immediately after @code{ChfEndTry}.
@node Chf behavior during structured condition handling, , Syntax of structured condition handlers, Structured condition handling
@section Chf behavior during structured condition handling
@ -1410,11 +1502,11 @@ immediately returns without doing anything, since Chf is now in state
@item
Chf transitions to the @code{CHF_IDLE} state and performs a non-local
control transfer to the structured condition handler's unwind context;
this corresponds to the code that follows @code{CHF_Catch}.
this corresponds to the code that follows @code{ChfCatch}.
The current condition group is not removed from the condition stack.
@item
Since the current condition group has not been removed from the
condition stack, the code that follows @code{CHF_Catch} can freely
condition stack, the code that follows @code{ChfCatch} can freely
access the condition group using @code{ChfGetTopCondition()}
and @code{ChfGetNextDescriptor()}.
@item
@ -1422,7 +1514,7 @@ If any new condition is generated in this phase, it is merged with the
current condition group; the condition group can be re-signaled at will
by invoking @code{ChfSignal()}.
@item
Immediately after the code that follows @code{CHF_Catch} completes,
Immediately after the code that follows @code{ChfCatch} completes,
@code{ChfDiscard()} is automatically invoked to remove the topmost
condition group from the stack.
@end itemize
@ -1439,38 +1531,38 @@ In summary, the following structured condition handling macros
are currently available:
@menu
* CHF_Try::
* CHF_Catch::
* CHF_EndTry::
* ChfTry::
* ChfCatch::
* ChfEndTry::
@end menu
@node CHF_Try, CHF_Catch, Chf behavior during structured condition handling, Chf behavior during structured condition handling
@subsection CHF_Try
@deftypefn Macro {} CHF_Try {...}
@node ChfTry, ChfCatch, Chf behavior during structured condition handling, Chf behavior during structured condition handling
@subsection ChfTry
@deftypefn Macro {} ChfTry {...}
This macro introduces a new structured condition handling body.
The body is either a statement or a block of statements to be
protected: if a @code{CHF_FATAL} exception is signaled during its
execution, control is transferred to the condition handling code
following @code{CHF_Catch}.
following @code{ChfCatch}.
@end deftypefn
@node CHF_Catch, CHF_EndTry, CHF_Try, Chf behavior during structured condition handling
@subsection CHF_Catch
@deftypefn Macro {} CHF_Catch {...}
@node ChfCatch, ChfEndTry, ChfTry, Chf behavior during structured condition handling
@subsection ChfCatch
@deftypefn Macro {} ChfCatch {...}
This macro must follow @code{CHF_Try} and introduces a new structured
This macro must follow @code{ChfTry} and introduces a new structured
condition handler following it; the handler can be either a statement or
a block of statements. If a @code{CHF_FATAL} exception is signaled
during the execution of the body protected by @code{CHF_Try}, control is
transferred to the condition handling code following @code{CHF_Catch}.
during the execution of the body protected by @code{ChfTry}, control is
transferred to the condition handling code following @code{ChfCatch}.
@end deftypefn
@node CHF_EndTry, , CHF_Catch, Chf behavior during structured condition handling
@subsection CHF_EndTry
@deftypefn Macro {} CHF_EndTry
@node ChfEndTry, , ChfCatch, Chf behavior during structured condition handling
@subsection ChfEndTry
@deftypefn Macro {} ChfEndTry
This macro marks the end of a body/condition handler pair.
@ -1818,6 +1910,36 @@ Contains the integer identifier of the message set containing the condition
messages for @code{errno} codes. It has the value 3.
@end deftypefn
@deftypefn Macro {} ChfChar
This macro is used to make portable declarations of character variables,
and is mapped into either @code{char} or @code{TCHAR} depending on the
platform.
@end deftypefn
@deftypefn Macro {} ChfText (x)
This macro is used to make portable declarations of character strings,
and is mapped into either @code{x} or @code{_T(x)} depending on the
platform.
@end deftypefn
@deftypefn Macro {} ChfSigjmp_buf
This macro is mapped into either @code{sigjmp_buf} or @code{jmp_buf},
depending on whether the platform supports @code{sigjmp_buf}
contexts or not.
@end deftypefn
@deftypefn Macro {} ChfSigsetjmp (x,y)
This macro is mapped into either @code{sigsetjmp()} or @code{setjmp()},
depending on whether the platform supports @code{sigjmp_buf}
contexts or not. In the latter case argument @code{x} is ignored.
@end deftypefn
@deftypefn Macro {} ChfSiglongjmp (x,y)
This macro is mapped into either @code{siglongjmp()} or @code{longjmp()},
depending on whether the platform supports @code{sigjmp_buf}
contexts or not.
@end deftypefn
@node Other useful functions, Changes since release 1, Other useful macro definitions, Top
@chapter Other useful functions
@cindex Other useful functions

271
libChf/src/Chf.h Normal file
View file

@ -0,0 +1,271 @@
/* .+
.identifier : $Id: Chf.h,v 2.2 2001/01/25 11:56:44 cibrario Exp $
.context : CHF, Condition Handling Facility
.title : $RCSfile: Chf.h,v $, main header
.kind : C header
.author : Ivan Cibrario B.
.site : CSTV-CNR
.creation : 2-May-1996
.keywords : *
.description :
This is the main header of the Condition Handling Facility
.include : stdio.h setjmp.h (Win32: tchar.h)
.notes :
$Log: Chf.h,v $
Revision 2.2 2001/01/25 11:56:44 cibrario
Added partial Win32 support (Windows CE only).
Revision 2.1 2000/05/26 14:10:08 cibrario
- Revised unwind context passing mechanism; redefined CHF_NULL_CONTEXT
- New macros: CHF_NULL_HANDLER, CHF_MAJOR_RELEASE_NUMBER,
CHF_MINOR_RELEASE_NUMBER
- New ChfAction value: CHF_UNWIND_KEEP; fixed spelling of ChfAction value:
CHF_SIGNALLING -> CHF_SIGNALING
- Added structured condition handling macros: ChfTry, ChfCatch, ChfEndTry
Revision 1.6 1997/01/15 13:41:20 cibrario
Defined the new data type ChfPointer, a generic (void *) pointer. Each
condition handler can have a private handler context pointer, of type
ChfPointer, that the function ChfPushHandler() stores and that is passed
to the handler when it's activated.
Fixed a wrong adjustment of the condition handlers stack pointer after
an unwind operation.
Revision 1.5 1996/10/04 09:45:30 cibrario
Updated the condition message format in the private header ChfPriv.h to
improve internationalization
Revision 1.4 1996/09/25 13:21:11 cibrario
Added macro CHF_LIBRARY_ID; it contains the current ID of the CHF library.
The module chf_init.o will contain it as a static char[] variable.
Revision 1.2 1996/06/11 13:02:10 cibrario
Added prototype for ChfGetTopCondition()
Revision 1.1 1996/05/28 12:56:47 cibrario
Initial revision
.- */
/* -------------------------------------------------------------------------
Win32 & UNICODE support
------------------------------------------------------------------------- */
#define ChfChar char
#define ChfText( x ) x
#define ChfSigjmp_buf sigjmp_buf
#define ChfSigsetjmp( x, y ) sigsetjmp( x, y )
#define ChfSiglongjmp( x, y ) siglongjmp( x, y )
/* -------------------------------------------------------------------------
CHF implementation limits and other symbolic constants
------------------------------------------------------------------------- */
#define CHF_MAX_MESSAGE_LENGTH 256
#define CHF_UNKNOWN_LINE_NUMBER ( -1 )
#define CHF_UNKNOWN_FILE_NAME ( ChfChar* )NULL
#define CHF_NULL_DESCRIPTOR ( ChfDescriptor* )NULL
#define CHF_NULL_CONTEXT ( void* )NULL
#define CHF_NULL_POINTER ( ChfPointer* )NULL
#define CHF_NULL_HANDLER ( ChfHandler ) NULL
#define CHF_LIBRARY_ID ChfText( "$Id: Chf.h,v 2.2 2001/01/25 11:56:44 cibrario Exp $" )
#define CHF_MAJOR_RELEASE_NUMBER 2
#define CHF_MINOR_RELEASE_NUMBER 2
#define CHF_MODULE_NAMES_SET 1
#define CHF_SET 2
#define CHF_ERRNO_SET 3
/* -------------------------------------------------------------------------
Condition codes
------------------------------------------------------------------------- */
#define CHF_S_OK 0
#define CHF_F_COND_STACK_FULL 1 /* Condition stack is full */
#define CHF_F_HDLR_STACK_FULL 2 /* Handler stack is full */
#define CHF_F_HDLR_STACK_EMPTY 3 /* Handler stack is empty */
#define CHF_F_BAD_STATE 4 /* Bad CHF state for req. operation */
#define CHF_F_INVALID_ACTION 5 /* Invalid action from handler: %d */
#define CHF_F_MALLOC 6 /* Dynamic memory allocation failed */
#define CHF_F_NOT_AVAILABLE 7 /* Function not available */
#define CHF_F_SETLOCALE 10 /* setlocale() failed */
#define CHF_F_CATOPEN 11 /* catopen() failed */
/* -------------------------------------------------------------------------
Type definitions
------------------------------------------------------------------------- */
typedef enum /* Condition severity codes */
{ CHF_SUCCESS,
CHF_INFO,
CHF_WARNING,
CHF_ERROR,
CHF_FATAL } ChfSeverity;
typedef enum /* Condition handler action codes */
{ CHF_CONTINUE, /* Continue application */
CHF_RESIGNAL, /* Resignal to next handler */
CHF_UNWIND, /* Stack unwind */
CHF_UNWIND_KEEP /* Unwind, keep last cond. group */
} ChfAction;
typedef int /* CHF options */
ChfOptions;
#define CHF_DEFAULT 0x0000 /* default flags */
#define CHF_ABORT 0x0001 /* use abort() instead of exit() */
typedef enum /* Current CHF state */
{ CHF_UNKNOWN,
CHF_IDLE,
CHF_SIGNALING,
CHF_UNWINDING,
CHF_SIGNAL_UNWINDING } ChfState;
typedef struct ChfDescriptor_S /* Condition descriptor */
{
int module_id; /* Module identifier */
int condition_code; /* Condition code */
ChfSeverity severity; /* Severity */
int line_number; /* Line # or CHF_UNK_LINE_NUMBER */
const ChfChar* file_name; /* File name or CHF_UNK_FILE_NAME */
ChfChar message[ CHF_MAX_MESSAGE_LENGTH ]; /* Partial message */
struct ChfDescriptor_S* next; /* Link to next descriptor */
} ChfDescriptor;
typedef struct ChfTable_S /* Standalone message table */
{
int module; /* Module identifier */
int code; /* Condition code */
ChfChar* msg_template; /* Message template */
} ChfTable;
typedef /* Generic pointer */
void* ChfPointer;
typedef /* Condition handler */
ChfAction ( *ChfHandler )( const ChfDescriptor*, const ChfState, ChfPointer );
typedef /* Message retrieval 'get_message' function */
const ChfChar* ( *ChfMrsGet )( void*, const int, const int, const ChfChar* default_message );
typedef /* Message retrieval 'exit' function */
void ( *ChfMrsExit )( void* );
/* -------------------------------------------------------------------------
Condition generation macros
------------------------------------------------------------------------- */
#if defined( CHF_EXTENDED_INFO )
# define ChfCondition \
ChfGenerate( \
CHF_MODULE_ID, \
ChfText(__FILE__), __LINE__,
# define ChfErrnoCondition ChfGenerate( CHF_ERRNO_SET, ChfText( __FILE__ ), __LINE__, errno, CHF_ERROR )
#else
# define ChfCondition \
ChfGenerate( \
CHF_MODULE_ID, \
CHF_UNKNOWN_FILE_NAME, CHF_UNKNOWN_LINE_NUMBER,
# define ChfErrnoCondition ChfGenerate( CHF_ERRNO_SET, CHF_UNKNOWN_FILE_NAME, CHF_UNKNOWN_LINE_NUMBER, errno, CHF_ERROR )
#endif
#define ChfEnd \
)
/* -------------------------------------------------------------------------
Structured condition handling
------------------------------------------------------------------------- */
#define ChfTry \
{ \
ChfSigjmp_buf _chf_sigjmp_buf; \
if ( ChfSigsetjmp( _chf_sigjmp_buf, 1 ) == 0 ) { \
ChfPushHandler( CHF_NULL_HANDLER, _chf_sigjmp_buf, CHF_NULL_POINTER );
#define ChfCatch \
ChfPopHandler(); \
} \
else \
{
#define ChfEndTry \
ChfDiscard(); \
} \
}
/* -------------------------------------------------------------------------
Other macros
------------------------------------------------------------------------- */
#define ChfGetNextDescriptor( d ) ( d )->next
#define ChfGetModuleId( d ) ( d )->module_id
#define ChfGetConditionCode( d ) ( d )->condition_code
#define ChfGetSeverity( d ) ( d )->severity
#define ChfGetLineNumber( d ) ( d )->line_number
#define ChfGetFileName( d ) ( d )->file_name
#define ChfGetPartialMessage( d ) ( d )->message
/* -------------------------------------------------------------------------
Function prototypes
------------------------------------------------------------------------- */
/* Generic initialization */
int ChfInit( const ChfChar* app_name, /* Application's name */
const ChfOptions options, /* Options */
void* mrs_data, /* Message retrieval private data */
ChfMrsGet mrs_get, /* 'GetMessage' function */
ChfMrsExit mrs_exit, /* 'Exit' function */
const int condition_stack_size, /* Size of the condition stack */
const int handler_stack_size, /* Size of the handler stack */
const int exit_code /* Abnormal exit code */
);
/* Initialization with msgcat subsystem */
int ChfMsgcatInit( const ChfChar* app_name, /* Application's name */
const ChfOptions options, /* Options */
const ChfChar* msgcat_name, /* Name of the message catalog */
const int condition_stack_size, /* Size of the condition stack */
const int handler_stack_size, /* Size of the handler stack */
const int exit_code /* Abnormal exit code */
);
/* Initialization with static message tables */
int ChfStaticInit( const ChfChar* app_name, /* Application's name */
const ChfOptions options, /* Options */
const ChfTable* table, /* Static message table */
const size_t table_size, /* Size of the message table */
const int condition_stack_size, /* Size of the condition stack */
const int handler_stack_size, /* Size of the handler stack */
const int exit_code /* Abnormal exit code */
);
/* Exit */
void ChfExit( void );
/* Abort application */
void ChfAbort( const int abort_code );
/* Push a new handler into the stack */
void ChfPushHandler( ChfHandler new_handler, /* Handler to be added */
void* unwind_context, /* Unwind context */
ChfPointer handler_context /* Private handler context */
);
/* Pop a handler */
void ChfPopHandler( void );
/* Build a condition message */
ChfChar* ChfBuildMessage( const ChfDescriptor* descriptor );
/* Signal the current conditions */
void ChfSignal( void );
/* Discard the current conditions */
void ChfDiscard( void );
/* Generate a condition into the stack */
void ChfGenerate( const int module_id, const ChfChar* file_name, const int line_number, const int condition_code,
const ChfSeverity severity, ... );
/* Retrieve a condition message */
const ChfChar* ChfGetMessage( const int module_id, const int condition_code, const ChfChar* default_message );
/* Retrieve top condition */
const ChfDescriptor* ChfGetTopCondition( void );

View file

@ -1,6 +1,3 @@
#ifndef _CHF_PRIV_H
#define _CHF_PRIV_H 1
/* .+
.identifier : $Id: ChfPriv.h,v 2.2 2001/01/25 11:57:57 cibrario Exp $
@ -40,8 +37,6 @@
.- */
#include "Chf.h"
/* -------------------------------------------------------------------------
Macros
------------------------------------------------------------------------- */
@ -49,6 +44,16 @@
#define CHF_MODULE_ID CHF_SET
#define CHF_TMP_MESSAGE_LENGTH ( 2 * CHF_MAX_MESSAGE_LENGTH )
#define CHF_DEF_MESSAGE_LENGTH 40
#define CHF_DEF_PARTIAL_MSG_FMT ChfText( "Code <%d>d" )
#define CHF_DEF_MID_MSG_FMT ChfText( "Mid <%d>d" )
#define CHF_EXTENDED_INFO_FMT ChfText( "(%s,%d)" )
#define CHF_SEVERITY_NAMES { ChfText( "S" ), ChfText( "I" ), ChfText( "W" ), ChfText( "E" ), ChfText( "F" ) }
#define CHF_UNKNOWN_SEVERITY ChfText( "?" )
#define CHF_MESSAGE_SEPARATOR ChfText( "-" )
#define CHF_MESSAGE_TERMINATOR ChfText( "\n" )
#define CHF_ABORT_HEADER ChfText( "ChfAbort-F-" )
#define CHF_ABORT_BAD_CODE_FMT ChfText( "Bad abort code <%d>d\n" )
#define CHF_ABORT_GOOD_CODE_FMT ChfText( "%s\n" )
/* -------------------------------------------------------------------------
Abort codes used with ChfAbort()
@ -73,14 +78,14 @@
typedef struct ChfHandlerDescriptor_S {
ChfHandler handler;
void* unwind_context;
void* handler_context;
ChfPointer handler_context;
} ChfHandlerDescriptor;
/* CHF Context */
typedef struct ChfContext_S {
typedef struct ChfContext_S /* CHF Context */
{
ChfState state; /* Current CHF state */
const char* app_name; /* Application's name */
int options; /* Options */
const ChfChar* app_name; /* Application's name */
ChfOptions options; /* Options */
void* mrs_data; /* Message retrieval private data */
ChfMrsGet mrs_get; /* 'GetMessage' function */
ChfMrsExit mrs_exit; /* 'Exit' function */
@ -92,7 +97,7 @@ typedef struct ChfContext_S {
ChfDescriptor* condition_sp; /* Current condition stack pointer */
ChfHandlerDescriptor* handler_stack; /* Handler stack */
ChfHandlerDescriptor* handler_sp; /* Current handler stack pointer */
char* message_buffer; /* Message buffer */
ChfChar* message_buffer; /* Message buffer */
} ChfContext;
/* -------------------------------------------------------------------------
@ -117,24 +122,13 @@ extern ChfContext _chf_context; /* CHF Context */
ChfContext* _ChfGetContext( void );
#endif
/* Generic initialization */
int ChfInit( const int module_id, const char* app_name, /* Application's name */
const int options, /* Options */
void* mrs_data, /* Message retrieval private data */
ChfMrsGet mrs_get, /* 'GetMessage' function */
ChfMrsExit mrs_exit, /* 'Exit' function */
const int condition_stack_size, /* Size of the condition stack */
const int handler_stack_size, /* Size of the handler stack */
const int exit_code /* Abnormal exit code */
);
/* -------------------------------------------------------------------------
Private redirection of stdlib functions needed by Win32
------------------------------------------------------------------------- */
/* Abort application */
void ChfAbort( const int abort_code );
/* Build a condition message */
char* ChfBuildMessage( const ChfDescriptor* descriptor );
/* Retrieve a condition message */
const char* ChfGetMessage( const int module_id, const int condition_code, const char* default_message );
#endif /*!_CHF_PRIV_H*/
#define ChfStrlen strlen
#define ChfStrcpy strcpy
#define ChfStrcat strcat
#define ChfStrncpy strncpy
#define ChfSprintf sprintf
#define ChfVsprintf vsprintf

View file

@ -30,8 +30,14 @@
.- */
#ifndef lint
static char rcs_id[] = "$Id: chf_abrt.c,v 2.2 2001/01/25 12:08:24 cibrario Exp $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <setjmp.h>
#include "Chf.h"
#include "ChfPriv.h"
@ -40,6 +46,23 @@
# include <pthread.h>
#endif
/* Abort codes message table; the relative position of the messages must
match the numeric codes CHF_ABORT_xxxx defined in ChfPriv.h
*/
static const ChfChar* message_table[] = { ( const ChfChar* )NULL,
ChfText( "Not initialized" ),
ChfText( "Temporary message buffer overflow" ),
ChfText( "Invalid action from last chance handler" ),
ChfText( "Already initialized" ),
ChfText( "Unwind request while unwinding" ),
ChfText( "Improperly handled condition" ),
ChfText( "Fatal condition while unwinding" ),
ChfText( "Condition stack overflow" ),
ChfText( "Can't prime a new Chf context" ),
ChfText( "Pthread interaction failed" ) };
#define MESSAGE_TABLE_SIZE ( sizeof( message_table ) / sizeof( const ChfChar* ) )
/* .+
.title : ChfAbort
@ -87,36 +110,22 @@
- added Win32 support
.- */
/* Abort application */
void ChfAbort( const int abort_code )
void ChfAbort( /* Abort application */
const int abort_code )
{
/* Abort codes message table; the relative position of the messages must
match the numeric codes CHF_ABORT_xxxx defined in ChfPriv.h
*/
const char* message_table[] = { ( const char* )NULL,
"Not initialized",
"Temporary message buffer overflow",
"Invalid action from last chance handler",
"Already initialized",
"Unwind request while unwinding",
"Improperly handled condition",
"Fatal condition while unwinding",
"Condition stack overflow",
"Can't prime a new Chf context",
"Pthread interaction failed" };
if ( abort_code != CHF_ABORT_SILENT ) {
fputs( "ChfAbort-F-", stderr );
fputs( CHF_ABORT_HEADER, stderr );
if ( abort_code < 0 || abort_code >= ( int )MESSAGE_TABLE_SIZE )
fprintf( stderr, CHF_ABORT_BAD_CODE_FMT, abort_code );
if ( abort_code < 0 || abort_code >= ( int )( sizeof( message_table ) / sizeof( const char* ) ) )
fprintf( stderr, "Bad abort code <%d>d\n", abort_code );
else
fprintf( stderr, "%s\n", message_table[ abort_code ] );
fprintf( stderr, CHF_ABORT_GOOD_CODE_FMT, message_table[ abort_code ] );
}
if ( chf_context.state == CHF_UNKNOWN || chf_context.options & CHF_ABORT )
abort();
else
#ifndef _REENTRANT
exit( chf_context.exit_code );

View file

@ -24,7 +24,14 @@
.- */
#ifndef lint
static char rcs_id[] = "$Id: chf_gen.c,v 2.2 2001/01/25 12:10:22 cibrario Exp $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <setjmp.h>
#include <stdarg.h>
#include <string.h>
@ -76,9 +83,9 @@
1.1, 3-May-1996, creation
.- */
/* Generate a condition into the stack */
void ChfGenerate( const int module_id, const char* file_name, const int line_number, const int condition_code, const ChfSeverity severity,
... )
void ChfGenerate( /* Generate a condition into the stack */
const int module_id, const ChfChar* file_name, const int line_number, const int condition_code,
const ChfSeverity severity, ... )
{
ChfDescriptor* new_descriptor;
va_list aux_arg;
@ -97,25 +104,30 @@ void ChfGenerate( const int module_id, const char* file_name, const int line_num
otherwise abort the application.
*/
if ( new_descriptor - chf_context.condition_stack == chf_context.condition_stack_size ) {
new_descriptor->module_id = module_id;
new_descriptor->module_id = CHF_MODULE_ID;
new_descriptor->condition_code = CHF_F_COND_STACK_FULL;
new_descriptor->severity = CHF_FATAL;
new_descriptor->line_number = CHF_UNKNOWN_LINE_NUMBER;
new_descriptor->file_name = CHF_UNKNOWN_FILE_NAME;
strncpy( new_descriptor->message, ChfGetMessage( module_id, CHF_F_COND_STACK_FULL, "Condition stack is full" ),
CHF_MAX_MESSAGE_LENGTH - 1 );
ChfStrncpy( new_descriptor->message,
ChfGetMessage( CHF_MODULE_ID, CHF_F_COND_STACK_FULL, ChfText( "Condition stack is full" ) ),
CHF_MAX_MESSAGE_LENGTH - 1 );
new_descriptor->message[ CHF_MAX_MESSAGE_LENGTH - 1 ] = '\0';
new_descriptor->next = CHF_NULL_DESCRIPTOR;
chf_context.condition_sp++;
ChfSignal( module_id );
} else
ChfSignal();
}
else
ChfAbort( CHF_ABORT_COND_STACK_OVF );
} else {
char def_message[ CHF_DEF_MESSAGE_LENGTH ];
char tmp_message[ CHF_TMP_MESSAGE_LENGTH ];
}
else {
ChfChar def_message[ CHF_DEF_MESSAGE_LENGTH ];
ChfChar tmp_message[ CHF_TMP_MESSAGE_LENGTH ];
new_descriptor->module_id = module_id;
new_descriptor->condition_code = condition_code;
@ -124,16 +136,16 @@ void ChfGenerate( const int module_id, const char* file_name, const int line_num
new_descriptor->file_name = file_name;
/* Generate the default message */
sprintf( def_message, "Code <%d>d", condition_code );
ChfSprintf( def_message, CHF_DEF_PARTIAL_MSG_FMT, condition_code );
/* Generate the partial message associated with the condition using a
temporary area
*/
if ( vsprintf( tmp_message, ChfGetMessage( module_id, condition_code, def_message ), aux_arg ) >= CHF_TMP_MESSAGE_LENGTH )
if ( ChfVsprintf( tmp_message, ChfGetMessage( module_id, condition_code, def_message ), aux_arg ) >= CHF_TMP_MESSAGE_LENGTH )
ChfAbort( CHF_ABORT_MSG_OVF );
/* Copy the message into the condition descriptor */
strncpy( new_descriptor->message, tmp_message, CHF_MAX_MESSAGE_LENGTH - 1 );
ChfStrncpy( new_descriptor->message, tmp_message, CHF_MAX_MESSAGE_LENGTH - 1 );
new_descriptor->message[ CHF_MAX_MESSAGE_LENGTH - 1 ] = '\0';
/* Link the new descriptor with the current descriptor list, if it

View file

@ -37,6 +37,15 @@
.- */
#ifndef lint
static char rcs_id[] = "$Id: chf_hdlr.c,v 2.2 2001/01/25 12:12:46 cibrario Exp $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <setjmp.h>
#include "Chf.h"
#include "ChfPriv.h"
@ -73,12 +82,12 @@
2.1, 19-May-2000, creation
.- */
static ChfAction StructuredHelper( const ChfDescriptor* desc, const ChfState state, void* handler_context )
static ChfAction StructuredHelper( const ChfDescriptor* desc, const ChfState state, ChfPointer handler_context )
{
ChfAction action;
const ChfDescriptor* d;
return ( ( state == CHF_SIGNALING && desc->severity == CHF_FATAL ) ? CHF_UNWIND_KEEP : CHF_RESIGNAL );
return ( ( state == CHF_SIGNALING && ChfGetSeverity( desc ) == CHF_FATAL ) ? CHF_UNWIND_KEEP : CHF_RESIGNAL );
}
/* .+
@ -123,7 +132,7 @@ static ChfAction StructuredHelper( const ChfDescriptor* desc, const ChfState sta
.input :
ChfHandler new_handler, new condition handler
void *unwind_context, handler unwind context pointer
void* handler_context, private handler context pointer
ChfPointer handler_context, private handler context pointer
.output :
void
.status_codes :
@ -139,25 +148,89 @@ static ChfAction StructuredHelper( const ChfDescriptor* desc, const ChfState sta
- added StructuredHelper handling
.- */
/* Push a new handler into the stack */
void ChfPushHandler( const int module_id, ChfHandler new_handler, void* unwind_context, void* handler_context )
void ChfPushHandler( /* Push a new handler into the stack */
ChfHandler new_handler, void* unwind_context, ChfPointer handler_context )
{
/* Make sure that CHF has been correctly initialized and is idle */
if ( chf_context.state == CHF_UNKNOWN )
ChfAbort( CHF_ABORT_INIT );
if ( chf_context.state != CHF_IDLE ) {
ChfGenerate( module_id, __FILE__, __LINE__, CHF_F_BAD_STATE, CHF_FATAL );
ChfSignal( module_id );
} else
/* Check if the handler stack is full */
if ( chf_context.handler_sp - chf_context.handler_stack >= chf_context.handler_stack_size ) {
ChfGenerate( module_id, __FILE__, __LINE__, CHF_F_HDLR_STACK_FULL, CHF_FATAL );
ChfSignal( module_id );
} else {
chf_context.handler_sp->unwind_context = unwind_context;
chf_context.handler_sp->handler_context = handler_context;
chf_context.handler_sp->handler = ( ( new_handler == CHF_NULL_HANDLER ) ? StructuredHelper : new_handler );
chf_context.handler_sp++;
}
ChfCondition CHF_F_BAD_STATE, CHF_FATAL ChfEnd;
ChfSignal();
}
/* Check if the handler stack is full */
else if ( chf_context.handler_sp - chf_context.handler_stack >= chf_context.handler_stack_size ) {
ChfCondition CHF_F_HDLR_STACK_FULL, CHF_FATAL ChfEnd;
ChfSignal();
}
else {
chf_context.handler_sp->unwind_context = unwind_context;
chf_context.handler_sp->handler_context = handler_context;
chf_context.handler_sp->handler = ( ( new_handler == CHF_NULL_HANDLER ) ? StructuredHelper : new_handler );
chf_context.handler_sp++;
}
}
/* .+
.title : ChfPopHandler
.kind : C function
.creation : 13-May-1996
.description :
This function pops the topmost condition handler from the handler stack and
returns to the caller.
If some error occours during the execution, the function will generate
and immediately signal one of the conditions listed below and marked with
(*). The function will never return directly to the caller, since all
conditions are CHF_FATAL.
NOTE: This function calls ChfAbort() with abort code CHF_ABORT_INIT if
the CHF subsystem has not been initialized.
.call :
ChfPopHandler();
.input :
void
.output :
void
.status_codes :
CHF_F_BAD_STATE, bad CHF state for requested operation
CHF_F_HDLR_STACK_FULL, the handler stack is full
.notes :
1.1, 13-May-1996, creation
1.6, 15-Jan-1997, update:
- improved documentation
2.1, 19-May-2000, update:
- improved documentation
.- */
void ChfPopHandler( /* Pop a handler */
void )
{
/* Make sure that CHF has been correctly initialized and is idle */
if ( chf_context.state == CHF_UNKNOWN )
ChfAbort( CHF_ABORT_INIT );
if ( chf_context.state != CHF_IDLE ) {
ChfCondition CHF_F_BAD_STATE, CHF_FATAL ChfEnd;
ChfSignal();
}
/* Check if the handler stack is empty */
else if ( chf_context.handler_sp == chf_context.handler_stack ) {
ChfCondition CHF_F_HDLR_STACK_EMPTY, CHF_FATAL ChfEnd;
ChfSignal();
}
/* Discard the topmost condition handler */
else
--chf_context.handler_sp;
}

View file

@ -47,8 +47,14 @@
.- */
#ifndef lint
static char rcs_id[] = "$Id: chf_init.c,v 2.2 2001/01/25 14:05:23 cibrario Exp $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <setjmp.h>
#include <string.h>
#include "Chf.h"
@ -58,12 +64,17 @@
Global and static variables
------------------------------------------------------------------------- */
/* Chf Library Id */
#ifndef lint
static ChfChar rcs_lib_id[] = CHF_LIBRARY_ID;
#endif
/* CHF context */
ChfContext _chf_context;
/* Message separator and severity names for ChfBuildMessage() */
static const char separator[] = "-";
static const char* severity_name[] = { "S", "I", "W", "E", "F" };
static const ChfChar separator[] = CHF_MESSAGE_SEPARATOR;
static const ChfChar* severity_name[] = CHF_SEVERITY_NAMES;
/* -------------------------------------------------------------------------
Multithreading support
@ -148,7 +159,7 @@ static void DestroyContext( void* context )
- added Win32 support
.- */
static ChfAction DefaultHandler( const ChfDescriptor* desc, const ChfState state, void* handler_context )
static ChfAction DefaultHandler( const ChfDescriptor* desc, const ChfState state, ChfPointer handler_context )
{
ChfAction action;
const ChfDescriptor* d;
@ -162,12 +173,12 @@ static ChfAction DefaultHandler( const ChfDescriptor* desc, const ChfState state
is done atomically if multithreading support is enabled.
In Win32, the default handler does not print anything.
*/
if ( desc->severity > CHF_SUCCESS ) {
if ( ChfGetSeverity( desc ) > CHF_SUCCESS ) {
#ifdef _REENTRANT
if ( pthread_mutex_lock( &fputs_mutex ) )
ChfAbort( CHF_ABORT_PTHREAD );
#endif
for ( d = desc; d != CHF_NULL_DESCRIPTOR; d = d->next )
for ( d = desc; d != CHF_NULL_DESCRIPTOR; d = ChfGetNextDescriptor( d ) )
fputs( ChfBuildMessage( d ), stderr );
#ifdef _REENTRANT
if ( pthread_mutex_unlock( &fputs_mutex ) )
@ -176,7 +187,7 @@ static ChfAction DefaultHandler( const ChfDescriptor* desc, const ChfState state
}
/* Determine the handler action */
switch ( desc->severity ) {
switch ( ChfGetSeverity( desc ) ) {
case CHF_SUCCESS:
case CHF_INFO:
case CHF_WARNING:
@ -226,18 +237,18 @@ static ChfAction DefaultHandler( const ChfDescriptor* desc, const ChfState state
1.1, 16-May-1996, creation
.- */
static char* scopy( char* p, const char* q, char* p_end )
static ChfChar* scopy( ChfChar* p, const ChfChar* q, ChfChar* p_end )
{
size_t q_len = strlen( q );
size_t q_len = ChfStrlen( q );
size_t p_avail = p_end - p;
if ( q_len < p_avail ) {
strcpy( p, q );
ChfStrcpy( p, q );
p += q_len;
}
else if ( p_avail > 1 ) {
strncpy( p, q, p_avail - 2 );
ChfStrncpy( p, q, p_avail - 2 );
p[ p_avail - 1 ] = '\0';
p = p_end;
}
@ -289,10 +300,10 @@ static char* scopy( char* p, const char* q, char* p_end )
- added Win32 support
.- */
/* Retrieve a condition message */
const char* ChfGetMessage( const int module_id, const int condition_code, const char* default_message )
const ChfChar* ChfGetMessage( /* Retrieve a condition message */
const int module_id, const int condition_code, const ChfChar* default_message )
{
const char* message;
const ChfChar* message;
/* Check that CHF has been correctly initialized */
if ( chf_context.state == CHF_UNKNOWN )
@ -339,12 +350,12 @@ const char* ChfGetMessage( const int module_id, const int condition_code, const
- added Win32 support
.- */
/* Build a condition message */
char* ChfBuildMessage( const ChfDescriptor* descriptor )
ChfChar* ChfBuildMessage( /* Build a condition message */
const ChfDescriptor* descriptor )
{
char* tmp_p;
char* tmp_end;
char def_message[ CHF_DEF_MESSAGE_LENGTH ];
ChfChar* tmp_p;
ChfChar* tmp_end;
ChfChar def_message[ CHF_DEF_MESSAGE_LENGTH ];
ChfSeverity severity;
/* Check that CHF has been correctly initialized */
@ -364,18 +375,18 @@ char* ChfBuildMessage( const ChfDescriptor* descriptor )
}
else
tmp_p = scopy( tmp_p, "\t", tmp_end );
tmp_p = scopy( tmp_p, ChfText( "\t" ), tmp_end );
/* The message continues with the module name */
sprintf( def_message, "Mid <%d>d", descriptor->module_id );
ChfSprintf( def_message, CHF_DEF_MID_MSG_FMT, ChfGetModuleId( descriptor ) );
tmp_p = scopy( tmp_p, ChfGetMessage( CHF_MODULE_NAMES_SET, descriptor->module_id, def_message ), tmp_end );
tmp_p = scopy( tmp_p, ChfGetMessage( CHF_MODULE_NAMES_SET, ChfGetModuleId( descriptor ), def_message ), tmp_end );
/* Add also the extended information, if any */
if ( descriptor->line_number != CHF_UNKNOWN_LINE_NUMBER ) {
tmp_p = scopy( tmp_p, " ", tmp_end );
if ( ChfGetLineNumber( descriptor ) != CHF_UNKNOWN_LINE_NUMBER ) {
tmp_p = scopy( tmp_p, ChfText( " " ), tmp_end );
sprintf( def_message, "(%s:%i)", descriptor->file_name, descriptor->line_number );
ChfSprintf( def_message, CHF_EXTENDED_INFO_FMT, ChfGetFileName( descriptor ), ChfGetLineNumber( descriptor ) );
tmp_p = scopy( tmp_p, def_message, tmp_end );
}
@ -383,14 +394,16 @@ char* ChfBuildMessage( const ChfDescriptor* descriptor )
tmp_p = scopy( tmp_p, separator, tmp_end );
/* Add the severity code of the message */
tmp_p = scopy( tmp_p, ( ( severity = descriptor->severity ) < CHF_SUCCESS || severity > CHF_FATAL ) ? "?" : severity_name[ severity ],
tmp_p = scopy( tmp_p,
( ( severity = ChfGetSeverity( descriptor ) ) < CHF_SUCCESS || severity > CHF_FATAL ) ? CHF_UNKNOWN_SEVERITY
: severity_name[ severity ],
tmp_end );
tmp_p = scopy( tmp_p, separator, tmp_end );
/* The message ends with the partial message from the descriptor */
tmp_p = scopy( tmp_p, descriptor->message, tmp_end );
( void )scopy( tmp_p, "\n", tmp_end );
tmp_p = scopy( tmp_p, ChfGetPartialMessage( descriptor ), tmp_end );
( void )scopy( tmp_p, CHF_MESSAGE_TERMINATOR, tmp_end );
return chf_context.message_buffer;
}
@ -421,7 +434,7 @@ char* ChfBuildMessage( const ChfDescriptor* descriptor )
exit_code);
.input :
const char *app_name, Application's name
const int options, Options
const ChfOptions options, Options
void *mrs_data, Message retrieval private data
ChfMrsGet mrs_get, 'GetMessage' function
ChfMrsExit mrs_exit, 'Exit' function
@ -442,15 +455,15 @@ char* ChfBuildMessage( const ChfDescriptor* descriptor )
- added Win32 support; a malloc() call was not portable.
.- */
/* Generic initialization */
int ChfInit( const int module_id, const char* app_name, /* Application's name */
const int options, /* Options */
void* mrs_data, /* Message retrieval private data */
ChfMrsGet mrs_get, /* 'GetMessage' function */
ChfMrsExit mrs_exit, /* 'Exit' function */
const int condition_stack_size, /* Size of the condition stack */
const int handler_stack_size, /* Size of the handler stack */
const int exit_code /* Abnormal exit code */
int ChfInit( /* Generic initialization */
const ChfChar* app_name, /* Application's name */
const ChfOptions options, /* Options */
void* mrs_data, /* Message retrieval private data */
ChfMrsGet mrs_get, /* 'GetMessage' function */
ChfMrsExit mrs_exit, /* 'Exit' function */
const int condition_stack_size, /* Size of the condition stack */
const int handler_stack_size, /* Size of the handler stack */
const int exit_code /* Abnormal exit code */
)
{
int cc;
@ -481,8 +494,8 @@ int ChfInit( const int module_id, const char* app_name, /* Application's name */
cc = CHF_F_MALLOC;
}
else if ( ( _chf_context.message_buffer = ( char* )malloc( ( size_t )( CHF_MAX_MESSAGE_LENGTH ) * sizeof( char ) ) ) ==
( char* )NULL ) {
else if ( ( _chf_context.message_buffer = ( ChfChar* )malloc( ( size_t )( CHF_MAX_MESSAGE_LENGTH ) * sizeof( ChfChar ) ) ) ==
( ChfChar* )NULL ) {
free( _chf_context.condition_stack );
free( _chf_context.handler_stack );
cc = CHF_F_MALLOC;
@ -520,7 +533,7 @@ int ChfInit( const int module_id, const char* app_name, /* Application's name */
/* Push the default handler; in the reentrant case, this will be
done once per thread, when the thread-specific context is primed.
*/
ChfPushHandler( module_id, DefaultHandler, CHF_NULL_CONTEXT, CHF_NULL_POINTER );
ChfPushHandler( DefaultHandler, CHF_NULL_CONTEXT, CHF_NULL_POINTER );
#endif
cc = CHF_S_OK;
@ -582,15 +595,15 @@ void ChfExit( void )
}
#endif
/* Destroy the context associated with this thread now; this is necessary
to ensure that the context is actually destroyed when a single-threaded
application links with the multithreaded version of Chf: in this case,
pthread_exit() is called *after* ChfExit(), the Chf data key no longer
exists when pthread_exit() is called and the destructor registered
with pthread_key_create() does not take place.
The data pointer associated with the Chf data key is set to NULL to
avoid any subsequent reactivation of the destructor.
*/
/* Destroy the context associated with this thread now; this is necessary
to ensure that the context is actually destroyed when a single-threaded
application links with the multithreaded version of Chf: in this case,
pthread_exit() is called *after* ChfExit(), the Chf data key no longer
exists when pthread_exit() is called and the destructor registered
with pthread_key_create() does not take place.
The data pointer associated with the Chf data key is set to NULL to
avoid any subsequent reactivation of the destructor.
*/
#ifdef _REENTRANT
DestroyContext( &chf_context );
if ( pthread_setspecific( data_key, ( void* )NULL ) ) {
@ -694,7 +707,7 @@ ChfContext* _ChfGetContext( void )
ChfAbort( CHF_ABORT_GET_CONTEXT );
/* Push the default handler */
ChfPushHandler( module_id, DefaultHandler, CHF_NULL_CONTEXT, CHF_NULL_POINTER );
ChfPushHandler( DefaultHandler, CHF_NULL_CONTEXT, CHF_NULL_POINTER );
}
return context;

151
libChf/src/chf_msgc.c Normal file
View file

@ -0,0 +1,151 @@
/* .+
.identifier : $Id: chf_msgc.c,v 2.2 2001/01/25 14:06:47 cibrario Exp $
.context : CHF, Condition Handling Facility
.title : $RCSfile: chf_msgc.c,v $, condition generation
.kind : C source
.author : Ivan Cibrario B.
.site : CSTV-CNR
.creation : 17-May-1996
.keywords : *
.description :
This module contains the CHF initialization function ChfMsgcatInit()
.include : Chf.h
.notes :
$Log: chf_msgc.c,v $
Revision 2.2 2001/01/25 14:06:47 cibrario
Added partial Win32 support (Windows CE only).
Revision 1.3 1996/06/21 14:19:22 cibrario
Bug fix: the private context of the message retrieval facility was
never freed by ExitMessage()
Revision 1.1 1996/05/28 12:55:15 cibrario
Initial revision
.- */
#ifndef lint
static char rcs_id[] = "$Id: chf_msgc.c,v 2.2 2001/01/25 14:06:47 cibrario Exp $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <setjmp.h>
#include <string.h>
#include <locale.h>
#include <nl_types.h>
#include "Chf.h"
#include "ChfPriv.h"
/* -------------------------------------------------------------------------
Global and static variables
------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------
Private type definitions
------------------------------------------------------------------------- */
typedef struct {
nl_catd catalog; /* Message catalog descriptor */
} ChfMsgcatContext;
/* -------------------------------------------------------------------------
Private functions
------------------------------------------------------------------------- */
static const char* GetMessage( void* private_context, const int module_id, const int condition_code, const char* default_message )
{
return ( catgets( ( ( ChfMsgcatContext* )private_context )->catalog, module_id, condition_code, default_message ) );
}
static void ExitMessage( void* private_context )
{
( void )catclose( ( ( ChfMsgcatContext* )private_context )->catalog );
free( private_context );
}
/* -------------------------------------------------------------------------
Public functions
------------------------------------------------------------------------- */
/* .+
.title : ChfMsgcatInit
.kind : C function
.creation : 17-May-1996
.description :
This function initializes CHF and returns to the caller a condition code;
that code will be either CHF_S_OK if the initialization was succesful,
or one of the other values listed below.
It's necessary to invoke succesfully either ChfMsgcatInit() or one of the
other CHF initialization routines before using any other CHF function.
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_DUP_INIT
if CHF has already been initialized before.
WIN32:
- this function is not available due to lack of system support, and
always returns CHF_F_NOT_AVAILABLE
.call :
cc = ChfMsgcatInit(app_name, options,
msgcat_name,
condition_stack_size, handler_stack_size,
exit_code);
.input :
const char *app_name, Application's name
const ChfOptions options, Options
const char *msgcat_name, Name of the message catalog
const int condition_stack_size, Size of the condition stack
const int handler_stack_size, Size of the handler stack
const int exit_code, Abnormal exit code
.output :
int cc, condition code
.status_codes :
CHF_F_SETLOCALE, setlocale() failed
CHF_F_CATOPEN, catopen() failed
CHF_F_MALLOC, FATAL, memory allocation failed
CHF_F_NOT_AVAILABLE, FATAL, function not available
.notes :
1.1, 17-May-1996, creation
2.2, 22-Jan-2001, update:
- added Win32 support
.- */
int ChfMsgcatInit( /* Initialization with msgcat subsystem */
const ChfChar* app_name, /* Application's name */
const ChfOptions options, /* Options */
const ChfChar* msgcat_name, /* Name of the message catalog */
const int condition_stack_size, /* Size of the condition stack */
const int handler_stack_size, /* Size of the handler stack */
const int exit_code /* Abnormal exit code */
)
{
ChfMsgcatContext* private_context;
int cc;
if ( ( private_context = ( ChfMsgcatContext* )malloc( sizeof( ChfMsgcatContext ) ) ) == ( ChfMsgcatContext* )NULL )
cc = CHF_F_MALLOC;
else if ( setlocale( LC_ALL, "" ) == ( char* )NULL ) {
free( private_context );
cc = CHF_F_SETLOCALE;
} else if ( ( private_context->catalog = catopen( msgcat_name, 0 ) ) == ( nl_catd )( -1 ) ) {
free( private_context );
cc = CHF_F_CATOPEN;
} else if ( ( cc = ChfInit( app_name, options, ( void* )private_context, GetMessage, ExitMessage, condition_stack_size,
handler_stack_size, exit_code ) ) != CHF_S_OK ) {
( void )catclose( private_context->catalog );
free( private_context );
} else
cc = CHF_S_OK;
return cc;
}

View file

@ -37,6 +37,13 @@
.- */
#ifndef lint
static char rcs_id[] = "$Id: chf_sig.c,v 2.2 2001/01/25 14:07:42 cibrario Exp $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <setjmp.h>
#include "Chf.h"
@ -84,7 +91,7 @@
- added support for structured condition handling
.- */
void ChfSignal( const int module_id )
void ChfSignal( void )
{
ChfState saved_state;
ChfDescriptor* saved_condition_base;
@ -162,21 +169,23 @@ void ChfSignal( const int module_id )
if ( chf_context.condition_sp > chf_context.condition_base ) {
if ( chf_context.state == CHF_SIGNALING ) {
/* Force the new severity to CHF_FATAL if necessary */
if ( current_condition->severity == CHF_FATAL )
( chf_context.condition_sp - 1 )->severity = CHF_FATAL;
if ( ChfGetSeverity( current_condition ) == CHF_FATAL )
ChfGetSeverity( chf_context.condition_sp - 1 ) = CHF_FATAL;
/* Link together the condition groups */
chf_context.condition_base->next = current_condition;
current_condition = chf_context.condition_sp - 1;
chf_context.condition_base = chf_context.condition_sp;
} else
}
else
chf_context.condition_sp = chf_context.condition_base;
}
/* The action CHF_CONTINUE is not allowed if the current condition
severity is CHF_FATAL; it's automatically changed to CHF_RESIGNAL
*/
if ( handler_result == CHF_CONTINUE && current_condition->severity == CHF_FATAL )
if ( handler_result == CHF_CONTINUE && ChfGetSeverity( current_condition ) == CHF_FATAL )
handler_result = CHF_RESIGNAL;
}
@ -285,7 +294,7 @@ void ChfSignal( const int module_id )
if ( unwind_handler->unwind_context == CHF_NULL_CONTEXT )
ChfAbort( CHF_ABORT_SILENT );
else
siglongjmp( unwind_handler->unwind_context, 1 );
ChfSiglongjmp( unwind_handler->unwind_context, 1 );
}
break;
@ -305,10 +314,12 @@ void ChfSignal( const int module_id )
otherwise call ChfAbort()
*/
if ( chf_context.handler_sp > chf_context.handler_stack ) {
ChfGenerate( module_id, __FILE__, __LINE__, CHF_F_INVALID_ACTION, CHF_FATAL, handler_result );
ChfCondition CHF_F_INVALID_ACTION, CHF_FATAL, handler_result ChfEnd;
ChfSignal( module_id );
} else
ChfSignal();
}
else
ChfAbort( CHF_ABORT_INVALID_ACTION );
break;
@ -319,3 +330,42 @@ void ChfSignal( const int module_id )
/* Restore the old CHF state */
chf_context.state = saved_state;
}
/* .+
.title : ChfDiscard
.kind : C function
.creation : 17-May-1996
.description :
This function discards the topmost condition group currently in the
condition stack, without signalling it. The function does nothing if
the condition stack is empty.
NOTE: This function uses the CHF function 'ChfAbort()' to
abort the application if either
- CHF has not been initialized correctly (abort code CHF_ABORT_INIT)
.call :
ChfDiscard();
.input :
void
.output :
void
.status_codes :
none
.notes :
1.1, 17-May-1996, creation
.- */
void ChfDiscard( /* Discard the current conditions */
void )
{
/* Check that CHF has been correctly initialized */
if ( chf_context.state == CHF_UNKNOWN )
ChfAbort( CHF_ABORT_INIT );
/* Reset the current condition stack pointer to the current condition
stack base pointer
*/
chf_context.condition_sp = chf_context.condition_base;
}

View file

@ -24,13 +24,23 @@
.- */
#ifndef lint
static char rcs_id[] = "$Id: chf_st.c,v 2.2 2001/01/25 14:08:45 cibrario Exp $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <setjmp.h>
#include <string.h>
#include "Chf.h"
#include "ChfPriv.h"
/* -------------------------------------------------------------------------
Global and static variables
------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------
Private type definitions
------------------------------------------------------------------------- */
@ -52,17 +62,20 @@ static int Search( const void* l, const void* r )
{
if ( ( ( ChfTable* )l )->module > ( ( ChfTable* )r )->module )
return ( GT );
else if ( ( ( ChfTable* )l )->module < ( ( ChfTable* )r )->module )
return ( LT );
else if ( ( ( ChfTable* )l )->code > ( ( ChfTable* )r )->code )
return ( GT );
else if ( ( ( ChfTable* )l )->code < ( ( ChfTable* )r )->code )
return ( LT );
return ( EQ );
}
static const char* StGetMessage( void* private_context, const int module_id, const int condition_code, const char* default_message )
static const ChfChar* StGetMessage( void* private_context, const int module_id, const int condition_code, const ChfChar* default_message )
{
ChfTable key;
ChfTable* res;
@ -106,7 +119,7 @@ static void ExitMessage( void* private_context ) {}
exit_code);
.input :
const char *app_name, Application's name
const int options, Options
const ChfOptions options, Options
const ChfTable *table, pointer to the static message table
const size_t table_size, size of the table (# of entries)
const int condition_stack_size, Size of the condition stack
@ -120,14 +133,14 @@ static void ExitMessage( void* private_context ) {}
1.1, 27-May-1996, creation
.- */
/* Initialization with static message tables */
int ChfStaticInit( const int module_id, const char* app_name, /* Application's name */
const int options, /* Options */
const ChfTable* table, /* Static message table */
const size_t table_size, /* Size of the message table */
const int condition_stack_size, /* Size of the condition stack */
const int handler_stack_size, /* Size of the handler stack */
const int exit_code /* Abnormal exit code */
int ChfStaticInit( /* Initialization with static message tables */
const ChfChar* app_name, /* Application's name */
const ChfOptions options, /* Options */
const ChfTable* table, /* Static message table */
const size_t table_size, /* Size of the message table */
const int condition_stack_size, /* Size of the condition stack */
const int handler_stack_size, /* Size of the handler stack */
const int exit_code /* Abnormal exit code */
)
{
ChfStaticContext* private_context;
@ -135,7 +148,7 @@ int ChfStaticInit( const int module_id, const char* app_name, /* Application's n
if ( ( private_context = ( ChfStaticContext* )malloc( sizeof( ChfStaticContext ) ) ) == ( ChfStaticContext* )NULL )
cc = CHF_F_MALLOC;
else if ( ( cc = ChfInit( module_id, app_name, options, ( void* )private_context, StGetMessage, ExitMessage, condition_stack_size,
else if ( ( cc = ChfInit( app_name, options, ( void* )private_context, StGetMessage, ExitMessage, condition_stack_size,
handler_stack_size, exit_code ) ) != CHF_S_OK )
free( private_context );
else {

106
libChf/src/chf_top.c Normal file
View file

@ -0,0 +1,106 @@
/* .+
.identifier : $Id: chf_top.c,v 2.2 2001/01/25 14:09:21 cibrario Exp $
.context : CHF, Condition Handling Facility
.title : $RCSfile: chf_top.c,v $
.kind : C source
.author : Ivan Cibrario B.
.site : CSTV-CNR
.creation : 5-Jun-1996
.keywords : *
.description :
This module implements the CHF function ChfGetTopCondition()
.include : Chf.h
.notes :
$Log: chf_top.c,v $
Revision 2.2 2001/01/25 14:09:21 cibrario
Added partial Win32 support (Windows CE only).
Revision 2.1 2000/05/26 14:23:33 cibrario
ChfGetTopCondition() used to return a pointer to the wrong condition
descriptor; fixed.
Revision 1.2 1996/06/11 12:47:17 cibrario
file creation
.- */
#ifndef lint
static char rcs_id[] = "$Id: chf_top.c,v 2.2 2001/01/25 14:09:21 cibrario Exp $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <setjmp.h>
#include <string.h>
#include "Chf.h"
#include "ChfPriv.h"
/* -------------------------------------------------------------------------
Public functions
------------------------------------------------------------------------- */
/* .+
.title : ChfGetTopCondition
.kind : C function
.creation : 5-Jun-1996
.description :
This function returns to the caller a pointer to the top condition of
the current condition group. It generates and immediately signals the
condition CHF_F_BAD_STATE if the current condition group is empty.
NOTE: During condition signalling, CHF creates a new, empty, condition group
immediately before starting the invocation sequence of the condition
handlers, as described in the documentation. Therefore
ChfGetTopCondition(), if called from a condition handler, will return
a pointer to the top condition generated during the handling ONLY, and
NOT to the top condition of the condition group being signalled. The
latter pointer is directly available, as an argument, to the condition
handlers.
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_INIT
if CHF hasn't been correctly initialized.
NOTE: The returned pointer is no longer valid when any other CHF function
is called after ChfGetTopCondition().
.call :
d = ChfGetTopCondition();
.input :
void
.output :
const ChfDescriptor *d, condition descriptor
.status_codes :
.notes :
1.2, 17-May-1996, creation
2.1, 24-May-2000, bug fix:
- condition stack referenced incorrectly
.- */
const ChfDescriptor* ChfGetTopCondition( /* Retrieve top condition */
void )
{
ChfDescriptor* d;
/* Check that CHF has been correctly initialized */
if ( chf_context.state == CHF_UNKNOWN )
ChfAbort( CHF_ABORT_INIT );
if ( ( d = chf_context.condition_sp ) == chf_context.condition_base ) {
ChfCondition CHF_F_BAD_STATE, CHF_FATAL ChfEnd;
ChfSignal();
}
/* The top element of the condition group is the element immediately
below the stack pointer.
*/
return d - 1;
}

15
libChf/src/resource.h Normal file
View file

@ -0,0 +1,15 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by chf.rc
//
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
# ifndef APSTUDIO_READONLY_SYMBOLS
# define _APS_NEXT_RESOURCE_VALUE 101
# define _APS_NEXT_COMMAND_VALUE 40001
# define _APS_NEXT_CONTROL_VALUE 1000
# define _APS_NEXT_SYMED_VALUE 101
# endif
#endif

40
libChf/tests/chf.msf Normal file
View file

@ -0,0 +1,40 @@
$ .+
$ .
$ .identifier : $Id: chf.msf,v 2.2 2001/01/25 12:00:19 cibrario Exp $
$ .context :
$ .title : $RCSfile: chf.msf,v $
$ .kind : Makefile
$ .author : Ivan Cibrario B.
$ .site : CSTV-CNR
$ .creation : 27-May-1996
$ .keywords : *
$ .description :
$ . Message source file for the CHF conditions
$ .notes :
$ . $Log: chf.msf,v $
$ . Revision 2.2 2001/01/25 12:00:19 cibrario
$ . Added partial Win32 support (Windows CE only).
$ .
$ . Revision 2.1 2000/05/26 14:17:21 cibrario
$ . Updated documentation block and RCS log message header to prevent
$ . gencat warnings on Linux boxes
$ .
$ . Revision 1.1 1996/05/28 12:57:06 cibrario
$ . Initial revision
$ .
$ .-
$set 1
2 Chf
3 Errno
$set 2
1 Condition stack is full
2 Handler stack is full
3 Handler stack is empty
4 Wrong Chf state for requested operation
5 Invalid action code from handler (code=<%d>d)
6 Dynamic memory allocation failed
7 Function not implemented
10 setlocale() failed
11 catopen() failed

View file

@ -16,7 +16,7 @@
#define CHF_MODULE_ID 255
#define CHF_EXTENDED_INFO
#include "../src/Chf.h"
#include "Chf.h"
int main( int argc, char* argv[] )
{
@ -44,7 +44,7 @@ int main( int argc, char* argv[] )
exit( EXIT_FAILURE );
/* Generate a condition and check descriptor; this is line 46 */
CHF_Condition 3, CHF_WARNING, 456 ChfEnd;
ChfCondition 3, CHF_WARNING, 456 ChfEnd;
if ( ( d = ChfGetTopCondition() ) == NULL )
exit( EXIT_FAILURE );
@ -53,7 +53,7 @@ int main( int argc, char* argv[] )
exit( EXIT_FAILURE );
/* Generate another condition and check; this is line 60 */
CHF_Condition 4, CHF_INFO, "arg" ChfEnd;
ChfCondition 4, CHF_INFO, "arg" ChfEnd;
if ( ( e = ChfGetTopCondition() ) == NULL )
exit( EXIT_FAILURE );
@ -65,7 +65,7 @@ int main( int argc, char* argv[] )
ChfDiscard();
/* This is line 77 */
CHF_Condition 5, CHF_ERROR, 456, 789 ChfEnd;
ChfCondition 5, CHF_ERROR, 456, 789 ChfEnd;
if ( ( d = ChfGetTopCondition() ) == NULL )
exit( EXIT_FAILURE );

View file

@ -16,7 +16,7 @@
#define CHF_MODULE_ID 255
#define CHF_EXTENDED_INFO
#include "../src/Chf.h"
#include "Chf.h"
void* task( void* arg )
{
@ -34,7 +34,7 @@ void* task( void* arg )
exit( EXIT_FAILURE );
/* Generate a condition and check descriptor; this is line 36 */
CHF_Condition 3, CHF_WARNING, 456 ChfEnd;
ChfCondition 3, CHF_WARNING, 456 ChfEnd;
if ( ( d = ChfGetTopCondition() ) == NULL )
exit( EXIT_FAILURE );
@ -43,7 +43,7 @@ void* task( void* arg )
exit( EXIT_FAILURE );
/* Generate another condition and check; this is line 50 */
CHF_Condition 4, CHF_INFO, "arg" ChfEnd;
ChfCondition 4, CHF_INFO, "arg" ChfEnd;
if ( ( e = ChfGetTopCondition() ) == NULL )
exit( EXIT_FAILURE );
@ -55,7 +55,7 @@ void* task( void* arg )
ChfDiscard();
/* This is line 67 */
CHF_Condition 5, CHF_ERROR, 456, 789 ChfEnd;
ChfCondition 5, CHF_ERROR, 456, 789 ChfEnd;
if ( ( d = ChfGetTopCondition() ) == NULL )
exit( EXIT_FAILURE );

View file

@ -19,7 +19,7 @@
#define CHF_MODULE_ID 255
#define CHF_EXTENDED_INFO
#include "../src/Chf.h"
#include "Chf.h"
void* task( void* arg )
{
@ -32,11 +32,11 @@ void* task( void* arg )
printf( "\tThread %d\n", ( int )arg );
/* Generate a condition group and signal it */
CHF_Condition 6, CHF_INFO, ( int )arg ChfEnd;
CHF_Condition 6, CHF_INFO, ( int )arg ChfEnd;
CHF_Condition 6, CHF_INFO, ( int )arg ChfEnd;
CHF_Condition 6, CHF_INFO, ( int )arg ChfEnd;
CHF_Condition 7, CHF_INFO, ( int )arg ChfEnd;
ChfCondition 6, CHF_INFO, ( int )arg ChfEnd;
ChfCondition 6, CHF_INFO, ( int )arg ChfEnd;
ChfCondition 6, CHF_INFO, ( int )arg ChfEnd;
ChfCondition 6, CHF_INFO, ( int )arg ChfEnd;
ChfCondition 7, CHF_INFO, ( int )arg ChfEnd;
/* The sleep() is here to increase contention between threads */
sleep( 1 );

View file

@ -19,20 +19,20 @@
#define CHF_MODULE_ID 255
#define CHF_EXTENDED_INFO
#include "../src/Chf.h"
#include "Chf.h"
struct tdata_s {
const ChfDescriptor *d, *e;
int phase;
};
ChfAction h1( const ChfDescriptor* c, const ChfState s, void* p )
ChfAction h1( const ChfDescriptor* c, const ChfState s, ChfPointer p )
{
struct tdata_s* tdata_p = ( struct tdata_s* )p;
ChfAction action;
if ( c != tdata_p->e || ChfGetNextDescriptor( c ) != tdata_p->d ) {
CHF_Condition 10, CHF_FATAL ChfEnd;
ChfCondition 10, CHF_FATAL ChfEnd;
action = CHF_RESIGNAL;
}
@ -42,7 +42,7 @@ ChfAction h1( const ChfDescriptor* c, const ChfState s, void* p )
return action;
}
ChfAction h2( const ChfDescriptor* c, const ChfState s, void* p )
ChfAction h2( const ChfDescriptor* c, const ChfState s, ChfPointer p )
{
struct tdata_s* tdata_p = ( struct tdata_s* )p;
ChfAction action;
@ -51,7 +51,7 @@ ChfAction h2( const ChfDescriptor* c, const ChfState s, void* p )
case CHF_SIGNALING:
{
if ( c != tdata_p->e || ChfGetNextDescriptor( c ) != tdata_p->d || ( tdata_p->phase != 2 && tdata_p->phase != 4 ) ) {
CHF_Condition 10, CHF_FATAL ChfEnd;
ChfCondition 10, CHF_FATAL ChfEnd;
action = CHF_RESIGNAL;
}
@ -76,7 +76,7 @@ ChfAction h2( const ChfDescriptor* c, const ChfState s, void* p )
return action;
}
ChfAction h3( const ChfDescriptor* c, const ChfState s, void* p )
ChfAction h3( const ChfDescriptor* c, const ChfState s, ChfPointer p )
{
struct tdata_s* tdata_p = ( struct tdata_s* )p;
ChfAction action;
@ -106,7 +106,7 @@ ChfAction h3( const ChfDescriptor* c, const ChfState s, void* p )
return action;
}
ChfAction h4( const ChfDescriptor* c, const ChfState s, void* p )
ChfAction h4( const ChfDescriptor* c, const ChfState s, ChfPointer p )
{
struct tdata_s* tdata_p = ( struct tdata_s* )p;
ChfAction action;
@ -119,14 +119,14 @@ ChfAction h4( const ChfDescriptor* c, const ChfState s, void* p )
case CHF_SIGNALING:
{
if ( c != tdata_p->e || ChfGetNextDescriptor( c ) != tdata_p->d ) {
CHF_Condition 10, CHF_FATAL ChfEnd;
ChfCondition 10, CHF_FATAL ChfEnd;
action = CHF_RESIGNAL;
}
else {
/* This generates a new group and signals it */
tdata_p->phase = 3;
CHF_Condition 9, CHF_INFO ChfEnd;
ChfCondition 9, CHF_INFO ChfEnd;
ChfSignal();
if ( tdata_p->phase != 4 )
@ -134,7 +134,7 @@ ChfAction h4( const ChfDescriptor* c, const ChfState s, void* p )
tdata_p->phase = 5;
if ( c != tdata_p->e || ChfGetNextDescriptor( c ) != tdata_p->d ) {
CHF_Condition 10, CHF_FATAL ChfEnd;
ChfCondition 10, CHF_FATAL ChfEnd;
action = CHF_RESIGNAL;
} else
action = CHF_CONTINUE;
@ -159,12 +159,12 @@ void* task( void* arg )
printf( "\tThread %d\n", ( int )arg );
/* Push the handler */
ChfPushHandler( h1, NULL, ( void* )( &tdata ) );
ChfPushHandler( h1, NULL, ( ChfPointer )( &tdata ) );
/* Generate a condition group and signal it */
CHF_Condition 6, CHF_INFO, ( int )arg ChfEnd;
ChfCondition 6, CHF_INFO, ( int )arg ChfEnd;
tdata.d = ChfGetTopCondition();
CHF_Condition 7, CHF_INFO, ( int )arg ChfEnd;
ChfCondition 7, CHF_INFO, ( int )arg ChfEnd;
tdata.e = ChfGetTopCondition();
/* The sleep() is here to increase contention between threads */
@ -178,9 +178,9 @@ void* task( void* arg )
and signal it; this checks that the handler has actually been
removed.
*/
CHF_Condition 6, CHF_INFO, ( int )arg ChfEnd;
ChfCondition 6, CHF_INFO, ( int )arg ChfEnd;
tdata.d = NULL;
CHF_Condition 7, CHF_INFO, ( int )arg ChfEnd;
ChfCondition 7, CHF_INFO, ( int )arg ChfEnd;
tdata.e = NULL;
ChfSignal();
@ -190,13 +190,13 @@ void* task( void* arg )
tdata.phase = 0;
if ( setjmp( jb ) == 0 ) {
ChfPushHandler( h2, jb, ( void* )( &tdata ) );
ChfPushHandler( h2, jb, ( ChfPointer )( &tdata ) );
/* Generate a condition group and signal it */
tdata.phase = 1;
CHF_Condition 6, CHF_INFO, ( int )arg ChfEnd;
ChfCondition 6, CHF_INFO, ( int )arg ChfEnd;
tdata.d = ChfGetTopCondition();
CHF_Condition 7, CHF_INFO, ( int )arg ChfEnd;
ChfCondition 7, CHF_INFO, ( int )arg ChfEnd;
tdata.e = ChfGetTopCondition();
/* This does not trigger an unwind */
@ -204,9 +204,9 @@ void* task( void* arg )
ChfSignal();
tdata.phase = 3;
CHF_Condition 6, CHF_INFO, ( int )arg ChfEnd;
ChfCondition 6, CHF_INFO, ( int )arg ChfEnd;
tdata.d = ChfGetTopCondition();
CHF_Condition 8, CHF_INFO, ( int )arg ChfEnd;
ChfCondition 8, CHF_INFO, ( int )arg ChfEnd;
tdata.e = ChfGetTopCondition();
/* This MUST trigger an unwind */
@ -230,13 +230,13 @@ void* task( void* arg )
{
tdata.phase = 0;
ChfPushHandler( h3, NULL, ( void* )&tdata );
ChfPushHandler( h4, NULL, ( void* )&tdata );
ChfPushHandler( h3, NULL, ( ChfPointer )&tdata );
ChfPushHandler( h4, NULL, ( ChfPointer )&tdata );
tdata.phase = 1;
CHF_Condition 6, CHF_INFO, ( int )arg ChfEnd;
ChfCondition 6, CHF_INFO, ( int )arg ChfEnd;
tdata.d = ChfGetTopCondition();
CHF_Condition 7, CHF_INFO, ( int )arg ChfEnd;
ChfCondition 7, CHF_INFO, ( int )arg ChfEnd;
tdata.e = ChfGetTopCondition();
tdata.phase = 2;

View file

@ -19,7 +19,7 @@
#define CHF_MODULE_ID 255
#define CHF_EXTENDED_INFO
#include "../src/Chf.h"
#include "Chf.h"
#define H_STACK_SIZE 10
#define C_STACK_SIZE 30
@ -27,14 +27,14 @@
/* Dummy handler; pushed only to verify that the handler stack overflow
checks are correct.
*/
ChfAction h1( const ChfDescriptor* c, const ChfState s, void* p ) { return CHF_RESIGNAL; }
ChfAction h1( const ChfDescriptor* c, const ChfState s, ChfPointer p ) { return CHF_RESIGNAL; }
/* Overflow check handler; it unwinds if the CHF_F_HDLR_STACK_FULL
condition is signalled exactly after H_STACK_SIZE-2 invocations
of ChfPushHandler(), it resignals a modified condition if the
condition is signalled too early
*/
ChfAction h2( const ChfDescriptor* c, const ChfState s, void* p )
ChfAction h2( const ChfDescriptor* c, const ChfState s, ChfPointer p )
{
int push_count = *( ( int* )p );
ChfAction action;
@ -45,7 +45,7 @@ ChfAction h2( const ChfDescriptor* c, const ChfState s, void* p )
if ( push_count == H_STACK_SIZE - 2 && ChfGetNextDescriptor( c ) == NULL && ChfGetSeverity( c ) == CHF_FATAL )
action = CHF_UNWIND;
else {
CHF_Condition 11, CHF_FATAL, push_count, H_STACK_SIZE - 2 ChfEnd;
ChfCondition 11, CHF_FATAL, push_count, H_STACK_SIZE - 2 ChfEnd;
action = CHF_RESIGNAL;
}
}
@ -59,10 +59,10 @@ ChfAction h2( const ChfDescriptor* c, const ChfState s, void* p )
/* Overflow check handler; it unwinds if the CHF_F_COND_STACK_FULL
condition is signalled exactly after C_STACK_SIZE invocations
of CHF_Condition, it resignals a modified condition if the
of ChfCondition, it resignals a modified condition if the
condition is signalled too early
*/
ChfAction h3( const ChfDescriptor* c, const ChfState s, void* p )
ChfAction h3( const ChfDescriptor* c, const ChfState s, ChfPointer p )
{
int push_count = *( ( int* )p );
ChfAction action;
@ -73,7 +73,7 @@ ChfAction h3( const ChfDescriptor* c, const ChfState s, void* p )
if ( push_count == C_STACK_SIZE && ChfGetNextDescriptor( c ) == NULL && ChfGetSeverity( c ) == CHF_FATAL )
action = CHF_UNWIND;
else {
CHF_Condition 12, CHF_FATAL, push_count, C_STACK_SIZE ChfEnd;
ChfCondition 12, CHF_FATAL, push_count, C_STACK_SIZE ChfEnd;
action = CHF_RESIGNAL;
}
}
@ -100,7 +100,7 @@ void* task( void* arg )
int i;
/* Push the handler */
ChfPushHandler( h2, jb, ( void* )( &push_count ) );
ChfPushHandler( h2, jb, ( ChfPointer )( &push_count ) );
/* The sleep() is here to increase contention between threads */
sleep( 1 );
@ -122,14 +122,14 @@ void* task( void* arg )
int i;
/* Push the handler */
ChfPushHandler( h3, jb, ( void* )( &push_count ) );
ChfPushHandler( h3, jb, ( ChfPointer )( &push_count ) );
/* The sleep() is here to increase contention between threads */
sleep( 1 );
/* Push dummy conditions until an error should occur */
for ( ; push_count <= C_STACK_SIZE; push_count++ )
CHF_Condition 1, CHF_INFO ChfEnd;
ChfCondition 1, CHF_INFO ChfEnd;
/* No error? Bad! */
return ( void* )EXIT_FAILURE;
@ -145,14 +145,14 @@ void* task( void* arg )
int i;
/* Push the handler */
ChfPushHandler( h3, jb, ( void* )( &push_count ) );
ChfPushHandler( h3, jb, ( ChfPointer )( &push_count ) );
/* The sleep() is here to increase contention between threads */
sleep( 1 );
/* Push dummy conditions until an error should occur */
for ( ; push_count <= C_STACK_SIZE; push_count++ )
CHF_Condition 1, CHF_INFO ChfEnd;
ChfCondition 1, CHF_INFO ChfEnd;
/* No error? Bad! */
return ( void* )EXIT_FAILURE;

View file

@ -19,7 +19,7 @@
#define CHF_MODULE_ID 255
#define CHF_EXTENDED_INFO
#include "../src/Chf.h"
#include "Chf.h"
#define H_STACK_SIZE 10
#define C_STACK_SIZE 30
@ -28,50 +28,50 @@ void* task( void* arg )
{
volatile int phase = 0;
CHF_Try
ChfTry
{
phase = 1;
CHF_Condition 20, CHF_SUCCESS ChfEnd;
ChfCondition 20, CHF_SUCCESS ChfEnd;
ChfSignal();
phase = 2;
CHF_Condition 20, CHF_INFO ChfEnd;
ChfCondition 20, CHF_INFO ChfEnd;
ChfSignal();
phase = 3;
CHF_Condition 20, CHF_WARNING ChfEnd;
ChfCondition 20, CHF_WARNING ChfEnd;
ChfSignal();
phase = 4;
CHF_Condition 20, CHF_ERROR ChfEnd;
ChfCondition 20, CHF_ERROR ChfEnd;
ChfSignal();
phase = 5;
CHF_Condition 20, CHF_FATAL ChfEnd;
ChfCondition 20, CHF_FATAL ChfEnd;
ChfSignal();
/* Should not be reached */
return ( void* )EXIT_FAILURE;
}
CHF_Catch
ChfCatch
{
/* Catched an exception; check descriptor */
const ChfDescriptor* d = ChfGetTopCondition();
if ( d == NULL || ChfGetNextDescriptor( d ) != NULL || ChfGetModuleId( d ) != CHF_MODULE_ID || ChfGetConditionCode( d ) != 20 )
return ( void* )EXIT_FAILURE;
}
CHF_EndTry;
ChfEndTry;
/* Check that the condition stack actually is empty after catch */
CHF_Try { const volatile ChfDescriptor* e = ChfGetTopCondition(); }
CHF_Catch
ChfTry { const volatile ChfDescriptor* e = ChfGetTopCondition(); }
ChfCatch
{
const ChfDescriptor* d = ChfGetTopCondition();
if ( d == NULL || ChfGetNextDescriptor( d ) != NULL || ChfGetModuleId( d ) != CHF_SET ||
ChfGetConditionCode( d ) != CHF_F_BAD_STATE )
return ( void* )EXIT_FAILURE;
}
CHF_EndTry;
ChfEndTry;
return ( void* )EXIT_SUCCESS;
}

View file

@ -16,7 +16,7 @@
#define CHF_MODULE_ID 255
#define CHF_EXTENDED_INFO
#include "../src/Chf.h"
#include "Chf.h"
extern ChfTable message_table[];
extern size_t message_table_size;
@ -44,7 +44,7 @@ int main( int argc, char* argv[] )
exit( EXIT_FAILURE );
/* Generate a condition and check descriptor; this is line 46 */
CHF_Condition 3, CHF_WARNING, 456 ChfEnd;
ChfCondition 3, CHF_WARNING, 456 ChfEnd;
if ( ( d = ChfGetTopCondition() ) == NULL )
exit( EXIT_FAILURE );
@ -53,7 +53,7 @@ int main( int argc, char* argv[] )
exit( EXIT_FAILURE );
/* Generate another condition and check; this is line 60 */
CHF_Condition 4, CHF_INFO, "arg" ChfEnd;
ChfCondition 4, CHF_INFO, "arg" ChfEnd;
if ( ( e = ChfGetTopCondition() ) == NULL )
exit( EXIT_FAILURE );
@ -65,7 +65,7 @@ int main( int argc, char* argv[] )
ChfDiscard();
/* This is line 77 */
CHF_Condition 5, CHF_ERROR, 456, 789 ChfEnd;
ChfCondition 5, CHF_ERROR, 456, 789 ChfEnd;
if ( ( d = ChfGetTopCondition() ) == NULL )
exit( EXIT_FAILURE );

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

64
src/MSFs/cpu.msf Normal file
View file

@ -0,0 +1,64 @@
$ .+
$ .identifier : $Id: cpu.msf,v 4.1 2000/12/11 09:54:19 cibrario Rel $
$ .context : SATURN, Saturn CPU / HP48 emulator
$ .title : $RCSfile: cpu.msf,v $
$ .kind : Message catalog source
$ .author : Ivan Cibrario B.
$ .site : CSTV-CNR
$ .creation : 13-Feb-1998
$ .keywords : *
$ .description :
$ Message catalog source file for the CPU emulation modules.
$ .notes :
$ . $Log: cpu.msf,v $
$ . Revision 4.1 2000/12/11 09:54:19 cibrario
$ . Public release.
$ .
$ . Revision 3.13 2000/11/09 11:27:48 cibrario
$ . Revised to add file selection box GUI element, CPU halt/run
$ . requests and emulator's extended functions:
$ .
$ . - New messages: 118, 119, 303
$ .
$ . Revision 3.8 2000/10/19 14:56:52 cibrario
$ . Bug fix:
$ . Removed lines with empty directives
$ .
$ Revision 3.1 2000/09/20 13:44:30 cibrario
$ Revised to implement passive CPU shutdown:
$ - new messages 114, 115, 116, 117
$ .
$ Revision 1.1 1998/02/18 11:50:36 cibrario
$ Initial revision
$ .-
$set 1
11 Cpu
$set 11
101 Function [%s] called
102 Executing @ PC[%05X]
103 CPU shutdown executed
104 CPU wake-up executed
105 %s request accepted
106 %s request pending
107 RTI loop to service %s
108 RTI returning
109 INTON servicing %s
110 CPU emulator [%s]
111 Timer1 expired CTRL[%01X]
112 Timer2 expired CTRL[%01X]
113 Emulator interrupt request detected
114 Timer[%s] Ctrl[%01X] Val[%08X]
115 Timer[%s] expires in [%d]d ms
116 Starting idle loop, timeout [%d]d ms
117 Spooling up after [%d]d us in idle loop
118 CPU halted by CpuHaltRequest()
119 CPU awoken by CpuRunRequest()
201 Can't restore CPU status from disk; resetting CPU
202 Monitor command syntax error [%s]
301 Bad opcode @ PC[%05X], N[%01X]
302 Can't save CPU status to disk
303 Halt/Run requests not allowed; #undef CPU_SPIN_SHUTDN
401 Internal error [%s]
402 Unexpected CPU shutdown

29
src/MSFs/debug.msf Normal file
View file

@ -0,0 +1,29 @@
$ .+
$ .identifier : $Id: debug.msf,v 4.1 2000/12/11 09:54:19 cibrario Rel $
$ .context : SATURN, Saturn CPU / HP48 emulator
$ .title : $RCSfile: debug.msf,v $
$ .kind : Message catalog source
$ .author : Ivan Cibrario B.
$ .site : CSTV-CNR
$ .creation : 13-Feb-1998
$ .keywords : *
$ .description :
$ Message catalog source file for the debugging support modules.
$ .notes :
$ . $Log: debug.msf,v $
$ . Revision 4.1 2000/12/11 09:54:19 cibrario
$ . Public release.
$ .
$ . Revision 3.8 2000/10/19 14:55:10 cibrario
$ . Bug fix:
$ . Removed lines with empty directives
$ .
$ Revision 1.1 1998/02/18 11:54:02 cibrario
$ Initial revision
$ .-
$set 1
30 Debug
$set 30
201 Debug not supported; Rebuild with -DDEBUG

44
src/MSFs/disk_io.msf Normal file
View file

@ -0,0 +1,44 @@
$ .+
$ .identifier : $Id: disk_io.msf,v 4.1 2000/12/11 09:54:19 cibrario Rel $
$ .context : SATURN, Saturn CPU / HP48 emulator
$ .title : $RCSfile: disk_io.msf,v $
$ .kind : Message catalog source
$ .author : Ivan Cibrario B.
$ .site : CSTV-CNR
$ .creation : 13-Feb-1998
$ .keywords : *
$ .description :
$ Message catalog source file for the disk I/O functions.
$ .notes :
$ . $Log: disk_io.msf,v $
$ . Revision 4.1 2000/12/11 09:54:19 cibrario
$ . Public release.
$ .
$ . Revision 3.14 2000/11/13 10:32:24 cibrario
$ . Implemented fast load/save; improved keyboard interface emulation at
$ . high emulated CPU speed:
$ .
$ . - Fixed spelling error in message 405
$ . - Added new messages: 407, 408
$ .
$ . Revision 3.8 2000/10/19 14:58:41 cibrario
$ . Bug fix:
$ . Removed lines with empty directives
$ .
$ Revision 1.1 1998/02/17 11:54:49 cibrario
$ Initial revision
$ .-
$set 1
13 Disk_IO
$set 13
101 Function [%s] called
401 Can't open file [%s]
402 getc() failed reading file [%s]
403 putc() failed writing file [%s]
404 fread() failed reading file [%s]
405 fwrite() failed writing file [%s]
406 Close file [%s] failed
407 File [%s] has a bad header
408 File [%s] is too large

38
src/MSFs/flash49.msf Normal file
View file

@ -0,0 +1,38 @@
$ .+
$ .identifier : $Id: flash49.msf,v 4.1 2000/12/11 09:54:19 cibrario Rel $
$ .context : SATURN, Saturn CPU / HPxx emulator
$ .title : $RCSfile: flash49.msf,v $
$ .kind : Message catalog source
$ .author : Ivan Cibrario B.
$ .site : CSTV-CNR
$ .creation : 25-Sep-2000
$ .keywords : *
$ .description :
$ Message catalog source file for the flash rom emulator.
$ .notes :
$ . $Log: flash49.msf,v $
$ . Revision 4.1 2000/12/11 09:54:19 cibrario
$ . Public release.
$ .
$ . Revision 3.8 2000/10/19 15:00:41 cibrario
$ . Bug fix:
$ . Removed lines with empty directives
$ .
$ Revision 3.3 2000/09/26 15:30:28 cibrario
$ *** empty log message ***
$ .-
$set 1
16 Flash
$set 16
101 Read (Nibble) A[%08X] D[%01X]
102 Write (Nibble) A[%08X] D[%01X]
103 FSM STATE[%d] CYCLE[%d]
104 \tFSM Args: (Byte)A[%08X] D[%02X]
105 \tFSM Next: STATE[%d] RESULT[%02X]
106 \tFSM Operation: [%s]
201 Command unknown/not implemented - FSM Info:\n\
\tSTATE[%d] CYCLE[%d] A[%08X] D[%02X]
202 Invalid address in Write to Buffer - FSM Info:\n\
\tSTATE[%d] CYCLE[%d] A[%08X] D[%02X]

103
src/MSFs/modules.msf Normal file
View file

@ -0,0 +1,103 @@
$ .+
$ .identifier : $Id: modules.msf,v 4.1 2000/12/11 09:54:19 cibrario Rel $
$ .context : SATURN, Saturn CPU / HP48 emulator
$ .title : $RCSfile: modules.msf,v $
$ .kind : Message catalog source
$ .author : Ivan Cibrario B.
$ .site : CSTV-CNR
$ .creation : 13-Feb-1998
$ .keywords : *
$ .description :
$ Message catalog source file for the peripheral modules emulator.
$ .notes :
$ . $Log: modules.msf,v $
$ . Revision 4.1 2000/12/11 09:54:19 cibrario
$ . Public release.
$ .
$ . Revision 3.8 2000/10/19 14:58:01 cibrario
$ . Bug fix:
$ . Removed lines with empty directives
$ .
$ Revision 3.3 2000/09/26 15:05:33 cibrario
$ Revised to implement Flash ROM write access:
$ - Added message 312
$ .
$ Revision 3.2 2000/09/22 14:07:04 cibrario
$ Implemented preliminary support of HP49 hw architecture:
$ - added new messages: 311, 407, 408
$ .
$ Revision 2.7 2000/09/19 11:13:12 cibrario
$ Deeply revised to implement config/unconfig cache.
$ .
$ Revision 2.4 2000/09/12 15:48:57 cibrario
$ Added messages 112, 113, 114, 211, 212, 306, 307, 308, 309, 310
$ .
$ Revision 2.1 2000/09/08 15:22:17 cibrario
$ Updated message 209; added message 210. Both updates reflect the
$ changes made to the keyboard emulation module in order to
$ accommodate the new GUI.
$ .
$ Revision 1.1 1998/02/17 14:53:53 cibrario
$ Initial revision
$ .-
$set 1
12 Modules
$set 12
101 Function [%s] called
102 Initializing module [%s]
103 Resetting module [%s]
106 ModGetID -> [%05X]
107 CONFIG M[%s] A[%05X] S[%05X]
108 UNCNFG M[%s] A[%05X] S[%05X]
109 Saving module [%s]
110 Function [%s] not implemented
111 Modules emulator: [%s]
112 Bank Switcher F/F set to A[%05X]
113 Port 1 has been write-protected
114 Port 2 has been write-protected
115 >>> PerfCtr [%s]=[%d]
116 Cached UNCNFG completed
117 Cached CONFIG A[%05X] completed
118 Late UNCNFG cache hit
119 Late UNCNFG cache miss
202 Bad ModConfig [%05X] ignored
203 Bad ModUnconfig [%05X] ignored
204 Bad HdwWrite A[%05X] N[%01X]
205 Bad HdwRead A[%05X]
206 Resetting all modules
207 Can't initialize internal RAM from disk
208 Can't initialize HDW from disk
209 Bad key [%s] ignored
210 Bad out_bit [%x] ignored
211 Can't initialize Port 1 from disk
212 Can't initialize Port 2 from disk
213 Unable to find CONFIG cache victim; flushing cache
301 Read from unmapped A[%05X]
302 Write to unmapped A[%05X] N[%01X]
303 Write into ROM A[%05X] D[%01X]
304 Can't save internal RAM status to disk
305 Can't save HDW status to disk
306 Can't save Port 1 status to disk
307 Write into CE1 A[%05X] D[%01X]
308 Can't save Port 1 status to disk
309 Read from NCE3 A[%05X] when Port 2 is not present
310 Write into NCE3 A[%05X] D[%01X] when Port 2 is not present
311 Hardware configuration [%s] not supported
312 Can't save Flash ROM status to disk
401 Can't save module mapping info
402 Can't initialize internal ROM
403 Dynamic allocation of ModMap failed
404 Bad alloc_c [%d] after FlushCache()
405 Cached struct ModMap chain corrupted; freeing unlinked entry
406 Unable to find CONFIG cache victim after cache flush
407 Allocation of ModStatus_xx failed ([%d]d bytes needed)
408 ModInit() invoked without registering a ModDescription first
501 A[%05X] -> *Not Mapped*
502 A[%05X] -> M[%s] R[%05X]
503 Device\t\t\tAddress\tSize\tStatus
504 %s\t%05X\t%05X\t%s
505 Configured
506 Size_configured
507 *Unconfigured*

33
src/MSFs/saturn.msf Normal file
View file

@ -0,0 +1,33 @@
$ .+
$ .identifier : $Id: saturn.msf,v 4.1 2000/12/11 09:54:19 cibrario Rel $
$ .context : SATURN, Saturn CPU / HP48 emulator
$ .title : $RCSfile: saturn.msf,v $
$ .kind : Message catalog source
$ .author : Ivan Cibrario B.
$ .site : CSTV-CNR
$ .creation : 8-Sep-2000
$ .keywords : *
$ .description :
$ Message catalog source file for the main program.
$ .notes :
$ . $Log: saturn.msf,v $
$ . Revision 4.1 2000/12/11 09:54:19 cibrario
$ . Public release.
$ .
$ . Revision 3.9 2000/10/24 16:11:48 cibrario
$ . Added messages 10/501 and 10/502 as suggested by GPL
$ .
$ . Revision 3.8 2000/10/19 15:01:20 cibrario
$ . Bug fix:
$ . Removed lines with empty directives
$ .
$ Revision 2.1 2000/09/08 15:35:43 cibrario
$ *** empty log message ***
$ .-
$set 1
10 Main
$set 10
501 saturn %s - A poor-man's emulator of HP48GX, HP49, HP39/40\nCopyright (C) 1998-2000 Ivan Cibrario Bertolotti\n
502 This program is free software, and comes with ABSOLUTELY NO WARRANTY;\nfor details see the accompanying documentation.\n\n

62
src/MSFs/serial.msf Normal file
View file

@ -0,0 +1,62 @@
$ .+
$ .identifier : $Id: serial.msf,v 4.1 2000/12/11 09:54:19 cibrario Rel $
$ .context : SATURN, Saturn CPU / HP48 emulator
$ .title : $RCSfile: serial.msf,v $
$ .kind : Message catalog source
$ .author : Ivan Cibrario B.
$ .site : CSTV-CNR
$ .creation : 13-Sep-2000
$ .keywords : *
$ .description :
$ Message catalog source file for the serial port emulator.
$ .notes :
$ . $Log: serial.msf,v $
$ . Revision 4.1 2000/12/11 09:54:19 cibrario
$ . Public release.
$ .
$ . Revision 3.16 2000/11/21 16:42:18 cibrario
$ . Ultrix/IRIX support:
$ . - New message: 203
$ .
$ . Revision 3.8 2000/10/19 15:00:10 cibrario
$ . Bug fix:
$ . Removed lines with empty directives
$ .
$ Revision 3.2 2000/09/22 14:38:08 cibrario
$ Implemented preliminary support of HP49 hw architecture:
$ - New messages: 408, 409
$ .
$ Revision 2.6 2000/09/15 09:26:18 cibrario
$ Added new messages: 403, 404, 405, 406, 407,
$ needed by the implementation of USE_STREAMSPTY
$ .
$ Revision 2.5 2000/09/14 15:44:49 cibrario
$ *** empty log message ***
$ .-
$set 1
15 Serial
$set 15
101 Function [%s] called
102 Serial port emulator: [%s]
103 Read [%s]; value [%01X]
104 Write [%s]; value [%01X](old) -> [%01X](new)
105 Read RBR; value [%02X]
106 Write TBR; value [%02X]
107 Pseudo-terminal name is [%s]
201 Read from empty receiver buffer, rcs [%01X]
202 Write into full transmitter buffer, tcs [%01X]
203 Pseudo-terminals not supported
301 Error draining transmitter buffer
302 Error charging receiver buffer
303 Error shutting down pseudo-terminal
401 openpty() failed on master pty
402 fcntl() failed on master pty
403 Can't open() pty master [%s]
404 grantpt() failed on master pty
405 unlockpt() failed on master pty
406 Can't open() pty slave [%s]
407 ioctl(I_PUSH,[%s]) failed on slave pty
408 tcgetattr() failed on master pty
409 tcsetattr() failed on master pty

38
src/MSFs/util.msf Normal file
View file

@ -0,0 +1,38 @@
$ .+
$ .identifier : $Id: util.msf,v 4.1 2000/12/11 09:54:19 cibrario Rel $
$ .context : SATURN, Saturn CPU / HPxx emulator
$ .title : $RCSfile: util.msf,v $
$ .kind : Message catalog source
$ .author : Ivan Cibrario B.
$ .site : CSTV-CNR
$ .creation : 2-Oct-2000
$ .keywords : *
$ .description :
$ Message catalog source file for the utility programs.
$ .notes :
$ . $Log: util.msf,v $
$ . Revision 4.1 2000/12/11 09:54:19 cibrario
$ . Public release.
$ .
$ . Revision 3.8 2000/10/19 15:01:43 cibrario
$ . Bug fix:
$ . Removed lines with empty directives
$ .
$ Revision 3.6 2000/10/02 13:59:02 cibrario
$ *** empty log message ***
$ .-
$set 1
17 Utilities
$set 17
1 Usage:\n\
pack <emu48_source_rom> <saturn_dest_rom>
2 Command line syntax error
3 stat(%s) failed
4 Invalid source file size: %d
5 malloc(%d) failed
6 open(%s) failed
7 read(%s) failed
8 WriteNibblesToFile() failed

77
src/MSFs/x11.msf Normal file
View file

@ -0,0 +1,77 @@
$ .+
$ .identifier : $Id: x11.msf,v 4.1 2000/12/11 09:54:19 cibrario Rel $
$ .context : SATURN, Saturn CPU / HP48 emulator
$ .title : $RCSfile: x11.msf,v $
$ .kind : Message catalog source
$ .author : Ivan Cibrario B.
$ .site : CSTV-CNR
$ .creation : 13-Feb-1998
$ .keywords : *
$ .description :
$ Message catalog source file for the X11 interface modules and main program.
$ .notes :
$ . $Log: x11.msf,v $
$ . Revision 4.1 2000/12/11 09:54:19 cibrario
$ . Public release.
$ .
$ . Revision 3.17 2000/11/23 17:03:52 cibrario
$ . Implemented sutil library and assorted bug fixes:
$ . - Added ending newline
$ .
$ . Revision 3.16 2000/11/21 16:43:40 cibrario
$ . Ultrix/IRIX support:
$ . - Removed single quote from message 402
$ .
$ . Revision 3.15 2000/11/15 14:16:14 cibrario
$ . GUI enhancements and assorted bug fixes:
$ . - Revised message 108 to list the new command-line option -batchXfer
$ . - Added new messages 204 and 402
$ .
$ . Revision 3.13 2000/11/09 11:39:18 cibrario
$ . Revised to add file selection box GUI element, CPU halt/run
$ . requests and emulator's extended functions:
$ .
$ . - New messages: 113, 114, 203, 303
$ .
$ . Revision 3.9 2000/10/24 16:12:25 cibrario
$ . Revised messages 108 (updated command-line options) and 301
$ .
$ . Revision 3.8 2000/10/19 14:59:23 cibrario
$ . Bug fix:
$ . Removed lines with empty directives
$ .
$ Revision 2.1 2000/09/08 15:31:18 cibrario
$ - Updated messages 104, 105, 108
$ - Removed message 106
$ - New messages 109, 110, 111, 112, 201, 202, 302
$ .
$ Revision 1.1 1998/02/19 12:01:14 cibrario
$ Initial revision
$ .-
$set 1
14 X11
$set 14
101 Function [%s] called
102 LCD Parameter [%s]: [%05X]
103 X Expose event LCD window, count=%d
104 Pressed key [%s]
105 Released key [%s]
107 X11 Interface [%s]
108 Usage:\n\t%s [-reset] [-monitor] [-batchXfer] [-stateDir <>]\n\t\t[-face <>] [-hw <>]\n\t\t[-cpu <>] [-mod <>] [-hdw <>]\n\t\t[-rom <>] [-ram <>] [-port1 <>] [-port2 <>]
109 Selected GUI face [%s]
110 Active GUI face has [%d] keys
111 Created key [%d], inOut [%s]
112 Found compoundString for widget [%s], value [%s]
113 Traversing widget [%s]
114 Current widget has [%d] children
201 Xt action called with wrong argc: [%d]
202 X Atom [%s] unknown
203 FSB continuation procedure not set
204 Too many messages not yet acknowledged (> [%d]).\n\tGUI logging temporarily suspended
301 Invalid option [%s] ignored
302 WM_COMMAND property bad or not set
303 No text segment found in a FSB XmString
401 X Window System fatal error
402 Face [%s] has no keys; the application resource\n\tfile probably is missing, corrupt, or unreachable

46
src/MSFs/x_func.msf Normal file
View file

@ -0,0 +1,46 @@
$ .+
$ .identifier : $Id: x_func.msf,v 4.1 2000/12/11 09:54:19 cibrario Rel $
$ .context : SATURN, Saturn CPU / HPxx emulator
$ .title : $RCSfile: x_func.msf,v $
$ .kind : Message catalog source
$ .author : Ivan Cibrario B.
$ .site : CSTV-CNR
$ .creation : 3-Nov-2000
$ .keywords : *
$ .description :
$ Message catalog source file for the emulator's extended functions.
$ .notes :
$ . $Log: x_func.msf,v $
$ . Revision 4.1 2000/12/11 09:54:19 cibrario
$ . Public release.
$ .
$ . Revision 3.14 2000/11/13 11:14:19 cibrario
$ . Implemented fast load/save; improved keyboard interface emulation at
$ . high emulated CPU speed:
$ .
$ . - Added new messages: 105, 106, 107, 202, 203, 303, 501, 502
$ .
$ . Revision 3.13 2000/11/09 11:42:22 cibrario
$ . *** empty log message ***
$ .
$ .-
$set 1
18 X_Func
$set 18
101 Function [%s] called
102 Emulator's extended function #[%01X]
103 Emulator speed set to [%d]MHz
104 Emulator at maximum speed
105 Transferring [%s]
106 Kget START[%05X] END[%05X] HDR[%s]
107 Send START[%05X] END[%05X] HDR[%s]
201 Invalid function code #[%01X] ignored
202 Operation aborted by user
203 Operation failed
301 Cpu Halt requests not allowed.\n\tRebuild with CPU_SPIN_SHUTDN undefined in config.h
302 Cpu speed control not available.\n\tRebuild with REAL_CPU_SPEED defined in config.h
303 Can't determine binary header for hw [%s]
501 Load object from disk...
502 Save object to disk...

534
src/___x11_lcd.c Normal file
View file

@ -0,0 +1,534 @@
/* -------------------------------------------------------------------------
saturn - A poor-man's emulator of some HP calculators
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
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 the documentation of this program; if not, write to
the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
For more information, please contact the author, preferably by email,
at the following address:
Ivan Cibrario Bertolotti
IRITI - National Research Council
c/o IEN "Galileo Ferraris"
Strada delle Cacce, 91
10135 - Torino (ITALY)
email: cibrario@iriti.cnr.it
------------------------------------------------------------------------- */
/* +-+ */
/* .+
.identifier : $Id: display.c,v 4.1.1.1 2002/11/11 16:12:46 cibrario Exp $
.context : SATURN, Saturn CPU / HP48 emulator
.title : $RCSfile: display.c,v $
.kind : C source
.author : Ivan Cibrario B.
.site : CSTV-CNR
.creation : 29-Jan-1998
.keywords : *
.description :
This source module emulates the Lcd driver of the Yorke chip.
References:
SASM.DOC by HP (HORN disk 4)
Guide to the Saturn Processor Rev. 0.00f by Matthew Mastracci
entries.srt by Mika Heiskanen (mheiskan@vipunen.hut.fi)
x48 source code by Eddie C. Dost (ecd@dressler.de)
NOTE: In the current (r1.1) implementation, the control fields
mod_status.hdw.lcd_offset and mod_status.hdw.lcd_contrast are
not supported. Therefore, the emulation accuracy is sometimes
poor; for example, the Equation Writer does not work well with
large equations.
.include : config.h, machdep.h, cpu.h, modules.h, display.h
.notes :
$Log: display.c,v $
Revision 4.1.1.1 2002/11/11 16:12:46 cibrario
Small screen support; preliminary
Revision 4.1 2000/12/11 09:54:19 cibrario
Public release.
Revision 3.10 2000/10/24 16:14:37 cibrario
Added/Replaced GPL header
Revision 3.8 2000/10/23 13:15:36 cibrario
Bug fix:
In InitLcd(), added a clip rectangle to GC, to avoid drawing non-existent
pixels, that is, pixels that *do* exist in the frame buffer, but should
never be viewed on screen.
Revision 3.5 2000/10/02 09:44:42 cibrario
Linux support:
- gcc does not like array subscripts with type 'char', and it is right.
Revision 3.1 2000/09/20 13:47:58 cibrario
Minor updates and fixes to avoid gcc compiler warnings on Solaris
when -ansi -pedantic -Wall options are selected.
* Revision 1.1 1998/02/17 14:14:39 cibrario
* Initial revision
*
.- */
#ifndef lint
static char rcs_id[] = "$Id: display.c,v 4.1.1.1 2002/11/11 16:12:46 cibrario Exp $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h> /* 3.1: memset() */
#include <X11/Xlib.h>
#include "config.h"
#include "machdep.h"
#include "cpu.h"
#include "modules.h"
#include "x11_lcd.h"
#include "x11.h"
#include "debug.h"
#define CHF_MODULE_ID X11_CHF_MODULE_ID
#include <Chf.h>
#ifndef LCD_MAG
# define LCD_MAG 2 /* 4.1.1.1: Compat. default */
#endif
#define NIBBLES_PER_ROW 34 /* 136 pixel total */
#define MAX_ROWS 64 /* 64 rows total */
#define N_ANN 6 /* # of annunciators */
#define LCD_X_ORIGIN 1 + 4 * ( LCD_MAG - 1 ) /* x origin */
#if LCD_MAG == 1
# define LCD_Y_ORIGIN 14 /* y origin */
#else
# define LCD_Y_ORIGIN 20 /* y origin */
#endif
/* 3.8: Origin and size of clip rectangle */
#define LCD_CLIP_X_ORIGIN LCD_X_ORIGIN
#define LCD_CLIP_Y_ORIGIN 0 /* Don't clip annunciators */
#define LCD_CLIP_WIDTH 131 * LCD_MAG
#define LCD_CLIP_HEIGHT LCD_Y_ORIGIN + 64 * LCD_MAG
#define MASK_ANN_LEFT 0x81 /* Annunciator's bit masks */
#define MASK_ANN_RIGHT 0x82
#define MASK_ANN_ALPHA 0x84
#define MASK_ANN_BATTERY 0x88
#define MASK_ANN_BUSY 0x90
#define MASK_ANN_IO 0xA0
/*---------------------------------------------------------------------------
Static/Global variables
---------------------------------------------------------------------------*/
static /*const*/ unsigned char nibble_bitmap_data[ NIBBLE_VALUES ][ LCD_MAG ] = {
#if LCD_MAG == 1
{ 0x00 }, /* ---- */
{ 0x01 }, /* *--- */
{ 0x02 }, /* -*-- */
{ 0x03 }, /* **-- */
{ 0x04 }, /* --*- */
{ 0x05 }, /* *-*- */
{ 0x06 }, /* -**- */
{ 0x07 }, /* ***- */
{ 0x08 }, /* ---* */
{ 0x09 }, /* *--* */
{ 0x0a }, /* -*-* */
{ 0x0b }, /* **-* */
{ 0x0c }, /* --** */
{ 0x0d }, /* *-** */
{ 0x0e }, /* -*** */
{ 0x0f } /* **** */
#elif LCD_MAG == 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 } /* **** */
#else
# error "Bad LCD_MAG; supported values are 1 and 2"
#endif
};
#define ANN_X( i ) ( 8 * LCD_MAG + ( 22 * LCD_MAG + 1 ) * i )
#define ANN_Y( i ) ( 1 + 3 * ( LCD_MAG - 1 ) )
static /*const*/ struct {
int mask; /* Bit mask */
int x, y; /* Position */
int w, h; /* Width, Height */
unsigned char bitmap_data[ 24 ]; /* Bitmap data */
} ann_data[ N_ANN ] = {
{MASK_ANN_LEFT, ANN_X( 0 ), ANN_Y( 0 ), 15, 12, { 0xfe, 0x3f, 0xff, 0x7f, 0x9f, 0x7f, 0xcf, 0x7f, 0xe7, 0x7f, 0x03, 0x78,
0x03, 0x70, 0xe7, 0x73, 0xcf, 0x73, 0x9f, 0x73, 0xff, 0x73, 0xfe, 0x33 } },
{MASK_ANN_RIGHT, ANN_X( 1 ), ANN_Y( 1 ), 15, 12, { 0xfe, 0x3f, 0xff, 0x7f, 0xff, 0x7c, 0xff, 0x79, 0xff, 0x73, 0x0f, 0x60,
0x07, 0x60, 0xe7, 0x73, 0xe7, 0x79, 0xe7, 0x7c, 0xe7, 0x7f, 0xe6, 0x3f } },
{MASK_ANN_ALPHA, ANN_X( 2 ), ANN_Y( 2 ), 15, 12, { 0xe0, 0x03, 0x18, 0x44, 0x0c, 0x4c, 0x06, 0x2c, 0x07, 0x2c, 0x07, 0x1c,
0x07, 0x0c, 0x07, 0x0c, 0x07, 0x0e, 0x0e, 0x4d, 0xf8, 0x38, 0x00, 0x00 } },
{MASK_ANN_BATTERY, ANN_X( 3 ), ANN_Y( 3 ), 15, 12, { 0x04, 0x10, 0x02, 0x20, 0x12, 0x24, 0x09, 0x48, 0xc9, 0x49, 0xc9, 0x49,
0xc9, 0x49, 0x09, 0x48, 0x12, 0x24, 0x02, 0x20, 0x04, 0x10, 0x00, 0x00 }},
{MASK_ANN_BUSY, ANN_X( 4 ), ANN_Y( 4 ), 15, 12, { 0xfc, 0x1f, 0x08, 0x08, 0x08, 0x08, 0xf0, 0x07, 0xe0, 0x03, 0xc0, 0x01,
0x40, 0x01, 0x20, 0x02, 0x10, 0x04, 0xc8, 0x09, 0xe8, 0x0b, 0xfc, 0x1f } },
{MASK_ANN_IO, ANN_X( 5 ), ANN_Y( 5 ), 15, 12, { 0x0c, 0x00, 0x1e, 0x00, 0x33, 0x0c, 0x61, 0x18, 0xcc, 0x30, 0xfe, 0x7f,
0xfe, 0x7f, 0xcc, 0x30, 0x61, 0x18, 0x33, 0x0c, 0x1e, 0x00, 0x0c, 0x00 } }
};
static Nibble lcd_buffer[ MAX_ROWS ][ NIBBLES_PER_ROW ];
static int ann_buffer;
static int clean;
static Display* display;
static Window window;
static GC gc;
static unsigned long fg_pixel, bg_pixel;
static unsigned int depth;
static Pixmap nibble_pixmap[ NIBBLE_VALUES ];
static Pixmap ann_pixmap[ N_ANN ];
/*---------------------------------------------------------------------------
Private functions
---------------------------------------------------------------------------*/
/* .+
.title : InitPixmaps
.kind : C function
.creation : 29-Jan-1998
.description :
This function initializes the pixmaps for the Lcd screen elements and
stores them into the appropriate global variables.
.call :
InitPixmaps();
.input :
void
.output :
void
.status_codes :
X11_I_CALLED
X11_F_X_ERROR
.notes :
1.1, 29-Jan-1998, creation
.- */
static void InitPixmaps( void )
{
int i;
debug1( DEBUG_C_TRACE, X11_I_CALLED, "InitPixmaps" );
/* Initialize nibble_pixmap */
for ( i = 0; i < NIBBLE_VALUES; i++ ) {
if ( ( nibble_pixmap[ i ] = XCreatePixmapFromBitmapData( display, window, ( char* )nibble_bitmap_data[ i ], 4 * LCD_MAG, LCD_MAG,
fg_pixel, bg_pixel, depth ) ) == None ) {
ChfCondition X11_F_X_ERROR, CHF_FATAL ChfEnd;
ChfSignal();
}
}
/* Initialize ann_pixmap */
for ( i = 0; i < N_ANN; i++ ) {
if ( ( ann_pixmap[ i ] = XCreatePixmapFromBitmapData( display, window, ( char* )ann_data[ i ].bitmap_data, ann_data[ i ].w,
ann_data[ i ].h, fg_pixel, bg_pixel, depth ) ) == None ) {
ChfCondition X11_F_X_ERROR, CHF_FATAL ChfEnd;
ChfSignal();
}
}
}
/* .+
.title : ClearLcd
.kind : C function
.creation : 29-Jan-1998
.description :
This function clears the Lcd screen
.call :
ClearLcd();
.input :
void
.output :
void
.status_codes :
X11_I_CALLED
.notes :
1.1, 29-Jan-1998, creation
.- */
static void ClearLcd( void )
{
debug1( DEBUG_C_TRACE, X11_I_CALLED, "ClearLcd" );
/* Clear Lcd display */
( void )memset( ( void* )lcd_buffer, 0, sizeof( lcd_buffer ) );
ann_buffer = 0;
XClearWindow( display, window );
XFlush( display );
}
/*---------------------------------------------------------------------------
Public funcitons
---------------------------------------------------------------------------*/
/* .+
.title : InitLcd
.kind : C function
.creation : 29-Jan-1998
.description :
This function initializes the Lcd driver emulator and prepares it for use.
The LCD screen is initially cleared.
.call :
InitLcd(lcd_display, lcd_window, lcd_fg_pixel, lcd_bg_pixel);
.input :
Display *lcd_display, X display
Window lcd_window, X window to be used for display
unsigned long lcd_fg_pixel, foreground color to be used
unsigned long lcd_bg_pixel, background color to be used
.output :
void
.status_codes :
X11_I_CALLED
X11_F_X_ERROR
.notes :
1.1, 29-Jan-1998, creation
3.8, 23-Oct-2000, bug fix:
- added clip rectangle to GC, to avoid drawing non-existent pixels.
.- */
void InitLcd( Display* lcd_display, Window lcd_window, unsigned long lcd_fg_pixel, unsigned long lcd_bg_pixel )
{
XWindowAttributes xwa;
XGCValues gc_values;
debug1( DEBUG_C_TRACE, X11_I_CALLED, "InitLcdWindow" );
display = lcd_display;
window = lcd_window;
fg_pixel = lcd_fg_pixel;
bg_pixel = lcd_bg_pixel;
/* Get window attributes and initialize window depth */
if ( XGetWindowAttributes( display, window, &xwa ) == 0 ) {
ChfCondition X11_F_X_ERROR, CHF_FATAL ChfEnd;
ChfSignal();
}
depth = xwa.depth;
/* Create GC */
gc_values.function = GXcopy;
gc_values.plane_mask = AllPlanes;
gc_values.subwindow_mode = IncludeInferiors;
gc_values.foreground = lcd_fg_pixel;
gc_values.background = lcd_bg_pixel;
gc_values.graphics_exposures = False;
gc = XCreateGC( display, window, GCFunction | GCPlaneMask | GCForeground | GCBackground | GCSubwindowMode | GCGraphicsExposures,
&gc_values );
{
/* 3.8: This clip rectangle prevents XCopyArea() (in DrawLcd()) from
drawing non-visible pixels
*/
XRectangle rect[ 1 ];
rect[ 0 ].x = LCD_CLIP_X_ORIGIN; /* This is the clip rectangle */
rect[ 0 ].y = LCD_CLIP_Y_ORIGIN;
rect[ 0 ].width = LCD_CLIP_WIDTH;
rect[ 0 ].height = LCD_CLIP_HEIGHT;
XSetClipRectangles( display, gc, 0, 0, /* Alsolute clip X,Y origin */
rect, 1, YXBanded );
}
/* Initialize Pixmaps */
InitPixmaps();
/* Clear screen and initialize the static memory areas */
ClearLcd();
/* Set the 'display is clean' flag */
clean = 1;
}
/* .+
.title : DrawLcd
.kind : C function
.creation : 29-Jan-1998
.description :
This function redraws the Lcd screen from the information contained in
the mod_status.hdw structure.
.call :
DrawLcd();
.input :
void
.output :
void
.status_codes :
X11_I_CALLED
X11_I_LCD_PAR
.notes :
1.1, 29-Jan-1998, creation
.- */
void DrawLcd( void )
{
Address addr = mod_status.hdw.lcd_base_addr;
int y, x;
Nibble v;
debug1( DEBUG_C_TRACE, X11_I_CALLED, "DrawLcd" );
/* If the debug class DEBUG_C_DISPLAY is enabled, print the display
parameters
*/
debug2( DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_base_addr", ( int )mod_status.hdw.lcd_base_addr );
debug2( DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_on", ( int )mod_status.hdw.lcd_on );
debug2( DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_contrast", ( int )mod_status.hdw.lcd_contrast );
debug2( DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_vlc", ( int )mod_status.hdw.lcd_vlc );
debug2( DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_offset", ( int )mod_status.hdw.lcd_offset );
debug2( DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_line_offset", ( int )mod_status.hdw.lcd_line_offset );
debug2( DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_menu_addr", ( int )mod_status.hdw.lcd_menu_addr );
debug2( DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_ann", ( int )mod_status.hdw.lcd_ann );
/* Check if display is on */
if ( !mod_status.hdw.lcd_on ) {
/* Display is off; clear lcd if necessary */
if ( !clean ) {
/* Set the 'display is clean' flag and clear the screen */
clean = 1;
ClearLcd();
}
return;
}
/* The display is on and will be no longer clean */
clean = 0;
/* Scan active display rows */
for ( y = 0; y <= mod_status.hdw.lcd_vlc; y++ ) {
/* Scan columns */
for ( x = 0; x < NIBBLES_PER_ROW; x++ ) {
v = FetchNibble( addr++ );
if ( v != lcd_buffer[ y ][ x ] ) {
lcd_buffer[ y ][ x ] = v;
XCopyArea( display, nibble_pixmap[ ( int )v ], window, gc, 0, 0, /* src_x, src_y */
4 * LCD_MAG, LCD_MAG, /* width, height */
x * 4 * LCD_MAG + LCD_X_ORIGIN, y * LCD_MAG + LCD_Y_ORIGIN );
}
}
addr += mod_status.hdw.lcd_line_offset;
}
/* Scan menu display rows */
addr = mod_status.hdw.lcd_menu_addr;
for ( ; y < MAX_ROWS; y++ ) {
/* Scan columns */
for ( x = 0; x < NIBBLES_PER_ROW; x++ ) {
v = FetchNibble( addr++ );
if ( v != lcd_buffer[ y ][ x ] ) {
lcd_buffer[ y ][ x ] = v;
XCopyArea( display, nibble_pixmap[ ( int )v ], window, gc, 0, 0, /* src_x, src_y */
4 * LCD_MAG, LCD_MAG, /* width, height */
x * 4 * LCD_MAG + LCD_X_ORIGIN, y * LCD_MAG + LCD_Y_ORIGIN );
}
}
}
/* Scan annunciators */
if ( mod_status.hdw.lcd_ann != ann_buffer ) {
ann_buffer = mod_status.hdw.lcd_ann;
for ( y = 0; y < N_ANN; y++ ) {
if ( ( ann_buffer & ann_data[ y ].mask ) == ann_data[ y ].mask ) {
XCopyArea( display, ann_pixmap[ y ], window, gc, 0, 0, /* src_x, src_y */
ann_data[ y ].w, ann_data[ y ].h, /* width, height */
ann_data[ y ].x, ann_data[ y ].y );
} else {
XClearArea( display, window, ann_data[ y ].x, ann_data[ y ].y, ann_data[ y ].w, ann_data[ y ].h, False /* No exposures */
);
}
}
}
/* Flush display */
XFlush( display );
}
/* .+
.title : RefreshLcd
.kind : C function
.creation : 17-Feb-1998
.description :
This function refreshes the Lcd screen after a X Window Expose event.
.call :
RefreshLcd();
.input :
void
.output :
void
.status_codes :
X11_I_CALLED
.notes :
1.1, 17-Feb-1998, creation
.- */
void RefreshLcd( void )
{
debug1( DEBUG_C_TRACE, X11_I_CALLED, "RefreshLcd" );
ClearLcd();
DrawLcd();
}

95
src/___x11_lcd.h Normal file
View file

@ -0,0 +1,95 @@
#ifndef _DISPLAY_H
#define _DISPLAY_H 1
/* -------------------------------------------------------------------------
saturn - A poor-man's emulator of some HP calculators
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
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 the documentation of this program; if not, write to
the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
For more information, please contact the author, preferably by email,
at the following address:
Ivan Cibrario Bertolotti
IRITI - National Research Council
c/o IEN "Galileo Ferraris"
Strada delle Cacce, 91
10135 - Torino (ITALY)
email: cibrario@iriti.cnr.it
------------------------------------------------------------------------- */
/* +-+ */
/* .+
.identifier : $Id: display.h,v 4.1 2000/12/11 09:54:19 cibrario Rel $
.context : SATURN, Saturn CPU / HP48 emulator
.title : $RCSfile: display.h,v $
.kind : C header
.author : Ivan Cibrario B.
.site : CSTV-CNR
.creation : 28-Jan-1998
.keywords : *
.description :
This header contains all definitions and declarations related to the
HP48's LCD display emulator. References:
SASM.DOC by HP (HORN disk 4)
Guide to the Saturn Processor Rev. 0.00f by Matthew Mastracci
entries.srt by Mika Heiskanen (mheiskan@vipunen.hut.fi)
x48 source code by Eddie C. Dost (ecd@dressler.de)
.include : config.h, machdep.h, cpu.h, modules.h, X11/Xlib.h
.notes :
$Log: display.h,v $
Revision 4.1 2000/12/11 09:54:19 cibrario
Public release.
Revision 3.10 2000/10/24 16:14:38 cibrario
Added/Replaced GPL header
Revision 1.1 1998/02/17 11:51:31 cibrario
Initial revision
.- */
#include <X11/Xlib.h> /* for InitLcd ( Display* ; Window ) */
/*---------------------------------------------------------------------------
Data type definitions - require config.h, machdep.h, cpu.h
---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
Macros
---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
Global variables
---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
Function prototypes
---------------------------------------------------------------------------*/
void InitLcd( Display* lcd_display, Window lcd_window, unsigned long lcd_fg_pixel, unsigned long lcd_bg_pixel ); /* used in x11.c */
void DrawLcd( void ); /* used in emulator.c */
void RefreshLcd( void ); /* used in x11.c */
#endif /*!_DISPLAY_H*/

286
src/___x11_main.c Normal file
View file

@ -0,0 +1,286 @@
/* -------------------------------------------------------------------------
saturn - A poor-man's emulator of some HP calculators
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
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 the documentation of this program; if not, write to
the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
For more information, please contact the author, preferably by email,
at the following address:
Ivan Cibrario Bertolotti
IRITI - National Research Council
c/o IEN "Galileo Ferraris"
Strada delle Cacce, 91
10135 - Torino (ITALY)
email: cibrario@iriti.cnr.it
------------------------------------------------------------------------- */
/* +-+ */
/* .+
.identifier : $Id: saturn.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $
.context : SATURN, Saturn CPU / HP48 emulator
.title : $RCSfile: saturn.c,v $
.kind : C source
.author : Ivan Cibrario B.
.site : CSTV-CNR
.creation : 8-Sep-2000
.keywords : *
.description :
This file contains the main program of the Saturn CPU / HP4x emulator
.include : *
.notes :
$Log: saturn.c,v $
Revision 4.1 2000/12/11 09:54:19 cibrario
Public release.
Revision 3.15 2000/11/15 14:07:53 cibrario
GUI enhancements and assorted bug fixes:
- made Chf initialization more robust with respect to incorrect
locale settings
- made stand-alone messages conforming to Chf standard format
- the copyright notice is now output through the GUI, too, if stdout
is not a tty
Revision 3.14 2000/11/13 11:31:16 cibrario
Implemented fast load/save; improved keyboard interface emulation at
high emulated CPU speed:
- Revision number bump with no changes
Revision 3.11 2000/10/25 11:14:35 cibrario
*** empty log message ***
Revision 3.10 2000/10/24 16:14:56 cibrario
Added/Replaced GPL header
Revision 3.9 2000/10/24 16:11:20 cibrario
The main program now has its own set of condition codes;
added printf of MAIN_M_COPYRIGHT and MAIN_M_LICENSE as suggested by GPL
Revision 3.8 2000/10/23 13:16:49 cibrario
Bug fix:
Improper use of sizeof() in main() could give a segmentation fault.
Revision 3.1 2000/09/20 13:58:41 cibrario
Minor updates and fixes to avoid gcc compiler warnings on Solaris
when -ansi -pedantic -Wall options are selected.
* Revision 2.5 2000/09/14 15:32:07 cibrario
* Added invotation of SerialInit() in main program, to initialize
* the serial port emulation module.
*
* Revision 2.1 2000/09/08 15:46:02 cibrario
* *** empty log message ***
*
.- */
#ifndef lint
static char rcs_id[] = "$Id: saturn.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#endif
#include <stdio.h>
#include <stdlib.h>
// #include <setjmp.h>
#include <string.h> /* 3.1: strcpy(), strcat() */
#include <unistd.h> /* isatty() */
#include "config.h"
#include "machdep.h"
#include "cpu.h"
#include "x11.h"
#include "serial.h"
#include "debug.h"
#include "monitor.h"
/* Chf condition codes (main program only) */
#define CHF_MODULE_ID MAIN_CHF_MODULE_ID
#include <Chf.h>
#define MAIN_M_COPYRIGHT 501
#define MAIN_M_LICENSE 502
/*---------------------------------------------------------------------------
Chf parameters - Do not change.
---------------------------------------------------------------------------*/
#define CONDITION_STACK_SIZE 16
#define HANDLER_STACK_SIZE 8
/* Conditional prefix and mandatory suffix to make a message catalog
name from argv[0]
*/
static const char cat_prefix[] = "./";
static const char cat_suffix[] = ".cat";
#define CAT_PREFIX_LEN ( sizeof( cat_prefix ) + 1 )
#define CAT_SUFFIX_LEN ( sizeof( cat_suffix ) + 1 )
static void adjust_setlocale( void )
{
fprintf( stderr, "saturn-W-locale probably bad; reverting to C locale\n" );
putenv( "LC_ALL=C" );
putenv( "LC_COLLATE=C" );
putenv( "LC_CTYPE=C" );
putenv( "LC_MESSAGES=C" );
putenv( "LC_MONETARY=C" );
putenv( "LC_NUMERIC=C" );
putenv( "LC_TIME=C" );
putenv( "LANG=C" );
}
/*---------------------------------------------------------------------------
Public functions
---------------------------------------------------------------------------*/
/* .+
.title : main
.kind : C function
.creation : 8-Sep-2000
.description :
Main program.
.notes :
2.1, 6-Sep-2000, creation
2.5, 14-Sep-2000, update
- added invotation of SerialInit().
3.9, 23-Oct-2000, update
- main() now has its own set of condition codes
3.15, 15-Nov-2000, update
- made Chf initialization more robust with respect to bad locales
.- */
int main( int argc, char* argv[] )
{
char* cat_name;
int st;
int retry = 0;
if ( ( cat_name = malloc( strlen( argv[ 0 ] ) + CAT_PREFIX_LEN + CAT_SUFFIX_LEN + 1 ) ) == NULL ) {
fprintf( stderr, "saturn-E-cat_name initialization failed\n" );
exit( EXIT_FAILURE );
}
/* Generate catalog name, without optional prefix */
strcpy( cat_name, argv[ 0 ] );
strcat( cat_name, cat_suffix );
/* 3.15: Retry the initialization steps below two times; before trying
the second time, adjust the setlocale() environment variables
with adjust_setlocale()
*/
while ( retry < 2 ) {
/* Chf initialization with msgcat subsystem; notice that on
some systems (e.g. Digital UNIX) catopen() can succeed even
if it was not able to open the right message catalog;
better try it now.
*/
if ( ( st = ChfMsgcatInit( argv[ 0 ], /* Application's name */
CHF_DEFAULT, /* Options */
cat_name, /* Name of the message catalog */
CONDITION_STACK_SIZE, /* Size of the condition stack */
HANDLER_STACK_SIZE, /* Size of the handler stack */
EXIT_FAILURE /* Abnormal exit code */
) ) != CHF_S_OK ||
ChfGetMessage( CHF_MODULE_ID, MAIN_M_COPYRIGHT, NULL ) == NULL )
fprintf( stderr, "saturn-E-Primary Chf initialization failed (%d)\n", st );
else
break;
/* Bring down Chf before initializing it again */
if ( st == CHF_S_OK )
ChfExit();
/* Try alternate message catalog name (with prefix) */
strcpy( cat_name, cat_prefix );
strcat( cat_name, argv[ 0 ] );
strcat( cat_name, cat_suffix );
if ( ( st = ChfMsgcatInit( argv[ 0 ], /* Application's name */
CHF_DEFAULT, /* Options */
cat_name, /* Name of the message catalog */
CONDITION_STACK_SIZE, /* Size of the condition stack */
HANDLER_STACK_SIZE, /* Size of the handler stack */
EXIT_FAILURE /* Abnormal exit code */
) ) != CHF_S_OK ||
ChfGetMessage( CHF_MODULE_ID, MAIN_M_COPYRIGHT, NULL ) == NULL )
fprintf( stderr, "saturn-E-Alternate Chf initialization failed (%d)\n", st );
else
break;
/* Bring down Chf before initializing it again */
if ( st == CHF_S_OK )
ChfExit();
/* Attempt to adjust setlocale() environment variables */
if ( retry++ == 0 )
adjust_setlocale();
}
if ( retry == 2 ) {
fprintf( stderr, "saturn-F-Application aborted\n" );
exit( EXIT_FAILURE );
}
/* cat_name no longer needed */
free( cat_name );
/* 3.9: Print out MAIN_M_COPYRIGHT and MAIN_M_LICENSE on stdout now */
fprintf( stdout, ChfGetMessage( CHF_MODULE_ID, MAIN_M_COPYRIGHT, "" ), "$Revision: 4.1 $" );
/* fprintf( stdout, ChfGetMessage( CHF_MODULE_ID, MAIN_M_LICENSE, "" ) ); */
/* Initialize GUI and associated lcd display emulation module */
InitializeGui( argc, argv );
/* Initialize serial port emulation.
This function returns the name of the slave side of the pty;
it is unused here, because the GUI condition handler intercepts
a condition containing the same information and displays the pty name
on the main emulator's window.
*/
( void )SerialInit();
/* Initialize emulator proper */
EmulatorInit();
/* 3.15: Repeat copyright message on GUI if stdout is not a tty */
if ( !isatty( fileno( stdout ) ) ) {
ChfCondition MAIN_M_LICENSE, CHF_INFO ChfEnd;
ChfCondition MAIN_M_COPYRIGHT, CHF_INFO, "$Revision: 4.1 $" ChfEnd;
ChfSignal();
}
if ( args.monitor )
/* Invoke Monitor */
Monitor();
else
/* Call Emulator directly */
Emulator();
return EXIT_SUCCESS;
}

View file

@ -1,178 +0,0 @@
#include "libChf/src/Chf.h"
#include "chf_messages.h"
ChfTable message_table[] = {
{CHF_MODULE_NAMES_SET, CHF_SET, "Chf" },
{CHF_MODULE_NAMES_SET, MAIN_CHF_MODULE_ID, "MAIN" },
{CHF_MODULE_NAMES_SET, CPU_CHF_MODULE_ID, "CPU" },
{CHF_MODULE_NAMES_SET, MOD_CHF_MODULE_ID, "MOD" },
{CHF_MODULE_NAMES_SET, DISK_IO_CHF_MODULE_ID, "DISK_IO" },
{CHF_MODULE_NAMES_SET, X11_CHF_MODULE_ID, "X11" },
{CHF_MODULE_NAMES_SET, SERIAL_CHF_MODULE_ID, "SERIAL" },
{CHF_MODULE_NAMES_SET, FLASH_CHF_MODULE_ID, "FLASH" },
{CHF_MODULE_NAMES_SET, UTIL_CHF_MODULE_ID, "UTIL" },
{CHF_MODULE_NAMES_SET, X_FUNC_CHF_MODULE_ID, "X_FUNC" },
{CHF_MODULE_NAMES_SET, DEBUG_CHF_MODULE_ID, "DEBUG" },
{CHF_SET, CHF_S_OK, "" },
{CHF_SET, CHF_F_COND_STACK_FULL, "Condition stack is full" },
{CHF_SET, CHF_F_HDLR_STACK_FULL, "Handler stack is full" },
{CHF_SET, CHF_F_HDLR_STACK_EMPTY, "Handler stack is empty" },
{CHF_SET, CHF_F_BAD_STATE, "Wrong Chf state for requested operation" },
{CHF_SET, CHF_F_INVALID_ACTION, "Invalid action code from handler (code=<%d>d)" },
{CHF_SET, CHF_F_MALLOC, "Dynamic memory allocation failed" },
{CHF_SET, CHF_F_NOT_AVAILABLE, "Function not implemented" },
{CHF_SET, CHF_F_SETLOCALE, "setlocale() failed" },
{CHF_SET, CHF_F_CATOPEN, "catopen() failed" },
{CPU_CHF_MODULE_ID, CPU_I_CALLED, "Function [%s] called" },
{CPU_CHF_MODULE_ID, CPU_I_EXECUTING, "Executing @ PC[%05X]" },
{CPU_CHF_MODULE_ID, CPU_I_SHUTDN, "CPU shutdown executed" },
{CPU_CHF_MODULE_ID, CPU_I_WAKE, "CPU wake-up executed" },
{CPU_CHF_MODULE_ID, CPU_I_INT, "%s request accepted" },
{CPU_CHF_MODULE_ID, CPU_I_INT_PENDING, "%s request pending" },
{CPU_CHF_MODULE_ID, CPU_I_RTI_LOOP, "RTI loop to service %s" },
{CPU_CHF_MODULE_ID, CPU_I_RTI_END, "RTI returning" },
{CPU_CHF_MODULE_ID, CPU_I_INTON, "INTON servicing %s" },
{CPU_CHF_MODULE_ID, CPU_I_REVISION, "CPU emulator [%s]" },
{CPU_CHF_MODULE_ID, CPU_I_TIMER1_EX, "Timer1 expired CTRL[%01X]" },
{CPU_CHF_MODULE_ID, CPU_I_TIMER2_EX, "Timer2 expired CTRL[%01X]" },
{CPU_CHF_MODULE_ID, CPU_I_EMULATOR_INT, "Emulator interrupt request detected" },
{CPU_CHF_MODULE_ID, CPU_I_TIMER_ST, "Timer[%s] Ctrl[%01X] Val[%08X]" },
{CPU_CHF_MODULE_ID, CPU_I_TIMER_EXP, "Timer[%s] expires in [%d]d ms" },
{CPU_CHF_MODULE_ID, CPU_I_IDLE_X_LOOP, "Starting idle loop, timeout [%d]d ms" },
{CPU_CHF_MODULE_ID, CPU_I_ELAPSED, "Spooling up after [%d]d us in idle loop" },
{CPU_CHF_MODULE_ID, CPU_I_HALT, "CPU halted by CpuHaltRequest()" },
{CPU_CHF_MODULE_ID, CPU_I_RUN, "CPU awoken by CpuRunRequest()" },
{CPU_CHF_MODULE_ID, CPU_W_RESETTING, "Can't restore CPU status from disk; resetting CPU" },
{CPU_CHF_MODULE_ID, CPU_W_BAD_MONITOR_CMD, "Monitor command syntax error [%s]" },
{CPU_CHF_MODULE_ID, CPU_E_BAD_OPCODE, "Bad opcode @ PC[%05X], N[%01X]" },
{CPU_CHF_MODULE_ID, CPU_E_SAVE, "Can't save CPU status to disk" },
{CPU_CHF_MODULE_ID, CPU_E_NO_HALT, "Halt/Run requests not allowed; #undef CPU_SPIN_SHUTDN" },
{CPU_CHF_MODULE_ID, CPU_F_INTERR, "Internal error [%s]" },
{CPU_CHF_MODULE_ID, CPU_F_BAD_SHUTDN, "Unexpected CPU shutdown" },
{DEBUG_CHF_MODULE_ID, DEBUG_W_NOT_SUPPORTED, "Debug not supported; Rebuild with -DDEBUG" },
{DEBUG_CHF_MODULE_ID, DEBUG_W_BAD_CMD, "Debug: Invalid command" },
{DISK_IO_CHF_MODULE_ID, DISK_IO_S_OK, "Disk IO: OK" },
{DISK_IO_CHF_MODULE_ID, DISK_IO_I_CALLED, "Function [%s] called" },
{DISK_IO_CHF_MODULE_ID, DISK_IO_E_OPEN, "Can't open file [%s]" },
{DISK_IO_CHF_MODULE_ID, DISK_IO_E_GETC, "getc() failed reading file [%s]" },
{DISK_IO_CHF_MODULE_ID, DISK_IO_E_PUTC, "putc() failed writing file [%s]" },
{DISK_IO_CHF_MODULE_ID, DISK_IO_E_READ, "fread() failed reading file [%s]" },
{DISK_IO_CHF_MODULE_ID, DISK_IO_E_WRITE, "fwrite() failed writing file [%s]" },
{DISK_IO_CHF_MODULE_ID, DISK_IO_E_CLOSE, "Close file [%s] failed" },
{DISK_IO_CHF_MODULE_ID, DISK_IO_E_BAD_HDR, "File [%s] has a bad header" },
{DISK_IO_CHF_MODULE_ID, DISK_IO_E_SIZE, "File [%s] is too large" },
{FLASH_CHF_MODULE_ID, FLASH_I_READ, "Read (Nibble) A[%08X] D[%01X]" },
{FLASH_CHF_MODULE_ID, FLASH_I_WRITE, "Write (Nibble) A[%08X] D[%01X]" },
{FLASH_CHF_MODULE_ID, FLASH_I_FSM, "FSM STATE[%d] CYCLE[%d]" },
{FLASH_CHF_MODULE_ID, FLASH_I_FSM_AD, "\tFSM Args: (Byte)A[%08X] D[%02X]" },
{FLASH_CHF_MODULE_ID, FLASH_I_FSM_RESULT, "\tFSM Next: STATE[%d] RESULT[%02X]" },
{FLASH_CHF_MODULE_ID, FLASH_I_FSM_OP, "\tFSM Operation: [%s]" },
{FLASH_CHF_MODULE_ID, FLASH_W_BAD_CMD, "Command unknown/not implemented - FSM Info:\n\\tSTATE[%d] CYCLE[%d] A[%08X] D[%02X]" },
{FLASH_CHF_MODULE_ID, FLASH_W_BAD_ADDRESS, "Invalid address in Write to Buffer - FSM Info:\n\\tSTATE[%d] CYCLE[%d] A[%08X] D[%02X]"},
{FLASH_CHF_MODULE_ID, FLASH_E_xxx, "FLASH_E_xxx" },
{FLASH_CHF_MODULE_ID, FLASH_F_xxx, "FLASH_F_xxx" },
{MOD_CHF_MODULE_ID, MOD_I_CALLED, "Function [%s] called" },
{MOD_CHF_MODULE_ID, MOD_I_INITIALIZING, "Initializing module [%s]" },
{MOD_CHF_MODULE_ID, MOD_I_RESETTING, "Resetting module [%s]" },
{MOD_CHF_MODULE_ID, MOD_I_GET_ID, "ModGetID -> [%05X]" },
{MOD_CHF_MODULE_ID, MOD_I_CONFIG, "CONFIG M[%s] A[%05X] S[%05X]" },
{MOD_CHF_MODULE_ID, MOD_I_UNCONFIG, "UNCNFG M[%s] A[%05X] S[%05X]" },
{MOD_CHF_MODULE_ID, MOD_I_SAVING, "Saving module [%s]" },
{MOD_CHF_MODULE_ID, MOD_I_NOT_IMPLEMENTED, "Function [%s] not implemented" },
{MOD_CHF_MODULE_ID, MOD_I_REVISION, "Modules emulator: [%s]" },
{MOD_CHF_MODULE_ID, MOD_I_BS_ADDRESS, "Bank Switcher F/F set to A[%05X]" },
{MOD_CHF_MODULE_ID, MOD_I_PORT_1_WP, "Port 1 has been write-protected" },
{MOD_CHF_MODULE_ID, MOD_I_PORT_2_WP, "Port 2 has been write-protected" },
{MOD_CHF_MODULE_ID, MOD_I_PERF_CTR, ">>> PerfCtr [%s]=[%d]" },
{MOD_CHF_MODULE_ID, MOD_I_CACHED_UNCONFIG, "Cached UNCNFG completed" },
{MOD_CHF_MODULE_ID, MOD_I_CACHED_CONFIG, "Cached CONFIG A[%05X] completed" },
{MOD_CHF_MODULE_ID, MOD_I_UNCONFIG_L_HIT, "Late UNCNFG cache hit" },
{MOD_CHF_MODULE_ID, MOD_I_UNCONFIG_L_MISS, "Late UNCNFG cache miss" },
{MOD_CHF_MODULE_ID, MOD_W_BAD_CONFIG, "Bad ModConfig [%05X] ignored" },
{MOD_CHF_MODULE_ID, MOD_W_BAD_UNCONFIG, "Bad ModUnconfig [%05X] ignored" },
{MOD_CHF_MODULE_ID, MOD_W_HDW_WRITE, "Bad HdwWrite A[%05X] N[%01X]" },
{MOD_CHF_MODULE_ID, MOD_W_HDW_READ, "Bad HdwRead A[%05X]" },
{MOD_CHF_MODULE_ID, MOD_W_RESETTING_ALL, "Resetting all modules" },
{MOD_CHF_MODULE_ID, MOD_W_RAM_INIT, "Can't initialize internal RAM from disk" },
{MOD_CHF_MODULE_ID, MOD_W_HDW_INIT, "Can't initialize HDW from disk" },
{MOD_CHF_MODULE_ID, MOD_W_BAD_KEY, "Bad key [%s] ignored" },
{MOD_CHF_MODULE_ID, MOD_W_BAD_OUT_BIT, "Bad out_bit [%x] ignored" },
{MOD_CHF_MODULE_ID, MOD_W_PORT_1_INIT, "Can't initialize Port 1 from disk" },
{MOD_CHF_MODULE_ID, MOD_W_PORT_2_INIT, "Can't initialize Port 2 from disk" },
{MOD_CHF_MODULE_ID, MOD_W_NO_VICTIM, "Unable to find CONFIG cache victim; flushing cache" },
{MOD_CHF_MODULE_ID, MOD_E_BAD_READ, "Read from unmapped A[%05X]" },
{MOD_CHF_MODULE_ID, MOD_E_BAD_WRITE, "Write to unmapped A[%05X] N[%01X]" },
{MOD_CHF_MODULE_ID, MOD_E_ROM_WRITE, "Write into ROM A[%05X] D[%01X]" },
{MOD_CHF_MODULE_ID, MOD_E_RAM_SAVE, "Can't save internal RAM status to disk" },
{MOD_CHF_MODULE_ID, MOD_E_HDW_SAVE, "Can't save HDW status to disk" },
{MOD_CHF_MODULE_ID, MOD_E_PORT_1_SAVE, "Can't save Port 1 status to disk" },
{MOD_CHF_MODULE_ID, MOD_E_CE1_WRITE, "Write into CE1 A[%05X] D[%01X]" },
{MOD_CHF_MODULE_ID, MOD_E_PORT_2_SAVE, "Can't save Port 1 status to disk" },
{MOD_CHF_MODULE_ID, MOD_E_NCE3_READ, "Read from NCE3 A[%05X] when Port 2 is not present" },
{MOD_CHF_MODULE_ID, MOD_E_NCE3_WRITE, "Write into NCE3 A[%05X] D[%01X] when Port 2 is not present" },
{MOD_CHF_MODULE_ID, MOD_E_NO_MATCH, "Hardware configuration [%s] not supported" },
{MOD_CHF_MODULE_ID, MOD_E_ROM_SAVE, "Can't save Flash ROM status to disk" },
{MOD_CHF_MODULE_ID, MOD_F_MAP_SAVE, "Can't save module mapping info" },
{MOD_CHF_MODULE_ID, MOD_F_ROM_INIT, "Can't initialize internal ROM" },
{MOD_CHF_MODULE_ID, MOD_F_MAP_ALLOC, "Dynamic allocation of ModMap failed" },
{MOD_CHF_MODULE_ID, MOD_F_BAD_ALLOC_C, "Bad alloc_c [%d] after FlushCache()" },
{MOD_CHF_MODULE_ID, MOD_F_CHAIN_CORRUPTED, "Cached struct ModMap chain corrupted; freeing unlinked entry" },
{MOD_CHF_MODULE_ID, MOD_F_NO_VICTIM, "Unable to find CONFIG cache victim after cache flush" },
{MOD_CHF_MODULE_ID, MOD_F_MOD_STATUS_ALLOC, "Allocation of ModStatus_xx failed ([%d]d bytes needed)" },
{MOD_CHF_MODULE_ID, MOD_F_NO_DESCRIPTION, "ModInit() invoked without registering a ModDescription first" },
{MOD_CHF_MODULE_ID, MOD_M_NOT_MAPPED, "A[%05X] -> *Not Mapped*" },
{MOD_CHF_MODULE_ID, MOD_M_MAPPED, "A[%05X] -> M[%s] R[%05X]" },
{MOD_CHF_MODULE_ID, MOD_M_MAP_TABLE_TITLE, "Device\t\t\tAddress\tSize\tStatus" },
{MOD_CHF_MODULE_ID, MOD_M_MAP_TABLE_ROW, "%s\t%05X\t%05X\t%s" },
{MOD_CHF_MODULE_ID, MOD_M_MAP_CONFIGURED, "Configured" },
{MOD_CHF_MODULE_ID, MOD_M_MAP_SZ_CONFIGURED, "Size_configured" },
{MOD_CHF_MODULE_ID, MOD_M_MAP_UNCONFIGURED, "*Unconfigured*" },
{SERIAL_CHF_MODULE_ID, SERIAL_I_CALLED, "Function [%s] called" },
{SERIAL_CHF_MODULE_ID, SERIAL_I_REVISION, "Serial port emulator: [%s]" },
{SERIAL_CHF_MODULE_ID, SERIAL_I_READ, "Read [%s]; value [%01X]" },
{SERIAL_CHF_MODULE_ID, SERIAL_I_WRITE, "Write [%s]; value [%01X](old) -> [%01X](new)" },
{SERIAL_CHF_MODULE_ID, SERIAL_I_RBR, "Read RBR; value [%02X]" },
{SERIAL_CHF_MODULE_ID, SERIAL_I_TBR, "Write TBR; value [%02X]" },
{SERIAL_CHF_MODULE_ID, SERIAL_I_PTY_NAME, "Pseudo-terminal name is [%s]" },
{SERIAL_CHF_MODULE_ID, SERIAL_W_EMPTY_RRB, "Read from empty receiver buffer, rcs [%01X]" },
{SERIAL_CHF_MODULE_ID, SERIAL_W_FULL_TRB, "Write into full transmitter buffer, tcs [%01X]" },
{SERIAL_CHF_MODULE_ID, SERIAL_W_NOPTY, "Pseudo-terminals not supported" },
{SERIAL_CHF_MODULE_ID, SERIAL_E_TRB_DRAIN, "Error draining transmitter buffer" },
{SERIAL_CHF_MODULE_ID, SERIAL_E_RRB_CHARGE, "Error charging receiver buffer" },
{SERIAL_CHF_MODULE_ID, SERIAL_E_PTY_CLOSE, "Error shutting down pseudo-terminal" },
{SERIAL_CHF_MODULE_ID, SERIAL_F_OPENPTY, "openpty() failed on master pty" },
{SERIAL_CHF_MODULE_ID, SERIAL_F_FCNTL, "fcntl() failed on master pty" },
{SERIAL_CHF_MODULE_ID, SERIAL_F_OPEN_MASTER, "Can't open() pty master [%s]" },
{SERIAL_CHF_MODULE_ID, SERIAL_F_GRANTPT, "grantpt() failed on master pty" },
{SERIAL_CHF_MODULE_ID, SERIAL_F_UNLOCKPT, "unlockpt() failed on master pty" },
{SERIAL_CHF_MODULE_ID, SERIAL_F_OPEN_SLAVE, "Can't open() pty slave [%s]" },
{SERIAL_CHF_MODULE_ID, SERIAL_F_PUSH, "ioctl(I_PUSH,[%s]) failed on slave pty" },
{SERIAL_CHF_MODULE_ID, SERIAL_F_TCGETATTR, "tcgetattr() failed on master pty" },
{SERIAL_CHF_MODULE_ID, SERIAL_F_TCSETATTR, "tcsetattr() failed on master pty" },
{X_FUNC_CHF_MODULE_ID, X_FUNC_I_CALLED, "Function [%s] called" },
{X_FUNC_CHF_MODULE_ID, X_FUNC_I_CODE, "Emulator's extended function #[%01X]" },
{X_FUNC_CHF_MODULE_ID, X_FUNC_I_SET_SPEED, "Emulator speed set to [%d]MHz" },
{X_FUNC_CHF_MODULE_ID, X_FUNC_I_MAX_SPEED, "Emulator at maximum speed" },
{X_FUNC_CHF_MODULE_ID, X_FUNC_I_FILE_NAME, "Transferring [%s]" },
{X_FUNC_CHF_MODULE_ID, X_FUNC_I_KGET, "Kget START[%05X] END[%05X] HDR[%s]" },
{X_FUNC_CHF_MODULE_ID, X_FUNC_I_SEND, "Send START[%05X] END[%05X] HDR[%s]" },
{X_FUNC_CHF_MODULE_ID, X_FUNC_W_BAD_CODE, "Invalid function code #[%01X] ignored" },
{X_FUNC_CHF_MODULE_ID, X_FUNC_W_ABORTED, "Operation aborted by user" },
{X_FUNC_CHF_MODULE_ID, X_FUNC_W_FAILED, "Operation failed" },
{X_FUNC_CHF_MODULE_ID, X_FUNC_E_NO_HALT, "Cpu Halt requests not allowed.\n\tRebuild with CPU_SPIN_SHUTDN undefined in config.h" },
{X_FUNC_CHF_MODULE_ID, X_FUNC_E_NO_SPEED, "Cpu speed control not available.\n\tRebuild with REAL_CPU_SPEED defined in config.h" },
{X_FUNC_CHF_MODULE_ID, X_FUNC_E_NO_BIN_HDR, "Can't determine binary header for hw [%s]" },
{X_FUNC_CHF_MODULE_ID, X_FUNC_F_xxx, "X_FUNC_F_xxx" },
{X_FUNC_CHF_MODULE_ID, X_FUNC_M_KGET, "Load object from disk..." },
{X_FUNC_CHF_MODULE_ID, X_FUNC_M_SEND, "Save object to disk..." },
};
size_t message_table_size = sizeof( message_table ) / sizeof( message_table[ 0 ] );

View file

@ -1,20 +0,0 @@
#ifndef _CHF_MESSAGES_H
#define _CHF_MESSAGES_H 1
#include <stdlib.h>
#include "libChf/src/Chf.h"
#include "config.h"
#include "cpu.h"
#include "debug.h"
#include "disk_io.h"
#include "flash49.h"
#include "modules.h"
#include "serial.h"
#include "x_func.h"
extern ChfTable message_table[];
extern size_t message_table_size;
#endif /*!_CHF_MESSAGES_H*/

View file

@ -124,7 +124,43 @@
.- */
#include "ui4x/config.h"
#include <stdbool.h>
#include "ui48_config.h"
/* CHF_EXTENDED_INFO:
Define this symbol if extended information is desired during condition
handling; this is usually useful only for debugging purposes.
*/
/* #define CHF_EXTENDED_INFO */
/* DEBUG:
Define this symbol to include the debugging code for all source modules
in the executable image.
At run-time, the debug level can be set using the function SetDebugLevel();
the initial debug level is set to the value of the symbol DEBUG_LEVEL,
if it is defined, otherwise it is set to zero.
*/
/* #define DEBUG */
/* DEBUG_LEVEL:
When this symbol is defined and the debugging code has been included
in the executable image (DEBUG symbol set), the initial debug level
is set to its value.
The value must be the bitwise OR of zero or more of the symbols
DEBUG_C_<> defined in debug.h; each of them corresponds to a class
of debugging conditions that can be individually enabled or disabled.
*/
#define DEBUG_LEVEL DEBUG_C_REVISION
/* 2.1: FORCE_NONMODAL
If this symbol is defined, nonmodal navigation is forced in the
OSF/Motif GUI, by setting navigationType to XmNONE and traversalOn
to False at the source code level.
*/
/* #define FORCE_NONMODAL */
/* 2.4: N_PORT_2_BANK
This symbol is used to dimension the HP48GX Port_2: it denotes the
@ -132,7 +168,6 @@
between 1 and 32, inclusive. When undefined, Port_2 is not emulated at all.
The default value is 8, that is, Port_2 is emulated and its size is 1Mbyte.
*/
// #define N_PORT_2_BANK ( config.model == MODEL_48GX ? 32 : 1 )
#define N_PORT_2_BANK 32
/* 2.5: SERIAL_FORCE_OPENPTY, SERIAL_FORCE_STREAMSPTY
@ -144,6 +179,20 @@
/* #define SERIAL_FORCE_OPENPTY */
/* #define SERIAL_FORCE_STREAMSPTY */
/* 3.2: HP49_SUPPORT
Define this symbol to enable HP49-specific support code in the
emulator; it does not harm if this symbol is defined when emulating
a HP48, too, since all changed should be backward-compatible.
*/
#define HP49_SUPPORT
/* 3.13: REAL_CPU_SPEED
Define this symbol (recommended) to force the emulated CPU to run
no faster than a software-controlled limit; by default, the limit
is close to the real CPU speed.
*/
#define REAL_CPU_SPEED
/* 3.14: CPU_SLOW_IN
Define this symbol (recommended) to slow down the A=IN and C=IN
instructions depending on the current emulated CPU speed.
@ -153,6 +202,14 @@
*/
#define CPU_SLOW_IN 16
/* 4.1.1.1: LCD_MAG
This symbol represents the magnification ratio of the emulated LCD pixels
when drawn on the emulated display; supported values are 1 and 2; 2 is the
default. Currently, the value cannot be set at runtime for performance
reasons.
*/
#define LCD_MAG 2
/* 4.1.1.1: When defined, this symbol represents the threshold of the long
key pression. When the mouse button is kept pressed on a calculator's key
for more than LONG_PRESS_THR milliseconds, the key stays pressed after
@ -175,9 +232,70 @@
#define X_FUNC_CHF_MODULE_ID 18 /* 3.13 */
#define DEBUG_CHF_MODULE_ID 30
/* .+
.identifier : $Id: args.h,v 4.1 2000/12/11 09:54:19 cibrario Rel $
.context : SATURN, Saturn CPU / HP48 emulator
.title : $RCSfile: args.h,v $
.kind : C header
.author : Ivan Cibrario B.
.site : CSTV-CNR
.creation : 19-Jan-1998
.keywords : *
.description :
This header declares a global data structure containing the emulator
invocation arguments; this data structure is initialized before startup,
either by means of argc/argv or in other ways.
.include : config.h
.notes :
$Log: args.h,v $
Revision 4.1 2000/12/11 09:54:19 cibrario
Public release.
Revision 3.15 2000/11/15 14:03:06 cibrario
GUI enhancements and assorted bug fixes:
- added .batchXfer boolean (corresponding to command-line option
-batchXfer) to struct Args
Revision 3.10 2000/10/24 16:14:25 cibrario
Added/Replaced GPL header
Revision 2.1 2000/09/08 14:45:06 cibrario
Added the following fields to 'struct Args': reset, monitor, hw.
The latter mimes the setting of the -hw command line option and
of the *hw top-level application resource; the former two have
been added to export them cleanly from the GUI modules.
* Revision 1.1 1998/02/17 11:58:37 cibrario
* Initial revision
*
.- */
/*---------------------------------------------------------------------------
Data type definitions - require config.h
---------------------------------------------------------------------------*/
struct Args {
bool reset; /* 2.1: Force emulator reset */
bool monitor; /* 2.1: Call monitor() on startup */
bool batchXfer; /* 3.15: Non-interactive file transfers */
char* mod_file_name;
char* cpu_file_name;
char* hdw_file_name;
char* rom_file_name;
char* ram_file_name;
char* port_1_file_name;
char* port_2_file_name;
char* hw; /* 2.1: Hardware configuration (unused) */
};
/*---------------------------------------------------------------------------
Global variables
---------------------------------------------------------------------------*/
extern config_t config;
extern struct Args args;
#endif /*!_CONFIG_H*/

2556
src/cpu.c

File diff suppressed because it is too large Load diff

View file

@ -108,8 +108,6 @@
.- */
#include <stdbool.h>
/*---------------------------------------------------------------------------
Macro/Data type definitions - require machdep.h
@ -136,48 +134,48 @@
#define CPU_RCS_INFO "$Revision: 4.1 $ $State: Rel $"
/* Instruction opcode access macros:
GET_FS(f) returns the short field-selector value from the
GetFS(f) returns the short field-selector value from the
given nibble (bits 2..0)
GET_IMMEDIATE_FS_FLAG(f) returns the immediate-field-selector flag from the
GetImmFS(f) returns the immediate-field-selector flag from the
given nibble (bit 3)
=0: regular field selector
!=0: immediate field selector
GET_OC_1(o) returns the short operation code from the given
GetOC_1(o) returns the short operation code from the given
nibble (bits 3..2 >>2)
GET_OC_2(f, o) returns the long operation code from the given
GetOC_2(f, o) returns the long operation code from the given
nibbles (f bit 3, o bits 3..2)
GET_OC_3b(o) returns the long operation code from the given
GetOC_3b(o) returns the long operation code from the given
nibble (bits 2..0)
GET_RP(o) returns the register-pair identifier from the given
GetRP(o) returns the register-pair identifier from the given
nibble (bits 1..0)
GET_Rn(r) returns the R register index from the given nibble
GetRn(r) returns the R register index from the given nibble
(bits 2..0)
GET_AC(r) returns the A/C register flag from the given nibble
GetAC(r) returns the A/C register flag from the given nibble
(bit 3)
=0: register A
!=0: register C
GET_AS(r) returns the add/subtract flag from the given nibble
GetAS(r) returns the add/subtract flag from the given nibble
(bit 3)
=0: add
!=0: subtract
*/
#define GET_FS( f ) ( ( f ) & 0x7 )
#define GET_IMMEDIATE_FS_FLAG( o ) ( ( o ) & 0x8 )
#define GET_OC_1( o ) ( ( ( o ) & 0xC ) >> 2 )
#define GET_OC_2( f, o ) ( ( ( ( f ) & 0x8 ) >> 1 ) | ( ( ( o ) & 0xC ) >> 2 ) )
#define GET_OC_3b( o ) ( ( o ) & 0x7 )
#define GET_RP( o ) ( ( o ) & 0x3 )
#define GET_Rn( r ) ( ( r ) & 0x7 )
#define GET_AC( r ) ( ( r ) & 0x8 )
#define GET_AS( r ) ( ( r ) & 0x8 )
#define GetFS( f ) ( ( f ) & 0x7 )
#define GetImmFS( o ) ( ( o ) & 0x8 )
#define GetOC_1( o ) ( ( ( o ) & 0xC ) >> 2 )
#define GetOC_2( f, o ) ( ( ( ( f ) & 0x8 ) >> 1 ) | ( ( ( o ) & 0xC ) >> 2 ) )
#define GetOC_3b( o ) ( ( o ) & 0x7 )
#define GetRP( o ) ( ( o ) & 0x3 )
#define GetRn( r ) ( ( r ) & 0x7 )
#define GetAC( r ) ( ( r ) & 0x8 )
#define GetAS( r ) ( ( r ) & 0x8 )
/* Field selector codes */
#define FS_P 0
@ -254,12 +252,12 @@ struct CpuStatus {
int fs_idx_lo[ N_FS ];
int fs_idx_hi[ N_FS ];
bool hexmode; /* DEC/HEX mode */
bool carry; /* Carry bit */
bool shutdn; /* SHUTDN flag */
bool halt; /* Halt flag */
bool int_enable; /* Int. enable */
bool int_service; /* Int. service */
int hexmode; /* DEC/HEX mode, 1=HEX */
int carry; /* Carry bit 1=set */
int shutdn; /* SHUTDN flag, 1=executed */
int halt; /* 3.13: # of pending Halt */
int int_enable; /* Int. enable, 1=enabled */
int int_service; /* Int. service, 1=service */
enum IntRequest int_pending; /* Pending interrupt request */
/* 3.13: inner_loop_max gives the upper limit of the CPU speed if the
@ -333,9 +331,9 @@ void EmulatorInit( void ); /* 2.1 */
void EmulatorExit( enum ExitOption opt ); /* 2.1 */
int CpuHaltRequest( void ); /* 3.13 */
int CpuRunRequest( void ); /* 3.13 */
bool CpuHaltAllowed( void ); /* 3.13 */
int CpuHaltAllowed( void ); /* 3.13 */
Address Disassemble( Address pc, char ob[ DISASSEMBLE_OB_SIZE ] ); /* dis.c */
Address Disassemble( Address pc, char ob[ DISASSEMBLE_OB_SIZE ] );
void DumpCpuStatus( char ob[ DUMP_CPU_STATUS_OB_SIZE ] );
#endif /*!_CPU_H*/

125
src/debug.c Normal file
View file

@ -0,0 +1,125 @@
/* -------------------------------------------------------------------------
saturn - A poor-man's emulator of some HP calculators
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
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 the documentation of this program; if not, write to
the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
For more information, please contact the author, preferably by email,
at the following address:
Ivan Cibrario Bertolotti
IRITI - National Research Council
c/o IEN "Galileo Ferraris"
Strada delle Cacce, 91
10135 - Torino (ITALY)
email: cibrario@iriti.cnr.it
------------------------------------------------------------------------- */
/* +-+ */
/* .+
.identifier : $Id: debug.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $
.context : SATURN, Saturn CPU / HP48 emulator
.title : $RCSfile: debug.c,v $
.kind : C source
.author : Ivan Cibrario B.
.site : CSTV-CNR
.creation : 28-Jan-1998
.keywords : *
.description :
Debugging support.
.include : debug.h
.notes :
$Log: debug.c,v $
Revision 4.1 2000/12/11 09:54:19 cibrario
Public release.
Revision 3.10 2000/10/24 16:14:32 cibrario
Added/Replaced GPL header
Revision 1.1 1998/02/17 11:42:30 cibrario
Initial revision
.- */
#ifndef lint
static char rcs_id[] = "$Id: debug.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include "config.h"
#include "machdep.h"
#include "cpu.h"
#include "debug.h"
#define CHF_MODULE_ID DEBUG_CHF_MODULE_ID
#include <Chf.h>
/*---------------------------------------------------------------------------
Static/Global variables
---------------------------------------------------------------------------*/
#ifdef DEBUG
# ifdef DEBUG_LEVEL
int debug_level = DEBUG_LEVEL;
# else
int debug_level = 0;
# endif
#endif
/*---------------------------------------------------------------------------
Public functions
---------------------------------------------------------------------------*/
/* .+
.title : SetDebugLevel
.kind : C function
.creation : 28-Jan-1998
.description :
If runtime debug support is enabled (symbol DEBUG defined during executable
image build) this function updates the 'debug_level' flag, otherwise
it signals a condition and does nothing more.
.call :
SetDebugLevel(new_level)
.input :
int new_level, new value of the debug_level flag
.output :
void
.status_codes :
DEBUG_W_NOT_SUPPORTED
.notes :
1.1, 28-Jan-1998, creation
.- */
void SetDebugLevel( int new_level )
{
#ifdef DEBUG
debug_level = new_level;
#else
ChfCondition DEBUG_W_NOT_SUPPORTED, CHF_WARNING ChfEnd;
ChfSignal();
#endif
}

View file

@ -102,22 +102,37 @@
.- */
#define debug_preamble( module_id, debug_class, condition_code ) \
{ \
if ( config.debug_level & ( debug_class ) ) { ChfGenerate( module_id, __FILE__, __LINE__, condition_code, CHF_INFO
#define debug_postamble( module_id ) ); \
ChfSignal( module_id ); \
} \
}
#ifdef DEBUG
#define debug0( module_id, debug_class, condition_code ) \
debug_preamble( module_id, debug_class, condition_code ) debug_postamble( module_id )
#define debug1( module_id, debug_class, condition_code, arg_1 ) \
debug_preamble( module_id, debug_class, condition_code ), arg_1 debug_postamble( module_id )
#define debug2( module_id, debug_class, condition_code, arg_1, arg_2 ) \
debug_preamble( module_id, debug_class, condition_code ), arg_1, arg_2 debug_postamble( module_id )
#define debug3( module_id, debug_class, condition_code, arg_1, arg_2, arg_3 ) \
debug_preamble( module_id, debug_class, condition_code ), arg_1, arg_2, arg_3 debug_postamble( module_id )
# define debug_preamble( debug_class, condition_code ) \
{ \
extern int debug_level; \
if ( debug_level & ( debug_class ) ) { \
ChfCondition( condition_code ), CHF_INFO
# define debug_postamble \
ChfEnd; \
ChfSignal(); \
} \
}
# define debug0( debug_class, condition_code ) debug_preamble( debug_class, condition_code ) debug_postamble
# define debug1( debug_class, condition_code, arg_1 ) debug_preamble( debug_class, condition_code ), arg_1 debug_postamble
# define debug2( debug_class, condition_code, arg_1, arg_2 ) debug_preamble( debug_class, condition_code ), arg_1, arg_2 debug_postamble
# define debug3( debug_class, condition_code, arg_1, arg_2, arg_3 ) \
debug_preamble( debug_class, condition_code ), arg_1, arg_2, arg_3 debug_postamble
#else
# define debug0( debug_class, condition_code )
# define debug1( debug_class, condition_code, arg_1 )
# define debug2( debug_class, condition_code, arg_1, arg_2 )
# define debug3( debug_class, condition_code, arg_1, arg_2, arg_3 )
#endif
/*---------------------------------------------------------------------------
Debug classes
@ -133,9 +148,8 @@
#define DEBUG_C_IMPLEMENTATION 0x0100 /* Feature implementation */
#define DEBUG_C_FLASH 0x0080 /* 3.3: Flash ROM */
#define DEBUG_C_X_FUNC 0x0040 /* 3.13: Extended functions */
#define DEBUG_C_XX 0x0010
#define DEBUG_C_OPCODES 0x0001 /* OpCodes */
#define DEBUG_C_NONE 0
#define DEBUG_C_REVISION 0x0010 /* Revision information */
#define DEBUG_C_X11 0x0001 /* X11 Interface */
/*---------------------------------------------------------------------------
Chf condition codes
@ -144,4 +158,10 @@
#define DEBUG_W_NOT_SUPPORTED 201 /* Debug not supported */
#define DEBUG_W_BAD_CMD 202 /* Invalid command */
/*---------------------------------------------------------------------------
Function prototypes
---------------------------------------------------------------------------*/
void SetDebugLevel( int new_level );
#endif /*!_DEBUG_H*/

575
src/dis.c

File diff suppressed because it is too large Load diff

View file

@ -61,10 +61,14 @@
.- */
#ifndef lint
static char rcs_id[] = "$Id: disk_io.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include "libChf/src/Chf.h"
#include <setjmp.h>
#include <errno.h>
#include "config.h"
#include "machdep.h"
@ -72,6 +76,9 @@
#include "disk_io.h"
#include "debug.h"
#define CHF_MODULE_ID DISK_IO_CHF_MODULE_ID
#include <Chf.h>
/* .+
.title : ReadNibblesFromFile
@ -105,18 +112,18 @@ int ReadNibblesFromFile( const char* name, int size, Nibble* dest )
int by;
int st = DISK_IO_S_OK;
debug1( DISK_IO_CHF_MODULE_ID, DEBUG_C_TRACE, DISK_IO_I_CALLED, "ReadNibblesFromFile" );
debug1( DEBUG_C_TRACE, DISK_IO_I_CALLED, "ReadNibblesFromFile" );
if ( ( f = fopen( name, "rb" ) ) == ( FILE* )NULL ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( DISK_IO_CHF_MODULE_ID, __FILE__, __LINE__, st = DISK_IO_E_OPEN, CHF_ERROR, name );
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_OPEN, CHF_ERROR, name ChfEnd;
} else {
for ( i = 0; i < size; ) {
by = getc( f );
if ( by == -1 ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( DISK_IO_CHF_MODULE_ID, __FILE__, __LINE__, st = DISK_IO_E_GETC, CHF_ERROR, name );
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_GETC, CHF_ERROR, name ChfEnd;
break;
}
@ -163,26 +170,26 @@ int WriteNibblesToFile( const Nibble* src, int size, const char* name )
int by;
int st = DISK_IO_S_OK;
debug1( DISK_IO_CHF_MODULE_ID, DEBUG_C_TRACE, DISK_IO_I_CALLED, "WriteNibblesToFile" );
debug1( DEBUG_C_TRACE, DISK_IO_I_CALLED, "WriteNibblesToFile" );
if ( ( f = fopen( name, "wb" ) ) == ( FILE* )NULL ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( DISK_IO_CHF_MODULE_ID, __FILE__, __LINE__, st = DISK_IO_E_OPEN, CHF_ERROR, name );
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_OPEN, CHF_ERROR, name ChfEnd;
} else {
for ( i = 0; i < size; ) {
by = ( int )src[ i++ ];
by |= ( int )src[ i++ ] << 4;
if ( putc( by, f ) == EOF ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( DISK_IO_CHF_MODULE_ID, __FILE__, __LINE__, st = DISK_IO_E_PUTC, CHF_ERROR, name );
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_PUTC, CHF_ERROR, name ChfEnd;
break;
}
}
if ( fclose( f ) == EOF ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( DISK_IO_CHF_MODULE_ID, __FILE__, __LINE__, st = DISK_IO_E_CLOSE, CHF_ERROR, name );
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_CLOSE, CHF_ERROR, name ChfEnd;
}
}
@ -218,15 +225,15 @@ int ReadStructFromFile( const char* name, size_t s_size, void* s )
FILE* f;
int st = DISK_IO_S_OK;
debug1( DISK_IO_CHF_MODULE_ID, DEBUG_C_TRACE, DISK_IO_I_CALLED, "ReadStructFromFile" );
debug1( DEBUG_C_TRACE, DISK_IO_I_CALLED, "ReadStructFromFile" );
if ( ( f = fopen( name, "rb" ) ) == ( FILE* )NULL ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( DISK_IO_CHF_MODULE_ID, __FILE__, __LINE__, st = DISK_IO_E_OPEN, CHF_ERROR, name );
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_OPEN, CHF_ERROR, name ChfEnd;
} else {
if ( fread( s, s_size, ( size_t )1, f ) != 1 ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( DISK_IO_CHF_MODULE_ID, __FILE__, __LINE__, st = DISK_IO_E_READ, CHF_ERROR, name );
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_READ, CHF_ERROR, name ChfEnd;
}
( void )fclose( f );
@ -266,20 +273,20 @@ int WriteStructToFile( const void* s, size_t s_size, const char* name )
FILE* f;
int st = DISK_IO_S_OK;
debug1( DISK_IO_CHF_MODULE_ID, DEBUG_C_TRACE, DISK_IO_I_CALLED, "WriteStructToFile" );
debug1( DEBUG_C_TRACE, DISK_IO_I_CALLED, "WriteStructToFile" );
if ( ( f = fopen( name, "wb" ) ) == ( FILE* )NULL ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( DISK_IO_CHF_MODULE_ID, __FILE__, __LINE__, st = DISK_IO_E_OPEN, CHF_ERROR, name );
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_OPEN, CHF_ERROR, name ChfEnd;
} else {
if ( fwrite( s, s_size, ( size_t )1, f ) != 1 ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( DISK_IO_CHF_MODULE_ID, __FILE__, __LINE__, st = DISK_IO_E_WRITE, CHF_ERROR, name );
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_WRITE, CHF_ERROR, name ChfEnd;
}
if ( fclose( f ) == EOF ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( DISK_IO_CHF_MODULE_ID, __FILE__, __LINE__, st = DISK_IO_E_CLOSE, CHF_ERROR, name );
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_CLOSE, CHF_ERROR, name ChfEnd;
}
}

View file

@ -58,12 +58,16 @@
.- */
#ifndef lint
static char rcs_id[] = "$Id: disk_io_obj.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <errno.h>
#include <string.h>
#include "libChf/src/Chf.h"
#include "config.h"
#include "machdep.h"
#include "cpu.h"
@ -71,6 +75,9 @@
#include "disk_io.h"
#include "debug.h"
#define CHF_MODULE_ID DISK_IO_CHF_MODULE_ID
#include <Chf.h>
/* .+
.title : ReadObjectFromFile
@ -128,26 +135,26 @@ int ReadObjectFromFile( const char* name, const char* hdr, Address start, Addres
int st = DISK_IO_S_OK;
debug1( DISK_IO_CHF_MODULE_ID, DEBUG_C_TRACE, DISK_IO_I_CALLED, "ReadObjectFromFile" );
debug1( DEBUG_C_TRACE, DISK_IO_I_CALLED, "ReadObjectFromFile" );
/* Save first nibbles of target space into save_area */
for ( cur = start, i = 0; cur < end && i < N_SAVE_AREA; cur++, i++ )
save_area[ i ] = ReadNibble( cur );
if ( ( f = fopen( name, "rb" ) ) == ( FILE* )NULL ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( DISK_IO_CHF_MODULE_ID, __FILE__, __LINE__, st = DISK_IO_E_OPEN, CHF_ERROR, name );
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_OPEN, CHF_ERROR, name ChfEnd;
} else {
/* Check and skip header */
for ( i = 0; i < ( int )hdr_len; i++ ) {
by = getc( f );
if ( by == EOF ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( DISK_IO_CHF_MODULE_ID, __FILE__, __LINE__, st = DISK_IO_E_GETC, CHF_ERROR, name );
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_GETC, CHF_ERROR, name ChfEnd;
break;
} else if ( hdr[ i ] != '?' && by != hdr[ i ] ) {
ChfGenerate( DISK_IO_CHF_MODULE_ID, __FILE__, __LINE__, st = DISK_IO_E_BAD_HDR, CHF_ERROR, name );
ChfCondition st = DISK_IO_E_BAD_HDR, CHF_ERROR, name ChfEnd;
break;
}
}
@ -159,7 +166,7 @@ int ReadObjectFromFile( const char* name, const char* hdr, Address start, Addres
while ( ( by = getc( f ) ) != EOF ) {
/* Next byte available in by; check available space */
if ( cur >= end - 1 ) {
ChfGenerate( DISK_IO_CHF_MODULE_ID, __FILE__, __LINE__, st = DISK_IO_E_SIZE, CHF_ERROR, name );
ChfCondition st = DISK_IO_E_SIZE, CHF_ERROR, name ChfEnd;
break;
}
@ -170,8 +177,8 @@ int ReadObjectFromFile( const char* name, const char* hdr, Address start, Addres
/* Check why getc() failed */
if ( ferror( f ) && !feof( f ) ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( DISK_IO_CHF_MODULE_ID, __FILE__, __LINE__, st = DISK_IO_E_GETC, CHF_ERROR, name );
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_GETC, CHF_ERROR, name ChfEnd;
}
/* Recover from save_area if transfer failed */
@ -229,17 +236,17 @@ int WriteObjectToFile( Address start, Address end, const char* hdr, const char*
int st = DISK_IO_S_OK;
debug1( DISK_IO_CHF_MODULE_ID, DEBUG_C_TRACE, DISK_IO_I_CALLED, "WriteObjectFromFile" );
debug1( DEBUG_C_TRACE, DISK_IO_I_CALLED, "WriteObjectFromFile" );
if ( ( f = fopen( name, "wb" ) ) == ( FILE* )NULL ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( DISK_IO_CHF_MODULE_ID, __FILE__, __LINE__, st = DISK_IO_E_OPEN, CHF_ERROR, name );
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_OPEN, CHF_ERROR, name ChfEnd;
} else {
/* Write header; replace wildcard character '?' with 'S' */
for ( i = 0; i < ( int )hdr_len; i++ ) {
if ( putc( hdr[ i ] == '?' ? 'S' : hdr[ i ], f ) == EOF ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( DISK_IO_CHF_MODULE_ID, __FILE__, __LINE__, st = DISK_IO_E_PUTC, CHF_ERROR, name );
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_PUTC, CHF_ERROR, name ChfEnd;
break;
}
}
@ -253,8 +260,8 @@ int WriteObjectToFile( Address start, Address end, const char* hdr, const char*
by |= ( int )ReadNibble( cur++ ) << 4;
if ( putc( by, f ) == EOF ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( DISK_IO_CHF_MODULE_ID, __FILE__, __LINE__, st = DISK_IO_E_PUTC, CHF_ERROR, name );
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_PUTC, CHF_ERROR, name ChfEnd;
break;
}
}
@ -264,16 +271,16 @@ int WriteObjectToFile( Address start, Address end, const char* hdr, const char*
by = ( int )ReadNibble( cur++ );
if ( putc( by, f ) == EOF ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( DISK_IO_CHF_MODULE_ID, __FILE__, __LINE__, st = DISK_IO_E_PUTC, CHF_ERROR, name );
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_PUTC, CHF_ERROR, name ChfEnd;
}
}
}
/* Close the output file anyway */
if ( fclose( f ) == EOF ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( DISK_IO_CHF_MODULE_ID, __FILE__, __LINE__, st = DISK_IO_E_CLOSE, CHF_ERROR, name );
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_CLOSE, CHF_ERROR, name ChfEnd;
}
}

View file

@ -107,6 +107,10 @@
.- */
#ifndef lint
static char rcs_id[] = "$Id: emulator.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
@ -114,15 +118,18 @@
#include <unistd.h>
#include <sys/time.h>
#include "libChf/src/Chf.h"
#include "config.h"
#include "machdep.h"
#include "cpu.h"
#include "modules.h"
#include "x11_lcd.h"
#include "x11.h"
#include "serial.h"
#include "debug.h"
#define CHF_MODULE_ID CPU_CHF_MODULE_ID
#include <Chf.h>
/*---------------------------------------------------------------------------
Private macros / variables / functions
---------------------------------------------------------------------------*/
@ -154,7 +161,7 @@
#define LCD_T1_MASK 0x3 /* LCD refresh timing mask */
#define INT_T1_MASK 0xF /* Int. req. timing mask */
static bool emulator_int_req = false; /* Interrupt request flag */
static int emulator_int_req = 0; /* Interrupt request flag */
/* This function contains the main emulator loop; under normal conditions,
it never returns to the caller. The only way to exit this function is
@ -166,26 +173,27 @@ static void EmulatorLoop( void )
int ela;
int inner_loop = cpu_status.inner_loop;
int t1_count = 0;
int i, j;
debug1( CPU_CHF_MODULE_ID, DEBUG_C_TRACE, CPU_I_CALLED, "EmulatorLoop" );
debug1( DEBUG_C_TRACE, CPU_I_CALLED, "EmulatorLoop" );
/* Ignore past interrupt requests */
emulator_int_req = false;
emulator_int_req = 0;
/* Get current time of day */
gettimeofday( &old_t, NULL );
while ( true ) {
while ( 1 ) {
/* T1 loop */
for ( int j = 0; j < T1_MULTIPLIER; j++ ) {
for ( j = 0; j < T1_MULTIPLIER; j++ ) {
/* Inner loop */
for ( int i = 0; i < inner_loop; i++ )
for ( i = 0; i < inner_loop; i++ )
OneStep();
/* T2 update */
if ( mod_status.hdw.t2_ctrl & T2_CTRL_TRUN ) {
if ( --mod_status.hdw.t2_val == ( int )0xFFFFFFFF ) {
debug1( CPU_CHF_MODULE_ID, DEBUG_C_TIMERS, CPU_I_TIMER2_EX, mod_status.hdw.t2_ctrl );
debug1( DEBUG_C_TIMERS, CPU_I_TIMER2_EX, mod_status.hdw.t2_ctrl );
mod_status.hdw.t2_ctrl |= T2_CTRL_SREQ;
@ -201,7 +209,7 @@ static void EmulatorLoop( void )
/* T1 update */
mod_status.hdw.t1_val = ( mod_status.hdw.t1_val - 1 ) & NIBBLE_MASK;
if ( mod_status.hdw.t1_val == 0xF ) {
debug1( CPU_CHF_MODULE_ID, DEBUG_C_TIMERS, CPU_I_TIMER1_EX, mod_status.hdw.t1_ctrl );
debug1( DEBUG_C_TIMERS, CPU_I_TIMER1_EX, mod_status.hdw.t1_ctrl );
mod_status.hdw.t1_ctrl |= T1_CTRL_SREQ;
@ -217,13 +225,13 @@ static void EmulatorLoop( void )
/* DrawLcd(); */
/* Emulator Interrupt Request */
if ( ( t1_count++ & INT_T1_MASK ) == 0 && emulator_int_req ) {
ChfGenerate( CPU_CHF_MODULE_ID, __FILE__, __LINE__, CPU_I_EMULATOR_INT, CHF_INFO );
ChfSignal( CPU_CHF_MODULE_ID );
if ( ( t1_count & INT_T1_MASK ) == 0 && emulator_int_req ) {
ChfCondition CPU_I_EMULATOR_INT, CHF_INFO ChfEnd;
ChfSignal();
}
/* UI Events handling */
// ui_get_event();
/* X Events handling */
/* HandleXEvents(); */
/* Handle serial port */
HandleSerial();
@ -237,237 +245,236 @@ static void EmulatorLoop( void )
if ( inner_loop < INNER_LOOP_MIN )
inner_loop = INNER_LOOP_MIN;
/* 3.13: Force an upper limit to the CPU speed if the run-time option
config.throttle is defined: inner_loop is limited to
#ifdef REAL_CPU_SPEED
/* 3.13: Force an upper limit to the CPU speed if the compile-time option
REAL_CPU_SPEED is defined: inner_loop is limited to
cpu_status.inner_loop_max
and the excess time, if any, is spent sleeping; usleep() is
BSD 4.3-specific, but most recent systems should offer it anyway,
well, I hope.
The special value cpu_status.inner_loop_max==0 gives maximum speed.
*/
if ( config.throttle )
if ( cpu_status.inner_loop_max != 0 && inner_loop >= cpu_status.inner_loop_max ) {
inner_loop = cpu_status.inner_loop_max;
if ( T1_INTERVAL > ela )
usleep( T1_INTERVAL - ela );
}
if ( cpu_status.inner_loop_max != 0 && inner_loop >= cpu_status.inner_loop_max ) {
inner_loop = cpu_status.inner_loop_max;
if ( T1_INTERVAL > ela )
usleep( T1_INTERVAL - ela );
}
#endif
cpu_status.inner_loop = inner_loop;
old_t = cur_t;
}
}
static ChfAction do_SHUTDN( void )
{
/* 3.1: CPU_SPIN_SHUTDN is not defined, and the cpu emulator
has just executed a shutdown instruction.
Let's do something a little tricky here:
//1- redraw the LCD
2- handle serial port activities
3- determine which timer will expire first, and
compute an approximate value of the maximum duration
of the shutdown --> ms
4- handle serial port activities
5- enter the inner idle loop; it breaks when either an
X Event occurred (possibly clearing the shutdown) or
the shutdown timeout elapses
6- determine the actual time we spend in the idle loop
(X timeouts are not accurate enough for this purpose)
7- update T1 and T2, check their state and wake/interrupt
the CPU if necessary
Activities 3-7 above are enclosed in an outer loop because we
cannot be absolutely sure of the actual time spent
in the idle loop; moreover, not all X Events actually
spool up the CPU. The outer loop breaks when the CPU is
actually brought out of shutdown.
frac_t1 and frac_t2 contain the number of microseconds
not accounted for in the last T1/T2 update, respectively;
they help minimize the cumulative timing error induced
by executing the outer idle loop more than once.
*/
struct timeval start_idle, end_idle;
int frac_t1 = 0, frac_t2 = 0;
gettimeofday( &start_idle, NULL );
/* Redraw the LCD immediately before entering idle loop;
this ensures that the latest LCD updated actually
get to the screen.
*/
// ui_update_display();
/* Handle serial port activity before entering the outer idle
loop, because this could possibly bring the cpu out of
shutdown right now.
*/
HandleSerial();
/* XXX
If either timer has a pending service request,
process it immediately. It is not clear why it was
not processed *before* shutdown, though.
*/
if ( mod_status.hdw.t1_ctrl & T1_CTRL_SREQ ) {
if ( mod_status.hdw.t1_ctrl & T1_CTRL_WAKE )
CpuWake();
if ( mod_status.hdw.t1_ctrl & T1_CTRL_INT )
CpuIntRequest( INT_REQUEST_IRQ );
}
if ( mod_status.hdw.t2_ctrl & T2_CTRL_SREQ ) {
if ( mod_status.hdw.t2_ctrl & T2_CTRL_WAKE )
CpuWake();
if ( mod_status.hdw.t2_ctrl & T2_CTRL_INT )
CpuIntRequest( INT_REQUEST_IRQ );
}
while ( cpu_status.shutdn ) {
unsigned long ms = MAX_IDLE_X_LOOP_TIMEOUT;
unsigned long mst;
int ela;
int ela_ticks;
debug3( CPU_CHF_MODULE_ID, DEBUG_C_TIMERS, CPU_I_TIMER_ST, "T1 (during SHUTDN)", mod_status.hdw.t1_ctrl, mod_status.hdw.t1_val );
debug3( CPU_CHF_MODULE_ID, DEBUG_C_TIMERS, CPU_I_TIMER_ST, "T2 (during SHUTDN)", mod_status.hdw.t2_ctrl, mod_status.hdw.t2_val );
/* Determine which timer will expire first */
if ( mod_status.hdw.t1_ctrl & ( T1_CTRL_INT | T1_CTRL_WAKE ) ) {
/* T1 will do something on expiration */
mst = ( ( unsigned long )mod_status.hdw.t1_val + 1 ) * T1_MS_MULTIPLIER;
debug2( CPU_CHF_MODULE_ID, DEBUG_C_TIMERS, CPU_I_TIMER_EXP, "T1", mst );
if ( mst < ms )
ms = mst;
}
if ( ( mod_status.hdw.t2_ctrl & T2_CTRL_TRUN ) && ( mod_status.hdw.t2_ctrl & ( T2_CTRL_INT | T2_CTRL_WAKE ) ) ) {
/* T2 is running and will do something on expiration */
mst = ( ( unsigned long )mod_status.hdw.t2_val + 1 ) / T2_MS_DIVISOR;
debug2( CPU_CHF_MODULE_ID, DEBUG_C_TIMERS, CPU_I_TIMER_EXP, "T2", mst );
if ( mst < ms )
ms = mst;
}
/* Handle serial port activities at each iteration of
the outer idle loop; this ensures that the serial
port emulation will not starve.
*/
HandleSerial();
/* Enter idle loop, possibly with timeout;
The loop breaks when:
- any X Event occurs (possibly clearing the shutdown)
- the given timeout expires
*/
debug1( CPU_CHF_MODULE_ID, DEBUG_C_TIMERS, CPU_I_IDLE_X_LOOP, ms );
// IdleXLoop( ms );
usleep( ms );
/* End of idle loop; compute actual elapsed time */
gettimeofday( &end_idle, NULL );
ela = ( end_idle.tv_sec - start_idle.tv_sec ) * 1000000 + ( end_idle.tv_usec - start_idle.tv_usec );
/* Update start_idle here to contain lag */
start_idle = end_idle;
debug1( CPU_CHF_MODULE_ID, DEBUG_C_TIMERS, CPU_I_ELAPSED, ela );
/* Update timers and act accordingly */
ela_ticks = ( ( ela + frac_t1 ) + T1_INTERVAL / 2 ) / T1_INTERVAL;
frac_t1 = ( ela + frac_t1 ) - ela_ticks * T1_INTERVAL;
if ( ela_ticks > mod_status.hdw.t1_val ) {
debug1( CPU_CHF_MODULE_ID, DEBUG_C_TIMERS, CPU_I_TIMER1_EX, mod_status.hdw.t1_ctrl );
mod_status.hdw.t1_ctrl |= T1_CTRL_SREQ;
if ( mod_status.hdw.t1_ctrl & T1_CTRL_WAKE )
CpuWake();
if ( mod_status.hdw.t1_ctrl & T1_CTRL_INT )
CpuIntRequest( INT_REQUEST_IRQ );
}
mod_status.hdw.t1_val = ( mod_status.hdw.t1_val - ela_ticks ) & T1_OVF_MASK;
if ( mod_status.hdw.t2_ctrl & T2_CTRL_TRUN ) {
ela_ticks = ( ( ela + frac_t2 ) + T2_INTERVAL / 2 ) / T2_INTERVAL;
frac_t2 = ( ela + frac_t2 ) - ela_ticks * T2_INTERVAL;
if ( ela_ticks > mod_status.hdw.t2_val ) {
debug1( CPU_CHF_MODULE_ID, DEBUG_C_TIMERS, CPU_I_TIMER2_EX, mod_status.hdw.t2_ctrl );
mod_status.hdw.t2_ctrl |= T2_CTRL_SREQ;
if ( mod_status.hdw.t2_ctrl & T2_CTRL_WAKE )
CpuWake();
if ( mod_status.hdw.t2_ctrl & T2_CTRL_INT )
CpuIntRequest( INT_REQUEST_IRQ );
}
mod_status.hdw.t2_val = ( mod_status.hdw.t2_val - ela_ticks ) & T2_OVF_MASK;
}
}
debug3( CPU_CHF_MODULE_ID, DEBUG_C_TIMERS, CPU_I_TIMER_ST, "T1 (after SHUTDN)", mod_status.hdw.t1_ctrl, mod_status.hdw.t1_val );
debug3( CPU_CHF_MODULE_ID, DEBUG_C_TIMERS, CPU_I_TIMER_ST, "T2 (after SHUTDN)", mod_status.hdw.t2_ctrl, mod_status.hdw.t2_val );
return CHF_CONTINUE;
}
/* Condition handler for the EmulatorLoop */
static ChfAction EmulatorLoopHandler( const ChfDescriptor* descriptor, const ChfState state, void* _ctx )
static ChfAction EmulatorLoopHandler( const ChfDescriptor* d, const ChfState s, ChfPointer ctx )
{
ChfAction act;
/* Check Chf state */
switch ( state ) {
switch ( s ) {
/* 2.1: Chf release 2 fixed the spelling of 'SIGNALING' */
case CHF_SIGNALING:
/* ChfSignal() in progress */
switch ( descriptor->module_id ) {
case CPU_CHF_MODULE_ID:
/* Condition from CPU modules; check Condition Code */
switch ( descriptor->condition_code ) {
case CPU_I_SHUTDN:
act = do_SHUTDN();
break;
if ( ChfGetModuleId( d ) == CPU_CHF_MODULE_ID ) {
/* Condition from CPU modules; check Condition Code */
switch ( ChfGetConditionCode( d ) ) {
case CPU_I_SHUTDN:
{
/* 3.1: CPU_SPIN_SHUTDN is not defined, and the cpu emulator
has just executed a shutdown instruction.
Let's do something a little tricky here:
case CPU_I_EMULATOR_INT:
/* Emulator interrupt; unwind */
act = CHF_UNWIND;
break;
1- redraw the LCD
2- handle serial port activities
3- determine which timer will expire first, and
compute an approximate value of the maximum duration
of the shutdown --> ms
4- handle serial port activities
5- enter the inner idle loop; it breaks when either an
X Event occurred (possibly clearing the shutdown) or
the shutdown timeout elapses
6- determine the actual time we spend in the idle loop
(X timeouts are not accurate enough for this purpose)
7- update T1 and T2, check their state and wake/interrupt
the CPU if necessary
Activities 3-7 above are enclosed in an outer loop because we
cannot be absolutely sure of the actual time spent
in the idle loop; moreover, not all X Events actually
spool up the CPU. The outer loop breaks when the CPU is
actually brought out of shutdown.
frac_t1 and frac_t2 contain the number of microseconds
not accounted for in the last T1/T2 update, respectively;
they help minimize the cumulative timing error induced
by executing the outer idle loop more than once.
*/
struct timeval start_idle, end_idle;
int frac_t1 = 0, frac_t2 = 0;
gettimeofday( &start_idle, NULL );
/* Redraw the LCD immediately before entering idle loop;
this ensures that the latest LCD updated actually
get to the screen.
*/
// DrawLcd();
/* Handle serial port activity before entering the outer idle
loop, because this could possibly bring the cpu out of
shutdown right now.
*/
HandleSerial();
/* XXX
If either timer has a pending service request,
process it immediately. It is not clear why it was
not processed *before* shutdown, though.
*/
if ( mod_status.hdw.t1_ctrl & T1_CTRL_SREQ ) {
if ( mod_status.hdw.t1_ctrl & T1_CTRL_WAKE )
CpuWake();
if ( mod_status.hdw.t1_ctrl & T1_CTRL_INT )
CpuIntRequest( INT_REQUEST_IRQ );
}
if ( mod_status.hdw.t2_ctrl & T2_CTRL_SREQ ) {
if ( mod_status.hdw.t2_ctrl & T2_CTRL_WAKE )
CpuWake();
if ( mod_status.hdw.t2_ctrl & T2_CTRL_INT )
CpuIntRequest( INT_REQUEST_IRQ );
}
while ( cpu_status.shutdn ) {
unsigned long ms = MAX_IDLE_X_LOOP_TIMEOUT;
unsigned long mst;
int ela;
int ela_ticks;
debug3( DEBUG_C_TIMERS, CPU_I_TIMER_ST, "T1 (during SHUTDN)", mod_status.hdw.t1_ctrl,
mod_status.hdw.t1_val );
debug3( DEBUG_C_TIMERS, CPU_I_TIMER_ST, "T2 (during SHUTDN)", mod_status.hdw.t2_ctrl,
mod_status.hdw.t2_val );
/* Determine which timer will expire first */
if ( mod_status.hdw.t1_ctrl & ( T1_CTRL_INT | T1_CTRL_WAKE ) ) {
/* T1 will do something on expiration */
mst = ( ( unsigned long )mod_status.hdw.t1_val + 1 ) * T1_MS_MULTIPLIER;
debug2( DEBUG_C_TIMERS, CPU_I_TIMER_EXP, "T1", mst );
if ( mst < ms )
ms = mst;
}
if ( ( mod_status.hdw.t2_ctrl & T2_CTRL_TRUN ) &&
( mod_status.hdw.t2_ctrl & ( T2_CTRL_INT | T2_CTRL_WAKE ) ) ) {
/* T2 is running and will do something on expiration */
mst = ( ( unsigned long )mod_status.hdw.t2_val + 1 ) / T2_MS_DIVISOR;
debug2( DEBUG_C_TIMERS, CPU_I_TIMER_EXP, "T2", mst );
if ( mst < ms )
ms = mst;
}
/* Handle serial port activities at each iteration of
the outer idle loop; this ensures that the serial
port emulation will not starve.
*/
HandleSerial();
/* Enter idle loop, possibly with timeout;
The loop breaks when:
- any X Event occurs (possibly clearing the shutdown)
- the given timeout expires
*/
debug1( DEBUG_C_TIMERS, CPU_I_IDLE_X_LOOP, ms );
// IdleXLoop( ms );
/* End of idle loop; compute actual elapsed time */
gettimeofday( &end_idle, NULL );
ela = ( end_idle.tv_sec - start_idle.tv_sec ) * 1000000 + ( end_idle.tv_usec - start_idle.tv_usec );
/* Update start_idle here to contain lag */
start_idle = end_idle;
debug1( DEBUG_C_TIMERS, CPU_I_ELAPSED, ela );
/* Update timers and act accordingly */
ela_ticks = ( ( ela + frac_t1 ) + T1_INTERVAL / 2 ) / T1_INTERVAL;
frac_t1 = ( ela + frac_t1 ) - ela_ticks * T1_INTERVAL;
if ( ela_ticks > mod_status.hdw.t1_val ) {
debug1( DEBUG_C_TIMERS, CPU_I_TIMER1_EX, mod_status.hdw.t1_ctrl );
mod_status.hdw.t1_ctrl |= T1_CTRL_SREQ;
if ( mod_status.hdw.t1_ctrl & T1_CTRL_WAKE )
CpuWake();
if ( mod_status.hdw.t1_ctrl & T1_CTRL_INT )
CpuIntRequest( INT_REQUEST_IRQ );
}
mod_status.hdw.t1_val = ( mod_status.hdw.t1_val - ela_ticks ) & T1_OVF_MASK;
if ( mod_status.hdw.t2_ctrl & T2_CTRL_TRUN ) {
ela_ticks = ( ( ela + frac_t2 ) + T2_INTERVAL / 2 ) / T2_INTERVAL;
frac_t2 = ( ela + frac_t2 ) - ela_ticks * T2_INTERVAL;
if ( ela_ticks > mod_status.hdw.t2_val ) {
debug1( DEBUG_C_TIMERS, CPU_I_TIMER2_EX, mod_status.hdw.t2_ctrl );
mod_status.hdw.t2_ctrl |= T2_CTRL_SREQ;
if ( mod_status.hdw.t2_ctrl & T2_CTRL_WAKE )
CpuWake();
if ( mod_status.hdw.t2_ctrl & T2_CTRL_INT )
CpuIntRequest( INT_REQUEST_IRQ );
}
mod_status.hdw.t2_val = ( mod_status.hdw.t2_val - ela_ticks ) & T2_OVF_MASK;
}
}
debug3( DEBUG_C_TIMERS, CPU_I_TIMER_ST, "T1 (after SHUTDN)", mod_status.hdw.t1_ctrl, mod_status.hdw.t1_val );
debug3( DEBUG_C_TIMERS, CPU_I_TIMER_ST, "T2 (after SHUTDN)", mod_status.hdw.t2_ctrl, mod_status.hdw.t2_val );
act = CHF_CONTINUE;
}
break;
case CPU_I_EMULATOR_INT:
/* Emulator interrupt; unwind */
act = CHF_UNWIND;
break;
default:
/* Condition Code not handled; resignal */
act = CHF_RESIGNAL;
}
} else
/* Condition from other modules; resignal */
act = CHF_RESIGNAL;
default:
/* Condition Code not handled; resignal */
act = CHF_RESIGNAL;
}
break;
default:
/* Condition from other modules; resignal */
act = CHF_RESIGNAL;
}
break;
default:
/* Other states; resignal the condition */
act = CHF_RESIGNAL;
break;
}
return act;
@ -510,12 +517,12 @@ void Emulator( void )
{
jmp_buf unwind_context;
debug1( CPU_CHF_MODULE_ID, DEBUG_C_TRACE, CPU_I_CALLED, "Emulator" );
debug1( DEBUG_C_TRACE, CPU_I_CALLED, "Emulator" );
/* Setup unwind_context */
if ( setjmp( unwind_context ) == 0 ) {
/* Push condition handler, with NULL context */
ChfPushHandler( CPU_CHF_MODULE_ID, EmulatorLoopHandler, &unwind_context, ( void* )NULL );
ChfPushHandler( EmulatorLoopHandler, &unwind_context, ( ChfPointer )NULL );
/* Activate emulator loop */
EmulatorLoop();
@ -546,7 +553,7 @@ void Emulator( void )
1.1, 18-Feb-1998, creation
.- */
void EmulatorIntRequest( void ) { emulator_int_req = true; }
void EmulatorIntRequest( void ) { emulator_int_req = 1; }
/* .+
@ -581,14 +588,14 @@ void EmulatorIntRequest( void ) { emulator_int_req = true; }
void EmulatorInit( void )
{
/* Select a module description table */
ModSelectDescription( config.model );
ModSelectDescription( args.hw );
/* Initialize cpu and modules subsystems */
CpuInit();
ModInit();
/* Reset if appropriate */
if ( config.reset ) {
if ( args.reset ) {
CpuReset();
ModReset();
}
@ -630,5 +637,4 @@ void EmulatorExit( enum ExitOption opt )
/* Default behavior; do nothing */
break;
}
ChfExit();
}

View file

@ -69,7 +69,14 @@
.- */
#include "libChf/src/Chf.h"
#ifndef lint
static char rcs_id[] = "$Id: flash49.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>
#include "config.h"
#include "machdep.h"
@ -78,6 +85,9 @@
#include "flash49.h"
#include "debug.h"
#define CHF_MODULE_ID FLASH_CHF_MODULE_ID
#include <Chf.h>
/*---------------------------------------------------------------------------
Private Macro/Data type definitions
---------------------------------------------------------------------------*/
@ -131,8 +141,8 @@ static int wb[ WB_SIZE ]; /* Write buffer */
static int BadCommand( enum FlashState* state, enum FlashCycle cycle, XAddress address, int data )
{
/* Unknown command: signal and reset state to FLASH_ST_READ_ARRAY */
ChfGenerate( FLASH_CHF_MODULE_ID, __FILE__, __LINE__, FLASH_W_BAD_CMD, CHF_WARNING, *state, cycle, address, data );
ChfSignal( FLASH_CHF_MODULE_ID );
ChfCondition FLASH_W_BAD_CMD, CHF_WARNING, *state, cycle, address, data ChfEnd;
ChfSignal();
*state = FLASH_ST_READ_ARRAY;
return 0; /* Dummy result */
@ -151,7 +161,7 @@ static int ParseCommand( enum FlashState* state, enum FlashCycle cycle, XAddress
switch ( data ) {
case FLASH_CMD_READ_ARRAY:
/* Transition to FLASH_ST_READ_ARRAY state */
debug1( FLASH_CHF_MODULE_ID, DEBUG_C_FLASH, FLASH_I_FSM_OP, "Read Array" );
debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Read Array" );
*state = FLASH_ST_READ_ARRAY;
break;
@ -160,14 +170,14 @@ static int ParseCommand( enum FlashState* state, enum FlashCycle cycle, XAddress
The current implementation does nothing, because
the value of the status register is fixed. No state transitions.
*/
debug1( FLASH_CHF_MODULE_ID, DEBUG_C_FLASH, FLASH_I_FSM_OP, "Clear Status" );
debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Clear Status" );
break;
case FLASH_CMD_WRITE_BUFFER:
/* Write to Buffer; section 4.8 on Data Sheet.
Transition to FLASH_ST_READ_XSR state.
*/
debug1( FLASH_CHF_MODULE_ID, DEBUG_C_FLASH, FLASH_I_FSM_OP, "Write to Buffer (start)" );
debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Write to Buffer (start)" );
*state = FLASH_ST_READ_XSR;
break;
@ -175,7 +185,7 @@ static int ParseCommand( enum FlashState* state, enum FlashCycle cycle, XAddress
/* Read Status; section 4.4 on Data Sheet.
Transition to FLASH_ST_READ_SR state.
*/
debug1( FLASH_CHF_MODULE_ID, DEBUG_C_FLASH, FLASH_I_FSM_OP, "Read Status" );
debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Read Status" );
*state = FLASH_ST_READ_SR;
break;
@ -184,14 +194,14 @@ static int ParseCommand( enum FlashState* state, enum FlashCycle cycle, XAddress
Transition to FLASH_ST_BL_ERASE state.
Consistency of block addresses is not checked.
*/
debug1( FLASH_CHF_MODULE_ID, DEBUG_C_FLASH, FLASH_I_FSM_OP, "Erase Block (start)" );
debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Erase Block (start)" );
*state = FLASH_ST_BL_ERASE;
break;
default:
/* Unknown command; signal, ignore, keep current state. */
ChfGenerate( FLASH_CHF_MODULE_ID, __FILE__, __LINE__, FLASH_W_BAD_CMD, CHF_WARNING, *state, cycle, address, data );
ChfSignal( FLASH_CHF_MODULE_ID );
ChfCondition FLASH_W_BAD_CMD, CHF_WARNING, *state, cycle, address, data ChfEnd;
ChfSignal();
break;
}
@ -204,7 +214,7 @@ static int ReadXSR( enum FlashState* state, enum FlashCycle cycle, XAddress addr
/* Return XSR status; a buffer is always available in the current
emulation scheme. Keep current state.
*/
debug1( FLASH_CHF_MODULE_ID, DEBUG_C_FLASH, FLASH_I_FSM_OP, "Read XSR" );
debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Read XSR" );
return FLASH_XSR_WBS;
}
@ -214,7 +224,7 @@ static int ReadSR( enum FlashState* state, enum FlashCycle cycle, XAddress addre
/* Return SR status; the WSM executes in zero time in the current
emulation scheme. Keep current state.
*/
debug1( FLASH_CHF_MODULE_ID, DEBUG_C_FLASH, FLASH_I_FSM_OP, "Read SR" );
debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Read SR" );
return FLASH_SR_WSMS;
}
@ -226,7 +236,7 @@ static int ReadSR( enum FlashState* state, enum FlashCycle cycle, XAddress addre
static int StoreCount( enum FlashState* state, enum FlashCycle cycle, XAddress address, int data )
{
/* Store WRITE_BUFFER count; next state is FLASH_ST_WRITE_DATA */
debug1( FLASH_CHF_MODULE_ID, DEBUG_C_FLASH, FLASH_I_FSM_OP, "Write to Buffer (count)" );
debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Write to Buffer (count)" );
wb_count = wb_cdown = data & WB_COUNT_MASK;
*state = FLASH_ST_WRITE_DATA_1;
@ -242,7 +252,7 @@ static int StoreData( enum FlashState* state, enum FlashCycle cycle, XAddress ad
{
int index;
debug1( FLASH_CHF_MODULE_ID, DEBUG_C_FLASH, FLASH_I_FSM_OP, "Write to Buffer (data)" );
debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Write to Buffer (data)" );
/* Store WRITE_BUFFER data; the first write also stores the
buffer starting address.
@ -258,8 +268,8 @@ static int StoreData( enum FlashState* state, enum FlashCycle cycle, XAddress ad
case FLASH_ST_WRITE_DATA_N:
index = address - wb_start;
if ( index < 0 || index >= WB_SIZE ) {
ChfGenerate( FLASH_CHF_MODULE_ID, __FILE__, __LINE__, FLASH_W_BAD_ADDRESS, CHF_WARNING, *state, cycle, address, data );
ChfSignal( FLASH_CHF_MODULE_ID );
ChfCondition FLASH_W_BAD_ADDRESS, CHF_WARNING, *state, cycle, address, data ChfEnd;
ChfSignal();
} else
wb[ index ] = data;
break;
@ -282,7 +292,7 @@ static int StoreData( enum FlashState* state, enum FlashCycle cycle, XAddress ad
*/
static int WriteConfirm( enum FlashState* state, enum FlashCycle cycle, XAddress address, int data )
{
debug1( FLASH_CHF_MODULE_ID, DEBUG_C_FLASH, FLASH_I_FSM_OP, "Write to Buffer (end)" );
debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Write to Buffer (end)" );
/* Expect Write to Buffer confirmation code */
if ( data == FLASH_CMD_WRITE_BUFFER_2 ) {
@ -308,7 +318,7 @@ static int WriteConfirm( enum FlashState* state, enum FlashCycle cycle, XAddress
*/
static int BlockErase( enum FlashState* state, enum FlashCycle cycle, XAddress address, int data )
{
debug1( FLASH_CHF_MODULE_ID, DEBUG_C_FLASH, FLASH_I_FSM_OP, "Block Erase (end)" );
debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Block Erase (end)" );
/* Expect Write to Buffer confirmation code */
if ( data == FLASH_CMD_BL_ERASE_2 ) {
@ -354,12 +364,12 @@ static int FSM( enum FlashCycle cycle, XAddress address, int data )
{
int result;
debug2( FLASH_CHF_MODULE_ID, DEBUG_C_FLASH, FLASH_I_FSM, fsm_state, cycle );
debug2( FLASH_CHF_MODULE_ID, DEBUG_C_FLASH, FLASH_I_FSM_AD, address, data );
debug2( DEBUG_C_FLASH, FLASH_I_FSM, fsm_state, cycle );
debug2( DEBUG_C_FLASH, FLASH_I_FSM_AD, address, data );
result = F[ fsm_state ][ cycle ]( &fsm_state, cycle, address, data );
debug2( FLASH_CHF_MODULE_ID, DEBUG_C_FLASH, FLASH_I_FSM_RESULT, fsm_state, result );
debug2( DEBUG_C_FLASH, FLASH_I_FSM_RESULT, fsm_state, result );
return result;
}
@ -406,7 +416,7 @@ Nibble FlashRead49( XAddress address )
result = LowNibble( r_buffer );
}
debug2( FLASH_CHF_MODULE_ID, DEBUG_C_TRACE | DEBUG_C_FLASH, FLASH_I_READ, address, result );
debug2( DEBUG_C_TRACE | DEBUG_C_FLASH, FLASH_I_READ, address, result );
return result;
}
@ -440,7 +450,7 @@ Nibble FlashRead49( XAddress address )
.- */
void FlashWrite49( XAddress address, Nibble datum )
{
debug2( FLASH_CHF_MODULE_ID, DEBUG_C_TRACE | DEBUG_C_FLASH, FLASH_I_WRITE, address, datum );
debug2( DEBUG_C_TRACE | DEBUG_C_FLASH, FLASH_I_WRITE, address, datum );
if ( IsOdd( address ) )
/* Odd address, invoke FSM; ignore result */

View file

@ -74,7 +74,7 @@
Revision 3.2 2000/09/22 13:46:30 cibrario
Implemented preliminary support of HP49 hw architecture:
- The HP49 firmware (1.19-4) reads a nibble from 0x30 for unknown reasons;
enabled reads from relative
conditionally (#ifdef HP49_SUPPORT) enabled reads from relative
addresses 0x30..0x34 without signaling a warning.
* Revision 3.1 2000/09/20 13:48:52 cibrario
@ -99,9 +99,15 @@
.- */
#include <string.h> /* 3.1: memset() */
#ifndef lint
static char rcs_id[] = "$Id: hdw.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#endif
#include "libChf/src/Chf.h"
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h> /* 3.1: memset() */
#include <errno.h>
#include "config.h"
#include "machdep.h"
@ -112,6 +118,9 @@
#include "x_func.h" /* 3.13: Extended emulator functions */
#include "debug.h"
#define CHF_MODULE_ID MOD_CHF_MODULE_ID
#include <Chf.h>
static const int addr_mask[] = { 0x0000F, 0x000F0, 0x00F00, 0x0F000, 0xF0000 };
static const int32 int32_mask[] = { 0x0000000F, 0x000000F0, 0x00000F00, 0x0000F000, 0x000F0000, 0x00F00000, 0x0F000000, 0xF0000000 };
@ -142,11 +151,11 @@ static const int32 int32_mask[] = { 0x0000000F, 0x000000F0, 0x00000F00, 0x0000F0
.- */
void HdwInit( void )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "HdwInit" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "HdwInit" );
if ( ReadStructFromFile( config.hdw_file_name, sizeof( mod_status.hdw ), &mod_status.hdw ) ) {
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_W_HDW_INIT, CHF_WARNING );
ChfSignal( MOD_CHF_MODULE_ID );
if ( ReadStructFromFile( args.hdw_file_name, sizeof( mod_status.hdw ), &mod_status.hdw ) ) {
ChfCondition MOD_W_HDW_INIT, CHF_WARNING ChfEnd;
ChfSignal();
( void )memset( &mod_status.hdw, 0, sizeof( mod_status.hdw ) );
}
@ -176,11 +185,11 @@ void HdwInit( void )
.- */
void HdwSave( void )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "HdwSave" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "HdwSave" );
if ( WriteStructToFile( &mod_status.hdw, sizeof( mod_status.hdw ), config.hdw_file_name ) ) {
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_E_HDW_SAVE, CHF_ERROR );
ChfSignal( MOD_CHF_MODULE_ID );
if ( WriteStructToFile( &mod_status.hdw, sizeof( mod_status.hdw ), args.hdw_file_name ) ) {
ChfCondition MOD_E_HDW_SAVE, CHF_ERROR ChfEnd;
ChfSignal();
}
}
@ -213,7 +222,7 @@ void HdwSave( void )
.- */
Nibble HdwRead( Address rel_address )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "HdwRead" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "HdwRead" );
/* In the following switch, each case corresponds to one hdw register.
If the register must be read from the shadow space mod_status.hdw.hdw[],
@ -299,6 +308,7 @@ Nibble HdwRead( Address rel_address )
case 0x2F: /* Timer 2 Control */
return mod_status.hdw.t2_ctrl;
#ifdef HP49_SUPPORT
/* 3.2: The HP49 firmware (1.19-4) reads a nibble from 0x30 */
case 0x30:
case 0x31:
@ -306,6 +316,7 @@ Nibble HdwRead( Address rel_address )
case 0x33:
case 0x34:
return ( Nibble )0x0;
#endif
case 0x37: /* Timer 1 value */
return mod_status.hdw.t1_val;
@ -321,8 +332,8 @@ Nibble HdwRead( Address rel_address )
return ( Nibble )( ( mod_status.hdw.t2_val >> ( ( rel_address - 0x38 ) * 4 ) ) & 0x0F );
default:
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_W_HDW_READ, CHF_WARNING, rel_address );
ChfSignal( MOD_CHF_MODULE_ID );
ChfCondition MOD_W_HDW_READ, CHF_WARNING, rel_address ChfEnd;
ChfSignal();
return ( Nibble )0xF;
}
@ -356,7 +367,7 @@ Nibble HdwRead( Address rel_address )
.- */
void HdwWrite( Address rel_address, Nibble data )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "HdwWrite" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "HdwWrite" );
/* This switch has a case for each 'known' hdw register. The code inside the
case performs the actions specific for that register; the code following
@ -528,8 +539,8 @@ void HdwWrite( Address rel_address, Nibble data )
break;
default:
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_W_HDW_WRITE, CHF_WARNING, rel_address, ( int )data );
ChfSignal( MOD_CHF_MODULE_ID );
ChfCondition MOD_W_HDW_WRITE, CHF_WARNING, rel_address, ( int )data ChfEnd;
ChfSignal();
}
/* Save copy into hdw register array */

View file

@ -72,7 +72,14 @@
.- */
#include "libChf/src/Chf.h"
#ifndef lint
static char rcs_id[] = "$Id: hw_config.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>
#include "config.h"
#include "machdep.h"
@ -80,6 +87,9 @@
#include "modules.h"
#include "debug.h"
#define CHF_MODULE_ID MOD_CHF_MODULE_ID
#include <Chf.h>
/*---------------------------------------------------------------------------
Module description tables
---------------------------------------------------------------------------*/
@ -140,23 +150,30 @@ extern void Ce1Write49( Address, Nibble );
extern void Ce2Write49( Address, Nibble );
extern void NCe3Write49( Address, Nibble );
static const ModDescription hw48_description = {
{"ROM (ROM)", 0x00, 0, RomInit, RomSave, RomRead, RomWrite, MOD_CONFIGURED, 0x00000, 0xFFFFF, 0},
{"Hardware Regs. (HDW)", 0x19, 5, HdwInit, HdwSave, HdwRead, HdwWrite, MOD_SIZE_CONFIGURED, 0x00000, 0x00040, 0},
{"Internal RAM (RAM)", 0x03, 4, RamInit, RamSave, RamRead, RamWrite, MOD_UNCONFIGURED, 0, 0, 0},
{"Bank Select (CE1)", 0x05, 2, Ce1Init, Ce1Save, Ce1Read, Ce1Write, MOD_UNCONFIGURED, 0, 0, 0},
{"Port 1 Control (CE2)", 0x07, 3, Ce2Init, Ce2Save, Ce2Read, Ce2Write, MOD_UNCONFIGURED, 0, 0, 0},
{"Port 2 Control (NCE3)", 0x01, 1, NCe3Init, NCe3Save, NCe3Read, NCe3Write, MOD_UNCONFIGURED, 0, 0, 0}
};
static const ModDescription hw49_description = {
{"ROM (ROM)", 0x00, 0, RomInit49, RomSave49, RomRead49, RomWrite49, MOD_CONFIGURED, 0x00000, 0xFFFFF, 0 },
{"Hardware Regs. (HDW)", 0x19, 5, HdwInit, HdwSave, HdwRead, HdwWrite, MOD_SIZE_CONFIGURED, 0x00000, 0x00040, 0 },
{"IRAM (RAM)", 0x03, 4, RamInit49, RamSave49, RamRead49, RamWrite49, MOD_UNCONFIGURED, 0, 0, 0 },
{"Bank Select (CE1)", 0x05, 2, Ce1Init49, Ce1Save49, Ce1Read49, Ce1Write49, MOD_UNCONFIGURED, 0, 0, 0 },
{"ERAM Bank 0 (CE2)", 0x07, 3, Ce2Init49, Ce2Save49, Ce2Read49, Ce2Write49, MOD_UNCONFIGURED, 0, 0, 0 },
{"ERAM Bank 1 (NCE3)", 0x01, 1, NCe3Init49, NCe3Save49, NCe3Read49, NCe3Write49, MOD_UNCONFIGURED, 0, 0, MOD_MAP_FLAGS_ABS}
static const struct {
const char* hw;
ModDescription description;
} table[] = {
{"hp48",
{ { "ROM (ROM)", 0x00, 0, RomInit, RomSave, RomRead, RomWrite, MOD_CONFIGURED, 0x00000, 0xFFFFF, 0 },
{ "Hardware Regs. (HDW)", 0x19, 5, HdwInit, HdwSave, HdwRead, HdwWrite, MOD_SIZE_CONFIGURED, 0x00000, 0x00040, 0 },
{ "Internal RAM (RAM)", 0x03, 4, RamInit, RamSave, RamRead, RamWrite, MOD_UNCONFIGURED, 0, 0, 0 },
{ "Bank Select (CE1)", 0x05, 2, Ce1Init, Ce1Save, Ce1Read, Ce1Write, MOD_UNCONFIGURED, 0, 0, 0 },
{ "Port 1 Control (CE2)", 0x07, 3, Ce2Init, Ce2Save, Ce2Read, Ce2Write, MOD_UNCONFIGURED, 0, 0, 0 },
{ "Port 2 Control (NCE3)", 0x01, 1, NCe3Init, NCe3Save, NCe3Read, NCe3Write, MOD_UNCONFIGURED, 0, 0, 0 } }},
{"hp49",
{ { "ROM (ROM)", 0x00, 0, RomInit49, RomSave49, RomRead49, RomWrite49, MOD_CONFIGURED, 0x00000, 0xFFFFF, 0 },
{ "Hardware Regs. (HDW)", 0x19, 5, HdwInit, HdwSave, HdwRead, HdwWrite, MOD_SIZE_CONFIGURED, 0x00000, 0x00040, 0 },
{ "IRAM (RAM)", 0x03, 4, RamInit49, RamSave49, RamRead49, RamWrite49, MOD_UNCONFIGURED, 0, 0, 0 },
{ "Bank Select (CE1)", 0x05, 2, Ce1Init49, Ce1Save49, Ce1Read49, Ce1Write49, MOD_UNCONFIGURED, 0, 0, 0 },
{ "ERAM Bank 0 (CE2)", 0x07, 3, Ce2Init49, Ce2Save49, Ce2Read49, Ce2Write49, MOD_UNCONFIGURED, 0, 0, 0 },
{ "ERAM Bank 1 (NCE3)", 0x01, 1, NCe3Init49, NCe3Save49, NCe3Read49, NCe3Write49, MOD_UNCONFIGURED, 0, 0,
MOD_MAP_FLAGS_ABS } } }
};
#define N_DESCRIPTIONS ( int )( sizeof( table ) / sizeof( table[ 0 ] ) )
/*---------------------------------------------------------------------------
Public functions
---------------------------------------------------------------------------*/
@ -184,22 +201,18 @@ static const ModDescription hw49_description = {
1.1, 28-Jan-1998, creation
.- */
void ModSelectDescription( int model )
void ModSelectDescription( const char* hw )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "ModSelectDescription" );
int i;
switch ( model ) {
case MODEL_48SX:
case MODEL_48GX:
ModRegisterDescription( hw48_description );
break;
case MODEL_40G:
case MODEL_49G:
ModRegisterDescription( hw49_description );
break;
default:
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_E_NO_MATCH, CHF_ERROR, "Unknown model" );
ChfSignal( MOD_CHF_MODULE_ID );
exit( EXIT_FAILURE );
}
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "ModSelectDescription" );
for ( i = 0; i < N_DESCRIPTIONS && strcmp( hw, table[ i ].hw ); i++ )
;
if ( i == N_DESCRIPTIONS ) {
ChfCondition MOD_E_NO_MATCH, CHF_ERROR, hw ChfEnd;
ChfSignal();
} else
ModRegisterDescription( table[ i ].description );
}

View file

@ -81,16 +81,24 @@
.- */
#include <stdio.h>
#include <string.h>
#ifndef lint
static char rcs_id[] = "$Id: keyb.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#endif
#include "libChf/src/Chf.h"
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>
#include "config.h"
#include "machdep.h"
#include "cpu.h"
#include "modules.h"
#include "keyb.h"
#include "debug.h"
#define CHF_MODULE_ID MOD_CHF_MODULE_ID
#include <Chf.h>
#define OUT_BITS 12
@ -159,11 +167,12 @@ InputRegister KeybIN( OutputRegister out )
{
/* Compute the current value of the IN register */
InputRegister in = ( InputRegister )0;
int bit;
/* For each bit set in the 'out' register, OR the corresponding IN register
value into 'in'
*/
for ( int bit = 0; bit < OUT_BITS; bit++ ) {
for ( bit = 0; bit < OUT_BITS; bit++ ) {
if ( out & 0x01 )
in |= cur_in[ bit ];
out >>= 1;
@ -201,8 +210,10 @@ void KeybPress( const char* key )
{
if ( strcmp( key, "*" ) == 0 ) {
/* This is the ON key */
int i;
/* Set all 0x8000 lines */
for ( int i = 0; i < OUT_BITS; i++ )
for ( i = 0; i < OUT_BITS; i++ )
cur_in[ i ] |= 0x8000;
/* Post an interrupt request to the CPU */
@ -211,11 +222,11 @@ void KeybPress( const char* key )
unsigned int in_val, out_bit;
if ( sscanf( key, "%x/%x", &out_bit, &in_val ) != 2 ) {
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_W_BAD_KEY, CHF_WARNING, key );
ChfSignal( MOD_CHF_MODULE_ID );
ChfCondition MOD_W_BAD_KEY, CHF_WARNING, key ChfEnd;
ChfSignal();
/* } else if ( out_bit < 0 || out_bit >= OUT_BITS ) { */
/* ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_W_BAD_OUT_BIT, CHF_WARNING, out_bit ); */
/* ChfSignal( MOD_CHF_MODULE_ID ); */
/* ChfCondition MOD_W_BAD_OUT_BIT, CHF_WARNING, out_bit ChfEnd; */
/* ChfSignal(); */
} else {
/* Update the cur_in array */
cur_in[ out_bit ] |= in_val;
@ -254,18 +265,20 @@ void KeybRelease( const char* key )
{
if ( strcmp( key, "*" ) == 0 ) {
/* This is the ON key */
int i;
/* Reset all 0x8000 lines */
for ( int i = 0; i < OUT_BITS; i++ )
for ( i = 0; i < OUT_BITS; i++ )
cur_in[ i ] &= 0x7FFF;
} else {
unsigned int in_val, out_bit;
if ( sscanf( key, "%x/%x", &out_bit, &in_val ) != 2 ) {
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_W_BAD_KEY, CHF_WARNING, key );
ChfSignal( MOD_CHF_MODULE_ID );
ChfCondition MOD_W_BAD_KEY, CHF_WARNING, key ChfEnd;
ChfSignal();
/* } else if ( out_bit < 0 || out_bit >= OUT_BITS ) { */
/* ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_W_BAD_OUT_BIT, CHF_WARNING, out_bit ); */
/* ChfSignal( MOD_CHF_MODULE_ID ); */
/* ChfCondition MOD_W_BAD_OUT_BIT, CHF_WARNING, out_bit ChfEnd; */
/* ChfSignal(); */
} else {
/* Update the cur_in array */
cur_in[ out_bit ] &= ~in_val;

View file

@ -1,171 +0,0 @@
#ifndef _CHF_H
#define _CHF_H 1
/* .+
.identifier : $Id: Chf.h,v 2.2 2001/01/25 11:56:44 cibrario Exp $
.context : CHF, Condition Handling Facility
.title : $RCSfile: Chf.h,v $, main header
.kind : C header
.author : Ivan Cibrario B.
.site : CSTV-CNR
.creation : 2-May-1996
.keywords : *
.description :
This is the main header of the Condition Handling Facility
.include : stdio.h setjmp.h (Win32: tchar.h)
.notes :
$Log: Chf.h,v $
Revision 2.2 2001/01/25 11:56:44 cibrario
Added partial Win32 support (Windows CE only).
Revision 2.1 2000/05/26 14:10:08 cibrario
- Revised unwind context passing mechanism; redefined CHF_NULL_CONTEXT
- New macros: CHF_NULL_HANDLER, CHF_MAJOR_RELEASE_NUMBER,
CHF_MINOR_RELEASE_NUMBER
- New ChfAction value: CHF_UNWIND_KEEP; fixed spelling of ChfAction value:
CHF_SIGNALLING -> CHF_SIGNALING
- Added structured condition handling macros: CHF_Try, CHF_Catch, CHF_EndTry
Revision 1.6 1997/01/15 13:41:20 cibrario
Defined the new data type void*, a generic (void *) pointer. Each
condition handler can have a private handler context pointer, of type
void*, that the function ChfPushHandler() stores and that is passed
to the handler when it's activated.
Fixed a wrong adjustment of the condition handlers stack pointer after
an unwind operation.
Revision 1.5 1996/10/04 09:45:30 cibrario
Updated the condition message format in the private header ChfPriv.h to
improve internationalization
Revision 1.4 1996/09/25 13:21:11 cibrario
Added macro CHF_LIBRARY_ID; it contains the current ID of the CHF library.
The module chf_init.o will contain it as a static char[] variable.
Revision 1.2 1996/06/11 13:02:10 cibrario
Added prototype for ChfGetTopCondition()
Revision 1.1 1996/05/28 12:56:47 cibrario
Initial revision
.- */
#include <stdlib.h>
#include <errno.h>
/* -------------------------------------------------------------------------
CHF implementation limits and other symbolic constants
------------------------------------------------------------------------- */
#define CHF_MAX_MESSAGE_LENGTH 256
#define CHF_UNKNOWN_LINE_NUMBER ( -1 )
#define CHF_UNKNOWN_FILE_NAME ( char* )NULL
#define CHF_NULL_DESCRIPTOR ( ChfDescriptor* )NULL
#define CHF_NULL_CONTEXT ( void* )NULL
#define CHF_NULL_POINTER ( void** )NULL
#define CHF_NULL_HANDLER ( ChfHandler ) NULL
#define CHF_MODULE_NAMES_SET 1
#define CHF_SET 2
#define CHF_ERRNO_SET 3
/* -------------------------------------------------------------------------
Condition codes
------------------------------------------------------------------------- */
#define CHF_S_OK 0
#define CHF_F_COND_STACK_FULL 1 /* Condition stack is full */
#define CHF_F_HDLR_STACK_FULL 2 /* Handler stack is full */
#define CHF_F_HDLR_STACK_EMPTY 3 /* Handler stack is empty */
#define CHF_F_BAD_STATE 4 /* Bad CHF state for req. operation */
#define CHF_F_INVALID_ACTION 5 /* Invalid action from handler: %d */
#define CHF_F_MALLOC 6 /* Dynamic memory allocation failed */
#define CHF_F_NOT_AVAILABLE 7 /* Function not available */
#define CHF_F_SETLOCALE 10 /* setlocale() failed */
#define CHF_F_CATOPEN 11 /* catopen() failed */
/* -------------------------------------------------------------------------
Type definitions
------------------------------------------------------------------------- */
/* Condition severity codes */
typedef enum { CHF_SUCCESS, CHF_INFO, CHF_WARNING, CHF_ERROR, CHF_FATAL } ChfSeverity;
/* Condition handler action codes */
typedef enum {
CHF_CONTINUE, /* Continue application */
CHF_RESIGNAL, /* Resignal to next handler */
CHF_UNWIND, /* Stack unwind */
CHF_UNWIND_KEEP /* Unwind, keep last cond. group */
} ChfAction;
#define CHF_DEFAULT 0x0000 /* default flags */
#define CHF_ABORT 0x0001 /* use abort() instead of exit() */
/* Current CHF state */
typedef enum { CHF_UNKNOWN, CHF_IDLE, CHF_SIGNALING, CHF_UNWINDING, CHF_SIGNAL_UNWINDING } ChfState;
/* Condition descriptor */
typedef struct ChfDescriptor_S {
int module_id; /* Module identifier */
int condition_code; /* Condition code */
ChfSeverity severity; /* Severity */
int line_number; /* Line # or CHF_UNK_LINE_NUMBER */
const char* file_name; /* File name or CHF_UNK_FILE_NAME */
char message[ CHF_MAX_MESSAGE_LENGTH ]; /* Partial message */
struct ChfDescriptor_S* next; /* Link to next descriptor */
} ChfDescriptor;
/* Standalone message table */
typedef struct ChfTable_S {
int module; /* Module identifier */
int code; /* Condition code */
const char* msg_template; /* Message template */
} ChfTable;
/* Condition handler */
typedef ChfAction ( *ChfHandler )( const ChfDescriptor*, const ChfState, void* );
/* Message retrieval 'get_message' function */
typedef const char* ( *ChfMrsGet )( void*, const int, const int, const char* default_message );
/* Message retrieval 'exit' function */
typedef void ( *ChfMrsExit )( void* );
/* -------------------------------------------------------------------------
Function prototypes
------------------------------------------------------------------------- */
/* Generate a condition into the stack */
void ChfGenerate( const int module_id, const char* file_name, const int line_number, const int condition_code, const ChfSeverity severity,
... );
/******************/
/* used in saturn */
/******************/
/* Initialization with static message tables */
int ChfStaticInit( const int module_id, const char* app_name, /* Application's name */
const int options, /* Options */
const ChfTable* table, /* Static message table */
const size_t table_size, /* Size of the message table */
const int condition_stack_size, /* Size of the condition stack */
const int handler_stack_size, /* Size of the handler stack */
const int exit_code /* Abnormal exit code */
);
/* Push a new handler into the stack */
void ChfPushHandler( const int module_id, ChfHandler new_handler, /* Handler to be added */
void* unwind_context, /* Unwind context */
void* handler_context /* Private handler context */
);
/* Signal the current conditions */
void ChfSignal( const int module_id );
/* Exit */
void ChfExit( void );
#endif /*!_CHF_H*/

View file

@ -1,61 +0,0 @@
/* .+
.identifier : $Id: chf_msgc.c,v 2.2 2001/01/25 14:06:47 cibrario Exp $
.context : CHF, Condition Handling Facility
.title : $RCSfile: chf_msgc.c,v $, condition generation
.kind : C source
.author : Ivan Cibrario B.
.site : CSTV-CNR
.creation : 17-May-1996
.keywords : *
.description :
This module contains the CHF initialization function ChfMsgcatInit()
.include : Chf.h
.notes :
$Log: chf_msgc.c,v $
Revision 2.2 2001/01/25 14:06:47 cibrario
Added partial Win32 support (Windows CE only).
Revision 1.3 1996/06/21 14:19:22 cibrario
Bug fix: the private context of the message retrieval facility was
never freed by ExitMessage()
Revision 1.1 1996/05/28 12:55:15 cibrario
Initial revision
.- */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <nl_types.h>
#include "Chf.h"
#include "ChfPriv.h"
/* -------------------------------------------------------------------------
Private type definitions
------------------------------------------------------------------------- */
typedef struct {
nl_catd catalog; /* Message catalog descriptor */
} ChfMsgcatContext;
/* -------------------------------------------------------------------------
Private functions
------------------------------------------------------------------------- */
static const char* GetMessage( void* private_context, const int module_id, const int condition_code, const char* default_message )
{
return ( catgets( ( ( ChfMsgcatContext* )private_context )->catalog, module_id, condition_code, default_message ) );
}
static void ExitMessage( void* private_context )
{
( void )catclose( ( ( ChfMsgcatContext* )private_context )->catalog );
free( private_context );
}

View file

@ -1,117 +0,0 @@
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include "ui4x/config.h"
#include "ui4x/emulator.h"
#include "ui4x/common.h"
#include "config.h"
#include "cpu.h"
#include "monitor.h"
#include "chf_messages.h"
#define UI_REFRESH_RATE_Hz 64
#define CONDITION_STACK_SIZE 16
#define HANDLER_STACK_SIZE 8
#define QUERY_EVENTS_EVERY_X_FRAME 4
void signal_handler( int sig )
{
static int nb_refreshes_since_last_checking_events = 0;
switch ( sig ) {
/* case SIGINT: /\* Ctrl-C *\/ */
/* enter_debugger |= USER_INTERRUPT; */
/* break; */
case SIGALRM:
if ( nb_refreshes_since_last_checking_events > QUERY_EVENTS_EVERY_X_FRAME ) {
nb_refreshes_since_last_checking_events = 0;
ui_get_event();
}
ui_update_display();
nb_refreshes_since_last_checking_events++;
break;
case SIGPIPE:
ui_stop();
exit_emulator();
exit( EXIT_SUCCESS );
default:
break;
}
}
int main( int argc, char** argv )
{
config = *config_init( argc, argv );
/* Chf initialization with msgcat subsystem
*/
if ( ( ChfStaticInit( MAIN_CHF_MODULE_ID, config.progname, /* Application's name */
CHF_DEFAULT, /* Options */
message_table, /* Name of the message catalog */
message_table_size, /* message catalog size */
CONDITION_STACK_SIZE, /* Size of the condition stack */
HANDLER_STACK_SIZE, /* Size of the handler stack */
EXIT_FAILURE /* Abnormal exit code */
) ) != CHF_S_OK ) {
fprintf( stderr, "saturn-E-Primary Chf initialization failed\n" );
exit( EXIT_FAILURE );
}
/* 3.9: Print out MAIN_M_COPYRIGHT and MAIN_M_LICENSE on stdout now */
fprintf( stdout,
"%s %i.%i.%i - A poor-man's emulator of HP48GX/SX, HP49, HP39/40\nCopyright (C) 1998-2000 Ivan Cibrario "
"Bertolotti\nCopyright (C) Gwenhael Le Moine\n",
config.progname, VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL );
fprintf( stdout,
"This program is free software, and comes with ABSOLUTELY NO WARRANTY;\nfor details see the accompanying documentation.\n\n" );
init_emulator( &config );
/* (G)UI */
setup_ui( &config );
ui_start( &config );
sigset_t set;
struct sigaction sa;
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 );
/************************************/
/* set the real time interval timer */
/************************************/
/*
Every <interval>µs setitimer will trigger a SIGALRM
which will getUI events and refresh UI in signal_handler
*/
struct itimerval it;
it.it_interval.tv_sec = 0;
it.it_interval.tv_usec = 1000000 / UI_REFRESH_RATE_Hz;
it.it_value.tv_sec = it.it_interval.tv_sec;
it.it_value.tv_usec = it.it_interval.tv_usec;
setitimer( ITIMER_REAL, &it, ( struct itimerval* )0 );
if ( config.monitor )
/* Invoke Monitor */
Monitor();
else
/* Call Emulator directly */
Emulator();
/* never reached */
return EXIT_SUCCESS;
}

View file

@ -94,7 +94,7 @@
* description table dynamically.
* - ModInit() now refuses to work if no module description table has
* been registered yet.
* - enabled forced alignment of
* - Conditionally (#ifdef HP49_SUPPORT) enabled forced alignment of
* module configuration sizes and addresses in ModConfig()
*
* Revision 3.1 2000/09/20 14:00:02 cibrario
@ -110,11 +110,15 @@
.- */
#ifndef lint
static char rcs_id[] = "$Id: modules.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libChf/src/Chf.h"
#include <errno.h>
#include <setjmp.h>
#include "config.h"
#include "machdep.h"
@ -123,6 +127,9 @@
#include "disk_io.h"
#include "debug.h"
#define CHF_MODULE_ID MOD_CHF_MODULE_ID
#include <Chf.h>
/*---------------------------------------------------------------------------
Static/Global variables
---------------------------------------------------------------------------*/
@ -136,7 +143,7 @@ struct ModStatus mod_status; /* Status information - global */
points to it.
*/
static struct ModMap* mod_map_ptr; /* Module mapping information */
#define MOD_MAP ( *mod_map_ptr )
#define mod_map ( *mod_map_ptr )
/* 2.7: All dynamically-allocated module mapping structures are linked
together; cache_head points to the head of the list. The list
@ -165,7 +172,7 @@ static int repl_c = 0; /* Entry replacement counter */
# define IncPerfCtr( x ) x++
# define DecPerfCtr( x ) x--
# define PrintPerfCtr( x ) debug2( MOD_CHF_MODULE_ID, DEBUG_C_MOD_CACHE, MOD_I_PERF_CTR, #x, x )
# define PrintPerfCtr( x ) debug2( DEBUG_C_MOD_CACHE, MOD_I_PERF_CTR, #x, x )
# define PrintCacheStats \
{ \
@ -218,8 +225,8 @@ static int repl_c = 0; /* Entry replacement counter */
.- */
static Nibble BadRead( Address addr )
{
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_E_BAD_READ, CHF_ERROR, addr );
ChfSignal( MOD_CHF_MODULE_ID );
ChfCondition MOD_E_BAD_READ, CHF_ERROR, addr ChfEnd;
ChfSignal();
return ( Nibble )0x0;
}
@ -250,8 +257,8 @@ static Nibble BadRead( Address addr )
.- */
static void BadWrite( Address addr, Nibble datum )
{
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_E_BAD_WRITE, CHF_ERROR, addr, datum );
ChfSignal( MOD_CHF_MODULE_ID );
ChfCondition MOD_E_BAD_WRITE, CHF_ERROR, addr, datum ChfEnd;
ChfSignal();
}
/* .+
@ -262,7 +269,7 @@ static void BadWrite( Address addr, Nibble datum )
.description :
This function rebuilds the module page table from page 'lo' to page 'hi',
inclusive, using the information contained in the current module
mapping structure (MOD_MAP.map_info).
mapping structure (mod_map.map_info).
.call :
RebuildPageTable(lo, hi);
@ -286,14 +293,17 @@ static void BadWrite( Address addr, Nibble datum )
.- */
static void RebuildPageTable( int lo, int hi )
{
int page;
int mod;
Address page_addr;
int prio;
int winner = -1;
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "RebuildPageTable" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RebuildPageTable" );
/* Scan all pages in the [lo, hi] range */
for ( int page = lo; page <= hi; page++ ) {
for ( page = lo; page <= hi; page++ ) {
/* Calculate the base page address for the current page */
page_addr = ModAddress( page );
@ -304,9 +314,9 @@ static void RebuildPageTable( int lo, int hi )
to MOD_MIN_ACCESS_PRIO.
*/
prio = MOD_MIN_ACCESS_PRIO;
for ( int mod = 0; mod < N_MOD; mod++ ) {
if ( MOD_MAP.map_info[ mod ].config == MOD_CONFIGURED && page_addr >= MOD_MAP.map_info[ mod ].abs_base_addr &&
page_addr < MOD_MAP.map_info[ mod ].abs_base_addr + MOD_MAP.map_info[ mod ].size &&
for ( mod = 0; mod < N_MOD; mod++ ) {
if ( mod_map.map_info[ mod ].config == MOD_CONFIGURED && page_addr >= mod_map.map_info[ mod ].abs_base_addr &&
page_addr < mod_map.map_info[ mod ].abs_base_addr + mod_map.map_info[ mod ].size &&
prio < mod_description[ mod ].access_prio ) {
winner = mod;
prio = mod_description[ mod ].access_prio;
@ -319,10 +329,10 @@ static void RebuildPageTable( int lo, int hi )
read/write functions to BadRead/BadWrite, to catch accesses to
unmapped addresses.
*/
MOD_MAP.page_table[ page ].index = MOD_NO_MOD_INDEX;
MOD_MAP.page_table[ page ].rel_base_addr = 0x00000;
MOD_MAP.page_table[ page ].read = BadRead;
MOD_MAP.page_table[ page ].write = BadWrite;
mod_map.page_table[ page ].index = MOD_NO_MOD_INDEX;
mod_map.page_table[ page ].rel_base_addr = 0x00000;
mod_map.page_table[ page ].read = BadRead;
mod_map.page_table[ page ].write = BadWrite;
} else {
/* The page is mapped
3.3: If the MOD_MAP_FLAGS_ABS is set in the winner's module
@ -330,13 +340,12 @@ static void RebuildPageTable( int lo, int hi )
absolute address; this way, the module read/write functions
will receive absolute addresses instead of relative ones.
*/
MOD_MAP.page_table[ page ].index = winner;
MOD_MAP.page_table[ page ].rel_base_addr = ( mod_description[ winner ].map_flags & MOD_MAP_FLAGS_ABS )
mod_map.page_table[ page ].index = winner;
mod_map.page_table[ page ].rel_base_addr = ( mod_description[ winner ].map_flags & MOD_MAP_FLAGS_ABS )
? page_addr
: page_addr - MOD_MAP.map_info[ winner ].abs_base_addr;
MOD_MAP.page_table[ page ].read = mod_description[ winner ].read;
// FIXME: 48gx VERSION bug: This is the place where the RomWrite fonction is set. Should we avoid ROM being able to win?
MOD_MAP.page_table[ page ].write = mod_description[ winner ].write;
: page_addr - mod_map.map_info[ winner ].abs_base_addr;
mod_map.page_table[ page ].read = mod_description[ winner ].read;
mod_map.page_table[ page ].write = mod_description[ winner ].write;
}
}
}
@ -369,7 +378,7 @@ static struct ModMap* ClearCachingInfo( struct ModMap* d )
int i;
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "ClearCachingInfo" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "ClearCachingInfo" );
for ( i = 0; i < N_MOD_CACHE_ENTRIES; i++ )
d->cache.config[ i ] = empty;
@ -417,12 +426,12 @@ static struct ModMap* NewModMap( void )
{
struct ModMap* new;
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "NewModMap" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "NewModMap" );
if ( ( new = ( struct ModMap* )malloc( sizeof( struct ModMap ) ) ) == ( struct ModMap* )NULL ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_F_MAP_ALLOC, CHF_FATAL );
ChfSignal( MOD_CHF_MODULE_ID );
ChfErrnoCondition;
ChfCondition MOD_F_MAP_ALLOC, CHF_FATAL ChfEnd;
ChfSignal();
}
/* Link new structure to the cache list */
@ -464,7 +473,7 @@ static struct ModMap* CopyModMap( struct ModMap* d, const struct ModMap* s )
{
struct ModMap* link = d->cache.link; /* Save .link of dest. */
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "CopyModMap" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "CopyModMap" );
*d = *s;
d->cache.link = link; /* Restore .link */
@ -507,7 +516,7 @@ static struct ModMap* CopyModMap( struct ModMap* d, const struct ModMap* s )
.- */
static void ReplaceModMap( struct ModMap** d, const struct ModMap* s )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "ReplaceModMap" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "ReplaceModMap" );
if ( *d == ( struct ModMap* )NULL )
/* Allocation needed; cache cleared after allocation */
@ -546,7 +555,7 @@ static void FlushCache( struct ModMap* save )
{
struct ModMap *p, *n;
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "FlushCache" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "FlushCache" );
/* Scan the cache list; free all elements except that pointed by 'save' */
p = cache_head;
@ -574,8 +583,8 @@ static void FlushCache( struct ModMap* save )
#ifdef DEBUG
/* The alloc_c performance counter must be exactly 1 now */
if ( alloc_c != 1 ) {
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_F_BAD_ALLOC_C, CHF_ERROR, alloc_c );
ChfSignal( MOD_CHF_MODULE_ID );
ChfCondition MOD_F_BAD_ALLOC_C, CHF_ERROR, alloc_c ChfEnd;
ChfSignal();
}
#endif
}
@ -607,11 +616,11 @@ static struct ModMap* AccessConfigCache( Address tag )
{
int i;
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "AccessConfigCache" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "AccessConfigCache" );
for ( i = 0; i < N_MOD_CACHE_ENTRIES; i++ )
if ( MOD_MAP.cache.config[ i ].tag == tag )
return MOD_MAP.cache.config[ i ].map_ptr;
if ( mod_map.cache.config[ i ].tag == tag )
return mod_map.cache.config[ i ].map_ptr;
return ( struct ModMap* )NULL;
}
@ -645,9 +654,9 @@ static struct ModMap* AccessUnconfigCache( int i )
{
struct ModMap* p;
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "AccessUnconfigCache" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "AccessUnconfigCache" );
p = MOD_MAP.cache.unconfig[ i ];
p = mod_map.cache.unconfig[ i ];
while ( p != ( struct ModMap* )NULL && !p->cache.config_point )
p = p->cache.unconfig[ i ];
@ -691,10 +700,10 @@ static struct ModMap* AccessUnconfigCache( int i )
.- */
struct ModCacheTableEntry* SelectConfigVictim( int retry )
{
int v = MOD_MAP.cache.victim;
int v = mod_map.cache.victim;
struct ModCacheTableEntry* victim = ( struct ModCacheTableEntry* )NULL;
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "AccessUnconfigCache" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "AccessUnconfigCache" );
/* Scan the config cache entries, starting at .cache.victim,
until a suitable one is found or the index loops around
@ -704,29 +713,29 @@ struct ModCacheTableEntry* SelectConfigVictim( int retry )
- it is empty (map_ptr == NULL)
- or the reference count of the associated map is 0
*/
if ( ( MOD_MAP.cache.config[ v ].map_ptr == ( struct ModMap* )NULL ) || MOD_MAP.cache.config[ v ].map_ptr->cache.ref_count == 0 )
victim = &( MOD_MAP.cache.config[ v ] );
if ( ( mod_map.cache.config[ v ].map_ptr == ( struct ModMap* )NULL ) || mod_map.cache.config[ v ].map_ptr->cache.ref_count == 0 )
victim = &( mod_map.cache.config[ v ] );
v = ( v + 1 ) % N_MOD_CACHE_ENTRIES;
} while ( victim == ( struct ModCacheTableEntry* )NULL && v != MOD_MAP.cache.victim );
} while ( victim == ( struct ModCacheTableEntry* )NULL && v != mod_map.cache.victim );
if ( victim == ( struct ModCacheTableEntry* )NULL ) {
if ( retry ) {
/* Unable to find a victim; flush the cache and retry */
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_W_NO_VICTIM, CHF_WARNING );
ChfSignal( MOD_CHF_MODULE_ID );
ChfCondition MOD_W_NO_VICTIM, CHF_WARNING ChfEnd;
ChfSignal();
FlushCache( mod_map_ptr );
victim = SelectConfigVictim( 0 );
} else {
/* Unable to find a victim; retry is not an option; give up */
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_F_NO_VICTIM, CHF_FATAL );
ChfSignal( MOD_CHF_MODULE_ID );
ChfCondition MOD_F_NO_VICTIM, CHF_FATAL ChfEnd;
ChfSignal();
}
} else
/* Found a victim; update next-victim index */
MOD_MAP.cache.victim = v;
mod_map.cache.victim = v;
return victim;
}
@ -764,7 +773,7 @@ static struct ModMap* CheckForLateHit( void )
struct ModMap* p;
int i;
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "AccessUnconfigCache" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "AccessUnconfigCache" );
p = cache_head;
@ -824,7 +833,7 @@ static void FreeModMap( struct ModMap* p )
{
struct ModMap* n;
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "FreeModMap" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "FreeModMap" );
/* Free the struct ModMap pointed by p, preserving the linkage of
other entries. The caller must ensure that the entry is not
@ -845,8 +854,8 @@ static void FreeModMap( struct ModMap* p )
/* Should never happen */
if ( n == ( struct ModMap* )NULL ) {
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_F_CHAIN_CORRUPTED, CHF_FATAL );
ChfSignal( MOD_CHF_MODULE_ID );
ChfCondition MOD_F_CHAIN_CORRUPTED, CHF_FATAL ChfEnd;
ChfSignal();
}
/* Bypass element pointed by p and free it */
@ -891,7 +900,7 @@ static void FreeModMap( struct ModMap* p )
.- */
void ModRegisterDescription( ModDescription p )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "ModRegisterDescription" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "ModRegisterDescription" );
mod_description = p;
}
@ -939,40 +948,42 @@ void ModInit( void )
{
int mod;
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "ModInit" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "ModInit" );
debug1( DEBUG_C_REVISION, MOD_I_REVISION, MOD_RCS_INFO );
/* First, a little sanity check on mod_description: ensure that
ModRegisterDescription() has been called at least once with a
non-NULL argument.
*/
if ( mod_description == NULL ) {
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_F_NO_DESCRIPTION, CHF_FATAL );
ChfSignal( MOD_CHF_MODULE_ID );
ChfCondition MOD_F_NO_DESCRIPTION, CHF_FATAL ChfEnd;
ChfSignal();
}
/* Scan the mod_description table, initializing all modules */
for ( mod = 0; mod < N_MOD; mod++ ) {
debug1( MOD_CHF_MODULE_ID, DEBUG_C_MODULES, MOD_I_INITIALIZING, mod_description[ mod ].name );
debug1( DEBUG_C_MODULES, MOD_I_INITIALIZING, mod_description[ mod ].name );
mod_description[ mod ].init();
}
/* Allocate the root struct ModMap and set it as the current one;
the structure can be accessed using either mod_map_ptr or MOD_MAP.
the structure can be accessed using either mod_map_ptr or mod_map.
*/
mod_map_ptr = ClearCachingInfo( NewModMap() );
/* Attempt to restore the mod_map from file; reset modules if the read
fails.
*/
if ( ReadStructFromFile( config.mod_file_name, sizeof( MOD_MAP.map_info ), &MOD_MAP.map_info ) ) {
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_W_RESETTING_ALL, CHF_WARNING );
ChfSignal( MOD_CHF_MODULE_ID );
if ( ReadStructFromFile( args.mod_file_name, sizeof( mod_map.map_info ), &mod_map.map_info ) ) {
ChfCondition MOD_W_RESETTING_ALL, CHF_WARNING ChfEnd;
ChfSignal();
/* Reset all modules */
ModReset();
} else
} else {
/* Rebuild page table (not saved on disk) */
RebuildPageTable( 0, N_PAGE_TABLE_ENTRIES - 1 );
}
}
/* .+
@ -1009,18 +1020,18 @@ void ModSave( void )
{
int mod;
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "ModSave" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "ModSave" );
/* Scan the mod_description table, initializing all modules */
for ( mod = 0; mod < N_MOD; mod++ ) {
debug1( MOD_CHF_MODULE_ID, DEBUG_C_MODULES, MOD_I_SAVING, mod_description[ mod ].name );
debug1( DEBUG_C_MODULES, MOD_I_SAVING, mod_description[ mod ].name );
mod_description[ mod ].save();
}
/* Attempt to save the mod_map from file */
if ( WriteStructToFile( &MOD_MAP.map_info, sizeof( MOD_MAP.map_info ), config.mod_file_name ) ) {
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_F_MAP_SAVE, CHF_FATAL );
ChfSignal( MOD_CHF_MODULE_ID );
if ( WriteStructToFile( &mod_map.map_info, sizeof( mod_map.map_info ), args.mod_file_name ) ) {
ChfCondition MOD_F_MAP_SAVE, CHF_FATAL ChfEnd;
ChfSignal();
}
}
@ -1065,12 +1076,12 @@ Address ModGetID( void )
int mod;
Address id;
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "ModGetID" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "ModGetID" );
/* Scan the module information table searching for either an unconfigured
or a partially configured module
*/
for ( mod = 0; mod < N_MOD && MOD_MAP.map_info[ mod ].config == MOD_CONFIGURED; mod++ )
for ( mod = 0; mod < N_MOD && mod_map.map_info[ mod ].config == MOD_CONFIGURED; mod++ )
;
if ( mod == N_MOD )
@ -1078,11 +1089,11 @@ Address ModGetID( void )
id = ( Address )0x00000;
else
/* Build the module id */
id = ( MOD_MAP.map_info[ mod ].abs_base_addr & 0xFFF00 ) |
( MOD_MAP.map_info[ mod ].config == MOD_UNCONFIGURED ? 0x00000 : 0x000F0 ) |
( mod_description[ mod ].id + ( MOD_MAP.map_info[ mod ].config == MOD_UNCONFIGURED ? 0 : 1 ) );
id = ( mod_map.map_info[ mod ].abs_base_addr & 0xFFF00 ) |
( mod_map.map_info[ mod ].config == MOD_UNCONFIGURED ? 0x00000 : 0x000F0 ) |
( mod_description[ mod ].id + ( mod_map.map_info[ mod ].config == MOD_UNCONFIGURED ? 0 : 1 ) );
debug1( MOD_CHF_MODULE_ID, DEBUG_C_MODULES, MOD_I_GET_ID, id );
debug1( DEBUG_C_MODULES, MOD_I_GET_ID, id );
return id;
}
@ -1115,18 +1126,18 @@ void ModReset( void )
{
int mod;
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "ModReset" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "ModReset" );
/* Scan the mod_description table, initializing the module
mapping information MOD_MAP.map_info.
mapping information mod_map.map_info.
*/
for ( mod = 0; mod < N_MOD; mod++ ) {
debug1( MOD_CHF_MODULE_ID, DEBUG_C_MODULES, MOD_I_RESETTING, mod_description[ mod ].name );
debug1( DEBUG_C_MODULES, MOD_I_RESETTING, mod_description[ mod ].name );
/* Set the module configuration status */
MOD_MAP.map_info[ mod ].config = mod_description[ mod ].r_config;
MOD_MAP.map_info[ mod ].abs_base_addr = mod_description[ mod ].r_abs_base_addr;
MOD_MAP.map_info[ mod ].size = mod_description[ mod ].r_size;
mod_map.map_info[ mod ].config = mod_description[ mod ].r_config;
mod_map.map_info[ mod ].abs_base_addr = mod_description[ mod ].r_abs_base_addr;
mod_map.map_info[ mod ].size = mod_description[ mod ].r_size;
}
/* Rebuild the module page table */
@ -1139,7 +1150,7 @@ void ModReset( void )
this flag is used by the unconfig cache code to correctly
undo the last config
*/
MOD_MAP.cache.config_point = 1;
mod_map.cache.config_point = 1;
}
/* .+
@ -1151,7 +1162,7 @@ void ModReset( void )
This function configures a module, using the given 'config_info'.
The target module will be the first unconfigured or partially configured
module found in the MOD_MAP.map_info table.
module found in the mod_map.map_info table.
If the target module is unconfigured, ModConfig sets the size of its
address space to 0x100000 - 'config_info'; the module then becomes
@ -1183,7 +1194,7 @@ void ModReset( void )
2.7, 15-Sep-2000, update
- implemented module config/unconfig cache
3.2, 22-Sep-2000, update
- enabled forced alignment
- conditionally (#ifdef HP49_SUPPORT) enabled forced alignment
of config_info
.- */
void ModConfig( Address config_info )
@ -1193,13 +1204,15 @@ void ModConfig( Address config_info )
int mod;
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "ModConfig" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "ModConfig" );
#ifdef HP49_SUPPORT
/* 3.2: The HP49 firmware (1.19-4) can generate misaligned config
addresses, that is, addresses that are not a multiple of 0x100;
silently align them here.
*/
config_info &= ~0xFF;
#endif
/* ACCESS CONFIG CACHE */
if ( ( nxt = AccessConfigCache( config_info ) ) != ( struct ModMap* )NULL ) {
@ -1208,7 +1221,7 @@ void ModConfig( Address config_info )
IncPerfCtr( hit_c );
debug1( MOD_CHF_MODULE_ID, DEBUG_C_MOD_CACHE, MOD_I_CACHED_CONFIG, config_info );
debug1( DEBUG_C_MOD_CACHE, MOD_I_CACHED_CONFIG, config_info );
return;
}
@ -1240,43 +1253,42 @@ void ModConfig( Address config_info )
/* Scan the module information table searching for either an unconfigured
or a partially configured module
*/
for ( mod = 0; mod < N_MOD && MOD_MAP.map_info[ mod ].config == MOD_CONFIGURED; mod++ )
for ( mod = 0; mod < N_MOD && mod_map.map_info[ mod ].config == MOD_CONFIGURED; mod++ )
;
if ( mod == N_MOD ) {
/* All modules are configured - Signal a warning */
// FIXME: 48gx bugs here when running VERSION
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_W_BAD_CONFIG, CHF_WARNING, config_info );
ChfSignal( MOD_CHF_MODULE_ID );
ChfCondition MOD_W_BAD_CONFIG, CHF_WARNING, config_info ChfEnd;
ChfSignal();
} else {
if ( MOD_MAP.map_info[ mod ].config == MOD_UNCONFIGURED ) {
if ( mod_map.map_info[ mod ].config == MOD_UNCONFIGURED ) {
/* The module was unconfigured; configure its size */
MOD_MAP.map_info[ mod ].size = 0x100000 - config_info;
MOD_MAP.map_info[ mod ].config = MOD_SIZE_CONFIGURED;
mod_map.map_info[ mod ].size = 0x100000 - config_info;
mod_map.map_info[ mod ].config = MOD_SIZE_CONFIGURED;
} else {
/* The module size was already configured; configure its base address */
MOD_MAP.map_info[ mod ].abs_base_addr = config_info;
MOD_MAP.map_info[ mod ].config = MOD_CONFIGURED;
mod_map.map_info[ mod ].abs_base_addr = config_info;
mod_map.map_info[ mod ].config = MOD_CONFIGURED;
/* Rebuild the page table */
RebuildPageTable( ModPage( MOD_MAP.map_info[ mod ].abs_base_addr ),
ModPage( MOD_MAP.map_info[ mod ].abs_base_addr + MOD_MAP.map_info[ mod ].size - 1 ) );
RebuildPageTable( ModPage( mod_map.map_info[ mod ].abs_base_addr ),
ModPage( mod_map.map_info[ mod ].abs_base_addr + mod_map.map_info[ mod ].size - 1 ) );
/* Mark the current struct ModMap to be a configuration point;
this flag is used by the unconfig cache code to correctly
undo the last config
*/
MOD_MAP.cache.config_point = 1;
mod_map.cache.config_point = 1;
debug3( MOD_CHF_MODULE_ID, DEBUG_C_MODULES | DEBUG_C_MOD_CACHE, MOD_I_CONFIG, mod_description[ mod ].name,
MOD_MAP.map_info[ mod ].abs_base_addr, MOD_MAP.map_info[ mod ].size );
debug3( DEBUG_C_MODULES | DEBUG_C_MOD_CACHE, MOD_I_CONFIG, mod_description[ mod ].name, mod_map.map_info[ mod ].abs_base_addr,
mod_map.map_info[ mod ].size );
}
/* Set the unconfig cache pointer of module 'mod' to the old ModMap,
and increment its reference counter, to avoid freeing it
improperly.
*/
MOD_MAP.cache.unconfig[ mod ] = old;
mod_map.cache.unconfig[ mod ] = old;
old->cache.ref_count++;
}
}
@ -1318,15 +1330,15 @@ void ModUnconfig( Address unconfig_info )
struct ModMap *nxt, *old;
int mod;
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "ModUnconfig" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "ModUnconfig" );
/* Determine the module to unconfigure */
if ( ( mod = MOD_MAP.page_table[ ModPage( unconfig_info ) ].index ) == MOD_NO_MOD_INDEX ) {
if ( ( mod = mod_map.page_table[ ModPage( unconfig_info ) ].index ) == MOD_NO_MOD_INDEX ) {
/* There isn't any module configured at the given address -
Signal a warning
*/
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_W_BAD_UNCONFIG, CHF_WARNING, unconfig_info );
ChfSignal( MOD_CHF_MODULE_ID );
ChfCondition MOD_W_BAD_UNCONFIG, CHF_WARNING, unconfig_info ChfEnd;
ChfSignal();
} else if ( mod_description[ mod ].r_config == MOD_CONFIGURED ) {
/* The module is automatically configured after reset; it can never
be unconfigured.
@ -1339,7 +1351,7 @@ void ModUnconfig( Address unconfig_info )
IncPerfCtr( hit_c );
debug0( MOD_CHF_MODULE_ID, DEBUG_C_MOD_CACHE, MOD_I_CACHED_UNCONFIG );
debug0( DEBUG_C_MOD_CACHE, MOD_I_CACHED_UNCONFIG );
return;
}
@ -1365,18 +1377,18 @@ void ModUnconfig( Address unconfig_info )
mod_map_ptr = CopyModMap( NewModMap(), mod_map_ptr );
/* Update the mapping information table */
MOD_MAP.map_info[ mod ].config = mod_description[ mod ].r_config;
mod_map.map_info[ mod ].config = mod_description[ mod ].r_config;
/* Rebuild the page table */
RebuildPageTable( ModPage( MOD_MAP.map_info[ mod ].abs_base_addr ),
ModPage( MOD_MAP.map_info[ mod ].abs_base_addr + MOD_MAP.map_info[ mod ].size - 1 ) );
RebuildPageTable( ModPage( mod_map.map_info[ mod ].abs_base_addr ),
ModPage( mod_map.map_info[ mod ].abs_base_addr + mod_map.map_info[ mod ].size - 1 ) );
/* Reset the module configuration status; the abs_base_addr of the module
is not reset because its old value is still needed by ModGetId()
The size is reset for the modules that are already MOD_SIZE_CONFIGURED
immediately after reset.
*/
MOD_MAP.map_info[ mod ].size = mod_description[ mod ].r_size;
mod_map.map_info[ mod ].size = mod_description[ mod ].r_size;
if ( ( nxt = CheckForLateHit() ) != ( struct ModMap* )NULL ) {
/* Update pointer from the old map to the new one, and increment
@ -1390,7 +1402,7 @@ void ModUnconfig( Address unconfig_info )
mod_map_ptr = nxt;
IncPerfCtr( lhit_c );
debug0( MOD_CHF_MODULE_ID, DEBUG_C_MOD_CACHE, MOD_I_UNCONFIG_L_HIT );
debug0( DEBUG_C_MOD_CACHE, MOD_I_UNCONFIG_L_HIT );
} else {
/* Continue to use the new map with no caching information,
and hope that further configuration activities will link it
@ -1401,14 +1413,14 @@ void ModUnconfig( Address unconfig_info )
this flag is used by the unconfig cache code to correctly
undo the last config
*/
MOD_MAP.cache.config_point = 1;
mod_map.cache.config_point = 1;
IncPerfCtr( miss_c );
debug0( MOD_CHF_MODULE_ID, DEBUG_C_MOD_CACHE, MOD_I_UNCONFIG_L_MISS );
debug0( DEBUG_C_MOD_CACHE, MOD_I_UNCONFIG_L_MISS );
debug3( MOD_CHF_MODULE_ID, DEBUG_C_MODULES | DEBUG_C_MOD_CACHE, MOD_I_UNCONFIG, mod_description[ mod ].name,
MOD_MAP.map_info[ mod ].abs_base_addr, MOD_MAP.map_info[ mod ].size );
debug3( DEBUG_C_MODULES | DEBUG_C_MOD_CACHE, MOD_I_UNCONFIG, mod_description[ mod ].name, mod_map.map_info[ mod ].abs_base_addr,
mod_map.map_info[ mod ].size );
}
}
}
@ -1440,7 +1452,7 @@ Nibble FetchNibble( Address addr )
{
register int page = ModPage( addr );
return MOD_MAP.page_table[ page ].read( MOD_MAP.page_table[ page ].rel_base_addr | ModOffset( addr ) );
return mod_map.page_table[ page ].read( mod_map.page_table[ page ].rel_base_addr | ModOffset( addr ) );
}
/* .+
@ -1476,10 +1488,10 @@ Nibble ReadNibble( Address addr )
register Nibble d;
/* Read the nibble from the peripheral module */
d = MOD_MAP.page_table[ page ].read( MOD_MAP.page_table[ page ].rel_base_addr | ModOffset( addr ) );
d = mod_map.page_table[ page ].read( mod_map.page_table[ page ].rel_base_addr | ModOffset( addr ) );
/* Update the crc register, if appropriate */
if ( MOD_MAP.page_table[ page ].index != MOD_HDW_INDEX )
if ( mod_map.page_table[ page ].index != MOD_HDW_INDEX )
mod_status.hdw.crc = ( mod_status.hdw.crc >> 4 ) ^ ( ( ( mod_status.hdw.crc ^ d ) & 0x0F ) * 0x1081 );
/* Return to the caller */
@ -1514,7 +1526,7 @@ void WriteNibble( Address addr, Nibble datum )
{
register int page = ModPage( addr );
MOD_MAP.page_table[ page ].write( MOD_MAP.page_table[ page ].rel_base_addr | ModOffset( addr ), datum );
mod_map.page_table[ page ].write( mod_map.page_table[ page ].rel_base_addr | ModOffset( addr ), datum );
}
/*---------------------------------------------------------------------------
@ -1551,16 +1563,16 @@ void ModMapCheck( Address addr, char ob[ MOD_MAP_CHECK_OB_SIZE ] )
page = ModPage( addr );
offset = ModOffset( addr );
if ( ( mod = MOD_MAP.page_table[ page ].index ) == MOD_NO_MOD_INDEX )
sprintf( ob, "A[%05X] -> *Not Mapped*", addr );
if ( ( mod = mod_map.page_table[ page ].index ) == MOD_NO_MOD_INDEX )
sprintf( ob, ChfGetMessage( CHF_MODULE_ID, MOD_M_NOT_MAPPED, "" ), addr );
else {
Address rel_addr;
rel_addr = MOD_MAP.page_table[ page ].rel_base_addr | offset;
rel_addr = mod_map.page_table[ page ].rel_base_addr | offset;
sprintf( ob, "A[%05X] -> M[%s] R[%05X]", addr, mod_description[ mod ].name, rel_addr );
sprintf( ob, ChfGetMessage( CHF_MODULE_ID, MOD_M_MAPPED, "" ), addr, mod_description[ mod ].name, rel_addr );
}
ChfSignal( MOD_CHF_MODULE_ID );
ChfSignal();
}
/* .+
@ -1588,14 +1600,16 @@ void ModMapTable( char ob[ MOD_MAP_TABLE_OB_SIZE ] )
{
int mod;
sprintf( ob, "%s\n", "Device\t\t\tAddress\tSize\tStatus" );
sprintf( ob, "%s\n", ChfGetMessage( CHF_MODULE_ID, MOD_M_MAP_TABLE_TITLE, "" ) );
ob += strlen( ob );
for ( mod = 0; mod < N_MOD; mod++ ) {
sprintf( ob, "%s\t%05X\t%05X\t%s", mod_description[ mod ].name, MOD_MAP.map_info[ mod ].abs_base_addr, MOD_MAP.map_info[ mod ].size,
MOD_MAP.map_info[ mod ].config == MOD_CONFIGURED
? "Configured"
: ( MOD_MAP.map_info[ mod ].config == MOD_SIZE_CONFIGURED ? "Size_configured" : "*Unconfigured*" ) );
sprintf( ob, ChfGetMessage( CHF_MODULE_ID, MOD_M_MAP_TABLE_ROW, "" ), mod_description[ mod ].name,
mod_map.map_info[ mod ].abs_base_addr, mod_map.map_info[ mod ].size,
mod_map.map_info[ mod ].config == MOD_CONFIGURED ? ChfGetMessage( CHF_MODULE_ID, MOD_M_MAP_CONFIGURED, "C" )
: ( mod_map.map_info[ mod ].config == MOD_SIZE_CONFIGURED
? ChfGetMessage( CHF_MODULE_ID, MOD_M_MAP_SZ_CONFIGURED, "S" )
: ChfGetMessage( CHF_MODULE_ID, MOD_M_MAP_UNCONFIGURED, "U" ) ) );
strcat( ob, "\n" );
ob += strlen( ob );

View file

@ -229,7 +229,7 @@ typedef void ( *ModWriteFunction )( Address rel_addr, Nibble data );
enum ModConfig { MOD_UNCONFIGURED, MOD_SIZE_CONFIGURED, MOD_CONFIGURED };
struct ModDescriptionEntry {
const char* name;
char* name;
Address id;
int access_prio;
#define MOD_MIN_ACCESS_PRIO ( -1 )
@ -570,7 +570,7 @@ extern struct ModStatus mod_status;
---------------------------------------------------------------------------*/
/* Initialization */
void ModSelectDescription( int model );
void ModSelectDescription( const char* hw );
void ModRegisterDescription( ModDescription p );
void ModInit( void );
void ModSave( void );

View file

@ -65,17 +65,25 @@
.- */
#ifndef lint
static char rcs_id[] = "$Id: monitor.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>
#include <signal.h>
#include "libChf/src/Chf.h"
#include <errno.h>
#include "config.h"
#include "machdep.h"
#include "cpu.h"
#include "modules.h"
#include "debug.h"
#define CHF_MODULE_ID CPU_CHF_MODULE_ID
#include <Chf.h>
/*---------------------------------------------------------------------------
Macro & Data type definitions
@ -136,7 +144,7 @@ static int debug( void )
Address addr;
if ( ReadHexAddress( &addr ) )
return FAILED;
config.debug_level |= ( int )addr;
SetDebugLevel( ( int )addr );
return OK;
}
@ -248,12 +256,12 @@ static int mon_quit( void )
---------------------------------------------------------------------------*/
struct TEntry {
const char* name;
const char* desc;
char* name;
char* desc;
int ( *function )( void );
};
#define TABLE_SIZE( t ) ( sizeof( t ) / sizeof( struct TEntry ) )
#define TableSize( t ) ( sizeof( t ) / sizeof( struct TEntry ) )
/* Forward declaration for the Help funcion */
static int Help( void );
@ -277,15 +285,16 @@ static const struct TEntry table[] = {
static int InvokeCommand( char* tk )
{
int i;
for ( i = 0; i < ( int )TABLE_SIZE( table ) && strcmp( tk, table[ i ].name ); i++ )
for ( i = 0; i < ( int )TableSize( table ) && strcmp( tk, table[ i ].name ); i++ )
;
return i == TABLE_SIZE( table ) ? FAILED : table[ i ].function();
return i == TableSize( table ) ? FAILED : table[ i ].function();
}
/* Print help information */
static int Help( void )
{
for ( int i = 0; i < ( int )TABLE_SIZE( table ); i++ )
int i;
for ( i = 0; i < ( int )TableSize( table ); i++ )
printf( "%s\t\t%s\n", table[ i ].name, table[ i ].desc );
return OK;
@ -332,7 +341,7 @@ void Monitor( void )
signal( SIGINT, sigint_handler );
/* Infinite loop; it's exited only when a condition is signalled */
while ( true ) {
while ( 1 ) {
/* Write prompt */
fputs( PROMPT, stdout );
fflush( stdout );
@ -341,16 +350,16 @@ void Monitor( void )
/* New command empty; try old command */
if ( ( tk = strtok( old_cmd, TOK_DELIMITERS ) ) != ( char* )NULL )
if ( InvokeCommand( tk ) )
ChfGenerate( CPU_CHF_MODULE_ID, __FILE__, __LINE__, CPU_W_BAD_MONITOR_CMD, CHF_WARNING, tk );
ChfSignal( CPU_CHF_MODULE_ID );
ChfCondition CPU_W_BAD_MONITOR_CMD, CHF_WARNING, tk ChfEnd;
ChfSignal();
} else {
/* Save command */
strcpy( old_cmd, cmd );
/* New command */
if ( InvokeCommand( tk ) ) {
ChfGenerate( CPU_CHF_MODULE_ID, __FILE__, __LINE__, CPU_W_BAD_MONITOR_CMD, CHF_WARNING, tk );
ChfSignal( CPU_CHF_MODULE_ID );
ChfCondition CPU_W_BAD_MONITOR_CMD, CHF_WARNING, tk ChfEnd;
ChfSignal();
}
}
}

View file

@ -64,32 +64,27 @@
.- */
#ifndef lint
static char rcs_id[] = "$Id";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include "libChf/src/Chf.h"
#include <errno.h>
#include "config.h"
#include "machdep.h"
#include "cpu.h"
#include "disk_io.h"
/* Condition codes used by this utility */
#define UTIL_CHF_MODULE_ID 17
#define UTIL_I_PACK_USAGE 1
#define UTIL_F_PACK_CMD_LINE 2
#define UTIL_F_PACK_STAT 3
#define UTIL_F_PACK_SRC_SIZE 4
#define UTIL_F_PACK_MALLOC 5
#define UTIL_F_PACK_OPEN 6
#define UTIL_F_PACK_READ 7
#define UTIL_F_PACK_WRITE_NIBBLES 8
#define CHF_MODULE_ID UTIL_CHF_MODULE_ID
#include <Chf.h>
/* Maximum size of source ROM (bytes) handled by this utility; set to
a reasonable value
@ -106,20 +101,24 @@
/* Conditional prefix and mandatory suffix to make a message catalog
name from cat_base_name.
*/
/* Message catalog */
static const char cat_base_name[] = "saturn";
ChfTable message_table[] = {
{UTIL_CHF_MODULE_ID, UTIL_I_PACK_USAGE, "Usage:\n pack <emu48_source_rom> <saturn_dest_rom>"},
{UTIL_CHF_MODULE_ID, UTIL_F_PACK_CMD_LINE, "Command line syntax error" },
{UTIL_CHF_MODULE_ID, UTIL_F_PACK_STAT, "stat(%s) failed" },
{UTIL_CHF_MODULE_ID, UTIL_F_PACK_SRC_SIZE, "Invalid source file size: %d" },
{UTIL_CHF_MODULE_ID, UTIL_F_PACK_MALLOC, "malloc(%d) failed" },
{UTIL_CHF_MODULE_ID, UTIL_F_PACK_OPEN, "open(%s) failed" },
{UTIL_CHF_MODULE_ID, UTIL_F_PACK_READ, "read(%s) failed" },
{UTIL_CHF_MODULE_ID, UTIL_F_PACK_WRITE_NIBBLES, "WriteNibblesToFile() failed" },
};
static const char cat_prefix[] = "./";
static const char cat_suffix[] = ".cat";
size_t message_table_size = sizeof( message_table ) / sizeof( message_table[ 0 ] );
#define CAT_PREFIX_LEN ( sizeof( cat_prefix ) + 1 )
#define CAT_SUFFIX_LEN ( sizeof( cat_suffix ) + 1 )
/* Message catalog base_name */
static const char cat_base_name[] = "saturn";
/* Condition codes used by this utility */
#define UTIL_I_PACK_USAGE 1
#define UTIL_F_PACK_CMD_LINE 2
#define UTIL_F_PACK_STAT 3
#define UTIL_F_PACK_SRC_SIZE 4
#define UTIL_F_PACK_MALLOC 5
#define UTIL_F_PACK_OPEN 6
#define UTIL_F_PACK_READ 7
#define UTIL_F_PACK_WRITE_NIBBLES 8
/*---------------------------------------------------------------------------
Public functions
@ -139,73 +138,112 @@ size_t message_table_size = sizeof( message_table ) / sizeof( message_table[ 0 ]
.- */
int main( int argc, char* argv[] )
{
char* cat_name; /* Message catalog name */
struct stat statb; /* stat() buffer on source file */
char* b; /* Source buffer */
Nibble* nb; /* Nibble buffer */
int d; /* Source file descriptor */
int i;
int st;
if ( ( cat_name = malloc( sizeof( cat_base_name ) + CAT_PREFIX_LEN + CAT_SUFFIX_LEN + 1 ) ) == NULL ) {
fprintf( stderr, "Cat_name initialization failed\n" );
exit( EXIT_FAILURE );
}
/* Generate catalog name, without optional prefix */
strcpy( cat_name, cat_base_name );
strcat( cat_name, cat_suffix );
/* Chf initialization with msgcat subsystem;
notice that on some systems (e.g. Digital UNIX) catopen() can succeed
even if it was not able to open the right message catalog; better
try it now.
*/
if ( ChfStaticInit( argv[ 0 ], /* Application's name */
CHF_DEFAULT, /* Options */
message_table, /* message catalog */
message_table_size, /* message catalog size */
CONDITION_STACK_SIZE, /* Size of the condition stack */
HANDLER_STACK_SIZE, /* Size of the handler stack */
EXIT_FAILURE /* Abnormal exit code */
) != CHF_S_OK ) {
fprintf( stderr, "Chf initialization failed\n" );
exit( EXIT_FAILURE );
if ( ( st = ChfMsgcatInit( argv[ 0 ], /* Application's name */
CHF_DEFAULT, /* Options */
cat_name, /* Name of the message catalog */
CONDITION_STACK_SIZE, /* Size of the condition stack */
HANDLER_STACK_SIZE, /* Size of the handler stack */
EXIT_FAILURE /* Abnormal exit code */
) ) != CHF_S_OK ||
ChfGetMessage( CHF_MODULE_ID, UTIL_I_PACK_USAGE, NULL ) == NULL ) {
if ( st != CHF_S_OK && st != CHF_F_CATOPEN ) {
fprintf( stderr, "Chf initialization failed\n" );
exit( EXIT_FAILURE );
} else {
fprintf( stderr, "Default message catalog open failed; trying alternate\n" );
/* Bring down Chf before initializing it again */
if ( st == CHF_S_OK )
ChfExit();
/* Try alternate message catalog name (with prefix) */
strcpy( cat_name, cat_prefix );
strcat( cat_name, cat_base_name );
strcat( cat_name, cat_suffix );
if ( ( st = ChfMsgcatInit( argv[ 0 ], /* Application's name */
CHF_DEFAULT, /* Options */
cat_name, /* Name of the message catalog */
CONDITION_STACK_SIZE, /* Size of the condition stack */
HANDLER_STACK_SIZE, /* Size of the handler stack */
EXIT_FAILURE /* Abnormal exit code */
) ) != CHF_S_OK ||
ChfGetMessage( CHF_MODULE_ID, UTIL_I_PACK_USAGE, NULL ) == NULL ) {
fprintf( stderr, "Alternate Chf initialization failed\n" );
exit( EXIT_FAILURE );
}
}
}
/* cat_name no longer needed */
free( cat_name );
/* Now, do some useful work; pack argv[1] into argv[2] */
if ( argc != 3 ) {
ChfGenerate( UTIL_CHF_MODULE_ID, __FILE__, __LINE__, UTIL_I_PACK_USAGE, CHF_INFO );
ChfGenerate( UTIL_CHF_MODULE_ID, __FILE__, __LINE__, UTIL_F_PACK_CMD_LINE, CHF_FATAL );
ChfSignal( UTIL_CHF_MODULE_ID );
ChfCondition UTIL_I_PACK_USAGE, CHF_INFO ChfEnd;
ChfCondition UTIL_F_PACK_CMD_LINE, CHF_FATAL ChfEnd;
ChfSignal();
}
/* Get the size of the source file */
if ( stat( argv[ 1 ], &statb ) ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( UTIL_CHF_MODULE_ID, __FILE__, __LINE__, UTIL_F_PACK_STAT, CHF_FATAL, argv[ 1 ] );
ChfSignal( UTIL_CHF_MODULE_ID );
ChfErrnoCondition;
ChfCondition UTIL_F_PACK_STAT, CHF_FATAL, argv[ 1 ] ChfEnd;
ChfSignal();
}
/* Check that actual size is reasonable */
if ( statb.st_size > MAX_SRC_SIZE ) {
ChfGenerate( UTIL_CHF_MODULE_ID, __FILE__, __LINE__, UTIL_F_PACK_SRC_SIZE, CHF_FATAL, statb.st_size );
ChfSignal( UTIL_CHF_MODULE_ID );
ChfCondition UTIL_F_PACK_SRC_SIZE, CHF_FATAL, statb.st_size ChfEnd;
ChfSignal();
}
/* Allocate source buffer */
if ( ( b = ( char* )malloc( statb.st_size ) ) == ( char* )NULL ||
( nb = ( Nibble* )malloc( sizeof( Nibble ) * statb.st_size ) ) == ( Nibble* )NULL ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( UTIL_CHF_MODULE_ID, __FILE__, __LINE__, UTIL_F_PACK_MALLOC, CHF_FATAL, statb.st_size );
ChfSignal( UTIL_CHF_MODULE_ID );
ChfErrnoCondition;
ChfCondition UTIL_F_PACK_MALLOC, CHF_FATAL, statb.st_size ChfEnd;
ChfSignal();
return EXIT_FAILURE;
}
/* open/read/close */
if ( ( d = open( argv[ 1 ], O_RDONLY ) ) == -1 ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( UTIL_CHF_MODULE_ID, __FILE__, __LINE__, UTIL_F_PACK_OPEN, CHF_FATAL, argv[ 1 ] );
ChfSignal( UTIL_CHF_MODULE_ID );
ChfErrnoCondition;
ChfCondition UTIL_F_PACK_OPEN, CHF_FATAL, argv[ 1 ] ChfEnd;
ChfSignal();
}
if ( read( d, b, statb.st_size ) != statb.st_size ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfErrnoCondition;
( void )close( d );
ChfGenerate( UTIL_CHF_MODULE_ID, __FILE__, __LINE__, UTIL_F_PACK_READ, CHF_FATAL, argv[ 1 ] );
ChfSignal( UTIL_CHF_MODULE_ID );
ChfCondition UTIL_F_PACK_READ, CHF_FATAL, argv[ 1 ] ChfEnd;
ChfSignal();
}
( void )close( d );
@ -219,8 +257,8 @@ int main( int argc, char* argv[] )
/* Write */
if ( WriteNibblesToFile( nb, statb.st_size, argv[ 2 ] ) ) {
ChfGenerate( UTIL_CHF_MODULE_ID, __FILE__, __LINE__, UTIL_F_PACK_WRITE_NIBBLES, CHF_FATAL );
ChfSignal( UTIL_CHF_MODULE_ID );
ChfCondition UTIL_F_PACK_WRITE_NIBBLES, CHF_FATAL ChfEnd;
ChfSignal();
}
return EXIT_SUCCESS;

View file

@ -78,12 +78,16 @@
.- */
#ifndef lint
static char rcs_id[] = "$Id: romram.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>
#include <unistd.h> /* access() */
#include "libChf/src/Chf.h"
#include <errno.h>
#include "config.h"
#include "machdep.h"
@ -92,6 +96,9 @@
#include "disk_io.h"
#include "debug.h"
#define CHF_MODULE_ID MOD_CHF_MODULE_ID
#include <Chf.h>
/* 3.2: The rom/ram storage areas are now dynamically allocated in
a private struct ModStatus_48. The dynamic allocation is performed during
Rom initialization, and the following macro allows us to reuse the
@ -134,20 +141,17 @@ static struct ModStatus_48* mod_status_48;
.- */
void RomInit( void )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "RomInit" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RomInit" );
if ( ( mod_status_48 = ( struct ModStatus_48* )malloc( sizeof( struct ModStatus_48 ) ) ) == ( struct ModStatus_48* )NULL ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_F_MOD_STATUS_ALLOC, CHF_FATAL, sizeof( struct ModStatus_48 ) );
ChfSignal( MOD_CHF_MODULE_ID );
ChfErrnoCondition;
ChfCondition MOD_F_MOD_STATUS_ALLOC, CHF_FATAL, sizeof( struct ModStatus_48 ) ChfEnd;
ChfSignal();
}
if ( ReadNibblesFromFile( config.rom_file_name, N_ROM_SIZE, mod_status_rom ) ) {
// To load 48SX ROM, try again with half the size this time.
if ( ReadNibblesFromFile( config.rom_file_name, N_ROM_SIZE / 2, mod_status_rom ) ) {
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_F_ROM_INIT, CHF_FATAL );
ChfSignal( MOD_CHF_MODULE_ID );
}
if ( ReadNibblesFromFile( args.rom_file_name, N_ROM_SIZE, mod_status_rom ) ) {
ChfCondition MOD_F_ROM_INIT, CHF_FATAL ChfEnd;
ChfSignal();
}
}
@ -172,7 +176,7 @@ void RomInit( void )
1.1, 11-Feb-1998, creation
.- */
void RomSave( void ) { debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "RomSave" ); }
void RomSave( void ) { debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RomSave" ); }
/* .+
@ -197,7 +201,7 @@ void RomSave( void ) { debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "
.- */
Nibble RomRead( Address rel_address )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "RomRead" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RomRead" );
return mod_status_rom[ rel_address ];
}
@ -227,11 +231,10 @@ Nibble RomRead( Address rel_address )
.- */
void RomWrite( Address rel_address, Nibble datum )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "RomWrite" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RomWrite" );
// FIXME: 48gx: saturn48gx-Mid <12>d (src/romram.c,235)-E-Write into ROM A[1B632] D[9]
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_E_ROM_WRITE, CHF_ERROR, rel_address, datum );
ChfSignal( MOD_CHF_MODULE_ID );
ChfCondition MOD_E_ROM_WRITE, CHF_ERROR, rel_address, datum ChfEnd;
ChfSignal();
}
/*---------------------------------------------------------------------------
@ -261,11 +264,11 @@ void RomWrite( Address rel_address, Nibble datum )
.- */
void RamInit( void )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "RamInit" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RamInit" );
if ( ReadNibblesFromFile( config.ram_file_name, N_RAM_SIZE, mod_status_ram ) ) {
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_W_RAM_INIT, CHF_WARNING );
ChfSignal( MOD_CHF_MODULE_ID );
if ( ReadNibblesFromFile( args.ram_file_name, N_RAM_SIZE, mod_status_ram ) ) {
ChfCondition MOD_W_RAM_INIT, CHF_WARNING ChfEnd;
ChfSignal();
( void )memset( mod_status_ram, 0, sizeof( mod_status_ram ) );
}
@ -291,17 +294,17 @@ void RamInit( void )
.notes :
1.1, 11-Feb-1998, creation
2.4, 12-Sep-2000, update
- upon failure, added push of ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR ) to condition stack.
- upon failure, added push of ChfErrnoCondition to condition stack.
.- */
void RamSave( void )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "RamSave" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RamSave" );
if ( WriteNibblesToFile( mod_status_ram, N_RAM_SIZE, config.ram_file_name ) ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_E_RAM_SAVE, CHF_ERROR );
ChfSignal( MOD_CHF_MODULE_ID );
if ( WriteNibblesToFile( mod_status_ram, N_RAM_SIZE, args.ram_file_name ) ) {
ChfErrnoCondition;
ChfCondition MOD_E_RAM_SAVE, CHF_ERROR ChfEnd;
ChfSignal();
}
}
@ -328,7 +331,7 @@ void RamSave( void )
.- */
Nibble RamRead( Address rel_address )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "RamRead" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RamRead" );
return mod_status_ram[ rel_address ];
}
@ -357,7 +360,7 @@ Nibble RamRead( Address rel_address )
.- */
void RamWrite( Address rel_address, Nibble datum )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "RamWrite" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RamWrite" );
mod_status_ram[ rel_address ] = datum;
}
@ -390,7 +393,7 @@ void RamWrite( Address rel_address, Nibble datum )
.- */
void Ce1Init( void )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Init" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Init" );
/* Check if bank-switcher accelerators are valid; if not, initialize
them to a reasonable value (that is, select Port_2 bank 0).
@ -424,7 +427,7 @@ void Ce1Init( void )
.- */
void Ce1Save( void )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Save" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Save" );
/* Nothing to be done herel the bank-switcher accelerators are saved
by the hdw modules
@ -458,8 +461,8 @@ void Ce1Save( void )
.- */
Nibble Ce1Read( Address rel_address )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Read" );
debug1( MOD_CHF_MODULE_ID, DEBUG_C_MODULES, MOD_I_BS_ADDRESS, rel_address );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Read" );
debug1( DEBUG_C_MODULES, MOD_I_BS_ADDRESS, rel_address );
/* Save the read address into the hdw accelerators.
bs_address can be directly or-ed with a relative port address to
@ -499,10 +502,10 @@ Nibble Ce1Read( Address rel_address )
.- */
void Ce1Write( Address rel_address, Nibble datum )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Write" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Write" );
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_E_CE1_WRITE, CHF_ERROR, rel_address, datum );
ChfSignal( MOD_CHF_MODULE_ID );
ChfCondition MOD_E_CE1_WRITE, CHF_ERROR, rel_address, datum ChfEnd;
ChfSignal();
}
/*---------------------------------------------------------------------------
@ -536,11 +539,11 @@ void Ce2Init( void )
{
Nibble new_status;
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Init" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Init" );
if ( ReadNibblesFromFile( config.port_1_file_name, N_PORT_1_SIZE, mod_status_port_1 ) ) {
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_W_PORT_1_INIT, CHF_WARNING );
ChfSignal( MOD_CHF_MODULE_ID );
if ( ReadNibblesFromFile( args.port_1_file_name, N_PORT_1_SIZE, mod_status_port_1 ) ) {
ChfCondition MOD_W_PORT_1_INIT, CHF_WARNING ChfEnd;
ChfSignal();
( void )memset( mod_status_port_1, 0, sizeof( mod_status_port_1 ) );
@ -549,14 +552,14 @@ void Ce2Init( void )
/* Card present; check write protection */
new_status = mod_status_hdw.card_status | CE2_CARD_PRESENT;
if ( access( config.port_1_file_name, W_OK ) == 0 )
if ( access( args.port_1_file_name, W_OK ) == 0 )
new_status |= CE2_CARD_WE;
else {
new_status &= ~CE2_CARD_WE;
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_I_PORT_1_WP, CHF_INFO );
ChfSignal( MOD_CHF_MODULE_ID );
ChfErrnoCondition;
ChfCondition MOD_I_PORT_1_WP, CHF_INFO ChfEnd;
ChfSignal();
}
}
@ -595,13 +598,13 @@ void Ce2Init( void )
.- */
void Ce2Save( void )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Save" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Save" );
/* Attempt to save only if port is write-enabled */
if ( ( mod_status_hdw.card_status & CE2_CARD_WE ) && WriteNibblesToFile( mod_status_port_1, N_PORT_1_SIZE, config.port_1_file_name ) ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_E_PORT_1_SAVE, CHF_ERROR );
ChfSignal( MOD_CHF_MODULE_ID );
if ( ( mod_status_hdw.card_status & CE2_CARD_WE ) && WriteNibblesToFile( mod_status_port_1, N_PORT_1_SIZE, args.port_1_file_name ) ) {
ChfErrnoCondition;
ChfCondition MOD_E_PORT_1_SAVE, CHF_ERROR ChfEnd;
ChfSignal();
}
}
@ -628,7 +631,7 @@ void Ce2Save( void )
.- */
Nibble Ce2Read( Address rel_address )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Read" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Read" );
return mod_status_port_1[ rel_address ];
}
@ -657,7 +660,7 @@ Nibble Ce2Read( Address rel_address )
.- */
void Ce2Write( Address rel_address, Nibble datum )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Write" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Write" );
mod_status_port_1[ rel_address ] = datum;
}
@ -694,12 +697,12 @@ void NCe3Init( void )
{
Nibble new_status;
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Init" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Init" );
#ifdef N_PORT_2_BANK
if ( ReadNibblesFromFile( config.port_2_file_name, N_PORT_2_SIZE, mod_status_port_2 ) ) {
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_W_PORT_2_INIT, CHF_WARNING );
ChfSignal( MOD_CHF_MODULE_ID );
if ( ReadNibblesFromFile( args.port_2_file_name, N_PORT_2_SIZE, mod_status_port_2 ) ) {
ChfCondition MOD_W_PORT_2_INIT, CHF_WARNING ChfEnd;
ChfSignal();
( void )memset( mod_status_port_2, 0, sizeof( mod_status_port_2 ) );
@ -708,14 +711,14 @@ void NCe3Init( void )
/* Card present; check write protection */
new_status = mod_status_hdw.card_status | NCE3_CARD_PRESENT;
if ( access( config.port_2_file_name, W_OK ) == 0 )
if ( access( args.port_2_file_name, W_OK ) == 0 )
new_status |= NCE3_CARD_WE;
else {
new_status &= ~NCE3_CARD_WE;
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_I_PORT_2_WP, CHF_INFO );
ChfSignal( MOD_CHF_MODULE_ID );
ChfErrnoCondition;
ChfCondition MOD_I_PORT_2_WP, CHF_INFO ChfEnd;
ChfSignal();
}
}
@ -759,15 +762,14 @@ void NCe3Init( void )
.- */
void NCe3Save( void )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Save" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Save" );
#ifdef N_PORT_2_BANK
/* Attempt to save only if port is write-enabled */
if ( ( mod_status_hdw.card_status & NCE3_CARD_WE ) &&
WriteNibblesToFile( mod_status_port_2, N_PORT_2_SIZE, config.port_2_file_name ) ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_E_PORT_2_SAVE, CHF_ERROR );
ChfSignal( MOD_CHF_MODULE_ID );
if ( ( mod_status_hdw.card_status & NCE3_CARD_WE ) && WriteNibblesToFile( mod_status_port_2, N_PORT_2_SIZE, args.port_2_file_name ) ) {
ChfErrnoCondition;
ChfCondition MOD_E_PORT_2_SAVE, CHF_ERROR ChfEnd;
ChfSignal();
}
#endif
}
@ -797,14 +799,14 @@ void NCe3Save( void )
.- */
Nibble NCe3Read( Address rel_address )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Read" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Read" );
#ifdef N_PORT_2_BANK
return mod_status_port_2[ rel_address | mod_status_hdw.accel.a48.bs_address ];
#else
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_E_NCE3_READ, CHF_ERROR, rel_address );
ChfSignal( MOD_CHF_MODULE_ID );
ChfCondition MOD_E_NCE3_READ, CHF_ERROR, rel_address ChfEnd;
ChfSignal();
return ( Nibble )0;
#endif
@ -837,14 +839,14 @@ Nibble NCe3Read( Address rel_address )
.- */
void NCe3Write( Address rel_address, Nibble datum )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Write" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Write" );
#ifdef N_PORT_2_BANK
mod_status_port_2[ rel_address | mod_status_hdw.accel.a48.bs_address ] = datum;
#else
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_E_NCE3_WRITE, CHF_ERROR, rel_address, datum );
ChfSignal( MOD_CHF_MODULE_ID );
ChfCondition MOD_E_NCE3_WRITE, CHF_ERROR, rel_address, datum ChfEnd;
ChfSignal();
#endif
}

View file

@ -90,12 +90,16 @@
.- */
#ifndef lint
static char rcs_id[] = "$Id: romram49.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>
#include <unistd.h> /* access() */
#include "libChf/src/Chf.h"
#include <errno.h>
#include "config.h"
#include "machdep.h"
@ -105,6 +109,9 @@
#include "disk_io.h"
#include "debug.h"
#define CHF_MODULE_ID MOD_CHF_MODULE_ID
#include <Chf.h>
#define FLASH_VIEW_SELECTOR 0x40000
#define FLASH_BANK_MASK 0x3FFFF
@ -149,17 +156,17 @@ struct ModStatus_49* mod_status_49;
.- */
void RomInit49( void )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "RomInit49" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RomInit49" );
if ( ( mod_status_49 = ( struct ModStatus_49* )malloc( sizeof( struct ModStatus_49 ) ) ) == ( struct ModStatus_49* )NULL ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_F_MOD_STATUS_ALLOC, CHF_FATAL, sizeof( struct ModStatus_49 ) );
ChfSignal( MOD_CHF_MODULE_ID );
ChfErrnoCondition;
ChfCondition MOD_F_MOD_STATUS_ALLOC, CHF_FATAL, sizeof( struct ModStatus_49 ) ChfEnd;
ChfSignal();
}
if ( ReadNibblesFromFile( config.rom_file_name, N_FLASH_SIZE_49, mod_status_49->flash ) ) {
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_F_ROM_INIT, CHF_FATAL );
ChfSignal( MOD_CHF_MODULE_ID );
if ( ReadNibblesFromFile( args.rom_file_name, N_FLASH_SIZE_49, mod_status_49->flash ) ) {
ChfCondition MOD_F_ROM_INIT, CHF_FATAL ChfEnd;
ChfSignal();
}
}
@ -187,12 +194,12 @@ void RomInit49( void )
.- */
void RomSave49( void )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "RomSave49" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RomSave49" );
if ( WriteNibblesToFile( mod_status_49->flash, N_FLASH_SIZE_49, config.rom_file_name ) ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_E_ROM_SAVE, CHF_ERROR );
ChfSignal( MOD_CHF_MODULE_ID );
if ( WriteNibblesToFile( mod_status_49->flash, N_FLASH_SIZE_49, args.rom_file_name ) ) {
ChfErrnoCondition;
ChfCondition MOD_E_ROM_SAVE, CHF_ERROR ChfEnd;
ChfSignal();
}
}
@ -221,7 +228,7 @@ Nibble RomRead49( Address rel_address )
{
register XAddress view;
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "RomRead49" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RomRead49" );
view = mod_status.hdw.accel.a49.view[ ( rel_address & FLASH_VIEW_SELECTOR ) != 0 ];
@ -258,7 +265,7 @@ Nibble RomRead49( Address rel_address )
.- */
void RomWrite49( Address rel_address, Nibble datum )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "RomWrite49" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RomWrite49" );
/* Ignore write cycles through ROM controller; HP49 ROM 1.19-4
can do this when to ON key is pressed.
@ -292,11 +299,11 @@ void RomWrite49( Address rel_address, Nibble datum )
.- */
void RamInit49( void )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "RamInit49" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RamInit49" );
if ( ReadNibblesFromFile( config.ram_file_name, N_RAM_SIZE_49, mod_status_49->ram ) ) {
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_W_RAM_INIT, CHF_WARNING );
ChfSignal( MOD_CHF_MODULE_ID );
if ( ReadNibblesFromFile( args.ram_file_name, N_RAM_SIZE_49, mod_status_49->ram ) ) {
ChfCondition MOD_W_RAM_INIT, CHF_WARNING ChfEnd;
ChfSignal();
( void )memset( mod_status_49->ram, 0, sizeof( mod_status_49->ram ) );
}
@ -325,12 +332,12 @@ void RamInit49( void )
.- */
void RamSave49( void )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "RamSave49" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RamSave49" );
if ( WriteNibblesToFile( mod_status_49->ram, N_RAM_SIZE_49, config.ram_file_name ) ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( MOD_CHF_MODULE_ID, __FILE__, __LINE__, MOD_E_RAM_SAVE, CHF_ERROR );
ChfSignal( MOD_CHF_MODULE_ID );
if ( WriteNibblesToFile( mod_status_49->ram, N_RAM_SIZE_49, args.ram_file_name ) ) {
ChfErrnoCondition;
ChfCondition MOD_E_RAM_SAVE, CHF_ERROR ChfEnd;
ChfSignal();
}
}
@ -357,7 +364,7 @@ void RamSave49( void )
.- */
Nibble RamRead49( Address rel_address )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "RamRead49" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RamRead49" );
return mod_status_49->ram[ rel_address ];
}
@ -386,7 +393,7 @@ Nibble RamRead49( Address rel_address )
.- */
void RamWrite49( Address rel_address, Nibble datum )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "RamWrite49" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RamWrite49" );
mod_status_49->ram[ rel_address ] = datum;
}
@ -418,7 +425,7 @@ void RamWrite49( Address rel_address, Nibble datum )
.- */
void Ce1Init49( void )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Init49" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Init49" );
/* Check if bank-switcher accelerators are valid; if not, initialize
them to a reasonable value (that is, select Flash Rom bank 0 for
@ -452,7 +459,7 @@ void Ce1Init49( void )
.- */
void Ce1Save49( void )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Save49" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Save49" );
/* Nothing to be done here; the bank-switcher accelerators are saved
by the hdw modules
@ -497,8 +504,8 @@ void Ce1Save49( void )
.- */
Nibble Ce1Read49( Address rel_address )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Read49" );
debug1( MOD_CHF_MODULE_ID, DEBUG_C_MODULES, MOD_I_BS_ADDRESS, rel_address );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Read49" );
debug1( DEBUG_C_MODULES, MOD_I_BS_ADDRESS, rel_address );
/* Save the ROM view base addresses address into the hdw accelerators.
view[] can be directly or-ed with a relative port address to
@ -537,8 +544,8 @@ Nibble Ce1Read49( Address rel_address )
.- */
void Ce1Write49( Address rel_address, Nibble datum )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Write49" );
debug1( MOD_CHF_MODULE_ID, DEBUG_C_MODULES, MOD_I_BS_ADDRESS, rel_address );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Write49" );
debug1( DEBUG_C_MODULES, MOD_I_BS_ADDRESS, rel_address );
/* Save the ROM view base addresses address into the hdw accelerators.
view[] can be directly or-ed with a relative port address to
@ -577,7 +584,7 @@ void Ce1Write49( Address rel_address, Nibble datum )
.- */
void Ce2Init49( void )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Init49" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Init49" );
/* Set base of ce2 area */
mod_status_49->ce2 = mod_status_49->ram + CE2_RAM_OFFSET;
@ -616,7 +623,7 @@ void Ce2Init49( void )
.- */
void Ce2Save49( void )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Save49" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Save49" );
/* Do nothing; the whole RAM is saved by RamSave49() */
}
@ -643,7 +650,7 @@ void Ce2Save49( void )
.- */
Nibble Ce2Read49( Address rel_address )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Read49" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Read49" );
return mod_status_49->ce2[ rel_address ];
}
@ -671,7 +678,7 @@ Nibble Ce2Read49( Address rel_address )
.- */
void Ce2Write49( Address rel_address, Nibble datum )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Write49" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Write49" );
mod_status_49->ce2[ rel_address ] = datum;
}
@ -706,7 +713,7 @@ void Ce2Write49( Address rel_address, Nibble datum )
.- */
void NCe3Init49( void )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Init49" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Init49" );
/* Set base of nce3 area */
mod_status_49->nce3 = mod_status_49->ram + NCE3_RAM_OFFSET;
@ -745,7 +752,7 @@ void NCe3Init49( void )
.- */
void NCe3Save49( void )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Save49" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Save49" );
/* Do nothing; the whole RAM is saved by RamSave49() */
}
@ -782,7 +789,7 @@ void NCe3Save49( void )
.- */
Nibble NCe3Read49( Address rel_address )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Read49" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Read49" );
return ( mod_status.hdw.hdw[ HDW_LCR_OFFSET ] & LCR_LED )
? FlashRead49( mod_status.hdw.accel.a49.view[ ( rel_address & FLASH_VIEW_SELECTOR ) != 0 ] |
@ -824,7 +831,7 @@ Nibble NCe3Read49( Address rel_address )
.- */
void NCe3Write49( Address rel_address, Nibble datum )
{
debug1( MOD_CHF_MODULE_ID, DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Write49" );
debug1( DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Write49" );
if ( mod_status.hdw.hdw[ HDW_LCR_OFFSET ] & LCR_LED )
FlashWrite49( mod_status.hdw.accel.a49.view[ ( rel_address & FLASH_VIEW_SELECTOR ) != 0 ] | ( rel_address & FLASH_BANK_MASK ),

View file

@ -79,13 +79,13 @@
Revision 3.2 2000/09/22 14:34:55 cibrario
Implemented preliminary support of HP49 hw architecture:
- simplified handling of
- Conditionally (#ifdef HP49_SUPPORT) simplified handling of
RCS_RBZ and RCS_RBF bits of RCS register.
- disabled local ECHO on master
- Conditionally (#ifdef HP49_SUPPORT) disabled local ECHO on master
pty when USE_OPENPTY is in effect; this avoid spurious rx
when no process is connected to the slave pty yet. Apparently,
USE_STREAMSPTY does not suffer from this.
- removed warning message
- Conditionally (#ifdef HP49_SUPPORT) removed warning message
when reading from an empty RRB.
* Revision 2.6 2000/09/15 09:23:02 cibrario
@ -100,18 +100,24 @@
.- */
#ifndef lint
static char rcs_id[] = "$Id: serial.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <errno.h>
#include "libChf/src/Chf.h"
#include "config.h"
#include "machdep.h"
#include "cpu.h"
#include "serial.h" /* 2.5: Serial port emulation module */
#include "debug.h"
#define CHF_MODULE_ID SERIAL_CHF_MODULE_ID
#include <Chf.h>
/*---------------------------------------------------------------------------
Determine pty implementation
@ -415,7 +421,7 @@ static int slave_pty; /* File descriptor of pty's slave side */
- if the receiver ring buffer is empty,
RCS_RBZ and RCS_RBF are both reset
3.2: the RCS_RBZ bit is
3.2: If HP49_SUPPORT is enabled, the RCS_RBZ bit is
always left clear and only RCS_RBF is updated;
this is simpler and works well on the 48, too.
@ -435,12 +441,24 @@ static int slave_pty; /* File descriptor of pty's slave side */
( ( ioc & IOC_ERBZ ) && ( rcs & RCS_RBZ ) ) ) ) \
CpuIntRequest( INT_REQUEST_IRQ )
#define UpdateRCS \
if ( FullSlots( rrb ) > 0 ) { \
rcs |= RCS_RBF; \
} else { \
rcs &= ~( RCS_RBF ); \
}
#ifdef HP49_SUPPORT
# define UpdateRCS \
if ( FullSlots( rrb ) > 0 ) { \
rcs |= RCS_RBF; \
} else { \
rcs &= ~( RCS_RBF ); \
}
#else
# define UpdateRCS \
if ( FullSlots( rrb ) > 1 ) { \
rcs |= ( RCS_RBF | RCS_RBZ ); \
} else if ( FullSlots( rrb ) > 0 ) { \
rcs |= RCS_RBF; \
rcs &= ~RCS_RBZ; \
} else { \
rcs &= ~( RCS_RBF | RCS_RBZ ); \
}
#endif
#define UpdateTCS \
if ( EmptySlots( trb ) > 1 ) { \
@ -494,7 +512,7 @@ static int slave_pty; /* File descriptor of pty's slave side */
2.6, 15-Sep-2000, update
- implemented USE_STREAMSPTY
3.2, 22-Sep-2000, update
- disabled local ECHO on master
- conditionally (#ifdef HP49_SUPPORT) disabled local ECHO on master
pty when USE_OPENPTY is in effect; this avoid spurious rx
when no process is connected to the slave pty yet.
3.16, 16-Nov-2000, update
@ -505,7 +523,7 @@ static int slave_pty; /* File descriptor of pty's slave side */
.- */
const char* SerialInit( void )
{
debug1( SERIAL_CHF_MODULE_ID, DEBUG_C_TRACE, SERIAL_I_CALLED, "SerialInit" );
debug1( DEBUG_C_TRACE, SERIAL_I_CALLED, "SerialInit" );
/* Initialize ring buffers */
InitRingBuffer( rrb );
@ -519,9 +537,9 @@ const char* SerialInit( void )
if ( openpty( &master_pty, &slave_pty, NULL, NULL, NULL ) ) {
pty_name = ( char* )NULL;
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( SERIAL_CHF_MODULE_ID, __FILE__, __LINE__, SERIAL_F_OPENPTY, CHF_FATAL );
ChfSignal( SERIAL_CHF_MODULE_ID );
ChfErrnoCondition;
ChfCondition SERIAL_F_OPENPTY, CHF_FATAL ChfEnd;
ChfSignal();
} else {
int cur_flags;
@ -532,9 +550,9 @@ const char* SerialInit( void )
/* Set O_NONBLOCK on master_pty */
if ( ( cur_flags = fcntl( master_pty, F_GETFL, 0 ) ) < 0 || fcntl( master_pty, F_SETFL, cur_flags | O_NONBLOCK ) < 0 ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( SERIAL_CHF_MODULE_ID, __FILE__, __LINE__, SERIAL_F_FCNTL, CHF_FATAL );
ChfSignal( SERIAL_CHF_MODULE_ID );
ChfErrnoCondition;
ChfCondition SERIAL_F_FCNTL, CHF_FATAL ChfEnd;
ChfSignal();
}
}
# endif
@ -544,30 +562,30 @@ const char* SerialInit( void )
if ( ( master_pty = open( PTY_MASTER, O_RDWR | O_NONBLOCK ) ) < 0 ) {
pty_name = ( char* )NULL;
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( SERIAL_CHF_MODULE_ID, __FILE__, __LINE__, SERIAL_F_OPEN_MASTER, CHF_FATAL, PTY_MASTER );
ChfSignal( SERIAL_CHF_MODULE_ID );
ChfErrnoCondition;
ChfCondition SERIAL_F_OPEN_MASTER, CHF_FATAL, PTY_MASTER ChfEnd;
ChfSignal();
} else {
/* Master side opened ok; change permissions and unlock slave side */
if ( grantpt( master_pty ) < 0 ) {
/* close() may modify errno; save it first */
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfErrnoCondition;
( void )close( master_pty );
ChfGenerate( SERIAL_CHF_MODULE_ID, __FILE__, __LINE__, SERIAL_F_GRANTPT, CHF_FATAL );
ChfSignal( SERIAL_CHF_MODULE_ID );
ChfCondition SERIAL_F_GRANTPT, CHF_FATAL ChfEnd;
ChfSignal();
}
if ( unlockpt( master_pty ) < 0 ) {
/* close() may modify errno; save it first */
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfErrnoCondition;
( void )close( master_pty );
ChfGenerate( SERIAL_CHF_MODULE_ID, __FILE__, __LINE__, SERIAL_F_UNLOCKPT, CHF_FATAL );
ChfSignal( SERIAL_CHF_MODULE_ID );
ChfCondition SERIAL_F_UNLOCKPT, CHF_FATAL ChfEnd;
ChfSignal();
}
/* Get name of slave side; this must be done on the *master* side */
@ -576,12 +594,12 @@ const char* SerialInit( void )
/* Open slave in nonblocking mode */
if ( ( slave_pty = open( pty_name, O_RDWR | O_NONBLOCK ) ) < 0 ) {
/* close() may modify errno; save it first */
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfErrnoCondition;
( void )close( master_pty );
ChfGenerate( SERIAL_CHF_MODULE_ID, __FILE__, __LINE__, SERIAL_F_OPEN_SLAVE, CHF_FATAL, pty_name );
ChfSignal( SERIAL_CHF_MODULE_ID );
ChfCondition SERIAL_F_OPEN_SLAVE, CHF_FATAL, pty_name ChfEnd;
ChfSignal();
}
/* Remember: close the pty before exiting */
@ -592,19 +610,20 @@ const char* SerialInit( void )
indistinguishable from a real terminal.
*/
if ( ioctl( slave_pty, I_PUSH, "ptem" ) == -1 ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( SERIAL_CHF_MODULE_ID, __FILE__, __LINE__, SERIAL_F_PUSH, CHF_FATAL, "ptem" );
ChfSignal( SERIAL_CHF_MODULE_ID );
ChfErrnoCondition;
ChfCondition SERIAL_F_PUSH, CHF_FATAL, "ptem" ChfEnd;
ChfSignal();
}
if ( ioctl( slave_pty, I_PUSH, "ldterm" ) == -1 ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( SERIAL_CHF_MODULE_ID, __FILE__, __LINE__, SERIAL_F_PUSH, CHF_FATAL, "ldterm" );
ChfSignal( SERIAL_CHF_MODULE_ID );
ChfErrnoCondition;
ChfCondition SERIAL_F_PUSH, CHF_FATAL, "ldterm" ChfEnd;
ChfSignal();
}
}
# endif
# ifdef HP49_SUPPORT
/* 3.17: Ensure that the pty is fully trasparent by default.
This allows to use most non-terminal-aware applications (such as od)
on the pty directly.
@ -613,9 +632,9 @@ const char* SerialInit( void )
struct termios tios;
if ( tcgetattr( slave_pty, &tios ) ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( SERIAL_CHF_MODULE_ID, __FILE__, __LINE__, SERIAL_F_TCGETATTR, CHF_FATAL );
ChfSignal( SERIAL_CHF_MODULE_ID );
ChfErrnoCondition;
ChfCondition SERIAL_F_TCGETATTR, CHF_FATAL ChfEnd;
ChfSignal();
}
tios.c_iflag &= ~( BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IUCLC | IXON | IXANY | IXOFF | IMAXBEL );
@ -638,24 +657,23 @@ const char* SerialInit( void )
tios.c_cc[ VTIME ] = 0;
if ( tcsetattr( slave_pty, TCSANOW, &tios ) ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( SERIAL_CHF_MODULE_ID, __FILE__, __LINE__, SERIAL_F_TCSETATTR, CHF_FATAL );
ChfSignal( SERIAL_CHF_MODULE_ID );
ChfErrnoCondition;
ChfCondition SERIAL_F_TCSETATTR, CHF_FATAL ChfEnd;
ChfSignal();
}
}
# endif
/* Publish pty name */
if ( config.verbose ) {
ChfGenerate( SERIAL_CHF_MODULE_ID, __FILE__, __LINE__, SERIAL_I_PTY_NAME, CHF_INFO, pty_name );
ChfSignal( SERIAL_CHF_MODULE_ID );
}
ChfCondition SERIAL_I_PTY_NAME, CHF_INFO, pty_name ChfEnd;
ChfSignal();
#else
/* Dummy implementation; do nothing */
pty_name = "";
ChfGenerate( SERIAL_CHF_MODULE_ID, __FILE__, __LINE__, SERIAL_W_NOPTY, CHF_WARNING );
ChfSignal( SERIAL_CHF_MODULE_ID );
ChfCondition SERIAL_W_NOPTY, CHF_WARNING ChfEnd;
ChfSignal();
#endif
return pty_name;
@ -691,12 +709,12 @@ const char* SerialInit( void )
.- */
void SerialClose( void )
{
debug1( SERIAL_CHF_MODULE_ID, DEBUG_C_TRACE, SERIAL_I_CALLED, "SerialClose" );
debug1( DEBUG_C_TRACE, SERIAL_I_CALLED, "SerialClose" );
if ( close( slave_pty ) || close( master_pty ) ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( SERIAL_CHF_MODULE_ID, __FILE__, __LINE__, SERIAL_E_PTY_CLOSE, CHF_ERROR );
ChfSignal( SERIAL_CHF_MODULE_ID );
ChfErrnoCondition;
ChfCondition SERIAL_E_PTY_CLOSE, CHF_ERROR ChfEnd;
ChfSignal();
}
}
@ -728,7 +746,7 @@ void SerialClose( void )
.- */
const char* SerialPtyName( void )
{
debug1( SERIAL_CHF_MODULE_ID, DEBUG_C_TRACE, SERIAL_I_CALLED, "SerialPtyName" );
debug1( DEBUG_C_TRACE, SERIAL_I_CALLED, "SerialPtyName" );
return pty_name;
}
@ -760,8 +778,8 @@ const char* SerialPtyName( void )
.- */
Nibble Serial_IOC_Read( void )
{
debug1( SERIAL_CHF_MODULE_ID, DEBUG_C_TRACE, SERIAL_I_CALLED, "Serial_IOC_Read" );
debug2( SERIAL_CHF_MODULE_ID, DEBUG_C_SERIAL, SERIAL_I_READ, "IOC", ioc );
debug1( DEBUG_C_TRACE, SERIAL_I_CALLED, "Serial_IOC_Read" );
debug2( DEBUG_C_SERIAL, SERIAL_I_READ, "IOC", ioc );
return ioc;
}
@ -793,8 +811,8 @@ Nibble Serial_IOC_Read( void )
.- */
Nibble Serial_RCS_Read( void )
{
debug1( SERIAL_CHF_MODULE_ID, DEBUG_C_TRACE, SERIAL_I_CALLED, "Serial_RCS_Read" );
debug2( SERIAL_CHF_MODULE_ID, DEBUG_C_SERIAL, SERIAL_I_READ, "RCS", rcs );
debug1( DEBUG_C_TRACE, SERIAL_I_CALLED, "Serial_RCS_Read" );
debug2( DEBUG_C_SERIAL, SERIAL_I_READ, "RCS", rcs );
return rcs;
}
@ -826,8 +844,8 @@ Nibble Serial_RCS_Read( void )
.- */
Nibble Serial_TCS_Read( void )
{
debug1( SERIAL_CHF_MODULE_ID, DEBUG_C_TRACE, SERIAL_I_CALLED, "Serial_TCS_Read" );
debug2( SERIAL_CHF_MODULE_ID, DEBUG_C_SERIAL, SERIAL_I_READ, "TCS", tcs );
debug1( DEBUG_C_TRACE, SERIAL_I_CALLED, "Serial_TCS_Read" );
debug2( DEBUG_C_SERIAL, SERIAL_I_READ, "TCS", tcs );
return tcs;
}
@ -859,14 +877,14 @@ Nibble Serial_TCS_Read( void )
.notes :
2.5, 13-Sep-2000, creation
3.2, 22-Sep-2000, update
- removed warning message
- conditionally (#ifdef HP49_SUPPORT) removed warning message
when reading from an empty RRB.
.- */
int8 Serial_RBR_Read( void )
{
int8 rx;
debug1( SERIAL_CHF_MODULE_ID, DEBUG_C_TRACE, SERIAL_I_CALLED, "Serial_RBR_Read" );
debug1( DEBUG_C_TRACE, SERIAL_I_CALLED, "Serial_RBR_Read" );
/* Pull one character from rbr, if not empty */
if ( FullSlots( rrb ) > 0 ) {
@ -874,6 +892,14 @@ int8 Serial_RBR_Read( void )
} else {
/* rrb is empty */
#ifndef HP49_SUPPORT
/* 3.2: The HP49 firmware (1.19-4) can read from an empty RRB;
this is not harmful, and this warning can be removed.
*/
ChfCondition SERIAL_W_EMPTY_RRB, CHF_WARNING, rcs ChfEnd;
ChfSignal();
#endif
rx = ( int8 )0xFF;
}
@ -883,7 +909,7 @@ int8 Serial_RBR_Read( void )
/* Post a new IRQ if necessary */
CheckIRQ;
debug1( SERIAL_CHF_MODULE_ID, DEBUG_C_SERIAL, SERIAL_I_RBR, rx );
debug1( DEBUG_C_SERIAL, SERIAL_I_RBR, rx );
return rx;
}
@ -915,8 +941,8 @@ int8 Serial_RBR_Read( void )
.- */
void Serial_IOC_Write( Nibble n )
{
debug1( SERIAL_CHF_MODULE_ID, DEBUG_C_TRACE, SERIAL_I_CALLED, "Serial_IOC_Write" );
debug3( SERIAL_CHF_MODULE_ID, DEBUG_C_SERIAL, SERIAL_I_WRITE, "IOC", ioc, n );
debug1( DEBUG_C_TRACE, SERIAL_I_CALLED, "Serial_IOC_Write" );
debug3( DEBUG_C_SERIAL, SERIAL_I_WRITE, "IOC", ioc, n );
ioc = n;
@ -950,8 +976,8 @@ void Serial_IOC_Write( Nibble n )
.- */
void Serial_RCS_Write( Nibble n )
{
debug1( SERIAL_CHF_MODULE_ID, DEBUG_C_TRACE, SERIAL_I_CALLED, "Serial_RCS_Write" );
debug3( SERIAL_CHF_MODULE_ID, DEBUG_C_SERIAL, SERIAL_I_WRITE, "RCS", rcs, n );
debug1( DEBUG_C_TRACE, SERIAL_I_CALLED, "Serial_RCS_Write" );
debug3( DEBUG_C_SERIAL, SERIAL_I_WRITE, "RCS", rcs, n );
rcs = n;
}
@ -983,8 +1009,8 @@ void Serial_RCS_Write( Nibble n )
.- */
void Serial_TCS_Write( Nibble n )
{
debug1( SERIAL_CHF_MODULE_ID, DEBUG_C_TRACE, SERIAL_I_CALLED, "Serial_TCS_Write" );
debug3( SERIAL_CHF_MODULE_ID, DEBUG_C_SERIAL, SERIAL_I_WRITE, "TCS", tcs, n );
debug1( DEBUG_C_TRACE, SERIAL_I_CALLED, "Serial_TCS_Write" );
debug3( DEBUG_C_SERIAL, SERIAL_I_WRITE, "TCS", tcs, n );
tcs = n;
}
@ -1015,8 +1041,8 @@ void Serial_TCS_Write( Nibble n )
.- */
void Serial_CRER_Write( Nibble n )
{
debug1( SERIAL_CHF_MODULE_ID, DEBUG_C_TRACE, SERIAL_I_CALLED, "Serial_CRER_Write" );
debug3( SERIAL_CHF_MODULE_ID, DEBUG_C_SERIAL, SERIAL_I_WRITE, "CRER", 0, n );
debug1( DEBUG_C_TRACE, SERIAL_I_CALLED, "Serial_CRER_Write" );
debug3( DEBUG_C_SERIAL, SERIAL_I_WRITE, "CRER", 0, n );
rcs &= ~RCS_RER;
}
@ -1051,16 +1077,16 @@ void Serial_CRER_Write( Nibble n )
.- */
void Serial_TBR_Write( int8 d )
{
debug1( SERIAL_CHF_MODULE_ID, DEBUG_C_TRACE, SERIAL_I_CALLED, "Serial_TBR_Write" );
debug1( SERIAL_CHF_MODULE_ID, DEBUG_C_SERIAL, SERIAL_I_TBR, d );
debug1( DEBUG_C_TRACE, SERIAL_I_CALLED, "Serial_TBR_Write" );
debug1( DEBUG_C_SERIAL, SERIAL_I_TBR, d );
/* Pull one character from rbr, if not empty */
if ( EmptySlots( trb ) > 0 ) {
Push( trb, d );
} else {
/* trb is full; discard character */
ChfGenerate( SERIAL_CHF_MODULE_ID, __FILE__, __LINE__, SERIAL_W_FULL_TRB, CHF_WARNING, tcs );
ChfSignal( SERIAL_CHF_MODULE_ID );
ChfCondition SERIAL_W_FULL_TRB, CHF_WARNING, tcs ChfEnd;
ChfSignal();
}
/* Update transmitter status */
@ -1112,7 +1138,7 @@ void HandleSerial( void )
{
int result;
debug1( SERIAL_CHF_MODULE_ID, DEBUG_C_TRACE, SERIAL_I_CALLED, "HandleSerial" );
debug1( DEBUG_C_TRACE, SERIAL_I_CALLED, "HandleSerial" );
#ifndef USE_NOPTY
/* Attempt to drain transmitter buffer even if serial port is closed */
@ -1120,9 +1146,9 @@ void HandleSerial( void )
/* Signal a condition upon failure */
if ( result < 0 ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( SERIAL_CHF_MODULE_ID, __FILE__, __LINE__, SERIAL_E_TRB_DRAIN, CHF_ERROR );
ChfSignal( SERIAL_CHF_MODULE_ID );
ChfErrnoCondition;
ChfCondition SERIAL_E_TRB_DRAIN, CHF_ERROR ChfEnd;
ChfSignal();
}
/* Update tcs */
@ -1134,9 +1160,9 @@ void HandleSerial( void )
/* Signal a condition upon failure */
if ( result < 0 ) {
ChfGenerate( CHF_ERRNO_SET, __FILE__, __LINE__, errno, CHF_ERROR );
ChfGenerate( SERIAL_CHF_MODULE_ID, __FILE__, __LINE__, SERIAL_E_RRB_CHARGE, CHF_ERROR );
ChfSignal( SERIAL_CHF_MODULE_ID );
ChfErrnoCondition;
ChfCondition SERIAL_E_RRB_CHARGE, CHF_ERROR ChfEnd;
ChfSignal();
}
/* Update receiver status */

172
src/ui48_bitmaps_big_font.h Normal file
View file

@ -0,0 +1,172 @@
#ifndef _UI48_BITMAPS_BIG_FONT_H
#define _UI48_BITMAPS_BIG_FONT_H 1
#define big_font_dot_width 8
#define big_font_dot_height 13
static unsigned char big_font_dot_bits[] = {
0, 0, 0, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0,
};
#define big_font_0_width 8
#define big_font_0_height 13
static unsigned char big_font_0_bits[] = {
24, 60, 102, 102, 195, 195, 195, 195, 195, 102, 102, 60, 24,
};
#define big_font_1_width 8
#define big_font_1_height 13
static unsigned char big_font_1_bits[] = {
24, 28, 30, 27, 24, 24, 24, 24, 24, 24, 24, 24, 255,
};
#define big_font_2_width 8
#define big_font_2_height 13
static unsigned char big_font_2_bits[] = {
60, 102, 195, 195, 192, 192, 96, 56, 12, 6, 3, 3, 255,
};
#define big_font_3_width 8
#define big_font_3_height 13
static unsigned char big_font_3_bits[] = {
60, 102, 195, 195, 192, 96, 56, 96, 192, 195, 195, 102, 60,
};
#define big_font_4_width 8
#define big_font_4_height 13
static unsigned char big_font_4_bits[] = {
96, 112, 120, 108, 102, 99, 99, 255, 96, 96, 96, 96, 96,
};
#define big_font_5_width 8
#define big_font_5_height 13
static unsigned char big_font_5_bits[] = {
255, 3, 3, 3, 3, 59, 103, 192, 192, 192, 195, 102, 60,
};
#define big_font_6_width 8
#define big_font_6_height 13
static unsigned char big_font_6_bits[] = {
60, 102, 67, 3, 3, 59, 103, 195, 195, 195, 195, 102, 60,
};
#define big_font_7_width 8
#define big_font_7_height 13
static unsigned char big_font_7_bits[] = {
255, 192, 192, 96, 96, 48, 48, 24, 24, 12, 12, 6, 6,
};
#define big_font_8_width 8
#define big_font_8_height 13
static unsigned char big_font_8_bits[] = {
60, 102, 195, 195, 195, 102, 60, 102, 195, 195, 195, 102, 60,
};
#define big_font_9_width 8
#define big_font_9_height 13
static unsigned char big_font_9_bits[] = {
62, 195, 195, 195, 195, 195, 230, 220, 192, 192, 194, 102, 60,
};
#define big_font_A_width 8
#define big_font_A_height 10
static unsigned char big_font_A_bits[] = {
30, 51, 51, 51, 51, 51, 63, 51, 51, 51,
};
#define big_font_C_width 8
#define big_font_C_height 10
static unsigned char big_font_C_bits[] = {
30, 51, 51, 3, 3, 3, 3, 51, 51, 30,
};
#define big_font_D_width 8
#define big_font_D_height 10
static unsigned char big_font_D_bits[] = {
15, 27, 51, 51, 51, 51, 51, 51, 27, 15,
};
#define big_font_E_width 8
#define big_font_E_height 10
static unsigned char big_font_E_bits[] = {
63, 3, 3, 3, 31, 3, 3, 3, 3, 63,
};
#define big_font_G_width 8
#define big_font_G_height 10
static unsigned char big_font_G_bits[] = {
30, 51, 51, 3, 3, 59, 51, 51, 51, 30,
};
#define big_font_H_width 8
#define big_font_H_height 10
static unsigned char big_font_H_bits[] = {
51, 51, 51, 51, 63, 51, 51, 51, 51, 51,
};
#define big_font_I_width 8
#define big_font_I_height 10
static unsigned char big_font_I_bits[] = {
63, 12, 12, 12, 12, 12, 12, 12, 12, 63,
};
#define big_font_L_width 8
#define big_font_L_height 10
static unsigned char big_font_L_bits[] = {
3, 3, 3, 3, 3, 3, 3, 3, 3, 63,
};
#define big_font_M_width 8
#define big_font_M_height 10
static unsigned char big_font_M_bits[] = {
33, 51, 51, 63, 63, 51, 51, 51, 51, 51,
};
#define big_font_N_width 8
#define big_font_N_height 10
static unsigned char big_font_N_bits[] = {
51, 51, 55, 55, 55, 59, 59, 59, 51, 51,
};
#define big_font_O_width 8
#define big_font_O_height 10
static unsigned char big_font_O_bits[] = {
30, 51, 51, 51, 51, 51, 51, 51, 51, 30,
};
#define big_font_P_width 8
#define big_font_P_height 10
static unsigned char big_font_P_bits[] = {
31, 51, 51, 51, 51, 31, 3, 3, 3, 3,
};
#define big_font_R_width 8
#define big_font_R_height 10
static unsigned char big_font_R_bits[] = {
31, 51, 51, 51, 31, 27, 51, 51, 51, 51,
};
#define big_font_S_width 8
#define big_font_S_height 10
static unsigned char big_font_S_bits[] = {
30, 51, 51, 6, 12, 12, 24, 51, 51, 30,
};
#define big_font_T_width 8
#define big_font_T_height 10
static unsigned char big_font_T_bits[] = {
63, 12, 12, 12, 12, 12, 12, 12, 12, 12,
};
#define big_font_V_width 8
#define big_font_V_height 10
static unsigned char big_font_V_bits[] = {
51, 51, 51, 51, 51, 51, 51, 30, 30, 12,
};
#define big_font_X_width 8
#define big_font_X_height 10
static unsigned char big_font_X_bits[] = {
51, 51, 30, 30, 12, 12, 30, 30, 51, 51,
};
#endif /* _UI48_BITMAPS_BIG_FONT_H 1 */

View file

@ -1,5 +1,5 @@
#ifndef _UI4x_BITMAPS_MISC_H
#define _UI4x_BITMAPS_MISC_H 1
#ifndef _UI48_BITMAPS_MISC_H
#define _UI48_BITMAPS_MISC_H 1
#define hp_width 96
#define hp_height 24
@ -221,4 +221,4 @@ static unsigned char last_bitmap[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
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 };
#endif /* _UI4x_BITMAPS_MISC_H 1 */
#endif /* _UI48_BITMAPS_MISC_H 1 */

View file

@ -0,0 +1,423 @@
#ifndef _UI48_BITMAPS_SMALL_FONT_H
#define _UI48_BITMAPS_SMALL_FONT_H 1
#define blank_width 4
#define blank_height 7
static unsigned char blank_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
#define hash_width 5
#define hash_height 7
static unsigned char hash_bits[] = { 0x00, 0x0a, 0x1f, 0x0a, 0x0a, 0x1f, 0x0a };
#define lbrace_width 3
#define lbrace_height 7
static unsigned char lbrace_bits[] = { 0x04, 0x02, 0x01, 0x01, 0x01, 0x02, 0x04 };
#define rbrace_width 3
#define rbrace_height 7
static unsigned char rbrace_bits[] = { 0x01, 0x02, 0x04, 0x04, 0x04, 0x02, 0x01 };
#define comma_width 3
#define comma_height 7
static unsigned char comma_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x03 };
#define slash_width 3
#define slash_height 7
static unsigned char slash_bits[] = { 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01 };
#define zero_width 5
#define zero_height 7
static unsigned char zero_bits[] = {
14, 17, 25, 21, 19, 17, 14,
};
#define one_width 5
#define one_height 7
static unsigned char one_bits[] = {
4, 6, 5, 4, 4, 4, 31,
};
#define two_width 5
#define two_height 7
static unsigned char two_bits[] = { 0x0e, 0x11, 0x10, 0x08, 0x04, 0x02, 0x1f };
#define three_width 5
#define three_height 7
static unsigned char three_bits[] = { 0x0e, 0x11, 0x10, 0x0c, 0x10, 0x11, 0x0e };
#define four_width 5
#define four_height 7
static unsigned char four_bits[] = {
8, 12, 10, 9, 31, 8, 8,
};
#define five_width 5
#define five_height 7
static unsigned char five_bits[] = {
31, 1, 1, 15, 16, 16, 15,
};
#define six_width 5
#define six_height 7
static unsigned char six_bits[] = {
14, 17, 1, 15, 17, 17, 14,
};
#define seven_width 5
#define seven_height 7
static unsigned char seven_bits[] = {
31, 16, 8, 4, 2, 1, 1,
};
#define eight_width 5
#define eight_height 7
static unsigned char eight_bits[] = {
14, 17, 17, 14, 17, 17, 14,
};
#define nine_width 5
#define nine_height 7
static unsigned char nine_bits[] = {
14, 17, 17, 30, 16, 17, 14,
};
#define small_colon_width 2
#define small_colon_height 7
static unsigned char small_colon_bits[] = { 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x00 };
#define d_width 5
#define d_height 7
static unsigned char d_bits[] = {
16, 16, 30, 17, 17, 30, 0,
};
#define e_width 5
#define e_height 7
static unsigned char e_bits[] = {
0, 14, 17, 15, 1, 14, 0,
};
#define i_width 5
#define i_height 7
static unsigned char i_bits[] = {
4, 0, 6, 4, 4, 14, 0,
};
#define p_width 5
#define p_height 7
static unsigned char p_bits[] = {
0, 15, 17, 17, 15, 1, 1,
};
#define r_width 5
#define r_height 7
static unsigned char r_bits[] = {
0, 29, 3, 1, 1, 1, 0,
};
#define s_width 5
#define s_height 7
static unsigned char s_bits[] = {
0, 30, 1, 14, 16, 15, 0,
};
#define t_width 5
#define t_height 7
static unsigned char t_bits[] = {
2, 15, 2, 2, 2, 12, 0,
};
#define v_width 5
#define v_height 7
static unsigned char v_bits[] = {
0, 17, 17, 10, 10, 4, 0,
};
#define w_width 5
#define w_height 7
static unsigned char w_bits[] = {
0, 17, 17, 21, 21, 10, 0,
};
#define y_width 5
#define y_height 7
static unsigned char y_bits[] = {
0, 0, 17, 17, 30, 16, 15,
};
#define A_width 5
#define A_height 7
static unsigned char A_bits[] = { 0x0e, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11 };
#define B_width 5
#define B_height 7
static unsigned char B_bits[] = { 0x0f, 0x11, 0x11, 0x0f, 0x11, 0x11, 0x0f };
#define C_width 5
#define C_height 7
static unsigned char C_bits[] = { 0x0e, 0x11, 0x01, 0x01, 0x01, 0x11, 0x0e };
#define D_width 5
#define D_height 7
static unsigned char D_bits[] = { 0x0f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0f };
#define E_width 5
#define E_height 7
static unsigned char E_bits[] = { 0x1f, 0x01, 0x01, 0x0f, 0x01, 0x01, 0x1f };
#define F_width 5
#define F_height 7
static unsigned char F_bits[] = { 0x1f, 0x01, 0x01, 0x0f, 0x01, 0x01, 0x01 };
#define G_width 5
#define G_height 7
static unsigned char G_bits[] = { 0x0e, 0x11, 0x01, 0x01, 0x19, 0x11, 0x0e };
#define H_width 5
#define H_height 7
static unsigned char H_bits[] = { 0x11, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11 };
#define I_width 1
#define I_height 7
static unsigned char I_bits[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
#define J_width 4
#define J_height 7
static unsigned char J_bits[] = { 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x06 };
#define K_width 5
#define K_height 7
static unsigned char K_bits[] = { 0x11, 0x09, 0x05, 0x03, 0x05, 0x09, 0x11 };
#define L_width 4
#define L_height 7
static unsigned char L_bits[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0f };
#define M_width 5
#define M_height 7
static unsigned char M_bits[] = { 0x11, 0x1b, 0x15, 0x11, 0x11, 0x11, 0x11 };
#define N_width 5
#define N_height 7
static unsigned char N_bits[] = { 0x11, 0x11, 0x13, 0x15, 0x19, 0x11, 0x11 };
#define O_width 5
#define O_height 7
static unsigned char O_bits[] = { 0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e };
#define P_width 5
#define P_height 7
static unsigned char P_bits[] = { 0x0f, 0x11, 0x11, 0x0f, 0x01, 0x01, 0x01 };
#define Q_width 5
#define Q_height 7
static unsigned char Q_bits[] = { 0x0e, 0x11, 0x11, 0x11, 0x15, 0x09, 0x16 };
#define R_width 5
#define R_height 7
static unsigned char R_bits[] = { 0x0f, 0x11, 0x11, 0x0f, 0x05, 0x09, 0x11 };
#define S_width 5
#define S_height 7
static unsigned char S_bits[] = { 0x0e, 0x11, 0x01, 0x0e, 0x10, 0x11, 0x0e };
#define T_width 5
#define T_height 7
static unsigned char T_bits[] = { 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
#define U_width 5
#define U_height 7
static unsigned char U_bits[] = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e };
#define V_width 5
#define V_height 7
static unsigned char V_bits[] = { 0x11, 0x11, 0x11, 0x11, 0x0a, 0x0a, 0x04 };
#define W_width 5
#define W_height 7
static unsigned char W_bits[] = { 0x11, 0x11, 0x11, 0x11, 0x15, 0x1b, 0x11 };
#define X_width 5
#define X_height 7
static unsigned char X_bits[] = { 0x11, 0x11, 0x0a, 0x04, 0x0a, 0x11, 0x11 };
#define Y_width 5
#define Y_height 7
static unsigned char Y_bits[] = { 0x11, 0x11, 0x0a, 0x04, 0x04, 0x04, 0x04 };
#define Z_width 5
#define Z_height 7
static unsigned char Z_bits[] = { 0x1f, 0x10, 0x08, 0x04, 0x02, 0x01, 0x1f };
#define lbracket_width 3
#define lbracket_height 7
static unsigned char lbracket_bits[] = { 0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07 };
#define rbracket_width 3
#define rbracket_height 7
static unsigned char rbracket_bits[] = { 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07 };
#define arrow_width 7
#define arrow_height 7
static unsigned char arrow_bits[] = { 0x00, 0x08, 0x18, 0x3f, 0x18, 0x08, 0x00 };
#define diff_width 5
#define diff_height 7
static unsigned char diff_bits[] = { 0x0e, 0x10, 0x10, 0x1e, 0x11, 0x11, 0x0e };
#define integral_width 5
#define integral_height 8
static unsigned char integral_bits[] = { 0x0c, 0x12, 0x02, 0x04, 0x04, 0x08, 0x09, 0x06 };
#define sigma_width 6
#define sigma_height 9
static unsigned char sigma_bits[] = { 0x3f, 0x21, 0x02, 0x04, 0x08, 0x04, 0x02, 0x21, 0x3f };
#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 };
#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 };
#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 };
#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 };
#define under_width 6
#define under_height 7
static unsigned char under_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f };
#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 };
#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 };
#define equal_width 5
#define equal_height 7
static unsigned char equal_bits[] = { 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00 };
#define nl_width 8
#define nl_height 7
static unsigned char nl_bits[] = { 0x00, 0x84, 0x86, 0xff, 0x06, 0x04, 0x00 };
#define pi_width 6
#define pi_height 7
static unsigned char pi_bits[] = { 0x20, 0x1f, 0x12, 0x12, 0x12, 0x12, 0x12 };
#define angle_width 8
#define angle_height 7
static unsigned char angle_bits[] = { 0x40, 0x20, 0x10, 0x28, 0x44, 0x42, 0xff };
#define lcurly_width 5
#define lcurly_height 7
static unsigned char lcurly_bits[] = { 0x18, 0x04, 0x04, 0x02, 0x04, 0x04, 0x18 };
#define rcurly_width 5
#define rcurly_height 7
static unsigned char rcurly_bits[] = { 0x03, 0x04, 0x04, 0x08, 0x04, 0x04, 0x03 };
#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 };
#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 };
#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 };
#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 };
#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 };
#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 };
#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 };
#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 };
#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 };
#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 };
#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 };
#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 };
#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 };
#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 };
#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 };
#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 };
#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 };
#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 };
#endif /* _UI48_BITMAPS_SMALL_FONT_H 1 */

2291
src/ui48_common.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
#ifndef _UI4x_COMMON_H
#define _UI4x_COMMON_H 1
#ifndef _UI48_COMMON_H
#define _UI48_COMMON_H 1
#include "config.h"
#include "ui48_config.h"
/*************************************************/
/* public API: if it's there it's used elsewhere */
@ -15,4 +15,4 @@ extern void ( *ui_stop )( void );
extern void setup_ui( config_t* config );
extern void close_and_exit( void );
#endif /* !_UI4x_COMMON_H */
#endif /* !_UI48_COMMON_H */

271
src/ui48_config.c Normal file
View file

@ -0,0 +1,271 @@
#include <assert.h>
#include <errno.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <getopt.h>
#include "ui48_config.h"
static config_t config = {
.progname = ( char* )"ui48",
.model = MODEL_48GX,
.verbose = false,
.shiftless = false,
.frontend = FRONTEND_SDL,
.mono = false,
.gray = false,
.chromeless = false,
.fullscreen = false,
.scale = 1.0,
.tiny = false,
.small = false,
.wire_name = ( char* )"/dev/wire",
.ir_name = ( char* )"/dev/ir",
/* from args.h */
.reset = false,
.monitor = false,
.batchXfer = false,
.state_dir_path = ( char* )".",
.mod_file_name = ( char* )"mod",
.cpu_file_name = ( char* )"cpu",
.hdw_file_name = ( char* )"hdw",
.rom_file_name = ( char* )"rom",
.ram_file_name = ( char* )"ram",
.port_1_file_name = ( char* )"port1",
.port_2_file_name = ( char* )"port2",
.hw = ( char* )"hp48", /* 2.1: Hardware configuration (unused) */
};
/* Path/name dynamic allocator */
/* static char* GetPathname( char* path, char* name ) */
/* { */
/* char* s = malloc( strlen( path ) + strlen( name ) + 2 ); */
/* strcpy( s, path ); */
/* strcat( s, "/" ); */
/* strcat( s, name ); */
/* return s; */
/* } */
config_t* config_init( int argc, char* argv[] )
{
int option_index;
int c = '?';
int clopt_model = -1;
int clopt_verbose = -1;
int clopt_shiftless = -1;
int clopt_frontend = -1;
int clopt_mono = -1;
int clopt_gray = -1;
int clopt_chromeless = -1;
int clopt_fullscreen = -1;
double clopt_scale = -1.0;
int clopt_tiny = -1;
int clopt_small = -1;
int clopt_reset = -1;
int clopt_monitor = -1;
int clopt_batchXfer = -1;
char* clopt_state_dir_path;
char* clopt_mod_file_name;
char* clopt_cpu_file_name;
char* clopt_hdw_file_name;
char* clopt_rom_file_name;
char* clopt_ram_file_name;
char* clopt_port_1_file_name;
char* clopt_port_2_file_name;
char* clopt_hw;
const char* optstring = "h";
struct option long_options[] = {
{"help", no_argument, NULL, 'h' },
{"48sx", no_argument, &clopt_model, MODEL_48SX },
{"48gx", no_argument, &clopt_model, MODEL_48GX },
{"40g", no_argument, &clopt_model, MODEL_40G },
{"49g", no_argument, &clopt_model, MODEL_49G },
{"verbose", no_argument, &clopt_verbose, true },
{"shiftless", no_argument, &clopt_shiftless, true },
{"gui", no_argument, &clopt_frontend, FRONTEND_SDL },
{"tui", no_argument, &clopt_frontend, FRONTEND_NCURSES},
{"tui-small", no_argument, NULL, 6110 },
{"tui-tiny", no_argument, NULL, 6120 },
{"mono", no_argument, &clopt_mono, true },
{"gray", no_argument, &clopt_gray, true },
{"chromeless", no_argument, &clopt_chromeless, true },
{"fullscreen", no_argument, &clopt_fullscreen, true },
{"scale", required_argument, NULL, 7110 },
{"reset", no_argument, &clopt_reset, true },
{"monitor", no_argument, &clopt_monitor, true },
{"batchXfer", no_argument, &clopt_batchXfer, true },
{"state-dir", required_argument, NULL, 8999 },
{"mod", required_argument, NULL, 8000 },
{"cpu", required_argument, NULL, 8010 },
{"hdw", required_argument, NULL, 8020 },
{"rom", required_argument, NULL, 8030 },
{"ram", required_argument, NULL, 8040 },
{"port1", required_argument, NULL, 8050 },
{"port2", required_argument, NULL, 8060 },
{"hw", required_argument, NULL, 8070 },
{0, 0, 0, 0 }
};
const char* help_text = "usage: %s [options]\n"
"options:\n"
" -h --help what you are reading\n"
" --gui graphical (SDL2) front-end (default: true)\n"
" --tui text front-end (default: false)\n"
" --tui-small text small front-end (2×2 pixels per character) (default: "
"false)\n"
" --tui-tiny text tiny front-end (2×4 pixels per character) (default: "
"false)\n"
" --chromeless only show display (default: "
"false)\n"
" --fullscreen make the UI fullscreen "
"(default: false)\n"
" --scale=<n> make the UI scale <n> times "
"(default: 1.0)\n"
" --mono make the UI monochrome (default: "
"false)\n"
" --gray make the UI grayscale (default: "
"false)\n"
" --48gx make the GUI looks like a HP 48GX (default: "
"auto)\n"
" --48sx make the GUI looks like a HP 48SX (default: "
"auto)\n"
" --shiftless don't map the shift keys to let them free for numbers (default: "
"false)\n";
while ( c != EOF ) {
c = getopt_long( argc, argv, optstring, long_options, &option_index );
switch ( c ) {
case 'h':
fprintf( stderr, help_text, config.progname );
exit( 0 );
break;
case 6110:
clopt_frontend = FRONTEND_NCURSES;
clopt_small = true;
break;
case 6120:
clopt_frontend = FRONTEND_NCURSES;
clopt_tiny = true;
break;
case 7110:
clopt_scale = atof( optarg );
break;
case 8999:
clopt_state_dir_path = optarg;
break;
case 8000:
clopt_mod_file_name = optarg;
break;
case 8010:
clopt_cpu_file_name = optarg;
break;
case 8020:
clopt_hdw_file_name = optarg;
break;
case 8030:
clopt_rom_file_name = optarg;
break;
case 8040:
clopt_ram_file_name = optarg;
break;
case 8050:
clopt_port_1_file_name = optarg;
break;
case 8060:
clopt_port_2_file_name = optarg;
break;
case 8070:
clopt_hw = optarg;
break;
default:
break;
}
}
if ( optind < argc ) {
fprintf( stderr, "Invalid arguments : " );
while ( optind < argc )
fprintf( stderr, "%s\n", argv[ optind++ ] );
fprintf( stderr, "\n" );
}
/****************************************************/
/* 2. treat command-line params which have priority */
/****************************************************/
if ( clopt_verbose != -1 )
config.verbose = clopt_verbose == true;
if ( clopt_model != -1 )
config.model = clopt_model;
if ( clopt_frontend != -1 )
config.frontend = clopt_frontend;
if ( clopt_chromeless != -1 )
config.chromeless = clopt_chromeless == true;
if ( clopt_fullscreen != -1 )
config.fullscreen = clopt_fullscreen == true;
if ( clopt_scale > 0.0 )
config.scale = clopt_scale;
if ( clopt_mono != -1 )
config.mono = clopt_mono == true;
if ( clopt_small != -1 )
config.small = clopt_small == true;
if ( clopt_tiny != -1 )
config.tiny = clopt_tiny == true;
if ( clopt_gray != -1 )
config.gray = clopt_gray == true;
if ( clopt_shiftless != -1 )
config.shiftless = clopt_shiftless == true;
if ( clopt_reset != -1 )
config.reset = clopt_reset;
if ( clopt_monitor != -1 )
config.monitor = clopt_monitor;
if ( clopt_batchXfer != -1 )
config.batchXfer = clopt_batchXfer;
if ( clopt_state_dir_path != NULL )
config.state_dir_path = strdup( clopt_state_dir_path );
if ( clopt_mod_file_name != NULL )
config.mod_file_name = strdup( clopt_mod_file_name );
if ( clopt_cpu_file_name != NULL )
config.cpu_file_name = strdup( clopt_cpu_file_name );
if ( clopt_hdw_file_name != NULL )
config.hdw_file_name = strdup( clopt_hdw_file_name );
if ( clopt_rom_file_name != NULL )
config.rom_file_name = strdup( clopt_rom_file_name );
if ( clopt_ram_file_name != NULL )
config.ram_file_name = strdup( clopt_ram_file_name );
if ( clopt_port_1_file_name != NULL )
config.port_1_file_name = strdup( clopt_port_1_file_name );
if ( clopt_port_2_file_name != NULL )
config.port_2_file_name = strdup( clopt_port_2_file_name );
if ( clopt_hw != NULL )
config.hw = strdup( clopt_hw );
fprintf( stderr, "config.chromeless = %s\n\n", config.chromeless ? "true" : "false" );
return &config;
}

View file

@ -1,5 +1,5 @@
#ifndef _UI4x_CONFIG_H
#define _UI4x_CONFIG_H 1
#ifndef _UI48_CONFIG_H
#define _UI48_CONFIG_H 1
#include <stdbool.h>
@ -15,11 +15,8 @@ typedef struct {
char* progname;
int model;
bool throttle;
bool verbose;
bool shiftless;
bool big_screen;
bool black_lcd;
int frontend;
bool mono;
@ -40,8 +37,6 @@ typedef struct {
bool monitor; /* 2.1: Call monitor() on startup */
bool batchXfer; /* 3.15: Non-interactive file transfers */
char* state_dir_path;
char* config_file_name;
char* mod_file_name;
char* cpu_file_name;
char* hdw_file_name;
@ -49,9 +44,7 @@ typedef struct {
char* ram_file_name;
char* port_1_file_name;
char* port_2_file_name;
int debug_level;
bool enable_BUSCC;
char* hw; /* 2.1: Hardware configuration (unused) */
} config_t;
/*************/
@ -59,4 +52,4 @@ typedef struct {
/*************/
extern config_t* config_init( int argc, char* argv[] );
#endif /* !_UI4x_CONFIG_H */
#endif /* !_UI48_CONFIG_H */

View file

@ -2,18 +2,14 @@
#include <stdlib.h>
#include <string.h>
#include "ui48_config.h"
#include "ui48_emulator.h"
#include "config.h"
#include "emulator.h"
#include "keyb.h"
#include "modules.h"
#include "../config.h"
#include "../keyb.h"
#include "../modules.h"
#include "../serial.h"
#define KEYBOARD ( config.model == MODEL_48GX || config.model == MODEL_48SX ? keyboard48 : keyboard49 )
#define NB_KEYS ( config.model == MODEL_48GX || config.model == MODEL_48SX ? NB_HP48_KEYS : NB_HP49_KEYS )
config_t config;
static config_t config;
typedef struct hpkey_t {
int code;
@ -21,7 +17,7 @@ typedef struct hpkey_t {
char* inOut;
} hpkey_t;
static hpkey_t keyboard48[ NB_HP48_KEYS ] = {
static hpkey_t keyboard48[ NB_KEYS ] = {
/* From top left to bottom right */
{0x14, false, "1/10"},
{0x84, false, "8/10"},
@ -82,104 +78,29 @@ static hpkey_t keyboard48[ NB_HP48_KEYS ] = {
{0x00, false, "0/01"},
};
static hpkey_t keyboard49[ NB_HP49_KEYS ] = {
/* From top left to bottom right */
{0x50, false, "5/01"},
{0x51, false, "5/02"},
{0x52, false, "5/04"},
{0x53, false, "5/08"},
{0x54, false, "5/10"},
{0x55, false, "5/20"},
{0x57, false, "5/80"},
{0x47, false, "4/80"},
{0x37, false, "3/80"},
{0x27, false, "2/80"},
{0x17, false, "1/80"},
{0x07, false, "0/80"},
{0x62, false, "6/04"},
{0x63, false, "6/08"},
{0x60, false, "6/01"},
{0x61, false, "6/02"},
{0x46, false, "4/40"},
{0x36, false, "3/40"},
{0x26, false, "2/40"},
{0x16, false, "1/40"},
{0x06, false, "0/40"},
{0x45, false, "4/20"},
{0x35, false, "3/20"},
{0x25, false, "2/20"},
{0x15, false, "1/20"},
{0x05, false, "0/20"},
{0x44, false, "4/10"},
{0x34, false, "3/10"},
{0x24, false, "2/10"},
{0x14, false, "1/10"},
{0x04, false, "0/10"},
{0x73, false, "7/08"},
{0x33, false, "3/08"},
{0x23, false, "2/08"},
{0x13, false, "1/08"},
{0x03, false, "0/08"},
{0x72, false, "7/04"},
{0x32, false, "3/04"},
{0x22, false, "2/04"},
{0x12, false, "1/04"},
{0x02, false, "0/04"},
{0x71, false, "7/02"},
{0x31, false, "3/02"},
{0x21, false, "2/02"},
{0x11, false, "1/02"},
{0x01, false, "0/02"},
{0x8000, false, "*" },
{0x30, false, "3/01"},
{0x20, false, "2/01"},
{0x10, false, "1/01"},
{0x00, false, "0/01"},
};
void press_key( int hpkey )
{
if ( hpkey < 0 || hpkey > NB_KEYS )
return;
// Check not already pressed (may be important: avoids a useless do_kbd_int)
if ( KEYBOARD[ hpkey ].pressed )
if ( keyboard48[ hpkey ].pressed )
return;
KEYBOARD[ hpkey ].pressed = true;
keyboard48[ hpkey ].pressed = true;
KeybPress( KEYBOARD[ hpkey ].inOut );
KeybPress( keyboard48[ hpkey ].inOut );
}
void release_key( int hpkey )
{
if ( hpkey < 0 || hpkey > NB_KEYS )
return;
// Check not already released (not critical)
if ( !KEYBOARD[ hpkey ].pressed )
if ( !keyboard48[ hpkey ].pressed )
return;
KEYBOARD[ hpkey ].pressed = false;
keyboard48[ hpkey ].pressed = false;
KeybRelease( KEYBOARD[ hpkey ].inOut );
KeybRelease( keyboard48[ hpkey ].inOut );
}
bool is_key_pressed( int hpkey )
{
if ( hpkey < 0 || hpkey > NB_KEYS )
return false;
return KEYBOARD[ hpkey ].pressed;
}
bool is_key_pressed( int hpkey ) { return keyboard48[ hpkey ].pressed; }
unsigned char get_annunciators( void ) { return mod_status.hdw.lcd_ann; }
@ -197,9 +118,8 @@ void get_lcd_buffer( int* target )
for ( x = 0; x < NIBBLES_PER_ROW; x++ ) {
v = FetchNibble( addr++ );
// split nibble
for ( int nx = 0; nx < 4; nx++ )
target[ ( y * LCD_WIDTH ) + ( x * 4 ) + nx ] = v & ( 1 << ( nx & 3 ) );
target[ ( y * 131 ) + ( x * 4 ) + nx ] = v & ( 1 << ( nx & 3 ) );
}
addr += mod_status.hdw.lcd_line_offset;
@ -207,27 +127,52 @@ void get_lcd_buffer( int* target )
/* Scan menu display rows */
addr = mod_status.hdw.lcd_menu_addr;
for ( ; y < LCD_HEIGHT; y++ ) {
#define MAX_ROWS 64
for ( ; y < MAX_ROWS; y++ ) {
/* Scan columns */
for ( x = 0; x < NIBBLES_PER_ROW; x++ ) {
v = FetchNibble( addr++ );
// split nibble
for ( int nx = 0; nx < 4; nx++ )
target[ ( y * LCD_WIDTH ) + ( x * 4 ) + nx ] = v & ( 1 << ( nx & 3 ) );
target[ ( y * 131 ) + ( x * 4 ) + nx ] = v & ( 1 << ( nx & 3 ) );
}
}
}
int get_contrast( void ) { return mod_status.hdw.lcd_contrast - 6; }
int get_contrast( void ) { return mod_status.hdw.lcd_contrast; }
struct Args args;
/* Path/name dynamic allocator */
static char* GetPathname( char* path, char* name )
{
char* s = malloc( strlen( path ) + strlen( name ) + 2 );
strcpy( s, path );
strcat( s, "/" );
strcat( s, name );
return s;
}
void init_emulator( config_t* conf )
{
config = *conf;
EmulatorInit();
/* Fill the emulator options data structure. */
args.reset = config.reset;
args.monitor = config.monitor;
args.batchXfer = config.batchXfer;
args.mod_file_name = GetPathname( config.state_dir_path, config.mod_file_name );
args.cpu_file_name = GetPathname( config.state_dir_path, config.cpu_file_name );
args.hdw_file_name = GetPathname( config.state_dir_path, config.hdw_file_name );
args.rom_file_name = GetPathname( config.state_dir_path, config.rom_file_name );
args.ram_file_name = GetPathname( config.state_dir_path, config.ram_file_name );
args.port_1_file_name = GetPathname( config.state_dir_path, config.port_1_file_name );
args.port_2_file_name = GetPathname( config.state_dir_path, config.port_2_file_name );
args.hw = config.hw;
conf->wire_name = ( char* )SerialInit();
EmulatorInit();
}
void exit_emulator( void ) { EmulatorExit( SAVE_AND_EXIT ); }

103
src/ui48_emulator.h Normal file
View file

@ -0,0 +1,103 @@
#ifndef _UI48_EMULATOR_H
#define _UI48_EMULATOR_H 1
#include <stdbool.h>
#include "ui48_config.h"
// Keys
#define HPKEY_A 0
#define HPKEY_B 1
#define HPKEY_C 2
#define HPKEY_D 3
#define HPKEY_E 4
#define HPKEY_F 5
#define HPKEY_MTH 6
#define HPKEY_PRG 7
#define HPKEY_CST 8
#define HPKEY_VAR 9
#define HPKEY_UP 10
#define HPKEY_NXT 11
#define HPKEY_QUOTE 12
#define HPKEY_STO 13
#define HPKEY_EVAL 14
#define HPKEY_LEFT 15
#define HPKEY_DOWN 16
#define HPKEY_RIGHT 17
#define HPKEY_SIN 18
#define HPKEY_COS 19
#define HPKEY_TAN 20
#define HPKEY_SQRT 21
#define HPKEY_POWER 22
#define HPKEY_INV 23
#define HPKEY_ENTER 24
#define HPKEY_NEG 25
#define HPKEY_EEX 26
#define HPKEY_DEL 27
#define HPKEY_BS 28
#define HPKEY_ALPHA 29
#define HPKEY_7 30
#define HPKEY_8 31
#define HPKEY_9 32
#define HPKEY_DIV 33
#define HPKEY_SHL 34
#define HPKEY_4 35
#define HPKEY_5 36
#define HPKEY_6 37
#define HPKEY_MUL 38
#define HPKEY_SHR 39
#define HPKEY_1 40
#define HPKEY_2 41
#define HPKEY_3 42
#define HPKEY_MINUS 43
#define HPKEY_ON 44
#define HPKEY_0 45
#define HPKEY_PERIOD 46
#define HPKEY_SPC 47
#define HPKEY_PLUS 48
#define FIRST_HPKEY HPKEY_A
#define LAST_HPKEY HPKEY_PLUS
#define NB_KEYS ( LAST_HPKEY + 1 )
#define KEYS_BUFFER_SIZE 9
// Annunciators
#define NB_ANNUNCIATORS 6
#define ANN_LEFT 0x81
#define ANN_RIGHT 0x82
#define ANN_ALPHA 0x84
#define ANN_BATTERY 0x88
#define ANN_BUSY 0x90
#define ANN_IO 0xa0
// LCD
#define NIBBLES_PER_ROW 34
#define LCD_WIDTH 131
#define LCD_HEIGHT 64
/*************************************************/
/* public API: if it's there it's used elsewhere */
/*************************************************/
extern void press_key( int hpkey );
extern void release_key( int hpkey );
extern bool is_key_pressed( int hpkey );
extern void init_emulator( config_t* conf );
extern void exit_emulator( void );
extern unsigned char get_annunciators( void );
extern bool get_display_state( void );
extern void get_lcd_buffer( int* target );
extern int get_contrast( void );
#endif /* !_UI48_EMULATOR_H */

93
src/ui48_inner.h Normal file
View file

@ -0,0 +1,93 @@
#ifndef _UI48_INNER_H
#define _UI48_INNER_H 1
#include "ui48_emulator.h"
#include "ui48_bitmaps_misc.h"
#include "ui48_bitmaps_small_font.h"
#include "ui48_bitmaps_big_font.h"
// Colors
/* SX GX */
#define WHITE 0 /* #ffffff #ffffff */
#define LEFT 1 /* #ffa600 #ffbaff */
#define RIGHT 2 /* #00d2ff #00ffcc */
#define BUT_TOP 3 /* #6d5d5d #646464 */
#define BUTTON 4 /* #5a4d4d #585858 */
#define BUT_BOT 5 /* #4c4141 #4a4a4a */
#define LCD 6 /* #cadd5c #cadd5c */
#define PIXEL 7 /* #000080 #000080 */
#define PAD_TOP 8 /* #6d4e4e #585858 */
#define PAD 9 /* #5a4040 #4a4a4a */
#define PAD_BOT 10 /* #4c3636 #404040 */
#define DISP_PAD_TOP 11 /* #9b7654 #808080 */
#define DISP_PAD 12 /* #7c5e43 #68686e */
#define DISP_PAD_BOT 13 /* #644b35 #54545a */
#define LOGO 14 /* #cca96b #b0b0b8 */
#define LOGO_BACK 15 /* #404040 #68686e */
#define LABEL 16 /* #cab890 #f0f0f0 */
#define FRAME 17 /* #000000 #000000 */
#define UNDERLAY 18 /* #3c2a2a #68686e */
#define BLACK 19 /* #000000 #000000 */
#define FIRST_COLOR WHITE
#define LAST_COLOR BLACK
#define NB_COLORS ( LAST_COLOR + 1 )
/***********/
/* typedef */
/***********/
typedef struct letter_t {
unsigned int w, h;
unsigned char* bits;
} letter_t;
typedef struct color_t {
const char* name;
int r, g, b, a;
int mono_rgb;
int gray_rgb;
} color_t;
typedef struct button_t {
const char* name;
int x, y;
int w, h;
int lc;
const char* label;
short font_size;
unsigned int lw, lh;
unsigned char* lb;
const char* letter;
const char* left;
short is_menu;
const char* right;
const char* sub;
} button_t;
/*************/
/* variables */
/*************/
extern letter_t small_font[ 128 ];
extern letter_t big_font[ 128 ];
extern color_t colors_sx[ NB_COLORS ];
extern color_t colors_gx[ NB_COLORS ];
extern button_t buttons_sx[ NB_KEYS ];
extern button_t buttons_gx[ NB_KEYS ];
#define small_ascent 8
#define small_descent 4
/*************/
/* functions */
/*************/
extern int SmallTextWidth( const char* string, unsigned int length );
extern int BigTextWidth( const char* string, unsigned int length );
#endif /* _UI48_INNER_H */

196
src/ui48_main.c Normal file
View file

@ -0,0 +1,196 @@
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include "ui48_config.h"
#include "ui48_emulator.h"
#include "ui48_common.h"
#include "config.h"
#include "cpu.h"
#include "monitor.h"
#define SPEED_HZ_UI 64
/* Chf condition codes (main program only) */
#define CHF_MODULE_ID MAIN_CHF_MODULE_ID
#include <Chf.h>
#define MAIN_M_COPYRIGHT 501
#define MAIN_M_LICENSE 502
/*---------------------------------------------------------------------------
Chf parameters - Do not change.
---------------------------------------------------------------------------*/
#define CONDITION_STACK_SIZE 16
#define HANDLER_STACK_SIZE 8
/* Conditional prefix and mandatory suffix to make a message catalog
name from argv[0]
*/
static const char cat_prefix[] = "./";
static const char cat_suffix[] = ".cat";
#define CAT_PREFIX_LEN ( sizeof( cat_prefix ) + 1 )
#define CAT_SUFFIX_LEN ( sizeof( cat_suffix ) + 1 )
static void adjust_setlocale( void )
{
fprintf( stderr, "saturn-W-locale probably bad; reverting to C locale\n" );
putenv( "LC_ALL=C" );
putenv( "LC_COLLATE=C" );
putenv( "LC_CTYPE=C" );
putenv( "LC_MESSAGES=C" );
putenv( "LC_MONETARY=C" );
putenv( "LC_NUMERIC=C" );
putenv( "LC_TIME=C" );
putenv( "LANG=C" );
}
void signal_handler( int sig )
{
switch ( sig ) {
/* case SIGINT: /\* Ctrl-C *\/ */
/* enter_debugger |= USER_INTERRUPT; */
/* break; */
case SIGALRM:
ui_get_event();
ui_update_display();
break;
case SIGPIPE:
ui_stop();
exit_emulator();
exit( 0 );
default:
break;
}
}
int main( int argc, char** argv )
{
config_t* config = config_init( argc, argv );
char* cat_name;
int st;
int retry = 0;
if ( ( cat_name = malloc( strlen( argv[ 0 ] ) + CAT_PREFIX_LEN + CAT_SUFFIX_LEN + 1 ) ) == NULL ) {
fprintf( stderr, "saturn-E-cat_name initialization failed\n" );
exit( EXIT_FAILURE );
}
/* Generate catalog name, without optional prefix */
strcpy( cat_name, argv[ 0 ] );
strcat( cat_name, cat_suffix );
/* 3.15: Retry the initialization steps below two times; before trying
the second time, adjust the setlocale() environment variables
with adjust_setlocale()
*/
while ( retry < 2 ) {
/* Chf initialization with msgcat subsystem; notice that on
some systems (e.g. Digital UNIX) catopen() can succeed even
if it was not able to open the right message catalog;
better try it now.
*/
if ( ( st = ChfMsgcatInit( argv[ 0 ], /* Application's name */
CHF_DEFAULT, /* Options */
cat_name, /* Name of the message catalog */
CONDITION_STACK_SIZE, /* Size of the condition stack */
HANDLER_STACK_SIZE, /* Size of the handler stack */
EXIT_FAILURE /* Abnormal exit code */
) ) != CHF_S_OK ||
ChfGetMessage( CHF_MODULE_ID, MAIN_M_COPYRIGHT, NULL ) == NULL )
fprintf( stderr, "saturn-E-Primary Chf initialization failed (%d)\n", st );
else
break;
/* Bring down Chf before initializing it again */
if ( st == CHF_S_OK )
ChfExit();
/* Try alternate message catalog name (with prefix) */
strcpy( cat_name, cat_prefix );
strcat( cat_name, argv[ 0 ] );
strcat( cat_name, cat_suffix );
if ( ( st = ChfMsgcatInit( argv[ 0 ], /* Application's name */
CHF_DEFAULT, /* Options */
cat_name, /* Name of the message catalog */
CONDITION_STACK_SIZE, /* Size of the condition stack */
HANDLER_STACK_SIZE, /* Size of the handler stack */
EXIT_FAILURE /* Abnormal exit code */
) ) != CHF_S_OK ||
ChfGetMessage( CHF_MODULE_ID, MAIN_M_COPYRIGHT, NULL ) == NULL )
fprintf( stderr, "saturn-E-Alternate Chf initialization failed (%d)\n", st );
else
break;
/* Bring down Chf before initializing it again */
if ( st == CHF_S_OK )
ChfExit();
/* Attempt to adjust setlocale() environment variables */
if ( retry++ == 0 )
adjust_setlocale();
}
if ( retry == 2 ) {
fprintf( stderr, "saturn-F-Application aborted\n" );
exit( EXIT_FAILURE );
}
/* cat_name no longer needed */
free( cat_name );
/* 3.9: Print out MAIN_M_COPYRIGHT and MAIN_M_LICENSE on stdout now */
fprintf( stdout, ChfGetMessage( CHF_MODULE_ID, MAIN_M_COPYRIGHT, "" ), "$Revision: 4.1 $" );
/* fprintf( stdout, ChfGetMessage( CHF_MODULE_ID, MAIN_M_LICENSE, "" ) ); */
init_emulator( config );
/* (G)UI */
setup_ui( config );
ui_start( config );
sigset_t set;
struct sigaction sa;
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 );
/************************************/
/* set the real time interval timer */
/************************************/
/*
Every <interval>µs setitimer will trigger a SIGALRM
which will getUI events and refresh UI in signal_handler
*/
struct itimerval it;
it.it_interval.tv_sec = 0;
it.it_interval.tv_usec = 1000000 / SPEED_HZ_UI;
it.it_value.tv_sec = 0;
it.it_value.tv_usec = 1000000 / SPEED_HZ_UI;
setitimer( ITIMER_REAL, &it, ( struct itimerval* )0 );
if ( config->monitor )
/* Invoke Monitor */
Monitor();
else
/* Call Emulator directly */
Emulator();
/* never reached */
return EXIT_SUCCESS;
}

View file

@ -14,13 +14,13 @@
#include <curses.h>
#include "config.h"
#include "emulator.h"
#include "common.h"
#include "inner.h"
#include "ui48_config.h"
#include "ui48_emulator.h"
#include "ui48_common.h"
#include "ui48_inner.h"
#define COLORS ( config.model == MODEL_48GX ? colors_48gx : ( config.model == MODEL_49G ? colors_49g : colors_48sx ) )
#define BUTTONS ( config.model == MODEL_48GX ? buttons_48gx : ( config.model == MODEL_49G ? buttons_49g : buttons_48sx ) )
#define COLORS ( config.model == MODEL_48GX ? colors_gx : colors_sx )
#define BUTTONS ( config.model == MODEL_48GX ? buttons_gx : buttons_sx )
#define LCD_OFFSET_X 1
#define LCD_OFFSET_Y 1
@ -38,7 +38,7 @@
/* variables */
/*************/
static config_t config;
static int lcd_pixels_buffer[ LCD_WIDTH * 80 ];
static int lcd_pixels_buffer[ LCD_WIDTH * LCD_HEIGHT ];
static int last_annunciators = -1;
// static int last_contrast = -1;
@ -259,179 +259,170 @@ void ui_get_event_ncurses( void )
switch ( k ) {
case '0':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_0 : HP48_KEY_0 );
hpkey = HPKEY_0;
break;
case '1':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_1 : HP48_KEY_1 );
hpkey = HPKEY_1;
break;
case '2':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_2 : HP48_KEY_2 );
hpkey = HPKEY_2;
break;
case '3':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_3 : HP48_KEY_3 );
hpkey = HPKEY_3;
break;
case '4':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_4 : HP48_KEY_4 );
hpkey = HPKEY_4;
break;
case '5':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_5 : HP48_KEY_5 );
hpkey = HPKEY_5;
break;
case '6':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_6 : HP48_KEY_6 );
hpkey = HPKEY_6;
break;
case '7':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_7 : HP48_KEY_7 );
hpkey = HPKEY_7;
break;
case '8':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_8 : HP48_KEY_8 );
hpkey = HPKEY_8;
break;
case '9':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_9 : HP48_KEY_9 );
hpkey = HPKEY_9;
break;
case 'a':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_A : HP48_KEY_A );
hpkey = HPKEY_A;
break;
case 'b':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_B : HP48_KEY_B );
hpkey = HPKEY_B;
break;
case 'c':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_C : HP48_KEY_C );
hpkey = HPKEY_C;
break;
case 'd':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_D : HP48_KEY_D );
hpkey = HPKEY_D;
break;
case 'e':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_E : HP48_KEY_E );
hpkey = HPKEY_E;
break;
case 'f':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_F : HP48_KEY_F );
hpkey = HPKEY_F;
break;
case 'g':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_APPS : HP48_KEY_MTH );
hpkey = HPKEY_MTH;
break;
case 'h':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_MODE : HP48_KEY_PRG );
hpkey = HPKEY_PRG;
break;
case 'i':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_TOOL : HP48_KEY_CST );
hpkey = HPKEY_CST;
break;
case 'j':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_VAR : HP48_KEY_VAR );
hpkey = HPKEY_VAR;
break;
case 'k':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_STO : HP48_KEY_UP );
break;
case KEY_UP:
hpkey = ( config.model == MODEL_49G ? HP49_KEY_UP : HP48_KEY_UP );
hpkey = HPKEY_UP;
break;
case 'l':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_NXT : HP48_KEY_NXT );
hpkey = HPKEY_NXT;
break;
case 'm':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_HIST : HP48_KEY_QUOTE );
hpkey = HPKEY_QUOTE;
break;
case 'n':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_CAT : HP48_KEY_STO );
hpkey = HPKEY_STO;
break;
case 'o':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_EQW : HP48_KEY_EVAL );
hpkey = HPKEY_EVAL;
break;
case 'p':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_SYMB : HP48_KEY_LEFT );
break;
case KEY_LEFT:
hpkey = ( config.model == MODEL_49G ? HP49_KEY_LEFT : HP48_KEY_LEFT );
hpkey = HPKEY_LEFT;
break;
case 'q':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_POWER : HP48_KEY_DOWN );
break;
case KEY_DOWN:
hpkey = ( config.model == MODEL_49G ? HP49_KEY_DOWN : HP48_KEY_DOWN );
hpkey = HPKEY_DOWN;
break;
case 'r':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_SQRT : HP48_KEY_RIGHT );
break;
case KEY_RIGHT:
hpkey = ( config.model == MODEL_49G ? HP49_KEY_RIGHT : HP48_KEY_RIGHT );
hpkey = HPKEY_RIGHT;
break;
case 's':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_SIN : HP48_KEY_SIN );
hpkey = HPKEY_SIN;
break;
case 't':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_COS : HP48_KEY_COS );
hpkey = HPKEY_COS;
break;
case 'u':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_TAN : HP48_KEY_TAN );
hpkey = HPKEY_TAN;
break;
case 'v':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_EEX : HP48_KEY_SQRT );
hpkey = HPKEY_SQRT;
break;
case 'w':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_NEG : HP48_KEY_POWER );
hpkey = HPKEY_POWER;
break;
case 'x':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_X : HP48_KEY_INV );
hpkey = HPKEY_INV;
break;
case 'y':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_INV : HP48_KEY_NEG );
hpkey = HPKEY_NEG;
break;
case 'z':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_DIV : HP48_KEY_EEX );
hpkey = HPKEY_EEX;
break;
case ' ':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_SPC : HP48_KEY_SPC );
hpkey = HPKEY_SPC;
break;
case KEY_DC:
hpkey = ( config.model == MODEL_49G ? -1 : HP48_KEY_DEL );
hpkey = HPKEY_DEL;
break;
case '.':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_PERIOD : HP48_KEY_PERIOD );
hpkey = HPKEY_PERIOD;
break;
case '+':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_PLUS : HP48_KEY_PLUS );
hpkey = HPKEY_PLUS;
break;
case '-':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_MINUS : HP48_KEY_MINUS );
hpkey = HPKEY_MINUS;
break;
case '*':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_MUL : HP48_KEY_MUL );
hpkey = HPKEY_MUL;
break;
case '/':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_DIV : HP48_KEY_DIV );
hpkey = HPKEY_DIV;
break;
case KEY_F( 1 ):
case KEY_ENTER:
case '\n':
case ',':
case 13:
hpkey = ( config.model == MODEL_49G ? HP49_KEY_ENTER : HP48_KEY_ENTER );
hpkey = HPKEY_ENTER;
break;
case KEY_BACKSPACE:
case 127:
case '\b':
hpkey = ( config.model == MODEL_49G ? HP49_KEY_BS : HP48_KEY_BS );
hpkey = HPKEY_BS;
break;
case KEY_F( 2 ):
case '[':
case 339: /* PgUp */
hpkey = ( config.model == MODEL_49G ? HP49_KEY_SHL : HP48_KEY_SHL );
hpkey = HPKEY_SHL;
break;
case KEY_F( 3 ):
case ']':
case 338: /* PgDn */
hpkey = ( config.model == MODEL_49G ? HP49_KEY_SHR : HP48_KEY_SHR );
hpkey = HPKEY_SHR;
break;
case KEY_F( 4 ):
case ';':
case KEY_IC: /* Ins */
hpkey = ( config.model == MODEL_49G ? HP49_KEY_ALPHA : HP48_KEY_ALPHA );
hpkey = HPKEY_ALPHA;
break;
case KEY_F( 5 ):
case '\\':
case 27: /* Esc */
case 262: /* Home */
hpkey = ( config.model == MODEL_49G ? HP49_KEY_ON : HP48_KEY_ON );
hpkey = HPKEY_ON;
break;
case KEY_F( 7 ):
@ -443,7 +434,7 @@ void ui_get_event_ncurses( void )
break;
}
if ( hpkey > 0 && !is_key_pressed( hpkey ) )
if ( !is_key_pressed( hpkey ) )
press_key( hpkey );
}
}
@ -457,6 +448,9 @@ void ui_stop_ncurses( void )
void ui_start_ncurses( config_t* conf )
{
if ( config.verbose )
fprintf( stderr, "UI is ncurses\n" );
config = *conf;
setlocale( LC_ALL, "" );
@ -472,15 +466,11 @@ void ui_start_ncurses( config_t* conf )
start_color();
if ( config.gray ) {
init_color( LCD_COLOR_BG, COLORS[ UI4X_COLOR_PIXEL_OFF ].gray_rgb, COLORS[ UI4X_COLOR_PIXEL_OFF ].gray_rgb,
COLORS[ UI4X_COLOR_PIXEL_OFF ].gray_rgb );
init_color( LCD_COLOR_FG, COLORS[ UI4X_COLOR_PIXEL_ON ].gray_rgb, COLORS[ UI4X_COLOR_PIXEL_ON ].gray_rgb,
COLORS[ UI4X_COLOR_PIXEL_ON ].gray_rgb );
init_color( LCD_COLOR_BG, COLORS[ LCD ].gray_rgb, COLORS[ LCD ].gray_rgb, COLORS[ LCD ].gray_rgb );
init_color( LCD_COLOR_FG, COLORS[ PIXEL ].gray_rgb, COLORS[ PIXEL ].gray_rgb, COLORS[ PIXEL ].gray_rgb );
} else {
init_color( LCD_COLOR_BG, ( COLORS[ UI4X_COLOR_PIXEL_OFF ].rgb >> 16 ) & 0xff,
( COLORS[ UI4X_COLOR_PIXEL_OFF ].rgb >> 8 ) & 0xff, COLORS[ UI4X_COLOR_PIXEL_OFF ].rgb & 0xff );
init_color( LCD_COLOR_BG, ( COLORS[ UI4X_COLOR_PIXEL_ON ].rgb >> 16 ) & 0xff, ( COLORS[ UI4X_COLOR_PIXEL_ON ].rgb >> 8 ) & 0xff,
COLORS[ UI4X_COLOR_PIXEL_ON ].rgb & 0xff );
init_color( LCD_COLOR_BG, COLORS[ LCD ].r, COLORS[ LCD ].g, COLORS[ LCD ].b );
init_color( LCD_COLOR_FG, COLORS[ PIXEL ].r, COLORS[ PIXEL ].g, COLORS[ PIXEL ].b );
}
init_pair( LCD_PIXEL_OFF, LCD_COLOR_BG, LCD_COLOR_BG );

6
src/ui48_ncurses.h Normal file
View file

@ -0,0 +1,6 @@
#ifndef _UI48_NCURSES_H
#define _UI48_NCURSES_H 1
extern void setup_frontend_ncurses( void );
#endif /* _UI48_NCURSES_H */

1110
src/ui48_sdl2.c Normal file

File diff suppressed because it is too large Load diff

6
src/ui48_sdl2.h Normal file
View file

@ -0,0 +1,6 @@
#ifndef _UI48_SDL2_H
#define _UI48_SDL2_H 1
extern void setup_frontend_sdl( void );
#endif /* _UI48_SDL2_H */

View file

@ -1,908 +0,0 @@
#include "inner.h"
color_t colors_48gx[ NB_COLORS ] = {
/* UI4X_COLOR_HP_LOGO */
{
.a = 0xFF,
.mono_rgb = 0xFF,
.gray_rgb = 0xB0,
.rgb = 0xB0B0B8,
},
/* UI4X_COLOR_HP_LOGO_BG */
{
.a = 0xFF,
.mono_rgb = 0x0,
.gray_rgb = 0x68,
.rgb = 0x68686E,
},
/* UI4X_COLOR_48GX_128K_RAM */
{
.a = 0xFF,
.mono_rgb = 0xFF,
.gray_rgb = 0xF0,
.rgb = 0xF0F0F0,
},
/* UI4X_COLOR_FRAME */
{
.a = 0xFF,
.mono_rgb = 0xFF,
.gray_rgb = 0x0,
.rgb = 0x000000,
},
/* UI4X_COLOR_UPPER_FACEPLATE_EDGE_TOP */
{
.a = 0xFF,
.mono_rgb = 0x0,
.gray_rgb = 0x80,
.rgb = 0x80808A,
},
/* UI4X_COLOR_UPPER_FACEPLATE */
{
.a = 0xFF,
.mono_rgb = 0x0,
.gray_rgb = 0x68,
.rgb = 0x68686E,
},
/* UI4X_COLOR_UPPER_FACEPLATE_EDGE_BOTTOM */
{
.a = 0xFF,
.mono_rgb = 0x0,
.gray_rgb = 0x54,
.rgb = 0x54545A,
},
/* UI4X_COLOR_FACEPLATE_EDGE_TOP */
{
.a = 0xFF,
.mono_rgb = 0x0,
.gray_rgb = 0x58,
.rgb = 0x585858,
},
/* UI4X_COLOR_FACEPLATE */
{
.a = 0xFF,
.mono_rgb = 0x0,
.gray_rgb = 0x4A,
.rgb = 0x4A4A4A,
},
/* UI4X_COLOR_FACEPLATE_EDGE_BOTTOM */
{
.a = 0xFF,
.mono_rgb = 0x0,
.gray_rgb = 0x40,
.rgb = 0x404040,
},
/* UI4X_COLOR_KEYPAD_HIGHLIGHT */
{
.a = 0xFF,
.mono_rgb = 0x0,
.gray_rgb = 0x68,
.rgb = 0x68686E,
},
/* UI4X_COLOR_BUTTON_EDGE_TOP */
{
.a = 0xFF,
.mono_rgb = 0x0,
.gray_rgb = 0x68,
.rgb = 0x686868,
},
/* UI4X_COLOR_BUTTON */
{
.a = 0xFF,
.mono_rgb = 0x0,
.gray_rgb = 0x58,
.rgb = 0x585858,
},
/* UI4X_COLOR_BUTTON_EDGE_BOTTOM */
{
.a = 0xFF,
.mono_rgb = 0x0,
.gray_rgb = 0x4A,
.rgb = 0x4A4A4A,
},
/* UI4X_COLOR_PIXEL_OFF */
{
.a = 0xFF,
.mono_rgb = 0xFF,
.gray_rgb = 0xCD,
.rgb = 0xCADD5C,
},
/* UI4X_COLOR_PIXEL_ON */
{
.a = 0xFF,
.mono_rgb = 0x0,
.gray_rgb = 0x14,
.rgb = 0x000080,
},
/* UI4X_COLOR_BLACK_PIXEL_OFF */
{
.a = 0xFF,
.mono_rgb = 0xFF,
.gray_rgb = 0xCD,
.rgb = 0xf5f5f5,
},
/* UI4X_COLOR_BLACK_PIXEL_ON */
{
.a = 0xFF,
.mono_rgb = 0x0,
.gray_rgb = 0x14,
.rgb = 0x000000,
},
/* UI4X_COLOR_LABEL */
{
.a = 0xFF,
.mono_rgb = 0xFF,
.gray_rgb = 0xFF,
.rgb = 0xFFFFFF,
},
/* UI4X_COLOR_ALPHA */
{
.a = 0xFF,
.mono_rgb = 0xFF,
.gray_rgb = 0xFF,
.rgb = 0xFFFFFF,
},
/* UI4X_COLOR_SHIFT_LEFT */
{
.a = 0xFF,
.mono_rgb = 0xFF,
.gray_rgb = 0xDC,
.rgb = 0xFFBAFF,
},
/* UI4X_COLOR_SHIFT_RIGHT */
{
.a = 0xFF,
.mono_rgb = 0xFF,
.gray_rgb = 0xA9,
.rgb = 0x00FFCC,
},
};
#define KB_LINE_HEIGHT 50
#define KB_COLUMN_WIDTH_6_KEYS 50
#define KB_COLUMN_WIDTH_5_KEYS 60
button_t buttons_48gx[ NB_HP48_KEYS ] = {
{.x = 0,
.y = 0,
.w = 36,
.h = 23,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = menu_label_width,
.label_graphic_h = menu_label_height,
.label_graphic = menu_label_bitmap,
.letter = "A",
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = KB_COLUMN_WIDTH_6_KEYS,
.y = 0,
.w = 36,
.h = 23,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = menu_label_width,
.label_graphic_h = menu_label_height,
.label_graphic = menu_label_bitmap,
.letter = "B",
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_6_KEYS,
.y = 0,
.w = 36,
.h = 23,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = menu_label_width,
.label_graphic_h = menu_label_height,
.label_graphic = menu_label_bitmap,
.letter = "C",
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_6_KEYS,
.y = 0,
.w = 36,
.h = 23,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = menu_label_width,
.label_graphic_h = menu_label_height,
.label_graphic = menu_label_bitmap,
.letter = "D",
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_6_KEYS,
.y = 0,
.w = 36,
.h = 23,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = menu_label_width,
.label_graphic_h = menu_label_height,
.label_graphic = menu_label_bitmap,
.letter = "E",
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 5 * KB_COLUMN_WIDTH_6_KEYS,
.y = 0,
.w = 36,
.h = 23,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = menu_label_width,
.label_graphic_h = menu_label_height,
.label_graphic = menu_label_bitmap,
.letter = "F",
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 0,
.y = KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "MTH",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "G",
.left = "RAD",
.highlight = false,
.right = "POLAR",
.sub = 0 },
{.x = KB_COLUMN_WIDTH_6_KEYS,
.y = KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "PRG",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "H",
.left = "CHARS",
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_6_KEYS,
.y = KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "CST",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "I",
.left = "MODES",
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_6_KEYS,
.y = KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "VAR",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "J",
.left = "MEMORY",
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_6_KEYS,
.y = KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = up_width,
.label_graphic_h = up_height,
.label_graphic = up_bitmap,
.letter = "K",
.left = "STACK",
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 5 * KB_COLUMN_WIDTH_6_KEYS,
.y = KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "NXT",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "L",
.left = "PREV",
.highlight = false,
.right = "MENU",
.sub = 0 },
{.x = 0,
.y = 2 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = quote_width,
.label_graphic_h = quote_height,
.label_graphic = quote_bitmap,
.letter = "M",
.left = "UP",
.highlight = false,
.right = "HOME",
.sub = 0 },
{.x = KB_COLUMN_WIDTH_6_KEYS,
.y = 2 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "STO",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "N",
.left = "DEF",
.highlight = false,
.right = "RCL",
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_6_KEYS,
.y = 2 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "EVAL",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "O",
.left = "\x06NUM",
.highlight = false,
.right = "UNDO",
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_6_KEYS,
.y = 2 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = left_width,
.label_graphic_h = left_height,
.label_graphic = left_bitmap,
.letter = "P",
.left = "PICTURE",
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_6_KEYS,
.y = 2 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = down_width,
.label_graphic_h = down_height,
.label_graphic = down_bitmap,
.letter = "Q",
.left = "VIEW",
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 5 * KB_COLUMN_WIDTH_6_KEYS,
.y = 2 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = right_width,
.label_graphic_h = right_height,
.label_graphic = right_bitmap,
.letter = "R",
.left = "SWAP",
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 0,
.y = 3 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "SIN",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "S",
.left = "ASIN",
.highlight = false,
.right = "\x07",
.sub = 0 },
{.x = KB_COLUMN_WIDTH_6_KEYS,
.y = 3 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "COS",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "T",
.left = "ACOS",
.highlight = false,
.right = "\x08",
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_6_KEYS,
.y = 3 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "TAN",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "U",
.left = "ATAN",
.highlight = false,
.right = "\x09",
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_6_KEYS,
.y = 3 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = sqrt_width,
.label_graphic_h = sqrt_height,
.label_graphic = sqrt_bitmap,
.letter = "V",
.left = "\x13",
.highlight = false,
.right = "\x14",
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_6_KEYS,
.y = 3 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = power_width,
.label_graphic_h = power_height,
.label_graphic = power_bitmap,
.letter = "W",
.left = "\x15",
.highlight = false,
.right = "LOG",
.sub = 0 },
{.x = 5 * KB_COLUMN_WIDTH_6_KEYS,
.y = 3 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = inv_width,
.label_graphic_h = inv_height,
.label_graphic = inv_bitmap,
.letter = "X",
.left = "\x16",
.highlight = false,
.right = "LN",
.sub = 0 },
{.x = 0,
.y = 4 * KB_LINE_HEIGHT,
.w = 86,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "ENTER",
.font_size = 2,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "EQUATION",
.highlight = false,
.right = "MATRIX",
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_6_KEYS,
.y = 4 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = neg_width,
.label_graphic_h = neg_height,
.label_graphic = neg_bitmap,
.letter = "Y",
.left = "EDIT",
.highlight = false,
.right = "CMD",
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_6_KEYS,
.y = 4 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "EEX",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "Z",
.left = "PURG",
.highlight = false,
.right = "ARG",
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_6_KEYS,
.y = 4 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "DEL",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "CLEAR",
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 5 * KB_COLUMN_WIDTH_6_KEYS,
.y = 4 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = bs_width,
.label_graphic_h = bs_height,
.label_graphic = bs_bitmap,
.letter = 0,
.left = "DROP",
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 0,
.y = 5 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = alpha_width,
.label_graphic_h = alpha_height,
.label_graphic = alpha_bitmap,
.letter = 0,
.left = "USER",
.highlight = false,
.right = "ENTRY",
.sub = 0 },
{.x = KB_COLUMN_WIDTH_5_KEYS,
.y = 5 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "7",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "SOLVE",
.highlight = true,
.right = 0,
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_5_KEYS,
.y = 5 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "8",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "PLOT",
.highlight = true,
.right = 0,
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_5_KEYS,
.y = 5 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "9",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "SYMBOLIC",
.highlight = true,
.right = 0,
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_5_KEYS,
.y = 5 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = div_width,
.label_graphic_h = div_height,
.label_graphic = div_bitmap,
.letter = 0,
.left = "\x17 ",
.highlight = false,
.right = "\x18",
.sub = 0 },
{.x = 0,
.y = 6 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_SHIFT_LEFT,
.label_text = 0,
.font_size = 0,
.label_graphic_w = shl_width,
.label_graphic_h = shl_height,
.label_graphic = shl_bitmap,
.letter = 0,
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = KB_COLUMN_WIDTH_5_KEYS,
.y = 6 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "4",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "TIME",
.highlight = true,
.right = 0,
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_5_KEYS,
.y = 6 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "5",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "STAT",
.highlight = true,
.right = 0,
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_5_KEYS,
.y = 6 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "6",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "UNITS",
.highlight = true,
.right = 0,
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_5_KEYS,
.y = 6 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = mul_width,
.label_graphic_h = mul_height,
.label_graphic = mul_bitmap,
.letter = 0,
.left = "\x19 ",
.highlight = false,
.right = "\x1a",
.sub = 0 },
{.x = 0,
.y = 7 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_SHIFT_RIGHT,
.label_text = 0,
.font_size = 0,
.label_graphic_w = shr_width,
.label_graphic_h = shr_height,
.label_graphic = shr_bitmap,
.letter = 0,
.left = 0,
.highlight = true,
.right = 0,
.sub = 0 },
{.x = KB_COLUMN_WIDTH_5_KEYS,
.y = 7 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "1",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "I/O",
.highlight = true,
.right = 0,
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_5_KEYS,
.y = 7 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "2",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "LIBRARY",
.highlight = true,
.right = 0,
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_5_KEYS,
.y = 7 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "3",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "EQ LIB",
.highlight = true,
.right = 0,
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_5_KEYS,
.y = 7 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = minus_width,
.label_graphic_h = minus_height,
.label_graphic = minus_bitmap,
.letter = 0,
.left = "\x1b ",
.highlight = false,
.right = "\x1c",
.sub = 0 },
{.x = 0,
.y = 8 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "ON",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "CONT",
.highlight = false,
.right = "OFF",
.sub = "CANCEL"},
{.x = KB_COLUMN_WIDTH_5_KEYS,
.y = 8 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "0",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "\x04 ",
.highlight = false,
.right = "\x03",
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_5_KEYS,
.y = 8 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = ".",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "\x02 ",
.highlight = false,
.right = "\x01",
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_5_KEYS,
.y = 8 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "SPC",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "\x05 ",
.highlight = false,
.right = "\x1f",
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_5_KEYS,
.y = 8 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = plus_width,
.label_graphic_h = plus_height,
.label_graphic = plus_bitmap,
.letter = 0,
.left = "\x1d ",
.highlight = false,
.right = "\x1e",
.sub = 0 },
};

View file

@ -1,908 +0,0 @@
#include "inner.h"
color_t colors_48sx[ NB_COLORS ] = {
/* UI4X_COLOR_HP_LOGO */
{
.a = 0xFF,
.mono_rgb = 0xFF,
.gray_rgb = 0xAC,
.rgb = 0xCCA96B,
},
/* UI4X_COLOR_HP_LOGO_BG */
{
.a = 0xFF,
.mono_rgb = 0x00,
.gray_rgb = 0x41,
.rgb = 0x404040,
},
/* UI4X_COLOR_48GX_128K_RAM */
{
.a = 0xFF,
.mono_rgb = 0xFF,
.gray_rgb = 0xB9,
.rgb = 0xCAB890,
},
/* UI4X_COLOR_FRAME */
{
.a = 0xFF,
.mono_rgb = 0xFF,
.gray_rgb = 0x00,
.rgb = 0x000000,
},
/* UI4X_COLOR_UPPER_FACEPLATE_EDGE_TOP */
{
.a = 0xFF,
.mono_rgb = 0x00,
.gray_rgb = 0x7C,
.rgb = 0x9B7654,
},
/* UI4X_COLOR_UPPER_FACEPLATE */
{
.a = 0xFF,
.mono_rgb = 0x00,
.gray_rgb = 0x63,
.rgb = 0x7C5E43,
},
/* UI4X_COLOR_UPPER_FACEPLATE_EDGE_BOTTOM */
{
.a = 0xFF,
.mono_rgb = 0x00,
.gray_rgb = 0x4F,
.rgb = 0x644B35,
},
/* UI4X_COLOR_FACEPLATE_EDGE_TOP */
{
.a = 0xFF,
.mono_rgb = 0x00,
.gray_rgb = 0x58,
.rgb = 0x6D4E4E,
},
/* UI4X_COLOR_FACEPLATE */
{
.a = 0xFF,
.mono_rgb = 0x00,
.gray_rgb = 0x49,
.rgb = 0x5A4040,
},
/* UI4X_COLOR_FACEPLATE_EDGE_BOTTOM */
{
.a = 0xFF,
.mono_rgb = 0x00,
.gray_rgb = 0x3C,
.rgb = 0x4C3636,
},
/* UI4X_COLOR_KEYPAD_HIGHLIGHT */
{
.a = 0xFF,
.mono_rgb = 0x00,
.gray_rgb = 0x30,
.rgb = 0x3C2A2A,
},
/* UI4X_COLOR_BUTTON_EDGE_TOP */
{
.a = 0xFF,
.mono_rgb = 0x00,
.gray_rgb = 0x5B,
.rgb = 0x6D5D5D,
},
/* UI4X_COLOR_BUTTON */
{
.a = 0xFF,
.mono_rgb = 0x00,
.gray_rgb = 0x51,
.rgb = 0x5A4D4D,
},
/* UI4X_COLOR_BUTTON_EDGE_BOTTOM */
{
.a = 0xFF,
.mono_rgb = 0x00,
.gray_rgb = 0x45,
.rgb = 0x4C4141,
},
/* UI4X_COLOR_PIXEL_OFF */
{
.a = 0xFF,
.mono_rgb = 0xFF,
.gray_rgb = 0xCD,
.rgb = 0xCADD5C,
},
/* UI4X_COLOR_PIXEL_ON */
{
.a = 0xFF,
.mono_rgb = 0x00,
.gray_rgb = 0x14,
.rgb = 0x000080,
},
/* UI4X_COLOR_BLACK_PIXEL_OFF */
{
.a = 0xFF,
.mono_rgb = 0xFF,
.gray_rgb = 0xCD,
.rgb = 0xf5f5f5,
},
/* UI4X_COLOR_BLACK_PIXEL_ON */
{
.a = 0xFF,
.mono_rgb = 0x00,
.gray_rgb = 0x14,
.rgb = 0x000000,
},
/* UI4X_COLOR_LABEL */
{
.a = 0xFF,
.mono_rgb = 0xFF,
.gray_rgb = 0xFF,
.rgb = 0xFFFFFF,
},
/* UI4X_COLOR_ALPHA */
{
.a = 0xFF,
.mono_rgb = 0xFF,
.gray_rgb = 0xFF,
.rgb = 0xFFFFFF,
},
/* UI4X_COLOR_SHIFT_LEFT */
{
.a = 0xFF,
.mono_rgb = 0xFF,
.gray_rgb = 0xE6,
.rgb = 0xFFA600,
},
/* UI4X_COLOR_SHIFT_RIGHT */
{
.a = 0xFF,
.mono_rgb = 0xFF,
.gray_rgb = 0xA9,
.rgb = 0x00D2FF,
},
};
#define KB_LINE_HEIGHT 50
#define KB_COLUMN_WIDTH_6_KEYS 50
#define KB_COLUMN_WIDTH_5_KEYS 60
button_t buttons_48sx[ NB_HP48_KEYS ] = {
{.x = 0,
.y = 0,
.w = 36,
.h = 23,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = menu_label_width,
.label_graphic_h = menu_label_height,
.label_graphic = menu_label_bitmap,
.letter = "A",
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = KB_COLUMN_WIDTH_6_KEYS,
.y = 0,
.w = 36,
.h = 23,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = menu_label_width,
.label_graphic_h = menu_label_height,
.label_graphic = menu_label_bitmap,
.letter = "B",
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_6_KEYS,
.y = 0,
.w = 36,
.h = 23,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = menu_label_width,
.label_graphic_h = menu_label_height,
.label_graphic = menu_label_bitmap,
.letter = "C",
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_6_KEYS,
.y = 0,
.w = 36,
.h = 23,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = menu_label_width,
.label_graphic_h = menu_label_height,
.label_graphic = menu_label_bitmap,
.letter = "D",
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_6_KEYS,
.y = 0,
.w = 36,
.h = 23,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = menu_label_width,
.label_graphic_h = menu_label_height,
.label_graphic = menu_label_bitmap,
.letter = "E",
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 5 * KB_COLUMN_WIDTH_6_KEYS,
.y = 0,
.w = 36,
.h = 23,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = menu_label_width,
.label_graphic_h = menu_label_height,
.label_graphic = menu_label_bitmap,
.letter = "F",
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 0,
.y = KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "MTH",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "G",
.left = "PRINT",
.highlight = true,
.right = 0,
.sub = 0 },
{.x = KB_COLUMN_WIDTH_6_KEYS,
.y = KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "PRG",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "H",
.left = "I/O",
.highlight = true,
.right = 0,
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_6_KEYS,
.y = KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "CST",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "I",
.left = "MODES",
.highlight = true,
.right = 0,
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_6_KEYS,
.y = KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "VAR",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "J",
.left = "MEMORY",
.highlight = true,
.right = 0,
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_6_KEYS,
.y = KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = up_width,
.label_graphic_h = up_height,
.label_graphic = up_bitmap,
.letter = "K",
.left = "LIBRARY",
.highlight = true,
.right = 0,
.sub = 0 },
{.x = 5 * KB_COLUMN_WIDTH_6_KEYS,
.y = KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "NXT",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "L",
.left = "PREV",
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 0,
.y = 2 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = quote_width,
.label_graphic_h = quote_height,
.label_graphic = quote_bitmap,
.letter = "M",
.left = "UP",
.highlight = false,
.right = "HOME",
.sub = 0 },
{.x = KB_COLUMN_WIDTH_6_KEYS,
.y = 2 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "STO",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "N",
.left = "DEF",
.highlight = false,
.right = "RCL",
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_6_KEYS,
.y = 2 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "EVAL",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "O",
.left = "\x80Q",
.highlight = false,
.right = "\x80NUM",
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_6_KEYS,
.y = 2 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = left_width,
.label_graphic_h = left_height,
.label_graphic = left_bitmap,
.letter = "P",
.left = "GRAPH",
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_6_KEYS,
.y = 2 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = down_width,
.label_graphic_h = down_height,
.label_graphic = down_bitmap,
.letter = "Q",
.left = "REVIEW",
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 5 * KB_COLUMN_WIDTH_6_KEYS,
.y = 2 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = right_width,
.label_graphic_h = right_height,
.label_graphic = right_bitmap,
.letter = "R",
.left = "SWAP",
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 0,
.y = 3 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "SIN",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "S",
.left = "ASIN",
.highlight = false,
.right = "\x07",
.sub = 0 },
{.x = KB_COLUMN_WIDTH_6_KEYS,
.y = 3 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "COS",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "T",
.left = "ACOS",
.highlight = false,
.right = "\x08",
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_6_KEYS,
.y = 3 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "TAN",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "U",
.left = "ATAN",
.highlight = false,
.right = "\x09",
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_6_KEYS,
.y = 3 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = sqrt_width,
.label_graphic_h = sqrt_height,
.label_graphic = sqrt_bitmap,
.letter = "V",
.left = "\x0a",
.highlight = false,
.right = "\x0b",
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_6_KEYS,
.y = 3 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = power_width,
.label_graphic_h = power_height,
.label_graphic = power_bitmap,
.letter = "W",
.left = "\x0c",
.highlight = false,
.right = "LOG",
.sub = 0 },
{.x = 5 * KB_COLUMN_WIDTH_6_KEYS,
.y = 3 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = inv_width,
.label_graphic_h = inv_height,
.label_graphic = inv_bitmap,
.letter = "X",
.left = "\x0d",
.highlight = false,
.right = "LN",
.sub = 0 },
{.x = 0,
.y = 4 * KB_LINE_HEIGHT,
.w = 86,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "ENTER",
.font_size = 2,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "EQUATION",
.highlight = false,
.right = "MATRIX",
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_6_KEYS,
.y = 4 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = neg_width,
.label_graphic_h = neg_height,
.label_graphic = neg_bitmap,
.letter = "Y",
.left = "EDIT",
.highlight = false,
.right = "VISIT",
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_6_KEYS,
.y = 4 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "EEX",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "Z",
.left = "2D",
.highlight = false,
.right = "3D",
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_6_KEYS,
.y = 4 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "DEL",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "PURGE",
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 5 * KB_COLUMN_WIDTH_6_KEYS,
.y = 4 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = bs_width,
.label_graphic_h = bs_height,
.label_graphic = bs_bitmap,
.letter = 0,
.left = "DROP",
.highlight = false,
.right = "CLR",
.sub = 0 },
{.x = 0,
.y = 5 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = alpha_width,
.label_graphic_h = alpha_height,
.label_graphic = alpha_bitmap,
.letter = 0,
.left = "USR",
.highlight = false,
.right = "ENTRY",
.sub = 0 },
{.x = KB_COLUMN_WIDTH_5_KEYS,
.y = 5 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "7",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "SOLVE",
.highlight = true,
.right = 0,
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_5_KEYS,
.y = 5 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "8",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "PLOT",
.highlight = true,
.right = 0,
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_5_KEYS,
.y = 5 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "9",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "ALGEBRA",
.highlight = true,
.right = 0,
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_5_KEYS,
.y = 5 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = div_width,
.label_graphic_h = div_height,
.label_graphic = div_bitmap,
.letter = 0,
.left = "( )",
.highlight = false,
.right = "#",
.sub = 0 },
{.x = 0,
.y = 6 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_SHIFT_LEFT,
.label_text = 0,
.font_size = 0,
.label_graphic_w = shl_width,
.label_graphic_h = shl_height,
.label_graphic = shl_bitmap,
.letter = 0,
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = KB_COLUMN_WIDTH_5_KEYS,
.y = 6 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "4",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "TIME",
.highlight = true,
.right = 0,
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_5_KEYS,
.y = 6 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "5",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "STAT",
.highlight = true,
.right = 0,
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_5_KEYS,
.y = 6 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "6",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "UNITS",
.highlight = true,
.right = 0,
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_5_KEYS,
.y = 6 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = mul_width,
.label_graphic_h = mul_height,
.label_graphic = mul_bitmap,
.letter = 0,
.left = "[ ]",
.highlight = false,
.right = "_",
.sub = 0 },
{.x = 0,
.y = 7 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_SHIFT_RIGHT,
.label_text = 0,
.font_size = 0,
.label_graphic_w = shr_width,
.label_graphic_h = shr_height,
.label_graphic = shr_bitmap,
.letter = 0,
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = KB_COLUMN_WIDTH_5_KEYS,
.y = 7 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "1",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "RAD",
.highlight = false,
.right = "POLAR",
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_5_KEYS,
.y = 7 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "2",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "STACK",
.highlight = false,
.right = "ARG",
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_5_KEYS,
.y = 7 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "3",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "CMD",
.highlight = false,
.right = "MENU",
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_5_KEYS,
.y = 7 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = minus_width,
.label_graphic_h = minus_height,
.label_graphic = minus_bitmap,
.letter = 0,
.left = "\x0e",
.highlight = false,
.right = "\x0f",
.sub = 0 },
{.x = 0,
.y = 8 * KB_LINE_HEIGHT,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "ON",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "CONT",
.highlight = false,
.right = "OFF",
.sub = "ATTN"},
{.x = KB_COLUMN_WIDTH_5_KEYS,
.y = 8 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "0",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "= ",
.highlight = false,
.right = " \x80",
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_5_KEYS,
.y = 8 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = ".",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = ",",
.highlight = false,
.right = " \x10",
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_5_KEYS,
.y = 8 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "SPC",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "\x11 ",
.highlight = false,
.right = " \x12",
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_5_KEYS,
.y = 8 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = plus_width,
.label_graphic_h = plus_height,
.label_graphic = plus_bitmap,
.letter = 0,
.left = "{ }",
.highlight = false,
.right = ": :",
.sub = 0 },
};

View file

@ -1,940 +0,0 @@
#include "inner.h"
color_t colors_49g[ NB_COLORS ] = {
/* UI4X_COLOR_HP_LOGO */
{
.a = 0xff,
.mono_rgb = 0xff,
.gray_rgb = 0xB0,
.rgb = 0xB0B0B8,
},
/* UI4X_COLOR_HP_LOGO_BG */
{
.a = 0xff,
.mono_rgb = 0x00,
.gray_rgb = 0x68,
.rgb = 0x131313,
},
/* UI4X_COLOR_48GX_128K_RAM */
{
.a = 0xff,
.mono_rgb = 0xff,
.gray_rgb = 0xF0,
.rgb = 0xF0F0F0,
},
/* UI4X_COLOR_FRAME */
{
.a = 0xff,
.mono_rgb = 0xff,
.gray_rgb = 0x00,
.rgb = 0x000000,
},
/* UI4X_COLOR_UPPER_FACEPLATE_EDGE_TOP */
{
.a = 0xff,
.mono_rgb = 0x00,
.gray_rgb = 0x80,
.rgb = 0x000000,
},
/* UI4X_COLOR_UPPER_FACEPLATE */
{
.a = 0xff,
.mono_rgb = 0x00,
.gray_rgb = 0x68,
.rgb = 0x262626,
},
/* UI4X_COLOR_UPPER_FACEPLATE_EDGE_BOTTOM */
{
.a = 0xff,
.mono_rgb = 0x00,
.gray_rgb = 0x54,
.rgb = 0x000000,
},
/* UI4X_COLOR_FACEPLATE_EDGE_TOP */
{
.a = 0xff,
.mono_rgb = 0x00,
.gray_rgb = 0x58,
.rgb = 0x585858,
},
/* UI4X_COLOR_FACEPLATE */
{
.a = 0xff,
.mono_rgb = 0x00,
.gray_rgb = 0x4A,
.rgb = 0x272727,
},
/* UI4X_COLOR_FACEPLATE_EDGE_BOTTOM */
{
.a = 0xff,
.mono_rgb = 0x00,
.gray_rgb = 0x40,
.rgb = 0x404040,
},
/* UI4X_COLOR_KEYPAD_HIGHLIGHT */
{
.a = 0xff,
.mono_rgb = 0x00,
.gray_rgb = 0x68,
.rgb = 0x4f6165,
},
/* UI4X_COLOR_BUTTON_EDGE_TOP */
{
.a = 0xff,
.mono_rgb = 0x00,
.gray_rgb = 0x68,
.rgb = 0x4b4b4b,
},
/* UI4X_COLOR_BUTTON */
{
.a = 0xff,
.mono_rgb = 0x00,
.gray_rgb = 0x58,
.rgb = 0x3f3f3f,
},
/* UI4X_COLOR_BUTTON_EDGE_BOTTOM */
{
.a = 0xff,
.mono_rgb = 0x00,
.gray_rgb = 0x4A,
.rgb = 0x3d3d3d,
},
/* UI4X_COLOR_PIXEL_OFF */
{
.a = 0xff,
.mono_rgb = 0xff,
.gray_rgb = 0xCD,
.rgb = 0xcdcdcd,
},
/* UI4X_COLOR_PIXEL_ON */
{
.a = 0xff,
.mono_rgb = 0x00,
.gray_rgb = 0x14,
.rgb = 0x000000,
},
/* UI4X_COLOR_BLACK_PIXEL_OFF */
{
.a = 0xFF,
.mono_rgb = 0xFF,
.gray_rgb = 0xCD,
.rgb = 0xf5f5f5,
},
/* UI4X_COLOR_BLACK_PIXEL_ON */
{
.a = 0xFF,
.mono_rgb = 0x0,
.gray_rgb = 0x14,
.rgb = 0x000000,
},
/* UI4X_COLOR_LABEL */
{
.a = 0xff,
.mono_rgb = 0xff,
.gray_rgb = 0xff,
.rgb = 0xffffff,
},
/* UI4X_COLOR_ALPHA */
{
.a = 0xff,
.mono_rgb = 0xff,
.gray_rgb = 0xDC,
.rgb = 0x67c184,
},
/* UI4X_COLOR_SHIFT_LEFT */
{
.a = 0xff,
.mono_rgb = 0xff,
.gray_rgb = 0xDC,
.rgb = 0x82b1ff,
},
/* UI4X_COLOR_SHIFT_RIGHT */
{
.a = 0xff,
.mono_rgb = 0xff,
.gray_rgb = 0xA9,
.rgb = 0xff8a80,
},
};
#define KB_LINE_HEIGHT 48
#define KB_COLUMN_WIDTH_6_KEYS 50
#define KB_COLUMN_WIDTH_5_KEYS 60
button_t buttons_49g[ NB_HP49_KEYS ] = {
{.x = 0,
.y = 0,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "F1",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "A",
.left = "Y=",
.highlight = false,
.right = 0,
.sub = 0 },
{.x = KB_COLUMN_WIDTH_6_KEYS,
.y = 0,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "F2",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "B",
.left = "WIN",
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_6_KEYS,
.y = 0,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "F3",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "C",
.left = "GRAPH",
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_6_KEYS,
.y = 0,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "F4",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "D",
.left = "2D/3D",
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_6_KEYS,
.y = 0,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "F5",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "E",
.left = "TBLSET",
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 5 * KB_COLUMN_WIDTH_6_KEYS,
.y = 0,
.w = 36,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "F6",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "F",
.left = "TABLE",
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 0,
.y = 1 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "APPS",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "G",
.left = "FILES",
.highlight = false,
.right = "BEGIN",
.sub = 0 },
{.x = KB_COLUMN_WIDTH_5_KEYS,
.y = 1 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "MODE",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "H",
.left = "CUSTOM",
.highlight = false,
.right = "END",
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_5_KEYS,
.y = 1 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "TOOL",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "I",
.left = "i",
.highlight = false,
.right = "I",
.sub = 0 },
{.x = 0,
.y = 2 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "VAR",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "J",
.left = "UPDIR",
.highlight = false,
.right = "COPY",
.sub = 0 },
{.x = KB_COLUMN_WIDTH_5_KEYS,
.y = 2 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "STO",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "K",
.left = "RCL",
.highlight = false,
.right = "CUT",
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_5_KEYS,
.y = 2 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "NXT",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "L",
.left = "PREV",
.highlight = false,
.right = "PASTE",
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_5_KEYS,
.y = 1.4 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = left_width,
.label_graphic_h = left_height,
.label_graphic = left_bitmap,
.letter = 0,
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 210,
.y = 0.75 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = up_width,
.label_graphic_h = up_height,
.label_graphic = up_bitmap,
.letter = 0,
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_5_KEYS,
.y = 1.4 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = right_width,
.label_graphic_h = right_height,
.label_graphic = right_bitmap,
.letter = 0,
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 210,
.y = 2 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = down_width,
.label_graphic_h = down_height,
.label_graphic = down_bitmap,
.letter = 0,
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = 0,
.y = 3 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "HIST",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "M",
.left = "CMD",
.highlight = false,
.right = "UNDO",
.sub = 0 },
{.x = KB_COLUMN_WIDTH_5_KEYS,
.y = 3 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "CAT",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "N",
.left = "PRG",
.highlight = false,
.right = "CHARS",
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_5_KEYS,
.y = 3 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "EQW",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "O",
.left = "MTRW",
.highlight = false,
.right = "\x27",
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_5_KEYS,
.y = 3 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "SYMB",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "P",
.left = "MTH",
.highlight = false,
.right = "EVAL",
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_5_KEYS,
.y = 3 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = bs_width,
.label_graphic_h = bs_height,
.label_graphic = bs_bitmap,
.letter = 0,
.left = "DEL",
.highlight = false,
.right = "CLEAR",
.sub = 0 },
{.x = 0,
.y = 4 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = power_width,
.label_graphic_h = power_height,
.label_graphic = power_bitmap,
.letter = "Q",
.left = "\x16",
.highlight = false,
.right = "LN",
.sub = 0 },
{.x = KB_COLUMN_WIDTH_5_KEYS,
.y = 4 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = sqrt_width,
.label_graphic_h = sqrt_height,
.label_graphic = sqrt_bitmap,
.letter = "R",
.left = "\x13",
.highlight = false,
.right = "\x14",
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_5_KEYS,
.y = 4 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "SIN",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "S",
.left = "ASIN",
.highlight = false,
.right = "\x09",
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_5_KEYS,
.y = 4 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "COS",
.font_size = 2,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "T",
.left = "ACOS",
.highlight = false,
.right = "\x07",
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_5_KEYS,
.y = 4 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "TAN",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "U",
.left = "ATAN",
.highlight = false,
.right = "\x08",
.sub = 0 },
{.x = 0,
.y = 5 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "EEX",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "V",
.left = "\x15",
.highlight = false,
.right = "LOG",
.sub = 0 },
{.x = KB_COLUMN_WIDTH_5_KEYS,
.y = 5 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = neg_width,
.label_graphic_h = neg_height,
.label_graphic = neg_bitmap,
.letter = "W",
.left = "\x60",
.highlight = false,
.right = "=",
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_5_KEYS,
.y = 5 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "X",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = "X",
.left = "\x3b",
.highlight = false,
.right = "\x3c",
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_5_KEYS,
.y = 5 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = inv_width,
.label_graphic_h = inv_height,
.label_graphic = inv_bitmap,
.letter = "Y",
.left = "\x3f",
.highlight = false,
.right = "\x3e",
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_5_KEYS,
.y = 5 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = div_width,
.label_graphic_h = div_height,
.label_graphic = div_bitmap,
.letter = "Z",
.left = "ABS ",
.highlight = false,
.right = "ARG",
.sub = 0 },
{.x = 0,
.y = 6 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_ALPHA,
.label_text = 0,
.font_size = 0,
.label_graphic_w = alpha_width,
.label_graphic_h = alpha_height,
.label_graphic = alpha_bitmap,
.letter = 0,
.left = "USER",
.highlight = false,
.right = "ENTRY",
.sub = 0 },
{.x = KB_COLUMN_WIDTH_5_KEYS,
.y = 6 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "7",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "S.SLV",
.highlight = false,
.right = "N.SLV", //"NUM.SLV",
.sub = 0},
{.x = 2 * KB_COLUMN_WIDTH_5_KEYS,
.y = 6 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "8",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "EXP", //"EXP&LN",
.highlight = false,
.right = "TRIG",
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_5_KEYS,
.y = 6 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "9",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "FIN.", //"FINANCE",
.highlight = false,
.right = "TIME",
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_5_KEYS,
.y = 6 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = mul_width,
.label_graphic_h = mul_height,
.label_graphic = mul_bitmap,
.letter = 0,
.left = "\x19 ",
.highlight = false,
.right = "\x1c",
.sub = 0 },
{.x = 0,
.y = 7 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_SHIFT_LEFT,
.label_text = 0,
.font_size = 0,
.label_graphic_w = shl_width,
.label_graphic_h = shl_height,
.label_graphic = shl_bitmap,
.letter = 0,
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = KB_COLUMN_WIDTH_5_KEYS,
.y = 7 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "4",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "CALC",
.highlight = false,
.right = "ALG",
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_5_KEYS,
.y = 7 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "5",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "MATR.", //"MATRICES",
.highlight = false,
.right = "STAT",
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_5_KEYS,
.y = 7 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "6",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "CNVRT", //"CONVERT",
.highlight = false,
.right = "UNITS",
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_5_KEYS,
.y = 7 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = minus_width,
.label_graphic_h = minus_height,
.label_graphic = minus_bitmap,
.letter = 0,
.left = "\x17 ",
.highlight = false,
.right = "\x1a",
.sub = 0 },
{.x = 0,
.y = 8 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_SHIFT_RIGHT,
.label_text = 0,
.font_size = 0,
.label_graphic_w = shr_width,
.label_graphic_h = shr_height,
.label_graphic = shr_bitmap,
.letter = 0,
.left = 0,
.highlight = false,
.right = 0,
.sub = 0 },
{.x = KB_COLUMN_WIDTH_5_KEYS,
.y = 8 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "1",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "ARITH",
.highlight = false,
.right = "CMPLX",
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_5_KEYS,
.y = 8 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "2",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "DEF",
.highlight = false,
.right = "LIB",
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_5_KEYS,
.y = 8 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "3",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "\x23",
.highlight = false,
.right = "BASE",
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_5_KEYS,
.y = 8 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = 0,
.font_size = 0,
.label_graphic_w = plus_width,
.label_graphic_h = plus_height,
.label_graphic = plus_bitmap,
.letter = 0,
.left = "\x1d ",
.highlight = false,
.right = "\x1b",
.sub = 0 },
{.x = 0,
.y = 9 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "ON",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "CONT",
.highlight = false,
.right = "OFF",
.sub = "CANCEL" },
{.x = KB_COLUMN_WIDTH_5_KEYS,
.y = 9 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "0",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "\x7e",
.highlight = false,
.right = "\x03",
.sub = 0 },
{.x = 2 * KB_COLUMN_WIDTH_5_KEYS,
.y = 9 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = ".",
.font_size = 1,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "\x1e",
.highlight = false,
.right = "\x01",
.sub = 0 },
{.x = 3 * KB_COLUMN_WIDTH_5_KEYS,
.y = 9 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "SPC",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "\x05 ",
.highlight = false,
.right = "\x02",
.sub = 0 },
{.x = 4 * KB_COLUMN_WIDTH_5_KEYS,
.y = 9 * KB_LINE_HEIGHT,
.w = 46,
.h = 26,
.label_color = UI4X_COLOR_LABEL,
.label_text = "ENTER",
.font_size = 0,
.label_graphic_w = 0,
.label_graphic_h = 0,
.label_graphic = 0,
.letter = 0,
.left = "ANS ",
.highlight = false,
.right = "\x06NUM",
.sub = 0 },
};

View file

@ -1,33 +0,0 @@
#include <stdlib.h>
#include "common.h"
#include "inner.h"
#include "sdl2.h"
#include "ncurses.h"
void ( *ui_get_event )( void );
void ( *ui_update_display )( void );
void ( *ui_start )( config_t* config );
void ( *ui_stop )( void );
void setup_ui( config_t* config )
{
switch ( config->frontend ) {
case FRONTEND_NCURSES:
setup_frontend_ncurses();
break;
case FRONTEND_SDL:
default:
setup_frontend_sdl();
break;
}
}
void close_and_exit( void )
{
exit_emulator();
ui_stop();
exit( 0 );
}

View file

@ -1,567 +0,0 @@
#include <assert.h>
#include <errno.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <libgen.h>
#include <getopt.h>
#include <lua.h>
#include <lauxlib.h>
#include "config.h"
#include "../debug.h"
#ifndef LUA_OK
# define LUA_OK 0
#endif
static config_t config = {
.progname = ( char* )"saturn4xxx",
.model = MODEL_48GX,
.throttle = false,
.verbose = false,
.shiftless = false,
.big_screen = false,
.black_lcd = false,
.frontend = FRONTEND_SDL,
.mono = false,
.gray = false,
.chromeless = false,
.fullscreen = false,
.scale = 1.0,
.tiny = false,
.small = false,
/* from args.h */
.reset = false,
.monitor = false,
.batchXfer = false,
.state_dir_path = ( char* )".",
.debug_level = DEBUG_C_NONE,
.enable_BUSCC = false,
};
lua_State* config_lua_values;
static inline bool config_read( const char* filename )
{
int rc;
assert( filename != NULL );
/*---------------------------------------------------
; Create the Lua state, which includes NO predefined
; functions or values. This is literally an empty
; slate.
;----------------------------------------------------*/
config_lua_values = luaL_newstate();
if ( config_lua_values == NULL ) {
fprintf( stderr, "cannot create Lua state\n" );
return false;
}
/*-----------------------------------------------------
; For the truly paranoid about sandboxing, enable the
; following code, which removes the string library,
; which some people find problematic to leave un-sand-
; boxed. But in my opinion, if you are worried about
; such attacks in a configuration file, you have bigger
; security issues to worry about than this.
;------------------------------------------------------*/
#ifdef PARANOID
lua_pushliteral( config_lua_values, "x" );
lua_pushnil( config_lua_values );
lua_setmetatable( config_lua_values, -2 );
lua_pop( config_lua_values, 1 );
#endif
/*-----------------------------------------------------
; Lua 5.2+ can restrict scripts to being text only,
; to avoid a potential problem with loading pre-compiled
; Lua scripts that may have malformed Lua VM code that
; could possibly lead to an exploit, but again, if you
; have to worry about that, you have bigger security
; issues to worry about. But in any case, here I'm
; restricting the file to "text" only.
;------------------------------------------------------*/
rc = luaL_loadfile( config_lua_values, filename );
if ( rc != LUA_OK ) {
fprintf( stderr, "Lua error: (%d) %s\n", rc, lua_tostring( config_lua_values, -1 ) );
return false;
}
rc = lua_pcall( config_lua_values, 0, 0, 0 );
if ( rc != LUA_OK ) {
fprintf( stderr, "Lua error: (%d) %s\n", rc, lua_tostring( config_lua_values, -1 ) );
return false;
}
return true;
}
static void print_config( void )
{
fprintf( stdout, "--------------------------------------------------------------------------------\n" );
fprintf( stdout, "-- Configuration file for saturnng\n" );
fprintf( stdout, "-- This is a comment\n" );
fprintf( stdout, "model = \"" );
switch ( config.model ) {
case MODEL_48GX:
fprintf( stdout, "48gx" );
break;
case MODEL_48SX:
fprintf( stdout, "48sx" );
break;
case MODEL_40G:
fprintf( stdout, "40g" );
break;
case MODEL_49G:
fprintf( stdout, "49g" );
break;
}
fprintf( stdout, "\" -- possible values: \"48gx\", \"48sx\", \"40g\", \"49g\"\n" );
fprintf( stdout, "\n" );
fprintf( stdout, "verbose = %s\n", config.verbose ? "true" : "false" );
fprintf( stdout, "throttle = %s\n", config.throttle ? "true" : "false" );
fprintf( stdout, "\n" );
fprintf( stdout, "monitor = %s\n", config.monitor ? "true" : "false" );
fprintf( stdout, "\n" );
fprintf( stdout, "--------------------\n" );
fprintf( stdout, "-- User Interface --\n" );
fprintf( stdout, "--------------------\n" );
fprintf( stdout, "frontend = \"" );
switch ( config.frontend ) {
case FRONTEND_SDL:
fprintf( stdout, "sdl" );
break;
case FRONTEND_NCURSES:
fprintf( stdout, "tui" );
if ( config.small )
fprintf( stdout, "-small" );
else if ( config.tiny )
fprintf( stdout, "-tiny" );
break;
}
fprintf( stdout, "\" -- possible values: \"sdl\", \"tui\", \"tui-small\", \"tui-tiny\"\n" );
fprintf( stdout, "\n" );
fprintf( stdout, "gray = %s\n", config.gray ? "true" : "false" );
fprintf( stdout, "mono = %s\n", config.mono ? "true" : "false" );
fprintf( stdout, "\n" );
fprintf( stdout, " -- Following options are specific to sdl frontend\n" );
fprintf( stdout, "big_screen = %s\n", config.big_screen ? "true" : "false" );
fprintf( stdout, "black_lcd = %s\n", config.black_lcd ? "true" : "false" );
fprintf( stdout, "chromeless = %s\n", config.chromeless ? "true" : "false" );
fprintf( stdout, "fullscreen = %s\n", config.fullscreen ? "true" : "false" );
fprintf( stdout, "scale = %f\n", config.scale );
fprintf( stdout, "shiftless = %s\n", config.shiftless ? "true" : "false" );
fprintf( stdout, "\n" );
fprintf( stdout, "--- End of saturnng configuration ----------------------------------------------\n" );
}
/* Path/name dynamic allocator */
static char* normalize_filename( char* path, char* name )
{
char* s = malloc( strlen( path ) + strlen( name ) + 2 );
strcpy( s, path );
strcat( s, "/" );
strcat( s, name );
return s;
}
config_t* config_init( int argc, char* argv[] )
{
int option_index;
int c = '?';
char* config_file_name = ( char* )"config.lua";
char* mod_file_name = ( char* )"mod";
char* cpu_file_name = ( char* )"cpu";
char* hdw_file_name = ( char* )"hdw";
char* rom_file_name = ( char* )"rom";
char* ram_file_name = ( char* )"ram";
char* port_1_file_name = ( char* )"port1";
char* port_2_file_name = ( char* )"port2";
int print_config_and_exit = false;
int clopt_model = -1;
int clopt_verbose = -1;
int clopt_big_screen = -1;
int clopt_black_lcd = -1;
int clopt_throttle = -1;
int clopt_shiftless = -1;
int clopt_frontend = -1;
int clopt_mono = -1;
int clopt_gray = -1;
int clopt_chromeless = -1;
int clopt_fullscreen = -1;
double clopt_scale = -1.0;
int clopt_tiny = -1;
int clopt_small = -1;
int clopt_reset = -1;
int clopt_monitor = -1;
/* int clopt_batchXfer = -1; */
int clopt_enable_BUSCC = -1;
char* clopt_state_dir_path = ( char* )".";
const char* optstring = "h";
struct option long_options[] = {
{"help", no_argument, NULL, 'h' },
{"verbose", no_argument, &clopt_verbose, true },
{"print-config", no_argument, &print_config_and_exit, true },
{"throttle", no_argument, &clopt_throttle, true },
{"big-screen", no_argument, &clopt_big_screen, true },
{"black-lcd", no_argument, &clopt_black_lcd, true },
{"48sx", no_argument, &clopt_model, MODEL_48SX },
{"48gx", no_argument, &clopt_model, MODEL_48GX },
{"40g", no_argument, &clopt_model, MODEL_40G },
{"49g", no_argument, &clopt_model, MODEL_49G },
{"reset", no_argument, &clopt_reset, true },
{"monitor", no_argument, &clopt_monitor, true },
/* {"batchXfer", no_argument, &clopt_batchXfer, true }, */
{"state-dir", required_argument, NULL, 8999 },
{"shiftless", no_argument, &clopt_shiftless, true },
{"gui", no_argument, &clopt_frontend, FRONTEND_SDL },
{"chromeless", no_argument, &clopt_chromeless, true },
{"fullscreen", no_argument, &clopt_fullscreen, true },
{"scale", required_argument, NULL, 7110 },
{"tui", no_argument, &clopt_frontend, FRONTEND_NCURSES},
{"tui-small", no_argument, NULL, 6110 },
{"tui-tiny", no_argument, NULL, 6120 },
{"mono", no_argument, &clopt_mono, true },
{"gray", no_argument, &clopt_gray, true },
{"debug-opcodes", no_argument, NULL, 38601 },
/* {"debug-xx", no_argument, NULL, 38602 }, */
{"debug-x-func", no_argument, NULL, 38603 },
{"debug-flash", no_argument, NULL, 38604 },
{"debug-implementation", no_argument, NULL, 38605 },
{"debug-mod-cache", no_argument, NULL, 38606 },
{"debug-serial", no_argument, NULL, 38607 },
{"debug-timers", no_argument, NULL, 38608 },
{"debug-interruptions", no_argument, NULL, 38609 },
{"debug-display", no_argument, NULL, 38610 },
{"debug-modules", no_argument, NULL, 38611 },
{"debug-trace", no_argument, NULL, 38612 },
{"implement-BUSCC", no_argument, &clopt_enable_BUSCC, true },
{0, 0, 0, 0 }
};
const char* help_text = "usage: %s [options]\n"
"options:\n"
" -h --help what you are reading\n"
" --print-config output current configuration to stdout and exit (in config.lua formatting)\n"
" --verbose display more informations\n"
" --throttle throttle CPU speed\n"
" --big-screen 131×80 screen (default: false)\n"
" --black-lcd (default: false)\n"
" --48gx emulate a HP 48GX\n"
" --48sx emulate a HP 48SX\n"
" --40g emulate a HP 40G\n"
" --49g emulate a HP 49G\n"
" --state-dir=<path> use a different data directory "
"(default: ~/.config/saturnMODEL/)\n"
" --gui graphical (SDL2) front-end (default: true)\n"
" --tui text front-end (default: false)\n"
" --tui-small text small front-end (2×2 pixels per character) (default: "
"false)\n"
" --tui-tiny text tiny front-end (2×4 pixels per character) (default: "
"false)\n"
" --chromeless only show display (default: "
"false)\n"
" --fullscreen make the UI fullscreen "
"(default: false)\n"
" --scale=<n> make the UI scale <n> times "
"(default: 1.0)\n"
" --mono make the UI monochrome (default: "
"false)\n"
" --gray make the UI grayscale (default: "
"false)\n"
" --shiftless don't map the shift keys to let them free for numbers (default: "
"false)\n"
" --reset force a reset\n"
" --monitor start with monitor (default: no)\n"
"\n"
" --debug-opcodes enables debugging opcodes (default: no)\n"
/* " --debug- enables debugging something (default: no)\n" */
" --debug-x-func enables debugging extended functions (default: no)\n"
" --debug-flash enables debugging flash (default: no)\n"
" --debug-implementation enables debugging implementation (default: no) (UNUSED)\n"
" --debug-mod-cache enables debugging mod cache (default: no)\n"
" --debug-serial enables debugging serial (default: no)\n"
" --debug-timers enables debugging timers (default: no)\n"
" --debug-interruptions enables debugging interruptions (default: no)\n"
" --debug-display enables debugging display (default: no) (UNUSED)\n"
" --debug-modules enables debugging modules (default: no)\n"
" --debug-trace enables debugging trace (default: no)\n";
while ( c != EOF ) {
c = getopt_long( argc, argv, optstring, long_options, &option_index );
switch ( c ) {
case 'h':
fprintf( stdout, help_text, config.progname );
exit( EXIT_SUCCESS );
break;
case 6110:
clopt_frontend = FRONTEND_NCURSES;
clopt_small = true;
break;
case 6120:
clopt_frontend = FRONTEND_NCURSES;
clopt_tiny = true;
break;
case 7110:
clopt_scale = atof( optarg );
break;
case 8999:
clopt_state_dir_path = optarg;
break;
case 38601:
config.debug_level |= DEBUG_C_OPCODES;
break;
/* case 38602: */
/* config.debug_level |= DEBUG_C_XX; */
/* break; */
case 38603:
config.debug_level |= DEBUG_C_X_FUNC;
break;
case 38604:
config.debug_level |= DEBUG_C_FLASH;
break;
case 38605:
config.debug_level |= DEBUG_C_IMPLEMENTATION;
break;
case 38606:
config.debug_level |= DEBUG_C_MOD_CACHE;
break;
case 38607:
config.debug_level |= DEBUG_C_SERIAL;
break;
case 38608:
config.debug_level |= DEBUG_C_TIMERS;
break;
case 38609:
config.debug_level |= DEBUG_C_INT;
break;
case 38610:
config.debug_level |= DEBUG_C_DISPLAY;
break;
case 38611:
config.debug_level |= DEBUG_C_MODULES;
break;
case 38612:
config.debug_level |= DEBUG_C_TRACE;
break;
default:
break;
}
}
if ( clopt_state_dir_path != NULL )
config.state_dir_path = strdup( clopt_state_dir_path );
config.config_file_name = normalize_filename( config.state_dir_path, config_file_name );
config.mod_file_name = normalize_filename( config.state_dir_path, mod_file_name );
config.cpu_file_name = normalize_filename( config.state_dir_path, cpu_file_name );
config.hdw_file_name = normalize_filename( config.state_dir_path, hdw_file_name );
config.rom_file_name = normalize_filename( config.state_dir_path, rom_file_name );
config.ram_file_name = normalize_filename( config.state_dir_path, ram_file_name );
config.port_1_file_name = normalize_filename( config.state_dir_path, port_1_file_name );
config.port_2_file_name = normalize_filename( config.state_dir_path, port_2_file_name );
/**********************/
/* 1. read config.lua */
/**********************/
bool haz_config_file = config_read( config.config_file_name );
if ( haz_config_file ) {
lua_getglobal( config_lua_values, "verbose" );
config.verbose = lua_toboolean( config_lua_values, -1 );
lua_getglobal( config_lua_values, "throttle" );
config.throttle = lua_toboolean( config_lua_values, -1 );
lua_getglobal( config_lua_values, "big_screen" );
config.big_screen = lua_toboolean( config_lua_values, -1 );
lua_getglobal( config_lua_values, "black_lcd" );
config.black_lcd = lua_toboolean( config_lua_values, -1 );
lua_getglobal( config_lua_values, "chromeless" );
config.chromeless = lua_toboolean( config_lua_values, -1 );
lua_getglobal( config_lua_values, "fullscreen" );
config.fullscreen = lua_toboolean( config_lua_values, -1 );
lua_getglobal( config_lua_values, "gray" );
config.gray = lua_toboolean( config_lua_values, -1 );
lua_getglobal( config_lua_values, "mono" );
config.mono = lua_toboolean( config_lua_values, -1 );
lua_getglobal( config_lua_values, "shiftless" );
config.shiftless = lua_toboolean( config_lua_values, -1 );
lua_getglobal( config_lua_values, "monitor" );
config.monitor = lua_toboolean( config_lua_values, -1 );
lua_getglobal( config_lua_values, "model" );
const char* svalue_model = luaL_optstring( config_lua_values, -1, "49g" );
if ( svalue_model != NULL ) {
if ( strcmp( svalue_model, "49g" ) == 0 )
config.model = MODEL_49G;
if ( strcmp( svalue_model, "40g" ) == 0 )
config.model = MODEL_40G;
if ( strcmp( svalue_model, "48gx" ) == 0 )
config.model = MODEL_48GX;
if ( strcmp( svalue_model, "48sx" ) == 0 )
config.model = MODEL_48SX;
}
lua_getglobal( config_lua_values, "frontend" );
const char* svalue = luaL_optstring( config_lua_values, -1, "sdl" );
if ( svalue != NULL ) {
if ( strcmp( svalue, "sdl" ) == 0 )
config.frontend = FRONTEND_SDL;
if ( strcmp( svalue, "tui" ) == 0 ) {
config.frontend = FRONTEND_NCURSES;
config.small = false;
config.tiny = false;
}
if ( strcmp( svalue, "tui-small" ) == 0 ) {
config.frontend = FRONTEND_NCURSES;
config.small = true;
config.tiny = false;
}
if ( strcmp( svalue, "tui-tiny" ) == 0 ) {
config.frontend = FRONTEND_NCURSES;
config.small = false;
config.tiny = true;
}
}
lua_getglobal( config_lua_values, "scale" );
config.scale = luaL_optnumber( config_lua_values, -1, 1.0 );
}
/****************************************************/
/* 2. treat command-line params which have priority */
/****************************************************/
if ( clopt_verbose != -1 )
config.verbose = clopt_verbose == true;
if ( clopt_model != -1 )
config.model = clopt_model;
if ( clopt_throttle != -1 )
config.throttle = clopt_throttle == true;
if ( clopt_big_screen != -1 )
config.big_screen = clopt_big_screen == true;
if ( clopt_black_lcd != -1 )
config.black_lcd = clopt_black_lcd == true;
if ( clopt_frontend != -1 )
config.frontend = clopt_frontend;
if ( clopt_chromeless != -1 )
config.chromeless = clopt_chromeless == true;
if ( clopt_fullscreen != -1 )
config.fullscreen = clopt_fullscreen == true;
if ( clopt_scale > 0.0 )
config.scale = clopt_scale;
if ( clopt_mono != -1 )
config.mono = clopt_mono == true;
if ( clopt_small != -1 )
config.small = clopt_small == true;
if ( clopt_tiny != -1 )
config.tiny = clopt_tiny == true;
if ( clopt_gray != -1 )
config.gray = clopt_gray == true;
if ( clopt_shiftless != -1 )
config.shiftless = clopt_shiftless == true;
if ( clopt_reset != -1 )
config.reset = clopt_reset;
if ( clopt_monitor != -1 )
config.monitor = clopt_monitor;
/* if ( clopt_batchXfer != -1 ) */
/* config.batchXfer = clopt_batchXfer; */
if ( clopt_enable_BUSCC != -1 )
config.enable_BUSCC = clopt_enable_BUSCC;
if ( config.model == MODEL_49G )
config.black_lcd = true;
config.progname = basename( strdup( argv[ 0 ] ) );
switch ( config.model ) {
case MODEL_48GX:
strcat( config.progname, "48gx" );
break;
case MODEL_48SX:
strcat( config.progname, "48sx" );
break;
case MODEL_49G:
strcat( config.progname, "49g" );
break;
case MODEL_40G:
strcat( config.progname, "40g" );
break;
}
if ( config.verbose ) {
if ( !print_config_and_exit )
print_config();
if ( optind < argc ) {
fprintf( stderr, "%i invalid arguments : ", argc - optind );
while ( optind < argc )
fprintf( stderr, "%s\n", argv[ optind++ ] );
fprintf( stderr, "\n" );
}
}
if ( print_config_and_exit ) {
print_config();
exit( EXIT_SUCCESS );
}
if ( !haz_config_file ) {
fprintf( stdout, "\nConfiguration file %s doesn't seem to exist or is invalid!\n", config.config_file_name );
fprintf( stdout, "You can solve this by running `mkdir -p %s && %s --print-config >> %s`\n\n", config.state_dir_path,
config.progname, config.config_file_name );
}
return &config;
}

Some files were not shown because too many files have changed in this diff Show more