Jump to content
matthew180

Assembly on the 99/4A

Recommended Posts

On 1/1/2021 at 1:35 PM, Torrax said:

You can also alter the Screen Image Table layout from 1,2,3 ... 255. To change the indexing of your bytes from 8x8 to 8x16; 8x32 or 8x64. Just make sure the SIT is repeated the same way all three times.

 

0,8,16,24 ... 248

1,9,17,25 ...  249

:

6,14,22,30 ... 254

7,15,23,31 ... 255

 

Repeated 3 times -- 8x64

Admittedly, this being a learning thread I’d have to ask you something clever like, “What?”  

 

I really do wish to understand what you’re suggesting yet it soars above my head.

Share this post


Link to post
Share on other sites
1 hour ago, Airshack said:

So the hardware knows to somehow use the one color table for all three panes?

 

Sounds like a reasonable compromise which allows for retaining the use of ALL Sprite’s I presume. For my understanding can you confirm the characters repeated in all three panes MUST be defined three times and appear in the same position (number) in all three panes?

Yes, if you want the same 256 patterns across the screen you must set up three identical patterns tables. But nothing will stop you from defining at least some of the patterns differently, which I did in Flying Shark for the patterns in the left side panel. The colors *will* be the same, however, so it can be a bit tricky. You enter this mode by setting VR0 = >02,  VR3 = >9F and  VR4 = >03.

  • Like 4

Share this post


Link to post
Share on other sites
10 hours ago, Jeff White said:

You can reduce the pattern table to 2 kilobytes, color table to 64 bytes, use 8 screen image tables for scrolling the screen, and have room for sprites, file buffers, etc.

The problem with reducing the color table to less than 2K is that the masking of the colors will also affect the patterns, as Nouspikel explains:

  • At the extreme, VR3 = >00 results in >40-byte tables. As there are 8 bytes per characters, this means characters are arranged in 8 groups of 32 identical characters: chars 0-7 are identical to chars 8-15, 16-23, etc.

http://www.unige.ch/medecine/nouspikel/ti99/tms9918a.htm#hybrid bitmap

  • Like 2

Share this post


Link to post
Share on other sites
2 hours ago, Asmusr said:

The problem with reducing the color table to less than 2K is that the masking of the colors will also affect the patterns, as Nouspikel explains:

  • At the extreme, VR3 = >00 results in >40-byte tables. As there are 8 bytes per characters, this means characters are arranged in 8 groups of 32 identical characters: chars 0-7 are identical to chars 8-15, 16-23, etc.

http://www.unige.ch/medecine/nouspikel/ti99/tms9918a.htm#hybrid bitmap

 

For my application, I needed to have 768 dynamically generated unique tiles on the screen, but only a foreground and a background color.

 

Thierry's explanation is somewhat confusing unless you know what it means.  VR3 = >00 puts a truncated 64-byte (>40-byte) color table at >0000.  VR3 = >80 puts a truncated 64-byte color table at >8000.

 

Because there are only 64 bytes of color information, tiles 0, 8, 16, 24, ... 248 (32 tiles, aka 32 patterns or 32 characters) get their same color information from bytes 0 through 7 of the color table.

 

Tiles 1, 9, 17, 25, ... 249 get their same color information from bytes 8 through 15 of the color table.

 

The eighth group of 32 tiles 7, 15, 23, 31, ... 255 get their same color information from bytes 56 through 63 of the color table.

 

Note that if the pattern definition table is the full 6K, it is 3 sets of 256 tiles that get color information from the truncated 64-byte color table.

 

VR3 = >9F puts a truncated 2048-byte color table at >8000.  Because there are only 2048 bytes of color information, tile 0 from each of the 3 sets of 256 tiles gets color information from bytes 0 through 7 of the color table.  Tile 1 from each of the 3 sets of 256 tiles gets color information from bytes 8 through 15 of the color table... Tile 255 from each of the 3 sets of 256 tiles gets color information from bytes 2040 through 2047 of the color table.

  • Like 1
  • Confused 1

Share this post


Link to post
Share on other sites
9 hours ago, Airshack said:

For my understanding can you confirm the characters repeated in all three panes MUST be defined three times and appear in the same position (number) in all three panes?

 

It might be better to think of the pattern table as 8x8 blocks of pattern “identifiers” rather than as “characters”. It is the number of the identifier (0 – 255) that is important. The important idea is that each third must have 256 unique numbers (identifiers).

 

...lee

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
38 minutes ago, Jeff White said:

 

For my application, I needed to have 768 dynamically generated unique tiles on the screen, but only a foreground and a background color.

 

Thierry's explanation is somewhat confusing unless you know what it means.  VR3 = >00 puts a truncated 64-byte (>40-byte) color table at >0000.  VR3 = >80 puts a truncated 64-byte color table at >8000.

 

Because there are only 64 bytes of color information, tiles 0, 8, 16, 24, ... 248 (32 tiles, aka 32 patterns or 32 characters) get their same color information from bytes 0 through 7 of the color table.

 

Tiles 1, 9, 17, 25, ... 249 get their same color information from bytes 8 through 15 of the color table.

 

The eighth group of 32 tiles 7, 15, 23, 31, ... 255 get their same color information from bytes 56 through 63 of the color table.

 

Note that if the pattern definition table is the full 6K, it is 3 sets of 256 tiles that get color information from the truncated 64-byte color table.

 

VR3 = >9F puts a truncated 2048-byte color table at >8000.  Because there are only 2048 bytes of color information, tile 0 from each of the 3 sets of 256 tiles gets color information from bytes 0 through 7 of the color table.  Tile 1 from each of the 3 sets of 256 tiles gets color information from bytes 8 through 15 of the color table... Tile 255 from each of the 3 sets of 256 tiles gets color information from bytes 2040 through 2047 of the color table.

What you write about the colors is correct. But the problem is that the pattern mask is dependent of the color mask except for the first two bits. If the color mask is 00XCCCCCCC111111 where 7 Cs are taken from VR3, the pattern mask becomes 00XPPCCCCC111111 where only the 2 Ps and taken from VR4 and the 5 Cs are the least significant bits of VR3. It means that if you reduce the number of colors below 256 you also reduce the number of unique patterns. As you describe your 64-column terminal emulator you used a 2K color table, which is fine, but if you go below that you cannot use a full character set.

Edited by Asmusr
  • Like 3

Share this post


Link to post
Share on other sites

What would you expect the value of R1 to be after running this code?

LWPI >8300
STWP R0
MOV *R0+,R1

I would have expected >8300, but according to a bug report for js99er the correct value is >8302. 

Share this post


Link to post
Share on other sites
1 hour ago, Willsy said:

>8300

My tests show that the answer on hardware (and MAME) is >8302. Classic99 says >8300. And JS99er also says >8300 because the CPU emulation is ported from Classic99. @Tursi

 

I have attached the test code from the user, which is using different values. The relevant output is the second line where R4=A082 on hardware and A080 in Classic99/JS99er. 

TEST.dsk test8.bin

 

Edit: The output on line 5 is about overflowing workspace by dividing R15. In that case Classic99 appears to be right and MAME is wrong (at least the old version I'm using). It should read DIV=0000 and not DIV=0100.

Edited by Asmusr
  • Like 2

Share this post


Link to post
Share on other sites
2 hours ago, Asmusr said:

What would you expect the value of R1 to be after running this code?

LWPI >8300
STWP R0
MOV *R0+,R1

I would have expected >8300, but according to a bug report for js99er the correct value is >8302. 

 

I guess this means that the microcode for MOV *R0+,R1, with >8300 in R0 does this:

  1. Retrieves the contents of R0, which is the address from which to retrieve the data to store in the destination address.
  2. Increments R0, which now contains >8302
  3. Reads the contents of the retrieved address (>8300), which just happens to be the address of R0, which has already been incremented to >8302!
  4. Copies >8302 to R1.

This would seem an undesirable side effect of the microcode—even, dare I say, a TMS9900 bug.

 

...lee

  • Like 3
  • Sad 1

Share this post


Link to post
Share on other sites
1 hour ago, Asmusr said:

My tests show that the answer on hardware (and MAME) is >8302. Classic99 says >8300. And JS99er also says >8300 because the CPU emulation is ported from Classic99. @Tursi

 

I have attached the test code from the user, which is using different values. The relevant output is the second line where R4=A082 on hardware and A080 in Classic99/JS99er. 

TEST.dsk 180 kB · 3 downloads test8.bin 16 kB · 1 download

 

Edit: The output on line 5 is about overflowing workspace by dividing R15. In that case Classic99 appears to be right and MAME is wrong (at least the old version I'm using). It should read DIV=0000 and not DIV=0100.

Interesting.. thanks for the tag. Lee's theory makes some sense... Classic99's post-increment handling happens after the source data is fully fetched, it would appear I need to nudge it a little earlier.

 

I also would not have expected that result. I need to set up my TI so I can play with these things. ;)

 

Share this post


Link to post
Share on other sites

This is the microcode that I implemented in MAME:

 

REG_READ, ALU_SETADDR_ADDONE, ALU_ADDONE, REG_WRITE, MEMORY_READ, RET

 

for the data derivation sequence for *Rx+, according to the description in chapter 4 of "9900 Family Systems Design" (see attached copy). This is not a bug, but it may be a surprising effect indeed.

 

RegAutoIncrement.png

Share this post


Link to post
Share on other sites
3 hours ago, Asmusr said:

Edit: The output on line 5 is about overflowing workspace by dividing R15. In that case Classic99 appears to be right and MAME is wrong (at least the old version I'm using). It should read DIV=0000 and not DIV=0100.

From what I saw in the source code, the operation is a division of R15 by R14. The problem is that the dividend consists of the two words starting at the specified address, which means R15 and the subsequent word (R16, which does not exist). So R15 is at >A09E and contains >0000, the subsequent word at >A0A0 is >1000, and R14 is >0010.

 

I'd read this as a division >00001000 / >0010, and this should be >0100, remainder >0000.

 

So why this is wrong?

Share this post


Link to post
Share on other sites

Well, the increment either happens on the final address, or on the workspace register. If the former, your assertion would be correct. If the latter, it would wrap around to 0. Should be easy enough to generate a test on hardware to see which it is... load known values into R0 and after R15, and see which division happens. :)

 

Not sure why Classic99 would be right in this case, though... it appears to do the same thing as MAME...

 

I'll dig out my TI if nobody beats me to it ;)

 

Share this post


Link to post
Share on other sites

Confirm no wrap on Classic99 and on real hardware - it just advances past the workspace into the next address. It seems to me that the E/A manual even mentions this...

 

I used this test code, and examined memory directly in the Classic99 debugger and with EasyBug on real hardware (that's why it returns ;) ).

 

* Division test - what happens at the end of the register space?
* We can probably extrapolate the same for MPY...

  LWPI >8300
  LI R14,>0010    * divisor - >0010
  LI R15,>1001
  MOV R15,@>8320
  CLR R15         * dividend - >00001001 if it doesn't wrap (result: 0100, remainder 1)
  LI R0,>0012     * dividend - >00000012 if it does wrap (result: 0001, remainder 2)
  
  DIV R14,R15
  
  LWPI >83E0
  B *R11
  END
  
* Classic99, MAME, JS99er and hardware return >0100 in R15 and >0001 at >8320, suggesting no wrap

 

They all seem to be doing the right thing - did I test the wrong thing?

 

 

 

  • Like 1

Share this post


Link to post
Share on other sites

The Editor/Assembler manual states on page 89:

 

If the destination operand is specified as Workspace Register 15, the first word of the destination operand is Workspace register 15 and the second word of the destination operand is the word in memory immediately following the workspace area.

 

 

  • Like 4

Share this post


Link to post
Share on other sites

What if you did the following?

 

LWPI >8300

STWP R0

MOV  *R0+,*R0+

 

Will the 9900 (99/4A) with its destination prefetch give a different result than the 9995 (in the 99/8, 99/2, Tutor, and Geneve)?

 

I believe so.  What are the values in R0, R1, and R2 after the MOV?

 

Share this post


Link to post
Share on other sites
44 minutes ago, Tursi said:

They all seem to be doing the right thing - did I test the wrong thing?

 

1 hour ago, mizapf said:

So why this is wrong?

 

Sorry, it looks like only the cartridge image, which is what I used on my real hardware (and in Classic99/JS99er), is returning DIV=0000, so there must be something wrong with it.

IMG_0726.JPG

 

Edited by Asmusr
  • Like 1

Share this post


Link to post
Share on other sites
9 hours ago, GDMike said:

A video explaining what is going on would be cool.

Several topics have been discussed today, but this is a video of the sprite duplication in half bitmap mode with 2K patterns and color tables. The top 3rd contains sprites 1-4 (not duplicated) and sprites 17-20 (duplicated). The Sprite I move around is number 8. If it's located in the 1st part, it is duplicated to the 2nd and the 3rd parts. If it's located in the 2nd part it is not duplicated. If it's located in the 3rd part it is hidden. 

 

 

This is how it looks in JS99er:

 

Edited by Asmusr
  • Like 2

Share this post


Link to post
Share on other sites

And this is how it looks when the sprite duplication issue is not emulated:

 

 

I'm just warning new developers: the half-bitmap mode may be tempting to use but your plans may be shattered when you discover you can only use sprites 0-7. 

Edited by Asmusr
  • Like 6

Share this post


Link to post
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...