/*********************************************************************
 *     dump.c - dumps the emu10k1 registers
 *      Copyright (C) 2000 Rui Sousa 
 ********************************************************************* 
 *     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 <stdlib.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include <fcntl.h>
#include <linux/types.h>

#define CMD_WRITE    0x2
#define CMD_READ     0x1

int main(int argc, char **argv)
{
	copr_buffer buf;
	int audio_fd;
	int offset, length;
	int loword, hiword;
	int op, z, w, x, y;
	int align;
	int i;

	if (argc < 3) {
		fprintf(stderr,
			"usage:\n    dump offset length (values in bytes)\n");
		exit(EXIT_FAILURE);
	}

	if ((audio_fd = open("/dev/dsp", O_WRONLY, 0)) == -1) {
		perror("open");
		exit(EXIT_FAILURE);
	}

	sscanf(argv[1], "%d", &offset);
	sscanf(argv[2], "%d", &length);

	while (length > 0) {
		buf.command = CMD_READ;
		buf.offs = offset;
		buf.len = length < 1000 ? length : 1000;

		if (ioctl(audio_fd, SNDCTL_COPR_LOAD, &buf) == -1) {
			perror("SNDCTL_COPR_LOAD");
			offset += buf.len;
			length -= buf.len;
			continue;
		}

		for (i = 0; (i < buf.len) && (buf.offs + i) < 0x7ff; i++) {
			if (buf.offs + i < 0x400) {
				loword = ((__u32 *) buf.data)[i];
				printf("0x%03x   0x%08x\n", i + buf.offs,
				       loword);
			} else {
				align = (buf.offs + i) % 2;
				loword = ((__u32 *) buf.data)[i + align];
				hiword = ((__u32 *) buf.data)[i + 1 + align];
				op = (hiword >> 20) & 0x1f;
				z = (hiword >> 10) & 0x3ff;
				w = hiword & 0x3ff;
				x = (loword >> 10) & 0x3ff;
				y = loword & 0x3ff;

				printf
				    ("0x%03x   0x%08x   0x%08x   OP(%2d, 0x%03x, 0x%03x, 0x%03x, 0x%03x)\n",
				     i + buf.offs + align, loword, hiword, op,
				     z, w, x, y);
				i++;
			}
		}

		offset += buf.len;
		length -= buf.len;
	}

	return 0;
}
