foxygit / doom Log in
commit 0cc2ad38090b1b286ded01321afc0e199b37372c
Author:     Simon Howard <fraggle@gmail.com>
AuthorDate: Mon Dec 18 18:15:47 2006 +0000
Commit:     Simon Howard <fraggle@gmail.com>
CommitDate: Mon Dec 18 18:15:47 2006 +0000

    x3, x4 aspect ratio corrected scale functions.

    Subversion-branch: /trunk/chocolate-doom
    Subversion-revision: 786
---
 TODO          |   1 -
 src/i_scale.c | 282 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/i_scale.h |   2 +
 src/i_video.c |   8 ++
 4 files changed, 292 insertions(+), 1 deletion(-)

diff --git a/TODO b/TODO
index 83b9ecdc..41971825 100644
--- a/TODO
+++ b/TODO
@@ -5,7 +5,6 @@ To do:
   - Debian/Ubuntu .deb packages, Fedora .rpm packages.
   - Windows NSIS installer.
   - MacOS X .dmg packages (should be universal binaries!)
-* Aspect ratio correction - stretch 320x200 to 320x240, 640x480, etc.
 * Smarter setup program - detect IWADs automatically and make them
   selectable from a list.
 * Free version of the Chocolate Doom logo (from scratch, not using the
diff --git a/src/i_scale.c b/src/i_scale.c
index 29bc8731..deda0551 100644
--- a/src/i_scale.c
+++ b/src/i_scale.c
@@ -402,3 +402,285 @@ void I_Stretch2x(int x1, int y1, int x2, int y2)
     }
 }

+static void WriteLine3x(byte *dest, byte *src)
+{
+    int x;
+
+    for (x=0; x<SCREENWIDTH; ++x)
+    {
+        dest[0] = *src;
+        dest[1] = *src;
+        dest[2] = *src;
+        dest += 3;
+        ++src;
+    }
+}
+
+static void WriteBlendedLine3x(byte *dest, byte *src1, byte *src2,
+                               byte *stretch_table)
+{
+    int x;
+    int val;
+
+    for (x=0; x<SCREENWIDTH; ++x)
+    {
+        val = stretch_table[*src1 * 256 + *src2];
+        dest[0] = val;
+        dest[1] = val;
+        dest[2] = val;
+        dest += 3;
+        ++src1;
+        ++src2;
+    }
+}
+
+void I_Stretch3x(int x1, int y1, int x2, int y2)
+{
+    byte *bufp, *screenp;
+    int y;
+
+    // Only works with full screen update
+
+    if (x1 != 0 || y1 != 0 || x2 != SCREENWIDTH || y2 != SCREENHEIGHT)
+    {
+        return;
+    }
+
+    // Need to byte-copy from buffer into the screen buffer
+
+    bufp = src_buffer + y1 * SCREENWIDTH + x1;
+    screenp = (byte *) dest_buffer + y1 * dest_pitch + x1;
+
+    // For every 5 lines of src_buffer, 18 lines are written to dest_buffer.
+    // (200 -> 720)
+
+    for (y=0; y<SCREENHEIGHT; y += 5)
+    {
+        // 100% line 0
+        WriteLine3x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 0
+        WriteLine3x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 0
+        WriteLine3x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 60% line 0, 40% line 1
+        WriteBlendedLine3x(screenp, bufp + SCREENWIDTH, bufp, stretch_tables[1]);
+        screenp += dest_pitch; bufp += SCREENWIDTH;
+
+        // 100% line 1
+        WriteLine3x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 1
+        WriteLine3x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 1
+        WriteLine3x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 20% line 1, 80% line 2
+        WriteBlendedLine3x(screenp, bufp, bufp + SCREENWIDTH, stretch_tables[0]);
+        screenp += dest_pitch; bufp += SCREENWIDTH;
+
+        // 100% line 2
+        WriteLine3x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 2
+        WriteLine3x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 80% line 2, 20% line 3
+        WriteBlendedLine3x(screenp, bufp + SCREENWIDTH, bufp, stretch_tables[0]);
+        screenp += dest_pitch; bufp += SCREENWIDTH;
+
+        // 100% line 3
+        WriteLine3x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 3
+        WriteLine3x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 3
+        WriteLine3x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 40% line 3, 60% line 4
+        WriteBlendedLine3x(screenp, bufp, bufp + SCREENWIDTH, stretch_tables[1]);
+        screenp += dest_pitch; bufp += SCREENWIDTH;
+
+        // 100% line 4
+        WriteLine3x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 4
+        WriteLine3x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 4
+        WriteLine3x(screenp, bufp);
+        screenp += dest_pitch; bufp += SCREENWIDTH;
+    }
+}
+
+static void WriteLine4x(byte *dest, byte *src)
+{
+    int x;
+
+    for (x=0; x<SCREENWIDTH; ++x)
+    {
+        dest[0] = *src;
+        dest[1] = *src;
+        dest[2] = *src;
+        dest[3] = *src;
+        dest += 4;
+        ++src;
+    }
+}
+
+static void WriteBlendedLine4x(byte *dest, byte *src1, byte *src2,
+                               byte *stretch_table)
+{
+    int x;
+    int val;
+
+    for (x=0; x<SCREENWIDTH; ++x)
+    {
+        val = stretch_table[*src1 * 256 + *src2];
+        dest[0] = val;
+        dest[1] = val;
+        dest[2] = val;
+        dest[3] = val;
+        dest += 4;
+        ++src1;
+        ++src2;
+    }
+}
+
+void I_Stretch4x(int x1, int y1, int x2, int y2)
+{
+    byte *bufp, *screenp;
+    int y;
+
+    // Only works with full screen update
+
+    if (x1 != 0 || y1 != 0 || x2 != SCREENWIDTH || y2 != SCREENHEIGHT)
+    {
+        return;
+    }
+
+    // Need to byte-copy from buffer into the screen buffer
+
+    bufp = src_buffer + y1 * SCREENWIDTH + x1;
+    screenp = (byte *) dest_buffer + y1 * dest_pitch + x1;
+
+    // For every 5 lines of src_buffer, 24 lines are written to dest_buffer.
+    // (200 -> 960)
+
+    for (y=0; y<SCREENHEIGHT; y += 5)
+    {
+        // 100% line 0
+        WriteLine4x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 0
+        WriteLine4x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 0
+        WriteLine4x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 0
+        WriteLine4x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 90% line 0, 20% line 1
+        WriteBlendedLine4x(screenp, bufp + SCREENWIDTH, bufp, stretch_tables[0]);
+        screenp += dest_pitch; bufp += SCREENWIDTH;
+
+        // 100% line 1
+        WriteLine4x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 1
+        WriteLine4x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 1
+        WriteLine4x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 1
+        WriteLine4x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 60% line 1, 40% line 2
+        WriteBlendedLine4x(screenp, bufp + SCREENWIDTH, bufp, stretch_tables[1]);
+        screenp += dest_pitch; bufp += SCREENWIDTH;
+
+        // 100% line 2
+        WriteLine4x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 2
+        WriteLine4x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 2
+        WriteLine4x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 2
+        WriteLine4x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 40% line 2, 60% line 3
+        WriteBlendedLine4x(screenp, bufp, bufp + SCREENWIDTH, stretch_tables[1]);
+        screenp += dest_pitch; bufp += SCREENWIDTH;
+
+        // 100% line 3
+        WriteLine4x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 3
+        WriteLine4x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 3
+        WriteLine4x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 3
+        WriteLine4x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 20% line 3, 80% line 4
+        WriteBlendedLine4x(screenp, bufp, bufp + SCREENWIDTH, stretch_tables[0]);
+        screenp += dest_pitch; bufp += SCREENWIDTH;
+
+        // 100% line 4
+        WriteLine4x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 4
+        WriteLine4x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 4
+        WriteLine4x(screenp, bufp);
+        screenp += dest_pitch;
+
+        // 100% line 4
+        WriteLine4x(screenp, bufp);
+        screenp += dest_pitch; bufp += SCREENWIDTH;
+    }
+}
+
diff --git a/src/i_scale.h b/src/i_scale.h
index 6f523039..578b2b36 100644
--- a/src/i_scale.h
+++ b/src/i_scale.h
@@ -37,6 +37,8 @@ void I_Scale3x(int x1, int y1, int x2, int y2);
 void I_Scale4x(int x1, int y1, int x2, int y2);
 void I_Stretch1x(int x1, int y1, int x2, int y2);
 void I_Stretch2x(int x1, int y1, int x2, int y2);
+void I_Stretch3x(int x1, int y1, int x2, int y2);
+void I_Stretch4x(int x1, int y1, int x2, int y2);
 void I_InitStretchTables(byte *palette);

 #endif /* #ifndef __I_SCALE__ */
diff --git a/src/i_video.c b/src/i_video.c
index 26f8ec16..e2b12ed4 100644
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -591,6 +591,14 @@ static void BlitArea(int x1, int y1, int x2, int y2)
         {
             scale_function = I_Stretch2x;
         }
+        else if (screenmultiply == 3)
+        {
+            scale_function = I_Stretch3x;
+        }
+        else if (screenmultiply == 4)
+        {
+            scale_function = I_Stretch4x;
+        }
         else
         {
             I_Error("No aspect ratio stretching function for screenmultiply=%i",