/[VRac]/VRac.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /VRac.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 128 by dpavlin, Sat Aug 4 20:28:51 2007 UTC revision 211 by dpavlin, Mon Apr 14 21:26:16 2008 UTC
# Line 3  package VRac; Line 3  package VRac;
3  use warnings;  use warnings;
4  use strict;  use strict;
5    
6  use Carp qw/confess croak/;  use Carp qw/confess croak cluck carp/;
7  use File::Slurp;  use File::Slurp;
8  use Data::Dump qw/dump/;  use Data::Dump qw/dump/;
9    
# Line 12  __PACKAGE__->mk_accessors(qw(booted)); Line 12  __PACKAGE__->mk_accessors(qw(booted));
12    
13  =head1 NAME  =head1 NAME
14    
15  VRac - Virtualno Računalo  VRac - Virtualno Računalo
16    
17  =head1 VERSION  =head1 VERSION
18    
# Line 27  our $VERSION = '0.00'; Line 27  our $VERSION = '0.00';
27  Emulator of 8-bit architectures based on L<M6502> or L<Z80> emulation.  Emulator of 8-bit architectures based on L<M6502> or L<Z80> emulation.
28    
29  This project is homage to 8-bit computers in Croatia and former Yugoslavia  This project is homage to 8-bit computers in Croatia and former Yugoslavia
30  from 1980-1990. Word B<vrac> means also I<wizzard> in Croatian.  from 1980-1990. Word B<vrac> means also I<wizard> in Croatian.
31    
32    This project should enable anyone with limited knowledge of perl and 8-bit
33    arhitecture of some machine to write emulator in an afternoon. To achieve this,
34    code is written is as cleanly as possible.
35    
36    Porting existing emulators should be especially easy: you need passive
37    understaning of language in which emulator is written and you can be on your
38    way C<:-)>
39    
40  =cut  =cut
41    
# Line 49  sub run { Line 57  sub run {
57          confess "please implement $self::run\n";          confess "please implement $self::run\n";
58  }  }
59    
 =head2 jump  
60    
61  Start execution from some location (modify PC)  =head1 Memory management
62    
63    VRac implements callback for all I/O operations. This was main reason why
64    L<Acme::6502> module with tied memory was too slow to emulate L<Orao>, so I
65    had to write C binding for L<M6502>.
66    
67    B<This functions will die with stack trace when called>. They should be
68    implemented for each architecture.
69    
70    =cut
71    
72    =head2 read
73    
74    Read from memory
75    
76      $byte = read( $address );
77    
78  =cut  =cut
79    
80  sub jump {  sub read {
81          my $self = shift;          my $self = shift;
82          confess "please implement $self::jump\n";          confess "please implement $self::read()";
83  }  }
84    
85    =head2 write
86    
87    Write into emory
88    
89      write( $address, $byte );
90    
91    =cut
92    
93    sub write {
94            my $self = shift;
95            confess "please implement $self::write()";
96    }
97    
98  =head1 Helper functions  =head1 Helper functions
99    
# Line 121  sub save_dump { Line 155  sub save_dump {
155          $from ||= 0;          $from ||= 0;
156          $to ||= 0xffff;          $to ||= 0xffff;
157    
158          open(my $fh, '>', $path) || die "can't open $path: $!";          if ( open(my $fh, '>', $path) ) {
159          print $fh $self->read_chunk( $from, $to );                  print $fh $self->read_chunk( $from, $to );
160          close($fh);                  close($fh);
161    
162                    my $size = -s $path;
163                    print sprintf "saved %s %04x-%04x %d %x bytes\n", $path, $from, $to, $size, $size;
164            } else {
165                    warn "can't create $path: $!";
166            }
167    
         my $size = -s $path;  
         warn sprintf "saved %s %d %x bytes\n", $path, $size, $size;  
168  }  }
169    
170  =head2 hexdump  =head2 hexdump
# Line 152  sub hexdump { Line 190  sub hexdump {
190          );          );
191  }  }
192    
193  =head1 Memory management  =head2 append_to_file
   
 VRac implements all I/O using mmap addresses. This was main reason why  
 L<Acme::6502> was just too slow to handle it.  
   
 =cut  
   
 =head2 read  
   
 Read from memory  
194    
195    $byte = read( $address );    $self->append_to_file( '/path/to/file', $byte, $byte ... );
196    
197  =cut  =cut
198    
199  sub read {  sub append_to_file {
200          my $self = shift;          my $self = shift;
201          confess "please implement $self::read()";          my $path = shift || confess "no path?";
202  }          my $bytes = join('', @_);
   
 =head2 write  
203    
204  Write into emory          my $size = -s $path || 0;
205            my $len = length($bytes);
206    
207    write( $address, $byte );          open(my $fh, '>>', $path) || confess "can't open $path: $!";
208            print($fh $bytes);
209            my $pos = tell($fh);
210    
211            my $expected = $size + $len;
212            if ( $pos != $expected ) {
213                    #cluck "BUG: file grows too big got $pos, expected $expected !";
214                    truncate $fh, $expected;
215            }
216    
217  =cut          close($fh);
218    
219  sub write {          warn sprintf("## append_to_file('%s',%s)\n", $path, dump($bytes));
         my $self = shift;  
         confess "please implement $self::write()";  
220  }  }
221    
222  =head1 Command Line  =head1 Command Line
# Line 225  sub cli { Line 259  sub cli {
259          my $self = shift;          my $self = shift;
260          my $a = $self->cpu_PC() || confess "can't find PC";          my $a = $self->cpu_PC() || confess "can't find PC";
261          my $run_for = 0;          my $run_for = 0;
262          warn $self->dump_R() if $show_R;          print $self->dump_R() if $show_R;
263          while ( my ($line, @v) = $self->prompt( $a, $last ) ) {          while ( my ($line, @v) = $self->prompt( $a, $last ) ) {
264                  my $c = shift @v;                  my $c = shift @v;
265                  next unless defined($c);                  next unless defined($c);
# Line 238  sub cli { Line 272  sub cli {
272                  } elsif ( $c eq '?' ) {                  } elsif ( $c eq '?' ) {
273                          my $t = $self->trace ? 'on' : 'off' ;                          my $t = $self->trace ? 'on' : 'off' ;
274                          my $d = $self->debug ? 'on' : 'off' ;                          my $d = $self->debug ? 'on' : 'off' ;
275                          warn <<__USAGE__;                          print <<__USAGE__;
276  Usage:  Usage:
277    
278  x|q\t\texit  x|q\t\texit
# Line 248  j|u 1000\t\tjump (change pc) Line 282  j|u 1000\t\tjump (change pc)
282  r 42\t\trun 42 instruction opcodes  r 42\t\trun 42 instruction opcodes
283  t\t\ttrace [$t]  t\t\ttrace [$t]
284  d\t\tdebug [$d]  d\t\tdebug [$d]
285    tape name 168\tload tape and start at offset
286    
287  __USAGE__  __USAGE__
288                          warn $self->dump_R;                          print $self->tape_status if $self->can('tape_status');
289                            print $self->dump_R;
290                          $last = '';                          $last = '';
291                  } elsif ( $c =~ m/^e/i ) {                  } elsif ( $c =~ m/^e/i ) {
292                          $a = $v if defined($v);                          $a = $v if defined($v);
# Line 302  __USAGE__ Line 338  __USAGE__
338                          $show_R = 1;                          $show_R = 1;
339                          last;                          last;
340                  } elsif ( $c =~ m/^tape/ ) {                  } elsif ( $c =~ m/^tape/ ) {
341                          if ( $c =~ m/rate/ ) {                          if ( ! $v ) {
                                 $self->tape_rate( $v );  
                                 warn "will read table with rate $v\n";  
                         } elsif ( ! $v ) {  
342                                  warn "ERROR: please specify tape name!\n";                                  warn "ERROR: please specify tape name!\n";
343                          } elsif ( ! -e $v ) {                          } elsif ( ! -e $v ) {
344                                  warn "ERROR: tape $v: $!\n";                                  warn "ERROR: tape $v: $!\n";
345                          } else {                          } else {
346                                  $self->load_tape( $v );                                  $self->load_tape( $v, shift @v );
347                          }                          }
348                          $last = '';                          $last = '';
349                  } elsif ( $c =~ m/^t/i ) {                  } elsif ( $c =~ m/^t/i ) {
# Line 330  __USAGE__ Line 363  __USAGE__
363          return $run_for;          return $run_for;
364  }  }
365    
366    =head1 SEE ALSO
367    
368    Components: L<M6502>, L<Z80>, L<Screen>, L<Tape>, L<Session>
369    
370    Emulators: L<Orao>, L<Galaksija>
371    
372    L<References> about different architectures
373    
374  =head1 AUTHOR  =head1 AUTHOR
375    
376  Dobrica Pavlinusic, C<< <dpavlin@rot13.org> >>  Dobrica Pavlinusic, C<< <dpavlin@rot13.org> >>
377    
 =head1 BUGS  
   
378  =head1 ACKNOWLEDGEMENTS  =head1 ACKNOWLEDGEMENTS
379    
380    Structure and Interpretation of Computer Programs by Abelson, Sussman, and
381    Sussman L<http://mitpress.mit.edu/sicp/> is a great book. It gave me idea
382    that you should have wizard powers over your computer, even if it's 8 bit
383    one.
384    
385  =head1 COPYRIGHT & LICENSE  =head1 COPYRIGHT & LICENSE
386    
387  Copyright 2007 Dobrica Pavlinusic, All Rights Reserved.  Copyright 2007 Dobrica Pavlinusic, All Rights Reserved.

Legend:
Removed from v.128  
changed lines
  Added in v.211

  ViewVC Help
Powered by ViewVC 1.1.26