DEADSOFTWARE

more implemented functions for allegro port
[d2df-sdl.git] / src / nogl / noGLALSW.inc
index 60b207228bcd321fc1c9848af9cb9a78e847f7fe..55ee112fe1bfbd05dfcd820cefca48fd799b9f34 100644 (file)
@@ -7,15 +7,19 @@ implementation
 
   const
     ValPerVertex = 2;
-    ValPerColor = 4;
+    ValPerColor = 1; (* colors stored in one integer *)
     ValPerCoord = 2;
+    StackSize = 16;
 
   type
-    TArrayFloat = array of Integer;
+    TArrayFloat = array of GLfloat;
+    TArrayInteger = array of Integer;
 
     TCmds = record
       mode: GLenum;
-      v, c, t: TArrayFloat;
+      v: TArrayInteger;
+      c: TArrayInteger;
+      t: TArrayFloat;
     end;
 
     TArrayTexture = array of record
@@ -28,6 +32,11 @@ implementation
     tex: TArrayTexture;
     ctex: Integer;
     ccol: Integer;
+    clearColor: cint;
+    stack: array [0..StackSize - 1] of record
+      x, y: Integer;
+    end;
+    stack_ptr: Integer;
 
   function AddTexture: Integer;
     var i: Integer;
@@ -54,10 +63,19 @@ implementation
     assert(tex[i].used);
     tex[i].used := false;
     if tex[i].bmp <> nil then
-      destroy_bitmap(tex[i].bmp)
+      destroy_bitmap(tex[i].bmp);
+    tex[i].bmp := nil
   end;
 
-  procedure Add (var x: TArrayFloat; f: Integer);
+  procedure Addi (var x: TArrayInteger; f: Integer);
+    var i: Integer;
+  begin
+    i := Length(x);
+    SetLength(x, i + 1);
+    x[i] := f;
+  end;
+
+  procedure Addf (var x: TArrayFloat; f: GLfloat);
     var i: Integer;
   begin
     i := Length(x);
@@ -86,14 +104,14 @@ implementation
   end;
 
   procedure glClearColor(red, green, blue, alpha: GLclampf);
-    var color: Integer;
   begin
-    color := makeacol(floor(red * 255), floor(green * 255), floor(blue * 255), floor(alpha * 255));
-    clear_to_color(sdl2allegro_screen, color)
+    clearColor := makeacol(floor(red * 255), floor(green * 255), floor(blue * 255), floor(alpha * 255));
   end;
 
   procedure glClear(mask: GLbitfield);
   begin
+    if (mask and GL_COLOR_BUFFER_BIT) <> 0 then
+      clear_to_color(sdl2allegro_screen, clearColor)
   end;
 
   procedure glAlphaFunc(func: GLenum; ref: GLclampf);
@@ -136,13 +154,20 @@ implementation
   end;
 
   procedure glEnd;
-    var i, x, y, w, h: Integer;
+    var
+      i, j, k, w, h, x0, y0, x1, y1, offx, offy, tmp, s0, t0, s1, t1: Integer;
+      oldx0, oldy0, oldx1, oldy1: cint;
+      flipv, fliph: Boolean;
+      draw_sprite_proc: procedure (bmp, sprite: Allegro.PBITMAP; x, y: cint); cdecl;
   begin
     assert(cmds.mode <> GL_INVALID_ENUM);
     assert(Length(cmds.v) mod ValPerVertex = 0);
     assert(Length(cmds.c) mod ValPerColor = 0);
     assert(Length(cmds.t) mod ValPerCoord = 0);
 
+    offx := stack[stack_ptr].x;
+    offy := stack[stack_ptr].y;
+
     case cmds.mode of
     GL_POINTS:
       begin
@@ -151,12 +176,12 @@ implementation
          begin
            assert(Length(cmds.c) * 2 = Length(cmds.v)); (* not enough colors *)
            for i := 0 to Length(cmds.v) div 2 - 1 do
-             putpixel(sdl2allegro_screen, cmds.v[i * 2], cmds.v[i * 2 + 1], cmds.c[i])
+             putpixel(sdl2allegro_screen, offx + cmds.v[i * 2], offy + cmds.v[i * 2 + 1], cmds.c[i])
          end
          else
          begin
            for i := 0 to Length(cmds.v) div 2 - 1 do
-             putpixel(sdl2allegro_screen, cmds.v[i * 2], cmds.v[i * 2 + 1], ccol)
+             putpixel(sdl2allegro_screen, offx + cmds.v[i * 2], offy + cmds.v[i * 2 + 1], ccol)
          end
       end;
     GL_LINES:
@@ -167,43 +192,104 @@ implementation
         begin
           assert(Length(cmds.c) * 2 = Length(cmds.v));
           for i := 0 to Length(cmds.v) div 4 - 1 do
-            fastline(sdl2allegro_screen, cmds.v[i * 4], cmds.v[i * 4 + 1], cmds.v[i * 4 + 2], cmds.v[i * 4 + 3], cmds.c[i * 2])
+            fastline(sdl2allegro_screen, offx + cmds.v[i * 4], offy + cmds.v[i * 4 + 1], offx + cmds.v[i * 4 + 2], offy + cmds.v[i * 4 + 3], cmds.c[i * 2])
         end
         else
         begin
           for i := 0 to Length(cmds.v) div 4 - 1 do
-            fastline(sdl2allegro_screen, cmds.v[i * 4], cmds.v[i * 4 + 1], cmds.v[i * 4 + 2], cmds.v[i * 4 + 3], ccol)
+            fastline(sdl2allegro_screen, offx + cmds.v[i * 4], offy + cmds.v[i * 4 + 1], offx + cmds.v[i * 4 + 2], offy + cmds.v[i * 4 + 3], ccol)
         end
       end;
     GL_QUADS:
       begin
-        assert(Length(cmds.v) mod 8 = 0); (* broken quad *)
+        ASSERT(Length(cmds.v) mod 8 = 0); (* broken quad *)
         if Length(cmds.t) <> 0 then
         begin
-          assert(Length(cmds.t) = Length(cmds.v)); (* not enough texture coords *)
-          assert(ctex >= 0);
-          assert(ctex <= High(tex));
+          ASSERT(Length(cmds.t) = Length(cmds.v)); (* not enough texture coords *)
+          ASSERT(ctex >= 0);
+          ASSERT(ctex <= High(tex));
+          ASSERT(tex[ctex].bmp <> nil);
           for i := 0 to Length(cmds.v) div 8 - 1 do
           begin
-            x := cmds.v[i * 8];
-            y := cmds.v[i * 8 + 1];
-            w := abs(cmds.v[i * 4 + 5] - x);
-            h := abs(cmds.v[i * 4 + 6] - y);
-            //e_LogWriteFLn('Textured Quad %s %s', [w, h]);
-            draw_sprite(sdl2allegro_screen, tex[ctex].bmp, x, y);
-            //rect(sdl2allegro_screen, x, y, w, h, makecol(255, 0, 0))
+            flipv := False; fliph := False;
+            x0 := cmds.v[i * 8 + 0]; y0 := cmds.v[i * 8 + 1];
+            x1 := cmds.v[i * 8 + 4]; y1 := cmds.v[i * 8 + 5];
+            if x1 < x0 then
+            begin
+              tmp := x0;
+              x0 := x1;
+              x1 := tmp;
+              fliph := not fliph
+            end;
+            if y1 < y0 then
+            begin
+              tmp := y0;
+              y0 := y1;
+              y1 := tmp;
+              flipv := not flipv
+            end;
+
+            w := tex[ctex].bmp.w;
+            h := tex[ctex].bmp.h;
+            s0 := Trunc(cmds.t[i * 8 + 0] * w);
+            t0 := Trunc(cmds.t[i * 8 + 1] * h);
+            s1 := Trunc(cmds.t[i * 8 + 4] * w);
+            t1 := Trunc(cmds.t[i * 8 + 5] * h);
+
+            if s1 < s0 then
+            begin
+              tmp := s0;
+              s0 := s1;
+              s1 := tmp;
+              fliph := not fliph
+            end;
+            if t1 < t0 then
+            begin
+              tmp := t0;
+              t0 := t1;
+              t1 := tmp;
+              flipv := not flipv
+            end;
+
+            s0 := s0 mod w;
+            t0 := t0 mod h;
+            s1 := s1 mod w;
+            t1 := t1 mod h;
+
+            if flipv and fliph then
+              draw_sprite_proc := Allegro.draw_sprite_vh_flip
+            else if flipv then
+              draw_sprite_proc := Allegro.draw_sprite_v_flip
+            else if fliph then
+              draw_sprite_proc := Allegro.draw_sprite_h_flip
+            else
+              draw_sprite_proc := Allegro.draw_sprite;
+
+            oldx0 := 0; oldy0 := 0; oldx1 := 0; oldy1 := 0;
+            get_clip_rect(sdl2allegro_screen, oldx0, oldy0, oldx1, oldy1);
+            set_clip_rect(sdl2allegro_screen, max(oldx0, offx + x0), max(oldy0, offy + y0), min(oldx1, offx + x1), min(oldy1, offy + y1));
+
+            for j := 0 to (y1 - y0 + h - 1) div h - 1 do
+              for k := 0 to (x1 - x0 + w - 1) div w - 1 do
+                draw_sprite_proc(sdl2allegro_screen, tex[ctex].bmp, offx + x0 + k * w - s0, offy + y0 + j * h - t0);
+                //blit(tex[ctex].bmp, sdl2allegro_screen, 0, 0, offx + x0 + k * w - s0, offy + y0 + j * h - t0, w, h);
+
+            set_clip_rect(sdl2allegro_screen, oldx0, oldy0, oldx1, oldy1);
+
+            //rect(sdl2allegro_screen, offx + x0, offy + y0, offx + x1, offy + y1, makecol(255, 0, 0));
+            //rect(sdl2allegro_screen, offx + oldx0, offy + oldy0, offx + oldx1, offy + oldx1, makecol(0, 255, 0));
           end
         end
         else if Length(cmds.c) <> 0 then
         begin
           assert(Length(cmds.c) * 2 = Length(cmds.v)); (* not enough colors *)
           for i := 0 to Length(cmds.v) div 8 - 1 do
-            rectfill(sdl2allegro_screen, cmds.v[i * 8], cmds.v[i * 8 + 1], cmds.v[i * 4 + 5], cmds.v[i * 4 + 6], cmds.c[i * 4])
+            rectfill(sdl2allegro_screen, offx + cmds.v[i * 8], offy + cmds.v[i * 8 + 1], offx + cmds.v[i * 8 + 4], offy + cmds.v[i * 8 + 5], cmds.c[i * 4])
         end
         else
         begin
           for i := 0 to Length(cmds.v) div 8 - 1 do
-            rectfill(sdl2allegro_screen, cmds.v[i * 8], cmds.v[i * 8 + 1], cmds.v[i * 4 + 5], cmds.v[i * 4 + 6], ccol)
+            rectfill(sdl2allegro_screen, offx + cmds.v[i * 8], offy + cmds.v[i * 8 + 1], offx + cmds.v[i * 8 + 4], offy + cmds.v[i * 8 + 5], ccol)
         end
       end;
     else
@@ -218,44 +304,44 @@ implementation
 
   procedure glVertex2f(x, y: GLfloat);
   begin
-    Add(cmds.v, ceil(x));
-    Add(cmds.v, ceil(y))
+    Addi(cmds.v, ceil(x));
+    Addi(cmds.v, ceil(y))
   end;
 
   procedure glVertex2i(x, y: GLint);
   begin
-    Add(cmds.v, x);
-    Add(cmds.v, y)
+    Addi(cmds.v, x);
+    Addi(cmds.v, y)
   end;
 
   procedure glColor4f(red, green, blue, alpha: GLfloat);
   begin
     ccol := makeacol(floor(red * 255), floor(green * 255), floor(blue * 255), floor(alpha * 255));
-    Add(cmds.c, ccol)
+    Addi(cmds.c, ccol)
   end;
 
   procedure glColor4ub(red, green, blue, alpha: GLubyte);
   begin
     ccol := makeacol(red, green, blue, alpha);
-    Add(cmds.c, ccol)
+    Addi(cmds.c, ccol)
   end;
 
   procedure glColor3ub(red, green, blue: GLubyte);
   begin
     ccol := makecol(red, green, blue);
-    Add(cmds.c, ccol)
+    Addi(cmds.c, ccol)
   end;
 
   procedure glTexCoord2f(s, t: GLfloat);
   begin
-    Add(cmds.t, floor(s));
-    Add(cmds.t, floor(t));
+    Addf(cmds.t, s);
+    Addf(cmds.t, t);
   end;
 
   procedure glTexCoord2i(s, t: GLint);
   begin
-    Add(cmds.t, s);
-    Add(cmds.t, t);
+    Addf(cmds.t, s);
+    Addf(cmds.t, t);
   end;
 
   procedure glReadPixels(x, y: GLint; width, height: GLsizei; format, atype: GLenum; pixels: Pointer);
@@ -264,6 +350,11 @@ implementation
 
   procedure glLoadIdentity;
   begin
+    with stack[stack_ptr] do
+    begin
+      x := 0;
+      y := 0;
+    end
   end;
 
   procedure glMatrixMode(mode: GLenum);
@@ -277,22 +368,32 @@ implementation
 
   procedure glPushMatrix;
   begin
+    stack[stack_ptr + 1] := stack[stack_ptr];
+    INC(stack_ptr);
   end;
 
   procedure glPopMatrix;
   begin
+    DEC(stack_ptr)
   end;
 
   procedure glTranslatef(x, y, z: GLfloat);
   begin
+    ASSERT(z = 0); (* 3D not supported *)
+    stack[stack_ptr].x := Trunc(x);
+    stack[stack_ptr].y := Trunc(y);
   end;
 
   procedure glRotatef(angle, x, y, z: GLfloat);
   begin
+    //ASSERT(z = 0); (* 3D not supported *)
+    (* TODO Rotation *)
   end;
 
   procedure glScalef(x, y, z: GLfloat);
   begin
+    //ASSERT(z = 1); (* 3D not supported *)
+    (* TODO Scale *)
   end;
 
   procedure glViewport(x, y: GLint; width, height: GLsizei);
@@ -345,7 +446,7 @@ implementation
   end;
 
   procedure glTexImage2D(target: GLenum; level, internalformat: GLint; width, height: GLsizei; border: GLint; format, atype: GLenum; const pixels: Pointer);
-    var i, j, adr: Integer; p: PByte;
+    var i, j, adr: Integer; p: PByte; color: cint;
   begin
     assert(target = GL_TEXTURE_2D);
     assert(level = 0);
@@ -360,6 +461,7 @@ implementation
 
     if tex[ctex].bmp <> nil then
       destroy_bitmap(tex[ctex].bmp);
+    // Video bitmap can lead to bad textures under dos
     //tex[ctex].bmp := create_video_bitmap(width, height);
     //if tex[ctex].bmp = nil then
       tex[ctex].bmp := create_system_bitmap(width, height);
@@ -376,7 +478,11 @@ implementation
         for i := 0 to width - 1 do
         begin
           adr := j * width * 4 + i * 4;
-          putpixel(tex[ctex].bmp, i, height - j, makeacol(p[adr], p[adr + 1], p[adr + 2], p[adr + 3]))
+          if p[adr + 3] <> $FF then
+            color := 0
+          else
+            color := makeacol(p[adr], p[adr + 1], p[adr + 2], p[adr + 3]);
+          putpixel(tex[ctex].bmp, i, j, color)
         end
     end
     else
@@ -391,7 +497,7 @@ implementation
   end;
 
   procedure glTexSubImage2D(target: GLenum; level, xoffset, yoffset: GLint; width, height: GLsizei; format, atype: GLenum; const pixels: Pointer);
-    var i, j, adr: Integer; p: PByte;
+    var i, j, adr: Integer; p: PByte; color: Cint;
   begin
     assert(target = GL_TEXTURE_2D);
     assert(level = 0);
@@ -414,7 +520,11 @@ implementation
         for i := 0 to width - 1 do
         begin
           adr := j * width * 4 + i * 4;
-          putpixel(tex[ctex].bmp, i, height - j, makeacol(p[adr], p[adr + 1], p[adr + 2], p[adr + 3]))
+          if p[adr + 3] <> $FF then
+            color := 0
+          else
+            color := makeacol(p[adr], p[adr + 1], p[adr + 2], p[adr + 3]);
+          putpixel(tex[ctex].bmp, i, j, color)
         end
     end
     else