// Funky Spirals - 31st January 1998 // (Tidied up 23rd February 1998) // - V 1.2 - // // James Rutherford (Mr. Frosty - Hex Heroes) // // http://www.netyaroze-europe.com/~mrfrosty // j.t.rutherford@sms.ed.ac.uk // I've given the code quite a thorough commenting, // I hope you can follow it okay... // // James. // ---------------------> Things To Play With <--------------------- // Uncomment the following line for NTSC displays (default is PAL) // #define NTSC // Play about with this to vertically centre the screen // (should be alright at 15 for PAL - probably for NTSC too...) #define YSCREEN_CENTRE 15 // -------------> Inclusions, Definitions and Globals <------------- // // N.B. Globals are prefixed by GBL_ to prevent confusion... #include // Uses fcontrol v1.5 #include "fcontrol.h" #define OT_LENGTH 1 GsOT GBL_world_ot[2]; GsOT_TAG GBL_world_ot_tag[2][1< Prototypes <-------------------------- // Main Stuff void DoSpirals(void); void PrintDebugInfo(GsSPRITE* screensprite); // Controller Handling int AllControllers(GsSPRITE* screensprite, int port); int StdPadControl(GsSPRITE* screensprite, int port); int AnaPadControl(GsSPRITE* screensprite, int port); int IllegalController(GsSPRITE* screensprite); // General Stuff void InitialiseAll(void); void CloseDown(void); // -------------------------> Procedures <-------------------------- void main(void) { InitialiseAll(); DoSpirals(); CloseDown(); } void DoSpirals(void) { int exit_now = 0; int n; // oldscreen is the fading copy of the screen (being fed-back) // movescreen is the new copy of the screen (rotated and scaled) // Two of each are used for simplicity, one for each of the double // buffers. GsSPRITE oldscreen[2], movescreen[2]; oldscreen[0].attribute = (2<<24); // (2<<24) sets 15bit direct oldscreen[0].x = 0; oldscreen[0].y = 0; oldscreen[0].w = 256; oldscreen[0].h = 256; oldscreen[0].tpage = GetTPage(2,0,0,0); oldscreen[0].u = 0; oldscreen[0].v = 0; oldscreen[0].r = 125; // 125 fades the feedback copy a little oldscreen[0].g = 125; // N.B. 128 would be normal brightness... oldscreen[0].b = 125; oldscreen[0].mx = 256/2; oldscreen[0].my = 256/2; oldscreen[0].scalex = ONE; oldscreen[0].scaley = ONE; oldscreen[0].rotate = 0; oldscreen[1].attribute = (2<<24); oldscreen[1].x = 0; oldscreen[1].y = 0; oldscreen[1].w = 256; oldscreen[1].h = 256; oldscreen[1].tpage = GetTPage(2,0,0,256); oldscreen[1].u = 0; oldscreen[1].v = 0; oldscreen[1].r = 125; oldscreen[1].g = 125; oldscreen[1].b = 125; oldscreen[1].mx = 256/2; oldscreen[1].my = 256/2; oldscreen[1].scalex = ONE; oldscreen[1].scaley = ONE; oldscreen[1].rotate = 0; movescreen[0].attribute = (2<<24) + (1<<30); movescreen[0].x = 128; movescreen[0].y = 128; movescreen[0].w = 256; movescreen[0].h = 256; movescreen[0].tpage = GetTPage(2,0,0,0); movescreen[0].u = 0; movescreen[0].v = 0; movescreen[0].r = 128; movescreen[0].g = 128; movescreen[0].b = 128; movescreen[0].mx = 256/2; movescreen[0].my = 256/2; movescreen[0].scalex = ONE; movescreen[0].scaley = ONE; movescreen[0].rotate = 0; movescreen[1].attribute = (2<<24) + (1<<30); movescreen[1].x = 128; movescreen[1].y = 128; movescreen[1].w = 256; movescreen[1].h = 256; movescreen[1].tpage = GetTPage(2,0,0,256); movescreen[1].u = 0; movescreen[1].v = 0; movescreen[1].r = 128; movescreen[1].g = 128; movescreen[1].b = 128; movescreen[1].mx = 256/2; movescreen[1].my = 256/2; movescreen[1].scalex = ONE; movescreen[1].scaley = ONE; movescreen[1].rotate = 0; // Setup graphics environment. GsInitGraph(256,256, GsOFSGPU, 1, 0); GsDefDispBuff(0, 0, 0, 256); // Patch for proper display - thanks to Alex Herbert (see newsgroups) GsDISPENV.screen.h = 256; GsDISPENV.screen.y = YSCREEN_CENTRE; // This little loop is needed to stop the brick screen from feeding // back... for(n=0; n<2; n++) { GBL_active_buffer = GsGetActiveBuff(); GsSetWorkBase(GBL_gpu_packet_area[GBL_active_buffer]); GsClearOt(0, 0, &GBL_world_ot[GBL_active_buffer]); DrawSync(0); VSync(0); GsSwapDispBuff(); GsSortClear(0, 0, 0, &GBL_world_ot[GBL_active_buffer]); GsDrawOt(&GBL_world_ot[GBL_active_buffer]); } // This is the main loop... while(exit_now == 0) { GBL_active_buffer = GsGetActiveBuff(); GsSetWorkBase(GBL_gpu_packet_area[GBL_active_buffer]); GsClearOt(0, 0, &GBL_world_ot[GBL_active_buffer]); // Do Stuff // ...There's not actually a lot to do, AllControllers (below) // takes care of all the movements and the sprites are // automatically registered below anyway. // Register Stuff DrawSync(0); GBL_vtimer = VSync(0); GsSwapDispBuff(); // AllControllers(blah) twiddles the moving screen important bits. // exit_now becomes -1 for exit, 0 otherwise. exit_now = AllControllers(&movescreen[GBL_active_buffer], PORT_ONE); // copy movescreen important bits to movescreen for the other buffer. movescreen[1-GBL_active_buffer].scalex = movescreen[GBL_active_buffer].scalex; movescreen[1-GBL_active_buffer].scaley = movescreen[GBL_active_buffer].scaley; movescreen[1-GBL_active_buffer].rotate = movescreen[GBL_active_buffer].rotate; // Sort sprites into OT... GsSortSprite(&movescreen[GBL_active_buffer], &GBL_world_ot[GBL_active_buffer], 0); GsSortFastSprite(&oldscreen[GBL_active_buffer], &GBL_world_ot[GBL_active_buffer], 0); // ...and draw it. GsDrawOt(&GBL_world_ot[GBL_active_buffer]); // Flush debug font to screen. FntFlush(-1); } } void PrintDebugInfo(GsSPRITE* screensprite) { FntPrint("Funky Spirals\n"); FntPrint("Vtime = %d\n", GBL_vtimer); FntPrint("scalex %d of 4096\n", screensprite->scalex); FntPrint("scaley %d of 4096\n", screensprite->scaley); FntPrint("rotate %d\n", (screensprite->rotate)/ONE); } // Returns -1 for exit, 0 otherwise int AllControllers(GsSPRITE* screensprite, int port) { u_char contype = FControllerType(port); switch(contype) { case CONTYPE_STANDARD_PAD: return(StdPadControl(screensprite, port)); break; case CONTYPE_ANALOGUE_PAD: return(AnaPadControl(screensprite, port)); break; default: return(IllegalController(screensprite)); } } // Returns -1 for exit, 0 otherwise int StdPadControl(GsSPRITE* screensprite, int port) { u_short fspad = FSPadRead(port); if(fspad & SPADleft) { screensprite->scalex -= 16; if(screensprite->scalex < 2048) screensprite->scalex = 2048; } if(fspad & SPADright) { screensprite->scalex += 16; if(screensprite->scalex > (2048 + 4096)) screensprite->scalex = (2048 + 4096); } if(fspad & SPADup) { screensprite->scaley -= 16; if(screensprite->scaley < 2048) screensprite->scaley = 2048; } if(fspad & SPADdown) { screensprite->scaley += 16; if(screensprite->scaley > (2048 + 4096)) screensprite->scaley = (2048 + 4096); } if(fspad & SPADsq) { screensprite->rotate -= (16*40); if(screensprite->rotate < -(ONE*20)) screensprite->rotate = -(ONE*20); } if(fspad & SPADci) { screensprite->rotate += (16*40); if(screensprite->rotate > (ONE*20)) screensprite->rotate = (ONE*20); } if(fspad & SPADl1) GsSortBoxFill(&GBL_gsboxf[0], &GBL_world_ot[GBL_active_buffer], 0); if(fspad & SPADl2) GsSortBoxFill(&GBL_gsboxf[1], &GBL_world_ot[GBL_active_buffer], 0); if(fspad & SPADr1) GsSortBoxFill(&GBL_gsboxf[2], &GBL_world_ot[GBL_active_buffer], 0); if(fspad & SPADr2) GsSortBoxFill(&GBL_gsboxf[3], &GBL_world_ot[GBL_active_buffer], 0); if(fspad & SPADstart) PrintDebugInfo(screensprite); if(fspad & SPADselect) return(-1); else return(0); } // Returns -1 for exit, 0 otherwise int AnaPadControl(GsSPRITE* screensprite, int port) { u_short fapad = FAPadRead(port); screensprite->scalex = 2048 + (4096 * FAPadStick255(port, APADl3x))/255; screensprite->scaley = 2048 + (4096 * FAPadStick255(port, APADl3y))/255; screensprite->rotate = -ONE*20 + (ONE*40 * FAPadStick255(port, APADr3x))/255; if(fapad & APADl1) GsSortBoxFill(&GBL_gsboxf[0], &GBL_world_ot[GBL_active_buffer], 0); if(fapad & APADl2) GsSortBoxFill(&GBL_gsboxf[1], &GBL_world_ot[GBL_active_buffer], 0); if(fapad & APADr1) GsSortBoxFill(&GBL_gsboxf[2], &GBL_world_ot[GBL_active_buffer], 0); if(fapad & APADr2) GsSortBoxFill(&GBL_gsboxf[3], &GBL_world_ot[GBL_active_buffer], 0); if(fapad & APADstart) PrintDebugInfo(screensprite); if(fapad & APADselect) return(-1); else return(0); } // Returns 0 for [no-exit]. int IllegalController(GsSPRITE* screensprite) { screensprite->scalex = ONE; screensprite->scaley = ONE; screensprite->rotate = 0; FntPrint("%s\n%s\n", "Sorry! Pad Not Supported.", "Standard or analogue pads only."); return(0); } void InitialiseAll(void) { // Set Screen Mode #ifdef NTSC SetVideoMode(MODE_NTSC); #else SetVideoMode(MODE_PAL); #endif // Setup Control Port Interface FSetPortBuffers(); // Setup OT Stuff GBL_world_ot[0].length = OT_LENGTH; GBL_world_ot[0].org = GBL_world_ot_tag[0]; GBL_world_ot[1].length = OT_LENGTH; GBL_world_ot[1].org = GBL_world_ot_tag[1]; // Load Debug Font FntLoad(960, 256); FntOpen(0, 0, 256, 256, 0, 512); } void CloseDown(void) { // why 3? - I still haven't figured it out, but // it's what everyone else does, so... ResetGraph(3); }