core: Add DefineBinaryData and SymbolClass connection (Part of #1368)
This commit is contained in:
parent
535b614ee4
commit
7b9049cedf
|
@ -7,6 +7,7 @@ use crate::avm2::object::{bytearray_allocator, Object, TObject};
|
|||
use crate::avm2::string::AvmString;
|
||||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use crate::character::Character;
|
||||
use encoding_rs::Encoding;
|
||||
use encoding_rs::UTF_8;
|
||||
use gc_arena::{GcCell, MutationContext};
|
||||
|
@ -20,6 +21,27 @@ pub fn instance_init<'gc>(
|
|||
) -> Result<Value<'gc>, Error> {
|
||||
if let Some(this) = this {
|
||||
activation.super_init(this, &[])?;
|
||||
|
||||
let class_object = this
|
||||
.as_class_object()
|
||||
.ok_or("Attempted to construct non-instance ByteArray")?;
|
||||
if let Some((movie, id)) = activation
|
||||
.context
|
||||
.library
|
||||
.avm2_class_registry()
|
||||
.class_symbol(class_object)
|
||||
{
|
||||
if let Some(lib) = activation.context.library.library_for_movie(movie) {
|
||||
if let Some(Character::BinaryData(binary_data)) = lib.character_by_id(id) {
|
||||
let mut byte_array = this
|
||||
.as_bytearray_mut(activation.context.gc_context)
|
||||
.ok_or_else(|| "Unable to get bytearray storage".to_string())?;
|
||||
byte_array.clear();
|
||||
byte_array.write_bytes(binary_data.as_ref())?;
|
||||
byte_array.set_position(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Value::Undefined)
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
use crate::tag_utils::{SwfMovie, SwfSlice};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub type BinaryData = SwfSlice;
|
||||
|
||||
impl BinaryData {
|
||||
pub fn from_swf_tag(movie: Arc<SwfMovie>, tag: &swf::DefineBinaryData) -> Self {
|
||||
SwfSlice::from(movie).to_subslice(tag.data).unwrap()
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
use crate::backend::audio::SoundHandle;
|
||||
use crate::binary_data::BinaryData;
|
||||
use crate::display_object::{
|
||||
Avm1Button, Avm2Button, Bitmap, EditText, Graphic, MorphShape, MovieClip, Text, Video,
|
||||
};
|
||||
|
@ -19,4 +20,5 @@ pub enum Character<'gc> {
|
|||
Text(Text<'gc>),
|
||||
Sound(#[collect(require_static)] SoundHandle),
|
||||
Video(Video<'gc>),
|
||||
BinaryData(BinaryData),
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ use crate::backend::ui::MouseCursor;
|
|||
use bitflags::bitflags;
|
||||
|
||||
use crate::avm1::activation::{Activation as Avm1Activation, ActivationIdentifier};
|
||||
use crate::binary_data::BinaryData;
|
||||
use crate::character::Character;
|
||||
use crate::context::{ActionType, RenderContext, UpdateContext};
|
||||
use crate::display_object::container::{
|
||||
|
@ -465,6 +466,10 @@ impl<'gc> MovieClip<'gc> {
|
|||
tag_len,
|
||||
)
|
||||
}
|
||||
TagCode::DefineBinaryData => self
|
||||
.0
|
||||
.write(context.gc_context)
|
||||
.define_binary_data(context, reader),
|
||||
_ => Ok(()),
|
||||
};
|
||||
let _ = tag_utils::decode_tags(&mut reader, tag_callback, TagCode::End);
|
||||
|
@ -602,14 +607,21 @@ impl<'gc> MovieClip<'gc> {
|
|||
if id == 0 {
|
||||
//TODO: This assumes only the root movie has `SymbolClass` tags.
|
||||
self.set_avm2_class(activation.context.gc_context, Some(class_object));
|
||||
} else if let Some(Character::MovieClip(mc)) = library.character_by_id(id) {
|
||||
mc.set_avm2_class(activation.context.gc_context, Some(class_object));
|
||||
} else {
|
||||
log::warn!(
|
||||
"Symbol class {} cannot be assigned to invalid character id {}",
|
||||
class_name,
|
||||
id
|
||||
);
|
||||
match library.character_by_id(id) {
|
||||
Some(Character::MovieClip(mc)) => mc.set_avm2_class(
|
||||
activation.context.gc_context,
|
||||
Some(class_object),
|
||||
),
|
||||
Some(Character::BinaryData(_)) => {}
|
||||
_ => {
|
||||
log::warn!(
|
||||
"Symbol class {} cannot be assigned to invalid character id {}",
|
||||
class_name,
|
||||
id
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => log::warn!(
|
||||
|
@ -2986,6 +2998,21 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn define_binary_data(
|
||||
&mut self,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
reader: &mut SwfStream<'a>,
|
||||
) -> DecodeResult {
|
||||
let tag_data = reader.read_define_binary_data()?;
|
||||
let binary_data = BinaryData::from_swf_tag(self.movie(), &tag_data);
|
||||
context
|
||||
.library
|
||||
.library_for_movie_mut(self.movie())
|
||||
.register_character(tag_data.id, Character::BinaryData(binary_data));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn script_limits(&mut self, reader: &mut SwfStream<'a>, avm: &mut Avm1<'gc>) -> DecodeResult {
|
||||
let max_recursion_depth = reader.read_u16()?;
|
||||
|
|
|
@ -24,6 +24,7 @@ extern crate num_derive;
|
|||
#[macro_use]
|
||||
mod avm1;
|
||||
mod avm2;
|
||||
mod binary_data;
|
||||
pub mod bitmap;
|
||||
mod bounding_box;
|
||||
mod character;
|
||||
|
|
|
@ -363,10 +363,7 @@ impl<'a> Reader<'a> {
|
|||
TagCode::ShowFrame => Tag::ShowFrame,
|
||||
TagCode::CsmTextSettings => Tag::CsmTextSettings(tag_reader.read_csm_text_settings()?),
|
||||
TagCode::DefineBinaryData => {
|
||||
let id = tag_reader.read_u16()?;
|
||||
tag_reader.read_u32()?; // Reserved
|
||||
let data = tag_reader.read_slice_to_end();
|
||||
Tag::DefineBinaryData { id, data }
|
||||
Tag::DefineBinaryData(tag_reader.read_define_binary_data()?)
|
||||
}
|
||||
TagCode::DefineBits => {
|
||||
let id = tag_reader.read_u16()?;
|
||||
|
@ -2342,6 +2339,13 @@ impl<'a> Reader<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn read_define_binary_data(&mut self) -> Result<DefineBinaryData<'a>> {
|
||||
let id = self.read_u16()?;
|
||||
self.read_u32()?; // Reserved
|
||||
let data = self.read_slice_to_end();
|
||||
Ok(DefineBinaryData { id, data })
|
||||
}
|
||||
|
||||
pub fn read_define_text(&mut self, version: u8) -> Result<Text> {
|
||||
let id = self.read_character_id()?;
|
||||
let bounds = self.read_rectangle()?;
|
||||
|
|
|
@ -41,10 +41,10 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
|||
),
|
||||
(
|
||||
9, // Minimum version not listed in SWF19.
|
||||
Tag::DefineBinaryData {
|
||||
Tag::DefineBinaryData(DefineBinaryData {
|
||||
id: 1,
|
||||
data: &[84, 101, 115, 116, 105, 110, 103, 33],
|
||||
},
|
||||
}),
|
||||
read_tag_bytes_from_file("tests/swfs/DefineBinaryData.swf", TagCode::DefineBinaryData),
|
||||
),
|
||||
(
|
||||
|
|
|
@ -786,10 +786,7 @@ pub enum Tag<'a> {
|
|||
Protect(Option<&'a SwfStr>),
|
||||
CsmTextSettings(CsmTextSettings),
|
||||
DebugId(DebugId),
|
||||
DefineBinaryData {
|
||||
id: CharacterId,
|
||||
data: &'a [u8],
|
||||
},
|
||||
DefineBinaryData(DefineBinaryData<'a>),
|
||||
DefineBits {
|
||||
id: CharacterId,
|
||||
jpeg_data: &'a [u8],
|
||||
|
@ -1301,6 +1298,12 @@ pub struct FontInfo<'a> {
|
|||
pub code_table: Vec<u16>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct DefineBinaryData<'a> {
|
||||
pub id: CharacterId,
|
||||
pub data: &'a [u8],
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Text {
|
||||
pub id: CharacterId,
|
||||
|
|
|
@ -499,12 +499,7 @@ impl<W: Write> Writer<W> {
|
|||
self.write_u8(0)?; // Reserved (0).
|
||||
}
|
||||
|
||||
Tag::DefineBinaryData { id, data } => {
|
||||
self.write_tag_header(TagCode::DefineBinaryData, data.len() as u32 + 6)?;
|
||||
self.write_u16(id)?;
|
||||
self.write_u32(0)?; // Reserved
|
||||
self.output.write_all(data)?;
|
||||
}
|
||||
Tag::DefineBinaryData(ref binary_data) => self.write_define_binary_data(binary_data)?,
|
||||
|
||||
Tag::DefineBits { id, jpeg_data } => {
|
||||
self.write_tag_header(TagCode::DefineBits, jpeg_data.len() as u32 + 2)?;
|
||||
|
@ -2284,6 +2279,14 @@ impl<W: Write> Writer<W> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write_define_binary_data(&mut self, binary_data: &DefineBinaryData) -> Result<()> {
|
||||
self.write_tag_header(TagCode::DefineBinaryData, binary_data.data.len() as u32 + 6)?;
|
||||
self.write_u16(binary_data.id)?;
|
||||
self.write_u32(0)?; // Reserved
|
||||
self.output.write_all(binary_data.data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_define_text(&mut self, text: &Text) -> Result<()> {
|
||||
let mut buf = Vec::new();
|
||||
{
|
||||
|
|
|
@ -621,6 +621,7 @@ swf_tests! {
|
|||
(as3_istypelate_coerce, "avm2/istypelate_coerce", 1),
|
||||
(as3_class_cast_call, "avm2/class_cast_call", 1),
|
||||
(as3_class_supercalls_mismatched, "avm2/class_supercalls_mismatched", 1),
|
||||
(as3_symbol_class_binary_data, "avm2/symbol_class_binary_data", 1),
|
||||
}
|
||||
|
||||
// TODO: These tests have some inaccuracies currently, so we use approx_eq to test that numeric values are close enough.
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package {
|
||||
import flash.display.Sprite;
|
||||
import flash.utils.ByteArray;
|
||||
|
||||
public class TestArray extends ByteArray {
|
||||
public function TestArray() {
|
||||
}
|
||||
}
|
||||
|
||||
public class TestArray2 extends ByteArray {
|
||||
public function TestArray2() {
|
||||
}
|
||||
}
|
||||
|
||||
public class Test extends Sprite {
|
||||
public function Test()
|
||||
{
|
||||
super();
|
||||
var bytearr:* = new TestArray();
|
||||
trace("ByteArray = ");
|
||||
trace(bytearr);
|
||||
trace("ByteArray Position = ");
|
||||
trace(bytearr.position);
|
||||
|
||||
var bytearr2:* = new TestArray2();
|
||||
trace("ByteArray2 = ");
|
||||
trace(bytearr2);
|
||||
trace("ByteArray2 Position = ");
|
||||
trace(bytearr.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
ByteArray =
|
||||
TestArrayContent
|
||||
ByteArray Position =
|
||||
0
|
||||
ByteArray2 =
|
||||
TestArray2Content
|
||||
ByteArray2 Position =
|
||||
0
|
Binary file not shown.
Loading…
Reference in New Issue