Added x86 asm and C wav writer and player examples.

Specifically:
* Added win32, elf32 and elf64 asm player and wav writers using winmm.
* Added dsound player in C.
* Separated the ALL target and the examples; introduced a new examples target.
This commit is contained in:
Alexander Kraus
2023-08-28 23:54:04 +02:00
committed by Veikko Sariola
parent a439a4fa48
commit 607e5b5da0
17 changed files with 886 additions and 34 deletions

View File

@ -0,0 +1,12 @@
if(WIN32)
set(CMAKE_ASM_NASM_OBJECT_FORMAT win64)
elseif(UNIX)
set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64)
endif()
set(CMAKE_ASM_NASM_COMPILE_OBJECT "<CMAKE_ASM_NASM_COMPILER> <INCLUDES> <DEFINES> <FLAGS> -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o <OBJECT> <SOURCE>")
if(UNIX)
add_asm_example(asmplay "${PROJECT_SOURCE_DIR}/examples/patches/physics_girl_st.yml" amd64 64 "winmm" "asound;pthread")
add_asm_example(asmwav "${PROJECT_SOURCE_DIR}/examples/patches/physics_girl_st.yml" amd64 64 "" "")
target_compile_definitions(asmwav-amd64 PRIVATE FILENAME="physics_girl_st.wav")
endif()

View File

@ -0,0 +1,81 @@
%include TRACK_INCLUDE
%define SND_PCM_FORMAT_S16_LE 0x2
%define SND_PCM_FORMAT_FLOAT 0xE
%define SND_PCM_ACCESS_RW_INTERLEAVED 0x3
%define SND_PCM_STREAM_PLAYBACK 0x0
section .bss
sound_buffer:
resb SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT
render_thread:
resq 1
pcm_handle:
resq 1
section .data
default_device:
db "default", 0
section .text
symbols:
extern pthread_create
extern sleep
extern snd_pcm_open
extern snd_pcm_set_params
extern snd_pcm_writei
global main
main:
; Prologue
push rbp
mov rbp, rsp
sub rsp, 0x10
; Unix does not have gm.dls, no need to ifdef and setup here.
; We render in the background while playing already.
mov rcx, sound_buffer
lea rdx, su_render_song
mov rsi, 0x0
mov rdi, render_thread
call pthread_create
; We can't start playing too early or the missing samples will be audible.
mov edi, 0x2
call sleep
; Play the track.
mov rdi, pcm_handle
mov rsi, default_device
mov rdx, SND_PCM_STREAM_PLAYBACK
mov rcx, 0x0
call snd_pcm_open
; This is unfortunate. amd64 ABI calling convention kicks in.
; now we have to maintain the stack pointer :/
mov rdi, qword [pcm_handle]
sub rsp, 0x8
push SU_LENGTH_IN_SAMPLES
%ifdef SU_SAMPLE_FLOAT
mov rsi, SND_PCM_FORMAT_FLOAT
%else ; SU_SAMPLE_FLOAT
mov rsi, SND_PCM_FORMAT_S16_LE
%endif ; SU_SAMPLE_FLOAT
mov rdx, SND_PCM_ACCESS_RW_INTERLEAVED
mov rcx, SU_CHANNEL_COUNT
mov r8d, SU_SAMPLE_RATE
mov r9d, 0x0
call snd_pcm_set_params
mov rdi, qword [pcm_handle]
mov rsi, sound_buffer
mov rdx, SU_LENGTH_IN_SAMPLES
call snd_pcm_writei
exit:
; At least we can skip the epilogue :)
leave
ret

View File

@ -0,0 +1,91 @@
%include TRACK_INCLUDE
%define WAVE_FORMAT_PCM 0x1
%define WAVE_FORMAT_IEEE_FLOAT 0x3
section .bss
sound_buffer:
resb SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT
file:
resq 1
section .data
; Change the filename over -DFILENAME="yourfilename.wav"
filename:
db FILENAME, 0
format:
db "wb", 0
; This is the wave file header.
wave_file:
db "RIFF"
dd wave_file_end + SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT - wave_file
db "WAVE"
db "fmt "
wave_format_end:
dd wave_format_end - wave_file
%ifdef SU_SAMPLE_FLOAT
dw WAVE_FORMAT_IEEE_FLOAT
%else ; SU_SAMPLE_FLOAT
dw WAVE_FORMAT_PCM
%endif ; SU_SAMPLE_FLOAT
dw SU_CHANNEL_COUNT
dd SU_SAMPLE_RATE
dd SU_SAMPLE_SIZE * SU_SAMPLE_RATE * SU_CHANNEL_COUNT
dw SU_SAMPLE_SIZE * SU_CHANNEL_COUNT
dw SU_SAMPLE_SIZE * 8
wave_header_end:
db "data"
dd wave_file_end + SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT - wave_header_end
wave_file_end:
section .text
symbols:
extern fopen
extern fwrite
extern fclose
global main
main:
; elf32 uses the cdecl calling convention. This is more readable imo ;)
; Prologue
push rbp
mov rbp, rsp
sub rsp, 0x10
; Unix does not have gm.dls, no need to ifdef and setup here.
; We render the complete track here.
mov rdi, sound_buffer
call su_render_song
; Now we open the file and save the track.
mov rsi, format
mov rdi, filename
call fopen
mov qword [file], rax
; Write header
mov rcx, qword [file]
mov rdx, 0x1
mov rsi, wave_file_end - wave_file
mov rdi, wave_file
call fwrite
; write data
mov rcx, qword [file]
mov rdx, 0x1
mov rsi, SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT
mov rdi, sound_buffer
call fwrite
mov rdi, qword [file]
call fclose
exit:
; At least we can skip the epilogue :)
leave
ret