diff options
author | Simon Howard | 2011-03-09 19:02:15 +0000 |
---|---|---|
committer | Simon Howard | 2011-03-09 19:02:15 +0000 |
commit | d610772a0b58e63f665403386f167b3e19a5dcfd (patch) | |
tree | 9deb16bac7c58f71eeecc34f16619afdc0bb81bd | |
parent | ed4adeba77bf7dd803e7b944ee5f871965a0ca29 (diff) | |
download | chocolate-doom-d610772a0b58e63f665403386f167b3e19a5dcfd.tar.gz chocolate-doom-d610772a0b58e63f665403386f167b3e19a5dcfd.tar.bz2 chocolate-doom-d610772a0b58e63f665403386f167b3e19a5dcfd.zip |
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
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | src/i_system.c | 106 | ||||
-rw-r--r-- | src/i_system.h | 1 | ||||
-rw-r--r-- | src/p_map.c | 59 | ||||
-rw-r--r-- | src/p_setup.c | 25 |
5 files changed, 162 insertions, 32 deletions
@@ -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 diff --git a/src/i_system.c b/src/i_system.c index 9f599192..4db97276 100644 --- a/src/i_system.c +++ b/src/i_system.c @@ -369,3 +369,109 @@ void I_Error (char *error, ...) 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; +} + diff --git a/src/i_system.h b/src/i_system.h index a5e06a50..06e7f662 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -86,6 +86,7 @@ void I_Tactile (int on, int off, int total); void I_Error (char *error, ...); +boolean I_GetMemoryValue(unsigned int offset, void *value, int size); #endif diff --git a/src/p_map.c b/src/p_map.c index 1ac76349..cac44dd2 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -885,24 +885,16 @@ PTR_AimTraverse (intercept_t* in) 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) 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 @@ boolean PTR_ShootTraverse (intercept_t* in) 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; - 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; - } + 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->ceilingheight != li->backsector->ceilingheight) + { + slope = FixedDiv (opentop - shootz , dist); + if (slope < aimslope) + goto hitline; + } + } // shot continues return true; diff --git a/src/p_setup.c b/src/p_setup.c index 3fc95cab..e18ec81e 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -155,7 +155,24 @@ void P_LoadVertexes (int lump) 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 @@ void P_LoadSegs (int lump) if (sidenum < 0 || sidenum >= numsides) { - sidenum = 0; + li->backsector = GetSectorAtNullAddress(); + } + else + { + li->backsector = sides[sidenum].sector; } - - li->backsector = sides[sidenum].sector; } else { |