BJGuillot Posted May 2, 2016 Share Posted May 2, 2016 I'm a bit stuck with a problem. I want my QR Code Generator to be able to run on a non-expanded TI. It had been working until I added support for the "small character set" needed for 40-column mode. I traced the problem into the GPLLNK call that I found from TurboForth that was used to obtain the small character set. For some reason, the BLWP call to GPLLNK works fine in js99er.net if the 32 KB memory expansion option is enabled, but if I turn that option off, the program causes the emulated TI to reset back to the title screen when it encounters the "bl *r4" line. When the program runs correctly, it will simply display "HELLO WORLD" and freeze. I'm not sure if it's my fault in the way I've got things setup, something in the GPLLNK routine itself, something in the emulator, or if there is some fundamental reason that doesn't allow GPLLNK to work on a non-expanded TI. I have attached a small sample program that demonstrates the problem. (I assemble it using "xas 99 -R -c gpltest.a99" to get an RPK that I can load with js99er.net. Any assistance would be appreciated. And if there's a way to load the small character set without using GPLLNK, I'm open to using an alternate technique. This was just the only technique I'd been able to find so far. gpltest.a99 Quote Link to comment Share on other sites More sharing options...
+mizapf Posted May 2, 2016 Share Posted May 2, 2016 Bummer ... I wanted to do a quick test, but I cannot assemble this code with Editor/Assembler because you are using lowercase commands and other non-TI formatting. I know this looks nice for external assemblers like xas, but it blocks any way to assemble this inside the emulation or on real iron. Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted May 2, 2016 Share Posted May 2, 2016 The routine uses some of the lower 8K (>2000). When you disable the 32K, the routine has no where to store the data it is moving or looking for when it gets to the "bl *r4". Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted May 2, 2016 Share Posted May 2, 2016 The problem with calling GPLLNK is that you need a way back to ALC. The only option I'm aware of is via the GPL XML command (>0F). If you are not writing and executing your own GPL program, you must find in an existing GROM the >0F byte followed immediately by a byte that gets you to an ALC location that contains the address of an ALC routine. The only areas over which the programmer has any control for this purpose in the present case are low RAM and cartridge ROM. The GPLLNK routine you are using (from Millers Graphics, originally) uses the only viable byte combination in GROM 0, viz., >0F27, at >176C, which translates to “XML 27”, which branches to >200E in low RAM. That is why the 32KiB expansion must be present. In order to branch to cartridge space, you would need to find a GROM byte combination of >0F70 – >0F7F, which would allow branches to ROM addresses >6010 – >602E. There is no such byte combination in GROM 0. I don't know about GROM 1 or GROM 2 because I don't have a dump of those GROMs. Another option would be to copy the character patterns from GROM to VRAM yourself. The small capital character set (64 patterns) starts at >06B0 in GROM 0 and the lower case character set (31 patterns) starts at >0870 in GROM 0. One fly in the ointment is that each pattern is only 7 bytes of the 8 bytes required for each character! Between the two character sets, it saved 95 bytes. You would need to zero the first byte and copy the next 7. If you are interested, I could probably cobble together a routine to do either or both sets. ...lee 2 Quote Link to comment Share on other sites More sharing options...
BJGuillot Posted May 2, 2016 Author Share Posted May 2, 2016 Thanks for the help guys. It seems a lot more complicated than I expected. When InsaneMultitasker pointed out I was hitting low expanded RAM at >2000, I had one of those Doh! moments, and thought it'd be a simple matter to just change that to a location in scratch RAM, but for all the reasons Lee pointed out, it seems like that was a dead end. I did find a thread, http://atariage.com/forums/topic/169349-the-quest-for-the-gpl-gate, where retroclouds was trying to do something similar, but I am not following it closely enough to try to replicate it. I think trying to copy the character set from GROM to VRAM will be the better approach. Thanks for the offer to cobble up a routine, but I'd like to try it first myself. I hate asking for help on things unless I get totally stuck or need to discuss options. I did encounter some discussions about the danger of bypassing GPL and copying the character set from GROM is that different GROM versions may have the character set starting at different addresses. Is there any truth to that? Quote Link to comment Share on other sites More sharing options...
BJGuillot Posted May 2, 2016 Author Share Posted May 2, 2016 OK, I went ahead and gave up on trying to use GPL to load the small character set. I'm attaching a file that uses the method suggested (to read the character set out of GROM). A few differences noted from what was suggested: I had to use address >06B4 (instead of >06B0). Also, I noticed that I could read all 95 patterns sequentially from GROM (instead of the first 64 patterns at >06B4, and then looking for the other 31 patterns at the other location). I'm not sure if this is something being caused by the js99er.net emulator or if it might be something else. (I have not tried this on a real console yet.) grom.a99 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted May 3, 2016 Share Posted May 3, 2016 Also, I noticed that I could read all 95 patterns sequentially from GROM (instead of the first 64 patterns at >06B4, and then looking for the other 31 patterns at the other location). I'm not sure if this is something being caused by the js99er.net emulator or if it might be something else. (I have not tried this on a real console yet.) Yes...The two sets are contiguous. ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted May 3, 2016 Share Posted May 3, 2016 I had to use address >06B4 (instead of >06B0). Classic99's GROM 0 is, in fact, 3 bytes off in one place from Heiner Martin's dump of GROM 0. The Classic99 GROM 0 does use >06B4 for the start of the small cap char set patterns. There is an >FC byte just before the start of the table that might be useful for registration. ...lee 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted May 3, 2016 Share Posted May 3, 2016 BJ... I noticed in grom.a99 that you set VDPSC to >08FF, which is one byte before the pattern for 'space' (ASCII 32)—not capital 'A' as you indicate. That has the effect of shifting the characters one pixel higher than starting at >0900. It's not a problem because the zero byte of the next character pads the bottom of the current character. I just wondered whether that was your intent. ...lee Quote Link to comment Share on other sites More sharing options...
Tursi Posted May 3, 2016 Share Posted May 3, 2016 Since there are a couple of GROM0's out there, I actually released code a while back that copies the lower case character set by parsing the GROM jump vector to find the code... let me see if I can find that for you. 2 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted May 3, 2016 Share Posted May 3, 2016 (edited) GPLLNK can be used without the memory expansion. I need to know a little more about your memory usage before I can help you. It looks like your workspace is at >8300. Do you use other parts of the scratchpad? Will your assembly code be in a ROM cartridge? Let me know and I will be able to look at this tonight and come up with a solution that will work. (edit) Forgot to ask if you only want to load the lower case characters or if you need the full GPLLNK for other purposes. Edited May 3, 2016 by senior_falcon Quote Link to comment Share on other sites More sharing options...
+acadiel Posted May 3, 2016 Share Posted May 3, 2016 Since there are a couple of GROM0's out there, I actually released code a while back that copies the lower case character set by parsing the GROM jump vector to find the code... let me see if I can find that for you. I think I have that. We put it as part of the 32K cart that we used with Fred's disk utility multicart, I believe. * BANK 0-4 ROM HEADER FOR 32K BANKED * SWITCHED CART DEF SFIRST,SLAST,SLOAD UNL * ROM HEADER AORG >6000 SFIRST EQU $ SLOAD EQU $ GRMHDR BYTE >AA,1,1,0,0,0 DATA PROG BYTE 0,0,0,0,0,0,0,0 PROG DATA 0 DATA GOGO BYTE 8 TEXT 'DM2K 2.3' EVEN MINIT EQU $ LWPI >8300 * Entry point here - ideally put this code first in your ROM * load R3 with 6 for 99/4, or 7 for 99/4A GOGO CLR R0 BL @GPLSET BL @GETGPL * read GROM >0000 LI R3,7 CI R0,>AA01 * 99/4 is AA01, all versions of 99/4A seem to be AA02 (even 2.2!) JNE IS4A * note we also assume unknown is 99/4A just to be safe DEC R3 * make a copy of the capitals for the 99/4 to 'support' lowercase * this will be partially overwritten by the main set, but it works! LI R0,>0018 * GPL vector address LI R1,>4A00 * dest in VDP - must OR with >4000 for write LI R2,>0040 * how many chars BL @GPLVDP * this function goes somewhere later in your ROM JMP MNSET IS4A * 'lowercase' letters LI R0,>004A * GPL vector address (not available for 99/4) LI R1,>4B00 * dest in VDP - must OR with >4000 for write LI R2,>001F * how many chars BL @GPLVDP * this function goes somewhere later in your ROM * main set MNSET LI R0,>0018 * GPL vector address LI R1,>4900 * dest in VDP - must OR with >4000 for write LI R2,>0040 * how many chars BL @GPLVDP * this function goes somewhere later in your ROM * THIS IS THE ROUTINE THAT WILL * SWAP BANKS TO HIGH BANK MAIN MOV R0,@>6000 LI R4,>0714 * BYTES DIV 4 LI R9,>63B0 * ADDRESS TO COPY FROM LI R10,>A000 * ADDRESS TO COPY TO LP1 MOV *R9+,*R10+ MOV *R9+,*R10+ DEC R4 JNE LP1 * THIS IS THE ROUTINE THAT WILL * SWAP BANKS TO NEXT BANK MAIN2 MOV R0,@>6002 LI R4,>0714 LI R9,>63B0 LI R10,>BC50 LP2 MOV *R9+,*R10+ MOV *R9+,*R10+ DEC R4 JNE LP2 * THIS IS THE ROUTINE THAT WILL * SWAP BANKS TO NEXT BANK MAIN3 MOV R0,@>6004 LI R4,>0714 LI R9,>63B0 LI R10,>D8A0 LP3 MOV *R9+,*R10+ MOV *R9+,*R10+ DEC R4 JNE LP3 * THIS IS THE ROUTINE THAT WILL * SWAP BANKS TO THE LOW BANK MAIN4 MOV R0,@>6006 LI R4,>023F LI R9,>7704 LI R10,>2000 LP4 MOV *R9+,*R10+ MOV *R9+,*R10+ DEC R4 JNE LP4 * ALRIGHT, WE'RE DONE. LET'S GO! B @>A000 * Set GROM address GPLSET MOVB R0,@>9C02 SWPB R0 MOVB R0,@>9C02 B *R11 * Get a word from GPL GETGPL MOVB @>9800,R0 SWPB R0 MOVB @>9800,R0 SWPB R0 B *R11 * Copy R2 characters from a GPL copy function vectored at * R0 to VDP R1. GPL vector must be a B or BR and * the first actual instruction must be a DEST with an * immediate operand. Set R3 to 6 for 99/4 (6 byte characters) * or 7 for a 99/4A (7 byte characters) GPLVDP MOV R11,R10 * save return address BL @GPLSET * set GROM address BL @GETGPL * Get branch instruction (not verified!) ANDI R0,>1FFF * mask out instruction part AI R0,3 * skip instruction and destination BL @GPLSET * set new GROM address BL @GETGPL * get actual address of the table BL @GPLSET * and set that GROM address - GROM is now ready! SWPB R1 * assume VDP is already prepared for write to save space MOVB R1,@>8C02 SWPB R1 MOVB R1,@>8C02 * VDP is now ready! CLR R0 LP8 MOVB R0,@>8C00 * pad the top of the char with a space MOV R3,R0 * then copy 7 (or 6) bytes CI R3,6 * check for 99/4 JNE LP9 MOVB R0,@>8C00 * extra blank line for 99/4 LP9 MOVB @>9800,@>8C00 * copy a byte (both sides autoincrement) DEC R0 JNE LP9 DEC R2 * next character JNE LP8 B *R10 FINISH EQU $ SLAST END 1 Quote Link to comment Share on other sites More sharing options...
BJGuillot Posted May 3, 2016 Author Share Posted May 3, 2016 I noticed in grom.a99 that you set VDPSC to >08FF, which is one byte before the pattern for 'space' (ASCII 32)—not capital 'A' as you indicate. That has the effect of shifting the characters one pixel higher than starting at >0900. It's not a problem because the zero byte of the next character pads the bottom of the current character. I just wondered whether that was your intent. Hmm... I think I probably grabbed the >08FF address from something I saw during one of my Google searches and just stuck with it. I'll need to go fix it. Still getting the hang of the memory map and other oddities of the TI. And still have a hard time thinking in hexadecimal. :-) Thanks for the help. Quote Link to comment Share on other sites More sharing options...
BJGuillot Posted May 3, 2016 Author Share Posted May 3, 2016 GPLLNK can be used without the memory expansion. I need to know a little more about your memory usage before I can help you. It looks like your workspace is at >8300. Do you use other parts of the scratchpad? Will your assembly code be in a ROM cartridge? Let me know and I will be able to look at this tonight and come up with a solution that will work. (edit) Forgot to ask if you only want to load the lower case characters or if you need the full GPLLNK for other purposes. The primary purpose was just to get the character set to use for the 40- (and 80-) column modes. It looks like reading them directly from GROM may be a suitable workaround, though. For play and learning purposes, it might be fun to try calling some of the other GPL routines (like the beep/honk sounds), but I assume those can probably be done without GPL as well. I'd like to be able to run my code from a ROM cartridge at some point (for non-expanded TI's), but also provide the flexibility to run it from disk using EA (for people with a PEB or NanoPEB). Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted May 3, 2016 Share Posted May 3, 2016 The primary purpose was just to get the character set to use for the 40- (and 80-) column modes. It looks like reading them directly from GROM may be a suitable workaround, though. For play and learning purposes, it might be fun to try calling some of the other GPL routines (like the beep/honk sounds), but I assume those can probably be done without GPL as well. I'd like to be able to run my code from a ROM cartridge at some point (for non-expanded TI's), but also provide the flexibility to run it from disk using EA (for people with a PEB or NanoPEB). Will have it tonight for you. Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted May 3, 2016 Share Posted May 3, 2016 The problem with calling GPLLNK is that you need a way back to ALC. The only option I'm aware of is via the GPL XML command (>0F). If you are not writing and executing your own GPL program, you must find in an existing GROM the >0F byte followed immediately by a byte that gets you to an ALC location that contains the address of an ALC routine. The only areas over which the programmer has any control for this purpose in the present case are low RAM and cartridge ROM. This last statement is wrong. The E/A manual has an incomplete list of XML table references! Thierry's site has the complete list and there are two XML table references to scratchpad RAM: >A0 – >AF and >F0 – >FF, both of which refer to >8300 – >831E. There are seven locations in GROM 0 that can be used to get you to a routine whose address is in >8300, >8306, >8316, >831C and >831E. The locations and their references are listed below: GROM 0 Address XML Cmd Vector Address -------------- ------- -------------- >00E8 XML >FF >831E >034C XML >FF >831E >0379 XML >F0 >8300 >0DBB XML >F3 >8306 >0EDE XML >FB >8316 >1264 XML >F0 >8300 >1675 XML >FE >831C ...lee Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted May 3, 2016 Share Posted May 3, 2016 You're on the right path now. You might find that a BL @GPLLNK will work as well as BLWP @GPLLNK. Unless someone beats me to it I will post a BL @GPLLNK routine tonight. 1 Quote Link to comment Share on other sites More sharing options...
Tursi Posted May 3, 2016 Share Posted May 3, 2016 I think I have that. We put it as part of the 32K cart that we used with Fred's disk utility multicart, I believe. That's it, thanks. GPLVDP is the function in question in there, and it's called twice (once for uppercase, once for lowercase). Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted May 3, 2016 Share Posted May 3, 2016 Hoo-boy! In revisiting my last post with an eye to comparing the two GROM 0's I now know about, they only agree on the last address!! At least, there appears to be one invariant—unless there's a third one out there that could scramble this. Here's the result for the GROM 0 used by Classis99 compared to the one dumped by Heiner Martin: GROM 0 Address XML Cmd Vector Address (Classic99) (Martin) (Classic99) (Martin) (Classic99) (Martin) -------------------- -------------------- -------------------- >00E8 >00E5 XML >FF XML >FF >831E >831E >034C >0349 XML >FF XML >FF >831E >831E >0379 >0376 XML >F0 XML >F0 >8300 >8300 >0DBB >0DB7 XML >F3 XML >EF >8306 >D01E >0EDE >0EDA XML >FB XML >F7 >8316 >830E >1264 >1260 XML >F0 XML >F0 >8300 >8300 >1675 >1675 XML >FE XML >FE >831C >831C ...lee 1 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted May 4, 2016 Share Posted May 4, 2016 (edited) I haven't tested it, but this should do the trick: (edited per Lee's suggestion below) ******************************************************************************** *GPLLNK AND DSRLINK FROM THE SMART PROGRAMMER *adapted to use scratchpad RAM only *Uses >8320 as a workspace ******************************************************************************** GPLWS EQU >83E0 GLNKWS EQU >8320 GR4 EQU GPLWS+8 GR6 EQU GPLWS+12 LDGADD EQU >60 XTABFE EQU >831C GETSTK EQU >166C GPLLNK DATA GLNKWS DATA GLINK1 GXMLAD DATA >1675 GLINK1 MOV @>0050,@GR4 MOV *R14+,@GR6 MOV @XTABFE,R12 LI R9,XMLRTN MOV R9,@XTABFE LWPI GPLWS BL *R4 MOV @GXMLAD,@>8302(R4) INCT @>8373 B @LDGADD XMLRTN MOV @GETSTK,R4 BL *R4 LWPI GLNKWS MOV R12,@XTABFE RTWP Edited May 4, 2016 by senior_falcon 3 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted May 4, 2016 Share Posted May 4, 2016 Looks good, Harry! I think I would change the 'XTAB27' label to 'XTABFE' to avoid confusion, however. ...lee Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted May 5, 2016 Share Posted May 5, 2016 I just tested the modified GPLLNK in post #20 and it works fine for loading the 3 possible character sets (Large, regular and lower case) Main program workspace was at >8300 and the BLWP workspace was at >8320. 1 Quote Link to comment Share on other sites More sharing options...
ralphb Posted March 20, 2019 Share Posted March 20, 2019 Heh, I arrived almost at the same code, but what's the relation of XTABFE and GXMLAD? AFAIK the original routine uses >200E and >176C, but both >1675 and >176C don't make any sense address-wise. How are those values used? I might want to move XTABFE somewhere else. Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted March 20, 2019 Share Posted March 20, 2019 Heh, I arrived almost at the same code, but what's the relation of XTABFE and GXMLAD? AFAIK the original routine uses >200E and >176C, but both >1675 and >176C don't make any sense address-wise. How are those values used? I might want to move XTABFE somewhere else. The following probably contains a lot of what you already know, but, hopefully, it answers your questions and may help the casual reader with other details: XTABFE contains the address of the 15th vector (16 possible) in the 16th XML vector table (16 possible) referenced by the GPL code: “XML >FE”. The two-byte, hex code for this is >0FFE. The XML table:element refrence is >FE, with >Fx referencing the table starting at >8300 and >xE referencing element >1C—hence >831C as the value of XTABFE. GXMLAD contains the address of the GPL XML instruction (>0FFE) we wish the GPL interpreter to execute, which is located at GROM0 address >1675. Regarding the GROM0 addresses >1675 and >176C, GPL instructions are on byte boundaries, not word boundaries as with ALC. The GPL XML instruction opcode (>0F) appears at both locations. The XML table:vector byte that follows it in the first reference (>1675) is >FE, which is explained above. In the Heiner Martin GROM0 dump, the byte following >0F at >176C is >27, which points to the 8th vector (>200E) in the 3rd XML vector table, starting at >2000 in low RAM. Because the GPL interpreter is byte oriented, it does not matter that the GPL “instructions” at >1675 and >176C are data and never normally executed. It is sufficient that they happen, fortuitously, to be the actual instructions we need to serve our ends. ...lee 2 Quote Link to comment Share on other sites More sharing options...
ralphb Posted March 20, 2019 Share Posted March 20, 2019 Oooh, I see now! I thought that these might be GROM addresses, but then in TI Intern I saw that these are within text strings?! Oh, how clever! Thanks for enlightening me, I'll be looking for other, more convenient >0F's! 2 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.