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