16-bit programming HELL!

Started by
16 comments, last by lack o comments 18 years, 11 months ago
use far pointers
Advertisement
As Ilici suggests, I'd go for using protected mode - knowing about how to get around the pain of x86 real mode isn't exactly much of a valuable skill in this day and age...

You could persuade the school to save a lot of pain and use the free Open Watcom http://www.openwatcom.com/, that comes with protected mode DOS extenders.

Watcom used to be a commercial product back in those days, and was particularly well respected by game developers.

Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site

Quote:
The fact that it's a calcuation makes no difference. It still creates a value which is passed to the function, and this value is probably truncated (is that the right word?) to a 16-bit value, or basically masked with 0xFFFF.

Yeah. I realized what you were saying a little while later. Anyway. I tried farmalloc(long), an the function failed. It was late and I didn't feel like fixing my post.

Quote:
As Ilici suggests, I'd go for using protected mode - knowing about how to get around the pain of x86 real mode isn't exactly much of a valuable skill in this day and age...

This is simply not a posiblity. The school insists on using this ancient compiler and my friend has no other alternative. The compiler itself existed before 32-bit protected mode. It MUST be 16-bit code. Personally, I can't stand using the thing, and would have never touched it again if not for this situation. I got my fill of 16-bit a while back.

I tried talking to the teacher several years ago when I attended. I suggested several 32-bit compilers. But I can see that never got very far. (BTW: It's only an intro high school class, so it's not like it's earth-shatteringly important to them)

Well, thanks anyways, folks, for the time and effort.
Using 16 Bit mode, you can only manage data structures with a size of 64KB maximum. However when using far pointers, you may create multiple data structures of a size <= 64kb.

Maybe you can call DOS functions to allocate memory chunks greater than 64kb. Dis you try this ?
Read here.

Does the runtime library of turbo C manage more than 64kb heap ? If you do not need the memory to be contigous, you may write a simple helper class that allocates multiple blocks via malloc (and using far pointers) to provide more than 64kb memory chunk.
From the Turbo C++ documentation: about 'far'
	far <type modifier>	Forces pointers to be far, generates function code for a far call	and far return.		<type> far <pointer-definition>;			OR		<type> far <function-definition>	The first version of far declares a pointer to be two words with a range	of 1 megabyte. This type modifier is usually used when compiling in the	tiny, small, or compact models to force pointer to be far.	...



From the Turbo C++ documentation: about farmalloc()
	void far *farmalloc(unsigned long nbytes);		farmalloc allocates a block of memory nbytes long from the far heap.	For allocation from the far heap, note that		*All available RAM can be allocated		*blocks larger that 64k can be allocated		*far pointers are used to access the allocated blocks	...


I've already coded a simple solution to split the data into chunks. I was trying to avoid it because I'm writing a software graphics library and with such an old compiler, I need all the speed I can get.
So does farmalloc work as expected ? Then you should stick to it. Otherwise try the direct call to DOS.
Quote:Original post by lack o comments
Nope. I am passing a calculation (320*240*1) as the parameter. I also tried using a compiler-specific function. 'farmalloc()' which is supposed to use the 'far' heap no matter what. Still nothing.
This is exaclty what I expected to see in your code. If you hadn't posted this I would have asked you.

I would have thought that there'd be more 16-bit programmers around that would know this. Anyway, I know exactly what your problem is because I program for a 16-bit machine regularly and have made the same mistake.
Here it is: Your calculation 320 as a WORD, multiplied by 240 as a WORD, multiplied by 1 as a WORD.
The result is stored in a WORD!!! The compiler does not know that the result of the multiplication is too big for a WORD.

Instead write:
320UL*240UL*U1L
'UL' means unsigned long when put at the end of a constant.
or:
320L*240L*sizeof(char)
if you prefer (assuming that I've guessed correctly with the 1 was for[smile]). 'L' means long when put at the end of a constant.

In may case I did this:
(NUM_RECS * sizeof(myStruct))
but NUM_RECS is 1000 and sizeof returns a WORD, so if the size of myStruct > 65 you get a WORD times a WORD again. Had to make it 1000L.

Now, how about declaring that 320L as a constant or #define eh! (tsk tsk)
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
Actually, the literals were only to let everyone know how much memory I was allocating. I always specify sign and size when working in 16-bit (learned that the hard way long ago). The real equation used variables of type 'unsigned short int'. However, I found part of the mistake. Here is how it looked:
g_BackBuffer.Data = (BYTE far*)farmalloc((DWORD)(g_BackBuffer.Width*g_BackBuffer.Height*g_BackBuffer.Bpp));

Unlike my newer compilers, Turbo didn't know how to cast that entire equation. I tried putting a cast in front of each variable and the function returned successfully.

The problem of corruption still remains though. As a test, I allocated 76800 bytes, set all of the values to zero and the last one to 101. I then looped through the array until I found the byte with 101. For some strange reason, it's always byte 11163. Except when I use huge poiinters. Then the byte can range by a few hundred. [headshake]

BTW: Someone mentioned DOS calls. Unfortunately, DOS only recognizes the first 640k. So, I'm still screwed ;)

This topic is closed to new replies.

Advertisement