3 * Iter Vehemens ad Necem (IVAN)
4 * Copyright (C) Timo Kiviluoto
5 * Released under the GNU General
8 * See LICENSING which should be included
9 * along with this file for more details
14 #ifndef DISABLE_OPENGL
26 #if !defined(DISABLE_SOUND) && defined(ENABLE_ALSA)
27 # include <alsa/asoundlib.h>
28 // shut the fuck up, alsa!
30 static void alsa_message_fucker (const char *file
, int line
, const char *function_
, int err
, const char *fmt
, ...) {}
32 void fuck_alsa_messages () {
33 snd_lib_error_set_handler(&alsa_message_fucker
);
36 void fuck_alsa_messages () {}
40 void (*graphics::SwitchModeHandler
) ();
42 SDL_Surface
*graphics::Screen
;
44 bitmap
*graphics::DoubleBuffer
;
46 int graphics::ColorDepth
;
47 rawbitmap
*graphics::DefaultFont
= 0;
49 int graphics::curx
= -666;
50 int graphics::cury
= -666;
51 int graphics::curvisible
= 0;
54 CursorState::CursorState (int ax
, int ay
, int avis
, int newx
, int newy
, truth newvis
) { x
= ax
; y
= ay
; vis
= avis
; graphics::curx
= newx
; graphics::cury
= newy
; if (newvis
) graphics::showCursor(); else graphics::hideCursor(); }
55 CursorState::CursorState (int ax
, int ay
, int avis
, int newx
, int newy
) { x
= ax
; y
= ay
; vis
= avis
; graphics::curx
= newx
; graphics::cury
= newy
; }
56 CursorState::CursorState (int ax
, int ay
, int avis
, truth newvis
) { x
= ax
; y
= ay
; vis
= avis
; if (newvis
) graphics::showCursor(); else graphics::hideCursor(); }
57 CursorState::~CursorState () { if (vis
!= -666) { graphics::curx
= x
; graphics::cury
= y
; graphics::curvisible
= vis
; } }
60 static truth dblRes
= false;
61 static truth origDblRes
= false;
62 static uint8_t *bufc32
= 0;
64 //#define DIVISOR (1.7)
65 static float DIVISOR
= 1.7;
68 static int fixVal (int v
) { return (dblRes
? (int)(v
*DIVISOR
) : v
); }
71 #ifndef DISABLE_OPENGL
72 static GLuint maintid
= 0;
75 static void killTexture () {
77 glDeleteTextures(1, &maintid
);
83 void graphics::createTexture () {
84 glGenTextures(1, &maintid
);
85 if (maintid
== 0) ABORT("Couldn't create OpenGL texture.");
87 //GLint gltextbinding;
88 //glGetIntegerv(GL_TEXTURE_BINDING_2D, &gltextbinding);
89 //scope(exit) glBindTexture(GL_TEXTURE_2D, gltextbinding);
91 glBindTexture(GL_TEXTURE_2D
, maintid
);
92 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
93 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
94 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
95 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
96 //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
97 //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
99 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, Res
.X
, Res
.Y
, 0, /*GL_RGBA*/GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
); // this inits texture
106 float frc0
, frc1
, yfrc0
, yfrc1
;
110 static KIt
*kernel
= 0;
115 static void buildKernel (int resx
, int resy
) {
116 bufc32
= (uint8_t*)realloc(bufc32
, resx
*resy
*4);
117 #ifdef DISABLE_OPENGL
118 if (fixVal(resx
) == resx
&& fixVal(resy
) == resy
) return;
120 KIt
* res
= (KIt
*)realloc(kernel
, fixVal(resy
)*fixVal(resx
)*sizeof(KIt
));
121 for (int y
= 0; y
< fixVal(resy
); ++y
) {
122 for (int x
= 0; x
< fixVal(resx
); ++x
) {
123 KIt
* i
= res
+y
*fixVal(resx
)+x
;
124 float fx
= x
/DIVISOR
;
125 float fy
= y
/DIVISOR
;
126 float frc1
= fx
-(int)fx
;
127 float frc0
= 1.0-frc1
;
128 float yfrc1
= fy
-(int)fy
;
129 float yfrc0
= 1.0-yfrc1
;
134 //r[0] = (r[0]*frc0+r[1]*frc1)*yfrc0+(r[2]*frc0+r[3]*frc1)*yfrc1;
135 for (int dy
= 0; dy
< 2; ++dy
) {
136 for (int dx
= 0; dx
< 2; ++dx
) {
137 int sx
= (int)(fx
+dx
);
138 int sy
= (int)(fy
+dy
);
139 if (sx
>= 0 && sy
>= 0 && sx
< resx
&& sy
< resy
) {
140 i
->sofs
[dy
*2+dx
] = sy
*(resx
*4)+sx
*4;
142 i
->sofs
[dy
*2+dx
] = 0;
153 void graphics::Init () {
154 static truth AlreadyInstalled
= false;
155 if (!AlreadyInstalled
) {
156 AlreadyInstalled
= true;
157 if (SDL_Init(SDL_INIT_VIDEO
|SDL_INIT_TIMER
|SDL_INIT_NOPARACHUTE
)) ABORT("Can't initialize SDL.");
158 atexit(graphics::DeInit
);
163 void graphics::DeInit () {
164 #ifndef DISABLE_OPENGL
173 void graphics::SetMode (cchar
*Title
, cchar
*IconName
, v2 NewRes
, truth FullScreen
, sLong adresmod
) {
175 SDL_Surface
*Icon
= SDL_LoadBMP(IconName
);
176 SDL_SetColorKey(Icon
, SDL_SRCCOLORKEY
, SDL_MapRGB(Icon
->format
, 255, 255, 255));
177 SDL_WM_SetIcon(Icon
, NULL
);
180 if (adresmod
< 0) adresmod
= 0; else if (adresmod
> 10) adresmod
= 10;
181 dblRes
= (adresmod
> 0);
182 if (adresmod
== 10) DIVISOR
= 2.0f
; else DIVISOR
= 1.0f
+(adresmod
/10.0f
);
187 SDL_ShowCursor(SDL_DISABLE
);
188 Flags
|= SDL_FULLSCREEN
;
192 #ifndef DISABLE_OPENGL
194 SDL_GL_SetAttribute(SDL_GL_RED_SIZE
, 8);
195 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE
, 8);
196 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE
, 8);
197 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE
, 8);
198 //SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
199 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER
, 1);
202 Flags
|= SDL_SWSURFACE
;
205 Screen
= SDL_SetVideoMode(fixVal(NewRes
.X
), fixVal(NewRes
.Y
), /*16*/32, Flags
);
206 if (!Screen
) ABORT("Couldn't set video mode.");
207 SDL_WM_SetCaption(Title
, 0);
208 globalwindowhandler::Init();
209 DoubleBuffer
= new bitmap(NewRes
);
211 ColorDepth
= 32/*16*/;
212 fuck_alsa_messages();
213 buildKernel(NewRes
.X
, NewRes
.Y
);
215 #ifndef DISABLE_OPENGL
222 static inline void toRGB (int* r
, int* g
, int* b
, packcol16 c
) {
223 if (b
) *b
= (c
<<3)&0xff;
224 if (g
) *g
= ((c
>>5)<<2)&0xff;
225 if (r
) *r
= ((c
>>11)<<3)&0xff;
229 static inline packcol16
fromRGB (int r
, int g
, int b
) {
230 if (r
< 0) r
= 0; else if (r
> 255) r
= 255;
231 if (g
< 0) g
= 0; else if (g
> 255) g
= 255;
232 if (b
< 0) b
= 0; else if (b
> 255) b
= 255;
242 void graphics::gotoXY (int cx
, int cy
) {
248 bool graphics::isCursorVisible () { return (curvisible
> 0); }
249 void graphics::showCursor () { ++curvisible
; }
250 void graphics::hideCursor () { --curvisible
; }
252 CursorState
graphics::getCursorState () { return CursorState(curx
, cury
, curvisible
); }
253 CursorState
graphics::getCursorState (int newx
, int newy
, truth newvis
) { return CursorState(curx
, cury
, curvisible
, newx
, newy
, newvis
); }
254 CursorState
graphics::getCursorState (int newx
, int newy
) { return CursorState(curx
, cury
, curvisible
, newx
, newy
); }
255 CursorState
graphics::getCursorState (truth newvis
) { return CursorState(curx
, cury
, curvisible
, newvis
); }
258 void graphics::BlitDBToScreen () {
259 const packcol16
*SrcPtr
= DoubleBuffer
->GetImage()[0];
260 const int newx
= fixVal(Res
.X
);
261 const int newy
= fixVal(Res
.Y
);
263 // convert source buffer
264 const packcol16
*sptr
= SrcPtr
;
265 uint32_t *dptr
= (uint32_t*)bufc32
;
266 for (int y
= 0; y
< Res
.Y
; ++y
) {
267 for (int x
= 0; x
< Res
.X
; ++x
) {
268 packcol16 c
= *sptr
++;
269 unsigned char b
= (c
<<3)&0xff;
270 unsigned char g
= ((c
>>5)<<2)&0xff;
271 unsigned char r
= ((c
>>11)<<3)&0xff;
272 *dptr
++ = b
|(g
<<8)|(r
<<16);
276 if (curvisible
> 0 && curx
>= -7 && cury
>= 0 && curx
+8 <= Res
.X
&& cury
< Res
.Y
) {
277 truth curhi
= (SDL_GetTicks()%1200 < 600);
278 dptr
= (uint32_t*)bufc32
;
280 if (curx
>= 0) dptr
+= curx
;
281 for (int x
= curx
; x
< curx
+8; ++x
) {
282 if (x
>= 0 && x
< Res
.X
) *dptr
++ = (curhi
? 0xffffff : 0x7f7f7f);
287 if (SDL_MUSTLOCK(Screen
) && SDL_LockSurface(Screen
) < 0) ABORT("Can't lock screen");
289 unsigned char *DestPtr
= static_cast<unsigned char*>(Screen
->pixels
);
290 feuLong ScreenYMove
= Screen
->pitch
;
293 if (DIVISOR
!= 2.0f
) {
294 // copy converted buffer used kernel
295 unsigned char *curs
= bufc32
;
297 for (int y
= 0; y
< newy
; ++y
) {
298 uint32_t *dp
= (uint32_t*)DestPtr
;
299 for (int x
= 0; x
< newx
; ++x
) {
301 for (int n
= 0; n
< 3; ++n
) {
302 int c
= lrintf(curs
[i
->sofs
[0]+n
]*i
->frc0
+curs
[i
->sofs
[1]+n
]*i
->frc1
)*i
->yfrc0
+(curs
[i
->sofs
[2]+n
]*i
->frc0
+curs
[i
->sofs
[3]+n
]*i
->frc1
)*i
->yfrc1
;
303 //if (c < 0) c = 0; else if (c > 255) c = 255;
304 //dclr |= (c<<(n*8));
305 dclr
|= ((c
&0xff)|(255-((-(int)(c
< 256))>>24)))<<(n
*8); //K8 WARNING! ABSOLUTELY NON-PORTABLE AND CAUSES UB!
310 DestPtr
+= ScreenYMove
;
313 for (int y
= 0; y
< Res
.Y
; ++y
, DestPtr
+= ScreenYMove
) {
314 uint32_t *s
= (uint32_t*)(bufc32
+y
*(Res
.X
*4));
315 uint32_t *d
= (uint32_t*)(DestPtr
);
316 for (int x
= 0; x
< Res
.X
; ++x
) { *d
++ = *s
; *d
++ = *s
++; }
317 DestPtr
+= ScreenYMove
;
318 memcpy(DestPtr
, bufc32
+y
*(Res
.X
*4), Res
.X
*4*2);
322 for (int y
= 0; y
< Res
.Y
; ++y
, DestPtr
+= ScreenYMove
) {
323 uint32_t *s
= (uint32_t*)(bufc32
+y
*(Res
.X
*4));
324 memcpy(DestPtr
, s
, Res
.X
*4);
327 if (SDL_MUSTLOCK(Screen
)) SDL_UnlockSurface(Screen
);
328 SDL_UpdateRect(Screen
, 0, 0, fixVal(Res
.X
), fixVal(Res
.Y
));
330 if (maintid
== 0) ABORT("OpenGL not initialized.");
332 glMatrixMode(GL_PROJECTION
); // for ortho camera
334 glOrtho(0, newx
, newy
, 0, -1, 1); // top-to-bottom
336 glViewport(0, 0, newx
, newy
);
338 glMatrixMode(GL_MODELVIEW
);
341 glBindTexture(GL_TEXTURE_2D
, maintid
);
342 glTexSubImage2D(GL_TEXTURE_2D
, 0, 0/*x*/, 0/*y*/, Res
.X
, Res
.Y
, /*GL_RGBA*/GL_BGRA
, GL_UNSIGNED_BYTE
, bufc32
);
344 glEnable(GL_TEXTURE_2D
);
345 glDisable(GL_LIGHTING
);
346 glDisable(GL_DITHER
);
348 glDisable(GL_DEPTH_TEST
);
349 glDisable(GL_STENCIL_TEST
);
350 glDisable(GL_SCISSOR_TEST
);
351 glDisable(GL_CULL_FACE
);
352 glDisable(GL_POLYGON_OFFSET_FILL
);
353 glDisable(GL_ALPHA_TEST
);
355 glDisable(GL_COLOR_LOGIC_OP
);
356 glDisable(GL_INDEX_LOGIC_OP
);
357 glDisable(GL_POLYGON_SMOOTH
);
359 glColor4f(1.0f
, 1.0f
, 1.0f
, 1.0f
);
361 glTexCoord2f(0.0f
, 0.0f
); glVertex2i(0, 0); // top-left
362 glTexCoord2f(1.0f
, 0.0f
); glVertex2i(newx
, 0); // top-right
363 glTexCoord2f(1.0f
, 1.0f
); glVertex2i(newx
, newy
); // bottom-right
364 glTexCoord2f(0.0f
, 1.0f
); glVertex2i(0, newy
); // bottom-left
367 glBindTexture(GL_TEXTURE_2D
, 0);
369 SDL_GL_SwapBuffers();
374 void graphics::SwitchMode () {
376 if (Screen
->flags
& SDL_FULLSCREEN
) {
377 SDL_ShowCursor(SDL_ENABLE
);
378 Flags
= SDL_SWSURFACE
;
381 SDL_ShowCursor(SDL_DISABLE
);
382 Flags
= SDL_SWSURFACE
|SDL_FULLSCREEN
;
385 if (SwitchModeHandler
) SwitchModeHandler();
386 #ifndef DISABLE_OPENGL
390 Screen
= SDL_SetVideoMode(fixVal(Res
.X
), fixVal(Res
.Y
), ColorDepth
, Flags
);
391 if (!Screen
) ABORT("Couldn't toggle fullscreen mode.");
392 buildKernel(Res
.X
, Res
.Y
);
393 #ifndef DISABLE_OPENGL
400 void graphics::ReinitMode (sLong adresmod
) {
401 if (adresmod
< 0) adresmod
= 0; else if (adresmod
> 10) adresmod
= 10;
402 dblRes
= (adresmod
> 0);
403 if (adresmod
== 10) DIVISOR
= 2.0f
; else DIVISOR
= 1.0f
+(adresmod
/10.0f
);
406 if (Screen
->flags
&SDL_FULLSCREEN
) {
408 //Flags = SDL_SWSURFACE|SDL_FULLSCREEN;
409 return; // nothing to do here, really
412 #ifndef DISABLE_OPENGL
416 Flags
= SDL_SWSURFACE
;
418 Screen
= SDL_SetVideoMode(fixVal(Res
.X
), fixVal(Res
.Y
), ColorDepth
, Flags
);
419 buildKernel(Res
.X
, Res
.Y
);
420 #ifndef DISABLE_OPENGL
427 void graphics::LoadDefaultFont (cfestring
&FileName
) {
428 DefaultFont
= new rawbitmap(FileName
);