brain Posted December 28, 2016 Share Posted December 28, 2016 I hate to ask for help, but after spending days reading the forums, I've still got gaps in my understanding of TI cartridges. I am hoping someone can help me with at least a link or two: In this posting: (http://atariage.com/forums/topic/224528-setting-up-a-512k-cart/page-2?do=findComment&comment=2981463), there's mention of a GPL Simulator. I did a search, but can only find a emulator with that name. Is there a link to said simulator code (I saw another posting that showed how to trick the internal GPL interpreter to use VDP, but not sure if that is the same thing. Same thread, the next poster notes that all Atari carts have been in EA5 format for a long time. Is there a link that explains what that means? Were the carts originally in GROMs and someone hand converted them out into source, which is in E/A format? I found little information on ROM-only carts autostarting. Is it possible? If so, where does the console expect to see the autostart magic bytes? I understand there are 3 different ways carts banked. normal, inverse, and CRU: Is there any information on CRU banking? Normal I understand, but on inverse, it looks like simply re-ordering the ROM banks allows one to use inverted images in normal carts. Is there more? In UberGROM, which I understand much better now (GROMs, maybe not all of UberGROM), you can define GROMs in up to 16*5 GROM locations. But, I notice that the TI, if it sees there are different base addresses, it makes you do the "review" to get the next list (the base 9800/9c00 GROMs show on the power up, then you do a "review", and the 9804/9c04 stuff shows, etc.) But, is there any value to that over having a GROM (or maybe ROM) menu app that configures the 5 GROM slots to be whatever you want? If the above hold water, how many GROM 8kB locations can be used (realistically)? I know 5 can be supported, but does the GPL interpreter allow a running GPL program to move to a new base and run 5 more? I assume so, but wonder, is it realistic, or would the app just reconfigure the current 5 or so to hold new GROM data and call into them. I'd like to make the ROM (not GROM) flashable from the TI. The TI bank switching design makes that a bit difficult, as does the CPU nature of doing a word read before a write messes up doing the magic writes needed to unlock a flash cart. Has there ever been a TI-writeable cart design that is available to peruse, or an idea that folks know that works? (I can create 3 registers in the cpld, hi byte, lo byte, data, to do writes, but that's so archaic. Is there a list of all of the GROM-based carts, which of the GROM locations (>6*,>8*, etc.) they have to run from, and whether they will work from a GROM base other than 9800/9c00? I read this ( Is there more information on GROMs to ingest? Is there a schematic of a GROM cart anywhere to peruse? I'm wondering how >9800 is selected to route to the GROM on the cart. I ask because I have finally acquired a TI with a PEB, and I'm not playing with it enough, so I thought challenging myself to learn the cart port would give me an excuse to enjoy it, and also an excuse to see if I could replicate the GROM in a CPLD. Jim 2 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted December 28, 2016 Share Posted December 28, 2016 I can answer some of your questions: 1. It's called the GPL linker. I asked the same question here: http://atariage.com/forums/topic/258764-are-we-going-to-have-a-ti-christmas/page-3?do=findComment&comment=3634564 2. They were originally ROM only cartridges. 3. A ROM only cartridge cannot autostart. 6. That's all there is to it. Quote Link to comment Share on other sites More sharing options...
+Ksarul Posted December 28, 2016 Share Posted December 28, 2016 1. In addition to the GPL Linker, there is a program called YLOAD out there that will load and run cartridge files from the 32K space. 2. Very few third-party cartridges used anything like GROM. Parker Brothers included a pair of CROM chips on their cartridges that were GROM work-alikes, several cartridge files over the years were produced for use in the GRAM Kracker or similar GRAM devices (and can now be turned into physical cartridges using the UberGROM) with three that come to mind there as follows: Winkler's XB3, the various flavors of Gilberton's RXB, and Knerr's XB 2.7. Triton's Super Extended BASIC used simulated GROMs (and the board could be extended to use multiple GROM bases and add other cartridge images into the mix), and the new Break Free game is written in GPL, so it needs the UberGROM as well. 3. The console looks for the auto-start magic bytes in GROM, so a ROM-only cart won't be seen during that check. 4. DataBioTics was the only company that used CRU banking, and then only on a small number of their cartridges. 5. You might want to check the documentation for the Superspace II module for CRU banking examples, along with the software templates they included on the disks for it. 6. As Rasmus noted, you have that one nailed. 7. Note on placement of GROM files into the UberGROM: it allows access to the first 16 GROM bases. Each GROM base can have up to five GROMs assigned to it at the cartridge port (giving the 16x5 in your example), BUT you can only use 15 (and a half) of those GROM slots practically, due to the size of the memory included on the ATMEL1284 chip doing the GROM simulation. The UberGROM also allows you to limit your programmed space to the five slots in the first GROM base and lock it down so that REVIEW MODULE LIBRARY does not trigger. 8. You can use no more than 15 slots on an UberGROM cartridge--but it could conceivably be one GROM in each of 15 GROM bases, each accessed by the REVIEW MODULE LIBRARY function. I have never seen a program written that cosses a GrOM base boundary. It may be possible, but I wouldn't count on it. 9. Look at Ralf Benzinger's FlashROM cartridge. It is probably the closest to what you are asking for here that exists. 10. There is not. There is a partial list out there, however. Acadiel maintains it. 11. Pull down the manual for the UberGROM, read through the various GPL documents from TI on WHT. 12. I believe I put a schematic for the UberGROM up on one of the threads here as well. Quote Link to comment Share on other sites More sharing options...
brain Posted December 28, 2016 Author Share Posted December 28, 2016 I can answer some of your questions: 1. It's called the GPL linker. I asked the same question here: http://atariage.com/forums/topic/258764-are-we-going-to-have-a-ti-christmas/page-3?do=findComment&comment=3634564 2. They were originally ROM only cartridges. Thanks 3. A ROM only cartridge cannot autostart. I now realize I asked an incorrect question. What I meant to ask is if a ROM-only cart can show up in the Power Up menu. FlashROM99 makes it appear like you can do that. But, to your original answer, can a GROM cart boot right inot the cart, bypassing the Power Up menu? Is that what you mean by auto start? (never have seen that...) 6. That's all there is to it. Cool. Thanks. Quote Link to comment Share on other sites More sharing options...
brain Posted December 28, 2016 Author Share Posted December 28, 2016 1. In addition to the GPL Linker, there is a program called YLOAD out there that will load and run cartridge files from the 32K space. With that in mind, is there an advantage to native GROM functionality as opposed to a menu that loads the game/util/app from ROM into 32K space, and runs YLOAD on that data? (I'm not trying to knock UberGROM, etc., just wanting to understand the limitations, if any to simulating) 2. Very few third-party cartridges used anything like GROM. Parker Brothers included a pair of CROM chips on their cartridges that were GROM work-alikes, several cartridge files over the years were produced for use in the GRAM Kracker or similar GRAM devices (and can now be turned into physical cartridges using the UberGROM) with three that come to mind there as follows: Winkler's XB3, the various flavors of Gilberton's RXB, and Knerr's XB 2.7. Triton's Super Extended BASIC used simulated GROMs (and the board could be extended to use multiple GROM bases and add other cartridge images into the mix), and the new Break Free game is written in GPL, so it needs the UberGROM as well. 3. The console looks for the auto-start magic bytes in GROM, so a ROM-only cart won't be seen during that check. But, I assume the ROM cart will be seen and shown in the Power up menu, correct? 4. DataBioTics was the only company that used CRU banking, and then only on a small number of their cartridges. 5. You might want to check the documentation for the Superspace II module for CRU banking examples, along with the software templates they included on the disks for it. Will look for it. 6. As Rasmus noted, you have that one nailed. 7. Note on placement of GROM files into the UberGROM: it allows access to the first 16 GROM bases. Each GROM base can have up to five GROMs assigned to it at the cartridge port (giving the 16x5 in your example), BUT you can only use 15 (and a half) of those GROM slots practically, due to the size of the memory included on the ATMEL1284 chip doing the GROM simulation. The UberGROM also allows you to limit your programmed space to the five slots in the first GROM base and lock it down so that REVIEW MODULE LIBRARY does not trigger. Yep, I watched his video, where he loaded one up. It had multiple bases and multiple GROMs per base. And, if someone wanted to do "review", then multiple GROM bases are key. 8. You can use no more than 15 slots on an UberGROM cartridge--but it could conceivably be one GROM in each of 15 GROM bases, each accessed by the REVIEW MODULE LIBRARY function. I have never seen a program written that cosses a GrOM base boundary. It may be possible, but I wouldn't count on it. Well, mainly looking at what would be realistic. 9. Look at Ralf Benzinger's FlashROM cartridge. It is probably the closest to what you are asking for here that exists. I read all about it last night. But, as previous posts will show, I was (and am) very interested in understanding the GROM functionality. At the time (2014), I just did not know enough about programmable logic, but time has passed and I have more knowledge now 10. There is not. There is a partial list out there, however. Acadiel maintains it. I think I saw it. 11. Pull down the manual for the UberGROM, read through the various GPL documents from TI on WHT. I found an old (v .7) version of the manual, but had not found a final version. Link? 12. I believe I put a schematic for the UberGROM up on one of the threads here as well. I saw a black (and then someone made it blue) schematic. Very enlightening. Is that the one you're describing? One new question. I'm an EAGLE CAD user (Yes, I know the crowd here tends to prefer KiCAD or ExpressPCB), and was wondering if anyone knew of a EAGLE footprint for the cart edge connector? I can absolutely make one, but always eager to use already proven footprints. Jim Quote Link to comment Share on other sites More sharing options...
brain Posted December 28, 2016 Author Share Posted December 28, 2016 I can answer some of your questions: 1. It's called the GPL linker. I asked the same question here: http://atariage.com/forums/topic/258764-are-we-going-to-have-a-ti-christmas/page-3?do=findComment&comment=3634564 Just finished reading. I think it also answers my question about why UberGROM is useful, as some games just took up so much ROM+GROM room. Jim Quote Link to comment Share on other sites More sharing options...
Tursi Posted December 28, 2016 Share Posted December 28, 2016 (edited) The UberGROM also allows you to limit your programmed space to the five slots in the first GROM base and lock it down so that REVIEW MODULE LIBRARY does not trigger. The 'review module library' option appears when the first 32 bytes of the first and second bases differ at GROM address >6000. So you can also prevent it from appearing on a cartridge with multiple bases by duplicating the first bank. (IIRC it's >6000, anyway). 8. You can use no more than 15 slots on an UberGROM cartridge--but it could conceivably be one GROM in each of 15 GROM bases, each accessed by the REVIEW MODULE LIBRARY function. I have never seen a program written that crosses a GROM base boundary. It may be possible, but I wouldn't count on it. That's only 15 slots of GROM (120k / 8k per slot). There is also 4k of EEPROM, 12k of RAM, 6 GPIO, 4 ADCs and a timer, all of which can be mapped to slots - so you can technically use 29 slots with distinct elements. A second problem is a surprising number of GROM programs won't work at any base except >9800 (they change the base rather than just letting the interpreter manage it)... only way to know is to try. Regarding crossing a GROM base boundary - you shouldn't do it. The UberGROM allows it by option, and the older simulators like the GRAM Kracker probably allow it, but real hardware does not. This is because real GROMs only have a 13-bit address counter (the upper three bits are fixed and used only to determine which specific GROM should answer reads). When they wrap, they wrap back to the beginning of the GROM's memory. As a result, if you did wrap from one GROM into the next, you would become out of sync with the console's GROMs. It's not necessary anyway, in GPL the GROM address is always set before fetching a byte (one of the reasons it's slower), so even if you did wrap across, it would still work fine. It only becomes an issue when reading GROMs from assembly code. I'm going to take the above statement back. It's true that the address is always set, but it's also usually read from the chips and not tracked elsewhere, so I actually don't know if wrapping naturally via code or via a MOVE works on the internal GROMs. (They use different blocks of code so may behave differently). TI code never did but they were also avoiding 2k of undefined data at the end of each 8k space. Edited December 28, 2016 by Tursi 1 Quote Link to comment Share on other sites More sharing options...
+acadiel Posted December 28, 2016 Share Posted December 28, 2016 10. There is not. There is a partial list out there, however. Acadiel maintains it. Yep, here you go. 1 Quote Link to comment Share on other sites More sharing options...
brain Posted December 29, 2016 Author Share Posted December 29, 2016 The 'review module library' option appears when the first 32 bytes of the first and second bases differ at GROM address >6000. So you can also prevent it from appearing on a cartridge with multiple bases by duplicating the first bank. (IIRC it's >6000, anyway).[/font][/color] I saw that in a post you made. BUt, it seemed very kludgey to have to do "review" to advance the menu all the time. I assume most folks prefer a single entry for UberGROM and then navigating through a menu. That's only 15 slots of GROM (120k / 8k per slot). There is also 4k of EEPROM, 12k of RAM, 6 GPIO, 4 ADCs and a timer, all of which can be mapped to slots - so you can technically use 29 slots with distinct elements. A second problem is a surprising number of GROM programs won't work at any base except >9800 (they change the base rather than just letting the interpreter manage it)... only way to know is to try. Which brought me to an idea, where there would be 5 GROM slot configs, and a menu could real-time map any GROM into those slots. Regarding crossing a GROM base boundary - you shouldn't do it. The UberGROM allows it by option, and the older simulators like the GRAM Kracker probably allow it, but real hardware does not. This is because real GROMs only have a 13-bit address counter (the upper three bits are fixed and used only to determine which specific GROM should answer reads). When they wrap, they wrap back to the beginning of the GROM's memory. As a result, if you did wrap from one GROM into the next, you would become out of sync with the console's GROMs. I think I am using the wrong terminology. I read the "debate" about the internal GROM counter and I understand that point. What I meant was a single GPL app that would run from 9800:3, then 9800:4... 9800:7 and then want to start executing in 9804:3, and so on. I'm going to take the above statement back. It's true that the address is always set, but it's also usually read from the chips and not tracked elsewhere, so I actually don't know if wrapping naturally via code or via a MOVE works on the internal GROMs. (They use different blocks of code so may behave differently). TI code never did but they were also avoiding 2k of undefined data at the end of each 8k space. In your AVR code, do you maintain a separate counter for 9800 set, 9804 set, etc.? Or, do you just run 1 13 bit counter for all GROM bases? Jim Quote Link to comment Share on other sites More sharing options...
brain Posted December 29, 2016 Author Share Posted December 29, 2016 Yep, here you go. Thanks. Very helpful. R0/1/2/3. I assume ROM, but what is the significance of the 0,1,2,3? 8kB banks? I thought so until I got to MAGIC MEMORY (TI WORKSHOP), which has 2s in each location. I asume that means 2 8kB ROMs in each of the 4 ROM locations, but how does the switching work in that situation? Also, concerning the various multi-carts, if they are ROM multicarts... How does the cart handle a "double offset" into the cart ROM? Namely, if you have stored a 32kB cart image at zome offset besides 0 in the ROM, a poke to the '378 from the application would not know about the initial offset, just it's offset from the beginning of the ROM image. Jim Quote Link to comment Share on other sites More sharing options...
+acadiel Posted December 29, 2016 Share Posted December 29, 2016 Thanks. Very helpful. R0/1/2/3. I assume ROM, but what is the significance of the 0,1,2,3? 8kB banks? I thought so until I got to MAGIC MEMORY (TI WORKSHOP), which has 2s in each location. I asume that means 2 8kB ROMs in each of the 4 ROM locations, but how does the switching work in that situation? Also, concerning the various multi-carts, if they are ROM multicarts... How does the cart handle a "double offset" into the cart ROM? Namely, if you have stored a 32kB cart image at zome offset besides 0 in the ROM, a poke to the '378 from the application would not know about the initial offset, just it's offset from the beginning of the ROM image. Jim Yes, 0, 1, 2, and 3 are 8K banks. The ROM bank switching is always done 8K at a time. The method used is either CRU, non inverted, or inverted. DataBiotics used the CRU (via custom PAL) and inverted (via 74LS379) methods. Others have used non inverted (74LS378, 377). The Databiotics >8K carts were the more prevalent ones and the ones I originally cloned for the 16K/64K cartridge boards, so they used inverted. The UberGROM manual has a very good section I wrote on how the different bank switching worked. About the 2, I don't remember. It might have been my initial way of denoting the CRU bank switch carts. Or maybe Ksarul when he edited did that to note his changes. These CRU carts included: Beyond Wordwriter (32K) Desktop Publisher (32K) Red Baron Flight Simulator (32K) Stargazer I/II/III Combo cart (32K) TI Workshop/Magic Memory (64K) Only TI Workshop has been modified to work with the 74LS378/379 bank switch method. Tursi did that a while back. Still looking for volunteers to help with the other four titles. About the offset; not sure what you're referring to. The random power up bank (yes, different 37x chips had different ones) meant that it was typically the first or last bank where the system powered up. We put a header in there in the first and last banks with the different offsets for the programs. The Assembly code we usually hand wrote with the offsets. Something like this, and I believe someone already make a EA/5 cart maker to do this automatically by now. Calculations: Offsets in the 32K ROM Header: >15->1C = Title (8 characters) >70->71 = Bytes in an 8K segment divided by four >74->75 = Where do the aforementioned bytes live on the ROM? >78->79 = Where to copy the first 8K bank to in memory expansion >88->89 = Bytes in an 8K segment divided by four >8C->8D = Where do the aforementioned bytes live on the ROM? >90->91 = Where to copy the second 8K bank to in memory expansion >A0->A1 = Bytes in an 8K segment divided by four >A4->A5 = Where do the aforementioned bytes live on the ROM? >A8->A9 = Where to copy the third 8K bank to in memory expansion >B8->B9 = Bytes in the last 8K segment divided by four >BC->BD = Where do the aforementioned bytes live on the ROM? >C0->C1 = Where to copy the fourth 8K bank to in memory expansion =============================================================================== DU2KLM = 23278 bytes, or 7760 x 3 (add two bytes to make divisible by 3 then DU2N = 4090 bytes, or 4096 (add six bytes to make divisible by 23280 DU2KLM-A000 4096 DU2N-2000 23280 BYTES (DU2KLM-A000) ------------------------- 7760 (>1E50) div 4 = 1940 or >0794 >61B0 to >7FFF = >1E50 (where each bank lives on the EPROM) A000 - BE4F bank 0 BE50 - DC9F bank 1 DCA0 - FAEF bank 2 4096 BYTES (DU2N-2000) ---------------------- 4096 (>1000) div 4 = 1024 or >0400 >7000 to >7FFF = >1000 (where it lives on the EPROM) =============================================================================== DM2KLM = 21998 bytes, or 7336 x 3 (add ten bytes to make divisible by 3 then DM2N = 3066 bytes, or 3072 (add six bytes to make divisible by 22008 DM2KLM-A000 3072 DM2N-2000 22008 BYTES (DM2KLM-A000) ------------------------- 7336 (>1CA8) div 4 = 1834 or >072A >6358 to >7FFF = >1CA8 (where each bank lives on the EPROM) A000 - BCA7 bank 0 BCA8 - D94F bank 1 D950 - F5F7 bank 2 3072 BYTES (DM2N-2000) ---------------------- 3072 (>0C00) div 4 = 768 or >0300 >7400 to >7FFF = >0C00 (where it lives on the EPROM) =============================================================================== CF2KLM = 22766 bytes, or 7592 x 3 (add ten bytes to make divisible by 3 then CF2N = 4858 bytes, or 4864 (add six bytes to make divisible by 22776 CF2KLM-A000 4864 CF2N-2000 22776 BYTES (CF2KLM-A000) ------------------------- 7592 (>1DA8) div 4 = 1898 or >076A >6258 to >7FFF = >1DA8 (where each bank lives on the EPROM) A000 - BDA7 bank 0 (40960 to 48551) BDA8 - DB4F bank 1 (48552 to 56143) DB50 - F8F7 bank 2 (56144 to 63735) 4864 BYTES (CF2N-2000 - v1.4) ---------------------- 4864 (>1300) div 4 = 1216 or >04C0 >6D00 to >7FFF = >1300 (where it lives on the EPROM) new ver 3834 BYTES (CF2N-2000 - v2.0) ---------------------- 3834 (>0EFA) div 4 = 958 or >03BE >7106 to >7FFF = >0EFA (where it lives on the EPROM) =============================================================================== Code (credits to Tursi and Stuart for helping with this a long time ago...) * THREE PROGRAM HEADER FOR 128K 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 PROG3 BYTE 0,0,0,0,0,0,0,0 PROG3 DATA PROG2 DATA DU2K BYTE 8 TEXT 'DU2K 2.0' EVEN PROG2 DATA PROG DATA DM2K BYTE 8 TEXT 'DM2K 2.4' EVEN PROG DATA 0 DATA CF2K BYTE 8 TEXT 'CF2K 1.4' EVEN *************** * Copy Data for Modules * * Format is: * First, the address to load for the first source bank. * Number of 32-bit words, source address, target address * To end list, provide a start address greater than >8000 * (This means you can't start in the low RAM bank) *************** CF2KDT DATA >6000 DATA >076A,>6258,>A000,>076A,>6258,>BDA8 DATA >076A,>6258,>DB50,>04C0,>6D00,>2000 DATA >A000 DM2KDT DATA >6008 DATA >072A,>6358,>A000,>072A,>6358,>BCA8 DATA >072A,>6358,>D950,>0300,>7400,>2000 DATA >A000 DU2KDT DATA >6010 DATA >0794,>61B0,>A000,>0794,>61B0,>BE50 DATA >0794,>61B0,>DCA0,>0400,>7000,>2000 DATA >A000 *************** * CF2K Module * *************** CF2K LWPI >8300 LI R14,CF2KDT * address of copy table JMP COPYLP *************** * DM2K Module * *************** DM2K LWPI >8300 LI R14,DM2KDT * address of copy table JMP COPYLP *************** * DU2K Module * *************** DU2K LWPI >8300 LI R14,DU2KDT * address of copy table JMP COPYLP *************** * Common Code * *************** COPYLP BL @GOGO * Set up Char Sets MOV *R14+,R7 * get bank ONEBLK MOV *R14+,R4 * Get bytes divided by 4 JGT CONT * Branch if positive (less than >8000) B *R4 * Else it's the jump address, so start the program CONT MOV *R14+,R9 * Address to copy from MOV *R14+,R10 * Address to copy to BL @COPYME * COPY IT! INCT R7 * Next Bank JMP ONEBLK **************** * Copy Routine * **************** * R4 - Bytes Div 4 * R7 - Bank switch address * R9 - Address to copy from * R10 - Address to copy to * R11 - Return spot COPYME MOV R0,*R7 * Do the bank switch LOOPIT MOV *R9+,*R10+ MOV *R9+,*R10+ DEC R4 JNE LOOPIT B *R11 * We're done. **************************** * Load lower case charsets * **************************** * Note, if you still need space, you can remove support for the * 99/4 by deleting the code marked between * +++ 99/4 support +++ begin/end * blocks GOGO MOV R11,R9 * Save our return spot * +++ 99/4 support begin +++ * load R3 with 6 for 99/4, or 7 for 99/4A 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 * +++ 99/4 support end +++ * If you delete the above block, replace with * LI R3,7 * so that the character size counter is still valid 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 B *R9 * RETURN TO CALLER ***************** * GROM routines * ***************** * 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 * +++ 99/4 support begin +++ CI R3,6 * check for 99/4 JNE LP9 MOVB R0,@>8C00 * extra blank line for 99/4 * +++ 99/4 support end +++ * no changes needed if this block removed 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 Quote Link to comment Share on other sites More sharing options...
brain Posted December 29, 2016 Author Share Posted December 29, 2016 (edited) I read the section in the manual about banking, which I understand (though I still need to trace the circuit to understand how the '378 does not trigger on both of the writes of the 16 bit write sequence) The above gives me the impression that 32kB carts produced in the day copies their contents to main RAM, and then ran from main RAM? That seems odd, but perhaps that was the norm for TI. I suspect I am all wrong on this and need to go reading some more. If I am right, other banked cart designs I have seen for other platforms ran the code straight from ROM, and the application would trigger the bank register when needed. This posed a problem when making banked carts that held more than 1 multi-bank game, as the game would not know about the banking in the mega cart, just it's own banking. The app (game) code would assume bank 0 was the lowest bank, etc. So, to address this, the idea of an "offset" register was created. The main menu of the mega cart would set up the overall bank register such that the first 8kB ROM bank (if the cart was a multi-bank 8kB ROM cart) would be present in the 8KB ROM "window". Then, it would zero out the "offset register". The game would then run. The game only knew about about the offset register, so as it incremented the offset register, the game code thought it was paging through 8kB banks 0,1,2,3 etc. However, it really was paging through banks 34,35,36,37..., as the offset register value was added to the overall bank register to get the full bank value. Jim Edited December 29, 2016 by brain Quote Link to comment Share on other sites More sharing options...
+Ksarul Posted December 29, 2016 Share Posted December 29, 2016 TI cartridges BITD were a mixed bag. About 60 commercial cartridges were 8K ROM images requiring no bank switching. Another 30 or so were 16K ROM images with (mostly) 379-style inverted switching. All of these cartridges ran out of the cartridge space, as did the mixed ROM/GROM cartridges from TI. The five larger bank switched cartridges Acadiel identified also ran from cartridge space. The only cartridges that lived in the memory expansion space were the limited number of sideport cartridges that were produced back then (about half a dozen titles were made to work this way). Note that when using these, they were the memory expansion (in ROM), because they were connected to the side of the console. The software you see in the modern multicarts is something different. It may be a number of the 8K cartridges concatenated into a large multicart file with a header to jump to the right module in the compilation, it might be a mix of larger ROM cartridges or ROM/GROM cartridges that are lobbed into the 32K space to run (because we haven't modified the source code to run any other way), or it might even be a disk program stored on the multicart and executed from the 32K space (where it was originally intended to reside BITD). Sometimes, we have taken the effort to modify the code of the old school cartridges with bank switching to make them run in a space (or fashion) other than originally intended (Rasmus did a great job modifying all of the Atarisoft titles to allow them to run from a single compilation cartridge while remaining in cartridge space), others modified Arcturus to get part of it out of the >4000 DSR space so that it could be used in a regular cartridge (using the lob it into 32K method), and Acadiel already mentioned one other that has been modified to eliminate reliance on CRU switching. A few new cartridges have even been written to take advantage of the larger space of the new bank-switching cartridges, and do a lot of their processing in that space as well. 1 Quote Link to comment Share on other sites More sharing options...
brain Posted December 29, 2016 Author Share Posted December 29, 2016 Your answer suggests a new question: Looking at the ROM list, let's say I pick pitfall, a 32kB cart that has 4 8kB ROMs. Reading the tutorial in the Development Resources, I see he uses the '379 inverted bank selection logic to set a bank. Now, let's say I want to load that game, which is ROM only) into a 512kB image for UberGROM. And, I want to put it at the 8th 8kB bank (>10000). I'll also re-arrange the banks because UberROM is a '378 design, not a '379 design. I cna put it there, but when I set the '378 to the first bank of the Pitfall code, it will start running and then when it tries to set a new bank, it will select bank 2 (let's assume), which means storing a 1 into the '379. But, the '378/'379 on the UberGROM was already set at bank 8 (>10000) and the next bank for pitfall is #9, not #1. I assume, due to this, if someone wants to have pitfall in their UberGROM, they either have to re-assemble it so that it will use banks 8,9,10,11 instead of 0,1,2,3, or lob the disk version of the code, stored into ROM, into ram and run that version. Am I understanding things correctly? And, if so, what does one do if there is a multi-bank ROM-only game/app that has no source code? DOes one hand edit the code to use different banks than original? I don't even see the "lob it into 32kB RAM" as working, because the code expects to run from ROM, all at the same address (>6000->7fff, I assume) and thus all of the absolute jumps will be wrong if it is loaded into the 32kB RAM space. I can't imagine someone hand editting multi-bank ROM code to run from UberGROM or RAM in this manner, so I have to be missing a piece. I apologize in advance for being dense, but I would appreciate any clarity you can provide... Jim Quote Link to comment Share on other sites More sharing options...
Tursi Posted December 29, 2016 Share Posted December 29, 2016 I saw that in a post you made. BUt, it seemed very kludgey to have to do "review" to advance the menu all the time. I assume most folks prefer a single entry for UberGROM and then navigating through a menu. I just created a GROM simulator. How developers use it is up to them, not me. Which brought me to an idea, where there would be 5 GROM slot configs, and a menu could real-time map any GROM into those slots. I do this in my (unreleased) MPD, because it needs to bank a lot and the code can't be relocated. I debated putting that in the released uberGROM, but nobody was asking for it. You can do it with the existing code, but the problem is that every write goes to the EEPROM, and the EEPROM has a limited lifespan. After 100,000 bank switches, your cart will be done unless you implement some form of wear leveling. In the MPD I went further and had the bank switch data and write to RAM instead, and just load from the EEPROM on reset. Either way, code changes would be required. What I meant was a single GPL app that would run from 9800:3, then 9800:4... 9800:7 and then want to start executing in 9804:3, and so on. Should be doable. In your AVR code, do you maintain a separate counter for 9800 set, 9804 set, etc.? Or, do you just run 1 13 bit counter for all GROM bases? It's constrained by how the console GROMs operate - because all GROMs share an address counter I need to do the same as they do. So there is one 13-bit counter for all GROM bases. Quote Link to comment Share on other sites More sharing options...
Tursi Posted December 29, 2016 Share Posted December 29, 2016 I can't imagine someone hand editting multi-bank ROM code to run from UberGROM or RAM in this manner, so I have to be missing a piece. I apologize in advance for being dense, but I would appreciate any clarity you can provide... The thing is, this cartridge was designed for the purpose of creating new software, not creating multicarts. So it doesn't do the things that would make multi-carts easy, like remapping blocks to the same physical address/pages. So yes, anything dropped into the multicarts there has probably been edited, often by hand. As for copying to RAM, only software that was designed to run from RAM in the first place gets that treatment. For instance, we have a lot of disk software that we pack into a cartridge with a little loader - we are just loading from silicon instead of floppy. Quote Link to comment Share on other sites More sharing options...
+Ksarul Posted December 29, 2016 Share Posted December 29, 2016 And one other note: for most of this software we don't have the original source code, so hand editing is often the only viable option. Quote Link to comment Share on other sites More sharing options...
brain Posted December 29, 2016 Author Share Posted December 29, 2016 I just created a GROM simulator. How developers use it is up to them, not me. Hehe. Fair enough. No intent to demean your work. Mainly just wondering how folks use it. I do this in my (unreleased) MPD, because it needs to bank a lot and the code can't be relocated. I debated putting that in the released uberGROM, but nobody was asking for it. You can do it with the existing code, but the problem is that every write goes to the EEPROM, and the EEPROM has a limited lifespan. After 100,000 bank switches, your cart will be done unless you implement some form of wear leveling. In the MPD I went further and had the bank switch data and write to RAM instead, and just load from the EEPROM on reset. Either way, code changes would be required. I doubt they would ask, unless they start finding lots of programs that only run at 9800:>6000 Should be doable. Good to know. It's constrained by how the console GROMs operate - because all GROMs share an address counter I need to do the same as they do. So there is one 13-bit counter for all GROM bases. Well, yes, and no, as I see it. The 3 console groms see all 98xx accesses, so that fall in line with your statement. But, if I put 2 real GROMs on the cart port, one decoded at 9800..9803 and one at 9804..9807, it seems like the 2 groms would not share a counter. (it doesn't look like I can do tables here, so I hope this all makes sense: Assume all GROMs have been configured with address >6000 time 1: read data from 9800 GROMs internal console groms address counter (6002) 9800 cart port address counter (6002) 9804 cart port address counter (6001) (it did not get selected for an access, so no address counter bump, correct?) Which means, if I understand the GROM correctly, putting GROMs at alternate base addresses would have been problematic if someone wanted to read an address, as the internal GROMs see all 98xx accesses, while fully decoded GROMs would only see a fraction of them. An address read of a GROM at 9804 would cause data bus contention, as I think all GROMs respond to a read address command. In the above a read address at 9804 base would bring the 9804 cart GROM online *AND* the 9800 base console GROMs online, but with different values for bits 0 and 1. Of course, it is no worse than a data read at GROM address >0000 to >5fff with an external GROM responding to those addresses, but I wonder if the 16 bases were just a vestige of early development efforts, partially cost reduced out of the console due to the lack of full decoding on the console GROMs, or if TI truly was OK with the design, and simply assume no one would read an address from a GROM. Jim Quote Link to comment Share on other sites More sharing options...
brain Posted December 29, 2016 Author Share Posted December 29, 2016 The thing is, this cartridge was designed for the purpose of creating new software, not creating multicarts. So it doesn't do the things that would make multi-carts easy, like remapping blocks to the same physical address/pages. So yes, anything dropped into the multicarts there has probably been edited, often by hand. I apologize, then, as I didn't fully understand the use case of the UberGROM (I mean, I understood it was an outgrowth of your MPD project, but not that it was primarily for new software development). As for copying to RAM, only software that was designed to run from RAM in the first place gets that treatment. For instance, we have a lot of disk software that we pack into a cartridge with a little loader - we are just loading from silicon instead of floppy. A ROM-disk, as it were :-) Quote Link to comment Share on other sites More sharing options...
brain Posted December 29, 2016 Author Share Posted December 29, 2016 And one other note: for most of this software we don't have the original source code, so hand editing is often the only viable option. The first part I assumed, for having source code would be improbable. It was/is the second part that seemed amazing. In that case, you all should give yourselves kudos. Most other platforms' users are not so flexible :-) Quote Link to comment Share on other sites More sharing options...
+Ksarul Posted December 29, 2016 Share Posted December 29, 2016 (edited) Multiple GROM bases were regularly used by TI internally with their various EGROM and GSIM devices. A TI-99/4A can also end up having more than one GROM base installed (the p-Code card has 8 GROMs). Note that the /4A can actually have up to 256 GROM bases, but only the first 16 are available at the cartridge port. This practice continued with the 99/8, but it reduced the number of available GROM bases at the cartridge port to four (while leaving the maximum number of in-system GROM bases at 256). The main reason you didn't see multiple GROM bases used by TI in delivered product cartridges was power. Put too much in there and you exceed the specs for cartridge port power draw, and at that time, each GROM chip was a discrete, power hungry object. Edited December 29, 2016 by Ksarul Quote Link to comment Share on other sites More sharing options...
brain Posted December 29, 2016 Author Share Posted December 29, 2016 (edited) I think 64 bases are available at the cart port, if my math holds. GROM SELECT is >98XX, and there are 4 addresses per GROM. I thought Tursi noted in another thread that 16 is the limit of the menu reading code. Does the 99/8 more fully decode the console GROMs? Does anything have more GROMs than the p Code card? Did any other cards have more than 5? I found EGROM references at: http://atariage.com/forums/topic/247033-homebrew-goodies-from-the-past-%f0%9f%98/page-2, but could not find anything on GSIM. Links? When you state "internally", are you suggesting that none of the solutions were released? Jim Edited December 29, 2016 by brain Quote Link to comment Share on other sites More sharing options...
+acadiel Posted December 29, 2016 Share Posted December 29, 2016 The first part I assumed, for having source code would be improbable. It was/is the second part that seemed amazing. In that case, you all should give yourselves kudos. Most other platforms' users are not so flexible :-) Yes, that's what Tursi did with TI Workshop. He used Classic99 and the debugger to find all the CRU bank writes, and switched them to write-to-ROM bank instructions. It was all done by hand. If you want to relocate a 32K ROM (let's say - Pitfall, bank switched 74LS379) from its native 32K namespace and put it, say, in the second 32K address space of a 64K EPROM (the bottom, >0000), you will also have to find all the banking instructions in the ROM and 'relocate' them (by hand) to write to the new namespace. To keep it simple, say that you have a 16K cartridge. Write to >6000 bring you to >2000 (the second 8K boundary in the 16K EPROM). Writing to >6002 will bring you to >0000 (the first 8K boundary in the 16K EPROM). Now, move to a 32K cartridge. Write to >6000 brings you to >6000 on the EPROM address space. Write to >6002 brings you to >4000, write to >6004 brings you to >2000, and write to >6006 brings you to >0000 in the EPROM's address space. Non inverted is a lot easier. I inadvertently created headaches for some developers like RetroClouds by implementing the inverted scheme, but it is easy enough to reverse the 8K banks to make non inverted images work on a 379 or make inverted images work on a 378/377. We now have cartridges that can do both. You have to be aware of which scheme the images were built with, but the community has done an excellent job making compilations of them, especially for the FlashROM99 cart. For the Copy to ROM cartridges, just finding the loop that banks to a certain bank before it copies to a certain memory location needs to be edited to move them around. Those are a lot easier, all the stuff is in the very header (i.e. the source I posted). A lot of these are PROGRAM images that really you just B @>A000 once your unroll them to memory expansion, and then they start. 1 Quote Link to comment Share on other sites More sharing options...
+Ksarul Posted December 29, 2016 Share Posted December 29, 2016 On GROM bases and the cartridge port, you have to look at what addresses are scanned or GROM content at power-up, not the theoretical number of available bases. The 99/4A only scans the first 16 bases, so anything beyond that isn't going to show up on power-up. Cartridges from TI with more than 5 GROMs were never produced (even as prototypes). Only one PEB card was ever produced that used GROMs--the p-Code card. The 99/8 also had a lot of GROMs in it--I think it was a total of 16 of them in two GROM bases (I'd have to look inside one of my 99/8s to be sure that it was only 16 of them). The GSIM was a GRAM device from TI that they used to test code before committing it to silicon, somewhat fondly referred to as the silver pizza box. There are less than 20 of them in circulation (I have one that is functional as a GRAM device and one that was modified to make it into a test version of the PLATO cartridge using ROMs). The TI GRAM card from the TI labs at Almelo, Holland (four examples survive) was the next iteration of the GSIM. The design was then further updated to create the Mechatronic GRAM Karte sometime after TI pulled out of the market. Quote Link to comment Share on other sites More sharing options...
+mizapf Posted December 29, 2016 Share Posted December 29, 2016 Total of 22 GROMs - see MAME's emulation of the 99/8. 3 console GROMs (port f830) 8 Text-to-speech GROMs (port f840) 8 Pascal Lib 1 GROMs (port f850) 3 Pascal Lib 2 GROMs (port f860) Ports in Armadillo mode, i.e. TI-99/8 native mode. In compatibility mode, the console GROMs appear at base 9800, while the Pascal GROMs should not be activated (CRU bit) since their port overlaps with the RAM area. 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.