$surface->pixel is slow + audio data chunks

[email protected] ("Brian Cassidy")
Newsgroups perl.sdl.devel
Message-ID <[email protected]>
Hey All,

I've writing a little 8088 Corruption player [1] w/ SDL_Perl but I've
come across a few issues.

The data format is very much like an ANSI file where there's a
background color then a char on top of in another color. each
character in an 8x8 block needs to be checked against the bit mask of
the font to see if it writes a fg color to the screen or not.

I've attached my program + a required font data file to this message.
you can grab the original movie data file (8088_COR.DAT) from the
original zip [2].

You can see the section commented out in my program that does the fg
color calculations. Things slow to a crawl once you uncomment that
section.

If anyone has any ideas on how to speed this up, I'd love to hear them.

My other question is that I can't for the life of me figure out how to
play the audio frame portion ($abuffer in the program) -- is it even
possible to play raw audio from a variable with SDL_Perl?

-Brian

[1] http://www.oldskool.org/pc/8088_Corruption
[2] http://www.oldskool.org/pc/8088_Corruption/8088_cor.zip
8088_player.pl (application/x-perl, 3.3 KB)
use strict;
use warnings;

use SDL;
use SDL::App;
use SDL::Event;
use SDL::Mixer;
use IO::File;

my $VIDEO_FRAME_WIDTH  = 40;
my $VIDEO_FRAME_HEIGHT = 25;
my $VIDEO_FRAME_SIZE   = $VIDEO_FRAME_WIDTH * $VIDEO_FRAME_HEIGHT * 2;
my $AUDIO_FRAME_SIZE   = 735;
my $TOTAL_FRAME_SIZE   = $VIDEO_FRAME_SIZE + $AUDIO_FRAME_SIZE;
my $FPS                = 1000 / 30;

my @palette = (
    0x000000, 0x0000AA, 0x00AA00, 0x00AAAA,
    0xAA0000, 0xAA00AA, 0xAA5500, 0xAAAAAA,
    0x555555, 0x5555FF, 0x55FF55, 0x55FFFF,
    0xFF5555, 0xFF55FF, 0xFFFF55, 0xFFFFFF
);

my $dat = $ARGV[ 0 ] || die 'No data file specified';
die 'File not found' unless -e $dat;

my $filesize = -s $dat;
die 'Invalid file size' unless $filesize % $TOTAL_FRAME_SIZE == 0;

my $frames = $filesize / $TOTAL_FRAME_SIZE;

my $app = SDL::App->new(
    -height => $VIDEO_FRAME_HEIGHT * 8,
    -width  => $VIDEO_FRAME_WIDTH * 8,
    -depth  => 32,
    -title  => '8088 Corruption Player',
    -flags  => SDL_SWSURFACE,
);

my @colors = map {
    SDL::Color->new(
        -r => ( $_ & 0xFF0000 ) >> 16,
        -g => ( $_ & 0x00FF00 ) >> 8,
        -b => ( $_ & 0x0000FF )
    )
} @palette;

my @font = unpack( 'C*', do { my $font = IO::File->new( 'CGA_FONT.8X8' ); local $/; <$font> } );

my( $done, $paused );
my $event = SDL::Event->new;
my $file  = IO::File->new( $dat );

while( !$file->eof and !$done ) {
    if( $event->poll ) {
        $done = 1 if $event->type eq SDL_QUIT;
        if( $event->type eq SDL_KEYDOWN ) {
            if( $event->key_sym eq SDLK_ESCAPE ) {
                $done = 1;
                next;
            }
        }
        elsif( $event->type eq SDL_KEYUP ) {
            my $sym = $event->key_sym;
            if( $sym eq SDLK_SPACE ) {
                $paused = !$paused;
                next;
            }
            elsif( grep { $sym eq $_ } (
                SDLK_0, SDLK_1, SDLK_2, SDLK_3, SDLK_4,
                SDLK_5, SDLK_6, SDLK_7, SDLK_8, SDLK_9
            ) ) {
                $file->seek( int( ( $frames * ( $sym - SDLK_0 ) / 10 ) ) * $TOTAL_FRAME_SIZE, 0 );
            }
        }
    }

    next if $paused;

    $app->delay( $FPS );

    my( $vbuffer, $abuffer );
    $file->read( $vbuffer, $VIDEO_FRAME_SIZE );
    $file->read( $abuffer, $AUDIO_FRAME_SIZE );

    $app->lock if $app->lockp;
    render_frame( $app, $vbuffer );
    $app->unlock if $app->lockp;
    $app->sync;
}

$file->close;

sub render_frame {
    my( $app, $buffer ) = @_;
    my @frame     = unpack( 'C*', $buffer );
    my $frame_idx = 0;

    for my $y ( 0..$VIDEO_FRAME_HEIGHT - 1 ) {
        for my $x ( 0..$VIDEO_FRAME_WIDTH - 1 ) {
            my( $idx, $attr ) = @frame[ $frame_idx++..$frame_idx++ ];

            my $scale_x = $x * 8;
            my $scale_y = $y * 8;
            $app->fill(
                SDL::Rect->new( -x => $scale_x, -y => $scale_y, -width => 8, -height => 8 ),
                $colors[ $attr >> 4 ]
            );

            my $fg    = $colors[ $attr & 0x0F ];
            my $start = $idx * 8;

=pod

            for my $fy ( 0..8 ) {
                my $mask = 0x80;
                my $bit  = $font[ $start + $fy ];
                for my $fx ( 0..8  ) {
                    $app->pixel( $scale_x + $fx, $scale_y + $fy, $fg ) if $bit & $mask;
                    $mask >>= 1;
                }
            }

=cut

        }
    }

}
CGA_FONT.8X8 (application/octet-stream, 2 KB) - not displayed
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.