diff --git a/Makefile.am b/Makefile.am index 759bf973..234355c0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -39,6 +39,7 @@ VIDEO_SRC = \ src/video/glvideo.c \ src/video/glanimation.c \ src/video/glcpuanim.c \ + src/video/glhudmodel.c \ src/video/glutinput.c \ src/video_util/matrixUtil.c \ src/video_util/modelUtil.c \ diff --git a/configure.ac b/configure.ac index 3f6069fa..bc99874b 100644 --- a/configure.ac +++ b/configure.ac @@ -170,7 +170,7 @@ AC_ARG_ENABLE([opengl], AS_HELP_STRING([--disable-opengl], [Disable OpenGL video opengl_supported='yes' AC_DEFINE(VIDEO_OPENGL, 1, [Use OpenGL]) AC_DEFINE(USE_GLUT, 1, [Use GLUT library]) - VIDEO_O="src/video/glvideo.o src/video/glanimation.o src/video/glcpuanim.o src/video/glutinput.o src/video_util/matrixUtil.o src/video_util/modelUtil.o src/video_util/sourceUtil.o src/video_util/vectorUtil.o" + VIDEO_O="src/video/glvideo.o src/video/glanimation.o src/video/glcpuanim.o src/video/glhudmodel.o src/video/glutinput.o src/video_util/matrixUtil.o src/video_util/modelUtil.o src/video_util/sourceUtil.o src/video_util/vectorUtil.o" AC_MSG_RESULT([Building emulator with OpenGL support, w00t!]) ], [ AC_MSG_WARN([Did not find OpenGL GLEW library...]) diff --git a/src/display.c b/src/display.c index 698ce046..8df5df66 100644 --- a/src/display.c +++ b/src/display.c @@ -719,9 +719,9 @@ GLUE_C_WRITE(video__write_2e_text1_mixed) } // ---------------------------------------------------------------------------- -// interface/messages plotting +// Classic interface and printing HUD messages -void video_load_interface_fonts(void) { +static void _load_interface_fonts(void) { video_loadfont_int(0x00,0x40,ucase_glyphs); video_loadfont_int(0x40,0x20,ucase_glyphs); video_loadfont_int(0x60,0x20,lcase_glyphs); @@ -732,146 +732,21 @@ void video_load_interface_fonts(void) { video_loadfont_int(MOUSETEXT_BEGIN,0x20,mousetext_glyphs); } -// Classic interface and messages -void video_plotchar_fb(uint8_t *fb, int fb_width, int x, int y, int scheme, uint8_t c) { +void interface_plotChar(uint8_t *fb, int fb_pix_width, int col, int row, interface_colorscheme_t cs, uint8_t c) { _vid_dirty = true; - unsigned int off = y * fb_width * 16 + x * 7 + 4; + unsigned int off = row * fb_pix_width * FONT_HEIGHT_PIXELS + col * FONT80_WIDTH_PIXELS + _INTERPOLATED_PIXEL_ADJUSTMENT_PRE; uint8_t *dst = fb + off; - uint8_t *src = video__int_font[scheme] + c * 64; + uint8_t *src = video__int_font[cs] + c * (FONT_GLYPH_X*FONT_GLYPH_Y); - _plot_char80(&dst, &src, fb_width); - _plot_char80(&dst, &src, fb_width); - _plot_char80(&dst, &src, fb_width); - _plot_char80(&dst, &src, fb_width); - _plot_char80(&dst, &src, fb_width); - _plot_char80(&dst, &src, fb_width); - _plot_char80(&dst, &src, fb_width); - _plot_char80(&dst, &src, fb_width); -} - -void video_plotchar(int x, int y, int scheme, uint8_t c) { - video_plotchar_fb(video__fb1, SCANWIDTH, x, y, scheme, c); -} - -void video_interface_print_fb(uint8_t *fb, int fb_width, int x, int y, int cs, const char *s) { - for (; *s; x++, s++) { - video_plotchar_fb(fb, fb_width, x, y, cs, *s); - } -} - -void video_interface_print(int x, int y, int cs, const char *s) { - video_interface_print_fb(video__fb1, SCANWIDTH, x, y, cs, s); -} - -#define IsGraphic(c) ((c) == '|' || (((unsigned char)c) >= 0x80 && ((unsigned char)c) <= 0x8A)) -#define IsInside(x,y) ((x) >= 0 && (x) <= xlen-1 && (y) >= 0 && (y) <= ylen-1) - -static void _convert_screen_graphics(char *screen, const int x, const int y, const int xlen, const int ylen) { - static char map[11][3][4] ={ { "...", - ".||", - ".|." }, - - { "...", - "||.", - ".|." }, - - { ".|.", - ".||", - "..." }, - - { ".|.", - "||.", - "..." }, - - { "~|~", - ".|.", - "~|~" }, - - { "~.~", - "|||", - "~.~" }, - - { ".|.", - ".||", - ".|." }, - - { ".|.", - "||.", - ".|." }, - - { "...", - "|||", - ".|." }, - - { ".|.", - "|||", - "..." }, - - { ".|.", - "|||", - ".|." } }; - - bool found_glyph = false; - int k = 10; - for (; k >= 0; k--) { - found_glyph = true; - - for (int yy = y - 1; found_glyph && yy <= y + 1; yy++) { - int idx = yy*(xlen+1); - for (int xx = x - 1; xx <= x + 1; xx++) { - char map_ch = map[k][ yy - y + 1 ][ xx - x + 1 ]; - - if (IsInside(xx, yy)) { - char c = *(screen + idx + xx); - if (!IsGraphic( c ) && (map_ch == '|')) { - found_glyph = false; - break; - } else if (IsGraphic( c ) && (map_ch == '.')) { - found_glyph = false; - break; - } - } else if (map_ch == '|') { - found_glyph = false; - break; - } - } - idx += xlen+1; - } - - if (found_glyph) { - break; - } - } - - if (found_glyph) { - *(screen + y*(xlen+1) + x) = 0x80 + k; - } -} - -void video_interface_translate_screen_x_y(char *screen, const int xlen, const int ylen) { - for (int idx=0, y=0; y < ylen; y++, idx+=xlen+1) { - for (int x = 0; x < xlen; x++) { - if (*(screen + idx + x) == '|') { - _convert_screen_graphics(screen, x, y, xlen, ylen); - } - } - } -} - -void video_interface_print_submenu_centered_fb(uint8_t *fb, int submenu_width, int submenu_height, char *submenu, const int xlen, const int ylen) { - video_interface_translate_screen_x_y(submenu, xlen, ylen); - int x = (submenu_width - xlen) >> 1; - int y = (submenu_height - ylen) >> 1; - int fb_width = (submenu_width*7) + INTERPOLATED_PIXEL_ADJUSTMENT; // HACK NOTE : interpolated pixel adjustment still necessary ... - int ymax = y+ylen; - for (int idx=0; y < ymax; y++, idx+=xlen+1) { - video_interface_print_fb(fb, fb_width, x, y, 2, &submenu[ idx ]); - } -} - -void video_interface_print_submenu_centered(char *submenu, const int xlen, const int ylen) { - video_interface_print_submenu_centered_fb(video__fb1, INTERFACE_SCREEN_X, TEXT_ROWS, submenu, xlen, ylen); + _plot_char80(&dst, &src, fb_pix_width); + _plot_char80(&dst, &src, fb_pix_width); + _plot_char80(&dst, &src, fb_pix_width); + _plot_char80(&dst, &src, fb_pix_width); + _plot_char80(&dst, &src, fb_pix_width); + _plot_char80(&dst, &src, fb_pix_width); + _plot_char80(&dst, &src, fb_pix_width); + _plot_char80(&dst, &src, fb_pix_width); } // ---------------------------------------------------------------------------- @@ -1398,3 +1273,9 @@ uint8_t floating_bus_hibit(const bool hibit) { return (b & ~0x80) | (hibit ? 0x80 : 0); } +__attribute__((constructor)) +static void _init_interface(void) { + LOG("display subsystem startup"); + _load_interface_fonts(); +} + diff --git a/src/interface.c b/src/interface.c index be76f648..149fc8a3 100644 --- a/src/interface.c +++ b/src/interface.c @@ -16,11 +16,139 @@ #include "common.h" +// 2015/04/12 : This was legacy code for rendering the menu interfaces on desktop Linux. Portions here are resurrected +// to render HUD messages on desktop and mobile. Nothing special or pretty here, but has "just worked" for 20+ years ;-) + +#define IsGraphic(c) ((c) == '|' || (((unsigned char)c) >= 0x80 && ((unsigned char)c) <= 0x8A)) +#define IsInside(x,y) ((x) >= 0 && (x) <= xlen-1 && (y) >= 0 && (y) <= ylen-1) + +// Draws special interface menu "characters" +static void _convert_screen_graphics(char *screen, const int x, const int y, const int xlen, const int ylen) { + static char map[11][3][4] ={ { "...", + ".||", + ".|." }, + + { "...", + "||.", + ".|." }, + + { ".|.", + ".||", + "..." }, + + { ".|.", + "||.", + "..." }, + + { "~|~", + ".|.", + "~|~" }, + + { "~.~", + "|||", + "~.~" }, + + { ".|.", + ".||", + ".|." }, + + { ".|.", + "||.", + ".|." }, + + { "...", + "|||", + ".|." }, + + { ".|.", + "|||", + "..." }, + + { ".|.", + "|||", + ".|." } }; + + bool found_glyph = false; + int k = 10; + for (; k >= 0; k--) { + found_glyph = true; + + for (int yy = y - 1; found_glyph && yy <= y + 1; yy++) { + int idx = yy*(xlen+1); + for (int xx = x - 1; xx <= x + 1; xx++) { + char map_ch = map[k][ yy - y + 1 ][ xx - x + 1 ]; + + if (IsInside(xx, yy)) { + char c = *(screen + idx + xx); + if (!IsGraphic( c ) && (map_ch == '|')) { + found_glyph = false; + break; + } else if (IsGraphic( c ) && (map_ch == '.')) { + found_glyph = false; + break; + } + } else if (map_ch == '|') { + found_glyph = false; + break; + } + } + idx += xlen+1; + } + + if (found_glyph) { + break; + } + } + + if (found_glyph) { + *(screen + y*(xlen+1) + x) = 0x80 + k; + } +} + +static void _translate_screen_x_y(char *screen, const int xlen, const int ylen) { + for (int idx=0, y=0; y < ylen; y++, idx+=xlen+1) { + for (int x = 0; x < xlen; x++) { + if (*(screen + idx + x) == '|') { + _convert_screen_graphics(screen, x, y, xlen, ylen); + } + } + } +} + +// ---------------------------------------------------------------------------- +// Menu/HUD message printing + +void interface_printMessage(uint8_t *fb, int fb_pix_width, int col, int row, interface_colorscheme_t cs, const char *message) { + for (; *message; col++, message++) { + char c = *message; + interface_plotChar(fb, fb_pix_width, col, row, cs, c); + } +} + +void interface_printMessageCentered(uint8_t *fb, int fb_cols, int fb_rows, interface_colorscheme_t cs, char *message, const int message_cols, const int message_rows) { + _translate_screen_x_y(message, message_cols, message_rows); + int col = (fb_cols - message_cols) >> 1; + int row = (fb_rows - message_rows) >> 1; + int fb_pix_width = (fb_cols*FONT80_WIDTH_PIXELS) + INTERPOLATED_PIXEL_ADJUSTMENT; // HACK NOTE : interpolated pixel adjustment still necessary ... + int row_max = row + message_rows; + for (int idx=0; rowtplWidth; const unsigned int rows = hudElement->tplHeight; uint8_t *fb = hudElement->pixels; - const unsigned int fb_w = hudElement->pixWidth; - const unsigned int fb_h = hudElement->pixHeight; // render template into indexed fb - const unsigned int submenu_width = cols; - const unsigned int submenu_height = rows; - video_interface_print_submenu_centered_fb(fb, submenu_width, submenu_height, submenu, submenu_width, submenu_height); + interface_printMessageCentered(fb, cols, rows, RED_ON_BLACK, submenu, cols, rows); // generate RGBA_8888 from indexed color + const unsigned int fb_w = hudElement->pixWidth; + const unsigned int fb_h = hudElement->pixHeight; const unsigned int count = fb_w * fb_h; for (unsigned int i=0, j=0; i -#define USE_VAO 1 -#endif - // TODO: implement 3D CRT object, possibly with perspective drawing? #define PERSPECTIVE 0 -// VAO optimization (may not be available on all platforms) -#ifdef ANDROID -#include "glanimation.h" -// NOTE : 2015/04/01 ... Certain Android and Android-ish devices (*cough* Kindle *cough*) have buggy OpenGL VAO support, -// so don't rely on it. Is it the future yet? -#define USE_VAO 0 -#elif !defined(USE_VAO) -#define USE_VAO 1 -#endif - #include "video_util/modelUtil.h" #include "video_util/matrixUtil.h" #include "video_util/sourceUtil.h" -enum { - POS_ATTRIB_IDX, - TEXCOORD_ATTRIB_IDX, - NORMAL_ATTRIB_IDX, -}; - enum { TEXTURE_ID_FRAMEBUFFER=0, TEXTURE_ID_MESSAGE, @@ -60,26 +37,6 @@ enum { #endif }; -static inline GLsizei getGLTypeSize(GLenum type) { - switch (type) { - case GL_BYTE: - return sizeof(GLbyte); - case GL_UNSIGNED_BYTE: - return sizeof(GLubyte); - case GL_SHORT: - return sizeof(GLshort); - case GL_UNSIGNED_SHORT: - return sizeof(GLushort); - case GL_INT: - return sizeof(GLint); - case GL_UNSIGNED_INT: - return sizeof(GLuint); - case GL_FLOAT: - return sizeof(GLfloat); - } - return 0; -} - extern GLint uniformTex2Use; extern GLint alphaValue; diff --git a/src/video/video.h b/src/video/video.h index 54b512fd..6b2f5bfe 100644 --- a/src/video/video.h +++ b/src/video/video.h @@ -97,11 +97,6 @@ void video_set(int flags); */ void video_loadfont(int first, int qty, const uint8_t *data, int mode); -/* - * Loads the interface/messages to a seperate character table for system menus/messages - */ -void video_load_interface_fonts(void); - /* * Redraw the display. This is called after exiting an interface display, * when changes have been made to the Apple's emulated framebuffer that @@ -128,35 +123,6 @@ bool video_dirty(void); // ---------------------------------------------------------------------------- -/* - * Plot a character to the text mode screen, *not* writing to apple - * memory. This is used by the interface screens. - * - * ROW, COL, and CODE are self-expanatory. COLOR gives the color scheme - * to use: - * - * 0 - Green text on Black background - * 1 - Green text on Blue background - * 2 - Red text on Black background - */ -void video_plotchar(int row, int col, int color, uint8_t code); - -/* - * Same as video_plotchar(), but allows plotting to a separate buffer - */ -void video_plotchar_fb(uint8_t *fb, int fb_width, int row, int col, int color, uint8_t code); - -void video_interface_print(int x, int y, const int cs, const char *s); - -void video_interface_print_fb(uint8_t *fb, int fb_width, int x, int y, const int cs, const char *s); - -void video_interface_print_submenu_centered(char *submenu, const int xlen, const int ylen); - -void video_interface_print_submenu_centered_fb(uint8_t *fb, int screen_char_width, int screen_char_height, char *submenu, const int xlen, const int ylen); - -// ---------------------------------------------------------------------------- - - /* * Show CPU speed animation */ @@ -184,7 +150,9 @@ uint8_t floating_bus_hibit(const bool hibit); * machines) for a standard resolution. */ #define _SCANWIDTH 560 -#define INTERPOLATED_PIXEL_ADJUSTMENT (4+4) +#define _INTERPOLATED_PIXEL_ADJUSTMENT_PRE 4 +#define _INTERPOLATED_PIXEL_ADJUSTMENT_POST 4 +#define INTERPOLATED_PIXEL_ADJUSTMENT (_INTERPOLATED_PIXEL_ADJUSTMENT_PRE+_INTERPOLATED_PIXEL_ADJUSTMENT_POST) #define SCANWIDTH (_SCANWIDTH+INTERPOLATED_PIXEL_ADJUSTMENT) #define SCANHEIGHT 384 @@ -193,7 +161,8 @@ uint8_t floating_bus_hibit(const bool hibit); #define TEXT_COLS 40 #define TEXT80_COLS 80 -#define INTERFACE_SCREEN_X TEXT80_COLS +#define FONT_GLYPH_X 8 +#define FONT_GLYPH_Y FONT_GLYPH_X #define FONT_HEIGHT_PIXELS 16 #define FONT_WIDTH_PIXELS 14 diff --git a/src/video_util/glUtil.h b/src/video_util/glUtil.h index a301f461..a79d1033 100644 --- a/src/video_util/glUtil.h +++ b/src/video_util/glUtil.h @@ -15,7 +15,9 @@ #define __GL_UTIL_H__ #if defined(__APPLE__) -# include +# define USE_VAO 1 +# import +# import # if TARGET_OS_IPHONE # import # import @@ -27,6 +29,9 @@ # include # include #elif defined(ANDROID) +// NOTE : 2015/04/01 ... Certain Android and Android-ish devices (*cough* Kindle *cough*) have buggy OpenGL VAO support, +// so don't rely on it. Is it the future yet? +# define USE_VAO 0 # include # include #else @@ -36,6 +41,10 @@ # include #endif +#if !defined(USE_VAO) +#define USE_VAO 1 +#endif + static inline const char * GetGLErrorString(GLenum error) { const char *str; switch (error) { diff --git a/src/video_util/modelUtil.c b/src/video_util/modelUtil.c index 86121c28..cc6f47e6 100644 --- a/src/video_util/modelUtil.c +++ b/src/video_util/modelUtil.c @@ -329,7 +329,7 @@ static void _quadCreateVAOAndVBOs(GLModel *model) { glEnableVertexAttribArray(POS_ATTRIB_IDX); // Get the size of the position type so we can set the stride properly - GLsizei posTypeSize = _get_gl_type_size(model->positionType); + GLsizei posTypeSize = getGLTypeSize(model->positionType); // Set up parmeters for position attribute in the VAO including, // size, type, stride, and offset in the currenly bound VAO @@ -355,7 +355,7 @@ static void _quadCreateVAOAndVBOs(GLModel *model) { glEnableVertexAttribArray(TEXCOORD_ATTRIB_IDX); // Get the size of the texcoord type so we can set the stride properly - GLsizei texcoordTypeSize = _get_gl_type_size(model->texcoordType); + GLsizei texcoordTypeSize = getGLTypeSize(model->texcoordType); // Set up parmeters for texcoord attribute in the VAO including, // size, type, stride, and offset in the currenly bound VAO diff --git a/src/video_util/modelUtil.h b/src/video_util/modelUtil.h index d17b8a5d..6117de87 100644 --- a/src/video_util/modelUtil.h +++ b/src/video_util/modelUtil.h @@ -18,6 +18,12 @@ #define UNINITIALIZED_GL 31337 +enum { + POS_ATTRIB_IDX, + TEXCOORD_ATTRIB_IDX, + NORMAL_ATTRIB_IDX, +}; + typedef struct GLModel; #define MODEL_CLASS(CLS, ...) \ @@ -83,4 +89,24 @@ GLModel *mdlCreateQuad(GLfloat skew_x, GLfloat skew_y, GLfloat obj_w, GLfloat ob void mdlDestroyModel(INOUT GLModel **model); +static inline GLsizei getGLTypeSize(GLenum type) { + switch (type) { + case GL_BYTE: + return sizeof(GLbyte); + case GL_UNSIGNED_BYTE: + return sizeof(GLubyte); + case GL_SHORT: + return sizeof(GLshort); + case GL_UNSIGNED_SHORT: + return sizeof(GLushort); + case GL_INT: + return sizeof(GLint); + case GL_UNSIGNED_INT: + return sizeof(GLuint); + case GL_FLOAT: + return sizeof(GLfloat); + } + return 0; +} + #endif //__MODEL_UTIL_H__