pub trait ZxMemory {
    const ROM_SIZE: usize;
    const RAMTOP: u16;
    const PAGES_MAX: u8;
    const SCR_BANKS_MAX: usize;
    const ROM_BANKS_MAX: usize;
    const RAM_BANKS_MAX: usize;
    const PAGE_SIZE: usize = 16_384usize;
Show 35 methods fn reset(&mut self); fn read(&self, addr: u16) -> u8; fn read16(&self, addr: u16) -> u16; fn read_screen(&self, screen_bank: usize, addr: u16) -> u8; fn write(&mut self, addr: u16, val: u8); fn write16(&mut self, addr: u16, val: u16); fn mem_ref(&self) -> &[u8] ; fn mem_mut(&mut self) -> &mut [u8] ; fn screen_ref(&self, screen_bank: usize) -> Result<&ScreenArray>; fn screen_mut(&mut self, screen_bank: usize) -> Result<&mut ScreenArray>; fn page_kind(&self, page: u8) -> Result<MemoryKind>; fn page_bank(&self, page: u8) -> Result<(MemoryKind, usize)>; fn page_ref(&self, page: u8) -> Result<&[u8]>; fn page_mut(&mut self, page: u8) -> Result<&mut [u8]>; fn rom_bank_ref(&self, rom_bank: usize) -> Result<&[u8]>; fn rom_bank_mut(&mut self, rom_bank: usize) -> Result<&mut [u8]>; fn ram_bank_ref(&self, ram_bank: usize) -> Result<&[u8]>; fn ram_bank_mut(&mut self, ram_bank: usize) -> Result<&mut [u8]>; fn map_rom_bank(&mut self, rom_bank: usize, page: u8) -> Result<()>; fn map_ram_bank(&mut self, ram_bank: usize, page: u8) -> Result<()>; fn map_exrom(&mut self, _exrom_bank: ExRom, _page: u8) -> Result<()> { ... } fn unmap_exrom(&mut self, _exrom_bank: &ExRom) { ... } fn is_exrom_at(&self, _page: u8) -> bool { ... } fn has_mapped_exrom(&self, _exrom_bank: &ExRom) -> bool { ... } fn page_index_at(&self, address: u16) -> Result<MemPageOffset> { ... } fn rom_ref(&self) -> &[u8] { ... } fn rom_mut(&mut self) -> &mut [u8] { ... } fn ram_ref(&self) -> &[u8] { ... } fn ram_mut(&mut self) -> &mut [u8] { ... } fn load_into_rom<R: Read>(&mut self, rd: R) -> Result<()> { ... } fn load_into_rom_bank<R: Read>(
        &mut self,
        rom_bank: usize,
        rd: R
    ) -> Result<()> { ... } fn iter_pages<A: RangeBounds<u16>>(
        &self,
        address_range: A
    ) -> Result<MemPageRefIter<'_, Self>> { ... } fn for_each_page_mut<A: RangeBounds<u16>, F>(
        &mut self,
        address_range: A,
        f: F
    ) -> Result<()>
    where
        for<'a> F: FnMut(PageMutSlice<'a>) -> Result<()>
, { ... } fn load_into_mem<A: RangeBounds<u16>, R: Read>(
        &mut self,
        address_range: A,
        rd: R
    ) -> Result<()> { ... } fn fill_mem<R, F>(&mut self, address_range: R, f: F) -> Result<()>
    where
        R: RangeBounds<u16>,
        F: FnMut() -> u8
, { ... }
}
Expand description

A trait for interfacing ZX Spectrum’s various memory types.

Required Associated Constants§

The size of the whole ROM, not just one bank.

The last available memory address.

A maximum value allowed for a page argument.

A maximum value allowed for a screen_bank argument

A maximum value allowed for a rom_bank argument

A maximum value allowed for a ram_bank argument

Provided Associated Constants§

This is just a hint. Actual page sizes may vary.

Required Methods§

Resets memory banks.

If addr is above RAMTOP the function should return std::u8::MAX.

If addr is above RAMTOP the function should return std::u16::MAX.

Reads a byte from screen memory at the given addr.

The screen banks are different from memory banks. E.g. for Spectrum 128k then screen bank 0 resides in a memory bank 5 and screen bank 1 resides in a memory bank 7. For 16k/48k Spectrum, there is only one screen bank: 0.

addr is in screen address space (0 addresses the first byte of screen memory).

Panics

If addr is above the upper limit of screen memory address space the function should panic. If screen_bank doesn’t exist the function should also panic.

If addr is above RAMTOP the function should do nothing.

If addr is above RAMTOP the function should do nothing.

Provides a continuous view into the whole memory (all banks: ROM + RAM).

Provides a continuous view into the whole memory (all banks: ROM + RAM).

Returns a reference to the screen memory.

See ZxMemory::read_screen for an explanation of screen_bank argument.

Returns a mutable reference to the screen memory.

See ZxMemory::read_screen for an explanation of screen_bank argument.

Returns an enum describing what kind of memory is currently paged at the specified page.

If an EX-ROM bank is currently mapped at the specified page a MemoryKind::Rom will be returned in this instance.

page should be less or equal to PAGES_MAX.

Returns a tuple of an enum describing what kind of memory and which bank of that memory is currently paged at the specified page.

Note

Unlike ZxMemory::page_kind this method ignores if an EX-ROM bank is currently mapped at the specified page. In this instance, the returned value corresponds to a memory bank that would be mapped at the page if the EX-ROM bank wasn’t mapped.

page should be less or equal to PAGES_MAX.

page should be less or equal to PAGES_MAX.

page should be less or equal to PAGES_MAX.

rom_bank should be less or equal to ROM_BANKS_MAX.

rom_bank should be less or equal to ROM_BANKS_MAX.

ram_bank should be less or equal to RAM_BANKS_MAX.

ram_bank should be less or equal to RAM_BANKS_MAX.

rom_bank should be less or equal to ROM_BANKS_MAX and page should be less or equal to PAGES_MAX.

ram_bank should be less or equal to RAM_BANKS_MAX and page should be less or equal to PAGES_MAX.

Provided Methods§

Maps EX-ROM bank at the specified page.

exrom_bank should be one of the attachable EX-ROMS and page should be less or equal to PAGES_MAX.

Only one EX-ROM can be mapped at the same time. If an EX-ROM bank is already mapped when calling this function it will be unmapped first, regardless of the page, the previous EX-ROM bank has been mapped at.

Not all types of memory support attaching external ROMs.

Unmaps an external ROM if the currently mapped EX-ROM bank is the same as in the argument. Otherwise does nothing.

Returns true if an EX-ROM bank is currently being mapped at the specified memory page.

Returns true if a specified EX-ROM bank is currently being mapped.

Returns Ok(MemPageOffset) if address is equal to or less than ZxMemory::RAMTOP.

Examples found in repository?
src/memory.rs (line 361)
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
    fn next(&mut self) -> Option<Self::Item> {
        let cursor = self.cursor;
        let end = self.end;
        if cursor < end {
            let MemPageOffset { index, offset, .. } = self.mem.page_index_at(cursor as u16).unwrap();
            let offset = offset as usize;
            let page = self.mem.page_ref(index).unwrap();
            let read_len = end - cursor;
            let read_end = page.len().min(offset + read_len);
            let read_page = &page[offset..read_end];
            self.cursor += read_page.len();
            Some(read_page)
        }
        else {
            None
        }
    }
}

struct MemPageMutIter<'a, Z: ?Sized> {
    mem: &'a mut Z,
    cursor: usize,
    end: usize
}

impl<'a, Z: ZxMemory + ?Sized> Iterator for MemPageMutIter<'a, Z> {
    type Item = PageMutSlice<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        let cursor = self.cursor;
        let end = self.end;
        if cursor < end {
            let MemPageOffset { kind, index, offset } = self.mem.page_index_at(cursor as u16).unwrap();
            let offset = offset as usize;
            let page = self.mem.page_mut(index).unwrap();
            // this may lead to yielding pages that view the same memory bank slices;
            // so this struct isn't public, and it's only used internally when no
            // two iterated pages are allowed to be accessed at once.
            let page = unsafe { core::mem::transmute::<&mut[u8], &'a mut[u8]>(page) };
            let read_len = end - cursor;
            let read_end = page.len().min(offset + read_len);
            let read_page = &mut page[offset..read_end];
            self.cursor += read_page.len();
            match kind {
                MemoryKind::Rom => {
                    Some(PageMutSlice::Rom(read_page))
                },
                MemoryKind::Ram => {
                    Some(PageMutSlice::Ram(read_page))
                }
            }
        }
        else {
            None
        }
    }

Provides a continuous view into the ROM memory (all banks).

Provides a continuous mutable view into the ROM memory (all banks).

Examples found in repository?
src/memory.rs (line 276)
275
276
277
278
    fn load_into_rom<R: Read>(&mut self, mut rd: R) -> Result<()> {
        let slice = self.rom_mut();
        rd.read_exact(slice).map_err(ZxMemoryError::Io)
    }

Provides a continuous view into RAM (all banks).

Provides a continuous mutable view into RAM (all banks).

The data read depends on how big ROM is ZxMemory::ROM_SIZE. Results in an error when the ROM data size is less than the ROM_SIZE.

Results in an error when the ROM data size is less than the ROM bank’s size.

Returns an iterator of memory page slice references intersecting with a given address range.

Errors

May return an ZxMemoryError::UnsupportedAddressRange error.

Iterates over mutable memory page slices PageMutSlice intersecting with a given address range passing the slices to the closure f.

Errors

May return an ZxMemoryError::UnsupportedAddressRange error or an error returned by the provided closure.

Examples found in repository?
src/memory.rs (lines 322-328)
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
    fn load_into_mem<A: RangeBounds<u16>, R: Read>(&mut self, address_range: A, mut rd: R) -> Result<()> {
        self.for_each_page_mut(address_range, |page| {
            match page {
                PageMutSlice::Rom(slice)|PageMutSlice::Ram(slice) => {
                    rd.read_exact(slice).map_err(ZxMemoryError::Io)
                }
            }
        })
    }
    /// Fills currently paged-in pages with the data produced by the closure F.
    ///
    /// Useful to fill RAM with random bytes.
    ///
    /// Provide the address range.
    ///
    /// *NOTE*: this will overwrite both ROM and RAM locations.
    fn fill_mem<R, F>(&mut self, address_range: R, mut f: F) -> Result<()>
    where R: RangeBounds<u16>, F: FnMut() -> u8
    {
        self.for_each_page_mut(address_range, |page| {
            for p in page.into_mut_slice().iter_mut() {
                *p = f()
            }
            Ok(())
        })
    }

Reads data into a paged-in memory area at the given address range.

Fills currently paged-in pages with the data produced by the closure F.

Useful to fill RAM with random bytes.

Provide the address range.

NOTE: this will overwrite both ROM and RAM locations.

Implementors§