; Hello World 1.0
; February 2, 2007
; John Harrison
; Based mostly from GALP
	org &0000
	
; IRQs
	org &0040
;sVblankPos:
;cVblankpos equ &40-VblankPos
	;ds cVblankpos,0
;SECTION	"Vblank",HOME($0040)
	reti
;SECTION	"LCDC",HOME($0048)
sLCDC:
	;ds &48-sLCDC,0
		org &0048
	reti
;sTimer_Overflow:
	org &0050
	;ds &50-Timer_Overflow,0
;SECTION	"Timer_Overflow",HOME($0050)
	reti
sSerial:
	org &0058
;	ds &58-sSerial,0
	org &0058
;SECTION	"Serial",HOME($0058)
	reti
sp1thru4:
;SECTION	"p1thru4",HOME($0060)
;;	ds &60-sp1thru4,0
	org &0060
	reti

; ****************************************************************************************
; boot loader jumps to here.
; ****************************************************************************************
sstart:
	org &0100
	;ds &100-sstart,0
	;SECTION	"start",HOME($0100)
	nop
	jp	begin

; ****************************************************************************************
; ROM HEADER and ASCII character set
; ****************************************************************************************
; ROM header
	
 DB $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D
 DB $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99
 DB $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E

 DB "EXAMPLE",0,0,0,0,0,0,0,0 ; Cart name - 15bytes
 DB $80                         ; $143 - console $80 - color
 DB 0,0                       ; $144 - Licensee code (not important)
 DB 0                         ; $146 - SGB Support indicator
 DB 0	  		   			  ; $147 - Cart type
 DB 0                         ; $148 - ROM Size
 DB 0                         ; $149 - RAM Size
 DB 1                         ; $14a - Destination code
 DB $33                       ; $14b - Old licensee code
 DB 0                         ; $14c - Mask ROM version
 DB 0                         ; $14d - Complement check (important)
 DW 0                         ; $14e - Checksum (not important)

 

	
	
TileData:
	include "ibmpc1ape.asm" ; ASCII character set from devrs.com

; ****************************************************************************************
; Main code Initialization:
; set the stack pointer, enable interrupts, set the palette, set the screen relative to the window
; copy the ASCII character table, clear the screen
; ****************************************************************************************
begin:
	nop
	di
	ld	sp, $ffff		; set the stack pointer to highest mem location + 1
init:
	ld	a, %11100100 	; Window palette colors, from darkest to lightest
	ld	($FF47), a		; CLEAR THE SCREEN

	ld	a,0			; SET SCREEN TO TO UPPER RIGHT HAND CORNER
	ld	($FF43), a
	ld	($FF42), a		
	call	StopLCD		; YOU CAN NOT LOAD $8000 WITH LCD ON
	ld	hl, TileData
	ld	de, $8000 		; $8000
	ld	bc, 8*256 		; the ASCII character set: 256 characters, each with 8 bytes of display data
	call	mem_CopyMono	; load tile data
	;       LWwbBOoD
	ld	a, %11010101
;Bit 7 - LCD Control Operation *
;Bit 6 - Window Tile Map Display Select  0: $9800-$9BFF   1: $9C00-$9FFF
;Bit 5 - Window Display
;Bit 4 - BG & Window Tile Data Select                      0: $8800-$97FF                      1: $8000-$8FFF <- Same area as OBJ
;Bit 3 - BG Tile Map Display Select                      0: $9800-$9BFF                      1: $9C00-$9FFF
;Bit 2 - OBJ (Sprite) Size                      0: 8*8                      1: 8*16 (width*height)
;Bit 1 - OBJ (Sprite) Display
;Bit 0 - BG Display    0: off	1: on


	
	ld	($FF40), a	
	ld a,12*8
	ld ($FF4A),a ;wy
	xor a
	ld ($FF4B),a ;wx
	
	ld	a, 32		; ASCII FOR BLANK SPACE
	ld	hl, $9800
	ld	bc, 32 * 32
	call	mem_SetVRAM
	
	
	;      xBBBBBGGGGGRRRRR
	ld de,%0000001111100000
	    ;  xxcccppx
	LD	C,%00000110	; Colour 1 of Palette 1
	call SetGBCPAL

	;      xBBBBBGGGGGRRRRR
	ld de,%0011110000011111
	    ;  xxcccppx
	LD	C,%00000000	; Colour 0 of Palette 1
	call SetGBCPAL

	
	
	
	
; ****************************************************************************************
; Main code:
; Print a character string in the middle of the screen
; ****************************************************************************************
	

	ld	b,0
	ld  c,0
	ld d,0
NextScrPos:
	call getscreenpos
	di
	call VramWait
	ld (hl),d
	inc d
	inc c
	ld a,c
	cp 20
	jr nz,NextScrPos
	ld c,0
	inc b
	ld a,b
	cp 18
	jr nz,NextScrPos
	;jr nz,NextScrPos
	di
	halt
	ld bc,&1800-1
	ld hl,&8000
	ld de,&8001
	call Ldir
	
	
	
	di
	halt
getscreenpos:	;B=Ypos, C=Xpos
	push bc
		ld	hl, $9800
		xor a
		rr b
		rra
		rr b
		rra
		rr b
		rra
		or c
		ld c,a
		add hl,bc
	pop bc
		
	ret

Ldir:
	push af
Ldirb:
		ld a,(hl)
		ld (de),a
		inc hl
		inc de
		dec c
		jr nz,Ldirb
		dec b
		jr nz,Ldirb
	pop af
	ret
FillAgain:
	ld (de),a
	inc de
	inc a
	dec c
	jr nz,FillAgain
	dec b
	jr nz,FillAgain
	ei
	
	
; ****************************************************************************************
; Prologue
; Wait patiently 'til somebody kills you
; ****************************************************************************************
wait:
	halt
	nop
	jr	wait
	
; ****************************************************************************************
; hard-coded data
; ****************************************************************************************
Title:
	DB	"Vasm World !"
TitleEnd:

SetGBCPAL:
	LD	HL,$FF68	; set up a pointer to the BCPS
	LD	A,C			; Load A with the write specification data
	LDI	(HL),A		; place the data in the specification register and move the pointer to the  BCPD
	LD	A,E			; get the low data BYTE
	LDI	(HL),A		; send the low data BYTE to the register
	LD	HL,$FF68	; set the pointer back to the BCPS
	LD	A,C			; Load A with the write specification data
	INC	A			; Add 1 to the data, therefore setting BIT 0 which means we are now writing the high data BYTE
	LDI	(HL),A		; place the data in the specification register and move the pointer to the BCPD
	LD	A,D			; get the high data BYTE
	LDI	(HL),A		; send the high data BYTE to the register
ret

VramWait:
		push af
VramWaitAgain:
			ld      a,($FF41) 
			and     %00000010 
			jr nz,VramWaitAgain
		pop af
		ret
		

		
; ****************************************************************************************
; StopLCD:
; turn off LCD if it is on
; and wait until the LCD is off
; ****************************************************************************************
StopLCD:
        ld      a,($FF40)
        rlca                    ; Put the high bit of LCDC into the Carry flag
        ret     nc              ; Screen is off already. Exit.

; Loop until we are in VBlank

.wait:
        ld      a,($FF44)
        cp      145             ; Is display on scan line 145 yet?
        jr      nz,.wait        ; no, keep waiting

; Turn off the LCD

        ld      a,($FF40)
        res     7,a             ; Reset bit 7 of LCDC
        ld      ($FF40),a

        ret
mem_CopyVRAM:
	inc	b
	inc	c
	jr	.skip
.loop   di
        ;lcd_WaitVRAM
.waitagain
        ld      a,($FF41)       ; <---+
        and     %00000010      ;     |
        jr      nz,.waitagain         ; ----+
		
        ldi      a,(hl)
	ld	(de),a
        ei
	inc	de
.skip	dec	c
	jr	nz,.loop
	dec	b
	jr	nz,.loop
	ret
	
mem_SetVRAM::
	inc	b
	inc	c
	jr	.skip
.loop   push    af
        di
.waitagain
        ld      a,($FF41)       ; <---+
        and     %00000010      ;     |
        jr      nz,.waitagain         ; ----+
		
        pop     af
        ldi      (hl),a
        ei
.skip	dec	c
	jr	nz,.loop
	dec	b
	jr	nz,.loop
	ret
	
mem_CopyMono::
	inc	b
	inc	c
	jr	.skip
.loop	ldi	a,(hl)
	ld	(de),a
	inc	de
        ld      (de),a
        inc     de
.skip	dec	c
	jr	nz,.loop
	dec	b
	jr	nz,.loop
	ret