Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)

# this is originally a Windows project, so it uses _DEBUG, not NDEBUG
add_compile_definitions("$<$<CONFIG:DEBUG>:_DEBUG>")
add_compile_options(-Werror=return-type -Wno-switch)
if (MSVC)
add_compile_options(/W4)
else()
add_compile_options(-Werror=return-type -Wno-switch)
endif()

if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
add_compile_options(-Werror=format -Wno-error=format-overflow -Wno-error=format-truncation -Wno-psabi)
Expand Down Expand Up @@ -61,8 +65,12 @@ if (BUILD_LIBRETRO OR BUILD_APPLEN OR BUILD_SA2)
add_subdirectory(source/frontends/common2)
endif()

if (BUILD_APPLEN)
add_subdirectory(source/frontends/ncurses)
if (NOT MSVC)
# ncurses is not supported on Windows MSVC, only on MSYS2/MinGW
# TODO: add support for Windows MSVC via PDCurses
if (BUILD_APPLEN)
add_subdirectory(source/frontends/ncurses)
endif()
endif()

if (BUILD_LIBRETRO)
Expand All @@ -71,6 +79,7 @@ endif()

if (BUILD_SA2)
add_subdirectory(source/frontends/sdl)
set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT sa2)
endif()

if (NOT WIN32)
Expand Down
4 changes: 4 additions & 0 deletions libyaml/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,7 @@ target_include_directories(yaml PRIVATE
target_compile_definitions(yaml PRIVATE
HAVE_CONFIG_H
)

if (MSVC)
target_compile_definitions(yaml PUBLIC YAML_DECLARE_STATIC)
endif()
4 changes: 4 additions & 0 deletions minizip/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ add_library(minizip STATIC
target_include_directories(minizip INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/..
)

find_package(ZLIB REQUIRED)

target_link_libraries(minizip PRIVATE ZLIB::ZLIB)
15 changes: 13 additions & 2 deletions source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ endif()
target_link_libraries(appleii PUBLIC
yaml
minizip
apple2roms
)

target_link_directories(appleii PUBLIC
Expand All @@ -284,9 +285,19 @@ target_link_directories(appleii PUBLIC
${ZLIB_LIBRARY_DIRS}
)

target_compile_options(appleii PUBLIC
-Wno-multichar
if (MSVC)
target_compile_options(appleii PUBLIC
/wd4566 # disable multi-character constant warning
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

ideally we should fix this code in the upstream repo. can you propose a MR there.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Let me see where it pukes and propose a PR

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Well they use /utf-8 in the upstream repo so here for MSVC I can use:
add_compile_options(/utf-8)
instead of /wd4566, which tracks closer to upstream. But your -Wno-multichar is also /wd4566.
Thoughts?

)
target_compile_definitions(appleii PRIVATE
NOMINMAX # to avoid conflicts with std::min/max
DISABLE_SPEECH_API # undefine because the original AppleWin speech API is not supported here
)
else()
target_compile_options(appleii PUBLIC
-Wno-multichar
)
endif()

# wildcards (*.SYM) are not supported on Windows msys2
add_custom_command(
Expand Down
6 changes: 4 additions & 2 deletions source/StdAfx.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@
#define SM_CXPADDEDBORDER 92
#endif

#ifndef __MINGW32__
#define USE_SPEECH_API
#ifndef DISABLE_SPEECH_API
# ifndef __MINGW32__
# define USE_SPEECH_API
# endif
#endif

#ifdef __MINGW32__
Expand Down
14 changes: 14 additions & 0 deletions source/frontends/common2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,20 @@ target_link_libraries(common2 PRIVATE
apple2roms
)

# ---- getopt for Windows (MSVC/MinGW on Win32) ----
if (WIN32)
# Build the local getopt implementation and expose its headers to this target
target_sources(common2 PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/getopt.c
)
target_include_directories(common2 PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)

# Prevent <Windows.h> from defining min/max macros, which break numeric_limits::min/max
target_compile_definitions(common2 PRIVATE NOMINMAX)
endif()

if (NOT WIN32)
target_link_libraries(common2 PUBLIC
windows
Expand Down
6 changes: 5 additions & 1 deletion source/frontends/common2/argparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@

#include "Memory.h"

#include <getopt.h>
#ifdef _WIN32
# include "frontends/common2/getopt.h"
#else
# include <getopt.h>
#endif
#include <regex>
#include <iostream>
#include <iomanip>
Expand Down
109 changes: 109 additions & 0 deletions source/frontends/common2/getopt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#include "getopt.h"
#include <string.h>
#include <stdio.h>

// For Windows MSVC only
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

where does this code come from?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

ChatGPT. There are tons of versions of this code online. I would credit someone but the amount of copy-paste in there is quite significant.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

uhm... originally I was using boost which is well tested and portable. nobody likes it, so now we replace it with some random code which has no guarantee to behave the same as the target getopt. I see it as a regression,not a way forward.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

We are committing to a multiplatform codebase. We ahould be using the easiest and most reliable code to do that. Because MSVC doesn't have getopt I hacked together something to make it compile. But if instead we use boost I have no problem, the more reliable and the fewer platform-specific splits the better.
Did people say no to boost? It's big and cumbersome, but multiplatform is big and cumbersome. I really really think we should have ONE multiplatform codebase, with ONE front end that works 100% across all platforms, where any dev on any platform can use the canonical IDE to work on the codebase.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I did try a switch (back?) from argparser.cpp to boost::program_options, removing getopt althogether and it certainly is a better multiplatform solution. Let me know if you want me to include it in the PR while we're at it.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I have moved to getopt recently because the libretro build cannot use boost. let me fix all the rest and then we come back to this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Quick comment: you still use boost::property_tree in common2 so that would also have to go if we're getting off boost 100%


char *optarg = NULL;
int optind = 1, opterr = 1, optopt = '?';

static int optpos = 1;

static int
_parse_short(int argc, char * const argv[], const char *optstring)
{
char c = argv[optind][optpos];
const char *cp = strchr(optstring, c);

if (!cp) {
if (opterr)
fprintf(stderr, "unknown option -- %c\n", c);
if (argv[optind][++optpos] == '\0') {
optind++;
optpos = 1;
}
optopt = c;
return '?';
}
if (cp[1] == ':') {
if (argv[optind][optpos+1] != '\0') {
optarg = &argv[optind][optpos+1];
optind++;
} else if (++optind < argc) {
optarg = argv[optind++];
} else {
optopt = c;
return (optstring[0] == ':') ? ':' : '?';
}
optpos = 1;
} else {
if (argv[optind][++optpos] == '\0') {
optpos = 1;
optind++;
}
optarg = NULL;
}
return c;
}

int getopt(int argc, char * const argv[], const char *optstring)
{
if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
return -1;
if (strcmp(argv[optind], "--") == 0) {
optind++;
return -1;
}
return _parse_short(argc, argv, optstring);
}

int getopt_long(int argc, char * const argv[], const char *optstring,
const struct option *longopts, int *longindex)
{
if (optind >= argc) return -1;

if (argv[optind][0] == '-' && argv[optind][1] == '-') {
const char *name = argv[optind] + 2;
const char *eq = strchr(name, '=');
size_t len = eq ? (size_t)(eq - name) : strlen(name);

for (int i = 0; longopts[i].name; i++) {
if (strncmp(name, longopts[i].name, len) == 0
&& len == strlen(longopts[i].name)) {
if (longindex) *longindex = i;
if (longopts[i].has_arg == no_argument) {
optarg = NULL;
} else if (longopts[i].has_arg == required_argument) {
if (eq)
optarg = (char*)eq+1;
else if (optind+1 < argc)
optarg = argv[++optind];
else
return optopt = longopts[i].val, '?';
} else if (longopts[i].has_arg == optional_argument) {
optarg = eq ? (char*)eq+1 : NULL;
}
optind++;
if (longopts[i].flag) {
*(longopts[i].flag) = longopts[i].val;
return 0;
} else {
return longopts[i].val;
}
}
}
/* no match */
if (opterr)
fprintf(stderr, "unrecognized option '--%s'\n", name);
optind++;
return '?';
}
/* fallback to short option parsing */
return getopt(argc, argv, optstring);
}

int getopt_long_only(int argc, char * const argv[], const char *optstring,
const struct option *longopts, int *longindex)
{
return getopt_long(argc, argv, optstring, longopts, longindex);
}
39 changes: 39 additions & 0 deletions source/frontends/common2/getopt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#ifndef GETOPT_H
#define GETOPT_H

// For Windows MSVC only

#ifdef __cplusplus
extern "C" {
#endif

/* argument flags */
#define no_argument 0
#define required_argument 1
#define optional_argument 2

struct option {
const char *name;
int has_arg;
int *flag;
int val;
};

/* globals */
extern char *optarg;
extern int optind, opterr, optopt;

/* functions */
int getopt(int argc, char * const argv[], const char *optstring);

int getopt_long(int argc, char * const argv[], const char *optstring,
const struct option *longopts, int *longindex);

int getopt_long_only(int argc, char * const argv[], const char *optstring,
const struct option *longopts, int *longindex);

#ifdef __cplusplus
}
#endif

#endif /* GETOPT_H */
29 changes: 29 additions & 0 deletions source/frontends/docs/msvc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Microsoft VisualStudio support

## Why

The original AppleWin project is built with Visual Studio. We now provide support for Visual Studio when building 'sa2', the SDL version of AppleWin.

## Status

`sa2` compiles under VisualStudio 2022.

## Building

Very **important** to install `vcpkg`. Refer to the Microsoft documentation.

Install using `vcpkg` the following packages:
```
vcpkg install sdl2 sdl2-image sdl2-ttf
vcpkg install zlib
vcpkg install boost
```
Then configure:
```
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=C:\PATH_TO_VCPKG\scripts\buildsystems\vcpkg.cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DVCPKG_TARGET_TRIPLET=x64-windows -DBUILD_SA2=ON
```
Then open the generated `build\applewin.sln` file in Visual Studio.

## Running

`sa2` should be the startup project that runs when you press F5.
23 changes: 23 additions & 0 deletions source/frontends/docs/xcode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Apple Xcode support

## Status

Compiles cleanly under Xcode.

## Building

Configure:
Move to the top level directory of AppleWin
Create a `build` directory and configure (here to build the SDL version):
```
mkdir build
cmake -G Xcode -B build -DBUILD_SA2=ON
```
Then open the generated `build/applewin.xcodeproj` file in Xcode, or just type:
```
open build/applewin.xcodeproj
```

## Running

`sa2` should be inside build/Debug or build/Release depending on your choice.
20 changes: 17 additions & 3 deletions source/frontends/sdl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ find_package(SDL2 REQUIRED)
# we should use find_package, but Ubuntu does not provide it for SDL2_image
pkg_search_module(SDL2_IMAGE REQUIRED SDL2_image)

target_compile_features(common2 PUBLIC cxx_std_20)
Comment thread
hasseily marked this conversation as resolved.

if ((${CMAKE_SYSTEM_NAME} MATCHES "Darwin") OR (${CMAKE_SYSTEM_NAME} MATCHES "Windows"))
# only OpenGL supported on MacOS and Windows
Expand All @@ -27,7 +28,6 @@ else()
)
endif()


set(SOURCE_FILES
main.cpp
gamepad.cpp
Expand Down Expand Up @@ -128,7 +128,21 @@ target_include_directories(sa2 PRIVATE

target_compile_definitions(sa2 PRIVATE
IMGUI_USER_CONFIG="frontends/sdl/imgui/imconfig.h"
)
)

if (MSVC)
target_compile_definitions(sa2 PRIVATE
NOMINMAX # to avoid conflicts with std::min/max
DISABLE_SPEECH_API # undefine because the original AppleWin speech API is not supported here
)
endif()

install(TARGETS sa2
DESTINATION bin)
RUNTIME_DEPENDENCIES
PRE_EXCLUDE_REGEXES "api-ms-" "ext-ms-" # skip Windows system DLLs
POST_EXCLUDE_REGEXES ".*system32/.*" # skip more system DLLs
FRAMEWORK DESTINATION Frameworks
RUNTIME DESTINATION bin
LIBRARY DESTINATION bin
ARCHIVE DESTINATION lib
)
4 changes: 4 additions & 0 deletions source/frontends/sdl/processfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
#include <cstring>
#include <sstream>

#ifdef _WIN32
# define strcasecmp _stricmp
#endif

namespace
{

Expand Down