1
0
mirror of https://github.com/rzzzwilson/pymlac.git synced 2025-06-10 09:32:41 +00:00

Added Thai numerals, fixed frame rate

This commit is contained in:
Ross Wilson
2022-07-16 20:42:47 +07:00
parent e3d32891f0
commit 6356f3b848

View File

@@ -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 <stdbool.h>
#include <SDL.h>
#include <SDL_image.h>
@@ -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