Index: TODO ================================================================== --- TODO +++ TODO @@ -1,8 +1,9 @@ * Sound effects * Compressed wave sounds (?) * Numeric sounds (?) + * Band limited synthesis * Game engine features * String data (partially implemented) * A ,PopUp command to use a popup with arguments starting from a mark * Possibility to define auto-generation levels mode * Popup inventory list (with optional possibility of choice) (?) Index: heromesh.h ================================================================== --- heromesh.h +++ heromesh.h @@ -49,10 +49,11 @@ #define N_MESSAGES 30 #define N_STANDARD_SOUNDS 49 extern const char*const standard_message_names[]; extern const char*const standard_sound_names[]; extern const char*const heromesh_key_names[256]; +extern const char jispunct[]; extern sqlite3*userdb; extern xrm_db*resourcedb; extern const char*basefilename; extern xrm_quark optionquery[16]; @@ -89,10 +90,12 @@ unsigned char*read_lump_or_userstate(int sol,int lvl,long*sz,char us); void write_lump(int sol,int lvl,long sz,const unsigned char*data); void write_userstate(int sol,int lvl,long sz,const unsigned char*data); const char*load_level(int lvl); void set_cursor(int id); +Uint32*tron8to32(const Uint8*); +Uint8*tron32to8(const Uint32*); const char*log_if_error(const char*t); #define FIL_SOLUTION 1 #define FIL_LEVEL 0 #define LUMP_LEVEL_IDX (-1) Index: internals.doc ================================================================== --- internals.doc +++ internals.doc @@ -142,10 +142,28 @@ 27 (\T) = Multibyte character escape; used only during parsing 127 = Internal representation of % 254 = Plane shift 255 = Switch to ASCII until the next plane shift (internal only) + +Internally a variant of TRON-32 may be used during text editing (N.B.: this +feature is not implemented yet). In addition to TRON-32 characters, it also +uses the following codes: + +* Control codes, with the same values and meanings listed above except 16, +27, 31, 254, and 255. + +* ASCII codes 0x20 to 0x7E. (These may sometimes be converted to/from the +corresponding TRON characters, but are usually used within the text of a +\i or \d escape, and as the terminator.) + +* Codes 0x1000 to 0x10FF for quiz buttons. + +* Codes 0x1F00 to 0x1FFF for graphic characters. + +* Codes 0x7F20 to 0x7F7E for substitution codes (which converts to the +internal variant of TRON-8 as 127 and then the ASCII character). === User state data === The user state data for levels in the user cache database can be in the Index: main.c ================================================================== --- main.c +++ main.c @@ -44,10 +44,19 @@ "CREATE TEMPORARY TABLE `PICTURES`(`ID` INTEGER PRIMARY KEY, `NAME` TEXT COLLATE NOCASE, `OFFSET` INT, `DEPENDENT` INT, `MISC` BLOB);" "CREATE TEMPORARY TABLE `VARIABLES`(`ID` INTEGER PRIMARY KEY, `NAME` TEXT);" "CREATE TEMPORARY TABLE `DIVISIONS`(`HEADING` BLOB NOT NULL, `FIRST` INT NOT NULL);" "COMMIT;" ; + +const char jispunct[0x60]= + " ,.,. :;?! '` " + "^~_ ---/" + "\\~|| ''\"\"() []" + "{}<> +- " + " = <> '\" \\" + "$ #%#&*@ " +; sqlite3*userdb; xrm_db*resourcedb; const char*basefilename; xrm_quark optionquery[16]; @@ -764,10 +773,152 @@ void set_cursor(int id) { id>>=1; if(!cursor[id]) cursor[id]=SDL_CreateCursor((void*)cursorimg+(id<<6),(void*)cursorimg+(id<<6)+32,16,16,cursorhot[id]>>4,cursorhot[id]&15); SDL_SetCursor(cursor[id]); } + +Uint32*tron8to32(const Uint8*si) { + // This function does not interpret the internal-only 0xFF code, which will be implemented in picture.c instead. + Uint16 cs=0; + int n=0; + Uint32*so=0; + int k=0; + if(*si==0xFE) { + // TRON + for(k=0;si[k];k++) { + if(si[k]==31 && si[k+1]) { + n+=2; + k++; + } else if(si[k]==14 || si[k]==30) { + while(si[k] && si[k]!='\\') { + n+=2; + k++; + } + n+=2; + } else if(si[k]==0xFE) { + n--; + while(si[k+1]==0xFE) k++; + } else { + n++; + if(si[k]<=0x20) n++; + } + } + so=calloc(sizeof(Uint32),(n>>=1)+2); + if(!so) fatal("Allocation failed\n"); + n++; k=0; + while(*si && k0x20) { + so[k++]=(si[0]<<8)|si[1]|(cs<<16); + si+=2; + } else { + si++; + } + } + } else { + // ASCII + so=calloc(sizeof(Uint32),(n=strlen(si))+1); + if(!so) fatal("Allocation failed\n"); + while(*si) { + if(*si==16 || *si==31 || *si==127) { + if(!si[1]) break; + so[k++]=(si[0]<<8)|si[1]; + si+=2; + } else { + so[k++]=*si++; + } + } + } + return so; +} + +Uint8*tron32to8(const Uint32*si) { + Uint16 cs=0; + int i; + Uint8*so=0; + size_t sz=0; + FILE*f=open_memstream((char**)&so,&sz); + if(!f) fatal("Allocation failed\n"); + for(i=0;si[i];i++) if(si[i]>0x200000) goto nonascii; + while(*si) { + if(*si<0x7F) { + fputc(*si++,f); + } else if(*si>=0x1000 && *si<=0x10FF) { + fputc(16,f); + fputc((*si++&0xFF)?:0x20,f); + } else if(*si>=0x1F00 && *si<=0x1FFF) { + fputc(31,f); + fputc((*si++&0xFF)?:0xFF,f); + } else if(*si>=0x7F20 && *si<0x7F7F) { + fputc('%',f); + fputc(*si++&0xFF,f); + } + } + nonascii: + while(*si) { + if(*si>0x200000) { + if(cs!=(*si>>16)) { + cs=*si>>16; + for(i=cs>>8;i>=0;i--) fputc(0xFE,f); + fputc(cs,f); + } + fputc(*si>>8,f); + fputc(*si++,f); + } else if(*si<0x21) { + fputc(i=*si++,f); + if(i==14 || i==30) while(*si) { + if(*si=='\\') { + fputc(*si++,f); + break; + } else if(*si<0xFE || (*si>=0x702221 && *si<0x70227F) || (*si>=0x212330 && *si<0x21237B)) { + fputc(*si++,f); + } else if(*si>=0x212121 && *si<0x21217F) { + fputc(jispunct[*si++-0x212120],f); + } else if(*si<0xFE) { + fputc(*si++,f); + } else { + fputc(' ',f); + si++; + } + } + } else if(*si<0x7F) { + if(cs!=0x70) { + cs=0x70; + fputc(0xFE,f); + fputc(0x70,f); + } + fputc(0x22,f); + fputc(*si++,f); + } else if(*si>=0x1000 && *si<=0x10FF) { + fputc(16,f); + fputc(*si++?:0x20,f); + } else if(*si>=0x1F00 && *si<=0x1FFF) { + fputc(31,f); + fputc(*si++?:0xFF,f); + } else if(*si>=0x7F20 && *si<0x7F7F) { + fputc(127,f); + fputc(*si++,f); + } else { + si++; + } + } + fputc(0,f); + fclose(f); + if(!so) fatal("Allocation failed\n"); + return so; +} static void set_path(const char*arg) { const char*s; if(main_options['h']) goto home; if((s=getenv("HEROMESH_PREFIX")) && *s) { @@ -852,22 +1003,27 @@ while(SDL_WaitEvent(&ev)) switch(ev.type) { case SDL_KEYDOWN: switch(ev.key.keysym.sym) { case SDLK_BACKSPACE: n/=10; - snprintf(buf,30,"%u",n); - SDL_WM_SetCaption(buf,buf); - break; + goto setnum; case SDLK_SPACE: n=0; SDL_WM_SetCaption("0","0"); break; case SDLK_0 ... SDLK_9: n=10*n+ev.key.keysym.sym-SDLK_0; + setnum: snprintf(buf,30,"%u",n); SDL_WM_SetCaption(buf,buf); break; + case SDLK_KP_MINUS: + if(n) n--; + goto setnum; + case SDLK_KP_PLUS: + n++; + goto setnum; case SDLK_c: SDL_FillRect(screen,0,n); SDL_Flip(screen); break; case SDLK_e: @@ -882,10 +1038,24 @@ if(picture_size*(i+1)>screen->w) i=0,j++; if(picture_size*(j+1)>screen->h) break; draw_picture(picture_size*i,picture_size*j,n++); } SDL_Flip(screen); + break; + case SDLK_o: + if(n<0x4000 && classes[n] && classes[n]->gamehelp) { + Uint32*a=tron8to32(classes[n]->gamehelp); + Uint8*b=tron32to8(a); + for(i=0;classes[n]->gamehelp[i];i++) printf("%02X ",classes[n]->gamehelp[i]&0xFF); + puts(";"); + for(i=0;a[i];i++) printf("%08X ",a[i]); + puts(";"); + for(i=0;b[i];i++) printf("%02X ",b[i]); + puts("."); + free(a); + free(b); + } break; case SDLK_p: sqlite3_exec(userdb,"SELECT * FROM `PICTURES`;",test_sql_callback,0,0); break; case SDLK_q: @@ -1141,10 +1311,11 @@ if(main_options['z']) init_composite(); load_pictures(); if(main_options['T']) { printf("argv[0] = %s\n",argv[0]); init_sound(); + if(main_options['+']) load_classes(); test_mode(); return 0; } if(main_options['n']) { new_puzzle_set(); Index: picture.c ================================================================== --- picture.c +++ picture.c @@ -988,15 +988,17 @@ if(fontdata && fontdata!=pcfont) fatal("Multiple code page specifications\n"); optionquery[1]=Q_codepage; v=xrm_get_resource(resourcedb,optionquery,optionquery,2); if(!v || !*v) { if(n==437 || ignore_code_page()) return; + if(main_options['T']) goto done; fatal("Cannot load code page %d; code page file is not configured\n",n); } fp=fopen(v,"r"); if(!fp) { perror(0); + if(main_options['T']) goto done; fatal("Cannot open code page file\n"); } fontdata=d=malloc(0x800); if(!d) fatal("Allocation failed\n"); memcpy(d,pcfont,0x800); @@ -1003,10 +1005,11 @@ name: s=i=0; for(;;) { c=fgetc(fp); if(c<0) { + if(main_options['T']) goto done; if(n!=437 && !ignore_code_page()) fatal("Cannot find code page %d\n",n); goto done; } if(!c) break; if(!s) {