1 Star 1 Fork 2

weimingtom/Onscripter-Official

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
ONScripter.cpp 40.64 KB
一键复制 编辑 原始数据 按行查看 历史
只要998 提交于 2020-04-21 07:04 . 20200419
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322
/* -*- C++ -*-
*
* ONScripter.cpp - Execution block parser of ONScripter
*
* Copyright (c) 2001-2020 Ogapee. All rights reserved.
*
* ogapee@aqua.dti2.ne.jp
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ONScripter.h"
#ifdef USE_FONTCONFIG
#include <fontconfig/fontconfig.h>
#endif
extern "C" void waveCallback( int channel );
#define DEFAULT_AUDIOBUF 4096
#define FONT_FILE "default.ttf"
#define REGISTRY_FILE "registry.txt"
#define DLL_FILE "dll.txt"
#define DEFAULT_ENV_FONT "lr SVbN"
#define DEFAULT_AUTOMODE_TIME 1000
void ONScripter::initSDL()
{
/* ---------------------------------------- */
/* Initialize SDL */
if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO ) < 0 ){
fprintf( stderr, "Couldn't initialize SDL: %s\n", SDL_GetError() );
exit(-1);
}
atexit(SDL_Quit);
#ifdef USE_CDROM
if( cdaudio_flag && SDL_InitSubSystem( SDL_INIT_CDROM ) < 0 ){
fprintf( stderr, "Couldn't initialize CD-ROM: %s\n", SDL_GetError() );
exit(-1);
}
#endif
#if !defined(IOS)
if(SDL_InitSubSystem( SDL_INIT_JOYSTICK ) == 0 && SDL_JoystickOpen(0) != NULL)
printf( "Initialize JOYSTICK\n");
#endif
#if defined(PSP) || defined(IPODLINUX) || defined(GP2X) || defined(WINCE)
SDL_ShowCursor(SDL_DISABLE);
#endif
/* ---------------------------------------- */
/* Initialize SDL */
if ( TTF_Init() < 0 ){
fprintf( stderr, "can't initialize SDL TTF\n");
exit(-1);
}
#if defined(BPP16)
screen_bpp = 16;
#else
screen_bpp = 32;
#endif
#if defined(PDA_WIDTH)
screen_ratio1 = PDA_WIDTH;
screen_ratio2 = script_h.screen_width;
screen_width = PDA_WIDTH;
#elif defined(PDA_AUTOSIZE)
SDL_Rect **modes;
modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
if (modes == (SDL_Rect **)0){
fprintf(stderr, "No Video mode available.\n");
exit(-1);
}
else if (modes == (SDL_Rect **)-1){
// no restriction
}
else{
int width;
if (modes[0]->w * screen_height > modes[0]->h * screen_width)
width = (modes[0]->h*screen_width/screen_height) & (~0x01); // to be 2 bytes aligned
else
width = modes[0]->w;
screen_ratio1 = width;
screen_ratio2 = script_h.screen_width;
screen_width = width;
}
#endif
screen_height = screen_width*script_h.screen_height/script_h.screen_width;
screen_device_width = screen_width;
screen_device_height = screen_height;
#if defined(USE_SDL_RENDERER)
// use hardware scaling
screen_ratio1 = 1;
screen_ratio2 = 1;
screen_width = script_h.screen_width;
screen_height = script_h.screen_height;
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
window = SDL_CreateWindow(NULL, 0, 0, screen_device_width, screen_device_height, SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN|SDL_WINDOW_BORDERLESS);
SDL_GetWindowSize(window, &device_width, &device_height);
renderer = SDL_CreateRenderer(window, -1, 0);
texture_format = SDL_PIXELFORMAT_ARGB8888;
SDL_RendererInfo info;
SDL_GetRendererInfo(renderer, &info);
if (info.texture_formats[0] == SDL_PIXELFORMAT_ABGR8888)
texture_format = SDL_PIXELFORMAT_ABGR8888;
SDL_RenderClear(renderer);
#else
#if defined(ANDROID)
// use hardware scaling
screen_ratio1 = 1;
screen_ratio2 = 1;
screen_width = script_h.screen_width;
screen_height = script_h.screen_height;
#endif
screen_surface = SDL_SetVideoMode( screen_width, screen_height, screen_bpp, DEFAULT_VIDEO_SURFACE_FLAG|(fullscreen_mode?SDL_FULLSCREEN:0) );
#ifdef BPP16
texture_format = SDL_PIXELFORMAT_RGB565;
#else
#if defined(ANDROID)
SDL_SetSurfaceBlendMode(screen_surface, SDL_BLENDMODE_NONE);
texture_format = SDL_PIXELFORMAT_ABGR8888;
#else
texture_format = SDL_PIXELFORMAT_ARGB8888;
#endif
#endif
#endif
/* ---------------------------------------- */
/* Check if VGA screen is available. */
#if !defined(USE_SDL_RENDERER) && (PDA_WIDTH==640)
if ( screen_surface == NULL ){
screen_ratio1 /= 2;
screen_width /= 2;
screen_height /= 2;
screen_device_width = screen_width;
screen_device_height = screen_height;
screen_surface = SDL_SetVideoMode( screen_device_width, screen_device_height, screen_bpp, DEFAULT_VIDEO_SURFACE_FLAG|(fullscreen_mode?SDL_FULLSCREEN:0) );
}
#endif
underline_value = script_h.screen_height;
#ifndef USE_SDL_RENDERER
if ( screen_surface == NULL ) {
fprintf( stderr, "Couldn't set %dx%dx%d video mode: %s\n",
screen_width, screen_height, screen_bpp, SDL_GetError() );
exit(-1);
}
#endif
printf("Display: %d x %d (%d bpp)\n", screen_width, screen_height, screen_bpp);
dirty_rect.setDimension(screen_width, screen_height);
screen_rect.x = screen_rect.y = 0;
screen_rect.w = screen_width;
screen_rect.h = screen_height;
wm_title_string = new char[ strlen(DEFAULT_WM_TITLE) + 1 ];
memcpy( wm_title_string, DEFAULT_WM_TITLE, strlen(DEFAULT_WM_TITLE) + 1 );
wm_icon_string = new char[ strlen(DEFAULT_WM_ICON) + 1 ];
memcpy( wm_icon_string, DEFAULT_WM_TITLE, strlen(DEFAULT_WM_ICON) + 1 );
SDL_WM_SetCaption( wm_title_string, wm_icon_string );
}
void ONScripter::openAudio(int freq)
{
Mix_CloseAudio();
#if (defined(PDA_WIDTH) || defined(PDA_AUTOSIZE)) && !defined(PSP) && !defined(IPHONE) && !defined(IOS) && !defined(PANDORA)
if ( Mix_OpenAudio( (freq<0)?22050:freq, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, DEFAULT_AUDIOBUF ) < 0 ){
#else
if ( Mix_OpenAudio( (freq<0)?44100:freq, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, DEFAULT_AUDIOBUF ) < 0 ){
#endif
fprintf(stderr, "Couldn't open audio device!\n"
" reason: [%s].\n", SDL_GetError());
audio_open_flag = false;
}
else{
int freq;
Uint16 format;
int channels;
Mix_QuerySpec( &freq, &format, &channels);
printf("Audio: %d Hz %d bit %s\n", freq,
(format&0xFF),
(channels > 1) ? "stereo" : "mono");
audio_format.format = format;
audio_format.freq = freq;
audio_format.channels = channels;
audio_open_flag = true;
Mix_AllocateChannels( ONS_MIX_CHANNELS+ONS_MIX_EXTRA_CHANNELS );
Mix_ChannelFinished( waveCallback );
}
}
ONScripter::ONScripter()
{
is_script_read = false;
cdrom_drive_number = 0;
cdaudio_flag = false;
default_font = NULL;
registry_file = NULL;
setStr( &registry_file, REGISTRY_FILE );
dll_file = NULL;
setStr( &dll_file, DLL_FILE );
getret_str = NULL;
enable_wheeldown_advance_flag = false;
disable_rescale_flag = false;
edit_flag = false;
key_exe_file = NULL;
fullscreen_mode = false;
window_mode = false;
sprite_info = new AnimationInfo[MAX_SPRITE_NUM];
sprite2_info = new AnimationInfo[MAX_SPRITE2_NUM];
texture_info = new AnimationInfo[MAX_TEXTURE_NUM];
smpeg_info = NULL;
layer_alpha_buf = NULL;
current_button_state.down_flag = false;
int i;
for (i=0 ; i<MAX_SPRITE2_NUM ; i++)
sprite2_info[i].affine_flag = true;
// External Players
#if defined(WINCE)
midi_cmd = NULL;
#else
midi_cmd = getenv("MUSIC_CMD");
#endif
makeFuncLUT();
}
ONScripter::~ONScripter()
{
reset();
delete[] sprite_info;
delete[] sprite2_info;
}
void ONScripter::enableCDAudio(){
cdaudio_flag = true;
}
void ONScripter::setCDNumber(int cdrom_drive_number)
{
this->cdrom_drive_number = cdrom_drive_number;
}
void ONScripter::setFontFile(const char *filename)
{
setStr(&default_font, filename);
}
void ONScripter::setRegistryFile(const char *filename)
{
setStr(&registry_file, filename);
}
void ONScripter::setDLLFile(const char *filename)
{
setStr(&dll_file, filename);
}
void ONScripter::setArchivePath(const char *path)
{
if (archive_path) delete[] archive_path;
archive_path = new char[ RELATIVEPATHLENGTH + strlen(path) + 2 ];
sprintf( archive_path, RELATIVEPATH "%s%c", path, DELIMITER );
}
void ONScripter::setSaveDir(const char *path)
{
if (save_dir) delete[] save_dir;
save_dir = new char[ RELATIVEPATHLENGTH + strlen(path) + 2 ];
sprintf( save_dir, RELATIVEPATH "%s%c", path, DELIMITER );
script_h.setSaveDir(save_dir);
}
void ONScripter::setFullscreenMode()
{
fullscreen_mode = true;
}
void ONScripter::setWindowMode()
{
window_mode = true;
}
void ONScripter::enableButtonShortCut()
{
force_button_shortcut_flag = true;
}
void ONScripter::enableWheelDownAdvance()
{
enable_wheeldown_advance_flag = true;
}
void ONScripter::disableRescale()
{
disable_rescale_flag = true;
}
void ONScripter::renderFontOutline()
{
#if (SDL_TTF_MAJOR_VERSION>=2) && (SDL_TTF_MINOR_VERSION>=0) && (SDL_TTF_PATCHLEVEL>=10)
render_font_outline = true;
#else
fprintf(stderr, "--render-font-outline is not supported with SDL_ttf %d.%d.%d\n", SDL_TTF_MAJOR_VERSION, SDL_TTF_MINOR_VERSION, SDL_TTF_PATCHLEVEL);
#endif
}
void ONScripter::enableEdit()
{
edit_flag = true;
}
void ONScripter::setKeyEXE(const char *filename)
{
setStr(&key_exe_file, filename);
}
int ONScripter::openScript()
{
if (is_script_read) return 0;
is_script_read = true;
if (archive_path == NULL){
archive_path = new char[1];
archive_path[0] = 0;
}
if (key_exe_file){
createKeyTable( key_exe_file );
script_h.setKeyTable( key_table );
}
return ScriptParser::openScript();
}
int ONScripter::init()
{
initSDL();
openAudio();
image_surface = AnimationInfo::alloc32bitSurface( 1, 1, texture_format );
accumulation_surface = AnimationInfo::allocSurface( screen_width, screen_height, texture_format );
backup_surface = AnimationInfo::allocSurface( screen_width, screen_height, texture_format );
effect_src_surface = AnimationInfo::allocSurface( screen_width, screen_height, texture_format );
effect_dst_surface = AnimationInfo::allocSurface( screen_width, screen_height, texture_format );
layer_alpha_buf = new unsigned char[screen_width*screen_height];
#if defined(USE_SDL_RENDERER)
screenshot_surface = AnimationInfo::alloc32bitSurface( screen_device_width, screen_device_height, texture_format );
#else
screenshot_surface = AnimationInfo::alloc32bitSurface( screen_width, screen_height, texture_format );
#endif
screenshot_w = screen_width;
screenshot_h = screen_height;
#ifdef USE_SDL_RENDERER
texture = SDL_CreateTextureFromSurface(renderer, accumulation_surface);
#endif
tmp_image_buf = NULL;
tmp_image_buf_length = 0;
mean_size_of_loaded_images = 0;
num_loaded_images = 10; // to suppress temporal increase at the start-up
text_info.num_of_cells = 1;
text_info.allocImage( screen_width, screen_height, texture_format );
text_info.fill(0, 0, 0, 0);
text_info.blending_mode = AnimationInfo::BLEND_ADD2;
// ----------------------------------------
// Initialize font
if ( default_font ){
font_file = new char[ strlen(default_font) + 1 ];
sprintf( font_file, "%s", default_font );
}
else{
font_file = new char[ strlen(archive_path) + strlen(FONT_FILE) + 1 ];
sprintf( font_file, "%s%s", archive_path, FONT_FILE );
#ifdef USE_FONTCONFIG
FILE *fp = NULL;
if ((fp = ::fopen(font_file, "rb")) == NULL){
FcPattern *pat = FcPatternCreate();
FcPatternAddString( pat, FC_LANG, (const FcChar8*)"ja" );
FcPatternAddBool( pat, FC_OUTLINE, FcTrue );
FcPatternAddInteger( pat, FC_SLANT, FC_SLANT_ROMAN );
FcPatternAddInteger( pat, FC_WEIGHT, FC_WEIGHT_NORMAL );
FcConfigSubstitute( NULL, pat, FcMatchPattern );
FcDefaultSubstitute( pat );
FcResult result;
FcPattern *p_pat = FcFontMatch( NULL, pat, &result );
FcPatternDestroy( pat );
FcChar8* val_s;
if (FcResultMatch == FcPatternGetString( p_pat, FC_FILE, 0, &val_s )){
delete[] font_file;
font_file = new char[ strlen((const char*)val_s) + 1 ];
strcpy( font_file, (const char*)val_s );
printf("Font: %s\n", font_file);
}
FcPatternDestroy( p_pat );
}
else{
fclose(fp);
}
#endif
}
// ----------------------------------------
// variables relevant to sound
this->cdaudio_flag = cdaudio_flag;
#ifdef USE_CDROM
cdrom_info = NULL;
if ( cdaudio_flag ){
if ( cdrom_drive_number >= 0 && cdrom_drive_number < SDL_CDNumDrives() )
cdrom_info = SDL_CDOpen( cdrom_drive_number );
if ( !cdrom_info ){
fprintf(stderr, "Couldn't open default CD-ROM: %s\n", SDL_GetError());
}
else if ( cdrom_info && !CD_INDRIVE( SDL_CDStatus( cdrom_info ) ) ) {
fprintf( stderr, "no CD-ROM in the drive\n" );
SDL_CDClose( cdrom_info );
cdrom_info = NULL;
}
}
#endif
wave_file_name = NULL;
midi_file_name = NULL;
midi_info = NULL;
music_file_name = NULL;
fadeout_music_file_name = NULL;
music_buffer = NULL;
music_info = NULL;
layer_smpeg_buffer = NULL;
layer_smpeg_loop_flag = false;
#if defined(USE_SMPEG)
layer_smpeg_sample = NULL;
#endif
loop_bgm_name[0] = NULL;
loop_bgm_name[1] = NULL;
int i;
for (i=0 ; i<ONS_MIX_CHANNELS+ONS_MIX_EXTRA_CHANNELS ; i++) wave_sample[i] = NULL;
// ----------------------------------------
// Initialize misc variables
breakup_cells = NULL;
breakup_mask = breakup_cellforms = NULL;
internal_timer = SDL_GetTicks();
trap_dist = NULL;
resize_buffer = new unsigned char[16];
resize_buffer_size = 16;
for (i=0 ; i<MAX_PARAM_NUM ; i++) bar_info[i] = prnum_info[i] = NULL;
loadEnvData();
defineresetCommand();
readToken();
if ( sentence_font.openFont( font_file, screen_ratio1, screen_ratio2 ) == NULL ){
fprintf( stderr, "can't open font file: %s\n", font_file );
return -1;
}
return 0;
}
void ONScripter::reset()
{
automode_flag = false;
automode_time = DEFAULT_AUTOMODE_TIME;
autoclick_time = 0;
btntime2_flag = false;
btntime_value = -1;
btnwait_time = 0;
transbtn_flag = 0;
disableGetButtonFlag();
system_menu_enter_flag = false;
system_menu_mode = SYSTEM_NULL;
shift_pressed_status = 0;
ctrl_pressed_status = 0;
display_mode = DISPLAY_MODE_NORMAL;
event_mode = IDLE_EVENT_MODE;
all_sprite_hide_flag = false;
all_sprite2_hide_flag = false;
if (resize_buffer_size != 16){
delete[] resize_buffer;
resize_buffer = new unsigned char[16];
resize_buffer_size = 16;
}
current_over_button = -1;
shift_over_button = -1;
current_button_link = NULL;
num_fingers = 0;
variable_edit_mode = NOT_EDIT_MODE;
new_line_skip_flag = false;
text_on_flag = true;
setStr(&getret_str, NULL);
getret_int = 0;
// ----------------------------------------
// variables relevant to sound
wave_play_loop_flag = false;
midi_play_loop_flag = false;
music_play_loop_flag = false;
music_loopback_offset = 0.0;
cd_play_loop_flag = false;
mp3save_flag = false;
mp3fade_start = 0;
mp3fadeout_duration = 0;
mp3fadein_duration = 0;
mp3fadeout_duration_internal = 0;
mp3fadein_duration_internal = 0;
current_cd_track = -1;
resetSub();
}
void ONScripter::resetSub()
{
int i;
for ( i=0 ; i<script_h.global_variable_border ; i++ )
script_h.getVariableData(i).reset(false);
for ( i=0 ; i<3 ; i++ ) human_order[i] = 2-i; // "rcl"
refresh_shadow_text_mode = REFRESH_NORMAL_MODE | REFRESH_SHADOW_MODE | REFRESH_TEXT_MODE;
erase_text_window_mode = 1;
skip_mode = SKIP_NONE;
monocro_flag = false;
monocro_color[0] = monocro_color[1] = monocro_color[2] = 0;
nega_mode = 0;
clickstr_state = CLICK_NONE;
trap_mode = TRAP_NONE;
setStr(&trap_dist, NULL);
saveon_flag = true;
internal_saveon_flag = true;
is_kinsoku = true;
indent_offset = 0;
line_enter_status = 0;
page_enter_status = 0;
in_textbtn_flag = false;
resetSentenceFont();
deleteNestInfo();
deleteButtonLink();
deleteSelectLink();
stopCommand();
loopbgmstopCommand();
stopAllDWAVE();
setStr(&loop_bgm_name[1], NULL);
stopSMPEG();
// ----------------------------------------
// reset AnimationInfo
btndef_info.reset();
bg_info.reset();
setStr( &bg_info.file_name, "black" );
createBackground();
for (i=0 ; i<3 ; i++) tachi_info[i].reset();
for (i=0 ; i<MAX_SPRITE_NUM ; i++) sprite_info[i].reset();
for (i=0 ; i<MAX_SPRITE2_NUM ; i++) sprite2_info[i].reset();
for (i=0 ; i<MAX_TEXTURE_NUM ; i++) texture_info[i].reset();
smpeg_info = NULL;
effect_src_info.reset();
barclearCommand();
prnumclearCommand();
for (i=0 ; i<2 ; i++) cursor_info[i].reset();
show_dialog_flag = false;
for (i=0 ; i<4 ; i++) lookback_info[i].reset();
sentence_font_info.reset();
dirty_rect.fill( screen_width, screen_height );
}
void ONScripter::resetSentenceFont()
{
sentence_font.reset(&script_h.enc);
sentence_font.font_size_xy[0] = DEFAULT_FONT_SIZE;
sentence_font.font_size_xy[1] = DEFAULT_FONT_SIZE;
sentence_font.top_xy[0] = 21;
sentence_font.top_xy[1] = 16;// + sentence_font.font_size;
sentence_font.num_xy[0] = 23;
sentence_font.num_xy[1] = 16;
sentence_font.pitch_xy[0] = sentence_font.font_size_xy[0];
sentence_font.pitch_xy[1] = 2 + sentence_font.font_size_xy[1];
sentence_font.wait_time = 20;
sentence_font.window_color[0] = sentence_font.window_color[1] = sentence_font.window_color[2] = 0x99;
sentence_font_info.orig_pos.x = 0;
sentence_font_info.orig_pos.y = 0;
sentence_font_info.orig_pos.w = script_h.screen_width +1;
sentence_font_info.orig_pos.h = script_h.screen_height+1;
sentence_font_info.scalePosXY( screen_ratio1, screen_ratio2 );
sentence_font_info.scalePosWH( screen_ratio1, screen_ratio2 );
sentence_font.old_xy[0] = sentence_font.x(false);
sentence_font.old_xy[1] = sentence_font.y(false);
}
void ONScripter::flush( int refresh_mode, SDL_Rect *rect, bool clear_dirty_flag, bool direct_flag )
{
if ( direct_flag ){
flushDirect( *rect, refresh_mode );
}
else{
if ( rect ) dirty_rect.add( *rect );
if (dirty_rect.bounding_box.w * dirty_rect.bounding_box.h > 0)
flushDirect( dirty_rect.bounding_box, refresh_mode );
}
if ( clear_dirty_flag ) dirty_rect.clear();
}
void ONScripter::flushDirect( SDL_Rect &rect, int refresh_mode )
{
//printf("flush %d: %d %d %d %d\n", refresh_mode, rect.x, rect.y, rect.w, rect.h );
refreshSurface( accumulation_surface, &rect, refresh_mode );
#ifdef USE_SDL_RENDERER
SDL_Rect src_rect = {0, 0, screen_width, screen_height};
SDL_Rect dst_rect = {(device_width -screen_device_width )/2,
(device_height-screen_device_height)/2,
screen_device_width, screen_device_height};
SDL_LockSurface(accumulation_surface);
SDL_UpdateTexture(texture, &rect, (unsigned char*)accumulation_surface->pixels+accumulation_surface->pitch*rect.y+rect.x*sizeof(ONSBuf), accumulation_surface->pitch);
SDL_UnlockSurface(accumulation_surface);
SDL_RenderCopy(renderer, texture, &src_rect, &dst_rect);
SDL_RenderPresent(renderer);
#else
SDL_Rect dst_rect = rect;
if (AnimationInfo::doClipping(&dst_rect, &screen_rect) || (dst_rect.w==0 && dst_rect.h==0)) return;
SDL_BlitSurface( accumulation_surface, &dst_rect, screen_surface, &dst_rect );
SDL_UpdateRect( screen_surface, dst_rect.x, dst_rect.y, dst_rect.w, dst_rect.h );
#endif
}
void ONScripter::flushDirectYUV(SDL_Overlay *overlay)
{
#ifdef USE_SDL_RENDERER
SDL_Rect dst_rect = {(device_width -screen_device_width )/2,
(device_height-screen_device_height)/2,
screen_device_width, screen_device_height};
SDL_UpdateTexture(texture, &screen_rect, overlay->pixels[0], overlay->pitches[0]);
SDL_RenderCopy(renderer, texture, &screen_rect, &dst_rect);
SDL_RenderPresent(renderer);
#endif
}
void ONScripter::mouseOverCheck( int x, int y )
{
int c = 0, max_c = 0;
last_mouse_state.x = x;
last_mouse_state.y = y;
/* ---------------------------------------- */
/* Check button */
int button = -1;
ButtonLink *bl = root_button_link.next, *max_bl = NULL;
unsigned int max_alpha = 0;
while( bl ){
if ( x >= bl->select_rect.x && x < bl->select_rect.x + bl->select_rect.w &&
y >= bl->select_rect.y && y < bl->select_rect.y + bl->select_rect.h ){
if (transbtn_flag == false || shift_over_button == bl->no){
max_bl = bl;
max_c = c;
break;
}
else{
unsigned char alpha = 0;
if ( (bl->button_type == ButtonLink::SPRITE_BUTTON &&
max_alpha < (alpha = sprite_info[ bl->sprite_no ].getAlpha(x, y))) ||
(bl->button_type == ButtonLink::NORMAL_BUTTON &&
max_alpha < (alpha = bl->anim[0]->getAlpha(x, y))) ){
max_alpha = alpha;
max_bl = bl;
max_c = c;
}
}
}
bl = bl->next;
c++;
}
if (max_bl){
bl = max_bl;
button = bl->no;
c = max_c;
}
if ( current_over_button != button ){
DirtyRect dirty = dirty_rect;
dirty_rect.clear();
SDL_Rect check_src_rect = {0, 0, 0, 0};
SDL_Rect check_dst_rect = {0, 0, 0, 0};
if ( current_over_button != -1 ){
ButtonLink *cbl = current_button_link;
cbl->show_flag = 0;
check_src_rect = cbl->image_rect;
if ( cbl->button_type == ButtonLink::SPRITE_BUTTON ){
if ( cbl->exbtn_ctl[0] )
decodeExbtnControl( cbl->exbtn_ctl[0], &check_src_rect, &check_dst_rect );
else{
sprite_info[ cbl->sprite_no ].visible = true;
sprite_info[ cbl->sprite_no ].setCell(0);
}
}
else if ( cbl->button_type == ButtonLink::TMP_SPRITE_BUTTON ){
cbl->show_flag = 1;
cbl->anim[0]->visible = true;
cbl->anim[0]->setCell(0);
}
else if ( cbl->anim[1] != NULL ){
cbl->show_flag = 2;
}
dirty_rect.add( cbl->image_rect );
}
if ( is_exbtn_enabled && exbtn_d_button_link.exbtn_ctl[1] ){
decodeExbtnControl( exbtn_d_button_link.exbtn_ctl[1], &check_src_rect, &check_dst_rect );
}
if ( bl ){
if ( system_menu_mode != SYSTEM_NULL ){
if ( menuselectvoice_file_name[MENUSELECTVOICE_OVER] )
playSound(menuselectvoice_file_name[MENUSELECTVOICE_OVER],
SOUND_CHUNK, false, MIX_WAVE_CHANNEL);
}
else{
if ( selectvoice_file_name[SELECTVOICE_OVER] )
playSound(selectvoice_file_name[SELECTVOICE_OVER],
SOUND_CHUNK, false, MIX_WAVE_CHANNEL);
}
check_dst_rect = bl->image_rect;
if ( bl->button_type == ButtonLink::SPRITE_BUTTON ){
if (!bexec_flag || !bl->exbtn_ctl[1]){
sprite_info[ bl->sprite_no ].visible = true;
sprite_info[ bl->sprite_no ].setCell(1);
}
if ( bl->exbtn_ctl[1] )
decodeExbtnControl( bl->exbtn_ctl[1], &check_src_rect, &check_dst_rect );
}
else if ( bl->button_type == ButtonLink::TMP_SPRITE_BUTTON ){
bl->show_flag = 1;
bl->anim[0]->visible = true;
bl->anim[0]->setCell(1);
}
else if ( bl->button_type == ButtonLink::NORMAL_BUTTON ||
bl->button_type == ButtonLink::LOOKBACK_BUTTON ){
bl->show_flag = 1;
}
dirty_rect.add( bl->image_rect );
current_button_link = bl;
shortcut_mouse_line = c;
}
flush( refreshMode() );
dirty_rect = dirty;
}
current_over_button = button;
shift_over_button = -1;
}
void ONScripter::executeLabel()
{
executeLabelTop:
while ( current_line<current_label_info.num_of_lines ){
if ( debug_level > 0 )
printf("***** executeLabel %s:%d/%d:%d:%d *****\n",
current_label_info.name,
current_line,
current_label_info.num_of_lines,
string_buffer_offset, display_mode );
if ( script_h.getStringBuffer()[0] == '~' ){
last_tilde.next_script = script_h.getNext();
readToken();
continue;
}
if ( break_flag && !script_h.isName("next") ){
if ( script_h.getStringBuffer()[string_buffer_offset] == 0x0a )
current_line++;
if ( script_h.getStringBuffer()[string_buffer_offset] != ':' &&
script_h.getStringBuffer()[string_buffer_offset] != ';' &&
script_h.getStringBuffer()[string_buffer_offset] != 0x0a )
script_h.skipToken();
readToken();
continue;
}
if ( kidokuskip_flag && skip_mode & SKIP_NORMAL && kidokumode_flag && !script_h.isKidoku() ) skip_mode &= ~SKIP_NORMAL;
int ret = parseLine();
if ( ret & (RET_SKIP_LINE | RET_EOL) ){
if (ret & RET_SKIP_LINE) script_h.skipLine();
if (++current_line >= current_label_info.num_of_lines) break;
}
if (!(ret & RET_NO_READ)) readToken();
}
current_label_info = script_h.lookupLabelNext( current_label_info.name );
current_line = 0;
if ( current_label_info.start_address != NULL ){
script_h.setCurrent( current_label_info.label_header );
readToken();
goto executeLabelTop;
}
fprintf( stderr, " ***** End *****\n");
endCommand();
}
void ONScripter::runScript()
{
readToken();
parseLine();
}
int ONScripter::parseLine( )
{
if (debug_level > 0) printf("ONScripter::Parseline %s\n", script_h.getStringBuffer() );
const char *cmd = script_h.getStringBuffer();
if (cmd[0] == ';') return RET_CONTINUE;
else if (strncmp(cmd, "langjp", 6) == 0 &&
script_h.current_language == 0) return RET_CONTINUE;
else if (strncmp(cmd, "langen", 6) == 0 &&
script_h.current_language == 1) return RET_CONTINUE;
else if (cmd[0] == '*') return RET_CONTINUE;
else if (cmd[0] == ':') return RET_CONTINUE;
if (script_h.isText()){
if ( current_mode == DEFINE_MODE ) errorAndExit( "text cannot be displayed in define section." );
return textCommand();
}
if (cmd[0] != '_'){
if (cmd[0] >= 'a' && cmd[0] <= 'z'){
UserFuncHash &ufh = user_func_hash[cmd[0]-'a'];
UserFuncLUT *uf = ufh.root.next;
while(uf){
if (!strcmp( uf->command, cmd )){
if (uf->lua_flag){
#ifdef USE_LUA
if (lua_handler.callFunction(false, cmd))
errorAndExit( lua_handler.error_str );
#endif
}
else{
gosubReal( cmd, script_h.getNext() );
}
return RET_CONTINUE;
}
uf = uf->next;
}
}
}
else{
cmd++;
}
if (cmd[0] >= 'a' && cmd[0] <= 'z'){
FuncHash &fh = func_hash[cmd[0]-'a'];
for (int i=0 ; i<fh.num ; i++){
if ( !strcmp( fh.func[i].command, cmd ) ){
//if (saveon_flag) saveSaveFile(false);
return (this->*fh.func[i].method)();
}
}
}
if ( cmd[0] == 0x0a )
return RET_CONTINUE | RET_EOL;
else if ( cmd[0] == 'v' && cmd[1] >= '0' && cmd[1] <= '9' )
return vCommand();
else if ( cmd[0] == 'd' && cmd[1] == 'v' && cmd[2] >= '0' && cmd[2] <= '9' )
return dvCommand();
fprintf( stderr, " command [%s] is not supported yet!!\n", cmd );
script_h.skipToken();
return RET_CONTINUE;
}
/* ---------------------------------------- */
void ONScripter::deleteButtonLink()
{
ButtonLink *b1 = root_button_link.next;
while( b1 ){
ButtonLink *b2 = b1;
b1 = b1->next;
if (b2 == current_button_link) current_over_button = -1;
delete b2;
}
root_button_link.next = NULL;
for (int i=0 ; i<3 ; i++){
if ( exbtn_d_button_link.exbtn_ctl[i] ){
delete[] exbtn_d_button_link.exbtn_ctl[i];
exbtn_d_button_link.exbtn_ctl[i] = NULL;
}
}
is_exbtn_enabled = false;
}
void ONScripter::refreshMouseOverButton()
{
int mx, my;
current_over_button = -1;
shift_over_button = -1;
current_button_link = root_button_link.next;
SDL_GetMouseState( &mx, &my );
if (!(SDL_GetAppState() & SDL_APPMOUSEFOCUS)){
mx = screen_device_width;
my = screen_device_height;
}
mx = mx * screen_width / screen_device_width;
my = my * screen_width / screen_device_width;
mouseOverCheck( mx, my );
}
/* ---------------------------------------- */
/* Delete select link */
void ONScripter::deleteSelectLink()
{
SelectLink *link, *last_select_link = root_select_link.next;
while ( last_select_link ){
link = last_select_link;
last_select_link = last_select_link->next;
delete link;
}
root_select_link.next = NULL;
}
void ONScripter::clearCurrentPage()
{
sentence_font.clear();
int num = (sentence_font.num_xy[0]*2+1)*sentence_font.num_xy[1];
if (sentence_font.getTateyokoMode() == FontInfo::TATE_MODE)
num = (sentence_font.num_xy[1]*2+1)*sentence_font.num_xy[0];
if ( current_page->text &&
current_page->max_text != num ){
delete[] current_page->text;
current_page->text = NULL;
}
if ( !current_page->text ){
current_page->text = new char[num];
current_page->max_text = num;
}
current_page->text_count = 0;
if (current_page->tag){
delete[] current_page->tag;
current_page->tag = NULL;
}
num_chars_in_sentence = 0;
internal_saveon_flag = true;
text_info.fill( 0, 0, 0, 0 );
cached_page = current_page;
}
void ONScripter::shadowTextDisplay( SDL_Surface *surface, SDL_Rect &clip )
{
if ( current_font->is_transparent ){
SDL_Rect rect = screen_rect;
if ( current_font == &sentence_font )
rect = sentence_font_info.pos;
if ( AnimationInfo::doClipping( &rect, &clip ) ) return;
if ( rect.x + rect.w > surface->w ) rect.w = surface->w - rect.x;
if ( rect.y + rect.h > surface->h ) rect.h = surface->h - rect.y;
SDL_LockSurface( surface );
ONSBuf *buf = (ONSBuf *)surface->pixels + rect.y * surface->w + rect.x;
SDL_PixelFormat *fmt = surface->format;
int color[3];
color[0] = current_font->window_color[0] + 1;
color[1] = current_font->window_color[1] + 1;
color[2] = current_font->window_color[2] + 1;
for ( int i=rect.y ; i<rect.y + rect.h ; i++ ){
for ( int j=rect.x ; j<rect.x + rect.w ; j++, buf++ ){
*buf = (((*buf & fmt->Rmask) >> fmt->Rshift) * color[0] >> 8) << fmt->Rshift |
(((*buf & fmt->Gmask) >> fmt->Gshift) * color[1] >> 8) << fmt->Gshift |
(((*buf & fmt->Bmask) >> fmt->Bshift) * color[2] >> 8) << fmt->Bshift;
}
buf += surface->w - rect.w;
}
SDL_UnlockSurface( surface );
}
else if ( sentence_font_info.image_surface ){
drawTaggedSurface( surface, &sentence_font_info, clip );
}
}
void ONScripter::newPage()
{
if ( current_page->text_count != 0 ){
current_page = current_page->next;
if ( start_page == current_page )
start_page = start_page->next;
clearCurrentPage();
}
page_enter_status = 0;
flush( refreshMode(), &sentence_font_info.pos );
}
ButtonLink *ONScripter::getSelectableSentence( char *buffer, FontInfo *info, bool flush_flag, bool nofile_flag )
{
int current_text_xy[2];
current_text_xy[0] = info->xy[0];
current_text_xy[1] = info->xy[1];
ButtonLink *bl = new ButtonLink();
bl->button_type = ButtonLink::TMP_SPRITE_BUTTON;
bl->show_flag = 1;
AnimationInfo *ai = bl->anim[0] = new AnimationInfo();
ai->trans_mode = AnimationInfo::TRANS_STRING;
ai->is_single_line = false;
ai->num_of_cells = 2;
ai->color_list = new uchar3[ ai->num_of_cells ];
for (int i=0 ; i<3 ; i++){
if (nofile_flag)
ai->color_list[0][i] = info->nofile_color[i];
else
ai->color_list[0][i] = info->off_color[i];
ai->color_list[1][i] = info->on_color[i];
}
setStr( &ai->file_name, buffer );
ai->orig_pos.x = info->x();
ai->orig_pos.y = info->y();
ai->scalePosXY( screen_ratio1, screen_ratio2 );
ai->visible = true;
setupAnimationInfo( ai, info );
bl->select_rect = bl->image_rect = ai->pos;
info->newLine();
if (info->getTateyokoMode() == FontInfo::YOKO_MODE)
info->xy[0] = current_text_xy[0];
else
info->xy[1] = current_text_xy[1];
dirty_rect.add( bl->image_rect );
return bl;
}
void ONScripter::decodeExbtnControl( const char *ctl_str, SDL_Rect *check_src_rect, SDL_Rect *check_dst_rect )
{
char sound_name[256];
int i, sprite_no, sprite_no2, cell_no;
while( char com = *ctl_str++ ){
if (com == 'C' || com == 'c'){
sprite_no = getNumberFromBuffer( &ctl_str );
sprite_no2 = sprite_no;
cell_no = -1;
if ( *ctl_str == '-' ){
ctl_str++;
sprite_no2 = getNumberFromBuffer( &ctl_str );
}
for (i=sprite_no ; i<=sprite_no2 ; i++)
refreshSprite( i, false, cell_no, NULL, NULL );
}
else if (com == 'P' || com == 'p'){
sprite_no = getNumberFromBuffer( &ctl_str );
if ( *ctl_str == ',' ){
ctl_str++;
cell_no = getNumberFromBuffer( &ctl_str );
}
else
cell_no = 0;
refreshSprite( sprite_no, true, cell_no, check_src_rect, check_dst_rect );
}
else if (com == 'S' || com == 's'){
sprite_no = getNumberFromBuffer( &ctl_str );
if (sprite_no < 0) sprite_no = 0;
else if (sprite_no >= ONS_MIX_CHANNELS) sprite_no = ONS_MIX_CHANNELS-1;
if ( *ctl_str != ',' ) continue;
ctl_str++;
if ( *ctl_str != '(' ) continue;
ctl_str++;
char *buf = sound_name;
while (*ctl_str != ')' && *ctl_str != '\0' ) *buf++ = *ctl_str++;
*buf++ = '\0';
playSound(sound_name, SOUND_CHUNK, false, sprite_no);
if ( *ctl_str == ')' ) ctl_str++;
}
else if (com == 'M' || com == 'm'){
sprite_no = getNumberFromBuffer( &ctl_str );
AnimationInfo *ai = &sprite_info[sprite_no];
SDL_Rect rect = ai->pos;
if ( *ctl_str != ',' ) continue;
ctl_str++; // skip ','
ai->orig_pos.x = getNumberFromBuffer( &ctl_str );
if ( *ctl_str != ',' ) continue;
ctl_str++; // skip ','
ai->orig_pos.y = getNumberFromBuffer( &ctl_str );
ai->scalePosXY( screen_ratio1, screen_ratio2 );
dirty_rect.add( rect );
ai->visible = true;
dirty_rect.add( ai->pos );
}
}
}
void ONScripter::saveAll()
{
saveEnvData();
saveGlovalData();
if ( filelog_flag ) writeLog( script_h.log_info[ScriptHandler::FILE_LOG] );
if ( labellog_flag ) writeLog( script_h.log_info[ScriptHandler::LABEL_LOG] );
if ( kidokuskip_flag ) script_h.saveKidokuData();
}
void ONScripter::loadEnvData()
{
volume_on_flag = true;
text_speed_no = 1;
skip_mode &= ~SKIP_TO_EOP;
default_env_font = NULL;
cdaudio_on_flag = true;
default_cdrom_drive = NULL;
kidokumode_flag = true;
setStr( &save_dir_envdata, NULL );
automode_time = DEFAULT_AUTOMODE_TIME;
if (loadFileIOBuf( "envdata" ) > 0){
if (readInt() == 1 && window_mode == false) menu_fullCommand();
if (readInt() == 0) volume_on_flag = false;
text_speed_no = readInt();
if (readInt() == 1) skip_mode |= SKIP_TO_EOP;
readStr( &default_env_font );
if (default_env_font == NULL)
setStr(&default_env_font, DEFAULT_ENV_FONT);
if (readInt() == 0) cdaudio_on_flag = false;
readStr( &default_cdrom_drive );
voice_volume = DEFAULT_VOLUME - readInt();
se_volume = DEFAULT_VOLUME - readInt();
music_volume = DEFAULT_VOLUME - readInt();
if (readInt() == 0) kidokumode_flag = false;
readInt();
readStr( &save_dir_envdata ); // save_dir_envdata is not used directly
if (!save_dir && save_dir_envdata){
// a workaround not to overwrite save_dir given in command line options
save_dir = new char[ strlen(archive_path) + strlen(save_dir_envdata) + 2 ];
sprintf( save_dir, "%s%s%c", archive_path, save_dir_envdata, DELIMITER );
script_h.setSaveDir(save_dir);
}
automode_time = readInt();
}
else{
setStr( &default_env_font, DEFAULT_ENV_FONT );
voice_volume = se_volume = music_volume = DEFAULT_VOLUME;
}
}
void ONScripter::saveEnvData()
{
file_io_buf_ptr = 0;
bool output_flag = false;
for (int i=0 ; i<2 ; i++){
writeInt( fullscreen_mode?1:0, output_flag );
writeInt( volume_on_flag?1:0, output_flag );
writeInt( text_speed_no, output_flag );
writeInt( (skip_mode & SKIP_TO_EOP)?1:0, output_flag );
writeStr( default_env_font, output_flag );
writeInt( cdaudio_on_flag?1:0, output_flag );
writeStr( default_cdrom_drive, output_flag );
writeInt( DEFAULT_VOLUME - voice_volume, output_flag );
writeInt( DEFAULT_VOLUME - se_volume, output_flag );
writeInt( DEFAULT_VOLUME - music_volume, output_flag );
writeInt( kidokumode_flag?1:0, output_flag );
writeInt( 0, output_flag ); // ?
writeStr( save_dir_envdata, output_flag );
writeInt( automode_time, output_flag );
if (i==1) break;
allocFileIOBuf();
output_flag = true;
}
saveFileIOBuf( "envdata" );
}
int ONScripter::refreshMode()
{
if (display_mode & DISPLAY_MODE_TEXT)
return refresh_shadow_text_mode;
return REFRESH_NORMAL_MODE;
}
void ONScripter::quit()
{
saveAll();
#ifdef USE_CDROM
if ( cdrom_info ){
SDL_CDStop( cdrom_info );
SDL_CDClose( cdrom_info );
}
#endif
if ( midi_info ){
Mix_HaltMusic();
Mix_FreeMusic( midi_info );
midi_info = NULL;
}
if ( music_info ){
Mix_HaltMusic();
Mix_FreeMusic( music_info );
music_info = NULL;
}
}
void ONScripter::disableGetButtonFlag()
{
bexec_flag = false;
btndown_flag = false;
getzxc_flag = false;
gettab_flag = false;
getpageup_flag = false;
getpagedown_flag = false;
getmclick_flag = false;
getinsert_flag = false;
getfunction_flag = false;
getenter_flag = false;
getcursor_flag = false;
getmouseover_flag = false;
spclclk_flag = false;
}
int ONScripter::getNumberFromBuffer( const char **buf )
{
int ret = 0;
while ( **buf >= '0' && **buf <= '9' )
ret = ret*10 + *(*buf)++ - '0';
return ret;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/weimingtom/Onscripter-Official.git
git@gitee.com:weimingtom/Onscripter-Official.git
weimingtom
Onscripter-Official
Onscripter-Official
master

搜索帮助