Files
picogus/sw/CMakeLists.txt
T

784 lines
28 KiB
CMake

# Generated Cmake Pico project file
cmake_minimum_required(VERSION 3.13)
set(PICO_BOARD_HEADER_DIRS ${CMAKE_CURRENT_LIST_DIR}/boards)
if(NOT PICO_BOARD)
set(PICO_BOARD "picogus2")
message("PICO_BOARD not set, defaulting to ${PICO_BOARD}")
endif()
set(PICO_COPY_TO_RAM 1)
# Initialise pico_sdk from installed location
# (note this can come from environment, CMake cache etc)
# to manually set Pico SDK path, uncomment this with your path.
# Otherwise, the environment variable PICO_SDK_PATH will be used.
#set(PICO_SDK_PATH "${CMAKE_SOURCE_DIR}/../../pico/pico-sdk")
# Pull in Raspberry Pi Pico SDK (must be before project)
include(pico_sdk_import.cmake)
project(picogus
VERSION "4.1.0"
LANGUAGES C CXX ASM
)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
include(pico_extras_import.cmake)
#set(PICO_DEOPTIMIZED_DEBUG "1")
#set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_BUILD_TYPE "Release")
#set(SKIP_PICO_MALLOC 1)
if(NOT PROJECT_TYPE)
set(PROJECT_TYPE "GUS")
message("PROJECT_TYPE not set, defaulting to ${PROJECT_TYPE}")
endif()
set(PICO_TINYUSB_PATH ${CMAKE_CURRENT_LIST_DIR}/tinyusb)
# Initialise the Raspberry Pi Pico SDK
pico_sdk_init()
################################################################################
# Helper function for setting linker script
function(set_linker_script TARGET script)
target_link_directories(${TARGET} PRIVATE ${CMAKE_SOURCE_DIR}/multifw)
pico_set_linker_script(${TARGET} ${script})
# Add dependencies on the 'included' linker scripts so that the target gets
# rebuilt if they are changed
pico_add_link_depend(${TARGET} ${script})
endfunction()
option(PGDEBUG "Enable debug printf framework" OFF)
find_package(Python3 COMPONENTS Interpreter QUIET)
# Global definitions across all targets
add_compile_definitions(
# 370MHz is extremely closely evenly divisible by 44100Hz.
# Actual overclock happens at runtime via overclock_370mhz() since 370MHz
# requires PLL REFDIV=2 which can't be set via SDK boot-time defaults.
RP2_CLOCK_SPEED=370000
PICO_DEFAULT_UART=0
PICO_DEFAULT_UART_TX_PIN=28
PICO_DEFAULT_UART_RX_PIN=-1
PICO_DEFAULT_UART_BAUD_RATE=230400
PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS=250
)
################################################################################
# Helper function for common firmware build
function(config_target TARGET_NAME MULTIFW)
# Add executable. Default name is the project name, version 0.1
add_executable(${TARGET_NAME} picogus.cpp)
pico_set_program_version(${TARGET_NAME} ${CMAKE_PROJECT_VERSION})
# Add include directory for the new structure
target_include_directories(${TARGET_NAME} PRIVATE
${CMAKE_CURRENT_LIST_DIR}
)
target_compile_definitions(${TARGET_NAME} PRIVATE
USE_AUDIO_I2S=1
PICO_AUDIO_I2S_DATA_PIN=16
PICO_AUDIO_I2S_CLOCK_PIN_BASE=17
PICO_AUDIO_I2S_PIO=1
PICO_AUDIO_I2S_SM=3
M62429_PIO=1
)
if(USE_LTO)
# Pico SDK must be patched to allow for LTO so it is not enabled by default.
# To patch to Pico SDK, run:
# sed -i 's/WRAPPER_FUNC(x) __wrap_/WRAPPER_FUNC(x) __attribute__((used)) __wrap_/' "$PICO_SDK_PATH"/src/rp2_common/pico_platform/include/pico/platform.h
target_compile_options(${TARGET_NAME} PRIVATE -flto=jobserver)
endif()
target_sources(${TARGET_NAME} PRIVATE system/pico_reflash.c system/flash_settings.c)
# target_compile_options(${TARGET_NAME} PRIVATE -save-temps -fverbose-asm)
if(MULTIFW)
set_linker_script(${TARGET_NAME} ${CMAKE_BINARY_DIR}/${TARGET_NAME}.ld)
endif()
if(USB_JOYSTICK OR USB_MOUSE OR CDROM)
set(USB_STACK TRUE)
endif()
if (USB_STACK)
# USB stack common stuff
target_link_libraries(${TARGET_NAME} tinyusb_host)
target_compile_definitions(${TARGET_NAME} PRIVATE USB_STACK=1)
target_sources(${TARGET_NAME} PRIVATE usb_hid/hid_app.c)
endif()
if(USB_JOYSTICK)
# Joystick stuff
target_link_libraries(${TARGET_NAME} hardware_pwm)
target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/usb_hid)
target_link_libraries(${TARGET_NAME} xinput_host)
target_compile_definitions(${TARGET_NAME} PRIVATE USB_JOYSTICK=1)
endif()
if (USB_MOUSE)
# USB Mouse stuff
target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/mouse)
target_compile_definitions(${TARGET_NAME} PRIVATE USB_MOUSE=1)
target_sources(${TARGET_NAME} PRIVATE
mouse/8250uart.cpp
mouse/sermouse.cpp
)
endif()
if(CDROM)
target_link_libraries(${TARGET_NAME} cdrom)
target_sources(${TARGET_NAME} PRIVATE
mke/mke.c
cdrom/msc_app.c
)
target_compile_definitions(${TARGET_NAME} PRIVATE CDROM=1)
target_sources(${TARGET_NAME} PRIVATE
${CMAKE_CURRENT_LIST_DIR}/fatfs/source/ff.c
${CMAKE_CURRENT_LIST_DIR}/fatfs/source/ffsystem.c
${CMAKE_CURRENT_LIST_DIR}/fatfs/source/ffunicode.c
)
target_include_directories(${TARGET_NAME} PRIVATE
${CMAKE_CURRENT_LIST_DIR}/fatfs/source/
)
endif()
target_sources(${TARGET_NAME} PRIVATE
M62429/M62429.cpp
system/pico_pic.c
)
pico_generate_pio_header(${TARGET_NAME} ${CMAKE_CURRENT_LIST_DIR}/M62429/M62429.pio)
pico_generate_pio_header(${TARGET_NAME} ${CMAKE_CURRENT_LIST_DIR}/isa/isa_io.pio)
if(SOUND_MPU)
target_sources(${TARGET_NAME} PRIVATE mpu401/mpu401.c mpu401/midi.c)
target_compile_definitions(${TARGET_NAME} PRIVATE SOUND_MPU=1)
endif()
if(SOUND_OPL)
if(USE_YMF3812)
# ymfm ym3812 (OPL2): 9 ch / 18 op / 1 output — ~3-4x faster than ymf262.
# USE_YMF3812=1 is propagated automatically via opl_ym3812's INTERFACE definitions.
target_compile_definitions(${TARGET_NAME} PRIVATE
SOUND_OPL=1
OPL_CMD_BUFFER=1
)
target_link_libraries(${TARGET_NAME} opl_ym3812)
elseif(USE_YMFM_OPL)
# ymfm ymf262 (OPL3): 18 ch / 36 op / 4 outputs — games detect OPL3.
target_compile_definitions(${TARGET_NAME} PRIVATE
SOUND_OPL=1
USE_YMFM_OPL=1
OPL_CMD_BUFFER=1
)
target_link_libraries(${TARGET_NAME} opl_ymfm)
elseif(USE_DBOPL_OPL)
# DOSBox OPL emulation
target_compile_definitions(${TARGET_NAME} PRIVATE
SOUND_OPL=1
USE_DBOPL_OPL=1
OPL_CMD_BUFFER=1
)
target_link_libraries(${TARGET_NAME} opl_dbopl)
else()
# Default: emu8950 (OPL2, assembly-optimized for RP2040)
target_compile_definitions(${TARGET_NAME} PRIVATE
SOUND_OPL=1
USE_EMU8950_OPL=1
EMU8950_ASM=1
EMU8950_TLL_FLASH=1 # pre-computed TLL table stored in flash via .flashdata section (not copied to RAM)
EMU8950_NO_FLOAT=1 # RP2040 has no FPU; float only used in TLL init anyway
EMU8950_NO_TIMER=1 # disable timer which isn't used
EMU8950_NO_TEST_FLAG=1 # disable test flags (which aren't used)
OPL_CMD_BUFFER=1 # queue OPL writes on core 0, drain on core 1 to eliminate cross-core struct race
)
target_link_libraries(${TARGET_NAME} opl)
endif()
endif()
target_link_libraries(
${TARGET_NAME}
pico_stdlib
pico_multicore
pico_audio_i2s
pico_flash
hardware_pio
hardware_pll
hardware_flash
hardware_adc
hardware_exception
)
pico_add_extra_outputs(${TARGET_NAME})
# Determine which stdio drivers are available for this firmware type
if (SOUND_MPU)
pico_enable_stdio_uart(${TARGET_NAME} 0)
else()
set(HAS_STDIO_UART TRUE)
endif()
if (USB_STACK)
pico_enable_stdio_usb(${TARGET_NAME} 0)
else()
set(HAS_STDIO_USB TRUE)
endif()
if(PGDEBUG AND (HAS_STDIO_UART OR HAS_STDIO_USB))
# Debug output is possible: enable available drivers and printf formatter
target_compile_definitions(${TARGET_NAME} PRIVATE PGDEBUG=1)
target_compile_definitions(rp2040-psram INTERFACE PSRAM_DEBUG=1)
if (HAS_STDIO_UART)
pico_enable_stdio_uart(${TARGET_NAME} 1)
endif()
if (HAS_STDIO_USB)
pico_enable_stdio_usb(${TARGET_NAME} 1)
endif()
else()
# No debug output possible or not requested: strip printf entirely
if (NOT SOUND_MPU)
pico_enable_stdio_uart(${TARGET_NAME} 0)
endif()
if (NOT USB_STACK)
pico_enable_stdio_usb(${TARGET_NAME} 0)
endif()
pico_set_printf_implementation(${TARGET_NAME} none)
endif()
if(NOT PGDEBUG AND Python3_FOUND)
# With printf stripped, __wrap_snprintf is the panic stub, so any
# stray printf call dead-loops the firmware. Fail the build if we
# find one.
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
COMMAND ${Python3_EXECUTABLE}
${CMAKE_SOURCE_DIR}/scripts/check_printf_leak.py
${CMAKE_OBJDUMP} ${CMAKE_ADDR2LINE}
$<TARGET_FILE:${TARGET_NAME}>
VERBATIM
)
endif()
pico_enable_stdio_semihosting(${TARGET_NAME} 0)
endfunction()
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/tusb_xinput)
add_subdirectory(rp2040-psram)
add_subdirectory(opl)
add_subdirectory(ne2000)
add_subdirectory(cdrom)
add_subdirectory(resampler)
################################################################################
# Build GUS firmware
function(build_gus TARGET_NAME MULTIFW)
set(USB_JOYSTICK TRUE)
set(SOUND_MPU TRUE)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-gus")
target_sources(${TARGET_NAME} PRIVATE
audio/volctrl.cpp
gusplay.cpp
isa/isa_dma.c
audio/audio_i2s_minimal.c
)
target_compile_definitions(${TARGET_NAME} PRIVATE
SOUND_GUS=1
PSRAM=1
TEST_PSRAM=1
PSRAM_ASYNC=1
#PSRAM_ASYNC_DMA_IRQ=1
PSRAM_SPINLOCK=1
# PSRAM_MUTEX=1
# PSRAM_WAITDMA=1
PSRAM_CORE0=1
PSRAM_PIN_CS=1
PSRAM_PIN_SCK=2
PSRAM_PIN_MOSI=3
PSRAM_PIN_MISO=0
# POLLING_DMA=1
INTERP_CLAMP=1
# INTERP_LINEAR=1
SCALE_22K_TO_44K=1
# FORCE_28CH_27CH=1
)
pico_generate_pio_header(${TARGET_NAME} ${CMAKE_CURRENT_LIST_DIR}/isa/isa_dma.pio)
target_link_libraries(${TARGET_NAME} rp2040-psram hardware_interp)
endfunction()
option(SOUND_WSS "Build SB firmware with WSS (AD1848) support instead of SB16 DSP" OFF)
################################################################################
# Build SB firmware
function(build_sb_8950 TARGET_NAME MULTIFW)
set(USB_JOYSTICK TRUE)
set(SOUND_MPU TRUE)
set(SOUND_OPL TRUE)
set(CDROM TRUE)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-sb")
target_sources(${TARGET_NAME} PRIVATE
audio/volctrl.cpp
sbplay.cpp
isa/isa_dma.c
audio/audio_fifo.c
audio/audio_i2s_minimal.c
)
if(SOUND_WSS)
target_sources(${TARGET_NAME} PRIVATE ad1848/ad1848.cpp)
target_compile_definitions(${TARGET_NAME} PRIVATE SOUND_WSS=1)
else()
target_sources(${TARGET_NAME} PRIVATE sbdsp/sbdsp.cpp)
endif()
target_compile_definitions(${TARGET_NAME} PRIVATE
SOUND_SB=1
SOUND_DSP=1
USE_CD_AUDIO_FIFO=1
# USE_IRQ=1
# AUDIO_CALLBACK_CORE0=1
)
target_link_libraries(${TARGET_NAME} resampler)
pico_generate_pio_header(${TARGET_NAME} ${CMAKE_CURRENT_LIST_DIR}/isa/isa_dma.pio)
endfunction()
################################################################################
# Build SB firmware — ymfm ymf262 OPL3
function(build_sb_ymf262 TARGET_NAME MULTIFW)
set(USE_YMFM_OPL TRUE)
set(USB_JOYSTICK TRUE)
set(SOUND_MPU TRUE)
set(SOUND_OPL TRUE)
set(CDROM TRUE)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-sb-ymf262")
target_sources(${TARGET_NAME} PRIVATE
audio/volctrl.cpp
sbdsp/sbdsp.cpp
sbplay.cpp
isa/isa_dma.c
audio/audio_fifo.c
audio/audio_i2s_minimal.c
)
target_compile_definitions(${TARGET_NAME} PRIVATE
SOUND_SB=1
SOUND_DSP=1
SB_BUFFERLESS=1
SB_BUFFERLESS_NG=1
USE_CD_AUDIO_FIFO=1
)
target_link_libraries(${TARGET_NAME} resampler)
pico_generate_pio_header(${TARGET_NAME} ${CMAKE_CURRENT_LIST_DIR}/isa/isa_dma.pio)
endfunction()
################################################################################
# Build SB firmware — DOSBox OPL3 core
function(build_sb_dbopl3 TARGET_NAME MULTIFW)
set(USE_DBOPL_OPL TRUE)
set(USB_JOYSTICK TRUE)
set(SOUND_MPU TRUE)
set(SOUND_OPL TRUE)
set(CDROM TRUE)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-sb-dbopl3")
target_sources(${TARGET_NAME} PRIVATE
audio/volctrl.cpp
sbdsp/sbdsp.cpp
sbplay.cpp
isa/isa_dma.c
audio/audio_fifo.c
audio/audio_i2s_minimal.c
)
target_compile_definitions(${TARGET_NAME} PRIVATE
SOUND_SB=1
SOUND_DSP=1
SB_BUFFERLESS=1
SB_BUFFERLESS_NG=1
USE_CD_AUDIO_FIFO=1
INTERP_VOLCTRL=1
INTERP_SB_LINEAR=1
)
target_link_libraries(${TARGET_NAME} resampler)
target_link_libraries(${TARGET_NAME} hardware_interp)
pico_generate_pio_header(${TARGET_NAME} ${CMAKE_CURRENT_LIST_DIR}/isa/isa_dma.pio)
endfunction()
################################################################################
# Build AdLib firmware
function(build_adlib TARGET_NAME MULTIFW)
set(USB_JOYSTICK TRUE)
set(USB_MOUSE TRUE)
set(SOUND_MPU TRUE)
set(SOUND_OPL TRUE)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-adlib")
target_sources(${TARGET_NAME} PRIVATE
audio/volctrl.cpp
sbplay.cpp
audio/audio_i2s_minimal.c
)
target_link_libraries(${TARGET_NAME} resampler)
endfunction()
################################################################################
# Build AdLib firmware — ymf262 OPL3 variant
function(build_adlib_ymf262 TARGET_NAME MULTIFW)
set(USE_YMFM_OPL TRUE)
set(USB_JOYSTICK TRUE)
set(USB_MOUSE TRUE)
set(SOUND_MPU TRUE)
set(SOUND_OPL TRUE)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-adlib-ymf262")
target_sources(${TARGET_NAME} PRIVATE
audio/volctrl.cpp
sbplay.cpp
audio/audio_i2s_minimal.c
)
target_link_libraries(${TARGET_NAME} resampler)
endfunction()
################################################################################
# Build AdLib firmware — DOSBox OPL3 core
function(build_adlib_dbopl3 TARGET_NAME MULTIFW)
set(USE_DBOPL3_OPL TRUE)
set(USB_JOYSTICK TRUE)
set(USB_MOUSE TRUE)
set(SOUND_MPU TRUE)
set(SOUND_OPL TRUE)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-adlib-dbopl3")
target_sources(${TARGET_NAME} PRIVATE
audio/volctrl.cpp
sbplay.cpp
audio/audio_i2s_minimal.c
)
target_link_libraries(${TARGET_NAME} resampler)
endfunction()
################################################################################
# Build AdLib firmware — ymfm OPL2 (ym3812) variant
function(build_adlib_ym3812 TARGET_NAME MULTIFW)
set(USE_YMF3812 TRUE)
set(USB_JOYSTICK TRUE)
set(USB_MOUSE TRUE)
set(SOUND_MPU TRUE)
set(SOUND_OPL TRUE)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-adlib-ym3812")
target_sources(${TARGET_NAME} PRIVATE
audio/volctrl.cpp
sbplay.cpp
audio/audio_i2s_minimal.c
)
target_link_libraries(${TARGET_NAME} resampler)
endfunction()
################################################################################
# Build SB firmware — ymfm OPL2 (ym3812) variant
function(build_sb_ym3812 TARGET_NAME MULTIFW)
set(USE_YMF3812 TRUE)
set(USB_JOYSTICK TRUE)
set(SOUND_MPU TRUE)
set(SOUND_OPL TRUE)
set(CDROM TRUE)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-sb-ym3812")
target_sources(${TARGET_NAME} PRIVATE
audio/volctrl.cpp
sbdsp/sbdsp.cpp
sbplay.cpp
isa/isa_dma.c
audio/audio_fifo.c
audio/audio_i2s_minimal.c
)
target_compile_definitions(${TARGET_NAME} PRIVATE
SOUND_SB=1
SOUND_DSP=1
SB_BUFFERLESS=1
SB_BUFFERLESS_NG=1
USE_CD_AUDIO_FIFO=1
)
target_link_libraries(${TARGET_NAME} resampler)
pico_generate_pio_header(${TARGET_NAME} ${CMAKE_CURRENT_LIST_DIR}/isa/isa_dma.pio)
endfunction()
################################################################################
# Build MPU-only firmware
function(build_mpu TARGET_NAME MULTIFW)
set(USB_JOYSTICK TRUE)
set(SOUND_MPU TRUE)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-mpu401")
target_compile_definitions(${TARGET_NAME} PRIVATE
# Enable MPU-401 IRQ support only in this firmware
MPU_IRQ=1
# Larger buffer for sysex delay
MPU_ONLY=1
)
target_sources(${TARGET_NAME} PRIVATE mpuplay.cpp)
endfunction()
################################################################################
# Build PSG firmware
function(build_psg TARGET_NAME MULTIFW)
set(USB_JOYSTICK TRUE)
set(USB_MOUSE TRUE)
set(SOUND_MPU TRUE)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-psg")
target_compile_definitions(${TARGET_NAME} PRIVATE
SOUND_TANDY=1
SOUND_CMS=1
)
target_sources(${TARGET_NAME} PRIVATE
audio/volctrl.cpp
audio/audio_i2s_minimal.c
square/square.cpp
)
target_sources(${TARGET_NAME} PRIVATE psgplay.cpp)
endfunction()
################################################################################
# Build USB-only firmware (joystick + mouse support)
function(build_usb TARGET_NAME MULTIFW)
set(USB_JOYSTICK TRUE)
set(USB_MOUSE TRUE)
set(SOUND_MPU TRUE)
set(CDROM TRUE)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-usb")
target_compile_definitions(${TARGET_NAME} PRIVATE
USB_ONLY=1
USE_CD_AUDIO_FIFO=1
)
target_sources(${TARGET_NAME} PRIVATE
audio/volctrl.cpp
audio/audio_fifo.c
audio/audio_i2s_minimal.c
usbplay.cpp
)
endfunction()
function(build_ne2k TARGET_NAME MULTIFW)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-ne2k")
target_compile_definitions(${TARGET_NAME} PRIVATE
NE2000=1
PICOW=1
CYW43_CONFIG_FILE="cyw43_firmware.h"
CYW43_PIO_CLOCK_DIV_INT=3
)
target_sources(${TARGET_NAME} PRIVATE
ne2000play.cpp
)
target_link_libraries(
${TARGET_NAME}
ne2000
)
endfunction()
################################################################################
# Build "multifw" - all firmwares in one UF2
if(PROJECT_TYPE STREQUAL "MULTIFW")
set(FW_TARGET picogus)
# ---------------------------------------------------------------------------
# OPL variant for the adlib slot in the multifw bundle.
# Uncomment exactly one of the lines below:
set(MULTIFW_OPL_VARIANT "emu8950") # original emu8950 — OPL2, assembly-optimized
# set(MULTIFW_OPL_VARIANT "ym3812") # ymfm ym3812 — OPL2, ymfm quality
# set(MULTIFW_OPL_VARIANT "ymf262") # ymfm ymf262 — OPL3, true stereo - note not yet fast enough for RP2040
# ---------------------------------------------------------------------------
if(MULTIFW_OPL_VARIANT STREQUAL "ymf262")
set(ADLIB_TARGET_NAME "pg-adlib-ymf262")
set(ADLIB_BUILD_FN build_adlib_ymf262)
elseif(MULTIFW_OPL_VARIANT STREQUAL "ym3812")
set(ADLIB_TARGET_NAME "pg-adlib-ym3812")
set(ADLIB_BUILD_FN build_adlib_ym3812)
else()
set(ADLIB_TARGET_NAME "pg-adlib")
set(ADLIB_BUILD_FN build_adlib)
endif()
message("Multifw OPL variant: ${MULTIFW_OPL_VARIANT} → ${ADLIB_TARGET_NAME}")
add_custom_command(
OUTPUT
"${CMAKE_BINARY_DIR}/generated/multifw/flash_firmware.h"
"${CMAKE_BINARY_DIR}/pg-gus-multifw.ld"
"${CMAKE_BINARY_DIR}/${ADLIB_TARGET_NAME}-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-mpu-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-psg-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-sb-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-usb-multifw.ld"
COMMAND
${CMAKE_COMMAND}
-DFLASH_FIRMWARE_H_IN="${CMAKE_SOURCE_DIR}/multifw/flash_firmware.h.in"
-DFLASH_FIRMWARE_H="${CMAKE_BINARY_DIR}/generated/multifw/flash_firmware.h"
-DFW_LD_IN="${CMAKE_SOURCE_DIR}/multifw/firmware.ld.in"
-DFW_1_BIN="${CMAKE_BINARY_DIR}/pg-gus.bin"
-DFW_1_LD="${CMAKE_BINARY_DIR}/pg-gus-multifw.ld"
-DFW_2_BIN="${CMAKE_BINARY_DIR}/${ADLIB_TARGET_NAME}.bin"
-DFW_2_LD="${CMAKE_BINARY_DIR}/${ADLIB_TARGET_NAME}-multifw.ld"
-DFW_3_BIN="${CMAKE_BINARY_DIR}/pg-mpu.bin"
-DFW_3_LD="${CMAKE_BINARY_DIR}/pg-mpu-multifw.ld"
-DFW_4_BIN="${CMAKE_BINARY_DIR}/pg-psg.bin"
-DFW_4_LD="${CMAKE_BINARY_DIR}/pg-psg-multifw.ld"
-DFW_5_BIN="${CMAKE_BINARY_DIR}/pg-sb.bin"
-DFW_5_LD="${CMAKE_BINARY_DIR}/pg-sb-multifw.ld"
-DFW_6_BIN="${CMAKE_BINARY_DIR}/pg-usb.bin"
-DFW_6_LD="${CMAKE_BINARY_DIR}/pg-usb-multifw.ld"
-P ${CMAKE_SOURCE_DIR}/multifw/generate_ld.cmake
DEPENDS
"${CMAKE_SOURCE_DIR}/multifw/firmware.ld.in"
pg-gus
${ADLIB_TARGET_NAME}
pg-mpu
pg-psg
pg-sb
pg-usb
)
add_custom_target(generate_flash_firmware_h DEPENDS
"${CMAKE_BINARY_DIR}/generated/multifw/flash_firmware.h"
"${CMAKE_BINARY_DIR}/pg-gus-multifw.ld"
"${CMAKE_BINARY_DIR}/${ADLIB_TARGET_NAME}-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-mpu-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-psg-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-sb-multifw.ld"
"${CMAKE_BINARY_DIR}/pg-usb-multifw.ld"
)
build_gus(pg-gus FALSE)
build_gus(pg-gus-multifw TRUE)
add_dependencies(pg-gus-multifw pg-gus generate_flash_firmware_h)
cmake_language(CALL ${ADLIB_BUILD_FN} ${ADLIB_TARGET_NAME} FALSE)
cmake_language(CALL ${ADLIB_BUILD_FN} ${ADLIB_TARGET_NAME}-multifw TRUE)
add_dependencies(${ADLIB_TARGET_NAME}-multifw ${ADLIB_TARGET_NAME} generate_flash_firmware_h)
build_mpu(pg-mpu FALSE)
build_mpu(pg-mpu-multifw TRUE)
add_dependencies(pg-mpu-multifw pg-mpu generate_flash_firmware_h)
build_psg(pg-psg FALSE)
build_psg(pg-psg-multifw TRUE)
add_dependencies(pg-psg-multifw pg-psg generate_flash_firmware_h)
build_sb_dbopl3(pg-sb FALSE)
build_sb_dbopl3(pg-sb-multifw TRUE)
add_dependencies(pg-sb-multifw pg-sb generate_flash_firmware_h)
build_usb(pg-usb FALSE)
build_usb(pg-usb-multifw TRUE)
add_dependencies(pg-usb-multifw pg-usb generate_flash_firmware_h)
add_executable(bootloader)
target_sources(bootloader PRIVATE multifw/bootloader.c system/flash_settings.c)
target_link_libraries(bootloader PRIVATE pico_stdlib hardware_flash pico_flash hardware_exception)
pico_add_extra_outputs(bootloader)
# set_linker_script(bootloader ${CMAKE_SOURCE_DIR}/multifw/bootloader.ld)
target_include_directories(bootloader PRIVATE
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_BINARY_DIR}/generated/multifw
)
pico_enable_stdio_uart(bootloader 0)
pico_enable_stdio_usb(bootloader 0)
pico_enable_stdio_semihosting(bootloader 0)
if(NOT PGDEBUG)
pico_set_printf_implementation(bootloader none)
endif()
if(NOT PGDEBUG AND Python3_FOUND)
add_custom_command(TARGET bootloader POST_BUILD
COMMAND ${Python3_EXECUTABLE}
${CMAKE_SOURCE_DIR}/scripts/check_printf_leak.py
${CMAKE_OBJDUMP} ${CMAKE_ADDR2LINE}
$<TARGET_FILE:bootloader>
VERBATIM
)
endif()
add_dependencies(bootloader generate_flash_firmware_h)
if (NOT UF2CREATE_FOUND)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/multifw)
# Needs to be an external project so it can be built as a native binary outside of the Pico SDK
find_package(UF2CREATE)
# Rebuild uf2create if flash_firmware.h is regenerated
ExternalProject_Add_StepDependencies(UF2CREATEBuild build generate_flash_firmware_h)
endif()
add_custom_command(
OUTPUT picogus.uf2
DEPENDS bootloader UF2CREATE pg-gus-multifw ${ADLIB_TARGET_NAME}-multifw pg-mpu-multifw pg-psg-multifw pg-sb-multifw pg-usb-multifw
COMMAND UF2CREATE bootloader.bin pg-gus-multifw.bin ${ADLIB_TARGET_NAME}-multifw.bin pg-mpu-multifw.bin pg-psg-multifw.bin pg-sb-multifw.bin pg-usb-multifw.bin picogus.uf2
)
add_custom_target(picogus ALL DEPENDS picogus.uf2)
################################################################################
# Builds for individual "legacy" firmware modes
elseif(PROJECT_TYPE STREQUAL "GUS")
set(FW_TARGET pg-gus)
build_gus(pg-gus FALSE)
elseif(PROJECT_TYPE STREQUAL "SB_EMU8950")
set(FW_TARGET pg-sb-emu8950)
build_sb_emu8950(pg-sb-emu8950 FALSE)
elseif(PROJECT_TYPE STREQUAL "SB_YMF262")
set(FW_TARGET pg-sb-ymf262)
build_sb_ymf262(pg-sb-ymf262 FALSE)
elseif(PROJECT_TYPE STREQUAL "SB_YM3812")
set(FW_TARGET pg-sb-ym3812)
build_sb_ym3812(pg-sb-ym3812 FALSE)
elseif(PROJECT_TYPE STREQUAL "SB_DBOPL3")
set(FW_TARGET pg-sb-dbopl3)
build_sb_dbopl3(pg-sb-dbopl3 FALSE)
elseif(PROJECT_TYPE STREQUAL "ADLIB")
set(FW_TARGET pg-adlib)
build_adlib(pg-adlib FALSE)
elseif(PROJECT_TYPE STREQUAL "ADLIB_YMFM")
set(FW_TARGET pg-adlib-ymf262)
build_adlib_ymf262(pg-adlib-ymf262 FALSE)
elseif(PROJECT_TYPE STREQUAL "ADLIB_YMF262")
set(FW_TARGET pg-adlib-ymf262)
build_adlib_ymf262(pg-adlib-ymf262 FALSE)
elseif(PROJECT_TYPE STREQUAL "ADLIB_YM3812")
set(FW_TARGET pg-adlib-ym3812)
build_adlib_ym3812(pg-adlib-ym3812 FALSE)
elseif(PROJECT_TYPE STREQUAL "ADLIB_DBOPL3")
set(FW_TARGET pg-adlib-dbopl3)
build_adlib_dbopl3(pg-adlib-dbopl3 FALSE)
elseif(PROJECT_TYPE STREQUAL "MPU")
set(FW_TARGET pg-mpu)
build_mpu(pg-mpu FALSE)
elseif(PROJECT_TYPE STREQUAL "PSG")
set(FW_TARGET pg-psg)
build_psg(pg-psg FALSE)
elseif(PROJECT_TYPE STREQUAL "USB")
set(FW_TARGET pg-usb)
build_usb(pg-usb FALSE)
elseif(PROJECT_TYPE STREQUAL "NE2K")
set(FW_TARGET pg-ne2k)
build_ne2k(pg-ne2k FALSE)
elseif(PROJECT_TYPE STREQUAL "ANALYZER")
set(FW_TARGET pg-analyzer)
add_executable(pg-analyzer isa_analyzer.cpp)
pico_set_program_name(pg-analyzer "picogus-analyzer")
pico_set_program_version(pg-analyzer ${CMAKE_PROJECT_VERSION})
target_compile_definitions(pg-analyzer PRIVATE
PICO_MALLOC_PANIC=0
)
pico_generate_pio_header(pg-analyzer ${CMAKE_CURRENT_LIST_DIR}/isa_analyzer.pio)
target_link_libraries(pg-analyzer
pico_stdlib
hardware_pio
)
pico_enable_stdio_uart(pg-analyzer 1)
pico_enable_stdio_usb(pg-analyzer 0)
pico_enable_stdio_semihosting(pg-analyzer 0)
pico_add_extra_outputs(pg-analyzer)
endif()
################################################################################
# Optional target to program built firmware via openocd
add_custom_target(
program
DEPENDS ${FW_TARGET}
COMMAND openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000\; program ${FW_TARGET}.bin verify reset exit 0x10000000"
)