27#ifndef ALLEGRO_UNSTABLE
28#define ALLEGRO_UNSTABLE
38#include <allegro5/allegro.h>
39#include <allegro5/allegro_primitives.h>
40#include <allegro5/allegro_image.h>
41#include <allegro5/allegro_font.h>
42#include <allegro5/allegro_ttf.h>
43#include <allegro5/allegro_audio.h>
44#include <allegro5/allegro_acodec.h>
57_Static_assert(
KEY_A == ALLEGRO_KEY_A,
"KEY_A");
58_Static_assert(
KEY_0 == ALLEGRO_KEY_0,
"KEY_0");
59_Static_assert(
KEY_F1 == ALLEGRO_KEY_F1,
"KEY_F1");
60_Static_assert(
KEY_ESC == ALLEGRO_KEY_ESCAPE,
"KEY_ESC");
61_Static_assert(
KEY_BACKSPACE == ALLEGRO_KEY_BACKSPACE,
"KEY_BACKSPACE");
62_Static_assert(
KEY_TAB == ALLEGRO_KEY_TAB,
"KEY_TAB");
63_Static_assert(
KEY_ENTER == ALLEGRO_KEY_ENTER,
"KEY_ENTER");
64_Static_assert(
KEY_SPACE == ALLEGRO_KEY_SPACE,
"KEY_SPACE");
65_Static_assert(
KEY_INSERT == ALLEGRO_KEY_INSERT,
"KEY_INSERT");
66_Static_assert(
KEY_DEL == ALLEGRO_KEY_DELETE,
"KEY_DEL");
67_Static_assert(
KEY_HOME == ALLEGRO_KEY_HOME,
"KEY_HOME");
68_Static_assert(
KEY_END == ALLEGRO_KEY_END,
"KEY_END");
69_Static_assert(
KEY_PGUP == ALLEGRO_KEY_PGUP,
"KEY_PGUP");
70_Static_assert(
KEY_PGDN == ALLEGRO_KEY_PGDN,
"KEY_PGDN");
71_Static_assert(
KEY_LEFT == ALLEGRO_KEY_LEFT,
"KEY_LEFT");
72_Static_assert(
KEY_RIGHT == ALLEGRO_KEY_RIGHT,
"KEY_RIGHT");
73_Static_assert(
KEY_UP == ALLEGRO_KEY_UP,
"KEY_UP");
74_Static_assert(
KEY_DOWN == ALLEGRO_KEY_DOWN,
"KEY_DOWN");
75_Static_assert(
KEY_ENTER_PAD == ALLEGRO_KEY_PAD_ENTER,
"KEY_ENTER_PAD");
76_Static_assert(
KEY_LSHIFT == ALLEGRO_KEY_LSHIFT,
"KEY_LSHIFT");
77_Static_assert(
KEY_ALTGR == ALLEGRO_KEY_ALTGR,
"KEY_ALTGR");
78_Static_assert(
KEY_MAX == ALLEGRO_KEY_MAX,
"KEY_MAX");
81#define A4_MASK_COLOR 0x00FF00FF
92 ALLEGRO_LOCKED_REGION*
lock;
103#define A4_SAMPLE_IDS 16
116#define A4P(b) ((A4_BMP*)((b)->priv))
147#define A4_KEYBUF_SIZE 64
161#define A4_MAX_TIMERS 16
187 if (!path)
return NULL;
188 char* p = strdup(path);
191 for (
char* c = p; *c; c++)
192 if (*c ==
'\\') *c =
'/';
193 if (access(p, F_OK) == 0)
return p;
195 size_t len = strlen(p);
196 char* out = malloc(len + 3);
200 char* work = strdup(p);
205 int absolute = (p[0] ==
'/');
206 if (absolute) strcpy(out,
"/");
207 for (
char* comp = strtok_r(work,
"/", &save); comp; comp = strtok_r(NULL,
"/", &save)) {
208 const char* dir = out[0] ? out :
".";
209 char candidate[4096];
210 snprintf(candidate,
sizeof(candidate),
"%s%s%s", out, (out[0] && out[strlen(out) - 1] !=
'/') ?
"/" :
"", comp);
211 const char* chosen = comp;
212 char found[256] =
"";
213 if (access(candidate, F_OK) != 0) {
214 DIR* d = opendir(dir);
216 struct dirent* ent = NULL;
217 while ((ent = readdir(d)) != NULL) {
218 if (strcasecmp(ent->d_name, comp) == 0) {
219 snprintf(found,
sizeof(found),
"%s", ent->d_name);
225 if (found[0]) chosen = found;
227 size_t need = strlen(out) + strlen(chosen) + 2;
228 if (need > len + 3) {
229 char* bigger = realloc(out, need + 16);
234 if (out[0] && out[strlen(out) - 1] !=
'/') strcat(out,
"/");
241 for (
char* c = p; *c; c++)
242 if (*c ==
'/') *c =
'\\';
249 char* r = malloc(n + 1);
259 uint32_t c = (uint32_t)color;
260 uint32_t a = c >> 24;
262 return (a << 24) | (c & 0x00FFFFFFu);
266 if ((p >> 24) == 255)
return (
int)(p & 0x00FFFFFFu);
270static ALLEGRO_COLOR
_a4_rgba(
int color,
int alpha) {
271 uint32_t c = (uint32_t)color;
272 return al_map_rgba((
unsigned char)((c >> 16) & 0xFF), (
unsigned char)((c >> 8) & 0xFF), (
unsigned char)(c & 0xFF), (
unsigned char)alpha);
276#define A4_BLEND_COPY 0
277#define A4_BLEND_ALPHA 1
278#define A4_BLEND_FADE 2
292static ALLEGRO_COLOR
_a4_prim(
int color,
int* blend) {
295 float a = n > 0 ? (float)(n + 1) / 256.0f : 0.0f;
296 if (a > 1.0f) a = 1.0f;
297 if ((((uint32_t)color) & 0x00FFFFFFu) == 0 && n > 0 && n < 255) {
299 float bias = 1.0f / 255.0f;
300 return al_map_rgba_f(bias, bias, bias, (
float)n / 256.0f);
303 uint32_t c = (uint32_t)color;
304 return al_map_rgba_f((
float)((c >> 16) & 0xFF) / 255.0f, (
float)((c >> 8) & 0xFF) / 255.0f, (
float)(c & 0xFF) / 255.0f, a);
311 return ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF);
319 return (
int)(((uint32_t)(a & 0xFF) << 24) | (uint32_t)
makecol(r, g, b));
327 return (
int)((((uint32_t)c) >> 16) & 0xFF);
331 return (
int)((((uint32_t)c) >> 8) & 0xFF);
335 return (
int)(((uint32_t)c) & 0xFF);
345 if (!b || !b->
priv)
return;
348 al_unlock_bitmap(p->
bmp);
357 p->
lock = al_lock_bitmap(p->
bmp, ALLEGRO_PIXEL_FORMAT_ARGB_8888, ALLEGRO_LOCK_READWRITE);
364 if (!b || !b->
priv)
return FALSE;
368 if (al_get_target_bitmap() != p->
bmp) al_set_target_bitmap(p->
bmp);
381 if (!b || !b->
priv)
return NULL;
385 if (!masked)
return p->
bmp;
388 p->
masked = al_create_bitmap(b->
w, b->
h);
392 al_store_state(&state, ALLEGRO_STATE_TARGET_BITMAP | ALLEGRO_STATE_BLENDER);
393 al_set_target_bitmap(p->
masked);
394 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
395 al_draw_bitmap(p->
bmp, 0, 0, 0);
396 al_convert_mask_to_alpha(p->
masked, al_map_rgb(255, 0, 255));
397 al_restore_state(&state);
404 if (!abmp)
return NULL;
412 al_destroy_bitmap(abmp);
417 b->
w = al_get_bitmap_width(abmp);
418 b->
h = al_get_bitmap_height(abmp);
426 al_set_separate_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
431 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
437 al_set_separate_blender(ALLEGRO_DEST_MINUS_SRC, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ZERO, ALLEGRO_ONE);
447 ALLEGRO_COLOR c =
_a4_prim(color, &blend);
459#define A4_BATCH_MAX 6144
468 if (al_get_target_bitmap() != t) al_set_target_bitmap(t);
492static void _a4_vertex(ALLEGRO_VERTEX* v,
float x,
float y, ALLEGRO_COLOR c) {
502static void _a4_quad(
BITMAP* b,
float x1,
float y1,
float x2,
float y2,
float x3,
float y3,
float x4,
float y4,
int color) {
504 ALLEGRO_COLOR c =
_a4_prim(color, &blend);
515static void _a4_box(
BITMAP* b,
float l,
float t,
float r,
float bt,
int color) {
516 _a4_quad(b, l, t, r, t, r, bt, l, bt, color);
523 case ALLEGRO_EVENT_KEY_DOWN:
524 if (ev->keyboard.keycode > 0 && ev->keyboard.keycode <
KEY_MAX)
key[ev->keyboard.keycode] = 1;
526 case ALLEGRO_EVENT_KEY_UP:
527 if (ev->keyboard.keycode > 0 && ev->keyboard.keycode <
KEY_MAX)
key[ev->keyboard.keycode] = 0;
529 case ALLEGRO_EVENT_KEY_CHAR: {
530 int ascii = (ev->keyboard.unichar > 0 && ev->keyboard.unichar < 256) ? ev->keyboard.unichar : 0;
531 int k = (ev->keyboard.keycode << 8) | ascii;
540 case ALLEGRO_EVENT_MOUSE_AXES:
541 case ALLEGRO_EVENT_MOUSE_WARPED:
550 case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN:
551 if (ev->mouse.button >= 1 && ev->mouse.button <= 3)
mouse_b |= (1 << (ev->mouse.button - 1));
552 if (ev->mouse.button == 1) {
560 case ALLEGRO_EVENT_MOUSE_BUTTON_UP:
561 if (ev->mouse.button >= 1 && ev->mouse.button <= 3)
mouse_b &= ~(1 << (ev->mouse.button - 1));
563 case ALLEGRO_EVENT_DISPLAY_SWITCH_OUT:
564 memset((
void*)
key, 0,
sizeof(
key));
567 case ALLEGRO_EVENT_DISPLAY_CLOSE:
578 while (!al_get_thread_should_stop(thr)) {
587 while (!al_get_thread_should_stop(thr)) {
588 double now = al_get_time();
601 if (left < wait) wait = left;
604 for (
int i = 0; i < nb_due; i++) due[i]();
605 if (wait > 0.0) al_rest(wait);
616 al_init_primitives_addon();
617 al_init_image_addon();
618 al_init_font_addon();
620 memset((
void*)
key, 0,
sizeof(
key));
637 f->
f = al_create_builtin_font();
671 if (
font->f) al_destroy_font(
font->f);
694 return strcasecmp(s1, s2);
698 if (depth != 32)
n_log(
LOG_DEBUG,
"color depth %d requested, using 32", depth);
707 float dw = (float)al_get_display_width(
a4_display);
708 float dh = (float)al_get_display_height(
a4_display);
709 float sx = dw / (float)
screen->w;
710 float sy = dh / (float)
screen->h;
724 int flags = ALLEGRO_WINDOWED;
726 al_set_new_display_flags(flags);
766 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
767 if (
a4_off_x > 0.0f ||
a4_off_y > 0.0f) al_clear_to_color(al_map_rgb(0, 0, 0));
791 if (!al_is_keyboard_installed() && !al_install_keyboard())
return -1;
792 al_register_event_source(
a4_input_queue, al_get_keyboard_event_source());
848 if (!al_is_mouse_installed() && !al_install_mouse())
return -1;
849 al_register_event_source(
a4_input_queue, al_get_mouse_event_source());
893 if (!proc || speed <= 0)
return -1;
909 a4_timers[i].next = al_get_time() + period;
930 al_rest((
double)ms / 1000.0);
936 if (width <= 0 || height <= 0)
return NULL;
937 al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_ANY_32_WITH_ALPHA);
938 ALLEGRO_BITMAP* abmp = al_create_bitmap(width, height);
944 al_store_state(&state, ALLEGRO_STATE_TARGET_BITMAP);
945 al_set_target_bitmap(abmp);
946 al_clear_to_color(al_map_rgb(0, 0, 0));
947 al_restore_state(&state);
970 if (p->
bmp) al_destroy_bitmap(p->
bmp);
980 if (!path)
return NULL;
981 al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_ANY_32_WITH_ALPHA);
982 ALLEGRO_BITMAP* abmp = al_load_bitmap_flags(path, ALLEGRO_NO_PREMULTIPLIED_ALPHA);
993 if (!bmp || !filename)
return -1;
995 return al_save_bitmap(filename,
A4P(bmp)->bmp) ? 0 : -1;
1029static void _a4_draw_region(
BITMAP* source,
BITMAP* dest,
int masked,
float sx,
float sy,
float sw,
float sh,
float dx,
float dy,
float dw,
float dh,
int flags) {
1030 if (!source || !dest || sw <= 0 || sh <= 0 || dw <= 0 || dh <= 0)
return;
1031 ALLEGRO_BITMAP* src =
_a4_source(source, masked);
1032 ALLEGRO_BITMAP* tmp = NULL;
1033 if (source == dest) {
1034 tmp = al_create_bitmap((
int)sw, (
int)sh);
1036 al_set_target_bitmap(tmp);
1037 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
1038 al_draw_bitmap_region(src, sx, sy, sw, sh, 0, 0, 0);
1048 al_draw_scaled_bitmap(src, sx, sy, sw, sh, dx, dy, dw, dh, flags);
1050 if (tmp) al_destroy_bitmap(tmp);
1054void blit(
BITMAP* source,
BITMAP* dest,
int source_x,
int source_y,
int dest_x,
int dest_y,
int width,
int height) {
1055 _a4_draw_region(source, dest, FALSE, (
float)source_x, (
float)source_y, (
float)width, (
float)height, (
float)dest_x, (
float)dest_y, (
float)width, (
float)height, 0);
1059 _a4_draw_region(source, dest, TRUE, (
float)source_x, (
float)source_y, (
float)width, (
float)height, (
float)dest_x, (
float)dest_y, (
float)width, (
float)height, 0);
1062void stretch_blit(
BITMAP* source,
BITMAP* dest,
int source_x,
int source_y,
int source_width,
int source_height,
int dest_x,
int dest_y,
int dest_width,
int dest_height) {
1063 _a4_draw_region(source, dest, FALSE, (
float)source_x, (
float)source_y, (
float)source_width, (
float)source_height, (
float)dest_x, (
float)dest_y, (
float)dest_width, (
float)dest_height, 0);
1067 _a4_draw_region(source, dest, TRUE, (
float)source_x, (
float)source_y, (
float)source_w, (
float)source_h, (
float)dest_x, (
float)dest_y, (
float)dest_w, (
float)dest_h, 0);
1071 if (!sprite)
return;
1072 _a4_draw_region(sprite, bmp, TRUE, 0, 0, (
float)sprite->
w, (
float)sprite->
h, (
float)x, (
float)y, (
float)sprite->
w, (
float)sprite->
h, flags);
1080 _a4_sprite(bmp, sprite, x, y, ALLEGRO_FLIP_HORIZONTAL);
1084 _a4_sprite(bmp, sprite, x, y, ALLEGRO_FLIP_VERTICAL);
1088 _a4_sprite(bmp, sprite, x, y, ALLEGRO_FLIP_HORIZONTAL | ALLEGRO_FLIP_VERTICAL);
1092 if (!sprite)
return;
1093 _a4_draw_region(sprite, bmp, TRUE, 0, 0, (
float)sprite->
w, (
float)sprite->
h, (
float)x, (
float)y, (
float)w, (
float)h, 0);
1097 if (!sprite || !bmp || sprite == bmp)
return;
1104 al_draw_bitmap(src, (
float)x, (
float)y, 0);
1106 al_draw_tinted_bitmap(src, al_map_rgba_f(1, 1, 1, (
float)
a4_trans_alpha / 255.0f), (
float)x, (
float)y, 0);
1111 if (!sprite || !bmp || sprite == bmp)
return;
1112 ALLEGRO_BITMAP* src =
_a4_source(sprite, TRUE);
1115 float radians = (float)(
fixtof(angle) * ALLEGRO_PI / 128.0);
1116 float s = (float)
fixtof(scale);
1117 al_draw_scaled_rotated_bitmap(src, cx, cy, x, y, s, s, radians, 0);
1122 if (!sprite)
return;
1123 _a4_rotated(bmp, sprite, (
float)x + (
float)sprite->
w / 2.0f, (
float)y + (
float)sprite->
h / 2.0f, (
float)sprite->
w / 2.0f, (
float)sprite->
h / 2.0f, angle,
itofix(1));
1127 if (!sprite)
return;
1128 float s = (float)
fixtof(scale);
1129 _a4_rotated(bmp, sprite, (
float)x + (
float)sprite->
w * s / 2.0f, (
float)y + (
float)sprite->
h * s / 2.0f, (
float)sprite->
w / 2.0f, (
float)sprite->
h / 2.0f, angle, scale);
1133 _a4_rotated(bmp, sprite, (
float)x, (
float)y, (
float)cx, (
float)cy, angle,
itofix(1));
1137 _a4_rotated(bmp, sprite, (
float)x, (
float)y, (
float)cx, (
float)cy, angle, scale);
1166 if (!bmp || x < 0 || y < 0 || x >= bmp->
w || y >= bmp->
h)
return;
1168 if (!bmp->
priv)
return;
1169 _a4_box(bmp, (
float)x, (
float)y, (
float)x + 1.0f, (
float)y + 1.0f, color);
1173 ALLEGRO_LOCKED_REGION* lr =
_a4_lock(bmp);
1175 uint32_t*
row = (uint32_t*)((
char*)lr->data + (ptrdiff_t)y * lr->pitch);
1177 A4P(bmp)->masked_dirty = 1;
1182 if (!bmp || x < 0 || y < 0 || x >= bmp->
w || y >= bmp->
h)
return -1;
1183 const ALLEGRO_LOCKED_REGION* lr =
_a4_lock(bmp);
1185 const uint32_t*
row = (
const uint32_t*)((
const char*)lr->data + (ptrdiff_t)y * lr->pitch);
1189void line(
BITMAP* bmp,
int x1,
int y1,
int x2,
int y2,
int color) {
1190 if (!bmp || !bmp->
priv)
return;
1193 float ax = (float)x1 + 0.5f, ay = (
float)y1 + 0.5f;
1194 float bx = (float)x2 + 0.5f, by = (
float)y2 + 0.5f;
1195 float dx = bx - ax, dy = by - ay;
1196 float len = sqrtf(dx * dx + dy * dy);
1198 _a4_box(bmp, (
float)x1, (
float)y1, (
float)x1 + 1.0f, (
float)y1 + 1.0f, color);
1200 float ux = dx / len * 0.5f, uy = dy / len * 0.5f;
1205 _a4_quad(bmp, ax - uy, ay + ux, bx - uy, by + ux, bx + uy, by - ux, ax + uy, ay - ux, color);
1211 rectfill(bmp, x1, y, x2, y, color);
1215 rectfill(bmp, x, y1, x, y2, color);
1218void rect(
BITMAP* bmp,
int x1,
int y1,
int x2,
int y2,
int color) {
1219 if (!bmp || !bmp->
priv)
return;
1230 _a4_box(bmp, (
float)x1, (
float)y1, (
float)x2 + 1.0f, (
float)y1 + 1.0f, color);
1231 if (y2 > y1)
_a4_box(bmp, (
float)x1, (
float)y2, (
float)x2 + 1.0f, (
float)y2 + 1.0f, color);
1233 _a4_box(bmp, (
float)x1, (
float)y1 + 1.0f, (
float)x1 + 1.0f, (
float)y2, color);
1234 if (x2 > x1)
_a4_box(bmp, (
float)x2, (
float)y1 + 1.0f, (
float)x2 + 1.0f, (
float)y2, color);
1240 if (!bmp || !bmp->
priv)
return;
1251 _a4_box(bmp, (
float)x1, (
float)y1, (
float)x2 + 1.0f, (
float)y2 + 1.0f, color);
1257 al_draw_circle((
float)x + 0.5f, (
float)y + 0.5f, (
float)radius,
_a4_prim_color(color), 1.0f);
1263 al_draw_filled_circle((
float)x + 0.5f, (
float)y + 0.5f, (
float)radius + 0.5f,
_a4_prim_color(color));
1269 al_draw_ellipse((
float)x + 0.5f, (
float)y + 0.5f, (
float)rx, (
float)ry,
_a4_prim_color(color), 1.0f);
1275 al_draw_filled_ellipse((
float)x + 0.5f, (
float)y + 0.5f, (
float)rx + 0.5f, (
float)ry + 0.5f,
_a4_prim_color(color));
1279void triangle(
BITMAP* bmp,
int x1,
int y1,
int x2,
int y2,
int x3,
int y3,
int color) {
1280 if (!bmp || !bmp->
priv)
return;
1282 ALLEGRO_COLOR c =
_a4_prim(color, &blend);
1284 _a4_vertex(&v[0], (
float)x1 + 0.5f, (
float)y1 + 0.5f, c);
1285 _a4_vertex(&v[1], (
float)x2 + 0.5f, (
float)y2 + 0.5f, c);
1286 _a4_vertex(&v[2], (
float)x3 + 0.5f, (
float)y3 + 0.5f, c);
1297 if (!bmp || y < 0 || y >= bmp->
h)
return 0;
1298 ALLEGRO_LOCKED_REGION* lr =
_a4_lock(bmp);
1300 A4P(bmp)->masked_dirty = 1;
1302 return (uintptr_t)((
char*)lr->data + (ptrdiff_t)y * lr->pitch);
1306 if (!bmp || y < 0 || y >= bmp->
h)
return 0;
1307 ALLEGRO_LOCKED_REGION* lr =
_a4_lock(bmp);
1309 return (uintptr_t)((
char*)lr->data + (ptrdiff_t)y * lr->pitch);
1319 if (f && f->
f)
return f->
f;
1325 return (af && str) ? al_get_text_width(af, str) : 0;
1330 return af ? al_get_font_line_height(af) : 0;
1334static void _a4_text(
BITMAP* bmp,
const FONT* f,
const char* s,
int x,
int y,
int color,
int bg,
int align) {
1336 if (!af || !s)
return;
1337 int w = al_get_text_width(af, s);
1338 int left = align == 1 ? x - w / 2 : (align == 2 ? x - w : x);
1342 rectfill(bmp, left, y, left + w - 1, y + al_get_font_line_height(af) - 1, bg);
1347 al_set_separate_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
1348 ALLEGRO_COLOR c = (color == -1) ? al_map_rgb(255, 255, 255) :
_a4_rgba(color, 255);
1349 al_draw_text(af, c, (
float)left, (
float)y, ALLEGRO_ALIGN_LEFT, s);
1354 _a4_text(bmp, f, s, x, y, color, bg, 0);
1358 _a4_text(bmp, f, s, x, y, color, bg, 1);
1362 _a4_text(bmp, f, s, x, y, color, bg, 2);
1366#define A4_TEXTPRINTF(align) \
1369 va_start(ap, format); \
1370 vsnprintf(buf, sizeof(buf), format, ap); \
1372 _a4_text(bmp, f, buf, x, y, color, bg, align);
1375#pragma GCC diagnostic push
1376#pragma GCC diagnostic ignored "-Wformat-nonliteral"
1378#pragma GCC diagnostic pop
1382#pragma GCC diagnostic push
1383#pragma GCC diagnostic ignored "-Wformat-nonliteral"
1385#pragma GCC diagnostic pop
1389#pragma GCC diagnostic push
1390#pragma GCC diagnostic ignored "-Wformat-nonliteral"
1392#pragma GCC diagnostic pop
1397 if (!path)
return NULL;
1398 ALLEGRO_FONT* af = al_load_ttf_font(path, points, smooth ==
ALLEGTTF_NOSMOOTH ? ALLEGRO_TTF_MONOCHROME : 0);
1409 al_destroy_font(af);
1421 if (!f || f ==
font)
return;
1422 if (f->
f) al_destroy_font(f->
f);
1431 va_start(ap, format);
1432#pragma GCC diagnostic push
1433#pragma GCC diagnostic ignored "-Wformat-nonliteral"
1434 vsnprintf(msg,
sizeof(msg), format, ap);
1435#pragma GCC diagnostic pop
1437 fprintf(stderr,
"%s\n", msg);
1441 ALLEGRO_FONT* af =
font->f;
1442 int lh = al_get_font_line_height(af) + 4;
1443 int maxw =
screen->w - 60;
1446 for (
char* p = msg; *p && nb < 128;) {
1447 char* end = strchr(p,
'\n');
1448 size_t n = end ? (size_t)(end - p) : strlen(p);
1449 while (n > 0 && nb < 128) {
1453 size_t c = take <
sizeof(tmp) - 1 ? take :
sizeof(tmp) - 1;
1456 if (al_get_text_width(af, tmp) <= maxw || take <= 1)
break;
1460 if (!lines[nb])
break;
1466 if (n == 0 && end == p) {
1473 for (
int i = 0; i < nb; i++) {
1474 int w = lines[i] ? al_get_text_width(af, lines[i]) : 0;
1477 const char* hint =
"Press a key or click to continue";
1478 if (al_get_text_width(af, hint) > bw) bw = al_get_text_width(af, hint);
1480 int bh = (nb + 2) * lh + 30;
1481 int bx = (
screen->w - bw) / 2;
1482 int by = (
screen->h - bh) / 2;
1492 for (
int i = 0; i < nb; i++) {
1508 for (
int i = 0; i <
KEY_MAX; i++)
key[i] = 0;
1517 for (
int i = 0; i < nb; i++) free(lines[i]);
1520int alert(
const char* s1,
const char* s2,
const char* s3,
const char* b1,
const char* b2,
int c1,
int c2) {
1521 const char* lines[3] = {s1, s2, s3};
1523 for (
int i = 0; i < 3; i++)
1524 if (lines[i]) fprintf(stderr,
"%s\n", lines[i]);
1527 ALLEGRO_FONT* af =
font->f;
1528 int lh = al_get_font_line_height(af) + 6;
1529 int nb_buttons = b2 ? 2 : 1;
1530 const char* labels[2] = {b1 ? b1 :
"OK", b2};
1532 for (
int i = 0; i < 3; i++)
1533 if (lines[i] && al_get_text_width(af, lines[i]) > bw) bw = al_get_text_width(af, lines[i]);
1535 for (
int i = 0; i < nb_buttons; i++)
1536 if (al_get_text_width(af, labels[i]) + 24 > btn_w) btn_w = al_get_text_width(af, labels[i]) + 24;
1537 if (nb_buttons * btn_w + 20 > bw) bw = nb_buttons * btn_w + 20;
1539 int bh = 5 * lh + 30;
1540 int bx = (
screen->w - bw) / 2, by = (
screen->h - bh) / 2;
1541 int btn_y = by + bh - lh - 20;
1543 for (
int i = 0; i < nb_buttons; i++) btn_x[i] = bx + (bw - nb_buttons * btn_w - (nb_buttons - 1) * 20) / 2 + i * (btn_w + 20);
1560 choice = nb_buttons;
1564 for (
int i = 0; i < nb_buttons; i++)
1568 for (
int i = 0; i < 3; i++)
1570 for (
int i = 0; i < nb_buttons; i++) {
1572 rect(
screen, btn_x[i], btn_y, btn_x[i] + btn_w - 1, btn_y + lh + 5,
makecol(200, 200, 220));
1578 int ascii = k & 0xFF;
1579 if (c1 && ascii && (ascii == c1 || ascii == (c1 ^ 0x20))) choice = 1;
1580 if (nb_buttons > 1 && c2 && ascii && (ascii == c2 || ascii == (c2 ^ 0x20))) choice = 2;
1582 if ((k >> 8) ==
KEY_ESC) choice = nb_buttons;
1585 for (
int i = 0; i < nb_buttons; i++)
1586 if (cx >= btn_x[i] && cx < btn_x[i] + btn_w && cy >= btn_y && cy < btn_y + lh + 6) choice = i + 1;
1613 if (!al_install_audio()) {
1617 al_init_acodec_addon();
1618 if (!al_reserve_samples(32)) {
1630 al_uninstall_audio();
1637 if (!path)
return NULL;
1638 ALLEGRO_SAMPLE* s = al_load_sample(path);
1648 al_destroy_sample(s);
1660 al_stop_sample(&s->
ids[i]);
1669 if (spl->
spl) al_destroy_sample(spl->
spl);
1678 float p = ((float)pan - 128.0f) / 127.0f;
1679 return p < -1.0f ? -1.0f : (p > 1.0f ? 1.0f : p);
1685 ALLEGRO_SAMPLE_ID id;
1686 if (!al_play_sample(s->
spl,
_a4_gain(vol),
_a4_pan(pan), (
float)freq / 1000.0f, loop ? ALLEGRO_PLAYMODE_LOOP : ALLEGRO_PLAYMODE_ONCE, &
id))
return -1;
1698 if (!s->
used[i])
continue;
1699 ALLEGRO_SAMPLE_INSTANCE* inst = al_lock_sample_id(&s->
ids[i]);
1701 al_set_sample_instance_gain(inst,
_a4_gain(vol));
1702 al_set_sample_instance_pan(inst,
_a4_pan(pan));
1703 al_set_sample_instance_speed(inst, (
float)freq / 1000.0f);
1704 al_set_sample_instance_playmode(inst, loop ? ALLEGRO_PLAYMODE_LOOP : ALLEGRO_PLAYMODE_ONCE);
1706 al_unlock_sample_id(&s->
ids[i]);
1712typedef void* (*fs_new_settings_f)(void);
1715typedef void* (*fs_new_synth_f)(
void*);
1717typedef void* (*fs_new_player_f)(
void*);
1723typedef void* (*fs_set_log_function_f)(int,
void*,
void*);
1750 ALLEGRO_AUDIO_STREAM* stream;
1751 ALLEGRO_EVENT_QUEUE* queue;
1752 ALLEGRO_THREAD* thread;
1753 ALLEGRO_MUTEX* mutex;
1756#define A4_MIDI_RATE 44100
1757#define A4_MIDI_FRAG 1024
1760 static const char* names[] = {
1761#if defined(__windows__)
1762 "libfluidsynth-3.dll",
"libfluidsynth-2.dll",
"fluidsynth.dll"
1763#elif defined(__APPLE__)
1764 "libfluidsynth.3.dylib",
"libfluidsynth.dylib"
1766 "libfluidsynth.so.3",
"libfluidsynth.so.2",
"libfluidsynth.so"
1769 for (
size_t i = 0; i <
sizeof(names) /
sizeof(names[0]); i++) {
1779 if (!p || fsize !=
sizeof(p))
return FALSE;
1780 memcpy(fptr, &p, fsize);
1784#define A4_SYM(field, name) ok = ok && _a4_fluidsynth_sym(a4_fs.lib, name, &a4_fs.field, sizeof(a4_fs.field))
1787 static const char* candidates[] = {
1788 "/usr/share/sounds/sf2/default-GM.sf2",
1789 "/usr/share/sounds/sf2/FluidR3_GM.sf2",
1790 "/usr/share/sounds/sf2/TimGM6mb.sf2",
1791 "/usr/share/soundfonts/default.sf2",
1792 "/usr/share/soundfonts/FluidR3_GM.sf2",
1793 "/usr/local/share/soundfonts/default.sf2",
1795 const char* env = getenv(
"NILOREA_SOUNDFONT");
1796 if (env && env[0])
return env;
1797 for (
size_t i = 0; i <
sizeof(candidates) /
sizeof(candidates[0]); i++) {
1798 FILE* f = fopen(candidates[i],
"rb");
1801 return candidates[i];
1809 while (!al_get_thread_should_stop(thr)) {
1811 if (!al_wait_for_event_timed(
a4_fs.queue, &ev, 0.05f))
continue;
1812 if (ev.type != ALLEGRO_EVENT_AUDIO_STREAM_FRAGMENT)
continue;
1813 float* buf = al_get_audio_stream_fragment(
a4_fs.stream);
1815 al_lock_mutex(
a4_fs.mutex);
1820 al_unlock_mutex(
a4_fs.mutex);
1821 al_set_audio_stream_fragment(
a4_fs.stream, buf);
1833 n_log(
LOG_NOTICE,
"no General MIDI soundfont found (set NILOREA_SOUNDFONT), MIDI is silent");
1842 A4_SYM(new_settings,
"new_fluid_settings");
1843 A4_SYM(setnum,
"fluid_settings_setnum");
1844 A4_SYM(setstr,
"fluid_settings_setstr");
1845 A4_SYM(new_synth,
"new_fluid_synth");
1846 A4_SYM(sfload,
"fluid_synth_sfload");
1847 A4_SYM(new_player,
"new_fluid_player");
1848 A4_SYM(player_add,
"fluid_player_add");
1849 A4_SYM(player_play,
"fluid_player_play");
1850 A4_SYM(player_stop,
"fluid_player_stop");
1851 A4_SYM(player_set_loop,
"fluid_player_set_loop");
1852 A4_SYM(write_float,
"fluid_synth_write_float");
1853 A4_SYM(system_reset,
"fluid_synth_system_reset");
1854 A4_SYM(delete_player,
"delete_fluid_player");
1855 A4_SYM(delete_synth,
"delete_fluid_synth");
1856 A4_SYM(delete_settings,
"delete_fluid_settings");
1858 n_log(
LOG_NOTICE,
"libfluidsynth lacks an expected symbol, MIDI is silent");
1864 for (
int level = 2; level <= 4; level++)
a4_fs.set_log_function(level, NULL, NULL);
1867 if (!
a4_fs.settings)
return FALSE;
1869 a4_fs.setnum(
a4_fs.settings,
"synth.gain", 0.5);
1871 a4_fs.setstr(
a4_fs.settings,
"player.timing-source",
"sample");
1873 if (!
a4_fs.synth)
return FALSE;
1878 a4_fs.mutex = al_create_mutex();
1879 a4_fs.queue = al_create_event_queue();
1883 if (!al_attach_audio_stream_to_mixer(
a4_fs.stream, al_get_default_mixer()))
return FALSE;
1884 al_register_event_source(
a4_fs.queue, al_get_audio_stream_event_source(
a4_fs.stream));
1886 if (!
a4_fs.thread)
return FALSE;
1887 al_start_thread(
a4_fs.thread);
1888 n_log(
LOG_DEBUG,
"MIDI through fluidsynth with soundfont %s", sf);
1897 a4_fs.player = NULL;
1900 a4_fs.current = NULL;
1906 al_destroy_thread(
a4_fs.thread);
1907 a4_fs.thread = NULL;
1911 al_destroy_audio_stream(
a4_fs.stream);
1912 a4_fs.stream = NULL;
1915 al_destroy_event_queue(
a4_fs.queue);
1919 al_destroy_mutex(
a4_fs.mutex);
1925 a4_fs.settings = NULL;
1932 if (!path)
return NULL;
1933 FILE* f = fopen(path,
"rb");
1956 al_lock_mutex(
a4_fs.mutex);
1961 a4_fs.player_set_loop(
a4_fs.player, loop ? -1 : 1);
1963 a4_fs.current = midi;
1965 al_unlock_mutex(
a4_fs.mutex);
1970 if (!
a4_fs.ok)
return;
1971 al_lock_mutex(
a4_fs.mutex);
1973 al_unlock_mutex(
a4_fs.mutex);
1984 if (!
a4_fs.ok)
return;
1985 al_lock_mutex(
a4_fs.mutex);
1987 al_unlock_mutex(
a4_fs.mutex);
1991 if (!
a4_fs.ok)
return;
1992 al_lock_mutex(
a4_fs.mutex);
1994 al_unlock_mutex(
a4_fs.mutex);
1998 if (digi_volume >= 0)
a4_digi_volume = digi_volume > 255 ? 255 : digi_volume;
1999 if (midi_volume >= 0)
a4_midi_volume = midi_volume > 255 ? 255 : midi_volume;
2005int gfx_mode(
int mode,
int w,
int h,
int v_w,
int v_h,
int depth,
double r,
double g,
double b,
double a) {
2013 double scale = (r > 1.0 || g > 1.0 || b > 1.0) ? 1.0 : 255.0;
2028 if (str) memset(str, c, len);
2033 if (!keybuf || !cur || max <= 0)
return 0;
2034 if (*cur < 0) *cur = 0;
2035 if (*cur > max - 1) *cur = max - 1;
2039 int ascii = k & 0xFF;
2042 if (*cur > 0) (*cur)--;
2043 keybuf[*cur] =
'\0';
2044 }
else if (ascii >= 32 && ascii < 127 && *cur < max - 1) {
2045 keybuf[(*cur)++] = (char)ascii;
2046 keybuf[*cur] =
'\0';
2073 if (!strcasecmp(v,
"center") || !strcasecmp(v,
"centre") || !strcasecmp(v,
"middle"))
return 1;
2074 if (is_h && !strcasecmp(v,
"right"))
return 2;
2075 if (!is_h && !strcasecmp(v,
"bottom"))
return 2;
2082 if (!b)
return NULL;
2085 al_clear_to_color(al_map_rgba(0, 0, 0, 0));
2087 al_draw_bitmap(s, 0, 0, 0);
2089 al_set_separate_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE, ALLEGRO_ADD, ALLEGRO_ZERO, ALLEGRO_ONE);
2090 al_draw_tinted_bitmap(s, al_map_rgba_f(0.35f, 0.35f, 0.35f, 1.0f), 0, 0, 0);
2095 if (!file || !section)
return NULL;
2097 if (!path)
return NULL;
2098 ALLEGRO_CONFIG* cfg = al_load_config_file(path);
2108 al_destroy_config(cfg);
2111 const char* bg = al_get_config_value(cfg, section,
"bg");
2117 snprintf(k,
sizeof(k),
"item%d", count);
2118 if (!al_get_config_value(cfg, section, k))
break;
2122 if (!menu->
items) count = 0;
2123 for (
int i = 0; i < count; i++) {
2126 snprintf(k,
sizeof(k),
"item%d", i);
2127 snprintf(sec,
sizeof(sec),
"%s.%s", section, al_get_config_value(cfg, section, k));
2129 const char* v = al_get_config_value(cfg, sec,
"x");
2130 it->
x = v ? atoi(v) : 0;
2131 v = al_get_config_value(cfg, sec,
"y");
2132 it->
y = v ? atoi(v) : 0;
2135 v = al_get_config_value(cfg, sec,
"image");
2138 v = al_get_config_value(cfg, sec,
"sound");
2142 al_destroy_config(cfg);
2147 if (!menu || item < 0 || item >= menu->
nb_items)
return NULL;
2154 float sx = menu->
bg ? (float)buf->
w / (
float)menu->
bg->
w : 1.0f;
2155 float sy = menu->
bg ? (float)buf->
h / (
float)menu->
bg->
h : 1.0f;
2156 float iw = it->
image ? (float)it->
image->
w : 0.0f;
2157 float ih = it->
image ? (float)it->
image->
h : 0.0f;
2158 float ix = (float)it->
x;
2159 float iy = (float)it->
y;
2165 if (it->
h_align == 1) ix -= iw / 2.0f;
2166 if (it->
h_align == 2) ix -= iw;
2167 if (it->
v_align == 1) iy -= ih / 2.0f;
2168 if (it->
v_align == 0) iy -= ih;
2176 for (
int i = 0; i < menu->
nb_items; i++) {
2179 if ((
float)mx >= x && (
float)mx < x + w && (
float)my >= y && (
float)my < y + h)
return i;
2185 if (!menu || !buf || menu->
nb_items <= 0)
return -1;
2196 while (chosen == -2) {
2210 if (k ==
KEY_ESC) chosen = -1;
2226 for (
int i = 0; i < menu->
nb_items; i++) {
2234 al_draw_scaled_bitmap(s, 0, 0, (
float)img->
w, (
float)img->
h, x, y, w, h, 0);
2253 if (!menu)
return NULL;
2254 for (
int i = 0; i < menu->
nb_items; i++) {
static void type(N_GUI_CTX *gui, const char *s)
Type a whole string into whatever has focus.
static const char * row(N_GUI_TREE *tree, int index)
the text of a visible row, "" past the end
void * priv
private state of the compatibility layer
unsigned char ** line
always NULL: direct line access goes through bmp_write_line()
int makeacol32(int r, int g, int b, int a)
make a colour with alpha
#define KEY_RIGHT
key code
void allegro_gl_unset_allegro_mode(void)
no-op
void stretch_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height)
copy and scale a rectangle
int install_mouse(void)
start the input thread for the mouse
SAMPLE * load_sample(const char *filename)
load a WAV, OGG, FLAC or VOC file
uintptr_t bmp_write_line(BITMAP *bmp, int y)
lock the bitmap and return the address of line y, 32 bit ARGB pixels
FONT * load_ttf_font_mem(const char *filename, int points, int smooth)
same as load_ttf_font()
void draw_sprite_h_flip(BITMAP *bmp, BITMAP *sprite, int x, int y)
draw a sprite mirrored horizontally
#define MODE_STD
gfx_status() value: a non OpenGL mode
void destroy_bitmap(BITMAP *bmp)
free a bitmap
void set_trans_blender(int r, int g, int b, int a)
blend with a constant opacity a (0-255), r, g and b are ignored
void allegro_exit(void)
shut everything down
int is_memory_bitmap(BITMAP *bmp)
always FALSE: pixels are reached through bmp_write_line()
char allegro_error[256]
last error message, as in Allegro 4
BITMAP * create_video_bitmap(int width, int height)
same as create_bitmap()
int set_close_button_callback(void(*proc)(void))
call proc when the window close button is pressed
int a4_get_keyboard(char *keybuf, int *cur, int flags, int max)
read the typed keys into keybuf at *cur (printable ASCII, backspace erases), keeping it nul terminate...
int poll_mouse(void)
no-op, input is updated by a thread
uintptr_t bmp_read_line(BITMAP *bmp, int y)
lock the bitmap and return the address of line y, 32 bit ARGB pixels
#define KEY_BACKSPACE
key code
void bmp_unwrite_line(BITMAP *bmp)
no-op, the bitmap is unlocked when next drawn with the GPU
int install_int_ex(void(*proc)(void), long speed)
call proc every speed timer ticks, from the timer thread
BITMAP * create_bitmap(int width, int height)
create a w x h bitmap
int install_sound(int digi, int midi, const char *cfg_path)
start the audio, cfg_path is ignored
void destroy_sample(SAMPLE *spl)
free a sample, stopping it
int bitmap_mask_color(BITMAP *bmp)
the mask colour, magenta
int getr(int c)
red component
int readkey(void)
wait for a key: (scancode << 8) | ascii
void line(BITMAP *bmp, int x1, int y1, int x2, int y2, int color)
draw a line
volatile char key[227]
TRUE while the key is held.
int save_bitmap(const char *filename, BITMAP *bmp, const RGB *pal)
save a bitmap
void draw_sprite_vh_flip(BITMAP *bmp, BITMAP *sprite, int x, int y)
draw a sprite mirrored both ways
void textout_right_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int bg)
draw a string ending at x
#define GFX_AUTODETECT_FULLSCREEN
fullscreen
int ustricmp(const char *s1, const char *s2)
case insensitive string compare
FONT * font
the default 8x8 font, valid after allegro_init()
void clear_keybuf(void)
empty the readkey() buffer
void set_uformat(int type)
no-op, kept for source compatibility
void textprintf_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int bg, const char *format,...)
draw a formatted string
void drawing_mode(int mode, BITMAP *pattern, int x_anchor, int y_anchor)
set the drawing mode of primitives, pattern arguments are ignored
#define TIMERS_PER_SECOND
ticks per second of install_int_ex() speeds
int makecol32(int r, int g, int b)
make an opaque colour
#define itofix(x)
int to fixed
#define DIGI_NONE
no digital sound
volatile int mouse_x
mouse x in screen coordinates
#define DRAW_MODE_SOLID
drawing mode: plain copy
int poll_keyboard(void)
no-op, input is updated by a thread
volatile int key_shifts
modifier flags, unused
void ellipse(BITMAP *bmp, int x, int y, int rx, int ry, int color)
draw an ellipse outline
void rotate_scaled_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale)
rotate and scale a sprite around its centre
void destroy_midi(MIDI *midi)
free a MIDI song, stopping it if it plays
void remove_int(void(*proc)(void))
stop calling proc
int makeacol(int r, int g, int b, int a)
make a colour with alpha
#define SET
gfx_status() action: set the status (same value as n_common.h's)
void solid_mode(void)
same as drawing_mode(DRAW_MODE_SOLID, ...)
BITMAP * screen
the screen, valid after set_gfx_mode()
void textout_centre_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int bg)
draw a string centred on x
void set_alpha_blender(void)
blend with the alpha channel of the source colour or sprite
#define KEY_ALTGR
key code
#define GFX_OPENGL_WINDOWED
AllegroGL windowed: screen is shown on allegro_gl_flip() only.
#define DRAW_MODE_TRANS
drawing mode: blend with the current blender
#define KEY_MAX
number of entries in key[]
void masked_stretch_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int source_w, int source_h, int dest_x, int dest_y, int dest_w, int dest_h)
copy and scale a rectangle, skipping mask colour pixels
void get_mouse_mickeys(int *mickeyx, int *mickeyy)
movement since the last call
#define GFX_OPENGL
AllegroGL, windowed.
int install_keyboard(void)
start the input thread for the keyboard
BITMAP * create_bitmap_ex(int depth, int width, int height)
same as create_bitmap(), depth is ignored
void vline(BITMAP *bmp, int x, int y1, int y2, int color)
draw a vertical line
void allegro_message(const char *format,...)
show a message: a box over the screen, or stderr without a display
int set_gfx_mode(int card, int w, int h, int v_w, int v_h)
open a display of w x h pixels, or close it with GFX_TEXT
void position_mouse(int x, int y)
move the mouse pointer
void set_volume(int digi_volume, int midi_volume)
set the volumes (0-255), a negative value leaves one unchanged
int allegro_init(void)
init the layer and Allegro 5
int install_timer(void)
no-op, timers are always available
void circle(BITMAP *bmp, int x, int y, int radius, int color)
draw a circle outline
int lexMenuRun(LexMenu *menu, BITMAP *buf)
run the menu, drawing into buf: the chosen item index, -1 on escape
void adjust_sample(const SAMPLE *spl, int vol, int pan, int freq, int loop)
change the settings of the playing instances of a sample
void clear_bitmap(BITMAP *bmp)
clear to black
void set_window_title(const char *name)
set the window title
int makecol(int r, int g, int b)
make an opaque colour
int play_sample(const SAMPLE *spl, int vol, int pan, int freq, int loop)
play a sample: vol and pan 0-255, freq 1000 = normal speed
void blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
copy a rectangle
void allegro_gl_set_allegro_mode(void)
no-op
int bitmap_color_depth(BITMAP *bmp)
always 32
#define ALLEGTTF_NOSMOOTH
no anti aliasing
void masked_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
copy a rectangle, skipping mask colour pixels
#define fixtof(x)
fixed to double
void ellipsefill(BITMAP *bmp, int x, int y, int rx, int ry, int color)
draw a filled ellipse
int get_color_depth(void)
return the color depth (always 32)
void stop_sample(const SAMPLE *spl)
stop every playing instance of a sample
#define KEY_SPACE
key code
int install_int(void(*proc)(void), int speed)
call proc every speed milliseconds, from the timer thread
void textprintf_centre_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int bg, const char *format,...)
draw a formatted string centred on x
int32_t fixed
16.16 fixed point number
int getb(int c)
blue component
int gfx_mode(int mode, int w, int h, int v_w, int v_h, int depth, double r, double g, double b, double a)
set the color depth and the graphics mode in one go, clearing the screen to (r,g,b),...
#define GFX_TEXT
leave graphics mode
void destroy_font(FONT *f)
free a font loaded with load_ttf_font()
void bmp_select(BITMAP *bmp)
no-op
LexMenu * lexMenuDestroy(LexMenu *menu)
free a menu, returns NULL
volatile int mouse_b
button flags: 1 left, 2 right, 4 middle
void remove_sound(void)
stop the audio
void midi_pause(void)
pause the MIDI song
void pivot_scaled_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale)
rotate and scale a sprite around (cx,cy) in the sprite, drawn at (x,y)
int install_allegro_gl(void)
no-op, the layer always uses Allegro 5's own driver
MIDI * load_midi(const char *filename)
load a MIDI file
int getg(int c)
green component
void fill_str(char *str, int c, size_t len)
fill len bytes of str with c
void draw_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y)
draw a sprite
void rotate_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle)
rotate a sprite around its centre, angle in 256ths of a turn, clockwise
#define KEY_INSERT
key code
int alert(const char *s1, const char *s2, const char *s3, const char *b1, const char *b2, int c1, int c2)
a box with up to three lines and one or two buttons (b2 may be NULL), chosen with the mouse,...
#define KEY_ENTER_PAD
key code
volatile int mouse_y
mouse y in screen coordinates
void midi_resume(void)
resume the MIDI song
void textprintf_right_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int bg, const char *format,...)
draw a formatted string ending at x
int keypressed(void)
TRUE if a key is waiting in the readkey() buffer.
uint32_t _a4_pixel_from_color(int color)
store a colour as it is kept in a bitmap (opaque when its alpha byte is 0)
BITMAP * load_bitmap(const char *filename, RGB *pal)
load a BMP, PCX, TGA, PNG or JPG file, pal is ignored
void stretch_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int w, int h)
draw a sprite scaled to w x h
void putpixel(BITMAP *bmp, int x, int y, int color)
write a pixel
int gfx_status(int action, int value)
with GET, MODE_OGL when the current mode is an AllegroGL one, else MODE_STD
#define KEY_ENTER
key code
void set_color_depth(int depth)
set the color depth, only 32 is honoured
void clear_to_color(BITMAP *bmp, int color)
clear to a colour
void rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color)
draw a filled rectangle
void hline(BITMAP *bmp, int x1, int y, int x2, int color)
draw a horizontal line
#define GFX_DIRECTX
DirectX fullscreen, mapped to fullscreen.
void triangle(BITMAP *bmp, int x1, int y1, int x2, int y2, int x3, int y3, int color)
draw a filled triangle
FONT * load_ttf_font(const char *filename, int points, int smooth)
load a TrueType font at the given pixel size
void pivot_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle)
rotate a sprite around (cx,cy) in the sprite, drawn at (x,y)
#define MODE_OGL
gfx_status() value: an AllegroGL mode
int text_height(const FONT *f)
height of the font in pixels
void rest(unsigned int ms)
sleep ms milliseconds
int text_length(const FONT *f, const char *str)
width of str in pixels
int geta(int c)
alpha component, 255 for an opaque colour
void circlefill(BITMAP *bmp, int x, int y, int radius, int color)
draw a filled circle
void textout_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int bg)
draw a string
LexMenu * lexLoadMenuFromFile(const char *file, const char *section)
load menu section from INI file file, NULL on error
#define ALLEGRO_ERROR_SIZE
size of the allegro_error buffer
#define MSEC_TO_TIMER(x)
convert milliseconds to timer ticks
void draw_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y)
draw a sprite mirrored vertically
volatile int mouse_z
mouse wheel position
void draw_trans_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y)
draw a sprite with the current blender (set_alpha_blender / set_trans_blender)
#define KEY_LSHIFT
key code
void show_mouse(BITMAP *bmp)
show the system cursor (bmp != NULL) or hide it (NULL)
void clear(BITMAP *bmp)
clear to black
int getpixel(BITMAP *bmp, int x, int y)
read a pixel, -1 outside the bitmap
void allegro_gl_flip(void)
show the screen bitmap
void stop_midi(void)
stop the MIDI song
BITMAP * lexMenuGetBitmap(LexMenu *menu, int item, int state)
the image of item item in state state, NULL if there is none
#define LEX_MENU_OVER
item state for lexMenuGetBitmap(): under the pointer
void rect(BITMAP *bmp, int x1, int y1, int x2, int y2, int color)
draw a rectangle outline
#define GFX_OPENGL_FULLSCREEN
AllegroGL fullscreen: screen is shown on allegro_gl_flip() only.
int play_midi(MIDI *midi, int loop)
play a MIDI song, replacing the current one, NULL stops
palette entry, unused in 32 bit mode
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
#define Free(__ptr)
Free Handler to get errors.
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
#define LOG_DEBUG
debug-level messages
#define LOG_ERR
error conditions
#define LOG_NOTICE
normal but significant condition
N_MODULE * n_module_open(const char *path)
Open a shared library.
int n_module_close(N_MODULE **module)
Close a library and free its handle.
void * n_module_symbol(N_MODULE *module, const char *name)
Find a symbol in an opened library.
static int _a4_target(BITMAP *b)
static ALLEGRO_THREAD * a4_timer_thread
static float _a4_pan(int pan)
static ALLEGRO_VERTEX a4_batch[6144]
static int a4_screen_dirty
static void _a4_box(BITMAP *b, float l, float t, float r, float bt, int color)
void *(* fs_set_log_function_f)(int, void *, void *)
void *(* fs_new_player_f)(void *)
static int a4_click_pending
static int a4_cursor_shown
static int _a4_item_at(const LexMenu *menu, const BITMAP *buf, int mx, int my)
static int a4_midi_volume
static ALLEGRO_COLOR _a4_prim_color(int color)
static void _a4_midi_shutdown(void)
int(* fs_player_int_f)(void *)
static char * _a4_resolve(const char *path)
static BITMAP * a4_batch_target
static BITMAP * _a4_wrap(ALLEGRO_BITMAP *abmp)
static volatile int a4_close_requested
static ALLEGRO_COLOR _a4_rgba(int color, int alpha)
int(* fs_settings_setstr_f)(void *, const char *, const char *)
static struct @346262156126311217342151060122117020361320217156 a4_fs
static ALLEGRO_EVENT_QUEUE * a4_input_queue
static void * _a4_timer_proc(ALLEGRO_THREAD *thr, void *arg)
static ALLEGRO_DISPLAY * a4_display
static void _a4_vertex(ALLEGRO_VERTEX *v, float x, float y, ALLEGRO_COLOR c)
static void _a4_quad(BITMAP *b, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, int color)
static void _a4_text(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int bg, int align)
int(* fs_sfload_f)(void *, const char *, int)
static void _a4_unlock(BITMAP *b)
static ALLEGRO_MUTEX * a4_input_mutex
static void _a4_destroy_display(void)
static void _a4_done(const BITMAP *b)
static int a4_keybuf_start
static int _a4_take_click(int *x, int *y)
static void _a4_blend_alpha(void)
static ALLEGRO_MUTEX * a4_timer_mutex
int(* fs_player_set_loop_f)(void *, int)
static A4_TIMER a4_timers[16]
static void _a4_midi_stop_locked(void)
static void _a4_rotated(BITMAP *bmp, BITMAP *sprite, float x, float y, float cx, float cy, fixed angle, fixed scale)
static void(* a4_close_cb)(void)
static int a4_trans_alpha
ALLEGRO_LOCKED_REGION * lock
static int a4_batch_blend
static ALLEGRO_FONT * _a4_font(const FONT *f)
static ALLEGRO_BITMAP * _a4_source(BITMAP *b, int masked)
static ALLEGRO_LOCKED_REGION * _a4_lock(BITMAP *b)
static int a4_keybuf_count
void(* fs_delete_f)(void *)
static void _a4_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int flags)
#define A4_TEXTPRINTF(align)
int(* fs_write_float_f)(void *, int, void *, int, int, void *, int, int)
static void * _a4_midi_proc(ALLEGRO_THREAD *thr, void *arg)
ALLEGRO_SAMPLE_ID ids[16]
void *(* fs_new_synth_f)(void *)
static void _a4_blend_copy(void)
static void _a4_present(void)
static void _a4_set_blend(int blend)
static const char * _a4_soundfont(void)
#define A4_SYM(field, name)
static float _a4_gain(int vol)
static void _a4_draw_region(BITMAP *source, BITMAP *dest, int masked, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, int flags)
static BITMAP * _a4_highlight(BITMAP *src)
static int _a4_midi_init(void)
static void _a4_item_rect(const LexMenu *menu, const BITMAP *buf, int i, float *x, float *y, float *w, float *h)
static ALLEGRO_COLOR _a4_prim(int color, int *blend)
static ALLEGRO_THREAD * a4_input_thread
static int _a4_fluidsynth_sym(N_MODULE *lib, const char *name, void *fptr, size_t fsize)
void *(* fs_new_settings_f)(void)
static void _a4_compute_scale(void)
static N_MODULE * _a4_fluidsynth_open(void)
int(* fs_settings_setnum_f)(void *, const char *, double)
static int _a4_align(const char *v, int is_h)
static void * _a4_input_proc(ALLEGRO_THREAD *thr, void *arg)
static int _a4_color_from_pixel(uint32_t p)
static int a4_digi_volume
static void _a4_flush(void)
static void _a4_input_handle(const ALLEGRO_EVENT *ev)
static char * _a4_strndup(const char *s, size_t n)
int(* fs_player_add_f)(void *, const char *)
static ALLEGRO_VERTEX * _a4_reserve(BITMAP *b, int blend, int n)
static int a4_alpha_blender
a font: the built in one, or a TTF font loaded with load_ttf_font()
Allegro 4 compatibility layer on top of Allegro 5.
Common headers and low-level functions & define.
Load a shared library at runtime and find its symbols.