Struct spectrusty::chip::ula::frame_cache::UlaFrameCache
source · pub struct UlaFrameCache<V> {
pub frame_pixels: [(u32, [u8; 32]); 192],
pub frame_colors: [(u32, [u8; 32]); 192],
pub frame_colors_coarse: [(u32, [u8; 32]); 24],
/* private fields */
}
Expand description
Spectrum’s video data frame cache.
When a byte is being written to the video memory and the video beam position has already passed the referenced screen cell, the cell value is being cached from memory before the data in memory is being modified.
The caching is performed only once per frame for each potential cell so subsequent writes to the same memory address won’t modify the cached cell value.
When a screen is being drawn the data stored in cache will override any value currently residing in video memory.
Fields§
§frame_pixels: [(u32, [u8; 32]); 192]
§frame_colors: [(u32, [u8; 32]); 192]
§frame_colors_coarse: [(u32, [u8; 32]); 24]
Implementations§
source§impl<V> UlaFrameCache<V>
impl<V> UlaFrameCache<V>
sourcepub fn clear(&mut self)
pub fn clear(&mut self)
Examples found in repository?
More examples
577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
fn prepare_next_frame<C: MemoryContention>(
&mut self,
vtsc: VFrameTsCounter<U::VideoFrame, C>
) -> VFrameTsCounter<U::VideoFrame, C>
{
self.beg_render_mode = self.cur_render_mode;
self.beg_source_mode = self.cur_source_mode;
self.beg_palette = self.cur_palette;
self.sec_frame_cache.clear();
self.shadow_sec_frame_cache.clear();
self.palette_changes.clear();
self.source_changes.clear();
self.mode_changes.clear();
self.ula.prepare_next_frame(vtsc)
}
source§impl<V: VideoFrame> UlaFrameCache<V>
impl<V: VideoFrame> UlaFrameCache<V>
sourcepub fn update_frame_pixels<M: ZxMemory>(
&mut self,
memory: &M,
_: CellCoords,
addr: u16,
ts: VideoTs
)
pub fn update_frame_pixels<M: ZxMemory>(
&mut self,
memory: &M,
_: CellCoords,
addr: u16,
ts: VideoTs
)
Compares the given bitmap cell coordinates with the video timestamp and depending on the result of that comparison caches (or not) the bitmap cell with the value from the memory at the given address.
Examples found in repository?
149 150 151 152 153 154 155 156 157 158 159 160 161
pub(super) fn update_frame_cache(&mut self, addr: u16, ts: VideoTs) {
match addr {
0x4000..=0x57FF => {
let coords = pixel_address_coords(addr);
self.frame_cache.update_frame_pixels(&self.memory, coords, addr, ts);
}
0x5800..=0x5AFF => {
let coords = color_address_coords(addr);
self.frame_cache.update_frame_colors(&self.memory, coords, addr, ts);
}
_ => {}
}
}
More examples
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
pub(super) fn update_frame_cache(&mut self, addr: u16, ts: VideoTs) {
let frame_cache = match addr {
0x4000..=0x5AFF if self.mem_paged & 4 == 0 => &mut self.ula.frame_cache,
0x6000..=0x7AFF if self.mem_paged & 8 == 0 => &mut self.sec_frame_cache,
_ => return
};
if addr & 0x1800 != 0x1800 {
let coords = pixel_address_coords(addr);
frame_cache.update_frame_pixels(&self.ula.memory, coords, addr, ts);
}
else {
let coords = color_address_coords(addr);
frame_cache.update_frame_colors(&self.ula.memory, coords, addr, ts);
}
}
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
pub(super) fn update_frame_cache(&mut self, addr: u16, ts: VideoTs) {
let frame_cache = match addr {
0x4000..=0x5AFF => &mut self.ula.frame_cache,
0xC000..=0xDAFF => match self.page3_screen_shadow_bank() {
Some(false) => &mut self.ula.frame_cache,
Some(true) => &mut self.shadow_frame_cache,
None => return
}
_ => return
};
if addr & 0x1800 != 0x1800 {
let coords = pixel_address_coords(addr);
frame_cache.update_frame_pixels(&self.ula.memory, coords, addr, ts);
}
else {
let coords = color_address_coords(addr);
frame_cache.update_frame_colors(&self.ula.memory, coords, addr, ts);
}
}
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
pub(super) fn update_frame_cache(&mut self, addr: u16, ts: VideoTs) {
let maybe_shadow = match addr {
0x4000..=0x5AFF => self.page1_screen_shadow_bank(),
0xC000..=0xDAFF => self.page3_screen_shadow_bank(),
_ => return
};
let frame_cache = match maybe_shadow {
Some(false) => &mut self.ula.frame_cache,
Some(true) => &mut self.shadow_frame_cache,
None => return
};
if addr & 0x1800 != 0x1800 {
let coords = pixel_address_coords(addr);
frame_cache.update_frame_pixels(&self.ula.memory, coords, addr, ts);
}
else {
let coords = color_address_coords(addr);
frame_cache.update_frame_colors(&self.ula.memory, coords, addr, ts);
}
}
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
pub(super) fn update_frame_cache(&mut self, addr: u16, ts: VideoTs) {
let (frame_cache, memory_ref): (&mut UlaFrameCache<_>, _) = match addr {
0x4000..=0x5AFF => match self.ula.page1_screen0_shadow_bank() {
Some(false) => self.ula.frame_cache_mut_mem_ref(),
Some(true) => self.ula.shadow_frame_cache_mut_mem_ref(),
None => return
}
0x6000..=0x7AFF => match self.ula.page1_screen1_shadow_bank() {
Some(false) => (&mut self.sec_frame_cache, self.ula.memory_ref()),
Some(true) => (&mut self.shadow_sec_frame_cache, self.ula.memory_ref()),
None => return
}
0xC000..=0xDAFF => match self.ula.page3_screen0_shadow_bank() {
Some(false) => self.ula.frame_cache_mut_mem_ref(),
Some(true) => self.ula.shadow_frame_cache_mut_mem_ref(),
None => return
}
0xE000..=0xFAFF => match self.ula.page3_screen1_shadow_bank() {
Some(false) => (&mut self.sec_frame_cache, self.ula.memory_ref()),
Some(true) => (&mut self.shadow_sec_frame_cache, self.ula.memory_ref()),
None => return
}
_ => return
};
if addr & 0x1800 != 0x1800 {
let coords = pixel_address_coords(addr);
frame_cache.update_frame_pixels(memory_ref, coords, addr, ts);
}
else {
let coords = color_address_coords(addr);
frame_cache.update_frame_colors(memory_ref, coords, addr, ts);
}
}
sourcepub fn update_frame_colors<M: ZxMemory>(
&mut self,
memory: &M,
_: CellCoords,
addr: u16,
ts: VideoTs
)
pub fn update_frame_colors<M: ZxMemory>(
&mut self,
memory: &M,
_: CellCoords,
addr: u16,
ts: VideoTs
)
Compares the given attribute cell coordinates with the video timestamp and depending on the result of that comparison caches (or not) the attribute cell or cells with the value from the memory at the given address.
Examples found in repository?
149 150 151 152 153 154 155 156 157 158 159 160 161
pub(super) fn update_frame_cache(&mut self, addr: u16, ts: VideoTs) {
match addr {
0x4000..=0x57FF => {
let coords = pixel_address_coords(addr);
self.frame_cache.update_frame_pixels(&self.memory, coords, addr, ts);
}
0x5800..=0x5AFF => {
let coords = color_address_coords(addr);
self.frame_cache.update_frame_colors(&self.memory, coords, addr, ts);
}
_ => {}
}
}
More examples
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
pub(super) fn update_frame_cache(&mut self, addr: u16, ts: VideoTs) {
let frame_cache = match addr {
0x4000..=0x5AFF if self.mem_paged & 4 == 0 => &mut self.ula.frame_cache,
0x6000..=0x7AFF if self.mem_paged & 8 == 0 => &mut self.sec_frame_cache,
_ => return
};
if addr & 0x1800 != 0x1800 {
let coords = pixel_address_coords(addr);
frame_cache.update_frame_pixels(&self.ula.memory, coords, addr, ts);
}
else {
let coords = color_address_coords(addr);
frame_cache.update_frame_colors(&self.ula.memory, coords, addr, ts);
}
}
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
pub(super) fn update_frame_cache(&mut self, addr: u16, ts: VideoTs) {
let frame_cache = match addr {
0x4000..=0x5AFF => &mut self.ula.frame_cache,
0xC000..=0xDAFF => match self.page3_screen_shadow_bank() {
Some(false) => &mut self.ula.frame_cache,
Some(true) => &mut self.shadow_frame_cache,
None => return
}
_ => return
};
if addr & 0x1800 != 0x1800 {
let coords = pixel_address_coords(addr);
frame_cache.update_frame_pixels(&self.ula.memory, coords, addr, ts);
}
else {
let coords = color_address_coords(addr);
frame_cache.update_frame_colors(&self.ula.memory, coords, addr, ts);
}
}
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
pub(super) fn update_frame_cache(&mut self, addr: u16, ts: VideoTs) {
let maybe_shadow = match addr {
0x4000..=0x5AFF => self.page1_screen_shadow_bank(),
0xC000..=0xDAFF => self.page3_screen_shadow_bank(),
_ => return
};
let frame_cache = match maybe_shadow {
Some(false) => &mut self.ula.frame_cache,
Some(true) => &mut self.shadow_frame_cache,
None => return
};
if addr & 0x1800 != 0x1800 {
let coords = pixel_address_coords(addr);
frame_cache.update_frame_pixels(&self.ula.memory, coords, addr, ts);
}
else {
let coords = color_address_coords(addr);
frame_cache.update_frame_colors(&self.ula.memory, coords, addr, ts);
}
}
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
pub(super) fn update_frame_cache(&mut self, addr: u16, ts: VideoTs) {
let (frame_cache, memory_ref): (&mut UlaFrameCache<_>, _) = match addr {
0x4000..=0x5AFF => match self.ula.page1_screen0_shadow_bank() {
Some(false) => self.ula.frame_cache_mut_mem_ref(),
Some(true) => self.ula.shadow_frame_cache_mut_mem_ref(),
None => return
}
0x6000..=0x7AFF => match self.ula.page1_screen1_shadow_bank() {
Some(false) => (&mut self.sec_frame_cache, self.ula.memory_ref()),
Some(true) => (&mut self.shadow_sec_frame_cache, self.ula.memory_ref()),
None => return
}
0xC000..=0xDAFF => match self.ula.page3_screen0_shadow_bank() {
Some(false) => self.ula.frame_cache_mut_mem_ref(),
Some(true) => self.ula.shadow_frame_cache_mut_mem_ref(),
None => return
}
0xE000..=0xFAFF => match self.ula.page3_screen1_shadow_bank() {
Some(false) => (&mut self.sec_frame_cache, self.ula.memory_ref()),
Some(true) => (&mut self.shadow_sec_frame_cache, self.ula.memory_ref()),
None => return
}
_ => return
};
if addr & 0x1800 != 0x1800 {
let coords = pixel_address_coords(addr);
frame_cache.update_frame_pixels(memory_ref, coords, addr, ts);
}
else {
let coords = color_address_coords(addr);
frame_cache.update_frame_colors(memory_ref, coords, addr, ts);
}
}
sourcepub fn apply_snow_interference(
&mut self,
screen: &ScreenArray,
_: CellCoords,
snow: u8
)
pub fn apply_snow_interference(
&mut self,
screen: &ScreenArray,
_: CellCoords,
snow: u8
)
Caches the bitmap and attribute cell at the given coordinates with the snow
distortion applied.
Examples found in repository?
More examples
174 175 176 177 178 179 180 181 182 183 184 185 186
pub(super) fn update_snow_interference(&mut self, ts: VideoTs, ir: u16) {
if self.memory_contention().is_contended_address(ir) {
if let Some(coords) = Ula128VidFrame::snow_interference_coords(ts) {
let (screen, frame_cache) = if self.cur_screen_shadow {
(self.ula.memory.screen_ref(1).unwrap(), &mut self.shadow_frame_cache)
}
else {
(self.ula.memory.screen_ref(0).unwrap(), &mut self.ula.frame_cache)
};
frame_cache.apply_snow_interference(screen, coords, ir as u8);
}
}
}
Trait Implementations§
source§impl<V: Clone> Clone for UlaFrameCache<V>
impl<V: Clone> Clone for UlaFrameCache<V>
source§fn clone(&self) -> UlaFrameCache<V>
fn clone(&self) -> UlaFrameCache<V>
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read moresource§impl<V> Debug for UlaFrameCache<V>
impl<V> Debug for UlaFrameCache<V>
Auto Trait Implementations§
impl<V> RefUnwindSafe for UlaFrameCache<V>where
V: RefUnwindSafe,
impl<V> Send for UlaFrameCache<V>where
V: Send,
impl<V> Sync for UlaFrameCache<V>where
V: Sync,
impl<V> Unpin for UlaFrameCache<V>where
V: Unpin,
impl<V> UnwindSafe for UlaFrameCache<V>where
V: UnwindSafe,
Blanket Implementations§
§impl<T> Conv for T
impl<T> Conv for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self
to use its Binary
implementation when Debug
-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self
to use its Octal
implementation when Debug
-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
source§impl<S, T> IntoSample<S> for Twhere
S: FromSample<T>,
impl<S, T> IntoSample<S> for Twhere
S: FromSample<T>,
source§fn into_sample(self) -> S
fn into_sample(self) -> S
S
a sample type from self
.§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> Rwhere
Self: Borrow<B>,
B: 'a + ?Sized,
R: 'a,
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> Rwhere
Self: Borrow<B>,
B: 'a + ?Sized,
R: 'a,
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R
) -> Rwhere
Self: BorrowMut<B>,
B: 'a + ?Sized,
R: 'a,
fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R
) -> Rwhere
Self: BorrowMut<B>,
B: 'a + ?Sized,
R: 'a,
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> Rwhere
Self: AsRef<U>,
U: 'a + ?Sized,
R: 'a,
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> Rwhere
Self: AsRef<U>,
U: 'a + ?Sized,
R: 'a,
self
, then passes self.as_ref()
into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> Rwhere
Self: AsMut<U>,
U: 'a + ?Sized,
R: 'a,
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> Rwhere
Self: AsMut<U>,
U: 'a + ?Sized,
R: 'a,
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Selfwhere
Self: Borrow<B>,
B: ?Sized,
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Selfwhere
Self: Borrow<B>,
B: ?Sized,
Borrow<B>
of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere
Self: BorrowMut<B>,
B: ?Sized,
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere
Self: BorrowMut<B>,
B: ?Sized,
BorrowMut<B>
of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Selfwhere
Self: AsRef<R>,
R: ?Sized,
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Selfwhere
Self: AsRef<R>,
R: ?Sized,
AsRef<R>
view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere
Self: AsMut<R>,
R: ?Sized,
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere
Self: AsMut<R>,
R: ?Sized,
AsMut<R>
view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Selfwhere
Self: Deref<Target = T>,
T: ?Sized,
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Selfwhere
Self: Deref<Target = T>,
T: ?Sized,
Deref::Target
of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Selfwhere
Self: DerefMut<Target = T> + Deref,
T: ?Sized,
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Selfwhere
Self: DerefMut<Target = T> + Deref,
T: ?Sized,
Deref::Target
of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap()
only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut()
only in debug builds, and is erased in release
builds. Read more§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Selfwhere
Self: Borrow<B>,
B: ?Sized,
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Selfwhere
Self: Borrow<B>,
B: ?Sized,
.tap_borrow()
only in debug builds, and is erased in release
builds. Read more§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere
Self: BorrowMut<B>,
B: ?Sized,
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere
Self: BorrowMut<B>,
B: ?Sized,
.tap_borrow_mut()
only in debug builds, and is erased in release
builds. Read more§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Selfwhere
Self: AsRef<R>,
R: ?Sized,
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Selfwhere
Self: AsRef<R>,
R: ?Sized,
.tap_ref()
only in debug builds, and is erased in release
builds. Read more§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere
Self: AsMut<R>,
R: ?Sized,
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere
Self: AsMut<R>,
R: ?Sized,
.tap_ref_mut()
only in debug builds, and is erased in release
builds. Read more