|
Post by oziphantom on Apr 23, 2022 14:27:17 GMT
this is cute tsx ; save stackpointer pla ; value of $ff00 (see $ff33) pla ; value of Y-reg pla ; value of X-reg sta $d600 ; restore $d600 txs ; restore stackpointer but will still nail you hard.
Ways this can go wrong
stx $d600 L1: bit $d600 ; breaks here, it got a negative value .. IRQ here, uses a lot of clocks, so the VDC is no longer ready .. bpl L1 ; comes back to code here sta $d601 ; write value when it is not ready rts
stx $d600 L1: bit $d600 bpl L1 ; IRQ here. again ready fails. sta $d601 rts
basically to be safe, you either do all your VDC writes either in or out of IRQ so you don't trash yourself. or you make the functions IRQ safe with a
sei stx $d600 L1: bit $d600 bpl L1 sta $d601 cli rts
so this way the write/read from VDC can't be interrupted by an IRQ and it stays consistent.
|
|
|
Post by wendling on Apr 23, 2022 14:30:11 GMT
VDC-IRQ example:
Prints "hello" in upper right corner. It stays there during scrolling.
Editor continues working with no random artifacts or roque scroll lines.
. 01300 sei ; set new irq vector . 01301 lda #$0d . 01303 sta $0314 . 01306 lda #$13 . 01308 sta $0315 . 0130b cli . 0130c rts
. 0130d ldx #$12 ; save update address . 0130f jsr $cdda . 01312 sta $13f0 . 01315 inx . 01316 jsr $cdda . 01319 sta $13f1
. 0131c lda #$00 ; set update address . 0131e ldx #$12 . 01320 jsr $cdcc . 01323 lda #$48 ; vdc screen address $0048: y=0 x=72 . 01325 inx . 01326 jsr $cdcc
. 01329 lda #$08 ; print "hello" in right upper corner vdc-screen . 0132b jsr $cdca . 0132e lda #$05 . 01330 jsr $cdca . 01333 lda #$0c . 01335 jsr $cdca . 01338 lda #$0c . 0133a jsr $cdca . 0133d lda #$0f . 0133f jsr $cdca . 01342 lda #$20 ; last character is space to eliminate roque scroll lines . 01344 jsr $cdca; (if irq fires between setting of datareg31 and countreg30)
. 01347 lda $13f0 ; restore update address . 0134a ldx #$12 . 0134c jsr $cdcc . 0134f lda $13f1 . 01352 inx . 01353 jsr $cdcc
. 01356 tsx ; restore reg $d600 . 01357 pla . 01358 pla . 01359 pla . 0135a sta $d600 . 0135d txs . 0135e jmp $fa65 ; jump to old irq
|
|
|
Post by stiggity on Apr 23, 2022 16:06:53 GMT
Ozi: I didn't even give it any thought to SEI/CLI during BIT $d600. I haven't compiled yet, but something tells me this may work. Wendling, thanks again! I'm putting together your example routine, and will havea something to play with over the weekend!!! You guys Rock!!!
|
|
|
Post by stiggity on Apr 23, 2022 17:46:13 GMT
Ozi: When i attempt to add the following into my copied $cdca/$cdd8/$cdcc/$cdda kernal calls, the moment i attempt to turn on my IRQ (Which calls these copied address's for screen writes) it crashes! "break" over and over.. the moment io revert to previous, and remove the SEI/CLI the IRQ functions.. the copied kernal calls sits in $1300-$3fff and banks kernal ROM IN, calls copied kernal calls, restrores bank.... what am i doing wrong?? heres a snippet..
cdca sei
sta ltemp0
lda $ff00
sta ent1
lda #$0c
sta $ff00
lda ltemp0
ldx #$1f
stx $d600
L1 bit $d600
bpl L1
sta $d601
sta ltemp1
lda ent1
sta $ff00
lda ltemp1 cli
rts
i tried placing SEI before stx $d600, then cli right after the sta $d601 - Sheesh..
|
|
|
Post by stiggity on Apr 23, 2022 18:49:06 GMT
Wendling: should i perform this...
tsx ; save stackpointer
pla ; value of $ff00 (see $ff33)
pla ; value of Y-reg
pla ; value of X-reg
sta $d600 ; restore $d600
txs ; restore stackpointer
before i exit back to IRQ exit, or after each "hook" attached to IRQ?? Theres only 2 routines...its not a Multi Monster MegaHook!! ehhe..
|
|
|
Post by wendling on Apr 24, 2022 5:47:27 GMT
Stiggity: Oziphantom pointed out an VDC-ready issue, so I changed the jmp $fa65 call in my VDC-IRQ example. See below. Now it's clear where to restore $d600: At the very, very, very last moment just before the IRQ exits.
Oziphantom: I see what you mean. And I think I have a solution: I changed the jmp $fa65 in my VDC-IRQ example and do all the IRQ stuff first and then wait for the VDC to be unoccupied just before the IRQ exits. So instead of tsx pla pla pla sta $d600 txs jmp $fa65 this:
cld ; see $fa65 jsr $c024 bcc exit jsr $f5f8 jsr $eed0 lda $dc0d lda $0a04 lsr bcc exit jsr $4006 exit: pla ; see $ff33 sta $ff00 pla tay pla tax ; here the x-reg is restored. That is the value I need to restore $d600 pla stx $d600 : restore $d600 with x-reg wait: bit $d600 ; wait for VDC to be ready bpl wait rti ; return from interrupt (only 7 cycles)
|
|
|
Post by oziphantom on Apr 24, 2022 9:15:39 GMT
while I'm at it
tsx ; save stackpointer pla ; value of $ff00 (see $ff33) pla ; value of Y-reg pla ; value of X-reg sta $d600 ; restore $d600 txs ; restore stackpointer you can just dotsx lda $103,x sta $d600
this will get the 3rd byte pushed on the stack, without needing to pull or restore the value. The Stack pointer is always the Next value so 100,x is the next address that will be pushed, 101 is the last thing that was pushed, 102 was the value before that etc
cdca sei sta ltemp0 lda $ff00 sta ent1 lda #$0c sta $ff00 lda ltemp0 ldx #$1f stx $d600 L1 bit $d600 bpl L1 sta $d601 sta ltemp1 lda ent1 sta $ff00 lda ltemp1 cli rts Since you trash X anyway you can avoid having to store and restore A
cdca sei ldx $ff00 stx ent1 ldx #$0c stx $ff00 ldx #$1f stx $d600 L1 bit $d600 bpl L1 sta $d601 ldx ent1 stx $ff00 cli rts
Since you are wrapping your read/writes with SEI you don't need to restore d600 in the IRQ anymore as the IRQ can't happen mid read/write. however if you are using an KERNAL routines that modify the VDC while you are not in the IRQ handler you run the race condition risk. Saving d600 from the stack only narrows the race condition, doesn't avoid it. So you need to be diligent about which routines are used not in IRQ and guard them as well if necessary. Multi threaded code is complicated
|
|
|
Post by wendling on Apr 25, 2022 11:31:50 GMT
Stiggity:
Just a thought about a cursor: If you print a character and set its attribute to flash(bit4) it looks like a cursor.
10 v=dec("cdcc")
18 sysv,0,18:sysv,78,19: rem right upper corner vdc screen
19 sysv,81,31: rem sphere
20 sysv,8,18:sysv,78,19
30 sysv,16+7,31: rem flash and color
And I saw your irq kernal banking out routine: I know you know this but you must set update reg #$12 before reg #$13. In your code you set #$13 first.
And why the tsx lda 0107,x test?
|
|
|
Post by stiggity on Apr 25, 2022 16:14:40 GMT
Wendling,
>>And I saw your irq kernal banking out routine: I know you know this but you must set update reg #$12 before reg #$13. In your code you set #$13 first.
That is how I've done it for quite sometime. What would the routine look like, setting updreg#$12 before reg#$13??
>>And why the tsx lda 0107,x test?
to get the interrupted prog loc. Hi byte
eor #$cd
beq continue and skip vdc access if in range $CDxx
This may be a crude fasion of doing things, and it _was_ working, until BANKing out kernal came into the picture..
I'm going to play with the alternative cursor snippet you added!! Your full of wonderful idea's/techniques!!!!!!!
|
|
|
Post by wendling on Apr 25, 2022 21:35:30 GMT
Stiggity:
I tried your tsx lda $0107,x. As exercize as tested also on the lowbyte lda $0106,x.
It worked until, like you, I put it under the kernal: random artifacts all over the place!
But I figured it out: I put it under the kernal with a JSR, which means two more bytes on the stack as return address, which means lda $0107,x shifts and should be $0109,x!
Almost certain that's your issue.
So you had already a solution for the random artifacts: Amazing. Well now you have seen what happens if an IRQ fires between D600 and D601.
Always set the update address like this:
lda #highbyte ldx #$12 jsr $cdcc lda #lowbyte inx jsr $cdcc
The VDC copies the update address to its internal memory when reg $13 is set. So if you set reg $13 first, the value of reg $12 in that moment is copied. The reg $12 you set after reg $13 is left unused until the moment you set reg $13 again. But maybe it doesn't work like this in an emulator.
|
|