/* MeTool V1.7x - the Magic Engine Header Tool by vOlker Oth (dOnut) in 6/1997 For bug reports and comments mail to volkeroth@aol.com You might find a more advanced version someday at my homepage: members.aol.com/volkeroth You need a properly installed Allegro 2.2 to compile MeTool. To avoid crashes, insert the following line at the end of allegro\src\djgpp\mouse.c: _mouse_screen = NULL; */ #include #include #include #include #include #include #include #include #include "guidat.h" /*constants*/ #define true -1 #define false 0 #define error 1 #define info_split 1 /* bit values used in rom header */ #define info_title 2 #define info_us 128 #define w_all 1 /* values for state of radio buttons */ #define w_rom 2 #define w_sav 3 #define FA_MYFILE FA_RDONLY + FA_HIDDEN + FA_SYSTEM + FA_ARCH #define maxfiles 1024 /* maximum files read in directory */ #define maxlines 1024 /* maximum lines saved to list/idx file */ #define maxbackups 512 /* maximum entries in backup ram */ #define ident_exec "[Exec]" /* ident. strings used in ini file */ #define ident_startpath "[StartPath]" #define ident_nosound "[NoSound]" #define ident_nojoy "[NoJoy]" #define ident_romsonly "[RomsOnly]" #define backup_file ".\\BACKUP.RAM" /* some string definitions */ #define io_err "I/O Error" #define io_err_inf "" #define mem_err "Memory Error" #define mem_err_nl "Memory Error\n" #define wild_all "*.*" #define debug(c) puts(c) /*typedefs*/ typedef unsigned char byte; typedef unsigned short int word; typedef unsigned long int dword; typedef struct { /* used to store file informations */ char name[13]; long size; /* file size */ byte dir; /* boolean: is this a directory ? */ byte rom; /* boolean: is there a rom extension ? */ } t_file_info; typedef struct { /* used to store backup ram infos */ word size; /* size of the entry */ word offset; /* offset of entry */ char name[11]; /* name of entry */ } t_backup_info; typedef struct { /* the header of BACKUP.RAM */ char hubm[4]; /* identification: "HUBM" */ word adr_end; /* address of first byte after backup ram: always 0xA000 */ word adr_free; /* address of first free directory entry */ char zero[8]; /* 8 zeroes */ } t_backup_header; typedef struct { /* dir entry of BACKUP RAM */ word size; /* size of entry */ word crc; /* crc ??? */ word zero; /* 8 zeroes */ char name[10]; /* name of entry */ } t_backup_entry; /* Dialog definitions */ enum my_dialog_ix { #define DIA_ENTRY( proc, mnem, x, y, w, h, fg, bg, key, flags, d1, d2, dp )\ mnem #include "metool.dia" }; enum filereq_ix { #define DIA_ENTRY( proc, mnem, x, y, w, h, fg, bg, key, flags, d1, d2, dp )\ mnem #include "filereq.dia" }; enum setup_ix { #define DIA_ENTRY( proc, mnem, x, y, w, h, fg, bg, key, flags, d1, d2, dp )\ mnem #include "setup.dia" }; enum backup_ix { #define DIA_ENTRY( proc, mnem, x, y, w, h, fg, bg, key, flags, d1, d2, dp )\ mnem #include "backup.dia" }; enum rename_ix { #define DIA_ENTRY( proc, mnem, x, y, w, h, fg, bg, key, flags, d1, d2, dp )\ mnem #include "rename.dia" }; /* variables */ struct t_header { /* the magic engine rom header */ byte blocknum; /* how many 8kb blocks */ byte info; /* bit 0: split, bit 1: title, bit 7: us */ byte reserved[446]; byte nlength; /* length of name */ byte crc; /* crc of name (XOR) */ char name[62]; /* name */ } meheader; char* options[] = { 0,0,0,0,0,0,0 }; /* used for calling Magic Engine */ char* text_list[maxlines]; /* used for sorting output */ int line_num = 0; /* number of lines in text_list */ t_file_info* file_info[maxfiles]; /* contains fileinfo */ int file_num = 0; /* the actual number of fitting files */ int file_idx = 0; /* number of actual file in file_num */ FILE *f; /* standard file handle */ struct ffblk dirinfo; /* needed for dir functions */ char *rom_buf; /* used for adding/deleting headers */ int doserror; /* return variable for file-functions*/ char *backup_buf; /* used for loading backup ram */ char str_backup_free[50]; /* used for displaying free ram */ int backup_num=0; /* no. of entries in backup ram */ int actbackup_num; /* actually selected entry in backup ram */ int backup_free; /* how many bytes are free in backup ram */ t_backup_info *backup_info[maxbackups]; /* contains backup info */ t_backup_header *backup_header; /* header of backup ram */ t_backup_entry *backup_entry; /* header of backup ram entry */ char str_ini[128]; /* holds path and name of ini file */ char str_fname[13]; /* string holding current filename */ char str_rename[13]; /* string holding rename filename */ char str_path[128]; /* string holding current path */ char str_startpath[128]="."; /* start path */ char str_pce[128]="pce.exe"; /* pce exec path */ char str_view[13]; /* used in View button */ char str_exec[128]="\0"; /* used to execute pce */ char str_wild[13]; /* wild card used in get_files */ char str_title[62]="\0"; /* string holding current rom title */ char str_info[25] = ""; /* string holding current rom info */ char str_blocks[13]= "0"; /* string holding current block no. */ char str_crc[13]= "0"; /* string holding current checksum */ char fr_path[128]; /* path used in file requester */ char fr_fname[13]; /* name used in file requester */ char fr_title[50]; /* title used in file requester */ int roms_only=false; /* show only roms */ int nosound=false; /* use -nosound option */ int nojoy=false; /* use -nojoy option */ int rom = false; /* boolean: is this a rom ? */ int header=false; /* boolean: is there a header ? */ int changed=false; /* boolean: was rom changed ? */ int us=false; /* boolean: is rom of US type ? */ int split=false; /* boolean: is rom of split type ? */ int wild = w_all; /* current state of radio buttons/wild card */ byte blocks=0; /* current 8kb block number */ byte crc =0; /* current checksum */ int leave=false; /* boolean: leave program ? */ int i; /* loop counter */ int ret; /* dialog return variable */ word old_gmode; /* Misc functions */ char** __crt0_glob_function(char *_argument) { return(NULL);} void __crt0_load_environment_file(char *_appname) {} /* GUI keyboard functions */ int replacement_keypressed() { return _bios_keybrd(_KEYBRD_READY); } int replacement_readkey() { return _bios_keybrd(_KEYBRD_READ); } /* GUI functions */ static int gui_textout(BITMAP *bmp, char *s, int x, int y, int color, int centre) /* copied from allegro's gui.c since it is not exported */ { char tmp[160]; int c; int len = 0; int pix_len; int hline_pos = -1; for (c=0; (s[c]) && (len<159); c++) { if (s[c] == '&') { if (s[c+1] != '&') hline_pos = len; else { tmp[len++] = '&'; c++; } } else tmp[len++] = s[c]; } tmp[len] = 0; pix_len = text_length(font, tmp); if (centre) x -= pix_len / 2; if (bmp) { textout(bmp, font, tmp, x, y, color); if (hline_pos >= 0) { c = tmp[hline_pos]; tmp[hline_pos] = 0; hline_pos = text_length(font, tmp); tmp[0] = c; tmp[1] = 0; c = text_length(font, tmp); hline(bmp, x+hline_pos, y+text_height(font)-gui_font_baseline, x+hline_pos+c-1, color); } } return pix_len; } static int gui_strlen(char *s) /* copied from allegro's gui.c since it is not exported */ { return gui_textout(NULL, s, 0, 0, 0, 0); } static void dotted_rect(int x1, int y1, int x2, int y2, int fg, int bg) /* copied from allegro's gui.c since it is not exported */ /* Draws a dotted rectangle, for showing an object has the input focus.*/ { int c; for (c=x1; c<=x2; c+=2) { /* "<=" else a pixel is missing */ putpixel(screen, c, y1, fg); putpixel(screen, c, y2, fg); } for (c=x1+1; cflags & D_HIDDEN)) { if (!(d->flags & D_DISABLED)) { rectfill(screen, d->x+2, d->y+2, d->x+d->w-2, d->y+d->h-2, 7); rect(screen, d->x, d->y, d->x+d->w, d->y+d->h, 1); col1=8; col2 = 6; } vline(screen, d->x+1, d->y+1, d->y+d->h-1, col1); hline(screen, d->x+1, d->y+1, d->x+d->w-1, col1); vline(screen, d->x+d->w-1, d->y+2, d->y+d->h-1, col2); hline(screen, d->x+2, d->y+d->h-1, d->x+d->w-1, col2); } return D_O_K; } int d_3d_button_proc(int msg, DIALOG *d, int c) /* based on d_button_proc: uses 3d effect*/ { int fg; int col1; int col2; int g; if (msg==MSG_DRAW) { fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; if ((d->flags & D_SELECTED) || (d->flags & D_DISABLED)) { col1=2; col2=3; g=1; } else { col1=4; col2=2; g=0; } rect(screen, d->x, d->y, d->x+d->w, d->y+d->h, 1); rectfill(screen, d->x+2, d->y+2, d->x+d->w-2, d->y+d->h-2, 3); text_mode(-1); gui_textout(screen, d->dp, d->x+d->w/2+g, d->y+d->h/2-text_height(font)/2+g, fg, TRUE); vline(screen, d->x+1, d->y+1, d->y+d->h-1, col1); hline(screen, d->x+1, d->y+1, d->x+d->w-1, col1); vline(screen, d->x+d->w-1, d->y+1+g, d->y+d->h-1, col2); hline(screen, d->x+1+g, d->y+d->h-1, d->x+d->w-1, col2); if (d->flags & D_GOTFOCUS) dotted_rect(d->x+3, d->y+3, d->x+d->w-3, d->y+d->h-3, fg, d->bg); return D_O_K; } return d_button_proc(msg, d, 0); } int d_3d_check_proc(int msg, DIALOG *d, int c) /* modified d_check_proc based on d_button_proc */ { int x; int fg; BITMAP *spr_check; if (msg==MSG_DRAW) { fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; text_mode(-1); x = d->x + gui_textout(screen, d->dp, d->x, d->y+(d->h-(text_height(font)-gui_font_baseline))/2, fg, FALSE) + text_height(font)/2; if (d->flags & D_SELECTED) { if (d->flags & D_DISABLED) spr_check = &spr_check1_p; else spr_check = &spr_check1; } else { if (d->flags & D_DISABLED) spr_check = &spr_check2_p; else spr_check = &spr_check2; } draw_sprite(screen,spr_check,x,d->y); if (d->flags & D_GOTFOCUS) dotted_rect(x+1, d->y+1, x+d->h-1, d->y+d->h-1, fg, d->bg); return D_O_K; } return d_button_proc(msg, d, 0); } int d_3d_radio_proc(int msg, DIALOG *d, int c) /* radio button based on d_button_proc */ /* the radio button behaviour is controlled by the program */ /* in opposite to the standard d_radio_proc of the gui */ { int x, center, fg; if (msg==MSG_DRAW) { fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; text_mode(d->bg); gui_textout(screen, d->dp, d->x+d->h+text_height(font), d->y+(d->h-(text_height(font)-gui_font_baseline))/2, fg, FALSE); x = d->x; if (d->flags & D_SELECTED) draw_sprite(screen,&spr_radio2,x,d->y); else draw_sprite(screen,&spr_radio1,x,d->y); if (d->flags & D_GOTFOCUS) dotted_rect(d->x, d->y, d->x+13, d->y+13, fg, d->bg); return D_O_K; } return d_button_proc(msg, d, 0); } static DIALOG alert3d_dialog[] = { /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ { d_3d_box_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, { d_ctext_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, { d_ctext_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, { d_ctext_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, { d_3d_box_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, { d_3d_button_proc, 0, 0, 0, 0, 0, 0, 0, D_EXIT, 0, 0, NULL }, { d_3d_box_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, { d_3d_button_proc, 0, 0, 0, 0, 0, 0, 0, D_EXIT, 0, 0, NULL }, { d_3d_box_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, { d_3d_button_proc, 0, 0, 0, 0, 0, 0, 0, D_EXIT, 0, 0, NULL }, { NULL } }; #define A_S1 1 #define A_S2 2 #define A_S3 3 #define A_R1 4 #define A_B1 5 #define A_R2 6 #define A_B2 7 #define A_R3 8 #define A_B3 9 int alert3d(char *s1, char *s2, char *s3, char *b1, char *b2, char *b3, int c1, int c2, int c3) /* modified alert3 to get 3d effect */ { int maxlen = 0; int len1, len2, len3; int avg_w = text_length(font, " "); int avg_h = text_height(font)+2; /* +2 to make it look nicer */ int avg_hx = avg_h+3; /* +5 to make it look nicer */ int buttons = 0; int b[3]; int c; #define SORT_OUT_BUTTON(x) { \ if (b##x) { \ alert3d_dialog[A_B##x].flags &= ~D_HIDDEN; \ alert3d_dialog[A_B##x].key = c##x; \ alert3d_dialog[A_B##x].dp = b##x; \ len##x = gui_strlen(b##x); \ b[buttons++] = A_B##x; \ } \ else { \ alert3d_dialog[A_B##x].flags |= D_HIDDEN; \ len##x = 0; \ } \ } alert3d_dialog[A_S1].dp = alert3d_dialog[A_S2].dp = alert3d_dialog[A_S3].dp = alert3d_dialog[A_B1].dp = alert3d_dialog[A_B2].dp = ""; if (s1) { alert3d_dialog[A_S1].dp = s1; maxlen = text_length(font, s1); } if (s2) { alert3d_dialog[A_S2].dp = s2; len1 = text_length(font, s2); if (len1 > maxlen) maxlen = len1; } if (s3) { alert3d_dialog[A_S3].dp = s3; len1 = text_length(font, s3); if (len1 > maxlen) maxlen = len1; } SORT_OUT_BUTTON(1); SORT_OUT_BUTTON(2); SORT_OUT_BUTTON(3); len1 = MAX(len1, MAX(len2, len3)) + avg_w*3; if (len1*buttons > maxlen) maxlen = len1*buttons; maxlen += avg_w*4; alert3d_dialog[0].w = maxlen; alert3d_dialog[A_S1].x = alert3d_dialog[A_S2].x = alert3d_dialog[A_S3].x = alert3d_dialog[0].x + maxlen/2; alert3d_dialog[A_B1].w = alert3d_dialog[A_B2].w = alert3d_dialog[A_B3].w = len1; alert3d_dialog[A_B1].x = alert3d_dialog[A_B2].x = alert3d_dialog[A_B3].x = alert3d_dialog[0].x + maxlen/2 - len1/2; if (buttons == 3) { alert3d_dialog[b[0]].x = alert3d_dialog[0].x + maxlen/2 - len1*3/2 - avg_w; alert3d_dialog[b[2]].x = alert3d_dialog[0].x + maxlen/2 + len1/2 + avg_w; } else if (buttons == 2) { alert3d_dialog[b[0]].x = alert3d_dialog[0].x + maxlen/2 - len1 - avg_w; alert3d_dialog[b[1]].x = alert3d_dialog[0].x + maxlen/2 + avg_w; } alert3d_dialog[0].h = avg_hx*7; /* changed */ alert3d_dialog[A_S1].y = alert3d_dialog[0].y + avg_hx; /* changed */ alert3d_dialog[A_S2].y = alert3d_dialog[0].y + avg_hx*2; /* changed */ alert3d_dialog[A_S3].y = alert3d_dialog[0].y + avg_hx*3; /* changed */ alert3d_dialog[A_S1].h = alert3d_dialog[A_S2].h = alert3d_dialog[A_S2].h = avg_hx; /* changed */ alert3d_dialog[A_B1].y = alert3d_dialog[A_B2].y = alert3d_dialog[A_B3].y = alert3d_dialog[0].y + avg_hx*3+avg_h*2; /* changed */ alert3d_dialog[A_B1].h = alert3d_dialog[A_B2].h = alert3d_dialog[A_B3].h = avg_h*2; alert3d_dialog[A_R1].x = alert3d_dialog[A_B1].x-2; alert3d_dialog[A_R1].y = alert3d_dialog[A_B1].y-2; alert3d_dialog[A_R1].w = alert3d_dialog[A_B1].w+4; alert3d_dialog[A_R1].h = alert3d_dialog[A_B1].h+4; alert3d_dialog[A_R1].flags = alert3d_dialog[A_B1].flags & D_HIDDEN | D_DISABLED; alert3d_dialog[A_R2].x = alert3d_dialog[A_B2].x-2; alert3d_dialog[A_R2].y = alert3d_dialog[A_B2].y-2; alert3d_dialog[A_R2].w = alert3d_dialog[A_B2].w+4; alert3d_dialog[A_R2].h = alert3d_dialog[A_B2].h+4; alert3d_dialog[A_R2].flags = alert3d_dialog[A_B2].flags & D_HIDDEN | D_DISABLED; alert3d_dialog[A_R3].x = alert3d_dialog[A_B3].x-2; alert3d_dialog[A_R3].y = alert3d_dialog[A_B3].y-2; alert3d_dialog[A_R3].w = alert3d_dialog[A_B3].w+4; alert3d_dialog[A_R3].h = alert3d_dialog[A_B3].h+4; alert3d_dialog[A_R3].flags = alert3d_dialog[A_B3].flags & D_HIDDEN |D_DISABLED; centre_dialog(alert3d_dialog); set_dialog_color(alert3d_dialog, gui_fg_color, gui_bg_color); clear_keybuf(); do {} while (mouse_b); c = popup_dialog(alert3d_dialog, A_B1); if (c == A_B1) return 1; else if (c == A_B2) return 2; else return 3; } int d_edit_proc2(int msg, DIALOG *d, int c) /* This is a modified d_edit_proc from allegro: */ /* It will close the dialog if return was pressed. */ /* The shown text also scrolls if there is more text */ /* than can be displayed */ { int f, l, p, w, x, fg; int b; /* no. of chars that can be displayed */ int scroll=false; /* bool: does text have to be scrolled */ char *s; char buf[2]; s = d->dp; l = strlen(s); if (d->d2 > l) d->d2 = l; /* calculate maximal number of displayable characters */ b=x=0; if (d->d2==l) x=text_height(font); /* reserve place for cursor */ buf[1] = 0; for (p=d->d2; p>=0; p--) { /* step backwards through string */ buf[0] = s[p]; b++; x += text_length(font, buf); if (x > d->w) break; } if (x <= d->w) b=l; /* nope, we don't have to scroll */ else { b--; /* yep, we have to scroll */ scroll=true; } switch (msg) { case MSG_START: d->d2 = l; /* start with cursor at end of string */ do { /* find last character that doesn't have to be scrolled */ scroll=false; b=x=0; if (d->d2==l) x=text_height(font); /* reserve place for cursor */ for (p=d->d2; p>=0; p--) { /* calc max no. of chars */ buf[0] = s[p]; b++; x += text_length(font, buf); if (x > d->w) break; } if (x > d->w) { d->d2--; /* loop once again */ scroll=true; } } while (scroll); break; case MSG_DRAW: fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; x = 0; /* handle text box scrolling */ if (scroll) { p = d->d2-b+1; /* increase start position */ b = d->d2; /* display to current pos */ } else p=0; /* b == l ! */ for (p; p<=b; p++) { buf[0] = s[p] ? s[p] : ' '; w = text_length(font, buf); if (x+w > d->w) break; f = ((p == d->d2) && (d->flags & D_GOTFOCUS)); text_mode(f ? fg : d->bg); textout(screen, font, buf, d->x+x, d->y, f ? d->bg : fg); x += w; } if (xw) rectfill(screen, d->x+x, d->y, d->x+d->w-1, d->y+text_height(font)-1, d->bg); break; case MSG_CLICK: x = d->x; /* handle text box scrolling */ if (scroll) { p = d->d2-b+1; /* increase start position */ b = d->d2; /* display to current pos */ } else p=0; /* b == l ! */ for (p; p mouse_x) break; } d->d2 = MID(0, p, l); show_mouse(NULL); SEND_MESSAGE(d, MSG_DRAW, 0); show_mouse(screen); break; case MSG_WANTFOCUS: case MSG_LOSTFOCUS: case MSG_KEY: return D_WANTFOCUS; case MSG_CHAR: if ((c >> 8) == KEY_LEFT) { if (d->d2 > 0) d->d2--; } else if ((c >> 8) == KEY_RIGHT) { if (d->d2 < l) d->d2++; } else if ((c >> 8) == KEY_HOME) { d->d2 = 0; } else if ((c >> 8) == KEY_END) { d->d2 = l; } else if ((c >> 8) == KEY_DEL) { if (d->d2 < l) for (p=d->d2; s[p]; p++) s[p] = s[p+1]; } else if ((c >> 8) == KEY_BACKSPACE) { if (d->d2 > 0) { d->d2--; for (p=d->d2; s[p]; p++) s[p] = s[p+1]; } } /* close dialog if enter was pressed and D_EXIT is set */ else if ((c >> 8) == KEY_ENTER) { if (d->flags & D_EXIT) { show_mouse(NULL); SEND_MESSAGE(d, MSG_DRAW, 0); show_mouse(screen); return D_CLOSE; } } else { c &= 0xff; if ((c >= 32) && (c <= 126)) { if (l < d->d1) { while (l >= d->d2) { s[l+1] = s[l]; l--; } s[d->d2] = c; d->d2++; } } else return D_O_K; } /* if we changed something, better redraw... */ show_mouse(NULL); SEND_MESSAGE(d, MSG_DRAW, 0); show_mouse(screen); return D_USED_CHAR; } return D_O_K; } char* get_file_list( int index, int *list_size ) /* needed by the file list box */ { static char str_dir[128]; if (index < 0) { *list_size = file_num; return NULL; } else if (!file_info[index]->dir) return (char*)file_info[index]->name; else { /* show directory entrys in square brackets */ strcpy(str_dir,"["); strcat(str_dir,file_info[index]->name); strcat(str_dir,"]"); return (char*)str_dir; } } char* get_backup_list( int index, int *list_size ) /* needed by the backup entry list box */ { static char str_help[50]; char str_int[10]; int i; int h; if (index < 0) { *list_size = backup_num; return NULL; } else { strcpy(str_help,backup_info[index]->name); h= strlen(str_help); for (i=h; i<12; i++) strcat(str_help," "); /* show entry's size in brackets */ itoa(backup_info[index]->size,str_int,10); strcat(str_help,"("); strcat(str_help,str_int); strcat(str_help,")"); return (char*)&str_help[0]; } } /* include the main dialog */ DIALOG my_dialog[] = { #include "metool.dia" }; /* include the about dialog */ DIALOG about_dialog[] = { #include "about.dia" }; /* include the file request dialog */ DIALOG fr_dialog[] = { #include "filereq.dia" }; /* include the setup dialog */ DIALOG setup_dialog[] = { #include "setup.dia" }; /* include the backup dialog */ DIALOG backup_dialog[] = { #include "backup.dia" }; /* include the rename dialog */ DIALOG rename_dialog[] = { #include "rename.dia" }; void clr_scrn() /* simply clears the screen */ { show_mouse(NULL); set_clip(screen, 0, 0, SCREEN_W-1, SCREEN_H-1); clear_to_color(screen, 7); /* show_mouse(screen); */ } void get_gmode() { __dpmi_regs r; r.x.ax = 0x0f00; /* function 0f */ __dpmi_int(0x10,&r); old_gmode = (r.x.ax & 255); /* gfx mode in al */ } void set_gmode() { __dpmi_regs r; r.x.ax = old_gmode; /* function 0 */ __dpmi_int(0x10,&r); old_gmode = (r.x.ax & 255); /* gfx mode in al */ } /* program functions */ int file_overwrite(char fname[]) /* Displays alert "file exists" */ /* returns true if file doesn't exist yet or Overwrite-Yes was selected */ { if (file_exists(fname, 63, NULL)) if (alert3d("File exists !","Overwrite ?",0,"&Yes","&No",0,'y','n',0)==2) return false; else return true; else return true; } void ok_alert(char s1[], char s2[], char s3[]) /* shortcut for the often used 'ok' type alert */ { alert3d(s1,s2,s3,"&Ok",0,0,'o',0,0); } int bigger(int s1, int s2) /* compare function used by sort_files */ /* files are always "bigger" than directories, "z*.*" is bigger than "a*.*" */ { int h; h = file_info[s2]->dir - file_info[s1]->dir; if (h==0) return strcmp(file_info[s1]->name,file_info[s2]->name); else return h; } void sort_files() /* sort files in list by name - directories before normal files */ /* used by get_files */ { t_file_info *hstruct; int i=1; int j=1; do { for (i= j+1; i< file_num;i++) if (bigger(j,i)>0) { hstruct = file_info[j]; file_info[j]=file_info[i]; file_info[i]=hstruct; } j++; } while (j < file_num); } void add_file() /* store file informations in array file_info */ /* used by get_files */ { if (strcmp(dirinfo.ff_name,".")) { if (file_info[file_num] = (t_file_info*)malloc(sizeof(t_file_info))) { strcpy(file_info[file_num]->name, strupr(dirinfo.ff_name)); file_info[file_num]->size = dirinfo.ff_fsize; file_info[file_num]->dir = (dirinfo.ff_attrib & FA_DIREC) == FA_DIREC; if (!strcmp(get_extension(file_info[file_num]->name),"PCE")) file_info[file_num]->rom = true; else if(!strcmp(get_extension(file_info[file_num]->name),"ROM")) file_info[file_num]->rom = true; else file_info[file_num]->rom = false; file_num++; } } } void free_file_info() /* frees all memory used by the entries of the file_info structure */ { int i; for (i=0;i1) sort_files(); } byte calc_crc(char s[]) /* calculate checksum of embedded name */ { byte c=0; for (i=0; isize % 8192; if (h==512) return true; /* yes, there is a header */ else if (!h) return false; /* no, there ain't no header */ else return error; /* no rom at all */ } int check_rom() /* check if file is rom and read its header if it has got one */ { changed = 0; strcpy(str_fname,file_info[file_idx]->name); if (file_info[file_idx]->rom) { blocks = file_info[file_idx]->size / 8192; header = has_header(file_idx); if (header == error) { strcpy(str_info,""); clean_header(); return false; /* size is not correct */ } else rom=1; } else { strcpy(str_info,""); clean_header(); return false; } /* ok, it is a valid rom */ strcpy(str_info,"Magic Engine Rom"); if (header) { f = fopen(str_fname,"rb"); if (f==NULL) { ok_alert(io_err,0,0); strcpy(str_info,io_err_inf); clean_header(); return false; } fread(&meheader,1,512,f); fclose(f); } else { meheader.blocknum = blocks; meheader.info = 0; meheader.nlength= 0; meheader.crc=0; for (i=0; i<446; i++) meheader.reserved[i]=0; for (i=0; i<62; i++) meheader.name[i]=0; } itoa(blocks,str_blocks,10); if (meheader.blocknum != blocks) { strcat(str_blocks," "); meheader.blocknum = blocks; changed=true; } strcpy(str_title,meheader.name); crc = calc_crc(str_title); itoa(crc, str_crc,10); if (meheader.crc != crc) { strcat(str_crc," "); changed=true; } split = (meheader.info & info_split); us = meheader.info & info_us; } int check_ram(char fname[]) /* check if file is a valid backup_ram */ { char str_help[5]; doserror=findfirst(fname,&dirinfo,FA_MYFILE); if (doserror) return false; /* not found */ if (dirinfo.ff_fsize != 8192) return false; /*invalid size */ f = fopen(fname,"rb"); if (f==NULL) return false; /* io error */ fread(&str_help,1,4,f); str_help[4]=0; fclose(f); if (strcmp(str_help,"HUBM")) return false; /* missing identification */ else return true; } void check_disabled() /* change/set state of displayed dialog parts */ { if (header) my_dialog[check_header].flags |= D_SELECTED; else my_dialog[check_header].flags &= ~D_SELECTED; if (split) my_dialog[check_split].flags |= D_SELECTED; else my_dialog[check_split].flags &= ~D_SELECTED; if (us) my_dialog[check_us].flags |= D_SELECTED; else my_dialog[check_us].flags &= ~D_SELECTED; if (rom) { my_dialog[check_header].flags &= ~D_DISABLED; my_dialog[text_8kb].flags &= ~D_DISABLED; my_dialog[text_blocks].flags &= ~D_DISABLED; my_dialog[check_split].flags &= ~D_DISABLED; my_dialog[check_us].flags &= ~D_DISABLED; my_dialog[text_checksum].flags &= ~D_DISABLED; my_dialog[text_crc].flags &= ~D_DISABLED; my_dialog[text_name].flags &= ~D_DISABLED; my_dialog[edit_name].flags &= ~D_DISABLED; my_dialog[button_run].flags &= ~D_DISABLED; } else { my_dialog[check_header].flags |= D_DISABLED; my_dialog[text_8kb].flags |= D_DISABLED; my_dialog[text_blocks].flags |= D_DISABLED; my_dialog[check_split].flags |= D_DISABLED; my_dialog[check_us].flags |= D_DISABLED; my_dialog[text_checksum].flags |= D_DISABLED; my_dialog[text_crc].flags |= D_DISABLED; my_dialog[text_name].flags |= D_DISABLED; my_dialog[edit_name].flags |= D_DISABLED; my_dialog[button_run].flags |= D_DISABLED; } /* write button */ if (changed) my_dialog[button_write].flags &= ~D_DISABLED; else my_dialog[button_write].flags |= D_DISABLED; /* radio buttons */ if (wild==w_rom) { my_dialog[radio_rom].flags |= D_SELECTED; my_dialog[radio_all].flags &= ~D_SELECTED; my_dialog[radio_sav].flags &= ~D_SELECTED; } else if (wild==w_all) { my_dialog[radio_rom].flags &= ~D_SELECTED; my_dialog[radio_all].flags |= D_SELECTED; my_dialog[radio_sav].flags &= ~D_SELECTED; } else if (wild==w_sav) { my_dialog[radio_rom].flags &= ~D_SELECTED; my_dialog[radio_all].flags &= ~D_SELECTED; my_dialog[radio_sav].flags |= D_SELECTED; } /* rename/delete buttons */ if (str_fname[0]) { my_dialog[button_delete].flags &= ~D_DISABLED; my_dialog[button_rename].flags &= ~D_DISABLED; } else { my_dialog[button_delete].flags |= D_DISABLED; my_dialog[button_rename].flags |= D_DISABLED; } } int get_rom() /* load rom into memory */ { rom_buf = (char*) malloc(file_info[file_idx]->size); if (rom_buf!=NULL) { f = fopen(file_info[file_idx]->name,"rb"); if (f!=NULL) { fread(rom_buf,1,file_info[file_idx]->size,f); fclose(f); return true; } else { ok_alert(io_err,0,0); strcpy(str_info,io_err_inf); free(rom_buf); } } else { ok_alert(mem_err,0,0); strcpy(str_info,""); } return false; } void put_rom(void* b, int append) /* put rom from memory to file */ { f = fopen(file_info[file_idx]->name,"wb"); if (f!=NULL) { if (append) fwrite(&meheader,1,512,f); fwrite(b,1,file_info[file_idx]->size,f); fclose(f); } else { strcpy(str_info,io_err_inf); ok_alert(io_err,0,0); } free(rom_buf); } void write_header() /* Add, kill or change header depending on current state */ { meheader.blocknum = blocks; meheader.info = 0; if (us) meheader.info += info_us; if (split) meheader.info += info_split; for (i=0; i<62; i++) meheader.name[i]=0; meheader.nlength= strlen(str_title); meheader.crc= calc_crc(str_title); if (str_title[0] !=0) { meheader.info += info_title; strcpy(meheader.name,str_title); } if (!header && has_header(file_idx)) { /* kill header */ if (get_rom()) { file_info[file_idx]->size -= 512; put_rom(rom_buf+512,false); free(rom_buf); changed=false; } } else if (header && !has_header(file_idx)) { /* add header */ if (get_rom()) { put_rom(rom_buf,true); free(rom_buf); file_info[file_idx]->size += 512; changed=false; } } else if (header && has_header(file_idx)) { /* change header */ f = fopen(file_info[file_idx]->name,"rb+"); if (f!=NULL) { fwrite(&meheader,1,512,f); fclose(f); changed=false; } } } void conv_slash(char p[]) /* converts slashs in string into backslashs */ { int i; for (i=0; i=0; i--) { if (s[i]==':') break; if (s[i]=='\\') break; if (s[i]=='/') break; } if (i>0) if(s[i-1]==':') i++; p[i]=0; } int file_request(char title[], char name[], char wild[]) /* show a file request box */ /* title is shown at top of the box */ /* name is path+filename to start with */ /* wild is wildcard to start with */ { int fr_leave=false; int rvalue=false; char save_wild[13]; BITMAP *bmp; bmp = create_bitmap(fr_dialog->w+1, fr_dialog->h+1); /* save background */ if (bmp) { show_mouse(NULL); blit(screen,bmp,fr_dialog->x,fr_dialog->y,0,0,fr_dialog->w+1,fr_dialog->h+1); } strcpy(fr_fname,get_filename(name)); strcpy(fr_path,name); if (fr_fname[0]) clip_path(fr_path); strcpy(fr_title,title); strcpy(save_wild,str_wild); strcpy(str_wild,wild); change_path(fr_path,false); while(!fr_leave) { ret = do_dialog( fr_dialog, find_dialog_focus(fr_dialog)); switch( ret ) { case fr_button_ok: fr_leave=true; strcpy(name,fr_path); put_backslash(name); strcat(name,fr_fname); rvalue=true; break; case fr_button_cncl: fr_leave=true; break; break; case fr_button_a: strcpy(fr_path,"A:"); change_path(fr_path,false); break; case fr_button_b: strcpy(fr_path,"B:"); change_path(fr_path,false); break; case fr_button_c: strcpy(fr_path,"C:"); change_path(fr_path,false); break; case fr_button_d: strcpy(fr_path,"D:"); change_path(fr_path,false); break; case fr_button_e: strcpy(fr_path,"E:"); change_path(fr_path,false); break; case fr_button_f: strcpy(fr_path,"F:"); change_path(fr_path,false); break; case fr_button_g: strcpy(fr_path,"G:"); change_path(fr_path,false); break; case fr_button_h: strcpy(fr_path,"H:"); change_path(fr_path,false); break; case fr_edit_path: change_path(fr_path,false); break; case fr_edit_name: if (fr_fname[0]==0) strcpy(str_wild,wild_all); else strcpy(str_wild,fr_fname); get_files(false); break; case fr_list: file_idx = fr_dialog[fr_list].d1; if (file_info[file_idx]->dir) { chdir(file_info[file_idx]->name); getcwd(fr_path,255); conv_slash(fr_path); get_files(false); my_dialog[file_list].d1 = 0; my_dialog[file_list].d2 = 0; } else { strcpy(fr_fname,file_info[file_idx]->name); } break; } } /* restore background */ if (bmp) { show_mouse(NULL); blit(bmp,screen,0,0,fr_dialog->x, fr_dialog->y, fr_dialog->w+1, fr_dialog->h+1); destroy_bitmap(bmp); } strcpy(str_wild,save_wild); change_path(str_path,true); return rvalue; } void sort_list() /* sort lines in list */ { char* hstring; int i=1; int j=1; do { for (i= j+1; i< line_num;i++) if (strcmp(text_list[j],text_list[i])>0) { /* strcpy(hstring,text_list[j]); strcpy(text_list[j],text_list[i]); strcpy(text_list[i],hstring); */ hstring = text_list[j]; text_list[j]=text_list[i]; text_list[i]=hstring; } j++; } while (j < line_num); } void free_text_list() /* frees all memory occupied by entries of text_list */ { int i; for (i=0;irom) { if (has_header(i)) { f = fopen(file_info[i]->name,"rb"); if (f!=NULL) { fread(&meheader,1,512,f); fclose(f); if (meheader.info & info_title) strcpy(s_out,meheader.name); else { strcpy(s_out,file_info[i]->name); h=24-strlen(s_out); for (j=0;jname); h=24-strlen(s_out); for (j=0;jsize / 1024,s_help,10); strcat(s_out,s_help); } if ((text_list[line_num]=(char*)malloc(90))&&(line_num 24) h=24; for (k=0; krom) { _us = false; _split=false; s_out[0]=0; if (has_header(i)) { f = fopen(file_info[i]->name,"rb"); if (f!=NULL) { fread(&meheader,1,512,f); fclose(f); if (meheader.info & info_title) strcpy(s_out,meheader.name); _us = (meheader.info & info_us); _split = (meheader.info & info_split); } } if (s_out[0]==0) { strcpy(s_out,file_info[i]->name); s_out[strlen(file_info[i]->name)-4]=0; } format_idx(s_out); strcat(s_out,"@"); strcat(s_out,file_info[i]->name); strcat(s_out,"@"); strncat(s_out,file_info[i]->name,strlen(file_info[i]->name)-4); if (_us && _split) strcat(s_out,"#3"); if (_us && !_split) strcat(s_out,"#1"); if (!_us && _split) strcat(s_out,"#2"); if ((text_list[line_num]=(char*)malloc(90))&&(line_numw+1, setup_dialog->h+1); /* save background */ if (bmp) { show_mouse(NULL); blit(screen,bmp,setup_dialog->x,setup_dialog->y,0,0,setup_dialog->w+1, setup_dialog->h+1); } while(!s_leave) { /* init check boxes */ if (roms_only) setup_dialog[setup_check_romsonly].flags |= D_SELECTED; else setup_dialog[setup_check_romsonly].flags &= ~D_SELECTED; if (nosound) setup_dialog[setup_check_nosound].flags |= D_SELECTED; else setup_dialog[setup_check_nosound].flags &= ~D_SELECTED; if (nojoy) setup_dialog[setup_check_nojoy].flags |= D_SELECTED; else setup_dialog[setup_check_nojoy].flags &= ~D_SELECTED; ret = do_dialog( setup_dialog, find_dialog_focus(setup_dialog)); switch( ret ) { case setup_button_ok: if (check_setup()) s_leave=true; break; case setup_button_save: write_ini(); if (check_setup()) s_leave=true; break; case setup_check_romsonly: roms_only=~roms_only; break; case setup_check_nosound: nosound=~nosound; break; case setup_check_nojoy: nojoy=~nojoy; break; } } if (bmp) { show_mouse(NULL); blit(bmp,screen,0,0,setup_dialog->x, setup_dialog->y, setup_dialog->w+1, setup_dialog->h+1); destroy_bitmap(bmp); } } void free_backup_info() { int i; for (i=0;iadr_free) { backup_entry=backup_ptr; if (backup_info[backup_num]=(t_backup_info*)malloc(sizeof(t_backup_info))){ backup_info[backup_num]->size = backup_entry->size; backup_info[backup_num]->offset = offset; memcpy(backup_info[backup_num]->name,backup_entry->name,10); backup_info[backup_num]->name[10]=0; backup_num++; backup_ptr+= backup_entry->size; offset+= backup_entry->size; } } backup_free = 8192 - (backup_header->adr_free-0x8000); itoa(backup_free, str_help, 10); strcpy(str_backup_free,"Space left: "); strcat(str_backup_free,str_help); strcat(str_backup_free," bytes"); } int get_backup(char fname[]) /* reads backup file and transfers data into backup_info */ { int i; if (!check_ram(fname)) { ok_alert("No Backup Ram found","or invalid.","Created a new one"); /* create empty backup ram */ for (i=0; i<8192; i++) backup_buf[i]=0; backup_buf[0]='H'; backup_buf[1]='U'; backup_buf[2]='B'; backup_buf[3]='M'; backup_buf[4]=0x00; backup_buf[5]=0xa0; backup_buf[6]=0x10; backup_buf[7]=0x80; } else { f = fopen(fname,"rb"); if (f==NULL) { ok_alert(io_err,0,0); return false; } fread(backup_buf,1,8192,f); } backup_header=(t_backup_header*)backup_buf; /* set header structure */ scan_backup(); return true; } void reset_backup() /* resets backup ram */ { int i; /* clear buffer */ for (i=8; i<8192;i++) backup_buf[i]=0; backup_header->adr_free=0x8010; /* set address of first free entry */ scan_backup(); } int kill_backup() /* kills a backup entry and shifts the following entries up */ { int i; int ofs_end; int size; if (backup_num ==0) return false; size = backup_info[actbackup_num]->size; /* no. of bytes to shift */ ofs_end = backup_header->adr_free - 0x8000 - size;/* last byte to replace*/ /* shift bytes */ for (i=backup_info[actbackup_num]->offset;iadr_free -= size; scan_backup(); } void remove_spaces(char str[]) /* removes spaces from a string */ { int i=0; int j; while (str[i]) { if (str[i]==32) /* if space then shift rest of string to the left */ for (j=i+1; j<=strlen(str); j++) str[j-1] = str[j]; else { if (str[i]=='.') str[i]='_'; /* replace dots by underscores */ i++; } } } int export_backup() /* exports an entry from backup ram */ { char exp_fname[128]; char str_help[15]; if (backup_num ==0) return false; /* put together default filename */ check_path(str_path,FALSE); /* first comes the current path */ strcpy(exp_fname,str_path); put_backslash(exp_fname); strcpy(str_help,backup_info[actbackup_num]->name);/* now create filename */ remove_spaces(str_help); str_help[8]=0; strcat(str_help,".SAV"); strcat(exp_fname,str_help); if (!file_request("Backup Export File",exp_fname,"*.SAV")) return false; if (!file_overwrite(exp_fname)) return false; f = fopen(exp_fname,"wb"); if (f==NULL) { ok_alert("Couldn't open","export file !",0); return false; } fwrite(&backup_buf[backup_info[actbackup_num]->offset],1, backup_info[actbackup_num]->size,f); fclose(f); } int import_backup() /* imports an entry to backup ram */ { char inp_fname[128]; t_backup_entry *entry; word size; long fsize; int i; int found; /* put together default filename */ check_path(str_path,FALSE); /* first comes the current path */ strcpy(inp_fname,str_path); put_backslash(inp_fname); strcat(inp_fname,"import.sav"); /* get file name */ if (!file_request("Backup Import File",inp_fname,"*.sav")) return false; doserror=findfirst(inp_fname,&dirinfo,FA_MYFILE); fsize = dirinfo.ff_fsize; /* get size of selected file */ /* open file */ f = fopen(inp_fname,"rb"); if (f==NULL) { ok_alert("Couldn't open","import file !",0); return false; } /* check if valid import file */ fread(&size,2,1,f); if ((size!=fsize)||(fsize>=8192)||(fsize<16)) ok_alert("No valid","import file !",0); else { /* check if name already exists */ fseek(f,6,SEEK_SET); /* set at entry name */ fread(&inp_fname,1,10,f); inp_fname[10]=0; /* get name */ fseek(f,0,SEEK_SET); /* and reset to start */ found=-1; for (i=0; iname,inp_fname)) found=i; if (found!=-1) { /* entry of same name exists */ if (alert3d("Entry exists !","Replace ?",0,"&Yes","&No",0,'y','n',0)==1){ if (backup_info[found]->size!=size) ok_alert("Entry has different size !","Import failed !",0); else fread(&backup_buf[backup_info[found]->offset],1,size,f); } } else /* entry doesn't exist yet */ if (size>backup_free) ok_alert("Not enough memory","left in Backup Ram !",0); else { /* add new entry */ fread(&backup_buf[backup_header->adr_free-0x8000],1,size,f); backup_header->adr_free+=size; } } fclose(f); scan_backup(); } int save_backup(char fname[]) /* saves backup ram to a file */ { char ram_fname[128]; /* put together default filename */ check_path(str_path,FALSE); /* first comes the current path */ strcpy(ram_fname,str_path); put_backslash(ram_fname); strcat(ram_fname,fname); if (!file_request("Backup Save File",ram_fname,"*.RAM")) return false; if (!file_overwrite(ram_fname)) return false; f = fopen(ram_fname,"wb"); if (f==NULL) { ok_alert("Couldn't open","backup file !",0); return false; } fwrite(backup_buf,1,8192,f); fclose(f); } int backup(char fname[]) /* implements the backup dialog */ { int b_leave=false; BITMAP *bmp; bmp = create_bitmap(backup_dialog->w+1, backup_dialog->h+1); /* save background */ if (bmp) { show_mouse(NULL); blit(screen,bmp,backup_dialog->x,backup_dialog->y,0,0,backup_dialog->w+1, backup_dialog->h+1); } backup_buf = (char*) malloc(8192); if (!backup_buf) { ok_alert(mem_err,0,0); return false; } get_backup(fname); while(!b_leave) { /* init check boxes */ ret = do_dialog( backup_dialog, find_dialog_focus(backup_dialog)); actbackup_num = backup_dialog[backup_list].d1; switch( ret ) { case backup_button_cancel: b_leave=true; break; case backup_button_save: save_backup(fname); b_leave=true; break; case backup_button_reset: reset_backup(); break; case backup_button_kill: kill_backup(); break; case backup_button_export: export_backup(); break; case backup_button_import: import_backup(); break; } } free(backup_buf); free_backup_info(); /* restore background */ if (bmp) { show_mouse(NULL); blit(bmp,screen,0,0,backup_dialog->x, backup_dialog->y, backup_dialog->w+1, backup_dialog->h+1); destroy_bitmap(bmp); } get_files(true); } void before_change() /* called everytime, the changes in header could get lost */ { if (changed) if (alert3d("Write Header","or discard changes",0,"&Write","&Discard",0,'w','d',0)==1) write_header(); changed=rom=header=blocks=str_fname[0]=0; strcpy(str_info,""); clean_header(); } void do_change(char p[]) /* called if path is changed */ { strcpy(str_path,p); before_change(); change_path(str_path,true); } int main( int argc, char *argv[] ) { debug("MeTool started"); __djgpp_set_ctrl_c(0); /* treat ctrl-c as normal key */ _crt0_startup_flags |= _CRT0_FLAG_NO_LFN; /* disable long filenames */ get_gmode(); /* put together the path of the ini file and read it */ strcpy(str_ini,argv[0]); clip_path(str_ini); conv_slash(str_ini); put_backslash(str_ini); strcat(str_ini,"MeTool.ini"); read_ini(); debug("ini file read"); /* do some initialization */ init_allegro(); strcpy(str_path,str_startpath); change_path(str_path,true); centre_dialog(about_dialog); centre_dialog(fr_dialog); centre_dialog(setup_dialog); centre_dialog(backup_dialog); centre_dialog(rename_dialog); /* main loop */ while(!leave) { check_disabled(); ret = do_dialog( my_dialog, find_dialog_focus(my_dialog)); /* react on dialog event */ switch( ret ) { case button_quit: before_change(); leave=true; break; case button_about: popup_dialog(about_dialog, -1); break; case button_write: if (changed) write_header(); break; case button_makelist: create_list(); change_path(str_path,true); break; case button_makeidx: create_idx(); change_path(str_path,true); break; case edit_name: crc = calc_crc(str_title); itoa(crc, str_crc,10); if (meheader.crc != crc) strcat(str_crc," "); header=true; changed=true; break; case button_a: do_change("A:"); break; case button_b: do_change("B:"); break; case button_c: do_change("C:"); break; case button_d: do_change("D:"); break; case button_e: do_change("E:"); break; case button_f: do_change("F:"); break; case button_g: do_change("G:"); break; case edit_path: before_change(); change_path(str_path,true); break; case check_header: header = !header; if (!header) { us=0; split=0; crc=0; str_crc[0]=0; str_title[0]=0; } changed = true; break; case check_us: us = !us; header = true; changed = true; break; case check_split: split = !split; header = true; changed = true; break; case file_list: if ((file_idx==my_dialog[file_list].d1) && rom) run_game(); else { before_change(); file_idx = my_dialog[file_list].d1; if (file_info[file_idx]->dir) { chdir(file_info[file_idx]->name); getcwd(str_path,255); conv_slash(str_path); get_files(true); my_dialog[file_list].d1 = 0; my_dialog[file_list].d2 = 0; } else if (check_ram(file_info[file_idx]->name)) { backup(file_info[file_idx]->name); } else check_rom(); } break; case button_setup: setup(); break; case button_backup: backup(backup_file); break; case radio_all: strcpy(str_wild,wild_all); wild = w_all; get_files(true); break; case radio_rom: strcpy(str_wild,"*.PCE"); wild = w_rom; get_files(true); break; case radio_sav: strcpy(str_wild,"*.RAM"); wild = w_sav; get_files(true); break; case button_rename: strcpy(str_exec, str_fname); /* save filename in str_exec */ strcpy(str_rename,str_fname); /* init rename name with file name */ ret = popup_dialog(rename_dialog, -1); if (ret==rename_button_rename) { before_change(); /* str_fname is deleted here ! */ doserror=_rename(str_exec,str_rename); get_files(true); } break; case button_delete: if (alert3d("Really delete file",str_fname,0,"&Yes","&No",0,'y','n',0)==1) { strcpy(str_exec, str_fname); /* save filename in str_exec */ before_change(); /* str_fname is deleted here ! */ doserror=remove(str_exec); get_files(true); } break; case button_run: run_game(); } } /* close down */ clip_path(str_ini); change_path(str_ini,false); /* change back to path MeTool was started in */ free_file_info(); allegro_exit(); set_gmode(); exit(0); }