modified IPL font support to always use ANSI font by default (fix corrupted text on Japanese consoles)

This commit is contained in:
ekeeke31 2010-02-28 19:26:04 +00:00
parent 55a8c5a7ac
commit 62b3cce887

View File

@ -1,10 +1,10 @@
/***************************************************************************** /*****************************************************************************
* font.c * font.c
* *
* IPL FONT Engine, using GX hardware * IPL font engine
* *
* original font engine by Softdev (2006) * original font support by Softdev (2006)
* GX engine by Eke-Eke (2008,2009) * GX rendering by Eke-Eke (2008,2009)
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -26,9 +26,27 @@
#include "font.h" #include "font.h"
#include "gui.h" #include "gui.h"
int font_size[256], fheight; #define _SHIFTR(v, s, w) \
((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
typedef struct _yay0header {
unsigned int id ATTRIBUTE_PACKED;
unsigned int dec_size ATTRIBUTE_PACKED;
unsigned int links_offset ATTRIBUTE_PACKED;
unsigned int chunks_offset ATTRIBUTE_PACKED;
} yay0header;
int font_size[256];
int fheight;
static u8 *fontImage;
static u8 *fontTexture;
static void *ipl_fontarea;
static sys_fontheader *fontHeader;
#ifndef HW_RVL #ifndef HW_RVL
/* disable Qoob Modchip before IPL access (emukiddid) */ /* disable Qoob Modchip before IPL access (emukiddid) */
static void ipl_set_config(unsigned char c) static void ipl_set_config(unsigned char c)
{ {
@ -47,56 +65,135 @@ static void ipl_set_config(unsigned char c)
while (exi[0 * 5 + 3] & 1); while (exi[0 * 5 + 3] & 1);
exi[0] &= 0x405; //deselect IPL exi[0] &= 0x405; //deselect IPL
} }
#endif #endif
static sys_fontheader *fontHeader; static void decode_szp(void *src,void *dest)
static u8 *fontTexture;
int FONT_Init(void)
{ {
#ifndef HW_RVL u32 i,k,link;
/* disable Qoob before accessing IPL */ u8 *dest8,*tmp;
ipl_set_config(6); u32 loff,coff,roff;
#endif u32 size,cnt,cmask,bcnt;
yay0header *header;
/* initialize IPL font */ dest8 = (u8*)dest;
fontHeader = memalign(32,sizeof(sys_fontheader)); header = (yay0header*)src;
if (!fontHeader) return 0; size = header->dec_size;
SYS_InitFont(&fontHeader); loff = header->links_offset;
coff = header->chunks_offset;
/* character width table */ roff = sizeof(yay0header);
int i,c; cmask = 0;
for (i=0; i<256; ++i) cnt = 0;
{ bcnt = 0;
if ((i < fontHeader->first_char) || (i > fontHeader->last_char)) c = fontHeader->inval_char;
else c = i - fontHeader->first_char;
font_size[i] = ((unsigned char*)fontHeader)[fontHeader->width_table + c];
}
/* default font height */ do {
fheight = fontHeader->cell_height; if(!bcnt) {
cmask = *(u32*)(src+roff);
roff += 4;
bcnt = 32;
}
/* initialize texture data */ if(cmask&0x80000000) {
fontTexture = memalign(32, fontHeader->cell_width * fontHeader->cell_height / 2); dest8[cnt++] = *(u8*)(src+coff);
if (!fontTexture) coff++;
{ } else {
free(fontHeader); link = *(u16*)(src+loff);
return 0; loff += 2;
}
return 1; tmp = dest8+(cnt-(link&0x0fff)-1);
k = link>>12;
if(k==0) {
k = (*(u8*)(src+coff))+18;
coff++;
} else k += 2;
for(i=0;i<k;i++) {
dest8[cnt++] = tmp[i];
}
}
cmask <<= 1;
bcnt--;
} while(cnt<size);
} }
void FONT_Shutdown(void) static void expand_font(u8 *src,u8 *dest)
{ {
if (fontHeader) free(fontHeader); s32 cnt;
if (fontTexture) free(fontTexture); u32 idx;
u8 val1,val2;
sys_fontheader *sys_fontdata = fontHeader;
u8 *data = (u8*)sys_fontdata+44;
if(sys_fontdata->sheet_format==0x0000) {
cnt = (sys_fontdata->sheet_fullsize/2)-1;
while(cnt>=0) {
idx = _SHIFTR(src[cnt],6,2);
val1 = data[idx];
idx = _SHIFTR(src[cnt],4,2);
val2 = data[idx];
dest[(cnt<<1)+0] =((val1&0xf0)|(val2&0x0f));
idx = _SHIFTR(src[cnt],2,2);
val1 = data[idx];
idx = _SHIFTR(src[cnt],0,2);
val2 = data[idx];
dest[(cnt<<1)+1] =((val1&0xf0)|(val2&0x0f));
cnt--;
}
}
DCStoreRange(dest,sys_fontdata->sheet_fullsize);
}
static void GetFontTexel(s32 c,void *image,s32 pos,s32 stride)
{
u32 sheets,rem;
u32 xoff,yoff;
u32 xpos,ypos;
u8 *img_start;
u8 *ptr1,*ptr2;
sys_fontheader *sys_fontdata = fontHeader;
if(c<sys_fontdata->first_char || c>sys_fontdata->last_char) c = sys_fontdata->inval_char;
else c -= sys_fontdata->first_char;
sheets = sys_fontdata->sheet_column*sys_fontdata->sheet_row;
rem = c%sheets;
sheets = c/sheets;
xoff = (rem%sys_fontdata->sheet_column)*sys_fontdata->cell_width;
yoff = (rem/sys_fontdata->sheet_column)*sys_fontdata->cell_height;
img_start = fontImage+(sys_fontdata->sheet_size*sheets);
ypos = 0;
while(ypos<sys_fontdata->cell_height) {
xpos = 0;
while(xpos<sys_fontdata->cell_width) {
ptr1 = img_start+(((sys_fontdata->sheet_width/8)<<5)*((ypos+yoff)/8));
ptr1 = ptr1+(((xpos+xoff)/8)<<5);
ptr1 = ptr1+(((ypos+yoff)%8)<<2);
ptr1 = ptr1+(((xpos+xoff)%8)/2);
ptr2 = image+((ypos/8)*(((stride<<1)/8)<<5));
ptr2 = ptr2+(((xpos+pos)/8)<<5);
ptr2 = ptr2+(((xpos+pos)%8)/2);
ptr2 = ptr2+((ypos%8)<<2);
*ptr2 = *ptr1;
xpos += 2;
}
ypos++;
}
} }
static void DrawChar(unsigned char c, int xpos, int ypos, int size, GXColor color) static void DrawChar(unsigned char c, int xpos, int ypos, int size, GXColor color)
{ {
s32 width;
/* reintialize texture object */ /* reintialize texture object */
GXTexObj texobj; GXTexObj texobj;
GX_InitTexObj(&texobj, fontTexture, fontHeader->cell_width, fontHeader->cell_height, GX_TF_I4, GX_CLAMP, GX_CLAMP, GX_FALSE); GX_InitTexObj(&texobj, fontTexture, fontHeader->cell_width, fontHeader->cell_height, GX_TF_I4, GX_CLAMP, GX_CLAMP, GX_FALSE);
@ -104,12 +201,12 @@ static void DrawChar(unsigned char c, int xpos, int ypos, int size, GXColor colo
/* reinitialize font texture data */ /* reinitialize font texture data */
memset(fontTexture,0,fontHeader->cell_width * fontHeader->cell_height / 2); memset(fontTexture,0,fontHeader->cell_width * fontHeader->cell_height / 2);
SYS_GetFontTexel(c,fontTexture,0,fontHeader->cell_width/2,&width); GetFontTexel(c,fontTexture,0,fontHeader->cell_width/2);
DCFlushRange(fontTexture, fontHeader->cell_width * fontHeader->cell_height / 2); DCFlushRange(fontTexture, fontHeader->cell_width * fontHeader->cell_height / 2);
GX_InvalidateTexAll(); GX_InvalidateTexAll();
/* adjust texture width */ /* adjust texture width */
width = (fontHeader->cell_width * size) / fontHeader->cell_height; s32 width = (fontHeader->cell_width * size) / fontHeader->cell_height;
/* GX rendering */ /* GX rendering */
GX_Begin(GX_QUADS, GX_VTXFMT0, 4); GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
@ -129,37 +226,68 @@ static void DrawChar(unsigned char c, int xpos, int ypos, int size, GXColor colo
GX_DrawDone(); GX_DrawDone();
} }
/****************************************************************************
* IPL font support
*
****************************************************************************/
extern void __SYS_ReadROM(void *buf,u32 len,u32 offset);
void write_font(int x, int y, char *string) int FONT_Init(void)
{ {
int ox = x; #ifndef HW_RVL
while (*string && (x < (ox + 640))) /* --- Game Cube --- disable Qoob before accessing IPL */
ipl_set_config(6);
#endif
/* read IPL font (ASCII) from Mask ROM */
ipl_fontarea = memalign(32,131360);
if (!ipl_fontarea)
return 0;
memset(ipl_fontarea,0,131360);
__SYS_ReadROM(ipl_fontarea+119072,12288,0x1FCF00);
/* YAY0 decompression */
decode_szp(ipl_fontarea+119072,ipl_fontarea);
/* retrieve IPL font data */
fontHeader = (sys_fontheader*)ipl_fontarea;
fontImage = (u8*)((((u32)ipl_fontarea+fontHeader->sheet_image)+31)&~31);
/* expand to I4 format */
expand_font((u8*)ipl_fontarea+fontHeader->sheet_image,fontImage);
/* character width table */
int i,c;
for (i=0; i<256; ++i)
{ {
DrawChar(*string, x -(vmode->fbWidth/2), y-(vmode->efbHeight/2),fontHeader->cell_height,(GXColor)WHITE); if ((i < fontHeader->first_char) || (i > fontHeader->last_char))
x += font_size[(u8)*string]; c = fontHeader->inval_char;
string++; else
c = i - fontHeader->first_char;
font_size[i] = ((unsigned char*)fontHeader)[fontHeader->width_table + c];
} }
/* font height */
fheight = fontHeader->cell_height;
/* initialize texture data */
fontTexture = memalign(32, fontHeader->cell_width * fontHeader->cell_height / 2);
if (!fontTexture)
{
free(ipl_fontarea);
return 0;
}
return 1;
} }
void WriteCentre( int y, char *string) void FONT_Shutdown(void)
{ {
int x, t; if (fontHeader)
for (x=t=0; t<strlen(string); t++) x += font_size[(u8)string[t]]; free(ipl_fontarea);
if (x>640) x=640; if (fontTexture)
x = (640 - x) >> 1; free(fontTexture);
write_font(x, y, string);
}
void WriteCentre_HL( int y, char *string)
{
gx_texture *texture = gxTextureOpenPNG(Overlay_bar_png,0);
if (texture)
{
gxDrawTexture(texture, 0, y-fheight, 640, fheight,240);
if (texture->data) free(texture->data);
free(texture);
}
WriteCentre(y, string);
} }
int FONT_write(char *string, int size, int x, int y, int max_width, GXColor color) int FONT_write(char *string, int size, int x, int y, int max_width, GXColor color)
@ -234,6 +362,43 @@ void FONT_alignRight(char *string, int size, int x, int y, GXColor color)
} }
} }
/****************************************************************************
* Write functions (OLD)
*
****************************************************************************/
void write_font(int x, int y, char *string)
{
int ox = x;
while (*string && (x < (ox + 640)))
{
DrawChar(*string, x -(vmode->fbWidth/2), y-(vmode->efbHeight/2),fontHeader->cell_height,(GXColor)WHITE);
x += font_size[(u8)*string];
string++;
}
}
void WriteCentre( int y, char *string)
{
int x, t;
for (x=t=0; t<strlen(string); t++) x += font_size[(u8)string[t]];
if (x>640) x=640;
x = (640 - x) >> 1;
write_font(x, y, string);
}
void WriteCentre_HL( int y, char *string)
{
gx_texture *texture = gxTextureOpenPNG(Overlay_bar_png,0);
if (texture)
{
gxDrawTexture(texture, 0, y-fheight, 640, fheight,240);
if (texture->data) free(texture->data);
free(texture);
}
WriteCentre(y, string);
}
/**************************************************************************** /****************************************************************************
* Draw functions (FrameBuffer) * Draw functions (FrameBuffer)
* *