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: