From 6356f3b848b8ed580fcc42bbfe028f4a217f2d1c Mon Sep 17 00:00:00 2001 From: Ross Wilson Date: Sat, 16 Jul 2022 20:42:47 +0700 Subject: [PATCH] Added Thai numerals, fixed frame rate --- imlac_sdl/animation/test.c | 361 ++++++++++++++++++++++++++++--------- 1 file changed, 272 insertions(+), 89 deletions(-) diff --git a/imlac_sdl/animation/test.c b/imlac_sdl/animation/test.c index 7cdac2a..a236448 100644 --- a/imlac_sdl/animation/test.c +++ b/imlac_sdl/animation/test.c @@ -1,3 +1,15 @@ +/*****************************************************************************\ + * This is a test program to see how SDL2 can be used as the display for an + * Imlac simulator. + * + * The display uses the idea of a "drawlist" that is created between display + * writes. This is similar to how the Imlac main processor writes display + * code that is executed by the display processor. Some attempt has been made + * to lock display updates to a fixed rate. + * + * Draw some text, a pentagram and a few Thai numerals (0, 1, 2 and 3). +\******************************************************************************/ + #include #include #include @@ -8,8 +20,8 @@ #define SAVEFILE "snapshot.png" -enum BEAM {OFF, ON}; // beam ON/OFF -enum OP {ABS, REL}; // absolute/relative moves +enum BEAM {OFF, ON}; // beam ON/OFF +enum OP {ABS, REL}; // absolute/relative moves typedef struct { @@ -19,7 +31,7 @@ typedef struct int dy; } DLine; -#define DRAWLIST_SIZE 1000 +#define DRAWLIST_SIZE 1000 DLine drawlist[DRAWLIST_SIZE]; @@ -31,56 +43,159 @@ unsigned int drawlist_end = 0; //------------------------- DLine Char_I[] = {{REL, OFF, 0, -6}, - {REL, ON, 2, 0}, - {REL, OFF, -1, 0}, - {REL, ON, 0, 6}, - {REL, OFF, -1, 0}, - {REL, ON, 2, 0}, - }; + {REL, ON, 2, 0}, + {REL, OFF, -1, 0}, + {REL, ON, 0, 6}, + {REL, OFF, -1, 0}, + {REL, ON, 2, 0}, + }; int len_Char_I = (sizeof(Char_I) / sizeof(Char_I[0])); DLine Char_m[] = {{REL, ON, 0, -3}, - {REL, ON, 1, -1}, - {REL, ON, 1, 1}, - {REL, ON, 0, 1}, - {REL, OFF, 0, -1}, - {REL, ON, 1, -1}, - {REL, ON, 1, 1}, - {REL, ON, 0, 3}, - }; + {REL, ON, 1, -1}, + {REL, ON, 1, 1}, + {REL, ON, 0, 1}, + {REL, OFF, 0, -1}, + {REL, ON, 1, -1}, + {REL, ON, 1, 1}, + {REL, ON, 0, 3}, + }; int len_Char_m = (sizeof(Char_m) / sizeof(Char_m[0])); DLine Char_l[] = {{REL, OFF, 1, 0}, - {REL, ON, -1, -1}, - {REL, ON, 0, -5}, - }; + {REL, ON, -1, -1}, + {REL, ON, 0, -5}, + }; int len_Char_l = (sizeof(Char_l) / sizeof(Char_l[0])); DLine Char_a[] = {{REL, OFF, 0, -1}, - {REL, ON, 0, -2}, - {REL, ON, 1, -1}, - {REL, ON, 2, 0}, - {REL, ON, 1, 1}, - {REL, ON, 0, 3}, - {REL, OFF, -4, -1}, - {REL, ON, 1, 1}, - {REL, ON, 1, 0}, - {REL, ON, 2, -2}, - }; + {REL, ON, 0, -2}, + {REL, ON, 1, -1}, + {REL, ON, 2, 0}, + {REL, ON, 1, 1}, + {REL, ON, 0, 3}, + {REL, OFF, -4, -1}, + {REL, ON, 1, 1}, + {REL, ON, 1, 0}, + {REL, ON, 2, -2}, + }; int len_Char_a = (sizeof(Char_a) / sizeof(Char_a[0])); DLine Char_c[] = {{REL, OFF, 3, -1}, - {REL, ON, -1, 1}, - {REL, ON, -1, 0}, - {REL, ON, -1, -1}, - {REL, ON, 0, -2}, - {REL, ON, 1, -1}, - {REL, ON, 1, 0}, - {REL, ON, 1, 1}, - }; + {REL, ON, -1, 1}, + {REL, ON, -1, 0}, + {REL, ON, -1, -1}, + {REL, ON, 0, -2}, + {REL, ON, 1, -1}, + {REL, ON, 1, 0}, + {REL, ON, 1, 1}, + }; int len_Char_c = (sizeof(Char_c) / sizeof(Char_c[0])); -int Magnification = 4; +DLine Pentagram[] = {{REL, ON, 60, 0}, + {REL, ON, -50, 30}, + {REL, ON, 20, -50}, + {REL, ON, 20, 50}, + {REL, ON, -50, -30}, + }; +int len_Pentagram = (sizeof(Pentagram) / sizeof(Pentagram[0])); + +DLine Suun[] = {{REL, OFF, 1, 0}, + {REL, ON, -1, -1}, + {REL, ON, 0, -1}, + {REL, ON, 1, -1}, + {REL, ON, 2, 0}, + {REL, ON, 1, 1}, + {REL, ON, 0, 1}, + {REL, ON, -1, 1}, + {REL, ON, -2, 0}, + }; +int len_Suun = (sizeof(Suun) / sizeof(Suun[0])); + +DLine Neung[] = {{REL, OFF, 2, 0}, + {REL, ON, -1, -1}, + {REL, ON, 1, -1}, + {REL, ON, 1, 1}, + {REL, ON, -1, 1}, + {REL, ON, -1, 0}, + {REL, ON, -1, -1}, + {REL, ON, 0, -1}, + {REL, ON, 1, -1}, + {REL, ON, 2, 0}, + {REL, ON, 1, 1}, + {REL, ON, 0, 1}, + {REL, ON, -1, 1}, + }; +int len_Neung = (sizeof(Neung) / sizeof(Neung[0])); + +DLine Soong[] = {{REL, OFF, 1, -1}, + {REL, ON, 1, 0}, + {REL, ON, 0, 1}, + {REL, ON, -1, 0}, + {REL, ON, -1, -1}, + {REL, ON, 0, -1}, + {REL, ON, 1, -1}, + {REL, ON, 1, 0}, + {REL, ON, 1, 1}, + {REL, ON, 0, 1}, + {REL, OFF, 0, -1}, + {REL, ON, 1, -1}, + {REL, ON, 1, 0}, + {REL, ON, 1, 1}, + {REL, ON, 0, 2}, + {REL, ON, -1, 1}, + }; +int len_Soong = (sizeof(Soong) / sizeof(Soong[0])); + +DLine Saam[] = {{REL, OFF, 1, -1}, + {REL, ON, 1, 0}, + {REL, ON, 0, 1}, + {REL, ON, -1, 0}, + {REL, ON, -1, -1}, + {REL, ON, 0, -1}, + {REL, ON, 1, -1}, + {REL, ON, 1, 0}, + {REL, ON, 1, 1}, + {REL, ON, 0, 1}, + {REL, OFF, 0, -1}, + {REL, ON, 1, -1}, + {REL, ON, 1, 0}, + {REL, ON, 1, 1}, + {REL, ON, 0, 2}, + {REL, ON, -1, 1}, // + {REL, ON, -6, 0}, + {REL, ON, -1, -1}, + {REL, ON, 0, -4}, + }; +int len_Saam = (sizeof(Saam) / sizeof(Saam[0])); + +int Magnification = 2; + + +#define TICK_INTERVAL 25 // roughly 40 frames/sec +//#define TICK_INTERVAL 17 // roughly 60 frames/sec +unsigned int TimeNextFrame; + + +void +imlac_error(char *msg) +{ + printf("%s\n", msg); + exit(1); +} + + +unsigned int +time_left(void) +{ + unsigned int now; + + now = SDL_GetTicks(); + if (TimeNextFrame <= now) + return 0; + else + return TimeNextFrame - now; +} unsigned int @@ -91,42 +206,54 @@ make_drawlist(void) static int deltax = 2; static int deltay = 1; + // whare to place drawlist instructions in "drawlist" drawlist_end = 0; + // draw rext: "Imlac" DLine dline = {ABS, OFF, x_origin, y_origin}; memcpy(&drawlist[drawlist_end], &dline, sizeof(dline)); ++drawlist_end; + if (drawlist_end >= DRAWLIST_SIZE) imlac_error("Draw list overflow"); memcpy(&drawlist[drawlist_end], Char_I, sizeof(Char_I)); drawlist_end += len_Char_I; + if (drawlist_end >= DRAWLIST_SIZE) imlac_error("Draw list overflow"); DLine dline2 = {ABS, OFF, x_origin+4, y_origin}; memcpy(&drawlist[drawlist_end], &dline2, sizeof(dline2)); ++drawlist_end; + if (drawlist_end >= DRAWLIST_SIZE) imlac_error("Draw list overflow"); memcpy(&drawlist[drawlist_end], Char_m, sizeof(Char_m)); drawlist_end += len_Char_m; + if (drawlist_end >= DRAWLIST_SIZE) imlac_error("Draw list overflow"); DLine dline3 = {ABS, OFF, x_origin+10, y_origin}; memcpy(&drawlist[drawlist_end], &dline3, sizeof(dline3)); ++drawlist_end; + if (drawlist_end >= DRAWLIST_SIZE) imlac_error("Draw list overflow"); memcpy(&drawlist[drawlist_end], Char_l, sizeof(Char_l)); drawlist_end += len_Char_l; + if (drawlist_end >= DRAWLIST_SIZE) imlac_error("Draw list overflow"); DLine dline4 = {ABS, OFF, x_origin+13, y_origin}; memcpy(&drawlist[drawlist_end], &dline4, sizeof(dline4)); ++drawlist_end; + if (drawlist_end >= DRAWLIST_SIZE) imlac_error("Draw list overflow"); memcpy(&drawlist[drawlist_end], Char_a, sizeof(Char_a)); drawlist_end += len_Char_a; + if (drawlist_end >= DRAWLIST_SIZE) imlac_error("Draw list overflow"); DLine dline5 = {ABS, OFF, x_origin+19, y_origin}; memcpy(&drawlist[drawlist_end], &dline5, sizeof(dline5)); ++drawlist_end; + if (drawlist_end >= DRAWLIST_SIZE) imlac_error("Draw list overflow"); memcpy(&drawlist[drawlist_end], Char_c, sizeof(Char_c)); drawlist_end += len_Char_c; + if (drawlist_end >= DRAWLIST_SIZE) imlac_error("Draw list overflow"); // move origins x_origin += deltax; @@ -134,14 +261,64 @@ make_drawlist(void) if (x_origin > 200 || x_origin < 10) { - deltax = -deltax; + deltax = -deltax; } if (y_origin > 230 || y_origin < 10) { - deltay = -deltay; + deltay = -deltay; } + // draw a pentagram + DLine dline6 = {ABS, OFF, 50, 120}; + memcpy(&drawlist[drawlist_end], &dline6, sizeof(dline6)); + ++drawlist_end; + if (drawlist_end >= DRAWLIST_SIZE) imlac_error("Draw list overflow"); + + memcpy(&drawlist[drawlist_end], Pentagram, sizeof(Pentagram)); + drawlist_end += len_Pentagram; + if (drawlist_end >= DRAWLIST_SIZE) imlac_error("Draw list overflow"); + + // draw "suun" + DLine dline10 = {ABS, OFF, 38, 50}; + memcpy(&drawlist[drawlist_end], &dline10, sizeof(dline10)); + ++drawlist_end; + if (drawlist_end >= DRAWLIST_SIZE) imlac_error("Draw list overflow"); + + memcpy(&drawlist[drawlist_end], Suun, sizeof(Suun)); + drawlist_end += len_Suun; + if (drawlist_end >= DRAWLIST_SIZE) imlac_error("Draw list overflow"); + + // draw "neung" + DLine dline9 = {ABS, OFF, 44, 50}; + memcpy(&drawlist[drawlist_end], &dline9, sizeof(dline9)); + ++drawlist_end; + if (drawlist_end >= DRAWLIST_SIZE) imlac_error("Draw list overflow"); + + memcpy(&drawlist[drawlist_end], Neung, sizeof(Neung)); + drawlist_end += len_Neung; + if (drawlist_end >= DRAWLIST_SIZE) imlac_error("Draw list overflow"); + + // draw "soong" + DLine dline7 = {ABS, OFF, 50, 50}; + memcpy(&drawlist[drawlist_end], &dline7, sizeof(dline7)); + ++drawlist_end; + if (drawlist_end >= DRAWLIST_SIZE) imlac_error("Draw list overflow"); + + memcpy(&drawlist[drawlist_end], Soong, sizeof(Soong)); + drawlist_end += len_Soong; + if (drawlist_end >= DRAWLIST_SIZE) imlac_error("Draw list overflow"); + + // draw "saam" + DLine dline8 = {ABS, OFF, 60, 50}; + memcpy(&drawlist[drawlist_end], &dline8, sizeof(dline8)); + ++drawlist_end; + if (drawlist_end >= DRAWLIST_SIZE) imlac_error("Draw list overflow"); + + memcpy(&drawlist[drawlist_end], Saam, sizeof(Saam)); + drawlist_end += len_Saam; + if (drawlist_end >= DRAWLIST_SIZE) imlac_error("Draw list overflow"); + return drawlist_end; } @@ -155,35 +332,35 @@ saveScreenshotBMP(char *savefile, SDL_Window* window, SDL_Renderer* renderer) info_surface = SDL_GetWindowSurface(window); if (info_surface == NULL) { - printf("Failed to create info surface from window in saveScreenshotBMP(string), SDL_GetError() - %s\n", SDL_GetError()); + printf("Failed to create info surface from window in saveScreenshotBMP(string), SDL_GetError() - %s\n", SDL_GetError()); } else { unsigned char * pixels = malloc(info_surface->w * info_surface->h * info_surface->format->BytesPerPixel); if (pixels == 0) - { - printf("Unable to allocate memory for screenshot pixel data buffer!\n"); + { + printf("Unable to allocate memory for screenshot pixel data buffer!\n"); return false; } - else - { + else + { if (SDL_RenderReadPixels(renderer, &info_surface->clip_rect, info_surface->format->format, - pixels, info_surface->w * info_surface->format->BytesPerPixel) != 0) - { - printf("Failed to read pixel data from SDL_Renderer object. SDL_GetError() - %s\n", SDL_GetError()); + pixels, info_surface->w * info_surface->format->BytesPerPixel) != 0) + { + printf("Failed to read pixel data from SDL_Renderer object. SDL_GetError() - %s\n", SDL_GetError()); free(pixels); return false; } - else - { + else + { save_surface = SDL_CreateRGBSurfaceFrom(pixels, info_surface->w, info_surface->h, - info_surface->format->BitsPerPixel, - info_surface->w * info_surface->format->BytesPerPixel, - info_surface->format->Rmask, info_surface->format->Gmask, - info_surface->format->Bmask, info_surface->format->Amask); + info_surface->format->BitsPerPixel, + info_surface->w * info_surface->format->BytesPerPixel, + info_surface->format->Rmask, info_surface->format->Gmask, + info_surface->format->Bmask, info_surface->format->Amask); if (save_surface == NULL) - { - printf("Couldn't create SDL_Surface from renderer pixel data. SDL_GetError() - %s\n", SDL_GetError()); + { + printf("Couldn't create SDL_Surface from renderer pixel data. SDL_GetError() - %s\n", SDL_GetError()); free(pixels); return false; } @@ -210,6 +387,8 @@ main(int argc, char **argv) bool snapshot = false; SDL_Event event; SDL_Surface* icon = IMG_Load("icon.png"); + + TimeNextFrame = SDL_GetTicks() + TICK_INTERVAL; // init SDL SDL_Init(SDL_INIT_VIDEO); @@ -225,7 +404,11 @@ main(int argc, char **argv) { drawlist_end = make_drawlist(); - SDL_Delay(30); + // wait until next frame should be shown + SDL_Delay(time_left()); + TimeNextFrame += TICK_INTERVAL; + +// SDL_Delay(30); SDL_PollEvent(&event); switch (event.type) @@ -240,7 +423,7 @@ main(int argc, char **argv) quit = true; break; case SDL_BUTTON_MIDDLE: - snapshot = true; + snapshot = true; break; } break; @@ -253,53 +436,53 @@ main(int argc, char **argv) // set draw colour SDL_SetRenderDrawColor(renderer, 200, 255, 200, 255); - // set beam at (0, 0) - unsigned int abs_x = 0; - unsigned int abs_y = 0; + // set beam at (0, 0) + unsigned int abs_x = 0; + unsigned int abs_y = 0; - // draw the drawlist + // draw the drawlist for (int dindex = 0; dindex < drawlist_end; ++dindex) - { + { enum OP type = drawlist[dindex].type; enum BEAM beam = drawlist[dindex].beam; int dx = drawlist[dindex].dx * Magnification; int dy = drawlist[dindex].dy * Magnification; - unsigned int new_x; - unsigned int new_y; + unsigned int new_x; + unsigned int new_y; - if (type == ABS) - { - new_x = dx; - new_y = dy; + if (type == ABS) + { + new_x = dx; + new_y = dy; - if (beam == ON) - { + if (beam == ON) + { SDL_RenderDrawLine(renderer, abs_x, abs_y, new_x, new_y); - } - } - else - { - new_x = abs_x + dx; - new_y = abs_y + dy; + } + } + else + { + new_x = abs_x + dx; + new_y = abs_y + dy; - if (beam == ON) - { + if (beam == ON) + { SDL_RenderDrawLine(renderer, abs_x, abs_y, new_x, new_y); - } - } + } + } - abs_x = new_x; - abs_y = new_y; - } + abs_x = new_x; + abs_y = new_y; + } // render window SDL_RenderPresent(renderer); - if (snapshot) - { + if (snapshot) + { saveScreenshotBMP(SAVEFILE, window, renderer); - snapshot = false; - } + snapshot = false; + } } // cleanup SDL