> compile NEMU
221220000 张三 Linux zzy 5.15.146.1-microsoft-standard-WSL2 #1 SMP Thu Jan 11 04:09:03 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux 20:49:41 up 3 days, 15:55, 1 user, load average: 0.79, 0.71, 0.56
This commit is contained in:
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user