mirror of
https://github.com/holub/mame
synced 2025-06-29 23:48:56 +03:00
osd: Cleaned up Windows API usage a little.
* Bumped target windows version to 6.0.0 (Vista). * Use WRL COM pointers to manage some COM-like objects. * Cleaned up logging in DirectSound module. * Cleaned up includes in Windows input modules. * Switched to Common Item Dialogs in Windows debugger. * Replaced disabled code that never really worked with a TODO comment.
This commit is contained in:
parent
362201a23b
commit
9ce44fa048
@ -29,12 +29,13 @@ function maintargetosdoptions(_target,_subtarget)
|
|||||||
end
|
end
|
||||||
|
|
||||||
links {
|
links {
|
||||||
"dinput8",
|
|
||||||
"comctl32",
|
"comctl32",
|
||||||
"comdlg32",
|
"comdlg32",
|
||||||
"psapi",
|
"dinput8",
|
||||||
"ole32",
|
"ole32",
|
||||||
|
"psapi",
|
||||||
"shlwapi",
|
"shlwapi",
|
||||||
|
"uuid",
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -33,7 +33,8 @@ if _OPTIONS["MODERN_WIN_API"]=="1" then
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
defines {
|
defines {
|
||||||
"_WIN32_WINNT=0x0501",
|
"_WIN32_WINNT=0x0600",
|
||||||
|
"NTDDI_VERSION=0x06000000",
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -12,15 +12,196 @@
|
|||||||
#include "debugviewinfo.h"
|
#include "debugviewinfo.h"
|
||||||
#include "uimetrics.h"
|
#include "uimetrics.h"
|
||||||
|
|
||||||
#include "debugger.h"
|
// emu
|
||||||
#include "debug/debugcon.h"
|
#include "debug/debugcon.h"
|
||||||
|
#include "debugger.h"
|
||||||
|
#include "image.h"
|
||||||
|
#include "softlist_dev.h"
|
||||||
#include "debug/debugcpu.h"
|
#include "debug/debugcpu.h"
|
||||||
|
|
||||||
|
// devices
|
||||||
#include "imagedev/cassette.h"
|
#include "imagedev/cassette.h"
|
||||||
|
|
||||||
#include "strconv.h"
|
// osd/windows
|
||||||
#include "winutf8.h"
|
#include "winutf8.h"
|
||||||
|
|
||||||
#include "softlist_dev.h"
|
// osd
|
||||||
|
#include "strconv.h"
|
||||||
|
|
||||||
|
// C++
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Windows
|
||||||
|
#include <commctrl.h>
|
||||||
|
#include <shlobj.h>
|
||||||
|
#include <shobjidl.h>
|
||||||
|
#include <shtypes.h>
|
||||||
|
#include <wrl/client.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class comdlg_filter_helper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
comdlg_filter_helper(comdlg_filter_helper const &) = delete;
|
||||||
|
comdlg_filter_helper &operator=(comdlg_filter_helper const &) = delete;
|
||||||
|
|
||||||
|
comdlg_filter_helper(device_image_interface &device, bool include_archives)
|
||||||
|
{
|
||||||
|
m_count = 0U;
|
||||||
|
|
||||||
|
std::wstring const extensions = osd::text::to_wstring(device.file_extensions());
|
||||||
|
std::wstring_view extview = extensions;
|
||||||
|
m_description = L"Media Image Files (";
|
||||||
|
for (auto comma = extview.find(','); !extview.empty(); comma = extview.find(','))
|
||||||
|
{
|
||||||
|
bool const found = std::wstring_view::npos != comma;
|
||||||
|
std::wstring_view const ext = found ? extview.substr(0, comma) : extview;
|
||||||
|
extview.remove_prefix(found ? (comma + 1) : extview.length());
|
||||||
|
if (m_extensions.empty())
|
||||||
|
{
|
||||||
|
m_default = ext;
|
||||||
|
m_description.append(L"*.");
|
||||||
|
m_extensions.append(L"*.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_description.append(L"; *.");
|
||||||
|
m_extensions.append(L";*.");
|
||||||
|
}
|
||||||
|
m_description.append(ext);
|
||||||
|
m_extensions.append(ext);
|
||||||
|
}
|
||||||
|
m_description.append(1, L')');
|
||||||
|
m_specs[m_count].pszName = m_description.c_str();
|
||||||
|
m_specs[m_count].pszSpec = m_extensions.c_str();
|
||||||
|
++m_count;
|
||||||
|
|
||||||
|
if (include_archives)
|
||||||
|
{
|
||||||
|
m_specs[m_count].pszName = L"Archive Files (*.zip; *.7z)";
|
||||||
|
m_specs[m_count].pszSpec = L"*.zip;*.7z";
|
||||||
|
++m_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_specs[m_count].pszName = L"All Files (*.*)";
|
||||||
|
m_specs[m_count].pszSpec = L"*.*";
|
||||||
|
++m_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT file_types() const noexcept
|
||||||
|
{
|
||||||
|
return m_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
COMDLG_FILTERSPEC const *filter_spec() const noexcept
|
||||||
|
{
|
||||||
|
return m_specs;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPCWSTR default_extension() const noexcept
|
||||||
|
{
|
||||||
|
return m_default.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
COMDLG_FILTERSPEC m_specs[3];
|
||||||
|
std::wstring m_description;
|
||||||
|
std::wstring m_extensions;
|
||||||
|
std::wstring m_default;
|
||||||
|
UINT m_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void choose_image(device_image_interface &device, HWND owner, REFCLSID class_id, bool allow_archives, T &&handler)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
// create file dialog
|
||||||
|
Microsoft::WRL::ComPtr<IFileDialog> dialog;
|
||||||
|
hr = CoCreateInstance(class_id, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(dialog.GetAddressOf()));
|
||||||
|
|
||||||
|
// set file types
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
DWORD flags;
|
||||||
|
hr = dialog->GetOptions(&flags);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
hr = dialog->SetOptions(flags | FOS_NOCHANGEDIR | FOS_FORCEFILESYSTEM);
|
||||||
|
comdlg_filter_helper filters(device, allow_archives);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
hr = dialog->SetFileTypes(filters.file_types(), filters.filter_spec());
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
hr = dialog->SetFileTypeIndex(1);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
hr = dialog->SetDefaultExtension(filters.default_extension());
|
||||||
|
}
|
||||||
|
|
||||||
|
// set starting folder
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
std::string dir = device.working_directory();
|
||||||
|
if (dir.empty())
|
||||||
|
{
|
||||||
|
dir = device.device().machine().image().setup_working_directory();
|
||||||
|
device.set_working_directory(dir);
|
||||||
|
}
|
||||||
|
std::string full;
|
||||||
|
if (!dir.empty() && !osd_get_full_path(full, dir))
|
||||||
|
{
|
||||||
|
// FIXME: strip off archive names - opening a file inside an archive decompresses it to a temporary location
|
||||||
|
std::wstring wfull = osd::text::to_wstring(full);
|
||||||
|
Microsoft::WRL::ComPtr<IShellItem> item;
|
||||||
|
if (SUCCEEDED(SHCreateItemFromParsingName(wfull.c_str(), nullptr, IID_PPV_ARGS(item.GetAddressOf()))))
|
||||||
|
{
|
||||||
|
//dialog->SetFolder(item); disabled until
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// show the dialog
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = dialog->Show(owner);
|
||||||
|
if (HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
Microsoft::WRL::ComPtr<IShellItem> result;
|
||||||
|
hr = dialog->GetResult(result.GetAddressOf());
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
PWSTR selection = nullptr;
|
||||||
|
hr = result->GetDisplayName(SIGDN_FILESYSPATH, &selection);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
std::string const utf_selection = osd::text::from_wstring(selection);
|
||||||
|
CoTaskMemFree(selection);
|
||||||
|
handler(utf_selection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
int pressed;
|
||||||
|
TaskDialog(
|
||||||
|
owner,
|
||||||
|
nullptr, // instance
|
||||||
|
nullptr, // title
|
||||||
|
L"Error showing file dialog",
|
||||||
|
nullptr, // content
|
||||||
|
TDCBF_OK_BUTTON,
|
||||||
|
TD_ERROR_ICON,
|
||||||
|
&pressed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
consolewin_info::consolewin_info(debugger_windows_interface &debugger) :
|
consolewin_info::consolewin_info(debugger_windows_interface &debugger) :
|
||||||
@ -186,8 +367,8 @@ void consolewin_info::update_menu()
|
|||||||
if (img.is_readonly())
|
if (img.is_readonly())
|
||||||
flags_for_writing |= MF_GRAYED;
|
flags_for_writing |= MF_GRAYED;
|
||||||
|
|
||||||
// not working properly, removed for now until investigation can be done
|
// FIXME: needs a real software item picker to be useful
|
||||||
//if (get_softlist_info(&img))
|
//if (get_softlist_info(img))
|
||||||
// AppendMenu(devicesubmenu, MF_STRING, new_item + DEVOPTION_ITEM, TEXT("Mount Item..."));
|
// AppendMenu(devicesubmenu, MF_STRING, new_item + DEVOPTION_ITEM, TEXT("Mount Item..."));
|
||||||
|
|
||||||
AppendMenu(devicesubmenu, MF_STRING, new_item + DEVOPTION_OPEN, TEXT("Mount File..."));
|
AppendMenu(devicesubmenu, MF_STRING, new_item + DEVOPTION_OPEN, TEXT("Mount File..."));
|
||||||
@ -265,179 +446,14 @@ bool consolewin_info::handle_command(WPARAM wparam, LPARAM lparam)
|
|||||||
{
|
{
|
||||||
switch ((LOWORD(wparam) - ID_DEVICE_OPTIONS) % DEVOPTION_MAX)
|
switch ((LOWORD(wparam) - ID_DEVICE_OPTIONS) % DEVOPTION_MAX)
|
||||||
{
|
{
|
||||||
case DEVOPTION_ITEM :
|
case DEVOPTION_ITEM:
|
||||||
{
|
// TODO: this is supposed to show a software list item picker - it never worked properly
|
||||||
std::string filter;
|
|
||||||
build_generic_filter(nullptr, false, filter);
|
|
||||||
{
|
|
||||||
osd::text::tstring t_filter = osd::text::to_tstring(filter);
|
|
||||||
|
|
||||||
// convert a pipe-char delimited string into a NUL delimited string
|
|
||||||
for (int i = 0; t_filter[i] != '\0'; i++)
|
|
||||||
{
|
|
||||||
if (t_filter[i] == '|')
|
|
||||||
t_filter[i] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string opt_name = img->instance_name();
|
|
||||||
std::string as = slmap.find(opt_name)->second;
|
|
||||||
|
|
||||||
/* Make sure a folder was specified, and that it exists */
|
|
||||||
if ((!osd::directory::open(as)) || (as.find(':') == std::string::npos))
|
|
||||||
{
|
|
||||||
/* Default to emu directory */
|
|
||||||
osd_get_full_path(as, ".");
|
|
||||||
}
|
|
||||||
osd::text::tstring t_dir = osd::text::to_tstring(as);
|
|
||||||
|
|
||||||
// display the dialog
|
|
||||||
TCHAR selectedFilename[MAX_PATH];
|
|
||||||
selectedFilename[0] = '\0';
|
|
||||||
OPENFILENAME ofn;
|
|
||||||
memset(&ofn, 0, sizeof(ofn));
|
|
||||||
ofn.lStructSize = sizeof(ofn);
|
|
||||||
ofn.hwndOwner = nullptr;
|
|
||||||
ofn.lpstrFile = selectedFilename;
|
|
||||||
ofn.lpstrFile[0] = '\0';
|
|
||||||
ofn.nMaxFile = MAX_PATH;
|
|
||||||
ofn.lpstrFilter = t_filter.c_str();
|
|
||||||
ofn.nFilterIndex = 1;
|
|
||||||
ofn.lpstrFileTitle = nullptr;
|
|
||||||
ofn.nMaxFileTitle = 0;
|
|
||||||
ofn.lpstrInitialDir = t_dir.c_str();
|
|
||||||
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
|
|
||||||
|
|
||||||
if (GetOpenFileName(&ofn))
|
|
||||||
{
|
|
||||||
std::string buf = std::string(osd::text::from_tstring(selectedFilename));
|
|
||||||
// Get the Item name out of the full path
|
|
||||||
size_t t1 = buf.find(".zip"); // get rid of zip name and anything after
|
|
||||||
if (t1 != std::string::npos)
|
|
||||||
buf.erase(t1);
|
|
||||||
t1 = buf.find(".7z"); // get rid of 7zip name and anything after
|
|
||||||
if (t1 != std::string::npos)
|
|
||||||
buf.erase(t1);
|
|
||||||
t1 = buf.find_last_of("\\"); // put the swlist name in
|
|
||||||
buf[t1] = ':';
|
|
||||||
t1 = buf.find_last_of("\\"); // get rid of path; we only want the item name
|
|
||||||
buf.erase(0, t1+1);
|
|
||||||
|
|
||||||
// load software
|
|
||||||
img->load_software(buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
case DEVOPTION_OPEN :
|
case DEVOPTION_OPEN :
|
||||||
{
|
open_image_file(*img);
|
||||||
std::string filter;
|
|
||||||
build_generic_filter(img, false, filter);
|
|
||||||
{
|
|
||||||
osd::text::tstring t_filter = osd::text::to_tstring(filter);
|
|
||||||
|
|
||||||
// convert a pipe-char delimited string into a NUL delimited string
|
|
||||||
for (int i = 0; t_filter[i] != '\0'; i++)
|
|
||||||
{
|
|
||||||
if (t_filter[i] == '|')
|
|
||||||
t_filter[i] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
char buf[400];
|
|
||||||
std::string as;
|
|
||||||
strcpy(buf, machine().options().emu_options::sw_path());
|
|
||||||
// This pulls out the first path from a multipath field
|
|
||||||
const char* t1 = strtok(buf, ";");
|
|
||||||
if (t1)
|
|
||||||
as = t1; // the first path of many
|
|
||||||
else
|
|
||||||
as = buf; // the only path
|
|
||||||
|
|
||||||
/* Make sure a folder was specified, and that it exists */
|
|
||||||
if ((!osd::directory::open(as)) || (as.find(':') == std::string::npos))
|
|
||||||
{
|
|
||||||
/* Default to emu directory */
|
|
||||||
osd_get_full_path(as, ".");
|
|
||||||
}
|
|
||||||
osd::text::tstring t_dir = osd::text::to_tstring(as);
|
|
||||||
|
|
||||||
TCHAR selectedFilename[MAX_PATH];
|
|
||||||
selectedFilename[0] = '\0';
|
|
||||||
OPENFILENAME ofn;
|
|
||||||
memset(&ofn, 0, sizeof(ofn));
|
|
||||||
ofn.lStructSize = sizeof(ofn);
|
|
||||||
ofn.hwndOwner = nullptr;
|
|
||||||
ofn.lpstrFile = selectedFilename;
|
|
||||||
ofn.lpstrFile[0] = '\0';
|
|
||||||
ofn.nMaxFile = MAX_PATH;
|
|
||||||
ofn.lpstrFilter = t_filter.c_str();
|
|
||||||
ofn.nFilterIndex = 1;
|
|
||||||
ofn.lpstrFileTitle = nullptr;
|
|
||||||
ofn.nMaxFileTitle = 0;
|
|
||||||
ofn.lpstrInitialDir = t_dir.c_str();
|
|
||||||
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
|
|
||||||
|
|
||||||
if (GetOpenFileName(&ofn))
|
|
||||||
{
|
|
||||||
auto utf8_buf = osd::text::from_tstring(selectedFilename);
|
|
||||||
img->load(utf8_buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
case DEVOPTION_CREATE:
|
case DEVOPTION_CREATE:
|
||||||
{
|
create_image_file(*img);
|
||||||
std::string filter;
|
|
||||||
build_generic_filter(img, true, filter);
|
|
||||||
{
|
|
||||||
osd::text::tstring t_filter = osd::text::to_tstring(filter);
|
|
||||||
// convert a pipe-char delimited string into a NUL delimited string
|
|
||||||
for (int i = 0; t_filter[i] != '\0'; i++)
|
|
||||||
{
|
|
||||||
if (t_filter[i] == '|')
|
|
||||||
t_filter[i] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
char buf[400];
|
|
||||||
std::string as;
|
|
||||||
strcpy(buf, machine().options().emu_options::sw_path());
|
|
||||||
// This pulls out the first path from a multipath field
|
|
||||||
const char* t1 = strtok(buf, ";");
|
|
||||||
if (t1)
|
|
||||||
as = t1; // the first path of many
|
|
||||||
else
|
|
||||||
as = buf; // the only path
|
|
||||||
|
|
||||||
/* Make sure a folder was specified, and that it exists */
|
|
||||||
if ((!osd::directory::open(as)) || (as.find(':') == std::string::npos))
|
|
||||||
{
|
|
||||||
/* Default to emu directory */
|
|
||||||
osd_get_full_path(as, ".");
|
|
||||||
}
|
|
||||||
osd::text::tstring t_dir = osd::text::to_tstring(as);
|
|
||||||
|
|
||||||
TCHAR selectedFilename[MAX_PATH];
|
|
||||||
selectedFilename[0] = '\0';
|
|
||||||
OPENFILENAME ofn;
|
|
||||||
memset(&ofn, 0, sizeof(ofn));
|
|
||||||
ofn.lStructSize = sizeof(ofn);
|
|
||||||
ofn.hwndOwner = nullptr;
|
|
||||||
ofn.lpstrFile = selectedFilename;
|
|
||||||
ofn.lpstrFile[0] = '\0';
|
|
||||||
ofn.nMaxFile = MAX_PATH;
|
|
||||||
ofn.lpstrFilter = t_filter.c_str();
|
|
||||||
ofn.nFilterIndex = 1;
|
|
||||||
ofn.lpstrFileTitle = nullptr;
|
|
||||||
ofn.nMaxFileTitle = 0;
|
|
||||||
ofn.lpstrInitialDir = t_dir.c_str();
|
|
||||||
ofn.Flags = OFN_PATHMUSTEXIST;
|
|
||||||
|
|
||||||
if (GetSaveFileName(&ofn))
|
|
||||||
{
|
|
||||||
auto utf8_buf = osd::text::from_tstring(selectedFilename);
|
|
||||||
img->create(utf8_buf, img->device_get_indexed_creatable_format(0), nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
case DEVOPTION_CLOSE:
|
case DEVOPTION_CLOSE:
|
||||||
img->unload();
|
img->unload();
|
||||||
@ -492,77 +508,39 @@ void consolewin_info::process_string(std::string const &string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void consolewin_info::build_generic_filter(device_image_interface *img, bool is_save, std::string &filter)
|
void consolewin_info::open_image_file(device_image_interface &device)
|
||||||
{
|
{
|
||||||
std::string file_extension;
|
choose_image(
|
||||||
|
device,
|
||||||
if (img)
|
window(),
|
||||||
file_extension = img->file_extensions();
|
CLSID_FileOpenDialog,
|
||||||
|
true,
|
||||||
if (!is_save)
|
[&device] (std::string_view selection)
|
||||||
file_extension.append(",zip,7z");
|
{
|
||||||
|
device.load(selection);
|
||||||
add_filter_entry(filter, "Common image types", file_extension.c_str());
|
});
|
||||||
|
|
||||||
filter.append("All files (*.*)|*.*|");
|
|
||||||
|
|
||||||
if (!is_save)
|
|
||||||
filter.append("Compressed Images (*.zip;*.7z)|*.zip;*.7z|");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void consolewin_info::add_filter_entry(std::string &dest, const char *description, const char *extensions)
|
void consolewin_info::create_image_file(device_image_interface &device)
|
||||||
{
|
{
|
||||||
// add the description
|
choose_image(
|
||||||
dest.append(description);
|
device,
|
||||||
dest.append(" (");
|
window(),
|
||||||
|
CLSID_FileSaveDialog,
|
||||||
// add the extensions to the description
|
false,
|
||||||
copy_extension_list(dest, extensions);
|
[&device] (std::string_view selection)
|
||||||
|
{
|
||||||
// add the trailing rparen and '|' character
|
device.create(selection, device.device_get_indexed_creatable_format(0), nullptr);
|
||||||
dest.append(")|");
|
});
|
||||||
|
|
||||||
// now add the extension list itself
|
|
||||||
copy_extension_list(dest, extensions);
|
|
||||||
|
|
||||||
// append a '|'
|
|
||||||
dest.append("|");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void consolewin_info::copy_extension_list(std::string &dest, const char *extensions)
|
bool consolewin_info::get_softlist_info(device_image_interface &device)
|
||||||
{
|
|
||||||
// our extension lists are comma delimited; Win32 expects to see lists
|
|
||||||
// delimited by semicolons
|
|
||||||
char const *s = extensions;
|
|
||||||
while (*s)
|
|
||||||
{
|
|
||||||
// append a semicolon if not at the beginning
|
|
||||||
if (s != extensions)
|
|
||||||
dest.push_back(';');
|
|
||||||
|
|
||||||
// append ".*"
|
|
||||||
dest.append("*.");
|
|
||||||
|
|
||||||
// append the file extension
|
|
||||||
while (*s && (*s != ','))
|
|
||||||
dest.push_back(*s++);
|
|
||||||
|
|
||||||
// if we found a comma, advance
|
|
||||||
while(*s == ',')
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================
|
|
||||||
// get_softlist_info
|
|
||||||
//============================================================
|
|
||||||
bool consolewin_info::get_softlist_info(device_image_interface *img)
|
|
||||||
{
|
{
|
||||||
bool has_software = false;
|
bool has_software = false;
|
||||||
bool passes_tests = false;
|
bool passes_tests = false;
|
||||||
std::string sl_dir, opt_name = img->instance_name();
|
std::string sl_dir, opt_name = device.instance_name();
|
||||||
|
|
||||||
// Get the path to suitable software
|
// Get the path to suitable software
|
||||||
for (software_list_device &swlist : software_list_device_enumerator(machine().root_device()))
|
for (software_list_device &swlist : software_list_device_enumerator(machine().root_device()))
|
||||||
@ -578,8 +556,8 @@ bool consolewin_info::get_softlist_info(device_image_interface *img)
|
|||||||
continue;
|
continue;
|
||||||
if (!has_software && (opt_name == image.instance_name()))
|
if (!has_software && (opt_name == image.instance_name()))
|
||||||
{
|
{
|
||||||
const char *interface = image.image_interface();
|
const char *intf = image.image_interface();
|
||||||
if (interface && part.matches_interface(interface))
|
if (intf && part.matches_interface(intf))
|
||||||
{
|
{
|
||||||
sl_dir = "\\" + swlist.list_name();
|
sl_dir = "\\" + swlist.list_name();
|
||||||
has_software = true;
|
has_software = true;
|
||||||
|
@ -47,14 +47,13 @@ private:
|
|||||||
|
|
||||||
virtual void process_string(std::string const &string) override;
|
virtual void process_string(std::string const &string) override;
|
||||||
|
|
||||||
static void build_generic_filter(device_image_interface *img, bool is_save, std::string &filter);
|
void open_image_file(device_image_interface &device);
|
||||||
static void add_filter_entry(std::string &dest, char const *description, char const *extensions);
|
void create_image_file(device_image_interface &device);
|
||||||
static void copy_extension_list(std::string &dest, char const *extensions);
|
bool get_softlist_info(device_image_interface &img);
|
||||||
bool get_softlist_info(device_image_interface *img);
|
|
||||||
|
|
||||||
device_t *m_current_cpu;
|
device_t *m_current_cpu;
|
||||||
HMENU m_devices_menu;
|
HMENU m_devices_menu;
|
||||||
std::map<std::string,std::string> slmap;
|
std::map<std::string,std::string> slmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // MAME_DEBUGGER_WIN_CONSOLEWININFO_H
|
||||||
|
@ -6,40 +6,27 @@
|
|||||||
//
|
//
|
||||||
//============================================================
|
//============================================================
|
||||||
|
|
||||||
#include "input_module.h"
|
|
||||||
#include "modules/osdmodule.h"
|
#include "modules/osdmodule.h"
|
||||||
|
|
||||||
#if defined(OSD_WINDOWS)
|
#if defined(OSD_WINDOWS)
|
||||||
|
|
||||||
// standard windows headers
|
#include "emu.h"
|
||||||
#include <windows.h>
|
|
||||||
#include <initguid.h>
|
|
||||||
#include <tchar.h>
|
|
||||||
#include <wrl/client.h>
|
|
||||||
|
|
||||||
// undef WINNT for dinput.h to prevent duplicate definition
|
#include "input_dinput.h"
|
||||||
#undef WINNT
|
|
||||||
#include <dinput.h>
|
#include "winutil.h"
|
||||||
#undef interface
|
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
// MAME headers
|
// standard windows headers
|
||||||
#include "emu.h"
|
#include <initguid.h>
|
||||||
#include "strconv.h"
|
#include <tchar.h>
|
||||||
|
|
||||||
// MAMEOS headers
|
|
||||||
#include "window.h"
|
|
||||||
#include "winutil.h"
|
|
||||||
|
|
||||||
#include "input_common.h"
|
|
||||||
#include "input_windows.h"
|
|
||||||
#include "input_dinput.h"
|
|
||||||
|
|
||||||
using namespace Microsoft::WRL;
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
using namespace Microsoft::WRL;
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
// dinput_joystick_pov_get_state
|
// dinput_joystick_pov_get_state
|
||||||
//============================================================
|
//============================================================
|
||||||
|
@ -1,10 +1,28 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Aaron Giles, Brad Hughes
|
||||||
|
//============================================================
|
||||||
|
//
|
||||||
|
// input_dinput.h - Windows DirectInput support
|
||||||
|
//
|
||||||
|
//============================================================
|
||||||
#ifndef MAME_OSD_INPUT_INPUT_DINPUT_H
|
#ifndef MAME_OSD_INPUT_INPUT_DINPUT_H
|
||||||
#define MAME_OSD_INPUT_INPUT_DINPUT_H
|
#define MAME_OSD_INPUT_INPUT_DINPUT_H
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "input_common.h"
|
#include "input_windows.h"
|
||||||
|
|
||||||
#include "modules/lib/osdlib.h"
|
#include "modules/lib/osdlib.h"
|
||||||
|
#include "modules/lib/osdobj_common.h"
|
||||||
|
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
|
#include "strconv.h"
|
||||||
|
|
||||||
|
#include <dinput.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <wrl/client.h>
|
||||||
|
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
// dinput_device - base directinput device
|
// dinput_device - base directinput device
|
||||||
@ -52,14 +70,14 @@ public:
|
|||||||
virtual ~dinput_api_helper();
|
virtual ~dinput_api_helper();
|
||||||
int initialize();
|
int initialize();
|
||||||
|
|
||||||
template<class TDevice>
|
template <class TDevice>
|
||||||
TDevice* create_device(
|
TDevice *create_device(
|
||||||
running_machine &machine,
|
running_machine &machine,
|
||||||
input_module_base &module,
|
input_module_base &module,
|
||||||
LPCDIDEVICEINSTANCE instance,
|
LPCDIDEVICEINSTANCE instance,
|
||||||
LPCDIDATAFORMAT format1,
|
LPCDIDATAFORMAT format1,
|
||||||
LPCDIDATAFORMAT format2,
|
LPCDIDATAFORMAT format2,
|
||||||
dinput_cooperative_level cooperative_level)
|
dinput_cooperative_level cooperative_level)
|
||||||
{
|
{
|
||||||
HRESULT result;
|
HRESULT result;
|
||||||
std::shared_ptr<win_window_info> window;
|
std::shared_ptr<win_window_info> window;
|
||||||
|
@ -6,32 +6,29 @@
|
|||||||
//
|
//
|
||||||
//============================================================
|
//============================================================
|
||||||
|
|
||||||
#include "input_module.h"
|
|
||||||
#include "modules/osdmodule.h"
|
#include "modules/osdmodule.h"
|
||||||
|
|
||||||
#if defined(OSD_WINDOWS)
|
#if defined(OSD_WINDOWS)
|
||||||
|
|
||||||
// standard windows headers
|
// MAME headers
|
||||||
#include <windows.h>
|
#include "emu.h"
|
||||||
#include <tchar.h>
|
|
||||||
#undef interface
|
#include "input_windows.h"
|
||||||
|
|
||||||
|
#include "winmain.h"
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
|
#include "modules/lib/osdlib.h"
|
||||||
|
#include "strconv.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
// MAME headers
|
// standard windows headers
|
||||||
#include "emu.h"
|
#include <windows.h>
|
||||||
#include "strconv.h"
|
#include <tchar.h>
|
||||||
|
|
||||||
// MAMEOS headers
|
|
||||||
#include "modules/lib/osdlib.h"
|
|
||||||
#include "winmain.h"
|
|
||||||
#include "window.h"
|
|
||||||
|
|
||||||
#include "input_common.h"
|
|
||||||
#include "input_windows.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -7,25 +7,18 @@
|
|||||||
//============================================================
|
//============================================================
|
||||||
|
|
||||||
#include "input_module.h"
|
#include "input_module.h"
|
||||||
#include "modules/osdmodule.h"
|
|
||||||
|
|
||||||
#if defined(OSD_WINDOWS)
|
#if defined(OSD_WINDOWS)
|
||||||
|
|
||||||
// standard windows headers
|
|
||||||
#include <windows.h>
|
|
||||||
#include <tchar.h>
|
|
||||||
#undef interface
|
|
||||||
|
|
||||||
// MAME headers
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
|
|
||||||
|
#include "input_windows.h"
|
||||||
|
|
||||||
#include "strconv.h"
|
#include "strconv.h"
|
||||||
|
|
||||||
// MAMEOS headers
|
// standard windows headers
|
||||||
#include "winmain.h"
|
#include <tchar.h>
|
||||||
#include "window.h"
|
|
||||||
|
|
||||||
#include "input_common.h"
|
|
||||||
#include "input_windows.h"
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -13,16 +13,15 @@
|
|||||||
// MAME headers
|
// MAME headers
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
|
|
||||||
// MAMEOS headers
|
#include "input_windows.h"
|
||||||
|
|
||||||
|
#include "window.h"
|
||||||
#include "winmain.h"
|
#include "winmain.h"
|
||||||
|
|
||||||
#include "util/language.h"
|
#include "util/language.h"
|
||||||
|
|
||||||
#include "osdepend.h"
|
#include "osdepend.h"
|
||||||
|
|
||||||
#include "input_common.h"
|
|
||||||
#include "input_windows.h"
|
|
||||||
|
|
||||||
|
|
||||||
bool windows_osd_interface::should_hide_mouse() const
|
bool windows_osd_interface::should_hide_mouse() const
|
||||||
{
|
{
|
||||||
|
@ -10,13 +10,15 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// standard windows headers
|
#include "input_common.h"
|
||||||
#include <windows.h>
|
|
||||||
#undef interface
|
|
||||||
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "winmain.h"
|
#include "winmain.h"
|
||||||
|
|
||||||
|
// standard windows headers
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
// TYPEDEFS
|
// TYPEDEFS
|
||||||
//============================================================
|
//============================================================
|
||||||
|
@ -6,46 +6,31 @@
|
|||||||
//
|
//
|
||||||
//============================================================
|
//============================================================
|
||||||
|
|
||||||
#include "input_module.h"
|
|
||||||
#include "modules/osdmodule.h"
|
#include "modules/osdmodule.h"
|
||||||
|
|
||||||
#if defined(OSD_WINDOWS)
|
#if defined(OSD_WINDOWS)
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
|
||||||
|
#include "input_dinput.h"
|
||||||
|
#include "input_xinput.h"
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
// standard windows headers
|
#include <oleauto.h>
|
||||||
#include <windows.h>
|
|
||||||
#include <wrl/client.h>
|
|
||||||
#include <wbemcli.h>
|
#include <wbemcli.h>
|
||||||
|
|
||||||
// XInput/DirectInput
|
|
||||||
#include <xinput.h>
|
|
||||||
#include <dinput.h>
|
|
||||||
|
|
||||||
#undef interface
|
|
||||||
|
|
||||||
// MAME headers
|
|
||||||
#include "emu.h"
|
|
||||||
|
|
||||||
// MAMEOS headers
|
|
||||||
#include "strconv.h"
|
|
||||||
#include "winmain.h"
|
|
||||||
|
|
||||||
#include "input_common.h"
|
|
||||||
#include "input_windows.h"
|
|
||||||
#include "input_xinput.h"
|
|
||||||
#include "input_dinput.h"
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using namespace Microsoft::WRL;
|
using namespace Microsoft::WRL;
|
||||||
|
|
||||||
template<class TCom>
|
template <class TCom>
|
||||||
class ComArray
|
class ComArray
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::vector<TCom*> m_entries;
|
std::vector<TCom *> m_entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ComArray(size_t capacity) : m_entries(capacity, nullptr)
|
ComArray(size_t capacity) : m_entries(capacity, nullptr)
|
||||||
|
@ -6,29 +6,17 @@
|
|||||||
//
|
//
|
||||||
//============================================================
|
//============================================================
|
||||||
|
|
||||||
#include "input_module.h"
|
|
||||||
#include "modules/osdmodule.h"
|
#include "modules/osdmodule.h"
|
||||||
|
|
||||||
#if defined(OSD_WINDOWS)
|
#if defined(OSD_WINDOWS)
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
|
||||||
|
#include "input_xinput.h"
|
||||||
|
|
||||||
// standard windows headers
|
// standard windows headers
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
// XInput header
|
|
||||||
#include <xinput.h>
|
|
||||||
|
|
||||||
#undef interface
|
|
||||||
|
|
||||||
// MAME headers
|
|
||||||
#include "emu.h"
|
|
||||||
|
|
||||||
// MAMEOS headers
|
|
||||||
#include "winutil.h"
|
|
||||||
#include "winmain.h"
|
|
||||||
|
|
||||||
#include "input_common.h"
|
|
||||||
#include "input_windows.h"
|
|
||||||
#include "input_xinput.h"
|
|
||||||
|
|
||||||
#define XINPUT_LIBRARIES { "xinput1_4.dll", "xinput9_1_0.dll" }
|
#define XINPUT_LIBRARIES { "xinput1_4.dll", "xinput9_1_0.dll" }
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "input_windows.h"
|
||||||
|
|
||||||
#include "modules/lib/osdlib.h"
|
#include "modules/lib/osdlib.h"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@ -10,8 +12,12 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
|
#include <xinput.h>
|
||||||
|
|
||||||
|
|
||||||
class xinput_joystick_device;
|
class xinput_joystick_device;
|
||||||
|
|
||||||
|
|
||||||
class xinput_api_helper : public std::enable_shared_from_this<xinput_api_helper>
|
class xinput_api_helper : public std::enable_shared_from_this<xinput_api_helper>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -40,6 +46,7 @@ private:
|
|||||||
xinput_get_caps_fn XInputGetCapabilities = nullptr;
|
xinput_get_caps_fn XInputGetCapabilities = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class xinput_joystick_device : public device_info
|
class xinput_joystick_device : public device_info
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -11,15 +11,6 @@
|
|||||||
|
|
||||||
#if defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
|
#if defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
|
||||||
|
|
||||||
// standard windows headers
|
|
||||||
#include <windows.h>
|
|
||||||
#include <mmsystem.h>
|
|
||||||
|
|
||||||
// undef WINNT for dsound.h to prevent duplicate definition
|
|
||||||
#undef WINNT
|
|
||||||
#include <dsound.h>
|
|
||||||
#undef interface
|
|
||||||
|
|
||||||
// MAME headers
|
// MAME headers
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "osdepend.h"
|
#include "osdepend.h"
|
||||||
@ -33,15 +24,175 @@
|
|||||||
#include "winmain.h"
|
#include "winmain.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
// standard windows headers
|
||||||
|
#include <dsound.h>
|
||||||
|
#include <mmsystem.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <wrl/client.h>
|
||||||
|
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
// DEBUGGING
|
// DEBUGGING
|
||||||
//============================================================
|
//============================================================
|
||||||
|
|
||||||
#define LOG_SOUND 0
|
#define LOG_SOUND 0
|
||||||
|
|
||||||
#define LOG(x) do { if (LOG_SOUND) osd_printf_verbose x; } while(0)
|
#define LOG(...) do { if (LOG_SOUND) osd_printf_verbose(__VA_ARGS__); } while(0)
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class buffer_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit operator bool() const { return bool(m_buffer); }
|
||||||
|
|
||||||
|
unsigned long release() { return m_buffer.Reset(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Microsoft::WRL::ComPtr<IDirectSoundBuffer> m_buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class primary_buffer : public buffer_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HRESULT create(LPDIRECTSOUND dsound)
|
||||||
|
{
|
||||||
|
assert(!m_buffer);
|
||||||
|
DSBUFFERDESC desc;
|
||||||
|
memset(&desc, 0, sizeof(desc));
|
||||||
|
desc.dwSize = sizeof(desc);
|
||||||
|
desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_GETCURRENTPOSITION2;
|
||||||
|
desc.lpwfxFormat = nullptr;
|
||||||
|
return dsound->CreateSoundBuffer(&desc, &m_buffer, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT get_format(WAVEFORMATEX &format) const
|
||||||
|
{
|
||||||
|
assert(m_buffer);
|
||||||
|
return m_buffer->GetFormat(&format, sizeof(format), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT set_format(WAVEFORMATEX const &format) const
|
||||||
|
{
|
||||||
|
assert(m_buffer);
|
||||||
|
return m_buffer->SetFormat(&format);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class stream_buffer : public buffer_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HRESULT create(LPDIRECTSOUND dsound, DWORD size, WAVEFORMATEX &format)
|
||||||
|
{
|
||||||
|
assert(!m_buffer);
|
||||||
|
DSBUFFERDESC desc;
|
||||||
|
memset(&desc, 0, sizeof(desc));
|
||||||
|
desc.dwSize = sizeof(desc);
|
||||||
|
desc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
|
||||||
|
desc.dwBufferBytes = size;
|
||||||
|
desc.lpwfxFormat = &format;
|
||||||
|
m_size = size;
|
||||||
|
return dsound->CreateSoundBuffer(&desc, &m_buffer, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT play_looping() const
|
||||||
|
{
|
||||||
|
assert(m_buffer);
|
||||||
|
return m_buffer->Play(0, 0, DSBPLAY_LOOPING);
|
||||||
|
}
|
||||||
|
HRESULT stop() const
|
||||||
|
{
|
||||||
|
assert(m_buffer);
|
||||||
|
return m_buffer->Stop();
|
||||||
|
}
|
||||||
|
HRESULT set_volume(LONG volume) const
|
||||||
|
{
|
||||||
|
assert(m_buffer);
|
||||||
|
return m_buffer->SetVolume(volume);
|
||||||
|
}
|
||||||
|
HRESULT set_min_volume() { return set_volume(DSBVOLUME_MIN); }
|
||||||
|
|
||||||
|
HRESULT get_current_positions(DWORD &play_pos, DWORD &write_pos) const
|
||||||
|
{
|
||||||
|
assert(m_buffer);
|
||||||
|
return m_buffer->GetCurrentPosition(&play_pos, &write_pos);
|
||||||
|
}
|
||||||
|
HRESULT copy_data(DWORD cursor, DWORD bytes, void const *data)
|
||||||
|
{
|
||||||
|
HRESULT result = lock(cursor, bytes);
|
||||||
|
if (DS_OK != result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
assert(m_bytes1);
|
||||||
|
assert((m_locked1 + m_locked2) >= bytes);
|
||||||
|
memcpy(m_bytes1, data, std::min(m_locked1, bytes));
|
||||||
|
if (m_locked1 < bytes)
|
||||||
|
{
|
||||||
|
assert(m_bytes2);
|
||||||
|
memcpy(m_bytes2, (uint8_t const *)data + m_locked1, bytes - m_locked1);
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock();
|
||||||
|
return DS_OK;
|
||||||
|
}
|
||||||
|
HRESULT clear()
|
||||||
|
{
|
||||||
|
HRESULT result = lock_all();
|
||||||
|
if (DS_OK != result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
assert(m_bytes1);
|
||||||
|
assert(!m_bytes2);
|
||||||
|
assert(m_size == m_locked1);
|
||||||
|
assert(0U == m_locked2);
|
||||||
|
memset(m_bytes1, 0, m_locked1);
|
||||||
|
|
||||||
|
unlock();
|
||||||
|
return DS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD size() const { return m_size; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
HRESULT lock(DWORD cursor, DWORD bytes)
|
||||||
|
{
|
||||||
|
assert(cursor < m_size);
|
||||||
|
assert(bytes <= m_size);
|
||||||
|
assert(m_buffer);
|
||||||
|
assert(!m_bytes1);
|
||||||
|
return m_buffer->Lock(
|
||||||
|
cursor, bytes,
|
||||||
|
&m_bytes1,
|
||||||
|
&m_locked1,
|
||||||
|
&m_bytes2,
|
||||||
|
&m_locked2,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
HRESULT lock_all() { return lock(0, m_size); }
|
||||||
|
HRESULT unlock()
|
||||||
|
{
|
||||||
|
assert(m_buffer);
|
||||||
|
assert(m_bytes1);
|
||||||
|
HRESULT const result = m_buffer->Unlock(
|
||||||
|
m_bytes1,
|
||||||
|
m_locked1,
|
||||||
|
m_bytes2,
|
||||||
|
m_locked2);
|
||||||
|
m_bytes1 = m_bytes2 = nullptr;
|
||||||
|
m_locked1 = m_locked2 = 0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD m_size = 0;
|
||||||
|
void *m_bytes1 = nullptr, *m_bytes2 = nullptr;
|
||||||
|
DWORD m_locked1 = 0, m_locked2 = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class sound_direct_sound : public osd_module, public sound_module
|
class sound_direct_sound : public osd_module, public sound_module
|
||||||
@ -51,7 +202,6 @@ public:
|
|||||||
sound_direct_sound() :
|
sound_direct_sound() :
|
||||||
osd_module(OSD_SOUND_PROVIDER, "dsound"),
|
osd_module(OSD_SOUND_PROVIDER, "dsound"),
|
||||||
sound_module(),
|
sound_module(),
|
||||||
m_dsound(nullptr),
|
|
||||||
m_bytes_per_sample(0),
|
m_bytes_per_sample(0),
|
||||||
m_primary_buffer(),
|
m_primary_buffer(),
|
||||||
m_stream_buffer(),
|
m_stream_buffer(),
|
||||||
@ -70,177 +220,21 @@ public:
|
|||||||
virtual void set_mastervolume(int attenuation) override;
|
virtual void set_mastervolume(int attenuation) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class buffer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
buffer() : m_buffer(nullptr) { }
|
|
||||||
~buffer() { release(); }
|
|
||||||
|
|
||||||
ULONG release()
|
|
||||||
{
|
|
||||||
ULONG const result = m_buffer ? m_buffer->Release() : 0;
|
|
||||||
m_buffer = nullptr;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator bool() const { return m_buffer; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
LPDIRECTSOUNDBUFFER m_buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
class primary_buffer : public buffer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HRESULT create(LPDIRECTSOUND dsound)
|
|
||||||
{
|
|
||||||
assert(!m_buffer);
|
|
||||||
DSBUFFERDESC desc;
|
|
||||||
memset(&desc, 0, sizeof(desc));
|
|
||||||
desc.dwSize = sizeof(desc);
|
|
||||||
desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_GETCURRENTPOSITION2;
|
|
||||||
desc.lpwfxFormat = nullptr;
|
|
||||||
return dsound->CreateSoundBuffer(&desc, &m_buffer, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT get_format(WAVEFORMATEX &format) const
|
|
||||||
{
|
|
||||||
assert(m_buffer);
|
|
||||||
return m_buffer->GetFormat(&format, sizeof(format), nullptr);
|
|
||||||
}
|
|
||||||
HRESULT set_format(WAVEFORMATEX const &format) const
|
|
||||||
{
|
|
||||||
assert(m_buffer);
|
|
||||||
return m_buffer->SetFormat(&format);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class stream_buffer : public buffer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
stream_buffer() : m_size(0), m_bytes1(nullptr), m_bytes2(nullptr), m_locked1(0), m_locked2(0) { }
|
|
||||||
|
|
||||||
HRESULT create(LPDIRECTSOUND dsound, DWORD size, WAVEFORMATEX &format)
|
|
||||||
{
|
|
||||||
assert(!m_buffer);
|
|
||||||
DSBUFFERDESC desc;
|
|
||||||
memset(&desc, 0, sizeof(desc));
|
|
||||||
desc.dwSize = sizeof(desc);
|
|
||||||
desc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
|
|
||||||
desc.dwBufferBytes = size;
|
|
||||||
desc.lpwfxFormat = &format;
|
|
||||||
m_size = size;
|
|
||||||
return dsound->CreateSoundBuffer(&desc, &m_buffer, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT play_looping() const
|
|
||||||
{
|
|
||||||
assert(m_buffer);
|
|
||||||
return m_buffer->Play(0, 0, DSBPLAY_LOOPING);
|
|
||||||
}
|
|
||||||
HRESULT stop() const
|
|
||||||
{
|
|
||||||
assert(m_buffer);
|
|
||||||
return m_buffer->Stop();
|
|
||||||
}
|
|
||||||
HRESULT set_volume(LONG volume) const
|
|
||||||
{
|
|
||||||
assert(m_buffer);
|
|
||||||
return m_buffer->SetVolume(volume);
|
|
||||||
}
|
|
||||||
HRESULT set_min_volume() { return set_volume(DSBVOLUME_MIN); }
|
|
||||||
|
|
||||||
HRESULT get_current_positions(DWORD &play_pos, DWORD &write_pos) const
|
|
||||||
{
|
|
||||||
assert(m_buffer);
|
|
||||||
return m_buffer->GetCurrentPosition(&play_pos, &write_pos);
|
|
||||||
}
|
|
||||||
HRESULT copy_data(DWORD cursor, DWORD bytes, void const *data)
|
|
||||||
{
|
|
||||||
HRESULT result = lock(cursor, bytes);
|
|
||||||
if (DS_OK != result)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
assert(m_bytes1);
|
|
||||||
assert((m_locked1 + m_locked2) >= bytes);
|
|
||||||
memcpy(m_bytes1, data, std::min(m_locked1, bytes));
|
|
||||||
if (m_locked1 < bytes)
|
|
||||||
{
|
|
||||||
assert(m_bytes2);
|
|
||||||
memcpy(m_bytes2, (uint8_t const *)data + m_locked1, bytes - m_locked1);
|
|
||||||
}
|
|
||||||
|
|
||||||
unlock();
|
|
||||||
return DS_OK;
|
|
||||||
}
|
|
||||||
HRESULT clear()
|
|
||||||
{
|
|
||||||
HRESULT result = lock_all();
|
|
||||||
if (DS_OK != result)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
assert(m_bytes1);
|
|
||||||
assert(!m_bytes2);
|
|
||||||
assert(m_size == m_locked1);
|
|
||||||
assert(0U == m_locked2);
|
|
||||||
memset(m_bytes1, 0, m_locked1);
|
|
||||||
|
|
||||||
unlock();
|
|
||||||
return DS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD size() const { return m_size; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
HRESULT lock(DWORD cursor, DWORD bytes)
|
|
||||||
{
|
|
||||||
assert(cursor < m_size);
|
|
||||||
assert(bytes <= m_size);
|
|
||||||
assert(m_buffer);
|
|
||||||
assert(!m_bytes1);
|
|
||||||
return m_buffer->Lock(
|
|
||||||
cursor, bytes,
|
|
||||||
&m_bytes1,
|
|
||||||
&m_locked1,
|
|
||||||
&m_bytes2,
|
|
||||||
&m_locked2,
|
|
||||||
0);
|
|
||||||
}
|
|
||||||
HRESULT lock_all() { return lock(0, m_size); }
|
|
||||||
HRESULT unlock()
|
|
||||||
{
|
|
||||||
assert(m_buffer);
|
|
||||||
assert(m_bytes1);
|
|
||||||
HRESULT const result = m_buffer->Unlock(
|
|
||||||
m_bytes1,
|
|
||||||
m_locked1,
|
|
||||||
m_bytes2,
|
|
||||||
m_locked2);
|
|
||||||
m_bytes1 = m_bytes2 = nullptr;
|
|
||||||
m_locked1 = m_locked2 = 0;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD m_size;
|
|
||||||
void *m_bytes1, *m_bytes2;
|
|
||||||
DWORD m_locked1, m_locked2;
|
|
||||||
};
|
|
||||||
|
|
||||||
HRESULT dsound_init();
|
HRESULT dsound_init();
|
||||||
void dsound_kill();
|
void dsound_kill();
|
||||||
HRESULT create_buffers(DWORD size, WAVEFORMATEX &format);
|
HRESULT create_buffers(DWORD size, WAVEFORMATEX &format);
|
||||||
void destroy_buffers();
|
void destroy_buffers();
|
||||||
|
|
||||||
// DirectSound objects
|
// DirectSound objects
|
||||||
LPDIRECTSOUND m_dsound;
|
Microsoft::WRL::ComPtr<IDirectSound> m_dsound;
|
||||||
|
|
||||||
// descriptors and formats
|
// descriptors and formats
|
||||||
uint32_t m_bytes_per_sample;
|
uint32_t m_bytes_per_sample;
|
||||||
|
|
||||||
// sound buffers
|
// sound buffers
|
||||||
primary_buffer m_primary_buffer;
|
primary_buffer m_primary_buffer;
|
||||||
stream_buffer m_stream_buffer;
|
stream_buffer m_stream_buffer;
|
||||||
uint32_t m_stream_buffer_in;
|
uint32_t m_stream_buffer_in;
|
||||||
|
|
||||||
// buffer over/underflow counts
|
// buffer over/underflow counts
|
||||||
unsigned m_buffer_underflows;
|
unsigned m_buffer_underflows;
|
||||||
@ -281,7 +275,7 @@ void sound_direct_sound::exit()
|
|||||||
m_buffer_underflows);
|
m_buffer_underflows);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(("Sound buffer: overflows=%u underflows=%u\n", m_buffer_overflows, m_buffer_underflows));
|
LOG("Sound buffer: overflows=%u underflows=%u\n", m_buffer_overflows, m_buffer_underflows);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -385,7 +379,7 @@ HRESULT sound_direct_sound::dsound_init()
|
|||||||
result = DirectSoundCreate(nullptr, &m_dsound, nullptr);
|
result = DirectSoundCreate(nullptr, &m_dsound, nullptr);
|
||||||
if (result != DS_OK)
|
if (result != DS_OK)
|
||||||
{
|
{
|
||||||
osd_printf_error("Error creating DirectSound: %08x\n", (unsigned)result);
|
osd_printf_error("Error creating DirectSound: %08x\n", result);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,7 +389,7 @@ HRESULT sound_direct_sound::dsound_init()
|
|||||||
result = m_dsound->GetCaps(&dsound_caps);
|
result = m_dsound->GetCaps(&dsound_caps);
|
||||||
if (result != DS_OK)
|
if (result != DS_OK)
|
||||||
{
|
{
|
||||||
osd_printf_error("Error getting DirectSound capabilities: %08x\n", (unsigned)result);
|
osd_printf_error("Error getting DirectSound capabilities: %08x\n", result);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,7 +407,7 @@ HRESULT sound_direct_sound::dsound_init()
|
|||||||
}
|
}
|
||||||
if (result != DS_OK)
|
if (result != DS_OK)
|
||||||
{
|
{
|
||||||
osd_printf_error("Error setting DirectSound cooperative level: %08x\n", (unsigned)result);
|
osd_printf_error("Error setting DirectSound cooperative level: %08x\n", result);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,7 +426,7 @@ HRESULT sound_direct_sound::dsound_init()
|
|||||||
DWORD stream_buffer_size = stream_format.nSamplesPerSec * stream_format.nBlockAlign * audio_latency / 10;
|
DWORD stream_buffer_size = stream_format.nSamplesPerSec * stream_format.nBlockAlign * audio_latency / 10;
|
||||||
stream_buffer_size = std::max(DWORD(1024), (stream_buffer_size / 1024) * 1024);
|
stream_buffer_size = std::max(DWORD(1024), (stream_buffer_size / 1024) * 1024);
|
||||||
|
|
||||||
LOG(("stream_buffer_size = %u\n", (unsigned)stream_buffer_size));
|
LOG("stream_buffer_size = %u\n", stream_buffer_size);
|
||||||
|
|
||||||
// create the buffers
|
// create the buffers
|
||||||
m_bytes_per_sample = stream_format.nBlockAlign;
|
m_bytes_per_sample = stream_format.nBlockAlign;
|
||||||
@ -446,7 +440,7 @@ HRESULT sound_direct_sound::dsound_init()
|
|||||||
result = m_stream_buffer.play_looping();
|
result = m_stream_buffer.play_looping();
|
||||||
if (result != DS_OK)
|
if (result != DS_OK)
|
||||||
{
|
{
|
||||||
osd_printf_error("Error playing: %08x\n", (uint32_t)result);
|
osd_printf_error("Error playing: %08x\n", result);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
return DS_OK;
|
return DS_OK;
|
||||||
@ -466,9 +460,7 @@ error:
|
|||||||
void sound_direct_sound::dsound_kill()
|
void sound_direct_sound::dsound_kill()
|
||||||
{
|
{
|
||||||
// release the object
|
// release the object
|
||||||
if (m_dsound)
|
m_dsound.Reset();
|
||||||
m_dsound->Release();
|
|
||||||
m_dsound = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -484,10 +476,10 @@ HRESULT sound_direct_sound::create_buffers(DWORD size, WAVEFORMATEX &format)
|
|||||||
HRESULT result;
|
HRESULT result;
|
||||||
|
|
||||||
// create the primary buffer
|
// create the primary buffer
|
||||||
result = m_primary_buffer.create(m_dsound);
|
result = m_primary_buffer.create(m_dsound.Get());
|
||||||
if (result != DS_OK)
|
if (result != DS_OK)
|
||||||
{
|
{
|
||||||
osd_printf_error("Error creating primary DirectSound buffer: %08x\n", (unsigned)result);
|
osd_printf_error("Error creating primary DirectSound buffer: %08x\n", result);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,7 +487,7 @@ HRESULT sound_direct_sound::create_buffers(DWORD size, WAVEFORMATEX &format)
|
|||||||
result = m_primary_buffer.set_format(format);
|
result = m_primary_buffer.set_format(format);
|
||||||
if (result != DS_OK)
|
if (result != DS_OK)
|
||||||
{
|
{
|
||||||
osd_printf_error("Error setting primary DirectSound buffer format: %08x\n", (unsigned)result);
|
osd_printf_error("Error setting primary DirectSound buffer format: %08x\n", result);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,20 +496,20 @@ HRESULT sound_direct_sound::create_buffers(DWORD size, WAVEFORMATEX &format)
|
|||||||
result = m_primary_buffer.get_format(primary_format);
|
result = m_primary_buffer.get_format(primary_format);
|
||||||
if (result != DS_OK)
|
if (result != DS_OK)
|
||||||
{
|
{
|
||||||
osd_printf_error("Error getting primary DirectSound buffer format: %08x\n", (unsigned)result);
|
osd_printf_error("Error getting primary DirectSound buffer format: %08x\n", result);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
osd_printf_verbose(
|
osd_printf_verbose(
|
||||||
"DirectSound: Primary buffer: %d Hz, %d bits, %d channels\n",
|
"DirectSound: Primary buffer: %d Hz, %d bits, %d channels\n",
|
||||||
(int)primary_format.nSamplesPerSec,
|
primary_format.nSamplesPerSec,
|
||||||
(int)primary_format.wBitsPerSample,
|
primary_format.wBitsPerSample,
|
||||||
(int)primary_format.nChannels);
|
primary_format.nChannels);
|
||||||
|
|
||||||
// create the stream buffer
|
// create the stream buffer
|
||||||
result = m_stream_buffer.create(m_dsound, size, format);
|
result = m_stream_buffer.create(m_dsound.Get(), size, format);
|
||||||
if (result != DS_OK)
|
if (result != DS_OK)
|
||||||
{
|
{
|
||||||
osd_printf_error("Error creating DirectSound stream buffer: %08x\n", (unsigned)result);
|
osd_printf_error("Error creating DirectSound stream buffer: %08x\n", result);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,7 +517,7 @@ HRESULT sound_direct_sound::create_buffers(DWORD size, WAVEFORMATEX &format)
|
|||||||
result = m_stream_buffer.clear();
|
result = m_stream_buffer.clear();
|
||||||
if (result != DS_OK)
|
if (result != DS_OK)
|
||||||
{
|
{
|
||||||
osd_printf_error("Error locking DirectSound stream buffer: %08x\n", (unsigned)result);
|
osd_printf_error("Error locking DirectSound stream buffer: %08x\n", result);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -555,8 +547,11 @@ void sound_direct_sound::destroy_buffers()
|
|||||||
m_primary_buffer.release();
|
m_primary_buffer.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#else // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
|
#else // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
|
||||||
MODULE_NOT_SUPPORTED(sound_direct_sound, OSD_SOUND_PROVIDER, "dsound")
|
MODULE_NOT_SUPPORTED(sound_direct_sound, OSD_SOUND_PROVIDER, "dsound")
|
||||||
#endif // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
|
#endif // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
MODULE_DEFINITION(SOUND_DSOUND, sound_direct_sound)
|
MODULE_DEFINITION(SOUND_DSOUND, sound_direct_sound)
|
||||||
|
@ -6,18 +6,18 @@
|
|||||||
//
|
//
|
||||||
//============================================================
|
//============================================================
|
||||||
|
|
||||||
|
#include "winutil.h"
|
||||||
|
|
||||||
|
// lib/util
|
||||||
|
#include "timeconv.h"
|
||||||
|
|
||||||
|
// osd
|
||||||
|
#include "strconv.h"
|
||||||
|
|
||||||
// standard windows headers
|
// standard windows headers
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
|
|
||||||
// MAME headers
|
|
||||||
#include "emu.h"
|
|
||||||
|
|
||||||
// MAMEOS headers
|
|
||||||
#include "winutil.h"
|
|
||||||
#include "strconv.h"
|
|
||||||
#include "timeconv.h"
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
// win_attributes_to_entry_type
|
// win_attributes_to_entry_type
|
||||||
|
@ -6,18 +6,23 @@
|
|||||||
//
|
//
|
||||||
//============================================================
|
//============================================================
|
||||||
|
|
||||||
#ifndef __WINUTIL__
|
#ifndef MAME_OSD_WINDOWS_WINUTIL_H
|
||||||
#define __WINUTIL__
|
#define MAME_OSD_WINDOWS_WINUTIL_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include "osdfile.h"
|
#include "osdfile.h"
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
|
||||||
// Shared code
|
// Shared code
|
||||||
osd::directory::entry::entry_type win_attributes_to_entry_type(DWORD attributes);
|
osd::directory::entry::entry_type win_attributes_to_entry_type(DWORD attributes);
|
||||||
std::chrono::system_clock::time_point win_time_point_from_filetime(LPFILETIME file_time);
|
std::chrono::system_clock::time_point win_time_point_from_filetime(LPFILETIME file_time);
|
||||||
BOOL win_is_gui_application(void);
|
BOOL win_is_gui_application();
|
||||||
HMODULE WINAPI GetModuleHandleUni();
|
HMODULE WINAPI GetModuleHandleUni();
|
||||||
|
|
||||||
#endif // __WINUTIL__
|
#endif // MAME_OSD_WINDOWS_WINUTIL_H
|
||||||
|
Loading…
Reference in New Issue
Block a user