// Tab stops = 4 spaces #include "syscall.h" typedef signed char PsxInt8; typedef unsigned char PsxUInt8; typedef signed short PsxInt16; typedef unsigned short PsxUInt16; typedef signed int PsxInt32; typedef unsigned int PsxUInt32; typedef struct { PsxUInt8 r,g,b,code; PsxUInt16 x,y; PsxUInt8 u,v; PsxUInt16 clut; } SPRITE; typedef char bool; #define true 1 #define false 0 #include "fontdata.h" #define SPR_X 512 void loadfont(); void nop(); bool p2gpucommand(SPRITE*s0, SPRITE*s1, char c, bool* bQuit, PsxUInt32 x0); void WaitGPU(); void Clear_(void) { } void gpuInit(void) { // printf("Initing..."); SendGPU(0); /* Some kind of reset ? */ Clear_(); SendGPU(0x05000000); /* Display offset */ WaitGPU(); SendGPU(0x03000000); /* Display Mask (enable display) */ Clear_(); SendGPU(0x06c60260); /* Screen horizontal start/end (0/256) */ Clear_(); SendGPU(0x07040010); /* Screen vertical start/end (0/240) */ Clear_(); SendGPU(0x08000000); /* Display mode, 256x240/NTSC/noninterlaced */ Clear_(); GPU_cw(0xe10006cf); /* Draw on display area / dither on / texture page */ Clear_(); //0xe10006cf GPU_cw(0xe3000000); /* Draw Area x, y (0,0) */ Clear_(); GPU_cw(0xe407429f); /* Draw Area w, h (...,...) */ // GPU_cw(0xe407ffff); /* Draw Area w, h (1023,511) */ Clear_(); GPU_cw(0xe5000000); /* Draw Offset (0,0) */ Clear_(); } void loadfont() { int i; WaitGPU(); mem2vram(SPR_X,0,256,64,(long*)fontdata); WaitGPU(); } // Does nothing, just takes a cpu cycle or two void nop() { } /* Verbosely displays the current graphics status. Calls GetGPUStatus() and interprets. Author : Jimb Esser */ void DisplayStatus() { PsxUInt32 s = GetGPUStatus(); PsxUInt32 t; printf("Status : 0x%X :\n", s); t = s & 0xf; printf(" Texture Page: x:%d y:%d ", t*64, (s&0x10)?256:0); s = s >> 5; printf("abr: %d ", s&0x3); s = s>>2; printf("texpage : "); switch (s & 0x3) { case 0: printf("4bit CLUT"); break; case 1: printf("8bit CLUT"); break; case 2: printf("15bit"); break; } s = s >> 2; printf(" dither: %s\n", (s&1)?"on":"off"); s = s >> 1; printf(" draw2display: %s", (s&1)?"on":"off"); s = s >> 1; printf(" applymask: %s", (s&1)?"on":"off"); s = s >> 1; printf(" nodraw2mask: %s\n", (s&1)?"on":"off"); s = s >> 1; s = s >> 3; // unused bits; if (s&1) { printf(" 384x"); } else { switch ((s >> 1)&3) { case 0: printf(" 256x"); break; case 1: printf(" 320x"); break; case 2: printf(" 512x"); break; case 3: printf(" 640x"); break; } } s = s >> 3; printf("%d ", (s&1)?480:240); s = s >> 1; printf("%s ", (s&1)?"PAL":"NTSC"); s = s >> 1; printf("%s ", (s&1)?"24bit":"15bit"); s = s >> 1; printf("Interlace %s, ", (s&1)?"on":"off"); s = s >> 1; printf("Display %s, ", (s&1)?"off":"on"); s = s >> 1; s = s >> 2; // Unused bits printf("GPU %s, ", (s&1)?"idle":"busy"); s = s >> 1; printf("img %s,\n", (s&1)?"ready":"not ready"); s = s >> 1; printf("Command %s, ", (s&1)?"ready":"not ready"); s = s >> 1; printf("DMA: "); switch (s&3) { case 0: printf("off"); break; case 1: printf("unknown"); break; case 2: printf("CPU->GPU"); break; case 3: printf("GPU->CPU"); break; } s = s >> 2; printf(", drawing %s\n", (s&1)?"odd":"even"); s = s >> 1; } /* Waits for the Command Ready bit of the GPU status to be flagged */ void WaitGPU() { PsxUInt32 v1=0; while (v1==0) { v1 = GetGPUStatus(); v1 = v1 & 0x10000000; } } /* Prints characters using the font loaded with loadfont() listed above by drawing 2 8x8 sprites for each 8x16 text character. Author: Jimb Esser Original Code: doomed@c64.org|psx.rules.org */ void printGPU(char *s, PsxUInt32 x, PsxUInt32 y, PsxInt32 color) { char *c = s; bool bContinueLooping; bool bNext; PsxUInt32 x0 = x; PsxUInt32 y0 = y; PsxUInt32 clut = 0; // Color LookUp Table (not used) SPRITE s0, s1; // Initialize two sprites for the two blits we need to do to draw a character *(long*)(&s0.r) = color; // Copy all color values at once *(long*)(&s1.r) = color; s0.code = 0x74; // 0x74 is an 8x8 sprite s1.code = 0x74; s0.clut = clut; s1.clut = clut; s0.x = x; s0.y = y; s1.x = x; s1.y = y + 8; SendGPU(0x04000000); // DMA transfer off command WaitGPU(); GPU_cw(0xe1000700 | (SPR_X >> 6)); // Draw mode settings - pass in address of texture page // DisplayStatus(); // command characters if (*c < 0x20) { p2gpucommand(&s0, &s1, *c, &bContinueLooping, x0); } bContinueLooping=true; while (bContinueLooping) { // find texture coords // get loworder 5 bits * 8 // same as u = *c % 32 (32 chars per line in the font texture) s0.u = (*c & 0x001f) << 3; // get highorder 3 bits * 16 // same as u = *c / 32 (32 chars per line in the font texture) s0.v = *c>>5; s0.v = s0.v<<4; // Wait for the GPU to be ready, and then send commands WaitGPU(); GPU_cwb((long*)&s0, 3); // Bottom half of the letter // Texture coords s1.u = s0.u; s1.v = s0.v + 8; WaitGPU(); GPU_cwb((long*)&s1, 3); // For a proportional font, we'd feed the width here s0.x += 8; s1.x += 8; // Grab the next character bNext=true; while (bNext) { bNext=false; c++; if (*c < 20) { bNext = p2gpucommand(&s0, &s1, *c, &bContinueLooping, x0); } } } // while (continuelooping) } bool p2gpucommand(SPRITE*s0, SPRITE*s1, char c, bool* bQuit, PsxUInt32 x0) { if (c==0) { *bQuit=false; return false; } // Linefeed if (c==0x0a) { s0->y = s0->y + 0x10; s1->y = s1->y + 0x10; return true; } // Carriage return if (c==0x0d) { s0->x = x0; s1->x = x0; return true; } return true; } int main(int argc,char **argv) { int i; char s[255] = "Testing\r\n some text"; char s2[255] = "In different\r\n colors!"; long t[3] = {0x7C2F8F8F, 0x00200020, 0x7FC02020}; // printf("Initing...\n"); gpuInit(); // printf("Loading font...\n"); loadfont(); // printf("Printing...\n"); printGPU(s, 0x20, 0x20, 0x00ffffff); printGPU(s2, 0x20, 0x80, 0x007f2fff); printf("Done.\n"); while (1); }