2021-11-12 20:03:04 +01:00
|
|
|
#include "ati3dcif.hpp"
|
|
|
|
#include "Error.hpp"
|
|
|
|
#include "Renderer.hpp"
|
|
|
|
#include "Utils.hpp"
|
|
|
|
|
|
|
|
#include <glrage/GLRage.hpp>
|
|
|
|
#include <glrage_util/ErrorUtils.hpp>
|
|
|
|
#include <glrage_util/Logger.hpp>
|
|
|
|
|
|
|
|
#include <stdexcept>
|
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
namespace glrage {
|
|
|
|
namespace cif {
|
|
|
|
|
|
|
|
static Context& context = GLRage::getContext();
|
|
|
|
static std::unique_ptr<Renderer> renderer;
|
|
|
|
static bool contextCreated = false;
|
|
|
|
|
|
|
|
C3D_EC
|
|
|
|
HandleException()
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
throw;
|
|
|
|
} catch (const Error& ex) {
|
|
|
|
#ifdef _DEBUG
|
|
|
|
ErrorUtils::warning(ex);
|
|
|
|
#endif
|
|
|
|
LOG_INFO("CIF error: %s (0x%x %s)", ex.what(), ex.getErrorCode(),
|
|
|
|
ex.getErrorName());
|
|
|
|
return ex.getErrorCode();
|
|
|
|
} catch (const std::runtime_error& ex) {
|
|
|
|
ErrorUtils::warning(ex);
|
|
|
|
return C3D_EC_GENFAIL;
|
|
|
|
} catch (const std::logic_error& ex) {
|
|
|
|
ErrorUtils::warning(ex);
|
|
|
|
return C3D_EC_GENFAIL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
2021-11-14 23:42:18 +01:00
|
|
|
C3D_EC WINAPI ATI3DCIF_Term(void)
|
|
|
|
{
|
|
|
|
LOG_TRACE("");
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (renderer) {
|
|
|
|
renderer.release();
|
|
|
|
}
|
|
|
|
} catch (...) {
|
|
|
|
return HandleException();
|
|
|
|
}
|
|
|
|
|
|
|
|
// SDK PDF says "TRUE if successful, otherwise FALSE", but the
|
|
|
|
// function uses C3D_EC as return value.
|
|
|
|
// In other words: TRUE = C3D_EC_GENFAIL and FALSE = C3D_EC_OK? WTF...
|
|
|
|
// Anyway, most apps don't seem to care about the return value
|
|
|
|
// of this function, so stick with C3D_EC_OK for now.
|
|
|
|
return C3D_EC_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
C3D_EC WINAPI ATI3DCIF_Init(void)
|
2021-11-12 20:03:04 +01:00
|
|
|
{
|
|
|
|
LOG_TRACE("");
|
|
|
|
|
|
|
|
context.init();
|
|
|
|
context.attach();
|
|
|
|
|
|
|
|
ErrorUtils::setHWnd(context.getHWnd());
|
|
|
|
|
|
|
|
// do some cleanup in case the app forgets to call ATI3DCIF_Term
|
|
|
|
if (renderer) {
|
|
|
|
LOG_INFO("Previous instance was not terminated by ATI3DCIF_Term!");
|
|
|
|
ATI3DCIF_Term();
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
renderer = std::make_unique<Renderer>();
|
|
|
|
} catch (...) {
|
|
|
|
return HandleException();
|
|
|
|
}
|
|
|
|
|
|
|
|
return C3D_EC_OK;
|
|
|
|
}
|
|
|
|
|
2021-11-14 23:42:18 +01:00
|
|
|
C3D_EC WINAPI ATI3DCIF_GetInfo(PC3D_3DCIFINFO p3DCIFInfo)
|
2021-11-12 20:03:04 +01:00
|
|
|
{
|
|
|
|
LOG_TRACE("");
|
|
|
|
|
|
|
|
// check for invalid struct
|
|
|
|
if (!p3DCIFInfo || p3DCIFInfo->u32Size > 48) {
|
|
|
|
return C3D_EC_BADPARAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
// values from an ATI Xpert 98 with a 3D Rage Pro AGP 2x
|
|
|
|
|
|
|
|
// Host pointer to frame buffer base (TODO: allocate memory?)
|
|
|
|
p3DCIFInfo->u32FrameBuffBase = 0;
|
|
|
|
// Host pointer to offscreen heap (TODO: allocate memory?)
|
2021-11-14 23:42:18 +01:00
|
|
|
p3DCIFInfo->u32OffScreenHeap = 0;
|
2021-11-12 20:03:04 +01:00
|
|
|
p3DCIFInfo->u32OffScreenSize = 0x4fe800; // Size of offscreen heap
|
|
|
|
p3DCIFInfo->u32TotalRAM = 8 << 20; // Total amount of RAM on the card
|
|
|
|
p3DCIFInfo->u32ASICID = 0x409; // ASIC Id. code
|
|
|
|
p3DCIFInfo->u32ASICRevision = 0x47ff; // ASIC revision
|
|
|
|
|
|
|
|
// older CIF versions don't have CIF caps, so check the size first
|
|
|
|
if (p3DCIFInfo->u32Size == 48) {
|
|
|
|
// note: 0x400 and 0x800 are reported in 4.10.2690 and later but are not
|
|
|
|
// defined in ATI3DCIF.H
|
|
|
|
p3DCIFInfo->u32CIFCaps1 = C3D_CAPS1_FOG | C3D_CAPS1_POINT |
|
|
|
|
C3D_CAPS1_RECT | C3D_CAPS1_Z_BUFFER |
|
|
|
|
C3D_CAPS1_CI4_TMAP | C3D_CAPS1_CI8_TMAP |
|
|
|
|
C3D_CAPS1_DITHER_EN | C3D_CAPS1_ENH_PERSP |
|
|
|
|
C3D_CAPS1_SCISSOR | 0x400 | 0x800;
|
|
|
|
p3DCIFInfo->u32CIFCaps2 = C3D_CAPS2_TEXTURE_CLAMP |
|
|
|
|
C3D_CAPS2_DESTINATION_ALPHA_BLEND |
|
|
|
|
C3D_CAPS2_TEXTURE_TILING;
|
|
|
|
|
|
|
|
// unused caps
|
|
|
|
p3DCIFInfo->u32CIFCaps3 = 0;
|
|
|
|
p3DCIFInfo->u32CIFCaps4 = 0;
|
|
|
|
p3DCIFInfo->u32CIFCaps5 = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return C3D_EC_OK;
|
|
|
|
}
|
|
|
|
|
2021-11-14 23:42:18 +01:00
|
|
|
C3D_EC WINAPI ATI3DCIF_TextureReg(C3D_PTMAP ptmapToReg, C3D_PHTX phtmap)
|
2021-11-12 20:03:04 +01:00
|
|
|
{
|
|
|
|
LOG_TRACE("0x%p, 0x%p", *ptmapToReg, *phtmap);
|
|
|
|
|
|
|
|
try {
|
|
|
|
renderer->textureReg(ptmapToReg, phtmap);
|
|
|
|
} catch (...) {
|
|
|
|
return HandleException();
|
|
|
|
}
|
|
|
|
|
|
|
|
return C3D_EC_OK;
|
|
|
|
}
|
|
|
|
|
2021-11-14 23:42:18 +01:00
|
|
|
C3D_EC WINAPI ATI3DCIF_TextureUnreg(C3D_HTX htxToUnreg)
|
2021-11-12 20:03:04 +01:00
|
|
|
{
|
|
|
|
LOG_TRACE("0x%p", htxToUnreg);
|
|
|
|
|
|
|
|
try {
|
|
|
|
renderer->textureUnreg(htxToUnreg);
|
|
|
|
} catch (...) {
|
|
|
|
return HandleException();
|
|
|
|
}
|
|
|
|
|
|
|
|
return C3D_EC_OK;
|
|
|
|
}
|
|
|
|
|
2021-11-14 23:42:18 +01:00
|
|
|
C3D_EC WINAPI ATI3DCIF_TexturePaletteCreate(C3D_ECI_TMAP_TYPE epalette, void* pPalette, C3D_PHTXPAL phtpalCreated)
|
2021-11-12 20:03:04 +01:00
|
|
|
{
|
|
|
|
LOG_TRACE("%s, 0x%p, 0x%p", cif::C3D_ECI_TMAP_TYPE_NAMES[epalette],
|
|
|
|
pPalette, phtpalCreated);
|
|
|
|
|
|
|
|
try {
|
|
|
|
renderer->texturePaletteCreate(epalette, pPalette, phtpalCreated);
|
|
|
|
} catch (...) {
|
|
|
|
return HandleException();
|
|
|
|
}
|
|
|
|
|
|
|
|
return C3D_EC_OK;
|
|
|
|
}
|
|
|
|
|
2021-11-14 23:42:18 +01:00
|
|
|
C3D_EC WINAPI ATI3DCIF_TexturePaletteDestroy(C3D_HTXPAL htxpalToDestroy)
|
2021-11-12 20:03:04 +01:00
|
|
|
{
|
|
|
|
LOG_TRACE("0x%p", htxpalToDestroy);
|
|
|
|
|
|
|
|
try {
|
|
|
|
renderer->texturePaletteDestroy(htxpalToDestroy);
|
|
|
|
} catch (...) {
|
|
|
|
return HandleException();
|
|
|
|
}
|
|
|
|
|
|
|
|
return C3D_EC_OK;
|
|
|
|
}
|
|
|
|
|
2021-11-14 23:42:18 +01:00
|
|
|
C3D_EC WINAPI ATI3DCIF_TexturePaletteAnimate(C3D_HTXPAL htxpalToAnimate, C3D_UINT32 u32StartIndex, C3D_UINT32 u32NumEntries, C3D_PPALETTENTRY pclrPalette)
|
2021-11-12 20:03:04 +01:00
|
|
|
{
|
|
|
|
LOG_TRACE("0x%p, %d, %d, 0x%p", htxpalToAnimate, u32StartIndex,
|
|
|
|
u32NumEntries, *pclrPalette);
|
|
|
|
|
|
|
|
try {
|
|
|
|
renderer->texturePaletteAnimate(
|
|
|
|
htxpalToAnimate, u32StartIndex, u32NumEntries, pclrPalette);
|
|
|
|
} catch (...) {
|
|
|
|
return HandleException();
|
|
|
|
}
|
|
|
|
|
|
|
|
return C3D_EC_OK;
|
|
|
|
}
|
|
|
|
|
2021-11-14 23:42:18 +01:00
|
|
|
C3D_HRC WINAPI ATI3DCIF_ContextCreate(void)
|
2021-11-12 20:03:04 +01:00
|
|
|
{
|
|
|
|
LOG_TRACE("");
|
|
|
|
|
|
|
|
context.attach();
|
|
|
|
|
|
|
|
// can't create more than one context
|
|
|
|
if (contextCreated) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
contextCreated = true;
|
|
|
|
|
|
|
|
// According to ATI3DCIF.H, "only one context may be exist at a time",
|
|
|
|
// so always returning 1 should be fine
|
|
|
|
return (C3D_HRC)1;
|
|
|
|
}
|
|
|
|
|
2021-11-14 23:42:18 +01:00
|
|
|
C3D_EC WINAPI ATI3DCIF_ContextDestroy(C3D_HRC hRC)
|
2021-11-12 20:03:04 +01:00
|
|
|
{
|
|
|
|
LOG_TRACE("0x%p", hRC);
|
|
|
|
|
|
|
|
// can't destroy a context that wasn't created
|
|
|
|
if (!contextCreated) {
|
|
|
|
return C3D_EC_BADPARAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
contextCreated = false;
|
|
|
|
|
|
|
|
return C3D_EC_OK;
|
|
|
|
}
|
|
|
|
|
2021-11-14 23:42:18 +01:00
|
|
|
C3D_EC WINAPI ATI3DCIF_ContextSetState(C3D_HRC hRC, C3D_ERSID eRStateID, C3D_PRSDATA pRStateData)
|
2021-11-12 20:03:04 +01:00
|
|
|
{
|
|
|
|
#ifdef LOG_TRACE_ENABLED
|
|
|
|
std::string stateDataStr =
|
|
|
|
cif::Utils::dumpRenderStateData(eRStateID, pRStateData);
|
|
|
|
LOG_TRACE("0x%p, %s, %s", hRC, cif::C3D_ERSID_NAMES[eRStateID],
|
|
|
|
stateDataStr.c_str());
|
|
|
|
#endif
|
|
|
|
|
|
|
|
try {
|
|
|
|
renderer->setState(eRStateID, pRStateData);
|
|
|
|
} catch (...) {
|
|
|
|
return HandleException();
|
|
|
|
}
|
|
|
|
|
|
|
|
return C3D_EC_OK;
|
|
|
|
}
|
|
|
|
|
2021-11-14 23:42:18 +01:00
|
|
|
C3D_EC WINAPI ATI3DCIF_RenderBegin(C3D_HRC hRC)
|
2021-11-12 20:03:04 +01:00
|
|
|
{
|
|
|
|
LOG_TRACE("0x%p", hRC);
|
|
|
|
|
|
|
|
try {
|
|
|
|
renderer->renderBegin(hRC);
|
|
|
|
} catch (...) {
|
|
|
|
return HandleException();
|
|
|
|
}
|
|
|
|
|
|
|
|
return C3D_EC_OK;
|
|
|
|
}
|
|
|
|
|
2021-11-14 23:42:18 +01:00
|
|
|
C3D_EC WINAPI ATI3DCIF_RenderEnd(void)
|
2021-11-12 20:03:04 +01:00
|
|
|
{
|
|
|
|
LOG_TRACE("");
|
|
|
|
|
|
|
|
try {
|
|
|
|
renderer->renderEnd();
|
|
|
|
} catch (...) {
|
|
|
|
return HandleException();
|
|
|
|
}
|
|
|
|
|
|
|
|
return C3D_EC_OK;
|
|
|
|
}
|
|
|
|
|
2021-11-14 23:42:18 +01:00
|
|
|
C3D_EC WINAPI ATI3DCIF_RenderSwitch(C3D_HRC hRC)
|
2021-11-12 20:03:04 +01:00
|
|
|
{
|
|
|
|
LOG_TRACE("0x%p", hRC);
|
|
|
|
// function has officially never been implemented
|
|
|
|
return C3D_EC_NOTIMPYET;
|
|
|
|
}
|
|
|
|
|
2021-11-14 23:42:18 +01:00
|
|
|
C3D_EC WINAPI ATI3DCIF_RenderPrimStrip(C3D_VSTRIP vStrip, C3D_UINT32 u32NumVert)
|
2021-11-12 20:03:04 +01:00
|
|
|
{
|
|
|
|
LOG_TRACE("0x%p, %d", vStrip, u32NumVert);
|
|
|
|
|
|
|
|
try {
|
|
|
|
renderer->renderPrimStrip(vStrip, u32NumVert);
|
|
|
|
} catch (...) {
|
|
|
|
return HandleException();
|
|
|
|
}
|
|
|
|
|
|
|
|
return C3D_EC_OK;
|
|
|
|
}
|
|
|
|
|
2021-11-14 23:42:18 +01:00
|
|
|
C3D_EC WINAPI ATI3DCIF_RenderPrimList(C3D_VLIST vList, C3D_UINT32 u32NumVert)
|
2021-11-12 20:03:04 +01:00
|
|
|
{
|
|
|
|
LOG_TRACE("0x%p, %d", vList, u32NumVert);
|
|
|
|
|
|
|
|
try {
|
|
|
|
renderer->renderPrimList(vList, u32NumVert);
|
|
|
|
} catch (...) {
|
|
|
|
return HandleException();
|
|
|
|
}
|
|
|
|
|
|
|
|
return C3D_EC_OK;
|
|
|
|
}
|
|
|
|
|
2021-11-14 23:42:18 +01:00
|
|
|
C3D_EC WINAPI ATI3DCIF_RenderPrimMesh(C3D_PVARRAY vMesh, C3D_PUINT32 pu32Indicies, C3D_UINT32 u32NumIndicies)
|
2021-11-12 20:03:04 +01:00
|
|
|
{
|
|
|
|
LOG_TRACE("0x%p, %d", vMesh, u32NumIndicies);
|
|
|
|
|
|
|
|
// TODO
|
|
|
|
return C3D_EC_NOTIMPYET;
|
|
|
|
}
|
|
|
|
|
2021-11-14 23:42:18 +01:00
|
|
|
// export macro for CIF implementation
|
|
|
|
#define EXPORT(function_name, return_type, parameters) \
|
|
|
|
function_name##_t function_name##_lib = function_name; \
|
|
|
|
return_type WINAPI function_name parameters \
|
|
|
|
|
|
|
|
|
|
|
|
C3D_EC (*WINAPI ATI3DCIF_Term_lib)(void) = ATI3DCIF_Term;
|
|
|
|
C3D_EC (*WINAPI ATI3DCIF_Init_lib)(void) = ATI3DCIF_Init;
|
|
|
|
C3D_EC (*WINAPI ATI3DCIF_GetInfo_lib)(PC3D_3DCIFINFO p3DCIFInfo) = ATI3DCIF_GetInfo;
|
|
|
|
C3D_EC (*WINAPI ATI3DCIF_TextureReg_lib)(C3D_PTMAP ptmapToReg, C3D_PHTX phtmap) = ATI3DCIF_TextureReg;
|
|
|
|
C3D_EC (*WINAPI ATI3DCIF_TextureUnreg_lib)(C3D_HTX htxToUnreg) = ATI3DCIF_TextureUnreg;
|
|
|
|
C3D_EC (*WINAPI ATI3DCIF_TexturePaletteCreate_lib)(C3D_ECI_TMAP_TYPE epalette, void* pPalette, C3D_PHTXPAL phtpalCreated) = ATI3DCIF_TexturePaletteCreate;
|
|
|
|
C3D_EC (*WINAPI ATI3DCIF_TexturePaletteDestroy_lib)(C3D_HTXPAL htxpalToDestroy) = ATI3DCIF_TexturePaletteDestroy;
|
|
|
|
C3D_EC (*WINAPI ATI3DCIF_TexturePaletteAnimate_lib)(C3D_HTXPAL htxpalToAnimate, C3D_UINT32 u32StartIndex, C3D_UINT32 u32NumEntries, C3D_PPALETTENTRY pclrPalette) = ATI3DCIF_TexturePaletteAnimate;
|
|
|
|
C3D_HRC (*WINAPI ATI3DCIF_ContextCreate_lib)(void) = ATI3DCIF_ContextCreate;
|
|
|
|
C3D_EC (*WINAPI ATI3DCIF_ContextDestroy_lib)(C3D_HRC hRC) = ATI3DCIF_ContextDestroy;
|
|
|
|
C3D_EC (*WINAPI ATI3DCIF_ContextSetState_lib)(C3D_HRC hRC, C3D_ERSID eRStateID, C3D_PRSDATA pRStateData) = ATI3DCIF_ContextSetState;
|
|
|
|
C3D_EC (*WINAPI ATI3DCIF_RenderBegin_lib)(C3D_HRC hRC) = ATI3DCIF_RenderBegin;
|
|
|
|
C3D_EC (*WINAPI ATI3DCIF_RenderEnd_lib)(void) = ATI3DCIF_RenderEnd;
|
|
|
|
C3D_EC (*WINAPI ATI3DCIF_RenderSwitch_lib)(C3D_HRC hRC) = ATI3DCIF_RenderSwitch;
|
|
|
|
C3D_EC (*WINAPI ATI3DCIF_RenderPrimStrip_lib)(C3D_VSTRIP vStrip, C3D_UINT32 u32NumVert) = ATI3DCIF_RenderPrimStrip;
|
|
|
|
C3D_EC (*WINAPI ATI3DCIF_RenderPrimList_lib)(C3D_VLIST vList, C3D_UINT32 u32NumVert) = ATI3DCIF_RenderPrimList;
|
|
|
|
C3D_EC (*WINAPI ATI3DCIF_RenderPrimMesh_lib)(C3D_PVARRAY vMesh, C3D_PUINT32 pu32Indicies, C3D_UINT32 u32NumIndicies) = ATI3DCIF_RenderPrimMesh;
|
|
|
|
|
2021-11-12 20:03:04 +01:00
|
|
|
} // extern "C"
|
|
|
|
|
|
|
|
} // namespace cif
|
2021-11-14 23:42:18 +01:00
|
|
|
} // namespace glrage
|