• Please review our updated Terms and Rules here

Question about Turbo C and changing memory models

discolando

Member
Joined
Mar 8, 2020
Messages
16
Location
Kansas City, KS USA
First off, apologies for my last thread where I came in guns blazing without a proper introduction. :D

I'm along time developer in the midwest USA who has recently had my love of 8 and 16 bit era computing rekindled by several retro projects and games I've seen on YouTube. I've decided to dive in, relearn the tools, and see what I can make. So far, it's been a ton of fun!

I've decided on a CGA based graphical interactive fiction engine because I loved playing that style of game both on my Commodore 64 and later on my Tandy 1000 EX. (Think Oo-Topos, Mindshadow, The Coveted Mirror, etc...) However, I want to put my own spin on it and utilize modern tools such as Photoshop to produce really high quality content on something that will run great even on a 5150.

I've settled on building this in Turbo C 2.01 + x86 assembler as I'm relatively familiar (although far from expert level) with both. I've got keyboard and graphics routines in asm and the rest (file I/O, data structs, text parser, game loop) in C. Thanks to Trixter, I'm also utilizing LZ4 decompression in asm so I will be able to cram in a ton of content on what will amount to a couple of 360k floppies!

However, with all of that, I'm currently running into one road block. TCC defaults to the tiny memory model (64k code, 64k data) and I'm already about to break through that. I've done some preliminary testing on compiling in the compact memory model (64k code, up to 1Mb data) and things... aren't pretty. It crashes randomly and data at times appears to just disappear. From what I've read in Borland's official text, I need to utilize far pointers, but between that book and an old copy of "Mastering Turbo C" I'm not able to discern specifically what I need to do to get this running stably in the compact model.

Does anyone have any guides or suggested reading for this? This is the last major milestone I need to overcome and I'll be able to finish this project pretty quickly. Any help would be greatly appreciated!
 
Compact is a small amount of code (64KB or less) but multiple data segments.

In general the compiler will generate far data pointers for you, which is the correct thing to do. Where you may get into trouble is when you take the default pointer type and try to have it point to something else. For example, in the tiny model if you want to manipulate the CGA video buffer you have to explicitly declare the pointer to the video buffer as a far pointer.

I'm having problems coming up with a case where your data pointers (far by default) are being mixed with near pointers. Keep in mind it might not be anything like that at all; you might have exceeded your stack allocation given the growth of the default pointer size. (You can set the default stack size in the linker options.)

I use TC++ 3.01 ... it also includes support for straight C.
 
Tiny is 64K code+data
Small is 64K code + 64K data
See here for terminology

Using far and huge pointers can get to be a bit hairy. See this discussion for examples

Abstracting pointer types, etc. can help with portability, particularly if you eventually want to move to a 32-bit or 64-bit platform. Typedef can be your friend.

Oops... you're right. TCC shows that it defaults to the small model, and I want to switch to compact.

Thanks for the help, I'll check that out.
 
Trixter, I'm also utilizing LZ4 decompression in asm so I will be able to cram in a ton of content on what will amount to a couple of 360k floppies!

Switch to LZSA1, you'll get better compression and faster decomp speed (and you can still greet me because I wrote that decompressor as well ;-) Or, if you need more compression with less speed, LZSA2.
 
Switch to LZSA1, you'll get better compression and faster decomp speed (and you can still greet me because I wrote that decompressor as well ;-) Or, if you need more compression with less speed, LZSA2.

Are there pre-compiled binaries for LZSA1 compression (preferably Unix/WSL) or do I need to compile from source?

Thanks!
 
A common mistake made in C programming is storing a pointer in an int variable. In the compact and large models, an int is two bytes and pointers are four.
 
Github is https://github.com/emmanuel-marty/lzsa which has full source, and the releases contain win32 and win64 compiled binaries for the compressor. So you'll likely need to compile the compressor for Linux.

Thanks, I was able to get that compiled and ran some tests. LZSA so far is giving me anywhere from a 3-10% improvement on compressing my bitmaps, which is awesome.

I've added your source with the lzsa1_decompress_speed routine into my makefile and I'm able to compile it with TASM and link it to the project. What is the recommended method for calling this function from Turbo C? For comparison, my CGA graphics routines accept arguments that match my function in C:

draw_pixels PROC
ARG x:WORD, y:WORD, pixels:WORD

extern void draw_pixel(int x, int y, unsigned char pixels);

In this instance, how do I appropriately set the call to lzsa1_decompress_speed to pass in the pointer to my input and output buffers to match DS:SI and ES:DI?

For that matter, is there a better way to call my graphics functions so they don't require memory access to pass in the values, instead going straight to registers?
 
I'm not sure how to call it from Turbo C; you may want to look for a Turbo C manual online such as http://www.bitsavers.org/pdf/borland/turbo_c/ . The routine expects DS:SI to point to the source compressed data, and ES:DI to the target buffer, so if Turbo C can only call parameterized functions (ie. where arguments are pushed on the stack and then popped off), you'll need to modify the routine somewhat. Hopefully the manual(s) have examples.
 
Back
Top