File: STARTUP.S - Tab length: 1 2 4 8 - Lines: on off - No wrap: on off

;-----------------------------------------------------------------------------
; Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! Warning!!!
; Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! Warning!!!
;-----------------------------------------------------------------------------
; Do not change any of the code in this file except where explicitly noted.
; Making other changes can cause your program's startup code to be incorrect.
;-----------------------------------------------------------------------------


;----------------------------------------------------------------------------
; Jaguar Development System Source Code
; Copyright (c)1995 Atari Corp.
; ALL RIGHTS RESERVED
;
; Module: startup.s - Hardware initialization/License screen display
;
; Revision History:
;  1/12/95 - SDS: Modified from MOU.COF sources.
;  2/28/95 - SDS: Optimized some code from MOU.COF.
;  3/14/95 - SDS: Old code preserved old value from INT1 and OR'ed the
;                 video interrupt enable bit. Trouble is that could cause
;                 pending interrupts to persist. Now it just stuffs the value.
;  4/17/95 - MF:  Moved definitions relating to startup picture's size and
;                 filename to top of file, separate from everything else (so
;                 it's easier to swap in different pictures).
;----------------------------------------------------------------------------
; Program Description:
; Jaguar Startup Code
;
; Steps are as follows:
; 1. Set GPU/DSP to Big-Endian mode
; 2. Set VI to $FFFF to disable video-refresh.
; 3. Initialize a stack pointer to high ram.
; 4. Initialize video registers.
; 5. Create an object list as follows:
;            BRANCH Object (Branches to stop object if past display area)
;            BRANCH Object (Branches to stop object if prior to display area)
;            BITMAP Object (Jaguar License Acknowledgement - see below)
;            STOP Object
; 6. Install interrupt handler, configure VI, enable video interrupts,
;    lower 68k IPL to allow interrupts.
; 7. Use GPU routine to stuff OLP with pointer to object list.
; 8. Turn on video.
; 9. Jump to _start.
;
; Notes:
; All video variables are exposed for program use. 'ticks' is exposed to allow
; a flicker-free transition from license screen to next. gSetOLP and olp2set
; are exposed so they don't need to be included by exterior code again.
;-----------------------------------------------------------------------------

    .include    "jaguar.inc"

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Begin STARTUP PICTURE CONFIGURATION -- Edit this to change startup picture
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PPP         .equ    4               ; Pixels per Phrase (1-bit)
BMP_WIDTH       .equ    192             ; Width in Pixels
BMP_HEIGHT      .equ    48              ; Height in Pixels

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Change this macro as necessary. Games published by Atari but created by a
; third-party should use "LICENSED TO" screen. Games published and
; created by a third-party company should use "LICENSED BY" screen.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    .macro license_logo
    .incbin "/jaguar/source/sample.rgb" ; "Jaguar Developer Kit Sample"
;   .incbin "/jaguar/startup/lt_box.rgb"    ; "Licensed To Atari Corp."
;   .incbin "/jaguar/startup/lb_box.rgb"    ; "Licensed By Atari Corp."
    .endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; End of STARTUP PICTURE CONFIGURATION
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; Globals
        .globl  gSetOLP
        .globl  olp2set
        .globl  ticks

        .globl  a_vdb
        .globl  a_vde
        .globl  a_hdb
        .globl  a_hde
        .globl  width
        .globl  height
; Externals
        .extern _start

BMP_PHRASES     .equ    (BMP_WIDTH/PPP)     ; Width in Phrases
BMP_LINES       .equ    (BMP_HEIGHT*2)      ; Height in Half Scanlines
BITMAP_OFF      .equ    (2*8)               ; Two Phrases
LISTSIZE        .equ    5               ; List length (in phrases)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Program Entry Point Follows...

        .text

        move.l  #$70007,G_END       ; big-endian mode
        move.l  #$70007,D_END
        move.w  #$FFFF,VI           ; disable video interrupts

        move.l  #INITSTACK,a7       ; Setup a stack

;       jsr     Interlace           ; modify video regs for interlace mode          

        jsr     InitVideo           ; Setup our video registers.
        jsr     InitLister          ; Initialize Object Display List
        jsr     InitVBint           ; Initialize our VBLANK routine

;;; Sneaky trick to cause display to popup at first VB

        move.l  #$0,listbuf+BITMAP_OFF
        move.l  #$C,listbuf+BITMAP_OFF+4

        move.l  d0,olp2set          ; D0 is swapped OLP from InitLister
        move.l  #gSetOLP,G_PC       ; Set GPU PC
        move.l  #RISCGO,G_CTRL      ; Go!
waitforset:
        move.l  G_CTRL,d0           ; Wait for write.
        andi.l  #$1,d0
        bne     waitforset

        move.w  #$2C7,VMODE         ; Configure Video
       
;boucle:    
;       bra.s   boucle
        jmp     _start          ; Jump to main code

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Procedure: gSetOLP
;            Use the GPU to set the OLP and quit.
;
;    Inputs: olp2set - Variable contains pre-swapped value to stuff OLP with.
;
; NOTE!!!: This code can run in DRAM only because it contains no JUMP's or
;          JR's. It will generate a warning with current versions of MADMAC
;          because it doesn't '.ORG'.
;
        .long
        .gpu
gSetOLP:
        movei   #olp2set,r0         ; Read value to write
        load    (r0),r1

        movei   #OLP,r0             ; Store it
        store   r1,(r0)

        moveq   #0,r0               ; Stop GPU
        movei   #G_CTRL,r1
        store   r0,(r1)
        nop                     ; Two "feet" on the brake pedal
        nop

        .68000
        .bss
        .long

olp2set:        .ds.l   1                   ; GPU Code Parameter

        .text

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Procedure: InitVBint
; Install our vertical blank handler and enable interrupts
;

InitVBint:
        move.l  d0,-(sp)

        move.l  #UpdateList,LEVEL0  ; Install 68K LEVEL0 handler

        move.w  a_vde,d0            ; Must be ODD
        ori.w   #1,d0
        move.w  d0,VI
        move.w  d0,vi_line      ; save it for later, VI is write-only

        move.w  #C_VIDENA,INT1          ; Enable video interrupts

        move.w  sr,d0
        and.w   #$F8FF,d0           ; Lower 68k IPL to allow
        move.w  d0,sr               ; interrupts

        move.l  (sp)+,d0
        rts

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Procedure: Interlace
;            Sets up video signals correctly to enable interlaced video
;            Modifies registers we were told never to touch.
;            Code by Zerosquare of Jagware
;
Interlace:
        move.w  CONFIG, d0
        andi.w  #16, d0
        bne.s   Init60HzI
                                         
        Init50HzI:
        move.w  #0, HC  
        move.w  #1, VC    
        move.w  #624,   VP    
        move.w  #614,   VEB  
        move.w  #619,   VS    
        move.w  #4, VEE  
        move.w  #40,    VBE  
        move.w  #614,   VBB  
        move.w  #850,   HP  
        move.w  #1749,  HS  
        move.w  #787,   HEQ  
        move.w  #600,   HVS  
        move.w  #1709,  HBB
        move.w  #153,   HBE  
        bra.s   done

        Init60HzI:
        move.w  #0, HC  
        move.w  #1, VC  
        move.w  #524,   VP  
        move.w  #512,   VEB  
        move.w  #518,   VS  
        move.w  #5,VEE  
        move.w  #30,VBE  
        move.w  #512,VBB  
        move.w  #844,HP    
        move.w  #1743,HS  
        move.w  #780,HEQ  
        move.w  #595,HVS  
        move.w  #1697,HBB  
        move.w  #118,HBE  

done:       rts
       
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Procedure: InitVideo (same as in vidinit.s)
;            Build values for hdb, hde, vdb, and vde and store them.
;
                       
InitVideo:
        movem.l d0-d6,-(sp)
           
        move.w  CONFIG,d0            ; Also is joystick register
        andi.w  #VIDTYPE,d0          ; 0 = PAL, 1 = NTSC
        beq     palvals

        move.w  #NTSC_HMID,d2
        move.w  #NTSC_WIDTH,d0

        move.w  #NTSC_VMID,d6
        move.w  #NTSC_HEIGHT,d4

        bra     calc_vals
palvals:
        move.w  #PAL_HMID,d2
        move.w  #PAL_WIDTH,d0

        move.w  #PAL_VMID,d6
        move.w  #PAL_HEIGHT,d4

calc_vals:
        move.w  d0,width
        move.w  d4,height

        move.w  d0,d1
        asr     #1,d1               ; Width/2

        sub.w   d1,d2               ; Mid - Width/2
        add.w   #4,d2               ; (Mid - Width/2)+4

        sub.w   #1,d1               ; Width/2 - 1
        ori.w   #$400,d1            ; (Width/2 - 1)|$400
       
        move.w  d1,a_hde
        move.w  d1,HDE

        move.w  d2,a_hdb
        move.w  d2,HDB1
        move.w  d2,HDB2

        move.w  d6,d5
        sub.w   d4,d5
        move.w  d5,a_vdb

        add.w   d4,d6
        move.w  d6,a_vde

        move.w  a_vdb,VDB
        move.w  #$FFFF,VDE
           
        move.l  #0,BORD1            ; Black border
        move.w  #0,BG               ; Init line buffer to black
       
;       move.w  #0,HC
;       move.w  #1,VC

        move.w  #524,VP
       
        movem.l (sp)+,d0-d6
        rts

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; InitLister: Initialize Object List Processor List
;
;    Returns: Pre-word-swapped address of current object list in d0.l
;
;  Registers: d0.l/d1.l - Phrase being built
;             d2.l/d3.l - Link address overlays
;             d4.l      - Work register
;             a0.l      - Roving object list pointer
       
InitLister:
        movem.l d1-d4/a0,-(sp)      ; Save registers
           
        lea     listbuf,a0
        move.l  a0,d2               ; Copy

        add.l   #(LISTSIZE-1)*8,d2      ; Address of STOP object
        move.l  d2,d3           ; Copy for low half

        lsr.l   #8,d2           ; Shift high half into place
        lsr.l   #3,d2
       
        swap    d3          ; Place low half correctly
        clr.w   d3
        lsl.l   #5,d3

; Write first BRANCH object (branch if YPOS > a_vde )

        clr.l   d0
        move.l  #(BRANCHOBJ|O_BRLT),d1  ; $4000 = VC < YPOS
        or.l    d2,d0           ; Do LINK overlay
        or.l    d3,d1
                               
        move.w  a_vde,d4                ; for YPOS
        lsl.w   #3,d4                   ; Make it bits 13-3
        or.w    d4,d1

        move.l  d0,(a0)+
        move.l  d1,(a0)+

; Write second branch object (branch if YPOS < a_vdb)
; Note: LINK address is the same so preserve it

        andi.l  #$FF000007,d1           ; Mask off CC and YPOS
        ori.l   #O_BRGT,d1          ; $8000 = VC > YPOS
        move.w  a_vdb,d4                ; for YPOS
        lsl.w   #3,d4                   ; Make it bits 13-3
        or.w    d4,d1

        move.l  d0,(a0)+
        move.l  d1,(a0)+

; Write a standard BITMAP object

        move.l  d2,d0
        move.l  d3,d1

        ori.l  #BMP_HEIGHT/2<<14,d1       ; Height of image

        move.w  height,d4               ; Center bitmap vertically
        sub.w   #BMP_HEIGHT/2,d4
        add.w   a_vdb,d4
        andi.w  #$FFFE,d4               ; Must be even
        lsl.w   #3,d4
        or.w    d4,d1                   ; Stuff YPOS in low phrase

        move.l  #license,d4
       
        lsl.l   #8,d4
        or.l    d4,d0
   
        move.l  d0,(a0)+
        move.l  d1,(a0)+
        movem.l d0-d1,bmpupdate

; Second Phrase of Bitmap

        move.l  #BMP_PHRASES>>4,d0  ; Only part of top LONG is IWIDTH
        move.l  #O_DEPTH16|O_NOGAP,d1   ; Bit Depth = 16-bit, Contiguous data

        move.w  width,d4                ; Get width in clocks
        lsr.w   #1,d4                   ; /4 Pixel Divisor
        sub.w   #BMP_WIDTH,d4
        lsr.w   #1,d4
        or.w    d4,d1

        ori.l   #((BMP_PHRASES*2)<<18)|(BMP_PHRASES<<28),d1 ; DWIDTH|IWIDTH

        move.l  d0,(a0)+
        move.l  d1,(a0)+

; Write a STOP object at end of list
        clr.l   (a0)+
        move.l  #(STOPOBJ|O_STOPINTS),(a0)+

; Now return swapped list pointer in D0

        move.l  #listbuf,d0
        swap    d0

        movem.l (sp)+,d1-d4/a0
        rts

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Procedure: UpdateList
;        Handle Video Interrupt and update object list fields
;        destroyed by the object processor.

UpdateList:
        movem.l  d0/a0,-(sp)

        move.l  #listbuf+BITMAP_OFF,a0

        move.l  bmpupdate,(a0)          ; Phrase = d1.l/d0.l
        move.l  bmpupdate+4,4(a0)

        add.l   #1,ticks        ; Increment ticks semaphore

        move.w  #$101,INT1          ; Signal we're done
        move.w  #$0,INT2
       
        btst.b  #(11-8),VC      ; we're testing bit 11 (the 12th bit) of VC but...
        bne .bottom         ; btst only works on bytes when operating on memory

        ; top field
        ori.w   #1,vi_line      ; set line next VI will occur on
        move.w  vi_line,VI      ; and set it (VI is write-only)

        bra .done

.bottom:    ; bottom field
        andi.w  #$fffe,vi_line      ; set line next VI will occur on
        move.w  vi_line,VI      ; and set it (VI is write-only)

        add.l   #((BMP_PHRASES)<<11),(a0) ; add IWIDTH to DATA to start one line lower

.done:  

; test de scrolling
;       move.w  bmpupdate+6,d0
;       add.w   #16,d0
;       and.w   #$CFFF,d0
;       move.w  d0,bmpupdate+6
       
        movem.l  (sp)+,d0/a0
        rte

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        .data
        .phrase
license:
        license_logo

        .bss
        .dphrase

listbuf:        .ds.l   LISTSIZE*2          ; Object List
bmpupdate:      .ds.l   2               ; One Phrase of Bitmap for Refresh
ticks:      .ds.l   1           ; Incrementing # of ticks
vi_line:    .ds.w   1           ; VI is write only, so cache it
a_hdb:      .ds.w   1
a_hde:          .ds.w   1
a_vdb:          .ds.w   1
a_vde:          .ds.w   1
width:          .ds.w   1
height:         .ds.w   1

        .end