www.pudn.com > ncdzsrc.rar > memintrf.c


/*************************************************************************** 
 
	memintrf.c 
 
	メモリインターフェース及びM68000用メモリアクセス関数 
 
***************************************************************************/ 
 
#include "neogeocd.h" 
#include "zlib/zlib.h" 
 
#ifdef LOG 
#undef LOG 
#endif 
 
#define VERBOSE OUTPUT_MEMORY_LOG 
#if VERBOSE 
#define LOG(x) logerror x 
#else 
#define LOG(x) 
#endif 
 
 
#define MEM_AMASK 0x00ffffff 
 
/**************************************************************************** 
	プロトタイプ 
 ***************************************************************************/ 
 
// 内部用メモリリード 
static int m68k_readmem8(offs_t offset, UINT8 *data); 
static int m68k_readmem16(offs_t offset, UINT16 *data); 
static int m68k_readmem32(offs_t offset, UINT32 *data); 
 
// 内部用メモリライト 
static int m68k_writemem8(offs_t offset, UINT8 data); 
static int m68k_writemem16(offs_t offset, UINT16 data); 
static int m68k_writemem32(offs_t offset, UINT32 data); 
 
// M68K RAMリードライト 
static UINT8 MRA8_RAM(offs_t offset); 
static UINT16 MRA16_RAM(offs_t offset); 
static UINT32 MRA32_RAM(offs_t offset); 
static void MWA8_RAM(offs_t offset, UINT8 data); 
static void MWA16_RAM(offs_t offset, UINT16 data); 
static void MWA32_RAM(offs_t offset, UINT32 data); 
 
// M68K ROMリードライト 
static UINT8 MRA8_ROM(offs_t offset); 
static UINT16 MRA16_ROM(offs_t offset); 
static UINT32 MRA32_ROM(offs_t offset); 
 
// M68K リードライトアドレスエラー 
static UINT8 MRA8_BAD(offs_t offset); 
static UINT16 MRA16_BAD(offs_t offset); 
static UINT32 MRA32_BAD(offs_t offset); 
static void MWA8_BAD(offs_t offset, UINT8 data); 
static void MWA16_BAD(offs_t offset, UINT16 data); 
static void MWA32_BAD(offs_t offset, UINT32 data); 
 
 
/**************************************************************************** 
	グローバル変数 
 ***************************************************************************/ 
 
UINT8 *m68k_rambase; 
UINT8 *m68k_rombase; 
UINT8 *opcode_base; 
UINT8 *opcode_entry; 
 
 
/**************************************************************************** 
	ローカル変数 
 ***************************************************************************/ 
 
static MEMREGION *memory_region_map; 
static READMEM read_map[0x100]; 
static WRITEMEM write_map[0x100]; 
 
#include "binary/sysfont.c" 
 
 
/*************************************************************************** 
	グローバル関数 (メモリインタフェース関数) 
 ***************************************************************************/ 
 
/*------------------------------------------------------ 
 
	指定された番号のメモリ領域のポインタを取得 
 
	引  数: int type   メモリ領域番号 
	戻り値: メモリ領域のポインタ 
 
 -----------------------------------------------------*/ 
 
UINT8 *memory_region(int type) 
{ 
	int i; 
 
	for (i = 0; i < REGION_MAX; i++) 
	{ 
		if (memory_region_map[i].type == type) 
			return memory_region_map[i].base; 
	} 
	return NULL; 
} 
 
 
/*------------------------------------------------------ 
 
	指定された番号のメモリ領域のサイズ取得 
 
	引  数: int type   メモリ領域番号 
	戻り値: メモリ領域のサイズ 
 
 -----------------------------------------------------*/ 
 
size_t memory_region_length(int type) 
{ 
	int i; 
 
	for (i = 0; i < REGION_MAX; i++) 
	{ 
		if (memory_region_map[i].type == type) 
			return memory_region_map[i].length; 
	} 
	return 0; 
} 
 
 
/*------------------------------------------------------ 
 
	メモリ領域の確保 
 
	引  数: なし 
	戻り値: 1:成功 0:失敗 
 
 -----------------------------------------------------*/ 
 
static int allocate_memory_regions(void) 
{ 
	int i; 
 
	for (i = 0; i < REGION_MAX; i++) 
	{ 
		if (memory_region_map[i].base == NULL) 
		{ 
			memory_region_map[i].base = malloc(memory_region_map[i].length); 
			if (memory_region_map[i].base == NULL) 
				return 0; 
 
			memset(memory_region_map[i].base, 0, memory_region_map[i].length); 
		} 
	} 
	return 1; 
} 
 
 
/*------------------------------------------------------ 
 
	メモリ領域の開放 
 
	引  数: なし 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void free_memory_regions(void) 
{ 
	int i; 
 
	for (i = 0; i < REGION_MAX; i++) 
	{ 
		if (memory_region_map[i].base) 
		{ 
			free(memory_region_map[i].base); 
			memory_region_map[i].base = NULL; 
		} 
	} 
} 
 
 
/*------------------------------------------------------ 
 
	メモリインターフェースの初期化 
 
	引  数: なし 
	戻り値: 1:成功 0:失敗 
 
  ※同時にROMファイルとUI用のフォントも取り込みます 
 
 -----------------------------------------------------*/ 
 
int memory_init(void) 
{ 
	FILE *fp; 
	UINT8 *mem; 
	UINT32 crc, length; 
	int i; 
 
	// メモリ領域マップを設定 
	memory_region_map = neogeo_memory_region; 
 
	// メモリを確保 
	if (allocate_memory_regions() == 0) 
		return 0; 
 
	m68k_rambase = memory_region(REGION_CPU1); 
	m68k_rombase = memory_region(REGION_USER1); 
 
	// メモリマップを初期化 
	initialize_memmap(); 
 
	// NEOGEO CDZ BIOSの読み込み 
	fp = fopen("neocd.bin", "rb"); 
	if (fp) 
	{ 
		mem = memory_region(REGION_USER1); 
 
		fseek(fp, 0, SEEK_END); 
		length = ftell(fp); 
		fseek(fp, 0, SEEK_SET); 
 
		fread(mem, 1, length, fp); 
		fclose(fp); 
 
		crc = crc32(0L, mem, length); 
		switch (crc) 
		{ 
		case 0xdf9de490: 
			break; 
 
		case 0x33697892: 
			swab(mem, mem, 0x80000); 
			break; 
 
		default: 
			osd_show_message("Invalid neocd.bin (CRC %08X) found.", crc); 
			return 0; 
		} 
 
		logerror("neocd.bin found. (CRC %08x)\n", crc); 
	} 
	else 
	{ 
		osd_show_message("neocd.bin not found."); 
		return 0; 
	} 
 
	// ラインオフセットROMの読み込み 
	for (i= 0; i < 2; i++) 
	{ 
		const char *lo_rom[2] = { "000-lo.lo", "ng-lo.rom" }; 
 
		fp = fopen(lo_rom[i], "rb"); 
		if (fp) 
		{ 
			mem = memory_region(REGION_GFX3); 
 
			fread(mem, 1, 0x10000, fp); 
			fclose(fp); 
 
			crc = crc32(0L, mem, 0x10000); 
			if (crc != 0xe09e253c) 
			{ 
				osd_show_message("Invalid %s (CRC %08X) found.", lo_rom[i], crc); 
				return 0; 
			} 
 
			memcpy(mem + 0x10000, mem, 0x10000); 
 
			logerror("%s found. (CRC %08x)\n", lo_rom[i], crc); 
			break; 
		} 
		else if (i == 1) 
		{ 
			osd_show_message("000-lo.lo (ng-lo.rom) not found."); 
			return 0; 
		} 
	} 
 
	// システムフォント読み込み 
	mem = memory_region(REGION_GFX4); 
	memcpy(mem, sysfont, 0x2000); 
	neogeo_decode_fix(mem, 0, 0x2000); 
 
	return 1; 
} 
 
 
/*------------------------------------------------------ 
 
	メモリインターフェースの終了 
 
	引  数: なし 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void memory_shutdown(void) 
{ 
	free_memory_regions(); 
} 
 
 
/*************************************************************************** 
	グローバル関数 (M68000メモリアクセス関数) 
 ***************************************************************************/ 
 
/*------------------------------------------------------ 
 
	メモリマップの初期化 
 
	引  数: なし 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void initialize_memmap(void) 
{ 
	int i; 
	offs_t start, end; 
	READMEM *read; 
	WRITEMEM *write; 
 
 
	for (i = 0; i <= 0xff; i++) 
	{ 
		start = (i << 16); 
		end   = ((i + 1) << 16) - 1; 
 
		read_map[i].type  = MEM_BAD; 
		read_map[i].start = start; 
		read_map[i].end   = end; 
		read_map[i].func  = NULL; 
 
		write_map[i].type  = MEM_BAD; 
		write_map[i].start = start; 
		write_map[i].end   = end; 
		write_map[i].func  = NULL; 
	} 
 
	read  = neogeo_readmem; 
 
	while (read->type != MEM_END) 
	{ 
		start = (read->start >> 16) & 0xff; 
		end   = (read->end   >> 16) & 0xff; 
 
		for (i = start; i <= end; i++) 
		{ 
			read_map[i].type  = read->type; 
			read_map[i].func  = read->func; 
			if (i == end) 
				read_map[i].end = read->end; 
		} 
		read++; 
	} 
 
	write = neogeo_writemem; 
 
	while (write->type != MEM_END) 
	{ 
		start = (write->start >> 16) & 0xff; 
		end   = (write->end   >> 16) & 0xff; 
 
		for (i = start; i <= end; i++) 
		{ 
			write_map[i].type  = write->type; 
			write_map[i].func  = write->func; 
			if (i == end) 
				write_map[i].end = write->end; 
		} 
		write++; 
	} 
} 
 
 
/*------------------------------------------------------ 
 
	M68000 8bitデータリード 
 
	引  数: offs_t offset   オフセット 
	戻り値: データ(byte) 
 
 -----------------------------------------------------*/ 
 
UINT8 m68000_read_memory_8(offs_t offset) 
{ 
	UINT8 data; 
 
	offset &= MEM_AMASK; 
 
	if (m68k_readmem8(offset, &data)) 
		return data; 
	else 
		return MRA8_BAD(offset); 
} 
 
 
/*------------------------------------------------------ 
 
	M68000 16bitデータリード 
 
	引  数: offs_t offset   オフセット 
	戻り値: データ(word) 
 
 -----------------------------------------------------*/ 
 
UINT16 m68000_read_memory_16(offs_t offset) 
{ 
	UINT16 data; 
 
	offset &= MEM_AMASK; 
 
	if (m68k_readmem16(offset, &data)) 
		return data; 
	else 
		return MRA16_BAD(offset); 
} 
 
 
/*------------------------------------------------------ 
 
	M68000 32bitデータリード 
 
	引  数: offs_t offset   オフセット 
	戻り値: データ(double word) 
 
 -----------------------------------------------------*/ 
 
UINT32 m68000_read_memory_32(offs_t offset) 
{ 
	UINT32 data; 
 
	offset &= MEM_AMASK; 
 
	if (m68k_readmem32(offset, &data)) 
		return data; 
	else 
		return MRA32_BAD(offset); 
} 
 
 
/*------------------------------------------------------ 
 
	M68000 8bitデータライト 
 
	引  数: offs_t offset   オフセット 
			UINT8 data		データ(byte) 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void m68000_write_memory_8(offs_t offset, UINT8 data) 
{ 
	offset &= MEM_AMASK; 
 
	if (m68k_writemem8(offset, data) == 0) 
		MWA8_BAD(offset, data); 
} 
 
 
/*------------------------------------------------------ 
 
	M68000 16bitデータライト 
 
	引  数: offs_t offset   オフセット 
			UINT16 data		データ(word) 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void m68000_write_memory_16(offs_t offset, UINT16 data) 
{ 
	offset &= MEM_AMASK; 
 
	if (m68k_writemem16(offset, data) == 0) 
		MWA16_BAD(offset, data); 
} 
 
 
/*------------------------------------------------------ 
 
	M68000 32bitデータライト 
 
	引  数: offs_t offset   オフセット 
			UINT32 data		データ(double word) 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void m68000_write_memory_32(offs_t offset, UINT32 data) 
{ 
	offset &= MEM_AMASK; 
 
	if (m68k_writemem32(offset, data) == 0) 
		MWA32_BAD(offset, data); 
} 
 
 
/*------------------------------------------------------ 
 
	M68000 OPコード実行ベースオフセット変更 
 
	引  数: offs_t offset   オフセット 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void m68000_setopbase(offs_t offset) 
{ 
	offset &= MEM_AMASK; 
 
	if (offset >= 0xc00000) 
		opcode_base = m68k_rombase - 0xc00000; 
	else 
		opcode_base = m68k_rambase; 
} 
 
 
/*------------------------------------------------------ 
 
	M68000 デバッグ用メモリリード 
 
	引  数: int offset  オフセット 
	戻り値: データ 
 
 -----------------------------------------------------*/ 
 
int m68000_read_memory_8_debug(int offset) 
{ 
	return m68000_read_memory_8(offset); 
} 
 
int m68000_read_memory_16_debug(int offset) 
{ 
	return m68000_read_memory_16(offset); 
} 
 
int m68000_read_memory_32_debug(int offset) 
{ 
	return m68000_read_memory_32(offset); 
} 
 
 
/*************************************************************************** 
	ローカル関数 (M68000メモリアクセス関数) 
 ***************************************************************************/ 
 
/*------------------------------------------------------ 
 
	M68000 RAMリードライト 
 
	引  数: 
	戻り値: 
 
 -----------------------------------------------------*/ 
 
static UINT8 MRA8_RAM(offs_t offset) 
{ 
	return m68k_rambase[offset ^ 1]; 
} 
 
static UINT16 MRA16_RAM(offs_t offset) 
{ 
	return *(UINT16 *)(m68k_rambase + offset); 
} 
 
static UINT32 MRA32_RAM(offs_t offset) 
{ 
	UINT32 data; 
 
	data = *(UINT32 *)(m68k_rambase + offset); 
	return (data << 16) | (data >> 16); 
} 
 
static void MWA8_RAM(offs_t offset, UINT8 data) 
{ 
	m68k_rambase[offset ^ 1] = data; 
} 
 
static void MWA16_RAM(offs_t offset, UINT16 data) 
{ 
	*(UINT16 *)(m68k_rambase + offset) = data; 
} 
 
static void MWA32_RAM(offs_t offset, UINT32 data) 
{ 
	*(UINT32 *)(m68k_rambase + offset) = (data << 16) | (data >> 16); 
} 
 
 
/*------------------------------------------------------ 
 
	M68000 ROMリード 
 
	引  数: 
	戻り値: 
 
 -----------------------------------------------------*/ 
 
static UINT8 MRA8_ROM(offs_t offset) 
{ 
	return m68k_rombase[(offset ^ 1) & 0x7ffff]; 
} 
 
static UINT16 MRA16_ROM(offs_t offset) 
{ 
	return *(UINT16 *)(m68k_rombase + (offset & 0x7ffff)); 
} 
 
static UINT32 MRA32_ROM(offs_t offset) 
{ 
	UINT32 data; 
 
	data = *(UINT32 *)(m68k_rombase + (offset & 0x7ffff)); 
	return (data << 16) | (data >> 16); 
} 
 
 
/*------------------------------------------------------ 
 
	M68000 メモリリードライト範囲エラー 
 
	引  数: 
	戻り値: 
 
 -----------------------------------------------------*/ 
 
static UINT8 MRA8_BAD(offs_t offset) 
{ 
	LOG(("Read byte from unmapped address %06x\n", offset)); 
	return 0xff; 
} 
 
static UINT16 MRA16_BAD(offs_t offset) 
{ 
	LOG(("Read word from unmapped address %06x\n", offset)); 
	return 0xffff; 
} 
 
static UINT32 MRA32_BAD(offs_t offset) 
{ 
	LOG(("Read dword from unmapped address %06x\n", offset)); 
	return 0xffffff; 
} 
 
static void MWA8_BAD(offs_t offset, UINT8 data) 
{ 
	LOG(("Write byte (%02x) to unmapped address %06x\n", data, offset)); 
} 
 
static void MWA16_BAD(offs_t offset, UINT16 data) 
{ 
	LOG(("Write word (%04x) to unmapped address %06x\n", data, offset)); 
} 
 
static void MWA32_BAD(offs_t offset, UINT32 data) 
{ 
	LOG(("Write dword (%08x) to unmapped address %06x\n", data, offset)); 
} 
 
 
/*------------------------------------------------------ 
 
	M68000 8bitデータリードコア 
 
	引  数: offs_t offset   オフセット 
			UINT8 *data     データを格納するポインタ 
	戻り値: 読み込み成功:1 読み込み失敗:0 
 
 -----------------------------------------------------*/ 
 
static int m68k_readmem8(offs_t offset, UINT8 *data) 
{ 
	READMEM *read = &read_map[offset >> 16]; 
	int shift; 
 
	*data = 0xff; 
 
	if (offset >= read->start && offset <= read->end) 
	{ 
		switch (read->type) 
		{ 
		case MEM_ROM: *data = MRA8_ROM(offset); return 1; 
		case MEM_RAM: *data = MRA8_RAM(offset); return 1; 
		case MEM_NOP: return 1; 
		case MEM_MAP: 
			shift = 8 * (~offset & 1); 
			*data = (read->func)(offset >> 1, ~(0xff << shift)) >> shift; 
			return 1; 
		} 
	} 
 
	return 0; 
} 
 
 
/*------------------------------------------------------ 
 
	M68000 16bitデータリードコア 
 
	引  数: offs_t offset   オフセット 
			UINT16 *data    データを格納するポインタ 
	戻り値: 読み込み成功:1 読み込み失敗:0 
 
 -----------------------------------------------------*/ 
 
static int m68k_readmem16(offs_t offset, UINT16 *data) 
{ 
	READMEM *read = &read_map[offset >> 16]; 
 
	*data = 0xffff; 
 
	if (offset >= read->start && offset <= read->end) 
	{ 
		switch (read->type) 
		{ 
		case MEM_ROM: *data = MRA16_ROM(offset); return 1; 
		case MEM_RAM: *data = MRA16_RAM(offset); return 1; 
		case MEM_NOP: return 1; 
		case MEM_MAP: *data = (read->func)(offset >> 1, 0); return 1; 
		} 
	} 
 
	return 0; 
} 
 
 
/*------------------------------------------------------ 
 
	M68000 32bitデータリードコア 
 
	引  数: offs_t offset   オフセット 
			UINT32 *data    データを格納するポインタ 
	戻り値: 読み込み成功:1 読み込み失敗:0 
 
 -----------------------------------------------------*/ 
 
static int m68k_readmem32(offs_t offset, UINT32 *data) 
{ 
	READMEM *read = &read_map[offset >> 16]; 
 
	*data = 0xffffffff; 
 
	if (offset >= read->start && offset <= read->end) 
	{ 
		switch (read->type) 
		{ 
		case MEM_ROM: *data = MRA32_ROM(offset); return 1; 
		case MEM_RAM: *data = MRA32_RAM(offset); return 1; 
		case MEM_NOP: return 1; 
		case MEM_MAP: 
			offset >>= 1; 
			*data = ((read->func)(offset, 0) << 16) | (read->func)(offset + 1, 0); 
			return 1; 
		} 
	} 
 
	return 0; 
} 
 
 
/*------------------------------------------------------ 
 
	M68000 8bitデータライトコア 
 
	引  数: offs_t offset   オフセット 
			UINT8 data      データ 
	戻り値: 書き込み成功:1 書き込み失敗:0 
 
 -----------------------------------------------------*/ 
 
static int m68k_writemem8(offs_t offset, UINT8 data) 
{ 
	WRITEMEM *write = &write_map[offset >> 16]; 
	int shift; 
 
	if (offset >= write->start && offset <= write->end) 
	{ 
		switch (write->type) 
		{ 
		case MEM_RAM: MWA8_RAM(offset, data); return 1; 
		case MEM_NOP: return 1; 
		case MEM_MAP: 
			shift = 8 * (~offset & 1); 
			(write->func)(offset >> 1, (data << shift), ~(0xff << shift)); 
			return 1; 
		} 
	} 
 
	return 0; 
} 
 
 
/*------------------------------------------------------ 
 
	M68000 16bitデータライトコア 
 
	引  数: offs_t offset   オフセット 
			UINT16 data     データ 
	戻り値: 書き込み成功:1 書き込み失敗:0 
 
 -----------------------------------------------------*/ 
 
static int m68k_writemem16(offs_t offset, UINT16 data) 
{ 
	WRITEMEM *write = &write_map[offset >> 16]; 
 
	if (offset >= write->start && offset <= write->end) 
	{ 
		switch (write->type) 
		{ 
		case MEM_RAM: MWA16_RAM(offset, data); return 1; 
		case MEM_NOP: return 1; 
		case MEM_MAP: 
			(write->func)(offset >> 1, data, 0); 
			return 1; 
		} 
	} 
 
	return 0; 
} 
 
 
/*------------------------------------------------------ 
 
	M68000 32bitデータライトコア 
 
	引  数: offs_t offset   オフセット 
			UINT32 data     データ 
	戻り値: 書き込み成功:1 書き込み失敗:0 
 
 -----------------------------------------------------*/ 
 
static int m68k_writemem32(offs_t offset, UINT32 data) 
{ 
	WRITEMEM *write = &write_map[offset >> 16]; 
 
	if (offset >= write->start && offset <= write->end) 
	{ 
		switch (write->type) 
		{ 
		case MEM_RAM: MWA32_RAM(offset, data); return 1; 
		case MEM_NOP: return 1; 
		case MEM_MAP: 
			offset >>= 1; 
			(write->func)(offset, data >> 16, 0); 
			(write->func)(offset + 1, data & 0xffff, 0); 
			return 1; 
		} 
	} 
 
	return 0; 
}