Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory management #11

Open
toncho11 opened this issue Aug 18, 2024 · 6 comments
Open

Memory management #11

toncho11 opened this issue Aug 18, 2024 · 6 comments
Labels
pc IBM PC

Comments

@toncho11
Copy link

toncho11 commented Aug 18, 2024

An IBM PC 16 bit will use 8086 real-mode. Even with Open Watcom large model pointers are still limited to a 64k range of memory and program's heap (using malloc) is also limited to 64k, just like in small model.

So doomtd3 needs to use code that manage separately-allocated 64K chunks of memory in order to use more than 64 kb of memory. Is that how doomtd3 is programmed to use 300kb of memory?

Or maybe there is never a need for an array that is bigger than 64 kb, so everything is indeed done in chunks of 64 kb.

@FrenkelS FrenkelS added the pc IBM PC label Aug 18, 2024
@FrenkelS
Copy link
Owner

FrenkelS commented Aug 18, 2024

At startup, _dos_allocmem is used, instead of malloc and halloc, to allocate all available memory (which should be at least 300 kB) as one big contiguous block of memory*. Then the various Z_Malloc functions are used to allocate pieces, that are always smaller than 64 kB, of this big block.

*Technically it can be one big contiguous block of memory plus 64 kB of EMS memory. Point is, all memory should be addressable without having to use bank switching.

@toncho11
Copy link
Author

toncho11 commented Aug 18, 2024

I am a bit confused. I thought IBM PC means 16 bit 8088 or 8086, but I see that _dos_allocmem is only used with:

#if defined DJGPP || defined _M_I386

where DJGPP is 32 bit compiler and the other is 386 which gives the impression that _dos_allocmem is only 32 bit?

@FrenkelS
Copy link
Owner

The IBM PC 16-bit version can be compiled with gcc-ia16 and Open Watcom. In those cases _dos_allocmem is supplied by the compiler / runtime / libc.
In case of DJGPP (__DJGPP__) and Open Watcom 32-bit (_M_I386) I use my own implementation of _dos_allocmem.

@toncho11
Copy link
Author

toncho11 commented Aug 19, 2024

So for 16bit OW on а 16 bit OS different from DOS and OS/2 (such as ELKS) a new custom version of _dos_allocmem is required in i_ibm.c? The built-in version uses DOS system calls, so it won't work for ELKS.

@toncho11
Copy link
Author

So fmemalloc from ELKS can be used as a replacement of _dos_allocmem for ELKS.

Question: are there any special timer and interrupt routines that needs to be refactored for ELKS for doomtd3?

@FrenkelS
Copy link
Owner

To port doomtd3 to ELKS create the file i_elks.c and implement the 15 functions that are defined in i_system.h, and a main() function.
Take a look at i_amiga.c, i_hp95lx.c, i_ibm.c and i_mac.c to see how these functions are implemented for other platforms.

For example, I_ZoneBase() can be based on the implementation in i_mac.c:

segment_t I_ZoneBase(uint32_t *size)
{
	uint32_t paragraphs = 550 * 1024L / PARAGRAPH_SIZE;
	uint8_t __far* ptr = fmemalloc(paragraphs * PARAGRAPH_SIZE);
	while (!ptr)
	{
		paragraphs--;
		ptr = fmemalloc(paragraphs * PARAGRAPH_SIZE);
	}

	// align ptr
	uint32_t m = (uint32_t) ptr;
	if ((m & (PARAGRAPH_SIZE - 1)) != 0)
	{
		paragraphs--;
		while ((m & (PARAGRAPH_SIZE - 1)) != 0)
			m = (uint32_t) ++ptr;
	}

	*size = paragraphs * PARAGRAPH_SIZE;
	return D_FP_SEG(ptr);
}

Or when _fmemalloc turns out to be the same as _dos_allocmem I_ZoneBase() can be implemented as:

segment_t I_ZoneBase(uint32_t *size)
{
	unsigned int max, segment;
	_fmemalloc(0xffff, &max);
	_fmemalloc(max, &segment);
	*size = (uint32_t)max * PARAGRAPH_SIZE;
	return segment;
}

In my opinion, there are no special timer routines. I_StartClock() and I_EndClock() are used to calculate the frame rate. They can be implemented by using clock(), but I'm not sure ELKS supports the clock() function. Though it looks like ELKS does have gettimeofday() so that can be used instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pc IBM PC
Projects
None yet
Development

No branches or pull requests

2 participants