
UserRam Equ &C000				;System Memory

vdpControl equ &BF
vdpData    equ &BE

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

	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														

	;Define our character tiles
	ld de, 0*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
	
	;Define 25x20 Screen
	ld bc,&0000		;Start Position in BC
	ld hl,&1914		;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 de,0			;SMS has 512 tiles, so start at 256
	
	call FillAreaWithTiles		;Fill a grid area with consecutive tiles 

	ld c,0
	ld b,8
PSetAgain:
	ld d,15
	call PSET
	inc c
	inc b
	ld a,c
	cp 80
	jr nz,PSetAgain
	
	di
	halt
	
PSET:		;BC=XYpos  D=Color
	push bc
		push de
			ld hl,PixelMask
			ld a,b
			and %00000111
			add l
			ld l,a
			ld a,(hl)
			ld d,a
			cpl 
			ld e,a
			push de
				
				ld hl,0
				ld de,4
				ld a,b
				and %11111000
				call nz,mult
				
				ld de,4
				ld a,c
				and %00000111
				call nz,mult
				
				ld de,25*4
				ld a,c
				and %11111000
				call nz,mult
				
				call prepareVramRead
			pop bc			
			in a,(vdpData)
			and c
			ld ixh,a
			in a,(vdpData)
			and c
			ld ixl,a
			in a,(vdpData)
			and c
			ld iyh,a
			in a,(vdpData)
			and c
			ld iyl,a
			call prepareVram
		pop de
		ld a,ixh
		rr d
		jr nc,Pset1
		or b
Pset1:
		out (vdpData),a
		ld a,ixl
		rr d
		jr nc,Pset2
		or b
Pset2:
		out (vdpData),a
		ld a,iyh
		rr d
		jr nc,Pset3
		or b
Pset3:
		out (vdpData),a
		ld a,iyl
		rr d
		jr nc,Pset4
		or b
Pset4:
		out (vdpData),a
	pop bc
	ret
	
	align 4
PixelMask:
	db %10000000,%01000000,%00100000,%00010000,%00001000,%00000100,%00000010,%00000001
	
mult:
	add hl,de
	dec a
	ret z
	jp mult
	
	
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							;this does not cause a problem
	
prepareVramRead:				;Set vdpData to write to memory address HL in vram
	    ld a,l
	    out (vdpControl),a
	    ld a,h
	    out (vdpControl),a	;As the VDP ram only goes from &0000-&3FFF 
    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,%00000000;0
		db %00000111,%00000111;1
		db %11110000,%00001111;2
		db %11111111,%11111111;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 %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
	endif
	
BitmapData:	;Sprite Data of our Chibiko character
	incbin "Z:\ResALL\Sprites\RawSMS.RAW"
BitmapDataEnd:

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

FillAreaWithTiles:	;BC = X,Y	HL = W,H 	DE = Start Tile
	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
		push hl
			call GetVDPScreenPos	;Move to the correcr VDP location
		pop hl	
FillAreaWithTiles_Xagain:;Tilemap takes two bytes, ---pcvhn nnnnnnnn
		ld a,e			;nnnnnnnn - Tile number
		out (vdpData),a	
		ld a,d			;---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)
		inc de
		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
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
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
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

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

 