⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gbagpu.cpp

📁 一个任天堂掌上游戏机NDS的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
                    rotScaleParam = (attr1 >> 9) & 0x1F;                    dx =  (s16)OAMh[(rotScaleParam * 4 * 4) + 3];                    dmx = (s16)OAMh[(rotScaleParam * 4 * 4) + 7];                    dy =  (s16)OAMh[(rotScaleParam * 4 * 4) + 11];                    dmy = (s16)OAMh[(rotScaleParam * 4 * 4) + 15];                    cx = rwidth / 2;                    cy = rheight / 2;                    baseSprite = attr2 & 0x3FF;                    if (dispcnt&0x0040)                        // 1 dimensional                        pitch = (width / 8) * scale;                    else                        // 2 dimensional                        pitch = 0x20;                    rx = (s16)((dmx * (spritey - cy)) - (cx * dx) + (width << 7));                    ry = (s16)((dmy * (spritey - cy)) - (cx * dy) + (height << 7));                    // Draw a rot/scale sprite                    if (attr0&0x2000)                    {			//if(baseSprite && spritey>=0 && spritey<height)                        //printf("GPU: Line #%d: Sprite #%d: %dx%d at %d,%d, rotating, 8-bit\n",curline,oamNum,width,height,x,y);                        // 256 colors                        for (i = x; i < x + rwidth; i++)                        {                            tx = rx >> 8;                            ty = ry >> 8;                            if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height)                            {                                curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 8) + (tx & 7);                                b = VRAMb[0x10000 + curIdx];                                if(b) COLSHIFT(buf+(i&0x1ff)*4, PALh[b+256]);                            }                            rx += dx;                            ry += dy;                        }                    }                    else                    {                        // 16 colors			//if(baseSprite && spritey>=0 && spritey<height)                        //printf("GPU: Line #%d: Sprite #%d: %dx%d at %d,%d, rotating, 4-bit\n",curline,oamNum,width,height,x,y);                        palIdx = ((attr2 >> 8) & 0xF0);                        for (i = x; i < x + rwidth; i++)                        {                            tx = rx >> 8;                            ty = ry >> 8;                            if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height)                            {                                curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 4) + ((tx & 7) / 2);                                b = VRAMb[0x10000 + curIdx];                                if (tx & 1) b>>=4; b&=15;                                if(b) COLSHIFT(buf+(i&0x1ff)*4, PALh[palIdx+b+256]);                            }                            rx += dx;                            ry += dy;                        }                    }                }    } while(oamNum);}// NOTE: Each renderer draws the backgrounds in reverse priority order,// rendering the sprites on each priority level after the background.// Mode 0: 4 tiled BGsvoid gbaGPU::lineM0(u8 *buf){    u16 dispcnt=REG(DISPCNT);    for(int pri=3;pri>=0;pri--)    {        if(ForceBG[3]!=2) if(dispcnt&0x0800 || ForceBG[3]) if((REG(BG3CNT)&3)==pri) scanTile(buf,3);        if(ForceBG[2]!=2) if(dispcnt&0x0400 || ForceBG[2]) if((REG(BG2CNT)&3)==pri) scanTile(buf,2);        if(ForceBG[1]!=2) if(dispcnt&0x0200 || ForceBG[1]) if((REG(BG1CNT)&3)==pri) scanTile(buf,1);        if(ForceBG[0]!=2) if(dispcnt&0x0100 || ForceBG[0]) if((REG(BG0CNT)&3)==pri) scanTile(buf,0);        sprites(buf,pri);    }}// Mode 1: Two tiled and 1 rot BGvoid gbaGPU::lineM1(u8 *buf){    u16 dispcnt=REG(DISPCNT);    for(int pri=3;pri>=0;pri--)    {        if(ForceBG[3]!=2) if(dispcnt&0x0400 || ForceBG[2]) if((REG(BG2CNT)&3)==pri) scanRot(buf,2);        if(ForceBG[2]!=2) if(dispcnt&0x0200 || ForceBG[1]) if((REG(BG1CNT)&3)==pri) scanTile(buf,1);        if(ForceBG[1]!=2) if(dispcnt&0x0100 || ForceBG[0]) if((REG(BG0CNT)&3)==pri) scanTile(buf,0);        sprites(buf,pri);    }}// Mode 2: 2 rot backgroundsvoid gbaGPU::lineM2(u8 *buf){    u16 dispcnt=REG(DISPCNT);    for(int pri=3;pri>=0;pri--)    {        if(ForceBG[3]!=2) if(dispcnt&0x0800 || ForceBG[3]) if((REG(BG3CNT)&3)==pri) scanRot(buf,3);        if(ForceBG[2]!=2) if(dispcnt&0x0400 || ForceBG[2]) if((REG(BG2CNT)&3)==pri) scanRot(buf,2);        sprites(buf,pri);    }}// Mode 3: Flat (rotatable) 16-bit framebuffervoid gbaGPU::lineM3(u8 *buf){    u16 dispcnt=REG(DISPCNT), bg2cnt=REG(BG2CNT), i; int pri;    u32 x,y,ax,ay; s16 dx,dy; u16 mosx,mospx,mosy;    for(pri=3;pri>(bg2cnt&3);pri--) sprites(buf,pri);    if(ForceBG[2]!=2 && (dispcnt&0x0400 || ForceBG[2]==1))    {        x=BGX[0]; y=BGY[0];        if(bg2cnt&0x0040)        {            mosx=(REG(MOSAIC)&0x000F);            mosy=((REG(MOSAIC)&0x00F0)>>4);            mospx=mosx; if(!curline) mospy[2]=mosy;            mospy[2]++; if(mospy[2]<=mosy) y-=mospy[2]*256;            else mospy[2]=0;        } else { mospx=0; mosx=0; }        dx=(signed)REG(BG2PA); dy=(signed)REG(BG2PC);        for(i=0;i<240;i++)        {            ax=x>>8; ay=y>>8;            if (ax >= 0 && ax < 240 && ay >= 0 && ay < 160)            {                if(mospx>=mosx) COLSHIFT(buf+i*4, VRAMh[ay*240+ax]);            }            mospx+=(dx>>8); if(mospx>mosx) mospx=0;            x+=dx; y+=dy;        }    }    for(pri=(bg2cnt&3);pri>=0;pri--) sprites(buf,pri);}// Mode 4: 2 paletted framebuffers, switchable on BG2CNT bit 4void gbaGPU::lineM4(u8 *buf){    u16 dispcnt=REG(DISPCNT), bg2cnt=REG(BG2CNT), i; int pri;    u32 x,y,ax,ay; s16 dx,dy; u8 b=0; u16 mosx,mospx,mosy;    u16 baseIdx=(bg2cnt&0x0010)?0xA000:0;    for(pri=3;pri>(bg2cnt&3);pri--) sprites(buf,pri);    if(ForceBG[2]!=2 && (dispcnt&0x0400 || ForceBG[2]==1))    {        x=BGX[0]; y=BGY[0];        if(bg2cnt&0x0040)        {            mosx=(REG(MOSAIC)&0x000F);            mosy=((REG(MOSAIC)&0x00F0)>>4);            mospx=mosx; if(!curline) mospy[2]=mosy;            mospy[2]++; if(mospy[2]<=mosy) y-=mospy[2]*256;            else mospy[2]=0;        } else { mospx=0; mosx=0; }        dx=(signed)REG(BG2PA); dy=(signed)REG(BG2PC);        for(i=0;i<240;i++)        {            ax=x>>8; ay=y>>8;            if (ax >= 0 && ax < 240 && ay >= 0 && ay < 160)            {                if(mospx>=mosx) b=VRAMb[baseIdx+ay*240+ax];                if(b) COLSHIFT(buf+i*4, PALh[b]);            }            mospx+=(dx>>8); if(mospx>mosx) mospx=0;            x+=dx; y+=dy;        }    }    for(pri=(bg2cnt&3);pri>=0;pri--) sprites(buf,pri);}// Mode 5: 2 reduced-size framebuffers, switchable on BG2CNT b4void gbaGPU::lineM5(u8 *buf){    u16 dispcnt=REG(DISPCNT), bg2cnt=REG(BG2CNT), i; int pri;    u32 x,y,ax,ay; s16 dx,dy; u16 mosx,mospx,mosy;    u16 baseIdx=(bg2cnt&0x0010)?(160*128):0;    for(pri=3;pri>(bg2cnt&3);pri--) sprites(buf,pri);    if(ForceBG[2]!=2 && (dispcnt&0x0400 || ForceBG[2]==1))    {        x=BGX[0]; y=BGY[0];        if(bg2cnt&0x0040)        {            mosx=(REG(MOSAIC)&0x000F);            mosy=((REG(MOSAIC)&0x00F0)>>4);            mospx=mosx; if(!curline) mospy[2]=mosy;            mospy[2]++; if(mospy[2]<=mosy) y-=mospy[2]*256;            else mospy[2]=0;        } else { mospx=0; mosx=0; }        dx=(signed)REG(BG2PA); dy=(signed)REG(BG2PC);        for(i=0;i<240;i++)        {            ax=x>>8; ay=y>>8;            if (ax >= 0 && ax < 160 && ay >= 0 && ay < 128)            {                if(mospx>=mosx) COLSHIFT(buf+i*4, VRAMh[baseIdx+ay*160+ax]);            }            mospx+=(dx>>8); if(mospx>mosx) mospx=0;            x+=dx; y+=dy;        }    }    for(pri=(bg2cnt&3);pri>=0;pri--) sprites(buf,pri);}// Null renderer: Should never have to draw this.void gbaGPU::lineMNULL(u8 *buf){    Logger::log(pluginName) << "How'd we get to lineMNULL?";}// Tell the GPU where it'll be rendering tovoid gbaGPU::setDisplay(u8 *buf){    dispbuffer=buf;}// Render a scanline (wrapper for mode-specific renderers)void gbaGPU::line(){    u16 dispcnt = REG(DISPCNT);    u8 *buffer = dispbuffer;    if(curline >= 0 && curline <= 160)    {	buffer += (curline*240*4);	if(dispcnt&0x0080)  // Blank screen	{	    for(int i=0; i<240; ++i) COLSHIFT(buffer+i*4, 0x00FFFFFF);        }	else  // First draw the backdrop, then the line	{	    for(int i=0; i<240; ++i) COLSHIFT(buffer+i*4, PALh[0]);	    lineM[dispcnt&7](buffer);	}    }    // The line's done, so hblank begins    HBLstart();}// Beginning of hblank: Set hbl bit, fire interruptvoid gbaGPU::HBLstart(){    reg[REG_DISPSTAT].b[0] |= 2;    if(reg[REG_DISPSTAT].b[0] & 16)    {	if((MMU->rdH(0x04000200) & 2) && MMU->rdH(0x04000208))	{	    MMU->wrH(0x04000202, MMU->rdH(0x04000202)&~2);	    CPU->interrupt(CPU_INTERRUPT_NORMAL);	}    }    MMU->event(MMU_EVENT_IMMEDIATE, NULL);        // Tell the GUI to stop hblank in 272 cycles    GUI->eventPush(272, EVENT_HBLANK_END, (vfptr)hblankend, this);}// Finish hblankvoid gbaGPU::HBLend(){    curline++;    // If that end of hblank took us to line 160, we've come to the vblank.    // Fire that off to the CPU    if(curline==160)    {	reg[REG_DISPSTAT].b[0] |= 1;	if(reg[REG_DISPSTAT].b[0] & 8)	{	    if((MMU->rdH(0x04000200) & 1) && MMU->rdH(0x04000208))	    {		MMU->wrH(0x04000202, MMU->rdH(0x04000202)&~1);		CPU->interrupt(CPU_INTERRUPT_NORMAL);	    }	}    }    if(curline>227) curline = 0;    // Update line counter. If we hit a requested vcount, fire    // an interrupt.    reg[REG_VCOUNT].b[0] = curline;    if(curline == reg[REG_DISPSTAT].b[1])    {	reg[REG_DISPSTAT].b[0] |= 4;	if(reg[REG_DISPSTAT].b[0] & 32)	{	    if((MMU->rdH(0x04000200) & 4) && MMU->rdH(0x04000208))	    {		MMU->wrH(0x04000202, MMU->rdH(0x04000202)&~4);		CPU->interrupt(CPU_INTERRUPT_NORMAL);	    }	}    }    else reg[REG_DISPSTAT].b[0] &= ~4;        REG(DISPSTAT)&=(~2);        // Update the background rotation characteristics. If we're at    // the top of the screen, reload them.    BGX[0]+=(s16)REG(BG2PB); BGY[0]+=(s16)REG(BG2PD);    BGX[1]+=(s16)REG(BG3PB); BGY[1]+=(s16)REG(BG3PD);    switch(curline)    {        case 0:           REG(DISPSTAT)&=(~1);           BGX[0]=REG(BG2XL)+(REG(BG2XH)<<16);           BGX[1]=REG(BG3XL)+(REG(BG3XH)<<16);           BGY[0]=REG(BG2YL)+(REG(BG2YH)<<16);           BGY[1]=REG(BG3YL)+(REG(BG3YH)<<16);           break;        case 160:	   REG(DISPSTAT)|=1;	   break;    }    MMU->event(MMU_EVENT_IMMEDIATE, NULL);        // Tell the GUI to draw a line in 960 cycles' time.    GUI->eventPush(960, EVENT_HBLANK_START, (vfptr)drawline, this);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -