mirror of
https://github.com/retro100/dosbox-wii.git
synced 2024-11-16 15:19:15 +01:00
215 lines
6.9 KiB
C++
215 lines
6.9 KiB
C++
/*
|
|
* Copyright (C) 2002-2019 The DOSBox Team
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
|
|
#include "dosbox.h"
|
|
#include "callback.h"
|
|
#include "mem.h"
|
|
#include "regs.h"
|
|
#include "dos_inc.h"
|
|
#include <list>
|
|
|
|
|
|
static Bitu call_int2f,call_int2a;
|
|
|
|
static std::list<MultiplexHandler*> Multiplex;
|
|
typedef std::list<MultiplexHandler*>::iterator Multiplex_it;
|
|
|
|
void DOS_AddMultiplexHandler(MultiplexHandler * handler) {
|
|
Multiplex.push_front(handler);
|
|
}
|
|
|
|
void DOS_DelMultiplexHandler(MultiplexHandler * handler) {
|
|
for(Multiplex_it it =Multiplex.begin();it != Multiplex.end();it++) {
|
|
if(*it == handler) {
|
|
Multiplex.erase(it);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
static Bitu INT2F_Handler(void) {
|
|
for(Multiplex_it it = Multiplex.begin();it != Multiplex.end();it++)
|
|
if( (*it)() ) return CBRET_NONE;
|
|
|
|
LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Multiplex Unhandled call %4X",reg_ax);
|
|
return CBRET_NONE;
|
|
}
|
|
|
|
|
|
static Bitu INT2A_Handler(void) {
|
|
return CBRET_NONE;
|
|
}
|
|
|
|
static bool DOS_MultiplexFunctions(void) {
|
|
switch (reg_ax) {
|
|
case 0x1216: /* GET ADDRESS OF SYSTEM FILE TABLE ENTRY */
|
|
// reg_bx is a system file table entry, should coincide with
|
|
// the file handle so just use that
|
|
LOG(LOG_DOSMISC,LOG_ERROR)("Some BAD filetable call used bx=%X",reg_bx);
|
|
if(reg_bx <= DOS_FILES) CALLBACK_SCF(false);
|
|
else CALLBACK_SCF(true);
|
|
if (reg_bx<16) {
|
|
RealPt sftrealpt=mem_readd(Real2Phys(dos_infoblock.GetPointer())+4);
|
|
PhysPt sftptr=Real2Phys(sftrealpt);
|
|
Bitu sftofs=0x06+reg_bx*0x3b;
|
|
|
|
if (Files[reg_bx]) mem_writeb(sftptr+sftofs,Files[reg_bx]->refCtr);
|
|
else mem_writeb(sftptr+sftofs,0);
|
|
|
|
if (!Files[reg_bx]) return true;
|
|
|
|
Bit32u handle=RealHandle(reg_bx);
|
|
if (handle>=DOS_FILES) {
|
|
mem_writew(sftptr+sftofs+0x02,0x02); // file open mode
|
|
mem_writeb(sftptr+sftofs+0x04,0x00); // file attribute
|
|
mem_writew(sftptr+sftofs+0x05,Files[reg_bx]->GetInformation()); // device info word
|
|
mem_writed(sftptr+sftofs+0x07,0); // device driver header
|
|
mem_writew(sftptr+sftofs+0x0d,0); // packed time
|
|
mem_writew(sftptr+sftofs+0x0f,0); // packed date
|
|
mem_writew(sftptr+sftofs+0x11,0); // size
|
|
mem_writew(sftptr+sftofs+0x15,0); // current position
|
|
} else {
|
|
Bit8u drive=Files[reg_bx]->GetDrive();
|
|
|
|
mem_writew(sftptr+sftofs+0x02,(Bit16u)(Files[reg_bx]->flags&3)); // file open mode
|
|
mem_writeb(sftptr+sftofs+0x04,(Bit8u)(Files[reg_bx]->attr)); // file attribute
|
|
mem_writew(sftptr+sftofs+0x05,0x40|drive); // device info word
|
|
mem_writed(sftptr+sftofs+0x07,RealMake(dos.tables.dpb,drive*9)); // dpb of the drive
|
|
mem_writew(sftptr+sftofs+0x0d,Files[reg_bx]->time); // packed file time
|
|
mem_writew(sftptr+sftofs+0x0f,Files[reg_bx]->date); // packed file date
|
|
Bit32u curpos=0;
|
|
Files[reg_bx]->Seek(&curpos,DOS_SEEK_CUR);
|
|
Bit32u endpos=0;
|
|
Files[reg_bx]->Seek(&endpos,DOS_SEEK_END);
|
|
mem_writed(sftptr+sftofs+0x11,endpos); // size
|
|
mem_writed(sftptr+sftofs+0x15,curpos); // current position
|
|
Files[reg_bx]->Seek(&curpos,DOS_SEEK_SET);
|
|
}
|
|
|
|
// fill in filename in fcb style
|
|
// (space-padded name (8 chars)+space-padded extension (3 chars))
|
|
const char* filename=(const char*)Files[reg_bx]->GetName();
|
|
if (strrchr(filename,'\\')) filename=strrchr(filename,'\\')+1;
|
|
if (strrchr(filename,'/')) filename=strrchr(filename,'/')+1;
|
|
if (!filename) return true;
|
|
const char* dotpos=strrchr(filename,'.');
|
|
if (dotpos) {
|
|
dotpos++;
|
|
size_t nlen=strlen(filename);
|
|
size_t extlen=strlen(dotpos);
|
|
Bits nmelen=(Bits)nlen-(Bits)extlen;
|
|
if (nmelen<1) return true;
|
|
nlen-=(extlen+1);
|
|
|
|
if (nlen>8) nlen=8;
|
|
size_t i;
|
|
|
|
for (i=0; i<nlen; i++)
|
|
mem_writeb((PhysPt)(sftptr+sftofs+0x20+i),filename[i]);
|
|
for (i=nlen; i<8; i++)
|
|
mem_writeb((PhysPt)(sftptr+sftofs+0x20+i),' ');
|
|
|
|
if (extlen>3) extlen=3;
|
|
for (i=0; i<extlen; i++)
|
|
mem_writeb((PhysPt)(sftptr+sftofs+0x28+i),dotpos[i]);
|
|
for (i=extlen; i<3; i++)
|
|
mem_writeb((PhysPt)(sftptr+sftofs+0x28+i),' ');
|
|
} else {
|
|
size_t i;
|
|
size_t nlen=strlen(filename);
|
|
if (nlen>8) nlen=8;
|
|
for (i=0; i<nlen; i++)
|
|
mem_writeb((PhysPt)(sftptr+sftofs+0x20+i),filename[i]);
|
|
for (i=nlen; i<11; i++)
|
|
mem_writeb((PhysPt)(sftptr+sftofs+0x20+i),' ');
|
|
}
|
|
|
|
SegSet16(es,RealSeg(sftrealpt));
|
|
reg_di=RealOff(sftrealpt+sftofs);
|
|
reg_ax=0xc000;
|
|
|
|
}
|
|
return true;
|
|
case 0x1607:
|
|
if (reg_bx == 0x15) {
|
|
switch (reg_cx) {
|
|
case 0x0000: // query instance
|
|
reg_cx = 0x0001;
|
|
reg_dx = 0x50; // dos driver segment
|
|
SegSet16(es,0x50); // patch table seg
|
|
reg_bx = 0x60; // patch table ofs
|
|
return true;
|
|
case 0x0001: // set patches
|
|
reg_ax = 0xb97c;
|
|
reg_bx = (reg_dx & 0x16);
|
|
reg_dx = 0xa2ab;
|
|
return true;
|
|
case 0x0003: // get size of data struc
|
|
if (reg_dx==0x0001) {
|
|
// CDS size requested
|
|
reg_ax = 0xb97c;
|
|
reg_dx = 0xa2ab;
|
|
reg_cx = 0x000e; // size
|
|
}
|
|
return true;
|
|
case 0x0004: // instanced data
|
|
reg_dx = 0; // none
|
|
return true;
|
|
case 0x0005: // get device driver size
|
|
reg_ax = 0;
|
|
reg_dx = 0;
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
else if (reg_bx == 0x18) return true; // idle callout
|
|
else return false;
|
|
case 0x1680: /* RELEASE CURRENT VIRTUAL MACHINE TIME-SLICE */
|
|
//TODO Maybe do some idling but could screw up other systems :)
|
|
return true; //So no warning in the debugger anymore
|
|
case 0x1689: /* Kernel IDLE CALL */
|
|
case 0x168f: /* Close awareness crap */
|
|
/* Removing warning */
|
|
return true;
|
|
case 0x4a01: /* Query free hma space */
|
|
case 0x4a02: /* ALLOCATE HMA SPACE */
|
|
LOG(LOG_DOSMISC,LOG_WARN)("INT 2f:4a HMA. DOSBox reports none available.");
|
|
reg_bx=0; //number of bytes available in HMA or amount successfully allocated
|
|
//ESDI=ffff:ffff Location of HMA/Allocated memory
|
|
SegSet16(es,0xffff);
|
|
reg_di=0xffff;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void DOS_SetupMisc(void) {
|
|
/* Setup the dos multiplex interrupt */
|
|
call_int2f=CALLBACK_Allocate();
|
|
CALLBACK_Setup(call_int2f,&INT2F_Handler,CB_IRET,"DOS Int 2f");
|
|
RealSetVec(0x2f,CALLBACK_RealPointer(call_int2f));
|
|
DOS_AddMultiplexHandler(DOS_MultiplexFunctions);
|
|
/* Setup the dos network interrupt */
|
|
call_int2a=CALLBACK_Allocate();
|
|
CALLBACK_Setup(call_int2a,&INT2A_Handler,CB_IRET,"DOS Int 2a");
|
|
RealSetVec(0x2A,CALLBACK_RealPointer(call_int2a));
|
|
}
|