Skip to content

Commit

Permalink
ISA 15MB memory hole option, especially for PC-98 games
Browse files Browse the repository at this point in the history
  • Loading branch information
joncampbell123 committed Oct 9, 2023
1 parent dc9e0ff commit cdcfb55
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
Next:
- Change ISA memory hole 512kb option from boolean to true/false/auto.
- Add ISA memory hole 15mb option, make it true/false/auto. Auto
means off for IBM compatible mode and on for PC-9821 compatible mode.
This should allow some DOS games that depend on the linear framebuffer
to work properly even if memsize=16 or higher.

2023.10.06
- Add "VRD" debugger command to force redraw of the VGA screen.
Expand Down
6 changes: 6 additions & 0 deletions src/dosbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1804,6 +1804,12 @@ void DOSBOX_SetupConfigSections(void) {
Pstring->Set_values(truefalseautoopt);
Pstring->Set_help("If set, emulate an ISA memory hole at the 512KB to 640KB area (0x80000-0x9FFFF).");

Pstring = secprop->Add_string("isa memory hole at 15mb",Property::Changeable::WhenIdle,"auto");
Pstring->Set_values(truefalseautoopt);
Pstring->Set_help("If set, emulate an ISA memory hole at the 15MB to 16MB area (0xF00000-0xFFFFFF).\n"
"If auto, hole is disabled by default for IBM compatible modes and enabled by default for NEC PC-98 compatible modes.\n"
"The reason for this is that the hole is needed for the PC-9821 256-color mode linear framebuffer to work with some DOS games even when memsize >= 16.");

Pint = secprop->Add_int("reboot delay", Property::Changeable::WhenIdle,-1);
Pint->SetMinMax(-1,10000);
Pint->Set_help(
Expand Down
22 changes: 20 additions & 2 deletions src/hardware/memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ class MEM_callout_vector : public std::vector<MEM_CalloutObject> {

static MEM_callout_vector MEM_callouts[MEM_callouts_max];

extern bool isa_memory_hole_15mb;

bool a20_guest_changeable = true;
bool a20_fake_changeable = false;
bool a20_fast_changeable = false;
Expand Down Expand Up @@ -279,8 +281,13 @@ static PageHandler *MEM_SlowPath(Bitu page) {

/* TEMPORARY, REMOVE LATER. SHOULD NOT HAPPEN. */
if (page < memory.reported_pages) {
LOG(LOG_MISC,LOG_WARN)("MEM_SlowPath called within system RAM at page %x",(unsigned int)page);
f = (PageHandler*)(&ram_page_handler);
if (page >= 0xf00 && page <= 0xfff && isa_memory_hole_15mb) { /* 0xF00000-0xFFFFFF (15MB-16MB) */
/* ignore, ISA memory hole */
}
else {
LOG(LOG_MISC,LOG_WARN)("MEM_SlowPath called within system RAM at page %x",(unsigned int)page);
f = (PageHandler*)(&ram_page_handler);
}
}

/* check motherboard devices (ROM BIOS, system RAM, etc.) */
Expand Down Expand Up @@ -1885,6 +1892,12 @@ void Init_RAM() {
for (;i < memory.handler_pages;i++)
memory.phandlers[i] = NULL;//&illegal_page_handler;

/* ISA 15MB memory hole? */
if (isa_memory_hole_15mb) {
for (i=0xf00;i <= 0xfff && i < memory.handler_pages;i++)
memory.phandlers[i] = NULL;//&illegal_page_handler;
}

/* FIXME: VGA emulation will selectively respond to 0xA0000-0xBFFFF according to the video mode,
* what we want however is for the VGA emulation to assign illegal_page_handler for
* address ranges it is not responding to when mapping changes. */
Expand Down Expand Up @@ -2059,6 +2072,11 @@ void Init_MemHandles() {

for (i = 0;i < memory.pages;i++)
memory.mhandles[i] = 0; //Set to 0 for memory allocation

// ISA memory hole awareness (15MB region). Block off 0xF00000-0xFFFFFF with a dummy handle.
if (isa_memory_hole_15mb) {
for (i=0xF00;i<=0xFFF && i < memory.pages;i++) memory.mhandles[i] = 0x7FFFFFFF;
}
}

void Init_MemoryAccessArray() {
Expand Down
7 changes: 3 additions & 4 deletions src/hardware/vga_memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ extern bool vga_ignore_extended_memory_bit;
extern bool memio_complexity_optimization;
extern bool enable_pc98_256color_planar;
extern bool enable_pc98_256color;
extern bool isa_memory_hole_15mb;

extern unsigned int vbe_window_granularity;
extern unsigned int vbe_window_size;
Expand Down Expand Up @@ -2725,10 +2726,8 @@ void VGA_SetupHandlers(void) {
else
MEM_ResetPageHandler_Unmapped(0xE0, 8);

// TODO: What about PC-9821 systems with more than 15MB of RAM? Do they maintain a "hole"
// in memory for this linear framebuffer? Intel motherboard chipsets of that era do
// support a 15MB memory hole.
if (MEM_TotalPages() <= 0xF00/*FIXME*/) {
/* If the system has 15MB or less RAM, OR the ISA memory hole at 15MB is enabled */
if (MEM_TotalPages() <= 0xF00 || isa_memory_hole_15mb) {
/* F00000-FF7FFFh linear framebuffer (256-packed)
* - Does not exist except in 256-color mode.
* - Switching from 256-color mode immediately unmaps this linear framebuffer.
Expand Down
27 changes: 25 additions & 2 deletions src/ints/bios.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ bool APM_PowerButtonSendsSuspend = true;

bool bochs_port_e9 = false;
bool isa_memory_hole_512kb = false;
bool isa_memory_hole_15mb = false;
bool int15_wait_force_unmask_irq = false;

int unhandled_irq_method = UNHANDLED_IRQ_SIMPLE;
Expand Down Expand Up @@ -7216,11 +7217,17 @@ void BIOS_ZeroExtendedSize(bool in) {
* capacity does not include conventional memory below 1MB, nor any memory
* above 16MB.
*
* PC-98 systems may reserve the top 1MB, limiting the top to 15MB instead.
* PC-98 systems may reserve the top 1MB, limiting the top to 15MB instead,
* for the ISA memory hole needed for DOS games that use the 256-color linear framebuffer.
*
* 0x70 = 128KB * 0x70 = 14MB
* 0x78 = 128KB * 0x70 = 15MB */
if (ext > 0x78) ext = 0x78;
if (isa_memory_hole_15mb) {
if (ext > 0x70) ext = 0x70;
}
else {
if (ext > 0x78) ext = 0x78;
}

mem_writeb(0x401,ext);
}
Expand Down Expand Up @@ -9929,6 +9936,20 @@ class BIOS:public Module_base{
isa_memory_hole_512kb = false;
}

// TODO: motherboard init, especially when we get around to full Intel Triton/i440FX chipset emulation
{
std::string s = section->Get_string("isa memory hole at 15mb");

if (s == "true" || s == "1")
isa_memory_hole_15mb = true;
else if (s == "false" || s == "0")
isa_memory_hole_15mb = false;
else if (IS_PC98_ARCH)
isa_memory_hole_15mb = true; // For the sake of some DOS games, enable by default
else
isa_memory_hole_15mb = false;
}

// FIXME: Erm, well this couldv'e been named better. It refers to the amount of conventional memory
// made available to the operating system below 1MB, which is usually DOS.
dos_conventional_limit = (unsigned int)section->Get_int("dos mem limit");
Expand Down Expand Up @@ -10070,6 +10091,8 @@ class BIOS:public Module_base{
if (start < end) MEM_ResetPageHandler_Unmapped(start,end-start);
}

if (isa_memory_hole_15mb) MEM_ResetPageHandler_Unmapped(0xf00,0x100); /* 0xF00000-0xFFFFFF */

if (machine == MCH_TANDY) {
/* Take 16KB off the top for video RAM.
* This value never changes after boot, even if you then use the 16-color modes which then moves
Expand Down

0 comments on commit cdcfb55

Please sign in to comment.