ysdl - 7/10/2010 release, copyright (c) 2010 Sean Bolton.

This is a lightweight SDL binding for Lua 5.1.x.  Depending on what
you are looking for, it may or may not be of interest to you.

Advantages:
- simple: only a single C file to include in your application
- small: many of the most common SDL functions are bound, but not
    all of them, so the binding isn't larger than Lua itself
- LUA function names closely match their SDL counterparts, with
    predictable changes
- MIT-style licensing, see the enclosed file COPYRIGHT
- fast: very little type and error checking is done

Disadvantages:
- unforgiving: very little type and error checking is done; if you
    pass the wrong argument to a SDL function, you will crash
- small: if you need something that isn't yet bound, you'll have to
    add a binding yourself
- not all SDL functions are bound
- documentation is minimal (this file)

Usage
=====
To use ysdl, add the file ysdl.c to your makefile or project setup,
and then in your C startup code call luaopen_ysdl() after you've
initialized Lua:

    LUALIB_API int luaopen_ysdl (lua_State *L);

    /* initialize Lua */ 
    lua_State *L = lua_open();
    luaL_openlibs(L);
    luaopen_ysdl(L);

See the file minimal-main.c for a simple example.

If you want to use SDL_image, SDL_mixer, SDL_ttf, or the convenience
bit operation functions (e.g. SDL.And(), SDL.Xor()), you'll need to
set the following defines, either at the top of ysdl.c or on your
compiler command line:

    #define YSDL_WANT_IMAGE
    #define YSDL_WANT_MIXER
    #define YSDL_WANT_TTF
    #define YSDL_WANT_BITOPS

Compilation requires Lua 5.1.x, SDL 1.2.x, and optionally, SDL_image
1.2.x, SDL_mixer 1.2.x, and SDL_ttf 2.0.x.  On my linux system, the
following command line works:

$ gcc -Wall -O2 -g -o ysdl-minimal-main minimal-main.c ysdl.c \
    -DYSDL_WANT_IMAGE -DYSDL_WANT_MIXER -DYSDL_WANT_TTF \
    -DYSDL_WANT_BITOPS -llua \
    `sdl-config --cflags --libs` -lSDL_image -lSDL_mixer -lSDL_ttf

You may then wish to try the example, example1.lua, like so:

$ ./ysdl-minimal-main example1.lua

Several of the SDL data structures (SDL_Rect and SDL_Color) are
handled on the Lua side as simple userdata, and no type checking is
done when they are passed as arguments to bound SDL functions,
meaning if you make a mistake and pass the wrong kind of userdata,
your program will crash.  So be careful.

For the most part, you don't need to worry about freeing SDL
resources when you are done with them, since they will be freed when
their Lua counterparts are garbage collected.  You may also use
e.g. surface:FreeSurface(), mixchunk:FreeChunk(), or
font:CloseFont() to free resources before they are collected.

Binding Naming Convention
=========================
All of the ysdl functions are accessed either through four global
tables ('SDL', 'IMG', 'Mix', and 'TTF'), or through method
invocations on the SDL userdata.  With few exceptions, the names of
the global functions are exactly as they are in SDL, except that the
first underscore is replaced by a period.  So, for example,
SDL_Init() becomes SDL.Init().  The names of the method functions
are exactly as they are in SDL, with the prefix up to and including
the first underscore removed. So SDL_Flip(surface) becomes
surface:Flip().

SDL Function Bindings
=====================
The following SDL functions are bound.  Those marked with '**' have
different syntax or semantics from their SDL counterparts; those not
so marked accept the same arguments, and return the same result as
their SDL counterparts.

SDL_BlitSurface

    result = SDL.BlitSurface(srcsurface, srcrect, dstsurface, dstrect)
    
    -- (see SDL_Rect in 'SDL Data Structures' below for information
    --  on manipulating SDL_Rect structures)

SDL_Color

    (See SDL Data Structures below)

SDL_CreateRGBSurface

    surface = SDL.CreateRGBSurface(flags, width, height, bpp,
                                   rmask, gmask, bmask, amask)
              -- returns nil on error

SDL_Delay

    SDL.Delay(milliseconds)

SDL_DisplayFormat

    newsurface = SDL.DisplayFormat(surface)
    newsurface = surface:DisplayFormat()

SDL_FillRect

    result = SDL.FillRect(surface, rect, color) -- returns -1 on error
    result = surface:FillRect(rect, color)      -- returns -1 on error

    -- (see SDL_Rect and SDL_Color in 'SDL Data Structures' below
    --  for information on manipulating SDL_Rect and SDL_Color
    --  structures)

SDL_Flip

    result = SDL.Flip(screen_surface) -- returns -1 on error
    result = screen_surface:Flip()    -- returns -1 on error

SDL_FreeSurface

    SDL.FreeSurface(surface)
    surface:FreeSurface()

SDL_GetClipRect **

    rect = SDL.GetClipRect(surface)
    rect = surface:GetClipRect()

    -- (see SDL_Rect in 'SDL Data Structures' below for information
    --  on manipulating SDL_Rect structures)

SDL_GetError

    errorstring = SDL.GetError()

SDL_GetKeyState **

    pressed = SDL.GetKeyState(keysym)

    -- SDL.GetKeyState takes a SDL.K_* key number as its argument,
    -- and returns true if that key is pressed, for example:

    pressed = SDL.GetKeyState(SDL.K_SPACE) -- returns true if
                                           -- spacebar is pressed

SDL_GetMouseState **

    buttonstate, x, y = SDL.GetMouseState()

SDL_GetTicks

    milliseconds = SDL.GetTicks()

SDL_Init

    result = SDL.Init(flags)

SDL_LoadBMP

    surface = SDL.LoadBMP(filename) -- returns nil on error

SDL_LockSurface

    result = SDL.LockSurface(surface) -- returns -1 on error, 0 on success
    result = surface:LockSurface()    -- returns -1 on error, 0 on success

SDL_LowerBlit

    result = SDL.LowerBlit(src, srcrect, dst, dstrect)

SDL_MapRGB **
SDL_MapRGBA **

    -- ysdl has as yet side-stepped having to deal with
    -- SDL_PixelFormat structures through the use of the following
    -- functions, where the pixelformat is obtained from a surface:

    pixelvalue = SDL.MapRGB_using_Surface(surface, r, g, b)
    pixelvalue = SDL.MapRGBA_using_Surface(surface, r, g, b, a)

SDL_PollEvent **

    -- SDL.PollEvent() and SDL.WaitEvent() return Lua tables which
    -- partially reflect the contents of the SDL_Event structure, or
    -- nil if no events were available or an error occurred.  For
    -- example: 

    event = SDL.PollEvent()
    if event and event.type == SDL.QUIT then
        SDL.Quit()
        os.exit(0)
     end

    -- The table fields set depend on the type of event:

    -- Type                 Table Key  SDL_Event Field Used for Value
    -- ====                 =========  ==============================
    -- (all)                  type       ev->type
    -- SDL_KEYDOWN            sym        ev->key.keysym.sym
    -- SDL_KEYDOWN            mod        ev->key.keysym.mod
    -- SDL_MOUSEBUTTONDOWN    button     ev->button.button
    -- SDL_MOUSEBUTTONDOWN    x          ev->button.x
    -- SDL_MOUSEBUTTONDOWN    y          ev->button.y
    -- SDL_MOUSEMOTION        x          ev->motion.x
    -- SDL_MOUSEMOTION        y          ev->motion.y

SDL_Quit

    SDL.Quit()

SDL_Rect

    (See SDL Data Structures below)

SDL_SaveBMP

    result = SDL.SaveBMP(surface, filename)

SDL_SetAlpha

    result = SDL.SetAlpha(surface, flags, alpha) -- returns -1 on error
    result = surface:SetAlpha(flags, alpha)      -- returns -1 on error

SDL_SetColorKey

    result = SDL.SetColorKey(surface, flag, key) -- returns -1 on error
    result = surface:SetColorKey(flag, key)      -- returns -1 on error

SDL_SetPallete **

    -- SDL_SetPalette is available for the special case where
    -- ncolors is 1: 

    sucess = SDL.SetPalette1(surface, flags, color, firstcolor)
    sucess = surface:SetPalette1(flags, color, firstcolor)

SDL_SetVideoMode

    surface = SDL.SetVideoMode(width, height, bpp, flags)
              -- returns nil on error
              -- returned surface will be freed by SDL.Quit(),
              --   do NOT free with surface:FreeSurface()

SDL_ShowCursor

    state = SDL.ShowCursor(toggle)

SDL_Surface

    (See SDL Data Structures below)

SDL_UnlockSurface

    SDL.UnlockSurface(surface)
    surface:UnlockSurface()

SDL_UpdateRect

    SDL.UpdateRect(screen_surface, x, y, w, h)
    screen_surface:UpdateRect(x, y, w, h)

SDL_UpdateRects **

    -- On modern hardware, a Lua-based SDL_UpdateRects() would be
    -- slower than just doing the following:

    screen_surface:UpdateRect(0, 0, 0, 0) -- update the entire screen

    -- If you really need the speed, see how SDL_UpdateRects() is
    -- implemented on the C side in awesometd-lua_ysdl_port-0.3r4.

SDL_WaitEvent **

    -- see SDL_PollEvent() for a description of the returned event
    event = SDL.WaitEvent()

SDL_WM_SetCaption

    SDL.WM_SetCaption(windowtitle, icontitle)

SDL Data Structures
===================
SDL_Color

    -- SDL_Color structures are created using the function:

    color = SDL.newColor(r, g, b)

SDL_Rect

    -- SDL_Rect structures are created and manipulated using the
    -- following functions:

    rect = SDL.newRect(x, y, w, h)  -- x, y, w, and h all default to
                                    -- zero if not specified

    x, y, w, h = SDL.getRect(rect)

    SDL.setRect(rect, x, y, w, h)

SDL_Surface

    -- The 'flags' field of an SDL_Surface may be obtained using
    -- this method:

    flags = surface:getFlags()

    -- The pixel value at a particular point may be obtained using
    -- this method (surface should be locked):

    pixelvalue = surface:getPixel(x, y)

    -- The size of an SDL_Surface may be obtained using this method:

    x, y = surface:getSize()

SDL_image Bindings
==================
The following SDL_image functions are bound, accept the same arguments,
and return the same result as their SDL_image counterparts:

    IMG.GetError
    IMG.Load

SDL_mixer Bindings
==================
The following SDL_mixer functions are bound, accept the same arguments,
and return the same result as their SDL_mixer counterparts:

    Mix.CloseAudio
    Mix.GetError
    Mix.HaltChannel
    Mix.LoadMUS
    Mix.LoadWAV
    Mix.OpenAudio
    Mix.PlayChannel
    Mix.Playing
    Mix.PlayingMusic
    Mix.PlayMusic

Mix_Chunk and Mix_Music structures may be freed with their
respective methods:

    :FreeChunk
    :FreeMusic

SDL_ttf Bindings
================
The following SDL_ttf functions are bound, accept the same arguments,
and return the same result as their SDL_ttf counterparts:

    TTF.GetError
    TTF.Init
    TTF.OpenFont
    TTF.Quit

Methods operating on fonts are:

    :CloseFont
    :RenderText_Solid

SDL Enumerations
================
A selection of SDL enumerations are available in the SDL table.
For SDL enumerations beginning with 'SDL_', the 'SDL_' becomes 'SDL.':

    SDL.INIT_EVERYTHING
    SDL.SWSURFACE

Key numbers beginning with 'SDLK_' become:

    SDL.K_DOWN
    SDL.K_1
    SDL.K_a

Some SDL_mixer constants are available like so:

    SDL.AUDIO_U8
    SDL.AUDIO_S16SYS

If you need a constant that is not defined on the Lua side, it is
trivial to add it to the 'ysdl_enums' array in ysdl.c.

Convenience Bit Operations
==========================
Since Lua 5.1 does not provide the bitwise operations commonly used
with SDL enumerations, ysdl optionally provides them:

    SDL.And
    SDL.Not
    SDL.Or
    SDL.Xor

