QUIKMAN 2008 for the unexpanded VIC 20
Moderator: Moderators
- Mike
- Herr VC
- Posts: 4901
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
If an interrupt occurs while that wait routine is executing, that IRQ might hinder the loop to recognize, that the correct number is in the raster register. Then a frame will be dropped.
This might not easy be recognised on a PAL VIC, since the responsible IRQ is the jiffy clock, which goes with ~60 Hz, while the frames come with 50 Hz, i.e. pretty asynchronous.
But on a NTSC VIC, the jiffy clock runs nearly synchronous to the screen repetition rate, so that the "dead zone" literally slowly glides over the screen. When it occludes the raster line to wait for, the wait routine won't execute, dropping a frame not only a single, but multiple times.
The correct solution is *not* to put a SEI/CLI bracket around the wait routine. Instead, you:
- sync the VIA interrupt to the raster line, and then
- set a flag in memory, when that IRQ occurs,
- wait for that flag in the foreground program, and
- clear the flag by the foreground program, and continue execution.
Michael
This might not easy be recognised on a PAL VIC, since the responsible IRQ is the jiffy clock, which goes with ~60 Hz, while the frames come with 50 Hz, i.e. pretty asynchronous.
But on a NTSC VIC, the jiffy clock runs nearly synchronous to the screen repetition rate, so that the "dead zone" literally slowly glides over the screen. When it occludes the raster line to wait for, the wait routine won't execute, dropping a frame not only a single, but multiple times.
The correct solution is *not* to put a SEI/CLI bracket around the wait routine. Instead, you:
- sync the VIA interrupt to the raster line, and then
- set a flag in memory, when that IRQ occurs,
- wait for that flag in the foreground program, and
- clear the flag by the foreground program, and continue execution.
Michael
@Mike: tell me if I have understood well: in a NTSC Vic, it might happen that IRQ and raster-line get in phase for several frames so that when the main program exits from the "wait" loop and expects to execute the sprite routine, IRQ comes in and is executed instead of the sprite routine. So the problem is: IRQ routine execute instead of the sprite routine for several frames. Is that correct?
@Robert: you can easily compute the time spent by your sprite routine this way: turn the border cyan before your routine and restore it to black at the end. The longer the execution time, the wider the cyan stripe. This lets you "tune" what is the bottom raster line to start from; for example in quikman you can start from the bottom border of the maze (included) because you don't have sprites there.
@Robert: you can easily compute the time spent by your sprite routine this way: turn the border cyan before your routine and restore it to black at the end. The longer the execution time, the wider the cyan stripe. This lets you "tune" what is the bottom raster line to start from; for example in quikman you can start from the bottom border of the maze (included) because you don't have sprites there.
- Mike
- Herr VC
- Posts: 4901
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
Not quite. Suppose the raster to wait for is #250. The IRQ routine maybe needs 3 raster lines to execute, and then the two following scenarios would be O.K.:nippur72 wrote:So the problem is: IRQ routine execute instead of the sprite routine for several frames. Is that correct?
- wait routine begins execution,
- IRQ occurs in raster line 240,
- IRQ is left in raster line 242,
- wait routine senses line 250, and exits.
- wait routine begins execution,
- wait routine senses line 250, and exits,
- IRQ occurs in raster line 251,
- IRQ is left in raster line 253.
but not:
- wait routine begins execution,
- IRQ occurs in raster line 249,
- IRQ is left in raster line 251,
- wait routine has been hindered to run - by the IRQ - during line 250, so it waits (at least) another full frame.
And in NTSC, that condition can be true not only for a single frame, but for several consecutive frames.
But, as I said, bracketing the wait routine with SEI/CLI is not a good idea for a solution. Generally, one should not leave IRQs disabled for prolonged times.
Does it ever take that long? I make that 12 lines or so from the hypothesised line 250.so the raster register resets to 0 in the meanwhile.
Even if it did take that long you could get round that with something like ..
Code: Select all
wait
LDA $9004
BPL done
CMP #rasterline
BCC wait
done
Lee.
- Mike
- Herr VC
- Posts: 4901
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
I quickly hacked this into the VICE monitor:
Start the IRQ Server with SYS673, and then the main program with SYS828. If a key is pressed, IRQ processing (green) nearly extends to the bottom, making for a close call.
I only could test this on VICE. Could someone confirm, that the timing constants, and raster line are also correct for a real NTSC VIC?
Code: Select all
; Interrupt server and wait routine.
; The Timer 1 timing constant ($4243) and raster line ($75) need be changed for PAL.
.C:02a1 78 SEI
.C:02a2 A9 BF LDA #$BF
.C:02a4 8D 14 03 STA $0314
.C:02a7 A9 02 LDA #$02
.C:02a9 8D 15 03 STA $0315
.C:02ac A2 43 LDX #$43 ; load T1 latch low
.C:02ae 8E 24 91 STX $9124
.C:02b1 A2 42 LDX #$42
.C:02b3 A9 75 LDA #$75
.C:02b5 CD 04 90 CMP $9004
.C:02b8 D0 FB BNE $02B5 ; sync to line $75, once, with IRQ's disabled
.C:02ba 8E 25 91 STX $9125 ; load T1 latch high, and transfer both bytes to T1 counter
.C:02bd 58 CLI
.C:02be 60 RTS
.C:02bf A9 1D LDA #$1D
.C:02c1 8D 0F 90 STA $900F ; border=GRN, signals IRQ processing
.C:02c4 A9 01 LDA #$01
.C:02c6 8D D9 02 STA $02D9 ; set flag
.C:02c9 4C BF EA JMP $EABF
.C:02cc A9 01 LDA #$01 ; entry for wait routine
.C:02ce CD D9 02 CMP $02D9
.C:02d1 D0 FB BNE $02CE
.C:02d3 A9 00 LDA #$00
.C:02d5 8D D9 02 STA $02D9
.C:02d8 60 RTS
.C:02d9 00 BRK
; "Main" program
.C:033c A9 1A LDA #$1B ; border=CYAN => idle time
.C:033e 8D 0F 90 STA $900F
.C:0341 20 CC 02 JSR $02CC ; wait
.C:0344 A9 1B LDA #$1A ; border=RED => simulated processing time
.C:0346 8D 0F 90 STA $900F
.C:0349 A2 08 LDX #$08
.C:034b A0 00 LDY #$00
.C:034d 88 DEY
.C:034e D0 FD BNE $034D
.C:0350 CA DEX
.C:0351 D0 FA BNE $034D
.C:0353 4C 3C 03 JMP $033C
I only could test this on VICE. Could someone confirm, that the timing constants, and raster line are also correct for a real NTSC VIC?
-
- Omega Star Commander
- Posts: 1371
- Joined: Thu Jan 31, 2008 2:12 pm
- Website: https://robert.hurst-ri.us
- Location: Providence, RI
- Occupation: Tech & Innovation
Very interesting Mike ... and that's exactly the weird timing behavior I was seeing on an NTSC VIC, whereas the "dead zone" you speak of was causing severe "frame drops", until it drifted back. An astute explanation!!
So, I had to try your "hack", but I resorted to ca65 assembler to compile it. Made file irq.s from this:
And got these results from VICE 2.1:
RUNNING IDLE
HOLDING A SHIFT KEY DOWN
And the homed "@" (FLAG = 0) never flickers, because it only becomes "A" (FLAG = 1) when MYIRQ gets fired off, indicated by the GREEN border area. And that GREEN border area expands because the keyboard scanning routine takes longer to execute, because there is an active keypress to decode (which means more rasters are being displayed), before it can return control back to the MAIN loop to reset it to RED.
Simple demo, but very effective. And it really shows that there is only a small amount of processing time available to update the active screen pages. Thanks again!
So, I had to try your "hack", but I resorted to ca65 assembler to compile it. Made file irq.s from this:
Code: Select all
; Interrupt server and wait routine.
;
; uses standard VIC20 (unexpanded)
.org $0FFF
.segment "STARTUP"
;
FLAG = $1E00
;
;********************************************************************
; LOAD "IRQSCAN.S",8,1
.word $1001 ; starting load address
BASIC: .byte $0B, $10
; 2009 SYS4109
.byte $D9, $07, $9E, $34, $31, $30, $39
.byte $00, $00, $00
;
; The Timer 1 timing constant ($4243) and raster line ($75) need be changed for PAL.
SEI
LDA #<MYIRQ
STA $0314
LDA #>MYIRQ
STA $0315
LDX #$43 ; load T1 latch low
STX $9124
LDX #$42
LDA #$75
@wait: CMP $9004
BNE @wait ; sync to line 234/235, once, with IRQ's disabled
STX $9125 ; load T1 latch high, and transfer both bytes to T1 counter
CLI
;
MAIN:
LDA #$1B ; border=CYAN => idle time
STA $900F
JSR POLLWAIT
LDA #$1A ; border=RED => simulated processing time
STA $900F
LDX #$08 ; burn some CPU cycles ...
LDY #$00
@loop: DEY
BNE @loop
DEX
BNE @loop
JMP MAIN
;
POLLWAIT:
LDA #$01 ; entry for wait routine
@wait: CMP FLAG
BNE @wait
LDA #$00
STA FLAG
RTS
;
MYIRQ:
LDA #$1D
STA $900F ; border=GRN, signals IRQ processing
LDA #$01
STA FLAG ; set flag
JMP $EABF
RUNNING IDLE
HOLDING A SHIFT KEY DOWN
And the homed "@" (FLAG = 0) never flickers, because it only becomes "A" (FLAG = 1) when MYIRQ gets fired off, indicated by the GREEN border area. And that GREEN border area expands because the keyboard scanning routine takes longer to execute, because there is an active keypress to decode (which means more rasters are being displayed), before it can return control back to the MAIN loop to reset it to RED.
Simple demo, but very effective. And it really shows that there is only a small amount of processing time available to update the active screen pages. Thanks again!
Last edited by rhurst on Sat Oct 16, 2010 10:03 am, edited 1 time in total.
-
- Omega Star Commander
- Posts: 1371
- Joined: Thu Jan 31, 2008 2:12 pm
- Website: https://robert.hurst-ri.us
- Location: Providence, RI
- Occupation: Tech & Innovation
Ok, I applied Mike's technique on top of the 4k ROM version -- which had to be expanded for the 8k ROM address space -- and it integrated just fine. I had to remove all of the CPU "slowdown" loop, because the game started to run too slowly with this VSYNC timing.
As a result: Quikman, Red, and Green did not flicker once. Cyan flickered only when it was roaming around the top fifth of the screen. Yellow was punished with visible flickering the most... because it is rendered on-the-fly after all others which is mainly occurring during the frame refresh. I would have to redo the graphics handling to have all 5 move without the flickering. The timing and pace of the game would have to be redone as well, if it is paced to 50/60 frames a second.
Interesting effect.
As a result: Quikman, Red, and Green did not flicker once. Cyan flickered only when it was roaming around the top fifth of the screen. Yellow was punished with visible flickering the most... because it is rendered on-the-fly after all others which is mainly occurring during the frame refresh. I would have to redo the graphics handling to have all 5 move without the flickering. The timing and pace of the game would have to be redone as well, if it is paced to 50/60 frames a second.
Interesting effect.
-
- Omega Star Commander
- Posts: 1371
- Joined: Thu Jan 31, 2008 2:12 pm
- Website: https://robert.hurst-ri.us
- Location: Providence, RI
- Occupation: Tech & Innovation
Good idea.f you sort the rendering of the sprites by raster line, ...
I hacked some additional code to auto-detect whether the VIC is PAL or NTSC, and to synchronize IRQ with the screen's last raster line appropriately. This seems to work on VICE just fine. Any comment?
Code: Select all
; my interrupt vector init
SEI
LDX #<MYIRQ
LDY #>MYIRQ
STX $0314
STY $0315
; PAL setup
@PAL = $5686 ; (312 * 71 - 2)
@pal: LDA $9125
AND #$10
BEQ @ntsc
LDX #<@PAL ; load T1 latch low
STX $9124
LDX #>@PAL
LDA #$82 ; raster line 260/261
BNE @wait
; NTSC setup
@NTSC = $4243 ; (261 * 65 - 2)
@ntsc: LDX #<@NTSC ; load T1 latch low
STX $9124
LDX #>@NTSC
LDA #$75 ; raster line 234/235
@wait: CMP VIC+$04
BNE @wait ; vsync
STX $9125 ; load T1 latch high, and transfer both bytes to T1 counter
CLI
-
- Omega Star Commander
- Posts: 1371
- Joined: Thu Jan 31, 2008 2:12 pm
- Website: https://robert.hurst-ri.us
- Location: Providence, RI
- Occupation: Tech & Innovation
Very unlikely... no wiggle room, and I am not that talented!Do you think to update the 4K rom version ?
I got my lovely copy of Retro-Gamer #59 this afternoon. This issue holds extra special meaning to me, first because it features Battle Zone on the front cover, and then a neat article on the Pac-Man world record holder, Jon Stoodley. But most obvious, because of the Quikman 2008 entertaining review -- to see it in print on a full-page, its so l-a-r-g-e!! And to be listed first on their brand-new section called Homebrew, it's such an honor. It is so cool an article with layout, I am going to the local print shop to get it enlarged to hang in my office.
Well, the love gotten back from all of this has been indeed a special joy -- thanks everyone!
Thank God!rhurst wrote:Very unlikely... no wiggle room, and I am not that talented!Do you think to update the 4K rom version ?
Yes it's a great conversion, i've played, ops tested it on Mega-Cart last night for a good while...But most obvious, because of the Quikman 2008 entertaining review -- to see it in print on a full-page, its so l-a-r-g-e!! And to be listed first on their brand-new section called Homebrew, it's such an honor.
Mega-Cart: the cartridge you plug in once and for all.