Source Tales of Pirate 2026 x64 DX9 by alexxst.st

We all have ai it's not hard to ask/create something like this xD

If you aren't using AI alexst might agree probably isn't worth the effort to use his files over mothanna's.

--

I forked and am working implementing top2 stuff on these files. Might share, but there are some pretty complicated issues you probably wouldn't be able to navigate without years of previous knowledge and or opus 4.8/codex 5.5. And strong knowledge on agentic ai use to effectively make it work.
Hahaha, "without years of previous knowledge" is a big statement for the history of agent development, which only started to do something worthwhile in 2025.

P.S. @Fade, you can try claude code (better than codex) for development. Some small features can be added on any source. Features that require global refactoring and architectural changes can be sent to me. I will definitely get to them.
 
1780249142822.webp

RmlUI is base integrated. -
Please, Log in or Register to view URLs content!

Coming soon - create any interfaces in client in lua script + html + css
 
  • Like
Reactions: Panda
Alex I was taking to a friend they said this might be completely rewriteable in rust. Haven't actually given it any thought but wanted to see what you thought.

I'm going to investigate I'll post my findings.


edit:

Following up on my offer to dig into the Rust angle — I went deep on it (scoped the actual LOC across engine/client/server, the DX8/9 surface, the CaLua coupling, the IOCP/MSSQL server stack) and honestly, alexxst, you're right about the core problem. You can't translate this codebase as-is. The coupling is exactly what you said — global state, deep pointer graphs, the architectural layers all bleeding into each other — and that's the textbook worst case for Rust's ownership model. Anyone who thinks you autocxx your way through a mixed-up engine like this is going to have a bad time. So to be clear, I'm not proposing a line-by-line port of the current tree, and the work you're already doing — C++23, decoupling the layers, bgfx for rendering, RmUI for scripting — is exactly the refactoring that would make any future port tractable in the first place. The cleaner the boundaries get, the more a rewrite stops being insane.

Where I'd push back gently is on the framing of "translate." The interesting path isn't translation, it's rewrite-against-an-oracle — and that sidesteps the coupling entirely, because you're matching observable behavior, not porting internal structure. The old client and server still run, so you capture real traffic, replay it against both, and diff. Every discrepancy is observable and fixable, which means correctness becomes convergent rather than a gamble — you grind diffs to green instead of hoping you reproduced 20 years of edge cases. With that harness, server-first (Linux-native, no Windows/IOCP lock-in, memory-safe packet handling, kills the 32-bit dependency hell), I'd put a faithful result genuinely high. None of this is an argument to drop what you're doing — your modernization is the prerequisite. It's more "once the layers are actually separated, the Rust question stops being theoretical." Happy to share the full scoping numbers if anyone wants them.
 
Last edited:
Alex I was taking to a friend they said this might be completely rewriteable in rust. Haven't actually given it any thought but wanted to see what you thought.

I'm going to investigate I'll post my findings.
I don't know.

In my opinion, the client-server architecture is a piсe of shit right now, and all the architectural layers are mixed up, and as a 20-year-experienced system architect, I'm crying bloody tears.
I'm not even trying to make any features right now, because they'll inevitably blow up in other places and cause unexpected issues.
I'm doing my best to improve the architecture.
Raise the language level to C++23.
Throw out the bad modules and add the already written, well-established third-party libraries (fontstash font rendering, RmUI, throw out the DirectX renderer and rewrite it with bgfx. Implement LuaBridge and eradicate the obscene language in lua scripts.
Using C++ and AI, I can replace the voluminous code of the server and client in parts, monitoring the negative trends in time. I've already had multiple rollbacks because something in the client just fell off completely due to forgotten edits or strange variables.

I believe that due to the excessive coupling, it won't be possible to simply rewrite this game into any other language other than the original one. However, after refactoring, it might be possible because the code's coupling will decrease significantly, allowing the AI to track everything correctly.
 
  • Like
Reactions: elpepe122
Following up on the Rust idea I floated earlier, since I said I'd investigate and report back. After digging into it properly, I've landed somewhere different from where I started, and I think it's worth sharing because the conclusion surprised me.

Short version: I don't think a full Rust rewrite is the move, and finishing the C++23 x64 path is. Not because Rust is bad, but because the question kind of dissolved once I looked closely. 64-bit is already a solved problem on this engine (there are native 64-bit builds running out there, mAPKO being the obvious one), so Rust was never actually needed to get there. The client side doesn't need Rust either, especially with milten21's Unity port building first-class importers for the proprietary formats. So the only place a rewrite ever made real sense was the server, which is also the one part Rust is genuinely good at. "Rewrite everything in Rust" quietly turned into "maybe rewrite just the server, eventually."

And here's the part that settled it for me. The only safe way to rewrite the server is to verify it against the existing C++ server, capture real traffic, replay it, and diff the output until it matches. That means you need a finished, working C++ server to check against. So finishing the C++ x64 work isn't a competitor to a rewrite, it's a prerequisite for one. Even if the server in Rust were the end goal, you'd still finish the C++ version first to have a reference to verify against. That flips the whole thing: C++ first, regardless of what you do later.
 
Wanted to share some progress and, more usefully, document the specific traps, since anyone porting this engine to x64 is going to hit the exact same ones.

Short version: I have a native x64 build of the client (Game64.exe) that's playable end to end against the unmodified 32-bit servers. Login, character select, world load, rendering, combat all work. No server changes required.

Why it can talk to 32-bit servers unchanged: Windows x64 is LLP64, so int and long stay 32-bit and only pointers grow to 8 bytes. The packets serialize field by field and carry no raw pointers, so the wire format is identical between the 32-bit and 64-bit builds. That's the key realization that lets you do an x64 client without touching the server at all.

Approach: every x64 change is wrapped in #ifdef _WIN64, the 32-bit build stays byte-identical, and the x64 output is isolated to its own folder. I deliberately did not refactor anything while porting. The goal was "get to playable x64 with zero regression to the shipping client," and keeping the two builds surgically separated is what made that achievable.

The mechanical stuff (expected): inline x86 asm rewritten as portable C (MSVC x64 forbids __asm), ODBC indicator vars to SQLLEN/SQLULEN, SetWindowLongPtr/INT_PTR for the window and dialog procs, and sourcing x64 builds of every third-party dep (DX9 libs, LuaJIT, SDL2 in place of SDL 1.2.7, discord-rpc, CryptoPP with asm disabled).

The part actually worth documenting, because LLP64 means only pointer-bearing serialized structs break:

1. lwTexInfo::data is a void*. It's a 4-byte slot in the on-disk model file but 8 bytes in the x64 struct, so a raw fread of the record over-reads and desyncs all the material/texture data, then crashes during resource load. It is the only directly-fread pointer-bearing struct in the whole model/mesh/material/bone/anim path, so the fix is narrow: read each record through a 32-bit on-disk mirror struct and leave the rest untouched.
2. Table .bin: CRawDataInfo::pData is also a void*, which breaks the encrypted record stride on x64. I read these through a mirror with the on-disk stride derived from the record count rather than sizeof, because tail-padding on x64 makes a sizeof-based guess wrong for any table whose derived fields aren't an 8-byte multiple (that one cost me a crash before I figured it out).
3. Biggest landmine, flagging this one loudly: if your x64 build ever calls the "make bin" path, it rewrites the shared .bin files (StringSet.bin in my case) in 64-bit record layout. Your 32-bit client then reads that as garbage and crashes on load. If you run both builds against shared data, guard every bin-write path with #ifndef _WIN64 or you'll corrupt your working 32-bit client from the x64 one and spend a while wondering why.

Still open: the bad-model handler is currently a try/catch net rather than a real fix, deeper in-game testing, and then the server x64 phase, which will hit the same pointer-in-serialized-struct issues for the server-side data structs.

None of this is a replacement for the proper modernization work happening on the engine, it's the conservative "keep 32-bit intact, get x64 running alongside it" route. Happy to compare notes with anyone going down the same path, the serialization gotchas above are engine-wide and not specific to my fork.
 
Btw..i have noticed some are using these files but they are facings some random crashes..check that if possible