@@ -20,21 +20,21 @@ use oasis_backend_psp::{
2020} ;
2121
2222// oasis-core SDI integration types.
23- use oasis_core:: active_theme:: ActiveTheme ;
2423use oasis_core:: bottombar:: BottomBar ;
2524use oasis_core:: dashboard:: { AppEntry as CoreAppEntry , DashboardConfig , DashboardState } ;
2625use oasis_core:: platform:: { BatteryState , CpuClock , PowerInfo , SystemTime } ;
27- use oasis_core:: skin:: SkinFeatures ;
2826use oasis_core:: statusbar:: StatusBar ;
2927use oasis_core:: terminal_sdi;
3028
3129mod boot;
3230mod chrome;
3331mod commands;
3432mod desktop;
33+ mod skins;
3534mod theme;
3635mod types;
3736mod views;
37+ mod views_sdi;
3838
3939use theme:: * ;
4040use types:: * ;
@@ -155,32 +155,13 @@ fn psp_main() {
155155 dbg_log ( "[EBOOT] sysinfo queried" ) ;
156156
157157 // -- ActiveTheme (SDI integration) --
158- // Use default theme directly to avoid pulling in the TOML parser and
159- // 17 embedded skin files (~850KB code). ActiveTheme::default() provides
160- // PSIX-style layout already matched to 480x272.
158+ // Derive theme from a lightweight preset (9 base colors) instead of
159+ // pulling in the TOML parser + 18 embedded skin strings (~850KB).
161160 dbg_log ( "[EBOOT] creating theme..." ) ;
162- let mut active_theme = ActiveTheme :: default ( )
163- . with_screen_size ( SCREEN_WIDTH , SCREEN_HEIGHT ) ;
164- // PSP: make bar backgrounds opaque to prevent darkening window content.
165- // Default is semi-transparent (alpha=80) which looks muddy on 480x272.
166- active_theme. bar . statusbar_bg = Color :: rgba ( 10 , 10 , 20 , 255 ) ;
167- active_theme. bar . bg = Color :: rgba ( 10 , 10 , 20 , 255 ) ;
168- // PSP: match actual bar sizes (theme.rs constants) so SDI grid aligns.
169- active_theme. statusbar_height = 18 ;
170- active_theme. tab_row_height = 0 ;
171- active_theme. bottombar_height = 32 ;
172- // PSP: compact icons for 4x3 grid on 480x272.
173- active_theme. icon_width = 34 ;
174- active_theme. icon_height = 34 ;
175- active_theme. icon_stripe_h = 6 ;
176- active_theme. icon_fold_size = 5 ;
177- active_theme. grid_padding_x = 8 ;
178- active_theme. grid_padding_y = 2 ;
179- active_theme. cursor_pad = 2 ;
180- let mut skin_features = SkinFeatures :: default ( ) ;
181- skin_features. grid_cols = 4 ;
182- skin_features. grid_rows = 3 ;
183- skin_features. icons_per_page = 12 ;
161+ let skin_key = config. get_str ( "skin" ) . unwrap_or ( "psix" ) ;
162+ let mut current_preset = skins:: PspSkinPreset :: from_key ( skin_key) ;
163+ let mut active_theme = current_preset. to_active_theme ( ) ;
164+ let skin_features = skins:: PspSkinPreset :: skin_features ( ) ;
184165 dbg_log ( "[EBOOT] active_theme created" ) ;
185166 let dash_config = DashboardConfig :: from_features ( & skin_features, & active_theme) ;
186167
@@ -228,6 +209,7 @@ fn psp_main() {
228209 // -- App mode --
229210 let mut app_mode = AppMode :: Classic ;
230211 let mut classic_view = ClassicView :: Dashboard ;
212+ let mut prev_classic_view = ClassicView :: Dashboard ;
231213
232214 let mut icons_hidden: bool = false ;
233215 let mut viz_frame: u32 = 0 ;
@@ -896,6 +878,47 @@ fn psp_main() {
896878 audio. send ( AudioCmd :: Stop ) ;
897879 ( vec ! [ "Stopped." . into( ) ] , false )
898880 } ,
881+ "skin" => {
882+ let names: Vec < String > = skins:: PspSkinPreset :: ALL
883+ . iter ( )
884+ . map ( |p| {
885+ let marker =
886+ if * p == current_preset { ">" } else { " " } ;
887+ format ! ( "{} {}" , marker, p. name( ) )
888+ } )
889+ . collect ( ) ;
890+ let mut out = vec ! [ "Skins (use 'skin NAME'):" . into( ) ] ;
891+ out. extend ( names) ;
892+ ( out, false )
893+ } ,
894+ _ if cmd. trim ( ) . starts_with ( "skin " ) => {
895+ let key = cmd. trim ( ) . strip_prefix ( "skin " ) . unwrap ( ) . trim ( ) ;
896+ let preset = skins:: PspSkinPreset :: from_key ( key) ;
897+ if preset == current_preset {
898+ ( vec ! [ format!( "Already using '{}'." , key) ] , false )
899+ } else {
900+ current_preset = preset;
901+ active_theme = preset. to_active_theme ( ) ;
902+ dashboard. config = DashboardConfig :: from_features (
903+ & skin_features,
904+ & active_theme,
905+ ) ;
906+ config. set (
907+ "skin" ,
908+ psp:: config:: ConfigValue :: Str (
909+ preset. key ( ) . to_string ( ) ,
910+ ) ,
911+ ) ;
912+ let _ = config. save ( CONFIG_PATH ) ;
913+ (
914+ vec ! [ format!(
915+ "Skin changed to '{}'." ,
916+ preset. name( )
917+ ) ] ,
918+ false ,
919+ )
920+ }
921+ } ,
899922 _ => {
900923 let r = commands:: execute_command ( & cmd, & mut config) ;
901924 ( r. lines , r. used_dialog )
@@ -1628,6 +1651,13 @@ fn psp_main() {
16281651 terminal_sdi:: set_terminal_visible ( & mut sdi, false ) ;
16291652 }
16301653
1654+ // View transition: hide old SDI objects, set up new ones.
1655+ if classic_view != prev_classic_view {
1656+ views_sdi:: hide_all ( & mut sdi) ;
1657+ views_sdi:: setup_view ( & mut sdi, classic_view) ;
1658+ prev_classic_view = classic_view;
1659+ }
1660+
16311661 match classic_view {
16321662 ClassicView :: Dashboard => {
16331663 backend. force_bitmap_font = true ;
@@ -1666,9 +1696,8 @@ fn psp_main() {
16661696 backend. force_bitmap_font = false ;
16671697 } ,
16681698 ClassicView :: FileManager => {
1669- backend. force_bitmap_font = true ;
1670- views:: draw_file_manager_dual (
1671- & mut backend,
1699+ views_sdi:: update_file_manager (
1700+ & mut sdi,
16721701 & fm_path,
16731702 & fm_entries,
16741703 fm_selected,
@@ -1678,38 +1707,44 @@ fn psp_main() {
16781707 fm2_selected,
16791708 fm2_scroll,
16801709 fm_active_panel,
1710+ & active_theme,
16811711 ) ;
1712+ backend. force_bitmap_font = true ;
16821713 chrome:: draw_button_hints (
16831714 & mut backend,
16841715 & [ ( "X" , "Open" ) , ( "O" , "Back" ) , ( "<>" , "Panel" ) , ( "^v" , "Nav" ) ] ,
16851716 ) ;
16861717 backend. force_bitmap_font = false ;
16871718 } ,
16881719 ClassicView :: PhotoViewer => {
1689- backend. force_bitmap_font = true ;
16901720 if pv_viewing {
1691- views:: draw_photo_view ( & mut backend, pv_tex, pv_img_w, pv_img_h) ;
1721+ views_sdi:: update_photo_view ( & mut sdi, pv_tex, pv_img_w, pv_img_h) ;
1722+ backend. force_bitmap_font = true ;
16921723 chrome:: draw_button_hints ( & mut backend, & [ ( "O" , "Back" ) ] ) ;
1724+ backend. force_bitmap_font = false ;
16931725 } else if pv_loading {
16941726 desktop:: draw_loading_indicator ( & mut backend, "Decoding image..." ) ;
16951727 } else {
1696- views :: draw_photo_browser (
1697- & mut backend ,
1728+ views_sdi :: update_photo_browser (
1729+ & mut sdi ,
16981730 & pv_path,
16991731 & pv_entries,
17001732 pv_selected,
17011733 pv_scroll,
1734+ & active_theme,
17021735 ) ;
1736+ backend. force_bitmap_font = true ;
17031737 chrome:: draw_button_hints (
17041738 & mut backend,
17051739 & [ ( "X" , "View" ) , ( "O" , "Back" ) , ( "^v" , "Nav" ) ] ,
17061740 ) ;
1741+ backend. force_bitmap_font = false ;
17071742 }
1708- backend. force_bitmap_font = false ;
17091743 } ,
17101744 ClassicView :: MusicPlayer => {
1711- backend. force_bitmap_font = true ;
17121745 if audio. is_playing ( ) {
1746+ // Now-playing view uses direct rendering for visualizer.
1747+ backend. force_bitmap_font = true ;
17131748 views:: draw_music_player_threaded (
17141749 & mut backend,
17151750 & mp_file_name,
@@ -1720,34 +1755,38 @@ fn psp_main() {
17201755 & mut backend,
17211756 & [ ( "X" , "Pause" ) , ( "[]" , "Stop" ) , ( "^v" , "Back" ) ] ,
17221757 ) ;
1758+ backend. force_bitmap_font = false ;
17231759 } else {
1724- views :: draw_music_browser (
1725- & mut backend ,
1760+ views_sdi :: update_music_browser (
1761+ & mut sdi ,
17261762 & mp_path,
17271763 & mp_entries,
17281764 mp_selected,
17291765 mp_scroll,
1766+ & active_theme,
17301767 ) ;
1768+ backend. force_bitmap_font = true ;
17311769 chrome:: draw_button_hints (
17321770 & mut backend,
17331771 & [ ( "X" , "Play" ) , ( "O" , "Back" ) , ( "^v" , "Nav" ) ] ,
17341772 ) ;
1773+ backend. force_bitmap_font = false ;
17351774 }
1736- backend. force_bitmap_font = false ;
17371775 } ,
17381776 ClassicView :: Browser => {
1739- backend. force_bitmap_font = true ;
17401777 if br_loading {
17411778 desktop:: draw_loading_indicator ( & mut backend, "Loading page..." ) ;
17421779 } else {
1743- views :: draw_browser_view (
1744- & mut backend ,
1780+ views_sdi :: update_browser (
1781+ & mut sdi ,
17451782 & br_url,
17461783 & br_content_lines,
17471784 br_scroll,
17481785 & br_status_msg,
1786+ & active_theme,
17491787 ) ;
17501788 }
1789+ backend. force_bitmap_font = true ;
17511790 chrome:: draw_button_hints (
17521791 & mut backend,
17531792 & [
@@ -1763,7 +1802,12 @@ fn psp_main() {
17631802 backend. force_bitmap_font = true ;
17641803 match radio_status {
17651804 RadioStatus :: Stopped => {
1766- views:: draw_radio_stations ( & mut backend, radio_selected, radio_scroll) ;
1805+ views_sdi:: update_radio (
1806+ & mut sdi,
1807+ radio_selected,
1808+ radio_scroll,
1809+ & active_theme,
1810+ ) ;
17671811 chrome:: draw_button_hints (
17681812 & mut backend,
17691813 & [ ( "X" , "Tune" ) , ( "^v" , "Nav" ) , ( "O" , "Back" ) ] ,
@@ -1818,12 +1862,13 @@ fn psp_main() {
18181862 & [ ( "X" , "Retry" ) , ( "O" , "Back" ) ] ,
18191863 ) ;
18201864 } else {
1821- views :: draw_tv_channels (
1822- & mut backend ,
1865+ views_sdi :: update_tv_channels (
1866+ & mut sdi ,
18231867 & tv_channels,
18241868 & tv_catalogs,
18251869 tv_selected,
18261870 tv_scroll,
1871+ & active_theme,
18271872 ) ;
18281873 chrome:: draw_button_hints (
18291874 & mut backend,
@@ -1984,10 +2029,18 @@ fn psp_main() {
19842029 // - Overlay layer always (status bar, bottom bar at z=900)
19852030 // This avoids 100+ unnecessary draw calls in non-dashboard views.
19862031 let needs_base = match app_mode {
1987- AppMode :: Classic => matches ! (
1988- classic_view,
1989- ClassicView :: Dashboard | ClassicView :: Terminal
1990- ) ,
2032+ AppMode :: Classic => {
2033+ // SDI base layer is needed for dashboard, terminal, and all
2034+ // SDI-migrated list views. Skip only when a direct-rendered
2035+ // overlay is active (music now-playing, radio playing, etc.).
2036+ let is_direct_only =
2037+ ( classic_view == ClassicView :: MusicPlayer && audio. is_playing ( ) )
2038+ || ( classic_view == ClassicView :: Radio
2039+ && radio_status != RadioStatus :: Stopped )
2040+ || ( classic_view == ClassicView :: TvGuide
2041+ && ( tv_tuned. is_some ( ) || !tv_error_msg. is_empty ( ) ) ) ;
2042+ !is_direct_only
2043+ } ,
19912044 AppMode :: Desktop => false , // WM draws windows directly
19922045 } ;
19932046 if needs_base {
0 commit comments