initial commit

This commit is contained in:
R-type
2015-12-14 14:00:35 +01:00
commit 5a96c0ca66
377 changed files with 149124 additions and 0 deletions
+404
View File
@@ -0,0 +1,404 @@
#include "config.h"
#include "screen.h"
#include "render_direct3d.h"
#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>
extern "C" HWND hWndMain;
extern "C" {
#include "colours.h"
#include "log.h"
}
typedef D3DXMATRIX* (WINAPI* D3DXMatrixLookAtLHFunc)(D3DXMATRIX*, CONST D3DXVECTOR3*, CONST D3DXVECTOR3*, CONST D3DXVECTOR3*);
typedef D3DXMATRIX* (WINAPI* D3DXMatrixPerspectiveFovLHFunc)(D3DXMATRIX*, FLOAT, FLOAT, FLOAT, FLOAT);
typedef D3DXMATRIX* (WINAPI* D3DXMatrixRotationYFunc)(D3DXMATRIX*, FLOAT);
// D3D declarations
static LPDIRECT3D9 d3d;
static LPDIRECT3DDEVICE9 d3d_device;
static LPDIRECT3DVERTEXBUFFER9 vertex_buffer = NULL;
static LPDIRECT3DTEXTURE9 texture_buffer = NULL;
static D3DPRESENT_PARAMETERS d3dpp;
struct CUSTOMVERTEX {FLOAT X, Y, Z; DWORD COLOR; FLOAT U, V;};
#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
static float const pi = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862f;
static float texturehorizclip = 0.0f;
static float texturevertclip = 0.0f;
static HMODULE hD3DX = NULL;
static D3DXMatrixLookAtLHFunc D3DXMatrixLookAtLHPtr = NULL;
static D3DXMatrixPerspectiveFovLHFunc D3DXMatrixPerspectiveFovLHPtr = NULL;
static D3DXMatrixRotationYFunc D3DXMatrixRotationYPtr = NULL;
extern "C" void startupdirect3d(int screenwidth, int screenheight, BOOL windowed, FRAMEPARAMS *fp)
{
// look for the newest, oldest, then generic versions
if ((hD3DX = LoadLibrary("d3dx9_42.dll")) != NULL || (hD3DX = LoadLibrary("d3dx9_24.dll")) != NULL || (hD3DX = LoadLibrary("d3dx9.dll")) != NULL)
{
D3DXMatrixLookAtLHPtr = (D3DXMatrixLookAtLHFunc) GetProcAddress(hD3DX, "D3DXMatrixLookAtLH");
D3DXMatrixPerspectiveFovLHPtr = (D3DXMatrixPerspectiveFovLHFunc) GetProcAddress(hD3DX, "D3DXMatrixPerspectiveFovLH");
D3DXMatrixRotationYPtr = (D3DXMatrixRotationYFunc) GetProcAddress(hD3DX, "D3DXMatrixRotationY");
// unlikely failure to load function pointers
if (D3DXMatrixLookAtLHPtr == NULL || D3DXMatrixPerspectiveFovLHPtr == NULL || D3DXMatrixRotationYPtr == NULL)
{
FreeLibrary(hD3DX);
hD3DX = NULL;
Log_print("Extended Direct3D functions disabled - load failure");
}
}
else
{
Log_print("Extended Direct3D functions disabled - updated DirectX runtime needed");
}
d3d = Direct3DCreate9(D3D_SDK_VERSION);
initpresentparams(screenwidth, screenheight, windowed);
// create the D3D device
d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWndMain,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3d_device);
initdevice(fp);
return;
}
// Function used when we need to change present params
void resetdevice(int screenwidth, int screenheight, BOOL windowed, FRAMEPARAMS *fp)
{
texture_buffer->Release(); // close and release the texture
initpresentparams(screenwidth, screenheight, windowed);
d3d_device->Reset(&d3dpp);
initdevice(fp);
return;
}
void initpresentparams(int screenwidth, int screenheight, BOOL windowed)
{
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = windowed;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWndMain;
d3dpp.BackBufferWidth = screenwidth;
d3dpp.BackBufferHeight = screenheight;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
// Only need this in fullscreen mode.
if (!windowed) {
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
}
return;
}
void initdevice(FRAMEPARAMS *fp)
{
UINT texturesize;
D3DTEXTUREFILTERTYPE filtertype;
// compute a horizontal & vertical offset
// with compensation for possible cropping & stretching
int clip_width = fp->view.right - fp->view.left;
int clip_height = fp->view.bottom - fp->view.top;
// set the type of interpolation filtering selected by the user
// only bilinear or none are available.
if (fp->filter == BILINEAR)
filtertype = D3DTEXF_LINEAR;
else
filtertype = D3DTEXF_POINT;
d3d_device->SetRenderState(D3DRS_LIGHTING, FALSE); // turn off the 3D lighting
d3d_device->SetRenderState(D3DRS_ZENABLE, TRUE); // turn on the z-buffer
d3d_device->SetSamplerState( 0, D3DSAMP_MAGFILTER, filtertype);
d3d_device->SetFVF(CUSTOMFVF);
// In Direct3D we paint the Atari screen onto a texture that overlays a vertex buffer polygon.
// Although most newer graphics cards support rectangular textures of variable size,
// for compatibility and performance reasons, it is better that the texture be square with
// sides that are a power of two. Since the size of the bitmap changes depending
// on the scanline mode, we set that here. We also set the clipping parameters here
// that we'll use in the vertex buffer init to only map the drawn portion of the
// texture to the vertex buffer.
switch (fp->scanlinemode)
{
case NONE: // we are just mapping the standard 320x240 Atari screen bitmap.
texturesize = 512;
texturehorizclip = clip_width / (float)texturesize;
texturevertclip = clip_height / (float)texturesize;
break;
case LOW: // LOW res scanlines produces a 320x480 pixel bitmap
texturesize = 512;
texturehorizclip = clip_width / (float)texturesize;
texturevertclip = (clip_height * 2 + 1) / (float)texturesize;
break;
case MEDIUM: // MEDIUM res scanlines produces a 320x720 pixel bitmap
texturesize = 1024;
texturehorizclip = clip_width / (float)texturesize;
texturevertclip = (clip_height * 3 + 2) / (float)texturesize;
break;
case HIGH: // HIGH res canlines produces a 320x960 pixel bitmap
texturesize = 1024;
texturehorizclip = clip_width / (float)texturesize;
texturevertclip = (clip_height * 4 + 3) / (float)texturesize;
break;
}
// now lets go ahead and create a blank texture of the appropriate dimensions
d3d_device->CreateTexture(texturesize, texturesize, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture_buffer, NULL );
return;
}
// this function creates the 2D vertex buffer polygon and attaches the texture to it
void init_vertices(float x, float y, float z)
{
// Create the vertices.
// What we're actually doing here is specifying two right triangles
// attached to one another to form a wireframe rectangle. We also specify
// that our texture (the screen) should be mapped to extend to the edges
// of this rectangle. This is basically how we create a 2D surface with
// a 3D toolset.
struct CUSTOMVERTEX vertex_def[] =
{
{-x, y, z, 0xffffffff, 0, 0,},
{x, y, z, 0xffffffff, texturehorizclip, 0,},
{-x, -y, -z, 0xffffffff, 0, texturevertclip,},
{x, -y, -z, 0xffffffff, texturehorizclip, texturevertclip,},
};
d3d_device->CreateVertexBuffer(4*sizeof(CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&vertex_buffer,
NULL);
VOID* pVoid; // a void pointer
// lock vertex_buffer and load the vertices into it
vertex_buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, vertex_def, sizeof(vertex_def));
vertex_buffer->Unlock();
return;
}
// this is the function used to render each frame
void refreshv_direct3d(UBYTE *scr_ptr, FRAMEPARAMS *fp)
{
// clear the contents of the vertex buffer polygon and make it black
d3d_device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
d3d_device->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
// If the caller has set fp->d3dRefresh to true it means that the vertex
// buffer has changed (usually because the window or texture size has changed).
// In these cases we will re-init the vertices prior to building the frame.
if (fp->d3dRefresh)
{
if (hD3DX != NULL)
{
init_vertices(fp->d3dWidth, 0, fp->d3dHeight);
}
else
{
init_vertices(fp->d3dWidth, fp->d3dHeight, 0);
}
fp->d3dRefresh = FALSE;
}
// We can now unlock the backbuffer and start to draw our frame
d3d_device->BeginScene();
// refresh the texture buffer for the frame
// this function call actually draws the contents of the Atari screen buffer
// to the Direct3D backbuffer.
refresh_frame(scr_ptr, fp);
// set the texture
d3d_device->SetTexture(0, texture_buffer);
// select the vertex buffer to display
d3d_device->SetStreamSource(0, vertex_buffer, 0, sizeof(CUSTOMVERTEX));
//***********************************************************************
// This next section supports the 3D screensaver and tilt functions by
// using some simple matrix tranformations on the vertex buffer polygon.
// Note: If you want to remove this 3D screensaver effect and operate
// in a more purely 2D view, change the init_vertices statement above to
// init_vertices(fp->d3dWidth, fp->d3dHeight, 0);
// and remove all statements from here to the end of this
// 3D Matrix Transformations section.
//***********************************************************************
if (hD3DX != NULL)
{
D3DXMATRIX matView;
static float index = pi; // rotation amount
static float cy = 2.41f; // amount of zoom
static float cz = 0.00001f; // amount of tilt
static float by = 0.0;
if (fp->screensaver)
{
fp->tiltlevel = TILTLEVEL0; // make sure tiltlevel is disabled
// this transformation creates and animates the 3D screensaver
if (cy > 1.5f)
cy -= 0.002f; // zoom
if (cz < 2.2)
cz += 0.005f; // tilt
index+=0.005f; // rotation index
}
else if (fp->tiltlevel != TILTLEVEL0)
{
index = pi;
switch (fp->tiltlevel)
{
case TILTLEVEL1:
if (cz < 1.0)
cz += 0.012f; // tilt
if (by > -0.2f)
by -= 0.003f; // slide up
break;
case TILTLEVEL2:
if (cz < 1.5)
cz += 0.016f; // tilt
if (cy > 2.3f)
cy -= 0.004f; // zoom
break;
case TILTLEVEL3:
if (cz < 1.8)
cz += 0.012f; // tilt
if (cy > 2.1f)
cy -= 0.008f; // zoom
if (by > -0.25f)
by -= 0.002f; // slide up
break;
}
}
else
{
// this transformation creates a standard 2D view
index = pi;
cy = 2.41f;
cz = 0.00001f;
by = 0.0;
}
// Create the transform matView
D3DXMatrixLookAtLHPtr(&matView,
&D3DXVECTOR3 (0.0f, cy, cz), // tilt & zoom the camera
&D3DXVECTOR3 (0.0f, by, 0.0f), // raise & lower the camera
&D3DXVECTOR3 (0.0f, 1.0, 0.0f)); // flip the camera
d3d_device->SetTransform(D3DTS_VIEW, &matView); // set the view transform to matView
// set the projection transform
D3DXMATRIX matProjection; // the projection transform matrix
D3DXMatrixPerspectiveFovLHPtr(&matProjection,
D3DXToRadian(45), // the horizontal field of view
1.0f, // aspect ratio
1.0f, // the near view-plane
100.0f); // the far view-plane
d3d_device->SetTransform(D3DTS_PROJECTION, &matProjection); // set the projection
// set the world transform
D3DXMATRIX matRotateY; // a matrix to store the rotation for each triangle
D3DXMatrixRotationYPtr(&matRotateY, index); // the rotation matrix
d3d_device->SetTransform(D3DTS_WORLD, &(matRotateY)); // set the world transform
}
//***********************************************************************
// End 3D transformations
//***********************************************************************
// draw the fully rendered and transformed surface to the backbuffer
d3d_device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
// We now lock the backbuffer
d3d_device->EndScene();
// Now tell Direct3D to flip the image to the screen.
d3d_device->Present(NULL, NULL, NULL, NULL);
return;
}
// shutdown the Direct3D engine
extern "C" void shutdowndirect3d(void)
{
vertex_buffer->Release(); // close and release the vertex buffer
texture_buffer->Release(); // close and release the texture
d3d_device->Release(); // close and release the 3D device
d3d->Release(); // close and release Direct3D
if (hD3DX != NULL)
{
FreeLibrary(hD3DX);
hD3DX = NULL;
}
return;
}
// Copy the raw screen buffer data to the texture buffer
void refresh_frame(UBYTE *scr_ptr, FRAMEPARAMS *fp)
{
int pixel = 0;
int i, x, y;
int texturewidth;
// calculate texture width
int viewwidth = fp->view.right - fp->view.left;
D3DLOCKED_RECT d3dlr;
texture_buffer->LockRect(0, &d3dlr, 0, 0);
DWORD* pixels = (DWORD*)d3dlr.pBits;
texturewidth = d3dlr.Pitch / 4;
// copy screen buffer to the texture
scr_ptr += fp->view.top * Screen_WIDTH + fp->view.left;
for (y = fp->view.top; y < fp->view.bottom; y++) {
for (x = fp->view.left; x < fp->view.right; x++) {
if (y < 0 || y >= Screen_HEIGHT || x < 0 || x >= Screen_WIDTH)
pixels[pixel] = Colours_table[0];
else
pixels[pixel] = Colours_table[*scr_ptr];
for (i = 0; i < fp->scanlinemode; i++) {
pixels[pixel + i * texturewidth] = pixels[pixel];
}
scr_ptr++;
pixel++;
}
scr_ptr += Screen_WIDTH - viewwidth;
pixel += texturewidth - viewwidth;
pixel += texturewidth * fp->scanlinemode;
}
texture_buffer->UnlockRect(0);
}