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


        .include "jaguar.inc"

        .text

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

;       .extern Mandle          ; Do mandelbrot picture...
        .extern start_mandGPU
        .extern end_mandGPU
        .extern mandGPU

        .extern olp2set         ; objectlist pointer...
        .extern gSetOLP         ; routine for setting OLP
        .extern ticks           ; video stuff...
        .extern a_vdb
        .extern a_vde
        .extern a_hdb
        .extern a_hde
        .extern width
        .extern height

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

bitmap_addr             .equ    $20000  ; Buffer in main memory
BM_WIDTH                .equ    640     ; Bitmap width in pixels
BM_HEIGHT               .equ    480     ; Bitmap height in pixels
BM_DEPTH                .equ    8       ; 8 bits per pixel
BM_PHRASES              .equ    ((BM_WIDTH*BM_DEPTH)/64)        ; phrase = 64 bits
BM_OFFSET               .equ    (2*8)   ; Two Phrases = offset to bitmap object

MY_LISTSIZE     .equ    5       ; List size in phrases:        
                                                        ; branch (1)
                                                        ; branch (1)
                                                        ; bitmap (2)
                                                        ; stop (1)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This is where we get control after the startup code...

_start::
        move.l  ticks,d0        ; get the VB counter
.2:
        move.l  ticks,d1
        sub.l   d0,d1
        cmp.l   #100,d1         ; Wait for 5-6 seconds (300 vb ticks)
        ble     .2

; Go make a new object list for our pictures...

        bsr     make_list

;;; Borrow Scott's Sneaky trick to cause display to popup at first VB
;;; (Change the bitmap to a STOP object, until the VB kicks in and updates it)

        move.l  #$0,my_objlist+BM_OFFSET
        move.l  #$C,my_objlist+BM_OFFSET+4

; OK, now we stick in our new object list pointer.

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

; Now we stick in our new VB routine.  This
; is OK because the move.l is atomic.

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

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

;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Copy over the GPU program

        move.l  #mandGPU,a0             ; Get the address of the GPU code
        move.l  #start_mandGPU,a1       ; Get destination address
        move.l  #end_mandGPU,d0         ; and calculate length of GPU code
        sub.l   #start_mandGPU,d0
        asr.l   #2,d0                   ; divide by 4 since we're copying longs
.loop:
        move.l  (a0)+,(a1)+     ; actually copy the code...
        dbra    d0,.loop

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Copy the palette into the chip

        move.l  #256,d0
        move.l  #CLUT,a0
        move.l  #cry_data,a1

.cloop:
        move.w  (a1)+,(a0)+
        dbra    d0,.cloop

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Now set the proper Vmode...

        move.w  #$2C1,VMODE     ; Set 16 bit CRY; 640 overscanned

;       bsr     clearpic

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Draw the fractal, then just bail out to an illegal instruction...

        move.l  #G_RAM,G_PC             ; GPU Program counter gets $00f03000

        move.l  #$1,G_CTRL              ; Set the GPU going
;       jsr     Mandle
prout:
        bra.s   prout



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Use the blitter to clear the bitmap for our fractal picture...
; Just set up enough Blitter stuff to do a block draw.  Set A1_FLAGS to:
;
;       Contiguous data
;       16 bit per pixel
;       width of 56 pixels
;       add increment
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

clearpic:
        move.l  #PITCH1|PIXEL8|WID256|XADDPIX,d0
        move.l  d0,A1_FLAGS

; Point A1BASE to the data

        move.l  #$20000,d0
        move.l  d0,A1_BASE

; Set the pixel point to 0,0

        move.w  #0,d0                   ; y
        swap    d0
        move.w  #0,d0                   ; x
        move.l  d0,A1_PIXEL

; Set up the step size to -256 in x, 1 in y
; The x step requires that the pixel pointer by

        move.w  #1,d0                   ; y
        swap    d0
        move.w  #(-256),d0              ; x
        move.l  d0,A1_STEP

        move.l  #0,A1_CLIP

; Set up Counters register to 256 in x write long to clear upper
; 256 in y, or in y as a word

        move.w  #200,d0                 ; y
        swap    d0
        move.w  #256,d0                 ; x
        move.l  d0,B_COUNT

; Put some data in the blitter for it to write.

        move.l  #0,d0
        move.l  d0,B_PATD      
        move.l  #0,d0
        move.l  d0,B_PATD+4

; Now Turn IT ON !!!!!!!!!!!!!

; NO SOURCE DATA, NO OUTER LOOP, Turn on pattern data, Allow outer loop update

        move.l  #PATDSEL|UPDA1,d0
        move.l  d0,B_CMD
        rts

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; make_list: Create my 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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

make_list:
                movem.l d1-d4/a0,-(sp)          ; Save registers
                       
                lea     my_objlist,a0
                move.l  a0,d2                   ; Copy

                add.l   #(MY_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  #BM_HEIGHT/2<<14,d1       ; Height of image

                move.w  #0,d4
;               move.w  height,d4               ; Center bitmap vertically
;               sub.w   #BM_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  #bitmap_addr,d4
               
                lsl.l   #8,d4
                or.l    d4,d0
         
                move.l  d0,(a0)+
                move.l  d1,(a0)+
                movem.l d0-d1,ol_update

; Second Phrase of Bitmap

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

                move.w  #32,d4
;               move.w  width,d4                ; Get width in clocks
;               lsr.w   #1,d4                   ; /2 Pixel Divisor
;               sub.w   #BM_WIDTH,d4
;               lsr.w   #1,d4
                or.w    d4,d1

                ori.l   #((BM_PHRASES*2)<<18)|(BM_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  #my_objlist,d0
                swap    d0

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

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

my_UpdateList:
                move.l  a0,-(sp)

                move.l  #my_objlist+BM_OFFSET,a0

                move.l  ol_update,(a0)          ; Phrase = d1.l/d0.l
                move.l  ol_update+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_line2             ; set line next VI will occur on
                move.w  vi_line2,VI             ; and set it (VI is write-only)

                bra     .done

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

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

.done:  

                move.l  (sp)+,a0
                rte

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

        .data

; This file has a label cry_data that has, in 68k format the top level
; of cry for 8 bits
       
        .include "cry.pal"

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

        .phrase
        .bss
        .dphrase

my_objlist:
        .ds.l   16

ol_update:
        .ds.l   2

vi_line2:       .ds.w   1                       ; VI is write only, so cache it