Skip to content

Commit

Permalink
INT 21h: Add option whether to assign MCB ownership or return an erro…
Browse files Browse the repository at this point in the history
…r if a DOS program attempts to resize a freed memory block. Fix DOS resize to assign ownership even if the MCB is already the size requested to resize to.
  • Loading branch information
joncampbell123 committed Apr 16, 2024
1 parent 2d4fedd commit 641c696
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 1 deletion.
8 changes: 8 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
Next:
- INT 21h: If a DOS program frees a memory block, and then resizes the
freed memory block, reassign ownership of that block to the program
as if allocated. This is apparently canonical MS-DOS behavior. Added
dosbox.conf option to control whether resizing a freed block silently
assigns ownership (default setting) or whether it returns an error.
DOS resize memory function for the most part DID assign ownership but
not in the case where the size of the MCB was exactly the size requested
to resize to. (joncampbell123).
- Sound Blaster: Fix bug where "force autoinit" prevented Sound Blaster
playback from working at all, fix for "Jump" by Public NMI (joncampbell123).
- Debugger UI now shows PIC_FullIndex() and whether or not the CPU is
Expand Down
2 changes: 2 additions & 0 deletions src/dos/dos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ bool enable_dbcs_tables = true;
bool enable_share_exe = true;
bool enable_filenamechar = true;
bool shell_keyboard_flush = true;
bool freed_mcb_allocate_on_resize = true;
bool enable_network_redirector = true;
bool force_conversion = false;
bool hidenonrep = true;
Expand Down Expand Up @@ -4110,6 +4111,7 @@ class DOS:public Module_base{
#endif

dos_sda_size = section->Get_int("dos sda size");
freed_mcb_allocate_on_resize = section->Get_bool("resized free memory block becomes allocated");
shell_keyboard_flush = section->Get_bool("command shell flush keyboard buffer");
enable_network_redirector = section->Get_bool("network redirector");
enable_dbcs_tables = section->Get_bool("dbcs");
Expand Down
14 changes: 13 additions & 1 deletion src/dos/dos_memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ bool DOS_AllocateMemory(uint16_t * segment,uint16_t * blocks) {
return false;
}

extern bool freed_mcb_allocate_on_resize;

bool DOS_ResizeMemory(uint16_t segment,uint16_t * blocks) {
if (segment < DOS_MEM_START+1) {
Expand All @@ -349,6 +350,13 @@ bool DOS_ResizeMemory(uint16_t segment,uint16_t * blocks) {
return false;
}

if (mcb.GetPSPSeg()==MCB_FREE && !freed_mcb_allocate_on_resize) {
*blocks=0;
DOS_SetError(DOSERR_MCB_DESTROYED);
LOG(LOG_DOSMISC,LOG_DEBUG)("DOS application attempted to resize freed memory block at segment 0x%x",(unsigned int)segment);
return false;
}

uint16_t total=mcb.GetSize();
DOS_MCB mcb_next(segment+total);

Expand All @@ -359,7 +367,10 @@ bool DOS_ResizeMemory(uint16_t segment,uint16_t * blocks) {

if (*blocks<=total) {
if (GCC_UNLIKELY(*blocks==total)) {
/* Nothing to do */
/* Nothing to do, however if the block is freed, canonical MS-DOS behavior is to assign your PSP segment as if allocated (Incentiv by DID, party '94) */
if (mcb.GetPSPSeg()==MCB_FREE && freed_mcb_allocate_on_resize)
mcb.SetPSPSeg(dos.psp());

return true;
}
/* Shrinking MCB */
Expand Down Expand Up @@ -405,6 +416,7 @@ bool DOS_ResizeMemory(uint16_t segment,uint16_t * blocks) {
/* adjust type of joined MCB */
mcb.SetType(mcb_next.GetType());
}

mcb.SetSize(total);
mcb.SetPSPSeg(dos.psp());
if (*blocks==total) return true; /* block fit exactly */
Expand Down
4 changes: 4 additions & 0 deletions src/dosbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4229,6 +4229,10 @@ void DOSBOX_SetupConfigSections(void) {
Pbool->Set_help("Enable XMS support.");
Pbool->SetBasic(true);

Pbool = secprop->Add_bool("resized free memory block becomes allocated",Property::Changeable::WhenIdle,true);
Pbool->Set_help("If set, and the DOS application resizes a freed memory block, that block will be marked as allocated to that program.\n"
"MS-DOS behaves in this manner, apparently.");

Pint = secprop->Add_int("xms handles",Property::Changeable::WhenIdle,0);
Pint->Set_help("Number of XMS handles available for the DOS environment, or 0 to use a reasonable default");
Pint->SetBasic(true);
Expand Down

0 comments on commit 641c696

Please sign in to comment.