#include "m_font.h" #include "audio.h" #include "m_lib.h" #include "gbi_extensions.h" #include "dataobject.h" #include "game.h" #include "graph.h" #include "types.h" #include "libultra/gu.h" #include "sys_matrix.h" #include "MSL_C/w_math.h" #include "m_rcp.h" #include "libc/math.h" #define mFont_CC_FONT 0, 0, 0, PRIMITIVE, PRIMITIVE, 0, TEXEL0, 0 #define mFont_CC_NOFONT 0, 0, 0, PRIMITIVE, 0, PRIMITIVE, TEXEL0, PRIMITIVE /* @unused static u8* mFont_Get_end_load_texture() */ extern void mFont_ct() { // code removed probably } static int mMsg_CutLeftSpace(u8* str, int str_len) { // This should've been renamed or moved to m_message.h u8* dst; u8* src; int i, j; for (i = 0; i < str_len; i++) { if (str[i] != CHAR_SPACE) { break; } } if (i == str_len) { return 0; } else if (i == 0) { return str_len; } dst = str; src = str + i; for (j = i; j < str_len; j++) { *dst++ = *src++; } for (j = 0; j < i; j++) { *dst++ = CHAR_SPACE; } return str_len - i; } static u8 mFont_suji_data[] = "0123456789"; static int mFont_suji_check(u8 c) { u8* suji = mFont_suji_data; int i; for (i = 0; i < 10; i++) { if (c == suji[i]) { return TRUE; } } return FALSE; } extern int mFont_UnintToString( u8* str, int figure, u32 num, int figure_start, int left_cut, int fill_zero, int separator ) { int i; int j; u32 cur_num; int next; int temp2; int last_figure; int l = figure - figure_start; u8 fill_char = fill_zero ? CHAR_ZERO : CHAR_SPACE ; u8 left_fill_char = fill_zero && !left_cut ? CHAR_ZERO : CHAR_SPACE; cur_num = num; for (last_figure = figure - 1; last_figure >= l; last_figure--) { next = cur_num / 10; temp2 = cur_num - next * 10; if (cur_num == 0) { if (num == 0 && last_figure == figure - 1) { str[last_figure] = CHAR_ZERO; } else { str[last_figure] = fill_char; } } else { str[last_figure] = mFont_suji_data[temp2]; } cur_num = next; } for (i = last_figure; i >= 0; i--) { str[i] = left_fill_char; } if (separator) { int count = 0; for (i = figure - 1; i >= 0; i--) { if (mFont_suji_check(str[i])) { count++; if (count > 3) { for (j = 0; j < i; j++) { str[j] = str[j + 1]; } str[i] = CHAR_COMMA; count = 0; } } } } if (left_cut) { return mMsg_CutLeftSpace(str, figure); } return figure; } extern int mFont_char_save_data_check(u8 c) { return c == CHAR_CONTROL_CODE || c == CHAR_MESSAGE_TAG; } // TODO: Match extern u8 mFont_small_to_capital(u8 small) { static const u8 tbl[56][2] = { { CHAR_a, CHAR_A }, { CHAR_b, CHAR_B }, { CHAR_c, CHAR_C }, { CHAR_d, CHAR_D }, { CHAR_e, CHAR_E }, { CHAR_f, CHAR_F }, { CHAR_g, CHAR_G }, { CHAR_h, CHAR_H }, { CHAR_i, CHAR_I }, { CHAR_j, CHAR_J }, { CHAR_k, CHAR_K }, { CHAR_l, CHAR_L }, { CHAR_m, CHAR_M }, { CHAR_n, CHAR_N }, { CHAR_o, CHAR_O }, { CHAR_p, CHAR_P }, { CHAR_q, CHAR_Q }, { CHAR_r, CHAR_R }, { CHAR_s, CHAR_S }, { CHAR_t, CHAR_T }, { CHAR_u, CHAR_U }, { CHAR_v, CHAR_V }, { CHAR_w, CHAR_W }, { CHAR_x, CHAR_X }, { CHAR_y, CHAR_Y }, { CHAR_z, CHAR_Z }, { CHAR_DIARESIS_a, CHAR_DIAERESIS_A }, { CHAR_GRAVE_a, CHAR_GRAVE_A }, { CHAR_ACUTE_a, CHAR_ACUTE_A }, { CHAR_CIRCUMFLEX_a, CHAR_CIRCUMFLEX_A }, { CHAR_TILDE_a, CHAR_TILDE_A }, { CHAR_ANGSTROM_a, CHAR_ANGSTROM_A }, { CHAR_LOWER_CEDILLA, CHAR_CEDILLA }, { CHAR_GRAVE_e, CHAR_GRAVE_E }, { CHAR_ACUTE_e, CHAR_ACUTE_E }, { CHAR_CIRCUMFLEX_e, CHAR_CIRCUMFLEX_E }, { CHAR_DIARESIS_e, CHAR_DIARESIS_E }, { CHAR_GRAVE_i, CHAR_GRAVE_I }, { CHAR_ACUTE_i, CHAR_ACUTE_I }, { CHAR_CIRCUMFLEX_i, CHAR_CIRCUMFLEX_I }, { CHAR_DIARESIS_i, CHAR_DIARESIS_I }, { CHAR_LOWER_ETH, CHAR_ETH }, { CHAR_TILDE_n, CHAR_TILDE_N }, { CHAR_GRAVE_o, CHAR_GRAVE_O }, { CHAR_ACUTE_o, CHAR_ACUTE_O }, { CHAR_CIRCUMFLEX_o, CHAR_CIRCUMFLEX_O }, { CHAR_TILDE_o, CHAR_TILDE_O }, { CHAR_DIARESIS_o, CHAR_DIARESIS_O }, { CHAR_oe, CHAR_OE }, { CHAR_GRAVE_u, CHAR_GRAVE_U }, { CHAR_ACUTE_u, CHAR_ACUTE_U }, { CHAR_CIRCUMFLEX_u, CHAR_CIRCUMFLEX_U }, { CHAR_DIARESIS_u, CHAR_DIARESIS_U }, { CHAR_ACUTE_y, CHAR_ACUTE_Y }, { CHAR_LOWER_THORN, CHAR_THORN }, { CHAR_LOWER_ASH, CHAR_ASH } }; int i; for (i = 0; i < 56; i++) { if (tbl[i][0] == small) { return tbl[i][1]; } } return small; } static int mFont_Get_FontOffset(int c) { static u8 offset_data[256] = { 6, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 4, 4, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 7, 6, 5, 5, 5, 1, 4, 8, 6, 6, 1, 0, 8, 4, 8, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 1, 4, 3, 4, 4, 2, 3, 5, 4, 4, 5, 5, 4, 4, 6, 6, 5, 5, 2, 4, 4, 5, 3, 5, 5, 5, 4, 4, 2, 5, 5, 6, 5, 0, 5, 5, 3, 5, 5, 5, 5, 5, 6, 7, 5, 4, 7, 7, 6, 7, 3, 5, 5, 5, 4, 6, 6, 7, 5, 6, 3, 6, 6, 7, 5, 5, 5, 5, 0, 0, 6, 6, 6, 6, 8, 4, 5, 5, 5, 5, 5, 5, 3, 5, 5, 0, 5, 5, 5, 5, 5, 5, 6, 6, 5, 5, 4, 5, 6, 6, 6, 3, 4, 2, 3, 5, 2, 2, 0, 0, 0, 0, 0, 5, 5, 5, 0, 1, 1, 1, 0, 3, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, 8, 3, 8, 6, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 }; return offset_data[c]; } static u8* mFont_Get_FontTex_p() { return FONT_nes_tex_font1; } extern int mFont_GetCodeWidth(int c, int cut) { return mFont_TEX_CHAR_WIDTH - (cut ? mFont_Get_FontOffset(c) : 0); } extern int mFont_GetStringWidth(u8* str, int len, int cut) { int width = 0; int i; for (i = 0; i < len; i++) { width += mFont_GetCodeWidth(str[i], cut); } return width; } extern int mFont_GetStringWidth2(u8* str, int len, int cut) { int width = 0; int i; int skip_size; for (i = 0; i < len; i += skip_size) { u8 c = str[i]; if (c != CHAR_CONTROL_CODE) { width += mFont_GetCodeWidth(c, cut); } skip_size = mFont_CodeSize_get(str + i); } return width; } typedef struct control_code_s { s8 size; s8 attribute; } mFont_ControlCodeInfo_t; static mFont_ControlCodeInfo_t mFont_cont_info_tbl[mFont_CONT_CODE_NUM] = { { 2, mFont_CONT_ATTRIBUTE_0 }, { 2, mFont_CONT_ATTRIBUTE_0 }, { 2, mFont_CONT_ATTRIBUTE_0 }, { 3, mFont_CONT_ATTRIBUTE_0 }, { 2, mFont_CONT_ATTRIBUTE_0 }, { 5, mFont_CONT_ATTRIBUTE_0 }, { 2, mFont_CONT_ATTRIBUTE_0 }, { 2, mFont_CONT_ATTRIBUTE_0 }, { 5, mFont_CONT_ATTRIBUTE_DEMO }, { 5, mFont_CONT_ATTRIBUTE_DEMO }, { 5, mFont_CONT_ATTRIBUTE_DEMO }, { 5, mFont_CONT_ATTRIBUTE_DEMO }, { 5, mFont_CONT_ATTRIBUTE_DEMO }, { 2, mFont_CONT_ATTRIBUTE_0 }, { 4, mFont_CONT_ATTRIBUTE_0 }, { 4, mFont_CONT_ATTRIBUTE_0 }, { 4, mFont_CONT_ATTRIBUTE_0 }, { 4, mFont_CONT_ATTRIBUTE_0 }, { 4, mFont_CONT_ATTRIBUTE_0 }, { 6, mFont_CONT_ATTRIBUTE_0 }, { 8, mFont_CONT_ATTRIBUTE_0 }, { 10, mFont_CONT_ATTRIBUTE_0 }, { 6, mFont_CONT_ATTRIBUTE_0 }, { 8, mFont_CONT_ATTRIBUTE_0 }, { 10, mFont_CONT_ATTRIBUTE_0 }, { 2, mFont_CONT_ATTRIBUTE_0 }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_3 }, { 2, mFont_CONT_ATTRIBUTE_3 }, { 2, mFont_CONT_ATTRIBUTE_3 }, { 2, mFont_CONT_ATTRIBUTE_3 }, { 2, mFont_CONT_ATTRIBUTE_3 }, { 2, mFont_CONT_ATTRIBUTE_3 }, { 2, mFont_CONT_ATTRIBUTE_3 }, { 2, mFont_CONT_ATTRIBUTE_3 }, { 2, mFont_CONT_ATTRIBUTE_3 }, { 2, mFont_CONT_ATTRIBUTE_3 }, { 2, mFont_CONT_ATTRIBUTE_3 }, { 2, mFont_CONT_ATTRIBUTE_3 }, { 2, mFont_CONT_ATTRIBUTE_3 }, { 2, mFont_CONT_ATTRIBUTE_3 }, { 2, mFont_CONT_ATTRIBUTE_3 }, { 6, mFont_CONT_ATTRIBUTE_CHARACTER }, { 3, mFont_CONT_ATTRIBUTE_0 }, { 3, mFont_CONT_ATTRIBUTE_SENTENCE }, { 3, mFont_CONT_ATTRIBUTE_SENTENCE }, { 3, mFont_CONT_ATTRIBUTE_CHARACTER }, { 2, mFont_CONT_ATTRIBUTE_0 }, { 4, mFont_CONT_ATTRIBUTE_BGM }, { 4, mFont_CONT_ATTRIBUTE_BGM }, { 3, mFont_CONT_ATTRIBUTE_0 }, { 3, mFont_CONT_ATTRIBUTE_SE }, { 3, mFont_CONT_ATTRIBUTE_SENTENCE }, { 2, mFont_CONT_ATTRIBUTE_SE }, { 2, mFont_CONT_ATTRIBUTE_3 }, { 2, mFont_CONT_ATTRIBUTE_3 }, { 2, mFont_CONT_ATTRIBUTE_0 }, { 2, mFont_CONT_ATTRIBUTE_0 }, { 2, mFont_CONT_ATTRIBUTE_0 }, { 2, mFont_CONT_ATTRIBUTE_3 }, { 2, mFont_CONT_ATTRIBUTE_0 }, { 6, mFont_CONT_ATTRIBUTE_0 }, { 3, mFont_CONT_ATTRIBUTE_AGB_DUMMY }, { 3, mFont_CONT_ATTRIBUTE_AGB_DUMMY }, { 4, mFont_CONT_ATTRIBUTE_AGB_DUMMY }, { 3, mFont_CONT_ATTRIBUTE_SENTENCE }, { 2, mFont_CONT_ATTRIBUTE_AGB_DUMMY }, { 2, mFont_CONT_ATTRIBUTE_AGB_DUMMY }, { 6, mFont_CONT_ATTRIBUTE_0 }, { 2, mFont_CONT_ATTRIBUTE_AGB_DUMMY }, { 2, mFont_CONT_ATTRIBUTE_AGB_DUMMY }, { 3, mFont_CONT_ATTRIBUTE_AGB_DUMMY }, { 3, mFont_CONT_ATTRIBUTE_AGB_DUMMY }, { 3, mFont_CONT_ATTRIBUTE_AGB_DUMMY }, { 3, mFont_CONT_ATTRIBUTE_AGB_DUMMY }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 2, mFont_CONT_ATTRIBUTE_0 }, { 2, mFont_CONT_ATTRIBUTE_0 }, { 2, mFont_CONT_ATTRIBUTE_0 }, { 2, mFont_CONT_ATTRIBUTE_0 }, { 2, mFont_CONT_ATTRIBUTE_STRING }, { 4, mFont_CONT_ATTRIBUTE_0 }, { 4, mFont_CONT_ATTRIBUTE_0 }, { 12, mFont_CONT_ATTRIBUTE_0 }, { 14, mFont_CONT_ATTRIBUTE_0 } }; extern int mFont_CodeSize_get(u8* str) { int size = 1; int c0 = *str; int c1; if (c0 == CHAR_CONTROL_CODE) { c1 = *(str + 1); if (c1 >= 0 && c1 < mFont_CONT_CODE_NUM) { size = mFont_cont_info_tbl[c1].size; } else { size = 2; } } else if (c0 == CHAR_MESSAGE_TAG) { size = 2; } return size; } extern int mFont_CodeSize_idx_get(u8* str, int idx) { return mFont_CodeSize_get(str + idx); } extern int mFont_cont_attr_get(int cont_code) { return mFont_cont_info_tbl[cont_code].attribute; } extern void mFont_gppSetMode(Gfx** gfx_pp) { static Gfx disp[] = { gsDPPipeSync(), gsSPTexture(0x8000, 0x8000, 0, G_TX_RENDERTILE, G_ON), gsSPClearGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH), gsDPSetTextureLOD(G_TL_TILE), gsDPSetTextureConvert(G_TC_FILT), gsDPSetTextureLUT(G_TT_NONE), gsDPSetTextureFilter(G_TF_BILERP), gsDPSetCycleType(G_CYC_1CYCLE), gsDPSetTexturePersp(G_TP_PERSP), gsDPSetCombineMode(mFont_CC_FONT, mFont_CC_FONT), gsDPSetRenderMode(G_RM_XLU_SURF, G_RM_XLU_SURF2), gsDPSetPrimColor(0, 0, 255, 255, 255, 255), gsSPEndDisplayList() }; gSPDisplayList((*gfx_pp)++, disp); } extern void mFont_SetMode(GRAPH* graph, int mode) { Gfx* g; OPEN_DISP(graph); if (mode == 0) { g = NOW_POLY_OPA_DISP; mFont_gppSetMode(&g); SET_POLY_OPA_DISP(g); } else { g = NOW_FONT_DISP; mFont_gppSetMode(&g); SET_FONT_DISP(g); } CLOSE_DISP(graph); } static Gfx* mFont_gfxSetPrimColor(Gfx* gfx, int r, int g, int b, int a) { gDPSetPrimColor(gfx++, 0, 0, r, g, b, a); return gfx; } static Gfx* mFont_gppSetPrimColor(Gfx** gpp, rgba_t* color) { Gfx* g = *gpp; gDPSetPrimColor( g++, 0, 0, color->r, color->g, color->b, color->a ); *gpp = g; } extern void mFont_SetPrimColor(GRAPH* graph, int r, int g, int b, int a, int mode) { Gfx* gfx; OPEN_DISP(graph); if (mode == 0) { gfx = NOW_POLY_OPA_DISP; gfx = mFont_gfxSetPrimColor(gfx, r, g, b, a); SET_POLY_OPA_DISP(gfx); } else { gfx = NOW_FONT_DISP; gfx = mFont_gfxSetPrimColor(gfx, r, g, b, a); SET_FONT_DISP(gfx); } CLOSE_DISP(graph); } static Gfx* mFont_gfxSetCombineMode(Gfx* gfx, int no_font, int sync) { if (sync) { gDPPipeSync(gfx++); } if (no_font) { gDPSetCombineMode(gfx++, mFont_CC_FONT, mFont_CC_NOFONT); } else { gDPSetCombineMode(gfx++, mFont_CC_FONT, mFont_CC_FONT); } return gfx; } static void mFont_gppSetCombineMode(Gfx** gpp, int no_font, int sync) { Gfx* g = *gpp; if (sync) { gDPPipeSync(g++); } if (no_font) { gDPSetCombineMode(g++, mFont_CC_FONT, mFont_CC_NOFONT); } else { gDPSetCombineMode(g++, mFont_CC_FONT, mFont_CC_FONT); } *gpp = g; } extern void mFont_SetCombineMode(GRAPH* graph, int revert_flag, int mode) { Gfx* g; OPEN_DISP(graph); if (mode == 0) { g = NOW_POLY_OPA_DISP; g = mFont_gfxSetCombineMode(g, revert_flag, TRUE); SET_POLY_OPA_DISP(g); } else { g = NOW_FONT_DISP; g = mFont_gfxSetCombineMode(g, revert_flag, TRUE); SET_FONT_DISP(g); } CLOSE_DISP(graph); } static void mFont_gppLoadTexture(Gfx** gpp, int c, int* uls, int* ult, int* lrs, int* lrt) { Gfx* g = *gpp; u8* font_tex = mFont_Get_FontTex_p(); int t = c >> 4; int n_ult = t << 4; int n_uls = (c - n_ult) * mFont_TEX_CHAR_WIDTH; int n_lrs = n_uls + (mFont_TEX_CHAR_WIDTH - 1); int n_lrt = n_ult + (mFont_TEX_CHAR_HEIGHT - 1); gDPLoadTextureTile_4b_Dolphin( g++, font_tex, G_IM_FMT_I, mFont_TEX_CHAR_WIDTH * 16, mFont_TEX_CHAR_HEIGHT * 16 ); *gpp = g; *uls = n_uls; *ult = n_ult; *lrs = n_lrs; *lrt = n_lrt; } static void mFont_SetVertex_dol(Vtx* vtx, int x, int y, int s, int t) { vtx->v.ob[0] = x; vtx->v.ob[1] = y; vtx->v.ob[2] = 0; vtx->v.flag = 1; vtx->v.tc[0] = s; vtx->v.tc[1] = t; vtx->v.cn[0] = 0; vtx->v.cn[1] = 0; vtx->v.cn[2] = 0; vtx->v.cn[3] = 0; } // TEMP #define SCREEN_WIDTH 320 #define SCREEN_HEIGHT 240 #define HALF_SCR_WIDTH ((f32)(SCREEN_WIDTH / 2)) #define HALF_SCR_HEIGHT ((f32)(SCREEN_HEIGHT / 2)) #define NHALF_SCR_WIDTH ((f32)(-SCREEN_WIDTH / 2)) #define NHALF_SCR_HEIGHT ((f32)(-SCREEN_HEIGHT / 2)) extern f32 mFont_SetVertexRectangle( GAME* game, f32 x, f32 y, int s, int t, f32 scale_x, f32 scale_y, int mode ) { f32 sS = ((f32)s) * scale_x; f32 sT = ((f32)t) * scale_y; f32 n = x + sS; f32 pos_x = x - HALF_SCR_WIDTH; f32 pos_y = -y + HALF_SCR_HEIGHT; f32 start_x = pos_x; f32 start_y = pos_y; f32 end_x = start_x + sS; f32 end_y = start_y - sT; f32 l_ofs = 0.0f; f32 r_ofs = 0.0f; f32 t_ofs = 0.0f; f32 b_ofs = 0.0f; if (start_x > HALF_SCR_WIDTH || start_y < NHALF_SCR_HEIGHT || end_x < NHALF_SCR_WIDTH || end_y > HALF_SCR_HEIGHT) { return n; } { f32 dist_l = start_x - NHALF_SCR_WIDTH; f32 dist_t = start_y - HALF_SCR_HEIGHT; f32 dist_r = end_x - HALF_SCR_WIDTH; f32 dist_b = end_y - NHALF_SCR_HEIGHT; if (dist_l < 0.0f) { start_x = NHALF_SCR_WIDTH; l_ofs -= dist_l; } if (dist_t > 0.0f) { start_y = HALF_SCR_HEIGHT; t_ofs += dist_t; } if (dist_r > 0.0f) { end_x = HALF_SCR_WIDTH; r_ofs += dist_r; } if (dist_b < 0.0f) { end_y = NHALF_SCR_HEIGHT; b_ofs -= dist_b; } } { f32 inv_scale_x = 1.0f / scale_x; f32 inv_scale_y = 1.0f / scale_y; int vert_left_s = (int)(l_ofs * inv_scale_x) << 6; int vert_top_t = (int)(t_ofs * inv_scale_y) << 6; int vert_right_s = (int)(((f32)s) - r_ofs * inv_scale_x) << 6; int vert_bot_t = (int)(((f32)t) - b_ofs * inv_scale_y) << 6; int vert_left_x = (int)(start_x * mFont_SCALE_F); int vert_top_y = (int)(start_y * mFont_SCALE_F); int vert_right_x = (int)(end_x * mFont_SCALE_F); int vert_bot_y = (int)(end_y * mFont_SCALE_F); Vtx* vtx = GRAPH_ALLOC_TYPE(game->graph, Vtx, 4); Gfx* gfx = GRAPH_ALLOC_TYPE(game->graph, Gfx, 3); if (vtx != NULL && gfx != NULL) { mFont_SetVertex_dol(vtx++, vert_left_x, vert_top_y, vert_left_s, vert_top_t); mFont_SetVertex_dol(vtx++, vert_right_x, vert_top_y, vert_right_s, vert_top_t); mFont_SetVertex_dol(vtx++, vert_right_x, vert_bot_y, vert_right_s, vert_bot_t); mFont_SetVertex_dol(vtx, vert_left_x, vert_bot_y, vert_left_s, vert_bot_t); OPEN_DISP(game->graph); if (mode == 1) { gSPDisplayList(NOW_FONT_DISP++, gfx); } else { gSPDisplayList(NOW_POLY_OPA_DISP++, gfx); } CLOSE_DISP(game->graph); gSPVertex(gfx++, vtx - 3, 4, 0); gSPNTrianglesInit_5b( gfx++, 2, // 2 triangles 0, 2, 1, // 0 -> 2 -> 1 0, 3, 2, // 0 -> 3 -> 2 0, 0, 0 // unused ); gSPEndDisplayList(gfx); } } return n; } static f32 mFont_SetLineStrings_AndSpace_new( GAME* game, u8* str, int len, f32 x, f32 y, int r, int g, int b, int a, int flag_revert, int flag_cut, int unused, f32 scale_x, f32 scale_y, int mode ) { Gfx* g; mFontSentence sentence; int use_polygon_opaque = mode == 0; u32 flag; xy_t pos; xy_t scale; rgba_t color; if (fabsf(scale_x) < 0.001f || fabsf(scale_y) < 0.001f) { return 0.0f; } if (len <= 0) { return 0.0f; } OPEN_DISP(game->graph); if (use_polygon_opaque) { g = NOW_POLY_OPA_DISP; } else { g = NOW_FONT_DISP; } flag = mFont_SENTENCE_FLAG_USE_POLY; if (flag_revert) { flag |= mFont_SENTENCE_FLAG_REVERT; } if (flag_cut) { flag |= mFont_SENTENCE_FLAG_CUT; } pos.x = x; pos.y = y; scale.x = scale_x; scale.y = scale_y; color.r = r; color.g = g; color.b = b; color.a = a; mFontSentence_set(&sentence, str, len, flag, &pos, mFont_LineType_Top, &scale, &color, 0, 0, 0, 0, 0); mFontSentence_gppDraw(&sentence, game, &g); if (use_polygon_opaque) { SET_POLY_OPA_DISP(g); } else { SET_FONT_DISP(g); } CLOSE_DISP(game->graph); return sentence.width; } extern f32 mFont_SetLineStrings_AndSpace( GAME* game, u8* str, int len, f32 x, f32 y, int r, int g, int b, int a, int flag_revert, int flag_cut, int unused, f32 scale_x, f32 scale_y, int mode ) { return mFont_SetLineStrings_AndSpace_new( game, str, len, x, y, r, g, b, a, flag_revert, flag_cut, unused, scale_x, scale_y, mode ); } extern f32 mFont_SetLineStrings( GAME* game, u8* str, int len, f32 x, f32 y, int r, int g, int b, int a, int flag_revert, int flag_cut, f32 scale_x, f32 scale_y, int mode ) { return mFont_SetLineStrings_AndSpace( game, str, len, x, y, r, g, b, a, flag_revert, flag_cut, 0, scale_x, scale_y, mode ); } extern void mFont_CulcOrthoMatrix(Mtx* m) { guOrtho( m, NHALF_SCR_WIDTH * mFont_SCALE_F, HALF_SCR_WIDTH * mFont_SCALE_F, NHALF_SCR_HEIGHT * mFont_SCALE_F, HALF_SCR_HEIGHT * mFont_SCALE_F, -800.0f, 800.0f, 1.0f ); } extern void mFont_SetMatrix(GRAPH* graph, int mode) { static Mtx mtx_projection; static int first = TRUE; if (first) { mFont_CulcOrthoMatrix(&mtx_projection); first = FALSE; } Matrix_push(); Matrix_put(&MtxF_clear); OPEN_DISP(graph); if (mode == 1) { gSPMatrix(NOW_FONT_DISP++, &mtx_projection, G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH); gSPMatrix(NOW_FONT_DISP++, &Mtx_clear, G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH); } else { gSPMatrix(NOW_POLY_OPA_DISP++, &mtx_projection, G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH); gSPMatrix(NOW_POLY_OPA_DISP++, &Mtx_clear, G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH); } CLOSE_DISP(graph); } extern void mFont_UnSetMatrix(GRAPH* graph, int mode) { Matrix_pull(); } extern void mFont_Main_start(GRAPH* graph) { mFont_SetMode(graph, 1); } /* @unused f32 mFont_Get_NextCharRectX(???) */ /* @unused f32 mFont_Get_NextCharRectY(???) */ static void mFont_gppDrawCharRect( GRAPH* graph, Gfx** gfx_pp, int c, u32 ulx, u32 uly, u32 lrx, u32 lry, int dsdx, int dtdy ) { Gfx* g = *gfx_pp; int uls; int ult; int lrs; int lrt; mFont_gppLoadTexture(&g, c, &uls, &ult, &lrs, &lrt); // Convert to signed 10.5 format uls <<= 5; ult <<= 5; g = gfx_gSPTextureRectangle1(g, ulx, uly, lrx, lry, G_TX_RENDERTILE, (int)uls, (int)ult, dsdx, dtdy); *gfx_pp = g; } // TODO: Non-matching static void mFont_gppDrawCharPoly( GRAPH* graph, Gfx** gfx_pp, int c, xy_t* pos_tl, xy_t* pos_br, int s, int t ) { Gfx* g = *gfx_pp; Vtx* vtx = GRAPH_ALLOC_TYPE(graph, Vtx, 4); int uls, ult, lrs, lrt; int ulx, uly, lrx, lry; xy_t vert_tl, vert_br; f32 inv_half_s, inv_half_t; mFont_gppLoadTexture(&g, c, &uls, &ult, &lrs, &lrt); vert_tl.x = pos_tl->x - ((f32)SCREEN_WIDTH * 0.5f); vert_tl.y = -(pos_tl->y - ((f32)SCREEN_HEIGHT * 0.5f)); vert_br.x = pos_br->x - ((f32)SCREEN_WIDTH * 0.5f) - vert_tl.x; vert_br.y = -(pos_br->y - ((f32)SCREEN_HEIGHT * 0.5f)) - vert_tl.y; inv_half_s = 0.5f / (f32)s; inv_half_t = 0.5f / (f32)t; ulx = (vert_tl.x + vert_br.x * inv_half_s) * mFont_SCALE_F; uly = (vert_tl.y + vert_br.y * inv_half_t) * mFont_SCALE_F; lrx = (vert_tl.x + vert_br.x * (1.0f - inv_half_s)) * mFont_SCALE_F; lry = (vert_tl.y + vert_br.y * (1.0f - inv_half_t)) * mFont_SCALE_F; lrs = ((uls + s) << 6) - 32; lrt = ((ult + t) << 6) - 32; uls = (uls << 6) + 32; ult = (ult << 6) + 32; mFont_SetVertex_dol(vtx + 0, ulx, uly, uls, ult); mFont_SetVertex_dol(vtx + 1, ulx, lry, uls, lrt); mFont_SetVertex_dol(vtx + 2, lrx, lry, lrs, lrt); mFont_SetVertex_dol(vtx + 3, lrx, uly, lrs, ult); gSPVertex(g++, vtx, 4, 0); gSPNTrianglesInit_5b( g++, 2, // 2 tris 0, 1, 2, // tri 1 0, 2, 3, // tri 2 0, 0, 0 // unused ); *gfx_pp = g; } static void mFontChar_gppDraw_sentence_restore(mFontChar* this, mFontSentence* sentence, Gfx** gfx_pp) { if (this->color_ctr > 0) { this->color_ctr--; if (this->color_ctr == 0) { rgba_t_move(&this->color, &sentence->color); mFont_gppSetPrimColor(gfx_pp, &this->color); } } if ((this->flags & mFont_CHAR_FLAG_SCALE)) { this->scale.x = 1.0f; this->scale.y = 1.0f; this->inv_scale.x = 1.0f; this->inv_scale.y = 1.0f; this->flags &= ~mFont_CHAR_FLAG_SCALE; this->flags |= mFont_CHAR_FLAG_SCALE_RESET; } } static void mFontChar_total_scale_reset(mFontChar* this, mFontSentence* sentence) { if ((this->flags & mFont_CHAR_FLAG_SCALE_RESET)) { this->scaled_size.x = this->scale.x * sentence->scale.x * sentence->line_scale; this->scaled_size.y = this->scale.y * sentence->scale.y * sentence->line_scale; this->inv_scaled_size.x = this->inv_scale.x * sentence->inv_scale.x * sentence->inv_line_scale; this->inv_scaled_size.y = this->inv_scale.y * sentence->inv_scale.y * sentence->inv_line_scale; this->flags &= ~mFont_CHAR_FLAG_SCALE_RESET; } } static void mFontChar_ContProc_set_color_char(mFontChar* this, Gfx** gfx_pp) { this->color.r = this->char_p[2]; this->color.g = this->char_p[3]; this->color.b = this->char_p[4]; this->color.a = 255; this->color_ctr = this->char_p[5]; mFont_gppSetPrimColor(gfx_pp, &this->color); } static void mFontChar_ContProc_set_char_scale(mFontChar* this, Gfx** gfx_pp) { int scale_val = this->char_p[2]; f32 scale = (f32)scale_val * (1.0f / 32.0f); f32 inv_scale = 1.0f / scale; this->scale.x = scale; this->scale.y = scale; this->inv_scale.x = inv_scale; this->inv_scale.y = inv_scale; this->flags |= (mFont_CHAR_FLAG_SCALE | mFont_CHAR_FLAG_SCALE_RESET); } static mFont_ControlCodeCharFunc mFontChar_cont_proc_get(int control_code) { if (control_code == mFont_CONT_CODE_SET_COLOR_CHAR) { return mFontChar_ContProc_set_color_char; } else if (control_code == mFont_CONT_CODE_SET_CHAR_SCALE) { return mFontChar_ContProc_set_char_scale; } else { return NULL; } } static void mFontChar_set( mFontChar* this, u8* char_p, int len, u8 flags, xy_t* pos, xy_t* scale, xy_t* inv_scale, f32 ofs_y, rgba_t* color ) { bzero(this, sizeof(mFontChar)); this->char_p = char_p; this->len = len; this->flags = flags; this->position = *pos; this->scale = *scale; this->inv_scale = *inv_scale; this->ofs_y = ofs_y; rgba_t_move(&this->color, color); } static void mFontChar_gppDrawRect(mFontChar* this, GRAPH* graph, Gfx** gfx_pp) { u32 ulx, uly, lrx, lry; int dsdx, dtdy; f32 t; f32 width; t = -this->ofs_y; uly = (int)((t * this->scaled_size.y - t + this->position.y) * 4.0f); t = mFont_TEX_CHAR_HEIGHT_F32 - this->ofs_y; lry = (int)((t * this->scaled_size.y - t + this->position.y + mFont_TEX_CHAR_HEIGHT_F32) * 4.0f); ulx = (int)(this->position.x * 4.0f); width = (f32)mFont_GetCodeWidth(*this->char_p, this->flags & mFont_CHAR_FLAG_CUT) * this->scaled_size.x; lrx = (int)((width + this->position.x) * 4.0f); dsdx = (1024.0f * this->inv_scaled_size.x); /* 1 << 10 for correct s5.10 format? */ dtdy = (1024.0f * this->inv_scaled_size.y); /* 1 << 10 for correct s5.10 format? */ this->width = width; mFont_gppDrawCharRect(graph, gfx_pp, *this->char_p, ulx, uly, lrx, lry, dsdx, dtdy); } // TODO: match static void mFontChar_gppDrawPoly(mFontChar* this, GRAPH* graph, Gfx** gfx_pp) { xy_t top_left; xy_t bottom_right; f32 t; f32 width; int s; int c = *this->char_p; t = -this->ofs_y; top_left.y = (t * this->scaled_size.y) - t + this->position.y; t = mFont_TEX_CHAR_HEIGHT_F32 - this->ofs_y; bottom_right.y = (t * this->scaled_size.y) - t + this->position.y + mFont_TEX_CHAR_HEIGHT_F32; top_left.x = this->position.x; s = mFont_GetCodeWidth(c, this->flags & mFont_CHAR_FLAG_CUT); width = s * this->scaled_size.x; bottom_right.x = width + this->position.x; this->width = width; mFont_gppDrawCharPoly(graph, gfx_pp, c, &top_left, &bottom_right, s, mFont_TEX_CHAR_HEIGHT); } static void mFontChar_gppDraw(mFontChar* this, GRAPH* graph, Gfx** gfx_pp) { if (this->flags & mFont_CHAR_FLAG_USE_POLY) { mFontChar_gppDrawPoly(this, graph, gfx_pp); } else { mFontChar_gppDrawRect(this, graph, gfx_pp); } } static f32 mFontSentence_line_offset_calc(int line_type) { static f32 offset_value[mFont_LineType_End] = { mFont_TEX_CHAR_HEIGHT_F32 * 0.0f, mFont_TEX_CHAR_HEIGHT_F32 * 0.5f, mFont_TEX_CHAR_HEIGHT_F32 * 1.0f }; return offset_value[line_type]; } static void mFontSentence_ContProc_set_line_offset(mFontSentence* this, Gfx** gfx_pp) { mFontChar* character = &this->character; int t = (u8)(*(this->sentence_p + this->now_idx + 2)) - 128; this->offset = t; character->position.y = this->position.y + this->offset; } static void mFontSentence_ContProc_set_line_type(mFontSentence* this, Gfx** gfx_pp) { mFontChar* character = &this->character; int type = *(this->sentence_p + this->now_idx + 2); this->line_type = type; character->ofs_y = mFontSentence_line_offset_calc(this->line_type); } static void mFontSentence_ContProc_set_line_scale(mFontSentence* this, Gfx** gfx_pp) { mFontChar* character = &this->character; int scale = *(this->sentence_p + this->now_idx + 2); f32 f_scale = (f32)scale * (1.0f / 32.0f); f32 f_inv_scale = 1.0f / f_scale; this->line_scale = f_scale; this->inv_line_scale = f_inv_scale; character->flags |= mFont_CHAR_FLAG_SCALE_RESET; } static void mFontSentence_ContProc_space(mFontSentence* this, Gfx** gfx_pp) { mFontChar* character = &this->character; int c = *(this->sentence_p + this->now_idx + 2); this->width += c * character->scaled_size.x; } static mFont_ControlCodeSentenceFunc mFontSentence_cont_proc_get(int control_code) { if (control_code == mFont_CONT_CODE_SET_LINE_OFFSET) { return mFontSentence_ContProc_set_line_offset; } else if (control_code == mFont_CONT_CODE_SET_LINE_TYPE) { return mFontSentence_ContProc_set_line_type; } else if (control_code == mFont_CONT_CODE_SET_LINE_SCALE) { return mFontSentence_ContProc_set_line_scale; } else if (control_code == mFont_CONT_CODE_SPACE) { return mFontSentence_ContProc_space; } else { return NULL; } } static void mFontSentence_animal_voice_se(mFontSentence* this) { mFontChar* character = &this->character; f32 f_scale; int scale; f_scale = character->scale.x * character->scale.x + character->scale.y * character->scale.y; f_scale = sqrtf(f_scale); scale = this->line_scale * f_scale * (32.0f / SQRT_OF_2_F) + 0.5f; scale = scale < 0 ? 0 : (scale > 255 ? 255 : scale); // TODO: these definitely deserve to be promoted to defines or enums in the future. // Unsure which sfx & case this is referring to. if (this->voice_idx == 0x80 && this->se_character_id != 0 && scale == 32 && character->color.r == 50 && character->color.g == 60 && character->color.b == 50 && character->color.a == 255) { this->se_character_id = 0; } sAdo_VoiceSe(this->voice_idx, this->voice2_idx, this->voice3_idx, this->se_character_id, (u8)scale, 0); } extern void mFontSentence_set( mFontSentence* this, u8* sentence_p, int len, u32 flags, xy_t* pos, int line_type, xy_t* scale, rgba_t* color, int se_voice_pos, u8 voice_idx, u8 voice2_idx, u8 voice3_idx, s16 voice_se_character_idx ) { static xy_t unit_vec_xy = { 1.0f, 1.0f }; u8 character_flags = 0; bzero(this, sizeof(mFontSentence)); this->sentence_p = sentence_p; this->len = len; this->flags = flags; this->position = *pos; this->line_type = line_type; this->scale = *scale; this->inv_scale.x = 1.0f / scale->x; this->inv_scale.y = 1.0f / scale->y; this->line_scale = 1.0f; this->inv_line_scale = 1.0f; rgba_t_move(&this->color, color); this->se_pos = se_voice_pos; this->voice_idx = voice_idx; this->voice2_idx = voice2_idx; this->voice3_idx = voice3_idx; this->se_character_id = voice_se_character_idx; if (this->flags & mFont_SENTENCE_FLAG_CUT) { character_flags |= mFont_CHAR_FLAG_CUT; } if (this->flags & mFont_SENTENCE_FLAG_USE_POLY) { character_flags |= mFont_CHAR_FLAG_USE_POLY; } character_flags |= mFont_CHAR_FLAG_SCALE_RESET; mFontChar_set( &this->character, this->sentence_p, 1, character_flags, &this->position, &unit_vec_xy, &unit_vec_xy, mFontSentence_line_offset_calc(this->line_type), &this->color ); } static void mFontSentence_gppDraw_before(mFontSentence* this, Gfx** gfx_pp) { if (!(this->flags & mFont_SENTENCE_FLAG_3)) { if (this->flags & mFont_SENTENCE_FLAG_USE_POLY) { mFont_gppSetMode(gfx_pp); } else { mFont_gppSetRectMode(gfx_pp); } } if (!(this->flags & mFont_SENTENCE_FLAG_NO_COMBINE)) { mFont_gppSetCombineMode(gfx_pp, this->flags & mFont_SENTENCE_FLAG_REVERT, FALSE); } if (!(this->flags & mFont_SENTENCE_FLAG_NO_COLOR)) { mFont_gppSetPrimColor(gfx_pp, &this->color); } } static void mFontSentence_gppDraw_main(mFontSentence* this, GAME* game, Gfx** gfx_pp) { GRAPH* graph = game->graph; u8* char_p = this->sentence_p + this->now_idx; int c = *char_p; int char_size = mFont_CodeSize_get(char_p); this->character.char_p = char_p; this->character.len = char_size; if (c == CHAR_CONTROL_CODE) { int next = *(char_p + 1); int type = mFont_cont_attr_get(next); if (type == mFont_CONT_ATTRIBUTE_SENTENCE) { (mFontSentence_cont_proc_get(next))(this, gfx_pp); } else if (type == mFont_CONT_ATTRIBUTE_CHARACTER) { (mFontChar_cont_proc_get(next))(&this->character, gfx_pp); } } else { if (!((this->flags & mFont_SENTENCE_SKIP_DRAW_NEW_LINE) && c == CHAR_NEW_LINE)) { this->character.position.x = this->position.x + this->width; mFontChar_total_scale_reset(&this->character, this); mFontChar_gppDraw(&this->character, graph, gfx_pp); if ((this->flags & mFont_SENTENCE_FLAG_VOICE_SE) && this->now_idx == this->se_pos) { mFontSentence_animal_voice_se(this); } this->width += this->character.width; mFontChar_gppDraw_sentence_restore(&this->character, this, gfx_pp); } } this->now_idx += char_size; } static void mFontSentence_gppDraw_after(mFontSentence* this, Gfx** gfx_pp) { } extern void mFontSentence_gppDraw(mFontSentence* this, GAME* game, Gfx** gfx_pp) { mFontSentence_gppDraw_before(this, gfx_pp); while (this->now_idx < this->len) { mFontSentence_gppDraw_main(this, game, gfx_pp); } mFontSentence_gppDraw_after(this, gfx_pp); } static u8* mFont_Get_MarkTex_p(int mark_type) { static u8* tex_p_array[mFont_MARKTYPE_TOTAL] = { FONT_nes_tex_jyouge, FONT_nes_tex_sayuu, FONT_nes_tex_cursor, FONT_nes_tex_next, FONT_nes_tex_choice }; if (0 <= mark_type && mark_type < mFont_MARKTYPE_TOTAL && tex_p_array[mark_type] != NULL) { return tex_p_array[mark_type]; } return NULL; } static int mFont_Get_MarkTex_sizeW(int mark_type) { static int size_array[mFont_MARKTYPE_TOTAL] = { 16, 16, 16, 16, 16 }; if (0 <= mark_type && mark_type < mFont_MARKTYPE_TOTAL && size_array[mark_type] != 0) { return size_array[mark_type]; } return 0; } static int mFont_Get_MarkTex_sizeH(int mark_type) { static int size_array[mFont_MARKTYPE_TOTAL] = { 16, 16, 16, 16, 16 }; if (0 <= mark_type && mark_type < mFont_MARKTYPE_TOTAL && size_array[mark_type] != 0) { return size_array[mark_type]; } return 0; } // TODO: match extern f32 mFont_SetMarkChar( GAME* game, u8 mark_type, f32 x, f32 y, int r, int g, int b, int a, int revert_flag, f32 scale_x, f32 scale_y, int mode ) { f32 next_x = x; if ((int)mark_type < mFont_MARKTYPE_TOTAL) { u8* tex = mFont_Get_MarkTex_p(mark_type); int w = mFont_Get_MarkTex_sizeW(mark_type); int h = mFont_Get_MarkTex_sizeH(mark_type); GRAPH* graph = game->graph; Gfx* gfx = GRAPH_ALLOC_TYPE(graph, Gfx, 9); if (tex != NULL && w != 0 && h != 0 && gfx != NULL) { mFont_SetMode(graph, mode); mFont_SetPrimColor(graph, r, g, b, a, mode); mFont_SetCombineMode(graph, revert_flag, mode); OPEN_DISP(graph); if (mode == 1) { gSPDisplayList(NOW_FONT_DISP++, gfx); } else { gSPDisplayList(NOW_POLY_OPA_DISP++, gfx); } CLOSE_DISP(graph); /* TODO: they seem to have a secondary macro that does the operations directly */ gDPLoadTextureTile_4b_Dolphin( gfx++, tex, G_IM_FMT_I, w, h + mFont_TEX_CHAR_HEIGHT ); gSPEndDisplayList(gfx); next_x = mFont_SetVertexRectangle(game, x, y, w, h, scale_x, scale_y, mode); } } return next_x; } extern void mFont_gppSetRectMode(Gfx** gfx_pp) { static Gfx disp[] = { gsDPPipeSync(), gsSPTexture(0x8000, 0x8000, 0, G_TX_RENDERTILE, G_ON), gsSPClearGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH), gsDPSetTextureLOD(G_TL_TILE), gsDPSetTextureConvert(G_TC_FILT), gsDPSetTextureLUT(G_TT_NONE), gsDPSetTextureFilter(G_TF_BILERP), gsDPSetCycleType(G_CYC_1CYCLE), gsDPSetTexturePersp(G_TP_NONE), gsDPSetCombineMode(mFont_CC_FONT, mFont_CC_FONT), gsDPSetRenderMode(G_RM_AA_DEC_LINE, G_RM_AA_DEC_LINE2), gsDPSetPrimColor(0, 0, 255, 255, 255, 255), gsSPEndDisplayList(), }; gSPDisplayList((*gfx_pp)++, disp); }