play96 0.3.2

Programmable libretro harness for *96 fantasy-console cores
Documentation
#ifndef PLAY96_HPP
#define PLAY96_HPP

#include "play96.h"

#include <stdexcept>
#include <string>

namespace play96 {

struct Color {
    unsigned char red;
    unsigned char green;
    unsigned char blue;
    unsigned char alpha = 255;
};

enum class MouseButton : size_t {
    Left = PLAY96_MOUSE_LEFT,
    Right = PLAY96_MOUSE_RIGHT,
    Middle = PLAY96_MOUSE_MIDDLE,
    Button4 = PLAY96_MOUSE_BUTTON4,
    Button5 = PLAY96_MOUSE_BUTTON5,
};

enum class InputDevice : unsigned {
    None = PLAY96_DEVICE_NONE,
    Joypad = PLAY96_DEVICE_JOYPAD,
    Mouse = PLAY96_DEVICE_MOUSE,
    Keyboard = PLAY96_DEVICE_KEYBOARD,
};

class Session {
public:
    Session(const char* core_path, const char* cartridge_path) {
        check(play96_create(core_path, cartridge_path, &session_));
    }

    ~Session() { play96_destroy(session_); }
    Session(const Session&) = delete;
    Session& operator=(const Session&) = delete;
    Session(Session&& other) noexcept : session_(other.session_) { other.session_ = nullptr; }
    Session& operator=(Session&& other) noexcept {
        if (this != &other) {
            play96_destroy(session_);
            session_ = other.session_;
            other.session_ = nullptr;
        }
        return *this;
    }

    void run_frame() { check(play96_run_frame(session_)); }
    void run_frames(size_t frames) { check(play96_run_frames(session_, frames)); }
    void set_button(unsigned port, unsigned button, bool pressed) { check(play96_set_button(session_, port, button, pressed)); }
    void clear_buttons(unsigned port = 0) { check(play96_clear_buttons(session_, port)); }
    void set_controller_device(unsigned port, InputDevice device) {
        check(play96_set_controller_device(session_, port, static_cast<play96_input_device>(device)));
    }
    void set_key(uint32_t keycode, bool pressed) { check(play96_set_key(session_, keycode, pressed)); }
    void clear_keys() { check(play96_clear_keys(session_)); }
    void set_mouse_delta(int16_t x, int16_t y) { check(play96_set_mouse_delta(session_, x, y)); }
    void set_mouse_button(MouseButton button, bool pressed) {
        check(play96_set_mouse_button(session_, static_cast<size_t>(button), pressed));
    }
    void clear_mouse_buttons() { check(play96_clear_mouse_buttons(session_)); }
    void set_mouse_wheel(int16_t vertical, int16_t horizontal = 0) {
        check(play96_set_mouse_wheel(session_, vertical, horizontal));
    }
    unsigned width() const { return play96_framebuffer_width(session_); }
    unsigned height() const { return play96_framebuffer_height(session_); }
    uint32_t pixel_xrgb(unsigned x, unsigned y) const { return play96_pixel_xrgb(session_, x, y); }
    void assert_pixel(unsigned x, unsigned y, Color color) const {
        check(play96_assert_pixel(session_, x, y, {color.red, color.green, color.blue, color.alpha}));
    }
    void assert_pixel_xrgb(unsigned x, unsigned y, uint32_t color) const { check(play96_assert_pixel_xrgb(session_, x, y, color)); }
    const int16_t* audio_samples() const { return play96_audio_samples(session_); }
    size_t audio_sample_count() const { return play96_audio_sample_count(session_); }
    size_t audio_frame_count() const { return play96_audio_frame_count(session_); }
    double audio_sample_rate() const { return play96_audio_sample_rate(session_); }
    uint64_t audio_hash() const { return play96_audio_hash(session_); }
    void assert_audio_sample(size_t frame, size_t channel, int16_t expected, uint16_t tolerance = 0) const {
        check(play96_assert_audio_sample(session_, frame, channel, expected, tolerance));
    }
    void assert_audio_hash(uint64_t expected) const { check(play96_assert_audio_hash(session_, expected)); }
    void save_state(const char* path) { check(play96_save_state(session_, path)); }
    void load_state(const char* path) { check(play96_load_state(session_, path)); }
    void write_png(const char* path) const { check(play96_write_png(session_, path)); }

private:
    static void check(const char* error) {
        if (error) throw std::runtime_error(error);
    }

    play96_session* session_ = nullptr;
};

} // namespace play96

#endif