function(sprite)
    set(options "")
    set(multiValueArgs "")
    set(oneValueArgs NAME X Y TRANSPARENT BPP CX CY)
    cmake_parse_arguments(SPRITE "${options}" "${oneValueArgs}"
        "${multiValueArgs}" ${ARGN})

    if(PS1_BUILD)
        if(${SPRITE_TRANSPARENT})
            set(trans -mpink)
        endif()

        if(NOT "${SPRITE_BPP}" STREQUAL "16")
            set(clut "-clut=${SPRITE_CX},${SPRITE_CY}")
        endif()

        add_custom_target(${SPRITE_NAME}_img ALL
            bmp2tim ${SPRITE_NAME}.bmp ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME}
                ${SPRITE_BPP} -org=${SPRITE_X},${SPRITE_Y} ${clut} ${trans}
            WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
            DEPENDS ${SPRITE_NAME}.bmp
            BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME})
        add_dependencies(iso ${SPRITE_NAME}_img)
    elseif(SDL1_2_BUILD)
        if(${SPRITE_TRANSPARENT})
            set(trans "transparent=1")
        else()
            set(trans "transparent=0")
        endif()

        add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME}
            COMMAND ${TOOLS_PREFIX}/bin/add-header ${trans} ${SPRITE_NAME}_24.bmp ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME}
            WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
            DEPENDS ${SPRITE_NAME}_24.bmp
            VERBATIM)
        add_custom_target(${SPRITE_NAME}_img
            DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME})
        add_dependencies(${SPRITE_NAME}_img tools)
    endif()
endfunction()

function(sound)
    set(options "")
    set(multiValueArgs "")
    set(oneValueArgs NAME LOOP)
    cmake_parse_arguments(SOUND "${options}" "${oneValueArgs}"
        "${multiValueArgs}" ${ARGN})

    if(PS1_BUILD)
        if(${SOUND_LOOP})
            set(loop -L)
        endif()

        add_custom_target(${SOUND_NAME}_snd ALL
            wav2vag ${SOUND_NAME}.wav
                ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME} ${loop}
            WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
            DEPENDS ${SOUND_NAME}.wav
            BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME})
        add_dependencies(iso ${SOUND_NAME}_snd)
    elseif(SDL1_2_BUILD)
        if(${SOUND_LOOP})
            set(loop "loop=1")
        else()
            set(loop "loop=0")
        endif()

        # Reference: https://gist.github.com/socantre/7ee63133a0a3a08f3990
        add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME}
            COMMAND ${TOOLS_PREFIX}/bin/add-header ${loop} ${SOUND_NAME}.wav ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME}
            WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
            DEPENDS ${SOUND_NAME}.wav
            VERBATIM)
        add_custom_target(${SOUND_NAME}_snd
            DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME})
        add_dependencies(${SOUND_NAME}_snd tools)
    endif()
endfunction()

function(container)
    set(options "")
    set(multiValueArgs SPRITES SOUNDS)
    set(oneValueArgs NAME)
    cmake_parse_arguments(CONTAINER "${options}" "${oneValueArgs}"
        "${multiValueArgs}" ${ARGN})

    add_custom_command(OUTPUT ${cdroot}/${CONTAINER_NAME}.cnt
        COMMAND ${TOOLS_PREFIX}/bin/container ${CONTAINER_SPRITES} ${CONTAINER_SOUNDS}
            ${cdroot}/${CONTAINER_NAME}.cnt
        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
        VERBATIM)

    add_custom_target(${CONTAINER_NAME}_container
        DEPENDS ${cdroot}/${CONTAINER_NAME}.cnt)
    add_dependencies(${PROJECT_NAME} ${CONTAINER_NAME}_container)
    add_dependencies(${CONTAINER_NAME}_container tools)

    foreach(sprite ${CONTAINER_SPRITES})
        add_dependencies(${CONTAINER_NAME}_container ${sprite}_img)
    endforeach()

    foreach(sound ${CONTAINER_SOUNDS})
        add_dependencies(${CONTAINER_NAME}_container ${sound}_snd)
    endforeach()

    if(PS1_BUILD)
        add_dependencies(iso ${CONTAINER_NAME}_container)
    endif()
endfunction()

sprite(NAME worker_n
    X 384
    Y 0
    BPP 4
    CX 384
    CY 31
    TRANSPARENT TRUE)

sprite(NAME worker_ne
    X 384
    Y 32
    BPP 4
    CX 384
    CY 63
    TRANSPARENT TRUE)

sprite(NAME worker_e
    X 384
    Y 64
    BPP 4
    CX 384
    CY 97
    TRANSPARENT TRUE)

sprite(NAME worker_se
    X 384
    Y 98
    BPP 4
    CX 384
    CY 129
    TRANSPARENT TRUE)

sprite(NAME worker_s
    X 384
    Y 130
    BPP 4
    CX 384
    CY 163
    TRANSPARENT TRUE)

sprite(NAME grass
    X 368
    Y 0
    BPP 4
    CX 368
    CY 510
    TRANSPARENT FALSE)

sprite(NAME cursor
    X 368
    Y 32
    BPP 4
    CX 368
    CY 509
    TRANSPARENT TRUE)

sprite(NAME barracks
    X 384
    Y 180
    BPP 4
    CX 368
    CY 508
    TRANSPARENT TRUE)

sprite(NAME gui_bar_left
    X 376
    Y 0
    BPP 4
    CX 368
    CY 507
    TRANSPARENT TRUE)

sprite(NAME gui_bar_mid
    X 472
    Y 168
    BPP 4
    CX 368
    CY 506
    TRANSPARENT FALSE)

sprite(NAME gui_bar_right
    X 376
    Y 56
    BPP 4
    CX 368
    CY 505
    TRANSPARENT TRUE)

sprite(NAME sel_up_left
    X 368
    Y 64
    BPP 4
    CX 368
    CY 504
    TRANSPARENT TRUE)

sprite(NAME sel_up_right
    X 372
    Y 64
    BPP 4
    CX 368
    CY 503
    TRANSPARENT TRUE)

sprite(NAME sel_down_left
    X 368
    Y 52
    BPP 4
    CX 368
    CY 502
    TRANSPARENT TRUE)

sprite(NAME sel_down_right
    X 372
    Y 52
    BPP 4
    CX 368
    CY 501
    TRANSPARENT TRUE)

sprite(NAME sel_mid
    X 376
    Y 52
    BPP 4
    CX 368
    CY 500
    TRANSPARENT TRUE)

sprite(NAME sel_mid_v
    X 382
    Y 0
    BPP 4
    CX 368
    CY 499
    TRANSPARENT FALSE)

sprite(NAME font
    X 472
    Y 0
    BPP 4
    CX 368
    CY 498
    TRANSPARENT TRUE)

sprite(NAME gold_mine
    X 448
    Y 0
    BPP 4
    CX 368
    CY 497
    TRANSPARENT TRUE)

sprite(NAME tree
    X 368
    Y 76
    BPP 4
    CX 368
    CY 496
    TRANSPARENT TRUE)

sprite(NAME btn_left
    X 376
    Y 80
    BPP 4
    CX 368
    CY 495
    TRANSPARENT TRUE)

sprite(NAME btn_right
    X 376
    Y 106
    BPP 4
    CX 368
    CY 494
    TRANSPARENT TRUE)

sprite(NAME btn_mid
    X 368
    Y 122
    BPP 4
    CX 368
    CY 493
    TRANSPARENT FALSE)

sound(NAME acknowledge_01)
sound(NAME acknowledge_02)
sound(NAME selected_01)

container(NAME rts
    SPRITES
        barracks
        btn_left
        btn_mid
        btn_right
        worker_n
        worker_ne
        worker_e
        worker_se
        worker_s
        font
        grass
        cursor
        tree
        gui_bar_left
        gui_bar_mid
        gui_bar_right
        gold_mine
        sel_up_left
        sel_up_right
        sel_down_left
        sel_down_right
        sel_mid
        sel_mid_v
    SOUNDS
        acknowledge_01
        acknowledge_02
        selected_01
    )
