--- Orao.pm 2007/08/04 14:13:28 124 +++ Orao.pm 2007/08/04 21:04:05 132 @@ -4,11 +4,10 @@ use strict; use Carp qw/confess/; -use lib './lib'; -#use Time::HiRes qw(time); use File::Slurp; use Data::Dump qw/dump/; -use M6502; +use M6502; # import @mem $PC and friends +use Screen qw/$white $black/; use base qw(Class::Accessor VRac M6502 Screen Prefs Tape); #__PACKAGE__->mk_accessors(qw()); @@ -19,11 +18,11 @@ =head1 VERSION -Version 0.04 +Version 0.05 =cut -our $VERSION = '0.04'; +our $VERSION = '0.05'; =head1 SUMMARY @@ -33,21 +32,17 @@ =head1 FUNCTIONS -=head2 boot - -Start emulator, open L, load initial ROM images, and render memory +=head2 run - my $emu = Orao->new({}); - $emu->boot; +Start emulator, open L, load initial ROM images, and start emulator loop =cut our $emu; -select(STDERR); $| = 1; - -sub boot { +sub run { my $self = shift; + warn "Orao calling upstream init\n"; $self->SUPER::init( read => sub { $self->read( @_ ) }, @@ -58,11 +53,13 @@ warn "emulating ", $#mem, " bytes of memory\n"; +# $self->scale( 2 ); + $self->open_screen; $self->load_rom({ # 0x1000 => 'dump/SCRINV.BIN', # should be 0x6000, but oraoemu has 2 byte prefix -# 0x5FFE => 'dump/screen.dmp', +# 0x5FFE => '/home/dpavlin/orao/dump/screen.dmp', # 0xC000 => 'rom/Orao/BAS12.ROM', # 0xE000 => 'rom/Orao/CRT12.ROM', 0xC000 => 'rom/Orao/BAS13.ROM', @@ -83,7 +80,7 @@ $self->debug( 0 ); warn "rendering video memory\n"; - $self->render_vram( @mem[ 0x6000 .. 0x7fff ] ); + $self->render_vram; if ( $self->show_mem ) { @@ -116,36 +113,31 @@ M6502::reset(); - $self->booted( 1 ); -} - -=head2 run - -Run interactive emulation loop - - $emu->run; +# $self->load_tape( '../oraoigre/bdash.tap' ); -=cut + $self->loop( sub { + my $run_for = shift; + warn sprintf("about to exec from PC %04x for %d cycles\n", $PC, $run_for) if $self->trace; + M6502::exec( $run_for ); + $self->render_vram; + }); +}; -sub run { - my $self = shift; - $self->boot if ( ! $self->booted ); +=head1 Helper functions -# $self->load_tape( '../oraoigre/bdash.tap' ); +=head2 write_chunk - $self->loop; -}; +Write chunk directly into memory, updateing vram if needed -=head1 Helper functions + $emu->write_chunk( 0x1000, $chunk_data ); =cut -# write chunk directly into memory, updateing vram if needed -sub _write_chunk { +sub write_chunk { my $self = shift; my ( $addr, $chunk ) = @_; - $self->write_chunk( $addr, $chunk ); + $self->SUPER::write_chunk( $addr, $chunk ); my $end = $addr + length($chunk); my ( $f, $t ) = ( 0x6000, 0x7fff ); @@ -158,7 +150,7 @@ $t = $end if ( $end < $t ); warn sprintf("refresh video ram %04x-%04x\n", $f, $t); - $self->render_vram( @mem[ 0x6000 .. 0x7fff ] ); + $self->render_vram; $self->render_mem( @mem ) if $self->show_mem; } @@ -188,34 +180,17 @@ if ( $size == 65538 ) { $addr = 0; warn sprintf "loading oraoemu 64k dump %s at %04x - %04x %02x\n", $path, $addr, $addr+$size-1, $size; - $self->_write_chunk( $addr, substr($buff,2) ); + $self->write_chunk( $addr, substr($buff,2) ); return 1; } elsif ( $size == 32800 ) { $addr = 0; warn sprintf "loading oraoemu 1.3 dump %s at %04x - %04x %02x\n", $path, $addr, $addr+$size-1, $size; - $self->_write_chunk( $addr, substr($buff,0x20) ); + $self->write_chunk( $addr, substr($buff,0x20) ); return 1; } - printf "loading %s at %04x - %04x %02x\n", $path, $addr, $addr+$size-1, $size; - $self->_write_chunk( $addr, $buff ); - return 1; - - my $chunk; - - my $pos = 0; - - while ( my $long = substr($buff,$pos,4) ) { - my @b = split(//, $long, 4); - $chunk .= - ( $b[3] || '' ) . - ( $b[2] || '' ) . - ( $b[1] || '' ) . - ( $b[0] || '' ); - $pos += 4; - } - - $self->_write_chunk( $addr, $chunk ); + printf "loading %s at %04x - %04x %02x\n", $path, $addr, $addr+$size-1, $size; + $self->write_chunk( $addr, $buff ); return 1; }; @@ -361,6 +336,7 @@ sub read { my $self = shift; my ($addr) = @_; + return if ( $addr > 0xffff ); my $byte = $mem[$addr]; confess sprintf("can't find memory at address %04x",$addr) unless defined($byte); warn sprintf("# Orao::read(%04x) = %02x\n", $addr, $byte) if $self->trace; @@ -424,6 +400,61 @@ return; } +=head2 render_vram + +Render one frame of video ram + + $self->render_vram; + +=cut + +my @flip; + +foreach my $i ( 0 .. 255 ) { + my $t = 0; + $i & 0b00000001 and $t = $t | 0b10000000; + $i & 0b00000010 and $t = $t | 0b01000000; + $i & 0b00000100 and $t = $t | 0b00100000; + $i & 0b00001000 and $t = $t | 0b00010000; + $i & 0b00010000 and $t = $t | 0b00001000; + $i & 0b00100000 and $t = $t | 0b00000100; + $i & 0b01000000 and $t = $t | 0b00000010; + $i & 0b10000000 and $t = $t | 0b00000001; + #warn "$i = $t\n"; + $flip[$i] = $t; +} + + +sub render_vram { + my $self = shift; + + my $pixels = pack("C*", map { $flip[$_] } @mem[ 0x6000 .. 0x7fff ]); + + my $vram = SDL::Surface->new( + -width => 256, + -height => 256, + -depth => 1, # 1 bit per pixel + -pitch => 32, # bytes per line + -from => $pixels, + ); + $vram->set_colors( 0, $black, $white ); + + $self->render_frame( $vram ); +} + +=head2 cpu_PC + +=cut + +sub cpu_PC { + my ( $self, $addr ) = @_; + if ( defined($addr) ) { + $PC = $addr; + warn sprintf("running from PC %04x\n", $PC); + }; + return $PC; +} + =head1 AUTHOR Dobrica Pavlinusic, C<< >>