Ejemplo n.º 1
0
int test_outputfunc()
{
	LOG		*g = NULL ;
	
	g = CreateLogHandle() ;
	if( g == NULL )
	{
		printf( "创建日志句柄失败errno[%d]\n" , errno );
		return -1;
	}
	else
	{
		printf( "创建日志句柄成功\n" );
	}
	
	SetLogOutput( g , LOG_OUTPUT_CALLBACK , "127.0.0.1:514" , & MyOpenLogFirst , NULL , & MyWriteLog , NULL , NULL , & MyCloseLogFinally );
	SetLogLevel( g , LOG_LEVEL_INFO );
	SetLogStyles( g , LOG_STYLES_LOG , LOG_NO_STYLEFUNC );
	
	DebugLog( g , __FILE__ , __LINE__ , "hello iLOG3\n" );
	InfoLog( g , __FILE__ , __LINE__ , "hello iLOG3\n" );
	WarnLog( g , __FILE__ , __LINE__ , "hello iLOG3\n" );
	ErrorLog( g , __FILE__ , __LINE__ , "hello iLOG3\n" );
	FatalLog( g , __FILE__ , __LINE__ , "hello iLOG3\n" );
	
	DestroyLogHandle( g );
	printf( "销毁日志句柄\n" );
	
	return 0;
}
Ejemplo n.º 2
0
void Map::Init4bpp(const Image16Bpp& image)
{
    for (unsigned int i = 0; i < data.size(); i++)
    {
        int tilex = i % width;
        int tiley = i / width;
        ImageTile imageTile(image, tilex, tiley);
        int tile_id = 0;
        int pal_id = 0;

        if (!tileset->Match(imageTile, tile_id, pal_id))
        {
            WarnLog("Image: %s No match for tile starting at (%d %d) px, using empty tile instead.", image.name.c_str(), tilex * 8, tiley * 8);
            WarnLog("Image: %s No match for palette for tile starting at (%d %d) px, using palette 0 instead.", image.name.c_str(), tilex * 8, tiley * 8);
        }
        VerboseLog("%d %d => %d %d", tilex, tiley, pal_id, tile_id);
        data[i] = pal_id << 12 | tile_id;
    }
}
int CmdLineParserHelper::GetHexInt(const std::string& param, int def_value, int min, int max)
{
    wxString hex;
    if (!parser.Found(param, &hex)) return def_value;
    long ret;
    if (!hex.ToLong(&ret, 16))
    {
        WarnLog("Could not parse %s into hex ignoring", param.c_str());
        return def_value;
    }

    int val = ret;
    if (val < min || val > max)
    {
        WarnLog("Invalid value given for %s range [%d %d] given %d ignoring", param.c_str(), min, max, val);
        val = def_value;
    }
    return val;
}
int CmdLineParserHelper::GetInt(const std::string& param, int def_value, int min, int max)
{
    long ret;
    if (!parser.Found(param, &ret)) return def_value;

    int val = ret;
    if (val < min || val > max)
    {
        WarnLog("Invalid value given for %s range [%d %d] given %d ignoring", param.c_str(), min, max, val);
        val = def_value;
    }
    return val;
}
Ejemplo n.º 5
0
void Map::Init8bpp(const Image16Bpp& image)
{
    for (unsigned int i = 0; i < data.size(); i++)
    {
        int tilex = i % width;
        int tiley = i / width;
        ImageTile tile(image, tilex, tiley);
        int tile_id = 0;
        int pal_id = 0;

        if (!tileset->Match(tile, tile_id, pal_id))
            WarnLog("Image: %s No match for tile starting at (%d %d) px, using empty tile instead.", image.name.c_str(), tilex * 8, tiley * 8);

        data[i] = tile_id;
    }
}
Ejemplo n.º 6
0
double RawData::getBlockAveEnergy(int index){
    double ret = 0;
    int st = index *SAMPLES_IN_EACH_FRAME;
    
    // overflow
    if(st > frame_num){
        WarnLog("Calculate average energy in %d block, max %d",
                index,frame_num/SAMPLES_IN_EACH_FRAME);
        return ret;
    }
    
    //calculating
    for(int i = 0;i<SAMPLES_IN_EACH_FRAME;i++){
        double x = data[st+i];
        ret +=  x*x;
    }
    ret /= SAMPLES_IN_EACH_FRAME;
    return ret;
}
Ejemplo n.º 7
0
void Nin10Edit::OnOpen(wxCommandEvent& event)
{
    EventLog l(__func__);
    std::unique_ptr<wxFileDialog> filedlg(new wxFileDialog(this, _("Open Image"), "", "", wxFileSelectorDefaultWildcardStr,
                                                           wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR | wxFD_PREVIEW | wxFD_OPEN));
    if (filedlg->ShowModal() == wxID_CANCEL)
    {
        WarnLog("No image given");
        return;
    }


    std::string file = filedlg->GetPath().ToStdString();
    InfoLog("Got file: %s", file.c_str());
    images.emplace(file, file);
    ConvertToMode4(images, images8);

    auto* graphics_panel = new GraphicsEditorPanel(graphics_notebook);
	graphics_notebook->AddPage(graphics_panel, file, false);

    graphics_panel->SetImage(&images8[0]);
    palette_panel->SetPalette(images8[0].palette);
}
Ejemplo n.º 8
0
BOOL CheckForGarbage ( Slot_Mgr_Shr_t *MemPtr ) {

  int               SlotIndex;
  int               ProcIndex;
  int               Err;
  BOOL              ValidPid;

  ASSERT( MemPtr != NULL_PTR );
  #ifdef DEV
    DbgLog(DL5, "Thread %d is checking for garbage", pthread_self());
  #endif /* DEV */


  #ifdef DEV
    DbgLog (DL5, "Garbage collection attempting global shared memory lock");
  #endif /* DEV */

  /* Grab the global Shared mem mutex since we might modify global_session_count */

#ifdef PKCS64
  Err = msem_lock(&(MemPtr->slt_mutex),0);
#else
  Err = pthread_mutex_lock ( &(MemPtr->slt_mutex) );
#endif

  if ( Err != 0 ) {
    DbgLog (DL0, "Garbage collection: Locking attempt for global shmem mutex returned %s", SysConst(Err) );
    return FALSE;
  }

  #ifdef DEV
  DbgLog ( DL5, "Garbage collection: Got global shared memory lock");
  #endif /* DEV */


  for ( ProcIndex = 0; ProcIndex < NUMBER_PROCESSES_ALLOWED; ProcIndex++ ) {

#ifdef PKCS64
    Slot_Mgr_Proc_t_64 *pProc = &(MemPtr->proc_table[ProcIndex]);
#else
    Slot_Mgr_Proc_t   *pProc = &(MemPtr->proc_table[ProcIndex]);
#endif

    ASSERT(pProc != NULL_PTR);

    if ( ! (pProc->inuse) ) {
      continue;
    }

    ValidPid = ( (IsValidProcessEntry ( pProc->proc_id, pProc->reg_time )) && (pProc->proc_id != 0) );


    if ( ( pProc->inuse ) && (! ValidPid ) ) {

      #ifdef DEV
        DbgLog(DL1, "Garbage collection routine found bad entry for pid %d (Index: %d); removing from table", pProc->proc_id, ProcIndex );
      #endif /* DEV */

      /*                         */
      /* Clean up session counts */
      /*                         */
      for ( SlotIndex = 0; SlotIndex < NUMBER_SLOTS_MANAGED; SlotIndex++ ) {


#ifdef PKCS64
	unsigned int *pGlobalSessions    = &(MemPtr->slot_info[SlotIndex].global_sessions);
	unsigned int *pProcSessions      = &(pProc->slot_session_count[SlotIndex]);
#else
	int *pGlobalSessions    = &(MemPtr->slot_info[SlotIndex].global_sessions);
	int *pProcSessions      = &(pProc->slot_session_count[SlotIndex]);
#endif


	if ( *pProcSessions > 0 ) {

  	  #ifdef DEV
	    DbgLog ( DL2, "GC: Invalid pid (%d) is holding %d sessions open on slot %d.  Global session count for this slot is %d", pProc->proc_id, *pProcSessions, SlotIndex, *pGlobalSessions );
          #endif /* DEV */

	  if ( *pProcSessions > *pGlobalSessions ) {
	    #ifdef DEV
	      WarnLog ( "Garbage Collection: Illegal values in table for defunct process");
	      DbgLog  ( DL0, "Garbage collection: A process ( Index: %d, pid: %d ) showed %d sessions open on slot %s, but the global count for this slot is only %d",
			ProcIndex, pProc->proc_id, *pProcSessions, SlotIndex, *pGlobalSessions );
	    #endif /* DEV */
	    *pGlobalSessions = 0;
	  } else {
	    *pGlobalSessions -= *pProcSessions;
	  }

	  *pProcSessions = 0;

	} /* end if *pProcSessions */

      } /* end for SlotIndex */


      /*                                      */
      /* NULL out everything except the mutex */
      /*                                      */

      #if PER_PROCESS_MUTEXES
        /* Grab the mutex for this proc's shared memory data structure */

#ifdef PKCS64
        Err = msem_lock(&(pProc->proc_mutex),MSEM_IF_NOWAIT);
#else 
        Err = pthread_mutex_trylock( &(pProc->proc_mutex) );
#endif

	if ( ( Err != 0 ) ) {
	  /* We didn't get the lock! */
	  /* Attempting to destroy a locked mutex results in undefined behavior */
	  /* http://techlib.austin.ibm.com/techlib/manuals/adoclib/libs/basetrf1/pthreads.htm */
	  DbgLog (DL0,"Unable to get per-process mutex for pid %d (%s) - skipping", pProc->proc_id, SysConst( Err ) );

	  /* 
	     The exit routine will figure out that this is an invalid process entry
	     (by calling IsValidProcessEntry()), and won't prevent the slotd from exiting
	     because of this entry.
	     */

	  continue;
	}
      #endif /* PER_PROCESS_MUTEXES */

      memset( &(pProc->inuse),              '\0', sizeof(pProc->inuse) );
      memset( &(pProc->proc_id),            '\0', sizeof(pProc->proc_id) );
      memset( &(pProc->slotmap),            '\0', sizeof(pProc->slotmap) );
      memset( &(pProc->blocking),           '\0', sizeof(pProc->blocking ));
      memset( &(pProc->error),              '\0', sizeof(pProc->error) );
      memset( &(pProc->slot_session_count), '\0', sizeof(pProc->slot_session_count) );
      memset( &(pProc->reg_time),           '\0', sizeof(pProc->reg_time) );

    } /* end if inuse && ValidPid */
    

    #if PER_PROCESS_MUTEXES

#ifdef PKCS64 
      msem_unlock(&(pProc->proc_mutex),0)
    
#else
      pthread_mutex_unlock( &(pProc->proc_mutex));
#endif

    #endif /* PER_PROCESS_MUTEXES  */
   
    
  } /* end for ProcIndex */
  
#ifdef PKCS64
  msem_unlock(&(MemPtr->slt_mutex),0);
#else
  pthread_mutex_unlock ( &(MemPtr->slt_mutex) );
#endif

  DbgLog ( DL5, "Garbage collection: Released global shared memory lock");

  return TRUE;
  
}
Ejemplo n.º 9
0
BOOL CheckForGarbage ( Slot_Mgr_Shr_t *MemPtr ) {

  int               SlotIndex;
  int               ProcIndex;
  int               Err;
  BOOL              ValidPid;

  ASSERT( MemPtr != NULL_PTR );
  #ifdef DEV
    DbgLog(DL5, "Thread %d is checking for garbage", pthread_self());
  #endif /* DEV */


  #ifdef DEV
    DbgLog (DL5, "Garbage collection attempting global shared memory lock");
  #endif /* DEV */

  /* Grab the global Shared mem mutex since we might modify global_session_count */

    Err = XProcLock();
  if ( Err != TRUE ) {
    DbgLog (DL0, "Garbage collection: Locking attempt for global shmem mutex returned %s", SysConst(Err) );
    return FALSE;
  }

  #ifdef DEV
  DbgLog ( DL5, "Garbage collection: Got global shared memory lock");
  #endif /* DEV */


  for ( ProcIndex = 0; ProcIndex < NUMBER_PROCESSES_ALLOWED; ProcIndex++ ) {

    Slot_Mgr_Proc_t_64 *pProc = &(MemPtr->proc_table[ProcIndex]);

    ASSERT(pProc != NULL_PTR);

    if ( ! (pProc->inuse) ) {
      continue;
    }

    ValidPid = ( (IsValidProcessEntry ( pProc->proc_id, pProc->reg_time )) && (pProc->proc_id != 0) );


    if ( ( pProc->inuse ) && (! ValidPid ) ) {

      #ifdef DEV
        DbgLog(DL1, "Garbage collection routine found bad entry for pid %d (Index: %d); removing from table", pProc->proc_id, ProcIndex );
      #endif /* DEV */

      /*                         */
      /* Clean up session counts */
      /*                         */
      for ( SlotIndex = 0; SlotIndex < NUMBER_SLOTS_MANAGED; SlotIndex++ ) {

	unsigned int *pGlobalSessions =
		      &(MemPtr->slot_global_sessions[SlotIndex]);
	unsigned int *pProcSessions = &(pProc->slot_session_count[SlotIndex]);

	if ( *pProcSessions > 0 ) {

  	  #ifdef DEV
	    DbgLog ( DL2, "GC: Invalid pid (%d) is holding %d sessions open on slot %d.  Global session count for this slot is %d", pProc->proc_id, *pProcSessions, SlotIndex, *pGlobalSessions );
          #endif /* DEV */

	  if ( *pProcSessions > *pGlobalSessions ) {
	    #ifdef DEV
	      WarnLog ( "Garbage Collection: Illegal values in table for defunct process");
	      DbgLog  ( DL0, "Garbage collection: A process ( Index: %d, pid: %d ) showed %d sessions open on slot %s, but the global count for this slot is only %d",
			ProcIndex, pProc->proc_id, *pProcSessions, SlotIndex, *pGlobalSessions );
	    #endif /* DEV */
	    *pGlobalSessions = 0;
	  } else {
	    *pGlobalSessions -= *pProcSessions;
	  }

	  *pProcSessions = 0;

	} /* end if *pProcSessions */

      } /* end for SlotIndex */


      /*                                      */
      /* NULL out everything except the mutex */
      /*                                      */

      memset( &(pProc->inuse),              '\0', sizeof(pProc->inuse) );
      memset( &(pProc->proc_id),            '\0', sizeof(pProc->proc_id) );
      memset( &(pProc->slotmap),            '\0', sizeof(pProc->slotmap) );
      memset( &(pProc->blocking),           '\0', sizeof(pProc->blocking ));
      memset( &(pProc->error),              '\0', sizeof(pProc->error) );
      memset( &(pProc->slot_session_count), '\0', sizeof(pProc->slot_session_count) );
      memset( &(pProc->reg_time),           '\0', sizeof(pProc->reg_time) );

    } /* end if inuse && ValidPid */

  } /* end for ProcIndex */

  XProcUnLock();
  DbgLog ( DL5, "Garbage collection: Released global shared memory lock");

  return TRUE;

}
Ejemplo n.º 10
0
int worker( struct TcpdaemonEntryParam *pep , struct TcpdaemonServerEnv *pse )
{
	struct sembuf		sb ;
	fd_set			readfds ;
	
	struct sockaddr		accept_addr ;
	socklen_t		accept_addrlen ;
	int			accept_sock ;
	
	int			nret = 0 ;
	
	while(1)
	{
		DebugLog( __FILE__ , __LINE__ , "WORKER(%ld) | waiting for entering accept mutex\n" , pse->index );
		
		/* 进入临界区 */
		memset( & sb , 0x00 , sizeof(struct sembuf) );
		sb.sem_num = 0 ;
		sb.sem_op = -1 ;
		sb.sem_flg = SEM_UNDO ;
		nret = semop( pse->accept_mutex , & sb , 1 ) ;
		if( nret == -1 )
		{
			ErrorLog( __FILE__ , __LINE__ , "WORKER(%ld) | enter accept mutex failed , errno[%d]\n" , pse->index , errno );
			return -1;
		}
		else
		{
			DebugLog( __FILE__ , __LINE__ , "WORKER(%ld) | enter accept mutex ok\n" , pse->index );
		}
		
		/* 监控侦听socket或存活管道事件 */
		FD_ZERO( & readfds );
		FD_SET( pse->listen_sock , & readfds );
		FD_SET( pse->alive_pipe->fd[0] , & readfds );
		nret = select( MAX_INT(pse->listen_sock,pse->alive_pipe->fd[0])+1 , & readfds , NULL , NULL , NULL ) ;
		if( nret == -1 )
		{	
			ErrorLog( __FILE__ , __LINE__ , "WORKER(%ld) | select failed , errno[%d]\n" , pse->index , errno );
			break;
		}
		
		if( FD_ISSET( pse->alive_pipe->fd[0] , & readfds ) )
		{
			DebugLog( __FILE__ , __LINE__ , "WORKER(%ld) | alive_pipe received quit command\n" , pse->index );
			break;
		}
		
		/* 接受新客户端连接 */
		accept_addrlen = sizeof(struct sockaddr) ;
		memset( & accept_addr , 0x00 , accept_addrlen );
		accept_sock = accept( pse->listen_sock , & accept_addr , & accept_addrlen ) ;
		if( accept_sock == -1 )
		{
			ErrorLog( __FILE__ , __LINE__ , "WORKER(%ld) | accept failed , errno[%d]\n" , pse->index , errno );
			break;
		}
		else
		{
			DebugLog( __FILE__ , __LINE__ , "WORKER(%ld) | accept ok , [%d]accept[%d]\n" , pse->index , pse->listen_sock , accept_sock );
		}
		
		if( pep->tcp_nodelay > 0 )
		{
			setsockopt( accept_sock , IPPROTO_TCP , TCP_NODELAY , (void*) & (pep->tcp_nodelay) , sizeof(int) );
		}
		
		if( pep->tcp_linger > 0 )
		{
			struct linger	lg ;
			lg.l_onoff = 1 ;
			lg.l_linger = pep->tcp_linger - 1 ;
			setsockopt( accept_sock , SOL_SOCKET , SO_LINGER , (void *) & lg , sizeof(struct linger) );
		}
		
		/* 离开临界区 */
		memset( & sb , 0x00 , sizeof(struct sembuf) );
		sb.sem_num = 0 ;
		sb.sem_op = 1 ;
		sb.sem_flg = SEM_UNDO ;
		nret = semop( pse->accept_mutex , & sb , 1 ) ;
		if( nret == -1 )
		{
			ErrorLog( __FILE__ , __LINE__ , "WORKER(%ld) | leave accept mutex failed , errno[%d]\n" , pse->index , errno );
			return -1;
		}
		else
		{
			DebugLog( __FILE__ , __LINE__ , "WORKER(%ld) | leave accept mutex ok\n" , pse->index );
		}
		
		/* 调用通讯数据协议及应用处理回调函数 */
		DebugLog( __FILE__ , __LINE__ , "WORKER(%ld) | 调用tcpmain\n" , pse->index );
		nret = pse->pfunc_tcpmain( pep->param_tcpmain , accept_sock , & accept_addr ) ;
		if( nret < 0 )
		{
			ErrorLog( __FILE__ , __LINE__ , "WORKER(%ld) | tcpmain return[%d]\n" , pse->index , nret );
			return -1;
		}
		else if( nret > 0 )
		{
			WarnLog( __FILE__ , __LINE__ , "WORKER(%ld) | tcpmain return[%d]\n" , pse->index , nret );
		}
		else
		{
			DebugLog( __FILE__ , __LINE__ , "WORKER(%ld) | tcpmain return[%d]\n" , pse->index , nret );
		}
		
		/* 关闭客户端连接 */
		close( accept_sock );
		DebugLog( __FILE__ , __LINE__ , "close[%d]\n" , accept_sock );
		
		/* 检查工作进程处理数量 */
		pse->requests_per_process++;
		if( pep->max_requests_per_process != 0 && pse->requests_per_process >= pep->max_requests_per_process )
		{
			InfoLog( __FILE__ , __LINE__ , "WORKER(%ld) | maximum number of processing[%ld][%ld] , ending\n" , pse->index , pse->requests_per_process , pep->max_requests_per_process );
			return -1;
		}
	}
	
	/* 最终离开临界区 */
	memset( & sb , 0x00 , sizeof(struct sembuf) );
	sb.sem_num = 0 ;
	sb.sem_op = 1 ;
	sb.sem_flg = SEM_UNDO ;
	nret = semop( pse->accept_mutex , & sb , 1 ) ;
	if( nret == -1 )
	{
		InfoLog( __FILE__ , __LINE__ , "WORKER(%ld) | leave accept mutex finally failed , errno[%d]\n" , pse->index , errno );
		return -1;
	}
	else
	{
		DebugLog( __FILE__ , __LINE__ , "WORKER(%ld) | leave accept mutex finally ok\n" , pse->index );
	}
	
	return 0;
}
void InitMediaMananger()
{
	InitializeCriticalSection(&g_locker);

	HKEY hKey;
	LONG lRet;

	lRet = RegOpenKeyEx(HKEY_CURRENT_USER, REG_PATH, 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hKey );
	if (lRet == ERROR_FILE_NOT_FOUND)
	{
		return ;
	}

	if( lRet != ERROR_SUCCESS )
	{
		WarnLog("Faild(%d) to RegOpenKeyEx\n", lRet);
		return ;
	}

	for(int i = 0; ; i++)
	{
		wchar_t achGuid[256];
		DWORD cchGuid = 256;
		struct MediaInfo info;

		if (RegEnumValue(hKey, i, achGuid, &cchGuid, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) break;

		DWORD cbData = REG_SIZE;
		DWORD dwType = REG_BINARY;
		lRet = RegQueryValueEx(hKey, achGuid, 0, &dwType, (LPBYTE)(&info), &cbData);
		if ((lRet != ERROR_SUCCESS ) || (dwType != REG_BINARY) || (cbData != REG_SIZE))
		{
			ErrorLog("Faild(%d) to RegQueryValueEx\n", lRet);
			RegDeleteValue(hKey, achGuid);
			continue;
		}

		if (CheckMediaInfo(&info) == FALSE)
		{
			lRet = RegDeleteValue(hKey, achGuid);
			continue;
		}

		g_media_list = (MediaInfo **)MemoryRealloc(g_media_list, (g_media_info_count + 1) * sizeof(MediaInfo*));
		g_media_list[g_media_info_count] = (MediaInfo *)MemoryAlloc(sizeof(MediaInfo));
		g_media_list[g_media_info_count][0] = info;
		g_media_info_count ++;
	}
	RegCloseKey( hKey );

	if (g_media_info_count > 1)
	{
		qsort(g_media_list, g_media_info_count, sizeof(MediaInfo *), (int32_t (__cdecl *)(const void *,const void *))mediainfo_compare);
	}

	// ɾ³ý
	wchar_t szFileFormat[MAX_PATH];
	StringCchPrintf(szFileFormat, MAX_PATH, L"%ls\\vmeisoft_v1_*.*", g_szTempPath);
	WIN32_FIND_DATAW wfd;
	HANDLE hFind = FindFirstFile(szFileFormat, &wfd);
	if (hFind != INVALID_HANDLE_VALUE)
	{
		do
		{
			GUID id = GetGuidFromFileName(wfd.cFileName);

			BOOL bFound = FALSE;
			for(int i = 0; i < g_media_info_count; i++)
			{
				if (g_media_list[i]->m_Id == id)
				{
					bFound = TRUE;
					break;
				}
			}
			if (bFound == FALSE)
			{
				wchar_t szFileName[MAX_PATH];
				StringCchPrintf(szFileName, MAX_PATH, L"%ls\\%ls", g_szTempPath, wfd.cFileName);
				DeleteFile(szFileName);
			}
		}
		while (FindNextFile(hFind, &wfd) != 0);
		FindClose(hFind);
	}
}
Ejemplo n.º 12
0
void Tileset::Init8bpp(const std::vector<Image16Bpp>& images16)
{
    int tile_width = 8 + params.border;

    // Reduce all and get the global palette and reduced images.
    Image8BppScene scene(images16, name, palette);
    palette = scene.palette;

    const Tile& nullTile = Tile::GetNullTile8();
    const ImageTile& nullImageTile = ImageTile::GetNullTile();
    tiles.insert(nullTile);
    tilesExport.push_back(nullTile);
    matcher.insert(std::pair<ImageTile, Tile>(nullImageTile, nullTile));

    for (unsigned int k = 0; k < images16.size(); k++)
    {
        const Image8Bpp& image = scene.GetImage(k);
        const Image16Bpp& image16 = images16[k];

        unsigned int tilesX = image.width / tile_width;
        unsigned int tilesY = image.height / tile_width;
        unsigned int totalTiles = tilesX * tilesY;

        // Perform reduce.
        for (unsigned int i = 0; i < totalTiles; i++)
        {
            int tilex = i % tilesX;
            int tiley = i / tilesX;
            Tile tile(image, tilex, tiley, params.border);
            std::set<Tile>::iterator foundTile = tiles.find(tile);
            if (foundTile == tiles.end())
            {
                tile.id = tiles.size();
                tiles.insert(tile);
                tilesExport.push_back(tile);
                // Add matcher data
                ImageTile imageTile(image16, tilex, tiley, params.border);
                matcher.insert(std::pair<ImageTile, Tile>(imageTile, tile));
            }
        }
    }

    // Checks
    int tile_size = TILE_SIZE_BYTES_8BPP;
    int memory_b = tiles.size() * tile_size;
    if (params.force)
    {
        if (!affine && tiles.size() >= 1024)
            WarnLog("Too many tiles. Found %d tiles. Maximum is 1024. Associated maps exported against this tileset may be incorrect.", tiles.size());
        else if (affine && tiles.size() >= 256)
            WarnLog("Too many tiles found for affine. Found %d tiles. Maximum is 256. Associated maps exported against this tileset may be incorrect.", tiles.size());
    }
    else
    {
        if (!affine && tiles.size() >= 1024)
            FatalLog("Too many tiles. Found %d tiles. Maximum is 1024. Please make the map/tileset simpler. Use --force to override this.", tiles.size());
        else if (affine && tiles.size() >= 256)
            FatalLog("Too many tiles found for affine. Found %d tiles. Maximum is 256. Please make the map/tileset simpler. Use --force to override this.", tiles.size());
    }

    // Delicious infos
    int cbbs = tiles.size() * tile_size / SIZE_CBB_BYTES;
    int sbbs = (int) ceil(tiles.size() * tile_size % SIZE_CBB_BYTES / ((double)SIZE_SBB_BYTES));
    InfoLog("Tiles found %zu.", tiles.size());
    InfoLog("Tiles uses %d charblocks and %d screenblocks.", cbbs, sbbs);
    InfoLog("Total utilization %.2f/4 charblocks or %d/32 screenblocks, %d/65536 bytes.",
        memory_b / ((double)SIZE_CBB_BYTES), (int) ceil(memory_b / ((double)SIZE_SBB_BYTES)), memory_b);
}
Ejemplo n.º 13
0
void Tileset::Init4bpp(const std::vector<Image16Bpp>& images)
{
    // Tile image into 16 bit tiles
    Tileset tileset16bpp(images, name, 16, affine);
    std::set<ImageTile> imageTiles = tileset16bpp.itiles;

    const Tile& nullTile = Tile::GetNullTile4();
    const ImageTile& nullImageTile = ImageTile::GetNullTile();
    tiles.insert(nullTile);
    tilesExport.push_back(nullTile);
    matcher.insert(std::pair<ImageTile, Tile>(nullImageTile, nullTile));

    // Reduce each tile to 4bpp
    std::vector<Tile> gbaTiles;
    for (const auto& imageTile : imageTiles)
        gbaTiles.emplace_back(imageTile, 4);

    // Ensure image contains < 256 colors
    std::set<Color16> bigPalette;
    for (const auto& tile : gbaTiles)
    {
        const std::vector<Color16>& tile_palette = tile.palette.GetColors();
        bigPalette.insert(tile_palette.begin(), tile_palette.end());
    }

    if (bigPalette.size() > 256 && !params.force)
        FatalLog("Image after reducing tiles to 4 bpp still contains more than 256 distinct colors. Found %d colors. Please fix. Use --force to override.", bigPalette.size());
    else if (bigPalette.size() > 256 && params.force)
        WarnLog("Image after reducing tiles to 4 bpp still contains more than 256 distinct colors. Found %d colors. Potential for image color quality loss.");

    // Greedy approach deal with tiles with largest palettes first.
    std::sort(gbaTiles.begin(), gbaTiles.end(), TilesPaletteSizeComp);

    // Construct palette banks, assign bank id to tile, remap tile to palette bank given, assign tile ids
    for (auto& tile : gbaTiles)
    {
        int pbank = -1;
        // Fully contains checks
        for (unsigned int i = 0; i < paletteBanks.Size(); i++)
        {
            PaletteBank& bank = paletteBanks[i];
            if (bank.Contains(tile.palette))
                pbank = i;
        }

        // Ok then find least affected bank
        if (pbank == -1)
        {
            int min_delta = 0x7FFFFFFF;
            for (unsigned int i = 0; i < paletteBanks.Size(); i++)
            {
                PaletteBank& bank = paletteBanks[i];
                int colors_left;
                int delta;
                bank.CanMerge(tile.palette, colors_left, delta);
                if (colors_left >= 0 && delta < min_delta)
                {
                    min_delta = delta;
                    pbank = i;
                }
            }
        }

        // Cry and die for now. Unless you tell me to keep going.
        if (pbank == -1 && !params.force)
            FatalLog("More than 16 distinct palettes found, please use 8bpp mode. Use --force to override.");
        else if (pbank == -1 && params.force)
            WarnLog("More than 16 distinct palettes found. Huge potential for image color quality loss.");

        // Alright...
        if (pbank == -1)
        {
            pbank = paletteBanks.FindBestMatch(tile.palette);
            paletteBanks[pbank].BestMerge(tile.palette);
        }
        else
        {
            // Merge step and assign palette bank
            paletteBanks[pbank].Merge(tile.palette);
        }

        tile.palette_bank = pbank;
        tile.UsePalette(paletteBanks[pbank]);

        // Assign tile id
        const auto& it = tiles.find(tile);
        if (it == tiles.end())
        {
            tile.id = tiles.size();
            tiles.insert(tile);
            tilesExport.push_back(tile);
        }
        else
        {
            tile.id = it->id;
        }

        // Form mapping from ImageTile to Tile
        matcher.insert(std::pair<ImageTile, Tile>(*tile.sourceTile, tile));
    }

    int tile_size = TILE_SIZE_BYTES_4BPP;
    int memory_b = tiles.size() * tile_size;
    // 4bpp mode so !affine can be assumed here. Affine maps have a max of 256 tiles.
    if (tiles.size() >= 1024 && !params.force)
        FatalLog("Too many tiles. Found %d tiles. Maximum is 1024. Please make the image simpler. Use --force to override.", tiles.size());
    else if (tiles.size() >= 1024 && params.force)
        WarnLog("Too many tiles. Found %d tiles. Maximum is 1024. Associated maps exported against this tileset may be incorrect.", tiles.size());

    // Delicious infos
    int cbbs = tiles.size() * tile_size / SIZE_CBB_BYTES;
    int sbbs = (int) ceil(tiles.size() * tile_size % SIZE_CBB_BYTES / ((double)SIZE_SBB_BYTES));
    InfoLog("Tiles found %zu.", tiles.size());
    InfoLog("Tiles uses %d charblocks and %d screenblocks.", cbbs, sbbs);
    InfoLog("Total utilization %.2f/4 charblocks or %d/32 screenblocks, %d/65536 bytes.",
           memory_b / ((double)SIZE_CBB_BYTES), (int) ceil(memory_b / ((double)SIZE_SBB_BYTES)), memory_b);
}