Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get libretro core compiling for Windows #198

Open
wants to merge 15 commits into
base: master
Choose a base branch
from

Conversation

Jamiras
Copy link

@Jamiras Jamiras commented Nov 29, 2024

Closes #49

I apologize about the size of the PR, but this is really what it took.

image

Highlight of changes:

  • Changed checks on _MSC_VER to _WIN32.
  • Resources are converted to array data and embedded in the libretro core.
  • Replace IDirectSoundBuffer psuedo-class with SoundBufferBase base class and SoundBuffer implementation class.
    • SoundBufferBase replaces LPDIRECTSOUNDBUFFER in VOICE class. Methods previously acting directly on the LPDIRECTSOUNDBUFFER object now route through the class instance.
    • Original DirectSound implementation moved to DSSoundBuffer subclass.
    • DSInit and DSUninit are now replaced, and the alternate implementations primarily just define which subclass of SoundBufferBase should be initialized.
    • This allows the alternate implementation in an environment that already has DirectX defines (Windows) and constitutes the largest majority of the changes in this PR. Without these changes, the attempted indirections implemented in IDirectSoundBuffer would not line up with the vtable for the actual IDirectSoundBuffer defined in DirectX.
  • Many printf type statements had to be modified to explicitly cast to the format type (i.e. HRESULT -> unsigned). The compiler was raising warnings/errors that would interrupt the compilation.
  • Some files were conditionally removed from the common2 library as they are not needed for the libretro build and were causing undesirable dependencies on boost. More information will be provided in comments near the affected components.
  • Additional notes will be added near relevant pieces of code.

This PR strictly focuses on getting the existing code to compile a Windows core. All four Linux projects still build and seem to be working (on Ubuntu). My testing focus has been the Windows core.

I would like to make further changes to the core behavior in future PRs:

  • L/R buttons should not modify configuration - let the configuration menu in the frontend handle that.
  • Double-start should not reset the emulator - let the frontend handle that. This is especially important for achievements, as the achievement logic is reset on emulator reset, and there's no way to know a reset internal to the core has occurred. Also, It's common for users to hit Start to pause their game, and it's too easy to accidentally double tap it.
  • Double-select should not try to quit. The libretro documentation says "Should only be used if game has a specific way to shutdown the game from a menu item or similar." This is implemented as a hotkey, not in-game functionality.
  • Need some way to switch disks in drive two. I recommend using the L1/R1 buttons similar to how the PC-8800 core does it. This would also simplify switching disks in drive one.
  • Alt buttons seem to be bound to action keys (Return, Space, or ESC maybe)?

@@ -26,6 +26,10 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
add_compile_options(-Werror=format -Wno-error=format-overflow -Wno-error=format-truncation -Wno-psabi)
endif()

if (BUILD_LIBRETRO)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++")
endif()
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

libretro should statically link to as much as possible to prevent possible missing dependency errors and/or conflicting versions of dependencies between the core and the frontend.

@@ -37,8 +37,6 @@ if ("${SLIRP_FOUND}" STREQUAL "")
endif()
endif()

find_package(Boost REQUIRED)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

boost is now only pulled in to the common2 library, and only if building the files dependent on it.

linux/network/portfwds.cpp
linux/resources.cpp
linux/soundbuffer.cpp
linux/version.cpp
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This directory should be moved. They're no longer linux-specific. I couldn't think of a good name. Maybe they should be moved into the common2 folder?

@@ -287,7 +314,8 @@ target_compile_options(appleii PUBLIC

add_custom_command(
TARGET appleii POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/bin/*.SYM ${CMAKE_BINARY_DIR}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

msys2 didn't like the *.SYM, so I split it into two statements.

@@ -140,7 +140,7 @@ enum AppMode_e
#define WM_USER_FULLSCREEN WM_USER+8
#define VK_SNAPSHOT_TEXT WM_USER+9 // PrintScreen+Ctrl

#ifdef _MSC_VER
#ifdef _WIN32
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_MSC_VER is only defined when building with Visual Studio. I've changed most of the _MSC_VER checks to _WIN32.

@@ -28,13 +28,23 @@ namespace
return std::equal(prefix.begin(), prefix.end(), value.begin());
}

static std::string fileStem(const std::string& path)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if the msys2 compiler doesn't support c++17, or if the CMake setting isn't being honored, but the compiler couldn't find string::stem or string::native.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

compiler or linker error?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compiler. I might have been misreading it. It's not "not finding string::stem", it's having issues converting value types:

error: no match for 'operator=' (operand types are 'std::string' {aka 'std::__cxx11::basic_string<char>'} and 'std::filesystem::__cxx11::path')
   47 |       label = path.stem();

and

 error: invalid initialization of reference of type 'const std::string&' {aka 'const std::__cxx11::basic_string<char>&'} from expression of type 'const std::filesystem::__cxx11::path::string_type' {aka 'const std::__cxx11::basic_string<wchar_t>'}
  108 |       myImages.push_back({ filePath.native(), fileStem(filePath.native()), writeProtected, createIfNecessary });
      |                                                        ~~~~~~~~~~~~~~~^~

using u8string in both cases works, so I've removed the fileStem helper.

namespace
{

void saveRegistryToINI(const std::shared_ptr<common2::PTreeRegistry> & registry)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

libretro cores should not write files, and i couldn't come up with a good reason to keep this. the frontend will store the modified configuration according to its implementation.

Copy link
Owner

@audetto audetto Nov 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a feature I use to debug issues, it saves its configuration to a file I can reload in a non-liretro run. People don't need to use it, nor does it change anything to the libretro execution, it is write-only.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is my previous attempt: e7795ab

I will review the whole thing again and extend it to all frontends.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that mean this is okay, or you want me to put it back?

@@ -47,13 +26,11 @@ namespace ra2
, myAudioSource(AudioSource::UNKNOWN)
, myKeyboardType(KeyboardType::ASCII)
{
myLoggerContext = std::make_shared<LoggerContext>(true);
myLoggerContext = std::make_shared<LoggerContext>(false);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar to above, the core should not be writing files unnecessarily. this could be modified to write to the frontend log via log_cb, but I felt it was reasonable to just disable it entirely.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right now, this is premature. will be addressed once the compilation is fixed.

@@ -173,6 +173,53 @@ namespace

namespace ra2
{
class RetroRegistry : public Registry
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid boost dependency by storing values in map of maps.


#include <cstring>

IDirectSoundBuffer::IDirectSoundBuffer(LPCDSBUFFERDESC lpcDSBufferDesc)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved to soundbuffer.cpp

@audetto
Copy link
Owner

audetto commented Nov 30, 2024

Hi, impressive work!

If you are thinking about merging this, I need to warn you about some of the constraints of this project.

This projects does not all any change to any file which is already part of the original AppleWin project. Otherwise, merging becomes a nightmare, while now, I get 1 conflict every 6 months.
You might still see a handful of files with differences, simply because I have not unstreamed them yet.

So, where to go from here?

  1. All the trivial changes, (_MSC_VER, int, casting) should go directly to https://github.com/AppleWin/AppleWin (1 or 2 PRs)
  2. The sound abstraction should be a separate PR, still to the AppleWin repository.

Then they will land here and we will make the relevant changes for linux - libretro.

  1. Given the amount of infrastructure, any change of behaviour needs to be a separate PR which will have its own conversation. (otherwise, 1 single PR thread for 5 changes becomes unreadable).

It might sound very painful and a waste of time, but it is exactly what I have done for linux and the results are an extremely successful integration. (look at the fate of https://github.com/linappleii/linapple to see how important this is).

DWORD dwRetVal = GetTempPathA(MAX_PATH, lpTempPathBuffer);
if (dwRetVal > MAX_PATH || (dwRetVal == 0))
{
throw std::runtime_error("Cannot create temporary file");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall indentation is unfortunately non uniform, but each file's is.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is time to force a decent formatting standards. I will resuscitate an old attempt AppleWin#1202

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

i noticed the inconsistency, and did my best to maintain it on a per-file basis.

@Jamiras
Copy link
Author

Jamiras commented Dec 1, 2024

All the trivial changes, (_MSC_VER, int, casting) should go directly to https://github.com/AppleWin/AppleWin (1 or 2 PRs)

Will open that later today

The sound abstraction should be a separate PR, still to the AppleWin repository.

Will open that after the first PR is accepted.

Then they will land here and we will make the relevant changes for linux - libretro.

Will leave this open for that.

Given the amount of infrastructure, any change of behaviour needs to be a separate PR which will have its own conversation.

Absolutely, which is why I left this blurb in the original text: "I would like to make further changes to the core behavior in future PRs"

@audetto
Copy link
Owner

audetto commented Dec 3, 2024

All the trivial changes, (_MSC_VER, int, casting) should go directly to https://github.com/AppleWin/AppleWin (1 or 2 PRs)

Will open that later today

I saw it, good.

The sound abstraction should be a separate PR, still to the AppleWin repository.

Will open that after the first PR is accepted.

Then they will land here and we will make the relevant changes for linux - libretro.

Will leave this open for that.

Yes we will use it as a reference for what is still missing.
There are definitely some good ideas in your work, which I started and never completed.

I will look at these first

  1. resources
  2. boost
  3. clang-format

@@ -78,11 +82,11 @@ typedef UINT64 uint64_t;
#include <vector>
#include <cassert>

#include "windows.h"
#include "linux/libwindows/windows.h"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't touch this. my windows.h is supposed to be a drop in replacement of the real one. if there is an ambiguity, it means there is a problem in the makefile.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ambiguity is that I didn't know it wasn't Microsoft's windows.h until I had spent several more hours trying to detangle defines.

utils.h
timer.h
speed.h
)

if (BUILD_APPLEN OR BUILD_QAPPLE OR BUILD_SA2)
set(SOURCE_FILES ${SOURCE_FILES}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will handle this in a different way. The content of the libraries should not depend on what one is building. Better to split the libraries. Leave it with me.

@@ -290,10 +267,6 @@ namespace ra2
{
myFrame->Cycle50ScanLines();
}
if (checkButton(RETRO_DEVICE_ID_JOYPAD_L2))
{
saveRegistryToINI(myRegistry);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same, no change of behaviour until it compiles

@@ -1,7 +1,9 @@
#include "StdAfx.h"
#include "linux/linuxframe.h"
#include "linux/context.h"
#ifndef _WIN32
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be handled via SLIRP_FOUND

@@ -1,6 +1,9 @@
#pragma once

#include "wincompat.h"
#ifndef _WIN32
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should probably include windows.h

@@ -6538,7 +6538,9 @@ bool ParseAssemblyListing ( bool bBytesToMemory, bool bAddSymbols )
{
*p = 0;
// sscanf( sLine, "%s %s %s %s %s %s %s %s", sAddr1, sByte1, sByte2, sByte3, sLineN, sLabel, sAsm, sParam );
sscanf( sLine, "%X", &nAddress );
unsigned nScanAddress; // helper variable in case sizeof(DWORD) != sizeof(unsigned)
sscanf( sLine, "%X", &nScanAddress );
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect this will require more care.

I must define DWORD as unsigned int. Can you check what your version of gcc uses?

We will probably have to use a macro to select the correct print format like we already do for size_t and ptrdiff

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on my comments here, mingw uses unsigned long int for DWORD.

By sscanfing into a secondary variable, we know exactly which format to use ("%X" is appropriate for unsigned - see here). The assignment then converts that to whatever DWORD is defined as.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

libretro: compilation on Windows & MSYS2
2 participants