Commit Graph
100 Commits
Author SHA1 Message Date
shenleiandClaude Opus 5.5 f345bd5d3b Ring 70058: usable from level 1, tooltip says unlimited and no cooldown
The item_proto limit (LEVEL 30) kept new characters from using the warp
ring. ring-warp/install.sh now clears it in share/conf/item_proto.txt and
the player.item_proto mirror. The client proto gets the same limit through
a new item_limits_server.tsv fed to locale_proto_patch, and the zh
itemdesc overlay replaces the "50 uses" text.

Verified on 203: a fresh level-1 character opened the warp menu four times
in a row (one real warp in between), ring still in the bag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 20:59:21 +09:00
shenleiandClaude Opus 5.5 01cc252a1d Host: 2x UI textures from hd_ui.pak (AI-upscaled 40250 UI art)
The phone magnifies the 600-high 40250 UI about 1.8x, so the 1x window art
and icons look soft next to the oversampled text. scripts/build_hd_ui.py
upscales every UI image the zh client loads (d:/ymir work/ui/, icon/,
locale/zh/) with realesrgan-x4plus, reduces it to 2x and back-projects the
residual so the board grain the network denoises away comes back; the host
uploads a texture found in hd_ui.pak in place of the pack file. Layout,
sizes and UVs stay the engine's 1x ones. MT_HD_UI=0 disables it; the pak
(135 MB, Ymir art) is built into the client dir and synced to the phone,
never committed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 20:04:46 +09:00
shenleiandClaude Opus 5.5 c5b709d38d Merge branch 'tools/android-deploy'
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 18:52:01 +09:00
shenleiandClaude Opus 5.5 8182445f8b Merge branch 'feat/app-icon'
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 18:52:00 +09:00
shenleiandClaude Opus 5.5 8ec8f1a445 UserInterface: poll the network stream on the 60 Hz update clock
40250 runs CPythonApplication::Process every 16/17 ms and only skips the
render when late, so GamePhase gets its three-packets-a-poll budget 60
times a second. The host polled once per rendered frame: at 30 fps idle
(or a slow phone) mob move packets queued behind character add/del
bursts for up to a second and mobs stopped, then jumped. Poll once per
elapsed 60 Hz tick. Real-server A/B: move push gap p50 138-178 -> 70-92
ms, p90 580-785 -> 358-403 ms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 18:36:49 +09:00
shenleiandClaude Opus 5.5 3aa4c482e9 tools/server: shop-item-time patch — NPC shop items carry a new item's time sockets
40250 game zeroes alSockets for NPC (shop.cpp) and extended (shopEx.cpp) shop items, so
uitooltip shows 'remaining 0 min' for mounts and item-mall time items. MT_GetNewItemSockets
fills them with ITEM_MANAGER::CreateItem's rules (UNIQUE remain time, auto potions,
LIMIT_REAL_TIME, LIMIT_TIMER_BASED_ON_WEAR). Deployed on 203; mount shop 20368 verified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 17:55:36 +09:00
shenleiandClaude Opus 5.5 f9be09d2c2 fix(touch): show the joystick and skill buttons only in the game phase
The controls keyed off CPythonBackground's warp map name, which the
loading window sets before the game window exists, so the loading screen
already showed them. Also require CPythonNetworkStream's phase to be
"Game" (PORT_IsGamePhase, exposed as PythonBoot::InGamePhase).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 17:33:46 +09:00
shenleiandClaude Opus 5.5 5c8d583b31 fix(touch): raise the soft keyboard only for a tap on the visible focused EditLine
A chat line keeps the IME focus under a hidden board (interfacemodule
__HideWindows for an NPC dialog, the focus handed back by
UnlockWindow/DeactivateWindow), and IsPointInsideFocusedWindow only
checked its own show flag and rect, so taps on the NPC dialog or the
minimap buttons opened the keyboard. Require the whole parent chain to
render and the picked window to be the focused one or its child.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 17:00:39 +09:00
shenleiandClaude Opus 5.5 78d14776b8 fix(platform): decode GDI ANSI text with the font charset's code page
TextOutA / GetTextExtentPoint32A in the Win32 GDI shim always decoded with CP_ACP (1252), so the
server notices drawn by uiTip.TipBoard / BigBoard (CTextBar, a GB2312_CHARSET font in the 936
locale) showed GBK bytes as Latin-1 mojibake. Windows GDI decodes ANSI calls with the code page of
the selected font's charset; the shim now keeps lfCharSet on the font and does the same.
port.text_bar checks TextOutA of GBK bytes against TextOutW of the Unicode text, and the extent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 16:42:44 +09:00
shenleiandClaude Opus 5.5 cd9e5b259d android: build.sh installs and syncs the game files when a phone is attached
After building the APK, android/build.sh now picks the attached device (ANDROID_SERIAL for several),
installs the APK (reinstalling on a signature mismatch), syncs the zh client into files/Client and, with
--launch, wakes the phone and starts the app. Without a device it only builds.

push-client.sh is now incremental (android/sync_client.py): the device keeps files/Client/.mt_sync
(size, mtime, path of what the last sync wrote), so later syncs send only new and changed files as one
tar streamed through `adb shell -T run-as` (no copy in /data/local/tmp) and delete the ones gone
locally. Only game resources are synced; settings and logs the app writes there are kept. --locale zh
rebuilds build/zh-locale/Client first when its inputs changed. android/adb_env.sh picks adb and falls
back to server port 5038 when :5037 cannot bind.

Verified against a fake adb device: first sync (1.4 GB, byte-identical), no-op resync, changed files,
deletions, locale switch, --full, the install/launch path and the no-device path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 16:36:21 +09:00
shenleiandClaude Opus 5.5 a60ed6b03f Add the Metin2 app icon for Android, macOS and iOS
branding/icon/icon.svg (a cracked Metin stone with glowing runes, inside a studded gold ring, in front of
a blood moon over ink mountains) is the single source; build_icons.sh renders it with headless Chrome and
writes the committed outputs: Android legacy + adaptive mipmaps (wired into the manifest), the macOS
AppIcon.icns and the iOS AppIcon.appiconset. scripts/package_mac_app.sh wraps mt_native_render into a
local Metin2.app using that icon.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 16:23:42 +09:00
shenleiandClaude Opus 5.5 58a3d01027 port: ScriptLib Resource.cpp verbatim 40250; PythonUtils mapped (already verbatim)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 16:10:32 +09:00
shenleiandClaude Opus 5.5 f9cd63713f docs: PORT-PLAN numbers after the platform TODO sweep
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:08:26 +09:00
shenleiandClaude Opus 5.5 b497fce393 port: UserInterface.cpp entry unit — ApplicationSetErrorString/StringTable_Initialize verbatim, Main ADAPTED to PythonBoot, Win32 entry N_A
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:08:00 +09:00
shenleiandClaude Opus 5.5 fd4d9a39df port: GrpDetector verbatim 40250 over a host IDirect3D8 (Direct3DCreate8); GrpDevice::Create verbatim
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:02:12 +09:00
shenleiandClaude Opus 5.5 65c43a84cd port: GrpDevice verbatim 40250 (Create over the recording device, declaration vertex shaders -> stream-0 FVF)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:50:21 +09:00
shenleiandClaude Opus 5.5 b5d413afa6 port: GrpScreen verbatim 40250 (2d draws via UIRender, D3D8 shim device-lost/Present/ID3DXMesh)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:40:57 +09:00
shenleiandClaude Opus 5.5 d73f5ea4bd port: SkyBox verbatim 40250 (native-terrain gate, qualified pure-virtual Destroy)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:31:07 +09:00
shenleiandClaude Opus 5.5 cfae658b6a audit: GrpTextInstance port-map (verbatim, Render draws via UI commands)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:21:57 +09:00
shenleiandClaude Opus 5.5 6f32387567 audit: GrpFontTexture port-map (40250 bodies, HiDPI oversample adaptations)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:21:37 +09:00
shenleiandClaude Opus 5.5 65777331f7 port: GrpImageInstance/GrpExpandedImageInstance verbatim; fix SCREEN blend factor
Both units are the 40250 bodies; only the PDT-stream draw becomes
UIRenderAddImage (with the rendering mode). SCREEN/COLOR_DODGE were packed as
0x28 (INVDESTALPHA+ONE); 40250 uses INVDESTCOLOR+ONE (0x2A). OnIsType calls the
base OnIsType instead of 40250's recursing IsType. port.grp_resource covers the
quads, UVs, colour and blend mode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:21:13 +09:00
shenleiandClaude Opus 5.5 010e99f070 port: Grp texture/image/buffer units toward 40250 (+ port.grp_resource)
GrpImage/GrpSubImage verbatim; GrpImageTexture DDS path through CDXTCImage
header + low-texture-memory mip bias, CreateDeviceObjects/CreateFromDiskFile
verbatim; GrpTexture::SetTextureStage via STATEMANAGER. Port-map entries for
GrpTexture/Image/SubImage/ImageTexture/IndexBuffer/VertexBuffer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:15:45 +09:00
shenleiandClaude Opus 5.5 7e385f827b test: login_flow waits out the 300 ms inventory/safebox refresh before dragging
CPythonNetworkStream::GamePhase throttles RefreshInventory/RefreshSafebox to
one call per 300 ms, so the bag slot could still be empty in the UI when the
test clicked it right after player state changed (~1 in 3 runs failed).
Also drops a leftover debug printf from CWindowManager::RunMouseMove.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:15:45 +09:00
shenleiandClaude Opus 5.5 75ea2703c6 port: EterImageLib Image/TGAImage/DXTCImage verbatim (+ d3d.h ddraw shim)
-fno-strict-aliasing on the port targets: 40250 relies on MSVC's lack of
type-based alias analysis (DXTCImage reads Color8888 through DWORD*).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:31:21 +09:00
shenleiandClaude Opus 5.5 32c5a09d6e port: EterLib/Input over host key events (DirectInput polling adapted)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:21:25 +09:00
shenleiandClaude Opus 5.5 5d64311a4d port: MSWindow/MSApplication verbatim over a winuser.h shim (Win32User.cpp)
Host-side window records + message queue; WM_SIZE/WM_MOVE/WM_DESTROY sent
synchronously as Win32 does; PostQuitMessage also queues WM_QUIT. 64-bit
pointer casts ADAPTED. port.ms_window.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:19:36 +09:00
shenleiandClaude Opus 5.5 80c5a1e39f port: ProcessCRC verbatim (module introspection adapted) + XTrap mapped
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:10:54 +09:00
shenleiandClaude Opus 5.5 6d2d262de8 port(EterLib): TextBar/DibBar/BlockTexture for uiTip TipBoard/BigBoard
TextBar and DibBar verbatim over the FreeType GDI shim (+GetTextExtentPoint32A);
BlockTexture verbatim except Render, which records the clipped quad as a UI
image of the device CPU texture (UIRenderAddImageNamed). Notices now render;
port.text_bar covers block split, pixels, colour, ClearBar and TipBoard clip.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:07:24 +09:00
shenleiandClaude Opus 5.5 c7bcb9bbbe port(EterLib): GrpMath/GrpColor/GrpColorInstance verbatim
port.grp_math pins the 40250 conventions: D3DXVec3Rotation applies the
inverse rotation, GetRotationFromMatrix returns negated Z*X*Y angles, and
CGraphicColor defaults to opaque white.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:59:44 +09:00
shenleiandClaude Opus 5.5 042bddf195 port(EterLib): Mutex/Thread/FileLoaderThread/GrpVertexBufferDynamic verbatim over Win32Crt kernel-object shims
Adds CreateSemaphore/ReleaseSemaphore/WaitForSingleObject/CloseHandle/
SetThreadPriority/_beginthreadex to Win32Crt; port.file_loader_thread covers
the shims, CThread and both the un-Created (40250 live) and Created loader.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:56:24 +09:00
shenleiandClaude Opus 5.5 e0cdcee2e6 port: EterBase/Debug.cpp log functions verbatim (log.txt, syserr.txt)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:49:20 +09:00
shenleiandClaude Opus 5.5 f9b1044a4a audit: EterBase CRC32/FileBase/MappedFile mapped, with port.utils checks
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:46:43 +09:00
shenleiandClaude Opus 5.5 290a331aef port: CPythonGraphic::Destroy; audit the last PythonGraphic units
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:44:41 +09:00
shenleiandClaude Opus 5.5 f96b339309 audit: EterBase/error.cpp N_A (Win32 SEH crash log)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:43:38 +09:00
shenleiandClaude Opus 5.5 bda85eea50 port: grp.SaveScreenShot via next-frame swapchain readback + JPEG
CPythonGraphic::SaveScreenShot queues a readback of the next presented
frame (ScreenShotHost -> VulkanWindow::request_frame); WriteScreenShot runs
the rest of 40250's function verbatim (X8R8G8B8 rows, SaveJPEG, EXIF tag).
jpeg_save is encoded with stb_image_write. SHGetSpecialFolderPath returns
$HOME/Documents (else cwd); CreateDirectory/_access/jpeg_save accept '\\'.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:43:03 +09:00
shenleiandClaude Opus 5.5 c21e012965 Port map: correct the WebPage/Logo/MovieMan evidence (scripts grepped with LC_ALL=C)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:32:49 +09:00
shenleiandClaude Opus 5.5 ff71726ff0 Port PythonExceptionSender and install it at boot as 40250 Main does
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:31:04 +09:00
shenleiandClaude Opus 5.5 3dfb09df92 Port map: mark the platform units the 40250 SINGAPORE build never reaches N_A
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:27:25 +09:00
shenleiandClaude Opus 5.5 549e12db7c Mark GrpDIB, GrpText, CullingManager and FileLoader PORTED; test the text file loader
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:25:28 +09:00
shenleiandClaude Opus 5.5 3c2ef81536 SphereLib: mark the verbatim sphere tree PORTED with a query test
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:24:24 +09:00
shenleiandClaude Opus 5.5 ed61b2d20f SpeedTree: read the .spt collision and composite texcoord blocks
The CSpeedTreeRT stand-in now returns the collision objects stored in
the .spt (12000 section: spheres and cylinders) instead of one fixed trunk
cylinder, and takes leaf texture rects from the 10000 section instead of
hand-picked atlas rects (trees without leaf maps use the frond rect).
SpeedGrass/BoundaryShapeManager are N_A (no 40250 caller).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:20:34 +09:00
shenleiandClaude Opus 5.5 17cb7326c1 docs: PORT-PLAN MilesLib done, platform 61.2%
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:07:51 +09:00
shenleiandClaude Opus 5.5 11991d4d1f MilesLib: run the 40250 sound sources verbatim over an AIL software mixer
Copy SoundBase/SoundData/SoundInstance*/SoundManager*/Type from 40250 and
implement the AIL_* calls they make in MilesAil.cpp (2D pan, 3D distance and
listener pan, threaded stream decode, loop counts). The SDL host drains the
mixer. CSoundManager is created/updated/destroyed where 40250 does it and the
old AudioCommands bridge is removed. Port-map MilesLib 142/142 PORTED.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:07:37 +09:00
shenleiandClaude Opus 5.5 d509f0a8b4 PORT-PLAN §4: performance batch 2 status
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 11:43:00 +09:00
shenleiandClaude Opus 5.5 e4331bca3e gr2: binary-search the curve knot (upper_bound) when knots are ascending
Curve::eval scanned every knot to find the first one past t; long animation
tracks made that the top of CPythonCharacterManager::Deform. Knots are checked
for ascending order at load and unsorted curves keep the linear scan, so the
chosen knot is unchanged. Desktop live game: Deform samples 93 -> 58.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 11:42:31 +09:00
shenleiandClaude Opus 5.5 6bfcac7d68 RecordingDevice: lend cached geometry instead of copying it per draw
A geometry-cache hit moved every vertex vector out of the cache into the draw
(deep copy of positions/normals/uv/diffuse/indices/bones each frame). The cache
now lends its vectors to the frame's first draw of that geometry and takes them
back in Render3DBeginFrame; later draws of the same key+revision in the frame
(terrain splat layers, shadow-map pass) are marked shared_geometry and carry no
vectors -- the native host looks the GPU geometry up by key+revision, and draw
captures expand them (Render3DExpandSharedGeometry). Index reads reuse a scratch
buffer. Desktop live game: RenderGame rnd 1.7 -> 1.2 ms, no visual change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 11:39:01 +09:00
shenleiandClaude Opus 5.5 44a020f01e native renderer: game world at MT_RENDER_SCALE (0.75 on Android), MSAA default 2
Draws recorded inside CPythonApplication::RenderGame are marked Render3DDraw::scene and
drawn by a scene pass compatible with pass_ into a reduced-resolution image, composited
where RenderGame drew; the UI stays full resolution. --render-scale / MT_RENDER_SCALE,
desktop default 1.0 (unchanged path).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 11:28:05 +09:00
shenleiandClaude Opus 5.5 b7c215ee42 zh locale: translate all 40250 itemdesc descriptions, wrapped for the tooltip
itemdesc_translate_zh.tsv maps the English description/summary text to Chinese (1,788 entries,
every itemdesc row covered). build_zh_locale.py replaces the cells and wraps Chinese into
26-byte lines joined by ' |', which 40250's Western SplitDescription turns into forced line
breaks; the 50307 overlay row is wrapped the same way.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 11:17:21 +09:00
shenleiandClaude Opus 5.5 3fcb27dd4d Server: hunt set once per character, rebuild.sh for patch build/deploy/rollback
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 11:01:36 +09:00
shenleiandClaude Opus 5.5 d163aab949 hunt-set: 小狩猎套装礼包 is free in the item mall
CShopEx::Buy rejected price 0 as a hack; allow it like CShop::Buy already does.
Rebuilt and deployed game on 203; buying the box for 0 verified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 10:30:46 +09:00
shenleiandClaude Opus 5.5 7155785167 Add 小狩猎套装礼包: level-1 +9 set with full attributes, sold in the item mall
Server (tools/server/hunt-set, deployed on 203): game patch adds quest function
item.set_attribute (CItem::SetForceAttribute); quest hunt_set turns the unused
ITEM_QUEST 50307 into a per-class box of eight +9 pieces with five max-value
attributes each. Item mall sells it for 2,000,000.

Client locale: name overlay plus whole-row overlays for item_list.txt (gift-box
icon) and itemdesc.txt (build_zh_locale.py ROW_FILES).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 10:23:33 +09:00
shenleiandClaude Opus 5.5 20b189a9da client: the player's own character walks through buildings and blocked cells
The server checks a move only for its distance and speed, so the local
character skips the background-object and map-attribute collision.
Other characters and doors still block it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 09:42:10 +09:00
shenleiandClaude Opus 5.5 34c6049199 zh locale: translate skill names and descriptions
skilldesc.txt takes Longju's name, description and condition columns
and its affect texts where their format arguments match 40250's; a
reviewed overlay fills the gaps and renames the empire languages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 08:56:03 +09:00
shenleiandClaude Opus 5.5 f8bbfc7fb3 server: support skills at max level on a character's first login
support_skills_max.quest sets 121/122/124/126-129/131 to their skill_proto
max, the horse to level 30 (skill 130) and the horse skills 137-139 (140 for
assassins), once per character. install.sh adds it to locale_list and
pc.set_skill_level to quest_functions (qc rejects it otherwise), then make.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 08:45:58 +09:00
shenleiandClaude Opus 5.5 42e4cf1a9f server: unlimited teleport ring 70058, sold in a two-page item mall
ring-warp/: ring_warp.quest without use count or cooldown (the ring is never
used up) + install.sh (GBK, make.py, item name 移动戒指).
npc-shops: [page] lines in items.tsv make an extended shop written to
shop_table_ex.txt; item-mall is now 增益 (29) + 道具 (12, incl. 70058 at 1 gold).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 08:18:56 +09:00
shenleiandClaude Opus 5.5 000d4841fd quest zh: translate the inline quest text (change_name, item_delete, manwoo, forked_road, ...)
128 literals written directly in the quest sources, outside gameforge.*;
build_zh_quest_inline.py patches them in GBK before make.py (qc) on the server.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 03:32:33 +09:00
shenleiandClaude Opus 5.5 808e711f74 quest zh: translate the remaining translate.lua strings (chunks 57-72: pony, heavens cave, reset scrolls, ride, skill groups, spider dungeon, subquests, grand master training, mount training, refine scrolls, warehouse, olympic badge)
All 8477 gameforge strings now have a Chinese row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 03:06:14 +09:00
shenleiandClaude Opus 5.5 5440045f1e quest zh: translate chunks 47-56 (map_warp, marriage, side quests lv7-lv80, npc_talk, oxevent, patrol, pets, pony)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:51:02 +09:00
shenleiandClaude Opus 5.5 2217205ad4 quest zh: translate chunks 41-46 (Dark Dragon Rock main quests lv84-lv98, map_warp)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 01:57:41 +09:00
shenleiandClaude Opus 5.5 2578e1b150 quest zh: translate chunks 37-40 (main quests lv40-lv84, blacksmith/fisherman)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 01:34:01 +09:00
shenleiandClaude Opus 5.5 ca7b47c4f0 quest zh: translate chunks 31-36 (stash, new year, flame main quest, early main quests)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 01:27:41 +09:00
shenleiandClaude Opus 5.5 85cd541560 quest zh: translate chunks 25-30 (old pirate, questscroll, quiz, skill groups); keep [TAG] whole when wrapping
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 01:19:29 +09:00
shenleiandClaude Opus 5.5 69d214ba20 quest zh: translate chunks 11-24 of translate.lua (3056/8477 strings)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 01:11:06 +09:00
shenleiandClaude Opus 5.5 c5ace7b848 quest zh: translate chunks 5-10 (1425 of 8477 strings)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 01:00:41 +09:00
shenleiandClaude Opus 5.5 f4995b9a73 zh quest text: biologist and Seon-Pyeong quests, couple ring, catacomb entry
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:53:19 +09:00
shenleiandClaude Opus 5.5 671155eecc zh quests: translate.lua builder + first 100 quest strings
40250 quests say gameforge.<quest>.<key>, loaded by game from
share/locale/<locale>/translate.lua at start. build_zh_translate_lua.py
lays the reviewed data/zh_40250/quest_translate_zh.tsv over the English
file line by line (nested tables kept), re-wraps at the quest window
width, and writes GBK with 0x5C trail bytes doubled. Deployed on 203;
blacksmith dialog shows Chinese.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:46:52 +09:00
shenleiandClaude Opus 5.5 3ae77c3530 zh locale: take ui/windows images from Longju
The character window's tabs and stat labels (VIT/INT/Character Status,
Status/Abilities/...) are baked into locale/<xx>/ui/windows/windows.dds;
the zh build only overlaid text keys, so they stayed English. The folder
is now replaced as a whole (its .sub files index its own atlas).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:38:37 +09:00
shenleiandClaude Opus 5.5 54fa2c0fc3 npc-shops: generic NPC shop installer + mount shop 15 on NPC 20368
tools/server/item-mall-shop becomes tools/server/npc-shops with one
directory per shop (shop.conf + items.tsv) and install.sh <shop dir>.
New mount shop: 35 ride tickets on NPC 20368 (renamed 坐骑商人 via
NPC_NAME -> mob_names.txt) beside the stable boy in a1/b1/c1. Verified
on 203: 35 slots at the drafted prices, bought + used 71114 -> mounted.
zh overlay: 71118 虎坐骑券(黄), 20368 坐骑商人.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:38:37 +09:00
shenleiandClaude Opus 5.5 4bfc4244bd 商城按钮改为提示去找百店老板娘
203 没有网页商城,端口也没有网页窗口,系统菜单的商城按钮打开的是空窗口。
新 PORT 模块 mt_mallhint 替换 SystemDialog 的商城按钮和 GameWindow 的 mall 命令处理,
弹出提示框(并在聊天栏提示):商城物品请到各村杂货店旁的百店老板娘处购买。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:17:28 +09:00
shenleiandClaude Opus 5.5 cc18db5dd1 商城 NPC 商店:9010 百店老板娘在三个村卖商城物品(服务端安装脚本)
203 没有网页商城,系统菜单的商城窗口是空的。把 40 件商城物品放进商店 14,
挂在 a1/b1/c1 杂货店旁的 NPC 9010 上,按 item_proto gold 金币出售(红龙/蓝龙 1 金币)。
9010 的 mob_proto on_click 原为 2(无处理),改为 1(ON_CLICK_SHOP)才能打开商店。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:37:15 +09:00
shenleiandClaude Opus 5.5 71d8f8c6e7 移动端界面大小设置:默认 600 逻辑高,系统选项可选 600/700/800
Android 上 40250 界面原先固定按 800 逻辑像素高排版,弹窗文字在手机上只有约 1 mm 高。
- UIScaleMode.h + host ui_scale.cpp:逻辑高度来自保存的设置(默认 600),ui_height.cfg 保存,下次启动生效;
  桌面可用 MT_UI_HEIGHT 测试
- app.GetUIHeight/GetAppliedUIHeight/SetUIHeight
- mt_uiscale PORT 模块:系统选项对话框加高一行,"界面大小 大/中/小",修改后聊天提示重启生效

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:10:51 +09:00
shenleiandClaude Opus 5.5 e33e41c12b 背包扩展到 5 页:服务端补丁 + DB 迁移 + 客户端 mt_inventory
- GameType.h: c_Inventory_Page_Count 2 -> 5; SQuickSlot.Position BYTE -> WORD
- quickslot 包/接口 pos 改为 WORD(CG/GC 5 字节),wire_classic 同步
- mt_inventory PORT 模块:inventorywindow.py 装备格 90 -> EQUIPMENT_SLOT_START 重映射、5 个小页签、
  自动药水高亮与 SelectItemWindow 扫描全部 5 页;40250 脚本保持不变
- tools/server/inventory-5-pages: server.patch(格子布局 +135、quickslot WORD)、migrate_db.py、README

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:37:44 +09:00
shenleiandClaude Opus 5.5 22d534c5eb Split vulkan_window.cpp by responsibility and render() into phases
VulkanWindow's 3000-line TU becomes sdl_window.cpp (window, events,
cursor, screenshot BMP), vk_device.cpp (device, swapchain, MSAA,
framebuffers), vk_pipelines.cpp (render passes, pipelines),
vk_resources.cpp (buffers, render targets, geometry), vk_textures.cpp
(textures, samplers, descriptors), vk_frame.cpp (render) and
ui_batches.cpp; vulkan_window.cpp keeps construction and timing stats.
Function bodies move verbatim.

render() now reads fence/acquire -> prepare_draws -> prepare_ui ->
write_draw_states -> record_passes -> record_readbacks -> submit ->
finish_readbacks -> present, with FrameDraws / Readback carrying the
locals that used to live across 500 lines.

Verified: login-screen screenshot byte-identical to HEAD; game-world
draw/vertex/index/UI counts identical; ctest, port_gate macos+android,
Android build pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:54:36 +09:00
shenleiandClaude Opus 5.5 eab5938072 host: cross-platform audio decode (Android has sound)
Replace the macOS-only AudioToolbox decoder with mt_host::decode_audio: a
RIFF/WAVE PCM parser plus vendored dr_mp3, resampled/remixed to 44.1 kHz
stereo float with SDL_ConvertAudioSamples. macOS and Android now share one
path; the AudioToolbox link is gone.

BGM is no longer cached in clips_ (a 5-minute track is ~100 MB of float):
only the playing track is kept, and a new one decodes on a worker thread
(the pack read stays on the main thread) so map changes do not stall.

host.audio_decode test: synthetic wav layouts + all 1578 pack .wav, 9 pack
.mp3 and 25 Client/BGM .mp3 decode (7060 s of audio in ~3.6 s on M2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:11 +09:00
shenleiandClaude Opus 5.5 75d2dd8545 host: split src/host/main.cpp into translation units
main.cpp (4.5k lines) -> main.cpp (entry, args, synthetic benchmark) plus
vulkan_window, live_client, frame_policy, native_audio, texture_decode,
render_state, input_keymap, host_util. Bodies are moved verbatim; multi-line
VulkanWindow / NativeAudioEngine / FrameRatePolicy members are defined out of
line; one-line accessors stay inline. Anonymous namespace -> mt_host.

No behavior change: ctest 15/15, port_gate macos+android PASS, desktop
--live-client login screen and synthetic --draws runs unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 19:30:44 +09:00
shenleiandClaude Opus 5.5 a46093104c layout: restructure into src/ tests/ android/ scripts/ tools/
- extension/src/{port,platform,codepage} -> src/; native_render -> src/host
  (+ dxt, shaders/); libgr2 -> src/gr2; extension/third_party -> third_party
- extension/tests -> tests/port, libgr2/tests -> tests/gr2
- android-native -> android (build.sh, push-client.sh moved in)
- script -> scripts; tools/40250 -> tools/server; oracle -> tools/granny-oracle;
  perf tools -> tools/perf
- all build trees under build/ (native, release, android, port-gate)
- xrender:: CMake aliases -> mt::; port-map ledger impl paths rewritten

No code changes. ctest 15/15, port_gate macos+android PASS, port_map check 0 errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 19:08:19 +09:00
shenleiandClaude Opus 5.5 70710477cf cleanup: remove Godot-era test data, formats/, dead proto reader and duplicates
- test/: bgfx/Godot render goldens and compare shots nothing reads any more;
  the Granny oracle result m2-numeric.json moves to oracle/
- formats/: only the .spt sniffer was still linked; it moves into
  platform/SpeedTreeLib, the rest and tools/map_probe go
- bgm/ duplicated Client/BGM byte for byte; tools/root archived root scripts
  that root.epk already holds; extension/src/proto had no build reference
- GEMINI.md duplicated AGENTS.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 18:43:19 +09:00
shenleiandClaude Opus 5.5 0137f852d3 docs: rewrite PORT-PLAN for the native SDL3 architecture
Godot-era batch records move verbatim to docs/archive/PORT-HISTORY.md.
README and THIRD-PARTY no longer mention submodules.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 18:26:54 +09:00
shenleiandClaude Opus 5.5 f970f95800 cleanup: drop Godot-era build trees, m2dev net/pack layers and stale docs
- Untrack build-debug/ and build-asan/ (CMake trees committed by mistake in
  c9389431) and ignore them.
- Remove extension/src/net and extension/src/pack (m2dev protocol and XChaCha
  pack format, superseded by the ported 40250 code), their 18 unregistered tests
  and the net/pack tools, the MT_BUILD_NET_TOOLS probe, and the libsodium and zstd
  submodules they alone used.
- The fake login server's classic cipher, sequence table and wire layouts move to
  extension/tests/classic/ (still used by port.login_flow, port.packet and the
  native client's offline mode).
- Archive Godot/m2dev-era plans under docs/archive/; THIRD-PARTY.md updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 18:17:25 +09:00
shenleiandClaude Opus 5.5 82503315c6 native: frame-rate setting, idle frame rate and battery power telemetry
- MtFrameRate setting (30 / 60 default / display max) as app.Get/SetFrameRateMode,
  with a "画面帧率" row injected into the system option dialog (mt_framerate); saved
  in the SDL pref path.
- FrameRatePolicy in the live loop: 30 fps after 15 s without input (not while auto
  hunting), display switched to 60 Hz unless the highest mode, ADPF
  setPreferPowerEfficiency, vsync pacing when the display already runs at the target.
  --fps-mode / --idle-fps / --idle-after; --fps-cap / --refresh-rate still pin a test run.
- Perf log: battery current/voltage/power, plugged, fps_mode, idle columns;
  perf_summary groups power by mode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 18:14:19 +09:00
shenleiandClaude Opus 5.5 c2cc093ed0 native: perf telemetry, 2 frames in flight, 120 Hz pacing, GPU shadow map
- --perf-log CSV + logcat telemetry (perf_log.h, EterBase/PerfCounters.h),
  incl. display refresh rate / app vsync rate, thermal, CPU clocks;
  tools/pull_perf_logs.sh + tools/perf_summary.py
- Vulkan renderer: two frames in flight, in-frame texture uploads (no
  vkQueueWaitIdle), --fps-cap / --refresh-rate / --frames-in-flight
- Android: ANativeWindow_setFrameRate, ADPF performance hint,
  appCategory=game (ColorOS no longer drops to 60 Hz when idle)
- Character shadow map rendered on the GPU into an offscreen render target
  instead of CPU rasterization + per-frame 1 MB upload; --cpu-shadow keeps
  the old path. Device (120 Hz, 32 mobs): 75 -> ~115 fps, script thread
  8.9 -> 3.4 ms. draw_capture format v10.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 17:59:23 +09:00
shenleiandClaude Opus 5.5 3e3708ef06 android-native: auto hunt, in-client account registration, mobile UI polish
- Auto hunt (client-only): PythonPlayerAutoHunt.cpp + AutoHuntScript.inc as the
  embedded mt_autohunt module, AUTO touch button, F9/F8.
- Account registration: tools/40250/register_server.py (rc.d mt_register, :11080)
  inserts into account.account; net.RegisterAccount/GetRegisterAccountResult
  (PythonAccountRegister.cpp) and the mt_register login-window dialog
  (RegisterScript.inc).
- --py-exec also runs in --login-screen mode for scripted login-screen tests.
- Touch controller, window manager and render command updates for the
  Android native client.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 16:15:04 +09:00
shenleiandClaude Opus 5.5 53d06c3c26 android-native: real-server login by default, readable CJK text, 16 KB pages
- FreeType: add the cff/psaux/pshinter modules (from the pinned 2.13.3
  tarball, same sha256). Android's only CJK font is the CFF2
  NotoSansCJK-Regular.ttc, which the TrueType-only build could not open,
  so every Chinese glyph drew as a box.
- Font oversample rounds the UI density up: Android's 1760x800 UI on a
  2376x1080 screen is 1.35, which rounded to 1x bilevel glyphs stretched
  1.35x. Now 2x anti-aliased glyphs are scaled down. macOS 2.0 unchanged.
- MainActivity: a launcher start (no intent args) opens the login screen
  against 192.168.21.203 instead of auto-logging into the in-process fake
  server; explicit args still select the fake-server smoke flow.
- build-android-native.sh: ANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON for SDL3
  and libmain (LOAD alignment 0x1000 -> 0x4000), with a stamp that
  rebuilds a cached pre-flag SDL3. Clears Android's 16 KB compat warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 12:16:38 +09:00
shenleiandClaude Opus 5.5 a1ae69aa7a zh locale: pack locale_zh and add reviewed Chinese names
eterpack_pack writes locale packs in the original format (COMPRESS
entries, LZO+TEA index), and build_zh_locale.py packs locale/zh into
locale_zh.eix/.epk registered in pack/Index instead of leaving loose
files.

The reviewed translations for names and keys still in English are
kept apart from the server snapshot in data/zh_40250/*_zh_overlay.txt
(1,607 items, 231 mobs/NPCs, 45 locale_game keys) and override it at
build time. Only YMIR, the coordinate-named warp markers and the empty
TOOLTIP_UNSEAL_LEFT_TIME remain English.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 18:45:58 +09:00
shenleiandClaude Opus 5.5 fd051cc3ed android-native: SDL3 APK build for the native client
build-android-native.sh downloads SDL 3.4.16 (sha256-checked), builds
libSDL3.so and libmain.so (native_render + port_platform + embedded
Python) at API 24, and wraps them in the SDLActivity shell under
android-native/ (package org.metin2port.client). push-android-client.sh
copies the 40250 Client directory into the app's files/ with run-as
(--locale XX selects locale_XX.cfg). port_logic links with
--no-dependent-libraries on ELF targets so the verbatim
`#pragma comment(lib, ...)` lines do not break lld.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 18:45:58 +09:00
shenleiandClaude Opus 5.5 0b701d88c3 codepage: replace iconv with bundled WindowsBestFit tables
mt_codepage implements code pages 874/932/936/949/950/1250-1258 from
Microsoft's bestfit<cp>.txt sources (script/gen_codepage_tables.py,
SHA-256 pinned). Win32Crt's MultiByteToWideChar/WideCharToMultiByte/
IsDBCSLeadByteEx and net/text_codec use it, so the Android API 24 build
no longer depends on iconv. port.codepage checks every table against
its source file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 18:45:49 +09:00
shenleiandClaude Opus 5.5 07c101fdc8 Merge native HiDPI rendering and shop item layout fix
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 16:56:52 +09:00
shenleiandClaude Opus 5.5 52ccb80d01 native_render: HiDPI glyph pages, sharp UI upscaling, 4x MSAA
- CGraphicFontTexture rasterises glyph pages at the swapchain density
  (UISetFontOversample, MT_FONT_OVERSAMPLE) with anti-aliased coverage;
  metrics, packing and UVs stay the 40250 1x values. Default 1 keeps the
  verbatim bilevel path (Godot unchanged).
- native.frag: sharp-bilinear sampling for magnified UI textures.
- Multisampled colour/depth with a resolve into the swapchain (MT_MSAA,
  default 4); stats line reports msaa=N.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 16:56:36 +09:00
shenleiandClaude Opus 5.5 22ca5da387 UserInterface: 32-bit LONG sockets in TItemData/TShopItemData
The 40250 wire structs hold Win32 long (4 bytes) sockets; on LP64 `long`
is 8, so each TShopItemData was too wide and SHOP_SUBHEADER_GC_START/_EX
misread every item after the first. Pin the wire size with a static_assert.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 16:56:36 +09:00
shenleiandClaude Opus 5.5 b776fd071f gitignore: ignore the build-native/ CMake tree
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 14:56:58 +09:00
shenleiandClaude Opus 5.5 9c6e3d6d9e render parity: close SpeedTree .spt 0x4E25 follow-up (billboard rect, not leaf texcoords)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 14:33:22 +09:00
shenleiandClaude Opus 5.5 d2356d59c3 render parity unit K: 40250 DDS mip levels
DXT DDS textures upload the file's own mip levels like 40250
CGraphicImageTexture::CreateDDSTexture (max(1, dwMipMapCount), level i read
at sum(dwLinearSize>>2k), Copy of dwLinearSize>>2i bytes) instead of a
regenerated chain. Non-DDS images keep the D3DX_DEFAULT full chain and mem:
textures get one level. The invented is_ui_tex no-mip rule (icon/, ui/,
locale/, <=128px) is deleted. dxt_decode_test is registered in ctest with
mip-level cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 14:29:30 +09:00
shenleiandClaude Opus 5.5 dda885a17a render parity unit J: 40250 automatic sight range in CPythonApplication::Process
Process now runs 40250's render-time / face-count block and sets view
distance set 0 each frame (25600 under 5000 faces, else scaled by render
time, or the forced range). SetForceSightRange and SkipRenderBuffering are
ported from stubs; the invented SetCursorPosition in UpdateGame is removed.
Port-map boilerplate notes replaced; Destroy recorded as DIVERGENT.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 14:22:41 +09:00
shenleiandClaude Opus 5.5 0e8a1574cb render parity unit I: 40250 PythonGraphic SetGamma, cooldown fan, up/down buttons
SetGamma, RenderCoolTimeBox, RenderUp/DownButton and GetAvailableMemory are
transliterated from 40250 in place of stubs. The cooldown fan is emitted as
untextured polygon UI commands (native_render + python_ui_surface.gd draw
Bar+quad as a polygon); D3D8 shim gains SetGammaRamp/D3DGAMMARAMP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 14:17:27 +09:00
shenleiandClaude Opus 5.5 d3fd5f8613 test: login_flow waits a fixed frame count between mouse move and click
The 0.1 s wall-clock waits could fit a single frame under ctest -j3, so the
shopkeeper pick missed about one run in four.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 14:17:26 +09:00
shenleiandClaude Opus 5.5 3e270dccc1 render parity unit H2: verbatim 40250 water
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 14:03:12 +09:00
shenleiandClaude Opus 5.5 6dffd1572a render parity unit H1: verbatim 40250 HTP terrain
MapOutdoorRenderHTP.cpp is the full 40250 source behind the native-terrain
gate: no invented texture-0 fallback, first-splat stage-1 ALPHAOP DISABLE,
GetNumTextures() bound, 40250 shadow-pass states (FOGCOLOR white, CLAMP,
TEXTURE1 m_matDynamicShadow). Fixes the white far-terrain band.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 13:57:55 +09:00
shenleiandClaude Opus 5.5 863f3771af render parity unit G: 40250 tiling selection + verbatim STP terrain
- PythonApplication::Create mirrors 40250 :1196-1251 (SOFTWARE_TILING cfg,
  auto tiling IsFastTNL ? HTP : STP, MinLOD on !IsFastTNL)
- RecordingDevice caps: VertexShaderVersion 1.1 + CLIPTLVERTS (fast T&L -> HTP)
- MapOutdoorRenderSTP.cpp replaced by the full 40250 source (native gate only)
- native_render XYZRHW: fix inverted screen->NDC Y, negative rhw clip,
  no texture transform on TL vertices, specular-alpha vertex fog (capture v9)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 13:54:11 +09:00
shenleiandClaude Opus 5.5 91ce13c3cf EterLib: port GrpMarkInstance.cpp verbatim
Replace the platform_stub skeleton (every member unimplemented) with the 40250 source, so
guild marks in text tails and mark boxes load and draw.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 13:34:03 +09:00
shenleiandClaude Opus 5.5 d817bd7cab SpeedTreeLib: port 40250 wrapper/forest verbatim over a CSpeedTreeRT stand-in
Delete the platform proxy tree renderer and copy SpeedTreeWrapper, SpeedTreeForest,
SpeedTreeForestDirectX8, SpeedTreeConfig.h and VertexShaders.h from 40250. The SDK
SpeedTreeRT.h public API becomes the shim; the closed CSpeedTreeRT is reimplemented in
platform/SpeedTreeLib/SpeedTreeRT.cpp (procedural geometry, static lighting, single LOD,
DIVERGENT). Shims gain the D3D8 vertex shader declaration tokens, D3D_OK,
CreateVertexShader/DeleteVertexShader, ID3DXBuffer/D3DXAssembleShader, MessageBox and
__min/__max.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 13:31:57 +09:00