#include "app.h"
#define DIRECTINPUT_VERSION 0x0800
#define DIRECTSOUND_VERSION 0x0800

unsigned char Flicker=0;
//unsigned char HardwareFilter=1;
extern float getVolume();
extern void setVolume(float v);
 
extern "C" {
   extern unsigned char cfgSoundQuality;
   extern unsigned char antienab;
   extern unsigned char Mode7HiRes16b;
   extern unsigned char newgfx16b;
   extern unsigned char RevStereo;
   extern unsigned char OldGfxMode2;
   extern unsigned char Surround;
   extern DWORD SoundQuality;
}

#define u32 unsigned int
#define u8 unsigned char
#define uint32 unsigned int
#define uint16 unsigned short
#define uint8 unsigned char

extern void Normal2x(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch,
							int width, int height);
extern void Normal1x(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch,
							int width, int height);
extern void AdMame2x(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
			  u8 *dstPtr, u32 dstPitch, int width, int height);

extern void AdvMame2x(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch,
							 int width, int height);
unsigned char SoftwareFilter;

extern IDirect3DVertexBuffer8 *VertexBuffer;
extern IDirect3DVertexBuffer8 *VertexBufferPreview;
extern IDirect3DVertexBuffer8 *VertexBufferLinear;
extern IDirect3DVertexBuffer8 *VertexBufferResize;
extern IDirect3DVertexBuffer8 *VertexBufferController;
extern IDirect3DVertexBuffer8 *VertexBufferOptions;
//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)
extern CustomVertex VertexList[4];
extern CustomVertex VertexListPreview[4];
extern CustomVertex VertexListLinear[4];
extern CustomVertex VertexListResize[4];
extern CustomVertex VertexListController[4];
extern CustomVertex VertexListOptions[4];
extern int screenResize;
extern int screenController;
extern int screenOptions;
extern  float zBottom;
extern  float zTop;
extern  float zLeft;
extern  float zRight;
extern void makeVertexListLinear();
extern void makeVertexListResize();
extern void makeVertexListController();
extern void makeVertexListOptions();
extern void setTextureMode();
extern float zTop;
extern float zLeft;
extern float zBottom;
extern float zRight;

extern "C" {
    void loadIni() {
       FILE* f;
    	f = fopen("D:\\ini\\ZsnexBox.ini", "r");
    	//dprintf("Screen Before: %d, %d, %d, %d\n", zLeft, zRight, zTop, zBottom);
    	if(f) {
    		char line[100];
    		
    		fgets(line,100, f);
    		for(int i = 0; i < 100; i++) {
    			if(line[i] == '=') {
    				//char c = line[i+1];
    				zLeft =  (float) atof(&line[i+1]);
    				break;
    			}
    		}
    		
    		char line2[100];
    		fgets(line2,100, f);
    		for(int i = 0; i < 100; i++) {
    			if(line2[i] == '=') {
    				char c = line2[i+1];
    				zRight =  (float) atof(&line2[i+1]);;
    				break;
    			}
    		}
    		
    		char line3[100];
    		fgets(line3,100, f);
    		for(int i = 0; i < 100; i++) {
    			if(line3[i] == '=') {
    				char c = line3[i+1];
    				zTop =  (float) atof(&line3[i+1]);
    				break;
    			}
    		}
    		
    		char line4[100];
    		fgets(line4,100, f);
    		for(int i = 0; i < 100; i++) {
    			if(line4[i] == '=') {
    				char c = line4[i+1];
    				zBottom = (float) atof(&line4[i+1]);
    				break;
    			}
    		}
    	}
    	else {
    		dprintf("Unable to load ini\n");
    		
    	}
    
    	if(f) fclose(f);
    
    	SoftwareFilter = 3;
    	Surround = 0;
    	return;
    }
}

extern void SwitchFullScreen(void);
extern  void pauseMusic();
extern void pauseMusic();
extern void resumeMusic();
extern void updateSound();
extern void setTexture();
//struct Input ZsnesInp;
//HANDLE ZsnesGamePad=NULL;
//XINPUT_STATE ZsnesPad;

//struct Input ZsnesInp2;
//HANDLE ZsnesGamePad2=NULL;
//XINPUT_STATE ZsnesPad2;

extern  void playEffect(); 
extern  void updateEffect(); 
extern int MenuRender();
extern "C" void init();
extern "C" unsigned char fname[512];
extern "C" unsigned char fnames[512];
extern "C" unsigned char fnamest[512];
class FileMenu
{
public:
  FileMenu();
  int init();
  int scan();
  void exit();
  int render();
  int scroll(int amount);
  int getFilePath(char *name);

private:
  int nameReset();
  int nameFind(char *path);
  int nameAdd(char *entry);
  int nameSizeUp();
  int nameOffset(int index);

  char currentPath[260];
  char *nameList;
  int nameSize,nameMax;
  int nameCount;

  int choiceFocus;
};

extern FileMenu FileMenu;
extern bool a;
extern bool b;

extern "C" {
    extern unsigned char FPSAtStart;
    volatile int SPCSize;
    extern unsigned int pl1selk;
    extern unsigned int pl1startk;
    extern unsigned int pl1upk;
    extern unsigned int pl1Ak;
    extern unsigned int pl1Bk;
    extern unsigned int pl1Lk;
    extern unsigned int pl1Rk;
    extern unsigned int pl1Xk;
    extern unsigned int pl1Yk;
    extern unsigned int pl1downk;
    extern unsigned int pl1leftk;
    extern unsigned int pl1rightk;
    extern unsigned int pl2selk;
    extern unsigned int pl2startk;
    extern unsigned int pl2upk;
    extern unsigned int pl2Ak;
    extern unsigned int pl2Bk;
    extern unsigned int pl2Lk;
    extern unsigned int pl2Rk;
    extern unsigned int pl2Xk;
    extern unsigned int pl2Yk;
    extern unsigned int pl2downk;
    extern unsigned int pl2leftk;
    extern unsigned int pl2rightk;
    extern unsigned char pl1contrl;
    extern unsigned char pl2contrl;
    extern unsigned char KeyFastFrwrd;
    extern unsigned char KeyRewind;
    extern unsigned char KeySaveState;
    extern unsigned char KeyLoadState;
    extern void statesaver();
    extern void loadstate();
}

extern "C" {
   #include <stdio.h>
   #include <time.h>
}
#include <math.h>
#include <dsound.h>
#include "resource.h"
extern "C" int dprintf(char *Format, ...);
extern LPDIRECTSOUND8  m_pDSound;
extern int SetupMatrices();

D3DLOCKED_RECT lockScreen;

#ifdef __GNUC__ //MinGW

//Simple start and end structure, set as volatile so perhaps we can use -O1+ later
#define ASM_BEGIN asm volatile ( \
ASM_COMMAND(pushad)
#define ASM_END ASM_COMMAND(popad) \
);
//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

HANDLE debugWindow = 0;

extern "C"
{
HINSTANCE hInst;
unsigned char KitchenSync = 0;
unsigned char Force60hz = 0;
}

LPDIRECTSOUNDBUFFER     lpPrimaryBuffer = NULL;
DSBUFFERDESC dsbd;

LPVOID lpvPtr1;
DWORD dwBytes1;
LPVOID lpvPtr2;
DWORD dwBytes2;
RECT                    rcWindow;

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;

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 DisplayWIPDisclaimer();
    void InitDebugger();
    
    void Clear2xSaIBuffer();
    void clear_display();
}

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;

#define UPDATE_TICKS_GAME (1000.0/59.948743718592964824120603015060)
#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;

extern "C" BYTE vsyncon;
extern "C" BYTE KitchenSync;
extern "C" BYTE TripleBufferWin;
extern "C" BYTE PauseFocusChange;

extern "C" {
    extern BYTE GUIOn;
    extern BYTE GUIOn2;
}
DWORD InputEn=1;

extern "C" {
    void initwinvideo();
    void DosExit(void);
    extern BYTE cfgsoundon;
    extern BYTE StereoSound;
    
    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;
}

BYTE PrevStereoSound;
DWORD PrevSoundQuality;

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 NTSCMode=0;
DWORD prevHQMode=~0;
DWORD prevNTSCMode=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[];
extern "C" BYTE GUINTVID[];

extern "C" void FreeDirectX(){}
extern "C" void DXLoadError(){FreeDirectX();}
extern "C" void ImportDirectX(){}
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(){}
void DrawScreen(){}
extern "C" void MultiMouseInit();
extern "C" void MultiMouseShutdown();

BOOL InputAcquire(void){InputEn = 1;return TRUE;}
BOOL InputDeAcquire(void){InputEn = 0;return TRUE;}

extern "C" void CheckPriority(){}
extern "C" void CheckAlwaysOnTop(){}
extern "C" void CheckScreenSaver(){}
extern "C" void MinimizeWindow(){IsActivated = 0;}
extern "C" BYTE MouseWheel;
BOOL InputRead(void){return TRUE;}
extern "C" void SaveSramData(void);
extern "C" void GUISaveVars(void);
extern "C" void createnewcfg(void);
void ExitFunction(){}
LRESULT CALLBACK Main_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){return 0;}
int RegisterWinClass(void){return TRUE;}
extern "C" { extern unsigned char PrimaryBuffer; }

BOOL ReInitSound(){return TRUE;}
void ReleaseDirectInput(){}
void ReleaseDirectSound(){}
void ReleaseDirectDraw(){}
void DInputError(){}
bool InitInput(){return TRUE;}
void TestJoy(){}
int InitDirectDraw(){return TRUE;}
BYTE* SurfBuf;
DWORD LockSurface(){return 0;}
void UnlockSurface(){}

extern "C" {
    void WinUpdateDevices();
    short Buffer[1800*2];
    int X, Y;
    DWORD pitch;
    DWORD SurfBufD;
    int count, x,count2;
    HRESULT hr;
    int i;
    short *Sound;
    DWORD CurrentPos;
    DWORD WritePos;
    DWORD T60HZEnabled=0;
    DWORD T36HZEnabled=0;  
    extern unsigned int pressed;
    extern unsigned char romispal;  
    void Stop36HZ(void){T36HZEnabled=0;}
    char WinMessage[256];
    void clearwin();
    char WinName[]={"ZSNESW\0"};
    extern unsigned int vidbuffer;
    extern void SoundProcess();
    extern int DSPBuffer;
    int * DSPBuffer1;
    DWORD ScreenPtr;
    DWORD ScreenPtr2;
    extern void GUI36hzcall(void);
    extern void Game60hzcall(void); 
    extern unsigned char MMXSupport;
    extern "C" {volatile int buffer_ptr;}
    int DataNeeded;    
    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(){}
    void clear_display(){}
    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;
    extern unsigned char FPSAtStart;
    extern unsigned char FPSOn;
    extern unsigned char En2xSaI; 
    extern void GUIDoReset();
    void clearvidsound();
    int ZsnesModeUpdate(){return 0;}
    int gpInit = 0;
    int m = 0;
    int GetMouseX(void){return 0;}
    int GetMouseY(void){return 0;}
    int GetMouseMoveX(void){return 0;}
    int GetMouseMoveY(void){return 0;}
    int GetMouseButton(void){return 0;}
    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 ZsnesPage(){MouseX = 0;MouseY = 0;}
    void DocsPage(){MouseX = 0;MouseY = 0;}
    extern "C" signed int NumberOfOpcodes;
    void WriteLine(){char buf[50];sprintf(buf, "%d\n", NumberOfOpcodes);}
    void InitDebugger(){}
    int CheckBattery(){return 0;}
    int CheckBatteryTime(){return 0;}
    int CheckBatteryPercent(){return 0;}
    void DoSleep(){Sleep(1);}
    extern "C" unsigned int PrevBuildNum;
    void DisplayWIPDisclaimer(){}
}

extern "C" void InitPreGame();
extern "C" void DeInitPostGame();

