Skip to content

Commit

Permalink
krkrwine v9.0 - rewrite almost everything
Browse files Browse the repository at this point in the history
  • Loading branch information
Alcaro committed Mar 28, 2024
1 parent c202934 commit 30a6544
Show file tree
Hide file tree
Showing 9 changed files with 785 additions and 2,251 deletions.
66 changes: 36 additions & 30 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,31 +28,34 @@ krkrwine-i386.dll: krkrwine.cpp Makefile
$(MINGW32) krkrwine.cpp -shared -fPIC -o krkrwine-i386.dll -lole32

prepare:
cp $(EGGROLL)/files/lib64/gstreamer-1.0/libgstmpegpsdemux.so Glorious-Eggroll/x86_64-libgstmpegpsdemux.so
cp $(EGGROLL)/files/lib64/gstreamer-1.0/libgstasf.so Glorious-Eggroll/x86_64-libgstasf.so
cp $(EGGROLL)/files/lib64/libgstcodecparsers-1.0.so.0 Glorious-Eggroll/x86_64-libgstcodecparsers-1.0.so.0
cp $(EGGROLL)/files/lib64/libavcodec.so.58 Glorious-Eggroll/x86_64-libavcodec.so.58
cp $(EGGROLL)/files/lib64/libavutil.so.56 Glorious-Eggroll/x86_64-libavutil.so.56
cp $(EGGROLL)/files/lib64/libavfilter.so.7 Glorious-Eggroll/x86_64-libavfilter.so.7
cp $(EGGROLL)/files/lib64/libavformat.so.58 Glorious-Eggroll/x86_64-libavformat.so.58
cp $(EGGROLL)/files/lib64/libavdevice.so.58 Glorious-Eggroll/x86_64-libavdevice.so.58
cp $(EGGROLL)/files/lib64/libswresample.so.3 Glorious-Eggroll/x86_64-libswresample.so.3
cp $(EGGROLL)/files/lib64/libswscale.so.5 Glorious-Eggroll/x86_64-libswscale.so.5
cp $(EGGROLL)/files/lib/gstreamer-1.0/libgstmpegpsdemux.so Glorious-Eggroll/i386-libgstmpegpsdemux.so
cp $(EGGROLL)/files/lib/gstreamer-1.0/libgstasf.so Glorious-Eggroll/i386-libgstasf.so
cp $(EGGROLL)/files/lib/libgstcodecparsers-1.0.so.0 Glorious-Eggroll/i386-libgstcodecparsers-1.0.so.0
cp $(EGGROLL)/files/lib/libavcodec.so.58 Glorious-Eggroll/i386-libavcodec.so.58
cp $(EGGROLL)/files/lib/libavutil.so.56 Glorious-Eggroll/i386-libavutil.so.56
cp $(EGGROLL)/files/lib/libavfilter.so.7 Glorious-Eggroll/i386-libavfilter.so.7
cp $(EGGROLL)/files/lib/libavformat.so.58 Glorious-Eggroll/i386-libavformat.so.58
cp $(EGGROLL)/files/lib/libavdevice.so.58 Glorious-Eggroll/i386-libavdevice.so.58
cp $(EGGROLL)/files/lib/libswresample.so.3 Glorious-Eggroll/i386-libswresample.so.3
cp $(EGGROLL)/files/lib/libswscale.so.5 Glorious-Eggroll/i386-libswscale.so.5
mkdir Glorious-Eggroll/
cp $(EGGROLL)/files/lib64/gstreamer-1.0/libgstmpegpsdemux.so Glorious-Eggroll/x86_64-libgstmpegpsdemux.so
cp $(EGGROLL)/files/lib64/gstreamer-1.0/libgstasf.so Glorious-Eggroll/x86_64-libgstasf.so
cp $(EGGROLL)/files/lib64/gstreamer-1.0/libgstvideoparsersbad.so Glorious-Eggroll/x86_64-libgstvideoparsersbad.so
cp $(EGGROLL)/files/lib64/libgstcodecparsers-1.0.so.0 Glorious-Eggroll/x86_64-libgstcodecparsers-1.0.so.0
cp $(EGGROLL)/files/lib64/libavcodec.so.58 Glorious-Eggroll/x86_64-libavcodec.so.58
cp $(EGGROLL)/files/lib64/libavutil.so.56 Glorious-Eggroll/x86_64-libavutil.so.56
cp $(EGGROLL)/files/lib64/libavfilter.so.7 Glorious-Eggroll/x86_64-libavfilter.so.7
cp $(EGGROLL)/files/lib64/libavformat.so.58 Glorious-Eggroll/x86_64-libavformat.so.58
cp $(EGGROLL)/files/lib64/libavdevice.so.58 Glorious-Eggroll/x86_64-libavdevice.so.58
cp $(EGGROLL)/files/lib64/libswresample.so.3 Glorious-Eggroll/x86_64-libswresample.so.3
cp $(EGGROLL)/files/lib64/libswscale.so.5 Glorious-Eggroll/x86_64-libswscale.so.5
cp $(EGGROLL)/files/lib/gstreamer-1.0/libgstmpegpsdemux.so Glorious-Eggroll/i386-libgstmpegpsdemux.so
cp $(EGGROLL)/files/lib/gstreamer-1.0/libgstasf.so Glorious-Eggroll/i386-libgstasf.so
cp $(EGGROLL)/files/lib/lib/gstreamer-1.0/libgstvideoparsersbad.so Glorious-Eggroll/i386-libgstvideoparsersbad.so
cp $(EGGROLL)/files/lib/libgstcodecparsers-1.0.so.0 Glorious-Eggroll/i386-libgstcodecparsers-1.0.so.0
cp $(EGGROLL)/files/lib/libavcodec.so.58 Glorious-Eggroll/i386-libavcodec.so.58
cp $(EGGROLL)/files/lib/libavutil.so.56 Glorious-Eggroll/i386-libavutil.so.56
cp $(EGGROLL)/files/lib/libavfilter.so.7 Glorious-Eggroll/i386-libavfilter.so.7
cp $(EGGROLL)/files/lib/libavformat.so.58 Glorious-Eggroll/i386-libavformat.so.58
cp $(EGGROLL)/files/lib/libavdevice.so.58 Glorious-Eggroll/i386-libavdevice.so.58
cp $(EGGROLL)/files/lib/libswresample.so.3 Glorious-Eggroll/i386-libswresample.so.3
cp $(EGGROLL)/files/lib/libswscale.so.5 Glorious-Eggroll/i386-libswscale.so.5


krkrwine.tar.gz: | Glorious-Eggroll/x86_64-libgstmpegpsdemux.so
$(MAKE) clean
$(MAKE) OPT=1
$(MAKE) OPT=1 -j4
-rm krkrwine.tar.gz
tar -czvf krkrwine.tar.gz --transform='s%^%krkrwine/%' --show-transformed-names README.md install.py gstkrkr-i386.so gstkrkr-x86_64.so krkrwine-i386.dll krkrwine-x86_64.dll Glorious-Eggroll/

Expand Down Expand Up @@ -105,11 +108,11 @@ wai:
ln -s $(shell realpath .)/krmovie.dll /games/wine/waga/waga/plugin/krmovie.dll

X1_HOME = /home/walrus/mount/x1/home/x1/
X1_PROTON = $(X1_HOME)steam/steamapps/common/"Proton 8.0"/
X1_PFX = $(X1_PROTON)dist/share/default_pfx/
X1_DLL = $(X1_PFX)drive_c/windows/syswow64/krkrwine.dll
X1_PROTON = $(X1_HOME)steam/steamapps/common/"Proton 9.0 (Beta)"/
X1_TARGET = $(X1_PROTON)krkrwine/
X1_DLL = $(X1_TARGET)krkrwine-i386.dll
X1_GST = $(X1_TARGET)gstkrkr-i386.so
X1_EXE = $(X1_HOME)Desktop/a.exe
X1_GST = $(X1_PROTON)dist/lib/gstreamer-1.0/gstkrkr-i386.so
ax1: run32.exe krkrwine-i386.dll gstkrkr-i386.so
-rm $(X1_DLL) $(X1_EXE) $(X1_GST)
cp krkrwine-i386.dll $(X1_DLL)
Expand All @@ -119,12 +122,15 @@ ax1: run32.exe krkrwine-i386.dll gstkrkr-i386.so
installx1: all
./install.py $(X1_PROTON)

X2_HOME = /home/walrus/mount/x2/home/x2/
X2_PROTON = $(X2_HOME)steam/steamapps/common/"Proton 9.0 (Beta)"/
X2_WAGA = $(X2_HOME)steam/steamapps/common/"WAGAMAMA HIGH SPEC"

installx2: all
./install.py /home/walrus/mount/x2/home/x2/steam/steamapps/common/"Proton 8.0"/
./install.py $(X2_PROTON)

X2_WAGAPATH = /home/walrus/mount/x2/home/x2/steam/steamapps/common/"WAGAMAMA HIGH SPEC"
waux2:
mv $(X2_WAGAPATH)/plugin/_rmovie.dll $(X2_WAGAPATH)/plugin/krmovie.dll
mv $(X2_WAGA)/plugin/_rmovie.dll $(X2_WAGA)/plugin/krmovie.dll
waix2: krmovie.dll
mv -n $(X2_WAGAPATH)/plugin/krmovie.dll $(X2_WAGAPATH)/plugin/_rmovie.dll
cp krmovie.dll $(X2_WAGAPATH)/plugin/krmovie.dll
mv -n $(X2_WAGA)/plugin/krmovie.dll $(X2_WAGA)/plugin/_rmovie.dll
cp krmovie.dll $(X2_WAGA)/plugin/krmovie.dll
50 changes: 15 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,34 @@
krkrwine
========

This program implements various missing functionality in Wine / Proton, such that videos work properly in Kirikiri-based visual novels. (Other games are not targetted by krkrwine, but they may be improved as well.)
This program implements various missing functionality in Wine / Proton, such that videos work properly in Kirikiri- and BURIKO-based visual novels. (Other software is not targetted by krkrwine, but may be improved as well.)

While I am doing my best to upstream my fixes, Proton's release cycle is once a year; krkrwine allows me to run these VNs before Proton 10 releases in 2025.

Installation - Linux/Proton
---------------------------

Simply download and extract [a release](https://github.com/Alcaro/krkrwine/releases), run ./install.py ~/steam/steamapps/common/Proton\ 8.0/, and it will install into every current and future game using that Proton. Installing krkrwine into Glorious Eggroll should work too, though this is untested.
Simply download and extract [a release](https://github.com/Alcaro/krkrwine/releases), run `./install.py ~/'steam/steamapps/common/Proton 9.0 (Beta)/'`, and it will install into every current and future game using that Proton. Installing krkrwine into Glorious Eggroll should work too, though this is untested.

krkrwine does not replace any existing files, and Steam's updater ignores files it doesn't recognize; therefore, you don't need to reinstall krkrwine if Proton updates. (However, if you reinstall Proton, or download a new Proton version, you obviously need to reinstall krkrwine too.)

krkrwine is only tested in Proton 8.0; I don't think it'll break too hard in anything else, but it's untested.
krkrwine is only tested in Proton 9.0, and may misbehave in other Proton versions. For Proton 8.0, use an older release; for older Proton, upgrade.

Installation - Linux/Wine
-------------------------

On Debian,

- Download and extract [a release](https://github.com/Alcaro/krkrwine/releases)
- sudo apt install gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-plugins-good:i386 gstreamer1.0-plugins-bad:i386 gstreamer1.0-plugins-ugly:i386 gstreamer1.0-libav:i386
- ./install.py --wine

On other distros, the package names are different.
Not recommended. I recommend using the latest Wine, such that krkrwine is unnecessary.

Note that on Debian, gstreamer1.0-libav is not part of, or a dependency of, gstreamer1.0-plugins-good, -bad, nor -ugly; it must be installed separately. I haven't checked other distros.
If you or your distro feel otherwise, you can use `./install.py --wine`. (It will obey WINEPREFIX, if set.)

install.py will obey the WINEPREFIX environment variable, if set.
Make sure to use the correct krkrwine version; krkrwine 9.0 needs Wine 9.0 or higher. For older Wine, use an older release.

krkrwine's GStreamer component will not be installed under Wine; it does nothing useful if you have the above plugins and don't have protonmediaconverter. If you want them anyways for development purposes, you can copy or link them to ~/.local/share/gstreamer-1.0/plugins/.
Do not install krkrwine's codecs; instead (for Debian), `sudo apt install gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-plugins-good:i386 gstreamer1.0-plugins-bad:i386 gstreamer1.0-plugins-ugly:i386 gstreamer1.0-libav:i386`. For other distros, the packages have different names. (Note that on Debian, gstreamer1.0-libav is not part of, or a dependency of, gstreamer1.0-plugins-good, -bad, nor -ugly; it must be installed separately.)

Installation - macOS
--------------------

See the Linux/Wine steps, it'll probably work. However, it's untested, and I can't help you if it breaks.
Not recommended. Feel free to try the Linux/Wine steps, but it's more untested than Linux/Wine; I can't help you if it breaks.

Installation - Windows
----------------------
Expand All @@ -46,8 +42,10 @@ Compilation
- sudo apt install make gcc libgstreamer1.0-dev gcc-multilib libgstreamer1.0-dev:i386 g++-mingw-w64-i686-win32 g++-mingw-w64-x86-64-win32
- make prepare EGGROLL=/home/user/steam/compatibilitytools.d/GE-Proton8-4/
- make
- ./install.py /home/user/steam/steamapps/common/Proton\ 8.0/
If desired, you may acquire i686-w64-mingw32-g++-win32 and x86_64-w64-mingw32-g++-win32 programs from elsewhere. I use https://winlibs.com/ in Wine. (Compiling with *-mingw32-g++-posix is not recommended, since it adds dependencies on libwinpthread-1.dll, and possibly others; I don't know if installing that lib into system32 breaks anything, and I don't feel like finding out.)
- ./install.py ~/'steam/steamapps/common/Proton 9.0 (Beta)/'
If desired, you may acquire i686-w64-mingw32-g++-win32 and x86_64-w64-mingw32-g++-win32 from elsewhere. I use https://winlibs.com/ in Wine. (Compiling with *-mingw32-g++-posix is not recommended, since it adds dependencies on libwinpthread-1.dll, and possibly others; I don't know if installing that lib into system32 breaks anything, and I don't feel like finding out.)

If you want to use krkrwine's GStreamer components under Wine for debugging purposes, copy or link them to ~/.local/share/gstreamer-1.0/plugins/. For anyone else, use gst-libav.

License
-------
Expand All @@ -59,22 +57,4 @@ The Glorious-Eggroll subdirectory of the releases is, as the name implies, copie
Upstreaming
-----------

Ideally, this project would be unnecessary (other than the codec installation). As such, I'm offering bounties on fixing the Windows-side issues in upstream Wine.

- $250 - CLSID_MPEG1Splitter video output, and CLSID_CMpegVideoCodec (these objects may use GStreamer, of course)
- $25 - CLSID_MPEG1Splitter IAMStreamSelect (doesn't need to be fully implemented, just needs the parts Kirikiri uses)
- ~~$25 - CLSID_VideoMixingRenderer9 ChangeD3DDevice and NotifyEvent~~ Resolved and claimed
- $500 - WMCreateSyncReader compressed output, CLSID_CWMADecMediaObject, and CLSID_CWMVDecMediaObject
- $100 - Direct3D 9 on WS_CHILD windows under wined3d in the Debian package - the bug doesn't reproduce if I compile Wine from source
- $25 - make WMSyncReader resize its allocator, so it can output RGB32 properly
- $100 - figure out what's going on with the memory allocator and VFW_E_NOT_COMMITTED, and solve it
- $0 - anything involving gstkrkr and Proton's GStreamer. That's a patent issue; it's a question for lawyers, not programmers. It's only needed in Proton, not vanilla Wine.
- Anything that Kirikiri needs but isn't in the above list - that's a bug in this readme, contact me

though I'm working on them myself, so fair chance I'll finish first.

You are allowed, but not required, to base such efforts on this project. My architecture is very different from Wine's existing objects, and many of them are implemented in an awful way, so most of my code is unusable; but you're welcome to look for hints on the objects' expected behavior, or otherwise use them to help implement yours. You may also use the Kirikiri source code, <https://github.com/krkrz/krkr2/tree/master/kirikiri2/trunk>

To claim a bounty, post at <https://github.com/Alcaro/krkrwine/discussions/1>, or email me at [email protected]. These bounties can be combined with similar offers made by others.

If I see any of the above implemented, but nobody claims the bounty, I will wait one month, then donate it to Wine.
All relevant pieces of this project have been upstreamed. The bounties that were here have been claimed.
38 changes: 33 additions & 5 deletions fake-krmovie.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,19 @@
// (I'm not sure if headers and other required interopability data is covered by copyright, but better safe than sorry.)
// (I also don't know if Kirikiri is 2.0 only or 2.0 or later, so I'll pick the safe choice.)

//#define DOIT
#ifdef __MINGW32__
# define _FILE_OFFSET_BITS 64
// mingw *really* wants to define its own printf/scanf, which adds ~20KB random stuff to the binary
// (on some 32bit mingw versions, it also adds a dependency on libgcc_s_sjlj-1.dll)
// extra kilobytes and dlls is the opposite of what I want, and my want is stronger, so here's some shenanigans
// comments say libstdc++ demands a POSIX printf, but I don't use libstdc++'s text functions, so I don't care
# define __USE_MINGW_ANSI_STDIO 0 // trigger a warning if it's enabled already - probably wrong include order
# include <cstdbool> // include some random c++ header; they all include <bits/c++config.h>,
# undef __USE_MINGW_ANSI_STDIO // which ignores my #define above and sets this flag; re-clear it before including <stdio.h>
# define __USE_MINGW_ANSI_STDIO 0 // (subsequent includes of c++config.h are harmless, there's an include guard)
#endif

#define DOIT

#define STRSAFE_NO_DEPRECATE
#define INITGUID
Expand All @@ -16,6 +28,22 @@
#include <d3d9.h>
#include <vmr9.h>

// can't use stdout from wine/proton since 8.12 https://gitlab.winehq.org/wine/wine/-/commit/dcf0bf1f383f8429136cb761f5170a04503a297b
static void my_puts(const char * a, bool linebreak=true)
{
static int __cdecl (*__wine_dbg_output)( const char *str );
if (!__wine_dbg_output)
__wine_dbg_output = (decltype(__wine_dbg_output))GetProcAddress(GetModuleHandle("ntdll.dll"), "__wine_dbg_output");
if (__wine_dbg_output)
{
__wine_dbg_output(a);
if (linebreak)
__wine_dbg_output("\n");
}
}
#define puts my_puts
#define printf(...) do { char my_buf[4096]; sprintf(my_buf, __VA_ARGS__); my_puts(my_buf, false); } while(0)

#ifdef __i386__
// needs some extra shenanigans to kill the stdcall @12 suffix
#define EXPORT_STDCALL(ret, name, args) \
Expand Down Expand Up @@ -322,7 +350,6 @@ BOOL __stdcall myMoveWindow(HWND hWnd, int X, int Y, int nWidth, int nHeight, BO
return MoveWindow(hWnd, X, Y, nWidth, nHeight, bRepaint);
}

IDirect3DDevice9* g_d3ddev;
bool dump_texture(IDirect3DSurface9* renderTarget, const char * filename)
{
HRESULT hr;
Expand Down Expand Up @@ -500,22 +527,23 @@ class fancy_iTVPVideoOverlay : public iTVPVideoOverlay // this is not a COM obje
virtual void __stdcall GetStatus(tTVPVideoStatus* status) { puts("fancy_iTVPVideoOverlay GetStatus"); orig_overlay->GetStatus(status); }
virtual void __stdcall GetEvent(long* evcode, long* param1, long* param2, bool* got)
{
//puts("fancy_iTVPVideoOverlay GetEvent");
puts("fancy_iTVPVideoOverlay GetEvent");
orig_overlay->GetEvent(evcode, param1, param2, got);
printf("ev %ld %ld %ld %d\n", *evcode, *param1, *param2, *got);
}

// Start: Add: T.Imoto
virtual void __stdcall FreeEventParams(long evcode, long param1, long param2)
{
//puts("fancy_iTVPVideoOverlay FreeEventParams");
puts("fancy_iTVPVideoOverlay FreeEventParams");
orig_overlay->FreeEventParams(evcode, param1, param2);
}

virtual void __stdcall Rewind() { puts("fancy_iTVPVideoOverlay Rewind"); orig_overlay->Rewind(); }
virtual void __stdcall SetFrame( int f ) { puts("fancy_iTVPVideoOverlay SetFrame"); orig_overlay->SetFrame(f); }
virtual void __stdcall GetFrame( int* f )
{
//puts("fancy_iTVPVideoOverlay GetFrame");
puts("fancy_iTVPVideoOverlay GetFrame");
orig_overlay->GetFrame(f);
printf("frame=%d\n", *f);
}
Expand Down
16 changes: 10 additions & 6 deletions gstkrkr.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,15 +256,19 @@ static gboolean gst_krkr_video_sink_event(GstPad* pad, GstObject* parent, GstEve

static GstFlowReturn gst_krkr_video_sink_chain(GstPad* pad, GstObject* parent, GstBuffer* buf)
{
//fprintf(stderr, "gstkrkr: reading\n");
GstKrkrPlMpegVideo* filter = GST_KRKRPLMPEG_VIDEO(parent);
for (size_t n=0;n<gst_buffer_n_memory(buf);n++)
{
GstMapInfo meminf;
GstMemory* mem = gst_buffer_get_memory(buf, n);
mem = gst_memory_make_mapped(mem, &meminf, GST_MAP_READ);
//fprintf(stderr, "gstkrkr: read %zu bytes\n", meminf.size);
plm_buffer_write(filter->buf, meminf.data, meminf.size);
gst_memory_unmap(mem, &meminf);
gst_memory_unref(mem);
}
gst_buffer_unref(buf);

while (true)
{
Expand Down Expand Up @@ -294,7 +298,7 @@ static GstFlowReturn gst_krkr_video_sink_chain(GstPad* pad, GstObject* parent, G

size_t buflen = frame->width*frame->height*12/8;
uint8_t* ptr = g_malloc(buflen);
GstBuffer* buf = gst_buffer_new_wrapped(ptr, buflen);
GstBuffer* buf2 = gst_buffer_new_wrapped(ptr, buflen);
for (int y=0;y<frame->height;y++)
{
memcpy(ptr, frame->y.data + frame->y.width*y, frame->width);
Expand All @@ -311,11 +315,11 @@ static GstFlowReturn gst_krkr_video_sink_chain(GstPad* pad, GstObject* parent, G
ptr += frame->width/2;
}

buf->pts = frame->time * 1000000000;
buf->dts = frame->time * 1000000000;
buf->duration = 1000000000 / plm_video_get_framerate(filter->decode);
//fprintf(stderr, "gstkrkr: send frame, %lu bytes\n", gst_buffer_get_size(buf));
gst_pad_push(filter->srcpad, buf);
buf2->pts = frame->time * 1000000000;
buf2->dts = frame->time * 1000000000;
buf2->duration = 1000000000 / plm_video_get_framerate(filter->decode);
//fprintf(stderr, "gstkrkr: send frame, %zu bytes\n", gst_buffer_get_size(buf2));
gst_pad_push(filter->srcpad, buf2);
}

return GST_FLOW_OK;
Expand Down
Loading

0 comments on commit 30a6544

Please sign in to comment.