/* * SYSTEM 16 ARCADE EMULATOR SOURCE CODE * * Copyright 1996/97 Thierry Lescot */ #include #include "cpudefs.h" #define FADE_SPEED 16 #define SHINOBI_NUMBER 1 #define EMULATOR_VERSION 0x0051 extern char game_basename[9]; extern char game, joy, joystick_support, ws[80], joydef[4]; extern UBYTE vid_bank, txt_bank, ext_bank, pal_bank; extern int sx, sy, svga; PALLETE menu_save_palette; RGB pal[256]; int int_value, screen_update; extern BITMAP *vscreen; extern int keydef[40]; extern UBYTE shinobi_ds1[10], shinobi_ds2[10], reset_palette; extern UBYTE Palette256[0x1000]; BITMAP *save_screen, *save_screen_2; char *b1[6]= {"ATTACK","PUNCH","-","LEFT FLIPPER","-","JUMP"}; char *b2[6]= {"JUMP","KICK","-","RIGHT FLIPPER","-","MAGIC"}; char *b3[6]= {"MAGIC","JUMP","-","-","-","ATTACK"}; struct { char ok; char description[20]; } savegame_list[10]; void Outline_Text(int y, int c, char *str) { int dx, dy; text_mode(-1); for (dx=-1;dx!=2;dx++) for (dy=-1;dy!=2;dy++) textout_centre(screen, font, str, 160+dx, y+dy, 4); textout_centre(screen, font, str, 160, y, c); text_mode(0); } void OutlineXY_Text(int x, int y, int c, char *str) { int dx, dy; text_mode(-1); for (dx=-1;dx!=2;dx++) for (dy=-1;dy!=2;dy++) textout(screen, font, str, x+dx, y+dy, 4); textout(screen, font, str, x, y, c); text_mode(0); } void GetTextGfx(char *caption, char *p, int lm) { int pos=0, key; int l=strlen(p); int px=(300-(lm*10))/2; int py=100; int w=(10*lm)+20; char one_char[2] = {0,0}; blit(screen, save_screen_2, 0, 0, 0, 0, 320, 240); rectfill(screen, px, py, px+w, py+28, 8); rect(screen, px, py, px+w, py+28, 4); Outline_Text(py+3, 2, caption); do { if (pos!=lm) rectfill(screen, px+10+(pos*10), py+15, px+18+(pos*10), py+23, 5); key=(readkey()&0x00FF); if (pos!=lm) { rectfill(screen, px+10+(pos*10), py+15, px+18+(pos*10), py+23, 8); if ((key>='a')&&(key<='z')) key-=32; if (((key>='A')&&(key<='Z'))|| ((key>='0')&&(key<='9'))||(key==' ')) { p[pos]=key; one_char[0]=key; OutlineXY_Text(px+11+(pos*10), py+16, 1, one_char); pos++; p[pos]=0; } } if ((key==8)&&(pos)) { pos--; p[pos]=0; } } while (key!=13); blit(save_screen_2, screen, 0, 0, 0, 0, 320, 240); } void Message(char *txt, int c, int p) { int w=((text_length(font, txt)/2)+20); blit(screen, save_screen, 0, 0, 0, 0, 320, 240); rectfill(screen, 160-w, 106, 160+w, 134, 7); rect(screen, 160-w, 106, 160+w, 134, 4); Outline_Text(117, c, txt); if (p) { clear_keybuf(); while (!keypressed()); clear_keybuf(); } else { rest(1500); } blit(save_screen, screen, 0, 0, 0, 0, 320, 240); } void Message_NoPause(char *txt, int c) { int w=((text_length(font, txt)/2)+20); rectfill(screen, 160-w, 106, 160+w, 134, 7); rect(screen, 160-w, 106, 160+w, 134, 4); Outline_Text(117, c, txt); } void Hide_Screen(char *titre) { fade_out(FADE_SPEED); clear(screen); Outline_Text(10, 3, "THE SEGA SYSTEM 16 EMULATOR v0.53"); Outline_Text(30, 3, titre); } void Show_Screen() { fade_in(pal, FADE_SPEED); } void Draw_Main_Menu() { Hide_Screen("SETUP MENU"); Outline_Text(50, 2, "F1 - SETUP KEYBOARD"); Outline_Text(90, 2, "F3 - SETUP DIP SWITCHS"); Outline_Text(110,2, "F5 - SAVE CURRENT GAME TO DISK"); Outline_Text(130,2, "F6 - LOAD GAME STORED ON DISK"); Outline_Text(150,2, "F8 - SAVE CURRENT CONFIG"); Outline_Text(180,2, "F10 - RESET THE GAME"); Outline_Text(210,1, "ESC - QUIT SETUP MENU"); Show_Screen(); } void Get_New_Key(int key_number, char *key_name) { int ok=1, scancode, i; clear_keybuf(); rectfill(screen, 0, 115, 319, 132, 0); do { Outline_Text(124, 5, key_name); scancode=0; do { if (keypressed()) scancode=(readkey()>>8); if (key[KEY_CONTROL]) scancode=KEY_CONTROL; if (key[KEY_ALT]) scancode=KEY_ALT; } while (!scancode); if (key_number) { ok=1; for (i=0;i!=key_number;i++) { if (keydef[i]==scancode) { Message("THIS IS ALREADY USED", 6, 0); ok=0; continue; } } } while (key[keydef[key_number]]); clear_keybuf(); } while (!ok); keydef[key_number]=scancode; } void Setup_KB(int t, char *texte) { Hide_Screen(texte); Outline_Text(100, 2, "PRESS THE KEY FOR"); Show_Screen(); switch (t) { case 0: Get_New_Key(0, "1P START"); Get_New_Key(1, "2P START"); Get_New_Key(2, "COIN SLOT 1"); Get_New_Key(3, "COIN SLOT 2"); Get_New_Key(4, "SERVICE"); Get_New_Key(5, "TEST"); break; case 6: case 20: switch (game) { case 2: Get_New_Key(t, "PUCH"); Get_New_Key(t+1, "KICK"); Get_New_Key(t+2, "JUMP"); Get_New_Key(t+3, "UP"); Get_New_Key(t+4, "DOWN"); Get_New_Key(t+5, "LEFT"); Get_New_Key(t+6, "RIGHT"); break; case 4: Get_New_Key(t, "LEFT FLIPPER"); Get_New_Key(t+1, "RIGHT FLIPPER"); keydef[t+2]=127; Get_New_Key(t+3, "FRONT PUSH SWITCH"); keydef[t+4]=127; Get_New_Key(t+5, "LEFT PUSH SWITCH"); Get_New_Key(t+6, "RIGHT PUSH SWITCH"); break; case 6: // Shadow Dancer Get_New_Key(t, "JUMP"); Get_New_Key(t+1, "MAGIC"); Get_New_Key(t+2, "ATTACK"); Get_New_Key(t+3, "UP"); Get_New_Key(t+4, "DOWN"); Get_New_Key(t+5, "LEFT"); Get_New_Key(t+6, "RIGHT"); break; default : Get_New_Key(t, "ATTACK"); Get_New_Key(t+1, "JUMP"); Get_New_Key(t+2, "MAGIC"); Get_New_Key(t+3, "UP"); Get_New_Key(t+4, "DOWN"); Get_New_Key(t+5, "LEFT"); Get_New_Key(t+6, "RIGHT"); break; } break; } } void Get_New_Button(int key_number, char *key_name) { int ok=1, scancode, i, tmp; char bval, *bname; clear_keybuf(); rectfill(screen, 0, 115, 319, 132, 0); do { Outline_Text(124, 5, key_name); do { poll_joystick(); bval=(joy_b[1]+joy_b[2]+joy_b[3]+joy_b[4]); } while (bval); do { poll_joystick(); bval=(joy_b[1]+joy_b[2]+joy_b[3]+joy_b[4]); } while ((!bval)&&(!key[KEY_ESC])); if (bval) { if (bval>1) { Message("?", 5, 0); ok=0; } else { if (joy_b[1]) bval=1; else if (joy_b[2]) bval=2; else if (joy_b[3]) bval=3; else if (joy_b[4]) bval=4; ok=1; for (i=0;i!=key_number;i++) { if (joydef[i]==bval) { switch (i) { case 0: bname=b1[game-1]; break; case 1: bname=b2[game-1]; break; case 2: bname=b3[game-1]; break; } sprintf(ws, "BUTTON %c ALREADY USED FOR %s", bval+64, bname); Message(ws, 6, 0); ok=0; continue; } } } } else (ok=1); } while (!ok); joydef[key_number]=bval; } void Setup_Joy() { Hide_Screen("JOYSTICK BUTTON MAPPING"); Outline_Text(100, 2, "PRESS THE BUTTON FOR"); Outline_Text(220, 3, "ESC - DON'T MAP THIS BUTTON"); Show_Screen(); if (b1[game-1][0]!='-') Get_New_Button(0, b1[game-1]); else joydef[0]=0; if (b1[game-1][1]!='-') Get_New_Button(1, b2[game-1]); else joydef[1]=0; if (b1[game-1][2]!='-') Get_New_Button(2, b3[game-1]); else joydef[2]=0; } void Setup_Keyboard() { int touche; do { Hide_Screen("KEYBOARD SETUP"); Outline_Text(90, 3, "1 - PLAYER ONE KEYS"); Outline_Text(110, 3, "2 - PLAYER TWO KEYS"); Outline_Text(130, 3, "G - GENERAL KEYS"); if (joy) Outline_Text(170, 3, "B - JOYSTICK BUTTON CONFIGURATION"); if (joystick_support) { rectfill(screen, 0, 149, 319, 159, 0); switch (joy) { case 0: Outline_Text(150, 3, "J - JOYSTICK = NOT USED"); break; case 1: Outline_Text(150, 3, "J - JOYSTICK = 1ST PLAYER"); break; case 2: Outline_Text(150, 3, "J - JOYSTICK = 2ND PLAYER"); break; } } Outline_Text(220, 2, "ESC to cancel"); Show_Screen(); clear_keybuf(); touche=(readkey()>>8); switch (touche) { case 0x4F: case KEY_1: Setup_KB(6, "Player one keys"); break; case 0x50: case KEY_2: Setup_KB(20, "Player two keys"); break; case KEY_G: Setup_KB(0, "General keys"); break; case KEY_J: if (joystick_support) { joy++; if (joy==3) joy=0; } break; case KEY_B: Setup_Joy(); break; } } while (touche!=KEY_ESC); } void Save_Config() { PACKFILE *f; int version=EMULATOR_VERSION; sprintf(ws, "%s.cfg", game_basename); f=pack_fopen(ws, F_WRITE_PACKED); if (f!=NULL) { pack_iputw(version, f); pack_fwrite(&keydef[0], sizeof(keydef[0])*40, f); pack_fwrite(shinobi_ds1, 10, f); pack_fwrite(shinobi_ds2, 10, f); pack_fwrite(joydef, 4, f); pack_fclose(f); Message("CONFIGURATION SAVED", 5, 0); } else { Message("DISK WRITE ERROR", 6, 0); } } void Load_Config() { PACKFILE *f; int version; sprintf(ws, "%s.cfg", game_basename); f=pack_fopen(ws, F_READ_PACKED); if (f!=NULL) { version=pack_igetw(f); pack_fread(&keydef[0], sizeof(keydef[0])*((version>=0055)? 40:20), f); pack_fread(shinobi_ds1, 10, f); pack_fread(shinobi_ds2, 10, f); if (version>=0051) pack_fread(joydef, 5, f); pack_fclose(f); } } void FillSavegameList() { int i, trash; char fn[15], desc[21]; PACKFILE *f; for (i=0;i!=10;i++) { sprintf(fn, "%s.sa%d", game_basename, i); if (file_exists(fn, 0, NULL)) { f=pack_fopen(fn, F_READ_PACKED); trash=pack_igetw(f); trash=pack_igetw(f); pack_fread(savegame_list[i].description, 21, f); pack_fclose(f); } else strcpy(savegame_list[i].description, "free slot"); } } char SelectFromSavegameList(char *caption) { int i, key; rectfill(screen, 70, 45, 250, 180, 8); rectfill(screen, 75, 65, 245, 175, 0); rect(screen, 70, 45, 250, 180, 4); rect(screen, 75, 65, 245, 175, 4); Outline_Text(50, 2, caption); for (i=0;i!=10;i++) OutlineXY_Text(80, 70+10*i, 5, savegame_list[i].description); i=0; Outline_Text(190, 2, "UP/DOWN to change"); Outline_Text(205, 2, "ENTER to select a slot"); Outline_Text(220, 2, "ESC to cancel"); Show_Screen(); do { rect(screen, 77, 68+(10*i), 243, 78+(10*i), 5); key=(readkey()>>8); rect(screen, 77, 68+(10*i), 243, 78+(10*i), 0); if ((key==KEY_UP)&&(i)) i--; if ((key==KEY_DOWN)&&(i!=9)) i++; if (key==KEY_ESC) { key=KEY_ENTER; i=-1; } } while (key!=KEY_ENTER); return(i); } void Load_GameFromDisk(char n) { char fn[15], desc[21]; int trash; PACKFILE *f; sprintf(fn, "%s.sa%d", game_basename, n); printf("Loading saved game number %d...\n", n); f=pack_fopen(fn, F_READ_PACKED); if (f!=NULL) { trash=pack_igetw(f); trash=pack_igetw(f); pack_fread(desc, 21, f); printf("Description : %s\n", desc); pack_fread(®s, sizeof(regs), f); pack_fread(&lastint_regs, sizeof(regs), f); pack_fread(®flags, sizeof(regflags), f); pack_fread(RAM[0x40], 0x10000, f); pack_fread(RAM[0x41], 0x1000, f); pack_fread(RAM[0x44], 0x2000, f); pack_fread(RAM[0x84], 0x1000, f); pack_fread(RAM[0xFE], 0x40, f); pack_fread(RAM[0xFF], 0x10000, f); pack_fclose(f); reset_palette=1; /* reset the palette */ printf("Game loaded !\n"); } else { printf("Can't open %s !\n", fn); } } void Load_Game() { PACKFILE *f; char desc[21], i, fn[15]; int version, game_number; Hide_Screen("Load a game from disk"); FillSavegameList(); i=SelectFromSavegameList("SELECT A SAVED GAME"); if (i!=-1) { sprintf(fn, "%s.sa%d", game_basename, i); f=pack_fopen(fn, F_READ_PACKED); if (f!=NULL) { Message_NoPause("Loading...", 5); version=pack_igetw(f); game_number=pack_igetw(f); pack_fread(desc, 21, f); pack_fread(®s, sizeof(regs), f); pack_fread(&lastint_regs, sizeof(regs), f); pack_fread(®flags, sizeof(regflags), f); pack_fread(RAM[vid_bank], 0x10000, f); pack_fread(RAM[txt_bank], 0x1000, f); pack_fread(RAM[ext_bank], 0x2000, f); pack_fread(RAM[pal_bank], 0x1000, f); pack_fread(RAM[0xFE], 0x40, f); pack_fread(RAM[0xFF], 0x10000, f); pack_fclose(f); reset_palette=1; /* reset the palette */ Message("GAME LOADED", 5, 0); } else { Message("DISK READ ERROR", 6, 0); } } } void Save_Game() { char desc[21], i, fn[15]; PACKFILE *f; int version=EMULATOR_VERSION; int game_number=game; Hide_Screen("Save the current game"); FillSavegameList(); i=SelectFromSavegameList("SELECT A SLOT"); if (i!=-1) { GetTextGfx("ENTER THE DESCRIPTION", desc, 20); sprintf(fn, "%s.sa%d", game_basename, i); f=pack_fopen(fn, F_WRITE_PACKED); if (f!=NULL) { Message_NoPause("Saving...", 5); pack_iputw(version, f); pack_iputw(game_number, f); pack_fwrite(desc, 21, f); pack_fwrite(®s, sizeof(regs), f); pack_fwrite(&lastint_regs, sizeof(regs), f); pack_fwrite(®flags, sizeof(regflags), f); pack_fwrite(RAM[vid_bank], 0x10000, f); pack_fwrite(RAM[txt_bank], 0x1000, f); pack_fwrite(RAM[ext_bank], 0x2000, f); pack_fwrite(RAM[pal_bank], 0x1000, f); pack_fwrite(RAM[0xFE], 0x40, f); pack_fwrite(RAM[0xFF], 0x10000, f); pack_fclose(f); Message("GAME SAVED", 5, 0); } else { Message("DISK WRITE ERROR", 6, 1); } } } void Interface() { int touche; get_palette(menu_save_palette); pal[1].r=pal[1].g=pal[1].b=63; pal[0].r=pal[0].g=pal[0].b=32; pal[2].b=0; pal[2].g=pal[2].r=63; pal[3].r=0; pal[3].g=pal[3].b=63; pal[4].r=pal[4].g=pal[4].b=0; pal[5].r=pal[5].b=0;pal[5].g=63; pal[6].g=pal[6].b=0;pal[6].r=63; pal[7].r=pal[7].g=pal[7].b=16; pal[8].r=pal[8].g=16;pal[8].b=32; Draw_Main_Menu(); save_screen=create_bitmap(320, 240); save_screen_2=create_bitmap(320, 240); do { clear_keybuf(); touche=(readkey()>>8); switch (touche) { case KEY_F1: Setup_Keyboard(); Draw_Main_Menu(); break; case KEY_F3: Setup_Dip_Swicths(); Draw_Main_Menu(); break; case KEY_F5: Save_Game(); Draw_Main_Menu(); break; case KEY_F6: Load_Game(); Draw_Main_Menu(); break; case KEY_F8: Save_Config(); break; case KEY_F10: MC68000_reset(); touche=KEY_ESC; break; } } while (touche!=KEY_ESC); while (key[KEY_ESC]); clear_keybuf(); fade_out(FADE_SPEED); clear(screen); blit(vscreen, screen, 104, 88, sx, sy, 312, 224); fade_in(menu_save_palette, FADE_SPEED); destroy_bitmap(save_screen); destroy_bitmap(save_screen_2); }