ftg0673@tamsun.tamu.edu (Rick Grevelle) (06/14/91)
This is an enhanced version of the HACKIT thing. It includes several new features which further facilitate hacking in the 48, and are as follows: o Multifunctional PEEK will now allow the normally hidden 32k of ROM to be peeked. When flag 14 is clear the 32k of memory between #70000h and #7FFFFh is RAM. When the flag is set this is shifted to #F0000h through #FFFFFh, and #70000h through #7FFFFh becomes what was previously covered by RAM; this configuration is identical to that of the built in memory scanner. o Bank switching capabilities have also been incorporated in the SEEK scheme, functioning exactly as described in the PEEK routine. o DIR-> is a new addition to the OUT-> command; it allows a directory in level 1 to be decomposed on the stack in to its constituent parts. Due to this change, it's not necessary to include the RCLDR scheme in the library as it was added to the original HACKIT post only after all first attempts to produce a successful DIR-> had failed. o Flags -28 and -29 have now been combined into one flag, 15. This flag affects the way in which the ->ASCI, and ASCI-> routines handle code objects. Currently a ->STR, and STR-> scheme is being conceived that will provide a superior editing scheme for queer objects. At the risk of being reiterative, I'm including an improved version of the documentation which appeared in the original posting of this library. It should be a bit more articulate, and contain examples for those whose time is allowing. Much work still remains to be done regarding the completely bullet proof hacking library, but since all the fun seems to be in getting there, hopefully it will take a long time. A final word of caution; do *not* attempt to implement a bank shift using either PEEK, or SEEK, if this library is stored in port 0, or anywhere in the address space being displaced. This means both of the 32k banks that are affected by setting flag 14 are off limits, as far as this feature is concerned, for the storing of this library. Should there be any question about this, or anything else, feel free to call, or write, and I shall be glad to provide any answers of which I might be capable :-). Rick Grevelle (409) 774-1169 ftg0673@tamsun.tamu.edu HACKIT ============================================================================== HACKIT is a library of utilities designed to facilitate hacking in the HP48SX. The fourteen programs it contains were conceived for two fundamental purposes: o Exploration, documentation, and accessing of the machine code, and RPL operating system contained in the 48's vast ROM. o Construction, and manipulation of the various object types not supported by the 48's editor, user language commands, functions, or operations. ->ASCI This is a generalized binary-to-ascii conversion scheme that returns a string of hexadecimal characters which are the equivalent internal representation of the argument. When USER FLAG 15 is set both the prolog and the length of code objects are truncated meaning that the result string contains in-line machine code only. When this flag is clear, which is the default, truncation does not occur. All other object types are unaffected by the flag setting. ASCI-> Reversing the result of the previous routine is made possible with this scheme, which converts ascii-to-binary, taking as its argument a string of hexadecimal characters. When USER FLAG 15 is set all strings are treated as in-line machine code, whereby a code object would be the result. When flag 15 is clear one of two things happens depending on the string argument itself, and is explained in the following summary. IMPORTANT POINTS o The above routines were intended to provide a means for *toggling* stack objects back between their internal string representation and immediately executable form, which means ROM objects must be dealt with differently. An important attribute associated with these two schemes is their ability to differentiate between ROM and RAM objects. o When an argument taken by the ->ASCI routine is a ROM object, a character string representing the five nibble address where that object is located in ROM is returned. Strings containing only five characters that are used as arguments for ASCI-> are treated as pointers; solitary prologs are not permitted though (i.e. "D9D20", "C2A20", "11920"). Future versions should be more than capable of dealing with such complexities as this. o Spaces and newline carriage returns are allowed in strings that are to be converted by ASCI->. This helps to alleviate some of the confusion when looking at long strings of hexadecimal characters in that spaces can now be used to separate groups of characters, and newline carriage returns to segment the string into several lines when editing. o Any object encoded using ->ASC can be unencoded using ASCI->. There's no longer a need for these silly schemes to delete newline carriage returns, or calculate a new checksum to tack onto an ->ASC encoded object that has been altered in order to get ASC-> to work. ->ASC, and ASC-> were written to provide a safe means of transferring data, and not for hacking. It is therefore not recommended to use these two schemes in place of ->ASC, and ACS->. o ASCI-> performs equally well on strings of odd number lengths because the RPL segments of the program correctly utilize the block allocate routine at #61C1Ch. But because of its very nature, it's still quite possible to suffer a memory loss from abusing this routine; so be careful. Example: Construct the DUP command from it ASCII string representation. _________________________ _________________________ |{HOME} | |{HOME} | |-----------------------| |-----------------------| |4: | |4: | |3: | :3: | |2: | |2: | |1: "78BF1"| |1: DUP| |### ### ### ### ### ###| |### ### ### ### ### ###| ------------------------- ------------------------- 1) Enter the string "78DF1". 2) Implement ASCI-> to obtain the command DUP. SCRC Calculates the checksum of a string of hexadecimal characters as if they were in immediately executable form. So objects which have been converted to their internal hexadecimal character string form (ASCII) using ->ASCI will have the same checksum when SCRC is used on the ASCII string, as they would have had in their binary form using the BYTES command. This allows queer objects such as libraries and backups that contain checksums which do not include the complete data structure to be altered, or even constructed from scratch, in the 48. So for an example a trivial backup object will be built utilizing SCRC, ->ASCI, and the ASCI-> routines. Example: Build a backup object named "Hex" containing the hexadecimal integer, # 123456789ABCDEF0h. o Construct the backup object's appropriate name. _________________________ _________________________ |{HOME} | |{HOME} | |-----------------------| |-----------------------| |4: | |4: | |3: | |3: | |2: | |2: | |1: 'Hex'| |1: "84E2030845687"| |### ### ### ### ### ###| |### ### ### ### ### ###| ------------------------- ------------------------- 1) Enter the name 'Hex'. 2) Implement ->ASCI on the name. _________________________ _________________________ |{HOME} | |{HOME} | |-----------------------| |-----------------------| |4: | |4: | |3: | |3: | |2: | |2: | |1: "30845687"| |1: "3084568730"| |### ### ### ### ### ###| |### ### ### ### ### ###| ------------------------- ------------------------- 3) Edit the string to delete 4) Concatenate "30" by using the first five characters. the plus (+) key. o Prepare the backup object's contents for concatenation. _________________________ _________________________ |{HOME} | |{HOME} | |-----------------------| |-----------------------| |4: | |4: | |3: | |3: | |2: "3084568730"| |2: "3084568730"| |1: # 123456789ABCDEF0h| |1: "E4A20510000FEDCBA..| |### ### ### ### ### ###| |### ### ### ### ### ###| ------------------------- ------------------------- 1) Enter the integer data. 2) Implement ->ASCI once again. o Make final preparations for checksumming. _________________________ _________________________ |{HOME} | |{HOME} | |-----------------------| |-----------------------| |4: | |4: | |3: | |3: | |2: | |2: "3084568730E3A2051..| |1: "3084568730E4A2051..| |1: "33000"| |### ### ### ### ### ###| |### ### ### ### ### ###| ------------------------- ------------------------- 1) Concatenate the previous 2) DUP the result string, and two result strings using use SIZE to obtain its size. the plus (+) key again. Add 15 to the size, convert the result to a hexadecimal number, and enter backwards as a five character string. _________________________ _________________________ |{HOME} | |{HOME} | |-----------------------| |-----------------------| |4: | |4: | |3: | |3: | |2: | |2: "330003084568730E4..| |1: "330003084568730E4..| |1: "119200"| |### ### ### ### ### ###| |### ### ### ### ### ###| ------------------------- ------------------------- 3) Perform a SWAP, and using 4) Append the string "119200" the plus (+) key, prepend to the end of the string, the length onto the front DUP the result, and using of the string. SCRC calculate the object's proper checksum. o Make final preparations for coverting the string. _________________________ _________________________ |{HOME} | |{HOME} | |-----------------------| |-----------------------| |4: | |4: | |3: | |3: | |2: "330003084568730E4..| |2: "26B20"| |1: "0B41"| |1: "330003084568730E4..| |### ### ### ### ### ###| |### ### ### ### ### ###| ------------------------- ------------------------- 1) Enter the four hexadecimal 2) Enter the prolog for the characters of the checksum backup object backwards, backwards in a string, and and perform another SWAP. append this to the string for which the checksum was calculated. _________________________ _________________________ |{HOME} | |{HOME} | |-----------------------| |-----------------------| |4: | |4: | |3: | |3: | |2: | |2: | |1: "26B20330003084568..| |1: Backup Hex| |### ### ### ### ### ###| |### ### ### ### ### ###| ------------------------- ------------------------- 3) Prepend the prolog using 4) Convert the string using the plus (+) key one last ASCI-> to its binary form. time. SEEK Appearing first in his Processor Notes, SEEK is in fact a modified version of Alonzo Gariepy's FIND routine. SEEK was specifically modified to run in the 48; it's one third the size of the original version for the 28, and should run a bit quicker too. Alonzo's predominately register, rather than memory oriented algorithm remains unchanged. Recall the overall increase in speed was only about 10% over that of the brute force approach, which he attributed to an increased time spent in the looping structures. Because it demonstrates several programming features specific to the 48, I've taken the liberty of renaming the routine. The way to use this program is to specify a memory pattern and a place to start looking. A memory pattern can be sequence of up to fifteen nibbles, and a one nibble length (one minus the number of nibbles in the pattern). An application for SEEK could be to locate the occurrences of the instruction 808C in memory. To do this enter # C8083h in level two, and a starting place such as # 0h. All that remains to be done is to implement SEEK, and to continue doing so to find any subsequent instances. This is because the result returned will be a binary integer which is the address one higher than where the pattern exist in memory. IMPORTANT POINTS o Bank shifting capabilities have been incorporated into SEEK, allowing the normally hidden 32k bank of ROM to be searched. With USER FLAG 14 clear, the 32 kilobytes of memory between #70000h, and #7FFFFh, is RAM. Setting flag 14 shifts the RAM to #F0000h through #FFFFFh, and reconfigures what was previously hidden ROM in its place. o This version does not stop until it finds an instance, or scans the entire address space. So even though the routine is fast, due to the size of the 48's address space, matching certain patterns could take several seconds. Example: Determine the first occurrence of the ARRAY prolog, # 029E8h, in the normally hidden 32k bank of ROM. (flag 14 set) _________________________ _________________________ |{HOME} | |{HOME} | |-----------------------| |-----------------------| |4: | |4: | |3: | |3: | |2: # 29E84h| |2: # 29E84h| |1: # 70000h| |1: # 72001h| |### ### ### ### ### ###| |### ### ### ### ### ###| ------------------------- ------------------------- 1) Enter the bit pattern with 2) The result returned is the the number of nibbles minus one higher than where the one, and the address where actual pattern was found. to begin searching. PEEK Speed is still an essential attribute of this dual functioning PEEK. Only the variable length version will slow slightly when large result strings hundreds of characters long are returned. The routine is smart enough to know which of the PEEKs to implement based on the arguments it's given. When string results are preferred, level two should contain a binary integer that's the address to be peeked, while level one should be a real number representing the length of the result string. The bank shifting features as described in SEEK scheme are also available in this version of PEEK; an example follows. Example: Using PEEK and ASCI->, recover the message array from the hidden ROM found in the previous example. (flag 14 set) _________________________ _________________________ |{HOME} | |{HOME} | |-----------------------| |-----------------------| |4: | |4: | |3: # 29E84h| |3: | |2: # 72000h| |2: # 29E84h| |1: 641| |1: Array of String| |### ### ### ### ### ###| |### ### ### ### ### ###| ------------------------- ------------------------- 1) Subtract one from the above 2) Now implement ASCI-> on the result, enter the number of result to obtain the ARRAY. nibbles to be returned, and implement PEEK. POKE Complimenting PEEK is this dual functioning variable length POKE scheme which will accept either a string of hexadecimal characters, or a binary integer for the level two argument that represents the data to be poked. Level one should be a binary integer that is the address to poke. It is important to note that when the level two argument is a binary integer, the wordsize of that specific integer will be used to determine the number of nibbles to poke, and isn't in any way dependent upon the current wordsize returned by RCWS. OUT-> Multifunctioning OUT-> encompasses several of the object types on which OBJ-> will not work. In addition, and analogous to the LIST-> command, ALG-> and PRG-> are intended to function on algebraics, and programs. ARR-> functions identically to ARRY->, but works on all the various array types such as the array of string, algebraic, list, etc. DIR-> decomposes a directory that is in level one into its constituent parts. XLIB-> has also been included; it decomposes visible, and hidden XLIBs into their library and command numbers. Example: Decompose the Array of String obtained in previous example into its constituent parts. _________________________ _________________________ |{HOME} | |{HOME} | |-----------------------| |-----------------------| |4: | |4: "Try To Recover Me..| |3: | |3: "Replace RAM, Pres..| |2: # 29E84h| |2: "No Mem To Config ..| |1: Array of String| |1: { 16 }| |### ### ### ### ### ###| |### ### ### ### ### ###| ------------------------- ------------------------- 1) Using the array obtained 2) Recompose the array again in the previous example, by using the ->ARR routine. implementing OUT-> will The result will look like reveal the strings. that of frame 1). ->ALG Be careful with this one; the stack arguments must be in strict RPN order. As before, ->ALG is analogous to ->LIST, only the result is an algebraic, rather than a list. ->ARR This is my version of ->ARRY; it will build an array of any kind providing all stack arguments are of the same type. (i.e. strings, reals, algebraics, etc.) It functions identically to ->ARRY, except that real and complex numbers can't be mixed. Level one can be either a real number, a list containing a real, or a list containing two reals that is the size the resulting array is to be. ->DIR Builds a directory from the stack on the stack. Level one must contain a real which is the total number of variables that the directory is to contain, level two a global name, and level three the contents of that global name. Because the entire process utilizes dynamic RAM, it is relatively fast for moderately sized directories, but slows substantially on very large ones. Using both the DIR-> feature found in the OUT-> command along with this routine, a directory on the stack can be effectively toggled between its constituent parts, and its composite form. ->PRG Functions identically to ->LIST, only the result is a program, and not a list. ->XLIB Builds an XLIB from two stack arguments. Level two can be either a real number or a binary integer that's the number of the library to which the XLIB belongs. Level one must be the same argument type as level two and should be the command number of the desired XLIB. ADDR Returns the address where the following stack arguments are located in memory: any ROM object, any XLIB belonging to a library stored in a port, any TAGGED that's either a BACKUP object or a LIBRARY stored a port. One final attribute associated with ADDR that merits mentioning, regards those XLIBs that belong to the three intrinsic ROM libraries with a link table. This routine can just as easily locate these address, as it can those in port memory. Even if the memory location happens to be that of the hidden ROM, ADDR will determine its address. RCLIB This multifunctional routine is to a library what RCL is to a directory. RCLIB will recall a library as a fully operational directory. All that is necessary to do is to put either the library's name or (real) number in level one. Again this is slowed greatly on very large libraries. RCLIB will work on any library including ROM (i.e. 2, 240, 1792). Finally, the contents of any library's XLIB can be recalled to the stack; simply put the appropriate XLIB in level one, and the result will be comparable to using RCL on variable stored in a directory. O / \/ /\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ O \ %%HP: T(1)A(D)F(.); "04B204341060841434B49445608854100000000D610063010E4A20E510000000 0000000000640003C00000000000000000000000000000000000000000000000 000000000003C000403534253420040355454B430040055454B44004005F4B45 450040F45545D860040D814C47470040D814252580040D844942590040D80525 74A004014444425C0050D8143534940005014353494D810050D885C49424B005 02534C49424D00C3000230008C0000C0008B0000B0008A0000A0008900009000 88000550005800005000E4A2037000570001D10029200AC3001C400C8600B570 0D480077800F7A00A8B000AB002FB001ED00E7E0029E00DDE0093F0059F001FF 0053010D51108885000D9D205AA81D9D20580408773508316CB916D9D20D9F81 61DC138E51FEF30D9D200CA30E0F06B2130B213032230A2170D9D20AD2A18DA1 6D9D20FD55035040C1C1612040CCD20720008F146608FB9760CCD81431301691 746E50B2130D9D208813020950FD5502C230F6E30C1C1632230CCD20C50008F1 46608FB9760CCD8143130169174143131AE015B03103A6A31939EA903170A6A1 48161170CD56D8D34150B2130B9F06B2130B2130B21308885100D9D20ECE81D0 040D9D205D5502265008316C1C16322308A816852305804087735A2170D9D208 81307104038D30A217068F0166F6088130616507104038D30A217068F0130040 C9B26AD2A1B3A1675660B213029E20885510B9F06B2130B21308885200D9D20E CE81D0040D9D2088130636508A81644230CCD206E0008F146608FB9760D81431 31179D0100CDD014B31A0962E631029625631149EE913103B6A4D631909E6466 510B6A31509E64530AA0A7650D230F0EF2D7331801D0CF480CA68FF118F61087 C20100171CD508238FF2245142164808C8F2D7608DB8F01101FC1180EF6121FE 0EF21110EFE013223063650FBD81ED2A2EF9A2B2130B21308885300D9D20FDE8 1ECD46D9D2030A50B704087735DA916CCD20C00008446010CCD20DA0008548F1 46608FB97601478643210810134FFFFF8FD7FB01182430F2011113416A1567AF 51801564130152780DF91052160BF4B4651F80CF0D40E910BDBF41605FE132E4 100864908F741C0248FF2245142164808CB2130B21308885400D9D20ECE81D50 40D9D2030A50B704087735DA916CCD20710008F146608FB97606920CCD208600 08548F146608FB9760D680D489750844864811002034FFFFF8FD7FB011013015 27100864908F741C02F8FF2245142164808CB21309FF30D9D202BF814CD46D9D 20AEC81FD5502C2308A816A2116F6E30C1C1633F0630A50B704087735DA916CC D20C00008446010CCD20990008548FD5F30068FB9760147864D2102108071093 4FFFFF8FD7FB0119061182430F2011213416907135D8CDAE015B03103A6A3193 9EA903170A6A148161170CD56D864908F741C08D34150B2130B2130B21308885 500D9D2008A81D9D202BF818AB46D9D2030A50322305D5502265008316C1C163 22308A81668F0129E20885510B4826B2130ECD46D9D2030A50B2130FEF302BC8 1B21302C23061650CCD20130008FD5F30068FB9760147134169131078FC07608 D3415044230B21308885600D9D20ECE8171040D9D20BCB73122702C230D1730C 0726433709A53092591B213012040379C1F3040379C194040379C158040D9D20 CCC80FBD8132230FBD8132230B213003B46D9D20FEF30083162A170E34240D97 1EE170D9D20881303E2808DF06FED308DF068DF06B21305E17044230FBD81B21 30B21308885700D9D2043C81D9D208A8162AC81D6450B2130B21308885800D9D 205AA81D9D202BF819FF30DEE3212040D9D209BC2603FD16B436B2130FEF302B C81B2130AD3911E136353369B191C41302C230FED3038D30A21702CC81CCD20F 71008F146608FB97601001438FC1830DB10A3441000CBC7C7C31741471371431 35104118CE45506143130D814211C8A2018F2D7608D7BC818F91030184136E9C 35908D066501740757B8FC455011B5F013706DB10B84A8F8DA604ED136109135 348E92014517411B13418413614517411C14517411A145D71B97507142130142 130174CF4F08F878301455DE118D707CF43313418414213606D81308F9103018 4D9136E91648FC07605AC8F2D760118C3DAC6C6C2133CA1311191458D94150B2 1308885900D9D20ECE819FF30D9D20AEC818A816D9D2041E8091870B2130F6E3 0C41302C23038D30A21702CC81FEF3032230BD3708131605391A2170E3424D9D 209AF168DA1667E7075660B2130122703F21653026A21702BC819EB504B25639 15051B503223012270FED30300405A3705D550D0040C1C162C23056316FED309 54506AE42B2130B21308885A00D9D2043C8154450B21308885B00D9D20FDE819 9040D9D20AEC8132230AEC813223005E70B2130ECD46D9D201D3F405E70B2130 B21308885C00D9D205AA81AD2A139916CCD20220008FB9760143248FC2245142 164808C8A12639916CCD203B0008FB9760143130167D01523D8182D015231B9D 707146AB7162A3F4B6146932D09B2E516759E16214613416C1428A844136CA13 0E5D4C4C4C01641468BE72136CA1301468AA71CA248FC2245142164808C8F2D7 608DB10506222639916D9D20881307CE50D9D20C435645DB05F290D9D2085356 45DB09FF304635645DB0300402FF40B21302BAA0B9F06E9016B9F0655C26A217 02FF40B2130B9F062A170E34248813028BA08DA16D9D20CAF064F912C121679B 308E8160CA30A2116CC95018A30B2130A00508C170B21302BC81B21308885D00 D9D205AA812BF819FF30D9D20AEC81881309C080A2170650115B826A21706501 129E20885410B2130B2040D9D20F4180A2170650118813029E20885410B21305 8040D9D2099E70B3A1661050B2130B2130D9D20119208850090770B2130D9D20 88130F128039916B9F06CCC804E761322304E7614525639150493262B1614932 651B50B2130D9D20FA450881303C37052330AD2A1A2170D9D2029E208853108A 126CB91629E20885F00B21309427043370D6450B2130D9D20FA450881303C370 52330AD2A1A2170D9D2029E208853108A126CB91629E20885F00B21309427043 37095450B2130D9D20FA450881303C37052330AD2A1A2170D9D2029E20885310 8A126CB91629E20885F00B2130942704337054450B2130D9D207E1263991629E 20885210112263991629E208851102D1263991629E20885010B2130D9D205D55 0D0040C1C16CAF06FEF30083162A170E342405E70D9D2088130F1280399169EB 5088130CCC804E761322304E7614525639150493262B16149326B21304B25639 15051B503223099E70EE170D9D20AD2A18DA16D9D209AF168DA1667E7075660B 213029E20885310EF116FED30F6E30D2E300831635316E9330FED30CA130B213 05E17062726F6E30FED30954506AE42B2130CCD20CC0008F146608FB9760D814 7C2134168174147C4C21C413717706D2305D7CD14B31A0962A43102962143114 9EED13103B6A4A531909E61515006910B6A31509E6D330AA0A1500180E71C1CD 56A183DB14418434CCD20144071361448D341508F2D7608DB8F0182823564"