Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

//c VBL Polling

190 views
Skip to first unread message

Oliver Schmidt

unread,
Jun 15, 2020, 3:00:11 PM6/15/20
to
Hi,

My //e code to wait for a "fresh" VBL looks like this:

wait:
1: bit $C019
bpl 1
2: bit $C019
bmi 2
rts

After reading 'Apple IIgs TechNote #40, VBL Signal' my IIgs code looks like this:

wait:
1: bit $C019
bmi 1
2: bit $C019
bpl 2
rts

After reading 'Apple IIc TechNote #9, Detecting VBL' my //c code looks like this:

init:
sei
sta $C07F
bit $C05B
rts

done:
sta $C07F
bit $C05A
cli
rts

wait:
bit $C070
1: bit $C019
bpl 1
rts

So as far as I understand I have to enable VBL interrupts to get the flag I want to poll. But I don't want the overhead of VBL interrupts so I mask IRQs at the CPU.

My questions are:

1. Is there another, "cleaner" way to archive this result on the //c?

2. I understand that masking IRQs "breaks" serial I/O, mouse handling and keyboard typeahead (?). Is there anything else I break I'm not aware of?

3. Is it safe to do the CLI right after the $C05A access? Or could an IRQ still by "stuck somewhere" and get delivered to the CPU after the CLI? If that could happen: Is there some "default" handler for VBL interrupts? Or can my code rather result in an "unclaimed interrupt" which after 255(?) times makes ProDOS panic?

As always thanks for hints,
Oliver

qkumba

unread,
Jun 15, 2020, 6:21:08 PM6/15/20
to
I don't know for (1) and (2), but for (3), here's what I wrote for Total Replay:

iUnwaitForVBL
- bit $C019
bpl -
lda $C070 ; $c019 bit 7 is sticky, reset it
sta $C07F ; enable access to VBL register
sta $C05A ; disable VBL polling
sta $C07E ; disable access to VBL register
cli
rts

So I'm waiting for VBL to trigger before the IRQ is dropped and then I don't get surprised.

qkumba

unread,
Jun 15, 2020, 6:34:02 PM6/15/20
to
Oh, and as I understand things, your wait has the $C070 in the wrong place. $C070 resets the bit so it should be accessed after $C019 goes high, not before, otherwise there won't be another IRQ triggered because the existing one will still appear to be pending.

Oliver Schmidt

unread,
Jun 16, 2020, 3:27:16 AM6/16/20
to
Hi qkumba,

First of all thanks for your quick and helpful reply :-)

> I don't know for (1) and (2), but for (3), here's what I wrote for Total Replay:
[...]

So you're running with the IRQ mask set all the time too - good to know...

> So I'm waiting for VBL to trigger before the IRQ is dropped and then I don't get surprised.

I see, thanks for the hint!

Regards,
Oliver

Oliver Schmidt

unread,
Jun 16, 2020, 3:43:28 AM6/16/20
to
Hi qkumba,

> Oh, and as I understand things, your wait has the $C070 in the wrong place. $C070 resets the bit so it should be accessed after $C019 goes high, not before, otherwise there won't be another IRQ triggered because the existing one will still appear to be pending.

Hm, it rather seems different to me. With your...

1: bit $C019
bpl 1
bit $C070
rts

...the idea is: "When I come too late for the begin of the VBL, then don't wait at all because I have to catch up." but with my...

bit $C070
1: bit $C019
bpl 1
rts

...the idea is: "When I come too late for the begin of the VBL, then wait for the next one to make sure to have a full VBL cycle ahead of me on return."

If I had to choose one idea over the other without knowing the actual use case I'd opt for mine because the usual //e code...

1: bit $C019
bpl 1
2: bit $C019
bmi 2
rts

...behaves like my //c code so the behavior is more consistent across the different machines.

Or did I get something completely wrong?

Regards,
Oliver

remy gibert

unread,
Jun 16, 2020, 7:14:59 AM6/16/20
to
Here is what i do in A2osX:

>PUSHWI MSG.CPU.SPEED
>PUSHBI 0
>SYSCALL2 printf

stz A2osX.RANDOM16
stz A2osX.RANDOM16+1

php
sei

clc
lda MACHID
and #MACHID.T
eor #MACHID.T.IIc
bne .1

sec
.1 ror ZPPtr1 save //c flag

bpl .11

sta CLRIOUDIS
lda IO.IIC.RDVBLMSK
sta ZPPtr1+1 Save VBLIRQ enable

sta IO.IIC.ENVBL

.11 bit VBL
bpl .11

bit ZPPtr1 //c ?
bpl .2

lda IO.IIC.CLRVBLIRQ yes, clear IRQ

.2 lda VBL
bmi .2

ldx #2

.20 bit ZPPtr1 //c ?
bpl .3

lda IO.IIC.CLRVBLIRQ yes, clear IRQ
lda #0 wait for UP again

.3 pha (3)
pla (4)
pha (3)
pla (4)

nop (2)
nop (2)
nop (2)

inc A2osX.RANDOM16 (6)
bne .5 (2*)

inc A2osX.RANDOM16+1 (6)

bra .6 (3)

.5 nop (2)
nop (2)
nop (2)

bra .6 (3)

.6 eor VBL (4)
bpl .3 (2*)

dex
bne .20

bit ZPPtr1 //c ?

bpl .60

lda IO.IIC.CLRVBLIRQ yes, clear IRQ

bit ZPPtr1+1 Disable VBLIRQ ?
bpl .60

sta IO.IIC.DISVBL

.60 stz A2osX.CPUSPEED

.7 sec
lda A2osX.RANDOM16
sbc #100
tax
lda A2osX.RANDOM16+1
sbc /100
bcc .8

stx A2osX.RANDOM16
sta A2osX.RANDOM16+1
inc A2osX.CPUSPEED
bra .7

.8 lda A2osX.RANDOM16
sta A2osX.CPUSPEED+1

plp

>PUSHWI MSG.CPU.SPEEDOK
lda A2osX.CPUSPEED
>PUSHA push CPU speed HI
lda A2osX.CPUSPEED+1
>PUSHA push CPU speed LO
>PUSHBI 2
>SYSCALL2 printf

remy gibert

unread,
Jun 16, 2020, 7:16:35 AM6/16/20
to
Where :

*--------------------------------------
IO.IIC.RDVBLMSK .EQ $C041 R, B7=1: VBL interrupts enabled
*--------------------------------------
IO.IIC.DISVBL .EQ $C05A W, Disable VBL interrupts
IO.IIC.ENVBL .EQ $C05B W, Enable VBL interrupts
IO.IIC.CLRVBLIRQ .EQ $C070 R, Clear the VBL interrupt condition

Antoine Vignau

unread,
Jun 16, 2020, 3:17:57 PM6/16/20
to
Arnaud French Touch Cocquière's code for VBL is great and clear and easy understandable. Jordan Mechner's for PoP (or Karateka) is also very readable.

The IIc has no VBL thing à la IIe IIgs so you have to add a couple of things to "simulate it".

Good luck,
Antoine

Oliver Schmidt

unread,
Jun 16, 2020, 5:21:30 PM6/16/20
to
Hi Antoine,

> Arnaud French Touch Cocquière's code for VBL is great and clear and easy understandable.

I can't find the source. Can you provide me with a link?

> Jordan Mechner's for PoP (or Karateka) is also very readable.

The code seems indeed really very readable - thanks for the hint.

* PoP uses an actual interrupt - which I want to avoid.
* I can't find the Karateka source. Can you provide me with a link?

Regards,
Oliver

Antoine Vignau

unread,
Jun 16, 2020, 6:20:14 PM6/16/20
to
Oliver,

FT: http://fr3nch.t0uch.free.fr/
PoP: you have it, so it was PoP code, not Karateka's which is not available. But no interrupt, no help, I do not know the IIc to help you more, sorry.

Antoine

Oliver Schmidt

unread,
Jun 16, 2020, 6:35:17 PM6/16/20
to
Hi,

Putting all together I learned so far it seems that this all-in-one approach (no init code and no exit code) is preferable as it is least intrusive:

* It sets the CPU IRQ mask only during the actual wait.
* It restores the VBL interrupt mask to the previous state.

RDVBLBAR := $C019 ; >127 if not vertical blanking
RDVBLMSK := $C041 ; >127 if VBL interrupts enabled
DISVBL := $C05A ; Disable VBL interrupts
ENVBL := $C05B ; Enable VBL interrupts
IOUDISON := $C07E ; Disable IOU
IOUDISOFF := $C07F ; Enable IOU

sei
sta IOUDISOFF
lda RDVBLMSK
bit ENVBL
bit PTRIG ; Reset VBL interrupt flag
1: bit RDVBLBAR
bpl 1
asl
bcs 2 ; VBL interrupts were already enabled
bit DISVBL
2: sta IOUDISON ; IIc Tech Ref Man: The firmware normally leaves IOUDIS on.
cli
rts

Regards,
Oliver

Oliver Schmidt

unread,
Jun 16, 2020, 6:59:05 PM6/16/20
to
Hi Antoine,

> FT: http://fr3nch.t0uch.free.fr/

Thanks, pretty interesting!

At least partly related to this thread: I see code to detect 50Hz vs. 60Hz using cycle counting. But I don't find code to set the IIgs to normal speed or to slow down accelerators by accessing $C070 before doing so. Am I just blind or does the code presume the user to have manually set the machine to 1MHz before running a program.

Regards,
Oliver

Brian Patrie

unread,
Jun 16, 2020, 9:16:56 PM6/16/20
to
WTH possessed them to change this in the IIc,IIc+, anyway?
Senseless PITA!

qkumba

unread,
Jun 17, 2020, 3:14:37 PM6/17/20
to
> bit $C070
> 1: bit $C019
> bpl 1
> rts
>
> ...the idea is: "When I come too late for the begin of the VBL, then wait for the next one to make sure to have a full VBL cycle ahead of me on return."

I understand. That's better. I will change TR.

Oliver Schmidt

unread,
Jun 17, 2020, 6:21:54 PM6/17/20
to
Hi,

> > ...the idea is: "When I come too late for the begin of the VBL, then wait for the next one to make sure to have a full VBL cycle ahead of me on return."

> I understand. That's better. I will change TR.

I'm really happy that I could contribute to Total Replay - I appreciate your work very much!

Regards,
Oliver

PS: That "order aspect" is also relevant for iUnwaitForVBL - in fact even more because with the "wrong order" you might run into the very situation you said you wanted to avoid: That an interrupt occurs while cleaning up.

qkumba

unread,
Jun 19, 2020, 12:55:40 AM6/19/20
to
> I'm really happy that I could contribute to Total Replay - I appreciate your work very much!

Thank you for this and thank you for that. It's a good change.

> PS: That "order aspect" is also relevant for iUnwaitForVBL - in fact even more because with the "wrong order" you might run into the very situation you said you wanted to avoid: That an interrupt occurs while cleaning up.

Yes, I realised the same before I checked it in.

cybernesto

unread,
Jul 21, 2020, 11:55:55 AM7/21/20
to
I'm a bit late to the party but I did some interrupt free VBL detection for the //c some time ago for this demo:
https://github.com/cybernesto/F15-DGamma-Clone-A2/commit/488d53094e06c54e1308cb94b34e9d3d02022166#diff-102ef3ff63be5d1a6b40f88512a96100

Maybe it can be of some interest too.

qkumba

unread,
Jul 21, 2020, 4:28:33 PM7/21/20
to
That one has the same issue that I had originally - it can exit too soon if it's late to start checking.

cybernesto

unread,
Jul 22, 2020, 7:09:14 AM7/22/20
to
Oh, now I get it. You are right. I should have read the thread more carefully.
0 new messages