CPU-Emulator-Memory

 view release on metacpan or  search on metacpan

lib/CPU/Emulator/Memory/Banked.pm  view on Meta::CPAN

            unless(exists($params{file}));
        $contents = $self->_readROM($params{file}, $size);
    } elsif($type eq 'RAM') {
        $contents = (exists($params{file}))
            ? $self->_readRAM($params{file}, $size)
            : chr(0) x $size;
    } elsif($type eq 'dynamic') {
        die("For dynamic banks you need to specify function_read and function_write\n")
            unless(exists($params{function_read}) && exists($params{function_write}));
    }
    foreach my $bank (@{$self->{overlays}}) {
        if(
            (      # does an older bank start in the middle of this one?
                $bank->{address} >= $address &&
                $bank->{address} < $address + $size
            ) || ( # does this start in the middle of an older bank?
                $address >=  $bank->{address} &&
                $address < $bank->{address} + $bank->{size}
            )
        ) { $self->unbank(address => $bank->{address}) }
    }
    push @{$self->{overlays}}, {
        address  => $address,
        size     => $size,
        type     => $type,
        (length($contents) ? (contents => $contents) : ()),
        (exists($params{file}) ? (file => $params{file}) : ()),
        (exists($params{writethrough}) ? (writethrough => $params{writethrough}) : ()),
        (exists($params{function_read}) ? (function_read => $params{function_read}) : ()),
        (exists($params{function_write}) ? (function_write => $params{function_write}) : ())
    };
}

lib/CPU/Emulator/Memory/Banked.pm  view on Meta::CPAN


This method unloads a bank of memory, making the main RAM visible
again at the affected addresses.  It takes a single named parameter
'address' to tell which bank to switch.

=cut

sub unbank {
    my($self, %params) = @_;
    die("unbank: No address specified\n") unless(exists($params{address}));
    $self->{overlays} = [
        grep { $_->{address} != $params{address} }
        @{$self->{overlays}}
    ];
}

=head2 peek

This is replaced by a version that is aware of memory banks but has the
same interface.  peek8
and peek16 are wrappers around it and so are unchanged.

=cut

sub peek {
    my($self, $addr) = @_;
    die("Address $addr out of range") if($addr< 0 || $addr > $self->{size} - 1);
    foreach my $bank (@{$self->{overlays}}) {
        if(
            $bank->{address} <= $addr &&
            $bank->{address} + $bank->{size} > $addr
        ) {
            if($bank->{type} eq 'dynamic') {
                return $bank->{function_read}->($self, $addr);
            } else {
                return ord(substr($bank->{contents}, $addr - $bank->{address}, 1));
            }
        }

lib/CPU/Emulator/Memory/Banked.pm  view on Meta::CPAN

This method is replaced by a bank-aware version with the same interface.
poke8 and poke16 are wrappers around it and so are unchanged.

=cut

sub poke {
    my($self, $addr, $value) = @_;
    die("Value $value out of range") if($value < 0 || $value > 255);
    die("Address $addr out of range") if($addr< 0 || $addr > $self->{size} - 1);
    $value = chr($value);
    foreach my $bank (@{$self->{overlays}}) {
        if(
            $bank->{address} <= $addr &&
            $bank->{address} + $bank->{size} > $addr
        ) {
            if($bank->{type} eq 'RAM') {
                substr($bank->{contents}, $addr - $bank->{address}, 1) = $value;
                $self->_writeRAM($bank->{file}, $bank->{contents})
                    if(exists($bank->{file}));
                return 1;
            } elsif($bank->{type} eq 'ROM' && $bank->{writethrough}) {

t/03-banked-memory-ROM.t  view on Meta::CPAN

$memory->bank(
    address => 0,
    type    => 'ROM',
    file    => 'romfile.rom'
);
$memory->bank(
    address => 6,
    type    => 'ROM',
    file    => 'romfile.rom'
);
ok($memory->peek(0) == 0, "Loading a new overlay starting in an older one unloads the old one ...");
ok($memory->peek(6) == ord('T'), "... and loads the new one");

$memory->bank(
    address => 6,
    type    => 'ROM',
    file    => 'romfile.rom'
);
$memory->bank(
    address => 0,
    type    => 'ROM',
    file    => 'romfile.rom'
);
ok($memory->peek(5 + length('This is a ROM')) == 0, "Loading a new overlay finishing in an older one unloads the old one ...");
ok($memory->peek(0) == ord('T'), "... and loads the new one");
ok($memory->peek16(0) == ord('T') + 256 * ord('h'), "peek16 reads from ROM too");

ok(unlink('ramfile.ram'), "ramfile.ram deleted");
ok(unlink('romfile.rom'), "romfile.rom deleted");

$memory->bank(
    address => 0,
    size => 1,
    type => 'ROM',



( run in 0.298 second using v1.01-cache-2.11-cpan-49f99fa48dc )