void OPL_Delay(uint64_t us) { delay_data_t delay_data; if (driver == NULL) { return; } // Create a callback that will signal this thread after the // specified time. delay_data.finished = 0; delay_data.mutex = SDL_CreateMutex(); delay_data.cond = SDL_CreateCond(); OPL_SetCallback(us, DelayCallback, &delay_data); // Wait until the callback is invoked. SDL_LockMutex(delay_data.mutex); while (!delay_data.finished) { SDL_CondWait(delay_data.cond, delay_data.mutex); } SDL_UnlockMutex(delay_data.mutex); // Clean up. SDL_DestroyMutex(delay_data.mutex); SDL_DestroyCond(delay_data.cond); }
void TimerCallback(void *data) { struct timer_data *timer_data = data; int delay; if (!timer_data->running) { return; } // Read data until we must make a delay. for (;;) { int reg, val; // End of file? if (feof(timer_data->fstream)) { timer_data->running = 0; return; } reg = fgetc(timer_data->fstream); val = fgetc(timer_data->fstream); // Register value of 0 or 1 indicates a delay. if (reg == 0x00) { delay = val; break; } else if (reg == 0x01) { val |= (fgetc(timer_data->fstream) << 8); delay = val; break; } else { WriteReg(reg, val); } } // Schedule the next timer callback. OPL_SetCallback(delay, TimerCallback, timer_data); }
void PlayFile(char *filename) { struct timer_data timer_data; int running; char buf[8]; timer_data.fstream = fopen(filename, "rb"); if (timer_data.fstream == NULL) { fprintf(stderr, "Failed to open %s\n", filename); exit(-1); } if (fread(buf, 1, 8, timer_data.fstream) < 8) { fprintf(stderr, "failed to read raw OPL header\n"); exit(-1); } if (strncmp(buf, HEADER_STRING, 8) != 0) { fprintf(stderr, "Raw OPL header not found\n"); exit(-1); } fseek(timer_data.fstream, 28, SEEK_SET); timer_data.running = 1; // Start callback loop sequence. OPL_SetCallback(0, TimerCallback, &timer_data); // Sleep until the playback finishes. do { OPL_Lock(); running = timer_data.running; OPL_Unlock(); SDL_Delay(100); } while (running); fclose(timer_data.fstream); }