Apple2: implement get_tv()
get_tv() will return TV_NTSC or TV_PAL for any Apple II model with a way of checking vblank. For Apple ][ and ][+ it will return TV_OTHER and let the user figure it out in another way.
This commit is contained in:
committed by
Oliver Schmidt
parent
96e8e89776
commit
2085646e57
@@ -354,6 +354,7 @@ usage.
|
||||
<item>allow_lowercase
|
||||
<item>beep
|
||||
<item>dir_entry_count
|
||||
<item>get_tv
|
||||
<item>get_ostype
|
||||
<item>gmtime_dt
|
||||
<item>mktime_dt
|
||||
|
||||
@@ -333,6 +333,7 @@ usage.
|
||||
<item>_datetime
|
||||
<item>beep
|
||||
<item>dir_entry_count
|
||||
<item>get_tv
|
||||
<item>get_ostype
|
||||
<item>gmtime_dt
|
||||
<item>mktime_dt
|
||||
|
||||
@@ -98,6 +98,7 @@ function.
|
||||
<item>allow_lowercase
|
||||
<item><ref id="beep" name="beep">
|
||||
<item><ref id="dir_entry_count" name="dir_entry_count">
|
||||
<item><ref id="get_tv" name="get_tv">
|
||||
<item><ref id="get_ostype" name="get_ostype">
|
||||
<item><ref id="gmtime_dt" name="gmtime_dt">
|
||||
<item><ref id="mktime_dt" name="mktime_dt">
|
||||
@@ -111,6 +112,7 @@ function.
|
||||
<item>_dos_type
|
||||
<item><ref id="beep" name="beep">
|
||||
<item><ref id="dir_entry_count" name="dir_entry_count">
|
||||
<item><ref id="get_tv" name="get_tv">
|
||||
<item><ref id="get_ostype" name="get_ostype">
|
||||
<item><ref id="gmtime_dt" name="gmtime_dt">
|
||||
<item><ref id="mktime_dt" name="mktime_dt">
|
||||
@@ -140,7 +142,7 @@ function.
|
||||
<!-- <item><ref id="_setcolor_low" name="_setcolor_low"> -->
|
||||
<item><ref id="_sound" name="_sound">
|
||||
<item><ref id="get_ostype" name="get_ostype">
|
||||
<!-- <item><ref id="get_tv" name="get_tv"> -->
|
||||
<item><ref id="get_tv" name="get_tv">
|
||||
</itemize>
|
||||
|
||||
(incomplete)
|
||||
@@ -227,7 +229,7 @@ function.
|
||||
<!-- <item><ref id="cbm_readdir" name="cbm_readdir"> -->
|
||||
<!-- <item><ref id="cbm_save" name="cbm_save"> -->
|
||||
<!-- <item><ref id="cbm_write" name="cbm_write"> -->
|
||||
<!-- <item><ref id="get_tv" name="get_tv"> -->
|
||||
<item><ref id="get_tv" name="get_tv">
|
||||
<item><ref id="kbrepeat" name="kbrepeat">
|
||||
<item><ref id="waitvsync" name="waitvsync">
|
||||
</itemize>
|
||||
@@ -348,7 +350,7 @@ function.
|
||||
<itemize>
|
||||
<!-- <item><ref id="get_numbanks" name="get_numbanks"> -->
|
||||
<item><ref id="get_ostype" name="get_ostype">
|
||||
<!-- <item><ref id="get_tv" name="get_tv"> -->
|
||||
<item><ref id="get_tv" name="get_tv">
|
||||
<!-- <item><ref id="set_tv" name="set_tv"> -->
|
||||
<!-- <item><ref id="vera_layer_enable" name="vera_layer_enable"> -->
|
||||
<!-- <item><ref id="vera_sprites_enable" name="vera_sprites_enable"> -->
|
||||
@@ -443,7 +445,7 @@ see also <tt>testcode/lib/em-test.c</tt> and <tt>samples/multidemo.c</tt>.
|
||||
<sect1><tt/gamate.h/<label id="gamate.h"><p>
|
||||
|
||||
<itemize>
|
||||
<!-- <item><ref id="get_tv" name="get_tv"> -->
|
||||
<item><ref id="get_tv" name="get_tv">
|
||||
<item><ref id="waitvsync" name="waitvsync">
|
||||
</itemize>
|
||||
|
||||
@@ -550,7 +552,7 @@ see also <tt>testcode/lib/em-test.c</tt> and <tt>samples/multidemo.c</tt>.
|
||||
<sect1><tt/nes.h/<label id="nes.h"><p>
|
||||
|
||||
<itemize>
|
||||
<!-- <item><ref id="get_tv" name="get_tv"> -->
|
||||
<item><ref id="get_tv" name="get_tv">
|
||||
<item><ref id="waitvsync" name="waitvsync">
|
||||
</itemize>
|
||||
|
||||
@@ -568,7 +570,7 @@ It does not declare any functions.
|
||||
<sect1><tt/pce.h/<label id="pce.h"><p>
|
||||
|
||||
<itemize>
|
||||
<!-- <item><ref id="get_tv" name="get_tv"> -->
|
||||
<item><ref id="get_tv" name="get_tv">
|
||||
<item><ref id="waitvsync" name="waitvsync">
|
||||
</itemize>
|
||||
|
||||
@@ -4108,6 +4110,31 @@ be used in presence of a prototype.
|
||||
</quote>
|
||||
|
||||
|
||||
<sect1>get_tv<label id="get_tv"><p>
|
||||
|
||||
<quote>
|
||||
<descrip>
|
||||
<tag/Function/The function returns the system's vertical blank frequency.
|
||||
<tag/Header/<tt/<ref id="apple2.h" name="apple2.h">,
|
||||
<ref id="atari.h" name="atari.h">, <ref id="cbm.h" name="cbm.h">,
|
||||
<ref id="cx16.h" name="cx16.h">, <ref id="gamate.h" name="gamate.h">,
|
||||
<ref id="nes.h" name="nes.h">, <ref id="pce.h" name="pce.h">/
|
||||
<tag/Declaration/<tt/unsigned char get_tv (void);/
|
||||
<tag/Description/<tt/get_tv/ is machine dependent and does not exist for
|
||||
all supported targets. If it exists, it returns a number that identifies the
|
||||
frequency at which the screen vertical blank happens (either 50 or 60Hz),
|
||||
if possible.
|
||||
<tag/Notes/<itemize>
|
||||
<item>The function does not exist on all platforms.
|
||||
<item>Return TV_NTSC for 60Hz systems, TV_PAL for 50Hz systems, or
|
||||
TV_OTHER if the scan frequency can not be determined.
|
||||
</itemize>
|
||||
<tag/Availability/cc65 (not all platforms)
|
||||
<tag/Example/None.
|
||||
</descrip>
|
||||
</quote>
|
||||
|
||||
|
||||
<sect1>get_ostype<label id="get_ostype"><p>
|
||||
|
||||
<quote>
|
||||
|
||||
@@ -122,6 +122,11 @@
|
||||
#define APPLE_IIGS1 0x81 /* Apple IIgs (ROM 1) */
|
||||
#define APPLE_IIGS3 0x83 /* Apple IIgs (ROM 3) */
|
||||
|
||||
/* Return codes for get_tv() */
|
||||
#define TV_NTSC 0
|
||||
#define TV_PAL 1
|
||||
#define TV_OTHER 2
|
||||
|
||||
extern unsigned char _dos_type;
|
||||
/* Valid _dos_type values:
|
||||
**
|
||||
@@ -200,6 +205,9 @@ extern void a2_lo_tgi[];
|
||||
void beep (void);
|
||||
/* Beep beep. */
|
||||
|
||||
unsigned char get_tv (void);
|
||||
/* Get the machine vblank frequency. Returns one of the TV_xxx codes. */
|
||||
|
||||
unsigned char get_ostype (void);
|
||||
/* Get the machine type. Returns one of the APPLE_xxx codes. */
|
||||
|
||||
|
||||
189
libsrc/apple2/get_tv.s
Normal file
189
libsrc/apple2/get_tv.s
Normal file
@@ -0,0 +1,189 @@
|
||||
;
|
||||
; Colin Leroy-Mira <colin@colino.net>, 2025
|
||||
;
|
||||
; unsigned char __fastcall__ get_tv(void)
|
||||
;
|
||||
.export _get_tv
|
||||
|
||||
.import _set_iigs_speed, _get_iigs_speed
|
||||
.import ostype
|
||||
|
||||
.constructor calibrate_tv, 2
|
||||
|
||||
.include "accelerator.inc"
|
||||
.include "apple2.inc"
|
||||
.include "get_tv.inc"
|
||||
|
||||
.segment "ONCE"
|
||||
|
||||
; Cycle wasters
|
||||
waste_72:
|
||||
jsr waste_36
|
||||
waste_36:
|
||||
jsr waste_12
|
||||
waste_24:
|
||||
jsr waste_12
|
||||
waste_12:
|
||||
rts
|
||||
|
||||
.proc calibrate_tv
|
||||
lda ostype
|
||||
bmi iigs
|
||||
cmp #$20
|
||||
bcc iip
|
||||
cmp #$40
|
||||
bcc iie
|
||||
|
||||
iic: jmp calibrate_iic
|
||||
iigs: jmp calibrate_iigs
|
||||
iie: jmp calibrate_iie
|
||||
iip: rts ; Keep TV::OTHER.
|
||||
.endproc
|
||||
|
||||
|
||||
; Magic numbers
|
||||
WASTE_LOOP_CYCLES = 92 ; The wait loop total cycles
|
||||
NTSC_LOOP_COUNT = 17030/WASTE_LOOP_CYCLES ; How many loops expected on NTSC
|
||||
PAL_LOOP_COUNT = 20280/WASTE_LOOP_CYCLES ; How many loops expected on PAL
|
||||
STOP_PTRIG = 16500/WASTE_LOOP_CYCLES ; Stop PTRIG at 16.5ms
|
||||
|
||||
; Carry set at enter: wait for VBL +
|
||||
; Carry clear at enter: wait for VBL -
|
||||
; Increments X every 92 cycles.
|
||||
.proc count_until_vbl_bit
|
||||
lda #$10 ; BPL
|
||||
bcc :+
|
||||
lda #$30 ; BMI
|
||||
: sta sign
|
||||
|
||||
; Wait for VBLsign change with 92 cycles loops.
|
||||
; Hit PTRIG repeatedly so that accelerators will slow down.
|
||||
; But stop hitting PTRIG after 16.5ms cycles, so that on the //c,
|
||||
; the VBLINT will not be reset right before we get it. 16.5ms
|
||||
; is a good value because it's far enough from 17ms for NTSC
|
||||
; models, and close enough to 20.2ms for PAL models that accelerators
|
||||
; will stay slow until there. (5ms usually).
|
||||
|
||||
: cpx #STOP_PTRIG ; 2 - see if we spent 16.5ms already
|
||||
bcs notrig ; 4 / 5 - if so, stop hitting PTRIG
|
||||
sta PTRIG ; 8 - otherwise hit it
|
||||
bcc count ; 11
|
||||
notrig:
|
||||
nop ; 7 - keep cycle count constant when not
|
||||
nop ; 9 - hitting PTRIG
|
||||
nop ; 11
|
||||
count:
|
||||
inx ; 13
|
||||
jsr waste_72 ; 85
|
||||
bit RDVBLBAR ; 89 - Wait for VBL change
|
||||
sign:
|
||||
bpl :- ; 92 - patched with bpl/bmi
|
||||
rts
|
||||
.endproc
|
||||
|
||||
.proc calibrate_iic
|
||||
php
|
||||
sei
|
||||
|
||||
sta IOUDISOFF
|
||||
lda RDVBLMSK
|
||||
pha ; Back up for cleanup
|
||||
|
||||
bit ENVBL
|
||||
bit PTRIG ; Reset VBL interrupt flag
|
||||
: bit RDVBLBAR ; Wait for one VBL
|
||||
bpl :-
|
||||
|
||||
bit PTRIG ; Reset VBL interrupt flag again
|
||||
ldx #$00
|
||||
clc
|
||||
jsr count_until_vbl_bit
|
||||
|
||||
pla ; Cleanup
|
||||
asl
|
||||
bcs :+ ; VBL interrupts were already enabled
|
||||
bit DISVBL
|
||||
: sta IOUDISON ; IIc Tech Ref Man: The firmware normally leaves IOUDIS on.
|
||||
|
||||
plp
|
||||
jmp calibrate_done
|
||||
.endproc
|
||||
|
||||
.proc calibrate_iie
|
||||
: bit RDVBLBAR ; Wait for bit 7 to be off (VBL start)
|
||||
bmi :-
|
||||
: bit RDVBLBAR ; Wait for bit 7 to be on (VBL end)
|
||||
bpl :-
|
||||
|
||||
; Wait and count during a full cycle
|
||||
ldx #$00
|
||||
sec
|
||||
jsr count_until_vbl_bit
|
||||
clc
|
||||
jsr count_until_vbl_bit
|
||||
|
||||
jmp calibrate_done
|
||||
.endproc
|
||||
|
||||
.proc calibrate_iigs
|
||||
; Backup speed and slow down
|
||||
jsr _get_iigs_speed
|
||||
pha
|
||||
lda #SPEED_SLOW
|
||||
jsr _set_iigs_speed
|
||||
|
||||
; The same as IIe, but reverted, because... something?
|
||||
: bit RDVBLBAR ; Wait for bit 7 to be on (VBL start)
|
||||
bpl :-
|
||||
: bit RDVBLBAR ; Wait for bit 7 to be off (VBL end)
|
||||
bmi :-
|
||||
|
||||
; Wait and count during a full cycle
|
||||
ldx #$00
|
||||
clc
|
||||
jsr count_until_vbl_bit
|
||||
sec
|
||||
jsr count_until_vbl_bit
|
||||
|
||||
jsr calibrate_done
|
||||
|
||||
; Restore user speed
|
||||
pla
|
||||
jmp _set_iigs_speed
|
||||
.endproc
|
||||
|
||||
.proc calibrate_done
|
||||
; Consider X +/- 3 to be valid,
|
||||
; anything else is unknown.
|
||||
|
||||
lda #TV::NTSC
|
||||
cpx #NTSC_LOOP_COUNT-3
|
||||
bcc unexpected
|
||||
cpx #NTSC_LOOP_COUNT+3
|
||||
bcc matched
|
||||
|
||||
lda #TV::PAL
|
||||
cpx #PAL_LOOP_COUNT-3
|
||||
bcc unexpected
|
||||
cpx #PAL_LOOP_COUNT+3
|
||||
bcs unexpected
|
||||
|
||||
matched:
|
||||
sta tv
|
||||
|
||||
unexpected:
|
||||
rts
|
||||
.endproc
|
||||
|
||||
.code
|
||||
|
||||
; The only thing remaining from that code after init
|
||||
.proc _get_tv
|
||||
lda tv
|
||||
ldx #>$0000
|
||||
rts
|
||||
.endproc
|
||||
|
||||
.segment "INIT"
|
||||
|
||||
tv: .byte TV::OTHER
|
||||
Reference in New Issue
Block a user