maug
Quick and dirty C mini-augmentation library.
Loading...
Searching...
No Matches
retrowin.h
Go to the documentation of this file.
1
2#ifndef RETROW3D_H
3#define RETROW3D_H
4
48
49#ifndef RETROWIN_TRACE_LVL
50# define RETROWIN_TRACE_LVL 0
51#endif /* !RETROWIN_TRACE_LVL */
52
58#define RETROWIN_FLAG_INIT_GUI 0x10
59
60#define RETROWIN_FLAG_INIT_BMP 0x20
61
62#define RETROWIN_FLAG_GUI_LOCKED 0x04
63
64#define RETROWIN_FLAG_BORDER_NONE 0x00
65#define RETROWIN_FLAG_BORDER_GRAY 0x01
66#define RETROWIN_FLAG_BORDER_BLUE 0x02
67
68#define retrowin_win_is_active( win ) \
69 (RETROWIN_FLAG_INIT_BMP == (RETROWIN_FLAG_INIT_BMP & (win)->flags))
70
71#define RETROWIN_FLAG_BORDER_MASK 0x03
72
73#define retrowin_lock_gui( win ) \
74 if( \
75 RETROWIN_FLAG_INIT_GUI == (RETROWIN_FLAG_INIT_GUI & (win)->flags) && \
76 RETROWIN_FLAG_GUI_LOCKED != (RETROWIN_FLAG_GUI_LOCKED & (win)->flags) \
77 ) { \
78 /* debug_printf( RETROWIN_TRACE_LVL, "locking managed gui handle %p...", \
79 (win)->gui_h ); */ \
80 maug_mlock( (win)->gui_h, (win)->gui_p ); \
81 maug_cleanup_if_null_lock( struct RETROGUI*, (win)->gui_p ); \
82 (win)->flags |= RETROWIN_FLAG_GUI_LOCKED; \
83 /* debug_printf( RETROWIN_TRACE_LVL, "locked managed gui to pointer %p!", \
84 (win)->gui_p ); */ \
85 }
86
87#define retrowin_unlock_gui( win ) \
88 if( \
89 RETROWIN_FLAG_INIT_GUI == (RETROWIN_FLAG_INIT_GUI & (win)->flags) && \
90 RETROWIN_FLAG_GUI_LOCKED == (RETROWIN_FLAG_GUI_LOCKED & (win)->flags) \
91 ) { \
92 /* debug_printf( RETROWIN_TRACE_LVL, "unlocking managed gui pointer %p...", \
93 (win)->gui_h ); */ \
94 maug_munlock( (win)->gui_h, (win)->gui_p ); \
95 (win)->flags &= ~RETROWIN_FLAG_GUI_LOCKED; \
96 }
97
98struct RETROWIN {
99 uint8_t flags;
100 size_t idc;
101 size_t x;
102 size_t y;
103 MAUG_MHANDLE gui_h;
104 struct RETROGUI* gui_p;
105 retroflat_blit_t gui_bmp;
106};
107
108MERROR_RETVAL retrowin_redraw_win_stack( struct MDATA_VECTOR* win_stack );
109
114
115retrogui_idc_t retrowin_poll_win_stack(
116 struct MDATA_VECTOR* win_stack, retrogui_idc_t idc_active,
117 RETROFLAT_IN_KEY* p_input, struct RETROFLAT_INPUT* input_evt );
118
124 struct MDATA_VECTOR* win_stack,
125 retrogui_idc_t idc_win, retrogui_idc_t idc_ctl );
126
127void retrowin_free_win( struct RETROWIN* win );
128
129ssize_t retrowin_get_by_idc( size_t idc, struct MDATA_VECTOR* win_stack );
130
139ssize_t retrowin_push_win(
140 struct RETROGUI* gui, struct MDATA_VECTOR* win_stack,
141 size_t idc, const char* font_filename,
142 size_t x, size_t y, size_t w, size_t h, uint8_t flags );
143
150 struct MDATA_VECTOR* win_stack, size_t idc );
151
152#ifdef RETROW3D_C
153
154static MERROR_RETVAL _retrowin_draw_border( struct RETROWIN* win ) {
155 MERROR_RETVAL retval = MERROR_OK;
156
157 assert(
158 RETROWIN_FLAG_INIT_GUI != (RETROWIN_FLAG_INIT_GUI & win->flags) ||
159 RETROWIN_FLAG_GUI_LOCKED == (RETROWIN_FLAG_GUI_LOCKED & win->flags) );
160
161 switch( RETROWIN_FLAG_BORDER_MASK & win->flags ) {
162 case RETROWIN_FLAG_BORDER_NONE:
163 retroflat_2d_rect(
164 win->gui_p->draw_bmp, RETROFLAT_COLOR_BLACK,
165 0, 0,
166 retroflat_2d_bitmap_w( win->gui_p->draw_bmp ),
167 retroflat_2d_bitmap_h( win->gui_p->draw_bmp ),
169 break;
170
171 case RETROWIN_FLAG_BORDER_GRAY:
172 retroflat_2d_rect(
173 win->gui_p->draw_bmp,
174 2 < retroflat_screen_colors() ?
175 RETROFLAT_COLOR_GRAY : RETROFLAT_COLOR_WHITE, 0, 0,
176 retroflat_2d_bitmap_w( win->gui_p->draw_bmp ),
177 retroflat_2d_bitmap_h( win->gui_p->draw_bmp ),
179
180 /* Draw the border. */
181 retroflat_2d_rect(
182 win->gui_p->draw_bmp,
183 2 < retroflat_screen_colors() ?
184 RETROGUI_COLOR_BORDER : RETROFLAT_COLOR_BLACK, 0, 0,
185 retroflat_2d_bitmap_w( win->gui_p->draw_bmp ),
186 retroflat_2d_bitmap_h( win->gui_p->draw_bmp ),
187 0 );
188 if( 2 < retroflat_screen_colors() ) {
189 /* Draw highlight lines only visible in >2-color mode. */
190 retroflat_2d_line(
191 win->gui_p->draw_bmp, RETROFLAT_COLOR_WHITE,
192 1, 1, retroflat_2d_bitmap_w( win->gui_p->draw_bmp ) - 2, 1, 0 );
193 retroflat_2d_line(
194 win->gui_p->draw_bmp, RETROFLAT_COLOR_WHITE,
195 1, 2, 1, retroflat_2d_bitmap_h( win->gui_p->draw_bmp ) - 3, 0 );
196 }
197 break;
198
199 case RETROWIN_FLAG_BORDER_BLUE:
200 retroflat_2d_rect(
201 win->gui_p->draw_bmp,
202 2 < retroflat_screen_colors() ?
203 RETROFLAT_COLOR_BLUE : RETROFLAT_COLOR_BLACK, 0, 0,
204 retroflat_2d_bitmap_w( win->gui_p->draw_bmp ),
205 retroflat_2d_bitmap_h( win->gui_p->draw_bmp ),
207
208 /* Draw the border. */
209 retroflat_2d_rect(
210 win->gui_p->draw_bmp,
211 2 < retroflat_screen_colors() ?
212 RETROGUI_COLOR_BORDER : RETROFLAT_COLOR_BLACK, 2, 2,
213 retroflat_2d_bitmap_w( win->gui_p->draw_bmp ) - 4,
214 retroflat_2d_bitmap_h( win->gui_p->draw_bmp ) - 4,
215 0 );
216 retroflat_2d_rect(
217 win->gui_p->draw_bmp, RETROFLAT_COLOR_WHITE, 1, 1,
218 retroflat_2d_bitmap_w( win->gui_p->draw_bmp ) - 2,
219 retroflat_2d_bitmap_h( win->gui_p->draw_bmp ) - 2,
220 0 );
221 retroflat_2d_rect(
222 win->gui_p->draw_bmp,
223 2 < retroflat_screen_colors() ?
224 RETROGUI_COLOR_BORDER : RETROFLAT_COLOR_BLACK, 0, 0,
225 retroflat_2d_bitmap_w( win->gui_p->draw_bmp ),
226 retroflat_2d_bitmap_h( win->gui_p->draw_bmp ),
227 0 );
228 break;
229 }
230
231 return retval;
232}
233
234/* === */
235
236static MERROR_RETVAL _retrowin_redraw_win( struct RETROWIN* win ) {
237 MERROR_RETVAL retval = MERROR_OK;
238
239 assert(
240 RETROWIN_FLAG_INIT_GUI != (RETROWIN_FLAG_INIT_GUI & win->flags) ||
241 RETROWIN_FLAG_GUI_LOCKED == (RETROWIN_FLAG_GUI_LOCKED & win->flags) );
242
243 retroflat_2d_lock_bitmap( &(win->gui_bmp) );
244
245 /* Dirty detection is in retrogui_redraw_ctls(). */
246 win->gui_p->draw_bmp = &(win->gui_bmp);
247
248 debug_printf( RETROWIN_TRACE_LVL,
249 "redrawing window " SIZE_T_FMT " (GUI %p)...", win->idc, win->gui_p );
250
251 _retrowin_draw_border( win );
252
253 /* This is a bit of a hack... Set X/Y to 0 so that we draw at the top
254 * of the bitmap that will be used as a texture. Reset it below so input
255 * detection works!
256 */
257 win->gui_p->x = 0;
258 win->gui_p->y = 0;
259 retval = retrogui_redraw_ctls( win->gui_p );
260 win->gui_p->x = win->x;
261 win->gui_p->y = win->y;
262 maug_cleanup_if_not_ok();
263
264 retroflat_2d_release_bitmap( &(win->gui_bmp) );
265
266cleanup:
267
268 return retval;
269}
270
271/* === */
272
273MERROR_RETVAL retrowin_redraw_win_stack( struct MDATA_VECTOR* win_stack ) {
274 MERROR_RETVAL retval = MERROR_OK;
275 size_t i = 0;
276 struct RETROWIN* win = NULL;
277
278 if( 0 == mdata_vector_ct( win_stack ) ) {
279 goto cleanup;
280 }
281
282 assert( !mdata_vector_is_locked( win_stack ) );
283 mdata_vector_lock( win_stack );
284
285 for( i = 0 ; mdata_vector_ct( win_stack ) > i ; i++ ) {
286 win = mdata_vector_get( win_stack, i, struct RETROWIN );
287 assert( NULL != win );
288
289 if( !retrowin_win_is_active( win ) ) {
290 continue;
291 }
292
293 retrowin_lock_gui( win );
294
295 /* OpenGL tends to call glClear on every frame, so always redraw! */
296 if( RETROGUI_FLAGS_DIRTY == (RETROGUI_FLAGS_DIRTY & win->gui_p->flags) ) {
297 debug_printf( RETROWIN_TRACE_LVL,
298 "redrawing window idx " SIZE_T_FMT ", IDC " SIZE_T_FMT,
299 i, win->idc );
300
301 /* Redraw the window bitmap, including controls. */
302 retval = _retrowin_redraw_win( win );
303 maug_cleanup_if_not_ok();
304 }
305
306 /* Always blit the finished window to the screen, to compensate for e.g.
307 * the implicit screen-clearing of the engine loop.
308 */
309 retval = retroflat_2d_blit_win(
310 &(win->gui_bmp), win->gui_p->x, win->gui_p->y );
311
312 retrowin_unlock_gui( win );
313 }
314
315cleanup:
316
317 mdata_vector_unlock( win_stack );
318
319 return retval;
320}
321
322/* === */
323
325 MERROR_RETVAL retval = MERROR_OK;
326 size_t i = 0;
327 struct RETROWIN* win = NULL;
328
329 if( 0 == mdata_vector_ct( win_stack ) ) {
330 goto cleanup;
331 }
332
333 assert( !mdata_vector_is_locked( win_stack ) );
334 mdata_vector_lock( win_stack );
335
336 for( i = 0 ; mdata_vector_ct( win_stack ) > i ; i++ ) {
337 win = mdata_vector_get( win_stack, i, struct RETROWIN );
338 assert( NULL != win );
339
340 if( !retrowin_win_is_active( win ) ) {
341 continue;
342 }
343
344 retrowin_lock_gui( win );
345
346 debug_printf( RETROWIN_TRACE_LVL,
347 "refreshing window idx " SIZE_T_FMT ", IDC " SIZE_T_FMT,
348 i, win->idc );
349
350 win->gui_p->flags |= RETROGUI_FLAGS_DIRTY;
351
352 retrowin_unlock_gui( win );
353 }
354
355cleanup:
356
357 mdata_vector_unlock( win_stack );
358
359 return retval;
360}
361
362/* === */
363
364retrogui_idc_t retrowin_poll_win_stack(
365 struct MDATA_VECTOR* win_stack, retrogui_idc_t idc_active,
366 RETROFLAT_IN_KEY* p_input, struct RETROFLAT_INPUT* input_evt
367) {
368 retrogui_idc_t idc_out = RETROGUI_IDC_NONE;
369 MERROR_RETVAL retval = MERROR_OK;
370 struct RETROWIN* win = NULL;
371 int autolock = 0;
372 ssize_t win_idx = -1;
373
374 if( !mdata_vector_is_locked( win_stack ) ) {
375 mdata_vector_lock( win_stack );
376 autolock = 1;
377 }
378
379 win_idx = retrowin_get_by_idc( idc_active, win_stack );
380 if( 0 > win_idx ) {
381 /* No window found! */
382 error_printf( "polling invalid window!" );
383 goto cleanup;
384 }
385
386 win = mdata_vector_get( win_stack, win_idx, struct RETROWIN );
387 assert( NULL != win );
388 assert( idc_active == win->idc );
389 if( !retrowin_win_is_active( win ) ) {
390 /* Window not active! */
391 error_printf( "polling inactive window!" );
392 goto cleanup;
393 }
394
395 retrowin_lock_gui( win );
396 if( 0 != *p_input ) {
397 debug_printf( RETROWIN_TRACE_LVL,
398 "polling window idx " SIZE_T_FMT ", IDC " RETROGUI_IDC_FMT,
399 win_idx, win->idc );
400 }
401 idc_out = retrogui_poll_ctls( win->gui_p, p_input, input_evt );
402 retrowin_unlock_gui( win );
403
404cleanup:
405
406 if( MERROR_OK != retval ) {
407 error_printf( "error polling windows!" );
408 idc_out = RETROGUI_IDC_NONE;
409 }
410
411 if( autolock ) {
412 mdata_vector_unlock( win_stack );
413 }
414
415 return idc_out;
416}
417
418/* === */
419
421 struct MDATA_VECTOR* win_stack,
422 retrogui_idc_t idc_win, retrogui_idc_t idc_ctl
423) {
424 ssize_t idx_out = -1;
425 MERROR_RETVAL retval = MERROR_OK;
426 struct RETROWIN* win = NULL;
427 int autolock = 0;
428 ssize_t win_idx = -1;
429
430 if( !mdata_vector_is_locked( win_stack ) ) {
431 mdata_vector_lock( win_stack );
432 autolock = 1;
433 }
434
435 win_idx = retrowin_get_by_idc( idc_win, win_stack );
436 if( 0 > win_idx ) {
437 /* No window found! */
438 error_printf( "polling invalid window!" );
439 goto cleanup;
440 }
441
442 win = mdata_vector_get( win_stack, win_idx, struct RETROWIN );
443 assert( NULL != win );
444 assert( idc_win == win->idc );
445 if( !retrowin_win_is_active( win ) ) {
446 /* Window not active! */
447 error_printf( "polling inactive window!" );
448 goto cleanup;
449 }
450
451 retrowin_lock_gui( win );
452 idx_out = retrogui_get_ctl_sel_idx( win->gui_p, idc_ctl );
453 retrowin_unlock_gui( win );
454
455cleanup:
456
457 if( MERROR_OK != retval ) {
458 error_printf( "error getting window control selection index!" );
459 idx_out = merror_retval_to_sz( retval );
460 }
461
462 if( autolock ) {
463 mdata_vector_unlock( win_stack );
464 }
465
466 return idx_out;
467}
468
469/* === */
470
471void retrowin_free_win( struct RETROWIN* win ) {
472 MERROR_RETVAL retval = MERROR_OK;
473
474 if( RETROWIN_FLAG_INIT_BMP == (RETROWIN_FLAG_INIT_BMP & win->flags) ) {
475 retroflat_2d_destroy_bitmap( &(win->gui_bmp) );
476 retrowin_lock_gui( win );
477 win->gui_p->draw_bmp = NULL;
478 retrowin_unlock_gui( win );
479 }
480
481 if( RETROWIN_FLAG_INIT_GUI == (RETROWIN_FLAG_INIT_GUI & win->flags) ) {
482 /* This GUI was created by a NULL to push_win(). */
483 retrowin_lock_gui( win )
484 retrogui_destroy( win->gui_p );
485 retrowin_unlock_gui( win )
486 maug_mfree( win->gui_h );
487 }
488
489cleanup:
490
491 if( MERROR_OK != retval ) {
492 error_printf( "error while locking self-managed GUI! not freed!" );
493 }
494
495 maug_mzero( win, sizeof( struct RETROWIN ) );
496}
497
498/* === */
499
500ssize_t retrowin_get_by_idc( size_t idc, struct MDATA_VECTOR* win_stack ) {
501 ssize_t idx_out = -1;
502 int autolock = 0;
503 size_t i = 0;
504 struct RETROWIN* win = NULL;
505 MERROR_RETVAL retval = MERROR_OK;
506
507 if( 0 == mdata_vector_ct( win_stack ) ) {
508 goto cleanup;
509 }
510
511 if( !mdata_vector_is_locked( win_stack ) ) {
512 mdata_vector_lock( win_stack );
513 autolock = 1;
514 }
515
516 for( i = 0 ; mdata_vector_ct( win_stack ) > i ; i++ ) {
517 win = mdata_vector_get( win_stack, i, struct RETROWIN );
518 if( idc == win->idc ) {
519 idx_out = i;
520 goto cleanup;
521 }
522 }
523
524cleanup:
525
526 if( autolock ) {
527 mdata_vector_unlock( win_stack );
528 }
529
530 if( MERROR_OK != retval ) {
531 idx_out = merror_retval_to_sz( retval );
532 }
533
534 return idx_out;
535}
536
537/* === */
538
539ssize_t retrowin_push_win(
540 struct RETROGUI* gui, struct MDATA_VECTOR* win_stack,
541 size_t idc, const char* font_filename,
542 size_t x, size_t y, size_t w, size_t h, uint8_t flags
543) {
544 MERROR_RETVAL retval = MERROR_OK;
545 struct RETROWIN win;
546 ssize_t idx_out = -1;
547
548 idx_out = retrowin_get_by_idc( idc, win_stack );
549 if( 0 <= idx_out ) {
550 error_printf( "window IDC " SIZE_T_FMT " already exists!", idc );
551 goto cleanup;
552 }
553
554 maug_mzero( &win, sizeof( struct RETROWIN ) );
555
556 win.flags = 0;
557
558 if( NULL != gui ) {
559 win.gui_p = gui;
560 } else {
561 win.gui_p = NULL;
562 win.gui_h = maug_malloc( 1, sizeof( struct RETROGUI ) );
563 maug_cleanup_if_null_alloc( MAUG_MHANDLE, win.gui_h );
564
565 win.flags |= RETROWIN_FLAG_INIT_GUI;
566
567 /* Prepare gui_p for use as if it had just been assigned. */
568 retrowin_lock_gui( &win );
569
570 retval = retrogui_init( win.gui_p );
571 maug_cleanup_if_not_ok();
572
573 retval = retrogui_set_font( win.gui_p, font_filename );
574 maug_cleanup_if_not_ok();
575 }
576
577 retval = retroflat_2d_create_bitmap( w, h, &(win.gui_bmp), 0 );
578 maug_cleanup_if_not_ok();
579
580 win.flags |= RETROWIN_FLAG_INIT_BMP;
581
582 win.gui_p->w = w;
583 win.gui_p->h = h;
584 /* These might seem redundant, but check out retrowin_redraw_win()
585 * to see how they're used.
586 */
587 win.x = x;
588 win.y = y;
589 win.gui_p->x = x;
590 win.gui_p->y = y;
591 win.idc = idc;
592 win.flags |= flags;
593
594 debug_printf( RETROWIN_TRACE_LVL,
595 "pushing window IDC " SIZE_T_FMT ", GUI %p: " SIZE_T_FMT "x" SIZE_T_FMT
596 " @ " SIZE_T_FMT ", " SIZE_T_FMT,
597 win.idc, win.gui_p,
598 win.gui_p->w, win.gui_p->h, win.gui_p->x, win.gui_p->y );
599
600 retrowin_unlock_gui( &win );
601
602 idx_out = mdata_vector_append( win_stack, &win, sizeof( struct RETROWIN ) );
603 if( 0 > idx_out ) {
604 goto cleanup;
605 }
606
607 if( w != h ) {
608 /* TODO: Update to detect proportional windows. */
609 error_printf(
610 "non-square window created; some systems may have trouble!" );
611 }
612
613 retrowin_refresh_win_stack( win_stack );
614
615cleanup:
616
617 /* Unlock if unlock above was skipped due to error. */
618 retrowin_unlock_gui( &win );
619
620 return idx_out;
621}
622
623/* === */
624
626 struct MDATA_VECTOR* win_stack, size_t idc
627) {
628 size_t i = 0;
629 MERROR_RETVAL retval = MERROR_OK;
630 struct RETROWIN* win = NULL;
631 ssize_t i_free = -1;
632 int autolock = 0;
633
634 debug_printf( RETROWIN_TRACE_LVL,
635 "attempting to destroy window: " SIZE_T_FMT, idc );
636
637 if( !mdata_vector_is_locked( win_stack ) ) {
638 mdata_vector_lock( win_stack );
639 autolock = 1;
640 }
641
642 for( i = 0 ; mdata_vector_ct( win_stack ) > i ; i++ ) {
643 win = mdata_vector_get( win_stack, i, struct RETROWIN );
644 assert( NULL != win );
645 if( idc != win->idc ) {
646 continue;
647 }
648
649 if( !retrowin_win_is_active( win ) ) {
650 debug_printf( RETROWIN_TRACE_LVL,
651 "window IDC " SIZE_T_FMT " found, but not active! (flags: 0x%02x)",
652 idc, win->flags );
653 continue;
654 }
655
656 debug_printf( RETROWIN_TRACE_LVL, "freeing window: " SIZE_T_FMT,
657 win->idc );
658
659 retrowin_free_win( win );
660
661 i_free = i;
662
663 break;
664 }
665
666 /* Remove the window from the vector if asked to. */
667 if( 0 <= i_free ) {
668 if( autolock ) {
669 mdata_vector_unlock( win_stack );
670 }
671 mdata_vector_remove( win_stack, i_free );
672 if( autolock ) {
673 mdata_vector_lock( win_stack );
674 }
675 }
676
677cleanup:
678
679 if( autolock ) {
680 mdata_vector_unlock( win_stack );
681 }
682
683 return retval;
684}
685
686#endif /* RETROW3D_C */
687 /* maug_retrowin */
689 /* maug_retroflt */
691
692#endif /* !RETROW3D_H */
693
uint16_t MERROR_RETVAL
Return type indicating function returns a value from this list.
Definition merror.h:19
#define RETROFLAT_FLAGS_FILL
Flag for retroflat_rect() or retroflat_ellipse(), indicating drawn shape should be filled.
Definition retroflt.h:373
retrogui_idc_t retrogui_poll_ctls(struct RETROGUI *gui, RETROFLAT_IN_KEY *p_input, struct RETROFLAT_INPUT *input_evt)
Poll for the last clicked control and maintain listboxes and menus.
MERROR_RETVAL retrogui_set_font(struct RETROGUI *gui, const char *font_path)
Load the RetroFont API for the given RETROGUI to draw its controls with. Use RetroGXCache API if avai...
int16_t retrogui_idc_t
Unique identifying constant number for controls.
Definition retrogui.h:292
#define RETROGUI_COLOR_BORDER
RetroGUI will try to use this color on non-monochrome systems instead of black to draw things like bo...
Definition retrogui.h:95
MERROR_RETVAL retrowin_refresh_win_stack(struct MDATA_VECTOR *win_stack)
Force all windows on the stack to redraw.
ssize_t retrowin_push_win(struct RETROGUI *gui, struct MDATA_VECTOR *win_stack, size_t idc, const char *font_filename, size_t x, size_t y, size_t w, size_t h, uint8_t flags)
Create a new window on the given win_stack.
ssize_t retrowin_get_win_stack_sel_idx(struct MDATA_VECTOR *win_stack, retrogui_idc_t idc_win, retrogui_idc_t idc_ctl)
Get the selected index of the given control in the given window from the window stack.
MERROR_RETVAL retrowin_destroy_win(struct MDATA_VECTOR *win_stack, size_t idc)
Destroy the given window's resources and remove it from the window stack.
#define RETROWIN_FLAG_INIT_GUI
Flag for RETROWIN::flags indicating RETROWIN::gui_p should be locked from RETROWIN::gui_h before use.
Definition retrowin.h:58
A vector of uniformly-sized objects, stored contiguously.
Definition mdata.h:93
Struct passed to retroflat_poll_input() to hold return data.
Definition retroflt.h:814
Definition retrogui.h:430
Definition retrowin.h:95