Games-NES-Emulator
view release on metacpan or search on metacpan
lib/Games/NES/Emulator/CPU.pm view on Meta::CPAN
package Games::NES::Emulator::CPU;
use strict;
use warnings;
use base qw( CPU::Emulator::6502 );
use Scalar::Util ();
__PACKAGE__->mk_accessors( 'context' );
=head1 NAME
Games::NES::Emulator::CPU - NES Central Processing Unit
=head1 SYNOPSIS
=head1 DESCRIPTION
=head1 METHODS
=head2 init()
=cut
sub init {
my $self = shift;
my $emu = shift;
Scalar::Util::weaken( $emu );
$self->SUPER::init( @_ );
$self->context( $emu );
$self->interrupt_line( 0 );
$self->memory( [ ( 0 ) x ( 0xFFFF + 1 ) ] );
my $reg = $self->registers;
$reg->{ pc } = 0x8000;
$reg->{ sp } = 0xFF;
$self->toggle( 1 );
$self->cycle_counter( 0 );
$self->frame_counter( 0 );
}
=head2 RAM_read( $addr )
=cut
sub RAM_read {
my( $self, $addr ) = @_;
my $c = $self->context;
my $block = $addr >> 13;
if( $block == 0 ) {
return $self->SUPER::RAM_read( $addr & 0x7FF );
}
elsif( $block == 1 ) {
my $ppu_addr = ( $addr & 0x7 ) + 0x2000;
my $ppu = $c->ppu;
my $reg = $ppu->registers;
if( $ppu_addr == 0x2002 ) {
$self->toggle( 1 );
my $val = $reg->{ status };
$reg->{ status } &= 0x7f;
return $val;
}
elsif( $ppu_addr == 0x2007 ) {
return $ppu->VRAM->read( $reg->{ VRAM_addr }, 1 );
}
}
elsif( $block == 2 ) {
if( ( $addr & 0x3F40 ) == 0 ) {
if( $addr == 0x4016 ) {
return $c->inputs->[ 0 ]->poll;
}
elsif( $addr == 0x4017 ) {
return $c->inputs->[ 1 ]->poll;
}
return $c->apu->read( $addr );
}
return $c->mapper->read( $addr );
}
elsif( $block == 3 ) {
return $self->SUPER::RAM_read( $addr );
}
( run in 2.133 seconds using v1.01-cache-2.11-cpan-5a3173703d6 )