Jump to content
IGNORED

Rotating map demo


Asmusr

Recommended Posts

Very nice. :)

 

Thinking of game aspects... I wonder if you could adapt it slightly for a "mode7"-like projection and get a pseudo 3D road map up there. I haven't /done/ it, so I'm not quite sure, but just changing the scale each line seems like it'd work... and you only have to draw half the screen in that case. ;)

Link to comment
Share on other sites

Great demo!

 

Is plain scrolling faster then zooming or rotating i.e., could you go faster than 20 fps when scrolling? And if you used high color mode, would the result be 5 fps, or actually faster?

 

Plain scrolling of the name table could easily be done at 60 FPS. I have had an idea of doing a very fast character scrolling game for a while.

 

Multicolor mode is 1536 bytes (as opposed to the 768 bytes of the name table) and requires 2 pixels to be packed into one byte, so it would be slower. See:

http://atariage.com/forums/topic/228454-multicolor-mode-the-mode-nobody-wanted

Link to comment
Share on other sites

Very nice. :)

 

Thinking of game aspects... I wonder if you could adapt it slightly for a "mode7"-like projection and get a pseudo 3D road map up there. I haven't /done/ it, so I'm not quite sure, but just changing the scale each line seems like it'd work... and you only have to draw half the screen in that case. ;)

 

I never heard of mode 7 before, so I had to look it up. :) Yes that might be possible. The cost of re-scaling each row should be more than compensated for by not updating the entire screen.

Link to comment
Share on other sites

I have attached the source code.

 

This is the central loop that draws the screen:

       LI   R15,24                     ; Row counter
FRAME1 LI   R14,32                     ; Column counter
       MOV  R12,@X                     ; Save X
       MOV  R13,@Y                     ; Save Y
*      Upload byte
FRAME2 MOV  R13,R1                     ; Y
       MOVB R12,@R1LB                  ; YX
       ANDI R1,>3FFF                   ; Wrap Y to 64
       MOVB @MAP(R1),*R0               ; Send to VDP (R0 is VDPWD)
*      Next position
       A    R3,R12                     ; X += cos(a) * scale
       A    R2,R13                     ; Y += sin(a) * scale
*      Column loop
       DEC  R14                        ; Column counter
       JNE  FRAME2
*      Row loop
       MOV  @X,R12                     ; Restore X
       MOV  @Y,R13                     ; Restore Y
       S    R2,R12                     ; X -= sin(a) * scale
       A    R3,R13                     ; Y += cos(a) * scale
       DEC  R15                        ; Row counter
       JNE  FRAME1
       B    *R11

(looking at the code now I see I could save a little bit of time by saving X and Y in registers)

 

X and Y are stored as 8.8 fixed point values, so the integer part is simply the MSB. And because the map is 256 bytes/characters wide, all the takes to generate an offset is to use integer Y as MSB and integer X as LSB. The ANDI R1,>3FFF is required to wrap the vertical edges of the map, but could be left out if the map had boundaries. To move (X,Y) to next column you simply add (cos(a) * scale, sin(a) * scale) and to move to the next row you add the orthogonal of this vector (-sin, cos).

 

I have a question about the MPY instruction: From what I can read in the E/A manual page 93 it's supposedly for unsigned values, but I have used it now for several projects on signed values. The only thing is that it overflows more easily on negative values because of the sign bits. Is that what it means that it's for unsigned values?

rotate.a99

map6.a99

  • Like 2
Link to comment
Share on other sites

...

I have a question about the MPY instruction: From what I can read in the E/A manual page 93 it's supposedly for unsigned values, but I have used it now for several projects on signed values. ...

 

The TMS9900 Data Manual says this, as well.

...

The only thing is that it overflows more easily on negative values because of the sign bits. Is that what it means that it's for unsigned values?

 

How are you getting the MPY instruction to overflow when no status bits are affected by it? It is impossible for the MPY instruction to overflow. That is why status is unaffected. The largest unsigned, 16-bit number, FFFFh, when multiplied by same, is FFFE0001h (the unsigned, 32-bit result), which can neither carry nor overflow. The fact that the leftmost bit is set is the only reason we might consider the number negative.

 

...lee

Link to comment
Share on other sites

I have a question about the MPY instruction: From what I can read in the E/A manual page 93 it's supposedly for unsigned values, but I have used it now for several projects on signed values. The only thing is that it overflows more easily on negative values because of the sign bits. Is that what it means that it's for unsigned values?

 

MPY is clearly for unsigned values only. The TMS9995 offers a separate MPYS (and DIVS).

 

You can only work with signed values when they are positive. For instance, multiplying -1 by -1 (FFFF * FFFF) will deliver FFFE0001 with MPY, but 00000001 with MPYS.

Edited by mizapf
Link to comment
Share on other sites

 

 

The TMS9900 Data Manual says this, as well.

 

How are you getting the MPY instruction to overflow when no status bits are affected by it? It is impossible for the MPY instruction to overflow. That is why status is unaffected. The largest unsigned, 16-bit number, FFFFh, when multiplied by same, is FFFE0001h (the unsigned, 32-bit result), which can neither carry nor overflow. The fact that the leftmost bit is set is the only reason we might consider the number negative.

 

...lee

 

 

You're right, of course, that MPY cannot overflow. What I mean is overflowing into the most significant word. What I'm usually doing is to multiply two signed words, then use only the least significant word of the result. In the case of >FFFF (-1) * >FFFF (-1) the result as you say is >FFFE0001 and the least significant word is >0001, which is correct. Another example: >FFFE (-2) * >0003 (3) = >0002 FFFA, where >FFFA = -6. What I think I have found is that there is a limit to how big numbers this works for, but I'm not sure. Edit: I mean a more restrictive limit than the obvious of not being able to store the result in a single word.

Link to comment
Share on other sites

This is an interesting observation. In fact, when you consider negative numbers in their 2s complement format to be subtracted from the maximum unsigned number +1, you can find:

 

0xFFFE * 0xFFFD = (0x10000 - 0x0002) * (0x10000 - 0x0003) = 0x10000^2 - 0x10000 * 0x0003 - 0x10000 * 0x0002 + 0x0002 * 0x0003

 

The first term (0x10000^2) is 0 mod 2^32, then there is (0x10000 * (- 0x0003 - 0x0002)) = (0x10000 * (-0x0005)) = 0xFFFB0000, and finally 0x0006.

  • Like 1
Link to comment
Share on other sites

 

You're right, of course, that MPY cannot overflow. What I mean is overflowing into the most significant word. What I'm usually doing is to multiply two signed words, then use only the least significant word of the result. In the case of >FFFF (-1) * >FFFF (-1) the result as you say is >FFFE0001 and the least significant word is >0001, which is correct. Another example: >FFFE (-2) * >0003 (3) = >0002 FFFA, where >FFFA = -6. What I think I have found is that there is a limit to how big numbers this works for, but I'm not sure. Edit: I mean a more restrictive limit than the obvious of not being able to store the result in a single word.

 

Yes—I think the product result must be from -32768 to 32767 for your scenario to work.

 

...lee

Link to comment
Share on other sites

As @mizapf said, the only way to do signed multiplication is with positive numbers, which would mean the extra steps of converting to positive numbers and tracking the sign. Then, any non-zero value in the MSW of the product would indicate overflow.

 

Of course, -32768 would need to be handled as a special case because you cannot negate it in 16 bits and 32768 would be a legitimate intermediate result if the result sign were negative.

 

...lee

Edited by Lee Stewart
Link to comment
Share on other sites

Of course, -32768 would need to be handled as a special case because you cannot negate it in 16 bits and 32768 would be a legitimate intermediate result if the result sign were negative.

 

I don't think you need a special case. Negating >8000 (-32768) gives >8000 (32768), which is what you want for the multiplication.

 

Anyway, it looks like I can continue to use MPY directly as long as the numbers are small enough, e.g. if both numbers are -128 < 0 < 128.

Link to comment
Share on other sites

I don't think you need a special case. Negating >8000 (-32768) gives >8000 (32768), which is what you want for the multiplication.

It is still a negative number; but, the effect with MPY is moot as you imply. However, I should have gone further with what determines overflow. Overflow is indicated not only by a non-zero MSW, but by a 1 in the MSb of the LSW. The special case is when the result is exactly >8000 and the result sign is negative.

Anyway, it looks like I can continue to use MPY directly as long as the numbers are small enough, e.g. if both numbers are -128 < 0 < 128.

 

Indeed.

 

...lee

Link to comment
Share on other sites

Hope that save2600 with TI-Kart is referring to Mario Kart ?

* (the one on the RetroPie Nintendo64 (64 version) - Mario Kart, is quite fun with rotating platforms)

 

* new version of a TI-Super Asteroids ? (I got a bit the feeling like that)

 

* 3D Tetris ?

 

* or a kind of Escher game ?

Link to comment
Share on other sites

Very nice. :)

 

Thinking of game aspects... I wonder if you could adapt it slightly for a "mode7"-like projection and get a pseudo 3D road map up there. I haven't /done/ it, so I'm not quite sure, but just changing the scale each line seems like it'd work... and you only have to draw half the screen in that case. ;)

 

It does look a bit like a racing game, but even Pole Position looks like Full HD in comparison. ;-)

 

 

I think the best game for this technique would be a top view racing game where sprites could be used to provide some high res details.

  • Like 6
Link to comment
Share on other sites

       MOVB @MAP(R1),*R0               ; Send to VDP (R0 is VDPWD)

       A    R3,R12                     ; X += cos(a) * scale

 

The first one above is a nice one. Somehow I've never used it much and probably never in an inner loop, but it seems just fine.

 

The second one looks kickass. The comment threw me off a bit. cos(a) * scale is of course not calculated here.

 

Overall impressive framerates.

 

:thumbsup:

 

Edited by sometimes99er
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...