inada-s / gdxsv

Mobile Suit Gundam: Federation vs. Zeon&DX Private Game Server
https://www.gdxsv.net
GNU Affero General Public License v3.0
23 stars 7 forks source link

Go Into NetworkMode (ps2) #1

Closed inada-s closed 4 years ago

inada-s commented 4 years ago

Probably this is the most difficult phase of creating GDX server.

There is a talk of making a Dreamcast version of the game server, but there are a lot of debug symbols left in the PS2 version of the game, so I plan to develop a server based on the PS2 version.

I believe the Dreamcast and PS2 versions to be served on almost the same game server.

inada-s commented 4 years ago

通信対戦メニューの関数テーブル 003c4f50

image

inada-s commented 4 years ago

シーンID? 06 00 で通信対戦メニューへジャンプ 008710D0 image

inada-s commented 4 years ago
003C4F50

接続ボタン押した後
network_connect => modem_connect から関数テーブルをjalr
00359720 dialing10
00359370 dialing10_00
003595A0 dialing10_01
00359600 dialing10_02 (TCP, PPP初期化)

これらの関数を書き換えれば通信できそうである。

image

アプローチとしては2つあって、ps2devを使ってirxライブラリを作り、ライブラリの関数を呼び出すように書き換える。 もう一つは、pcsx2を自前ビルドして、これらの関数の呼び出しをフックして、自作のコードを呼び出す。

ps2devのほうが将来的に実機で遊べるようにするためには良いだろうが、pcsx2からアプローチしたほうがデバッグしやすそう。

gh0stl1ne commented 4 years ago

This means Gundam DX (PS2) is a modem-only game?

I never tried to modify a game to use the broadband adapter instead of the modem. Interesting task!

Online revival will be easy, it's plain KDDI:

void Send_LineCheck(void)

{
  SetSendCommand((message *)&send_work,0x6001);
  SetSendCategory((message *)&send_work,2);
  SetSendCommandLen((message *)&send_work);
  Write_Socket((message *)&send_work);
  return;
}
inada-s commented 4 years ago

This means Gundam DX (PS2) is a modem-only game?

YES. When the game released, only Multi-Matching (Not Multi Matching BB) was on service.

I never tried to modify a game to use the broadband adapter instead of the modem.

This task is the first step. I'm going to modify pcsx2 codes so that it can enter online mode to get started with server development.

inada-s commented 4 years ago

replace modem_recognition button into network_battle button

cpu->write32(0x003c4f58, 0x0015f110);

skip ppp step

cpu->write32(0x0035a660, 0x24030002);

dns lookup phase have something tricky..

my dirty work is here. https://github.com/inada-s/pcsx2

inada-s commented 4 years ago

Note: Ave_XXX functions

Ave_SifCallRpc is a function to communicate AVE_TCP library. other Ave_XXX functions are wrapper of Ave_SifCallRpc.

https://www.retroreversing.com/playStation-2-architecture#example-of-sif-in-action

An example of using the SIF to communicate between both processors is the controller pad libraries. We want to communicate between libpad.a which runs on the Emotion Engine and padman.irx which runs on the I/O Processor. So during the VBlank period the IOP Padman.irx uses SIFDMA to send controller information (such as which buttons are pressed) to the Emotion Engine. The Emotion Engine can then request this information by calling the API scePadRead

If needed to modify the game to make good use of Ethernet adapter,

  1. investigate how AVE_TCP functions are used in MonsterHunter and impl them as patches.
  2. develop a new iop library using ps2dev to replace AVE_TCP library.

Either way, both seem to be difficult.

inada-s commented 4 years ago

hand-decompiled TcpGetStatus

void TcpGetStatus(a0, a1) {
    // stack size = 0x0010
    sp[0] = s0
    sp[1] = ra

    s0 = a1
    // dsll32: Doubleword Shift Left Logical Plus 32
    a0 = a1 << (16+32)
    a2 = s0 + 2
    a3 = s0 + 4

    // dsra32       a0, a0, 16
    a0 = a0 >> (16+32)

    v0 = Ave_TcpStat(a0, a1, a2, a3) // Ave_TcpStat is `select(2)` like function

    v0 <<= (16+32)
    v0 >>= (16+32)

    if (0 <= v0) { // bgez 00381eac
        v1 = s0[0]
        if (v1 < 11) {
            v1 >>= 2
            switch (v1 + a0) {
                case 0: s0[0]=0 break
                case 1: v1=1, s0[0]=v1 break
                case 2: v1=2, s0[0]=v1 break
                case 3: v1=3, s0[0]=v1 break
                case 4: v1=4, s0[0]=v1 break
                case 5: v1=5, s0[0]=v1 break
                case 6: v1=6, s0[0]=v1 break
                case 7: v1=7, s0[0]=v1 break
                case 8: v1=8, s0[0]=v1 break
                case 9: v1=9, s0[0]=v1 break
                case 10:v1=10,s0[0]=v1 break
            }
        } else {
            v1 = 7
            s0[0] = v1
        }
    }
    ra = sp[1]
    s0 = sp[0]
}

// connect_ps2_check
void connect_ps2_check(a0) {
    // stack size = 0x0020
    ra = sp[0]
    a1 = sp + 0x0018
    v0 = TcpGetStatus(a0, a1)
    if (0 <= v0) {
        v0 = sp[0x0018]
        v0 ^= 4
        v0 = 0 < v0
        v0 ^= 1
    } else {
        v0 = -1
    }
    ra = sp[0]
}

tcp_init() {
...

    a0 = gp[-0x652C] # sock
    connect_ps2_check(a0)

}
inada-s commented 4 years ago

I modified the pcsx2 code to set breakpoints on functions likely to be involved in network, and to call C ++ callbacks when passing through those functions. In the callbacks, skip the ppp process and bypass tcp's Open / Read / Write to winsock's.

inada-s commented 4 years ago

A little progress :) image image

inada-s commented 4 years ago

next task is https://github.com/inada-s/gdxsv/issues/3

gh0stl1ne commented 4 years ago

You're super fast. I'm still in the process of getting the game. Not an easy task these days.