📄 hal_mllc.c
字号:
/*-------------------------------------------------------------------------
//
// Copyright (c) 1997, 2001 Epson Research and Development, Inc.
// All Rights Reserved.
//
//-----------------------------------------------------------------------*/
#include "hal.h"
/*
** Because malloc.h redefines NULL, undefine NULL here first.
*/
#undef NULL
#include <stdio.h>
#include "nonsefns.h"
#include <malloc.h>
#ifdef INTEL_W32
#pragma warning(disable:4001) // Disable the 'single line comment' warning.
#pragma warning(disable:4115) // ignore "named type definition in parentheses" warning
#pragma warning(disable:4514) // ignore "unreferenced inline function has been removed" warning
#pragma warning(disable:4201) // Disable the 'nonstandard extension used : nameless struct/union'
#pragma warning(disable:4214) // Disable the 'single line comment' warning.
#pragma warning(disable:4702) // Disable the 'unreachable code' warning.
#endif
/*-----------------------------------------------------------------------------
//
// Static function prototypes
//
//---------------------------------------------------------------------------*/
static DWORD seBackAlloc(DWORD size,DWORD alignment);
static void seVmemBlocksMerge(void);
static _MEMBLOCKST *seGetLastBlock(void);
static _MEMBLOCKST *seNewBlockAppend(_MEMBLOCKST *mbpta);
/*-----------------------------------------------------------------------------
//
// Global data.
//
//---------------------------------------------------------------------------*/
static _MEMBLOCKST gMB;
static DWORD gDualPanelBuffer;
static DWORD DualPanelBufferSize = 0;
/*-----------------------------------------------------------------------------
//
// Claim the whole video memory as one free block.
// This function MUST be called as part of the HAL init sequence
// before any video memory allocations calls.
//
// Arguments:
// DWORD size : total amount of video memory installed (bytes)
//
//---------------------------------------------------------------------------*/
void _seVmemInit(DWORD size)
{
gMB.next = gMB.prev = NULL;
gMB.size = size;
gMB.free = TRUE;
gDualPanelBuffer = 0;
gMB.address = _DispLinearAddress;
DualPanelBufferSize = 0;
_AutoAllocDualPanelBufferAddr = 0;
#ifdef _DEBUG
printf("_seVmemInit(%08lX)\n", size);
#endif
}
/*-----------------------------------------------------------------------------
//
// Allocate a block of memory for HW ink layer.
// It is any address on an 8k boundary.
//
// Arguments:
// DWORD overlaysize : amount of video memory (bytes) to allocate
//
//---------------------------------------------------------------------------*/
DWORD seVmemAllocInk(DWORD overlaysize)
{
DWORD addr;
#ifdef _DEBUG
char str[50];
#endif
addr = seBackAlloc(overlaysize,8192);
#ifdef _DEBUG
sprintf(str, "seVmemAllocInk(%08lX) > %08lX", overlaysize, addr);
_seVmemDump(str);
#endif
return addr;
}
/*-----------------------------------------------------------------------------
//
// Allocate a block of memory for HW cursor.
// It is either the very last 1k of video memory
// or any address on an 8k boundary.
//
//---------------------------------------------------------------------------*/
DWORD seVmemAllocCursor(void)
{
DWORD addr;
#ifdef _DEBUG
char str[50];
#endif
addr = seBackAlloc(1024,1024);
#ifdef _DEBUG
sprintf(str, "seVmemAllocCursor(%08lX) > %08lX", (DWORD) 1024, addr);
_seVmemDump(str);
#endif
return addr;
}
/*-----------------------------------------------------------------------------
//
// Allocate a block of memory for Dual Panel Buffer.
// This function must be called whenever the dual panel buffer is needed.
//
// Arguments:
// DWORD size : amount of video memory (bytes) to allocate
//
//---------------------------------------------------------------------------*/
DWORD seVmemAllocDualPanelBuffer(DWORD size)
{
_MEMBLOCKST *mbpt;
int forever = 1;
#ifdef _DEBUG
char str[50];
#endif
// If a dual panel buffer is allocated, free it first
seVmemFreeDualPanelBuffer();
// Carve the block at the end of the video memory.
// If the block is not free, free it first.
do
{
mbpt = seGetLastBlock();
if (mbpt->size >= size)
{
// block big enough. We'll split it into two blocks.
// The first one will be free, the last one used (our
// dual panel buffer)
_MEMBLOCKST *newblock = seNewBlockAppend(mbpt);
if (newblock == NULL)
{
#ifdef _DEBUG
sprintf(str, "seVmemAllocDualPanelBuffer(%08lX) FAILED", size);
_seVmemDump(str);
#endif
#ifdef INTEL_DOS
return -1;
#else
return 0;
#endif
}
// Truncate the original block.
mbpt->size = mbpt->size - size;
newblock->size = size;
newblock->free = FALSE;
newblock->address = mbpt->address+mbpt->size;
// Free the original block (to force blocks merge)
mbpt->free = FALSE;
seVmemFree(mbpt->address);
gDualPanelBuffer = newblock->address;
#ifdef _DEBUG
sprintf(str, "seVmemAllocDualPanelBuffer(%08lX) > %08lX", size, newblock->address);
_seVmemDump(str);
#endif
DualPanelBufferSize = size;
return newblock->address;
}
else
{
// block too small. Merge the last two blocks
// and start all over again.
if (mbpt->prev == NULL)
{
#ifdef _DEBUG
sprintf(str, "seVmemAllocDualPanelBuffer(%08lX) FAILED", size);
_seVmemDump(str);
#endif
#ifdef INTEL_DOS
return -1;
#else
return 0;
#endif
}
seVmemFree(mbpt->prev->address);
seVmemFree(mbpt->address);
}
} while (forever);
#ifdef INTEL_DOS
return -1;
#else
return 0;
#endif
}
/*-----------------------------------------------------------------------------
//
//
//---------------------------------------------------------------------------*/
void seVmemFreeDualPanelBuffer(void)
{
if (gDualPanelBuffer)
{
seVmemFree(gDualPanelBuffer);
gDualPanelBuffer = 0;
DualPanelBufferSize = 0;
}
}
/*-----------------------------------------------------------------------------
//
//
//---------------------------------------------------------------------------*/
DWORD seVmemGetDualPanelBufferSize(void)
{
return DualPanelBufferSize;
}
/*-----------------------------------------------------------------------------
//
// Allocate a block of video memory.
//
// Arguments:
// DWORD size : amount of video memory (bytes) to allocate
//
//---------------------------------------------------------------------------*/
DWORD seVmemAlloc(DWORD size)
{
_MEMBLOCKST *mbpt;
#ifdef _DEBUG
char str[50];
#endif
// round up to the next 1k boundary
size += 1023;
size &= ~1023;
for (mbpt = &gMB; mbpt != NULL; mbpt = mbpt->next)
{
if (mbpt->free == TRUE)
{
// is the block big enough?
if (mbpt->size == size)
{
// Snug fit. Just claim the block not free.
mbpt->free = FALSE;
#ifdef _DEBUG
sprintf(str, "seVmemAlloc(%08lX) > %08lX", size, mbpt->address);
_seVmemDump(str);
#endif
return mbpt->address;
}
else if (mbpt->size > size)
{
// Split the free block.
_MEMBLOCKST *newblock = seNewBlockAppend(mbpt);
if (newblock == NULL)
{
#ifdef _DEBUG
sprintf(str, "seVmemAlloc(%08lX) FAILED", size);
_seVmemDump(str);
#endif
return 0;
}
newblock->size = mbpt->size-size;
newblock->address = mbpt->address + size;
newblock->free = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -