view zdis.c @ 505:b7b7a1cab44a

The local clone on my laptop got messed up and some changes had not been pushed. This commit represents the status of the working copy from that clone. It unfortunately contains some changes that I did not intend to commit yet, but this seems like the best option at the moment.
author Michael Pavone <pavone@retrodev.com>
date Mon, 06 Jan 2014 22:54:05 -0800
parents 140af5509ce7
children 3eced113081c
line wrap: on
line source

/*
 Copyright 2013 Michael Pavone
 This file is part of BlastEm. 
 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
*/
#include "z80inst.h"
#include <stdio.h>
#include <stdlib.h>

uint8_t visited[(64*1024)/8];
uint8_t label[(64*1024)/8];

void visit(uint16_t address)
{
	visited[address/8] |= 1 << (address % 8);
}

void reference(uint16_t address)
{
	//printf("referenced: %X\n", address);
	label[address/8] |= 1 << (address % 8);
}

uint8_t is_visited(uint16_t address)
{
	return visited[address/8] & (1 << (address % 8));
}

uint8_t is_label(uint16_t address)
{
	return label[address/8] & (1 << (address % 8));
}

typedef struct deferred {
	uint16_t address;
	struct deferred *next;
} deferred;

deferred * defer(uint16_t address, deferred * next)
{
	if (is_visited(address)) {
		return next;
	}
	//printf("deferring %X\n", address);
	deferred * d = malloc(sizeof(deferred));
	d->address = address;
	d->next = next;
	return d;
}

uint8_t labels = 0;
uint8_t addr = 0;
uint8_t only = 0;

int main(int argc, char ** argv)
{
	long filesize;
	uint8_t *filebuf;
	char disbuf[1024];
	z80inst instbuf;
	uint8_t * cur;
	FILE * f = fopen(argv[1], "rb");
	fseek(f, 0, SEEK_END);
	filesize = ftell(f);
	fseek(f, 0, SEEK_SET);
	filebuf = malloc(filesize);
	fread(filebuf, 1, filesize, f);
	fclose(f);
	deferred *def = NULL, *tmpd;
	for(uint8_t opt = 2; opt < argc; ++opt) {
		if (argv[opt][0] == '-') {
			FILE * address_log;
			switch (argv[opt][1])
			{
			case 'l':
				labels = 1;
				break;
			case 'a':
				addr = 1;
				break;
			case 'o':
				only = 1;
				break;
			case 'f':
				opt++;
				if (opt >= argc) {
					fputs("-f must be followed by a filename\n", stderr);
					exit(1);
				}
				address_log = fopen(argv[opt], "r");
				if (!address_log) {
					fprintf(stderr, "Failed to open %s for reading\n", argv[opt]);
					exit(1);
				}
				while (fgets(disbuf, sizeof(disbuf), address_log)) {
				 	if (disbuf[0]) {
						uint16_t address = strtol(disbuf, NULL, 16);
						if (address) {
							def = defer(address, def);
							reference(address);
						}
					}
				}
			}
		} else {
			uint16_t address = strtol(argv[opt], NULL, 16);
			def = defer(address, def);
			reference(address);
		}
	}
	uint16_t start = 0;
	uint8_t *encoded, *next;
	uint32_t size;
	if (!def || !only) {
		def = defer(start, def);
	}
	uint16_t address;
	while(def) {
		do {
			encoded = NULL;
			address = def->address;
			if (!is_visited(address)) {
				encoded = filebuf + address;
			}
			tmpd = def;
			def = def->next;
			free(tmpd);
		} while(def && encoded == NULL);
		if (!encoded) {
			break;
		}
		for(;;) {
			if (address > filesize || is_visited(address)) {
				break;
			}
			visit(address);
			next = z80_decode(encoded, &instbuf);
			address += (next-encoded);
			encoded = next;
			
			//z80_disasm(&instbuf, disbuf);
			//printf("%X: %s\n", address, disbuf);
			switch (instbuf.op)
			{
			case Z80_JR:
				address += instbuf.immed;
				encoded = filebuf + address;
				break;
			case Z80_JRCC:
				reference(address + instbuf.immed);
				def = defer(address + instbuf.immed, def);
				break;
			case Z80_JP:
				address = instbuf.immed;
				encoded = filebuf + address;
				break;
			case Z80_JPCC:
			case Z80_CALL:
			case Z80_CALLCC:
			case Z80_RST:
				reference(instbuf.immed);
				def = defer(instbuf.immed, def);
				break;
			default:
				if (z80_is_terminal(&instbuf)) {
					address = filesize + 1;
				}
			}
		}
	}
	if (labels) {
		for (address = filesize; address < (64*1024); address++) {
			if (is_label(address)) {
				printf("ADR_%X equ $%X\n", address, address);
			}
		}
		puts("");
	}
	for (address = 0; address < filesize; address++) {
		if (is_visited(address)) {
			encoded = filebuf + address;
			z80_decode(encoded, &instbuf);
			if (labels) {
				/*m68k_disasm_labels(&instbuf, disbuf);
				if (is_label(instbuf.address)) {
					printf("ADR_%X:\n", instbuf.address);
				}
				if (addr) {
					printf("\t%s\t;%X\n", disbuf, instbuf.address);
				} else {
					printf("\t%s\n", disbuf);
				}*/
			} else {
				z80_disasm(&instbuf, disbuf, address);
				printf("%X: %s\n", address, disbuf);
			}
		}
	}
	return 0;
}