I have finished porting Jazz over to the HP49G+ and HP50G (ROM 2.15). The latest version (version 1.1) includes support for FPTR2 and ZINT tokens, as well as all new opcodes. The SysRPL debugger (SDB) is also now available. One caveat is that Jazz has its own entries table (which can now be installed in any port without speed limitations nor RAM requirements to copy the tables from covered ports) whereas SDB uses extable. This choice was due to the fact that there are users who prefer the internal MASD compiler (which uses extable) and only want to use SDB.
The files have been uploaded to hpcalc.org, but until the site is refreshed, you can download the new versions via:
Here's a quick update to Jazz 50G. Minor fixes to label generation during disassembly. Major fixes in SDB, including updates to CK&DISPATCH1 emulation to handle updated sym/arry classes, conversion of integers to reals, and a patch to work around the 2 bugs in ROM 2.15.
Until hpcalc.org does another refresh of files, you can get the updates at:
> Here's a quick update to Jazz 50G. Minor fixes to label generation > during disassembly. Major fixes in SDB, including updates to > CK&DISPATCH1 emulation to handle updated sym/arry classes, conversion > of integers to reals, and a patch to work around the 2 bugs in ROM > 2.15
About this last patch -- is it a patch to the actual ROM, or a patch for which you have to run all programs under Jazz? (the latter does not seem very practical).
If there is a bug, what if it's in _all_ ROM versions?
If Jazz can correct a ROM bug, can it correct _all_ of them?
Say, why can't Emu48 correct ROM bugs, too?
That way, everyone using it, instead of a real calculator, can have a perfect HP49/50 series calculator ;-)
> > Here's a quick update to Jazz 50G. Minor fixes to label generation > > during disassembly. Major fixes in SDB, including updates to > > CK&DISPATCH1 emulation to handle updated sym/arry classes, conversion > > of integers to reals, and a patch to work around the 2 bugs in ROM > > 2.15
> About this last patch -- is it a patch to the actual ROM, > or a patch for which you have to run all programs under Jazz? > (the latter does not seem very practical).
> If there is a bug, what if it's in _all_ ROM versions?
> If Jazz can correct a ROM bug, can it correct _all_ of them?
> Say, why can't Emu48 correct ROM bugs, too?
> That way, everyone using it, instead of a real calculator, > can have a perfect HP49/50 series calculator ;-)
> [r->] [OFF]
Sorry if there was any confusion. It is a patch of SDB. SDB was designed to emulate CK&DISPATCH1 exactly as it is in ROM. I had planned for the updated SDB to continue this -- emulating even the bugs -- but then decided against this. I called it a patch because by excluding the 2 bugs, SDB was no longer emulating the entry as it is in ROM (i.e. bugs and all). It has nothing to do with patching the actual ROM.
as you might know, patching the ROM from the outside is quite difficult.
The O.S. provides some "hooks" for this (e.g. the ROMPART) but not for all (e.g. PTRs, FLASHPTRs).
One way to be able to patch the ROM from the outside is to install a new SOL (SystemOuterLoop) and an additional RAM area where the information for the patches is stored/handled. To my knowledge I am the only one who has done this with the MLPs (Watch the video: http://www.youtube.com/watch?v=Pj72miclisM).
Another way would be to patch the binary of the ROM *before* downloading it into the calculator by exchanging the desired parts and recalculating the needed checksums (of course while keeping supported entries stable). IIRC this was an approach by the never released and now abandoned HPGCC 3.0.
And a third way would be to program your own ROM :-)
> Say, why can't Emu48 correct ROM bugs, too? > That way, everyone using it, instead of a real > calculator, can have a perfect HP49/50 series > calculator ;-) But then, why should one buy a 50G with *bugs* from HP when there would be a *bug-free* version available for free ? What would be the reaction of HP´s legal department and the bean counters ? And what would that mean for the calculator division ?
> as you might know, patching the ROM from the outside is quite > difficult.
> The O.S. provides some "hooks" for this (e.g. the ROMPART) but not for > all (e.g. PTRs, FLASHPTRs).
> One way to be able to patch the ROM from the outside is to install a > new SOL (SystemOuterLoop) and an additional RAM area where the > information for the patches is stored/handled. To my knowledge I am > the only one who has done this with the MLPs (Watch the video:http://www.youtube.com/watch?v=Pj72miclisM).
> Another way would be to patch the binary of the ROM *before* > downloading it into the calculator by exchanging the desired parts and > recalculating the needed checksums (of course while keeping supported > entries stable). IIRC this was an approach by the never released and > now abandoned HPGCC 3.0.
> And a third way would be to program your own ROM :-)
> > Say, why can't Emu48 correct ROM bugs, too? > > That way, everyone using it, instead of a real > > calculator, can have a perfect HP49/50 series > > calculator ;-) > But then, why should one buy a 50G with *bugs* from HP when there > would be a *bug-free* version available for free ? > What would be the reaction of HP´s legal department and the bean > counters ? > And what would that mean for the calculator division ?
Would it also be possible to take over the ROM by mapping a flash bank over the main bank? This is a technique that has always been available since the HP48SX. The Metakernel used this technique on the HP48GX if I'm not mistaken.
> Would it also be possible to take over the ROM by mapping > a flash bank over the main bank? This is a technique that > has always been available since the HP48SX. The Metakernel > used this technique on the HP48GX if I'm not mistaken.
There must be some misunderstanding here. FlashBanks were introduced with the49G, the 48GX has no FlashBanks but uses a technique called "covered ROM" which is still present in the 49G. "Covered ROM" contains built-in libraries which means that you can take over them by exchanging the hash table (but be aware of the STO bug in the 49G which zeroes this pointers everytime something is stored in a port). "Covered ROM" can be accessed through Access Pointers which are stored in RAM. An ACPTR is 15 Nibbles, 5 Nibbles Prolog, 5 Nibbles for the access routine to configure the memory and 5 Nibbles as an address pointer to the program code.
The Metakernel exchanges the SOL as far as I know but Cyrille could give a definitive answer. Unfortunately it has been quite some time since he made a post here.
> Sorry if there was any confusion. It is a patch of SDB. SDB was > designed to emulate CK&DISPATCH1 exactly as it is in ROM. I had > planned for the updated SDB to continue this -- emulating even the > bugs -- but then decided against this. I called it a patch because by > excluding the 2 bugs, SDB was no longer emulating the entry as it is > in ROM (i.e. bugs and all). It has nothing to do with patching the > actual ROM.
I don't quite understand for which side of this issue you are voting :)
I think that emulators and debuggers should all simply "follow the ROM"; otherwise the results are not what will really happen in the calculator, but instead will be results which can occur only in the emulator or debugger.
> I think that emulators and debuggers should all simply > "follow the ROM"; otherwise the results are not what > will really happen in the calculator, but instead will > be results which can occur only in the emulator or debugger.
Wishful thinking.
As a matter of fact EMU49 and the 50g use different ROMs (you know that :-) and also the emulation of the original Saturn is not the same. The carry flag inside of the emulated Saturn behaves different, but don't ask which is right or wrong.
Conclusion: If one wants to write new software for the ancient Saturn one must know the differences depending on where you want to run your code.
> > Say, why can't Emu48 correct ROM bugs, too? > > That way, everyone using it, instead of a real > > calculator, can have a perfect HP49/50 series > > calculator ;-) > But then, why should one buy a 50G with *bugs* from HP when there > would be a *bug-free* version available for free ? > What would be the reaction of HP´s legal department and the bean > counters ? > And what would that mean for the calculator division ?
Is that also "tongue-in cheek" mode?
Anyone can have an emulated 50G for free -- on mobile devices, for example, as well as on any PC (and probably other platforms).
Anyone can also suggest ROM patches, or make them.
As a precedent, old 49G version 1.19-6 (the best version before the later 49G+/50G series started production) was never available from HP itself (HP stopped at much inferior version 1.18, which is _still_ the last you can get directly from HP for the HP49G).
I'd guess that HP was pretty glad that 1.19-6 was available elsewhere, because it probably increased sales in the long run, at the same time as it allowed HP to disclaim responsibility -- don't we all love to get more without taking any responsibility? ;-)
Of course, all versions through 2.10 also run fine on HP49G, although getting the 49G updated needs an emulator's help, plus a ROM left in "pure Saturn" form for the emulator (or a directly transferable ".flash" file, which no doubt either exists or can be generated from other ROM files).
I don't recall any bug fix in 2.15 that's not in 2.10 (is there any?) The normal 2.10 (not BP's) doesn't seem to be available, but 2.09 is still very close, with very few small fixes.
BP's "2.10" comes with some unofficial extras, plus an internal shift which doesn't support something from A.M. (has anyone found any other software which won't run on it?)
I gotta go now and count some beans (or at least eat them).
> As a matter of fact EMU49 and the 50g use different ROMs > (you know that :-)
The only difference between my Emu48 and my [ARM] calculator ROMs is that at various locations which call a few very common ROM functions (mainly to shift large chunks of memory and to return to RPL), the [ARM] calculator ROM has an overlaid "hook" to invoke an ARM-based function having the same exact result, where Emu48 (and my old HP49G) still follow the original Saturn code -- again, with identical result, the purpose of these "hooks" being simply to speed up those few (but frequently called and time-consuming) functions even more than going through the normal Saturn emulation.
I call this "identical"
> and also the emulation of the original Saturn is not the > same. The carry flag inside of the emulated Saturn behaves different, > but don't ask which is right or wrong.
Miraculously enough, no program that I have ever used (or written), nor apparently all of the programming in the ROM itself, has ever behaved the slightest bit differently between all of my calculators and Emu48, so this must not have so great a significance as it sounds ;-)
You are just one rare programmer who has managed to write things so deeply dependent that it may affect your own program(s).
> Conclusion: If one wants to write new software for the ancient Saturn > one must know the differences depending on where you want to run your > code.
www.hpcalc.org contains (how many? thousands?) of programs for the HP49G/49G+/50G series -- how many don't run identically between calculators and emulators, other than by virtue of bugs involving things like not checking for screen height, or other issues equally irrelevant to the one you raise?
And the entire ROM itself -- does anything in it (other than the beeper :) not work when emulated by Emu48, or by the ARM emulator?
I guess this is an unending chat between us, where you eternally assert this problem of yours, while I eternally remind everyone of how little it matters to anyone else.
Like "kryptonite," it seems to affect no one else but Superman himself :)
> There must be some misunderstanding here. FlashBanks were introduced > with the49G, the 48GX has no FlashBanks but uses a technique called > "covered ROM" which is still present in the 49G. "Covered ROM"
I was referring to the technique of covering and uncovering memory. From a programmer's point of view, a flash bank is no different from a RAM card, ROM card, built-in ROM, etc. They're all just blocks of memory that are either configured or not configured, and viewable or not viewable. The technique of covering and uncovering memory has been around for some time.
> contains built-in libraries which means that you can take over them by
Covered ROM could contain anything, or even nothing (such as the block of ROM covered by hardware I/O addresses). As I understand it, covered memory is just a configured block of memory (RAM/ROM/Flash/etc) with lower priority than some other memory device/block with higher priority. Theoretically, it should be possible to program your own OS, write the the data to a specific flash page available to users, then configure that page to cover the ROM in the #00000 #3FFFFF range, and have your new OS take over. This, of course, would much more difficult than simply replacing some built-in libraries. Your new OS would have to have its own interrupt system, handle the configuring and unconfiguring of flash pages, etc.
> exchanging the hash table (but be aware of the STO bug in the 49G
Are hash tables actually exchanged? I thought this could be accomplished simply by repositioning the library address and configuration address within ROMPTAB (so that the modified library's configuration information appears before the built-in one). It's the same idea as with covering memory. Or is this what you meant by exchanging hash tables?
> which zeroes this pointers everytime something is stored in a port).
Is this bug only on the HP49G? Or does it affect the 49G+ and 50G? When you store something into a port, I was under the impression the OS has to reconfigure the ROMPTAB to account for what may possibly be a new library that just got stored into port. Each entry includes an address pointing to the library id, and an address to the configuration routine. When it rebuilds this table, most built-in libraries have higher priority. I believe that the code first checks the visible memory blocks for libraries, then it starts to look for libraries that are in covered memory blocks. So many of the built-in libraries get their configuration address set to 0 to signify that CONFIG/UNCONFIG is not necessary to access the library contents. Or were you referring to a different set of pointers?
> I think that emulators and debuggers should all simply "follow the ROM"; > otherwise the results are not what will really happen in the calculator, > but instead will be results which can occur only in the emulator or debugger.
I'm not sure I can wholeheartedly agree here. The point of an emulator is to emulate -- be as close to the real thing as possible. The point of a debugger, though, is to try to find bugs that the user created. When there is a bug in the ROM, that is not a bug created by the user's source files. If the debugger emulates the ROM exactly, then the user's results may be wrong -- but not because of a bug within his own code. This was why I was debating whether SDB's emulation of CK&DISPATCH1 (and hence, all related dispatch entries) should duplicate the bugs in ROM. In the end, I decided that it was better to just warn users about the bug in the ROM, and write the CK&DISPATCH1 emulation to behave as it is supposed to (without bugs). That way, users won't get a wrong result and wonder if there's a bug in SDB itself, let alone the ROM =)
> Of course, all versions through 2.10 also run fine on HP49G, > although getting the 49G updated needs an emulator's help,
Thanks again for telling me what I described first in this newsgroup, although a detailed explanation based on my post was given by James M. Prange.
> Miraculously enough, no program that I have ever used (or written), > nor apparently all of the programming in the ROM itself, > has ever behaved the slightest bit differently > between all of my calculators and Emu48, > so this must not have so great a significance as it sounds ;-)
There are two possible reasons for this: 1. You have never written an advanced Saturn-ASM program 2. You did not dig deep enough in the ROM, maybe you do not want to awake the Balrog as the dwarfes did when they dug to deep in Khazad- dûm
I could show you both but most likely it would not make a difference to you. Some examples for programs that rely deeply on the underlying microprocessor: Compiler/Decompiler (Jazz) Compressors/Decompressors (BZ2) Memory movement/access to covered ports (usually part of program) SOL-replacements (MLP) ML-code making decisions based on the state of the carry flag (advanced speed up for ML programs) etc.
> You are just one rare programmer who has managed to write things > so deeply dependent that it may affect your own program(s).
All programs that I have written behave correctly to the original physical Saturn (which also contains some bugs which can be used as a feature). Forgive me if I corrected bugs in the ROM that I encountered when I developed my software. And IMHO a bug is not a matter of how many use or not use an existing API. As a matter of fact I had to adopt/change parts of it for the emulated Saturn.
> I guess this is an unending chat between us, > where you eternally assert this problem of yours, > while I eternally remind everyone of how little it matters to anyone else.
There is no problem of mine, except that I dug to deep, even deeper than the original developers. Or, if you like that more, it is just another prove that is impossible to write bug free software but a better quality control on HP's side wouldn´t hurt.
But I aggree with you: If you argue that it does not matter because the majority of the programs does not use this *then* arguing is pointless. Most likely the majority of the 50g users do not program at all, so why bother ?
But for something as advanced as Jazz it might be helpful to know all possible pitfalls.
> Covered ROM could contain anything, or even nothing (such as the block > of ROM covered by hardware I/O addresses).
Of course you are right. What I was trying to say was that covered memory in 48GX is accessed through ACPTR whereas in the 49G the FLASHPTR configures the memory and then usually a PTR is called and therefore the FLASHPTR is faster but can not be exchanged as easily as there is no RAM "hook". As always the devil is in the details ;-)
> Are hash tables actually exchanged?
This can be used to replace commands of a library while still using the rest of the original library, an example is my advanced CAS help in the MLP. Also I am planning to do this with my GUISLV (if I find the time for it) to exchange the slow stuff and the unsupported display size. That way I could use my improved code together with the original routines that I do not want to replace (saves time and space).
> Is this bug only on the HP49G? Or does it affect the 49G+ and 50G?
This bug is present in the ROM from the very first one until today. A detailed presentation about this was given at HHC 2008 by me. If you do not have it mail me and I will send it to you.
> > Covered ROM could contain anything, or even nothing (such as the block > > of ROM covered by hardware I/O addresses).
> Of course you are right. What I was trying to say was that covered > memory in 48GX is accessed through ACPTR whereas in the 49G the > FLASHPTR configures the memory and then usually a PTR is called and > therefore the FLASHPTR is faster but can not be exchanged as easily as > there is no RAM "hook". As always the devil is in the details ;-)
> > Are hash tables actually exchanged?
> This can be used to replace commands of a library while still using > the rest of the original library, an example is my advanced CAS help > in the MLP. Also I am planning to do this with my GUISLV (if I find > the time for it) to exchange the slow stuff and the unsupported > display size. That way I could use my improved code together with the > original routines that I do not want to replace (saves time and > space).
> > Is this bug only on the HP49G? Or does it affect the 49G+ and 50G?
> This bug is present in the ROM from the very first one until today. > A detailed presentation about this was given at HHC 2008 by me. If you > do not have it mail me and I will send it to you.
> > When there is a bug in the ROM
> Bugzilla still list a lot of bugs for the 50g...
> I'm not sure I can wholeheartedly agree here. The point of an emulator > is to emulate -- be as close to the real thing as possible. The point > of a debugger, though, is to try to find bugs that the user created.
I think that the point of a debugger is only to step through what actually happens on the real machine.
This helps a programmer to find his/her own problems, but I think it no favor to make it produce results that can't, in the end, be duplicated on the real hardware, after which the programmer can be left perplexed, saying "but it works perfectly when debugging, so there can't be any bug" :)
Or to look at it another way, shouldn't the debugger also detect bugs in the ROM, rather then try to hide them, particularly when they are not going to be fixed, but instead have to be faced and dealt with?
> Some examples for programs that rely deeply on the underlying > microprocessor: Compiler/Decompiler (Jazz)
The original (HP48) Jazz (I use Jazz 5.9 in Hacker's ROM Rev. B) works for me under Emu48 -- is Emu48 at least faithful to the Saturn? If not, can it be fixed?
Apparently you have succeeded in working around a bug in the ARM emulator on the HP49G+/50G series (which needed major update to Jazz), in your own projects.
Everyone has probably been faced with working around bugs, including those in ROM functions or in the CAS.
If the bugs won't work themselves out, then what else can we do but discover them, then defend against and work around them?
You might be able to patch the internal emulator and reload it into real calculators, but then programs which can only run under those ideal conditions could be used only by people who first patch their own calculators.
I seem to recall that Wolfgang Rautenberg was very annoyed that certain ROM functions upon which he depended for his advanced libraries were not "supported," hence might (and subsequently did) move between ROM versions.
But, insisting on using them anyway, because they enabled his programs to be smaller and faster, with which goal he seemed to have been obsessed, he released some libraries which later crashed after ROM updates (did they cause anyone the inopportune total loss of all their stored info and personal investment in programming?) and had to be updated for later ROM versions.
This could lead to a discussion of whether to aim for absolute minimum program size and time, or for absolute maximum of safety, or somewhere between, and I suppose not everyone will ever be persuaded of any particular position on that entire scale, which considerations have their parallels in every field of engineering, of software, of hardware, of economics, and of everything up to the overall management of all the world's societies, resources, and the future of this "Spaceship Earth," as R. Buckminster Fuller called it.
>> Of course, all versions through 2.10 also run fine on HP49G, >> although getting the 49G updated needs an emulator's help
AM:
> Thanks again for telling me what I described first in this newsgroup, > although a detailed explanation based on my post was given by James M. > Prange.
I am not telling you; this is a public newsgroup, to which new users who don't yet know things may arrive at any time, and might like to know; it might also give them some perspective on what otherwise would seem a closed "insider" discussion without wider meaning to them.
> I think that the point of a debugger is only to step through > what actually happens on the real machine.
You make a very good case here. I think I will revert CK&DISPATCH1 behavior to mirror that of ROM in the next release -- at least until the bugs are fixed in the ROM itself (I won't hold my breath).
1. I was unable to duplicate the bug as described in your talk -- at least as far as non-system libraries were concerned. Storing objects into PORT 0 did not change the table within SRRP (located at the pointer stored in =USEROB (#80711h)). Whether an object or library was stored, the SRRP's table was exactly the same. The table only changed with either a library was attached/detached, or after a warmstart.
2. Manually attaching new libraries (e.g. :: 992 TOSRRP ; or << 992 ATTACH >>) updated the SRRP table, but again none of the entries was overwritten with 0's. I then manually attached library 6 (not possible with UserRPL; I used :: 6 TOSRRP ; instead). When this was attached, the hash/message table was updated, but written with 0's only for the hash address (makes sense if library 6 does not contain commands). The message table, however, was correctly found. I tried other orders (attach lib 6 first, then store something into PORT 0, etc) and got the same results -- the hash/message table was updated correctly and as expected. (Tested on ROM 1.23 and 2.15 with the same results.)
3. Warmstarts reset the SRRP hash/message table, so that library 6 is no longer attached. However, newly installed libraries were correctly added to the table, and old entries were left intact.
I have not tried to overwrite or adjust ROMPTAB to use replacement libraries (e.g. replacing library 6). When I checked how the ROM updates the table, I did not see anything out of the ordinary. In ROM 2.15, the only time the values in the table are overwritten with 0's is if the attached library does not have an entry in ROMPTAB, or the old values were invalid. The values are considered invalid if the libraries are covered, and the old hash/msg table info did not point to ACPTRs. Here's my dissassembly of the routine (with my own comments) from Jazz:
L09811 D1=(5) =USEROB A=DAT1 A D1=A D1=D1+ 5 skip DORRP prologue C=DAT1 X get lib count D=C X D[X] = lib count in SRRP D1=D1- 10 prepare D1 to enter loop
L0982B D=D-1 X RTNC CS: no more libs to search; RTN D1=D1+ 13 skip to lib ID A=DAT1 X A[X] = current lib ID in SRRP D0=(5) =ROMPTAB C=DAT0 X B=C X B[X] = lib count in ROMPTAB D0=D0+ 3 C=0 W B=B-1 X prepare loop; 0-based count GOC L0986E only reached if no libs exist!?
L09852 C=DAT0 X ?C=A X found a matching lib ID? GOYES L0986E D0=D0+ 16 no B=B-1 X GONC L09852 get next lib ID C=0 A lib ID never found DAT1=C 13 write 0's GOTO L0982B and do next attached library
L0986E D0=D0+ 3 found matching lib ID A=DAT0 A A=A+CON A,3 A[A] = address of hash table offset LC(5) #40000 ?C>=A A is the library in main ROM? (e.g. lib 2) GOYES L0982B yes, no need to update in SRRP D1=D1+ 3 no, so skip lib ID; D1 -> hash offset D0=D0+ 5 C=DAT0 A C[A] = config address from ROMPTAB ?C#0 A is the library covered? GOYES L098C4 yes
* update SRRP info if library does not require configuring D0=A no, D0 -> hash table offset C=DAT0 A C[A] = hash table offset ?C=0 A does hash table exist? GOYES L098A1 no, write 0's C=C+A A yes, C[A] = address of hash table L098A1 DAT1=C A save hash table info in SRRP D1=D1+ 5 D1 -> message table in SRRP D0=D0+ 5 D0 -> message table offset A=A+CON A,5 A[A] = address of msg table offset C=DAT0 A ?C=0 A do we have a message table? GOYES L098BA no, write 0's C=C+A A yes, C[A] = address of msg table L098BA DAT1=C A save msg table info in SRRP D1=D1- 8 D1 -> lib num in SRRP GOTO L0982B do next attached library
* if library is covered, update SRRP info and necessary ACPTRs in RAM L098C4 RSTK=C library was covered; RSTK : cfg addr P= 0 P=0 means configure library GOSUB L097BF PC=C C=RSTK C[A] = cfg addr RSTK=C R0=A.F A R0[A] = addr of hash table offset LA(5) =IRAMBUFF R1=A.F A R1[A] = addr of IRAMBUFF AD1EX B=A A B[A] = addr of hash info in SRRP C=0 S LA(5) #A P= 2 P=2 means copy from R0[A] to R1[A] GOSUB L097BF PC=C (calls MOVEDOWN); restore Bank2 C=RSTK BCEX A B[A] = cfg addr, C[A] = ->hash in SRRP D1=C A=R0.F A A=A-CON A,10 D0=(5) =IRAMBUFF D0 -> hash table offset GOSUB L0993D D1=D1+ 5 A=R0.F A A=A-CON A,5 D0=(5) (=IRAMBUFF)+5 D0 -> msg table offset GOSUB L0993D D1=D1- 8 GOTO L0982B do next attached library
* update the list RAM area containing ACPTRs to hash/msg tables L0993D C=DAT0 A ?C#0 A do we have a hash or msg table? GOYES L0994A DAT1=C A no, write 0's RTN L0994A C=C+A A yes, C[A] = addr of table A=DAT1 A A[A] = old table addr D0=A A=DAT0 A CD0EX save C[A] in D0 LC(5) =DOACPTR ?C=A A was old table addr valid? GOYES L0996B C=0 A no, so write 0's DAT1=C A RTN L0996B C=DAT1 A old hash addr was valid CD0EX C[A] = addr of hash table; D0 -> ACPTR D0=D0+ 5 skip prologue DAT0=C A write the table address D0=D0+ 5 skip address C=B A get cfg addr DAT0=C A and save RTN
I tried your example, and indeed noticed that the table indeed gets written with 0's -- but I think this was intended in design (as a safety measure). When storing into ports, the SRRP table needs to be validated for any possible changes in library configurations. If what it finds is invalid, it writes 0's so that the system doesn't jump to erroneous addresses when accessing a command, or possibly obtain an extremely large message filled with garbage characters when retrieving a message.
The problem is in the use of SETMESG. Somewhat related, the documentation for SETMESG, GETMSG, SETHASH, etc. are either incomplete or incorrect (as in the case for GETMSG, which returns an ACPTR to the table and T/F). As far as I can tell, there does not appear to be any SysRPL routine in ROM in the HP48 series which calls SETMESG (I have not checked ROM 2.15 if this also the case). On the other hand, the ML routines used by SETMESG (48, 49G, 49G+, 50G) are also the same ones used by the system to set up the hash and message tables (see ML entry =SET). Based on the disassembly, though, it seems reasonable to conclude that the original design expects a library and all its contents (including hash and message tables) to be located in the same memory bank. In fact, if you look peek into the entry =SET, you will see that:
* in the HP48SX, absolutely no checking is done whatsoever to ensure that the object being set as the hash or message table is valid; it simply sets the SRRP table to point to the object
* in the HP48GX and the HP50G, there is a check to see if the table is a ROMPTR and then ACPTRs are created as necessary; the SRRP table gets updated with the address to these ACPTRs; if the object is not a ROMPTR, then the ROM first ensures the object is not in temporary memory, and then behaves like the HP48SX code
In both cases, not much validation is done when setting tables. There is no need to validate, since the system should know what to "feed" the SETMESG command, or the =SET in ML and anyone programming in SysRPL presumably knows what they're doing. Instead, validation is done when a user does something that would require validating the SRRP table (e.g. storing into port memory, attaching a library, etc.)
When validating the SRRP table, the ROM expects the library's message table (and likewise, its hash table) to lie in the same bank of memory as the library itself, as it should. The reason the SRRP table is being overwritten with 0's is due the fact that ROM expects the address in the SRRP table to point to an ACPTR. By replacing covered message tables with tables stored in uncovered memory, you're essentially asking that the system be able to handle cases where libraries are partly covered (the main parts of the library) and partly uncovered (the message table). While this may seem like a nice feature, I don't think this was the intended design. In fact, this would make library handling more difficult if the hash and message tables were allowed to be separate from the library itself. (By separate, I mean in a different memory bank).
You would get the exact same behavior described in your talk if you tried to replace the message/hash tables of regular libraries using SETMESG "incorrectly". Upon storing an object into a port, the SRRP table gets re-validated and will simply be either written with 0's, or reset to its default value (unless you also modify ROMPTAB). I see this as a safety net to ensure that the pointers to a library's hash and message tables get updated properly, or nullified when something is amiss.
So that the SRRP table is not overwritten with 0's, one should ensure that the message tables are referenced by ACPTRs (even if they are not stored in covered memory) regardless of how we store the tables (be it in global variables or even in covered memory). If the table is not in covered memory, just use 0's for the config address in the ACPTRs and make the ACPTRs point to the replacement table. Next, we would need to adjust ROMPTAB so that when the SRRP table gets validated, it does not reset the modified ACPTRs back to their original values. Older versions of SpeedUI used this trick to shadow some of the keyob tables.
Minor fix: the ACPTRs config pointers should not be 0 if the replacement table is not covered. Instead, it should point to whatever place in ROM that simply does RTN (i.e. no config necessary)
nice explanation and advocacy of the ROM but you are making the wrong conclusions IMHO.
1. This behavior does not happen in the 48GX series
2. The behavior happens on the 49G if you use a replacement message table as an IDentifier, a ROMPTR for Port0 or an ACPTR for Port1 and Port2 for the covered libraries (all libraries > 5).
3. From my understanding the problem is not SETMSG, here the same code is used in the 48 and the 49. The problem is the dynamic rebuild of the ROMPART which was introduced in the 49G as a feature to make warmstarts unnecessary after a lib has been stored in a port. In the 48GX the ROMPART is only rebuild at system start and this table is fixed which means that you have to warmstart after installing a library so that the config routines (if they exist) of each library is run. In the 49G this is done dynamically so that a warmstart is not necessary. However, this feature has never worked correctly so that everybody still gives the advise to warmstart after a library installation, even HP still gives this advise in their official documentation. See page 27 of the "HP 50g Graphing Calculator Quick Start Guide".
4. The problem is the STO routine which behaves as explained above while zeroing the message table and the hash table if something is stored in a port *if* alternative message tables and hash tables are used. I have a note somewhere from Cyrille where to look, but I can not find it at the moment. However, this is buried so deeply in the system that changing/fixing this would require a lot of work to keep supported entries stable. Personally I do not expect that this will be fixed ever because of the much work needed for it (Is there actually any ROM development happening ?) and because a workaround is possible and now exists. Note that the workaround I programmed has no impact on speed of the machine because the workaround is done completely in Saturn-ML.
> When storing into ports, the SRRP table needs
> to be validated for any possible changes in library > configurations. In the 48GX this is only done at system boot. In the 49G this is done at system boot *and* dynamically each time something is stored in a port and that is where the problem lies, in the STO-code !
> GETMSG, which returns an ACPTR to the > table and T/F Yes, the documentation of SETHASH/GETHASH and SETMSG/GETMSG is incomplete. GETMSG returns a pointer to the message table if the library is not in covered memory and returns an ACPTR if the message table is in covered memory.
> it seems reasonable to conclude that the original > design expects a library and all its contents > (including hash and message tables) to be located > in the same memory bank. This is an incorrect assumption from you, see below.
> When validating the SRRP table, the ROM > expects the library's message table (and > likewise, its hash table) to lie in the same bank > of memory as the library itself, as it should. Nope, this is a wishful assumption from you, because as an example the code for the solver (Flashbank2) and the messages for it (FlashBank3) are *not* in the same flashbanks. This is used frequently in the ROM.
> In fact, this would make library handling more > difficult if the hash and message tables were > allowed to be separate from the library itself. (By > separate, I mean in a different memory bank). As shown above this is intended by design. Some built-in libraries even come without a message table and instead they have a PTR that points to a message array somewhere in memory. This PTR either leads directly to the message table or otherwise points to an ACPTR which will then lead to the message table.
> So that the SRRP table is not overwritten with 0's, > one should ensure that the message tables are > referenced by ACPTRs (even if they are not stored > in covered memory) regardless of how we store the > tables (be it in global variables or even in covered > memory). Again, using an ACPTR does not help. The code example I sent to you was just a very easy way to show the problem. I spend a lot of time and effort to investigate this and to come up with a circumvention of this.