www.pudn.com > ncdzsrc.rar > machine.c
/***************************************************************************
machine.c
NEOGEO CD マシンエミュレーションコア
***************************************************************************/
#include "neogeocd.h"
#define VERBOSE 0
#if VERBOSE
#define LOG(x) logerror x
#else
#define LOG(x)
#endif
/****************************************************************************
プロトタイプ
***************************************************************************/
static void neogeo_run_game(void);
static void neogeo_run_bios(void);
/****************************************************************************
グローバル変数
***************************************************************************/
int game_index;
char game_name[16];
int driver_type;
int driver_flag;
/****************************************************************************
ローカル変数
***************************************************************************/
// 外部メモリの転送情報
static UINT8 exmem[0x100];
static UINT8 exmem_latch[0x100];
static UINT8 exmem_bank[4];
static UINT8 exmem_counter;
// ハードウェア転送情報
static UINT8 upload_mode;
static UINT8 upload_type;
static UINT32 upload_offset1;
static UINT32 upload_offset2;
static UINT32 upload_length;
static UINT16 upload_pattern;
static int upload_executing;
#if 1
static offs_t z80_cdda_offset;
#endif
static UINT8 neogeo_game_vectors[0x100];
#if ENABLE_SYSTEM_CHECK
static int system_check = 1;
#endif
#include "binary/startup.c" // startup.bin
/***************************************************************************
グローバル関数
***************************************************************************/
/*------------------------------------------------------
NEOGEO CDのエミュレーションを実行
引 数: なし
戻り値: なし
-----------------------------------------------------*/
void neogeo_run(void)
{
FILE *fp;
UINT16 *mem16;
time_t ltime;
struct tm *today;
int region = options.region & 0x03;
// CPUのメモリ初期化
memset(memory_region(REGION_CPU1), 0, memory_region_length(REGION_CPU1));
memset(memory_region(REGION_CPU2), 0, memory_region_length(REGION_CPU2));
memset(memory_region(REGION_USER3), 0, memory_region_length(REGION_USER3));
// 起動時のメモリ状態データ書き込み
swab(startup_bin, memory_region(REGION_CPU1) + 0x10f300, 0x0d00);
// 外部メモリの転送情報をクリア
memset(exmem, 0xff, 0x100);
memset(exmem_latch, 0xff, 0x100);
memset(exmem_bank, 0, 4);
exmem_counter = 0;
// ハードウェア転送情報をクリア
upload_mode = UPLOAD_IMMIDIATE;
upload_type = UNKNOWN_TYPE;
upload_offset1 = 0;
upload_offset2 = 0;
upload_length = 0;
upload_pattern = 0;
upload_executing = 0;
#if 1
z80_cdda_offset = 0;
#endif
// BIOSにパッチを当てて動作をフックする
mem16 = (UINT16 *)memory_region(REGION_USER1);
// ファイル読み込み
mem16[0xdb70 >> 1] = 0xfac0;
mem16[0xdb72 >> 1] = 0x4e75;
// 入力受付フラグのクリアを無効に
mem16[0xb040 >> 1] = 0x4e71;
mem16[0xb042 >> 1] = 0x4e71;
// CDDAチェック
mem16[0x056a >> 1] = 0xfac1;
mem16[0x056c >> 1] = 0x4e75;
// リセット
mem16[0xa87a >> 1] = 0x4239;
mem16[0xa87c >> 1] = 0x0010;
mem16[0xa87e >> 1] = 0xfdae;
#if ENABLE_SYSTEM_CHECK
// システムチェック
mem16[0xab5e >> 1] = 0x4e71;
mem16[0xab60 >> 1] = 0x4e71;
m68000_write_memory_8(0x108000 + 0x73d8, 0x05);
#endif
// カレンダ設定 (設定しても意味なし)
time(<ime);
today = localtime(<ime);
pd4990a.seconds = ((today->tm_sec/10)<<4) + (today->tm_sec%10);
pd4990a.minutes = ((today->tm_min/10)<<4) + (today->tm_min%10);
pd4990a.hours = ((today->tm_hour/10)<<4) + (today->tm_hour%10);
pd4990a.days = ((today->tm_mday/10)<<4) + (today->tm_mday%10);
pd4990a.month = (today->tm_mon + 1);
pd4990a.year = (((today->tm_year%100)/10)<<4) + (today->tm_year%10);
pd4990a.weekday = today->tm_wday;
// 言語設定を初期化
m68000_write_memory_16(0xff011c, ~(region << 8));
// VRAMクリア
neogeo_clear_vram();
// バックアップメモリ読み込み
fp = fopen("backup.bin", "rb");
if (fp != NULL)
{
fread(memory_region(REGION_USER2), 1, 0x2000, fp);
fclose(fp);
logerror("Backup memory loaded.\n");
}
if (game_index >= 0)
{
// ゲームを起動
neogeo_run_game();
}
if (game_index < 0)
{
// BIOS起動かゲームの実行失敗
neogeo_run_bios();
}
// バックアップメモリ書き込み
fp = fopen("backup.bin", "wb");
if (fp != NULL)
{
fwrite(memory_region(REGION_USER2), 1, 0x2000, fp);
fclose(fp);
logerror("Backup memory saved.\n");
}
}
/*------------------------------------------------------
NEOGEO CDのゲームを起動
引 数: なし
戻り値: なし
-----------------------------------------------------*/
static void neogeo_run_game(void)
{
int result;
UINT16 *mem16 = (UINT16 *)memory_region(REGION_CPU1);
// ゲーム番号が0以上のときはゲーム起動
strcpy(game_name, games[game_index].name);
driver_type = games[game_index].driver;
driver_flag = games[game_index].flag;
options.raster = (driver_type > 1) ? 1 : 0;
// 初期値設定
m68000_write_memory_32(0x120002, 0xffffffff);
m68000_write_memory_32(0x11c808, 0xc0c760); // 初期化
m68000_write_memory_32(0x11c80c, 0xc0c814); // プログレスバー
m68000_write_memory_32(0x11c810, 0xc190e2); // アニメデータ
// IPL.TXTを処理
if ((result = cdrom_process_ipl()) == 1)
{
options_type save_options;
// デフォルトの設定保存
memcpy(&save_options, &options, sizeof(options_type));
// 個別設定読み込み
load_game_config();
// 入力デバイスの個別設定を反映
input_reset();
// ベクタテーブル保存
memcpy(neogeo_game_vectors, memory_region(REGION_CPU1), 0x100);
if (driver_flag & PATCH_SSRPG)
{
// 真説サムライスピリッツ専用
// EXT_SYS.PRGにパッチを当てる
// 標準のファイル読み込みルーチンに変更
mem16[0x132020 >> 1] = 0x4ef9;
mem16[0x132022 >> 1] = 0x00c0;
mem16[0x132024 >> 1] = 0xdb60;
mem16[0x132026 >> 1] = 0x4ef9;
mem16[0x132028 >> 1] = 0x00c0;
mem16[0x13202a >> 1] = 0xdb6a;
}
// CDDAを初期化
neogeo_cdda_init();
//------------- ゲーム起動 -----------------
cpu_run();
//------------- ゲーム終了 -----------------
// CDDAを終了
neogeo_cdda_exit();
// 個別設定保存
save_game_config();
// デフォルトの設定に戻す
memcpy(&options.key, &save_options.key, sizeof(options.key));
memcpy(&options.joyid, &save_options.joyid, sizeof(options.joyid));
memcpy(&options.joy, &save_options.joy, sizeof(options.joy));
memcpy(&options.hotkey, &save_options.hotkey, sizeof(options.hotkey));
// 入力デバイスのデフォルトの設定を反映
input_reset();
}
else
{
// 失敗したらBIOSを起動
if (result == 0)
{
// 中断でない時はメッセージ表示
osd_show_message("ERROR: could not to process IPL.TXT.");
}
game_index = -1;
cdrom_current_drive = -1;
}
}
/*------------------------------------------------------
NEOGEO CDのBIOSを起動
引 数: なし
戻り値: なし
※ BIOS起動時はCDDAを初期化しません
-----------------------------------------------------*/
static void neogeo_run_bios(void)
{
// BIOSシミュレーションを再初期化
bios_init();
neogeo_set_title();
// ドライバ設定初期化
strcpy(game_name, "neogeocd");
driver_type = NEOGEO;
driver_flag = 0;
// ベクタテーブル保存 (テストモード用)
memcpy(neogeo_game_vectors, memory_region(REGION_USER1), 0x100);
//------------- BIOS起動 -----------------
cpu_run();
//------------- BIOS終了 -----------------
// 念の為CDDAを終了
osd_cdda_exit();
}
/*------------------------------------------------------
NEOGEO CDのハードウェアをリセット
引 数: なし
戻り値: なし
-----------------------------------------------------*/
void neogeo_reset(void)
{
if (cdrom_loading_state == CDROM_LOADING)
{
// ロード中の場合は強制停止
cdrom_abort_loading();
cdrom_loading_state = CDROM_IDLE;
}
// ゲーム起動中の場合
if (game_index >= 0)
{
if (cpu_reset_flag == 0)
{
m68000_set_reg(M68K_PC, 0xc0a822);
m68000_write_memory_32(0x108000 + 0x76ee, m68000_read_memory_32(0x68));
// m68000_write_memory_32(0x108000 + 0x767c, 0xffffd642); //不明:餓狼スペシャル修正
m68000_write_memory_8(0x108000 + 0x76d9, 0x01);
m68000_write_memory_8(0x108000 + 0x76c3, 0x01);
m68000_write_memory_8(0x108000 + 0x764b, 0xff);
m68000_write_memory_8(0x108000 + 0x76f6, 0xff);
m68000_write_memory_8(0x108000 + 0x7e85, 0x01);
m68000_write_memory_8(0x108000 + 0x7d83, options.region & 0x03);
}
else
{
m68000_set_reg(M68K_PC, 0x000122);
// メモリをリセット
m68000_write_memory_8(0x108000 + 0x7d80, 0x82);
m68000_write_memory_8(0x108000 + 0x7daf, 0x01);
m68000_write_memory_8(0x108000 + 0x7ee1, 0x0a);
m68000_write_memory_8(0x108000 + 0x7675, 0x01);
m68000_write_memory_8(0x108000 + 0x7ebf, 0x00);
m68000_write_memory_32(0x108000 + 0x7db6, 0);
m68000_write_memory_32(0x108000 + 0x7dba, 0);
#if ENABLE_SYSTEM_CHECK
if (m68000_read_memory_8(0x108000 + 0x73d8) != 0x05)
{
m68000_write_memory_8(0x108000 + 0x73d8, 0x00);
system_check = 0;
}
#endif
}
}
// ドライバをリセット
neogeo_driver_reset();
// 画面処理をリセット
neogeo_video_reset();
// CDDAをリセット
neogeo_cdda_reset();
// BIOSシミュレートを初期化
if (game_index < 0)
bios_init();
neogeo_set_title();
}
/*------------------------------------------------------
スプライトのデコード
引 数: UINT8 *mem SPRのメモリ
offs_t offset デコード開始オフセット
UINT32 length データ長(バイト)
int usage_no 透過フラグの番号
戻り値: なし
-----------------------------------------------------*/
#define decode_spr(n, s) \
{ \
*dst |= (*(s) & 0x01) << ((n + 0) - 0); \
*dst |= (*(s) & 0x02) << ((n + 4) - 1); \
*dst |= (*(s) & 0x04) << ((n + 8) - 2); \
*dst |= (*(s) & 0x08) << ((n + 12) - 3); \
*dst |= (*(s) & 0x10) << ((n + 16) - 4); \
*dst |= (*(s) & 0x20) << ((n + 20) - 5); \
*dst |= (*(s) & 0x40) << ((n + 24) - 6); \
*dst |= (*(s) & 0x80) << ((n + 28) - 7); \
(s)++; \
}
void neogeo_decode_spr(UINT8 *mem, offs_t offset, UINT32 length)
{
UINT8 buf[128], *usage;
UINT32 *dst;
int i, j, k;
dst = (UINT32 *)(mem + offset);
usage = video_spr_usage + (offset >> 7);
for (i = 0; i < length; i += 128)
{
int opaque = 0;
UINT8 *src, *src2;
memcpy(buf, dst, 128);
src = buf;
src2 = buf + 64;
for (j = 0; j < 16; j++)
{
*dst = 0;
decode_spr(1, src2);
decode_spr(0, src2);
decode_spr(3, src2);
decode_spr(2, src2);
for (k = 0; k < 32; k += 4)
opaque += (*dst & (0x0f << k)) != 0;
dst++;
*dst = 0;
decode_spr(1, src);
decode_spr(0, src);
decode_spr(3, src);
decode_spr(2, src);
for (k = 0; k < 32; k += 4)
opaque += (*dst & (0x0f << k)) != 0;
dst++;
}
if (opaque)
*usage = (opaque == 256) ? 1 : 2;
else
*usage = 0;
usage++;
}
}
/*------------------------------------------------------
固定スプライトのデコード
引 数: UINT8 *mem FIXのメモリ
offs_t offset デコード開始オフセット
UINT32 length データ長
戻り値: なし
-----------------------------------------------------*/
#define decode_fix(n) \
{ \
tile = buf[n]; \
*mem++ = tile; \
opaque += (tile & 0x0f) != 0; \
opaque += (tile >> 4) != 0; \
}
void neogeo_decode_fix(UINT8 *mem, offs_t offset, UINT32 length)
{
int i, j;
UINT8 tile, opaque;
UINT8 buf[32], *usage;
mem += (offset >> 1);
usage = video_fix_usage + (offset >> 6);
for (i = 0; i < length; i += 32)
{
opaque = 0;
memcpy(buf, mem, 32);
for (j = 0; j < 8; j++)
{
decode_fix(j + 16);
decode_fix(j + 24);
decode_fix(j + 0);
decode_fix(j + 8);
}
if (opaque)
*usage = (opaque == 64) ? 1 : 2;
else
*usage = 0;
*usage++;
}
}
/*------------------------------------------------------
固定スプライトの復元
引 数: UINT8 *mem FIXのメモリ
offs_t offset デコード開始オフセット
UINT32 length データ長
戻り値: なし
-----------------------------------------------------*/
#define undecode_fix(n) \
{ \
tile = *(mem2 + (ofs++)); \
buf[n] = tile; \
}
void neogeo_undecode_fix(UINT8 *mem, offs_t offset, UINT32 length)
{
int i, j, ofs;
UINT8 tile;
UINT8 buf[32];
UINT8 *mem2 = mem + offset;
for (i = 0; i < length; i += 32)
{
ofs = 0;
for (j = 0; j < 8; j++)
{
undecode_fix(j + 16);
undecode_fix(j + 24);
undecode_fix(j + 0);
undecode_fix(j + 8);
}
memcpy(mem2, buf, 32);
mem2 += 32;
}
}
/*------------------------------------------------------
Z80のパッチ反映
引 数: UINT16 *src PATファイルを読み込んだメモリ
int bank バンク
offs_t offset オフセット
戻り値: なし
-----------------------------------------------------*/
#define PATCH_Z80(a, b) \
{ \
dst[((a) + 0)] = (b) & 0xff; \
dst[((a) + 1)] = ((b) >> 8) & 0xff; \
}
void neogeo_apply_patch(UINT16 *src, int bank, offs_t offset)
{
UINT8 *dst = memory_region(REGION_CPU2);
offset = (((bank * 0x100000) + offset) >> 8) & 0xffff;
while (*src)
{
PATCH_Z80(src[0] + 0, (src[1] + offset) >> 1);
PATCH_Z80(src[0] + 2, ((src[2] + offset) >> 1) - 1);
if (src[3] && src[4])
{
PATCH_Z80(src[0] + 5, (src[3] + offset) >> 1);
PATCH_Z80(src[0] + 7, ((src[4] + offset) >> 1) - 1);
}
src += 5;
}
}
/*------------------------------------------------------
ベクタテーブル書き換え(BIOS)
引 数: offs_t offset オフセット(未使用)
UINT16 datat データ(未使用)
戻り値: なし
-----------------------------------------------------*/
WRITE16_HANDLER( neogeo_select_bios_vectors )
{
UINT8 *gamerom = memory_region(REGION_CPU1);
UINT8 *biosrom = memory_region(REGION_USER1);
memcpy(gamerom, biosrom, 0x100);
}
/*------------------------------------------------------
ベクタテーブル書き換え(ゲーム)
引 数: offs_t offset オフセット(未使用)
UINT16 datat データ(未使用)
戻り値: なし
-----------------------------------------------------*/
WRITE16_HANDLER( neogeo_select_game_vectors )
{
UINT8 *gamerom = memory_region(REGION_CPU1);
memcpy(gamerom, neogeo_game_vectors, 0x100);
}
/*------------------------------------------------------
バックアップメモリリード ($800000 - $803fff)
引 数: offs_t offset 読み込むオフセット
戻り値: 読み込んだデータ
-----------------------------------------------------*/
READ16_HANDLER( neogeo_memcard16_r )
{
UINT8 *mem = memory_region(REGION_USER2);
offset &= 0x1fff;
return mem[offset] | 0xff00;
}
/*------------------------------------------------------
バックアップメモリライト ($800000 - $803fff)
引 数: offs_t offset 書き込むオフセット
UINT16 datat 書き込むデータ
戻り値: なし
-----------------------------------------------------*/
WRITE16_HANDLER( neogeo_memcard16_w )
{
if (ACCESSING_LSB)
{
UINT8 *mem = memory_region(REGION_USER2);
offset &= 0x1fff;
mem[offset] = data & 0xff;
}
}
/*------------------------------------------------------
外部メモリリード ($e000000 - $efffff)
引 数: offs_t offset 読み込むオフセット
戻り値: 各メモリのデータ
-----------------------------------------------------*/
READ16_HANDLER( neogeo_externalmem_16_r )
{
UINT8 *src;
UINT16 retdata = 0xffff;
offset -= (0xe00000 >> 1);
switch (exmem[exmem_counter])
{
case EXMEM_OBJ:
src = memory_region(REGION_GFX2);
offset = (offset << 1) + (exmem_bank[EXMEM_OBJ] << 20);
retdata = (src[offset] << 8) | src[offset + 1];
break;
case EXMEM_PCMA:
src = memory_region(REGION_SOUND1);
offset = offset + (exmem_bank[EXMEM_PCMA] << 19);
retdata = src[offset] | 0xff00;
break;
case EXMEM_Z80:
#if 1
if (z80_cdda_offset)
{
if (offset == z80_cdda_offset || offset == z80_cdda_offset + 1)
{
// 読み込むと問題が起こる場合があるので、とりあえず無視
return 0;
}
}
#endif
src = memory_region(REGION_CPU2);
retdata = src[offset] | 0xff00;
break;
case EXMEM_FIX:
src = memory_region(REGION_GFX1);
retdata = src[offset] | 0xff00;
break;
}
return retdata;
}
/*------------------------------------------------------
外部メモリライト ($e000000 - $efffff)
引 数: offs_t offset 書き込むオフセット
UINT16 datat 書き込むデータ
戻り値: なし
-----------------------------------------------------*/
WRITE16_HANDLER( neogeo_externalmem_16_w )
{
UINT8 *dst;
offset -= (0xe00000 >> 1);
switch (exmem[exmem_counter])
{
case EXMEM_OBJ:
offset = (offset << 1) + (exmem_bank[EXMEM_OBJ] << 20);
data = (data << 8) | (data >> 8);
dst = memory_region(REGION_GFX2);
COMBINE_SWABDATA((UINT16 *)(dst + offset));
#if ENABLE_SYSTEM_CHECK
dst = memory_region(REGION_GFX6);
COMBINE_SWABDATA((UINT16 *)(dst + offset));
#endif
if ((offset & 0x7f) == 0x7e)
neogeo_decode_spr(dst, (offset & ~0x7f), 128);
return;
case EXMEM_PCMA:
dst = memory_region(REGION_SOUND1);
offset += exmem_bank[EXMEM_PCMA] << 19;
dst[offset] = data & 0xff;
return;
case EXMEM_Z80:
#if 1
if (z80_cdda_offset)
{
if (offset == z80_cdda_offset || offset == z80_cdda_offset + 1)
{
// 書き込むと問題が起こる場合があるので、とりあえず無視
return;
}
}
#endif
dst = memory_region(REGION_CPU2);
dst[offset] = data & 0xff;
return;
case EXMEM_FIX:
dst = memory_region(REGION_GFX1);
dst[offset] = data & 0xff;
#if ENABLE_SYSTEM_CHECK
dst = memory_region(REGION_GFX5);
dst[offset] = data & 0xff;
#endif
if ((offset & 0x1f) == 0x1f)
neogeo_decode_fix(dst, (offset & ~0x1f) << 1, 32);
return;
}
}
/*------------------------------------------------------
ハードウェア制御データ読み込み
引 数: offs_t offset 読み込むオフセット
戻り値: 各メモリのデータ
-----------------------------------------------------*/
READ16_HANDLER( neogeo_hardcontrol_16_r )
{
UINT16 *mem = (UINT16 *)memory_region(REGION_USER3);
LOG(("neogeo_hardcontrol_16_r(): offset = %06x\n", offset << 1));
offset &= 0xff;
return mem[offset];
}
/*------------------------------------------------------
ハードウェアデータ転送 ($ff0060 - $ff0061)
引 数: offs_t offset 書き込むオフセット (未使用)
UINT16 datat 書き込むデータ
戻り値: なし
-----------------------------------------------------*/
static WRITE16_HANDLER( hardware_upload_16_w )
{
if (data == 0x00) // ハードウェア転送情報クリア
{
upload_mode = UPLOAD_IMMIDIATE;
upload_offset1 = 0;
upload_offset2 = 0;
upload_length = 0;
}
else if (data == 0x40) // ハードウェア転送実行
{
int i;
UINT8 *src, *dst;
if (upload_mode == UPLOAD_MEMORY)
{
upload_type = upload_get_type() & 0x0f;
}
else
{
if (upload_offset1 >= 0x000000 && upload_offset1 < 0x200000)
{
upload_type = PRG_TYPE;
}
else if (upload_offset1 >= 0x400000 && upload_offset1 < 0x500000)
{
upload_type = PAL_TYPE;
}
else if (upload_offset1 >= 0x800000 && upload_offset1 < 0x804000)
{
upload_type = BACKUP_RAM;
}
else // 0xe00000
{
switch (exmem[exmem_counter])
{
case EXMEM_OBJ: upload_type = SPR_TYPE; break;
case EXMEM_PCMA: upload_type = PCM_TYPE; break;
case EXMEM_Z80: upload_type = Z80_TYPE; break;
case EXMEM_FIX: upload_type = FIX_TYPE; break;
}
}
}
#if 0
logerror("\nhardware upload\n");
logerror(" mode = ");
switch (upload_mode)
{
case UPLOAD_IMMIDIATE: logerror("IMMIDIATE\n"); break;
case UPLOAD_PATTERN: logerror("PATTERN\n"); break;
case UPLOAD_MEMORY: logerror("MEMORY\n"); break;
case UPLOAD_FILE: logerror("FILE\n"); break;
}
logerror(" type = ");
switch (upload_type)
{
case PRG_TYPE: logerror("MAIN\n"); break;
case FIX_TYPE: logerror("FIX\n"); break;
case SPR_TYPE: logerror("OBJ\n"); break;
case Z80_TYPE: logerror("Z80\n"); break;
case PCM_TYPE: logerror("PCM-A\n"); break;
case PAL_TYPE: logerror("PALETTE\n"); break;
case BACKUP_RAM: logerror("BACKUP\n"); break;
default: logerror("UNKNOWN\n"); break;
}
if (upload_mode == UPLOAD_MEMORY)
{
logerror(" offset1(src) = %06x\n", upload_offset1);
logerror(" offset2(dst) = %06x\n", upload_offset2);
if (upload_type == SPR_TYPE || upload_type == PCM_TYPE)
logerror(" bank = %x\n", upload_get_bank());
}
else
{
logerror(" offset(dst) = %06x\n", upload_offset1);
if (upload_type == SPR_TYPE) logerror(" bank = %x\n", exmem_bank[EXMEM_OBJ]);
if (upload_type == PCM_TYPE) logerror(" bank = %x\n", exmem_bank[EXMEM_PCMA]);
}
logerror(" length = %x\n", upload_length);
if (upload_mode == UPLOAD_PATTERN)
logerror(" pattern = %04x\n", upload_pattern);
logerror("\n");
#endif
switch (upload_mode)
{
#if ENABLE_SYSTEM_CHECK
case UPLOAD_IMMIDIATE:
{
// 即値(アドレスの値のみっぽい)転送モード
// テストモードで使用、ゲームでは使用されていないと思われる
switch (upload_type)
{
case FIX_TYPE:
case Z80_TYPE:
case PCM_TYPE:
case BACKUP_RAM:
for (i = 0; i < upload_length; i++)
{
offset = upload_offset1 + (i * 8);
m68000_write_memory_16(offset + 0, ((offset >> 24) & 0xff) | 0xff00);
m68000_write_memory_16(offset + 2, ((offset >> 16) & 0xff) | 0xff00);
m68000_write_memory_16(offset + 4, ((offset >> 8) & 0xff) | 0xff00);
m68000_write_memory_16(offset + 6, ((offset >> 0) & 0xff) | 0xff00);
}
break;
case PRG_TYPE:
case PAL_TYPE:
case SPR_TYPE:
for (i = 0; i < upload_length; i++)
{
offset = upload_offset1 + (i * 4);
m68000_write_memory_32(offset, offset);
}
break;
}
}
break;
#endif
case UPLOAD_PATTERN:
{
// パターン転送モード
// テストモードとパレットのクリアで使用
switch (upload_type)
{
case FIX_TYPE:
case Z80_TYPE:
case PCM_TYPE:
case BACKUP_RAM:
for (i = 0; i < upload_length; i++)
{
offset = upload_offset1 + (i * 2);
m68000_write_memory_16(offset, (upload_pattern & 0xff) | 0xff00);
}
break;
case PRG_TYPE:
case PAL_TYPE:
case SPR_TYPE:
for (i = 0; i < upload_length; i++)
{
offset = upload_offset1 + (i * 2);
m68000_write_memory_16(offset, upload_pattern);
}
break;
}
}
break;
case UPLOAD_MEMORY:
{
// メモリ転送モード
UINT32 length;
length = upload_length << 1;
src = memory_region(REGION_CPU1) + upload_offset1;
switch (upload_type & 0x0f)
{
case PRG_TYPE:
dst = memory_region(REGION_CPU1);
memcpy(dst + upload_offset2, src, length);
break;
case FIX_TYPE:
dst = memory_region(REGION_GFX1);
offset = upload_offset2 - 0xe00000;
swab(src, dst + (offset >> 1), length);
#if ENABLE_SYSTEM_CHECK
dst = memory_region(REGION_GFX5);
swab(src, dst + (offset >> 1), length);
#endif
neogeo_decode_fix(dst, offset, length);
break;
case SPR_TYPE:
dst = memory_region(REGION_GFX2);
offset = (upload_offset2 - 0xe00000) + (upload_get_bank() << 20);
swab(src, dst + offset, length);
#if ENABLE_SYSTEM_CHECK
dst = memory_region(REGION_GFX6);
swab(src, dst + offset, length);
#endif
neogeo_decode_spr(dst, offset, length);
exmem_bank[EXMEM_OBJ] = ((offset + upload_get_length()) >> 20) & 0x03;
break;
case Z80_TYPE:
dst = memory_region(REGION_CPU2);
offset = upload_offset2 - 0xe00000;
swab(src, dst + (offset >> 1), length);
break;
case PAL_TYPE:
for (i = 0; i < length; i++)
{
data = m68000_read_memory_16(upload_offset1 + i * 2);
m68000_write_memory_16(upload_offset2 + i * 2, data);
}
break;
}
}
break;
case UPLOAD_FILE:
// ファイル転送モード
// 現状はcdrom_load_files()で処理
break;
}
}
}
/*------------------------------------------------------
転送オフセット1設定 ($ff0064 - $ff0065)
($ff0066 - $ff0067)
引 数: offs_t offset 書き込むオフセット (未使用)
UINT16 datat 書き込むデータ
戻り値: なし
※ 転送モードが即値、パターンの場合は転送先オフセット
メモリ転送の場合は転送元オフセット
-----------------------------------------------------*/
static WRITE16_HANDLER( upload_offset1_16_w )
{
if (offset)
upload_offset1 = (upload_offset1 & 0xffff0000) | (UINT32)data;
else
upload_offset1 = (upload_offset1 & 0x0000ffff) | ((UINT32)data << 16);
}
/*------------------------------------------------------
転送オフセット2設定 ($ff0068 - $ff0069)
($ff006a - $ff006b)
引 数: offs_t offset 書き込むオフセット (未使用)
UINT16 datat 書き込むデータ
戻り値: なし
※ メモリ転送モードの転送先オフセット
この値が設定された場合は、メモリ転送モード
-----------------------------------------------------*/
static WRITE16_HANDLER( upload_offset2_16_w )
{
if (offset)
upload_offset2 = (upload_offset2 & 0xffff0000) | (UINT32)data;
else
upload_offset2 = (upload_offset2 & 0x0000ffff) | ((UINT32)data << 16);
upload_mode = UPLOAD_MEMORY;
}
/*------------------------------------------------------
転送パターン設定 ($ff006c - $ff006d)
引 数: offs_t offset 書き込むオフセット (未使用)
UINT16 datat 書き込むデータ
戻り値: なし
※ この値が設定された場合は、パターン転送モード
-----------------------------------------------------*/
static WRITE16_HANDLER( upload_pattern_16_w )
{
upload_pattern = data;
upload_mode = UPLOAD_PATTERN;
}
/*------------------------------------------------------
転送データ長設定 ($ff0070 - $ff0071)
($ff0072 - $ff0073)
引 数: offs_t offset 書き込むオフセット (未使用)
UINT16 datat 書き込むデータ
戻り値: なし
-----------------------------------------------------*/
static WRITE16_HANDLER( upload_length_16_w )
{
if (offset)
upload_length = (upload_length & 0xffff0000) | (UINT32)data;
else
upload_length = (upload_length & 0x0000ffff) | ((UINT32)data << 16);
}
/*------------------------------------------------------
外部メモリ転送タイプ設定 ($ff0105)
引 数: offs_t offset 書き込むオフセット (未使用)
UINT16 datat 書き込むデータ
戻り値: なし
-----------------------------------------------------*/
static WRITE16_HANDLER( exmem_type_16_w )
{
exmem[exmem_counter] = data;
#if 1
if (exmem[exmem_counter] == EXMEM_Z80)
{
z80_cdda_offset = m68000_read_memory_32(0x108000 + 0x76ea);
if (z80_cdda_offset)
z80_cdda_offset = (z80_cdda_offset - 0xe00000) >> 1;
}
#endif
if (exmem[exmem_counter] == EXMEM_OBJ) exmem_bank[EXMEM_OBJ] = 0;
if (exmem[exmem_counter] == EXMEM_PCMA) exmem_bank[EXMEM_PCMA] = 0;
}
/*------------------------------------------------------
SPR描画停止 ($ff0111)
引 数: offs_t offset 書き込むオフセット (未使用)
UINT16 datat 書き込むデータ
戻り値: なし
-----------------------------------------------------*/
static WRITE16_HANDLER( spr_disable_16_w )
{
spr_disable = data & 0xff;
}
/*------------------------------------------------------
FIX描画停止 ($ff0115)
引 数: offs_t offset 書き込むオフセット (未使用)
UINT16 datat 書き込むデータ
戻り値: なし
-----------------------------------------------------*/
static WRITE16_HANDLER( fix_disable_16_w )
{
fix_disable = data & 0xff;
}
/*------------------------------------------------------
ビデオ出力有効 ($ff0119)
引 数: offs_t offset 書き込むオフセット (未使用)
UINT16 datat 書き込むデータ
戻り値: なし
-----------------------------------------------------*/
static WRITE16_HANDLER( video_enable_16_w )
{
video_enable = data & 0xff;
}
/*------------------------------------------------------
外部メモリ転送番号設定 ($ff0121) - OBJ RAM
($ff0123) - PCM-A RAM
($ff0127) - Z80 RAM
($ff0129) - FIX RAM
引 数: offs_t offset 書き込むオフセット
UINT16 datat 書き込むデータ
戻り値: なし
※本来であれば、該当するメモリのアクセスを無効に
しているはず
-----------------------------------------------------*/
static WRITE16_HANDLER( exmem_latch_16_w )
{
exmem_counter++;
exmem_latch[exmem_counter] = offset & 0x0f;
#if ENABLE_SYSTEM_CHECK
if (system_check && exmem_latch[exmem_counter] == 0x03)
z80_reset(0);
#endif
}
/*------------------------------------------------------
外部メモリ転送番号消去 ($ff0141) - OBJ RAM
($ff0143) - PCM-A RAM
($ff0147) - Z80 RAM
($ff0149) - FIX RAM
引 数: offs_t offset 書き込むオフセット
UINT16 datat 書き込むデータ
戻り値: なし
※本来であれば、該当するメモリのアクセス無効を
解除しているはず
-----------------------------------------------------*/
static WRITE16_HANDLER( exmem_latch_clear_16_w )
{
offset &= 0x0f;
if (exmem_latch[exmem_counter] == offset)
{
#if ENABLE_SYSTEM_CHECK
if (system_check && exmem_latch[exmem_counter] == 0x03)
z80_enable(1);
#endif
exmem_latch[exmem_counter] = EXMEM_UNKNOWN;
exmem_counter--;
}
}
/*------------------------------------------------------
転送フラグ設定 ($ff0161)
引 数: offs_t offset 書き込むオフセット (未使用)
UINT16 datat 書き込むデータ
戻り値: なし
-----------------------------------------------------*/
static WRITE16_HANDLER( upload_executing_16_w )
{
upload_executing = data & 0xff;
}
/*------------------------------------------------------
Z80リセット/イネーブル ($ff0183)
引 数: offs_t offset 書き込むオフセット (未使用)
UINT16 datat 書き込むデータ
戻り値: なし
-----------------------------------------------------*/
static WRITE16_HANDLER( z80_enable_16_w )
{
if (data & 0xff)
z80_enable(1);
else
z80_reset(0);
}
/*------------------------------------------------------
外部メモリ転送バンク設定 ($ff01a1) - OBJ RAM
($ff01a3) - PCM-A RAM
引 数: offs_t offset 書き込むオフセット (未使用)
UINT16 datat 書き込むデータ
戻り値: なし
-----------------------------------------------------*/
static WRITE16_HANDLER( exmem_bank_16_w )
{
offset &= 0x0f;
exmem_bank[offset] = data & 0x03;
}
/*------------------------------------------------------
ハードウェア制御データ書き込み
引 数: offs_t offset 書き込むオフセット
UINT16 datat 書き込むデータ
戻り値: なし
-----------------------------------------------------*/
WRITE16_HANDLER( neogeo_hardcontrol_16_w )
{
UINT16 *mem = (UINT16 *)memory_region(REGION_USER3);
offset &= 0xff;
switch (offset << 1)
{
case 0x00: break; // unknown
case 0x02: break; // unknown
case 0x04: break; // unknown
case 0x06: break; // unknown
case 0x60: hardware_upload_16_w(0, data, mem_mask); break;
case 0x64: upload_offset1_16_w(0, data, mem_mask); break;
case 0x66: upload_offset1_16_w(1, data, mem_mask); break;
case 0x68: upload_offset2_16_w(0, data, mem_mask); break;
case 0x6a: upload_offset2_16_w(1, data, mem_mask); break;
case 0x6c: upload_pattern_16_w(0, data, mem_mask); break;
case 0x70: upload_length_16_w(0, data, mem_mask); break;
case 0x72: upload_length_16_w(1, data, mem_mask); break;
case 0x7e: break; // unknown
case 0x80: break; // unknown
case 0x82: break; // unknown
case 0x84: break; // unknown
case 0x86: break; // unknown
case 0x88: break; // unknown
case 0x8a: break; // unknown
case 0x8c: break; // unknown
case 0x8e: break; // unknown
case 0x104: exmem_type_16_w(0, data, mem_mask); break;
case 0x110: spr_disable_16_w(0, data, mem_mask); break;
case 0x114: fix_disable_16_w(0, data, mem_mask); break;
case 0x118: video_enable_16_w(0, data, mem_mask); break;
case 0x11c: break; // machine settings (read only)
case 0x120: // OBJ RAM latch
case 0x122: // PCM-A RAM latch
case 0x126: // Z80 RAM latch
case 0x128: // FIX RAM latch
exmem_latch_16_w(offset, data, mem_mask);
break;
case 0x140: // OBJ RAM latch clear
case 0x142: // PCM-A RAM latch clear
case 0x146: // Z80 RAM latch clear
case 0x148: // FIX RAM latch clear
exmem_latch_clear_16_w(offset, data, mem_mask);
break;
case 0x180: break; // unknown
case 0x182: z80_enable_16_w(0, data, mem_mask); break;
case 0x1a0: // OBJ RAM bank
case 0x1a2: // PCM-A RAM bank
case 0x1a6: // unknown (PAT bank?)
exmem_bank_16_w(offset, data, mem_mask);
break;
default:
LOG(("neogeo_hardcontrol_16_w(): offset = %06x, data = %04x\n", offset << 1, data));
break;
}
COMBINE_DATA(&mem[offset]);
}
/*------------------------------------------------------
ゲーム名をウィンドウタイトルに設定
引 数: なし
戻り値: なし
メモリから取得するタイトルは正確ではないです
(KOF96 NEOGEO Collectionが得点王3だったり)
ウィンドウタイトルのゲーム名はgames構造体に
登録してあります
-----------------------------------------------------*/
void neogeo_set_title(void)
{
int index = game_index;
if (index < 0)
index = next_game_index;
if (index < 0)
{
if (options.region)
osd_set_title(APPNAME);
else
osd_set_title("NEOGEO CDZ Emulator");
}
else
{
int i = options.region & 3;
while (i >= 0)
{
if (games[index].title[i])
{
osd_set_title("%s", games[index].title[i]);
break;
}
i--;
}
}
}