From 1462c330e8ae3da3c8b62cb276661d288ecc7d18 Mon Sep 17 00:00:00 2001 From: tracer-ics2023 Date: Fri, 20 Sep 2024 20:49:42 +0800 Subject: [PATCH] =?UTF-8?q?>=20=20compile=20NEMU=20221220000=20=E5=BC=A0?= =?UTF-8?q?=E4=B8=89=20Linux=20zzy=205.15.146.1-microsoft-standard-WSL2=20?= =?UTF-8?q?#1=20SMP=20Thu=20Jan=2011=2004:09:03=20UTC=202024=20x86=5F64=20?= =?UTF-8?q?x86=5F64=20x86=5F64=20GNU/Linux=20=2020:49:41=20up=203=20days,?= =?UTF-8?q?=2015:55,=20=201=20user,=20=20load=20average:=200.79,=200.71,?= =?UTF-8?q?=200.56?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../am/src/platform/nemu/ioe/audio.c | 26 ++++++- .../am/src/platform/nemu/ioe/gpu.c | 1 + nemu/src/device/audio.c | 71 +++++++++++++++---- nemu/src/device/vga.c | 1 + 4 files changed, 85 insertions(+), 14 deletions(-) diff --git a/abstract-machine/am/src/platform/nemu/ioe/audio.c b/abstract-machine/am/src/platform/nemu/ioe/audio.c index 81839c4..b99f971 100644 --- a/abstract-machine/am/src/platform/nemu/ioe/audio.c +++ b/abstract-machine/am/src/platform/nemu/ioe/audio.c @@ -8,19 +8,41 @@ #define AUDIO_INIT_ADDR (AUDIO_ADDR + 0x10) #define AUDIO_COUNT_ADDR (AUDIO_ADDR + 0x14) +static size_t audio_write = 0; +static size_t audio_sbuf_size; + void __am_audio_init() { } void __am_audio_config(AM_AUDIO_CONFIG_T *cfg) { - cfg->present = false; + cfg->present = true; + cfg->bufsize = inl(AUDIO_SBUF_SIZE_ADDR); + audio_sbuf_size = cfg->bufsize; } void __am_audio_ctrl(AM_AUDIO_CTRL_T *ctrl) { + if (inl(AUDIO_INIT_ADDR) == 1) { + panic("audio initialized"); + } + outl(AUDIO_CHANNELS_ADDR, ctrl->channels); + outl(AUDIO_SAMPLES_ADDR, ctrl->samples); + outl(AUDIO_FREQ_ADDR, ctrl->freq); + outl(AUDIO_INIT_ADDR, 1); } void __am_audio_status(AM_AUDIO_STATUS_T *stat) { - stat->count = 0; + stat->count = inl(AUDIO_COUNT_ADDR); } void __am_audio_play(AM_AUDIO_PLAY_T *ctl) { + for (int i = 0; i < ctl->buf.end - ctl->buf.start; i++) { + if (inl(AUDIO_COUNT_ADDR) == audio_sbuf_size) { + i--; + continue; + } else { + outl(AUDIO_COUNT_ADDR, inl(AUDIO_COUNT_ADDR) + 1); + } + outb(AUDIO_SBUF_ADDR + audio_write, ((uint8_t*)ctl->buf.start)[i]); + audio_write = (audio_write + 1) % audio_sbuf_size; + } } diff --git a/abstract-machine/am/src/platform/nemu/ioe/gpu.c b/abstract-machine/am/src/platform/nemu/ioe/gpu.c index 9701037..7a64389 100644 --- a/abstract-machine/am/src/platform/nemu/ioe/gpu.c +++ b/abstract-machine/am/src/platform/nemu/ioe/gpu.c @@ -38,6 +38,7 @@ void __am_gpu_fbdraw(AM_GPU_FBDRAW_T *ctl) { } } if (ctl->sync) { + while (inl(SYNC_ADDR) != 0) ; outl(SYNC_ADDR, 1); } } diff --git a/nemu/src/device/audio.c b/nemu/src/device/audio.c index cd9fbc5..11fe2c9 100644 --- a/nemu/src/device/audio.c +++ b/nemu/src/device/audio.c @@ -29,27 +29,74 @@ enum { static uint8_t *sbuf = NULL; static uint32_t *audio_base = NULL; +static uint32_t pos_read = 0; -// static void init_sdl_audio() { -// SDL_AudioSpec s = {}; -// s.format = AUDIO_S16SYS; // 假设系统中音频数据的格式总是使用16位有符号数来表示 -// s.userdata = NULL; // 不使用 +#define MIN(a, b) ((a) < (b) ? (a) : (b)) -// SDL_InitSubSystem(SDL_INIT_AUDIO); -// SDL_OpenAudio(&s, NULL); -// SDL_PauseAudio(0); -// } +static void audio_callback(void *userdata, uint8_t *stream, int len) { + uint32_t count = audio_base[reg_count]; + uint32_t read_cnt = MIN(count, len); + uint32_t to_end_cnt = audio_base[reg_sbuf_size] - pos_read; + int32_t out_bound_cnt = read_cnt - to_end_cnt; + if (out_bound_cnt > 0) { + SDL_memcpy(stream, sbuf + pos_read, to_end_cnt); + SDL_memcpy(stream + to_end_cnt, sbuf, out_bound_cnt); + } else { + SDL_memcpy(stream, sbuf + pos_read, read_cnt); + } + pos_read += read_cnt; + pos_read %= audio_base[reg_sbuf_size]; + if (len > read_cnt) SDL_memset(stream + read_cnt, 0, len - read_cnt); + audio_base[reg_count] -= read_cnt; +} + +static inline void init_audio_dev() { + SDL_AudioSpec s = {}; + s.format = AUDIO_S16SYS; // 假设系统中音频数据的格式总是使用16位有符号数来表示 + s.userdata = NULL; // 不使用 + s.freq = audio_base[reg_freq]; + s.channels = audio_base[reg_channels]; + s.samples = audio_base[reg_samples]; + s.callback = audio_callback; + + assert(SDL_InitSubSystem(SDL_INIT_AUDIO) == 0); + assert(SDL_OpenAudio(&s, NULL) == 0); + SDL_PauseAudio(0); +} static void audio_io_handler(uint32_t offset, int len, bool is_write) { - + assert(offset % 4 == 0); + int idx = offset / 4; + switch (idx) { + case reg_freq: + case reg_channels: + case reg_samples: + break; + case reg_sbuf_size: + assert(is_write == false); + break; + case reg_init: + if (is_write && audio_base[reg_init] != 0) { + init_audio_dev(); + } + break; + case reg_count: + // TODO: must be add a lock here + break; + default: + assert(0); + } } void init_audio() { - audio_base = (uint32_t *)new_space(24); + uint32_t space_size = sizeof(uint32_t) * nr_reg; + audio_base = (uint32_t *)new_space(space_size); + audio_base[reg_sbuf_size] = CONFIG_SB_SIZE; + audio_base[reg_init] = 0; #ifdef CONFIG_HAS_PORT_IO - add_pio_map ("audio", CONFIG_AUDIO_CTL_PORT, audio_base, 24, audio_io_handler); + add_pio_map ("audio", CONFIG_AUDIO_CTL_PORT, audio_base, space_size, audio_io_handler); #else - add_mmio_map("audio", CONFIG_AUDIO_CTL_MMIO, audio_base, 24, audio_io_handler); + add_mmio_map("audio", CONFIG_AUDIO_CTL_MMIO, audio_base, space_size, audio_io_handler); #endif sbuf = (uint8_t *)new_space(CONFIG_SB_SIZE); diff --git a/nemu/src/device/vga.c b/nemu/src/device/vga.c index 44313aa..38bf089 100644 --- a/nemu/src/device/vga.c +++ b/nemu/src/device/vga.c @@ -84,6 +84,7 @@ void vga_update_screen() { void init_vga() { vgactl_port_base = (uint32_t *)new_space(8); vgactl_port_base[0] = (screen_width() << 16) | screen_height(); + vgactl_port_base[1] = 0; #ifdef CONFIG_HAS_PORT_IO add_pio_map ("vgactl", CONFIG_VGA_CTL_PORT, vgactl_port_base, 8, NULL); #else