| | Hermit
Registered: May 2008 Posts: 208 |
shortest CIA-stable raster
<Post edited by moderator on 4/4-2009 14:47>
Hi, Guys :)
While preparing for compo I've developed maybe the shortest
CIA-type stable raster solution (fits in 64 bytes, 24 asm-rows).
If you can do even shorter, I'm curious :)
It works fine in practice, don't have to type novels to achieve
stable raster, and no need for raster-IRQ,CMPd012 method is enough.
If you find it useful for fast & short demo-writing, we may implement it
into codebase64.
;setting the CIA1-timerA to beam in the program beginning:
-----------------------------------------------------------
sei ;we don't want lost cycles by IRQ calls :)
sync cmp $d012 ;scan for begin rasterline (A=$11 after first return)
bne *-3 ;wait if not reached rasterline #$11 yet
ldy #8 ;the walue for cia timer fetch & for y-delay loop
sty $dc04 ;CIA Timer will count from 8,8 down to 7,6,5,4,3,2,1
dey ;Y=Y-1 (8 iterations: 7,6,5,4,3,2,1,0)
bne *-1 ;loop needed to complete the poll-delay with 39 cycles
sty $dc05 ;no need Hi-byte for timer at all (or it will mess up)
sta $dc0e,y ;forced restart of the timer to value 8 (set in dc04)
lda #$11 ;value for d012 scan and for timerstart in dc0e
cmp $d012 ;check if line ended (new line) or not (same line)
sty $d015 ;switch off sprites, they eat cycles when fetched
bne sync ;if line changed after 63 cycles, resyncronize it!
.... the rest (this is also a stable-timed point, can be used for sg.)
B;EXAMPLE-using timerA to stabilize 7 cycle jitter when using CMPd012:
-----------------------------------------------------------------------
scan ldx #$31 ;a good value that's not badline, in border and 1=white
cpx $d012 ;scan rasterline
bne *-3 ;wait until rasterline will be $31
lda $dc04 ;check timer A, here it jitters between 7...1
eor #7 ;A=7-A so jitter will be 0...6 in A
sta corr+1 ;self-writing code, the bpl jump-address = A
corr bpl *+2 ;the jump to timer (A) dependent byte
cmp #$c9 ;if A=0, cmp#$c9; if A=1, cmp #$c9 again 2 cycles later
cmp #$c9 ;if A=2, cmp#$c9, if A=3, CMP #$EA 2 cycles later
bit $ea24 ;if A=4,bit$ea24; if A=5, bit $ea, if A=6, only NOP
stx $d020 ;x was 1 so border is white at the stable cycle
sty $d020 ;y ended in 0 in sync routine, so border black after 4 cycles
jmp scan ;go to the raster again (or can go new raster)
-----------------------------------------------------------------------
Opinions?
Hermit Software Hungary |
|
| | Hermit
Registered: May 2008 Posts: 208 |
I'm working on the form, but no spaces appear in post. :(
Hermit Software Hungary |
| | chatGPZ
Registered: Dec 2001 Posts: 11356 |
fixed it (use the "code" tag =)) |
| | Hermit
Registered: May 2008 Posts: 208 |
Many thaks
Hermit Software Hungary |
| | Oswald
Registered: Apr 2002 Posts: 5086 |
nice one, but a bit too overoptimised. expecting A being $11 at the start is over the top, as it will be used as a subroutine inside someone's code most probably. secondly I'd prefer to see it setup the timer for a raster irq and a raster irq example. thirdly if this is done put it in codebase, there's a huge demand for such code :) |
| | Hermit
Registered: May 2008 Posts: 208 |
Hi, Oswald.
Yes, it's very optimised, but does the work in any circumstances I've tried, and the aim was the least typing work.
It makes no sense whatever value is in A when calling this routine, because first D012 check can be anywhere, and A will surely be $11 after the first syncronizing phase. And 1st phase appears.
OK,whait a while, I'll work out & share also the IRQ-version today. And of course put it to codebase.
!!One important thing to pay attention: The stx $d020, sty$d020 is only an example, and works.
But put some delay, if only several rows are in this section, because checking d012 ("scan") will appear again in the same raster-row with other timings, that can -of course- crash the program.
It's not a problem in real demo-programming, we very-rarely use a raster interrupt only for some D020 modifying commands...in that case no danger of cmpd012 repetition on the same line.
Hermit Software Hungary |
| | Hermit
Registered: May 2008 Posts: 208 |
Good news, the CIA setter-routine (first part) works well also for raster IRQ. :)
Set the IRQ then,
The form after IRQ entry (when IRQ calld) should be something like this:
pha
lda $dc04
eor #7
sta *+4
bpl *+2
lda #$a9
lda #$a9
lda $eaa5
txa
pha
tya
pha
...
...the rest processes in the IRQ routine
...
asl $d019
pla
tay
pla
tax
pla
rti
I'll refresh Codebase64 with this info:)
Hermit Software Hungary |
| | Copyfault
Registered: Dec 2001 Posts: 475 |
Quote: Good news, the CIA setter-routine (first part) works well also for raster IRQ. :)
Set the IRQ then,
The form after IRQ entry (when IRQ calld) should be something like this:
pha
lda $dc04
eor #7
sta *+4
bpl *+2
lda #$a9
lda #$a9
lda $eaa5
txa
pha
tya
pha
...
...the rest processes in the IRQ routine
...
asl $d019
pla
tay
pla
tax
pla
rti
I'll refresh Codebase64 with this info:)
Hermit Software Hungary
Hmm, the first part of your code can be "optimized" ;)
What about...
pha
lda $dc04
lsr
bcs *+2
asr #$07
bcc *+6
bcs *+4
bne .end
bne *-2
.end
...
eats up the same amount of cycles but saves one byte (unless you're running the code within the zp, which makes it even more unflexible)
Maybe one can even cut it down further by two bytes... it's tackling to try to get rid of one of these branch opcodes, but up to now I didn't see a way to do it.
Copyfault |
| | Hermit
Registered: May 2008 Posts: 208 |
Good to see this approach, I was thinkig about a similar delayer with branch-commands but couldn't realize yet.
As I could, I avoided to use illegal opcodes, because some assemblers (or machine-types?) make it hardly, and also the beginners need a clear code to understand on Codebase64.
I've tried this routine and really works, and GREAT NEWS: no need for ASR#7, an LSR is pretty enough. Why? Because our CIA is counting only in 9 cycles, and at the LDA DC04 only 7..1 appears, no need to turn off any bits. 1 byte saved again.
pha
lda $dc04
lsr
bcs *+2
LSR
bcc *+6
bcs *+4
bne .end
bne *-2
.end
Although, If you can advise a C64 turbo assembler that accepts illegals, I would be happy.
Other idea is, we could do this bne-bcc-bcs..etc like delayer with a halving method, that may reduce steps..
My other approach is to load dc04 to X or Y, and make an indexed jump to a delay-routine. So no need to invert (EOR) the dc04 which is unfortunately counting BACK from 7 to 1 (8 to 0 (8) to be true). Or "JMP ($dc03)" method can be useful to reduce rows.
Hermit Software Hungary |
| | Copyfault
Registered: Dec 2001 Posts: 475 |
I really wonder how a simple LSR instead of ASR #$07 can work. The timing registers NEVER go down to #$00. After #$01, instead of counting down to #$00 the regs are directly reset to the initial value (here $3e most probably). So without masking, we can not make sure that the bne-commands work as intended.
Be careful with the jitter range: it is true that a (legal) RMW-Opcode eats max. 7 cycles, but in combination with branch-opcodes the number of cycles to be considered for jitter can be even longer. This also depends on page_breaks. I once started a thread here about this... will post a link later when I found it.
If desired I can send some acme-source code which clearly shows that there are 8 possible jitter states (value read by $dc04 goes from e.g. $10 to $17). You can do these tests yourself by experimenting with some code like
inc abs,x
bpl *-3
bmi *-5
as main routine.
The jmp ($dc03)-approach has already been done before. Ninja took the idea behind it to perfection. IIRC there was some article out there in VN.
Copyfault |
| | Copyfault
Registered: Dec 2001 Posts: 475 |
Me again,
the discussion I mentioned above was about Stable Raster via Timer.
Copyfault |
... 17 posts hidden. Click here to view all posts.... |
Previous - 1 | 2 | 3 - Next | |