#include <stdint.h>
#include <string.h>

/* x86 memory map
 0x00000 - 0x003FF	IVT	0x400
 0x00400 - 0x9FFFF	FREE	0x9FC00
 0xA0000 - 0xBFFFF	VGA	0x20000
 0xC0000 - 0xFFFFF	FREE	0x40000

 total freemem - 0xDFC00 - 916480 bytes/895.0K
*/

typedef struct { // pointer into program data into which load segment is added
	uint16_t offset,
		 segment;
} __attribute__((packed)) reloc;

typedef struct { // no endian checks - this will only work on x86+vm anyway
	uint16_t mz,
		 bytes,
		 pages,
		 relsz,
		 len,
		 minalloc, // can easily ignore - we have 895k free
		 maxalloc,
		 ss,
		 sp,
		 sum,
		 ip,
		 cs,
		 rel, // pointer to 
		 overlay; // zero if main binary
	reloc	 r[];
} __attribute__((packed)) mz;

typedef struct {
	uint16_t ss, sp, ip, cs;
} mz_start;

#define m8 ((uint8_t*)m) // access mz by byte
uint32_t loadmz(mz* m, uint8_t* mem, uint32_t seg, mz_start* m) {

	uint32_t sz = (((uint32_t)m->pages) << 9) + m->bytes;
	memcpy( // copy mz to memory
		mem + (seg << 4),
		m8 + (m->len << 4),
		sz
	);

	for(int i = 0; i < m->relsz; i++) *(uint16_t*)(
		m8 +
		(seg << 4) +
		((uint32_t)m->r[i].segment << 4) +
		(uint32_t)m->r[i].offset
	) += seg;

	*m = (mz_start) {
		m->ss+seg,
		m->sp,
		m->ip,
		m->cs+seg
	};
}
