mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 15:27:46 -04:00
rm old windows port
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@805 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
parent
823b9004c4
commit
91842de3ea
12 changed files with 0 additions and 1921 deletions
|
@ -1,148 +0,0 @@
|
||||||
|
|
||||||
#include "app.h"
|
|
||||||
|
|
||||||
#ifndef _XBOX
|
|
||||||
#pragma warning (disable:4201)
|
|
||||||
#include <mmsystem.h>
|
|
||||||
#include <dsound.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static IDirectSound *DSound=NULL;
|
|
||||||
static IDirectSoundBuffer *LoopBuffer=NULL;
|
|
||||||
static int LoopLen=0,LoopWrite=0; // Next position in loop to write
|
|
||||||
|
|
||||||
short *DSoundNext=NULL; // Buffer for next sound data to put in loop
|
|
||||||
|
|
||||||
static int LoopBlank()
|
|
||||||
{
|
|
||||||
void *mema=NULL,*memb=NULL;
|
|
||||||
DWORD sizea=0,sizeb=0;
|
|
||||||
|
|
||||||
LoopBuffer->Lock(0,LoopLen<<((PicoOpt&8) ? 2 : 1), &mema,&sizea, &memb,&sizeb, 0);
|
|
||||||
|
|
||||||
if (mema) memset(mema,0,sizea);
|
|
||||||
|
|
||||||
LoopBuffer->Unlock(mema,sizea, memb,sizeb);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DSoundInit()
|
|
||||||
{
|
|
||||||
DSBUFFERDESC dsbd;
|
|
||||||
WAVEFORMATEX wfx;
|
|
||||||
|
|
||||||
memset(&dsbd,0,sizeof(dsbd));
|
|
||||||
memset(&wfx,0,sizeof(wfx));
|
|
||||||
|
|
||||||
// Make wave format:
|
|
||||||
wfx.wFormatTag=WAVE_FORMAT_PCM;
|
|
||||||
wfx.nChannels=(unsigned short)((PicoOpt&8) ? 2 : 1); // Stereo/mono
|
|
||||||
wfx.nSamplesPerSec=PsndRate;
|
|
||||||
wfx.wBitsPerSample=16;
|
|
||||||
|
|
||||||
wfx.nBlockAlign=(WORD)((wfx.nChannels*wfx.wBitsPerSample)>>3);
|
|
||||||
wfx.nAvgBytesPerSec=wfx.nBlockAlign*wfx.nSamplesPerSec;
|
|
||||||
|
|
||||||
// Make buffer for the next seg to put into the loop:
|
|
||||||
DSoundNext=(short *)malloc((PsndLen<<2)+64); if (DSoundNext==NULL) return 1;
|
|
||||||
memset(DSoundNext,0,PsndLen<<2);
|
|
||||||
// lprintf("p %p\n", DSoundNext);
|
|
||||||
|
|
||||||
// Create the DirectSound interface:
|
|
||||||
DirectSoundCreate(NULL,&DSound,NULL);
|
|
||||||
if (DSound==NULL) return 1;
|
|
||||||
|
|
||||||
LoopLen=PsndLen<<1; // 2 segs
|
|
||||||
|
|
||||||
#ifndef _XBOX
|
|
||||||
LoopLen<<=1; // 4 segs
|
|
||||||
DSound->SetCooperativeLevel(FrameWnd,DSSCL_PRIORITY);
|
|
||||||
dsbd.dwFlags=DSBCAPS_GLOBALFOCUS; // Play in background
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Create the looping buffer:
|
|
||||||
dsbd.dwSize=sizeof(dsbd);
|
|
||||||
dsbd.dwBufferBytes=LoopLen<<wfx.nChannels; // 16bit stereo?
|
|
||||||
dsbd.lpwfxFormat=&wfx;
|
|
||||||
|
|
||||||
DSound->CreateSoundBuffer(&dsbd,&LoopBuffer,NULL);
|
|
||||||
if (LoopBuffer==NULL) return 1;
|
|
||||||
|
|
||||||
LoopBlank();
|
|
||||||
LoopBuffer->Play(0,0,DSBPLAY_LOOPING);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DSoundExit()
|
|
||||||
{
|
|
||||||
if (LoopBuffer) LoopBuffer->Stop();
|
|
||||||
RELEASE(LoopBuffer)
|
|
||||||
RELEASE(DSound)
|
|
||||||
DSound=0;
|
|
||||||
if (DSoundNext) free(DSoundNext); DSoundNext=NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int WriteSeg()
|
|
||||||
{
|
|
||||||
void *mema=NULL,*memb=NULL;
|
|
||||||
DWORD sizea=0,sizeb=0;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
// Lock the segment at 'LoopWrite' and copy the next segment in
|
|
||||||
ret = LoopBuffer->Lock(LoopWrite<<((PicoOpt&8) ? 2 : 1),PsndLen<<((PicoOpt&8) ? 2 : 1), &mema,&sizea, &memb,&sizeb, 0);
|
|
||||||
if (ret) lprintf("LoopBuffer->Lock() failed: %i\n", ret);
|
|
||||||
|
|
||||||
if (mema) memcpy(mema,DSoundNext,sizea);
|
|
||||||
// if (memb) memcpy(memb,DSoundNext+sizea,sizeb);
|
|
||||||
if (sizeb != 0) lprintf("sizeb is not 0! (%i)\n", sizeb);
|
|
||||||
|
|
||||||
ret = LoopBuffer->Unlock(mema,sizea, memb,0);
|
|
||||||
if (ret) lprintf("LoopBuffer->Unlock() failed: %i\n", ret);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int DSoundFake()
|
|
||||||
{
|
|
||||||
static int ticks_old = 0;
|
|
||||||
int ticks = GetTickCount() * 1000;
|
|
||||||
int diff;
|
|
||||||
|
|
||||||
diff = ticks - ticks_old;
|
|
||||||
if (diff >= 0 && diff < 1000000/60*4)
|
|
||||||
{
|
|
||||||
while (diff >= 0 && diff < 1000000/60)
|
|
||||||
{
|
|
||||||
Sleep(1);
|
|
||||||
diff = GetTickCount()*1000 - ticks_old;
|
|
||||||
}
|
|
||||||
ticks_old += 1000000/60;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ticks_old = ticks;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DSoundUpdate()
|
|
||||||
{
|
|
||||||
DWORD play=0;
|
|
||||||
int pos=0;
|
|
||||||
|
|
||||||
if (LoopBuffer==NULL) return DSoundFake();
|
|
||||||
|
|
||||||
LoopBuffer->GetCurrentPosition(&play,NULL);
|
|
||||||
pos=play>>((PicoOpt&8) ? 2 : 1);
|
|
||||||
|
|
||||||
// 'LoopWrite' is the next seg in the loop that we want to write
|
|
||||||
// First check that the sound 'play' pointer has moved out of it:
|
|
||||||
if (pos>=LoopWrite && pos<LoopWrite+PsndLen) return 1; // No, it hasn't
|
|
||||||
|
|
||||||
WriteSeg();
|
|
||||||
|
|
||||||
// Advance LoopWrite to next seg:
|
|
||||||
LoopWrite+=PsndLen; if (LoopWrite+PsndLen>LoopLen) LoopWrite=0;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,423 +0,0 @@
|
||||||
#include "app.h"
|
|
||||||
|
|
||||||
#ifdef USE_D3D
|
|
||||||
// d3d
|
|
||||||
static IDirect3D8 *Direct3D=NULL;
|
|
||||||
IDirect3DDevice8 *Device=NULL;
|
|
||||||
IDirect3DSurface8 *DirectBack=NULL; // Back Buffer
|
|
||||||
|
|
||||||
static IDirect3DVertexBuffer8 *VertexBuffer=NULL;
|
|
||||||
|
|
||||||
struct CustomVertex
|
|
||||||
{
|
|
||||||
float x,y,z; // Vertex cordinates
|
|
||||||
unsigned int colour;
|
|
||||||
float u,v; // Texture coordinates
|
|
||||||
};
|
|
||||||
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
|
|
||||||
|
|
||||||
static CustomVertex VertexList[4];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ddraw
|
|
||||||
#include <ddraw.h>
|
|
||||||
|
|
||||||
LPDIRECTDRAW7 m_pDD = NULL;
|
|
||||||
LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer = NULL;
|
|
||||||
LPDIRECTDRAWSURFACE7 m_pddsBackBuffer = NULL;
|
|
||||||
|
|
||||||
// quick and dirty stuff..
|
|
||||||
static void DirectExitDDraw()
|
|
||||||
{
|
|
||||||
RELEASE(m_pddsBackBuffer);
|
|
||||||
RELEASE(m_pddsFrontBuffer);
|
|
||||||
RELEASE(m_pDD);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int DirectDrawInit()
|
|
||||||
{
|
|
||||||
HRESULT ret;
|
|
||||||
LPDIRECTDRAWCLIPPER pcClipper = NULL;
|
|
||||||
DDSURFACEDESC2 ddsd;
|
|
||||||
|
|
||||||
ret = DirectDrawCreateEx(NULL, (VOID**)&m_pDD, IID_IDirectDraw7, NULL);
|
|
||||||
if (ret) { LOGFAIL(); return 1; }
|
|
||||||
|
|
||||||
// Set cooperative level
|
|
||||||
ret = m_pDD->SetCooperativeLevel( FrameWnd, DDSCL_NORMAL );
|
|
||||||
if (ret) { LOGFAIL(); goto fail; }
|
|
||||||
|
|
||||||
// Create the primary surface
|
|
||||||
ZeroMemory( &ddsd, sizeof( ddsd ) );
|
|
||||||
ddsd.dwSize = sizeof( ddsd );
|
|
||||||
ddsd.dwFlags = DDSD_CAPS;
|
|
||||||
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
|
||||||
|
|
||||||
ret = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL );
|
|
||||||
if (ret) { LOGFAIL(); goto fail; }
|
|
||||||
|
|
||||||
// Create the backbuffer surface
|
|
||||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
|
||||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
|
||||||
ddsd.dwWidth = EmuWidth;
|
|
||||||
ddsd.dwHeight = EmuHeight;
|
|
||||||
|
|
||||||
ret = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL );
|
|
||||||
if (ret) { LOGFAIL(); goto fail; }
|
|
||||||
|
|
||||||
// clipper
|
|
||||||
ret = m_pDD->CreateClipper( 0, &pcClipper, NULL );
|
|
||||||
if (ret) { LOGFAIL(); goto fail; }
|
|
||||||
|
|
||||||
ret = pcClipper->SetHWnd( 0, FrameWnd );
|
|
||||||
if (ret) { LOGFAIL(); goto fail; }
|
|
||||||
|
|
||||||
ret = m_pddsFrontBuffer->SetClipper( pcClipper );
|
|
||||||
if (ret) { LOGFAIL(); goto fail; }
|
|
||||||
|
|
||||||
RELEASE(pcClipper);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
RELEASE(pcClipper);
|
|
||||||
DirectExitDDraw();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int DirectScreenDDraw()
|
|
||||||
{
|
|
||||||
DDSURFACEDESC2 sd;
|
|
||||||
unsigned short *ps=EmuScreen;
|
|
||||||
int ret, x, y;
|
|
||||||
|
|
||||||
memset(&sd, 0, sizeof(sd));
|
|
||||||
sd.dwSize = sizeof(sd);
|
|
||||||
ret = m_pddsBackBuffer->Lock(NULL, &sd, DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_WRITEONLY, NULL);
|
|
||||||
if (ret) { LOGFAIL(); return 1; }
|
|
||||||
|
|
||||||
//lprintf("w: %i h: %i pi: %i pf: %i\n", sd.dwWidth, sd.dwHeight, sd.lPitch, sd.ddpfPixelFormat.dwRGBBitCount);
|
|
||||||
|
|
||||||
if (sd.ddpfPixelFormat.dwRGBBitCount == 32)
|
|
||||||
{
|
|
||||||
int *dst = (int *)sd.lpSurface;
|
|
||||||
for (y = 0; y < EmuHeight; y++)
|
|
||||||
{
|
|
||||||
for (x = 0; x < EmuWidth; x++)
|
|
||||||
{
|
|
||||||
int s = *ps++;
|
|
||||||
dst[x] = ((s&0xf800)<<8) | ((s&0x07e0)<<5) | ((s&0x001f)<<3);
|
|
||||||
}
|
|
||||||
dst = (int *)((char *)dst + sd.lPitch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (sd.ddpfPixelFormat.dwRGBBitCount == 24) /* wine uses this for me */
|
|
||||||
{
|
|
||||||
void *dst = sd.lpSurface;
|
|
||||||
for (y = 0; y < EmuHeight; y++)
|
|
||||||
{
|
|
||||||
unsigned char *dst1 = (unsigned char *) dst;
|
|
||||||
for (x = 0; x < EmuWidth; x++, dst1 += 3)
|
|
||||||
{
|
|
||||||
int s = *ps++;
|
|
||||||
dst1[2] = (s&0xf800)>>8; dst1[1] = (s&0x07e0)>>3; dst1[0] = s<<3; // BGR
|
|
||||||
}
|
|
||||||
dst = (void *)((char *)dst + sd.lPitch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (sd.ddpfPixelFormat.dwRGBBitCount == 16)
|
|
||||||
{
|
|
||||||
unsigned short *dst = (unsigned short *)sd.lpSurface;
|
|
||||||
for (y = 0; y < EmuHeight; y++)
|
|
||||||
{
|
|
||||||
memcpy(dst, ps, EmuWidth*2);
|
|
||||||
ps += EmuWidth;
|
|
||||||
dst = (unsigned short *)((char *)dst + sd.lPitch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOGFAIL();
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = m_pddsBackBuffer->Unlock(NULL);
|
|
||||||
if (ret) { LOGFAIL(); return 1; }
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int DirectClearDDraw(unsigned int colour)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
DDBLTFX ddbltfx;
|
|
||||||
ZeroMemory( &ddbltfx, sizeof(ddbltfx) );
|
|
||||||
ddbltfx.dwSize = sizeof(ddbltfx);
|
|
||||||
ddbltfx.dwFillColor = colour;
|
|
||||||
|
|
||||||
if (m_pddsBackBuffer != NULL)
|
|
||||||
ret = m_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx );
|
|
||||||
if (ret) { LOGFAIL(); return 1; }
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int DirectPresentDDraw()
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
if (FrameRectMy.right - FrameRectMy.left > 0 && FrameRectMy.bottom - FrameRectMy.top > 0)
|
|
||||||
ret = m_pddsFrontBuffer->Blt(&FrameRectMy, m_pddsBackBuffer, &EmuScreenRect, DDBLT_WAIT, NULL);
|
|
||||||
if (ret) { LOGFAIL(); return 1; }
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* D3D */
|
|
||||||
|
|
||||||
int DirectInit()
|
|
||||||
{
|
|
||||||
#if USE_D3D
|
|
||||||
D3DPRESENT_PARAMETERS d3dpp;
|
|
||||||
D3DDISPLAYMODE mode;
|
|
||||||
int i,u,ret=0;
|
|
||||||
|
|
||||||
memset(&d3dpp,0,sizeof(d3dpp));
|
|
||||||
memset(&mode,0,sizeof(mode));
|
|
||||||
|
|
||||||
Direct3D=Direct3DCreate8(D3D_SDK_VERSION); if (Direct3D==NULL) return 1;
|
|
||||||
|
|
||||||
// Set up the structure used to create the D3D device:
|
|
||||||
d3dpp.BackBufferWidth =MainWidth;
|
|
||||||
d3dpp.BackBufferHeight=MainHeight;
|
|
||||||
d3dpp.BackBufferCount =1;
|
|
||||||
d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
|
|
||||||
d3dpp.MultiSampleType =D3DMULTISAMPLE_NONE;
|
|
||||||
|
|
||||||
#ifdef _XBOX
|
|
||||||
d3dpp.BackBufferFormat=D3DFMT_X8R8G8B8;
|
|
||||||
d3dpp.FullScreen_RefreshRateInHz=60;
|
|
||||||
#else
|
|
||||||
Direct3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&mode);
|
|
||||||
d3dpp.BackBufferFormat=mode.Format;
|
|
||||||
d3dpp.Windowed=1;
|
|
||||||
d3dpp.hDeviceWindow=FrameWnd;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Try to create a device with hardware vertex processing:
|
|
||||||
for (i=0;i<3;i++)
|
|
||||||
{
|
|
||||||
int behave=D3DCREATE_HARDWARE_VERTEXPROCESSING;
|
|
||||||
|
|
||||||
// Try software vertex processing:
|
|
||||||
if (i==1) behave=D3DCREATE_MIXED_VERTEXPROCESSING;
|
|
||||||
if (i==2) behave=D3DCREATE_SOFTWARE_VERTEXPROCESSING;
|
|
||||||
|
|
||||||
Direct3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,FrameWnd,
|
|
||||||
behave|D3DCREATE_MULTITHREADED,&d3dpp,&Device);
|
|
||||||
if (Device) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Device==NULL)
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
// try ref
|
|
||||||
Direct3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_REF,FrameWnd,
|
|
||||||
D3DCREATE_SOFTWARE_VERTEXPROCESSING|D3DCREATE_MULTITHREADED,&d3dpp,&Device);
|
|
||||||
if (Device==NULL) goto fail0;
|
|
||||||
HMODULE test = LoadLibrary("d3d8d.dll");
|
|
||||||
if (test != NULL) FreeLibrary(test);
|
|
||||||
else {
|
|
||||||
error("Sorry, but this program requires Direct3D with hardware acceleration.\n\n"
|
|
||||||
"You can try using Direct3D software emulation, but you have to install "
|
|
||||||
"DirectX SDK for it to work\n(it seems to be missing now).");
|
|
||||||
goto fail1;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
goto fail1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
Device->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&DirectBack);
|
|
||||||
if (DirectBack==NULL) goto fail1;
|
|
||||||
|
|
||||||
Device->CreateVertexBuffer(sizeof(VertexList),0,D3DFVF_CUSTOMVERTEX,D3DPOOL_DEFAULT,&VertexBuffer);
|
|
||||||
if (VertexBuffer==NULL) goto fail2;
|
|
||||||
|
|
||||||
ret=TexScreenInit(); if (ret) goto fail3;
|
|
||||||
|
|
||||||
//FontInit();
|
|
||||||
|
|
||||||
Device->SetRenderState(D3DRS_LIGHTING,0); // Turn off lighting
|
|
||||||
|
|
||||||
// Set up texture modes:
|
|
||||||
Device->SetTextureStageState(0,D3DTSS_ADDRESSU,D3DTADDRESS_CLAMP);
|
|
||||||
Device->SetTextureStageState(0,D3DTSS_ADDRESSV,D3DTADDRESS_CLAMP);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
fail3:
|
|
||||||
RELEASE(VertexBuffer)
|
|
||||||
fail2:
|
|
||||||
RELEASE(DirectBack)
|
|
||||||
fail1:
|
|
||||||
RELEASE(Device)
|
|
||||||
fail0:
|
|
||||||
RELEASE(Direct3D)
|
|
||||||
|
|
||||||
// error("Failed to use Direct3D, trying DirectDraw..");
|
|
||||||
#endif
|
|
||||||
// try DirectDraw
|
|
||||||
return DirectDrawInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirectExit()
|
|
||||||
{
|
|
||||||
#ifdef USE_D3D
|
|
||||||
TexScreenExit();
|
|
||||||
|
|
||||||
// d3d
|
|
||||||
RELEASE(VertexBuffer)
|
|
||||||
RELEASE(DirectBack)
|
|
||||||
RELEASE(Device)
|
|
||||||
RELEASE(Direct3D)
|
|
||||||
#endif
|
|
||||||
DirectExitDDraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
int DirectClear(unsigned int colour)
|
|
||||||
{
|
|
||||||
#ifdef USE_D3D
|
|
||||||
if (Device != NULL) {
|
|
||||||
Device->Clear(0,NULL,D3DCLEAR_TARGET,colour,1.0f,0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return DirectClearDDraw(colour);
|
|
||||||
}
|
|
||||||
|
|
||||||
int DirectPresent()
|
|
||||||
{
|
|
||||||
#ifdef USE_D3D
|
|
||||||
if (Device != NULL) {
|
|
||||||
Device->Present(NULL,NULL,NULL,NULL);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return DirectPresentDDraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_D3D
|
|
||||||
#define PI 3.14159265f
|
|
||||||
|
|
||||||
static int MakeVertexList()
|
|
||||||
{
|
|
||||||
struct CustomVertex *vert=NULL,*pv=NULL;
|
|
||||||
float dist=0.0f;
|
|
||||||
float scalex=0.0f,scaley=0.0f;
|
|
||||||
unsigned int colour=0xffffff;
|
|
||||||
float right=0.0f,bottom=0.0f;
|
|
||||||
|
|
||||||
if (LoopMode!=8) colour=0x102040;
|
|
||||||
|
|
||||||
dist=10.0f; scalex=dist*1.3333f; scaley=dist;
|
|
||||||
|
|
||||||
scalex*=640.0f/(float)MainWidth;
|
|
||||||
scaley*=448.0f/(float)MainHeight;
|
|
||||||
|
|
||||||
vert=VertexList;
|
|
||||||
|
|
||||||
// Put the vertices for the corners of the screen:
|
|
||||||
pv=vert;
|
|
||||||
pv->z=dist;
|
|
||||||
pv->x=-scalex; pv->y=scaley;
|
|
||||||
pv->colour=colour; pv++;
|
|
||||||
|
|
||||||
*pv=vert[0]; pv->x= scalex; pv->y= scaley; pv++;
|
|
||||||
*pv=vert[0]; pv->x=-scalex; pv->y=-scaley; pv++;
|
|
||||||
*pv=vert[0]; pv->x= scalex; pv->y=-scaley; pv++;
|
|
||||||
|
|
||||||
// Find where the screen images ends on the texture
|
|
||||||
right =(float)EmuWidth /(float)TexWidth;
|
|
||||||
bottom=(float)EmuHeight/(float)TexHeight;
|
|
||||||
|
|
||||||
// Write texture coordinates:
|
|
||||||
pv=vert;
|
|
||||||
pv->u=0.0f; pv->v=0.00f; pv++;
|
|
||||||
pv->u=right; pv->v=0.00f; pv++;
|
|
||||||
pv->u=0.0f; pv->v=bottom; pv++;
|
|
||||||
pv->u=right; pv->v=bottom; pv++;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int SetupMatrices()
|
|
||||||
{
|
|
||||||
D3DXVECTOR3 eye ( 0.0f, 0.0f, 0.0f );
|
|
||||||
D3DXVECTOR3 look( 0.0f, 0.0f, 0.0f );
|
|
||||||
D3DXVECTOR3 up ( 0.0f, 1.0f, 0.0f );
|
|
||||||
D3DXMATRIX mat;
|
|
||||||
float nudgex=0.0f,nudgey=0.0f;
|
|
||||||
|
|
||||||
memset(&mat,0,sizeof(mat));
|
|
||||||
|
|
||||||
mat.m[0][0]=mat.m[1][1]=mat.m[2][2]=mat.m[3][3]=1.0f;
|
|
||||||
Device->SetTransform(D3DTS_WORLD,&mat);
|
|
||||||
|
|
||||||
look.x=(float)Inp.axis[2]/2457.6f;
|
|
||||||
look.y=(float)Inp.axis[3]/2457.6f;
|
|
||||||
look.z=10.0f;
|
|
||||||
|
|
||||||
// Nudge pixels to the centre of each screen pixel:
|
|
||||||
nudgex=13.3333f/(float)(MainWidth <<1);
|
|
||||||
nudgey=10.0000f/(float)(MainHeight<<1);
|
|
||||||
eye.x +=nudgex; eye.y +=nudgey;
|
|
||||||
look.x+=nudgex; look.y+=nudgey;
|
|
||||||
|
|
||||||
D3DXMatrixLookAtLH(&mat,&eye,&look,&up);
|
|
||||||
Device->SetTransform(D3DTS_VIEW,&mat);
|
|
||||||
|
|
||||||
D3DXMatrixPerspectiveFovLH(&mat, 0.5f*PI, 1.3333f, 0.2f, 1000.0f);
|
|
||||||
Device->SetTransform(D3DTS_PROJECTION,&mat);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DirectScreen()
|
|
||||||
{
|
|
||||||
unsigned char *lock=NULL;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (Device == NULL)
|
|
||||||
return DirectScreenDDraw();
|
|
||||||
|
|
||||||
// Copy the screen to the screen texture:
|
|
||||||
#ifdef _XBOX
|
|
||||||
TexScreenSwizzle();
|
|
||||||
#else
|
|
||||||
ret=TexScreenLinear();
|
|
||||||
if (ret) lprintf("TexScreenLinear failed\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SetupMatrices();
|
|
||||||
|
|
||||||
MakeVertexList();
|
|
||||||
|
|
||||||
// Copy vertices in:
|
|
||||||
VertexBuffer->Lock(0,sizeof(VertexList),&lock,0);
|
|
||||||
if (lock==NULL) { lprintf("VertexBuffer->Lock failed\n"); return 1; }
|
|
||||||
memcpy(lock,VertexList,sizeof(VertexList));
|
|
||||||
VertexBuffer->Unlock();
|
|
||||||
|
|
||||||
Device->BeginScene();
|
|
||||||
Device->SetTexture(0,TexScreen);
|
|
||||||
Device->SetStreamSource(0,VertexBuffer,sizeof(CustomVertex));
|
|
||||||
Device->SetVertexShader(D3DFVF_CUSTOMVERTEX);
|
|
||||||
Device->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2);
|
|
||||||
Device->EndScene();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
int DirectScreen()
|
|
||||||
{
|
|
||||||
return DirectScreenDDraw();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
|
|
||||||
#include "app.h"
|
|
||||||
|
|
||||||
unsigned short *EmuScreen=NULL;
|
|
||||||
int EmuWidth=320,EmuHeight=224;
|
|
||||||
RECT EmuScreenRect = { 0, 0, 320, 224 };
|
|
||||||
int PicoPadAdd = 0;
|
|
||||||
|
|
||||||
static int EmuScan(unsigned int num);
|
|
||||||
unsigned char *PicoDraw2FB = NULL;
|
|
||||||
|
|
||||||
int EmuInit()
|
|
||||||
{
|
|
||||||
int len=0;
|
|
||||||
|
|
||||||
PicoInit();
|
|
||||||
|
|
||||||
// Allocate screen:
|
|
||||||
EmuWidth=320; EmuHeight=224;
|
|
||||||
len=EmuWidth*EmuHeight; len<<=1;
|
|
||||||
EmuScreen=(unsigned short *)malloc(len); if (EmuScreen==NULL) return 1;
|
|
||||||
PicoDraw2FB=(unsigned char *)malloc((8+320)*(8+224+8)*2);
|
|
||||||
memset(EmuScreen,0,len);
|
|
||||||
|
|
||||||
PicoDrawSetColorFormat(1);
|
|
||||||
PicoScanBegin=EmuScan;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmuExit()
|
|
||||||
{
|
|
||||||
//RomFree();
|
|
||||||
free(EmuScreen); EmuScreen=NULL; // Deallocate screen
|
|
||||||
free(PicoDraw2FB);
|
|
||||||
EmuWidth=EmuHeight=0;
|
|
||||||
|
|
||||||
PicoExit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Megadrive scanline callback:
|
|
||||||
static int EmuScan(unsigned int num)
|
|
||||||
{
|
|
||||||
DrawLineDest=EmuScreen+(num<<8)+(num<<6);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int EmuFrame()
|
|
||||||
{
|
|
||||||
char map[12]={0,1,2,3,8,9,10,4,11,12,13,14}; // Joypads, format is UDLR BCAS ZYXM
|
|
||||||
int a=0,input=0;
|
|
||||||
|
|
||||||
// Set Megadrive buttons:
|
|
||||||
for (a=0;a<12;a++)
|
|
||||||
{
|
|
||||||
int m=map[a];
|
|
||||||
if (m>=0) if (Inp.button[m]>30) input|=1<<a;
|
|
||||||
}
|
|
||||||
|
|
||||||
PicoPad[0]=input;
|
|
||||||
PicoPad[0]|=PicoPadAdd;
|
|
||||||
|
|
||||||
PsndOut=(short *)DSoundNext;
|
|
||||||
PicoFrame();
|
|
||||||
PsndOut=NULL;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void mp3_update(int *buffer, int length, int stereo)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void mp3_start_play(FILE *f, int pos)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int mp3_get_bitrate(FILE *f, int size)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,193 +0,0 @@
|
||||||
|
|
||||||
#include "app.h"
|
|
||||||
#include <commdlg.h>
|
|
||||||
|
|
||||||
struct Input Inp;
|
|
||||||
|
|
||||||
// --------------------- XBox Input -----------------------------
|
|
||||||
#ifdef _XBOX
|
|
||||||
static HANDLE GamePad=NULL;
|
|
||||||
static XINPUT_STATE Pad;
|
|
||||||
|
|
||||||
static int DeadZone(short *paxis)
|
|
||||||
{
|
|
||||||
int zone=0x2000;
|
|
||||||
int a=*paxis;
|
|
||||||
|
|
||||||
if (a<-zone) a+=zone;
|
|
||||||
else if (a> zone) a-=zone; else a=0;
|
|
||||||
|
|
||||||
*paxis=(short)a;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int DeviceRead()
|
|
||||||
{
|
|
||||||
int but=0,a=0;
|
|
||||||
|
|
||||||
memset(Inp.axis, 0,sizeof(Inp.axis));
|
|
||||||
memset(Inp.button,0,sizeof(Inp.button));
|
|
||||||
|
|
||||||
if (GamePad==NULL) GamePad=XInputOpen(XDEVICE_TYPE_GAMEPAD,0,XDEVICE_NO_SLOT,NULL);
|
|
||||||
if (GamePad==NULL) return 1;
|
|
||||||
|
|
||||||
// Read XBox joypad:
|
|
||||||
XInputGetState(GamePad,&Pad);
|
|
||||||
|
|
||||||
// Get analog axes:
|
|
||||||
Inp.axis[0]=Pad.Gamepad.sThumbLX;
|
|
||||||
Inp.axis[1]=Pad.Gamepad.sThumbLY;
|
|
||||||
Inp.axis[2]=Pad.Gamepad.sThumbRX;
|
|
||||||
Inp.axis[3]=Pad.Gamepad.sThumbRY;
|
|
||||||
|
|
||||||
for (a=0;a<4;a++) DeadZone(Inp.axis+a);
|
|
||||||
|
|
||||||
// Get digital buttons:
|
|
||||||
but=Pad.Gamepad.wButtons;
|
|
||||||
for (a=0;a<8;a++)
|
|
||||||
{
|
|
||||||
if (but&(1<<a)) Inp.button[a]=0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get analog buttons:
|
|
||||||
memcpy(Inp.button+8, Pad.Gamepad.bAnalogButtons, 8);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// --------------------- Windows Input -----------------------------
|
|
||||||
|
|
||||||
#ifndef _XBOX
|
|
||||||
|
|
||||||
static int DeviceRead()
|
|
||||||
{
|
|
||||||
int push=0x6000;
|
|
||||||
int axis[]={0,0,0,0};
|
|
||||||
int i=0;
|
|
||||||
|
|
||||||
memset(Inp.axis, 0,sizeof(Inp.axis));
|
|
||||||
memset(Inp.button,0,sizeof(Inp.button));
|
|
||||||
|
|
||||||
if (GetForegroundWindow()!=FrameWnd) return 1;
|
|
||||||
|
|
||||||
if (GetAsyncKeyState(VK_LEFT )) axis[0]-=push;
|
|
||||||
if (GetAsyncKeyState(VK_RIGHT)) axis[0]+=push;
|
|
||||||
if (GetAsyncKeyState(VK_DOWN )) axis[1]-=push;
|
|
||||||
if (GetAsyncKeyState(VK_UP )) axis[1]+=push;
|
|
||||||
for (i=0;i<4;i++) Inp.axis[i]=(short)axis[i];
|
|
||||||
|
|
||||||
if (GetAsyncKeyState(VK_RETURN)) Inp.button[4]=0xff; // Start
|
|
||||||
//if (GetAsyncKeyState(VK_ESCAPE)) Inp.button[7]=0xff; // Right thumb
|
|
||||||
|
|
||||||
if (GetAsyncKeyState('Z')) Inp.button[10]=0xff;
|
|
||||||
if (GetAsyncKeyState('X')) Inp.button[ 8]=0xff;
|
|
||||||
if (GetAsyncKeyState('C')) Inp.button[ 9]=0xff;
|
|
||||||
|
|
||||||
if (GetAsyncKeyState('A')) Inp.button[13]=0xff;
|
|
||||||
if (GetAsyncKeyState('S')) Inp.button[12]=0xff;
|
|
||||||
if (GetAsyncKeyState('D')) Inp.button[11]=0xff;
|
|
||||||
if (GetAsyncKeyState('F')) Inp.button[14]=0xff;
|
|
||||||
|
|
||||||
static int sblobked = 0;
|
|
||||||
if (!sblobked && GetAsyncKeyState(VK_TAB)) {
|
|
||||||
PicoReset();
|
|
||||||
sblobked = 1;
|
|
||||||
}
|
|
||||||
else if (!sblobked && GetAsyncKeyState(VK_ESCAPE))
|
|
||||||
{
|
|
||||||
PostMessage(FrameWnd, WM_COMMAND, 0x20000 | 1000, 0);
|
|
||||||
sblobked = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
sblobked = GetAsyncKeyState(VK_TAB) | GetAsyncKeyState(VK_ESCAPE);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int InputInit()
|
|
||||||
{
|
|
||||||
memset(&Inp,0,sizeof(Inp));
|
|
||||||
#ifdef _XBOX
|
|
||||||
memset(&Pad,0,sizeof(Pad));
|
|
||||||
XInitDevices(0,NULL);
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputExit()
|
|
||||||
{
|
|
||||||
#ifdef _XBOX
|
|
||||||
if (GamePad) XInputClose(GamePad);
|
|
||||||
GamePad=NULL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int InputUpdate()
|
|
||||||
{
|
|
||||||
int i=0;
|
|
||||||
int push=0x2000;
|
|
||||||
|
|
||||||
DeviceRead(); // Read XBox or PC device
|
|
||||||
|
|
||||||
// Use left analog for left digital too:
|
|
||||||
if (Inp.axis[1]>= push) Inp.button[0]|=0xff; // Up
|
|
||||||
if (Inp.axis[1]<=-push) Inp.button[1]|=0xff; // Down
|
|
||||||
if (Inp.axis[0]<=-push) Inp.button[2]|=0xff; // Left
|
|
||||||
if (Inp.axis[0]>= push) Inp.button[3]|=0xff; // Right
|
|
||||||
|
|
||||||
// Update debounce/time held information:
|
|
||||||
for (i=0;i<sizeof(Inp.held);i++)
|
|
||||||
{
|
|
||||||
if (Inp.held[i]==0)
|
|
||||||
{
|
|
||||||
if (Inp.button[i]>30) Inp.held[i]=1; // Just pressed
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Is the button still being held down?
|
|
||||||
Inp.held[i]++;
|
|
||||||
if (Inp.held[i]>=0x80) Inp.held[i]&=0xbf; // (Keep looping around)
|
|
||||||
|
|
||||||
if (Inp.button[i]<25) Inp.held[i]=0; // No
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Work out some key repeat values:
|
|
||||||
for (i=0;i<sizeof(Inp.repeat);i++)
|
|
||||||
{
|
|
||||||
char rep=0;
|
|
||||||
int held=Inp.held[i];
|
|
||||||
|
|
||||||
if (held==1) rep=1;
|
|
||||||
if (held>=0x20 && (held&1)) rep=1;
|
|
||||||
|
|
||||||
Inp.repeat[i]=rep;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set Lightgun calibration values:
|
|
||||||
int InputLightCal(int cx,int cy,int ux,int uy)
|
|
||||||
{
|
|
||||||
#ifdef _XBOX
|
|
||||||
XINPUT_LIGHTGUN_CALIBRATION_OFFSETS cal;
|
|
||||||
|
|
||||||
memset(&cal,0,sizeof(cal));
|
|
||||||
|
|
||||||
cal.wCenterX =(WORD)cx;
|
|
||||||
cal.wCenterY =(WORD)cy;
|
|
||||||
cal.wUpperLeftX=(WORD)ux;
|
|
||||||
cal.wUpperLeftY=(WORD)uy;
|
|
||||||
XInputSetLightgunCalibration(GamePad,&cal);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
(void)(cx+cy+ux+uy);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,143 +0,0 @@
|
||||||
#include "app.h"
|
|
||||||
//#include "FileMenu.h"
|
|
||||||
|
|
||||||
char LoopQuit=0,LoopWait=0,LoopWaiting=0;
|
|
||||||
static FILE *DebugFile=NULL;
|
|
||||||
int LoopMode=0;
|
|
||||||
static void UpdateSound(int len);
|
|
||||||
|
|
||||||
int LoopInit()
|
|
||||||
{
|
|
||||||
int ret=0;
|
|
||||||
|
|
||||||
// bits LSb->MSb:
|
|
||||||
// enable_ym2612&dac, enable_sn76496, enable_z80, stereo_sound;
|
|
||||||
// alt_renderer, 6button_gamepad, accurate_timing, accurate_sprites
|
|
||||||
PicoOpt=0xbccf;
|
|
||||||
PsndRate=44100;
|
|
||||||
|
|
||||||
// Init Direct3D:
|
|
||||||
ret=DirectInit(); if (ret) { error("DirectX video init failed"); return 1; }
|
|
||||||
InputInit();
|
|
||||||
|
|
||||||
// Init DirectSound:
|
|
||||||
//DSoundInit();
|
|
||||||
|
|
||||||
ret=EmuInit(); if (ret) return 1;
|
|
||||||
|
|
||||||
LoopMode=8;
|
|
||||||
PicoWriteSound = UpdateSound;
|
|
||||||
PicoAutoRgnOrder = 0x184;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" char *debugString();
|
|
||||||
|
|
||||||
void LoopExit()
|
|
||||||
{
|
|
||||||
dprintf(debugString());
|
|
||||||
|
|
||||||
EmuExit();
|
|
||||||
InputExit();
|
|
||||||
DirectExit();
|
|
||||||
|
|
||||||
if (DebugFile) fclose(DebugFile);
|
|
||||||
DebugFile=NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------
|
|
||||||
|
|
||||||
static void UpdateSound(int len)
|
|
||||||
{
|
|
||||||
while (DSoundUpdate() > 0) { Sleep(1); }
|
|
||||||
//while (DSoundUpdate()== 0) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
static void PostProcess()
|
|
||||||
{
|
|
||||||
static int lock_to_1_1_prev = 0, is_40_prev = -1;
|
|
||||||
int is_40;
|
|
||||||
PicoGetInternal(PI_IS40_CELL, (pint_ret_t *)&is_40);
|
|
||||||
if (lock_to_1_1)
|
|
||||||
{
|
|
||||||
if (is_40 != is_40_prev || !lock_to_1_1_prev)
|
|
||||||
PostMessage(FrameWnd, WM_COMMAND, 0x20000 | (is_40 ? 1100 : 1101), 0);
|
|
||||||
}
|
|
||||||
if (is_40 != is_40_prev)
|
|
||||||
{
|
|
||||||
EmuScreenRect.left = is_40 ? 0 : 32;
|
|
||||||
EmuScreenRect.right = is_40 ? 320 : 256+32;
|
|
||||||
}
|
|
||||||
lock_to_1_1_prev = lock_to_1_1;
|
|
||||||
is_40_prev = is_40;
|
|
||||||
}
|
|
||||||
|
|
||||||
int LoopCode()
|
|
||||||
{
|
|
||||||
|
|
||||||
// Main loop:
|
|
||||||
while (!LoopQuit)
|
|
||||||
{
|
|
||||||
if (LoopWait)
|
|
||||||
{
|
|
||||||
DSoundExit();
|
|
||||||
while (!LoopQuit && LoopWait) { LoopWaiting=1; Sleep(100); }
|
|
||||||
if (LoopQuit) break;
|
|
||||||
DSoundInit();
|
|
||||||
}
|
|
||||||
InputUpdate();
|
|
||||||
|
|
||||||
DirectClear(0);
|
|
||||||
EmuFrame();
|
|
||||||
PostProcess();
|
|
||||||
DirectScreen();
|
|
||||||
DirectPresent();
|
|
||||||
// UpdateSound();
|
|
||||||
}
|
|
||||||
DSoundExit();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
extern "C" int dprintf(char *format, ...)
|
|
||||||
{
|
|
||||||
char *name=NULL;
|
|
||||||
va_list val=NULL;
|
|
||||||
|
|
||||||
#ifdef _XBOX
|
|
||||||
name="d:\\zout.txt";
|
|
||||||
#else
|
|
||||||
name="zout.txt";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (DebugFile==NULL) DebugFile=fopen(name,"wt");
|
|
||||||
if (DebugFile==NULL) return 1;
|
|
||||||
|
|
||||||
fprintf(DebugFile, "%05i: ", emu_frame);
|
|
||||||
va_start(val,format);
|
|
||||||
vfprintf(DebugFile,format,val);
|
|
||||||
fprintf(DebugFile, "\n");
|
|
||||||
fflush(DebugFile);
|
|
||||||
|
|
||||||
va_end(val);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern "C" int lprintf(char *format, ...)
|
|
||||||
{
|
|
||||||
char str[512];
|
|
||||||
va_list val=NULL;
|
|
||||||
|
|
||||||
va_start(val,format);
|
|
||||||
vsprintf(str,format,val);
|
|
||||||
va_end(val);
|
|
||||||
OutputDebugString(str);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,576 +0,0 @@
|
||||||
#include "app.h"
|
|
||||||
#include "version.h"
|
|
||||||
#include <crtdbg.h>
|
|
||||||
#include <commdlg.h>
|
|
||||||
#include "../../common/readpng.h"
|
|
||||||
#include "../../common/config.h"
|
|
||||||
|
|
||||||
char *romname=NULL;
|
|
||||||
HWND FrameWnd=NULL;
|
|
||||||
RECT FrameRectMy;
|
|
||||||
int lock_to_1_1 = 1;
|
|
||||||
static HWND PicoSwWnd=NULL, PicoPadWnd=NULL;
|
|
||||||
|
|
||||||
int MainWidth=720,MainHeight=480;
|
|
||||||
|
|
||||||
static HMENU mmain = 0, mdisplay = 0, mpicohw = 0;
|
|
||||||
static int rom_loaded = 0;
|
|
||||||
static HBITMAP ppad_bmp = 0;
|
|
||||||
static HBITMAP ppage_bmps[7] = { 0, };
|
|
||||||
static char rom_name[0x20*3+1];
|
|
||||||
static int main_wnd_as_pad = 0;
|
|
||||||
|
|
||||||
static void UpdateRect()
|
|
||||||
{
|
|
||||||
WINDOWINFO wi;
|
|
||||||
memset(&wi, 0, sizeof(wi));
|
|
||||||
wi.cbSize = sizeof(wi);
|
|
||||||
GetWindowInfo(FrameWnd, &wi);
|
|
||||||
FrameRectMy = wi.rcClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int extract_rom_name(char *dest, const unsigned char *src, int len)
|
|
||||||
{
|
|
||||||
char *p = dest, s_old = 0x20;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = len - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
if (src[i^1] != ' ') break;
|
|
||||||
}
|
|
||||||
len = i + 1;
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
unsigned char s = src[i^1];
|
|
||||||
if (s == 0x20 && s_old == 0x20) continue;
|
|
||||||
else if (s >= 0x20 && s < 0x7f && s != '%')
|
|
||||||
{
|
|
||||||
*p++ = s;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sprintf(p, "%%%02x", s);
|
|
||||||
p += 3;
|
|
||||||
}
|
|
||||||
s_old = s;
|
|
||||||
}
|
|
||||||
*p = 0;
|
|
||||||
|
|
||||||
return p - dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void check_name_alias(const char *afname)
|
|
||||||
{
|
|
||||||
char buff[256], *var, *val;
|
|
||||||
FILE *f;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
f = fopen(afname, "r");
|
|
||||||
if (f == NULL) return;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
ret = config_get_var_val(f, buff, sizeof(buff), &var, &val);
|
|
||||||
if (ret == 0) break;
|
|
||||||
if (ret == -1) continue;
|
|
||||||
|
|
||||||
if (strcmp(rom_name, var) == 0) {
|
|
||||||
lprintf("rom aliased: \"%s\" -> \"%s\"\n", rom_name, val);
|
|
||||||
strncpy(rom_name, val, sizeof(rom_name));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
static HBITMAP png2hb(const char *fname, int is_480)
|
|
||||||
{
|
|
||||||
BITMAPINFOHEADER bih;
|
|
||||||
HBITMAP bmp;
|
|
||||||
void *bmem;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
bmem = calloc(1, is_480 ? 480*240*3 : 320*240*3);
|
|
||||||
if (bmem == NULL) return NULL;
|
|
||||||
ret = readpng(bmem, fname, is_480 ? READPNG_480_24 : READPNG_320_24);
|
|
||||||
if (ret != 0) {
|
|
||||||
free(bmem);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&bih, 0, sizeof(bih));
|
|
||||||
bih.biSize = sizeof(bih);
|
|
||||||
bih.biWidth = is_480 ? 480 : 320;
|
|
||||||
bih.biHeight = -240;
|
|
||||||
bih.biPlanes = 1;
|
|
||||||
bih.biBitCount = 24;
|
|
||||||
bih.biCompression = BI_RGB;
|
|
||||||
bmp = CreateDIBitmap(GetDC(FrameWnd), &bih, CBM_INIT, bmem, (BITMAPINFO *)&bih, 0);
|
|
||||||
if (bmp == NULL)
|
|
||||||
lprintf("CreateDIBitmap failed with %i", GetLastError());
|
|
||||||
|
|
||||||
free(bmem);
|
|
||||||
return bmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void PrepareForROM(void)
|
|
||||||
{
|
|
||||||
unsigned char *rom_data = NULL;
|
|
||||||
int i, ret, show = PicoAHW & PAHW_PICO;
|
|
||||||
|
|
||||||
PicoGetInternal(PI_ROM, (pint_ret_t *) &rom_data);
|
|
||||||
EnableMenuItem(mmain, 2, MF_BYPOSITION|(show ? MF_ENABLED : MF_GRAYED));
|
|
||||||
ShowWindow(PicoPadWnd, show ? SW_SHOWNA : SW_HIDE);
|
|
||||||
ShowWindow(PicoSwWnd, show ? SW_SHOWNA : SW_HIDE);
|
|
||||||
CheckMenuItem(mpicohw, 1210, show ? MF_CHECKED : MF_UNCHECKED);
|
|
||||||
CheckMenuItem(mpicohw, 1211, show ? MF_CHECKED : MF_UNCHECKED);
|
|
||||||
PostMessage(FrameWnd, WM_COMMAND, 1220 + PicoPicohw.page, 0);
|
|
||||||
DrawMenuBar(FrameWnd);
|
|
||||||
InvalidateRect(PicoSwWnd, NULL, 1);
|
|
||||||
|
|
||||||
PicoPicohw.pen_pos[0] =
|
|
||||||
PicoPicohw.pen_pos[1] = 0x8000;
|
|
||||||
PicoPadAdd = 0;
|
|
||||||
|
|
||||||
ret = extract_rom_name(rom_name, rom_data + 0x150, 0x20);
|
|
||||||
if (ret == 0)
|
|
||||||
extract_rom_name(rom_name, rom_data + 0x130, 0x20);
|
|
||||||
|
|
||||||
if (show)
|
|
||||||
{
|
|
||||||
char path[MAX_PATH], *p;
|
|
||||||
GetModuleFileName(NULL, path, sizeof(path) - 32);
|
|
||||||
p = strrchr(path, '\\');
|
|
||||||
if (p == NULL) p = path;
|
|
||||||
else p++;
|
|
||||||
if (ppad_bmp == NULL) {
|
|
||||||
strcpy(p, "pico\\pad.png");
|
|
||||||
ppad_bmp = png2hb(path, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(p, "pico\\alias.txt");
|
|
||||||
check_name_alias(path);
|
|
||||||
|
|
||||||
for (i = 0; i < 7; i++) {
|
|
||||||
if (ppage_bmps[i] != NULL) DeleteObject(ppage_bmps[i]);
|
|
||||||
sprintf(p, "pico\\%s_%i.png", rom_name, i);
|
|
||||||
ppage_bmps[i] = png2hb(path, 1);
|
|
||||||
}
|
|
||||||
// games usually don't have page 6, so just duplicate page 5.
|
|
||||||
if (ppage_bmps[6] == NULL && ppage_bmps[5] != NULL) {
|
|
||||||
sprintf(p, "pico\\%s_5.png", rom_name);
|
|
||||||
ppage_bmps[6] = png2hb(path, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void LoadROM(const char *cmdpath)
|
|
||||||
{
|
|
||||||
static char rompath[MAX_PATH] = { 0, };
|
|
||||||
unsigned char *rom_data_new = NULL;
|
|
||||||
unsigned int rom_size = 0;
|
|
||||||
pm_file *rom = NULL;
|
|
||||||
int oldwait=LoopWait;
|
|
||||||
int i, ret;
|
|
||||||
|
|
||||||
if (cmdpath) {
|
|
||||||
strcpy(rompath, cmdpath + (cmdpath[0] == '\"' ? 1 : 0));
|
|
||||||
if (rompath[strlen(rompath)-1] == '\"') rompath[strlen(rompath)-1] = 0;
|
|
||||||
if (strlen(rompath) > 4) rom = pm_open(rompath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rom) {
|
|
||||||
OPENFILENAME of; ZeroMemory(&of, sizeof(OPENFILENAME));
|
|
||||||
of.lStructSize = sizeof(OPENFILENAME);
|
|
||||||
of.lpstrFilter = "ROMs\0*.smd;*.bin;*.gen;*.zip\0";
|
|
||||||
of.lpstrFile = rompath; rompath[0] = 0;
|
|
||||||
of.nMaxFile = MAX_PATH;
|
|
||||||
of.Flags = OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
|
|
||||||
of.hwndOwner = FrameWnd;
|
|
||||||
if (!GetOpenFileName(&of)) return;
|
|
||||||
rom = pm_open(rompath);
|
|
||||||
if (!rom) { error("failed to open ROM"); return; }
|
|
||||||
}
|
|
||||||
|
|
||||||
ret=PicoCartLoad(rom, &rom_data_new, &rom_size);
|
|
||||||
pm_close(rom);
|
|
||||||
if (ret) {
|
|
||||||
error("failed to load ROM");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// halt the work thread..
|
|
||||||
// just a hack, should've used proper sync. primitives here, but who will use this emu anyway..
|
|
||||||
LoopWaiting=0;
|
|
||||||
LoopWait=1;
|
|
||||||
for (i = 0; LoopWaiting == 0 && i < 10; i++) Sleep(100);
|
|
||||||
|
|
||||||
PicoCartUnload();
|
|
||||||
PicoCartInsert(rom_data_new, rom_size);
|
|
||||||
|
|
||||||
PrepareForROM();
|
|
||||||
|
|
||||||
rom_loaded = 1;
|
|
||||||
romname = rompath;
|
|
||||||
LoopWait=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int rect_widths[4] = { 320, 256, 640, 512 };
|
|
||||||
static int rect_heights[4] = { 224, 224, 448, 448 };
|
|
||||||
|
|
||||||
// Window proc for the frame window:
|
|
||||||
static LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
|
|
||||||
{
|
|
||||||
POINT pt;
|
|
||||||
RECT rc;
|
|
||||||
int i;
|
|
||||||
switch (msg)
|
|
||||||
{
|
|
||||||
case WM_CLOSE: PostQuitMessage(0); return 0;
|
|
||||||
case WM_DESTROY: FrameWnd=NULL; break; // Blank handle
|
|
||||||
case WM_SIZE:
|
|
||||||
case WM_MOVE:
|
|
||||||
case WM_SIZING: UpdateRect(); break;
|
|
||||||
case WM_COMMAND:
|
|
||||||
switch (LOWORD(wparam))
|
|
||||||
{
|
|
||||||
case 1000: LoadROM(NULL); break;
|
|
||||||
case 1001: PicoReset(); return 0;
|
|
||||||
case 1002: PostQuitMessage(0); return 0;
|
|
||||||
case 1100:
|
|
||||||
case 1101:
|
|
||||||
case 1102:
|
|
||||||
case 1103:
|
|
||||||
LoopWait=1; // another sync hack
|
|
||||||
for (i = 0; !LoopWaiting && i < 10; i++) Sleep(10);
|
|
||||||
FrameRectMy.right = FrameRectMy.left + rect_widths[wparam&3];
|
|
||||||
FrameRectMy.bottom = FrameRectMy.top + rect_heights[wparam&3];
|
|
||||||
AdjustWindowRect(&FrameRectMy, WS_OVERLAPPEDWINDOW, 1);
|
|
||||||
MoveWindow(hwnd, FrameRectMy.left, FrameRectMy.top,
|
|
||||||
FrameRectMy.right-FrameRectMy.left, FrameRectMy.bottom-FrameRectMy.top, 1);
|
|
||||||
UpdateRect();
|
|
||||||
if (HIWORD(wparam) == 0) { // locally sent
|
|
||||||
lock_to_1_1=0;
|
|
||||||
CheckMenuItem(mdisplay, 1104, MF_UNCHECKED);
|
|
||||||
}
|
|
||||||
if (rom_loaded) LoopWait=0;
|
|
||||||
return 0;
|
|
||||||
case 1104:
|
|
||||||
lock_to_1_1=!lock_to_1_1;
|
|
||||||
CheckMenuItem(mdisplay, 1104, lock_to_1_1 ? MF_CHECKED : MF_UNCHECKED);
|
|
||||||
return 0;
|
|
||||||
case 1210:
|
|
||||||
case 1211:
|
|
||||||
i = IsWindowVisible((LOWORD(wparam)&1) ? PicoPadWnd : PicoSwWnd);
|
|
||||||
i = !i;
|
|
||||||
ShowWindow((LOWORD(wparam)&1) ? PicoPadWnd : PicoSwWnd, i ? SW_SHOWNA : SW_HIDE);
|
|
||||||
CheckMenuItem(mpicohw, LOWORD(wparam), i ? MF_CHECKED : MF_UNCHECKED);
|
|
||||||
return 0;
|
|
||||||
case 1212:
|
|
||||||
main_wnd_as_pad = !main_wnd_as_pad;
|
|
||||||
CheckMenuItem(mpicohw, 1212, main_wnd_as_pad ? MF_CHECKED : MF_UNCHECKED);
|
|
||||||
return 0;
|
|
||||||
case 1220:
|
|
||||||
case 1221:
|
|
||||||
case 1222:
|
|
||||||
case 1223:
|
|
||||||
case 1224:
|
|
||||||
case 1225:
|
|
||||||
case 1226:
|
|
||||||
PicoPicohw.page = LOWORD(wparam) % 10;
|
|
||||||
for (i = 0; i < 7; i++)
|
|
||||||
CheckMenuItem(mpicohw, 1220 + i, MF_UNCHECKED);
|
|
||||||
CheckMenuItem(mpicohw, 1220 + PicoPicohw.page, MF_CHECKED);
|
|
||||||
InvalidateRect(PicoSwWnd, NULL, 1);
|
|
||||||
return 0;
|
|
||||||
case 1300:
|
|
||||||
MessageBox(FrameWnd, "PicoDrive v" VERSION " (c) notaz, 2006-2008\n"
|
|
||||||
"SVP and Pico demo edition\n\n"
|
|
||||||
"Credits:\n"
|
|
||||||
"fDave: base code of PicoDrive, GenaDrive (the frontend)\n"
|
|
||||||
"Chui: Fame/C\n"
|
|
||||||
"NJ: CZ80\n"
|
|
||||||
"MAME devs: YM2612 and SN76496 cores\n"
|
|
||||||
"Stéphane Dallongeville: Gens code, base of Fame/C (C68K), CZ80\n"
|
|
||||||
"Tasco Deluxe: SVP RE work\n"
|
|
||||||
"Pierpaolo Prazzoli: info about SSP16 chips\n",
|
|
||||||
"About", 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case WM_TIMER:
|
|
||||||
GetCursorPos(&pt);
|
|
||||||
GetWindowRect(PicoSwWnd, &rc);
|
|
||||||
if (PtInRect(&rc, pt)) break;
|
|
||||||
GetWindowRect(PicoPadWnd, &rc);
|
|
||||||
if (PtInRect(&rc, pt)) break;
|
|
||||||
PicoPicohw.pen_pos[0] |= 0x8000;
|
|
||||||
PicoPicohw.pen_pos[1] |= 0x8000;
|
|
||||||
PicoPadAdd = 0;
|
|
||||||
break;
|
|
||||||
case WM_LBUTTONDOWN: PicoPadAdd |= 0x20; return 0;
|
|
||||||
case WM_LBUTTONUP: PicoPadAdd &= ~0x20; return 0;
|
|
||||||
case WM_MOUSEMOVE:
|
|
||||||
if (!main_wnd_as_pad) break;
|
|
||||||
PicoPicohw.pen_pos[0] = 0x03c + (320 * LOWORD(lparam) / (FrameRectMy.right - FrameRectMy.left));
|
|
||||||
PicoPicohw.pen_pos[1] = 0x1fc + (232 * HIWORD(lparam) / (FrameRectMy.bottom - FrameRectMy.top));
|
|
||||||
SetTimer(FrameWnd, 100, 1000, NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DefWindowProc(hwnd,msg,wparam,lparam);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void key_down(WPARAM key)
|
|
||||||
{
|
|
||||||
switch (key) {
|
|
||||||
case VK_LEFT: PicoPadAdd |= 4; break;
|
|
||||||
case VK_RIGHT: PicoPadAdd |= 8; break;
|
|
||||||
case VK_UP: PicoPadAdd |= 1; break;
|
|
||||||
case VK_DOWN: PicoPadAdd |= 2; break;
|
|
||||||
case 'X': PicoPadAdd |= 0x10; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void key_up(WPARAM key)
|
|
||||||
{
|
|
||||||
switch (key) {
|
|
||||||
case VK_LEFT: PicoPadAdd &= ~0x04; break;
|
|
||||||
case VK_RIGHT: PicoPadAdd &= ~0x08; break;
|
|
||||||
case VK_UP: PicoPadAdd &= ~0x01; break;
|
|
||||||
case VK_DOWN: PicoPadAdd &= ~0x02; break;
|
|
||||||
case 'X': PicoPadAdd &= ~0x10; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static LRESULT CALLBACK PicoSwWndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
|
|
||||||
{
|
|
||||||
PAINTSTRUCT ps;
|
|
||||||
HDC hdc, hdc2;
|
|
||||||
|
|
||||||
switch (msg)
|
|
||||||
{
|
|
||||||
case WM_DESTROY: PicoSwWnd=NULL; break;
|
|
||||||
case WM_LBUTTONDOWN: PicoPadAdd |= 0x20; return 0;
|
|
||||||
case WM_LBUTTONUP: PicoPadAdd &= ~0x20; return 0;
|
|
||||||
case WM_MOUSEMOVE:
|
|
||||||
if (HIWORD(lparam) < 0x20) break;
|
|
||||||
PicoPicohw.pen_pos[0] = 0x03c + LOWORD(lparam) * 2/3;
|
|
||||||
PicoPicohw.pen_pos[1] = 0x2f8 + HIWORD(lparam) - 0x20;
|
|
||||||
SetTimer(FrameWnd, 100, 1000, NULL);
|
|
||||||
break;
|
|
||||||
case WM_KEYDOWN: key_down(wparam); break;
|
|
||||||
case WM_KEYUP: key_up(wparam); break;
|
|
||||||
case WM_PAINT:
|
|
||||||
hdc = BeginPaint(hwnd, &ps);
|
|
||||||
if (ppage_bmps[PicoPicohw.page] == NULL)
|
|
||||||
{
|
|
||||||
SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
|
|
||||||
SetTextColor(hdc, RGB(255, 255, 255));
|
|
||||||
SetBkColor(hdc, RGB(0, 0, 0));
|
|
||||||
TextOut(hdc, 2, 2, "missing PNGs for", 16);
|
|
||||||
TextOut(hdc, 2, 18, rom_name, strlen(rom_name));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hdc2 = CreateCompatibleDC(GetDC(FrameWnd));
|
|
||||||
SelectObject(hdc2, ppage_bmps[PicoPicohw.page]);
|
|
||||||
BitBlt(hdc, 0, 0, 480, 240, hdc2, 0, 0, SRCCOPY);
|
|
||||||
DeleteDC(hdc2);
|
|
||||||
}
|
|
||||||
EndPaint(hwnd, &ps);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DefWindowProc(hwnd,msg,wparam,lparam);
|
|
||||||
}
|
|
||||||
|
|
||||||
static LRESULT CALLBACK PicoPadWndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
|
|
||||||
{
|
|
||||||
PAINTSTRUCT ps;
|
|
||||||
HDC hdc, hdc2;
|
|
||||||
|
|
||||||
switch (msg)
|
|
||||||
{
|
|
||||||
case WM_DESTROY: PicoPadWnd=NULL; break;
|
|
||||||
case WM_LBUTTONDOWN: PicoPadAdd |= 0x20; return 0;
|
|
||||||
case WM_LBUTTONUP: PicoPadAdd &= ~0x20; return 0;
|
|
||||||
case WM_MOUSEMOVE:
|
|
||||||
PicoPicohw.pen_pos[0] = 0x03c + LOWORD(lparam);
|
|
||||||
PicoPicohw.pen_pos[1] = 0x1fc + HIWORD(lparam);
|
|
||||||
SetTimer(FrameWnd, 100, 1000, NULL);
|
|
||||||
break;
|
|
||||||
case WM_KEYDOWN: key_down(wparam); break;
|
|
||||||
case WM_KEYUP: key_up(wparam); break;
|
|
||||||
case WM_PAINT:
|
|
||||||
if (ppad_bmp == NULL) break;
|
|
||||||
hdc = BeginPaint(hwnd, &ps);
|
|
||||||
hdc2 = CreateCompatibleDC(GetDC(FrameWnd));
|
|
||||||
SelectObject(hdc2, ppad_bmp);
|
|
||||||
BitBlt(hdc, 0, 0, 320, 240, hdc2, 0, 0, SRCCOPY);
|
|
||||||
EndPaint(hwnd, &ps);
|
|
||||||
DeleteDC(hdc2);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DefWindowProc(hwnd,msg,wparam,lparam);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int FrameInit()
|
|
||||||
{
|
|
||||||
WNDCLASS wc;
|
|
||||||
RECT rect={0,0,0,0};
|
|
||||||
HMENU mfile;
|
|
||||||
int style=0;
|
|
||||||
int left=0,top=0,width=0,height=0;
|
|
||||||
|
|
||||||
memset(&wc,0,sizeof(wc));
|
|
||||||
|
|
||||||
// Register the window class:
|
|
||||||
wc.lpfnWndProc=WndProc;
|
|
||||||
wc.hInstance=GetModuleHandle(NULL);
|
|
||||||
wc.hCursor=LoadCursor(NULL,IDC_ARROW);
|
|
||||||
wc.hbrBackground=CreateSolidBrush(0);
|
|
||||||
wc.lpszClassName="PicoMainFrame";
|
|
||||||
RegisterClass(&wc);
|
|
||||||
|
|
||||||
wc.lpszClassName="PicoSwWnd";
|
|
||||||
wc.lpfnWndProc=PicoSwWndProc;
|
|
||||||
RegisterClass(&wc);
|
|
||||||
|
|
||||||
wc.lpszClassName="PicoPadWnd";
|
|
||||||
wc.lpfnWndProc=PicoPadWndProc;
|
|
||||||
RegisterClass(&wc);
|
|
||||||
|
|
||||||
rect.right =320;//MainWidth;
|
|
||||||
rect.bottom=224;//MainHeight;
|
|
||||||
|
|
||||||
// Adjust size of windows based on borders:
|
|
||||||
style=WS_OVERLAPPEDWINDOW;
|
|
||||||
AdjustWindowRect(&rect,style,1);
|
|
||||||
width =rect.right-rect.left;
|
|
||||||
height=rect.bottom-rect.top;
|
|
||||||
|
|
||||||
// Place window in the centre of the screen:
|
|
||||||
SystemParametersInfo(SPI_GETWORKAREA,0,&rect,0);
|
|
||||||
left=rect.left+rect.right;
|
|
||||||
top=rect.top+rect.bottom;
|
|
||||||
|
|
||||||
left-=width; left>>=1;
|
|
||||||
top-=height; top>>=1;
|
|
||||||
|
|
||||||
// Create menu:
|
|
||||||
mfile = CreateMenu();
|
|
||||||
InsertMenu(mfile, -1, MF_BYPOSITION|MF_STRING, 1000, "&Load ROM");
|
|
||||||
InsertMenu(mfile, -1, MF_BYPOSITION|MF_STRING, 1001, "&Reset");
|
|
||||||
InsertMenu(mfile, -1, MF_BYPOSITION|MF_STRING, 1002, "E&xit");
|
|
||||||
mdisplay = CreateMenu();
|
|
||||||
InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1100, "320x224");
|
|
||||||
InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1101, "256x224");
|
|
||||||
InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1102, "640x448");
|
|
||||||
InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1103, "512x448");
|
|
||||||
InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1104, "Lock to 1:1");
|
|
||||||
mpicohw = CreateMenu();
|
|
||||||
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1210, "Show &Storyware");
|
|
||||||
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1211, "Show &Drawing pad");
|
|
||||||
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1212, "&Main window as pad");
|
|
||||||
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_SEPARATOR, 0, NULL);
|
|
||||||
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1220, "Title page (&0)");
|
|
||||||
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1221, "Page &1");
|
|
||||||
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1222, "Page &2");
|
|
||||||
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1223, "Page &3");
|
|
||||||
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1224, "Page &4");
|
|
||||||
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1225, "Page &5");
|
|
||||||
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1226, "Page &6");
|
|
||||||
mmain = CreateMenu();
|
|
||||||
InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, (UINT_PTR) mfile, "&File");
|
|
||||||
InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, (UINT_PTR) mdisplay, "&Display");
|
|
||||||
InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, (UINT_PTR) mpicohw, "&Pico");
|
|
||||||
EnableMenuItem(mmain, 2, MF_BYPOSITION|MF_GRAYED);
|
|
||||||
// InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, 1200, "&Config");
|
|
||||||
InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING, 1300, "&About");
|
|
||||||
|
|
||||||
// Create the window:
|
|
||||||
FrameWnd=CreateWindow("PicoMainFrame","PicoDrive " VERSION,style|WS_VISIBLE,
|
|
||||||
left,top,width,height,NULL,mmain,NULL,NULL);
|
|
||||||
|
|
||||||
CheckMenuItem(mdisplay, 1104, lock_to_1_1 ? MF_CHECKED : MF_UNCHECKED);
|
|
||||||
ShowWindow(FrameWnd, SW_NORMAL);
|
|
||||||
UpdateWindow(FrameWnd);
|
|
||||||
UpdateRect();
|
|
||||||
|
|
||||||
// create Pico windows
|
|
||||||
style = WS_OVERLAPPED|WS_CAPTION|WS_BORDER;
|
|
||||||
rect.left=rect.top=0;
|
|
||||||
rect.right =320;
|
|
||||||
rect.bottom=224;
|
|
||||||
|
|
||||||
AdjustWindowRect(&rect,style,1);
|
|
||||||
width =rect.right-rect.left;
|
|
||||||
height=rect.bottom-rect.top;
|
|
||||||
|
|
||||||
left += 326;
|
|
||||||
PicoSwWnd=CreateWindow("PicoSwWnd","Storyware",style,
|
|
||||||
left,top,width+160,height,FrameWnd,NULL,NULL,NULL);
|
|
||||||
|
|
||||||
top += 266;
|
|
||||||
PicoPadWnd=CreateWindow("PicoPadWnd","Drawing Pad",style,
|
|
||||||
left,top,width,height,FrameWnd,NULL,NULL,NULL);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------
|
|
||||||
|
|
||||||
static DWORD WINAPI ThreadCode(void *)
|
|
||||||
{
|
|
||||||
LoopCode();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR cmdline,int)
|
|
||||||
{
|
|
||||||
MSG msg;
|
|
||||||
int ret=0;
|
|
||||||
DWORD tid=0;
|
|
||||||
HANDLE thread=NULL;
|
|
||||||
|
|
||||||
FrameInit();
|
|
||||||
ret=LoopInit(); if (ret) goto end0;
|
|
||||||
|
|
||||||
// Make another thread to run LoopCode():
|
|
||||||
LoopQuit=0;
|
|
||||||
LoopWait=1; // wait for ROM to be loaded
|
|
||||||
thread=CreateThread(NULL,0,ThreadCode,NULL,0,&tid);
|
|
||||||
|
|
||||||
LoadROM(cmdline);
|
|
||||||
|
|
||||||
// Main window loop:
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
GetMessage(&msg,NULL,0,0);
|
|
||||||
if (msg.message==WM_QUIT) break;
|
|
||||||
|
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessage(&msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Signal thread to quit and wait for it to exit:
|
|
||||||
LoopQuit=1; WaitForSingleObject(thread,5000);
|
|
||||||
CloseHandle(thread); thread=NULL;
|
|
||||||
|
|
||||||
end0:
|
|
||||||
LoopExit();
|
|
||||||
DestroyWindow(FrameWnd);
|
|
||||||
|
|
||||||
_CrtDumpMemoryLeaks();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void error(char *text)
|
|
||||||
{
|
|
||||||
MessageBox(FrameWnd, text, "Error", 0);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
# Makefile for MS Visual C
|
|
||||||
|
|
||||||
R=..\..\..\
|
|
||||||
|
|
||||||
CFLAGS=/nologo /W2 /O2 /D "_CRT_SECURE_NO_WARNINGS" -I. -I$(R) -I$(R)zlib\
|
|
||||||
|
|
||||||
LDFLAGS=/nologo /machine:I386 /opt:nowin98 /out:PicoDrive.exe
|
|
||||||
|
|
||||||
CFLAGS=$(CFLAGS) /DEMU_F68K
|
|
||||||
|
|
||||||
CFLAGS=$(CFLAGS) /D_USE_CZ80
|
|
||||||
|
|
||||||
# debug
|
|
||||||
#CFLAGS=$(CFLAGS) /Gi
|
|
||||||
|
|
||||||
#LDFLAGS=$(LDFLAGS) /DEBUG
|
|
||||||
|
|
||||||
# emu
|
|
||||||
OBJ = Emu.obj Input.obj Main.obj Direct.obj DSound.obj Loop.obj
|
|
||||||
|
|
||||||
# TexScreen.obj
|
|
||||||
|
|
||||||
# common
|
|
||||||
#OBJS += platform\common\emu.obj platform\common\menu.obj platform\common\fonts.obj
|
|
||||||
# platform\common\mp3_helix.obj
|
|
||||||
OBJ = $(OBJ) $(R)platform\common\readpng.obj $(R)platform\common\config.obj
|
|
||||||
|
|
||||||
# Pico
|
|
||||||
OBJ = $(OBJ) $(R)Pico\Area.obj $(R)Pico\Cart.obj $(R)Pico\Memory.obj $(R)Pico\Misc.obj $(R)Pico\Pico.obj $(R)Pico\Sek.obj \
|
|
||||||
$(R)Pico\VideoPort.obj $(R)Pico\Draw2.obj $(R)Pico\Draw.obj $(R)Pico\Patch.obj
|
|
||||||
# Pico - CD
|
|
||||||
OBJ = $(OBJ) $(R)Pico\cd\Pico.obj $(R)Pico\cd\Memory.obj $(R)Pico\cd\Sek.obj $(R)Pico\cd\LC89510.obj \
|
|
||||||
$(R)Pico\cd\cd_sys.obj $(R)Pico\cd\cd_file.obj $(R)Pico\cd\gfx_cd.obj \
|
|
||||||
$(R)Pico\cd\Area.obj $(R)Pico\cd\Misc.obj $(R)Pico\cd\pcm.obj $(R)Pico\cd\buffering.obj \
|
|
||||||
$(R)Pico\cd\cue.obj
|
|
||||||
# Pico - Pico
|
|
||||||
OBJ = $(OBJ) $(R)Pico\Pico\Pico.obj $(R)Pico\Pico\Memory.obj $(R)Pico\Pico\xpcm.obj
|
|
||||||
# Pico - sound
|
|
||||||
OBJ = $(OBJ) $(R)Pico\sound\sound.obj $(R)Pico\sound\sn76496.obj $(R)Pico\sound\ym2612.obj $(R)Pico\sound\mix.obj
|
|
||||||
# Pico - carthw
|
|
||||||
OBJ = $(OBJ) $(R)Pico\carthw\carthw.obj $(R)Pico\carthw\svp\svp.obj $(R)Pico\carthw\svp\Memory.obj \
|
|
||||||
$(R)Pico\carthw\svp\ssp16.obj $(R)Pico\carthw\svp\compiler.obj
|
|
||||||
# zlib
|
|
||||||
OBJ = $(OBJ) $(R)zlib\gzio.obj $(R)zlib\inffast.obj $(R)zlib\inflate.obj $(R)zlib\inftrees.obj $(R)zlib\trees.obj \
|
|
||||||
$(R)zlib\deflate.obj $(R)zlib\crc32.obj $(R)zlib\adler32.obj $(R)zlib\zutil.obj $(R)zlib\compress.obj $(R)zlib\uncompr.obj
|
|
||||||
# unzip
|
|
||||||
OBJ = $(OBJ) $(R)unzip\unzip.obj $(R)unzip\unzip_stream.obj
|
|
||||||
# CPU cores
|
|
||||||
OBJ = $(OBJ) $(R)cpu\fame\famec.obj
|
|
||||||
# z80
|
|
||||||
OBJ = $(OBJ) $(R)cpu\cz80\cz80.obj
|
|
||||||
|
|
||||||
|
|
||||||
.c.obj:
|
|
||||||
cl $(CFLAGS) /c $< /Fo$@
|
|
||||||
|
|
||||||
.cpp.obj:
|
|
||||||
cl $(CFLAGS) /c $< /Fo$@
|
|
||||||
|
|
||||||
|
|
||||||
ALL : PicoDrive.exe
|
|
||||||
|
|
||||||
PicoDrive.exe : $(OBJ)
|
|
||||||
link.exe $(LDFLAGS) $(OBJ) libpng.lib gdi32.lib user32.lib advapi32.lib dsound.lib comdlg32.lib ddraw.lib dxguid.lib
|
|
||||||
|
|
||||||
# d3d8.lib d3dx8.lib
|
|
||||||
|
|
||||||
clean:
|
|
||||||
-del $(OBJ) PicoDrive.exe
|
|
||||||
|
|
||||||
|
|
||||||
test.exe : test.cpp
|
|
||||||
cl $(CFLAGS) test.cpp user32.lib d3dx8.lib d3d8.lib
|
|
||||||
|
|
||||||
dxtut1.exe : dxtut1.cpp
|
|
||||||
cl $(CFLAGS) dxtut1.cpp user32.lib d3d8.lib
|
|
||||||
|
|
||||||
# d3dx8.lib
|
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
|
|
||||||
#include "app.h"
|
|
||||||
|
|
||||||
IDirect3DTexture8 *TexScreen=NULL;
|
|
||||||
int TexWidth=0,TexHeight=0;
|
|
||||||
|
|
||||||
// Blank the texture:
|
|
||||||
static int TexBlank()
|
|
||||||
{
|
|
||||||
D3DLOCKED_RECT lock={0,NULL};
|
|
||||||
unsigned char *dest=NULL;
|
|
||||||
int y=0,line=0;
|
|
||||||
|
|
||||||
TexScreen->LockRect(0,&lock,NULL,0); if (lock.pBits==NULL) return 1;
|
|
||||||
|
|
||||||
dest=(unsigned char *)lock.pBits;
|
|
||||||
for (y=0; y<TexHeight; y++,line+=lock.Pitch)
|
|
||||||
{
|
|
||||||
memset(dest+line,0,TexWidth<<1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TexScreen->UnlockRect(0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int TexScreenInit()
|
|
||||||
{
|
|
||||||
TexWidth =512;
|
|
||||||
TexHeight=512;
|
|
||||||
|
|
||||||
Device->CreateTexture(TexWidth,TexHeight,1,0,D3DFMT_R5G6B5,D3DPOOL_MANAGED,&TexScreen);
|
|
||||||
if (TexScreen==NULL) return 1;
|
|
||||||
|
|
||||||
TexBlank();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TexScreenExit()
|
|
||||||
{
|
|
||||||
RELEASE(TexScreen)
|
|
||||||
TexWidth=TexHeight=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy screen to a swizzled texture
|
|
||||||
int TexScreenSwizzle()
|
|
||||||
{
|
|
||||||
D3DLOCKED_RECT lock={0,NULL};
|
|
||||||
unsigned char *dest=NULL;
|
|
||||||
int y=0,sy=0,mask=0;
|
|
||||||
unsigned short *ps=NULL;
|
|
||||||
|
|
||||||
mask=TexWidth*TexHeight-1;
|
|
||||||
|
|
||||||
TexScreen->LockRect(0,&lock,NULL,0); if (lock.pBits==NULL) return 1;
|
|
||||||
|
|
||||||
dest=(unsigned char *)lock.pBits;
|
|
||||||
ps=EmuScreen;
|
|
||||||
|
|
||||||
// Write to swizzled locations:
|
|
||||||
for (y=0,sy=0; y<EmuHeight; y++,sy++)
|
|
||||||
{
|
|
||||||
int x=0,sx=0;
|
|
||||||
sy|=0x55555555;
|
|
||||||
|
|
||||||
for (x=0,sx=0; x<EmuWidth; x++,sx++)
|
|
||||||
{
|
|
||||||
int addr=0;
|
|
||||||
|
|
||||||
sx|=0xaaaaaaaa;
|
|
||||||
addr=sx&sy&mask; // Calculate swizzled address
|
|
||||||
|
|
||||||
((unsigned short *)dest)[addr]=*ps++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TexScreen->UnlockRect(0);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy screen to a linear texture:
|
|
||||||
int TexScreenLinear()
|
|
||||||
{
|
|
||||||
D3DLOCKED_RECT lock={0,NULL};
|
|
||||||
unsigned char *dest=NULL;
|
|
||||||
int y=0,line=0;
|
|
||||||
unsigned short *ps=NULL;
|
|
||||||
|
|
||||||
TexScreen->LockRect(0,&lock,NULL,0);
|
|
||||||
if (lock.pBits==NULL) return 1;
|
|
||||||
|
|
||||||
dest=(unsigned char *)lock.pBits;
|
|
||||||
ps=EmuScreen;
|
|
||||||
|
|
||||||
for (y=0; y<EmuHeight; y++,line+=lock.Pitch)
|
|
||||||
{
|
|
||||||
int x=0;
|
|
||||||
int addr=line;
|
|
||||||
|
|
||||||
for (x=0; x<EmuWidth; x++,addr+=2)
|
|
||||||
{
|
|
||||||
*(unsigned int *)(dest+addr)=*ps++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TexScreen->UnlockRect(0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,85 +0,0 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <windows.h>
|
|
||||||
#include <d3d8.h>
|
|
||||||
|
|
||||||
#include <d3dx8.h>
|
|
||||||
|
|
||||||
#include <pico/pico.h>
|
|
||||||
|
|
||||||
#define RELEASE(x) if (x) x->Release(); x=NULL;
|
|
||||||
|
|
||||||
#ifndef __FUNCTION__
|
|
||||||
#define __FUNCTION__ ""
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LOGFAIL() lprintf("fail: %s %s:%i\n", __FUNCTION__, __FILE__, __LINE__)
|
|
||||||
|
|
||||||
|
|
||||||
// Emu.cpp
|
|
||||||
extern unsigned short *EmuScreen;
|
|
||||||
extern int EmuWidth,EmuHeight;
|
|
||||||
extern RECT EmuScreenRect;
|
|
||||||
extern int PicoPadAdd;
|
|
||||||
int EmuInit();
|
|
||||||
void EmuExit();
|
|
||||||
int EmuRomLoad(char *name);
|
|
||||||
int EmuFrame();
|
|
||||||
|
|
||||||
// Input.cpp
|
|
||||||
struct Input
|
|
||||||
{
|
|
||||||
short axis[4];
|
|
||||||
unsigned char button[16];
|
|
||||||
unsigned char held[16]; // How long has the button been held
|
|
||||||
char repeat[16]; // Auto-repeat
|
|
||||||
};
|
|
||||||
extern struct Input Inp;
|
|
||||||
int InputInit();
|
|
||||||
void InputExit();
|
|
||||||
int InputUpdate();
|
|
||||||
int InputLightCal(int cx,int cy,int ux,int uy);
|
|
||||||
|
|
||||||
// Loop.cpp
|
|
||||||
extern char LoopQuit,LoopWait,LoopWaiting;
|
|
||||||
extern int LoopMode;
|
|
||||||
|
|
||||||
int LoopInit();
|
|
||||||
void LoopExit();
|
|
||||||
int LoopCode();
|
|
||||||
//extern "C" int dprintf(char *format, ...);
|
|
||||||
extern "C" int lprintf(char *format, ...);
|
|
||||||
|
|
||||||
// Main.cpp
|
|
||||||
extern char *romname;
|
|
||||||
extern HWND FrameWnd;
|
|
||||||
extern RECT FrameRectMy;
|
|
||||||
extern int MainWidth,MainHeight;
|
|
||||||
extern int lock_to_1_1;
|
|
||||||
extern void error(char *text);
|
|
||||||
|
|
||||||
// --------------------------------------------
|
|
||||||
// Direct.cpp
|
|
||||||
extern IDirect3DDevice8 *Device;
|
|
||||||
extern IDirect3DSurface8 *DirectBack; // Back Buffer
|
|
||||||
int DirectInit();
|
|
||||||
int DirectClear(unsigned int colour);
|
|
||||||
int DirectScreen();
|
|
||||||
int DirectPresent();
|
|
||||||
void DirectExit();
|
|
||||||
|
|
||||||
// DSound.cpp:
|
|
||||||
int DSoundInit();
|
|
||||||
void DSoundExit();
|
|
||||||
int DSoundUpdate();
|
|
||||||
extern short *DSoundNext; // Buffer for next sound data to put in loop
|
|
||||||
|
|
||||||
// TexScreen.cpp
|
|
||||||
extern IDirect3DTexture8 *TexScreen;
|
|
||||||
extern int TexWidth,TexHeight;
|
|
||||||
int TexScreenInit();
|
|
||||||
void TexScreenExit();
|
|
||||||
int TexScreenSwizzle();
|
|
||||||
int TexScreenLinear();
|
|
|
@ -1,19 +0,0 @@
|
||||||
// port specific settings
|
|
||||||
|
|
||||||
#ifndef PORT_CONFIG_H
|
|
||||||
#define PORT_CONFIG_H
|
|
||||||
|
|
||||||
// draw2.c
|
|
||||||
#define START_ROW 0 // which row of tiles to start rendering at?
|
|
||||||
#define END_ROW 28 // ..end
|
|
||||||
|
|
||||||
#define SIMPLE_WRITE_SOUND 1
|
|
||||||
#define mix_32_to_16l_stereo_lvl mix_32_to_16l_stereo
|
|
||||||
|
|
||||||
// pico.c
|
|
||||||
#define CAN_HANDLE_240_LINES 0
|
|
||||||
|
|
||||||
#define dprintf
|
|
||||||
#define strcasecmp stricmp
|
|
||||||
|
|
||||||
#endif //PORT_CONFIG_H
|
|
|
@ -1,61 +0,0 @@
|
||||||
|
|
||||||
About
|
|
||||||
-----
|
|
||||||
|
|
||||||
This is a quick windows port of PicoDrive, a Megadrive / Genesis emulator for
|
|
||||||
handheld devices. It was originally coded having ARM CPU based devices in mind
|
|
||||||
(most work was done on GP2X version), but there is also a PSP port.
|
|
||||||
|
|
||||||
The sole purpose of this port is to demonstrate my SVP and Sega Pico emulation
|
|
||||||
code. This makes it one of the most minimal emulators out there. If you need
|
|
||||||
more features, you will have to wait until support is integrated in Kega,
|
|
||||||
Gens and the likes, as this emu was not meant to compete with them.
|
|
||||||
|
|
||||||
For more info, visit http://notaz.gp2x.de/svp.php
|
|
||||||
|
|
||||||
|
|
||||||
Releases
|
|
||||||
--------
|
|
||||||
|
|
||||||
1.40 - first release.
|
|
||||||
1.40a - Tasco Deluxe's dithering fix.
|
|
||||||
1.40b - Perspective fix thanks to Pierpaolo Prazzoli's info.
|
|
||||||
1.45 - Added preliminary Sega Pico emulation.
|
|
||||||
1.45a - Few bugfixes and additions.
|
|
||||||
|
|
||||||
|
|
||||||
Controls
|
|
||||||
--------
|
|
||||||
|
|
||||||
These are currently hardcoded, keyboard only:
|
|
||||||
|
|
||||||
PC Gen/MD Sega Pico
|
|
||||||
-------+-----------+---------
|
|
||||||
Enter: Start
|
|
||||||
Z: A
|
|
||||||
X: B red button
|
|
||||||
C: C pen push
|
|
||||||
TAB: (reset)
|
|
||||||
Esc: (load ROM)
|
|
||||||
Arrows: D-pad
|
|
||||||
|
|
||||||
|
|
||||||
Credits
|
|
||||||
-------
|
|
||||||
|
|
||||||
A lot of work on making SVP emulation happen was done by Tasco Deluxe, my
|
|
||||||
stuff is a continuation of his. Pierpaolo Prazzoli's information and his
|
|
||||||
SSP1610 disassembler in MAME code helped a lot too.
|
|
||||||
|
|
||||||
The original PicoDrive was written by fDave from finalburn.com
|
|
||||||
|
|
||||||
This PicoDrive version uses bits and pieces of from other projects:
|
|
||||||
|
|
||||||
68k: FAME/C core, by Chui and Stéphane Dallongeville (as C68K).
|
|
||||||
z80: CZ80 by Stéphane Dallongeville and modified by NJ.
|
|
||||||
YM2612 and SN76496 cores: MAME devs.
|
|
||||||
|
|
||||||
Special thanks to Rokas and Lordus for various ideas.
|
|
||||||
|
|
||||||
Greets to all the sceners and emu authors out there!
|
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
#define VERSION "1.45a"
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue