2 // Rolling Thunder HD63701/YM2151 sound test
5 // (C) 2014 Underground Software
15 // HD63701's memory (RAM & ROM)
16 uint8_t memory[0x10000];
19 static SDL_AudioSpec desired, obtained;
20 static SDL_AudioDeviceID device;
21 static bool soundInitialized = false;
22 static int16_t sample;
23 static uint8_t soundBuffer[1024];
26 static uint32_t frameCount = 0;
27 static uint32_t startTicks;
28 static int ymRegister;
31 #define WriteLog printf
32 #define SAMPLE_RATE 48000
34 // Private function prototypes
35 static void SDLSoundCallback(void * userdata, Uint8 * buffer, int length);
38 // Bogus M.A.M.E. shite
39 int cpu_scalebyfcount(int f) { return f; }
40 void timer_remove(void *) { printf("STUB: timer_remove()\n"); }
41 void * timer_set(int, int, void (*)(int)) { printf("STUB: timer_set()\n"); return 0; }
44 uint8_t ReadMemory(uint16_t address)
49 // printf("V63701 read $%02X from $%02X...\n", memory[address], address);
50 return InternalRegisterRead(address);
54 if ((address >= 0x2000) && (address <= 0x2001))
58 // else if (address == 0x2020)
59 // return input_port_0_r(0);
60 // else if (address == 0x2021)
61 // return input_port_1_r(0);
63 return memory[address];
67 void WriteMemory(uint16_t address, uint8_t data)
72 // printf("V63701 wrote $%02X to $%02X...\n", data, address);
73 InternalRegisterWrite(address, data);
78 if (((address >= 0x4000) && (address <= 0xBFFF))
79 || (address >= 0xF000))
81 else if (address == 0x2000)
86 else if (address == 0x2001)
88 //printf("Writing $%02X to YM2151 register $%02X...\n", data, ymRegister);
89 YMWriteReg(0, ymRegister, data);
93 // RAM is from $0 - $3FFF, $C000 - $EFFF
94 memory[address] = data;
100 FILE * file1 = fopen("../ROMs/rt1-mcu.bin", "rb");
101 FILE * file2 = fopen("../ROMs/rt1-4.6b", "rb");
105 printf("Could not open file \"rt1-mcu.bin\"!\n");
111 printf("Could not open file \"rt1-4.6b\"!\n");
115 fread(&memory[0xF000], 1, 0x1000, file1);
116 fread(&memory[0x4000], 1, 0x8000, file2);
127 desired.freq = SAMPLE_RATE; // SDL will do conversion on the fly, if it can't get the exact rate. Nice!
128 desired.format = AUDIO_S16SYS; // This uses the native endian (for portability)...
129 desired.channels = 1;
130 desired.samples = 512; // Let's try a 1/2K buffer (can always go lower)
131 desired.callback = SDLSoundCallback;
133 device = SDL_OpenAudioDevice(NULL, 0, &desired, &obtained, 0);
137 WriteLog("Sound: Failed to initialize SDL sound.\n");
141 // conditional = SDL_CreateCond();
142 // mutex = SDL_CreateMutex();
143 // mutex2 = SDL_CreateMutex();// Let's try real signalling...
144 // soundBufferPos = 0;
145 // lastToggleCycles = 0;
146 sample = desired.silence; // ? wilwok ? yes
148 SDL_PauseAudioDevice(device, 0); // Start playback!
149 soundInitialized = true;
150 WriteLog("Sound: Successfully initialized.\n");
154 static void SDLSoundCallback(void * userdata, Uint8 * buffer, int length)
157 //printf("Callback: buffer size is %i bytes.\n", length);
164 memcpy(buffer, soundBuffer, 1024);
170 memcpy(buffer, soundBuffer, length);
176 // Length / 2 is because it's set up for 16-bit samples
177 YM2151UpdateOne(buffer, length / 2);
182 void ShutdownSound(void)
184 if (soundInitialized)
186 SDL_PauseAudioDevice(device, 1);
187 SDL_CloseAudioDevice(device);
188 // SDL_DestroyCond(conditional);
189 // SDL_DestroyMutex(mutex);
190 // SDL_DestroyMutex(mutex2);
191 WriteLog("Sound: Done.\n");
203 08: (SM)^KON 1(CH #) (Key on, SN=4 bits, CH #=3 (SN = C2,M2,C1,M1))
204 0F: [NE] [XX] [NFRQ][][][][] (Noise enable, noise frequency)
206 11: [XXXXXX][CLKA2][]
208 14: [CSM][X][FLAG RESET B][A][[IRQEN B][A][LOAD B][A]
209 18: LFRQ (LFO frequency)
210 19: PMD/AMD (7 bits, bit 8 => 1=PMD, 0=AMD)
211 1B: [CT][][XXXX][W][] (Ctrl Output,Wave => 0=saw, 1=square, 2=triangle, 3=noise)
214 [RL][][FB][][][CONECT][][] (Right/Left, Feedback, Connection)
215 [X][KC][][][][][][] (Key code, 7 bits: 3=octave, 4=note)
216 [KF][][][][][][XX] (Key fractionb, 6-bits)
217 [X][PMS][][][XX][AMS][]
219 [X][DT1][][][MUL][][][] (Detune 1, Phase multiply)
221 [X][TL][][][][][][] (Total level, 7 bits)
223 [KS][][X][AR][][][][] (Key scaling, Attack rate)
225 [AMS-EN][XX][D1R][][][][] (1st decay rate)
227 [DT2][][X][D2R][][][][] (Detune 2, 2nd decay rate)
229 [D1L][][][][RR][][][] (1st decay level, Release rate)
233 XX: [B][XXXXX][ist][] (Busy flag, 0=ready, 1=busy; IRQ status)
236 FUNCTION | Modulator 1 | Modulator 2 | Carrier 1 2 |
237 ---------+-----------------+------------------------+------------ ... ---|
238 Slot # | 1 2 3 4 5 6 7 8 | 9 10 11 12 13 14 15 16 | 17 18 19 20 ... 32 |
239 Channel #| 1 2 3 4 5 6 7 8 | 1 2 3 4 5 6 7 8 | 1 2 3 4 ... 8 |
242 NOTE: C# D D# E F F# G G# A A# B C
243 0 1 2 4 5 6 8 9 10 12 13 14
248 int main(int, char * [])
251 memset(&mcu, 0, sizeof(V63701REGS));
252 mcu.RdMem = ReadMemory;
253 mcu.WrMem = WriteMemory;
255 mcu.cpuFlags |= V63701_ASSERT_LINE_RESET;
257 uint8_t * sbp[1] = { soundBuffer };
258 // soundBuffer[0] = new uint8_t[1024];
259 // ptrToBuffer = (SAMPLE **)sbp;
261 if (YMInit(1, 3579580, 48000, 16, 512, (SAMPLE **)sbp))
263 WriteLog("YM: Could not init YM2151 emulator!\n");
270 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE) != 0)
272 WriteLog("Video: Could not initialize the SDL library: %s\n", SDL_GetError());
276 SDL_Window * sdlWindow = NULL;
277 SDL_Renderer * sdlRenderer = NULL;
278 int retVal = SDL_CreateWindowAndRenderer(500, 400, SDL_WINDOW_OPENGL, &sdlWindow, &sdlRenderer);
282 WriteLog("Video: Could not window and/or renderer: %s\n", SDL_GetError());
290 startTicks = SDL_GetTicks();
292 //try to get some noise outta this sucka
293 //YMWriteReg(0, 0x20, 0xC0); // Enable R+L channel
294 //YMWriteReg(0, 0x21, 0xC0); // Enable R+L channel
295 YMWriteReg(0, 0x28, 0x4A); // KC = A 440
296 YMWriteReg(0, 0x29, 0x50); // KC = C# 440+
297 YMWriteReg(0, 0x2A, 0x34); // KC = E 440-
298 YMWriteReg(0, 0x40, 0x01); // Write phase multiply of 1
299 YMWriteReg(0, 0x41, 0x01); // Write phase multiply of 1
300 YMWriteReg(0, 0x42, 0x01); // Write phase multiply of 1
301 YMWriteReg(0, 0x60, 0x7F); // Total level = 127
302 YMWriteReg(0, 0x61, 0x7F); // Total level = 127
303 YMWriteReg(0, 0x62, 0x7F); // Total level = 127
304 YMWriteReg(0, 0xE0, 0x7F); // 1st decay = 7, release = 15
305 YMWriteReg(0, 0xE1, 0x7F); // 1st decay = 7, release = 15
306 YMWriteReg(0, 0xE2, 0x7F); // 1st decay = 7, release = 15
307 YMWriteReg(0, 0x08, 0x78); // Key on channel #1, M1+C1+M2+C2
308 YMWriteReg(0, 0x08, 0x79); // Key on channel #2, M1+C1+M2+C2
309 YMWriteReg(0, 0x08, 0x7A); // Key on channel #3, M1+C1+M2+C2
313 while (SDL_PollEvent(&event))
318 if (event.key.keysym.sym == SDLK_ESCAPE)
320 else if (event.key.keysym.sym == SDLK_SPACE)
322 YMWriteReg(0, 0x08, 0x40);
323 YMWriteReg(0, 0x08, 0x41);
324 YMWriteReg(0, 0x08, 0x42);
326 else if (event.key.keysym.sym == SDLK_1)
330 else if (event.key.keysym.sym == SDLK_2)
334 else if (event.key.keysym.sym == SDLK_3)
338 else if (event.key.keysym.sym == SDLK_4)
342 else if (event.key.keysym.sym == SDLK_5)
346 else if (event.key.keysym.sym == SDLK_6)
350 else if (event.key.keysym.sym == SDLK_7)
354 else if (event.key.keysym.sym == SDLK_8)
358 else if (event.key.keysym.sym == SDLK_9)
362 else if (event.key.keysym.sym == SDLK_0)
366 else if (event.key.keysym.sym == SDLK_q)
370 else if (event.key.keysym.sym == SDLK_w)
374 else if (event.key.keysym.sym == SDLK_e)
381 // 49152000/32 = 1536000 Hz, /60 = 25600
382 Execute63701(&mcu, 25600);
384 frameCount = (frameCount + 1) % 3;
385 uint32_t waitFrameTime = 17 - (frameCount == 0 ? 1 : 0);
387 // Wait for next frame...
388 while (SDL_GetTicks() - startTicks < waitFrameTime)
391 startTicks = SDL_GetTicks();
397 // delete[] soundBuffer[0];
400 FILE * f = fopen("mcu-dis-$4000.txt", "w");
401 uint32_t address = 0x4000;
402 //for(uint32_t i=0xF000, i<0x10000; i++)
406 address += Decode63701(memory, address, line);
407 fprintf(f, "%s\n", line);
409 while (address < 0xC000);
413 printf("MCU state:\nPC=%04X, S=%04X, X=%04X, D=%04X, CC=%02X\n", mcu.pc, mcu.s, mcu.x, mcu.d.word, mcu.cc);
420 #define MCU_MEMORY(NAME,ADDR_LOWROM,ADDR_INPUT,ADDR_UNK1,ADDR_UNK2) \
421 static MEMORY_READ_START( NAME##_mcu_readmem ) \
422 { 0x0000, 0x001f, hd63701_internal_registers_r }, \
423 { 0x0080, 0x00ff, MRA_RAM }, \
424 { 0x1000, 0x10ff, namcos1_wavedata_r }, /* PSG device, shared RAM */ \
425 { 0x1100, 0x113f, namcos1_sound_r }, /* PSG device, shared RAM */ \
426 { 0x1000, 0x13ff, shared1_r }, \
427 { 0x1400, 0x1fff, MRA_RAM }, \
428 { ADDR_INPUT+0x00, ADDR_INPUT+0x01, YM2151_status_port_0_r }, \
429 { ADDR_INPUT+0x20, ADDR_INPUT+0x20, input_port_0_r }, \
430 { ADDR_INPUT+0x21, ADDR_INPUT+0x21, input_port_1_r }, \
431 { ADDR_INPUT+0x30, ADDR_INPUT+0x30, dsw0_r }, \
432 { ADDR_INPUT+0x31, ADDR_INPUT+0x31, dsw1_r }, \
433 { ADDR_LOWROM, ADDR_LOWROM+0x3fff, MRA_ROM }, \
434 { 0x8000, 0xbfff, MRA_ROM }, \
435 { 0xf000, 0xffff, MRA_ROM }, \
438 static MEMORY_WRITE_START( NAME##_mcu_writemem ) \
439 { 0x0000, 0x001f, hd63701_internal_registers_w }, \
440 { 0x0080, 0x00ff, MWA_RAM }, \
441 { 0x1000, 0x10ff, namcos1_wavedata_w }, /* PSG device, shared RAM */ \
442 { 0x1100, 0x113f, namcos1_sound_w }, /* PSG device, shared RAM */ \
443 { 0x1000, 0x13ff, shared1_w }, \
444 { 0x1400, 0x1fff, MWA_RAM }, \
445 { ADDR_INPUT+0x00, ADDR_INPUT+0x00, YM2151_register_port_0_w }, \
446 { ADDR_INPUT+0x01, ADDR_INPUT+0x01, YM2151_data_port_0_w }, \
447 { ADDR_UNK1, ADDR_UNK1, MWA_NOP }, /* ??? written (not always) at end of interrupt */ \
448 { ADDR_UNK2, ADDR_UNK2, MWA_NOP }, /* ??? written (not always) at end of interrupt */ \
449 { ADDR_LOWROM, ADDR_LOWROM+0x3fff, MWA_ROM }, \
450 { 0x8000, 0xbfff, MWA_ROM }, \
451 { 0xf000, 0xffff, MWA_ROM }, \
454 #define UNUSED 0x4000
455 /* LOWROM INPUT UNK1 UNK2 */
456 MCU_MEMORY( rthunder, 0x4000, 0x2000, 0xb000, 0xb800 )
466 Sound: Successfully initialized.
467 V63701 read $00 from $00...
468 V63701 read $00 from $14...
470 V63701 wrote $40 to $14...
471 V63701 wrote $FF to $05...
473 V63701 read $40 from $14...
475 V63701 wrote $40 to $14...
476 V63701 wrote $00 to $02...
477 V63701 wrote $00 to $00...
479 V63701 read $40 from $14...
480 V63701 read $00 from $08...
482 V63701 wrote $00 to $09...
483 V63701 wrote $00 to $0A...
484 V63701 wrote $01 to $0B...
485 V63701 wrote $00 to $0C...
487 V63701 read $00 from $08...
489 V63701 wrote $08 to $08...
491 V63701 read $00 from $02...
492 V63701 read $00 from $02...
493 V63701 read $00 from $02...
495 V63701 wrote $00 to $03...
496 V63701 wrote $18 to $01...
497 V63701 wrote $C0 to $14...
500 PC=814F, S=1FFD, X=8065, D=A600, CC=C4
505 8110: 86 C0 LDAA #$C0
506 [PC=8112 S=1FFF X=1100 A=C0 B=00 CC=..N... TN=2C00 CT=2BBA OC=2C00 TO=3F00]
508 [PC=8114 S=1FFF X=1100 A=C0 B=00 CC=..N... TN=2C00 CT=2BBC OC=2C00 TO=3F00]
510 [PC=8116 S=1FFF X=14F0 A=C0 B=00 CC=...... TN=2C00 CT=2BBF OC=2C00 TO=3F00]
512 ; Fetches 3 bytes here instead of 2!!
513 8116: 6D 7A TST $7A,X
514 [PC=8119 S=1FFF X=14F0 A=C0 B=00 CC=...... TN=2C00 CT=2BC3 OC=2C00 TO=3F00]
516 ; Execution is wrong at this point!!
518 [PC=811A S=1FFF X=14F0 A=C0 B=00 CC=...... TN=2C00 CT=2BC7 OC=2C00 TO=3F00]
520 [PC=811C S=1FFF X=14F0 A=00 B=00 CC=...Z.. TN=2C00 CT=2BC8 OC=2C00 TO=3F00]
522 [PC=811E S=1FFF X=14F0 A=00 B=00 CC=...Z.. TN=2C00 CT=2BCB OC=2C00 TO=3F00]
524 [PC=8120 S=1FFF X=14F0 A=00 B=00 CC=...Z.. TN=2C00 CT=2BCE OC=2C00 TO=3F00]
525 8120: 7F 00 82 CLR $0082
526 [PC=8123 S=1FFF X=14F0 A=00 B=00 CC=...Z.. TN=2C00 CT=2BD1 OC=2C00 TO=3F00]
528 [PC=8125 S=1FFF X=8068 A=00 B=00 CC=..N... TN=2C00 CT=2BD6 OC=2C00 TO=3F00]
529 8125: AD 00 JSR $00,X
530 [PC=8068 S=1FFD X=8068 A=00 B=00 CC=..N... TN=2C00 CT=2BDA OC=2C00 TO=3F00]
532 [PC=8127 S=1FFF X=8068 A=00 B=00 CC=..N... TN=2C00 CT=2BDF OC=2C00 TO=3F00]
533 8127: 86 A6 LDAA #$A6
534 [PC=8129 S=1FFF X=8068 A=A6 B=00 CC=..N... TN=2C00 CT=2BE4 OC=2C00 TO=3F00]
535 8129: B7 11 82 STAA $1182
536 [PC=812C S=1FFF X=8068 A=A6 B=00 CC=..N... TN=2C00 CT=2BE6 OC=2C00 TO=3F00]
538 [PC=812E S=1FFF X=14F0 A=A6 B=00 CC=...... TN=2C00 CT=2BEA OC=2C00 TO=3F00]
539 812E: EE 2C LDX $2C,X
540 [PC=8130 S=1FFF X=8065 A=A6 B=00 CC=..N... TN=2C00 CT=2BEE OC=2C00 TO=3F00]
541 8130: AD 00 JSR $00,X
542 [PC=8065 S=1FFD X=8065 A=A6 B=00 CC=..N... TN=2C00 CT=2BF3 OC=2C00 TO=3F00]
543 8065: B7 B0 00 STAA $B000
544 [PC=8068 S=1FFD X=8065 A=A6 B=00 CC=..N... TN=2C00 CT=2BF8 OC=2C00 TO=3F00]
546 [PC=8132 S=1FFF X=8065 A=A6 B=00 CC=..N... TN=2C00 CT=2BFC OC=2C00 TO=3F00]