;-----------------------------------------------------------------------------
; 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