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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user