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


/*************************************************************************** 
 
	cdrom.c 
 
	NEOGEO CD CD-ROM制御 
 
***************************************************************************/ 
 
#include "neogeocd.h" 
 
 
#ifndef LOG 
#define VERBOSE 0 
#if VERBOSE 
#define LOG(x) logerror x 
#else 
#define LOG(x) 
#endif 
#endif /* LOG */ 
 
 
#define MAX_FILELIST	32 
 
/**************************************************************************** 
	プロトタイプ 
 ***************************************************************************/ 
 
static int load_file(int fileno); 
static void init_loading_progress(void); 
static int get_filetype(const char *ext); 
 
 
/**************************************************************************** 
	グローバル変数 
 ***************************************************************************/ 
 
int cdrom_current_drive;		// 使用するCD-ROMドライブ番号 
int cdrom_loading_state;		// CD-ROMの状態 
int cdrom_ipl_loading;			// IPL.TXT処理中 
 
 
/**************************************************************************** 
	Internal valiables 
 ***************************************************************************/ 
 
static int cdrom_drive_state[MAX_DRIVE]; 
 
static UINT8 *cdrom_cache; 
 
static FILE *cdrom_fp = NULL; 
static int current_fileno = 0; 
static int total_sectors = 0; 
 
static int disable_tray_check; 
 
 
/**************************************************************************** 
	Internal structure 
 ***************************************************************************/ 
 
static struct filelist_t 
{ 
	UINT8	name[16]; 
	int		bank; 
	offs_t	offset; 
	UINT32	length; 
	int     type; 
	offs_t	next; 
	UINT32	left; 
	int		sectors; 
} filelist[MAX_FILELIST]; 
 
 
/*************************************************************************** 
	グローバル関数 
 ***************************************************************************/ 
 
/*------------------------------------------------------ 
 
	CD-ROM処理の初期化 
 
	引  数: なし 
	戻り値: とりあえず常に1 
 
 -----------------------------------------------------*/ 
 
int cdrom_init(void) 
{ 
	int i, tray; 
 
	cdrom_abort_loading(); 
 
	cdrom_cache = memory_region(REGION_CPU1) + 0x111204; 
	cdrom_loading_state = CDROM_IDLE; 
	cdrom_ipl_loading = 0; 
	disable_tray_check = 0; 
 
	for (i = 0; i < MAX_DRIVE; i++) 
	{ 
		if (osd_get_drive_type(i) == OSD_DRIVE_CDROM) 
		{ 
			cdrom_drive_state[i] = CDROM_NOTREADY; 
 
			tray = osd_get_tray_state(i); 
			if (tray == -1) 
				disable_tray_check = 1; 
			else 
				cdrom_drive_state[i] |= tray << 4; 
		} 
		else 
			cdrom_drive_state[i] = CDROM_NOTEXIST; 
	} 
 
	return 1; 
} 
 
 
/*------------------------------------------------------ 
 
	CD-ROM処理の終了 
 
	引  数: なし 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void cdrom_shutdown(void) 
{ 
	cdrom_abort_loading(); 
} 
 
 
/*------------------------------------------------------ 
 
	CD-ROM状態チェック 
 
	引  数: int drive  ドライブ番号 
	戻り値: 変化があればドライブの状態の値 
 
 -----------------------------------------------------*/ 
 
int cdrom_check_state(int drive) 
{ 
	int status; 
 
	if (cdrom_drive_state[drive] == CDROM_NOTEXIST) 
		return CDROM_NOTEXIST; 
 
	if (osd_drive_is_ready(drive) == OSD_OK) 
		status = CDROM_READY; 
	else 
		status = CDROM_NOTREADY; 
 
	if (!disable_tray_check) 
	{ 
		int tray = osd_get_tray_state(drive); 
 
		if (tray != -1) 
			status |= tray << 4; 
	} 
 
	if (status != cdrom_drive_state[drive]) 
	{ 
		cdrom_drive_state[drive] = status; 
		return status; 
	} 
	return 0; 
} 
 
 
/*------------------------------------------------------ 
 
	CD-ROM状態取得 
 
	引  数: int drive  ドライブ番号 
	戻り値: ドライブの状態の値 
 
 -----------------------------------------------------*/ 
 
int cdrom_get_state(int drive) 
{ 
	return cdrom_drive_state[drive]; 
} 
 
 
/*------------------------------------------------------ 
 
	CD-ROM読み込みの強制終了 
 
	引  数: なし 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void cdrom_abort_loading(void) 
{ 
	current_fileno = 0; 
	total_sectors = 0; 
	cdrom_loading_state = CDROM_DONE; 
 
	if (cdrom_fp != NULL) 
	{ 
		fclose(cdrom_fp); 
		cdrom_fp = NULL; 
	} 
} 
 
 
/*------------------------------------------------------ 
 
	IPL.TXT処理 
 
	引  数: なし 
	戻り値: エラー=0, 成功==1 
 
 -----------------------------------------------------*/ 
 
int cdrom_process_ipl(void) 
{ 
	struct filelist_t *file = &filelist[0]; 
	UINT8 path[MAX_PATH], readbuf[32]; 
	UINT8 *fname, *ext, *str_offs, *str_bank, *start_p, *p; 
	char region_chr[3] = { 'j','u','e' }; 
	UINT32 length; 
	int i; 
	FILE *fp; 
 
	// LOGO_x.PRG読み込み 
	for (i = options.region & 3; i >= 0; i--) 
	{ 
		sprintf(path, "%c:/LOGO_%c.PRG", 'A' + cdrom_current_drive, region_chr[i]); 
 
		if ((length = osd_file_exist(path)) != 0) 
		{ 
			UINT8 *mem = memory_region(REGION_CPU1) + 0x120000; 
 
			fp = fopen(path, "rb"); 
			if (fp != NULL) 
			{ 
				fread(mem, length, 1, fp); 
				fclose(fp); 
 
				swab(mem, mem, length); 
				break; 
			} 
		} 
	} 
 
	total_sectors = 0; 
 
	sprintf(path, "%c:\\IPL.TXT", cdrom_current_drive + 'A'); 
 
	length = osd_file_exist(path); 
	if (length == 0) 
	{ 
		logerror("CD-ROM: IPL.TXT not exist.\n"); 
		return 0; 
	} 
 
	fp = fopen(path, "rb"); 
	if (fp == NULL) 
	{ 
		logerror("CD-ROM: could not open IPL.TXT.\n"); 
		return 0; 
	} 
	fread(cdrom_cache, length, 1, fp); 
	fclose(fp); 
 
	cdrom_ipl_loading = 1; 
 
	p = cdrom_cache; 
 
	logerror("Processing IPL.TXT...\n"); 
 
	while (*p && *p != 0x1a)	// EOFまでループ 
	{ 
		start_p = p; 
 
		// 改行コードを0に置き換え 
		p = strchr(start_p, 0x0d); 
		*p++ = '\0'; 
		*p++ = '\0'; 
 
		strcpy(readbuf, start_p); 
 
		// 1行展開 - IPL.TXTはCSV形式 
		fname    = strtok(readbuf, ",\r\n");	// ファイル名 
		str_bank = strtok(NULL, ",\r\n");		// バンク 
		str_offs = strtok(NULL, ",\r\n");		// オフセット 
 
		if (fname == NULL || str_offs == NULL || str_bank == NULL) 
			break; 
 
		// ファイル名 
		for (i = 0; i <= strlen(fname); i++) 
			file->name[i] = toupper(fname[i]); 
 
		// バンクナンバー 
		sscanf(str_bank, "%d", &file->bank); 
		file->bank &= 3; 
 
		// オフセット 
		sscanf(str_offs, "%x", &file->offset); 
 
		// ファイルタイプ 
		ext = strrchr(file->name, '.') + 1; 
		if (ext[0] == 'O') strcpy(ext, "SPR"); 
		file->type = get_filetype(ext); 
 
		// ファイルサイズ 
		sprintf(path, "%c:\\%s", cdrom_current_drive + 'A', file->name); 
		file->length = osd_file_exist(path); 
 
		file->sectors = (file->length + 0x7ff) / 0x800; 
 
		// 分割ロード用設定 
		file->next = 0; 
 
		// トータルセクタ数計算 
		total_sectors += file->sectors; 
 
		logerror("entry: %s,%d,%06x,%06x,%x\n", file->name, file->bank, file->offset, file->length, file->sectors); 
 
		file++; 
	} 
 
	file->name[0] = '\0'; 
 
	m68000_write_memory_8(0x108000 + 0x7ddc, 0x01);	// ロード画面の有無 
 
	init_loading_progress(); 
 
	loading_screen_start(); 
 
	cdrom_loading_state = CDROM_LOADING; 
 
	while (cdrom_loading_state != CDROM_IDLE) 
	{ 
		if (osd_get_app_state()) 
			return -1; 
 
		update_input_port(); 
		loading_updatescreen(); 
	} 
 
	loading_screen_stop(); 
 
	m68000_write_memory_8(0x108000 + 0x7ddc, 0x00);	// ロード画面の有無 
	m68000_write_memory_32(0x108000 + 0x7690, 0); 
 
	cdrom_ipl_loading = 0; 
 
	return 1; 
} 
 
 
/*------------------------------------------------------ 
 
	CD-ROM読み込み開始 
 
	引  数: なし 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
static UINT8 save1, save2; 
 
void cdrom_load_files(void) 
{ 
	struct filelist_t *file = &filelist[0]; 
	UINT8 *mem, path[32], *ext; 
	int i; 
	offs_t offset, src, dst; 
	UINT32 data; 
 
	if (m68000_read_memory_8(m68000_get_reg(M68K_A0)) == 0) 
		return; 
 
	neogeo_cdda_stop(); 
 
	save1 = m68000_read_memory_8(0x108000 + 0x7d80); 
	save2 = m68000_read_memory_8(0x108000 + 0x7dc2); 
 
	if (with_image()) 
		logerror("CD-ROM: load with image\n"); 
	else 
		logerror("CD-ROM: load without image\n"); 
 
	mem = memory_region(REGION_CPU1); 
 
	// ファイル情報領域をクリア 
	offset = 0x115a06; 
	for (i = 0; i < 0x20; i++) 
	{ 
		memset(mem + offset, 0, 0x20); 
		m68000_write_memory_16(offset + 0x1c, 0xffff); 
		offset += 0x20; 
	} 
 
	// ファイル情報領域を設定 
	offset = 0x115a06; 
 
	src = m68000_get_reg(M68K_A0); 
 
	while (1) 
	{ 
		if (m68000_read_memory_8(src) == 0) 
			break; 
 
		dst = offset; 
 
		// ファイル名取得 
		while (1) 
		{ 
			data = m68000_read_memory_8(src++); 
 
			if (data == 0) break; 
 
			// 小文字の場合は大文字に変換 
			if (data >= 'a') data -= 0x20; 
 
			m68000_write_memory_8(dst++, data); 
		} 
 
		// 拡張子がOBJの場合はSPRに変更 
		if (m68000_read_memory_8(dst - 3) == 'O') 
		{ 
			m68000_write_memory_8(dst - 3, 'S'); 
			m68000_write_memory_8(dst - 2, 'P'); 
			m68000_write_memory_8(dst - 1, 'R'); 
		} 
 
		// バンク番号取得 
		dst = offset + 0x10; 
		data = m68000_read_memory_8(src++) & 0x03; 
		m68000_write_memory_8(dst++, data); 
 
		// アドレスを調整 
		src = (src + 1) & 0xfffffe; 
		dst = (dst + 1) & 0xfffffe; 
 
		// オフセットを取得 
		m68000_write_memory_32(dst, m68000_read_memory_32(src)); 
 
		// 次のファイル情報の位置を設定 
		src += 4; 
		offset += 0x20; 
	} 
 
	total_sectors = 0; 
	offset = 0x115a06; 
 
	do 
	{ 
		char *p; 
 
		swab(mem + offset, file->name, 16); 
 
		p = strchr(file->name, ';'); 
		if (p != NULL) *p = '\0'; 
 
		ext = strrchr(file->name, '.') + 1; 
		file->type = get_filetype(ext); 
 
		file->bank   = m68000_read_memory_8(offset + 0x10); 
		file->offset = m68000_read_memory_32(offset + 0x12); 
 
		sprintf(path, "%c:/%s", cdrom_current_drive + 'A', file->name); 
		file->length = osd_file_exist(path); 
 
		file->sectors = (file->length + 0x7ff) / 0x800; 
 
		file->next = 0; 
 
		// トータルブロック数計算 
		total_sectors += file->sectors; 
 
		logerror("entry: %s,%d,%06x,%06x,%d\n", file->name, file->bank, file->offset, file->length, file->sectors); 
 
		offset += 0x20; 
		file++; 
 
	} while (mem[offset] != 0); 
 
	file->name[0] = '\0'; 
 
#if FAST_SPRITE_DRAW 
	if (GAME_NAME("ngcdsp")) 
	{ 
		char *ext = strrchr(filelist[0].name, '.') + 1; 
 
		if (get_filetype(ext) == FIX_TYPE) 
		{ 
			if (strcmp(filelist[0].name, "G046.FIX") == 0) 
				neogeo_change_sprite_func(1, 0); 
			else 
				neogeo_change_sprite_func(0, 0); 
		} 
	} 
#endif 
 
	// ロード情報書き込み 
//	m68000_write_memory_8(0x108000 + 0x7657, 0x01);	// CD-ROM読み込み中フラグ 
//	m68000_write_memory_8(0x108000 + 0x76c3, 0x00);	// CDDAイネーブル 
 
	init_loading_progress(); 
 
	loading_screen_start(); 
 
	cdrom_loading_state = CDROM_LOADING; 
 
	if (driver_flag & LOADING_TYPE1) 
	{ 
		while (cdrom_loading_state != CDROM_IDLE) 
		{ 
			if (osd_get_app_state()) 
				return; 
 
			update_input_port(); 
			loading_updatescreen(); 
		} 
 
		cdrom_finish_load_files(); 
	} 
} 
 
 
/*------------------------------------------------------ 
 
	CD-ROM読み込み終了 
 
	引  数: なし 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void cdrom_finish_load_files(void) 
{ 
	loading_screen_stop(); 
 
	// 終了状態のデータ書き込み 
	m68000_write_memory_8(0x108000 + 0x7e88, 0x00); 
	m68000_write_memory_8(0x108000 + 0x7ddd, 0x00); 
	m68000_write_memory_8(0x108000 + 0x76db, 0x01); 
	m68000_write_memory_8(0x108000 + 0x7ec4, 0x01); 
 
	m68000_write_memory_32(0x10f742, 0); 
	m68000_write_memory_32(0x10f746, 0); 
 
	m68000_write_memory_32(0x108000 + 0x768c, 0);	// ファイルのブロック数 
	m68000_write_memory_32(0x108000 + 0x7690, 0);	// 読み込み進行度 
	m68000_write_memory_32(0x108000 + 0x7694, 0);	// 読み込みセクタ数 
 
	m68000_write_memory_8(0x108000 + 0x7657, 0x00);	// CD-ROM読み込み中フラグ 
	m68000_write_memory_8(0x108000 + 0x76d9, 0x01); 
	m68000_write_memory_8(0x108000 + 0x76c3, 0x01);	// CDDAイネーブル 
	m68000_write_memory_8(0x108000 + 0x76f6, 0xff);	// CDDAコマンド1 
	m68000_write_memory_8(0x108000 + 0x764b, 0xff);	// CDDAトラック1 
 
	m68000_write_memory_8(0x108000 + 0x7ddc, 0x00);	// ロード画面の有無 
	m68000_write_memory_8(0x108000 + 0x7e85, 0xff); 
 
	m68000_write_memory_8(0x108000 + 0x7dc2, save2); 
	m68000_write_memory_8(0x108000 + 0x7d80, save1); 
} 
 
 
/*------------------------------------------------------ 
 
	CD-ROMからファイルを読み込みメモリに転送する 
 
	引  数: なし 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void cdrom_load_next_data(void) 
{ 
	struct filelist_t *file = &filelist[current_fileno]; 
 
	if (load_file(current_fileno) == 0) 
	{ 
		// 読み込み終了 
		current_fileno++; 
		file = &filelist[current_fileno]; 
 
		if (strlen(file->name) == 0) 
		{ 
			current_fileno = 0; 
			cdrom_loading_state = CDROM_DONE; 
		} 
	} 
} 
 
 
/*------------------------------------------------------ 
 
	CDのチェック 
 
	引  数: int drive チェックするドライブ 
	戻り値: game構造体のインデックス番号 
 
 
  ※ゲームを判別するためのものですが、一応簡易 
    コピー対策にもなってます。 
    丸ごとバックアップしたディスクの場合は問題なく 
    動いてしまうと思いますが、ISO + WAVで焼いたりした 
    場合は引っかかるかと。 
 
    判別だけなら固有のファイル名をチェックしたほうが 
    いいです。(かぶるものもありますが) 
 
 -----------------------------------------------------*/ 
 
int cdrom_verify_disc(int drive) 
{ 
	int i, j, num_tracks, cdda_status, index = -1; 
	UINT32 leadout; 
	UINT8 path[MAX_PATH]=""; 
	UINT32 length; 
 
	if (cdrom_drive_state[drive] & CDROM_NOTEXIST) 
	{ 
		// ドライブがCD-ROMドライブではない 
		return -1; 
	} 
 
	if ((cdda_status = osd_cdda_get_status()) == CDDA_NOTREADY) 
	{ 
		// 初期化していない場合は初期化する 
		if (osd_cdda_init(drive) == OSD_ERROR) 
		{ 
			// MCIを初期化できなかった 
//			LOG(("OSD_CDDA: could not initialize.\n")); 
			return -1; 
		} 
	} 
 
	// トラック数 
	num_tracks = osd_cdda_get_num_tracks(); 
 
	// リードアウトLBA 
	leadout = osd_cdda_get_track_lba(0); 
 
	i = 0; 
	while (games[i].name && index == -1) 
	{ 
		// トラック数を比較 
		if (games[i].cdrom->num_tracks == num_tracks) 
		{ 
			for (j = 0; j < games[i].cdrom->num_trackdata; j++) 
			{ 
				// リードアウトのLBAを比較 
				if (leadout == games[i].cdrom->tracks[j][0]) 
				{ 
					int track; 
					const UINT32 *tracks = games[i].cdrom->tracks[j]; 
 
					// 仮にゲーム番号を設定 
					index = i; 
 
					// 各トラックのLBAを比較 
					for (track = 1; track <= games[i].cdrom->num_tracks; track++) 
					{ 
						if (osd_cdda_get_track_lba(track) != tracks[track]) 
						{ 
							// トラック構造が違うのでNEOGEO CDのディスクではない 
							index = -1; 
							break; 
						} 
					} 
				} 
 
				if (index != -1) 
				{ 
					// NEOGEO CDのディスク 
					logerror("\"%s\" found.\n", games[index].name); 
					break; 
				} 
 
			} 
		} 
		i++; 
	} 
 
	if (index == -1) 
	{ 
		sprintf(path, "%c:\\IPL.TXT", drive+ 'A'); 
		length = osd_file_exist(path); 
		if (length != 0) 
		{ 
			index = 98; 
		} 
		else if (osd_cdda_has_audio_track()) 
		{ 
			// オーディオトラックがあればオーディオCD 
			index = -2; 
		} 
	} 
 
	if (cdda_status == CDDA_NOTREADY) 
	{ 
		// チェック開始時に初期化されてなかった場合は、CDDA処理を終了 
		osd_cdda_exit(); 
	} 
 
	return index; 
} 
 
 
/*************************************************************************** 
	ローカル関数 
 ***************************************************************************/ 
 
/*------------------------------------------------------ 
 
	CD-ROMからファイルを読み込みメモリに転送する 
 
	引  数: int fileno  ファイル番号 
	戻り値: 読み込んだデータ長 
 
 -----------------------------------------------------*/ 
 
static void upload_file(int fileno, offs_t offset, UINT32 length) 
{ 
	UINT8 *mem; 
	offs_t base; 
	struct filelist_t *file = &filelist[fileno]; 
 
	switch (file->type) 
	{ 
	case PRG_TYPE: 
	case AXX_TYPE: 
		mem = memory_region(REGION_CPU1); 
		swab(cdrom_cache, mem + file->offset + offset, length); 
		break; 
 
	case FIX_TYPE: 
		if (with_image()) 
		{ 
			offs_t offset1, offset2, start, end; 
			UINT32 length1, length2; 
 
			start = (file->offset >> 1) + offset; 
			end   = (start + length) - 1; 
 
			if (start >= 0x6000) 
			{ 
				offset1 = 0; 
				length1 = 0; 
				offset2 = start << 1; 
				length2 = length; 
			} 
			else if (end < 0x6000) 
			{ 
				offset1 = start << 1; 
				length1 = length; 
				offset2 = 0; 
				length2 = 0; 
			} 
			else 
			{ 
				offset1 = start << 1; 
				length1 = 0x6000 - start; 
				offset2 = 0x6000 << 1; 
				length2 = length - length1; 
			} 
 
			if (length1) 
			{ 
				mem = memory_region(REGION_CPU1) + 0x115e06; 
				memcpy(mem + (offset1 >> 1), cdrom_cache, length1); 
			} 
 
			if (length2) 
			{ 
				mem = memory_region(REGION_GFX1); 
				memcpy(mem + (offset2 >> 1), cdrom_cache + length1, length2); 
#if ENABLE_SYSTEM_CHECK 
				mem = memory_region(REGION_GFX5); 
				memcpy(mem + (offset2 >> 1), cdrom_cache + length1, length2); 
#endif 
				neogeo_decode_fix(mem, offset2, length2); 
			} 
		} 
		else 
		{ 
			mem = memory_region(REGION_GFX1); 
			base = file->offset >> 1; 
			memcpy(mem + base + offset, cdrom_cache, length); 
#if ENABLE_SYSTEM_CHECK 
			mem = memory_region(REGION_GFX5); 
			memcpy(mem + base + offset, cdrom_cache, length); 
#endif 
			neogeo_decode_fix(mem, file->offset + (offset << 1), length); 
		} 
		break; 
 
	case SPR_TYPE: 
		mem = memory_region(REGION_GFX2); 
		base = (file->bank << 20) + file->offset; 
		memcpy(mem + base + offset, cdrom_cache, length); 
#if ENABLE_SYSTEM_CHECK 
		mem = memory_region(REGION_GFX6); 
		memcpy(mem + base + offset, cdrom_cache, length); 
#endif 
		neogeo_decode_spr(mem, base + offset, length); 
		break; 
 
	case Z80_TYPE: 
		mem = memory_region(REGION_CPU2); 
		base = (file->bank << 16) + (file->offset >> 1); 
		memcpy(mem + base + offset, cdrom_cache, length); 
		break; 
 
	case PAT_TYPE: 
		swab(cdrom_cache, cdrom_cache, length); 
		neogeo_apply_patch((UINT16 *)cdrom_cache, file->bank, file->offset); 
		break; 
 
	case PCM_TYPE: 
		mem = memory_region(REGION_SOUND1); 
		base = (file->bank << 19) + (file->offset >> 1); 
		memcpy(mem + base + offset, cdrom_cache, length); 
		break; 
	} 
} 
 
 
/*------------------------------------------------------ 
 
	CD-ROMからファイルを読み込みメモリに転送する 
 
	引  数: int fileno  ファイル番号 
	戻り値: 読み込んだブロック数 
 
 -----------------------------------------------------*/ 
 
static int load_file(int fileno) 
{ 
	struct filelist_t *file = &filelist[fileno]; 
 
	if (file->next == 0) 
	{ 
		char path[MAX_PATH]; 
 
		osd_set_title("Loading %s", file->name); 
		logerror("loading: %s,%d,%06x\n", file->name, file->bank, file->offset); 
 
		sprintf(path, "%c:\\%s", cdrom_current_drive + 'A', file->name); 
 
		cdrom_fp = fopen(path, "rb"); 
		if (!cdrom_fp) 
		{ 
			logerror("CD-ROM: %s Could not open.\n", path); 
			return 0; 
		} 
 
		if (file->type == Z80_TYPE) 
			m68000_write_memory_8(0xff0183, 0x00); 
	} 
 
	if (options.cdspeed) 
	{ 
		int read_sectors = 1 << options.cdspeed; 
 
		if (file->sectors > read_sectors) 
		{ 
			UINT32 left = read_sectors; 
 
			while (left) 
			{ 
				if (file->length - file->next < 0x800) 
				{ 
					fread(cdrom_cache, file->length - file->next, 1, cdrom_fp); 
					upload_file(fileno, file->next, file->length - file->next); 
				} 
				else 
				{ 
					fread(cdrom_cache, 0x800, 1, cdrom_fp); 
					upload_file(fileno, file->next, 0x800); 
				} 
 
				file->next += 0x800; 
				file->sectors--; 
				left--; 
 
				loading_update_progress(); 
			} 
 
			return file->sectors; 
		} 
	} 
 
	while (file->sectors) 
	{ 
		if (file->length - file->next < 0x800) 
		{ 
			fread(cdrom_cache, file->length - file->next, 1, cdrom_fp); 
			upload_file(fileno, file->next, file->length - file->next); 
		} 
		else 
		{ 
			fread(cdrom_cache, 0x800, 1, cdrom_fp); 
			upload_file(fileno, file->next, 0x800); 
		} 
 
		file->next += 0x800; 
		file->sectors--; 
 
		loading_update_progress(); 
	} 
 
	fclose(cdrom_fp); 
	cdrom_fp = NULL; 
 
	if (file->type == Z80_TYPE) 
		m68000_write_memory_8(0xff0183, 0xff); 
 
	return file->sectors; 
} 
 
 
/*------------------------------------------------------ 
 
	読み込み進行度更新 
 
	引  数: なし 
	戻り値: 画面更新フラグ 
 
 -----------------------------------------------------*/ 
 
static void init_loading_progress(void) 
{ 
	m68000_write_memory_32(0x108000 + 0x7694, total_sectors); 
 
	total_sectors = ((0x8000 / total_sectors) << 8) | 0x80; 
 
	m68000_write_memory_32(0x108000 + 0x768c, total_sectors); 
	m68000_write_memory_32(0x108000 + 0x7690, 0); 
} 
 
 
/*------------------------------------------------------ 
 
	拡張子からデータの形式を判別 
 
	引  数: const char *ext 拡張子の文字列 
	戻り値: データ形式の番号 
 
 -----------------------------------------------------*/ 
 
static int get_filetype(const char *ext) 
{ 
	int type = UNKNOWN_TYPE; 
 
	if (strlen(ext) == 3) 
	{ 
		if (stricmp(ext, "PRG") == 0) type = PRG_TYPE; 
		if (stricmp(ext, "FIX") == 0) type = FIX_TYPE; 
		if (stricmp(ext, "SPR") == 0) type = SPR_TYPE; 
		if (stricmp(ext, "Z80") == 0) type = Z80_TYPE; 
		if (stricmp(ext, "PCM") == 0) type = PCM_TYPE; 
		if (stricmp(ext, "PAT") == 0) type = PAT_TYPE; 
		if (ext[0] == 'A') type = AXX_TYPE; 
	} 
 
	return type; 
}