DieHard Wolfers Forum Index DieHard Wolfers
A Wolfenstein 3d Fan Community


  Hosted by: MCS & Areyep.com - Designed by: BrotherTank

Original Yahoo Forum - Die Hard Archives

AReyeP HomepageAreyep Homepage DieHard Wolfenstein BunkerDieHard Wolfenstein Bunker Log inLog in RegisterRegister Banlist FAQFAQ Search ForumsSearch

  Username:    Password:      Remember me       

ScaleShape bugfix
Page 1 of 1
DieHard Wolfers Forum Index -> Code Crackers View Previous TopicRefresh this PageAdd Topic to your Browser FavoritesSearch ForumsPrint this TopicE-mail TopicGoto Page BottomView Next Topic
Post new topicReply to topic
Author Message
Aryan_Wolf3D
DieHard Guard
DieHard Guard


Joined: 21 Jul 2011
Last Visit: 10 Dec 2019

Topics: 8
Posts: 271

blank.gif

PostPosted: Wed Nov 20, 2019 4:30 am
   Subject: ScaleShape bugfix
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Next PostGoto Bottom of Posts

As I'm sure most are aware, the original sprite drawing code is buggy... The game will freeze up if the leftmost column contains a non-transparent pixel, and even if just the left half of the sprite contains pixels and nothing in the right, it's still almost guaranteed to freeze, or cause bizarre memory leaks. For example, using a sprite like this (every pixel on the left half of the sprite):



Can cause stuff like this to happen:



I am aware that there's already a bunch of different ScaleShape/SimpleScaleShape routines out there that fix these problems, but to my knowledge, no one has fixed them in the original code. So here's how to do it!

First, let's fix the bug that causes freezes with solid pixels on the leftmost column... The problematic code is this, in WL_SCALE.C in the routine ScaleShape:

::: CODE :::
srcx = 32;
slinex = xcenter;
stopx = shape->leftpix;
cmdptr = &shape->dataofs[31-stopx];

while ( --srcx >=stopx && slinex>0)

This may look innocent enough, and it does work fine until the value of srcx becomes 0, which will happen when it reaches the leftmost column. The problem is, srcx is unsigned, which means that it will roll over to 65535 when it's decremented from 0. And since it's using the prefix decrement operator, this will happen before it checks if it's >= stopx, resulting in an infinite loop. To fix this, just add the code in red to the bottom of the while loop:

::: CODE :::

   while ( --srcx >=stopx && slinex>0)
   {
      (unsigned)linecmds = *cmdptr--;
      if ( !(slinewidth = comptable->width[srcx]) )
         continue;

      if (slinewidth == 1)
      {
         slinex--;

         if (slinex<viewwidth)
         {
            if (wallheight[slinex] >= height)
               continue;      // obscured by closer wall
            ScaleLine ();
         }
         continue;
      }

      //
      // handle multi pixel lines
      //
      if (slinex>viewwidth)
      {
         slinex -= slinewidth;

         slinewidth = viewwidth-slinex;
         if (slinewidth<1)
            continue;      // still off the right side
      }
      else
      {
         if (slinewidth>slinex)
            slinewidth = slinex;
         slinex -= slinewidth;
      }

      leftvis = (wallheight[slinex] < height);
      rightvis = (wallheight[slinex+slinewidth-1] < height);

      if (leftvis)
      {
         if (rightvis)
            ScaleLine ();
         else
         {
            while (wallheight[slinex+slinewidth-1] >= height)
               slinewidth--;

            ScaleLine ();
         }
      }
      else
      {
         if (!rightvis)
            continue;      // totally obscured

         while (wallheight[slinex] >= height)
         {
            slinex++;
            slinewidth--;
         }

         ScaleLine ();
         break;         // the rest of the shape is gone
      }
      
      if (!srcx)
          break;

   }

And the same again in SimpleScaleShape:

::: CODE :::
   while ( --srcx >= stopx )
   {
        (unsigned)linecmds = *cmdptr--;
      if ( !(slinewidth = comptable->width[srcx]) )
         continue;

        slinex -= slinewidth;

      ScaleLine ();

        if (!srcx)
            break;

   }

Be sure to only modify the first while loop in both routines; there's nothing wrong with the "scale to the right" loops. Alright, now with that done, let's fix the bug that causes all kinds of weird stuff to happen when only the left half of the sprite has solid pixels (you may have noticed that no original Wolf3D sprites are like this!)

Back in ScaleShape, add the red code to the first while loop:

::: CODE :::
   while ( --srcx >=stopx && slinex>0)
   {
      (unsigned)linecmds = *cmdptr--;
      if ( !(slinewidth = comptable->width[srcx]) )
         continue;

      if (slinewidth == 1)
      {
         slinex--;

            if (srcx > shape->rightpix)
                continue;


         if (slinex<viewwidth)
         {
            if (wallheight[slinex] >= height)
               continue;      // obscured by closer wall
            ScaleLine ();
         }
         continue;
      }

      //
      // handle multi pixel lines
      //
      if (slinex>viewwidth)
      {
         slinex -= slinewidth;

         slinewidth = viewwidth-slinex;
         if (slinewidth<1)
            continue;      // still off the right side
      }
      else
      {
         if (slinewidth>slinex)
            slinewidth = slinex;
         slinex -= slinewidth;
      }

      leftvis = (wallheight[slinex] < height);
      rightvis = (wallheight[slinex+slinewidth-1] < height);

      if (leftvis)
      {
         if (rightvis && srcx <= shape->rightpix)
            ScaleLine ();
         else
         {
            while (wallheight[slinex+slinewidth-1] >= height)
               slinewidth--;

                if (srcx > shape->rightpix)
                    continue;


            ScaleLine ();
         }
      }
      else
      {
         if (!rightvis)
            continue;      // totally obscured

         while (wallheight[slinex] >= height)
         {
            slinex++;
            slinewidth--;
         }

            if (srcx > shape->rightpix)
                continue;


         ScaleLine ();
         break;         // the rest of the shape is gone
      }
      
      if (!srcx)
          break;
   }

And then in SimpleScaleShape:
::: CODE :::
   while ( --srcx >= stopx )
   {
        (unsigned)linecmds = *cmdptr--;
      if ( !(slinewidth = comptable->width[srcx]) )
         continue;

        slinex -= slinewidth;

        if (srcx > shape->rightpix)
            continue;


      ScaleLine ();

        if (!srcx)
            break;
   }

And that's it. I'm not sure how these slipped past John Carmack, because they're extremely noticeable bugs when they occur ingame. I wonder if by a happy chance he never even noticed it because none of the original sprites had pixels that touched the left edge or only filled the left half.

I don't know if anyone still cares about DOS, but I still enjoy tinkering with the original code... And this was one of the oldest and weirdest bugs in the original game, despite not being an issue without modification. I guess we've moved on from it now though, what with DarkOne's fix, and more prominently Ripper's "removing the scalers" code that rewrote the ScaleShape code altogether. Still though, that's two bugs less in the original! Laughing

I'd like to give a shout out to DarkOne for the 2nd bugfix, since I got the idea to add those lines from looking at his NewWolf classic code.

Long Live DOS!
AryanWolf3D

_________________
"Way too many #ifdefs in the code!" - John Carmack
gerolf
DieHard Wolfer
DieHard Wolfer


Joined: 28 Jan 2010
Last Visit: 09 Dec 2019

Topics: 162
Posts: 1115
Location: Virginia
usa.gif

PostPosted: Sun Nov 24, 2019 5:44 pm
   Subject: Re: ScaleShape bugfix
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Previous PostGoto Bottom of Posts

Thanks, AryanWolf <3

This is a great fix!

_________________
Display posts from previous:   
Post new topicReply to topic Time synchronized with the forum server time
DieHard Wolfers Forum Index -> Code Crackers View Previous TopicRefresh this PageAdd Topic to your Browser FavoritesSearch ForumsPrint this TopicE-mail TopicGoto Page TopView Next Topic
Page 1 of 1
Jump to:  

Related topics
 Topics   Replies   Views   Last Post 
No new posts [Info] Black & White Effect - Tutorial
Author: Guest
10 299 Thu Mar 17, 2005 6:24 pm
Dugtrio17 View latest post
No new posts [Code] Run with Stamina - TekZK
Author: BrotherTank
8 3840 Sun May 16, 2004 12:54 am
Codetech84 View latest post
This topic is locked: you cannot edit posts or make replies. [Info] Source code for Darkone's NewWolf Classic
Author: Raistlin
1 2141 Tue Feb 10, 2004 10:18 am
BrotherTank View latest post
No new posts [Info] Assigning Static Objects problem.
Author: Guest
1 104 Sun Jul 06, 2003 1:25 pm
Guest View latest post
No new posts [Info] Alarm Sounding in game?? WSJ...??
Author: Guest
7 311 Tue Jun 17, 2003 10:04 pm
Reivax44 View latest post
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
   You cannot delete your posts in this forum
You cannot vote in polls in this forum


Copyright ©2003-2008 DieHard Wolfers
A Modified subBunker Theme by BrotherTank
Powered by phpBB © 2001, 2005 phpBB Group