
	
;Port $DC: I/O port A and B
;Bit 	Function 
;7 	Port B Down pin input 
;6 	Port B Up pin input 
;5 	Port A TR pin input 
;4 	Port A TL pin input 
;3 	Port A Right pin input 
;2 	Port A Left pin input 
;1 	Port A Down pin input 
;0 	Port A Up pin input 


;Port $DD: I/O port B and miscellaneous
;Bit	Function 
;7 	Port B TH pin input (Unused)
;6 	Port A TH pin input (Unused)
;5 	Cartridge slot CONT pin * 
;4 	Reset button (1= not pressed, 0= pressed) * 
;3 	Port B TR pin input 
;2 	Port B TL pin input 
;1 	Port B Right pin input 
;0	Port B Left pin input

;The Game Gear has three face buttons: buttons 1 and 2 as in the Master System, and additionally a Start button.

;When running in Game Gear mode, the Start button state may be read by inputting from port $00; bit 7 reflects its state, with active-low logic (1 = not pressed, 0 = pressed). 


PlayerX 	equ &C010	;Current player pos
PlayerY 	equ &C011

PlayerX2 	equ &C012	;Last player pos 
PlayerY2	equ &C013		;(For clearing sprite)

vdpControl equ &BF
vdpData    equ &BE


	org &0000
	jr ProgramStart		;&0000 - RST 0
	ds 6,&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
	ds 8,&C9			;&0038 - RST 7
	ds 38,&C9			;&0066 - NMI
	ds 26,&C9			;&0080
						
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
	; effective Start address &0080
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
	ifdef BuildSGG
		ld b,16*2 		;Byte count (32 on SGG)
	else
		ld b,16			;Byte count (16 on SMS)
	endif
	ld c,vdpData		;Destination port
	otir				;Out (c),(hl).. inc HL... dec B, djnz  
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;					Start of the Test Code														

	;Copy bitmap to tilemap
	ld de, 128*8*4			;8 lines of 4 bytes per tile
	ld hl, BitmapData		;Source Address of sprite data
	ld bc, BitmapDataEnd-BitmapData ; Length of sprite data
	call DefineTiles		;Send data to VRAM

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;										Our program													

	ld a,0					;Clear Player Pos
	ld (PlayerX),a
	ld (PlayerY),a
	
	JR StartDraw			;Need A=0
	
infloop:
	in a,(&DC)			;Read Player 1 controller
	cp 255
	jr z,infloop		;See if no keys are pressed
	
StartDraw:
	push af
		ld a,(PlayerX)	;Back up X
		ld b,a
		ld (PlayerX2),a

		ld a,(PlayerY)	;Back up Y
		ld c,a
		ld (PlayerY2),a

		push bc
			call BlankPlayer ;Remove old player sprite
		pop bc
	pop af
	
	ld d,a
	cp %11111110
	jr nz,JoyNotUp		;Jump if UP not presesd
	dec c				;Move Y Up the screen
JoyNotUp:
	ld a,d
	cp %11111101
	jr nz,JoyNotDown	;Jump if DOWN not presesd
	inc c				;Move Y Down the screen
JoyNotDown:
	ld a,d
	cp %11111011
	jr nz,JoyNotLeft 	;Jump if LEFT not presesd
	dec b				;Move X Left 
JoyNotLeft:
	ld a,d
	cp %11110111
	jr nz,JoyNotRight	;Jump if RIGHT not presesd
	inc b				;Move X Right
JoyNotRight: 
	ld a,b
	ld (PlayerX),a		;Update X
	ld a,c
	ld (PlayerY),a		;Update Y
	
;X Boundary Check - if we go <0 we will end up back at &FFFF	
	ld a,b
	ifdef BuildSGG
		cp 20			;SGG
	else	
		cp 32			;SMS
	endif
	jr c,PlayerPosXOk
	jr PlayerReset		;Player out of bounds - Reset!
PlayerPosXOk

;Y Boundary Check - only need to check 1 byte
	ld a,c
	ifdef BuildSGG
		cp 18			;SGG
	else 
		cp 24			;SMS
	endif
	jr c,PlayerPosYOk	;Not Out of bounds
	
PlayerReset:
	ld a,(PlayerX2) 	;Reset Xpos	
	ld b,a
	ld (PlayerX),a	

	ld a,(PlayerY2) 	;Reset Ypos
	ld c,a
	ld (PlayerY),a
	
PlayerPosYOk:
	call DrawPlayer		;Draw Player Sprite

	ld bc,5000
	call PauseBC		;Wait a bit!

	jp infloop

PauseBC:
	dec bc
	ld a,b
	or c
	jr nz,PauseBC
	ret		

BlankPlayer:	
	ld a,129
	jr DrawBoth
DrawPlayer:	
	ld a,128
DrawBoth:	
	push af
		call GetVDPScreenPos;Move to the correcr VDP location
	pop af
	out (vdpData),a		;Tilemap takes two bytes,nnnnnnnn - Tile number
	ld a,0				;---pcvhn p=Priority (1=Sprites behind) C=color palette
	out (vdpData),a		;(0=back 1=sprite), V=Vert Flip, H=Horiz Flip, N=Tilenum (0-511)
	
	ret
						;this does not cause a problem
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;					VDP Register settings (needed to turn on screen)							
	
VdpInitData:
	db %00000110,128+0 ; reg. 0, display and interrupt mode.
	db %11100001,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:
	ifdef BuildSGG					;SGG
		   ;GGGGRRRR, ----BBBB
		db %00000000,%00001111;0
		db %11111111,%00000000;1
		db %11110000,%00001111;2
		db %00001111,%00000000;3
		db %00001111,%00001111;4
		db %00001111,%00001111;5
		db %00001111,%00001111;6
		db %00001111,%00001111;7
		db %00001111,%00001111;8
		db %00001111,%00001111;9
		db %00001111,%00001111;10
		db %00001111,%00001111;11
		db %00001111,%00001111;12
		db %00001111,%00001111;13
		db %00001111,%00001111;14
		db %11111111,%00000000;15
	else 							;SMS
		;   --BBGGRR
		db %00110000	;0
		db %00001111	;1
		db %00111100	;2
		db %00000011	;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
	endif
	
	
BitmapData:	;Smiley bitmap (8x8)
;Bitplane   00  11  22  33     = 16 color
        DB &3C,&00,&00,&00     ;  0
        DB &7E,&00,&00,&00     ;  1
        DB &FF,&24,&00,&00     ;  2
        DB &FF,&00,&00,&00     ;  3
        DB &FF,&00,&00,&00     ;  4
        DB &DB,&24,&00,&00     ;  5
        DB &66,&18,&00,&00     ;  6
        DB &3C,&00,&00,&00     ;  7
BitmapDataEnd:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
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
	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		
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

GetVDPScreenPos:	;Move to a memory address in VDP by BC cursor pos
	push bc				;B=Xpos, C=Ypos
		ifdef BuildSGG
			ld a,c
			add 3		;Need add 3 on Ypos for GG to reposition screen
			ld h,a
		else 
			ld h,c
		endif
		xor a			
		rr h			;Multiply Y*64
		rra
		rr h
		rra
		rlc b			;Multiply X*2 (Two byte per tile)
		or b
		ifdef BuildSGG
			add 6*2		;Need add 6 on Xpos for GG to reposition screen
		endif
		ld l,a
		ld a,h
		add &38			;Address of TileMap &3800 
		ld h,a				;(32x28 - 2 bytes per cell = &700 bytes)
		call prepareVram
	pop bc
	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
	
	ifdef BuildSGG	;Region & Rom size (see below) - only checked by SMS export bios
		db &6C		;GG Export - 32k
	else
		db &4C		;SMS Export - 32k
	endif

;&3- SMS Japan 
;&4- SMS Export 
;&5- GG 	Japan 
;&6- GG 	Export 
;&7- GG 	International 
;&-C 32KB   
;&-F 128KB   
;&-0 256KB   
;&-1 512KB

 