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

Getting PocoMan.exe running #43

Open
25 of 27 tasks
LinusU opened this issue Sep 13, 2024 · 23 comments
Open
25 of 27 tasks

Getting PocoMan.exe running #43

LinusU opened this issue Sep 13, 2024 · 23 comments

Comments

@LinusU
Copy link
Contributor

LinusU commented Sep 13, 2024

This issue is to track my work in getting PocoMan v4.0 running. See more background in #39

My working branch is here: https://github.com/LinusU/retrowin32/tree/pocoman

@evmar
Copy link
Owner

evmar commented Sep 13, 2024

This looks great so far, thanks for breaking it up! Also if you need any help or advice looking into your binary please reach out. I would love to flesh out the docs with anything useful for you.

@evmar
Copy link
Owner

evmar commented Sep 14, 2024

By the way, if a function is missing, retrowin32 logs a warning about it but keeps running. So it will only matter if your binary actually calls it (where it will crash after calling a null pointer). Functions like ExitThread might not matter until you get to the end of the program, not sure.

@LinusU
Copy link
Contributor Author

LinusU commented Sep 14, 2024

It seems like the threading is just used to kick of one thread that connects to the internet and check some kind of latest news, stores it in the registry, and then exits. Without ExitThread it crashed the entire program when it tried to exit, which since I've only stubbed the internet connect functions is basically immediately 😅

I'm at a point now where the program can run more than a few milliseconds! Unfortunately, it's a very tiny window, and something with the rendering seems broken. And as soon as I press anywhere it tries to call WideCharToMultiByte.

Screenshot 2024-09-14 at 23 30 00
INFO win32/src/winapi/user32/window.rs:324 user32/window/CreateWindowExA(dwExStyle:Err(300), lpClassName:Name("PocoMan Class"), lpWindowName:Some("PocoMan"), dwStyle:Ok(BORDER | DLGFRAME | SYSMENU | GROUP), X:80000000, Y:0, nWidth:1, nHeight:1, hWndParent:HANDLE(0), hMenu:0, hInstance:400000, lpParam:0) -> HANDLE(1)

This part seems a bit suspicious: X:80000000, Y:0, nWidth:1, nHeight:1

@evmar
Copy link
Owner

evmar commented Sep 15, 2024

One idea is you could maybe locally stub out the CreateThread impl such that it never starts the thread in the first place, just to see what happens next. Depends on if it waits for the thread to come back though. I saw in your above list you had CreateEvent/SetEvent which are typically used for thread synchronization...


I ran the installer (via wine 😊 ) and I get this:

     Running `target/debug/retrowin32 --win32-trace - '/Users/evmar/.wine/drive_c/Program Files (x86)/PocoMan/pocoman.exe'`
WARN win32/src/winapi/kernel32/dll.rs:216 load_library("wsock32.dll"): not found
WARN win32/src/winapi/kernel32/misc.rs:152 IsProcessorFeaturePresent(Ok(FLOATING_POINT_PRECISION_ERRATA)) => false
thread 'main' panicked at x86/src/ops/basic.rs:478:16:
attempt to shift left with overflow

I guess I need more of your patches?


The window size could indicate a problem, but also some apps I've seen create a window with an unknown size, then resize it later in response to some window messages.
... since I have the exe anyway I checked and that is what it does.

ghidra says:

      g_hwnd = CreateWindowExA(0x300,s_PocoMan_Class_00418174,s_PocoMan_00418184,0xca0000,local_14,
                               local_18,1,1,(HWND)0x0,(HMENU)0x0,pHVar2,(LPVOID)0x0);

and there is some function called by the wndproc that does

  GetWindowRect(g_hwnd,&local_3c);
  GetClientRect(g_hwnd,&tStack_4c);
  SetWindowPos(g_hwnd,(HWND)0x0,0,0, ...

@evmar
Copy link
Owner

evmar commented Sep 15, 2024

My above crash is fixed in 6427aed, which now reveals the actual problem was running from the wrong directory

MessageBox: PocoMan
Can't open PocoMan.map for reading

@evmar
Copy link
Owner

evmar commented Sep 16, 2024

If it helps you any, feel free to send a PR that is just like "here are all the stubs I need". You don't need to send separate PRs for them if it's too much effort. (I'm fine with separate PRs, just trying to save you some effort...)

@LinusU
Copy link
Contributor Author

LinusU commented Sep 16, 2024

Sorry, I have had limited with time today and just cherry picked som already done work. Will give some more time to the comments later!

If it helps you any, feel free to send a PR that is just like "here are all the stubs I need"

Hehe, yeah I realized that that would probably have been a good strategy 😅

At this point I think that they are all merged though! Well, as far as I have gotten at least, will probably be a bit more when I get more time to dig further!

Thanks for all the help, and for looking into the binary yourself! As said, I'll try to read thru all your comments properly and answer in a few days

@LinusU
Copy link
Contributor Author

LinusU commented Sep 22, 2024

Making progress!

Screenshot 2024-09-22 at 17 19 28

Updating SetWindowPos to actually resize the host window fixed the sizing issue!

Need to implement stretching in StretchDIBits now 🐎

...and it seems like there are some flags to flip/rotate tiles that needs to be implemented

@LinusU
Copy link
Contributor Author

LinusU commented Sep 22, 2024

I'm running into a really strange problem. For some reason, the application is closing its file handle whilst in the middle of reading from it. It's reading the map data, and since it then errors out goes into an error state. Making CloseHandle a no-op fixes the issue:

diff --git a/win32/src/winapi/kernel32/file.rs b/win32/src/winapi/kernel32/file.rs
index 79e7b8a1..c8a6946f 100644
--- a/win32/src/winapi/kernel32/file.rs
+++ b/win32/src/winapi/kernel32/file.rs
@@ -382,7 +382,7 @@ pub fn SetFilePointer(
         lDistanceToMove |= (**high as i64) << 32;
     }
     let Some(file) = machine.state.kernel32.files.get_mut(hFile) else {
-        log::debug!("SetFilePointer({hFile:?}) unknown handle");
+        log::warn!("SetFilePointer({hFile:?}) unknown handle");
         set_last_error(machine, ERROR_INVALID_HANDLE);
         return u32::MAX;
     };
diff --git a/win32/src/winapi/kernel32/misc.rs b/win32/src/winapi/kernel32/misc.rs
index d6d06472..49de0c85 100644
--- a/win32/src/winapi/kernel32/misc.rs
+++ b/win32/src/winapi/kernel32/misc.rs
@@ -279,6 +279,7 @@ pub fn FormatMessageW(
 
 #[win32_derive::dllexport]
 pub fn CloseHandle(machine: &mut Machine, hObject: HFILE) -> bool {
+    return true; // FIXME: remove this line
     if machine.state.kernel32.files.remove(hObject).is_none() {
         log::debug!("CloseHandle({hObject:?}): unknown handle");
         set_last_error(machine, ERROR_INVALID_HANDLE);

It's happening right after the call to InternetOpenA, which I think is called by a background thread. I'm wondering if the file handles are somehow interfering with each other from the different threads 🤔

Reading the disassembled source, there are calls to InternetCloseHandle at the end of the function that runs in the background thread...

@LinusU
Copy link
Contributor Author

LinusU commented Sep 22, 2024

With the CloseHandle patch from last comment, the first map now loads! 🙌

Screenshot 2024-09-22 at 19 06 40

(something seems broken with the time in the titlebar, I just started the game in the screenshot)

@evmar
Copy link
Owner

evmar commented Sep 23, 2024

Re time, I just monkeyed with it here, maybe I got something wrong: 0c3e485

Re CloseHandle, I looked at the places where it's called in pocoman and most seemed to be error paths. But the one at address 00410419 might be it(?).

I wrote all of the threading-related stubs before retrowin32 supported threads so they are all definitely wrong. I see some use of thread-local storage in pocoman and that also is certainly wrong right now, not sure how serious it is. The function passed to CreateThread immediately calls TlsSetValue, probably to stash some sort of "current state" object.

@evmar
Copy link
Owner

evmar commented Sep 23, 2024

Hm wait, the call at 0040c77d seems to be the thread function shutting down and is closing a handle found in the Tls, that seems very likely it.

@evmar
Copy link
Owner

evmar commented Sep 23, 2024

(moving TLS discussion to #70 to not clutter this up)

@evmar
Copy link
Owner

evmar commented Oct 5, 2024

With 8c1713a it now plays "I am pocoman" audio on startup. Might get annoying, we can put it behind a flag if so!

@LinusU
Copy link
Contributor Author

LinusU commented Oct 6, 2024

With 8c1713a it now plays "I am pocoman" audio on startup. Might get annoying, we can put it behind a flag if so!

That's amazing!! 🤩

Although it seems like the audio then underflows and crashes the entire application 😅

WARN cli/src/sdl.rs:319 audiobuf underflow
thread '<unnamed>' panicked at cli/src/sdl.rs:315:34:
range start index 44544 out of range for slice of length 44100
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
libc++abi: terminating due to uncaught foreign exception
zsh: abort      cargo run -p retrowin32 -F x86-emu,sdl -- --win32-trace '*' PocoMan.exe

@evmar
Copy link
Owner

evmar commented Oct 6, 2024

Oh no! I pushed another commit to disable it by default until I have it all working, sorry!

@evmar
Copy link
Owner

evmar commented Oct 7, 2024

I added a --audio flag to the command line, and verified that after clicking through the first screen audio continues to work on the map if you click around. I think with StretchBlt and some keyboard support this would be pretty solid.

@evmar
Copy link
Owner

evmar commented Oct 7, 2024

The bitmap code is still gross but I made it a lot less gross in af32dd4 , with a special eye to making StretchBlt easy to implement.

evmar added a commit that referenced this issue Oct 9, 2024
When doing a stretching bit copy, we don't clip the src rectangle to match the
dst, we instead transform coordinates to fit within the bounds.

Part of #43.
@evmar
Copy link
Owner

evmar commented Oct 9, 2024

image

@evmar
Copy link
Owner

evmar commented Oct 10, 2024

image

sample program in exe/rust/bin/dib.rs that runs some of these functions

@evmar
Copy link
Owner

evmar commented Oct 10, 2024

oh and i can run it in wine to compare!

image

@evmar
Copy link
Owner

evmar commented Oct 12, 2024

ccdac71

image

@evmar
Copy link
Owner

evmar commented Oct 12, 2024

Implemented some missing file stuff on the web site, now runs in my browser!

image

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