// ========================================================================== // try to load 1 palette from the ./res/data/ directory int misc_load_pal_from_disk(int pal_idx) { char tmp[100]; FILE *in; long size; sprintf(tmp, "%s/pal%i.bin", glb_ds1edit_data_dir, pal_idx); if(file_exists(tmp, -1, NULL)){ // load the palette from disk, instead of mpq in = fopen(tmp, "rb"); if (in == NULL){ DEBUG_MESSAGE("could not read %s\n", tmp); }else{ // 求取文件大小的常用方法 fseek(in, 0, SEEK_END); size = ftell(in); fseek(in, 0, SEEK_SET); // malloc glb_ds1edit.d2_pal[pal_idx] = (UBYTE *) malloc(size); if (glb_ds1edit.d2_pal[pal_idx] == NULL){ FATAL_EXIT("misc_load_pal_from_disk() : not enough mem (%li bytes) for palette %i", size, pal_idx); } // filling it DEBUG_MESSAGE("loading %s\n", tmp); fread(glb_ds1edit.d2_pal[pal_idx], size, 1, in); fclose(in); glb_ds1edit.pal_size[pal_idx] = size; return TRUE; } } return FALSE; }
/** Make sure the fd used by this redirection is not used by i.e. a pipe. */ void free_fd( io_data_t *io, int fd ) { if( !io ) return; if( ( io->io_mode == IO_PIPE ) || ( io->io_mode == IO_BUFFER ) ) { int i; for( i=0; i<2; i++ ) { if(io->param1.pipe_fd[i] == fd ) { while(1) { if( (io->param1.pipe_fd[i] = dup(fd)) == -1) { if( errno != EINTR ) { debug( 1, FD_ERROR, fd ); wperror( L"dup" ); FATAL_EXIT(); } } else { break; } } } } } free_fd( io->next, fd ); }
/// Sets up appropriate signal handlers. void signal_set_handlers() { struct sigaction act; act.sa_flags = 0; sigemptyset(&act.sa_mask); // Ignore SIGPIPE. We'll detect failed writes and deal with them appropriately. We don't want // this signal interrupting other syscalls or terminating us. act.sa_handler = SIG_IGN; sigaction(SIGPIPE, &act, 0); // Whether or not we're interactive we want SIGCHLD to not interrupt restartable syscalls. act.sa_flags = SA_SIGINFO; act.sa_sigaction = &handle_chld; act.sa_flags = SA_SIGINFO | SA_RESTART; if (sigaction(SIGCHLD, &act, 0)) { wperror(L"sigaction"); FATAL_EXIT(); } if (shell_is_interactive()) { set_interactive_handlers(); } else { set_non_interactive_handlers(); } }
// ========================================================================== // return the column number of a txt file, given its name int misc_get_txt_column_num(RQ_ENUM txt_idx, char * col_name) { int i = 0; char *desc; char tmp_str[256]; char txt_list[RQ_MAX][80] = { {"data/global/excel/lvltypes.txt"}, {"data/global/excel/lvlprest.txt"}, {"data/obj.txt"}, {"data/global/excel/objects.txt"}, }; if (txt_idx >= RQ_MAX){ return -1; } for(;;) { // 这个东西是以前手动填入的 desc = glb_txt_req_ptr[txt_idx][i]; if (desc == NULL){ FATAL_EXIT("misc_get_txt_column_num() :\n can't find <%s> in txt file <%i> <%s>\n", col_name, txt_idx, txt_list[txt_idx] ); }else{ if (stricmp(col_name, desc) == 0){ return i; }else{ i++; } } } }
//============================================================================= void CTransformComponent2::SetPosition (const Point2 & pos) { if (m_parent) { FATAL_EXIT("Not implemented"); } else { m_positionLocal = pos; } }
//============================================================================= void CTransformComponent2::SetRotation (Radian angle) { if (m_parent) { FATAL_EXIT("Not implemented"); } else { ASSERT(Math::IsFinite(float32(angle))); m_rotationLocal = angle; } }
int parser_t::eval_block_node(node_offset_t node_idx, const io_chain_t &io, enum block_type_t block_type) { // Paranoia. It's a little frightening that we're given only a node_idx and we interpret this in // the topmost execution context's tree. What happens if two trees were to be interleaved? // Fortunately that cannot happen (yet); in the future we probably want some sort of reference // counted trees. parse_execution_context_t *ctx = execution_contexts.back(); assert(ctx != NULL); CHECK_BLOCK(1); // Handle cancellation requests. If our block stack is currently empty, then we already did // successfully cancel (or there was nothing to cancel); clear the flag. If our block stack is // not empty, we are still in the process of cancelling; refuse to evaluate anything. if (this->cancellation_requested) { if (!block_stack.empty()) { return 1; } this->cancellation_requested = false; } // Only certain blocks are allowed. if ((block_type != TOP) && (block_type != SUBST)) { debug(1, INVALID_SCOPE_ERR_MSG, parser_t::get_block_desc(block_type)); bugreport(); return 1; } job_reap(0); // not sure why we reap jobs here /* Start it up */ const block_t *const start_current_block = current_block(); block_t *scope_block = new scope_block_t(block_type); this->push_block(scope_block); int result = ctx->eval_node_at_offset(node_idx, scope_block, io); // Clean up the block stack. this->pop_block(); while (start_current_block != current_block()) { if (current_block() == NULL) { debug(0, _(L"End of block mismatch. Program terminating.")); bugreport(); FATAL_EXIT(); break; } this->pop_block(); } job_reap(0); // reap again return result; }
/** This function is a wrapper around fork. If the fork calls fails with EAGAIN, it is retried FORK_LAPS times, with a very slight delay between each lap. If fork fails even then, the process will exit with an error message. */ pid_t execute_fork(bool wait_for_threads_to_die) { ASSERT_IS_MAIN_THREAD(); if (wait_for_threads_to_die || JOIN_THREADS_BEFORE_FORK) { /* Make sure we have no outstanding threads before we fork. This is a pretty sketchy thing to do here, both because exec.cpp shouldn't have to know about iothreads, and because the completion handlers may do unexpected things. */ iothread_drain_all(); } pid_t pid; struct timespec pollint; int i; g_fork_count++; for (i=0; i<FORK_LAPS; i++) { pid = fork(); if (pid >= 0) { return pid; } if (errno != EAGAIN) { break; } pollint.tv_sec = 0; pollint.tv_nsec = FORK_SLEEP_TIME; /* Don't sleep on the final lap - sleeping might change the value of errno, which will break the error reporting below. */ if (i != FORK_LAPS-1) { nanosleep(&pollint, NULL); } } debug_safe(0, FORK_ERROR); safe_perror("fork"); FATAL_EXIT(); return 0; }
void signal_unblock() { ASSERT_IS_MAIN_THREAD(); sigset_t chldset; block_count--; if (block_count < 0) { debug(0, _(L"Signal block mismatch")); bugreport(); FATAL_EXIT(); } if (!block_count) { sigfillset(&chldset); VOMIT_ON_FAILURE(pthread_sigmask(SIG_UNBLOCK, &chldset, 0)); } // debug( 0, L"signal block level decreased to %d", block_count ); }
/** Make sure the fd used by each redirection is not used by a pipe. Note that while this does not modify the vector, it does modify the IO redirections within (gulp) */ static void free_redirected_fds_from_pipes(const io_chain_t &io_chain) { size_t max = io_chain.size(); for (size_t i = 0; i < max; i++) { int fd_to_free = io_chain.at(i)->fd; /* We only have to worry about fds beyond the three standard ones */ if (fd_to_free <= 2) continue; /* Make sure the fd is not used by a pipe */ for (size_t j = 0; j < max; j++) { /* We're only interested in pipes */ io_data_t *io = io_chain.at(j).get(); if (io->io_mode != IO_PIPE && io->io_mode != IO_BUFFER) continue; CAST_INIT(io_pipe_t *, possible_conflict, io); /* If the pipe is a conflict, dup it to some other value */ for (int k=0; k<2; k++) { /* If it's not a conflict, we don't care */ if (possible_conflict->pipe_fd[k] != fd_to_free) continue; /* Repeat until we have a replacement fd */ int replacement_fd = -1; while (replacement_fd < 0) { replacement_fd = dup(fd_to_free); if (replacement_fd == -1 && errno != EINTR) { debug_safe_int(1, FD_ERROR, fd_to_free); safe_perror("dup"); FATAL_EXIT(); } } possible_conflict->pipe_fd[k] = replacement_fd; } } } }
// ========================================================================== // read the gamma correction file void misc_read_gamma(void) { FILE *in; int gt; int i; int v; char tmp[150]; char gamma_path[100]; sprintf(gamma_path, "%s/%s", glb_ds1edit_data_dir, "gamma.dat"); in = fopen(gamma_path, "rb"); if(in == NULL){ FATAL_EXIT("misc_read_gamma() : can't open %s", gamma_path); } for(gt=GC_060; gt<GC_MAX; gt++){ for(i=0; i<256; i++){ v = fgetc(in); glb_ds1edit.gamma_table[gt][i] = v; } } fclose(in); }
/** This function is a wrapper around fork. If the fork calls fails with EAGAIN, it is retried FORK_LAPS times, with a very slight delay between each lap. If fork fails even then, the process will exit with an error message. */ static pid_t exec_fork() { pid_t pid; struct timespec pollint; int i; for( i=0; i<FORK_LAPS; i++ ) { pid = fork(); if( pid >= 0) { return pid; } if( errno != EAGAIN ) { break; } pollint.tv_sec = 0; pollint.tv_nsec = FORK_SLEEP_TIME; /* Don't sleep on the final lap - sleeping might change the value of errno, which will break the error reporting below. */ if( i != FORK_LAPS-1 ) { nanosleep( &pollint, NULL ); } } debug( 0, FORK_ERROR ); wperror (L"fork"); FATAL_EXIT(); }
//============================================================================= ComponentType CComponent::GetType () const { FATAL_EXIT("Dervied components must specify a type"); return ComponentType::Null; }
/// Sets appropriate signal handlers. void signal_set_handlers() { struct sigaction act; sigemptyset(&act.sa_mask); act.sa_flags = SA_SIGINFO; act.sa_sigaction = &default_handler; // First reset everything to a use default_handler, a function whose sole action is to fire of // an event. sigaction(SIGINT, &act, 0); sigaction(SIGQUIT, &act, 0); sigaction(SIGTSTP, &act, 0); sigaction(SIGTTIN, &act, 0); sigaction(SIGTTOU, &act, 0); sigaction(SIGCHLD, &act, 0); // Ignore sigpipe, which we may get from the universal variable notifier. sigaction(SIGPIPE, &act, 0); if (shell_is_interactive()) { // Interactive mode. Ignore interactive signals. We are a shell, we know what is best for // the user. act.sa_handler = SIG_IGN; sigaction(SIGINT, &act, 0); sigaction(SIGQUIT, &act, 0); sigaction(SIGTSTP, &act, 0); sigaction(SIGTTIN, &act, 0); sigaction(SIGTTOU, &act, 0); act.sa_sigaction = &handle_int; act.sa_flags = SA_SIGINFO; if (sigaction(SIGINT, &act, 0)) { wperror(L"sigaction"); FATAL_EXIT(); } act.sa_sigaction = &handle_chld; act.sa_flags = SA_SIGINFO; if (sigaction(SIGCHLD, &act, 0)) { wperror(L"sigaction"); FATAL_EXIT(); } #ifdef SIGWINCH act.sa_flags = SA_SIGINFO; act.sa_sigaction = &handle_winch; if (sigaction(SIGWINCH, &act, 0)) { wperror(L"sigaction"); FATAL_EXIT(); } #endif act.sa_flags = SA_SIGINFO; act.sa_sigaction = &handle_hup; if (sigaction(SIGHUP, &act, 0)) { wperror(L"sigaction"); FATAL_EXIT(); } // SIGTERM restores the terminal controlling process before dying. act.sa_flags = SA_SIGINFO; act.sa_sigaction = &handle_term; if (sigaction(SIGTERM, &act, 0)) { wperror(L"sigaction"); FATAL_EXIT(); } } else { // Non-interactive. Ignore interrupt, check exit status of processes to determine result // instead. act.sa_handler = SIG_IGN; sigaction(SIGINT, &act, 0); sigaction(SIGQUIT, &act, 0); act.sa_handler = SIG_DFL; act.sa_sigaction = &handle_chld; act.sa_flags = SA_SIGINFO; if (sigaction(SIGCHLD, &act, 0)) { wperror(L"sigaction"); exit_without_destructors(1); } } }
wchar_t *escape( const wchar_t *in_orig, escape_flags_t flags ) { const wchar_t *in = in_orig; bool escape_all = !! (flags & ESCAPE_ALL); bool no_quoted = !! (flags & ESCAPE_NO_QUOTED); bool no_tilde = !! (flags & ESCAPE_NO_TILDE); wchar_t *out; wchar_t *pos; int need_escape=0; int need_complex_escape=0; if( !in ) { debug( 0, L"%s called with null input", __func__ ); FATAL_EXIT(); } if( !no_quoted && (wcslen( in ) == 0) ) { out = wcsdup(L"''"); if( !out ) DIE_MEM(); return out; } out = (wchar_t *)malloc( sizeof(wchar_t)*(wcslen(in)*4 + 1)); pos = out; if( !out ) DIE_MEM(); while( *in != 0 ) { if( ( *in >= ENCODE_DIRECT_BASE) && ( *in < ENCODE_DIRECT_BASE+256) ) { int val = *in - ENCODE_DIRECT_BASE; int tmp; *(pos++) = L'\\'; *(pos++) = L'X'; tmp = val/16; *pos++ = tmp > 9? L'a'+(tmp-10):L'0'+tmp; tmp = val%16; *pos++ = tmp > 9? L'a'+(tmp-10):L'0'+tmp; need_escape=need_complex_escape=1; } else { wchar_t c = *in; switch( c ) { case L'\t': *(pos++) = L'\\'; *(pos++) = L't'; need_escape=need_complex_escape=1; break; case L'\n': *(pos++) = L'\\'; *(pos++) = L'n'; need_escape=need_complex_escape=1; break; case L'\b': *(pos++) = L'\\'; *(pos++) = L'b'; need_escape=need_complex_escape=1; break; case L'\r': *(pos++) = L'\\'; *(pos++) = L'r'; need_escape=need_complex_escape=1; break; case L'\x1b': *(pos++) = L'\\'; *(pos++) = L'e'; need_escape=need_complex_escape=1; break; case L'\\': case L'\'': { need_escape=need_complex_escape=1; if( escape_all ) *pos++ = L'\\'; *pos++ = *in; break; } case L'&': case L'$': case L' ': case L'#': case L'^': case L'<': case L'>': case L'(': case L')': case L'[': case L']': case L'{': case L'}': case L'?': case L'*': case L'|': case L';': case L'"': case L'%': case L'~': { if (! no_tilde || c != L'~') { need_escape=1; if( escape_all ) *pos++ = L'\\'; } *pos++ = *in; break; } default: { if( *in < 32 ) { if( *in <27 && *in > 0 ) { *(pos++) = L'\\'; *(pos++) = L'c'; *(pos++) = L'a' + *in -1; need_escape=need_complex_escape=1; break; } int tmp = (*in)%16; *pos++ = L'\\'; *pos++ = L'x'; *pos++ = ((*in>15)? L'1' : L'0'); *pos++ = tmp > 9? L'a'+(tmp-10):L'0'+tmp; need_escape=need_complex_escape=1; } else { *pos++ = *in; } break; } } } in++; } *pos = 0; /* Use quoted escaping if possible, since most people find it easier to read. */ if( !no_quoted && need_escape && !need_complex_escape && escape_all ) { free( out ); out = escape_simple( in_orig ); } return out; }
// ========================================================================== // make the block table of 1 ds1 void misc_make_block_table(int ds1_idx) { //typedef struct BLOCK_TABLE_S //{ // // key // int dt1_idx_for_ds1; // long main_index; // long orientation; // long sub_index; // // // datas // int dt1_idx; // long rarity; // int block_idx; // BLK_TYP_E type; // int zero_line; // int roof_y; // // // conflicts managment // char conflict; // char used_by_game; // True / False // char used_by_editor; // True / False // // // animated tile // long curr_frame; // int updated; //} BLOCK_TABLE_S; //typedef struct BLOCK_S //{ // long direction; // WORD roof_y; // UBYTE sound; // UBYTE animated; // long size_y; // long size_x; // // long zeros1; // long orientation; // long main_index; // long sub_index; // long rarity; // /* // UBYTE unknown_a; // UBYTE unknown_b; // UBYTE unknown_c; // UBYTE unknown_d; // */ // UBYTE sub_tiles_flags[25]; // // int zeros2[7]; // long tiles_ptr; // long tiles_length; // long tiles_number; // // int zeros3[12]; //} BLOCK_S; //block估计是tile那一类..就是dt里面的块状结构 //因为在block内部有一个sound域, 是人物踩在上面的声音 //block_table是什么了? 因为我发现block_s和block_table_s有很多相似的域 //比如 orientation, main_index之类的 //但是block_table_s没有sound域 BLOCK_TABLE_S *bt_ptr; BLOCK_S *b_ptr; char tmp_str[80]; int i, d, b, size; int n = 0; //#define DT1_IN_DS1_MAX 33 //估计是32+1个ds1edit.dt1 for (i=0; i<DT1_IN_DS1_MAX; i++){ d = glb_ds1.dt1_idx[i]; if(d != -1){ n += glb_dt1[d].block_num; } //n获取的是所有dt1文件的block总数 } //为毛自增了一下 n++; //这里看来每个block都有一个block_table_s啊 size = sizeof(BLOCK_TABLE_S) * n; glb_ds1.block_table = (BLOCK_TABLE_S *) malloc(size); if(glb_ds1.block_table == NULL){ FATAL_EXIT("make_block_table(%i), not enough mem for %i bytes\n", ds1_idx, size ); } memset(glb_ds1.block_table, 0, size); //block_table_num的意思 glb_ds1.bt_num = n; // fill it bt_ptr = glb_ds1.block_table; //第一个手动的填写? //貌似第一个也没用...难道这就是上面n++的原因? //我现在怀疑这段代码是作者从另一个作者那里拿来修修补补用的 bt_ptr->orientation = -1; bt_ptr->main_idx = -1; bt_ptr->sub_idx = -1; bt_ptr->rarity = -1; bt_ptr->dt1_idx_for_ds1 = -1; bt_ptr->dt1_idx = -1; bt_ptr->block_idx = -1; bt_ptr->roof_y = -1; bt_ptr->type = -1; bt_ptr->zero_line = -1; //第二个block_table_s开始 bt_ptr++; //这里把bh_buffer的东西全部填写到bt_table中了 //bh_buffer的初始化过程参见 void dt1_bh_update(int i) for(i=0; i<DT1_IN_DS1_MAX; i++){ d = glb_ds1.dt1_idx[i]; if(d != -1){ b_ptr = glb_dt1[d].bh_buffer; for(b=0; b<glb_dt1[d].block_num; b++){ // sort-key //nmb,这些都是用来排序的 bt_ptr->orientation = b_ptr->orientation; bt_ptr->main_idx = b_ptr->main_idx; bt_ptr->sub_idx = b_ptr->sub_idx; bt_ptr->rarity = b_ptr->rarity; // datas //这些都是更加handy的block_table数据结构了 //但是所有信息都直接来自dt1文件解析时候的block_header // block headers : block_num structs of BLOCK_S // void * bh_buffer; //看来block_s是直接描述.dt1文件结构的数据结构 //而block_table_s是更加倾向于程序本身的数据结构, 里面加入了一些在程序中被分配的各种编号和type~ bt_ptr->dt1_idx_for_ds1 = i; bt_ptr->dt1_idx = d; bt_ptr->block_idx = b; bt_ptr->roof_y = 0; bt_ptr->zero_line = 0; // type 这里的zero_line是个什么???????????????????貌似很重要的样子 和dt1_tool那个代码结合看看 if (bt_ptr->orientation == 0){ // floor bt_ptr->zero_line = 0; if (b_ptr->animated == 0x01){ bt_ptr->type = BT_ANIMATED; } else { bt_ptr->type = BT_STATIC; } }else if(bt_ptr->orientation == 13){ // shadow bt_ptr->type = BT_SHADOW; bt_ptr->zero_line = - b_ptr->size_y; } else { // walls if ((bt_ptr->orientation == 10) || (bt_ptr->orientation == 11)) { // special bt_ptr->type = BT_SPECIAL; bt_ptr->zero_line = - b_ptr->size_y; } else if (bt_ptr->orientation == 15) { // roof bt_ptr->type = BT_ROOF; bt_ptr->roof_y = b_ptr->roof_y; bt_ptr->zero_line = 0; } else if (bt_ptr->orientation < 15) { // wall up bt_ptr->type = BT_WALL_UP; bt_ptr->zero_line = - b_ptr->size_y; } else if (bt_ptr->orientation > 15) { // wall down bt_ptr->type = BT_WALL_DOWN; bt_ptr->zero_line = 96; } } // next elements bt_ptr++; b_ptr++; } } } // display dt1 idx & file, to help user printf("\ndt1_idx file\n" "------- ---------------------------------------------------------------------\n"); for (d=0; d<DT1_IN_DS1_MAX; d++) { if (glb_ds1.dt1_idx[d] != -1) { for (i=0; i<DT1_MAX; i++) { if (i == glb_ds1.dt1_idx[d]) { if (glb_dt1[i].ds1_usage > 0) { printf("%7i %s\n", i, glb_dt1[i].name); } } } } } // sort it for conflict qsort(glb_ds1.block_table, n, sizeof(BLOCK_TABLE_S), misc_qsort_helper_block_table_1); // conflicts managment //没搞懂 misc_check_tiles_conflicts(ds1_idx); // sort it for useability qsort(glb_ds1.block_table, n, sizeof(BLOCK_TABLE_S), misc_qsort_helper_block_table_2); // display it printf("\nsorted block_table of glb_ds1 (%i blocks) :\n", ds1_idx, n); printf("block orientation main_idx sub_idx frame dt1_idx blk_idx roof_y type line0\n"); printf("----- ----------- -------- ------- ----- ------- ------- ------ ---- -----\n"); for (b=0; b<glb_ds1.bt_num; b++) { printf("%5i %11li %8li %7li %5li %7li %7li %6i %4i %5i", b, glb_ds1.block_table[b].orientation, glb_ds1.block_table[b].main_idx, glb_ds1.block_table[b].sub_idx, glb_ds1.block_table[b].rarity, glb_ds1.block_table[b].dt1_idx, glb_ds1.block_table[b].block_idx, glb_ds1.block_table[b].roof_y, glb_ds1.block_table[b].type, glb_ds1.block_table[b].zero_line ); glb_ds1.block_table[b].conflict = FALSE; if (glb_ds1.block_table[b].rarity == 0) { if (b>1) { if ( (glb_ds1.block_table[b].orientation == glb_ds1.block_table[b-1].orientation) && (glb_ds1.block_table[b].main_idx == glb_ds1.block_table[b-1].main_idx) && (glb_ds1.block_table[b].sub_idx == glb_ds1.block_table[b-1].sub_idx) ) { //没有执行到这里的..表示没有冲突~ glb_ds1.block_table[b].conflict = TRUE; } } if (b < (glb_ds1.bt_num-1)) { if ( (glb_ds1.block_table[b].orientation == glb_ds1.block_table[b+1].orientation) && (glb_ds1.block_table[b].main_idx == glb_ds1.block_table[b+1].main_idx) && (glb_ds1.block_table[b].sub_idx == glb_ds1.block_table[b+1].sub_idx) ) { glb_ds1.block_table[b].conflict = TRUE; } } } if (glb_ds1.block_table[b].conflict) { printf(" *"); } printf("\n"); } }