aboutsummaryrefslogblamecommitdiffstats
path: root/Game/Code/SMpeg/USmpeg.pas
blob: ed7e194a51ee95382e6bf8da2445be727504d120 (plain) (tree)


















































































































































































































































































































                                                                                                                                                                  
unit USmpeg;

interface
uses SDL,
     smpeg,
     gl,
     glu,
     glext,
     SysUtils,
     UIni;

procedure OpenSmpeg(FileName: string);
procedure SkipSmpeg(Time: single);
procedure PlaySmpeg;
procedure PauseSmpeg; //PauseMod
procedure UpdateSmpeg;
procedure CloseSmpeg;
function glmovie_init(Width : GLuint; Height : GLuint ) : GLenum;
procedure glmpeg_update(surface: PSDL_Surface; x: Sint32; y: Sint32; w: Uint32; h: Uint32); cdecl;
procedure DrawSmpeg(frame: PGLubyte);
procedure glmovie_resize( width : GLuint; height : GLuint );
procedure glmovie_quit;

var
  mpeg:       PSMPEG;
  mpeg_info:  TSMPEG_Info;
  surface:    PSDL_Surface;

type
  { Some data is redundant at this stage. }
  PGLMovieTexture = ^TGLMovieTexture;
  TGLMovieTexture = record
    id : GLuint; (* OpenGL texture id. *)
    poly_width : GLuint; (* Quad width for tile. *)
    poly_height : GLuint; (* Quad height for tile. *)
    movie_width : GLuint; (* Width of movie inside tile. *)
    movie_height : GLuint; (* Height of movie inside tile. *)
    skip_rows : GLuint; (* Number of rows of movie to skip *)
    skip_pixels : GLuint; (* Number of columns of movie to skip *)
    row : GLuint; (* Row number of tile in scheme. *)
    col : GLuint; (* Column number of tile in scheme. *)
  end;

type
  TGLuintArray = array of GLuint;
  PGLuintArray = ^TGLuintArray;
  TGLMovieTextureArray = array of TGLMovieTexture;
  PGLMovieTextureArray = ^TGLMovieTextureArray;

var
  (* Our evil maximum texture size. Boo 3Dfxnot  *)
  texture_size : GLuint = 1024;//512;
  texture_ids : GLuint;
  textures:     TGLMovieTexture;
  tiled_width : GLuint = 0;
  tiled_height : GLuint = 0;
  movie_width : GLuint = 0;
  movie_height : GLuint = 0;

implementation

procedure OpenSmpeg(FileName: string);
begin
  mpeg := SMPEG_new(PChar(FileName), @mpeg_info, 0); // audio
  if ( mpeg = nil ) then begin
    SDL_Quit;
    Exit;
  end;

//  SMPEG_setvolume(mpeg, 50);
  SMPEG_enableaudio(mpeg, 0);

  (* Everything needs to be in RGB for GL, but needs to be 32-bit for SMPEG. *)
  surface := SDL_AllocSurface( SDL_SWSURFACE,
    mpeg_info.width,
    mpeg_info.height,
    32,
    $000000FF,
    $0000FF00,
    $00FF0000,
    $FF000000 );

  if ( surface = nil ) then begin
    SDL_Quit;
    Exit;
  end;

  (* *Initialize* with mpeg size. *)
  if (glmovie_init( mpeg_info.width, mpeg_info.height ) <> GL_NO_ERROR ) then begin
    SDL_Quit;
    Exit;
  end;

  SMPEG_setdisplay(mpeg, surface, nil, @glmpeg_update);
end;

procedure SkipSmpeg(Time: single);
begin
  SMPEG_skip(mpeg, Time);
end;

procedure PlaySmpeg;
begin
  SMPEG_play(mpeg);
end;

//Pause Mod
procedure PauseSmpeg;
begin
  SMPEG_pause(mpeg);
end;

procedure UpdateSmpeg;
begin
//  glmpeg_update(surface,0,0,0,0);
  DrawSmpeg( PGLubyte( surface.pixels ) );
end;

procedure CloseSmpeg;
begin
  SMPEG_delete(mpeg);
  //Fixing the Memory Lag in earlyer Versions (X-Mas Mod, all Official Versions)
  glmovie_quit;
end;

function glmovie_init( Width : GLuint; Height : GLuint ) : GLenum;
type
  PGLubyteArray = ^TGLubyteArray;
  TGLubyteArray = array of GLubyte;
var
  (* Initial black texels. *)
  pixels : TGLubyteArray;
  (* Absolute offsets from within tiled frame. *)
  //offset_x: GLuint;
  //offset_y: GLuint;
  skip_rows : GLuint;
  skip_pixels : GLuint;
  i, j, current : GLuint;
begin
  skip_rows := 0;
  current := 0;
  (* Save original movie dimensions. *)
  movie_width := width;
  movie_height := height;

  (* Get the power of 2 dimensions. *)
  tiled_width := 1024{512};
  tiled_height := 1024{512};

  texture_size := 1024{512};

  (* Time for fun with data type = record *)
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  glEnable(GL_TEXTURE_2D);
  glEnable(GL_DITHER);

  glGenTextures(1, @texture_ids);

      current := 0;
      (* Setup texture. *)
      textures.id := texture_ids;
      textures.poly_width := texture_size;
      textures.poly_height := texture_size;
      textures.movie_width := movie_width - 2;
      textures.movie_height := movie_height - 2;
      textures.row := i;
      textures.col := j;
      textures.skip_pixels := skip_pixels;
      textures.skip_rows := skip_rows;

      SetLength( pixels, textures.poly_width * textures.poly_height * 4 );
      if ( pixels = nil ) then
      begin
        glDeleteTextures(1, @texture_ids);
        result := GL_OUT_OF_MEMORY;
        exit;
      end;
      //FillChar( pixels^, textures[ current ].poly_width * textures[ current ].poly_height * 4, 0 );

      (* Do all of our useful binding. *)
      glBindTexture(GL_TEXTURE_2D, texture_ids);
//      glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
      (* Specify our 256x256 black texture. *)
      glTexImage2D( GL_TEXTURE_2D,
        0,
        GL_RGB,
        1024{512},//textures.poly_width,
        1024{512},//textures.poly_height,
        0,
        GL_RGBA,
        GL_UNSIGNED_BYTE,
        @pixels[0] );
        SetLength( pixels, 0 );


  (* Simple state setup at the end. *)
  result := glGetError( );
end;

procedure glmpeg_update( surface : PSDL_Surface; x : Sint32; y : Sint32; w : Uint32;
  h : Uint32 ); cdecl;
var
  error : GLenum;
begin
  glClear( GL_COLOR_BUFFER_BIT );
  glMatrixMode( GL_MODELVIEW );
  glLoadIdentity;
  DrawSmpeg( PGLubyte( surface.pixels ) );
  error := glGetError( );
  if ( error <> GL_NO_ERROR ) then Exit;
  SDL_GL_SwapBuffers;
end;

procedure DrawSmpeg(frame: PGLubyte);
var
  Shift:    GLdouble;
  CropT:    real;
  CropB:    real;
  TexT:     real;
  TexB:     real;
  TexL:     real;
  TexR:     real;
  Wide:     boolean;
begin
  (* full screen mpeg *)
{  CropT := 0;
  CropB := 600;
  TexT := 0;
  TexB := 1;
  TexL := 0;
  TexW := 1;}

  // set movie texture crop
  Wide := false;
  if (textures.movie_width = 720-2) and (textures.movie_height = 344-2) then begin
    TexT := 0;
    TexB := 342/1024;
    Wide := true;
  end;
  if textures.movie_height = 304-2 then begin
    TexT := 0;
    TexB := 304/1024;
    Wide := true;
  end;
  if textures.movie_height = 152-2 then begin
    TexT := 0;
    TexB := 152/1024;
    Wide := true;
  end;

  CropT := 110; // (110/800 = 13,75% max crop)
  CropB := 490; // (110/800 = 13,75% max crop)

  if (textures.movie_height <> 304-2) and (textures.movie_height <> 152-2) and (textures.movie_height <> 344-2) then begin
    TexT := 110 / 600 * (textures.movie_height / 1024{512});
    TexB := 490 / 600 * (textures.movie_height / 1024{512});

    if Ini.MovieSize >= 1 then begin
      // full screen size
      CropT := 0;
      CropB := 600;
      TexT := 0;
      TexB := textures.movie_height / 1024{512};
    end;
  end;

  TexL := {10}0/600 * (textures.movie_width / 1024{512});
  TexR := {590}600/600 * (textures.movie_width / 1024{512});

  glEnable(GL_TEXTURE_2D);
  glDisable(GL_BLEND);
  glColor3f(1, 1, 1);
  glBindTexture( GL_TEXTURE_2D, texture_ids );
//  glPixelStorei( GL_UNPACK_ROW_LENGTH, movie_width );
  glPixelStorei( GL_UNPACK_SKIP_ROWS, 0);
  glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0);
  glTexSubImage2D( GL_TEXTURE_2D, 0, 0, (* offset_x *) 0, (* offset_y *) textures.movie_width + 2, textures.movie_height + 2, GL_RGBA, GL_UNSIGNED_BYTE, frame );

  // draw
  glBegin( GL_QUADS );
    glTexCoord2f(TexL, TexT); glVertex2f(0, CropT);
    glTexCoord2f(TexL, TexB); glVertex2f(0, CropB);
    glTexCoord2f(TexR, TexB); glVertex2f(800, CropB);
    glTexCoord2f(TexR, TexT); glVertex2f(800, CropT);
  glEnd;
  glDisable(GL_TEXTURE_2D);
end;

procedure glmovie_resize( width : GLuint; height : GLuint );
begin
  glViewport(0, 0, width, height);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity;
  gluOrtho2D(0, 800, 600, 0);
end;

procedure glmovie_quit;
begin
  glDeleteTextures(1, @texture_ids);
  SDL_FreeSurface(surface);
end;

end.