If you buy/have BlitzMax, this module will allow you to use normal 2D instead of the hardware accelerated stuff. It doesn't use Max2D so you'd have to do your own implementation of it -- I'm using this for software rendering. The code is licensed under the GNU Lesser General Public License (if you for some reason do not like the LGPL then you can jump off a bridge :D ).
ce_softdev.h
// CEngine - 3D engine for graphics and game development
// Copyright (C) 2005 Noel Raymond Cower
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// To contact the author, e-mail him at noel_cower@... and/or hooker.with.a.penis@...
// Technically, this code has almost nothing to do with the software device
// All it's used for is 2D functionality that is otherwise nonexistant in BlitzMax
#ifndef _CE_SOFTDEV_H_
#define _CE_SOFTDEV_H_
// if i decide to not use SDL at some point in time, these bits might come in handy
#include "SDL/SDL.h"
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
# define CE_R_MASK 0xff000000
# define CE_G_MASK 0x00ff0000
# define CE_B_MASK 0x0000ff00
# define CE_A_MASK 0x000000ff
#else
# define CE_A_MASK 0xff000000
# define CE_R_MASK 0x00ff0000
# define CE_G_MASK 0x0000ff00
# define CE_B_MASK 0x000000ff
#endif
#ifndef NULL
# ifdef _cplusplus
# define NULL 0
# else
# define NULL (void*)0
# endif
#endif
#ifdef _cplusplus
extern "C" {
#endif
// For the sake of simplicity
#define ce_New(i) ((i*)malloc(sizeof(i)))
// And for the sake of consistency
#define ce_Delete(i) (free(i))
// A buffer or surface
typedef struct ce_Surface {
SDL_Surface* surf;
int locked;
// Used for updating portions of the buffer
int last_min_x, last_min_y;
int last_max_x, last_max_y;
int w;
int h;
} ce_Surface;
extern ce_Surface* framebuffer;
extern ce_Surface* curBuffer;
// Used for updating portions of the framebuffer
extern int last_min_x, last_min_y, last_max_x, last_max_y;
// Initialize the software device
int ce_InitDevice(int, int, int, int);
// Dispose (free, delete, remove, destroy) the software device
int ce_DisposeDevice(void);
// Write a pixel to a buffer
int ce_WritePixel(int, int, int, int, int, int, ce_Surface*);
// Read a pixel from a buffer
int ce_ReadPixel(int, int, ce_Surface*);
// Get the framebuffer
ce_Surface* ce_GetFramebuffer(void);
// Creates a buffer
ce_Surface* ce_CreateBuffer(int, int, int);
// Disposes of a buffer
int ce_DisposeBuffer(ce_Surface*);
// Swaps the front and back buffers
int ce_SwapBuffers(void);
// Lock a buffer
int ce_LockBuffer(ce_Surface*);
// Unlock a buffer
int ce_UnlockBuffer(ce_Surface*);
// Get whether or not a buffer is locked
int ce_BufferIsLocked(ce_Surface*);
// Blits buffer src to buffer dst at X,Y
int ce_BlitBuffer(ce_Surface*, ce_Surface*, int, int);
// Fills a rectangular area of a buffer
int ce_FillRect(ce_Surface*, int, int, int, int, int, int, int, int);
// Sets a buffer to a single color
int ce_ClearBuffer(ce_Surface*, int, int, int, int);
#ifdef _cplusplus
}
#endif
#endif //_CE_SOFTDEV_H_
ce_softdev.c
// CEngine - 3D engine for graphics and game development
// Copyright (C) 2005 Noel Raymond Cower
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// To contact the author, e-mail him at noel_cower@... and/or hooker.with.a.penis@...
// Technically, this code has almost nothing to do with the software device
// All it's used for is 2D functionality that is otherwise nonexistant in BlitzMax
#include "ce_softdev.h"
#include "stdio.h"
static ce_Surface* framebuffer = NULL;
static ce_Surface* curBuffer = NULL;
int ce_InitDevice(int w, int h, int bpp, int fs) {
if (framebuffer!=NULL)
return -2; // Cannot initialize it more than once
int sdlFlags = SDL_SWSURFACE | SDL_DOUBLEBUF;
if (fs>0)
sdlFlags|=SDL_FULLSCREEN;
SDL_Init(SDL_INIT_VIDEO);
SDL_WM_SetCaption("CEngine Software Window", "CEngine Software Window");
SDL_Surface* surf = SDL_SetVideoMode(w,h,bpp,sdlFlags);
if (surf==NULL) {
fprintf(stderr,
"Failed to create display device at %i*%i at %i BPP with %i for fullscreen, error is "%s"\n",
w, h, bpp, fs, SDL_GetError());
return -1;
}
framebuffer = ce_New(ce_Surface);
framebuffer->last_min_x = 0;
framebuffer->last_min_y = 0;
framebuffer->last_max_x = 0;
framebuffer->last_max_y = 0;
framebuffer->locked = 0;
framebuffer->surf = surf;
framebuffer->w = w;
framebuffer->h = h;
curBuffer = framebuffer;
return 0;
}
int ce_DisposeDevice(void) {
SDL_Quit();
framebuffer = NULL;
curBuffer = NULL;
}
int ce_SwapBuffers(void) {
if (framebuffer->locked > 0)
return -1;
//SDL_UpdateRect(framebuffer->surf,0,0,framebuffer->w,framebuffer->h);
SDL_Flip(framebuffer->surf);
return 0;
}
ce_Surface* ce_CreateBuffer(int w, int h, int bpp) {
SDL_Surface* i = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, bpp,
CE_R_MASK, CE_G_MASK, CE_B_MASK, CE_A_MASK);
if (i == NULL)
return NULL;
ce_Surface* surf = ce_New(ce_Surface);
surf->surf = i;
surf->w = w;
surf->h = h;
surf->last_min_x = 0;
surf->last_min_y = 0;
surf->last_max_x = 0;
surf->last_max_y = 0;
surf->locked = 0;
return surf;
}
ce_Surface* ce_GetFramebuffer(void) {
return framebuffer;
}
int ce_DisposeBuffer(ce_Surface* surf) {
SDL_FreeSurface(surf->surf);
ce_Delete(surf);
return 0;
}
int ce_WritePixel(int x, int y, int r, int g, int b, int a, ce_Surface* surf) {
if (surf->locked==0)
if (SDL_LockSurface(surf->surf)!=0)
return -1;
Uint32 pixel = SDL_MapRGBA(surf->surf->format,r,g,b,a);
// Mostly just going off of the example in the SDL reference manual
Uint8* bits = ((Uint8*)(surf->surf->pixels) + y*surf->surf->pitch + x*surf->surf->format->BytesPerPixel);
switch (surf->surf->format->BytesPerPixel) {
case 1:
*((Uint8*)bits) = (Uint8)pixel;
break;
case 2:
*((Uint16*)bits) = (Uint16)pixel;
break;
case 3: {
Uint8 r,g,b;
r=(pixel>>surf->surf->format->Rshift)&0xFF;
g=(pixel>>surf->surf->format->Gshift)&0xFF;
b=(pixel>>surf->surf->format->Bshift)&0xFF;
*(bits + surf->surf->format->Rshift/8) = r;
*(bits + surf->surf->format->Gshift/8) = g;
*(bits + surf->surf->format->Bshift/8) = b;
}
break;
case 4:
*((Uint32*)bits) = (Uint32)pixel;
break;
}
if (surf->locked==0) {
SDL_UnlockSurface(surf->surf);
// SDL_UpdateRect(surf->surf,x,y,1,1);
} else {
// set update region
if (x < surf->last_min_x)
surf->last_min_x = x;
if (y < surf->last_min_y)
surf->last_min_y = y;
if (x > surf->last_max_x)
surf->last_max_x = x;
if (y > surf->last_max_y)
surf->last_max_y = y;
if (surf->last_max_y == surf->last_min_y)
surf->last_max_y++;
if (surf->last_max_x == surf->last_min_x)
surf->last_max_x++;
}
}
int ce_ReadPixel(int x, int y, ce_Surface* surf) {
SDL_Surface* i = surf->surf;
if (surf->locked == 0)
if (SDL_LockSurface(i)!=0)
return 0;
Uint32 pix = *(Uint32*)((Uint8*)i->pixels + y*i->pitch + x*i->format->BytesPerPixel);
//Uint32 pixel = pix;
//Uint8 *colors = (Uint8*)pixel;
//SDL_GetRGBA(pix, i->format, colors, colors+1, colors+2, colors+3);
if (surf->locked == 0)
SDL_UnlockSurface(i);
return pix;
}
int ce_BufferIsLocked(ce_Surface* surf) {
return (surf->locked>0);
}
int ce_LockBuffer(ce_Surface* surf) {
int res = SDL_LockSurface(surf->surf);
if (res == 0)
surf->locked++;
return res;
}
int ce_UnlockBuffer(ce_Surface* surf) {
if (surf->locked == 0)
return 0;
SDL_UnlockSurface(surf->surf);
surf->locked--;
if (surf->locked==0) {
SDL_Rect r;
r.x = surf->last_min_x;
r.y = surf->last_min_y;
r.w = surf->last_max_x-surf->last_min_x;
r.h = surf->last_max_y-surf->last_min_y;
if (r.w == 0 || r.h == 0)
return 0;
if (r.x < 0) {
r.w += r.x;
r.x = 0;
}
if (r.y < 0) {
r.h += r.y;
r.y = 0;
}
// SDL_UpdateRect(surf->surf,r.x,r.y,r.w,r.h);
}
return 0;
}
int ce_FillRect(ce_Surface* surf, int x, int y, int w, int h, int r, int g, int b, int a) {
SDL_Surface* i = surf->surf;
SDL_Rect rc;
if (x < 0) {
w += x;
x = 0;
}
if (y < 0) {
h += y;
y = 0;
}
rc.x = x; rc.y = y;
rc.w = w; rc.h = h;
if (rc.w == 0 || rc.h == 0)
return 0;
if (surf->locked==0)
if (SDL_LockSurface(i)!=0)
return -1;
if (SDL_FillRect(i,&rc,SDL_MapRGBA(surf->surf->format,r,g,b,a))!=0) {
if (surf->locked==0)
SDL_UnlockSurface(i);
return -1;
}
if (surf->locked==0) {
SDL_UnlockSurface(i);
// SDL_UpdateRect(i,x,y,w,h);
}
return 0;
}
int ce_ClearBuffer(ce_Surface* surf, int r, int g, int b, int a) {
SDL_Surface* i = surf->surf;
if (surf->locked==0)
if (SDL_LockSurface(i)!=0)
return -1;
if (SDL_FillRect(i,NULL,SDL_MapRGBA(surf->surf->format,r,g,b,a))!=0) {
if (surf->locked==0)
SDL_UnlockSurface(i);
return -1;
}
if (surf->locked==0) {
SDL_UnlockSurface(i);
// SDL_UpdateRect(i,0,0,surf->w,surf->h);
}
return 0;
}
int ce_BlitBuffer(ce_Surface* src, ce_Surface* dst, int x, int y) {
SDL_Rect ra;
SDL_Rect rb;
ra.x = 0;
ra.y = 0;
ra.w = src->w;
ra.h = src->h;
rb.x = x;
rb.y = y;
rb.w = ra.w;
rb.h = ra.h;
return SDL_BlitSurface(src->surf,&ra,dst->surf,&rb);
}
softdevice.bmx (mod/cengine.mod/softdevice.mod/softdevice.bmx)
'#Region Copyright and license
' CEngine - 3D engine for graphics and game development
' Copyright 2005 Noel R. Cower
'
' This library is free software; you can redistribute it and/or
' modify it under the terms of the GNU Lesser General Public
' License as published by the Free Software Foundation; either
' version 2.1 of the License, or (at your option) any later version.
'
' This library is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
' Lesser General Public License for more details.
'
' You should have received a copy of the GNU Lesser General Public
' License along with this library; if not, write to the Free Software
' Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
'
' To contact the author, e-mail him at noel_cower@... and/or hooker.with.a.penis@...
'#End Region
Strict
Module CEngine.SoftDevice
ModuleInfo "CEngine software device class"
ModuleInfo "Uses SDL (www.libsdl.org VISIT THEM) for drawing"
ModuleInfo "Written by Noel R. Cower"
'Import CEngine.EngineCore
Import "-lSDL"
Import "ce_softdev.c"
Extern "C"
Function ce_InitDevice(w:Int, h:Int, bpp:Int, fs:Int)
Function ce_DisposeDevice()
Function ce_CreateBuffer:Byte Ptr(w:Int,h:Int,bpp:Int)
Function ce_DisposeBuffer(buffer:Byte Ptr)
Function ce_GetFramebuffer:Byte Ptr()
Function ce_ReadPixel(x:Int,y:Int,buf:Byte Ptr)
Function ce_WritePixel(x:Int,y:Int,r:Int, g:Int, b:Int, a:Int,buf:Byte Ptr)
Function ce_LockBuffer(buf:Byte Ptr)
Function ce_UnlockBuffer(buf:Byte Ptr)
Function ce_BufferIsLocked(buf:Byte Ptr)
Function ce_SwapBuffers()
Function ce_FillRect(surf:Byte Ptr, x:Int, y:Int, w:Int, h:Int, r:Int, g:Int, b:Int, a:Int)
Function ce_ClearBuffer(surf:Byte Ptr, r:Int, g:Int, b:Int, a:Int)
Function ce_BlitBuffer(src:Byte Ptr, dst:Byte Ptr, x:Int, y:Int)
End Extern
Type CSoftwareBuffer
Global _framebuffer:CSoftwareBuffer
Field _ptr:Byte Ptr
Method GetWidth()
Return (Int Ptr(_ptr+24))[0];
End Method
Method GetHeight()
Return (Int Ptr(_ptr+28))[0];
End Method
Method Lock()
ce_LockBuffer(_ptr)
End Method
Method Unlock()
ce_UnlockBuffer(_ptr)
End Method
Method IsLocked()
Return ce_BufferIsLocked(_ptr)
End Method
Method LockLevel()
Return (Int Ptr(_ptr+4))[0]
End Method
Method WritePixel(x,y,r,g,b,a)
Return ce_WritePixel(x,y,r,g,b,a,_ptr)
End Method
Method ReadPixel(x,y,r:Byte Ptr = Null,g:Byte Ptr = Null,b:Byte Ptr = Null,a:Byte Ptr = Null)
Local ret = ce_ReadPixel(x,y,_ptr)
If r <> Null Or g <> Null Or b <> Null Or a <> Null
Local i:Byte Ptr = Byte Ptr(Varptr(ret))
If r <> Null Then r[0] = i[0]
If g <> Null Then g[0] = i[1]
If b <> Null Then b[0] = i[2]
If a <> Null Then a[0] = i[3]
EndIf
Return ret
End Method
Method FillRect(x,y,w,h,r,g,b,a)
Return ce_FillRect(_ptr,x,y,w,h,r,g,b,a)
End Method
Method Clear(r,g,b,a)
Return ce_ClearBuffer(_ptr,r,g,b,a)
End Method
Method Blit(toSurf:CSoftwareBuffer,X:Int,Y:Int)
Return ce_BlitBuffer(_ptr,toSurf._ptr,X,Y)
End Method
Method Delete()
ce_DisposeBuffer(_ptr)
_ptr = Null
End Method
Function Create:CSoftwareBuffer(Width:Int, Height:Int, BPP:Int=32)
Local _ptr:Byte Ptr = ce_CreateBuffer(Width,Height,BPP)
If _ptr = Null Then Return Null
Local i:CSoftwareBuffer = New CSoftwareBuffer
i._ptr = _ptr
Return i
End Function
Function FrameBuffer:CSoftwareBuffer()
If _framebuffer = Null And ce_GetFramebuffer() <> Null
_framebuffer = New CSoftwareBuffer
_framebuffer._ptr = ce_GetFramebuffer()
EndIf
Return _framebuffer
End Function
End Type