Subject: Re: [stella] my programs aren't good enough at doing nothing|
From: Andrew Towers <mariofrog@xxxxxxxxxxx>
Date: Tue, 27 Aug 2002 18:48:56 +1000
As I haven't been posting to the list much (at all actually), I thought this would be a good oportunity to make a fool of myself (as required to initiate all newbies).
So I've taken Kirk Israel's Thin Red Line and added a few comments to try and explain the problems he's on about, and anything else that came to mind at the time.
In the end I took a copy and rearranged it liberally with lots more comments added in for good measure. This one gives me a nice clean red line and no artifacts in Z26, and a single (erroneous I think) HMOVE blank in StellaX. I don't have an NTSC TV here just at the moment so I haven't tested this on a real live TV.
Only one thing is giving me grief; when I set TIM64T to 43, I didn't get the exact timing I was expecting - it's actually out by around 64 cycles (give or take 5). Any explanation of this would be greeted with profound thanks and adoration.
; thin red line by Kirk Israel processor 6502 include vcs.h org $F000 Start SEI CLD LDX #$FF TXS LDA #0 ClearMem STA 0,X DEX BNE ClearMem LDA #%11001000 ; melon green STA COLUBK LDA #33 STA COLUP0 ; Misc note: the VSYNC is turned on and off on cycles 12 and 11 respectively ; (this is for the second and subsequent frames; for the first frame the ; VSYNC will happen at a completely random time.) I'm not sure how safe ; this is or whether it matters, but this means the VSYNC will be a bit ; out of phase with the horizontal timing in the TV.
MainLoop LDA #2 ;+2 STA VSYNC ;+3 *12* STA WSYNC ;-- end of first VSYNC line STA WSYNC ;-- end of second VSYNC line STA WSYNC ;-- end of third VSYNC line ; Setting the timer to 44, 45 or 46 reduces the half-line relic because ; it is shifting the "unknown positions" (commented below) to the right ; by 64 cycles each time. This visually moves the start-of-line left ; by 12 cycles (76-64=12) or 36 pixels and moves the start of screen ; down one line, which also breaks the 262-line VSYNC timing.
LDA #43 ;+2 STA TIM64T ;+4 LDA #0 ;+2 STA VSYNC ;+3 *11*
WaitForVblankEnd LDA INTIM BNE WaitForVblankEnd LDY #191
; The following "unknown positions" cause the half-line of background colour ; and also the extra dot lagging behind on the second half of the top line ; (because the missile is enabled half way along the line above the HMOVE.) ; Running Z26 in trace mode shows that the VBLANK is done on cycle 40, ; part-way along a scanline.
STA VBLANK ;+3 *?* unknown position on line LDA #$F0 ;+2 STA HMM0 ;+3 *?* also unknown position
STA WSYNC ;-- start first fully-visible line STA HMOVE ;-- there will be a HMOVE blank on this line ScanLoop STA WSYNC ;-- LDA #2 STA ENAM0 DEY BNE ScanLoop
LDA #2 STA WSYNC ;-- STA VBLANK ;+3 *3* LDX #30 OverScanWait STA WSYNC ;-- start of first VSYNC line on exit DEX ;+2 BNE OverScanWait ;+2/3 JMP MainLoop ;+3
org $FFFC .word Start .word Start
; thin red line by Kirk Israel ; with timing tweaks by Andrew Towers
processor 6502 include vcs.h org $F000 Start SEI CLD LDX #$FF TXS LDA #0 ClearMem STA 0,X DEX BNE ClearMem LDA #%11001000 ; melon green STA COLUBK LDA #33 STA COLUP0
; The VSYNC is changed on the 3rd cycle every time for the first and ; every subsequent frame, and occupies lines 1-3 (starting from line 1 ; as does Z26 so I don't confuse myself or someone like me).
; In a Z26 trace, the STA VSYNC shows up as line 263 for cycles 0-2, ; then the line becomes line 1 starting on cycle 3. This looks odd but ; it makes sense to me if we need a total of 262 -whole- lines.
MainLoop LDA #2 ;+2 STA WSYNC ;-- wait for start of first VSYNC line STA VSYNC ;+3 *3* start of line 1 STA WSYNC ;-- end of first VSYNC line STA WSYNC ;-- end of second VSYNC line LDA #0 ;+2 STA WSYNC ;-- end of third VSYNC line STA VSYNC ;+3 *3* start of line 4
; Set up the timer. We need to wait for 37 whole lines minus a bit, to ; make sure we drop out of WaitForVblankEnd before the end of the last ; VBLANK line. Since we're not scraping for processing time yet, we ; can just make sure we're waiting -more than- 36 lines (hence rounding ; down 37*76/64=43.94 to 43, giving 36.21 lines.)
; Now I can't get this to work properly in a Z26 trace. It always drops ; out of WaitForVblankEnd in the middle of line 39 (cycle 43) whereas ; I would expect it to be cycle 25-30 (9 + 0.21 * 76) on line 40.
; The only explanations I can think of are (a) I'm missing something ; (b) I'm going senile (c) The RIOT (or the Z26 emulation) doesn't ; reset it's div-by-64 counter when TIM64T is written. This would ; allow an end time anywhere between cycle 37 on line 39 and cycle ; 25 on line 40.
; In any case a count of 44 gives me the results I'm looking for, ; exiting the loop 63 cycles later on cycle 30 at line 40. ; Anyone have any ideas why my TIM64T count is out by one?
LDA #44 ;+2 timer for 44*64 cycles STA TIM64T ;+4 ... starting on cycle *9* line 4
; Use the VBLANK time to do setup for the next frame, ; such as enabling the missile and moving it into position. ; Note that nothing will be seen while VBLANK is on, so this ; won't produce any HMOVE lines or stray missiles.
LDA #2 STA ENAM0 ; enable missile (not visible yet)
LDA #$F0 STA HMM0 ; set up the missile movement STA WSYNC ;-- wait for start of any line STA HMOVE ; do the HMOVE now when no-one can see it
; Wait for the timer to end. Note that we have a 64-cycle window of ; opportunity to spot the zero-count, which is plenty for a 5-cycle ; loop.
WaitForVblankEnd LDA INTIM BNE WaitForVblankEnd
; We will drop out of the timer loop somewhere in the middle of the ; last line of VBLANK (line 40), so we'll have to wait for the end ; of that line before turning VBLANK off.
LDA #0 ;+2 STA WSYNC ;-- wait for start of first visible line STA VBLANK ;+3
LDY #191 ScanLoop STA WSYNC ;-- count 191 more visible lines DEY BNE ScanLoop
; Now wait for the end of the last visible line (232), start of the ; first line of overscan (233), and immediately turn on VBLANK.
LDA #2 STA WSYNC ;-- wait for end of visible line 192, STA VBLANK ;+3 *3* start of first overscan line
; There are 29 start-of-lines left in the overscan, then we can jump ; to the top which will finish the 30th line.
LDX #29 OverScanWait STA WSYNC ;-- wait for the start of 29 more lines DEX ;+2 BNE OverScanWait ;+2/3
; Jump back to the start, which will wait for the end of the last ; overscan line (262), start of the first VSYNC line (1) before ; doing anything.
org $FFFC .word Start .word Start
---------------------------------------------------------------------------------------------- Archives (includes files) at http://www.biglist.com/lists/stella/archives/ Unsub & more at http://www.biglist.com/lists/stella/