import { CustomMemoryType } from "../../settings" ; import { Z80Registers } from "../z80registers" ; import { BankType } from "../zsimulator/simmemory" ; export interface MemoryBank { start : number ; end : number ; name : string ; } /**
 * Class that takes care of the memory paging.
 * I.e. it defines which memory bank to slot association is used.
 *
 * Is the base class and defines:
 * 0000-FFFF: RAM
 */ export class MemoryModel { /**
     * Initialize.
     * Set decoder.
     */ public init ( ) { Z80Registers . setSlotsAndBanks ( undefined , undefined ) ; } param slots returns public getMemoryBanks ( slots ) { const pages = [ { start : 0x0000 , end : 0xFFFF , name : "RAM" } ] ; return pages ; } returns public getBankSize ( ) { return 0 ; } } /**
 * Class that takes care of the memory paging.
 * I.e. it defines which memory bank to slot association is used.
 *
 * Is the base class and defines:
 * 0000-3FFF: ROM
 * 4000-7FFF: RAM
 */ export class Zx16MemoryModel extends MemoryModel { param slots returns public getMemoryBanks ( slots ) { return [ { start : 0x0000 , end : 0x3FFF , name : "ROM" } , { start : 0x4000 , end : 0x7FFF , name : "RAM" } , { start : 0x8000 , end : 0xFFFF , name : "UNUSED" } ] ; } returns public getBankSize ( ) { return 0 ; } } /**
 * Class that takes care of the memory paging.
 * I.e. it defines which memory bank to slot association is used.
 *
 * Is the base class and defines:
 * 0000-3FFF: ROM
 * 4000-FFFF: RAM
 */ export class Zx48MemoryModel extends MemoryModel { param slots returns public getMemoryBanks ( slots ) { return [ { start : 0x0000 , end : 0x3FFF , name : "ROM" } , { start : 0x4000 , end : 0xFFFF , name : "RAM" } ] ; } returns public getBankSize ( ) { return 0 ; } } /**
 * The ZX 128k memory model:
 * 4 slots per 16k.
 * 0000-3FFF: ROM
 * 4000-7FFF: RAM
 * 8000-BFFF: RAM
 * C000-FFFF: RAM
 */ export class Zx128MemoryModel extends MemoryModel { protected countSlots : number ; protected bankSize : number ; param countSlots constructor ( countSlots = 4 ) { super ( ) ; this . countSlots = countSlots ; this . bankSize = 0x10000 / countSlots ; } /**
     * Initialize.
     * Set decoder.
     */ public init ( ) { Z80Registers . setSlotsAndBanks ( ( address , slots ) => { const slotNr = address >>> 14 ; const bank = slots [ slotNr ] + 1 ; const result = address + ( bank << 16 ) ; return result ; } , ( addr ) => { const slotIndex = ( addr >>> 14 ) & 0x03 ; return slotIndex ; } ) ; } param slots returns public getMemoryBanks ( slots ) { const pages = [ ] ; if ( slots ) { let start = 0x0000 ; let i = 0 ; slots . forEach ( bank => { const end = start + this . bankSize - 1 ; const name = ( i == 0 ) ? "ROM" + ( bank & 0x01 ) : "BANK" + bank ; pages . push ( { start , end , name } ) ; start = end + 1 ; i ++ ; } ) ; } return pages ; } returns public getBankSize ( ) { return this . bankSize ; } } /**
 * The ZX Next memory model:
 * 8 slots per 8k.
 * 0000-1FFF: RAM/ROM
 * 2000-3FFF: RAM/ROM
 * 4000-5FFF: RAM
 * 6000-7FFF: RAM
 * 8000-9FFF: RAM
 * A000-BFFF: RAM
 * C000-DFFF: RAM
 * A000-FFFF: RAM
 */ export class ZxNextMemoryModel extends Zx128MemoryModel { /**
     * Constructor.
     */ constructor ( ) { super ( 8 ) ; } /**
     * Initialize.
     * Set decoder.
     */ public init ( ) { Z80Registers . setSlotsAndBanks ( ( address , slots ) => { const slotNr = address >>> 13 ; const bank = slots [ slotNr ] + 1 ; const result = address + ( bank << 16 ) ; return result ; } , ( addr ) => { const slotIndex = ( addr >>> 13 ) & 0x07 ; return slotIndex ; } ) ; } param slots returns public getMemoryBanks ( slots ) { const pages = [ ] ; if ( slots ) { let start = 0x0000 ; slots . forEach ( bank => { const end = start + this . bankSize - 1 ; const name = ( bank >= 254 ) ? "ROM" : "BANK" + bank ; pages . push ( { start , end , name } ) ; start = end + 1 ; } ) ; } return pages ; } } /**
 * Takes the custom memory model description and creates the description of the memory banks.
 */ export class CustomMemoryModel extends MemoryModel { protected memoryBanks : MemoryBank [ ] = [ ] ; param customMemory constructor ( customMemory ) { super ( ) ; const nob = customMemory . numberOfBanks ; const bankSize = 0x10000 / nob ; let addr = 0 ; for ( let i = 0 ; i < nob ; i ++ ) { let bankName = customMemory . banks [ i . toString ( ) ] ; if ( bankName == undefined ) bankName = BankType [ BankType . UNUSED ] ; this . memoryBanks . push ( { start : addr , end : addr + bankSize - 1 , name : bankName } ) ; addr += bankSize ; } } param slots returns public getMemoryBanks ( slots ) { return this . memoryBanks ; } returns public getBankSize ( ) { return 0 ; } }