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 )