diff --git a/source/app.d b/source/app.d index 0f2b032..b715a37 100644 --- a/source/app.d +++ b/source/app.d @@ -31,7 +31,10 @@ version (unittest) { // shoot me, but im hardcoding it for now. nds.load_bios7(load_file_as_bytes("roms/biosnds7.rom")); nds.load_bios9(load_file_as_bytes("roms/biosnds9.rom")); - nds.load_firmware(load_file_as_bytes("roms/firmware.rom")); + + MmFile firmware_file = new MmFile("roms/firmware.rom", MmFile.Mode.readWrite, 262144, null, 0); + nds.load_firmware(firmware_file); + nds.load_rom(load_file_as_bytes(cli_args.rom_path)); auto save_path = cli_args.rom_path.stripExtension().setExtension(".bsv"); @@ -41,8 +44,8 @@ version (unittest) { } } - MmFile mm_file = new MmFile(save_path, MmFile.Mode.readWrite, nds.get_backup_size(), null, 0); - nds.load_save_mmfile(mm_file); + MmFile save_file = new MmFile(save_path, MmFile.Mode.readWrite, nds.get_backup_size(), null, 0); + nds.load_save_mmfile(save_file); nds.set_sample_rate(48_000); diff --git a/source/emu/hw/gpu/gpu.d b/source/emu/hw/gpu/gpu.d index 13b4dd2..f4de928 100644 --- a/source/emu/hw/gpu/gpu.d +++ b/source/emu/hw/gpu/gpu.d @@ -45,8 +45,6 @@ final class GPU { // } void on_hblank_start() { - log_gpu3d("on_hblank_start()"); - if (hblank_irq_enabled9) interrupt9.raise_interrupt(Interrupt.LCD_HBLANK); if (hblank_irq_enabled7) interrupt7.raise_interrupt(Interrupt.LCD_HBLANK); @@ -65,21 +63,14 @@ final class GPU { } void on_hblank_end() { - log_gpu3d("on_hblank_end(%d)", scanline); - hblank = false; scanline++; - log_gpu3d("here3"); gpu_engine_a.ppu.canvas.on_hblank_end(scanline); - log_gpu3d("here5"); gpu_engine_b.ppu.canvas.on_hblank_end(scanline); - log_gpu3d("here4 %d", scanline); if (scanline == 192) on_vblank_start(); - log_gpu3d("here68"); - import std.stdio; if (scanline == 263) on_vblank_end(); if (scanline == vcount_lyc) { @@ -91,8 +82,6 @@ final class GPU { } void set_hblank_flag() { - log_gpu3d("set_hblank_flag()"); - hblank = true; if (0 <= scanline && scanline < 192) { @@ -111,21 +100,12 @@ final class GPU { } void on_vblank_end() { - - log_gpu3d("here69"); - import std.stdio; - // readln(); - vblank = false; scanline = 0; - log_gpu3d("here11"); - import std.stdio; - // readln(); apply_master_brightness_to_video_buffers(&gpu_engine_a.videobuffer, &gpu_engine_b.videobuffer); - log_gpu3d("here12"); -log_ppu("pointers: %x %x %x %x", gpu_engine_a.videobuffer.ptr, gpu_engine_b.videobuffer.ptr, gpu_engine_a.videobuffer.length, gpu_engine_b.videobuffer.length); if (display_swap) { + if (display_swap) { present_videobuffers(&gpu_engine_a.videobuffer, &gpu_engine_b.videobuffer); } else { present_videobuffers(&gpu_engine_b.videobuffer, &gpu_engine_a.videobuffer); @@ -254,30 +234,15 @@ log_ppu("pointers: %x %x %x %x", gpu_engine_a.videobuffer.ptr, gpu_engine_b.vide int master_brightness_b; void apply_master_brightness_to_video_buffers(Pixel[192][256]* top, Pixel[192][256]* bot) { - import std.stdio; - log_gpu3d("here"); - // readln(); - // log_gpu3d("here %x %x", top, bot); apply_master_brightness_to_video_buffer(top, master_brightness_a, master_bright_mode_a); - log_gpu3d("here"); - // readln(); - // log_gpu3d("here %x %x", top, bot); apply_master_brightness_to_video_buffer(bot, master_brightness_b, master_bright_mode_b); - log_gpu3d("here"); - // readln(); - // log_gpu3d("here %x %x", top, bot); } void apply_master_brightness_to_video_buffer(Pixel[192][256]* video_buffer, ref int master_brightness, ref MasterBrightMode master_bright_mode) { import std.stdio; - if (master_bright_mode == MasterBrightMode.DISABLED) return; - log_gpu3d("here2"); - // readln(); for (int x = 0; x < 256; x++) { for (int y = 0; y < 192; y++) { - log_gpu3d("here6"); - // readln(); (*video_buffer)[x][y].r = ((*video_buffer)[x][y].r * master_brightness) / 64; (*video_buffer)[x][y].g = ((*video_buffer)[x][y].g * master_brightness) / 64; (*video_buffer)[x][y].b = ((*video_buffer)[x][y].b * master_brightness) / 64; diff --git a/source/emu/hw/gpu/gpu3d/geometry_engine.d b/source/emu/hw/gpu/gpu3d/geometry_engine.d index eefb20c..5dd4cb0 100644 --- a/source/emu/hw/gpu/gpu3d/geometry_engine.d +++ b/source/emu/hw/gpu/gpu3d/geometry_engine.d @@ -280,9 +280,6 @@ final class GeometryEngine { case MatrixMode.TEXTURE: texture_matrix = matrix; - for (int x = 0; x < 4; x++) { - log_gpu3d("TEXMATR %f %f %f %f", cast(float) texture_matrix[x][0], cast(float) texture_matrix[x][1], cast(float) texture_matrix[x][2], cast(float) texture_matrix[x][3]); - } break; } } @@ -401,17 +398,6 @@ final class GeometryEngine { void handle_MTX_LOAD_4x4(Word* args) { auto convert = (Word x) => FixedPoint!(20, 12).from_repr(x); - - if (matrix_mode == MatrixMode.TEXTURE) { - for (int x = 0; x < 4; x++) { - log_gpu3d("TEXMATR input %08x %08x %08x %08x", - args[x * 4 + 0], - args[x * 4 + 1], - args[x * 4 + 2], - args[x * 4 + 3] - ); - } - } set_current_matrix( Matrix([ diff --git a/source/emu/hw/gpu/gpu3d/gpu3d.d b/source/emu/hw/gpu/gpu3d/gpu3d.d index 243cf4e..d5ae0d0 100644 --- a/source/emu/hw/gpu/gpu3d/gpu3d.d +++ b/source/emu/hw/gpu/gpu3d/gpu3d.d @@ -137,7 +137,7 @@ final class GPU3D { void plot(int scanline, Pixel p, int x, Coord_14_18 z, Coord_14_18 w) { Coord_14_18 depth_value = depth_buffering_mode ? w : z; - if (depth_buffering_mode ? (w < 0) : (z < 0)) return; + if (depth_buffering_mode ? (w < 0) : (w < 0)) return; // if (depth_buffer[scanline][x] >= depth_value && p.a != 0) { // depth_buffer[scanline][x] = depth_value; diff --git a/source/emu/hw/gpu/gpu3d/rendering_engine.d b/source/emu/hw/gpu/gpu3d/rendering_engine.d index 7da1ddc..290ba46 100644 --- a/source/emu/hw/gpu/gpu3d/rendering_engine.d +++ b/source/emu/hw/gpu/gpu3d/rendering_engine.d @@ -295,9 +295,6 @@ final class RenderingEngine { parent.start_rendering(); for (int i = 0; i < num_polygons; i++) { - // if (i == 1) continue; - if (i == 1) log_gpu3d("alpha: %x", annotated_polygons[i].orig.alpha); - // log_gpu3d("rendering funky polygon #%d", i); auto p = annotated_polygons[i]; diff --git a/source/emu/hw/memory/strategy/memstrategy.d b/source/emu/hw/memory/strategy/memstrategy.d index 87fb80f..853afce 100644 --- a/source/emu/hw/memory/strategy/memstrategy.d +++ b/source/emu/hw/memory/strategy/memstrategy.d @@ -7,7 +7,7 @@ import emu.hw.memory.strategy.fastmem; import emu.hw.memory.strategy.slowmem; import util; -alias Mem = SlowMem; +alias Mem = FastMem; interface MemStrategy { Word read_data_word7(Word address); diff --git a/source/emu/hw/misc/rtc.d b/source/emu/hw/misc/rtc.d index 6eb85d0..ded5210 100644 --- a/source/emu/hw/misc/rtc.d +++ b/source/emu/hw/misc/rtc.d @@ -305,14 +305,6 @@ final class RTC_S_35199A01 { this.date_time_hh.value = to_bcd(st.hour); this.date_time_mm.value = to_bcd(st.minute); this.date_time_ss.value = to_bcd(st.second); - - this.date_time_year.value = 0; // to_bcd(st.year - 2000); - this.date_time_month.value = 0; //to_bcd(st.month); - this.date_time_day.value = 0; //to_bcd(st.day); - this.date_time_day_of_week.value = 0; //to_bcd(st.dayOfWeek); - this.date_time_hh.value = 0; //to_bcd(st.hour); - this.date_time_mm.value = 0; //to_bcd(st.minute); - this.date_time_ss.value = 0; //to_bcd(st.second); } void reset() { diff --git a/source/emu/hw/nds.d b/source/emu/hw/nds.d index c039b0f..cf80a52 100644 --- a/source/emu/hw/nds.d +++ b/source/emu/hw/nds.d @@ -150,8 +150,8 @@ final class NDS { mem.load_bios9(data); } - void load_firmware(Byte[] data) { - firmware.load_firmware(data); + void load_firmware(MmFile mm_file) { + firmware.load_firmware(mm_file); } void direct_boot() { @@ -191,7 +191,7 @@ final class NDS { arm7.run_instruction(); arm9.run_instruction(); arm9.run_instruction(); - scheduler.tick(1); + scheduler.tick(2); scheduler.process_events(); while (arm7.halted && arm9.halted) { diff --git a/source/emu/hw/spi/device/eeprom.d b/source/emu/hw/spi/device/eeprom.d index 8bbdf4c..2684796 100644 --- a/source/emu/hw/spi/device/eeprom.d +++ b/source/emu/hw/spi/device/eeprom.d @@ -135,7 +135,7 @@ public class EEPROM(int page_size, int num_pages) : SPIDevice { case 0x9F: state = State.READING_JEDEC_ID; break; case 0x06: write_enable_latch = true; break; case 0x04: write_enable_latch = false; break; - default: error_eeprom("invalid eeprom command dummy: %x", b); + default: log_eeprom("invalid eeprom command dummy: %x", b); } } } \ No newline at end of file diff --git a/source/emu/hw/spi/device/firmware.d b/source/emu/hw/spi/device/firmware.d index 6a86565..dcb322a 100644 --- a/source/emu/hw/spi/device/firmware.d +++ b/source/emu/hw/spi/device/firmware.d @@ -2,6 +2,7 @@ module emu.hw.spi.device.firmware; import emu.hw.memory.mem; import emu.hw.spi.device; +import std.mmfile; import util; enum FirmwareLanguage { @@ -74,7 +75,7 @@ final class Firmware : SPIDevice { int access_number; - Byte[0x1000000] data; + MmFile data; Word address; this() { @@ -88,17 +89,17 @@ final class Firmware : SPIDevice { power_on = true; } - void load_firmware(Byte[] data) { - this.data[0..FIRMWARE_SIZE] = data[0..FIRMWARE_SIZE]; + void load_firmware(MmFile mm_file) { + this.data = mm_file; - user_settings.adc_x1 = data.read!Half(0x3FE58); - user_settings.adc_y1 = data.read!Half(0x3FE5A); - user_settings.scr_x1 = data.read!Byte(0x3FE5C); - user_settings.scr_y1 = data.read!Byte(0x3FE5D); - user_settings.adc_x2 = data.read!Half(0x3FE5E); - user_settings.adc_y2 = data.read!Half(0x3FE60); - user_settings.scr_x2 = data.read!Byte(0x3FE62); - user_settings.scr_y2 = data.read!Byte(0x3FE63); + user_settings.adc_x1 = (cast(Byte[]) data[]).read!Half(0x3FE58); + user_settings.adc_y1 = (cast(Byte[]) data[]).read!Half(0x3FE5A); + user_settings.scr_x1 = (cast(Byte[]) data[]).read!Byte(0x3FE5C); + user_settings.scr_y1 = (cast(Byte[]) data[]).read!Byte(0x3FE5D); + user_settings.adc_x2 = (cast(Byte[]) data[]).read!Half(0x3FE5E); + user_settings.adc_y2 = (cast(Byte[]) data[]).read!Half(0x3FE60); + user_settings.scr_x2 = (cast(Byte[]) data[]).read!Byte(0x3FE62); + user_settings.scr_y2 = (cast(Byte[]) data[]).read!Byte(0x3FE63); touchscreen.recalibrate(); } @@ -232,7 +233,7 @@ final class Firmware : SPIDevice { case 0xDB: command = Command.PageErase; return true; case 0xD8: command = Command.SectorErase; return true; - default: error_eeprom("invalid eeprom command dummy"); return false; + default: log_eeprom("invalid eeprom command dummy"); return false; } } } \ No newline at end of file diff --git a/source/emu/hw/spu/spu.d b/source/emu/hw/spu/spu.d index e663093..8508394 100644 --- a/source/emu/hw/spu/spu.d +++ b/source/emu/hw/spu/spu.d @@ -3,6 +3,7 @@ module emu.hw.spu.spu; import emu.hw.memory.mem9; import emu.hw.memory.strategy.memstrategy; import emu.scheduler; +import std.algorithm; import ui.device; import util; @@ -70,10 +71,15 @@ final class SPU { } void reset() { - log_gpu3d("spu reset()"); + // log_gpu3d("spu reset()"); scheduler.add_event_relative_to_self(&sample, cycles_per_sample); } + struct ChannelSample { + s32 L; + s32 R; + } + struct SoundChannel { public { int volume_mul; @@ -93,7 +99,7 @@ final class SPU { private { Word current_address; - Sample current_sample; + ChannelSample current_sample; bool half_read; int extra_cycles; int cycles_since_last_sample_was_calculated; @@ -101,17 +107,20 @@ final class SPU { Byte ima_byte; short ima_pcm16bit; int ima_index; + Byte ima_byte_at_pnt; + short ima_pcm16bit_at_pnt; + int ima_index_at_pnt; } void reset() { current_address = source_address; - current_sample = Sample(0, 0); + current_sample = ChannelSample(0, 0); cycles_since_last_sample_was_calculated = 0; half_read = 0; } - Sample get_sample(Mem mem) { - if (!enabled) return Sample(0, 0); + ChannelSample get_sample(Mem mem) { + if (!enabled) return ChannelSample(0, 0); cycles_since_last_sample_was_calculated += spu.cycles_per_sample; @@ -122,14 +131,38 @@ final class SPU { cycles_since_last_sample_was_calculated -= cycles_till_calculate_next_sample; } - Sample sample; - sample.L = cast(short) ((((current_sample.L) / (this.volume_div + 1.0f)) * (this.volume_mul)) / 128); - sample.R = cast(short) ((((current_sample.R) / (this.volume_div + 1.0f)) * (this.volume_mul)) / 128); + int divider = this.volume_div; + if (this.volume_div == 3) { + divider = 4; + } + + long l = cast(long) cast(int) this.current_sample.L; + long r = cast(long) cast(int) this.current_sample.R; + + // log_spu("Sample: %x %x", l, r); + + l <<= 4; + r <<= 4; + - sample.L = cast(short) (sample.L * (127 - panning) / 128); - sample.R = cast(short) (sample.R * ( panning) / 128); + l >>= divider; + r >>= divider; + // log_spu("Sample after div: %x %x", l, r); - return sample; + l *= (this.volume_mul == 127) ? 128 : this.volume_mul; + r *= (this.volume_mul == 127) ? 128 : this.volume_mul; + + // log_spu("Sample after mul: %x %x", l, r); + l *= (128 - (this.panning == 127 ? 128 : this.panning)); + r *= ( (this.panning == 127 ? 128 : this.panning)); + + // log_spu("Sample after pan: %x %x", l, r); + + l >>= 10; + r >>= 10; + + // log_spu("Sample after shift: %x %x", l, r); + return ChannelSample(cast(s32) l, cast(s32) r); } void calculate_next_sample(Mem mem) { @@ -144,15 +177,23 @@ final class SPU { break; case Format.PCM8: sample_data = cast(short)(( mem.read_data_byte7(current_address)) << 8); + long index_int_channel_array = &this - &spu.sound_channels[0]; + log_spu("Sample Data: %x %x %x", index_int_channel_array,sample_data, current_address); this.current_address += 1; break; case Format.IMA_ADPCM: + if (this.current_address == this.source_address + this.loopstart * 4 && !this.half_read) { + this.ima_byte_at_pnt = this.ima_byte; + this.ima_index_at_pnt = this.ima_index; + this.ima_pcm16bit_at_pnt = this.ima_pcm16bit; + } + if (this.current_address == this.source_address) { if (shouldLog) { - log_spu("--------------------------------"); - log_spu("Reading IMA Header"); - log_spu("IMA Source Address: %d", this.source_address); - log_spu("--------------------------------"); + // log_spu("--------------------------------"); + // log_spu("Reading IMA Header"); + // log_spu("IMA Source Address: %d", this.source_address); + // log_spu("--------------------------------"); } Word header_data = mem.read_data_word7(current_address); this.ima_pcm16bit = cast(short) header_data[0..15]; @@ -165,8 +206,8 @@ final class SPU { byte data4bit = 0; if (!this.half_read) { if (shouldLog) { - log_spu("IMA Half Read 1"); - log_spu("IMA Current Address: %d", this.current_address); + // log_spu("IMA Half Read 1"); + // log_spu("IMA Current Address: %d", this.current_address); } this.ima_byte = mem.read_data_byte7(current_address); data4bit = this.ima_byte[0..3]; @@ -174,8 +215,8 @@ final class SPU { } else { if (shouldLog) { - log_spu("IMA Half Read 2"); - log_spu("IMA Current Address: %d", this.current_address); + // log_spu("IMA Half Read 2"); + // log_spu("IMA Current Address: %d", this.current_address); } data4bit = this.ima_byte[4..7]; this.half_read = 0; @@ -199,19 +240,31 @@ final class SPU { // PCM8: 4N samples // PCM16: 2N samples // IMA: 8(N-1) samples - if (repeat_mode == RepeatMode.LOOP_INF) { - if (format != Format.IMA_ADPCM && - current_address >= source_address + length * 4) { - this.current_address = this.source_address; - } - else if (format == Format.IMA_ADPCM && - current_address >= source_address + (8*(length - 1))) { - this.current_address = this.source_address + 4; - } + final switch (repeat_mode) { + case RepeatMode.MANUAL: + break; + case RepeatMode.ONESHOT: + if (this.current_address == this.source_address + this.loopstart * 4 + this.length * 4) { + this.enabled = false; + } + break; + case RepeatMode.LOOP_INF: + if (this.current_address >= this.source_address + this.loopstart * 4 + 4 * this.length) { + this.current_address = this.source_address + 4 * this.loopstart; + + if (format == Format.IMA_ADPCM) { + this.ima_byte = this.ima_byte_at_pnt; + this.ima_index = this.ima_index_at_pnt; + this.ima_pcm16bit = this.ima_pcm16bit_at_pnt; + } + } + break; + case RepeatMode.UNKNOWN: + break; } - current_sample = Sample(sample_data, sample_data); + current_sample = ChannelSample(sample_data, sample_data); } short interpret_ima_sample(byte data4bit) { @@ -295,7 +348,7 @@ final class SPU { if (sound_channels[x].enabled) { sound_channels[x].reset(); - // log_spu("Channel Enabled: %x. %s CNT: %08x SAD: %04x TMR: %04x PNT: %04x LEN: %08x", + // // log_spu("Channel Enabled: %x. %s CNT: %08x SAD: %04x TMR: %04x PNT: %04x LEN: %08x", // x, // cast(Format) sound_channels[x].format, // ((cast(int) read_SOUNDxCNT(0, x) << 0) | @@ -379,23 +432,36 @@ final class SPU { } void sample() { - Sample result = Sample(0, 0); - int Lholder = 0; - int Rholder = 0; + s64 mixed_sample_L = 0; + s64 mixed_sample_R = 0; + for (int i = 0; i < 16; i++) { - shouldLog = (i == 4) ? 1 : 0; // TODO: Remove!! - Sample channel_sample = sound_channels[i].get_sample(mem); - Lholder += cast(int) channel_sample.L; - Rholder += cast(int) channel_sample.R; + ChannelSample channel_sample = sound_channels[i].get_sample(mem); + mixed_sample_L += channel_sample.L; + mixed_sample_R += channel_sample.R; } - result.L = cast(short) Lholder; - result.R = cast(short) Rholder; - result.L += sound_bias; - result.R += sound_bias; + // log_spu("Sample after mixing: %x %x", mixed_sample_L, mixed_sample_R); + + mixed_sample_L *= (master_volume == 127) ? 128 : master_volume; + mixed_sample_R *= (master_volume == 127) ? 128 : master_volume; + + // log_spu("Sample after master volume: %x %x", mixed_sample_L, mixed_sample_R); + mixed_sample_L >>= 21; + mixed_sample_R >>= 21; + + // log_spu("Sample after clipping: %x %x", mixed_sample_L, mixed_sample_R); + + mixed_sample_L += sound_bias; + mixed_sample_R += sound_bias; + + // log_spu("Sample after bias: %x %x", mixed_sample_L, mixed_sample_R); - push_sample_callback(result); + // mixed_sample_L = mixed_sample_L.clamp(0, 0x3FF); + // mixed_sample_R = mixed_sample_R.clamp(0, 0x3FF); + // log_spu("Samples: %x %x", mixed_sample_L, mixed_sample_R); + push_sample_callback(Sample(cast(short) mixed_sample_L, cast(short) mixed_sample_R)); scheduler.add_event_relative_to_self(&sample, cycles_per_sample); } diff --git a/source/emu/scheduler.d b/source/emu/scheduler.d index b927f04..1801400 100644 --- a/source/emu/scheduler.d +++ b/source/emu/scheduler.d @@ -42,7 +42,7 @@ final class Scheduler { } private ulong add_event(void delegate() callback, ulong timestamp) { - int insert_at; + int insert_at = 0; for (; insert_at < events_in_queue; insert_at++) { if (timestamp < events[insert_at].timestamp) { diff --git a/source/ui/reng/device.d b/source/ui/reng/device.d index 2d52d62..02c67b4 100644 --- a/source/ui/reng/device.d +++ b/source/ui/reng/device.d @@ -7,6 +7,7 @@ import std.format; import std.string; import ui.device; import ui.reng; +import util.log; class RengMultimediaDevice : MultiMediaDevice { enum SAMPLE_RATE = 48_000; @@ -20,14 +21,16 @@ class RengMultimediaDevice : MultiMediaDevice { DSVideo ds_video; AudioStream stream; - bool fast_foward; + bool fast_forward; string rom_title; int fps; + int screen_scale; this(int screen_scale, bool full_ui) { - Core.target_fps = 999; + Core.target_fps = 60; reng_core = new RengCore(screen_scale, full_ui); + this.screen_scale = screen_scale; InitAudioDevice(); SetAudioStreamBufferSizeDefault(SAMPLES_PER_UPDATE); @@ -90,12 +93,16 @@ class RengMultimediaDevice : MultiMediaDevice { int buffer_cursor = 0; void push_sample(Sample s) { - buffer[buffer_cursor + 0] = s.L; - buffer[buffer_cursor + 1] = s.R; + if (buffer_cursor >= NUM_CHANNELS * SAMPLES_PER_UPDATE * BUFFER_SIZE_MULTIPLIER) return; + + buffer[buffer_cursor + 0] = cast(short) (s.L << 5); + buffer[buffer_cursor + 1] = cast(short) (s.R << 5); buffer_cursor += 2; } void update() { + Core.target_fps = buffer_cursor < NUM_CHANNELS * SAMPLES_PER_UPDATE * (BUFFER_SIZE_MULTIPLIER - 1) ? 999 : 60; + handle_input(); handle_audio(); reng_core.update_pub(); @@ -106,7 +113,8 @@ class RengMultimediaDevice : MultiMediaDevice { } bool should_cycle_nds() { - return buffer_cursor < NUM_CHANNELS * BUFFER_SIZE_MULTIPLIER * SAMPLES_PER_UPDATE - (SAMPLE_RATE / 60) * 2; + return true; + // return buffer_cursor < NUM_CHANNELS * (BUFFER_SIZE_MULTIPLIER - 1) * SAMPLES_PER_UPDATE; } void handle_input() { @@ -117,19 +125,19 @@ class RengMultimediaDevice : MultiMediaDevice { auto mouse_position = Input.mouse_position(); update_touchscreen_position( - clamp(cast(int) mouse_position.x, 0, 256), - clamp(cast(int) mouse_position.y - 192, 0, 192) + clamp(cast(int) mouse_position.x / screen_scale, 0, 256), + clamp(cast(int) mouse_position.y / screen_scale - 192 * screen_scale, 0, 192 * screen_scale) ); static foreach (re_key, gba_key; keys) { update_key(gba_key, Input.is_key_down(re_key)); } - fast_foward = Input.is_key_down(FAST_FOWARD_KEY); + fast_forward = Input.is_key_down(FAST_FOWARD_KEY); } bool should_fast_forward() { - return fast_foward; + return fast_forward; } } @@ -138,8 +146,26 @@ class RengMultimediaDevice : MultiMediaDevice { ds_video.update_title("%s [FPS: %d]".format(rom_title, fps)); } + short[200] sine_buffer; + import std.math; + int sine_cursor = 0; + void sine_wave() { + int period = 100; + for (int i = 0; i < 100; i++) { + sine_buffer[i * 2 + 0] = cast(short) (sin(2 * PI * i / period) * 1000); + sine_buffer[i * 2 + 1] = cast(short) (sin(2 * PI * i / period) * 1000); + } + } + void handle_audio() { if (IsAudioStreamProcessed(stream)) { + // sine_wave(); + // for (int i = 0; i < SAMPLES_PER_UPDATE * NUM_CHANNELS; i++) { + // buffer[i] = sine_buffer[sine_cursor % (100 * NUM_CHANNELS)]; + // sine_cursor++; + // sine_cursor %= 100 * NUM_CHANNELS; + // } + UpdateAudioStream(stream, cast(void*) buffer, SAMPLES_PER_UPDATE); for (int i = 0; i < NUM_CHANNELS * SAMPLES_PER_UPDATE * (BUFFER_SIZE_MULTIPLIER - 1); i++) { @@ -147,9 +173,12 @@ class RengMultimediaDevice : MultiMediaDevice { } buffer_cursor -= NUM_CHANNELS * SAMPLES_PER_UPDATE; - if (buffer_cursor < 0) buffer_cursor = 0; + if (buffer_cursor < 0) { + buffer_cursor = 0; + log_nds("Audio buffer underflowed"); + } - if (fast_foward) buffer_cursor = 0; + if (fast_forward) buffer_cursor = 0; } }