rlm@1: #ifndef VBA_GBA_GFX_H rlm@1: #define VBA_GBA_GFX_H rlm@1: rlm@1: #if _MSC_VER > 1000 rlm@1: #pragma once rlm@1: #endif // _MSC_VER > 1000 rlm@1: rlm@1: #include "../Port.h" rlm@1: #include "GBA.h" rlm@1: #include "GBAGlobals.h" rlm@1: rlm@1: //#define SPRITE_DEBUG rlm@1: rlm@1: void gfxDrawTextScreen(u16, u16, u16, u32 *); rlm@1: void gfxDrawRotScreen(u16, rlm@1: u16, u16, rlm@1: u16, u16, rlm@1: u16, u16, rlm@1: u16, u16, rlm@1: int&, int&, rlm@1: int, rlm@1: u32 *); rlm@1: void gfxDrawRotScreen16Bit(u16, rlm@1: u16, u16, rlm@1: u16, u16, rlm@1: u16, u16, rlm@1: u16, u16, rlm@1: int&, int&, rlm@1: int, rlm@1: u32 *); rlm@1: void gfxDrawRotScreen256(u16, rlm@1: u16, u16, rlm@1: u16, u16, rlm@1: u16, u16, rlm@1: u16, u16, rlm@1: int&, int&, rlm@1: int, rlm@1: u32 *); rlm@1: void gfxDrawRotScreen16Bit160(u16, rlm@1: u16, u16, rlm@1: u16, u16, rlm@1: u16, u16, rlm@1: u16, u16, rlm@1: int&, int&, rlm@1: int, rlm@1: u32 *); rlm@1: void gfxDrawSprites(u32 *); rlm@1: void gfxIncreaseBrightness(u32 *line, int coeff); rlm@1: void gfxDecreaseBrightness(u32 *line, int coeff); rlm@1: void gfxAlphaBlend(u32 *ta, u32 *tb, int ca, int cb); rlm@1: rlm@1: void mode0RenderLine(); rlm@1: void mode0RenderLineNoWindow(); rlm@1: void mode0RenderLineAll(); rlm@1: rlm@1: void mode1RenderLine(); rlm@1: void mode1RenderLineNoWindow(); rlm@1: void mode1RenderLineAll(); rlm@1: rlm@1: void mode2RenderLine(); rlm@1: void mode2RenderLineNoWindow(); rlm@1: void mode2RenderLineAll(); rlm@1: rlm@1: void mode3RenderLine(); rlm@1: void mode3RenderLineNoWindow(); rlm@1: void mode3RenderLineAll(); rlm@1: rlm@1: void mode4RenderLine(); rlm@1: void mode4RenderLineNoWindow(); rlm@1: void mode4RenderLineAll(); rlm@1: rlm@1: void mode5RenderLine(); rlm@1: void mode5RenderLineNoWindow(); rlm@1: void mode5RenderLineAll(); rlm@1: rlm@1: extern int coeff[32]; rlm@1: rlm@1: #define LINE_BUFFER_OVERFLOW_LEEWAY (512-240) rlm@1: rlm@1: extern u32 line0[240+LINE_BUFFER_OVERFLOW_LEEWAY]; rlm@1: extern u32 line1[240+LINE_BUFFER_OVERFLOW_LEEWAY]; rlm@1: extern u32 line2[240+LINE_BUFFER_OVERFLOW_LEEWAY]; rlm@1: extern u32 line3[240+LINE_BUFFER_OVERFLOW_LEEWAY]; rlm@1: extern u32 lineOBJ[240+LINE_BUFFER_OVERFLOW_LEEWAY]; rlm@1: extern u32 lineOBJWin[240+LINE_BUFFER_OVERFLOW_LEEWAY]; rlm@1: extern u32 lineMix[240+LINE_BUFFER_OVERFLOW_LEEWAY]; rlm@1: extern bool gfxInWin0[240+LINE_BUFFER_OVERFLOW_LEEWAY]; rlm@1: extern bool gfxInWin1[240+LINE_BUFFER_OVERFLOW_LEEWAY]; rlm@1: rlm@1: extern int gfxBG2Changed; rlm@1: extern int gfxBG3Changed; rlm@1: rlm@1: extern int gfxBG2X; rlm@1: extern int gfxBG2Y; rlm@1: extern int gfxBG2LastX; rlm@1: extern int gfxBG2LastY; rlm@1: extern int gfxBG3X; rlm@1: extern int gfxBG3Y; rlm@1: extern int gfxBG3LastX; rlm@1: extern int gfxBG3LastY; rlm@1: extern int gfxLastVCOUNT; rlm@1: rlm@1: inline void gfxClearArray(u32 *array) rlm@1: { rlm@1: for (int i = 0; i < 240; i++) rlm@1: { rlm@1: *array++ = 0x80000000; rlm@1: } rlm@1: } rlm@1: rlm@1: inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs, rlm@1: u32 *line) rlm@1: { rlm@1: u16 *palette = (u16 *)paletteRAM; rlm@1: u8 * charBase = &vram[((control >> 2) & 0x03) * 0x4000]; rlm@1: u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800]; rlm@1: u32 prio = ((control & 3)<<25) + 0x1000000; rlm@1: int sizeX = 256; rlm@1: int sizeY = 256; rlm@1: switch ((control >> 14) & 3) rlm@1: { rlm@1: case 0: rlm@1: break; rlm@1: case 1: rlm@1: sizeX = 512; rlm@1: break; rlm@1: case 2: rlm@1: sizeY = 512; rlm@1: break; rlm@1: case 3: rlm@1: sizeX = 512; rlm@1: sizeY = 512; rlm@1: break; rlm@1: } rlm@1: rlm@1: int maskX = sizeX-1; rlm@1: int maskY = sizeY-1; rlm@1: rlm@1: bool mosaicOn = (control & 0x40) ? true : false; rlm@1: rlm@1: int xxx = hofs & maskX; rlm@1: int yyy = (vofs + VCOUNT) & maskY; rlm@1: int mosaicX = (MOSAIC & 0x000F)+1; rlm@1: int mosaicY = ((MOSAIC & 0x00F0)>>4)+1; rlm@1: rlm@1: if (mosaicOn) rlm@1: { rlm@1: if ((VCOUNT % mosaicY) != 0) rlm@1: { rlm@1: mosaicY = (VCOUNT / mosaicY) * mosaicY; rlm@1: yyy = (vofs + mosaicY) & maskY; rlm@1: } rlm@1: } rlm@1: rlm@1: if (yyy > 255 && sizeY > 256) rlm@1: { rlm@1: yyy &= 255; rlm@1: screenBase += 0x400; rlm@1: if (sizeX > 256) rlm@1: screenBase += 0x400; rlm@1: } rlm@1: rlm@1: int yshift = ((yyy>>3)<<5); rlm@1: if ((control) & 0x80) rlm@1: { rlm@1: u16 *screenSource = screenBase + 0x400 * (xxx>>8) + ((xxx & 255)>>3) + yshift; rlm@1: for (int x = 0; x < 240; x++) rlm@1: { rlm@1: u16 data = READ16LE(screenSource); rlm@1: rlm@1: int tile = data & 0x3FF; rlm@1: int tileX = (xxx & 7); rlm@1: int tileY = yyy & 7; rlm@1: rlm@1: if (data & 0x0400) rlm@1: tileX = 7 - tileX; rlm@1: if (data & 0x0800) rlm@1: tileY = 7 - tileY; rlm@1: rlm@1: u8 color = charBase[tile * 64 + tileY * 8 + tileX]; rlm@1: rlm@1: line[x] = color ? (READ16LE(&palette[color]) | prio) : 0x80000000; rlm@1: rlm@1: if (data & 0x0400) rlm@1: { rlm@1: if (tileX == 0) rlm@1: screenSource++; rlm@1: } rlm@1: else if (tileX == 7) rlm@1: screenSource++; rlm@1: xxx++; rlm@1: if (xxx == 256) rlm@1: { rlm@1: if (sizeX > 256) rlm@1: screenSource = screenBase + 0x400 + yshift; rlm@1: else rlm@1: { rlm@1: screenSource = screenBase + yshift; rlm@1: xxx = 0; rlm@1: } rlm@1: } rlm@1: else if (xxx >= sizeX) rlm@1: { rlm@1: xxx = 0; rlm@1: screenSource = screenBase + yshift; rlm@1: } rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: u16 *screenSource = screenBase + 0x400*(xxx>>8)+((xxx&255)>>3) + rlm@1: yshift; rlm@1: for (int x = 0; x < 240; x++) rlm@1: { rlm@1: u16 data = READ16LE(screenSource); rlm@1: rlm@1: int tile = data & 0x3FF; rlm@1: int tileX = (xxx & 7); rlm@1: int tileY = yyy & 7; rlm@1: rlm@1: if (data & 0x0400) rlm@1: tileX = 7 - tileX; rlm@1: if (data & 0x0800) rlm@1: tileY = 7 - tileY; rlm@1: rlm@1: u8 color = charBase[(tile<<5) + (tileY<<2) + (tileX>>1)]; rlm@1: rlm@1: if (tileX & 1) rlm@1: { rlm@1: color = (color >> 4); rlm@1: } rlm@1: else rlm@1: { rlm@1: color &= 0x0F; rlm@1: } rlm@1: rlm@1: int pal = (READ16LE(screenSource)>>8) & 0xF0; rlm@1: line[x] = color ? (READ16LE(&palette[pal + color])|prio) : 0x80000000; rlm@1: rlm@1: if (data & 0x0400) rlm@1: { rlm@1: if (tileX == 0) rlm@1: screenSource++; rlm@1: } rlm@1: else if (tileX == 7) rlm@1: screenSource++; rlm@1: xxx++; rlm@1: if (xxx == 256) rlm@1: { rlm@1: if (sizeX > 256) rlm@1: screenSource = screenBase + 0x400 + yshift; rlm@1: else rlm@1: { rlm@1: screenSource = screenBase + yshift; rlm@1: xxx = 0; rlm@1: } rlm@1: } rlm@1: else if (xxx >= sizeX) rlm@1: { rlm@1: xxx = 0; rlm@1: screenSource = screenBase + yshift; rlm@1: } rlm@1: } rlm@1: } rlm@1: if (mosaicOn) rlm@1: { rlm@1: if (mosaicX > 1) rlm@1: { rlm@1: int m = 1; rlm@1: for (int i = 0; i < 239; i++) rlm@1: { rlm@1: line[i+1] = line[i]; rlm@1: m++; rlm@1: if (m == mosaicX) rlm@1: { rlm@1: m = 1; rlm@1: i++; rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: inline void gfxDrawRotScreen(u16 control, rlm@1: u16 x_l, u16 x_h, rlm@1: u16 y_l, u16 y_h, rlm@1: u16 pa, u16 pb, rlm@1: u16 pc, u16 pd, rlm@1: int& currentX, int& currentY, rlm@1: int changed, rlm@1: u32 *line) rlm@1: { rlm@1: u16 *palette = (u16 *)paletteRAM; rlm@1: u8 * charBase = &vram[((control >> 2) & 0x03) * 0x4000]; rlm@1: u8 * screenBase = (u8 *)&vram[((control >> 8) & 0x1f) * 0x800]; rlm@1: int prio = ((control & 3) << 25) + 0x1000000; rlm@1: rlm@1: int sizeX = 128; rlm@1: int sizeY = 128; rlm@1: switch ((control >> 14) & 3) rlm@1: { rlm@1: case 0: rlm@1: break; rlm@1: case 1: rlm@1: sizeX = sizeY = 256; rlm@1: break; rlm@1: case 2: rlm@1: sizeX = sizeY = 512; rlm@1: break; rlm@1: case 3: rlm@1: sizeX = sizeY = 1024; rlm@1: break; rlm@1: } rlm@1: rlm@1: int dx = pa & 0x7FFF; rlm@1: if (pa & 0x8000) rlm@1: dx |= 0xFFFF8000; rlm@1: int dmx = pb & 0x7FFF; rlm@1: if (pb & 0x8000) rlm@1: dmx |= 0xFFFF8000; rlm@1: int dy = pc & 0x7FFF; rlm@1: if (pc & 0x8000) rlm@1: dy |= 0xFFFF8000; rlm@1: int dmy = pd & 0x7FFFF; rlm@1: if (pd & 0x8000) rlm@1: dmy |= 0xFFFF8000; rlm@1: rlm@1: if (VCOUNT == 0) rlm@1: changed = 3; rlm@1: rlm@1: if (changed & 1) rlm@1: { rlm@1: currentX = (x_l) | ((x_h & 0x07FF)<<16); rlm@1: if (x_h & 0x0800) rlm@1: currentX |= 0xF8000000; rlm@1: } rlm@1: else rlm@1: { rlm@1: currentX += dmx; rlm@1: } rlm@1: rlm@1: if (changed & 2) rlm@1: { rlm@1: currentY = (y_l) | ((y_h & 0x07FF)<<16); rlm@1: if (y_h & 0x0800) rlm@1: currentY |= 0xF8000000; rlm@1: } rlm@1: else rlm@1: { rlm@1: currentY += dmy; rlm@1: } rlm@1: rlm@1: int realX = currentX; rlm@1: int realY = currentY; rlm@1: rlm@1: if (control & 0x40) rlm@1: { rlm@1: int mosaicY = ((MOSAIC & 0xF0)>>4) + 1; rlm@1: int y = (VCOUNT % mosaicY); rlm@1: realX -= y*dmx; rlm@1: realY -= y*dmy; rlm@1: } rlm@1: rlm@1: int xxx = (realX >> 8); rlm@1: int yyy = (realY >> 8); rlm@1: rlm@1: if (control & 0x2000) rlm@1: { rlm@1: xxx %= sizeX; rlm@1: yyy %= sizeY; rlm@1: if (xxx < 0) rlm@1: xxx += sizeX; rlm@1: if (yyy < 0) rlm@1: yyy += sizeY; rlm@1: } rlm@1: rlm@1: if (control & 0x80) rlm@1: { rlm@1: for (int x = 0; x < 240; x++) rlm@1: { rlm@1: if (xxx < 0 || rlm@1: yyy < 0 || rlm@1: xxx >= sizeX || rlm@1: yyy >= sizeY) rlm@1: { rlm@1: line[x] = 0x80000000; rlm@1: } rlm@1: else rlm@1: { rlm@1: int tile = screenBase[(xxx>>3) + (yyy>>3)*(sizeX>>3)]; rlm@1: rlm@1: int tileX = (xxx & 7); rlm@1: int tileY = yyy & 7; rlm@1: rlm@1: u8 color = charBase[(tile<<6) + (tileY<<3) + tileX]; rlm@1: rlm@1: line[x] = color ? (READ16LE(&palette[color])|prio) : 0x80000000; rlm@1: } rlm@1: realX += dx; rlm@1: realY += dy; rlm@1: rlm@1: xxx = (realX >> 8); rlm@1: yyy = (realY >> 8); rlm@1: rlm@1: if (control & 0x2000) rlm@1: { rlm@1: xxx %= sizeX; rlm@1: yyy %= sizeY; rlm@1: if (xxx < 0) rlm@1: xxx += sizeX; rlm@1: if (yyy < 0) rlm@1: yyy += sizeY; rlm@1: } rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: for (int x = 0; x < 240; x++) rlm@1: { rlm@1: if (xxx < 0 || rlm@1: yyy < 0 || rlm@1: xxx >= sizeX || rlm@1: yyy >= sizeY) rlm@1: { rlm@1: line[x] = 0x80000000; rlm@1: } rlm@1: else rlm@1: { rlm@1: int tile = screenBase[(xxx>>3) + (yyy>>3)*(sizeX>>3)]; rlm@1: rlm@1: int tileX = (xxx & 7); rlm@1: int tileY = yyy & 7; rlm@1: rlm@1: u8 color = charBase[(tile<<6) + (tileY<<3) + tileX]; rlm@1: rlm@1: line[x] = color ? (READ16LE(&palette[color])|prio) : 0x80000000; rlm@1: } rlm@1: realX += dx; rlm@1: realY += dy; rlm@1: rlm@1: xxx = (realX >> 8); rlm@1: yyy = (realY >> 8); rlm@1: rlm@1: if (control & 0x2000) rlm@1: { rlm@1: xxx %= sizeX; rlm@1: yyy %= sizeY; rlm@1: if (xxx < 0) rlm@1: xxx += sizeX; rlm@1: if (yyy < 0) rlm@1: yyy += sizeY; rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: if (control & 0x40) rlm@1: { rlm@1: int mosaicX = (MOSAIC & 0xF) + 1; rlm@1: if (mosaicX > 1) rlm@1: { rlm@1: int m = 1; rlm@1: for (int i = 0; i < 239; i++) rlm@1: { rlm@1: line[i+1] = line[i]; rlm@1: m++; rlm@1: if (m == mosaicX) rlm@1: { rlm@1: m = 1; rlm@1: i++; rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: inline void gfxDrawRotScreen16Bit(u16 control, rlm@1: u16 x_l, u16 x_h, rlm@1: u16 y_l, u16 y_h, rlm@1: u16 pa, u16 pb, rlm@1: u16 pc, u16 pd, rlm@1: int& currentX, int& currentY, rlm@1: int changed, rlm@1: u32 *line) rlm@1: { rlm@1: u16 *screenBase = (u16 *)&vram[0]; rlm@1: int prio = ((control & 3) << 25) + 0x1000000; rlm@1: int sizeX = 240; rlm@1: int sizeY = 160; rlm@1: rlm@1: int startX = (x_l) | ((x_h & 0x07FF)<<16); rlm@1: if (x_h & 0x0800) rlm@1: startX |= 0xF8000000; rlm@1: int startY = (y_l) | ((y_h & 0x07FF)<<16); rlm@1: if (y_h & 0x0800) rlm@1: startY |= 0xF8000000; rlm@1: rlm@1: int dx = pa & 0x7FFF; rlm@1: if (pa & 0x8000) rlm@1: dx |= 0xFFFF8000; rlm@1: int dmx = pb & 0x7FFF; rlm@1: if (pb & 0x8000) rlm@1: dmx |= 0xFFFF8000; rlm@1: int dy = pc & 0x7FFF; rlm@1: if (pc & 0x8000) rlm@1: dy |= 0xFFFF8000; rlm@1: int dmy = pd & 0x7FFFF; rlm@1: if (pd & 0x8000) rlm@1: dmy |= 0xFFFF8000; rlm@1: rlm@1: if (VCOUNT == 0) rlm@1: changed = 3; rlm@1: rlm@1: if (changed & 1) rlm@1: { rlm@1: currentX = (x_l) | ((x_h & 0x07FF)<<16); rlm@1: if (x_h & 0x0800) rlm@1: currentX |= 0xF8000000; rlm@1: } rlm@1: else rlm@1: currentX += dmx; rlm@1: rlm@1: if (changed & 2) rlm@1: { rlm@1: currentY = (y_l) | ((y_h & 0x07FF)<<16); rlm@1: if (y_h & 0x0800) rlm@1: currentY |= 0xF8000000; rlm@1: } rlm@1: else rlm@1: { rlm@1: currentY += dmy; rlm@1: } rlm@1: rlm@1: int realX = currentX; rlm@1: int realY = currentY; rlm@1: rlm@1: if (control & 0x40) rlm@1: { rlm@1: int mosaicY = ((MOSAIC & 0xF0)>>4) + 1; rlm@1: int y = (VCOUNT % mosaicY); rlm@1: realX -= y*dmx; rlm@1: realY -= y*dmy; rlm@1: } rlm@1: rlm@1: int xxx = (realX >> 8); rlm@1: int yyy = (realY >> 8); rlm@1: rlm@1: for (int x = 0; x < 240; x++) rlm@1: { rlm@1: if (xxx < 0 || rlm@1: yyy < 0 || rlm@1: xxx >= sizeX || rlm@1: yyy >= sizeY) rlm@1: { rlm@1: line[x] = 0x80000000; rlm@1: } rlm@1: else rlm@1: { rlm@1: line[x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio); rlm@1: } rlm@1: realX += dx; rlm@1: realY += dy; rlm@1: rlm@1: xxx = (realX >> 8); rlm@1: yyy = (realY >> 8); rlm@1: } rlm@1: rlm@1: if (control & 0x40) rlm@1: { rlm@1: int mosaicX = (MOSAIC & 0xF) + 1; rlm@1: if (mosaicX > 1) rlm@1: { rlm@1: int m = 1; rlm@1: for (int i = 0; i < 239; i++) rlm@1: { rlm@1: line[i+1] = line[i]; rlm@1: m++; rlm@1: if (m == mosaicX) rlm@1: { rlm@1: m = 1; rlm@1: i++; rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: inline void gfxDrawRotScreen256(u16 control, rlm@1: u16 x_l, u16 x_h, rlm@1: u16 y_l, u16 y_h, rlm@1: u16 pa, u16 pb, rlm@1: u16 pc, u16 pd, rlm@1: int ¤tX, int& currentY, rlm@1: int changed, rlm@1: u32 *line) rlm@1: { rlm@1: u16 *palette = (u16 *)paletteRAM; rlm@1: u8 * screenBase = (DISPCNT & 0x0010) ? &vram[0xA000] : &vram[0x0000]; rlm@1: int prio = ((control & 3) << 25) + 0x1000000; rlm@1: int sizeX = 240; rlm@1: int sizeY = 160; rlm@1: rlm@1: int startX = (x_l) | ((x_h & 0x07FF)<<16); rlm@1: if (x_h & 0x0800) rlm@1: startX |= 0xF8000000; rlm@1: int startY = (y_l) | ((y_h & 0x07FF)<<16); rlm@1: if (y_h & 0x0800) rlm@1: startY |= 0xF8000000; rlm@1: rlm@1: int dx = pa & 0x7FFF; rlm@1: if (pa & 0x8000) rlm@1: dx |= 0xFFFF8000; rlm@1: int dmx = pb & 0x7FFF; rlm@1: if (pb & 0x8000) rlm@1: dmx |= 0xFFFF8000; rlm@1: int dy = pc & 0x7FFF; rlm@1: if (pc & 0x8000) rlm@1: dy |= 0xFFFF8000; rlm@1: int dmy = pd & 0x7FFFF; rlm@1: if (pd & 0x8000) rlm@1: dmy |= 0xFFFF8000; rlm@1: rlm@1: if (VCOUNT == 0) rlm@1: changed = 3; rlm@1: rlm@1: if (changed & 1) rlm@1: { rlm@1: currentX = (x_l) | ((x_h & 0x07FF)<<16); rlm@1: if (x_h & 0x0800) rlm@1: currentX |= 0xF8000000; rlm@1: } rlm@1: else rlm@1: { rlm@1: currentX += dmx; rlm@1: } rlm@1: rlm@1: if (changed & 2) rlm@1: { rlm@1: currentY = (y_l) | ((y_h & 0x07FF)<<16); rlm@1: if (y_h & 0x0800) rlm@1: currentY |= 0xF8000000; rlm@1: } rlm@1: else rlm@1: { rlm@1: currentY += dmy; rlm@1: } rlm@1: rlm@1: int realX = currentX; rlm@1: int realY = currentY; rlm@1: rlm@1: if (control & 0x40) rlm@1: { rlm@1: int mosaicY = ((MOSAIC & 0xF0)>>4) + 1; rlm@1: int y = (VCOUNT / mosaicY) * mosaicY; rlm@1: realX = startX + y*dmx; rlm@1: realY = startY + y*dmy; rlm@1: } rlm@1: rlm@1: int xxx = (realX >> 8); rlm@1: int yyy = (realY >> 8); rlm@1: rlm@1: for (int x = 0; x < 240; x++) rlm@1: { rlm@1: if (xxx < 0 || rlm@1: yyy < 0 || rlm@1: xxx >= sizeX || rlm@1: yyy >= sizeY) rlm@1: { rlm@1: line[x] = 0x80000000; rlm@1: } rlm@1: else rlm@1: { rlm@1: u8 color = screenBase[yyy * 240 + xxx]; rlm@1: rlm@1: line[x] = color ? (READ16LE(&palette[color])|prio) : 0x80000000; rlm@1: } rlm@1: realX += dx; rlm@1: realY += dy; rlm@1: rlm@1: xxx = (realX >> 8); rlm@1: yyy = (realY >> 8); rlm@1: } rlm@1: rlm@1: if (control & 0x40) rlm@1: { rlm@1: int mosaicX = (MOSAIC & 0xF) + 1; rlm@1: if (mosaicX > 1) rlm@1: { rlm@1: int m = 1; rlm@1: for (int i = 0; i < 239; i++) rlm@1: { rlm@1: line[i+1] = line[i]; rlm@1: m++; rlm@1: if (m == mosaicX) rlm@1: { rlm@1: m = 1; rlm@1: i++; rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: inline void gfxDrawRotScreen16Bit160(u16 control, rlm@1: u16 x_l, u16 x_h, rlm@1: u16 y_l, u16 y_h, rlm@1: u16 pa, u16 pb, rlm@1: u16 pc, u16 pd, rlm@1: int& currentX, int& currentY, rlm@1: int changed, rlm@1: u32 *line) rlm@1: { rlm@1: u16 *screenBase = (DISPCNT & 0x0010) ? (u16 *)&vram[0xa000] : rlm@1: (u16 *)&vram[0]; rlm@1: int prio = ((control & 3) << 25) + 0x1000000; rlm@1: int sizeX = 160; rlm@1: int sizeY = 128; rlm@1: rlm@1: int startX = (x_l) | ((x_h & 0x07FF)<<16); rlm@1: if (x_h & 0x0800) rlm@1: startX |= 0xF8000000; rlm@1: int startY = (y_l) | ((y_h & 0x07FF)<<16); rlm@1: if (y_h & 0x0800) rlm@1: startY |= 0xF8000000; rlm@1: rlm@1: int dx = pa & 0x7FFF; rlm@1: if (pa & 0x8000) rlm@1: dx |= 0xFFFF8000; rlm@1: int dmx = pb & 0x7FFF; rlm@1: if (pb & 0x8000) rlm@1: dmx |= 0xFFFF8000; rlm@1: int dy = pc & 0x7FFF; rlm@1: if (pc & 0x8000) rlm@1: dy |= 0xFFFF8000; rlm@1: int dmy = pd & 0x7FFFF; rlm@1: if (pd & 0x8000) rlm@1: dmy |= 0xFFFF8000; rlm@1: rlm@1: if (VCOUNT == 0) rlm@1: changed = 3; rlm@1: rlm@1: if (changed & 1) rlm@1: { rlm@1: currentX = (x_l) | ((x_h & 0x07FF)<<16); rlm@1: if (x_h & 0x0800) rlm@1: currentX |= 0xF8000000; rlm@1: } rlm@1: else rlm@1: { rlm@1: currentX += dmx; rlm@1: } rlm@1: rlm@1: if (changed & 2) rlm@1: { rlm@1: currentY = (y_l) | ((y_h & 0x07FF)<<16); rlm@1: if (y_h & 0x0800) rlm@1: currentY |= 0xF8000000; rlm@1: } rlm@1: else rlm@1: { rlm@1: currentY += dmy; rlm@1: } rlm@1: rlm@1: int realX = currentX; rlm@1: int realY = currentY; rlm@1: rlm@1: if (control & 0x40) rlm@1: { rlm@1: int mosaicY = ((MOSAIC & 0xF0)>>4) + 1; rlm@1: int y = (VCOUNT / mosaicY) * mosaicY; rlm@1: realX = startX + y*dmx; rlm@1: realY = startY + y*dmy; rlm@1: } rlm@1: rlm@1: int xxx = (realX >> 8); rlm@1: int yyy = (realY >> 8); rlm@1: rlm@1: for (int x = 0; x < 240; x++) rlm@1: { rlm@1: if (xxx < 0 || rlm@1: yyy < 0 || rlm@1: xxx >= sizeX || rlm@1: yyy >= sizeY) rlm@1: { rlm@1: line[x] = 0x80000000; rlm@1: } rlm@1: else rlm@1: { rlm@1: line[x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio); rlm@1: } rlm@1: realX += dx; rlm@1: realY += dy; rlm@1: rlm@1: xxx = (realX >> 8); rlm@1: yyy = (realY >> 8); rlm@1: } rlm@1: rlm@1: if (control & 0x40) rlm@1: { rlm@1: int mosaicX = (MOSAIC & 0xF) + 1; rlm@1: if (mosaicX > 1) rlm@1: { rlm@1: int m = 1; rlm@1: for (int i = 0; i < 239; i++) rlm@1: { rlm@1: line[i+1] = line[i]; rlm@1: m++; rlm@1: if (m == mosaicX) rlm@1: { rlm@1: m = 1; rlm@1: i++; rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: inline void gfxDrawSprites(u32 *lineOBJ) rlm@1: { rlm@1: int m = 0; rlm@1: gfxClearArray(lineOBJ); rlm@1: if (layerEnable & 0x1000) rlm@1: { rlm@1: u16 *sprites = (u16 *)oam; rlm@1: u16 *spritePalette = &((u16 *)paletteRAM)[256]; rlm@1: int mosaicY = ((MOSAIC & 0xF000)>>12) + 1; rlm@1: int mosaicX = ((MOSAIC & 0xF00)>>8) + 1; rlm@1: for (int x = 0; x < 128; x++) rlm@1: { rlm@1: u16 a0 = READ16LE(sprites++); rlm@1: u16 a1 = READ16LE(sprites++); rlm@1: u16 a2 = READ16LE(sprites++); rlm@1: sprites++; rlm@1: rlm@1: // ignore OBJ-WIN rlm@1: if ((a0 & 0x0c00) == 0x0800) rlm@1: continue; rlm@1: rlm@1: int sizeY = 8; rlm@1: int sizeX = 8; rlm@1: rlm@1: switch (((a0 >>12) & 0x0c)|(a1>>14)) rlm@1: { rlm@1: case 0: rlm@1: break; rlm@1: case 1: rlm@1: sizeX = sizeY = 16; rlm@1: break; rlm@1: case 2: rlm@1: sizeX = sizeY = 32; rlm@1: break; rlm@1: case 3: rlm@1: sizeX = sizeY = 64; rlm@1: break; rlm@1: case 4: rlm@1: sizeX = 16; rlm@1: break; rlm@1: case 5: rlm@1: sizeX = 32; rlm@1: break; rlm@1: case 6: rlm@1: sizeX = 32; rlm@1: sizeY = 16; rlm@1: break; rlm@1: case 7: rlm@1: sizeX = 64; rlm@1: sizeY = 32; rlm@1: break; rlm@1: case 8: rlm@1: sizeY = 16; rlm@1: break; rlm@1: case 9: rlm@1: sizeY = 32; rlm@1: break; rlm@1: case 10: rlm@1: sizeX = 16; rlm@1: sizeY = 32; rlm@1: break; rlm@1: case 11: rlm@1: sizeX = 32; rlm@1: sizeY = 64; rlm@1: break; rlm@1: default: rlm@1: continue; rlm@1: } rlm@1: rlm@1: #ifdef SPRITE_DEBUG rlm@1: int maskX = sizeX-1; rlm@1: int maskY = sizeY-1; rlm@1: #endif rlm@1: rlm@1: int sy = (a0 & 255); rlm@1: rlm@1: if (sy > 160) rlm@1: sy -= 256; rlm@1: rlm@1: if (a0 & 0x0100) rlm@1: { rlm@1: int fieldX = sizeX; rlm@1: int fieldY = sizeY; rlm@1: if (a0 & 0x0200) rlm@1: { rlm@1: fieldX <<= 1; rlm@1: fieldY <<= 1; rlm@1: } rlm@1: rlm@1: int t = VCOUNT - sy; rlm@1: if ((t >= 0) && (t < fieldY)) rlm@1: { rlm@1: int sx = (a1 & 0x1FF); rlm@1: if ((sx < 240) || (((sx + fieldX) & 511) < 240)) rlm@1: { rlm@1: // int t2 = t - (fieldY >> 1); rlm@1: int rot = (a1 >> 9) & 0x1F; rlm@1: u16 *OAM = (u16 *)oam; rlm@1: int dx = READ16LE(&OAM[3 + (rot << 4)]); rlm@1: if (dx & 0x8000) rlm@1: dx |= 0xFFFF8000; rlm@1: int dmx = READ16LE(&OAM[7 + (rot << 4)]); rlm@1: if (dmx & 0x8000) rlm@1: dmx |= 0xFFFF8000; rlm@1: int dy = READ16LE(&OAM[11 + (rot << 4)]); rlm@1: if (dy & 0x8000) rlm@1: dy |= 0xFFFF8000; rlm@1: int dmy = READ16LE(&OAM[15 + (rot << 4)]); rlm@1: if (dmy & 0x8000) rlm@1: dmy |= 0xFFFF8000; rlm@1: rlm@1: if (a0 & 0x1000) rlm@1: { rlm@1: t -= (t % mosaicY); rlm@1: } rlm@1: rlm@1: int realX = ((sizeX) << 7) - (fieldX >> 1)*dx - (fieldY>>1)*dmx rlm@1: + t * dmx; rlm@1: int realY = ((sizeY) << 7) - (fieldX >> 1)*dy - (fieldY>>1)*dmy rlm@1: + t * dmy; rlm@1: rlm@1: u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); rlm@1: rlm@1: if (a0 & 0x2000) rlm@1: { rlm@1: int c = (a2 & 0x3FF); rlm@1: if ((DISPCNT & 7) > 2 && (c < 512)) rlm@1: continue; rlm@1: int inc = 32; rlm@1: if (DISPCNT & 0x40) rlm@1: inc = sizeX >> 2; rlm@1: else rlm@1: c &= 0x3FE; rlm@1: for (int x = 0; x < fieldX; x++) rlm@1: { rlm@1: int xxx = realX >> 8; rlm@1: int yyy = realY >> 8; rlm@1: rlm@1: if (xxx < 0 || xxx >= sizeX || rlm@1: yyy < 0 || yyy >= sizeY || rlm@1: sx >= 240) rlm@1: ; rlm@1: else rlm@1: { rlm@1: u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5) rlm@1: + ((yyy & 7)<<3) + ((xxx >> 3)<<6) + rlm@1: (xxx & 7))&0x7FFF)]; rlm@1: if ((color == 0) && (((prio >> 25)&3) < rlm@1: ((lineOBJ[sx]>>25)&3))) rlm@1: { rlm@1: lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio; rlm@1: if ((a0 & 0x1000) && m) rlm@1: lineOBJ[sx] = (lineOBJ[sx-1] & 0xF9FFFFFF) | prio; rlm@1: } rlm@1: else if ((color) && (prio < (lineOBJ[sx]&0xFF000000))) rlm@1: { rlm@1: lineOBJ[sx] = READ16LE(&spritePalette[color]) | prio; rlm@1: if ((a0 & 0x1000) && m) rlm@1: lineOBJ[sx] = (lineOBJ[sx-1] & 0xF9FFFFFF) | prio; rlm@1: } rlm@1: rlm@1: if (a0 & 0x1000) rlm@1: { rlm@1: m++; rlm@1: if (m == mosaicX) rlm@1: m = 0; rlm@1: } rlm@1: #ifdef SPRITE_DEBUG rlm@1: if (t == 0 || t == maskY || x == 0 || x == maskX) rlm@1: lineOBJ[sx] = 0x001F; rlm@1: #endif rlm@1: } rlm@1: sx = (sx+1)&511;; rlm@1: realX += dx; rlm@1: realY += dy; rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: int c = (a2 & 0x3FF); rlm@1: if ((DISPCNT & 7) > 2 && (c < 512)) rlm@1: continue; rlm@1: rlm@1: int inc = 32; rlm@1: if (DISPCNT & 0x40) rlm@1: inc = sizeX >> 3; rlm@1: int palette = (a2 >> 8) & 0xF0; rlm@1: for (int x = 0; x < fieldX; x++) rlm@1: { rlm@1: int xxx = realX >> 8; rlm@1: int yyy = realY >> 8; rlm@1: if (xxx < 0 || xxx >= sizeX || rlm@1: yyy < 0 || yyy >= sizeY || rlm@1: sx >= 240) rlm@1: ; rlm@1: else rlm@1: { rlm@1: u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5) rlm@1: + ((yyy & 7)<<2) + ((xxx >> 3)<<5) + rlm@1: ((xxx & 7)>>1))&0x7FFF)]; rlm@1: if (xxx & 1) rlm@1: color >>= 4; rlm@1: else rlm@1: color &= 0x0F; rlm@1: rlm@1: if ((color == 0) && (((prio >> 25)&3) < rlm@1: ((lineOBJ[sx]>>25)&3))) rlm@1: { rlm@1: lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio; rlm@1: if ((a0 & 0x1000) && m) rlm@1: lineOBJ[sx] = (lineOBJ[sx-1] & 0xF9FFFFFF) | prio; rlm@1: } rlm@1: else if ((color) && (prio < (lineOBJ[sx]&0xFF000000))) rlm@1: { rlm@1: lineOBJ[sx] = READ16LE(&spritePalette[palette+color]) | prio; rlm@1: if ((a0 & 0x1000) && m) rlm@1: lineOBJ[sx] = (lineOBJ[sx-1] & 0xF9FFFFFF) | prio; rlm@1: } rlm@1: } rlm@1: if ((a0 & 0x1000) && m) rlm@1: { rlm@1: m++; rlm@1: if (m == mosaicX) rlm@1: m = 0; rlm@1: } rlm@1: rlm@1: #ifdef SPRITE_DEBUG rlm@1: if (t == 0 || t == maskY || x == 0 || x == maskX) rlm@1: lineOBJ[sx] = 0x001F; rlm@1: #endif rlm@1: sx = (sx+1)&511;; rlm@1: realX += dx; rlm@1: realY += dy; rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: int t = VCOUNT - sy; rlm@1: if ((t >= 0) && (t < sizeY)) rlm@1: { rlm@1: int sx = (a1 & 0x1FF); rlm@1: if (((sx < 240) || (((sx+sizeX)&511) < 240)) && !(a0 & 0x0200)) rlm@1: { rlm@1: if (a0 & 0x2000) rlm@1: { rlm@1: if (a1 & 0x2000) rlm@1: t = sizeY - t - 1; rlm@1: int c = (a2 & 0x3FF); rlm@1: if ((DISPCNT & 7) > 2 && (c < 512)) rlm@1: continue; rlm@1: rlm@1: int inc = 32; rlm@1: if (DISPCNT & 0x40) rlm@1: { rlm@1: inc = sizeX >> 2; rlm@1: } rlm@1: else rlm@1: { rlm@1: c &= 0x3FE; rlm@1: } rlm@1: int xxx = 0; rlm@1: if (a1 & 0x1000) rlm@1: xxx = sizeX-1; rlm@1: rlm@1: if (a0 & 0x1000) rlm@1: { rlm@1: t -= (t % mosaicY); rlm@1: } rlm@1: rlm@1: int address = 0x10000 + ((((c+ (t>>3) * inc) << 5) rlm@1: + ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7)) & 0x7FFF); rlm@1: rlm@1: if (a1 & 0x1000) rlm@1: xxx = 7; rlm@1: u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); rlm@1: rlm@1: for (int xx = 0; xx < sizeX; xx++) rlm@1: { rlm@1: if (sx < 240) rlm@1: { rlm@1: u8 color = vram[address]; rlm@1: if ((color == 0) && (((prio >> 25)&3) < rlm@1: ((lineOBJ[sx]>>25)&3))) rlm@1: { rlm@1: lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio; rlm@1: if ((a0 & 0x1000) && m) rlm@1: lineOBJ[sx] = (lineOBJ[sx-1] & 0xF9FFFFFF) | prio; rlm@1: } rlm@1: else if ((color) && (prio < (lineOBJ[sx]&0xFF000000))) rlm@1: { rlm@1: lineOBJ[sx] = READ16LE(&spritePalette[color]) | prio; rlm@1: if ((a0 & 0x1000) && m) rlm@1: lineOBJ[sx] = (lineOBJ[sx-1] & 0xF9FFFFFF) | prio; rlm@1: } rlm@1: rlm@1: if (a0 & 0x1000) rlm@1: { rlm@1: m++; rlm@1: if (m == mosaicX) rlm@1: m = 0; rlm@1: } rlm@1: rlm@1: #ifdef SPRITE_DEBUG rlm@1: if (t == 0 || t == maskY || xx == 0 || xx == maskX) rlm@1: lineOBJ[sx] = 0x001F; rlm@1: #endif rlm@1: } rlm@1: rlm@1: sx = (sx+1) & 511; rlm@1: if (a1 & 0x1000) rlm@1: { rlm@1: xxx--; rlm@1: address--; rlm@1: if (xxx == -1) rlm@1: { rlm@1: address -= 56; rlm@1: xxx = 7; rlm@1: } rlm@1: if (address < 0x10000) rlm@1: address += 0x8000; rlm@1: } rlm@1: else rlm@1: { rlm@1: xxx++; rlm@1: address++; rlm@1: if (xxx == 8) rlm@1: { rlm@1: address += 56; rlm@1: xxx = 0; rlm@1: } rlm@1: if (address > 0x17fff) rlm@1: address -= 0x8000; rlm@1: } rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: if (a1 & 0x2000) rlm@1: t = sizeY - t - 1; rlm@1: int c = (a2 & 0x3FF); rlm@1: if ((DISPCNT & 7) > 2 && (c < 512)) rlm@1: continue; rlm@1: rlm@1: int inc = 32; rlm@1: if (DISPCNT & 0x40) rlm@1: { rlm@1: inc = sizeX >> 3; rlm@1: } rlm@1: int xxx = 0; rlm@1: if (a1 & 0x1000) rlm@1: xxx = sizeX - 1; rlm@1: rlm@1: if (a0 & 0x1000) rlm@1: { rlm@1: t -= (t % mosaicY); rlm@1: } rlm@1: rlm@1: int address = 0x10000 + ((((c + (t>>3) * inc)<<5) rlm@1: + ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7FFF); rlm@1: u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); rlm@1: int palette = (a2 >> 8) & 0xF0; rlm@1: if (a1 & 0x1000) rlm@1: { rlm@1: xxx = 7; rlm@1: for (int xx = sizeX - 1; xx >= 0; xx--) rlm@1: { rlm@1: if (sx < 240) rlm@1: { rlm@1: u8 color = vram[address]; rlm@1: if (xx & 1) rlm@1: { rlm@1: color = (color >> 4); rlm@1: } rlm@1: else rlm@1: color &= 0x0F; rlm@1: rlm@1: if ((color == 0) && (((prio >> 25)&3) < rlm@1: ((lineOBJ[sx]>>25)&3))) rlm@1: { rlm@1: lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio; rlm@1: if ((a0 & 0x1000) && m) rlm@1: lineOBJ[sx] = (lineOBJ[sx-1] & 0xF9FFFFFF) | prio; rlm@1: } rlm@1: else if ((color) && (prio < (lineOBJ[sx]&0xFF000000))) rlm@1: { rlm@1: lineOBJ[sx] = READ16LE(&spritePalette[palette + color]) | prio; rlm@1: if ((a0 & 0x1000) && m) rlm@1: lineOBJ[sx] = (lineOBJ[sx-1] & 0xF9FFFFFF) | prio; rlm@1: } rlm@1: } rlm@1: if (a0 & 0x1000) rlm@1: { rlm@1: m++; rlm@1: if (m == mosaicX) rlm@1: m = 0; rlm@1: } rlm@1: #ifdef SPRITE_DEBUG rlm@1: if (t == 0 || t == maskY || xx == 0 || xx == maskX) rlm@1: lineOBJ[sx] = 0x001F; rlm@1: #endif rlm@1: sx = (sx+1) & 511; rlm@1: xxx--; rlm@1: if (!(xx & 1)) rlm@1: address--; rlm@1: if (xxx == -1) rlm@1: { rlm@1: xxx = 7; rlm@1: address -= 28; rlm@1: } rlm@1: if (address < 0x10000) rlm@1: address += 0x8000; rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: for (int xx = 0; xx < sizeX; xx++) rlm@1: { rlm@1: if (sx < 240) rlm@1: { rlm@1: u8 color = vram[address]; rlm@1: if (xx & 1) rlm@1: { rlm@1: color = (color >> 4); rlm@1: } rlm@1: else rlm@1: color &= 0x0F; rlm@1: rlm@1: if ((color == 0) && (((prio >> 25)&3) < rlm@1: ((lineOBJ[sx]>>25)&3))) rlm@1: { rlm@1: lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio; rlm@1: if ((a0 & 0x1000) && m) rlm@1: lineOBJ[sx] = (lineOBJ[sx-1] & 0xF9FFFFFF) | prio; rlm@1: } rlm@1: else if ((color) && (prio < (lineOBJ[sx]&0xFF000000))) rlm@1: { rlm@1: lineOBJ[sx] = READ16LE(&spritePalette[palette + color]) | prio; rlm@1: if ((a0 & 0x1000) && m) rlm@1: lineOBJ[sx] = (lineOBJ[sx-1] & 0xF9FFFFFF) | prio; rlm@1: } rlm@1: } rlm@1: if (a0 & 0x1000) rlm@1: { rlm@1: m++; rlm@1: if (m == mosaicX) rlm@1: m = 0; rlm@1: } rlm@1: #ifdef SPRITE_DEBUG rlm@1: if (t == 0 || t == maskY || xx == 0 || xx == maskX) rlm@1: lineOBJ[sx] = 0x001F; rlm@1: #endif rlm@1: sx = (sx+1) & 511; rlm@1: xxx++; rlm@1: if (xx & 1) rlm@1: address++; rlm@1: if (xxx == 8) rlm@1: { rlm@1: address += 28; rlm@1: xxx = 0; rlm@1: } rlm@1: if (address > 0x17fff) rlm@1: address -= 0x8000; rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: inline void gfxDrawOBJWin(u32 *lineOBJWin) rlm@1: { rlm@1: gfxClearArray(lineOBJWin); rlm@1: if (layerEnable & 0x8000) rlm@1: { rlm@1: u16 *sprites = (u16 *)oam; rlm@1: // u16 *spritePalette = &((u16 *)paletteRAM)[256]; rlm@1: for (int x = 0; x < 128; x++) rlm@1: { rlm@1: u16 a0 = READ16LE(sprites++); rlm@1: u16 a1 = READ16LE(sprites++); rlm@1: u16 a2 = READ16LE(sprites++); rlm@1: sprites++; rlm@1: rlm@1: // ignore non OBJ-WIN rlm@1: if ((a0 & 0x0c00) != 0x0800) rlm@1: continue; rlm@1: rlm@1: int sizeY = 8; rlm@1: int sizeX = 8; rlm@1: rlm@1: switch (((a0 >>12) & 0x0c)|(a1>>14)) rlm@1: { rlm@1: case 0: rlm@1: break; rlm@1: case 1: rlm@1: sizeX = sizeY = 16; rlm@1: break; rlm@1: case 2: rlm@1: sizeX = sizeY = 32; rlm@1: break; rlm@1: case 3: rlm@1: sizeX = sizeY = 64; rlm@1: break; rlm@1: case 4: rlm@1: sizeX = 16; rlm@1: break; rlm@1: case 5: rlm@1: sizeX = 32; rlm@1: break; rlm@1: case 6: rlm@1: sizeX = 32; rlm@1: sizeY = 16; rlm@1: break; rlm@1: case 7: rlm@1: sizeX = 64; rlm@1: sizeY = 32; rlm@1: break; rlm@1: case 8: rlm@1: sizeY = 16; rlm@1: break; rlm@1: case 9: rlm@1: sizeY = 32; rlm@1: break; rlm@1: case 10: rlm@1: sizeX = 16; rlm@1: sizeY = 32; rlm@1: break; rlm@1: case 11: rlm@1: sizeX = 32; rlm@1: sizeY = 64; rlm@1: break; rlm@1: default: rlm@1: continue; rlm@1: } rlm@1: rlm@1: int sy = (a0 & 255); rlm@1: rlm@1: if (sy > 160) rlm@1: sy -= 256; rlm@1: rlm@1: if (a0 & 0x0100) rlm@1: { rlm@1: int fieldX = sizeX; rlm@1: int fieldY = sizeY; rlm@1: if (a0 & 0x0200) rlm@1: { rlm@1: fieldX <<= 1; rlm@1: fieldY <<= 1; rlm@1: } rlm@1: rlm@1: int t = VCOUNT - sy; rlm@1: if ((t >= 0) && (t < fieldY)) rlm@1: { rlm@1: int sx = (a1 & 0x1FF); rlm@1: if ((sx < 240) || (((sx + fieldX) & 511) < 240)) rlm@1: { rlm@1: // int t2 = t - (fieldY >> 1); rlm@1: int rot = (a1 >> 9) & 0x1F; rlm@1: u16 *OAM = (u16 *)oam; rlm@1: int dx = READ16LE(&OAM[3 + (rot << 4)]); rlm@1: if (dx & 0x8000) rlm@1: dx |= 0xFFFF8000; rlm@1: int dmx = READ16LE(&OAM[7 + (rot << 4)]); rlm@1: if (dmx & 0x8000) rlm@1: dmx |= 0xFFFF8000; rlm@1: int dy = READ16LE(&OAM[11 + (rot << 4)]); rlm@1: if (dy & 0x8000) rlm@1: dy |= 0xFFFF8000; rlm@1: int dmy = READ16LE(&OAM[15 + (rot << 4)]); rlm@1: if (dmy & 0x8000) rlm@1: dmy |= 0xFFFF8000; rlm@1: rlm@1: int realX = ((sizeX) << 7) - (fieldX >> 1)*dx - (fieldY>>1)*dmx rlm@1: + t * dmx; rlm@1: int realY = ((sizeY) << 7) - (fieldX >> 1)*dy - (fieldY>>1)*dmy rlm@1: + t * dmy; rlm@1: rlm@1: // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); rlm@1: rlm@1: if (a0 & 0x2000) rlm@1: { rlm@1: int c = (a2 & 0x3FF); rlm@1: if ((DISPCNT & 7) > 2 && (c < 512)) rlm@1: continue; rlm@1: int inc = 32; rlm@1: if (DISPCNT & 0x40) rlm@1: inc = sizeX >> 2; rlm@1: else rlm@1: c &= 0x3FE; rlm@1: for (int x = 0; x < fieldX; x++) rlm@1: { rlm@1: int xxx = realX >> 8; rlm@1: int yyy = realY >> 8; rlm@1: rlm@1: if (xxx < 0 || xxx >= sizeX || rlm@1: yyy < 0 || yyy >= sizeY) rlm@1: {} rlm@1: else rlm@1: { rlm@1: u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5) rlm@1: + ((yyy & 7)<<3) + ((xxx >> 3)<<6) + rlm@1: (xxx & 7))&0x7fff)]; rlm@1: if (color) rlm@1: { rlm@1: lineOBJWin[sx] = 1; rlm@1: } rlm@1: } rlm@1: sx = (sx+1)&511;; rlm@1: realX += dx; rlm@1: realY += dy; rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: int c = (a2 & 0x3FF); rlm@1: if ((DISPCNT & 7) > 2 && (c < 512)) rlm@1: continue; rlm@1: rlm@1: int inc = 32; rlm@1: if (DISPCNT & 0x40) rlm@1: inc = sizeX >> 3; rlm@1: // int palette = (a2 >> 8) & 0xF0; rlm@1: for (int x = 0; x < fieldX; x++) rlm@1: { rlm@1: int xxx = realX >> 8; rlm@1: int yyy = realY >> 8; rlm@1: rlm@1: // if(x == 0 || x == (sizeX-1) || rlm@1: // t == 0 || t == (sizeY-1)) { rlm@1: // lineOBJ[sx] = 0x001F | prio; rlm@1: // } else { rlm@1: if (xxx < 0 || xxx >= sizeX || rlm@1: yyy < 0 || yyy >= sizeY) rlm@1: {} rlm@1: else rlm@1: { rlm@1: u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5) rlm@1: + ((yyy & 7)<<2) + ((xxx >> 3)<<5) + rlm@1: ((xxx & 7)>>1))&0x7fff)]; rlm@1: if (xxx & 1) rlm@1: color >>= 4; rlm@1: else rlm@1: color &= 0x0F; rlm@1: rlm@1: if (color) rlm@1: { rlm@1: lineOBJWin[sx] = 1; rlm@1: } rlm@1: } rlm@1: // } rlm@1: sx = (sx+1)&511;; rlm@1: realX += dx; rlm@1: realY += dy; rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: int t = VCOUNT - sy; rlm@1: if ((t >= 0) && (t < sizeY)) rlm@1: { rlm@1: int sx = (a1 & 0x1FF); rlm@1: if (((sx < 240) || (((sx+sizeX)&511) < 240)) && !(a0 & 0x0200)) rlm@1: { rlm@1: if (a0 & 0x2000) rlm@1: { rlm@1: if (a1 & 0x2000) rlm@1: t = sizeY - t - 1; rlm@1: int c = (a2 & 0x3FF); rlm@1: if ((DISPCNT & 7) > 2 && (c < 512)) rlm@1: continue; rlm@1: rlm@1: int inc = 32; rlm@1: if (DISPCNT & 0x40) rlm@1: { rlm@1: inc = sizeX >> 2; rlm@1: } rlm@1: else rlm@1: { rlm@1: c &= 0x3FE; rlm@1: } rlm@1: int xxx = 0; rlm@1: if (a1 & 0x1000) rlm@1: xxx = sizeX-1; rlm@1: int address = 0x10000 + ((((c+ (t>>3) * inc) << 5) rlm@1: + ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7))&0x7fff); rlm@1: if (a1 & 0x1000) rlm@1: xxx = 7; rlm@1: // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); rlm@1: for (int xx = 0; xx < sizeX; xx++) rlm@1: { rlm@1: if (sx < 240) rlm@1: { rlm@1: u8 color = vram[address]; rlm@1: if (color) rlm@1: { rlm@1: lineOBJWin[sx] = 1; rlm@1: } rlm@1: } rlm@1: rlm@1: sx = (sx+1) & 511; rlm@1: if (a1 & 0x1000) rlm@1: { rlm@1: xxx--; rlm@1: address--; rlm@1: if (xxx == -1) rlm@1: { rlm@1: address -= 56; rlm@1: xxx = 7; rlm@1: } rlm@1: if (address < 0x10000) rlm@1: address += 0x8000; rlm@1: } rlm@1: else rlm@1: { rlm@1: xxx++; rlm@1: address++; rlm@1: if (xxx == 8) rlm@1: { rlm@1: address += 56; rlm@1: xxx = 0; rlm@1: } rlm@1: if (address > 0x17fff) rlm@1: address -= 0x8000; rlm@1: } rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: if (a1 & 0x2000) rlm@1: t = sizeY - t - 1; rlm@1: int c = (a2 & 0x3FF); rlm@1: if ((DISPCNT & 7) > 2 && (c < 512)) rlm@1: continue; rlm@1: rlm@1: int inc = 32; rlm@1: if (DISPCNT & 0x40) rlm@1: { rlm@1: inc = sizeX >> 3; rlm@1: } rlm@1: int xxx = 0; rlm@1: if (a1 & 0x1000) rlm@1: xxx = sizeX - 1; rlm@1: int address = 0x10000 + ((((c + (t>>3) * inc)<<5) rlm@1: + ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7fff); rlm@1: // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); rlm@1: // int palette = (a2 >> 8) & 0xF0; rlm@1: if (a1 & 0x1000) rlm@1: { rlm@1: xxx = 7; rlm@1: for (int xx = sizeX - 1; xx >= 0; xx--) rlm@1: { rlm@1: if (sx < 240) rlm@1: { rlm@1: u8 color = vram[address]; rlm@1: if (xx & 1) rlm@1: { rlm@1: color = (color >> 4); rlm@1: } rlm@1: else rlm@1: color &= 0x0F; rlm@1: rlm@1: if (color) rlm@1: { rlm@1: lineOBJWin[sx] = 1; rlm@1: } rlm@1: } rlm@1: sx = (sx+1) & 511; rlm@1: xxx--; rlm@1: if (!(xx & 1)) rlm@1: address--; rlm@1: if (xxx == -1) rlm@1: { rlm@1: xxx = 7; rlm@1: address -= 28; rlm@1: } rlm@1: if (address < 0x10000) rlm@1: address += 0x8000; rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: for (int xx = 0; xx < sizeX; xx++) rlm@1: { rlm@1: if (sx < 240) rlm@1: { rlm@1: u8 color = vram[address]; rlm@1: if (xx & 1) rlm@1: { rlm@1: color = (color >> 4); rlm@1: } rlm@1: else rlm@1: color &= 0x0F; rlm@1: rlm@1: if (color) rlm@1: { rlm@1: lineOBJWin[sx] = 1; rlm@1: } rlm@1: } rlm@1: sx = (sx+1) & 511; rlm@1: xxx++; rlm@1: if (xx & 1) rlm@1: address++; rlm@1: if (xxx == 8) rlm@1: { rlm@1: address += 28; rlm@1: xxx = 0; rlm@1: } rlm@1: if (address > 0x17fff) rlm@1: address -= 0x8000; rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: inline u32 gfxIncreaseBrightness(u32 color, int coeff) rlm@1: { rlm@1: int r = (color & 0x1F); rlm@1: int g = ((color >> 5) & 0x1F); rlm@1: int b = ((color >> 10) & 0x1F); rlm@1: rlm@1: r = r + (((31 - r) * coeff) >> 4); rlm@1: g = g + (((31 - g) * coeff) >> 4); rlm@1: b = b + (((31 - b) * coeff) >> 4); rlm@1: if (r > 31) rlm@1: r = 31; rlm@1: if (g > 31) rlm@1: g = 31; rlm@1: if (b > 31) rlm@1: b = 31; rlm@1: color = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r; rlm@1: return color; rlm@1: } rlm@1: rlm@1: inline void gfxIncreaseBrightness(u32 *line, int coeff) rlm@1: { rlm@1: for (int x = 0; x < 240; x++) rlm@1: { rlm@1: u32 color = *line; rlm@1: int r = (color & 0x1F); rlm@1: int g = ((color >> 5) & 0x1F); rlm@1: int b = ((color >> 10) & 0x1F); rlm@1: rlm@1: r = r + (((31 - r) * coeff) >> 4); rlm@1: g = g + (((31 - g) * coeff) >> 4); rlm@1: b = b + (((31 - b) * coeff) >> 4); rlm@1: if (r > 31) rlm@1: r = 31; rlm@1: if (g > 31) rlm@1: g = 31; rlm@1: if (b > 31) rlm@1: b = 31; rlm@1: *line++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r; rlm@1: } rlm@1: } rlm@1: rlm@1: inline u32 gfxDecreaseBrightness(u32 color, int coeff) rlm@1: { rlm@1: int r = (color & 0x1F); rlm@1: int g = ((color >> 5) & 0x1F); rlm@1: int b = ((color >> 10) & 0x1F); rlm@1: rlm@1: r = r - ((r * coeff) >> 4); rlm@1: g = g - ((g * coeff) >> 4); rlm@1: b = b - ((b * coeff) >> 4); rlm@1: if (r < 0) rlm@1: r = 0; rlm@1: if (g < 0) rlm@1: g = 0; rlm@1: if (b < 0) rlm@1: b = 0; rlm@1: color = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r; rlm@1: rlm@1: return color; rlm@1: } rlm@1: rlm@1: inline void gfxDecreaseBrightness(u32 *line, int coeff) rlm@1: { rlm@1: for (int x = 0; x < 240; x++) rlm@1: { rlm@1: u32 color = *line; rlm@1: int r = (color & 0x1F); rlm@1: int g = ((color >> 5) & 0x1F); rlm@1: int b = ((color >> 10) & 0x1F); rlm@1: rlm@1: r = r - ((r * coeff) >> 4); rlm@1: g = g - ((g * coeff) >> 4); rlm@1: b = b - ((b * coeff) >> 4); rlm@1: if (r < 0) rlm@1: r = 0; rlm@1: if (g < 0) rlm@1: g = 0; rlm@1: if (b < 0) rlm@1: b = 0; rlm@1: *line++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r; rlm@1: } rlm@1: } rlm@1: rlm@1: inline u32 gfxAlphaBlend(u32 color, u32 color2, int ca, int cb) rlm@1: { rlm@1: if (color < 0x80000000) rlm@1: { rlm@1: int r = (color & 0x1F); rlm@1: int g = ((color >> 5) & 0x1F); rlm@1: int b = ((color >> 10) & 0x1F); rlm@1: int r0 = (color2 & 0x1F); rlm@1: int g0 = ((color2 >> 5) & 0x1F); rlm@1: int b0 = ((color2 >> 10) & 0x1F); rlm@1: rlm@1: r = ((r * ca) >> 4) + ((r0 * cb) >> 4); rlm@1: g = ((g * ca) >> 4) + ((g0 * cb) >> 4); rlm@1: b = ((b * ca) >> 4) + ((b0 * cb) >> 4); rlm@1: rlm@1: if (r > 31) rlm@1: r = 31; rlm@1: if (g > 31) rlm@1: g = 31; rlm@1: if (b > 31) rlm@1: b = 31; rlm@1: rlm@1: return (color & 0xFFFF0000) | (b << 10) | (g << 5) | r; rlm@1: } rlm@1: return color; rlm@1: } rlm@1: rlm@1: inline void gfxAlphaBlend(u32 *ta, u32 *tb, int ca, int cb) rlm@1: { rlm@1: for (int x = 0; x < 240; x++) rlm@1: { rlm@1: u32 color = *ta; rlm@1: if (color < 0x80000000) rlm@1: { rlm@1: int r = (color & 0x1F); rlm@1: int g = ((color >> 5) & 0x1F); rlm@1: int b = ((color >> 10) & 0x1F); rlm@1: u32 color2 = (*tb++); rlm@1: int r0 = (color2 & 0x1F); rlm@1: int g0 = ((color2 >> 5) & 0x1F); rlm@1: int b0 = ((color2 >> 10) & 0x1F); rlm@1: rlm@1: r = ((r * ca) >> 4) + ((r0 * cb) >> 4); rlm@1: g = ((g * ca) >> 4) + ((g0 * cb) >> 4); rlm@1: b = ((b * ca) >> 4) + ((b0 * cb) >> 4); rlm@1: rlm@1: if (r > 31) rlm@1: r = 31; rlm@1: if (g > 31) rlm@1: g = 31; rlm@1: if (b > 31) rlm@1: b = 31; rlm@1: rlm@1: *ta++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r; rlm@1: } rlm@1: else rlm@1: { rlm@1: ta++; rlm@1: tb++; rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: #endif // VBA_GBA_GFX_H