//------------------------------------------------------------------------------------- // // JGE is a hardware accelerated 2D game SDK for PSP/Windows. // // Licensed under the BSD license, see LICENSE in JGE root for details. // // Copyright (c) 2007 James Hui (a.k.a. Dr.Watson) // //------------------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include "../include/vram.h" #include "../include/JLogger.h" #include #ifdef __cplusplus extern "C" { #endif #include #ifdef __cplusplus } #endif #include "../include/JGE.h" #include "../include/JRenderer.h" #include "../include/JFileSystem.h" static unsigned int __attribute__((aligned(16))) list[262144]; extern void SwizzlePlot(u8* out, PIXEL_TYPE color, int i, int j, unsigned int width); void Swap(float *a, float *b) { float n=*a; *a = *b; *b = n; } JQuad::JQuad(JTexture *tex, float x, float y, float width, float height) :mTex(tex), mX(x), mY(y), mWidth(width), mHeight(height) { mHotSpotX = 0.0f; mHotSpotY = 0.0f; mBlend = DEFAULT_BLEND; //GU_TFX_MODULATE; for (int i=0;i<4;i++) mColor[i] = ARGB(255,255,255,255); mHFlipped = false; mVFlipped = false; } void JQuad::GetTextureRect(float *x, float *y, float *w, float *h) { *x=mX; *y=mY; *w=mWidth; *h=mHeight; } void JQuad::SetTextureRect(float x, float y, float w, float h) { mX = x; mY = y; mWidth = w; mHeight = h; } void JQuad::SetColor(PIXEL_TYPE color) { for (int i=0;i<4;i++) mColor[i] = color; } void JQuad::SetHotSpot(float x, float y) { mHotSpotX = x; mHotSpotY = y; } ////////////////////////////////////////////////////////////////////////// JTexture::JTexture() { mBits = NULL; mInVideoRAM = false; mTextureFormat = TEXTURE_FORMAT; } JTexture::~JTexture() { if (mBits) { if (mInVideoRAM) vfree(mBits); else free(mBits); } } void JTexture::UpdateBits(int x, int y, int width, int height, PIXEL_TYPE* bits) { for (int i=0;iInitRenderer(); } return mInstance; } void JRenderer::Destroy() { if (mInstance) { mInstance->DestroyRenderer(); delete mInstance; mInstance = NULL; } } JRenderer::JRenderer() { } JRenderer::~JRenderer() { } void JRenderer::InitRenderer() { mCurrentRenderMode = MODE_2D; #ifdef USING_MATH_TABLE for (int i=0;i<360;i++) { mSinTable[i] = sinf(i*DEG2RAD); mCosTable[i] = cosf(i*DEG2RAD); } #endif mCurrTexBlendSrc = BLEND_SRC_ALPHA; mCurrTexBlendDest = BLEND_ONE_MINUS_SRC_ALPHA; mSwizzle = 1; mVsync = false; mTexCounter = 0; mCurrentTex = -1; mCurrentBlend = -1; mCurrentTextureFormat = TEXTURE_FORMAT; mFOV = 75.0f; mImageFilter = NULL; mCurrentTextureFilter = TEX_FILTER_LINEAR; sceGuInit(); fbp0 = ( u32* ) valloc ( FRAME_BUFFER_SIZE ) ; fbp1 = ( u32* ) valloc ( FRAME_BUFFER_SIZE ); zbp = NULL; // setup GU sceGuStart(GU_DIRECT,list); sceGuDrawBuffer(BUFFER_FORMAT, vrelptr (fbp0), FRAME_BUFFER_WIDTH); sceGuDispBuffer(SCREEN_WIDTH, SCREEN_HEIGHT, vrelptr (fbp1), FRAME_BUFFER_WIDTH); if (m3DEnabled) { zbp = ( u16* ) valloc ( FRAME_BUFFER_WIDTH*SCREEN_HEIGHT*2); sceGuDepthBuffer(vrelptr (zbp), FRAME_BUFFER_WIDTH); } sceGuOffset(2048 - (SCREEN_WIDTH/2), 2048 - (SCREEN_HEIGHT/2)); sceGuViewport(2048, 2048, SCREEN_WIDTH, SCREEN_HEIGHT); sceGuScissor(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); sceGuEnable(GU_SCISSOR_TEST); //sceGuFrontFace(GU_CW); sceGuFrontFace(GU_CCW); sceGuEnable(GU_TEXTURE_2D); sceGuShadeModel(GU_SMOOTH); sceGuTexWrap(GU_REPEAT, GU_REPEAT); // enable alpha channel sceGuEnable(GU_BLEND); sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); sceGuTexFilter(GU_LINEAR,GU_LINEAR); if (m3DEnabled) { sceGuDepthRange(65535,0); sceGuEnable(GU_DEPTH_TEST); sceGuDepthFunc(GU_GEQUAL); sceGuEnable(GU_CULL_FACE); sceGuEnable(GU_CLIP_PLANES); sceGuClearColor(0x00ff0000); sceGuClearDepth(0); sceGuTexEnvColor(0xffffffff); sceGuTexScale(1.0f,1.0f); sceGuTexOffset(0.0f,0.0f); sceGuAmbientColor(0xffffffff); sceGumMatrixMode(GU_PROJECTION); sceGumLoadIdentity(); sceGumPerspective(mFOV,16.0f/9.0f,0.5f,1000.0f); //sceGumPerspective(90.0f,480.0f/272.0f,0.5f,1000.0f); } //sceGuClear(GU_COLOR_BUFFER_BIT); sceGuFinish(); sceGuSync(0,0); sceDisplayWaitVblankStart(); sceGuDisplay(1); } void JRenderer::SetTexBlend(int src, int dest) { if (src != mCurrTexBlendSrc || dest != mCurrTexBlendDest) { mCurrTexBlendSrc = src; mCurrTexBlendDest = dest; int fixSrc = 0; int fixDest = 0; if (src == BLEND_ZERO) src = GU_FIX; else if (src == BLEND_ONE) { src = GU_FIX; fixSrc = 0x00FFFFFF; } if (dest == BLEND_ZERO) dest = GU_FIX; else if (dest == BLEND_ONE) { dest = GU_FIX; fixDest = 0x00FFFFFF; } //glBlendFunc(src, dest); sceGuBlendFunc(GU_ADD, src, dest, fixSrc, fixDest); } } void JRenderer::EnableTextureFilter(bool flag) { if (flag) mCurrentTextureFilter = TEX_FILTER_LINEAR; else mCurrentTextureFilter = TEX_FILTER_NEAREST; } void JRenderer::DestroyRenderer() { sceGuDisplay(GU_FALSE); sceGuTerm(); vfree(fbp0); vfree(fbp1); //debugged = 0; if (zbp) vfree(zbp); } void JRenderer::BeginScene() { sceGuStart(GU_DIRECT, list); if (m3DEnabled) { //if (mMode3D) sceGuClear(GU_DEPTH_BUFFER_BIT|GU_COLOR_BUFFER_BIT); } else { sceGuClear(GU_COLOR_BUFFER_BIT); } sceGuTexMode(TEXTURE_FORMAT, 0, 0, mSwizzle); mCurrentTextureFormat = TEXTURE_FORMAT; if (mCurrentTextureFilter == TEX_FILTER_NEAREST) sceGuTexFilter(GU_NEAREST, GU_NEAREST); // GU_NEAREST good for tile-map else sceGuTexFilter(GU_LINEAR, GU_LINEAR); // GU_LINEAR good for scaling //Keep this until we get rev 2489 (or better) of the SDK //See http://code.google.com/p/wagic/issues/detail?id=92 sceGuSendCommandi(210,BUFFER_FORMAT); } void JRenderer::EndScene() { sceGuFinish(); sceGuSync(0,0); if (mVsync) sceDisplayWaitVblankStart(); sceGuSwapBuffers(); mCurrentTex = -1; mCurrentBlend = -1; } void JRenderer::EnableVSync(bool flag) { mVsync = flag; } void JRenderer::ClearScreen(PIXEL_TYPE color) { static PIXEL_TYPE previousColor = 0xFFFFFFFF; if (previousColor != color) { sceGuClearColor(color); sceGuClear(GU_COLOR_BUFFER_BIT); previousColor = color; } } void JRenderer::FillRect(float x, float y, float width, float height, PIXEL_TYPE color) { struct VertexColor* vertices = (struct VertexColor*)sceGuGetMemory(2 * sizeof(struct VertexColor)); vertices[0].color = color; vertices[0].x = x; vertices[0].y = y; vertices[0].z = 0.0f; vertices[1].color = color; vertices[1].x = x + width; vertices[1].y = y + height; vertices[1].z = 0.0f; sceGuDisable(GU_TEXTURE_2D); sceGuShadeModel(GU_SMOOTH); sceGuAmbientColor(0xffffffff); sceGuDrawArray(GU_SPRITES, TEXTURE_COLOR_FORMAT|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices); sceGuEnable(GU_TEXTURE_2D); } void JRenderer::FillRect(float x, float y, float width, float height, PIXEL_TYPE* colors) { struct VertexColor* vertices = (struct VertexColor*)sceGuGetMemory(4 * sizeof(struct VertexColor)); vertices[0].color = colors[0]; vertices[0].x = x; vertices[0].y = y; vertices[0].z = 0.0f; vertices[1].color = colors[1]; vertices[1].x = x + width; vertices[1].y = y; vertices[1].z = 0.0f; vertices[2].color = colors[2]; vertices[2].x = x; vertices[2].y = y + height; vertices[2].z = 0.0f; vertices[3].color = colors[3]; vertices[3].x = x + width; vertices[3].y = y + height; vertices[3].z = 0.0f; sceGuDisable(GU_TEXTURE_2D); sceGuShadeModel(GU_SMOOTH); sceGuAmbientColor(0xffffffff); sceGuDrawArray(GU_TRIANGLE_STRIP, TEXTURE_COLOR_FORMAT|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 4, 0, vertices); sceGuEnable(GU_TEXTURE_2D); } void JRenderer::DrawRect(float x, float y, float width, float height, PIXEL_TYPE color) { struct VertexColor* vertices = (struct VertexColor*)sceGuGetMemory(5 * sizeof(struct VertexColor)); vertices[0].color = color; vertices[0].x = x; vertices[0].y = y; vertices[0].z = 0.0f; vertices[1].color = color; vertices[1].x = x; vertices[1].y = y + height; vertices[1].z = 0.0f; vertices[2].color = color; vertices[2].x = x + width; vertices[2].y = y + height; vertices[2].z = 0.0f; vertices[3].color = color; vertices[3].x = x + width; vertices[3].y = y; vertices[3].z = 0.0f; vertices[4].color = color; vertices[4].x = x; vertices[4].y = y; vertices[4].z = 0.0f; sceGuDisable(GU_TEXTURE_2D); sceGuShadeModel(GU_SMOOTH); sceGuAmbientColor(0xffffffff); sceGuDrawArray(GU_LINE_STRIP, TEXTURE_COLOR_FORMAT|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 5, 0, vertices); sceGuEnable(GU_TEXTURE_2D); } void JRenderer::DrawLine(float x1, float y1, float x2, float y2, PIXEL_TYPE color) { struct VertexColor* vertices = (struct VertexColor*)sceGuGetMemory(2 * sizeof(struct VertexColor)); vertices[0].color = color; vertices[0].x = x1; vertices[0].y = y1; vertices[0].z = 0.0f; vertices[1].color = color; vertices[1].x = x2; vertices[1].y = y2; vertices[1].z = 0.0f; sceGuDisable(GU_TEXTURE_2D); sceGuShadeModel(GU_SMOOTH); sceGuAmbientColor(0xffffffff); sceGuDrawArray(GU_LINES, TEXTURE_COLOR_FORMAT|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices); sceGuEnable(GU_TEXTURE_2D); } void JRenderer::Plot(float x, float y, PIXEL_TYPE color) { struct VertexColor* vertices = (struct VertexColor*)sceGuGetMemory(1 * sizeof(struct VertexColor)); vertices[0].color = color; vertices[0].x = x; vertices[0].y = y; vertices[0].z = 0.0f; sceGuDisable(GU_TEXTURE_2D); sceGuShadeModel(GU_SMOOTH); sceGuAmbientColor(0xffffffff); sceGuDrawArray(GU_POINTS, TEXTURE_COLOR_FORMAT|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 1, 0, vertices); sceGuEnable(GU_TEXTURE_2D); } void JRenderer::PlotArray(float *x, float *y, int count, PIXEL_TYPE color) { struct VertexColor* vertices = (struct VertexColor*)sceGuGetMemory(count * sizeof(struct VertexColor)); for (int i=0;imTex == NULL) { JLOG("JRenderer::RenderQuad:: invalid texture!"); return; } if (mCurrentTextureFormat != quad->mTex->mTextureFormat) { mCurrentTextureFormat = quad->mTex->mTextureFormat; sceGuTexMode(mCurrentTextureFormat, 0, 0, mSwizzle); } if (mCurrentTex != quad->mTex->mTexId) { sceGuTexImage(0, quad->mTex->mTexWidth, quad->mTex->mTexHeight, quad->mTex->mTexWidth, quad->mTex->mBits); mCurrentTex = quad->mTex->mTexId; } if (mCurrentBlend != quad->mBlend) { sceGuTexFunc(quad->mBlend, GU_TCC_RGBA); mCurrentBlend = quad->mBlend; } //float destWidth = quad->mWidth*quad->mScaleX; float destHeight = quad->mHeight*yScale; float x = xo - quad->mHotSpotX*xScale; float y = yo - quad->mHotSpotY*yScale; float start, end; float width; float destWidth; float fixedWidth = SLICE_SIZE_F*xScale; float xx, yy; float cosAngle = cosf(angle); float sinAngle = sinf(angle); if (quad->mHFlipped)// || quad->mVFlipped) { for (end = quad->mX, start = quad->mX+quad->mWidth; start > end; start -= SLICE_SIZE_F) { // allocate memory on the current display list for temporary storage // in order to rotate, we use 4 vertices this time struct Vertex* vertices = (struct Vertex*)sceGuGetMemory(4 * sizeof(struct Vertex)); if ((start - SLICE_SIZE_F) > end) { width = SLICE_SIZE_F; destWidth = fixedWidth; } else { width = start-end; destWidth = width*xScale; } vertices[0].u = start; vertices[0].v = quad->mY; vertices[0].color = quad->mColor[0];//.color; vertices[0].x = x; vertices[0].y = y; vertices[0].z = 0.0f; vertices[2].u = start - width; vertices[2].v = quad->mY; vertices[2].color = quad->mColor[2];//.color; vertices[2].x = x + destWidth; vertices[2].y = y; vertices[2].z = 0.0f; vertices[1].u = start; vertices[1].v = quad->mY + quad->mHeight; vertices[1].color = quad->mColor[1];//.color; vertices[1].x = x; vertices[1].y = y + destHeight; vertices[1].z = 0.0f; vertices[3].u = start - width; vertices[3].v = quad->mY + quad->mHeight; vertices[3].color = quad->mColor[3];//.color; vertices[3].x = x + destWidth; vertices[3].y = y + destHeight; vertices[3].z = 0.0f; if (quad->mVFlipped) { Swap(&vertices[0].v, &vertices[2].v); Swap(&vertices[1].v, &vertices[3].v); } if (angle != 0.0f) { for (int i=0;i<4;i++) { xx = (cosAngle*(vertices[i].x-xo) - sinAngle*(vertices[i].y-yo) + xo); yy = (sinAngle*(vertices[i].x-xo) + cosAngle*(vertices[i].y-yo) + yo); vertices[i].x = xx; vertices[i].y = yy; } } x += destWidth; sceGuDrawArray(GU_TRIANGLE_STRIP,GU_TEXTURE_32BITF|TEXTURE_COLOR_FORMAT|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 4, 0, vertices); } } else { for (start = quad->mX, end = quad->mX+quad->mWidth; start < end; start += SLICE_SIZE_F) { // allocate memory on the current display list for temporary storage // in order to rotate, we use 4 vertices this time struct Vertex* vertices = (struct Vertex*)sceGuGetMemory(4 * sizeof(struct Vertex)); if ((start + SLICE_SIZE_F) < end) { width = SLICE_SIZE_F; destWidth = fixedWidth; } else { width = end-start; destWidth = width*xScale; } vertices[0].u = start; vertices[0].v = quad->mY; vertices[0].color = quad->mColor[0];//.color; vertices[0].x = x; vertices[0].y = y; vertices[0].z = 0.0f; vertices[2].u = start + width; vertices[2].v = quad->mY; vertices[2].color = quad->mColor[2];//.color; vertices[2].x = x + destWidth; vertices[2].y = y; vertices[2].z = 0.0f; vertices[1].u = start; vertices[1].v = quad->mY + quad->mHeight; vertices[1].color = quad->mColor[1];//.color; vertices[1].x = x; vertices[1].y = y + destHeight; vertices[1].z = 0.0f; vertices[3].u = start + width; vertices[3].v = quad->mY + quad->mHeight; vertices[3].color = quad->mColor[3];//.color; vertices[3].x = x + destWidth; vertices[3].y = y + destHeight; vertices[3].z = 0.0f; if (quad->mVFlipped) { Swap(&vertices[0].v, &vertices[2].v); Swap(&vertices[1].v, &vertices[3].v); } if (angle != 0.0f) { for (int i=0;i<4;i++) { xx = (cosAngle*(vertices[i].x-xo) - sinAngle*(vertices[i].y-yo) + xo); yy = (sinAngle*(vertices[i].x-xo) + cosAngle*(vertices[i].y-yo) + yo); vertices[i].x = xx; vertices[i].y = yy; } } x += destWidth; sceGuDrawArray(GU_TRIANGLE_STRIP,GU_TEXTURE_32BITF|TEXTURE_COLOR_FORMAT|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 4, 0, vertices); } } } void JRenderer::RenderQuad(JQuad* quad, VertexColor* points) { if (mCurrentTextureFormat != quad->mTex->mTextureFormat){ mCurrentTextureFormat = quad->mTex->mTextureFormat; sceGuTexMode(mCurrentTextureFormat, 0, 0, mSwizzle); } if (mCurrentTex != quad->mTex->mTexId) { sceGuTexImage(0, quad->mTex->mTexWidth, quad->mTex->mTexHeight, quad->mTex->mTexWidth, quad->mTex->mBits); mCurrentTex = quad->mTex->mTexId; } if (mCurrentBlend != quad->mBlend) { sceGuTexFunc(quad->mBlend, GU_TCC_RGBA); mCurrentBlend = quad->mBlend; } // allocate memory on the current display list for temporary storage // in order to rotate, we use 4 vertices this time struct Vertex* vertices = (struct Vertex*)sceGuGetMemory(4 * sizeof(struct Vertex)); vertices[0].u = quad->mX; vertices[0].v = quad->mY; vertices[1].u = quad->mX; vertices[1].v = quad->mY + quad->mHeight; vertices[2].u = quad->mX + quad->mWidth; vertices[2].v = quad->mY; vertices[3].u = quad->mX + quad->mWidth; vertices[3].v = quad->mY + quad->mHeight; vertices[0].color = points[3].color; vertices[0].x = points[3].x; vertices[0].y = points[3].y; vertices[0].z = points[3].z; vertices[1].color = points[0].color; vertices[1].x = points[0].x; vertices[1].y = points[0].y; vertices[1].z = points[0].z; vertices[2].color = points[2].color; vertices[2].x = points[2].x; vertices[2].y = points[2].y; vertices[2].z = points[2].z; vertices[3].color = points[1].color; vertices[3].x = points[1].x; vertices[3].y = points[1].y; vertices[3].z = points[1].z; sceGuDrawArray(GU_TRIANGLE_STRIP,GU_TEXTURE_32BITF|TEXTURE_COLOR_FORMAT|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 4, 0, vertices); } /* ** No-op on PSP. This is purely a PC openGL utility. */ void JRenderer::TransferTextureToGLContext(JTexture& inTexture) { } //------------------------------------------------------------------------------------------------ // Taken from: // http://svn.ps2dev.org/filedetails.php?repname=psp&path=/trunk/libpng/screenshot/main.c&rev=0&sc=0 // Save current visible screen as PNG //------------------------------------------------------------------------------------------------ void JRenderer::ScreenShot(const char* filename) { u32* vram32; u16* vram16; void* temp; int bufferwidth; int pixelformat; int i, x, y; png_structp png_ptr; png_infop info_ptr; FILE* fp; u8* line; fp = fopen(filename, "wb"); if (!fp) return; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fclose(fp); return; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); fclose(fp); return; } png_init_io(png_ptr, fp); png_set_IHDR(png_ptr, info_ptr, SCREEN_WIDTH, SCREEN_HEIGHT, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png_ptr, info_ptr); line = (u8*) malloc(SCREEN_WIDTH * 3); sceDisplayWaitVblankStart(); // if framebuf was set with PSP_DISPLAY_SETBUF_NEXTFRAME, wait until it is changed sceDisplayGetFrameBuf(&temp, &bufferwidth, &pixelformat, PSP_DISPLAY_SETBUF_NEXTFRAME); //temp = (void*)(0x04000000+0x40000000); vram32 = (u32*) temp; vram16 = (u16*) vram32; for (y = 0; y < SCREEN_HEIGHT; y++) { for (i = 0, x = 0; x < SCREEN_WIDTH; x++) { u32 color = 0; u8 r = 0, g = 0, b = 0; switch (pixelformat) { case PSP_DISPLAY_PIXEL_FORMAT_565: color = vram16[x + y * bufferwidth]; r = (color & 0x1f) << 3; g = ((color >> 5) & 0x3f) << 2 ; b = ((color >> 11) & 0x1f) << 3 ; break; case PSP_DISPLAY_PIXEL_FORMAT_5551: color = vram16[x + y * bufferwidth]; r = (color & 0x1f) << 3; g = ((color >> 5) & 0x1f) << 3 ; b = ((color >> 10) & 0x1f) << 3 ; break; case PSP_DISPLAY_PIXEL_FORMAT_4444: color = vram16[x + y * bufferwidth]; r = (color & 0xf) << 4; g = ((color >> 4) & 0xf) << 4 ; b = ((color >> 8) & 0xf) << 4 ; break; case PSP_DISPLAY_PIXEL_FORMAT_8888: color = vram32[x + y * bufferwidth]; r = color & 0xff; g = (color >> 8) & 0xff; b = (color >> 16) & 0xff; break; } line[i++] = r; line[i++] = g; line[i++] = b; } png_write_row(png_ptr, line); } free(line); png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, (png_infopp)NULL); fclose(fp); } static void PNGCustomWarningFn(png_structp png_ptr, png_const_charp warning_msg) { JLOG("PNG error callback fired!"); JLOG(warning_msg); } static void PNGCustomReadDataFn(png_structp png_ptr, png_bytep data, png_size_t length) { png_size_t check; JFileSystem *fileSystem = (JFileSystem*)png_ptr->io_ptr; check = fileSystem->ReadFile(data, length); if (check != length) { png_error(png_ptr, "Read Error!"); } } static int getNextPower2(int width) { int b = width; int n; for (n = 0; b != 0; n++) b >>= 1; b = 1 << n; if (b == 2 * width) b >>= 1; return b; } /* ** Alternate swizzle function that can handle any number of lines (as opposed to swizzle_fast, which is ** hardcoded to do 8 at a time) */ static void swizzle_lines(const u8* inSrc, u8* inDst, unsigned int inWidth, unsigned int inLines) { unsigned int rowblocks = (inWidth * sizeof(u32) / 16); for (unsigned int j = 0; j < inLines; ++j) { for (unsigned int i = 0; i < inWidth * sizeof(u32); ++i) { unsigned int blockx = i / 16; unsigned int blocky = j / 8; unsigned int x = (i - blockx * 16); unsigned int y = (j - blocky * 8); unsigned int block_index = blockx + ((blocky) * rowblocks); unsigned int block_address = block_index * 16 * 8; inDst[block_address + x + y * 16] = inSrc[i + j * inWidth * sizeof(u32)]; } } } typedef u32* u32_ptr; static void swizzle_row(const u8* inSrc, u32_ptr& inDst, unsigned int inBlockWidth, unsigned int inPitch) { for (unsigned int blockx = 0; blockx < inBlockWidth; ++blockx) { const u32* src = (u32*)inSrc; for (unsigned int j = 0; j < 8; ++j) { *(inDst++) = *(src++); *(inDst++) = *(src++); *(inDst++) = *(src++); *(inDst++) = *(src++); src += inPitch; } inSrc += 16; } } static void swizzle_fast(u8* out, const u8* in, unsigned int width, unsigned int height) { unsigned int width_blocks = (width / 16); unsigned int height_blocks = (height / 8); unsigned int src_pitch = (width-16)/4; unsigned int src_row = width * 8; const u8* ysrc = in; u32* dst = (u32*)out; for (unsigned int blocky = 0; blocky < height_blocks; ++blocky) { const u8* xsrc = ysrc; swizzle_row(xsrc, dst, width_blocks, src_pitch); ysrc += src_row; } } static void jpg_null(j_decompress_ptr cinfo) { } static boolean jpg_fill_input_buffer(j_decompress_ptr cinfo) { return 1; } static void jpg_skip_input_data(j_decompress_ptr cinfo, long num_bytes) { cinfo->src->next_input_byte += (size_t) num_bytes; cinfo->src->bytes_in_buffer -= (size_t) num_bytes; } static void jpeg_mem_src(j_decompress_ptr cinfo, u8 *mem, int len) { cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(struct jpeg_source_mgr)); cinfo->src->init_source = jpg_null; cinfo->src->fill_input_buffer = jpg_fill_input_buffer; cinfo->src->skip_input_data = jpg_skip_input_data; cinfo->src->resync_to_restart = jpeg_resync_to_restart; cinfo->src->term_source = jpg_null; cinfo->src->bytes_in_buffer = len; cinfo->src->next_input_byte = mem; } int JRenderer::PixelSize(int textureMode){ switch (textureMode) { case GU_PSM_5650: case GU_PSM_5551: case GU_PSM_4444: return 2; case GU_PSM_8888: return 4; } return PIXEL_SIZE; } void JRenderer::LoadJPG(TextureInfo &textureInfo, const char *filename, int mode, int textureMode) { JLOG("JRenderer::LoadJPG"); textureInfo.mBits = NULL; bool useVideoRAM = (mode == TEX_TYPE_USE_VRAM); struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; u8 *rawdata, *scanline, *p; u16 *rgbadata16, *q16, *bits16; u32 *rgbadata32, *q32, *bits32; int rawsize, i; int pixelSize = PixelSize(textureMode); bits16 = NULL; bits32 = NULL; JFileSystem* fileSystem = JFileSystem::GetInstance(); if (!fileSystem->OpenFile(filename)) { return; } rawsize = fileSystem->GetFileSize(); rawdata = new u8[rawsize]; if (!rawdata) { fileSystem->CloseFile(); return; } fileSystem->ReadFile(rawdata, rawsize); fileSystem->CloseFile(); cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpeg_mem_src(&cinfo, rawdata, rawsize); jpeg_read_header(&cinfo, true); jpeg_start_decompress(&cinfo); if(cinfo.output_components != 3 && cinfo.output_components != 4) { jpeg_destroy_decompress(&cinfo); return; } int tw = getNextPower2(cinfo.output_width); int th = getNextPower2(cinfo.output_height); bool videoRAMUsed = false; int size = tw * th * pixelSize; if (useVideoRAM) { if (pixelSize == 2) { bits16 = (u16*)valloc(size); } else { bits32 = (u32*)valloc(size); } videoRAMUsed = true; } //else if (bits16 == NULL && bits32 == NULL) { videoRAMUsed = false; if (pixelSize == 2) { bits16 = (u16*)memalign(16, size); } else { bits32 = (u32*)memalign(16, size); } } rgbadata16 = bits16; rgbadata32 = bits32; if (mSwizzle) { if (rgbadata16) rgbadata16 = (u16*) memalign(16, size); if (rgbadata32) rgbadata32 = (u32*) memalign(16, size); if(!rgbadata16 && !rgbadata32) { jpeg_destroy_decompress(&cinfo); if (videoRAMUsed) { if (bits16) vfree(bits16); if (bits32) vfree(bits32); } else { if (bits16) free(bits16); if (bits32) free(bits32); } return; } } scanline = (u8 *)malloc(cinfo.output_width * 3); if(!scanline) { jpeg_destroy_decompress(&cinfo); if (videoRAMUsed) { if (bits16) vfree(bits16); if (bits32) vfree(bits32); } else { if (bits16) free(bits16); if (bits32) free(bits32); } if (mSwizzle) { if (rgbadata16) free(rgbadata16); if (rgbadata32) free(rgbadata32); } return; } u16 * currRow16 = rgbadata16; u32 * currRow32 = rgbadata32; u16 color16; u32 color32; while(cinfo.output_scanline < cinfo.output_height) { p = scanline; jpeg_read_scanlines(&cinfo, &scanline, 1); q16 = currRow16; q32 = currRow32; for (i=0; i<(int)cinfo.output_width; ++i) { int a = 255; int r = p[0]; int g = p[1]; int b = p[2]; switch (textureMode) { case GU_PSM_5650: color16 = (r >> 3) | ((g >> 2) << 5) | ((b >> 3) << 11); *(q16) = color16; break; case GU_PSM_5551: color16 = (r >> 3) | ((g >> 3) << 5) | ((b >> 3) << 10) | ((a >> 7) << 15); *(q16) = color16; break; case GU_PSM_4444: color16 = (r >> 4) | ((g >> 4) << 4) | ((b >> 4) << 8) | ((a >> 4) << 12); *(q16) = color16; break; case GU_PSM_8888: color32 = r | (g << 8) | (b << 16) | (a << 24); *(q32) = color32; break; } p+=3; if (q16) q16+=1; if (q32) q32+=1; } if (currRow32) currRow32+= tw; if (currRow16) currRow16+= tw; } free(scanline); try { jpeg_finish_decompress(&cinfo); } catch(...) {} if (mSwizzle) { if (rgbadata16){ swizzle_fast((u8*)bits16, (const u8*)rgbadata16, tw*pixelSize, th/*cinfo.output_height*/); free (rgbadata16); } if (rgbadata32){ swizzle_fast((u8*)bits32, (const u8*)rgbadata32, tw*pixelSize, th/*cinfo.output_height*/); free (rgbadata32); } } if (bits16) textureInfo.mBits = (u8 *)bits16; else textureInfo.mBits = (u8 *)bits32; textureInfo.mWidth = cinfo.output_width; textureInfo.mHeight = cinfo.output_height; textureInfo.mTexWidth = tw; textureInfo.mTexHeight = th; textureInfo.mVRAM =videoRAMUsed; jpeg_destroy_decompress(&cinfo); delete [] rawdata; JLOG("-- OK -- JRenderer::LoadJPG"); } JTexture* JRenderer::LoadTexture(const char* filename, int mode, int textureMode) { JLOG("JRenderer::LoadTexture"); TextureInfo textureInfo; textureInfo.mVRAM = false; textureInfo.mBits = NULL; int ret = 0; if (strstr(filename, ".jpg")!=NULL || strstr(filename, ".JPG")!=NULL) LoadJPG(textureInfo, filename, mode, textureMode); else if(strstr(filename, ".gif")!=NULL || strstr(filename, ".GIF")!=NULL) { textureMode = TEXTURE_FORMAT; //textureMode not supported in Gif yet LoadGIF(textureInfo,filename, mode, textureMode); } else if(strstr(filename, ".png")!=NULL || strstr(filename, ".PNG")!=NULL) { textureMode = TEXTURE_FORMAT; //textureMode not supported in PNG yet ret = LoadPNG(textureInfo, filename, mode, textureMode); if (ret < 0) { char buf[512]; sprintf(buf, "--LoadPNG sent error code: %i for file %s", ret, filename); JLOG(buf); } } if (textureInfo.mBits == NULL) return NULL; bool done = false; JTexture* tex = new JTexture(); if (tex) { if (mImageFilter != NULL) mImageFilter->ProcessImage((PIXEL_TYPE*)textureInfo.mBits, textureInfo.mWidth, textureInfo.mHeight); tex->mTexId = mTexCounter++; tex->mTextureFormat = textureMode; tex->mWidth = textureInfo.mWidth; tex->mHeight = textureInfo.mHeight; tex->mTexWidth = textureInfo.mTexWidth; tex->mTexHeight = textureInfo.mTexHeight; tex->mInVideoRAM = textureInfo.mVRAM; tex->mBits = (PIXEL_TYPE *)textureInfo.mBits; done = true; } if (!done) { SAFE_DELETE(tex); } JLOG("-- OK -- JRenderer::LoadTexture"); return tex; } /* ** Helper function for LoadPNG */ void ReadPngLine( png_structp& png_ptr, u32_ptr& line, png_uint_32 width, int pixelformat, u16* p16, u32* p32 ) { png_read_row(png_ptr, (u8*) line, png_bytep_NULL); for (int x = 0; x < (int)width; ++x) { u32 color32 = line[x]; u16 color16; int a = (color32 >> 24) & 0xff; int r = color32 & 0xff; int g = (color32 >> 8) & 0xff; int b = (color32 >> 16) & 0xff; switch (pixelformat) { case PSP_DISPLAY_PIXEL_FORMAT_565: color16 = (r >> 3) | ((g >> 2) << 5) | ((b >> 3) << 11); *(p16+x) = color16; break; case PSP_DISPLAY_PIXEL_FORMAT_5551: color16 = (r >> 3) | ((g >> 3) << 5) | ((b >> 3) << 10) | ((a >> 7) << 15); *(p16+x) = color16; break; case PSP_DISPLAY_PIXEL_FORMAT_4444: color16 = (r >> 4) | ((g >> 4) << 4) | ((b >> 4) << 8) | ((a >> 4) << 12); *(p16+x) = color16; break; case PSP_DISPLAY_PIXEL_FORMAT_8888: color32 = r | (g << 8) | (b << 16) | (a << 24); *(p32+x) = color32; break; } } } //------------------------------------------------------------------------------------------------ // Based on: // http://svn.ps2dev.org/filedetails.php?repname=psp&path=/trunk/libpng/screenshot/main.c&rev=0&sc=0 // Load PNG as texture //------------------------------------------------------------------------------------------------ int JRenderer::LoadPNG(TextureInfo &textureInfo, const char* filename, int mode, int textureMode) { //JLOG("JRenderer::LoadPNG: "); //JLOG(filename); textureInfo.mBits = NULL; bool useVideoRAM = (mode == TEX_TYPE_USE_VRAM); int pixelformat = PIXEL_FORMAT; u32* p32; u16* p16; png_structp png_ptr; png_infop info_ptr; unsigned int sig_read = 0; png_uint_32 width, height; int bit_depth, color_type, interlace_type; u32* line; JFileSystem* fileSystem = JFileSystem::GetInstance(); if (!fileSystem->OpenFile(filename)) return JGE_ERR_CANT_OPEN_FILE; //JLOG("PNG opened - creating read struct"); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fileSystem->CloseFile(); return JGE_ERR_PNG; } //JLOG("Setting error callback func"); png_set_error_fn(png_ptr, (png_voidp) NULL, (png_error_ptr) NULL, PNGCustomWarningFn); info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fileSystem->CloseFile(); png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); return JGE_ERR_PNG; } png_init_io(png_ptr, NULL); png_set_read_fn(png_ptr, (png_voidp)fileSystem, PNGCustomReadDataFn); png_set_sig_bytes(png_ptr, sig_read); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, int_p_NULL, int_p_NULL); png_set_strip_16(png_ptr); png_set_packing(png_ptr); if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); line = (u32*) malloc(width * 4); if (!line) { fileSystem->CloseFile(); png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); return JGE_ERR_MALLOC_FAILED; } int texWidth = getNextPower2(width); int texHeight = getNextPower2(height); bool done = false; PIXEL_TYPE* bits = NULL; bool videoRAMUsed = false; int size = texWidth * texHeight * sizeof(PIXEL_TYPE); { if (useVideoRAM) { bits = (PIXEL_TYPE*) valloc(size); videoRAMUsed = true; } if (bits == NULL) { videoRAMUsed = false; bits = (PIXEL_TYPE*) memalign(16, size); } PIXEL_TYPE* buffer = bits; const unsigned int kVerticalBlockSize = 8; if (mSwizzle) { //JLOG("allocating swizzle buffer"); buffer = (PIXEL_TYPE*) memalign(16, texWidth * kVerticalBlockSize * sizeof(PIXEL_TYPE)); if (!buffer) { JLOG("failed to allocate destination swizzle buffer!"); std::ostringstream stream; stream << "Alloc failed for: Tex Width: " << texWidth << " Tex Height: " << kVerticalBlockSize << ", total bytes: " << texWidth * kVerticalBlockSize * sizeof(PIXEL_TYPE); JLOG(stream.str().c_str()); fileSystem->CloseFile(); png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); return JGE_ERR_MALLOC_FAILED; } } if (buffer) { unsigned int src_row = texWidth * 8; u32* dst = (u32*)bits; u32* ysrc = (u32*) buffer; unsigned int totalVerticalBlocksToProcess = height / kVerticalBlockSize; p32 = (u32*) buffer; p16 = (u16*) p32; for (unsigned int block = 0; block < totalVerticalBlocksToProcess; ++block) { for (unsigned int y = 0; y < kVerticalBlockSize; ++y) { ReadPngLine(png_ptr, line, width, pixelformat, p16, p32); p32 += texWidth; p16 += texWidth; } if (mSwizzle) { swizzle_fast((u8*) dst, (const u8*) buffer, texWidth * sizeof(PIXEL_TYPE), kVerticalBlockSize); dst += src_row; // if we're swizzling, reset the read pointers to the top of the buffer, as we re-read into an 8 line // block of memory (if we're not swizzling, we're reading directly into the destination, so we // want to continue iterating through) p32 = (u32*) buffer; p16 = (u16*) p32; } } //now the last remaining lines (ie if the height wasn't evenly divisible by 8) { if (mSwizzle) { //clear the conversion buffer so that leftover scan lines are transparent memset(buffer, 255, texWidth * kVerticalBlockSize * sizeof(PIXEL_TYPE)); } unsigned int remainingLines = height % kVerticalBlockSize; for (unsigned int y = 0; y < remainingLines; ++y) { ReadPngLine(png_ptr, line, width, pixelformat, p16, p32); p32 += texWidth; p16 += texWidth; } if (mSwizzle) { // swizzle_fast only can handle eight lines at a time, and will overrun memory in our destination, // which only has remainingLines to fill - use the swizzle_lines function instead swizzle_lines((const u8*) buffer, (u8*) dst, texWidth, remainingLines); } } free(buffer); done = true; } } //JLOG("Freeing line"); free (line); //JLOG("Reading end"); png_read_end(png_ptr, info_ptr); //JLOG("Destroying read struct"); png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); //JLOG("Closing PNG"); fileSystem->CloseFile(); if (done) { textureInfo.mBits = (u8 *)bits; textureInfo.mWidth = width; textureInfo.mHeight = height; textureInfo.mTexWidth = texWidth; textureInfo.mTexHeight = texHeight; textureInfo.mVRAM = videoRAMUsed; JLOG("-- OK -- JRenderer::LoadPNG"); return 1; } else { JLOG("LoadPNG failure - deallocating bits"); textureInfo.mBits = NULL; if (videoRAMUsed) vfree(bits); else free(bits); return JGE_ERR_GENERIC; } } ////////////////////////////////////////////////////////////////////////// /// GIF Support int JRenderer::image_readgif(void * handle, TextureInfo &textureInfo, DWORD * bgcolor, InputFunc readFunc,int mode, int textureMode) { bool useVideoRAM = (mode == TEX_TYPE_USE_VRAM); // pixel ** image_data=NULL; DWORD *p32=NULL; //#define gif_color(c) RGB(palette->Colors[c].Red, palette->Colors[c].Green, palette->Colors[c].Blue) #define gif_color32(c) ARGB(255,palette->Colors[c].Red,palette->Colors[c].Green, palette->Colors[c].Blue) GifRecordType RecordType; GifByteType *Extension; GifRowType LineIn = NULL; GifFileType *GifFileIn = NULL; ColorMapObject *palette; int ExtCode; int i, j; if ((GifFileIn = DGifOpen(handle, readFunc)) == NULL) return 1; *bgcolor = 0; textureInfo.mWidth = 0; textureInfo.mHeight = 0; //*image_data = NULL; bool videoRAMUsed = false; int size = 0; do { if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR) { DGifCloseFile(GifFileIn); return 1; } switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: { if (DGifGetImageDesc(GifFileIn) == GIF_ERROR) { DGifCloseFile(GifFileIn); return 1; } if((palette = (GifFileIn->SColorMap != NULL) ? GifFileIn->SColorMap : GifFileIn->Image.ColorMap) == NULL) { DGifCloseFile(GifFileIn); return 1; } textureInfo.mWidth = GifFileIn->Image.Width; textureInfo.mHeight = GifFileIn->Image.Height; *bgcolor = gif_color32(GifFileIn->SBackGroundColor); if((LineIn = (GifRowType) malloc(GifFileIn->Image.Width * sizeof(GifPixelType))) == NULL) { DGifCloseFile(GifFileIn); return 1; } //--------------------------------------- textureInfo.mTexWidth = getNextPower2(GifFileIn->Image.Width); textureInfo.mTexHeight = getNextPower2(GifFileIn->Image.Height); bool done = false; PIXEL_TYPE* bits = NULL; size = textureInfo.mTexWidth * textureInfo.mTexHeight * sizeof(PIXEL_TYPE); if (useVideoRAM)// && (mCurrentPointer+size)<0x200000) { //bits = (PIXEL_TYPE*) (0x04000000+0x40000000+mCurrentPointer); //mCurrentPointer += size; bits = (PIXEL_TYPE*) valloc(size); videoRAMUsed = true; } //else if (bits == NULL) { videoRAMUsed = false; bits = (PIXEL_TYPE*) memalign(16, size); } PIXEL_TYPE* buffer = bits; if (mSwizzle) buffer = (PIXEL_TYPE*) memalign(16, textureInfo.mTexWidth * textureInfo.mTexHeight * sizeof(PIXEL_TYPE)); if (buffer) { p32 = (DWORD*) buffer; } //if((*image_data = (pixel *)malloc(sizeof(pixel) * GifFileIn->Image.Width * GifFileIn->Image.Height)) == NULL) if(p32 == NULL) { free((void *)LineIn); DGifCloseFile(GifFileIn); return 1; } DWORD * curr = p32; DWORD * imgdata = p32; for (i = 0; i < GifFileIn->Image.Height; i ++) { imgdata = curr; if (DGifGetLine(GifFileIn, LineIn, GifFileIn->Image.Width) == GIF_ERROR) { if (videoRAMUsed) vfree(bits); else free(bits); if (mSwizzle) free((void *)p32); free((void *)LineIn); DGifCloseFile(GifFileIn); return 1; } for(j = 0; j < GifFileIn->Image.Width; j ++) { DWORD color32 = gif_color32(LineIn[j]); *imgdata++ = color32; } curr += textureInfo.mTexWidth; } if (mSwizzle) { swizzle_fast((u8*)bits, (const u8*)buffer, textureInfo.mTexWidth*sizeof(PIXEL_TYPE), textureInfo.mTexHeight/*GifFileIn->Image.Height*/); free (buffer); } done = true; textureInfo.mBits = (u8 *)bits; textureInfo.mVRAM = videoRAMUsed; break; } case EXTENSION_RECORD_TYPE: if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == GIF_ERROR) { if(textureInfo.mBits != NULL) { if (videoRAMUsed) vfree(textureInfo.mBits); else free((void *)textureInfo.mBits); textureInfo.mBits = NULL; } if(LineIn != NULL) free((void *)LineIn); DGifCloseFile(GifFileIn); return 1; } while (Extension != NULL) { if (DGifGetExtensionNext(GifFileIn, &Extension) == GIF_ERROR) { if(textureInfo.mBits != NULL) { if (videoRAMUsed) vfree(textureInfo.mBits); else free((void *)textureInfo.mBits); textureInfo.mBits = NULL; } if(LineIn != NULL) free((void *)LineIn); DGifCloseFile(GifFileIn); return 1; } } break; case TERMINATE_RECORD_TYPE: break; default: break; } } while (RecordType != TERMINATE_RECORD_TYPE); if(LineIn != NULL) free((void *)LineIn); DGifCloseFile(GifFileIn); return 0; } int image_gif_read(GifFileType * ft, GifByteType * buf, int size) { JFileSystem *fileSys = (JFileSystem *)ft->UserData; if (fileSys->ReadFile(buf, size)) return size; else return 0; } void JRenderer::LoadGIF(TextureInfo &textureInfo, const char *filename, int mode, int textureMode) { textureInfo.mBits = NULL; JFileSystem *fileSys = JFileSystem::GetInstance(); if (!fileSys->OpenFile(filename)) return; DWORD bkcol; int result = image_readgif(fileSys, textureInfo, &bkcol, image_gif_read, mode); if(result!=0) textureInfo.mBits=NULL; fileSys->CloseFile(); return ; } JTexture* JRenderer::CreateTexture(int width, int height, int mode) { bool useVideoRAM = (mode == TEX_TYPE_USE_VRAM); JTexture* tex = new JTexture(); if (tex) { tex->mWidth = width; tex->mHeight = height; tex->mTexWidth = getNextPower2(width); tex->mTexHeight = getNextPower2(height); int size = tex->mTexWidth * tex->mTexHeight * sizeof(PIXEL_TYPE); if (useVideoRAM) { tex->mInVideoRAM = true; tex->mBits = (PIXEL_TYPE*) valloc(size); } //else if (tex->mBits == NULL) { tex->mInVideoRAM = false; tex->mBits = (PIXEL_TYPE*) memalign(16, size); } memset(tex->mBits, 0, size); tex->mTexId = mTexCounter++; } return tex; } void JRenderer::BindTexture(JTexture *tex) { if (mCurrentTex != tex->mTexId) { sceGuTexImage(0, tex->mTexWidth, tex->mTexHeight, tex->mTexWidth, tex->mBits); mCurrentTex = tex->mTexId; if (m3DEnabled) { if (mCurrentRenderMode == MODE_3D) { sceKernelDcacheWritebackAll(); sceGuTexFunc(GU_TFX_ADD,GU_TCC_RGB); } } } } ////////////////////////////////////////////////////////////////////////// void JRenderer::Enable2D() { mCurrentRenderMode = MODE_2D; sceGuDisable(GU_DEPTH_TEST); } ////////////////////////////////////////////////////////////////////////// void JRenderer::Enable3D() { mCurrentRenderMode = MODE_3D; mCurrentBlend = -1; sceGuEnable(GU_DEPTH_TEST); LoadIdentity(); } ////////////////////////////////////////////////////////////////////////// void JRenderer::SetClip(int x, int y, int width, int height) { sceGuScissor(x, y, width, height); } void JRenderer::LoadIdentity() { sceGumMatrixMode(GU_VIEW); sceGumLoadIdentity(); sceGumMatrixMode(GU_MODEL); sceGumLoadIdentity(); } void JRenderer::Translate(float x, float y, float z) { ScePspFVector3 pos = { x, y, z }; sceGumTranslate(&pos); } void JRenderer::RotateX(float angle) { sceGumRotateX(angle); } void JRenderer::RotateY(float angle) { sceGumRotateY(angle); } void JRenderer::RotateZ(float angle) { sceGumRotateZ(angle); } void JRenderer::PushMatrix() { sceGumPushMatrix(); } void JRenderer::PopMatrix() { sceGumPopMatrix(); } void JRenderer::RenderTriangles(JTexture* texture, Vertex3D *tris, int start, int count) { if (texture) BindTexture(texture); PSPVertex3D* vertices = (PSPVertex3D*) sceGuGetMemory(count * 3 * sizeof(PSPVertex3D)); int n = 0; int index = start*3; for (int i = 0; i < count; i++) { vertices[n].texture.x = tris[index].u; vertices[n].texture.y = tris[index].v; vertices[n].pos.x = tris[index].x; vertices[n].pos.y = tris[index].y; vertices[n].pos.z = tris[index].z; index++; n++; vertices[n].texture.x = tris[index].u; vertices[n].texture.y = tris[index].v; vertices[n].pos.x = tris[index].x; vertices[n].pos.y = tris[index].y; vertices[n].pos.z = tris[index].z; index++; n++; vertices[n].texture.x = tris[index].u; vertices[n].texture.y = tris[index].v; vertices[n].pos.x = tris[index].x; vertices[n].pos.y = tris[index].y; vertices[n].pos.z = tris[index].z; index++; n++; } sceGuColor(0xff000000); sceGumDrawArray(GU_TRIANGLES,GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_3D,count*3,0,vertices); } void JRenderer::SetFOV(float fov) { mFOV = fov; sceGumMatrixMode(GU_PROJECTION); sceGumLoadIdentity(); sceGumPerspective(mFOV,16.0f/9.0f,0.5f,1000.0f); } void JRenderer::FillPolygon(float* x, float* y, int count, PIXEL_TYPE color) { struct VertexColor* vertices = (struct VertexColor*)sceGuGetMemory(count * sizeof(struct VertexColor)); for(int i=0; i y2-y1) { q=(float)sqrt(radius*radius - (i-(y2-y1))*(i-(y2-y1))); nextq=(float)sqrt(radius*radius - (i+1-(y2-y1))*(i+1-(y2-y1))); } if (nextq == q) nextq = q+1; if (i==-radius || i == y2-y1+radius-1){ DrawLine(x1+(radius-q),y1+i+radius,x2+q+radius,y1+i+radius,color); }else{ DrawLine(x1+(radius-q),y1+i+radius,x1+(radius-nextq),y1+i+radius,color); DrawLine(x2+radius+q,y1+i+radius,x2+radius+nextq,y1+i+radius,color); } } } void JRenderer::FillRoundRect(float x, float y, float w, float h, float radius, PIXEL_TYPE color) { x+=w+radius; y+=radius; struct VertexColor* vertices = (struct VertexColor*)sceGuGetMemory(182 * sizeof(struct VertexColor)); vertices[0].color = color; vertices[0].x = x; vertices[0].y = y; vertices[0].z = 0.0f; int angle = 359; for(int i=0; i<45; i++) { vertices[i+1].color = color; vertices[i+1].x = x+radius*COSF(angle); vertices[i+1].y = y+radius*SINF(angle); vertices[i+1].z = 0.0f; angle -= 2; if (angle < 0) angle = 0; } x-=w; for(int i=45; i<90; i++) { vertices[i+1].color = color; vertices[i+1].x = x+radius*COSF(angle); vertices[i+1].y = y+radius*SINF(angle); vertices[i+1].z = 0.0f; angle -= 2; if (angle < 0) angle = 0; } y+=h; for(int i=90; i<135; i++) { vertices[i+1].color = color; vertices[i+1].x = x+radius*COSF(angle); vertices[i+1].y = y+radius*SINF(angle); vertices[i+1].z = 0.0f; angle -= 2; if (angle < 0) angle = 0; } x+=w; for(int i=135; i<180; i++) { vertices[i+1].color = color; vertices[i+1].x = x+radius*COSF(angle); vertices[i+1].y = y+radius*SINF(angle); vertices[i+1].z = 0.0f; angle -= 2; if (angle < 0) angle = 0; } y-=h; vertices[181].color = color; vertices[181].x = x+radius*COSF(359); vertices[181].y = y+radius*SINF(359); vertices[181].z = 0.0f; sceGuDisable(GU_TEXTURE_2D); sceGuShadeModel(GU_SMOOTH); sceGuAmbientColor(0xffffffff); sceGuDrawArray(GU_TRIANGLE_FAN, TEXTURE_COLOR_FORMAT|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 182, 0, vertices); sceGuEnable(GU_TEXTURE_2D); } void JRenderer::SetImageFilter(JImageFilter* imageFilter) { mImageFilter = imageFilter; }