Jump to content
IGNORED

Questions about cartridges


brain

Recommended Posts

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:

 

  1. 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.
  2. 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?
  3. 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?
  4. I understand there are 3 different ways carts banked. normal, inverse, and CRU:
  5. Is there any information on CRU banking?
  6. 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?
  7. 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?
  8. 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.
  9. 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.
  10. 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?
  11. I read this ( Is there more information on GROMs to ingest?
  12. 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

  • Like 2
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

 

 

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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 by Tursi
  • Like 1
Link to comment
Share on other sites

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

 

Link to comment
Share on other sites

 

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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 by brain
Link to comment
Share on other sites

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.

  • Like 1
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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. ;)

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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 :-)

Link to comment
Share on other sites

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 :-)

Link to comment
Share on other sites

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 by Ksarul
Link to comment
Share on other sites

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 by brain
Link to comment
Share on other sites

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.

  • Like 1
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...