--- VRac.pm 2007/08/04 20:28:51 128 +++ VRac.pm 2007/08/06 09:20:20 169 @@ -3,7 +3,7 @@ use warnings; use strict; -use Carp qw/confess croak/; +use Carp qw/confess croak cluck carp/; use File::Slurp; use Data::Dump qw/dump/; @@ -12,7 +12,7 @@ =head1 NAME -VRac - Virtualno Računalo +VRac - Virtualno Računalo =head1 VERSION @@ -27,7 +27,15 @@ Emulator of 8-bit architectures based on L or L emulation. This project is homage to 8-bit computers in Croatia and former Yugoslavia -from 1980-1990. Word B means also I in Croatian. +from 1980-1990. Word B means also I in Croatian. + +This project should enable anyone with limited knowledge of perl and 8-bit +arhitecture of some machine to write emulator in an afternoon. To achieve this, +code is written is as cleanly as possible. + +Porting existing emulators should be especially easy: you need passive +understaning of language in which emulator is written and you can be on your +way C<:-)> =cut @@ -49,17 +57,43 @@ confess "please implement $self::run\n"; } -=head2 jump -Start execution from some location (modify PC) +=head1 Memory management + +VRac implements callback for all I/O operations. This was main reason why +L module with tied memory was too slow to emulate L, so I +had to write C binding for L. + +B. They should be +implemented for each architecture. + +=cut + +=head2 read + +Read from memory + + $byte = read( $address ); =cut -sub jump { +sub read { my $self = shift; - confess "please implement $self::jump\n"; + confess "please implement $self::read()"; } +=head2 write + +Write into emory + + write( $address, $byte ); + +=cut + +sub write { + my $self = shift; + confess "please implement $self::write()"; +} =head1 Helper functions @@ -121,12 +155,16 @@ $from ||= 0; $to ||= 0xffff; - open(my $fh, '>', $path) || die "can't open $path: $!"; - print $fh $self->read_chunk( $from, $to ); - close($fh); + if ( open(my $fh, '>', $path) ) { + print $fh $self->read_chunk( $from, $to ); + close($fh); + + my $size = -s $path; + print sprintf "saved %s %04x-%04x %d %x bytes\n", $path, $from, $to, $size, $size; + } else { + warn "can't create $path: $!"; + } - my $size = -s $path; - warn sprintf "saved %s %d %x bytes\n", $path, $size, $size; } =head2 hexdump @@ -152,37 +190,33 @@ ); } -=head1 Memory management - -VRac implements all I/O using mmap addresses. This was main reason why -L was just too slow to handle it. - -=cut - -=head2 read - -Read from memory +=head2 append_to_file - $byte = read( $address ); + $self->append_to_file( '/path/to/file', $byte, $byte ... ); =cut -sub read { +sub append_to_file { my $self = shift; - confess "please implement $self::read()"; -} - -=head2 write + my $path = shift || confess "no path?"; + my $bytes = join('', @_); -Write into emory + my $size = -s $path || 0; + my $len = length($bytes); - write( $address, $byte ); + open(my $fh, '>>', $path) || confess "can't open $path: $!"; + print($fh $bytes); + my $pos = tell($fh); + + my $expected = $size + $len; + if ( $pos != $expected ) { + #cluck "BUG: file grows too big got $pos, expected $expected !"; + truncate $fh, $expected; + } -=cut + close($fh); -sub write { - my $self = shift; - confess "please implement $self::write()"; + warn sprintf("## append_to_file('%s',%s)\n", $path, dump($bytes)); } =head1 Command Line @@ -225,7 +259,7 @@ my $self = shift; my $a = $self->cpu_PC() || confess "can't find PC"; my $run_for = 0; - warn $self->dump_R() if $show_R; + print $self->dump_R() if $show_R; while ( my ($line, @v) = $self->prompt( $a, $last ) ) { my $c = shift @v; next unless defined($c); @@ -238,7 +272,7 @@ } elsif ( $c eq '?' ) { my $t = $self->trace ? 'on' : 'off' ; my $d = $self->debug ? 'on' : 'off' ; - warn <<__USAGE__; + <<__USAGE__; Usage: x|q\t\texit @@ -250,7 +284,8 @@ d\t\tdebug [$d] __USAGE__ - warn $self->dump_R; + print $self->tape_status if $self->can('tape_status'); + print $self->dump_R; $last = ''; } elsif ( $c =~ m/^e/i ) { $a = $v if defined($v); @@ -302,10 +337,7 @@ $show_R = 1; last; } elsif ( $c =~ m/^tape/ ) { - if ( $c =~ m/rate/ ) { - $self->tape_rate( $v ); - warn "will read table with rate $v\n"; - } elsif ( ! $v ) { + if ( ! $v ) { warn "ERROR: please specify tape name!\n"; } elsif ( ! -e $v ) { warn "ERROR: tape $v: $!\n"; @@ -330,14 +362,25 @@ return $run_for; } +=head1 SEE ALSO + +Components: L, L, L, L, L + +Emulators: L, L + +L about different architectures + =head1 AUTHOR Dobrica Pavlinusic, C<< >> -=head1 BUGS - =head1 ACKNOWLEDGEMENTS +Structure and Interpretation of Computer Programs by Abelson, Sussman, and +Sussman L is a great book. It gave me idea +that you should have wizard powers over your computer, even if it's 8 bit +one. + =head1 COPYRIGHT & LICENSE Copyright 2007 Dobrica Pavlinusic, All Rights Reserved.