Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Started on Games::Neverhood::Video

  • Loading branch information...
commit 40b7e94e6dd0eca14fa7388e7777e463fdfbf972 1 parent 1fd9b1d
@Blaizer authored
View
54 lib/Games/Neverhood/Image.xs
@@ -39,56 +39,56 @@ typedef struct {
Uint32 data_offset;
} NHC_IMG_Frame_Header;
-void NHC_IMG_Read_Palette(SDL_RWops* src, SDL_Surface* surface) {
+void NHC_IMG_Read_Palette(SDL_RWops* file, SDL_Surface* surface) {
SDL_Color palette[256];
- SDL_RWread(src, palette, 1024, 1);
+ SDL_RWread(file, palette, 1024, 1);
SDL_SetPalette(surface, SDL_LOGPAL, palette, 0, 256);
}
-void NHC_IMG_Read_Runs(SDL_RWops* src, SDL_Surface* surface) {
+void NHC_IMG_Read_Runs(SDL_RWops* file, SDL_Surface* surface) {
int ypos = 0;
Uint8* pixels = surface->pixels;
for(;;) {
Uint16 rows, cols;
- SDL_RWread(src, &rows, 2, 1);
- SDL_RWread(src, &cols, 2, 1);
+ SDL_RWread(file, &rows, 2, 1);
+ SDL_RWread(file, &cols, 2, 1);
if(!rows && !cols) break;
int i, j;
for(i = 0; i < rows; i++) {
for(j = 0; j < cols; j++) {
Uint16 xpos, fragment_len;
- SDL_RWread(src, &xpos, 2, 1);
- SDL_RWread(src, &fragment_len, 2, 1);
+ SDL_RWread(file, &xpos, 2, 1);
+ SDL_RWread(file, &fragment_len, 2, 1);
- SDL_RWread(src, pixels + ypos + xpos, fragment_len, 1);
+ SDL_RWread(file, pixels + ypos + xpos, fragment_len, 1);
}
ypos += surface->pitch;
}
}
}
-SDL_Surface* NHC_IMG_Load_Image(SDL_RWops* src) {
+SDL_Surface* NHC_IMG_Load_Image(SDL_RWops* file) {
NHC_IMG_Image_Header header;
- SDL_RWread(src, &header, 6, 1);
+ SDL_RWread(file, &header, 6, 1);
SDL_Surface* surface = SDL_CreateRGBSurface(SDL_SWSURFACE, header.width, header.height, 8, 0, 0, 0, 0);
if(header.format & 0x8) {
// palette
- NHC_IMG_Read_Palette(src, surface);
+ NHC_IMG_Read_Palette(file, surface);
}
if(header.format & 0x4) {
// unknown
- SDL_RWseek(src, 4, SEEK_CUR);
+ SDL_RWseek(file, 4, SEEK_CUR);
}
SDL_LockSurface(surface);
if(header.format & 0x1) {
// compressed
- NHC_IMG_Read_Runs(src, surface);
+ NHC_IMG_Read_Runs(file, surface);
}
else {
// uncompressed
@@ -96,7 +96,7 @@ SDL_Surface* NHC_IMG_Load_Image(SDL_RWops* src) {
int surface_len = header.height * surface->pitch;
int ypos;
for(ypos = 0; ypos < surface_len; ypos += surface->pitch) {
- SDL_RWread(src, pixels + ypos, header.width, 1);
+ SDL_RWread(file, pixels + ypos, header.width, 1);
}
}
SDL_UnlockSurface(surface);
@@ -104,45 +104,45 @@ SDL_Surface* NHC_IMG_Load_Image(SDL_RWops* src) {
return surface;
}
-SDL_Surface* NHC_IMG_Load_Sequence(SDL_RWops* src, int frame) {
+SDL_Surface* NHC_IMG_Load_Sequence(SDL_RWops* file, int frame) {
NHC_IMG_Sequence_Header header;
- SDL_RWread(src, &header, 20, 1);
+ SDL_RWread(file, &header, 20, 1);
if(header.format == 2) {
// unknown
- SDL_RWseek(src, 8, SEEK_CUR);
+ SDL_RWseek(file, 8, SEEK_CUR);
}
NHC_IMG_Frame_Header frame_header;
- if(frame) SDL_RWseek(src, frame * 32, SEEK_CUR);
- SDL_RWread(src, &frame_header, 32, 1);
+ if(frame) SDL_RWseek(file, frame * 32, SEEK_CUR);
+ SDL_RWread(file, &frame_header, 32, 1);
SDL_Surface* surface = SDL_CreateRGBSurface(SDL_SWSURFACE, frame_header.width, frame_header.height, 8, 0, 0, 0, 0);
- SDL_RWseek(src, header.palette_offset, SEEK_SET);
- NHC_IMG_Read_Palette(src, surface);
+ SDL_RWseek(file, header.palette_offset, SEEK_SET);
+ NHC_IMG_Read_Palette(file, surface);
- SDL_RWseek(src, header.data_offset + frame_header.data_offset, SEEK_SET);
+ SDL_RWseek(file, header.data_offset + frame_header.data_offset, SEEK_SET);
SDL_LockSurface(surface);
- NHC_IMG_Read_Runs(src, surface);
+ NHC_IMG_Read_Runs(file, surface);
SDL_UnlockSurface(surface);
return surface;
}
SDL_Surface* NHC_IMG_Load(const char* filename, int type, int frame) {
- SDL_RWops* src = SDL_RWFromFile(filename, "rb");
+ SDL_RWops* file = SDL_RWFromFile(filename, "rb");
SDL_Surface* surface;
if(type == 2) {
- surface = NHC_IMG_Load_Image(src);
+ surface = NHC_IMG_Load_Image(file);
}
else if(type == 4) {
- surface = NHC_IMG_Load_Sequence(src, frame);
+ surface = NHC_IMG_Load_Sequence(file, frame);
}
else { /* error */ }
- SDL_RWclose(src);
+ SDL_RWclose(file);
return surface;
}
View
2  lib/Games/Neverhood/Scene/Nursery/One.pm
@@ -70,7 +70,7 @@ sub on_space {
package Games::Neverhood::Scene::Nursery::One::door_cover;
use constant {
file => 505,
- pos => [ 640-68, 480-280 ],
+ pos => [ 572, 200 ],
alpha => 0,
};
sub palette { $;->sprites->{background} }
View
4 lib/Games/Neverhood/Scene/Test.pm
@@ -4,6 +4,8 @@ use warnings;
package Games::Neverhood::Scene::Test;
use parent qw/Games::Neverhood::Scene/;
+use Games::Neverhood::Video;
+use File::Spec;
use constant {
fps => 24,
@@ -11,7 +13,7 @@ use constant {
};
sub sprites_list {
[
- 'test'
+ Games::Neverhood::Video->new(File::Spec->catfile($Games::Neverhood::ShareDir, 'hd', '73.0A')),
];
}
View
175 lib/Games/Neverhood/Video.pm
@@ -1,178 +1,9 @@
+use 5.01;
use strict;
use warnings;
-use 5.01;
package Games::Neverhood::Video;
-use autodie;
-
-use File::Spec ();
-
-use Games::Neverhood::Video::BitStream;
-use Games::Neverhood::Video::Huffman::BigTree;
-
-use constant no_store => qw/file next no_skip pos on_set on_unset/;
-
-# file next no_skip pos on_set on_unset
-
-sub new {
- my ($class, %arg) = @_;
- my $self = bless \%arg, ref $class || $class;
- # file
- # next
- # no_skip
- $self->{pos}[0] //= 0;
- $self->{pos}[1] //= 0;
- # on_set
- # on_unset
-
- open my $fh, File::Spec->catfile('..', 'blb', @{$self->file});
- binmode $fh;
- my $buf;
-
- # Header
- read $fh, $buf, 104;
- (@{$self->{Header}}{
- 'Signature', # all SMK2
- 'Width',
- 'Height',
- 'Frames',
- 'FrameRate', # all negative
- 'Flags', # all 0
- 'AudioSize', # all 0
- 'TreesSize',
- 'MMapSize',
- 'MClrSize',
- 'FullSize',
- 'TypeSize',
- 'AudioRate', # all 1 or 0 elements. have bit: 31=1, 30=1, 29=1 mostly but 0 for all m and one c, 28=0, 27-26=0, 25-24=0, 23-0=22050 but 11025 for all m
- 'Dummy', # all undef
- }) = unpack 'A4LLLlLA28LLLLLA28L', $buf;
- $self->{Header}{AudioSize} = [ unpack 'LLLLLLL', $self->{Header}{AudioSize} ];
- $self->{Header}{AudioRate} = [ unpack 'LLLLLLL', $self->{Header}{AudioRate} ];
-
- # FrameSizes
- read $fh, $buf, $self->{Header}{Frames} * 4;
- $self->{FrameSizes} = [ unpack 'L' x $self->{Header}{Frames}, $buf ];
- # no bit 0, no bit 1
-
- # FrameTypes
- read $fh, $buf, $self->{Header}{Frames};
- $self->{FrameTypes} = [ unpack 'C' x $self->{Header}{Frames}, $buf ];
- # all bit 0 on first FrameType some have bit 0 after, no bit 1 near the end..., no bits 2-7
-
- my $bit = Games::Neverhood::Video::BitStream->new($fh);
-
- $self->{HuffmanTrees}{MMap} = Games::Neverhood::Video::Huffman::BigTree->new($bit);
- $self->{HuffmanTrees}{MClr} = Games::Neverhood::Video::Huffman::BigTree->new($bit);
- $self->{HuffmanTrees}{Full} = Games::Neverhood::Video::Huffman::BigTree->new($bit);
- $self->{HuffmanTrees}{Type} = Games::Neverhood::Video::Huffman::BigTree->new($bit);
-
- $self->{bit} = $bit;
-
- $self;
-}
-
-use constant palmap => [
- 0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C,
- 0x20, 0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C,
- 0x41, 0x45, 0x49, 0x4D, 0x51, 0x55, 0x59, 0x5D,
- 0x61, 0x65, 0x69, 0x6D, 0x71, 0x75, 0x79, 0x7D,
- 0x82, 0x86, 0x8A, 0x8E, 0x92, 0x96, 0x9A, 0x9E,
- 0xA2, 0xA6, 0xAA, 0xAE, 0xB2, 0xB6, 0xBA, 0xBE,
- 0xC3, 0xC7, 0xCB, 0xCF, 0xD3, 0xD7, 0xDB, 0xDF,
- 0xE3, 0xE7, 0xEB, 0xEF, 0xF3, 0xF7, 0xFB, 0xFF
-];
-
-sub next_frame {
- my ($self) = @_;
- my $bit = $self->{bit};
-
- my $frame_type = shift @{$self->{FrameTypes}};
- my $frame_size = shift @{$self->{FrameSizes}};
-
- if($frame_type & 1) { # palette
- # // System.Console.WriteLine("Updating palette");
- my $old_pal = $self->{pal};
- $self->{pal} = [];
- my $size = $bit->read_8;
- $size = $size * 4 - 1;
-
- $frame_size -= $size + 1;
- my $sz = 0;
- my $pos = $bit->tell + $size;
- my $pal_index = 0;
- while($sz < 256) {
- my $t = $bit->read_8;
- if($t & 0x80) {
- # /* skip palette entries */
- $sz += ($t & 0x7F) + 1;
- for(my $i = 0; $i < ($t & 0x7F) + 1 && $sz < 256; $i++) {
- $self->{pal}[$pal_index++] = [0, 0, 0];
- }
- }
- elsif($t & 0x40 != 0) {
- # /* copy with offset */
- my $off = $bit->read_8;
- my $j = ($t & 0x3F) + 1;
- while($j-- != 0 && $sz < 256) {
- $self->{pal}[$pal_index++] = $old_pal->[$off];
- $sz++;
- $off++;
- }
- }
- else {
- # /* new entries */
- $self->{pal}[$pal_index++] = [palmap->[$t], palmap->[$bit->read_8 & 0x3F], palmap->[$bit->read_8 & 0x3F]];
- $sz++;
- }
- }
- $bit->seek($pos);
- }
-
- if($frame_type & 2 ) { # audio
-
- }
-
- # video
-}
-
-###############################################################################
-### Accessors
-
-sub file { $_[0]->{file} }
-sub next { $_[0]->{next} }
-sub no_skip { $_[0]->{no_skip} }
-sub pos { $_[0]->{pos} }
-# sub pos {
- # if(@_ > 1) { $_[0]->{pos} = $_[1]; return $_[0]; }
- # $_[0]->{pos};
-# }
-sub on_set {
- my $self = shift;
- $self->{on_set}->(@_) if $self->{on_set};
-}
-sub on_unset {
- my $self = shift;
- $self->{on_unset}->(@_) if $self->{on_unset};
-}
-
-for("blb/c") {
- for("$_/72.0A") {
- s~blb/~~;
- my $n = $_;
- my $game = Games::Neverhood::Video->new(
- file => [$_],
- );
- # print join " ", @{$game->{Header}}{qw/TreesSize MMapSize MClrSize FullSize TypeSize/};
- }
-}
-# my $game = Games::Neverhood::Video->new(
- # path => ['c', 'ID_018C0407-FF.smk'],
- # next => 'Scene::Shack';
- # no_skip => 1,
- # pos => [20, 40],
- # on_set => sub { $Game->no_skip(0) if $GG{did_this} },
- # on_unset => sub { $GG{did_this} = 1; },
-# );
+use XSLoader;
+XSLoader::load('Games::Neverhood::Video');
1;
View
149 lib/Games/Neverhood/Video.xs
@@ -0,0 +1,149 @@
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+#include "ppport.h"
+
+#include <stdio.h>
+#include <SDL/SDL.h>
+
+#define BUFFER_LEN 1024
+
+typedef struct {
+ SDL_RWops* file;
+ int byte_offset;
+ int bit_offset;
+ Uint8 buffer[BUFFER_LEN];
+} NHC_BS;
+
+NHC_BS* NHC_BS_new(SDL_RWops* file) {
+ NHC_BS* bs;
+ bs->file = file;
+ bs->byte_offset = 0;
+ bs->bit_offset = 0;
+ return bs;
+}
+
+int NHC_BS_read(NHC_BS* bs, int bits) {
+ return SDL_RWread(bs->file, bs->buffer, ceil(((float)(bits + bs->bit_offset)) / 8), 1);
+}
+
+int NHC_BS_seek(NHC_BS* bs, int bits) {
+ int ret = SDL_RWseek(bs->file, (int)(bits / 8), SEEK_SET);
+ bs->byte_offset = 0;
+ bs->bit_offset = bits % 8;
+ return ret;
+}
+
+int NHC_BS_tell(NHC_BS* bs) {
+ return SDL_RWtell(bs->file) * 8 + bs->bit_offset;
+}
+
+Uint8 NHC_BS_next_1(NHC_BS* bs) {
+ Uint8 ret = (bs->buffer)[bs->byte_offset] >> bs->bit_offset & 1;
+ if(++bs->bit_offset >= 8) {
+ bs->bit_offset = 0;
+ bs->byte_offset++;
+ }
+ return ret;
+}
+
+Uint8 NHC_BS_next_8(NHC_BS* bs) {
+ if(bs->bit_offset) {
+ return
+ (bs->buffer)[bs->byte_offset] >> bs->bit_offset
+ | (bs->buffer)[++bs->byte_offset] << 8 - bs->bit_offset & 0xFF
+ ;
+ }
+ return (bs->buffer)[bs->byte_offset++];
+}
+
+Uint16 NHC_BS_next_16(NHC_BS* bs) {
+ if(bs->bit_offset) {
+ return
+ (Uint16)((bs->buffer)[bs->byte_offset] >> bs->bit_offset
+ | (bs->buffer)[++bs->byte_offset] << 8 - bs->bit_offset & 0xFF)
+ | (Uint16)((bs->buffer)[++bs->byte_offset]) << 16 - bs->bit_offset & 0xFFFF;
+ ;
+ }
+ return
+ (Uint16)((bs->buffer)[bs->byte_offset])
+ | (Uint16)((bs->buffer)[++bs->byte_offset])
+ ;
+}
+
+typedef struct {
+ Uint32 signature;
+ Uint32 width;
+ Uint32 height;
+ Uint32 frames;
+ Uint32 frame_rate;
+ Uint32 flags;
+ Uint32 audio_size[7];
+ Uint32 trees_size;
+ Uint32 mmap_size;
+ Uint32 mclr_size;
+ Uint32 full_size;
+ Uint32 type_size;
+ Uint32 audio_rate[7];
+ Uint32 unused;
+} NHC_VID_Header;
+
+typedef struct {
+ Uint8* mmap;
+ Uint8* mclr;
+ Uint8* full;
+ Uint8* type;
+} NHC_VID_Huffman_Trees;
+
+typedef struct {
+ NHC_BS* bs;
+ NHC_VID_Header* header;
+ Uint32* frame_sizes;
+ Uint8* frame_types;
+ NHC_VID_Huffman_Trees* huffman_trees;
+ Uint8* frames_data;
+} NHC_VID;
+
+// typedef struct {
+
+// } NHC_VID_Huffman_Tree;
+
+NHC_VID* NHC_VID_new(const char* filename) {
+ NHC_VID* vid;
+ // SDL_RWops* file = SDL_RWFromFile(filename, "rb");
+ // SDL_RWread(file, vid->header, 104, 1);
+
+ // vid->frame_sizes = malloc(vid->header->frames * 4);
+ // SDL_RWread(file, vid->frame_sizes, vid->header->frames * 4, 1);
+
+ // vid->frame_types = malloc(vid->header->frames);
+ // SDL_RWread(file, vid->frame_types, vid->header->frames, 1);
+
+ // vid->bs = NHC_BS_new(file);
+
+ // vid->huffman_trees->mmap = NHC_VID_Huffman_Tree_new(vid->bs, vid->header->mmap_size);
+ // vid->huffman_trees->mclr = NHC_VID_Huffman_Tree_new(vid->bs, vid->header->mclr_size);
+ // vid->huffman_trees->full = NHC_VID_Huffman_Tree_new(vid->bs, vid->header->full_size);
+ // vid->huffman_trees->type = NHC_VID_Huffman_Tree_new(vid->bs, vid->header->type_size);
+
+ return vid;
+}
+
+MODULE = Games::Neverhood::Video PACKAGE = Games::Neverhood::Video PREFIX = Neverhood_Video_
+
+NHC_VID*
+Neverhood_Video_new(CLASS, filename)
+ char* CLASS
+ const char* filename
+ CODE:
+ RETVAL = NHC_VID_new(filename);
+ OUTPUT:
+ RETVAL
+
+char*
+Neverhood_Video_name(vid)
+ NHC_VID* vid
+ CODE:
+ RETVAL = "video";
+ OUTPUT:
+ RETVAL
View
BIN  share/hd/73.0A
Binary file not shown
View
1  typemap
@@ -103,6 +103,7 @@ SDL_RWops* O_OBJECT
SDL_svg_context* T_PTR
int T_IV
intArray T_ARRAY
+NHC_VID* O_OBJECT
OUTPUT
Please sign in to comment.
Something went wrong with that request. Please try again.