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

	
Print_String:
;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
	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)
	bra.s @Loop
@Loop_End:
	rts

CalcOffset:
;Calculate VDP command shits from an adress in d0.... breaks.... nothing!
;Optimization time!!!
	move.l d0, -(a7)
    ; abcdefghijklmnop abcdefghijklmnop
    lsl.l   #2, d0
    lsr.w   #2, d0
    or.w    #$4000, d0
    swap    d0
    move.l d0, (VDPControl)
	move.l (a7)+, d0
	rts
	
; Run length decoder written by Oerg866
;
; ARGUMENTS: A6 = SOURCE (the stuff you want to decode)
;            A5 = DESTINATION (the location where you want 
;                              the decompressed data to be in RAM)
 
RunLengthDecoding:
        moveq #0, d0                   ; Clear out d0
        move.b (a6)+, d0               ; Read one byte, in case compressed data is unaligned
        lsl.w #8, d0                   ; Make it the upper byte inside a word
        move.b (a6)+, d0               ; move next byte into the lower byte of that word, which is the size word
        move.b (a6)+, 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 (a6)+, d2               ; Fetch next byte into d2
        move.b d1,(a5)+                ; 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 (a6)+, 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, (a5)+               ; Write the amount of bytes in succession...
        dbra d2, RLD_WriteLoop         ; Looping until d2 is 0....
        move.b (a6)+, 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
	
; 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

BusError: RTE
AddressError: RTE
IllegalInstruction: RTE
DivZero: RTE
ChkException: RTE
TRAPV: RTE
PrivViolation: RTE
TRACE: RTE
Line1010: RTE
Line1111: RTE
Spurious: RTE
Interrupt: RTE
HINT: RTE
VINT: rte
TRAP: RTE
Return: rte

Font:   
	incbin "./font.rle"
Font_End:
	even
    