From: GaaK on 31 Dec 2006 12:09 James M. Prange wrote: > \<< @ > RCLF @ Get current flags, leave on stack. > -55 SF @ Force last arguments off. > 64 STWS @ Force wordsize. use LCD\-> BYTES SWAP DROP (131*64=1098, 131*80=1370) > "'LQ'" @ > IFERR @ > STR\-> @ STR\-> compiles "'LQ'" to global name on 48SX/S, > @ but errors out on other models. > THEN @ Not 48SX/X. > CASE @ > NOVAL TYPE 14 == @ NOVAL is type 19 on 49 series. > THEN @ > 1. @ 48GX/G/G+. > END @ > VERSION @ > DROP @ Discard the Copyright string. > 11 11 SUB "5" == @ will be "4" for 48gII or 49G. VERSION command?... maybe... good for 50G > THEN @ > 5. @ 50g. > END @ > LCD\-> @ > SIZE @ > SWAP DROP @ Discard width. > #50h == @ #50h on 49g+ or 50g, otherwise #40h. ....replace this > THEN @ > 3. @ 49g+ > END @ > 1. @ > IFERR @ > PVARS @ 1. PVARS errors out on 48gII, works on other 49 > @ series. PVARS very very slow (49G full port 1). Purge 'IOPAR', then 1 TRANSIO (force default 'IOPAR') IOPAR HEAD (9600:49G, 115200:48gII) > THEN @ > 4. @ 48gII > ELSE @ > DROP2 @ Discard port variable list and > @ available port capacity. > 2. @ 49G > END @ End of "inner" IFERR structure. > END @ End of CASE structure. > ELSE @ > DROP @ Discard 'LQ'. > 0. @ 48SX/S. > END @ End of "outer" IFERR structure. > SWAP @ Move flags list down to level 1. > STOF @ Restore original flags. > \>> @ - GaaK -
From: James M. Prange on 31 Dec 2006 20:43 John H Meyers wrote: > On Sun, 31 Dec 2006 05:05:53 -0600, per James M. Prange: > > NOVAL TYPE 14 == @ NOVAL is type 19 on 49 series. > > Why not eliminate the chance of a variable > (or even a library command) named NOVAL, e.g.: > > DUP SIZE 3 < @ Flag list is shorter on 48 series Good point; I took the trouble to work around the possibility of a global variable named LQ (or NOVAL) in the 48S*, but neglected the possibility of a global variable named NOVAL (using the SysRPL $>ID command, the S~N development library command, or by renaming with the filer), or a library command named NOVAL, in later models. But there could be a local variable named LQ, in which case "'LQ'" STR\-> works on any model, or there could be a library command named LQ on a 48S*, in which case "'LQ'" would error out unless there were also a local variable with the same name, so that's not bullet-proof after all. Of course, an earlier model may very well have a variable or library command that duplicates the name of a built-in command on a later model. Any particular reason for using DUP SIZE 3 < instead of DUP SIZE 2 == ? > Actually, if you want to rely on NOVAL, > "{NOVAL" STR\-> 1 GET TYPE yields: > 48G[X] ==> 14 > 49... ==> 19 > 48S[X] ==> 6 "NOVAL" STR\-> seems to do the same for me, at least once I remembered to purge my global variable NOVAL. > So you wouldn't need another "'LQ'" STR\-> > > But just to warn of the potential for being fooled, > all of the above are only *probable* results -- why? > > Consider that although VARS is generally a command, > I have a *variable* (type 6) named VARS in my 48G[X] > (for a 50-fold speed increase :), > others have a ROMPTR (type 14) named VARS in their 48GX > (same reason, when HACK library is installed), > and the same can actually occur with any name at all, > so likewise nothing is guaranteed about NOVAL. And for that matter, a local name would take precedence over all other names. At least for now, I'll use the SYSEVAL equivalent of VERSTRING to determine whether it a 48S* or 48G* Come to think of it, any of the commands used in the program could be superseded by variables or library commands that behave differently, which means that any source code version can't be absolutely reliable, but I'd hope that that wouldn't be the case for such basic commands. > Another (very minor): > > 11 11 SUB "5" == @ 11 DUP is 8 bytes shorter Thanks! I overlooked an obvious code saving; actually, 8 bytes shorter on a 48 series, 4 bytes shorter on a 49 series. > It's not inconceivable that one "Code" object might actually > be devised to work on all series and models, using only addresses > in a range which is the same on all of these; Certainly it's conceivable, but I'd want to start with a list of which 48SX commands have never changed entry points, and I don't know of one offhand, so I'd have to make my own. Of course the zints would have to be changed to reals too. What I've done so far is mostly meant as a "proof of concept" that there are indeed ways to distinguish the hardware, and I really don't care to go that far. Actually, I'd guess that it may well be easier using SysRPL or assembler language. > I would also > not mind if it returned more than one result, such as: > > ROM series for entry points (0/1 for 48 vs 49), I'd separate the 48S* from the 48G* as well. > keyboard (0/1/2/3 for 48S/48G/49G/later) > screen dimensions (perhaps a sublist), etc., > all returned in one list would be okay (and expandable), > which are individually more important results > for any programs that could use such generalized tests. I see your point, but note that all of the above can be determined by division into categories of 48S*, 48G*, 49G, and 49g+/50g. Well, except for differences in the entry point/command set of the 49G depending on the ROM revision. Splitting 49g+/50g into 2 categories gives additional information on the external I/O and power supply differences. Then too, I expect that often a programmer would be interested in only one characteristic, such as the screen size, or whether it's an ARM-based model, or which external I/O ports are available, so wouldn't need such a large program. > More optional results? Well, where would we stop adding to the list of characteristics? > o Highest port number? Or in the 48SX/GX, which ports are free? Your question of how to determine whether it was running on an emulator is a very good one. Of course, ideally it wouldn't matter, but the emulations are less than perfect, so sometimes it does matter. It seems to me that it would be a matter of trying something that works differently on the emulator than it does on a real calculator, but without crashing either one. I had thought to use the same test that I used for distinguishing a 49G from a 49g+, which depends on a Saturn+ opcode, and was very surprised to find that the Saturn+ opcode actually worked on the emulated 49g+, so I was wrong about that; the emulator can indeed use at least some of the Saturn+ opcodes. Digging into the source code for the emulator available from http://www.hpcalc.org/details.php?id=6523 (e48sp42plus.zip) gives information on which opcodes are currently emulated there, but the emulator included with Debug4x seems to be different, and I don't know where to find source code for that one. > o [nominate, petition, vote (early and often :)] And if that doesn't work, sneak in a vote after the polls have closed. ;-) Seriously, I'd think that the categories 48S*, 48G*, 49G, 49g+, 48gII, and 50g, plus the version letter for the 48 series and revision number for the 49 series would be most appropriate. If someone needs to know which (memory) ports are available, and how much capacity is left in them, then that can be checked separately with PVARS. Well, except for the SD card; it's existence could be checked by trying to store a dummy object there; if the STO succeeds the card is present and the dummy object can be purged, or if it errors out with "Object In Use" then the card is present, or if it errors out with "No SD card inserted" then of course the card isn't present. The state of flag -55 determines whether last arguments need to be dealt with. But I suspect that finding it's available capacity would require SysRPL (or lowel level) code. But one could at least determine whether the card has "enough" capacity by trying to store an object in it. -- Happy New Year, everyone! James
From: James M. Prange on 31 Dec 2006 20:58 Veli-Pekka Nousiainen wrote: > "James M. Prange" <jmprange(a)i-is.com> wrote in message > news:e024e$45979995$4267eaf1$10204(a)123.NET... > X >>> So the Bronze goes to Tim "Joker" Wessman >>> and you release your code and we'll see who is titled to GOLD & Silver > X >>> Both versions (the expanded, too) should go to the >>> www.hpcalc.org >> Well, maybe, but as John noted, often a shorter test, such as for >> the screen size, the availability of a "mass storage" port, or >> which I/O ports are available, will suffice. >> >>> in the Programming section of both 48 and 49: >>> The code is _exactly_ the same for all models >>> *and* UserRPL compatible. >> Well, the *source code* is the same for all models, so will work >> from an "ASCII" ("Text") transfer, but it will compile to 3 >> different program objects, depending on whether it's entered on a >> 48SX/S, a 48GX/G/G+, or a 49 series, thus binary transfers from >> one of these groups to another won't work. > > > Source code compatibility on an interpreted language is enough, IMO > > I think that the purpose was > 1) to show off some programming skills Well yes, I do rather like to show off once in a while. But it's also a learning experience. Someone is almost certain to point out something that doesn't work in all cases, or ways to do something using less bytes or execution time. > 2) to show that it's possible in UserRPL and benefit on it Yes, it may well be easier in SysRPL or assembly language, but I think that UserRPL is more powerful than many give it credit for, and making some code conditional on the hardware can be useful even in UserRPL. > eg. the final code will find it's way to the > www.hpcalc.org Maybe, but mostly as a demonstration. I doubt that many would need that much information, but they could choose whichever code they wanted for their particular tests. -- Happy New Year! James
From: James M. Prange on 31 Dec 2006 21:38 GaaK wrote: > James M. Prange wrote: >> \<< @ >> RCLF @ Get current flags, leave on stack. >> -55 SF @ Force last arguments off. >> 64 STWS @ Force wordsize. > use LCD\-> BYTES SWAP DROP (131*64=1098, 131*80=1370) Excellent! That not only mean that 64 STWS isn't needed, but any zint with fewer than 15 digits or any real takes fewer bytes than #50h. <snip> >> 1. @ >> IFERR @ >> PVARS @ 1. PVARS errors out on 48gII, works on other 49 >> @ series. > PVARS very very slow (49G full port 1). > Purge 'IOPAR', then 1 TRANSIO (force default 'IOPAR') > IOPAR HEAD (9600:49G, 115200:48gII) You have a good point, but if I did anything to IOPAR, I'd want to restore everything about it to exactly the way that it originally was, which opens a real can of worms; whether IOPAR originally existed in the home directory, and if so, its original contents and order within the directory. I've done that before so I know that it's possible, but it would take more bytes and would also be slow. I expect that I'll simply try storing a dummy object to port 1 instead. I expect that it will take a few more bytes than the PVARS method, but should be reasonably fast no matter what's stored in port 1 of a 49G. >> THEN @ >> 4. @ 48gII >> ELSE @ >> DROP2 @ Discard port variable list and >> @ available port capacity. >> 2. @ 49G >> END @ End of "inner" IFERR structure. <snip> But I'll think that I'm expected at my niece's house for a few glasses of sparkling grape juice soon, so I'll walk over there now that the rain's slowed a bit. Well, at least it's not snow or freezing rain, so I consider it good weather for New Year's Eve. -- Happy New Year to all! James
From: John H Meyers on 1 Jan 2007 16:47
On Sun, 31 Dec 2006 11:09:21 -0600, GaaK wrote: > Purge 'IOPAR', then 1 TRANSIO (force default 'IOPAR') OPENIO CLOSEIO also creates default IOPAR when not present (OPENIO creates it; CLOSEIO is to shut down the UART again :) |