Sophie

Sophie

distrib > Mandriva > 2010.2 > i586 > media > contrib-backports > by-pkgid > df29c83ca401d91ec9c00bfcf7fea4ea > files > 136

shedskin-0.8-2mdv2010.2.i586.rpm

#!/usr/bin/env python2
# I, Danny Milosavljevic, hereby place this file into the public domain.

import sys
import memory

# TODO actually the memory is separated into pages of 256 bytes each on a real C64.

# $0000-$00FF, 0-256 zero page (without $0 and $1).
# $0100-$01FF, 256-511 processor stack.
# $0200-$02FF, buffers.
# $0300-$03FF, 768-1023 IRQ vectors.
# $0400-$07FF, 1024-2047 default screen memory.
# $0800-$9FFF, 2048-40959 basic area.
# $A000-$BFFF, 40960-49151 BASIC ROM
# $C000-$CFFF, 49152-53247 upper RAM area.
# $D000-$DFFF, 53248-57343 I/O Area
# $D000-$DFFF, 53248-57343 character ROM
# $D000-$D3FF, 53248-54271 VIC II
# $D400-$D7FF, 54272-55295 SID
# $D800-$DBFF, 55296-56319 Color RAM (only 4 bits per byte)!
# $DC00-$DCFF, 56320-56575 CIA#1 inputs
# $DD00-$DDFF, 56576-56831 CIA#2 serial, NMI
# $DE00-$DEFF, 56832-57087 external device memory maps.
# $DF00-$DFFF, 57088-57343 external device memory maps.
# $E000-$FFFF, 57344-65535 kernal ROM!!!
# $FFFA-$FFFF, 65530-65535 hardware vectors.

class ROM(memory.Memory):
    def __init__(self, value, B_active = True):
        self.B_active = B_active
        self.memory = []
        for i in range(len(value)): # for some reason, in ShedSkin "for c in value: self.memory.append(ord(c))" doesn't work.
            c = value[i]
            v = ord(c)
            self.memory.append(v)

        #self.memory = [ord(c) for c in value]
        self.B_can_write = False # in the instance because of ShedSkin

    def read_memory(self, address, size = 1):
        if size == 1:
            return self.memory[address]
        return one_big_value(self.memory[address : address + size])

    def write_memory(self, address, value, size):
        raise NotImplementedError("cannot write to ROM")

minimal_overlay_address = 0xA000

def one_big_value(part):
    assert len(part) <= 4, "mmu.one_big_value: len(part)<=4"
    f = 0
    v = 0
    for c in part:
        v = v | (c << f)
        f += 8
    return v

class MMU(memory.Memory):
    def __init__(self):
        self.overlays = {}
        self.overlay_values = []
        self.memory = 65536 * [0]

    def set_overlay(self, name, overlay):
        self.overlays[name] = overlay
        self.overlay_values = self.overlays.values()

    def read_memory(self, address, size = 1):
        value = self.xread_memory(address, size)
        #if value is None:
        #    print("memory at address $%X broken" % address)
        #    assert(size == 1)
        #    return 0xFF
        #assert(value is not None)
        #print("memory at $%X is %r=$%X" % (address, value, value))
        return value

    def read_zero_page(self, address, size = 1):
        return self.read_memory(address, size)

    def xread_memory(self, address, size = 1):
        if address >= minimal_overlay_address or address < 2:
            for range_1, controller in self.overlay_values:
                if address >= range_1[0] and address < range_1[1] and controller.B_active:
                    return controller.read_memory(address - range_1[0], size)
        if size == 1:
            return (self.memory[address])
        assert size >= 0, "MMU.read_memory: size>=0"
        v = one_big_value(self.memory[address : address + size])
        return v

    def write_memory(self, address, value, size):
        a = address
        if address >= minimal_overlay_address or address < 2:
            for range_1, controller in self.overlay_values:
                if address >= range_1[0] and address < range_1[1] and controller.B_active and controller.B_can_write: # FIXME and hasattr(controller, "write_memory"):
                    # WTF assert(address != 0x1FC and address != 0x1FD)
                    #print(address, range_1, controller)
                    return controller.write_memory(address - range_1[0], value, size)

        assert isinstance(value, int), "MMU.write_memory: value is an integer"
        for i in range(size):
            self.memory[address + i] = value & 0xFF
            value >>= 8

    def map_ROM(self, name, address, value, B_active):
        assert address >= minimal_overlay_address, "MMU.map_ROM address >= minimal_overlay_address" # ??  or range_1[1] == 2
        ROM_1 = ROM(value, B_active)
        self.set_overlay(name, (((address, address + len(value)), ROM_1)))
        return ROM_1

    def map_IO(self, name, range_1, IO):
        assert range_1[0] >= minimal_overlay_address or range_1[1] == 2, "MMU.map_IO"
        self.set_overlay(name, (((range_1[0], range_1[1]), IO)))

    def set_overlay_active(self, name, value):
        #print("setting overlay %r to %r" % (name, value))
        self.overlays[name][1].B_active = value
        #self.overlay_values = self.overlays.values()
        #if value == False:
        #    for s in range(0xD1, 0xD1 + 4):
        #        sys.stdout.write("%02X " % (self.read_memory(s)))