view modules/sdl.tp @ 347:ff7ea11b4b60

Add length method to executable bytearrays
author Michael Pavone <pavone@retrodev.com>
date Fri, 10 Apr 2015 00:48:12 -0700
parents 6bbf12c203f7
children
line wrap: on
line source
{
	_helper <- #{
		llMessage: createWindow withVars: {
			title <- string ptr
			x <- obj_int32 ptr
			y <- obj_int32 ptr
			w <- obj_int32 ptr
			h <- obj_int32 ptr
			flags <- obj_uint32 ptr
			makeWindow <- lambda ptr
			windowOpaque <- cpointer ptr
			win <- object ptr
		} andCode: :title x y w h flags makeWindow {
			windowOpaque <- make_object: (addr_of: cpointer_meta) NULL 0
			windowOpaque val!: (SDL_CreateWindow: (title data) (x num) (y num) (w num) (h num) (flags num))
			if: (windowOpaque val) {
				win <- ccall: makeWindow 1 (windowOpaque castTo: (object ptr))
				mcall: value 2 option win
			} else: {
				mcall: none 1 option
			}
		}

		llMessage: createRenderer withVars: {
			window <- cpointer ptr
			index <- obj_int32 ptr
			flags <- obj_uint32 ptr
			rendOpaque <- cpointer ptr
			rend <- object ptr
			makeRender <- lambda ptr
		} andCode: :window index flags makeRender {
			rendOpaque <- make_object: (addr_of: cpointer_meta) NULL 0
			rendOpaque val!: (SDL_CreateRenderer: (window val) (index num) (flags num))
			if: (rendOpaque val) {
				rend <- ccall: makeRender 1 (rendOpaque castTo: (object ptr))
				mcall: value 2 option rend
			} else: {
				mcall: none 1 option
			}
		}

		llMessage: loadBMP withVars: {
			filename <- string ptr
			makeSurface <- lambda ptr
			surfOpaque <- cpointer ptr
			surf <- object ptr
		} andCode: :filename makeSurface{
			surfOpaque <- make_object: (addr_of: cpointer_meta) NULL 0
			surfOpaque val!: (SDL_LoadBMP: (filename data))
			if: (surfOpaque val) {
				surf <- ccall: makeSurface 1 (surfOpaque castTo: (object ptr))
				mcall: value 2 option surf
			} else: {
				mcall: none 1 option
			}
		}

		llMessage: createTextureFromSurface withVars: {
			rendOpaque <- cpointer ptr
			surfOpaque <- cpointer ptr
			makeTexture <- lambda ptr
			texOpaque <- cpointer ptr
			tex <- object ptr
		} andCode: :rendOpaque surfOpaque makeTexture {
			texOpaque <- make_object: (addr_of: cpointer_meta) NULL 0
			texOpaque val!: (SDL_CreateTextureFromSurface: (rendOpaque val) (surfOpaque val))
			if: (texOpaque val) {
				tex <- ccall: makeTexture 2 (rendOpaque castTo: (object ptr)) (texOpaque castTo: (object ptr))
				mcall: value 2 option tex
			} else: {
				mcall: none 1 option
			}
		}
		
		llMessage: createTexture withVars: {
			rendOpaque <- cpointer ptr
			format <- object ptr
			formatn <- obj_uint32 ptr
			access <- object ptr
			accessn <- obj_int32 ptr
			w <- object ptr
			wn <- obj_int32 ptr
			h <- object ptr
			hn <- obj_int32 ptr
			makeTexture <- lambda ptr
			texOpaque <- cpointer ptr
			tex <- object ptr
		} andCode: :rendOpaque format access w h makeTexture {
			formatn <- (mcall: uint32 1 format) castTo: (obj_uint32 ptr)
			accessn <- (mcall: int32 1 access) castTo: (obj_int32 ptr)
			wn <- (mcall: int32 1 w) castTo: (obj_int32 ptr)
			hn <- (mcall: int32 1 h) castTo: (obj_int32 ptr)
			texOpaque <- make_object: (addr_of: cpointer_meta) NULL 0
			texOpaque val!: (SDL_CreateTexture: (rendOpaque val) (formatn num) (accessn num) (wn num) (hn num))
			if: (texOpaque val) {
				tex <- ccall: makeTexture 2 (rendOpaque castTo: (object ptr)) (texOpaque castTo: (object ptr))
				mcall: value 2 option tex
			} else: {
				mcall: none 1 option
			}
		}

		llMessage: pollEvent withVars: {
			constructor <- lambda ptr
			event <- SDL_Event
			eventPtr <- cpointer ptr
			eventType <- obj_uint32 ptr
			timeStampO <- obj_uint32 ptr
		} andCode: :constructor {
			if: (SDL_PollEvent: (addr_of: event)) {
				eventType <- make_object: (addr_of: obj_uint32_meta) NULL 0
				timeStampO <- make_object: (addr_of: obj_uint32_meta) NULL 0
				eventType num!: ((addr_of: event) type)
				timeStampO num!: ((addr_of: ((addr_of: event) common)) timestamp)
				eventPtr <- make_object: (addr_of: cpointer_meta) NULL 0
				eventPtr val!: (addr_of: event)
				mcall: value 2 option (ccall: constructor 3 (eventType castTo: (object ptr)) (
					timeStampO castTo: (object ptr)) (eventPtr castTo: (object ptr)))
			} else: {
				mcall: none 1 option
			}
		}
		
		llMessage: waitEvent withVars: {
			constructor <- lambda ptr
			event <- SDL_Event
			eventPtr <- cpointer ptr
			eventType <- obj_uint32 ptr
			timeStampO <- obj_uint32 ptr
		} andCode: :constructor {
			if: (SDL_WaitEvent: (addr_of: event)) {
				eventType <- make_object: (addr_of: obj_uint32_meta) NULL 0
				timeStampO <- make_object: (addr_of: obj_uint32_meta) NULL 0
				eventType num!: ((addr_of: event) type)
				timeStampO num!: ((addr_of: ((addr_of: event) common)) timestamp)
				eventPtr <- make_object: (addr_of: cpointer_meta) NULL 0
				eventPtr val!: (addr_of: event)
				mcall: value 2 option (ccall: constructor 3 (eventType castTo: (object ptr)) (
					timeStampO castTo: (object ptr)) (eventPtr castTo: (object ptr)))
			} else: {
				mcall: none 1 option
			}
		}

		llMessage: populateWindowEvent withVars: {
			eventPtr <- cpointer ptr
			empty <- object ptr
			winEvent <- SDL_WindowEvent ptr
			ou32 <- obj_uint32 ptr
			oi32 <- obj_int32 ptr
		} andCode: :eventPtr empty {
			winEvent <- eventPtr val
			ou32 <- make_object: (addr_of: obj_uint32_meta) NULL 0
			ou32 num!: (winEvent windowID)
			mcall: windowID! 2 empty ou32
			ou32 <- make_object: (addr_of: obj_uint32_meta) NULL 0
			ou32 num!: (winEvent event)
			mcall: event! 2 empty ou32
			oi32 <- make_object: (addr_of: obj_int32_meta) NULL 0
			oi32 num!: (winEvent data1)
			mcall: data1! 2 empty oi32
			oi32 <- make_object: (addr_of: obj_int32_meta) NULL 0
			oi32 num!: (winEvent data2)
			mcall: data2! 2 empty oi32
			empty
		}

		llMessage: populateKeyEvent withVars: {
			eventPtr <- cpointer ptr
			empty <- object ptr
			keyEvent <- SDL_KeyboardEvent ptr
			ou32 <- obj_uint32 ptr
			ou16 <- obj_uint32 ptr
			ou8 <- obj_uint8 ptr
		} andCode: :eventPtr empty {
			keyEvent <- eventPtr val
			ou32 <- make_object: (addr_of: obj_uint32_meta) NULL 0
			ou32 num!: (keyEvent windowID)
			mcall: windowID! 2 empty ou32
			if: (keyEvent state) = SDL_PRESSED {
				mcall: pressed?! 2 empty true
			} else: {
				mcall: pressed?! 2 empty false
			}
			ou8 <- make_object: (addr_of: obj_uint8_meta) NULL 0
			ou8 num!: (keyEvent repeat)
			mcall: repeat! 2 empty ou8
			ou32 <- make_object: (addr_of: obj_uint32_meta) NULL 0
			ou32 num!: ((addr_of: (keyEvent keysym)) scancode)
			mcall: scanCode! 2 empty ou32
			ou32 <- make_object: (addr_of: obj_uint32_meta) NULL 0
			ou32 num!: ((addr_of: (keyEvent keysym)) sym)
			mcall: keyCode! 2 empty ou32
			ou16 <- make_object: (addr_of: obj_uint16_meta) NULL 0
			ou16 num!: ((addr_of: (keyEvent keysym)) mod)
			mcall: mod! 2 empty ou16
			empty
		}

		llMessage: populateMouseButtonEvent withVars: {
			eventPtr <- cpointer ptr
			empty <- object ptr
			mouseButEvent <- SDL_MouseButtonEvent ptr
			ou32 <- obj_uint32 ptr
			ou8 <- obj_uint8 ptr
			oi32 <- obj_int32 ptr
		} andCode: :eventPtr empty {
			mouseButEvent <- eventPtr val
			ou32 <- make_object: (addr_of: obj_uint32_meta) NULL 0
			ou32 num!: (mouseButEvent windowID)
			mcall: windowID! 2 empty ou32
			ou32 <- make_object: (addr_of: obj_uint32_meta) NULL 0
			ou32 num!: (mouseButEvent which)
			mcall: mouseID! 2 empty ou32
			ou8 <- make_object: (addr_of: obj_uint8_meta) NULL 0
			ou8 num!: (mouseButEvent button)
			mcall: button! 2 empty ou8
			if: (mouseButEvent state) = SDL_PRESSED {
				mcall: pressed?! 2 empty true
			} else: {
				mcall: pressed?! 2 empty false
			}
			ou8 <- make_object: (addr_of: obj_uint8_meta) NULL 0
			ou8 num!: (mouseButEvent clicks)
			mcall: clicks! 2 empty ou8
			oi32 <- make_object: (addr_of: obj_int32_meta) NULL 0
			oi32 num!: (mouseButEvent x)
			mcall: x! 2 empty oi32
			oi32 <- make_object: (addr_of: obj_int32_meta) NULL 0
			oi32 num!: (mouseButEvent y)
			mcall: y! 2 empty oi32
			empty
		}

		llMessage: populateMouseMotionEvent withVars: {
			eventPtr <- cpointer ptr
			empty <- object ptr
			mouseMotEvent <- SDL_MouseMotionEvent ptr
			ou32 <- obj_uint32 ptr
			oi32 <- obj_int32 ptr
		} andCode: :eventPtr empty {
			mouseMotEvent <- eventPtr val
			ou32 <- make_object: (addr_of: obj_uint32_meta) NULL 0
			ou32 num!: (mouseMotEvent windowID)
			mcall: windowID! 2 empty ou32
			ou32 <- make_object: (addr_of: obj_uint32_meta) NULL 0
			ou32 num!: (mouseMotEvent which)
			mcall: mouseID! 2 empty ou32
			ou32 <- make_object: (addr_of: obj_uint32_meta) NULL 0
			ou32 num!: (mouseMotEvent state)
			mcall: buttonState! 2 empty ou32
			oi32 <- make_object: (addr_of: obj_int32_meta) NULL 0
			oi32 num!: (mouseMotEvent x)
			mcall: x! 2 empty oi32
			oi32 <- make_object: (addr_of: obj_int32_meta) NULL 0
			oi32 num!: (mouseMotEvent y)
			mcall: y! 2 empty oi32
			oi32 <- make_object: (addr_of: obj_int32_meta) NULL 0
			oi32 num!: (mouseMotEvent xrel)
			mcall: xRel! 2 empty oi32
			oi32 <- make_object: (addr_of: obj_int32_meta) NULL 0
			oi32 num!: (mouseMotEvent yrel)
			mcall: yRel! 2 empty oi32
			empty
		}
	}

	_constant <- macro: :name cname {
		quote: (llMessage: name withVars: {
			uintret <- obj_uint32 ptr
		} andCode: {
			uintret <- make_object: (addr_of: obj_uint32_meta) NULL 0
			uintret num!: cname
			uintret
		})
	}
	_subsystems <- #{
		_constant: timer SDL_INIT_TIMER
		_constant: audio SDL_INIT_AUDIO
		_constant: video SDL_INIT_VIDEO
		_constant: joystick SDL_INIT_JOYSTICK
		_constant: haptic SDL_INIT_HAPTIC
		_constant: gameController SDL_INIT_GAMECONTROLLER
		_constant: events SDL_INIT_EVENTS
		_constant: everything SDL_INIT_EVERYTHING
	}

	_windowOpts <- #{
		_constant: fullscreen SDL_WINDOW_FULLSCREEN
		_constant: fullscreenDesktop SDL_WINDOW_FULLSCREEN_DESKTOP
		_constant: opengl SDL_WINDOW_OPENGL
		_constant: hidden SDL_WINDOW_HIDDEN
		_constant: borderless SDL_WINDOW_BORDERLESS
		_constant: minimized SDL_WINDOW_MINIMIZED
		_constant: maximized SDL_WINDOW_MAXIMIZED
		_constant: inputGrabbed SDL_WINDOW_INPUT_GRABBED
		_constant: allowHighDPI SDL_WINDOW_ALLOW_HIGHDPI
	}

	_renderOpts <- #{
		_constant: software SDL_RENDERER_SOFTWARE
		_constant: accelerated SDL_RENDERER_ACCELERATED
		_constant: presentVSYNC SDL_RENDERER_PRESENTVSYNC
		_constant: targetTexture SDL_RENDERER_TARGETTEXTURE

	}

	_events <- #{
		_constant: quit SDL_QUIT
		_constant: window SDL_WINDOWEVENT
		_constant: sysWM SDL_SYSWMEVENT
		_constant: keyDown SDL_KEYDOWN
		_constant: keyUp SDL_KEYUP
		_constant: textEditing SDL_TEXTEDITING
		_constant: textInput SDL_TEXTINPUT
		_constant: mouseMotion SDL_MOUSEMOTION
		_constant: mouseDown SDL_MOUSEBUTTONDOWN
		_constant: mouseUp SDL_MOUSEBUTTONUP
		_constant: mouseWheel SDL_MOUSEWHEEL
		_constant: joyAxis SDL_JOYAXISMOTION
		_constant: joyBall SDL_JOYBALLMOTION
		_constant: joyHat SDL_JOYHATMOTION
		_constant: joyDown SDL_JOYBUTTONDOWN
		_constant: joyUp SDL_JOYBUTTONUP
		_constant: joyDeviceAdded SDL_JOYDEVICEADDED
		_constant: joyDeviceRemoved SDL_JOYDEVICEREMOVED
		_constant: controllerAxis SDL_CONTROLLERAXISMOTION
		_constant: controllerDown SDL_CONTROLLERBUTTONDOWN
		_constant: controllerUp SDL_CONTROLLERBUTTONUP
		_constant: controllerDeviceAdded SDL_CONTROLLERDEVICEADDED
		_constant: controllerDeviceRemoved SDL_CONTROLLERDEVICEREMOVED
		_constant: controllerDeviceRemapped SDL_CONTROLLERDEVICEREMAPPED
		_constant: dropFile SDL_DROPFILE
		//TODO: Add mobile/touch/gesture events
	}
	
	_windowEvents <- #{
		_constant: shown SDL_WINDOWEVENT_SHOWN
		_constant: hidden SDL_WINDOWEVENT_HIDDEN
		_constant: exposed SDL_WINDOWEVENT_EXPOSED
		_constant: moved SDL_WINDOWEVENT_MOVED
		_constant: resized SDL_WINDOWEVENT_RESIZED
		_constant: sizeChanged SDL_WINDOWEVENT_SIZE_CHANGED
		_constant: minimized SDL_WINDOWEVENT_MINIMIZED
		_constant: maximized SDL_WINDOWEVENT_MAXIMIZED
		_constant: restored SDL_WINDOWEVENT_RESTORED
		_constant: enter SDL_WINDOWEVENT_ENTER
		_constant: leave SDL_WINDOWEVENT_LEAVE
		_constant: focusGained SDL_WINDOWEVENT_FOCUS_GAINED
		_constant: focusLost SDL_WINDOWEVENT_FOCUS_LOST
		_constant: close SDL_WINDOWEVENT_CLOSE
	}
	
	_textureAccess <- #{
		_constant: static SDL_TEXTUREACCESS_STATIC
		_constant: streaming SDL_TEXTUREACCESS_STREAMING
		_constant: target SDL_TEXTUREACCESS_TARGET
	}
	
	_pixelFormats <- #{
		_constant: unknown SDL_PIXELFORMAT_UNKNOWN
		_constant: index1LSB SDL_PIXELFORMAT_INDEX1LSB
		_constant: index1MSB SDL_PIXELFORMAT_INDEX1MSB
		_constant: index4LSB SDL_PIXELFORMAT_INDEX4LSB
		_constant: index4MSB SDL_PIXELFORMAT_INDEX4MSB
		_constant: index8 SDL_PIXELFORMAT_INDEX8
		_constant: rgb332 SDL_PIXELFORMAT_RGB332
		_constant: rgb444 SDL_PIXELFORMAT_RGB444
		_constant: rgb555 SDL_PIXELFORMAT_RGB555
		_constant: bgr555 SDL_PIXELFORMAT_BGR555
		_constant: argb4444 SDL_PIXELFORMAT_ARGB4444
		_constant: bgra4444 SDL_PIXELFORMAT_BGRA4444
		_constant: argb1555 SDL_PIXELFORMAT_ARGB1555
		_constant: rgba5551 SDL_PIXELFORMAT_RGBA5551
		_constant: abgr1555 SDL_PIXELFORMAT_ABGR1555
		_constant: bgra5551 SDL_PIXELFORMAT_BGRA5551
		_constant: rgb565 SDL_PIXELFORMAT_RGB565
		_constant: bgr565 SDL_PIXELFORMAT_BGR565
		_constant: rgb24 SDL_PIXELFORMAT_RGB24
		_constant: bgr24 SDL_PIXELFORMAT_BGR24
		_constant: rgb888 SDL_PIXELFORMAT_RGB888
		_constant: rgbx8888 SDL_PIXELFORMAT_RGBX8888
		_constant: bgr888 SDL_PIXELFORMAT_BGR888
		_constant: bgrx8888 SDL_PIXELFORMAT_BGRX8888
		_constant: argb8888 SDL_PIXELFORMAT_ARGB8888
		_constant: rgba8888 SDL_PIXELFORMAT_RGBA8888
		_constant: abgr8888 SDL_PIXELFORMAT_ABGR8888
		_constant: bgra8888 SDL_PIXELFORMAT_BGRA8888
		_constant: argb2101010 SDL_PIXELFORMAT_ARGB2101010
		_constant: yv12 SDL_PIXELFORMAT_YV12
		_constant: iyuv SDL_PIXELFORMAT_IYUV
		_constant: yuy2 SDL_PIXELFORMAT_YUY2
		_constant: uyvy SDL_PIXELFORMAT_UYVY
		_constant: yvyu SDL_PIXELFORMAT_YVYU
	}
	
	_blendModes <- #{
		_constant: none SDL_BLENDMODE_NONE
		_constant: blend SDL_BLENDMODE_BLEND
		_constant: add SDL_BLENDMODE_ADD
		_constant: mod SDL_BLENDMODE_MOD
	}

	_eventConstructors <- dict hash
	_eventConstructors set: (_events window) :typ tstamp eventPtr {
		_helper populateWindowEvent: eventPtr #{
			type <- typ
			timeStamp <- tstamp
			windowID <- 0u32
			event <- 0u32
			data1 <- 0
			data2 <- 0
		}
	}
	keyEvent <- :typ tstamp eventPtr {
		_helper populateKeyEvent: eventPtr #{
			type <- typ
			timeStamp <- tstamp
			windowID <- 0u32
			pressed? <- false
			repeat <- 0u8
			scanCode <- 0
			keyCode <- 0
			mod <- 0u16
			_constant: scanCodeMask SDLK_SCANCODE_MASK
			keyChar <- {
				if: (keyCode and (self scanCodeMask)) = 0 {
					keyCode utf8
				} else: {
					""
				}
			}
		}
	}
	_eventConstructors set: (_events keyDown) keyEvent
	_eventConstructors set: (_events keyUp) keyEvent

	mouseButtonEvent <- :typ tstamp eventPtr {
		_helper populateMouseButtonEvent: eventPtr #{
			type <- typ
			timeStamp <- tstamp
			windowID <- 0u32
			mouseID <- 0u32
			button <- 0u8
			pressed? <- false
			clicks <- 0u8
			x <- 0
			y <- 0
		}
	}
	_eventConstructors set: (_events mouseDown) mouseButtonEvent
	_eventConstructors set: (_events mouseUp) mouseButtonEvent

	_eventConstructors set: (_events mouseMotion) :typ tstamp eventPtr {
		_helper populateMouseMotionEvent: eventPtr #{
			type <- typ
			timeStamp <- tstamp
			windowID <- 0u32
			mouseID <- 0u32
			buttonState <- 0u32
			x <- 0
			y <- 0
			xRel <- 0
			yRel <- 0
		}
	}

	/*
	_eventConstructors set: (_events mouseWheel) :type tstamp eventPtr {
		_helper populateMouseWheelEvent: eventPtr #{
			type <- typ
			timeStamp <- tstamp
			windowID <- 0u32
			mouseID <- 0u32
			x <- 0
			y <- 0
		}
	}
	*/

	_makeTexture <- :rendptr texptr {
		#{
			includeSystemHeader: "SDL.h"
			llProperty: renderer withType: (SDL_Renderer ptr)
			llProperty: texture withType: (SDL_Texture ptr)
			llProperty: _width withType: int32_t
			llProperty: _height withType: int32_t
			llProperty: _format withType: uint32_t
			llProperty: _access withType: int32_t
			llMessage: opaque withVars: {
				ptr <- cpointer ptr
			} andCode: {
				ptr <- make_object: (addr_of: cpointer_meta) NULL 0
				ptr val!: texture
				ptr
			}
			llMessage: _ptr_init withVars: {
				rendptr <- cpointer ptr
				texptr <- cpointer ptr
			} andCode: :rendptr texptr{
				renderer <- rendptr val
				texture <- texptr val
				SDL_QueryTexture: texture (addr_of: _format) (addr_of: _access) (addr_of: _width) (addr_of: _height)
				self
			}

			llMessage: copy withVars: {
				intret <- obj_int32 ptr
			} andCode: {
				intret <- make_object: (addr_of: obj_int32_meta) NULL 0
				intret num!: (SDL_RenderCopy: renderer texture NULL NULL)
				intret
			}

			llMessage: copyTo withVars: {
				dst <- object ptr
				dstOpaque <- cpointer ptr
				intret <- obj_int32 ptr
			} andCode: :dst {
				dstOpaque <- (mcall: _rectPointer 1 dst) castTo: (cpointer ptr)
				intret <- make_object: (addr_of: obj_int32_meta) NULL 0
				intret num!: (SDL_RenderCopy: renderer texture NULL (dstOpaque val))
				intret
			}

			llMessage: copyRect:To withVars: {
				src <- object ptr
				dst <- object ptr
				srcOpaque <- cpointer ptr
				dstOpaque <- cpointer ptr
				intret <- obj_int32 ptr
			} andCode: :src :dst {
				srcOpaque <- (mcall: _rectPointer 1 src) castTo: (cpointer ptr)
				dstOpaque <- (mcall: _rectPointer 1 dst) castTo: (cpointer ptr)
				intret <- make_object: (addr_of: obj_int32_meta) NULL 0
				intret num!: (SDL_RenderCopy: renderer texture (srcOpaque val) (dstOpaque val))
				intret
			}

			llMessage: copyTo:rotated withVars: {
				dst <- object ptr
				angle <- object ptr
				dstOpaque <- cpointer ptr
				anglef <- obj_float32 ptr
				intret <- obj_int32 ptr
			} andCode: :dst :angle {
				anglef <- (mcall: f32 1 angle) castTo: (obj_float32 ptr)
				dstOpaque <- (mcall: _rectPointer 1 dst) castTo: (cpointer ptr)
				intret <- make_object: (addr_of: obj_int32_meta) NULL 0
				intret num!: (SDL_RenderCopyEx: renderer texture NULL (dstOpaque val) (anglef num) NULL SDL_FLIP_NONE)
				intret
			}

			llMessage: lockRect:with withVars: {
				fun <- lambda ptr
				rectOpaque <- cpointer ptr
				pitch <- obj_int32 ptr
				bufsize <- obj_int32 ptr
				height <- obj_int32 ptr
				pixels <- cpointer ptr
				bytearr <- object ptr
				rect <- object ptr
				result <- int32_t
				ret <- object ptr
			} andCode: :rect fun {
				rectOpaque <- (mcall: _rectPointer 1 rect) castTo: (cpointer ptr)
				pitch <- make_object: (addr_of: obj_int32_meta) NULL 0
				pixels <- make_object: (addr_of: cpointer_meta) NULL 0
				//TODO: Check return value
				result <- SDL_LockTexture: texture (rectOpaque val) (addr_of: (pixels val)) (addr_of: (pitch num))
				if: result = 0 {
					height <- (mcall: h 1 rect) castTo: (obj_int32 ptr) 
					bufsize <- make_object: (addr_of: obj_int32_meta) NULL 0
					bufsize num!: (pitch num) * (height num)
					bytearr <- mcall: fromOpaque:withSize 3 bytearray pixels bufsize
					ret <- ccall: fun 2 bytearr pitch
					SDL_UnlockTexture: texture
					//TODO: Return value?
				} else: {
					ret <- false
				}
				ret
			}
			
			llMessage: blendMode! withVars: {
				omode <- object ptr
				mode <- obj_uint32 ptr
			} andCode: :omode {
				mode <- (mcall: uint32 1 omode) castTo: (obj_uint32 ptr)
				SDL_SetTextureBlendMode: texture (mode num)
				self
			}
			
			llMessage: blendMode withVars: {
				mode <- obj_uint32 ptr
			} andCode: {
				mode <- make_object: (addr_of: obj_uint32_meta) NULL 0
				SDL_GetTextureBlendMode: texture (addr_of: (mode num))
				mode
			}
			
			llMessage: colorMod! withVars: {
				color <- object ptr
				tmp <- object ptr
				r <- obj_uint8 ptr
				g <- obj_uint8 ptr
				b <- obj_uint8 ptr
				intret <- obj_int32 ptr
			} andCode: :color {
				tmp <- mcall: r 1 color
				r <- (mcall: uint8 1 tmp) castTo: (obj_uint8 ptr)
				tmp <- mcall: g 1 color
				g <- (mcall: uint8 1 tmp) castTo: (obj_uint8 ptr)
				tmp <- mcall: b 1 color
				b <- (mcall: uint8 1 tmp) castTo: (obj_uint8 ptr)
				intret <- make_object: (addr_of: obj_int32_meta) NULL 0
				intret num!: (SDL_SetTextureColorMod: texture (r num) (g num) (b num))
				intret
			}
			
			llMessage: colorMod withVars: {
				color <- object ptr
				r <- obj_uint8 ptr
				g <- obj_uint8 ptr
				b <- obj_uint8 ptr
				rescode <- int32_t
			} andCode: {
				r <- make_object: (addr_of: obj_uint8_meta) NULL 0
				g <- make_object: (addr_of: obj_uint8_meta) NULL 0
				b <- make_object: (addr_of: obj_uint8_meta) NULL 0
				rescode <- SDL_GetTextureColorMod: texture (addr_of: (r num)) (addr_of: (g num)) (addr_of: (b num))
				if: rescode {
					mcall: none 1 option
				} else: {
					mcall: value 2 option (mcall: r:g:b 4 sdl r g b)
				}
			}
			
			llMessage: width withVars: {
				intret <- obj_int32 ptr
			} andCode: {
				intret <- make_object: (addr_of: obj_int32_meta) NULL 0
				intret num!: _width
				intret
			}
			
			llMessage: height withVars: {
				intret <- obj_int32 ptr
			} andCode: {
				intret <- make_object: (addr_of: obj_int32_meta) NULL 0
				intret num!: _height
				intret
			}

			llMessage: destroy withVars: {} andCode: {
				SDL_DestroyTexture: texture
				true
			}
		} _ptr_init: rendptr texptr
	}

	_makeSurface <- :ptr {
		#{
			includeSystemHeader: "SDL.h"
			llProperty: surface withType: (SDL_Surface ptr)
			llMessage: opaque withVars: {
				ptr <- cpointer ptr
			} andCode: {
				ptr <- make_object: (addr_of: cpointer_meta) NULL 0
				ptr val!: surface
				ptr
			}
			llMessage: _ptr_init withVars: {
				ptr <- cpointer ptr
			} andCode: :ptr {
				surface <- ptr val
				self
			}

			asTexture <- :renderer {
				_helper createTextureFromSurface: (renderer opaque) opaque _makeTexture
			}

			llMessage: free withVars: {} andCode: {
				SDL_FreeSurface: surface
				true
			}
		} _ptr_init: ptr
	}

	#{
		includeSystemHeader: "SDL.h"
		includeSystemHeader: "stdlib.h"

		llMessage: init withVars: {
			flags <- obj_uint32 ptr
			intret <- obj_int32 ptr
		} andCode: :flags {
			intret <- make_object: (addr_of: obj_int32_meta) NULL 0
			intret num!: (SDL_Init: (flags num))
			if: (intret num) {
				atexit: SDL_Quit
			}
			intret
		}

		llMessage: initSubSystem withVars: {
			flags <- obj_uint32 ptr
			intret <- obj_int32 ptr
		} andCode: :flags {
			intret <- make_object: (addr_of: obj_int32_meta) NULL 0
			intret num!: (SDL_InitSubSystem: (flags num))
			intret
		}

		llMessage: quitSubSystem withVars: {
			flags <- obj_uint32 ptr
		} andCode: :flags {
			SDL_QuitSubSystem: (flags num)
			true
		}

		r:g:b:a <- :rc :gc :bc :ac {
			#{
				r <- rc
				g <- gc
				b <- bc
				a <- ac
			}
		}

		r:g:b <- :r :g :b {
			r: r g: g b: b a: 255u8
		}

		createWindow:pos:size:flags <- :title :x y :w h :flags{
			_helper createWindow: title x y w h flags :ptr {
				print: (string: ptr) . "\n"
				#{
					includeSystemHeader: "SDL.h"
					llProperty: window withType: (SDL_Window ptr)
					llMessage: opaque withVars: {
						op <- cpointer ptr
					} andCode: {
						op <- make_object: (addr_of: cpointer_meta) NULL 0
						op val!: window
						op
					}

					llMessage: _ptr_init withVars: {
						ptr <- cpointer ptr
					} andCode: :ptr {
						window <- ptr val
						self
					}

					renderOpts <- { _renderOpts }

					createRenderer:flags <- :index :flags {
						_helper createRenderer: (self opaque) index flags :ptr {
							#{
								includeSystemHeader: "SDL.h"
								llProperty: renderer withType: (SDL_Renderer ptr)
								llMessage: opaque withVars: {
									op <- cpointer ptr
								} andCode: {
									op <- make_object: (addr_of: cpointer_meta) NULL 0
									op val!: renderer
									op
								}
								llMessage: _ptr_init withVars: {
									ptr <- cpointer ptr
								} andCode: :ptr {
									renderer <- ptr val
									self
								}

								llMessage: drawColor! withVars: {
									color <- object ptr
									rc <- obj_uint8 ptr
									gc <- obj_uint8 ptr
									bc <- obj_uint8 ptr
									ac <- obj_uint8 ptr
									intret <- obj_int32 ptr
								} andCode: :color {
									intret <- make_object: (addr_of: obj_int32_meta) NULL 0
									rc <- (mcall: r 1 color) castTo: (obj_uint8 ptr)
									gc <- (mcall: g 1 color) castTo: (obj_uint8 ptr)
									bc <- (mcall: b 1 color) castTo: (obj_uint8 ptr)
									ac <- (mcall: a 1 color) castTo: (obj_uint8 ptr)
									intret num!: (SDL_SetRenderDrawColor: renderer (rc num) (gc num) (bc num) (ac num))
									intret
								}
								
								createTexture:access:width:height <- :format :access :w :h {
									_helper createTexture: opaque format access w h _makeTexture
								}

								llMessage: clear withVars: {
									intret <- obj_int32 ptr
								} andCode: {
									intret <- make_object: (addr_of: obj_int32_meta) NULL 0
									intret num!: (SDL_RenderClear: renderer)
									intret
								}

								llMessage: present withVars: {} andCode: {
									SDL_RenderPresent: renderer
									true
								}

								llMessage: destroy withVars: {} andCode: {
									SDL_DestroyRenderer: renderer
									true
								}
							} _ptr_init: ptr
						}
					}

					llMessage: destroy withVars: {
					} andCode: {
						SDL_DestroyWindow: window
						true
					}
				} _ptr_init: ptr
			}
		}

		loadBMP <- :filename {
			_helper loadBMP: filename _makeSurface
		}

		llMessage: delay withVars: {
			ms <- obj_uint32 ptr
		} andCode: :ms {
			SDL_Delay: (ms num)
			true
		}

		llMessage: clearError withVars: {} andCode: {
			SDL_ClearError:
			true
		}

		rect:size <- :x y :w h {
			getter <- macro: :propName {
				quote: (llMessage: propName withVars: {
					intret <- obj_int32 ptr
				} andCode: {
					intret <- make_object: (addr_of: obj_int32_meta) NULL 0
					intret num!: ((addr_of: rect) propName)
					intret
				})
			}
			setter <- macro: :propName {
				quote: (llMessage: propName withVars: {
					v <- obj_int32 ptr
				} andCode: :v {
					(addr_of: rect) propName: (v num)
					self
				})
			}
			(((#{
				llProperty: rect withType: SDL_Rect
				getter: x
				setter: x!
				getter: y
				setter: y!
				getter: w
				setter: w!
				getter: h
				setter: h!
				llMessage: _rectPointer withVars: {
					retptr <- cpointer ptr
				} andCode: {
					retptr <- make_object: (addr_of: cpointer_meta) NULL 0
					retptr val!: (addr_of: (self rect))
					retptr
				}
			} x!: x) y!: y) w!: w) h!: h
		}

		llMessage: getError withVars: {
			str <- string ptr
			rawstr <- const: (char ptr)
		} andCode: {
			rawstr <- SDL_GetError:
			str <- make_object: (addr_of: string_meta) NULL 0
			str bytes!: (strlen: rawstr)
			str len!: (str bytes)
			str data!: (GC_MALLOC: (str bytes) + 1)
			memcpy: (str data) rawstr (str bytes) + 1
			str
		}

		pollEvent <- {
			_helper pollEvent: :typ tstamp eventPtr {
				_eventConstructors ifget: typ :handler {
					handler: typ tstamp eventPtr
				} else: {
					//fallback event
					#{
						type <- typ
						timeStamp <- tstamp
					}
				}
			}
		}
		
		waitEvent <- {
			_helper waitEvent: :typ tstamp eventPtr {
				_eventConstructors ifget: typ :handler {
					handler: typ tstamp eventPtr
				} else: {
					//fallback event
					#{
						type <- typ
						timeStamp <- tstamp
					}
				}
			}
		}

		subsystems <- { _subsystems }
		windowOpts <- { _windowOpts }
		eventTypes <- { _events }
		windowEventTypes <- { _windowEvents }
		textureAccess <- { _textureAccess }
		pixelFormats <- { _pixelFormats }
		blendModes <- { _blendModes }
	}
}