📄 dos.c
字号:
#include "osd.h"
#include "uifont.h"
/* Display timing data */
volatile int frame_skip = 1;
volatile int frame_count = 0;
volatile int frames_rendered = 0;
volatile int frame_rate = 0;
volatile int tick_count = 0;
volatile int old_tick_count = 0;
volatile int skip = 0;
/* UI and feature data */
int exit_flag = 0;
int fg = 0;
int bg = 0;
volatile int msg_enable = 0;
FILE *music_log = NULL;
int music_log_count = 0;
int state_slot = 0;
int snap_count = 0;
char msg[0x100];
/* Blitter data */
BITMAP *sms_bmp = NULL;
PALETTE sms_pal;
/* Game file name */
char game_name[0x100];
/* CRTC parameters for 256x384 and 160x576 displays */
word twktbl[2][0x10] =
{
{ 0x4F00, 0x3F01, 0x4002, 0x9203, 0x4204, 0x1005, 0xAF06, 0x1F07,
0x4109, 0x8C10, 0x7E11, 0x7F12, 0x8615, 0xA916, 0x0063, 0x0101 },
{ 0x2D00, 0x2701, 0x2802, 0x9003, 0x2B04, 0x8005, 0x5306, 0xF007,
0x6309, 0x4010, 0xAC11, 0x3F12, 0x4015, 0x4A16, 0x0067, 0x0901 },
};
int main (int argc, char **argv)
{
/* Show version information if no arguments are specified */
if(argc < 2)
{
printf("\nSMS Plus\n");
printf("(C) Charles Mac Donald in 1998, 1999, 2000\n");
printf("Version %s, build date: %s, %s\n", VERSION, __DATE__, __TIME__);
printf("Usage: sp <filename.ext> [-options]\n");
printf("Type 'sp -help' for a summary of the available options\n");
exit(1);
}
/* Show option list */
if(stricmp(argv[1], "-help") == 0)
{
printf("Options:\n");
printf(" -vdriver <s> \t specify video driver.\n");
printf(" -res <x> <y> \t set the display resolution.\n");
printf(" -scale \t scale display to full resolution. (slow)\n");
printf(" -expand \t force 512x384 or 400x300 zoomed display.\n");
printf(" -nommx \t disable use of MMX instructions.\n");
printf(" -novga \t disable use of VGA vertical scaling with '-expand'.\n");
printf(" -depth <n> \t specify color depth. (8, 16)\n");
printf(" -blur \t blur display. (16-bit color only)\n");
printf(" -scanlines \t use scanlines effect.\n");
printf(" -tweak \t force 256x192 or 160x144 tweaked display.\n");
printf(" -vsync \t wait for vertical sync before blitting.\n");
printf(" -throttle \t limit updates to 60 frames per second.\n");
printf(" -sound \t enable sound. (auto-throttle)\n");
printf(" -sndrate <n> \t specify sound rate. (8000, 11025, 22050, 44100)\n");
printf(" -sndcard <n> \t specify sound card. (0-7)\n");
printf(" -joy <s> \t specify joystick type.\n");
printf(" -jp \t use Japanese console type.\n");
printf(" -fm \t required to enable YM2413 sound.\n");
exit(1);
}
/* Do configuration */
do_config("sp.cfg");
/* Make copy of game filename */
strcpy(game_name, argv[1]);
/* Attempt to load game off commandline */
if(load_rom(game_name) == 0)
{
printf("Error loading `%s'.\n", game_name);
exit(1);
}
/* Set up video, audio, input, etc. */
init_machine();
/* Initialize the virtual console emulation */
system_init(option.sound ? option.sndrate : 0);
sms.country = option.country;
sms.use_fm = option.fm_enable;
snd.callback = log_handler;
/* Load SRAM from disk if possible */
load_sram();
pick_blitter_proc();
if(blitter_proc == NULL)
{
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
printf("Illegal combination of parameters - not all options can be combined.\n");
exit(1);
}
/* Main emulation loop */
for(;;)
{
if(exit_flag) break;
/* Bump frame count */
frame_count += 1;
frames_rendered += 1;
skip = (frame_count % frame_skip == 0) ? 0 : 1;
/* Get current input */
update_input();
check_ui_keys();
/* Run the system emulation for a frame */
sms_frame(skip);
/* Update the display */
if(skip == 0)
{
update_audio();
update_video();
}
/* Speed throttling */
if(option.throttle)
{
while(tick_count == old_tick_count);
old_tick_count = tick_count;
}
}
save_sram();
system_shutdown();
trash_machine();
return (0);
}
/****************************************************************************/
/* Handles music log writing */
void log_handler(int data)
{
if(music_log) fputc(data, music_log);
}
/* Timer handler, runs at 60Hz */
void tick_handler(void)
{
tick_count += 1;
if(msg_enable) --msg_enable;
if(tick_count % FRAMES_PER_SECOND == 0)
{
frame_rate = frames_rendered;
frames_rendered = 0;
}
}
END_OF_FUNCTION(tick_handler);
/* Initialize machine dependant stuff */
void init_machine(void)
{
/* Set up sound hardware */
if(option.sound)
{
/* Initialize sound and update sample rate */
int ret = msdos_init_sound(&option.sndrate, option.sndcard);
/* Error - disable sound */
if(ret != 0) option.sound = 0;
}
/* Set up the Allegro library */
allegro_init();
/* Disable MMX usage if requested */
if(option.no_mmx == 1) cpu_mmx = 0;
/* Install input devices */
install_keyboard();
install_joystick(option.joy_driver);
/* Install tick handler */
install_timer();
LOCK_FUNCTION(tick_handler);
LOCK_VARIABLE(tick_count);
LOCK_VARIABLE(frame_rate);
LOCK_VARIABLE(frames_rendered);
LOCK_VARIABLE(msg_enable);
install_int_ex(tick_handler, BPS_TO_TIMER(FRAMES_PER_SECOND));
/* Change video settings if screen expansion is enabled */
if(option.expand)
{
option.video_driver = GFX_AUTODETECT;
option.video_width = (IS_GG) ? 400 : 512;
option.video_height = (IS_GG) ? 300 : 384;
}
/* Double requested height if scanlines are being used
and screen expansion is disabled */
if((option.scanlines == 1) && (option.expand == 0))
{
option.video_height *= 2;
}
/* Change video settings if tweaked display is enabled */
if(option.tweak)
{
option.video_driver = GFX_VGA;
option.video_depth = 8;
option.video_width = 320;
option.video_height = 200;
}
/* Attempt to set graphics mode */
set_color_depth(option.video_depth);
if(set_gfx_mode(option.video_driver, option.video_width, option.video_height, 0, 0) != 0)
{
printf("Error: %s\n", allegro_error);
exit(1);
}
/* Clear palette and display */
memcpy(sms_pal, black_palette, sizeof(PALETTE));
sms_pal[0xFE].r = sms_pal[0xFE].g = sms_pal[0xFE].b = 0xFF;
set_palette(sms_pal);
clear(screen);
/* Use vertical stretching if screen expansion is enabled,
VGA expansion is disabled, and scanlines are disabled */
if((option.expand == 1) && (option.no_vga == 0) && (option.scanlines == 0))
{
outp(0x3D4, 0x09);
outp(0x3D5, (inp(0x3D5) & 0xE0) | 0x03);
}
/* Force overscan color to be black */
if(option.video_depth == 8)
{
inp(0x3DA);
outp(0x3C0, 0x31);
outp(0x3C0, 0xFF);
clear_to_color(screen, 0xFF);
}
/* Tweak display accordingly */
if(option.tweak)
{
int i, j = IS_GG ? 1 : 0;
/* Disable CRTC write protect */
outp(0x3D4, 0x11);
outp(0x3D5, inp(0x3D5) & 0x7F);
/* Load CRTC parameters */
for(i = 0; i <= 0x0D; i += 1)
outpw(0x3D4, twktbl[j][i]);
/* Enable CRTC write protect */
outp(0x3D4, 0x11);
outp(0x3D5, inp(0x3D5) | 0x80);
/* Set clocking mode register */
outp(0x3C2, twktbl[j][0x0E]);
/* Set miscellaneous output register */
outpw(0x3C4, twktbl[j][0x0F]);
}
/* Allocate memory bitmap for blitting */
sms_bmp = create_bitmap_ex(option.video_depth, 256, 192);
clear(sms_bmp);
/* Set up bitmap structure */
memset(&bitmap, 0, sizeof(t_bitmap));
bitmap.width = sms_bmp->w;
bitmap.height = sms_bmp->h;
bitmap.depth = option.video_depth;
bitmap.pitch = (bitmap.width * (bitmap.depth >> 3));
bitmap.data = (unsigned char *)&sms_bmp->line[0][0];
/* Set up text printing */
text_mode(-1);
font = &zyrinx_font;
fg = (option.video_depth == 8) ? 0xFE : makecol(0xFF, 0xFF, 0xFF);
bg = (option.video_depth == 8) ? 0xFF : makecol(0x00, 0x00, 0x00);
}
/* Free system resources */
void trash_machine(void)
{
if(option.sound) msdos_shutdown_sound();
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
}
/* Debounce keyboard buttons */
int check_key(int code)
{
static int lastpressed = 0;
if((!key[code]) && (lastpressed == code))
lastpressed = 0;
if((key[code]) && (lastpressed != code))
{
lastpressed = code;
return (1);
}
return (0);
}
/* Update virtual console input */
void update_input(void)
{
/* Clear all button states */
memset(&input, 0, sizeof(t_input));
/* System buttons */
if(key[KEY_ENTER] || key[KEY_SPACE]) input.system |= (IS_GG) ? INPUT_START : INPUT_PAUSE;
if(check_key(KEY_DEL)) input.system |= INPUT_HARD_RESET;
if(check_key(KEY_TAB)) input.system |= (IS_GG) ? INPUT_HARD_RESET : INPUT_SOFT_RESET;
/* Player 1 buttons */
if(key[KEY_UP]) input.pad[0] |= INPUT_UP;
else
if(key[KEY_DOWN]) input.pad[0] |= INPUT_DOWN;
if(key[KEY_LEFT]) input.pad[0] |= INPUT_LEFT;
else
if(key[KEY_RIGHT]) input.pad[0] |= INPUT_RIGHT;
if(key[KEY_LCONTROL]) input.pad[0] |= INPUT_BUTTON2;
if(key[KEY_ALT]) input.pad[0] |= INPUT_BUTTON1;
/* Is the joystick being used ? */
if(option.joy_driver != JOY_TYPE_NONE)
{
poll_joystick();
/* Check player 1 joystick */
if(joy[0].stick[0].axis[1].d1) input.pad[0] |= INPUT_UP;
else
if(joy[0].stick[0].axis[1].d2) input.pad[0] |= INPUT_DOWN;
if(joy[0].stick[0].axis[0].d1) input.pad[0] |= INPUT_LEFT;
else
if(joy[0].stick[0].axis[0].d2) input.pad[0] |= INPUT_RIGHT;
if(joy[0].button[0].b) input.pad[0] |= INPUT_BUTTON2;
if(joy[0].button[1].b) input.pad[0] |= INPUT_BUTTON1;
if(joy[0].button[2].b) input.system |= (IS_GG) ? INPUT_START : INPUT_PAUSE;
/* More than one joystick supported ? */
if(num_joysticks > 2)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -