mirror of
https://github.com/Pecusx/libretro-atari800.git
synced 2026-05-21 14:49:36 +02:00
initial commit
This commit is contained in:
@@ -0,0 +1 @@
|
||||
atari.res
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* atari.rc - Win32 port specific code
|
||||
*
|
||||
* Copyright (C) 2000 Krzysztof Nikiel
|
||||
* Copyright (C) 2000-2003 Atari800 development team (see DOC/CREDITS)
|
||||
*
|
||||
* This file is part of the Atari800 emulator project which emulates
|
||||
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
|
||||
*
|
||||
* Atari800 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.
|
||||
*
|
||||
* Atari800 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 Atari800; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
Icon1 ICON win32/atari1.ico
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 766 B |
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,123 @@
|
||||
#ifndef _ATARI_WIN32_H_
|
||||
#define _ATARI_WIN32_H_
|
||||
|
||||
#define DIRECTINPUT_VERSION 0x0500
|
||||
|
||||
#include <dinput.h>
|
||||
#include "akey.h"
|
||||
|
||||
#define MAXKEYNAMELENGTH 40
|
||||
|
||||
/* keyboard code key-value pairs */
|
||||
/* for use in joystick button mapping */
|
||||
typedef struct {
|
||||
int keyvalue;
|
||||
char* keyname;
|
||||
} _keyref;
|
||||
|
||||
/* Set of keys that may be mapped to joystick/gamepad buttons */
|
||||
/* If you add to this list, be sure to TEST them, not all keys work the same */
|
||||
/* and may require additional code support. */
|
||||
static const _keyref keyref[] = {
|
||||
{AKEY_0, "0"}, {AKEY_1, "1"}, {AKEY_2, "2"}, {AKEY_3, "3"}, {AKEY_4, "4"},
|
||||
{AKEY_5, "5"}, {AKEY_6, "6"}, {AKEY_7, "7"}, {AKEY_8, "8"}, {AKEY_9, "9"},
|
||||
{AKEY_a, "a"}, {AKEY_b, "b"}, {AKEY_c, "c"}, {AKEY_d, "d"}, {AKEY_e, "e"},
|
||||
{AKEY_f, "f"}, {AKEY_g, "g"}, {AKEY_h, "h"}, {AKEY_i, "i"}, {AKEY_j, "j"},
|
||||
{AKEY_k, "k"}, {AKEY_l, "l"}, {AKEY_m, "m"}, {AKEY_n, "n"}, {AKEY_o, "o"},
|
||||
{AKEY_p, "p"}, {AKEY_q, "q"}, {AKEY_r, "r"}, {AKEY_s, "s"}, {AKEY_t, "t"},
|
||||
{AKEY_u, "u"}, {AKEY_v, "v"}, {AKEY_w, "w"}, {AKEY_x, "x"}, {AKEY_y, "y"},
|
||||
{AKEY_z, "z"}, {AKEY_A, "A"}, {AKEY_B, "B"}, {AKEY_C, "C"}, {AKEY_D, "D"},
|
||||
{AKEY_E, "E"}, {AKEY_F, "F"}, {AKEY_G, "G"}, {AKEY_H, "H"}, {AKEY_I, "I"},
|
||||
{AKEY_J, "J"}, {AKEY_K, "K"}, {AKEY_L, "L"}, {AKEY_M, "M"}, {AKEY_N, "N"},
|
||||
{AKEY_O, "O"}, {AKEY_P, "P"}, {AKEY_Q, "Q"}, {AKEY_R, "R"}, {AKEY_S, "S"},
|
||||
{AKEY_T, "T"}, {AKEY_U, "U"}, {AKEY_V, "V"}, {AKEY_W, "W"}, {AKEY_X, "X"},
|
||||
{AKEY_Y, "Y"}, {AKEY_Z, "Z"}, {AKEY_START, "START"}, {AKEY_SELECT, "SELECT"},
|
||||
{AKEY_OPTION, "OPTION"}, {AKEY_RETURN, "RETURN"}, {AKEY_SPACE, "SPACE"}
|
||||
};
|
||||
|
||||
static const int MAXKEYREFS = sizeof(keyref)/sizeof(*keyref);
|
||||
|
||||
/* keypad mode joydefs */
|
||||
static const UBYTE joydefs[] =
|
||||
{
|
||||
DIK_NUMPAD0, /* fire */
|
||||
DIK_NUMPAD7, /* up/left */
|
||||
DIK_NUMPAD8, /* up */
|
||||
DIK_NUMPAD9, /* up/right */
|
||||
DIK_NUMPAD4, /* left */
|
||||
DIK_NUMPAD6, /* right */
|
||||
DIK_NUMPAD1, /* down/left */
|
||||
DIK_NUMPAD2, /* down */
|
||||
DIK_NUMPAD3, /* down/right */
|
||||
};
|
||||
|
||||
/* keypad mode joymask */
|
||||
static const UBYTE joymask[] =
|
||||
{
|
||||
INPUT_STICK_CENTRE, /* not used */
|
||||
INPUT_STICK_UL, /* up/left */
|
||||
INPUT_STICK_FORWARD, /* up */
|
||||
INPUT_STICK_UR, /* up/right */
|
||||
INPUT_STICK_LEFT, /* left */
|
||||
INPUT_STICK_RIGHT, /* right */
|
||||
INPUT_STICK_LL, /* down/left */
|
||||
INPUT_STICK_BACK, /* down */
|
||||
INPUT_STICK_LR, /* down/right */
|
||||
};
|
||||
|
||||
/* keypad plus mode joydefs */
|
||||
static const UBYTE joydefs_plus[] =
|
||||
{
|
||||
DIK_NUMPAD0, /* fire */
|
||||
DIK_NUMPAD7, /* up/left */
|
||||
DIK_NUMPAD8, /* up */
|
||||
DIK_NUMPAD9, /* up/right */
|
||||
DIK_NUMPAD4, /* left */
|
||||
DIK_NUMPAD6, /* right */
|
||||
DIK_NUMPAD1, /* down/left */
|
||||
DIK_NUMPAD2, /* down */
|
||||
DIK_NUMPAD5, /* duplicate down on 5 key for inverted T */
|
||||
DIK_NUMPAD3, /* down/right */
|
||||
};
|
||||
|
||||
/* keypad plus mode joymask */
|
||||
static const UBYTE joymask_plus[] =
|
||||
{
|
||||
INPUT_STICK_CENTRE, /* not used */
|
||||
INPUT_STICK_UL, /* up/left */
|
||||
INPUT_STICK_FORWARD, /* up */
|
||||
INPUT_STICK_UR, /* up/right */
|
||||
INPUT_STICK_LEFT, /* left */
|
||||
INPUT_STICK_RIGHT, /* right */
|
||||
INPUT_STICK_LL, /* down/left */
|
||||
INPUT_STICK_BACK, /* down */
|
||||
INPUT_STICK_BACK, /* duplicate down on 5 key for inverted T */
|
||||
INPUT_STICK_LR, /* down/right */
|
||||
};
|
||||
|
||||
/* arrow mode joydefs */
|
||||
static const UBYTE joydefs_arrow[] =
|
||||
{
|
||||
DIK_NUMPAD0,
|
||||
DIK_UP,
|
||||
DIK_LEFT,
|
||||
DIK_RIGHT,
|
||||
DIK_DOWN,
|
||||
};
|
||||
|
||||
/* arrow mod joymask */
|
||||
static const UBYTE joymask_arrow[] =
|
||||
{
|
||||
INPUT_STICK_CENTRE, /* not used */
|
||||
INPUT_STICK_FORWARD, /* up */
|
||||
INPUT_STICK_LEFT, /* left */
|
||||
INPUT_STICK_RIGHT, /* right */
|
||||
INPUT_STICK_BACK, /* down */
|
||||
};
|
||||
|
||||
int getkeyvalue(char *name);
|
||||
void getkeyname(int value, char *name);
|
||||
void Win32_Init(void);
|
||||
|
||||
#endif /* _ATARI_WIN32_H_ */
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* joystick.c - Win32 port specific code
|
||||
*
|
||||
* Copyright (C) 2005 James Wilkinson
|
||||
* Copyright (C) 2005-2010 Atari800 development team (see DOC/CREDITS)
|
||||
*
|
||||
* This file is part of the Atari800 emulator project which emulates
|
||||
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
|
||||
*
|
||||
* Atari800 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.
|
||||
*
|
||||
* Atari800 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 Atari800; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define DIRECTINPUT_VERSION 0x0500
|
||||
|
||||
#include "config.h"
|
||||
#include <windows.h>
|
||||
#include <dinput.h>
|
||||
|
||||
#include "atari.h"
|
||||
#include "input.h"
|
||||
#include "log.h"
|
||||
|
||||
#include "joystick.h"
|
||||
#include "main.h"
|
||||
|
||||
HRESULT
|
||||
SetDIDwordProperty(LPDIRECTINPUTDEVICE pdev, REFGUID guidProperty,
|
||||
DWORD dwObject, DWORD dwHow, DWORD dwValue);
|
||||
|
||||
tjoystat joystat;
|
||||
static LPDIRECTINPUTDEVICE2 dijoy[NUM_STICKS] = {NULL};
|
||||
|
||||
int joyreacquire(int num)
|
||||
{
|
||||
if (!dijoy[num])
|
||||
return 1;
|
||||
if (IDirectInputDevice_Acquire(dijoy[num]) >= 0)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
int procjoy(int num)
|
||||
{
|
||||
DIJOYSTATE js;
|
||||
HRESULT hRes;
|
||||
int i;
|
||||
|
||||
if (!dijoy[num])
|
||||
return 1;
|
||||
IDirectInputDevice2_Poll(dijoy[num]);
|
||||
|
||||
hRes = IDirectInputDevice_GetDeviceState(dijoy[num], sizeof(DIJOYSTATE), &js);
|
||||
if (hRes != DI_OK)
|
||||
{
|
||||
if (hRes == DIERR_INPUTLOST)
|
||||
joyreacquire(num);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* process trigger */
|
||||
joystat.trig = (js.rgbButtons[ 0 ] & 0x80) ? 1 : 0;
|
||||
|
||||
/* process programmable buttons */
|
||||
for (i = 0; i < MAX_PROG_BUTTONS; i++) {
|
||||
joystat.jsbutton[num][i][STATE] = (js.rgbButtons[ i + 1 ] & 0x80) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* process primary joystick. X and Y joystick axis*/
|
||||
if (js.lX == 0)
|
||||
{
|
||||
if (js.lY == 0) joystat.stick = INPUT_STICK_CENTRE;
|
||||
else if (js.lY < 0) joystat.stick = INPUT_STICK_FORWARD;
|
||||
else joystat.stick = INPUT_STICK_BACK;
|
||||
}
|
||||
else if (js.lX < 0)
|
||||
{
|
||||
if (js.lY == 0) joystat.stick = INPUT_STICK_LEFT;
|
||||
else if (js.lY < 0) joystat.stick = INPUT_STICK_UL;
|
||||
else joystat.stick = INPUT_STICK_LL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (js.lY == 0) joystat.stick = INPUT_STICK_RIGHT;
|
||||
else if (js.lY < 0) joystat.stick = INPUT_STICK_UR;
|
||||
else joystat.stick = INPUT_STICK_LR;
|
||||
}
|
||||
|
||||
/* process second joystick on the same gamepad (for dual stick
|
||||
games like Robotron). Second stick must use Z-axis (throttle)
|
||||
and Z-axis rotation (rudder) for it's X and Y motions. */
|
||||
if (alternateJoystickMode == JOY_DUAL_MODE)
|
||||
{
|
||||
if (js.lZ == 0)
|
||||
{
|
||||
if (js.lRz == 0) joystat.stick_1 = INPUT_STICK_CENTRE;
|
||||
else if (js.lRz < 0) joystat.stick_1 = INPUT_STICK_FORWARD;
|
||||
else joystat.stick_1 = INPUT_STICK_BACK;
|
||||
}
|
||||
else if (js.lZ < 0)
|
||||
{
|
||||
if (js.lRz == 0) joystat.stick_1 = INPUT_STICK_LEFT;
|
||||
else if (js.lRz < 0) joystat.stick_1 = INPUT_STICK_UL;
|
||||
else joystat.stick_1 = INPUT_STICK_LL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (js.lRz == 0) joystat.stick_1 = INPUT_STICK_RIGHT;
|
||||
else if (js.lRz < 0) joystat.stick_1 = INPUT_STICK_UR;
|
||||
else joystat.stick_1 = INPUT_STICK_LR;
|
||||
}
|
||||
}
|
||||
/* end dual stick processing */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK joycallback(LPCDIDEVICEINSTANCE pdevinst, LPVOID pv)
|
||||
{
|
||||
DIPROPRANGE dipr;
|
||||
HRESULT hRes;
|
||||
LPDIRECTINPUTDEVICE pdev;
|
||||
LPDIRECTINPUT lpdi = pv;
|
||||
static int i = 0;
|
||||
|
||||
if (i > 1) return DIENUM_STOP;
|
||||
|
||||
if (IDirectInput_CreateDevice(lpdi, &pdevinst->guidInstance, &pdev, NULL) != DI_OK)
|
||||
{
|
||||
return DIENUM_STOP;
|
||||
}
|
||||
|
||||
if (IDirectInputDevice_SetDataFormat(pdev, &c_dfDIJoystick) != DI_OK)
|
||||
{
|
||||
IDirectInputDevice_Release(pdev);
|
||||
return DIENUM_STOP;
|
||||
}
|
||||
if (IDirectInputDevice_SetCooperativeLevel(pdev, hWndMain,
|
||||
DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK)
|
||||
{
|
||||
IDirectInputDevice_Release(pdev);
|
||||
return DIENUM_STOP;
|
||||
}
|
||||
|
||||
dipr.diph.dwSize = sizeof(dipr);
|
||||
dipr.diph.dwHeaderSize = sizeof(dipr.diph);
|
||||
dipr.diph.dwObj = DIJOFS_X;
|
||||
dipr.diph.dwHow = DIPH_BYOFFSET;
|
||||
dipr.lMin = -1000;
|
||||
dipr.lMax = 1000;
|
||||
|
||||
if (IDirectInputDevice_SetProperty(pdev, DIPROP_RANGE, &dipr.diph) != DI_OK)
|
||||
{
|
||||
IDirectInputDevice_Release(pdev);
|
||||
return DIENUM_STOP;
|
||||
}
|
||||
|
||||
dipr.diph.dwObj = DIJOFS_Y;
|
||||
|
||||
if (IDirectInputDevice_SetProperty(pdev, DIPROP_RANGE, &dipr.diph) != DI_OK)
|
||||
{
|
||||
IDirectInputDevice_Release(pdev);
|
||||
return DIENUM_STOP;
|
||||
}
|
||||
|
||||
if (SetDIDwordProperty(pdev, DIPROP_DEADZONE, DIJOFS_X, DIPH_BYOFFSET, 5000) != DI_OK)
|
||||
{
|
||||
IDirectInputDevice_Release(pdev);
|
||||
return DIENUM_STOP;
|
||||
}
|
||||
if (SetDIDwordProperty(pdev, DIPROP_DEADZONE, DIJOFS_Y, DIPH_BYOFFSET, 5000) != DI_OK)
|
||||
{
|
||||
IDirectInputDevice_Release(pdev);
|
||||
return DIENUM_STOP;
|
||||
}
|
||||
|
||||
/* Initialize the Z and Z-Rotation axis for dual stick mode */
|
||||
/* No reason to stop if these fail, even if GetCapabilities says they should not */
|
||||
|
||||
dipr.diph.dwObj = DIJOFS_Z;
|
||||
IDirectInputDevice_SetProperty(pdev, DIPROP_RANGE, &dipr.diph);
|
||||
dipr.diph.dwObj = DIJOFS_RZ;
|
||||
IDirectInputDevice_SetProperty(pdev, DIPROP_RANGE, &dipr.diph);
|
||||
SetDIDwordProperty(pdev, DIPROP_DEADZONE, DIJOFS_Z, DIPH_BYOFFSET, 5000);
|
||||
SetDIDwordProperty(pdev, DIPROP_DEADZONE, DIJOFS_RZ, DIPH_BYOFFSET, 5000);
|
||||
|
||||
/* End Z and Z-Rotation axis initialization */
|
||||
|
||||
hRes = IDirectInputDevice_QueryInterface(pdev, &IID_IDirectInputDevice2,
|
||||
(LPVOID*) &dijoy[i]);
|
||||
IDirectInputDevice_Release(pdev);
|
||||
if (hRes < 0)
|
||||
return DIENUM_STOP;
|
||||
joyreacquire(i);
|
||||
Log_print("joystick %d found!", i);
|
||||
i ++;
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
int initjoystick(void)
|
||||
{
|
||||
LPDIRECTINPUT pdi;
|
||||
HRESULT hRes;
|
||||
|
||||
if (DirectInputCreate(myInstance, DIRECTINPUT_VERSION, &pdi, NULL) != DI_OK)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
hRes = IDirectInput_EnumDevices(pdi, DIDEVTYPE_JOYSTICK, joycallback, pdi, DIEDFL_ATTACHEDONLY);
|
||||
IDirectInput_Release(pdi);
|
||||
if(!dijoy[0]/*hRes != DI_OK*/)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uninitjoystick(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_STICKS; i ++)
|
||||
{
|
||||
if (dijoy[i])
|
||||
{
|
||||
IDirectInputDevice_Unacquire(dijoy[i]);
|
||||
IDirectInputDevice_Release(dijoy[i]);
|
||||
dijoy[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#ifndef JOYSTICK_H_
|
||||
#define JOYSTICK_H_
|
||||
|
||||
#define NUM_STICKS 2
|
||||
#define MAX_PROG_BUTTONS 9
|
||||
#define STATE 0
|
||||
#define ASSIGN 1
|
||||
#define STICK1 0
|
||||
#define STICK2 1
|
||||
|
||||
/* keyboard joystick modes */
|
||||
typedef enum KEYJOYMODE_ {
|
||||
KEYPAD_MODE,
|
||||
KEYPAD_PLUS_MODE,
|
||||
ARROW_MODE
|
||||
} KEYJOYMODE;
|
||||
|
||||
/* alternate joystick modes */
|
||||
typedef enum ALTJOYMODE_ {
|
||||
JOY_NORMAL_MODE,
|
||||
JOY_DUAL_MODE,
|
||||
JOY_SHARED_MODE
|
||||
} ALTJOYMODE;
|
||||
|
||||
int procjoy(int num);
|
||||
int joyreacquire(int num);
|
||||
int initjoystick(void);
|
||||
void uninitjoystick(void);
|
||||
void clearjoy(void);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int trig;
|
||||
|
||||
/* holds stick id, button state, and button assignment */
|
||||
int jsbutton[NUM_STICKS][MAX_PROG_BUTTONS][2];
|
||||
|
||||
int stick;
|
||||
int stick_1;
|
||||
} tjoystat;
|
||||
extern tjoystat joystat;
|
||||
|
||||
extern KEYJOYMODE keyboardJoystickMode;
|
||||
extern ALTJOYMODE alternateJoystickMode;
|
||||
|
||||
#endif /* JOYSTICK_H_ */
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* keyboard.c - Win32 port specific code
|
||||
*
|
||||
* Copyright (C) 2000 Krzysztof Nikiel
|
||||
* Copyright (C) 2000-2005 Atari800 development team (see DOC/CREDITS)
|
||||
*
|
||||
* This file is part of the Atari800 emulator project which emulates
|
||||
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
|
||||
*
|
||||
* Atari800 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.
|
||||
*
|
||||
* Atari800 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 Atari800; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#define DIRECTINPUT_VERSION 0x0500
|
||||
#include <windows.h>
|
||||
#include <dinput.h>
|
||||
|
||||
#include "atari.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "keyboard.h"
|
||||
|
||||
#define KEYBUFSIZE 0x40
|
||||
|
||||
static LPDIRECTINPUTDEVICE2 dikb0 = NULL;
|
||||
int pause_hit;
|
||||
|
||||
int kbcode;
|
||||
UBYTE kbhits[KBCODES];
|
||||
|
||||
int kbreacquire(void)
|
||||
{
|
||||
if (!dikb0)
|
||||
return 1;
|
||||
if (IDirectInputDevice_Acquire(dikb0) >= 0)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
int prockb(void)
|
||||
{
|
||||
DIDEVICEOBJECTDATA que[KEYBUFSIZE];
|
||||
DWORD dwEvents;
|
||||
DWORD i;
|
||||
HRESULT hRes;
|
||||
|
||||
dwEvents = KEYBUFSIZE;
|
||||
hRes = IDirectInputDevice_GetDeviceData(dikb0,
|
||||
sizeof(DIDEVICEOBJECTDATA),
|
||||
que, &dwEvents, 0);
|
||||
if (hRes != DI_OK)
|
||||
{
|
||||
if ((hRes == DIERR_INPUTLOST))
|
||||
kbreacquire();
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < dwEvents; i++)
|
||||
{
|
||||
#if 0
|
||||
printf("%02x(%02x)\n", que[i].dwOfs, que[i].dwData);
|
||||
#endif
|
||||
if (que[i].dwOfs >= KBCODES)
|
||||
continue;
|
||||
if (que[i].dwOfs == DIK_PAUSE)
|
||||
{
|
||||
if (que[i].dwData)
|
||||
pause_hit = 1;
|
||||
continue;
|
||||
}
|
||||
if (que[i].dwData)
|
||||
kbhits[kbcode = que[i].dwOfs] = 1;
|
||||
else
|
||||
{
|
||||
kbhits[kbcode = que[i].dwOfs] = 0;
|
||||
kbcode |= 0x100;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uninitinput(void)
|
||||
{
|
||||
if (dikb0)
|
||||
{
|
||||
IDirectInputDevice_Unacquire(dikb0);
|
||||
IDirectInputDevice_Release(dikb0);
|
||||
dikb0 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT
|
||||
SetDIDwordProperty(LPDIRECTINPUTDEVICE pdev, REFGUID guidProperty,
|
||||
DWORD dwObject, DWORD dwHow, DWORD dwValue)
|
||||
{
|
||||
DIPROPDWORD dipdw;
|
||||
|
||||
dipdw.diph.dwSize = sizeof(dipdw);
|
||||
dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
|
||||
dipdw.diph.dwObj = dwObject;
|
||||
dipdw.diph.dwHow = dwHow;
|
||||
dipdw.dwData = dwValue;
|
||||
|
||||
return pdev->lpVtbl->SetProperty(pdev, guidProperty, &dipdw.diph);
|
||||
}
|
||||
|
||||
static int initkb(LPDIRECTINPUT pdi)
|
||||
{
|
||||
LPDIRECTINPUTDEVICE pdev;
|
||||
HRESULT hRes;
|
||||
|
||||
if (IDirectInput_CreateDevice(pdi,
|
||||
&GUID_SysKeyboard, &pdev, NULL) != DI_OK)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (IDirectInputDevice_SetDataFormat(pdev, &c_dfDIKeyboard) != DI_OK)
|
||||
{
|
||||
IDirectInputDevice_Release(pdev);
|
||||
return 1;
|
||||
}
|
||||
if (IDirectInputDevice_SetCooperativeLevel(pdev, hWndMain,
|
||||
DISCL_NONEXCLUSIVE |
|
||||
DISCL_FOREGROUND) != DI_OK)
|
||||
{
|
||||
IDirectInputDevice_Release(pdev);
|
||||
return 1;
|
||||
}
|
||||
if (SetDIDwordProperty(pdev, DIPROP_BUFFERSIZE, 0, DIPH_DEVICE,
|
||||
KEYBUFSIZE) != DI_OK)
|
||||
{
|
||||
IDirectInputDevice_Release(pdev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
hRes = pdev->lpVtbl->QueryInterface(pdev, &IID_IDirectInputDevice2,
|
||||
(LPVOID *) (void*) & dikb0);
|
||||
if (hRes < 0)
|
||||
return 1;
|
||||
IDirectInputDevice_Release(pdev);
|
||||
kbreacquire();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int initinput(void)
|
||||
{
|
||||
int i;
|
||||
LPDIRECTINPUT pdi;
|
||||
|
||||
if (DirectInputCreate(myInstance, DIRECTINPUT_VERSION, &pdi, NULL) != DI_OK)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
i = initkb(pdi);
|
||||
IDirectInput_Release(pdi);
|
||||
if (i)
|
||||
return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void clearkb(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < KBCODES; i++)
|
||||
kbhits[i] = 0;
|
||||
pause_hit = 0;
|
||||
kbcode = 0;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef KEYBOARD_H_
|
||||
#define KEYBOARD_H_
|
||||
|
||||
#define SHOWKBCODES 0
|
||||
#define KBCODES 0x100
|
||||
|
||||
#include <dinput.h>
|
||||
|
||||
extern int pause_hit;
|
||||
extern int kbcode;
|
||||
extern UBYTE kbhits[KBCODES];
|
||||
int prockb(void);
|
||||
int kbreacquire(void);
|
||||
int initinput(void);
|
||||
void uninitinput(void);
|
||||
void clearkb(void);
|
||||
HRESULT
|
||||
SetDIDwordProperty(LPDIRECTINPUTDEVICE pdev, REFGUID guidProperty,
|
||||
DWORD dwObject, DWORD dwHow, DWORD dwValue);
|
||||
|
||||
#endif /* KEYBOARD_H_ */
|
||||
@@ -0,0 +1,536 @@
|
||||
/*
|
||||
* main.cpp - Win32 port specific code
|
||||
*
|
||||
* Copyright (C) 2000 Krzysztof Nikiel
|
||||
* Copyright (C) 2000-2014 Atari800 development team (see DOC/CREDITS)
|
||||
*
|
||||
* This file is part of the Atari800 emulator project which emulates
|
||||
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
|
||||
*
|
||||
* Atari800 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.
|
||||
*
|
||||
* Atari800 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 Atari800; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define MOUSE_CENTER_X 100
|
||||
#define MOUSE_CENTER_Y 100
|
||||
#define WM_MOUSEHWHEEL 0x020E
|
||||
|
||||
#include "config.h"
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <process.h>
|
||||
|
||||
extern "C" {
|
||||
#include "atari.h"
|
||||
#include "input.h"
|
||||
#include "platform.h"
|
||||
#include "screen.h"
|
||||
#include "sound.h"
|
||||
#include "ui.h"
|
||||
#include "ui_basic.h"
|
||||
#include "log.h"
|
||||
#include "config.h"
|
||||
#include "main_menu.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "screen_win32.h"
|
||||
#include "atari_win32.h"
|
||||
#include "keyboard.h"
|
||||
#include "joystick.h"
|
||||
}
|
||||
|
||||
char *myname = "Atari800";
|
||||
HWND hWndMain = NULL;
|
||||
HINSTANCE myInstance = NULL;
|
||||
FILE *stdout_stream;
|
||||
|
||||
// menus
|
||||
HMENU hMainMenu = NULL;
|
||||
HMENU hFileMenu = NULL;
|
||||
HMENU hManageMenu = NULL;
|
||||
HMENU hSystemMenu = NULL;
|
||||
HMENU hDisplayMenu = NULL;
|
||||
HMENU hHelpMenu = NULL;
|
||||
|
||||
static int bActive = 0; /* activity indicator */
|
||||
static bool quit_ok = TRUE;
|
||||
static keycommand_t keycommand = {AKEY_NONE, -1};
|
||||
bool help_only = FALSE;
|
||||
BOOL useconsole = FALSE;
|
||||
|
||||
#if 1
|
||||
void exit(int code)
|
||||
{
|
||||
if (useconsole)
|
||||
{
|
||||
FreeConsole();
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(stdout_stream);
|
||||
}
|
||||
|
||||
MSG msg;
|
||||
while (GetMessage(&msg, NULL, 0, 0)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
ExitProcess(code);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Used where necessary to keep UI
|
||||
// responsive to system events
|
||||
void DoEvents()
|
||||
{
|
||||
MSG msg;
|
||||
msg.message = WM_NULL;
|
||||
|
||||
PLATFORM_DisplayScreen();
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
{
|
||||
PostQuitMessage(10);
|
||||
Atari800_Exit(FALSE);
|
||||
exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Used by PLATFORM_Keyboard to retrieve a menu command
|
||||
void GetCommandKey(keycommand_t *kc)
|
||||
{
|
||||
if (keycommand.keystroke != AKEY_NONE) {
|
||||
kc->keystroke = keycommand.keystroke;
|
||||
kc->function = keycommand.function;
|
||||
keycommand.keystroke = AKEY_NONE;
|
||||
keycommand.function = -1;
|
||||
}
|
||||
else {
|
||||
kc->keystroke = AKEY_NONE;
|
||||
kc->function = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void SuppressNextQuitMessage()
|
||||
{
|
||||
quit_ok = FALSE;
|
||||
}
|
||||
|
||||
void OnSize(HWND hWnd, UINT state, int cx, int cy)
|
||||
{
|
||||
refreshframe(); // handled in screen_win32.c
|
||||
}
|
||||
|
||||
void OnActivateApp(HWND hWnd, BOOL fActivate, DWORD dwThreadId)
|
||||
{
|
||||
bActive = fActivate;
|
||||
if (bActive) {
|
||||
kbreacquire();
|
||||
#ifdef SOUND
|
||||
Sound_Continue();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
HWND OnSysChar(HWND hWnd, TCHAR ch, int cRepeat)
|
||||
{
|
||||
/* empty function suppresses beep on alt-key shortcuts */
|
||||
return(0);
|
||||
}
|
||||
|
||||
void OnClose(HWND hWnd)
|
||||
{
|
||||
Atari800_Exit(FALSE);
|
||||
}
|
||||
|
||||
void OnDestroy(HWND hWnd)
|
||||
{
|
||||
if (quit_ok)
|
||||
PostQuitMessage(10);
|
||||
quit_ok = TRUE;
|
||||
}
|
||||
|
||||
void OnCommand(HWND hWnd, int id, HWND hwndCtl, UINT codeNotify)
|
||||
{
|
||||
switch (id) {
|
||||
// File Menu
|
||||
case ID_RUN_ATARI_PROGRAM:
|
||||
if (UI_current_function != UI_MENU_RUN) {
|
||||
keycommand.keystroke = AKEY_UI;
|
||||
keycommand.function = UI_MENU_RUN;
|
||||
}
|
||||
break;
|
||||
case ID_RESET:
|
||||
keycommand.keystroke = AKEY_UI;
|
||||
keycommand.function = UI_MENU_RESETW;
|
||||
break;
|
||||
case ID_REBOOT:
|
||||
keycommand.keystroke = AKEY_UI;
|
||||
keycommand.function = UI_MENU_RESETC;
|
||||
break;
|
||||
case ID_CONFIGURATION:
|
||||
keycommand.keystroke = AKEY_UI;
|
||||
break;
|
||||
case ID_SAVE_CONFIG:
|
||||
if (UI_is_active) {
|
||||
keycommand.keystroke = AKEY32_MENU_SAVE_CONFIG;
|
||||
}
|
||||
else {
|
||||
keycommand.keystroke = AKEY_UI;
|
||||
keycommand.function = UI_MENU_SAVE_CONFIG;
|
||||
}
|
||||
break;
|
||||
case ID_BACK:
|
||||
keycommand.keystroke = AKEY_ESCAPE;
|
||||
keycommand.function = -1;
|
||||
break;
|
||||
case ID_EXIT:
|
||||
keycommand.keystroke = AKEY_EXIT;
|
||||
keycommand.function = -1;
|
||||
break;
|
||||
|
||||
// Manage Menu
|
||||
case ID_DISK_MANAGEMENT:
|
||||
keycommand.keystroke = AKEY_UI;
|
||||
keycommand.function = UI_MENU_DISK;
|
||||
break;
|
||||
case ID_CART_MANAGEMENT:
|
||||
keycommand.keystroke = AKEY_UI;
|
||||
keycommand.function = UI_MENU_CARTRIDGE;
|
||||
break;
|
||||
case ID_TAPE_MANAGEMENT:
|
||||
keycommand.keystroke = AKEY_UI;
|
||||
keycommand.function = UI_MENU_CASSETTE;
|
||||
break;
|
||||
case ID_EMULATOR_BIOS:
|
||||
keycommand.keystroke = AKEY_UI;
|
||||
keycommand.function = UI_MENU_SETTINGS;
|
||||
break;
|
||||
|
||||
// System Menu
|
||||
case ID_NTSC:
|
||||
//CheckMenuItem(hSystemMenu, ID_NTSC, MF_CHECKED);
|
||||
//CheckMenuItem(hSystemMenu, ID_PAL, MF_UNCHECKED);
|
||||
Atari800_SetTVMode(Atari800_TV_NTSC);
|
||||
Atari800_InitialiseMachine();
|
||||
break;
|
||||
case ID_PAL:
|
||||
//CheckMenuItem(hSystemMenu, ID_PAL, MF_CHECKED);
|
||||
//CheckMenuItem(hSystemMenu, ID_NTSC, MF_UNCHECKED);
|
||||
Atari800_SetTVMode(Atari800_TV_PAL);
|
||||
Atari800_InitialiseMachine();
|
||||
break;
|
||||
case ID_SELECT_MACHINE:
|
||||
keycommand.keystroke = AKEY_UI;
|
||||
keycommand.function = UI_MENU_SYSTEM;
|
||||
break;
|
||||
#ifdef SOUND
|
||||
case ID_SOUND:
|
||||
keycommand.keystroke = AKEY_UI;
|
||||
keycommand.function = UI_MENU_SOUND;
|
||||
break;
|
||||
#endif
|
||||
case ID_CONTROLLERS:
|
||||
keycommand.keystroke = AKEY_UI;
|
||||
keycommand.function = UI_MENU_CONTROLLER;
|
||||
break;
|
||||
|
||||
// Display Menu
|
||||
case ID_FULLSCREEN:
|
||||
togglewindowstate();
|
||||
break;
|
||||
case ID_WINDOW_SIZE_UP:
|
||||
changewindowsize(STEPUP, 50);
|
||||
break;
|
||||
case ID_WINDOW_SIZE_DOWN:
|
||||
changewindowsize(STEPDOWN, 50);
|
||||
break;
|
||||
case ID_ATARI_DISPLAY:
|
||||
keycommand.keystroke = AKEY_UI;
|
||||
keycommand.function = UI_MENU_DISPLAY;
|
||||
break;
|
||||
case ID_WINDOWS_DISPLAY:
|
||||
keycommand.keystroke = AKEY_UI;
|
||||
keycommand.function = UI_MENU_WINDOWS;
|
||||
break;
|
||||
|
||||
// Help Menu
|
||||
case ID_ABOUT_ATARI800:
|
||||
keycommand.keystroke = AKEY_UI;
|
||||
keycommand.function = UI_MENU_ABOUT;
|
||||
break;
|
||||
case ID_FUNCTION_KEY_HELP:
|
||||
keycommand.keystroke = AKEY_UI;
|
||||
keycommand.function = UI_MENU_FUNCT_KEY_HELP;
|
||||
break;
|
||||
case ID_HOT_KEY_HELP:
|
||||
keycommand.keystroke = AKEY_UI;
|
||||
keycommand.function = UI_MENU_HOT_KEY_HELP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// set the PAL/NTSC mode - called in atari.c
|
||||
void SetTVModeMenuItem(int mode)
|
||||
{
|
||||
if (mode == Atari800_TV_NTSC) {
|
||||
CheckMenuItem(hSystemMenu, ID_NTSC, MF_CHECKED);
|
||||
CheckMenuItem(hSystemMenu, ID_PAL, MF_UNCHECKED);
|
||||
}
|
||||
else {
|
||||
CheckMenuItem(hSystemMenu, ID_PAL, MF_CHECKED);
|
||||
CheckMenuItem(hSystemMenu, ID_NTSC, MF_UNCHECKED);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" LRESULT CALLBACK Atari_WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
int nx, ny;
|
||||
|
||||
switch (message) {
|
||||
|
||||
HANDLE_MSG(hWnd, WM_SIZE, OnSize);
|
||||
HANDLE_MSG(hWnd, WM_ACTIVATEAPP, OnActivateApp);
|
||||
HANDLE_MSG(hWnd, WM_SYSCHAR, OnSysChar);
|
||||
HANDLE_MSG(hWnd, WM_CLOSE, OnClose);
|
||||
HANDLE_MSG(hWnd, WM_DESTROY, OnDestroy);
|
||||
HANDLE_MSG(hWnd, WM_COMMAND, OnCommand);
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_MBUTTONUP:
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_RBUTTONUP:
|
||||
INPUT_mouse_buttons = ((wParam & MK_LBUTTON) ? 1 : 0)
|
||||
| ((wParam & MK_RBUTTON) ? 2 : 0)
|
||||
| ((wParam & MK_MBUTTON) ? 4 : 0);
|
||||
|
||||
// handle mouse clicks in the config UI
|
||||
if (UI_is_active) {
|
||||
switch (INPUT_mouse_buttons) {
|
||||
case 1:
|
||||
getnativecoords(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), &nx, &ny);
|
||||
SetMouseIndex(nx, ny);
|
||||
keycommand.keystroke = AKEY32_UI_MOUSE_CLICK;
|
||||
break;
|
||||
case 2:
|
||||
keycommand.keystroke = AKEY_ESCAPE;
|
||||
keycommand.function = -1;
|
||||
break;
|
||||
case 4:
|
||||
keycommand.keystroke = AKEY_RETURN;
|
||||
keycommand.function = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_LBUTTONDBLCLK:
|
||||
if (UI_is_active && UI_mouse_click.y != -1) {
|
||||
keycommand.keystroke = AKEY_RETURN;
|
||||
keycommand.function = -1;
|
||||
}
|
||||
break;
|
||||
case WM_MOUSEWHEEL:
|
||||
if (UI_is_active) {
|
||||
if (GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA > 0)
|
||||
keycommand.keystroke = AKEY_UP;
|
||||
else if (GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA < 0)
|
||||
keycommand.keystroke = AKEY_DOWN;
|
||||
}
|
||||
break;
|
||||
case WM_MOUSEHWHEEL:
|
||||
if (UI_is_active) {
|
||||
if (GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA > 0)
|
||||
keycommand.keystroke = AKEY_RIGHT;
|
||||
else if (GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA < 0)
|
||||
keycommand.keystroke = AKEY_LEFT;
|
||||
}
|
||||
break;
|
||||
case WM_SETCURSOR:
|
||||
if (GetRenderMode() == DIRECTDRAW) {
|
||||
SetCursor(NULL);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case WM_ENTERMENULOOP:
|
||||
Sound_Pause();
|
||||
break;
|
||||
case WM_EXITMENULOOP:
|
||||
if (!UI_is_active)
|
||||
Sound_Continue();
|
||||
break;
|
||||
}
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
int WINAPI WinMain(HINSTANCE hinstance,
|
||||
HINSTANCE hprevinstance,
|
||||
LPSTR lpcmdline,
|
||||
int nshowcmd)
|
||||
{
|
||||
//***********************************************
|
||||
// Convert WinMain() style command line arguments
|
||||
// to main() style arguments (argc, *argv[])
|
||||
// This maintains compatibility with the former
|
||||
// main() entry point's parameters.
|
||||
//***********************************************
|
||||
|
||||
char **argv = NULL;
|
||||
int argc = 1;
|
||||
|
||||
char *app_path = new char[MAX_PATH];
|
||||
strcpy(app_path, GetCommandLine());
|
||||
if (app_path[0] == '\"')
|
||||
{
|
||||
app_path = (app_path+1);
|
||||
char *lastdit = strchr(app_path, '\"');
|
||||
*lastdit = '\x0';
|
||||
}
|
||||
|
||||
if ( *lpcmdline != '\x0' )
|
||||
{
|
||||
char *cmdlinecopy = new char[strlen(lpcmdline)+1];
|
||||
strcpy(cmdlinecopy, lpcmdline);
|
||||
|
||||
char *c = cmdlinecopy;
|
||||
while(c)
|
||||
{
|
||||
++argc;
|
||||
c = strchr((c+1),' ');
|
||||
}
|
||||
|
||||
argv = new char*[argc];
|
||||
argv[0] = app_path;
|
||||
|
||||
if(argc > 1)
|
||||
{
|
||||
argv[1] = cmdlinecopy;
|
||||
char *c = strchr(cmdlinecopy, ' ');
|
||||
int n = 2;
|
||||
while(c)
|
||||
{
|
||||
*c = '\x0';
|
||||
argv [n] = (c+1);
|
||||
++n;
|
||||
c = strchr((c+1), ' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
argv = new char *[1];
|
||||
argv[0] = app_path;
|
||||
}
|
||||
|
||||
//*********************************************
|
||||
// Process commandline and activate console
|
||||
// if -console switch is set.
|
||||
//*********************************************
|
||||
int i,j;
|
||||
|
||||
for (i = j = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-console") == 0) {
|
||||
useconsole = TRUE;
|
||||
}
|
||||
else if (strcmp(argv[i], "-help") == 0) {
|
||||
|
||||
help_only = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (useconsole || help_only) {
|
||||
AllocConsole(); // start a console window
|
||||
freopen("CONIN$","rb",stdin); // reopen stdin handle as console window input
|
||||
freopen("CONOUT$","wb",stdout); // reopen stout handle as console window output
|
||||
freopen("CONOUT$","wb",stderr); // reopen stderr handle as console window output
|
||||
}
|
||||
else // not using console
|
||||
{
|
||||
// console is supressed, so stream console output to a file
|
||||
stdout_stream = freopen("atari800.txt", "w", stdout);
|
||||
|
||||
if (stdout_stream == NULL)
|
||||
fprintf(stdout, "Error opening atari800.txt\n");
|
||||
}
|
||||
|
||||
//*********************************************
|
||||
// Begin main processing
|
||||
//*********************************************
|
||||
|
||||
MSG msg;
|
||||
POINT mouse;
|
||||
|
||||
Win32_Init();
|
||||
myInstance = GetModuleHandle(NULL);
|
||||
|
||||
if (help_only) {
|
||||
/* initialize the Atari800 for help only */
|
||||
Atari800_Initialise(&argc, argv);
|
||||
Log_print("\t-console Show the Atari800 console window");
|
||||
Log_print("\n");
|
||||
system("PAUSE");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* initialise Atari800 core for use */
|
||||
if (!Atari800_Initialise(&argc, argv))
|
||||
return 3;
|
||||
|
||||
msg.message = WM_NULL;
|
||||
|
||||
/* main loop */
|
||||
for (;;) {
|
||||
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
if (msg.message == WM_QUIT)
|
||||
break;
|
||||
|
||||
if (!bActive)
|
||||
continue;
|
||||
|
||||
INPUT_key_code = PLATFORM_Keyboard();
|
||||
|
||||
// support mouse device modes
|
||||
// only supported in fullscreen modes for now
|
||||
if (GetScreenMode() == FULLSCREEN)
|
||||
{
|
||||
GetCursorPos(&mouse);
|
||||
INPUT_mouse_delta_x = mouse.x - MOUSE_CENTER_X;
|
||||
INPUT_mouse_delta_y = mouse.y - MOUSE_CENTER_Y;
|
||||
if (INPUT_mouse_delta_x | INPUT_mouse_delta_y)
|
||||
SetCursorPos(MOUSE_CENTER_X, MOUSE_CENTER_Y);
|
||||
}
|
||||
|
||||
Atari800_Frame();
|
||||
if (Atari800_display_screen)
|
||||
PLATFORM_DisplayScreen();
|
||||
}
|
||||
|
||||
return msg.wParam;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef MAIN_H_
|
||||
#define MAIN_H_
|
||||
|
||||
extern char *myname;
|
||||
extern HWND hWndMain;
|
||||
extern HINSTANCE myInstance;
|
||||
extern BOOL useconsole;
|
||||
extern int internalkey;
|
||||
|
||||
extern HMENU hMainMenu;
|
||||
extern HMENU hFileMenu;
|
||||
extern HMENU hManageMenu;
|
||||
extern HMENU hSystemMenu;
|
||||
extern HMENU hDisplayMenu;
|
||||
extern HMENU hHelpMenu;
|
||||
|
||||
LRESULT CALLBACK Atari_WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
void SuppressNextQuitMessage(void);
|
||||
void DoEvents(void);
|
||||
void SetTVModeMenuItem(int mode);
|
||||
|
||||
typedef struct {
|
||||
int keystroke;
|
||||
int function;
|
||||
} keycommand_t;
|
||||
|
||||
void GetCommandKey(keycommand_t *keycommand);
|
||||
|
||||
#endif /* MAIN_H_ */
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef _MAIN_MENU_H_
|
||||
#define _MAIN_MENU_H_
|
||||
|
||||
#define ID_FILE 101
|
||||
#define ID_RUN_ATARI_PROGRAM 102
|
||||
#define ID_RESET 103
|
||||
#define ID_REBOOT 104
|
||||
#define ID_CONFIGURATION 105
|
||||
#define ID_SAVE_CONFIG 106
|
||||
#define ID_BACK 107
|
||||
#define ID_EXIT 108
|
||||
#define ID_MANAGE 201
|
||||
#define ID_DISK_MANAGEMENT 202
|
||||
#define ID_CART_MANAGEMENT 203
|
||||
#define ID_TAPE_MANAGEMENT 204
|
||||
#define ID_EMULATOR_BIOS 205
|
||||
#define ID_SYSTEM 301
|
||||
#define ID_NTSC 302
|
||||
#define ID_PAL 303
|
||||
#define ID_SELECT_MACHINE 304
|
||||
#define ID_SOUND 305
|
||||
#define ID_CONTROLLERS 306
|
||||
#define ID_DISPLAY 401
|
||||
#define ID_FULLSCREEN 402
|
||||
#define ID_WINDOW_SIZE_UP 403
|
||||
#define ID_WINDOW_SIZE_DOWN 404
|
||||
#define ID_ATARI_DISPLAY 405
|
||||
#define ID_WINDOWS_DISPLAY 406
|
||||
#define ID_HELP 901
|
||||
#define ID_ABOUT_ATARI800 902
|
||||
#define ID_FUNCTION_KEY_HELP 903
|
||||
#define ID_HOT_KEY_HELP 904
|
||||
|
||||
#endif /* _MENU_H_ */
|
||||
@@ -0,0 +1,93 @@
|
||||
# Makefile for Microsoft NMAKE + CL
|
||||
# Invoke with:
|
||||
# nmake /f win32\msc\Makefile
|
||||
# from the "src" directory.
|
||||
# Compile using DirectX 9.0 SDK (Summer 2004)
|
||||
|
||||
CC = cl
|
||||
RC = rc
|
||||
|
||||
DEFS =
|
||||
LIBS = \
|
||||
libpng.lib zlib.lib \
|
||||
ddraw.lib dinput.lib dsound.lib dxguid.lib gdi32.lib gdiplus.lib d3d9.lib d3dx9.lib \
|
||||
user32.lib winmm.lib advapi32.lib
|
||||
TARGET = atari800.exe
|
||||
|
||||
CFLAGS = /nologo /O2 /GS- /W3 /wd4996 /I win32\msc /I .
|
||||
CPPFLAGS = /nologo /O2 /GS- /W3 /wd4996 /I win32\msc /I ./
|
||||
LDFLAGS = /nologo
|
||||
|
||||
OBJS = \
|
||||
afile.obj \
|
||||
antic.obj \
|
||||
artifact.obj \
|
||||
atari.obj \
|
||||
binload.obj \
|
||||
cartridge.obj \
|
||||
cassette.obj \
|
||||
cfg.obj \
|
||||
colours.obj \
|
||||
colours_external.obj \
|
||||
colours_ntsc.obj \
|
||||
colours_pal.obj \
|
||||
compfile.obj \
|
||||
cpu.obj \
|
||||
crc32.obj \
|
||||
cycle_map.obj \
|
||||
devices.obj \
|
||||
emuos.obj \
|
||||
esc.obj \
|
||||
gtia.obj \
|
||||
img_tape.obj \
|
||||
input.obj \
|
||||
log.obj \
|
||||
memory.obj \
|
||||
monitor.obj \
|
||||
mzpokeysnd.obj \
|
||||
pbi.obj \
|
||||
pbi_xld.obj \
|
||||
pia.obj \
|
||||
pokey.obj \
|
||||
pokeysnd.obj \
|
||||
remez.obj \
|
||||
rtime.obj \
|
||||
screen.obj \
|
||||
sio.obj \
|
||||
sndsave.obj \
|
||||
statesav.obj \
|
||||
sysrom.obj \
|
||||
ui.obj \
|
||||
ui_basic.obj \
|
||||
util.obj \
|
||||
votrax.obj \
|
||||
votraxsnd.obj \
|
||||
win32\atari_win32.obj \
|
||||
win32\joystick.obj \
|
||||
win32\keyboard.obj \
|
||||
win32\main.obj \
|
||||
win32\screen_win32.obj \
|
||||
win32\render_gdi.obj \
|
||||
win32\render_gdiplus.obj \
|
||||
win32\render_directdraw.obj \
|
||||
win32\render_direct3d.obj \
|
||||
win32\sound.obj \
|
||||
win32\atari.res
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
$(CC) /Fe$(TARGET) $(LDFLAGS) $(OBJS) $(LIBS)
|
||||
|
||||
# the default .c.obj rule would place the object files in the src directory
|
||||
{win32\}.c{win32\}.obj:
|
||||
$(CC) $(CFLAGS) /c /Fo$@ $**
|
||||
|
||||
{win32\}.cpp{win32\}.obj:
|
||||
$(CC) $(CPPFLAGS) /c /Fo$@ $**
|
||||
|
||||
clean:
|
||||
del *.obj
|
||||
del win32\*.obj
|
||||
del win32\atari.res
|
||||
del $(TARGET)
|
||||
@@ -0,0 +1,551 @@
|
||||
/* config.h for DirectX version of Atari800 compiled with MSVC 6. */
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define if building universal (internal helper macro) */
|
||||
/* #undef AC_APPLE_UNIVERSAL_BUILD */
|
||||
|
||||
/* The Austin Franklin 80 column card. */
|
||||
/* #undef AF80 */
|
||||
|
||||
/* Target: Android */
|
||||
/* #undef ANDROID */
|
||||
|
||||
/* Target: standard I/O. */
|
||||
/* #undef BASIC */
|
||||
|
||||
/* Define to use buffered debug output. */
|
||||
/* #undef BUFFERED_LOG */
|
||||
|
||||
/* Define to allow sound clipping. */
|
||||
/* #undef CLIP_SOUND */
|
||||
|
||||
/* Define to 1 if the `closedir' function returns void instead of `int'. */
|
||||
/* #undef CLOSEDIR_VOID */
|
||||
|
||||
/* Define to allow console sound (keyboard clicks). */
|
||||
#define CONSOLE_SOUND 1
|
||||
|
||||
/* Define to activate crash menu after CIM instruction. */
|
||||
#define CRASH_MENU 1
|
||||
|
||||
/* Define to disable bitmap graphics emulation in CURSES target. */
|
||||
/* #undef CURSES_BASIC */
|
||||
|
||||
/* Alternate config filename due to 8+3 fs limit. */
|
||||
#define DEFAULT_CFG_NAME "atari800.cfg"
|
||||
|
||||
/* Target: Windows with DirectX. */
|
||||
#define DIRECTX 1
|
||||
|
||||
/* Define to use dirty screen partial repaints. */
|
||||
/* #undef DIRTYRECT */
|
||||
|
||||
/* Define to use back slash as directory separator. */
|
||||
#define DIR_SEP_BACKSLASH 1
|
||||
|
||||
/* Target: DOS VGA. */
|
||||
/* #undef DOSVGA */
|
||||
|
||||
/* Define to enable DOS style drives support. */
|
||||
#define DOS_DRIVES 1
|
||||
|
||||
/* Define to enable event recording. */
|
||||
/* #undef EVENT_RECORDING */
|
||||
|
||||
/* Target: Atari Falcon system. */
|
||||
/* #undef FALCON */
|
||||
|
||||
/* Define to use m68k assembler CPU core for Falcon target. */
|
||||
/* #undef FALCON_CPUASM */
|
||||
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
/* #undef HAVE_ARPA_INET_H */
|
||||
|
||||
/* Define to 1 if you have the `atexit' function. */
|
||||
#define HAVE_ATEXIT 1
|
||||
|
||||
/* Define to 1 if you have the `chmod' function. */
|
||||
/* #undef HAVE_CHMOD */ /* it is in <io.h> */
|
||||
|
||||
/* Define to 1 if you have the `clock' function. */
|
||||
#define HAVE_CLOCK 1
|
||||
|
||||
/* Define to 1 if you have the <direct.h> header file. */
|
||||
#define HAVE_DIRECT_H 1
|
||||
|
||||
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
|
||||
*/
|
||||
/* #undef HAVE_DIRENT_H */
|
||||
|
||||
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
|
||||
/* #undef HAVE_DOPRNT */
|
||||
|
||||
/* Define to 1 if you have the <errno.h> header file. */
|
||||
#define HAVE_ERRNO_H 1
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#define HAVE_FCNTL_H 1
|
||||
|
||||
/* Define to 1 if you have the `fdopen' function. */
|
||||
#define HAVE_FDOPEN 1
|
||||
|
||||
/* Define to 1 if you have the `fflush' function. */
|
||||
#define HAVE_FFLUSH 1
|
||||
|
||||
/* Define to 1 if you have the <file.h> header file. */
|
||||
/* #undef HAVE_FILE_H */
|
||||
|
||||
/* Define to 1 if you have the `floor' function. */
|
||||
#define HAVE_FLOOR 1
|
||||
|
||||
/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
|
||||
/* #undef HAVE_FSEEKO */
|
||||
|
||||
/* Define to 1 if you have the `fstat' function. */
|
||||
#define HAVE_FSTAT 1
|
||||
|
||||
/* Define to 1 if you have the `getcwd' function. */
|
||||
#define HAVE_GETCWD 1
|
||||
|
||||
/* Define to 1 if you have the `gethostbyaddr' function. */
|
||||
/* #undef HAVE_GETHOSTBYADDR */
|
||||
|
||||
/* Define to 1 if you have the `gethostbyname' function. */
|
||||
/* #undef HAVE_GETHOSTBYNAME */
|
||||
|
||||
/* Define to 1 if you have the `gettimeofday' function. */
|
||||
#define HAVE_GETTIMEOFDAY 1
|
||||
|
||||
/* Define to 1 if you have the `inet_ntoa' function. */
|
||||
/* #undef HAVE_INET_NTOA */
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
/* #undef HAVE_INTTYPES_H */
|
||||
|
||||
/* Define to 1 if you have the `gem' library (-lgem). */
|
||||
/* #undef HAVE_LIBGEM */
|
||||
|
||||
/* Define to 1 if you have the `png' library (-lpng). */
|
||||
#define HAVE_LIBPNG 1
|
||||
|
||||
/* Define to 1 if you have the `z' library (-lz). */
|
||||
#define HAVE_LIBZ 1
|
||||
|
||||
/* Define to 1 if you have the `localtime' function. */
|
||||
#define HAVE_LOCALTIME 1
|
||||
|
||||
/* Define to 1 if you have the `memmove' function. */
|
||||
#define HAVE_MEMMOVE 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the `memset' function. */
|
||||
#define HAVE_MEMSET 1
|
||||
|
||||
/* Define to 1 if you have the `mkdir' function. */
|
||||
#define HAVE_MKDIR 1
|
||||
|
||||
/* Define to 1 if you have the `mkstemp' function. */
|
||||
/* #undef HAVE_MKSTEMP */
|
||||
|
||||
/* Define to 1 if you have the `mktemp' function. */
|
||||
#define HAVE_MKTEMP 1
|
||||
|
||||
/* Define to 1 if you have the `modf' function. */
|
||||
#define HAVE_MODF 1
|
||||
|
||||
/* Define to 1 if you have the `nanosleep' function. */
|
||||
/* #undef HAVE_NANOSLEEP */
|
||||
|
||||
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
|
||||
/* #undef HAVE_NDIR_H */
|
||||
|
||||
/* Define to 1 if you have the <netdb.h> header file. */
|
||||
/* #undef HAVE_NETDB_H */
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
/* #undef HAVE_NETINET_IN_H */
|
||||
|
||||
/* Define to 1 if you have the `opendir' function. */
|
||||
/* #undef HAVE_OPENDIR */
|
||||
|
||||
/* Support for OpenGL graphics acceleration. */
|
||||
/* #undef HAVE_OPENGL */
|
||||
|
||||
/* Define to 1 if you have the <readline/readline.h> header file. */
|
||||
/* #undef HAVE_READLINE_READLINE_H */
|
||||
|
||||
/* Define to 1 if you have the `rename' function. */
|
||||
#define HAVE_RENAME 1
|
||||
|
||||
/* Define to 1 if you have the `rewind' function. */
|
||||
#define HAVE_REWIND 1
|
||||
|
||||
/* Define to 1 if you have the `rmdir' function. */
|
||||
#define HAVE_RMDIR 1
|
||||
|
||||
/* Define to 1 if you have the `select' function. */
|
||||
/* #undef HAVE_SELECT */
|
||||
|
||||
/* Define to 1 if you have the `signal' function. */
|
||||
#define HAVE_SIGNAL 1
|
||||
|
||||
/* Define to 1 if you have the <signal.h> header file. */
|
||||
#define HAVE_SIGNAL_H 1
|
||||
|
||||
/* Define to 1 if you have the `snprintf' function. */
|
||||
/* #undef HAVE_SNPRINTF */
|
||||
|
||||
/* Define to 1 if you have the `socket' function. */
|
||||
/* #undef HAVE_SOCKET */
|
||||
|
||||
/* Define to 1 if you have the `stat' function. */
|
||||
#define HAVE_STAT 1
|
||||
|
||||
/* Define to 1 if `stat' has the bug that it succeeds when given the
|
||||
zero-length file name argument. */
|
||||
/* #undef HAVE_STAT_EMPTY_STRING_BUG */
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
/* #undef HAVE_STDINT_H */
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the `strcasecmp' function. */
|
||||
/* #undef HAVE_STRCASECMP */
|
||||
|
||||
/* Define to 1 if you have the `strchr' function. */
|
||||
#define HAVE_STRCHR 1
|
||||
|
||||
/* Define to 1 if you have the `strdup' function. */
|
||||
#define HAVE_STRDUP 1
|
||||
|
||||
/* Define to 1 if you have the `strerror' function. */
|
||||
#define HAVE_STRERROR 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
/* #undef HAVE_STRINGS_H */
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the `strncpy' function. */
|
||||
/* #undef HAVE_STRNCPY */
|
||||
|
||||
/* Define to 1 if you have the `strrchr' function. */
|
||||
#define HAVE_STRRCHR 1
|
||||
|
||||
/* Define to 1 if you have the `strstr' function. */
|
||||
#define HAVE_STRSTR 1
|
||||
|
||||
/* Define to 1 if you have the `strtol' function. */
|
||||
#define HAVE_STRTOL 1
|
||||
|
||||
/* Define to 1 if you have the `system' function. */
|
||||
#define HAVE_SYSTEM 1
|
||||
|
||||
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
|
||||
*/
|
||||
/* #undef HAVE_SYS_DIR_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
/* #undef HAVE_SYS_IOCTL_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
|
||||
*/
|
||||
/* #undef HAVE_SYS_NDIR_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||
/* #undef HAVE_SYS_SELECT_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
/* #undef HAVE_SYS_SOCKET_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/soundcard.h> header file. */
|
||||
/* #undef HAVE_SYS_SOUNDCARD_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
/* #undef HAVE_SYS_TIME_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <termios.h> header file. */
|
||||
/* #undef HAVE_TERMIOS_H */
|
||||
|
||||
/* Define to 1 if you have the `time' function. */
|
||||
#define HAVE_TIME 1
|
||||
|
||||
/* Define to 1 if you have the <time.h> header file. */
|
||||
#define HAVE_TIME_H 1
|
||||
|
||||
/* Define to 1 if you have the `tmpfile' function. */
|
||||
#define HAVE_TMPFILE 1
|
||||
|
||||
/* Define to 1 if you have the `tmpnam' function. */
|
||||
#define HAVE_TMPNAM 1
|
||||
|
||||
/* Define to 1 if you have the `uclock' function. */
|
||||
/* #undef HAVE_UCLOCK */
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
/* #undef HAVE_UNISTD_H */
|
||||
|
||||
/* Define to 1 if you have the <unixio.h> header file. */
|
||||
/* #undef HAVE_UNIXIO_H */
|
||||
|
||||
/* Define to 1 if you have the `unlink' function. */
|
||||
#define HAVE_UNLINK 1
|
||||
|
||||
/* Define to 1 if you have the `usleep' function. */
|
||||
/* #undef HAVE_USLEEP */
|
||||
|
||||
/* Define to 1 if you have the `vprintf' function. */
|
||||
#define HAVE_VPRINTF 1
|
||||
|
||||
/* Define to 1 if you have the `vsnprintf' function. */
|
||||
/* #undef HAVE_VSNPRINTF */
|
||||
|
||||
/* Define to 1 if you have the <windows.h> header file. */
|
||||
#define HAVE_WINDOWS_H 1
|
||||
|
||||
/* Define to 1 if you have the <winsock2.h> header file. */
|
||||
#define HAVE_WINSOCK2_H 1
|
||||
|
||||
/* Define to 1 if you have the `_mkdir' function. */
|
||||
/* #undef HAVE__MKDIR */
|
||||
|
||||
/* Define to add IDE harddisk emulation. */
|
||||
/* #undef IDE */
|
||||
|
||||
/* Define to allow sound interpolation. */
|
||||
#define INTERPOLATE_SOUND 1
|
||||
|
||||
/* Target: Java NestedVM. */
|
||||
/* #undef JAVANVM */
|
||||
|
||||
/* Define to use LINUX joystick. */
|
||||
/* #undef LINUX_JOYSTICK */
|
||||
|
||||
/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
|
||||
slash. */
|
||||
/* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */
|
||||
|
||||
/* Define if mkdir takes only one argument. */
|
||||
#define MKDIR_TAKES_ONE_ARG 1
|
||||
|
||||
/* Define to activate assembler in monitor. */
|
||||
#define MONITOR_ASSEMBLER 1
|
||||
|
||||
/* Define to activate code breakpoints and execution history. */
|
||||
#define MONITOR_BREAK 1
|
||||
|
||||
/* Define to activate user-defined breakpoints. */
|
||||
/* #undef MONITOR_BREAKPOINTS */
|
||||
|
||||
/* Define to activate hints in disassembler. */
|
||||
#define MONITOR_HINTS 1
|
||||
|
||||
/* Define to activate 6502 opcode profiling. */
|
||||
/* #undef MONITOR_PROFILE */
|
||||
|
||||
/* Define to activate readline support in monitor. */
|
||||
/* #undef MONITOR_READLINE */
|
||||
|
||||
/* Define to activate TRACE command in monitor. */
|
||||
/* #undef MONITOR_TRACE */
|
||||
|
||||
/* Target: X11 with Motif. */
|
||||
/* #undef MOTIF */
|
||||
|
||||
/* Define to allow color changes inside a scanline. */
|
||||
#define NEW_CYCLE_EXACT 1
|
||||
|
||||
/* Define to use nonlinear POKEY mixing. */
|
||||
/* #undef NONLINEAR_MIXING */
|
||||
|
||||
/* Use NTSC video filter. */
|
||||
/* #undef NTSC_FILTER */
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
/* #undef PACKAGE_BUGREPORT */
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
/* #undef PACKAGE_NAME */
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
/* #undef PACKAGE_STRING */
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
/* #undef PACKAGE_TARNAME */
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
/* #undef PACKAGE_URL */
|
||||
|
||||
/* Define to the version of this package. */
|
||||
/* #undef PACKAGE_VERSION */
|
||||
|
||||
/* Define to use page-based attribute array. */
|
||||
/* #undef PAGED_ATTRIB */
|
||||
|
||||
/* Define to emulate the Black Box. */
|
||||
/* #undef PBI_BB */
|
||||
|
||||
/* Define to emulate the MIO board. */
|
||||
/* #undef PBI_MIO */
|
||||
|
||||
/* A prototype 80 column card for the 1090 expansion box. */
|
||||
/* #undef PBI_PROTO80 */
|
||||
|
||||
/* Define to emulate the 1400XL/1450XLD. */
|
||||
/* #undef PBI_XLD */
|
||||
|
||||
/* Target: Sony PlayStation 2. */
|
||||
/* #undef PS2 */
|
||||
|
||||
/* Define as the return type of signal handlers (`int' or `void'). */
|
||||
#define RETSIGTYPE void
|
||||
|
||||
/* Define to use R: device. */
|
||||
/* #undef R_IO_DEVICE */
|
||||
|
||||
/* Define to use IP network connection with the R: device. */
|
||||
/* #undef R_NETWORK */
|
||||
|
||||
/* Define to use the host serial port with the R: device. */
|
||||
/* #undef R_SERIAL */
|
||||
|
||||
/* Target: SDL library. */
|
||||
/* #undef SDL */
|
||||
|
||||
/* Define to the type of arg 1 for `select'. */
|
||||
/* #undef SELECT_TYPE_ARG1 */
|
||||
|
||||
/* Define to the type of args 2, 3 and 4 for `select'. */
|
||||
/* #undef SELECT_TYPE_ARG234 */
|
||||
|
||||
/* Define to the type of arg 5 for `select'. */
|
||||
/* #undef SELECT_TYPE_ARG5 */
|
||||
|
||||
/* Define to allow serial in/out sound. */
|
||||
/* #undef SERIO_SOUND */
|
||||
|
||||
/* Target: X11 with shared memory extensions. */
|
||||
/* #undef SHM */
|
||||
|
||||
/* Define to activate sound support. */
|
||||
#define SOUND 1
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Define to allow stereo sound. */
|
||||
/* #undef STEREO_SOUND */ /* TODO */
|
||||
|
||||
/* Can change video modes on the fly. */
|
||||
/* #undef SUPPORTS_CHANGE_VIDEOMODE */
|
||||
|
||||
/* Save additional config file options. */
|
||||
#define SUPPORTS_PLATFORM_CONFIGSAVE
|
||||
|
||||
/* Additional config file options. */
|
||||
#define SUPPORTS_PLATFORM_CONFIGURE
|
||||
|
||||
/* Update the Palette if it changed. */
|
||||
#define SUPPORTS_PLATFORM_PALETTEUPDATE 1
|
||||
|
||||
/* Platform-specific sleep function. */
|
||||
/* #undef SUPPORTS_PLATFORM_SLEEP */
|
||||
|
||||
/* Can display the screen rotated sideways. */
|
||||
/* #undef SUPPORTS_ROTATE_VIDEOMODE */
|
||||
|
||||
/* Reinitialise the sound system. */
|
||||
/* #undef SUPPORTS_SOUND_REINIT */
|
||||
|
||||
/* Define to use synchronized sound. */
|
||||
/* #undef SYNCHRONIZED_SOUND */
|
||||
|
||||
/* Alternate system-wide config file for non-Unix OS. */
|
||||
#define SYSTEM_WIDE_CFG_FILE "c:\\atari800.cfg"
|
||||
|
||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
||||
/* #undef TIME_WITH_SYS_TIME */
|
||||
|
||||
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
|
||||
/* #undef TM_IN_SYS_TIME */
|
||||
|
||||
/* Target: Curses-compatible library. */
|
||||
/* #undef USE_CURSES */
|
||||
|
||||
/* Define for using cursor/ctrl keys for keyboard joystick. */
|
||||
/* #undef USE_CURSORBLOCK */
|
||||
|
||||
/* Target: Ncurses library. */
|
||||
/* #undef USE_NCURSES */
|
||||
|
||||
/* Define to use very slow computer support (faster -refresh). */
|
||||
/* #undef VERY_SLOW */
|
||||
|
||||
/* Define to emulate the Alien Group Voice Box. */
|
||||
/* #undef VOICEBOX */
|
||||
|
||||
/* Define to allow volume only sound. */
|
||||
#define VOL_ONLY_SOUND 1
|
||||
|
||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||
significant byte first (like Motorola and SPARC, unlike Intel). */
|
||||
#if defined AC_APPLE_UNIVERSAL_BUILD
|
||||
# if defined __BIG_ENDIAN__
|
||||
# define WORDS_BIGENDIAN 1
|
||||
# endif
|
||||
#else
|
||||
# ifndef WORDS_BIGENDIAN
|
||||
/* # undef WORDS_BIGENDIAN */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Define if unaligned word access is ok. */
|
||||
#define WORDS_UNALIGNED_OK 1
|
||||
|
||||
/* Target: Standard X11. */
|
||||
/* #undef X11 */
|
||||
|
||||
/* Emulate the XEP80. */
|
||||
/* #undef XEP80_EMULATION */
|
||||
|
||||
/* Target: X11 with XView. */
|
||||
/* #undef XVIEW */
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
/* #undef _FILE_OFFSET_BITS */
|
||||
|
||||
/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
|
||||
/* #undef _LARGEFILE_SOURCE */
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
/* #undef _LARGE_FILES */
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef const */
|
||||
|
||||
/* Define as `__inline' if that's what the C compiler calls it, or to nothing
|
||||
if it is not supported. */
|
||||
#define inline __inline
|
||||
|
||||
/* Define to `unsigned' if <sys/types.h> does not define. */
|
||||
/* #undef size_t */
|
||||
|
||||
/* Define to empty if the keyword `volatile' does not work. Warning: valid
|
||||
code using `volatile' can become incorrect without. Disable with care. */
|
||||
/* #undef volatile */
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/* use our exit() instead of libc's */
|
||||
#define exit main_exit
|
||||
@@ -0,0 +1,404 @@
|
||||
#include "config.h"
|
||||
#include "screen.h"
|
||||
#include "render_direct3d.h"
|
||||
#include <windows.h>
|
||||
|
||||
#include <d3d9.h>
|
||||
#include <d3dx9.h>
|
||||
|
||||
extern "C" HWND hWndMain;
|
||||
extern "C" {
|
||||
#include "colours.h"
|
||||
#include "log.h"
|
||||
}
|
||||
|
||||
typedef D3DXMATRIX* (WINAPI* D3DXMatrixLookAtLHFunc)(D3DXMATRIX*, CONST D3DXVECTOR3*, CONST D3DXVECTOR3*, CONST D3DXVECTOR3*);
|
||||
typedef D3DXMATRIX* (WINAPI* D3DXMatrixPerspectiveFovLHFunc)(D3DXMATRIX*, FLOAT, FLOAT, FLOAT, FLOAT);
|
||||
typedef D3DXMATRIX* (WINAPI* D3DXMatrixRotationYFunc)(D3DXMATRIX*, FLOAT);
|
||||
|
||||
// D3D declarations
|
||||
static LPDIRECT3D9 d3d;
|
||||
static LPDIRECT3DDEVICE9 d3d_device;
|
||||
static LPDIRECT3DVERTEXBUFFER9 vertex_buffer = NULL;
|
||||
static LPDIRECT3DTEXTURE9 texture_buffer = NULL;
|
||||
static D3DPRESENT_PARAMETERS d3dpp;
|
||||
|
||||
struct CUSTOMVERTEX {FLOAT X, Y, Z; DWORD COLOR; FLOAT U, V;};
|
||||
#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
|
||||
|
||||
static float const pi = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862f;
|
||||
|
||||
static float texturehorizclip = 0.0f;
|
||||
static float texturevertclip = 0.0f;
|
||||
|
||||
static HMODULE hD3DX = NULL;
|
||||
static D3DXMatrixLookAtLHFunc D3DXMatrixLookAtLHPtr = NULL;
|
||||
static D3DXMatrixPerspectiveFovLHFunc D3DXMatrixPerspectiveFovLHPtr = NULL;
|
||||
static D3DXMatrixRotationYFunc D3DXMatrixRotationYPtr = NULL;
|
||||
|
||||
extern "C" void startupdirect3d(int screenwidth, int screenheight, BOOL windowed, FRAMEPARAMS *fp)
|
||||
{
|
||||
// look for the newest, oldest, then generic versions
|
||||
if ((hD3DX = LoadLibrary("d3dx9_42.dll")) != NULL || (hD3DX = LoadLibrary("d3dx9_24.dll")) != NULL || (hD3DX = LoadLibrary("d3dx9.dll")) != NULL)
|
||||
{
|
||||
D3DXMatrixLookAtLHPtr = (D3DXMatrixLookAtLHFunc) GetProcAddress(hD3DX, "D3DXMatrixLookAtLH");
|
||||
D3DXMatrixPerspectiveFovLHPtr = (D3DXMatrixPerspectiveFovLHFunc) GetProcAddress(hD3DX, "D3DXMatrixPerspectiveFovLH");
|
||||
D3DXMatrixRotationYPtr = (D3DXMatrixRotationYFunc) GetProcAddress(hD3DX, "D3DXMatrixRotationY");
|
||||
// unlikely failure to load function pointers
|
||||
if (D3DXMatrixLookAtLHPtr == NULL || D3DXMatrixPerspectiveFovLHPtr == NULL || D3DXMatrixRotationYPtr == NULL)
|
||||
{
|
||||
FreeLibrary(hD3DX);
|
||||
hD3DX = NULL;
|
||||
Log_print("Extended Direct3D functions disabled - load failure");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log_print("Extended Direct3D functions disabled - updated DirectX runtime needed");
|
||||
}
|
||||
|
||||
d3d = Direct3DCreate9(D3D_SDK_VERSION);
|
||||
|
||||
initpresentparams(screenwidth, screenheight, windowed);
|
||||
|
||||
// create the D3D device
|
||||
d3d->CreateDevice(D3DADAPTER_DEFAULT,
|
||||
D3DDEVTYPE_HAL,
|
||||
hWndMain,
|
||||
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
|
||||
&d3dpp,
|
||||
&d3d_device);
|
||||
|
||||
initdevice(fp);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Function used when we need to change present params
|
||||
void resetdevice(int screenwidth, int screenheight, BOOL windowed, FRAMEPARAMS *fp)
|
||||
{
|
||||
texture_buffer->Release(); // close and release the texture
|
||||
initpresentparams(screenwidth, screenheight, windowed);
|
||||
d3d_device->Reset(&d3dpp);
|
||||
initdevice(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
void initpresentparams(int screenwidth, int screenheight, BOOL windowed)
|
||||
{
|
||||
ZeroMemory(&d3dpp, sizeof(d3dpp));
|
||||
d3dpp.Windowed = windowed;
|
||||
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
d3dpp.hDeviceWindow = hWndMain;
|
||||
d3dpp.BackBufferWidth = screenwidth;
|
||||
d3dpp.BackBufferHeight = screenheight;
|
||||
d3dpp.EnableAutoDepthStencil = TRUE;
|
||||
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
|
||||
|
||||
// Only need this in fullscreen mode.
|
||||
if (!windowed) {
|
||||
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void initdevice(FRAMEPARAMS *fp)
|
||||
{
|
||||
UINT texturesize;
|
||||
D3DTEXTUREFILTERTYPE filtertype;
|
||||
|
||||
// compute a horizontal & vertical offset
|
||||
// with compensation for possible cropping & stretching
|
||||
int clip_width = fp->view.right - fp->view.left;
|
||||
int clip_height = fp->view.bottom - fp->view.top;
|
||||
|
||||
// set the type of interpolation filtering selected by the user
|
||||
// only bilinear or none are available.
|
||||
if (fp->filter == BILINEAR)
|
||||
filtertype = D3DTEXF_LINEAR;
|
||||
else
|
||||
filtertype = D3DTEXF_POINT;
|
||||
|
||||
d3d_device->SetRenderState(D3DRS_LIGHTING, FALSE); // turn off the 3D lighting
|
||||
d3d_device->SetRenderState(D3DRS_ZENABLE, TRUE); // turn on the z-buffer
|
||||
d3d_device->SetSamplerState( 0, D3DSAMP_MAGFILTER, filtertype);
|
||||
d3d_device->SetFVF(CUSTOMFVF);
|
||||
|
||||
// In Direct3D we paint the Atari screen onto a texture that overlays a vertex buffer polygon.
|
||||
// Although most newer graphics cards support rectangular textures of variable size,
|
||||
// for compatibility and performance reasons, it is better that the texture be square with
|
||||
// sides that are a power of two. Since the size of the bitmap changes depending
|
||||
// on the scanline mode, we set that here. We also set the clipping parameters here
|
||||
// that we'll use in the vertex buffer init to only map the drawn portion of the
|
||||
// texture to the vertex buffer.
|
||||
|
||||
switch (fp->scanlinemode)
|
||||
{
|
||||
case NONE: // we are just mapping the standard 320x240 Atari screen bitmap.
|
||||
texturesize = 512;
|
||||
texturehorizclip = clip_width / (float)texturesize;
|
||||
texturevertclip = clip_height / (float)texturesize;
|
||||
break;
|
||||
case LOW: // LOW res scanlines produces a 320x480 pixel bitmap
|
||||
texturesize = 512;
|
||||
texturehorizclip = clip_width / (float)texturesize;
|
||||
texturevertclip = (clip_height * 2 + 1) / (float)texturesize;
|
||||
break;
|
||||
case MEDIUM: // MEDIUM res scanlines produces a 320x720 pixel bitmap
|
||||
texturesize = 1024;
|
||||
texturehorizclip = clip_width / (float)texturesize;
|
||||
texturevertclip = (clip_height * 3 + 2) / (float)texturesize;
|
||||
break;
|
||||
case HIGH: // HIGH res canlines produces a 320x960 pixel bitmap
|
||||
texturesize = 1024;
|
||||
texturehorizclip = clip_width / (float)texturesize;
|
||||
texturevertclip = (clip_height * 4 + 3) / (float)texturesize;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// now lets go ahead and create a blank texture of the appropriate dimensions
|
||||
d3d_device->CreateTexture(texturesize, texturesize, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture_buffer, NULL );
|
||||
return;
|
||||
}
|
||||
|
||||
// this function creates the 2D vertex buffer polygon and attaches the texture to it
|
||||
void init_vertices(float x, float y, float z)
|
||||
{
|
||||
// Create the vertices.
|
||||
// What we're actually doing here is specifying two right triangles
|
||||
// attached to one another to form a wireframe rectangle. We also specify
|
||||
// that our texture (the screen) should be mapped to extend to the edges
|
||||
// of this rectangle. This is basically how we create a 2D surface with
|
||||
// a 3D toolset.
|
||||
|
||||
struct CUSTOMVERTEX vertex_def[] =
|
||||
{
|
||||
{-x, y, z, 0xffffffff, 0, 0,},
|
||||
{x, y, z, 0xffffffff, texturehorizclip, 0,},
|
||||
{-x, -y, -z, 0xffffffff, 0, texturevertclip,},
|
||||
{x, -y, -z, 0xffffffff, texturehorizclip, texturevertclip,},
|
||||
};
|
||||
|
||||
d3d_device->CreateVertexBuffer(4*sizeof(CUSTOMVERTEX),
|
||||
0,
|
||||
CUSTOMFVF,
|
||||
D3DPOOL_MANAGED,
|
||||
&vertex_buffer,
|
||||
NULL);
|
||||
|
||||
VOID* pVoid; // a void pointer
|
||||
|
||||
// lock vertex_buffer and load the vertices into it
|
||||
vertex_buffer->Lock(0, 0, (void**)&pVoid, 0);
|
||||
memcpy(pVoid, vertex_def, sizeof(vertex_def));
|
||||
vertex_buffer->Unlock();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// this is the function used to render each frame
|
||||
void refreshv_direct3d(UBYTE *scr_ptr, FRAMEPARAMS *fp)
|
||||
{
|
||||
// clear the contents of the vertex buffer polygon and make it black
|
||||
d3d_device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
|
||||
d3d_device->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
|
||||
|
||||
// If the caller has set fp->d3dRefresh to true it means that the vertex
|
||||
// buffer has changed (usually because the window or texture size has changed).
|
||||
// In these cases we will re-init the vertices prior to building the frame.
|
||||
if (fp->d3dRefresh)
|
||||
{
|
||||
if (hD3DX != NULL)
|
||||
{
|
||||
init_vertices(fp->d3dWidth, 0, fp->d3dHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
init_vertices(fp->d3dWidth, fp->d3dHeight, 0);
|
||||
}
|
||||
fp->d3dRefresh = FALSE;
|
||||
}
|
||||
|
||||
// We can now unlock the backbuffer and start to draw our frame
|
||||
d3d_device->BeginScene();
|
||||
|
||||
// refresh the texture buffer for the frame
|
||||
// this function call actually draws the contents of the Atari screen buffer
|
||||
// to the Direct3D backbuffer.
|
||||
refresh_frame(scr_ptr, fp);
|
||||
|
||||
// set the texture
|
||||
d3d_device->SetTexture(0, texture_buffer);
|
||||
|
||||
// select the vertex buffer to display
|
||||
d3d_device->SetStreamSource(0, vertex_buffer, 0, sizeof(CUSTOMVERTEX));
|
||||
|
||||
//***********************************************************************
|
||||
// This next section supports the 3D screensaver and tilt functions by
|
||||
// using some simple matrix tranformations on the vertex buffer polygon.
|
||||
// Note: If you want to remove this 3D screensaver effect and operate
|
||||
// in a more purely 2D view, change the init_vertices statement above to
|
||||
// init_vertices(fp->d3dWidth, fp->d3dHeight, 0);
|
||||
// and remove all statements from here to the end of this
|
||||
// 3D Matrix Transformations section.
|
||||
//***********************************************************************
|
||||
if (hD3DX != NULL)
|
||||
{
|
||||
|
||||
D3DXMATRIX matView;
|
||||
|
||||
static float index = pi; // rotation amount
|
||||
static float cy = 2.41f; // amount of zoom
|
||||
static float cz = 0.00001f; // amount of tilt
|
||||
static float by = 0.0;
|
||||
|
||||
if (fp->screensaver)
|
||||
{
|
||||
fp->tiltlevel = TILTLEVEL0; // make sure tiltlevel is disabled
|
||||
|
||||
// this transformation creates and animates the 3D screensaver
|
||||
|
||||
if (cy > 1.5f)
|
||||
cy -= 0.002f; // zoom
|
||||
if (cz < 2.2)
|
||||
cz += 0.005f; // tilt
|
||||
|
||||
index+=0.005f; // rotation index
|
||||
}
|
||||
else if (fp->tiltlevel != TILTLEVEL0)
|
||||
{
|
||||
index = pi;
|
||||
|
||||
switch (fp->tiltlevel)
|
||||
{
|
||||
case TILTLEVEL1:
|
||||
if (cz < 1.0)
|
||||
cz += 0.012f; // tilt
|
||||
if (by > -0.2f)
|
||||
by -= 0.003f; // slide up
|
||||
break;
|
||||
case TILTLEVEL2:
|
||||
if (cz < 1.5)
|
||||
cz += 0.016f; // tilt
|
||||
if (cy > 2.3f)
|
||||
cy -= 0.004f; // zoom
|
||||
break;
|
||||
case TILTLEVEL3:
|
||||
if (cz < 1.8)
|
||||
cz += 0.012f; // tilt
|
||||
if (cy > 2.1f)
|
||||
cy -= 0.008f; // zoom
|
||||
if (by > -0.25f)
|
||||
by -= 0.002f; // slide up
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// this transformation creates a standard 2D view
|
||||
|
||||
index = pi;
|
||||
|
||||
cy = 2.41f;
|
||||
cz = 0.00001f;
|
||||
by = 0.0;
|
||||
}
|
||||
|
||||
// Create the transform matView
|
||||
D3DXMatrixLookAtLHPtr(&matView,
|
||||
&D3DXVECTOR3 (0.0f, cy, cz), // tilt & zoom the camera
|
||||
&D3DXVECTOR3 (0.0f, by, 0.0f), // raise & lower the camera
|
||||
&D3DXVECTOR3 (0.0f, 1.0, 0.0f)); // flip the camera
|
||||
|
||||
d3d_device->SetTransform(D3DTS_VIEW, &matView); // set the view transform to matView
|
||||
|
||||
// set the projection transform
|
||||
D3DXMATRIX matProjection; // the projection transform matrix
|
||||
D3DXMatrixPerspectiveFovLHPtr(&matProjection,
|
||||
D3DXToRadian(45), // the horizontal field of view
|
||||
1.0f, // aspect ratio
|
||||
1.0f, // the near view-plane
|
||||
100.0f); // the far view-plane
|
||||
d3d_device->SetTransform(D3DTS_PROJECTION, &matProjection); // set the projection
|
||||
|
||||
// set the world transform
|
||||
D3DXMATRIX matRotateY; // a matrix to store the rotation for each triangle
|
||||
D3DXMatrixRotationYPtr(&matRotateY, index); // the rotation matrix
|
||||
d3d_device->SetTransform(D3DTS_WORLD, &(matRotateY)); // set the world transform
|
||||
}
|
||||
|
||||
//***********************************************************************
|
||||
// End 3D transformations
|
||||
//***********************************************************************
|
||||
|
||||
// draw the fully rendered and transformed surface to the backbuffer
|
||||
d3d_device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
||||
|
||||
// We now lock the backbuffer
|
||||
d3d_device->EndScene();
|
||||
|
||||
// Now tell Direct3D to flip the image to the screen.
|
||||
d3d_device->Present(NULL, NULL, NULL, NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// shutdown the Direct3D engine
|
||||
extern "C" void shutdowndirect3d(void)
|
||||
{
|
||||
vertex_buffer->Release(); // close and release the vertex buffer
|
||||
texture_buffer->Release(); // close and release the texture
|
||||
d3d_device->Release(); // close and release the 3D device
|
||||
d3d->Release(); // close and release Direct3D
|
||||
|
||||
if (hD3DX != NULL)
|
||||
{
|
||||
FreeLibrary(hD3DX);
|
||||
hD3DX = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy the raw screen buffer data to the texture buffer
|
||||
void refresh_frame(UBYTE *scr_ptr, FRAMEPARAMS *fp)
|
||||
{
|
||||
int pixel = 0;
|
||||
int i, x, y;
|
||||
int texturewidth;
|
||||
|
||||
// calculate texture width
|
||||
int viewwidth = fp->view.right - fp->view.left;
|
||||
|
||||
D3DLOCKED_RECT d3dlr;
|
||||
texture_buffer->LockRect(0, &d3dlr, 0, 0);
|
||||
|
||||
DWORD* pixels = (DWORD*)d3dlr.pBits;
|
||||
texturewidth = d3dlr.Pitch / 4;
|
||||
|
||||
// copy screen buffer to the texture
|
||||
scr_ptr += fp->view.top * Screen_WIDTH + fp->view.left;
|
||||
for (y = fp->view.top; y < fp->view.bottom; y++) {
|
||||
for (x = fp->view.left; x < fp->view.right; x++) {
|
||||
if (y < 0 || y >= Screen_HEIGHT || x < 0 || x >= Screen_WIDTH)
|
||||
pixels[pixel] = Colours_table[0];
|
||||
else
|
||||
pixels[pixel] = Colours_table[*scr_ptr];
|
||||
|
||||
for (i = 0; i < fp->scanlinemode; i++) {
|
||||
pixels[pixel + i * texturewidth] = pixels[pixel];
|
||||
}
|
||||
|
||||
scr_ptr++;
|
||||
pixel++;
|
||||
}
|
||||
scr_ptr += Screen_WIDTH - viewwidth;
|
||||
pixel += texturewidth - viewwidth;
|
||||
pixel += texturewidth * fp->scanlinemode;
|
||||
}
|
||||
|
||||
texture_buffer->UnlockRect(0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef _RENDER_DIRECT3D_H_
|
||||
#define _RENDER_DIRECT3D_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "atari.h"
|
||||
#include "screen_win32.h"
|
||||
|
||||
void startupdirect3d(int screenwidth, int screenheight, BOOL windowed, FRAMEPARAMS *fp);
|
||||
void shutdowndirect3d(void);
|
||||
void refreshv_direct3d(UBYTE *scr_ptr, FRAMEPARAMS *fp);
|
||||
void init_vertices(float x, float y, float z);
|
||||
void refresh_frame(UBYTE *scr_ptr, FRAMEPARAMS *fp);
|
||||
void initpresentparams(int screenwidth, int screenheight, BOOL windowed);
|
||||
void resetdevice(int screenwidth, int screenheight, BOOL windowed, FRAMEPARAMS *fp);
|
||||
void initdevice(FRAMEPARAMS *fp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
#include "render_directdraw.h"
|
||||
#include "main.h"
|
||||
#include "colours.h"
|
||||
#include "screen_win32.h"
|
||||
#include "screen.h"
|
||||
#include <ddraw.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define MAX_CLR 0x100
|
||||
static PALETTEENTRY pal[MAX_CLR]; /* palette */
|
||||
|
||||
static LPDIRECTDRAW4 lpDD = NULL;
|
||||
static LPDIRECTDRAWSURFACE4 lpDDSPrimary = NULL;
|
||||
static LPDIRECTDRAWSURFACE4 lpDDSBack = NULL;
|
||||
static LPDIRECTDRAWSURFACE4 lpDDSsrc = NULL;
|
||||
static LPDIRECTDRAWPALETTE lpDDPal = NULL;
|
||||
|
||||
static int linesize = 0;
|
||||
static int scrwidth = SCREENWIDTH;
|
||||
static int scrheight = SCREENHEIGHT;
|
||||
static UBYTE *scraddr = NULL;
|
||||
|
||||
/* Platform-specific function to update the palette if it changed */
|
||||
void PLATFORM_PaletteUpdate(void)
|
||||
{
|
||||
if(lpDDPal != NULL) {
|
||||
int i;
|
||||
for (i = 0; i < MAX_CLR; i++) {
|
||||
palette(i, Colours_GetR(i), Colours_GetG(i), Colours_GetB(i));
|
||||
}
|
||||
palupd(0, MAX_CLR);
|
||||
}
|
||||
}
|
||||
|
||||
static int initFail(HWND hwnd, const char *func, HRESULT hr)
|
||||
{
|
||||
char txt[256];
|
||||
sprintf(txt, "DirectDraw Init FAILED: %s returned 0x%x", func, (unsigned int)hr);
|
||||
MessageBox(hwnd, txt, myname, MB_OK);
|
||||
groff();
|
||||
DestroyWindow(hwnd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void palupd(int beg, int cnt)
|
||||
{
|
||||
IDirectDrawPalette_SetEntries(lpDDPal, 0, beg, cnt, pal);
|
||||
}
|
||||
|
||||
void palette(int ent, UBYTE r, UBYTE g, UBYTE b)
|
||||
{
|
||||
if (ent >= MAX_CLR)
|
||||
return;
|
||||
pal[ent].peRed = r;
|
||||
pal[ent].peGreen = g;
|
||||
pal[ent].peBlue = b;
|
||||
pal[ent].peFlags = 0;
|
||||
}
|
||||
|
||||
/* Platform-specific function to update the palette if it changed */
|
||||
void Atari_PaletteUpdate(void)
|
||||
{
|
||||
if(lpDDPal != NULL) {
|
||||
int i;
|
||||
for (i = 0; i < MAX_CLR; i++) {
|
||||
palette(i, Colours_GetR(i), Colours_GetG(i), Colours_GetB(i));
|
||||
}
|
||||
palupd(0, MAX_CLR);
|
||||
}
|
||||
}
|
||||
|
||||
int startupdirectdraw(BOOL bltgfx, INT width)
|
||||
{
|
||||
DDSURFACEDESC2 ddsd;
|
||||
DDSCAPS2 ddscaps;
|
||||
HRESULT ddrval;
|
||||
int i;
|
||||
|
||||
if (width > 0) {
|
||||
scrwidth = width;
|
||||
scrheight = width * 3 / 4;
|
||||
}
|
||||
|
||||
ddrval = DirectDrawCreate(NULL, (void *) &lpDD, NULL);
|
||||
if (FAILED(ddrval))
|
||||
return initFail(hWndMain, "DirectDrawCreate", ddrval);
|
||||
ddrval = IDirectDraw4_QueryInterface(lpDD, &IID_IDirectDraw4, (void *) &lpDD);
|
||||
if (FAILED(ddrval))
|
||||
return initFail(hWndMain, "QueryInterface", ddrval);
|
||||
ddrval = IDirectDraw4_SetCooperativeLevel(lpDD, hWndMain, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
|
||||
if (FAILED(ddrval))
|
||||
return initFail(hWndMain, "SetCooperativeLevel", ddrval);
|
||||
|
||||
if (bltgfx) {
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddrval = IDirectDraw4_GetDisplayMode(lpDD, &ddsd);
|
||||
if (FAILED(ddrval))
|
||||
return initFail(hWndMain, "GetDisplayMode", ddrval);
|
||||
ddrval = IDirectDraw4_SetDisplayMode(lpDD, ddsd.dwWidth, ddsd.dwHeight, 32, 0, 0);
|
||||
}
|
||||
else {
|
||||
ddrval = IDirectDraw4_SetDisplayMode(lpDD, scrwidth, scrheight, 8, 0, 0);
|
||||
}
|
||||
if (FAILED(ddrval)) {
|
||||
if ((ddrval == DDERR_INVALIDMODE || ddrval == DDERR_UNSUPPORTED) && !bltgfx && width != 640) {
|
||||
/* 320x240 results in DDERR_INVALIDMODE on my Win98SE / Radeon 9000 */
|
||||
/* 320x240 results in DDERR_UNSUPPORTED on my WinXP / Toshiba laptop */
|
||||
MessageBox(hWndMain,
|
||||
"DirectDraw does not support the requested display mode.\n"
|
||||
"Try running with \"-blt\" or \"-width 640\" on the command line.",
|
||||
myname, MB_OK);
|
||||
groff();
|
||||
DestroyWindow(hWndMain);
|
||||
return 1;
|
||||
}
|
||||
return initFail(hWndMain, "SetDisplayMode", ddrval);
|
||||
}
|
||||
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
|
||||
ddsd.dwBackBufferCount = 1;
|
||||
ddrval = IDirectDraw4_CreateSurface(lpDD, &ddsd, &lpDDSPrimary, NULL);
|
||||
if (FAILED(ddrval))
|
||||
return initFail(hWndMain, "CreateSurface", ddrval);
|
||||
memset(&ddscaps, 0, sizeof(ddscaps));
|
||||
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
|
||||
ddrval = IDirectDrawSurface4_GetAttachedSurface(lpDDSPrimary, &ddscaps, &lpDDSBack);
|
||||
if (FAILED(ddrval))
|
||||
return initFail(hWndMain, "GetAttachedSurface", ddrval);
|
||||
|
||||
if (bltgfx) {
|
||||
ddrval = IDirectDraw4_GetDisplayMode(lpDD, &ddsd);
|
||||
if (FAILED(ddrval))
|
||||
return initFail(hWndMain, "GetDisplayMode", ddrval);
|
||||
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
|
||||
ddsd.dwWidth = 336;
|
||||
ddsd.dwHeight = 252;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
|
||||
ddrval = IDirectDraw4_CreateSurface(lpDD, &ddsd, &lpDDSsrc, NULL);
|
||||
if (FAILED(ddrval))
|
||||
return initFail(hWndMain, "CreateSurface", ddrval);
|
||||
|
||||
ddrval = IDirectDrawSurface4_Lock(lpDDSsrc, NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
|
||||
if (FAILED(ddrval))
|
||||
return initFail(hWndMain, "Lock", ddrval);
|
||||
|
||||
memset(ddsd.lpSurface, 0, ddsd.lPitch * ddsd.dwHeight);
|
||||
|
||||
ddrval = IDirectDrawSurface4_Unlock(lpDDSsrc, NULL);
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < MAX_CLR; i++)
|
||||
palette(i, Colours_GetR(i), Colours_GetG(i), Colours_GetB(i));
|
||||
IDirectDraw4_CreatePalette(lpDD, DDPCAPS_8BIT, pal, &lpDDPal, NULL);
|
||||
if (lpDDPal)
|
||||
IDirectDrawSurface4_SetPalette(lpDDSPrimary, lpDDPal);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void shutdowndirectdraw(void)
|
||||
{
|
||||
if (lpDD != NULL) {
|
||||
if (lpDDSsrc != NULL) {
|
||||
IDirectDrawSurface4_Release(lpDDSsrc);
|
||||
lpDDSsrc = NULL;
|
||||
}
|
||||
if (lpDDSPrimary != NULL) {
|
||||
IDirectDrawSurface4_Release(lpDDSPrimary);
|
||||
lpDDSPrimary = NULL;
|
||||
}
|
||||
if (lpDDPal != NULL) {
|
||||
IDirectDrawPalette_Release(lpDDPal);
|
||||
lpDDPal = NULL;
|
||||
}
|
||||
IDirectDraw4_Release(lpDD);
|
||||
lpDD = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void refreshv_directdraw(UBYTE *scr_ptr, BOOL bltgfx)
|
||||
{
|
||||
DDSURFACEDESC2 desc0;
|
||||
int err;
|
||||
int x, y;
|
||||
UBYTE *srcb;
|
||||
ULONG *srcl;
|
||||
ULONG *dst;
|
||||
int h, w;
|
||||
DDBLTFX ddbltfx;
|
||||
|
||||
desc0.dwSize = sizeof(desc0);
|
||||
err = IDirectDrawSurface4_Lock(bltgfx ? lpDDSsrc : lpDDSBack,
|
||||
NULL, &desc0, DDLOCK_WRITEONLY | DDLOCK_WAIT ,NULL);
|
||||
if (err == DD_OK) {
|
||||
linesize = desc0.lPitch;
|
||||
scrwidth = desc0.dwWidth;
|
||||
scrheight = desc0.dwHeight;
|
||||
scraddr = (UBYTE *) desc0.lpSurface + (bltgfx ? linesize * 6 : 0);
|
||||
|
||||
if (bltgfx) {
|
||||
for (y = 0; y < Screen_HEIGHT; y++) {
|
||||
dst = (ULONG *) (scraddr + y * linesize);
|
||||
srcb = scr_ptr + y * Screen_WIDTH;
|
||||
for (x = 0; x < scrwidth; x++)
|
||||
*dst++ = Colours_table[*srcb++];
|
||||
}
|
||||
}
|
||||
else {
|
||||
w = (scrwidth - 336) / 2;
|
||||
h = (scrheight - Screen_HEIGHT) / 2;
|
||||
if (w > 0)
|
||||
scraddr += w;
|
||||
else if (w < 0)
|
||||
scr_ptr -= w;
|
||||
if (h > 0)
|
||||
scraddr += linesize * h;
|
||||
for (y = 0; y < Screen_HEIGHT; y++) {
|
||||
dst = (ULONG *) (scraddr + y * linesize);
|
||||
srcl = (ULONG *) (scr_ptr + y * Screen_WIDTH);
|
||||
for (x = (w >= 0) ? (336 >> 2) : (scrwidth >> 2); x > 0; x--)
|
||||
*dst++ = *srcl++;
|
||||
}
|
||||
}
|
||||
|
||||
IDirectDrawSurface4_Unlock(bltgfx ? lpDDSsrc : lpDDSBack, NULL);
|
||||
linesize = 0;
|
||||
scrwidth = 0;
|
||||
scrheight = 0;
|
||||
scraddr = 0;
|
||||
}
|
||||
else if (err == DDERR_SURFACELOST)
|
||||
err = IDirectDrawSurface4_Restore(bltgfx ? lpDDSsrc : lpDDSBack);
|
||||
else {
|
||||
char txt[256];
|
||||
sprintf(txt, "DirectDraw error 0x%x", err);
|
||||
MessageBox(hWndMain, txt, myname, MB_OK);
|
||||
/* printf("error: %x\n", err); */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (bltgfx) {
|
||||
memset(&ddbltfx, 0, sizeof(ddbltfx));
|
||||
ddbltfx.dwSize = sizeof(ddbltfx);
|
||||
err = IDirectDrawSurface4_Blt(lpDDSBack, NULL, lpDDSsrc,
|
||||
NULL, DDBLT_WAIT, &ddbltfx);
|
||||
if (err == DDERR_SURFACELOST)
|
||||
err = IDirectDrawSurface4_Restore(lpDDSBack);
|
||||
}
|
||||
|
||||
#if (SHOWFRAME > 0)
|
||||
palette(0, 0x20, 0x20, 0);
|
||||
palupd(CLR_BACK, 1);
|
||||
#endif
|
||||
err = IDirectDrawSurface4_Flip(lpDDSPrimary, NULL, DDFLIP_WAIT);
|
||||
/* err = IDirectDrawSurface3_Flip(lpDDSPrimary, NULL, 0); */
|
||||
if (err == DDERR_SURFACELOST)
|
||||
err = IDirectDrawSurface4_Restore(lpDDSPrimary);
|
||||
#if (SHOWFRAME > 0)
|
||||
palette(0, 0x0, 0x20, 0x20);
|
||||
palupd(CLR_BACK, 1);
|
||||
#endif
|
||||
#if (SHOWFRAME > 0)
|
||||
palette(0, 0x0, 0x0, 0x0);
|
||||
palupd(CLR_BACK, 1);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef _RENDER_DIRECTDRAW_H_
|
||||
#define _RENDER_DIRECTDRAW_H_
|
||||
|
||||
#include "screen_win32.h"
|
||||
|
||||
int startupdirectdraw(BOOL bltgfx, INT width);
|
||||
void shutdowndirectdraw(void);
|
||||
void refreshv_directdraw(UBYTE *scr_ptr, BOOL bltgfx);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
#include "render_gdi.h"
|
||||
#include "screen_win32.h"
|
||||
#include "colours.h"
|
||||
#include "screen.h"
|
||||
|
||||
extern HWND hWndMain;
|
||||
extern char *myname;
|
||||
|
||||
// GDI specific rendering code
|
||||
void refreshv_gdi(UBYTE *scr_ptr, FRAMEPARAMS *fp)
|
||||
{
|
||||
HDC hCdc;
|
||||
BITMAPINFO bi;
|
||||
HBITMAP hBitmap;
|
||||
DWORD *pixels = NULL;
|
||||
int pixel = 0;
|
||||
int i, x, y;
|
||||
int v_adj = 0;
|
||||
|
||||
// calculate bitmap height & width
|
||||
int bmWidth = fp->view.right - fp->view.left;
|
||||
int bmHeight = fp->view.bottom - fp->view.top;
|
||||
|
||||
bmHeight *= fp->scanlinemode + 1;
|
||||
|
||||
// GDI specific window fill adjustment
|
||||
if (!fp->scanlinemode) {
|
||||
v_adj = (int) fp->height / bmHeight;
|
||||
}
|
||||
|
||||
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bi.bmiHeader.biWidth = bmWidth;
|
||||
bi.bmiHeader.biHeight = bmHeight;
|
||||
bi.bmiHeader.biPlanes = 1;
|
||||
bi.bmiHeader.biBitCount = 32;
|
||||
bi.bmiHeader.biCompression = BI_RGB;
|
||||
bi.bmiHeader.biSizeImage = 0;
|
||||
bi.bmiHeader.biXPelsPerMeter = 0;
|
||||
bi.bmiHeader.biYPelsPerMeter = 0;
|
||||
bi.bmiHeader.biClrUsed = 0;
|
||||
bi.bmiHeader.biClrImportant = 0;
|
||||
|
||||
hCdc = CreateCompatibleDC(fp->hdc);
|
||||
hBitmap = CreateDIBSection(hCdc, &bi, DIB_RGB_COLORS, (void *)&pixels, NULL, 0);
|
||||
if (!hBitmap) {
|
||||
MessageBox(hWndMain, "Could not create bitmap", myname, MB_OK);
|
||||
DestroyWindow(hWndMain);
|
||||
return;
|
||||
}
|
||||
|
||||
// copy screen buffer to the bitmap
|
||||
scr_ptr += fp->view.top * Screen_WIDTH + fp->view.left;
|
||||
for (y = fp->view.top; y < fp->view.bottom; y++) {
|
||||
for (x = fp->view.left; x < fp->view.right; x++) {
|
||||
if (y < 0 || y >= Screen_HEIGHT || x < 0 || x >= Screen_WIDTH)
|
||||
pixels[pixel] = Colours_table[0];
|
||||
else
|
||||
pixels[pixel] = Colours_table[*scr_ptr];
|
||||
|
||||
for (i = 0; i < fp->scanlinemode; i++) {
|
||||
pixels[pixel + i * bmWidth] = pixels[pixel];
|
||||
}
|
||||
|
||||
scr_ptr++;
|
||||
pixel++;
|
||||
}
|
||||
scr_ptr += Screen_WIDTH - bmWidth;
|
||||
pixel += bmWidth * fp->scanlinemode;
|
||||
}
|
||||
|
||||
SelectObject(hCdc, hBitmap);
|
||||
|
||||
// Draw the bitmap on the screen. The image must be flipped vertically
|
||||
if (!StretchBlt(fp->hdc, fp->x_origin, fp->y_origin, fp->width, fp->height + v_adj,
|
||||
hCdc, 0, bi.bmiHeader.biHeight, bi.bmiHeader.biWidth, -bi.bmiHeader.biHeight, SRCCOPY))
|
||||
{
|
||||
MessageBox(hWndMain, "Could not StretchBlt", myname, MB_OK);
|
||||
DestroyWindow(hWndMain);
|
||||
}
|
||||
|
||||
DeleteDC(hCdc);
|
||||
DeleteObject(hBitmap);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef _RENDER_GDI_H_
|
||||
#define _RENDER_GDI_H_
|
||||
|
||||
#include "screen_win32.h"
|
||||
|
||||
void refreshv_gdi(UBYTE *scr_ptr, FRAMEPARAMS *fp);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
#include "config.h"
|
||||
#include "render_gdiplus.h"
|
||||
#include "screen.h"
|
||||
|
||||
// GDI+ used to support interpolated filtering
|
||||
#include <gdiplus.h>
|
||||
using namespace Gdiplus;
|
||||
|
||||
extern "C" {
|
||||
#include "colours.h"
|
||||
}
|
||||
|
||||
// GDI+ startup stuff
|
||||
GdiplusStartupInput gdiplusStartupInput;
|
||||
ULONG_PTR gdiplusToken;
|
||||
// End GDI+ startup stuff
|
||||
|
||||
// Required startup function call for the GDI+ engine
|
||||
extern "C" void startupgdiplus(void)
|
||||
{
|
||||
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
|
||||
}
|
||||
|
||||
// Shutdown the GDI+ engine
|
||||
extern "C" void shutdowngdiplus(void)
|
||||
{
|
||||
GdiplusShutdown(gdiplusToken);
|
||||
}
|
||||
|
||||
// GDI+ specific frame rendering code
|
||||
extern "C" void refreshv_gdiplus(UBYTE *scr_ptr, FRAMEPARAMS *fp)
|
||||
{
|
||||
UINT* pixels;
|
||||
int pixel = 0;
|
||||
int i, x, y;
|
||||
int scanlinelength;
|
||||
InterpolationMode im;
|
||||
int h_adj = 0;
|
||||
int v_adj = 0;
|
||||
|
||||
// calculate bitmap height & width
|
||||
int bmWidth = fp->view.right - fp->view.left;
|
||||
int bmHeight = fp->view.bottom - fp->view.top;
|
||||
|
||||
bmHeight *= fp->scanlinemode + 1;
|
||||
|
||||
// gdiplus specific window fill adjustment
|
||||
if (!fp->scanlinemode) {
|
||||
v_adj = 1;
|
||||
h_adj = 1;
|
||||
}
|
||||
|
||||
// Choose the appropriate interpolation filter
|
||||
switch (fp->filter)
|
||||
{
|
||||
case NEARESTNEIGHBOR:
|
||||
im = InterpolationModeNearestNeighbor;
|
||||
break;
|
||||
case BILINEAR:
|
||||
im = InterpolationModeBilinear;
|
||||
break;
|
||||
case BICUBIC:
|
||||
im = InterpolationModeBicubic;
|
||||
break;
|
||||
case HQBILINEAR:
|
||||
im = InterpolationModeHighQualityBilinear;
|
||||
break;
|
||||
case HQBICUBIC:
|
||||
im = InterpolationModeHighQualityBicubic;
|
||||
break;
|
||||
default:
|
||||
im = InterpolationModeNearestNeighbor;
|
||||
}
|
||||
|
||||
Rect r(0, 0 , bmWidth, bmHeight);
|
||||
|
||||
Bitmap* bitmap = new Bitmap(bmWidth, bmHeight, PixelFormat32bppRGB);
|
||||
|
||||
BitmapData bitmapData;
|
||||
bitmap->LockBits(&r, ImageLockModeWrite, PixelFormat32bppRGB, &bitmapData);
|
||||
pixels = (UINT*)bitmapData.Scan0;
|
||||
scanlinelength = bitmapData.Stride / 4;
|
||||
|
||||
// copy screen buffer to the bitmap
|
||||
scr_ptr += fp->view.top * Screen_WIDTH + fp->view.left;
|
||||
for (y = fp->view.top; y < fp->view.bottom; y++) {
|
||||
for (x = fp->view.left; x < fp->view.right; x++) {
|
||||
if (y < 0 || y >= Screen_HEIGHT || x < 0 || x >= Screen_WIDTH)
|
||||
pixels[pixel] = Colours_table[0];
|
||||
else
|
||||
pixels[pixel] = Colours_table[*scr_ptr];
|
||||
|
||||
for (i = 0; i < fp->scanlinemode; i++) {
|
||||
pixels[pixel + i * scanlinelength] = pixels[pixel];
|
||||
}
|
||||
|
||||
scr_ptr++;
|
||||
pixel++;
|
||||
}
|
||||
scr_ptr += Screen_WIDTH - bmWidth;
|
||||
pixel += scanlinelength * fp->scanlinemode;
|
||||
}
|
||||
|
||||
bitmap->UnlockBits(&bitmapData);
|
||||
|
||||
Graphics* graphics = new Graphics(fp->hdc);
|
||||
graphics->SetInterpolationMode(im);
|
||||
graphics->DrawImage(bitmap, fp->x_origin, fp->y_origin, fp->width + h_adj, fp->height + v_adj);
|
||||
|
||||
delete graphics;
|
||||
delete bitmap;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef _RENDER_GDIPLUS_H_
|
||||
#define _RENDER_GDIPLUS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "screen_win32.h"
|
||||
|
||||
void startupgdiplus(void);
|
||||
void shutdowngdiplus(void);
|
||||
void refreshv_gdiplus(UBYTE *scr_ptr, FRAMEPARAMS *fp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _RENDER_GDIPLUS_H_ */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,143 @@
|
||||
#ifndef _SCREEN_WIN32_H_
|
||||
#define _SCREEN_WIN32_H_
|
||||
|
||||
#include "atari.h"
|
||||
#define SCREENWIDTH 336
|
||||
#define SCREENHEIGHT 240
|
||||
#define CROPPEDWIDTH 320
|
||||
#define STD_CROP 8
|
||||
#define STD_INDENT 24
|
||||
#define CLR_BACK 0x44
|
||||
|
||||
typedef enum CHANGEWINDOWSIZE_ {
|
||||
STEPUP,
|
||||
STEPDOWN,
|
||||
SET,
|
||||
RESET
|
||||
} CHANGEWINDOWSIZE;
|
||||
|
||||
typedef enum TILTLEVEL_ {
|
||||
TILTLEVEL0,
|
||||
TILTLEVEL1,
|
||||
TILTLEVEL2,
|
||||
TILTLEVEL3
|
||||
} TILTLEVEL;
|
||||
|
||||
typedef enum SCANLINEMODE_ {
|
||||
NONE,
|
||||
LOW,
|
||||
MEDIUM,
|
||||
HIGH
|
||||
} SCANLINEMODE;
|
||||
|
||||
typedef enum ASPECTMODE_ {
|
||||
OFF,
|
||||
NORMAL,
|
||||
SIMPLE,
|
||||
ADAPTIVE
|
||||
} ASPECTMODE;
|
||||
|
||||
typedef enum ASPECTRATIO_ {
|
||||
AUTO,
|
||||
WIDE,
|
||||
CROPPED,
|
||||
COMPRESSED
|
||||
} ASPECTRATIO;
|
||||
|
||||
typedef enum RENDERMODE_ {
|
||||
DIRECTDRAW,
|
||||
GDI,
|
||||
GDIPLUS,
|
||||
DIRECT3D
|
||||
} RENDERMODE;
|
||||
|
||||
typedef enum FILTER_ {
|
||||
NEARESTNEIGHBOR,
|
||||
BILINEAR,
|
||||
BICUBIC,
|
||||
HQBILINEAR,
|
||||
HQBICUBIC
|
||||
} FILTER;
|
||||
|
||||
typedef enum DISPLAYMODE_ {
|
||||
GDI_NEARESTNEIGHBOR,
|
||||
GDIPLUS_NEARESTNEIGHBOR,
|
||||
GDIPLUS_BILINEAR,
|
||||
GDIPLUS_HQBILINEAR,
|
||||
GDIPLUS_HQBICUBIC,
|
||||
DIRECT3D_NEARESTNEIGHBOR,
|
||||
DIRECT3D_BILINEAR,
|
||||
GDIPLUS_BICUBIC
|
||||
} DISPLAYMODE;
|
||||
|
||||
typedef enum SCREENMODE_ {
|
||||
FULLSCREEN,
|
||||
WINDOW
|
||||
} SCREENMODE;
|
||||
|
||||
typedef enum FSRESOLUTION_ {
|
||||
DESKTOP, /* Current Desktop Resolution */
|
||||
VGA, /* 4:3 [640x480] (2x) */
|
||||
SXGA, /* 4:3 [1280x960] (4x) */
|
||||
UXGA /* 4:3 [1600x1200] (5x) */
|
||||
} FSRESOLUTION;
|
||||
|
||||
typedef struct FRAMEPARAMS_ {
|
||||
HDC hdc;
|
||||
RECT view; /* viewport frame relative to the screen buffer */
|
||||
int width; /* window width */
|
||||
int height; /* window height */
|
||||
int x_origin; /* x origin within the window */
|
||||
int y_origin; /* y origin within the window */
|
||||
float d3dWidth; /* specialized width for use by direct3d only */
|
||||
float d3dHeight; /* specialized height for use by direct3d only */
|
||||
BOOL d3dRefresh; /* determines whether vertex buffer should be refreshed */
|
||||
SCANLINEMODE scanlinemode; /* scanline mode */
|
||||
FILTER filter; /* render mode filter, i.e. bilinear, etc. */
|
||||
TILTLEVEL tiltlevel; /* level of 3D tilt */
|
||||
BOOL screensaver; /* 3D screensaver on/off */
|
||||
} FRAMEPARAMS;
|
||||
|
||||
typedef struct CROP_ {
|
||||
int horizontal;
|
||||
int vertical;
|
||||
} CROP;
|
||||
|
||||
typedef struct OFFSET_ {
|
||||
int horizontal;
|
||||
int vertical;
|
||||
} OFFSET;
|
||||
|
||||
extern BOOL checkparamarg(char arg[]);
|
||||
|
||||
BOOL getres(char res[], int *width, int *height);
|
||||
int gron(int *argc, char *argv[]);
|
||||
void groff(void);
|
||||
void palupd(int beg, int cnt);
|
||||
void palette(int ent, UBYTE r, UBYTE g, UBYTE b);
|
||||
void refreshv(UBYTE * scr_ptr);
|
||||
void togglewindowstate(void);
|
||||
void changewindowsize(CHANGEWINDOWSIZE, int);
|
||||
void getscaledrect(RECT *rect);
|
||||
void refreshframe(void);
|
||||
void changescanlinemode(void);
|
||||
void togglescreensaver(void);
|
||||
void changetiltlevel(void);
|
||||
void getcenteredcoords(RECT rect, int* x, int* y);
|
||||
void setcursor(void);
|
||||
void destroymenu(void);
|
||||
void initmenu(void);
|
||||
void setmenu(void);
|
||||
void restoremenu(void);
|
||||
void togglemenustate(void);
|
||||
void getnativecoords(int mx, int my, int* nx, int* ny);
|
||||
|
||||
RENDERMODE GetRenderMode(void);
|
||||
DISPLAYMODE GetDisplayMode(void);
|
||||
DISPLAYMODE GetActiveDisplayMode(void);
|
||||
SCREENMODE GetScreenMode(void);
|
||||
|
||||
void SetDisplayMode(DISPLAYMODE dm);
|
||||
void GetDisplayModeName(char *name);
|
||||
|
||||
#endif /* _SCREEN_WIN32_H_ */
|
||||
@@ -0,0 +1,553 @@
|
||||
/*
|
||||
* sound.c - Win32 port specific code
|
||||
*
|
||||
* Copyright (C) 2000 Krzysztof Nikiel
|
||||
* Copyright (C) 2000-2003 Atari800 development team (see DOC/CREDITS)
|
||||
*
|
||||
* This file is part of the Atari800 emulator project which emulates
|
||||
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
|
||||
*
|
||||
* Atari800 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.
|
||||
*
|
||||
* Atari800 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 Atari800; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef SOUND
|
||||
|
||||
#include <windows.h>
|
||||
#ifdef DIRECTX
|
||||
# define DIRECTSOUND_VERSION 0x0500
|
||||
# include <dsound.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "sound.h"
|
||||
#include "main.h"
|
||||
#include "pokeysnd.h"
|
||||
#include "atari.h"
|
||||
#include "log.h"
|
||||
|
||||
#define MIXBUFSIZE 0x1000
|
||||
#define WAVSHIFT 9
|
||||
#define WAVSIZE (1 << WAVSHIFT)
|
||||
int buffers = 0;
|
||||
|
||||
enum {SOUND_NONE, SOUND_DX, SOUND_WAV};
|
||||
|
||||
static int usesound = TRUE;
|
||||
static int issound = SOUND_NONE;
|
||||
static int dsprate = 44100;
|
||||
static int snddelay = 40; /* delay in milliseconds */
|
||||
static int snddelaywav = 100;
|
||||
static int bit16 = FALSE;
|
||||
|
||||
static HANDLE event;
|
||||
static HWAVEOUT wout;
|
||||
static WAVEHDR *waves;
|
||||
|
||||
#ifdef DIRECTX
|
||||
static int wavonly = FALSE;
|
||||
static DWORD sbufsize = 0;
|
||||
static int samples = 0; /* #samples to be in play buffer */
|
||||
static UBYTE mixbuf[MIXBUFSIZE];
|
||||
static DWORD bufpos = 0;
|
||||
|
||||
static LPDIRECTSOUND lpDS = NULL;
|
||||
static LPDIRECTSOUNDBUFFER pDSB = NULL;
|
||||
|
||||
static int initsound_dx(void)
|
||||
{
|
||||
DWORD i;
|
||||
int err;
|
||||
DSBUFFERDESC dsBD =
|
||||
{0};
|
||||
WAVEFORMATEX wfx;
|
||||
DSBCAPS bc;
|
||||
|
||||
LPVOID pMem1, pMem2;
|
||||
DWORD dwSize1, dwSize2;
|
||||
|
||||
if (issound != SOUND_NONE)
|
||||
return 0;
|
||||
|
||||
if ((err = DirectSoundCreate(NULL, &lpDS, NULL)) < 0)
|
||||
return err;
|
||||
if ((err = IDirectSound_SetCooperativeLevel(lpDS, hWndMain,
|
||||
DSSCL_EXCLUSIVE)) < 0)
|
||||
goto end;
|
||||
|
||||
dsBD.dwSize = sizeof(dsBD);
|
||||
dsBD.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
|
||||
dsBD.dwBufferBytes = 0x4000;
|
||||
dsBD.lpwfxFormat = &wfx;
|
||||
|
||||
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||
#ifdef STEREO_SOUND
|
||||
wfx.nChannels = POKEYSND_stereo_enabled ? 2 : 1;
|
||||
#else
|
||||
wfx.nChannels = 1;
|
||||
#endif /* STEREO_SOUND */
|
||||
wfx.nSamplesPerSec = dsprate;
|
||||
wfx.nAvgBytesPerSec = dsprate * wfx.nChannels * (bit16 ? 2 : 1);
|
||||
wfx.nBlockAlign = wfx.nChannels * (bit16 ? 2 : 1);
|
||||
wfx.wBitsPerSample = bit16 ? 16 : 8;
|
||||
wfx.cbSize = 0;
|
||||
|
||||
if ((err = IDirectSound_CreateSoundBuffer(lpDS, &dsBD, &pDSB, NULL)) < 0)
|
||||
goto end;
|
||||
|
||||
bc.dwSize = sizeof(bc);
|
||||
IDirectSoundBuffer_GetCaps(pDSB, &bc);
|
||||
sbufsize = bc.dwBufferBytes;
|
||||
|
||||
if ((err = IDirectSoundBuffer_Lock(pDSB, 0, sbufsize,
|
||||
&pMem1, &dwSize1, &pMem2, &dwSize2,
|
||||
DSBLOCK_FROMWRITECURSOR)) < 0)
|
||||
goto end;
|
||||
|
||||
for (i = 0; i < dwSize1 >> 1; i++)
|
||||
*((short *) pMem1 + i) = 0;
|
||||
for (i = 0; i < dwSize2 >> 1; i++)
|
||||
*((short *) pMem2 + i) = 0;
|
||||
IDirectSoundBuffer_Unlock(pDSB, pMem1, dwSize1, pMem2, dwSize2);
|
||||
|
||||
IDirectSoundBuffer_Play(pDSB, 0, 0, DSBPLAY_LOOPING);
|
||||
|
||||
POKEYSND_Init(POKEYSND_FREQ_17_EXACT, (UWORD) dsprate, (UBYTE) wfx.nChannels, (bit16 ? POKEYSND_BIT16 : 0));
|
||||
|
||||
samples = dsprate * snddelay / 1000;
|
||||
|
||||
IDirectSoundBuffer_GetCurrentPosition(pDSB, 0, &bufpos);
|
||||
|
||||
issound = SOUND_DX;
|
||||
return 0;
|
||||
|
||||
end:
|
||||
MessageBox(hWndMain, "DirectSound Init FAILED", myname, MB_OK);
|
||||
Sound_Exit();
|
||||
return err;
|
||||
}
|
||||
|
||||
static void uninitsound_dx(void)
|
||||
{
|
||||
if (issound != SOUND_DX)
|
||||
return;
|
||||
|
||||
if (lpDS)
|
||||
{
|
||||
if (pDSB)
|
||||
{
|
||||
IDirectSoundBuffer_Stop(pDSB);
|
||||
IDirectSoundBuffer_Release(pDSB);
|
||||
pDSB = NULL;
|
||||
}
|
||||
IDirectSound_Release(lpDS);
|
||||
lpDS = NULL;
|
||||
}
|
||||
issound = SOUND_NONE;
|
||||
}
|
||||
|
||||
static void sound_update_dx(void)
|
||||
{
|
||||
DWORD wc;
|
||||
int d1;
|
||||
LPVOID pMem1, pMem2;
|
||||
DWORD dwSize1, dwSize2;
|
||||
signed short *p1s;
|
||||
signed short *p2s;
|
||||
UBYTE *p1b;
|
||||
UBYTE *p2b;
|
||||
signed short *pbufs;
|
||||
UBYTE *pbufb;
|
||||
int s1, s2;
|
||||
int err;
|
||||
int i;
|
||||
int samplesize = bit16 ? 2 : 1;
|
||||
|
||||
#ifdef STEREO_SOUND
|
||||
if (POKEYSND_stereo_enabled) samplesize *= 2;
|
||||
#endif
|
||||
|
||||
if (issound != SOUND_DX)
|
||||
return;
|
||||
|
||||
IDirectSoundBuffer_GetCurrentPosition(pDSB, 0, &wc);
|
||||
|
||||
d1 = (wc - bufpos);
|
||||
if ((DWORD) abs(d1) > (sbufsize >> 1)) {
|
||||
if (d1 < 0)
|
||||
d1 += sbufsize;
|
||||
else
|
||||
d1 -= sbufsize;
|
||||
}
|
||||
if (d1 < (-samples * samplesize)) // there is more than necessary bytes filled?
|
||||
return;
|
||||
|
||||
d1 = (samples * samplesize) + d1; // bytes to fill
|
||||
d1 = (d1 / samplesize) * samplesize; //round to a sample pair
|
||||
|
||||
if (d1 > (sizeof(mixbuf) / sizeof(mixbuf[0])))
|
||||
{
|
||||
d1 = (sizeof(mixbuf) / sizeof(mixbuf[0]));
|
||||
}
|
||||
|
||||
if ((err = IDirectSoundBuffer_Lock(pDSB,
|
||||
bufpos,
|
||||
d1,
|
||||
&pMem1, &dwSize1,
|
||||
&pMem2, &dwSize2,
|
||||
0)) < 0)
|
||||
{
|
||||
if (err == DSERR_BUFFERLOST)
|
||||
Sound_Continue();
|
||||
return;
|
||||
}
|
||||
|
||||
s1 = dwSize1;
|
||||
s2 = dwSize2;
|
||||
p1s = (signed short *)pMem1;
|
||||
p2s = (signed short *)pMem2;
|
||||
p1b = (UBYTE *)pMem1;
|
||||
p2b = (UBYTE *)pMem2;
|
||||
bufpos += (s1 + s2);
|
||||
if (bufpos >= sbufsize)
|
||||
bufpos -= sbufsize;
|
||||
|
||||
if (bit16)
|
||||
{
|
||||
s1 /= 2;
|
||||
s2 /= 2;
|
||||
}
|
||||
i = s1 + s2;
|
||||
|
||||
POKEYSND_Process(mixbuf, i);
|
||||
|
||||
pbufs = (signed short *)mixbuf;
|
||||
pbufb = (UBYTE *)mixbuf;
|
||||
if (s1)
|
||||
{
|
||||
if (bit16)
|
||||
for (; s1; s1--)
|
||||
*p1s++ = *pbufs++;
|
||||
else
|
||||
for (; s1; s1--)
|
||||
*p1b++ = *pbufb++;
|
||||
}
|
||||
if (s2)
|
||||
{
|
||||
if (bit16)
|
||||
for (; s2; s2--)
|
||||
*p2s++ = *pbufs++;
|
||||
else
|
||||
for (; s2; s2--)
|
||||
*p2b++ = *pbufb++;
|
||||
}
|
||||
|
||||
IDirectSoundBuffer_Unlock(pDSB, pMem1, dwSize1, pMem2, dwSize2);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* DIRECTX */
|
||||
|
||||
static void uninitsound_wav(void)
|
||||
{
|
||||
int i;
|
||||
MMRESULT err;
|
||||
|
||||
if (issound != SOUND_WAV)
|
||||
return;
|
||||
|
||||
l0:
|
||||
for (i = 0; i < buffers; i++)
|
||||
{
|
||||
if (!(waves[i].dwFlags & WHDR_DONE))
|
||||
{
|
||||
WaitForSingleObject(event, 5000);
|
||||
ResetEvent(event);
|
||||
goto l0;
|
||||
}
|
||||
}
|
||||
|
||||
waveOutReset (wout);
|
||||
|
||||
for (i = 0; i < buffers; i++)
|
||||
{
|
||||
err = waveOutUnprepareHeader(wout, &waves[i], sizeof (waves[i]));
|
||||
if (err != MMSYSERR_NOERROR)
|
||||
{
|
||||
fprintf(stderr, "warning: cannot unprepare wave header (%x)\n", err);
|
||||
}
|
||||
free(waves[i].lpData);
|
||||
}
|
||||
free(waves);
|
||||
|
||||
waveOutClose(wout);
|
||||
CloseHandle(event);
|
||||
|
||||
issound = SOUND_NONE;
|
||||
}
|
||||
|
||||
static int initsound_wav(void)
|
||||
{
|
||||
int i;
|
||||
WAVEFORMATEX wfx;
|
||||
MMRESULT err;
|
||||
|
||||
event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
memset(&wfx, 0, sizeof(wfx));
|
||||
|
||||
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||
#ifdef STEREO_SOUND
|
||||
wfx.nChannels = POKEYSND_stereo_enabled ? 2 : 1;
|
||||
#else
|
||||
wfx.nChannels = 1;
|
||||
#endif /* STEREO_SOUND */
|
||||
wfx.nSamplesPerSec = dsprate;
|
||||
wfx.nAvgBytesPerSec = dsprate * wfx.nChannels * (bit16 ? 2 : 1);
|
||||
wfx.nBlockAlign = wfx.nChannels * (bit16 ? 2 : 1);
|
||||
wfx.wBitsPerSample = bit16 ? 16 : 8;
|
||||
wfx.cbSize = 0;
|
||||
|
||||
err = waveOutOpen(&wout, WAVE_MAPPER, &wfx, (int)event, 0, CALLBACK_EVENT);
|
||||
if (err == WAVERR_BADFORMAT)
|
||||
{
|
||||
Log_print("wave output parameters unsupported\n");
|
||||
exit(1);
|
||||
}
|
||||
if (err != MMSYSERR_NOERROR)
|
||||
{
|
||||
Log_print("cannot open wave output (%x)\n", err);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
buffers = ((wfx.nAvgBytesPerSec * snddelaywav / 1000) >> WAVSHIFT) + 1;
|
||||
waves = (WAVEHDR *)malloc(buffers * sizeof(*waves));
|
||||
for (i = 0; i < buffers; i++)
|
||||
{
|
||||
memset(&waves[i], 0, sizeof (waves[i]));
|
||||
if (!(waves[i].lpData = (LPSTR)malloc(WAVSIZE)))
|
||||
{
|
||||
Log_print("could not get wave buffer memory\n");
|
||||
exit(1);
|
||||
}
|
||||
waves[i].dwBufferLength = WAVSIZE;
|
||||
err = waveOutPrepareHeader(wout, &waves[i], sizeof(waves[i]));
|
||||
if (err != MMSYSERR_NOERROR)
|
||||
{
|
||||
Log_print("cannot prepare wave header (%x)\n", err);
|
||||
exit(1);
|
||||
}
|
||||
waves[i].dwFlags |= WHDR_DONE;
|
||||
}
|
||||
|
||||
POKEYSND_Init(POKEYSND_FREQ_17_EXACT, (UWORD) dsprate, (UBYTE) wfx.nChannels, (bit16 ? POKEYSND_BIT16 : 0));
|
||||
|
||||
issound = SOUND_WAV;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Sound_Initialise(int *argc, char *argv[])
|
||||
{
|
||||
int i, j;
|
||||
int help = FALSE;
|
||||
|
||||
if (issound != SOUND_NONE)
|
||||
return TRUE;
|
||||
|
||||
for (i = j = 1; i < *argc; i++)
|
||||
{
|
||||
int i_a = (i + 1 < *argc); /* is argument available? */
|
||||
int a_m = FALSE; /* error, argument missing! */
|
||||
|
||||
if (strcmp(argv[i], "-sound") == 0)
|
||||
usesound = TRUE;
|
||||
else if (strcmp(argv[i], "-nosound") == 0)
|
||||
usesound = FALSE;
|
||||
else if (strcmp(argv[i], "-audio16") == 0)
|
||||
bit16 = TRUE;
|
||||
else if (strcmp(argv[i], "-dsprate") == 0)
|
||||
{
|
||||
if (i_a)
|
||||
sscanf(argv[++i], "%d", &dsprate);
|
||||
else a_m = TRUE;
|
||||
}
|
||||
else if (strcmp(argv[i], "-snddelay") == 0)
|
||||
{
|
||||
if (i_a)
|
||||
{
|
||||
sscanf(argv[++i], "%d", &snddelay);
|
||||
snddelaywav = snddelay;
|
||||
}
|
||||
else a_m = TRUE;
|
||||
}
|
||||
else if (strcmp(argv[i], "-quality") == 0) {
|
||||
if (i_a) {
|
||||
int quality;
|
||||
sscanf(argv[++i], "%d", &quality);
|
||||
if (quality > 1) {
|
||||
POKEYSND_SetMzQuality(quality - 1);
|
||||
POKEYSND_enable_new_pokey = 1;
|
||||
}
|
||||
else
|
||||
POKEYSND_enable_new_pokey = 0;
|
||||
}
|
||||
else a_m = TRUE;
|
||||
}
|
||||
#ifdef DIRECTX
|
||||
else if (strcmp(argv[i], "-wavonly") == 0)
|
||||
wavonly = TRUE;
|
||||
#endif
|
||||
else
|
||||
{
|
||||
if (strcmp(argv[i], "-help") == 0)
|
||||
{
|
||||
Log_print("\t-sound Enable sound\n"
|
||||
"\t-nosound Disable sound\n"
|
||||
#ifdef DIRECTX
|
||||
"\t-wavonly Disable direct sound\n"
|
||||
#endif
|
||||
"\t-dsprate <rate> Set dsp rate\n"
|
||||
"\t-snddelay <ms> Set sound delay\n"
|
||||
"\t-audio16 Use 16 bit mixing\n"
|
||||
"\t-quality <level> Set sound quality"
|
||||
);
|
||||
help = TRUE;
|
||||
}
|
||||
argv[j++] = argv[i];
|
||||
}
|
||||
|
||||
if (a_m) {
|
||||
Log_print("Missing argument for '%s'", argv[i]);
|
||||
usesound = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
*argc = j;
|
||||
|
||||
if (help || !usesound) {
|
||||
usesound = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef DIRECTX
|
||||
if (!wavonly)
|
||||
{
|
||||
i = initsound_dx();
|
||||
if (!i)
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
initsound_wav();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void Sound_Reinit(void)
|
||||
{
|
||||
if (usesound)
|
||||
{
|
||||
Sound_Exit();
|
||||
#ifdef DIRECTX
|
||||
if (!wavonly)
|
||||
{
|
||||
int i = initsound_dx();
|
||||
if (!i)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
initsound_wav();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void Sound_Exit(void)
|
||||
{
|
||||
#ifdef DIRECTX
|
||||
if (issound == SOUND_DX)
|
||||
uninitsound_dx();
|
||||
#endif
|
||||
if (issound == SOUND_WAV)
|
||||
uninitsound_wav();
|
||||
|
||||
issound = SOUND_NONE;
|
||||
}
|
||||
|
||||
static WAVEHDR *getwave(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < buffers; i++)
|
||||
{
|
||||
if (waves[i].dwFlags & WHDR_DONE)
|
||||
{
|
||||
waves[i].dwFlags &= ~WHDR_DONE;
|
||||
return &waves[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Sound_Update(void)
|
||||
{
|
||||
MMRESULT err;
|
||||
WAVEHDR *wh;
|
||||
|
||||
switch (issound)
|
||||
{
|
||||
case SOUND_WAV:
|
||||
while ((wh = getwave()))
|
||||
{
|
||||
POKEYSND_Process(wh->lpData, wh->dwBufferLength >> (bit16 ? 1 : 0));
|
||||
err = waveOutWrite(wout, wh, sizeof(*wh));
|
||||
if (err != MMSYSERR_NOERROR)
|
||||
{
|
||||
Log_print("cannot write wave output (%x)\n", err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#ifdef DIRECTX
|
||||
case SOUND_DX:
|
||||
sound_update_dx();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Sound_Pause(void)
|
||||
{
|
||||
#ifdef DIRECTX
|
||||
if (issound != SOUND_DX)
|
||||
return;
|
||||
if (!pDSB)
|
||||
return;
|
||||
IDirectSoundBuffer_Stop(pDSB);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Sound_Continue(void)
|
||||
{
|
||||
#ifdef DIRECTX
|
||||
if (issound != SOUND_DX)
|
||||
return;
|
||||
if (!pDSB)
|
||||
return;
|
||||
IDirectSoundBuffer_Restore(pDSB);
|
||||
IDirectSoundBuffer_Play(pDSB, 0, 0, DSBPLAY_LOOPING);
|
||||
IDirectSoundBuffer_GetCurrentPosition(pDSB, 0, &bufpos);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* SOUND */
|
||||
Reference in New Issue
Block a user