CAudioReader::CAudioReader(CAudioSource *source, AudioTrack *info)
{
	m_Source = source;
	m_Info = info;
	m_MediaInfo = info->m_Media;
	m_DestSampleRate = source->m_SampleRate;
	m_DestChannels = source->m_Channels;
	m_DestPacketBytes = source->m_PacketBytes;
	
	if (m_MediaInfo->m_IsPlanar)
	{
		m_SourceChannels = m_MediaInfo->m_nChannel;
		m_SourcePacketBytes = av_get_bytes_per_sample((enum AVSampleFormat)m_MediaInfo->m_SampleFormat);
	}
	else
	{
		m_SourceChannels = 1;
		m_SourcePacketBytes = m_MediaInfo->m_nChannel * av_get_bytes_per_sample((enum AVSampleFormat)m_MediaInfo->m_SampleFormat);
	}
	m_SourceSampleRate = m_MediaInfo->m_SampleRate;
	
	for(int i = 0; i < m_SourceChannels; i++)
	{
		m_hFiles[i] = CreateFile(m_MediaInfo->m_AudioTmpFile[i],
			GENERIC_READ,
			FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,                    
			NULL,                 
			OPEN_EXISTING,        
			FILE_ATTRIBUTE_NORMAL,
			NULL);
	}

	if (
		(m_MediaInfo->m_SampleRate != m_Source->m_SampleRate) ||
		(m_MediaInfo->m_nChannel != m_Source->m_Channels) ||
		(m_MediaInfo->m_SampleFormat != m_Source->m_SampleFormat) ||
		(m_MediaInfo->m_channel_layout != m_Source->m_Layout)
		)
	{
		swr_context =
		swr_alloc_set_opts(NULL,
						   m_Source->m_Layout, (AVSampleFormat)source->m_SampleFormat, m_Source->m_SampleRate,
						   m_MediaInfo->m_channel_layout, (AVSampleFormat)m_MediaInfo->m_SampleFormat, m_MediaInfo->m_SampleRate,
						   0, NULL);
		swr_init(swr_context);

		for(int i = 0; i < m_SourceChannels; i++)
		{
			m_ReadBuffer[i] = (uint8_t *)MemoryAlloc(m_SourceSampleRate * m_SourcePacketBytes);
		}

		for(int i = 0; i < m_DestChannels; i++)
		{
			m_ResampleBuffer[i] = (uint8_t *)MemoryAlloc(m_DestSampleRate * m_DestPacketBytes * 2);
		}
	}

	ResetStartStop();
}
void CInfoDecoder::OnAudioStreamStart(int64_t pts)
{
	m_MediaInfo->m_AudioStartPts = pts;
	if (pts)
	{
		m_AudioTotalSampes = pts * audio_sample_rate / AV_TIME_BASE_LL;
		int32_t n = (int32_t)(m_AudioTotalSampes * m_AudioSampleBytes);
		int32_t mutValue;
		if ((audio_format == AV_SAMPLE_FMT_U8) || (audio_format == AV_SAMPLE_FMT_U8P))
		{
			mutValue = 0x80;
		}
		else
		{
			mutValue = 0;
		}
		char *data = (char *)MemoryAlloc(n);
		memset(data, mutValue, n);
		for(int i = 0; i < m_AudioFiles; i++)
		{
			DWORD dwWriten;
			WriteFile(m_AudioTmpFile[i], data, n, &dwWriten, NULL);
		}
		MemoryFree(data);
	}
}
ClipInfo::ClipInfo(MediaInfo *info, HWND hwndMessage)
{
	
	m_AudioTrack[0].m_Media = info;
	m_MediaInfo = info;
	m_hwndMessage = hwndMessage;

	wchar_t Name[MAX_PATH];
	StringCchCopy(Name, MAX_PATH, info->m_szFileName);
	PathStripPath(Name);
	PathRemoveExtension(Name);
	StringCchCopy(m_Name, MAX_PATH, Name);
	for(int i = 0; i < VIDEO_FILTER_COUNT; i++)
	{
		m_Filters[i].m_id = VideoFilterTemplates[i].m_ClsID;
		m_Filters[i].m_Size = VideoFilterTemplates[i].m_cbParameter;
		if (VideoFilterTemplates[i].m_cbParameter)
		{
			m_Filters[i].m_Parameter = MemoryAlloc(VideoFilterTemplates[i].m_cbParameter);
			CopyMemory(m_Filters[i].m_Parameter, VideoFilterTemplates[i].m_pParameter, VideoFilterTemplates[i].m_cbParameter);
		}
		else
		{
			m_Filters[i].m_Parameter = NULL;
		}
	}

	m_Subtitle = new CSubtitle();
}
Example #4
0
BOOL ReceiveData(HANDLE hPipe, LPVOID* lppData, LPDWORD dataSize)
{
    DWORD read;
    DWORD size;
    LPVOID lpData;
    BOOL result;

    if (!ReceiveDword(hPipe, &size))
        return FALSE;

    lpData = MemoryAlloc(size, 1, FALSE);
    
    if (lpData == NULL)
        return FALSE;

    result = ReadFile(hPipe, lpData, size, &read, NULL);

    if (result && read != size)
    {
        result = FALSE;
        SetLastError(ERROR_PIPE_DATA_SIZE_MISMATCH);
    }

    if (!result) {
        MemoryFree(lpData);
        return FALSE;
    }

    *dataSize = size;
    *lppData = lpData;
    return TRUE;
}
Example #5
0
list_node_t* LinkedListCreateNode(uint_t numBytes)
{
    list_node_t* node = (list_node_t*)MemoryAlloc("linked list node", sizeof(list_node_t) + numBytes);
    if (!node)
    {
        return NULL;
    }

    ZeroMemory(node, sizeof(list_node_t) + numBytes);

    return node;
}
Example #6
0
/**
 * Changes the size of a specified memory object and re-allocate it if necessary.
 * @param pMemNode		Node of the memory object
 * @param size			New size of block
 */
void MemoryReAlloc(MEM_NODE *pMemNode, long size) {
	MEM_NODE *pNew;

	// validate mnode pointer
	assert(pMemNode >= mnodeList && pMemNode <= mnodeList + NUM_MNODES - 1);

	// align the size to machine boundary requirements
	size = (size + sizeof(void *) - 1) & ~(sizeof(void *) - 1);

	// validate the size
	assert(size);

	if (size != pMemNode->size) {
		// make sure memory object is discarded and not locked
		assert(pMemNode->flags == (DWM_USED | DWM_DISCARDED));
		assert(pMemNode->size == 0);

		// unlink the mnode from the current heap
		pMemNode->pNext->pPrev = pMemNode->pPrev;
		pMemNode->pPrev->pNext = pMemNode->pNext;

		// allocate a new node
		pNew = MemoryAlloc(size);

		// make sure memory allocated
		assert(pNew != NULL);

		// copy the node to the current node
		memcpy(pMemNode, pNew, sizeof(MEM_NODE));

		// relink the mnode into the list
		pMemNode->pPrev->pNext = pMemNode;
		pMemNode->pNext->pPrev = pMemNode;

		// free the new node
		FreeMemNode(pNew);
	}

	assert(pMemNode->pBaseAddr);
}
Example #7
0
Directory DirectoryOpen(const char *strDirectoryname)
{
#if defined(_WIN32)
	const char *str = strDirectoryname;
	char tmp[MAX_PATH];
	int length = strlen(strDirectoryname);
	memcpy(tmp, strDirectoryname, length);
	switch(tmp[length - 1])
	{
	case '\\':
	case '/':
		break;
	default:
		tmp[length++] = '\\';
}
	tmp[length + 0] = '*';
	tmp[length + 1] = '\0';

	WIN32_FIND_DATA findData;
	HANDLE h = FindFirstFile(tmp, &findData);
	if (h == INVALID_HANDLE_VALUE)
		return DirectoryInvalid;
	else
	{
		DirectoryData *dirData = (DirectoryData*)MemoryAlloc(sizeof(DirectoryData));
		dirData->hDir = h;
		dirData->FindData = findData;
		dirData->IsEnd = FALSE;
		return (Directory)dirData;
	}
#elif defined(PLATFORM_PSP2)
	SceUID id = sceIoDopen(strDirectoryname);
	if (id < 0)
		return DirectoryInvalid;
	else
		return (Directory)id;
#endif
	return DirectoryInvalid;
}
int CAudioSource::ReadSamples(uint8_t* _buffer[8])
{
	int samples = m_SampleRate;
	uint8_t* buffer[8] = {_buffer[0]};
	for(int i = 1; i < m_Channels; i++)
	{
		buffer[i] = _buffer[i];
	}

	if (m_EndOfStream)
	{
		int32_t bytes = samples * m_PacketBytes;
		for(int i = 0; i < m_Channels; i++)
		{
			FillMemory(buffer[i], bytes, m_MuteValue);
		}
		return 0;
	}

	struct
	{
		int index;
		int volume;
	}
	items[3];

	int count = 0;
	int bVolume = 0;
	for(int i = 0; i < 3; i++)
	{
		if (
			(m_Reader[i]) && 
			(m_Reader[i]->m_Info->m_Volume) && 
			(m_Reader[i]->m_StartPos <= m_CurrentPos) &&
			(m_Reader[i]->m_StopPos > m_CurrentPos) 
			)
		{
			if (m_Reader[i]->m_Info->m_Volume != 100)
			{
				bVolume = TRUE;
			}
			items[count].index = i;
			items[count].volume = m_Reader[i]->m_Info->m_Volume;
			count ++;
		}
	}
	
	if (m_CurrentPos + samples >= m_StopPos)
	{
		int len = m_StopPos - m_CurrentPos;
		int offset = len * m_PacketBytes;
		int bytes = (samples - len) * m_PacketBytes;
		for(int i = 0; i < m_Channels; i++)
		{
			FillMemory(buffer[i] + offset, bytes, m_MuteValue);
		}
		m_EndOfStream = TRUE;
		samples = len;
	}

	if (count == 0)
	{
		int32_t bytes = samples * m_PacketBytes;
		for(int i = 0; i < m_Channels; i++)
		{
			FillMemory(buffer[i], bytes, m_MuteValue);
		}
	}
	else if ((count == 1) && (bVolume == 0))
	{
		m_Reader[items[0].index]->ReadSamples(buffer, m_CurrentPos, samples);
	}
	else
	{
		for(int i = 0; i < count; i++)
		{
			for(int j = 0; j < m_Channels; j++)
			{
				if (m_Data[i][j] == NULL)
				{
					m_Data[i][j] = (uint8_t *)MemoryAlloc(m_SampleRate * m_PacketBytes);
				}
			}
		}

		for(int i = 0; i < count; i++)
		{
			m_Reader[items[i].index]->ReadSamples(m_Data[i], m_CurrentPos, samples);
		}

		int total =  samples * m_Samples;
		for(int i = 0; i < m_Channels; i++)
		{
			switch(m_SampleFormat)
			{
			case AV_SAMPLE_FMT_U8:
			case AV_SAMPLE_FMT_U8P:
				switch(count)
				{
				case 1:
					audio_procedure_volume1_8_v(buffer[i], m_Data[0][i], items[0].volume, total);
					break;

				case 2:
					if (bVolume)
					{
						audio_procedure_volume2_8_v(buffer[i], m_Data[0][i], items[0].volume, m_Data[1][i], items[1].volume, total);
					}
					else
					{
						audio_procedure_volume2_8(buffer[i], m_Data[0][i], m_Data[1][i], total);
					}
					break;

				case 3:
					if (bVolume)
					{
						audio_procedure_volume3_8_v(buffer[i], m_Data[0][i], items[0].volume, m_Data[1][i], items[1].volume, m_Data[2][i], items[2].volume, total);
					}
					else
					{
						audio_procedure_volume3_8(buffer[i], m_Data[0][i], m_Data[1][i], m_Data[2][i], total);
					}
					break;
				}
				break;

			case AV_SAMPLE_FMT_S16:
			case AV_SAMPLE_FMT_S16P:
				switch(count)
				{
				case 1:
					audio_procedure_volume1_16_v((int16_t *)buffer[i], (int16_t *)m_Data[0][i], items[0].volume, total);
					break;

				case 2:
					if (bVolume)
					{
						audio_procedure_volume2_16_v((int16_t *)buffer[i], (int16_t *)m_Data[0][i], items[0].volume, (int16_t *)m_Data[1][i], items[1].volume, total);
					}
					else
					{
						audio_procedure_volume2_16((int16_t *)buffer[i], (int16_t *)m_Data[0][i], (int16_t *)m_Data[1][i], total);
					}
					break;

				case 3:
					if (bVolume)
					{
						audio_procedure_volume3_16_v((int16_t *)buffer[i], (int16_t *)m_Data[0][i], items[0].volume, (int16_t *)m_Data[1][i], items[1].volume, (int16_t *)m_Data[2][i], items[2].volume, total);
					}
					else
					{
						audio_procedure_volume3_16((int16_t *)buffer[i], (int16_t *)m_Data[0][i], (int16_t *)m_Data[1][i], (int16_t *)m_Data[2][i], total);
					}
					break;
				}
				break;

			case AV_SAMPLE_FMT_FLT:
			case AV_SAMPLE_FMT_FLTP:
				switch(count)
				{
				case 1:
					audio_procedure_volume1_flt_v((float *)buffer[i], (float *)m_Data[0][i], items[0].volume, total);
					break;

				case 2:
					if (bVolume)
					{
						audio_procedure_volume2_flt_v((float *)buffer[i], (float *)m_Data[0][i], items[0].volume, (float *)m_Data[1][i], items[1].volume, total);
					}
					else
					{
						audio_procedure_volume2_flt((float *)buffer[i], (float *)m_Data[0][i], (float *)m_Data[1][i], total);
					}
					break;

				case 3:
					if (bVolume)
					{
						audio_procedure_volume3_flt_v((float *)buffer[i], (float *)m_Data[0][i], items[0].volume, (float *)m_Data[1][i], items[1].volume, (float *)m_Data[2][i], items[2].volume, total);
					}
					else
					{
						audio_procedure_volume3_flt((float *)buffer[i], (float *)m_Data[0][i], (float *)m_Data[1][i], (float *)m_Data[2][i], total);
					}
					break;
				}
				break;

			case AV_SAMPLE_FMT_S32:
			case AV_SAMPLE_FMT_S32P:
				switch(count)
				{
				case 1:
					audio_procedure_volume1_32_v((int32_t *)buffer[i], (int32_t *)m_Data[0][i], items[0].volume, total);
					break;

				case 2:
					if (bVolume)
					{
						audio_procedure_volume2_32_v((int32_t *)buffer[i], (int32_t *)m_Data[0][i], items[0].volume, (int32_t *)m_Data[1][i], items[1].volume, total);
					}
					else
					{
						audio_procedure_volume2_32((int32_t *)buffer[i], (int32_t *)m_Data[0][i], (int32_t *)m_Data[1][i], total);
					}
					break;

				case 3:
					if (bVolume)
					{
						audio_procedure_volume3_32_v((int32_t *)buffer[i], (int32_t *)m_Data[0][i], items[0].volume, (int32_t *)m_Data[1][i], items[1].volume, (int32_t *)m_Data[2][i], items[2].volume, total);
					}
					else
					{
						audio_procedure_volume3_32((int32_t *)buffer[i], (int32_t *)m_Data[0][i], (int32_t *)m_Data[1][i], (int32_t *)m_Data[2][i], total);
					}
					break;
				}
				break;

			case AV_SAMPLE_FMT_DBL:
			case AV_SAMPLE_FMT_DBLP:
				switch(count)
				{
				case 1:
					audio_procedure_volume1_dbl_v((double *)buffer[i], (double *)m_Data[0][i], items[0].volume, total);
					break;

				case 2:
					if (bVolume)
					{
						audio_procedure_volume2_dbl_v((double *)buffer[i], (double *)m_Data[0][i], items[0].volume, (double *)m_Data[1][i], items[1].volume, total);
					}
					else
					{
						audio_procedure_volume2_dbl((double *)buffer[i], (double *)m_Data[0][i], (double *)m_Data[1][i], total);
					}
					break;

				case 3:
					if (bVolume)
					{
						audio_procedure_volume3_dbl_v((double *)buffer[i], (double *)m_Data[0][i], items[0].volume, (double *)m_Data[1][i], items[1].volume, (double *)m_Data[2][i], items[2].volume, total);
					}
					else
					{
						audio_procedure_volume3_dbl((double *)buffer[i], (double *)m_Data[0][i], (double *)m_Data[1][i], (double *)m_Data[2][i], total);
					}
					break;
				}
				break;
			}
		}
	}

	m_CurrentPos += samples;
	return samples;
}
CSubtitleText::CSubtitleText(wchar_t *szFile)
{
    m_hFile =  CreateFile(szFile,
                          GENERIC_READ,
                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                          NULL,
                          OPEN_EXISTING,
                          FILE_ATTRIBUTE_NORMAL,
                          NULL);
    if (m_hFile == INVALID_HANDLE_VALUE)
    {
        m_hFile = NULL;
        return ;
    }

    LARGE_INTEGER liSize;
    GetFileSizeEx(m_hFile, &liSize);

    if (liSize.QuadPart < 16) return ;
    if (liSize.QuadPart > MAX_SUBTITILE_FILE_SIZE) return ;

    int32_t fSize = liSize.LowPart;
    m_Buffer = (uint8_t *)MemoryAlloc(fSize + 8);
    DWORD NumberOfBytesRead = 0;
    ReadFile(m_hFile, m_Buffer, fSize, &NumberOfBytesRead, NULL);
    if (NumberOfBytesRead != fSize) return ;
    ZeroMemory(m_Buffer + fSize, 8);
    SAFE_CLOSE(m_hFile);

    if ((m_Buffer[0] == 0xFF) && (m_Buffer[1] == 0xFE))
    {
        m_Scrpits = (wchar_t *)MemoryAlloc(fSize + 8);
        wchar_t *s = (wchar_t *)&m_Buffer[2];
        while (*s)
        {
            if (*s != L'\r')
            {
                m_Scrpits[m_cCharacter] = *s;
                m_cCharacter ++;
            }
            s++;
        }
        ZeroMemory(&m_Scrpits[m_cCharacter], 8);
    }
    else if ((m_Buffer[0] == 0xEF) && (m_Buffer[1] == 0xBB) && (m_Buffer[2] == 0xBF))
    {
        int32_t len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)m_Buffer + 3, fSize - 3, NULL, 0);
        if (len == 0) return ;
        m_Scrpits = (wchar_t *)MemoryAlloc(len * 2 + 8);
        m_cCharacter = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)m_Buffer + 3, fSize - 3, m_Scrpits, len * 2 + 2);
        if (m_cCharacter == 0) return ;
        ZeroMemory(&m_Scrpits[m_cCharacter], 8);
        wchar_t *p1 = m_Scrpits;
        wchar_t *p2 = m_Scrpits;
        while(*p2)
        {
            if (*p2 != '\r')*p1++ = *p2;
            p2 ++;
        }
        ZeroMemory(p2, 8);
    }
    else
    {
        INT unicode = IS_TEXT_UNICODE_UNICODE_MASK;
        INT unicodeReverse = IS_TEXT_UNICODE_REVERSE_MASK;
        INT notAscii = IS_TEXT_UNICODE_NOT_ASCII_MASK;
        if (((fSize & 1) == 0) && IsTextUnicode(m_Buffer, fSize, &unicode))
        {
            m_Scrpits = (wchar_t *)MemoryAlloc(fSize + 8);
            wchar_t *s = (wchar_t *)m_Buffer;
            while (*s)
            {
                if (*s != L'\r')
                {
                    m_Scrpits[m_cCharacter] = *s;
                    m_cCharacter ++;
                }
                s++;
            }
            ZeroMemory(&m_Scrpits[m_cCharacter], 8);
        }
        else if (((fSize & 1) == 0) && IsTextUnicode(m_Buffer, fSize, &unicodeReverse))
        {
            m_Scrpits = (wchar_t *)MemoryAlloc(fSize + 8);
            uint8_t *s = m_Buffer;
            while (*((uint16_t *)s))
            {
                wchar_t ch = (uint16_t)s[0] + ((uint16_t)s[1] << 8);
                if (ch != L'\r')
                {
                    m_Scrpits[m_cCharacter] = ch;
                    m_cCharacter ++;
                }
                s += 2;
            }
            ZeroMemory(&m_Scrpits[m_cCharacter], 8);
        }
        else if (IsTextUnicode(m_Buffer, fSize, &notAscii))
        {
            //
        }
        else
        {
            int32_t len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)m_Buffer, fSize - 3, NULL, 0);
            if (len == 0) return ;
            m_Scrpits = (wchar_t *)MemoryAlloc(len * 2 + 8);
            len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)m_Buffer, fSize - 3, m_Scrpits, len * 2 + 8);
            if (len == 0) return ;
            if (m_cCharacter == 0) return ;
            ZeroMemory(&m_Scrpits[m_cCharacter], 8);
            wchar_t *p1 = m_Scrpits;
            wchar_t *p2 = m_Scrpits;
            while(*p2)
            {
                if (*p2 != '\r')*p1++ = *p2;
                p2 ++;
            }
            ZeroMemory(p2, 8);
        }
    }

    if (m_cCharacter == NULL)
    {
        return ;
    }
}
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);
	}
}
Example #11
0
int common_startdisk(long newrowsize, long newcolsize, int colors)
{
    int freemem;
    long memorysize;
    unsigned int *fwd_link = nullptr;
    long longtmp;
    unsigned int cache_size;
    BYTE *tempfar = nullptr;
    if (g_disk_flag)
    {
        enddisk();
    }
    if (driver_diskp()) // otherwise, real screen also in use, don't hit it
    {
        char buf[128];
        helptitle();
        driver_set_attr(1, 0, C_DVID_BKGRD, 24*80);  // init rest to background
        for (int i = 0; i < BOXDEPTH; ++i)
        {
            driver_set_attr(BOXROW+i, BOXCOL, C_DVID_LO, BOXWIDTH);  // init box
        }
        driver_put_string(BOXROW+2, BOXCOL+4, C_DVID_HI, "'Disk-Video' mode");
        sprintf(buf, "Screen resolution: %d x %d", sxdots, sydots);
        driver_put_string(BOXROW+4, BOXCOL+4, C_DVID_LO, buf);
        if (disktarga)
        {
            driver_put_string(-1, -1, C_DVID_LO, "  24 bit Targa");
        }
        else
        {
            driver_put_string(-1, -1, C_DVID_LO, "  Colors: ");
            sprintf(buf, "%d", colors);
            driver_put_string(-1, -1, C_DVID_LO, buf);
        }
        sprintf(buf, "Save name: %s", savename);
        driver_put_string(BOXROW+8, BOXCOL+4, C_DVID_LO, buf);
        driver_put_string(BOXROW+10, BOXCOL+4, C_DVID_LO, "Status:");
        dvid_status(0, "clearing the 'screen'");
    }
    high_offset = -1;
    seek_offset = high_offset;
    cur_offset = seek_offset;
    cur_row    = -1;
    if (disktarga)
    {
        pixelshift = 0;
    }
    else
    {
        pixelshift = 3;
        int i = 2;
        while (i < colors)
        {
            i *= i;
            --pixelshift;
        }
    }
    timetodisplay = bf_math != bf_math_type::NONE ? 10 : 1000;  // time-to-g_driver-status counter

    /* allocate cache: try for the max; leave FREEMEMk free if we can get
        that much or more; if we can't get that much leave 1/2 of whatever
        there is free; demand a certain minimum or nogo at all */
    freemem = FREEMEM;

    for (cache_size = CACHEMAX; cache_size >= CACHEMIN; --cache_size)
    {
        longtmp = ((int)cache_size < freemem) ?
                  (long)cache_size << 11 : (long)(cache_size+freemem) << 10;
        tempfar = static_cast<BYTE *>(malloc(longtmp));
        if (tempfar != nullptr)
        {
            free(tempfar);
            break;
        }
    }
    if (debugflag == debug_flags::force_disk_min_cache)
    {
        cache_size = CACHEMIN;
    }
    longtmp = (long)cache_size << 10;
    cache_start = (cache *)malloc(longtmp);
    if (cache_size == 64)
    {
        --longtmp; // safety for next line
    }
    cache_lru = cache_start;
    cache_end = cache_lru + longtmp/sizeof(*cache_start);
    membuf = (BYTE *)malloc((long)BLOCKLEN);
    if (cache_start == nullptr || membuf == nullptr)
    {
        stopmsg(STOPMSG_NONE,
            "*** insufficient free memory for cache buffers ***");
        return -1;
    }
    if (driver_diskp())
    {
        char buf[50];
        sprintf(buf, "Cache size: %dK", cache_size);
        driver_put_string(BOXROW+6, BOXCOL+4, C_DVID_LO, buf);
    }

    // preset cache to all invalid entries so we don't need free list logic
    for (int i = 0; i < HASHSIZE; ++i)
    {
        hash_ptr[i] = 0xffff; // 0xffff marks the end of a hash chain
    }
    longtmp = 100000000L;
    for (cache *ptr1 = cache_start; ptr1 < cache_end; ++ptr1)
    {
        ptr1->dirty = false;
        ptr1->lru = false;
        longtmp += BLOCKLEN;
        fwd_link = &hash_ptr[(((unsigned short)longtmp >> BLOCKSHIFT) & (HASHSIZE-1))];
        ptr1->offset = longtmp;
        ptr1->hashlink = *fwd_link;
        *fwd_link = (int)((char *)ptr1 - (char *)cache_start);
    }

    memorysize = (long)(newcolsize) * newrowsize + headerlength;
    int i = (short)memorysize & (BLOCKLEN-1);
    if (i != 0)
    {
        memorysize += BLOCKLEN - i;
    }
    memorysize >>= pixelshift;
    memorysize >>= BLOCKSHIFT;
    g_disk_flag = true;
    rowsize = (unsigned int) newrowsize;
    colsize = (unsigned int) newcolsize;

    if (disktarga)
    {
        // Retrieve the header information first
        BYTE *tmpptr;
        tmpptr = membuf;
        fseek(fp, 0L, SEEK_SET);
        for (int i = 0; i < headerlength; i++)
        {
            *tmpptr++ = (BYTE)fgetc(fp);
        }
        fclose(fp);
        dv_handle = MemoryAlloc((U16)BLOCKLEN, memorysize, DISK);
    }
    else
    {
        dv_handle = MemoryAlloc((U16)BLOCKLEN, memorysize, MEMORY);
    }
    if (dv_handle == 0)
    {
        stopmsg(STOPMSG_NONE, "*** insufficient free memory/disk space ***");
        g_good_mode = false;
        rowsize = 0;
        return -1;
    }

    if (driver_diskp())
    {
        driver_put_string(BOXROW+2, BOXCOL+23, C_DVID_LO,
                          (MemoryType(dv_handle) == DISK) ? "Using your Disk Drive" : "Using your memory");
    }

    membufptr = membuf;

    if (disktarga)
    {
        // Put header information in the file
        MoveToMemory(membuf, (U16)headerlength, 1L, 0, dv_handle);
    }
    else
    {
        for (long offset = 0; offset < memorysize; offset++)
        {
            SetMemory(0, (U16)BLOCKLEN, 1L, offset, dv_handle);
            if (driver_key_pressed())           // user interrupt
            {
                // esc to cancel, else continue
                if (stopmsg(STOPMSG_CANCEL, "Disk Video initialization interrupted:\n"))
                {
                    enddisk();
                    g_good_mode = false;
                    return -2;            // -1 == failed, -2 == cancel
                }
            }
        }
    }

    if (driver_diskp())
    {
        dvid_status(0, "");
    }
    return 0;
}