OXYGENHUB
# 9120e87480a6 enhanced-x16-emulator / CMakeLists.txt
38.7 KiB · Plain Text · last changed chore(): initial commit 26 days ago source blame history raw
1
cmake_minimum_required(VERSION 3.15)
2
3
string(ASCII 27 Esc)
4
set(ColorReset  "${Esc}[m")
5
set(ColorYellow "${Esc}[33m")
6
set(ColorGreen  "${Esc}[32m")
7
set(ColorRed    "${Esc}[31m")
8
9
project(x16emu LANGUAGES C CXX)
10
11
# --- Options (Replacements for Env Vars) ---
12
option(ENABLE_LTO "Enable Link Time Optimization" ON)
13
14
# Turning this off builds only the unit tests, which link no emulator core and so
15
# need neither SDL nor a ROM. Chiefly for CI and for working on the tests.
16
option(BUILD_EMULATOR "Build the x16emu executable and makecart" ON)
17
18
# --- Configuration & Standards ---
19
set(CMAKE_C_STANDARD 11)
20
set(CMAKE_C_STANDARD_REQUIRED ON)
21
set(CMAKE_CXX_STANDARD 17)
22
set(CMAKE_CXX_STANDARD_REQUIRED ON)
23
set(CMAKE_C_EXTENSIONS OFF)
24
25
if(ENABLE_LTO)
26
    include(CheckIPOSupported)
27
    check_ipo_supported(RESULT lto_supported OUTPUT lto_error)
28
    if(lto_supported)
29
        set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
30
    else()
31
        message(STATUS "[x16] LTO not supported: ${lto_error}")
32
    endif()
33
endif()
34
35
# Common compiler warnings/flags
36
if(MSVC)
37
    # /W3 = production-level warnings, /WX = warnings as errors
38
    # Suppress common harmless warnings from the codebase:
39
    #   C4244: conversion with possible loss of data (e.g., int to uint8_t)
40
    #   C4267: conversion from size_t to smaller type
41
    #   C4018: signed/unsigned mismatch in comparison
42
    #   C4996: deprecated POSIX function names (unlink, etc.)
43
    #   C4334: result of 32-bit shift implicitly converted to 64 bits
44
    #   C4098: void function returning a value
45
    #   C4305: truncation from double to float
46
    add_compile_options(/W3 /WX /wd4244 /wd4267 /wd4018 /wd4996 /wd4334 /wd4098 /wd4305)
47
    add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
48
else()
49
    add_compile_options(-Wall -Werror)
50
endif()
51
52
set(GIT_REV_HEADER_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
53
set(GIT_REV_HEADER "${GIT_REV_HEADER_DIR}/git_rev.h")
54
file(MAKE_DIRECTORY ${GIT_REV_HEADER_DIR})
55
56
find_package(Git)
57
58
configure_file(
59
    "${CMAKE_CURRENT_SOURCE_DIR}/GetGitRevision.cmake.in"
60
    "${CMAKE_CURRENT_BINARY_DIR}/GetGitRevision.cmake"
61
    @ONLY
62
)
63
64
# Create a custom target that runs EVERY build
65
add_custom_target(
66
    update_git_rev
67
    ALL # Ensures this runs by default
68
    COMMAND ${CMAKE_COMMAND}
69
        -DCMAKE_SOURCE_DIR=${CMAKE_SOURCE_DIR}
70
        -DOUTPUT_FILE=${GIT_REV_HEADER}
71
        -P ${CMAKE_CURRENT_BINARY_DIR}/GetGitRevision.cmake
72
    BYPRODUCTS ${GIT_REV_HEADER}
73
    COMMENT "Checking Git revision..."
74
)
75
76
# --- Dependencies ---
77
# The unit tests link no emulator core, so a tests-only build (-DBUILD_EMULATOR=OFF)
78
# has no use for SDL or zlib and should not be blocked by their absence -- that is
79
# what lets the tests run on a bare machine and keeps them honestly independent of
80
# any one display backend. The exceptions are the tests whose sources reach SDL's
81
# headers through glue.h (code_map and timing_speed); those are skipped when SDL
82
# is absent rather than failing the build.
83
if(EMSCRIPTEN)
84
    # Emscripten: SDL2 is a built-in port, not a package we search for.
85
    # We create a "Dummy" target that passes the compiler flags (-s USE_SDL=2)
86
    # to any target that links against it.
87
    add_library(SDL2::SDL2 INTERFACE IMPORTED)
88
    target_compile_options(SDL2::SDL2 INTERFACE "SHELL:-s USE_SDL=2")
89
    target_link_options(SDL2::SDL2 INTERFACE "SHELL:-s USE_SDL=2")
90
91
    set(SDL2_FOUND TRUE)
92
93
    # Emscripten ZLIB (Built-in port)
94
    add_library(ZLIB::ZLIB INTERFACE IMPORTED)
95
    target_compile_options(ZLIB::ZLIB INTERFACE "SHELL:-s USE_ZLIB=1")
96
    target_link_options(ZLIB::ZLIB INTERFACE "SHELL:-s USE_ZLIB=1")
97
98
    set(ZLIB_FOUND TRUE)
99
else()
100
    if(BUILD_EMULATOR)
101
        find_package(SDL2 REQUIRED)
102
        find_package(ZLIB REQUIRED)
103
    else()
104
        find_package(SDL2 QUIET)
105
        find_package(ZLIB QUIET)
106
    endif()
107
    find_package(cJSON CONFIG QUIET)
108
endif()
109
110
find_package(Python3 COMPONENTS Interpreter REQUIRED)
111
find_package(PkgConfig QUIET)
112
113
# Dear ImGui debugger
114
#
115
# An in-process debugger UI in its own window: memory, disassembly, CPU, VERA,
116
# source, breakpoints, symbols and call stack. Opt in at runtime with -imgui.
117
# AUTO builds it when the vendored sources are present, which they are in-tree;
118
# OFF drops the third-party C++ from the build for anyone who does not want it.
119
120
set(ENABLE_IMGUI "AUTO" CACHE STRING "Build the Dear ImGui debugger UI (ON/OFF/AUTO)")
121
set_property(CACHE ENABLE_IMGUI PROPERTY STRINGS ON OFF AUTO)
122
123
set(USE_IMGUI FALSE)
124
# imgui_impl_sdlrenderer2 needs SDL_RenderGeometry(), added in SDL 2.0.17. Some
125
# distributions still ship older SDL2 (Raspbian bullseye, Debian oldstable), so
126
# AUTO has to check rather than assume. find_package sets SDL2_VERSION in config
127
# mode; fall back to pkg-config, and treat "unknown" as too old rather than
128
# assume the best -- an unbuildable configuration is worse than a missing panel.
129
set(IMGUI_MIN_SDL_VERSION 2.0.17)
130
set(IMGUI_SDL_VERSION "${SDL2_VERSION}")
131
if(NOT IMGUI_SDL_VERSION AND PKG_CONFIG_FOUND)
132
    pkg_check_modules(IMGUI_PC_SDL2 QUIET sdl2)
133
    set(IMGUI_SDL_VERSION "${IMGUI_PC_SDL2_VERSION}")
134
endif()
135
136
if(ENABLE_IMGUI STREQUAL "OFF")
137
    message(STATUS "[x16] ImGui debugger explicitly disabled.")
138
elseif(EMSCRIPTEN)
139
    # SDL2's emscripten backend is single-window -- it renders to the one HTML
140
    # canvas -- so the second SDL_CreateWindow the debugger needs cannot
141
    # succeed. Forced off rather than left to fail at runtime, which also keeps
142
    # ~70k lines of dead C++ out of the .wasm download.
143
    if(ENABLE_IMGUI STREQUAL "ON")
144
        message(FATAL_ERROR "[x16] ENABLE_IMGUI=ON is not supported under Emscripten (single-window backend).")
145
    endif()
146
    message(STATUS "[x16] ImGui debugger disabled: unsupported under Emscripten.")
147
elseif(NOT IMGUI_SDL_VERSION OR IMGUI_SDL_VERSION VERSION_LESS IMGUI_MIN_SDL_VERSION)
148
    if(ENABLE_IMGUI STREQUAL "ON")
149
        message(FATAL_ERROR "[x16] ENABLE_IMGUI=ON needs SDL ${IMGUI_MIN_SDL_VERSION} or newer, found '${IMGUI_SDL_VERSION}'.")
150
    endif()
151
    message(STATUS "[x16] ImGui debugger disabled: SDL '${IMGUI_SDL_VERSION}' is older than ${IMGUI_MIN_SDL_VERSION} (SDL_RenderGeometry).")
152
elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/extern/imgui/imgui.cpp")
153
    set(USE_IMGUI TRUE)
154
    message(STATUS "[x16] ImGui debugger enabled (SDL ${IMGUI_SDL_VERSION}).")
155
elseif(ENABLE_IMGUI STREQUAL "ON")
156
    message(FATAL_ERROR "[x16] ENABLE_IMGUI=ON but src/extern/imgui is missing.")
157
else()
158
    message(STATUS "[x16] Vendored ImGui not found; building without the debugger UI.")
159
endif()
160
161
# Debug Adapter Protocol server
162
#
163
# Speaks DAP over a TCP socket so an editor can drive the emulator's debugger.
164
# Needs cJSON. AUTO builds it when cJSON is present and quietly leaves it out
165
# when it is not, so a checkout without the dependency still builds an emulator
166
# -- just one that rejects -dap. ON makes a missing cJSON an error instead.
167
168
set(ENABLE_DAP "AUTO" CACHE STRING "Enable the Debug Adapter Protocol server (ON/OFF/AUTO)")
169
set_property(CACHE ENABLE_DAP PROPERTY STRINGS ON OFF AUTO)
170
171
set(USE_DAP FALSE)
172
if(ENABLE_DAP STREQUAL "OFF")
173
    message(STATUS "[x16] DAP server explicitly disabled.")
174
elseif(TARGET cjson OR TARGET cjson::cjson OR cJSON_FOUND)
175
    set(USE_DAP TRUE)
176
elseif(ENABLE_DAP STREQUAL "ON")
177
    message(FATAL_ERROR "[x16] ENABLE_DAP=ON but cJSON was not found.")
178
else()
179
    message(STATUS "[x16] cJSON not found; building without the DAP server.")
180
endif()
181
182
# Fluidsynth
183
184
set(ENABLE_FLUIDSYNTH "AUTO" CACHE STRING "Enable FluidSynth MIDI support (ON/OFF/AUTO)")
185
set_property(CACHE ENABLE_FLUIDSYNTH PROPERTY STRINGS ON OFF AUTO)
186
187
set(USE_FLUIDSYNTH FALSE)
188
189
if(ENABLE_FLUIDSYNTH STREQUAL "OFF")
190
    message(STATUS "[x16] FluidSynth support explicitly disabled.")
191
elseif(EMSCRIPTEN)
192
    if (ENABLE_FLUIDSYNTH STREQUAL "ON")
193
        message(FATAL_ERROR "[x16] FluidSynth cannot be enabled for wasm builds.")
194
    elseif (ENABLE_FLUIDSYNTH STREQUAL "AUTO")
195
        message(STATUS "[x16] FluidSynth disabled for wasm builds.")
196
    endif()
197
else()
198
    # Try pkg-config first, then fall back to find_package (for vcpkg/MSVC)
199
    if(PKG_CONFIG_FOUND)
200
        if(ENABLE_FLUIDSYNTH STREQUAL "ON")
201
            pkg_check_modules(FLUIDSYNTH REQUIRED IMPORTED_TARGET fluidsynth>=2.0)
202
            set(USE_FLUIDSYNTH TRUE)
203
            message(STATUS "[x16] FluidSynth found and enabled.")
204
        else() 
205
            pkg_check_modules(FLUIDSYNTH IMPORTED_TARGET fluidsynth>=2.0)
206
            if(FLUIDSYNTH_FOUND)
207
                set(USE_FLUIDSYNTH TRUE)
208
                message(STATUS "[x16] FluidSynth found and enabled (auto).")
209
            else()
210
                message(WARNING "[x16] FluidSynth not found. MIDI support disabled (auto).")
211
            endif()
212
        endif()
213
    else()
214
        # Fallback: try find_package (works with vcpkg and system installs)
215
        find_package(FluidSynth CONFIG QUIET)
216
        if(FluidSynth_FOUND OR FLUIDSYNTH_FOUND)
217
            set(USE_FLUIDSYNTH TRUE)
218
            message(STATUS "[x16] FluidSynth found via find_package and enabled.")
219
        elseif(ENABLE_FLUIDSYNTH STREQUAL "ON")
220
            message(FATAL_ERROR "FluidSynth requested (ON), but neither pkg-config nor find_package found it.")
221
        else()
222
            message(WARNING "[x16] pkg-config missing and find_package didn't find FluidSynth. MIDI support disabled.")
223
        endif()
224
    endif()
225
endif()
226
227
# Trace Logging
228
229
set(ENABLE_TRACE "AUTO" CACHE STRING "Enable trace logging support (ON/OFF/AUTO)")
230
set_property(CACHE ENABLE_TRACE PROPERTY STRINGS ON OFF AUTO)
231
232
set(USE_TRACE FALSE)
233
234
if(ENABLE_TRACE STREQUAL "OFF")
235
    message(STATUS "[x16] Trace support explicitly disabled.")
236
elseif(EMSCRIPTEN)
237
    if (ENABLE_TRACE STREQUAL "ON")
238
        message(FATAL_ERROR "[x16] Trace cannot be enabled for wasm builds.")
239
    elseif (ENABLE_TRACE STREQUAL "AUTO")
240
        message(STATUS "[x16] Trace disabled for wasm builds.")
241
    endif()
242
else()
243
    if(ENABLE_TRACE STREQUAL "ON")
244
        if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/rom_lst.h" AND
245
        EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/rom_labels.h")
246
            set(USE_TRACE ON)
247
            message(STATUS "[x16] Trace enabled and headers found (rom_lst.h, rom_labels.h).")
248
        else()
249
            message(FATAL_ERROR "[x16] Trace enabled but headers (rom_lst.h, rom_labels.h) not found.")
250
        endif()
251
    else()
252
        if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/rom_lst.h" AND
253
        EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/rom_labels.h")
254
            set(USE_TRACE ON)
255
            message(STATUS "[x16] Trace enabled (auto) and headers found (rom_lst.h, rom_labels.h).")
256
        else()
257
            message(STATUS "[x16] Trace disabled (auto). Headers (rom_lst.h, rom_labels.h) not found.")
258
        endif()
259
    endif()
260
endif()
261
262
# --- Code Generation (Python Script) ---
263
# This replaces the 'cpu/tables.h' rule in the Makefile
264
set(TABLE_GEN_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/src/cpu/buildtables.py")
265
set(TABLE_OUTPUT_H "${CMAKE_CURRENT_SOURCE_DIR}/src/cpu/tables.h")
266
set(MNEMONIC_OUTPUT_H "${CMAKE_CURRENT_SOURCE_DIR}/src/cpu/mnemonics.h")
267
268
add_custom_command(
269
    OUTPUT ${TABLE_OUTPUT_H} ${MNEMONIC_OUTPUT_H}
270
    COMMAND "${Python3_EXECUTABLE}" "${TABLE_GEN_SCRIPT}"
271
    WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src/cpu"
272
    DEPENDS "${TABLE_GEN_SCRIPT}" "${CMAKE_CURRENT_SOURCE_DIR}/src/cpu/6502.opcodes"
273
    DEPENDS "${TABLE_GEN_SCRIPT}" "${CMAKE_CURRENT_SOURCE_DIR}/src/cpu/65c02.opcodes"
274
    DEPENDS "${TABLE_GEN_SCRIPT}" "${CMAKE_CURRENT_SOURCE_DIR}/src/cpu/65c816.opcodes"
275
    COMMENT "Generating CPU tables..."
276
)
277
# Create a target so the main executable can depend on it
278
add_custom_target(gen_cpu_tables DEPENDS ${TABLE_OUTPUT_H})
279
280
# --- Sources ---
281
set(X16_SOURCES
282
    src/cpu/fake6502.c
283
    src/memory.c
284
    src/io_trace.c
285
    src/perf_budget.c
286
    src/vera_bandwidth.c
287
    src/disasm.c
288
    src/video.c
289
    src/sprite_trace.c
290
    src/i2c.c
291
    src/smc.c
292
    src/rtc.c
293
    src/via.c
294
    src/serial.c
295
    src/ieee.c
296
    src/vera_spi.c
297
    src/audio.c
298
    src/vera_pcm.c
299
    src/vera_psg.c
300
    src/sdcard.c
301
    src/sdcard_fat.c
302
    src/main.c
303
    src/debugger.c
304
    src/dbg_info.c
305
    src/dbg_load.c
306
    src/source_view.c
307
    src/insn_info.c
308
    src/code_map.c
309
    src/debug_core.c
310
    src/cpu/irq_ctx.c
311
    src/javascript_interface.c
312
    src/joystick.c
313
    src/rendertext.c
314
    src/keyboard.c
315
    src/icon.c
316
    src/timing.c
317
    src/wav_recorder.c
318
    src/testbench.c
319
    src/files.c
320
    src/cartridge.c
321
    src/iso_8859_15.c
322
    src/ymglue.cpp
323
    src/midi.c
324
    src/extern/ymfm/src/ymfm_opm.cpp
325
)
326
327
if(USE_IMGUI)
328
    # Vendored Dear ImGui (docking branch) + the SDL2 / SDLRenderer2 backends,
329
    # kept in their own list so the project's strict warnings can be relaxed
330
    # for just these files: ImGui does not build clean under /W3 /WX or
331
    # -Wall -Werror, and it is not ours to fix. The debug_ui sources are
332
    # deliberately NOT in this list -- see the warning settings below.
333
    set(IMGUI_SOURCES
334
        src/extern/imgui/imgui.cpp
335
        src/extern/imgui/imgui_draw.cpp
336
        src/extern/imgui/imgui_tables.cpp
337
        src/extern/imgui/imgui_widgets.cpp
338
        src/extern/imgui/imgui_demo.cpp
339
        src/extern/imgui/backends/imgui_impl_sdl2.cpp
340
        src/extern/imgui/backends/imgui_impl_sdlrenderer2.cpp
341
    )
342
343
    # The debug_ui module: a C-callable core plus self-registering panels.
344
    # Adding a panel means dropping a file under src/debug_ui/panels/ and
345
    # listing it here.
346
    set(DEBUG_UI_SOURCES
347
        src/debug_ui/debug_ui.cpp
348
        src/debug_ui/debug_ui_panels.cpp
349
        src/debug_ui/debug_ui_settings.cpp
350
        src/debug_ui/io_reg_info.cpp
351
        src/debug_ui/panels/memory_panel.cpp
352
        src/debug_ui/panels/disasm_panel.cpp
353
        src/debug_ui/panels/cpu_panel.cpp
354
        src/debug_ui/panels/vera_panel.cpp
355
        src/debug_ui/panels/sprite_multiplex_tab.cpp
356
        src/debug_ui/panels/source_panel.cpp
357
        src/debug_ui/panels/breakpoints_panel.cpp
358
        src/debug_ui/panels/symbols_panel.cpp
359
        src/debug_ui/panels/callstack_panel.cpp
360
        src/debug_ui/panels/psg_panel.cpp
361
        src/debug_ui/panels/fm_panel.cpp
362
        src/debug_ui/panels/pcm_panel.cpp
363
        src/debug_ui/panels/io_panel.cpp
364
    src/debug_ui/panels/perf_panel.cpp
365
    )
366
367
    list(APPEND X16_SOURCES ${IMGUI_SOURCES} ${DEBUG_UI_SOURCES})
368
endif()
369
370
if(WIN32)
371
    list(APPEND X16_SOURCES src/video_win32.c)
372
endif()
373
374
if(USE_DAP)
375
    list(APPEND X16_SOURCES src/debug_server.c)
376
endif()
377
378
# --- Main Executable Target ---
379
# Guarded so a tests-only build skips the emulator and its SDL dependency. The
380
# body is left un-indented deliberately: CMake ignores whitespace, and
381
# re-indenting ~150 lines would bury the one-line change in noise.
382
if(BUILD_EMULATOR)
383
384
add_executable(x16emu ${X16_SOURCES})
385
386
# Ensure the Python script runs before compiling x16emu
387
add_dependencies(x16emu gen_cpu_tables)
388
389
# Add git revision header
390
add_dependencies(x16emu update_git_rev)
391
392
# Includes
393
target_include_directories(x16emu PRIVATE
394
    src
395
    src/extern/include
396
    src/extern/ymfm/src
397
    ${GIT_REV_HEADER_DIR}
398
)
399
400
if(USE_IMGUI)
401
    target_include_directories(x16emu PRIVATE
402
        src/extern/imgui
403
        src/extern/imgui/backends
404
        src/extern/imgui_club
405
        src/debug_ui
406
    )
407
    target_compile_definitions(x16emu PRIVATE HAS_IMGUI)
408
    # Vendored ImGui does not build clean under this project's warning level,
409
    # and it is not ours to fix -- so warnings are silenced for those files
410
    # only. The debug_ui sources ARE ours and are held to the same standard as
411
    # the rest of the tree; suppressing them too would have hidden real defects
412
    # in the code most likely to contain them.
413
    if(MSVC)
414
        set_source_files_properties(${IMGUI_SOURCES} PROPERTIES COMPILE_OPTIONS "/w")
415
    else()
416
        set_source_files_properties(${IMGUI_SOURCES} PROPERTIES COMPILE_OPTIONS "-w")
417
    endif()
418
endif()
419
420
if(USE_TRACE)
421
    target_compile_definitions(x16emu PRIVATE TRACE)
422
endif()
423
424
# Linking
425
target_link_libraries(x16emu PRIVATE
426
    SDL2::SDL2
427
    ZLIB::ZLIB
428
)
429
430
if(TARGET SDL2::SDL2main)
431
    target_link_libraries(x16emu PRIVATE SDL2::SDL2main)
432
endif()
433
434
if(USE_DAP)
435
    target_compile_definitions(x16emu PRIVATE HAS_DAP)
436
    if(TARGET cjson::cjson)
437
        target_link_libraries(x16emu PRIVATE cjson::cjson)
438
    else()
439
        target_link_libraries(x16emu PRIVATE cjson)
440
    endif()
441
    if(WIN32)
442
        target_link_libraries(x16emu PRIVATE ws2_32)
443
    endif()
444
endif()
445
446
if(USE_FLUIDSYNTH)
447
    add_compile_definitions(HAS_FLUIDSYNTH)
448
    if(TARGET PkgConfig::FLUIDSYNTH)
449
        target_link_libraries(x16emu PRIVATE PkgConfig::FLUIDSYNTH)
450
    elseif(TARGET FluidSynth::libfluidsynth)
451
        target_link_libraries(x16emu PRIVATE FluidSynth::libfluidsynth)
452
    elseif(FLUIDSYNTH_LIBRARIES)
453
        target_link_libraries(x16emu PRIVATE ${FLUIDSYNTH_LIBRARIES})
454
        target_include_directories(x16emu PRIVATE ${FLUIDSYNTH_INCLUDE_DIRS})
455
    endif()
456
endif()
457
458
# Windows Specifics
459
if(WIN32)
460
    # MinGW Linker flags
461
    if(MINGW)
462
        target_link_options(x16emu PRIVATE
463
            -static-libstdc++
464
            -static-libgcc
465
            -Wl,--subsystem,console
466
        )
467
    endif()
468
    if(MSVC)
469
        target_link_options(x16emu PRIVATE /SUBSYSTEM:CONSOLE)
470
    endif()
471
    target_link_libraries(x16emu PRIVATE dwmapi)
472
endif()
473
474
# macOS Specifics
475
if(APPLE)
476
477
    find_library(COREAUDIO CoreAudio REQUIRED)
478
    find_library(AUDIOTOOLBOX AudioToolbox REQUIRED)
479
    find_library(FORCEFEEDBACK ForceFeedback REQUIRED)
480
    find_library(COREVIDEO CoreVideo REQUIRED)
481
    find_library(COCOA Cocoa REQUIRED)
482
    find_library(CARBON Carbon REQUIRED)
483
    find_library(IOKIT IOKit REQUIRED)
484
    find_library(ICONV iconv REQUIRED)
485
    find_library(QUARTZCORE QuartzCore REQUIRED)
486
    find_library(METAL Metal REQUIRED)
487
    find_library(COREHAPTICS CoreHaptics REQUIRED)
488
    find_library(GAMECONTROLLER GameController REQUIRED)
489
490
    target_link_libraries(x16emu PRIVATE
491
        ${COREAUDIO} ${AUDIOTOOLBOX} ${FORCEFEEDBACK}
492
        ${COREVIDEO} ${COCOA} ${CARBON} ${IOKIT} ${ICONV}
493
        ${QUARTZCORE} ${METAL} ${COREHAPTICS} ${GAMECONTROLLER}
494
    )
495
endif()
496
497
# Linux/Default Specifics
498
if(UNIX AND NOT APPLE AND NOT EMSCRIPTEN)
499
    target_link_libraries(x16emu PRIVATE dl pthread m)
500
endif()
501
502
# Emscripten
503
if(EMSCRIPTEN)
504
    set_target_properties(x16emu PROPERTIES SUFFIX ".html")
505
    target_link_options(x16emu PRIVATE
506
        --shell-file ${CMAKE_CURRENT_SOURCE_DIR}/webassembly/x16emu-template.html
507
        --preload-file ${CMAKE_CURRENT_SOURCE_DIR}/build/rom.bin
508
        "SHELL:-s TOTAL_MEMORY=32MB"
509
        "SHELL:-s ASSERTIONS=1"
510
        "SHELL:-s DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=1"
511
        "SHELL:-s EXPORTED_FUNCTIONS=['_j2c_reset','_j2c_paste','_j2c_start_audio','_main']"
512
        "SHELL:-s EXPORTED_RUNTIME_METHODS=['ccall','cwrap']"
513
        "SHELL:-s USE_ZLIB=1"
514
        "SHELL:-s EXIT_RUNTIME=1"
515
    )
516
endif()
517
518
# --- Secondary Target: Makecart ---
519
add_executable(makecart
520
    src/makecart.c
521
    src/files.c
522
    src/cartridge.c
523
    src/makecart_javascript_interface.c
524
)
525
526
add_dependencies(makecart update_git_rev)
527
528
# Makecart dependencies
529
target_include_directories(makecart PRIVATE
530
    src
531
    src/extern/include
532
    ${GIT_REV_HEADER_DIR}
533
)
534
target_link_libraries(makecart PRIVATE
535
    ZLIB::ZLIB
536
    SDL2::SDL2
537
)
538
539
if(TARGET SDL2::SDL2main)
540
    target_link_libraries(makecart PRIVATE SDL2::SDL2main)
541
endif()
542
543
if(EMSCRIPTEN)
544
    set_target_properties(makecart PROPERTIES SUFFIX ".html")
545
    target_link_options(makecart PRIVATE "SHELL:-s USE_ZLIB=1")
546
endif()
547
548
endif() # BUILD_EMULATOR
549
550
# --- Optional: unit tests ---
551
# Every test is off by default so none of them affect the normal `x16emu` build.
552
# -DBUILD_TESTS=ON turns the lot on at once, which is what CI does; the per-test
553
# options remain for building a single one while working on it. Each test stubs
554
# out whatever it needs from the emulator core, so none of them link x16emu, and
555
# none of them need a ROM.
556
#
557
# Emscripten is excluded throughout: the output there is .js/.wasm, which ctest
558
# cannot execute as a plain binary.
559
option(BUILD_TESTS "Build every unit test" OFF)
560
561
# add_test() only writes a CTestTestfile when testing is enabled, so this has to
562
# come before the x16_add_test() calls below.
563
if(NOT EMSCRIPTEN)
564
    enable_testing()
565
endif()
566
567
# Everything x16_add_test() registers hangs off this, so CI can build the whole
568
# suite by name without naming each test -- and without a bare --build, which
569
# would drag in the emulator and duplicate what the platform jobs already report.
570
# Without it, "adding a test is one line" would be false: the workflow would be
571
# a second place to remember, and forgetting it leaves ctest running executables
572
# that were never compiled.
573
add_custom_target(unit_tests)
574
575
# x16_add_test(<name> SOURCES <src>... [NEEDS_SDL] [NEEDS_CPU_TABLES])
576
#
577
# Declares the per-test BUILD_<NAME>_TEST option, builds tests/<name>_test from
578
# SOURCES, and registers it with ctest. Adding a test is therefore one line in
579
# one place, which matters when many tests land in parallel: a shared block per
580
# test would make this file a standing merge conflict.
581
#
582
# NEEDS_SDL marks a test whose sources reach SDL's headers (via glue.h). Those
583
# are skipped rather than failing the build when SDL is absent, so the tests that
584
# genuinely stand alone still run on a machine without it.
585
function(x16_add_test name)
586
    cmake_parse_arguments(T "NEEDS_SDL;NEEDS_CPU_TABLES" "" "SOURCES" ${ARGN})
587
588
    string(TOUPPER "${name}" name_uc)
589
    option(BUILD_${name_uc}_TEST "Build the ${name} unit test" OFF)
590
591
    if(EMSCRIPTEN)
592
        return()
593
    endif()
594
    if(NOT BUILD_TESTS AND NOT BUILD_${name_uc}_TEST)
595
        return()
596
    endif()
597
    if(T_NEEDS_SDL AND NOT SDL2_FOUND)
598
        message(STATUS "SDL2 not found: skipping ${name} test")
599
        return()
600
    endif()
601
602
    add_executable(${name}_test ${T_SOURCES})
603
    target_include_directories(${name}_test PRIVATE src)
604
    if(T_NEEDS_SDL)
605
        target_include_directories(${name}_test PRIVATE ${SDL2_INCLUDE_DIRS})
606
    endif()
607
    if(T_NEEDS_CPU_TABLES)
608
        add_dependencies(${name}_test gen_cpu_tables)
609
    endif()
610
    add_dependencies(unit_tests ${name}_test)
611
    add_test(NAME ${name} COMMAND ${name}_test)
612
endfunction()
613
614
# dbg_info.c has no dependency on the emulator core, so this links it on its own.
615
x16_add_test(dbg_info
616
    SOURCES tests/test_dbg_info.c src/dbg_info.c)
617
618
# code_map.c leans on only disasm(), dbg_info and two core symbols, so the test
619
# supplies its own memory and register file rather than linking the emulator
620
# core. disasm.c still includes SDL headers, and the generated cpu/mnemonics.h.
621
x16_add_test(code_map NEEDS_SDL NEEDS_CPU_TABLES
622
    SOURCES tests/test_code_map.c src/code_map.c src/disasm.c src/dbg_info.c)
623
624
# debug_core.c reaches for only the register file, the bank registers and a debug
625
# memory read, so the test supplies its own and links no emulator core.
626
x16_add_test(debug_core
627
    SOURCES tests/test_debug_core.c src/debug_core.c)
628
629
# The speed arithmetic in timing.c depends only on the machine's configured
630
# clock, so the test supplies the few emulator globals it touches.
631
x16_add_test(timing_speed NEEDS_SDL
632
    SOURCES tests/test_timing_speed.c src/timing.c)
633
634
# irq_ctx.c is pure bookkeeping with no dependencies, so the test links it alone.
635
x16_add_test(irq_ctx
636
    SOURCES tests/test_irq_ctx.c src/cpu/irq_ctx.c)
637
638
# dbg_load.c reports loads to dbg_info and source_view, so the test links those
639
# two alongside it. dbg_info.c has no dependency on the emulator core either.
640
x16_add_test(dbg_load
641
    SOURCES tests/test_dbg_load.c src/dbg_load.c src/dbg_info.c src/source_view.c)
642
643
# vera_pcm.c includes only its own header and libc, so the test links it alone.
644
x16_add_test(vera_pcm
645
    SOURCES tests/test_vera_pcm.c tests/support/harness.c src/vera_pcm.c)
646
647
# io_trace.c is deliberately free of emulator dependencies -- memory.c calls it,
648
# and memory.c is linked into tests that pair it with fake devices -- so the
649
# test links it alone, with no CPU, no memory and no SDL.
650
x16_add_test(io_trace
651
    SOURCES tests/test_io_trace.c tests/support/harness.c src/io_trace.c)
652
653
# sprite_trace.c is fed scalars by video.c rather than reaching into it, which is
654
# what lets the multiplexing analysis -- generation lifetimes, effective versus
655
# phantom sprites, budget overrun, burst costing -- be driven directly here
656
# without standing up a VERA.
657
x16_add_test(sprite_trace
658
    SOURCES tests/test_sprite_trace.c tests/support/harness.c src/sprite_trace.c)
659
660
# perf_budget.c takes everything it knows about the machine as an argument, for
661
# exactly this reason: the cycle classification and the statistics on top of it
662
# can be driven directly, with no CPU to run, no video to raise a frame and no
663
# SDL to link.
664
x16_add_test(perf_budget
665
    SOURCES tests/test_perf_budget.c tests/support/harness.c src/perf_budget.c)
666
667
# vera_bandwidth.c is the same shape as perf_budget.c and for the same reason:
668
# it takes a layer's mode as five scalars rather than video.c's property struct,
669
# so VERA's fetch arithmetic -- which is where every bandwidth figure comes from
670
# -- can be checked against the RTL's decode tables with nothing else standing.
671
x16_add_test(vera_bandwidth
672
    SOURCES tests/test_vera_bandwidth.c tests/support/harness.c src/vera_bandwidth.c)
673
674
# The FAT index parses untrusted binary data, so the test builds synthetic FAT16
675
# and FAT32 images and reads them back. It stubs the five file-access functions
676
# onto stdio rather than linking src/files.c, which would drag in SDL and zlib
677
# to test nothing extra: what is under test is the parser.
678
x16_add_test(sdcard_fat
679
    SOURCES tests/test_sdcard_fat.c tests/support/harness.c src/sdcard_fat.c)
680
681
# vera_psg.c likewise has no dependency beyond its own header and libc.
682
x16_add_test(vera_psg
683
    SOURCES tests/test_vera_psg.c tests/support/harness.c src/vera_psg.c)
684
685
# The real video.c, which is VERA plus the SDL host in one file. The fixture
686
# supplies the host half so the emulation half can be driven directly; the audio
687
# modules are linked for real because video.c routes $9F3B-$9F3D into them and
688
# they have no dependencies of their own.
689
x16_add_test(vera_video NEEDS_SDL
690
    SOURCES tests/test_vera_video.c tests/support/video_fixture.c tests/support/harness.c
691
            src/video.c src/sprite_trace.c src/vera_bandwidth.c src/vera_pcm.c src/vera_psg.c src/vera_spi.c)
692
693
# Sprite multiplexing end to end: attributes rewritten part-way down a frame,
694
# measured through the real renderer rather than through the recorder's API.
695
x16_add_test(sprite_multiplex NEEDS_SDL
696
    SOURCES tests/test_sprite_multiplex.c tests/support/video_fixture.c tests/support/harness.c
697
            src/video.c src/sprite_trace.c src/vera_bandwidth.c src/vera_pcm.c src/vera_psg.c src/vera_spi.c)
698
699
if(TARGET sprite_multiplex_test)
700
    target_include_directories(sprite_multiplex_test PRIVATE src src/extern/include)
701
    if(TARGET SDL2::SDL2)
702
        target_link_libraries(sprite_multiplex_test PRIVATE SDL2::SDL2)
703
    endif()
704
    if(UNIX AND NOT APPLE)
705
        target_link_libraries(sprite_multiplex_test PRIVATE m)
706
    endif()
707
endif()
708
709
# video.c includes gif.h, which is vendored rather than sitting alongside it.
710
# It also calls SDL directly from its host half, so unlike the other NEEDS_SDL
711
# tests -- which only need the headers -- this one links the library too.
712
if(TARGET vera_video_test)
713
    target_include_directories(vera_video_test PRIVATE src/extern/include)
714
    if(TARGET SDL2::SDL2)
715
        target_link_libraries(vera_video_test PRIVATE SDL2::SDL2)
716
    endif()
717
    # video.c calls round(). The emulator picks libm up transitively from its
718
    # other dependencies; this target links fewer of them, so it asks directly.
719
    if(UNIX AND NOT APPLE)
720
        target_link_libraries(vera_video_test PRIVATE m)
721
    endif()
722
endif()
723
724
# The CPU core reaches outside itself for only six symbols, all supplied by the
725
# fixture, so this links the real instruction tables against a flat 64K memory
726
# and nothing else. irq_ctx.c comes along because fake6502.c reports interrupt
727
# entry and exit to it.
728
x16_add_test(cpu_smoke NEEDS_CPU_TABLES
729
    SOURCES tests/test_cpu_smoke.c tests/support/cpu_fixture.c tests/support/harness.c
730
            src/cpu/fake6502.c src/cpu/irq_ctx.c)
731
732
x16_add_test(cpu_loadstore NEEDS_CPU_TABLES
733
    SOURCES tests/test_cpu_loadstore.c tests/support/cpu_fixture.c tests/support/harness.c
734
            src/cpu/fake6502.c src/cpu/irq_ctx.c)
735
736
x16_add_test(cpu_adc_sbc NEEDS_CPU_TABLES
737
    SOURCES tests/test_cpu_adc_sbc.c tests/support/cpu_fixture.c tests/support/harness.c
738
            src/cpu/fake6502.c src/cpu/irq_ctx.c)
739
740
x16_add_test(cpu_decimal NEEDS_CPU_TABLES
741
    SOURCES tests/test_cpu_decimal.c tests/support/cpu_fixture.c tests/support/harness.c
742
            src/cpu/fake6502.c src/cpu/irq_ctx.c)
743
744
x16_add_test(cpu_steprun NEEDS_CPU_TABLES
745
    SOURCES tests/test_cpu_steprun.c tests/support/cpu_fixture.c tests/support/harness.c
746
            src/cpu/fake6502.c src/cpu/irq_ctx.c)
747
748
# Klaus Dormann's functional tests: a program that walks every opcode and
749
# checks its own results. The binaries are fetched, not committed, and the test
750
# reports skipped without them.
751
x16_add_test(klaus NEEDS_CPU_TABLES
752
    SOURCES tests/test_klaus.c tests/support/cpu_fixture.c tests/support/harness.c
753
            src/cpu/fake6502.c src/cpu/irq_ctx.c)
754
755
# SingleStepTests/ProcessorTests: every opcode, thousands of randomised states
756
# each. Fixtures are fetched by tests/fetch_pt.py and not committed.
757
x16_add_test(processor_tests NEEDS_CPU_TABLES
758
    SOURCES tests/test_processor_tests.c tests/support/cpu_fixture.c
759
            tests/support/harness.c src/cpu/fake6502.c src/cpu/irq_ctx.c)
760
761
# The same binary over the 65816 suites. One executable rather than three: the
762
# fixtures differ only in which cases they hold, and each case says which core
763
# to run it on. Registered separately so a failure names the mode.
764
if(TARGET processor_tests_test)
765
    add_test(NAME processor_tests_816_emu
766
             COMMAND processor_tests_test 816-emu)
767
    add_test(NAME processor_tests_816_native
768
             COMMAND processor_tests_test 816-native)
769
endif()
770
771
# The generated opcode tables against the published 65C02 spec. ProcessorTests
772
# measures what the hardware does; this checks the tables still agree with the
773
# documentation, which is a different question and has disagreed once.
774
add_test(NAME opcode_spec
775
         COMMAND "${Python3_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/tests/check_opcode_spec.py")
776
777
# The VERA tests cite Verilog by file and line, which only means anything
778
# against one revision -- the one the emulator reports itself to be. This fails
779
# if src/video.c and the RTL pin in tests/fetch_vera_rtl.py drift apart, so a
780
# version bump has to be a deliberate step that re-checks the citations.
781
add_test(NAME vera_version
782
         COMMAND "${Python3_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/tests/check_vera_version.py")
783
784
# VERA's palette RAM is initialised from a memory file baked into the FPGA
785
# bitstream, so the default palette is hardware rather than a ROM convention.
786
# Skips when the RTL has not been fetched.
787
add_test(NAME vera_palette
788
         COMMAND "${Python3_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/tests/check_vera_palette.py")
789
790
# Register banking: the same addresses carry different registers per DCSEL.
791
x16_add_test(vera_regbank NEEDS_SDL
792
    SOURCES tests/test_vera_regbank.c tests/support/video_fixture.c tests/support/harness.c
793
            src/video.c src/sprite_trace.c src/vera_bandwidth.c src/vera_pcm.c src/vera_psg.c src/vera_spi.c)
794
795
if(TARGET vera_regbank_test)
796
    target_include_directories(vera_regbank_test PRIVATE src/extern/include)
797
    if(TARGET SDL2::SDL2)
798
        target_link_libraries(vera_regbank_test PRIVATE SDL2::SDL2)
799
    endif()
800
    if(UNIX AND NOT APPLE)
801
        target_link_libraries(vera_regbank_test PRIVATE m)
802
    endif()
803
endif()
804
805
# The value half of the debugOn contract: a debug read must report what a real
806
# read would. The existing contract test drives recording fakes, so it can only
807
# check side effects; this links the real video.c.
808
x16_add_test(vera_debug_read NEEDS_SDL
809
    SOURCES tests/test_vera_debug_read.c tests/support/video_fixture.c tests/support/harness.c
810
            src/video.c src/sprite_trace.c src/vera_bandwidth.c src/vera_pcm.c src/vera_psg.c src/vera_spi.c)
811
812
if(TARGET vera_debug_read_test)
813
    target_include_directories(vera_debug_read_test PRIVATE src/extern/include)
814
    if(TARGET SDL2::SDL2)
815
        target_link_libraries(vera_debug_read_test PRIVATE SDL2::SDL2)
816
    endif()
817
    if(UNIX AND NOT APPLE)
818
        target_link_libraries(vera_debug_read_test PRIVATE m)
819
    endif()
820
endif()
821
822
# The interrupt latch and mask: which ISR bits a write can clear, and which
823
# IEN bits a write can store.
824
x16_add_test(vera_irq NEEDS_SDL
825
    SOURCES tests/test_vera_irq.c tests/support/video_fixture.c tests/support/harness.c
826
            src/video.c src/sprite_trace.c src/vera_bandwidth.c src/vera_pcm.c src/vera_psg.c src/vera_spi.c)
827
828
if(TARGET vera_irq_test)
829
    target_include_directories(vera_irq_test PRIVATE src/extern/include)
830
    if(TARGET SDL2::SDL2)
831
        target_link_libraries(vera_irq_test PRIVATE SDL2::SDL2)
832
    endif()
833
    if(UNIX AND NOT APPLE)
834
        target_link_libraries(vera_irq_test PRIVATE m)
835
    endif()
836
endif()
837
838
# What a reset leaves behind: derived state must not outlive the registers it
839
# was derived from.
840
x16_add_test(vera_reset NEEDS_SDL
841
    SOURCES tests/test_vera_reset.c tests/support/video_fixture.c tests/support/harness.c
842
            src/video.c src/sprite_trace.c src/vera_bandwidth.c src/vera_pcm.c src/vera_psg.c src/vera_spi.c)
843
844
if(TARGET vera_reset_test)
845
    target_include_directories(vera_reset_test PRIVATE src/extern/include)
846
    if(TARGET SDL2::SDL2)
847
        target_link_libraries(vera_reset_test PRIVATE SDL2::SDL2)
848
    endif()
849
    if(UNIX AND NOT APPLE)
850
        target_link_libraries(vera_reset_test PRIVATE m)
851
    endif()
852
endif()
853
854
# The layer registers, and the map and tile base addresses derived from them.
855
x16_add_test(vera_layer NEEDS_SDL
856
    SOURCES tests/test_vera_layer.c tests/support/video_fixture.c tests/support/harness.c
857
            src/video.c src/sprite_trace.c src/vera_bandwidth.c src/vera_pcm.c src/vera_psg.c src/vera_spi.c)
858
859
if(TARGET vera_layer_test)
860
    target_include_directories(vera_layer_test PRIVATE src/extern/include)
861
    if(TARGET SDL2::SDL2)
862
        target_link_libraries(vera_layer_test PRIVATE SDL2::SDL2)
863
    endif()
864
    if(UNIX AND NOT APPLE)
865
        target_link_libraries(vera_layer_test PRIVATE m)
866
    endif()
867
endif()
868
869
# Which row of a layer each display line shows: the vertical half of the tile
870
# address path.
871
x16_add_test(vera_layer_rows NEEDS_SDL
872
    SOURCES tests/test_vera_layer_rows.c tests/support/video_fixture.c tests/support/harness.c
873
            src/video.c src/sprite_trace.c src/vera_bandwidth.c src/vera_pcm.c src/vera_psg.c src/vera_spi.c)
874
875
if(TARGET vera_layer_rows_test)
876
    target_include_directories(vera_layer_rows_test PRIVATE src/extern/include)
877
    if(TARGET SDL2::SDL2)
878
        target_link_libraries(vera_layer_rows_test PRIVATE SDL2::SDL2)
879
    endif()
880
    if(UNIX AND NOT APPLE)
881
        target_link_libraries(vera_layer_rows_test PRIVATE m)
882
    endif()
883
endif()
884
885
# The 65C22's interrupt flags and enables. via.c pulls in memory.h, which
886
# includes SDL.h, so it needs the headers -- but nothing here links SDL.
887
x16_add_test(via_irq NEEDS_SDL
888
    SOURCES tests/test_via_irq.c tests/support/via_fixture.c tests/support/harness.c
889
            src/via.c)
890
891
# The 65C22's interval timers: one-shot against free-run, and where the next
892
# count comes from.
893
x16_add_test(via_timers NEEDS_SDL
894
    SOURCES tests/test_via_timers.c tests/support/via_fixture.c tests/support/harness.c
895
            src/via.c)
896
897
# The SNES controller ports the VIA above clocks: the latch/shift register and
898
# the virtual joystick that drives a port with no gamepad attached. io_trace.c
899
# comes along because the latch path reports to it, and has no dependencies of
900
# its own.
901
x16_add_test(joystick NEEDS_SDL
902
    SOURCES tests/test_joystick.c tests/support/harness.c
903
            src/joystick.c src/io_trace.c)
904
905
# joystick.c enumerates controllers through SDL, so unlike the NEEDS_SDL tests
906
# that only want the headers, this one links the library. The test never calls
907
# joystick_init() -- the virtual path exists precisely so it does not have to --
908
# but those calls still have to resolve.
909
if(TARGET joystick_test)
910
    if(TARGET SDL2::SDL2)
911
        target_link_libraries(joystick_test PRIVATE SDL2::SDL2)
912
    endif()
913
endif()
914
915
# memory.c routes every I/O access, and carries the debugOn flag that says
916
# whether a read is the debugger looking or the machine running. The devices
917
# behind it are recording fakes; memory.c, debug_core.c and the CPU core are
918
# real, so this exercises the actual routing, watchpoint and cycle accounting.
919
x16_add_test(debugon_contract NEEDS_SDL NEEDS_CPU_TABLES
920
    SOURCES tests/test_debugon_contract.c tests/support/fake_devices.c
921
            tests/support/harness.c
922
            src/memory.c src/debug_core.c src/cpu/fake6502.c src/cpu/irq_ctx.c
923
            src/io_trace.c src/perf_budget.c)
924
925
# RAM and ROM banking: the registers at $0000 and $0001 and the windows they
926
# steer. Same real memory.c and fake devices as the debugOn tests.
927
x16_add_test(memory_banking NEEDS_SDL NEEDS_CPU_TABLES
928
    SOURCES tests/test_memory_banking.c tests/support/fake_devices.c
929
            tests/support/harness.c
930
            src/memory.c src/debug_core.c src/cpu/fake6502.c src/cpu/irq_ctx.c
931
            src/io_trace.c src/perf_budget.c)
932
933
# The write half of the debugOn contract, which does not exist: pins what a
934
# debugger's edit costs and disturbs, since nothing can tell it apart from a
935
# store the program executed.
936
x16_add_test(debug_write_path NEEDS_SDL NEEDS_CPU_TABLES
937
    SOURCES tests/test_debug_write_path.c tests/support/fake_devices.c
938
            tests/support/harness.c
939
            src/memory.c src/debug_core.c src/cpu/fake6502.c src/cpu/irq_ctx.c
940
            src/io_trace.c src/perf_budget.c)
941
942
# The watchpoint hook sits on the store path, so this links the same real
943
# memory.c, debug_core.c and CPU core as the debugOn tests, and asserts that
944
# watching an address changes nothing except that a break is reported.
945
x16_add_test(watchpoint_purity NEEDS_SDL NEEDS_CPU_TABLES
946
    SOURCES tests/test_watchpoint_purity.c tests/support/fake_devices.c
947
            tests/support/signature.c tests/support/harness.c
948
            src/memory.c src/debug_core.c src/cpu/fake6502.c src/cpu/irq_ctx.c
949
            src/io_trace.c src/perf_budget.c)
950
951
# Build summary
952
953
if(ENABLE_FLUIDSYNTH STREQUAL "AUTO" AND NOT USE_FLUIDSYNTH)
954
    set(FLUID_EN_MSG "${ColorYellow}DISABLED (Missing Dependency)${ColorReset}")
955
elseif(USE_FLUIDSYNTH)
956
    set(FLUID_EN_MSG "${ColorGreen}ENABLED${ColorReset}")
957
else()
958
    set(FLUID_EN_MSG "DISABLED (Explicit)")
959
endif()
960
961
if(ENABLE_TRACE STREQUAL "AUTO" AND NOT USE_TRACE)
962
    set(TRACE_EN_MSG "${ColorYellow}DISABLED (Missing ROM Headers)${ColorReset}")
963
elseif(USE_TRACE)
964
    set(TRACE_EN_MSG "${ColorGreen}ENABLED${ColorReset}")
965
else()
966
    set(TRACE_EN_MSG "DISABLED (Explicit)")
967
endif()
968
969
message(STATUS "\n")
970
message(STATUS "=========================================================================")
971
message(STATUS "   x16-emulator Build Options Summary")
972
message(STATUS "=========================================================================")
973
message(STATUS "   Fluidsynth Support : ${FLUID_EN_MSG}")
974
message(STATUS "   Trace Support      : ${TRACE_EN_MSG}")
975
message(STATUS "=========================================================================\n")