Exemplo n.º 1
0
// ==========================================================================
// 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;
}
Exemplo n.º 2
0
Arquivo: exec.c Projeto: CodeMonk/fish
/**
   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 );
}
Exemplo n.º 3
0
/// 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();
    }
}
Exemplo n.º 4
0
// ==========================================================================
// 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++;
            }
        }
    }
}
Exemplo n.º 5
0
//=============================================================================
void CTransformComponent2::SetPosition (const Point2 & pos)
{
    if (m_parent)
    {
        FATAL_EXIT("Not implemented");
    }
    else
    {
        m_positionLocal = pos;
    }
}
Exemplo n.º 6
0
//=============================================================================
void CTransformComponent2::SetRotation (Radian angle)
{
    if (m_parent)
    {
        FATAL_EXIT("Not implemented");
    }
    else
    {
        ASSERT(Math::IsFinite(float32(angle)));
        m_rotationLocal = angle;
    }
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
/**
   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;
}
Exemplo n.º 9
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 );
}
Exemplo n.º 10
0
/** 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;
            }
        }
    }
}
Exemplo n.º 11
0
// ==========================================================================
// 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);
}
Exemplo n.º 12
0
Arquivo: exec.c Projeto: CodeMonk/fish
/**
   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();
}
Exemplo n.º 13
0
//=============================================================================
ComponentType CComponent::GetType () const
{
    FATAL_EXIT("Dervied components must specify a type");
    return ComponentType::Null;
}
Exemplo n.º 14
0
/// 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);
        }
    }
}
Exemplo n.º 15
0
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;
}
Exemplo n.º 16
0
// ==========================================================================
// 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");
    }
}