📄 gbagpu.cpp
字号:
/*************************************************************************** DSemu - The Next Generation ** GBA scanline GPU: Plugin Implementation [gbagpu.cpp] ** Copyright Imran Nazar, 2005; released under the BSD public licence. ***************************************************************************/#include <string>#include "defs.h"#include "events.h"#include "gbagpu.h"#include "config.h"#include "font5x7.h"#include "log.h"#include "err.h"//---Static private class members------------------------------------------// Every plugin has an INFO structure attached, with info about the plugin.PLUGININFO gbaGPU::pInfo={ PLUGIN_TYPE_GPU, 0x00010001, "GBA graphics processor", "DSemu-ng"};u8 *gbaGPU::VRAMb, *gbaGPU::OAMb;u16 *gbaGPU::VRAMh, *gbaGPU::PALh, *gbaGPU::OAMh;u32 *gbaGPU::VRAMw, *gbaGPU::PALw, *gbaGPU::OAMw;gbaGPU::IOREG gbaGPU::reg[0x30];// IO access flags: 1=Readable, 2=Writableint gbaGPU::rflags[0x30]={ 3,3,3,1,3,3,3,3,3,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,0,3,3,3,0,0,0,0,0,};#define REG(x) reg[REG_ ## x].datau32 gbaGPU::BGX[2], gbaGPU::BGY[2];u8 gbaGPU::mospy[4];int gbaGPU::curline;std::string gbaGPU::pluginName;GUIPlugin *gbaGPU::GUI;int gbaGPU::palwinID;u32 *gbaGPU::palbuffer;u8 *gbaGPU::dispbuffer;int gbaGPU::ForceBG[4];// Convert a GBA 15-bit colour to 32-bit#define COLSHIFT(out, in) \{ \ *((out)+0) = ((in)<<3)&255; \ *((out)+1) = ((in)>>2)&255; \ *((out)+2) = ((in)>>7)&255; \ *((out)+3) = 0; \}// Table of function pointers to mode-specific renderersgbaGPU::modefptr gbaGPU::lineM[8]={ lineM0, lineM1, lineM2, lineM3, lineM4, lineM5, lineMNULL, lineMNULL};//---Implementation--------------------------------------------------------// ACK: gladius (tile and rotated BG, and sprite renderers)void gbaGPU::scanTile(u8 *buf, int bg){ u16 bgcnt, scrnBase, charBase, hofs, vofs, x, y, tileIdx, tileY; u16 tmpTileIdx, width=0, height=0, a, bgx, bgy, tileChar; u8 b=0, palnum; u8 mosx, mospx, mosy; bgcnt=reg[REG_BG0CNT+bg].data; switch((bgcnt>>14)&3) { case 0: width=256; height=256; break; case 1: width=512; height=256; break; case 2: width=256; height=512; break; case 3: width=512; height=512; break; } scrnBase=((bgcnt>>8)&0x1F)*0x400; charBase=((bgcnt>>2)&0x3)*0x4000; hofs=reg[REG_BG0HOFS+bg*2].data; vofs=reg[REG_BG0VOFS+bg*2].data;/* vramptr=VRAM+(VRAMmap[(lcd)*128]<<13); vram8ptr=VRAM8+(VRAMmap[(lcd)*128]<<14);*/ if(bgcnt&0x0040) { mosx=(REG(MOSAIC)&0x000F); mosy=((REG(MOSAIC)&0x00F0)>>4); mospx=mosx; if(!curline) mospy[bg]=mosy; mospy[bg]++; if(mospy[bg]<=mosy) vofs-=mospy[bg]; else mospy[bg]=0; } else { mospx=0; mosx=0; } if(bgcnt&0x0080) { bgy=((curline+vofs)&(height-1))/8; tileIdx=scrnBase+(((bgy&31)*32)); switch((bgcnt>>14)&3) { case 2: if(bgy>=32) tileIdx += 32*32; break; case 3: if(bgy>=32) tileIdx += 32*32*2; break; } tileY=((curline+vofs)&7)*8; for(a=0;a<240;a++) { bgx=((a+hofs)&(width-1))/8; tmpTileIdx=tileIdx+((bgx&31)); if(bgx>=32) tmpTileIdx += 32*32; tileChar=VRAMh[tmpTileIdx]; x=(a+hofs)&7; y=tileY; if(tileChar&0x0400) x=7-x; if(tileChar&0x0800) y=56-y; if(mospx>=mosx) b=VRAMb[charBase+((tileChar&0x03FF)*64)+x+y]; mospx++; if(mospx>mosx) mospx=0; if(b) COLSHIFT(buf+a*4,PALh[b]); } } else { bgy=((curline+vofs)&(height-1))/8; tileIdx=scrnBase+(((bgy&31)*32)); switch((bgcnt>>14)&3) { case 2: if(bgy>=32) tileIdx += 32*32; break; case 3: if(bgy>=32) tileIdx += 32*32*2; break; } tileY=((curline+vofs)&7)*4; for(a=0;a<240;a++) { bgx=((a+hofs)&(width-1))/8; tmpTileIdx=tileIdx+((bgx&31)); if(bgx>=32) tmpTileIdx += 32*32; tileChar=VRAMh[tmpTileIdx]; x=(a+hofs)&7; y=tileY; if(tileChar&0x0400) x=7-x; if(tileChar&0x0800) y=28-y; if(mospx>=mosx) { b=VRAMb[charBase+((tileChar&0x03FF)*32)+(x/2)+y]; if(x&1) b>>=4; b&=15; } palnum=((tileChar>>12)&15)*16; mospx++; if(mospx>mosx) mospx=0; if(b) COLSHIFT(buf+a*4,PALh[b+palnum]); } }}void gbaGPU::scanRot(u8 *buf, int bg){ u16 bgcnt, scrnBase, charBase; u32 x,y; int ax,ay; s16 dx,dy; int trans; u8 mosx, mospx, mosy; u16 tmpTileIdx, width=0, height=0, a, tileChar; u8 b=0; bgcnt=REG(BG0CNT+bg); bg-=2; trans=(bgcnt&0x2000)==0; switch((bgcnt>>14)&3) { case 0: width=128; height=128; break; case 1: width=256; height=256; break; case 2: width=512; height=512; break; case 3: width=1024; height=1024; break; } scrnBase=((bgcnt>>8)&0x1F)*0x800; charBase=((bgcnt>>2)&0x3)*0x4000; x=BGX[bg]; y=BGY[bg]; dx=REG(BG2PA+(bg*8)); dy=REG(BG2PC+(bg*8)); if(bgcnt&0x0040) { mosx=(REG(MOSAIC)&0x000F); mosy=((REG(MOSAIC)&0x00F0)>>4); mospx=mosx; if(!curline) mospy[bg]=mosy; mospy[bg]++; if(mospy[bg]<=mosy) y-=mospy[bg]*256; else mospy[bg]=0; } else { mospx=0; mosx=0; } for(a=0;a<240;a++) { ax=x>>8; ay=y>>8; if ((ax >= 0 && ax < width && ay >= 0 && ay < height) || !trans) { tmpTileIdx=scrnBase+(((ay&(height-1))/8)*(width/8)+((ax&(width-1))/8)); tileChar=VRAMb[tmpTileIdx]; if(mospx>=mosx) b=VRAMb[charBase+tileChar*64+((ay&7)*8)+(ax&7)]; mospx+=(dx>>8); if(mospx>mosx) mospx=0; if(b) COLSHIFT(buf+a*4,PALh[b]); } x+=dx; y+=dy; }}void gbaGPU::sprites(u8 *buf, int pri){ u16 dispcnt=REG(DISPCNT), oamNum, attr0,attr1,attr2; int x, y, i, width=-1, height=-1, rwidth, rheight, scale=1; int spritey, baseSprite, baseInc, curIdx, palIdx; u8 b; s16 dx,dmx,rx,dy,dmy,ry; int tx,ty,cx,cy,pitch,rotScaleParam; if(!(dispcnt&0x1000)) return; pri<<=10; oamNum=128; do { width=0; height=0; oamNum--; attr2=OAMh[oamNum*4+2]; if((attr2&0x0C00)!=pri) continue; attr0=OAMh[oamNum*4+0]; attr1=OAMh[oamNum*4+1]; x=attr1&0x01FF; y=attr0&0x00FF; switch ((attr0 >> 14) & 3) { case 0: // Square switch ((attr1 >> 14) & 3) { case 0: width = 8; height = 8; break; case 1: width = 16; height = 16; break; case 2: width = 32; height = 32; break; case 3: width = 64; height = 64; break; } break; case 1: // Horizontal Rectangle switch ((attr1 >> 14) & 3) { case 0: width = 16; height = 8; break; case 1: width = 32; height = 8; break; case 2: width = 32; height = 16; break; case 3: width = 64; height = 32; break; } break; case 2: // Vertical Rectangle switch ((attr1 >> 14) & 3) { case 0: width = 8; height = 16; break; case 1: width = 8; height = 32; break; case 2: width = 16; height = 32; break; case 3: width = 32; height = 64; break; } break; } rwidth=width; rheight=height; if (attr0&0x0100) // Rot-scale on if (attr0&0x0200) { rwidth*=2; rheight*=2; } else // Invalid sprite if (attr0&0x0200) width = -1; if (width == -1) // Invalid sprite continue; // Y clipping if (y > ((y + rheight) & 0xff)) if (curline >= ((y + rheight) & 0xff) && !(y < curline)) continue; else if (curline < y || curline >= ((y + rheight) & 0xff)) continue; if (attr0&0x2000) scale = 2; spritey = curline - y; if (spritey < 0) spritey += 256; if (!(attr0&0x0100)) { if (attr1&0x2000) spritey = (height - 1) - spritey; if (dispcnt&0x0040) // 1 dimensional baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * (width / 8)) * scale; else // 2 dimensional baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * 0x20); baseInc = scale; if (attr1&0x1000) { baseSprite += ((width / 8) * scale) - scale; baseInc = -baseInc; } if (attr0&0x2000) { // 256 colors //if(baseSprite && spritey>=0 && spritey<height) //printf("GPU: Line #%d: Sprite #%d: %dx%d at %d,%d, non-rotating, 8-bit\n",curline,oamNum,width,height,x,y); for (i = x; i < x + width; i++) { if ((i & 0x1ff) < 240 && spritey >= 0 && spritey < height) { tx = (i - x) & 7; if (attr1&0x1000) tx = 7 - tx; curIdx = baseSprite * 32 + ((spritey & 7) * 8) + tx; b = VRAMb[0x10000 + curIdx]; if (b) COLSHIFT(buf+(i&0x1ff)*4,PALh[b+256]); } if (((i - x) & 7) == 7) baseSprite += baseInc; } } else { // 16 colors //if(baseSprite && spritey>=0 && spritey<height) //printf("GPU: Line #%d: Sprite #%d: %dx%d at %d,%d, non-rotating, 4-bit\n",curline,oamNum,width,height,x,y); palIdx = ((attr2 >> 8) & 0xF0); for (i = x; i < x + width; i++) { if ((i & 0x1ff) < 240 && spritey >= 0 && spritey < height) { tx = (i - x) & 7; if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; curIdx = baseSprite * 32 + ((spritey & 7) * 4) + (tx / 2); b = VRAMb[0x10000 + curIdx]; if (tx & 1) b>>=4; b&=15; if(b) COLSHIFT(buf+(i&0x1ff)*4, PALh[palIdx+b+256]); } if (((i - x) & 7) == 7) baseSprite += baseInc; } } } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -