
vdpControl equ &BF
vdpData    equ &BE

	;Unrem this if building with vasm
	include "\SrcALL\VasmBuildCompat.asm"

	org &0000
	jp ProgramStart		;&0000 - RST 0
	ds 5,&C9			;&0002 - RST 0
	ds 8,&C9			;&0008 - RST 1
	ds 8,&C9			;&0010 - RST 2
	ds 8,&C9			;&0018 - RST 3
	ds 8,&C9			;&0020 - RST 4
	ds 8,&C9			;&0028 - RST 5
	ds 8,&C9			;&0030 - RST 6
	jp InterruptHandler	;&0038 - RST 7 
	ds 35,&C9			;&0066 - NMI
	ds 26,&C9			;&0080
	
	;We have two 'EyeBuffers' in VRAM
	;C000-C5FF: Left Eye Tilemap
	;C600-C6FF: Left Eye Sprites
	;C700-CCFF: Right Eye Tilemap
	;CD00-CDFF: Right Eye Sprites
	
InterruptHandler:
	exx
	ex af,af'				;';Swap in Shadow registers
		ld a,($fff8)
		xor %00000001
		ld ($fff8),a		;0=Right Eye Image 1=Left Eye Image
		jr z,RightEye
		jp LeftEye
InterruptDone:
		in a,(vdpControl)	;CLEAR SMS interrupt	
	ex af,af'
	exx
	ei
	ret
	
RightEye:
	ld hl,&3800			;Copy Right eye Tilemap
	call prepareVram	
	ld hl,&C700
	ld b,0
	ld c,vdpData
	otir
	otir
	otir
	otir
	otir
	otir
	
	ld hl,&3F00			;Copy Right eye Sprites
	call prepareVram
	ld hl,&C600
	ld b,0
	ld c,vdpData
	otir
	jp InterruptDone

LeftEye:
	ld hl,&3800
	call prepareVram	;Copy Left eye Tilemap
	ld hl,&C000
	ld b,0
	ld c,vdpData
	otir
	otir
	otir
	otir
	otir
	otir
	
	ld hl,&3F00			;Copy Left eye Sprites
	call prepareVram	
	ld hl,&CD00
	ld b,0
	ld c,vdpData
	otir
	jp InterruptDone
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	

ProgramStart:	
	
    im 1    			;Interrupt mode 1
    ld sp, &dff0		;Default stack pointer

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
;									Init the screen 												

	ld hl,VdpInitData	;Source of data
    ld b,VdpInitDataEnd-VdpInitData		;Byte count
    ld c,vdpControl		;Destination port
    otir				;Out (c),(hl).. inc HL... dec B, djnz 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
;									Define Palette 												
	
    ld hl, &c000	    ; set VRAM write address to CRAM (palette) address 0
		; note &C0-- is a set palette command... it's not a literal memory address 
    call prepareVram

    ld hl,PaletteData	;Source of data
		ld b,32			;Byte count (16 on SMS)
	ld c,vdpData		;Destination port
	otir				;Out (c),(hl).. inc HL... dec B, djnz  

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;					Start of the Test Code														

	;Define our character tiles
	ld de, 128*8*4				;8 lines of 4 bytes per tile
	ld hl, BitmapData			;Source of bitmap data
	ld bc, BitmapDataEnd-BitmapData;Length of bitmap data
	call DefineTiles
	
	;ld a,1		;Try 2 - bit 0= Glasses 'side'
	;ld ($fff8),a
	
	
;Right Eye Tiles	
	ld bc,&0303		;Start Position in BC
	ld hl,&0606		;Width/Height of the area to fill with tiles in HL
						;We need to load DE with the first tile number we want 
						;to fill the area with.
	ld iy,128		;First TileNum
	ld ixh,&C7		;&C700 - Right Eye Tilemap Cache
	call FillAreaWithTiles		;Fill a grid area with consecutive tiles 
	
;Left Eye Tiles	
	ld bc,&0203		;Start Position in BC
	ld hl,&0606		;Width/Height of the area to fill with tiles in HL
	ld iy,128		;First TileNum
	ld ixh,&C0		;&C000 - Left Eye Tilemap Cache
	call FillAreaWithTiles		;Fill a grid area with consecutive tiles 
	
	
;Left Eye Sprite
	ld ixh,&C6		;&C600 - Sprite Cache for Left Eye
	ld bc,&1040		;BC=Sprite XY Pos
	Call DrawCrosshair
	xor a
	
;Main Loop	
	ei
	ld d,1			;Direction Flag (1=R 0=L)
	ld e,0			;Sprite Pos
infloop:
	ld a,d
	cp 0
	jr nz,Positive
Negative:			;Move sprite Left
	dec e
	ld a,e
	cp -5			;Cnage Direction?
	jr nz,SpriteOk
	set 0,d
	jr SpriteOk
Positive:			;Move Sprite Right
	inc e
	ld a,e
	cp 5			;Cnage Direction?
	jr nz,SpriteOk
	res 0,d
SpriteOk:		
	halt			;Delay until next change of sprite pos
	halt
	halt
	halt
	halt
	halt
	
;Right Eye Sprite
	push de
	ld bc,&1040		;BC=Sprite XY Pos
	add b			;A contains Ofset
	ld b,a			;Add Offset to Spritepos
	
	ld ixh,&CD		;&CD00 - Sprite Cache for Left Eye
					;BC=Sprite XY Pos
	
	Call DrawCrosshair
	pop de	
	jp infloop
					;this does not cause a problem
DrawCrosshair:
	ld e,164		;pattern
	ld a,0			;Sprite
	Call SetHardwareSprite
	ld a,8
	add b
	ld b,a
	inc e
	ld a,1
	Call SetHardwareSprite
	ld a,8
	add c
	ld c,a
	inc e
	inc e	
	ld a,2
	Call SetHardwareSprite
	ld a,-8
	add b
	ld b,a
	dec e
	ld a,3
	Call SetHardwareSprite
	ret

prepareVram:				;Set vdpData to write to memory address HL in vram
	    ld a,l
	    out (vdpControl),a
	    ld a,h
	    or &40				;we set bit 6 to define that we want to Write data...
	    out (vdpControl),a	;As the VDP ram only goes from &0000-&3FFF 
    ret		
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;					VDP Register settings (needed to turn on screen)							

VdpInitData:
	db %00000110,128+0 ; reg. 0, display and interrupt mode.
	db %11100000,128+1 ; reg. 1, display and interrupt mode.
	db &ff		,128+2 ; reg. 2, name table address. &ff = name table at &3800
	db &ff		,128+3 ; reg. 3, Name Table Base Address  (no function) &0000
	db &ff 		,128+4 ; reg. 4, Color Table Base Address (no function) &0000
	db &ff		,128+5 ; reg. 5, sprite attribute table. -DCBA98- = bits of address $3f00
	db &00		,128+6 ; reg. 6, sprite tile address. -----D-- = bit 13 of address $2000
	db &00		,128+7 ; reg. 7, border color. 			----CCCC = Color
	db &00 		,128+8 ; reg. 8, horizontal scroll value = 0.
	db &00		,128+9 ; reg. 9, vertical scroll value = 0.
	db &ff 		,128+10; reg. 10, raster line interrupt. Turn off line int. requests.
VdpInitDataEnd:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;								Basic palette in native format									
	
PaletteData:
		;   --BBGGRR
		db %00000000	;0
		db %00100010	;1
		db %00111100	;2
		db %00111111	;3
		db %00001111	;4
		db %00001111	;5
		db %00001111	;6
		db %00001111	;7
		db %00001111	;8
		db %00001111	;9
		db %00001111	;A
		db %00001111	;B
		db %00001111	;C
		db %00001111	;D
		db %00001111	;E
		db %00001111	;F
;Sprite Palette
		db %00000000	;0
		db %00100010	;1
		db %00111100	;2
		db %00111111	;3
		db %00001111	;4
		db %00001111	;5
		db %00001111	;6
		db %00001111	;7
		db %00001111	;8
		db %00001111	;9
		db %00001111	;A
		db %00001111	;B
		db %00001111	;C
		db %00001111	;D
		db %00001111	;E
		db %00001111	;F
	
BitmapData:	;Sprite Data of our Chibiko character
	incbin "\ResALL\Sprites\RawSMS.RAW"
	incbin "\ResALL\Sprites\SpriteSMS.RAW"
BitmapDataEnd:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SetHardwareSprite:	;A=Hardware Sprite No. B,C = X,Y , D,E = Source Data, 					
	push hl			;IXH=Top byte of cache address
	push de
	push af	
		push af
			ld l,a		;1 byte per tile - so load L with sprite number
			ld a,ixh
			ld h,a		;first byte is at &3F00
			ld (hl),c	;Ypos
		pop af
		rlca			;2 bytes per tile - 1'st is X, 2nd is tile number
		add &80			;next data Starts from &3F80
		ld l,a
		ld (hl),b		;X Pos
		inc hl
		ld (hl),e		;tile number
	pop af
	pop de
	pop hl
	ret
	
FillAreaWithTiles:;BC = X,Y	HL = W,H 	IY = Start Tile 
					;IXH=Top byte of cache address
	ld a,h				;Calculate End Xpos
	add b
	ld h,a
	ld a,l				;Calculate End Ypos
	add c
	ld l,a
FillAreaWithTiles_Yagain:
	push bc
		call GetCacheScreenPos	;Move to the correcr VDP location
FillAreaWithTiles_Xagain:;Tilemap takes two bytes, ---pcvhn nnnnnnnn
		ld a,iyl			;nnnnnnnn - Tile number
		ld (de),a	
		inc de
		ld a,iyh			;---pcvhn - p=Priority (1=Sprites behind) C=color palette 
		ld (de),a	;(0=back 1=sprite), V=Vert Flip, H=Horiz Flip, N=Tilenum (0-511)
		inc de
		inc iy
		inc b			;Increase Xpos
		ld a,b
		cp h			;Are we at the end of the X-line?
		jr nz,FillAreaWithTiles_Xagain
	pop bc
	inc c				;Increase Ypos
	ld a,c
	cp l				;Are we at the end of the height Y-line?
	jr nz,FillAreaWithTiles_Yagain
	ret
	
;This will load into an XY pos into a 'Cached' tilemap 
	;at memory address &XX00 where X=IXH 
GetCacheScreenPos:	;Move to a memory address in VDP by BC cursor pos
	push bc				;B=Xpos, C=Ypos
		ld d,c
		xor a			
		rr d			;Multiply Y*64
		rra
		rr d
		rra
		rlc b			;Multiply X*2 (Two byte per tile)
		or b
		ld e,a
		ld a,d
		add ixh			;Address of TileMap &3800 
		ld d,a			;(32x28 - 2 bytes per cell = &700 bytes)
	pop bc
	ret
		
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DefineTiles:	;DE=VDP address, HL=Source,BC=Bytecount
	ex de,hl
	call prepareVram	;Set VRAM address we want to write to
	ex de,hl
DefineTiles2:
	ld a,(hl)
	out (vdpData),a		;Send Byte to VRAM
	inc hl
	dec bc				;Decrease counter and see if we're done
	ld a,b
	or c
	jr nz,DefineTiles2	;Continue defining tiles.
	ret
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;										Footer													

	
	org &7FF0
	db "TMR SEGA"	;Fixed data (needed by some SGG)
	db 0,0			;Reserved
	db &69,&69		;16 bit Checksum (sum of bytes $0000-$7FEF... Little endian)
					;Only needed for 'Export SMS', not checked by emulator without bios
	db 0,0,0 		;BCD Product Code & Version
	db &4C		;SMS Export - 32k
	
;&3- SMS Japan 
;&4- SMS Export 
;&5- GG 	Japan 
;&6- GG 	Export 
;&7- GG 	International 
;&-C 32KB   
;&-F 128KB   
;&-0 256KB   
;&-1 512KB

 