Home Dokumente Links

Emulatoren

HP48 Emulator

Nacheiferer IV

von Michael Mustun


x48 emuliert einen HP48 Taschenrecher. Was für Stolpersteine einem bei der Inbetriebnahme dieses Emulators begegnen können, und was man mit dem Taschenrechner der Taschenrechner sonst noch so machen kann, ist hier zu lesen.

Wer kennt ihn nicht -- den HP48 Taschenrechner. Doch wie man eine 128K RAM Karte baut, den Rechner in Assembler, RPL oder C programmiert, oder gar den Rechner öffnet -- das alles und mehr ist im Internet zu finden (s. Tabelle Infos und Quellen rund um den HP48) und dürfte so manchen Hunger nach mehr Informationen und Daten zu diesem Klassiker unter den Taschenrechner stillen.


Abbildung 1: Nur eine der vielen Web-Seiten über den HP48...

Oder wie wäre es mit einer kompletten Emulation auf Ihrem Linux Rechner? x48 ist ein solcher Emulator. Er emuliert einen Hewlett-Packards HP48 S/SX oder G/GX, je nach Wunsch (genauer: je nach ROM-Datei). Dieser Artikel beschreibt nebst der Beschaffung der Quellen, Kompilierung, Installation und Konfiguration auch die Tücken, die einem dabei über Weg laufen können.

Unterstützt wird:

  • HP48 S/SX und G/GX
  • Erweiterungs-Karten (128K oder 32K auf dem SX, bis 4M auf dem GX)
  • der serielle Port des x48 geht auf das Filesystem
  • die IR-Schnittstelle des x48 geht auf die serielle Leitung des PC's (Einschränkung auf max. 2400 Baud)
  • Sound (nur über eine Soundkarte?)

Nicht unterstützt wird:

  • ?

Benötigt wird:

  • Ihr HP Taschenrechner für die ROM-Datei
  • X-Window-System (X11)
  • Ein serielles Kabel für die Datenübertragung (Wer noch eine serielles Kabel braucht, findet unter [1] eine gute Bauanleitung.)

(Übrigens, ein HP48 Emulator gibt's nicht nur für Unix-Systeme, Emu48 ist z.B. eine Version für DOS/Windows....aber wir interessieren uns hier natürlich für die Version unter Linux... :)

Installation

Zuerst muss man sich den Quellcode beschaffen. Die Quellen findet man unter ftp://www.sunsite.unc.edu im Verzeichnis /pub/Linux/system/Emulators/, oder entsprechend auf den Sunsite-Mirrors.
Nach dem Download kann die Datei x48-0.4.0.tar.gz mit tar xzfv x48-0.4.0.tar.gz entpackt werden. Weiter sollte man noch ein chown und chgrp ausführen, # chown -R root x48-0.4.0, chgrp -R root x48-0.4.0 erledigt das.

Im Verzeichnis 'x48-0.4.0' muss die Datei config.h editiert werden. Hier werden Compiler-Flags, aber vor allem das Betriebssystem eingestellt.

Datei config.h

/*
* If you have class (hp48 assembler),
* uncomment the following line
*/
/* #define HAVE_CLASS */

/*
* If you don't have the XShm extension,
* comment the following line
*/
/* #define HAVE_XSHM */

/*
* Which OS are you on?
*/
#define UNIX_DEF -DLINUX
/* #define UNIX_DEF -DSOLARIS */
/* #define UNIX_DEF -DSUNOS */
/* #define UNIX_DEF -DIRIX */
/* #define UNIX_DEF -DHPUX */
Die Eingabe von
  1. xmkmf
2. make
im Verzeichnis 'x48-0.4.0' unter X-Window erzeugt den Emulator x48, den ASCII-ROM-file-to-bin-file Converter dump2rom und das ROM-Checkprogramm checkrom; weiter das Hilfprogramm für die Erweiterungskarten mkcard.

Schon nach kurzer Zeit läuft make mit der Fehlermeldung

cd src ; make all
make[1]: Entering directory `/tmpinst/ \
Emulators/x48-0.4.0/src'
Makefile:581: *** missing separator. Stop.
make[1]: Leaving directory `/tmpinst/ \
Emulators/x48-0.4.0/src'
make: *** [all] Error 2
in den Hammer. Offensichlich liegt ein Bug im automatisch erzeugten "/src/Makefile" vor. Wir schauen nach und finden die Zeilen:
577 $(BIN)/mkcard: $(OBJS4) $(DEPLIBS4)
578 $(RM) $@
579 $(CC) -o $@ $(LDOPTIONS) \
$(OBJS4) $(LDLIBS) $(EXTRA_LOAD_FLAGS)
580
581 SaberProgramTarget($(BIN)/mkcard, \
$(SRCS4),$(OBJS4),,)
582
In Zeile 581 fehlt ein Doppelpunkt nach "SaberProgramTarget". Wir korrigieren den Fehler aber nicht im Makefile; denn schon die "/src/Imakefile" Datei könnte falsch sein. Also suchen wir nach 'SaberProgramTarget'. Wir werden fündig:
98 #ifndef ComplexProgramTarget_4
99 #define ComplexProgramTarget_4(program, \
locallib,syslib) @@\
100 program: $(OBJS4) $(DEPLIBS4) @@\
101 RemoveTargetProgram($@) @@\
102 $(CC) -o $@ $(LDOPTIONS) \
$(OBJS4) locallib $(LDLIBS) syslib \
$(EX TRA_LOAD_FLAGS) @@\
103 @@\
104 SaberProgramTarget(program,$(SRCS4), \
$(OBJS4),locallib,syslib) @@\
105 @@\
106 InstallProgram(program,$(BINDIR)) @@\
107 InstallManPage(program,$(MANDIR))
108 #endif /* ComplexProgramTarget_4 */
Nach "SaberProgramTarget" muss ein Doppelpunkt (:) gefolgt von mindestens einem Leerzeichen eingefügt werden. Die neue Zeile heisst jetzt:
104 SaberProgramTarget:	  (program,$(SRCS4), \
$(OBJS4),locallib,syslib) @@\
Nach diesen Korrekturen und nochmaligem 'xmkmf' und 'make' wird alles übersetzt.

Nun muss alles noch an den richtigen Ort. make -n install liefert schon mal, wo das Programm überall Dateien hinkopiert, ohne dabei eine Aktion auszuführen. Die Binärdateien kämen ins Verzeichnis '/usr/X11R6/bin', und die globale Application-Default-Datei würde mit den Permission Bits 0444 ins '/usr/X11R6/lib/X11/app-defaults/X48' Verzeichnis kopiert. Ist man damit einverstanden, kann der x48 mit make install installiert werden.
Mit der Eingabe von # make -n install BINDIR=/usr/local/bin kann ein anderes Installations-Verzeichnis angegeben werden.

Wir wählen aber mal die Installation von Hand. Die bietet nähmlich den Vorteil, alle Dateien von einem Programm in einem Verzeichnis zu haben-- - wenn das Programm einen Update erhalten soll, so genügt ein Anpassen der Links.

  • Alles wird ins Verzeichnis '/usr/local/x48/' kopiert.
  • Danach werden die gewünschten Permission Bits gesetzt.
  • Nun müssen noch ein paar Links gemacht werden:
    • 'cd /usr/local/bin/', 'ln -s /usr/local/x48/bin/x48', dasselbe für 'checkrom', 'dump2rom' und 'mkcard'
    • und mit 'cd /usr/X11R6/lib/X11/app-defaults/', 'ln -s /usr/local/x48/src/X48.ad X48' für die Application Default Datei.
  • fertig!

Wer nicht selber kompilieren will, findet unter [2] die Linux-ELF Version.

Für den Betrieb der seriellen Schnittstelle müssen noch Einträge in der Datei '.Xdefaults' (oder jenachdem, in welcher Datei die eigenen Resourceneinstellungen vorgenommen werden) konfiguriert werden. Mit xrdb -merge .Xdefaults werden die Einträge aktiv.

x48*useSerial:  True
x48*serialLine: /dev/ttyS0
; your serial device here, this
; looks good for Linux.

Für weitere Infos schaue man in der Datei x48-0.4.0/src/X48.ad nach.

ROM Dump...

Nun benötigen wir noch das ROM-Dump. Das wird mit dem mitgeliefertem Program ROMDump im Verzeichnis 'romdump' erledigt. Dieses Programm wird auf den HP geladen. Dann wird auf dem PC ein Kermit-Programm mit der Übertragunsrate von 9600 Baud gestartet, weiter müssen die empfangenen Daten mit log session in eine ASCII-Datei gespeichert werden. Um ein Verbindungsaufbau von Seiten PC zu starten, muss noch connect eingegeben werden.

Auf dem HP kann nun mit der Eingabe von #0h #7FFFFh ROMDump (HP48 S/SX) oder #0h #FFFFFh ROMDump (HP48 G/GX) der Vorgang gestartet werden. Eine Wartezeit von ca. 30 Minuten ist nun angesagt...
Nach der Übertragung kann die Verbindung abgebrochen werden. Der ROM-Dump sollte nun in der Datei session.log sein. Diese Datei hat etwa folgenden Inhalt:

#00000:2369B108DADF1008
...
(und so weiter...)
Diese ASCII-Datei kann dann mit dem Programm-Aufruf dump2rom session.log in (endlich) eine für den Emulator lesbare binäre ROM-Dump Datei namens rom.dump konvertiert werden.

Gesagt getan. Das Programm #0h #7FFFFh ROMDump kommt aber nur von #0h bis #03F0h... (ein Programmfehler?!)
Nun, es gibt auch eine HP interne Routine, die eingentlich dasselbe erledigt (nur etwas langsamer wegen den Bildschirmausgaben). Und das geht so:
Die Tastenkombination [on] + [D] versetzt den HP in einen 'speziellen' Modus (Aber Achtung! Bitte vorher alle Daten sichern!). Weiter geht's mit [(backspace)]. Nun sieht man etwa folgendes:

705D9:1B8DB178E5A111B6
Links neben dem Doppelpunkt steht die Adresse, rechts die Bytes. Mit der Taste [del] kann die Adresse auf C0000 eingestellt werden. Nun muss mit der Taste [(pfeil-nach-unten)] die Adresse auf 00000 eingestellt werden. Die Taste [.] (Punkt) wird die aktuelle Zeile gesendet; mit der Taste [spc] (Space) wird ab der aktuellen Zeile gesendet...bis mit [on] + [c] unterbrochen wird. Allerdings stopt der Prozess alle paar Minuten -- ein Druck auf die Taste [spc] macht aber brav weiter... Hat man alle gewünschten Bytes, so kann die Verbindung abgebrochen werden. Endlich haben wir die ASCII-ROM-Datei!

Aber auch das Programm 'dump2rom' macht Probleme. Die Eingabe dump2rom session.log endet mit einem einer Fehlermeldung. Wieso? Weil die Datei nicht unter Linux, sondern mit einem Kermit Programm unter DOS empfangen wurde, enthält die ASCII-Datei noch nach jeder Zeile ein CR (Carriage Return, Hex 0Dh). Dieses Byte muss weg. Das geht so:

# cat session.log | tr "\r" "x" > session2.log
# sed -e 's/x//' session2.log > session3.log
(Natürlich währe das alles nicht nötig gewesen, wenn wir direkt unter Linux mit kermit die ASCII-Datei empfangen hätten --aber eben-- wenn es sein muss, geht's auch so...).
Die cat-tr Zeile ersetzt jedes DOS CR (=0x0d) in ein 'x'. Die sed Zeile löscht dieses 'x'. Das Ergebnis ist eine 'reine' Unix ASCII-Datei mit Zeilenabschlusszeichen LF (=0x0a).
(PS: Ein WinNT Anwender müsste hier wohl passen...)
Nun kann mit dump2rom session3.log die fertige Datei 'rom.dump' erstellt werden.

Den ROM-Dump kann man nun auch noch gleich mit checkrom rom.dump auf Korrektheit überprüfen. Das sieht so aus (abhängig von der ROM-Version):

# ./checkrom rom.dump
ROM Version is HP48-J
ROM CRC reads 0x9602
IROM OK: ROM CRC test passed.
#

Wenn alles ok ist, muss die ROM-Dump Datei ins 'bin' Verzeichnis des Emulators kopiert werden.

RAM-Karten standen dem Autor nicht zur Verfügung, aber soviel sei doch gesagt: Um eine RAM Karte zu benutzen (128K oder 32K auf dem SX, bis 4M auf dem GX), wird mit dem Programm mkcard eine Datei port1 bzw. port2 erstellt und ins Verzeichnis ~/.hp48/ kopiert. x48 erkennt dann diese 'Erweiterunskarten' automatisch.
Für ROM-Karten gilt dasselbe wie für RAM-Karten, nur dass hier noch mit chmod 444 $HOME/.hp48/port1 die Datei auf 'alle-nur-read-only' gesetzt werden muss. x48 behandelt dann diese Datei gewissermassen als ROM.

Der erste Start...

Gestartet wird x48 mit der Eingabe von x48, oder mit der expliziten Angabe einer ROM-Datei (x48 -rom <romdatei>). Die Kommandozeilenoptionen können mit x48 -help angezeigt werden. Endlich! Abbildung 2 zeigt das Prachtsstück. Abbildung 3 zeigt x48 in Aktion.


Abbildung 2: Die Mühe hat sich gelohnt...


Auf die Frage Try to recover memory? muss mit no geantwortet werden. Nun kann man auch gleich mal den Selftest laufen lassen ([on] + [e]). Dazu wird mit der mittleren Maustaste auf [on] geklickt, danach mit der linken auf [e]. Mit [on] + [c] wird unterbrochen. Mit der Tastatur gehts auch: [ESC] ist [on], [linkes shift] ist [<-|], [rechtes shift] ist [|->], [META] ist ["alpha"], ...


Abbildung 3: x48 in Aktion...

...Segfault

Was aber, wenn der Emulator mit einem "Segmentation fault" aussteigt? Hier meine Ergebnisse nach ein paar Debbuging-Sessions:
Auf einem coff (a.out) System musste der Schritt 4 (4. Values from XResourceManagerString() or ~/.Xdefaults) in der Datei "/src/x48_x11.c" mit #if 0 ... #endif vollständig auskommentiert werden. Danach funktionierte alles.
Bei einem anderen Fall (auf einem ELF System) wollte der Emulator von einer nicht vorhanden Erweiterungskarte lesen. Dort musste in der Datei "/src/memory.c" in der Funktion "read_nibble_sx" die Zeile 1018 (return saturn.port2[(addr - 0xc0000) & port2_mask];) ganz auskommentiert werden. Danach war alles ok.

Gut Verbunden

Im Emulator sieht man eine Zeile, die angibt, über welchen Device die serielle Schnittstelle und die lokale Harddisk erreicht wird.
  wire:/dev/ttyp2      IR:/dev/ttyS0
Mit der Einstellung [I/O] Menü, [SETUP]: wire, binary, 9600, none 0, 1, 3 und [I/O] Menü, [SERVER], Awaiting Server Cmd. seitens x48 und kermit starten, set line /dev/ttyp2, send backup-datei seitens Kermit-Programm kann eine HP-Backup-Datei geladen werden.

Software findet man zu hauf im Internet. Siehe auch Tabelle 'Infos und Quellen'.

Mir bleibt da nur noch viel Spass zu wünschen!

Infos und Quellen rund um den HP48


[1] HP48 Homepage http://www.hp48.com
* Autor von x48: mailto:ecd@dressler.de
* Programs for the HP48 and HP28 news:comp.sources.hp48
* Hewlett-Packard's HP48 and HP28 caculators news:comp.sys.hp48
* C-Compiler für HP48? (von Alex Ramos) ftp.engr.latech.edu:/pub/alex/hp48/
[2] Es geht an's Eingemachte... http://www.ee.ethz.ch/~jbalkaus/hp48.html
* SADHP Disassembler: ftp://wuarchive.wust.edu/systems/hp/hp48Uploads/

Der Autor

Michael Mustun ist Elektroniker und zur Zeit als Unix Systemadministrator tätig. Ab und zu steigt er gern in die Tiefen eines Programmes oder Betriebssystems hinab. 

Copyright © 1997 Linux-Magazin Verlag


Copyright  © 2003, 2002, 2001, 2000, 1999 by M i c h a e l Mustun michael@mustun.ch (Last modified: 05. September 2002)
All Rights Reserved / Dislaimer