ref: d610772a0b58e63f665403386f167b3e19a5dcfd
parent: ed4adeba77bf7dd803e7b944ee5f871965a0ca29
author: Simon Howard <[email protected]>
date: Wed Mar 9 14:02:15 EST 2011
Add null sector dereference emulation code from Prboom+, to fix desync with CLNJ-506.LMP (thanks entryway). Subversion-branch: /trunk/chocolate-doom Subversion-revision: 2298
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,9 @@
* Very short sound effects are not played, to better emulate the
behavior of DMX in Vanilla Doom (thanks to Quasar for help in
investigating this).
+ * The null sector dereference emulation code has been imported
+ from Prboom+ - this fixes a desync with CLNJ-506.LMP (thanks
+ entryway).
Bugs fixed:
* Menu navigation when using joystick/joypad (thanks Alexandre
--- a/src/i_system.c
+++ b/src/i_system.c
@@ -369,3 +369,109 @@
exit(-1);
}
+//
+// Read Access Violation emulation.
+//
+// From PrBoom+, by entryway.
+//
+
+// C:\>debug
+// -d 0:0
+//
+// DOS 6.22:
+// 0000:0000 (57 92 19 00) F4 06 70 00-(16 00)
+// DOS 7.1:
+// 0000:0000 (9E 0F C9 00) 65 04 70 00-(16 00)
+// Win98:
+// 0000:0000 (9E 0F C9 00) 65 04 70 00-(16 00)
+// DOSBox under XP:
+// 0000:0000 (00 00 00 F1) ?? ?? ?? 00-(07 00)
+
+#define DOS_MEM_DUMP_SIZE 10
+
+static const unsigned char mem_dump_dos622[DOS_MEM_DUMP_SIZE] = {
+ 0x57, 0x92, 0x19, 0x00, 0xF4, 0x06, 0x70, 0x00, 0x16, 0x00};
+static const unsigned char mem_dump_win98[DOS_MEM_DUMP_SIZE] = {
+ 0x9E, 0x0F, 0xC9, 0x00, 0x65, 0x04, 0x70, 0x00, 0x16, 0x00};
+static const unsigned char mem_dump_dosbox[DOS_MEM_DUMP_SIZE] = {
+ 0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00};
+static unsigned char mem_dump_custom[DOS_MEM_DUMP_SIZE];
+
+static const unsigned char *dos_mem_dump = mem_dump_dos622;
+
+boolean I_GetMemoryValue(unsigned int offset, void *value, int size)
+{
+ static boolean firsttime = true;
+
+ if (firsttime)
+ {
+ int p, i, val;
+
+ firsttime = false;
+ i = 0;
+
+ //!
+ // @category compat
+ // @arg <version>
+ //
+ // Specify DOS version to emulate for NULL pointer dereference
+ // emulation. Supported versions are: dos622, dos71, dosbox.
+ // The default is to emulate DOS 7.1 (Windows 98).
+ //
+
+ p = M_CheckParmWithArgs("-setmem", 1);
+
+ if (p > 0)
+ {
+ if (!strcasecmp(myargv[p + 1], "dos622"))
+ {
+ dos_mem_dump = mem_dump_dos622;
+ }
+ if (!strcasecmp(myargv[p + 1], "dos71"))
+ {
+ dos_mem_dump = mem_dump_win98;
+ }
+ else if (!strcasecmp(myargv[p + 1], "dosbox"))
+ {
+ dos_mem_dump = mem_dump_dosbox;
+ }
+ else
+ {
+ for (i = 0; i < DOS_MEM_DUMP_SIZE; ++i)
+ {
+ ++p;
+
+ if (p >= myargc || myargv[p][0] == '-')
+ {
+ break;
+ }
+
+ M_StrToInt(myargv[p], &val);
+ mem_dump_custom[i++] = (unsigned char) val;
+ }
+
+ dos_mem_dump = mem_dump_custom;
+ }
+ }
+ }
+
+ switch (size)
+ {
+ case 1:
+ *((unsigned char *) value) = dos_mem_dump[offset];
+ return true;
+ case 2:
+ *((unsigned short *) value) = dos_mem_dump[offset]
+ | (dos_mem_dump[offset + 1] << 8);
+ return true;
+ case 4:
+ *((unsigned int *) value) = dos_mem_dump[offset]
+ | (dos_mem_dump[offset + 1] << 8)
+ | (dos_mem_dump[offset + 2] << 16)
+ | (dos_mem_dump[offset + 3] << 24);
+ return true;
+ }
+
+ return false;
+}
+
--- a/src/i_system.h
+++ b/src/i_system.h
@@ -86,6 +86,7 @@
void I_Error (char *error, ...);
+boolean I_GetMemoryValue(unsigned int offset, void *value, int size);
#endif
--- a/src/p_map.c
+++ b/src/p_map.c
@@ -885,17 +885,8 @@
dist = FixedMul (attackrange, in->frac);
- // Return false if there is no back sector. This should never
- // be the case if the line is two-sided; however, some WADs
- // (eg. ottawau.wad) use this as an "impassible glass" trick
- // and rely on Vanilla Doom's (unintentional) support for this.
-
- if (li->backsector == NULL)
- {
- return false;
- }
-
- if (li->frontsector->floorheight != li->backsector->floorheight)
+ if (li->backsector == NULL
+ || li->frontsector->floorheight != li->backsector->floorheight)
{
slope = FixedDiv (openbottom - shootz , dist);
if (slope > bottomslope)
@@ -902,7 +893,8 @@
bottomslope = slope;
}
- if (li->frontsector->ceilingheight != li->backsector->ceilingheight)
+ if (li->backsector == NULL
+ || li->frontsector->ceilingheight != li->backsector->ceilingheight)
{
slope = FixedDiv (opentop - shootz , dist);
if (slope < topslope)
@@ -983,26 +975,35 @@
dist = FixedMul (attackrange, in->frac);
- // Check if backsector is NULL. See comment in PTR_AimTraverse.
+ // e6y: emulation of missed back side on two-sided lines.
+ // backsector can be NULL when emulating missing back side.
- if (li->backsector == NULL)
+ if (li->backsector == NULL)
{
- goto hitline;
+ slope = FixedDiv (openbottom - shootz , dist);
+ if (slope > aimslope)
+ goto hitline;
+
+ slope = FixedDiv (opentop - shootz , dist);
+ if (slope < aimslope)
+ goto hitline;
}
+ else
+ {
+ if (li->frontsector->floorheight != li->backsector->floorheight)
+ {
+ slope = FixedDiv (openbottom - shootz , dist);
+ if (slope > aimslope)
+ goto hitline;
+ }
- if (li->frontsector->floorheight != li->backsector->floorheight)
- {
- slope = FixedDiv (openbottom - shootz , dist);
- if (slope > aimslope)
- goto hitline;
- }
-
- if (li->frontsector->ceilingheight != li->backsector->ceilingheight)
- {
- slope = FixedDiv (opentop - shootz , dist);
- if (slope < aimslope)
- goto hitline;
- }
+ if (li->frontsector->ceilingheight != li->backsector->ceilingheight)
+ {
+ slope = FixedDiv (opentop - shootz , dist);
+ if (slope < aimslope)
+ goto hitline;
+ }
+ }
// shot continues
return true;
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -155,8 +155,25 @@
W_ReleaseLumpNum(lump);
}
+//
+// GetSectorAtNullAddress
+//
+sector_t* GetSectorAtNullAddress(void)
+{
+ static boolean null_sector_is_initialized = false;
+ static sector_t null_sector;
+ if (!null_sector_is_initialized)
+ {
+ memset(&null_sector, 0, sizeof(null_sector));
+ I_GetMemoryValue(0, &null_sector.floorheight, 4);
+ I_GetMemoryValue(4, &null_sector.ceilingheight, 4);
+ null_sector_is_initialized = true;
+ }
+ return &null_sector;
+}
+
//
// P_LoadSegs
//
@@ -204,10 +221,12 @@
if (sidenum < 0 || sidenum >= numsides)
{
- sidenum = 0;
+ li->backsector = GetSectorAtNullAddress();
}
-
- li->backsector = sides[sidenum].sector;
+ else
+ {
+ li->backsector = sides[sidenum].sector;
+ }
}
else
{