Jump to content
IGNORED

VDP scanline tricks


Asmusr

Recommended Posts

I don't think you will get it stable enough to do this -- this is in fact almost exactly what I was trying to do (except I was going for the tighter goal of every 4 pixels.) I updated my image converter to generate a 4 color image that changed 1 palette register every 4 pixels, sort of an Amiga HAM approach, and the results were great (AND the image fits in the 18k available)! BUT, you just can not sync accurately enough to the beginning of a scanline with the GPU to line up the color changes correctly. Even though my test suggested you could change about every 8 pixels, there was 4-6 pixels of jitter on every frame.

 

If you can come up with a way around that and just generate a test app that gives a stable dynamically updated image, we could probably run a long way with that!

 

Lets continue this branch here:

 

http://www.atariage.com/forums/topic/231685-fli-ish-and-similar-tricks-with-f18a/

Link to comment
Share on other sites

I made a small demo with 48 sprites on the screen. I'm switching to a 2nd SAT after displaying the first 24 sprites. This is triggered by the 5th sprite flag which gets set because of a 25th invisible sprite. At vertical retrace I'm switching back to the 1st SAT.

 

 

It works well in MESS, but it doesn't work on my F18A. It looks like it's not picking up the 5th sprite flag. Does it work on a 9918A (I don't have one)?

Splitscreen.zip

  • Like 4
Link to comment
Share on other sites

It does work on a real 9918A, but the whole display flickers about every second and it gets annoying. I suppose it may not be as noticeable in game context and probably not any more annoying than flickering sprites due to the 5-sprite limit or sprite rotation schemes.

 

The F18A 5th-sprite problem will be corrected and the fix will be part of the pending V1.6 update. Now I have at least two programs to test with, thanks!

  • Like 2
Link to comment
Share on other sites

It does work on a real 9918A, but the whole display flickers about every second and it gets annoying. I suppose it may not be as noticeable in game context and probably not any more annoying than flickering sprites due to the 5-sprite limit or sprite rotation schemes.

 

The F18A 5th-sprite problem will be corrected and the fix will be part of the pending V1.6 update. Now I have at least two programs to test with, thanks!

 

Do you mean that once per second the polling loop misses the 5th sprite condition ?

From my limited understanding of the source, the sole action between the vertical retrace flag

*	   Wait for vertical retrace
LOOP1  MOVB	@VDPSTA,R0
	   ANDI R0,>8000
	   JEQ	LOOP1

and the polling for the 5th sprite

*	   Wait for 5th sprite flag
LOOP2  MOVB	@VDPSTA,R0
	   ANDI R0,>4000
	   JEQ	LOOP2

is the update of SAT1, which is performed in a FIXED amount of CPU cycles.

It is impossible that the glitch is caused by the fact that this code takes too much time, or you would miss the 5th sprite condition in ALL the frames.

 

This could mean that the glitch you see is due to the fact the reading of the status register, for any reason, is not reliable.

 

 

Question: I cannot see if interrupts are disabled... is there any other place e.g. on ISR where the status register is read ?

You know, reading the status register resets its flags.

 

Otherwise we face something HW related... that would be very strange but possible, as something similar has been reported for some early msx1 with problems in the power supply. Actually it has been reported that on the early release of the sony HB-20P, Uridium occasionally hangs in the polling loop on the vdp status register. The fact is that on the HB-20P the VDP is a Toshiba clone, not a TMS-9918A.... so It would be very strange to see this same problem here.

 

 

@matthew180, are going to investigate how the status register works on the real 9918A in order to implement its details in the F18A?

In this case, could you also implement the behaviour of its lower 5 bits ?

As officially documented, when the 5th sprite flag is set, the plane of the 5th sprite is reported in the lower 5 bits of the status register.

 

But there is more: according to some early tests, while the 5th sprite flag is reset, the 9918A reports in the lower 5 bits the number of the current highest sprite plane traced on the current raster line, line by line.

 

I have not been able to investigate in detail as I have an msx with v9958, but, if this undocumented behaviour were confirmed, you should be able to know in which part of the screen the raster beam is by just reading the current sprite plane beeing processed.

Edited by artrag
Link to comment
Share on other sites

I made a small demo with 48 sprites on the screen. I'm switching to a 2nd SAT after displaying the first 24 sprites. This is triggered by the 5th sprite flag which gets set because of a 25th invisible sprite. At vertical retrace I'm switching back to the 1st SAT.

 

 

It works well in MESS, but it doesn't work on my F18A. It looks like it's not picking up the 5th sprite flag. Does it work on a 9918A (I don't have one)?

 

Maybe in order to see clearly how much time you spend in each section of the code (and make clear that the issue has nothing to do with the excess of CPU time in the early loop) you could try something like this:

(I'm also sure you have plenty of time to update the two sats under the vertical border, this will show if its possible)

*	   Wait for vertical retrace
LOOP1  MOVB	@VDPSTA,R0
	   ANDI R0,>8000
	   JEQ	LOOP1
*	   Switch to SAT0	   
	   LI   R0,>0576			* Reg 5: Sprite Attribute Table
	   BL   @VWTR				* SPRAT0 = >3B00 (>76 * >80)

	   LI   R0,>071F			* Reg 7
	   BL   @VWTR				* backdrop color 15

*	   Move SAT0	   
	   LI	R0,SDIR00
	   LI	R1,SAT0
	   BL	@MOVSPR
*	   Copy SAT0 to VDP
	   LI	R0,SPRAT0
	   LI	R1,SAT0
	   LI	R2,24*4
	   BL	@VMBW	   

	   LI   R0,>07F0			* Reg 7
	   BL   @VWTR				* backdrop color 0
	   
*	   Move SAT1	   
	   LI	R0,SDIR06
	   LI	R1,SAT1
	   BL	@MOVSPR
*	   Copy SAT1 to VDP	   
	   LI	R0,SPRAT1
	   LI	R1,SAT1
	   LI	R2,24*4
	   BL	@VMBW	

	   LI   R0,>07F4			* Reg 7
	   BL   @VWTR				* backdrop color 4
	   
*	   Wait for 5th sprite flag
LOOP2  MOVB	@VDPSTA,R0
	   ANDI R0,>4000
	   JEQ	LOOP2
*	   Switch to SAT1	   
	   LI   R0,>0577			* Reg 5: Sprite Attribute Table
	   BL   @VWTR				* SPRAT1 = >3B80 (>77 * >80)

	   LI   R0,>07F8			* Reg 7
	   BL   @VWTR				* backdrop color 8

	   *	   Loop
	   JMP	LOOP1
Edited by artrag
Link to comment
Share on other sites

I tried my demo (the original code, not artrag's modified version) on a PAL console (TMS9929A) and the result are the same as Matthew reports: it works most of the time but the screen is flickering so it looks like the 5th sprite flag is missed once in a while.

 

I have only made a single scan line with 5 sprites to trigger the flag, perhaps that could be the issue? I will try to move the triggering sprite a few lines up to see if it matters, but then the bottom lines of 6th row of sprites will probably disappear.

Link to comment
Share on other sites

Marc H. said that it was unsafe to be polling, like in reading the VDP Status Register over and over in a tight loop.

It seems as if you (Rasmus) has happily continued to "poll", - and with all the scrolling, I would have expected you to notice the problem if there were any. Maybe the problem, the glitches, is not too distinct on 50Hz based systems ?

I'm emulation only, but I'd like for my games to work (and be smooth) on the real deal. I've looked into an ISR based solution, knowing it occupies a few bytes in ScrathPad and taking some time (cycles). Of course hooking and turning off ISR services (as discussed by Matthew). Guess I have to step through the ISR routine to look for any fall-pits, like other interrupt types getting through.

Also I think I saw a CRU based solution for getting the vertical blank interrupt bit.

Was it all discussed in the Smooth scrolling thread ?

Edited by sometimes99er
Link to comment
Share on other sites

The very well documented problem that is reported in the official TI documents is that reading the status register RESETS the F flag, so if you read it while the F flag is being set you will miss its actual value.

The TI docs recommend you read the status register only AFTER a VDP interrupt is pending.

The demo code could fail not for the 5th sprite flag, but because of the polling on the F flag.
You cannot do an asynchronous polling on the status register neglecting the interrupts.
The simplest solution to prevent this well documented issue is to move everything on the ISR and see if the glitch occurs again.

To be clearer, this segment:

*	   Wait for vertical retrace
LOOP1  MOVB	@VDPSTA,R0	   
       ANDI R0,>8000	   
       JEQ	LOOP1

is unsafe, as could reset bit F while it is being set.

Read paragraph 2.3 at page 2-11 of the TMS9918A/TMS9928A/TMS9929A official manual.

Note
The TI manual reports also that the 5th sprite flag is reset once you read the status register, but this is not a real problem, as the 5th sprite condition can be larger than one single line - using only one sprite, up to 16 lines obviously ;-).
In this way, even if you miss the 5th sprite condition once due to "reset while set", you will catch it the next line.
This also means that, ONCE per second, you could have a jitter of one line in the screen split, that is perfectly acceptable (and this is what I observe on real msx's).

TMS9918.pdf

Edited by artrag
Link to comment
Share on other sites

This version is flicker free on my PAL console. Two changes were necessary:

  • The sprite triggering the 5th sprite flag has been moved up one scan line. Without this change the bottom half of the screen is flickering.
  • The vertical retrace is polled using CRU instead of the status flag. Without this change the top of the screen is flickering. Using the ISR would also be possible, I guess.

I have used status flag polling in all of my games and demos, so why are they running smoothly? I guess it could be because a very tight polling loop like is this demo makes the probability for reading the status flag while it's being written much higher. Usually I would do other things in the loop like saving the collision flag.

Splitscreen2.zip

Link to comment
Share on other sites

The VDP INT line is routed to one of the 9901* inputs. That way you can read the interrupt level without reading the VDP status register and without allowing interrupts.

 

* The TMS9901 is sometimes called "the CRU" even though this is not correct (but I admit I did it also many times). The CRU is a serial bus controlled within the CPU (Communications Register Unit). TI calls the 9901 the "Programmable System Interface".

Link to comment
Share on other sites

I have used status flag polling in all of my games and demos, so why are they running smoothly? I guess it could be because a very tight polling loop like is this demo makes the probability for reading the status flag while it's being written much higher. Usually I would do other things in the loop like saving the collision flag.

When we studied the problem Marc revealed, I thought (I don't remember for sure) that we felt the 5th sprite and collision flags were subject to the same race as the frame flag. (In fact I know we tested collision, because our recommended workaround was to make sure your flags are set for more than one scanline, so if it's missed, you'll likely catch it on the next one. Less certain about 5S.)

 

A tight loop increases the odds of the race occurring, yes. It's a narrow window and won't happen most of the time. So even if it happened once in 10-20 frames, would you even notice? Probably not if you weren't looking for it.

Link to comment
Share on other sites

Ok, so after looking at the source code I see the problem of this demo on the F18A. It does in fact work, however the you have to remove the jumper USR1 or set the max sprite value in VR30 to 4. On the F18A the "5S" flag becomes the "Nth-Sprite" flag. The default is 32 sprites on a line, so the flag was never set because you only have a max of 5 sprites on a line.

 

The demo runs very smooth on the F18A and there is no flicker like on the original hardware. There are also no missing pixels on the 6th row of sprites like there are on the real hardware. This demo does not use the 5th-sprite number technique described elsewhere and which makes Miner49er not currently work on the F18A.

 

The USR1 jumper sets a default at power on of 4 (jumper off) and 32 (jumper on - the default). Most software will benefit from having more sprites on a line visible, but some software will fail because it relies on the 5th sprite not being displayed and possibly triggering an event.

 

In V1.6 I'm going to introduce another register that allows you to set the sprite value at which the 5S flag will be set, and it will default to 5. This will be separate from the sprite max VR30.

Link to comment
Share on other sites

What does cru do? Does it wait for an interrupt?

On z80 we have halt for that

CRU on the 99xx is *kind of like* (not exactly) port mapped I/O on the Z80 (I.e. IN/OUT). The port instructions on the Z80 move 8 bits at a time and they don't take space out of the 64k memory map. Same on the 99xx but we can move any number of bits from 1 to... err... I can't remember!

Link to comment
Share on other sites

CRU on the 99xx is *kind of like* (not exactly) port mapped I/O on the Z80 (I.e. IN/OUT). The port instructions on the Z80 move 8 bits at a time and they don't take space out of the 64k memory map. Same on the 99xx but we can move any number of bits from 1 to... err... I can't remember!

 

4096. There is a CRU clock and CRU data line, so I assume the CRU is bit-shifted. If so, at what bit rate?

Link to comment
Share on other sites

When we studied the problem Marc revealed, I thought (I don't remember for sure) that we felt the 5th sprite and collision flags were subject to the same race as the frame flag. (In fact I know we tested collision, because our recommended workaround was to make sure your flags are set for more than one scanline, so if it's missed, you'll likely catch it on the next one. Less certain about 5S.)

 

A tight loop increases the odds of the race occurring, yes. It's a narrow window and won't happen most of the time. So even if it happened once in 10-20 frames, would you even notice? Probably not if you weren't looking for it.

 

Agreed, this is how it works with Uridium: the 5th sprite condition lasts 16 lines, so even missing the first, you catch the second.

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