Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 30 additions & 9 deletions psp/src/dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,20 +102,31 @@ fn run_dialog(params: &mut UtilityMsgDialogParams) -> Result<DialogResult, Dialo

for _ in 0..MAX_DIALOG_ITERATIONS {
let status = unsafe { crate::sys::sceUtilityMsgDialogGetStatus() };
if status == 0 {
if status == 0 || status < 0 {
break;
}

// Provide a GU frame for the dialog to render into.
// Provide a GU frame with a cleared screen as the dialog
// background, then close the frame before updating the
// utility dialog. PSPSDK convention: the dialog update
// must be called **outside** any open GU display list.
// SAFETY: DIALOG_LIST is only used by utility dialog loops
// which run on the main thread and never overlap.
unsafe {
crate::sys::sceGuStart(
crate::sys::GuContextType::Direct,
&raw mut DIALOG_LIST as *mut core::ffi::c_void,
);
crate::sys::sceGuClearColor(0xff00_0000); // opaque black
crate::sys::sceGuClear(crate::sys::ClearBuffer::COLOR_BUFFER_BIT);
crate::sys::sceGuFinish();
crate::sys::sceGuSync(
crate::sys::GuSyncMode::Finish,
crate::sys::GuSyncBehavior::Wait,
);
}

// Update the utility dialog outside the GU frame.
match status {
2 => unsafe {
crate::sys::sceUtilityMsgDialogUpdate(1);
Expand All @@ -126,19 +137,29 @@ fn run_dialog(params: &mut UtilityMsgDialogParams) -> Result<DialogResult, Dialo
_ => {},
}

// SAFETY: GU frame lifecycle calls to finalize the dialog's
// display list and present it on screen.
// SAFETY: Present the frame.
unsafe {
crate::sys::sceGuFinish();
crate::sys::sceGuSync(
crate::sys::GuSyncMode::Finish,
crate::sys::GuSyncBehavior::Wait,
);
crate::sys::sceDisplayWaitVblankStart();
crate::sys::sceGuSwapBuffers();
}
}

// If the dialog reached QUIT (3) or FINISHED (4) but the polling
// loop exited before it drained to NONE (0), finish the shutdown.
for _ in 0..120 {
let s = unsafe { crate::sys::sceUtilityMsgDialogGetStatus() };
match s {
3 => unsafe {
crate::sys::sceUtilityMsgDialogShutdownStart();
crate::sys::sceDisplayWaitVblankStart();
},
4 => unsafe {
crate::sys::sceDisplayWaitVblankStart();
},
_ => break,
}
}

Ok(match params.button_pressed {
UtilityMsgDialogPressed::Yes => DialogResult::Confirm,
UtilityMsgDialogPressed::No => DialogResult::Cancel,
Expand Down
41 changes: 32 additions & 9 deletions psp/src/osk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,20 +169,31 @@ impl OskBuilder {

for _ in 0..MAX_OSK_ITERATIONS {
let status = unsafe { crate::sys::sceUtilityOskGetStatus() };
if status == 0 {
if status == 0 || status < 0 {
break;
}

// Provide a GU frame for the dialog to render into.
// Provide a GU frame with a cleared screen as the dialog
// background, then close the frame before updating the
// utility dialog. PSPSDK convention: the dialog update
// must be called **outside** any open GU display list.
// SAFETY: DIALOG_LIST is only used by utility dialog loops
// which run on the main thread and never overlap.
unsafe {
crate::sys::sceGuStart(
crate::sys::GuContextType::Direct,
&raw mut DIALOG_LIST as *mut core::ffi::c_void,
);
crate::sys::sceGuClearColor(0xff00_0000); // opaque black
crate::sys::sceGuClear(crate::sys::ClearBuffer::COLOR_BUFFER_BIT);
crate::sys::sceGuFinish();
crate::sys::sceGuSync(
crate::sys::GuSyncMode::Finish,
crate::sys::GuSyncBehavior::Wait,
);
}

// Update the utility dialog outside the GU frame.
match status {
2 => unsafe {
crate::sys::sceUtilityOskUpdate(1);
Expand All @@ -193,19 +204,31 @@ impl OskBuilder {
_ => {},
}

// SAFETY: GU frame lifecycle calls to finalize the dialog's
// display list and present it on screen.
// SAFETY: Present the frame.
unsafe {
crate::sys::sceGuFinish();
crate::sys::sceGuSync(
crate::sys::GuSyncMode::Finish,
crate::sys::GuSyncBehavior::Wait,
);
crate::sys::sceDisplayWaitVblankStart();
crate::sys::sceGuSwapBuffers();
}
}

// If the dialog reached QUIT (3) or FINISHED (4) but the polling
// loop exited before it drained to NONE (0), finish the shutdown.
// We cannot call ShutdownStart from RUNNING (2) -- that requires
// user interaction to transition to QUIT first.
for _ in 0..120 {
let s = unsafe { crate::sys::sceUtilityOskGetStatus() };
match s {
3 => unsafe {
crate::sys::sceUtilityOskShutdownStart();
crate::sys::sceDisplayWaitVblankStart();
},
4 => unsafe {
crate::sys::sceDisplayWaitVblankStart();
},
_ => break,
}
}

match osk_data.result {
SceUtilityOskResult::Changed => {
let text = utf16_to_string(&output_buf);
Expand Down
Loading