www.pudn.com > ngcd080s.zip > NEOCD.C


/************************************** 
****  NEOCD.C  - Main Source File  **** 
**************************************/ 
 
//-- Include Files ----------------------------------------------------------- 
#include  
#include  
#include  
#include  
#include  
#include  
#include "cdaudio/cdaudio.h" 
#include "cdrom/cdrom.h" 
#include "mc68000/68kregs.h" 
#include "memory/memory.h" 
#include "video/video.h" 
#include "config/config.h" 
#include "input/input.h" 
#include "input/macro.h" 
#include "gui/gui.h" 
#include "gui/rsc.h" 
#include "winlow/winlow.h" 
#include "cheats/cheats.h" 
#include "z80/z80intrf.h" 
#include "sound/stream.h" 
#include "ym2610/ym2610.h" 
#include "ym2610/adpcm.h" 
 
extern char *strcat(char *_s1, const char *_s2); 
 
// Cut off Allegro size... 
BEGIN_DIGI_DRIVER_LIST 
END_DIGI_DRIVER_LIST 
 
BEGIN_MIDI_DRIVER_LIST 
END_MIDI_DRIVER_LIST 
 
BEGIN_GFX_DRIVER_LIST 
	GFX_DRIVER_VESA3 
	GFX_DRIVER_VESA2L 
	GFX_DRIVER_VESA2B 
	GFX_DRIVER_VESA1 
END_GFX_DRIVER_LIST 
 
// Version, date & time to display on startup 
#define VERSION1 "NEOGEO-CD Emulator v0.80" 
#define VERSION2 "Compiled on: "__DATE__" "__TIME__ 
 
//-- Private variables ------------------------------------------------------- 
static int		cdda_was_playing = 0; 
 
//-- Global Variables -------------------------------------------------------- 
char			*neogeo_rom_memory = NULL; 
char			*neogeo_prg_memory = NULL; 
char			*neogeo_fix_memory = NULL; 
char			*neogeo_spr_memory = NULL; 
char			*neogeo_pcm_memory = NULL; 
 
char			global_error[80]; 
unsigned char	neogeo_memorycard[8192]; 
int				neogeo_prio_mode = 0; 
DATAFILE		*rsc; 
int				neogeo_ipl_done = 0; 
int				windows_present; 
int				windows_hostile_mode = 0; 
 
//-- 68K Core related stuff -------------------------------------------------- 
int					mame_debug = 0; 
char				*OP_ROM; 
char				*OP_RAM; 
int					previouspc = 0; 
int					ophw = 0; 
int					cur_mrhard = 0; 
extern int			MC68000_ICount; 
extern Registers68K	regs; 
extern void			M68KRESET(void);	// 68K core init, not reset 
extern int			M68KRUN(int); 
extern void			initialize_memmap(void); 
 
//-- Function Prototypes ----------------------------------------------------- 
void	neogeo_init(void); 
void	neogeo_reset(void); 
void	neogeo_hreset(void); 
void	neogeo_shutdown(void); 
void	MC68000_Cause_Interrupt(int); 
void	neogeo_exception(void); 
void	neogeo_run(void); 
void	draw_main(void); 
void	neogeo_quit(void); 
void	not_implemented(void); 
void	neogeo_machine_settings(void); 
void	neogeo_debug_mode(void); 
void	neogeo_cdda_check(void); 
void	neogeo_cdda_control(void); 
void	neogeo_do_cdda( int command, int trck_number_bcd); 
 
//-- Main screen buttons ----------------------------------------------------- 
typedef void (*CALLBACK)(void); 
 
typedef struct { 
	int			x1; 
	int			y1; 
	int			x2; 
	int			y2; 
	int			nrm; 
	int			sel; 
	CALLBACK	func; 
} MAIN_ITEM; 
 
MAIN_ITEM	main_buttons[] = { 
	{ 212, 101, 283, 114, BT_RUN1,    BT_RUN2,    neogeo_run }, 
	{ 212, 116, 283, 129, BT_VSETUP1, BT_VSETUP2, video_setup }, 
	{ 212, 131, 283, 144, BT_ASETUP1, BT_ASETUP2, audio_setup }, 
	{ 212, 146, 283, 159, BT_JSETUP1, BT_JSETUP2, joystick_setup }, 
	{ 212, 161, 283, 174, BT_KSETUP1, BT_KSETUP2, keyboard_setup }, 
	{ 212, 176, 283, 189, BT_SYSSET1, BT_SYSSET2, neogeo_machine_settings }, 
	{ 212, 191, 283, 204, BT_QUIT1,   BT_QUIT2,   neogeo_quit }, 
	{  36, 162, 106, 175, BT_MACRO1,  BT_MACRO2,  macrokeys_select}, 
	{  36, 177, 106, 190, BT_DEBUG1,  BT_DEBUG2,  neogeo_debug_mode}, 
	{  36, 192, 106, 205, BT_CHEATS1, BT_CHEATS2, cheat_select} 
}; 
 
#define NB_ELEMS	10 
 
char *nation_getter(int index, int *list_size) 
{ 
	static char *nats[] = 
	{ 
		"Japanese", "American", "European" 
	}; 
	 
	if (index < 0) 
	{ 
		*list_size = 3; 
		return NULL; 
	} 
	else 
		return nats[index]; 
} 
 
char *drive_getter(int index, int *list_size) 
{ 
	static char *aut = "Detect"; 
	static char *drv = "X:"; 
	 
	if (index < 0) 
	{ 
		*list_size = nb_of_drives + 1; 
		return NULL; 
	} 
	 
	if (index == 0) 
		return aut; 
	 
	drv[0] = drive_list[index-1] + 65; 
	 
	return drv; 
} 
 
 
DIALOG machine_settings[] = 
{ 
   /* (dialog proc)   (x)  (y)  (w)  (h)    (fg)    (bg)  (key)  (flags)   (d1)  (d2)            (dp) */ 
 {d_neo_border_proc,   0,   0, 170, 190, 0x0000, 0x0000,      0,      0,     0,    0,                NULL}, 
 {d_neo_fbox_proc,     2,   2, 166,   8, 0x0000, 0x10E3,      0,      0,     0,    0,                NULL}, 
 {d_text_proc,        10,   3,   0,   0, 0xFFFF, 0x10E3,      0,      0,     0,    0,  "Machine Settings"}, 
 
 {d_neo_gbox_proc,    10,  20, 150,  40, 0xC71C, 0x328A,      0,      0,     0,    0,       "Nationality"}, 
 {d_neo_list_proc,    15,  25, 140,  30, 0xC71C, 0x9596,      0,      0,     0,    0,       nation_getter}, 
 
 {d_neo_button_proc,  10,  65,  60,  15, 0x0000, 0x0000,    'r', D_EXIT,     0,    0,            "&Reset"}, 
 {d_neo_button_proc,  75,  65,  85,  15, 0x0000, 0x0000,    'f', D_EXIT,     0,    0,     "&Force Reload"}, 
 
 {d_neo_gbox_proc,    10,  90,  70,  50, 0xC71C, 0x328A,      0,      0,     0,    0,            "CD-ROM"}, 
 {d_neo_gbox_proc,    90,  90,  70,  50, 0xC71C, 0x328A,      0,      0,     0,    0,          "CD-Audio"}, 
 
 {d_neo_list_proc,    15,  95,  60,  40, 0xC71C, 0x9596,      0,      0,     0,    0,        drive_getter}, 
 {d_neo_list_proc,    95,  95,  60,  40, 0xC71C, 0x9596,      0,      0,     0,    0,        drive_getter}, 
 
 {d_neo_button_proc,  10, 145,  70,  15, 0x0000, 0x0000,      0, D_EXIT,     0,    0,            "Change"}, 
 {d_neo_button_proc,  90, 145,  70,  15, 0x0000, 0x0000,      0, D_EXIT,     0,    0,            "Change"}, 
 
 {d_neo_button_proc,  10, 170,  70,  15, 0x0000, 0x0000,    'a', D_EXIT,     0,    0,            "&About"}, 
 {d_neo_button_proc,  90, 170,  70,  15, 0x0000, 0x0000,    'o', D_EXIT,     0,    0,               "&OK"}, 
 
 {NULL,                0,   0,   0,   0, 0x0000, 0x0000,      0,      0,     1,    1,                NULL} 
}; 
 
DIALOG about_box[] = 
{ 
 {d_neo_border_proc,   0,   0, 250, 195, 0x0000, 0xFFFF,      0,      0,     0,    0,                NULL}, 
 {d_icon_proc,         5,   1, 205, 116, 0xFFFF, 0xFFFF,      0,     32,     0,    0,                NULL}, 
 {d_text_proc,         4, 119,   0,   0, 0xFFFF, 0x9596,      0,      0,     0,    0,            VERSION1}, 
 {d_text_proc,         4, 127,   0,   0, 0xFFFF, 0x9596,      0,      0,     0,    0,            VERSION2}, 
 {d_text_proc,		   4, 142,   0,   0, 0xFFFF, 0x9596,      0,      0,     0,    0,                NULL}, 
 {d_text_proc,		   4, 150,   0,   0, 0xFFFF, 0x9596,      0,      0,     0,    0,                NULL}, 
 {d_neo_button_proc,   4, 165, 100,  20, 0x0000, 0xFFFF,      0, D_EXIT,     0,    0,               "&OK"}, 
 {NULL,                0,   0,   0,   0, 0x0000, 0x0000,      0,      0,     0,    0,                NULL} 
}; 
 
DIALOG debug_dialog[] = 
{ 
   /* (dialog proc)   (x)  (y)  (w)  (h)    (fg)    (bg)  (key)  (flags)   (d1)  (d2)            (dp) */ 
 {d_neo_border_proc,   0,   0, 239, 204, 0x0000, 0x0000,      0,      0,     0,    0,                NULL}, 
 {d_neo_fbox_proc,     2,   2, 235,   8, 0x0000, 0x10E3,      0,      0,     0,    0,                NULL}, 
 {d_text_proc,        10,   3,   0,   0, 0xFFFF, 0x10E3,      0,      0,     0,    0,        "Debug Mode"}, 
  
 {d_neo_gbox_proc,    10,  20, 220, 157, 0xC71C, 0x328A,      0,      0,     0,    0,"Debug Mode Settings"}, 
 {d_neo_check_proc,   15,  29,  10,  10, 0xFFFF, 0x9596,    'a',      0,     0,    0,"&Activate Debug Mode (RESET)"}, 
 
 {d_text_proc,       100,  46,   0,   0, 0xFFFF, 0x9596,      0,      0,     0,    0,                 "1"}, 
 {d_text_proc,       114,  46,   0,   0, 0xFFFF, 0x9596,      0,      0,     0,    0,                 "2"}, 
 {d_text_proc,       128,  46,   0,   0, 0xFFFF, 0x9596,      0,      0,     0,    0,                 "3"}, 
 {d_text_proc,       142,  46,   0,   0, 0xFFFF, 0x9596,      0,      0,     0,    0,                 "4"}, 
 {d_text_proc,       156,  46,   0,   0, 0xFFFF, 0x9596,      0,      0,     0,    0,                 "5"}, 
 {d_text_proc,       170,  46,   0,   0, 0xFFFF, 0x9596,      0,      0,     0,    0,                 "6"}, 
 {d_text_proc,       184,  46,   0,   0, 0xFFFF, 0x9596,      0,      0,     0,    0,                 "7"}, 
 {d_text_proc,       198,  46,   0,   0, 0xFFFF, 0x9596,      0,      0,     0,    0,                 "8"}, 
  
 {d_text_proc,        15,  58,   0,   0, 0xFFFF, 0x9596,      0,      0,     0,    0,      "Dip Switch 1"}, 
 {d_neo_dip_sw,       95,  55, 112,  14, 0xFFFF, 0x9596,      0,      0,     0,    0,                NULL}, 
 {d_text_proc,        15,  78,   0,   0, 0xFFFF, 0x9596,      0,      0,     0,    0,      "Dip Switch 2"}, 
 {d_neo_dip_sw,       95,  75, 112,  14, 0xFFFF, 0x9596,      0,      0,     0,    0,                NULL}, 
 {d_text_proc,        15,  98,   0,   0, 0xFFFF, 0x9596,      0,      0,     0,    0,      "Dip Switch 3"}, 
 {d_neo_dip_sw,       95,  95, 112,  14, 0xFFFF, 0x9596,      0,      0,     0,    0,                NULL}, 
 {d_text_proc,        15, 118,   0,   0, 0xFFFF, 0x9596,      0,      0,     0,    0,      "Dip Switch 4"}, 
 {d_neo_dip_sw,       95, 115, 112,  14, 0xFFFF, 0x9596,      0,      0,     0,    0,                NULL}, 
 {d_text_proc,        15, 138,   0,   0, 0xFFFF, 0x9596,      0,      0,     0,    0,      "Dip Switch 5"}, 
 {d_neo_dip_sw,       95, 135, 112,  14, 0xFFFF, 0x9596,      0,      0,     0,    0,                NULL}, 
 {d_text_proc,        15, 158,   0,   0, 0xFFFF, 0x9596,      0,      0,     0,    0,      "Dip Switch 6"}, 
 {d_neo_dip_sw,       95, 155, 112,  14, 0xFFFF, 0x9596,      0,      0,     0,    0,                NULL}, 
  
 {d_neo_button_proc,  87, 183,  65,  15, 0x0000, 0x0000,    'o', D_EXIT,     0,    0,               "&OK"}, 
 
 {NULL,                0,   0,   0,   0, 0x0000, 0x0000,      0,      0,     0,    0,                NULL} 
}; 
 
//---------------------------------------------------------------------------- 
int	main(void) 
{ 
	MACROFILE	fm; 
	FILE		*fp; 
	int			result; 
	int			a, b; 
	 
	// Displays version number, date and time 
	puts(VERSION1); 
	puts(VERSION2); 
	 
	// Detect Windows 
    windows_present = winlow_is_windows_present(); 
	 
	if (windows_present) 
		puts ("\nRunning under Windows...\n"); 
	else 
		puts("\nRunning under DOS...\n"); 
 
	// Allocate needed memory buffers 
	 
	puts("NEOGEO: Allocating memory..."); 
 
	printf("PRG (2Mo) ... "); 
	neogeo_prg_memory = calloc(1, 2097152); 
	if (neogeo_prg_memory==NULL) { 
		puts("failed !"); 
		return 0; 
	} 
	puts("OK!"); 
 
	printf("SPR (4Mo) ... "); 
	neogeo_spr_memory = calloc(1, 4194304); 
	if (neogeo_spr_memory==NULL) { 
		puts("failed !"); 
		return 0; 
	} 
	puts("OK!"); 
	 
	printf("ROM (128k) ... "); 
	neogeo_rom_memory = calloc(1, 131072); 
	if (neogeo_rom_memory==NULL) { 
		puts("failed !"); 
		return 0; 
	} 
	puts("OK!"); 
 
	printf("FIX (128k) ... "); 
	neogeo_fix_memory = calloc(1, 131072); 
	if (neogeo_fix_memory==NULL) { 
		puts("failed !"); 
		return 0; 
	} 
	puts("OK!"); 
 
	printf("PCM (1Mo) ... "); 
	neogeo_pcm_memory = calloc(1, 1048576); 
	if (neogeo_pcm_memory==NULL) { 
		puts("failed !"); 
		return 0; 
	} 
	puts("OK!"); 
	 
	// Initialize Memory Mapping 
	initialize_memmap(); 
 
	// Initialise Allegro 
	install_allegro(SYSTEM_AUTODETECT, &errno, atexit); 
 
	// Read memory card 
	fp = fopen("memcard.bin", "rb"); 
	if (fp!=NULL) { 
		fread(neogeo_memorycard, 1, 8192, fp); 
		fclose(fp); 
	} 
 
	// Register exit procedure 
	atexit(neogeo_shutdown); 
	 
	set_config_file("neocd.cfg"); 
 
	// Disable Windows if requested 
	windows_hostile_mode = get_config_int(NULL, "windows_hostile", 0); 
	if ((windows_present)&&(windows_hostile_mode)) 
		winlow_disable_windows(); 
 
	// 16Bit color depth 
	set_color_depth(16); 
 
	// Install PM keyboard, mouse and timer handlers 
	install_keyboard();  
	install_mouse(); 
	install_timer(); 
 
	// Load and Initialize rsc Datafile 
	rsc = load_datafile("rsc.dat"); 
	if (rsc==NULL) 
	{ 
		puts("FATAL: Couldn't find ressource datafile RSC.DAT"); 
		exit(0); 
	} 
 
	// Get color correction value 
	gamma_correction = get_config_float(NULL, "gamma", 1.0); 
 
	// Video init 
	result = video_init(); 
	if (!result) 
	{ 
		video_mode = 0; 
		puts(global_error); 
		return 0; 
	} 
 
	// Correct RGB order 
    fixup_datafile(rsc); 
 
	// Setup font and mouse cursor 
	font = rsc[FNT].dat; 
	set_mouse_sprite(rsc[CURSOR].dat); 
	gui_fg_color = 0xFFFF; 
	gui_mg_color = 0xC71C; 
	gui_bg_color = 0x9596; 
 
	show_mouse(screen); 
 
	sound_device = get_config_int(NULL, "soundcard", -1); 
	// Sound init 
	YM2610Init(); 
 
	// Load BIOS 
	fp = fopen("neocd.bin", "rb"); 
	if (fp==NULL) { 
		neo_alert1("Fatal Error", NULL, "Could not load NEOCD.BIN", NULL, "&Abort", 'a'); 
		return 0; 
	} 
	fread(neogeo_rom_memory, 1, 131072, fp); 
	fclose(fp); 
	swab(neogeo_rom_memory, neogeo_rom_memory, 131072); 
 
	// Load startup RAM 
	fp = fopen("startup.bin", "rb"); 
	if (fp==NULL) { 
		neo_alert1("Fatal Error", NULL, "Could not load STARTUP.BIN.", NULL, "&Abort", 'a'); 
		return 0; 
	} 
	fread(neogeo_prg_memory + 0x10F300, 1, 3328, fp); 
	fclose(fp); 
	swab(neogeo_prg_memory + 0x10F300, neogeo_prg_memory + 0x10F300, 3328); 
 
	// Check BIOS validity 
	if (*((short*)(neogeo_rom_memory+0xA822)) != 0x4BF9) 
	{ 
		neo_alert1("Fatal Error", NULL, "Invalid BIOS file.", NULL, "&Abort", 'a'); 
		return 0; 
	} 
 
	/*** Patch BIOS exit ***/ 
	*((short*)(neogeo_rom_memory+0x55e)) = 0xFABE; 
	*((short*)(neogeo_rom_memory+0x560)) = 0x4E75; 
	/*** Patch BIOS load files w/ now loading message ***/ 
	*((short*)(neogeo_rom_memory+0x552)) = 0xFABF; 
	*((short*)(neogeo_rom_memory+0x554)) = 0x4E75; 
	/*** Patch BIOS load files w/out now loading ***/ 
	*((short*)(neogeo_rom_memory+0x564)) = 0xFAC0; 
	*((short*)(neogeo_rom_memory+0x566)) = 0x4E75; 
	/*** Patch BIOS CDROM Check ***/ 
	*((short*)(neogeo_rom_memory+0xB040)) = 0x4E71; 
	*((short*)(neogeo_rom_memory+0xB042)) = 0x4E71; 
	/*** Patch BIOS upload command ***/ 
	*((short*)(neogeo_rom_memory+0x546)) = 0xFAC1; 
	*((short*)(neogeo_rom_memory+0x548)) = 0x4E75; 
 
	/*** Patch BIOS CDDA check ***/ 
	*((short*)(neogeo_rom_memory+0x56A)) = 0xFAC3; 
	*((short*)(neogeo_rom_memory+0x56C)) = 0x4E75; 
 
	/*** Full reset, please ***/ 
	*((short*)(neogeo_rom_memory+0xA87A)) = 0x4239; 
	*((short*)(neogeo_rom_memory+0xA87C)) = 0x0010; 
	*((short*)(neogeo_rom_memory+0xA87E)) = 0xFDAE; 
 
	/*** Trap exceptions ***/ 
	*((short*)(neogeo_rom_memory+0xA5B6)) = 0x4AFC; 
 
	// Initialize Macros 
	macro_init(); 
	 
	// Install joystick(s) 
	load_joystick_data(NULL); 
 
	// Read config files 
	config_read(); 
 
	// Initialize CD-DA 
	cdda_current_drive = cdrom_current_drive; 
	result = cdda_init(); 
	puts(global_error); 
	if (!result) 
		return 0; 
	cdrom_current_drive = cdda_current_drive; 
 
	// CD-ROM init 
	result = cdrom_init(); 
	if (!result) 
	{ 
		neo_alert1("Fatal Error", NULL, global_error, NULL, "&Abort", 'a'); 
		return 0; 
	} 
 
	// Get sound volume 
	sound_vol = get_config_int(NULL, "soundvol", 255); 
	 
	// Initialize everything 
	neogeo_init(); 
	draw_main(); 
	 
	// GUI main loop 
	while(1) 
	{	 
		while( !mouse_b&&!keypressed() ); 
 
		b = -1; 
 
		// Check shortcut keys 
		if (keypressed()) 
		{ 
			a = readkey()&0xDF; 
			 
			switch(a) 
			{ 
				case 'R': 
					b = 0; 
					break; 
				case 'V': 
					b = 1; 
					break; 
				case 'A': 
					b = 2; 
					break; 
				case 'J': 
					b = 3; 
					break; 
				case 'K': 
					b = 4; 
					break; 
				case 'S': 
					b = 5; 
					break; 
				case 'Q': 
					b = 6; 
					break; 
				case 'M': 
					b = 7; 
					break; 
				case 'D': 
					b = 8; 
					break; 
				case 'C': 
					b = 9; 
					break; 
			} 
 
			if (b>=0) 
			{ 
				scare_mouse(); 
				blit(rsc[main_buttons[b].sel].dat, screen, 0, 0, main_buttons[b].x1, main_buttons[b].y1, 71, 13); 
				unscare_mouse(); 
			}		 
		} 
		else 
		{ 
			for(a=0;a=main_buttons[a].x1)&&(mouse_x<=main_buttons[a].x2)&& 
					(mouse_y>=main_buttons[a].y1)&&(mouse_y<=main_buttons[a].y2)) 
				{ 
					b = a; 
					scare_mouse(); 
					blit(rsc[main_buttons[a].sel].dat, screen, 0, 0, main_buttons[a].x1, main_buttons[a].y1, 71, 13); 
					unscare_mouse(); 
					while( mouse_b ); 
					break; 
				} 
			} 
		} 
	 
		// Call associated function 
		if (b>=0) 
		{ 
			main_buttons[b].func(); 
			vsync(); 
			draw_main(); 
		} 
	} 
} 
 
//---------------------------------------------------------------------------- 
void	neogeo_init(void) 
{ 
	M68KRESET(); 
} 
 
//---------------------------------------------------------------------------- 
void	neogeo_hreset(void) 
{ 
	FILE	*fp; 
 
	// Read game name (used in macro system) 
	config_read_name(); 
	strtrim(config_game_name, config_game_name); 
 
	// Special patch 
	if (strcmp(config_game_name, "TEST PROGRAM USA") == 0) 
	{ 
		fp = fopen("patch.prg", "rb"); 
		fread(neogeo_prg_memory + 0x132000, 1, 112, fp); 
		fclose(fp); 
		swab(neogeo_prg_memory + 0x132000, neogeo_prg_memory + 0x132000, 112); 
	} 
 
	// First time init 
	memset((void *)®s, 0, sizeof(regs)); 
	regs.pc = 0xc0a822; 
	regs.sr = 0x2700; 
	regs.sr_h = 0x27; 
	regs.a7 = regs.isp = regs.usp = 0x10F300; 
	OP_ROM = neogeo_rom_memory - 0xC00000; 
	MC68000_ICount = 0; 
	cpu_writemem24_dword(0x10F6EE, cpu_readmem24_dword(0x68L)); // $68 *must* be copied at 10F6EE 
 
	if (cpu_readmem24(0x107)&0x7E) 
	{ 
		if (cpu_readmem24_word(0x13A)) 
		{ 
			cpu_writemem24_dword(0x10F6EA, (cpu_readmem24_word(0x13A)<<1) + 0xE00000); 
		} 
		else 
		{ 
			cpu_writemem24_dword(0x10F6EA, 0); 
			cpu_writemem24(0x00013B, 0x01); 
		} 
	} 
	else 
		cpu_writemem24_dword(0x10F6EA, 0xE1FDF0); 
 
	 
	cdda_current_track = 0; 
	cdda_get_disk_info(); 
	z80_init(); 
}	 
 
//---------------------------------------------------------------------------- 
void	neogeo_reset(void) 
{ 
	memset((void *)®s, 0, sizeof(regs)); 
	regs.pc = 0x122; 
	regs.sr = 0x2700; 
	regs.sr_h = 0x27; 
	regs.a7 = regs.isp = regs.usp = 0x10F300; 
	OP_ROM = neogeo_prg_memory; 
	MC68000_ICount = 0; 
	cpu_writemem24(0x10FD80, 0x82); 
	cpu_writemem24(0x10FDAF, 0x01); 
	cpu_writemem24(0x10FEE1, 0x0A); 
	cpu_writemem24(0x10F675, 0x01); 
	cpu_writemem24(0x10FEBF, 0x00); 
	cpu_writemem24_dword(0x10FDB6, 0); 
	cpu_writemem24_dword(0x10FDBA, 0); 
	 
	cdda_current_track = 0; 
	z80_init(); 
} 
 
//---------------------------------------------------------------------------- 
void	neogeo_shutdown(void) 
{ 
	FILE	*fp; 
	 
	// Close everything and free memory 
 
	if ((windows_present)&&(windows_hostile_mode)) 
		winlow_enable_windows(); 
 
	if (sound_device != -1) 
		YM2610Shutdown(); 
 
	unload_datafile(rsc); 
 
	cdda_shutdown(); 
	cdrom_shutdown(); 
	video_shutdown(); 
 
	allegro_exit(); 
 
	puts("NEOGEO: System Shutdown."); 
 
	fp = fopen("memcard.bin", "wb"); 
	fwrite(neogeo_memorycard, 1, 8192, fp); 
	fclose(fp); 
 
/*	fp = fopen("C:\\TMP\\Z80MEM.LOG", "wb"); 
	fwrite(subcpu_memspace, 1, 65536, fp); 
	fclose(fp); 
 
	fp = fopen("C:\\TMP\\PCMMEM.PCM", "wb"); 
	fwrite(neogeo_pcm_memory, 1, 1048576, fp); 
	fclose(fp);*/ 
 
	free(neogeo_prg_memory); 
	free(neogeo_rom_memory); 
	free(neogeo_spr_memory); 
	free(neogeo_fix_memory); 
} 
 
//---------------------------------------------------------------------------- 
void	neogeo_exception(void) 
{ 
	// Users should never see this message ! 
	 
	video_set_mode(VIDEO_TEXT); 
	printf("NEOGEO: Exception Trapped at %08x !\n", previouspc); 
	exit(0); 
}	 
 
//---------------------------------------------------------------------------- 
void MC68000_Cause_Interrupt(int level) 
{ 
	if (level >= 1 && level <= 7) 
        regs.irq |= 1 << (level-1); 
} 
 
//---------------------------------------------------------------------------- 
void	neogeo_exit(void) 
{ 
	video_set_mode(VIDEO_TEXT); 
	puts("NEOGEO: Exit requested by software..."); 
	exit(0); 
} 
 
//---------------------------------------------------------------------------- 
void	neogeo_run(void) 
{ 
	int	i; 
 
	// If IPL.TXT not loaded, load it ! 
	if (!neogeo_ipl_done) 
	{ 
		// Display Title 
		cdrom_load_title(); 
 
		// Process IPL.TXT 
		if (!cdrom_process_ipl()) { 
			neo_alert1("Error", NULL, "Error while processing IPL.TXT.", NULL, "&Abort", 'a'); 
			return; 
		} 
		 
		// Reset everything 
		neogeo_ipl_done = 1; 
		neogeo_hreset(); 
 
		cheats_enable = 0; 
		for(i=0;i<16;i++) 
		{ 
			cheat_list[i].cheat_name[0] = 0; 
			cheat_list[i].cheat_code = 0; 
			cheat_list[i].cheat_enable = 0; 
		} 
 
	} 
 
	// Remove Allegro mouse & timers 
	remove_mouse(); 
	remove_timer(); 
	 
	// Display Opaque Text 
	text_mode(0); 
	 
	// Change display mode 
	if (config_scanlines) 
		video_set_mode(VIDEO_SCANLINES); 
	else 
		clear(screen); 
 
	// Resume cdda if it was playing 
	if ((cdda_current_track != 0)&&(cdda_was_playing)) 
		cdda_resume(); 
		 
	// Set sound volume 
	ASetAudioMixerValue(AUDIO_MIXER_MASTER_VOLUME, sound_vol); 
 
	MC68000_ICount = 0; 
 
	// Main loop 
	while(!key[KEY_TILDE]) 
	{ 
		// Execute Z80 timeslice (one VBL) 
		mz80int(0); 
		mz80exec(z80_cycles); 
		z80_cycles = Z80_VBL_CYCLES; 
 
		// One-vbl timeslice 
		MC68000_ICount += 200000; 
		M68KRUN(0); 
		MC68000_Cause_Interrupt(2); 
 
		// Apply cheats 
		if (cheats_enable) 
		{ 
			for(i=0;i<15;i++) 
			{ 
				if (cheat_list[i].cheat_enable) 
				{ 
					if (cheat_list[i].cheat_type == 0 ) 
					{ 
						cpu_writemem24( 0x100000 + 
							((cheat_list[i].cheat_code>>16)&0xFFFF), 
							cheat_list[i].cheat_code&0xFF); 
					} 
					else 
					{ 
						cpu_writemem24_word( 0x100000 + 
							((cheat_list[i].cheat_code>>16)&0xFFFF), 
							cheat_list[i].cheat_code&0xFFFF); 
					} 
				} 
			} 
		} 
			 
		// Check if there are pending commands for CDDA 
		neogeo_cdda_check(); 
 
		// Poll joystick 
		poll_joystick(); 
	 
		if (sound_device != 0) 
		{ 
			// Update audio channels 
			for(i=0;i<6;i++) 
				adpcm_ch_decodea(&adpcm_ch[i]); 
 
			adpcm_ch_decodeb(&adpcm_ch[6]); 
		} 
 
		// Call appropriate display routine 
		if (neogeo_prio_mode) 
			video_draw_screen2(); 
		else 
			video_draw_screen1(); 
 
		cdda_loop_check(); 
 
		if (key[KEY_F12]) 
			video_save_snapshot(); 
	} 
 
	// Save current state and return to menu 
	cdda_was_playing = cdda_playing; 
 
	// Clear audio buffers 
	sound_mute(); 
 
	// Stop CDDA 
	if (cdda_playing) 
		cdda_stop(); 
 
	clear_keybuf(); 
	install_timer(); 
	install_mouse(); 
	video_set_mode(VIDEO_NORMAL); 
 
	set_mouse_sprite(rsc[CURSOR].dat); 
	show_mouse(screen); 
} 
 
//---------------------------------------------------------------------------- 
// This is a really dirty hack to make SAMURAI SPIRITS RPG work 
void	neogeo_prio_switch(void) 
{ 
//	video_set_txt_mode(); 
//	debug_dump_regs(); 
//	clear_keybuf(); 
//	readkey(); 
//	video_set_gfx_mode(); 
	 
	if (regs.d7 == 0xFFFF) 
		return; 
	 
	if ((regs.d7==9)&&(regs.a3==0x10DED9)&&((regs.a2==0x1081d0)||((regs.a2&0xFFF000)==0x102000))) 
	{ 
		neogeo_prio_mode = 0; 
		return; 
	} 
	 
	if ((regs.d7==8)&&(regs.a3==0x10DEC7)&&(regs.a2==0x102900)) 
	{ 
		neogeo_prio_mode = 0; 
		return; 
	} 
	 
	if (regs.a7 == 0x10F29C) 
	{ 
		if ((regs.d4&0x4010)==0x4010) 
		{ 
			neogeo_prio_mode = 0; 
			return; 
		} 
		 
		neogeo_prio_mode = 1; 
	} 
	else 
	{ 
		if (regs.a3==0x5140) 
		{ 
			neogeo_prio_mode = 1; 
			return; 
		} 
 
		if ( (regs.a3&~0xF) == (regs.a4&~0xF) ) 
			neogeo_prio_mode = 1; 
		else 
			neogeo_prio_mode = 0; 
	} 
} 
 
//---------------------------------------------------------------------------- 
void	draw_main(void) 
{ 
	int	i; 
	 
	scare_mouse(); 
	 
	blit(rsc[MAIN].dat, screen, 0, 0, 0, 0, 320, 240); 
	 
	if (neogeo_ipl_done) 
		blit(game_title, screen, 0, 0, 35, 30, 144, 80); 
 
	for(i=0;i2) 
		temp = 2; 
	machine_settings[4].d1 = temp; 
 
	do 
	{ 
		vsync(); 
		ret = do_dialog(machine_settings, 4); 
 
		if (machine_settings[4].d1 != temp) 
		{ 
			fp = fopen("startup.bin", "rb"); 
			if (fp==NULL) 
				neo_alert1("Error", NULL, "Could not load STARTUP.BIN.", NULL, "&Abort", 'a'); 
			else 
			{ 
				temp = machine_settings[4].d1; 
				set_config_int(NULL, "nationality", temp); 
				fread(neogeo_prg_memory + 0x10F300, 1, 3328, fp); 
				fclose(fp); 
				swab(neogeo_prg_memory + 0x10F300, neogeo_prg_memory + 0x10F300, 3328); 
				cpu_writemem24(0x10FD83, temp); 
				neogeo_ipl_done = 0; 
			} 
		} 
 
		if (ret == 5) 
			neogeo_reset(); 
		 
		if (ret == 6) 
			neogeo_ipl_done = 0; 
			 
		if (ret == 11) 
		{ 
			if (machine_settings[9].d1 == 0) 
			{ 
				cdrom_current_drive = drive_list[0]; 
				set_config_int(NULL, "cdrom", -1); 
			} 
			else 
			{ 
				cdrom_current_drive = drive_list[machine_settings[9].d1 - 1]; 
				set_config_int(NULL, "cdrom", drive_list[machine_settings[9].d1 - 1]); 
			} 
			 
			neogeo_ipl_done = 0; 
		} 
	 
		if (ret == 12) 
		{ 
			cdda_current_track = 0; 
			if (machine_settings[10].d1 == 0) 
			{ 
				cdda_current_drive = drive_list[0]; 
				set_config_int(NULL, "cdaudio", -1); 
			} 
			else 
			{ 
				cdda_current_drive = drive_list[machine_settings[10].d1 - 1]; 
				set_config_int(NULL, "cdaudio", drive_list[machine_settings[10].d1 - 1]); 
			} 
			 
			cdda_get_disk_info(); 
		} 
 
		if (ret == 13) 
		{ 
			char	info1[40]; 
			char	info2[40]; 
			 
			about_box[1].dp = rsc[NGCD].dat; 
			about_box[1].dp2 = rsc[NGCD].dat; 
 
			sprintf(info1, "Allegro version : %s", ALLEGRO_VERSION_STR); 
			sprintf(info2, "Your CPU : %d86", cpu_family); 
			 
			if (cpu_fpu) 
				strcat(info2, " / FPU"); 
			 
			if (cpu_mmx) 
				strcat(info2, " / MMX"); 
				 
			if (cpu_3dnow) 
				strcat(info2, " / 3DNow!"); 
 
			about_box[4].dp = info1; 
			about_box[5].dp = info2; 
			 
			CENTRE_ITEM(about_box, 1, about_box[1].w); 
			CENTRE_ITEM(about_box, 2, gui_strlen(VERSION1)); 
			CENTRE_ITEM(about_box, 3, gui_strlen(VERSION2)); 
			CENTRE_ITEM(about_box, 4, gui_strlen(info1)); 
			CENTRE_ITEM(about_box, 5, gui_strlen(info2)); 
			CENTRE_ITEM(about_box, 6, about_box[6].w); 
 
			centre_dialog(about_box); 
			popup_dialog(about_box, 0); 
		}			 
	} while( ret != 14 ); 
} 
 
//---------------------------------------------------------------------------- 
void neogeo_debug_mode(void) 
{ 
	int 			ret; 
	unsigned int	addr; 
	unsigned int    temp; 
 
	if (!neogeo_ipl_done) 
	{ 
		neo_alert1("Error", NULL, "This function is useless without a game loaded.", NULL, "&Abort", 'a'); 
		return; 
	} 
 
	centre_dialog(debug_dialog); 
 
	addr = cpu_readmem24_dword( 0x10E ); 
	 
	debug_dialog[14].d1 = cpu_readmem24( addr ); 
	debug_dialog[16].d1 = cpu_readmem24( addr + 1 ); 
	debug_dialog[18].d1 = cpu_readmem24( addr + 2 ); 
	debug_dialog[20].d1 = cpu_readmem24( addr + 3 ); 
	debug_dialog[22].d1 = cpu_readmem24( addr + 4 ); 
	debug_dialog[24].d1 = cpu_readmem24( addr + 5 ); 
	 
    temp = debug_dialog[4].flags; 
 
	vsync(); 
	ret = do_dialog(debug_dialog, 4); 
	 
    if (debug_dialog[4].flags != temp) 
    { 
            if (debug_dialog[4].flags&D_SELECTED) 
            { 
                    neogeo_hreset(); 
                    cpu_writemem24( 0x10FE80, 0xFF ); 
                    cpu_writemem24( 0x10FDAE, 0x00 ); 
            } 
            else 
            { 
                    cpu_writemem24( 0x10FE80, 0x00 ); 
            } 
    } 
 
	cpu_writemem24( addr, 		debug_dialog[14].d1 ); 
	cpu_writemem24( addr + 1,	debug_dialog[16].d1 ); 
	cpu_writemem24( addr + 2,	debug_dialog[18].d1 ); 
	cpu_writemem24( addr + 3,	debug_dialog[20].d1 ); 
	cpu_writemem24( addr + 4,	debug_dialog[22].d1 ); 
	cpu_writemem24( addr + 5,	debug_dialog[24].d1 );	 
} 
 
//---------------------------------------------------------------------------- 
void neogeo_cdda_check(void) 
{ 
	int		Offset; 
	 
	Offset = cpu_readmem24_dword(0x10F6EA); 
	if (Offset < 0xE00000)	// Invalid addr 
		return; 
 
	Offset -= 0xE00000; 
	Offset >>= 1; 
	 
	neogeo_do_cdda(subcpu_memspace[Offset], subcpu_memspace[Offset+1]); 
} 
 
//---------------------------------------------------------------------------- 
void neogeo_cdda_control(void) 
{ 
	neogeo_do_cdda( (regs.d0>>8)&0xFF, regs.d0&0xFF ); 
} 
 
//---------------------------------------------------------------------------- 
void neogeo_do_cdda( int command, int track_number_bcd) 
{ 
	FILE	*fp; 
	int		track_number; 
	int		offset; 
 
	if ((command == 0)&&(track_number_bcd == 0)) 
		return; 
 
/*	fp = fopen("C:\\TMP\\CDDA.LOG", "at"); 
	fprintf(fp, "%02x %02x\n", command, track_number_bcd); 
	fclose(fp);*/ 
 
	cpu_writemem24(0x10F64B, track_number_bcd); 
	cpu_writemem24(0x10F6F8, track_number_bcd); 
	cpu_writemem24(0x10F6F7, command); 
	cpu_writemem24(0x10F6F6, command); 
 
	offset = cpu_readmem24_dword(0x10F6EA); 
 
	if (offset) 
	{ 
		offset -= 0xE00000; 
		offset >>= 1; 
 
		cpu_writemem24(0x10F678, 1); 
 
		subcpu_memspace[offset] = 0; 
		subcpu_memspace[offset+1] = 0; 
	} 
 
	switch( command ) 
	{ 
		case	0: 
		case	1: 
		case	5: 
		case	4: 
		case	3: 
		case	7: 
			track_number = ((track_number_bcd>>4)*10) + (track_number_bcd&0x0F); 
			if ((track_number == 0)&&(!cdda_playing)) 
			{ 
				sound_mute(); 
				cdda_resume(); 
			} 
			else if ((track_number>1)&&(track_number<99)) 
			{ 
				sound_mute(); 
				cdda_play(track_number); 
				cdda_autoloop = !(command&1); 
			} 
			break; 
		case	6: 
		case	2: 
			if (cdda_playing) 
			{ 
				sound_mute(); 
				cdda_stop(); 
			} 
			break; 
	} 
}