1 /* -*- C++ -*-
2  *
3  *  ONScripter_command.cpp - Command executer of ONScripter
4  *
5  *  Copyright (c) 2001-2019 Ogapee. All rights reserved.
6  *
7  *  ogapee@aqua.dti2.ne.jp
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #include "ONScripter.h"
25 #if defined(LINUX) || defined(MACOSX) || defined(IOS)
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #elif defined(WIN32)
29 #include <direct.h>
30 #endif
31 #include "version.h"
32 
33 #if defined(MACOSX) && (SDL_COMPILEDVERSION >= 1208)
34 #include <CoreFoundation/CoreFoundation.h>
35 #endif
36 
37 extern SDL_TimerID timer_bgmfade_id;
38 extern "C" Uint32 SDLCALL bgmfadeCallback( Uint32 interval, void *param );
39 extern "C" void smpegCallback();
40 extern unsigned short convUTF162SJIS(unsigned short in);
41 
42 #define CONTINUOUS_PLAY
43 
yesnoboxCommand()44 int ONScripter::yesnoboxCommand()
45 {
46     bool yesno_flag = true;
47     if ( script_h.isName( "okcancelbox" ) ) yesno_flag = false;
48 
49     script_h.readInt();
50     script_h.pushVariable();
51 
52     script_h.readStr();
53     const char *mes1 = script_h.saveStringBuffer();
54     const char *mes2 = script_h.readStr();
55     ButtonLink *tmp_button_link = root_button_link.next;
56     root_button_link.next = NULL;
57     buildDialog(yesno_flag, mes1, mes2);
58 
59     show_dialog_flag = true;
60     dirty_rect.add(dialog_info.pos);
61     flush(refreshMode());
62 
63     while(1){
64         event_mode = WAIT_BUTTON_MODE;
65         waitEvent(-1);
66 
67         if (current_button_state.button == -1 ||
68             current_button_state.button == 2){
69             script_h.setInt(&script_h.pushed_variable, 0);
70             break;
71         }
72         else if (current_button_state.button == 1){
73             script_h.setInt(&script_h.pushed_variable, 1);
74             break;
75         }
76     }
77 
78     show_dialog_flag = false;
79     delete root_button_link.next->next;
80     delete root_button_link.next;
81     root_button_link.next = tmp_button_link;
82     dirty_rect.add(dialog_info.pos);
83     flush(refreshMode());
84 
85     return RET_CONTINUE;
86 }
87 
wavestopCommand()88 int ONScripter::wavestopCommand()
89 {
90     if ( wave_sample[MIX_WAVE_CHANNEL] ){
91         Mix_Pause( MIX_WAVE_CHANNEL );
92         Mix_FreeChunk( wave_sample[MIX_WAVE_CHANNEL] );
93         wave_sample[MIX_WAVE_CHANNEL] = NULL;
94     }
95     setStr( &wave_file_name, NULL );
96 
97     return RET_CONTINUE;
98 }
99 
waveCommand()100 int ONScripter::waveCommand()
101 {
102     wave_play_loop_flag = false;
103 
104     if (script_h.isName( "waveloop" ))
105         wave_play_loop_flag = true;
106 
107     wavestopCommand();
108 
109     setStr(&wave_file_name, script_h.readStr());
110     playSound(wave_file_name, SOUND_CHUNK, wave_play_loop_flag, MIX_WAVE_CHANNEL);
111 
112     return RET_CONTINUE;
113 }
114 
waittimerCommand()115 int ONScripter::waittimerCommand()
116 {
117     int count = script_h.readInt() + internal_timer - SDL_GetTicks();
118     if (count < 0) count = 0;
119 
120     event_mode = WAIT_TIMER_MODE;
121     waitEvent( count );
122 
123     return RET_CONTINUE;
124 }
125 
waitCommand()126 int ONScripter::waitCommand()
127 {
128     event_mode = WAIT_TIMER_MODE;
129     waitEvent( script_h.readInt() );
130 
131     return RET_CONTINUE;
132 }
133 
vspCommand()134 int ONScripter::vspCommand()
135 {
136     leaveTextDisplayMode();
137 
138     bool vsp2_flag = false;
139     if (script_h.isName("vsp2")) vsp2_flag = true;
140 
141     int no = script_h.readInt();
142     int v  = script_h.readInt();
143 
144     if (vsp2_flag){
145         sprite2_info[no].visible = (v==1)?true:false;
146         dirty_rect.add( sprite2_info[no].bounding_rect );
147     }
148     else{
149         sprite_info[no].visible = (v==1)?true:false;
150         dirty_rect.add( sprite_info[no].pos );
151     }
152 
153     return RET_CONTINUE;
154 }
155 
voicevolCommand()156 int ONScripter::voicevolCommand()
157 {
158     voice_volume = script_h.readInt();
159     if ( wave_sample[0] ) Mix_Volume( 0, voice_volume * MIX_MAX_VOLUME / 100 );
160 
161     return RET_CONTINUE;
162 }
163 
vCommand()164 int ONScripter::vCommand()
165 {
166     char buf[256];
167 
168     sprintf(buf, RELATIVEPATH "wav%c%s.wav", DELIMITER, script_h.getStringBuffer()+1);
169     playSound(buf, SOUND_CHUNK, false, MIX_WAVE_CHANNEL);
170 
171     return RET_CONTINUE;
172 }
173 
trapCommand()174 int ONScripter::trapCommand()
175 {
176     bool is_clicked = trap_mode & TRAP_CLICKED;
177 
178     if      ( script_h.isName( "lr_trap" ) ){
179         trap_mode = TRAP_LEFT_CLICK | TRAP_RIGHT_CLICK;
180     }
181     else if ( script_h.isName( "r_trap" ) ){
182         trap_mode = TRAP_RIGHT_CLICK;
183     }
184     else if ( script_h.isName( "trap" ) ){
185         trap_mode = TRAP_LEFT_CLICK;
186     }
187 
188     if ( script_h.compareString("off") ){
189         script_h.readLabel();
190         trap_mode = TRAP_NONE;
191         return RET_CONTINUE;
192     }
193     else if ( script_h.compareString("stop") ){
194         script_h.readLabel();
195         trap_mode |= TRAP_STOP;
196         return RET_CONTINUE;
197     }
198     else if ( script_h.compareString("resume") ){
199         script_h.readLabel();
200         if (is_clicked) trapHandler();
201         return RET_CONTINUE;
202     }
203 
204     const char *buf = script_h.readStr();
205     if ( buf[0] == '*' ){
206         setStr(&trap_dist, buf+1);
207     }
208     else{
209         printf("trapCommand: [%s] is not supported\n", buf );
210     }
211 
212     return RET_CONTINUE;
213 }
214 
transbtnCommand()215 int ONScripter::transbtnCommand()
216 {
217     transbtn_flag = true;
218 
219     return RET_CONTINUE;
220 }
221 
textspeeddefaultCommand()222 int ONScripter::textspeeddefaultCommand()
223 {
224     sentence_font.wait_time = -1;
225     return RET_CONTINUE;
226 }
227 
textspeedCommand()228 int ONScripter::textspeedCommand()
229 {
230     sentence_font.wait_time = script_h.readInt();
231 
232     return RET_CONTINUE;
233 }
234 
textshowCommand()235 int ONScripter::textshowCommand()
236 {
237     dirty_rect.fill( screen_width, screen_height );
238     refresh_shadow_text_mode = REFRESH_NORMAL_MODE | REFRESH_SHADOW_MODE | REFRESH_TEXT_MODE;
239     flush(refreshMode());
240 
241     return RET_CONTINUE;
242 }
243 
textonCommand()244 int ONScripter::textonCommand()
245 {
246     if (windowchip_sprite_no >= 0)
247         sprite_info[windowchip_sprite_no].visible = true;
248 
249     enterTextDisplayMode();
250 
251     text_on_flag = true;
252 
253     return RET_CONTINUE;
254 }
255 
textoffCommand()256 int ONScripter::textoffCommand()
257 {
258     if (windowchip_sprite_no >= 0)
259         sprite_info[windowchip_sprite_no].visible = false;
260 
261     leaveTextDisplayMode(true);
262 
263     text_on_flag = false;
264 
265     return RET_CONTINUE;
266 }
267 
texthideCommand()268 int ONScripter::texthideCommand()
269 {
270     dirty_rect.fill( screen_width, screen_height );
271     refresh_shadow_text_mode = REFRESH_NORMAL_MODE | REFRESH_SHADOW_MODE;
272     flush(refreshMode());
273 
274     return RET_CONTINUE;
275 }
276 
textcolorCommand()277 int ONScripter::textcolorCommand()
278 {
279     readColor( &sentence_font.color, script_h.readStr() );
280 
281     return RET_CONTINUE;
282 }
283 
textclearCommand()284 int ONScripter::textclearCommand()
285 {
286     newPage();
287     return RET_CONTINUE;
288 }
289 
texecCommand()290 int ONScripter::texecCommand()
291 {
292     if ( textgosub_clickstr_state == CLICK_NEWPAGE )
293         newPage();
294     else if ( textgosub_clickstr_state == (CLICK_WAIT|CLICK_EOL) ){
295         processEOT();
296         page_enter_status = 0;
297     }
298 
299     saveon_flag = true;
300 
301     return RET_CONTINUE;
302 }
303 
tateyokoCommand()304 int ONScripter::tateyokoCommand()
305 {
306     sentence_font.setTateyokoMode( script_h.readInt() );
307 
308     return RET_CONTINUE;
309 }
310 
talCommand()311 int ONScripter::talCommand()
312 {
313     leaveTextDisplayMode();
314 
315     char loc = script_h.readLabel()[0];
316     int no = -1, trans = 0;
317     if      ( loc == 'l' ) no = 0;
318     else if ( loc == 'c' ) no = 1;
319     else if ( loc == 'r' ) no = 2;
320 
321     if (no >= 0)
322         trans = script_h.readInt();
323 
324     if (no >= 0){
325         tachi_info[ no ].trans = trans;
326         dirty_rect.add( tachi_info[ no ].pos );
327     }
328 
329     EffectLink *el = parseEffect(true);
330     if (setEffect(el)) return RET_CONTINUE;
331     while (doEffect(el));
332 
333     return RET_CONTINUE;
334 }
335 
tablegotoCommand()336 int ONScripter::tablegotoCommand()
337 {
338     int count = 0;
339     int no = script_h.readInt();
340 
341     while( script_h.getEndStatus() & ScriptHandler::END_COMMA ){
342         const char *buf = script_h.readStr();
343         if ( count++ == no ){
344             setCurrentLabel( buf+1 );
345             break;
346         }
347     }
348 
349     return RET_CONTINUE;
350 }
351 
systemcallCommand()352 int ONScripter::systemcallCommand()
353 {
354     system_menu_mode = getSystemCallNo( script_h.readLabel() );
355 
356     executeSystemCall();
357 
358     return RET_CONTINUE;
359 }
360 
strspCommand()361 int ONScripter::strspCommand()
362 {
363     leaveTextDisplayMode();
364 
365     bool v = true;
366     if ( script_h.isName( "strsph" ) ) v = false;
367 
368     int sprite_no = script_h.readInt();
369     AnimationInfo *ai = &sprite_info[sprite_no];
370     ai->font_size_xy[0] = -1;
371 
372     if (ai->image_surface && ai->visible)
373         dirty_rect.add( ai->pos );
374 
375     ai->removeTag();
376     setStr(&ai->file_name, script_h.readStr());
377     ai->orig_pos.x = script_h.readInt();
378     ai->orig_pos.y = script_h.readInt();
379     ai->scalePosXY( screen_ratio1, screen_ratio2 );
380 
381     FontInfo fi;
382     fi.enc = &script_h.enc;
383     fi.is_newline_accepted = true;
384     fi.num_xy[0] = script_h.readInt();
385     fi.num_xy[1] = script_h.readInt();
386     fi.font_size_xy[0] = script_h.readInt();
387     fi.font_size_xy[1] = script_h.readInt();
388     fi.pitch_xy[0] = script_h.readInt() + fi.font_size_xy[0];
389     fi.pitch_xy[1] = script_h.readInt() + fi.font_size_xy[1];
390     fi.is_bold = script_h.readInt()?true:false;
391     fi.is_shadow = script_h.readInt()?true:false;
392 
393     char *buffer = script_h.getNext();
394     while(script_h.getEndStatus() & ScriptHandler::END_COMMA){
395         ai->num_of_cells++;
396         script_h.readStr();
397     }
398     if (ai->num_of_cells == 0){
399         ai->num_of_cells = 1;
400         ai->color_list = new uchar3[ai->num_of_cells];
401         ai->color_list[0][0] = ai->color_list[0][1] = ai->color_list[0][2] = 0xff;
402     }
403     else{
404         ai->color_list = new uchar3[ai->num_of_cells];
405         script_h.setCurrent(buffer);
406         for (int i=0 ; i<ai->num_of_cells ; i++)
407             readColor(&ai->color_list[i], script_h.readStr());
408     }
409 
410     ai->trans_mode = AnimationInfo::TRANS_STRING;
411     ai->trans = -1;
412     ai->visible = v;
413     ai->is_single_line = false;
414     ai->is_tight_region = false;
415     ai->is_ruby_drawable = sentence_font.rubyon_flag;
416     setupAnimationInfo(ai, &fi);
417     if ( ai->visible ) dirty_rect.add( ai->pos );
418 
419     return RET_CONTINUE;
420 }
421 
stopCommand()422 int ONScripter::stopCommand()
423 {
424     mp3stopCommand();
425     wavestopCommand();
426 
427     return RET_CONTINUE;
428 }
429 
sp_rgb_gradationCommand()430 int ONScripter::sp_rgb_gradationCommand()
431 {
432     int no = script_h.readInt();
433     int upper_r = script_h.readInt();
434     int upper_g = script_h.readInt();
435     int upper_b = script_h.readInt();
436     int lower_r = script_h.readInt();
437     int lower_g = script_h.readInt();
438     int lower_b = script_h.readInt();
439     ONSBuf key_r = script_h.readInt();
440     ONSBuf key_g = script_h.readInt();
441     ONSBuf key_b = script_h.readInt();
442     Uint32 alpha = script_h.readInt();
443 
444     AnimationInfo *ai;
445     if (no == -1) ai = &sentence_font_info;
446     else          ai = &sprite_info[no];
447     SDL_Surface *surface = ai->image_surface;
448     if (surface == NULL) return RET_CONTINUE;
449 
450     SDL_PixelFormat *fmt = surface->format;
451 
452     ONSBuf key_mask = (((key_r >> fmt->Rloss) << fmt->Rshift) |
453                        ((key_g >> fmt->Gloss) << fmt->Gshift) |
454                        ((key_b >> fmt->Bloss) << fmt->Bshift));
455     ONSBuf rgb_mask = fmt->Rmask | fmt->Gmask | fmt->Bmask;
456 
457     SDL_LockSurface(surface);
458     // check upper and lower bound
459     int i, j;
460     int upper_bound=0, lower_bound=0;
461     bool is_key_found = false;
462     for (i=0 ; i<surface->h ; i++){
463         ONSBuf *buf = (ONSBuf *)surface->pixels + surface->w * i;
464         for (j=0 ; j<surface->w ; j++, buf++){
465             if ((*buf & rgb_mask) == key_mask){
466                 if (is_key_found == false){
467                     is_key_found = true;
468                     upper_bound = lower_bound = i;
469                 }
470                 else{
471                     lower_bound = i;
472                 }
473                 break;
474             }
475         }
476     }
477 
478     // replace pixels of the key-color with the specified color in gradation
479     for (i=upper_bound ; i<=lower_bound ; i++){
480         ONSBuf *buf = (ONSBuf *)surface->pixels + surface->w * i;
481 #if defined(BPP16)
482         unsigned char *alphap = ai->alpha_buf + surface->w * i;
483 #else
484 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
485         unsigned char *alphap = (unsigned char *)buf + 3;
486 #else
487         unsigned char *alphap = (unsigned char *)buf;
488 #endif
489 #endif
490         Uint32 color = alpha << surface->format->Ashift;
491         if (upper_bound != lower_bound){
492             color |= (((lower_r - upper_r) * (i-upper_bound) / (lower_bound - upper_bound) + upper_r) >> fmt->Rloss) << fmt->Rshift;
493             color |= (((lower_g - upper_g) * (i-upper_bound) / (lower_bound - upper_bound) + upper_g) >> fmt->Gloss) << fmt->Gshift;
494             color |= (((lower_b - upper_b) * (i-upper_bound) / (lower_bound - upper_bound) + upper_b) >> fmt->Bloss) << fmt->Bshift;
495         }
496         else{
497             color |= (upper_r >> fmt->Rloss) << fmt->Rshift;
498             color |= (upper_g >> fmt->Gloss) << fmt->Gshift;
499             color |= (upper_b >> fmt->Bloss) << fmt->Bshift;
500         }
501 
502         for (j=0 ; j<surface->w ; j++, buf++){
503             if ((*buf & rgb_mask) == key_mask){
504                 *buf = color;
505                 *alphap = alpha;
506             }
507 #if defined(BPP16)
508             alphap++;
509 #else
510             alphap += 4;
511 #endif
512         }
513     }
514 
515     SDL_UnlockSurface(surface);
516 
517     if ( ai->visible )
518         dirty_rect.add( ai->pos );
519 
520     return RET_CONTINUE;
521 }
522 
spstrCommand()523 int ONScripter::spstrCommand()
524 {
525     decodeExbtnControl( script_h.readStr() );
526 
527     return RET_CONTINUE;
528 }
529 
spreloadCommand()530 int ONScripter::spreloadCommand()
531 {
532     int no = script_h.readInt();
533     AnimationInfo *ai;
534     if (no == -1) ai = &sentence_font_info;
535     else          ai = &sprite_info[no];
536 
537     parseTaggedString( ai );
538     setupAnimationInfo( ai );
539 
540     if ( ai->visible )
541         dirty_rect.add( ai->pos );
542 
543     return RET_CONTINUE;
544 }
545 
splitCommand()546 int ONScripter::splitCommand()
547 {
548     script_h.readStr();
549     const char *save_buf = script_h.saveStringBuffer();
550 
551     char delimiter = script_h.readStr()[0];
552 
553     char token256[256], *token=NULL;
554     while( script_h.getEndStatus() & ScriptHandler::END_COMMA ){
555 
556         unsigned int c=0;
557         while(save_buf[c] != delimiter && save_buf[c] != '\0')
558             c += script_h.enc.getBytes(save_buf[c]);
559 
560         if (c < 256)
561             token = token256;
562         else
563             token = new char[c+1];
564 
565         memcpy( token, save_buf, c );
566         token[c] = '\0';
567 
568         script_h.readVariable();
569         if ( script_h.current_variable.type & ScriptHandler::VAR_INT ||
570              script_h.current_variable.type & ScriptHandler::VAR_ARRAY ){
571             script_h.setInt( &script_h.current_variable, atoi(token) );
572         }
573         else if ( script_h.current_variable.type & ScriptHandler::VAR_STR ){
574             setStr( &script_h.getVariableData(script_h.current_variable.var_no).str, token );
575         }
576 
577         if (c >= 256) delete[] token;
578 
579         save_buf += c;
580         if (save_buf[0] != '\0') save_buf++;
581     }
582 
583     return RET_CONTINUE;
584 }
585 
spclclkCommand()586 int ONScripter::spclclkCommand()
587 {
588     if ( !force_button_shortcut_flag )
589         spclclk_flag = true;
590     return RET_CONTINUE;
591 }
592 
spbtnCommand()593 int ONScripter::spbtnCommand()
594 {
595     bool cellcheck_flag = false;
596 
597     if ( script_h.isName( "cellcheckspbtn" ) )
598         cellcheck_flag = true;
599 
600     int sprite_no = script_h.readInt();
601     int no        = script_h.readInt();
602     if (no < 1 ||
603         sprite_no < 0 ||
604         sprite_no >= MAX_SPRITE_NUM ||
605         sprite_info[sprite_no].image_surface == NULL)
606         return RET_CONTINUE;
607 
608     if ( cellcheck_flag ){
609         if ( sprite_info[ sprite_no ].num_of_cells < 2 ) return RET_CONTINUE;
610     }
611     else{
612         if ( sprite_info[ sprite_no ].num_of_cells == 0 ) return RET_CONTINUE;
613     }
614 
615     ButtonLink *button = new ButtonLink();
616     root_button_link.insert( button );
617 
618     button->button_type = ButtonLink::SPRITE_BUTTON;
619     button->sprite_no   = sprite_no;
620     button->no          = no;
621 
622     if ( sprite_info[ sprite_no ].image_surface ||
623          sprite_info[ sprite_no ].trans_mode == AnimationInfo::TRANS_STRING )
624         button->image_rect = button->select_rect = sprite_info[ sprite_no ].pos;
625 
626     return RET_CONTINUE;
627 }
628 
skipoffCommand()629 int ONScripter::skipoffCommand()
630 {
631     skip_mode &= ~SKIP_NORMAL;
632 
633     return RET_CONTINUE;
634 }
635 
showlangjpCommand()636 int ONScripter::showlangjpCommand()
637 {
638     script_h.current_language = 1;
639 
640     text_info.fill( 0, 0, 0, 0 );
641     flush(refreshMode(), &sentence_font_info.pos);
642 
643     return RET_CONTINUE;
644 }
645 
showlangenCommand()646 int ONScripter::showlangenCommand()
647 {
648     script_h.current_language = 0;
649 
650     text_info.fill( 0, 0, 0, 0 );
651     flush(refreshMode(), &sentence_font_info.pos);
652 
653     return RET_CONTINUE;
654 }
655 
sevolCommand()656 int ONScripter::sevolCommand()
657 {
658     se_volume = script_h.readInt();
659 
660     for ( int i=1 ; i<ONS_MIX_CHANNELS ; i++ )
661         if ( wave_sample[i] ) Mix_Volume( i, se_volume * MIX_MAX_VOLUME / 100 );
662 
663     if ( wave_sample[MIX_LOOPBGM_CHANNEL0] ) Mix_Volume( MIX_LOOPBGM_CHANNEL0, se_volume * MIX_MAX_VOLUME / 100 );
664     if ( wave_sample[MIX_LOOPBGM_CHANNEL1] ) Mix_Volume( MIX_LOOPBGM_CHANNEL1, se_volume * MIX_MAX_VOLUME / 100 );
665 
666     return RET_CONTINUE;
667 }
668 
setwindowCore()669 void ONScripter::setwindowCore()
670 {
671     sentence_font.ttf_font[0] = NULL;
672     sentence_font.ttf_font[1] = NULL;
673     sentence_font.top_xy[0] = script_h.readInt();
674     sentence_font.top_xy[1] = script_h.readInt();
675     sentence_font.num_xy[0] = script_h.readInt();
676     sentence_font.num_xy[1] = script_h.readInt();
677     sentence_font.font_size_xy[0] = script_h.readInt();
678     sentence_font.font_size_xy[1] = script_h.readInt();
679     sentence_font.pitch_xy[0] = script_h.readInt() + sentence_font.font_size_xy[0];
680     sentence_font.pitch_xy[1] = script_h.readInt() + sentence_font.font_size_xy[1];
681     sentence_font.wait_time = script_h.readInt();
682     sentence_font.is_bold = script_h.readInt()?true:false;
683     sentence_font.is_shadow = script_h.readInt()?true:false;
684 
685     const char *buf = script_h.readStr();
686     dirty_rect.add( sentence_font_info.pos );
687 
688     AnimationInfo *ai = &sentence_font_info;
689     if ( buf[0] == '#' ){
690         sentence_font.is_transparent = true;
691         readColor( &sentence_font.window_color, buf );
692 
693         ai->remove();
694         ai->orig_pos.x = script_h.readInt();
695         ai->orig_pos.y = script_h.readInt();
696         ai->orig_pos.w = script_h.readInt() - ai->orig_pos.x + 1;
697         ai->orig_pos.h = script_h.readInt() - ai->orig_pos.y + 1;
698         ai->scalePosXY( screen_ratio1, screen_ratio2 );
699         ai->scalePosWH( screen_ratio1, screen_ratio2 );
700     }
701     else{
702         if (buf[0] != 0){
703             ai->setImageName(buf);
704             parseTaggedString(ai);
705             setupAnimationInfo(ai);
706         }
707         ai->orig_pos.x = script_h.readInt();
708         ai->orig_pos.y = script_h.readInt();
709         if (script_h.getEndStatus() & ScriptHandler::END_COMMA)
710             script_h.readInt();
711         if (script_h.getEndStatus() & ScriptHandler::END_COMMA)
712             script_h.readInt();
713         ai->scalePosXY( screen_ratio1, screen_ratio2 );
714 
715         sentence_font.is_transparent = false;
716         sentence_font.window_color[0] = sentence_font.window_color[1] = sentence_font.window_color[2] = 0xff;
717     }
718 
719     sentence_font.old_xy[0] = sentence_font.x(false);
720     sentence_font.old_xy[1] = sentence_font.y(false);
721 }
722 
setwindow3Command()723 int ONScripter::setwindow3Command()
724 {
725     setwindowCore();
726 
727     clearCurrentPage();
728     indent_offset = 0;
729     line_enter_status = 0;
730     page_enter_status = 0;
731     display_mode = DISPLAY_MODE_NORMAL;
732     flush( refreshMode(), &sentence_font_info.pos );
733 
734     return RET_CONTINUE;
735 }
736 
setwindow2Command()737 int ONScripter::setwindow2Command()
738 {
739     const char *buf = script_h.readStr();
740     if ( buf[0] == '#' ){
741         sentence_font.is_transparent = true;
742         readColor( &sentence_font.window_color, buf );
743         sentence_font_info.remove();
744     }
745     else{
746         sentence_font.is_transparent = false;
747         sentence_font_info.setImageName( buf );
748         parseTaggedString( &sentence_font_info );
749         setupAnimationInfo( &sentence_font_info );
750     }
751     repaintCommand();
752 
753     return RET_CONTINUE;
754 }
755 
setwindowCommand()756 int ONScripter::setwindowCommand()
757 {
758     setwindowCore();
759 
760     lookbackflushCommand();
761     indent_offset = 0;
762     line_enter_status = 0;
763     page_enter_status = 0;
764     display_mode = DISPLAY_MODE_NORMAL;
765     flush( refreshMode(), &sentence_font_info.pos );
766 
767     return RET_CONTINUE;
768 }
769 
setcursorCommand()770 int ONScripter::setcursorCommand()
771 {
772     bool abs_flag;
773 
774     if ( script_h.isName( "abssetcursor" ) ){
775         abs_flag = true;
776     }
777     else{
778         abs_flag = false;
779     }
780 
781     int no = script_h.readInt();
782     script_h.readStr();
783     const char* buf = script_h.saveStringBuffer();
784     int x = script_h.readInt();
785     int y = script_h.readInt();
786 
787     loadCursor( no, buf, x, y, abs_flag );
788 
789     return RET_CONTINUE;
790 }
791 
selectCommand()792 int ONScripter::selectCommand()
793 {
794     enterTextDisplayMode();
795 
796     int select_mode = SELECT_GOTO_MODE;
797     SelectLink *last_select_link;
798 
799     if ( script_h.isName( "selnum" ) )
800         select_mode = SELECT_NUM_MODE;
801     else if ( script_h.isName( "selgosub" ) )
802         select_mode = SELECT_GOSUB_MODE;
803     else if ( script_h.isName( "select" ) )
804         select_mode = SELECT_GOTO_MODE;
805     else if ( script_h.isName( "csel" ) )
806         select_mode = SELECT_CSEL_MODE;
807 
808     if ( select_mode == SELECT_NUM_MODE ){
809         script_h.readVariable();
810         script_h.pushVariable();
811     }
812 
813     bool comma_flag = true;
814     if ( select_mode == SELECT_CSEL_MODE ){
815         if (saveon_flag && internal_saveon_flag) storeSaveFile();
816         saveon_flag = false;
817     }
818     shortcut_mouse_line = -1;
819 
820     int xy[2];
821     xy[0] = sentence_font.xy[0];
822     xy[1] = sentence_font.xy[1];
823 
824     if ( selectvoice_file_name[SELECTVOICE_OPEN] )
825         playSound(selectvoice_file_name[SELECTVOICE_OPEN],
826                   SOUND_CHUNK, false, MIX_WAVE_CHANNEL );
827 
828     last_select_link = &root_select_link;
829 
830     while(1){
831         if ( script_h.getNext()[0] != 0x0a && comma_flag == true ){
832 
833             const char *buf = script_h.readStr();
834             comma_flag = (script_h.getEndStatus() & ScriptHandler::END_COMMA);
835             if ( select_mode != SELECT_NUM_MODE && !comma_flag )
836                 errorAndExit( "select: missing comma." );
837 
838             // Text part
839             SelectLink *slink = new SelectLink();
840             setStr( &slink->text, buf );
841             //printf("Select text %s\n", slink->text);
842 
843             // Label part
844             if (select_mode != SELECT_NUM_MODE){
845                 script_h.readStr();
846                 setStr( &slink->label, script_h.getStringBuffer()+1 );
847                 //printf("Select label %s\n", slink->label );
848             }
849             last_select_link->next = slink;
850             last_select_link = last_select_link->next;
851 
852             comma_flag = (script_h.getEndStatus() & ScriptHandler::END_COMMA);
853             //printf("2 comma %d %c %x\n", comma_flag, script_h.getCurrent()[0], script_h.getCurrent()[0]);
854         }
855         else if (script_h.getNext()[0] == 0x0a){
856             //printf("comma %d\n", comma_flag);
857             char *buf = script_h.getNext() + 1; // consume eol
858             while ( *buf == ' ' || *buf == '\t' ) buf++;
859 
860             if (comma_flag && *buf == ',')
861                 errorAndExit( "select: double comma." );
862 
863             bool comma2_flag = false;
864             if (*buf == ','){
865                 comma2_flag = true;
866                 buf++;
867                 while ( *buf == ' ' || *buf == '\t' ) buf++;
868             }
869             script_h.setCurrent(buf);
870 
871             if (*buf == 0x0a){
872                 comma_flag |= comma2_flag;
873                 continue;
874             }
875 
876             if (!comma_flag && !comma2_flag){
877                 select_label_info.next_script = buf;
878                 //printf("select: stop at the end of line\n");
879                 break;
880             }
881 
882             //printf("continue\n");
883             comma_flag = true;
884         }
885         else{ // if select ends at the middle of the line
886             select_label_info.next_script = script_h.getNext();
887             //printf("select: stop at the middle of the line\n");
888             break;
889         }
890     }
891 
892     if ( select_mode != SELECT_CSEL_MODE ){
893         last_select_link = root_select_link.next;
894         int counter = 1;
895         while( last_select_link ){
896             if ( *last_select_link->text ){
897                 ButtonLink *button = getSelectableSentence( last_select_link->text, &sentence_font );
898                 root_button_link.insert( button );
899                 button->no = counter;
900             }
901             counter++;
902             last_select_link = last_select_link->next;
903         }
904     }
905 
906     if ( select_mode == SELECT_CSEL_MODE ){
907         setCurrentLabel( "customsel" );
908         return RET_CONTINUE;
909     }
910     automode_flag = false;
911     sentence_font.xy[0] = xy[0];
912     sentence_font.xy[1] = xy[1];
913 
914     flush( refreshMode() );
915 
916     refreshMouseOverButton();
917 
918     event_mode = WAIT_TEXT_MODE | WAIT_BUTTON_MODE | WAIT_TIMER_MODE;
919     do{
920         skip_mode &= ~SKIP_NORMAL;
921         if (waitEvent(-1)) return RET_CONTINUE;
922     }
923     while(current_button_state.button <= 0 || skip_mode & SKIP_NORMAL);
924 
925     if ( selectvoice_file_name[SELECTVOICE_SELECT] )
926         playSound(selectvoice_file_name[SELECTVOICE_SELECT],
927                   SOUND_CHUNK, false, MIX_WAVE_CHANNEL );
928 
929     deleteButtonLink();
930 
931     int counter = 1;
932     last_select_link = root_select_link.next;
933     while ( last_select_link ){
934         if ( current_button_state.button == counter++ ) break;
935         last_select_link = last_select_link->next;
936     }
937 
938     if ( select_mode  == SELECT_GOTO_MODE ){
939         setCurrentLabel( last_select_link->label );
940     }
941     else if ( select_mode == SELECT_GOSUB_MODE ){
942         gosubReal( last_select_link->label, select_label_info.next_script );
943     }
944     else{ // selnum
945         script_h.setInt( &script_h.pushed_variable, current_button_state.button - 1 );
946         current_label_info = script_h.getLabelByAddress( select_label_info.next_script );
947         current_line = script_h.getLineByAddress( select_label_info.next_script );
948         script_h.setCurrent( select_label_info.next_script );
949     }
950     deleteSelectLink();
951 
952     newPage();
953 
954     return RET_CONTINUE;
955 }
956 
savetimeCommand()957 int ONScripter::savetimeCommand()
958 {
959     int no = script_h.readInt();
960 
961     SaveFileInfo info;
962     searchSaveFile( info, no );
963 
964     script_h.readVariable();
965     if ( !info.valid ){
966         script_h.setInt( &script_h.current_variable, 0 );
967         for ( int i=0 ; i<3 ; i++ )
968             script_h.readVariable();
969         return RET_CONTINUE;
970     }
971 
972     script_h.setInt( &script_h.current_variable, info.month );
973     script_h.readInt();
974     script_h.setInt( &script_h.current_variable, info.day );
975     script_h.readInt();
976     script_h.setInt( &script_h.current_variable, info.hour );
977     script_h.readInt();
978     script_h.setInt( &script_h.current_variable, info.minute );
979 
980     return RET_CONTINUE;
981 }
982 
savescreenshotCommand()983 int ONScripter::savescreenshotCommand()
984 {
985     if      ( script_h.isName( "savescreenshot" ) ){
986     }
987     else if ( script_h.isName( "savescreenshot2" ) ){
988     }
989 
990     SDL_Surface *surface = AnimationInfo::alloc32bitSurface( screenshot_w, screenshot_h, texture_format );
991     resizeSurface( screenshot_surface, surface );
992 
993     const char *buf = script_h.readStr();
994     if (script_h.enc.getEncoding() == Encoding::CODE_UTF8){
995         char *dir = new char[strlen(archive_path) + strlen(buf) + 1];
996         sprintf(dir, "%s%s", archive_path, buf);
997         for (int i=strlen(dir)-1; i>=0; i--){
998             if (dir[i] == '/' || dir[i] == '\\'){
999                 dir[i] = 0;
1000 #if defined(LINUX) || defined(MACOSX) || defined(IOS)
1001                 mkdir(dir, 0755);
1002 #elif defined(WIN32)
1003                 _mkdir(dir);
1004 #endif
1005                 break;
1006             }
1007         }
1008         delete[] dir;
1009     }
1010 
1011     FILE *fp = fopen(buf, "wb");
1012     if (fp){
1013         SDL_RWops *rwops = SDL_RWFromFP(fp, SDL_TRUE);
1014         SDL_SaveBMP_RW(surface, rwops, 1);
1015     }
1016     SDL_FreeSurface(surface);
1017 
1018     return RET_CONTINUE;
1019 }
1020 
savepointCommand()1021 int ONScripter::savepointCommand()
1022 {
1023     storeSaveFile();
1024 
1025     return RET_CONTINUE;
1026 }
1027 
saveonCommand()1028 int ONScripter::saveonCommand()
1029 {
1030     if (!autosaveoff_flag)
1031         saveon_flag = true;
1032 
1033     return RET_CONTINUE;
1034 }
1035 
saveoffCommand()1036 int ONScripter::saveoffCommand()
1037 {
1038     if (!autosaveoff_flag){
1039         if (saveon_flag && internal_saveon_flag) storeSaveFile();
1040 
1041         saveon_flag = false;
1042     }
1043 
1044     return RET_CONTINUE;
1045 }
1046 
savegameCommand()1047 int ONScripter::savegameCommand()
1048 {
1049     bool savegame2_flag = false;
1050     if ( script_h.isName( "savegame2" ) )
1051         savegame2_flag = true;
1052 
1053     int no = script_h.readInt();
1054 
1055     const char* savestr = NULL;
1056     if (savegame2_flag)
1057         savestr = script_h.readStr();
1058 
1059     if (saveon_flag && internal_saveon_flag) storeSaveFile();
1060     writeSaveFile( no, savestr );
1061 
1062     return RET_CONTINUE;
1063 }
1064 
savefileexistCommand()1065 int ONScripter::savefileexistCommand()
1066 {
1067     script_h.readInt();
1068     script_h.pushVariable();
1069     int no = script_h.readInt();
1070 
1071     SaveFileInfo info;
1072     searchSaveFile( info, no );
1073 
1074     script_h.setInt( &script_h.pushed_variable, (info.valid==true)?1:0 );
1075 
1076     return RET_CONTINUE;
1077 }
1078 
rndCommand()1079 int ONScripter::rndCommand()
1080 {
1081     int upper, lower;
1082 
1083     if ( script_h.isName( "rnd2" ) ){
1084         script_h.readInt();
1085         script_h.pushVariable();
1086 
1087         lower = script_h.readInt();
1088         upper = script_h.readInt();
1089     }
1090     else{
1091         script_h.readInt();
1092         script_h.pushVariable();
1093 
1094         lower = 0;
1095         upper = script_h.readInt() - 1;
1096     }
1097 
1098     script_h.setInt( &script_h.pushed_variable, lower + (int)( (double)(upper-lower+1)*rand()/(RAND_MAX+1.0)) );
1099 
1100     return RET_CONTINUE;
1101 }
1102 
rmodeCommand()1103 int ONScripter::rmodeCommand()
1104 {
1105     if ( script_h.readInt() == 1 ) rmode_flag = true;
1106     else                           rmode_flag = false;
1107 
1108     return RET_CONTINUE;
1109 }
1110 
resettimerCommand()1111 int ONScripter::resettimerCommand()
1112 {
1113     internal_timer = SDL_GetTicks();
1114 
1115     return RET_CONTINUE;
1116 }
1117 
resetCommand()1118 int ONScripter::resetCommand()
1119 {
1120     int fadeout = mp3fadeout_duration;
1121     mp3fadeout_duration = 0; //don't use fadeout during a reset
1122     resetSub();
1123     mp3fadeout_duration = fadeout;
1124 
1125     start_page = current_page = &page_list[0];
1126     clearCurrentPage();
1127     flush( refreshMode(), &sentence_font_info.pos );
1128 
1129     /* Initialize local variables */
1130     for (int i=0 ; i<script_h.global_variable_border ; i++)
1131         script_h.getVariableData(i).reset(false);
1132 
1133     setCurrentLabel( "start" );
1134     storeSaveFile();
1135 
1136     return RET_CONTINUE;
1137 }
1138 
repaintCommand()1139 int ONScripter::repaintCommand()
1140 {
1141     dirty_rect.fill( screen_width, screen_height );
1142     flush( refreshMode() );
1143 
1144     return RET_CONTINUE;
1145 }
1146 
quakeCommand()1147 int ONScripter::quakeCommand()
1148 {
1149     int quake_type;
1150 
1151     if      ( script_h.isName( "quakey" ) ){
1152         quake_type = 0;
1153     }
1154     else if ( script_h.isName( "quakex" ) ){
1155         quake_type = 1;
1156     }
1157     else{
1158         quake_type = 2;
1159     }
1160 
1161     tmp_effect.no       = script_h.readInt();
1162     tmp_effect.duration = script_h.readInt();
1163     if ( tmp_effect.duration < tmp_effect.no * 4 ) tmp_effect.duration = tmp_effect.no * 4;
1164     tmp_effect.effect   = MAX_EFFECT_NUM + quake_type;
1165 
1166     dirty_rect.fill( screen_width, screen_height );
1167     SDL_BlitSurface( accumulation_surface, NULL, effect_dst_surface, NULL );
1168 
1169     if (setEffect(&tmp_effect)) return RET_CONTINUE;
1170     while (doEffect(&tmp_effect));
1171 
1172     return RET_CONTINUE;
1173 }
1174 
puttextCommand()1175 int ONScripter::puttextCommand()
1176 {
1177     enterTextDisplayMode(false);
1178 
1179     script_h.readStr();
1180 
1181     string_buffer_offset = 0;
1182     if (script_h.getEndStatus() & ScriptHandler::END_1BYTE_CHAR)
1183         string_buffer_offset = 1; // skip the heading `
1184 
1185     int s = line_enter_status;
1186     while(processText());
1187     line_enter_status = s;
1188 
1189     return RET_CONTINUE;
1190 }
1191 
prnumclearCommand()1192 int ONScripter::prnumclearCommand()
1193 {
1194     for ( int i=0 ; i<MAX_PARAM_NUM ; i++ ) {
1195         if ( prnum_info[i] ) {
1196             dirty_rect.add( prnum_info[i]->pos );
1197             delete prnum_info[i];
1198             prnum_info[i] = NULL;
1199         }
1200     }
1201     return RET_CONTINUE;
1202 }
1203 
prnumCommand()1204 int ONScripter::prnumCommand()
1205 {
1206     leaveTextDisplayMode();
1207 
1208     int no = script_h.readInt();
1209     if (no < 0 || no >= MAX_PARAM_NUM){
1210         script_h.readInt();
1211         script_h.readInt();
1212         script_h.readInt();
1213         script_h.readInt();
1214         script_h.readInt();
1215         script_h.readStr();
1216         return RET_CONTINUE;
1217     }
1218 
1219     if ( prnum_info[no] ){
1220         dirty_rect.add( prnum_info[no]->pos );
1221         delete prnum_info[no];
1222     }
1223     AnimationInfo *ai = prnum_info[no] = new AnimationInfo();
1224     ai->trans_mode = AnimationInfo::TRANS_STRING;
1225     ai->num_of_cells = 1;
1226     ai->setCell(0);
1227     ai->color_list = new uchar3[ ai->num_of_cells ];
1228 
1229     ai->param = script_h.readInt();
1230     ai->orig_pos.x = script_h.readInt();
1231     ai->orig_pos.y = script_h.readInt();
1232     ai->scalePosXY( screen_ratio1, screen_ratio2 );
1233     ai->font_size_xy[0] = script_h.readInt();
1234     ai->font_size_xy[1] = script_h.readInt();
1235     ai->font_pitch[0] = ai->font_size_xy[0];
1236     ai->font_pitch[1] = ai->font_size_xy[1];
1237 
1238     const char *buf = script_h.readStr();
1239     readColor( &ai->color_list[0], buf );
1240 
1241     char num_buf[7];
1242     script_h.getStringFromInteger( num_buf, ai->param, 3 );
1243     setStr( &ai->file_name, num_buf );
1244 
1245     setupAnimationInfo( ai );
1246     dirty_rect.add( ai->pos );
1247 
1248     return RET_CONTINUE;
1249 }
1250 
printCommand()1251 int ONScripter::printCommand()
1252 {
1253     leaveTextDisplayMode();
1254 
1255     EffectLink *el = parseEffect(true);
1256     if (setEffect(el)) return RET_CONTINUE;
1257     while (doEffect(el));
1258 
1259     return RET_CONTINUE;
1260 }
1261 
playstopCommand()1262 int ONScripter::playstopCommand()
1263 {
1264     stopBGM( false );
1265 
1266     return RET_CONTINUE;
1267 }
1268 
playCommand()1269 int ONScripter::playCommand()
1270 {
1271     bool loop_flag = true;
1272     if ( script_h.isName( "playonce" ) )
1273         loop_flag = false;
1274 
1275     const char *buf = script_h.readStr();
1276     if ( buf[0] == '*' ){
1277         cd_play_loop_flag = loop_flag;
1278         int new_cd_track = atoi( buf + 1 );
1279 #ifdef CONTINUOUS_PLAY
1280         if ( current_cd_track != new_cd_track ) {
1281 #endif
1282             stopBGM( false );
1283             current_cd_track = new_cd_track;
1284             playCDAudio();
1285 #ifdef CONTINUOUS_PLAY
1286         }
1287 #endif
1288     }
1289     else{ // play MIDI
1290         stopBGM( false );
1291 
1292         setStr(&midi_file_name, buf);
1293         midi_play_loop_flag = loop_flag;
1294         if (playSound(midi_file_name, SOUND_MIDI, midi_play_loop_flag) != SOUND_MIDI){
1295             fprintf(stderr, "can't play MIDI file %s\n", midi_file_name);
1296         }
1297     }
1298 
1299     return RET_CONTINUE;
1300 }
1301 
ofscopyCommand()1302 int ONScripter::ofscopyCommand()
1303 {
1304 #ifdef USE_SDL_RENDERER
1305     SDL_Surface *tmp_surface = AnimationInfo::alloc32bitSurface( screen_device_width, screen_device_height, texture_format );
1306     SDL_Rect rect = {(device_width -screen_device_width)/2,
1307                      (device_height-screen_device_height)/2,
1308                      screen_device_width, screen_device_height};
1309     SDL_LockSurface(tmp_surface);
1310     SDL_RenderReadPixels(renderer, &rect, tmp_surface->format->format, tmp_surface->pixels, tmp_surface->pitch);
1311     SDL_UnlockSurface(tmp_surface);
1312     resizeSurface( tmp_surface, accumulation_surface );
1313     SDL_FreeSurface(tmp_surface);
1314 #else
1315     SDL_BlitSurface(screen_surface, NULL, accumulation_surface, NULL);
1316 #endif
1317 
1318     return RET_CONTINUE;
1319 }
1320 
negaCommand()1321 int ONScripter::negaCommand()
1322 {
1323     nega_mode = script_h.readInt();
1324 
1325     dirty_rect.fill( screen_width, screen_height );
1326 
1327     return RET_CONTINUE;
1328 }
1329 
nextcselCommand()1330 int ONScripter::nextcselCommand()
1331 {
1332     script_h.readInt();
1333 
1334     if (last_nest_info != &root_nest_info &&
1335         last_nest_info->nest_mode == NestInfo::LABEL){
1336         char *buf = last_nest_info->next_script;
1337         while (*buf == ' ' || *buf == '\t' || *buf == 0x0a) buf++;
1338         if (strncmp( buf, "csel", 4) == 0)
1339             script_h.setInt( &script_h.current_variable, 1 );
1340         else
1341             script_h.setInt( &script_h.current_variable, 0 );
1342     }
1343     else
1344         script_h.setInt( &script_h.current_variable, 0 );
1345 
1346     return RET_CONTINUE;
1347 }
1348 
mspCommand()1349 int ONScripter::mspCommand()
1350 {
1351     leaveTextDisplayMode();
1352 
1353     bool msp2_flag = false;
1354     if (script_h.isName("msp2")) msp2_flag = true;
1355 
1356     int no = script_h.readInt();
1357     AnimationInfo *ai = NULL;
1358     if (msp2_flag) {
1359         ai = &sprite2_info[no];
1360         dirty_rect.add( ai->bounding_rect );
1361     }
1362     else{
1363         ai = &sprite_info[no];
1364         dirty_rect.add( ai->pos );
1365     }
1366 
1367     ai->orig_pos.x += script_h.readInt();
1368     ai->orig_pos.y += script_h.readInt();
1369     ai->scalePosXY( screen_ratio1, screen_ratio2 );
1370     if (msp2_flag){
1371         ai->scale_x += script_h.readInt();
1372         ai->scale_y += script_h.readInt();
1373         ai->rot     += script_h.readInt();
1374         ai->calcAffineMatrix();
1375         dirty_rect.add( ai->bounding_rect );
1376     }
1377     else{
1378         dirty_rect.add( ai->pos );
1379     }
1380 
1381     if ( script_h.getEndStatus() & ScriptHandler::END_COMMA ){
1382         if (ai->trans == -1)
1383             ai->trans = 255 + script_h.readInt();
1384         else
1385             ai->trans += script_h.readInt();
1386         if      (ai->trans <   0) ai->trans = 0;
1387         else if (ai->trans > 255) ai->trans = 255;
1388     }
1389 
1390     return RET_CONTINUE;
1391 }
1392 
mpegplayCommand()1393 int ONScripter::mpegplayCommand()
1394 {
1395     script_h.readStr();
1396     const char *save_buf = script_h.saveStringBuffer();
1397 
1398     bool click_flag = (script_h.readInt()==1)?true:false;
1399 
1400     stopBGM( false );
1401     if (playMPEG( save_buf, click_flag )) endCommand();
1402 
1403     repaintCommand();
1404 
1405     return RET_CONTINUE;
1406 }
1407 
mp3volCommand()1408 int ONScripter::mp3volCommand()
1409 {
1410     music_volume = script_h.readInt();
1411     Mix_VolumeMusic( music_volume * MIX_MAX_VOLUME / 100 );
1412 
1413     return RET_CONTINUE;
1414 }
1415 
mp3stopCommand()1416 int ONScripter::mp3stopCommand()
1417 {
1418     if (Mix_PlayingMusic() == 1 && timer_bgmfade_id && mp3fadeout_duration_internal > 0) // already in fadeout
1419         return RET_CONTINUE;
1420 
1421     if (Mix_PlayingMusic() == 1 && mp3fadeout_duration > 0){
1422         // do a bgm fadeout
1423         Mix_HookMusicFinished( NULL );
1424         mp3fadeout_duration_internal = mp3fadeout_duration;
1425         mp3fade_start = SDL_GetTicks();
1426         timer_bgmfade_id = SDL_AddTimer(20, bgmfadeCallback, 0);
1427         setStr(&fadeout_music_file_name, music_file_name);
1428 
1429         char *ext = NULL;
1430         if (music_file_name) ext = strrchr(music_file_name, '.');
1431         if (ext && (!strcmp(ext+1, "OGG") || !strcmp(ext+1, "ogg"))){
1432             // do not wait until fadout is finished when playing ogg
1433             event_mode = IDLE_EVENT_MODE;
1434             waitEvent(0);
1435             setStr( &music_file_name, NULL ); // to ensure not to play music during fadeout
1436 
1437             return RET_CONTINUE;
1438         }
1439         else{
1440             // wait until fadout is finished when playing music other than ogg
1441             event_mode = WAIT_TIMER_MODE;
1442             waitEvent(-1);
1443         }
1444     }
1445 
1446     stopBGM( false );
1447 
1448     return RET_CONTINUE;
1449 }
1450 
mp3fadeoutCommand()1451 int ONScripter::mp3fadeoutCommand()
1452 {
1453     mp3fadeout_duration = script_h.readInt();
1454 
1455     return RET_CONTINUE;
1456 }
1457 
mp3fadeinCommand()1458 int ONScripter::mp3fadeinCommand()
1459 {
1460     mp3fadein_duration = script_h.readInt();
1461 
1462     return RET_CONTINUE;
1463 }
1464 
mp3Command()1465 int ONScripter::mp3Command()
1466 {
1467     bool loop_flag = false;
1468     if      ( script_h.isName( "mp3save" ) ){
1469         mp3save_flag = true;
1470     }
1471     else if ( script_h.isName( "bgmonce" ) ){
1472         mp3save_flag = false;
1473     }
1474     else if ( script_h.isName( "mp3loop" ) ||
1475               script_h.isName( "bgm" ) ){
1476         mp3save_flag = true;
1477         loop_flag = true;
1478     }
1479     else{
1480         mp3save_flag = false;
1481     }
1482 
1483     mp3stopCommand();
1484     stopBGM( false );
1485 
1486     music_play_loop_flag = loop_flag;
1487     music_loopback_offset = 0.0;
1488 
1489     const char *buf = script_h.readStr();
1490     if (buf[0] != '\0'){
1491         if (buf[0]=='('){
1492             buf++;
1493             bool integer_flag = true;
1494             double decimal = 0.1;
1495             while (*buf != ')' && *buf != '\0'){
1496                 if (*buf >= '0' && *buf <= '9'){
1497                     if (integer_flag)
1498                         music_loopback_offset = music_loopback_offset*10.0 + *buf - '0';
1499                     else{
1500                         music_loopback_offset += decimal*(*buf - '0');
1501                         decimal *= 0.1;
1502                     }
1503                 }
1504                 else if (*buf == '.')
1505                     integer_flag = false;
1506                 buf++;
1507             }
1508             if (*buf == ')') buf++;
1509         }
1510 
1511         int tmp = music_volume;
1512         setStr(&music_file_name, buf);
1513 
1514         if (mp3fadein_duration > 0)
1515             music_volume = 0;
1516 
1517         playSound(music_file_name,
1518                   SOUND_MUSIC | SOUND_MIDI | SOUND_CHUNK,
1519                   music_play_loop_flag, MIX_BGM_CHANNEL);
1520 
1521         music_volume = tmp;
1522 
1523         if (mp3fadein_duration > 0) {
1524             // do a bgm fadein
1525             mp3fadein_duration_internal = mp3fadein_duration;
1526             mp3fade_start = SDL_GetTicks();
1527             timer_bgmfade_id = SDL_AddTimer(20, bgmfadeCallback,
1528                                             (void*)&timer_bgmfade_id);
1529 
1530             char *ext = NULL;
1531             if (music_file_name) ext = strrchr(music_file_name, '.');
1532             if (ext && (!strcmp(ext+1, "OGG") || !strcmp(ext+1, "ogg"))){
1533                 // do not wait until fadin is finished when playing ogg
1534                 event_mode = IDLE_EVENT_MODE;
1535                 waitEvent(0);
1536             }
1537             else{
1538                 // wait until fadin is finished when playing music other than ogg
1539                 event_mode = WAIT_TIMER_MODE;
1540                 waitEvent(-1);
1541             }
1542         }
1543     }
1544 
1545     return RET_CONTINUE;
1546 }
1547 
movieCommand()1548 int ONScripter::movieCommand()
1549 {
1550     if (script_h.compareString("stop")){
1551         script_h.readLabel();
1552         fprintf(stderr, " [movie stop] is not supported yet!!\n");
1553         return RET_CONTINUE;
1554     }
1555 
1556     script_h.readStr();
1557     const char *filename = script_h.saveStringBuffer();
1558 
1559     bool click_flag = false;
1560     bool loop_flag = false;
1561     bool nosound_flag = false;
1562 
1563     while (script_h.getEndStatus() & ScriptHandler::END_COMMA){
1564         if (script_h.compareString("pos")){ // not supported yet
1565             script_h.readLabel();
1566             script_h.readInt();
1567             script_h.readInt();
1568             script_h.readInt();
1569             script_h.readInt();
1570             fprintf(stderr, " [movie pos] is not supported yet!!\n");
1571         }
1572         else if (script_h.compareString("click")){
1573             script_h.readLabel();
1574             click_flag = true;
1575         }
1576         else if (script_h.compareString("loop")){
1577             script_h.readLabel();
1578             loop_flag = true;
1579         }
1580         else if (script_h.compareString("async")){ // not supported yet
1581             script_h.readLabel();
1582             fprintf(stderr, " [movie async] is not supported yet!!\n");
1583         }
1584         else if (script_h.compareString("nosound")){
1585             script_h.readLabel();
1586             nosound_flag = true;
1587         }
1588         else{
1589             script_h.readLabel();
1590         }
1591     }
1592 
1593     if (!nosound_flag) stopBGM(false);
1594 
1595     if (playMPEG(filename, click_flag, loop_flag, nosound_flag)) endCommand();
1596 
1597     return RET_CONTINUE;
1598 }
1599 
movemousecursorCommand()1600 int ONScripter::movemousecursorCommand()
1601 {
1602     int x = script_h.readInt() * screen_ratio1 / screen_ratio2;
1603     int y = script_h.readInt() * screen_ratio1 / screen_ratio2;
1604     x = x * screen_device_width / screen_width;
1605     y = y * screen_device_width / screen_width;
1606 
1607     SDL_WarpMouse(x, y);
1608 
1609     return RET_CONTINUE;
1610 }
1611 
monocroCommand()1612 int ONScripter::monocroCommand()
1613 {
1614     if ( script_h.compareString( "off" ) ){
1615         script_h.readLabel();
1616         monocro_flag = false;
1617     }
1618     else{
1619         monocro_flag = true;
1620         readColor( &monocro_color, script_h.readStr() );
1621 
1622         for (int i=0 ; i<256 ; i++){
1623             monocro_color_lut[i][0] = (monocro_color[0] * i) >> 8;
1624             monocro_color_lut[i][1] = (monocro_color[1] * i) >> 8;
1625             monocro_color_lut[i][2] = (monocro_color[2] * i) >> 8;
1626         }
1627     }
1628 
1629     dirty_rect.fill( screen_width, screen_height );
1630 
1631     return RET_CONTINUE;
1632 }
1633 
menu_windowCommand()1634 int ONScripter::menu_windowCommand()
1635 {
1636     if ( fullscreen_mode ){
1637 #if !defined(PSP)
1638         if ( !SDL_WM_ToggleFullScreen( screen_surface ) ){
1639             screen_surface = SDL_SetVideoMode( screen_device_width, screen_device_height, screen_bpp, DEFAULT_VIDEO_SURFACE_FLAG );
1640 #ifdef ANDROID
1641             SDL_SetSurfaceBlendMode(screen_surface, SDL_BLENDMODE_NONE);
1642 #endif
1643             flushDirect( screen_rect, refreshMode() );
1644         }
1645 #endif
1646         fullscreen_mode = false;
1647     }
1648 
1649     return RET_CONTINUE;
1650 }
1651 
menu_fullCommand()1652 int ONScripter::menu_fullCommand()
1653 {
1654     if ( !fullscreen_mode ){
1655 #if !defined(PSP)
1656         if ( !SDL_WM_ToggleFullScreen( screen_surface ) ){
1657             screen_surface = SDL_SetVideoMode( screen_device_width, screen_device_height, screen_bpp, DEFAULT_VIDEO_SURFACE_FLAG|SDL_FULLSCREEN );
1658 #ifdef ANDROID
1659             SDL_SetSurfaceBlendMode(screen_surface, SDL_BLENDMODE_NONE);
1660 #endif
1661             flushDirect( screen_rect, refreshMode() );
1662         }
1663 #endif
1664         fullscreen_mode = true;
1665     }
1666 
1667     return RET_CONTINUE;
1668 }
1669 
menu_click_pageCommand()1670 int ONScripter::menu_click_pageCommand()
1671 {
1672     skip_mode |= SKIP_TO_EOP;
1673     return RET_CONTINUE;
1674 }
1675 
menu_click_defCommand()1676 int ONScripter::menu_click_defCommand()
1677 {
1678     skip_mode &= ~SKIP_TO_EOP;
1679     return RET_CONTINUE;
1680 }
1681 
menu_automodeCommand()1682 int ONScripter::menu_automodeCommand()
1683 {
1684     automode_flag = true;
1685     skip_mode &= ~SKIP_NORMAL;
1686     printf("menu_automode: change to automode\n");
1687 
1688     return RET_CONTINUE;
1689 }
1690 
lsp2Command()1691 int ONScripter::lsp2Command()
1692 {
1693     leaveTextDisplayMode();
1694 
1695     bool v=true;
1696     if ( script_h.isName( "lsph2" ) ||
1697          script_h.isName( "lsph2add" ) ||
1698          script_h.isName( "lsph2sub" ))
1699         v = false;
1700 
1701     int blend_mode = AnimationInfo::BLEND_NORMAL;
1702     if ( script_h.isName( "lsp2add" ) || script_h.isName( "lsph2add" ))
1703         blend_mode = AnimationInfo::BLEND_ADD;
1704     else if ( script_h.isName( "lsp2sub" ) || script_h.isName( "lsph2sub" ))
1705         blend_mode = AnimationInfo::BLEND_SUB;
1706 
1707     int no = script_h.readInt();
1708     AnimationInfo *ai = &sprite2_info[no];
1709 
1710     if (ai->image_surface && ai->visible)
1711         dirty_rect.add( ai->bounding_rect );
1712     ai->visible = v;
1713     ai->blending_mode = blend_mode;
1714 
1715     const char *buf = script_h.readStr();
1716     ai->setImageName( buf );
1717 
1718     ai->orig_pos.x = script_h.readInt();
1719     ai->orig_pos.y = script_h.readInt();
1720     ai->scalePosXY( screen_ratio1, screen_ratio2 );
1721     ai->scale_x = script_h.readInt();
1722     ai->scale_y = script_h.readInt();
1723     ai->rot     = script_h.readInt();
1724 
1725     if ( script_h.getEndStatus() & ScriptHandler::END_COMMA )
1726         ai->trans = script_h.readInt();
1727     else
1728         ai->trans = -1;
1729 
1730     parseTaggedString( ai );
1731     setupAnimationInfo( ai );
1732     ai->calcAffineMatrix();
1733 
1734     if ( ai->visible )
1735         dirty_rect.add( ai->bounding_rect );
1736 
1737     return RET_CONTINUE;
1738 }
1739 
lspCommand()1740 int ONScripter::lspCommand()
1741 {
1742     leaveTextDisplayMode();
1743 
1744     bool v=true;
1745     if ( script_h.isName( "lsph" ) ) v = false;
1746 
1747     int no = script_h.readInt();
1748     AnimationInfo *ai = &sprite_info[no];
1749 
1750     if (ai->image_surface && ai->visible)
1751         dirty_rect.add( ai->pos );
1752     ai->visible = v;
1753 
1754     const char *buf = script_h.readStr();
1755     if (buf[0] == '*'){ // layer
1756         int layer_num=0, c=1;
1757         while (buf[c] >= '0' && buf[c] <= '9')
1758             layer_num = layer_num*10 + buf[c++] - '0';
1759 
1760         LayerInfo *li = &layer_info[layer_num];
1761         if (!li->str){
1762             fprintf(stderr, " lsp: layer %d is not configured.\n", layer_num);
1763             return RET_CONTINUE;
1764         }
1765 
1766         int w=1, h=1;
1767         size_t len = strlen("wcmpg.dll");
1768         if (strlen(li->str) >= len &&
1769             strncmp(li->str+strlen(li->str)-len, "wcmpg.dll", len) == 0){
1770             printf("lsp: %d wcmpg.dll is enabled.\n", no);
1771             smpeg_info = ai;
1772             w = screen_width;
1773             h = screen_height;
1774         }
1775 
1776         li->sprite_num = no;
1777         char filename[64];
1778         sprintf(filename, ":a/1,%d,0;>%d,%d,#000000", li->duration, w, h);
1779         ai->setImageName( filename );
1780         ai->orig_pos.x = 0;
1781         ai->orig_pos.y = 0;
1782         ai->scalePosXY( screen_ratio1, screen_ratio2 );
1783 
1784         ai->default_alpha = 0;
1785 
1786         sprintf(filename, ":a;>%d,%d,#000000", w, h);
1787         effect_src_info.setImageName( filename );
1788         effect_src_info.orig_pos.x = 0;
1789         effect_src_info.orig_pos.y = 0;
1790         effect_src_info.scalePosXY( screen_ratio1, screen_ratio2 );
1791         effect_src_info.blending_mode = AnimationInfo::BLEND_ADD2;
1792         parseTaggedString( &effect_src_info );
1793         setupAnimationInfo( &effect_src_info );
1794     }
1795     else{
1796         ai->setImageName( buf );
1797         ai->orig_pos.x = script_h.readInt();
1798         ai->orig_pos.y = script_h.readInt();
1799         ai->scalePosXY( screen_ratio1, screen_ratio2 );
1800 
1801         if ( script_h.getEndStatus() & ScriptHandler::END_COMMA )
1802             ai->trans = script_h.readInt();
1803         else
1804             ai->trans = -1;
1805     }
1806 
1807     parseTaggedString( ai );
1808     setupAnimationInfo( ai );
1809 
1810     if ( ai->visible ) dirty_rect.add( ai->pos );
1811 
1812     return RET_CONTINUE;
1813 }
1814 
loopbgmstopCommand()1815 int ONScripter::loopbgmstopCommand()
1816 {
1817     if ( wave_sample[MIX_LOOPBGM_CHANNEL0] ){
1818         Mix_Pause(MIX_LOOPBGM_CHANNEL0);
1819         Mix_FreeChunk( wave_sample[MIX_LOOPBGM_CHANNEL0] );
1820         wave_sample[MIX_LOOPBGM_CHANNEL0] = NULL;
1821     }
1822     if ( wave_sample[MIX_LOOPBGM_CHANNEL1] ){
1823         Mix_Pause(MIX_LOOPBGM_CHANNEL1);
1824         Mix_FreeChunk( wave_sample[MIX_LOOPBGM_CHANNEL1] );
1825         wave_sample[MIX_LOOPBGM_CHANNEL1] = NULL;
1826     }
1827     setStr(&loop_bgm_name[0], NULL);
1828 
1829     return RET_CONTINUE;
1830 }
1831 
loopbgmCommand()1832 int ONScripter::loopbgmCommand()
1833 {
1834     const char *buf = script_h.readStr();
1835     setStr( &loop_bgm_name[0], buf );
1836     buf = script_h.readStr();
1837     setStr( &loop_bgm_name[1], buf );
1838 
1839     playSound(loop_bgm_name[1],
1840               SOUND_PRELOAD|SOUND_CHUNK, false, MIX_LOOPBGM_CHANNEL1);
1841     playSound(loop_bgm_name[0],
1842               SOUND_CHUNK, false, MIX_LOOPBGM_CHANNEL0);
1843 
1844     return RET_CONTINUE;
1845 }
1846 
lookbackflushCommand()1847 int ONScripter::lookbackflushCommand()
1848 {
1849     current_page = current_page->next;
1850     for ( int i=0 ; i<max_page_list-1 ; i++ ){
1851         current_page->text_count = 0;
1852         current_page = current_page->next;
1853     }
1854     clearCurrentPage();
1855     start_page = current_page;
1856 
1857     return RET_CONTINUE;
1858 }
1859 
lookbackbuttonCommand()1860 int ONScripter::lookbackbuttonCommand()
1861 {
1862     for ( int i=0 ; i<4 ; i++ ){
1863         const char *buf = script_h.readStr();
1864         setStr( &lookback_info[i].image_name, buf );
1865         parseTaggedString( &lookback_info[i] );
1866         setupAnimationInfo( &lookback_info[i] );
1867     }
1868     return RET_CONTINUE;
1869 }
1870 
logspCommand()1871 int ONScripter::logspCommand()
1872 {
1873     leaveTextDisplayMode();
1874 
1875     bool logsp2_flag = false;
1876 
1877     if ( script_h.isName( "logsp2" ) )
1878         logsp2_flag = true;
1879 
1880     int no = script_h.readInt();
1881     AnimationInfo *ai = &sprite_info[no];
1882 
1883     if (ai->image_surface && ai->visible)
1884         dirty_rect.add( ai->pos );
1885     ai->remove();
1886     setStr( &ai->file_name, script_h.readStr() );
1887 
1888     ai->orig_pos.x = script_h.readInt();
1889     ai->orig_pos.y = script_h.readInt();
1890     ai->scalePosXY( screen_ratio1, screen_ratio2 );
1891 
1892     ai->trans_mode = AnimationInfo::TRANS_STRING;
1893     if (logsp2_flag){
1894         ai->font_size_xy[0] = script_h.readInt();
1895         ai->font_size_xy[1] = script_h.readInt();
1896         ai->font_pitch[0] = script_h.readInt() + ai->font_size_xy[0];
1897         ai->font_pitch[1] = script_h.readInt() + ai->font_size_xy[1];
1898     }
1899     else{
1900         ai->font_size_xy[0] = sentence_font.font_size_xy[0];
1901         ai->font_size_xy[1] = sentence_font.font_size_xy[1];
1902         ai->font_pitch[0] = sentence_font.pitch_xy[0];
1903         ai->font_pitch[1] = sentence_font.pitch_xy[1];
1904     }
1905 
1906     char *current = script_h.getNext();
1907     int num = 0;
1908     while(script_h.getEndStatus() & ScriptHandler::END_COMMA){
1909         script_h.readStr();
1910         num++;
1911     }
1912 
1913     script_h.setCurrent(current);
1914     if (num == 0){
1915         ai->num_of_cells = 1;
1916         ai->color_list = new uchar3[ ai->num_of_cells ];
1917         readColor( &ai->color_list[0], "#ffffff" );
1918     }
1919     else{
1920         ai->num_of_cells = num;
1921         ai->color_list = new uchar3[ ai->num_of_cells ];
1922         for (int i=0 ; i<num ; i++){
1923             readColor( &ai->color_list[i], script_h.readStr() );
1924         }
1925     }
1926 
1927     ai->is_single_line = false;
1928     ai->is_tight_region = false;
1929     ai->is_ruby_drawable = sentence_font.rubyon_flag;
1930     sentence_font.is_newline_accepted = true;
1931     setupAnimationInfo( ai );
1932     sentence_font.is_newline_accepted = false;
1933     ai->visible = true;
1934     dirty_rect.add( ai->pos );
1935 
1936     return RET_CONTINUE;
1937 }
1938 
locateCommand()1939 int ONScripter::locateCommand()
1940 {
1941     int x = script_h.readInt();
1942     int y = script_h.readInt();
1943     sentence_font.setXY( x, y );
1944 
1945     return RET_CONTINUE;
1946 }
1947 
loadgameCommand()1948 int ONScripter::loadgameCommand()
1949 {
1950     int no = script_h.readInt();
1951 
1952     int fadeout = mp3fadeout_duration;
1953     mp3fadeout_duration = 0; //don't use fadeout during a load
1954     if ( !loadSaveFile( no ) ){
1955         dirty_rect.fill( screen_width, screen_height );
1956         flush( refreshMode() );
1957 
1958         saveon_flag = true;
1959         internal_saveon_flag = true;
1960         skip_mode &= ~SKIP_NORMAL;
1961         automode_flag = false;
1962         deleteButtonLink();
1963         deleteSelectLink();
1964         text_on_flag = false;
1965         indent_offset = 0;
1966         line_enter_status = 0;
1967         page_enter_status = 0;
1968         string_buffer_offset = 0;
1969         break_flag = false;
1970 
1971         flushEvent();
1972 
1973 #ifdef USE_LUA
1974         if (lua_handler.isCallbackEnabled(LUAHandler::LUA_LOAD)){
1975             if (lua_handler.callFunction(true, "load", &no))
1976                 errorAndExit( lua_handler.error_str );
1977         }
1978 #endif
1979 
1980         if (loadgosub_label)
1981             gosubReal( loadgosub_label, script_h.getCurrent() );
1982     }
1983 
1984     mp3fadeout_duration = fadeout;
1985 
1986     return RET_CONTINUE;
1987 }
1988 
ldCommand()1989 int ONScripter::ldCommand()
1990 {
1991     leaveTextDisplayMode();
1992 
1993     char loc = script_h.readLabel()[0];
1994     int no = -1;
1995     if      (loc == 'l') no = 0;
1996     else if (loc == 'c') no = 1;
1997     else if (loc == 'r') no = 2;
1998 
1999     const char *buf = NULL;
2000     if (no >= 0) buf = script_h.readStr();
2001 
2002     if (no >= 0){
2003         AnimationInfo *ai = &tachi_info[no];
2004 
2005         if (ai->image_surface) dirty_rect.add( ai->pos );
2006         ai->setImageName( buf );
2007         parseTaggedString( ai );
2008         setupAnimationInfo( ai );
2009 
2010         if ( ai->image_surface ){
2011             ai->visible = true;
2012             ai->orig_pos.x = screen_width * (no+1) * screen_ratio2 / (4 * screen_ratio1) - ai->orig_pos.w / 2;
2013             ai->orig_pos.y = underline_value - ai->image_surface->h * screen_ratio2 / screen_ratio1;
2014             ai->scalePosXY( screen_ratio1, screen_ratio2 );
2015             dirty_rect.add( ai->pos );
2016         }
2017     }
2018 
2019     EffectLink *el = parseEffect(true);
2020     if (setEffect(el)) return RET_CONTINUE;
2021     while (doEffect(el));
2022 
2023     return RET_CONTINUE;
2024 }
2025 #if defined(USE_SMPEG)
smpeg_filter_callback(SDL_Overlay * dst,SDL_Overlay * src,SDL_Rect * region,SMPEG_FilterInfo * filter_info,void * data)2026 static void smpeg_filter_callback( SDL_Overlay * dst, SDL_Overlay * src, SDL_Rect * region, SMPEG_FilterInfo * filter_info, void * data )
2027 {
2028     if (dst){
2029         dst->w = 0;
2030         dst->h = 0;
2031     }
2032 
2033     ONScripter *ons = (ONScripter*)data;
2034     AnimationInfo *ai = ons->getSMPEGInfo();
2035     if (!ai) return;
2036 
2037     ai->convertFromYUV(src);
2038     ons->updateEffect();
2039 }
2040 
smpeg_filter_destroy(struct SMPEG_Filter * filter)2041 static void smpeg_filter_destroy( struct SMPEG_Filter * filter )
2042 {
2043 }
2044 #endif
2045 
layermessageCommand()2046 int ONScripter::layermessageCommand()
2047 {
2048     int no = script_h.readInt();
2049     const char *buf = script_h.readStr();
2050 
2051     if (!layer_info[no].str) return RET_CONTINUE;
2052 
2053 #if defined(USE_SMPEG)
2054     if (&sprite_info[layer_info[no].sprite_num] == smpeg_info){
2055         if (strncmp(buf, "open/",5) == 0){
2056             unsigned long length = script_h.cBR->getFileLength( buf+5 );
2057             if (length == 0){
2058                 fprintf( stderr, " *** can't find file [%s] ***\n", buf+5 );
2059                 return RET_CONTINUE;
2060             }
2061 
2062             stopSMPEG();
2063 
2064             layer_smpeg_buffer = new unsigned char[length];
2065             script_h.cBR->getFile( buf+5, layer_smpeg_buffer );
2066 
2067             layer_smpeg_sample = SMPEG_new_rwops( SDL_RWFromMem( layer_smpeg_buffer, length ), NULL, 0 );
2068 
2069             if ( SMPEG_error( layer_smpeg_sample ) ) return RET_CONTINUE;
2070 
2071             SMPEG_enableaudio( layer_smpeg_sample, 0 );
2072             SMPEG_enablevideo( layer_smpeg_sample, 1 );
2073 #ifdef USE_SDL_RENDERER
2074             // workaround to set a non-NULL value in the second argument
2075             SMPEG_setdisplay( layer_smpeg_sample, accumulation_surface, NULL,  NULL);
2076 #else
2077             SMPEG_setdisplay( layer_smpeg_sample, screen_surface, NULL,  NULL);
2078 #endif
2079         }
2080         else if (strcmp(buf, "play") == 0){
2081             smpeg_info->visible = true;
2082             layer_smpeg_filter.data = this;
2083             layer_smpeg_filter.callback = smpeg_filter_callback;
2084             layer_smpeg_filter.destroy = smpeg_filter_destroy;
2085             SMPEG_filter( layer_smpeg_sample, &layer_smpeg_filter );
2086             SMPEG_loop( layer_smpeg_sample, layer_smpeg_loop_flag?1:0);
2087             SMPEG_renderFrame( layer_smpeg_sample, 1 );
2088             SMPEG_play( layer_smpeg_sample );
2089         }
2090         else if (strcmp(buf, "pause") == 0){
2091             if (layer_smpeg_sample)
2092                 SMPEG_pause( layer_smpeg_sample );
2093         }
2094         else if (strcmp(buf, "close") == 0){
2095             smpeg_info->visible = false;
2096             stopSMPEG();
2097         }
2098         else if (strncmp(buf, "setloop/", 8) == 0){
2099             if (buf[8] == '1')
2100                 layer_smpeg_loop_flag = true;
2101             else
2102                 layer_smpeg_loop_flag = false;
2103         }
2104     }
2105 #endif
2106 
2107     return RET_CONTINUE;
2108 }
2109 
langjpCommand()2110 int ONScripter::langjpCommand()
2111 {
2112     current_read_language = 1;
2113 
2114     return RET_CONTINUE;
2115 }
2116 
langenCommand()2117 int ONScripter::langenCommand()
2118 {
2119     current_read_language = 0;
2120 
2121     return RET_CONTINUE;
2122 }
2123 
kinsokuCommand()2124 int ONScripter::kinsokuCommand()
2125 {
2126     if (script_h.compareString("on")){
2127         is_kinsoku = true;
2128         script_h.readLabel();
2129     }
2130     else if (script_h.compareString("off")){
2131         is_kinsoku = false;
2132         script_h.readLabel();
2133     }
2134 
2135     return RET_CONTINUE;
2136 }
2137 
jumpfCommand()2138 int ONScripter::jumpfCommand()
2139 {
2140     char *buf = script_h.getNext();
2141     while(*buf != '\0' && *buf != '~') buf++;
2142     if (*buf == '~') buf++;
2143 
2144     script_h.setCurrent(buf);
2145     current_label_info = script_h.getLabelByAddress(buf);
2146     current_line = script_h.getLineByAddress(buf);
2147 
2148     return RET_CONTINUE;
2149 }
2150 
jumpbCommand()2151 int ONScripter::jumpbCommand()
2152 {
2153     script_h.setCurrent( last_tilde.next_script );
2154     current_label_info = script_h.getLabelByAddress( last_tilde.next_script );
2155     current_line = script_h.getLineByAddress( last_tilde.next_script );
2156 
2157     return RET_CONTINUE;
2158 }
2159 
ispageCommand()2160 int ONScripter::ispageCommand()
2161 {
2162     script_h.readInt();
2163 
2164     if ( textgosub_clickstr_state == CLICK_NEWPAGE )
2165         script_h.setInt( &script_h.current_variable, 1 );
2166     else
2167         script_h.setInt( &script_h.current_variable, 0 );
2168 
2169     return RET_CONTINUE;
2170 }
2171 
isfullCommand()2172 int ONScripter::isfullCommand()
2173 {
2174     script_h.readInt();
2175     script_h.setInt( &script_h.current_variable, fullscreen_mode?1:0 );
2176 
2177     return RET_CONTINUE;
2178 }
2179 
isskipCommand()2180 int ONScripter::isskipCommand()
2181 {
2182     script_h.readInt();
2183 
2184     if ( automode_flag )
2185         script_h.setInt( &script_h.current_variable, 2 );
2186     else if ( skip_mode & SKIP_NORMAL )
2187         script_h.setInt( &script_h.current_variable, 1 );
2188     else
2189         script_h.setInt( &script_h.current_variable, 0 );
2190 
2191     return RET_CONTINUE;
2192 }
2193 
isdownCommand()2194 int ONScripter::isdownCommand()
2195 {
2196     script_h.readInt();
2197 
2198     if ( current_button_state.down_flag )
2199         script_h.setInt( &script_h.current_variable, 1 );
2200     else
2201         script_h.setInt( &script_h.current_variable, 0 );
2202 
2203     return RET_CONTINUE;
2204 }
2205 
inputCommand()2206 int ONScripter::inputCommand()
2207 {
2208     script_h.readStr();
2209 
2210     if ( script_h.current_variable.type != ScriptHandler::VAR_STR )
2211         errorAndExit( "input: no string variable." );
2212     int no = script_h.current_variable.var_no;
2213 
2214     script_h.readStr(); // description
2215     const char *buf = script_h.readStr(); // default value
2216     setStr( &script_h.getVariableData(no).str, buf );
2217 
2218     printf( "*** inputCommand(): $%d is set to the default value: %s\n",
2219             no, buf );
2220     script_h.readInt(); // maxlen
2221     script_h.readInt(); // widechar flag
2222     if ( script_h.getEndStatus() & ScriptHandler::END_COMMA ){
2223         script_h.readInt(); // window width
2224         script_h.readInt(); // window height
2225         script_h.readInt(); // text box width
2226         script_h.readInt(); // text box height
2227     }
2228 
2229     return RET_CONTINUE;
2230 }
2231 
indentCommand()2232 int ONScripter::indentCommand()
2233 {
2234     indent_offset = script_h.readInt();
2235 
2236     return RET_CONTINUE;
2237 }
2238 
humanorderCommand()2239 int ONScripter::humanorderCommand()
2240 {
2241     leaveTextDisplayMode();
2242 
2243     const char *buf = script_h.readStr();
2244     int i;
2245     for (i=0 ; i<3 ; i++){
2246         if      (buf[i] == 'l') human_order[i] = 0;
2247         else if (buf[i] == 'c') human_order[i] = 1;
2248         else if (buf[i] == 'r') human_order[i] = 2;
2249         else                    human_order[i] = -1;
2250     }
2251 
2252     for ( i=0 ; i<3 ; i++ )
2253         if (tachi_info[i].image_surface)
2254             dirty_rect.add( tachi_info[i].pos );
2255 
2256     EffectLink *el = parseEffect(true);
2257     if (setEffect(el)) return RET_CONTINUE;
2258     while (doEffect(el));
2259 
2260     return RET_CONTINUE;
2261 }
2262 
getzxcCommand()2263 int ONScripter::getzxcCommand()
2264 {
2265     getzxc_flag = true;
2266 
2267     return RET_CONTINUE;
2268 }
2269 
getvoicevolCommand()2270 int ONScripter::getvoicevolCommand()
2271 {
2272     script_h.readInt();
2273     script_h.setInt( &script_h.current_variable, voice_volume );
2274     return RET_CONTINUE;
2275 }
2276 
getversionCommand()2277 int ONScripter::getversionCommand()
2278 {
2279     script_h.readInt();
2280     script_h.setInt( &script_h.current_variable, NSC_VERSION );
2281 
2282     return RET_CONTINUE;
2283 }
2284 
gettimerCommand()2285 int ONScripter::gettimerCommand()
2286 {
2287     bool gettimer_flag=false;
2288 
2289     if      ( script_h.isName( "gettimer" ) ){
2290         gettimer_flag = true;
2291     }
2292     else if ( script_h.isName( "getbtntimer" ) ){
2293     }
2294 
2295     script_h.readInt();
2296 
2297     if ( gettimer_flag ){
2298         script_h.setInt( &script_h.current_variable, SDL_GetTicks() - internal_timer );
2299     }
2300     else{
2301         script_h.setInt( &script_h.current_variable, btnwait_time );
2302     }
2303 
2304     return RET_CONTINUE;
2305 }
2306 
gettextCommand()2307 int ONScripter::gettextCommand()
2308 {
2309     script_h.readStr();
2310     int no = script_h.current_variable.var_no;
2311 
2312     char *buf = new char[ current_page->text_count + 1 ];
2313     int i, j;
2314     for ( i=0, j=0 ; i<current_page->text_count ; i++ ){
2315         if ( current_page->text[i] != 0x0a )
2316             buf[j++] = current_page->text[i];
2317     }
2318     buf[j] = '\0';
2319 
2320     setStr( &script_h.getVariableData(no).str, buf );
2321     delete[] buf;
2322 
2323     return RET_CONTINUE;
2324 }
2325 
gettaglogCommand()2326 int ONScripter::gettaglogCommand()
2327 {
2328     script_h.readVariable();
2329     script_h.pushVariable();
2330 
2331     int page_no = script_h.readInt();
2332 
2333     Page *page = current_page;
2334     while(page != start_page && page_no > 0){
2335         page_no--;
2336         page = page->previous;
2337     }
2338 
2339     if (page->tag)
2340         setStr(&script_h.getVariableData(script_h.pushed_variable.var_no).str, page->tag);
2341     else
2342         setStr(&script_h.getVariableData(script_h.pushed_variable.var_no).str, NULL);
2343 
2344     return RET_CONTINUE;
2345 }
2346 
gettagCommand()2347 int ONScripter::gettagCommand()
2348 {
2349     if ( !last_nest_info->previous || last_nest_info->nest_mode != NestInfo::LABEL )
2350         errorAndExit( "gettag: not in a subroutine, i.e. pretextgosub" );
2351 
2352     char *buf = pretext_buf;
2353 
2354     int n = script_h.enc.getBytes(buf[0]);
2355     unsigned short unicode1 = script_h.enc.getUTF16(buf);
2356     unsigned short unicode2 = script_h.enc.getUTF16("��", Encoding::CODE_CP932);
2357     if (buf[0] == '[')
2358         buf++;
2359     else if (zenkakko_flag && unicode1 == unicode2)
2360         buf += n;
2361     else
2362         buf = NULL;
2363 
2364     int end_status;
2365     do{
2366         script_h.readVariable();
2367         end_status = script_h.getEndStatus();
2368         script_h.pushVariable();
2369 
2370         if ( script_h.pushed_variable.type & ScriptHandler::VAR_INT ||
2371              script_h.pushed_variable.type & ScriptHandler::VAR_ARRAY ){
2372             if (buf)
2373                 script_h.setInt( &script_h.pushed_variable, script_h.parseInt(&buf));
2374             else
2375                 script_h.setInt( &script_h.pushed_variable, 0);
2376         }
2377         else if ( script_h.pushed_variable.type & ScriptHandler::VAR_STR ){
2378             if (buf){
2379                 const char *buf_start = buf;
2380                 unicode1 = script_h.enc.getUTF16(buf);
2381                 unicode2 = script_h.enc.getUTF16("��", Encoding::CODE_CP932);
2382                 while(*buf != '/' && *buf != 0 && *buf != ']' &&
2383                       (!zenkakko_flag || unicode1 != unicode2)){
2384                     buf += script_h.enc.getBytes(buf[0]);
2385                 }
2386                 setStr( &script_h.getVariableData(script_h.pushed_variable.var_no).str, buf_start, buf-buf_start );
2387             }
2388             else{
2389                 setStr( &script_h.getVariableData(script_h.pushed_variable.var_no).str, NULL);
2390             }
2391         }
2392 
2393         if (buf) pretext_buf = buf;
2394         if (buf && *buf == '/')
2395             buf++;
2396         else
2397             buf = NULL;
2398     }
2399     while(end_status & ScriptHandler::END_COMMA);
2400 
2401     n = script_h.enc.getBytes(pretext_buf[0]);
2402     unicode1 = script_h.enc.getUTF16(pretext_buf);
2403     unicode2 = script_h.enc.getUTF16("��", Encoding::CODE_CP932);
2404     if (pretext_buf[0] == ']')
2405         pretext_buf++;
2406     else if (zenkakko_flag && unicode1 == unicode2)
2407         pretext_buf += n;
2408 
2409     return RET_CONTINUE;
2410 }
2411 
gettabCommand()2412 int ONScripter::gettabCommand()
2413 {
2414     gettab_flag = true;
2415 
2416     return RET_CONTINUE;
2417 }
2418 
getspsizeCommand()2419 int ONScripter::getspsizeCommand()
2420 {
2421     int no = script_h.readInt();
2422 
2423     script_h.readVariable();
2424     script_h.setInt( &script_h.current_variable, sprite_info[no].orig_pos.w );
2425     script_h.readVariable();
2426     script_h.setInt( &script_h.current_variable, sprite_info[no].orig_pos.h );
2427     if ( script_h.getEndStatus() & ScriptHandler::END_COMMA ){
2428         script_h.readVariable();
2429         script_h.setInt( &script_h.current_variable, sprite_info[no].num_of_cells );
2430     }
2431 
2432     return RET_CONTINUE;
2433 }
2434 
getspposCommand()2435 int ONScripter::getspposCommand()
2436 {
2437     int no = script_h.readInt();
2438 
2439     script_h.readVariable();
2440     script_h.setInt( &script_h.current_variable, sprite_info[no].orig_pos.x );
2441 
2442     script_h.readVariable();
2443     script_h.setInt( &script_h.current_variable, sprite_info[no].orig_pos.y );
2444 
2445     return RET_CONTINUE;
2446 }
2447 
getspmodeCommand()2448 int ONScripter::getspmodeCommand()
2449 {
2450     script_h.readVariable();
2451     script_h.pushVariable();
2452 
2453     int no = script_h.readInt();
2454     script_h.setInt( &script_h.pushed_variable, sprite_info[no].visible?1:0 );
2455 
2456     return RET_CONTINUE;
2457 }
2458 
getsevolCommand()2459 int ONScripter::getsevolCommand()
2460 {
2461     script_h.readInt();
2462     script_h.setInt( &script_h.current_variable, se_volume );
2463     return RET_CONTINUE;
2464 }
2465 
getscreenshotCommand()2466 int ONScripter::getscreenshotCommand()
2467 {
2468     int w = script_h.readInt();
2469     if (disable_rescale_flag) w = w * screen_ratio1 / screen_ratio2;
2470     int h = script_h.readInt();
2471     if (disable_rescale_flag) h = h * screen_ratio1 / screen_ratio2;
2472     if ( w == 0 ) w = 1;
2473     if ( h == 0 ) h = 1;
2474 
2475     screenshot_w = w;
2476     screenshot_h = h;
2477 #ifdef USE_SDL_RENDERER
2478     SDL_Rect rect = {(device_width -screen_device_width)/2,
2479                      (device_height-screen_device_height)/2,
2480                      screen_device_width, screen_device_height};
2481     SDL_LockSurface(screenshot_surface);
2482     SDL_RenderReadPixels(renderer, &rect, screenshot_surface->format->format, screenshot_surface->pixels, screenshot_surface->pitch);
2483     SDL_UnlockSurface(screenshot_surface);
2484 #else
2485     SDL_BlitSurface(screen_surface, NULL, screenshot_surface, NULL);
2486 #endif
2487 
2488     return RET_CONTINUE;
2489 }
2490 
getsavestrCommand()2491 int ONScripter::getsavestrCommand()
2492 {
2493     script_h.readVariable();
2494     if ( script_h.current_variable.type != ScriptHandler::VAR_STR )
2495         errorAndExit( "getsavestr: no string variable." );
2496 
2497     script_h.pushVariable();
2498 
2499     int no = script_h.readInt();
2500     char *buf = readSaveStrFromFile( no );
2501 
2502     setStr( &script_h.getVariableData(script_h.pushed_variable.var_no).str, buf );
2503     if (buf) delete[] buf;
2504 
2505     return RET_CONTINUE;
2506 }
2507 
getreadlangCommand()2508 int ONScripter::getreadlangCommand()
2509 {
2510     script_h.readInt();
2511     script_h.setInt(&script_h.current_variable, current_read_language);
2512 
2513     return RET_CONTINUE;
2514 }
2515 
getpageupCommand()2516 int ONScripter::getpageupCommand()
2517 {
2518     getpageup_flag = true;
2519 
2520     return RET_CONTINUE;
2521 }
2522 
getpageCommand()2523 int ONScripter::getpageCommand()
2524 {
2525     getpageup_flag = true;
2526     getpagedown_flag = true;
2527 
2528     return RET_CONTINUE;
2529 }
2530 
getretCommand()2531 int ONScripter::getretCommand()
2532 {
2533     script_h.readVariable();
2534 
2535     if ( script_h.current_variable.type == ScriptHandler::VAR_INT ||
2536          script_h.current_variable.type == ScriptHandler::VAR_ARRAY ){
2537         script_h.setInt( &script_h.current_variable, getret_int );
2538     }
2539     else if ( script_h.current_variable.type == ScriptHandler::VAR_STR ){
2540         int no = script_h.current_variable.var_no;
2541         setStr( &script_h.getVariableData(no).str, getret_str );
2542     }
2543     else errorAndExit( "getret: no variable." );
2544 
2545     return RET_CONTINUE;
2546 }
2547 
getregCommand()2548 int ONScripter::getregCommand()
2549 {
2550     script_h.readVariable();
2551 
2552     if ( script_h.current_variable.type != ScriptHandler::VAR_STR )
2553         errorAndExit( "getreg: no string variable." );
2554     int no = script_h.current_variable.var_no;
2555 
2556     const char *buf = script_h.readStr();
2557     char path[256], key[256];
2558     strcpy( path, buf );
2559     buf = script_h.readStr();
2560     strcpy( key, buf );
2561 
2562     printf("  reading Registry file for [%s] %s\n", path, key );
2563 
2564     FILE *fp;
2565     if ( ( fp = fopen( registry_file, "r" ) ) == NULL ){
2566         fprintf( stderr, "Cannot open file [%s]\n", registry_file );
2567         return RET_CONTINUE;
2568     }
2569 
2570     char reg_buf[256], reg_buf2[256];
2571     bool found_flag = false;
2572     while( fgets( reg_buf, 256, fp) && !found_flag ){
2573         if ( reg_buf[0] == '[' ){
2574             unsigned int c=0;
2575             while ( reg_buf[c] != ']' && reg_buf[c] != '\0' ) c++;
2576             if ( !strncmp( reg_buf + 1, path, (c-1>strlen(path))?(c-1):strlen(path) ) ){
2577                 while( fgets( reg_buf2, 256, fp) ){
2578 
2579                     script_h.pushCurrent( reg_buf2 );
2580                     buf = script_h.readStr();
2581                     if ( strncmp( buf,
2582                                   key,
2583                                   (strlen(buf)>strlen(key))?strlen(buf):strlen(key) ) ){
2584                         script_h.popCurrent();
2585                         continue;
2586                     }
2587 
2588                     if ( !script_h.compareString("=") ){
2589                         script_h.popCurrent();
2590                         continue;
2591                     }
2592                     script_h.setCurrent(script_h.getNext()+1);
2593 
2594                     buf = script_h.readStr();
2595                     setStr( &script_h.getVariableData(no).str, buf );
2596                     script_h.popCurrent();
2597                     printf("  $%d = %s\n", no, script_h.getVariableData(no).str );
2598                     found_flag = true;
2599                     break;
2600                 }
2601             }
2602         }
2603     }
2604 
2605     if ( !found_flag ) fprintf( stderr, "  The key is not found.\n" );
2606     fclose(fp);
2607 
2608     return RET_CONTINUE;
2609 }
2610 
getmclickCommand()2611 int ONScripter::getmclickCommand()
2612 {
2613     getmclick_flag = true;
2614 
2615     return RET_CONTINUE;
2616 }
2617 
getmp3volCommand()2618 int ONScripter::getmp3volCommand()
2619 {
2620     script_h.readInt();
2621     script_h.setInt( &script_h.current_variable, music_volume );
2622     return RET_CONTINUE;
2623 }
2624 
getmouseposCommand()2625 int ONScripter::getmouseposCommand()
2626 {
2627     script_h.readInt();
2628     script_h.setInt( &script_h.current_variable, current_button_state.x * screen_ratio2 / screen_ratio1 );
2629 
2630     script_h.readInt();
2631     script_h.setInt( &script_h.current_variable, current_button_state.y * screen_ratio2 / screen_ratio1 );
2632 
2633     return RET_CONTINUE;
2634 }
2635 
getmouseoverCommand()2636 int ONScripter::getmouseoverCommand()
2637 {
2638     getmouseover_flag = true;
2639 
2640     getmouseover_lower = script_h.readInt();
2641     getmouseover_upper = script_h.readInt();
2642 
2643     return RET_CONTINUE;
2644 }
2645 
getlogCommand()2646 int ONScripter::getlogCommand()
2647 {
2648     bool getlogtext_flag=false;
2649 
2650     if ( script_h.isName( "getlogtext" ) )
2651         getlogtext_flag = true;
2652 
2653     script_h.readVariable();
2654     script_h.pushVariable();
2655 
2656     int page_no = script_h.readInt();
2657 
2658     Page *page = current_page;
2659     while(page != start_page && page_no > 0){
2660         page_no--;
2661         page = page->previous;
2662     }
2663 
2664     if (page_no > 0)
2665         setStr( &script_h.getVariableData(script_h.pushed_variable.var_no).str, NULL );
2666     else{
2667         char *buf = page->text;
2668         int count = page->text_count;
2669         if (getlogtext_flag){
2670             char *p = page->text;
2671             char *p2 = buf = new char[page->text_count];
2672             count = 0;
2673             for (int i=0 ; i<page->text_count ; i++){
2674                 int n = script_h.enc.getBytes(*p);
2675                 if (n >= 2){
2676                     for (int j=0; j<n; j++)
2677                         p2[count++] = *p++;
2678                     i += n-1;
2679                 }
2680                 else if (*p != 0x0a)
2681                     p2[count++] = *p++;
2682                 else
2683                     p++;
2684             }
2685         }
2686 
2687         setStr( &script_h.getVariableData(script_h.pushed_variable.var_no).str, buf, count );
2688 
2689         if (getlogtext_flag) delete[] buf;
2690     }
2691 
2692     return RET_CONTINUE;
2693 }
2694 
getinsertCommand()2695 int ONScripter::getinsertCommand()
2696 {
2697     getinsert_flag = true;
2698 
2699     return RET_CONTINUE;
2700 }
2701 
getfunctionCommand()2702 int ONScripter::getfunctionCommand()
2703 {
2704     getfunction_flag = true;
2705 
2706     return RET_CONTINUE;
2707 }
2708 
getenterCommand()2709 int ONScripter::getenterCommand()
2710 {
2711     if ( !force_button_shortcut_flag )
2712         getenter_flag = true;
2713 
2714     return RET_CONTINUE;
2715 }
2716 
getcursorpos2Command()2717 int ONScripter::getcursorpos2Command()
2718 {
2719     script_h.readInt();
2720     script_h.setInt( &script_h.current_variable, sentence_font.old_xy[0] );
2721 
2722     script_h.readInt();
2723     script_h.setInt( &script_h.current_variable, sentence_font.old_xy[1] );
2724 
2725     return RET_CONTINUE;
2726 }
2727 
getcursorposCommand()2728 int ONScripter::getcursorposCommand()
2729 {
2730     FontInfo fi = sentence_font;
2731 
2732     if ( fi.isEndOfLine() ){
2733         fi.newLine();
2734         for (int i=0 ; i<indent_offset ; i++)
2735             fi.advanceCharInHankaku(2);
2736     }
2737 
2738     script_h.readInt();
2739     script_h.setInt( &script_h.current_variable, fi.x(false) );
2740 
2741     script_h.readInt();
2742     script_h.setInt( &script_h.current_variable, fi.y(false) );
2743 
2744     return RET_CONTINUE;
2745 }
2746 
getcursorCommand()2747 int ONScripter::getcursorCommand()
2748 {
2749     if ( !force_button_shortcut_flag )
2750         getcursor_flag = true;
2751 
2752     return RET_CONTINUE;
2753 }
2754 
getcselstrCommand()2755 int ONScripter::getcselstrCommand()
2756 {
2757     script_h.readVariable();
2758     script_h.pushVariable();
2759 
2760     int csel_no = script_h.readInt();
2761 
2762     int counter = 0;
2763     SelectLink *link = root_select_link.next;
2764     while (link){
2765         if (csel_no == counter++) break;
2766         link = link->next;
2767     }
2768 
2769     setStr(&script_h.getVariableData(script_h.pushed_variable.var_no).str, link?(link->text):NULL);
2770 
2771     return RET_CONTINUE;
2772 }
2773 
getcselnumCommand()2774 int ONScripter::getcselnumCommand()
2775 {
2776     int count = 0;
2777 
2778     SelectLink *link = root_select_link.next;
2779     while ( link ) {
2780         count++;
2781         link = link->next;
2782     }
2783     script_h.readInt();
2784     script_h.setInt( &script_h.current_variable, count );
2785 
2786     return RET_CONTINUE;
2787 }
2788 
gameCommand()2789 int ONScripter::gameCommand()
2790 {
2791     if ( current_mode != DEFINE_MODE )
2792         errorAndExit( "game: not in the define section" );
2793 
2794     int i;
2795     current_mode = NORMAL_MODE;
2796 
2797     /* ---------------------------------------- */
2798     if ( !lookback_info[0].image_surface ){
2799         setStr( &lookback_info[0].image_name, DEFAULT_LOOKBACK_NAME0 );
2800         parseTaggedString( &lookback_info[0] );
2801         setupAnimationInfo( &lookback_info[0] );
2802     }
2803     if ( !lookback_info[1].image_surface ){
2804         setStr( &lookback_info[1].image_name, DEFAULT_LOOKBACK_NAME1 );
2805         parseTaggedString( &lookback_info[1] );
2806         setupAnimationInfo( &lookback_info[1] );
2807     }
2808     if ( !lookback_info[2].image_surface ){
2809         setStr( &lookback_info[2].image_name, DEFAULT_LOOKBACK_NAME2 );
2810         parseTaggedString( &lookback_info[2] );
2811         setupAnimationInfo( &lookback_info[2] );
2812     }
2813     if ( !lookback_info[3].image_surface ){
2814         setStr( &lookback_info[3].image_name, DEFAULT_LOOKBACK_NAME3 );
2815         parseTaggedString( &lookback_info[3] );
2816         setupAnimationInfo( &lookback_info[3] );
2817     }
2818 
2819     /* ---------------------------------------- */
2820     /* Initialize text buffer */
2821     page_list = new Page[max_page_list];
2822     for ( i=0 ; i<max_page_list-1 ; i++ ){
2823         page_list[i].next = &page_list[i+1];
2824         page_list[i+1].previous = &page_list[i];
2825     }
2826     page_list[0].previous = &page_list[max_page_list-1];
2827     page_list[max_page_list-1].next = &page_list[0];
2828 
2829     resetCommand();
2830 
2831     loadCursor( 0, NULL, 0, 0 );
2832     loadCursor( 1, NULL, 0, 0 );
2833 
2834 #ifdef USE_LUA
2835     lua_handler.loadInitScript();
2836     if (lua_handler.isCallbackEnabled(LUAHandler::LUA_RESET)){
2837         if (lua_handler.callFunction(true, "reset"))
2838             errorAndExit( lua_handler.error_str );
2839     }
2840 #endif
2841 
2842     return RET_CONTINUE;
2843 }
2844 
fileexistCommand()2845 int ONScripter::fileexistCommand()
2846 {
2847     script_h.readInt();
2848     script_h.pushVariable();
2849     const char *buf = script_h.readStr();
2850 
2851     script_h.setInt( &script_h.pushed_variable, (script_h.cBR->getFileLength(buf)>0)?1:0 );
2852 
2853     return RET_CONTINUE;
2854 }
2855 
exec_dllCommand()2856 int ONScripter::exec_dllCommand()
2857 {
2858     const char *buf = script_h.readStr();
2859     char dll_name[256];
2860     unsigned int c=0, c2=0;
2861     while(buf[c] != '/' && buf[c] != 0x0){
2862         if (buf[c] == '\\'){
2863             c++;
2864             c2 = 0;
2865             continue;
2866         }
2867         dll_name[c2++] = buf[c++];
2868     }
2869     dll_name[c2] = '\0';
2870 
2871     if (strcmp(dll_name, "fileutil.dll") == 0){
2872         if (strncmp(buf+c, "/mkdir", 6) == 0){
2873             c += 7;
2874             char *dir = new char[strlen(archive_path) + strlen(buf+c) + 1];
2875             sprintf(dir, "%s%s", archive_path, buf+c);
2876 #if defined(LINUX) || defined(MACOSX) || defined(IOS)
2877             mkdir(dir, 0755);
2878 #elif defined(WIN32)
2879             _mkdir(dir);
2880 #endif
2881             delete[] dir;
2882         }
2883         return RET_CONTINUE;
2884     }
2885 
2886     FILE *fp;
2887     if ( ( fp = fopen( dll_file, "r" ) ) == NULL ){
2888         fprintf( stderr, "Cannot open file [%s] while reading %s\n", dll_file, dll_name );
2889         return RET_CONTINUE;
2890     }
2891 
2892     char dll_buf[256], dll_buf2[256];
2893     bool found_flag = false;
2894     while( fgets( dll_buf, 256, fp) && !found_flag ){
2895         if ( dll_buf[0] == '[' ){
2896             c=0;
2897             while ( dll_buf[c] != ']' && dll_buf[c] != '\0' ) c++;
2898             if ( !strncmp( dll_buf + 1, dll_name, (c-1>strlen(dll_name))?(c-1):strlen(dll_name) ) ){
2899                 found_flag = true;
2900                 while( fgets( dll_buf2, 256, fp) ){
2901                     c=0;
2902                     while ( dll_buf2[c] == ' ' || dll_buf2[c] == '\t' ) c++;
2903                     if ( !strncmp( &dll_buf2[c], "str", 3 ) ){
2904                         c+=3;
2905                         while ( dll_buf2[c] == ' ' || dll_buf2[c] == '\t' ) c++;
2906                         if ( dll_buf2[c] != '=' ) continue;
2907                         c++;
2908                         while ( dll_buf2[c] != '"' ) c++;
2909                         unsigned int c2 = ++c;
2910                         while ( dll_buf2[c2] != '"' && dll_buf2[c2] != '\0' ) c2++;
2911                         dll_buf2[c2] = '\0';
2912                         setStr( &getret_str, &dll_buf2[c] );
2913                         printf("  getret_str = %s\n", getret_str );
2914                     }
2915                     else if ( !strncmp( &dll_buf2[c], "ret", 3 ) ){
2916                         c+=3;
2917                         while ( dll_buf2[c] == ' ' || dll_buf2[c] == '\t' ) c++;
2918                         if ( dll_buf2[c] != '=' ) continue;
2919                         c++;
2920                         while ( dll_buf2[c] == ' ' || dll_buf2[c] == '\t' ) c++;
2921                         getret_int = atoi( &dll_buf2[c] );
2922                         printf("  getret_int = %d\n", getret_int );
2923                     }
2924                     else if ( dll_buf2[c] == '[' )
2925                         break;
2926                 }
2927             }
2928         }
2929     }
2930 
2931     if ( !found_flag ) fprintf( stderr, "  The DLL is not found in %s.\n", dll_file );
2932     fclose( fp );
2933 
2934     return RET_CONTINUE;
2935 }
2936 
exbtnCommand()2937 int ONScripter::exbtnCommand()
2938 {
2939     int sprite_no=-1, no=0;
2940     ButtonLink *bl;
2941 
2942     if ( script_h.isName( "exbtn_d" ) ||
2943          script_h.isName( "bdef" )){
2944         bl = &exbtn_d_button_link;
2945         for (int i=0 ; i<3 ; i++){
2946             if ( bl->exbtn_ctl[i] ){
2947                 delete[] bl->exbtn_ctl[i];
2948                 bl->exbtn_ctl[i] = NULL;
2949             }
2950         }
2951     }
2952     else{
2953         bool cellcheck_flag = false;
2954 
2955         if ( script_h.isName( "cellcheckexbtn" ) )
2956             cellcheck_flag = true;
2957 
2958         sprite_no = script_h.readInt();
2959         no = script_h.readInt();
2960 
2961         if (no < 1 ||
2962             sprite_no < 0 ||
2963             sprite_no >= MAX_SPRITE_NUM ||
2964             sprite_info[sprite_no].image_surface == NULL ||
2965             ( cellcheck_flag && sprite_info[ sprite_no ].num_of_cells < 2) ||
2966             (!cellcheck_flag && sprite_info[ sprite_no ].num_of_cells == 0)){
2967             script_h.readStr();
2968             return RET_CONTINUE;
2969         }
2970 
2971         bl = new ButtonLink();
2972         root_button_link.insert( bl );
2973         is_exbtn_enabled = true;
2974     }
2975 
2976     const char *buf = script_h.readStr();
2977 
2978     bl->button_type = ButtonLink::SPRITE_BUTTON;
2979     bl->sprite_no   = sprite_no;
2980     bl->no          = no;
2981     setStr( &bl->exbtn_ctl[1], buf );
2982 
2983     if ( sprite_no >= 0 &&
2984          ( sprite_info[ sprite_no ].image_surface ||
2985            sprite_info[ sprite_no ].trans_mode == AnimationInfo::TRANS_STRING ) )
2986         bl->image_rect = bl->select_rect = sprite_info[ sprite_no ].pos;
2987 
2988     return RET_CONTINUE;
2989 }
2990 
erasetextwindowCommand()2991 int ONScripter::erasetextwindowCommand()
2992 {
2993     erase_text_window_mode = script_h.readInt();
2994 
2995     return RET_CONTINUE;
2996 }
2997 
endCommand()2998 int ONScripter::endCommand()
2999 {
3000     quit();
3001     stopSMPEG();
3002     exit(0);
3003     return RET_CONTINUE; // dummy
3004 }
3005 
dwavestopCommand()3006 int ONScripter::dwavestopCommand()
3007 {
3008     int ch = script_h.readInt();
3009     if      (ch < 0) ch = 0;
3010     else if (ch >= ONS_MIX_CHANNELS) ch = ONS_MIX_CHANNELS-1;
3011 
3012     if ( wave_sample[ch] ){
3013         Mix_Pause( ch );
3014         Mix_FreeChunk( wave_sample[ch] );
3015         wave_sample[ch] = NULL;
3016     }
3017 
3018     return RET_CONTINUE;
3019 }
3020 
dwaveCommand()3021 int ONScripter::dwaveCommand()
3022 {
3023     int play_mode = WAVE_PLAY;
3024     bool loop_flag = false;
3025 
3026     if ( script_h.isName( "dwaveloop" ) ){
3027         loop_flag = true;
3028     }
3029     else if ( script_h.isName( "dwaveload" ) ){
3030         play_mode = WAVE_PRELOAD;
3031     }
3032     else if ( script_h.isName( "dwaveplayloop" ) ){
3033         play_mode = WAVE_PLAY_LOADED;
3034         loop_flag = true;
3035     }
3036     else if ( script_h.isName( "dwaveplay" ) ){
3037         play_mode = WAVE_PLAY_LOADED;
3038         loop_flag = false;
3039     }
3040 
3041     int ch = script_h.readInt();
3042     if      (ch < 0) ch = 0;
3043     else if (ch >= ONS_MIX_CHANNELS) ch = ONS_MIX_CHANNELS-1;
3044 
3045     if (play_mode == WAVE_PLAY_LOADED){
3046         Mix_PlayChannel(ch, wave_sample[ch], loop_flag?-1:0);
3047     }
3048     else{
3049         const char *buf = script_h.readStr();
3050         int fmt = SOUND_CHUNK;
3051         if (play_mode == WAVE_PRELOAD) fmt |= SOUND_PRELOAD;
3052         playSound(buf, fmt, loop_flag, ch);
3053     }
3054 
3055     return RET_CONTINUE;
3056 }
3057 
dvCommand()3058 int ONScripter::dvCommand()
3059 {
3060     char buf[256];
3061 
3062     sprintf(buf, RELATIVEPATH "voice%c%s.wav", DELIMITER, script_h.getStringBuffer()+2);
3063     playSound(buf, SOUND_CHUNK, false, 0);
3064 
3065     return RET_CONTINUE;
3066 }
3067 
drawtextCommand()3068 int ONScripter::drawtextCommand()
3069 {
3070     SDL_Rect clip;
3071     clip.x = clip.y = 0;
3072     clip.w = accumulation_surface->w;
3073     clip.h = accumulation_surface->h;
3074     text_info.blendOnSurface( accumulation_surface, 0, 0, clip, layer_alpha_buf );
3075 
3076     return RET_CONTINUE;
3077 }
3078 
drawsp3Command()3079 int ONScripter::drawsp3Command()
3080 {
3081     int sprite_no = script_h.readInt();
3082     int cell_no = script_h.readInt();
3083     int alpha = script_h.readInt();
3084     int x = script_h.readInt() * screen_ratio1 / screen_ratio2;
3085     int y = script_h.readInt() * screen_ratio1 / screen_ratio2;
3086 
3087     AnimationInfo *ai = &sprite_info[sprite_no];
3088     int old_cell_no = ai->current_cell;
3089     ai->setCell(cell_no);
3090 
3091     ai->mat[0][0] = script_h.readInt();
3092     ai->mat[0][1] = script_h.readInt();
3093     ai->mat[1][0] = script_h.readInt();
3094     ai->mat[1][1] = script_h.readInt();
3095 
3096     int denom = (ai->mat[0][0]*ai->mat[1][1]-ai->mat[0][1]*ai->mat[1][0])/1000;
3097     if (denom != 0){
3098         ai->inv_mat[0][0] =  ai->mat[1][1] * 1000 / denom;
3099         ai->inv_mat[0][1] = -ai->mat[0][1] * 1000 / denom;
3100         ai->inv_mat[1][0] = -ai->mat[1][0] * 1000 / denom;
3101         ai->inv_mat[1][1] =  ai->mat[0][0] * 1000 / denom;
3102     }
3103 
3104     ai->blendOnSurface2( accumulation_surface, x, y, screen_rect, layer_alpha_buf, alpha );
3105     ai->setCell(old_cell_no);
3106 
3107     return RET_CONTINUE;
3108 }
3109 
drawsp2Command()3110 int ONScripter::drawsp2Command()
3111 {
3112     int sprite_no = script_h.readInt();
3113     int cell_no = script_h.readInt();
3114     int alpha = script_h.readInt();
3115 
3116     AnimationInfo *ai = &sprite_info[sprite_no];
3117     ai->orig_pos.x = script_h.readInt();
3118     ai->orig_pos.y = script_h.readInt();
3119     ai->scalePosXY( screen_ratio1, screen_ratio2 );
3120     ai->scale_x = script_h.readInt();
3121     ai->scale_y = script_h.readInt();
3122     ai->rot     = script_h.readInt();
3123     ai->calcAffineMatrix();
3124     ai->setCell(cell_no);
3125 
3126     ai->blendOnSurface2( accumulation_surface, ai->pos.x, ai->pos.y, screen_rect, layer_alpha_buf, alpha );
3127 
3128     return RET_CONTINUE;
3129 }
3130 
drawspCommand()3131 int ONScripter::drawspCommand()
3132 {
3133     int sprite_no = script_h.readInt();
3134     int cell_no = script_h.readInt();
3135     int alpha = script_h.readInt();
3136     int x = script_h.readInt() * screen_ratio1 / screen_ratio2;
3137     int y = script_h.readInt() * screen_ratio1 / screen_ratio2;
3138 
3139     AnimationInfo *ai = &sprite_info[sprite_no];
3140     int old_cell_no = ai->current_cell;
3141     ai->setCell(cell_no);
3142     SDL_Rect clip;
3143     clip.x = clip.y = 0;
3144     clip.w = accumulation_surface->w;
3145     clip.h = accumulation_surface->h;
3146     ai->blendOnSurface( accumulation_surface, x, y, clip, layer_alpha_buf, alpha );
3147     ai->setCell(old_cell_no);
3148 
3149     return RET_CONTINUE;
3150 }
3151 
drawfillCommand()3152 int ONScripter::drawfillCommand()
3153 {
3154     int r = script_h.readInt();
3155     int g = script_h.readInt();
3156     int b = script_h.readInt();
3157 
3158     SDL_FillRect( accumulation_surface, NULL, SDL_MapRGBA( accumulation_surface->format, r, g, b, 0xff) );
3159 
3160     return RET_CONTINUE;
3161 }
3162 
drawclearCommand()3163 int ONScripter::drawclearCommand()
3164 {
3165     SDL_FillRect( accumulation_surface, NULL, SDL_MapRGBA( accumulation_surface->format, 0, 0, 0, 0xff) );
3166 
3167     return RET_CONTINUE;
3168 }
3169 
drawbgCommand()3170 int ONScripter::drawbgCommand()
3171 {
3172     SDL_Rect clip;
3173     clip.x = clip.y = 0;
3174     clip.w = accumulation_surface->w;
3175     clip.h = accumulation_surface->h;
3176     bg_info.blendOnSurface( accumulation_surface, bg_info.pos.x, bg_info.pos.y, clip, layer_alpha_buf );
3177 
3178     return RET_CONTINUE;
3179 }
3180 
drawbg2Command()3181 int ONScripter::drawbg2Command()
3182 {
3183     AnimationInfo bi = bg_info;
3184     bi.orig_pos.x = script_h.readInt();
3185     bi.orig_pos.y = script_h.readInt();
3186     bi.scalePosXY( screen_ratio1, screen_ratio2 );
3187     bi.scale_x = script_h.readInt();
3188     bi.scale_y = script_h.readInt();
3189     bi.rot     = script_h.readInt();
3190     bi.calcAffineMatrix();
3191 
3192     bi.blendOnSurface2( accumulation_surface, bi.pos.x, bi.pos.y, screen_rect, layer_alpha_buf, 255 );
3193 
3194     return RET_CONTINUE;
3195 }
3196 
drawCommand()3197 int ONScripter::drawCommand()
3198 {
3199     flushDirect( screen_rect, REFRESH_NONE_MODE );
3200     dirty_rect.clear();
3201 
3202     return RET_CONTINUE;
3203 }
3204 
delayCommand()3205 int ONScripter::delayCommand()
3206 {
3207     int val = script_h.readInt();
3208 
3209     if (skip_mode & SKIP_NORMAL || ctrl_pressed_status)
3210         return RET_CONTINUE;
3211 
3212     event_mode = WAIT_TIMER_MODE | WAIT_INPUT_MODE;
3213     waitEvent( val );
3214 
3215     return RET_CONTINUE;
3216 }
3217 
defineresetCommand()3218 int ONScripter::defineresetCommand()
3219 {
3220     saveGlovalData();
3221 
3222     script_h.reset();
3223     ScriptParser::reset();
3224     reset();
3225 
3226     setCurrentLabel( "define" );
3227 
3228     if ( loadFileIOBuf( "gloval.sav" ) > 0 )
3229         readVariables( script_h.global_variable_border, script_h.variable_range );
3230 
3231 #ifdef USE_LUA
3232     lua_handler.init(this, &script_h, screen_ratio1, screen_ratio2);
3233 #endif
3234 
3235     current_mode = DEFINE_MODE;
3236 
3237     return RET_CONTINUE;
3238 }
3239 
cspCommand()3240 int ONScripter::cspCommand()
3241 {
3242     leaveTextDisplayMode();
3243 
3244     bool csp2_flag = false;
3245     if (script_h.isName("csp2")) csp2_flag = true;
3246 
3247     int no = script_h.readInt();
3248     AnimationInfo *si = NULL;
3249     int num = 0;
3250     if (csp2_flag) {
3251         num = MAX_SPRITE2_NUM;
3252         si = sprite2_info;
3253     }
3254     else{
3255         num = MAX_SPRITE_NUM;
3256         si = sprite_info;
3257     }
3258 
3259     if ( no == -1 )
3260         for ( int i=0 ; i<num ; i++ ){
3261             if ( si[i].visible ){
3262                 if (csp2_flag)
3263                     dirty_rect.add( si[i].bounding_rect );
3264                 else
3265                     dirty_rect.add( si[i].pos );
3266             }
3267             if ( si[i].image_name ){
3268                 si[i].orig_pos.x = -1000;
3269                 si[i].orig_pos.y = -1000;
3270                 si[i].scalePosXY( screen_ratio1, screen_ratio2 );
3271             }
3272             if (!csp2_flag) root_button_link.removeSprite(i);
3273             si[i].remove();
3274         }
3275     else if (no >= 0 && no < MAX_SPRITE_NUM){
3276         if ( si[no].visible ){
3277             if (csp2_flag)
3278                 dirty_rect.add( si[no].bounding_rect );
3279             else
3280                 dirty_rect.add( si[no].pos );
3281         }
3282         if (!csp2_flag) root_button_link.removeSprite(no);
3283         si[no].remove();
3284     }
3285 
3286     return RET_CONTINUE;
3287 }
3288 
cselgotoCommand()3289 int ONScripter::cselgotoCommand()
3290 {
3291     int csel_no = script_h.readInt();
3292 
3293     int counter = 0;
3294     SelectLink *link = root_select_link.next;
3295     while( link ){
3296         if ( csel_no == counter++ ) break;
3297         link = link->next;
3298     }
3299     if ( !link ) errorAndExit( "cselgoto: no select link" );
3300 
3301     setCurrentLabel( link->label );
3302 
3303     deleteSelectLink();
3304     newPage();
3305 
3306     return RET_CONTINUE;
3307 }
3308 
cselbtnCommand()3309 int ONScripter::cselbtnCommand()
3310 {
3311     int csel_no   = script_h.readInt();
3312     int button_no = script_h.readInt();
3313 
3314     FontInfo csel_info = sentence_font;
3315     csel_info.rubyon_flag = false;
3316     csel_info.top_xy[0] = script_h.readInt();
3317     csel_info.top_xy[1] = script_h.readInt();
3318 
3319     int counter = 0;
3320     SelectLink *link = root_select_link.next;
3321     while ( link ){
3322         if ( csel_no == counter++ ) break;
3323         link = link->next;
3324     }
3325     if ( link == NULL || link->text == NULL || *link->text == '\0' )
3326         return RET_CONTINUE;
3327 
3328     openFont(&csel_info);
3329     csel_info.setLineArea(link->text);
3330     csel_info.clear();
3331     ButtonLink *button = getSelectableSentence( link->text, &csel_info );
3332     root_button_link.insert( button );
3333     button->no          = button_no;
3334     button->sprite_no   = csel_no;
3335 
3336     sentence_font.ttf_font[0] = csel_info.ttf_font[0];
3337     sentence_font.ttf_font[1] = csel_info.ttf_font[1];
3338 
3339     return RET_CONTINUE;
3340 }
3341 
clickCommand()3342 int ONScripter::clickCommand()
3343 {
3344     bool lrclick_flag = false;
3345     if ( script_h.isName( "lrclick" ) ) lrclick_flag = true;
3346 
3347     skip_mode &= ~SKIP_NORMAL;
3348 
3349     event_mode = WAIT_TIMER_MODE | WAIT_INPUT_MODE;
3350     if (lrclick_flag) event_mode |= WAIT_RCLICK_MODE;
3351     waitEvent(-1);
3352 
3353     if (lrclick_flag)
3354         getret_int = (current_button_state.button == -1)?0:1;
3355 
3356     return RET_CONTINUE;
3357 }
3358 
clCommand()3359 int ONScripter::clCommand()
3360 {
3361     leaveTextDisplayMode();
3362 
3363     char loc = script_h.readLabel()[0];
3364 
3365     if ( loc == 'l' || loc == 'a' ){
3366         dirty_rect.add( tachi_info[0].pos );
3367         tachi_info[0].remove();
3368     }
3369     if ( loc == 'c' || loc == 'a' ){
3370         dirty_rect.add( tachi_info[1].pos );
3371         tachi_info[1].remove();
3372     }
3373     if ( loc == 'r' || loc == 'a' ){
3374         dirty_rect.add( tachi_info[2].pos );
3375         tachi_info[2].remove();
3376     }
3377 
3378     EffectLink *el = parseEffect(true);
3379     if (setEffect(el)) return RET_CONTINUE;
3380     while (doEffect(el));
3381 
3382     return RET_CONTINUE;
3383 }
3384 
chvolCommand()3385 int ONScripter::chvolCommand()
3386 {
3387     int ch  = script_h.readInt();
3388     if      (ch < 0) ch = 0;
3389     else if (ch >= ONS_MIX_CHANNELS) ch = ONS_MIX_CHANNELS-1;
3390 
3391     int vol = script_h.readInt();
3392     if ( wave_sample[ch] ) Mix_Volume( ch, vol * MIX_MAX_VOLUME / 100 );
3393 
3394     return RET_CONTINUE;
3395 }
3396 
checkpageCommand()3397 int ONScripter::checkpageCommand()
3398 {
3399     script_h.readVariable();
3400     script_h.pushVariable();
3401 
3402     if ( script_h.pushed_variable.type != ScriptHandler::VAR_INT &&
3403          script_h.pushed_variable.type != ScriptHandler::VAR_ARRAY )
3404         errorAndExit( "checkpage: no integer variable." );
3405 
3406     int page_no = script_h.readInt();
3407 
3408     Page *page = current_page;
3409     while(page != start_page && page_no > 0){
3410         page_no--;
3411         page = page->previous;
3412     }
3413 
3414     if (page_no > 0)
3415         script_h.setInt( &script_h.pushed_variable, 0 );
3416     else
3417         script_h.setInt( &script_h.pushed_variable, 1 );
3418 
3419     return RET_CONTINUE;
3420 }
3421 
checkkeyCommand()3422 int ONScripter::checkkeyCommand()
3423 {
3424     script_h.readVariable();
3425     script_h.pushVariable();
3426     const char *str = script_h.readStr();
3427 
3428     if (strcmp(current_button_state.str, str) == 0)
3429         script_h.setInt( &script_h.pushed_variable, 1 );
3430     else
3431         script_h.setInt( &script_h.pushed_variable, 0 );
3432 
3433     return RET_CONTINUE;
3434 }
3435 
cellCommand()3436 int ONScripter::cellCommand()
3437 {
3438     int sprite_no = script_h.readInt();
3439     int no        = script_h.readInt();
3440 
3441     sprite_info[sprite_no].setCell(no);
3442     dirty_rect.add( sprite_info[sprite_no].pos );
3443 
3444     return RET_CONTINUE;
3445 }
3446 
captionCommand()3447 int ONScripter::captionCommand()
3448 {
3449     const char* buf = script_h.readStr();
3450     size_t len = strlen(buf);
3451 
3452     char *buf2 = new char[len*3+1];
3453 #if defined(MACOSX) && (SDL_COMPILEDVERSION >= 1208) /* convert sjis to utf-8 */
3454     DirectReader::convertFromSJISToUTF8(buf2, buf);
3455 #elif defined(LINUX) || (defined(WIN32) && defined(UTF8_CAPTION))
3456 #if defined(UTF8_CAPTION)
3457     if (script_h.enc.getEncoding() == Encoding::CODE_UTF8)
3458         strcpy(buf2, buf);
3459     else
3460         DirectReader::convertFromSJISToUTF8(buf2, buf);
3461 #else
3462     if (script_h.enc.getEncoding() == Encoding::CODE_UTF8){
3463         int c = 0;
3464         while(buf[0] != 0){
3465             int n = script_h.enc.getBytes(buf[0]);
3466             unsigned short unicode = script_h.enc.getUTF16(buf);
3467             if (n == 1){
3468                 buf2[c++] = unicode;
3469             }
3470             else{
3471                 unsigned short sjis = convUTF162SJIS(unicode);
3472                 buf2[c++] = sjis >> 8;
3473                 buf2[c++] = sjis & 0xff;
3474             }
3475             buf += n;
3476         }
3477         buf2[c] = 0;
3478     }
3479     else{
3480         strcpy(buf2, buf);
3481     }
3482     DirectReader::convertFromSJISToEUC(buf2);
3483 #endif
3484 #else
3485     strcpy(buf2, buf);
3486 #endif
3487 
3488     setStr( &wm_title_string, buf2 );
3489     setStr( &wm_icon_string,  buf2 );
3490     delete[] buf2;
3491 
3492     SDL_WM_SetCaption( wm_title_string, wm_icon_string );
3493 
3494     return RET_CONTINUE;
3495 }
3496 
btnwaitCommand()3497 int ONScripter::btnwaitCommand()
3498 {
3499     bool del_flag=false, textbtn_flag=false;
3500     bool bexec_int_flag=false;
3501     bexec_flag = false;
3502 
3503     if ( script_h.isName( "btnwait2" ) ){
3504         leaveTextDisplayMode();
3505     }
3506     else if ( script_h.isName( "btnwait" ) ){
3507         del_flag = true;
3508         leaveTextDisplayMode();
3509     }
3510     else if ( script_h.isName( "textbtnwait" ) ){
3511         textbtn_flag = true;
3512     }
3513     else if ( script_h.isName( "bexec" ) ){
3514         bexec_flag = true;
3515     }
3516 
3517     if (bexec_flag){
3518         script_h.readStr();
3519         script_h.pushVariable();
3520         if ( script_h.getEndStatus() & ScriptHandler::END_COMMA ){
3521             bexec_int_flag = true;
3522             script_h.readInt();
3523         }
3524         getpageup_flag = true;
3525         getpagedown_flag = true;
3526         getmclick_flag = true;
3527         getfunction_flag = true;
3528     }
3529     else{
3530         script_h.readInt();
3531     }
3532 
3533     ButtonLink *bl = root_button_link.next;
3534     while( bl ){
3535         bl->show_flag = 0;
3536         if ( bl->button_type == ButtonLink::SPRITE_BUTTON ){
3537             if ( bl->exbtn_ctl[0] ){
3538                 SDL_Rect check_src_rect = bl->image_rect;
3539                 SDL_Rect check_dst_rect = {0, 0, 0, 0};
3540                 decodeExbtnControl( bl->exbtn_ctl[0], &check_src_rect, &check_dst_rect );
3541             }
3542             else{
3543                 sprite_info[ bl->sprite_no ].visible = true;
3544                 sprite_info[ bl->sprite_no ].setCell(0);
3545             }
3546         }
3547         else if ( bl->button_type == ButtonLink::TMP_SPRITE_BUTTON ){
3548             bl->show_flag = 1;
3549             sprite_info[ bl->sprite_no ].visible = true;
3550             sprite_info[ bl->sprite_no ].setCell(0);
3551         }
3552         else if ( bl->anim[1] != NULL ){
3553             bl->show_flag = 2;
3554         }
3555         dirty_rect.add( bl->image_rect );
3556         bl = bl->next;
3557     }
3558 
3559     if (is_exbtn_enabled && exbtn_d_button_link.exbtn_ctl[1]){
3560         SDL_Rect check_src_rect = screen_rect;
3561         if (is_exbtn_enabled) decodeExbtnControl( exbtn_d_button_link.exbtn_ctl[1], &check_src_rect );
3562     }
3563 
3564     if ((textbtn_flag || bexec_flag) &&
3565         (skip_mode & SKIP_NORMAL ||
3566          (skip_mode & SKIP_TO_EOP && (textgosub_clickstr_state & 0x03) == CLICK_WAIT) ||
3567          ctrl_pressed_status) ){
3568         waitEventSub(0); // for checking keyup event
3569         current_button_state.button = 0;
3570         if (bexec_flag) current_button_state.button = -1;
3571         if (skip_mode & SKIP_NORMAL ||
3572             (skip_mode & SKIP_TO_EOP && (textgosub_clickstr_state & 0x03) == CLICK_WAIT))
3573             sprintf(current_button_state.str, "SKIP");
3574         else
3575             sprintf(current_button_state.str, "CTRL");
3576     }
3577     else{
3578         shortcut_mouse_line = 0;
3579         skip_mode &= ~SKIP_NORMAL;
3580 
3581         flush( refreshMode() );
3582 
3583         event_mode = WAIT_BUTTON_MODE;
3584         refreshMouseOverButton();
3585 
3586         int t = -1;
3587         if ( btntime_value >= 0 ){
3588             if ( btntime2_flag )
3589                 event_mode |= WAIT_VOICE_MODE;
3590             t = btntime_value;
3591             //if ( usewheel_flag ) current_button_state.button = -5;
3592             //else                 current_button_state.button = -2;
3593         }
3594         internal_button_timer = SDL_GetTicks();
3595 
3596         if ( textbtn_flag ){
3597             event_mode |= WAIT_INPUT_MODE;
3598             if ( btntime_value == -1 ){
3599                 if ( automode_flag ){
3600                     event_mode |= WAIT_VOICE_MODE;
3601                     if ( automode_time < 0 ){
3602                         if (t == -1 || t > -automode_time * num_chars_in_sentence)
3603                             t = -automode_time * num_chars_in_sentence;
3604                     }
3605                     else{
3606                         if (t == -1 || t > automode_time)
3607                             t = automode_time;
3608                     }
3609                     //current_button_state.button = 0;
3610                 }
3611                 else if (autoclick_time > 0 &&
3612                          (t == -1 || t > autoclick_time))
3613                     t = autoclick_time;
3614             }
3615         }
3616 
3617         event_mode |= WAIT_TIMER_MODE;
3618         waitEvent(t);
3619         skip_mode &= ~SKIP_TO_EOL;
3620     }
3621 
3622     btnwait_time = SDL_GetTicks() - internal_button_timer;
3623     num_chars_in_sentence = 0;
3624 
3625     if (bexec_flag){
3626         setStr( &script_h.getVariableData(script_h.pushed_variable.var_no).str, current_button_state.str );
3627         if (bexec_int_flag){
3628             if (current_button_state.button >= 0)
3629                 script_h.setInt( &script_h.current_variable, current_button_state.button );
3630             else
3631                 script_h.setInt( &script_h.current_variable, -1);
3632         }
3633     }
3634     else{
3635         script_h.setInt( &script_h.current_variable, current_button_state.button );
3636     }
3637 
3638     if ( current_button_state.button >= 1 && del_flag ){
3639         deleteButtonLink();
3640     }
3641 
3642     event_mode = IDLE_EVENT_MODE;
3643     disableGetButtonFlag();
3644 
3645     bl = root_button_link.next;
3646     while( bl ){
3647         bl->show_flag = 0;
3648         bl = bl->next;
3649     }
3650 
3651     return RET_CONTINUE;
3652 }
3653 
btntimeCommand()3654 int ONScripter::btntimeCommand()
3655 {
3656     bool btime_flag = false;
3657     if ( script_h.isName( "btime" )){
3658         btime_flag = true;
3659         btntime2_flag = false;
3660     }
3661     else if ( script_h.isName( "btntime2" ) )
3662         btntime2_flag = true;
3663     else
3664         btntime2_flag = false;
3665 
3666     btntime_value = script_h.readInt();
3667 
3668     if ( btime_flag && script_h.getEndStatus() & ScriptHandler::END_COMMA )
3669         if (script_h.readInt() == 1) btntime2_flag = true;
3670 
3671     return RET_CONTINUE;
3672 }
3673 
btndownCommand()3674 int ONScripter::btndownCommand()
3675 {
3676     btndown_flag = (script_h.readInt()==1)?true:false;
3677 
3678     return RET_CONTINUE;
3679 }
3680 
btndefCommand()3681 int ONScripter::btndefCommand()
3682 {
3683     if (script_h.isName( "bclear" )){
3684     }
3685     else if (script_h.compareString("clear")){
3686         script_h.readLabel();
3687     }
3688     else{
3689         const char *buf = script_h.readStr();
3690 
3691         btndef_info.remove();
3692 
3693         if ( buf[0] != '\0' ){
3694             btndef_info.setImageName( buf );
3695             parseTaggedString( &btndef_info );
3696             btndef_info.trans_mode = AnimationInfo::TRANS_COPY;
3697             setupAnimationInfo( &btndef_info );
3698             SDL_SetAlpha( btndef_info.image_surface, DEFAULT_BLIT_FLAG, SDL_ALPHA_OPAQUE );
3699         }
3700     }
3701 
3702     btntime_value = -1;
3703     transbtn_flag = false;
3704     deleteButtonLink();
3705 
3706     disableGetButtonFlag();
3707 
3708     return RET_CONTINUE;
3709 }
3710 
btnCommand()3711 int ONScripter::btnCommand()
3712 {
3713     SDL_Rect src_rect;
3714 
3715     ButtonLink *button = new ButtonLink();
3716 
3717     button->no           = script_h.readInt();
3718     button->image_rect.x = script_h.readInt() * screen_ratio1 / screen_ratio2;
3719     button->image_rect.y = script_h.readInt() * screen_ratio1 / screen_ratio2;
3720     button->image_rect.w = script_h.readInt() * screen_ratio1 / screen_ratio2;
3721     button->image_rect.h = script_h.readInt() * screen_ratio1 / screen_ratio2;
3722     button->select_rect = button->image_rect;
3723 
3724     src_rect.x = script_h.readInt() * screen_ratio1 / screen_ratio2;
3725     src_rect.y = script_h.readInt() * screen_ratio1 / screen_ratio2;
3726     if (btndef_info.image_surface &&
3727         src_rect.x + button->image_rect.w > btndef_info.image_surface->w){
3728         button->image_rect.w = btndef_info.image_surface->w - src_rect.x;
3729     }
3730     if (btndef_info.image_surface &&
3731         src_rect.y + button->image_rect.h > btndef_info.image_surface->h){
3732         button->image_rect.h = btndef_info.image_surface->h - src_rect.y;
3733     }
3734     src_rect.w = button->image_rect.w;
3735     src_rect.h = button->image_rect.h;
3736 
3737     AnimationInfo *ai = button->anim[0] = new AnimationInfo();
3738     ai->num_of_cells = 1;
3739     ai->trans_mode = AnimationInfo::TRANS_COPY;
3740     ai->pos.x = button->image_rect.x;
3741     ai->pos.y = button->image_rect.y;
3742     ai->allocImage( button->image_rect.w, button->image_rect.h, texture_format );
3743     ai->fill( 0, 0, 0, 0 );
3744     ai->copySurface( btndef_info.image_surface, &src_rect );
3745 
3746     root_button_link.insert( button );
3747 
3748     return RET_CONTINUE;
3749 }
3750 
bspCommand()3751 int ONScripter::bspCommand()
3752 {
3753     int no = script_h.readInt();
3754     if (no < 0 || no >= MAX_SPRITE_NUM ||
3755         sprite_info[no].image_surface == NULL){
3756         for (int i=0 ; i<3 ; i++)
3757             if ( script_h.getEndStatus() & ScriptHandler::END_COMMA )
3758                 script_h.readStr();
3759         return RET_CONTINUE;
3760     }
3761 
3762     ButtonLink *bl = new ButtonLink();
3763     root_button_link.insert( bl );
3764 
3765     bl->button_type = ButtonLink::SPRITE_BUTTON;
3766     bl->sprite_no   = no;
3767     bl->no          = no;
3768 
3769     if ( sprite_info[no].image_surface ||
3770          sprite_info[no].trans_mode == AnimationInfo::TRANS_STRING )
3771         bl->image_rect = bl->select_rect = sprite_info[no].pos;
3772 
3773     for (int i=0 ; i<3 ; i++)
3774         if ( script_h.getEndStatus() & ScriptHandler::END_COMMA )
3775             setStr( &bl->exbtn_ctl[i], script_h.readStr() );
3776 
3777     return RET_CONTINUE;
3778 }
3779 
brCommand()3780 int ONScripter::brCommand()
3781 {
3782     enterTextDisplayMode();
3783 
3784     sentence_font.newLine();
3785     current_page->add( 0x0a );
3786 
3787     return RET_CONTINUE;
3788 }
3789 
bltCommand()3790 int ONScripter::bltCommand()
3791 {
3792     Sint16 dx,dy,sx,sy;
3793     Sint16 dw,dh,sw,sh;
3794 
3795     dx = script_h.readInt() * screen_ratio1 / screen_ratio2;
3796     dy = script_h.readInt() * screen_ratio1 / screen_ratio2;
3797     dw = script_h.readInt() * screen_ratio1 / screen_ratio2;
3798     dh = script_h.readInt() * screen_ratio1 / screen_ratio2;
3799     sx = script_h.readInt() * screen_ratio1 / screen_ratio2;
3800     sy = script_h.readInt() * screen_ratio1 / screen_ratio2;
3801     sw = script_h.readInt() * screen_ratio1 / screen_ratio2;
3802     sh = script_h.readInt() * screen_ratio1 / screen_ratio2;
3803 
3804     if (btndef_info.image_surface == NULL) return RET_CONTINUE;
3805     if (dw == 0 || dh == 0 || sw == 0 || sh == 0) return RET_CONTINUE;
3806 
3807     if ( sw == dw && sw > 0 && sh == dh && sh > 0 ){
3808 
3809         SDL_Rect src_rect = {sx,sy,(Uint16)sw,(Uint16)sh};
3810         SDL_Rect dst_rect = {dx,dy,(Uint16)dw,(Uint16)dh};
3811 
3812 #ifdef USE_SDL_RENDERER
3813         dst_rect.x = dst_rect.x * screen_device_width / screen_width + (device_width -screen_device_width )/2;
3814         dst_rect.y = dst_rect.y * screen_device_width / screen_width + (device_height-screen_device_height)/2;
3815         dst_rect.w = dst_rect.w * screen_device_width / screen_width;
3816         dst_rect.h = dst_rect.h * screen_device_width / screen_width;
3817         SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, btndef_info.image_surface);
3818         SDL_RenderCopy(renderer, texture, &src_rect, &dst_rect);
3819         SDL_RenderPresent(renderer);
3820         SDL_DestroyTexture(texture);
3821 #else
3822         SDL_BlitSurface( btndef_info.image_surface, &src_rect, screen_surface, &dst_rect );
3823         SDL_UpdateRect( screen_surface, dst_rect.x, dst_rect.y, dst_rect.w, dst_rect.h );
3824 #endif
3825         dirty_rect.clear();
3826     }
3827     else{
3828         SDL_LockSurface(accumulation_surface);
3829         SDL_LockSurface(btndef_info.image_surface);
3830         ONSBuf *dst_buf = (ONSBuf*)accumulation_surface->pixels;
3831         ONSBuf *src_buf = (ONSBuf*)btndef_info.image_surface->pixels;
3832 #if defined(BPP16)
3833         int dst_width = accumulation_surface->pitch / 2;
3834         int src_width = btndef_info.image_surface->pitch / 2;
3835 #else
3836         int dst_width = accumulation_surface->pitch / 4;
3837         int src_width = btndef_info.image_surface->pitch / 4;
3838 #endif
3839 
3840         int step_y = 1;
3841         if (dh < 0) step_y = -1;
3842 
3843         int step_x = 1;
3844         if (dw < 0) step_x = -1;
3845 
3846         dst_buf += dst_width*dy;
3847         for (int i=dy ; i!=dy+dh ; i+=step_y){
3848             if (i < 0 || i >= screen_height) continue;
3849             int y = sy+sh*(i-dy)/dh;
3850 
3851             for (int j=dx ; j!=dx+dw ; j+=step_x){
3852                 if (j < 0 || j >= screen_width) continue;
3853                 int x = sx+sw*(j-dx)/dw;
3854 
3855                 if (x<0 || x>=btndef_info.image_surface->w ||
3856                     y<0 || y>=btndef_info.image_surface->h)
3857                     *(dst_buf+j) = 0;
3858                 else
3859                     *(dst_buf+j) = *(src_buf+y*src_width+x);
3860             }
3861             dst_buf += dst_width*step_y;
3862         }
3863         SDL_UnlockSurface(btndef_info.image_surface);
3864         SDL_UnlockSurface(accumulation_surface);
3865 
3866         SDL_Rect dst_rect;
3867         if (dw >= 0){
3868             dst_rect.x = dx;
3869             dst_rect.w = dw;
3870         }
3871         else{
3872             dst_rect.x = dx+dw+1;
3873             dst_rect.w = -dw;
3874         }
3875         if (dh >= 0){
3876             dst_rect.y = dy;
3877             dst_rect.h = dh;
3878         }
3879         else{
3880             dst_rect.y = dy+dh+1;
3881             dst_rect.h = -dh;
3882         }
3883 
3884         flushDirect( dst_rect, REFRESH_NONE_MODE );
3885     }
3886 
3887     return RET_CONTINUE;
3888 }
3889 
bgcopyCommand()3890 int ONScripter::bgcopyCommand()
3891 {
3892     ofscopyCommand();
3893 
3894     setStr( &bg_info.file_name, "*bgcpy" );
3895     bg_info.num_of_cells = 1;
3896     bg_info.trans_mode = AnimationInfo::TRANS_COPY;
3897     bg_info.pos.x = 0;
3898     bg_info.pos.y = 0;
3899     bg_info.copySurface( accumulation_surface, NULL );
3900 
3901     return RET_CONTINUE;
3902 }
3903 
bgCommand()3904 int ONScripter::bgCommand()
3905 {
3906     leaveTextDisplayMode();
3907 
3908     const char *buf;
3909     if (script_h.compareString("white")){
3910         buf = "white";
3911         script_h.readLabel();
3912     }
3913     else if (script_h.compareString("black")){
3914         buf = "black";
3915         script_h.readLabel();
3916     }
3917     else{
3918         buf = script_h.readStr();
3919     }
3920 
3921     for ( int i=0 ; i<3 ; i++ )
3922         tachi_info[i].remove();
3923 
3924     bg_info.remove();
3925     setStr( &bg_info.file_name, buf );
3926 
3927     createBackground();
3928     dirty_rect.fill( screen_width, screen_height );
3929 
3930     EffectLink *el = parseEffect(true);
3931     if (setEffect(el)) return RET_CONTINUE;
3932     while (doEffect(el));
3933 
3934     return RET_CONTINUE;
3935 }
3936 
bdownCommand()3937 int ONScripter::bdownCommand()
3938 {
3939     btndown_flag = true;
3940 
3941     return RET_CONTINUE;
3942 }
3943 
barclearCommand()3944 int ONScripter::barclearCommand()
3945 {
3946     for ( int i=0 ; i<MAX_PARAM_NUM ; i++ ) {
3947         if ( bar_info[i] ) {
3948             dirty_rect.add( bar_info[i]->pos );
3949             delete bar_info[i];
3950             bar_info[i] = NULL;
3951         }
3952     }
3953     return RET_CONTINUE;
3954 }
3955 
barCommand()3956 int ONScripter::barCommand()
3957 {
3958     int no = script_h.readInt();
3959     AnimationInfo *ai = bar_info[no];
3960 
3961     if ( ai ){
3962         dirty_rect.add( ai->pos );
3963         ai->remove();
3964     }
3965     else{
3966         ai = bar_info[no] = new AnimationInfo();
3967     }
3968 
3969     ai->trans_mode = AnimationInfo::TRANS_COPY;
3970     ai->num_of_cells = 1;
3971     ai->setCell(0);
3972 
3973     ai->param      = script_h.readInt();
3974     ai->orig_pos.x = script_h.readInt();
3975     ai->orig_pos.y = script_h.readInt();
3976     ai->max_width  = script_h.readInt();
3977     ai->orig_pos.w = 0;
3978     ai->orig_pos.h = script_h.readInt();
3979     ai->max_param  = script_h.readInt();
3980 
3981     ai->scalePosXY( screen_ratio1, screen_ratio2 );
3982 
3983     const char *buf = script_h.readStr();
3984     readColor( &ai->color, buf );
3985 
3986     int w = 0;
3987     if (ai->max_param != 0) w = ai->max_width * ai->param / ai->max_param;
3988     if (ai->max_width > 0 && w > 0) ai->orig_pos.w = w;
3989 
3990     ai->scalePosWH( screen_ratio1, screen_ratio2 );
3991     ai->allocImage( ai->pos.w, ai->pos.h, texture_format );
3992     ai->fill( ai->color[0], ai->color[1], ai->color[2], 0xff );
3993     dirty_rect.add( ai->pos );
3994 
3995     return RET_CONTINUE;
3996 }
3997 
aviCommand()3998 int ONScripter::aviCommand()
3999 {
4000     script_h.readStr();
4001     const char *save_buf = script_h.saveStringBuffer();
4002 
4003     bool click_flag = (script_h.readInt()==1)?true:false;
4004 
4005     stopBGM( false );
4006     if (playAVI( save_buf, click_flag )) endCommand();
4007 
4008     // should be commented out
4009     //repaintCommand();
4010 
4011     return RET_CONTINUE;
4012 }
4013 
automode_timeCommand()4014 int ONScripter::automode_timeCommand()
4015 {
4016     automode_time = script_h.readInt();
4017 
4018     return RET_CONTINUE;
4019 }
4020 
autoclickCommand()4021 int ONScripter::autoclickCommand()
4022 {
4023     autoclick_time = script_h.readInt();
4024 
4025     return RET_CONTINUE;
4026 }
4027 
amspCommand()4028 int ONScripter::amspCommand()
4029 {
4030     leaveTextDisplayMode();
4031 
4032     bool amsp2_flag = false;
4033     if (script_h.isName("amsp2")) amsp2_flag = true;
4034 
4035     int no = script_h.readInt();
4036     AnimationInfo *ai = NULL;
4037     if (amsp2_flag){
4038         ai = &sprite2_info[no];
4039         dirty_rect.add( ai->bounding_rect );
4040     }
4041     else{
4042         ai = &sprite_info[no];
4043         dirty_rect.add( ai->pos );
4044     }
4045 
4046     ai->orig_pos.x = script_h.readInt();
4047     ai->orig_pos.y = script_h.readInt();
4048     ai->scalePosXY( screen_ratio1, screen_ratio2 );
4049     if (amsp2_flag){
4050         ai->scale_x = script_h.readInt();
4051         ai->scale_y = script_h.readInt();
4052         ai->rot     = script_h.readInt();
4053         ai->calcAffineMatrix();
4054         dirty_rect.add( ai->bounding_rect );
4055     }
4056     else{
4057         dirty_rect.add( ai->pos );
4058     }
4059 
4060     if ( script_h.getEndStatus() & ScriptHandler::END_COMMA ){
4061         ai->trans = script_h.readInt();
4062         if      (ai->trans <   0) ai->trans = 0;
4063         else if (ai->trans > 255) ai->trans = 255;
4064     }
4065 
4066     return RET_CONTINUE;
4067 }
4068 
allsp2resumeCommand()4069 int ONScripter::allsp2resumeCommand()
4070 {
4071     all_sprite2_hide_flag = false;
4072 
4073     for ( int i=0 ; i<MAX_SPRITE2_NUM ; i++ ){
4074         AnimationInfo &ai = sprite2_info[i];
4075         if (ai.image_surface && ai.visible)
4076             dirty_rect.add( ai.bounding_rect );
4077     }
4078     return RET_CONTINUE;
4079 }
4080 
allspresumeCommand()4081 int ONScripter::allspresumeCommand()
4082 {
4083     all_sprite_hide_flag = false;
4084 
4085     for ( int i=0 ; i<3 ; i++ ){
4086         AnimationInfo &ai = tachi_info[i];
4087         if (ai.image_surface && ai.visible)
4088             dirty_rect.add( ai.pos );
4089     }
4090 
4091     for ( int i=0 ; i<MAX_SPRITE_NUM ; i++ ){
4092         AnimationInfo &ai = sprite_info[i];
4093         if (ai.image_surface && ai.visible)
4094             dirty_rect.add( ai.pos );
4095     }
4096 
4097     return RET_CONTINUE;
4098 }
4099 
allsp2hideCommand()4100 int ONScripter::allsp2hideCommand()
4101 {
4102     all_sprite2_hide_flag = true;
4103 
4104     for ( int i=0 ; i<MAX_SPRITE2_NUM ; i++ ){
4105         AnimationInfo *ai = &sprite2_info[i];
4106         if (ai->image_surface && ai->visible)
4107             dirty_rect.add( ai->bounding_rect );
4108     }
4109     return RET_CONTINUE;
4110 }
4111 
allsphideCommand()4112 int ONScripter::allsphideCommand()
4113 {
4114     all_sprite_hide_flag = true;
4115 
4116     for ( int i=0 ; i<3 ; i++ ){
4117         AnimationInfo &ai = tachi_info[i];
4118         if (ai.image_surface && ai.visible)
4119             dirty_rect.add( ai.pos );
4120     }
4121 
4122     for ( int i=0 ; i<MAX_SPRITE_NUM ; i++ ){
4123         AnimationInfo &ai = sprite_info[i];
4124         if (ai.image_surface && ai.visible)
4125             dirty_rect.add( ai.pos );
4126     }
4127 
4128     return RET_CONTINUE;
4129 }
4130 
NSDCallCommand(int texnum,const char * str1,int proc,const char * str2)4131 void ONScripter::NSDCallCommand(int texnum, const char *str1, int proc, const char *str2)
4132 {
4133     if (texnum < 0 || texnum >= MAX_TEXTURE_NUM) return;
4134 
4135     NSDLoadCommand(texnum, str1);
4136 
4137     if (proc == 1){ // deffontd.dll, Font
4138         FontInfo f_info = sentence_font;
4139         f_info.rubyon_flag = false;
4140         f_info.setTateyokoMode(0);
4141         f_info.top_xy[0] = f_info.top_xy[1] = 0;
4142         f_info.clear();
4143 
4144         f_info.ttf_font[0] = NULL;
4145         f_info.ttf_font[1] = NULL;
4146 
4147         RubyStruct rs_old = ruby_struct;
4148         ruby_struct.font_name = NULL;
4149 
4150         const char *start[8];
4151         start[0] = str2;
4152         int i=0, num_param=1;
4153         while(str2[i] && num_param<8) if (str2[i++]==',') start[num_param++] = str2+i;
4154         switch(num_param){
4155           case 8: case 7:
4156             for (i=0 ; i<2 ; i++){
4157                 int j=0;
4158                 ruby_struct.font_size_xy[i] = 0;
4159                 while(start[4+i][j]>='0' && start[4+i][j]<='9')
4160                     ruby_struct.font_size_xy[i] = ruby_struct.font_size_xy[i]*10 + start[4+i][j++] - '0';
4161             }
4162           case 5:
4163             i=0;
4164             while(start[3][i] != ',' && start[3][i] != 0){
4165                 if (start[3][i++] == 'r'){
4166                     f_info.rubyon_flag = true;
4167                     break;
4168                 }
4169             }
4170           case 4: case 3:
4171             for (i=0 ; i<2 ; i++){
4172                 int j=0;
4173                 f_info.font_size_xy[i] = 0;
4174                 while(start[i][j]>='0' && start[i][j]<='9')
4175                     f_info.font_size_xy[i] = f_info.font_size_xy[i]*10 + start[i][j++] - '0';
4176             }
4177             f_info.font_size_xy[0] *= 2;
4178             f_info.pitch_xy[0] = f_info.font_size_xy[0];
4179             f_info.pitch_xy[1] = f_info.font_size_xy[1];
4180         }
4181         uchar3 color = {0xff, 0xff, 0xff};
4182         char *p = (char*)start[num_param-1], *p2 = (char*)start[num_param-1];
4183         while(*p){
4184             int n = script_h.enc.getBytes(*p);
4185             if (n >= 2){
4186                 for (int i=0; i<n; i++)
4187                     *p2++ = *p++;
4188             }
4189             else if (*p == '%'){
4190                 p++;
4191                 if (*p == '%' || *p == '(' || *p == ')') // fix me later
4192                     *p2++ = *p++;
4193                 else if (*p == '#'){
4194                     readColor( &color, p );
4195                     p += 7;
4196                 }
4197             }
4198             else{
4199                 *p2++ = *p++;
4200             }
4201         }
4202         *p2 = 0;
4203 
4204         drawString(start[num_param-1], color, &f_info, false, NULL, NULL, &texture_info[texnum], false);
4205 
4206         ruby_struct = rs_old;
4207     }
4208 }
4209 
NSDDeleteCommand(int texnum)4210 void ONScripter::NSDDeleteCommand(int texnum)
4211 {
4212     if (texnum < 0 || texnum >= MAX_TEXTURE_NUM) return;
4213 
4214     texture_info[texnum].remove();
4215 }
4216 
NSDLoadCommand(int texnum,const char * str)4217 void ONScripter::NSDLoadCommand(int texnum, const char *str)
4218 {
4219     if (texnum < 0 || texnum >= MAX_TEXTURE_NUM) return;
4220 
4221     AnimationInfo *ai = &texture_info[texnum];
4222     if (str[0] != '*'){
4223         ai->setImageName( str );
4224         ai->trans = -1;
4225     }
4226     else{
4227         int c=1, n=0, val[6]={0}; // val[6] = {width, height, R, G, B, alpha}
4228 
4229         while(str[c] != 0 && n<6){
4230             if (str[c] >= '0' && str[c] <= '9')
4231                 val[n] = val[n]*10 + str[c] - '0';
4232             if (str[c] == ',') n++;
4233             c++;
4234         }
4235 
4236         char buf[32];
4237         sprintf(buf, ">%d,%d,#%02x%02x%02x", val[0], val[1], val[2], val[3], val[4]);
4238         ai->setImageName( buf );
4239         ai->default_alpha = val[5];
4240     }
4241 
4242     ai->visible = true;
4243     parseTaggedString( ai );
4244     ai->trans_mode = AnimationInfo::TRANS_ALPHA;
4245     setupAnimationInfo( ai );
4246 }
4247 
NSDPresentRectCommand(int x1,int y1,int x2,int y2)4248 void ONScripter::NSDPresentRectCommand(int x1, int y1, int x2, int y2)
4249 {
4250     SDL_Rect clip_src;
4251     clip_src.x = x1;
4252     clip_src.y = y1;
4253     clip_src.w = x2-x1+1;
4254     clip_src.h = y2-y1+1;
4255 
4256     SDL_Rect clip;
4257     clip.x = clip.y = 0;
4258     clip.w = accumulation_surface->w;
4259     clip.h = accumulation_surface->h;
4260     if ( AnimationInfo::doClipping( &clip, &clip_src ) ) return;
4261 
4262     for (int i=MAX_TEXTURE_NUM-1 ; i>0 ; i--)
4263         if (texture_info[i].image_surface && texture_info[i].visible)
4264             drawTaggedSurface( accumulation_surface, &texture_info[i], clip );
4265 
4266     flushDirect(clip, REFRESH_NONE_MODE);
4267 }
4268 
NSDSp2Command(int texnum,int dcx,int dcy,int sx,int sy,int w,int h,int xs,int ys,int rot,int alpha)4269 void ONScripter::NSDSp2Command(int texnum, int dcx, int dcy, int sx, int sy, int w, int h,
4270                                int xs, int ys, int rot, int alpha)
4271 {
4272     if (texnum < 0 || texnum >= MAX_TEXTURE_NUM) return;
4273 
4274     AnimationInfo *ai = &texture_info[texnum];
4275     ai->orig_pos.x = dcx;
4276     ai->orig_pos.y = dcy;
4277     ai->scalePosXY( screen_ratio1, screen_ratio2 );
4278     ai->scale_x = xs;
4279     ai->scale_y = ys;
4280     ai->rot     = rot;
4281     ai->trans = alpha;
4282 
4283     ai->affine_pos.x = sx*screen_ratio1/screen_ratio2;
4284     ai->affine_pos.y = sy*screen_ratio1/screen_ratio2;
4285     ai->affine_pos.w =  w*screen_ratio1/screen_ratio2;
4286     ai->affine_pos.h =  h*screen_ratio1/screen_ratio2;
4287     ai->calcAffineMatrix();
4288     ai->affine_flag = true;
4289 }
4290 
NSDSetSpriteCommand(int spnum,int texnum,const char * tag)4291 void ONScripter::NSDSetSpriteCommand(int spnum, int texnum, const char *tag)
4292 {
4293     if (spnum < 0 || spnum >= MAX_SPRITE_NUM) return;
4294     if (texnum < 0 || texnum >= MAX_TEXTURE_NUM) return;
4295 
4296     AnimationInfo *ais = &sprite_info[spnum];
4297     AnimationInfo *ait = &texture_info[texnum];
4298     *ais = *ait;
4299     ais->visible = true;
4300 
4301     char buf[256];
4302     if (tag)
4303         sprintf(buf, "%s%s", tag, ait->file_name);
4304     else
4305         sprintf(buf, ":a;%s", ait->file_name);
4306     ais->setImageName(buf);
4307     parseTaggedString(ais);
4308 
4309     if (ais->affine_flag){
4310         ais->orig_pos.x = ait->orig_pos.x;
4311         if (ait->num_of_cells > 0)
4312             ais->orig_pos.x -= ait->orig_pos.w/ait->num_of_cells/2;
4313         else
4314             ais->orig_pos.x -= ait->orig_pos.w/2;
4315         ais->orig_pos.y = ait->orig_pos.y - ait->orig_pos.h/2;
4316         ais->scalePosXY( screen_ratio1, screen_ratio2 );
4317         ais->affine_flag = false;
4318     }
4319 }
4320 
stopSMPEG()4321 void ONScripter::stopSMPEG()
4322 {
4323 #if defined(USE_SMPEG)
4324     if (layer_smpeg_sample){
4325         SMPEG_stop( layer_smpeg_sample );
4326         SMPEG_delete( layer_smpeg_sample );
4327         layer_smpeg_sample = NULL;
4328     }
4329     if (layer_smpeg_buffer){
4330         delete[] layer_smpeg_buffer;
4331         layer_smpeg_buffer = NULL;
4332     }
4333 #endif
4334 }
4335