// idbg - IJVM debugger.
// Copyright 2000 Tom Rothamel <tom-idbg@onegeek.org>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <netinet/in.h>

#include "ijvm.h"

int readint(FILE *f) {
	char buf[4];

	if (fread(buf, 4, 1, f) != 1) return -1;
	return ntohl(*(int *) buf);
}

char *Memory::load(FILE *f) {
	int i;
	int origin;
	int len;
	int c;
	
	i = readint(f);
	if (i != 0x1DEADFAD) {
		return strdup("Ijvm file has an invalid signature");
	}

	while (1) {
		origin = readint(f);
		if (origin == -1) return NULL;

		len = readint(f);

		for (i = 0; i < len; i++) {
			c = fgetc(f);
			if (c == EOF) {
				return strdup("Hit end of file while reading ijvm.");
			}

			setbyte(origin + i, c);
		}

	}

	return NULL;	
}
	    

// This fetches a pointer to the byte at off. It takes care of allocating
// memory if that's what it needs to do.
unsigned char *Memory::find(unsigned int off) {
	int bn = off >> 16;
	off &= 0xffff;
	unsigned char *bl;

	bl = mem[bn];

	if (!bl) {
		bl = (unsigned char *) calloc(1, 65536);
		mem[bn] = bl;
	}

	return &bl[off];
}

unsigned char Memory::getbyte(unsigned int off) {
	unsigned char *b;

	b = find(off);
	return *b;
}

void Memory::setbyte(unsigned int off, unsigned char d) {
	unsigned char *b;

	b = find(off);
	*b = d;
}

// These next two work because the << 2 guarantees that the full integer
// will be in one memory block.
int Memory::getword(unsigned int off) {
	int *b;

	off <<= 2;
	b = (int *) find(off);
	
	return ntohl(*b);
}

void Memory::setword(unsigned int off, int d) {
	int *b;
	
	off <<= 2;
	b = (int *) find(off);

	*b = htonl(d);
}
	
Memory::Memory() {
	mem = (unsigned char **) calloc(sizeof(char *), 65536);
}

