TIFILES1€óP1DIARY OF A KRACKER-HACKER "I've had a lot of fun and a lot of'frustration in the last couple of weeks%working with my GRAM-KRACKER, working'with very fragmentary information about'GPL, trying to make my 'custom' machine!do what I wanted it to do. In theÿ'course of all this I've found out a few%things and picked up a couple of tips'that may interest some of you. I am not#claiming that my techniques are the!best, my code the most compact or'efficient, or my knowledge particularlyÿ I wanted it to do. In theÿ&profound. In fact, the opposite of all&that is probably more accurate picture#of where I'm at. On the other hand,'these notes may save somebody else some&of the frustration I went through, and%thereby make for more _fun_, which isÿwanted it to do. In theÿwhat this deal is all about! "I got an 80K G/K, mainly because I'wanted to load custom character sets in&GROM 0, and store E/A and TIW in GROMs%1 and 2. Loading character sets is no$big deal, once you discover that the!utility provided with the GK onlyÿÿ copies the last seven bytes each!character definition and that the'operating system only holds seven bytes&for each 'small' character, using them#to define the _last_ seven bytes of#each eight-byte definition. Anyway,"once I had the characters loaded Iÿÿÿ$wanted to be able to get at them all$easily. This required adding two new'calls: one to load the so-called 'title$screen' characters (upper case only)$and one to restore lower case (since%the built-in CHARSET already restoresÿad the characters loaded Iÿÿÿ#the upper case.) The code for these"calls was already available in the$operating system, spelled out in the'June '84 issue of SMART PROGRAMMER. The problem I ran into, however, was'figuring out th proper method to RETURNÿoresÿad the characters loaded Iÿÿÿ&from the CALL so that I would re-enter"X-BASIC cleanly, and that the CALL would work in a running program. 'Understand that it is _easy_ to program'directly in GPL _without_ an assembler,!as long as you are writing short,ÿesÿad the characters loaded Iÿÿÿ%simple CALLS which use no symbolic or'relative references. Commands translate&fairly directly into bytes, and GPL iscompact enough so that you can'literally read it direcly, once you getthe hang of it. "From various sources, The EXPLORERÿrs loaded Iÿÿÿmanual, SMART PROGRAMMER, and#especially the excellent and fairly"complete manual for the Pascal GPL$Assembler in DL4, it seemed that the$simple byte command >00 was a RETURN%and, sure enough, using >00 seemed at"first to work. It always worked inÿed Iÿÿÿ&command mode and sometimes worked fromrunning programs. But obviously#sometimes is not good enough. From'checking out other calls in X-BASIC and$in the XBCALLS GK utility, I finally%realized that RETURN itself needed toÿwork. It always worked inÿed Iÿÿÿ'be called. CALL in GPL is >06, and CALL&must be followed by a _vector_ for the#called routine. That is, an address&containing the address of the routine.The EXPLORER manual tells all,"including the address of a routineÿoÿwork. It always worked inÿed Iÿÿÿ%which is suppossed to be "Return from%LINK or DSR." Well it also works as a"return from CALL, so it seems. Its%address is at >0012 in GROM 0, so the%complete RETURN fragment in GPL turns out to be: >06 CALL">00,>12 GPLLNK VECTOR FOR RETURN  ÿÿ#Now that may not be the best way to%return from a simple CALL, but it has'an obvious advantage: it works. So does$another fragment used by some of thesimple calls in XBCALLS: >05 BRANCH#>C1,>E3 (an address in the XBasicÿ VECTOR FOR RETURN  ÿÿ$ GROM which apparently also# CALLS the correct RETURN) #So add the return to the Load Title$Screen Characters code listed in theJune *SP* and you get: >31 GROM to VDP MOVE>02,>00 # of bytes to moveÿcÿ VECTOR FOR RETURN  ÿÿ#>A9,>00 VDP DESTINATION ADDR plus offset>04,>B4 GROM SOURCE ADDRESS>06 CALL>00,>12 RETURN VECTOR Unfortunately, this moves the$definitions to the wrong address for%BASIC, because of the notorious BASICÿcÿ VECTOR FOR RETURN  ÿÿ%offset. But alter the VDP DESTINATIONadress and it works just fine! $Another approach is to CALL the Load%Title Screen routine provided for use"by GPLLNK. This is a a _different_#routine from the code above, and it$uses a vectored destination address.ÿÿ$(You remember, place the destinationaddress at FAC...) >BF CPU STORE$>A4 at >83A4 (addresses in PAD! are referenced by LSBy)!>04,>00 VDP DESTINATION without offset>06 CALL&>00,>16 GPLLNK VECTOR for LOAD TITLEÿÿ# SCREEN CHARACTERS ROUTINE>06 CALL>00,>12 RETURN %Both versions are 10 bytes long; bothwork. 'Of course, when you add a CALL you have%to go to the last 'SUBROUTINE HEADER'$or what I call the last entry in theÿ VECTOR for LOAD TITLEÿÿ&CALL ref/def table, and add the header$for the new CALL. You have to modify#the previous header to point to the$addre ss of the new header; give the&address of the next header (or >00,>00&if there are no more); give the lengthÿtheÿ VECTOR for LOAD TITLEÿÿ%of the CALL name and the name itself;&and finally give its address. Where to$put the code? Anywhere you want, but$consider MG's XBCALLS. They continue%the chain of CALL headers starting at&G>D800, but scatter their code throughÿheÿ VECTOR for LOAD TITLEÿÿ&the remaining GROM space. I found that$the code for CLSALL and CLKOFF, both short six-byte sequences with no%relative references, are stuck out in&the middle of nowhere, so I moved them"to G >DA58 (right after CLOCK) andÿhroughÿheÿ VECTOR for LOAD TITLEÿÿ$changed their headers. This left melots of room to add my new CALL&headers. I then tacked the code for my!CALLS after CLSALL and CLKOFF, at&G>DA64 and beyond. [The long blocks of"code that constitute CLOCK and CAT$contain relative references, symbolsÿÿÿ&and the like, and are too messy to try$to move. One tip here though; don't!overwrite the >00,>00 you find at'G>DEC3. These bytes are part of the CAT code and must be left blank. Addanything you want at >DE40 andbeyond.] ÿelative references, symbolsÿÿÿ$Once I got my CALL BGCHAR working to%load my custom Title Screen character#set, I added CALL LC to restore the%lower case character set to 'normal;'"very useful for chaining programs: >BF CPU STORE>A4 at >83A4ÿelative references, symbolsÿÿÿ!>06,>00 VDP DESTINATION without offset>06 CALL&>00,>4A GPLLNK VECTOR for LOAD LOWER CASE CHARACTERS>06 CALL>00,>12 RETURN Using these built in GPLLNKs and!CALLing other CALLS is so _easy_,ÿ references, symbolsÿÿÿ%letting the GPL intrpreter keep track$of returns, that I went on and addedCALL BEEP and CALL HONK: >06 CALL>00,>34 VECTOR for BEEP>06 CALL>00,>12 VECTOR for RETURN >06 CALL>00,>36 VECTOR for HONK>06 CALLÿ symbolsÿÿÿ>00,>12 VECTOR for RETURN $And finally I checked out the actual'GPL code for HONK and decided to try to'add CALL CHIME. I had to store the data'for the CHIME sound list somewhere (the&data is in the E/A manual) so I tuckedÿNK>06 CALLÿ symbolsÿÿÿ#it down at G>DE40. The code for theCALL is as follows: >BF CPU STORE>58 at >8358">DE,>40 address of my sound list">F6 INPUT/OUTPUT INSTRUCTION#>58 CPU SOURCE address vector%>00 I/O FLAG: defines this as aÿLLÿ symbolsÿÿÿ" SOUND operation with the sound list in GROM>06 CALL>00,>12 VECTOR for RETURN This code turns on the sound and#immediately returns to the next GPL"statement. The E/A manual includes$>8358 in a general area defined as aÿlsÿÿÿ'stack area, used by DSR's, etc. I don't#know if any other PAD address wouldwork as well. "Once I got all this stuff going, I$decided to go for the big one. I hadpreviously written a package of$text-mode utilities for X-BASIC [seeÿrea defined as aÿlsÿÿÿ&X40 in DL4] and I decided that I could%store the code for those utilities in'the remaining unused X-BASIC GROM space$and write a simple CALL to read them%into memory. I mean, SYSTEX is great,%but memory-to-memory is the ultimate. ÿÿrea defined as aÿlsÿÿÿ$First I had to refine the X40 code abit. I already had my alternate#character set in console GROM, so I'took out the ALCHAR routine and its PAB'and a little associated baggage. Then I%moved all the buffers to the _end_ ofÿimate. ÿÿrea defined as aÿlsÿÿÿ'the source code so all the real meat of'the code would load contiguously at the&top of low memory. I wanted to be able#to fit everything I needed into the!unused space in GROMS 3,4, and 5,#leaving the rest of GROM 6 free forÿate. ÿÿrea defined as aÿlsÿÿÿ%more extensions of X-BASIC and GROM 7free altogether. I had >17F0 blank bytes of GROM&available; all I needed to save was my&program code and the ref/def table. My$code took up the space between >24F4"(the First Free Address after CALLÿfined as aÿlsÿÿÿ'INIT) and about >3870, the start of the$buffer space. This was only >137C of'code; the ref/def table was another >A0'bytes, still plenty of room. But how to$get this code, with all its symbolic'and relative addresses, from low memoryÿCALLÿfined as aÿlsÿÿÿ&into GROM? True, I only had to do this$once, but I certainly didn't want tohave to type it all in! $I couldn't use the GK editor for the#move, because _it_ resides in lower!memory, and overwrites the code I'needed to move. So I took a round-aboutÿÿlsÿÿÿ#route. I wrote a temporary GPL CALL%to move the entire 8K low-memory into$high memory from X-BASIC (after CALL&INIT::CALL LOAD(DSK1.X40:OBJ"). Then I#used the GK editor to move the code%from high-memory into GROMs 3, 4, andÿ So I took a round-aboutÿÿlsÿÿÿ'5. Here's the code that moved the stufffrom low to high: >35 CPU MOVE>20,>00 BYTE COUNT>8F CPU&>1D,>00 DESTINATION ( ->8300 OFFSET)>8F CPU>9D,>00 SOURCE (MINUS OFFSET)>06,>00,>12 THE USUAL RETURN ÿook a round-aboutÿÿlsÿÿÿ&This is lifted of course straight fromCM's tutorial on GPL moves. #I moved the code into GROM in threechunks, >7F0 bytes to G>7810(>7800-7809 used by the defeat'auto-load patch), >800 bytes to G>9800,&the remaining bytes to G>B800 with theÿboutÿÿlsÿÿÿ'ref/def table moved to G>BB90. This wasvery easy with the GK editor. I%immediately Saved the module with the A/L code in place just in case I&screwed up the next step. Then I wrote'the GPL CALL to move the code back intoplace in low memory. ÿoutÿÿlsÿÿÿ#Friend Miller does advise that it's%faster to write an A/L mover, use GPL$to move it into place in low memory,%then branch to it and let it move out"the rest of the code. This kind of#boot-strapping is said to be fasterÿoplace in low memory. ÿoutÿÿlsÿÿÿ&than using GPL to move the whole works&directly; it's certainly more elegant.&GPL is still simpler, however, and the%speed is fast enough with memories of%loading this stuff from disk so freshin my mind. So, four GPL moveÿace in low memory. ÿoutÿÿlsÿÿÿ&instuctions gets the three code blocks&and the ref/def table back into place,'and one last move instruction moves out$new First Free Address and Last Free"Address values to >2002. It may be$driving a nail with a sledge-hammer,ÿ in low memory. ÿoutÿÿlsÿÿÿ%but it works! Here's the actual code: >31 GROM to CPU move>07,>F0 BYTE COUNT>8F MARKS CPU ADDRESS >A1,>F4 DESTINATION, CPU >24F4 MINUS >8300 OFFSET>78,>10 GROM SOURCE and so on... >31,>08,>00,>8F,>A9,>E4,>98,>00ÿÿlsÿÿÿ>31,>03,>86,>8F,>B1,>E4,>B8,>00>31,>00,>B0,>8F,>BC,>50,>BB,>90>31,>00,>04,>8F,>9D,>02,>DA,>B8 >06,>00,>12 %Now from X-Basic I issue CALL INIT ::#CALL X40 and I am ready to use textmode! Who need MYARC! I hope these code fragments andÿ,>98,>00ÿÿlsÿÿÿ"procedural notes do serve a usefulpurpose. I am glad we are all!respecting TI's copyright and not%uploading actual altered modules, but!it does make for more emphasis on%technique in the message base and theDL's. $Once more written material on GPL isÿÿ available this will all be a lot'easier, I am sure, and my examples will!be seen for the clumsy dross they probably are. Personally, I look'forward to having a nice manual and not'having to read through the GRAM KRACKER"manual, the EXPLORER manual, SMARTÿ&PROGRAMMER, and various other sources,&feeling like a biblical scholar trying#to pin down specific references and%cross-reference ambiguities. But then&again, I guess that's why they call usKRACKER-HACKERS! Richard Minutillo [72277,1062] ÿnual, SMARTÿ @Þæ49äÿæ"xÞæ27\ÞæI 1°Þæ76”Þæ'èÞæ65ÌÞæv 4 ßæ