Mercurial > hg > forks > 3x666-SDL
view 3x666.c @ 19:16efabca7e04
Some work on making the audio work .. there is sound, but it's not correct.
Also some buffer overflows seem to happen, so there will eventually be a
crash.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 15 Mar 2013 20:27:12 +0200 |
parents | ea16e1b51284 |
children | 19fccd4a7404 |
line wrap: on
line source
#include <SDL.h> #include <math.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <stdarg.h> #include "config.h" #include "3xfont.h" #if !defined(FALSE) && !defined(TRUE) && !defined(BOOL) typedef enum { FALSE = 0, TRUE = 1 } BOOL; #endif #ifndef BOOL # ifdef bool # define BOOL bool # else # define BOOL int # endif #endif struct { int tickLen; int frameTime, frameCount, startTime, endTime; BOOL exitFlag; int mixFill, mixBufSize; Sint16 *mixBuf; int optVFlags; SDL_Surface *screen; SDL_Event event; SDL_AudioSpec optAfmt; } engine; typedef struct { int x, y, z; } vec3d; int *ballz; void setpal(void); static inline int dmClamp(const int v, const int min, const int max) { return (v < min ? min : (v > max ? max : v)); } static int engineGetTick() { return ((engine.frameTime - engine.startTime) * SET_DEMOHZ) / 1000; } void dmPrintVA(const char *fmt, va_list ap) { #ifndef __WIN32 vfprintf(stderr, fmt, ap); #endif } void dmPrint(const char *fmt, ...) { #ifndef __WIN32 va_list ap; va_start(ap, fmt); dmPrintVA(fmt, ap); va_end(ap); #endif } void dmErrorVA(const char *fmt, va_list ap) { fprintf(stderr, SET_PROG_NAME ": "); vfprintf(stderr, fmt, ap); } void dmError(const char *fmt, ...) { va_list ap; va_start(ap, fmt); dmErrorVA(fmt, ap); va_end(ap); } static BOOL engineInitializeVideo() { SDL_FreeSurface(engine.screen); engine.screen = SDL_SetVideoMode(SET_VID_BUFW, SET_VID_BUFH, 8, engine.optVFlags); if (engine.screen == NULL) { dmError("Can't SDL_SetVideoMode(): %s\n", SDL_GetError()); return FALSE; } setpal(); return TRUE; } /**************** tEXT dRAWiNG rOUTiNES ********** bitmaps are for lamers :) let's use a little 12-segment calculator font... ascii chars 32..90, 16 bits per char unpacked -> 114 bytes for the whole font ;) let's credit karl/nooon for the original idea. */ void txtDrawSegment(int y, int x, int w, int h) { /* clip clip clip */ if (x + w > SET_VID_BUFW) w = SET_VID_BUFW - x; if (x < 0) { w += x; x = 0; } if (y + h > SET_VID_BUFH) h = SET_VID_BUFH - y; if (y < 0) { h += y; y = 0; } if (w > 0 && h > 0) { Uint8 *b = engine.screen->pixels + (y * engine.screen->pitch) + x; for (; h; h--) { memset(b, 122, w); b += engine.screen->pitch; } } } void txtDrawChar(int x, int y, int c, int xunit, int yunit) { x -= xunit * 2; y -= yunit * 3; for (;;) { if (!c) break; if (c & 1) txtDrawSegment(y, x + 1, xunit * 2 - 2, yunit); if (c & 2) txtDrawSegment(y, x + 1 + xunit * 2, xunit * 2 - 2, yunit); y++; c >>= 2; if (!c) break; if (c & 1) txtDrawSegment(y, x, xunit, yunit * 3 - 2); if (c & 2) txtDrawSegment(y, x + ((xunit * 3) >> 1), xunit, yunit * 3 - 2); if (c & 4) txtDrawSegment(y, x + xunit * 3, xunit, yunit * 3 - 2); y += yunit * 2; c >>= 3; } } void drawtxtscr(char *str) { int x = SET_VID_BUFW >> 4, y = SET_VID_BUFH >> 3; while (*str) { if (*str >= 32) { txtDrawChar(x, y, phont[*str - 32], SET_VID_BUFW / 50, SET_VID_BUFW / 80); x += SET_VID_BUFW / 10; } else { x = SET_VID_BUFW >> 4; y += SET_VID_BUFW / 10; } str++; } } void flashtxt(char *str) { int x = (SET_VID_BUFW >> 1) - (strlen(str) + 1) * 3 * SET_VID_BUFW / 80; while (*str) { txtDrawChar(x, SET_VID_BUFH >> 1, phont[*str++ - 32], SET_VID_BUFW / 50, SET_VID_BUFW / 80); x += SET_VID_BUFW / 10; } } /*************************** DA PHONGBALL HEAVEN ************** A short course on phongball theory! A sphere: x^2+y^2+z^2=R^2 Diffuse shading: intensity = dotproduct(surfacenormal,lightvector) (doing this for every drawn point of the surface is sometimes called phong shading even if the normals aren't actually interpolated) For a sphere, a normal vector at a point of the surface == constant * the coordinates of the point (if center == origo). Thus, the function for the intensity of a 2d-projected phongball can be stated as intensity(x,y) = l.x*x + l.y*y + l.z*z, z = sqrt(R^2-x^2-y^2) The first two muls can be eliminated easily. (and will be eliminated by a good compiler even if you are lazy) The third mul can be eliminated by approximating l.z*z with a function of the form f(x)=a*x^2+c. This approximation makes the ball look a bit "twisty" but who cares, it just looks damn cool ;) ***/ #if (SET_VID_BUFH < SET_VID_BUFW) # define maxR (SET_VID_BUFH >> 1) #else # define maxR (SET_VID_BUFW >> 1) #endif struct { int *tab; signed int R; } balltab[50]; void preball() { unsigned int rR; signed int R; for (rR = 0; rR < 48; rR++) { int R2, *d; signed int y; R = (maxR * (rR + 4)) / 52; if (R < 2) R = 2; R2 = R * R; balltab[rR].R = R; d = balltab[rR].tab = malloc(R * 2 * sizeof(int)); for (y = -R + 1; y < R - 1; y++) *d++ = sqrt(R2 - y * y); } balltab[49].R = balltab[48].R = balltab[47].R; balltab[49].tab = balltab[48].tab = balltab[47].tab; } void drawball_inloop(Uint8 *d, int dotxyz, int ddot, int dddot, int x) { for (; x; x--) { dotxyz += ddot; ddot += dddot; *d++ = dotxyz >> 16; } } void drawball(SDL_Surface *screen, vec3d * l, int relR) { int R = balltab[relR].R, *s = balltab[relR].tab; signed int doty = (-(R - 1) * l->y); signed int y = R * 2 - 2; Uint8 *dp = screen->pixels + (SET_VID_BUFW >> 1) - R + ((SET_VID_BUFH >> 1) - R) * screen->pitch; for (; y; y--) { int halfw = *s++; if (halfw) { drawball_inloop(dp + R - halfw, (doty - (l->x * halfw)) << 8, (l->x + l->z) << 8, 0 - ((l->z << 8) / halfw), halfw << 1); } dp += screen->pitch; doty += l->y; } } /* some extra for freaks: a plasma made with the phongball innerloop :) looks ugly. void drawplasma(char *d,float t) { int y=SET_VID_BUFH; float u=0,du=500/SET_VID_BUFH; for(;y;y--){ drawball_inloop(d, sin(t*0.02+0+u*0.033)*65536*256, cos(t*0.04+1+u*0.022)*65536*4096/SET_VID_BUFW, -2*cos(t*0.04+1+u*0.022)*65536*4096/(SET_VID_BUFW*SET_VID_BUFW), SET_VID_BUFW); d+=SET_VID_BUFW; u+=du; } } */ /************************ oTHA FX ***************/ void rotochess(SDL_Surface *screen, int du, int dv, int iu, int iv) { int hu = iu - (dv * (SET_VID_BUFH >> 1)) - (du * (SET_VID_BUFW >> 1)), hv = iv + (du * (SET_VID_BUFH >> 1)) - (dv * (SET_VID_BUFW >> 1)); int y; Uint8 *dp = screen->pixels; for (y = SET_VID_BUFH; y; y--) { Uint8 *d = dp; int u = hu, v = hv, x; for (x = SET_VID_BUFW; x; x--) { u += du; v += dv; *d++ = ((u ^ v) >> 8) & 0xb1; } dp += screen->pitch; hu += dv; hv -= du; } } /***************************************************************/ void setpal(void) { SDL_Color pal[SET_VID_COLORS]; int i, a = 3, b = 0; for (i = 255; i; i--) { int n = (i + 128) & 255; pal[n].r = (abs(i - 140) >> a) & 255; pal[n].g = ((abs(i - 128) >> b) & 255) ^ 1; pal[n].b = (abs(i - 96) >> b) & 255; if (i == 128) { a = 0; b = 1; } } SDL_SetColors(engine.screen, pal, 0, SET_VID_COLORS); } void unitvec(vec3d * v, float a, float b, float c, float m) { float cam = cos(a) * m, sam = sin(a) * m, sbcam = sin(b) * cam; v->x = cos(b) * cam; v->y = cos(c) * sam - sin(c) * sbcam; v->z = cos(c) * sbcam + sin(c) * sam; } /************************* MUSiC cODE **************************/ /* This table was ripped (and reduced and rudely integerized) from the Maube tracker by K .. keep on the good work man! ;) */ const Sint16 noterate[3 * 12] = { 1000, 1059, 1122, 1189, 1259, 1334, 1414, 1498, 1587, 1681, 1781, 1887, 2000, 2118, 2244, 2378, 2519, 2669, 2828, 2996, 3174, 3363, 3563, 3775, 4000, 4237, 4489, 4756, 5039, 5339, 5656, 5993, 6349, 6727, 7127, 7550 }; /* 64 bytes of pure musical power ;) Originally composed with Scream Tracker. */ const char basstrak[32] = { 12, 0, 24, 12, 12, 24, 12, 24, 12, 0, 24, 12, 12, 24, 12, 24, 15, 0, 27, 15, 15, 27, 15, 27, 14, 0, 26, 14, 15, 27, 17, 29 }; const char melody[32] = { 24, 12, 19, 15, 24, 0, 19, 0, 24, 12, 19, 15, 24, 0, 15, 19, 15, 19, 15, 19, 22, 0, 15, 19, 14, 17, 21, 14, 22, 17, 17, 22 }; int *drum0, *drum1; /* sampling sucks! */ void audio_precalcs() { int drumlgt = engine.tickLen * SET_ROWTIX * 4; int *d = drum0 = malloc(drumlgt * sizeof(int)), *e = drum1 = malloc(drumlgt * sizeof(int)), i, vol = 24680, dvol = 35000 / (float) drumlgt; int o = 0, oo = 0; float a = 0, da = 386 / (float) drumlgt, dda = da / (float) drumlgt; dmPrint("aCtIvATiNg 303 eMuLAtOR\n"); for (i = drumlgt; i; i--) { o = (o >> 1) + (rand() % vol) - (rand() % vol); oo = (oo * 2 + ((rand() % vol) - (rand() % vol))) / 3; o *= sin(a); oo *= sin(a); *d++ = (vol * sin((a / 2) + ((float) dmClamp(o * 2, -65535, 65535)) / 80000)); *e++ = (vol * sin(a + ((float) oo) / 60000)); a += da; da -= dda; vol -= dvol; } } static int engineRenderAudio(Sint16 *stream) { static int rowno = 0; static signed int delta = -5; static char ismelody = 0, silend = 0; int i, rowlgt = engine.tickLen * SET_ROWTIX; Sint16 *d = stream, note; /* BASS (sawtooth ofcoz) */ note = basstrak[(rowno >> 1) & 31]; if (!note) note = basstrak[((rowno >> 1) & 31) - 1]; else if (rowno & 1) note = 0; if ((rowno & 3) == 3) note = 0; if (note) { int ps = 16384, dps; note += delta; dps = ((noterate[note] << 10) / SET_AUDIO_FREQ); for (i = rowlgt; i; i--) { *d++ = dmClamp(ps, -32767, 32767); ps = (ps + dps) & 32767; } } else { for (i = rowlgt; i; i--) *d++ = 16384; } /* MELODY (sawtooth as well :) */ if (!(silend && ((rowno & 63) > 47))) { if (ismelody) { d = (Sint16 *) stream; if (rowno & 1) note = 0; else note = melody[(rowno >> 1) & 31]; if (note) { int ps = 16384, dps; /* this loop is different */ note += delta; dps = ((noterate[note] << 12) / engine.optAfmt.freq); for (i = rowlgt; i; i--) { *d++ = dmClamp(ps, -32767, 32767); ps = (ps + dps) & 32767; } } } /* DRUMS (rave on!!!) */ { int *s = drum1; d = (Sint16 *) stream; if (rowno & 4) s = drum0; s += (rowno & 3) * rowlgt; for (i = rowlgt; i; i--) *d++ += *s++; } } /* PATTERN SHIFT */ rowno++; /* no switch+case? just check out how gcc handles them! it's 1024+ bytes for every phukken switch statement! in this case we can prefer size to speed, can't we? */ if ((rowno & 63) == 0) { int r = rowno >> 6; if (r == 2) delta = 0; if (r == 4) ismelody = 1; if (r == 6 || r == 10) delta = 5; if (r == 7 || r == 11) silend = 1; if (r == 8) delta = silend = 0; if (r == 12) { rowno = ismelody = silend = 0; delta = -5; } } return rowlgt; } static void engineAudioCallback(void *userdata, Uint8 *stream, int len) { (void) userdata; // We inherently assume mono here, as the audio code is not // capable of producing stereo anyway (for now, at least.) int need = len / sizeof(Sint16); // The audio rendering handling is a bit silly due to the way // the original code works (assumes that it can always render // a certain amount/duration of data, instead of being given // the buffer duration/size to render. So we cope with that here. while (engine.mixFill < need && engine.mixFill < engine.mixBufSize) { int got = engineRenderAudio(engine.mixBuf + engine.mixFill); engine.mixFill += got; } memcpy(stream, engine.mixBuf, len); engine.mixFill -= need; if (engine.mixFill > 0) { memmove(engine.mixBuf, engine.mixBuf + need, engine.mixFill * sizeof(Sint16)); } } /**************** tEXT gENERATORS eTC ***************/ char skrtxt[] = { " HI THERE ! THIS IS THE FIRST OCSA RELEASE FOR LINUX ! " "IT'S A STUPID INTRO CALLED 3X666 ! " }; #define CHTIME 16 #define CHPSCR 8 void plainscroll(int t) { int chno = t / CHTIME; int x = 0 - ((t % CHTIME) * (SET_VID_BUFW / CHPSCR)) / CHTIME; int h = (abs((t % 48) - 24) * SET_VID_BUFH) / 256, i; char *c = skrtxt + chno; for (i = 0; i < CHPSCR + 1; i++) { txtDrawChar(x, (SET_VID_BUFH * 3) / 4, phont[*c++ - 32], SET_VID_BUFW / (6 * CHPSCR), h); x += SET_VID_BUFW / CHPSCR; } } char *lyrix(void) { static int phinext = 0, philast; int phiwsty; char *phiword; phiwsty = phinext; if (!phiwsty) { if (!(rand() & 3)) phiwsty = 13; else phiwsty = 1 + (rand() & 1); } if (phiwsty == 1) { char *w[] = { "HERE", "THERE", "NOW", "TOMORROW", "TODAY", "NEVER" }; phiword = w[rand() % 6]; if (rand() & 1) phinext = 2; else phinext = 12; } else if (phiwsty == 2) { char nx[] = { 5, 10, 7, 3, 11 }; philast = rand() & 1; if (!philast) phiword = "YOU"; else phiword = "I"; phinext = nx[rand() % 5]; } else if (phiwsty == 3) { char *w[] = { "DON'T", "CAN'T", "WON'T", "COULDN'T" }; phiword = w[rand() % 4]; phinext = 7 + (rand() & 4); } else if (phiwsty == 4) { if (rand() & 1) phiword = "YOU"; else phiword = "ME"; if (rand() & 1) phinext = 6; else if (rand() & 1) phinext = 0; else phinext = 11; } else if (phiwsty == 5) { if (philast) phiword = "AM"; else phiword = "ARE"; if (rand() & 1) phinext = 6; else phinext = 12 + (rand() & 1); } else if (phiwsty == 6) { char *w[] = { "FALLING", "THINKING", "DREAMING", "CRYING", "LYING", "REACHING", "BREATHING", "BURNING", "RUNNING" }; phiword = w[rand() % 9]; if (rand() & 1) phinext = 9; else if (rand() & 1) phinext = 0; else phinext = 13; } else if (phiwsty == 7) { char nx[] = { 8, 4, 12 }; if (rand() & 1) phiword = "NEED"; else phiword = "WANT"; phinext = nx[rand() % 3]; } else if (phiwsty == 8) { phiword = "TO"; phinext = 11; } else if (phiwsty == 9) { char *w[] = { "DOWN", "OFF", "OUT", "UP", "ABOUT" }; phiword = w[rand() % 5]; if (rand() & 1) phinext = rand() & 4; else phinext = 12 + (rand() & 1); } else if (phiwsty == 10) { char *w[] = { "CAN", "COULD", "WOULD", "MAY", "MIGHT" }; phiword = w[rand() % 5]; if (rand() & 1) phinext = 11; else phinext = 12; } else if (phiwsty == 11) { char *w[] = { "SEE", "HEAR", "FEEL", "THINK" }; phiword = w[rand() % 4]; if (rand() & 1) phinext = 12; else phinext = rand() & 4; } else if (phiwsty == 12) { char *w[] = { "WHAT", "SOMETHING", "NOTHING", "THINGS", "WHATEVER" }; phiword = w[rand() % 5]; phinext = 2; } else if (phiwsty == 13) { phiword = "THE"; phinext = 14; } else { char *w[] = { "WAY", "EYES", "WORLD", "ROBOT", "FREEDOM", "HATE" }; phiword = w[rand() % 6]; phinext = 0; } return phiword; } char *dotxtscr(void) { static int cnt = 0; cnt++; if (cnt == 1) return "WHERES THE\n" "DESIGN?\n\n" "WHERES THE\n" "ATTITUDE?!"; if (cnt == 2) return "NOTHING\n" "HAPPENED\n" "IN 1997"; if (cnt == 3) return "PERHAPS\n" "IT IS TIME\n" "FOR A NEW\n" "PROPHECY?"; if (cnt == 4) return "IN 1998,\n" "SCENE WILL\n" "DIE !!!!!"; if (cnt == 5) return "PHONGBALLS\n" "WILL\n" "INVADE\n" "THE WORLD"; if ((cnt == 6) || (cnt == 7)) return "HALUU OLLA\n" "APPELSIINI"; return NULL; } const char *endscroll = "THAT'S ALL\n" "FOLKS !\n" "\n" "ALL CODING +\n" "COMPOSING\n" "BY VIZNUT !\n" "\n" "WHAT A\n" "MARVELOUS\n" "PALETTE !\n" "WHAT A\n" "SUPERB TUNE !\n" "\n" "BUT IT'S ALL\n" "BELOW 10 KB\n" "AND RUNS\n" "SMOOTHLY ON\n" "A 386\n" "\n" "GREETINGS TO\n" "ALL THE\n" "LINUX SCENE !\n" "\n" "LET'S MAKE\n" "THIS WORLD A\n" "BETTER PLACE\n" "TO LIVE IN !\n" "\n" "THIS IS JUST\n" "A PIECE OF\n" "SHITTY CODE\n" "BUT IT'S ALL\n" "YOURS !\n" "\n" "RIP OFF\n" "EVERYTHING !\n" "USE IT FOR\n" "SOMETHING\n" "CREATIVE !\n" "\n" "\n\n\nOCSA 1998"; void doendscroll(int t) { const char *s = endscroll; int y = SET_VID_BUFH - (SET_VID_BUFH * t / 512), x = SET_VID_BUFW / 24; while (*s) { if (*s < 32) { x = SET_VID_BUFW / 24; y += SET_VID_BUFH / 8; } else if (y >= 0 - (SET_VID_BUFH / 8) && y < SET_VID_BUFH) { txtDrawChar(x, y, phont[*s - 32], SET_VID_BUFW / 60, SET_VID_BUFH / 60); x += SET_VID_BUFW / 13; } s++; } } /********************** tHA kORE bEGiNS *********************/ #define BLACKBG 0x0001 #define FLASHBG 0x0002 #define OCSALOGO 0x0004 #define SCROLL0 0x0008 #define BALLIE 0x0010 #define BALLJUMPS 0x0020 #define COUNTAH 0x0040 #define CHESSBG 0x0080 #define PLASMABG 0x0100 #define FLASHTXT 0x0200 #define TXTSCR 0x0400 #define ENDSCR 0x0800 #define DEMOEND 0x1000 const Uint16 dezign[] = { 0 , BLACKBG | OCSALOGO | SCROLL0, 256 , FLASHBG | BALLIE | BALLJUMPS | COUNTAH, 384 , BLACKBG | BALLIE | BALLJUMPS | COUNTAH | OCSALOGO, 400 , BLACKBG | BALLIE | COUNTAH | OCSALOGO, 416 , BLACKBG | BALLIE, 448 , BLACKBG | BALLIE | TXTSCR, 512 , CHESSBG | BALLIE | BALLJUMPS | TXTSCR, 576 , CHESSBG | BALLIE | BALLJUMPS | TXTSCR, 640 , CHESSBG | BALLIE | BALLJUMPS | TXTSCR, 704 , CHESSBG | BALLIE | BALLJUMPS | TXTSCR, 768 , FLASHBG | FLASHTXT, 896 , FLASHBG | FLASHTXT | TXTSCR, 962 , FLASHBG | FLASHTXT | TXTSCR | BALLIE | BALLJUMPS, 1024, BLACKBG | BALLIE | ENDSCR, 1152, CHESSBG | BALLIE | BALLJUMPS | ENDSCR, 1344, FLASHBG | BALLIE | BALLJUMPS | ENDSCR, 1536, DEMOEND }; /* don't look at the rest of the code, it just sucks :) */ int main(int argc, char *argv[]) { BOOL initSDL = FALSE; const int U = SET_VID_BUFW / 40; const Uint16 *dez = dezign; int flagz = 0, flixtim = 0; char *phiword = NULL, *dizainword = NULL; dmPrint( SET_PROG_NAME " by Ocsa (PWP) (c) 1998\n" "libSDL port by ccr/TNSP^PWP (c) 2013\n"); // Parse commandline options // engine.optVFlags |= SDL_FULLSCREEN; // Initialize SDL components dmPrint("Engine initializing ..\n"); if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) != 0) { dmError("Could not initialize SDL: %s\n", SDL_GetError()); goto error_exit; } initSDL = TRUE; // Initialize audio parts engine.optAfmt.freq = SET_AUDIO_FREQ; engine.optAfmt.format = AUDIO_S16SYS; engine.optAfmt.channels = SET_AUDIO_CHN; engine.optAfmt.samples = engine.optAfmt.freq / 16; engine.optAfmt.callback = engineAudioCallback; // Initialize SDL audio if (SDL_OpenAudio(&engine.optAfmt, NULL) < 0) { dmError("Couldn't open SDL audio: %s\n", SDL_GetError()); } // Initialize SDL video if (!engineInitializeVideo()) goto error_exit; SDL_ShowCursor(SDL_DISABLE); SDL_WM_SetCaption(SET_WIN_NAME, SET_WIN_NAME); // Initialize effects preball(); srand(0); engine.tickLen = engine.optAfmt.freq / SET_DEMOHZ; audio_precalcs(); setpal(); engine.mixBufSize = (32 + SET_MAXROWLGT) * sizeof(Sint16); engine.mixBuf = malloc(engine.mixBufSize); // Start audio, enter main loop dmPrint("We are go.\n"); SDL_LockAudio(); SDL_PauseAudio(0); SDL_UnlockAudio(); engine.startTime = SDL_GetTicks(); while (!engine.exitFlag) { // Handle SDL events while (SDL_PollEvent(&engine.event)) switch (engine.event.type) { case SDL_KEYDOWN: switch (engine.event.key.keysym.sym) { case SDLK_ESCAPE: engine.exitFlag = TRUE; break; case SDLK_f: engine.optVFlags ^= SDL_FULLSCREEN; if (!engineInitializeVideo()) goto error_exit; break; case SDLK_RETURN: if (engine.event.key.keysym.mod & KMOD_ALT) { engine.optVFlags ^= SDL_FULLSCREEN; if (!engineInitializeVideo()) goto error_exit; } break; default: break; } break; case SDL_VIDEOEXPOSE: break; case SDL_QUIT: engine.exitFlag = TRUE; break; } // Draw frame engine.frameTime = SDL_GetTicks(); int qt = engineGetTick(&engine); if (SDL_MUSTLOCK(engine.screen) != 0 && SDL_LockSurface(engine.screen) != 0) { dmError("Can't lock surface.\n"); goto error_exit; } // Main rendering code while ((qt / SET_ROWTIX >= *dez) && (flagz & DEMOEND) == 0) { dez++; flagz = *dez++; if (flagz & FLASHTXT) flixtim = *(dez - 2); if (flagz & TXTSCR) dizainword = dotxtscr(); } if (flagz & FLASHTXT) { while ((qt / SET_ROWTIX) >= flixtim) { phiword = lyrix(); flixtim += 4; } } if (flagz & DEMOEND) engine.exitFlag = TRUE; if (flagz & BLACKBG) { SDL_FillRect(engine.screen, NULL, 0); } else if (flagz & FLASHBG) { unsigned char col = 130 + (qt % 48) * 2; SDL_FillRect(engine.screen, NULL, col); } if (flagz & CHESSBG) { int zoom = (10 + abs(((qt >> 1) % 96) - 48)) * 4096 / SET_VID_BUFW; rotochess(engine.screen, sin(qt * 0.03) * zoom, cos(qt * 0.03) * zoom, 0, 0); } //if(flagz&PLASMABG) drawplasma(ruutu, qt); if (flagz & OCSALOGO) { txtDrawChar(U * 6, U * 4, phont['O' - 32], U + U * sin(qt * 0.10 + 3), U); txtDrawChar(U * 14, U * 4, phont['C' - 32], U, U + U * sin(qt * 0.11 + 3)); txtDrawChar(U * 22, U * 4, phont['S' - 32], U, U + U * sin(qt * 0.12 + 3)); txtDrawChar(U * 30, U * 4, phont['A' - 32], U + U * sin(qt * 0.13 + 3), U); } if (flagz & SCROLL0) plainscroll(qt); if (flagz & BALLIE) { int zoom; vec3d joo; if (flagz & BALLJUMPS) zoom = abs((qt % 96) - 48); else zoom = 47; zoom = dmClamp(zoom, 0, 47); unitvec(&joo, 0.038 * qt, 0.023 * qt, 0.011 * qt, 32000 / balltab[zoom].R); joo.z <<= 1; drawball(engine.screen, &joo, zoom); } if (flagz & FLASHTXT) flashtxt(phiword); if ((flagz & TXTSCR) && ((qt / SET_ROWTIX) & 2)) drawtxtscr(dizainword); if (flagz & ENDSCR) doendscroll(qt - 1024 * SET_ROWTIX); if (flagz & COUNTAH) { int n = ((qt * 50 / 48) - 256 * 6); int dis = (rand() % U) >> 1; if (n > 666) n = 666; if (n > 600) { txtDrawChar(U * 12 + dis, (SET_VID_BUFH >> 1) + dis + U * 6, phont['X' - 32], U, U); txtDrawChar(U * 22 + dis, (SET_VID_BUFH >> 1) + dis + U * 6, phont['3' - 32], U, U); } txtDrawChar(U * 28 + dis, SET_VID_BUFH >> 1, phont[16 + (n % 10)], U, U); n /= 10; txtDrawChar(U * 18 + dis, SET_VID_BUFH >> 1, phont[16 + (n % 10)], U, U); n /= 10; txtDrawChar(U * 8 + dis, SET_VID_BUFH >> 1, phont[16 + (n % 10)], U, U); n /= 10; } // Flip screen, increase frame count, wait if (SDL_MUSTLOCK(engine.screen) != 0) SDL_UnlockSurface(engine.screen); engine.frameCount++; SDL_Flip(engine.screen); SDL_Delay(20); } error_exit: // Shutdown dmPrint("Shutting down.\n"); SDL_ShowCursor(SDL_ENABLE); if (engine.screen) SDL_FreeSurface(engine.screen); SDL_LockAudio(); SDL_PauseAudio(1); SDL_UnlockAudio(); if (initSDL) SDL_Quit(); return 0; }