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

001: ;-----------------------------------------------------------------------------
002: ; Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! Warning!!!
003: ; Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! Warning!!!
004: ;-----------------------------------------------------------------------------
005: ; Do not change any of the code in this file except where explicitly noted.
006: ; Making other changes can cause your program's startup code to be incorrect.
007: ;-----------------------------------------------------------------------------
008: 
009: 
010: ;----------------------------------------------------------------------------
011: ; Jaguar Development System Source Code
012: ; Copyright (c)1995 Atari Corp.
013: ; ALL RIGHTS RESERVED
014: ;
015: ; Module: startup.s - Hardware initialization/License screen display
016: ;
017: ; Revision History:
018: ;  1/12/95 - SDS: Modified from MOU.COF sources.
019: ;  2/28/95 - SDS: Optimized some code from MOU.COF.
020: ;  3/14/95 - SDS: Old code preserved old value from INT1 and OR'ed the
021: ;                 video interrupt enable bit. Trouble is that could cause
022: ;                 pending interrupts to persist. Now it just stuffs the value.
023: ;  4/17/95 - MF:  Moved definitions relating to startup picture's size and
024: ;                 filename to top of file, separate from everything else (so
025: ;                 it's easier to swap in different pictures).
026: ;----------------------------------------------------------------------------
027: ; Program Description:
028: ; Jaguar Startup Code
029: ;
030: ; Steps are as follows:
031: ; 1. Set GPU/DSP to Big-Endian mode
032: ; 2. Set VI to $FFFF to disable video-refresh.
033: ; 3. Initialize a stack pointer to high ram.
034: ; 4. Initialize video registers.
035: ; 5. Create an object list as follows:
036: ;            BRANCH Object (Branches to stop object if past display area)
037: ;            BRANCH Object (Branches to stop object if prior to display area)
038: ;            BITMAP Object (Jaguar License Acknowledgement - see below)
039: ;            STOP Object
040: ; 6. Install interrupt handler, configure VI, enable video interrupts,
041: ;    lower 68k IPL to allow interrupts.
042: ; 7. Use GPU routine to stuff OLP with pointer to object list.
043: ; 8. Turn on video.
044: ; 9. Jump to _start.
045: ;
046: ; Notes:
047: ; All video variables are exposed for program use. 'ticks' is exposed to allow
048: ; a flicker-free transition from license screen to next. gSetOLP and olp2set
049: ; are exposed so they don't need to be included by exterior code again.
050: ;-----------------------------------------------------------------------------
051: 
052:         .include        "jaguar.inc"
053: 
054: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
055: ; Begin STARTUP PICTURE CONFIGURATION -- Edit this to change startup picture
056: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
057: 
058: PPP             .equ    4                       ; Pixels per Phrase (1-bit)
059: BMP_WIDTH       .equ    192                     ; Width in Pixels
060: BMP_HEIGHT      .equ    48                      ; Height in Pixels
061: 
062: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
063: ; Change this macro as necessary. Games published by Atari but created by a
064: ; third-party should use "LICENSED TO" screen. Games published and
065: ; created by a third-party company should use "LICENSED BY" screen.
066: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
067: 
068:         .macro license_logo
069:         .incbin "/jaguar/source/sample.rgb"     ; "Jaguar Developer Kit Sample"
070: ;       .incbin "/jaguar/startup/lt_box.rgb"    ; "Licensed To Atari Corp."
071: ;       .incbin "/jaguar/startup/lb_box.rgb"    ; "Licensed By Atari Corp."
072:         .endm
073: 
074: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
075: ; End of STARTUP PICTURE CONFIGURATION
076: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
077: 
078: ; Globals
079:                 .globl  gSetOLP
080:                 .globl  olp2set
081:                 .globl  ticks
082: 
083:                 .globl  a_vdb
084:                 .globl  a_vde
085:                 .globl  a_hdb
086:                 .globl  a_hde
087:                 .globl  width
088:                 .globl  height
089: ; Externals
090:                 .extern _start
091: 
092: BMP_PHRASES     .equ    (BMP_WIDTH/PPP)         ; Width in Phrases
093: BMP_LINES       .equ    (BMP_HEIGHT*2)          ; Height in Half Scanlines
094: BITMAP_OFF      .equ    (2*8)                   ; Two Phrases
095: LISTSIZE        .equ    5                       ; List length (in phrases)
096: 
097: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Program Entry Point Follows...
098: 
099:                 .text
100: 
101:                 move.l  #$70007,G_END           ; big-endian mode
102:                 move.l  #$70007,D_END
103:                 move.w  #$FFFF,VI               ; disable video interrupts
104: 
105:                 move.l  #INITSTACK,a7           ; Setup a stack
106: 
107: ;               jsr             Interlace                       ; modify video regs for interlace mode                  
108: 
109:                 jsr     InitVideo               ; Setup our video registers.
110:                 jsr     InitLister              ; Initialize Object Display List
111:                 jsr     InitVBint               ; Initialize our VBLANK routine
112: 
113: ;;; Sneaky trick to cause display to popup at first VB
114: 
115:                 move.l  #$0,listbuf+BITMAP_OFF
116:                 move.l  #$C,listbuf+BITMAP_OFF+4
117: 
118:                 move.l  d0,olp2set              ; D0 is swapped OLP from InitLister
119:                 move.l  #gSetOLP,G_PC           ; Set GPU PC
120:                 move.l  #RISCGO,G_CTRL          ; Go!
121: waitforset:
122:                 move.l  G_CTRL,d0               ; Wait for write.
123:                 andi.l  #$1,d0
124:                 bne     waitforset
125: 
126:                 move.w  #$2C7,VMODE             ; Configure Video
127:                
128: ;boucle:        
129: ;               bra.s   boucle
130:         jmp     _start                  ; Jump to main code
131: 
132: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
133: ; Procedure: gSetOLP
134: ;            Use the GPU to set the OLP and quit.
135: ;
136: ;    Inputs: olp2set - Variable contains pre-swapped value to stuff OLP with.
137: ;
138: ; NOTE!!!: This code can run in DRAM only because it contains no JUMP's or
139: ;          JR's. It will generate a warning with current versions of MADMAC
140: ;          because it doesn't '.ORG'.
141: ;
142:                 .long
143:                 .gpu
144: gSetOLP:
145:                 movei   #olp2set,r0             ; Read value to write
146:                 load    (r0),r1
147: 
148:                 movei   #OLP,r0                 ; Store it
149:                 store   r1,(r0)
150: 
151:                 moveq   #0,r0                   ; Stop GPU
152:                 movei   #G_CTRL,r1
153:                 store   r0,(r1)
154:                 nop                             ; Two "feet" on the brake pedal
155:                 nop
156: 
157:                 .68000
158:                 .bss
159:                 .long
160: 
161: olp2set:        .ds.l   1                       ; GPU Code Parameter
162: 
163:                 .text
164: 
165: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
166: ; Procedure: InitVBint
167: ; Install our vertical blank handler and enable interrupts
168: ;
169: 
170: InitVBint:
171:                 move.l  d0,-(sp)
172: 
173:                 move.l  #UpdateList,LEVEL0      ; Install 68K LEVEL0 handler
174: 
175:                 move.w  a_vde,d0                ; Must be ODD
176:                 ori.w   #1,d0
177:                 move.w  d0,VI
178:                 move.w  d0,vi_line              ; save it for later, VI is write-only
179: 
180:                 move.w  #C_VIDENA,INT1          ; Enable video interrupts
181: 
182:                 move.w  sr,d0
183:                 and.w   #$F8FF,d0               ; Lower 68k IPL to allow
184:                 move.w  d0,sr                   ; interrupts
185: 
186:                 move.l  (sp)+,d0
187:                 rts
188: 
189: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
190: ; Procedure: Interlace
191: ;            Sets up video signals correctly to enable interlaced video
192: ;            Modifies registers we were told never to touch.
193: ;            Code by Zerosquare of Jagware
194: ;
195: Interlace:
196:                 move.w  CONFIG, d0
197:                 andi.w  #16, d0
198:                 bne.s   Init60HzI
199:                                                  
200:                 Init50HzI:
201:                 move.w  #0,     HC  
202:                 move.w  #1,     VC    
203:                 move.w  #624,   VP    
204:                 move.w  #614,   VEB  
205:                 move.w  #619,   VS    
206:                 move.w  #4,     VEE  
207:                 move.w  #40,    VBE  
208:                 move.w  #614,   VBB  
209:                 move.w  #850,   HP  
210:                 move.w  #1749,  HS  
211:                 move.w  #787,   HEQ  
212:                 move.w  #600,   HVS  
213:                 move.w  #1709,  HBB
214:                 move.w  #153,   HBE  
215:                 bra.s   done
216: 
217:                 Init60HzI:
218:                 move.w  #0,     HC  
219:                 move.w  #1,     VC  
220:                 move.w  #524,   VP  
221:                 move.w  #512,   VEB  
222:                 move.w  #518,   VS  
223:                 move.w  #5,VEE  
224:                 move.w  #30,VBE  
225:                 move.w  #512,VBB  
226:                 move.w  #844,HP    
227:                 move.w  #1743,HS  
228:                 move.w  #780,HEQ  
229:                 move.w  #595,HVS  
230:                 move.w  #1697,HBB  
231:                 move.w  #118,HBE  
232: 
233: done:           rts
234:                
235: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
236: ; Procedure: InitVideo (same as in vidinit.s)
237: ;            Build values for hdb, hde, vdb, and vde and store them.
238: ;
239:                                                
240: InitVideo:
241:                 movem.l d0-d6,-(sp)
242:                        
243:                 move.w  CONFIG,d0                ; Also is joystick register
244:                 andi.w  #VIDTYPE,d0              ; 0 = PAL, 1 = NTSC
245:                 beq     palvals
246: 
247:                 move.w  #NTSC_HMID,d2
248:                 move.w  #NTSC_WIDTH,d0
249: 
250:                 move.w  #NTSC_VMID,d6
251:                 move.w  #NTSC_HEIGHT,d4
252: 
253:                 bra     calc_vals
254: palvals:
255:                 move.w  #PAL_HMID,d2
256:                 move.w  #PAL_WIDTH,d0
257: 
258:                 move.w  #PAL_VMID,d6
259:                 move.w  #PAL_HEIGHT,d4
260: 
261: calc_vals:
262:                 move.w  d0,width
263:                 move.w  d4,height
264: 
265:                 move.w  d0,d1
266:                 asr     #1,d1                   ; Width/2
267: 
268:                 sub.w   d1,d2                   ; Mid - Width/2
269:                 add.w   #4,d2                   ; (Mid - Width/2)+4
270: 
271:                 sub.w   #1,d1                   ; Width/2 - 1
272:                 ori.w   #$400,d1                ; (Width/2 - 1)|$400
273:                
274:                 move.w  d1,a_hde
275:                 move.w  d1,HDE
276: 
277:                 move.w  d2,a_hdb
278:                 move.w  d2,HDB1
279:                 move.w  d2,HDB2
280: 
281:                 move.w  d6,d5
282:                 sub.w   d4,d5
283:                 move.w  d5,a_vdb
284: 
285:                 add.w   d4,d6
286:                 move.w  d6,a_vde
287: 
288:                 move.w  a_vdb,VDB
289:                 move.w  #$FFFF,VDE
290:                        
291:                 move.l  #0,BORD1                ; Black border
292:                 move.w  #0,BG                   ; Init line buffer to black
293:                
294: ;               move.w  #0,HC
295: ;               move.w  #1,VC
296: 
297:                 move.w  #524,VP
298:                
299:                 movem.l (sp)+,d0-d6
300:                 rts
301: 
302: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
303: ; InitLister: Initialize Object List Processor List
304: ;
305: ;    Returns: Pre-word-swapped address of current object list in d0.l
306: ;
307: ;  Registers: d0.l/d1.l - Phrase being built
308: ;             d2.l/d3.l - Link address overlays
309: ;             d4.l      - Work register
310: ;             a0.l      - Roving object list pointer
311:                
312: InitLister:
313:                 movem.l d1-d4/a0,-(sp)          ; Save registers
314:                        
315:                 lea     listbuf,a0
316:                 move.l  a0,d2                   ; Copy
317: 
318:                 add.l   #(LISTSIZE-1)*8,d2      ; Address of STOP object
319:                 move.l  d2,d3                   ; Copy for low half
320: 
321:                 lsr.l   #8,d2                   ; Shift high half into place
322:                 lsr.l   #3,d2
323:                
324:                 swap    d3                      ; Place low half correctly
325:                 clr.w   d3
326:                 lsl.l   #5,d3
327: 
328: ; Write first BRANCH object (branch if YPOS > a_vde )
329: 
330:                 clr.l   d0
331:                 move.l  #(BRANCHOBJ|O_BRLT),d1  ; $4000 = VC < YPOS
332:                 or.l    d2,d0                   ; Do LINK overlay
333:                 or.l    d3,d1
334:                                                                
335:                 move.w  a_vde,d4                ; for YPOS
336:                 lsl.w   #3,d4                   ; Make it bits 13-3
337:                 or.w    d4,d1
338: 
339:                 move.l  d0,(a0)+
340:                 move.l  d1,(a0)+
341: 
342: ; Write second branch object (branch if YPOS < a_vdb)
343: ; Note: LINK address is the same so preserve it
344: 
345:                 andi.l  #$FF000007,d1           ; Mask off CC and YPOS
346:                 ori.l   #O_BRGT,d1              ; $8000 = VC > YPOS
347:                 move.w  a_vdb,d4                ; for YPOS
348:                 lsl.w   #3,d4                   ; Make it bits 13-3
349:                 or.w    d4,d1
350: 
351:                 move.l  d0,(a0)+
352:                 move.l  d1,(a0)+
353: 
354: ; Write a standard BITMAP object
355: 
356:                 move.l  d2,d0
357:                 move.l  d3,d1
358: 
359:                 ori.l  #BMP_HEIGHT/2<<14,d1       ; Height of image
360: 
361:                 move.w  height,d4               ; Center bitmap vertically
362:                 sub.w   #BMP_HEIGHT/2,d4
363:                 add.w   a_vdb,d4
364:                 andi.w  #$FFFE,d4               ; Must be even
365:                 lsl.w   #3,d4
366:                 or.w    d4,d1                   ; Stuff YPOS in low phrase
367: 
368:                 move.l  #license,d4
369:                
370:                 lsl.l   #8,d4
371:                 or.l    d4,d0
372:        
373:                 move.l  d0,(a0)+
374:                 move.l  d1,(a0)+
375:                 movem.l d0-d1,bmpupdate
376: 
377: ; Second Phrase of Bitmap
378: 
379:                 move.l  #BMP_PHRASES>>4,d0      ; Only part of top LONG is IWIDTH
380:                 move.l  #O_DEPTH16|O_NOGAP,d1   ; Bit Depth = 16-bit, Contiguous data
381: 
382:                 move.w  width,d4                ; Get width in clocks
383:                 lsr.w   #1,d4                   ; /4 Pixel Divisor
384:                 sub.w   #BMP_WIDTH,d4
385:                 lsr.w   #1,d4
386:                 or.w    d4,d1
387: 
388:                 ori.l   #((BMP_PHRASES*2)<<18)|(BMP_PHRASES<<28),d1     ; DWIDTH|IWIDTH
389: 
390:                 move.l  d0,(a0)+
391:                 move.l  d1,(a0)+
392: 
393: ; Write a STOP object at end of list
394:                 clr.l   (a0)+
395:                 move.l  #(STOPOBJ|O_STOPINTS),(a0)+
396: 
397: ; Now return swapped list pointer in D0
398: 
399:                 move.l  #listbuf,d0
400:                 swap    d0
401: 
402:                 movem.l (sp)+,d1-d4/a0
403:                 rts
404: 
405: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
406: ; Procedure: UpdateList
407: ;        Handle Video Interrupt and update object list fields
408: ;        destroyed by the object processor.
409: 
410: UpdateList:
411:                 movem.l  d0/a0,-(sp)
412: 
413:                 move.l  #listbuf+BITMAP_OFF,a0
414: 
415:                 move.l  bmpupdate,(a0)          ; Phrase = d1.l/d0.l
416:                 move.l  bmpupdate+4,4(a0)
417: 
418:                 add.l   #1,ticks                ; Increment ticks semaphore
419: 
420:                 move.w  #$101,INT1              ; Signal we're done
421:                 move.w  #$0,INT2
422:                
423:                 btst.b  #(11-8),VC              ; we're testing bit 11 (the 12th bit) of VC but...
424:                 bne     .bottom                 ; btst only works on bytes when operating on memory
425: 
426:                 ; top field
427:                 ori.w   #1,vi_line              ; set line next VI will occur on
428:                 move.w  vi_line,VI              ; and set it (VI is write-only)
429: 
430:                 bra     .done
431: 
432: .bottom:        ; bottom field
433:                 andi.w  #$fffe,vi_line          ; set line next VI will occur on
434:                 move.w  vi_line,VI              ; and set it (VI is write-only)
435: 
436:                 add.l   #((BMP_PHRASES)<<11),(a0) ; add IWIDTH to DATA to start one line lower
437: 
438: .done:  
439: 
440: ; test de scrolling
441: ;               move.w  bmpupdate+6,d0
442: ;               add.w   #16,d0
443: ;               and.w   #$CFFF,d0
444: ;               move.w  d0,bmpupdate+6
445:                
446:                 movem.l  (sp)+,d0/a0
447:                 rte
448: 
449: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
450: 
451:                 .data
452:                 .phrase
453: license:
454:                 license_logo
455: 
456:                 .bss
457:                 .dphrase
458: 
459: listbuf:        .ds.l   LISTSIZE*2              ; Object List
460: bmpupdate:      .ds.l   2                       ; One Phrase of Bitmap for Refresh
461: ticks:          .ds.l   1                       ; Incrementing # of ticks
462: vi_line:        .ds.w   1                       ; VI is write only, so cache it
463: a_hdb:          .ds.w   1
464: a_hde:          .ds.w   1
465: a_vdb:          .ds.w   1
466: a_vde:          .ds.w   1
467: width:          .ds.w   1
468: height:         .ds.w   1
469: 
470:                 .end
471: