core: Retain properties for System in the player

This commit is contained in:
CUB3D 2020-05-27 01:52:22 +01:00
parent 8471523e49
commit 0f0f778830
4 changed files with 100 additions and 23 deletions

View File

@ -1,12 +1,12 @@
use crate::avm1::object::Object; use crate::avm1::object::Object;
use crate::avm1::property::Attribute::{DontDelete, DontEnum, ReadOnly}; use crate::avm1::property::Attribute::{DontDelete, DontEnum, ReadOnly};
use crate::avm1::return_value::ReturnValue; use crate::avm1::return_value::ReturnValue;
use crate::avm1::value::Value::{Bool, Undefined};
use crate::avm1::{Avm1, Error, ScriptObject, TObject, Value}; use crate::avm1::{Avm1, Error, ScriptObject, TObject, Value};
use crate::context::UpdateContext; use crate::context::UpdateContext;
use gc_arena::MutationContext; use gc_arena::MutationContext;
use num_enum::TryFromPrimitive; use num_enum::TryFromPrimitive;
use std::convert::TryFrom; use std::convert::TryFrom;
use crate::avm1::function::Executable;
#[derive(Debug, Copy, Clone, TryFromPrimitive)] #[derive(Debug, Copy, Clone, TryFromPrimitive)]
#[repr(u8)] #[repr(u8)]
@ -17,6 +17,27 @@ enum SettingsPanel {
Camera = 3, Camera = 3,
} }
/// The properties modified by 'System'
pub struct SystemProperties {
/// If true then settings should be saved and read from the exact same domain of the player
/// If false then they should be saved to the super domain
pub exact_settings: bool,
/// If true then the system codepage should be used instead of unicode for text files
/// If false then unicode should be used
pub use_codepage: bool
}
impl Default for SystemProperties {
fn default() -> Self {
SystemProperties {
//TODO: default to true on fp>=7, false <= 6
exact_settings: true,
//TODO: default to false on fp>=7, true <= 6
use_codepage: false
}
}
}
pub fn set_clipboard<'gc>( pub fn set_clipboard<'gc>(
avm: &mut Avm1<'gc>, avm: &mut Avm1<'gc>,
action_context: &mut UpdateContext<'_, 'gc, '_>, action_context: &mut UpdateContext<'_, 'gc, '_>,
@ -31,7 +52,7 @@ pub fn set_clipboard<'gc>(
log::warn!("System.setClipboard({}) not yet implemented", new_content); log::warn!("System.setClipboard({}) not yet implemented", new_content);
Ok(Undefined.into()) Ok(Value::Undefined.into())
} }
pub fn show_settings<'gc>( pub fn show_settings<'gc>(
@ -53,7 +74,59 @@ pub fn show_settings<'gc>(
.unwrap_or(last_panel); .unwrap_or(last_panel);
log::warn!("System.showSettings({:?}) not not implemented", panel); log::warn!("System.showSettings({:?}) not not implemented", panel);
Ok(Undefined.into()) Ok(Value::Undefined.into())
}
pub fn set_use_code_page<'gc>(
avm: &mut Avm1<'gc>,
action_context: &mut UpdateContext<'_, 'gc, '_>,
_this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error> {
let value = args
.get(0)
.unwrap_or(&Value::Undefined)
.to_owned()
.as_bool(avm.current_swf_version());
action_context.system.use_codepage = value;
Ok(Value::Undefined.into())
}
pub fn get_use_code_page<'gc>(
_avm: &mut Avm1<'gc>,
action_context: &mut UpdateContext<'_, 'gc, '_>,
_this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error> {
Ok(action_context.system.use_codepage.into())
}
pub fn set_exact_settings<'gc>(
avm: &mut Avm1<'gc>,
action_context: &mut UpdateContext<'_, 'gc, '_>,
_this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error> {
let value = args
.get(0)
.unwrap_or(&Value::Undefined)
.to_owned()
.as_bool(avm.current_swf_version());
action_context.system.exact_settings = value;
Ok(Value::Undefined.into())
}
pub fn get_exact_settings<'gc>(
_avm: &mut Avm1<'gc>,
action_context: &mut UpdateContext<'_, 'gc, '_>,
_this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error> {
Ok(action_context.system.exact_settings.into())
} }
pub fn on_status<'gc>( pub fn on_status<'gc>(
@ -63,7 +136,7 @@ pub fn on_status<'gc>(
_args: &[Value<'gc>], _args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error> { ) -> Result<ReturnValue<'gc>, Error> {
log::warn!("System.onStatus() not implemented"); log::warn!("System.onStatus() not implemented");
Ok(Undefined.into()) Ok(Value::Undefined.into())
} }
pub fn create<'gc>( pub fn create<'gc>(
@ -73,43 +146,41 @@ pub fn create<'gc>(
) -> Object<'gc> { ) -> Object<'gc> {
let mut system = ScriptObject::object(gc_context, proto); let mut system = ScriptObject::object(gc_context, proto);
//TODO: default to true on fp>=7, false <= 6 system.add_property(
// TODO: if true, settings are linked to exact domains (abc.example.com),
// if false then use the settings for the root domain (example.com)
system.define_value(
gc_context, gc_context,
"exactSettings", "exactSettings",
Bool(true), Executable::Native(get_exact_settings),
Some(Executable::Native(set_exact_settings)),
DontDelete | DontEnum, DontDelete | DontEnum,
); );
//TODO: default to false on fp>=7, true <= 6
// when true, external text data should be loaded using the system codepage instead of unicode system.add_property(
system.define_value(
gc_context, gc_context,
"useCodepage", "useCodepage",
Bool(false), Executable::Native(get_use_code_page),
Some(Executable::Native(set_use_code_page)),
DontDelete | DontEnum, DontDelete | DontEnum,
); );
system.define_value( system.define_value(
gc_context, gc_context,
"security", "security",
Undefined, Value::Undefined,
DontDelete | ReadOnly | DontEnum, DontDelete | ReadOnly | DontEnum,
); );
system.define_value( system.define_value(
gc_context, gc_context,
"capabilities", "capabilities",
crate::avm1::globals::system_capabilities::create(gc_context, proto, fn_proto).into(), crate::avm1::globals::system_capabilities::create(gc_context, proto).into(),
DontDelete | ReadOnly | DontEnum, DontDelete | ReadOnly | DontEnum,
); );
system.define_value( system.define_value(
gc_context, gc_context,
"IME", "IME",
Undefined, Value::Undefined,
DontDelete | ReadOnly | DontEnum, DontDelete | ReadOnly | DontEnum,
); );

View File

@ -1,12 +1,7 @@
use crate::avm1::object::Object; use crate::avm1::object::Object;
use crate::avm1::property::Attribute::{DontDelete, DontEnum, ReadOnly}; use crate::avm1::property::Attribute::{DontDelete, DontEnum, ReadOnly};
use crate::avm1::return_value::ReturnValue; use crate::avm1::{ScriptObject, TObject};
use crate::avm1::value::Value::{Bool, Undefined};
use crate::avm1::{Avm1, Error, ScriptObject, TObject, Value};
use crate::context::UpdateContext;
use gc_arena::MutationContext; use gc_arena::MutationContext;
use num_enum::TryFromPrimitive;
use std::convert::TryFrom;
use crate::avm1::globals::system_capabilities::Language::English; use crate::avm1::globals::system_capabilities::Language::English;
#[allow(dead_code)] #[allow(dead_code)]
@ -68,7 +63,6 @@ impl Language {
pub fn create<'gc>( pub fn create<'gc>(
gc_context: MutationContext<'gc, '_>, gc_context: MutationContext<'gc, '_>,
proto: Option<Object<'gc>>, proto: Option<Object<'gc>>,
fn_proto: Option<Object<'gc>>,
) -> Object<'gc> { ) -> Object<'gc> {
let capabilities = ScriptObject::object(gc_context, proto); let capabilities = ScriptObject::object(gc_context, proto);

View File

@ -17,6 +17,7 @@ use rand::rngs::SmallRng;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::sync::{Arc, Mutex, Weak}; use std::sync::{Arc, Mutex, Weak};
use crate::avm1::globals::system::SystemProperties;
/// `UpdateContext` holds shared data that is used by the various subsystems of Ruffle. /// `UpdateContext` holds shared data that is used by the various subsystems of Ruffle.
/// `Player` crates this when it begins a tick and passes it through the call stack to /// `Player` crates this when it begins a tick and passes it through the call stack to
@ -96,6 +97,9 @@ pub struct UpdateContext<'a, 'gc, 'gc_context> {
/// This is required for asynchronous behavior, such as fetching data from /// This is required for asynchronous behavior, such as fetching data from
/// a URL. /// a URL.
pub load_manager: &'a mut LoadManager<'gc>, pub load_manager: &'a mut LoadManager<'gc>,
/// The system properties
pub system: &'a mut SystemProperties,
} }
/// A queued ActionScript call. /// A queued ActionScript call.

View File

@ -20,6 +20,8 @@ use std::collections::BTreeMap;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::ops::DerefMut; use std::ops::DerefMut;
use std::sync::{Arc, Mutex, Weak}; use std::sync::{Arc, Mutex, Weak};
use crate::avm1::globals::system::SystemProperties;
static DEVICE_FONT_TAG: &[u8] = include_bytes!("../assets/noto-sans-definefont3.bin"); static DEVICE_FONT_TAG: &[u8] = include_bytes!("../assets/noto-sans-definefont3.bin");
@ -135,6 +137,8 @@ pub struct Player {
/// The current mouse cursor icon. /// The current mouse cursor icon.
mouse_cursor: MouseCursor, mouse_cursor: MouseCursor,
system: SystemProperties,
/// Self-reference to ourselves. /// Self-reference to ourselves.
/// ///
/// This is a weak reference that is upgraded and handed out in various /// This is a weak reference that is upgraded and handed out in various
@ -233,6 +237,7 @@ impl Player {
navigator, navigator,
input, input,
self_reference: None, self_reference: None,
system: SystemProperties::default()
}; };
player.mutate_with_update_context(|avm, context| { player.mutate_with_update_context(|avm, context| {
@ -831,6 +836,7 @@ impl Player {
stage_width, stage_width,
stage_height, stage_height,
player, player,
system_properties,
) = ( ) = (
self.player_version, self.player_version,
self.global_time, self.global_time,
@ -845,6 +851,7 @@ impl Player {
Twips::from_pixels(self.movie_width.into()), Twips::from_pixels(self.movie_width.into()),
Twips::from_pixels(self.movie_height.into()), Twips::from_pixels(self.movie_height.into()),
self.self_reference.clone(), self.self_reference.clone(),
&mut self.system,
); );
self.gc_arena.mutate(|gc_context, gc_root| { self.gc_arena.mutate(|gc_context, gc_root| {
@ -874,6 +881,7 @@ impl Player {
system_prototypes: avm.prototypes().clone(), system_prototypes: avm.prototypes().clone(),
player, player,
load_manager, load_manager,
system: system_properties
}; };
let ret = f(avm, &mut update_context); let ret = f(avm, &mut update_context);