artrag Posted November 10, 2014 Share Posted November 10, 2014 If you stay to split screen and to TMS9918A, the sprite trick (polling for the 5th sprite on a given plane) should be perfect. You could e.g. double the number of sprites on the screen, have two screen mode active (bitmap and multicolor), change sprite size, etc. Quote Link to comment Share on other sites More sharing options...
Wildstar Posted November 10, 2014 Share Posted November 10, 2014 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/ Quote Link to comment Share on other sites More sharing options...
Asmusr Posted November 15, 2014 Author Share Posted November 15, 2014 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 4 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted November 15, 2014 Share Posted November 15, 2014 Wow! That is very impressive. Isn't it fun to do stuff that the experts always said was impossible? Quote Link to comment Share on other sites More sharing options...
+Ksarul Posted November 15, 2014 Share Posted November 15, 2014 That is a beautiful trick, Rasmus! :) Quote Link to comment Share on other sites More sharing options...
artrag Posted November 15, 2014 Share Posted November 15, 2014 (edited) On classic99 there is a lot of flickering, i suspect it misses the split line. Anyone willing to try on a real TI with its original 9918A? Edited November 15, 2014 by artrag Quote Link to comment Share on other sites More sharing options...
matthew180 Posted November 16, 2014 Share Posted November 16, 2014 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! 2 Quote Link to comment Share on other sites More sharing options...
artrag Posted November 16, 2014 Share Posted November 16, 2014 (edited) 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 November 16, 2014 by artrag Quote Link to comment Share on other sites More sharing options...
Asmusr Posted November 16, 2014 Author Share Posted November 16, 2014 Interrupts are disabled, that's one of the first instructions: LIMI 0. Quote Link to comment Share on other sites More sharing options...
artrag Posted November 16, 2014 Share Posted November 16, 2014 (edited) 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 November 16, 2014 by artrag Quote Link to comment Share on other sites More sharing options...
Asmusr Posted November 16, 2014 Author Share Posted November 16, 2014 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. Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted November 16, 2014 Share Posted November 16, 2014 (edited) 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 November 16, 2014 by sometimes99er Quote Link to comment Share on other sites More sharing options...
artrag Posted November 16, 2014 Share Posted November 16, 2014 (edited) 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. NoteThe 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 November 16, 2014 by artrag Quote Link to comment Share on other sites More sharing options...
Asmusr Posted November 16, 2014 Author Share Posted November 16, 2014 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 Quote Link to comment Share on other sites More sharing options...
artrag Posted November 16, 2014 Share Posted November 16, 2014 (edited) What does cru do? Does it wait for an interrupt? On z80 we have halt for that Edited November 16, 2014 by artrag Quote Link to comment Share on other sites More sharing options...
Asmusr Posted November 16, 2014 Author Share Posted November 16, 2014 It's the Communication Register Unit. I can't explain how it works, but on the TI you can also read the VDP interrupt bit via the CRU, but you can't read other bits of the status register this way. Quote Link to comment Share on other sites More sharing options...
+mizapf Posted November 16, 2014 Share Posted November 16, 2014 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". Quote Link to comment Share on other sites More sharing options...
artrag Posted November 16, 2014 Share Posted November 16, 2014 The important is that it waits for the interrupt line and does not read the status register Quote Link to comment Share on other sites More sharing options...
Tursi Posted November 16, 2014 Share Posted November 16, 2014 On classic99 there is a lot of flickering, i suspect it misses the split line. Classic99's VDP doesn't do scanline emulation, so it won't work for now. Quote Link to comment Share on other sites More sharing options...
Tursi Posted November 16, 2014 Share Posted November 16, 2014 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. Quote Link to comment Share on other sites More sharing options...
matthew180 Posted November 16, 2014 Share Posted November 16, 2014 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. Quote Link to comment Share on other sites More sharing options...
Willsy Posted November 16, 2014 Share Posted November 16, 2014 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! Quote Link to comment Share on other sites More sharing options...
+OLD CS1 Posted November 16, 2014 Share Posted November 16, 2014 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? Quote Link to comment Share on other sites More sharing options...
+mizapf Posted November 16, 2014 Share Posted November 16, 2014 No, at most 16 bits in one go, but you're right for the number of addresses. The data rate is determined by the CPU cycle rate; I think it takes 2 cycles @ 333 ns per bit. Have to look it up, though. Quote Link to comment Share on other sites More sharing options...
artrag Posted November 16, 2014 Share Posted November 16, 2014 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. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.