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

📄 neogeo.c

📁 这个是延伸mame的在wince平台下的游戏模拟器的代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/***************************************************************************

  vidhrdw.c

  Functions to emulate the video hardware of the machine.

Important!  There are two types of NeoGeo romdump - MVS & MGD2.  They are both
converted to a standard format in the vh_start routines.


Graphics information:

0x00000 - 0xdfff	: Blocks of sprite data, each 0x80 bytes:
	Each 0x80 block is made up of 0x20 double words, their format is:
	Word: Sprite number (16 bits)
    Byte: Palette number (8 bits)
    Byte: Bit 0: X flip
          Bit 1: Y flip
          Bit 2: Automatic animation flag (4 tiles?)
          Bit 3: Automatic animation flag (8 tiles?)
          Bit 4: MSB of sprite number (confirmed, Karnov_r, Mslug). See note.
          Bit 5: MSB of sprite number (MSlug2)
          Bit 6: MSB of sprite number (Kof97)
          Bit 7: Unknown for now

    Each double word sprite is drawn directly underneath the previous one,
    based on the starting coordinates.

0x0e000 - 0x0ea00	: Front plane fix tiles (8*8), 2 bytes each

0x10000: Control for sprites banks, arranged in words

	Bit 0 to 3 - Y zoom LSB
    Bit 4 to 7 - Y zoom MSB (ie, 1 byte for Y zoom).
    Bit 8 to 11 - X zoom, 0xf is full size (no scale).
    Bit 12 to 15 - Unknown, probably unused

0x10400: Control for sprite banks, arranged in words

	Bit 0 to 5: Number of sprites in this bank (see note below).
	Bit 6 - If set, this bank is placed to right of previous bank (same Y-coord).
	Bit 7 to 15 - Y position for sprite bank.

0x10800: Control for sprite banks, arranged in words
	Bit 0 to 5: Unknown
	Bit 7 to 15 - X position for sprite bank.

Notes:

* If rom set has less than 0x10000 tiles then msb of tile must be ignored
(see Magician Lord).

***************************************************************************/

#include "driver.h"
#include "common.h"
/*#include "usrintrf.h"*/
#include "vidhrdw/generic.h"

/*#define NEO_DEBUG*/

/* The following two will save precomputed palette & graphics data to disk for fast
game startup - good for developers but uses lots of disk space! :) */

static unsigned char *vidram;
static unsigned char *neogeo_paletteram;       /* pointer to 1 of the 2 palette banks */
static unsigned char *pal_bank1;		/* 0x100*16 2 byte palette entries */
static unsigned char *pal_bank2;		/* 0x100*16 2 byte palette entries */
static int palno,modulo,where,high_tile,vhigh_tile,vvhigh_tile;
int no_of_tiles;
static int palette_swap_pending,fix_bank;

extern unsigned char *neogeo_ram;
extern unsigned int neogeo_frame_counter;
extern int neogeo_game_fix;
int neogeo_red_mask,neogeo_green_mask,neogeo_blue_mask;

void NeoMVSDrawGfx(unsigned char **line,const struct GfxElement *gfx,
		unsigned int code,unsigned int color,int flipx,int flipy,int sx,int sy,
        int zx,int zy);

static char dda_x_skip[16];
static char dda_y_skip[17];
static char full_y_skip[16]={0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};

#ifdef NEO_DEBUG
int neo_unknown[32];
void neo_unknown1(int offset, int data) {WRITE_WORD(&neo_unknown[0],data);}
void neo_unknown2(int offset, int data) {WRITE_WORD(&neo_unknown[2],data);}
void neo_unknown3(int offset, int data) {WRITE_WORD(&neo_unknown[4],data);}
void neo_unknown4(int offset, int data) {if (cpu_getpc()!=0x4a44) WRITE_WORD(&neo_unknown[6],data>>7);}

int dotiles = 0;
int screen_offs = 0x0000;

#endif

/******************************************************************************/

static void swap_palettes(void)
{
	int i,newword,red,green,blue;

    for (i=0; i<0x2000; i+=2) {
       	newword = READ_WORD(&neogeo_paletteram[i]);
    	red=   ((newword>>8)&neogeo_red_mask)*0x11;
		green= ((newword>>4)&neogeo_green_mask)*0x11;
		blue=  ((newword>>0)&neogeo_blue_mask)*0x11;

		palette_change_color(i / 2,red,green,blue);
    }

    palette_swap_pending=0;
}

void neogeo_setpalbank0(int offset,int data)
{
	if (palno != 0) {
		palno = 0;
		neogeo_paletteram = pal_bank1;
		palette_swap_pending=1;
	}
}

void neogeo_setpalbank1(int offset,int data)
{
	if (palno != 1) {
		palno = 1;
		neogeo_paletteram = pal_bank2;
		palette_swap_pending=1;
    }
}

int neogeo_paletteram_r(int offset)
{
	return READ_WORD(&neogeo_paletteram[offset]);
}

void neogeo_paletteram_w(int offset,int data)
{
	int oldword = READ_WORD (&neogeo_paletteram[offset]);
	int newword = COMBINE_WORD (oldword, data);
	int red=((newword>>8)&neogeo_red_mask);
	int green=((newword>>4)&neogeo_green_mask);
	int blue=((newword>>0)&neogeo_blue_mask);

	WRITE_WORD (&neogeo_paletteram[offset], newword);
	red			= red*0x11;
	green		= green*0x11;
	blue		= blue*0x11;

	palette_change_color(offset / 2,red,green,blue);
}

/******************************************************************************/

void neogeo_vh_stop(void)
{
   	if (pal_bank1) free (pal_bank1);
	if (pal_bank2) free (pal_bank2);
	if (vidram) free (vidram);
    if (neogeo_ram) free (neogeo_ram);

	pal_bank1=pal_bank2=vidram=neogeo_ram=0;
}

static int common_vh_start(void)
{
	pal_bank1=pal_bank2=vidram=0;

	pal_bank1 = malloc(0x2000);
	if (!pal_bank1) {
		neogeo_vh_stop();
		return 1;
	}

	pal_bank2 = malloc(0x2000);
	if (!pal_bank2) {
		neogeo_vh_stop();
		return 1;
	}

	vidram = malloc(0x20000); /* 0x20000 bytes even though only 0x10c00 is used */
	if (!vidram) {
		neogeo_vh_stop();
		return 1;
	}
	memset(vidram,0,0x20000);

	neogeo_paletteram = pal_bank1;
	palette_transparent_color = 4095;
    palno=0;
    modulo=1;
	where=0;
    fix_bank=0;
	palette_swap_pending=0;

	return 0;
}


/******************************************************************************/

static const unsigned char *neogeo_palette(void)
{
    int color,code,pal_base,y,my=0,x,count,offs,i;
 	int colmask[256];
    unsigned int *pen_usage; /* Save some struct derefs */

	int sx =0,sy =0,oy =0,zx = 1, rzy = 1;
    int tileno,tileatr,t1,t2,t3;
    char fullmode=0;
    int ddax=16,dday=256,rzx=15,yskip=0;

	memset(palette_used_colors,PALETTE_COLOR_UNUSED,4096);

	/* character foreground */
    pen_usage= Machine->gfx[fix_bank]->pen_usage;
	pal_base = Machine->drv->gfxdecodeinfo[fix_bank].color_codes_start;
	for (color = 0;color < 16;color++) colmask[color] = 0;
	for (offs=0xe000;offs<0xea00;offs+=2) {
    	code = READ_WORD( &vidram[offs] );
    	color = code >> 12;
        colmask[color] |= pen_usage[code&0xfff];
    }
	for (color = 0;color < 16;color++)
	{
		if (colmask[color] & (1 << 0))
			palette_used_colors[pal_base + 16 * color] = PALETTE_COLOR_TRANSPARENT;
		for (i = 1;i < 16;i++)
		{
			if (colmask[color] & (1 << i))
				palette_used_colors[pal_base + 16 * color + i] = PALETTE_COLOR_USED;
		}
	}

    /* Tiles */
    pen_usage= Machine->gfx[2]->pen_usage;
    pal_base = Machine->drv->gfxdecodeinfo[2].color_codes_start;
	for (color = 0;color < 256;color++) colmask[color] = 0;
    for (count=0;count<0x300;count+=2) {
		t3 = READ_WORD( &vidram[0x10000 + count] );
		t1 = READ_WORD( &vidram[0x10400 + count] );
		t2 = READ_WORD( &vidram[0x10800 + count] );

        /* If this bit is set this new column is placed next to last one */
		if (t1 & 0x40) {
			sx += rzx;
			if ( sx >= 0x1F0 )
				sx -= 0x200;

            /* Get new zoom for this column */
		    zx = (t3 >> 8) & 0x0f;
if(neogeo_game_fix==7 && (t3==0 || t3==0x147f))         
	zx=0xf;
			sy = oy;
		} else {	/* nope it is a new block */
        	/* Sprite scaling */
			zx = (t3 >> 8) & 0x0f;
			rzy = t3 & 0xff;
if(neogeo_game_fix==7 && (t3==0 || t3==0x147f))			
{
	zx=0xf;
	rzy=0xff;
}

			sx = (t2 >> 7);
			if ( sx >= 0x1F0 )
				sx -= 0x200;

            /* Number of tiles in this strip */
            my = t1 & 0x3f;
			if (my == 0x20) fullmode = 1;
			else if (my >= 0x21) fullmode = 2;	/* most games use 0x21, but */
												/* Alpha Mission II uses 0x3f */
			else fullmode = 0;

			sy = 0x1F0 - (t1 >> 7);
			if (sy > 0x100) sy -= 0x200;
			if (fullmode == 2 || (fullmode == 1 && rzy == 0xff))
			{
				while (sy < -16) sy += 2 * (rzy + 1);
			}
			oy = sy;

		  	if(my==0x21) my=0x20;
			else if(rzy!=0xff && my!=0)
				my=((my*16*256)/(rzy+1) + 15)/16;

            if(my>0x20) my=0x20;

            ddax=16;		/* setup x zoom */
		}

		/* No point doing anything if tile strip is 0 */
		if (my==0) continue;

		/* Process x zoom */
		if(zx!=15) {
			rzx=0;
			for(i=0;i<16;i++) {
				ddax-=zx+1;
				if(ddax<=0) {
					ddax+=15+1;
					rzx++;
				}
			}
		}
		else rzx=16;

		if(sx>311) continue;

		/* Setup y zoom */
		if(rzy==255)
			yskip=16;
		else
			dday=256;

		offs = count<<6;

        /* my holds the number of tiles in each vertical multisprite block */
        for (y=0; y < my ;y++) {
			tileno  = READ_WORD(&vidram[offs]);
            offs+=2;
			tileatr = READ_WORD(&vidram[offs]);
            offs+=2;

            if (high_tile && tileatr&0x10) tileno+=0x10000;
			if (vhigh_tile && tileatr&0x20) tileno+=0x20000;
			if (vvhigh_tile && tileatr&0x40) tileno+=0x40000;

            if (tileatr&0x8) tileno=(tileno&~7)+((tileno+neogeo_frame_counter)&7);
            else if (tileatr&0x4) tileno=(tileno&~3)+((tileno+neogeo_frame_counter)&3);

			if (fullmode == 2 || (fullmode == 1 && rzy == 0xff))
			{
				if (sy >= 224) sy -= 2 * (rzy + 1);
			}
			else if (fullmode == 1)
			{
				if (y == 0x10) sy -= 2 * (rzy + 1);
			}

            if(rzy!=255) {
            	yskip=0;
                for(i=0;i<16;i++) {
                    dday-=rzy+1;
                    if(dday<=0) {
                    	dday+=256;
                    	yskip++;
                    }
                }
            }

			if ( (tileatr>>8) != 0) 
			if (sy<224)                
			{
				tileatr=tileatr>>8;
		        colmask[tileatr] |= pen_usage[tileno];
			}

			sy +=yskip;

		}  /* for y */
	}  /* for count */

	for (color = 0;color < 256;color++)
	{
		if (colmask[color] & (1 << 0))
			palette_used_colors[pal_base + 16 * color] = PALETTE_COLOR_TRANSPARENT;
		for (i = 1;i < 16;i++)
		{
			if (colmask[color] & (1 << i))
				palette_used_colors[pal_base + 16 * color + i] = PALETTE_COLOR_USED;
		}
	}

	return palette_recalc();
}

/******************************************************************************/

void vidram_offset_w(int offset, int data)
{
	where = data*2;
}

int vidram_data_r(int offset)
{
	return (READ_WORD(&vidram[where & 0x1ffff]));
}

void vidram_data_w(int offset,int data)
{
	WRITE_WORD(&vidram[where & 0x1ffff],data);
	where += modulo;
}

/* Modulo can become negative , Puzzle Bobble Super Sidekicks and a lot */
/* of other games use this */
void vidram_modulo_w(int offset, int data) {
	if (data & 0x8000) {
		/* Sign extend it. */
		/* Where is the SEX instruction when you need it :-) */
		modulo = (data - 0x10000) << 1;
	}
	else
		modulo = data << 1;
}

int vidram_modulo_r(int offset) {
	return modulo >> 1;
}


/* Two routines to enable videoram to be read in debugger */
int mish_vid_r(int offset)
{
	return READ_WORD(&vidram[offset]);
}

void mish_vid_w(int offset, int data)
{
	COMBINE_WORD_MEM(&vidram[offset],data);
}

void neo_board_fix(int offset, int data)
{
	fix_bank=1;
}

void neo_game_fix(int offset, int data)
{
	fix_bank=0;
}

/******************************************************************************/

/* DWORD read - copied from common.c */

#ifdef ACORN /* GSL 980108 read/write nonaligned dword routine for ARM processor etc */

INLINE int read_dword(int *address)
{
	if ((int)address & 3)
	{
#ifdef LSB_FIRST  /* little endian version */
  		return (    *((unsigned char *)address) +
  			   (*((unsigned char *)address+1) << 8)  +
  		   	   (*((unsigned char *)address+2) << 16) +
  		           (*((unsigned char *)address+3) << 24) );
#else             /* big endian version */
  		return (    *((unsigned char *)address+3) +
  			   (*((unsigned char *)address+2) << 8)  +
  		   	   (*((unsigned char *)address+1) << 16) +
  		           (*((unsigned char *)address)   << 24) );
#endif
	}
	else
		return *(int *)address;
}

#else
#define read_dword(address) *(int *)address
#endif

#ifdef LSB_FIRST
#define BL0 0
#define BL1 1
#define BL2 2
#define BL3 3
#define WL0 0
#define WL1 1
#else
#define BL0 3
#define BL1 2
#define BL2 1
#define BL3 0
#define WL0 1
#define WL1 0
#endif

void NeoMVSDrawGfx(unsigned char **line,const struct GfxElement *gfx, /* AJP */
		unsigned int code,unsigned int color,int flipx,int flipy,int sx,int sy,
        int zx,int zy)
{
	int /*ox,*/oy,ex,ey,y,start,dy;
	unsigned char *bm;
	int col;
    int l; /* Line skipping counter */

    int mydword;

	unsigned char *fspr=0;

	unsigned char *PL1 = Machine->memory_region[2];
    unsigned char *PL2 = Machine->memory_region[3];

	char *l_y_skip;

    /* Safety feature */
    code=code%no_of_tiles;

    /* Check for total transparency, no need to draw */
    if ((gfx->pen_usage[code] & ~1) == 0)
    	return;

   	if(zy==16)
		 l_y_skip=full_y_skip;
	else
		 l_y_skip=dda_y_skip;


	if(code < no_of_tiles/2)
	{
		fspr=PL1;
	}
	else
	{
		fspr=PL2;
		code-=no_of_tiles/2;
	}

	/* Mish/AJP - Most clipping is done in main loop */
    oy=sy;
  	ey = sy + zy -1; 	/* Clip for size of zoomed object */

	if (sx <= -8) return;
	if (sy < 0) sy = 0;
    if (ey >= 224) ey = 224-1;

	if (flipy)	/* Y flip */
	{
		dy = -8;

⌨️ 快捷键说明

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