Sunday, February 16, 2014

Patching DOSBox by a Beginner for Beginners

In order to apply a patch to DOSBox, you must first be able to compile DOSBox from its source.  Start with this tutorial :

http://www.dosbox.com/wiki/Building_DOSBox_with_Visual_C_2008_Express

The link for Visual C++ 2008 Express given in that tutorial is out of date, you can obtain the downloader from here :

http://go.microsoft.com/?linkid=7729279

When you can compile a binary using the current SVN, then you are ready to begin patching DOSBox.

Patching DOSBox means you are making changes in the existing source code and recompiling DOSBox with those changes into a new binary.  First you need a copy of the source code you are modifying.  DOSBox is written in C++ and the source code is in almost plain text.  You can find the latest source here : http://source.dosbox.com/dosboxsvn.tgz.  Decompress it with a program like 7zip (it is doubly compressed), and look at the files.  The .cpp files contain most of the code you may be modifying.  

Next you need a good text editor, preferably one that supports line numbers.  Notepad just does not support enough of the formatting these files need.  Wordpad does, but you would do better with an editor like EditPad Lite 7, which supports line numbering.  Line numbering is very useful to determine which lines of code you need to modify.  

Finally, you need a patch file.  Patch files often use the .diff extension because they show the differences between two files or two sets of files.  If the patch is just code posted in a forum, you should copy and paste it into a new file opened in Wordpad or EditPad or something similar.  Maintaining the spacing in these files is important.  

Here is a sample patch file against the current DOSBox SVN (r3858) :  

--- adlib.cpp.old   2013-01-15 12:10:04 +0000
+++ adlib.cpp   2014-01-19 19:54:06 +0000
@@ -227,10 +227,10 @@
       Bitu i, val;
       /* Check the registers to add */
       for (i=0;i<256 font="" i="">
-         //Skip the note on entries
-         if (i>=0xb0 && i<=0xb8) 
-            continue;
          val = (*cache)[ i ];
+         //Silence the note on entries
+         if (i>=0xb0 && i<=0xb8) 
+            val &= ~0x20;
          if (val) {
             AddWrite( i, val );
          }

The first two lines identify the source file that was modified, in this case adlib.cpp.  Find and open adlib.cpp using your text editor in the DOSBox source directory.  It can be found in \dosbox\src\hardware.  This is what the existing source code looks like :

Bitu i, val;
/* Check the registers to add */
for (i=0;i<256 font="" i="">
//Skip the note on entries
if (i>=0xb0 && i<=0xb8) 
continue;
val = (*cache)[ i ];
if (val) {
AddWrite( i, val );
}

The next line in the patch file, @@ -227,10 +227,10 @@ pinpoints the lines in adlib.cpp that were modified.  Look for line 227 in the source code file or search   Sometimes, depending on the patcher's working source, the line number may not line up exactly with the DOSBox source, but it should be very close to the line.  Sometimes code looks similar, if you are unsure whether you have the right code, then copy as much of the code from the patch file as you can into a find box and search the source code file until you are sure you have the right lines.  

The lines with blank space in front of them show the existing code that will not be modified.  This is important to know where you will begin to modify and where you will end.  Lines beginning a - indicate that that line was deleted by the patch.  Conversely, lines beginning with a + indicate that that line was added by the patch.  From our example above, these lines were deleted : 

-         //Skip the note on entries
-         if (i>=0xb0 && i<=0xb8) 
-            continue;

In the original source file, highlight and delete them.  Remove the lines entirely so the code looks like this :

       Bitu i, val;
       /* Check the registers to add */
       for (i=0;i<256 font="" i="">
          val = (*cache)[ i ];

Now add these lines after val = (*cache)[ i ]; :

          //Silence the note on entries
          if (i>=0xb0 && i<=0xb8) 
             val &= ~0x20;

Copying and pasting usually gives better results than retyping.  Make sure the code fits where it is indicated and does not overwrite any lines without a - in front of them.  Also make sure, since your text editor must be using a fixed-width font, that the lines line up vertically as shown in the patch.  Do not forget the { and }.  The + characters also should be removed, and add an extra space to the line to preserve the code's position on the line.  Here is the code as it should look in the patched adlib.cpp file :

       Bitu i, val;
       /* Check the registers to add */
       for (i=0;i<256 font="" i="">
          val = (*cache)[ i ];
          //Silence the note on entries
          if (i>=0xb0 && i<=0xb8) 
             val &= ~0x20;
          if (val) {
             AddWrite( i, val );
          }

Once you are done, save the modified .cpp file.  There may be more than one place in the .cpp file to patch, so go to the next line indicator, which looks like @@ -227,10 +227,10 @@ and continue patching. .diff files can include more than one source code file to patch, so make sure you patch all source code files indicated by the .diff.  

Go back into Visual C++ 2008 Express Edition, open the DOSBox solution, and build a new binary.  If you have previously built a binary, then it will not take long as only the changes made by the patch need to be recompiled.  

While there are utilities that can do this for you, I have never gotten one to work properly and sometimes the line numbers do not match and you need to manually patch the code.  

More complex patches may require substantial modifications to the code, or may also require adding completely new code files.  They may also require new libraries and includes files, which are beyond the scope of this tutorial.  

No comments: