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 + -
显示快捷键?