Files
ZSNES/zsnes/src/win/winlink.cpp
2005-06-13 18:32:30 +00:00

3085 lines
75 KiB
C++

/*
Copyright (C) 1997-2005 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
http://www.zsnes.com
http://sourceforge.net/projects/zsnes
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define DIRECTINPUT_VERSION 0x0800
#define DIRECTSOUND_VERSION 0x0800
extern "C" {
#include <windows.h>
#include <stdio.h>
#include <ddraw.h>
//#include <initguid.h>
#include <mmsystem.h>
#include <time.h>
}
#include <math.h>
#include <dsound.h>
#include <dinput.h>
#include <winuser.h>
#include "resource.h"
/*
December 17 2004 -Nach
I added some macros for inline assembly to keep compatibility between GCC and MSVC
ASM_BEGIN is to start an assembly section
ASM_END is to end it
ASM_COMMAND is for any simple command without a , in it example: dec eax
ASM_COMMAND2 is when a command has a , for example: add ebx, 5
ASM_COMMAND3 is when the parameter after the , is a variable example: mov eax, my_variable
ASM_CALL is for calling another function inside assembly section
asm_call() can be treated like any C function, use it to call an assembly function
from any normal C code.
*/
#ifdef __GNUC__ //MinGW
//Simple start and end structure, set as volatile so perhaps we can use -O1+ later
#define ASM_BEGIN asm volatile (
#define ASM_END );
//All commands need quotes and a newline and tab. C vars are _ prefixed
#define ASM_COMMAND(line) #line"\n\t"
#define ASM_COMMAND2(line, part2) #line", "#part2"\n\t"
#define ASM_COMMAND3(line, var) #line", _"#var"\n\t"
//Just for the prefix
#define ASM_CALL(func) ASM_COMMAND(call _ ## func)
//A function call is a simple register backup, call, restore
#define asm_call(func) ASM_BEGIN \
ASM_COMMAND(pushad) \
ASM_CALL(func) \
ASM_COMMAND(popad) \
ASM_END
#else //MSVC
#define ASM_BEGIN _asm {
#define ASM_END };
//MSVC is all straight foward about these
#define ASM_COMMAND(line) line
#define ASM_COMMAND2(line, part2) line, part2
#define ASM_COMMAND3(line, var) ASM_COMMAND2(line, var)
//Next is not really special either
#define ASM_CALL(func) ASM_COMMAND(call func)
//Using this weird style because of MSVCs bad parsing
#define asm_call(func) _asm pushad \
_asm call func \
_asm popad
#endif
DWORD WindowWidth = 256;
DWORD WindowHeight = 224;
DWORD FullScreen=0;
DWORD Moving=0;
DWORD SoundBufferSize=1024*18;
DWORD FirstSound=1;
int SoundEnabled=1;
int UsePrimaryBuffer=0;
DWORD FirstActivate = 1;
#define BYTE unsigned char
#define WORD unsigned short
#define DWORD unsigned long
HWND hMainWindow;
HANDLE debugWindow = 0;
extern "C"
{
HINSTANCE hInst;
unsigned char KitchenSync = 0;
unsigned char Force60hz = 0;
}
LPDIRECTSOUND8 lpDirectSound = NULL;
LPDIRECTSOUNDBUFFER8 lpSoundBuffer = NULL;
LPDIRECTSOUNDBUFFER lpPrimaryBuffer = NULL;
DSBUFFERDESC dsbd;
LPVOID lpvPtr1;
DWORD dwBytes1;
LPVOID lpvPtr2;
DWORD dwBytes2;
LPDIRECTDRAW BasiclpDD = NULL;
LPDIRECTDRAW7 lpDD = NULL;
LPDIRECTDRAWSURFACE7 DD_Primary = NULL;
LPDIRECTDRAWSURFACE7 DD_CFB = NULL;
LPDIRECTDRAWSURFACE7 DD_CFB16 = NULL;
LPDIRECTDRAWSURFACE7 DD_BackBuffer = NULL;
LPDIRECTDRAWCLIPPER lpDDClipper = NULL;
RECT rcWindow;
LPDIRECTINPUT8 DInput = NULL;
LPDIRECTINPUTDEVICE8 MouseInput = NULL;
LPDIRECTINPUTDEVICE8 KeyboardInput = NULL;
LPDIRECTINPUTDEVICE8 JoystickInput[5];
DIJOYSTATE js[5];
DWORD X1Disable[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
DWORD X2Disable[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
DWORD Y1Disable[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
DWORD Y2Disable[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
DWORD Z1Disable[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
DWORD Z2Disable[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
DWORD RX1Disable[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
DWORD RX2Disable[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
DWORD RY1Disable[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
DWORD RY2Disable[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
DWORD RZ1Disable[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
DWORD RZ2Disable[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
DWORD S01Disable[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
DWORD S02Disable[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
DWORD S11Disable[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
DWORD S12Disable[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
DWORD POVDisable[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
DWORD NumPOV[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
DWORD NumBTN[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
DWORD CurrentJoy=0;
DWORD BitDepth;
DWORD GBitMask;
BYTE BackColor=0;
DEVMODE mode;
float MouseMinX=0;
float MouseMaxX=256;
float MouseMinY=0;
float MouseMaxY=223;
float MouseX;
float MouseY;
float MouseMoveX;
float MouseMoveY;
int MouseMove2X;
int MouseMove2Y;
BYTE MouseButtonPressed;
BYTE IsActivated=1;
WORD PrevRes=0;
RECT BlitArea;
BYTE AltSurface=0;
extern "C" {
DWORD MouseButton;
DWORD SurfaceX=0;
DWORD SurfaceY=0;
}
HANDLE hLock, hThread;
DWORD dwThreadId, dwThreadParam, semaphore_run;
extern "C" {
int SemaphoreMax = 5;
void InitSemaphore();
void ShutdownSemaphore();
void InitDebugger();
}
static char dinput8_dll[] = {"dinput8.dll\0"};
static char dinput8_imp[] = {"DirectInput8Create\0"};
static char ddraw_dll[] = {"ddraw.dll\0"};
static char ddraw_imp[] = {"DirectDrawCreateEx\0"};
static char dsound_dll[] = {"dsound.dll\0"};
static char dsound_imp[] = {"DirectSoundCreate8\0"};
static HMODULE hM_ddraw = NULL, hM_dsound = NULL,hM_dinput8 = NULL;
typedef HRESULT (WINAPI* lpDirectInput8Create)(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter);
static lpDirectInput8Create pDirectInput8Create;
typedef HRESULT (WINAPI* lpDirectDrawCreateEx)( GUID FAR * lpGuid, LPVOID *lplpDD, REFIID iid,IUnknown FAR *pUnkOuter );
static lpDirectDrawCreateEx pDirectDrawCreateEx;
typedef HRESULT (WINAPI* lpDirectSoundCreate8)(LPCGUID pcGuidDevice, LPDIRECTSOUND8 *ppDS8, LPUNKNOWN pUnkOuter);
static lpDirectSoundCreate8 pDirectSoundCreate8;
extern "C" void FreeDirectX()
{
FreeLibrary(hM_dsound);
FreeLibrary(hM_ddraw);
FreeLibrary(hM_dinput8);
exit(0);
}
extern "C" void DXLoadError()
{
if (MessageBox(NULL, "Sorry, you need to install or reinstall DirectX v8.0 or higher\nto use ZSNESW.\nWould you like to go to the DirectX homepage?", "Error", MB_ICONINFORMATION | MB_YESNO) == IDYES)
{
ShellExecute(NULL, NULL, "http://www.microsoft.com/directx/", NULL, NULL, 0);
}
FreeDirectX();
}
extern "C" void ImportDirectX()
{
hM_dinput8 = LoadLibrary(dinput8_dll);
if (hM_dinput8 == NULL)
{
DXLoadError();
}
pDirectInput8Create = (lpDirectInput8Create) GetProcAddress(hM_dinput8, dinput8_imp);
if (pDirectInput8Create == NULL)
{
char err[256];
wsprintf(err,"Failed to import %s:%s", dinput8_dll, dinput8_imp);
MessageBox(NULL, err, "Error", MB_ICONERROR);
DXLoadError();
}
hM_ddraw = LoadLibrary(ddraw_dll);
if (hM_ddraw == NULL)
{
char err[256];
wsprintf(err,"Failed to import %s",ddraw_dll);
MessageBox(NULL, err,"Error",MB_ICONERROR);
DXLoadError();
}
pDirectDrawCreateEx = (lpDirectDrawCreateEx) GetProcAddress(hM_ddraw, ddraw_imp);
if (pDirectDrawCreateEx == NULL)
{
char err[256];
wsprintf(err,"Failed to import %s:%s", ddraw_dll, ddraw_imp);
MessageBox(NULL, err, "Error", MB_ICONERROR);
DXLoadError();
}
hM_dsound = LoadLibrary(dsound_dll);
if (hM_dsound == NULL)
{
char err[256];
wsprintf(err,"Failed to import %s",dsound_dll);
MessageBox(NULL, err,"Error",MB_ICONERROR);
DXLoadError();
}
pDirectSoundCreate8 = (lpDirectSoundCreate8) GetProcAddress(hM_dsound, dsound_imp);
if (pDirectSoundCreate8 == NULL)
{
char err[256];
wsprintf(err,"Failed to import %s:%s", dsound_dll, dsound_imp);
MessageBox(NULL, err, "Error", MB_ICONERROR);
DXLoadError();
}
}
// milliseconds per world update
#define UPDATE_TICKS_GAME (1000.855001760297741789468390082/60.0)
#define UPDATE_TICKS_GAMEPAL (20.0)
#define UPDATE_TICKS_GUI (1000.0/36.0)
#define UPDATE_TICKS_UDP (1000.0/60.0)
double start, end, freq, update_ticks_pc, start2, end2, update_ticks_pc2;
void ReleaseDirectDraw();
void ReleaseDirectSound();
void ReleaseDirectInput();
int InitDirectDraw();
int ReInitSound();
extern "C"
{
void drawscreenwin(void);
DWORD LastUsedPos=0;
DWORD CurMode=~0;
void initDirectDraw()
{
InitDirectDraw();
}
void reInitSound()
{
ReInitSound();
}
}
void DDrawError(){
char message1[256];
sprintf(message1,"Error drawing to the screen\nMake sure the device is not being used by another process ");
MessageBox (NULL, message1, "DirectDraw Error" , MB_ICONERROR );
}
extern "C" BYTE vsyncon;
extern "C" BYTE KitchenSync;
extern "C" BYTE TripleBufferWin;
void DrawScreen()
{
if (FullScreen == 1)
{
if (TripleBufferWin == 1 || KitchenSync == 1)
{
if (DD_BackBuffer->Blt(&rcWindow, DD_CFB, &BlitArea, DDBLT_WAIT, NULL) == DDERR_SURFACELOST)
DD_Primary->Restore();
if (DD_Primary->Flip(NULL, DDFLIP_WAIT) == DDERR_SURFACELOST)
DD_Primary->Restore();
if (KitchenSync == 1)
{
if (DD_BackBuffer->Blt(&rcWindow, DD_CFB, &BlitArea, DDBLT_WAIT, NULL) == DDERR_SURFACELOST)
DD_Primary->Restore();
if (DD_Primary->Flip(NULL, DDFLIP_WAIT) == DDERR_SURFACELOST)
DD_Primary->Restore();
}
}
else
{
if (vsyncon == 1)
{
if (lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, NULL) != DD_OK)
{
DDrawError();
}
}
DD_Primary->Blt(&rcWindow, DD_CFB, &BlitArea, DDBLT_WAIT, NULL);
DD_Primary->Restore();
}
}
else
{
if (vsyncon == 1)
{
if (lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, NULL) != DD_OK)
{
DDrawError();
}
}
DD_Primary->Blt(&rcWindow, AltSurface == 0 ? DD_CFB : DD_CFB16, &BlitArea, DDBLT_WAIT, NULL);
}
}
DWORD InputEn=0;
BOOL InputAcquire(void)
{
if (JoystickInput[0]) JoystickInput[0]->Acquire();
if (JoystickInput[1]) JoystickInput[1]->Acquire();
if (JoystickInput[2]) JoystickInput[2]->Acquire();
if (JoystickInput[3]) JoystickInput[3]->Acquire();
if (JoystickInput[4]) JoystickInput[4]->Acquire();
if (MouseInput) MouseInput->Acquire();
if (KeyboardInput) KeyboardInput->Acquire();
InputEn = 1;
return TRUE;
}
BOOL InputDeAcquire(void)
{
if (MouseInput) { MouseInput->Unacquire(); }
if (KeyboardInput) KeyboardInput->Unacquire();
if (JoystickInput[0]) JoystickInput[0]->Unacquire();
if (JoystickInput[1]) JoystickInput[1]->Unacquire();
if (JoystickInput[2]) JoystickInput[2]->Unacquire();
if (JoystickInput[3]) JoystickInput[3]->Unacquire();
if (JoystickInput[4]) JoystickInput[4]->Unacquire();
InputEn = 0;
return TRUE;
}
extern "C" {
void initwinvideo();
void DosExit(void);
extern BYTE GUIOn;
extern BYTE GUIOn2;
extern BYTE EMUPause;
extern BYTE cfgsoundon;
extern BYTE StereoSound;
extern DWORD SoundQuality;
extern BYTE HighPriority;
extern BYTE AlwaysOnTop;
extern BYTE SaveMainWindowPos;
extern BYTE AllowMultipleInst;
extern BYTE DisableScreenSaver;
extern BYTE TrapMouseCursor;
extern signed short int MainWindowX;
extern signed short int MainWindowY;
extern int CurKeyPos;
extern int CurKeyReadPos;
extern int KeyBuffer[16];
extern BYTE debugger;
}
extern "C" void CheckPriority()
{
if (HighPriority == 1) SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
else SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
}
extern "C" void CheckAlwaysOnTop()
{
if (AlwaysOnTop == 1) SetWindowPos(hMainWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
else SetWindowPos(hMainWindow, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}
extern "C" void MinimizeWindow()
{
ShowWindow(hMainWindow, SW_MINIMIZE);
IsActivated = 0;
}
extern "C" BYTE MouseWheel;
BOOL InputRead(void)
{
static int PrevZ=0;
MouseMoveX=0;
MouseMoveY=0;
if (MouseInput&&InputEn==1)
{
DIMOUSESTATE dims;
HRESULT hr;
aquireagain:;
hr=MouseInput->GetDeviceState(sizeof(DIMOUSESTATE),&dims);
if (hr==DIERR_INPUTLOST)
{
hr=MouseInput->Acquire();
if (SUCCEEDED(hr))
{
goto aquireagain;
}
}
if (SUCCEEDED(hr))
{
MouseMoveX=(float)dims.lX;
MouseMoveY=(float)dims.lY;
if (MouseWheel == 1)
{
long zDelta = dims.lZ-PrevZ;
if (!dims.lZ) zDelta=0;
while (zDelta>0){
zDelta-=40;
if (!((CurKeyPos+1==CurKeyReadPos) || ((CurKeyPos+1==16)
&& (CurKeyReadPos==0)))){
KeyBuffer[CurKeyPos]=72+256;
CurKeyPos++;
if (CurKeyPos==16) CurKeyPos=0;
}
}
while (zDelta<0){
zDelta+=40;
if (!((CurKeyPos+1==CurKeyReadPos) || ((CurKeyPos+1==16)
&& (CurKeyReadPos==0)))){
KeyBuffer[CurKeyPos]=80+256;
CurKeyPos++;
if (CurKeyPos==16) CurKeyPos=0;
}
}
PrevZ=dims.lZ;
}
MouseButton=(dims.rgbButtons[0]>>7)|(dims.rgbButtons[1]>>6)|(dims.rgbButtons[2]>>5)|(dims.rgbButtons[3]>>4);
}
else
{
return FALSE;
}
}
return TRUE;
}
extern "C" void SaveSramData(void);
extern "C" void GUISaveVars(void);
extern "C" void createnewcfg(void);
void ExitFunction()
{
if (GUIOn2 == 0)
{
asm_call(SaveSramData);
}
asm_call(GUISaveVars);
asm_call(createnewcfg);
// We need to clean up the debug window if it's running
if (debugWindow) FreeConsole();
IsActivated = 0;
ReleaseDirectInput();
ReleaseDirectSound();
ReleaseDirectDraw();
FreeLibrary(hM_dsound);
FreeLibrary(hM_ddraw);
FreeLibrary(hM_dinput8);
DestroyWindow(hMainWindow);
}
LRESULT CALLBACK Main_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static bool shiftpr;
bool accept;
int vkeyval = 0;
switch (uMsg)
{
case WM_KEYDOWN: // sent when user presses a key
if (!((CurKeyPos+1==CurKeyReadPos) || ((CurKeyPos+1==16)
&& (CurKeyReadPos==0)))){
accept=false;
if (wParam==16)
shiftpr=true;
if (((wParam>='A') && (wParam<='Z')) ||
((wParam>='a') && (wParam<='z')) || (wParam==27) ||
(wParam==32) || (wParam==8) || (wParam==13) || (wParam==9)) {
accept=true; vkeyval=wParam;
}
if ((wParam>='0') && (wParam<='9')) {
accept=true; vkeyval=wParam;
if (shiftpr) {
switch (wParam) {
case '1': vkeyval='!'; break;
case '2': vkeyval='@'; break;
case '3': vkeyval='#'; break;
case '4': vkeyval='$'; break;
case '5': vkeyval='%'; break;
case '6': vkeyval='^'; break;
case '7': vkeyval='&'; break;
case '8': vkeyval='*'; break;
case '9': vkeyval='('; break;
case '0': vkeyval=')'; break;
}
}
}
if ((wParam>=VK_NUMPAD0) && (wParam<=VK_NUMPAD9)) {
accept=true; vkeyval=wParam-VK_NUMPAD0+'0';
}
if (!shiftpr){
switch (wParam) {
case 189: vkeyval='-'; accept=true; break;
case 187: vkeyval='='; accept=true; break;
case 219: vkeyval='['; accept=true; break;
case 221: vkeyval=']'; accept=true; break;
case 186: vkeyval=';'; accept=true; break;
case 222: vkeyval=39; accept=true; break;
case 188: vkeyval=','; accept=true; break;
case 190: vkeyval='.'; accept=true; break;
case 191: vkeyval='/'; accept=true; break;
case 192: vkeyval='`'; accept=true; break;
case 220: vkeyval=92; accept=true; break;
}
} else {
switch (wParam) {
case 189: vkeyval='_'; accept=true; break;
case 187: vkeyval='+'; accept=true; break;
case 219: vkeyval='{'; accept=true; break;
case 221: vkeyval='}'; accept=true; break;
case 186: vkeyval=':'; accept=true; break;
case 222: vkeyval='"'; accept=true; break;
case 188: vkeyval='<'; accept=true; break;
case 190: vkeyval='>'; accept=true; break;
case 191: vkeyval='?'; accept=true; break;
case 192: vkeyval='~'; accept=true; break;
case 220: vkeyval='|'; accept=true; break;
}
}
switch (wParam) {
case 33: vkeyval=256+73; accept=true; break;
case 38: vkeyval=256+72; accept=true; break;
case 36: vkeyval=256+71; accept=true; break;
case 39: vkeyval=256+77; accept=true; break;
case 12: vkeyval=256+76; accept=true; break;
case 37: vkeyval=256+75; accept=true; break;
case 34: vkeyval=256+81; accept=true; break;
case 40: vkeyval=256+80; accept=true; break;
case 35: vkeyval=256+79; accept=true; break;
case 107: vkeyval='+'; accept=true; break;
case 109: vkeyval='-'; accept=true; break;
case 106: vkeyval='*'; accept=true; break;
case 111: vkeyval='/'; accept=true; break;
case 110: vkeyval='.'; accept=true; break;
}
if (accept){
KeyBuffer[CurKeyPos]=vkeyval;
CurKeyPos++;
if (CurKeyPos==16) CurKeyPos=0;
}
}
break;
case WM_KEYUP: // sent when user releases a key
if (wParam==16)
shiftpr=false;
break;
case WM_MOUSEMOVE:
if (MouseInput) MouseInput->Acquire();
break;
case WM_MOVE:
break;
case WM_PAINT:
ValidateRect(hWnd,NULL);
break;
case WM_ACTIVATE:
if (LOWORD(wParam) != WA_INACTIVE)
{
IsActivated = 1;
if (FirstActivate == 0) initwinvideo();
InputAcquire();
if (FirstActivate == 1) FirstActivate = 0;
CheckPriority();
}
if (LOWORD(wParam) == WA_INACTIVE)
{
IsActivated = 0;
InputDeAcquire();
if (GUIOn || GUIOn2 || EMUPause) SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS);
}
break;
case WM_SETFOCUS:
if (FullScreen == 0) ShowWindow(hMainWindow, SW_SHOWNORMAL);
CheckPriority();
InputAcquire();
break;
case WM_KILLFOCUS:
InputDeAcquire();
IsActivated = 0;
if (GUIOn || GUIOn2 || EMUPause) SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS);
break;
case WM_DESTROY:
break;
case WM_CLOSE:
break;
case WM_SYSCOMMAND:
if (DisableScreenSaver)
{
switch (wParam)
{
case SC_MONITORPOWER:
return 0;
}
}
break;
}
return DefWindowProc(hWnd,uMsg,wParam,lParam);;
}
int RegisterWinClass(void)
{
if (AllowMultipleInst == 0)
{
HWND hFindWindow;
hFindWindow = FindWindow("ZSNES", NULL);
if (hFindWindow != NULL)
{
ShowWindow(hFindWindow, SW_SHOWNORMAL);
SetForegroundWindow(hFindWindow);
DosExit();
}
}
WNDCLASS wcl;
wcl.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE;
wcl.cbClsExtra = 0;
wcl.cbWndExtra = 0;
wcl.hIcon = LoadIcon(NULL,"ZSNESW.ICO");
wcl.hCursor = NULL;
wcl.hInstance = hInst;
wcl.lpfnWndProc = (WNDPROC)Main_Proc;
wcl.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wcl.lpszMenuName = NULL;
wcl.lpszClassName = "ZSNES";
if (RegisterClass(&wcl) == 0) return FALSE;
return TRUE;
}
BYTE PrevStereoSound;
DWORD PrevSoundQuality;
extern "C" { extern unsigned char PrimaryBuffer; }
BOOL InitSound()
{
WAVEFORMATEX wfx;
DSBCAPS dsbcaps;
SoundEnabled = 0;
if (cfgsoundon == 0) return FALSE;
PrevSoundQuality=SoundQuality;
PrevStereoSound=StereoSound;
if (DS_OK == pDirectSoundCreate8(NULL, &lpDirectSound,NULL))
{
lpDirectSound->Initialize(NULL);
if (PrimaryBuffer)
{
if (DS_OK != lpDirectSound->SetCooperativeLevel(hMainWindow, DSSCL_WRITEPRIMARY))
{
if (DS_OK != lpDirectSound->SetCooperativeLevel(hMainWindow, DSSCL_EXCLUSIVE))
return FALSE;
}
else UsePrimaryBuffer=1;
}
else
{
if (DS_OK != lpDirectSound->SetCooperativeLevel(hMainWindow, DSSCL_NORMAL))
{
if (DS_OK != lpDirectSound->SetCooperativeLevel(hMainWindow, DSSCL_EXCLUSIVE))
return FALSE;
}
else UsePrimaryBuffer=0;
}
}
else
{
return FALSE;
}
wfx.wFormatTag = WAVE_FORMAT_PCM;
switch (SoundQuality)
{
case 0:
wfx.nSamplesPerSec = 8000;
SoundBufferSize=1024*2;
break;
case 1:
wfx.nSamplesPerSec = 11025;
SoundBufferSize=1024*2;
break;
case 2:
wfx.nSamplesPerSec = 22050;
SoundBufferSize=1024*4;
break;
case 3:
wfx.nSamplesPerSec = 44100;
SoundBufferSize=1024*8;
break;
case 4:
wfx.nSamplesPerSec = 16000;
SoundBufferSize=1024*4;
break;
case 5:
wfx.nSamplesPerSec = 32000;
SoundBufferSize=1024*8;
break;
case 6:
wfx.nSamplesPerSec = 48000;
SoundBufferSize=1024*8;
break;
default:
wfx.nSamplesPerSec = 11025;
SoundBufferSize=1024*2;
}
if (StereoSound==1)
{
wfx.nChannels = 2;
wfx.nBlockAlign = 4;
SoundBufferSize*=2;
}
else
{
wfx.nChannels = 1;
wfx.nBlockAlign = 2;
}
wfx.wBitsPerSample = 16;
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
wfx.cbSize=0;
memset(&dsbd, 0, sizeof(DSBUFFERDESC));
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS;
if(UsePrimaryBuffer) dsbd.dwFlags |= DSBCAPS_PRIMARYBUFFER;
dsbd.dwBufferBytes = UsePrimaryBuffer ? 0 : SoundBufferSize;
dsbd.lpwfxFormat = UsePrimaryBuffer ? NULL : &wfx;
if (DS_OK == lpDirectSound->CreateSoundBuffer(&dsbd, &lpPrimaryBuffer, NULL))
{
if(!UsePrimaryBuffer)
{
if (DS_OK == lpPrimaryBuffer->QueryInterface(IID_IDirectSoundBuffer8, (LPVOID *) &lpSoundBuffer))
{
if (DS_OK != lpSoundBuffer->Play(0,0,DSBPLAY_LOOPING))
{
return FALSE;
}
}
else return FALSE;
}
else
{
lpPrimaryBuffer->SetFormat(&wfx);
dsbcaps.dwSize=sizeof(DSBCAPS);
lpPrimaryBuffer->GetCaps(&dsbcaps);
SoundBufferSize=dsbcaps.dwBufferBytes;
if (DS_OK != lpPrimaryBuffer->Play(0,0,DSBPLAY_LOOPING))
{
return FALSE;
}
}
SoundEnabled=1;
FirstSound=0;
return TRUE;
}
else
{
return FALSE;
}
}
BOOL ReInitSound()
{
WAVEFORMATEX wfx;
DSBCAPS dsbcaps;
if (lpSoundBuffer)
{
lpSoundBuffer->Stop();
lpSoundBuffer->Release();
lpSoundBuffer = NULL;
}
if (lpPrimaryBuffer)
{
lpPrimaryBuffer->Stop();
lpPrimaryBuffer->Release();
lpPrimaryBuffer = NULL;
}
if (cfgsoundon == 0)
{
SoundEnabled = 0;
ReleaseDirectSound();
return FALSE;
}
else if (SoundEnabled == 0)
return InitSound();
SoundEnabled = 0;
PrevSoundQuality=SoundQuality;
PrevStereoSound=StereoSound;
wfx.wFormatTag = WAVE_FORMAT_PCM;
switch (SoundQuality)
{
case 0:
wfx.nSamplesPerSec = 8000;
SoundBufferSize=1024*2;
break;
case 1:
wfx.nSamplesPerSec = 11025;
SoundBufferSize=1024*2;
break;
case 2:
wfx.nSamplesPerSec = 22050;
SoundBufferSize=1024*4;
break;
case 3:
wfx.nSamplesPerSec = 44100;
SoundBufferSize=1024*8;
break;
case 4:
wfx.nSamplesPerSec = 16000;
SoundBufferSize=1024*4;
break;
case 5:
wfx.nSamplesPerSec = 32000;
SoundBufferSize=1024*8;
break;
case 6:
wfx.nSamplesPerSec = 48000;
SoundBufferSize=1024*8;
break;
default:
wfx.nSamplesPerSec = 11025;
SoundBufferSize=1024*2;
}
if (StereoSound==1)
{
wfx.nChannels = 2;
wfx.nBlockAlign = 4;
SoundBufferSize*=2;
}
else
{
wfx.nChannels = 1;
wfx.nBlockAlign = 2;
}
wfx.wBitsPerSample = 16;
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
wfx.cbSize=0;
memset(&dsbd, 0, sizeof(DSBUFFERDESC));
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS;
if(UsePrimaryBuffer) dsbd.dwFlags |= DSBCAPS_PRIMARYBUFFER;
dsbd.dwBufferBytes = UsePrimaryBuffer ? 0 : SoundBufferSize;
dsbd.lpwfxFormat = UsePrimaryBuffer ? NULL : &wfx;
if (DS_OK == lpDirectSound->CreateSoundBuffer(&dsbd, &lpPrimaryBuffer, NULL))
{
if(!UsePrimaryBuffer)
{
if (DS_OK == lpPrimaryBuffer->QueryInterface(IID_IDirectSoundBuffer8, (LPVOID *) &lpSoundBuffer))
{
if (DS_OK != lpSoundBuffer->Play(0,0,DSBPLAY_LOOPING))
{
return FALSE;
}
}
else return FALSE;
}
else
{
lpPrimaryBuffer->SetFormat(&wfx);
dsbcaps.dwSize=sizeof(DSBCAPS);
lpPrimaryBuffer->GetCaps(&dsbcaps);
SoundBufferSize=dsbcaps.dwBufferBytes;
if (DS_OK != lpPrimaryBuffer->Play(0,0,DSBPLAY_LOOPING))
{
return FALSE;
}
}
SoundEnabled=1;
FirstSound=0;
return TRUE;
}
else
{
return FALSE;
}
}
BOOL FAR PASCAL InitJoystickInput(LPCDIDEVICEINSTANCE pdinst, LPVOID pvRef)
{
LPDIRECTINPUT8 pdi = (LPDIRECTINPUT8)pvRef;
GUID DeviceGuid = pdinst->guidInstance;
if (CurrentJoy>4)
return DIENUM_CONTINUE;
// Create the DirectInput joystick device.
if (pdi->CreateDevice(DeviceGuid,&JoystickInput[CurrentJoy], NULL) != DI_OK)
{
return DIENUM_CONTINUE;
}
if (JoystickInput[CurrentJoy]->SetDataFormat(&c_dfDIJoystick) != DI_OK)
{
JoystickInput[CurrentJoy]->Release();
return DIENUM_CONTINUE;
}
if (JoystickInput[CurrentJoy]->SetCooperativeLevel(hMainWindow, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND) != DI_OK)
{
JoystickInput[CurrentJoy]->Release();
return DIENUM_CONTINUE;
}
DIPROPRANGE diprg;
diprg.diph.dwSize = sizeof(diprg);
diprg.diph.dwHeaderSize = sizeof(diprg.diph);
diprg.diph.dwObj = DIJOFS_X;
diprg.diph.dwHow = DIPH_BYOFFSET;
diprg.lMin = -1000;
diprg.lMax = +1000;
if FAILED(JoystickInput[CurrentJoy]->SetProperty(DIPROP_RANGE, &diprg.diph))
{
X1Disable[CurrentJoy]=1;
X2Disable[CurrentJoy]=1;
}
diprg.diph.dwObj = DIJOFS_Y;
if FAILED(JoystickInput[CurrentJoy]->SetProperty(DIPROP_RANGE, &diprg.diph))
{
Y1Disable[CurrentJoy]=1;
Y2Disable[CurrentJoy]=1;
}
diprg.diph.dwObj = DIJOFS_Z;
if (FAILED(JoystickInput[CurrentJoy]->SetProperty(DIPROP_RANGE, &diprg.diph)))
{
Z1Disable[CurrentJoy]=1;
Z2Disable[CurrentJoy]=1;
}
diprg.diph.dwObj = DIJOFS_RX;
if (FAILED(JoystickInput[CurrentJoy]->SetProperty(DIPROP_RANGE, &diprg.diph)))
{
RX1Disable[CurrentJoy]=1;
RX2Disable[CurrentJoy]=1;
}
diprg.diph.dwObj = DIJOFS_RY;
if (FAILED(JoystickInput[CurrentJoy]->SetProperty(DIPROP_RANGE, &diprg.diph)))
{
RY1Disable[CurrentJoy]=1;
RY2Disable[CurrentJoy]=1;
}
diprg.diph.dwObj = DIJOFS_RZ;
if (FAILED(JoystickInput[CurrentJoy]->SetProperty(DIPROP_RANGE, &diprg.diph)))
{
RZ1Disable[CurrentJoy]=1;
RZ2Disable[CurrentJoy]=1;
}
diprg.diph.dwObj = DIJOFS_SLIDER(0);
if (FAILED(JoystickInput[CurrentJoy]->SetProperty(DIPROP_RANGE, &diprg.diph)))
{
S01Disable[CurrentJoy]=1;
S02Disable[CurrentJoy]=1;
}
diprg.diph.dwObj = DIJOFS_SLIDER(1);
if (FAILED(JoystickInput[CurrentJoy]->SetProperty(DIPROP_RANGE, &diprg.diph)))
{
S11Disable[CurrentJoy]=1;
S12Disable[CurrentJoy]=1;
}
DIDEVCAPS didc;
didc.dwSize = sizeof(DIDEVCAPS);
if (JoystickInput[CurrentJoy]->GetCapabilities(&didc) != DI_OK)
{
JoystickInput[CurrentJoy]->Release();
return DIENUM_CONTINUE;
}
if (didc.dwButtons <= 16)
NumBTN[CurrentJoy] = didc.dwButtons;
else
NumBTN[CurrentJoy] = 16;
if (didc.dwPOVs)
NumPOV[CurrentJoy] = didc.dwPOVs;
else
POVDisable[CurrentJoy] = 1;
DIPROPDWORD dipdw;
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
dipdw.diph.dwHow = DIPH_BYOFFSET;
dipdw.dwData = 2500;
dipdw.diph.dwObj = DIJOFS_X;
JoystickInput[CurrentJoy]->SetProperty(DIPROP_DEADZONE, &dipdw.diph);
dipdw.diph.dwObj = DIJOFS_Y;
JoystickInput[CurrentJoy]->SetProperty(DIPROP_DEADZONE, &dipdw.diph);
dipdw.diph.dwObj = DIJOFS_Z;
JoystickInput[CurrentJoy]->SetProperty(DIPROP_DEADZONE, &dipdw.diph);
dipdw.diph.dwObj = DIJOFS_RX;
JoystickInput[CurrentJoy]->SetProperty(DIPROP_DEADZONE, &dipdw.diph);
dipdw.diph.dwObj = DIJOFS_RY;
JoystickInput[CurrentJoy]->SetProperty(DIPROP_DEADZONE, &dipdw.diph);
dipdw.diph.dwObj = DIJOFS_RZ;
JoystickInput[CurrentJoy]->SetProperty(DIPROP_DEADZONE, &dipdw.diph);
dipdw.diph.dwObj = DIJOFS_SLIDER(0);
JoystickInput[CurrentJoy]->SetProperty(DIPROP_DEADZONE, &dipdw.diph);
dipdw.diph.dwObj = DIJOFS_SLIDER(1);
JoystickInput[CurrentJoy]->SetProperty(DIPROP_DEADZONE, &dipdw.diph);
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
dipdw.diph.dwHow = DIPH_DEVICE;
dipdw.dwData = DIPROPAXISMODE_ABS;
dipdw.diph.dwObj = 0;
JoystickInput[CurrentJoy]->SetProperty(DIPROP_AXISMODE, &dipdw.diph);
CurrentJoy+=1;
return DIENUM_CONTINUE;
}
void ReleaseDirectInput()
{
if (MouseInput)
{
MouseInput->Release();
MouseInput = NULL;
}
if (KeyboardInput)
{
KeyboardInput->Release();
KeyboardInput = NULL;
}
for (int i=0; i<5; i++)
if (JoystickInput[i])
{
JoystickInput[i]->Release();
JoystickInput[i] = NULL;
}
if (DInput)
{
DInput->Release();
DInput = NULL;
}
}
void ReleaseDirectSound()
{
if (lpSoundBuffer)
{
lpSoundBuffer->Release();
lpSoundBuffer = NULL;
}
if (lpPrimaryBuffer)
{
lpPrimaryBuffer->Release();
lpPrimaryBuffer = NULL;
}
if (lpDirectSound)
{
lpDirectSound->Release();
lpDirectSound = NULL;
}
}
void ReleaseDirectDraw()
{
if (DD_CFB)
{
DD_CFB->Release();
DD_CFB = NULL;
}
if (DD_CFB16)
{
DD_CFB16->Release();
DD_CFB16 = NULL;
}
if (lpDDClipper)
{
lpDDClipper->Release();
lpDDClipper = NULL;
}
if (DD_Primary)
{
DD_Primary->Release();
DD_Primary = NULL;
}
if (lpDD)
{
lpDD->Release();
lpDD = NULL;
}
}
void DInputError(){
char message1[256];
sprintf(message1,"Error initializing DirectInput\nYou may need to install DirectX 8.0a or higher located at www.microsoft.com/directx ");
MessageBox (NULL, message1, "DirectInput Error" , MB_ICONERROR );
}
bool InitInput()
{
char message1[256];
HRESULT hr;
if (FAILED(hr=pDirectInput8Create(hInst,DIRECTINPUT_VERSION,IID_IDirectInput8A,(void **) &DInput,NULL)))
{
sprintf(message1,"Error initializing DirectInput\nYou may need to install DirectX 8.0a or higher located at www.microsoft.com/directx ");
MessageBox (NULL, message1, "DirectInput Error" , MB_ICONERROR );
switch (hr)
{
case DIERR_BETADIRECTINPUTVERSION:
sprintf(message1,"Beta %X\n",hr);
MessageBox (NULL, message1, "Init", MB_ICONERROR );
break;
case DIERR_INVALIDPARAM:
sprintf(message1,"Invalid %X\n",hr);
MessageBox (NULL, message1, "Init", MB_ICONERROR );
break;
case DIERR_OLDDIRECTINPUTVERSION:
sprintf(message1,"OLDDIRECTINPUTVERSION %X\n",hr);
MessageBox (NULL, message1, "Init", MB_ICONERROR );
break;
case DIERR_OUTOFMEMORY:
sprintf(message1,"OUTOFMEMORY %X\n",hr);
MessageBox (NULL, message1, "Init", MB_ICONERROR );
break;
default:
sprintf(message1,"UNKNOWN %X\n",hr);
MessageBox (NULL, message1, "Init", MB_ICONERROR );
break;
}
return FALSE;
}
hr=DInput->CreateDevice(GUID_SysKeyboard, &KeyboardInput,NULL);
if (FAILED(hr)) {DInputError();return FALSE;}
hr=KeyboardInput->SetDataFormat(&c_dfDIKeyboard);
if (FAILED(hr)) {DInputError();return FALSE;}
hr=KeyboardInput->SetCooperativeLevel(hMainWindow,DISCL_NONEXCLUSIVE | DISCL_FOREGROUND );
hr=DInput->CreateDevice(GUID_SysMouse, &MouseInput,NULL);
if (FAILED(hr)) {DInputError();return FALSE;}
hr=MouseInput->SetDataFormat(&c_dfDIMouse);
if (FAILED(hr)) {DInputError();return FALSE;}
hr=MouseInput->SetCooperativeLevel(hMainWindow,DISCL_EXCLUSIVE|DISCL_FOREGROUND);
if (FAILED(hr)) {DInputError();return FALSE;}
JoystickInput[0]=NULL;JoystickInput[1]=NULL;JoystickInput[2]=NULL;JoystickInput[3]=NULL;
hr=DInput->EnumDevices(DI8DEVCLASS_GAMECTRL, InitJoystickInput,
DInput, DIEDFL_ATTACHEDONLY);
if (FAILED(hr)) {DInputError(); return FALSE;}
InputAcquire();
return TRUE;
}
void TestJoy()
{
int i;
for(i=0;i<5;i++)
{
if (JoystickInput[i])
{
JoystickInput[i]->Poll();
if (JoystickInput[i]->GetDeviceState(sizeof(DIJOYSTATE), &js[i])==DIERR_INPUTLOST)
{
if (JoystickInput[i]) JoystickInput[i]->Acquire();
if (FAILED(JoystickInput[i]->GetDeviceState(sizeof(DIJOYSTATE), &js[i]))) return;
}
if (!X1Disable[i])
{
if (js[i].lX>0) X1Disable[i]=1;
}
if (!X2Disable[i])
{
if (js[i].lX<0) X2Disable[i]=1;
}
if (!Y1Disable[i])
{
if (js[i].lY>0) Y1Disable[i]=1;
}
if (!Y2Disable[i])
{
if (js[i].lY<0) Y2Disable[i]=1;
}
if (!Z1Disable[i])
{
if (js[i].lZ>0) Z1Disable[i]=1;
}
if (!Z2Disable[i])
{
if (js[i].lZ<0) Z2Disable[i]=1;
}
if (!RY1Disable[i])
{
if (js[i].lRy>0) RY1Disable[i]=1;
}
if (!RY2Disable[i])
{
if (js[i].lRy<0) RY2Disable[i]=1;
}
if (!RZ1Disable[i])
{
if (js[i].lRz>0) RZ1Disable[i]=1;
}
if (!RZ2Disable[i])
{
if (js[i].lRz<0) RZ2Disable[i]=1;
}
if (!S01Disable[i])
{
if (js[i].rglSlider[0]>0) S01Disable[i]=1;
}
if (!S02Disable[i])
{
if (js[i].rglSlider[0]<0) S02Disable[i]=1;
}
if (!S11Disable[i])
{
if (js[i].rglSlider[1]>0) S11Disable[i]=1;
}
if (!S12Disable[i])
{
if (js[i].rglSlider[1]<0) S12Disable[i]=1;
}
}
}
}
extern "C" DWORD converta;
extern "C" unsigned int BitConv32Ptr;
extern "C" unsigned int RGBtoYUVPtr;
extern "C" unsigned char cvidmode;
extern "C" unsigned char hqFilter;
extern "C" unsigned short resolutn;
extern "C" unsigned short scanlines;
DWORD FirstVid=1;
DWORD FirstFull=1;
DWORD DMode=0;
DWORD SMode=0;
DWORD DSMode=0;
DWORD prevHQMode=~0;
DWORD prevScanlines=~0;
WORD Refresh = 0;
extern "C" BYTE GUIWFVID[];
extern "C" BYTE GUIDSIZE[];
extern "C" BYTE GUISMODE[];
extern "C" BYTE GUIDSMODE[];
extern "C" BYTE GUIHQ2X[];
extern "C" BYTE GUIHQ3X[];
extern "C" BYTE GUIHQ4X[];
int InitDirectDraw()
{
DDSURFACEDESC2 ddsd2;
DDPIXELFORMAT format;
//MK: unused 2003/08/31
//HRESULT hr;
//char message1[256];
unsigned int color32,ScreenPtr2;
int i, j, k, r, g, b, Y, u, v;
ScreenPtr2=BitConv32Ptr;
for(i=0;i<65536;i++)
{
color32=((i&0xF800)<<8)+
((i&0x07E0)<<5)+
((i&0x001F)<<3)+0xFF000000;
(*(unsigned int *)(ScreenPtr2))=color32;
ScreenPtr2+=4;
}
for (i=0; i<32; i++)
for (j=0; j<64; j++)
for (k=0; k<32; k++)
{
r = i << 3;
g = j << 2;
b = k << 3;
Y = (r + g + b) >> 2;
u = 128 + ((r - b) >> 2);
v = 128 + ((-r + 2*g -b)>>3);
*(((unsigned int *)RGBtoYUVPtr) + (i << 11) + (j << 5) + k) = (Y<<16) + (u<<8) + v;
}
if (!hMainWindow)
{
exit(1);
}
ReleaseDirectDraw();
GetClientRect(hMainWindow, &rcWindow);
ClientToScreen(hMainWindow, ( LPPOINT )&rcWindow);
ClientToScreen(hMainWindow, ( LPPOINT )&rcWindow + 1);
FullScreen=GUIWFVID[cvidmode];
DSMode=GUIDSMODE[cvidmode];
DWORD HQMode=0;
if ( hqFilter != 0 )
{
if ( GUIHQ2X[cvidmode] != 0 ) HQMode=2;
if ( GUIHQ3X[cvidmode] != 0 ) HQMode=3;
if ( GUIHQ4X[cvidmode] != 0 ) HQMode=4;
}
if (FullScreen == 1)
{
if (HQMode && !DSMode)
{
int marginx = (rcWindow.right - rcWindow.left - BlitArea.right + BlitArea.left)/2;
int marginy = (rcWindow.bottom - rcWindow.top - BlitArea.bottom + BlitArea.top)/2;
if (marginx>0)
{
rcWindow.left += marginx;
rcWindow.right -= marginx;
}
if (marginy>0)
{
rcWindow.top += marginy;
rcWindow.bottom -= marginy;
}
}
if ((DSMode == 1) && (scanlines != 0))
{
int OldHeight = rcWindow.bottom - rcWindow.top;
if ((OldHeight % 240) == 0)
{
int NewHeight = (OldHeight/240)*resolutn;
rcWindow.top += (OldHeight - NewHeight)/2;
rcWindow.bottom = rcWindow.top + NewHeight;
}
}
}
if (pDirectDrawCreateEx(NULL, (void **)&lpDD, IID_IDirectDraw7, NULL) != DD_OK)
{
MessageBox(NULL, "DirectDrawCreateEx failed.", "DirectDraw Error", MB_ICONERROR);
return FALSE;
}
if (FullScreen == 1)
{
if (lpDD->SetCooperativeLevel(hMainWindow, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT) != DD_OK)
{
MessageBox(NULL, "IDirectDraw7::SetCooperativeLevel failed.", "DirectDraw Error", MB_ICONERROR);
return FALSE;
}
if (lpDD->SetDisplayMode(WindowWidth, WindowHeight, 16, Refresh, 0) != DD_OK)
{
if (lpDD->SetDisplayMode(WindowWidth, WindowHeight, 16, 0, 0) != DD_OK)
{
MessageBox(NULL, "IDirectDraw7::SetDisplayMode failed.\nMake sure your video card supports this mode.", "DirectDraw Error", MB_ICONERROR);
return FALSE;
}
else
{
KitchenSync = 0;
Refresh = 0;
}
}
}
else
{
if (lpDD->SetCooperativeLevel(hMainWindow, DDSCL_NORMAL) != DD_OK)
{
MessageBox(NULL, "IDirectDraw7::SetCooperativeLevel failed.", "DirectDraw Error", MB_ICONERROR);
return FALSE;
}
CheckAlwaysOnTop();
}
ZeroMemory(&ddsd2, sizeof(DDSURFACEDESC2));
ddsd2.dwSize = sizeof(DDSURFACEDESC2);
ddsd2.dwFlags = DDSD_CAPS;
ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
if (FullScreen == 1)
{
ddsd2.dwFlags |= DDSD_BACKBUFFERCOUNT;
ddsd2.dwBackBufferCount = 2;
ddsd2.ddsCaps.dwCaps |= DDSCAPS_FLIP | DDSCAPS_COMPLEX;
}
HRESULT hRes = lpDD->CreateSurface(&ddsd2, &DD_Primary, NULL);
if (FullScreen == 1)
{
if ((hRes == DDERR_OUTOFMEMORY) || (hRes == DDERR_OUTOFVIDEOMEMORY))
{
ddsd2.dwBackBufferCount = 1;
hRes = lpDD->CreateSurface(&ddsd2, &DD_Primary, NULL);
}
}
if (hRes != DD_OK)
{
MessageBox(NULL, "IDirectDraw7::CreateSurface failed.", "DirectDraw Error", MB_ICONERROR);
return FALSE;
}
if (FullScreen == 1)
{
ddsd2.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
if (DD_Primary->GetAttachedSurface(&ddsd2.ddsCaps, &DD_BackBuffer) != DD_OK)
{
MessageBox(NULL, "IDirectDrawSurface7::GetAttachedSurface failed.", "DirectDraw Error", MB_ICONERROR);
return FALSE;
}
}
else
{
if (lpDD->CreateClipper(0,&lpDDClipper,NULL) != DD_OK)
{
lpDD->Release();
lpDD=NULL;
return FALSE;
}
if (lpDDClipper->SetHWnd(0,hMainWindow) != DD_OK)
{
lpDD->Release();
lpDD=NULL;
return FALSE;
}
if (DD_Primary->SetClipper(lpDDClipper) != DD_OK)
{
return FALSE;
}
}
format.dwSize = sizeof(DDPIXELFORMAT);
if (DD_Primary->GetPixelFormat(&format) != DD_OK)
{
MessageBox(NULL, "IDirectDrawSurface7::GetPixelFormat failed.", "DirectDraw Error", MB_ICONERROR);
return FALSE;
}
BitDepth=format.dwRGBBitCount;
GBitMask=format.dwGBitMask; // 0x07E0 or not
if (BitDepth==24)
{
MessageBox(NULL,"ZSNESw does not support 24bit color.\nPlease change your resolution to either 16bit or 32bit color","Error",MB_OK);
exit(0);
}
converta = (BitDepth==16 && GBitMask!=0x07E0);
ddsd2.dwSize = sizeof(ddsd2);
ddsd2.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
ddsd2.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd2.dwWidth = SurfaceX;
ddsd2.dwHeight = SurfaceY;
// create drawing surface
if (lpDD->CreateSurface(&ddsd2, &DD_CFB, NULL) != DD_OK)
{
MessageBox(NULL, "IDirectDraw7::CreateSurface failed.", "DirectDraw Error", MB_ICONERROR);
return FALSE;
}
AltSurface = 0;
// create alt. drawing surface
if ( BitDepth == 32 )
{
ddsd2.dwFlags |= DDSD_PIXELFORMAT;
ddsd2.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
ddsd2.ddpfPixelFormat.dwFlags = DDPF_RGB;
ddsd2.ddpfPixelFormat.dwRGBBitCount = 16;
ddsd2.ddpfPixelFormat.dwRBitMask = 0xF800;
ddsd2.ddpfPixelFormat.dwGBitMask = 0x07E0;
ddsd2.ddpfPixelFormat.dwBBitMask = 0x001F;
if (lpDD->CreateSurface(&ddsd2, &DD_CFB16, NULL) != DD_OK)
{
MessageBox(NULL, "IDirectDraw7::CreateSurface failed.", "DirectDraw Error", MB_ICONERROR);
return FALSE;
}
if (((SurfaceX==512) || (SurfaceX==640)) && (HQMode==0))
AltSurface = 1;
}
return TRUE;
}
BYTE* SurfBuf;
DDSURFACEDESC2 ddsd;
DWORD LockSurface()
{
HRESULT hRes;
if (AltSurface == 0)
{
if (DD_CFB != NULL)
{
memset(&ddsd,0,sizeof(ddsd));
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_LPSURFACE | DDSD_PITCH;
hRes = DD_CFB->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL);
if (hRes == DD_OK)
{
SurfBuf = (BYTE*)ddsd.lpSurface;
return(ddsd.lPitch);
}
else
{
if (hRes == DDERR_SURFACELOST)
DD_CFB->Restore();
return(0);
}
}
else
return(0);
}
else
{
if (DD_CFB16 != NULL)
{
memset(&ddsd,0,sizeof(ddsd));
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_LPSURFACE | DDSD_PITCH;
hRes = DD_CFB16->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL);
if (hRes == DD_OK)
{
SurfBuf = (BYTE*)ddsd.lpSurface;
return(ddsd.lPitch);
}
else
{
if (hRes == DDERR_SURFACELOST)
DD_CFB16->Restore();
return(0);
}
}
else
return(0);
}
}
void UnlockSurface()
{
if (AltSurface == 0)
DD_CFB->Unlock((struct tagRECT *)ddsd.lpSurface);
else
DD_CFB16->Unlock((struct tagRECT *)ddsd.lpSurface);
}
extern "C" {
void WinUpdateDevices();
short Buffer[1800*2];
int X, Y;
DWORD pitch;
MSG msg;
DWORD SurfBufD;
int count, x,count2;
HRESULT hr;
int i;
short *Sound;
DWORD CurrentPos;
DWORD WritePos;
DWORD T60HZEnabled=0;
DWORD T36HZEnabled=0;
DWORD WINAPI SemaphoreThread( LPVOID lpParam )
{
while(semaphore_run)
{
if (T60HZEnabled)
{
ReleaseSemaphore(hLock, 1, NULL);
Sleep(1);
}
else
Sleep(20);
}
return 0;
}
void InitSemaphore()
{
if (hLock) return;
hLock = CreateSemaphore(NULL, 1, SemaphoreMax, NULL);
semaphore_run = 1;
hThread = CreateThread(NULL, 0, SemaphoreThread, &dwThreadParam, 0, &dwThreadId);
}
void ShutdownSemaphore()
{
if (!hLock) return;
semaphore_run = 0;
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
CloseHandle(hLock);
hLock = NULL;
}
extern unsigned int pressed;
extern unsigned char romispal;
void Start60HZ(void)
{
update_ticks_pc2 = UPDATE_TICKS_UDP * freq / 1000.0;
if (romispal==1)
{
update_ticks_pc = UPDATE_TICKS_GAMEPAL * freq / 1000.0;
}
else
{
update_ticks_pc = UPDATE_TICKS_GAME * freq / 1000.0;
}
QueryPerformanceCounter((LARGE_INTEGER*)&start);
QueryPerformanceCounter((LARGE_INTEGER*)&start2);
T36HZEnabled=0;
T60HZEnabled=1;
InitSemaphore();
}
void Stop60HZ(void)
{
T60HZEnabled=0;
ShutdownSemaphore();
}
void Start36HZ(void)
{
update_ticks_pc2 = UPDATE_TICKS_UDP * freq / 1000.0;
update_ticks_pc = UPDATE_TICKS_GUI * freq / 1000.0;
QueryPerformanceCounter((LARGE_INTEGER*)&start);
QueryPerformanceCounter((LARGE_INTEGER*)&start2);
T60HZEnabled=0;
T36HZEnabled=1;
}
void Stop36HZ(void)
{
T36HZEnabled=0;
}
char WinMessage[256];
void clearwin();
void Clear2xSaIBuffer();
void clear_display();
char WinName[]={"ZSNESW\0"};
void initwinvideo(void)
{
WINDOWPLACEMENT wndpl;
RECT rc1;
DWORD newmode=0;
DWORD HQMode=0;
if ( hqFilter != 0 )
{
if ( GUIHQ2X[cvidmode] != 0 ) HQMode=2;
if ( GUIHQ3X[cvidmode] != 0 ) HQMode=3;
if ( GUIHQ4X[cvidmode] != 0 ) HQMode=4;
}
if ((CurMode!=cvidmode) || (prevHQMode!=HQMode))
{
CurMode=cvidmode;
prevHQMode=HQMode;
newmode=1;
SurfaceX=256;
SurfaceY=240;
X=0;
Y=0;
FullScreen=GUIWFVID[cvidmode];
DMode=GUIDSIZE[cvidmode];
SMode=GUISMODE[cvidmode];
DSMode=GUIDSMODE[cvidmode];
switch (cvidmode)
{
case 0:
WindowWidth=256;
WindowHeight=224;
break;
case 1:
WindowWidth=640;
WindowHeight=480;
break;
case 2:
case 3:
WindowWidth=512;
WindowHeight=448;
break;
case 4:
case 5:
case 6:
case 7:
case 8:
WindowWidth=640;
WindowHeight=480;
break;
case 9:
case 10:
WindowWidth=768;
WindowHeight=672;
break;
case 11:
case 12:
case 13:
case 14:
case 15:
WindowWidth=800;
WindowHeight=600;
break;
case 16:
case 17:
case 18:
case 19:
case 20:
WindowWidth=1024;
WindowHeight=768;
break;
case 21:
case 22:
WindowWidth=1024;
WindowHeight=896;
break;
case 23:
case 24:
case 25:
case 26:
case 27:
WindowWidth=1280;
WindowHeight=960;
break;
case 28:
case 29:
case 30:
case 31:
case 32:
WindowWidth=1280;
WindowHeight=1024;
break;
default:
WindowWidth=256;
WindowHeight=224;
break;
}
if (DMode == 1)
{
if ((DSMode == 1) || (FullScreen == 0))
SurfaceX = 512;
else
SurfaceX = 640;
SurfaceY=480;
}
else
{
if ((SMode == 0) && (FullScreen == 1))
SurfaceX=320;
else
SurfaceX=256;
SurfaceY=240;
}
switch ( HQMode )
{
case 2:
SurfaceX=512;
SurfaceY=480;
break;
case 3:
SurfaceX=768;
SurfaceY=720;
break;
case 4:
SurfaceX=1024;
SurfaceY=960;
break;
}
BlitArea.top = 0;
BlitArea.left = 0;
BlitArea.right = SurfaceX;
if ((SurfaceX == 640) || (SurfaceX == 320))
BlitArea.bottom = SurfaceY;
else
BlitArea.bottom = (SurfaceY/240)*resolutn;
if (PrevRes == 0) PrevRes = resolutn;
}
if (((PrevStereoSound!=StereoSound)||(PrevSoundQuality!=SoundQuality))&&FirstSound!=1)
ReInitSound();
if (!FirstVid)
{
if (X<0)X=0;
if (X>(int)(GetSystemMetrics(SM_CXSCREEN) - WindowWidth)) X=(GetSystemMetrics(SM_CXSCREEN) - WindowWidth);
if (Y<0)Y=0;
if (Y>(int)(GetSystemMetrics(SM_CYSCREEN) - WindowHeight)) Y=(GetSystemMetrics(SM_CYSCREEN) - WindowHeight);
if (FullScreen==1) {X=0; Y=0;}
if (FullScreen==0 && newmode == 1) { X = MainWindowX; Y = MainWindowY; }
else if (FullScreen==0) { MainWindowX = X; MainWindowY = Y; }
MoveWindow(hMainWindow, X, Y, WindowWidth, WindowHeight, TRUE);
wndpl.length = sizeof(wndpl);
GetWindowPlacement(hMainWindow, &wndpl);
SetRect(&rc1, 0, 0, WindowWidth, WindowHeight);
AdjustWindowRectEx(&rc1,GetWindowLong(hMainWindow, GWL_STYLE),
GetMenu(hMainWindow) != NULL, GetWindowLong(hMainWindow, GWL_EXSTYLE));
GetClientRect(hMainWindow, &rcWindow);
ClientToScreen(hMainWindow, (LPPOINT) &rcWindow);
ClientToScreen(hMainWindow, (LPPOINT) &rcWindow + 1);
if (FullScreen == 1)
{
if (HQMode && !DSMode)
{
int marginx = (rcWindow.right - rcWindow.left - BlitArea.right + BlitArea.left)/2;
int marginy = (rcWindow.bottom - rcWindow.top - BlitArea.bottom + BlitArea.top)/2;
if (marginx>0)
{
rcWindow.left += marginx;
rcWindow.right -= marginx;
}
if (marginy>0)
{
rcWindow.top += marginy;
rcWindow.bottom -= marginy;
}
}
if ((DSMode == 1) && (scanlines != 0))
{
int OldHeight = rcWindow.bottom - rcWindow.top;
if ((OldHeight % 240) == 0)
{
int NewHeight = (OldHeight/240)*resolutn;
rcWindow.top += (OldHeight - NewHeight)/2;
rcWindow.bottom = rcWindow.top + NewHeight;
clear_display();
}
}
}
}
else
{
atexit(ExitFunction);
if (!QueryPerformanceFrequency((LARGE_INTEGER*)&freq)) return;
if (!RegisterWinClass())
{
exit(1);
}
X=(GetSystemMetrics(SM_CXSCREEN) - WindowWidth) / 2;
Y=(GetSystemMetrics(SM_CYSCREEN) - WindowHeight) / 2;
if (FullScreen==1) {X=0; Y=0;}
if (hMainWindow)
{
CloseWindow(hMainWindow);
}
if (SaveMainWindowPos == 1 && MainWindowX != -1 && FullScreen == 0) { X = MainWindowX; Y = MainWindowY; }
hMainWindow = CreateWindow( "ZSNES", WinName, WS_VISIBLE|WS_POPUP,X,Y, //WS_OVERLAPPED "ZSNES"
WindowWidth,WindowHeight,NULL,NULL,hInst,NULL);
CheckPriority();
CheckAlwaysOnTop();
if (!hMainWindow)
{
return;
}
ShowWindow(hMainWindow, SW_SHOWNORMAL);
SetWindowText(hMainWindow,"ZSNES");
InitInput();
InitSound();
TestJoy();
if (debugger) InitDebugger(); // Start debugger
}
if (FirstVid == 1)
{
FirstVid = 0;
if (Force60hz) Refresh = 60;
InitDirectDraw();
clearwin();
Clear2xSaIBuffer();
clear_display();
return;
}
if (Moving == 1) return;
if (newmode == 1)
{
ReleaseDirectDraw();
InitDirectDraw();
clearwin();
Clear2xSaIBuffer();
clear_display();
return;
}
}
extern unsigned int vidbuffer;
extern void SoundProcess();
extern int DSPBuffer;
int * DSPBuffer1;
DWORD ScreenPtr;
DWORD ScreenPtr2;
extern void GUI36hzcall(void);
extern void Game60hzcall(void);
void CheckTimers(void)
{
// Lame fix for GUI using 100% CPU
if (GUIOn || GUIOn2 || EMUPause) Sleep(1);
QueryPerformanceCounter((LARGE_INTEGER*)&end2);
while ((end2 - start2) >= update_ticks_pc2)
{
start2 += update_ticks_pc2;
}
if (T60HZEnabled == 1)
{
QueryPerformanceCounter((LARGE_INTEGER*)&end);
while ((end - start) >= update_ticks_pc)
{
Game60hzcall();
start += update_ticks_pc;
}
}
if (T36HZEnabled == 1)
{
QueryPerformanceCounter((LARGE_INTEGER*)&end);
while ((end - start) >= update_ticks_pc)
{
GUI36hzcall();
start += update_ticks_pc;
}
}
}
extern unsigned char MMXSupport;
extern "C" {
volatile int SPCSize;
volatile int buffer_ptr;
}
void UpdateVFrame(void)
{
int DataNeeded;
SPCSize=256;
if (StereoSound==1) SPCSize=256;
while (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
WinUpdateDevices();
CheckTimers();
if (SoundEnabled == 0) return;
if(!UsePrimaryBuffer) lpSoundBuffer->GetCurrentPosition(&CurrentPos,&WritePos);
else lpPrimaryBuffer->GetCurrentPosition(&CurrentPos,&WritePos);
if (LastUsedPos <= CurrentPos)
{
DataNeeded=CurrentPos-LastUsedPos;
}
else
{
DataNeeded=SoundBufferSize - LastUsedPos + CurrentPos;
}
DataNeeded/=(SPCSize*2);
DataNeeded*=(SPCSize*2);
while (DataNeeded>0)
{
asm_call(SoundProcess);
DSPBuffer1=(int *)&DSPBuffer;
buffer_ptr = (int)&Buffer[0];
if (T36HZEnabled == 1)
{
if (MMXSupport == 1)
{
ASM_BEGIN
ASM_COMMAND3(mov edi,buffer_ptr)
ASM_COMMAND3(mov ecx,SPCSize)
ASM_COMMAND2(shr ecx,2)
ASM_COMMAND2(pxor mm0,mm0)
ASM_COMMAND(_blank_top_fpu:)
ASM_COMMAND2(movq [edi],mm0)
ASM_COMMAND2(add edi,8)
ASM_COMMAND(dec ecx)
ASM_COMMAND(jne _blank_top_fpu)
ASM_COMMAND(emms)
ASM_END
}
else
{
ASM_BEGIN
ASM_COMMAND3(mov edi,buffer_ptr)
ASM_COMMAND3(mov ecx,SPCSize)
ASM_COMMAND2(shr ecx,1)
ASM_COMMAND2(xor eax,eax)
ASM_COMMAND(_blank_top:)
ASM_COMMAND2(mov [edi],eax)
ASM_COMMAND2(add edi,4)
ASM_COMMAND(dec ecx)
ASM_COMMAND(jne _blank_top)
ASM_END
}
}
else
{
if (MMXSupport == 1)
{
ASM_BEGIN
ASM_COMMAND3(mov esi,DSPBuffer1)
ASM_COMMAND3(mov edi,buffer_ptr)
ASM_COMMAND3(mov ecx,SPCSize)
ASM_COMMAND2(shr ecx,2)
ASM_COMMAND(_top_mmx:)
ASM_COMMAND2(movq mm0,[esi])
ASM_COMMAND2(packssdw mm0,[esi+8])
ASM_COMMAND2(movq [edi],mm0)
ASM_COMMAND2(add esi,16)
ASM_COMMAND2(add edi,8)
ASM_COMMAND(dec ecx)
ASM_COMMAND(jne _top_mmx)
ASM_COMMAND(emms)
ASM_END
}
else
{
for(i=0;i<SPCSize;i++)
{
Buffer[i]=DSPBuffer1[i];
if (DSPBuffer1[i]>32767)Buffer[i]=32767;
if (DSPBuffer1[i]<-32767)Buffer[i]=-32767;
}
}
}
if(!UsePrimaryBuffer)
{
if (DS_OK!=lpSoundBuffer->Lock(LastUsedPos,
SPCSize*2, &lpvPtr1,
&dwBytes1, &lpvPtr2,
&dwBytes2, 0))
{
return;
}
}
else
{
if (DS_OK!=lpPrimaryBuffer->Lock(LastUsedPos,
SPCSize*2, &lpvPtr1,
&dwBytes1, &lpvPtr2,
&dwBytes2, 0))
{
return;
}
}
Sound=(short *)lpvPtr1;
CopyMemory(lpvPtr1, &Buffer[0], dwBytes1);
if (NULL != lpvPtr2)
{
CopyMemory(lpvPtr2, &Buffer[0]+dwBytes1, dwBytes2);
}
if(!UsePrimaryBuffer)
{
if (DS_OK != lpSoundBuffer->Unlock(lpvPtr1, dwBytes1, lpvPtr2, dwBytes2))
{
return;
}
}
else
{
if (DS_OK != lpPrimaryBuffer->Unlock(lpvPtr1, dwBytes1, lpvPtr2, dwBytes2))
{
return;
}
}
LastUsedPos+=SPCSize*2;
if (LastUsedPos==SoundBufferSize) LastUsedPos=0;
DataNeeded-=(SPCSize*2);
}
}
extern unsigned char curblank;
extern DWORD AddEndBytes;
extern DWORD NumBytesPerLine;
extern unsigned char * WinVidMemStart;
extern void copy640x480x16bwin(void);
extern void hq2x_16b(void);
extern void hq2x_32b(void);
extern void hq3x_16b(void);
extern void hq3x_32b(void);
extern void hq4x_16b(void);
extern void hq4x_32b(void);
extern unsigned char NGNoTransp;
extern unsigned char newengen;
extern void ClearWin16();
extern void ClearWin32();
void clearwin()
{
pitch=LockSurface();
if (pitch==0) { return; }
SurfBufD=(DWORD) &SurfBuf[0];
if (AltSurface == 0)
{
switch (BitDepth)
{
case 16:
ClearWin16();
break;
case 32:
ClearWin32();
break;
}
}
else
ClearWin16();
UnlockSurface();
}
void clear_display()
{
if (FullScreen == 1)
{
DDBLTFX ddbltfx;
ddbltfx.dwSize = sizeof(ddbltfx);
ddbltfx.dwFillColor = 0;
if (TripleBufferWin == 1)
{
if ((DD_Primary != NULL) && (DD_BackBuffer != NULL))
{
if (DD_BackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx ) == DDERR_SURFACELOST)
DD_Primary->Restore();
if (DD_Primary->Flip(NULL, DDFLIP_WAIT) == DDERR_SURFACELOST)
DD_Primary->Restore();
if (DD_BackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx ) == DDERR_SURFACELOST)
DD_Primary->Restore();
if (DD_Primary->Flip(NULL, DDFLIP_WAIT) == DDERR_SURFACELOST)
DD_Primary->Restore();
if (DD_BackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx ) == DDERR_SURFACELOST)
DD_Primary->Restore();
}
}
else
{
if (DD_Primary != NULL)
{
if (vsyncon == 1)
{
if (lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, NULL) != DD_OK)
{
DDrawError();
}
}
if (DD_Primary->Blt( NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx ) == DDERR_SURFACELOST)
DD_Primary->Restore();
}
}
}
}
extern void DrawWin256x224x16();
extern void DrawWin256x224x32();
extern void DrawWin320x240x16();
volatile __int64 copymaskRB = 0x001FF800001FF800LL;
volatile __int64 copymaskG = 0x0000FC000000FC00LL;
volatile __int64 copymagic = 0x0008010000080100LL;
volatile __int64 coef = 0x0066009a0066009aLL;
//extern BYTE MotionBlur;
extern WORD totlines;
void drawscreenwin(void)
{
DWORD i,j,color32;
DWORD *SURFDW;
NGNoTransp = 0; // Set this value to 1 within the appropriate
// video mode if you want to add a custom
// transparency routine or hardware
// transparency. This only works if
// the value of newengen is equal to 1.
// (see ProcessTransparencies in newgfx16.asm
// for ZSNES' current transparency code)
UpdateVFrame();
if (curblank!=0) return;
if (!(pitch = LockSurface()))
return;
ScreenPtr=vidbuffer;
ScreenPtr+=16*2+32*2+256*2;
DWORD HQMode=0;
if (MMXSupport == 0)
hqFilter=0;
if ( hqFilter != 0 )
{
if ( GUIHQ2X[cvidmode] != 0 ) HQMode=2;
if ( GUIHQ3X[cvidmode] != 0 ) HQMode=3;
if ( GUIHQ4X[cvidmode] != 0 ) HQMode=4;
}
if (PrevRes != resolutn)
{
if ((SurfaceX == 640) || (SurfaceX == 320))
BlitArea.bottom = SurfaceY;
else
BlitArea.bottom = (SurfaceY/240)*resolutn;
if ((FullScreen == 0) && (SMode == 0) && (DSMode == 0))
WindowHeight = (WindowHeight/224)*resolutn;
initwinvideo();
PrevRes = resolutn;
}
if (prevHQMode!=HQMode)
initwinvideo();
if (prevScanlines != scanlines)
{
initwinvideo();
prevScanlines = scanlines;
}
SurfBufD=(DWORD) &SurfBuf[0];
SURFDW=(DWORD *) &SurfBuf[0];
if (!KitchenSync && Refresh !=0 && !Force60hz)
{
Refresh = 0;
InitDirectDraw();
}
if (KitchenSync && Refresh != 120 && totlines == 263)
{
Refresh = 120;
InitDirectDraw();
}
if (KitchenSync && Refresh != 100 && totlines == 314)
{
Refresh = 100;
InitDirectDraw();
}
if ( HQMode == 0 )
{
if (SurfaceX == 256 && SurfaceY == 240)
{
switch (BitDepth)
{
case 16:
{
DrawWin256x224x16();
break;
}
case 32:
{
DrawWin256x224x32();
break;
}
SURFDW=(DWORD *) &SurfBuf[(resolutn-1)*pitch];
color32=0x7F000000;
for(i=0;i<256;i++)
{
SURFDW[i]=color32;
}
SURFDW=(DWORD *) &SurfBuf[resolutn*pitch];
color32=0x7F000000;
for(i=0;i<256;i++)
{
SURFDW[i]=color32;
}
break;
case 24:
MessageBox (NULL, "Sorry. ZSNESw does not work in windowed 24 bit color modes. \nClick 'OK' to switch to a full screen mode.", "DDRAW Error" , MB_ICONERROR );
cvidmode=3;
initwinvideo();
Sleep(1000);
drawscreenwin();
break;
default:
UnlockSurface();
MessageBox (NULL, "Mode only available in 16 and 32 bit color", "DDRAW Error" , MB_ICONERROR );
cvidmode=2;
initwinvideo();
Sleep(1000);
drawscreenwin();
break;
}
}
if (SurfaceX == 320 && SurfaceY == 240)
{
switch (BitDepth)
{
case 16:
{
DrawWin320x240x16();
break;
}
case 32:
for(j=0;j<8;j++)
{
SURFDW=(DWORD *) &SurfBuf[j*pitch];
color32=0x7F000000;
for(i=0;i<320;i++)
{
SURFDW[i]=color32;
}
}
for(j=8;(int)j<(resolutn-1)+8;j++)
{
color32=0x7F000000;
for(i=0;i<32;i++)
{
SURFDW[i]=color32;
}
for(i=32;i<(256+32);i++)
{
color32=(((*(WORD *)(ScreenPtr))&0xF800)<<8)+
(((*(WORD *)(ScreenPtr))&0x07E0)<<5)+
(((*(WORD *)(ScreenPtr))&0x001F)<<3)+0xFF000000;
// SURFDW[i]=color32;
ScreenPtr+=2;
}
color32=0x7F000000;
for(i=(256+32);i<320;i++)
{
SURFDW[i]=color32;
}
ScreenPtr=ScreenPtr+576-512;
SURFDW=(DWORD *) &SurfBuf[(j)*pitch];
}
for(j=((resolutn-1)+8);j<240;j++)
{
SURFDW=(DWORD *) &SurfBuf[j*pitch];
color32=0x7F000000;
for(i=0;i<320;i++)
{
SURFDW[i]=color32;
}
}
break;
default:
UnlockSurface();
MessageBox (NULL, "Mode only available in 16 and 32 bit color", "DDRAW Error" , MB_ICONERROR );
cvidmode=2;
initwinvideo();
Sleep(1000);
drawscreenwin();
break;
}
}
if (SurfaceX==512 && SurfaceY==480)
{
switch (BitDepth)
{
case 16:
case 32: // using 16bpp AltSurface
AddEndBytes=pitch-1024;
NumBytesPerLine=pitch;
WinVidMemStart=&SurfBuf[0];
asm_call(copy640x480x16bwin);
break;
default:
UnlockSurface();
MessageBox (NULL, "Mode only available in 16 and 32 bit color", "DDRAW Error" , MB_ICONERROR );
cvidmode=2;
initwinvideo();
Sleep(1000);
drawscreenwin();
}
}
if (SurfaceX == 640 && SurfaceY == 480)
{
switch (BitDepth)
{
case 16:
case 32: // using 16bpp AltSurface
AddEndBytes=pitch-1024;
NumBytesPerLine=pitch;
WinVidMemStart=&SurfBuf[(240-resolutn)*pitch+64*2];
asm_call(copy640x480x16bwin);
break;
default:
UnlockSurface();
MessageBox (NULL, "Mode only available in 16 and 32 bit color", "DDRAW Error" , MB_ICONERROR );
cvidmode=2;
initwinvideo();
Sleep(1000);
drawscreenwin();
}
}
}
else
{
// HQMode != 0
NumBytesPerLine = pitch;
AddEndBytes = pitch - SurfaceX*(BitDepth/8);
WinVidMemStart=&SurfBuf[0];
switch (BitDepth)
{
case 16:
{
switch (HQMode)
{
case 2: hq2x_16b(); break;
case 3: hq3x_16b(); break;
case 4: hq4x_16b(); break;
}
break;
}
case 32:
{
switch (HQMode)
{
case 2: hq2x_32b(); break;
case 3: hq3x_32b(); break;
case 4: hq4x_32b(); break;
}
break;
}
default:
{
UnlockSurface();
MessageBox (NULL, "Mode only available in 16 and 32 bit color", "DDRAW Error" , MB_ICONERROR );
cvidmode=2;
initwinvideo();
Sleep(1000);
drawscreenwin();
}
}
}
UnlockSurface();
DrawScreen();
}
extern void SwitchFullScreen(void);
void WinUpdateDevices()
{
int i,j;
unsigned char * keys;
unsigned char keys2[256];
//MK: unused 2003/08/31
//HRESULT hRes;
for (i = 0; i<256; i++)
keys2[i] = 0;
keys = (unsigned char *)&pressed;
if (KeyboardInput&&InputEn==1)
{
KeyboardInput->GetDeviceState(256, keys2);
}
else
{
return;
}
if (keys2[0x38] != 0 && keys2[0x3E] != 0) exit(0);
if (keys2[0xB8] != 0 && keys2[0x1C] != 0 || keys2[0x38] != 0 && keys2[0x1C] != 0)
{
asm_call(SwitchFullScreen);
return;
}
for(i=0; i<256; i++)
{
if (keys2[i] == 0) keys[i] = 0;
if (keys2[i] != 0 && keys[i] == 0) keys[i] = 1;
}
keys[0] = 0;
for(i=0; i<5; i++)
{
if (JoystickInput[i])
{
for(j=0; j<32; j++)
{
keys[0x100 + i * 32 + j] = 0;
}
JoystickInput[i]->Poll();
if (JoystickInput[i]->GetDeviceState(sizeof(DIJOYSTATE), &js[i])==DIERR_INPUTLOST)
{
if (JoystickInput[i]) JoystickInput[i]->Acquire();
if (FAILED(JoystickInput[i]->GetDeviceState(sizeof(DIJOYSTATE), &js[i]))) return;
}
if (!X1Disable[i])
{
if (js[i].lX>0) keys[0x100 + i * 32 + 0] = 1;
}
if (!X2Disable[i])
{
if (js[i].lX<0) keys[0x100 + i * 32 + 1] = 1;
}
if (!Y1Disable[i])
{
if (js[i].lY>0) keys[0x100 + i * 32 + 2] = 1;
}
if (!Y2Disable[i])
{
if (js[i].lY<0) keys[0x100 + i * 32 + 3] = 1;
}
if (!Z1Disable[i])
{
if (js[i].lZ>0) keys[0x100 + i * 32 + 4] = 1;
}
if (!Z2Disable[i])
{
if (js[i].lZ<0) keys[0x100 + i * 32 + 5] = 1;
}
if (!RY1Disable[i])
{
if (js[i].lRy>0) keys[0x100 + i * 32 + 6] = 1;
}
if (!RY2Disable[i])
{
if (js[i].lRy<0) keys[0x100 + i * 32 + 7] = 1;
}
if (!RZ1Disable[i])
{
if (js[i].lRz>0) keys[0x100 + i * 32 + 8] = 1;
}
if (!RZ2Disable[i])
{
if (js[i].lRz<0) keys[0x100 + i * 32 + 9] = 1;
}
if (!S01Disable[i])
{
if (js[i].rglSlider[0]>0) keys[0x100 + i * 32 + 10] = 1;
}
if (!S02Disable[i])
{
if (js[i].rglSlider[0]<0) keys[0x100 + i * 32 + 11] = 1;
}
if (!S11Disable[i])
{
if (js[i].rglSlider[1]>0) keys[0x100 + i * 32 + 12] = 1;
}
if (!S12Disable[i])
{
if (js[i].rglSlider[1]<0) keys[0x100 + i * 32 + 13] = 1;
}
if (!POVDisable[i])
{
for (int p=0; (unsigned long)p<NumPOV[i]; p++)
{
switch (js[i].rgdwPOV[p])
{
case 0:
keys[0x100 + i * 32 + 3] = 1;
break;
case 4500:
keys[0x100 + i * 32 + 0] = 1;
keys[0x100 + i * 32 + 3] = 1;
break;
case 9000:
keys[0x100 + i * 32 + 0] = 1;
break;
case 13500:
keys[0x100 + i * 32 + 0] = 1;
keys[0x100 + i * 32 + 2] = 1;
break;
case 18000:
keys[0x100 + i * 32 + 2] = 1;
break;
case 22500:
keys[0x100 + i * 32 + 1] = 1;
keys[0x100 + i * 32 + 2] = 1;
break;
case 27000:
keys[0x100 + i * 32 + 1] = 1;
break;
case 31500:
keys[0x100 + i * 32 + 1] = 1;
keys[0x100 + i * 32 + 3] = 1;
break;
}
}
}
if (NumBTN[i])
for (j=0; (unsigned long)j<NumBTN[i]; j++)
if (js[i].rgbButtons[j]) keys[0x100 + i * 32 + 16 + j] = 1;
}
else
{
for(j=0; j<32; j++)
{
keys[0x100 + i * 32 + j] = 0;
}
}
}
}
extern BYTE snesmouse;
int GetMouseX(void)
{
InputRead();
MouseX += MouseMoveX;
if (MouseX > MouseMaxX)
{
MouseX = MouseMaxX;
if (TrapMouseCursor == 1)
{
if (abs((int)MouseMoveX) > 10 && T36HZEnabled == 1 && FullScreen == 0 && MouseButtonPressed == 0)
{
MouseInput->Unacquire();
SetCursorPos(X + WindowWidth + 32, (int)(Y + (MouseY * WindowHeight / 224)));
}
}
else if (FullScreen == 0 && snesmouse == 0 && MouseButtonPressed == 0 && GUIOn2 == 1)
{
MouseInput->Unacquire();
SetCursorPos(X + WindowWidth + 1, (int)(Y + (MouseY * WindowHeight / 224)));
}
}
if (MouseX < MouseMinX)
{
MouseX = MouseMinX;
if (TrapMouseCursor == 1)
{
if (abs((int)MouseMoveX) > 10 && T36HZEnabled == 1 && FullScreen == 0 && MouseButtonPressed == 0)
{
MouseInput->Unacquire();
SetCursorPos(X - 32, (int)(Y + (MouseY * WindowHeight / 224)));
}
}
else if (FullScreen == 0 && snesmouse == 0 && MouseButtonPressed == 0 && GUIOn2 == 1)
{
MouseInput->Unacquire();
SetCursorPos(X - 1, (int)(Y + (MouseY * WindowHeight / 224)));
}
}
return((int) MouseX);
}
int GetMouseY(void)
{
MouseY += MouseMoveY;
if (MouseY > MouseMaxY)
{
MouseY = MouseMaxY;
if (TrapMouseCursor == 1)
{
if (abs((int)MouseMoveY) > 10 && T36HZEnabled == 1 && FullScreen == 0 && MouseButtonPressed == 0)
{
MouseInput->Unacquire();
SetCursorPos((int)(X+(MouseX * WindowWidth / 256)), Y + WindowHeight + 32);
}
}
else if (FullScreen == 0 && snesmouse == 0 && MouseButtonPressed == 0 && GUIOn2 == 1)
{
MouseInput->Unacquire();
SetCursorPos((int)(X+(MouseX * WindowWidth / 256)), Y + WindowHeight + 1);
}
}
if (MouseY < MouseMinY)
{
MouseY = MouseMinY;
if (TrapMouseCursor == 1)
{
if (abs((int)MouseMoveY) > 10 && T36HZEnabled == 1 && FullScreen == 0 && MouseButtonPressed == 0)
{
MouseInput->Unacquire();
SetCursorPos((int)(X + (MouseX * WindowWidth / 256)), Y - 32);
}
}
else if (FullScreen == 0 && snesmouse == 0 && MouseButtonPressed == 0 && GUIOn2 == 1)
{
MouseInput->Unacquire();
SetCursorPos((int)(X + (MouseX * WindowWidth / 256)), Y - 1);
}
}
return((int) MouseY);
}
int GetMouseMoveX(void)
{
MouseMove2X=(int)MouseMoveX;
return(MouseMove2X);
}
int GetMouseMoveY(void)
{
MouseMove2Y=(int)MouseMoveY;
return(MouseMove2Y);
}
int GetMouseButton(void)
{
//MK: unused 2003/08/31
//RECT rc1;
if (MouseButton == 1) MouseButtonPressed = 1;
else MouseButtonPressed = 0;
if (MouseButton&2)
{
while (MouseButton != 0 && T36HZEnabled && FullScreen == 0)
{
Moving = 1;
X += (int) MouseMoveX;
Y += (int) MouseMoveY;
if (X < 0)X = 0;
if (X > (int)(GetSystemMetrics(SM_CXSCREEN) - WindowWidth)) X = (GetSystemMetrics(SM_CXSCREEN) - WindowWidth);
if (Y < 0)Y=0;
if (Y > (int)(GetSystemMetrics(SM_CYSCREEN) - WindowHeight)) Y = (GetSystemMetrics(SM_CYSCREEN) - WindowHeight);
InputRead();
initwinvideo();
}
}
if (Moving == 1)
{
Moving = 0;
initwinvideo();
}
return((int) MouseButton);
}
void SetMouseMinX(int MinX)
{
MouseMinX = (float) MinX;
}
void SetMouseMaxX(int MaxX)
{
MouseMaxX = (float) MaxX;
}
void SetMouseMinY(int MinY)
{
MouseMinY = (float) MinY;
}
void SetMouseMaxY(int MaxY)
{
MouseMaxY = (float) MaxY;
}
void SetMouseX(int X)
{
MouseX = (float) X;
}
void SetMouseY(int Y)
{
MouseY = (float) Y;
}
void FrameSemaphore()
{
if (T60HZEnabled)
{
double delay;
QueryPerformanceCounter((LARGE_INTEGER*)&end);
delay = ((update_ticks_pc - (end - start)) * 1000.0 / freq) - 3.0;
if (delay>0.0) WaitForSingleObject(hLock, (unsigned int)delay);
}
}
void ZsnesPage()
{
ShellExecute(NULL, NULL, "http://www.zsnes.com/", NULL, NULL, 0);
MouseX = 0;
MouseY = 0;
}
// This function creates the debug console
void InitDebugger()
{
if(AllocConsole())
{
debugWindow = GetStdHandle(STD_OUTPUT_HANDLE);
WriteConsole(debugWindow, "Welcome to the ZSNES Debugger v0.01\n", sizeof("Welcome to the ZSNES Debugger v0.01\n"), NULL, NULL);
}
}
}