rastergf.cpp
来自「DGen源码最后版本」· C++ 代码 · 共 428 行
CPP
428 行
// rastergfx.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "md.h"
typedef unsigned char byte;
typedef unsigned short word;
static word *dstPix;
static unsigned int highpal[64]={0};
static unsigned char *vram=NULL,*vsram=NULL,*cram=NULL;
static unsigned char *reg=NULL;
static void DrawMDWindow( int scanline, int front );
static void DrawMDTile ( int scanline, word *pix, int tile );
static void DrawMDSolid ( int scanline, word *pix, int tile );
// Dave: this is the btye order switch (0=intel 1=68000-style)
#if 0
#define Get16(x) (*(unsigned short*)(x))
#else
#define Get16(x) ( ((unsigned char*)(x))[0]<<8 | ((unsigned char*)(x))[1] )
#endif
static void DrawMDSolid ( int scanline, word *pix, int tile )
{
unsigned int src, palTemp;
unsigned char *offPal;
offPal = (unsigned char*) &highpal[ (tile >> 9) & 0x0030 ];
palTemp = *(unsigned long*)offPal;
*(unsigned long*)offPal = highpal[reg[0x7]&63];
if( tile & 0x1000 ) // y flipped
{
scanline = 7-scanline;
}
if( reg[12] & 2 ) // interlace mode
{
src = *(unsigned int*) (vram + ((tile&2047) << 6) + (scanline << 3));
}
else
{
src = *(unsigned int*) (vram + ((tile&2047) << 5) + (scanline << 2));
}
if( tile & 0x0800 ) // x flipped
{
// Dave: Changed for intel order
*(pix+6) = *(unsigned long*)( offPal + ((src & 0x0000000F)<< 2));
*(pix+7) = *(unsigned long*)( offPal + ((src & 0x000000F0)>> 2));
*(pix+4) = *(unsigned long*)( offPal + ((src & 0x00000F00)>> 6));
*(pix+5) = *(unsigned long*)( offPal + ((src & 0x0000F000)>>10));
*(pix+2) = *(unsigned long*)( offPal + ((src & 0x000F0000)>>14));
*(pix+3) = *(unsigned long*)( offPal + ((src & 0x00F00000)>>18));
*(pix+0) = *(unsigned long*)( offPal + ((src & 0x0F000000)>>22));
*(pix+1) = *(unsigned long*)( offPal + ((src & 0xF0000000)>>26));
}
else
{
*(pix+6) = *(unsigned long*)( offPal + ((src & 0xF0000000)>>26));
*(pix+7) = *(unsigned long*)( offPal + ((src & 0x0F000000)>>22));
*(pix+4) = *(unsigned long*)( offPal + ((src & 0x00F00000)>>18));
*(pix+5) = *(unsigned long*)( offPal + ((src & 0x000F0000)>>14));
*(pix+2) = *(unsigned long*)( offPal + ((src & 0x0000F000)>>10));
*(pix+3) = *(unsigned long*)( offPal + ((src & 0x00000F00)>> 6));
*(pix+0) = *(unsigned long*)( offPal + ((src & 0x000000F0)>> 2));
*(pix+1) = *(unsigned long*)( offPal + ((src & 0x0000000F)<< 2));
}
*(unsigned long*)offPal = palTemp;
}
static void DrawMDTile ( int scanline, word *pix, int tile )
{
unsigned int src;
unsigned char *offPal;
offPal = (unsigned char*) &highpal[ (tile >> 9) & 0x0030 ];
if( tile & 0x1000 ) // y flipped
{
scanline = 7-scanline;
}
if( reg[12] & 2 ) // interlace mode
{
src = *(unsigned int*) (vram + ((tile&2047) << 6) + (scanline << 3));
}
else
{
src = *(unsigned int*) (vram + ((tile&2047) << 5) + (scanline << 2));
}
if( src )
{
// Dave: Changed for intel order
if( tile & 0x0800 ) // x flipped
{
if( (src & 0x0000000F)<< 2 ) *(pix+6) = *(unsigned long*)( offPal + ((src & 0x0000000F)<< 2));
if( (src & 0x000000F0)>> 2 ) *(pix+7) = *(unsigned long*)( offPal + ((src & 0x000000F0)>> 2));
if( (src & 0x00000F00)>> 6 ) *(pix+4) = *(unsigned long*)( offPal + ((src & 0x00000F00)>> 6));
if( (src & 0x0000F000)>>10 ) *(pix+5) = *(unsigned long*)( offPal + ((src & 0x0000F000)>>10));
if( (src & 0x000F0000)>>14 ) *(pix+2) = *(unsigned long*)( offPal + ((src & 0x000F0000)>>14));
if( (src & 0x00F00000)>>18 ) *(pix+3) = *(unsigned long*)( offPal + ((src & 0x00F00000)>>18));
if( (src & 0x0F000000)>>22 ) *(pix+0) = *(unsigned long*)( offPal + ((src & 0x0F000000)>>22));
if( (src & 0xF0000000)>>26 ) *(pix+1) = *(unsigned long*)( offPal + ((src & 0xF0000000)>>26));
}
else
{
if( (src & 0xF0000000)>>26 ) *(pix+6) = *(unsigned long*)( offPal + ((src & 0xF0000000)>>26));
if( (src & 0x0F000000)>>22 ) *(pix+7) = *(unsigned long*)( offPal + ((src & 0x0F000000)>>22));
if( (src & 0x00F00000)>>18 ) *(pix+4) = *(unsigned long*)( offPal + ((src & 0x00F00000)>>18));
if( (src & 0x000F0000)>>14 ) *(pix+5) = *(unsigned long*)( offPal + ((src & 0x000F0000)>>14));
if( (src & 0x0000F000)>>10 ) *(pix+2) = *(unsigned long*)( offPal + ((src & 0x0000F000)>>10));
if( (src & 0x00000F00)>> 6 ) *(pix+3) = *(unsigned long*)( offPal + ((src & 0x00000F00)>> 6));
if( (src & 0x000000F0)>> 2 ) *(pix+0) = *(unsigned long*)( offPal + ((src & 0x000000F0)>> 2));
if( (src & 0x0000000F)<< 2 ) *(pix+1) = *(unsigned long*)( offPal + ((src & 0x0000000F)<< 2));
}
}
}
static void DrawMDWindow( int scanline, int front )
{
int psx; // playfield size
int x,y,width,xStart;
int pl;
int totalWindow;
int add;
word *pix;
unsigned int tile;
byte *tileAddr;
y = scanline >> 3;
totalWindow = (y < (reg[0x12]&0x1f)) ^ (reg[0x12] >> 7);
psx = (reg[0xc] & 1) ? 64 : 32;
// Window
pl = (reg[0x3]<<10) + ((y&63)*psx*2);
if( reg[0xc] & 1 )
{
width=40; // wide mode (320 pixels across)
xStart=-8;
}
else
{
width=32; // narrow mode (256 pixels across)
xStart=24;
}
add = -2;
pix = dstPix + xStart;
for (x=-1;x<width;x++)
{
if (!totalWindow)
{
// Window
if (reg[0x11]&0x80)
{
if (x<((reg[0x11]&0x1f)<<1))
goto xskip;
}
else
{
if (x>=((reg[0x11]&0x1f)<<1))
goto xskip;
}
}
tileAddr = (byte*) vram + (pl+(add&((psx-1)<<1)));
tile = Get16( tileAddr );
if( (tile>>15) == front )
DrawMDTile(scanline&7, pix, tile);
xskip: add += 2;
pix += 8;
}
}
static int DrawMDSprites( int scanline, int front )
{
static unsigned char spriteOrder[0x101];
unsigned int spriteCount, tile, nextSprite = 0;
int tx, ty, x, y, xSize, ySize, which;
unsigned char *sprBase, *currentSpr;
word *pix;
sprBase = vram + (reg[0x05]<<9);
spriteCount=0;
spriteOrder[0]=0;
do
{
nextSprite = sprBase[ (nextSprite << 3) + 3 ];
spriteOrder[ ++spriteCount ] = nextSprite;
}
while( nextSprite && spriteCount<0x100 );
for( which = spriteCount-1; which>=0; which-- )
{
currentSpr = sprBase + (spriteOrder[which] << 3);
tile = Get16(currentSpr+4);
if ( (tile >> 15) == front )
{
y = Get16(currentSpr);
x = Get16(currentSpr+6) & 0x1FF;
if( reg[0xc] & 2 ) // interlace mode
{
y = (y & 0x3fe) >> 1;
}
else
{
y &= 0x1ff;
}
y-=0x80;
x-=0x80;
if( !(reg[0xc]&1) ) x += 32; // offset sprites in narrow mode
xSize = ((currentSpr[ 2 ]<<1) & 0x18) + x;
ySize = ((currentSpr[ 2 ]<<3) & 0x18) + y;
if( xSize > -8 && x < 320 && scanline >= y && scanline <= (ySize+7) )
{
switch( (tile & 0x1800) >> 11 )
{
case 0: // no flip
pix = dstPix + x;
for( tx=x; tx<=xSize; tx+=8 )
{
for( ty=y; ty<=ySize; ty+=8 )
{
if( (scanline >= ty) && (scanline <= (ty+7)) )
{
if( tx > -8 && tx < 320 )
{
DrawMDTile( scanline-ty, pix, tile );
}
}
tile++;
}
pix += 8;
}
break;
case 1: // flip x
pix = dstPix + xSize;
for( tx=xSize; tx>=x; tx-=8 )
{
for( ty=y; ty<=ySize; ty+=8 )
{
if( (scanline >= ty) && (scanline <= (ty+7)) )
{
if( tx > -8 && tx < 320 )
{
DrawMDTile( scanline-ty, pix, tile );
}
}
tile++;
}
pix -= 8;
}
break;
case 2: // flip y
pix = dstPix + x;
for( tx=x; tx<=xSize; tx+=8 )
{
for( ty=ySize; ty>=y; ty-=8 )
{
if( (scanline >= ty) && (scanline <= (ty+7)) )
{
if( tx > -8 && tx < 320 )
{
DrawMDTile( scanline-ty, pix, tile );
}
}
tile++;
}
pix += 8;
}
break;
default: // flip x and y
pix = dstPix + xSize;
for( tx=xSize; tx>=x; tx-=8 )
{
for( ty=ySize; ty>=y; ty-=8 )
{
if( (scanline >= ty) && (scanline <= (ty+7)) )
{
if( tx > -8 && tx < 320 )
{
DrawMDTile( scanline-ty, pix, tile );
}
}
tile++;
}
pix -= 8;
}
break;
}
}
}
}
return 0;
}
#define FRONT 0
#define PLANE 0
static void DrawMDPlaneBack0( int scanline )
#include "rasterpl.h"
#undef FRONT
#undef PLANE
#define FRONT 0
#define PLANE 1
static void DrawMDPlaneBack1( int scanline )
#include "rasterpl.h"
#undef FRONT
#undef PLANE
#define FRONT 1
#define PLANE 0
static void DrawMDPlaneFront0( int scanline )
#include "rasterpl.h"
#undef FRONT
#undef PLANE
#define FRONT 1
#define PLANE 1
static void DrawMDPlaneFront1( int scanline )
#include "rasterpl.h"
#undef FRONT
#undef PLANE
void DrawMDScanline( struct bmap *bits, struct dgen_sinfo *screen, int scanline,md *megaDrive)
{
unsigned int *pptr, count, color;
int layer_sel;
// Set up pointers
dstPix = (word*) (bits->data + 16 + (bits->pitch * (scanline+8)));
vram = screen->vram;
vsram = screen->vsram;
cram = screen->cram;
reg = screen->vdp_reg;
layer_sel=megaDrive->layer_sel;
// Calculate palette
if (megaDrive->vdp.dirt[0x34]&2)
{
// Dave: Slight modification here - only did 15-bit before
pptr = highpal;
for( count = 0; count<64; count++ )
{
int r,g,b;
b=(*cram&0x0e)<<4; cram++;
g=(*cram&0xe0);
r=(*cram&0x0e)<<4; cram++;
if (bits->bpp<=8) *pptr=count;
else if (bits->bpp<=15) *pptr=((r>>3)<<10) + ((g>>3)<<5) + (b>>3);
else if (bits->bpp<=16) *pptr=((r>>3)<<11) + ((g>>2)<<5) + (b>>3);
else if (bits->bpp<=32) *pptr=(r<<16) + (g<<8) + b;
pptr++;
}
megaDrive->vdp.dirt[0x34] &= ~2;
}
if(reg[1] & 0x40)
{
// Draw
if (layer_sel&1) DrawMDPlaneBack1( scanline ); // Plane 1, back
if (layer_sel&2) DrawMDPlaneBack0( scanline ); // Plane 0, back
if (layer_sel&4) DrawMDWindow ( scanline, false ); // Plane 2, back
if (layer_sel&8) DrawMDSprites ( scanline, false ); // Sprites, back
if (layer_sel&16) DrawMDPlaneFront1( scanline ); // Plane 1, front
if (layer_sel&32) DrawMDPlaneFront0( scanline ); // Plane 0, front
if (layer_sel&64) DrawMDWindow ( scanline, true ); // Plane 2, front
if (layer_sel&128) DrawMDSprites ( scanline, true ); // Sprites, front
}
else
{
// display off
memset(dstPix,0,bits->pitch);
}
// Clean up edges in narrow mode
if( !( reg[0xc] & 1 ) )
{
// the compiler generates crap for code unless you do this
// "explicit casting" stuff
unsigned long *dstLong = (unsigned long*)(dstPix);
color = highpal[ reg[0x7]&63 ];
color |= color << 16;
for( count=0; count<16; count++ )
{
*(dstLong + count ) =
*(dstLong + count + 144) = color;
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?