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