aboutsummaryrefslogtreecommitdiff
path: root/pokeytest/playsdl2.c
blob: 3970a2e4880ed2ecc42cc20bfae85a822e76d0f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include <SDL.h>

#include <stdio.h>
#include <stdlib.h>

#include "pokey.h"

#define ROM_FILE "../jumpmanjr.rom"
#define ROM_SIZE 0x4000

#define FREQ 44100

#define PAL_BUF_SIZE 882
#define NTSC_BUF_SIZE 735

#define PAL_DELAY 20
#define NTSC_DELAY 17

unsigned char sndbuf[PAL_BUF_SIZE + 1];

int buf_size = NTSC_BUF_SIZE;
int delay = NTSC_DELAY;

unsigned char rom[ROM_SIZE];

void usage(void) {
	fprintf(stderr, "usage: playsnd [-p] 0xaddr\n");
	exit(1);
}

void load_rom(void) {
	int size;
	FILE *f;

	f = fopen(ROM_FILE, "rb");
	if(!f) {
		perror(ROM_FILE);
		usage();
	}

	size = fread(rom, 1, ROM_SIZE, f);
	if(size != ROM_SIZE) {
		fprintf(stderr, "file %s should be %d bytes long, not %d\n",
				ROM_FILE, ROM_SIZE, size);
		usage();
	}

	fprintf(stderr, "loaded ROM %s, %d bytes\n", ROM_FILE, size);
}

void play_frames(unsigned char count) {
	fprintf(stderr, "playing for %d frames\n", count);
	while(count--) {
		SDL_Delay(delay);
	}
}

void play_sfx(int addr) {
	unsigned char *p = rom + (addr - 0x8000);

	while(1) {
		fprintf(stderr, "$%04lx: $%02x\n", (p - rom + 0x8000), *p);
		switch(*p) {
			case 0:
				fprintf(stderr, "opcode 0 (snd_end)\n");
				return;
			case 1:
				fprintf(stderr, "opcode 1 (snd_audc)\n");
				Update_pokey_sound(audc1, *++p);
				play_frames(*++p);
				++p;
				break;
			case 2:
				fprintf(stderr, "opcode 2 (snd_jump)\n");
				addr = *++p;
				addr |= ( (*++p) << 8);
				addr -= 0x8000;
				p = rom + addr;
				break;
			case 3:
				fprintf(stderr, "opcode 3 (snd_rest)\n");
				Update_pokey_sound(audc1, 0);
				play_frames(*++p);
				++p;
				break;
			default:
				fprintf(stderr, "opcode $%02x (snd_note)\n", *p);
				Update_pokey_sound(audf1, *p);
				play_frames(*++p);
				++p;
				break;
		}
	}
}

void sdl_audio_callback(void *userdata, Uint8* stream, int len) {
	Pokey_process(stream, len);
}

void init_sdl_audio(void) {
	SDL_AudioSpec want, have;
	SDL_AudioDeviceID dev;

	if(SDL_Init(SDL_INIT_AUDIO) < 0) {
		fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
		exit(-1);
	}
	atexit(SDL_Quit);

	SDL_memset(&want, 0, sizeof(want));
	want.freq = FREQ;
	want.format = AUDIO_U8;
	want.channels = 1;
	want.samples = buf_size;
	want.callback = sdl_audio_callback;

	dev = SDL_OpenAudioDevice(0, 0, &want, &have, 0);
	if(!dev) {
		fprintf(stderr, "Failed to open audio: %s\n", SDL_GetError());
		exit(-1);
	}

	SDL_PauseAudioDevice(dev, 0);
}

int main(int argc, char **argv) {
	int addr;

	if(argc < 2 || argc > 3) usage();

	if(argc == 3) {
		buf_size = PAL_BUF_SIZE;
		delay = PAL_DELAY;
		addr = (int)strtol(argv[2], 0, 16);
	} else {
		addr = (int)strtol(argv[1], 0, 16);
	}

	if(addr < 0x8000 || addr > 0xbfff) {
		fprintf(stderr, "invalid address, must be 0x8fff thru 0xbfff\n");
		usage();
	}

	load_rom();

	fprintf(stderr, "playing sfx at $%04x, buf_size %d\n", addr, buf_size);

	Pokey_sound_init(FREQ_17_APPROX, FREQ);
	init_sdl_audio();
	play_sfx(addr);

	return(0);
}