PCEAS_Startup_File

From ArchaicPixels: HuC and PCEAS Documentation

Jump to: navigation, search
;
; STARTUP.INC  -  MagicKit startup code equates and macros
;

; ----
; this block defines names for joypad
; direction and button bits

JOY_I           = $01
JOY_II          = $02
JOY_SEL         = $04
JOY_RUN         = $08
JOY_UP          = $10
JOY_RIGHT       = $20
JOY_DOWN        = $40
JOY_LEFT        = $80

JOY_TYPE6       = $50
JOY_III         = $01
JOY_IV          = $02
JOY_V           = $04
JOY_VI          = $08

JOY_BITI        = $0
JOY_BITII       = $1
JOY_BITSEL      = $2
JOY_BITRUN      = $3
JOY_BITUP       = $4
JOY_BITRT       = $5
JOY_BITDN       = $6
JOY_BITLT       = $7

JOY_BITIII      = $0
JOY_BITIV       = $1
JOY_BITV        = $2
JOY_BITVI       = $3

; ----
; this block defines names for interrupt
; vectors
;
IRQ2            = 0
IRQ1            = 1
TIMER           = 2
NMI             = 3
VSYNC           = 4
HSYNC           = 5
SOFT_RESET      = 6


; ----
; setvec(num, addr)
; ----
; num,  vector number (see defines above)
; addr, address of the new routine
; ----

setvec  .macro
         lda  \1
         ldx  #LOW(\2)
         ldy  #HIGH(\2)
         jsr  set_intvec
        .endm

; ----
; vec_on(num)
; ----
; num, vector to enable
; ----

vec_on  .macro
        .if (\1 = 5)
         smb  #6,<irq_m
        .else
         smb  \1,<irq_m
        .endif
        .endm

; ----
; vec_off(num)
; ----
; num, vector to disable
; ----

vec_off .macro
        .if (\1 = 5)
         rmb  #6,<irq_m
        .else
         rmb  \1,<irq_m
        .endif
        .endm

; ----
; vsync([nb])
; ----
; nb, number of frames to be sync'ed on
; ----

vsync   .macro
        .if (\# = 0)
         lda #1
        .else
         lda \1
        .endif
         jsr  wait_vsync
        .endm


;===================================================================


;
; STARTUP.ASM  -  MagicKit standard startup code
;

; first, set MOUSE to default on:
;
SUPPORT_MOUSE   .equ    1

                .list

                .ifdef HUC
                 .include "huc.inc"      ; HUC
                 .include "huc_opt.inc"
                .endif  ; HUC

                .include  "standard.inc" ; HUCARD


; ----
; setup flexible boundaries for startup code
; and user program's "main".
;
START_BANK      .equ    0
LIB1_BANK       .equ    START_BANK
LIB2_BANK       .equ    START_BANK+1
               .ifdef HUC
FONT_BANK       .equ    START_BANK+1

                .if  (CDROM)
CONST_BANK       .equ   START_BANK+2
DATA_BANK        .equ   START_BANK+3
                .else
PSG_BANK         .equ   START_BANK+2
CONST_BANK       .equ   START_BANK+3
DATA_BANK        .equ   START_BANK+4
                .endif

               .else

; HuC (because of .proc/.endp) does not use MAIN_BANK
MAIN_BANK       .equ    START_BANK+2
               .endif   ; HUC


; ----
; if FONT_VADDR is not specified, then specify it
; (VRAM address to load font into)
;
        .ifndef FONT_VADDR
FONT_VADDR      .equ    $0800
        .endif

; ----
; system variables
;
                .zp
zp_ptr1:        .ds 2


                .bss

        .if  (CDROM)    ; CDROM def's in system.inc

                .include  "system.inc"

        .else           ; ie HuCard

                .org    $2200
user_jmptbl:            ; user interrupt vectors
irq2_jmp:       .ds 2   ; IRQ2 (BRK instruction and external IRQ)
irq1_jmp:       .ds 2   ; IRQ1 (VDC interrupt)
timer_jmp:      .ds 2   ; TIMER
nmi_jmp:        .ds 2   ; NMI (unused)
vsync_hook:     .ds 2   ; VDC vertical sync routine
hsync_hook:     .ds 2   ; VDC horizontal sync rountine

bg_x1:          .ds 2
bg_x2:          .ds 2
bg_y1:          .ds 2
bg_y2:          .ds 2


                .org    $2227
joyena:         .ds 1   ; soft reset enable (bit 0/pad 1, bit 1/pad2, etc.)
joy:            .ds 5   ; 'current' pad values (pad #1-5)
joytrg:         .ds 5   ; 'delta' pad values (new keys hit)
joyold:         .ds 5   ; 'previous' pad values

                .org    $2241
irq_cnt:        .ds 1   ; VDC interrupt counter; increased 60 times per second
                        ; reset to zero when vsync() function called
vdc_mwr:        .ds 1
vdc_dcr:        .ds 1

        .endif

                .org    $2244
scr_mode:       .ds 1   ; screen mode and dimensions - set by <ex_scrmod>
scr_w:          .ds 1
scr_h:          .ds 1

                .org    $2284
soft_reset:     .ds 2   ; soft reset jump loc (run+select)

        .if  !(CDROM)
                .include  "sound.inc"
        .endif

                .org    $2680
vsync_cnt:      .ds 1   ; counter for 'wait_vsync' routine

joybuf:         .ds 5   ; 'delta' pad values collector
joyhook:        .ds 2   ; 'read_joypad' routine hook
joycallback:    .ds 6   ; joypad enhanced callback support
disp_cr:        .ds 1   ; display control (1 = on, 0 = off)
clock_hh        .ds 1   ; system clock, hours since startup (0-255)
clock_mm        .ds 1   ; system clock, minutes since startup (0-59)
clock_ss        .ds 1   ; system clock, seconds since startup (0-59)
clock_tt        .ds 1   ; system clock, ticks (1/60th sec) since startup (0-59)

joy6:           .ds 5   ; second byte for 6-button joysticks
joytrg6:        .ds 5
joyold6:        .ds 5
joybuf6:        .ds 5

joytmp:         .ds 5
joytmp6:        .ds 5

        .if (CDROM)
ovl_running     .ds   1 ; overlay # that is currently running
cd_super        .ds   1 ; Major CDROM version #
irq_storea      .ds   1 ; CDROM IRQ-specific handling stuff
irq_storeb      .ds   1
ram_vsync_hndl  .ds   25
ram_hsync_hndl  .ds   25
        .endif  ; (CDROM)

;±±±[ STARTUP CODE ]±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

; Let's prepare this secondary libray bank first, for use later.
; The reason, as you will see, is because code for a given function
; which sits together in a file, may have things in zero-page,
; bss, LIB1_BANK (ie. START_BANK), and LIB2_BANK.
;
; The assembler must know beforehand what address etc. to use as a basis.
;
        .data
        .bank LIB2_BANK,"Base Library 2/Font"
        .org  $6000
         .include "font.inc"
        .code
        .bank LIB2_BANK
        .org  $A600


        .data
        .bank CONST_BANK,"Constants"

        .data
        .bank DATA_BANK,"User Program"
        .org  $6000
;
; place overlay array here
; 50 entries, each containing
; 2 bytes for start sector,
; 2 bytes for # sectors
;
ovlarray:       .ds     200


        .code
        .bank START_BANK,"Base Library 1"

; A little introduction to the boot sequence:
;
; A HuCard has its origin at bank 0, and is mapped at $E000
; It needs to grab the interrupt vectors at $FFF6 and implement
; implement handlers for them
;
; A CDROM will load at bank $80 ($68 for SCD), and the initial
; loader will be mapped at $4000.  The current MagicKit sequence
; also maps $C000 to this same bank.  However, the initial boot
; sequence will execute at $4070, proceeding to load additional
; code and data, and then jump to a post-boot section called
; 'init_go'.  This is the point at which the loader explicitly
; relinquishes the $4000 segment.  It should be noted that there
; are library subroutines loaded as part of this initial segment,
; and those routines are located in the $C000 range as well.
;
; Sectors are loaded, up to and including the first "DATA_BANK",
; where the overlay array is stored - so that the CDROM error
; overlay can be located and executed in the event of a CDROM
; system version mismatch (ie. playing SCD games on CDROM)
;
; A second entry point is defined for overlays that are not
; being booted (ie. they are loaded and executed from another
; overlay).  This entry point is at $4000, after the segments
; have all found their natural loading spots (ie. segment $68
; for Super CDROMs).  This entry point maps the necessary
; segments and resets the stack, without clearing memory or
; performing other setup chores, and then maps and executes
; _main() to run the module.  The user has no choice regarding
; this function, although he can pass values through the global
; variables which main() can use to decide what to do next.
;
; An additional "Hook" area has now been defined at $4028,
; which is used at initial load time, in case a SCD overlay
; program is run on plain CDROM hardware, and the author
; wishes to override the default text error message by
; loading and executing a plain CDROM program instead
;
    ; ----
    ; interrupt vectors

       .if !(CDROM)
        .org  $FFF6

        .dw _irq2
        .dw _irq1
        .dw _timer
        .dw _nmi
        .dw _reset
       .endif   ; !(CDROM)

    ; ----
    ; develo startup code

       .if (DEVELO)
        .org $6000

        sei
        map  _reset
        jmp  _reset
_restart:
        cla             ; map the CD-ROM system bank
        tam   #7
        jmp   $4000     ; back to the Develo shell
       .endif   ; (DEVELO)


; ----
; reset
; ----
; things start here
; ----

    ; ----
    ; CDROM re-map library bank
    ;
;
; overlay entry point
;
; assume MMR0, MMR1, MMR6, MMR7 are set.
; set others & reset stack pointer
;
       .if (CDROM)
        .org $C000

; current overlay number that is running
; this is overwritten by the isolink prgram; the load
; statement must be the first in the block
;
ovlentry:
        lda  #1
        sta  ovl_running

        lda  #CONST_BANK+_bank_base
        tam  #2
        lda  #DATA_BANK+_bank_base
        tam  #3
        lda  #_call_bank
        tam  #4

        stw  #$4000,<__sp
        ldx  #$ff
        txs

        map  _main
        jsr  _main
        bra  *

;
; CDROM error message alternate load entry point
;
        .org  $4028

cderr_override:         .db     0
cderr_overlay_num:      .db     0

cdrom_err_load:

        ; since CDROM program will load into same area in RAM,
        ; this load routine must be executed from scratch RAM
        ; re-use the ram interrupt handler areas (not yet initialized)

        tii     .load_cd_ovl, ram_vsync_hndl, 64
        jmp     ram_vsync_hndl

.load_cd_ovl:
        lda     cderr_overlay_num
        asl     A
        asl     A
        tay
        lda     #DATA_BANK+$80
        tam     #3
        ldx     ovlarray,Y++
        lda     ovlarray,Y++
        stz     <_cl            ; sector (offset from base of track)
        sta     <_ch
        stx     <_dl
        lda     ovlarray,Y
        sta     <_al            ; # sectors
        lda     #$80
        sta     <_bl            ; bank #
        lda     #3
        sta     <_dh            ; MPR #
        jsr     cd_read
        cmp     #0
        bne     .error
        lda     #$80
        tam     #2
        jmp     _boot

.error: jmp     cd_boot         ; Can't load - reboot CDROM system card


;
; Proper Boot-time entry point
;
        .org  $4070
_boot:
        stz   $2680             ; clear program RAM
        tii   $2680,$2681,$197F

;
; Note: All CDROM boot loaders will load into MMR $80 region
;       regardless of whether they are CD or SCD.
;       Here, we will move the information to occupy
;       base memory at MMR $68 if appropriate
;
        .if (CDROM = SUPER_CD)
         jsr   ex_getver        ; check if SCD program running
         stx   cd_super         ; on SCD hardware
         cpx   #3               ; don't copy to _bank_base if
         bne   .nocopy          ; memory doesn't exist there

         lda   #_bank_base+1    ; copy bank 2 to proper location
         tam   #6
         tii   $6000,$C000,$2000
         tam   #3               ; FONT_BANK now lives in SCD area ($69 exactly)
         lda   #_bank_base      ; then copy bank 1
         tam   #6
         tii   $4000,$C000,$2000 ; then load rest of program
.nocopy:
        .endif  ; (CDROM = SUPER_CD)

       .else            ; (ie. if HuCard...)

        .org  $E010
_reset:
        sei                     ; disable interrupts
        csh                     ; select the 7.16 MHz clock
        cld                     ; clear the decimal flag
        ldx   #$FF              ; initialize the stack pointer
        txs
        lda   #$FF              ; map the I/O bank in the first page
        tam   #0
        lda   #$F8              ; and the RAM bank in the second page
        tam   #1
        stz   $2000             ; clear all the RAM
        tii   $2000,$2001,$1FFF

       .endif   ; (CDROM)

    ; ----
    ; initialize the hardware

_init:
       .if (CDROM)
        jsr   ex_dspoff
        jsr   ex_rcroff
        jsr   ex_irqoff
        jsr   ad_reset
       .else
        stz   timer_ctrl        ; init timer
       .endif   ; (CDROM)

        jsr   init_psg          ; init sound
        jsr   init_vdc          ; init video
        lda   #$1F              ; init joypad
        sta   joyena

    ; ----
    ; initialize interrupt vectors

       .if  (CDROM)
        jsr   ex_dspon
        jsr   ex_rcron
        jsr   ex_irqon
       .else

        ldx   #4                ; user vector table
        cly
.l2:    lda   #LOW(_rti)
        sta   user_jmptbl,Y
        iny
        lda   #HIGH(_rti)
        sta   user_jmptbl,Y
        iny
        dex
        bne   .l2

        stw   #_reset,soft_reset ; soft reset
        stw   #_rts,vsync_hook   ; user vsync routine
        stw   #_rts,hsync_hook   ; user hsync routine

        lda   #$01               ; enable interrupts
        sta   irq_disable
        stz   irq_status
        cli

    ; ----
    ; enable display and VSYNC interrupt

        vreg  #5
        lda   #$C8
        sta  <vdc_crl
        sta   video_data_l
        st2   #$00
        lda   #$01
        sta   disp_cr

       .endif   ; (CDROM)

    ; ----
    ; init TIA instruction in RAM (fast BLiTter to hardware)

        lda   #$E3              ; TIA instruction opcode
        sta   _ram_hdwr_tia
        lda   #$60              ; RTS instruction opcode
        sta   _ram_hdwr_tia_rts

    ; ----
    ; init random number generator

        lda   #1
        jsr   wait_vsync        ; wait for one frame & randomize _rndseed
        stw   #$03E7,<_cx       ; set random seed
        stw   _rndseed,<_dx
        jsr   srand

       .if (CDROM)
        .if (CDROM = SUPER_CD)
         lda   cd_super         ; don't load the program if SCD
         cmp   #3               ; program not running on SCD hrdware
         beq   loadprog
         lda   cderr_override
         lbeq  dontloadprog
         jmp   cdrom_err_load
        .endif  ; (SUPER_CD)

    ; ----
    ; load program
    ; ----
    ; CL/CH/DL = sector address
    ; DH = load mode - bank mode ($6000-$7FFF)
    ; BL = bank index
    ; AL = number of sectors
    ;
loadprog:
        lda   ovlentry+1        ; current overlay (as written by ISOLINK)
        cmp   #1                ; is it initial overlay ?
        lbne  _init_go          ; if not initial overlay, somebody else already
                                ; loaded us completely; do not try to load remainder
                                ; (ie. executing CDROM error overlay)

        stz   <_cl              ; initial boot doesn't load complete program;
        stz   <_ch              ; prepare to load remainder
        lda   #10               ; 10th sector (0-1 are boot;
                                ; 2-9 are this library...)
        sta   <_dl
        lda   #3                ; load mode (consecutive banks; use MPR 3)
        sta   <_dh
        stw   #(_bank_base+2),<_bx      ; 2 banks are boot/base library
        stw   #(_nb_bank-2)*4,<_ax
        jsr   cd_read
        cmp   #$00
        lbeq  _init_go

        ; ----
        jmp   cd_boot           ; reset


; This is the point in the CDROM loader where the code no longer
; executes in the $4000 segment, in favour of using the $C000
; segment (also used for the library subroutines)

       .org   $C130


; These routines will be run from RAM @ $2000 so we
; need to count bytes to determine how much to xfer
; (The total is 24 bytes, but we copy 25)

        .bank   LIB2_BANK

vsync_irq_ramhndlr:
        php                     ; 1 byte
        pha                     ; 1
        tma   #6                ; 2
        sta   irq_storea        ; 3
        lda   #BANK(_vsync_hndl) ;  2
        tam   #6                ; 2
        pla                     ; 1
        pha                     ; 1
        jsr   _vsync_hndl       ; 3
        lda   irq_storea        ; 3
        tam   #6                ; 2
        pla                     ; 1
        plp                     ; 1
        rts                     ; 1 = 24 bytes

hsync_irq_ramhndlr:
        php                     ; 1 byte
        pha                     ; 1
        tma   #6                ; 2
        sta   irq_storeb        ; 3
        lda   #BANK(_hsync_hndl) ;  2
        tam   #6                ; 2
        pla                     ; 1
        pha                     ; 1
        jsr   _hsync_hndl       ; 3
        lda   irq_storeb        ; 3
        tam   #6                ; 2
        pla                     ; 1
        plp                     ; 1
        rts                     ; 1 = 24 bytes

        .bank   LIB1_BANK

_init_go:
        .if (CDROM = SUPER_CD)
dontloadprog:
        .endif

       .endif   ; (CDROM)

    ; ----
    ; jump to main routine

    ; ----
    ; load font

       .ifdef HUC
        stw   #$4000,<__sp      ; init stack ptr first

        stw   #FONT_VADDR,<_di  ; Load Font @ VRAM addr

        ;
        ; this section of font loading was stolen
        ; from _load_default_font because the default
        ; FONT segment number is not yet guaranteed
        ; if the SCD is being run on a plain CDROM system
        ; so we need to trick the segment pointer
        ; with a reliable one
        ;
      __ldw   <_di      ; stolen from _load_default_font
                        ; because segment# default not reliable

        jsr   _set_font_addr            ; set VRAM

       .if  (CDROM)
        stb   #FONT_BANK+$80,<_bl       ; guarantee FONT_BANK even if
                                        ; SCD on regular CDROM system
       .else
        stb   #FONT_BANK+_bank_base,<_bl
       .endif

        stb   #96,<_cl
        stb   _font_color+1,<_ah
        lda   _font_color
        bne   .fntld
        inc   A
.fntld: sta   <_al
        clx
        lda   font_table,X
        sta   <_si
        inx
        lda   font_table,X
        sta   <_si+1


        ; Now, load the font
        ;
        ;   Note for CDROM/Super CDROM:
        ;
        ; The 'REAL' mapping for the lib2_load_font function
        ; maybe doesn't exist yet (we are executing from bank $80,
        ; not from $68 if it's a Super CDROM)
        ;
        ; So we must map the version at bank ($80 + LIB2_BANK)
        ; before executing it.  We remap the bank after completion,
        ; 'just in case'

       .if  (CDROM)
        tma   #page(lib2_load_font)
        pha
        lda   #LIB2_BANK+$80
        tam   #page(lib2_load_font)
        jsr   lib2_load_font
        pla
        tam   #page(lib2_load_font)
       .else
        jsr   load_font
       .endif

        ;
        ; END stolen font-load
        ;

        jsr   _cls

        stz  color_reg  ; set color #0 = 0/0/0 rgb
        stz  color_reg+1
        stz  color_data
        stz  color_data+1

        lda  #1         ; set color #1 = 7/7/7 rgb
        sta  color_reg
        stz  color_reg+1
        ldx  #$ff
        stx  color_data
        sta  color_data+1

    ; ----
    ; Super CDROM error message
    ; ----

        .if (CDROM)
         .if (CDROM = SUPER_CD)
          lda  cd_super
          cmp  #3
          lbeq  .ok     ; SCD running on Super system

          lda     #FONT_BANK+$80        ; guarantee FONT_BANK even if
                                        ; SCD on regular CDROM system
          tam     #PAGE(scdmsg1)

          __ldwi  scdmsg1
          __phw   2,2
          __ldwi  $0180
          call    _put_string.2

          __ldwi  scdmsg2
          __phw   2,2
          __ldwi  $0200
          call    _put_string.2

          __ldwi  scdmsg3
          __phw   2,2
          __ldwi  $0383
          call    _put_string.2

          __ldwi  scdmsg4
          __phw   2,2
          __ldwi  $0403
          call    _put_string.2

          bra  *                ; otherwise loop on blank screen

          .bank LIB2_BANK

scdmsg1:  .db  "This game was written for the"
          .db  0
scdmsg2:  .db  "PC Engine Super CDROM System"
          .db  0
scdmsg3:  .db  "Please use a PC Engine"
          .db  0
scdmsg4:  .db  "Super CDROM System card"
          .db  0

          .bank LIB1_BANK

.ok:
         .endif         ; (CDROM = SUPER_CD)

        .endif          ; (CDROM)
       .endif           ; (HUC)


       .ifdef SUPPORT_MOUSE
        jsr  mousinit           ; check existence of mouse
       .endif   ; SUPPORT_MOUSE

       .if  (CDROM)

; Now, install the RAM-based version of the
; interrupt-handlers and activate them

        tma   #page(vsync_irq_ramhndlr)
        pha
        lda   #bank(vsync_irq_ramhndlr)
        tam   #page(vsync_irq_ramhndlr)
        tii   vsync_irq_ramhndlr,ram_vsync_hndl,25
        tii   hsync_irq_ramhndlr,ram_hsync_hndl,25
        pla
        tam   #page(vsync_irq_ramhndlr)

        stw   #ram_vsync_hndl,vsync_hook        ; set VSYNC handler
        smb   #4,<irq_m         ; enable new code
        smb   #5,<irq_m         ; disable system card code

        stw   #ram_hsync_hndl,hsync_hook        ; set HSYNC handler
        smb   #6,<irq_m         ; enable new code
        smb   #7,<irq_m         ; disable system card code

       .endif   ; (CDROM)

       .ifdef HUC
    ; ----
    ; Map the final stuff before executing main()
    ; ----

        lda   #CONST_BANK+_bank_base    ; map string constants bank
        tam   #2                ; (ie. $4000-$5FFF)
        lda   #_call_bank       ; map call bank
        tam   #4                ; (ie. $8000-$9FFF)
        ; ---
        .if   (CDROM)
        lda   #1                ; first overlay to run at boot time
        sta   ovl_running       ; store for later use
        .endif
        ; ---
        stz   clock_hh          ; clear clock
        stz   clock_mm
        stz   clock_ss
        stz   clock_tt

        map   _main
        jsr   _main             ; go!
        bra   *
       .else
        map   main
        jmp   main
       .endif   ; HUC


; ----
; system
; ----
; give back control to the Develo system
; ----

       .if (DEVELO)
_system:
        sei
        csh
        cld
        ldx   #$FF      ; stack
        txs
        lda   #$FF      ; I/O bank
        tam   #0
        lda   #$F8      ; RAM bank
        tam   #1
        lda   #$80      ; Develo Bank
        tam   #2
        tma   #7        ; startup code bank
        tam   #3

    ; ----
    ; re-initialize the machine
    ;
        stz   $2000             ; clear RAM
        tii   $2000,$2001,$1FFF
        stz   timer_ctrl        ; init timer
        jsr   init_psg          ; init sound
        jsr   init_vdc          ; init video
        lda   #$1F              ; init joypad
        sta   joyena
        lda   #$07              ; set interrupt mask
        sta   irq_disable
        stz   irq_status                ; reset timer interrupt
        lda   #$80              ; disable sound driver
        sta   <$20E7
        st0   #5                ; enable display and vsync interrupt
        lda   #$C8
        sta  <vdc_crl
        sta   video_data_l
        jmp   _restart          ; restart
       .endif   ; (DEVELO)

;±±±[ INTERRUPT CODE ]±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

_rts:
        rts
_rti:
        rti

; ----
; irq2
; ----
; IRQ2 interrupt handler
; ----

       .if !(CDROM)
_irq2:
        bbs0 <irq_m,.user
        rti
.user:
        jmp   [irq2_jmp]
       .endif   ; !(CDROM)

; ----
; irq1
; ----
; VDC interrupt handler
; ----

       .if !(CDROM)

_irq1:
        bbs1 <irq_m,user_irq1   ; jump to the user irq1 vector if bit set
        ; --
        pha                     ; save registers
        phx
        phy
        ; --
        lda   video_reg         ; get VDC status register
        sta  <vdc_sr            ; save a copy

    ; ----
    ; vsync interrupt
    ;
.vsync:
        bbr5 <vdc_sr,.hsync
        ; --
        inc   irq_cnt           ; increment IRQ counter
        ; --
        st0   #5                ; update display control (bg/sp)
        lda  <vdc_crl
        sta   video_data_l
        ; --
        bbs5 <irq_m,.l3
        ; --
        jsr  _vsync_hndl
        ; --
.l3:    bbr4 <irq_m,.l4
        jsr  user_vsync         ; call user vsync routine
.l4:
    ; ----
    ; hsync interrupt
    ;
.hsync:
        bbr2 <vdc_sr,.exit
        bbs7 <irq_m,.l5
        ; --
        jsr  _hsync_hndl
        ; --
.l5:    bbr6 <irq_m,.exit
        jsr  user_hsync         ; call user handler

    ; ----
    ; exit interrupt
    ;
.exit:
        lda  <vdc_reg           ; restore VDC register index
        sta   video_reg
        ; --
        ply
        plx
        pla
        rti

    ; ----
    ; user routine hooks
    ;
user_irq1:
        jmp   [irq1_jmp]
user_hsync:
        jmp   [hsync_hook]
user_vsync:
        jmp   [vsync_hook]

       .endif   ; !(CDROM)


; ----
; _vsync_hndl
; ----
; Handle VSYNC interrupts
; ----
_vsync_hndl:
       .if  !(CDROM)
        ldx   disp_cr           ; check display state (on/off)
        bne  .l1
        and   #$3F              ; disable display
        st0   #5                ; update display control (bg/sp)
        sta   video_data_l
        bra  .l2
        ; --
       .endif
.l1:    jsr   rcr_init          ; init display list

.l2:    st0   #7                ; scrolling
        stw   bg_x1,video_data
        st0   #8
        stw   bg_y1,video_data

        ; --
        lda   clock_tt          ; keep track of time
        inc   A
        cmp   #60
        bne   .lcltt
        lda   clock_ss
        inc   A
        cmp   #60
        bne   .lclss
        lda   clock_mm
        inc   A
        cmp   #60
        bne   .lclmm
        inc   clock_hh
        cla
.lclmm: sta   clock_mm
        cla
.lclss: sta   clock_ss
        cla
.lcltt: sta   clock_tt
        ; --

       .if  (CDROM)
        jsr   ex_colorcmd
        inc   rndseed
        jsr   randomize
        lda   <$e7
        cmp   #$01
        bne  .skip_psg
        jsr   psg_driver
.skip_psg:
       .endif

       .ifdef SUPPORT_MOUSE
        lda   msflag            ; if mouse supported, and exists
        beq  .l3                ; then read mouse instead of pad
        jsr   mousread
        bra  .out
       .endif   ; SUPPORT_MOUSE

.l3:    jsr   read_joypad       ; else read joypad
.out:   rts


; ----
; _hsync_hndl
; ----
; Handle HSYNC interrupts
; ----
    ; ----
    ; hsync scrolling handler
    ;
_hsync_hndl:
        ldy   s_idx
        bpl  .r1
        ; --
        lda  <vdc_crl
        and   #$3F
        sta  <vdc_crl
        stz   s_idx
        ldx   s_list
        lda   s_top,X
        jsr   rcr5
        rts
        ; --
.r1:    ldx   s_list,Y
        lda  <vdc_crl
        and   #$3F
        ora   s_cr,X
        sta  <vdc_crl
        ; --
        jsr   rcr_set
        ; --
        lda   s_top,X
        cmp   #$FF
        beq  .out
        ; --
        st0   #7
        lda   s_xl,X
        ldy   s_xh,X
        sta   video_data_l
        sty   video_data_h
        st0   #8
        lda   s_yl,X
        ldy   s_yh,X
        sub   #1
        bcs  .r2
        dey
.r2:    sta   video_data_l
        sty   video_data_h
.out:   rts

    ; ----
    ; init display list
    ;
rcr_init:
        maplibfunc   build_disp_list
        bcs  .r3
        rts
        ; --
.r3:    smb   #7,<vdc_crl
        lda   #$FF
        sta   s_idx
        ldx   s_list
        ldy   s_top,X
        cpy   #$FF
        bne   rcr5
        ; --
        ldy   s_xl,X
        sty   bg_x1
        ldy   s_xh,X
        sty   bg_x1+1
        ldy   s_yl,X
        sty   bg_y1
        ldy   s_yh,X
        sty   bg_y1+1
        stz   s_idx
        bra   rcr5

    ; ----
    ; program scanline interrupt
    ;
rcr_set:
        iny
        sty   s_idx
        lda   s_list,Y
        tay
        lda   s_top,Y
        cmp   scr_height
        bhs   rcr6
        cmp   s_bottom,X
        blo   rcr5
        ; --
        lda   s_bottom,X
rcr4:   dec   A
        pha
        lda   #$F0
        sta   s_bottom,X
        stz   s_cr,X
        dec   s_idx
        pla
        ; --
rcr5:   st0   #6                ; set scanline counter
        add   #64
        sta   video_data_l
        cla
        adc   #0
        sta   video_data_h
        bra   __rcr_on
        ;--
rcr6:   lda   s_bottom,X
        cmp   scr_height
        blo   rcr4
        bra   __rcr_off

; ----
; rcr_on
; ----
; enable scanline interrupt
; ----

  rcr_on:
 _rcr_on:
        lda   #5
        sta  <vdc_reg
__rcr_on:
        st0   #5
        lda  <vdc_crl
        ora   #$04
        sta  <vdc_crl
        sta   video_data_l
        rts

; ----
; rcr_off
; ----
; disable scanline interrupt
; ----

  rcr_off:
 _rcr_off:
        lda   #5
        sta  <vdc_reg
__rcr_off:
        st0   #5
        lda  <vdc_crl
        and   #$FB
        sta  <vdc_crl
        sta   video_data_l
        rts



; ----
; timer
; ----
; timer interrupt handler
; ----

       .if  !(CDROM)
_timer_user:
        jmp   [timer_jmp]
_timer:
        bbs2 <irq_m,_timer_user
        pha
        phx
        phy

        sta   irq_status        ; acknowledge interrupt

        lda   <psg_irqflag      ; is IRQ being serviced ?
        bne   .exit

        inc   <psg_irqflag      ; IRQ being serviced
        cli                     ; but allow other interrupts to be processed

        lda   <psg_inhibit      ; if sound off, don't bother
        bne   .exit2

        bsr   psg_driver        ; do all sound-related stuff

.exit2: stz   <psg_irqflag      ; allow IRQ processing again
.exit:  ply
        plx
        pla
        rti

psg_driver:
        tma   #page(psg_drive)  ; map out the code segment
        pha
        lda   #bank(psg_drive)
        tam   #page(psg_drive)

        tma   #4                ; save data banks
        pha
        tma   #3
        pha

        lda   psg_bank1         ; map PSG data banks
        tam   #3
        lda   psg_bank2
        tam   #4

        jsr   psg_drive

        lda   psg_tempo
        bmi   .noreset

        sta   timer_cnt
        ora   #$80
        sta   psg_tempo

.noreset:
        pla                     ; restore data banks
        tam   #3
        pla
        tam   #4

        pla
        tam   #page(psg_drive)  ; restore code bank
        rts

       .endif   ; !(CDROM)

; ----
; nmi
; ----
; NMI interrupt handler
; ----

       .if  !(CDROM)
_nmi:
        bbs3 <irq_m,.user
        rti
.user:
        jmp   [nmi_jmp]

       .endif   ; !(CDROM)


;±±[ DATA ]±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

; ----
; font
; ----

        .ifdef HUC
font_table:
         .dw font_1
         .dw font_2
         .dw font_1
         .dw font_1

        .endif  ; HUC


;±±[ LIBRARY ]±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

; ----
; standard library
; ----

        .include "library.asm"
        .include "scroll.asm"
        .include "math.asm"

       .ifdef HUC
        .include "huc.asm"
        .include "huc_gfx.asm"
        .include "huc_math.asm"
        .include "huc_bram.asm"
        .include "huc_misc.asm"
       .endif   ; HUC

       .ifdef SUPPORT_MOUSE
        .include "mouse.asm"
       .endif   ; SUPPORT_MOUSE

       .if (CDROM)
        .include "cdrom.asm"
       .else
        .include "sound.asm"
       .endif   ; CDROM

; ----
; disp_on
; ----
; enable display
; ----

       .ifdef HUC
_disp_on:
        ldx   disp_cr
        lda   #1
        sta   disp_cr
        cla
        rts
       .else
 disp_on:
        lda   #1
        sta   disp_cr
        rts
       .endif   ; HUC

; ----
; disp_off
; ----
; disable display
; ----

       .ifdef HUC
_disp_off:
        ldx   disp_cr
        stz   disp_cr
        cla
        rts
       .else
 disp_off:
        stz   disp_cr
        rts
       .endif   ; HUC

; ----
; set_intvec
; ----
; set interrupt vector
; ----
; IN : A = vector number
;           0 IRQ2
;           1 IRQ1 (VDC)
;           2 TIMER
;           3 NMI
;           4 VSYNC
;           5 HSYNC
;           6 SOFT RESET (RUN + SELECT)
;      X = vector address low byte
;      Y =   "      "    high byte
; ----

       .if  !(CDROM)

set_intvec:
        php
        sei
        cmp   #6
        blo  .vector
        bne  .exit
.reset:
        stx   soft_reset
        sty   soft_reset+1
        bra  .exit
.vector:
        pha
        asl   A
        sax
        sta   user_jmptbl,X
        inx
        tya
        sta   user_jmptbl,X
        pla
.exit:
        plp
        rts
       .endif   ; !(CDROM)

; ----
; wait_vsync
; ----
; wait the next vsync
; ----
; IN :  A = number of frames to be sync'ed on
; ----
; OUT:  A = number of elapsed frames since last call
; ----

wait_vsync:
        bbr1 <irq_m,.l1
        cla                     ; return immediately if IRQ1 is redirected
       .ifdef HUC
        clx
       .endif
        rts

.l1:    sei                     ; disable interrupts
        cmp   irq_cnt           ; calculate how many frames to wait
        beq  .l2
        bhs  .l3
        lda   irq_cnt
.l2:    inc   A
.l3:    sub   irq_cnt
        sta   vsync_cnt
        cli                     ; re-enable interrupts

.l4:    lda   irq_cnt           ; wait loop
.l5:    incw  _rndseed
        cmp   irq_cnt
        beq  .l5
        dec   vsync_cnt
        bne  .l4

        stz   irq_cnt           ; reset system interrupt counter
        inc   A                 ; return number of elapsed frames

       .ifndef HUC
        rts
       .else

    ; ----
    ; callback support

        pha
        lda   joycallback       ; callback valid?
        bpl  .t3
        bit   #$01
        bne  .t3

        lda   joycallback+1     ; get events for all the
        beq  .t3                ; selected joypads
        sta  <_al
        cly
        cla
.t1:    lsr  <_al
        bcc  .t2
        ora   joybuf,Y
.t2:    iny
        cpy   #5
        blo  .t1

        and   joycallback+2     ; compare with requested state
        beq  .t3

        inc   joycallback       ; lock callback feature
        tax                     ; call user routine
        tma   #5
        pha
        lda   joycallback+3
        tam   #5
        cla
        jsr  .callback
        pla
        tam   #5
        dec   joycallback       ; unlock
        ; --
.t3:    plx
        cla
        rts

    ; ----
    ; user routine callback
    ;
.callback:
        jmp   [joycallback+4]
       .endif   ; ndef HUC

       .include  "joypad.asm"   ; read joypad values


;±±[ USER PROGRAM ]±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

;       .nomlist
;       .list

        ;...

;       .endif
Personal tools