// Frame Buffer viewer for PSYCHOS! (Type "siocons auto" to run.) // // Ever point a video camera at the TV screen that's showing what // the camera sees and wave it around? If you have and PARTICULARLY // enjoyed yourself then this 'game' is for you. Just move the pad // around and experience psychotic-tendancy-inducing nausea-floudering // mayhem. If you start saying 'wow' and words like 'infinity' it's // time to stop. // Originally I made it as a frame buffer viewer to see if TIMs/CLUTs etc // have loaded into video RAM properly and in the right place but // discovered that the SIOCONS tool thing wipes the whole thing, so // you have to code it into your programs. BUT it is a basic example // of how to have a virtual screen on the FB, and how to have the visible // screen anywhere you want. (in this case the middle of the FB). // If you play around with the delightful wavyness for over 10 minutes // you are guaranteed to have a migraine. Oh, I should probably warn // epileptics not to even try it.. // by James Shaughnessy james@manc.u-net.com // http://www.netyaroze-europe.com/~shaughnj #include #include #include "pad.h" extern DISPENV GsDISPENV; void PaintFB(); main() { u_long PadStatus = 0; RECT *scr; short inc, maxxpos = 768, maxypos = 256; // Setup graphics PAL SetVideoMode(MODE_PAL); GsInitGraph(256, 256, 4, 0, 0); GsDISPENV.screen.x = 0; GsDISPENV.screen.y = 20; GsDISPENV.screen.w = 256; GsDISPENV.screen.h = 256; GsDISPENV.disp.x = 384; GsDISPENV.disp.y = 136; GsDISPENV.disp.w = 256; GsDISPENV.disp.h = 256; //GsDISPENV.isinter = 1; //GsDISPENV.isrgb24 = 1; GsDefDispBuff(384, 136, 384, 136); PadInit(); scr->x = 384; scr->y = 136; scr->w = 256; scr->h = 256; PaintFB(); while(1) { PadStatus = PadRead(); // Quit if both Select and Start pressed if (PadStatus & PAD1select && PadStatus & PAD1start) break; inc = 1; if (PadStatus & PAD1R1) { inc +=3; if (PadStatus & PAD1L1) inc +=4; } if (PadStatus & PAD1Lleft) scr->x-=inc; if (PadStatus & PAD1Lright) scr->x+=inc; if (PadStatus & PAD1Lup) scr->y-=inc; if (PadStatus & PAD1Ldown) scr->y+=inc; if (scr->x < 0) scr->x = 0; else if (scr->x > maxxpos) scr->x = maxxpos; if (scr->y < 0) scr->y = 0; else if (scr->y > maxypos) scr->y = maxypos; // Wait for a vertical blank VSync(0); // Copy virtual screen to visible area MoveImage(scr, 384, 136); DrawSync(0); GsSwapDispBuff(); } ResetGraph(0); } void PaintFB() { short x, y; RECT box, FB; FB.x = FB.y = 0; FB.w = 1024; FB.h = 512; ClearImage(&FB, 0, 0, 0); box.w = 4; box.h = 5; for (y=0; y < 512; y+=6) { for (x=0; x < 1024; x+=5) { box.x = x; box.y = y; ClearImage(&box, rand()%256, rand()%256, rand()%256); } } } // ****** PAD routines ****** // low-level pad buffers: never need to touch volatile u_char *bb0, *bb1; // call once only in program initialisation void PadInit (void) { GetPadBuf(&bb0, &bb1); } // call once per VSync(0) // puts controller pad status into unsigned long integer // please refer to the manuals if you want explanation // of the internals of this function u_long PadRead(void) { return(~(*(bb0+3) | *(bb0+2) << 8 | *(bb1+3) << 16 | *(bb1+2) << 24)); }