********************************************************************************
* overlay-test
* written : 95..97 by 42Bastian Schick (elw5basc@gp.fht-esslingen.de)
*
* - it now works with interrupts, both gpu-object and timer
* - free ram (without the current irq-routines)
*    $f70-$a8 = 3784 bytes
*     ^    ^__end of dispatcher
*     |_______start of interrupt routines
*
* NOTES: Do _NOT_ use the blitter in interrupt !
*        Do _NOT_ mess with the overlay-registers !
*
* free registers : bank 1 : r0..r19
*                  bank 0 : r0..r27
*
********************************************************************************


                path "e:\bjl\js\"
                include "macro\help.mac"
                isyms "symbols\blit_eq.sym"

                include "include\dispatch.reg"
                include "include\dispatch.equ"

;----------------------
irq_routines    equ $f03f70     ; place at the end (above SP)

IRQ_SP.a        REG 31
IRQ_RTS.a       REG 30          ; redefined !!
IRQ_FLAGADR.a   REG 29
IRQ_FLAG.a      REG 28

_50Hz.a         REG 26
sec.a           REG 25
ms.a            REG 24
obl.a           reg 19



MACRO IRQ_PUSH
                subqt #4,IRQ_SP.a
                store \0,(IRQ_SP.a)
ENDM
MACRO IRQ_POP
                load (IRQ_SP.a),\0
                addqt #4,IRQ_SP.a
ENDM


OBL             equ $8000
OBL0            equ OBL+32*32

FunctionCount   set 0
***************
* Overlay-macros

* Note : \^ expands to the MACRO name

                MACRO FUNCTION ; name[,pos]
\0.num          equ FunctionCount
FunctionCount   set FunctionCount+1

                IFVAR \1
\0.loc::        equ \1
                ELSE
\0.loc::        equ OverlayEnd
                ENDIF

                MACRO \0
                movei #(\^.loc&$ffff)<<16|(\^.num*12),NewFunction
                movei #(.\_0<<16),CurrentAdr
                subqt #4,SP
                or CurrentFunction,CurrentAdr
                jump (Overlay)                  ; call dispatcher
                store CurrentAdr,(SP)
.\_0
                ENDM


                align 8
\0.st::
                run \0.loc
                ENDM

                MACRO CALL ; func
                movei #(\0.loc&$ffff)<<16|(\0.num*12),NewFunction
                movei #(.\_0<<16),CurrentAdr
                subqt #4,SP
                or CurrentFunction,CurrentAdr
                jump (Overlay)                  ; call dispatcher
                store CurrentAdr,(SP)
.\_0
                ENDM

                MACRO RETURN    ; don't mess it up with RTS !!!
                load (SP),NewFunction
                jump (Overlay)
                addqt #4,SP
                ENDM

                MACRO ENDFUNC
                IFVAR \1
                  ; empty
                ELSE
                load (SP),NewFunction
                jump (Overlay)
                addqt #4,SP
                ENDIF
                align 8

\0.len::        equ *-\0.loc

                run \0.st+\0.len
                ENDM
***************

                run OVLtab-4
; this is the main (first) function
                dc.l (MAIN.loc & $ffff)<<16|MAIN.num*12
; normal overlay-table
_OVLtab         dc.l InitTextScreen.st,InitTextScreen.len|$10000,InitTextScreen.loc ;,0
                dc.l Print.st,Print.len|$10000,Print.loc ;,0
                dc.l InitIRQ.st,InitIRQ.len|$10000,InitIRQ.loc ;,0
                dc.l InitIRQ2.st,InitIRQ2.len|$10000,InitIRQ2.loc ;,0
                dc.l MAIN.st,MAIN.len|$10000,MAIN.loc ;,0
OVLend



TextScreen      equ $100000

ScreenPtr.a     reg 6
Cursor.a        reg 7

max_x           equ 40
max_y           equ 12
****************************
* Textscreen with 8x8-Font *
* created : 29.06.95       *
* (c) Bastian Schick       *
****************************
;global EQUs
; max_x, max_y must be preset !
;global registers
;Cursor.a       
;ScreenPtr.a                    ; must be initialized !

****************  
* InitTextScreen
clr             reg 2
ptr             reg 1
count           reg 0

                FUNCTION InitTextScreen
                PUSH r0,r1,r2
                movei #TextScreen,r0
                moveta r0,ScreenPtr.a
                movefa ScreenPtr.a,ptr
                xor clr,clr
                movei #max_x*max_y<<2-1,count

;>                subq #1,clr
                store clr,(ptr)
.loop           subq #1,count
                addqt #4,ptr
                jr nz,.loop
                store clr,(ptr)

                xor clr,clr
                moveta clr,Cursor.a
                movei #$f00400,ptr
                movei #$fff,clr
                store clr,(ptr)                 ; set color
                 POP r2,r1,r0
                unreg clr,ptr,count
                ENDFUNC InitTextScreen
****************
* Print        *
                FUNCTION Print
                JSR (r1)
                RETURN
****************
* Print char in r0
********************
PChelp1         reg 3
PChelp          reg 2
ptr             reg 1
CharPtr         reg 0
PrintChar::
                PUSH r1,r2,r3
                movei #ASCII+8,ptr
;>                subq #32,r0                     ; 8x16 erst ab SPACE

                shlq #24,CharPtr
                movefa Cursor.a,PChelp          ; get current cursor
                shrq #24-3,CharPtr              ; (r0 and $ff)*16
                shrq #16,PChelp                 ; get x
                add ptr,CharPtr
                movefa ScreenPtr.a,ptr
                add PChelp,ptr
                movefa Cursor.a,PChelp
                movei #max_x<<3,PChelp1         ; bytes per line*16
                mult PChelp1,PChelp
                shrq #3,PChelp1                 ; = bytes per line
                add PChelp,ptr
                load (CharPtr),PChelp           ; get 4 bytes of char
                addq #4,CharPtr
                REPT 4
                  rorq #24,PChelp ; first byte down
                  storeb PChelp,(ptr)
                  add PChelp1,ptr
                ENDR
                load (CharPtr),PChelp
;---------------
;>                addq #4,CharPtr
;>                REPT 4
;>                  rorq #24,PChelp ; first byte down
;>                  storeb PChelp,(ptr)
;>                  add PChelp1,ptr
;>                ENDR
;>                load (CharPtr),PChelp
;>                addq #4,CharPtr
;>                REPT 4
;>                  rorq #24,PChelp ; first byte down
;>                  storeb PChelp,(ptr)
;>                  add PChelp1,ptr
;>                ENDR
;>                load (CharPtr),PChelp
;---------------
                REPT 3
                  rorq #24,PChelp ; first byte down
                  storeb PChelp,(ptr)
                  add PChelp1,ptr
                ENDR
                rorq #24,PChelp
                storeb PChelp,(ptr)
                movefa Cursor.a,PChelp
                move PChelp,r0
                shlq #16,r0
                shrq #16,PChelp
                shrq #16,r0
                addq #1,PChelp
                cmp PChelp,PChelp1
                jr nz,._1
                nop
                  moveq #0,PChelp
                  movei #max_y,PChelp1
                  addq #1,r0
                  cmp PChelp1,r0
                  jr nz,._1
                  nop
                    moveq #0,r0
._1             shlq #16,PChelp
                or PChelp,r0
                moveta r0,Cursor.a
                POP r3,r2,r1
                RTS

                unreg CharPtr,ptr,PChelp,PChelp1
***************
* prints r0 hex at cursor
printchar       reg 4
null            reg 3
PHhelp1         reg 2
PHHelp          reg 1
PrintHex::
                PUSH r0,r1,r2,r3,r4
                movei #"0",null
                move r0,r1
                movei #PrintChar,printchar
                REPT 4
                  rorq #24,r1
                  move r1,r0
                  shlq #24,r0     ; first byte up
                  move r0,r2
                  shrq #28,r0     ; high nibble down
                  shlq #4,r2      ; low nibble up
                  shrq #28,r2     ; low nibble down
                  cmpq #10,r0
                  jr n,._1@
                  add null,r0
                    addq #7,r0
._1@              cmpq #10,r2
                  jr n,._2@
                  add null,r2
                    addq #7,r2
._2@            JSR (printchar)
                move r2,r0
                JSR (printchar)
                INC@
                ENDR
                POP r4,r3,r2,r1,r0
                RTS
                unreg PHHelp,PHhelp1,null,printchar
****************
* prints text at r0 (C-style)
* text must be Long-aligned
****************
EXIT            reg 5
LOOP            reg 4
PRhelp          reg 3
printchar       reg 2
ptr             reg 1
PrintR0::
                PUSH r1,r2,r3,r4,r5
                move r0,ptr
                movei #.loop,LOOP
                movei #.exit,EXIT
                movei #PrintChar,printchar
                load (ptr),PRhelp
.loop           addq #4,ptr
                REPT 4
                  rorq #24,PRhelp
                  nop
                  move PRhelp,r0
                  shlq #24,r0
                  jump z,(EXIT)
                  shrq #24,r0     ; get byte
                  JSR (printchar)
                ENDR
                jump (LOOP)
                load (ptr),PRhelp

.exit           POP r5,r4,r3,r2,r1
                RTS
                unreg EXIT,LOOP,PRhelp,printchar,ptr
****************
                ENDFUNC Print
****************
                ALIGN 4
ASCII           ibytes "\bjl\font\light8x8.fnt"
****************
FUNCTION InitIRQ,$f03000
                RETURN

                org $f03020
                movei #timer_irq,IRQ_RTS.a
                load (IRQ_FLAGADR.a),IRQ_FLAG.a
                jump (IRQ_RTS.a)
                load (IRQ_SP.a),IRQ_RTS.a

                org $f03030
                movei #obj_irq,IRQ_RTS.a
                load (IRQ_FLAGADR.a),IRQ_FLAG.a
                jump (IRQ_RTS.a)
                load (IRQ_SP.a),IRQ_RTS.a
                ENDFUNC InitIRQ,1
****************
FUNCTION InitIRQ2,irq_routines
                RETURN
****************
* ms-timer
****************
timer_irq::     bclr #3,IRQ_FLAG.a
                addq #4,IRQ_SP.a
                bset #11,IRQ_FLAG.a
;---------------
                subq #1,_50Hz.a
                movei #$f02114,r20
                jr nz,.cont0
                load (r20),r21
                moveq #20,_50Hz.a
                bset #1,r21
                store r21,(r20)                 ; CPU-VBL anstožen

.cont0          subq #1,ms.a
                jr nn,.cont
                addq #2,IRQ_RTS.a

                movei #999,ms.a
                addq #1,sec.a
.cont
                jump (IRQ_RTS.a)
                store IRQ_FLAG.a,(IRQ_FLAGADR.a)
****************
* object-irq

obj_irq::
                bclr #3,IRQ_FLAG.a
                addqt #4,IRQ_SP.a
                bset #12,IRQ_FLAG.a
                addqt #2,IRQ_RTS.a
;---------------                
                IRQ_PUSH r20
                IRQ_PUSH r21
                IRQ_PUSH r22
                IRQ_PUSH r23

                movei #$f00026,r20
                storew r21,(r20)                ; resume OP

;>                movei #$f00058,r20
;>                storew obl.a,(r20)
                addqt #1,obl.a

                movei #OBL,r20
                movei #OBL0,r21
                movei #8*2,r22

                loadp (r21),r23
.loop           addq #8,r21
                subq #1,r22
                storep r23,(r20)
                addqt #8,r20
                jr nz,.loop
                loadp (r21),r23

                IRQ_POP r23
                IRQ_POP r22
                IRQ_POP r21
                IRQ_POP r20
;---------------
                jump (IRQ_RTS.a)
                store IRQ_FLAG.a,(IRQ_FLAGADR.a)
****************
eof_irq:
                if eof_irq > $f03ffe
                fail "irq-routines out of internal RAM"
                else
                echo "eof_irq %Heof_irq"
                endif
                ENDFUNC InitIRQ2,1
****************
FUNCTION MAIN
                moveta CurrentFunction,CurrentFunction
                movei #irq_routines,SP
                moveta SP,SP

                movei #$f02100,r0
                movei #(1<<14)|(%11111<<9),r1
                store r1,(r0)
                nop
                nop             ; set bank 1, clear pending IRQs
                movefa CurrentFunction,CurrentFunction

;- clear regs 0..19,0.a .. 19.a
                moveq #0,r0
                moveq #0,r1
                moveq #0,r2
                moveq #0,r3
                moveq #0,r4
                moveq #0,r5
                moveq #0,r6
                moveq #0,r7
                moveq #0,r8
                moveq #0,r9
                moveq #0,r10
                moveq #0,r12
                moveq #0,r13
                moveq #0,r14
                moveq #0,r15
                moveq #0,r16
                moveq #0,r17
                moveq #0,r18
                moveq #0,r19
                moveta r0,r0
                moveta r0,r1
                moveta r0,r2
                moveta r0,r3
                moveta r0,r4
                moveta r0,r5
                moveta r0,r6
                moveta r0,r7
                moveta r0,r8
                moveta r0,r9
                moveta r0,r10
                moveta r0,r11
                moveta r0,r12
                moveta r0,r13
                moveta r0,r14
                moveta r0,r15
                moveta r0,r16
                moveta r0,r17
                moveta r0,r18
                moveta r0,r19

                movei #$f03020,r0
                moveta r0,IRQ_SP.a
                movei #$f02100,r0
                moveta r0,IRQ_FLAGADR.a
                InitIRQ         ; init slots
                InitIRQ2        ; init subs
                InitTextScreen
;-------------------------
;- enable gpu-object-irq -

                xor r0,r0
                moveta r0,obl.a

                movei #$f02100,r0
                load (r0),r1
                bset #7,r1      ; enable object irq
                bset #12,r1
                store r1,(r0)
                nop
                nop

;-------------------------
;-- set OBL here, so we sure get the first IRQ

                movei #OBL<<16|OBL>>16,r0
                movei #$f00020,r1
                store r0,(r1)
                movei #$6c1,r0
                movei #$f00028,r1
                storew r0,(r1)
;---------------
                movei #14<<16,r0
                moveta r0,Cursor.a
                movei #PrintR0,r1
                movei #Hallo,r0
                Print
;---------------
                movei #$f14000,r0
                movei #$8180,r1
                storew r1,(r0)                  ; BUSY high => active

                movei #$f02100,r2
                xor r3,r3
.loop

                PUSH r3
                moveq #1,r0
                moveta r0,Cursor.a
                movei #GetLongFromSTE,r0
                JSR (r0)
                POP r3

                movei #.cont,r1
                jump z,(r1)
                nop

                PUSH r0
                movei #PrintHex,r1
                Print
                POP r0
                movei #$22071970,r1
                sub r1,r0
                movei #.cont,r1
                jump z,(r1)
                nop
                PUSH r0
                movefa Cursor.a,r0
                rorq #16,r0
                addq #1,r0
                rorq #16,r0
                moveta r0,Cursor.a

                addq #1,r3
                move r3,r0
                movei #PrintHex,r1
                Print
                movefa Cursor.a,r0
                rorq #16,r0
                addq #1,r0
                rorq #16,r0
                moveta r0,Cursor.a
                POP r0
                movei #PrintHex,r1
                Print

.cont
                movei #.loop,r0
                xor r1,r1
                load (r1),r1
                cmpq #0,r1
                jump z,(r0)
                nop
                STOP_GPU

*******************************
*** PART GetLongFromSTEHype ***
Value           REG 0
Joystick        REG 1
BusyHigh        REG 2
BusyLow         REG 3
Counter         REG 4
LOOP            REG 5
ReadValue       REG 6
WCounter        REG 7
TIMEOUT         REG 8
dummy           REG 9
TimeOutCnt      reg 10
help1           reg 12
help2           reg 13

GetLongFromSTE::
                movei #$f14000,Joystick
                movei #$81f0,BusyHigh

                movei #TimeOut,TIMEOUT

                moveq #4,Counter               ; 4*8 = 32 bit
                move BusyHigh,BusyLow
                moveq #0,Value
                bclr #7,BusyLow                 ; = $8170
                movei #.loop,LOOP
                movei #$100,r9                  ; switch port to input

                storew BusyLow,(Joystick)
.loop
                movei #10000,TimeOutCnt

                subq #1,TimeOutCnt
.wait1          load (Joystick),help2
                jump z,(TIMEOUT)
                btst #3,help2
                jr nz,.wait1                     ; wait for /STROBE low
                subq #1,TimeOutCnt

                storew r9,(Joystick)            ; switch to input
                                                ; set also BUSY = high
                load (Joystick),ReadValue       ; get data

; bits in ReadValue
;     pos 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
;    data  7  6  5  4  x  x  x  x B  2   1  0  x  x  x  x  x x   x  x  x  x x x x x x x S 3 x x
; B = BUSY (output)  high-active
; S = STROBE (input) high-active

                move ReadValue,r12
                move ReadValue,r13

                shlq #31-22,r12                 ; bits 2..0 => 31..29
                shrq #28,r13                    ; bits 7..4 => 3..0
                shrq #31-2,r12                  ; bits 2..0 => 2..0
                shlq #4,r13                     ; bits 7..4 => 7..4
               shlq #1,ReadValue                ; bit  3    => 3
                or r12,Value                    ; value |= (2..0)
               moveq #8,r12
                or r13,Value                    ; value |= (7..4)
               and r12,ReadValue                ; mask bit 3

                or ReadValue,Value              ; value |= (3)


                subq #1,TimeOutCnt
.wait2          load (Joystick),ReadValue
                jump z,(TIMEOUT)
                btst #3,ReadValue
                jr z,.wait2                    ; wait for /STROBE high
                subq #1,TimeOutCnt

                subq #1,Counter
                storew BusyLow,(Joystick)
                jump nz,(LOOP)
                rorq #8,Value


                xor ReadValue,ReadValue
                subq #1,ReadValue
;>                jump (r25)
                storew BusyHigh,(Joystick)
                RTS

TimeOut:        storew BusyHigh,(Joystick)
;>                jump (r25)
                xor Value,Value
                RTS

UNREG Value,Joystick,BusyHigh,BusyLow,Counter,LOOP,ReadValue,WCounter,dummy
UNREG TIMEOUT,TimeOutCnt

*******************************

                ENDFUNC MAIN,1

                align 4
Hallo           dc.b "GetLong Test "
                dc.b ^^TIME
                dc.b 0
                align 8


                end

