magiblot / tvision

A modern port of Turbo Vision 2.0, the classical framework for text-based user interfaces. Now cross-platform and with Unicode support.
Other
1.99k stars 150 forks source link

help: compiling a project #84

Closed ghost closed 1 year ago

ghost commented 1 year ago

Hello everybody

I try to compile old source code I found somewhere. Some info I know already about it

https://gitlab.com/twilight-cd.com/sourcecode-menu-twilight-9

Run menu.exe in DOSBox (https://www.dosbox.com/) to see this:

afbeelding

The screenshot is the program that I want to compile by using Tvision (if possible).

Is there anybody who can look at it and tell me if there is a way to compile it by using Tvision? I'm a complete beginner... So my question: is somebody interested to look at the code and try to compile it using Visual Studio and Tvision in order to get a modern code and executable that's doing the same as the original code? If the user interface is displayed, that would be already great. I don't know if the old code even uses Tvision (i'm a beginner)

Thanks for the help! Lisa

ghost commented 1 year ago

I never used Tvision myself and also not the modern Tvision on github here (I still need to learn it). So if somebody wants to help, I really need a Visual Studio project that I can open and just compile. I only have very basic C language knowledge :-)

magiblot commented 1 year ago

Hi Lisa!

The fact that the program is written in C does not mean that it can be compiled with Visual Studio.

In the source code you will find statements such as #include <conio.h> or #include <dos.h>; these are non-standard headers which provide access to features which are exclusive of MS-DOS (such as DOS interrupts). Therefore this program is written in a way such that it will only work on MS-DOS and it can be only compiled with the Borland compiler.

ghost commented 1 year ago

Hi

Thanks for the explanation.

The thing I try to do is to just make the user interface compile and appear on the screen (not the functionality of what it's doing when clicking a button, ... ). So basically have the user interface of the screenshot appear. So the features of MS-DOS can be removed :) I only wanted to compile the user interface using visual studio and using tvision here on github.

Can you tell me, by looking at the source code, if this project really uses Turbo Vision by Borland for making the user interface? If this is not the case, then all my questions are answered (considering tvision).

Thanks

magiblot commented 1 year ago

Okay. No, this program does not use Turbo Vision. Of course, you can use Turbo Vision to make a replica of the user interface, but that will imply rewriting an important part of the application. Therefore, it is not possible to just compile the user interface reusing the original code.

ghost commented 1 year ago

Ok thank you so much :) How is the user interface made exactly? All manually or what library is used? It must be a MS-DOS library anyway because this was a MS-DOS program only.

So basically: nothing from this source code can be used (without changing or porting) to compile it using a modern compiler (even if you don't use tvision)?

ghost commented 1 year ago

Are you interested to make an application that replicates the screenshot using tvision (if that's possible)? No functionality: just the user interface :) For me it would be a very long way do this myself (if I even succeed) since I never used tvision. But once I have it as an example, I can both learn tvision quickly and also understand how the user interface works.

You use DOSBox (https://www.dosbox.com/) to run this program and see exactly what it's doing.

Lisa

magiblot commented 1 year ago

You can see this in menu.c. It uses functions from conio.h and DOS interrupts, which means that it is drawing the interface manually. For example:

void cursorOn(void)
{
    union REGS regs;

    regs.h.ah = 1;
    regs.h.ch = 12;
    regs.h.cl = 13;
    int86(0x10, &regs, &regs); // DOS interrupt
}
void setYellowOnLightBlue(void)
{
    textcolor(YELLOW+128); // conio.h method
    textbackground(BLUE); // conio.h method
}

This does not mean that none of the code can be reused; for example, dialog.c does not call conio.h methods directly but instead uses methods from menu.c:

void dlgPutBar(DialogEntry *de)
{
    if(de->flags&DLG_SELECTED)
        setYellowOnLightBlue(); // menu.c method
    else
        setWhiteOnLightBlue(); // menu.c method

    writeAt(de->xpos, de->ypos, de->txt); // menu.c method
}

Therefore, there are parts of the user interface which can be reused after reimplementing menu.c, but this alone is already a tedious task.

ghost commented 1 year ago

I understand. It's just all MS-DOS related :) You answered all my questions! Unfortunately I thought it was just using tvision and could do something with the source code (in an easy way) :(

ghost commented 1 year ago

If I would use tvision to recreate the user interface, is it looking very differently then? Do you have a screenshot of widgets of tvision that are similar? Or is everything so custom that I would need to write my own tvision widgets for this?

magiblot commented 1 year ago

Yes, unfortunately it is going to look quite different, and you will most likely need to write custom widgets (or, otherwise, spend a good time understanding how the default ones work). Thus, if it were me, I would just reimplement with Turbo Vision the conio.h methods which menu.c uses. Although the idiomatic way to use Turbo Vision is through widget classes, Turbo Vision also provides ways to writing to the screen manually (but unlike conio.h, this is supported cross-platform).

ghost commented 1 year ago

What version of the Borland C compiler for DOS do you think can compile this code (or just use latest version)? I see somewhere there is assembly code too. Do you have experience what is needed to compile this (with assembly combination) or can Borland C all handle this when you just add the C code files?

magiblot commented 1 year ago

The cdrom.c file contains the following comment:

Written July 18, 1994
Using Borland C++ 3.1

Additionally, there are no makefiles, but there are .prj files. Therefore, I would try using Borland C++ 3.1 (available on WinWorld); I guess you will then be able to open the project files from the IDE (bc command, menu entry Project > Open) and build them one by one.

Inline assembly in .c files is supported out of the box; if you are instead referring to the fact that there are both .asm and .c files, then the thing is that the .prj files already tell the compiler which files have to be compiled, so you should be fine. However, you will also have to install Turbo Assembler 3.0 (available on VetusWare) since Borland C++ is unable to compile .asm files without it.

Of course, all of this has to be done in MS-DOS.

ghost commented 1 year ago

Thanks for all this information! I never coded in the MS-DOS age and never used those tools.

magiblot commented 1 year ago

I think Borland C++ just tries to find the tasm command; therefore, after installing Turbo Assembler, just make sure it is available in the PATH.

Yes, although I wrote "MS-DOS", I was thinking about DOSBox, which is what you are using. I haven't tried it myself, but I don't see a reason why it shouldn't work there.

I never coded in the MS-DOS age and never used those tools.

Me neither; what you are about to do now is the same I did when I began this project.

ghost commented 1 year ago

Thanks! You just gave me enough information to try it! I'll let you know soon if it worked or if I have problems.

ghost commented 1 year ago

Hi

Are you interested to try it yourself? Because I have very strange problems.

I found a cool website explaining how to compile Wolfenstein 3D source code. If you follow all steps, you can see it works and the game runs fine in DOSBox. You then also have everything to try to compile this source code.

https://fabiensanglard.net/Compile_Like_Its_1992/

The most important steps you NEED to do:

afbeelding

PATH=C:\BORLANDC\BIN

The TASM seems to be included with Borland C++ 3.1 but you need to set the PATH var because it's not found when compiling otherwise

So this means:

But:

This is all that happens :(

afbeelding

Thanks in advance!

ghost commented 1 year ago

I think it's a bug but I have no experience with Borland C++. If you have time and want to debug, maybe? I don't know if I can ask this ...

Run the menu.exe on the command line like this "menu /?" and it works.

afbeelding

So somewhere the program "hangs" when the user interface needs to be displayed

magiblot commented 1 year ago

I also get a crash. The integrated debugger is easy to use: after building, you can set breakpoints with Debug > Toggle breakpoint, then run the application with Run > Run.

In the end, I found that the program was failing in the readHelpData function (which in fact does weird things), so I commented out line 4168 (readHelpData(argv[0]);) and the program now starts up:

Screenshot_20221214_213700

ghost commented 1 year ago

Thanks! I'm now getting used to the debugger and for such an old program, it's really easy to use.

ghost commented 1 year ago

Does "run" work in your DOSEMU2? In DOSBox the executable is not run, so it doesn't do anything. (while it is build and I can run it in a new DOSBox window, but not when using the "run" command in Borland C++) So that makes I can't debug it :(

magiblot commented 1 year ago

No, running the program from within Borland C++ does not work for me either. This is understandable because running nested applications in DOS is a delicate issue.

There is also a standalone debugger, td, which could work, but I haven't been able to get it to properly detect the program's source code, so I haven't tried.

ghost commented 1 year ago

On WinWorld is also Borland C++ 5.x, and in the description "This version requires 32-bit Windows 95 or NT. It can still produce executables for DOS and Windows 3.1. " This won't probably work either , because a 16 bit MS-DOS EXE can't run on modern windows so debugging it is impossible too? Or do you think this source code can be debugged using Borland C++ 5.x?

Or any other idea you have to be able to debug it? :)

magiblot commented 1 year ago

I don't think a newer compiler version will help. I would also try with Windows 95; Borland C++ 3.1 already provides a GUI IDE (bcw); you can try and see if it works any better. You would need a virtual machine for this, though.

magiblot commented 1 year ago

It would be worth trying in Windows XP, too.

ghost commented 1 year ago

So back in the days you had 2 choices for making a DOS GUI: drawing manually like this program or using Turbo Vision?

magiblot commented 1 year ago

Well, there were other tools, such as Visual Basic for DOS. Additionally, I guess many people developed their own libraries. Note that Turbo Vision, under the hood, also draws to the screen manually.

"Drawing manually" can also be done in several ways; besides drawing characters it is also possible to use graphics, or to mix text and graphics by modifying the console font on-the-fly.

https://retrocomputing.stackexchange.com/questions/9599/alternatives-for-turbovision-on-dos https://www.youtube.com/watch?v=7nlNQcKsj74 https://www.math.ucdavis.edu/~mkoeppe/mkm/mkmeng.html

ghost commented 1 year ago

Hi

Thanks for the help so far!

Are you willing to try something again?

I can compile all projects except project THF.PRJ

I get this weird error:

afbeelding

I found this explanation but because I don't know ASM, I have no idea what this error means and how to fix it.

https://community.embarcadero.com/article/technical-articles/162-programming/14878-coping-with-fixup-overflow-messages

If you have the knowledge and want to do this, can you look at it and explain me why I get this error and how to solve it?

You just need to look at project THF.PRJ

magiblot commented 1 year ago

The suggested solution (in the page you linked) works for me:

If some of your object files (.OBJs) or libraries (.LIBs) are in one memory model, and others are in another model, the linker may not properly fixup (or match) addresses for the symbols that it gets from the compiler. The best way to find out if this is the case is to do a Build All (under the Compile menu in the Integrated Development Environment, aka IDE)

The first time I tried I forgot to set the Output directory to OBJ and it also worked. Maybe there is another project which also compiles one of these source files but uses a different memory model.

ghost commented 1 year ago

I don't understand what you are saying :( I have output directory to OBJ but here it doesn't work. So on your PC it compiles WITHOUT this error?

magiblot commented 1 year ago

What I meant is:

ghost commented 1 year ago

Do you have an idea how 2 identical source codes, identical compilers can give different results on 2 different pcs, since you don't get that error? Herebuild all gives the errors no matter how many times I try. It are 7 of those same errors.

magiblot commented 1 year ago

Here is my understanding of the situation:

Therefore, either Build All or changing the output directory should have worked. At least this is the behaviour I am observing.

Another thing you can try is to set the memory model of THF.PRJ to Large (Options > Compiler > Code generation) and Build All again.

ghost commented 1 year ago

It finally worked when using another output directory BUT now I have another error!

afbeelding

Do you know what this means? I have "OBJ2" as output directory now.

magiblot commented 1 year ago

Does the directory exist?

ghost commented 1 year ago

Those old tools don't create directories when they don't exist it seems. Problem fixed!!!

ghost commented 1 year ago

Now that it compiles I try to figure out how THF files are read. Maybe you want to have a look at it?

You run the tool on a THF file that can be found on the CD, here is TL09.THF from Twilight 9:

https://archive.org/download/cdrom-twilight-009/TWILIGHT009.iso/MENU%2FTL09.THF

This file contains ZIP files (of old MS-DOS games) and also what they call Viewer-files (this is a sort of help file). In the code you can also see there can be screenshots inside: PCX files. You put the THF file next to THF.EXE (in same directory) and can do several things on it.

afbeelding

Below I listed info about the THF file and the contents.

What I try to understand now:

Do you think this is possible because I see some DOS functions like _dos_write (and maybe more)

So if you want to help, my question is: how to extract all files from a THF file? What's the algorithm for this so I can understand it?

afbeelding

afbeelding

afbeelding

ghost commented 1 year ago

You can extract like this (see last command):

afbeelding

ghost commented 1 year ago

My current research found this about the encryption:

char *XORstr = "Û”Í$'v9èLÓ31¶¶!`e9]Òp_l<Ö!7Q:[Ú¯?sÆ$Í#";

char *variousxorstr = "Û”Í$'v9èLÓ31¶¶!`e9]Òp_l<Ö!7Q:[Ú¯?sÆ$Í#";

char *thfXORstr = "e!7Í“½<Ànš+ÉÉÞñrN÷55ï!`èõ33l$Âp";

And there is a encryption add: unsigned char thfEncrAdd = 43;

(see screenshot above, they match when reading the THF file information)

There is checked which file type is inside the file:

if(filetype == FT_ZIP) { if(_dos_read(thfGetHandle(), buf, nrread, &dummy) != 0) { printf("\n\nError reading file!\n"); exit(1); } if(!donotdecode) decryptZIPblock(buf, nrread); _dos_write(g, buf, nrread, &dummy); } else if(filetype == FT_TVF) { thfReadBlock(buf, nrread); decodeTVF(buf, nrread, g); } else { thfReadBlock(buf, nrread); _dos_write(g, buf, nrread, &dummy); }

So for a ZIP file the function decryptZIPblock is used. For a TVF file (or else) the function thfReadBlock is used (see below).

void decryptZIPblock(unsigned char huge buf, unsigned int size) { while(size--) { buf ^= 0x3c; buf += 0xb1; buf++ ^= 0x43; } }

char huge thfDecryptBlock(char huge dest, long size) { int xorlen; char huge *savedest = dest;

xorlen = strlen(thfXORstr) - 1;
while(size--) {
    *dest -= thfEncrAdd;
    *dest++ ^= thfXORstr[thfXORcount++];

    if(thfXORcount > xorlen) thfXORcount = 0;
}

return savedest;

}

If you want to help, I can't figure out this:

  1. How to the determine in the THF file if a ZIP, TVF or other type is following next (to decrypt)?
  2. Where do those 3 values in function decryptZIPblock come from? They are 0x3c, 0xb1 and 0x43. This has nothing to do with XOR, so where does it come from?

Thx

ghost commented 1 year ago

Update: I found out how the encryption works for everything!

The only thing I don't find at the moment: How to the determine in the THF file if a ZIP, TVF or other type is following next (to decrypt)?

If you still want to help? :)