void pcm_init(double clock, int samplerate) { /* PCM chip is running at original rate and is synchronized with SUB-CPU */ /* Chip output is resampled to desired rate using Blip Buffer. */ blip_set_rates(snd.blips[1][0], clock / PCM_SCYCLES_RATIO, samplerate); blip_set_rates(snd.blips[1][1], clock / PCM_SCYCLES_RATIO, samplerate); }
void pcm_init(blip_t* left, blip_t* right) { /* number of SCD master clocks run per second */ double mclk = snd.frame_rate ? (SCYCLES_PER_LINE * (vdp_pal ? 313 : 262) * snd.frame_rate) : SCD_CLOCK; /* PCM chips is running at original rate and is synchronized with SUB-CPU */ /* Chip output is resampled to desired rate using Blip Buffer. */ blip[0] = left; blip[1] = right; blip_set_rates(left, mclk / PCM_SCYCLES_RATIO, snd.sample_rate); blip_set_rates(right, mclk / PCM_SCYCLES_RATIO, snd.sample_rate); }
void GBAudioInit(struct GBAudio* audio, size_t samples, uint8_t* nr52, enum GBAudioStyle style) { audio->samples = samples; audio->left = blip_new(BLIP_BUFFER_SIZE); audio->right = blip_new(BLIP_BUFFER_SIZE); audio->clockRate = DMG_LR35902_FREQUENCY; // Guess too large; we hang producing extra samples if we guess too low blip_set_rates(audio->left, DMG_LR35902_FREQUENCY, 96000); blip_set_rates(audio->right, DMG_LR35902_FREQUENCY, 96000); audio->forceDisableCh[0] = false; audio->forceDisableCh[1] = false; audio->forceDisableCh[2] = false; audio->forceDisableCh[3] = false; audio->masterVolume = GB_AUDIO_VOLUME_MAX; audio->nr52 = nr52; audio->style = style; }
static void _mSDLAudioCallback(void* context, Uint8* data, int len) { struct mSDLAudio* audioContext = context; if (!context || !audioContext->core) { memset(data, 0, len); return; } blip_t* left = NULL; blip_t* right = NULL; int32_t clockRate = GBA_ARM7TDMI_FREQUENCY; if (audioContext->core) { left = audioContext->core->getAudioChannel(audioContext->core, 0); right = audioContext->core->getAudioChannel(audioContext->core, 1); clockRate = audioContext->core->frequency(audioContext->core); } double fauxClock = 1; if (audioContext->sync) { if (audioContext->sync->fpsTarget > 0) { fauxClock = GBAAudioCalculateRatio(1, audioContext->sync->fpsTarget, 1); } mCoreSyncLockAudio(audioContext->sync); } blip_set_rates(left, clockRate, audioContext->obtainedSpec.freq * fauxClock); blip_set_rates(right, clockRate, audioContext->obtainedSpec.freq * fauxClock); len /= 2 * audioContext->obtainedSpec.channels; int available = blip_samples_avail(left); if (available > len) { available = len; } blip_read_samples(left, (short*) data, available, audioContext->obtainedSpec.channels == 2); if (audioContext->obtainedSpec.channels == 2) { blip_read_samples(right, ((short*) data) + 1, available, 1); } if (audioContext->sync) { mCoreSyncConsumeAudio(audioContext->sync); } if (available < len) { memset(((short*) data) + audioContext->obtainedSpec.channels * available, 0, (len - available) * audioContext->obtainedSpec.channels * sizeof(short)); } }
ECL_EXPORT bool Init(bool cgb, const uint8_t *spc, int spclen) { if (spc) { GB_init_sgb(&GB); if (!sgb_init(spc, spclen)) return false; sgb = true; } else if (cgb) { GB_init_cgb(&GB); } else { GB_init(&GB); } if (GB_load_boot_rom(&GB, "boot.rom") != 0) return false; if (GB_load_rom(&GB, "game.rom") != 0) return false; GB_set_pixels_output(&GB, GBPixels); GB_set_vblank_callback(&GB, VBlankCallback); GB_set_log_callback(&GB, LogCallback); GB_set_rgb_encode_callback(&GB, RgbEncodeCallback); GB_set_infrared_callback(&GB, InfraredCallback); GB_set_rumble_callback(&GB, RumbleCallback); GB_set_sample_callback(&GB, SampleCallback); leftblip = blip_new(1024); rightblip = blip_new(1024); blip_set_rates(leftblip, sgb ? SOUND_RATE_SGB : SOUND_RATE_GB, 44100); blip_set_rates(rightblip, sgb ? SOUND_RATE_SGB : SOUND_RATE_GB, 44100); return true; }
void GBAAudioInit(struct GBAAudio* audio, size_t samples) { audio->samples = samples; #if RESAMPLE_LIBRARY != RESAMPLE_BLIP_BUF CircleBufferInit(&audio->left, samples * sizeof(int16_t)); CircleBufferInit(&audio->right, samples * sizeof(int16_t)); #else audio->left = blip_new(BLIP_BUFFER_SIZE); audio->right = blip_new(BLIP_BUFFER_SIZE); // Guess too large; we hang producing extra samples if we guess too low blip_set_rates(audio->left, GBA_ARM7TDMI_FREQUENCY, 96000); blip_set_rates(audio->right, GBA_ARM7TDMI_FREQUENCY, 96000); #endif CircleBufferInit(&audio->chA.fifo, GBA_AUDIO_FIFO_SIZE); CircleBufferInit(&audio->chB.fifo, GBA_AUDIO_FIFO_SIZE); audio->forceDisableCh[0] = false; audio->forceDisableCh[1] = false; audio->forceDisableCh[2] = false; audio->forceDisableCh[3] = false; audio->forceDisableChA = false; audio->forceDisableChB = false; audio->masterVolume = GBA_AUDIO_VOLUME_MAX; }
void end_audio_frame() { if (frame_offset == 0) // No audio added; blip_end_frame() dislikes being called with an // offset of 0 return; assert(!(is_backwards_frame && frame_offset != get_frame_len())); // Bring the signal level at the end of the frame to zero as outlined in // set_audio_signal_level() set_audio_signal_level(0); blip_end_frame(blip, frame_offset); if (playback_started) { // Fudge playback rate by an amount proportional to the difference // between the desired and current buffer fill levels to try to steer // towards it double const fudge_factor = 1.0 + 2*max_adjust*(0.5 - fill_level()); blip_set_rates(blip, cpu_clock_rate, sample_rate*fudge_factor); } else { if (fill_level() >= 0.5) { start_audio_playback(); playback_started = true; } } int const n_samples = blip_read_samples(blip, blip_samples, ARRAY_LEN(blip_samples), 0); // We expect to read all samples from blip_buf. If something goes wrong and // we don't, clear the buffer to prevent data piling up in blip_buf's // buffer (which lacks bounds checking). int const avail = blip_samples_avail(blip); if (avail != 0) { printf("Warning: didn't read all samples from blip_buf (%d samples remain) - dropping samples\n", avail); blip_clear(blip); } #ifdef RECORD_MOVIE add_movie_audio_frame(blip_samples, n_samples); #endif // Save the samples to the audio ring buffer lock_audio(); write_samples(blip_samples, n_samples); unlock_audio(); }
static void _GBASDLAudioCallback(void* context, Uint8* data, int len) { struct GBASDLAudio* audioContext = context; if (!context || !audioContext->thread || !audioContext->thread->gba) { memset(data, 0, len); return; } #if RESAMPLE_LIBRARY == RESAMPLE_NN audioContext->ratio = GBAAudioCalculateRatio(audioContext->thread->gba->audio.sampleRate, audioContext->thread->fpsTarget, audioContext->obtainedSpec.freq); if (audioContext->ratio == INFINITY) { memset(data, 0, len); return; } struct GBAStereoSample* ssamples = (struct GBAStereoSample*) data; len /= 2 * audioContext->obtainedSpec.channels; if (audioContext->obtainedSpec.channels == 2) { GBAAudioResampleNN(&audioContext->thread->gba->audio, audioContext->ratio, &audioContext->drift, ssamples, len); } #elif RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF double fauxClock = GBAAudioCalculateRatio(1, audioContext->thread->fpsTarget, 1); GBASyncLockAudio(&audioContext->thread->sync); blip_set_rates(audioContext->thread->gba->audio.left, GBA_ARM7TDMI_FREQUENCY, audioContext->obtainedSpec.freq * fauxClock); blip_set_rates(audioContext->thread->gba->audio.right, GBA_ARM7TDMI_FREQUENCY, audioContext->obtainedSpec.freq * fauxClock); len /= 2 * audioContext->obtainedSpec.channels; int available = blip_samples_avail(audioContext->thread->gba->audio.left); if (available > len) { available = len; } blip_read_samples(audioContext->thread->gba->audio.left, (short*) data, available, audioContext->obtainedSpec.channels == 2); if (audioContext->obtainedSpec.channels == 2) { blip_read_samples(audioContext->thread->gba->audio.right, ((short*) data) + 1, available, 1); } GBASyncConsumeAudio(&audioContext->thread->sync); if (available < len) { memset(((short*) data) + audioContext->obtainedSpec.channels * available, 0, (len - available) * audioContext->obtainedSpec.channels * sizeof(short)); } #endif }
void audio_set_rate(int samplerate, double framerate) { /* Number of M-cycles executed per second. */ /* All emulated chips are kept in sync by using a common oscillator (MCLOCK) */ /* */ /* The original console would run exactly 53693175 M-cycles per sec (53203424 for PAL), */ /* 3420 M-cycles per line and 262 (313 for PAL) lines per frame, which gives an exact */ /* framerate of 59.92 (49.70 for PAL) frames per second. */ /* */ /* Since audio samples are generated at the end of the frame, to prevent audio skipping */ /* or lag between emulated frames, number of samples rendered per frame must be set to */ /* output samplerate (number of samples played per second) divided by input framerate */ /* (number of frames emulated per seconds). */ /* */ /* On some systems, we may want to achieve 100% smooth video rendering by synchronizing */ /* frame emulation with VSYNC, which frequency is generally not exactly those values. */ /* In that case, input framerate (number of frames emulated per seconds) is the same as */ /* output framerate (number of frames rendered per seconds) by the host video hardware. */ /* */ /* When no framerate is specified, base clock is set to original master clock value. */ /* Otherwise, it is set to number of M-cycles emulated per line (fixed) multiplied by */ /* number of lines per frame (VDP mode specific) multiplied by input framerate. */ /* */ double mclk = framerate ? (MCYCLES_PER_LINE * (vdp_pal ? 313 : 262) * framerate) : system_clock; /* For maximal accuracy, sound chips are running at their original rate using common */ /* master clock timebase so they remain perfectly synchronized together, while still */ /* being synchronized with 68K and Z80 CPUs as well. Mixed sound chip output is then */ /* resampled to desired rate at the end of each frame, using Blip Buffer. */ blip_set_rates(snd.blips[0], mclk, samplerate); /* Mega CD sound hardware */ if (system_hw == SYSTEM_MCD) { /* number of SCD master clocks run per second */ mclk = (mclk / system_clock) * SCD_CLOCK; /* PCM core */ pcm_init(mclk, samplerate); /* CDD core */ cdd_init(samplerate); } /* Reinitialize internal rates */ snd.sample_rate = samplerate; snd.frame_rate = framerate; }
bool retro_load_game(const struct retro_game_info* game) { struct VFile* rom; if (game->data) { data = anonymousMemoryMap(game->size); dataSize = game->size; memcpy(data, game->data, game->size); rom = VFileFromMemory(data, game->size); } else { data = 0; rom = VFileOpen(game->path, O_RDONLY); } if (!rom) { return false; } core = NULL; #ifdef M_CORE_GBA if (!core && GBAIsROM(rom)) { core = GBACoreCreate(); } #endif #ifdef M_CORE_GB if (!core && GBIsROM(rom)) { core = GBCoreCreate(); } #endif if (!core) { rom->close(rom); mappedMemoryFree(data, game->size); return false; } mCoreInitConfig(core, NULL); core->init(core); core->setAVStream(core, &stream); outputBuffer = malloc(256 * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL); core->setVideoBuffer(core, outputBuffer, 256); core->setAudioBufferSize(core, SAMPLES); blip_set_rates(core->getAudioChannel(core, 0), core->frequency(core), 32768); blip_set_rates(core->getAudioChannel(core, 1), core->frequency(core), 32768); core->setRumble(core, &rumble); #ifdef M_CORE_GBA if (core->platform(core) == PLATFORM_GBA) { struct GBA* gba = core->board; gba->luminanceSource = &lux; const char* sysDir = 0; if (environCallback(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &sysDir)) { char biosPath[PATH_MAX]; snprintf(biosPath, sizeof(biosPath), "%s%s%s", sysDir, PATH_SEP, "gba_bios.bin"); struct VFile* bios = VFileOpen(biosPath, O_RDONLY); if (bios) { core->loadBIOS(core, bios, 0); } } GBACheatDeviceCreate(&cheats); GBACheatAttachDevice(gba, &cheats); GBACheatSetInit(&cheatSet, "libretro"); GBACheatAddSet(&cheats, &cheatSet); } #endif savedata = anonymousMemoryMap(SIZE_CART_FLASH1M); struct VFile* save = VFileFromMemory(savedata, SIZE_CART_FLASH1M); _reloadSettings(); core->loadROM(core, rom); core->loadSave(core, save); core->reset(core); return true; }
bool retro_load_game(const struct retro_game_info* game) { struct VFile* rom; if (game->data) { data = anonymousMemoryMap(game->size); dataSize = game->size; memcpy(data, game->data, game->size); rom = VFileFromMemory(data, game->size); } else { data = 0; rom = VFileOpen(game->path, O_RDONLY); } if (!rom) { return false; } core = mCoreFindVF(rom); if (!core) { rom->close(rom); mappedMemoryFree(data, game->size); return false; } mCoreInitConfig(core, NULL); core->init(core); core->setAVStream(core, &stream); size_t size = 256 * 224 * BYTES_PER_PIXEL; outputBuffer = malloc(size); memset(outputBuffer, 0xFF, size); core->setVideoBuffer(core, outputBuffer, 256); core->setAudioBufferSize(core, SAMPLES); blip_set_rates(core->getAudioChannel(core, 0), core->frequency(core), 32768); blip_set_rates(core->getAudioChannel(core, 1), core->frequency(core), 32768); core->setPeripheral(core, mPERIPH_RUMBLE, &rumble); savedata = anonymousMemoryMap(SIZE_CART_FLASH1M); struct VFile* save = VFileFromMemory(savedata, SIZE_CART_FLASH1M); _reloadSettings(); core->loadROM(core, rom); core->loadSave(core, save); const char* sysDir = 0; const char* biosName = 0; char biosPath[PATH_MAX]; environCallback(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &sysDir); #ifdef M_CORE_GBA if (core->platform(core) == PLATFORM_GBA) { core->setPeripheral(core, mPERIPH_GBA_LUMINANCE, &lux); biosName = "gba_bios.bin"; } #endif #ifdef M_CORE_GB if (core->platform(core) == PLATFORM_GB) { memset(&cam, 0, sizeof(cam)); cam.height = GBCAM_HEIGHT; cam.width = GBCAM_WIDTH; cam.caps = 1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER; cam.frame_raw_framebuffer = _updateCamera; core->setPeripheral(core, mPERIPH_IMAGE_SOURCE, &imageSource); environCallback(RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE, &cam); const char* modelName = mCoreConfigGetValue(&core->config, "gb.model"); struct GB* gb = core->board; if (modelName) { gb->model = GBNameToModel(modelName); } else { GBDetectModel(gb); } switch (gb->model) { case GB_MODEL_AGB: case GB_MODEL_CGB: biosName = "gbc_bios.bin"; break; case GB_MODEL_SGB: biosName = "sgb_bios.bin"; break; case GB_MODEL_DMG: default: biosName = "gb_bios.bin"; break; } } #endif if (core->opts.useBios && sysDir && biosName) { snprintf(biosPath, sizeof(biosPath), "%s%s%s", sysDir, PATH_SEP, biosName); struct VFile* bios = VFileOpen(biosPath, O_RDONLY); if (bios) { core->loadBIOS(core, bios, 0); } } core->reset(core); _setupMaps(core); return true; }
static void _setup(struct GBAGUIRunner* runner) { struct GBAOptions opts = { .useBios = true, .logLevel = 0, .idleOptimization = IDLE_LOOP_DETECT }; GBAConfigLoadDefaults(&runner->context.config, &opts); runner->context.gba->logHandler = GBA3DSLog; runner->context.gba->rotationSource = &rotation.d; if (hasSound) { runner->context.gba->stream = &stream; } GBAVideoSoftwareRendererCreate(&renderer); renderer.outputBuffer = linearAlloc(256 * VIDEO_VERTICAL_PIXELS * 2); renderer.outputBufferStride = 256; runner->context.renderer = &renderer.d; GBAAudioResizeBuffer(&runner->context.gba->audio, AUDIO_SAMPLES); } static void _gameLoaded(struct GBAGUIRunner* runner) { if (runner->context.gba->memory.hw.devices & HW_TILT) { HIDUSER_EnableAccelerometer(); } if (runner->context.gba->memory.hw.devices & HW_GYRO) { HIDUSER_EnableGyroscope(); } #if RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF double ratio = GBAAudioCalculateRatio(1, 60, 1); blip_set_rates(runner->context.gba->audio.left, GBA_ARM7TDMI_FREQUENCY, 0x8000 * ratio); blip_set_rates(runner->context.gba->audio.right, GBA_ARM7TDMI_FREQUENCY, 0x8000 * ratio); #endif if (hasSound) { memset(audioLeft, 0, AUDIO_SAMPLES * sizeof(int16_t)); memset(audioRight, 0, AUDIO_SAMPLES * sizeof(int16_t)); } } static void _gameUnloaded(struct GBAGUIRunner* runner) { if (hasSound) { CSND_SetPlayState(8, 0); CSND_SetPlayState(9, 0); csndExecCmds(false); } if (runner->context.gba->memory.hw.devices & HW_TILT) { HIDUSER_DisableAccelerometer(); } if (runner->context.gba->memory.hw.devices & HW_GYRO) { HIDUSER_DisableGyroscope(); } } static void _drawFrame(struct GBAGUIRunner* runner, bool faded) { GX_SetDisplayTransfer(0, renderer.outputBuffer, GX_BUFFER_DIM(256, VIDEO_VERTICAL_PIXELS), tex->data, GX_BUFFER_DIM(256, VIDEO_VERTICAL_PIXELS), 0x000002202); GSPGPU_FlushDataCache(0, tex->data, 256 * VIDEO_VERTICAL_PIXELS * 2); #if RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF if (!hasSound) { blip_clear(runner->context.gba->audio.left); blip_clear(runner->context.gba->audio.right); } #endif gspWaitForPPF(); _drawStart(); sf2d_draw_texture_scale_blend(tex, 40, 296, 1, -1, 0xFFFFFF3F | (faded ? 0 : 0xC0)); _drawEnd(); }
int audio_init(int samplerate, double framerate) { /* Number of M-cycles executed per second. */ /* All emulated chips are kept in sync by using a common oscillator (MCLOCK) */ /* */ /* The original console would run exactly 53693175 M-cycles per sec (53203424 for PAL), */ /* 3420 M-cycles per line and 262 (313 for PAL) lines per frame, which gives an exact */ /* framerate of 59.92 (49.70 for PAL) frames per second. */ /* */ /* Since audio samples are generated at the end of the frame, to prevent audio skipping */ /* or lag between emulated frames, number of samples rendered per frame must be set to */ /* output samplerate (number of samples played per second) divided by input framerate */ /* (number of frames emulated per seconds). */ /* */ /* On some systems, we may want to achieve 100% smooth video rendering by synchronizing */ /* frame emulation with VSYNC, which frequency is generally not exactly those values. */ /* In that case, input framerate (number of frames emulated per seconds) is the same as */ /* output framerate (number of frames rendered per seconds) by the host video hardware. */ /* */ /* When no framerate is specified, base clock is set to original master clock value. */ /* Otherwise, it is set to number of M-cycles emulated per line (fixed) multiplied by */ /* number of lines per frame (VDP mode specific) multiplied by input framerate. */ /* */ double mclk = framerate ? (MCYCLES_PER_LINE * (vdp_pal ? 313 : 262) * framerate) : system_clock; /* Shutdown first */ audio_shutdown(); /* Clear the sound data context */ memset(&snd, 0, sizeof (snd)); /* Initialize audio rates */ snd.sample_rate = samplerate; snd.frame_rate = framerate; /* Initialize Blip Buffers */ snd.blips[0][0] = blip_new(samplerate / 10); snd.blips[0][1] = blip_new(samplerate / 10); if (!snd.blips[0][0] || !snd.blips[0][1]) { audio_shutdown(); return -1; } /* For maximal accuracy, sound chips are running at their original rate using common */ /* master clock timebase so they remain perfectly synchronized together, while still */ /* being synchronized with 68K and Z80 CPUs as well. Mixed sound chip output is then */ /* resampled to desired rate at the end of each frame, using Blip Buffer. */ blip_set_rates(snd.blips[0][0], mclk, samplerate); blip_set_rates(snd.blips[0][1], mclk, samplerate); /* Initialize PSG core */ SN76489_Init(snd.blips[0][0], snd.blips[0][1], (system_hw < SYSTEM_MARKIII) ? SN_DISCRETE : SN_INTEGRATED); /* Mega CD sound hardware */ if (system_hw == SYSTEM_MCD) { /* allocate blip buffers */ snd.blips[1][0] = blip_new(samplerate / 10); snd.blips[1][1] = blip_new(samplerate / 10); snd.blips[2][0] = blip_new(samplerate / 10); snd.blips[2][1] = blip_new(samplerate / 10); if (!snd.blips[1][0] || !snd.blips[1][1] || !snd.blips[2][0] || !snd.blips[2][1]) { audio_shutdown(); return -1; } /* Initialize PCM core */ pcm_init(snd.blips[1][0], snd.blips[1][1]); /* Initialize CDD core */ cdd_init(snd.blips[2][0], snd.blips[2][1]); } /* Set audio enable flag */ snd.enabled = 1; /* Reset audio */ audio_reset(); return (0); }
void retro_init(void) { enum retro_pixel_format fmt; #ifdef COLOR_16_BIT #ifdef COLOR_5_6_5 fmt = RETRO_PIXEL_FORMAT_RGB565; #else #warning This pixel format is unsupported. Please use -DCOLOR_16-BIT -DCOLOR_5_6_5 fmt = RETRO_PIXEL_FORMAT_0RGB1555; #endif #else #warning This pixel format is unsupported. Please use -DCOLOR_16-BIT -DCOLOR_5_6_5 fmt = RETRO_PIXEL_FORMAT_XRGB8888; #endif environCallback(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt); struct retro_input_descriptor inputDescriptors[] = { { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "A" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Right" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Left" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Up" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Down" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "Brighten Solar Sensor" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "Darken Solar Sensor" } }; environCallback(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, &inputDescriptors); // TODO: RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME when BIOS booting is supported struct retro_rumble_interface rumbleInterface; if (environCallback(RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE, &rumbleInterface)) { rumbleCallback = rumbleInterface.set_rumble_state; CircleBufferInit(&rumbleHistory, RUMBLE_PWM); rumble.setRumble = _setRumble; } else { rumbleCallback = 0; } luxLevel = 0; lux.readLuminance = _readLux; lux.sample = _updateLux; _updateLux(&lux); struct retro_log_callback log; if (environCallback(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log)) { logCallback = log.log; } else { logCallback = 0; } stream.postAudioFrame = 0; stream.postAudioBuffer = _postAudioBuffer; stream.postVideoFrame = _postVideoFrame; GBACreate(&gba); ARMSetComponents(&cpu, &gba.d, 0, 0); ARMInit(&cpu); gba.logLevel = 0; // TODO: Settings gba.logHandler = GBARetroLog; gba.stream = &stream; gba.idleOptimization = IDLE_LOOP_REMOVE; // TODO: Settings if (rumbleCallback) { gba.rumble = &rumble; } gba.luminanceSource = &lux; rom = 0; const char* sysDir = 0; if (environCallback(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &sysDir)) { char biosPath[PATH_MAX]; snprintf(biosPath, sizeof(biosPath), "%s%s%s", sysDir, PATH_SEP, "gba_bios.bin"); bios = VFileOpen(biosPath, O_RDONLY); if (bios) { GBALoadBIOS(&gba, bios); } } GBAVideoSoftwareRendererCreate(&renderer); renderer.outputBuffer = malloc(256 * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL); renderer.outputBufferStride = 256; GBAVideoAssociateRenderer(&gba.video, &renderer.d); GBAAudioResizeBuffer(&gba.audio, SAMPLES); #if RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF blip_set_rates(gba.audio.left, GBA_ARM7TDMI_FREQUENCY, 32768); blip_set_rates(gba.audio.right, GBA_ARM7TDMI_FREQUENCY, 32768); #endif }
void init_audio_for_rom() { // Maximum number of unread samples the buffer can hold blip = blip_new(sample_rate/10); blip_set_rates(blip, cpu_clock_rate, sample_rate); }