From fd64dc3d1930a40d3f173c70206d77b554b92a21 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Tue, 10 May 2022 19:45:24 +0300 Subject: [PATCH 01/16] rt: started working on the tile-based rendering --- src/scr/raytrace.c | 108 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 79 insertions(+), 29 deletions(-) diff --git a/src/scr/raytrace.c b/src/scr/raytrace.c index bc9d654..ef6760a 100644 --- a/src/scr/raytrace.c +++ b/src/scr/raytrace.c @@ -21,7 +21,20 @@ static struct screen scr = { draw }; -static cgm_vec3 raydir[120][160]; +enum {LASTX = 1, LASTY = 2}; + +struct tile { + int sz; + unsigned int flags; + struct { int x, y; } cpos[4]; /* corner coordinates */ + uint16_t *cptr[4]; /* corner pixels */ +}; + +#define TILESZ 8 +#define NUM_TILES ((320 / TILESZ) * (240 / TILESZ)) + +static cgm_vec3 raydir[240][320]; +static struct tile tiles[NUM_TILES]; static struct rtscene scn; struct screen *raytrace_screen(void) @@ -31,17 +44,39 @@ struct screen *raytrace_screen(void) static int init(void) { - int i, j; + int i, j, k; float z = 1.0f / tan(cgm_deg_to_rad(25.0f)); + struct tile *tptr = tiles; - for(i=0; i<120; i++) { + for(i=0; i<240; i++) { cgm_vec3 *vptr = raydir[i]; - float y = 1.0f - (float)i / 60.0f; - for(j=0; j<160; j++) { - vptr->x = ((float)j / 80.0f - 1.0f) * 1.333333f; + float y = 1.0f - (float)i / 120.0f; + for(j=0; j<320; j++) { + vptr->x = ((float)j / 160.0f - 1.0f) * 1.333333f; vptr->y = y; vptr->z = z; vptr++; + + if(((j & (TILESZ-1)) | (i & (TILESZ-1))) == 0) { + tptr->sz = TILESZ; + tptr->flags = 0; + if(j + TILESZ >= 320) tptr->flags |= LASTX; + if(i + TILESZ >= 240) tptr->flags |= LASTY; + + tptr->cpos[0].x = j; + tptr->cpos[0].y = i; + tptr->cpos[1].x = j + (tptr->flags & LASTX ? TILESZ - 1 : TILESZ); + tptr->cpos[1].y = i; + tptr->cpos[2].x = j; + tptr->cpos[2].y = i + (tptr->flags & LASTY ? TILESZ - 1 : TILESZ); + tptr->cpos[3].x = tptr->cpos[1].x; + tptr->cpos[3].y = tptr->cpos[2].y; + + for(k=0; k<4; k++) { + tptr->cptr[k] = fb_pixels + tptr->cpos[k].y * 320 + tptr->cpos[k].x; + } + tptr++; + } } } @@ -71,33 +106,48 @@ static void start(long start_time) { } +static uint16_t INLINE rend_pixel(int x, int y) +{ + int r, g, b; + cgm_ray ray; + cgm_vec3 col; + + ray.dir = raydir[y][x]; + cgm_vcons(&ray.origin, 0, 0, -5); + + if(ray_trace(&ray, &scn, 0, &col)) { + r = cround64(col.x * 255.0f); + g = cround64(col.y * 255.0f); + b = cround64(col.z * 255.0f); + if(r > 255) r = 255; + if(g > 255) g = 255; + if(b > 255) b = 255; + return PACK_RGB16(r, g, b); + } + return 0; +} + +#define FBPTR(x, y) (fb_pixels + ((y) << 8) + ((y) << 6) + (x)) + static void draw(void) { - int i, j, r, g, b; - uint16_t pix, *fbptr = fb_pixels; - - for(i=0; i<120; i++) { - for(j=0; j<160; j++) { - cgm_ray ray; - cgm_vec3 col; - ray.dir = raydir[i][j]; - cgm_vcons(&ray.origin, 0, 0, -5); - - if(ray_trace(&ray, &scn, 0, &col)) { - r = cround64(col.x * 255.0f); - g = cround64(col.y * 255.0f); - b = cround64(col.z * 255.0f); - if(r > 255) r = 255; - if(g > 255) g = 255; - if(b > 255) b = 255; - pix = PACK_RGB16(r, g, b); - } else { - pix = 0; + int i, j, xbound, ybound; + uint16_t *fbptr; + struct tile *tptr; + + tptr = tiles; + for(i=0; icptr[0] = rend_pixel(tptr->cpos[0].x, tptr->cpos[0].y); + if(tptr->flags & LASTX) { + *tptr->cptr[1] = rend_pixel(tptr->cpos[1].x, tptr->cpos[1].y); + if(tptr->flags & LASTY) { + *tptr->cptr[3] = rend_pixel(tptr->cpos[3].x, tptr->cpos[3].y); } - fbptr[0] = fbptr[1] = fbptr[320] = fbptr[321] = pix; - fbptr += 2; } - fbptr += 320; + if(tptr->flags & LASTY) { + *tptr->cptr[2] = rend_pixel(tptr->cpos[2].x, tptr->cpos[2].y); + } + tptr++; } swap_buffers(0); -- 1.7.10.4 From edce4a6bc4cd26836484a0940a15afd9f02747d2 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Tue, 10 May 2022 21:58:49 +0300 Subject: [PATCH 02/16] rt: subsampling wip --- src/scr/raytrace.c | 116 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 79 insertions(+), 37 deletions(-) diff --git a/src/scr/raytrace.c b/src/scr/raytrace.c index ef6760a..32ade1f 100644 --- a/src/scr/raytrace.c +++ b/src/scr/raytrace.c @@ -21,13 +21,9 @@ static struct screen scr = { draw }; -enum {LASTX = 1, LASTY = 2}; - struct tile { - int sz; - unsigned int flags; - struct { int x, y; } cpos[4]; /* corner coordinates */ - uint16_t *cptr[4]; /* corner pixels */ + int x, y; + uint16_t *fbptr; }; #define TILESZ 8 @@ -58,23 +54,9 @@ static int init(void) vptr++; if(((j & (TILESZ-1)) | (i & (TILESZ-1))) == 0) { - tptr->sz = TILESZ; - tptr->flags = 0; - if(j + TILESZ >= 320) tptr->flags |= LASTX; - if(i + TILESZ >= 240) tptr->flags |= LASTY; - - tptr->cpos[0].x = j; - tptr->cpos[0].y = i; - tptr->cpos[1].x = j + (tptr->flags & LASTX ? TILESZ - 1 : TILESZ); - tptr->cpos[1].y = i; - tptr->cpos[2].x = j; - tptr->cpos[2].y = i + (tptr->flags & LASTY ? TILESZ - 1 : TILESZ); - tptr->cpos[3].x = tptr->cpos[1].x; - tptr->cpos[3].y = tptr->cpos[2].y; - - for(k=0; k<4; k++) { - tptr->cptr[k] = fb_pixels + tptr->cpos[k].y * 320 + tptr->cpos[k].x; - } + tptr->x = j; + tptr->y = i; + tptr->fbptr = fb_pixels + i * 320 + j; tptr++; } } @@ -127,27 +109,87 @@ static uint16_t INLINE rend_pixel(int x, int y) return 0; } -#define FBPTR(x, y) (fb_pixels + ((y) << 8) + ((y) << 6) + (x)) +#define CMPMASK 0xe79c +static void rend_tile(uint16_t *fbptr, int x0, int y0, int tsz, unsigned int valid) +{ + uint16_t *cptr[4]; + uint16_t cpix[4], tmp; + uint32_t pp0, pp1, pp2, pp3, *fb32; + int x1, y1, offs; + + if(tsz <= 1) { + if(!valid) { + *fbptr = rend_pixel(x0, y0); + } + return; + } + + offs = tsz - 1; + x1 = x0 + offs; + y1 = y0 + offs; + + cptr[0] = fbptr; + cptr[1] = fbptr + tsz - 1; + cptr[2] = fbptr + (offs << 8) + (offs << 6); + cptr[3] = cptr[2] + tsz - 1; + + cpix[0] = valid & 1 ? *cptr[0] : rend_pixel(x0, y0); + cpix[1] = valid & 2 ? *cptr[1] : rend_pixel(x1, y0); + cpix[2] = valid & 4 ? *cptr[2] : rend_pixel(x0, y1); + cpix[3] = valid & 8 ? *cptr[3] : rend_pixel(x1, y1); + + tmp = cpix[0] & CMPMASK; + if((cpix[1] & CMPMASK) != tmp) goto subdiv; + if((cpix[2] & CMPMASK) != tmp) goto subdiv; + if((cpix[3] & CMPMASK) != tmp) goto subdiv; + + pp0 = cpix[0] | ((uint32_t)cpix[0] << 16); + pp1 = cpix[1] | ((uint32_t)cpix[1] << 16); + pp2 = cpix[2] | ((uint32_t)cpix[2] << 16); + pp3 = cpix[3] | ((uint32_t)cpix[3] << 16); + fb32 = (uint32_t*)fbptr; + + switch(tsz) { + case 4: + fb32[1] = fb32[161] = pp1; + fb32[320] = fb32[480] = pp2; + fb32[321] = fb32[481] = pp3; + case 2: + fb32[0] = fb32[160] = pp0; + break; + case 8: + fb32[0] = fb32[1] = pp0; fb32[2] = fb32[3] = pp1; + fb32[160] = fb32[161] = pp0; fb32[162] = fb32[163] = pp1; + fb32[320] = fb32[321] = pp2; fb32[322] = fb32[323] = pp3; + fb32[480] = fb32[481] = pp2; fb32[482] = fb32[483] = pp3; + break; + } + +subdiv: + *cptr[0] = cpix[0]; + *cptr[1] = cpix[1]; + *cptr[2] = cpix[2]; + *cptr[3] = cpix[3]; + + tsz >>= 1; + rend_tile(fbptr, x0, y0, tsz, 1); + rend_tile(fbptr + tsz, x0 + tsz, y0, tsz, 2); + fbptr += (tsz << 8) + (tsz << 6); + y0 += tsz; + rend_tile(fbptr, x0, y0, tsz, 4); + rend_tile(fbptr, x0 + tsz, y0, tsz, 8); +} static void draw(void) { int i, j, xbound, ybound; uint16_t *fbptr; - struct tile *tptr; + struct tile *tile; - tptr = tiles; + tile = tiles; for(i=0; icptr[0] = rend_pixel(tptr->cpos[0].x, tptr->cpos[0].y); - if(tptr->flags & LASTX) { - *tptr->cptr[1] = rend_pixel(tptr->cpos[1].x, tptr->cpos[1].y); - if(tptr->flags & LASTY) { - *tptr->cptr[3] = rend_pixel(tptr->cpos[3].x, tptr->cpos[3].y); - } - } - if(tptr->flags & LASTY) { - *tptr->cptr[2] = rend_pixel(tptr->cpos[2].x, tptr->cpos[2].y); - } - tptr++; + rend_tile(tile->fbptr, tile->x, tile->y, TILESZ, 0); + tile++; } swap_buffers(0); -- 1.7.10.4 From ce7eae94dd17b0c24685a19b85baacbfb1146bcf Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Wed, 11 May 2022 00:30:27 +0300 Subject: [PATCH 03/16] rt: subsampling seems to work --- src/scr/raytrace.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/scr/raytrace.c b/src/scr/raytrace.c index 32ade1f..7b0314d 100644 --- a/src/scr/raytrace.c +++ b/src/scr/raytrace.c @@ -119,7 +119,7 @@ static void rend_tile(uint16_t *fbptr, int x0, int y0, int tsz, unsigned int val if(tsz <= 1) { if(!valid) { - *fbptr = rend_pixel(x0, y0); + *fbptr = 0xffff;//rend_pixel(x0, y0); } return; } @@ -150,20 +150,36 @@ static void rend_tile(uint16_t *fbptr, int x0, int y0, int tsz, unsigned int val fb32 = (uint32_t*)fbptr; switch(tsz) { + case 2: +#ifdef SUBDBG + pp0 = 0x18ff; +#endif + fb32[0] = fb32[160] = pp0; + break; case 4: +#ifdef SUBDBG + pp0 = pp1 = pp2 = pp3 = 0x03800380; +#endif + fb32[0] = fb32[160] = pp0; fb32[1] = fb32[161] = pp1; fb32[320] = fb32[480] = pp2; fb32[321] = fb32[481] = pp3; - case 2: - fb32[0] = fb32[160] = pp0; break; case 8: +#ifdef SUBDBG + pp1 = pp0 = pp2 = pp3 = 0xe00fe00f; +#endif fb32[0] = fb32[1] = pp0; fb32[2] = fb32[3] = pp1; fb32[160] = fb32[161] = pp0; fb32[162] = fb32[163] = pp1; - fb32[320] = fb32[321] = pp2; fb32[322] = fb32[323] = pp3; - fb32[480] = fb32[481] = pp2; fb32[482] = fb32[483] = pp3; + fb32[320] = fb32[321] = pp0; fb32[322] = fb32[323] = pp1; + fb32[480] = fb32[481] = pp0; fb32[482] = fb32[483] = pp1; + fb32[640] = fb32[641] = pp2; fb32[642] = fb32[643] = pp3; + fb32[800] = fb32[801] = pp2; fb32[802] = fb32[803] = pp3; + fb32[960] = fb32[961] = pp2; fb32[962] = fb32[963] = pp3; + fb32[1120] = fb32[1121] = pp2; fb32[1122] = fb32[1123] = pp3; break; } + return; subdiv: *cptr[0] = cpix[0]; @@ -177,7 +193,7 @@ subdiv: fbptr += (tsz << 8) + (tsz << 6); y0 += tsz; rend_tile(fbptr, x0, y0, tsz, 4); - rend_tile(fbptr, x0 + tsz, y0, tsz, 8); + rend_tile(fbptr + tsz, x0 + tsz, y0, tsz, 8); } static void draw(void) -- 1.7.10.4 From d591d56c7214fe25f93bc7a439c37b47fc5e5aea Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Wed, 11 May 2022 02:36:46 +0300 Subject: [PATCH 04/16] uninitialized variable in logger --- src/dos/logger.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dos/logger.c b/src/dos/logger.c index 2d61070..1976770 100644 --- a/src/dos/logger.c +++ b/src/dos/logger.c @@ -49,6 +49,7 @@ int print_tail(const char *fname) if(!(fp = fopen(fname, "r"))) { return -1; } + wr = rd = 0; lineoffs[wr++] = 0; while(fgets(buf, sizeof buf, fp)) { lineoffs[wr] = ftell(fp); -- 1.7.10.4 From 23c14b0ba8bac4d39824ae1d848be3058e9f9073 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Wed, 11 May 2022 04:02:23 +0300 Subject: [PATCH 05/16] raytrace improvements and random DOS fixes --- pull.bat | 22 +++++++++---------- src/3dgfx/polytmpl.h | 9 ++++---- src/scr/raytrace.c | 59 ++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 59 insertions(+), 31 deletions(-) diff --git a/pull.bat b/pull.bat index e3e1236..5064b7f 100644 --- a/pull.bat +++ b/pull.bat @@ -1,11 +1,11 @@ -rsync -uv 192.168.0.4::dosdemo/Makefile Makefile -rsync -uv 192.168.0.4::dosdemo/src/*.c src -rsync -uv 192.168.0.4::dosdemo/src/*.h src -rsync -uv 192.168.0.4::dosdemo/src/*.asm src -rsync -uv 192.168.0.4::dosdemo/src/dos/*.c src/dos -rsync -uv 192.168.0.4::dosdemo/src/dos/*.h src/dos -rsync -uv 192.168.0.4::dosdemo/src/dos/*.asm src/dos -rsync -uv 192.168.0.4::dosdemo/src/scr/*.c src/scr -rsync -uv 192.168.0.4::dosdemo/src/scr/*.h src/scr -rsync -uv 192.168.0.4::dosdemo/src/3dgfx/*.c src/3dgfx -rsync -uv 192.168.0.4::dosdemo/src/3dgfx/*.h src/3dgfx +rsync -v 192.168.0.4::dosdemo/Makefile Makefile +rsync -v 192.168.0.4::dosdemo/src/*.c src +rsync -v 192.168.0.4::dosdemo/src/*.h src +rsync -v 192.168.0.4::dosdemo/src/*.asm src +rsync -v 192.168.0.4::dosdemo/src/dos/*.c src/dos +rsync -v 192.168.0.4::dosdemo/src/dos/*.h src/dos +rsync -v 192.168.0.4::dosdemo/src/dos/*.asm src/dos +rsync -v 192.168.0.4::dosdemo/src/scr/*.c src/scr +rsync -v 192.168.0.4::dosdemo/src/scr/*.h src/scr +rsync -v 192.168.0.4::dosdemo/src/3dgfx/*.c src/3dgfx +rsync -v 192.168.0.4::dosdemo/src/3dgfx/*.h src/3dgfx diff --git a/src/3dgfx/polytmpl.h b/src/3dgfx/polytmpl.h index 62692fa..f601623 100644 --- a/src/3dgfx/polytmpl.h +++ b/src/3dgfx/polytmpl.h @@ -102,10 +102,6 @@ void POLYFILL(struct pvertex *pv, int nverts) int mid; int32_t dx, tmp; #endif -#if !defined(GOURAUD) && !defined(TEXMAP) - /* flat version, just pack the color now */ - color = G3D_PACK_RGB(pv[0].r, pv[0].g, pv[0].b); -#endif #ifdef GOURAUD int32_t r, g, b, dr, dg, db, rslope, gslope, bslope; #ifdef BLEND_ALPHA @@ -119,6 +115,11 @@ void POLYFILL(struct pvertex *pv, int nverts) int32_t z, dz, zslope; #endif +#if !defined(GOURAUD) && !defined(TEXMAP) + /* flat version, just pack the color now */ + color = G3D_PACK_RGB(pv[0].r, pv[0].g, pv[0].b); +#endif + for(i=1; i pv[botidx].y) botidx = i; diff --git a/src/scr/raytrace.c b/src/scr/raytrace.c index 7b0314d..1593d9f 100644 --- a/src/scr/raytrace.c +++ b/src/scr/raytrace.c @@ -26,7 +26,7 @@ struct tile { uint16_t *fbptr; }; -#define TILESZ 8 +#define TILESZ 16 #define NUM_TILES ((320 / TILESZ) * (240 / TILESZ)) static cgm_vec3 raydir[240][320]; @@ -110,16 +110,32 @@ static uint16_t INLINE rend_pixel(int x, int y) } #define CMPMASK 0xe79c -static void rend_tile(uint16_t *fbptr, int x0, int y0, int tsz, unsigned int valid) +static void rend_tile(uint16_t *fbptr, int x0, int y0, int tsz, int valid) { uint16_t *cptr[4]; uint16_t cpix[4], tmp; uint32_t pp0, pp1, pp2, pp3, *fb32; - int x1, y1, offs; + int i, x1, y1, offs; - if(tsz <= 1) { - if(!valid) { - *fbptr = 0xffff;//rend_pixel(x0, y0); + fb32 = (uint32_t*)fbptr; + + if(tsz <= 2) { + switch(valid) { + case 0: + fbptr[1] = fbptr[320] = fbptr[321] = *fbptr; + break; + case 1: + fbptr[0] = fbptr[320] = fbptr[321] = fbptr[1]; + break; + case 2: + fbptr[0] = fbptr[1] = fbptr[321] = fbptr[320]; + break; + case 3: + fbptr[0] = fbptr[1] = fbptr[320] = fbptr[321]; + break; + default: + printf("valid = %d\n", valid); + fbptr[0] = fbptr[1] = fbptr[320] = fbptr[321] = 0xff00; } return; } @@ -133,10 +149,10 @@ static void rend_tile(uint16_t *fbptr, int x0, int y0, int tsz, unsigned int val cptr[2] = fbptr + (offs << 8) + (offs << 6); cptr[3] = cptr[2] + tsz - 1; - cpix[0] = valid & 1 ? *cptr[0] : rend_pixel(x0, y0); - cpix[1] = valid & 2 ? *cptr[1] : rend_pixel(x1, y0); - cpix[2] = valid & 4 ? *cptr[2] : rend_pixel(x0, y1); - cpix[3] = valid & 8 ? *cptr[3] : rend_pixel(x1, y1); + cpix[0] = valid == 0 ? *cptr[0] : rend_pixel(x0, y0); + cpix[1] = valid == 1 ? *cptr[1] : rend_pixel(x1, y0); + cpix[2] = valid == 2 ? *cptr[2] : rend_pixel(x0, y1); + cpix[3] = valid == 3 ? *cptr[3] : rend_pixel(x1, y1); tmp = cpix[0] & CMPMASK; if((cpix[1] & CMPMASK) != tmp) goto subdiv; @@ -147,7 +163,6 @@ static void rend_tile(uint16_t *fbptr, int x0, int y0, int tsz, unsigned int val pp1 = cpix[1] | ((uint32_t)cpix[1] << 16); pp2 = cpix[2] | ((uint32_t)cpix[2] << 16); pp3 = cpix[3] | ((uint32_t)cpix[3] << 16); - fb32 = (uint32_t*)fbptr; switch(tsz) { case 2: @@ -178,6 +193,18 @@ static void rend_tile(uint16_t *fbptr, int x0, int y0, int tsz, unsigned int val fb32[960] = fb32[961] = pp2; fb32[962] = fb32[963] = pp3; fb32[1120] = fb32[1121] = pp2; fb32[1122] = fb32[1123] = pp3; break; + + case 16: +#ifdef SUBDBG + pp0 = 0xff00ff00; +#endif + for(i=0; i<4; i++) { + memset16(fbptr, pp0, 16); fbptr += 320; + memset16(fbptr, pp0, 16); fbptr += 320; + memset16(fbptr, pp0, 16); fbptr += 320; + memset16(fbptr, pp0, 16); fbptr += 320; + } + break; } return; @@ -188,12 +215,12 @@ subdiv: *cptr[3] = cpix[3]; tsz >>= 1; - rend_tile(fbptr, x0, y0, tsz, 1); - rend_tile(fbptr + tsz, x0 + tsz, y0, tsz, 2); + rend_tile(fbptr, x0, y0, tsz, 0); + rend_tile(fbptr + tsz, x0 + tsz, y0, tsz, 1); fbptr += (tsz << 8) + (tsz << 6); y0 += tsz; - rend_tile(fbptr, x0, y0, tsz, 4); - rend_tile(fbptr + tsz, x0 + tsz, y0, tsz, 8); + rend_tile(fbptr, x0, y0, tsz, 2); + rend_tile(fbptr + tsz, x0 + tsz, y0, tsz, 3); } static void draw(void) @@ -204,7 +231,7 @@ static void draw(void) tile = tiles; for(i=0; ifbptr, tile->x, tile->y, TILESZ, 0); + rend_tile(tile->fbptr, tile->x, tile->y, TILESZ, -1); tile++; } -- 1.7.10.4 From 0d1e0d22e3f1bc97dd6523b78602d886009e2145 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Wed, 11 May 2022 04:05:52 +0300 Subject: [PATCH 06/16] update pull.bat --- pull.bat | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pull.bat b/pull.bat index 5064b7f..c6e7689 100644 --- a/pull.bat +++ b/pull.bat @@ -5,7 +5,18 @@ rsync -v 192.168.0.4::dosdemo/src/*.asm src rsync -v 192.168.0.4::dosdemo/src/dos/*.c src/dos rsync -v 192.168.0.4::dosdemo/src/dos/*.h src/dos rsync -v 192.168.0.4::dosdemo/src/dos/*.asm src/dos +rsync -v 192.168.0.4::glutdemo/src/glut/*.c src/glut +rsync -v 192.168.0.4::glutdemo/src/glut/*.h src/glut +rsync -v 192.168.0.4::sdldemo/src/sdl/*.c src/sdl +rsync -v 192.168.0.4::sdldemo/src/sdl/*.h src/sdl rsync -v 192.168.0.4::dosdemo/src/scr/*.c src/scr rsync -v 192.168.0.4::dosdemo/src/scr/*.h src/scr rsync -v 192.168.0.4::dosdemo/src/3dgfx/*.c src/3dgfx rsync -v 192.168.0.4::dosdemo/src/3dgfx/*.h src/3dgfx + +rsync -v 192.168.0.4::dosdemo/tools/csprite/Makefile tools/csprite/Makefile +rsync -v 192.168.0.4::dosdemo/tools/csprite/src/*.c tools/csprite/src +rsync -v 192.168.0.4::dosdemo/tools/csprite/src/*.h tools/csprite/src + +rsync -v 192.168.0.4::dosdemo/tools/img2bin/Makefile tools/img2bin/Makefile +rsync -v 192.168.0.4::dosdemo/tools/img2bin/*.c tools/img2bin -- 1.7.10.4 From 2eb6ea48991f9e5462c0a83b50006e5b58f935a0 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Wed, 11 May 2022 04:14:05 +0300 Subject: [PATCH 07/16] fix pull.bat --- pull.bat | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/pull.bat b/pull.bat index c6e7689..a099a39 100644 --- a/pull.bat +++ b/pull.bat @@ -1,22 +1,30 @@ +mkdir src rsync -v 192.168.0.4::dosdemo/Makefile Makefile rsync -v 192.168.0.4::dosdemo/src/*.c src rsync -v 192.168.0.4::dosdemo/src/*.h src rsync -v 192.168.0.4::dosdemo/src/*.asm src +mkdir src\dos rsync -v 192.168.0.4::dosdemo/src/dos/*.c src/dos rsync -v 192.168.0.4::dosdemo/src/dos/*.h src/dos rsync -v 192.168.0.4::dosdemo/src/dos/*.asm src/dos -rsync -v 192.168.0.4::glutdemo/src/glut/*.c src/glut -rsync -v 192.168.0.4::glutdemo/src/glut/*.h src/glut -rsync -v 192.168.0.4::sdldemo/src/sdl/*.c src/sdl -rsync -v 192.168.0.4::sdldemo/src/sdl/*.h src/sdl +mkdir src\glut +rsync -v 192.168.0.4::dosdemo/src/glut/*.c src/glut +rsync -v 192.168.0.4::dosdemo/src/glut/*.h src/glut +mkdir src\sdl +rsync -v 192.168.0.4::dosdemo/src/sdl/*.c src/sdl +mkdir src\scr rsync -v 192.168.0.4::dosdemo/src/scr/*.c src/scr rsync -v 192.168.0.4::dosdemo/src/scr/*.h src/scr +mkdir src\3dgfx rsync -v 192.168.0.4::dosdemo/src/3dgfx/*.c src/3dgfx rsync -v 192.168.0.4::dosdemo/src/3dgfx/*.h src/3dgfx +mkdir tools +mkdir tools\csprite rsync -v 192.168.0.4::dosdemo/tools/csprite/Makefile tools/csprite/Makefile rsync -v 192.168.0.4::dosdemo/tools/csprite/src/*.c tools/csprite/src rsync -v 192.168.0.4::dosdemo/tools/csprite/src/*.h tools/csprite/src +mkdir tools\img2bin rsync -v 192.168.0.4::dosdemo/tools/img2bin/Makefile tools/img2bin/Makefile rsync -v 192.168.0.4::dosdemo/tools/img2bin/*.c tools/img2bin -- 1.7.10.4 From 2b20eeb790d6574518facaae579bfd8e6d5620d4 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Wed, 11 May 2022 04:27:57 +0300 Subject: [PATCH 08/16] glut backend: don't attempt to init sound if opt.music is false --- src/glut/audio.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/glut/audio.c b/src/glut/audio.c index a7ea50c..6a7b96c 100644 --- a/src/glut/audio.c +++ b/src/glut/audio.c @@ -9,6 +9,7 @@ #endif #include "mikmod.h" #include "audio.h" +#include "cfgopt.h" #ifdef _WIN32 #include @@ -37,6 +38,8 @@ int au_init(void) curmod = 0; vol_master = vol_mus = vol_sfx = 255; + if(!opt.music) return 0; + #if defined(__linux__) MikMod_RegisterDriver(&drv_alsa); #elif defined(__FreeBSD__) @@ -78,8 +81,10 @@ int au_init(void) void au_shutdown(void) { - curmod = 0; - MikMod_Exit(); + if(opt.music) { + curmod = 0; + MikMod_Exit(); + } } struct au_module *au_load_module(const char *fname) -- 1.7.10.4 From e5413255949140efda5ab0b1e27ec2363fcee542 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Wed, 11 May 2022 06:17:13 +0300 Subject: [PATCH 09/16] fixed djgpp version of memset16, missing input clobbers --- src/util.h | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/util.h b/src/util.h index f93efc8..ec87a4d 100644 --- a/src/util.h +++ b/src/util.h @@ -111,21 +111,26 @@ void halt(void); #ifdef __GNUC__ #if defined(__i386__) || defined(__x86_64__) -#define memset16(dest, val, count) asm volatile ( \ - "cld\n\t" \ - "test $1, %2\n\t" \ - "jz 0f\n\t" \ - "rep stosw\n\t" \ - "jmp 1f\n\t" \ - "0:\n\t" \ - "shr $1, %2\n\t" \ - "push %%ax\n\t" \ - "shl $16, %%eax\n\t" \ - "pop %%ax\n\t" \ - "rep stosl\n\t" \ - "1:\n\t"\ - :: "D"(dest), "a"((uint16_t)(val)), "c"(count) \ - : "memory") +#define memset16(dest, val, count) \ + do { \ + uint32_t dummy1, dummy2; \ + asm volatile ( \ + "cld\n\t" \ + "test $1, %%ecx\n\t" \ + "jz 0f\n\t" \ + "rep stosw\n\t" \ + "jmp 1f\n\t" \ + "0:\n\t" \ + "shr $1, %%ecx\n\t" \ + "push %%ax\n\t" \ + "shl $16, %%eax\n\t" \ + "pop %%ax\n\t" \ + "rep stosl\n\t" \ + "1:\n\t"\ + : "=D"(dummy1), "=c"(dummy2) \ + : "0"(dest), "a"((uint16_t)(val)), "1"(count) \ + : "flags", "memory"); \ + } while(0) #else static void INLINE memset16(void *dest, uint16_t val, int count) { -- 1.7.10.4 From f06babe97875e6023dad1843c1f0c56639967656 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Sun, 15 May 2022 06:18:53 +0300 Subject: [PATCH 10/16] added PCI code in anticipation of porting the S3 driver --- Makefile | 6 +- src/dos/cdpmi.h | 11 ++ src/dos/dosutil.h | 2 + src/dos/main.c | 4 + src/dos/pci.c | 421 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/dos/pci.h | 53 +++++++ 6 files changed, 495 insertions(+), 2 deletions(-) create mode 100644 src/dos/pci.c create mode 100644 src/dos/pci.h diff --git a/Makefile b/Makefile index c1a8cad..c862ea9 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,8 @@ !ifdef __UNIX__ dosobj = src/dos/audos.obj src/dos/djdpmi.obj src/dos/gfx.obj src/dos/keyb.obj & src/dos/logger.obj src/dos/main.obj src/dos/sball.obj src/dos/timer.obj & - src/dos/vbe.obj src/dos/vga.obj src/dos/watdpmi.obj src/dos/mouse.obj + src/dos/vbe.obj src/dos/vga.obj src/dos/watdpmi.obj src/dos/mouse.obj & + src/dos/pci.obj 3dobj = src/3dgfx/3dgfx.obj src/3dgfx/mesh.obj src/3dgfx/meshload.obj & src/3dgfx/polyclip.obj src/3dgfx/polyfill.obj srcobj = src/bsptree.obj src/cfgopt.obj src/console.obj src/demo.obj & @@ -23,7 +24,8 @@ libpath = libpath libs/imago libpath libs/anim libpath libs/midas dosobj = src\dos\audos.obj src\dos\djdpmi.obj src\dos\gfx.obj src\dos\keyb.obj & src\dos\logger.obj src\dos\main.obj src\dos\sball.obj src\dos\timer.obj & - src\dos\vbe.obj src\dos\vga.obj src\dos\watdpmi.obj src\dos\mouse.obj + src\dos\vbe.obj src\dos\vga.obj src\dos\watdpmi.obj src\dos\mouse.obj & + src\dos\pci.obj 3dobj = src\3dgfx\3dgfx.obj src\3dgfx\mesh.obj src\3dgfx\meshload.obj & src\3dgfx\polyclip.obj src\3dgfx\polyfill.obj srcobj = src\bsptree.obj src\cfgopt.obj src\console.obj src\demo.obj & diff --git a/src/dos/cdpmi.h b/src/dos/cdpmi.h index 71138b6..e8a6950 100644 --- a/src/dos/cdpmi.h +++ b/src/dos/cdpmi.h @@ -29,6 +29,17 @@ struct dpmi_regs { } PACKED; #pragma pack (pop) +enum { + FLAGS_CF = 0x000001, + FLAGS_PF = 0x000004, + FLAGS_ZF = 0x000040, + FLAGS_SF = 0x000080, + FLAGS_IF = 0x000020, + FLAGS_DF = 0x000040, + FLAGS_VM = 0x020000, + FLAGS_ID = 0x200000, +}; + uint16_t dpmi_alloc(unsigned int par, uint16_t *sel); void dpmi_free(uint16_t sel); void dpmi_int(int inum, struct dpmi_regs *regs); diff --git a/src/dos/dosutil.h b/src/dos/dosutil.h index 9894251..71af365 100644 --- a/src/dos/dosutil.h +++ b/src/dos/dosutil.h @@ -9,9 +9,11 @@ #define outp(p, v) outportb(p, v) #define outpw(p, v) outportw(p, v) +#define outpd(p, v) outportd(p, v) #define inp(p) inportb(p) #define inpw(p) inportw(p) +#define inpd(p) inportd(p) #endif #endif /* DOSUTIL_H_ */ diff --git a/src/dos/main.c b/src/dos/main.c index ee28dc9..7f67e85 100644 --- a/src/dos/main.c +++ b/src/dos/main.c @@ -62,6 +62,10 @@ int main(int argc, char **argv) init_timer(100); kb_init(32); + if(init_pci() != -1) { + /* TODO detect and initialize S3 virge */ + } + if(init_video() == -1) { return 1; } diff --git a/src/dos/pci.c b/src/dos/pci.c new file mode 100644 index 0000000..d3a1e7d --- /dev/null +++ b/src/dos/pci.c @@ -0,0 +1,421 @@ +/* +S3 Virge driver hack +Copyright (C) 2021 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#include +#include +#include +#include +#include +#include "inttypes.h" +#include "pci.h" +#include "cdpmi.h" + +#define CONFIG_ADDR_PORT 0xcf8 +#define CONFIG_DATA_PORT 0xcfc + +#define ADDR_ENABLE 0x80000000 +#define ADDR_BUSID(x) (((uint32_t)(x) & 0xff) << 16) +#define ADDR_DEVID(x) (((uint32_t)(x) & 0x1f) << 11) +#define ADDR_FUNC(x) (((uint32_t)(x) & 3) << 8) + +/* signature returned in edx by the PCI BIOS present function: FOURCC "PCI " */ +#define PCI_SIG 0x20494350 + +#define TYPE_MULTIFUNC 0x80 + + +static struct pci_device *pcidev; +static int num_pcidevs, max_pcidevs; + + +static int enum_bus(int busid); +static int enum_dev(int busid, int dev); +static int read_dev_info(struct pci_config_data *res, int bus, int dev, int func); +static void print_dev_info(struct pci_config_data *info, int bus, int dev, int func); + +static uint32_t cfg_read32_m1(int bus, int dev, int func, int reg); +static uint32_t cfg_read32_m2(int bus, int dev, int func, int reg); +static const char *class_str(int cc); +static const char *subclass_str(int cc, int sub); + +static uint32_t (*cfg_read32)(int, int, int, int); + +static void clear_devices(void); +static void add_device(struct pci_device *dev); + +int init_pci(void) +{ + int i, count = 0; + struct dpmi_regs regs = {0}; + + clear_devices(); + + regs.eax = 0xb101; + dpmi_int(0x1a, ®s); + + /* PCI BIOS present if CF=0, AH=0, and EDX has the "PCI " sig FOURCC */ + if((regs.flags & FLAGS_CF) || (regs.eax & 0xff00) || regs.edx != PCI_SIG) { + fprintf(stderr, "No PCI BIOS present\n"); + return -1; + } + + printf("PCI BIOS v%x.%x found\n", (regs.ebx & 0xff00) >> 8, regs.ebx & 0xff); + if(regs.eax & 1) { + cfg_read32 = cfg_read32_m1; + } else { + if(!(regs.eax & 2)) { + fprintf(stderr, "Failed to find supported PCI mess mechanism\n"); + return -1; + } + printf("PCI mess mechanism #1 unsupported, falling back to mechanism #2\n"); + cfg_read32 = cfg_read32_m2; + } + + for(i=0; i<256; i++) { + count += enum_bus(i); + } + printf("found %d PCI devices\n\n", count); + return 0; +} + +static int enum_bus(int busid) +{ + int i, count = 0; + + for(i=0; i<32; i++) { + count += enum_dev(busid, i); + } + + return count; +} + +static int enum_dev(int busid, int devid) +{ + int i, count; + struct pci_device dev; + + dev.bus = busid; + dev.dev = devid; + dev.func = 0; + + /* vendor id ffff is invalid */ + if((cfg_read32(busid, devid, 0, 0) & 0xffff) == 0xffff) { + return 0; + } + if(read_dev_info(&dev.cfg, busid, devid, 0) == -1) { + return 0; + } + print_dev_info(&dev.cfg, busid, devid, 0); + add_device(&dev); + + count = 1; + + if(dev.cfg.hdr_type & TYPE_MULTIFUNC) { + for(i=1; i<8; i++) { + if(read_dev_info(&dev.cfg, busid, devid, i) == -1) { + continue; + } + print_dev_info(&dev.cfg, busid, devid, i); + dev.func = i; + add_device(&dev); + count++; + } + } + return count; +} + +static int read_dev_info(struct pci_config_data *res, int bus, int dev, int func) +{ + int i; + uint32_t *ptr = (uint32_t*)res; + + *ptr++ = cfg_read32(bus, dev, func, 0); + if(res->vendor == 0xffff) { + return -1; + } + + for(i=1; i<16; i++) { + *ptr++ = cfg_read32(bus, dev, func, i * 4); + } + return 0; +} + +static void print_dev_info(struct pci_config_data *info, int bus, int dev, int func) +{ + printf("- (%d:%d,%d) Device %04x:%04x: ", bus, dev, func, info->vendor, info->device); + printf("\"%s\" (%d) - %s-func\n", class_str(info->class), info->class, + info->hdr_type & TYPE_MULTIFUNC ? "multi" : "single"); + printf(" subclass: \"%s\" (%d), iface: %d\n", subclass_str(info->class, info->subclass), + info->subclass, info->iface); +} + +static uint32_t cfg_read32_m1(int bus, int dev, int func, int reg) +{ + uint32_t addr = ADDR_ENABLE | ADDR_BUSID(bus) | ADDR_DEVID(dev) | + ADDR_FUNC(func) | reg; + + outpd(CONFIG_ADDR_PORT, addr); + return inpd(CONFIG_DATA_PORT); +} + +static uint32_t cfg_read32_m2(int bus, int dev, int func, int reg) +{ + fprintf(stderr, "BUG: PCI mess mechanism #2 not implemented yet!"); + demo_abort(); + return 0; +} + +static const char *class_names[] = { + "unknown", + "mass storage controller", + "network controller", + "display controller", + "multimedia device", + "memory controller", + "bridge device", + "simple communication controller", + "base system peripheral", + "input device", + "docking station", + "processor", + "serial bus controller", + "wireless controller", + "intelligent I/O controller", + "satellite communication controller", + "encryption/decryption controller", + "data acquisition & signal processing controller" +}; + +static const char *class_mass_names[] = { + "SCSI bus controller", + "IDE controller", + "floppy disk controller", + "IPI bus controller", + "RAID controller" +}; + +static const char *class_net_names[] = { + "ethernet controller", + "token ring controller", + "FDDI controller", + "ATM controller", + "ISDN controller" +}; + +static const char *class_disp_names[] = { + "VGA-compatible controller", + "XGA controller", + "3D controller" +}; + +static const char *class_mm_names[] = { + "video device", + "audio device", + "telephony device" +}; + +static const char *class_bridge_names[] = { + "host bridge", + "ISA bridge", + "EISA bridge", + "MCA bridge", + "PCI-to-PCI bridge", + "Subtractive decode PCI-to-PCI bridge", + "PCMCIA bridge", + "NuBus bridge", + "CardBus bridge", + "RACEway bridge" +}; + +static const char *class_comm_names[] = { + "serial controller", + "parallel/IEEE1284", + "multiport serial controller", + "modem" +}; + +static const char *class_base_names[] = { + "interrupt controller", + "DMA controller", + "timer", + "RTC", + "PCI hot-plug controller" +}; + +static const char *class_input_names[] = { + "keyboard controller", + "digitizer", + "mouse controller", + "scanner controller", + "gameport controller" +}; + +static const char *class_ser_names[] = { + "firewire", + "ACCESS.bus", + "SSA", + "USB", + "Fibre Channel", + "SMBus" +}; + +static const char *class_sat_names[] = { + "TV", + "audio", + "voice", + "data" +}; + + +static const char *class_str(int cc) +{ + if(cc == 0xff) { + return "other"; + } + if(cc >= 0x12) { + return "unknown"; + } + return class_names[cc]; +} + +static const char *subclass_str(int cc, int sub) +{ + if(sub == 0x80) return "other"; + + switch(cc) { + case 0: + if(sub == 1) return "VGA-compatible device"; + return "unknown"; + + case 1: + if(sub > 4) return "unknown"; + return class_mass_names[sub]; + + case 2: + if(sub > 4) return "unknown"; + return class_net_names[sub]; + + case 3: + if(sub > 2) return "unknown"; + return class_disp_names[sub]; + + case 4: + if(sub > 2) return "unknown"; + return class_mm_names[sub]; + + case 5: + if(sub == 0) return "RAM"; + if(sub == 1) return "flash"; + return "unknown"; + + case 6: + if(sub > 8) return "unknown"; + return class_bridge_names[sub]; + + case 7: + if(sub > 3) return "unknown"; + return class_comm_names[sub]; + + case 8: + if(sub > 4) return "unknown"; + return class_base_names[sub]; + + case 9: + if(sub > 4) return "unknown"; + return class_input_names[sub]; + + case 10: + if(sub == 0) return "generic docking station"; + return "unknown"; + + case 11: + switch(sub) { + case 0: return "386"; + case 1: return "486"; + case 2: return "pentium"; + case 0x10: return "alpha"; + case 0x20: return "powerpc"; + case 0x30: return "mips"; + case 0x40: return "co-processor"; + default: + break; + } + return "unknown"; + + case 12: + if(sub > 5) return "unknown"; + return class_ser_names[sub]; + + case 13: + if(sub == 0) return "irda controller"; + if(sub == 1) return "IR controller"; + if(sub == 0x10) return "RF controller"; + return "unknonw"; + + case 15: + if(sub > 4) return "unknown"; + return class_sat_names[sub]; + + case 16: + if(sub == 0) return "network & computing crypto"; + if(sub == 1) return "entertainment crypto"; + return "unknown"; + + case 17: + if(sub == 0) return "DPIO module"; + return "unknown"; + + default: + break; + } + return "unknown"; +} + +static void clear_devices(void) +{ + free(pcidev); + pcidev = 0; + num_pcidevs = max_pcidevs = 0; +} + +static void add_device(struct pci_device *dev) +{ + if(num_pcidevs >= max_pcidevs) { + void *newarr; + int newsz = max_pcidevs ? max_pcidevs << 1 : 8; + + if(!(newarr = realloc(pcidev, newsz * sizeof *pcidev))) { + fprintf(stderr, "failed to resize PCI device array (%d)\n", newsz); + return; + } + pcidev = newarr; + max_pcidevs = newsz; + } + + pcidev[num_pcidevs++] = *dev; +} + +struct pci_device *find_pci_dev(uint16_t vendorid, uint16_t devid) +{ + int i; + for(i=0; i + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#ifndef PCI_H_ +#define PCI_H_ + +#include "inttypes.h" +#include "util.h" + +#pragma pack (push, 1) +struct pci_config_data { + uint16_t vendor, device; + uint16_t cmd, status; + uint8_t rev, iface, subclass, class; + uint8_t cacheline_size; + uint8_t latency_timer; + uint8_t hdr_type; + uint8_t bist; + uint32_t base_addr[6]; + uint32_t cardbus_cis; + uint16_t subsys_vendor; + uint16_t subsys; + uint32_t rom_addr; + uint32_t reserved1, reserved2; + uint8_t intr_line, intr_pin; + uint8_t min_grant, max_latency; +} PACKED; +#pragma pop (push) + +struct pci_device { + int bus, dev, func; + struct pci_config_data cfg; +}; + +int init_pci(void); + +struct pci_device *find_pci_dev(uint16_t vendorid, uint16_t devid); + +#endif /* PCI_H_ */ -- 1.7.10.4 From 0d60e0e144c0faf5efb9551d1d23b7463ce8a4c0 Mon Sep 17 00:00:00 2001 From: Michael Georgoulopoulos Date: Sun, 15 May 2022 21:26:50 +0300 Subject: [PATCH 11/16] Moved RleBitmap to its own module and created minifx screen to experiment --- .clang-format | 3 + GNUmakefile | 4 +- src/minifx.c | 161 +++++++++++++++++++ src/scr/grise.c | 423 +++++++------------------------------------------ src/screen.c | 5 + src/utils/RleBitmap.c | 309 ++++++++++++++++++++++++++++++++++++ src/utils/RleBitmap.h | 66 ++++++++ 7 files changed, 607 insertions(+), 364 deletions(-) create mode 100644 .clang-format create mode 100644 src/minifx.c create mode 100644 src/utils/RleBitmap.c create mode 100644 src/utils/RleBitmap.h diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..c2b7d66 --- /dev/null +++ b/.clang-format @@ -0,0 +1,3 @@ +UseTab: Always +IndentWidth: 8 +ColumnLimit: 100 diff --git a/GNUmakefile b/GNUmakefile index 3608ddf..ea8082c 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,4 +1,4 @@ -src = $(wildcard src/*.c) $(wildcard src/3dgfx/*.c) $(wildcard src/scr/*.c) \ +src = $(wildcard src/*.c) $(wildcard src/3dgfx/*.c) $(wildcard src/scr/*.c) $(wildcard src/utils/*.c) \ $(wildcard src/glut/*.c) asmsrc = $(wildcard src/*.asm) obj = $(src:.c=.o) $(asmsrc:.asm=.o) @@ -8,7 +8,7 @@ bin = demo asmsrc += cspr/dbgfont.asm cspr/confont.asm bindata = data/loading.img -inc = -I/usr/local/include -Isrc -Isrc/3dgfx -Isrc/scr -Isrc/glut -Ilibs \ +inc = -I/usr/local/include -Isrc -Isrc/3dgfx -Isrc/scr -Isrc/utils -Isrc/glut -Ilibs \ -Ilibs/imago/src -Ilibs/mikmod/include def = -DMINIGLUT_USE_LIBC -DMIKMOD_STATIC warn = -pedantic -Wall -Wno-unused-variable -Wno-unused-function -Wno-address diff --git a/src/minifx.c b/src/minifx.c new file mode 100644 index 0000000..59a3269 --- /dev/null +++ b/src/minifx.c @@ -0,0 +1,161 @@ +#include "demo.h" +#include "imago2.h" +#include "screen.h" +#include +#include +#include +#include +#include + +#include + +/* APPROX. 170 FPS Minimum */ + +static int init(void); +static void destroy(void); +static void start(long trans_time); +static void stop(long trans_time); +static void draw(void); + +static void updatePropeller(float t, RleBitmap *rle); + +static unsigned short *backBuffer; + +static unsigned char miniFXBuffer[1024]; + +static long lastFrameTime = 0; + +static struct screen scr = {"minifx", init, destroy, start, 0, draw}; + +struct screen *minifx_screen(void) { + return &scr; +} + +static int init(void) { + /* Allocate back buffer */ + backBuffer = (unsigned short *)calloc(FB_WIDTH * FB_HEIGHT, sizeof(unsigned short)); + + return 0; +} + +static void destroy(void) { + free(backBuffer); + backBuffer = 0; +} + +static void start(long trans_time) { lastFrameTime = time_msec; } + +static void draw(void) { + long lastFrameDuration = (time_msec - lastFrameTime) / 1000.0f; + lastFrameTime = time_msec; + + int clearColor = 0x888888; + unsigned short clearColor16 = ((clearColor << 8) & 0xF800) /* R */ + | ((clearColor >> 5) & 0x07E0) /* G */ + | ((clearColor >> 19) & 0x001F); /* B */ + for (int i=0; i= 2; + } + } + + /* Then, encode to rle */ + rleEncode(rle, miniFXBuffer, 32, 32); + + /* Distribute the produced streaks so that they don't produce garbage when interpolated */ + rleDistributeStreaks(rle); +} diff --git a/src/scr/grise.c b/src/scr/grise.c index 1295a07..36e9ff9 100644 --- a/src/scr/grise.c +++ b/src/scr/grise.c @@ -1,35 +1,22 @@ +#include "demo.h" +#include "imago2.h" +#include "screen.h" +#include +#include #include #include #include -#include -#include -#include "imago2.h" -#include "demo.h" -#include "screen.h" -/* APPROX. 170 FPS Minimum */ +#include -typedef struct { - unsigned int w, h; - unsigned char *scans; -} RLEBitmap; - -static RLEBitmap *rleCreate(unsigned int w, unsigned int h); -static void rleDestroy(RLEBitmap *b); -static void rleBlit(unsigned short *dst, int dstW, int dstH, int dstStride, - RLEBitmap *bitmap, int blitX, int blitY); -static void rleBlitScale(unsigned short *dst, int dstW, int dstH, int dstStride, - RLEBitmap *bitmap, int blitX, int blitY, float scaleX, float scaleY); -static void rleBlitScaleInv(unsigned short *dst, int dstW, int dstH, int dstStride, - RLEBitmap *bitmap, int blitX, int blitY, float scaleX, float scaleY); -static RLEBitmap *rleEncode(RLEBitmap *b, unsigned char *pixels, unsigned int w, unsigned int h); +/* APPROX. 170 FPS Minimum */ static void updatePropeller(float t); #define BG_FILENAME "data/grise.png" #define GROBJ_01_FILENAME "data/grobj_01.png" -#define BB_SIZE 512 /* Let's use a power of 2. Maybe we'll zoom/rotate the effect */ +#define BB_SIZE 512 /* Let's use a power of 2. Maybe we'll zoom/rotate the effect */ /* Every backBuffer scanline is guaranteed to have that many dummy pixels before and after */ #define PIXEL_PADDING 32 @@ -59,8 +46,6 @@ static void processNormal(); static void initScrollTables(); static void updateScrollTables(float dt); - - static unsigned short *background = 0; static int backgroundW = 0; static int backgroundH = 0; @@ -80,42 +65,37 @@ static float nearScrollAmount = 0.0f; static unsigned char miniFXBuffer[1024]; -static RLEBitmap *grobj = 0; -static RLEBitmap *rlePropeller = 0; +static RleBitmap *grobj = 0; +static RleBitmap *rlePropeller = 0; -static struct screen scr = { - "galaxyrise", - init, - destroy, - start, - 0, - draw -}; +static struct screen scr = {"galaxyrise", init, destroy, start, 0, draw}; -struct screen *grise_screen(void) -{ +struct screen *grise_screen(void) { return &scr; } -static int init(void) -{ +static int init(void) { unsigned char *tmpBitmap; int tmpBitmapW, tmpBitmapH; /* Allocate back buffer */ - backBuffer = (unsigned short*) calloc(BB_SIZE * BB_SIZE, sizeof(unsigned short)); + backBuffer = (unsigned short *)calloc(BB_SIZE * BB_SIZE, sizeof(unsigned short)); - /* grise.png contains the background (horizon), baked reflection and normalmap for displacement */ - if (!(background = img_load_pixels(BG_FILENAME, &backgroundW, &backgroundH, IMG_FMT_RGBA32))) { + /* grise.png contains the background (horizon), baked reflection and normalmap for + * displacement */ + if (!(background = + img_load_pixels(BG_FILENAME, &backgroundW, &backgroundH, IMG_FMT_RGBA32))) { fprintf(stderr, "failed to load image " BG_FILENAME "\n"); return -1; } /* Convert to 16bpp */ - convert32To16((unsigned int*)background, background, backgroundW * NORMALMAP_SCANLINE); /* Normalmap will keep its 32 bit color */ + convert32To16((unsigned int *)background, background, + backgroundW * NORMALMAP_SCANLINE); /* Normalmap will keep its 32 bit color */ /* Load reflected objects */ - if (!(tmpBitmap = img_load_pixels(GROBJ_01_FILENAME, &tmpBitmapW, &tmpBitmapH, IMG_FMT_GREY8))) { + if (!(tmpBitmap = + img_load_pixels(GROBJ_01_FILENAME, &tmpBitmapW, &tmpBitmapH, IMG_FMT_GREY8))) { fprintf(stderr, "failed to load image " GROBJ_01_FILENAME "\n"); return -1; } @@ -131,8 +111,7 @@ static int init(void) return 0; } -static void destroy(void) -{ +static void destroy(void) { free(backBuffer); backBuffer = 0; @@ -141,14 +120,9 @@ static void destroy(void) rleDestroy(grobj); } -static void start(long trans_time) -{ - lastFrameTime = time_msec; -} - +static void start(long trans_time) { lastFrameTime = time_msec; } -static void draw(void) -{ +static void draw(void) { int scroll = MIN_SCROLL + (MAX_SCROLL - MIN_SCROLL) * mouse_x / FB_WIDTH; unsigned short *dst = backBuffer + PIXEL_PADDING; unsigned short *src = background + scroll; @@ -188,7 +162,9 @@ static void draw(void) } /* Blit reflections first, to be displaced */ - for (i = 0; i < 5; i++) rleBlitScaleInv(backBuffer + PIXEL_PADDING, FB_WIDTH, FB_HEIGHT, BB_SIZE, rlePropeller, 134 + (i-3) * 60, 200, 1.0f, 1.8f); + for (i = 0; i < 5; i++) + rleBlitScaleInv(rlePropeller, backBuffer + PIXEL_PADDING, FB_WIDTH, FB_HEIGHT, + BB_SIZE, 134 + (i - 3) * 60, 200, 1.0f, 1.8f); /* Perform displacement */ dst = backBuffer + HORIZON_HEIGHT * BB_SIZE + PIXEL_PADDING; @@ -202,9 +178,11 @@ static void draw(void) for (i = 0; i < FB_WIDTH; i++) { /* Try to immitate modulo without the division */ - if (i == md) accum += md; + if (i == md) + accum += md; scrolledIndex = i - accum + sc; - if (scrolledIndex >= md) scrolledIndex -= md; + if (scrolledIndex >= md) + scrolledIndex -= md; /* Displace */ d = dispScanline[scrolledIndex]; @@ -216,7 +194,9 @@ static void draw(void) } /* Then after displacement, blit the objects */ - for (i = 0; i < 5; i++) rleBlit(backBuffer + PIXEL_PADDING, FB_WIDTH, FB_HEIGHT, BB_SIZE, rlePropeller, 134 + (i-3) * 60, 100); + for (i = 0; i < 5; i++) + rleBlit(rlePropeller, backBuffer + PIXEL_PADDING, FB_WIDTH, FB_HEIGHT, BB_SIZE, + 134 + (i - 3) * 60, 100); /* Blit effect to framebuffer */ src = backBuffer + PIXEL_PADDING; @@ -235,9 +215,9 @@ static void convert32To16(unsigned int *src32, unsigned short *dst16, unsigned i unsigned int p; while (pixelCount) { p = *src32++; - *dst16++ = ((p << 8) & 0xF800) /* R */ - | ((p >> 5) & 0x07E0) /* G */ - | ((p >> 19) & 0x001F); /* B */ + *dst16++ = ((p << 8) & 0xF800) /* R */ + | ((p >> 5) & 0x07E0) /* G */ + | ((p >> 19) & 0x001F); /* B */ pixelCount--; } } @@ -252,20 +232,22 @@ static void processNormal() { short minDisplacement = 256; unsigned short *dst; short *dst2; - unsigned int *normalmap = (unsigned int*)background; + unsigned int *normalmap = (unsigned int *)background; normalmap += NORMALMAP_SCANLINE * backgroundW; - dst = (unsigned short*)normalmap; - displacementMap = (short*)dst; + dst = (unsigned short *)normalmap; + displacementMap = (short *)dst; dst2 = displacementMap; for (scanline = 0; scanline < REFLECTION_HEIGHT; scanline++) { - scrollModTable[scanline] = (int) (backgroundW / scrollScaleTable[scanline] + 0.5f); + scrollModTable[scanline] = (int)(backgroundW / scrollScaleTable[scanline] + 0.5f); for (i = 0; i < backgroundW; i++) { x = (int)(i * scrollScaleTable[scanline] + 0.5f); if (x < backgroundW) { *dst = (unsigned short)(normalmap[x] >> 8) & 0xFF; - if ((short)*dst > maxDisplacement) maxDisplacement = (short)(*dst); - if ((short)*dst < minDisplacement) minDisplacement = (short)(*dst); + if ((short)*dst > maxDisplacement) + maxDisplacement = (short)(*dst); + if ((short)*dst < minDisplacement) + minDisplacement = (short)(*dst); } else { *dst = 0; } @@ -282,9 +264,13 @@ static void processNormal() { /* Second pass - subtract half maximum displacement to displace in both directions */ for (scanline = 0; scanline < REFLECTION_HEIGHT; scanline++) { for (i = 0; i < backgroundW; i++) { - /* Remember that MIN_SCROLL is the padding around the screen, so ti's the maximum displacement we can get (positive & negative) */ - *dst2 = 2 * MAX_DISPLACEMENT * (*dst2 - minDisplacement) / (maxDisplacement - minDisplacement) - MAX_DISPLACEMENT; - *dst2 = (short)((float)*dst2 / scrollScaleTable[scanline] + 0.5f); /* Displacements must also scale with distance*/ + /* Remember that MIN_SCROLL is the padding around the screen, so ti's the + * maximum displacement we can get (positive & negative) */ + *dst2 = 2 * MAX_DISPLACEMENT * (*dst2 - minDisplacement) / + (maxDisplacement - minDisplacement) - + MAX_DISPLACEMENT; + *dst2 = (short)((float)*dst2 / scrollScaleTable[scanline] + + 0.5f); /* Displacements must also scale with distance*/ dst2++; } } @@ -306,12 +292,11 @@ static void initScrollTables() { } } - static void updateScrollTables(float dt) { int i = 0; nearScrollAmount += dt * NEAR_SCROLL_SPEED; - nearScrollAmount = (float) fmod(nearScrollAmount, 512.0f); + nearScrollAmount = (float)fmod(nearScrollAmount, 512.0f); for (i = 0; i < REFLECTION_HEIGHT; i++) { scrollTable[i] = nearScrollAmount / scrollScaleTable[i]; @@ -320,298 +305,9 @@ static void updateScrollTables(float dt) { } /* ------------------------------------------------------------------------------------------------- - * RLE STUFF + * PROPELLER STUFF * ------------------------------------------------------------------------------------------------- */ -/* Limit streak count per scanline so we can directly jump to specific scanline */ -#define RLE_STREAKS_PER_SCANLINE 4 -/* Every streak is encoded by 2 bytes: offset and count of black pixels in the streak */ -#define RLE_BYTES_PER_SCANLINE RLE_STREAKS_PER_SCANLINE * 2 -#define RLE_FILL_COLOR 0 -#define RLE_FILL_COLOR_32 ((RLE_FILL_COLOR << 16) | RLE_FILL_COLOR) - -#define RLE_FIXED_BITS 16 - -static int rleByteCount(int w, int h) { - return h * RLE_BYTES_PER_SCANLINE + w; -} - -static RLEBitmap *rleCreate(unsigned int w, unsigned int h) { - RLEBitmap *ret = (RLEBitmap*)malloc(sizeof(RLEBitmap)); - ret->w = w; - ret->h = h; - - /* Add some padding at the end of the buffer, with the worst case for a scanline (w/2 streaks) */ - ret->scans = (unsigned char*) calloc(rleByteCount(w, h), 1); - - return ret; -} - -static void rleDestroy(RLEBitmap *b) { - if (!b) return; - free(b->scans); - free(b); -} - -static RLEBitmap *rleEncode(RLEBitmap *b, unsigned char *pixels, unsigned int w, unsigned int h) { - int scanline; - int i; - int penActive = 0; - int counter = 0; - int accum = 0; - unsigned char *output; - - /* https://www.youtube.com/watch?v=RKMR02o1I88&feature=youtu.be&t=55 */ - if (!b) b = rleCreate(w, h); - else memset(b->scans, 0, rleByteCount(b->w, b->h)); /* The following code assumes cleared array */ - - for (scanline = 0; scanline < h; scanline++) { - output = b->scans + scanline * RLE_BYTES_PER_SCANLINE; - accum = 0; - for (i = 0; i < w; i++) { - if (*pixels++) { - if (penActive) { - if (counter >= PIXEL_PADDING) { - *output++ = (unsigned char) counter; - counter = 0; - *output++ = (unsigned char)accum; - } - counter++; - accum++; - } else { - *output++ = (unsigned char)accum; - counter = 1; - accum++; - penActive = 1; - } - } else { - if (penActive) { - *output++ = (unsigned char)counter; - counter = 1; - accum++; - penActive = 0; - } else { - counter++; - accum++; - } - } - } - - if (penActive) { - *output++ = (unsigned char)counter; - } - penActive = 0; - counter = 0; - } - - return b; -} - -static void rleDistributeStreaks(RLEBitmap *bitmap) { - int scanline, halfW = bitmap->w >> 1; - unsigned char *ptr, tmp; - - ptr = bitmap->scans; - for (scanline = 0; scanline < bitmap->h; scanline++) { - if (ptr[0] >= halfW) { - tmp = ptr[0]; - ptr[0] = ptr[6]; - ptr[6] = tmp; - tmp = ptr[1]; - ptr[1] = ptr[7]; - ptr[7] = tmp; - } - - ptr += 8; - } -} - -static void rleBlit(unsigned short *dst, int dstW, int dstH, int dstStride, - RLEBitmap *bitmap, int blitX, int blitY) -{ - int scanline = 0; - int streakPos = 0; - int streakLength = 0; - int streak = 0; - unsigned char *input = bitmap->scans; - unsigned short *output; - unsigned int *output32; - - dst += blitX + blitY * dstStride; - - for (scanline = blitY; scanline < blitY + bitmap->h; scanline++) { - if (scanline < 0 || scanline >= dstH) continue; - for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { - streakPos = *input++; - streakLength = *input++; - - if ((streakPos + blitX) <= 0) continue; - - output = dst + streakPos; - - /* Check if we need to write the first pixel as 16bit */ - if (streakLength % 2) { - *output++ = RLE_FILL_COLOR; - } - - /* Then, write 2 pixels at a time */ - streakLength >>= 1; - output32 = (unsigned int*) output; - while (streakLength--) { - *output32++ = RLE_FILL_COLOR_32; - } - } - - dst += dstStride; - } -} - -static void interpolateScan(unsigned char *output, unsigned char *a, unsigned char *b, float t) { - static int div = 1 << 23; - int ti, i; - - t += 1.0f; - ti = (*((unsigned int*)&t)) & 0x7FFFFF; - - for (i = 0; i < RLE_BYTES_PER_SCANLINE; i++) { - if (*a == 0) { - *output++ = *b++; - a++; - } else { - if (*b == 0) { - *output++ = *a++; - b++; - } else { - *output++ = ((*b++ * ti) + (*a++ * (div - ti))) >> 23; - } - } - } -} - -static void rleBlitScale(unsigned short *dst, int dstW, int dstH, int dstStride, - RLEBitmap *bitmap, int blitX, int blitY, float scaleX, float scaleY) -{ - int scanline = 0; - int streakPos = 0; - int streakLength = 0; - int streak = 0; - unsigned short *output; - unsigned int *output32; - unsigned char *input; - int scanlineCounter = 0; - int scaleXFixed; - static unsigned char scan[512]; - - /*int blitW = (int)(bitmap->w * scaleX + 0.5f);*/ - int blitH = (int)(bitmap->h * scaleY + 0.5f); - - /* From this point on, scaleY will be inverted */ - scaleY = 1.0f / scaleY; - - scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f); - - dst += blitX + blitY * dstStride; - - for (scanline = blitY; scanline < blitY + blitH; scanline++) { - float normalScan = scanlineCounter * scaleY; /* ScaleY is inverted */ - unsigned char *scan0 = bitmap->scans + RLE_BYTES_PER_SCANLINE * (int)normalScan; - unsigned char *scan1 = scan0 + RLE_BYTES_PER_SCANLINE; - normalScan -= (int)normalScan; - interpolateScan(scan, scan0, scan1, normalScan); - input = scan; - scanlineCounter++; - - if (scanline < 0 || scanline >= dstH) continue; - for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { - streakPos = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; - streakLength = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; - - if ((streakPos + blitX) <= 0) continue; - - output = dst + streakPos; - - /* Check if we need to write the first pixel as 16bit */ - if (streakLength % 2) { - *output++ = RLE_FILL_COLOR; - } - - /* Then, write 2 pixels at a time */ - streakLength >>= 1; - output32 = (unsigned int*)output; - while (streakLength--) { - *output32++ = RLE_FILL_COLOR_32; - } - } - - dst += dstStride; - } -} - - - -static void rleBlitScaleInv(unsigned short *dst, int dstW, int dstH, int dstStride, - RLEBitmap *bitmap, int blitX, int blitY, float scaleX, float scaleY) -{ - int scanline = 0; - int streakPos = 0; - int streakLength = 0; - int streak = 0; - unsigned short *output; - unsigned int *output32; - unsigned char *input; - int scanlineCounter = 0; - int scaleXFixed; - static unsigned char scan[512]; - - /*int blitW = (int)(bitmap->w * scaleX + 0.5f);*/ - int blitH = (int)(bitmap->h * scaleY + 0.5f); - - /* From this point on, scaleY will be inverted */ - scaleY = 1.0f / scaleY; - - scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f); - - dst += blitX + blitY * dstStride; - - for (scanline = blitY; scanline > blitY - blitH; scanline--) { - float normalScan = scanlineCounter * scaleY; /* ScaleY is inverted */ - unsigned char *scan0 = bitmap->scans + RLE_BYTES_PER_SCANLINE * (int)normalScan; - unsigned char *scan1 = scan0 + RLE_BYTES_PER_SCANLINE; - normalScan -= (int)normalScan; - interpolateScan(scan, scan0, scan1, normalScan); - input = scan; - scanlineCounter++; - - if (scanline < 0 || scanline >= dstH) continue; - for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { - streakPos = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; - streakLength = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; - - if ((streakPos + blitX) <= 0) continue; - - output = dst + streakPos; - - /* Check if we need to write the first pixel as 16bit */ - if (streakLength % 2) { - *output++ = RLE_FILL_COLOR; - } - - /* Then, write 2 pixels at a time */ - streakLength >>= 1; - output32 = (unsigned int*)output; - while (streakLength--) { - *output32++ = RLE_FILL_COLOR_32; - } - } - - dst -= dstStride; - } -} - -/* ------------------------------------------------------------------------------------------------- -* PROPELLER STUFF -* ------------------------------------------------------------------------------------------------- -*/ #define PROPELLER_CIRCLE_RADIUS 18 #define PROPELLER_CIRCLE_RADIUS_SQ (PROPELLER_CIRCLE_RADIUS * PROPELLER_CIRCLE_RADIUS) @@ -667,17 +363,20 @@ static void updatePropeller(float t) { /* First circle */ cx = propellerState.circleX[0] - i; cy = propellerState.circleY[0] - j; - if (cx*cx + cy*cy < PROPELLER_CIRCLE_RADIUS_SQ) count++; + if (cx * cx + cy * cy < PROPELLER_CIRCLE_RADIUS_SQ) + count++; /* 2nd circle */ cx = propellerState.circleX[1] - i; cy = propellerState.circleY[1] - j; - if (cx*cx + cy*cy < PROPELLER_CIRCLE_RADIUS_SQ) count++; + if (cx * cx + cy * cy < PROPELLER_CIRCLE_RADIUS_SQ) + count++; /* 3rd circle */ cx = propellerState.circleX[2] - i; cy = propellerState.circleY[2] - j; - if (cx*cx + cy*cy < PROPELLER_CIRCLE_RADIUS_SQ) count++; + if (cx * cx + cy * cy < PROPELLER_CIRCLE_RADIUS_SQ) + count++; *dst++ = count >= 2; } diff --git a/src/screen.c b/src/screen.c index 972e711..190b19f 100644 --- a/src/screen.c +++ b/src/screen.c @@ -27,6 +27,7 @@ struct screen *infcubes_screen(void); struct screen *hairball_screen(void); struct screen *cybersun_screen(void); struct screen *raytrace_screen(void); +struct screen *minifx_screen(void); void start_loadscr(void); void end_loadscr(void); @@ -87,6 +88,10 @@ int scr_init(void) if(!(scr[idx++] = raytrace_screen())) { return -1; } + if (!(scr[idx++] = minifx_screen())) { + return -1; + } + num_screens = idx; assert(num_screens <= NUM_SCR); diff --git a/src/utils/RleBitmap.c b/src/utils/RleBitmap.c new file mode 100644 index 0000000..8c344f2 --- /dev/null +++ b/src/utils/RleBitmap.c @@ -0,0 +1,309 @@ +#include "RleBitmap.h" +#include +#include + +/* Number of numbers per scanline. Each streak has 2 numbers (start, length) */ +#define RLE_ELEMENTS_PER_SCANLINE RLE_STREAKS_PER_SCANLINE * 2 + +/* Two RLE_TYPE elements per streak (= start,length) */ +#define RLE_BYTES_PER_SCANLINE RLE_ELEMENTS_PER_SCANLINE * sizeof(RLE_TYPE) + +/* RLE_TYPE count required for storing an RLE of w,h */ +static int rleWorstCaseElementCount(int w, int h) { + /* Allocate an extra worst case for one scanline, which is w/2 streaks = w + * (start,length) elements */ + return h * RLE_ELEMENTS_PER_SCANLINE + w; +} + +/* Byte count of the 'scans' buffer */ +static int rleScansByteCount(RleBitmap *rle) { + return rleWorstCaseElementCount(rle->w, rle->h) * sizeof(RLE_TYPE); +} + +RleBitmap *rleCreate(unsigned int w, unsigned int h) { + RleBitmap *ret = (RleBitmap *)malloc(sizeof(RleBitmap)); + ret->w = w; + ret->h = h; + + /* Allocate scans */ + ret->scans = (RLE_TYPE *)calloc(rleWorstCaseElementCount(w, h), sizeof(RLE_TYPE)); + + return ret; +} + +void rleDestroy(RleBitmap *b) { + if (!b) + return; + free(b->scans); + free(b); +} + +void rleClear(RleBitmap *rle) { memset(rle->scans, 0, rleScansByteCount(rle)); } + +RleBitmap *rleEncode(RleBitmap *rle, unsigned char *pixels, unsigned int pixelsW, + unsigned int pixelsH) { + int x = 0; + int y = 0; + int streakActive = 0; + int currentStreakLength = 0; + RLE_TYPE *output = 0; + unsigned char *currentInputPixel = pixels; + + /* https://www.youtube.com/watch?v=RKMR02o1I88&feature=youtu.be&t=55 */ + if (!rle) + rle = rleCreate(pixelsW, pixelsH); + else + rleClear(rle); /* The following code assumes cleared array */ + + for (y = 0; y < pixelsH; y++) { + /* Go to the beginning of the RLE scan */ + output = rle->scans + y * RLE_ELEMENTS_PER_SCANLINE; + + for (x = 0; x < pixelsW; x++) { + if (*currentInputPixel++) { + if (streakActive) { + if (currentStreakLength >= RLE_MAX_STREAK_LENGTH) { + /* Do not allow streaks of more than max length - + * close current streak */ + *output++ = (RLE_TYPE)currentStreakLength; + + /* Begin new streak at current x */ + *output++ = (RLE_TYPE)x; + currentStreakLength = 0; + } + } else { + /* Begin new streak */ + *output++ = (RLE_TYPE)x; + currentStreakLength = 0; + streakActive = 1; + } + currentStreakLength++; + } else { + if (streakActive) { + /* Close current streak */ + *output++ = (RLE_TYPE)currentStreakLength; + currentStreakLength = 0; + streakActive = 0; + } + } /* End if (current pixel on) */ + } /* End for (all x) */ + + /* We reached the end of the scan - close any active streak */ + if (streakActive) { + *output++ = (RLE_TYPE)currentStreakLength; + } + streakActive = 0; + currentStreakLength = 0; + } /* End for (all scans */ + + return rle; +} + +void rleDistributeStreaks(RleBitmap *rle) { + int scanline = 0; + int halfW = rle->w >> 1; + RLE_TYPE *ptr = 0; + RLE_TYPE tmp = 0; + +#define LAST_STREAK RLE_STREAKS_PER_SCANLINE + + ptr = rle->scans; + for (scanline = 0; scanline < rle->h; scanline++) { + if (ptr[0] >= halfW) { + /* Exchange first with last streak */ + tmp = ptr[0]; + ptr[0] = ptr[LAST_STREAK * 2 - 2]; + ptr[LAST_STREAK * 2 - 2] = tmp; + tmp = ptr[1]; + ptr[1] = ptr[LAST_STREAK * 2 - 1]; + ptr[LAST_STREAK * 2 - 1] = tmp; + } + + ptr += 8; + } +} + +void rleBlit(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX, + int blitY) { + int scanline = 0; + int streakPos = 0; + int streakLength = 0; + int streak = 0; + RLE_TYPE *input = rle->scans; + unsigned short *output; + unsigned int *output32; + + dst += blitX + blitY * dstStride; + + for (scanline = blitY; scanline < blitY + rle->h; scanline++) { + if (scanline < 0 || scanline >= dstH) + continue; + for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { + streakPos = (int)*input++; + streakLength = (int)*input++; + + if ((streakPos + blitX) <= 0) + continue; + + output = dst + streakPos; + + /* Check if we need to write the first pixel as 16bit */ + if (streakLength % 2) { + *output++ = RLE_FILL_COLOR; + } + + /* Then, write 2 pixels at a time */ + streakLength >>= 1; + output32 = (unsigned int *)output; + while (streakLength--) { + *output32++ = RLE_FILL_COLOR_32; + } + } + + dst += dstStride; + } +} + +/* This is madness. We could at least check that we are not interpolating from 0 -> something + * (length). This could remove the need for 'distributeScans' */ +void interpolateScan(RLE_TYPE *output, RLE_TYPE *a, RLE_TYPE *b, float t) { + static int div = 1 << 23; + int ti, i; + + t += 1.0f; + ti = (*((unsigned int *)&t)) & 0x7FFFFF; + + for (i = 0; i < RLE_ELEMENTS_PER_SCANLINE; i++) { + if (*a == 0) { + *output++ = *b++; + a++; + } else { + if (*b == 0) { + *output++ = *a++; + b++; + } else { + *output++ = ((*b++ * ti) + (*a++ * (div - ti))) >> 23; + } + } + } +} + +void rleBlitScale(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX, + int blitY, float scaleX, float scaleY) { + int scanline = 0; + int streakPos = 0; + int streakLength = 0; + int streak = 0; + unsigned short *output; + unsigned int *output32; + unsigned char *input; + int scanlineCounter = 0; + int scaleXFixed; + static unsigned char scan[512]; + + /*int blitW = (int)(rle->w * scaleX + 0.5f);*/ + int blitH = (int)(rle->h * scaleY + 0.5f); + + /* From this point on, scaleY will be inverted */ + scaleY = 1.0f / scaleY; + + scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f); + + dst += blitX + blitY * dstStride; + + for (scanline = blitY; scanline < blitY + blitH; scanline++) { + float normalScan = scanlineCounter * scaleY; /* ScaleY is inverted */ + unsigned char *scan0 = rle->scans + RLE_BYTES_PER_SCANLINE * (int)normalScan; + unsigned char *scan1 = scan0 + RLE_BYTES_PER_SCANLINE; + normalScan -= (int)normalScan; + interpolateScan(scan, scan0, scan1, normalScan); + input = scan; + scanlineCounter++; + + if (scanline < 0 || scanline >= dstH) + continue; + for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { + streakPos = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; + streakLength = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; + + if ((streakPos + blitX) <= 0) + continue; + + output = dst + streakPos; + + /* Check if we need to write the first pixel as 16bit */ + if (streakLength % 2) { + *output++ = RLE_FILL_COLOR; + } + + /* Then, write 2 pixels at a time */ + streakLength >>= 1; + output32 = (unsigned int *)output; + while (streakLength--) { + *output32++ = RLE_FILL_COLOR_32; + } + } + + dst += dstStride; + } +} + +void rleBlitScaleInv(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, + int blitX, int blitY, float scaleX, float scaleY) { + int scanline = 0; + int streakPos = 0; + int streakLength = 0; + int streak = 0; + unsigned short *output; + unsigned int *output32; + unsigned char *input; + int scanlineCounter = 0; + int scaleXFixed; + static unsigned char scan[512]; + + /*int blitW = (int)(rle->w * scaleX + 0.5f);*/ + int blitH = (int)(rle->h * scaleY + 0.5f); + + /* From this point on, scaleY will be inverted */ + scaleY = 1.0f / scaleY; + + scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f); + + dst += blitX + blitY * dstStride; + + for (scanline = blitY; scanline > blitY - blitH; scanline--) { + float normalScan = scanlineCounter * scaleY; /* ScaleY is inverted */ + unsigned char *scan0 = rle->scans + RLE_BYTES_PER_SCANLINE * (int)normalScan; + unsigned char *scan1 = scan0 + RLE_BYTES_PER_SCANLINE; + normalScan -= (int)normalScan; + interpolateScan(scan, scan0, scan1, normalScan); + input = scan; + scanlineCounter++; + + if (scanline < 0 || scanline >= dstH) + continue; + for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { + streakPos = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; + streakLength = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; + + if ((streakPos + blitX) <= 0) + continue; + + output = dst + streakPos; + + /* Check if we need to write the first pixel as 16bit */ + if (streakLength % 2) { + *output++ = RLE_FILL_COLOR; + } + + /* Then, write 2 pixels at a time */ + streakLength >>= 1; + output32 = (unsigned int *)output; + while (streakLength--) { + *output32++ = RLE_FILL_COLOR_32; + } + } + + dst -= dstStride; + } +} diff --git a/src/utils/RleBitmap.h b/src/utils/RleBitmap.h new file mode 100644 index 0000000..3f36b16 --- /dev/null +++ b/src/utils/RleBitmap.h @@ -0,0 +1,66 @@ +#ifndef __RLE_BITMAP_H__ +#define __RLE_BITMAP_H__ + +/* Limit streak count per scanline so we can directly jump to specific scanline + */ +#define RLE_STREAKS_PER_SCANLINE 4 + +/* Streaks will not exceed this many pixels. This allows us to optimize with a + * padded framebuffer. If a streak start position happens to lie within + * framebuffer, we will blit it without checking for out of bounds */ +#define RLE_MAX_STREAK_LENGTH 32 + +/* Using the following type for storing start and for storing length in (start, + * length) pairs. */ +#define RLE_TYPE unsigned char + +/* For now, keep a static fill color. We can change this. Not that much about + * speed, but let's keep function definitions more compact. */ +#define RLE_FILL_COLOR 0 + +/* Two entries of RLE_FILL_COLOR (16 bits) packed one after the other. */ +#define RLE_FILL_COLOR_32 ((RLE_FILL_COLOR << 16) | RLE_FILL_COLOR) + +/* For fixed-point arithmetic. Used for scaling. */ +#define RLE_FIXED_BITS 16 + +/* This is a bitmap (image in 1bpp), encoded as streaks of consecutive pixels. + */ +typedef struct { + unsigned int w, h; + + /* Each scan is RLE_BYTES_PER_SCANLINE long and contains pairs of + * (start, length). */ + RLE_TYPE *scans; +} RleBitmap; + +/* Constructor */ +RleBitmap *rleCreate(unsigned int w, unsigned int h); + +/* Destructor */ +void rleDestroy(RleBitmap *rle); + +/* Clears 'rle' to "all transparent" */ +void rleClear(RleBitmap *rle); + +/* Encode 'pixels' into 'rle' and also return it. Pixels are either 0 or 1. This + * will create an RleBitmap of 'h' scanlines. */ +RleBitmap *rleEncode(RleBitmap *rle, unsigned char *pixels, unsigned int pixelsW, + unsigned int pixelsH); + +/* Rearranges the streaks to make it less frequent that they produce garbege when interpolated */ +void rleDistributeStreaks(RleBitmap *rle); + +/* Blits without scaling */ +void rleBlit(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX, + int blitY); + +/* Scaled blit */ +void rleBlitScale(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX, + int blitY, float scaleX, float scaleY); + +/* Inverted blit (upside down) */ +void rleBlitScaleInv(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, + int blitX, int blitY, float scaleX, float scaleY); + +#endif // __RLE_BITMAP_H__ -- 1.7.10.4 From 280b3d2a948e965d7af7f017809c27a2b2ee2ce2 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Sun, 15 May 2022 22:18:51 +0300 Subject: [PATCH 12/16] - fixed C89 compliance issues with the last commit (rlebitmap/minifx) - moved minifx.c under scr, since it's a part - moved src/utils/RleBitmap.* under src/ since src is all about utility stuff anyway. - made filenames DOS 8.3 compatible and lowercase - fixed include malloc.h -> stdlib.h - removed casts from malloc - fixed indentation consistency issues in one file - added new files to the watcom makefile --- GNUmakefile | 2 +- Makefile | 10 +- src/minifx.c | 161 -------------------------- src/rlebmap.c | 309 +++++++++++++++++++++++++++++++++++++++++++++++++ src/rlebmap.h | 66 +++++++++++ src/scr/grise.c | 2 +- src/scr/minifx.c | 169 +++++++++++++++++++++++++++ src/utils/RleBitmap.c | 309 ------------------------------------------------- src/utils/RleBitmap.h | 66 ----------- 9 files changed, 552 insertions(+), 542 deletions(-) delete mode 100644 src/minifx.c create mode 100644 src/rlebmap.c create mode 100644 src/rlebmap.h create mode 100644 src/scr/minifx.c delete mode 100644 src/utils/RleBitmap.c delete mode 100644 src/utils/RleBitmap.h diff --git a/GNUmakefile b/GNUmakefile index ea8082c..767026f 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,4 +1,4 @@ -src = $(wildcard src/*.c) $(wildcard src/3dgfx/*.c) $(wildcard src/scr/*.c) $(wildcard src/utils/*.c) \ +src = $(wildcard src/*.c) $(wildcard src/3dgfx/*.c) $(wildcard src/scr/*.c) \ $(wildcard src/glut/*.c) asmsrc = $(wildcard src/*.asm) obj = $(src:.c=.o) $(asmsrc:.asm=.o) diff --git a/Makefile b/Makefile index c862ea9..1f6ab07 100644 --- a/Makefile +++ b/Makefile @@ -9,12 +9,13 @@ srcobj = src/bsptree.obj src/cfgopt.obj src/console.obj src/demo.obj & src/dynarr.obj src/gfxutil.obj src/metasurf.obj src/noise.obj & src/rbtree.obj src/screen.obj src/tinyfps.obj src/treestor.obj & src/image.obj src/ts_text.obj src/util.obj src/util_s.obj src/cpuid.obj & - src/cpuid_s.obj src/darray.obj src/data.obj + src/cpuid_s.obj src/darray.obj src/data.obj src/rlebmap.obj scrobj = src/scr/bump.obj src/scr/fract.obj src/scr/greets.obj & src/scr/grise.obj src/scr/hairball.obj src/scr/infcubes.obj & src/scr/metaball.obj src/scr/plasma.obj src/scr/polytest.obj & src/scr/smoketxt.obj src/scr/thunder.obj src/scr/tilemaze.obj & - src/scr/tunnel.obj src/scr/cybersun.obj src/scr/raytrace.obj src/scr/rt.obj + src/scr/tunnel.obj src/scr/cybersun.obj src/scr/raytrace.obj & + src/scr/rt.obj src/scr/minifx.obj csprobj = cspr/dbgfont.obj cspr/confont.obj incpath = -Isrc -Isrc/dos -Isrc/3dgfx -Ilibs -Ilibs/imago/src -Ilibs/anim/src & @@ -32,12 +33,13 @@ srcobj = src\bsptree.obj src\cfgopt.obj src\console.obj src\demo.obj & src\dynarr.obj src\gfxutil.obj src\metasurf.obj src\noise.obj & src\rbtree.obj src\screen.obj src\tinyfps.obj src\treestor.obj & src\image.obj src\ts_text.obj src\util.obj src\util_s.obj src\cpuid.obj & - src\cpuid_s.obj src\darray.obj src\data.obj + src\cpuid_s.obj src\darray.obj src\data.obj src\rlebmap.obj scrobj = src\scr\bump.obj src\scr\fract.obj src\scr\greets.obj & src\scr\grise.obj src\scr\hairball.obj src\scr\infcubes.obj & src\scr\metaball.obj src\scr\plasma.obj src\scr\polytest.obj & src\scr\smoketxt.obj src\scr\thunder.obj src\scr\tilemaze.obj & - src\scr\tunnel.obj src\scr\cybersun.obj src\scr\raytrace.obj src\scr\rt.obj + src\scr\tunnel.obj src\scr\cybersun.obj src\scr\raytrace.obj & + src\scr\rt.obj src\scr\minifx.obj csprobj = cspr\dbgfont.obj cspr\confont.obj incpath = -Isrc -Isrc\dos -Isrc\3dgfx -Ilibs -Ilibs\imago\src -Ilibs\anim\src & diff --git a/src/minifx.c b/src/minifx.c deleted file mode 100644 index 59a3269..0000000 --- a/src/minifx.c +++ /dev/null @@ -1,161 +0,0 @@ -#include "demo.h" -#include "imago2.h" -#include "screen.h" -#include -#include -#include -#include -#include - -#include - -/* APPROX. 170 FPS Minimum */ - -static int init(void); -static void destroy(void); -static void start(long trans_time); -static void stop(long trans_time); -static void draw(void); - -static void updatePropeller(float t, RleBitmap *rle); - -static unsigned short *backBuffer; - -static unsigned char miniFXBuffer[1024]; - -static long lastFrameTime = 0; - -static struct screen scr = {"minifx", init, destroy, start, 0, draw}; - -struct screen *minifx_screen(void) { - return &scr; -} - -static int init(void) { - /* Allocate back buffer */ - backBuffer = (unsigned short *)calloc(FB_WIDTH * FB_HEIGHT, sizeof(unsigned short)); - - return 0; -} - -static void destroy(void) { - free(backBuffer); - backBuffer = 0; -} - -static void start(long trans_time) { lastFrameTime = time_msec; } - -static void draw(void) { - long lastFrameDuration = (time_msec - lastFrameTime) / 1000.0f; - lastFrameTime = time_msec; - - int clearColor = 0x888888; - unsigned short clearColor16 = ((clearColor << 8) & 0xF800) /* R */ - | ((clearColor >> 5) & 0x07E0) /* G */ - | ((clearColor >> 19) & 0x001F); /* B */ - for (int i=0; i= 2; - } - } - - /* Then, encode to rle */ - rleEncode(rle, miniFXBuffer, 32, 32); - - /* Distribute the produced streaks so that they don't produce garbage when interpolated */ - rleDistributeStreaks(rle); -} diff --git a/src/rlebmap.c b/src/rlebmap.c new file mode 100644 index 0000000..de5e168 --- /dev/null +++ b/src/rlebmap.c @@ -0,0 +1,309 @@ +#include +#include +#include "rlebmap.h" + +/* Number of numbers per scanline. Each streak has 2 numbers (start, length) */ +#define RLE_ELEMENTS_PER_SCANLINE RLE_STREAKS_PER_SCANLINE * 2 + +/* Two RLE_TYPE elements per streak (= start,length) */ +#define RLE_BYTES_PER_SCANLINE RLE_ELEMENTS_PER_SCANLINE * sizeof(RLE_TYPE) + +/* RLE_TYPE count required for storing an RLE of w,h */ +static int rleWorstCaseElementCount(int w, int h) { + /* Allocate an extra worst case for one scanline, which is w/2 streaks = w + * (start,length) elements */ + return h * RLE_ELEMENTS_PER_SCANLINE + w; +} + +/* Byte count of the 'scans' buffer */ +static int rleScansByteCount(RleBitmap *rle) { + return rleWorstCaseElementCount(rle->w, rle->h) * sizeof(RLE_TYPE); +} + +RleBitmap *rleCreate(unsigned int w, unsigned int h) { + RleBitmap *ret = malloc(sizeof(RleBitmap)); + ret->w = w; + ret->h = h; + + /* Allocate scans */ + ret->scans = calloc(rleWorstCaseElementCount(w, h), sizeof(RLE_TYPE)); + + return ret; +} + +void rleDestroy(RleBitmap *b) { + if (!b) + return; + free(b->scans); + free(b); +} + +void rleClear(RleBitmap *rle) { memset(rle->scans, 0, rleScansByteCount(rle)); } + +RleBitmap *rleEncode(RleBitmap *rle, unsigned char *pixels, unsigned int pixelsW, + unsigned int pixelsH) { + int x = 0; + int y = 0; + int streakActive = 0; + int currentStreakLength = 0; + RLE_TYPE *output = 0; + unsigned char *currentInputPixel = pixels; + + /* https://www.youtube.com/watch?v=RKMR02o1I88&feature=youtu.be&t=55 */ + if (!rle) + rle = rleCreate(pixelsW, pixelsH); + else + rleClear(rle); /* The following code assumes cleared array */ + + for (y = 0; y < pixelsH; y++) { + /* Go to the beginning of the RLE scan */ + output = rle->scans + y * RLE_ELEMENTS_PER_SCANLINE; + + for (x = 0; x < pixelsW; x++) { + if (*currentInputPixel++) { + if (streakActive) { + if (currentStreakLength >= RLE_MAX_STREAK_LENGTH) { + /* Do not allow streaks of more than max length - + * close current streak */ + *output++ = (RLE_TYPE)currentStreakLength; + + /* Begin new streak at current x */ + *output++ = (RLE_TYPE)x; + currentStreakLength = 0; + } + } else { + /* Begin new streak */ + *output++ = (RLE_TYPE)x; + currentStreakLength = 0; + streakActive = 1; + } + currentStreakLength++; + } else { + if (streakActive) { + /* Close current streak */ + *output++ = (RLE_TYPE)currentStreakLength; + currentStreakLength = 0; + streakActive = 0; + } + } /* End if (current pixel on) */ + } /* End for (all x) */ + + /* We reached the end of the scan - close any active streak */ + if (streakActive) { + *output++ = (RLE_TYPE)currentStreakLength; + } + streakActive = 0; + currentStreakLength = 0; + } /* End for (all scans */ + + return rle; +} + +void rleDistributeStreaks(RleBitmap *rle) { + int scanline = 0; + int halfW = rle->w >> 1; + RLE_TYPE *ptr = 0; + RLE_TYPE tmp = 0; + +#define LAST_STREAK RLE_STREAKS_PER_SCANLINE + + ptr = rle->scans; + for (scanline = 0; scanline < rle->h; scanline++) { + if (ptr[0] >= halfW) { + /* Exchange first with last streak */ + tmp = ptr[0]; + ptr[0] = ptr[LAST_STREAK * 2 - 2]; + ptr[LAST_STREAK * 2 - 2] = tmp; + tmp = ptr[1]; + ptr[1] = ptr[LAST_STREAK * 2 - 1]; + ptr[LAST_STREAK * 2 - 1] = tmp; + } + + ptr += 8; + } +} + +void rleBlit(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX, + int blitY) { + int scanline = 0; + int streakPos = 0; + int streakLength = 0; + int streak = 0; + RLE_TYPE *input = rle->scans; + unsigned short *output; + unsigned int *output32; + + dst += blitX + blitY * dstStride; + + for (scanline = blitY; scanline < blitY + rle->h; scanline++) { + if (scanline < 0 || scanline >= dstH) + continue; + for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { + streakPos = (int)*input++; + streakLength = (int)*input++; + + if ((streakPos + blitX) <= 0) + continue; + + output = dst + streakPos; + + /* Check if we need to write the first pixel as 16bit */ + if (streakLength % 2) { + *output++ = RLE_FILL_COLOR; + } + + /* Then, write 2 pixels at a time */ + streakLength >>= 1; + output32 = (unsigned int *)output; + while (streakLength--) { + *output32++ = RLE_FILL_COLOR_32; + } + } + + dst += dstStride; + } +} + +/* This is madness. We could at least check that we are not interpolating from 0 -> something + * (length). This could remove the need for 'distributeScans' */ +void interpolateScan(RLE_TYPE *output, RLE_TYPE *a, RLE_TYPE *b, float t) { + static int div = 1 << 23; + int ti, i; + + t += 1.0f; + ti = (*((unsigned int *)&t)) & 0x7FFFFF; + + for (i = 0; i < RLE_ELEMENTS_PER_SCANLINE; i++) { + if (*a == 0) { + *output++ = *b++; + a++; + } else { + if (*b == 0) { + *output++ = *a++; + b++; + } else { + *output++ = ((*b++ * ti) + (*a++ * (div - ti))) >> 23; + } + } + } +} + +void rleBlitScale(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX, + int blitY, float scaleX, float scaleY) { + int scanline = 0; + int streakPos = 0; + int streakLength = 0; + int streak = 0; + unsigned short *output; + unsigned int *output32; + unsigned char *input; + int scanlineCounter = 0; + int scaleXFixed; + static unsigned char scan[512]; + + /*int blitW = (int)(rle->w * scaleX + 0.5f);*/ + int blitH = (int)(rle->h * scaleY + 0.5f); + + /* From this point on, scaleY will be inverted */ + scaleY = 1.0f / scaleY; + + scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f); + + dst += blitX + blitY * dstStride; + + for (scanline = blitY; scanline < blitY + blitH; scanline++) { + float normalScan = scanlineCounter * scaleY; /* ScaleY is inverted */ + unsigned char *scan0 = rle->scans + RLE_BYTES_PER_SCANLINE * (int)normalScan; + unsigned char *scan1 = scan0 + RLE_BYTES_PER_SCANLINE; + normalScan -= (int)normalScan; + interpolateScan(scan, scan0, scan1, normalScan); + input = scan; + scanlineCounter++; + + if (scanline < 0 || scanline >= dstH) + continue; + for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { + streakPos = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; + streakLength = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; + + if ((streakPos + blitX) <= 0) + continue; + + output = dst + streakPos; + + /* Check if we need to write the first pixel as 16bit */ + if (streakLength % 2) { + *output++ = RLE_FILL_COLOR; + } + + /* Then, write 2 pixels at a time */ + streakLength >>= 1; + output32 = (unsigned int *)output; + while (streakLength--) { + *output32++ = RLE_FILL_COLOR_32; + } + } + + dst += dstStride; + } +} + +void rleBlitScaleInv(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, + int blitX, int blitY, float scaleX, float scaleY) { + int scanline = 0; + int streakPos = 0; + int streakLength = 0; + int streak = 0; + unsigned short *output; + unsigned int *output32; + unsigned char *input; + int scanlineCounter = 0; + int scaleXFixed; + static unsigned char scan[512]; + + /*int blitW = (int)(rle->w * scaleX + 0.5f);*/ + int blitH = (int)(rle->h * scaleY + 0.5f); + + /* From this point on, scaleY will be inverted */ + scaleY = 1.0f / scaleY; + + scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f); + + dst += blitX + blitY * dstStride; + + for (scanline = blitY; scanline > blitY - blitH; scanline--) { + float normalScan = scanlineCounter * scaleY; /* ScaleY is inverted */ + unsigned char *scan0 = rle->scans + RLE_BYTES_PER_SCANLINE * (int)normalScan; + unsigned char *scan1 = scan0 + RLE_BYTES_PER_SCANLINE; + normalScan -= (int)normalScan; + interpolateScan(scan, scan0, scan1, normalScan); + input = scan; + scanlineCounter++; + + if (scanline < 0 || scanline >= dstH) + continue; + for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { + streakPos = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; + streakLength = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; + + if ((streakPos + blitX) <= 0) + continue; + + output = dst + streakPos; + + /* Check if we need to write the first pixel as 16bit */ + if (streakLength % 2) { + *output++ = RLE_FILL_COLOR; + } + + /* Then, write 2 pixels at a time */ + streakLength >>= 1; + output32 = (unsigned int *)output; + while (streakLength--) { + *output32++ = RLE_FILL_COLOR_32; + } + } + + dst -= dstStride; + } +} diff --git a/src/rlebmap.h b/src/rlebmap.h new file mode 100644 index 0000000..3f36b16 --- /dev/null +++ b/src/rlebmap.h @@ -0,0 +1,66 @@ +#ifndef __RLE_BITMAP_H__ +#define __RLE_BITMAP_H__ + +/* Limit streak count per scanline so we can directly jump to specific scanline + */ +#define RLE_STREAKS_PER_SCANLINE 4 + +/* Streaks will not exceed this many pixels. This allows us to optimize with a + * padded framebuffer. If a streak start position happens to lie within + * framebuffer, we will blit it without checking for out of bounds */ +#define RLE_MAX_STREAK_LENGTH 32 + +/* Using the following type for storing start and for storing length in (start, + * length) pairs. */ +#define RLE_TYPE unsigned char + +/* For now, keep a static fill color. We can change this. Not that much about + * speed, but let's keep function definitions more compact. */ +#define RLE_FILL_COLOR 0 + +/* Two entries of RLE_FILL_COLOR (16 bits) packed one after the other. */ +#define RLE_FILL_COLOR_32 ((RLE_FILL_COLOR << 16) | RLE_FILL_COLOR) + +/* For fixed-point arithmetic. Used for scaling. */ +#define RLE_FIXED_BITS 16 + +/* This is a bitmap (image in 1bpp), encoded as streaks of consecutive pixels. + */ +typedef struct { + unsigned int w, h; + + /* Each scan is RLE_BYTES_PER_SCANLINE long and contains pairs of + * (start, length). */ + RLE_TYPE *scans; +} RleBitmap; + +/* Constructor */ +RleBitmap *rleCreate(unsigned int w, unsigned int h); + +/* Destructor */ +void rleDestroy(RleBitmap *rle); + +/* Clears 'rle' to "all transparent" */ +void rleClear(RleBitmap *rle); + +/* Encode 'pixels' into 'rle' and also return it. Pixels are either 0 or 1. This + * will create an RleBitmap of 'h' scanlines. */ +RleBitmap *rleEncode(RleBitmap *rle, unsigned char *pixels, unsigned int pixelsW, + unsigned int pixelsH); + +/* Rearranges the streaks to make it less frequent that they produce garbege when interpolated */ +void rleDistributeStreaks(RleBitmap *rle); + +/* Blits without scaling */ +void rleBlit(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX, + int blitY); + +/* Scaled blit */ +void rleBlitScale(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX, + int blitY, float scaleX, float scaleY); + +/* Inverted blit (upside down) */ +void rleBlitScaleInv(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, + int blitX, int blitY, float scaleX, float scaleY); + +#endif // __RLE_BITMAP_H__ diff --git a/src/scr/grise.c b/src/scr/grise.c index 36e9ff9..c4a2e28 100644 --- a/src/scr/grise.c +++ b/src/scr/grise.c @@ -7,7 +7,7 @@ #include #include -#include +#include "rlebmap.h" /* APPROX. 170 FPS Minimum */ diff --git a/src/scr/minifx.c b/src/scr/minifx.c new file mode 100644 index 0000000..84f9c38 --- /dev/null +++ b/src/scr/minifx.c @@ -0,0 +1,169 @@ +#include "demo.h" +#include "imago2.h" +#include "screen.h" +#include +#include +#include +#include +#include + +#include "rlebmap.h" + +/* APPROX. 170 FPS Minimum */ + +static int init(void); +static void destroy(void); +static void start(long trans_time); +static void stop(long trans_time); +static void draw(void); + +static void updatePropeller(float t, RleBitmap *rle); + +static unsigned short *backBuffer; + +static unsigned char miniFXBuffer[1024]; + +static long lastFrameTime = 0; + +static struct screen scr = {"minifx", init, destroy, start, 0, draw}; + +struct screen *minifx_screen(void) { + return &scr; +} + +static int init(void) { + /* Allocate back buffer */ + backBuffer = calloc(FB_WIDTH * FB_HEIGHT, sizeof(unsigned short)); + + return 0; +} + +static void destroy(void) { + free(backBuffer); + backBuffer = 0; +} + +static void start(long trans_time) { lastFrameTime = time_msec; } + +static void draw(void) { + long lastFrameDuration; + int i, stride; + RleBitmap *rle; + int clearColor; + unsigned short clearColor16; + + lastFrameDuration = (time_msec - lastFrameTime) / 1000.0f; + lastFrameTime = time_msec; + + clearColor = 0x888888; + clearColor16 = ((clearColor << 8) & 0xF800) /* R */ + | ((clearColor >> 5) & 0x07E0) /* G */ + | ((clearColor >> 19) & 0x001F); /* B */ + + for (i=0; i= 2; + } + } + + /* Then, encode to rle */ + rleEncode(rle, miniFXBuffer, 32, 32); + + /* Distribute the produced streaks so that they don't produce garbage when interpolated */ + rleDistributeStreaks(rle); +} diff --git a/src/utils/RleBitmap.c b/src/utils/RleBitmap.c deleted file mode 100644 index 8c344f2..0000000 --- a/src/utils/RleBitmap.c +++ /dev/null @@ -1,309 +0,0 @@ -#include "RleBitmap.h" -#include -#include - -/* Number of numbers per scanline. Each streak has 2 numbers (start, length) */ -#define RLE_ELEMENTS_PER_SCANLINE RLE_STREAKS_PER_SCANLINE * 2 - -/* Two RLE_TYPE elements per streak (= start,length) */ -#define RLE_BYTES_PER_SCANLINE RLE_ELEMENTS_PER_SCANLINE * sizeof(RLE_TYPE) - -/* RLE_TYPE count required for storing an RLE of w,h */ -static int rleWorstCaseElementCount(int w, int h) { - /* Allocate an extra worst case for one scanline, which is w/2 streaks = w - * (start,length) elements */ - return h * RLE_ELEMENTS_PER_SCANLINE + w; -} - -/* Byte count of the 'scans' buffer */ -static int rleScansByteCount(RleBitmap *rle) { - return rleWorstCaseElementCount(rle->w, rle->h) * sizeof(RLE_TYPE); -} - -RleBitmap *rleCreate(unsigned int w, unsigned int h) { - RleBitmap *ret = (RleBitmap *)malloc(sizeof(RleBitmap)); - ret->w = w; - ret->h = h; - - /* Allocate scans */ - ret->scans = (RLE_TYPE *)calloc(rleWorstCaseElementCount(w, h), sizeof(RLE_TYPE)); - - return ret; -} - -void rleDestroy(RleBitmap *b) { - if (!b) - return; - free(b->scans); - free(b); -} - -void rleClear(RleBitmap *rle) { memset(rle->scans, 0, rleScansByteCount(rle)); } - -RleBitmap *rleEncode(RleBitmap *rle, unsigned char *pixels, unsigned int pixelsW, - unsigned int pixelsH) { - int x = 0; - int y = 0; - int streakActive = 0; - int currentStreakLength = 0; - RLE_TYPE *output = 0; - unsigned char *currentInputPixel = pixels; - - /* https://www.youtube.com/watch?v=RKMR02o1I88&feature=youtu.be&t=55 */ - if (!rle) - rle = rleCreate(pixelsW, pixelsH); - else - rleClear(rle); /* The following code assumes cleared array */ - - for (y = 0; y < pixelsH; y++) { - /* Go to the beginning of the RLE scan */ - output = rle->scans + y * RLE_ELEMENTS_PER_SCANLINE; - - for (x = 0; x < pixelsW; x++) { - if (*currentInputPixel++) { - if (streakActive) { - if (currentStreakLength >= RLE_MAX_STREAK_LENGTH) { - /* Do not allow streaks of more than max length - - * close current streak */ - *output++ = (RLE_TYPE)currentStreakLength; - - /* Begin new streak at current x */ - *output++ = (RLE_TYPE)x; - currentStreakLength = 0; - } - } else { - /* Begin new streak */ - *output++ = (RLE_TYPE)x; - currentStreakLength = 0; - streakActive = 1; - } - currentStreakLength++; - } else { - if (streakActive) { - /* Close current streak */ - *output++ = (RLE_TYPE)currentStreakLength; - currentStreakLength = 0; - streakActive = 0; - } - } /* End if (current pixel on) */ - } /* End for (all x) */ - - /* We reached the end of the scan - close any active streak */ - if (streakActive) { - *output++ = (RLE_TYPE)currentStreakLength; - } - streakActive = 0; - currentStreakLength = 0; - } /* End for (all scans */ - - return rle; -} - -void rleDistributeStreaks(RleBitmap *rle) { - int scanline = 0; - int halfW = rle->w >> 1; - RLE_TYPE *ptr = 0; - RLE_TYPE tmp = 0; - -#define LAST_STREAK RLE_STREAKS_PER_SCANLINE - - ptr = rle->scans; - for (scanline = 0; scanline < rle->h; scanline++) { - if (ptr[0] >= halfW) { - /* Exchange first with last streak */ - tmp = ptr[0]; - ptr[0] = ptr[LAST_STREAK * 2 - 2]; - ptr[LAST_STREAK * 2 - 2] = tmp; - tmp = ptr[1]; - ptr[1] = ptr[LAST_STREAK * 2 - 1]; - ptr[LAST_STREAK * 2 - 1] = tmp; - } - - ptr += 8; - } -} - -void rleBlit(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX, - int blitY) { - int scanline = 0; - int streakPos = 0; - int streakLength = 0; - int streak = 0; - RLE_TYPE *input = rle->scans; - unsigned short *output; - unsigned int *output32; - - dst += blitX + blitY * dstStride; - - for (scanline = blitY; scanline < blitY + rle->h; scanline++) { - if (scanline < 0 || scanline >= dstH) - continue; - for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { - streakPos = (int)*input++; - streakLength = (int)*input++; - - if ((streakPos + blitX) <= 0) - continue; - - output = dst + streakPos; - - /* Check if we need to write the first pixel as 16bit */ - if (streakLength % 2) { - *output++ = RLE_FILL_COLOR; - } - - /* Then, write 2 pixels at a time */ - streakLength >>= 1; - output32 = (unsigned int *)output; - while (streakLength--) { - *output32++ = RLE_FILL_COLOR_32; - } - } - - dst += dstStride; - } -} - -/* This is madness. We could at least check that we are not interpolating from 0 -> something - * (length). This could remove the need for 'distributeScans' */ -void interpolateScan(RLE_TYPE *output, RLE_TYPE *a, RLE_TYPE *b, float t) { - static int div = 1 << 23; - int ti, i; - - t += 1.0f; - ti = (*((unsigned int *)&t)) & 0x7FFFFF; - - for (i = 0; i < RLE_ELEMENTS_PER_SCANLINE; i++) { - if (*a == 0) { - *output++ = *b++; - a++; - } else { - if (*b == 0) { - *output++ = *a++; - b++; - } else { - *output++ = ((*b++ * ti) + (*a++ * (div - ti))) >> 23; - } - } - } -} - -void rleBlitScale(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX, - int blitY, float scaleX, float scaleY) { - int scanline = 0; - int streakPos = 0; - int streakLength = 0; - int streak = 0; - unsigned short *output; - unsigned int *output32; - unsigned char *input; - int scanlineCounter = 0; - int scaleXFixed; - static unsigned char scan[512]; - - /*int blitW = (int)(rle->w * scaleX + 0.5f);*/ - int blitH = (int)(rle->h * scaleY + 0.5f); - - /* From this point on, scaleY will be inverted */ - scaleY = 1.0f / scaleY; - - scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f); - - dst += blitX + blitY * dstStride; - - for (scanline = blitY; scanline < blitY + blitH; scanline++) { - float normalScan = scanlineCounter * scaleY; /* ScaleY is inverted */ - unsigned char *scan0 = rle->scans + RLE_BYTES_PER_SCANLINE * (int)normalScan; - unsigned char *scan1 = scan0 + RLE_BYTES_PER_SCANLINE; - normalScan -= (int)normalScan; - interpolateScan(scan, scan0, scan1, normalScan); - input = scan; - scanlineCounter++; - - if (scanline < 0 || scanline >= dstH) - continue; - for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { - streakPos = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; - streakLength = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; - - if ((streakPos + blitX) <= 0) - continue; - - output = dst + streakPos; - - /* Check if we need to write the first pixel as 16bit */ - if (streakLength % 2) { - *output++ = RLE_FILL_COLOR; - } - - /* Then, write 2 pixels at a time */ - streakLength >>= 1; - output32 = (unsigned int *)output; - while (streakLength--) { - *output32++ = RLE_FILL_COLOR_32; - } - } - - dst += dstStride; - } -} - -void rleBlitScaleInv(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, - int blitX, int blitY, float scaleX, float scaleY) { - int scanline = 0; - int streakPos = 0; - int streakLength = 0; - int streak = 0; - unsigned short *output; - unsigned int *output32; - unsigned char *input; - int scanlineCounter = 0; - int scaleXFixed; - static unsigned char scan[512]; - - /*int blitW = (int)(rle->w * scaleX + 0.5f);*/ - int blitH = (int)(rle->h * scaleY + 0.5f); - - /* From this point on, scaleY will be inverted */ - scaleY = 1.0f / scaleY; - - scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f); - - dst += blitX + blitY * dstStride; - - for (scanline = blitY; scanline > blitY - blitH; scanline--) { - float normalScan = scanlineCounter * scaleY; /* ScaleY is inverted */ - unsigned char *scan0 = rle->scans + RLE_BYTES_PER_SCANLINE * (int)normalScan; - unsigned char *scan1 = scan0 + RLE_BYTES_PER_SCANLINE; - normalScan -= (int)normalScan; - interpolateScan(scan, scan0, scan1, normalScan); - input = scan; - scanlineCounter++; - - if (scanline < 0 || scanline >= dstH) - continue; - for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { - streakPos = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; - streakLength = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; - - if ((streakPos + blitX) <= 0) - continue; - - output = dst + streakPos; - - /* Check if we need to write the first pixel as 16bit */ - if (streakLength % 2) { - *output++ = RLE_FILL_COLOR; - } - - /* Then, write 2 pixels at a time */ - streakLength >>= 1; - output32 = (unsigned int *)output; - while (streakLength--) { - *output32++ = RLE_FILL_COLOR_32; - } - } - - dst -= dstStride; - } -} diff --git a/src/utils/RleBitmap.h b/src/utils/RleBitmap.h deleted file mode 100644 index 3f36b16..0000000 --- a/src/utils/RleBitmap.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef __RLE_BITMAP_H__ -#define __RLE_BITMAP_H__ - -/* Limit streak count per scanline so we can directly jump to specific scanline - */ -#define RLE_STREAKS_PER_SCANLINE 4 - -/* Streaks will not exceed this many pixels. This allows us to optimize with a - * padded framebuffer. If a streak start position happens to lie within - * framebuffer, we will blit it without checking for out of bounds */ -#define RLE_MAX_STREAK_LENGTH 32 - -/* Using the following type for storing start and for storing length in (start, - * length) pairs. */ -#define RLE_TYPE unsigned char - -/* For now, keep a static fill color. We can change this. Not that much about - * speed, but let's keep function definitions more compact. */ -#define RLE_FILL_COLOR 0 - -/* Two entries of RLE_FILL_COLOR (16 bits) packed one after the other. */ -#define RLE_FILL_COLOR_32 ((RLE_FILL_COLOR << 16) | RLE_FILL_COLOR) - -/* For fixed-point arithmetic. Used for scaling. */ -#define RLE_FIXED_BITS 16 - -/* This is a bitmap (image in 1bpp), encoded as streaks of consecutive pixels. - */ -typedef struct { - unsigned int w, h; - - /* Each scan is RLE_BYTES_PER_SCANLINE long and contains pairs of - * (start, length). */ - RLE_TYPE *scans; -} RleBitmap; - -/* Constructor */ -RleBitmap *rleCreate(unsigned int w, unsigned int h); - -/* Destructor */ -void rleDestroy(RleBitmap *rle); - -/* Clears 'rle' to "all transparent" */ -void rleClear(RleBitmap *rle); - -/* Encode 'pixels' into 'rle' and also return it. Pixels are either 0 or 1. This - * will create an RleBitmap of 'h' scanlines. */ -RleBitmap *rleEncode(RleBitmap *rle, unsigned char *pixels, unsigned int pixelsW, - unsigned int pixelsH); - -/* Rearranges the streaks to make it less frequent that they produce garbege when interpolated */ -void rleDistributeStreaks(RleBitmap *rle); - -/* Blits without scaling */ -void rleBlit(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX, - int blitY); - -/* Scaled blit */ -void rleBlitScale(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX, - int blitY, float scaleX, float scaleY); - -/* Inverted blit (upside down) */ -void rleBlitScaleInv(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, - int blitX, int blitY, float scaleX, float scaleY); - -#endif // __RLE_BITMAP_H__ -- 1.7.10.4 From 764f509aa3c0b6b3a9aadcba7b1efba6ac98cc83 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Sun, 15 May 2022 22:22:04 +0300 Subject: [PATCH 13/16] fixed DJGPP build, broken due to the PCI commit earlier today --- src/dos/dosutil.h | 4 ++-- src/dos/pci.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dos/dosutil.h b/src/dos/dosutil.h index 71af365..4e4c8c3 100644 --- a/src/dos/dosutil.h +++ b/src/dos/dosutil.h @@ -9,11 +9,11 @@ #define outp(p, v) outportb(p, v) #define outpw(p, v) outportw(p, v) -#define outpd(p, v) outportd(p, v) +#define outpd(p, v) outportl(p, v) #define inp(p) inportb(p) #define inpw(p) inportw(p) -#define inpd(p) inportd(p) +#define inpd(p) inportl(p) #endif #endif /* DOSUTIL_H_ */ diff --git a/src/dos/pci.c b/src/dos/pci.c index d3a1e7d..19a2e4d 100644 --- a/src/dos/pci.c +++ b/src/dos/pci.c @@ -19,7 +19,7 @@ along with this program. If not, see . #include #include #include -#include +#include "dosutil.h" #include "inttypes.h" #include "pci.h" #include "cdpmi.h" -- 1.7.10.4 From cfa71f2849ee3482ebe617931972657b6a69c930 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Sun, 15 May 2022 22:51:52 +0300 Subject: [PATCH 14/16] added code conventions section in the README --- .clang-format | 4 ++-- README.md | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/.clang-format b/.clang-format index c2b7d66..b54f2e9 100644 --- a/.clang-format +++ b/.clang-format @@ -1,3 +1,3 @@ UseTab: Always -IndentWidth: 8 -ColumnLimit: 100 +IndentWidth: 4 +ColumnLimit: 90 diff --git a/README.md b/README.md index 5db81a5..6d34b63 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,31 @@ Source structure - libs/imago/ image loading library (includes libpng, zlib, libjpeg) - libs/anim/ keyframe animation library +Coding style conventions +------------------------ +Very few style issues are mandated: + + - All filenames should be lowercase unless convention says otherwise + (`Makefile`, `README`, etc). + - All filenames under `src/` and of any tools necessary to build from MS-DOS + will have to use maximum 8.3 characters. + - Source code should be C89-compliant. Any compiler-specific features beyond + that will have to be ifdefed. + - Use tabs for indentation, where each tab is equivalent to 4 spaces. + +Everything else is left to the discretion of each individual, but also if +you're editing an existing file, try to match the style of the surrounding code. + +Some general style suggestions, which will not be enforced: + + - Don't use overly long names, abbreviate wherever it makes sense. + - Don't cast the return value of malloc. `void*` are converted implicitly, and + the cast hides forgetting to include `stdlib.h`. + - Preferably use lowercase with underscores for everything. + - Preferably use the K&R brace style if possible. + +This section will be expanded as necessary. + Building on DOS with Watcom --------------------------- Make sure you have Watcom or OpenWatcom installed, and the appropriate env-vars -- 1.7.10.4 From 223ecd536161ba06dd1d0f39ccf911b082742b92 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Mon, 16 May 2022 07:29:14 +0300 Subject: [PATCH 15/16] UNIX line endings on 2 files --- .clang-format | 32 ++++++++++++++- src/sball.h | 72 +++++++++++++++++----------------- src/scr/thunder.c | 112 ++++++++++++++++++++++++++--------------------------- 3 files changed, 123 insertions(+), 93 deletions(-) diff --git a/.clang-format b/.clang-format index b54f2e9..5788564 100644 --- a/.clang-format +++ b/.clang-format @@ -1,3 +1,33 @@ +UseCRLF: false UseTab: Always +TabWidth: 4 IndentWidth: 4 -ColumnLimit: 90 +ColumnLimit: 95 +SortIncludes: Never +SpaceBeforeParens: Never +BreakBeforeBraces: Custom +BraceWrapping: + AfterFunction: true +AlignAfterOpenBracket: DontAlign +AlignConsecutiveAssignments: None +AlignConsecutiveMacros: AcrossEmptyLines +AlignEscapedNewlines: DontAlign +AlignOperands: DontAlign +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortEnumsOnASingleLine: true +AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortLoopsOnASingleLine: true +BinPackArguments: true +BinPackParameters: true +BreakBeforeBinaryOperators: NonAssignment +BreakStringLiterals: true +SpaceInEmptyParentheses: false +IndentCaseLabels: false +ReflowComments: true +PointerAlignment: Right +SpacesInCStyleCastParentheses: false +SpaceAfterCStyleCast: false +PenaltyBreakAssignment: 1000 +SpaceBeforeParens: Never +SpaceAfterLogicalNot: false diff --git a/src/sball.h b/src/sball.h index e12b12c..e26d336 100644 --- a/src/sball.h +++ b/src/sball.h @@ -1,36 +1,36 @@ -#ifndef SBALL_H_ -#define SBALL_H_ - -enum { - SBALL_EV_NONE, - SBALL_EV_MOTION, - SBALL_EV_BUTTON -}; - -struct sball_event_motion { - int type; - int motion[6]; -}; - -struct sball_event_button { - int type; - int id; - int pressed; - unsigned int state; -}; - -typedef union sball_event { - int type; - struct sball_event_motion motion; - struct sball_event_button button; -} sball_event; - -int sball_init(void); -void sball_shutdown(void); - -int sball_getdev(void); - -int sball_pending(void); -int sball_getevent(sball_event *ev); - -#endif /* SBALL_H_ */ +#ifndef SBALL_H_ +#define SBALL_H_ + +enum { + SBALL_EV_NONE, + SBALL_EV_MOTION, + SBALL_EV_BUTTON +}; + +struct sball_event_motion { + int type; + int motion[6]; +}; + +struct sball_event_button { + int type; + int id; + int pressed; + unsigned int state; +}; + +typedef union sball_event { + int type; + struct sball_event_motion motion; + struct sball_event_button button; +} sball_event; + +int sball_init(void); +void sball_shutdown(void); + +int sball_getdev(void); + +int sball_pending(void); +int sball_getevent(sball_event *ev); + +#endif /* SBALL_H_ */ diff --git a/src/scr/thunder.c b/src/scr/thunder.c index 062eb57..3aa3b7e 100644 --- a/src/scr/thunder.c +++ b/src/scr/thunder.c @@ -377,62 +377,62 @@ unsigned char fog(float z) { return (unsigned char)ret; } -void sort(PointSprite *begin, PointSprite *end) { - PointSprite pivotValue; - size_t sz; - PointSprite *left, *right; - int leftCond, rightCond; - PointSprite tmp; - - sz = end - begin; - - if (sz < 2) return; /* already sorted */ - if (sz == 2) { - /* trivial case */ - if (begin[1] < begin[0]) { - tmp = begin[0]; - begin[0] = begin[1]; - begin[1] = tmp; - return; - } - } - - /* minimum 3 elements from now on */ - - /* choose a pivot near the middle, since we frequently sort already sorted arrays */ - pivotValue = begin[sz / 2]; - - left = begin; - right = end - 1; - - while (right > left) { - /* check if left and right elements meet the conditions */ - leftCond = pivotValue >= *left; - rightCond = pivotValue < *right; - - if (!leftCond && !rightCond) { - tmp = *left; - *left = *right; - *right = tmp; - left++; - right--; - } - else if (leftCond && rightCond) { - left++; - right--; - } - else if (leftCond) { - left++; - } - else { - right--; - } - } - - /* recursion */ - sort(begin, left); - sort(left, end); -} +void sort(PointSprite *begin, PointSprite *end) { + PointSprite pivotValue; + size_t sz; + PointSprite *left, *right; + int leftCond, rightCond; + PointSprite tmp; + + sz = end - begin; + + if (sz < 2) return; /* already sorted */ + if (sz == 2) { + /* trivial case */ + if (begin[1] < begin[0]) { + tmp = begin[0]; + begin[0] = begin[1]; + begin[1] = tmp; + return; + } + } + + /* minimum 3 elements from now on */ + + /* choose a pivot near the middle, since we frequently sort already sorted arrays */ + pivotValue = begin[sz / 2]; + + left = begin; + right = end - 1; + + while (right > left) { + /* check if left and right elements meet the conditions */ + leftCond = pivotValue >= *left; + rightCond = pivotValue < *right; + + if (!leftCond && !rightCond) { + tmp = *left; + *left = *right; + *right = tmp; + left++; + right--; + } + else if (leftCond && rightCond) { + left++; + right--; + } + else if (leftCond) { + left++; + } + else { + right--; + } + } + + /* recursion */ + sort(begin, left); + sort(left, end); +} void sortPointSprites() { sort(pointSprites, pointSprites + pointSpriteCount); -- 1.7.10.4 From c2a04aaa48da2a34742fce66a9f66fc93cb26861 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Mon, 16 May 2022 08:02:27 +0300 Subject: [PATCH 16/16] removed clang-format and clang_complete files from the repo --- .clang-format | 33 --------------------------------- .clang_complete | 4 ---- 2 files changed, 37 deletions(-) delete mode 100644 .clang-format delete mode 100644 .clang_complete diff --git a/.clang-format b/.clang-format deleted file mode 100644 index 5788564..0000000 --- a/.clang-format +++ /dev/null @@ -1,33 +0,0 @@ -UseCRLF: false -UseTab: Always -TabWidth: 4 -IndentWidth: 4 -ColumnLimit: 95 -SortIncludes: Never -SpaceBeforeParens: Never -BreakBeforeBraces: Custom -BraceWrapping: - AfterFunction: true -AlignAfterOpenBracket: DontAlign -AlignConsecutiveAssignments: None -AlignConsecutiveMacros: AcrossEmptyLines -AlignEscapedNewlines: DontAlign -AlignOperands: DontAlign -AllowAllArgumentsOnNextLine: false -AllowAllParametersOfDeclarationOnNextLine: false -AllowShortEnumsOnASingleLine: true -AllowShortIfStatementsOnASingleLine: WithoutElse -AllowShortLoopsOnASingleLine: true -BinPackArguments: true -BinPackParameters: true -BreakBeforeBinaryOperators: NonAssignment -BreakStringLiterals: true -SpaceInEmptyParentheses: false -IndentCaseLabels: false -ReflowComments: true -PointerAlignment: Right -SpacesInCStyleCastParentheses: false -SpaceAfterCStyleCast: false -PenaltyBreakAssignment: 1000 -SpaceBeforeParens: Never -SpaceAfterLogicalNot: false diff --git a/.clang_complete b/.clang_complete deleted file mode 100644 index e2c26a4..0000000 --- a/.clang_complete +++ /dev/null @@ -1,4 +0,0 @@ --x c --Isrc --Isrc/dos --Isrc/dos/stl -- 1.7.10.4