;     Titan & MDEM Cooperational Demo
;     For Revision 2013
;
;     std.68k - General subroutines

Load_Palette:
;Loads a palette of 16 entries
; a0 = data source
; d0 = palette number
    move.l d1, -(a7)
    moveq #0, d1
    move.w #$C000, d1
    lsl.w #5, d0
    add.w d0, d1
    swap d1
    move.l d1, (VDPControl)
    lea (VDPData), a1
    rept 16
    move.w (a0)+, (a1)
    endr
    move.l (a7)+, d1
    rts
    
Load_Tiles:
;Loads tiles, a0 = in
;d0 = destination in vram1
;d1 = amount of tiles
;Breaks d0, d1, d2, d3, a0, a1
    jsr CalcOffset
    lea (VDPData), a1
@LoadLoop:
    rept 8
    move.l (a0)+, (a1)
    endr
    dbf d1, @LoadLoop
    rts

Display_Tiles:
;Displays Tiles in rectangular...erm... thing =P
;d0.w = vram adress
;d1.b = Plane (Scroll A/B):  0 == Scroll A, 1 == Scroll B
;d2.l = $yyyyxxxx yyyy= y-position onscreen, xxxx= x-position onscreen (in tiles)
;d3.l = Lower word = width in tiles, High word =  height in tiles
    movem.l d0-d5, -(a7)
    moveq #0, d4
     lsr.w #5, d0 ; Divide by 32 to get first tile index
    or.w #$C000, d4
    tst.b d1
    beq.s @Dont_add
    add.w #$2000, d4
@Dont_add:
    move.w d3, d1
    move.w #$0, d3
    swap d3
    add.w d2, d4
    add.w d2, d4
    swap d2
    moveq #0, d5
    move.w d0, d5
@Multiplication:
    add.w #128, d4
    dbf d2, @Multiplication
    move.l d4, d0
    bsr CalcOffset
    move.l d5, d4    
    move.l #VDPData, a0
    or.w (VRAM_Flags), d4                ; VDP Nametable flags (See CMDVDP.TXT)
    subq.w #1, d3                        ; Subtract 1 from width (dbf shenanigans)
    subq.w #1, d1                        ; Subtract 1 from height (dbf shenanigans)
    move.w d3, d2                        ; Temporary variable, as it gets lost (again, dbf shenanigans =P)
    
@Loop2:
@Loop:
    move.w d4, (a0)
    addq.w #1, d4    
    dbf d3, @Loop
    add.l #128, d0
    move.w d2, d3
    bsr CalcOffset
    dbf d1, @Loop2    
    movem.l (a7)+, d0-d5
    rts
    
Print_String:
    movem.l d0-d2/a0-a1, -(sp)
;Prints string, a0=instring, d0=txt x, d1= txt y
    moveq #0, d2
    add.w d0, d0
    tst.w d1
    beq @NoMulti
    subq.w #1, d1
@Multiplication:
    add.w #128, d0
    dbf d1, @Multiplication
@NoMulti:
    or.w #$C000, d0
    bsr CalcOffset
    lea (VDPData), a1
    moveq #0, d1
@Loop:
    move.b (a0)+, d1    
    tst.b d1
    beq @Loop_End; Jump if Zero
    sub.b #32, d1
    or.w (VRAM_FLAGS), d1 
    move.w d1, (a1)
    bra.s @Loop
@Loop_End:
    movem.l (sp)+, d0-d2/a0-a1
    rts

CalcOffset:
;Calculate VDP command shits from an adress in d0.... breaks.... nothing!
;Optimization time!!!
    move.l d0, -(a7)
    lsl.l   #2, d0
    lsr.w   #2, d0
    or.w    #$4000, d0
    swap    d0
    move.l d0, (VDPControl)
    move.l (a7)+, d0
    rts
    
CalcOffset_CRAM:
;Calculate VDP command shits from an adress in d0.... breaks.... nothing!
;Optimization time!!!
    move.l d0, -(a7)
    lsl.l   #2, d0
    lsr.w   #2, d0
    or.w    #$C000, d0
    swap    d0
    move.l d0, (VDPControl)
    move.l (a7)+, d0
    rts

Print_Delayed:
    movem.l d0-d3, -(a7)
;Print delayed, arguments like normal but d2 == amount of frames to wait  between each char =P
    add.w d0, d0
    move.w d2, d3
    subq.w #1, d3
    tst.w d1
    beq @NoMulti
    subq.w #1, d1
@Multiplication:
    add.l #128, d0
    dbf d1, @Multiplication
@NoMulti:
    add.l #$C000, d0
    jsr CalcOffset
    lea (VDPData), a1
    moveq #0, d1
@Loop:
    move.b (a0)+, d1    
    tst.b d1
    beq @Loop_End; Jump if Zero
    sub.b #32, d1
    or.w (VRAM_FLAGS), d1 
    move.w d1, (a1)
    move.w d3, d2
@WaitFrames:    
    WaitFrame
    dbf d2, @WaitFrames
    bra.s @Loop
@Loop_End:
    movem.l (a7)+, d0-d3
    rts
    
; Run length decoder written by Oerg866
;
; ARGUMENTS: A0 = SOURCE (the stuff you want to decode)
;            A1 = DESTINATION (the location where you want 
;                              the decompressed data to be in RAM)
 
RunLengthDecoding:
    moveq #0, d0                   ; Clear out d0
    move.b (a0)+, d0               ; Read one byte, in case compressed data is unaligned
    lsl.w #8, d0                   ; Make it the upper byte inside a word
    move.b (a0)+, d0               ; move next byte into the lower byte of that word, which is the size word
    move.b (a0)+, d1               ; Initialize "last read" byte
    subq.w #1, d0                  ; Decrease remaining size counter
RunLengthDecoding_LOOP:                ; DECODING LOOP START             
    subq.w #1, d0                  ; Decrease remaining size counter
    beq.s RLD_End                  ; If remaining size counter is 0, quit 
    move.b (a0)+, d2               ; Fetch next byte into d2
    move.b d1,(a1)+                ; Write the old byte to destination (since one occurance gets written no matter what)
    cmp.b d2, d1                   ; Check if the old and new byte are identical
    beq.s RLD_Identical            ; If yes, branch
RLD_NotIdentical:                      ; if not, leave it at that
    move.b d2, d1                  ; and make d2 the old byte.
    bra.s RunLengthDecoding_LOOP   ; Go back to main loop
RLD_Identical:                         ; if the bytes are identical...
    moveq #0, d2                   ; Clearing out d2 here is practical since it will only be done if we have a loop (dbra) 
    move.b (a0)+, d2               ; Grab the amount of bytes to be written in succession into d2 (saves a few cycles...)
    subq.w #1, d0                  ; decrease remaining size counter
RLD_WriteLoop:                         ; Start writing the sequence into the destination...              
    move.b d1, (a1)+               ; Write the amount of bytes in succession...
    dbra d2, RLD_WriteLoop         ; Looping until d2 is 0....
    move.b (a0)+, d1               ; Grab the next byte
    subq.w #1, d0                  ; decrease remaining size counter
    bra.s RunLengthDecoding_LOOP   ; and go back to the loop.
RLD_End:
    rts    
        
Print_HEXByte:
	movem.l d0-d3/a0, -(a7)
	moveq #0, d3
	lsl.w #4, d2
	lsr.b #4, d2
	move.b d2, d3
	lsr.w #8, d2 
	add.w d0, d0
	tst.w d1
	beq @NoMulti
	subq.w #1, d1
@Multiplication:
	add.w #128, d0
	dbf d1, @Multiplication
@NoMulti:
	or.w #$C000, d0
	jsr CalcOffset
	lea (VDPData), a0

	cmp.b #$A, d2
	blt.s @Number_2
	add.b #23, d2
	bra.s @Print_2
@Number_2:
	add.b #16, d2
@Print_2:
;	or.w (VRAM_FLAGS), d2
	move.w d2, (a0)
	
	cmp.b #$A, d3
	blt.s @Number_1
	add.b #23, d3
	bra.s @Print_1
@Number_1:
	add.b #16, d3
@Print_1:
	or.w (VRAM_FLAGS), d3 
	move.w d3, (a0)
@Loop_End:

		
	movem.l (a7)+, d0-d3/a0
	rts

INTERRUPT:
    rte
TRAP: 
    rte
    
JMPOpcode:
    JMP 0.l
    
    

; RECEIVE DATA
; (C) MASK OF DESTINY
; SEGA CD TRANSFER SUITE

Receive:
	move.b	#$30, $A1000B
RecvLoop:
	move.b	#$0, $A10005
	moveq	#0, d1
	moveq	#0, d2

WaitData:
	btst.b	#6, $A10005
	beq	WaitData

	
	move.b	$A10005, d1
	lsl.b	#4, d1
	and.b	#$F0, d1

	move.b	#$FF, $A10005
RWaitReady:
	btst.b	#6, $A10005
	bne	RWaitReady

	move.b	#$0, $A10005

WaitData2:
	btst.b	#6, $A10005
	beq	WaitData2

	move.b	$A10005, d2
	and.b	#$F, d2
	or.b	d2, d1

	move.b	d1, (a0)+

	move.b	#$FF, $A10005
RWaitReady2:
	btst.b	#6, $A10005
	bne	RWaitReady2

	dbra	d0, RecvLoop

	rts
