[docs]classMemory:""" Class emulating paginated memory bank. Methods: peek: Retrieve the content of a memory address. poke: Write a value to a memory address. """def__init__(self,pages:int=1):self.pages=pagesself.offset_cursor=0self.active_page=0self._offsets=65536# 64K per pageself._memory=[[0b00000000]*self._offsetsfor_inrange(self.pages)]self.terminal=Terminal()
[docs]def__str__(self)->str:"""Overload of the str() function. Returns: str: A string with the memory pages and offsets. """returnf"{self.pages} * {self._offsets}"
[docs]defget_num_memory_pages(self)->int:"""Get the number of memory pages. Returns: int: Number of memory pages. """returnself.pages
[docs]defget_num_memory_offsets(self)->int:"""Get the memory offsets. Returns: int: Memory offsets. """returnself._offsets
@dispatch(int)defpeek(self,address:int)->int:""" peek(self, address: int) -> int Retrieve the content of a memory address. Parameters: address (int): Address where to peek. Returns: int: Pointed address value. """returnself.peek(self.active_page,address)@dispatch(int,int)defpeek(self,page:int,address:int)->int:""" peek(self, page: int, address: int) -> int Retrieve the content of a memory address. Parameters: page (int): Page memory. address (int): Address where to peek. Returns: int: Pointed address value. """try:returnself._memory[page][address]except(ValueError,IndexError):self.terminal.warning_message("Memory.peek(): Invalid hexadecimal address or page.")return-1@dispatch(str,str)defpeek(self,page:str,address:str)->int:""" peek(self, page: str, address: str) -> int Retrieve the content of a memory address. Parameters: page (str): Page memory in hexadecimal. address (str): Address where to peek in hexadecimal. Returns: int: Pointed address value. """returnself.peek(int(page,16),int(address,16))@dispatch(int,int,int)defpoke(self,page:int,address:int,value:int)->bool:""" poke(self, page: int, address: int, value: int) -> bool Write a value to a memory address. Parameters: page (int): Page memory. address (int): Address where to poke. value (int): Value to set in memory. Returns: bool: Operation result. """ifnot(0<=value<=255)ornot(0<=page<len(self._memory))ornot(0<=address<self._offsets):self.terminal.warning_message(f"Memory.poke(): Invalid address or value. {page}/{len(self._memory)}:{address}/{self._offsets}, {value}")returnFalseself._memory[page][address]=valuereturnTrue@dispatch(int,int,str)defpoke(self,page:int,address:int,value:str)->bool:""" poke(self, page: int, address: int, value: str) -> bool Write a string to memory as a sequence of bytes. Parameters: page (int): Page memory. address (int): Address where to start writing. value (str): String to write as bytes. Returns: bool: Operation result. """ifnot(0<=page<len(self._memory))ornot(0<=address<self._offsets):self.terminal.warning_message(f"Memory.poke(): Invalid page/address. {page}/{len(self._memory)}:{address}/{self._offsets}")returnFalsebyte_values=value.encode("latin1")# 1 byte per char; avoids utf-8 multibyte issuesifaddress+len(byte_values)>self._offsets:self.terminal.warning_message(f"Memory.poke(): String too long for address range. {address} + {len(byte_values)} > {self._offsets}")returnFalsefori,byteinenumerate(byte_values):self._memory[page][address+i]=bytereturnTrue