code 'key',key

	extern SDL_WaitEvent

section .bss
	event 		resd 	200 	; must be big enough to hold all 
					; kinds of SDL events. Could probably
					; be smaller
	pressed_key 	resd 	1
	KEY_DOWN 	equ 	2
	KEY_OFS 	equ 	16

section .data
	keyerror db "SDL: error while waiting for event"
	keyerrorlen: 

section .text
	dup
	pusha

sdl_test_event:
	push event
	call SDL_WaitEvent
	pop ebx
	mov ecx,keyerror
	mov edx,keyerrorlen - keyerror
	call error_if_zero
	mov eax,[event]
	and eax,0ffh		; remove cruft...
	cmp eax,KEY_DOWN
	jne sdl_test_event;

	mov eax,[event+KEY_OFS]	; get the key
	cmp eax,0		; funny char 
	jz sdl_test_event	; ignore it
	cmp eax,100h		; multibyte char
	jae sdl_test_event	; ignore it
	cmp al,0dh		; cr pressed
	jne .skip_translate_cr
	mov al,0ah		; lf expected by editor
.skip_translate_cr:

	mov [pressed_key],eax
	popa
	mov eax,[pressed_key]
	ret
;---------------------------------------------------------------
;BLIT - Copy a rectangle to (x,y)
;	( w h x y -- )
code 'blit', blit

section .text

	push edx
	push edi
	call clip	;current position in ESI (temporarily in EDX)
	mov edx,edi
	call $at	;new position in EDI
	call clip
	upop ecx	;width in EAX, height in ECX

	call store_and_lock

	xchg esi,edx
.1	  push ecx
	  mov ecx,eax
	  rep movsb
	  mov ecx,dword [hp]
	  sub ecx,eax
	  add esi,ecx
	  add edi,ecx
	  pop ecx
	  loop .1
	xchg esi,edx
	pop edi
	pop edx
	drop

	call unlock_and_flip
next
code 'rect', rect

section .text

	push ecx
	push edx
	push edi
	call clip
	upop ecx		  ;h
	mov edx,eax		  ;w

	call store_and_lock

	mov eax,dword [fore]           ;color
.1	push ecx
        mov ecx,edx		  ;w
	rep stosb
	add edi,dword [hp]
	sub edi,edx
	pop ecx
	loop .1
	pop edi
	pop edx
	pop ecx
	drop

	call unlock_and_flip

 next
code 'emit', emit

section .text

	push esi			; emit
	push edi			;  Store a few registers
	push ecx
	push edx
	call ?cr			;  Wrap to a new line?
.0	and eax,0xff			;  Filter byte
	imul eax,ih*iw/8		;  byte/char in FONT
	lea esi,[font+eax]		;  Load byte from FONT
	call clip			;  Clip the drawing region
	mov edx,[fore] 			;  color (2 = green)
	mov ecx,ih		;  Height of character

	push eax
	mov eax,iw
	call store_and_lock
	pop eax

.line	
	push ecx			;  Store height
	lodsb			 	;  al=font line
	mov ecx,iw			;  Width of character
.pix	
	shl al,1			;  Begin drawing the character
	jnc .1
	mov [edi],dl			;  Store a pixel
.1	
	inc edi
	loop .pix			;  Is this line done?

	add edi,dword [hp]
	sub edi, iw			;  Yes? Then do next line
	pop ecx				;  Restore height/width
	loop .line			;  Are we done?

	pop edx				;  Yes!
	pop ecx				;  Restore the registers
	pop edi
	pop esi
	drop				; drop the character from stack
      add [xy],dword (iw<<16)		; And advance one space

	call unlock_and_flip

next
code 'bye',bye
	sub ebx,ebx	;Return exit status 0
	mov eax,ebx
	inc eax		;1 = sys_exit
	int 80h
;---------------------------------------------------------------
code 'at', $at
   shl eax, 16
   call $plus
   mov dword [xy], eax
   drop
next
;---------------------------------------------------------------
clip:
	mov edi,[xy]
	mov ecx,edi
	test cx,cx
	jns .1
	xor ecx,ecx
.1	and ecx,0xffff
	imul ecx,dword [hp]		;320*2 for 16-bit gfx
	sar edi,16
	jns .2
	xor edi,edi
.2	lea edi,[edi+ecx]	;edi*2 for 16-bit
      add edi,dword [frame]
next
;---------------------------------------------------------------
code 'cr', cr
	push ecx
        xor ecx,ecx     ;x=0
	mov cx,[xy]
	add cx,ih	;y=y+ih
	mov [xy],ecx
      add ecx,8
.scroll cmp cx,[vp]
        js .1
        pusha
        embed 'scroll'
        popa
.1      pop ecx
.2      ret
?cr:    push ecx
        mov cx,[xy+2]   ;x
        cmp cx,[hp]
        pop ecx
        js cr.2
        jmp cr

; ( Common data and routines needed by the SDL enabled drivers  )

;%include "inc/divio.asm"

extern SDL_Init
extern SDL_SetVideoMode
extern SDL_LockSurface
extern SDL_UnlockSurface
extern SDL_UpdateRect
extern SDL_EnableUNICODE

section .bss
	screen resd 1		; screen structure pointer (SDL_Surface)
	WIDTH_OFS equ 8		; offset to width in screen structure
	HEIGHT_OFS equ 12	; offset to height
	PITCH_OFS equ 16	; offet to pitch
	PIXELS_OFS equ 20	; offset to pointer to pixel data

	BPP equ 8 		; bits per pixel

	SDL_INIT_VIDEO equ 0x20
	SDL_SWSURFACE equ 0

	; variables for temporary storage of coordinates and dimensions,
	; used by the graphics drivers.
	rectx resd 1
	recty resd 1
	rectw resd 1
	recth resd 1

section .data
	initerror db "SDL: init failed"
	initerrorlen:
	modeerror db "SDL: videomode failed to initialize"
	modeerrorlen:
	widtherror db "SDL: wrong width"
	widtherrorlen:
	heighterror db "SDL: wrong height"
	heighterrorlen:
	pitcherror db "SDL: width != pitch"
	pitcherrorlen:
	lockerror db "SDL: failed to lock screen"
	lockerrorlen:

section .text
sdl_init:
	; initialize sdl
	push dword SDL_INIT_VIDEO
	call SDL_Init
	pop ebx
	mov ecx, initerror
	mov edx, initerrorlen - initerror
	call error_if_not_zero

	; enable unicode keysymbols, needed by the keyboard driver.
	push dword 1
	call SDL_EnableUNICODE
	pop ebx
		
	; set video mode
	push dword SDL_SWSURFACE
	push dword BPP
	push dword [vp]
	push dword [hp]
	call SDL_SetVideoMode
	add esp,16		; pop dword * 4
	mov [screen],eax
	mov ecx, modeerror
	mov edx, modeerrorlen - modeerror
	call error_if_zero

	; test if the mode given equals the requested
	mov ebx,[screen]
	mov eax,[ebx+WIDTH_OFS]
	sub eax,[hp]
	mov ecx, widtherror
	mov edx, widtherrorlen - widtherror
	call error_if_not_zero
	mov eax,[ebx+HEIGHT_OFS]
	sub eax,[vp]
	mov ecx, heighterror
	mov edx, heighterrorlen - heighterror
	call error_if_not_zero

	; SDL allows for the screen buffer to be wider than the actual sreen.
	; pitch is the number of bytes from the begining of one line
	; to the begining of the next. The drivers can't handle a situation 
	; where pitch != width,.
	xor eax,eax
	mov ax,[ebx+PITCH_OFS]
	sub eax,[hp]
	mov ecx, heighterror
	mov edx, heighterrorlen - heighterror
	call error_if_not_zero

	ret
	
lock_screen:	
	push dword [screen]
	call SDL_LockSurface
	pop ebx
	mov ecx, lockerror
	mov edx, lockerrorlen - lockerror
	call error_if_not_zero
	ret
	
unlock_screen:
	push dword [screen]
	call SDL_UnlockSurface
	pop eax
	ret

	; assumes: 
	;	eax = x
	;	ebx = y
	;	ecx = width
	;	edx = height
flip_rect:
	push dword edx
	push dword ecx
	push dword ebx
	push dword eax
	push dword [screen]
	call SDL_UpdateRect
	add esp,20		; pop dword * 5
	ret

	; assumes:
	;	eax = some value to be tested
error_if_not_zero:
	cmp eax,0
	jne error_if_zero.1
	ret
error_if_zero:
	cmp eax,0
	jnz .2
.1:
	mov eax,4
	mov ebx,1
	int 0x80		; print string
	mov ebx,1
	mov eax,1
	int 0x80		; exit
.2:
	ret

	; stores the coordinates and dimentions of an area of
	; the screen and locks the screen
	;assumes:
	;	edi = pointer to current postion on screen
	;	ecx = width
	;	eax = height
store_and_lock:
	pusha
	mov dword [rectw],eax
	mov dword [recth],ecx

	; this is a kludge...
	; edi points to the current position in screen memory.
	; by substracting [frame] and divide by the screen width
	; the vertical position is found. The horizontal position
	; is the remainder. Maybe this position is stored 
	; somewhere?
	mov ebx,[hp]
	xor edx,edx
	mov eax,edi
	sub eax,[frame]
	div ebx
	mov [recty],dword eax
	mov [rectx],dword edx

	call lock_screen
	popa
	ret

	; unlocks and updates the screen
unlock_and_flip:
	pusha
	call unlock_screen
	mov eax,[rectx]
	mov ebx,[recty]
	mov ecx,[rectw]
	mov edx,[recth]
	call flip_rect
	popa
	ret


; ---------------------------------------------------
; Graphical Settings
; ---------------------------------------------------
ih equ 8                       ; Font height
iw equ 8                       ; Font width
var 'color', fore, 0           ; Foreground (text) color
var 'xy', xy, 0                ; Starting X,Y position
var 'hp', hp, 640              ; Screen Width (pixels)
var 'vp', vp, 480              ; Screen Height (pixels)
var 'hc', hc, 640/iw           ; Screen Width (characters)
var 'vc', vc, 480/ih           ; Screen Height (characters)
var 'frame', frame, 0xA0000    ; Address of video RAM

section .data
font: incbin "font"   ; Pathname to the font file
section .text

section .bss
tib  resb   200h
sp0  resb   300h
d0   resb 10000h
h0   resb 80000h
section .text
