Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cdrom code #32

Closed
sezero opened this issue Mar 2, 2021 · 31 comments
Closed

cdrom code #32

sezero opened this issue Mar 2, 2021 · 31 comments
Assignees
Milestone

Comments

@sezero
Copy link
Contributor

sezero commented Mar 2, 2021

We have stubs for cdrom code in sdl12-compat.

Should we import the code from SDL-1.2? If we ever do that,
would there be licence issues (can any of the authors still be
reached, etc)?

If we'll keep the stubs, close this.

@icculus
Copy link
Collaborator

icculus commented Mar 2, 2021

I was looking at this last night, because at some point the ScummVM team told me not having CD support was a deal breaker, but we can't just paste that code in, and in some cases, it wouldn't be helpful (for example, Apple doesn't sell Macs with CD-ROM drives anymore, and for years before, the audio cable wasn't hooked up, so you couldn't just tell an audio CD to play in one...iTunes would play CDs by reading the raw data from the disc and playing it through CoreAudio, instead of just sending a command to the drive like these SDL APIs expect).

Also it feels weird to think that implementing this properly means that half of sdl12-compat would be CD-ROM code for various platforms. :)

Let's leave this open for now, but my suspicion is that modern hardware and a lack of readily-available discs is going to be the real problem in the future.

Part of me thinks it could be cool if we could configure sdl12-compat to pretend a directory full of MP3s is an audio CD, though.

@sezero
Copy link
Contributor Author

sezero commented Mar 2, 2021

Side note: libcdio could be used for cd-play, but it's GPLv3, not LGPL:
https://www.gnu.org/software/libcdio/

@icculus
Copy link
Collaborator

icculus commented Mar 8, 2021

Part of me thinks it could be cool if we could configure sdl12-compat to pretend a directory full of MP3s is an audio CD, though.

I did it. :) It's WIP, but almost done.

@icculus icculus self-assigned this Mar 8, 2021
@icculus icculus closed this as completed in e5a32aa Jun 7, 2021
@icculus
Copy link
Collaborator

icculus commented Jun 7, 2021

okay, I finished this work over the weekend.

Tested with quakespasm and the original Quake 1 soundtrack ripped to mp3, and it seems to work pretty well.

The only issue I see at the moment is that it doesn't have a way to specify data tracks, so for Quake to get the right music (which starts on track 2, past the game data at track 1), you have to copy a valid mp3 file to 0.mp3 to make sdl12-compat report tracks at the right place. This obviously should be fixed still, so I'm reopening this bug for now.

@icculus icculus reopened this Jun 7, 2021
@icculus
Copy link
Collaborator

icculus commented Jun 7, 2021

Also we should probably start with 1.mp3 instead of 0.mp3 so it matches the track number, and maybe call these things "track1.mp3" instead.

@sezero
Copy link
Contributor Author

sezero commented Jun 7, 2021

Are the static linkage issues fixed? (Haven't tested yet.)

Also we should probably start with 1.mp3 instead of 0.mp3 so it matches the track number, and maybe call these things "track1.mp3" instead.

I'd suggest using two-digits, like trackXX.mp3, starting with 01.

@sezero
Copy link
Contributor Author

sezero commented Jun 7, 2021

Are the static linkage issues fixed? (Haven't tested yet.)

Wrong choice of words - I meant windows linkage with -nostdlib

@sezero
Copy link
Contributor Author

sezero commented Jun 7, 2021

Mingw builds using Makefile.mingw:

Targeting i686:

i686-w64-mingw32-gcc -o SDL.dll -nostdlib -shared -Wl,--no-undefined -Wl,--enable-auto-image-base -Wl,--out-implib,libSDL.dll.a SDL12_compat.o version.o -lkernel32 -luser32
Creating library file: libSDL.dll.a
SDL12_compat.o:SDL12_compat.c:(.text+0x1775d): undefined reference to `___chkstk'
SDL12_compat.o:SDL12_compat.c:(.text+0x1896c): undefined reference to `___chkstk'
SDL12_compat.o:SDL12_compat.c:(.text+0x194ad): undefined reference to `___chkstk'
SDL12_compat.o:SDL12_compat.c:(.text+0x19ad8): undefined reference to `___udivdi3'
SDL12_compat.o:SDL12_compat.c:(.text+0x1a35a): undefined reference to `___chkstk'
SDL12_compat.o:SDL12_compat.c:(.text+0x1a3ba): undefined reference to `___chkstk'
SDL12_compat.o:SDL12_compat.c:(.text+0x1a56c): undefined reference to `___chkstk'
collect2: ld returned 1 exit status

Targeting x86_64:

x86_64-w64-mingw32-gcc -o SDL.dll -nostdlib -shared -Wl,--no-undefined -Wl,--enable-auto-image-base -Wl,--out-implib,libSDL.dll.a SDL12_compat.o version.o -lkernel32 -luser32
Creating library file: libSDL.dll.a
SDL12_compat.o:SDL12_compat.c:(.text+0x19c12): undefined reference to `___chkstk'
SDL12_compat.o:SDL12_compat.c:(.text+0x1a8d2): undefined reference to `___chkstk'
SDL12_compat.o:SDL12_compat.c:(.text+0x1afc6): undefined reference to `___chkstk'
SDL12_compat.o:SDL12_compat.c:(.text+0x1bac6): undefined reference to `___chkstk'
SDL12_compat.o:SDL12_compat.c:(.text+0x1bb46): undefined reference to `___chkstk'
SDL12_compat.o:SDL12_compat.c:(.text+0x1bd72): more undefined references to `___chkstk' follow
collect2: ld returned 1 exit status

Targeting i686 using really old mingw.org toolchain:

i686-pc-mingw32-gcc -o SDL.dll -nostdlib -shared -Wl,--no-undefined -Wl,--enable-auto-image-base -Wl,--out-implib,libSDL.dll.a SDL12_compat.o version.o -lkernel32 -luser32
SDL12_compat.o:SDL12_compat.c:(.text+0x1272c): undefined reference to `__alloca'
SDL12_compat.o:SDL12_compat.c:(.text+0x138e8): undefined reference to `___udivdi3'
SDL12_compat.o:SDL12_compat.c:(.text+0x13e5d): undefined reference to `__alloca'
SDL12_compat.o:SDL12_compat.c:(.text+0x14569): undefined reference to `__alloca'
SDL12_compat.o:SDL12_compat.c:(.text+0x147ac): undefined reference to `__alloca'
SDL12_compat.o:SDL12_compat.c:(.text+0x1509d): undefined reference to `__alloca'
SDL12_compat.o:SDL12_compat.c:(.text+0x1510b): undefined reference to `___fixunsdfdi'
SDL12_compat.o:SDL12_compat.c:(.text+0x165ac): undefined reference to `__alloca'
Creating library file: libSDL.dll.a
collect2: ld returned 1 exit status

Linkage succeeds for all three cases if I link to libgcc like:

diff --git a/src/Makefile.mingw b/src/Makefile.mingw
index 085ffcb..b509c69 100644
--- a/src/Makefile.mingw
+++ b/src/Makefile.mingw
@@ -17,7 +17,7 @@ CPPFLAGS = -DDLL_EXPORT -DNDEBUG
 
 CFLAGS  = -O3 -Wall
 LDFLAGS = -nostdlib -shared -Wl,--no-undefined -Wl,--enable-auto-image-base -Wl,--out-implib,$(LIB)
-LDLIBS  = -lkernel32 -luser32
+LDLIBS  = -lkernel32 -luser32 -static-libgcc -lgcc
 
 LIB = libSDL.dll.a
 DLL = SDL.dll

@sezero
Copy link
Contributor Author

sezero commented Jun 7, 2021

If I use a gcc-7.5 / mingw-w64-v5.0.4 based toolchain, the missing symbol
is __chkstk_ms instead of __chkstk. Solution is the same, i.e. linking to
libgcc.

sezero referenced this issue Jun 7, 2021
This is only safe because we only decode one mp3 at a time, but cleaning this
up more properly would be good.

Should prevent MSVC from inserting a call to _chkstk here.
@icculus
Copy link
Collaborator

icculus commented Jun 7, 2021

Are the static linkage issues fixed?

Not yet. The chkstk thing happens if you have more than 4 kilobytes of local variables, so I’m cleaning out some big scratch arrays still.

I'd suggest using two-digits, like trackXX.mp3, starting with 01.

Okay, we can do that.

@sezero
Copy link
Contributor Author

sezero commented Jun 7, 2021

Using Makefile.vc, with VS2017-v15.9.36,

Targeting i686:

	link /OUT:SDL.dll /nologo /DLL /NODEFAULTLIB /RELEASE SDL12_compat.obj version.res kernel32.lib user32.lib
   Creating library SDL.lib and object SDL.exp
SDL12_compat.obj : error LNK2019: unresolved external symbol __allmul referenced in function _drmp3__full_read_and_close_f32
SDL12_compat.obj : error LNK2019: unresolved external symbol __aulldiv referenced in function _drmp3_calculate_seek_points
SDL12_compat.obj : error LNK2019: unresolved external symbol __chkstk referenced in function _SDL_CDOpen
SDL12_compat.obj : error LNK2019: unresolved external symbol __dtoui3 referenced in function _SDL_CDOpen
SDL12_compat.obj : error LNK2019: unresolved external symbol __dtoul3 referenced in function _StartCDAudioPlaying
SDL12_compat.obj : error LNK2019: unresolved external symbol __ftol2_sse referenced in function _GetOpenGLLogicalScalingViewport
SDL12_compat.obj : error LNK2019: unresolved external symbol __ftoui3 referenced in function _drmp3__accumulate_running_pcm_frame_count
SDL12_compat.obj : error LNK2019: unresolved external symbol __ultod3 referenced in function _SDL_CDOpen
SDL.dll : fatal error LNK1120: 8 unresolved externals

Targeting x86_64:

	link /OUT:SDL.dll /nologo /DLL /NODEFAULTLIB /RELEASE SDL12_compat.obj version.res kernel32.lib user32.lib
   Creating library SDL.lib and object SDL.exp
SDL12_compat.obj : error LNK2019: unresolved external symbol __chkstk referenced in function SDL_CDOpen
SDL.dll : fatal error LNK1120: 1 unresolved externals

Using Makefile.vc, with VS2005-sp1,

Targeting i686:

	link /OUT:SDL.dll /nologo /DLL /NODEFAULTLIB /RELEASE SDL12_compat.obj version.res kernel32.lib user32.lib
   Creating library SDL.lib and object SDL.exp
SDL12_compat.obj : error LNK2019: unresolved external symbol __ftol2_sse referenced in function _GetOpenGLLogicalScalingViewport
SDL12_compat.obj : error LNK2019: unresolved external symbol __chkstk referenced in function _drmp3_read_pcm_frames_s16
SDL12_compat.obj : error LNK2019: unresolved external symbol __allmul referenced in function _drmp3_read_pcm_frames_s16
SDL12_compat.obj : error LNK2019: unresolved external symbol __aulldiv referenced in function _drmp3_calculate_seek_points
SDL12_compat.obj : error LNK2019: unresolved external symbol __ftol2 referenced in function _StartCDAudioPlaying
SDL.dll : fatal error LNK1120: 5 unresolved externals

Targeting x86_64:

	link /OUT:SDL.dll /nologo /DLL /NODEFAULTLIB /RELEASE SDL12_compat.obj version.res kernel32.lib user32.lib
   Creating library SDL.lib and object SDL.exp
SDL12_compat.obj : error LNK2019: unresolved external symbol __chkstk referenced in function drmp3_read_pcm_frames_s16
SDL.dll : fatal error LNK1120: 1 unresolved externals

Linking to chkstk.o should satisfy __chkstk and x64 builds would link.
Don't know how to satisfy 64bit math symbols for 32 bit (x86) builds.

@sezero
Copy link
Contributor Author

sezero commented Jun 8, 2021

As of commit bbebe7c, MinGW x64 builds seems to link. 32 bits (x86) is still trouble:

Using a mingw-w64 toolchain:

$ PATH=/opt/cross_win32/bin:$PATH make -f Makefile.mingw CROSS=i686-w64-mingw32
i686-w64-mingw32-gcc -O3 -Wall -DDLL_EXPORT -DNDEBUG -Iinclude -o SDL12_compat.o -c SDL12_compat.c
i686-w64-mingw32-windres -o version.o version.rc
i686-w64-mingw32-gcc -o SDL.dll -nostdlib -shared -Wl,--no-undefined -Wl,--enable-auto-image-base -Wl,--out-implib,libSDL.dll.a SDL12_compat.o version.o -lkernel32 -luser32
Creating library file: libSDL.dll.a
SDL12_compat.o:SDL12_compat.c:(.text+0x18d58): undefined reference to `___udivdi3'
collect2: ld returned 1 exit status
make: *** [SDL.dll] Error 1

Using a really old mingw.org-based toolchain:

$ PATH=/usr/local/cross-win32/bin:$PATH make -f Makefile.mingw CROSS=i686-pc-mingw32
i686-pc-mingw32-gcc -O3 -Wall -DDLL_EXPORT -DNDEBUG -Iinclude -o SDL12_compat.o -c SDL12_compat.c
i686-pc-mingw32-windres -o version.o version.rc
i686-pc-mingw32-gcc -o SDL.dll -nostdlib -shared -Wl,--no-undefined -Wl,--enable-auto-image-base -Wl,--out-implib,libSDL.dll.a SDL12_compat.o version.o -lkernel32 -luser32
SDL12_compat.o:SDL12_compat.c:(.text+0x13258): undefined reference to `___udivdi3'
SDL12_compat.o:SDL12_compat.c:(.text+0x13ed3): undefined reference to `___fixunsdfdi'
Creating library file: libSDL.dll.a
collect2: ld returned 1 exit status
make: *** [SDL.dll] Error 1

@sezero
Copy link
Contributor Author

sezero commented Jun 8, 2021

Same with VS2017 x86 builds:

	link /OUT:SDL.dll /nologo /DLL /NODEFAULTLIB /RELEASE SDL12_compat.obj version.res kernel32.lib user32.lib
   Creating library SDL.lib and object SDL.exp
SDL12_compat.obj : error LNK2019: unresolved external symbol __aulldiv referenced in function _drmp3_calculate_seek_points
SDL12_compat.obj : error LNK2019: unresolved external symbol __dtoui3 referenced in function _SDL_CDOpen
SDL12_compat.obj : error LNK2019: unresolved external symbol __dtoul3 referenced in function _StartCDAudioPlaying
SDL12_compat.obj : error LNK2019: unresolved external symbol __ftol2_sse referenced in function _GetOpenGLLogicalScalingViewport
SDL12_compat.obj : error LNK2019: unresolved external symbol __ftoui3 referenced in function _drmp3__accumulate_running_pcm_frame_count
SDL12_compat.obj : error LNK2019: unresolved external symbol __ultod3 referenced in function _SDL_CDOpen
SDL.dll : fatal error LNK1120: 6 unresolved externals

@icculus
Copy link
Collaborator

icculus commented Jun 8, 2021

So most (or all) of these are for SSE implementations of various math and casting operations, inserted by MSVC with the assumption that you're linking against their C runtime anyhow.

Since we've seen that SDL 1.2 linked against the C runtime on Windows by default, we should probably just not link with /NODEFAULTLIB which I think will solve this.

(But I am almost entirely ignorant of the politics of Windows C runtime compatibility, except that sometimes it's pretty complicated...but using whatever SDL 1.2 used here should be safe, right?)

@sezero
Copy link
Contributor Author

sezero commented Jun 8, 2021

So most (or all) of these are for SSE implementations of various math and casting operations, inserted by MSVC with the assumption that you're linking against their C runtime anyhow.

Since we've seen that SDL 1.2 linked against the C runtime on Windows by default, we should probably just not link with /NODEFAULTLIB which I think will solve this.

Doing that might allow linkage, yes. But, how does SDL2 x86 builds handle
those? We can borrow a few thing from there?

As for mingw, linking with libgcc fixes linkage (as I noted at #32 (comment))

(But I am almost entirely ignorant of the politics of Windows C runtime compatibility, except that sometimes it's pretty complicated...but using whatever SDL 1.2 used here should be safe, right?)

A new msvcrXX.dll for every new iteration of MSVC since version 2003.
That would be a mess. However, if libsdl.org will make official builds and do
so using mingw, there wouldn't be any crt issues.

sezero added a commit that referenced this issue Jun 8, 2021
@sezero
Copy link
Contributor Author

sezero commented Jun 8, 2021

Pushed fd56c5b to standalone Makefile.mingw: x86 builds link now.

Someone else should handle cmake side (can't use it - see bug 85)
Applied commit bc754b6 to cmake side for this (still can't use cmake
with mingw, though - see bug #85)

@sezero
Copy link
Contributor Author

sezero commented Jun 8, 2021

FWIW, I tried linking with libcmt.lib with MSVC 2017 to satisfy missing
syms, it resulted in a new missing sym (__except or something like it)
required by its ftol implementation. Whole situation is an eww. I guess
we should add our own versions of those syms like SDL2 does. (2 or 3 of
them are already in SDL_stdlib.c, 3 or more of them are not.)

@icculus
Copy link
Collaborator

icculus commented Jun 14, 2021

Whole situation is an eww.

Windows development in a nutshell. :)

I'll fight with this more soon.

@sezero
Copy link
Contributor Author

sezero commented Jun 15, 2021

My solution to msvc/x86 builds is making it not emit sse2 instructions,
and also provide _ftol, _aulldiv & co from SDL_stdlib.c of SDL2.

See the following patch:

diff --git a/src/Makefile.vc b/src/Makefile.vc
index bdfe142..8a2cd8e 100644
--- a/src/Makefile.vc
+++ b/src/Makefile.vc
@@ -1,5 +1,8 @@
 # Makefile for Win32 using MSVC:
 #	nmake /f Makefile.vc
+#
+# If you specifically want to build for x86:
+#	nmake /f Makefile.vc CPU=x86
 
 # change INCLUDES so it points to SDL2 headers directory:
 INCLUDES = -Iinclude
@@ -14,6 +17,10 @@ CFLAGS = /nologo /O2 /MD /W3 /GS-
 LDFLAGS = /nologo /DLL /NODEFAULTLIB /RELEASE
 LDLIBS = kernel32.lib user32.lib
 
+!if "$(CPU)" == "x86"
+CFLAGS = $(CFLAGS) /arch:SSE
+!endif
+
 DLLNAME = SDL.dll
 IMPNAME = SDL.lib
 
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ea181a9..874f89f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -38,6 +38,8 @@ set(SDL12COMPAT_SRCS
 )
 add_library(SDL SHARED ${SDL12COMPAT_SRCS})
 
+include(CheckCSourceCompiles)
+
 include(GNUInstallDirs)
 include("cmake/modules/FindSDL2.cmake")
 target_include_directories(SDL PRIVATE ${SDL2_INCLUDE_DIRS})
@@ -83,7 +85,16 @@ if(MINGW)
 endif()
 if(MSVC)
     # Don't try to link with the default set of libraries.
-    set_target_properties(SDL PROPERTIES COMPILE_FLAGS "/GS-")
+    set(MSVC_FLAGS "/GS-")
+    check_c_source_compiles("int main(void) {
+#ifndef _M_IX86
+#error not x86
+#endif
+return 0; }" IS_X86)
+    if(IS_X86)  # don't emit SSE2 in x86 builds
+      set(MSVC_FLAGS "${MSVC_FLAGS} /arch:SSE")
+    endif()
+    set_target_properties(SDL PROPERTIES COMPILE_FLAGS ${MSVC_FLAGS})
     set_target_properties(SDL PROPERTIES LINK_FLAGS "/NODEFAULTLIB")
     # Make sure /RTC1 is disabled: (from SDL2 CMake)
     foreach(flag_var
diff --git a/src/SDL12_compat.c b/src/SDL12_compat.c
index a3c3d3a..e17c1b5 100644
--- a/src/SDL12_compat.c
+++ b/src/SDL12_compat.c
@@ -5940,6 +5940,10 @@ SDL_LoadWAV_RW(SDL12_RWops *rwops12, int freerwops12,
    an audio CD-ROM, and will decode these files and mix them into an audio
    stream as if they were playing from a disc. */
 
+#if defined(_MSC_VER) && defined(_M_IX86)
+#include "x86_msvc.h"
+#endif
+
 #define CDAUDIO_FPS 75  /* CD audio frames per second. */
 
 /* public domain, single-header MP3 decoder for fake CD-ROM audio support! */

And here is the x86_msvc.h: x86_msvc.h.txt (Lose the .txt extension)
It is copied over from SDL2, with _ftol2 added as a redirection to _ftol.

Tested build using both Makefile.vc and cmake, using VS2005 and VS2017.
OK?

@icculus
Copy link
Collaborator

icculus commented Jun 15, 2021

Looks fine to me, commit it, please.

@sezero
Copy link
Contributor Author

sezero commented Jun 15, 2021

Pushed as d1f3c6e

@icculus
Copy link
Collaborator

icculus commented Jun 15, 2021

So the only thing still pending on this is to let people specify fake data tracks (quake 1 had the audio start at track 2 for example), I think.

@sezero
Copy link
Contributor Author

sezero commented Jun 15, 2021

So the only thing still pending on this is to let people specify fake data tracks (quake 1 had the audio start at track 2 for example), I think.

IMO, we shouldn't concern ourselves with at which track the cdaudio
starts: we should just support trackXX.mp3, with XX in the range of
01-99 as usual. The rest should be client program's responsibility.

As for what's left to do: I even had thought about modifying drmp3
to remove 64 bit offsets and sizes support - after all, we're only
concerned with cdaudio-rips - that would have reduced the number of
hoops to jump through in x86 builds, but that would be a serious &&
error-prone undertaking.

@sezero
Copy link
Contributor Author

sezero commented Jun 15, 2021

One thing to make sure is 'close'ing audio does close cdrom properly, and
a possible re-init of audio does reinit cdrom, etc... (I haven't actually
checked the code.)

Also, does it work if SDL_INIT_CDROM is specified and SDL_INIT_AUDIO
is not?

@sezero
Copy link
Contributor Author

sezero commented Jun 22, 2021

I'd suggest using two-digits, like trackXX.mp3, starting with 01.

Okay, we can do that.

Is the following OK to apply?
It still starts at 00, not 01: is that OK too, or should we start from 01?
(I do think that we should start from 01.)

diff --git a/src/SDL12_compat.c b/src/SDL12_compat.c
index ee352a3..ee21404 100644
--- a/src/SDL12_compat.c
+++ b/src/SDL12_compat.c
@@ -6169,7 +6169,8 @@ SDL_CDNumDrives(void)
             warned_once = SDL_TRUE;
             SDL20_Log("This app is looking for CD-ROM drives, but no path was specified");
             SDL20_Log("Set the SDL12COMPAT_FAKE_CDROM_PATH environment variable to a directory");
-            SDL20_Log("of MP3 files named NUM.mp3, where NUM is a track number from 0 to 99");
+            SDL20_Log("of MP3 files named trackXX.mp3 where XX is a track number in two digits");
+            SDL20_Log("from 00 to 99");
         }
     }
 
@@ -6243,10 +6244,13 @@ SDL_CDOpen(int drive)
         drmp3_uint64 pcmframes;
         drmp3_uint32 samplerate;
         SDL12_CDtrack *track;
+        char c0, c1;
 
         /* we only report audio tracks, starting at 0... */
         FIXME("Let there be fake data tracks (quake1's audio starts at track 2, etc).");
-        SDL20_snprintf(fullpath, alloclen, "%s%s%d.mp3", CDRomPath, DIRSEP, retval->numtracks);
+        c0 = retval->numtracks / 10 + '0';
+        c1 = retval->numtracks % 10 + '0';
+        SDL20_snprintf(fullpath, alloclen, "%s%strack%c%c.mp3", CDRomPath, DIRSEP, c0, c1);
         rw = SDL20_RWFromFile(fullpath, "rb");
         if (!rw) {
             break;  /* ok, we're done looking for more. */

@icculus
Copy link
Collaborator

icculus commented Jun 22, 2021

Let's start from 1 instead of zero, but yeah, apply this.

@sezero
Copy link
Contributor Author

sezero commented Jun 22, 2021

Let's start from 1 instead of zero, but yeah, apply this.

Applied as ffc3d79

@sezero
Copy link
Contributor Author

sezero commented Jun 22, 2021

I seem to have screwed up with numtracks value. Will push a fix shortly.

@sezero
Copy link
Contributor Author

sezero commented Jun 22, 2021

Pushed 67b5a5b to fix things.

@icculus
Copy link
Collaborator

icculus commented Jun 22, 2021

One thing to make sure is 'close'ing audio does close cdrom properly, and
a possible re-init of audio does reinit cdrom, etc... (I haven't actually
checked the code.)

Also, does it work if SDL_INIT_CDROM is specified and SDL_INIT_AUDIO
is not?

I think verifying this is the only pending item at this point. (I wouldn't risk removing 64-bit stuff from dr_mp3, as it's going to cause problems if we ever update that code. I need to send them patches for the changes I already made, in hopes of avoiding that problem.)

@icculus
Copy link
Collaborator

icculus commented Jan 24, 2022

This is the code I used to test the CD and OpenAudio stuff (and it did, in fact, reveal a bug)...it's basically loopwave.c with some changes.

This is not super-robust, but basically make sure you have SDL12COMPAT_FAKE_CDROM_PATH set up, run this with sample.wav available to it, and press 'a' to open the audio device, 's' to close it, 'c' to open the cd for playing, and 'v' to close it. Do it in various orders to see if it works (which it does, as of 719c652).

#include "SDL_config.h"

#include <stdio.h>
#include <stdlib.h>
#include "SDL.h"
#include "SDL_audio.h"

struct {
	SDL_AudioSpec spec;
	Uint8   *sound;			/* Pointer to wave data */
	Uint32   soundlen;		/* Length of wave data */
	int      soundpos;		/* Current play position */
} wave;


/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
static void quit(int rc)
{
	SDL_Quit();
	exit(rc);
}


void SDLCALL fillerup(void *unused, Uint8 *stream, int len)
{
	Uint8 *waveptr;
	int    waveleft;

	/* Set up the pointers */
	waveptr = wave.sound + wave.soundpos;
	waveleft = wave.soundlen - wave.soundpos;

	/* Go! */
	while ( waveleft <= len ) {
		SDL_memcpy(stream, waveptr, waveleft);
		stream += waveleft;
		len -= waveleft;
		waveptr = wave.sound;
		waveleft = wave.soundlen;
		wave.soundpos = 0;
	}
	SDL_memcpy(stream, waveptr, len);
	wave.soundpos += len;
}

static int done = 0;
void poked(int sig)
{
	done = 1;
}

int main(int argc, char *argv[])
{
	char name[32];
	const char *file;
    int done = 0;
    SDL_CD *cdrom = NULL;

	/* Load the SDL library */
	if ( SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_CDROM) < 0 ) {
		fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
		return(1);
	}

	printf("Using audio driver: %s\n", SDL_AudioDriverName(name, 32));

	file = (argc < 2) ? "sample.wav" : argv[1];
	/* Load the wave file into memory */
	if ( SDL_LoadWAV(file, &wave.spec, &wave.sound, &wave.soundlen) == NULL ) {
		fprintf(stderr, "Couldn't load %s: %s\n", file, SDL_GetError());
		quit(1);
	}

	wave.spec.callback = fillerup;

    if (!SDL_SetVideoMode(640, 480, 0, 0)) {
		fprintf(stderr, "Couldn't SetVideoMode: %s\n", SDL_GetError());
		quit(1);
	}

    while (!done) {
        SDL_Event e;
        while (SDL_PollEvent(&e)) {
            if (e.type == SDL_QUIT) {
                done = 1;
            } else if (e.type == SDL_KEYDOWN) {
                if (e.key.keysym.sym == SDLK_a) {
                	if ( SDL_OpenAudio(&wave.spec, NULL) < 0 ) {
		                fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
		                SDL_FreeWAV(wave.sound);
		                quit(2);
	                }
	                SDL_PauseAudio(0);

                } else if (e.key.keysym.sym == SDLK_s) {
                    SDL_CloseAudio();

                } else if (e.key.keysym.sym == SDLK_c) {
                    if (!cdrom) {
    	                cdrom = SDL_CDOpen(0);
                        if (!cdrom) {
    		                fprintf(stderr, "Couldn't open cdrom: %s\n", SDL_GetError());
    		                SDL_FreeWAV(wave.sound);
    		                quit(2);
    	                }
    			        if ( !CD_INDRIVE(SDL_CDStatus(cdrom)) ) {
    		                fprintf(stderr, "No CD in drive: %s\n", SDL_GetError());
    		                SDL_FreeWAV(wave.sound);
    		                quit(2);
    	                }
    				    if ( SDL_CDPlayTracks(cdrom, 0, 0, 0, 0) < 0 ) {
    		                fprintf(stderr, "Failed to play CD: %s\n", SDL_GetError());
    		                SDL_FreeWAV(wave.sound);
    		                quit(2);
    	                }
                    }
                } else if (e.key.keysym.sym == SDLK_v) {
                    SDL_CDClose(cdrom);
                    cdrom = NULL;

                } else if (e.key.keysym.sym == SDLK_q) {
                    done = 1;
                }
            }
        }
        SDL_Delay(100);
    }

	/* Clean up on signal */
    if (cdrom) { SDL_CDClose(cdrom); }
	SDL_CloseAudio();
	SDL_FreeWAV(wave.sound);
	SDL_Quit();
	return(0);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants