From a654a303232f8aa8cb31cc66564238e0acc71dc4 Mon Sep 17 00:00:00 2001 From: "fabio.olimpieri" Date: Sat, 9 Feb 2013 07:41:56 +0000 Subject: [PATCH] improved instant load, tzx instant load, tzx text on screen, shorten 128k load command, increased tape speed --- src/characters.c | 22 ++- src/computer.c | 29 ++- src/computer.h | 3 +- src/emulator.c | 7 +- src/gui_sdl.c | 33 ++-- src/tape.c | 488 +++++++++++++++++++++++++++++++++++++++++------ src/tape.h | 3 +- 7 files changed, 492 insertions(+), 93 deletions(-) diff --git a/src/characters.c b/src/characters.c index 80783b6..506257a 100644 --- a/src/characters.c +++ b/src/characters.c @@ -62,7 +62,7 @@ void printchar(unsigned char *memo, unsigned char carac, int x, int y, unsigned void print_string(unsigned char *memo, char *cadena, int x, int y, unsigned char color, unsigned char back, int width) { - int length, ncarac, bucle, xx; + int length, ncarac, bucle, xx,yy, nr; int xxx, yyy; int w,h; unsigned char *str2; @@ -79,12 +79,12 @@ void print_string(unsigned char *memo, char *cadena, int x, int y, unsigned char } for (ncarac=0,str2=cadena;*str2;str2++) { - if ((*str2)>=' ') { + if (((*str2)>=' ')||(*str2==13)) { ncarac++; } } length=w * ncarac; - + if (length > width) { if (x>=0) xx=x; @@ -96,9 +96,14 @@ void print_string(unsigned char *memo, char *cadena, int x, int y, unsigned char else xx=x; } - + + nr=length/width; + yy=y-h*nr; + + if (yy<0) yy=0; + xxx=xx; - yyy=y; + yyy=yy; str2=cadena; for (bucle=0;bucle0) ordenador.tape_start_countdwn--; if (ordenador.mustlock) { SDL_UnlockSurface (ordenador.screen); @@ -886,19 +890,23 @@ inline void show_screen_precision (int tstados) { if (ordenador.osd_time) { ordenador.osd_time--; if (ordenador.osd_time==0) { - ordenador.tab_extended=0; + //ordenador.tab_extended=0; ordenador.esc_again=0; } if (ordenador.osd_time) print_string (ordenador.screenbuffer,ordenador.osd_text, -1,450, 12, 0,ordenador.screen_width); - else { + /*else { if (ordenador.zaurus_mini==0) print_string (ordenador.screenbuffer," ",-1, 450, 12, 0,ordenador.screen_width); else print_string (ordenador.screenbuffer," ",-1, 450, 12, 0,ordenador.screen_width); - } + }*/ } + + if (ordenador.tape_start_countdwn==1) ordenador.pause=0; //Autoplay + + if (ordenador.tape_start_countdwn>0) ordenador.tape_start_countdwn--; if (ordenador.mustlock) { SDL_UnlockSurface (ordenador.screen); @@ -1224,12 +1232,12 @@ inline void read_keyboard () { break; case SDLK_F5: // STOP tape - if ((ordenador.tape_fast_load == 0) || (ordenador.tape_file_type==TAP_TZX)) + //if ((ordenador.tape_fast_load == 0)) ordenador.pause = 1; break; case SDLK_F6: // PLAY tape - if ((ordenador.tape_fast_load == 0) || (ordenador.tape_file_type==TAP_TZX)) + //if (ordenador.tape_fast_load == 0) ordenador.pause = 0; break; @@ -1501,7 +1509,7 @@ inline void read_keyboard () { ordenador.s15 = (ordenador.s15 & 0xE0)| (ordenador.k15 ^ 0x1F); ordenador.js = ordenador.jk; - if (joybutton_matrix[0][SDLK_F6] && ((ordenador.tape_fast_load == 0) || (ordenador.tape_file_type==TAP_TZX))) + if (joybutton_matrix[0][SDLK_F6] && (ordenador.tape_fast_load == 0)) ordenador.pause = 0; //Play the tape //Virtual Keyboard @@ -1664,6 +1672,7 @@ void ResetComputer () { } } ordenador.precision=ordenador.precision_old; //in case the machine is reset during loading + ordenador.tape_start_countdwn=0; } // check if there's contention and waits the right number of tstates diff --git a/src/computer.h b/src/computer.h index a28971d..a0239a9 100644 --- a/src/computer.h +++ b/src/computer.h @@ -100,7 +100,7 @@ struct computer { unsigned char s8,s9,s10,s11,s12,s13,s14,s15; unsigned char k8,k9,k10,k11,k12,k13,k14,k15; unsigned char readed; - unsigned char tab_extended; + //unsigned char tab_extended; unsigned char esc_again; // kempston joystick private global variables @@ -187,6 +187,7 @@ struct computer { unsigned int tape_bit1_level; unsigned char tape_bits_at_end; unsigned int tape_loop_counter; + unsigned int tape_start_countdwn; long tape_loop_pos; unsigned char tape_write; // 0 can't write; 1 can write diff --git a/src/emulator.c b/src/emulator.c index 7f56d8e..6c86830 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -1530,9 +1530,12 @@ int main(int argc,char *argv[]) { /* if PC is 0x0556, a call to LD_BYTES has been made, so if FAST_LOAD is 1, we must load the block in memory and return */ - if((!ordenador.mdr_paged)&&(PC==0x0556) && (ordenador.tape_fast_load==1)&&(ordenador.tape_file_type==TAP_TAP)) { + if((!ordenador.mdr_paged)&&(PC==0x056c) && (ordenador.tape_fast_load==1)) { if(ordenador.tap_file!=NULL) - fastload_block(ordenador.tap_file); + { + if (ordenador.tape_file_type==TAP_TAP) fastload_block_tap(ordenador.tap_file); + else fastload_block_tzx(ordenador.tap_file); + } else { sprintf(ordenador.osd_text,"No TAP file selected"); ordenador.osd_time=50; diff --git a/src/gui_sdl.c b/src/gui_sdl.c index a739688..604c491 100644 --- a/src/gui_sdl.c +++ b/src/gui_sdl.c @@ -80,7 +80,7 @@ static const char *emulation_messages[] = { /*01*/ "^|48k_2|48K_3|128k|+2|+2A/+3|128K_Sp|NTSC", /*02*/ "Frame rate", /*03*/ "^|100%|50%|33%|25%|20%", - /*04*/ "Tap instant load", + /*04*/ "Tape instant load", /*05*/ "^|on|off", /*06*/ "Turbo mode", /*07*/ "^|off|auto|fast|ultrafast", @@ -369,8 +369,9 @@ static int manage_tape(int which) break; case 1: //Emulate load "" countdown_buffer=8; - if (ordenador.mode128k==4) //Spanish 128k - { + switch (ordenador.mode128k) + { + case 4://Spanish 128k ordenador.keyboard_buffer[0][8]= SDLK_l; ordenador.keyboard_buffer[1][8]= 0; ordenador.keyboard_buffer[0][7]= SDLK_o; @@ -388,9 +389,18 @@ static int manage_tape(int which) ordenador.keyboard_buffer[0][1]= SDLK_F6; //F6 - play ordenador.keyboard_buffer[1][1]= 0; ordenador.kbd_buffer_pointer=8; - } - else - { + break; + case 3: //+3 + case 2: //+2 + case 1: //128k + ordenador.keyboard_buffer[0][2]= SDLK_RETURN; // Return + ordenador.keyboard_buffer[1][2]= 0; + ordenador.keyboard_buffer[0][1]= SDLK_F6; //F6 - play + ordenador.keyboard_buffer[1][1]= 0; + ordenador.kbd_buffer_pointer=2; + break; + case 0: //48k + default: ordenador.keyboard_buffer[0][5]= SDLK_j; //Load ordenador.keyboard_buffer[1][5]= 0; ordenador.keyboard_buffer[0][4]= SDLK_p; //" @@ -402,16 +412,17 @@ static int manage_tape(int which) ordenador.keyboard_buffer[0][1]= SDLK_F6; //F6 ordenador.keyboard_buffer[1][1]= 0; ordenador.kbd_buffer_pointer=5; - } + break; + } retorno=-1; - break; + break; case 2: //Play - if ((ordenador.tape_fast_load == 0) || (ordenador.tape_file_type==TAP_TZX)) + //if (ordenador.tape_fast_load == 0) ordenador.pause = 0; retorno=-1; break; case 3: //Stop - if ((ordenador.tape_fast_load == 0) || (ordenador.tape_file_type==TAP_TZX)) + //if (ordenador.tape_fast_load == 0) ordenador.pause = 1; retorno=-1; break; @@ -1088,7 +1099,7 @@ static int save_scr(int i) switch(retorno) { case 0: - if (i==1) msgInfo("SCR1 saved",3000,NULL); else msgInfo("SCR2 saved",3000,NULL); + if (i==1) msgInfo("Screen 1 saved",3000,NULL); else msgInfo("Screen 2 saved",3000,NULL); retorno2=-2; //come back to emulator break; case -1: diff --git a/src/tape.c b/src/tape.c index 6566168..3ef4856 100644 --- a/src/tape.c +++ b/src/tape.c @@ -24,6 +24,15 @@ #include "menus.h" #include "tape.h" +#ifdef DEBUG +extern FILE *fdebug; +#define printf(...) fprintf(fdebug,__VA_ARGS__) +#else + #ifdef GEKKO + #define printf(...) + #endif +#endif + int elcontador=0; int eltstado=0; char elbit=0; @@ -47,7 +56,8 @@ inline void tape_read(FILE *fichero, int tstados) { //Auto ultra fast mode if ((ordenador.turbo_state != 4)&&(ordenador.turbo==1)) { - update_frequency(11000000); + if (ordenador.tape_file_type==TAP_TAP) update_frequency(13000000); + else update_frequency(11000000); jump_frames=7; ordenador.precision_old=ordenador.precision; ordenador.precision =0; @@ -82,6 +92,7 @@ inline void tape_read_tap (FILE * fichero, int tstados) { } ordenador.tape_byte_counter = ((unsigned int) value) + 256 * ((unsigned int) value2); retval=fread (&(ordenador.tape_byte), 1, 1, fichero); + printf("TAP: Flag_byte_norm: %X en %ld\n",ordenador.tape_byte,ftell(fichero)); ordenador.tape_bit = 0x80; ordenador.tape_current_mode = TAP_GUIDE; ordenador.tape_counter0 = 2168; @@ -139,8 +150,8 @@ inline void tape_read_tap (FILE * fichero, int tstados) { ordenador.tape_counter0 = 1710 - tstados; ordenador.tape_counter1 = 1710; } else { - ordenador.tape_counter0 = 851 - tstados; - ordenador.tape_counter1 = 852; + ordenador.tape_counter0 = 855 - tstados; + ordenador.tape_counter1 = 855; } ordenador.tape_bit = ((ordenador.tape_bit >> 1) & 0x7F); // from bit0 to bit7 if (!ordenador.tape_bit) { @@ -195,7 +206,7 @@ inline void tape_read_tzx (FILE * fichero, int tstados) { done = 0; do { retval=fread(&value,1,1,fichero); // read block ID - //printf("ID: %X en %d\n",value,ftell(fichero)); + printf("TZX:ID_normal: %X en %ld\n",value,ftell(fichero)); if(feof(fichero)) done = 1; else @@ -204,7 +215,7 @@ inline void tape_read_tzx (FILE * fichero, int tstados) { done = 1; bucle = 0; ordenador.tape_current_bit = 0; - ordenador.tape_bit0_level = 852; + ordenador.tape_bit0_level = 855; ordenador.tape_bit1_level = 1710; ordenador.tape_bits_at_end = 8; ordenador.tape_block_level = 2168; @@ -431,9 +442,14 @@ inline void tape_read_tzx (FILE * fichero, int tstados) { case 0x31: // show text retval=fread(&value2,1,1,fichero); + if (value2 < 11) ordenador.osd_time=value2*50; else ordenador.osd_time=500; //max 10 sec retval=fread(&value2,1,1,fichero); // length for(bucle=0;bucle<((unsigned int)value2);bucle++) - retval=fread(&value3,1,1,fichero); + { + retval=fread(&value3,1,1,fichero); + if (bucle<199) ordenador.osd_text[bucle] = value3; + } + if (bucle>199) ordenador.osd_text[199]=0; else ordenador.osd_text[bucle]=0; break; case 0x32: // archive info @@ -704,21 +720,40 @@ void save_file(FILE *fichero) { return; } -void fastload_block (FILE * fichero) { +void fastload_block_tap (FILE * fichero) { - unsigned int longitud; - unsigned char value[65536], salir,empty,flag_found; - unsigned int veces; + /*Frome Fuse On exit: + * A = calculated parity byte if parity checked, else 0 (CHECKME) + * F : if parity checked, all flags are modified + * else carry only is modified (FIXME) + * B = 0xB0 (success) or 0x00 (failure) + * C = 0x01 (confirmed), 0x21, 0xFE or 0xDE (CHECKME) + * DE : decremented by number of bytes loaded or verified + * H = calculated parity byte or undefined + * L = last byte read, or 1 if none + * IX : incremented by number of bytes loaded or verified + * A' = unchanged on error + no flag byte, else 0x01 + * F' = 0x01 on error + no flag byte, else 0x45 + * R = no point in altering it :-) + * Other registers unchanged. + */ + + unsigned int longitud, bucle, number_bytes; + unsigned char value[65536], empty, parity; int retval; - ordenador.other_ret = 1; // next instruction must be RET + //ordenador.other_ret = 1; // next instruction must be RET + procesador.PC=0x5e2; - if (!(procesador.Rm.br.F & F_C)) { // if Carry=0, is VERIFY, so return OK + if (!(procesador.Ra.br.F & F_C)) { // if Carry=0, is VERIFY, so return OK procesador.Rm.br.F |= F_C; // verify OK procesador.Rm.wr.IX += procesador.Rm.wr.DE; procesador.Rm.wr.DE = 0; return; } + + procesador.Rm.br.B=0; + procesador.Rm.br.L=0x01; empty=file_empty(fichero); @@ -735,65 +770,394 @@ void fastload_block (FILE * fichero) { return; } - veces=0; - - flag_found=0; - do { - retval=fread (value, 2, 1, fichero); // read length of current block + retval=fread (value, 1, 2, fichero); // read length of current block if (feof (fichero)) { // end of file? - veces++; // one more time rewinded - sprintf (ordenador.osd_text, "Tape rewind"); + sprintf (ordenador.osd_text, "Rewind tape"); ordenador.osd_time = 100; - rewind (fichero); // again - retval=fread (value, 2, 1, fichero); // read length of current block - } - longitud = ((unsigned int) value[0]) + 256 * ((unsigned int) value[1]); - retval=fread (value, 1, 1, fichero); // read flag byte - longitud--; - if (value[0] != procesador.Rm.br.A) { // different flag - retval=fread (value, longitud, 1, fichero); // jump to the next block - if (veces==3) { // tape rewinded three times? Block with that flag not found. - sprintf(ordenador.osd_text,"Block with right flag not found"); - ordenador.osd_time = 100; - procesador.Rm.br.F &= (~F_C); // Load error - return; + rewind_tape(fichero, 1); + return; } - } else - flag_found = 1; - } while(flag_found == 0); + + longitud = ((unsigned int) value[0]) + 256 * ((unsigned int) value[1]); + + retval=fread (value, 1,1, fichero); //Flag Byte + if (retval!=1) + { + procesador.Rm.br.F &= (~F_C); // Load error + procesador.Rm.wr.IX += procesador.Rm.wr.DE; + procesador.Rm.wr.DE = 0; + printf("TAP: Read file error\n"); + return; + } - salir = 0; - do { - if (longitud == 0) - salir = 1; - if (procesador.Rm.wr.DE == 0) - salir = 2; - if (!salir) { - retval=fread (value, 1, 1, fichero); // read byte - Z80free_Wr_fake (procesador.Rm.wr.IX, (byte) value[0]); // store the byte + longitud--; + printf("TAP: Flag_byte_fast: %X en %ld\n",value[0],ftell(fichero)); + + if (value[0] != procesador.Ra.br.A) // different flag + { + procesador.Rm.br.F &= (~F_C); // Load error + procesador.Rm.wr.IX += procesador.Rm.wr.DE; + procesador.Rm.wr.DE = 0; + retval=fread (value, 1,longitud, fichero); //read the remaining bytes + printf("TAP: Flag byte error, expected %X\n", procesador.Ra.br.A); + return; + } + + parity=(byte) value[0]; + + if ((longitud-1)!=procesador.Rm.wr.DE) + { + printf("TAP: length block error\n"); + printf("TAP: expected by system %d\n", procesador.Rm.wr.DE); + printf("TAP: expected by file %d\n", longitud-1); + } + + if (procesador.Rm.wr.DE>(longitud-1)) + { + procesador.Rm.br.F &= (~F_C); // Load error + procesador.Rm.wr.IX += procesador.Rm.wr.DE; + procesador.Rm.wr.DE = 0; + retval=fread (value, 1,longitud, fichero); //read the remaining bytes + return; + } + + retval=fread (value, 1,longitud, fichero); + if (retval!=longitud) + { + procesador.Rm.br.F &= (~F_C); // Load error + procesador.Rm.wr.IX += procesador.Rm.wr.DE; + procesador.Rm.wr.DE = 0; + printf("TAP: Read file error\n"); + return; + } + + number_bytes=procesador.Rm.wr.DE; + + for(bucle=0;bucle 1) - retval=fread (value, longitud, 1, fichero); // jump to the next block - return; - } - - retval=fread (value, 1, 1, fichero); // jump over the checksum + parity^=value[number_bytes]; // checksum + + if (parity) printf("TAP: Parity error\n"); + + procesador.Rm.br.A=parity; + //CP 01 + Z80free_doArithmetic(&procesador,procesador.Rm.br.A,0x01,0,1); + Z80free_adjustFlags(&procesador,0x01); + + procesador.Rm.br.B=0xB0; + procesador.Rm.br.C=0x01; + procesador.Rm.br.H=parity; + procesador.Rm.br.L=value[longitud-1]; + procesador.Ra.br.A=0x01; + procesador.Ra.br.F=0x45; procesador.Rm.br.F |= F_C; // Load OK + + //if (longitud==6913) sleep(2); //Screen + return; +} + +void fastload_block_tzx (FILE * fichero) { + + /* From Fuse - On exit: + * A = calculated parity byte if parity checked, else 0 (CHECKME) + * F : if parity checked, all flags are modified + * else carry only is modified (FIXME) + * B = 0xB0 (success) or 0x00 (failure) + * C = 0x01 (confirmed), 0x21, 0xFE or 0xDE (CHECKME) + * DE : decremented by number of bytes loaded or verified + * H = calculated parity byte or undefined + * L = last byte read, or 1 if none + * IX : incremented by number of bytes loaded or verified + * A' = unchanged on error + no flag byte, else 0x01 + * F' = 0x01 on error + no flag byte, else 0x45 + * R = no point in altering it :-) + * Other registers unchanged. + */ + + unsigned int longitud, len, bucle, number_bytes, byte_position; + unsigned char value[65536], empty, blockid, parity; + int retval; + fpos_t *file_pos; + + + //ordenador.other_ret = 1; // next instruction must be RET + procesador.PC=0x5e2; + longitud =0; + + if (!(procesador.Ra.br.F & F_C)) { // if Carry=0, is VERIFY, so return OK + procesador.Rm.br.F |= F_C; // verify OK + procesador.Rm.wr.IX += procesador.Rm.wr.DE; + procesador.Rm.wr.DE = 0; + return; + } + + procesador.Rm.br.B=0; + procesador.Rm.br.L=0x01; + + empty=file_empty(fichero); + + + if ((fichero == NULL)||(empty)) { + procesador.Rm.br.F &= (~F_C); // Load error + procesador.Rm.wr.IX += procesador.Rm.wr.DE; + procesador.Rm.wr.DE = 0; + if(empty) + sprintf (ordenador.osd_text, "Tape file empty"); + else + sprintf (ordenador.osd_text, "No tape selected"); + ordenador.osd_time = 100; + return; + } + + do { + retval=fread (&blockid, 1, 1, fichero); //Read id block + if (feof (fichero)) // end of file? + { + sprintf (ordenador.osd_text, "Rewind tape"); + ordenador.osd_time = 100; + rewind_tape(fichero, 1); + return; + } + printf("TZX: ID_fast: %X en %ld\n",blockid,ftell(fichero)); + switch(blockid) { + case 0x10: // classic tape block + retval=fread (value, 1, 2, fichero); //pause lenght + retval=fread (value, 1, 2, fichero); // read length of current block + if (retval!=2) + { + procesador.Rm.br.F &= (~F_C); // Load error + procesador.Rm.wr.IX += procesador.Rm.wr.DE; + procesador.Rm.wr.DE = 0; + printf("TZX: Read file error\n"); + return; + } + longitud = ((unsigned int) value[0]) + 256 * ((unsigned int) value[1]); + break; + + case 0x11: // turbo + retval=fread(value,1,0x0F, fichero); + retval=fread (value, 1,3 ,fichero); // read length of current block + if (retval!=3) {procesador.Rm.br.F &= (~F_C);return;} + longitud = ((unsigned int) value[0]) + 256 * ((unsigned int) value[1])+ 65536 * ((unsigned int) value[2]); + for(bucle=0;bucle199) ordenador.osd_text[199]=0; else ordenador.osd_text[bucle]=0; + break; + + case 0x32: // archive info + retval=fread(value,1,2,fichero); // length + if (retval!=2) {procesador.Rm.br.F &= (~F_C);return;} + len = ((unsigned int) value[0]) + 256 * ((unsigned int) value[1]); + retval=fread(value,1,len,fichero); + break; + + case 0x33: // hardware info + retval=fread(value,1,1,fichero); + if (retval!=1) {procesador.Rm.br.F &= (~F_C);return;} + len = (unsigned int) value[0] *3; + retval=fread(value,1,len,fichero); + break; + + case 0x34: // emulation info + retval=fread(value,1,8,fichero); + break; + + case 0x35: // custom info + retval=fread(value,1,16,fichero); + retval=fread(value,1,4,fichero); + if (retval!=4) {procesador.Rm.br.F &= (~F_C);return;} + len = ((unsigned int) value[0]) + 256 * ((unsigned int) value[1]) + 65536*((unsigned int) value[2]);// + 16777216*((unsigned int) value[3]); + retval=fread(value,1,len,fichero); + break; + + default: // not supported + procesador.Rm.br.F &= (~F_C);return; //Tape error + break; + } + } while ((blockid!=0x10)&&(!feof(fichero))); + + if (feof(fichero)) {procesador.Rm.br.F &= (~F_C);return;} + + //Fast load routine + + retval=fread (value, 1,1, fichero); //Flag Byte + if (retval!=1) + { + procesador.Rm.br.F &= (~F_C); // Load error + procesador.Rm.wr.IX += procesador.Rm.wr.DE; + procesador.Rm.wr.DE = 0; + printf("TZX: Read file error\n"); + return; + } + + longitud--; + printf("TZX: Flag_byte_fast: %X en %ld\n",value[0],ftell(fichero)); + + if (value[0] != procesador.Ra.br.A) // different flag + { + procesador.Rm.br.F &= (~F_C); // Load error + procesador.Rm.wr.IX += procesador.Rm.wr.DE; + procesador.Rm.wr.DE = 0; + retval=fread (value, 1,longitud, fichero); //read the remaining bytes + printf("TZX Flag byte error, expected %X\n", procesador.Ra.br.A); + return; + } + + parity=(byte) value[0]; + + if ((longitud-1)!=procesador.Rm.wr.DE) + { + printf("TZX: length block error\n"); + printf("TZX: expected by system %d\n", procesador.Rm.wr.DE); + printf("TZX: expected by file %d\n", longitud-1); + } + + if (procesador.Rm.wr.DE>(longitud-1)) + { + procesador.Rm.br.F &= (~F_C); // Load error + procesador.Rm.wr.IX += procesador.Rm.wr.DE; + procesador.Rm.wr.DE = 0; + retval=fread (value, 1,longitud, fichero); //read the remaining bytes + return; + } + + retval=fread (value, 1,longitud, fichero); + if (retval!=longitud) + { + procesador.Rm.br.F &= (~F_C); // Load error + procesador.Rm.wr.IX += procesador.Rm.wr.DE; + procesador.Rm.wr.DE = 0; + printf("TZX: Read file error\n"); + return; + } + + number_bytes=procesador.Rm.wr.DE; + + for(bucle=0;bucle