Jump to content
IGNORED

Console power-up/reset code: set VDP RAM size code question


jbourke

Recommended Posts

Hi all,

 

I am looking at the following GPL code snippet in GROM 0 as part of power-up/reset (re-produced from TI-intern):

 

00B5 : CLR VDP@>0000 Check VDP RAM
00B8 : ST @>8370,>10
00BB : ST VDP*>8370,>A0
00BF : CZ VDP@>0000
00C2 : BR GROM@>00D9
00C4 : MOVE >0001 TO REG>01 FROM GROM@>044C
00CA : CLR VDP*>8370
00CD : ADD @>8370,@>8370 4, 8 or 16K?
00D0 : CEQ @>8370,>40
00D3 : BR GROM@>00BB
00D5 : ST @>83FD,>08 System flags (16k flag)
00D9 : DDEC @>8370 Pointer end VDP RAM
00DB : MOVE >0001 TO REG>01 FROM GROM@>0241
00E1 : CLR VDP@>0000

 

It's meant to check and set the amount of VDP RAM. But shouldn't the check at >00BF be "CZ VDP@*>8370" to see if the value written initially (>A0) is read back and thus RAM is present? The loop just seems to run until >8370 contains >4000 (16K RAM) while needlessly checking VDP RAM >0000.

 

Also I don't get the statement at >00DB which seems to write a value to VDP REG1 from a rather random GROM address, compared to the code at >00C4 which does it properly.

 

I am probably missing a thing or 2 :-)

 

Thanks!

 

John

Link to comment
Share on other sites

GROM >0241 is >00 so this sets Bits 0 to 7 in VDP Register to 4K VDP RAM, Screen Transparent, no VDP Interrupts, not in TEXT Mode, not in Multicolor Mode, unused bit, normal sized sprites and bit 7 unmagnified sprites.

 

GROM >044C is >80 so this sets bits 0 to 7 in VDP Register to 16K RAM, Screen Visible, no VDP Interrupts, not in TEXT Mode, not in Multicolor Mode, unused bit, normal sized sprites and bit 7 unmagnified sprites.

 

Originally >8370 is set to >10 as ST >10,@>8370 would be >8370 is >10 and >8371 is unknown.

Check VDP RAM
00B5 : CLR   VDP@>0000            Clear the first byte
00B8 : ST    >10,@>8370           Set to >10 or binary >1000
00BB : ST    >A0,V*>8370          Set byte at VDP ADDRESS in >8370 to >A0
00BF : CZ    V@>0000              Compare if VDP ADDRESS is zero at VDP >0000
00C2 : BR    GROM@>00D9           This is basically never set unless VDP RAM VDP ADDRESS  >0000 is not zero
00C4 : MOVE  1,G@>044C,#1         Put 1 byte at >044C (>80) into VDP Register number 1 
00CA : CLR   V*>8370              Set to zero the byte at VDP address in >8370        
00CD : ADD   @>8370,@>8370        Doubles the value in >8370 by >10+>10=>20+>20=>40 (Thus values are >10, >20, >40)
00D0 : CEQ   >40,@>8370           Does >8370 equal >40?
00D3 : BR    GROM@>00BB           No, so go back to >00BB
00D5 : ST    >08,@>83FD           System flags (16k flag) Also >8370 should contain >40 too. BINARY >83FD= 1000 and >8370= 1000
00D9 : DDEC  @>8370               Minus 1 from >8370 and >8371 (Unknown what is in >8371)
00DB : MOVE  1,G@>0241,#1         Put 1 byte at >0241 (>00) into VDP Register number 1 
00E1 : CLR   V@>0000              Set to zero at VDP ADDRESS >0000
00E4 : MOVE  >0FFF,V@0,V@1        Moves byte at VDP ADDRESS >0000 to VDP ADDRESS >0001 and does this until it reaches VDP ADRESS >0FFF (This zeros out all VDP tables in VDP)    

As for >00BF looks at VDP >0000 to be zero and if not jumps out. I think >00BF is used by another routine in GROM 0 somewhere and would better explain the logic.

And >00DB is explained above.

Edited by RXB
Link to comment
Share on other sites

I went through this confusing piece of code a few times when I was working on the 4k mode emulation. As far as I could suss out, it's basically trying to catch the memory wrapround point. >8370 is a /CPU/ memory location here, it's not a valid VDP address, and in the end it's the address that contains the top of VRAM pointer.

 

The TI ROMs use a lot of seemingly random memory offsets to copy data around, they happily pull needed bytes from the middle of tables or instructions at will. ;)

Link to comment
Share on other sites

GROM >0241 is >00 so this sets Bits 0 to 7 in VDP Register to 4K VDP RAM, Screen Transparent, no VDP Interrupts, not in TEXT Mode, not in Multicolor Mode, unused bit, normal sized sprites and bit 7 unmagnified sprites.

 

GROM >044C is >80 so this sets bits 0 to 7 in VDP Register to 16K RAM, Screen Visible, no VDP Interrupts, not in TEXT Mode, not in Multicolor Mode, unused bit, normal sized sprites and bit 7 unmagnified sprites.

 

Originally >8370 is set to >10 as ST >10,@>8370 would be >8370 is >10 and >8371 is unknown.

Check VDP RAM
00B5 : CLR   VDP@>0000            Clear the first byte
00B8 : ST    >10,@>8370           Set to >10 or binary >1000
00BB : ST    >A0,V*>8370          Set byte at VDP ADDRESS in >8370 to >A0
00BF : CZ    V@>0000              Compare if VDP ADDRESS is zero at VDP >0000
00C2 : BR    GROM@>00D9           This is basically never set unless VDP RAM VDP ADDRESS  >0000 is not zero
00C4 : MOVE  1,G@>044C,#1         Put 1 byte at >044C (>80) into VDP Register number 1 
00CA : CLR   V*>8370              Set to zero the byte at VDP address in >8370        
00CD : ADD   @>8370,@>8370        Doubles the value in >8370 by >10+>10=>20+>20=>40 (Thus values are >10, >20, >40)
00D0 : CEQ   >40,@>8370           Does >8370 equal >40?
00D3 : BR    GROM@>00BB           No, so go back to >00BB
00D5 : ST    >08,@>83FD           System flags (16k flag) Also >8370 should contain >40 too. BINARY >83FD= 1000 and >8370= 1000
00D9 : DDEC  @>8370               Minus 1 from >8370 and >8371 (Unknown what is in >8371)
00DB : MOVE  1,G@>0241,#1         Put 1 byte at >0241 (>00) into VDP Register number 1 
00E1 : CLR   V@>0000              Set to zero at VDP ADDRESS >0000
00E4 : MOVE  >0FFF,V@0,V@1        Moves byte at VDP ADDRESS >0000 to VDP ADDRESS >0001 and does this until it reaches VDP ADRESS >0FFF (This zeros out all VDP tables in VDP)    

As for >00BF looks at VDP >0000 to be zero and if not jumps out. I think >00BF is used by another routine in GROM 0 somewhere and would better explain the logic.

And >00DB is explained above.

 

>8371 would not be unknown but set to >00 as previous code in the power-up/reset code clears most of scratch pad. >8370 and >8371 contain the VDP address for read/write in GPL so you can see the code above neatly checks for >1000, >2000 and >4000 for top of VDP RAM. In any other cases I have seen/used myself it's a matter of writing a bit pattern, reading it back and comparing to see RAM is present. My conclusion so far is that this code works by accident :-)

Link to comment
Share on other sites

I went through this confusing piece of code a few times when I was working on the 4k mode emulation. As far as I could suss out, it's basically trying to catch the memory wrapround point. >8370 is a /CPU/ memory location here, it's not a valid VDP address, and in the end it's the address that contains the top of VRAM pointer.

 

The TI ROMs use a lot of seemingly random memory offsets to copy data around, they happily pull needed bytes from the middle of tables or instructions at will. ;)

See my reply to RBX for the use of >8370 and >8371 within the GPL interpreter. And yes you are so right, 1 time it's all nice and tabled and indexed and the next it just picks a random location that happens to have the right value :-)

Link to comment
Share on other sites

See my reply to RBX for the use of >8370 and >8371 within the GPL interpreter. And yes you are so right, 1 time it's all nice and tabled and indexed and the next it just picks a random location that happens to have the right value :-)

What random stuff?

 

I did not see anything in the GPL Code random in any way?

 

The GPL code has the >8370 WORD only DDEC @>8370 once it never loops and I could not find any code below to loop.

 

The start of the code is 00B5 CLR V@>0000 so 00C2 BR G@00D9 is never executed as CZ V@>0000 is always going to be zero do to 00B5 CLR V@>0000 and this only loops 3 times like I showed above.

 

I have no idea what you are talking about on saying it works by accident?

 

The only Word commands are DDEC and MOVE so where are you getting word commands from in that code?

 

(The only accident I see is it stores >A0 at >1000, >2000, and >4000 impossible as there is no >4000 but 00CA CLR V*>8370 each pass clears it anyway.)

 

Anyway I still do not see what you guys see. Are you sure you are not thinking word commands where it is byte only commands?

Edited by RXB
Link to comment
Share on other sites

Tursi: The TI ROMs use a lot of seemingly random memory offsets to copy data around, they happily pull needed bytes from the middle of tables or instructions at will.

RXB: What random stuff? I did not see anything in the GPL Code random in any way?

 

Here's what Tursi is getting at:

00C4 : MOVE >0001 TO REG>01 FROM GROM@>044C

(Grom at >044C is the start of a table labeled in INTERN "VDP Register Data". This is tidy and easy to follow)

00DB : MOVE >0001 TO REG>01 FROM GROM@>0241

(Grom at >0240 is MOV >0001 to REG >01 from GROM >044E. It's not obvious what value is at Grom >0241)

 

So it is not actually random, but it sure is mystifying when you try to make sense of it.

 

  • Like 2
Link to comment
Share on other sites

... The TI ROMs use a lot of seemingly random memory offsets to copy data around, they happily pull needed bytes from the middle of tables or instructions at will. ;)

 

 

See my reply to RBX for the use of >8370 and >8371 within the GPL interpreter. And yes you are so right, 1 time it's all nice and tabled and indexed and the next it just picks a random location that happens to have the right value :-)

 

 

... So it is not actually random, but it sure is mystifying when you try to make sense of it.

 

I am sure TI often did this to intentionally obfuscate the code; but, they were also looking to squeeze every byte of memory they could and grabbing fortuitously-valued bytes that were not expected to change was one way they did it. Debugging sessions were surely a lot of fun! :-o

 

...lee

  • Like 1
Link to comment
Share on other sites

I am sure TI often did this to intentionally obfuscate the code; but, they were also looking to squeeze every byte of memory they could and grabbing fortuitously-valued bytes that were not expected to change was one way they did it. Debugging sessions were surely a lot of fun! :-o

 

Some really evil stuff that I found in the GROM also makes me think that people from TI either tried hard to save space, or they had really bad manners when writing programs.

 

In particular, I found some subprograms that are usually called by CALL in GPL and return to the caller by RTN, as designed. But when they planned to call that subroutine and return right after it, they did a BR into that subprogram, which causes the RTN to return one level higher ... which is actually a bad idea, because it just saves a single byte (another RTN after the subprogram call).

Link to comment
Share on other sites

Here is my take on the snippet of GPL code under discussion:

Check VDP RAM—

00B5 : CLR   VDP@>0000        Clear the first byte.
00B8 : ST    >10,@>8370       Set to >10. @>8371 is already 0, so @>8370 now points to VRAM@>1000.
00BB : ST    >A0,V*>8370      Set byte at VRAM@(@>8370) to >A0. 
                              ...1st time through, possibilities are
                              ......(1) If VRAM is 4KiB, VRAM@>1000 wraps around to VRAM@0 = >A0.
                              ......(2) If VRAM is 16KiB, @>1000 is a legitimate address, so 
                              .........VRAM@>1000 = >A0 and
                              .........VRAM@0 = 0.
                              ...2nd time through, we know VRAM is 16KiB—so
                              ......VRAM@>2000 = >A0 and
                              ......VRAM@0 = 0.
                              ...There won't be a 3rd time!
00BF :    CZ    V@>0000          VRAM@0 = 0?, i.e., VRAM = 16KiB?, i.e., no wrap-around?
00C2 :    BR    GROM@>00D9       If not 16KiB, i.e., VRAM@0 = >A0, must be 4KiB, so exit loop.
00C4 :    MOVE  1,G@>044C,#1     Copy byte at GROM@>044C = >80 to VR01:
                                 ...16KiB VRAM,
                                 ...blank screen,
                                 ...disable VDP interrupt,
                                 ...not text mode,
                                 ...not multicolor mode,
                                 ...standard-sized sprites,
                                 ...unmagnified sprites.
00CA :    CLR   V*>8370          Zero byte at VRAM@(@>8370):
                                 ...1st time, VRAM@>1000 = 0.
                                 ...2nd time, VRAM@>2000 = 0.
00CD :    ADD   @>8370,@>8370    Doubles @>8370:
                                 ...1st time, = >20, which now references VRAM@>2000.
                                 ...2nd time, = >40, which now references VRAM@>4000.
00D0 :    CEQ   >40,@>8370       Does >8370 equal >40?
00D3 :    BR    GROM@>00BB       No (1st time), so go back to @>00BB.
                                 ...Yes (2nd time), so on to next instruction.
00D5 : ST    >08,@>83FD       Set 16KiB flag in system flags (LSB of GPL R14). 
                              ...Also, @>8370 = >40 from 2nd execution of @>00CD above.
00D9 : DDEC  @>8370           Set highest available VRAM by subtracting 1 from (word) @>8370:
                              ...So, now, @>8370 = >0FFF (4KiB) or >3FFF (16KiB).
00DB : MOVE  1,G@>0241,#1     Copy byte at GROM@>0241 = 0) into VR01:
                              ...Same as @>00C4 above, except set to 4KiB VRAM.
00E1 : CLR   V@>0000          Set VRAM@0 = 0.
00E4 : MOVE  >0FFF,V@0,V@1    Copies VRAM[0000] to VRAM[0001] – VRAM[>0FFF], i.e., zeroes lower 4KiB of VRAM.

The only line I am not clear on is @>00DB. It unconditionally sets VR01 to 4Kib VRAM. Without tracking down how it gets reset to 16KiB (if that is in fact the case), I am guessing that the system flag set in @00D5 will eventually get it done by causing the setting of @>83D4 to >80 or something similar—but, that's just a WAG! :P

 

...lee

Edited by Lee Stewart
Link to comment
Share on other sites

I think if you replace "CZ V@>0000" at >BF with "CZ V*>8370" the routine seems to work as intended: establish 4K, 8K or the max of 16K VDP RAM. Speculation: the >0000 could have been a typo and since all consoles were 16K anyway (no 4K and/or 8K models planned as far as I know?) testing didn't pick this up.

Link to comment
Share on other sites

Here is my take on the snippet of GPL code under discussion:

Check VDP RAM—

00B5 : CLR   VDP@>0000        Clear the first byte.
00B8 : ST    >10,@>8370       Set to >10. @>8371 is already 0, so @>8370 now points to VRAM@>1000.
00BB : ST    >A0,V*>8370      Set byte at VRAM@(@>8370) to >A0. 
                              ...1st time through, possibilities are
                              ......(1) If VRAM is 4KiB, VRAM@>1000 wraps around to VRAM@0 = >A0.
                              ......(2) If VRAM is 16KiB, @>1000 is a legitimate address, so 
                              .........VRAM@>1000 = >A0 and
                              .........VRAM@0 = 0.
                              ...2nd time through, we know VRAM is 16KiB—so
                              ......VRAM@>2000 = >A0 and
                              ......VRAM@0 = 0.
                              ...There won't be a 3rd time!
00BF :    CZ    V@>0000          VRAM@0 = 0?, i.e., VRAM = 16KiB?, i.e., no wrap-around?
00C2 :    BR    GROM@>00D9       If not 16KiB, i.e., VRAM@0 = >A0, must be 4KiB, so exit loop.
00C4 :    MOVE  1,G@>044C,#1     Copy byte at GROM@>044C = >80 to VR01:
                                 ...16KiB VRAM,
                                 ...blank screen,
                                 ...disable VDP interrupt,
                                 ...not text mode,
                                 ...not multicolor mode,
                                 ...standard-sized sprites,
                                 ...unmagnified sprites.
00CA :    CLR   V*>8370          Zero byte at VRAM@(@>8370):
                                 ...1st time, VRAM@>1000 = 0.
                                 ...2nd time, VRAM@>2000 = 0.
00CD :    ADD   @>8370,@>8370    Doubles @>8370:
                                 ...1st time, = >20, which now references VRAM@>2000.
                                 ...2nd time, = >40, which now references VRAM@>4000.
00D0 :    CEQ   >40,@>8370       Does >8370 equal >40?
00D3 :    BR    GROM@>00BB       No (1st time), so go back to @>00BB.
                                 ...Yes (2nd time), so on to next instruction.
00D5 : ST    >08,@>83FD       Set 16KiB flag in system flags (LSB of GPL R14). 
                              ...Also, @>8370 = >40 from 2nd execution of @>00CD above.
00D9 : DDEC  @>8370           Set highest available VRAM by subtracting 1 from (word) @>8370:
                              ...So, now, @>8370 = >0FFF (4KiB) or >3FFF (16KiB).
00DB : MOVE  1,G@>0241,#1     Copy byte at GROM@>0241 = 0) into VR01:
                              ...Same as @>00C4 above, except set to 4KiB VRAM.
00E1 : CLR   V@>0000          Set VRAM@0 = 0.
00E4 : MOVE  >0FFF,V@0,V@1    Copies VRAM[0000] to VRAM[0001] – VRAM[>0FFF], i.e., zeroes lower 4KiB of VRAM.

The only line I am not clear on is @>00DB. It unconditionally sets VR01 to 4Kib VRAM. Without tracking down how it gets reset to 16KiB (if that is in fact the case), I am guessing that the system flag set in @00D5 will eventually get it done by causing the setting of @>83D4 to >80 or something similar—but, that's just a WAG! :P

 

...lee

Lee you pretty much did what I did. And yes I would say the GROM 0 is designed to save as much space as possible.

 

Mizapf yes they have many different cubicles at TI when they wrote code.

 

You can really see this if you read the RXB Source Code as i kept all the comments that TI put in there for XB Source.

I only added my own code and always marked my code in RXB GPL Source with * RXB PATCH CODE * in the source.

Link to comment
Share on other sites

I think if you replace "CZ V@>0000" at >BF with "CZ V*>8370" the routine seems to work as intended: establish 4K, 8K or the max of 16K VDP RAM. Speculation: the >0000 could have been a typo and since all consoles were 16K anyway (no 4K and/or 8K models planned as far as I know?) testing didn't pick this up.

 

The code works as intended the way it is—and I am sure it was no accident. There are only two options possible for the TMS9918A, 4KiB and 16KiB. That's what bit 0 of VR01 is for. The idea of this code is to detect the wrap-around for a 4KiB VRAM console when >A0 is written to @>1000 the first time through the loop. When >A0 shows up at @>0000 instead of @>1000, it is because addressing @>1000 is the same as addressing @>0000 in only 4KiB of VRAM, i.e., address bits ≥ >4000 are ignored. TI programmers relied on this wrap-around in more places than this bit of GPL code. It did save bytes, but sure can be confusing if not well documented.

 

...lee

  • Like 1
Link to comment
Share on other sites

 

The code works as intended the way it is—and I am sure it was no accident. There are only two options possible for the TMS9918A, 4KiB and 16KiB. That's what bit 0 of VR01 is for. The idea of this code is to detect the wrap-around for a 4KiB VRAM console when >A0 is written to @>1000 the first time through the loop. When >A0 shows up at @>0000 instead of @>1000, it is because addressing @>1000 is the same as addressing @>0000 in only 4KiB of VRAM, i.e., address bits ≥ >4000 are ignored. TI programmers relied on this wrap-around in more places than this bit of GPL code. It did save bytes, but sure can be confusing if not well documented.

 

...lee

Thanks Lee and others for the clarification, much appreciated. I do think though that if only checking for 2 possible RAM sizes the loop seems unnecessary and the code could be shorter still. But then as RBX indicated it might be called from other GPL locations for slightly different purposes.

Link to comment
Share on other sites

Yes, it could be shorter. I've tested the console with emulated 4k RAM and everything works and sets up correctly.

 

Just to clarify one thing:

 

 

 

>8370 and >8371 contain the VDP address for read/write in GPL

 

>8370 and >8371 make a pointer to the top of free VRAM, and it is very important in the operation of the system. At the time of this loop they may simply be used as read/write addresses, but after this loop completes this pointer needs to remain unmolested. If this pointer is corrupted the disk system will cease to function. (The way that the disk system uses this pointer to find its buffers also means that nothing else could use them to reserve VDP memory, unless they initialized before the disk system or set up a similar structure.)

 

The routine isn't called from anywhere else as far as I can determine. (Again, after startup it would be destructive to change that pointer). But if you're looking for efficient or even good code in the TI ROMs and GROMs, you're looking in the wrong place. There's some, but as RXB says, "there were lots of cubicles", and it shows. ;)

  • Like 2
Link to comment
Share on other sites

I find it a little odd that, after all these years, the names of the people that had a real hand in the design of the /4 and the /4A are largely unknown. We know some of the names, Don Bynum et al (see The Orphan Chronicles) but the engineers that put the ROMs/GROMs together seem to be unknown to us. A shame. I'm sure they'd have some really interesting stories to tell.

Link to comment
Share on other sites

Some of the names show up in the margins of the schematics, some more show up in the various specifications documents, but not all of them show up. Mike Bunyard developed the Hombre chip used in the final versions of the /4A and also the four specialized chips used in the 99/8. I may have to go through all of the old documentation I have to compile a list of the names that were involved in the system development--it won't be complete by any means, but it will probably be a lot more than is obvious today.

  • Like 2
Link to comment
Share on other sites

Well Don Blazer owned a 990 Mini Frame he had in his basement and it would run TI BASIC and it looked to be in GPL.

 

I think the PROM's in the 990 lead the way to GROM's in Cartridge format for the TI99.

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