/************************************************************ * * * 2d1.c * * * * * LPGE 1997 * * * * Copyright (C) 1996 Sony Computer Entertainment Inc. * * All Rights Reserved * * * ***********************************************************/ /**************************************************************************** includes ****************************************************************************/ #include "2d1.h" #include "trig.h" /**************************************************************************** functions ****************************************************************************/ // just loads texture; no image info stored void InitialiseTexture (long address) { RECT rect; GsIMAGE timInfo; GsGetTimInfo((u_long *)(address+4), &timInfo); rect.x = timInfo.px; rect.y = timInfo.py; rect.w = timInfo.pw; rect.h = timInfo.ph; LoadImage(&rect, timInfo.pixel); if ( (timInfo.pmode>>3) & 0x01 ) { rect.x = timInfo.cx; rect.y = timInfo.cy; rect.w = timInfo.cw; rect.h = timInfo.ch; LoadImage(&rect, timInfo.clut); } DrawSync(0); } // the second argument is a global declared next to the #define for // the TIM file main memory address; // it allows endless sprites to be easily linked to it later on void ProperInitialiseTexture (long address, GsIMAGE* imageInfo) { RECT rect; // +4 because we need to skip head of TIM file GsGetTimInfo( (u_long *)(address+4), imageInfo); rect.x = imageInfo->px; rect.y = imageInfo->py; rect.w = imageInfo->pw; rect.h = imageInfo->ph; LoadImage( &rect, imageInfo->pixel); // if image needs a CLUT, load it up // (pmode: 8 or 9 ==> texture is 4-bit or 8-bit) if ( (imageInfo->pmode>>3)&0x01) { rect.x = imageInfo->cx; rect.y = imageInfo->cy; rect.w = imageInfo->cw; rect.h = imageInfo->ch; LoadImage( &rect, imageInfo->clut); } // wait for loading to finish DrawSync(0); } // this loads TIM to specific (argument) positions in frame buffer // useful if want to load a TIM from main RAM into // multiple places on frame buffer (eg when doing dynamic texturing) // the second argument is a global declared next to the #define for // the TIM file main memory address; // it allows endless sprites to be easily linked to it later on void ForceTextureIntoPosition (long address, GsIMAGE* imageInfo, int px, int py, int cx, int cy) { RECT rect; // +4 because we need to skip head of TIM file GsGetTimInfo( (u_long *)(address+4), imageInfo); rect.x = px; rect.y = py; rect.w = imageInfo->pw; rect.h = imageInfo->ph; assert(rect.x >= 0); assert(rect.x + rect.w <= 1024); assert(rect.y >= 0); assert(rect.y + rect.h <= 512); LoadImage( &rect, imageInfo->pixel); // if image needs a CLUT, load it up // (pmode: 8 or 9 ==> texture is 4-bit or 8-bit) if ( (imageInfo->pmode>>3)&0x01) { rect.x = cx; rect.y = cy; rect.w = imageInfo->cw; rect.h = imageInfo->ch; assert(rect.x >= 0); assert(rect.x + rect.w <= 1023); assert(rect.y >= 0); assert(rect.y + rect.h <= 511); LoadImage( &rect, imageInfo->clut); } // ensure the image is accurate to the VRAM data imageInfo->px = px; imageInfo->py = py; imageInfo->cx = cx; imageInfo->cy = cy; // wait for loading to finish DrawSync(0); } // automatically sorts out sprite attribute to sync with TIM; // sprite ready to use as is after this call void LinkSpriteToImageInfo (GsSPRITE* sprite, GsIMAGE* imageInfo) { int widthCompression; // on frame buffer int tPageType; int texturePageX, texturePageY, xOffset, yOffset; InitGsSprite(sprite); FindTopLeftOfTexturePage(imageInfo, &texturePageX, &texturePageY, &xOffset, &yOffset); switch(imageInfo->pmode) { case 2: // 16-bit sprite->attribute |= SIXTEEN_BIT_MASK; widthCompression = 1; tPageType = 2; break; case 8: // 4-bit widthCompression = 4; tPageType = 0; sprite->cx = imageInfo->cx; sprite->cy = imageInfo->cy; break; case 9: // 8-bit sprite->attribute |= EIGHT_BIT_MASK; widthCompression = 2; tPageType = 1; sprite->cx = imageInfo->cx; sprite->cy = imageInfo->cy; break; default: printf("Only 4, 8 and 16 bit modes supported\n"); printf("check case value for 16-bit: try 2\n"); assert(FALSE); // other modes not supported } sprite->tpage = GetTPage(tPageType, 0, texturePageX, texturePageY); sprite->w = imageInfo->pw * widthCompression; sprite->h = imageInfo->ph; sprite->u = xOffset * widthCompression; sprite->v = yOffset; } // init to void void InitGsSprite (GsSPRITE* sprite) { // initialise sprite to dummy sprite->attribute = 0; sprite->x = 0; sprite->y = 0; sprite->w = 0; sprite->h = 0; sprite->tpage = 0; sprite->u = 0; sprite->v = 0; sprite->cx = 0; sprite->cy = 0; sprite->r = 128; sprite->g = 128; sprite->b = 128; sprite->mx = 0; sprite->my = 0; sprite->scalex = ONE; sprite->scaley = ONE; sprite->rotate = 0; } int Get32TPageNumber (int x, int y) { int tPageNumber; assert(x >= 0); assert(x < 1024); assert(y >= 0); assert(y < 511); tPageNumber = x / 64; if (y >= 512) tPageNumber += 16; return tPageNumber; } // find coords wrt tpage top left points void FindTopLeftOfTexturePage (GsIMAGE* imageInfo, int* x, int* y, int* u, int* v) { int testX, testY; testX = imageInfo->px; testY = imageInfo->py; (*u) = 0; (*v) = 0; for (;;) { if (testX % 64 != 0) { testX--; (*u)++; } else break; } for (;;) { if (testY % 256 != 0) { testY--; (*v)++; } else break; } (*x) = testX; (*y) = testY; } // find coords wrt tpage top left points void GetTexturePage (GsIMAGE* imageInfo, int *tPageID, int* u, int* v) { int basicX, basicY; int widthCompression; basicX = imageInfo->px / 64; basicY = imageInfo->py / 256; *tPageID = basicX; if (basicY == 1) *tPageID += 16; switch(imageInfo->pmode) { case 2: // 16 bit widthCompression = 1; break; case 8: // 4 bit widthCompression = 4; break; case 9: // 8 bit widthCompression = 2; break; default: assert(FALSE); } *u = (imageInfo->px - (basicX * 64)) * widthCompression; *v = (imageInfo->py - (basicY * 256)) * widthCompression; } // spiral section // needs severe improvement: // account for expansion constant // account for orientation void GetPointOnSpiralArm (Spiral *spiral, int whichArm, short *pointX, short *pointY, int distanceRatio) { int cx, cy; int x, y; int theta, r, tempR; int offsetAngle; int numberArms; int angleOffsetPerArm; int baseMultiplier; assert(spiral != NULL); assert(whichArm >= 0); assert(whichArm < spiral->numberArms); assert(distanceRatio >= 0); assert(distanceRatio <= ONE); assert(spiral->expansionConstant > 0); numberArms = spiral->numberArms; angleOffsetPerArm = ONE / numberArms; cx = spiral->cx; cy = spiral->cy; offsetAngle = spiral->initialAngle + (whichArm * angleOffsetPerArm); switch(spiral->orientation) { case CLOCKWISE_OUT: theta = offsetAngle + distanceRatio; break; case ANTICLOCKWISE_OUT: theta = offsetAngle - distanceRatio; break; default: assert(FALSE); } baseMultiplier = (spiral->expansionConstant * distanceRatio) >> 12; //r = (baseMultiplier * spiral->rmax * (theta - offsetAngle)) >> 24; tempR = (baseMultiplier * spiral->rmax) >> 12; r = (tempR * (theta - offsetAngle)) >> 12; x = (r * rcos(theta)) >> 12; y = (r * rsin(theta)) >> 12; *pointX = cx + x; *pointY = cy + y; } void InitSpiralToVoid (Spiral *spiral) { assert(spiral != NULL); spiral->spiralID = -1; spiral->cx = spiral->cy = 0; spiral->numberArms = 0; spiral->orientation = 0; spiral->rmin = spiral->rmax = 0; spiral->expansionConstant = ONE; spiral->initialAngle = 0; InitGsSprite( &spiral->sprite); } void CreateSpiral (Spiral *spiral, int numberArms, int orientation, int expansionConstant, int initialAngle) { assert(spiral != NULL); InitSpiralToVoid(spiral); assert(numberArms >= 1); assert(numberArms <= MAX_SPIRAL_ARMS); spiral->numberArms = numberArms; assert(orientation == CLOCKWISE_OUT || orientation == ANTICLOCKWISE_OUT); spiral->orientation = orientation; assert(expansionConstant > 0); spiral->expansionConstant = expansionConstant; assert(initialAngle >= 0); assert(initialAngle < ONE); spiral->initialAngle = initialAngle; } void PositionSpiral (Spiral *spiral, int x, int y) { assert(spiral != NULL); spiral->cx = x; spiral->cy = y; } void SetSpiralLimits (Spiral *spiral, int rmin, int rmax) { assert(spiral != NULL); assert(rmin >= 0); assert(rmax > 0); assert(rmax > rmin); spiral->rmin = rmin; spiral->rmax = rmax; } void SetSpiralSprite (Spiral *spiral, GsSPRITE *sprite) { assert(sprite != NULL); spiral->sprite = *sprite; } void SetSpiralTwist (Spiral *spiral, int twistAngle) { assert(twistAngle >= 0); assert(twistAngle < 4096); assert(spiral != NULL); spiral->initialAngle = twistAngle; } void VerifySpiral (Spiral *spiral) { assert(spiral != NULL); assert(spiral->cx >= -160 && spiral->cx <= 160); assert(spiral->cy >= -120 && spiral->cy <= 120); assert(spiral->numberArms >= 0 && spiral->numberArms <= MAX_SPIRAL_ARMS); assert(spiral->orientation == CLOCKWISE_OUT || spiral->orientation == ANTICLOCKWISE_OUT); assert(spiral->rmin >= 0); assert(spiral->rmax > 0); assert(spiral->rmax > spiral->rmin); assert(spiral->expansionConstant > 0); assert(spiral->initialAngle >= 0 && spiral->initialAngle < ONE); } void DrawSpiral (Spiral *spiral, GsOT *ot, int grain, int otPlace) { DrawSpiralWithSprite(spiral, ot, &spiral->sprite, grain, otPlace); } void DrawSpiralWithSprite (Spiral *spiral, GsOT *ot, GsSPRITE *sprite, int grain, int otPlace) { int cx, cy; // centre int x, y; int theta, r; int arm; int offsetAngle; int numberArms; int angleOffsetPerArm; assert(grain > 0); assert(grain <= ONE/4); numberArms = spiral->numberArms; angleOffsetPerArm = ONE / numberArms; cx = spiral->cx; cy = spiral->cy; for (arm = 0; arm < numberArms; arm++) { offsetAngle = spiral->initialAngle + (arm * angleOffsetPerArm); theta = offsetAngle; for (;;) { r = (spiral->expansionConstant * (theta - offsetAngle)) >> 12; if (abs(r) < spiral->rmin) { switch(spiral->orientation) { case CLOCKWISE_OUT: theta -= grain; break; case ANTICLOCKWISE_OUT: theta += grain; break; default: assert(FALSE); } continue; } else if (abs(r) > spiral->rmax) // next arm break; x = (r * rcos(theta)) >> 12; y = (r * rsin(theta)) >> 12; if (r < 0) { x = -x; y = -y; } sprite->x = cx + x - (sprite->w/2); sprite->y = cy + y - (sprite->h/2); GsSortFastSprite(sprite, ot, otPlace); switch(spiral->orientation) { case CLOCKWISE_OUT: theta -= grain; break; case ANTICLOCKWISE_OUT: theta += grain; break; default: assert(FALSE); } } } } void DumpSpiral (Spiral *spiral) { printf("\n\nSpiral info :-\n\n"); printf("cx %d\n", spiral->cx); printf("cy %d\n", spiral->cy); printf("numberArms %d\n", spiral->numberArms); printf("orientation %d\n", spiral->orientation); printf("rmin %d\n", spiral->rmin); printf("rmax %d\n", spiral->rmax); printf("expansionConstant %d\n", spiral->expansionConstant); printf("initialAngle %d\n", spiral->initialAngle); dumpSPRITE( &spiral->sprite); printf("\n\n\n"); }