Free Hero Mesh

Check-in [d15195a921]
Login
This is a mirror of the main repository for Free Hero Mesh. New tickets and changes will not be accepted at this mirror.
Overview
Comment:Implement the Sound instruction. (There are still a few problems such as clicks at the end of some sound effects, and a few problems with the sound test menu. However, it mostly works, now.)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: d15195a921f6ff832bdb135bfb43a272f2294636
User & Date: user on 2022-01-29 05:55:37
Other Links: manifest | tags
Context
2022-02-04
06:56
Correct parsing instruction names beginning with a plus and minus sign. check-in: 547bf4ed86 user: user tags: trunk
2022-01-29
05:55
Implement the Sound instruction. (There are still a few problems such as clicks at the end of some sound effects, and a few problems with the sound test menu. However, it mostly works, now.) check-in: d15195a921 user: user tags: trunk
2022-01-25
06:31
Implement (attribute userflags) syntax, in order to access bit patterns of user flags directly in class codes (e.g. so that they can be passed to subroutines, etc). check-in: a724f44255 user: user tags: trunk
Changes

Modified TODO from [c921c09e17] to [a63cc0af2f].

1
2
3
4
5
6
7
8
9
10
11
12
13
* Sound effects
  * Wave sounds
    * Standard sounds
    * User sounds
    * Compressed wave sounds (?)
  * MML sounds
  * Numeric sounds (?)
* Game engine features
  * Multiple connected objects moving as a unit
  * String data (partially implemented)
  * A ,PopUp command to use a popup with arguments starting from a mark
  * "Goto message" instruction (?)
  * Returning a class from COLLIDE/COLLIDEBY to transform

<
<
<
|
<







1



2

3
4
5
6
7
8
9
* Sound effects



  * Compressed wave sounds (?)

  * Numeric sounds (?)
* Game engine features
  * Multiple connected objects moving as a unit
  * String data (partially implemented)
  * A ,PopUp command to use a popup with arguments starting from a mark
  * "Goto message" instruction (?)
  * Returning a class from COLLIDE/COLLIDEBY to transform

Modified bindings.doc from [09ad0658cd] to [ba75b7ef57].

229
230
231
232
233
234
235



236
237
238
239
240
241
242

'^P'
  Switch to the game play.

'^Q'
  Quit.




'go' <level>
  Go to the specified level. If the level number is negative, then it is
  a level order number, otherwise it is a level ID number.


=== Mode-independent commands ===








>
>
>







229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245

'^P'
  Switch to the game play.

'^Q'
  Quit.

'^Y'
  Sound test. (Does nothing if sound is not configured.)

'go' <level>
  Go to the specified level. If the level number is negative, then it is
  a level order number, otherwise it is a level ID number.


=== Mode-independent commands ===

Modified class.c from [633629bcf7] to [5513be6ecd].

524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
      break;
    case '$':
      if(fl) ParseError("Invalid use of , and = in token\n");
      tokent=TF_NAME;
      tokenv=look_class_name()+0x4000;
      break;
    case '!':
      // Just ignore sounds for now
      if(fl) ParseError("Invalid use of , and = in token\n");
      tokent=TF_NAME;
      tokenv=0x0400;
      break;
    case '%':
      if(fl&TF_COMMA) ParseError("Invalid use of , in token\n");
      tokent=TF_NAME|TF_ABNORMAL|fl;
      tokenv=OP_LOCAL;
      break;
    case '@':







<


|







524
525
526
527
528
529
530

531
532
533
534
535
536
537
538
539
540
      break;
    case '$':
      if(fl) ParseError("Invalid use of , and = in token\n");
      tokent=TF_NAME;
      tokenv=look_class_name()+0x4000;
      break;
    case '!':

      if(fl) ParseError("Invalid use of , and = in token\n");
      tokent=TF_NAME;
      tokenv=find_user_sound(tokenstr);
      break;
    case '%':
      if(fl&TF_COMMA) ParseError("Invalid use of , in token\n");
      tokent=TF_NAME|TF_ABNORMAL|fl;
      tokenv=OP_LOCAL;
      break;
    case '@':
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
  if(tokent==TF_INT) {
    return NVALUE(tokenv);
  } else if(Tokenf(TF_NAME)) {
    switch(tokenv) {
      case 0x0000 ... 0x00FF: return NVALUE(tokenv);
      case 0x0100 ... 0x01FF: return NVALUE(tokenv-0x0200);
      case 0x0200 ... 0x02FF: return MVALUE(tokenv&255);
      case 0x0300 ... 0x03FF: return UVALUE(0,TY_SOUND);
      case 0x0400 ... 0x04FF: return UVALUE(0,TY_USOUND);
      case 0x4000 ... 0x7FFF: return CVALUE(tokenv-0x4000);
      case OP_STRING: return UVALUE(pool_string(tokenstr),TY_STRING);
      case OP_BITCONSTANT ... OP_BITCONSTANT_LAST: return NVALUE(1<<(tokenv&31));
      case 0xC000 ... 0xFFFF: return MVALUE(tokenv-0xBF00);
    }
  }
  ParseError("Constant value expected\n");







|
|







1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
  if(tokent==TF_INT) {
    return NVALUE(tokenv);
  } else if(Tokenf(TF_NAME)) {
    switch(tokenv) {
      case 0x0000 ... 0x00FF: return NVALUE(tokenv);
      case 0x0100 ... 0x01FF: return NVALUE(tokenv-0x0200);
      case 0x0200 ... 0x02FF: return MVALUE(tokenv&255);
      case 0x0300 ... 0x03FF: return UVALUE(tokenv&255,TY_SOUND);
      case 0x0400 ... 0x04FF: return UVALUE(tokenv&255,TY_USOUND);
      case 0x4000 ... 0x7FFF: return CVALUE(tokenv-0x4000);
      case OP_STRING: return UVALUE(pool_string(tokenstr),TY_STRING);
      case OP_BITCONSTANT ... OP_BITCONSTANT_LAST: return NVALUE(1<<(tokenv&31));
      case 0xC000 ... 0xFFFF: return MVALUE(tokenv-0xBF00);
    }
  }
  ParseError("Constant value expected\n");

Modified default.heromeshrc from [7f0656bbc7] to [eab9494892].

182
183
184
185
186
187
188

189
190
191
?.?.kp_plus: select 'go',-(level()+1) where level()<max_level();
?.?.shift.kp_minus: select 'go',-1;
?.?.shift.kp_plus: select 'go',-max_level();
?.?.ctrl.G: select 'go',-:Go_To_Level where :Go_To_Level=cast(:Go_To_Level as int) and cast(:Go_To_Level as int)>0;
?.?.ctrl.Q: ^Q
?.?.ctrl.S: ^S
?.?.ctrl.T: ^T

?.?.shift.ctrl.M: select ':s';
?.?.f10: select ':x';








>



182
183
184
185
186
187
188
189
190
191
192
?.?.kp_plus: select 'go',-(level()+1) where level()<max_level();
?.?.shift.kp_minus: select 'go',-1;
?.?.shift.kp_plus: select 'go',-max_level();
?.?.ctrl.G: select 'go',-:Go_To_Level where :Go_To_Level=cast(:Go_To_Level as int) and cast(:Go_To_Level as int)>0;
?.?.ctrl.Q: ^Q
?.?.ctrl.S: ^S
?.?.ctrl.T: ^T
?.?.ctrl.Y: ^Y
?.?.shift.ctrl.M: select ':s';
?.?.f10: select ':x';

Modified edit.c from [13e928d083] to [cc13f87281].

1844
1845
1846
1847
1848
1849
1850



1851
1852
1853
1854
1855
1856
1857
      return -1;
    case '^S': // Save level
      save_level();
      return 1;
    case '^T': // Level title
      edit_string(&level_title);
      return 0;



    case '^Z': // Cancel rectangle
      editrect.x0=editrect.y0=editrect.x1=editrect.y1=0;
      return prev;
    case '^<': // First corner
      if((number&63?:64)>pfwidth || (number/64?:64)>pfheight) return prev;
      editrect.x0=number&63?:64;
      editrect.y0=number/64?:64;







>
>
>







1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
      return -1;
    case '^S': // Save level
      save_level();
      return 1;
    case '^T': // Level title
      edit_string(&level_title);
      return 0;
    case '^Y': // Sound test
      sound_test();
      return prev;
    case '^Z': // Cancel rectangle
      editrect.x0=editrect.y0=editrect.x1=editrect.y1=0;
      return prev;
    case '^<': // First corner
      if((number&63?:64)>pfwidth || (number/64?:64)>pfheight) return prev;
      editrect.x0=number&63?:64;
      editrect.y0=number/64?:64;

Modified edit.doc from [a922353611] to [5f662b4d3a].

223
224
225
226
227
228
229

230
231
232
233
234
235
236
  CTRL+I    Level index editor
  CTRL+N    Add new level (after last one)
  CTRL+P    Switch to play game (won't auto save)
  CTRL+Q    Quit (won't auto save)
  CTRL+S    Save level
  CTRL+T    Edit level title
  CTRL+X    Clear level (delete all objects)

  C         Set level code number
  E         Edit level strings
  F         Fill grid with current MRU
  R         Clear and resize level
  W         Exchange main/bizarro worlds
  F1        Import level (replacing current level)
  F2        Export level







>







223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
  CTRL+I    Level index editor
  CTRL+N    Add new level (after last one)
  CTRL+P    Switch to play game (won't auto save)
  CTRL+Q    Quit (won't auto save)
  CTRL+S    Save level
  CTRL+T    Edit level title
  CTRL+X    Clear level (delete all objects)
  CTRL+Y    Sound test
  C         Set level code number
  E         Edit level strings
  F         Fill grid with current MRU
  R         Clear and resize level
  W         Exchange main/bizarro worlds
  F1        Import level (replacing current level)
  F2        Export level

Modified exec.c from [d3751950c5] to [a961423181].

2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
    case OP_STRENGTH: StackReq(0,1); Push(NVALUE(o->strength)); break;
    case OP_STRENGTH_C: StackReq(1,1); Push(GetVariableOrAttributeOf(strength,NVALUE)); break;
    case OP_STRENGTH_E: NoIgnore(); StackReq(1,0); t1=Pop(); Numeric(t1); o->strength=t1.u; break;
    case OP_STRENGTH_E16: NoIgnore(); StackReq(1,0); t1=Pop(); Numeric(t1); o->strength=t1.u&0xFFFF; break;
    case OP_STRENGTH_EC: NoIgnore(); StackReq(2,0); t1=Pop(); Numeric(t1); i=v_object(Pop()); if(i!=VOIDLINK) objects[i]->strength=t1.u; break;
    case OP_STRENGTH_EC16: NoIgnore(); StackReq(2,0); t1=Pop(); Numeric(t1); i=v_object(Pop()); if(i!=VOIDLINK) objects[i]->strength=t1.u&0xFFFF; break;
    case OP_STRING: StackReq(0,1); Push(UVALUE(code[ptr++],TY_STRING)); break;
    case OP_SOUND: StackReq(2,0); t2=Pop(); t1=Pop(); break; // Sound not implemented at this time
    case OP_SUB: StackReq(2,1); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); Push(NVALUE(t1.u-t2.u)); break;
    case OP_SUPER: i=code[1]; code=classes[i]->codes; ptr=get_message_ptr(i,msgvars.msg); if(ptr==0xFFFF) break; break;
    case OP_SUPER_C: i=code[1]; j=get_message_ptr(i,msgvars.msg); if(j!=0xFFFF) execute_program(classes[i]->codes,j,obj); break;
    case OP_SWAP: StackReq(2,2); t1=Pop(); t2=Pop(); Push(t1); Push(t2); break;
    case OP_SWAPWORLD: NoIgnore(); swap_world(); break;
    case OP_SWEEP: StackReq(8,0); v_sweep(obj,NVALUE(0)); break;
    case OP_SWEEPEX: StackReq(9,0); t1=Pop(); v_sweep(obj,t1); break;







|







2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
    case OP_STRENGTH: StackReq(0,1); Push(NVALUE(o->strength)); break;
    case OP_STRENGTH_C: StackReq(1,1); Push(GetVariableOrAttributeOf(strength,NVALUE)); break;
    case OP_STRENGTH_E: NoIgnore(); StackReq(1,0); t1=Pop(); Numeric(t1); o->strength=t1.u; break;
    case OP_STRENGTH_E16: NoIgnore(); StackReq(1,0); t1=Pop(); Numeric(t1); o->strength=t1.u&0xFFFF; break;
    case OP_STRENGTH_EC: NoIgnore(); StackReq(2,0); t1=Pop(); Numeric(t1); i=v_object(Pop()); if(i!=VOIDLINK) objects[i]->strength=t1.u; break;
    case OP_STRENGTH_EC16: NoIgnore(); StackReq(2,0); t1=Pop(); Numeric(t1); i=v_object(Pop()); if(i!=VOIDLINK) objects[i]->strength=t1.u&0xFFFF; break;
    case OP_STRING: StackReq(0,1); Push(UVALUE(code[ptr++],TY_STRING)); break;
    case OP_SOUND: StackReq(2,0); t2=Pop(); t1=Pop(); set_sound_effect(t1,t2); break;
    case OP_SUB: StackReq(2,1); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); Push(NVALUE(t1.u-t2.u)); break;
    case OP_SUPER: i=code[1]; code=classes[i]->codes; ptr=get_message_ptr(i,msgvars.msg); if(ptr==0xFFFF) break; break;
    case OP_SUPER_C: i=code[1]; j=get_message_ptr(i,msgvars.msg); if(j!=0xFFFF) execute_program(classes[i]->codes,j,obj); break;
    case OP_SWAP: StackReq(2,2); t1=Pop(); t2=Pop(); Push(t1); Push(t2); break;
    case OP_SWAPWORLD: NoIgnore(); swap_world(); break;
    case OP_SWEEP: StackReq(8,0); v_sweep(obj,NVALUE(0)); break;
    case OP_SWEEPEX: StackReq(9,0); t1=Pop(); v_sweep(obj,t1); break;

Modified game.c from [e517a0c994] to [73bec037e1].

1158
1159
1160
1161
1162
1163
1164



1165
1166
1167
1168
1169
1170
1171
    case '^Q': // Quit
      return -1;
    case '^S': // Save solution
      if(gameover==1) record_solution();
      return 1;
    case '^T': // Show title
      modal_draw_popup(level_title);



      return prev;
    case '^d': // Describe object
      describe_at(number-65);
      return prev;
    case '^g': // Display global variables
      global_examine();
      return prev;







>
>
>







1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
    case '^Q': // Quit
      return -1;
    case '^S': // Save solution
      if(gameover==1) record_solution();
      return 1;
    case '^T': // Show title
      modal_draw_popup(level_title);
      return prev;
    case '^Y': // Sound test
      sound_test();
      return prev;
    case '^d': // Describe object
      describe_at(number-65);
      return prev;
    case '^g': // Display global variables
      global_examine();
      return prev;

Modified game.doc from [7328cb695b] to [fefbd2794f].

139
140
141
142
143
144
145

146
147
148
149
150
151
152
  CTRL+G      Go to level
  CTRL+I      Import move list
  CTRL+L      List of levels
  CTRL+Q      Quit
  CTRL+S      Save solution
  CTRL+T      Display level title
  CTRL+X      Export move list

  F1          Replay 1 move
  F2          Replay 10 moves
  F3          Replay 100 moves
  F4          Replay 1000 moves
  SHIFT+F1    Rewind 1 move
  SHIFT+F2    Rewind 10 moves
  SHIFT+F3    Rewind 100 moves







>







139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
  CTRL+G      Go to level
  CTRL+I      Import move list
  CTRL+L      List of levels
  CTRL+Q      Quit
  CTRL+S      Save solution
  CTRL+T      Display level title
  CTRL+X      Export move list
  CTRL+Y      Sound test
  F1          Replay 1 move
  F2          Replay 10 moves
  F3          Replay 100 moves
  F4          Replay 1000 moves
  SHIFT+F1    Rewind 1 move
  SHIFT+F2    Rewind 10 moves
  SHIFT+F3    Rewind 100 moves

Modified sound.c from [8e65d6bcfc] to [cf457c80d7].

193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
    i--;
    j=fgetc(fp)<<16; j|=fgetc(fp)<<24; j|=fgetc(fp)<<0; j|=fgetc(fp)<<8;
    l_offset=ftell(fp); l_size=j;
    if(i>4 && nam[i-4]=='.' && nam[i-3]=='W' && nam[i-1]=='V' && (nam[i-2]=='A' || nam[i-2]=='Z')) {
      j=nam[i-2];
      nam[i-4]=0;
      if(is_user) {
        if(nusersounds>0x03FD) goto done;
        i=nusersounds++;
        usersounds=realloc(usersounds,nusersounds*sizeof(WaveSound));
        user_sound_names=realloc(user_sound_names,nusersounds*sizeof(Uint8*));
        if(!usersounds || !user_sound_names) fatal("Allocation failed\n");
        user_sound_names[i]=strdup(nam);
        if(!user_sound_names[i]) fatal("Allocation failed\n");
        ws=usersounds+i;







|







193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
    i--;
    j=fgetc(fp)<<16; j|=fgetc(fp)<<24; j|=fgetc(fp)<<0; j|=fgetc(fp)<<8;
    l_offset=ftell(fp); l_size=j;
    if(i>4 && nam[i-4]=='.' && nam[i-3]=='W' && nam[i-1]=='V' && (nam[i-2]=='A' || nam[i-2]=='Z')) {
      j=nam[i-2];
      nam[i-4]=0;
      if(is_user) {
        if(nusersounds>255) goto done;
        i=nusersounds++;
        usersounds=realloc(usersounds,nusersounds*sizeof(WaveSound));
        user_sound_names=realloc(user_sound_names,nusersounds*sizeof(Uint8*));
        if(!usersounds || !user_sound_names) fatal("Allocation failed\n");
        user_sound_names[i]=strdup(nam);
        if(!user_sound_names[i]) fatal("Allocation failed\n");
        ws=usersounds+i;
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
  Value v;
  char buf[256];
  if(main_options['T'] && main_options['v']) {
    if(mmltuning) printf("mmltempo=%d; mmlvolume=%d; mmltuning[96]=%d\n",(int)mmltempo,(int)mmlvolume,(int)mmltuning[96]);
    for(i=0;i<nusersounds;i++) printf("%d: %s (ptr=%p, len=%d bytes)\n",i,user_sound_names[i],usersounds[i].data,usersounds[i].len);
    fflush(stdout);
  }
  if(!screen) return;
  nitems=nstandardsounds+nusersounds+8;
  columns=(screen->w-16)/240?:1;
  scrmax=(nitems+columns-1)/columns;
  set_cursor(XC_arrow);
  redraw:
  SDL_FillRect(screen,0,0x02);
  r.x=r.y=0;







|







406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
  Value v;
  char buf[256];
  if(main_options['T'] && main_options['v']) {
    if(mmltuning) printf("mmltempo=%d; mmlvolume=%d; mmltuning[96]=%d\n",(int)mmltempo,(int)mmlvolume,(int)mmltuning[96]);
    for(i=0;i<nusersounds;i++) printf("%d: %s (ptr=%p, len=%d bytes)\n",i,user_sound_names[i],usersounds[i].data,usersounds[i].len);
    fflush(stdout);
  }
  if(!screen || !sound_on) return;
  nitems=nstandardsounds+nusersounds+8;
  columns=(screen->w-16)/240?:1;
  scrmax=(nitems+columns-1)/columns;
  set_cursor(XC_arrow);
  redraw:
  SDL_FillRect(screen,0,0x02);
  r.x=r.y=0;