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;
}