--- M6502/M6502.pm 2007/08/01 22:25:37 86 +++ M6502/M6502.pm 2007/08/02 12:49:19 92 @@ -15,9 +15,11 @@ M6502 - perl bindings for M6502 CPU emulator +=head1 FUNCTIONS + =cut -my $debug = 1; +our $debug = 0; our @mem = (0xff) x 0x10000; # 64M @@ -37,47 +39,43 @@ # Exec6502 cycles our $run_for = 0; -=head1 FUNCTIONS - =head2 init -Called before C - -=cut - -sub init { - my $self = shift; - warn "inside init low-level M6502 from $self\n"; -}; - -=head2 read - -Read from memory +Setup read and write memory hooks (to implement memory mapped devices) - $byte = read( $address ); + $init->( + read => sub { + return $mem[$_[0]]; + }, + write => sub { + $mem[$_[0]] = $_[1]; + }, + ); =cut -sub read { - my ($addr) = @_; - my $byte = $mem[$addr]; - warn "## M6502::read(",dump(@_),") = ",dump( $byte ),"\n" if $debug; - return $byte; -} - -=head2 write +our $_rw_hooks = { + read => sub { + warn sprintf("# callback read(%04x) not implemented", @_) if $debug; + return $mem[$_[0]]; + }, + write => sub { + warn sprintf("# callback write(%04x,%02x) not implemented", @_) if $debug; + $mem[$_[0]] = $_[1]; + }, +}; -Write into emory +sub init { + my $self = shift; + my $args = {@_}; + warn "inside init low-level M6502 from ",ref($self),"\n"; - write( $address, $byte ); + foreach my $p ( qw/read write/ ) { + confess "need $p argument as coderef" unless ( $args->{$p} && ref($args->{$p}) eq 'CODE' ); + $_rw_hooks->{$p} = $args->{$p}; + } -=cut - -sub write { - warn "## M6502::write(",dump(@_),")\n" if $debug; - my ($addr,$byte) = @_; - $mem[$addr] = $byte; -} +}; =head2 poke_code @@ -94,7 +92,7 @@ warn sprintf("## M6502::poke_code(%04x,%s)\n", $addr, dump( @_ )) if $self->debug; #$mem[$addr++] = $_ foreach @_; # call low-level write - Arch::write($addr++, $_) foreach @_; + $_rw_hooks->{write}->( $addr++, $_ ) foreach @_; } =head2 ram @@ -137,14 +135,42 @@ return 1; } -=head2 push_R +=head1 XS Callbacks + +This functions are called from C + +=head2 _read -called by C to push changes in registars back to perl variables +Read from memory C callback + + $byte = M6502::_read( $address ); + +=cut + +sub _read { + return $_rw_hooks->{read}->( @_ ); +} + +=head2 _write + +Write into memory C callback + + M6502:_write( $address, $byte ); + +=cut + +sub _write { + return $_rw_hooks->{write}->( @_ ); +} + +=head2 _update_perl_R + +called by C to push changes in registars back to perl variables =cut -sub push_R { - warn "## M6502::push_R(",dump(@_),")\n" if $debug; +sub _update_perl_R { + warn "## M6502::update_perl_R(",dump(@_),")\n" if $debug; ( $A, $P, $X, $Y, $S, $PC, $IPeriod, $ICount, $IRequest, $IAutoReset, $TrapBadOps, $Trap, $Trace ) = @_; dump_R(); } @@ -167,6 +193,27 @@ return $dump; } +=head2 debug + +Turn perl and C-level debugging on/off + + $emu->debug( 0 ); + $emu->debug( 1 ); + print $emu->debug; + +=cut + +sub debug { + my $self = shift; + my $value = shift; + if (defined($value)) { + $debug = M6502::set_debug($value); + } else { + $debug = M6502::get_debug(); + } + return $debug; +} + =head1 SEE ALSO L is sample implementation using this module