logo
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//! The [`CoreWrapper`] is an _internal_ data structure.
//!
//! It stores runtime information provided by the libretro frontend without interfering with your [`Core`] implementation.
use crate::*;

/// Holds the core instance as well as runtime information from the libretro frontend.
///
/// This struct gets used in the code generated by the [`retro_core!()`]-macro.
pub(crate) struct CoreWrapper {
    pub(crate) environment_set: bool,
    pub(crate) environment_callback: retro_environment_t,

    /// Render a frame. Pixel format is 15-bit `0RGB1555` native endian
    /// unless changed (see [`RETRO_ENVIRONMENT_SET_PIXEL_FORMAT`]).
    ///
    /// Width and height specify dimensions of buffer.
    /// Pitch specifices length in bytes between two lines in buffer.
    ///
    /// For performance reasons, it is highly recommended to have a frame
    /// that is packed in memory, i.e. `pitch == width * byte_per_pixel`.
    /// Certain graphic APIs, such as OpenGL ES, do not like textures
    /// that are not packed in memory.
    pub(crate) video_refresh_callback: retro_video_refresh_t,

    /// Renders a single audio frame. Should only be used if implementation
    /// generates a single sample at a time.
    /// Format is signed 16-bit native endian.
    pub(crate) audio_sample_callback: retro_audio_sample_t,

    /// Renders multiple audio frames in one go.
    ///
    /// One frame is defined as a sample of left and right channels, interleaved.
    /// I.e. `int16_t buf[4] = { l, r, l, r };` would be 2 frames.
    /// Only one of the audio callbacks must ever be used.
    pub(crate) audio_sample_batch_callback: retro_audio_sample_batch_t,

    /// Polls input.
    pub(crate) input_poll_callback: retro_input_poll_t,

    /// Queries for input for player `port`. device will be masked with
    /// [`RETRO_DEVICE_MASK`].
    ///
    /// Specialization of devices such as `RETRO_DEVICE_JOYPAD_MULTITAP` that
    /// have been set with [`Core::on_set_controller_port_device`]
    /// will still use the higher level [`RETRO_DEVICE_JOYPAD`] to request input.
    pub(crate) input_state_callback: retro_input_state_t,

    pub(crate) rumble_interface: Option<retro_rumble_interface>,

    #[cfg(feature = "unstable-env-commands")]
    pub(crate) sensor_interface: Option<retro_sensor_interface>,

    pub(crate) camera_interface: Option<retro_camera_callback>,
    pub(crate) perf_interface: Option<retro_perf_callback>,
    pub(crate) location_interface: Option<retro_location_callback>,

    pub(crate) can_dupe: bool,
    pub(crate) had_frame: bool,
    pub(crate) last_width: u32,
    pub(crate) last_height: u32,
    pub(crate) last_pitch: u64,

    pub(crate) supports_bitmasks: bool,

    pub(crate) frame_delta: Option<i64>,

    /// The wrapped [`Core`] implementation.
    pub(crate) core: Box<dyn Core>,
}

impl CoreWrapper {
    pub(crate) fn new<C: 'static + Core>(core: C) -> Self {
        Self {
            environment_set: false,
            environment_callback: None,

            core: Box::new(core),

            // Callbacks
            video_refresh_callback: None,
            audio_sample_callback: None,
            audio_sample_batch_callback: None,
            input_poll_callback: None,
            input_state_callback: None,

            rumble_interface: None,

            #[cfg(feature = "unstable-env-commands")]
            sensor_interface: None,

            camera_interface: None,

            perf_interface: None,
            location_interface: None,

            can_dupe: false,
            had_frame: false,
            last_width: 0,
            last_height: 0,
            last_pitch: 0,

            frame_delta: None,

            supports_bitmasks: false,
        }
    }

    #[inline(always)]
    pub(crate) fn on_set_video_refresh(&mut self, arg1: retro_video_refresh_t) {
        self.video_refresh_callback = arg1;
    }

    #[inline(always)]
    pub(crate) fn on_set_audio_sample(&mut self, arg1: retro_audio_sample_t) {
        self.audio_sample_callback = arg1;
    }

    #[inline(always)]
    pub(crate) fn on_set_audio_sample_batch(&mut self, arg1: retro_audio_sample_batch_t) {
        self.audio_sample_batch_callback = arg1;
    }

    #[inline(always)]
    pub(crate) fn on_set_input_poll(&mut self, arg1: retro_input_poll_t) {
        self.input_poll_callback = arg1;
    }

    #[inline(always)]
    pub(crate) fn on_set_input_state(&mut self, arg1: retro_input_state_t) {
        self.input_state_callback = arg1;
    }
}