diff --git a/core/src/avm1/globals/movie_clip.rs b/core/src/avm1/globals/movie_clip.rs index 1124af42d..d1553c0c2 100644 --- a/core/src/avm1/globals/movie_clip.rs +++ b/core/src/avm1/globals/movie_clip.rs @@ -721,19 +721,19 @@ pub fn duplicate_movie_clip_with_bias<'gc>( } fn get_bytes_loaded<'gc>( - _movie_clip: MovieClip<'gc>, - activation: &mut Activation<'_, 'gc, '_>, + movie_clip: MovieClip<'gc>, + _activation: &mut Activation<'_, 'gc, '_>, _args: &[Value<'gc>], ) -> Result, Error<'gc>> { - Ok(activation.context.swf.header().uncompressed_length.into()) + Ok((movie_clip.movie().unwrap().data().len() + 20).into()) } fn get_bytes_total<'gc>( - _movie_clip: MovieClip<'gc>, - activation: &mut Activation<'_, 'gc, '_>, + movie_clip: MovieClip<'gc>, + _activation: &mut Activation<'_, 'gc, '_>, _args: &[Value<'gc>], ) -> Result, Error<'gc>> { - Ok(activation.context.swf.header().uncompressed_length.into()) + Ok((movie_clip.movie().unwrap().data().len() + 20).into()) } fn get_next_highest_depth<'gc>( diff --git a/core/src/tag_utils.rs b/core/src/tag_utils.rs index 44b348129..06a4784c3 100644 --- a/core/src/tag_utils.rs +++ b/core/src/tag_utils.rs @@ -1,7 +1,6 @@ use crate::backend::navigator::url_from_relative_path; use crate::property_map::PropertyMap; use gc_arena::Collect; -use std::convert::TryInto; use std::path::Path; use std::sync::Arc; use swf::{Header, TagCode}; @@ -33,9 +32,8 @@ impl SwfMovie { pub fn empty(swf_version: u8) -> Self { Self { header: Header { - compression: swf::Compression::None, version: swf_version, - uncompressed_length: 0, + compression: swf::Compression::None, stage_size: swf::Rectangle::default(), frame_rate: 1.0, num_frames: 0, @@ -87,11 +85,11 @@ impl SwfMovie { // It always errors, and doesn't return all the data if you use read_to_end, // but read_exact at least returns the data... why? // Does the decoder need to be flushed somehow? - let mut data = vec![0u8; header.uncompressed_length.try_into().unwrap()]; + let mut data = vec![0u8; swf_stream.uncompressed_length]; let _ = reader.get_mut().read_exact(&mut data); data } else { - let mut data = Vec::with_capacity(header.uncompressed_length.try_into().unwrap()); + let mut data = Vec::with_capacity(swf_stream.uncompressed_length); if let Err(e) = reader.get_mut().read_to_end(&mut data) { return Err(format!("Error decompressing SWF, may be corrupt: {}", e).into()); } diff --git a/swf/src/read.rs b/swf/src/read.rs index 61ace7285..71a1b5558 100644 --- a/swf/src/read.rs +++ b/swf/src/read.rs @@ -35,11 +35,11 @@ pub fn read_swf(input: R) -> Result { // It always errors, and doesn't return all the data if you use read_to_end, // but read_exact at least returns the data... why? // Does the decoder need to be flushed somehow? - let mut data = vec![0u8; header.uncompressed_length.try_into().unwrap()]; + let mut data = vec![0u8; swf_stream.uncompressed_length]; let _ = reader.get_mut().read_exact(&mut data); data } else { - let mut data = Vec::with_capacity(header.uncompressed_length.try_into().unwrap()); + let mut data = Vec::with_capacity(swf_stream.uncompressed_length); if let Err(e) = reader.get_mut().read_to_end(&mut data) { log::error!("Error decompressing SWF, may be corrupt: {}", e); } @@ -55,7 +55,7 @@ pub fn read_swf(input: R) -> Result { if let Err(e) = reader.get_mut().read_to_end(&mut data) { log::warn!("Error decompressing SWF stream, may be corrupt: {}", e); } - if data.len() != header.uncompressed_length.try_into().unwrap() { + if data.len() != swf_stream.uncompressed_length { log::warn!("SWF length doesn't match header, may be corrupt"); } let mut reader = Reader::new(&data[..], version); @@ -81,7 +81,10 @@ pub fn read_swf_header<'a, R: Read + 'a>(mut input: R) -> Result> // Read SWF header. let compression = Reader::read_compression_type(&mut input)?; let version = input.read_u8()?; - let uncompressed_length = input.read_u32::()?; + + // Uncompressed length includes the 4-byte header and 4-byte uncompressed length itself, + // subtract it here. + let uncompressed_length = input.read_u32::()? - 8; // Now the SWF switches to a compressed stream. let decompressed_input: Box = match compression { @@ -102,9 +105,7 @@ pub fn read_swf_header<'a, R: Read + 'a>(mut input: R) -> Result> version ); } - // Uncompressed length includes the 4-byte header and 4-byte uncompressed length itself, - // subtract it here. - make_lzma_reader(input, uncompressed_length - 8)? + make_lzma_reader(input, uncompressed_length)? } }; @@ -113,14 +114,17 @@ pub fn read_swf_header<'a, R: Read + 'a>(mut input: R) -> Result> let frame_rate = reader.read_fixed8()?; let num_frames = reader.read_u16()?; let header = Header { - compression, version, - uncompressed_length, + compression, stage_size, frame_rate, num_frames, }; - Ok(SwfStream { header, reader }) + Ok(SwfStream { + header, + uncompressed_length: uncompressed_length.try_into().unwrap(), + reader, + }) } #[cfg(feature = "flate2")] diff --git a/swf/src/types.rs b/swf/src/types.rs index 82f5b718d..e2e60544e 100644 --- a/swf/src/types.rs +++ b/swf/src/types.rs @@ -22,6 +22,7 @@ pub struct Swf { /// stream as well as the uncompressed data length. pub struct SwfStream<'a> { pub header: Header, + pub uncompressed_length: usize, pub reader: crate::read::Reader>, } @@ -32,9 +33,8 @@ pub struct SwfStream<'a> { /// [SWF19 p.27](https://www.adobe.com/content/dam/acom/en/devnet/pdf/swf-file-format-spec.pdf#page=27) #[derive(Debug, PartialEq, Clone)] pub struct Header { - pub compression: Compression, pub version: u8, - pub uncompressed_length: u32, + pub compression: Compression, pub stage_size: Rectangle, pub frame_rate: f32, pub num_frames: u16, diff --git a/swf/src/write.rs b/swf/src/write.rs index e8088a9c0..b3c5b8f25 100644 --- a/swf/src/write.rs +++ b/swf/src/write.rs @@ -2760,9 +2760,8 @@ mod tests { fn new_swf() -> Swf { Swf { header: Header { - compression: Compression::Zlib, version: 13, - uncompressed_length: 1024, + compression: Compression::Zlib, stage_size: Rectangle { x_min: Twips::from_pixels(0.0), x_max: Twips::from_pixels(640.0),