from cpu6502 import *


class CPUC64(CPU6502):

   def __init__(self):
       super().__init__()
       self.screen = 0x400
       # Name und Beschreibung fuer Programmoptionen
       self.progname = 'cpuC64.py'
       self.progdesc = '6502 CPU Emulator with C64 extensions'
       # Kernal-Routinen vor dem Einrichten der (erweiterten)
       # Zeropage laden, weil auf die Symboltabelle der
       # Kernal-Routinen zugegriffen wird.
       self._kernal()
       self._zeropage()

   def _zeropage(self):
       """ Zeropage (inkl. erweiterte ZP) anlegen """
       # $99: aktuelles Eingabegeraet
       # 0: Tastatur
       # 1: Datasette
       # 2: RS232
       # 3: Monitor
       # 4-7: Drucker usw.
       # ab 8: Diskettenlaufwerke, Festplatten
       self.mem[self.labels['inp_device']] = 0
       # $c6: Zeichenanzahl im Tastaturpuffer
       self.mem[self.labels['chars_in_keyb_buf']] = 0

   def _kernal(self):
       """ Laden der Kernal-Routinen """
       self.load('c64kernal.prg')
       self.loadsym('c64kernal.lst')

   def _scrcode2ascii(self, val):
       """ Wandelt den Bildschirmcode in ein ASCII-Zeichen um
           und liefert es zurueck. Wenn der Bildschirmcode invers
           ist (>= 128) wird das Zeichen durch die Terminal-Codes
           zum Invertieren eingeschlossen.
       """
       # Invertiertes Zeichen
       inv = (val >= 128)
       if inv:
           val = val & 127
       # Grossbuchstaben
       if val <= 31:
           ch = chr(val+64)
       # Ziffern und Satzzeichen
       elif (val >= 32) and (val <= 63):
           ch = chr(val)
       # Kleinbuchstaben
       elif (val >= 64) and (val <= 95):
           ch = chr(val+32)
       else:
           ch = '?'
       # Terminalcode zur Invertierung
       if inv:
           return chr(27)+"[7m"+ch+chr(27)+"[m"
       else:
           return ch

   def _ascii2scrcode(self, ch):
       """ Wandelt das ASCII-Zeichen in einen Bildschirmcode um
           und liefert diesen zurueck.
       """
       val = ord(ch)
       # Steuercodes
       if val < 32:
           val = 63 # -> Fragezeichen
       # Satzzeichen und Ziffern (keine Umwandlung)
       elif (val >= 32) and (val <= 63):
           pass
       # Grossbuchstaben
       elif (val >= 64) and (val <= 95):
           val = val - 64
       # Kleinbuchstaben
       elif (val >= 96) and (val <= 127):
           val = val - 32
       return val

   def print_screen(self):
       """ Gibt den Bildschirmspeicher in der Konsole aus """
       adr = self.screen
       print("+----------------------------------------+")
       for row in range(25):
           print("|", end='')
           for col in range(40):
               val = self.mem[adr + col]
               print(self._scrcode2ascii(val), end='')
           print("|")
           adr += 40
       print("+----------------------------------------+")

   def set_keyb_buf(self, s):
       """ Setzt den Inhalt des Tastaturpuffers (max. 10 Zeichen);
           falls die Anzahl der Zeichen zu hoch ist, wird ein
           ValueError ausgeloest.
       """
       if len(s) > 10:
           raise ValueError("Parameter hat mehr als 10 Zeichen")
       i = 0
       for c in s:
           self.mem[self.labels['keyb_buf'] + i] = ord(c)
           i += 1
       self.mem[self.labels['chars_in_keyb_buf']] = i

   def getargs(self):
       """ Verarbeitet die Parameter aus dem Programmaufruf
       """
       super().getargs()
       self.parser.add_argument("--screen", action='store_true',
                               help="print screen")
#         print(self.parser)
#         self.args = self.parser.parse_args()

   def executeargs(self):
       """ Fuehrt die beim Programm uebergebenen Argumente aus
       """
       super().executeargs()
       if self.args.screen:
           self.print_screen()


if __name__ == "__main__":

   cpu = CPUC64()
   cpu.getargs()
   cpu.parseargs()
   cpu.executeargs()