#include #include #include #include #include #include #include #include #include #include #include #include #define SCREEN_WIDTH 640 #define SCREEN_HEIGHT_NTSC 224 #define SCREEN_HEIGHT_PAL 240 #define XRES (SCREEN_WIDTH/8) #define YRES 13 #include "fontdata_8x8.inc" #include "image.inc" u_char *fontdata = fontdata_8x8; char text[XRES*YRES]; char buf[1024]; sceGsDispEnv disp; sceGsLoadImage limg; struct { sceGifTag giftag; sceGsDrawEnv1 draw; sceGsClear clear; } dex; struct { sceGifTag giftag; sceGsTexEnv tex; } tex; struct { sceGifTag giftag; sceGsAlphaEnv alpha; } aex; uint clut[16]; uint charpkt[5*4]; #define STRIDE (128/2) u_char texbuf[128*STRIDE]; void init_config_system(void) { sceDevVif0Reset(); sceDevVu0Reset(); sceGsResetPath(); sceDmaReset(1); } uint getsr(void) { uint ret; __asm__ volatile("mfc0 %0, $12" : "=r"(ret)); return ret; } uint setsr(uint sr) { uint ret; __asm__ volatile( "mtc0 %1, $12\n" "sync.p\n" "mfc0 %0, $12\n" "sync.p\n" : "=r"(ret) : "r"(sr) ); return ret; } void kernelmode(void) { setsr(getsr() & ~0x11); } void usermode(void) { setsr(getsr() | 0x11); } u_char isntsc(void) { u_char ntsc; kernelmode(); ntsc = ((*(u_char*)0xBF803100) & 1) == 0; usermode(); return ntsc; } void putcharpkt(sceDmaChan *chGif, u_char c, int x, int y) { uint *p; p = charpkt; *p++ = 0x8000 | 1; // EOP, 1 NLOOP *p++ = 4<<(60-32) | (GS_PRIM_FST_M | GS_PRIM_ABE_M | GS_PRIM_TME_M | 6)<<(47-32) | 1<<(46-32); // 4 REGS, PRE *p++ = SCE_GS_XYZ2<<12 | SCE_GS_UV<<8 | SCE_GS_XYZ2<<4 | SCE_GS_UV; p++; *p++ = ((c%16)*8) << 4; *p++ = ((c/16)*8) << 4; p++; p++; *p++ = x << 4; *p++ = y << 4; p++; p++; *p++ = ((c%16 + 1)*8) << 4; *p++ = ((c/16 + 1)*8) << 4; p++; p++; *p++ = (x+8) << 4; *p++ = (y+8) << 4; p++; p++; FlushCache(0); sceDmaSendN(chGif, charpkt, 5); sceDmaSync(chGif, 0, 0); } void maketexbuf(void) { u_char *cp, *pp; uint bit; int chr, c, i, j; for(chr = 0; chr < 256; chr++) { cp = &fontdata[chr*8]; for(i = 0; i < 8; i++) { pp = &texbuf[((chr/16)*8 + i)*STRIDE + (chr%16)*(8/2)]; bit = 0x80; c = *cp++; for(j = 0; j < 8; j++) { if(j%2) { if(c & bit) pp[j/2] |= 0xF0; else pp[j/2] &= 0x0F; } else { if(c & bit) pp[j/2] |= 0x0F; else pp[j/2] &= 0xF0; } bit >>= 1; } } } } int main() { int ntsc, height; int fd, n, curX, curY; int numX, numY, offX, offY; char *p, c; ntsc = isntsc(); height = ntsc ? SCREEN_HEIGHT_NTSC : SCREEN_HEIGHT_PAL; init_config_system(); sceGsResetGraph(0, SCE_GS_NOINTERLACE, ntsc ? SCE_GS_NTSC : SCE_GS_PAL, SCE_GS_FRAME); sceGsResetPath(); sceGsSetDefDispEnv(&disp, SCE_GS_PSMCT32, SCREEN_WIDTH, height, 0, 0); sceGsPutDispEnv(&disp); sceGsSetDefDrawEnv(&dex.draw, SCE_GS_PSMCT32, SCREEN_WIDTH, height, 0, 0); dex.draw.xyoffset1.OFX = 0; dex.draw.xyoffset1.OFY = 0; sceGsSetDefClear(&dex.clear, 0, 0, 0, SCREEN_WIDTH, ntsc ? 240 : 288, 0, 0, 0, 0, 0); SCE_GIF_CLEAR_TAG(&dex.giftag); dex.giftag.NLOOP = 8 + 6; dex.giftag.EOP = 1; dex.giftag.NREG = 1; dex.giftag.REGS0 = 0xe; FlushCache(0); sceGsPutDrawEnv(&dex.giftag); clut[0] = 0x50000000; clut[15] = 0x80FFFFFF; sceGsSetDefLoadImage(&limg, 0x3000, 1, SCE_GS_PSMCT32, 0, 0, 8, 2); FlushCache(0); sceGsExecLoadImage(&limg, (u_long128*)clut); maketexbuf(); sceGsSetDefLoadImage(&limg, 0x2000, 128/64, SCE_GS_PSMT4, 0, 0, 128, 128); FlushCache(0); sceGsExecLoadImage(&limg, (u_long128*)texbuf); sceGsSetDefTexEnv(&tex.tex, 1, 0x2000, 128/64, SCE_GS_PSMT4, 7, 8, 1, 0x3000, SCE_GS_PSMCT32, 2, 0); SCE_GIF_CLEAR_TAG(&tex.giftag); tex.giftag.NLOOP = 4; tex.giftag.EOP = 1; tex.giftag.NREG = 1; tex.giftag.REGS0 = 0xe; FlushCache(0); sceGsPutDrawEnv(&tex.giftag); sceDmaChan *chGif = sceDmaGetChan(SCE_DMA_GIF); sceGsSetDefAlphaEnv(&aex.alpha, 0); SCE_GIF_CLEAR_TAG(&aex.giftag); aex.giftag.NLOOP = 4; aex.giftag.EOP = 1; aex.giftag.NREG = 1; aex.giftag.REGS0 = 0xe; FlushCache(0); sceGsPutDrawEnv(&aex.giftag); sceGsSetDefLoadImage(&limg, 0, SCREEN_WIDTH/64, SCE_GS_PSMCT24, (SCREEN_WIDTH-image_width)/2, (height-image_height)/2, image_width, image_height); FlushCache(0); sceGsExecLoadImage(&limg, (u_long128*)image); fd = sceOpen("host0:text", SCE_RDONLY); if(fd < 0) { printf("Can't open 'text'\n"); exit(1); } curX = 0; curY = 0; numX = 0; numY = 0; while(curY < YRES) { n = sceRead(fd, buf, sizeof(buf)); if(n == 0) break; p = buf; while(n-- > 0 && curY < YRES) { c = *p++; switch(c) { case '\r': break; default: text[curY*XRES + curX++] = c; numY = curY+1; if(numX < curX) numX = curX; if(curX < XRES) break; // fall through case '\n': curX = 0; curY++; break; case '\t': do text[curY*XRES + curX++] = ' '; while((curX&7) != 0 && curX < XRES); if(numX < curX) numX = curX; break; } } } sceClose(fd); offX = (SCREEN_WIDTH - 8*(numX+2)) / 2; offY = (height - 8*(numY+2) - 90) / 2 + 90; for(curX = 0; curX < numX+2; curX++) putcharpkt(chGif, ' ', curX*8 + offX, offY); for(curY = 0; curY < numY; curY++) { putcharpkt(chGif, ' ', offX, 8*(curY+1) + offY); for(curX = 0; curX < numX; curX++) putcharpkt(chGif, text[curY*XRES + curX], 8*(curX+1) + offX, 8*(curY+1) + offY); putcharpkt(chGif, ' ', 8*(numX+1) + offX, 8*(curY+1) + offY); } for(curX = 0; curX < numX+2; curX++) putcharpkt(chGif, ' ', curX*8 + offX, 8*(numY+1) + offY); sceGsSyncPath(0, 0); return 0; }