Davvel Posted February 29, 2016 Author Share Posted February 29, 2016 (edited) As promised, today I am submitting my first tool for the "ATARI AGE" members who would like to have an easier way to compose 3 channel (no noise for now) music sequences for the TI 99/4A using a familiar interface. I opted to use Excel as the input medium as nothing beats the ease of use of Excel to input a lot of data and moving it around as required. Once all the notes are fed in the SCORE sheet, just click on Generate code and you will end up with a GPL program ready to be compiled using XGA99. One can utilise the sound list data bytes for assembly too by deleting the GPL Header and Footer templates in the TEMPLATE sheet in this same Excel. I urge you to look at the Sheet called "DEMO EXPLAINED" to appreciate the power of the tool and how easy it is to create a sound list data block which can be inserted in your games. I have protected some cells of the Excel Sheet to ensure no one overwrites the formulas by accident. Instructions: 1. Feed in Musical Score in the sheet called SCORE (Delete the demo data first by clicking on CLEAR ALL) 2. Click on GENERATE CODE 3. Switch to the OUTPUT sheet 4. Copy the content of the green code cell to notepad++ 5. Remove the 2 extra quotation marks that are delimiting the entire code block. 6. Compile using XGA99 7. Enjoy your TI GPL music using Classic 99 (see previous posts in this thread on how to compile and run GPL code) TIMUSICGenerator.zip Edited February 29, 2016 by Davvel 5 Quote Link to comment Share on other sites More sharing options...
+Ksarul Posted February 29, 2016 Share Posted February 29, 2016 Nice, every new tool for the GPL toolbox is a precious thing. Many thanks for writing this. . . 1 Quote Link to comment Share on other sites More sharing options...
Davvel Posted March 5, 2016 Author Share Posted March 5, 2016 Ralphb, kindly note that when using XGA99 and you accidentally have a duplicate label it would give you "Too many assembly passes" with no indication to why and where in the code caused this. Is there an easy way to identify the offending label that is causing this? Please remember that as long as the GPL program is small, finding the issue is manageable but when the program grows it may take quite some time to find what is causing the error. Thanks for your support. David Quote Link to comment Share on other sites More sharing options...
Davvel Posted March 6, 2016 Author Share Posted March 6, 2016 ralphb, Can you kindly indicate what is the expected result of an SRL 0,@>8300 ? I thought it would be ignored, but in fact it clears the content of >8300. Thanks David Quote Link to comment Share on other sites More sharing options...
ralphb Posted March 6, 2016 Share Posted March 6, 2016 Ha, that's actually quite a funny bug. It's been fixed on GitHub now, though. Most compilers and assemblers are multi-pass, i.e., they read the source code multiple times before generating code. The reason is quite simple: If you have a forward reference, e.g., . ... JMP NEXT <---- where is NEXT? ... NEXT CLR R0 . then you cannot create code for a jump to a location you haven't seen yet. The xas99 assembler is two-pass: The first pass reads the source code to find values for all symbols, and then the second pass generates code, substituting the previously found values for all symbols as it goes along. Interestingly, a two-pass assembler won't do for GPL. GPL has many different addressing modes for RAM, GROM, VDP RAM, and VDP registers. To save space, the language encodes addresses in 1, 2, or 3 bytes, depending on the value of the address. All ROM/RAM addresses are encoded relative to >8300, and the farther away an address is from >8300, the more bytes it takes to encode it. For example, in the instruction ST 1,@>8300, GPL encodes the @>8300 as @>00, but would encode @>8380 as @>0080 and @>9000 as @>0F1000. So if you have code like . .ST 1,@ADDR . then the compiler needs the second pass before it can generate the code for this instruction. Now look at this program (from the xga99 test suite): . S1 ST 1,@CPU1 S2 ST 2,@CPU2 S3 ST 3,@CPU3 EXIT CPU1 EQU >837F CPU2 EQU >837F+S2-S1-3 CPU3 EQU >837F+S3-S1-3-3 . The values of Sx and CPUx depend on each other, and since all CPUx values are just slightly below >8380, their encoding might be 1 or 2 bytes, depending on the size of each Sx instruction above. The first pass defines all symbols, but the second pass will move S2 and S3 as the argument of S1 has changed. Consequently, the values of CPUx will also change. In other words. the code after pass 2 is still "unstable", and thus not correct. So the GPL assembler needs another pass. This time, S3 is moved, as the argument of S2 has changed. Only in the fourth pass do all symbols remain stable, and we're done. xga99 has an upper limit of 32 passes, which is arbitrary, but 32 passes should be enough for anybody. But now back to the label bug: Because of some incorrect duplicate label check, the statement with the duplicate label changed the value of that label symbol twice per pass. xga99 correctly thought that some symbol is still unstable and triggered another pass, until we hit the 32 limit. So when I heard your error description, I knew immediately what went wrong. 1 Quote Link to comment Share on other sites More sharing options...
ralphb Posted March 6, 2016 Share Posted March 6, 2016 (edited) ralphb, Can you kindly indicate what is the expected result of an SRL 0,@>8300 ? Good question. The GPL spec doesn't state what happens for a shift value of 0. But if GPL is like assembly then shifting by 0 actually means shifting by 16 -- which would shift all the bits away. Now GPL is 8-bit only, so it makes only half sense ... Why don't you try SRA 0,@>8300, where the original value of >8300 is >80? If the assembly theory is correct, you should get >FF afterwards. EDIT: I just remembered: In assembly, shifting by 0 means shifting by R0, and if THAT is 0, then you shift by 16. So it only makes quarter sense for GPL now. Edited March 6, 2016 by ralphb 1 Quote Link to comment Share on other sites More sharing options...
Davvel Posted March 6, 2016 Author Share Posted March 6, 2016 ralphb, Thanks for your patience to answer my questions. I really appreciate your time. What I was after was a simple first pass check to see if someone typed 2 or more labels which are identical, this would throw an exception example : XGA99 Duplicate Label found "START". Quote Link to comment Share on other sites More sharing options...
ralphb Posted March 6, 2016 Share Posted March 6, 2016 What I was after was a simple first pass check to see if someone typed 2 or more labels which are identical, this would throw an exception example : XGA99 Duplicate Label found "START". Yes, the latest fix does just that. You can get the file from GitHub via the link above. 1 Quote Link to comment Share on other sites More sharing options...
Davvel Posted March 6, 2016 Author Share Posted March 6, 2016 Wow Ralph thanks for the fix, it will save me a lot of time. The last time I hit a duplicate label I had to use Excel to find which label was duplicate 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted March 7, 2016 Share Posted March 7, 2016 ralphb, Can you kindly indicate what is the expected result of an SRL 0,@>8300 ? I thought it would be ignored, but in fact it clears the content of >8300. Good question. The GPL spec doesn't state what happens for a shift value of 0. But if GPL is like assembly then shifting by 0 actually means shifting by 16 -- which would shift all the bits away. Now GPL is 8-bit only, so it makes only half sense ... Why don't you try SRA 0,@>8300, where the original value of >8300 is >80? If the assembly theory is correct, you should get >FF afterwards. EDIT: I just remembered: In assembly, shifting by 0 means shifting by R0, and if THAT is 0, then you shift by 16. So it only makes quarter sense for GPL now. After a careful look at the ALC for the GPL SRL and SRA instructions in the GPL Interpreter (Heiner Martin's disassembly listing of the TI-99/4A console ROM), I can say with confidence that the GPL SRL and SRA behave exactly like the ALC SRL and SRA, respectively, except that they are byte operations, of course. For all of the GPL shift instructions, the number to be shifted (destination operand) is first read into R0. For a byte operation, the byte is right-shifted with an ALC "SRA R0,8" to preserve the sign bit before it is copied to R2. For the GPL SRL instruction, after the number of bits to shift is put into the LSB of R0, the MSB of R2 is cleared with an ALC "SB R2,R2" to insure that zeroes are shifted into the LSB from the left. The shift is performed with an ALC "SRL R2,0", which uses the rightmost nybble (four bits) of R0 to get the number of bits to shift right. Any shift > 7 will result in clearing the byte. Shift = 0 will use a shift = 16, as noted by @ralphb, which, of course, also clears the byte. The shifted result is then copied from R2 to the destination byte. The GPL SRA instruction is set up just as for SRL except that the MSB of R2 is not cleared so as to maintain the sign bit already filling the MSB. The shift is performed by an ALC "SRA R2,0". And, yes, "SRA 0,@>8300" should transform >80 into >FF. ...lee 2 Quote Link to comment Share on other sites More sharing options...
RXB Posted March 7, 2016 Share Posted March 7, 2016 (edited) Well SRL is a byte command, DSRL is a word command. All commands in GPL that have no D in front are byte commands in GPL. i.e. DSRL or DSRA So SRL @>8300,0 as there are only 8 bits in a byte I think what happens is it decrements the value from 0 to F and repeats till it reaches 0 again. (Just a guess of the results) This might explain the results you get. Has anyone tried this with the RYTE DATA GPL Assembler yet? Aso the TI Intern has the commands backwards compared to the TI GPL manual and RYTE DATA GPL Assembler as TI Intern swaps the location and value spots. i.e. Ti Intern SRL 0,@>8300 while TI GPL Manual shows SRL @>8300,0 Also GPL has SRC (Shift Right Circular) or DSRC (Double Shift Right Circular) and there is no SLC or DSLC command. (A very useful command in GPL) Will have to check if the GPL Assembler I use says that 0 is a invalid data for a SRL or SRA or SLL or SLA command, would also have to check D commands for words. The RYTE DATA GPL Assembler does 16 passes with a value of PF (Passes 16) but is really a endless pass GPL Assembler. Edited March 7, 2016 by RXB Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted March 7, 2016 Share Posted March 7, 2016 So SRL @>8300,0 as there are only 8 bits in a byte I think what happens is it decrements the value from 0 to F and repeats till it reaches 0 again. (Just a guess of the results) You don't need to guess. In my last post, I explained what the GPL Interpreter actually does: It converts the operation to a TMS9900 ALC (Assembly Language Code) word (double-byte) operation with the shift in R0 and the data to be shifted in R2: SRL R2,0 The '0' shift signals the TMS9900 to use the LSN (Least Significant Nybble = 4 bits) of R0 for the actual shift. Regardless of the actual value in R0, the shift will always be limited to 1 – 16, with LSN = 0 signalling a shift of 16. I do not know how the various GPL Assemblers limit what GPL code is emitted; but, the GPL Interpreter will handle a shift of—say, 127—just fine. The LSN of 127 is 15. Aso the TI Intern has the commands backwards compared to the TI GPL manual and RYTE DATA GPL Assembler as TI Intern swaps the location and value spots. i.e. Ti Intern SRL 0,@>8300 while TI GPL Manual shows SRL @>8300,0 Actually, in his description of GPL, Heiner Martin shows source and destination operands in the same order as the TI manual. It is the GROM listings that are backwards, which he explains and so warns the reader on page 80 of his TI99/4A INTERN: The GROM listings have been worked out with the GPL disassembler. The disassembler chose the source operand and the destination operand in reverse order from what has been used in the following explanations to the GPL commands. Please pay attention when reading the GROM listing. The disassembler's order likely reflects the actual byte-code of GPL, which has the destination operand first. It was probably easier to write the disassembler this way. Ralph (@ralphb) surely has some insight here. Also GPL has SRC (Shift Right Circular) or DSRC (Double Shift Right Circular) and there is no SLC or DSLC command. (A very useful command in GPL) Well, there is no SLC in ALC, either. To effect "SLC" in GPL would only require subtracting the desired left shift from 8 and using that value with SRC. Of course, subtracting from 16 would be necessary for DSRC to manage a "DSLC". Interestingly, GPL (per the TI GPL Programmer's Guide) has (D)SLL, but no (D)SLA, whereas ALC has it the other way round, i.e., SLA, but no SLL. It is only in the mind of the programmer that this matters because they are the same operation. The GPL Interpreter converts the emitted code for (D)SLL to the ALC's SLA. Thierry Nouspikel's GPL Assembler allows (D)SLA which emits the same code as for (D)SLL. ...lee 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted March 8, 2016 Share Posted March 8, 2016 (edited) In case anyone is interested in a text-file ALC listing of the TI-99/4A console ROM, I have extracted it from Heiner Martin's TI99/4A INTERN. Of principal concern for this thread is the GPL Interpreter, which starts near the beginning. The biggest reason I extracted it was to allow me to view it in a side-by-side mode in Notepad++ in an effort to better follow the convoluted branching. One of these days, I may Convert all of the register references from numbers (0 – 15) to R-notation (R0 – R15) Replace hex memory-location labels (every line) with mnemonic labels Remove unreferenced hex memory-location labels Remove the machine code column. Some folks have probably already done this, especially those who have re-written the console ROM; but, here it is anyway: ConsoleROM_ALC.lst** ...lee **Corrected listing (see post #96 below): ConsoleROM_ALC_corr.lst Edited March 9, 2016 by Lee Stewart 2 Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted March 8, 2016 Share Posted March 8, 2016 Some folks have probably already done this, especially those who have re-written the console ROM; but, here it is anyway: Who, besides TI, has re-written the console ROM ? Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted March 8, 2016 Share Posted March 8, 2016 Who, besides TI, has re-written the console ROM ? I am pretty sure that Winfried Winkler and Tony Knerr both modified the console's GROM0; but, I do not know whether either (or anyone else) modified the ROM. I do know there are a lot of hardwired references in console-ROM to instruction code, the machine code of which just happened to be the value(s) needed. I ran into several when I deconstructed KSCAN. It was one of those things (unwise IMHO) TI did to conserve space. It also makes it very dangerous to attempt a rewrite. Even if it could be successfully rewritten, there is likely third-party (maybe TI, as well) code out there that also does this. Though not ROM, the one example I know about that did something like this with a GROM location is Craig Miller's GSRLNK/DSRLNK routines. He found 2 bytes in the middle of a data block that just happened to be the machine code for the GPL instruction, “XML >27”, which he used in his code to trick the GPL Interpreter into “returning” to his routine in ALC. ...lee 1 Quote Link to comment Share on other sites More sharing options...
Tursi Posted March 8, 2016 Share Posted March 8, 2016 (edited) I did this port of the TI Intern code some time ago, and verified that the CPU code successfully assembles. I also fixed the argument order in the GPL part, but I can't remember if we proved it builds correctly or not... (Edit: updated archive to include Lee's fix from below) tiintern.zip Edited March 9, 2016 by Tursi 2 Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted March 9, 2016 Share Posted March 9, 2016 (edited) Okay. Thanks. I've done quite a few hacks to the console ROM and GROM myself. Mainly just to try things out. Left it alone, since with almost any change, potential incompatibilities lurk around the corner.Is the hardware available for burning new GROMs and replace ? Edited March 9, 2016 by sometimes99er Quote Link to comment Share on other sites More sharing options...
+Ksarul Posted March 9, 2016 Share Posted March 9, 2016 Put an Atmel1284 programmed with a variant of the UberGROM code that lets you use GROMs 0, 1, and 2 and put it on a daughter board that plugs into a single GROM socket. That will allow you to replace all three console GROMs at once. . . 1 Quote Link to comment Share on other sites More sharing options...
RickyDean Posted March 9, 2016 Share Posted March 9, 2016 Put an Atmel1284 programmed with a variant of the UberGROM code that lets you use GROMs 0, 1, and 2 and put it on a daughter board that plugs into a single GROM socket. That will allow you to replace all three console GROMs at once. . . Something similar to a SOB from OPA 1 Quote Link to comment Share on other sites More sharing options...
Tursi Posted March 9, 2016 Share Posted March 9, 2016 Please be careful with my code if it has been modified to override the built-in GROMs. There are two caveats, which are why I shipped it with that code disabled: 1) No address read-back functionality. You need one real GROM somewhere in the system. This is deliberate for now as I wasn't ready to call my address read-back code done, but I have tested code that will ship in MPD. 2) If you're just overriding from the cartridge port, /probably/ no worries. I've done it, it works, but I didn't measure current draw to ensure there was no danger of burning anything out (we may need current limiting resistors) and I wanted to verify that I had tested against the internal pull up and pull down resistors before shipping it for that. if you mean to install inside the console and permanently /replace/ the GROMs, please use current limiting resistors, otherwise GRAMKrackers or future AVR-GROM products may end up fighting each other directly on the bus, causing damage. It's all just "be careful about maybes", but better safe than sorry. 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted March 9, 2016 Share Posted March 9, 2016 I did this port of the TI Intern code some time ago, and verified that the CPU code successfully assembles. I also fixed the argument order in the GPL part, but I can't remember if we proved it builds correctly or not... tiintern.zip I found an error in Heiner Martin's disassembly listing of the console ROM. The error is on page 62 of TI99/4A INTERN at location >17BC: 17BC 835C DATA >83C5 Pointer address VDP Verified from binary dumps (not mine) and my real iron, It should read 17BC 835C DATA >835C Pointer address VDP You will note that the machine code (the second hex number) is actually correct; but, because the error is in the ALC, it was propagated into the source code of TI994A_CPU.asm packaged in @Tursi's ZIP file referenced in his quote above. After assembling the corrected ALC and converting the OBJ file to BIN format, it is identical to the ROM binary used by Classic99 and MESS. ...lee 2 Quote Link to comment Share on other sites More sharing options...
Davvel Posted March 9, 2016 Author Share Posted March 9, 2016 After a careful look at the ALC for the GPL SRL and SRA instructions in the GPL Interpreter (Heiner Martin's disassembly listing of the TI-99/4A console ROM), I can say with confidence that the GPL SRL and SRA behave exactly like the ALC SRL and SRA, respectively, except that they are byte operations, of course. For all of the GPL shift instructions, the number to be shifted (destination operand) is first read into R0. For a byte operation, the byte is right-shifted with an ALC "SRA R0,8" to preserve the sign bit before it is copied to R2. For the GPL SRL instruction, after the number of bits to shift is put into the LSB of R0, the MSB of R2 is cleared with an ALC "SB R2,R2" to insure that zeroes are shifted into the LSB from the left. The shift is performed with an ALC "SRL R2,0", which uses the rightmost nybble (four bits) of R0 to get the number of bits to shift right. Any shift > 7 will result in clearing the byte. Shift = 0 will use a shift = 16, as noted by @ralphb, which, of course, also clears the byte. The shifted result is then copied from R2 to the destination byte. The GPL SRA instruction is set up just as for SRL except that the MSB of R2 is not cleared so as to maintain the sign bit already filling the MSB. The shift is performed by an ALC "SRA R2,0". And, yes, "SRA 0,@>8300" should transform >80 into >FF. ...lee Thanks Lee for the exhaustive explanation. It's much more interesting when you know what is going on underneath the hood. Quote Link to comment Share on other sites More sharing options...
Tursi Posted March 9, 2016 Share Posted March 9, 2016 I found an error in Heiner Martin's disassembly listing of the console ROM. The error is on page 62 of TI99/4A INTERN at location >17BC: Wow, thanks Lee! I thought I did a binary compare years ago, so I had trusted this. I've updated my local copy (and suggest anyone who downloaded it update theirs ). Quote Link to comment Share on other sites More sharing options...
RXB Posted March 14, 2016 Share Posted March 14, 2016 I am pretty sure that Winfried Winkler and Tony Knerr both modified the console's GROM0; but, I do not know whether either (or anyone else) modified the ROM. I do know there are a lot of hardwired references in console-ROM to instruction code, the machine code of which just happened to be the value(s) needed. I ran into several when I deconstructed KSCAN. It was one of those things (unwise IMHO) TI did to conserve space. It also makes it very dangerous to attempt a rewrite. Even if it could be successfully rewritten, there is likely third-party (maybe TI, as well) code out there that also does this. Though not ROM, the one example I know about that did something like this with a GROM location is Craig Miller's GSRLNK/DSRLNK routines. He found 2 bytes in the middle of a data block that just happened to be the machine code for the GPL instruction, “XML >27”, which he used in his code to trick the GPL Interpreter into “returning” to his routine in ALC. ...lee I have written several versions of GROM 0, GROM 1 and 2 changing and customizing different things. Many from the MIller Graphics notes on GROMs 0, 1 and 2. Also I came out with RBASIC that added EA Cartridge support to TI Basic without using a EA Cartridge. As far as I know no one else ever did this. Quote Link to comment Share on other sites More sharing options...
Davvel Posted October 4, 2016 Author Share Posted October 4, 2016 For all my friends here, first of all sorry for not being around the TI community in the past 5 months but between work and family I had little to no time for my hobbies. Now things settled down a little and I can commit several hours of my time again towards GPL development. I have approx. 90% of my game done. I have also found help in the music department which was killing my initiative to continue, but was lucky enough to find a friend who is composing a suitable music score for me to key in into a soundlist. All looks gelling and I am posting this message as a commitment to the community that by December the game has to be released for all to enjoy. For now all I can reveal is that name of game is "Break Free" - 100% GPL and is dedicated to the TI communities around the world. 8 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.