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 )