implements PLN-0109
This commit is contained in:
parent
117a18ee72
commit
9cf9fa6163
@ -11,8 +11,8 @@ use crate::touch::Touch;
|
||||
use prometeu_hal::cartridge::AssetsPayloadSource;
|
||||
use prometeu_hal::sprite::Sprite;
|
||||
use prometeu_hal::{
|
||||
AssetBridge, AudioBridge, GfxBridge, HardwareBridge, InputPlatform, NoopTelemetryPlatform,
|
||||
PadBridge, RenderBackend, RuntimePlatform, TelemetryPlatform, TouchBridge,
|
||||
AssetBridge, AudioBridge, InputPlatform, NoopTelemetryPlatform, PadBridge, RenderBackend,
|
||||
RuntimePlatform, TelemetryPlatform, TouchBridge,
|
||||
};
|
||||
use prometeu_hal::{
|
||||
Game2DFrameComposer, Game2DFramePacket, RenderSubmission, RenderSubmissionPacket,
|
||||
@ -53,32 +53,8 @@ impl Default for Hardware {
|
||||
}
|
||||
}
|
||||
|
||||
impl HardwareBridge for Hardware {
|
||||
fn begin_frame(&mut self) {
|
||||
self.frame_composer.begin_frame();
|
||||
}
|
||||
|
||||
fn bind_scene(&mut self, scene_bank_id: usize) -> bool {
|
||||
self.frame_composer.bind_scene(scene_bank_id)
|
||||
}
|
||||
|
||||
fn unbind_scene(&mut self) {
|
||||
self.frame_composer.unbind_scene();
|
||||
}
|
||||
|
||||
fn set_camera(&mut self, x: i32, y: i32) {
|
||||
self.frame_composer.set_camera(x, y);
|
||||
}
|
||||
|
||||
fn emit_sprite(&mut self, sprite: Sprite) -> bool {
|
||||
self.frame_composer.emit_sprite(sprite)
|
||||
}
|
||||
|
||||
fn close_game2d_packet(&self) -> Game2DFramePacket {
|
||||
self.frame_composer.close_game2d_packet()
|
||||
}
|
||||
|
||||
fn publish_render_submission(&mut self, submission: &RenderSubmission) {
|
||||
impl Hardware {
|
||||
fn consume_render_submission(&mut self, submission: &RenderSubmission) {
|
||||
match &submission.packet {
|
||||
RenderSubmissionPacket::Game2D(packet) => {
|
||||
if packet.composer.bound_scene.is_none() {
|
||||
@ -94,54 +70,6 @@ impl HardwareBridge for Hardware {
|
||||
}
|
||||
self.gfx.present();
|
||||
}
|
||||
|
||||
fn render_frame(&mut self) {
|
||||
if self.frame_composer.active_scene_id().is_none() {
|
||||
let packet = self.frame_composer.close_game2d_packet();
|
||||
self.gfx.render_game2d_frame_packet(&packet);
|
||||
} else {
|
||||
self.frame_composer.render_frame(&mut self.gfx);
|
||||
}
|
||||
}
|
||||
|
||||
fn has_glyph_bank(&self, bank_id: usize) -> bool {
|
||||
self.gfx.glyph_banks.glyph_bank_slot(bank_id).is_some()
|
||||
}
|
||||
|
||||
fn gfx(&self) -> &dyn GfxBridge {
|
||||
&self.gfx
|
||||
}
|
||||
fn gfx_mut(&mut self) -> &mut dyn GfxBridge {
|
||||
&mut self.gfx
|
||||
}
|
||||
|
||||
fn audio(&self) -> &dyn AudioBridge {
|
||||
&self.audio
|
||||
}
|
||||
fn audio_mut(&mut self) -> &mut dyn AudioBridge {
|
||||
&mut self.audio
|
||||
}
|
||||
|
||||
fn pad(&self) -> &dyn PadBridge {
|
||||
&self.pad
|
||||
}
|
||||
fn pad_mut(&mut self) -> &mut dyn PadBridge {
|
||||
&mut self.pad
|
||||
}
|
||||
|
||||
fn touch(&self) -> &dyn TouchBridge {
|
||||
&self.touch
|
||||
}
|
||||
fn touch_mut(&mut self) -> &mut dyn TouchBridge {
|
||||
&mut self.touch
|
||||
}
|
||||
|
||||
fn assets(&self) -> &dyn AssetBridge {
|
||||
&self.assets
|
||||
}
|
||||
fn assets_mut(&mut self) -> &mut dyn AssetBridge {
|
||||
&mut self.assets
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderSubmissionSink for Hardware {
|
||||
@ -149,14 +77,19 @@ impl RenderSubmissionSink for Hardware {
|
||||
&mut self,
|
||||
submission: RenderSubmission,
|
||||
) -> Result<(), RenderSubmitError> {
|
||||
self.publish_render_submission(&submission);
|
||||
self.consume_render_submission(&submission);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderBackend for Hardware {
|
||||
fn render_frame(&mut self) {
|
||||
HardwareBridge::render_frame(self);
|
||||
if self.frame_composer.active_scene_id().is_none() {
|
||||
let packet = self.frame_composer.close_game2d_packet();
|
||||
self.gfx.render_game2d_frame_packet(&packet);
|
||||
} else {
|
||||
self.frame_composer.render_frame(&mut self.gfx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,7 +116,7 @@ impl Game2DFrameComposer for Hardware {
|
||||
}
|
||||
|
||||
fn emit_sprite(&mut self, sprite: Sprite) -> prometeu_hal::ComposerOpStatus {
|
||||
if !self.has_glyph_bank(sprite.bank_id as usize) {
|
||||
if self.gfx.glyph_banks.glyph_bank_slot(sprite.bank_id as usize).is_none() {
|
||||
return prometeu_hal::ComposerOpStatus::BankInvalid;
|
||||
}
|
||||
|
||||
@ -406,9 +339,12 @@ mod tests {
|
||||
let mut glyph_slots = [None; 16];
|
||||
glyph_slots[0] = Some(0);
|
||||
hardware.assets.glyph_asset_slot_index().rebuild_from_slots(&glyph_slots);
|
||||
assert!(HardwareBridge::bind_scene(&mut hardware, 0));
|
||||
assert_eq!(
|
||||
Game2DFrameComposer::bind_scene(&mut hardware, 0),
|
||||
prometeu_hal::ComposerOpStatus::Ok
|
||||
);
|
||||
|
||||
let mut packet = HardwareBridge::close_game2d_packet(&hardware);
|
||||
let mut packet = Game2DFrameComposer::close_game2d_packet(&hardware);
|
||||
packet.gfx2d = vec![Gfx2dCommand::FillRect {
|
||||
rect: Rect { x: 0, y: 0, w: 1, h: 1 },
|
||||
color: Color::BLUE,
|
||||
@ -433,7 +369,10 @@ mod tests {
|
||||
let mut glyph_slots = [None; 16];
|
||||
glyph_slots[0] = Some(0);
|
||||
hardware.assets.glyph_asset_slot_index().rebuild_from_slots(&glyph_slots);
|
||||
assert!(HardwareBridge::bind_scene(&mut hardware, 0));
|
||||
assert_eq!(
|
||||
Game2DFrameComposer::bind_scene(&mut hardware, 0),
|
||||
prometeu_hal::ComposerOpStatus::Ok
|
||||
);
|
||||
|
||||
let packet = Game2DFramePacket::new(
|
||||
ComposerFramePacket {
|
||||
@ -455,7 +394,7 @@ mod tests {
|
||||
Vec::new(),
|
||||
);
|
||||
|
||||
HardwareBridge::begin_frame(&mut hardware);
|
||||
Game2DFrameComposer::begin_frame(&mut hardware);
|
||||
RenderSubmissionSink::submit_render_submission(
|
||||
&mut hardware,
|
||||
RenderSubmission::game2d(FrameId::ZERO, packet),
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
use crate::asset_bridge::AssetBridge;
|
||||
use crate::audio_bridge::AudioBridge;
|
||||
use crate::gfx_bridge::GfxBridge;
|
||||
use crate::pad_bridge::PadBridge;
|
||||
use crate::render_submission::{Game2DFramePacket, RenderSubmission};
|
||||
use crate::sprite::Sprite;
|
||||
use crate::touch_bridge::TouchBridge;
|
||||
|
||||
/// Legacy migration scaffold for code that has not moved to `platform` facades yet.
|
||||
///
|
||||
/// `HardwareBridge` is intentionally not the final runtime-facing contract. New
|
||||
/// platform boundaries belong in `crate::platform`, and this trait must be
|
||||
/// removed after runtime, firmware, host, and tests finish migrating.
|
||||
pub trait HardwareBridge {
|
||||
fn begin_frame(&mut self);
|
||||
fn bind_scene(&mut self, scene_bank_id: usize) -> bool;
|
||||
fn unbind_scene(&mut self);
|
||||
fn set_camera(&mut self, x: i32, y: i32);
|
||||
fn emit_sprite(&mut self, sprite: Sprite) -> bool;
|
||||
fn close_game2d_packet(&self) -> Game2DFramePacket;
|
||||
fn publish_render_submission(&mut self, submission: &RenderSubmission);
|
||||
fn render_frame(&mut self);
|
||||
fn has_glyph_bank(&self, bank_id: usize) -> bool;
|
||||
|
||||
fn gfx(&self) -> &dyn GfxBridge;
|
||||
fn gfx_mut(&mut self) -> &mut dyn GfxBridge;
|
||||
|
||||
fn audio(&self) -> &dyn AudioBridge;
|
||||
fn audio_mut(&mut self) -> &mut dyn AudioBridge;
|
||||
|
||||
fn pad(&self) -> &dyn PadBridge;
|
||||
fn pad_mut(&mut self) -> &mut dyn PadBridge;
|
||||
|
||||
fn touch(&self) -> &dyn TouchBridge;
|
||||
fn touch_mut(&mut self) -> &mut dyn TouchBridge;
|
||||
|
||||
fn assets(&self) -> &dyn AssetBridge;
|
||||
fn assets_mut(&mut self) -> &mut dyn AssetBridge;
|
||||
}
|
||||
@ -1,27 +1,17 @@
|
||||
use crate::hardware_bridge::HardwareBridge;
|
||||
use crate::platform::RuntimePlatform;
|
||||
use crate::vm_fault::VmFault;
|
||||
|
||||
pub struct HostContext<'a> {
|
||||
pub hw: Option<&'a mut dyn HardwareBridge>,
|
||||
pub platform: Option<&'a mut dyn RuntimePlatform>,
|
||||
}
|
||||
|
||||
impl<'a> HostContext<'a> {
|
||||
pub fn new(hw: Option<&'a mut dyn HardwareBridge>) -> Self {
|
||||
Self { hw, platform: None }
|
||||
pub fn new(platform: Option<&'a mut dyn RuntimePlatform>) -> Self {
|
||||
Self { platform }
|
||||
}
|
||||
|
||||
pub fn new_platform(platform: Option<&'a mut dyn RuntimePlatform>) -> Self {
|
||||
Self { hw: None, platform }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn require_hw(&mut self) -> Result<&mut dyn HardwareBridge, VmFault> {
|
||||
match &mut self.hw {
|
||||
Some(hw) => Ok(*hw),
|
||||
None => Err(VmFault::Unavailable),
|
||||
}
|
||||
Self::new(platform)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
@ -11,7 +11,6 @@ pub mod debugger_protocol;
|
||||
pub mod gfx_bridge;
|
||||
pub mod glyph;
|
||||
pub mod glyph_bank;
|
||||
pub mod hardware_bridge;
|
||||
pub mod host_context;
|
||||
pub mod host_return;
|
||||
pub mod input_signals;
|
||||
@ -40,7 +39,6 @@ pub use asset_bridge::AssetBridge;
|
||||
pub use audio_bridge::{AudioBridge, AudioOpStatus, LoopMode};
|
||||
pub use composer_status::ComposerOpStatus;
|
||||
pub use gfx_bridge::{BlendMode, GfxBridge, GfxOpStatus};
|
||||
pub use hardware_bridge::HardwareBridge;
|
||||
pub use host_context::{HostContext, HostContextProvider};
|
||||
pub use host_return::HostReturn;
|
||||
pub use input_signals::InputSignals;
|
||||
@ -49,9 +47,8 @@ pub use native_interface::{NativeInterface, SyscallId};
|
||||
pub use pad_bridge::PadBridge;
|
||||
pub use platform::{
|
||||
AssetStoragePlatform, AudioPlatform, ClockPacingPlatform, Game2DFrameComposer, InputPlatform,
|
||||
LegacyHardwareGame2DFrameComposer, LegacyHardwareRenderSubmissionSink,
|
||||
LegacyHardwareRuntimePlatform, NoopTelemetryPlatform, RenderBackend, RenderSubmissionSink,
|
||||
RenderSubmitError, RuntimePlatform, TelemetryPlatform, TestPlatform,
|
||||
NoopTelemetryPlatform, RenderBackend, RenderSubmissionSink, RenderSubmitError, RuntimePlatform,
|
||||
TelemetryPlatform, TestPlatform,
|
||||
};
|
||||
pub use render_submission::{
|
||||
BoundScenePacket, Camera2D, ComposerFramePacket, FrameId, Game2DFramePacket, GameSpritePacket,
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use crate::asset_bridge::AssetBridge;
|
||||
use crate::audio_bridge::AudioBridge;
|
||||
use crate::composer_status::ComposerOpStatus;
|
||||
use crate::hardware_bridge::HardwareBridge;
|
||||
use crate::pad_bridge::PadBridge;
|
||||
use crate::render_submission::{Game2DFramePacket, RenderSubmission};
|
||||
use crate::sprite::Sprite;
|
||||
@ -21,26 +20,6 @@ pub trait RenderSubmissionSink {
|
||||
) -> Result<(), RenderSubmitError>;
|
||||
}
|
||||
|
||||
pub struct LegacyHardwareRenderSubmissionSink<'a> {
|
||||
hw: &'a mut dyn HardwareBridge,
|
||||
}
|
||||
|
||||
impl<'a> LegacyHardwareRenderSubmissionSink<'a> {
|
||||
pub fn new(hw: &'a mut dyn HardwareBridge) -> Self {
|
||||
Self { hw }
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderSubmissionSink for LegacyHardwareRenderSubmissionSink<'_> {
|
||||
fn submit_render_submission(
|
||||
&mut self,
|
||||
submission: RenderSubmission,
|
||||
) -> Result<(), RenderSubmitError> {
|
||||
self.hw.publish_render_submission(&submission);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait RenderBackend {
|
||||
fn render_frame(&mut self);
|
||||
}
|
||||
@ -54,138 +33,6 @@ pub trait Game2DFrameComposer {
|
||||
fn close_game2d_packet(&self) -> Game2DFramePacket;
|
||||
}
|
||||
|
||||
pub struct LegacyHardwareGame2DFrameComposer<'a> {
|
||||
hw: &'a mut dyn HardwareBridge,
|
||||
}
|
||||
|
||||
impl<'a> LegacyHardwareGame2DFrameComposer<'a> {
|
||||
pub fn new(hw: &'a mut dyn HardwareBridge) -> Self {
|
||||
Self { hw }
|
||||
}
|
||||
}
|
||||
|
||||
impl Game2DFrameComposer for LegacyHardwareGame2DFrameComposer<'_> {
|
||||
fn begin_frame(&mut self) {
|
||||
self.hw.begin_frame();
|
||||
}
|
||||
|
||||
fn bind_scene(&mut self, scene_bank_id: usize) -> ComposerOpStatus {
|
||||
if self.hw.bind_scene(scene_bank_id) {
|
||||
ComposerOpStatus::Ok
|
||||
} else {
|
||||
ComposerOpStatus::SceneUnavailable
|
||||
}
|
||||
}
|
||||
|
||||
fn unbind_scene(&mut self) {
|
||||
self.hw.unbind_scene();
|
||||
}
|
||||
|
||||
fn set_camera(&mut self, x: i32, y: i32) -> ComposerOpStatus {
|
||||
self.hw.set_camera(x, y);
|
||||
ComposerOpStatus::Ok
|
||||
}
|
||||
|
||||
fn emit_sprite(&mut self, sprite: Sprite) -> ComposerOpStatus {
|
||||
if !self.hw.has_glyph_bank(sprite.bank_id as usize) {
|
||||
return ComposerOpStatus::BankInvalid;
|
||||
}
|
||||
|
||||
if self.hw.emit_sprite(sprite) {
|
||||
ComposerOpStatus::Ok
|
||||
} else {
|
||||
ComposerOpStatus::SpriteOverflow
|
||||
}
|
||||
}
|
||||
|
||||
fn close_game2d_packet(&self) -> Game2DFramePacket {
|
||||
self.hw.close_game2d_packet()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LegacyHardwareRuntimePlatform<'a> {
|
||||
hw: &'a mut dyn HardwareBridge,
|
||||
}
|
||||
|
||||
impl<'a> LegacyHardwareRuntimePlatform<'a> {
|
||||
pub fn new(hw: &'a mut dyn HardwareBridge) -> Self {
|
||||
Self { hw }
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderSubmissionSink for LegacyHardwareRuntimePlatform<'_> {
|
||||
fn submit_render_submission(
|
||||
&mut self,
|
||||
submission: RenderSubmission,
|
||||
) -> Result<(), RenderSubmitError> {
|
||||
self.hw.publish_render_submission(&submission);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderBackend for LegacyHardwareRuntimePlatform<'_> {
|
||||
fn render_frame(&mut self) {
|
||||
self.hw.render_frame();
|
||||
}
|
||||
}
|
||||
|
||||
impl Game2DFrameComposer for LegacyHardwareRuntimePlatform<'_> {
|
||||
fn begin_frame(&mut self) {
|
||||
self.hw.begin_frame();
|
||||
}
|
||||
|
||||
fn bind_scene(&mut self, scene_bank_id: usize) -> ComposerOpStatus {
|
||||
if self.hw.bind_scene(scene_bank_id) {
|
||||
ComposerOpStatus::Ok
|
||||
} else {
|
||||
ComposerOpStatus::SceneUnavailable
|
||||
}
|
||||
}
|
||||
|
||||
fn unbind_scene(&mut self) {
|
||||
self.hw.unbind_scene();
|
||||
}
|
||||
|
||||
fn set_camera(&mut self, x: i32, y: i32) -> ComposerOpStatus {
|
||||
self.hw.set_camera(x, y);
|
||||
ComposerOpStatus::Ok
|
||||
}
|
||||
|
||||
fn emit_sprite(&mut self, sprite: Sprite) -> ComposerOpStatus {
|
||||
if !self.hw.has_glyph_bank(sprite.bank_id as usize) {
|
||||
return ComposerOpStatus::BankInvalid;
|
||||
}
|
||||
|
||||
if self.hw.emit_sprite(sprite) {
|
||||
ComposerOpStatus::Ok
|
||||
} else {
|
||||
ComposerOpStatus::SpriteOverflow
|
||||
}
|
||||
}
|
||||
|
||||
fn close_game2d_packet(&self) -> Game2DFramePacket {
|
||||
self.hw.close_game2d_packet()
|
||||
}
|
||||
}
|
||||
|
||||
impl InputPlatform for LegacyHardwareRuntimePlatform<'_> {
|
||||
fn pad(&self) -> &dyn PadBridge {
|
||||
self.hw.pad()
|
||||
}
|
||||
|
||||
fn pad_mut(&mut self) -> &mut dyn PadBridge {
|
||||
self.hw.pad_mut()
|
||||
}
|
||||
|
||||
fn touch(&self) -> &dyn TouchBridge {
|
||||
self.hw.touch()
|
||||
}
|
||||
|
||||
fn touch_mut(&mut self) -> &mut dyn TouchBridge {
|
||||
self.hw.touch_mut()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AudioPlatform: AudioBridge {}
|
||||
impl<T: AudioBridge + ?Sized> AudioPlatform for T {}
|
||||
|
||||
@ -212,8 +59,6 @@ pub struct NoopTelemetryPlatform;
|
||||
|
||||
impl TelemetryPlatform for NoopTelemetryPlatform {}
|
||||
|
||||
static LEGACY_NOOP_TELEMETRY: NoopTelemetryPlatform = NoopTelemetryPlatform;
|
||||
|
||||
pub trait RuntimePlatform {
|
||||
fn display_size(&self) -> (usize, usize) {
|
||||
(480, 270)
|
||||
@ -231,48 +76,6 @@ pub trait RuntimePlatform {
|
||||
fn telemetry(&self) -> &dyn TelemetryPlatform;
|
||||
}
|
||||
|
||||
impl RuntimePlatform for LegacyHardwareRuntimePlatform<'_> {
|
||||
fn render_submission_sink(&mut self) -> &mut dyn RenderSubmissionSink {
|
||||
self
|
||||
}
|
||||
|
||||
fn render_backend(&mut self) -> &mut dyn RenderBackend {
|
||||
self
|
||||
}
|
||||
|
||||
fn game2d_frame_composer(&mut self) -> &mut dyn Game2DFrameComposer {
|
||||
self
|
||||
}
|
||||
|
||||
fn audio(&self) -> &dyn AudioBridge {
|
||||
self.hw.audio()
|
||||
}
|
||||
|
||||
fn audio_mut(&mut self) -> &mut dyn AudioBridge {
|
||||
self.hw.audio_mut()
|
||||
}
|
||||
|
||||
fn input(&self) -> &dyn InputPlatform {
|
||||
self
|
||||
}
|
||||
|
||||
fn input_mut(&mut self) -> &mut dyn InputPlatform {
|
||||
self
|
||||
}
|
||||
|
||||
fn assets(&self) -> &dyn AssetBridge {
|
||||
self.hw.assets()
|
||||
}
|
||||
|
||||
fn assets_mut(&mut self) -> &mut dyn AssetBridge {
|
||||
self.hw.assets_mut()
|
||||
}
|
||||
|
||||
fn telemetry(&self) -> &dyn TelemetryPlatform {
|
||||
&LEGACY_NOOP_TELEMETRY
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TestPlatform: RuntimePlatform {}
|
||||
impl<T: RuntimePlatform + ?Sized> TestPlatform for T {}
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ use crate::os::SystemOS;
|
||||
use prometeu_hal::app_mode::AppMode;
|
||||
use prometeu_hal::cartridge::Cartridge;
|
||||
use prometeu_hal::telemetry::{CertificationConfig, TelemetryFrame};
|
||||
use prometeu_hal::{HardwareBridge, InputSignals, RuntimePlatform};
|
||||
use prometeu_hal::{InputSignals, RuntimePlatform};
|
||||
use prometeu_vm::VirtualMachine;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
@ -47,9 +47,9 @@ impl<'a> VmFacade<'a> {
|
||||
pub fn debug_step_instruction(
|
||||
&mut self,
|
||||
vm: &mut VirtualMachine,
|
||||
hw: &mut dyn HardwareBridge,
|
||||
platform: &mut dyn RuntimePlatform,
|
||||
) -> Option<CrashReport> {
|
||||
self.os.vm_runtime.debug_step_instruction(&mut self.os.log_service, vm, hw)
|
||||
self.os.vm_runtime.debug_step_instruction(&mut self.os.log_service, vm, platform)
|
||||
}
|
||||
|
||||
pub fn paused(&self) -> bool {
|
||||
|
||||
@ -9,9 +9,8 @@ use crate::services::memcard::MemcardService;
|
||||
use prometeu_hal::asset::{BankTelemetry, BankType};
|
||||
use prometeu_hal::log::{LogLevel, LogService, LogSource};
|
||||
use prometeu_hal::{
|
||||
FrameId, HardwareBridge, HostContext, InputSignals, LegacyHardwareRuntimePlatform,
|
||||
RenderSubmission, RenderSubmissionPacket, RenderSubmissionSink, RuntimePlatform,
|
||||
ShellUiFramePacket,
|
||||
FrameId, HostContext, InputSignals, RenderSubmission, RenderSubmissionPacket,
|
||||
RenderSubmissionSink, RuntimePlatform, ShellUiFramePacket,
|
||||
};
|
||||
use prometeu_vm::LogicalFrameEndingReason;
|
||||
use std::collections::HashMap;
|
||||
@ -77,11 +76,10 @@ impl VirtualMachineRuntime {
|
||||
&mut self,
|
||||
log_service: &mut LogService,
|
||||
vm: &mut VirtualMachine,
|
||||
hw: &mut dyn HardwareBridge,
|
||||
platform: &mut dyn RuntimePlatform,
|
||||
) -> Option<CrashReport> {
|
||||
let step_result = {
|
||||
let mut platform = LegacyHardwareRuntimePlatform::new(hw);
|
||||
let mut ctx = HostContext::new_platform(Some(&mut platform));
|
||||
let mut ctx = HostContext::new_platform(Some(platform));
|
||||
let mut fs = VirtualFS::new();
|
||||
let mut fs_state = FsState::Unmounted;
|
||||
let mut memcard = MemcardService::new();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use prometeu_drivers::hardware::Hardware;
|
||||
use prometeu_firmware::{BootTarget, Firmware};
|
||||
use prometeu_hal::RuntimePlatform;
|
||||
use prometeu_hal::cartridge_loader::CartridgeLoader;
|
||||
use prometeu_hal::debugger_protocol::*;
|
||||
use prometeu_hal::telemetry::{CertificationConfig, TelemetryFrame};
|
||||
@ -99,7 +99,7 @@ impl HostDebugger {
|
||||
|
||||
/// Main maintenance method called by the HostRunner every iteration.
|
||||
/// It handles new connections and processes incoming commands.
|
||||
pub fn check_commands(&mut self, firmware: &mut Firmware, hardware: &mut Hardware) {
|
||||
pub fn check_commands(&mut self, firmware: &mut Firmware, platform: &mut dyn RuntimePlatform) {
|
||||
// 1. Accept new client connections.
|
||||
if let Some(listener) = &self.listener
|
||||
&& let Ok((stream, _addr)) = listener.accept()
|
||||
@ -154,7 +154,7 @@ impl HostDebugger {
|
||||
continue;
|
||||
}
|
||||
if let Ok(cmd) = serde_json::from_str::<DebugCommand>(trimmed) {
|
||||
self.handle_command(cmd, firmware, hardware);
|
||||
self.handle_command(cmd, firmware, platform);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -182,7 +182,7 @@ impl HostDebugger {
|
||||
&mut self,
|
||||
cmd: DebugCommand,
|
||||
firmware: &mut Firmware,
|
||||
hardware: &mut Hardware,
|
||||
platform: &mut dyn RuntimePlatform,
|
||||
) {
|
||||
match cmd {
|
||||
DebugCommand::Ok | DebugCommand::Start => {
|
||||
@ -201,7 +201,7 @@ impl HostDebugger {
|
||||
DebugCommand::Step => {
|
||||
// Execute exactly one instruction and keep paused.
|
||||
firmware.os.vm().set_paused(true);
|
||||
let _ = firmware.os.vm().debug_step_instruction(&mut firmware.vm, hardware);
|
||||
let _ = firmware.os.vm().debug_step_instruction(&mut firmware.vm, platform);
|
||||
}
|
||||
DebugCommand::StepFrame => {
|
||||
// Execute until the end of the current logical frame.
|
||||
|
||||
@ -31,6 +31,13 @@ MUST contain a frame id, the active app mode, and one typed packet:
|
||||
immutable. The runtime backpressure policy is latest-complete-submission-wins;
|
||||
it MUST NOT accumulate an unbounded frame queue.
|
||||
|
||||
The platform layer is the runtime-facing implementation boundary for render
|
||||
handoff. Runtime and firmware code publish completed frames through typed
|
||||
platform services such as `RenderSubmissionSink`, and they access Game 2D
|
||||
composition through `Game2DFrameComposer`. They MUST NOT depend on a monolithic
|
||||
hardware bridge, mutable `Hardware`, mutable `Gfx`, or live `FrameComposer`
|
||||
reference as the render handoff contract.
|
||||
|
||||
The current 2D graphics model is based on:
|
||||
|
||||
- framebuffer
|
||||
@ -127,6 +134,10 @@ to the logical/runtime side before handoff, or to an owning service. They MUST
|
||||
NOT require the render consumer to hold mutable VM, `Hardware`, `Gfx`, or
|
||||
`FrameComposer` references.
|
||||
|
||||
Local host implementations may keep a concrete hardware object internally as a
|
||||
platform implementation detail. That object is not part of the runtime-facing
|
||||
render boundary; the boundary is the typed platform service set.
|
||||
|
||||
The runtime does not guarantee visual integrity if a developer or framework
|
||||
replaces resources behind an in-flight submission in a way that violates asset
|
||||
discipline.
|
||||
|
||||
@ -123,9 +123,13 @@ The graphics system:
|
||||
|
||||
The platform layer:
|
||||
|
||||
- exposes typed service facades for render submission, render backend
|
||||
execution, Game 2D composition, input, audio, assets, and telemetry
|
||||
- consumes closed render submissions through a render-surface implementation
|
||||
- transports published RGBA8888 output into a host presentation surface without
|
||||
injecting host-owned debug overlay pixels
|
||||
- is the runtime-facing portability boundary; runtime and firmware code must not
|
||||
depend on a monolithic hardware bridge or on a concrete hardware aggregate
|
||||
|
||||
The host presentation layer MUST treat RGBA8888 as the canonical logical
|
||||
framebuffer format. RGB565 conversion is not part of the normal host
|
||||
|
||||
@ -50,6 +50,12 @@ Does not belong in `docs/runtime/specs/` as the primary canonical source:
|
||||
|
||||
Here, hardware is not a generic bucket for everything. In the current package, "hardware" means the machine's virtual peripherals: GFX, AUDIO, INPUT, TOUCH, and MEMCARD/save memory. VM, firmware, cartridge, and ABI sit in sibling categories rather than inside hardware.
|
||||
|
||||
The implementation boundary for host portability is the platform layer. Runtime,
|
||||
firmware, and host integration code use typed platform services for rendering,
|
||||
input, audio, assets, and telemetry. A concrete local hardware aggregate may
|
||||
exist inside a host or test platform, but it is not the normative runtime-facing
|
||||
contract.
|
||||
|
||||
## Document Functions
|
||||
|
||||
- `normative`: defines the technical contract, expected behavior, or implementation-facing surface.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user