Localization has been a topic considered on many HP models, especially since the HP-18C. In a Usenet newsgroup posting (January 1993), Charles Patton described how it was accomplished on the HP48:
We anticipated the need to produce multi-lingual versions of the machine as well as providing for system-wide re-definition of high-level aspects of the machine. In order to be able to be re-defined on-the-fly, these aspects of the machine (Hash tables for converting text to and from commands, and Message tables for defining standarized messages) must, at the very least, have "hooks" in RAM.
These "hooks" for Hash and Message tables are provided in the ROMPART of the HOME directory. Unlike subdirectories, the HOME directory can have multiple libraries "attached" (although "attached" here cannot have same expectation of exclusive ownership) and with each library attachment, a slot for the library’s Hash and Message table is allocated and filled, by default, with the library’s own Hash and Message tables. These, however, can be overwritten with alternative versions at a later time.
The first such re-definition was the Hyde library by Bill Wickes, released in November 1990. It made the HP48SX "unfriendly" by using funny alternative messages. Hackers soon learned how to use the system word SETMESG, and the HP48 began to display errors in local languages. (HP released Spanish, Italian and French versions, which Joe Horn included in his GD#11). But only the messages were changed: In spite of the supported entry provided by HP to change hash tables (SETHASH), nobody ever published such application. The complex structure of hash tables makes them much harder to handle than arrays of strings, but I believe that the real reason is that SETHASH was buggy until ROM revision P: On versions A to M (all S series and early G calcs) the instruction at address #0764Bh is GOC #07661 and should be GONC #07661, that is to say: the nibble at address #0764Bh must be ‘5’ instead of ‘4’. A workaround is however pretty simple: instead of SETHASH, just use the following code, which works on any HP48 (there is no problem with SETHASH on the HP49G):
I have written a library that renames all built-in command names on the HP48, which can be downloaded from the club’s website. (Feel free to email me if you want the source code in Jazz format). An HP49 version has been put off because I have found that the renamed commands are not retrieved by the stack viewer, old names are displayed instead. This does not happen on the command line or on the interactive stack. |
Before describing the libraries that you will find in the zip file, I would like to thank Christian Bourgeois for his Library Maker 5.1, from which I have taken a code for building hash tables. This has allowed me to develop the libraries in time for this issue.
It renames only one command: HOME, but at the same time, changes the word displayed on the path. There are two versions, for both S and G series. In order to install it, download the proper file, store it in any port of the S/SX or in ports 0 or 1 on the G/GX and provoke a warmstart (ON-C or power cycle). The libraries are self-modifying, so make sure there is no write protection enabled. (All this applies to the general version too). To purge it, I have included the BYE command that uninstalls the library completely:
:: | |
Clears saved name of previous command | |
No arguments, "BYE" not saved | |
The following ob is placed unevaluated on the stack | |
Cancels the HOME replacement | |
Detaches the library | |
:&:1046 | |
(GX/SX) Launches xPURGE using EvalNoCK | |
(SX:3AE6F) Displays the library menu | |
Signal to redraw the display | |
The above program is copied to temporary memory | |
and run without returning | |
; |
The other command provided in the homeless library is ->ROOT. It takes any string of 1 to 16 chars, which will be the new name for HOME until BYE is pressed. This library and the general version maintain the assignments even after a warmstart, due to a special configuration code described below. |
It allows you to rename any built-in command. There are also two versions and the installation procedure is the same. Notice that all of the libraries have the same id number: install only one at a time since they cannot share resources. To purge the lib, use the normal method but run RESET beforehand: RESET :n:1046 DUP DETACH PURGE, where n is the port number.
As the figure shows, there are four commands. RESET restores the built-in names and clears the internal list of new names. OLD activates old (built-in) names but keeps the list of renamed commands. Once run, OLD becomes NEW which activates the new (renamed) names and makes the calculator happy: the last softkey displays a help screen, but also works as an indicator of the current state. Needless to say, the default state of the calculator is happy (new names are used), that is why RESET must be executed before purging. |
REN takes two strings: the name of the command to rename (built-in or already renamed) and the new name. The changes are automatic: it does an implicit NEW. I have limited the length of the new name to 12 chars because of memory constraints; on the G version, each additional char would increase the library’s size by 600 bytes – keep in mind that REN (and ->ROOT) needs 12Kb of available memory to run. Anyway, the longest built-in names on the HP48 are PARAMETRIC and PARSURFACE, ten letters.
The REN command works in another way too. The command to be renamed can be input as #lllccch, where lll is the library number and ccc the command number, like the argument for LIBEVAL. Valid lib numbers are 2 and 700h (1792d) for S/SX machines; and 2, ABh (171), F1h (241) and 700h for the G version. Library 241 has the names FUNCTION, CONIC, POLAR, PARAMETRIC, TRUTH, SCATTER, HISTOGRAM and BAR; but not the ones displayed on menus 82.01 and 88.01, but the ones used in the reserved variable PPAR and displayed beside "Ptype" after Left-Shift+PLOT. For example, suppose you want to rename BAR to PUB. You should do: #F103A "PUB" REN and #20E3 "PUB" REN.
There are more cases of different commands having the same name. The sequence "END" "FIN" REN would change the END used in the IF and CASE clauses but not the ones used by DO and WHILE, since they are actually different commands. To change the END in DO clauses, for instance, type: #700017h "FIN" REN. In the zip file, you will find a document listing all of the command numbers along with their built-in names.
There is one more pitfall when renaming structure words such as THEN and NEXT. The compiler (OBJ-> or the command line) searches the program or object for these exact strings to check for correct syntax. It does not perform a name resolution, but mindlessly looks for the strings "ELSE" (PTR 253C4), "END" (253D6), "UNTIL" (253E6), "REPEAT" (253FA), "NEXT" (25410), "STEP" (25422) and "THEN" (25434). If you decide to rename them, you should use the old names in your programs and, optionally, the new names as remarks (preceded by ‘@’).
We have seen that different commands may have the same name. On the other hand, certain commands have multiple names: CLUSR, GRAPH and LAST are compiled as CLVAR, PICTURE and LASTARG on the HP48G. Under happy mode (i.e. using new names), these alternative names are no longer valid. Also if "DIR" (#70001B) is renamed, XLIB will not be a keyword any more, since ROMPTR 700 1B (XLIB 1792 27) has four names: C$, GROB, DIR, and XLIB. (The first three keywords are also hard-coded within ROM and not affected by the change, addresses 6533E, 6532C and 253A8 respectively). I could not resist applying this feature to my own library; hence you can use RENCMD as an alias for REN. It will be compiled as REN, not as a separate command. I got tired of invoking the wrong command: in Mika Heiskanen’s Hack Library (permanently installed on my calcs) REN is a command that renames global names!
Here’s the configuration code of the G version – I think it may show a few tips:
:: | |
Pointer to HOME user object area | |
If addr of current program is less | |
than HOME addr, then current prog is | |
running from TEMPOB, and therefore | |
this config code belongs to a lib stored | |
in a covered port. | |
If covered port, quits. Lib not attached | |
Attaches lib to HOME dir | |
Happy mode on | |
Sets new hash table for lib #2 | |
Sets new hash table for lib #AB | |
Since not yet attached (1792 > 1046) | |
attaches lib #700 & sets new hash table | |
Attaches lib #F1, not attached by system | |
Sets new hash table for lib #F1 | |
During config time, there’s a meta-ob of remaining lib # on the stack. | |
#700 should be removed. (GX:57676, SX:5768A) | |
If #700 not in meta-ob, quits. Otherwise: | |
Adds to a list all bints except #700 | |
Explodes the list of bints | |
Don’t forget that the config poll (a DOLOOP) has one fewer lib now | |
; |
Your turn to play now. Try funny replacements such as pi, * or <<, but remember to back up your RAM first. There is plenty of room for improvements: reduction of memory restrictions, faster execution (parallel list processing is enabled on the G version but slow), renaming non built-in commands ...
johil@tv3mail.com | Page last modified : 6th June 2002 |