Example #1
0
void ILGCDeinit()
{
	_FinalizerStopFlag = 1;

	GC_TRACE("ILGCDeinit: Performing final GC [thread:%d]\n", (int)ILThreadSelf());

	/* Do a final GC */
	ILGCCollect();
	/* Cleanup the finalizer thread */
	if (_FinalizerThread && _FinalizerThreadStarted)
	{
		GC_TRACE("ILGCDeinit: Peforming last finalizer run [thread:%d]\n", (int)ILThreadSelf());

		ILWaitEventSet(_FinalizerSignal);
		
		GC_TRACE("ILGCDeinit: Waiting for finalizer thread to end [thread:%d]\n", (int)ILThreadSelf());

		/* Wait for the finalizer thread */
		if (ILThreadJoin(_FinalizerThread, 15000))
		{
			GC_TRACE("ILGCDeinit: Finalizer thread finished [thread:%d]\n", (int)ILThreadSelf());			
		}
		else
		{
			GC_TRACE("ILGCDeinit: Finalizer thread not responding [thread:%d]\n", (int)ILThreadSelf());
		}

		/* Destroy the finalizer thread */
		ILThreadDestroy(_FinalizerThread);			
	}

	_ILMutexDestroy(&_FinalizerLock);
}
Example #2
0
int _fastcall TScanPort::ScanBRomComPort(int index)
{
    string friendlyName;
    string label;
    int number;
    COMPortUtils comFinder;
    int comportType;

    //First scan
    GC_TRACE("<TScanPort> Execute(): First scan...");
    comportType = BOOTROM_COMPORT;
    comFinder.ScanFriendlyNameByDDK(true, comportType);


    GC_TRACE("<TScanPort> Execute(): Scan Bootrom COM port for Channel[%d]...", index);
    while(!(*mpStopFlag))
    {
        if(comFinder.GetNewPortFriendlyName(friendlyName, comportType)){
            if(comFinder.ExtractCOMNumber(friendlyName, number)){
                GC_TRACE("<TScanPort> Execute(): Find new Bootrom COM port for Channel[%d]! COM%d, comportType = %d", index, number, comportType);
                mIndex = index;
                m_BromComNum = number;
                SyncUpdateCOMPort();
                break;
            }
        }
        Sleep(500);
    }
    return S_DONE;
}
Example #3
0
void __fastcall TScanPort::ScanPrealoderOnly()
{
    bool * chnChecked = new bool[mArraySize];
    COMPortUtils comFinder;
    int comportType;
    string friendlyName;
    int number;
	int iRet = S_STOP;
	
    memcpy(chnChecked, mpIndexArray, mArraySize * sizeof(bool));
    //=====================Step1 Scan Brom Comport========================
    for(unsigned int iCycle = 0; (iCycle < mArraySize) && (!(*mpStopFlag));iCycle++){
        if(chnChecked[iCycle]){
            m_BromComNum = 0;
            m_PreLoaderComNum = 0;
			mIndex = iCycle;
			
			//First scan and make comport list
			GC_TRACE("<TScanPort> ScanPrealoderOnly(): First scan...");
			comportType = PRELOADER_COMPORT;
			comFinder.ScanFriendlyNameByDDK(true, comportType);

			//Now we find the new comport and compare with the comport list created by first scan
			GC_TRACE("<TScanPort> ScanPrealoderOnly(): Scan Prealoader COM port for Channel[%d]...", mIndex);
			iRet = S_STOP;
			while(!(*mpStopFlag))
			{
			    if(comFinder.GetNewPortFriendlyName(friendlyName, comportType)){
			        if(comFinder.ExtractCOMNumber(friendlyName, number)){
			            GC_TRACE("<TScanPort> ScanPrealoderOnly(): Find new Prealoader COM port for Channel[%d]! COM%d, comportType = %d", mIndex, number, comportType);
			            mIndex = iCycle;
			            m_PreLoaderComNum = number;
			            SyncUpdateCOMPort();
						iRet = S_DONE;
			            break;
			        }
			    }
				Sleep(500);
			 }

            if(S_DONE == iRet && m_PreLoaderComNum != 0){
				SyncUpdateScanSuccess();
                GC_TRACE("<TScanPort> ScanPrealoderOnly(): ScanPrealoderOnly success!");
            }
            else{
                SyncUpdateScanFail();
                GC_TRACE("<TScanPort> ScanPrealoderOnly(): ScanPrealoderOnly fail!");
				break;
            }
        }
    }
	
    delete [] chnChecked;
    SyncEnableUIForScan();

}
static uint16_t _find_selected_button_id(GRAPHICS_CONTROLLER *gc)
{
    /* executed when playback condition changes (ex. new page, popup-on, ...) */
    PG_DISPLAY_SET *s         = gc->igs;
    BD_IG_PAGE     *page      = NULL;
    unsigned        page_id   = bd_psr_read(gc->regs, PSR_MENU_PAGE_ID);
    unsigned        button_id = bd_psr_read(gc->regs, PSR_SELECTED_BUTTON_ID);
    unsigned        ii;

    page = _find_page(&s->ics->interactive_composition, page_id);
    if (!page) {
        GC_TRACE("_find_selected_button_id(): unknown page #%d (have %d pages)\n",
              page_id, s->ics->interactive_composition.num_pages);
        return 0xffff;
    }

    /* run 5.9.8.3 */

    /* 1) always use page->default_selected_button_id_ref if it is valid */
    if (_find_button_page(page, page->default_selected_button_id_ref, NULL) &&
        _is_button_enabled(gc, page, page->default_selected_button_id_ref)) {

        GC_TRACE("_find_selected_button_id() -> default #%d\n", page->default_selected_button_id_ref);
        return page->default_selected_button_id_ref;
    }

    /* 2) fallback to current PSR10 value if it is valid */
    for (ii = 0; ii < page->num_bogs; ii++) {
        BD_IG_BOG *bog = &page->bog[ii];
        uint16_t   enabled_button = gc->bog_data[ii].enabled_button;

        if (button_id == enabled_button) {
            if (_find_button_bog(bog, enabled_button)) {
                GC_TRACE("_find_selected_button_id() -> PSR10 #%d\n", enabled_button);
                return enabled_button;
            }
        }
    }

    /* 3) fallback to find first valid_button_id_ref from page */
    for (ii = 0; ii < page->num_bogs; ii++) {
        BD_IG_BOG *bog = &page->bog[ii];
        uint16_t   enabled_button = gc->bog_data[ii].enabled_button;

        if (_find_button_bog(bog, enabled_button)) {
            GC_TRACE("_find_selected_button_id() -> first valid #%d\n", enabled_button);
            return enabled_button;
        }
    }

    GC_TRACE("_find_selected_button_id(): not found -> 0xffff\n");
    return 0xffff;
}
Example #5
0
void __fastcall TScanPort::Execute()
{
    switch(m_eScanComportType)
	{
        case SCAN_BROM_AND_PRELOADER:
			GC_TRACE("<TScanPort> Execute(): Scan brom and prealoder begin...");
			ScanBromAndPreloader();
			break;
		case SCAN_PRELOADER_ONLY:
			GC_TRACE("<TScanPort> Execute(): Scan prealoder begin...");
		    ScanPrealoderOnly();
			break;
		default:
			break;
	}
	
    
}
Example #6
0
//------------------------------------------------------------------------------
bool open_com_port( HANDLE &hCOM_HANDLE, int i_com_port, int i_baud_rate)
{
    if ( hCOM_HANDLE != NULL && hCOM_HANDLE != INVALID_HANDLE_VALUE )
    {
        PurgeComm( hCOM_HANDLE, PURGE_TXABORT);
        PurgeComm( hCOM_HANDLE, PURGE_RXABORT);
        PurgeComm( hCOM_HANDLE, PURGE_TXCLEAR);
        PurgeComm( hCOM_HANDLE, PURGE_RXCLEAR);
        CloseHandle( hCOM_HANDLE);
        hCOM_HANDLE = NULL;
    }

	char c_com[50];

    ::sprintf(c_com, "\\\\.\\COM%d", i_com_port);

	hCOM_HANDLE = ::CreateFile( c_com,
			                    GENERIC_READ|GENERIC_WRITE,
			                    0,
			                    NULL,
			                    OPEN_EXISTING,
			                    FILE_ATTRIBUTE_NORMAL,
			                    NULL);

	if( hCOM_HANDLE == INVALID_HANDLE_VALUE )
    {
        //ShowMessage(" COM" + IntToStr( i_com_port) + " is used by other program.");
		GC_TRACE("<EfuseWriter> open_com_port(): Com %d is used by other program", i_com_port);
        hCOM_HANDLE = NULL;
	    return false;
	}

	if( ::SetupComm(hCOM_HANDLE, 8192, 8192)==FALSE )
        return false;

	if( ::PurgeComm(hCOM_HANDLE, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR)==FALSE )
        return false;


    COMMTIMEOUTS TimeOut;
    TimeOut.ReadIntervalTimeout         = 0;
    TimeOut.ReadTotalTimeoutMultiplier  = 1;
    TimeOut.ReadTotalTimeoutConstant    = 700;
    TimeOut.WriteTotalTimeoutMultiplier = 1;
    TimeOut.WriteTotalTimeoutConstant   = 700;

    SetCommTimeouts(hCOM_HANDLE, &TimeOut);

	char c_dcb[50];
    ::sprintf( c_dcb, "%d,n,8,1", i_baud_rate);

    BuildCommDCB( c_dcb, &dcb );

    SetCommState( hCOM_HANDLE, &dcb );
    return true;
}
static BD_PG_OBJECT *_find_object_for_button(PG_DISPLAY_SET *s,
                                             BD_IG_BUTTON *button, int state,
                                             BOG_DATA *bog_data)
{
    BD_PG_OBJECT *object   = NULL;
    unsigned object_id     = 0xffff;
    unsigned object_id_end = 0xffff;
    unsigned repeat        = 0;

    switch (state) {
        case BTN_NORMAL:
            object_id     = button->normal_start_object_id_ref;
            object_id_end = button->normal_end_object_id_ref;
            repeat        = button->normal_repeat_flag;
            break;
        case BTN_SELECTED:
            object_id     = button->selected_start_object_id_ref;
            object_id_end = button->selected_end_object_id_ref;
            repeat        = button->selected_repeat_flag;
            break;
        case BTN_ACTIVATED:
            object_id     = button->activated_start_object_id_ref;
            object_id_end = button->activated_end_object_id_ref;
            break;
    }

    if (bog_data) {
        if (bog_data->animate_indx >= 0) {
            int range = object_id_end - object_id;

            if (range > 0 && object_id < 0xffff && object_id_end < 0xffff) {
                GC_TRACE("animate button #%d: animate_indx %d, range %d, repeat %d\n",
                         button->id, bog_data->animate_indx, range, repeat);

                object_id += bog_data->animate_indx % (range + 1);
                bog_data->animate_indx++;
                if (!repeat && bog_data->animate_indx > range) {
                /* terminate animation to the last object */
                    bog_data->animate_indx = -1;
                }

            } else {
                /* no animation for this button */
                bog_data->animate_indx = -1;
            }
        }
    }

    if (!repeat && object_id_end < 0xfffe) {
        object_id = object_id_end;
    }

    object = _find_object(s, object_id);

    return object;
}
Example #8
0
int _fastcall TScanPort::SwitchToHighSpeedComPort(string strVid, string strPid)
{
    int iRet = S_DONE;
    unsigned short tempVidPid;
    USB_Setup_Info usb_setup_info;
    //FlashTool_CheckUSBStatus arguments
    FlashTool_USB_Status_Arg usb_status_arg;
    FlashTool_USB_Status_Result  usb_statue_result;
    usb_status_arg.m_cb_usb_status_init = NULL;
    usb_status_arg.cb_usb_status_init_arg = NULL;
    usb_statue_result.usb_speed_status = USB_STATUS_UNKNOWN;
	GC_TRACE("[iComNum%d] SwitchToHighSpeedComPort():enter enum preloader comport.", m_BromComNum);
    iRet = FlashTool_CheckUSBStatus(m_ft_api_handle, &usb_status_arg, &usb_statue_result);
    if (usb_statue_result.usb_speed_status != USB_FULL_SPEED) // If usb is not full speed status, do not switch.
    {
        GC_TRACE("[COM%d] ScanPreLoaderComPort(): The com port is in high speed, do not switch it.",m_BromComNum);
        return -1;
    }
	GC_TRACE("[iComNum%d] SwitchToHighSpeedComPort():FlashTool_CheckUSBStatus, usb_speed_status is %d", m_BromComNum, usb_statue_result.usb_speed_status);
   
    //get new comport of Preloader comport
    usb_setup_info.enable_hs = 1;
    //translate pid&vid str to hex
    sscanf(strVid.c_str(), "%x", &tempVidPid);
    usb_setup_info.vid = tempVidPid;
    sscanf(strPid.c_str(), "%x", &tempVidPid);
    usb_setup_info.pid = tempVidPid;
    if(usb_setup_info.pid == 0 || usb_setup_info.vid == 0)
    {
        usb_setup_info.pid = 0x2000;
        usb_setup_info.vid = 0x0E8D;
    }
    GC_TRACE("[iComNum%d] SwitchToHighSpeedComPort():Preloader pid = 0x%4X, vid =0x%4X", m_BromComNum, usb_setup_info.pid, usb_setup_info.vid);
    iRet = FlashTool_SetupUSBDL_EX(&m_ft_api_handle, &usb_setup_info);
    if( S_DONE != iRet )
    {
        GC_TRACE("[COM%d] SwitchComport(): [ERROR] Setup USB DL fail!,ret=%d",m_BromComNum,iRet);
        return iRet;
    }

    return iRet;
}
static void _enable_button(GRAPHICS_CONTROLLER *gc, uint32_t button_id, unsigned enable)
{
    PG_DISPLAY_SET *s          = gc->igs;
    BD_IG_PAGE     *page       = NULL;
    BD_IG_BUTTON   *button     = NULL;
    unsigned        page_id    = bd_psr_read(gc->regs, PSR_MENU_PAGE_ID);
    unsigned        cur_btn_id = bd_psr_read(gc->regs, PSR_SELECTED_BUTTON_ID);
    unsigned        bog_idx    = 0;

    GC_TRACE("_enable_button(#%d, %s)\n", button_id, enable ? "enable" : "disable");

    page = _find_page(&s->ics->interactive_composition, page_id);
    if (!page) {
        GC_TRACE("_enable_button(): unknown page #%d (have %d pages)\n",
              page_id, s->ics->interactive_composition.num_pages);
        return;
    }

    /* find correct button overlap group */
    button = _find_button_page(page, button_id, &bog_idx);
    if (!button) {
        GC_TRACE("_enable_button(): unknown button #%d (page #%d)\n", button_id, page_id);
        return;
    }

    if (enable) {
        if (gc->bog_data[bog_idx].enabled_button == cur_btn_id) {
            /* selected button goes to disabled state */
            bd_psr_write(gc->regs, PSR_SELECTED_BUTTON_ID, 0x10000|button_id);
        }
        gc->bog_data[bog_idx].enabled_button = button_id;

    } else {
        if (gc->bog_data[bog_idx].enabled_button == button_id) {
            gc->bog_data[bog_idx].enabled_button = 0xffff;
        }

        if (cur_btn_id == button_id) {
            bd_psr_write(gc->regs, PSR_SELECTED_BUTTON_ID, 0xffff);
        }
    }
}
static void _update_selected_button(GRAPHICS_CONTROLLER *gc)
{
    /* executed after IG command sequence terminates */
    unsigned button_id = bd_psr_read(gc->regs, PSR_SELECTED_BUTTON_ID);

    GC_TRACE("_update_selected_button(): currently enabled button is #%d\n", button_id);

    /* special case: triggered only after enable button disables selected button */
    if (button_id & 0x10000) {
        button_id &= 0xffff;
        _select_button(gc, button_id);
        GC_TRACE("_update_selected_button() -> #%d [last enabled]\n", button_id);
        return;
    }

    if (button_id == 0xffff) {
        button_id = _find_selected_button_id(gc);
        _select_button(gc, button_id);
    }
}
Example #11
0
File: gc.c Project: CRogers/obc
/* find_block -- find a free block of specified size */
static header *find_block(unsigned size, unsigned objsize) {
    header *h = NULL, *h2;
    int i = min(size/GC_PAGESIZE, BIG_BLOCK);

    ASSERT(size % GC_PAGESIZE == 0);

    do {
        for (headers(h2, free_list[i])) {
            /* This always succeeds for small blocks, and gives
            first-fit allocation for big blocks. */
            if (size <= h2->h_size) {
                h = h2;
                break;
            }
        }
        i++;
    } while (h == NULL && i <= BIG_BLOCK);

    if (h == NULL) {
        /* No suitable block was found.  Get a big chunk. */
        unsigned chunk = max(size, CHUNK_SIZE);
        GC_TRACE("[ex]");
        ASSERT(chunk % GC_PAGESIZE == 0);
        h = alloc_header();
        h->h_memory = (uchar *) get_memory(chunk);
        h->h_size = chunk;
        /* Add to the free list for merging and page table setup */
        h = free_block(h, FALSE);
    }

    ASSERT(h->h_memory != NULL && h->h_size >= size);
    unlink(h);

    if (size < h->h_size) {
        /* Split the block, and return the waste to the free
           list.  It's best to use header h for the waste: that
           way, we don't have to reset lots of page table
           entries when we chip a small piece off a big block. */
        h2 = alloc_header();
        h2->h_memory = h->h_memory;
        h2->h_size = size;
        page_setup(h2->h_memory, size, h2);

        h->h_memory += size;
        h->h_size -= size;
        make_free(h);

        h = h2;
    }

    h->h_objsize = objsize;
    h->h_epoch = gencount;
    return h;
}
int gc_decode_ts(GRAPHICS_CONTROLLER *gc, uint16_t pid, uint8_t *block, unsigned num_blocks, int64_t stc)
{
    if (!gc) {
        GC_TRACE("gc_decode_ts(): no graphics controller\n");
        return -1;
    }

    if (pid >= 0x1400 && pid < 0x1500) {
        /* IG stream */

        if (!gc->igp) {
            gc->igp = graphics_processor_init();
        }

        bd_mutex_lock(&gc->mutex);

        if (!graphics_processor_decode_ts(gc->igp, &gc->igs,
                                          pid, block, num_blocks,
                                          stc)) {
            /* no new complete display set */
            bd_mutex_unlock(&gc->mutex);
            return 0;
        }

        if (!gc->igs || !gc->igs->complete) {
            bd_mutex_unlock(&gc->mutex);
            return 0;
        }

        bd_mutex_unlock(&gc->mutex);

        return 1;
    }

    else if (pid >= 0x1200 && pid < 0x1300) {
        /* PG stream */
        if (!gc->pgp) {
            gc->pgp = graphics_processor_init();
        }
        graphics_processor_decode_ts(gc->pgp, &gc->pgs,
                                     pid, block, num_blocks,
                                     stc);

        if (!gc->pgs || !gc->pgs->complete) {
            return 0;
        }

        return 1;
    }

    return -1;
}
Example #13
0
int _fastcall TScanPort::ScanPreLoaderComPort(unsigned int iComNum, int index)
{
    int iRet = S_DONE;
    string friendlyName;
    string label;
    int number;
    COMPortUtils comFinder;
    int comportType;

    //============Step1 Download Da and connect dA===============================
    GC_TRACE("[iComNum%d] ScanPreLoaderComPort():Da Connect begin.", iComNum);
    iRet = DAConnect(iComNum);
    if(S_DONE != iRet){
        GC_TRACE("[iComNum%d] ScanPreLoaderComPort(): [ERROR] DAConnect fail!ret=%d", iComNum, iRet);
        return iRet;
    }
    //============Step2 change brom pid & vid to preloader pid & vid=============

    //Step2.1 First scan to get comport list before change preloader pid & vid
    GC_TRACE("<TScanPort> ScanPreLoaderComPort(): First scan...");
    comportType = PRELOADER_COMPORT;
    comFinder.ScanFriendlyNameByDDK(true, comportType);

    //Step2.2 change Brom vid & pid to Preloader pid&vid
    iRet = SwitchToHighSpeedComPort(comFinder.GetAndroidVid(), comFinder.GetPreloaderPid());
    if(S_DONE != iRet)
    {
        DADisConnect();
        return iRet;
    }

    //=============Step3 Scan Preloader comport==================================
    GC_TRACE("<TScanPort> Execute(): Scan preloader COM port for Channel[%d]...", index);
    while(!(*mpStopFlag))
    {
        if(comFinder.GetNewPortFriendlyName(friendlyName, comportType)){
            if( comFinder.ExtractCOMNumber(friendlyName, number)){
                GC_TRACE("<TScanPort> Execute(): Find new preloader COM port for Channel[%d]! COM%d, comportType = %d", index, number, comportType);
                mIndex = index;
                m_PreLoaderComNum = number;
                SyncUpdateCOMPort();
                break;
            }
        }
        Sleep(500);
    }

    //=============Step4 change comport from full speed to high speed comport=================
    iRet = FlashTool_ChangeCOM(&m_ft_api_handle, m_PreLoaderComNum);
	if(iRet != S_DONE)
	{
	    GC_TRACE("<TScanPort> Execute():: [ERROR] Change COM port fail!");
		return iRet;
	}
    DADisConnect();
    return iRet;
}
Example #14
0
void __fastcall TScanPort::ScanBromAndPreloader()
{
	bool * chnChecked = new bool[mArraySize];
    m_bIsDaConnecting = false;
	
    memcpy(chnChecked, mpIndexArray, mArraySize * sizeof(bool));
    //=====================Step1 Scan Brom Comport========================
    for(unsigned int iCycle = 0; (iCycle < mArraySize) && (!(*mpStopFlag));iCycle++){
        if(chnChecked[iCycle]){
            m_BromComNum = 0;
            m_PreLoaderComNum = 0;
	        mIndex = iCycle;
            //Scan brom comport success
            if(S_DONE == ScanBRomComPort(iCycle) && m_BromComNum != 0){
                GC_TRACE("<TScanPort> ScanBromAndPreloader(): ScanBRomComPort success!");
                //Step2 Scan Preloader comport
                if(S_DONE == ScanPreLoaderComPort(m_BromComNum,iCycle)){
                    SyncUpdateScanSuccess();
                    GC_TRACE("<TScanPort> ScanBromAndPreloader(): ScanPreLoaderComPort Success!");
                }
                else{
                    SyncUpdateScanFail();
                    GC_TRACE("<TScanPort> ScanBromAndPreloader(): ScanPreLoaderComPort fail!");
					break;
                }
            }
            else{
                SyncUpdateScanFail();
                GC_TRACE("<TScanPort> ScanBromAndPreloader(): ScanBRomComPort fail!");
				break;
            }
        }
    }
	
    delete [] chnChecked;
    SyncEnableUIForScan();
}
Example #15
0
/*
 *	Main entry point for the finalizer thread.
 */
static void _FinalizerThreadFunc(void *data)
{
	GC_TRACE("GC:_FinalizerThread: Finalizer thread started [thread:%d]\n", (int)ILThreadSelf());

	for (;;)
	{
		ILWaitOne(_FinalizerSignal, -1);

		GC_TRACE("GC:_FinalizerThread: Signal [thread:%d]\n", (int)ILThreadSelf());

		/* This *must* to be set before checking for !_FinalizersDisabled to prevent
		    a race with ILGCDisableFinalizers */

		_FinalizersRunning = 1;

		ILThreadMemoryBarrier();

		if (GC_should_invoke_finalizers() && !_FinalizersDisabled)
		{
			GC_TRACE("GC:_FinalizerThread: Finalizers running [thread:%d]\n", (int)ILThreadSelf());
			
			GC_invoke_finalizers();
			
			GC_TRACE("GC:_FinalizerThread: Finalizers finished [thread:%d]\n", (int)ILThreadSelf());
		}

		_FinalizersRunning = 0;

		ILThreadMemoryBarrier();
		
		if (_FinalizerStopFlag)
		{
			/* Exit finalizer thread after having invoked finalizers one last time */

			GC_TRACE("GC:_FinalizerThread: Finalizer thread finished [thread:%d]\n", (int)ILThreadSelf());

			ILWaitEventReset(_FinalizerSignal);
			/* Wake all waiting threads */
			ILWaitEventPulse(_FinalizerResponse);
			
			return;
		}

		GC_TRACE("GC:_FinalizerThread: Response [thread:%d]\n", (int)ILThreadSelf());

		ILWaitEventReset(_FinalizerSignal);

		/* Wake all waiting threads */
		ILWaitEventPulse(_FinalizerResponse);
	}
}
Example #16
0
void EfuseSettings::ReadEfuseSettings(void)
{
    AnsiString iniFileNameWithPath = NULL;
    AnsiString asPath = NULL;
	AnsiString as_str;

    if (getPathFromStr(Application->ExeName,asPath))
    {
        GC_TRACE("<EfuseSettings> ReadEfuseSettings(): the tool path is %s", asPath);
        iniFileNameWithPath = asPath + "Efuse.ini";
        if (!Check_FileExist(iniFileNameWithPath))
        {
            GC_TRACE("<EfuseSettings> ReadEfuseSettings(): Can not find Efuse.ini file. ");
            return;
        }
    }

    TIniFile *ini;
    try
    {
       ini = new TIniFile(iniFileNameWithPath);
       if(ini != NULL)
       {
           as_str  = ini->ReadString(EFUSE_SETTINGS, "Enable", "0");
           mEfuseEnable = atoi(as_str.c_str());
		   as_str  = ini->ReadString(EFUSE_SETTINGS, "SettingsEnable", "0");
           mEfuseSettingsEnable = atoi(as_str.c_str());
		   as_str  = ini->ReadString(EFUSE_SETTINGS, "LockEnable", "0");
           mEfuseLockEnable = atoi(as_str.c_str());
		   as_str  = ini->ReadString(EFUSE_SETTINGS, "ReadBackEnable", "0");
           mEfuseReadBackEnable = atoi(as_str.c_str());

		   //dump
		   GC_TRACE("<EfuseSettings> ReadEfuseSettings() the mEfuseEnable = %d .", mEfuseEnable);
		   GC_TRACE("<EfuseSettings> ReadEfuseSettings() the mEfuseSettingsEnable = %d .", mEfuseSettingsEnable);
		   GC_TRACE("<EfuseSettings> ReadEfuseSettings() the mEfuseLockEnable = %d .", mEfuseLockEnable);
		   GC_TRACE("<EfuseSettings> ReadEfuseSettings() the mEfuseReadBackEnable = %d .", mEfuseReadBackEnable);
		   
           delete ini;
       }
    }
    catch (...)
    {
        ShowMessage( "read setup file " + iniFileNameWithPath + " error");
        delete ini;
    }

/*
    TIniFile* efuseSettingsIni;
    TStringList* str_list = NULL;
    try {
		str_list = new TStringList;
		efuseSettingsIni = new TIniFile(iniFileNameWithPath.c_str());
		efuseSettingsIni->ReadSection(EFUSE_SETTINGS, str_list);

		if ( 4 > str_list->Count )
		{
			GC_TRACE("<EfuseSettings> ReadEfuseSettings() the config numbers is smaller than 4.");
			return;
		}

		this->mEfuseEnable = atoi(efuseSettingsIni->ReadString(EFUSE_SETTINGS, str_list->Strings[0], "0").c_str());
		GC_TRACE("<EfuseSettings> ReadEfuseSettings() the mEfuseEnable is %d .", this->mEfuseEnable);
		this->mEfuseSettingsEnable = atoi(efuseSettingsIni->ReadString(EFUSE_SETTINGS, str_list->Strings[1], "0").c_str());
		GC_TRACE("<EfuseSettings> ReadEfuseSettings() the mEfuseSettingsEnable is %d .", this->mEfuseSettingsEnable);
		this->mEfuseLockEnable = atoi(efuseSettingsIni->ReadString(EFUSE_SETTINGS, str_list->Strings[2], "0").c_str());
		GC_TRACE("<EfuseSettings> ReadEfuseSettings() the mEfuseLockEnable is %d .", this->mEfuseLockEnable);
		this->mEfuseReadBackEnable = atoi(efuseSettingsIni->ReadString(EFUSE_SETTINGS, str_list->Strings[3], "0").c_str());
		GC_TRACE("<EfuseSettings> ReadEfuseSettings() the mEfuseReadBackEnable is %d .", this->mEfuseReadBackEnable);

    } catch (const std::exception& ex) {
        if (NULL != str_list) {
            delete str_list;
            str_list = NULL;
        }
        if (NULL != efuseSettingsIni) {
            delete efuseSettingsIni;
            efuseSettingsIni = NULL;
        }
        GC_TRACE("<EfuseSettings> ReadEfuseSettings() failed, reason(%s).", ex.what());
    }

    if (NULL != str_list)
    {
        delete str_list;
        str_list = NULL;
    }
    if (NULL != efuseSettingsIni)
    {
        delete efuseSettingsIni;
        efuseSettingsIni = NULL;
    }*/
}
Example #17
0
	// 发送数据
	bool CCommunication::PendingSend(DWORD dwlen)
	{
		WSABUF			wsabuf;
		WSAOVERLAPPED	over;
		DWORD			dwSend;
		DWORD           dwTotalSend = 0;
		DWORD			dwFlags;
		DWORD			dwRet;
		BOOL			fPending;

		ZeroMemory(&over, sizeof(WSAOVERLAPPED));
		wsabuf.buf  = m_pbBuffer;
		wsabuf.len  = dwlen;
		over.hEvent = WSACreateEvent();
		if (over.hEvent == WSA_INVALID_EVENT)
		{
#ifdef _ZZYDEBUG
					GC_TRACE("Error5");
#endif
			CloseSocket();
			return false;
		}

		while(1)
		{
			fPending = FALSE;
			// 发送数据
			int nRet = WSASend(m_WorkSocket, &wsabuf, 1, &dwSend, 0, &over, NULL);
			if (nRet != 0)
			{
				if (WSAGetLastError() != WSA_IO_PENDING)
				{
#ifdef _ZZYDEBUG
					GC_TRACE("Error4:%d",WSAGetLastError());
#endif
					WSACloseEvent(over.hEvent);
					CloseSocket();
					return false;
				}
				else
				{
					fPending = TRUE;
				}
			}
			else
			{
				fPending = TRUE;
			}

			// 发送I/O操作未结束
			if (fPending)
			{
				// 等待发送I/O操作接束
				dwRet = WSAWaitForMultipleEvents(1, &(over.hEvent), FALSE, m_nTimeOut*1000, FALSE);
				if (dwRet==WSA_WAIT_FAILED || dwRet==WAIT_TIMEOUT)
				{
#ifdef _ZZYDEBUG
					if (dwRet==WSA_WAIT_FAILED)
						GC_TRACE("Error1");
					else
						GC_TRACE("Error6");

#endif
					WSACloseEvent(over.hEvent);
					CloseSocket();
					return false;
				}

				WSAResetEvent(over.hEvent);

				// 判断重叠操作是否成功
				if (!WSAGetOverlappedResult(m_WorkSocket,	&over, &dwSend,	FALSE, &dwFlags))
				{
#ifdef _ZZYDEBUG
					GC_TRACE("Error2");
#endif
					WSACloseEvent(over.hEvent);
					CloseSocket();
					return false;
				}
				else
				{
					if (dwSend == 0)
					{
#ifdef _ZZYDEBUG
					GC_TRACE("Error3");
#endif
						WSACloseEvent(over.hEvent);
						CloseSocket();
						return false;
					}

					// 计算剩余发送字节数
					wsabuf.len -= dwSend;
					dwTotalSend += dwSend;

					if(wsabuf.len <= 0)
					{
						break;
					}
					else
					{
						wsabuf.buf += dwSend;
					}
				}
			}
		}//while (1) 发送未结束

		// 发送完成
		if(over.hEvent)
		{
			WSACloseEvent(over.hEvent);
		}
		return true;
	}
static int _user_input(GRAPHICS_CONTROLLER *gc, uint32_t key, GC_NAV_CMDS *cmds)
{
    PG_DISPLAY_SET *s          = gc->igs;
    BD_IG_PAGE     *page       = NULL;
    unsigned        page_id    = bd_psr_read(gc->regs, PSR_MENU_PAGE_ID);
    unsigned        cur_btn_id = bd_psr_read(gc->regs, PSR_SELECTED_BUTTON_ID);
    unsigned        new_btn_id = cur_btn_id;
    unsigned        ii;
    int             activated_btn_id = -1;

    if (s->ics->interactive_composition.ui_model == IG_UI_MODEL_POPUP && !gc->popup_visible) {
        GC_TRACE("_user_input(): popup menu not visible\n");
        return -1;
    }
    if (!gc->ig_drawn) {
        GC_ERROR("_user_input(): menu not visible\n");
        return -1;
    }

    GC_TRACE("_user_input(%d)\n", key);

    page = _find_page(&s->ics->interactive_composition, page_id);
    if (!page) {
        GC_ERROR("_user_input(): unknown page id %d (have %d pages)\n",
              page_id, s->ics->interactive_composition.num_pages);
        return -1;
    }

    if (key == BD_VK_MOUSE_ACTIVATE) {
        if (!gc->valid_mouse_position) {
            GC_TRACE("_user_input(): BD_VK_MOUSE_ACTIVATE outside of valid buttons\n");
            return -1;
        }
        key = BD_VK_ENTER;
    }

    for (ii = 0; ii < page->num_bogs; ii++) {
        BD_IG_BOG *bog      = &page->bog[ii];
        unsigned   valid_id = gc->bog_data[ii].enabled_button;
        BD_IG_BUTTON *button = _find_button_bog(bog, valid_id);
        if (!button) {
            continue;
        }

        /* numeric select */
        if (VK_IS_NUMERIC(key)) {
            if (button->numeric_select_value == VK_TO_NUMBER(key)) {
                new_btn_id = button->id;
            }
        }

        /* cursor keys */
        else if (VK_IS_CURSOR(key) || key == BD_VK_ENTER) {
            if (button->id == cur_btn_id) {
                switch(key) {
                    case BD_VK_UP:
                        new_btn_id = button->upper_button_id_ref;
                        break;
                    case BD_VK_DOWN:
                        new_btn_id = button->lower_button_id_ref;
                        break;
                    case BD_VK_LEFT:
                        new_btn_id = button->left_button_id_ref;
                        break;
                    case BD_VK_RIGHT:
                        new_btn_id = button->right_button_id_ref;
                        break;
                    case BD_VK_ENTER:
                        activated_btn_id = cur_btn_id;

                        cmds->num_nav_cmds = button->num_nav_cmds;
                        cmds->nav_cmds     = button->nav_cmds;
                        cmds->sound_id_ref = button->activated_sound_id_ref;
                        break;
                    default:;
                }
            }

            if (new_btn_id != cur_btn_id) {
                BD_IG_BUTTON *new_button = _find_button_page(page, new_btn_id, NULL);
                if (new_button) {
                    cmds->sound_id_ref = new_button->selected_sound_id_ref;
                }
            }
        }
    }

    /* render page ? */
    if (new_btn_id != cur_btn_id || activated_btn_id >= 0) {

        _select_button(gc, new_btn_id);

        _render_page(gc, activated_btn_id, cmds);

        /* found one*/
        return 1;
    }

    return 0;
}
static void _set_button_page(GRAPHICS_CONTROLLER *gc, uint32_t param)
{
    unsigned page_flag   = param & 0x80000000;
    unsigned effect_flag = param & 0x40000000;
    unsigned button_flag = param & 0x20000000;
    unsigned page_id     = (param >> 16) & 0xff;
    unsigned button_id   = param & 0xffff;
    unsigned bog_idx     = 0;

    PG_DISPLAY_SET *s      = gc->igs;
    BD_IG_PAGE     *page   = NULL;
    BD_IG_BUTTON   *button = NULL;

    GC_TRACE("_set_button_page(0x%08x): page flag %d, id %d, effects %d   button flag %d, id %d\n",
          param, !!page_flag, page_id, !!effect_flag, !!button_flag, button_id);

    /* 10.4.3.4 (D) */

    if (!page_flag && !button_flag) {
        return;
    }

    if (page_flag) {

        /* current page --> command is ignored */
        if (page_id == bd_psr_read(gc->regs, PSR_MENU_PAGE_ID)) {
            GC_TRACE("  page is current\n");
            return;
        }

        page = _find_page(&s->ics->interactive_composition, page_id);

        /* invalid page --> command is ignored */
        if (!page) {
            GC_TRACE("  page is invalid\n");
            return;
        }

        /* page changes */

        _select_page(gc, page_id);

    } else {
        /* page does not change */
        page_id = bd_psr_read(gc->regs, PSR_MENU_PAGE_ID);
        page    = _find_page(&s->ics->interactive_composition, page_id);

        if (!page) {
            GC_ERROR("_set_button_page(): PSR_MENU_PAGE_ID refers to unknown page %d\n", page_id);
            return;
        }
    }

    if (button_flag) {
        /* find correct button and overlap group */
        button = _find_button_page(page, button_id, &bog_idx);

        if (!page_flag) {
            if (!button) {
                /* page not given, invalid button --> ignore command */
                GC_TRACE("  button is invalid\n");
                return;
            }
            if (button_id == bd_psr_read(gc->regs, PSR_SELECTED_BUTTON_ID)) {
                /* page not given, current button --> ignore command */
                GC_TRACE("  button is current\n");
                return;
            }
        }
    }

    if (button) {
        gc->bog_data[bog_idx].enabled_button = button_id;
        _select_button(gc, button_id);
    }

    _render_page(gc, 0xffff, NULL); /* auto action not triggered yet */
}
static void _render_button(GRAPHICS_CONTROLLER *gc, BD_IG_BUTTON *button, BD_PG_PALETTE *palette,
                           int state, BOG_DATA *bog_data)
{
    BD_PG_OBJECT *object = _find_object_for_button(gc->igs, button, state, bog_data);
    if (!object) {
        GC_TRACE("_render_button(#%d): object (state %d) not found\n", button->id, state);

        _clear_bog_area(gc, bog_data);

        return;
    }

    /* object already rendered ? */
    if (bog_data->visible_object_id == object->id &&
        bog_data->x == button->x_pos && bog_data->y == button->y_pos &&
        bog_data->w == object->width && bog_data->h == object->height) {

        GC_TRACE("skipping already rendered button #%d (object #%d at %d,%d %dx%d)\n",
                 button->id, object->id,
                 button->x_pos, button->y_pos, object->width, object->height);

        return;
    }

    /* new object is smaller than already drawn one ? -> need to render background */
    if (bog_data->w > object->width ||
        bog_data->h > object->height) {

        /* make sure we won't wipe other buttons */
        unsigned ii, skip = 0;
        for (ii = 0; &gc->bog_data[ii] != bog_data; ii++) {
            if (_areas_overlap(bog_data, &gc->bog_data[ii]))
                skip = 1;
            /* FIXME: clean non-overlapping area */
        }

        GC_TRACE("object size changed, %sclearing background at %d,%d %dx%d\n",
                 skip ? " ** NOT ** " : "",
                 bog_data->x, bog_data->y, bog_data->w, bog_data->h);

        if (!skip) {
            _clear_bog_area(gc, bog_data);
        }
    }

    GC_TRACE("render button #%d using object #%d at %d,%d %dx%d\n",
             button->id, object->id,
             button->x_pos, button->y_pos, object->width, object->height);

    _render_object(gc, -1, BD_OVERLAY_IG,
                   button->x_pos, button->y_pos,
                   object, palette);

    bog_data->x = button->x_pos;
    bog_data->y = button->y_pos;
    bog_data->w = object->width;
    bog_data->h = object->height;
    bog_data->visible_object_id = object->id;

    gc->ig_drawn = 1;
    gc->ig_dirty = 1;
}
static int _render_page(GRAPHICS_CONTROLLER *gc,
                         unsigned activated_button_id,
                         GC_NAV_CMDS *cmds)
{
    PG_DISPLAY_SET *s       = gc->igs;
    BD_IG_PAGE     *page    = NULL;
    BD_PG_PALETTE  *palette = NULL;
    unsigned        page_id = bd_psr_read(gc->regs, PSR_MENU_PAGE_ID);
    unsigned        ii;
    unsigned        selected_button_id = bd_psr_read(gc->regs, PSR_SELECTED_BUTTON_ID);

    if (s->ics->interactive_composition.ui_model == IG_UI_MODEL_POPUP && !gc->popup_visible) {

        if (gc->ig_open) {
            GC_TRACE("_render_page(): popup menu not visible\n");
            _close_osd(gc, BD_OVERLAY_IG);
            return 1;
        }

        return 0;
    }

    page = _find_page(&s->ics->interactive_composition, page_id);
    if (!page) {
        GC_ERROR("_render_page: unknown page id %d (have %d pages)\n",
              page_id, s->ics->interactive_composition.num_pages);
        return -1;
    }

    palette = _find_palette(s, page->palette_id_ref);
    if (!palette) {
        GC_ERROR("_render_page: unknown palette id %d (have %d palettes)\n",
              page->palette_id_ref, s->num_palette);
        return -1;
    }

    GC_TRACE("rendering page #%d using palette #%d. page has %d bogs\n",
          page->id, page->palette_id_ref, page->num_bogs);

    if (!gc->ig_open) {
        _open_osd(gc, BD_OVERLAY_IG,
                  s->ics->video_descriptor.video_width,
                  s->ics->video_descriptor.video_height);
    }


    for (ii = 0; ii < page->num_bogs; ii++) {
        BD_IG_BOG    *bog      = &page->bog[ii];
        unsigned      valid_id = gc->bog_data[ii].enabled_button;
        BD_IG_BUTTON *button;

        button = _find_button_bog(bog, valid_id);

        if (!button) {
            GC_TRACE("_render_page(): bog %d: button %d not found\n", ii, valid_id);

            // render background
            _clear_bog_area(gc, &gc->bog_data[ii]);

        } else if (button->id == activated_button_id) {
            GC_TRACE("    button #%d activated\n", button->id);

            _render_button(gc, button, palette, BTN_ACTIVATED, &gc->bog_data[ii]);

        } else if (button->id == selected_button_id) {

            if (button->auto_action_flag && !gc->auto_action_triggered) {
                if (cmds) {
                    GC_TRACE("   auto-activate #%d\n", button->id);

                    cmds->num_nav_cmds = button->num_nav_cmds;
                    cmds->nav_cmds     = button->nav_cmds;

                    gc->auto_action_triggered = 1;
                } else {
                    GC_ERROR("   auto-activate #%d not triggered (!cmds)\n", button->id);
                }

                _render_button(gc, button, palette, BTN_ACTIVATED, &gc->bog_data[ii]);

            } else {
                _render_button(gc, button, palette, BTN_SELECTED, &gc->bog_data[ii]);
            }

        } else {
            _render_button(gc, button, palette, BTN_NORMAL, &gc->bog_data[ii]);

        }
    }

    if (gc->ig_dirty) {
        _flush_osd(gc, BD_OVERLAY_IG, -1);
        gc->ig_dirty = 0;
        return 1;
    }

    return 0;
}
Example #22
0
/*
 * Notify the finalization thread that there is work to do.
 */
static int PrivateGCNotifyFinalize(int timeout, int ignoreDisabled)
{
	int result;
	
	if (_FinalizersDisabled && !ignoreDisabled)
	{
		return 0;
	}

	/* Prevent recursive finalization */
	if (_FinalizersRunningSynchronously || ILThreadSelf() == _FinalizerThread)
	{	
		return 0;
	}

#ifdef GC_TRY_INVOKE_SYNCHRONOUSLY

	/* Try to invoke synchronously (for performance & single threaded systems) */
	if (_InvokeFinalizersSynchronously() == 0)
	{
		return 0;
	}
	
#endif

	/* There is no finalizer thread!
	   We've already attempted to invoke synchronously (above) so just exit. */
	if (_FinalizerThread == 0)
	{
		return 0;
	}
	
	/* Finalizers need to be run on a seperate thread.
	   Start the finalizer thread if it hasn't been started */
	if (!_FinalizerThreadStarted)
	{
		_ILMutexLock(&_FinalizerLock);
		
		if (!_FinalizerThreadStarted)
		{
			if (ILThreadStart(_FinalizerThread) == 0)
			{
				/* Couldn't create the finalizer thread */

				GC_TRACE("PrivateGCInvokeFinalizers: Couldn't " \
						 "start finalizer thread [thread: %d]\n",
						 (int)ILThreadSelf());
				
				_ILMutexUnlock(&_FinalizerLock);

				return 0;
			}

			_FinalizerThreadStarted = 1;
		}

		_ILMutexUnlock(&_FinalizerLock);
	}

	/* Signal the finalizer thread */

	GC_TRACE("PrivateGCInvokeFinalizers: Invoking finalizers " \
			"and waiting [thread: %d]\n", (int)ILThreadSelf());

	result = ILSignalAndWait(_FinalizerSignal, _FinalizerResponse, timeout);
	
	GC_TRACE("PrivateGCInvokeFinalizers: Finalizers finished[thread: %d]\n", (int)ILThreadSelf());

	return result;
}
Example #23
0
int __fastcall TScanPort::DAConnect(const int iComport)
{
    int iRet = S_DONE;
    unsigned char iConnetComNum = iComport;
    int force_charge = FORCE_CHARGE_ON;

    if(MainForm->m_miDADLNoBattery->Checked)
    {
        force_charge = FORCE_CHARGE_ON;
    }
    else if(MainForm->m_miDADLBattery->Checked)
    {
        force_charge = FORCE_CHARGE_OFF;
    }
    else if(MainForm->m_miDADLAutoDetect->Checked)
    {
        force_charge = FORCE_CHARGE_AUTO;
    }

    /* set FlashTool_Connect_Arg */
    m_sConnArg.m_com_ms_read_timeout  =  COM_DEFAULT_TIMEOUT;
    m_sConnArg.m_com_ms_write_timeout =  COM_DEFAULT_TIMEOUT;
    BootArgSetting(m_sConnArg.m_boot_arg);
    m_sConnArg.m_cb_security_pre_process_notify = NULL;
    m_sConnArg.m_cb_security_pre_process_notify_arg = NULL;
    m_sConnArg.m_nor_chip_select[0] = CS_0;
    m_sConnArg.m_nor_chip_select[1] = CS_WITH_DECODER;
    m_sConnArg.m_nand_chip_select   = m_sDnParam.s_bbchip_op.b_enable_nfi_cs1?CS_1:CS_0;
    m_sConnArg.m_p_nand_acccon      = NULL  ;
    m_sConnArg.m_boot_arg.m_bmt_block_count = frmMultiLoad->m_BMT_blocks;
    m_sConnArg.m_storage_type = frmMultiLoad->m_Storage_Type;// m_storage_type
    m_sConnArg.m_force_charge = force_charge;
    DL_HANDLE_T *p_dl_handle = MainForm->Get_DlHandle(0);
    m_sConnArg.m_p_dl_handle = *p_dl_handle;

    /* connect to target */
    iRet = FlashTool_Connect(
                            /*index + m_sDnParam.i_FirstComNo,*/
                            iConnetComNum,
                            &m_sConnArg,
                            &m_sConnResult,
                            NULL,
                            MainForm->_t_manager.Get_stop_flag_addr(mIndex),
                            &m_ft_api_handle);
    if(S_DONE != iRet)
    {
        GC_TRACE("[COM%d] DAConnect(): [ERROR] DA connect fail!", iConnetComNum);
        return iRet;
    }
	
    m_bIsDaConnecting = true;
    FlashTool_ChangeBaudrate_Arg  ft_cb_arg;
    ft_cb_arg.m_baudrate                       = MainForm->Get_Baudrate();
    ft_cb_arg.m_baudrate_full_sync_count       = 1;
    ft_cb_arg.m_cb_set_high_speed_baudrate     = NULL;
    ft_cb_arg.m_cb_set_high_speed_baudrate_arg = NULL;

    iRet = FlashTool_ChangeBaudrate(m_ft_api_handle, &ft_cb_arg);
    if(S_DONE != iRet)
    {
        GC_TRACE("[iComNum%d] DAConnect(): [ERROR] FlashTool_ChangeBaudrate fail!", iConnetComNum);
        DADisConnect();
        return iRet;
    }

    return iRet;
}
Example #24
0
ZEND_API int zend_gc_collect_cycles(void)
{
	int count = 0;

	if (GC_G(num_roots)) {
		gc_root_buffer *current, *last;
		zend_refcounted *p;
		uint32_t gc_flags = 0;
		uint32_t idx, end;
		gc_stack stack;

		stack.prev = NULL;
		stack.next = NULL;

		if (GC_G(gc_active)) {
			return 0;
		}

		GC_TRACE("Collecting cycles");
		GC_G(gc_runs)++;
		GC_G(gc_active) = 1;

		GC_TRACE("Marking roots");
		gc_mark_roots(&stack);
		GC_TRACE("Scanning roots");
		gc_scan_roots(&stack);

		GC_TRACE("Collecting roots");
		count = gc_collect_roots(&gc_flags, &stack);

		gc_stack_free(&stack);

		if (!GC_G(num_roots)) {
			/* nothing to free */
			GC_TRACE("Nothing to free");
			GC_G(gc_active) = 0;
			return 0;
		}

		end = GC_G(first_unused);

		if (gc_flags & GC_HAS_DESTRUCTORS) {
			uint32_t *refcounts;

			GC_TRACE("Calling destructors");

			// TODO: may be use emalloc() ???
			refcounts = pemalloc(sizeof(uint32_t) * end, 1);

			/* Remember reference counters before calling destructors */
			idx = GC_FIRST_ROOT;
			current = GC_IDX2PTR(GC_FIRST_ROOT);
			while (idx != end) {
				if (GC_IS_GARBAGE(current->ref)) {
					p = GC_GET_PTR(current->ref);
					refcounts[idx] = GC_REFCOUNT(p);
				}
				current++;
				idx++;
			}

			/* Call destructors
			 *
			 * The root buffer might be reallocated during destructors calls,
			 * make sure to reload pointers as necessary. */
			idx = GC_FIRST_ROOT;
			while (idx != end) {
				current = GC_IDX2PTR(idx);
				if (GC_IS_GARBAGE(current->ref)) {
					p = GC_GET_PTR(current->ref);
					if (GC_TYPE(p) == IS_OBJECT
					 && !(OBJ_FLAGS(p) & IS_OBJ_DESTRUCTOR_CALLED)) {
						zend_object *obj = (zend_object*)p;

						GC_TRACE_REF(obj, "calling destructor");
						GC_ADD_FLAGS(obj, IS_OBJ_DESTRUCTOR_CALLED);
						if (obj->handlers->dtor_obj != zend_objects_destroy_object
								|| obj->ce->destructor) {
							GC_ADDREF(obj);
							obj->handlers->dtor_obj(obj);
							GC_DELREF(obj);
						}
					}
				}
				idx++;
			}

			/* Remove values captured in destructors */
			idx = GC_FIRST_ROOT;
			current = GC_IDX2PTR(GC_FIRST_ROOT);
			while (idx != end) {
				if (GC_IS_GARBAGE(current->ref)) {
					p = GC_GET_PTR(current->ref);
					if (GC_REFCOUNT(p) > refcounts[idx]) {
						gc_remove_nested_data_from_buffer(p, current);
					}
				}
				current++;
				idx++;
			}

			pefree(refcounts, 1);

			if (GC_G(gc_protected)) {
				/* something went wrong */
				return 0;
			}
		}

		/* Destroy zvals */
		GC_TRACE("Destroying zvals");
		GC_G(gc_protected) = 1;
		current = GC_IDX2PTR(GC_FIRST_ROOT);
		last = GC_IDX2PTR(GC_G(first_unused));
		while (current != last) {
			if (GC_IS_GARBAGE(current->ref)) {
				p = GC_GET_PTR(current->ref);
				GC_TRACE_REF(p, "destroying");
				if (GC_TYPE(p) == IS_OBJECT) {
					zend_object *obj = (zend_object*)p;

					EG(objects_store).object_buckets[obj->handle] = SET_OBJ_INVALID(obj);
					GC_TYPE_INFO(obj) = IS_NULL |
						(GC_TYPE_INFO(obj) & ~GC_TYPE_MASK);
					if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) {
						GC_ADD_FLAGS(obj, IS_OBJ_FREE_CALLED);
						GC_ADDREF(obj);
						obj->handlers->free_obj(obj);
						GC_DELREF(obj);
					}

					ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(obj->handle);
					current->ref = GC_MAKE_GARBAGE(((char*)obj) - obj->handlers->offset);
				} else if (GC_TYPE(p) == IS_ARRAY) {
					zend_array *arr = (zend_array*)p;

					GC_TYPE_INFO(arr) = IS_NULL |
						(GC_TYPE_INFO(arr) & ~GC_TYPE_MASK);

					/* GC may destroy arrays with rc>1. This is valid and safe. */
					HT_ALLOW_COW_VIOLATION(arr);

					zend_hash_destroy(arr);
				}
			}
			current++;
		}

		/* Free objects */
		current = GC_IDX2PTR(GC_FIRST_ROOT);
		while (current != last) {
			if (GC_IS_GARBAGE(current->ref)) {
				p = GC_GET_PTR(current->ref);
				GC_LINK_UNUSED(current);
				GC_G(num_roots)--;
				efree(p);
			}
			current++;
		}

		GC_TRACE("Collection finished");
		GC_G(collected) += count;
		GC_G(gc_protected) = 0;
		GC_G(gc_active) = 0;
	}

	gc_compact();

	return count;
}
int gc_run(GRAPHICS_CONTROLLER *gc, gc_ctrl_e ctrl, uint32_t param, GC_NAV_CMDS *cmds)
{
    int result = -1;

    if (cmds) {
        cmds->num_nav_cmds = 0;
        cmds->nav_cmds     = NULL;
        cmds->sound_id_ref = -1;
        cmds->status       = GC_STATUS_NONE;
    }

    if (!gc) {
        GC_TRACE("gc_run(): no graphics controller\n");
        return result;
    }

    bd_mutex_lock(&gc->mutex);

    /* always accept reset */
    switch (ctrl) {
        case GC_CTRL_RESET:
            _gc_reset(gc);

            bd_mutex_unlock(&gc->mutex);
            return 0;

        default:;
    }

    /* other operations require complete display set */
    if (!gc->igs || !gc->igs->ics || !gc->igs->complete) {
        GC_TRACE("gc_run(): no interactive composition\n");
        bd_mutex_unlock(&gc->mutex);
        return result;
    }

    switch (ctrl) {

        case GC_CTRL_SET_BUTTON_PAGE:
            _set_button_page(gc, param);
            break;

        case GC_CTRL_VK_KEY:
            if (param != BD_VK_POPUP) {
                result = _user_input(gc, param, cmds);
                break;
            }
            param = !gc->popup_visible;
            /* fall thru (BD_VK_POPUP) */

        case GC_CTRL_POPUP:
            if (gc->igs->ics->interactive_composition.ui_model != IG_UI_MODEL_POPUP) {
                /* not pop-up menu */
                break;
            }

            gc->popup_visible = !!param;

            if (gc->popup_visible) {
                _select_page(gc, 0);
            }

            /* fall thru */

        case GC_CTRL_NOP:
            result = _render_page(gc, 0xffff, cmds);
            break;

        case GC_CTRL_INIT_MENU:
            _select_page(gc, 0);
            _render_page(gc, 0xffff, cmds);
            break;

        case GC_CTRL_IG_END:
            _update_selected_button(gc);
            _render_page(gc, 0xffff, cmds);
            break;

        case GC_CTRL_ENABLE_BUTTON:
            _enable_button(gc, param, 1);
            break;

        case GC_CTRL_DISABLE_BUTTON:
            _enable_button(gc, param, 0);
            break;

        case GC_CTRL_MOUSE_MOVE:
            result = _mouse_move(gc, param >> 16, param & 0xffff, cmds);
            break;

        case GC_CTRL_RESET:
            /* already handled */
            break;
    }

    if (cmds) {
        if (gc->igs->ics->interactive_composition.ui_model == IG_UI_MODEL_POPUP) {
            cmds->status |= GC_STATUS_POPUP;
        }
        if (gc->ig_drawn) {
            cmds->status |= GC_STATUS_MENU_OPEN;
        }
    }

    bd_mutex_unlock(&gc->mutex);

    return result;
}
static int _mouse_move(GRAPHICS_CONTROLLER *gc, unsigned x, unsigned y, GC_NAV_CMDS *cmds)
{
    PG_DISPLAY_SET *s          = gc->igs;
    BD_IG_PAGE     *page       = NULL;
    unsigned        page_id    = bd_psr_read(gc->regs, PSR_MENU_PAGE_ID);
    unsigned        cur_btn_id = bd_psr_read(gc->regs, PSR_SELECTED_BUTTON_ID);
    unsigned        new_btn_id = 0xffff;
    unsigned        ii;

    gc->valid_mouse_position = 0;

    if (!gc->ig_drawn) {
        GC_TRACE("_mouse_move(): menu not visible\n");
        return -1;
    }

    page = _find_page(&s->ics->interactive_composition, page_id);
    if (!page) {
        GC_ERROR("_mouse_move(): unknown page #%d (have %d pages)\n",
              page_id, s->ics->interactive_composition.num_pages);
        return -1;
    }

    for (ii = 0; ii < page->num_bogs; ii++) {
        BD_IG_BOG    *bog      = &page->bog[ii];
        unsigned      valid_id = gc->bog_data[ii].enabled_button;
        BD_IG_BUTTON *button   = _find_button_bog(bog, valid_id);

        if (!button)
            continue;

        if (x < button->x_pos || y < button->y_pos)
            continue;

        /* Check for SELECTED state object (button that can be selected) */
        BD_PG_OBJECT *object = _find_object_for_button(s, button, BTN_SELECTED, NULL);
        if (!object)
            continue;

        if (x >= button->x_pos + object->width || y >= button->y_pos + object->height)
            continue;

        /* mouse is over button */
        gc->valid_mouse_position = 1;

        /* is button already selected? */
        if (button->id == cur_btn_id) {
            return 1;
        }

        new_btn_id = button->id;

        if (cmds) {
            cmds->sound_id_ref = button->selected_sound_id_ref;
        }

        break;
    }

    if (new_btn_id != 0xffff) {
        _select_button(gc, new_btn_id);

        _render_page(gc, -1, cmds);
    }

    return gc->valid_mouse_position;
}