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

Merge branch 'master' of github.com:rzzzwilson/pymlac

This commit is contained in:
Ross Wilson 2023-01-22 15:19:28 +07:00
commit 89b90fd1c2
9 changed files with 614 additions and 0 deletions

3
imlac_sdl/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
test
hello_world
snapshot.png

8
imlac_sdl/NOTES Normal file
View File

@ -0,0 +1,8 @@
Linker options:
`sdl2-config --cflags --libs` -lSDL2 -lSDL2_mixer -lSDL2_image -lSDL2_ttf
eg:
gcc myProgram.c -o myProgram `sdl2-config --cflags --libs` -lSDL2 -lSDL2_mixer -lSDL2_image -lSDL2_ttf
g++ myProgram.cpp -o myProgram `sdl2-config --cflags --libs` -lSDL2 -lSDL2_mixer -lSDL2_image -lSDL2_ttf

View File

@ -0,0 +1,9 @@
CC=gcc
LDOPTS=`sdl2-config --cflags --libs` -lSDL2 -lSDL2_mixer -lSDL2_image -lSDL2_ttf
test: test.c Makefile
${CC} test.c -o test ${LDOPTS}
clean:
rm -Rf test snapshot.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

503
imlac_sdl/animation/test.c Normal file
View File

@ -0,0 +1,503 @@
/*****************************************************************************\
* 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>
#define WIDTH 1024
#define HEIGHT 1024
#define SAVEFILE "snapshot.png"
#define BKGND_RED 0
#define BKGND_GREEN 0
#define BKGND_BLUE 0
#define FOGND_RED 0
#define FOGND_GREEN 200
#define FOGND_BLUE 0
enum BEAM {OFF, ON}; // beam ON/OFF
enum OP {ABS, REL}; // absolute/relative moves
typedef struct
{
enum OP type;
enum BEAM beam;
int dx;
int dy;
} DLine;
#define DRAWLIST_SIZE 1000
DLine drawlist[DRAWLIST_SIZE];
// index of drawlist entry AFTER last instruction
unsigned int drawlist_end = 0;
//-------------------------
// Define some characters with relative moves
//-------------------------
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},
};
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},
};
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},
};
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},
};
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},
};
int len_Char_c = (sizeof(Char_c) / sizeof(Char_c[0]));
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, 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, 1},
{REL, ON, 0, 2},
{REL, ON, -1, 1}, //
{REL, ON, -4, 0},
{REL, ON, -1, -1},
{REL, ON, 0, -4},
};
int len_Saam = (sizeof(Saam) / sizeof(Saam[0]));
int Magnification = 4;
#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
make_drawlist(void)
{
static int x_origin = 10;
static int y_origin = 45;
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;
y_origin += deltay;
if (x_origin > 200 || x_origin < 10)
{
deltax = -deltax;
}
if (y_origin > 230 || y_origin < 10)
{
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, 58, 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;
}
bool
saveScreenshotBMP(char *savefile, SDL_Window* window, SDL_Renderer* renderer)
{
SDL_Surface* save_surface = NULL;
SDL_Surface* info_surface = NULL;
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());
}
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");
return false;
}
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());
free(pixels);
return false;
}
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);
if (save_surface == NULL)
{
printf("Couldn't create SDL_Surface from renderer pixel data. SDL_GetError() - %s\n", SDL_GetError());
free(pixels);
return false;
}
IMG_SavePNG(save_surface, SAVEFILE);
SDL_FreeSurface(save_surface);
save_surface = NULL;
}
free(pixels);
}
SDL_FreeSurface(info_surface);
info_surface = NULL;
}
return true;
}
int
main(int argc, char **argv)
{
// variables
bool quit = false;
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);
SDL_Window * window = SDL_CreateWindow("SDL2 line drawing",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
WIDTH, HEIGHT, SDL_WINDOW_BORDERLESS);
SDL_SetWindowIcon(window, icon);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
// handle events
while (!quit)
{
drawlist_end = make_drawlist();
// wait until next frame should be shown
SDL_Delay(time_left());
TimeNextFrame += TICK_INTERVAL;
// handle events, if any
SDL_PollEvent(&event);
switch (event.type)
{
case SDL_QUIT:
quit = true;
break;
case SDL_MOUSEBUTTONDOWN:
switch (event.button.button)
{
case SDL_BUTTON_LEFT:
quit = true;
break;
case SDL_BUTTON_MIDDLE:
snapshot = true;
break;
}
break;
}
// clear window to background colour
// SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_SetRenderDrawColor(renderer, BKGND_RED, BKGND_GREEN, BKGND_BLUE, 255);
SDL_RenderClear(renderer);
// set draw colour - foreground
// SDL_SetRenderDrawColor(renderer, 200, 255, 200, 255);
SDL_SetRenderDrawColor(renderer, FOGND_RED, FOGND_GREEN, FOGND_BLUE, 255);
// set beam at (0, 0)
unsigned int abs_x = 0;
unsigned int abs_y = 0;
// 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;
if (type == ABS)
{
new_x = dx;
new_y = dy;
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;
if (beam == ON)
{
SDL_RenderDrawLine(renderer, abs_x, abs_y, new_x, new_y);
}
}
abs_x = new_x;
abs_y = new_y;
}
// render window
SDL_RenderPresent(renderer);
if (snapshot)
{
saveScreenshotBMP(SAVEFILE, window, renderer);
snapshot = false;
}
}
// cleanup SDL
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}

View File

@ -0,0 +1,9 @@
CC=gcc
LDOPTS=`sdl2-config --cflags --libs` -lSDL2 -lSDL2_mixer -lSDL2_image -lSDL2_ttf
test: test.c Makefile
${CC} test.c -o test ${LDOPTS}
clean:
rm -Rf test

View File

@ -0,0 +1,64 @@
#include <stdbool.h>
#include <SDL.h>
#define WIDTH 1024
#define HEIGHT 1024
int main(int argc, char ** argv)
{
// variables
bool quit = false;
SDL_Event event;
// init SDL
SDL_Init(SDL_INIT_VIDEO);
SDL_Window * window = SDL_CreateWindow("SDL2 line drawing",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
WIDTH, HEIGHT, SDL_WINDOW_BORDERLESS);
SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);
// handle events
while (!quit)
{
SDL_Delay(10);
SDL_PollEvent(&event);
switch (event.type)
{
case SDL_QUIT:
quit = true;
break;
case SDL_MOUSEBUTTONUP:
switch (event.button.button)
{
case SDL_BUTTON_LEFT:
quit = true;
break;
}
break;
}
// clear window
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
// TODO rendering code goes here
SDL_SetRenderDrawColor(renderer, 200, 255, 200, 255);
SDL_RenderDrawLine(renderer, 0, 0, WIDTH, HEIGHT);
SDL_RenderDrawLine(renderer, WIDTH, 0, 0, HEIGHT);
// render window
SDL_RenderPresent(renderer);
}
// cleanup SDL
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}

View File

@ -0,0 +1,9 @@
CC=gcc
LDOPTS=`sdl2-config --cflags --libs` -lSDL2 -lSDL2_mixer -lSDL2_image -lSDL2_ttf
hello_world: hello_world.c Makefile
${CC} hello_world.c -o hello_world ${LDOPTS}
clean:
rm -Rf hello_world

View File

@ -0,0 +1,9 @@
#include <SDL.h>
int main(int argc, char *argv[])
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION,
"Smoke Test", "Hello, world!", NULL);
return 0;
}