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: