VOGONS


Speedy3D support in DOSBox

Topic actions

First post, by sharangad

User metadata
Rank Oldbie
Rank
Oldbie

Would adding RReady, the Rendition Verité wrapper, for Dosbox or Dosbox-X be allowed for Speedy3D (DOS Rendition)?

RReady is closed source, but I'm hoping to produce a GLiDOS style update to support Speedy3D. I know closed source is evil.

The staging guys didn't want to have anything to do with it (https://github.com/dosbox-staging/dosbox-stag … iscussions/3156). So I just thought I'd ask before attempting anything. This time I'm not even going to play around with the source until I know for sure.

Thanks guys and sorry if I'm offending you with a closed source wrapper.

Developer of RReady - Rendition Verité Wrapper.
https://www.youtube.com/@sharangadayananda

Reply 1 of 77, by DosFreak

User metadata
Rank l33t++
Rank
l33t++

By "allowed" I'm assuming you are wanting gpl code added to those projects to use the closed source wrapper but not code added to dosbox that is not GPL. Main problem is due to dosbox changes ensuring that nothing broke with the wrapper would be difficult......same as with forks that use glide wrappers.

Official dosbox doesn't use any wrappers for the main reason that the maintenance burden is too high for too little gain for a small number of dos games.

https://www.gnu.org/licenses/gpl-faq.html#FSWithNFLibs

The license allows it so likely best case for now is fork the code, assuming that the games you support work except for the required wrapper then if the patch is minimal it probably wouldn't be too much of a burden to maintain the fork. It may not be ideal but at least there would be something there for someone in the future to work on something more open source friendly.

Last edited by DosFreak on 2023-12-01, 12:28. Edited 3 times in total.

How To Ask Questions The Smart Way
Make your games work offline

Reply 2 of 77, by sharangad

User metadata
Rank Oldbie
Rank
Oldbie
DosFreak wrote on 2023-12-01, 11:49:
By "allowed" I'm assuming you are wanting gpl code added to those projects to use the closed source wrapper but not code added t […]
Show full quote

By "allowed" I'm assuming you are wanting gpl code added to those projects to use the closed source wrapper but not code added to dosbox that is not GPL. Main problem is due to dosbox changes ensuring that nothing broke with the wrapper would be difficult......same as with forks that use glide wrappers.

Official dosbox doesn't use any wrappers for the main reason that the maintenance burden is too high for too little gain for a small number of dos games.

https://www.gnu.org/licenses/gpl-faq.html#FSWithNFLibs

The license allows it so likely best case for now is fork the code, assuming that the games you support work except for the required wrapper then if the patch is nimal it probably wouldn't be too much of a burden to maintain the fork.

Thanks @DosFreak. That's what I was hoping for. I'll fork the code.

Developer of RReady - Rendition Verité Wrapper.
https://www.youtube.com/@sharangadayananda

Reply 3 of 77, by sharangad

User metadata
Rank Oldbie
Rank
Oldbie

Hi

Sorry guys. I realise you have other things to deal with but,

I've got a slight problem with heavy debug. I modified it to dump all instructions irrespective of breakpoints by modifying DEBUG_HeavyLogInstruction to store all instructions in a vector and DEBUG_HeavyIsBreakpoint to log them.

The problem is I get dumps like this (registers info. truncated):

05DB:0000030C  call 00000C0D($ + 8fe)                                  
05DB : 0000030C call 00000C0D($ + 8fe)
05DB : 00000C22 repe cmpsw
05DB : 00000C24 pop di
05DB : 0000030F mov[0035], cl ds : [00000035] = 8003
05DB : 0000030F mov[0035], cl ds : [00000035] = 8003
05DB : 00002824 mov[0D66], gs ds : [00000D66] = 0000
05DB : 00002824 mov[0D66], gs ds : [00000D66] = 0000
05DB : 0000283F cmp byte[11F0], 00 ds: [000011F0] = 0000
05DB : 0000283F cmp byte[11F0], 00 ds: [000011F0] = 0000
05DB : 000008CA mov al, 0F
05DB : 000008CA mov al, 0F
05DB : 0000031A smsw ax
05DB : 0000031A smsw ax
05DB : 0000031A smsw ax
05DB : 0000031D or al, 01

The duplicate instructions I get, sometimes DEBUG_HeavyIsBreakpoint is called multiple times for a single instruction.

What I don't get is EIP jumping around like crazy:

05DB : 0000283F  cmp  byte[11F0], 00             ds: [000011F0] = 0000 
05DB : 000008CA mov al, 0F

Sorry about my code. I'm still playing around with it.

I thought it was a problem with my added code, but can't be sure. the new bit is this
fullLog.push_back(inst); (fullLog is a std::vector)
:

void DEBUG_HeavyLogInstruction(void) {

static char empty[23] = { 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,0 };

PhysPt start = GetAddress(SegValue(cs),reg_eip);
char dline[200];
DasmI386(dline, start, reg_eip, cpu.code.big);
char* res = empty;
if (showExtend) {
res = AnalyzeInstruction(dline,false);
if (!res || !(*res)) res = empty;
Bitu reslen = strlen(res);
if (reslen < 22) memset(res + reslen, ' ',22 - reslen);
res[22] = 0;
};

Bitu len = strlen(dline);
if (len < 30) memset(dline + len,' ',30 - len);
dline[30] = 0;

TLogInst & inst = logInst[logCount];
strcpy(inst.dline,dline);
inst.s_cs = SegValue(cs);
inst.eip = reg_eip;
strcpy(inst.res,res);
inst.eax = reg_eax;
inst.ebx = reg_ebx;
inst.ecx = reg_ecx;
inst.edx = reg_edx;
inst.esi = reg_esi;
inst.edi = reg_edi;
inst.ebp = reg_ebp;
inst.esp = reg_esp;
inst.s_ds = SegValue(ds);
inst.s_es = SegValue(es);
inst.s_fs = SegValue(fs);
inst.s_gs = SegValue(gs);
inst.s_ss = SegValue(ss);
inst.c = get_CF()>0;
inst.z = get_ZF()>0;
inst.s = get_SF()>0;
inst.o = get_OF()>0;
inst.a = get_AF()>0;
inst.p = get_PF()>0;
inst.i = GETFLAGBOOL(IF);
fullLog.push_back(inst);

if (++logCount >= LOGCPUMAX) logCount = 0;
};

The new bits here are
//if (logHeavy)
DEBUG_HeavyLogInstruction();
#if LOG_TO_FILE
if(fullLog.size() > 2000)
DEBUG_HeavyWriteLogInstructionRendition();
#endif
:

bool DEBUG_HeavyIsBreakpoint(void) {
static Bitu zero_count = 0;

if (cpuLog) {
if (cpuLogCounter>0) {
LogInstruction(SegValue(cs),reg_eip,cpuLogFile);
cpuLogCounter--;
}
if (cpuLogCounter<=0) {
cpuLogFile.flush();
cpuLogFile.close();
DEBUG_ShowMsg("DEBUG: cpu log LOGCPU.TXT created\n");
cpuLog = false;
DEBUG_EnableDebugger();
return true;
}
}

// LogInstruction
//if (logHeavy)
DEBUG_HeavyLogInstruction();
#if LOG_TO_FILE
if(fullLog.size() > 2000)
DEBUG_HeavyWriteLogInstructionRendition();
#endif

and the logging function which dumps all instructions is (out is a global std::ofstream):

[code]void DEBUG_HeavyWriteLogInstructionRendition(void) {
//if (!logHeavy) return;
//logHeavy = false;

//DEBUG_ShowMsg("DEBUG: writing Rendition Dump.TXT, num %u\n", fullLog.size());

//ofstream out("LOGCPU_INT_CD.TXT");
if (!out.is_open()) {
DEBUG_ShowMsg("DEBUG: Failed.\n");
return;
}
out << hex << noshowbase << setfill('0') << uppercase;
//Bit32u startLog = logCount;
//do {
for (auto &inst : fullLog) {
// Write Instructions
//TLogInst& inst = logInst[startLog];
out << setw(4) << inst.s_cs << ":" << setw(8) << inst.eip << " "
<< inst.dline << " " << inst.res << " EAX:" << setw(8) << inst.eax
<< " EBX:" << setw(8) << inst.ebx << " ECX:" << setw(8) << inst.ecx
<< " EDX:" << setw(8) << inst.edx << " ESI:" << setw(8) << inst.esi
<< " EDI:" << setw(8) << inst.edi << " EBP:" << setw(8) << inst.ebp
<< " ESP:" << setw(8) << inst.esp << " DS:" << setw(4) << inst.s_ds
<< " ES:" << setw(4) << inst.s_es << " FS:" << setw(4) << inst.s_fs
<< " GS:" << setw(4) << inst.s_gs << " SS:" << setw(4) << inst.s_ss
<< " CF:" << inst.c << " ZF:" << inst.z << " SF:" << inst.s
<< " OF:" << inst.o << " AF:" << inst.a << " PF:" << inst.p
<< " IF:" << inst.i << endl;

/* fprintf(f,"%04X:%08X %s %s EAX:%08X EBX:%08X ECX:%08X EDX:%08X ESI:%08X EDI:%08X EBP:%08X ESP:%08X DS:%04X ES:%04X FS:%04X GS:%04X SS:%04X CF:%01X ZF:%01X SF:%01X OF:%01X AF:%01X PF:%01X IF:%01X\n",
logInst[startLog].s_cs,logInst[startLog].eip,logInst[startLog].dline,logInst[startLog].res,logInst[startLog].eax,logInst[startLog].ebx,logInst[startLog].ecx,logInst[startLog].edx,logInst[startLog].esi,logInst[startLog].edi,logInst[startLog].ebp,logInst[startLog].esp,
logInst[startLog].s_ds,logInst[startLog].s_es,logInst[startLog].s_fs,logInst[startLog].s_gs,logInst[startLog].s_ss,
Show last 29 lines
						logInst[startLog].c,logInst[startLog].z,logInst[startLog].s,logInst[startLog].o,logInst[startLog].a,logInst[startLog].p,logInst[startLog].i);*/
//if (++startLog >= LOGCPUMAX) startLog = 0;
//} while (startLog != logCount);
}
fullLog.clear();
//out.close();
//DEBUG_ShowMsg("DEBUG: Done.\n");
};

//#endif
if (zeroProtect) {
Bit32u value = 0;
if (!mem_readd_checked(SegPhys(cs)+reg_eip,&value)) {
if (value == 0) zero_count++;
else zero_count = 0;
}
if (GCC_UNLIKELY(zero_count == 10)) E_Exit("running zeroed code");
}

if (skipFirstInstruction) {
skipFirstInstruction = false;
return false;
}
if (!CBreakpoint::BPoints.empty() && CBreakpoint::CheckBreakpoint(SegValue(cs),reg_eip)) {
return true;
}
return false;
}

The only other thing I've modified is the INT 10h call, to support function (AX=0x158D).

Developer of RReady - Rendition Verité Wrapper.
https://www.youtube.com/@sharangadayananda

Reply 4 of 77, by ripsaw8080

User metadata
Rank DOSBox Author
Rank
DOSBox Author

Make sure you are using the core=normal setting, as the instruction pointer skipping around could be due to the dynamic core that executes blocks of instructions where the debugger can only be active between blocks.

Reply 5 of 77, by sharangad

User metadata
Rank Oldbie
Rank
Oldbie
ripsaw8080 wrote on 2023-12-06, 07:26:

Make sure you are using the core=normal setting, as the instruction pointer skipping around could be due to the dynamic core that executes blocks of instructions where the debugger can only be active between blocks.

Thanks @RipSaw8080!

That did the trick.

Developer of RReady - Rendition Verité Wrapper.
https://www.youtube.com/@sharangadayananda

Reply 6 of 77, by sharangad

User metadata
Rank Oldbie
Rank
Oldbie

Another quick question:

This:

mem_writed(0xF00009FC, 0x00000079);

produces an illegal write error in the console.

I think that's a video BIOS address.

static INLINE void mem_writed_inline(PhysPt address,Bit32u val) {
if ((address & 0xfff)<0xffd) {
HostPt tlb_addr=get_tlb_write(address);
if (tlb_addr) host_writed(tlb_addr+address,val);
else (get_tlb_writehandler(address))->writed(address,val);
} else mem_unalignedwrited(address,val);
}

Would I have to check the address and return address specific values in mem_readd?

Developer of RReady - Rendition Verité Wrapper.
https://www.youtube.com/@sharangadayananda

Reply 7 of 77, by ripsaw8080

User metadata
Rank DOSBox Author
Rank
DOSBox Author

FYI, segment 0xF000 is the system BIOS region, segment 0xC000 is the video BIOS region (for EGA/VGA).

Use phys_write to write to BIOS (read-only) regions, because mem_write cannot.

Perhaps this was your intent:

phys_writed(PhysMake(0xF000, 0x09FC), 0x00000079);

Reply 8 of 77, by sharangad

User metadata
Rank Oldbie
Rank
Oldbie
ripsaw8080 wrote on 2023-12-10, 00:40:
FYI, segment 0xF000 is the system BIOS region, segment 0xC000 is the video BIOS region (for EGA/VGA). […]
Show full quote

FYI, segment 0xF000 is the system BIOS region, segment 0xC000 is the video BIOS region (for EGA/VGA).

Use phys_write to write to BIOS (read-only) regions, because mem_write cannot.

Perhaps this was your intent:

phys_writed(PhysMake(0xF000, 0x09FC), 0x00000079);

Yup that's what I needed. The code reads mem address f00009fc and compares a 32 bit value there . I don't know what that value represents. The value there is Anded (test), checked for less than, on fail compared to 79h.

Need to see what a actual rendition setup returns.

The address 0x9fc with segment 0000 is returned in a video rom bios call int 10h ax=158dh on physical hardware . I *think* this is rendition specific. The net suggests this returns display adapter parameters, but doesn't list anything specific. The segment is offset with 0xf000.

Developer of RReady - Rendition Verité Wrapper.
https://www.youtube.com/@sharangadayananda

Reply 9 of 77, by sharangad

User metadata
Rank Oldbie
Rank
Oldbie
ripsaw8080 wrote on 2023-12-10, 00:40:
Perhaps this was your intent: […]
Show full quote

Perhaps this was your intent:

phys_writed(PhysMake(0xF000, 0x09FC), 0x00000079);

Doesn't this produce 0xF09FC as the address?

static INLINE PhysPt PhysMake(Bit16u seg,Bit16u off) {
return (seg<<4)+off;
}

Developer of RReady - Rendition Verité Wrapper.
https://www.youtube.com/@sharangadayananda

Reply 10 of 77, by sharangad

User metadata
Rank Oldbie
Rank
Oldbie

Also there was a bug with my Turbo C code in that it didn't correctly preserve registers.

It appears to return

CX=some fixed address dependent on the card
DX=C000

On further analysis the actual address games use are:
0x000C0A2C (for a Rendition V2200 reference bios) (Once I get feedback from an actual V1000 board with the new test app, I expect to get CX=0x9FC and DX=C000)

vQuake appears to add 0xF0000000
for an address of 0xF00C0A2C
and Rendition DMATest uses
0x000C0A2C

So PhysMake should be correct. But this isn't the video BIOS. It keeps incrementing the address until it encounters 0x79. If it doesn't it just keeps going.

The V2200 reference BIOS indicates that the address (0xC0000A2C) contains 3 bytes, "Rendition Reference Board", more bytes followed by 'y' (0x79).

V1000 bios indicates that the address (0xC00009FC) contains a chunk of bytes, "PCIRc", more bytes, "Rendition Reference board", more bytes and then 'y'.

[EDIT] It also appears to count how many bytes into the block it took to encounter byte 0x79.

Unless I'm missing something , 0x000C0000 isn't the video bios [EDIT2](unless maybe in real mode).

Developer of RReady - Rendition Verité Wrapper.
https://www.youtube.com/@sharangadayananda

Reply 11 of 77, by ripsaw8080

User metadata
Rank DOSBox Author
Rank
DOSBox Author

Video BIOS is at C000:0000, linear address 0xC00000. My example with PhysMake was based on real mode segment and offset for the system BIOS. Perhaps the apps you are looking at use protected mode, and thus reference 32-bit offsets within a descriptor.

Reply 12 of 77, by sharangad

User metadata
Rank Oldbie
Rank
Oldbie

vQuake and the DMA Test use Dos4GW .

The disassembly appears to show register access to eax, ebx and so on, which I think indicates protected mode.

I *don't* know. x86 assembler was never my forte. I did dabble with VESA BIOS extensions with Turbo C and direct writes to video RAM. I no longer have the source for any of that, though I do have some leftover binaries.

Developer of RReady - Rendition Verité Wrapper.
https://www.youtube.com/@sharangadayananda

Reply 13 of 77, by sharangad

User metadata
Rank Oldbie
Rank
Oldbie

Maybe there's an allocated structure at C0A2C.

But setting the uppermost 32 bit nibble to 0xF should be the system BIOS, unless I'm missing something.

[EDIT] Oops! That should be linear 0x00F00000, not 0xF000000. I've never done any DOS protected mode x86 stuff.

Developer of RReady - Rendition Verité Wrapper.
https://www.youtube.com/@sharangadayananda

Reply 14 of 77, by sharangad

User metadata
Rank Oldbie
Rank
Oldbie

BIOS calls aren't accessible in protected mode because, the CPU boots up in real mode and the BIOS is written to support that.

Could this be a side effect of paging? Not entirely sure what DOS4GW does.

Alternatively could you recommended a decent book on DOS protected mode coding?

[EDIT] There's no video BIOS access on Win32 and I have no idea how memory mapping/paging works on x86.

[EDIT] https://en.wikibooks.org/wiki/X86_Assembly/Protected_Mode seems to help. I have noticed CR<n> references in there.

[EDIT3] I see a lot of lldt and smsw.

Developer of RReady - Rendition Verité Wrapper.
https://www.youtube.com/@sharangadayananda

Reply 15 of 77, by xcomcmdr

User metadata
Rank Oldbie
Rank
Oldbie
sharangad wrote on 2024-01-06, 10:36:

Alternatively could you recommended a decent book on DOS protected mode coding?

https://www.amazon.com/Dos-Windows-Protected- … g/dp/0201632187 Seems like a good book

Reply 17 of 77, by sharangad

User metadata
Rank Oldbie
Rank
Oldbie

Does DOsbox prevent reads from the video BIOS?

For instance:

lea  ebx,[edx+eax]              [illegal]              EAX:000C0000 EBX:001CB3A4 ECX:00000000 EDX:00000A2C

where EAX + EDX = 0xC0A2C is in video ram doesn't seem to produce what's at the location.

Developer of RReady - Rendition Verité Wrapper.
https://www.youtube.com/@sharangadayananda