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