#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 char bool; #define true 1 #define false 0 #include "fontdata.h" /*PsxUInt16 clut[] = { 0x0000, 0x7fff, 0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff, 0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff}; */ #define SPR_X 512 void pgpu(); void loadfont(); void nop(); void p2gpudone(); void p2gpucommand(); void p2gpuLF(); void p2gpuCR(); void WaitGPU(); void Clear_(void) { } void gpuInit(void) { 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(); // mem2vram(0, 0x01ff, 0x0010, 0x0001, (long*)clut); // For some bizzare reason, we have to send a bunch of commands (anything) // before anything else will be recognized after a mem2vram... // Spent the better part of 10 hrs trying odd things because this was // misbehaving... // for (i=0; i<16; i++) GPU_cw(0); } // Does nothing, just takes a cpu cycle or two void nop() { } PsxUInt32 t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, v0, v1, v2; // Pretend these are registers :) PsxUInt32 a1, a2; PsxUInt32 x0, y0; char * a0; bool bContinueLooping; bool bNext; /* 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; } /* Wrapper function for directly ported asm-based version of printGPU. Author: Jimb Esser Original Code: doomed@c64.org|psx.rules.org */ void printGPU(char *s, PsxUInt32 x, PsxUInt32 y, PsxInt32 color) { a0 = s; a1 = (x << 16) | y; x0 = x; y0 = y; a2 = color; pgpu(); } void WaitGPU() { PsxUInt32 v1=0; // ;------------------------------------------------------------- // ; WaitGPU - waits until GPU ready to recieve commands // ;------------------------------------------------------------- // lui fp,$1f80 while (v1==0) { // lw v1, GP1(fp) ; load status word from GPU v1 = GetGPUStatus(); // printf("%X\n", v1); // lui v0, $1000 ; load bit $1c // and v1, v1, v0 ; and out all but bit $1c v1 = v1 & 0x10000000; } // beqz v1, WaitGPU ; bit $1c = 0 -> GPU is busy // Skip: // nop // jr ra // nop } void pgpu() { /*;------------------------------------------------------------- *; PrintGPU - plots text to the screen without using DMA. *; in: a0 : pointer to string (0 terminated) *; a1 : hi word=Y, lo word=X *; a2 : color *;-------------------------------------------------------------*/ //PrintGPU // Skip these: // or t0,zero,ra ; save RA // jal WaitDone ; also sets fp to $1f800000 // nop /* li t1,$e100060f ; draw mode setting. li t2,$04000000 ; Dma transfer off command sw t2,GP1(fp) ; DMA mode = 0 nop sw t1,GP0(fp) ; Set texture page */ SendGPU(0x04000000); // DMA transfer off command WaitGPU(); GPU_cw(0xe1000700 | (SPR_X >> 6)); // Draw mode settings DisplayStatus(); //Skip sw a1,c2XY ; save XY // lui v0,$7400 ; type $70 = 8*8 sprite v0 = 0x7400 << 16; // or t1,a2,v0 ; t1 = type + color t1 = a2 | v0; // lui t2, 511<<6 ; t2 = clut (0,511) t2 = (511<<6) << 16; // lh t4,c2Y ; t5 = Y1 t4 = a1 & 0x0000FFFF; // lh t3,c2X ; t4 = X t3 = (a1 & 0xFFFF0000) >> 16; // addiu t5,t4,$08 ; t6 = Y2 t5 = t4 + 0x08; // printf("a1:%X, t3:%X, t4:%x, t5:%X\n", a1, t3, t4, t5); // lbu v0,$0000(a0) ; get character v0 = *a0; // nop nop(); // slti v1,v0,$0020 ; first char command -> handle. // bne v1,zero,p2gpucommand // nop if (v0 < 0x20) { // p2gpucommand(); } bContinueLooping=true; while (bContinueLooping) { //p2gpuloop: // ; find texture coords // andi v1,v0,$001f ; get loworder 5 bits // sll v1,v1,3 ; * 8 = u v1 = (v0 & 0x001f) << 3; // srl v0,v0,5 ; get highorder 3 bits v0 = v0>>5; // sll v0,v0,4 ; * 16 = v v0 = v0<<4; // printf("u,v:%X,%X\n", v1, v0); // sll t9,v0,$8 ; V Top part t9 = v0 << 8; // or t9,t9,v1 ; U t9 = t9 | v1; // or t9,t9,t2 ; Clut t9 = t9 | t2; // addiu v0,v0,$08 ; v0 = v0 + 8; // printf("u,v:%X,%X\n", v1, v0); // sll t6,v0,$8 ; V Bottom part t6 = v0 << 8; // or t6,t6,v1 ; U t6 = t6 | v1; // or t6,t6,t2 ; Clut t6 = t6 | t2; // ; Plot top half // sll t8,t4,$10 ; Y t8 = t4 << 0x10; // or t8,t8,t3 ; X t8 = t8 | t3; // jal WaitGPU WaitGPU(); // nop // sw t1,GP0(fp) ; set type RGB GPU_cw(t1); // sw t8,GP0(fp) ; Y X GPU_cw(t8); // sw t9,GP0(fp) ; clut U V GPU_cw(t9); // printf("sent %X,%X,%X\n", t1, t8, t9); // ; Bottom half // sll t8,t5,$10 ; Y t8 = t5 << 0x10; // or t8,t8,t3 ; X t8 = t8 | t3; // jal WaitGPU WaitGPU(); // nop // sw t1,GP0(fp) ; send type|BGR GPU_cw(t1); // sw t8,GP0(fp) ; send Y |X GPU_cw(t8); // sw t6,GP0(fp) ; send clut|U|V GPU_cw(t6); // printf("sent %X,%X,%X\n", t1, t8, t6); // addiu t3,t3,$08 ; x = x + 8 <- for proportional // ; feed char width here. t3 = t3 + 8; //p2gpunxt: bNext=true; while (bNext) { bNext=false; // addiu a0,a0,$01 ; next character a0++; // lbu v0,$0000(a0) ; fetch v0 = *a0; // nop ; nop(); // slti v1,v0,$0020 ; command char?->handle // bgtz v1,p2gpucommand ; if (v0 < 20) { p2gpucommand(); } // nop ; } // j p2gpuloop ; otherwise plot next char. } // while (continuelooping) // nop } void p2gpudone() { /* or ra,zero,t0 ; return if done. jr ra ; nop ;*/ bContinueLooping=false; } void p2gpucommand() { // beq v0,zero,p2gpudone ; done yet? if (v0==0) { p2gpudone(); return; } // ori v1,zero,$000a ; // beq v0,v1,p2gpuLF ; handle linefeed. if (v0==0x0a) { p2gpuLF(); return; } // ori v1,zero,$000d ; // beq v0,v1,p2gpuCR ; handle carriage return. if (v0==0x0d) { p2gpuCR(); return; } // nop ; discard unknown codes. // j p2gpunxt ; bNext=true; } void p2gpuLF() { //p2gpuLF addiu t4,t4,$0010 ; linefeed. // j p2gpunxt ; Y=Y+$10 // addiu t5,t5,$0010 ; t4 = t4 + 0x10; t5 = t5 + 0x10; bNext=true; } void p2gpuCR() { //p2gpuCR lw t3,c2X ; carriage return. // j p2gpunxt ; X = start X. // nop t3 = x0; bNext=true; } /* skip: c2XY ; Temp XY storage. c2X dh $0 ; c2Y dh $0 ; */ 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}; gpuInit(); loadfont(); // la a0,text2 ; a0 = pointer to string. // li a1,$00600018 ; a1 : y<<16|x (y=$20,x=$20) // li a2,$00208080 ; a2 : bgr = 808080 = white. // jal PrintGPU ; print // nop ; printGPU(s, 0x20, 0x20, 0x00ffffff); printGPU(s2, 0x20, 0x80, 0x007f2fff); printf("Done.\n"); while (1); }