├── .editorconfig ├── .github └── workflows │ └── compilation.yml ├── .gitignore ├── Makefile ├── Makefile.mingw32 ├── README.md ├── doc ├── license.txt ├── ps2link-protocol.txt ├── ps2netfs-protocol.txt ├── readme-mingw32.txt ├── readme.txt └── todo.txt └── src ├── fsclient.c ├── fsclient.h ├── network.c ├── network.h ├── ps2client.c ├── ps2link.c ├── ps2link.h ├── ps2netfs.c ├── ps2netfs.h ├── utility.c └── utility.h /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig: http://EditorConfig.org 2 | 3 | # Top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | charset = utf-8 12 | 13 | # 1 space indentation 14 | [*.{c,h,js,css,html}] 15 | indent_style = space 16 | indent_size = 1 17 | 18 | # Tab indentation 19 | [Makefile*] 20 | indent_style = tab 21 | -------------------------------------------------------------------------------- /.github/workflows/compilation.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | build: 9 | runs-on: ${{ matrix.os[0] }} 10 | strategy: 11 | matrix: 12 | os: [ 13 | [macos-latest, arm64], 14 | [macos-13, x86_64], 15 | [ubuntu-latest, x86_64] 16 | ] 17 | 18 | steps: 19 | - uses: actions/checkout@v4 20 | 21 | - name: Compile native versions 22 | run: | 23 | make --debug 24 | 25 | - name: Get short SHA 26 | id: slug 27 | run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)" 28 | 29 | - name: Create tar archive (keep executable bit) 30 | run: tar -zcvf ps2client-${{ steps.slug.outputs.sha8 }}-${{ matrix.os[0] }}-${{ matrix.os[1] }}.tar.gz bin 31 | 32 | - uses: actions/upload-artifact@v4 33 | with: 34 | name: ps2client-${{ steps.slug.outputs.sha8 }}-${{ matrix.os[0] }}-${{ matrix.os[1] }} 35 | path: | 36 | *tar.gz 37 | 38 | build-win: 39 | runs-on: ubuntu-latest 40 | container: dockcross/windows-static-x86:latest 41 | 42 | steps: 43 | - uses: actions/checkout@v4 44 | 45 | - name: Compile windows version with cross-compilator 46 | run: | 47 | make -f Makefile.mingw32 --trace 48 | 49 | - name: Get short SHA 50 | id: slug 51 | run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)" 52 | 53 | - name: Create tar archive 54 | run: tar -zcvf ps2client-${{ steps.slug.outputs.sha8 }}-windows-latest-x86_64.tar.gz bin 55 | 56 | - uses: actions/upload-artifact@v4 57 | with: 58 | name: ps2client-${{ steps.slug.outputs.sha8 }}-windows-latest-x86_64 59 | path: | 60 | *tar.gz 61 | 62 | release: 63 | needs: [build, build-win] 64 | runs-on: ubuntu-latest 65 | if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/master' 66 | steps: 67 | - uses: actions/checkout@v4 68 | 69 | - name: Get short SHA 70 | id: slug 71 | run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)" 72 | 73 | - name: Download Mac x86_64 artifact 74 | uses: actions/download-artifact@v4 75 | with: 76 | name: ps2client-${{ steps.slug.outputs.sha8 }}-macos-13-x86_64 77 | 78 | - name: Download Mac arm64 artifact 79 | uses: actions/download-artifact@v4 80 | with: 81 | name: ps2client-${{ steps.slug.outputs.sha8 }}-macos-latest-arm64 82 | 83 | - name: Download Ubuntu artifact 84 | uses: actions/download-artifact@v4 85 | with: 86 | name: ps2client-${{ steps.slug.outputs.sha8 }}-ubuntu-latest-x86_64 87 | 88 | - name: Download Windows artifact 89 | uses: actions/download-artifact@v4 90 | with: 91 | name: ps2client-${{ steps.slug.outputs.sha8 }}-windows-latest-x86_64 92 | 93 | - name: Create pre-release 94 | if: github.ref == 'refs/heads/master' 95 | uses: marvinpinto/action-automatic-releases@latest 96 | with: 97 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 98 | prerelease: true 99 | automatic_release_tag: "latest" 100 | title: "Development build" 101 | files: | 102 | *tar.gz 103 | 104 | - name: Create Tagged Release Draft 105 | if: startsWith(github.ref, 'refs/tags/v') 106 | uses: marvinpinto/action-automatic-releases@latest 107 | with: 108 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 109 | prerelease: false 110 | draft: true 111 | files: | 112 | *tar.gz 113 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | obj/ 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DEBUG = 0 2 | 3 | ifndef CC 4 | CC = gcc 5 | endif 6 | 7 | CFLAGS = -std=gnu99 -Wall -pedantic -I/usr/include -I/usr/local/include 8 | 9 | ifeq ($(DEBUG), 1) 10 | CFLAGS += -O0 -g 11 | else 12 | CFLAGS += -O2 13 | endif 14 | 15 | ifneq "MINGW" "$(findstring MINGW,$(MSYSTEM))" 16 | LIBS = -lpthread 17 | else 18 | LIBS = -lwsock32 19 | endif 20 | 21 | ifeq "x$(PREFIX)" "x" 22 | PREFIX = $(PS2DEV) 23 | endif 24 | 25 | ifeq "MINGW" "$(findstring MINGW,$(MSYSTEM))" 26 | all: 27 | $(MAKE) -f Makefile.mingw32 all 28 | 29 | clean: 30 | $(MAKE) -f Makefile.mingw32 clean 31 | else 32 | all: bin/fsclient bin/ps2client 33 | 34 | clean: 35 | rm -f obj/*.o bin/*client* 36 | endif 37 | 38 | install: bin/fsclient bin/ps2client 39 | strip bin/*client* 40 | @mkdir -p $(DESTDIR)$(PREFIX)/bin 41 | cp bin/*client* $(DESTDIR)$(PREFIX)/bin 42 | 43 | #################### 44 | ## CLIENT MODULES ## 45 | #################### 46 | 47 | OFILES += obj/network.o 48 | obj/network.o: src/network.c src/network.h 49 | @mkdir -p obj 50 | $(CC) $(CFLAGS) -c src/network.c -o obj/network.o 51 | 52 | OFILES += obj/ps2link.o 53 | obj/ps2link.o: src/ps2link.c src/ps2link.h 54 | @mkdir -p obj 55 | $(CC) $(CFLAGS) -c src/ps2link.c -o obj/ps2link.o 56 | 57 | OFILES += obj/ps2netfs.o 58 | obj/ps2netfs.o: src/ps2netfs.c src/ps2netfs.h 59 | @mkdir -p obj 60 | $(CC) $(CFLAGS) -c src/ps2netfs.c -o obj/ps2netfs.o 61 | 62 | OFILES += obj/utility.o 63 | obj/utility.o: src/utility.c src/utility.h 64 | @mkdir -p obj 65 | $(CC) $(CFLAGS) -c src/utility.c -o obj/utility.o 66 | 67 | ##################### 68 | ## CLIENT PROGRAMS ## 69 | ##################### 70 | 71 | bin/fsclient: $(OFILES) src/fsclient.c 72 | @mkdir -p bin 73 | $(CC) $(CFLAGS) $(OFILES) src/fsclient.c -o bin/fsclient $(LIBS) 74 | 75 | bin/ps2client: $(OFILES) src/ps2client.c 76 | @mkdir -p bin 77 | $(CC) $(CFLAGS) $(OFILES) src/ps2client.c -o bin/ps2client $(LIBS) 78 | -------------------------------------------------------------------------------- /Makefile.mingw32: -------------------------------------------------------------------------------- 1 | 2 | #CC = i686-w64-mingw32.static-gcc -Wall 3 | LIB = -lwsock32 -lpthread 4 | 5 | ifeq "x$(PREFIX)" "x" 6 | PREFIX = $(PS2DEV) 7 | endif 8 | 9 | all: bin/fsclient.exe bin/ps2client.exe 10 | 11 | clean: 12 | rm -f obj/*.o bin/*client* 13 | 14 | ################# 15 | ## CLIENT LIBS ## 16 | ################# 17 | 18 | OFILES += obj/network.o 19 | obj/network.o: src/network.c src/network.h 20 | @mkdir -p obj 21 | $(CC) $(INC) -c src/network.c -o obj/network.o 22 | 23 | OFILES += obj/ps2link.o 24 | obj/ps2link.o: src/ps2link.c src/ps2link.h 25 | @mkdir -p obj 26 | $(CC) $(INC) -c src/ps2link.c -o obj/ps2link.o 27 | 28 | OFILES += obj/ps2netfs.o 29 | obj/ps2netfs.o: src/ps2netfs.c 30 | @mkdir -p obj 31 | $(CC) $(INC) -c src/ps2netfs.c -o obj/ps2netfs.o 32 | 33 | OFILES += obj/utility.o 34 | obj/utility.o: src/utility.c src/utility.h 35 | @mkdir -p obj 36 | $(CC) $(INC) -c src/utility.c -o obj/utility.o 37 | 38 | ##################### 39 | ## CLIENT PROGRAMS ## 40 | ##################### 41 | 42 | bin/fsclient.exe: $(OFILES) src/fsclient.c 43 | @mkdir -p bin 44 | $(CC) $(INC) $(OFILES) src/fsclient.c -o bin/fsclient.exe $(LIB) 45 | 46 | bin/ps2client.exe: $(OFILES) src/ps2client.c 47 | @mkdir -p bin 48 | $(CC) $(INC) $(OFILES) src/ps2client.c -o bin/ps2client.exe $(LIB) 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PS2Client 2 | 3 | ![CI](https://github.com/ps2dev/ps2client/workflows/CI/badge.svg) 4 | 5 | ## **ATTENTION** 6 | 7 | If you are confused on how to start developing for PS2, see the 8 | [getting started](https://ps2dev.github.io/#getting-started) section on 9 | the ps2dev main page. 10 | 11 | ## PS2CLIENT USAGE AND INFORMATION 12 | 13 | ### THE INTRODUCTION 14 | 15 | These programs, ps2client & fsclient, are command line tools used for interacting with a ps2 system running ps2link and/or ps2netfs. It will allow you to send various commands as well as respond to requests for data. This program was written and tested under Linux, Cygwin and Mac OS X but should compile on any reasonably unixlike system. 16 | 17 | ### BUILDING THE CLIENTS 18 | 19 | Building and installing is very simple: 20 | 21 | `make clean; make install` 22 | 23 | There are some build options, however: 24 | 25 | `PREFIX=/dir` 26 | 27 | Install directory, defaults to: `$PS2DEV`. `/bin` will be automatically appended. 28 | The software will be installed to the `/bin` sub-directory, under `PREFIX` (`PREFIX/bin`). 29 | 30 | These options can be used as follows: 31 | 32 | `make clean; make PREFIX=/new/path/prefix install` 33 | 34 | ### BUILDING WINDOWS BINARIES 35 | 36 | For building windows binaries on Unix system, you need to setup mingw cross-compiler and win32 threads. 37 | Build command: 38 | 39 | `make -f Makefile.mingw32` 40 | 41 | ### BASIC CLIENT USAGE 42 | 43 | Basic usage: 44 | 45 | ```txt 46 | ps2client [-h hostname] [-t timeout] [arguments] 47 | fsclient [-h hostname] 48 | ``` 49 | 50 | #### \[-h hostname] 51 | 52 | The address of the remote ps2. This can be an IP or a hostname. If none is given, the environment variable `$PS2HOSTNAME` will be checked for a valid address. If this variable isn't set, a default of 192.168.0.10 will be used. 53 | 54 | #### \[-t timeout] 55 | 56 | An idle timeout period in seconds that the client will wait before exiting. This is useful to allow a script to continue after calling ps2client to send a command to ps2link or ps2netfs. 57 | 58 | ### PS2LINK COMMANDS 59 | 60 | * `reset` 61 | 62 | Send a reset request to ps2link. 63 | 64 | * `execiop [arguments]` 65 | 66 | Tell ps2link to load and execute a file on the IOP. 67 | 68 | * `execee [arguments]` 69 | 70 | Tell ps2link to load and execute a file on the EE. 71 | 72 | * `poweroff` 73 | 74 | Send a poweroff request to ps2link. 75 | 76 | * `scrdump` 77 | 78 | Tell ps2link to dump exceptions to the screen. 79 | 80 | * `netdump` 81 | 82 | Tell ps2link to dump execetions to the network console. 83 | 84 | * `dumpmem ` 85 | 86 | Dump the contents of memory into a file. 87 | 88 | * `startvu ` 89 | 90 | Tell the specified vector unit to start operation. 91 | 92 | * `stopvu ` 93 | 94 | Tell the specified vector unit to stop operation. 95 | 96 | * `dumpreg ` 97 | 98 | Dump the registers of a given type into a file. 99 | 100 | * `gsexec ` 101 | 102 | Tell ps2link to load and send a file to the GS. 103 | 104 | * `writemem ` 105 | 106 | Write the contents of a file into memory. 107 | 108 | * `iopexcep` 109 | 110 | I really don't know! OH NOES!! 111 | 112 | * `listen` 113 | 114 | Listen to the ps2link network console. 115 | 116 | ## Community 117 | 118 | Links for discussion and chat are available 119 | [here](https://ps2dev.github.io/#community). 120 | -------------------------------------------------------------------------------- /doc/license.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * ps2client v3.0.0 3 | * 4 | * Copyright (c) 2005 Naomi Peori. All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * 3. The name of the author(s) may not be used to endorse or promote products 18 | * derived from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, 24 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 | * SUCH DAMAGE. 31 | * 32 | */ 33 | -------------------------------------------------------------------------------- /doc/ps2link-protocol.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------- 3 | PS2LINK OPERATION AND PROTOCOL 4 | Naomi Peori (naomi@peori.ca) 5 | Current as of: ps2link v1.22 6 | -------------------------------- 7 | 8 | Communication with ps2link takes place on three ports. I'm not entirely 9 | sure why, but it does. One udp port is used to send commands to ps2link 10 | in the form of command packets. A tcp port is used to receive requests 11 | and send responses during program runtime. And another udp port is used 12 | to receive log text from ps2link for debug or informational purposes. 13 | 14 | PS2LINK PORT NUMBERS 15 | 16 | Command (UDP) 0x4712 - One way communication to send commands. 17 | Request (TCP) 0x4711 - Two way communication to serve requests. 18 | Log (UDP) 0x4712 - One way communication to receive log text. 19 | 20 | Typical operation is to send a command, then enter a loop that waits for 21 | requests and log text from ps2link. If at any time contact is lost with 22 | ps2link, close and exit. Extra points are given if you close the command 23 | port during the loop to allow other commands to be sent to ps2link while 24 | your client is handling requests. 25 | 26 | ------------------------- 27 | PS2LINK COMMAND PACKETS 28 | ------------------------- 29 | 30 | When ps2link is finished booting, it waits for a command from a client to 31 | tell it what to do. These are simple commands sent as single packets for 32 | executing programs, resetting ps2link or other things. This list may grow 33 | as time goes on and new functionality is added to ps2link. 34 | 35 | ---------------------------- 36 | 0xBABE0201 (reset command) 37 | ---------------------------- 38 | 39 | Tell ps2link to reset and reload back to its information screen. 40 | 41 | PACKET STRUCTURE 42 | 43 | struct { int number; short length; } command; 44 | 45 | PACKET CONTENTS 46 | 47 | command.number = htonl(0xBABE0201); 48 | command.length = htons(sizeof(command)); 49 | 50 | ------------------------------ 51 | 0xBABE0202 (execiop command) 52 | ------------------------------ 53 | 54 | Tell ps2link to load and run the given program (IRX) on the IOP. 55 | 56 | PACKET STRUCTURE 57 | 58 | struct { int number; short length; int argc; char argv[256]; } command; 59 | 60 | PACKET CONTENTS 61 | 62 | command.number = htonl(0xBABE0202); 63 | command.length = htons(sizeof(command)); 64 | command.argc = htonl(argc); 65 | if (argv) { memcpy(command.argv, argv, 256); } 66 | 67 | ----------------------------- 68 | 0xBABE0203 (execee command) 69 | ----------------------------- 70 | 71 | Tell ps2link to load and run the given program (ELF) on the EE. 72 | 73 | PACKET STRUCTURE 74 | 75 | struct { int number; short length; int argc; char argv[256]; } command; 76 | 77 | PACKET CONTENTS 78 | 79 | command.number = htonl(0xBABE0203); 80 | command.length = htons(sizeof(command)); 81 | command.argc = htonl(argc); 82 | if (argv) { memcpy(command.argv, argv, 256); } 83 | 84 | ------------------------------- 85 | 0xBABE0204 (poweroff command) 86 | ------------------------------- 87 | 88 | Tell ps2link to power off the PS2. 89 | 90 | PACKET STRUCTURE 91 | 92 | struct { int number; short length; } command; 93 | 94 | PACKET CONTENTS 95 | 96 | command.number = htonl(0xBABE0204); 97 | command.length = htons(sizeof(command)); 98 | 99 | ------------------------------ 100 | 0xBABE0207 (dumpmem command) 101 | ------------------------------ 102 | 103 | Tell ps2link to dump memory starting at offset and of size bytes into 104 | the file specified by pathname. 105 | 106 | PACKET STRUCTURE 107 | 108 | struct { int number; short length; int offset, size; char pathname[256]; } command; 109 | 110 | PACKET CONTENTS 111 | 112 | command.number = htonl(0xBABE0207); 113 | command.length = htons(sizeof(command)); 114 | command.offset = htonl(offset); 115 | command.size = htonl(size); 116 | if (pathname) { strncpy(command.pathname, pathname, 256); } 117 | 118 | ------------------------------ 119 | 0xBABE0208 (startvu command) 120 | ------------------------------ 121 | 122 | Tell the specified vector unit to start operation. 123 | 124 | PACKET STRUCTURE 125 | 126 | struct { int number; short length; int vu; } command; 127 | 128 | PACKET CONTENTS 129 | 130 | command.number = htonl(0xBABE0208); 131 | command.length = htons(sizeof(command)); 132 | command.vu = htonl(vu); 133 | 134 | ----------------------------- 135 | 0xBABE0209 (stopvu command) 136 | ----------------------------- 137 | 138 | Tell the specified vector unit to stop operation. 139 | 140 | PACKET STRUCTURE 141 | 142 | struct { int number; short length; int vu; } command; 143 | 144 | PACKET CONTENTS 145 | 146 | command.number = htonl(0xBABE0209); 147 | command.length = htons(sizeof(command)); 148 | command.vu = htonl(vu); 149 | 150 | ------------------------------ 151 | 0xBABE020A (dumpreg command) 152 | ------------------------------ 153 | 154 | Tell ps2link to dump the specified register type into the file specified 155 | by pathname. 156 | 157 | PACKET STRUCTURE 158 | 159 | struct { int number; short length; int type; char pathname[256]; } command; 160 | 161 | REGISTER TYPES 162 | 163 | DMAC (0), INTC (1), Timer (2), GS (3), SIF (4), FIFO (5), GIF (6), 164 | VIF0 (7), VIF1 (8) IPU (9), all registers (10), VU0 (11), VU1 (12) 165 | 166 | PACKET CONTENTS 167 | 168 | command.number = htonl(0xBABE020A); 169 | command.length = htons(sizeof(command)); 170 | command.type = htonl(type); 171 | if (pathname) { strncpy(command.pathname, pathname, 256); } 172 | 173 | ----------------------------- 174 | 0xBABE020B (gsexec command) 175 | ----------------------------- 176 | 177 | Tell ps2link to load and send the file specified by pathname to the GS. 178 | 179 | PACKET STRUCTURE 180 | 181 | struct { int number; short length; int size; char pathname[256]; } command; 182 | 183 | PACKET CONTENTS 184 | 185 | command.number = htonl(0xBABE020B); 186 | command.length = htons(sizeof(command)); 187 | command.size = htonl(size); 188 | if (pathname) { strncpy(command.pathname, pathname, 256); } 189 | 190 | -------------------------------------- 191 | PS2LINK REQUEST AND RESPONSE PACKETS 192 | -------------------------------------- 193 | 194 | During runtime, ps2link will send requests to the client for various things, 195 | usually to manipulate data on the 'host:' device. These requests are a single 196 | packet with a command number, the packet length, and its arguments. A single 197 | response packet is sent with the result of the operation. 198 | 199 | ---------------------------- 200 | 0xBABE0111 (open request) 201 | 0xBABE0112 (open response) 202 | ---------------------------- 203 | 204 | A request from ps2link to open the file specified by pathname with the given 205 | flags. Note that the flags are similar but not the same as the standard unix 206 | command open() and need to be converted before passing them on. The resulting 207 | file descriptor is returned as the result in the response packet. 208 | 209 | PACKET STRUCTURES 210 | 211 | struct { int number; short length; int flags; char pathname[256]; } request; 212 | struct { int number; short length; int result; } response; 213 | 214 | FLAG VALUES 215 | 216 | #define OPEN_READ 0x0001 217 | #define OPEN_WRITE 0x0002 218 | #define OPEN_NONBLOCK 0x0010 219 | #define OPEN_APPEND 0x0100 220 | #define OPEN_CREATE 0x0200 221 | #define OPEN_TRUNCATE 0x0400 222 | 223 | RESPONSE VALUES 224 | 225 | response.number = htonl(0xBABE0112); 226 | response.length = htons(sizeof(response)); 227 | response.result = htonl(open(request.pathname, converted_flags, 0644)); 228 | 229 | ----------------------------- 230 | 0xBABE0121 (close request) 231 | 0xBABE0122 (close response) 232 | ----------------------------- 233 | 234 | A request from ps2link to close the file specified by the file descriptor, 235 | fd. The result of the close() call is returned in the response packet. 236 | 237 | PACKET STRUCTURES 238 | 239 | struct { int number; short length; int fd; } request; 240 | struct { int number; short length; int result; } response; 241 | 242 | RESPONSE VALUES 243 | 244 | response.number = htonl(0xBABE0122); 245 | response.length = htons(sizeof(response)); 246 | response.result = htonl(close(ntohl(request->fd))); 247 | 248 | ---------------------------- 249 | 0xBABE0131 (read request) 250 | 0xBABE0132 (read response) 251 | ---------------------------- 252 | 253 | A request from ps2link to read size bytes from the file specified by the 254 | file descriptor, fd. The result of the read() call is returned in the 255 | response packet, followed by the read data itself in the next packet. The 256 | current maximum size for any given read is 64k. 257 | 258 | PACKET STRUCTURES 259 | 260 | char buffer[65536]; 261 | struct { int number; short length; int fd, size; } request; 262 | struct { int number; short length; int result, size; } response; 263 | 264 | RESPONSE VALUES 265 | 266 | response.number = htonl(0xBABE0132); 267 | response.length = htons(sizeof(response)); 268 | response.result = htonl(read(ntohl(request->fd), buffer, ntohl(request->size))); 269 | response.size = response.result; 270 | 271 | ----------------------------- 272 | 0xBABE0141 (write request) 273 | 0xBABE0142 (write response) 274 | ----------------------------- 275 | 276 | A request from ps2link to write size bytes to the file specified by the 277 | file descriptor, fd. The data to be written immediately follows the request 278 | packet itself. The result of the write() call is returned in the response 279 | packet. The current maximum size for any given write is 64k. 280 | 281 | PACKET STRUCTURES 282 | 283 | struct { int number; short length; int fd, size; } request; 284 | struct { int number; short length; int result; } response; 285 | 286 | RESPONSE VALUES 287 | 288 | response.number = htonl(0xBABE0142); 289 | response.length = htons(sizeof(response)); 290 | response.result = htonl(write(ntohl(request->fd), request->data, ntohl(request->size))); 291 | 292 | ----------------------------- 293 | 0xBABE0151 (lseek request) 294 | 0xBABE0152 (lseek response) 295 | ----------------------------- 296 | 297 | A request from ps2link to perform a lseek on the file specified by the 298 | file descriptor, fd. The result of the lseek() call is returned in the 299 | response packet. Note that unlike the open request, the values in this 300 | lseek request are the same as in the unix lseek(). 301 | 302 | PACKET STRUCTURES 303 | 304 | struct { int number; short length; int fd, offset, whence; } request; 305 | struct { int number; short length; int result; } response; 306 | 307 | WHENCE VALUES 308 | 309 | #define LSEEK_SET 0x0000 310 | #define LSEEK_CURRENT 0x0001 311 | #define LSEEK_END 0x0002 312 | 313 | RESPONSE VALUES 314 | 315 | response.number = htonl(0xBABE0152); 316 | response.length = htons(sizeof(response)); 317 | response.result = htonl(lseek(ntohl(request->fd), ntohl(request->offset), ntohl(request->whence))); 318 | 319 | ----------------------------- 320 | 0xBABE0161 (dopen request) 321 | 0xBABE0162 (dopen response) 322 | ----------------------------- 323 | 324 | A request from ps2link to open the directory specified by the pathname with 325 | with the given flags. The resulting directory descriptor is returned as the 326 | result in the response packet. 327 | 328 | PACKET STRUCTURES 329 | 330 | struct { int number; short length; int flags; char pathname[256]; } request; 331 | struct { int number; short length; int result; } response; 332 | 333 | RESPONSE VALUES 334 | 335 | response.number = htonl(0xBABE0162); 336 | response.length = htons(sizeof(response)); 337 | response.dd = htonl((int)opendir(request->pathname)); 338 | 339 | ------------------------------ 340 | 0xBABE0171 (dread request) 341 | 0xBABE0172 (dread response) 342 | ------------------------------ 343 | 344 | A request from ps2link to read the next directory entry specified by the 345 | directory descriptor, dd. The result of the readdir() call is returned in 346 | the response packet, along with the actual entry information. To maintain 347 | compatibility with existing PS2 directory functions, this data must be 348 | almost entirely converted to a different format. 349 | 350 | PACKET STRUCTURES 351 | 352 | struct tm timem; 353 | struct stat stats; 354 | struct dirent *direptr; 355 | struct { int number; short length; int dd; } request; 356 | struct { int number; short length; int ret; u32 mode, attr, size; u08 ctime[8], atime[8], mtime[8]; u32 hisize; u08 name[256]; } reponse; 357 | 358 | RESPONSE VALUES 359 | 360 | response.number = htonl(0xBABE0182); 361 | response.length = htons(sizeof(packet)); 362 | response.result = htonl((int)direptr = readdir((DIR *)ntohl(request->dd))); 363 | 364 | // Fetch the stats for the entry. 365 | stat(direptr->d_name, &stats); 366 | 367 | // Convert and add the mode. 368 | response.mode = (stats.st_mode & 0x07); 369 | if (S_ISDIR(stats.st_mode)) { response.mode |= 0x20; } 370 | if (S_ISLNK(stats.st_mode)) { response.mode |= 0x08; } 371 | if (S_ISREG(stats.st_mode)) { response.mode |= 0x10; } 372 | response.mode = htonl(response.mode); 373 | 374 | // Add the attributes. 375 | response.attr = htonl(0); 376 | 377 | // Add the size. 378 | response.size = htonl(stats.st_size); 379 | 380 | // Convert and add the creation time. 381 | if (localtime_r(&(stats.st_ctime), &timem)) { 382 | response.ctime[6] = (u08)loctime.tm_year; 383 | response.ctime[5] = (u08)loctime.tm_mon + 1; 384 | response.ctime[4] = (u08)loctime.tm_mday; 385 | response.ctime[3] = (u08)loctime.tm_hour; 386 | response.ctime[2] = (u08)loctime.tm_min; 387 | response.ctime[1] = (u08)loctime.tm_sec; 388 | } 389 | 390 | // Convert and add the access time. 391 | if (localtime_r(&(stats.st_atime), &timem)) { 392 | response.atime[6] = (u08)loctime.tm_year; 393 | response.atime[5] = (u08)loctime.tm_mon + 1; 394 | response.atime[4] = (u08)loctime.tm_mday; 395 | response.atime[3] = (u08)loctime.tm_hour; 396 | response.atime[2] = (u08)loctime.tm_min; 397 | response.atime[1] = (u08)loctime.tm_sec; 398 | } 399 | 400 | // Convert and add the modification time. 401 | if (localtime_r(&(stats.st_mtime), &timem)) { 402 | response.mtime[6] = (u08)loctime.tm_year; 403 | response.mtime[5] = (u08)loctime.tm_mon + 1; 404 | response.mtime[4] = (u08)loctime.tm_mday; 405 | response.mtime[3] = (u08)loctime.tm_hour; 406 | response.mtime[2] = (u08)loctime.tm_min; 407 | response.mtime[1] = (u08)loctime.tm_sec; 408 | } 409 | 410 | // Add the hsize. (what is this?) 411 | response.hisize = htonl(0); 412 | 413 | ------------------------------ 414 | 0xBABE0181 (dclose request) 415 | 0xBABE0182 (dclose response) 416 | ------------------------------ 417 | 418 | A request from ps2link to close the directory specified by the directory 419 | descriptor, dd. The result of the closedir() call is returned in the 420 | response packet. 421 | 422 | PACKET STRUCTURES 423 | 424 | struct { int number; short length; int dd; } request; 425 | struct { int number; short length; int result; } response; 426 | 427 | RESPONSE VALUES 428 | 429 | response.number = htonl(0xBABE0172); 430 | response.length = htons(sizeof(reponse)); 431 | response.result = htonl(closedir((DIR *)ntohl(request->dd))); 432 | 433 | ----------------------------- 434 | 0xBABE0191 (remove request) 435 | 0xBABE0192 (remove response) 436 | ----------------------------- 437 | 438 | A request from ps2link to remove the file specified by the given filename 439 | 'name'. The result of the remove() call is returned in the 440 | response packet. 441 | 442 | PACKET STRUCTURES 443 | 444 | struct { int number; short length; int flags; char name[256]; } request; 445 | struct { int number; short length; int result; } response; 446 | 447 | RESPONSE VALUES 448 | 449 | response.number = htonl(0xBABE0192); 450 | response.length = htons(sizeof(response)); 451 | response.result = htonl(remove(request->name)); 452 | 453 | ----------------------------- 454 | 0xBABE01a1 (mkdir request) 455 | 0xBABE01a2 (mkdir response) 456 | ----------------------------- 457 | 458 | A request from ps2link to make a directory with the dirname 459 | 'name'. The result of the mkdir() call is returned in the 460 | response packet. 461 | 462 | PACKET STRUCTURES 463 | 464 | struct { int number; short length; int flags; char name[256]; } request; 465 | struct { int number; short length; int result; } response; 466 | 467 | RESPONSE VALUES 468 | 469 | response.number = htonl(0xBABE01a2); 470 | response.length = htons(sizeof(response)); 471 | response.result = htonl(mkdir(request->name)); 472 | 473 | ----------------------------- 474 | 0xBABE01b1 (rmdir request) 475 | 0xBABE01b2 (rmdir response) 476 | ----------------------------- 477 | 478 | A request from ps2link to remove a directory with the dirname 479 | 'name'. The result of the rmdir() call is returned in the 480 | response packet. 481 | 482 | PACKET STRUCTURES 483 | 484 | struct { int number; short length; int flags; char name[256]; } request; 485 | struct { int number; short length; int result; } response; 486 | 487 | RESPONSE VALUES 488 | 489 | response.number = htonl(0xBABE01b2); 490 | response.length = htons(sizeof(response)); 491 | response.result = htonl(rmdir(request->name)); 492 | 493 | --------------------- 494 | PS2LINK LOG PACKETS 495 | --------------------- 496 | 497 | Any data received from the log port from ps2link is meant to be displayed 498 | to the user via a simple printf. There is no special processing required 499 | or any packet format - just output to the screen. 500 | -------------------------------------------------------------------------------- /doc/ps2netfs-protocol.txt: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------- 3 | PS2NETFS OPERATION AND PROTOCOL 4 | Naomi Peori (naomi@peori.ca) 5 | Current as of March 6th, 2004 6 | --------------------------------- 7 | 8 | Communication with ps2netfs takes place on TCP socket 0x4713. A connection is 9 | opened then a request packet is sent. Soon afterwards, a response packet will 10 | be received and the connection closed. Through these simple request/response 11 | pairs more complex functions can be created to do things like copy files to 12 | and from the ps2 itself. For examples see ps2netfs.c in the ps2client source. 13 | 14 | ---------------------------- 15 | 0xBEEF8011 (open request) 16 | 0xBEEF8012 (open response) 17 | ---------------------------- 18 | 19 | PACKET STRUCTURES 20 | 21 | struct { int number; short length; int flags; char pathname[256]; } request; 22 | struct { int number; short length; int result; } response; 23 | 24 | FLAG VALUES 25 | 26 | #define OPEN_READ 0x0001 27 | #define OPEN_WRITE 0x0002 28 | #define OPEN_NONBLOCK 0x0010 29 | #define OPEN_APPEND 0x0100 30 | #define OPEN_CREATE 0x0200 31 | #define OPEN_TRUNCATE 0x0400 32 | 33 | REQUEST PACKET CONTENTS 34 | 35 | request.number = htonl(0xBEEF8011); 36 | request.length = htons(sizeof(request)); 37 | request.flags = htonl(mode); 38 | if (pathname) { strncpy(request.pathname, pathname, 256); } 39 | 40 | ----------------------------- 41 | 0xBEEF8021 (close request) 42 | 0xBEEF8022 (close response) 43 | ----------------------------- 44 | 45 | PACKET STRUCTURES 46 | 47 | struct { int number; short length; int fd; } request; 48 | struct { int number; short length; int result; } response; 49 | 50 | REQUEST PACKET CONTENTS 51 | 52 | request.number = htonl(0xBEEF8021); 53 | request.length = htons(sizeof(request)); 54 | request.fd = htonl(fd); 55 | 56 | ---------------------------- 57 | 0xBEEF8031 (read request) 58 | 0xBEEF8032 (read response) 59 | ---------------------------- 60 | 61 | PACKET STRUCTURES 62 | 63 | struct { int number; short length; int fd, size; } request; 64 | struct { int number; short length; int result, size; } response; 65 | 66 | REQUEST PACKET CONTENTS 67 | 68 | request.number = htonl(0xBEEF8031); 69 | request.length = htons(sizeof(request)); 70 | request.fd = htonl(fd); 71 | request.size = htonl(size); 72 | 73 | ----------------------------- 74 | 0xBEEF8041 (write request) 75 | 0xBEEF8042 (write response) 76 | ----------------------------- 77 | 78 | PACKET STRUCTURES 79 | 80 | struct { int number; short length; int fd, size; } request; 81 | struct { int number; short length; int result; } response; 82 | 83 | REQUEST PACKET CONTENTS 84 | 85 | request.number = htonl(0xBEEF8041); 86 | request.length = htons(sizeof(request)); 87 | request.fd = htonl(fd); 88 | request.size = htonl(size); 89 | 90 | ----------------------------- 91 | 0xBEEF8051 (lseek request) 92 | 0xBEEF8052 (lseek response) 93 | ----------------------------- 94 | 95 | PACKET STRUCTURES 96 | 97 | struct { int number; short length; int fd, offset, whence; } request; 98 | struct { int number; short length; int result; } response; 99 | 100 | WHENCE VALUES 101 | 102 | #define LSEEK_SET 0x0000 103 | #define LSEEK_CURRENT 0x0001 104 | #define LSEEK_END 0x0002 105 | 106 | REQUEST PACKET CONTENTS 107 | 108 | request.number = htonl(0xBEEF8051); 109 | request.length = htons(sizeof(request)); 110 | request.fd = htonl(fd); 111 | request.offset = htonl(offset); 112 | request.whence = htonl(whence); 113 | 114 | ----------------------------- 115 | 0xBEEF8061 (ioctl request) 116 | 0xBEEF8062 (ioctl response) 117 | ----------------------------- 118 | 119 | ------------------------------ 120 | 0xBEEF8071 (delete request) 121 | 0xBEEF8072 (delete response) 122 | ------------------------------ 123 | 124 | PACKET STRUCTURES 125 | 126 | struct { int number; short length; int flags; char pathname[256]; } request; 127 | struct { int number; short length; int result; } response; 128 | 129 | REQUEST PACKET CONTENTS 130 | 131 | request.number = htonl(0xBEEF8071); 132 | request.length = htons(sizeof(request)); 133 | request.flags = htonl(flags); 134 | if (pathname) { strncpy(request.pathname, pathname, 256); } 135 | 136 | ----------------------------- 137 | 0xBEEF8081 (mkdir request) 138 | 0xBEEF8082 (mkdir response) 139 | ----------------------------- 140 | 141 | PACKET STRUCTURES 142 | 143 | struct { int number; short length; int flags; char pathname[256]; } request; 144 | struct { int number; short length; int result; } response; 145 | 146 | REQUEST PACKET CONTENTS 147 | 148 | request.number = htonl(0xBEEF8081); 149 | request.length = htons(sizeof(request)); 150 | request.flags = htonl(flags); 151 | if (pathname) { strncpy(request.pathname, pathname, 256); } 152 | 153 | ----------------------------- 154 | 0xBEEF8091 (rmdir request) 155 | 0xBEEF8092 (rmdir response) 156 | ----------------------------- 157 | 158 | PACKET STRUCTURES 159 | 160 | struct { int number; short length; int flags; char pathname[256]; } request; 161 | struct { int number; short length; int result; } response; 162 | 163 | REQUEST PACKET CONTENTS 164 | 165 | request.number = htonl(0xBEEF8091); 166 | request.length = htons(sizeof(request)); 167 | request.flags = htonl(flags); 168 | if (pathname) { strncpy(request.pathname, pathname, 256); } 169 | 170 | ------------------------------ 171 | 0xBEEF80A1 (dopen request) 172 | 0xBEEF80A2 (dopen response) 173 | ------------------------------ 174 | 175 | PACKET STRUCTURES 176 | 177 | struct { int number; short length; int flags; char pathname[256]; } request; 178 | struct { int number; short length; int result; } response; 179 | 180 | REQUEST PACKET CONTENTS 181 | 182 | request.number = htonl(0xBEEF80A1); 183 | request.length = htons(sizeof(request)); 184 | request.flags = htonl(flags); 185 | if (pathname) { strncpy(request.pathname, pathname, 256); } 186 | 187 | ------------------------------ 188 | 0xBEEF80B1 (dclose request) 189 | 0xBEEF80B2 (dclose response) 190 | ------------------------------ 191 | 192 | PACKET STRUCTURES 193 | 194 | struct { int number; short length; int dd; } request; 195 | struct { int number; short length; int result; } response; 196 | 197 | REQUEST PACKET CONTENTS 198 | 199 | request.number = htonl(0xBEEF80B1); 200 | request.length = htons(sizeof(request)); 201 | request.dd = htonl(dd); 202 | 203 | ----------------------------- 204 | 0xBEEF80C1 (dread request) 205 | 0xBEEF80C2 (dread response) 206 | ----------------------------- 207 | 208 | PACKET STRUCTURES 209 | 210 | struct { int number; short length; int dd; } request; 211 | struct { int number; short length; int result; int mode, attr, size; char ctime[8], atime[8], mtime[8]; int hisize; char name[256]; } response; 212 | 213 | REQUEST PACKET CONTENTS 214 | 215 | request.number = htonl(0xBEEF80C1); 216 | request.length = htons(sizeof(request)); 217 | request.dd = htonl(dd); 218 | 219 | ------------------------------ 220 | 0xBEEF80F1 (format request) 221 | 0xBEEF80F2 (format response) 222 | ------------------------------ 223 | 224 | UNDOCUMENTED 225 | 226 | ------------------------------ 227 | 0xBEEF8111 (rename request) 228 | 0xBEEF8112 (rename response) 229 | ------------------------------ 230 | 231 | UNDOCUMENTED 232 | 233 | ---------------------------- 234 | 0xBEEF8131 (sync request) 235 | 0xBEEF8132 (sync response) 236 | ---------------------------- 237 | 238 | PACKET STRUCTURES 239 | 240 | struct { int number; short length; int flags; char device[256]; } request; 241 | struct { int number; short length; int result; } response; 242 | 243 | REQUEST PACKET CONTENTS 244 | 245 | request.number = htonl(0xBEEF8131); 246 | request.length = htons(sizeof(request)); 247 | request.flags = htonl(flags); 248 | if (device) { strncpy(request.device, device, 256); } 249 | 250 | ----------------------------- 251 | 0xBEEF8141 (mount request) 252 | 0xBEEF8142 (mount response) 253 | ----------------------------- 254 | 255 | PACKET STRUCTURES 256 | 257 | struct { int number; short length; char device[256], fsname[256]; int flags; char argv[256]; int argc; } request; 258 | struct { int number; short length; int result; } response; 259 | 260 | FLAG VALUES 261 | 262 | #define MOUNT_READWRITE 0x00 263 | #define MOUNT_READONLY 0x01 264 | 265 | REQUEST PACKET CONTENTS 266 | 267 | request.number = htonl(0xBEEF8141); 268 | request.length = htons(sizeof(request)); 269 | request.flags = htonl(flags); 270 | request.argc = htonl(argc); 271 | if (device) { strncpy(request.device, device, 256); } 272 | if (fsname) { strncpy(request.fsname, fsname, 256); } 273 | if (argv) { strncpy(request.argv, argv, 256); } 274 | 275 | ------------------------------ 276 | 0xBEEF8151 (umount request) 277 | 0xBEEF8152 (umount response) 278 | ------------------------------ 279 | 280 | PACKET STRUCTURES 281 | 282 | struct { int number; short length; int flags; char device[256]; } request; 283 | struct { int number; short length; int result; } response; 284 | 285 | REQUEST PACKET CONTENTS 286 | 287 | request.number = htonl(0xBEEF8151); 288 | request.length = htons(sizeof(request)); 289 | request.flags = htonl(flags); 290 | if (device) { strncpy(request.device, device, 256); } 291 | 292 | ------------------------------- 293 | 0xBEEF8F21 (devlist request) 294 | 0xBEEF8F22 (devlist response) 295 | ------------------------------- 296 | 297 | PACKET STRUCTURES 298 | 299 | struct { int number; short length; int flags; char pathname[256]; } request; 300 | struct { int number; short length; int result; int count; char devlist[256]; } response; 301 | 302 | REQUEST PACKET CONTENTS 303 | 304 | request.number = htonl(0xBEEF8F21); 305 | request.length = htons(sizeof(request)); 306 | request.flags = htonl(flags); 307 | if (pathname) { strncpy(request.pathname, pathname, 256); } 308 | -------------------------------------------------------------------------------- /doc/readme-mingw32.txt: -------------------------------------------------------------------------------- 1 | 2 | ================================= 3 | PS2CLIENT - NOTES FOR MINGW32 4 | ================================= 5 | 6 | ---------------------------------- 7 | BUILDING PS2CLIENT USING MINGW32 8 | ---------------------------------- 9 | 10 | Since now, ps2client uses the pthread library to work, you need the 11 | threads support. For example you can use MXE/MinGW-w64 with win32 12 | threads. 13 | -------------------------------------------------------------------------------- /doc/readme.txt: -------------------------------------------------------------------------------- 1 | 2 | =================================== 3 | PS2CLIENT USAGE AND INFORMATION 4 | =================================== 5 | 6 | ------------------ 7 | THE INTRODUCTION 8 | ------------------ 9 | 10 | These programs, ps2client & fsclient, are command line tools used for interacting 11 | with a ps2 system running ps2link and/or ps2netfs. It will allow you to send various 12 | commands as well as respond to requests for data. This program was written and tested 13 | under Linux, Cygwin and Mac OS X but should compile on any reasonably unixlike system. 14 | 15 | If you have any requests, questions or sugestions please feel free to contact me at 16 | peori@oopo.net. Also, don't be afraid to check out the latest development version of 17 | ps2client located at cvs.ps2dev.org. 18 | 19 | ---------------------- 20 | BUILDING THE CLIENTS 21 | ---------------------- 22 | 23 | Building and installing is very simple: 24 | 25 | make clean; make install 26 | 27 | There are some build options, however: 28 | 29 | PREFIX=/dir - Install directory, defaults to: $PS2DEV. "/bin" will be automatically appended. 30 | The software will be installed to the /bin sub-directory, under PREFIX (PREFIX/bin). 31 | 32 | These options can be used as follows: 33 | 34 | make clean; make PREFIX=/new/path/prefix install 35 | 36 | -------------------- 37 | BASIC CLIENT USAGE 38 | -------------------- 39 | 40 | Basic usage: 41 | 42 | ps2client [-h hostname] [-t timeout] [arguments] 43 | 44 | fsclient [-h hostname] 45 | 46 | [-h hostname] 47 | 48 | The address of the remote ps2. This can be an IP or a hostname. If none 49 | is given, the environment variable $PS2HOSTNAME will be checked for a 50 | valid address. If this variable isn't set, a default of 192.168.0.10 51 | will be used. 52 | 53 | [-t timeout] 54 | 55 | An idle timeout period in seconds that the client will wait before exiting. 56 | This is useful to allow a script to continue after calling ps2client to send 57 | a command to ps2link or ps2netfs. 58 | 59 | ------------------ 60 | PS2LINK COMMANDS 61 | ------------------ 62 | 63 | reset 64 | 65 | - Send a reset request to ps2link. 66 | 67 | execiop [arguments] 68 | 69 | - Tell ps2link to load and execute a file on the IOP. 70 | 71 | execee [arguments] 72 | 73 | - Tell ps2link to load and execute a file on the EE. 74 | 75 | poweroff 76 | 77 | - Send a poweroff request to ps2link. 78 | 79 | scrdump 80 | 81 | - Tell ps2link to dump exceptions to the screen. 82 | 83 | netdump 84 | 85 | - Tell ps2link to dump execetions to the network console. 86 | 87 | dumpmem 88 | 89 | - Dump the contents of memory into a file. 90 | 91 | startvu 92 | 93 | - Tell the specified vector unit to start operation. 94 | 95 | stopvu 96 | 97 | - Tell the specified vector unit to stop operation. 98 | 99 | dumpreg 100 | 101 | - Dump the registers of a given type into a file. 102 | 103 | gsexec 104 | 105 | - Tell ps2link to load and send a file to the GS. 106 | 107 | writemem 108 | 109 | - Write the contents of a file into memory. 110 | 111 | iopexcep 112 | 113 | - I really don't know! OH NOES!! 114 | 115 | listen 116 | 117 | - Listen to the ps2link network console. 118 | 119 | ------------------ 120 | MORE INFORMATION 121 | ------------------ 122 | 123 | If you want to get into the wonderful world of homebrew ps2 124 | development, there's a few places you can check out: 125 | 126 | http://www.ps2dev.org - News, tutorials and documentation. 127 | 128 | http://forums.ps2dev.org - The official ps2dev forums. 129 | 130 | #ps2dev on freenode (IRC) - Come banter in realtime. 131 | -------------------------------------------------------------------------------- /doc/todo.txt: -------------------------------------------------------------------------------- 1 | 2 | - dumpmem may be giving bad data 3 | - iopexcep needs to be implemented (what is it?) 4 | -------------------------------------------------------------------------------- /src/fsclient.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #ifndef _WIN32 8 | #include 9 | #endif 10 | #include "utility.h" 11 | #include "ps2netfs.h" 12 | #include "network.h" 13 | 14 | #include "fsclient.h" 15 | 16 | char hostname[256] = { "192.168.0.10" }; 17 | 18 | int main(int argc, char **argv, char **env) { int loop0 = 0; 19 | 20 | // Turn off stdout buffering. 21 | setbuf(stdout, NULL); 22 | 23 | // Parse the environment list for optional arguments. 24 | for (loop0=0; env[loop0]; loop0++) { 25 | 26 | // A hostname has been specified... 27 | if (strncmp(env[loop0], "PS2HOSTNAME", 11) == 0) { strncpy(hostname, &env[loop0][12], sizeof(hostname)); } 28 | 29 | } 30 | 31 | // Check the number of arguments. 32 | if (argc < 2) { print_usage(); return -1; } 33 | 34 | // Parse the argument list for optional arguments. 35 | for (loop0=1; argv[loop0]; loop0++) { 36 | 37 | // If an optional hostname has been specified... 38 | if (strncmp(argv[loop0], "-h", 2) == 0) { loop0++; 39 | 40 | // Check to make sure the hostname value was actually supplied. 41 | if (argc == loop0) { printf("Error: No hostname was supplied the '-h' option.\n"); print_usage(); return -1; } 42 | 43 | // Set the hostname to the supplied value. 44 | strncpy(hostname, argv[loop0], sizeof(hostname)); 45 | 46 | } 47 | 48 | // Else, the end of the options has been reached... 49 | else { break; } 50 | 51 | } 52 | 53 | // Increment the argument counters past any optional arguments. 54 | loop0++; argc -= loop0; argv += loop0; 55 | 56 | // Check to make sure a command was actually supplied. 57 | if (argc < 0) { printf("Error: No command was supplied.\n"); print_usage(); return -1; } 58 | 59 | #ifdef _WIN32 60 | 61 | // Startup network, under windows. 62 | if (network_startup() < 0) { printf("Error: Could not start up winsock.\n"); return 1; } 63 | 64 | #endif 65 | 66 | // Connect to the ps2netfs server. 67 | if (ps2netfs_connect(hostname) < 0) { printf("Error: Could not connect to the ps2netfs server. (%s)\n", hostname); return -1; } 68 | 69 | // Perform the requested command. 70 | if (strcmp(argv[-1], "copyfrom") == 0) { return fsclient_copyfrom(argv[0], argv[1]); } else 71 | if (strcmp(argv[-1], "copyto") == 0) { return fsclient_copyto(argv[0], argv[1]); } else 72 | if (strcmp(argv[-1], "delete") == 0) { return fsclient_delete(argv[0]); } else 73 | if (strcmp(argv[-1], "devlist") == 0) { return fsclient_devlist(); } else 74 | if (strcmp(argv[-1], "dir") == 0) { return fsclient_dir(argv[0]); } else 75 | if (strcmp(argv[-1], "mkdir") == 0) { return fsclient_mkdir(argv[0]); } else 76 | if (strcmp(argv[-1], "mount") == 0) { return fsclient_mount(argv[0], argv[1]); } else 77 | if (strcmp(argv[-1], "rmdir") == 0) { return fsclient_rmdir(argv[0]); } else 78 | if (strcmp(argv[-1], "sync") == 0) { return fsclient_sync(argv[0]); } else 79 | if (strcmp(argv[-1], "umount") == 0) { return fsclient_umount(argv[0]); } else 80 | 81 | // An unknown command was requested. 82 | { printf("Error: Unknown command requested. (%s)\n", argv[-1]); print_usage(); return -1; } 83 | 84 | // Disconnect from the ps2netfs server. 85 | if (ps2netfs_disconnect() < 0) { printf("Error: Could not disconnect from the ps2netfs server. (%s)\n", hostname); return -1; } 86 | 87 | // End program. 88 | return 0; 89 | 90 | } 91 | 92 | //////////////////////// 93 | // FSCLIENT FUNCTIONS // 94 | //////////////////////// 95 | 96 | int fsclient_copyfrom(char *source, char *destination) { int result = 0; 97 | int fd0, fd1, size, total = 0; char buffer[28000]; 98 | 99 | // Open the source file. 100 | fd0 = ps2netfs_command_open(source, OPEN_READ); 101 | if (fd0 < 0) { printf("Error: Open source file failed. (%d)\n", fd0); return -1; } 102 | 103 | // Get the source file size. 104 | size = ps2netfs_command_lseek(fd0, 0, LSEEK_END); ps2netfs_command_lseek(fd0, 0, LSEEK_SET); 105 | if (size < 0) { printf("Error: Get source file size failed. (%d)\n", size); return -1; } 106 | 107 | // Open the destination file. 108 | #if defined (__CYGWIN__) || defined (__MINGW32__) 109 | fd1 = open(destination, O_RDWR | O_CREAT | O_BINARY, 0644); 110 | #else 111 | fd1 = open(destination, O_RDWR | O_CREAT, 0644); 112 | #endif 113 | if (fd1 < 1) { printf("Error: Open destination file failed. (%d)\n", fd1); return -1; } 114 | 115 | // Output the display header. 116 | printf("\n [%s --> %s]\n\n Progress: ", source, destination); 117 | 118 | // Repeat until the copy is finished. 119 | while (total < size) { printf("#"); 120 | 121 | // Read the source data. 122 | result = ps2netfs_command_read(fd0, buffer, sizeof(buffer)); 123 | if (result < 0) { printf("Error: Read source data failed. (%d)\n", result); return -1; } 124 | 125 | // Write the destination data. 126 | result = write(fd1, buffer, result); 127 | if (result < 0) { printf("Error: Write destination data failed. (%d)\n", result); return -1; } 128 | 129 | // Increment the counter. 130 | total += result; 131 | 132 | } 133 | 134 | // Output the display footer. 135 | printf("\n\n [%d Bytes Copied]\n\n", total); 136 | 137 | // Close the source file. 138 | result = ps2netfs_command_close(fd0); 139 | if (result < 0) { printf("Error: Close source file failed. (%d)\n", result); return -1; } 140 | 141 | // Close the destination file. 142 | result = close(fd1); 143 | if (result < 0) { printf("Error: Close destination file failed. (%d)\n", result); return -1; } 144 | 145 | // End function. 146 | return 0; 147 | 148 | } 149 | 150 | int fsclient_copyto(char *source, char *destination) { int result = 0; 151 | int fd0, fd1, size, total = 0; char buffer[28000]; 152 | 153 | // Open the source file. 154 | #if defined (__CYGWIN__) || defined (__MINGW32__) 155 | fd0 = open(source, O_RDONLY | O_BINARY); 156 | #else 157 | fd0 = open(source, O_RDONLY); 158 | #endif 159 | if (fd0 < 0) { printf("Error: Open source file failed. (%d)\n", fd0); return -1; } 160 | 161 | // Get the source file size. 162 | size = lseek(fd0, 0, SEEK_END); lseek(fd0, 0, SEEK_SET); 163 | if (size < 0) { printf("Error: Get source file size failed. (%d)\n", size); return -1; } 164 | 165 | // Open the destination file. 166 | fd1 = ps2netfs_command_open(destination, OPEN_WRITE | OPEN_CREATE); 167 | if (fd0 < 1) { printf("Error: Open destination file failed. (%d)\n", fd1); return -1; } 168 | 169 | // Output the display header. 170 | printf("\n [%s --> %s]\n\n Progress: ", source, destination); 171 | 172 | // Repeat until the copy is finished. 173 | while (total < size) { printf("#"); 174 | 175 | // Read the source data. 176 | result = read(fd0, buffer, sizeof(buffer)); 177 | if (result < 0) { printf("Error: Read source data failed. (%d)\n", result); return -1; } 178 | 179 | // Write the destination data. 180 | result = ps2netfs_command_write(fd1, buffer, result); 181 | if (result < 0) { printf("Error: Write destination data failed. (%d)\n", result); return -1; } 182 | 183 | // Increment the counter. 184 | total += result; 185 | 186 | } 187 | 188 | // Output the display footer. 189 | printf("\n\n [%d Bytes Copied]\n\n", total); 190 | 191 | // Close the source file. 192 | result = close(fd0); 193 | if (result < 0) { printf("Error: Close source file failed. (%d)\n", result); return -1; } 194 | 195 | // Close the destination file. 196 | result = ps2netfs_command_close(fd1); 197 | if (result < 0) { printf("Error: Close destination file failed. (%d)\n", result); return -1; } 198 | 199 | // End function. 200 | return 0; 201 | 202 | } 203 | 204 | int fsclient_delete(char *pathname) { int result = 0; 205 | 206 | // Delete the file. 207 | result = ps2netfs_command_delete(pathname, 0); 208 | if (result < 0) { printf("Error: Delete file failed. (%d)\n", result); return -1; } 209 | 210 | // End function. 211 | return 0; 212 | 213 | } 214 | 215 | int fsclient_devlist(void) { 216 | int loop0, devcount; char devlist[256], *temp = devlist; 217 | 218 | // Get the device listing. 219 | devcount = ps2netfs_command_devlist("", 0, devlist); 220 | if (devcount < 0) { printf("Error: Get device listing failed. (%d)\n", devcount); return -1; } 221 | 222 | // Output the display header. 223 | printf("\n [Active Devices]\n\n"); 224 | 225 | // Output each available device. 226 | for(loop0=0;loop0 0) { printf(" "); 265 | 266 | // Output the mode information. 267 | if (ntohl(dirent.mode) & 0x4000) { printf("l"); } else 268 | if (ntohl(dirent.mode) & 0x2000) { printf("-"); } else 269 | if (ntohl(dirent.mode) & 0x1000) { printf("d"); } else { printf("-"); } 270 | if (ntohl(dirent.mode) & 0x0100) { printf("r"); } else { printf("-"); } 271 | if (ntohl(dirent.mode) & 0x0080) { printf("w"); } else { printf("-"); } 272 | if (ntohl(dirent.mode) & 0x0040) { printf("x"); } else { printf("-"); } 273 | if (ntohl(dirent.mode) & 0x0020) { printf("r"); } else { printf("-"); } 274 | if (ntohl(dirent.mode) & 0x0010) { printf("w"); } else { printf("-"); } 275 | if (ntohl(dirent.mode) & 0x0008) { printf("x"); } else { printf("-"); } 276 | if (ntohl(dirent.mode) & 0x0004) { printf("r"); } else { printf("-"); } 277 | if (ntohl(dirent.mode) & 0x0002) { printf("w"); } else { printf("-"); } 278 | if (ntohl(dirent.mode) & 0x0001) { printf("x"); } else { printf("-"); } 279 | 280 | // Output the file size. 281 | printf(" %10d", (int)ntohl(dirent.size)); 282 | 283 | // Output the date. 284 | printf(" %02d-%02d-%04d", dirent.mtime[5], dirent.mtime[4], (2048 + dirent.mtime[6])); 285 | 286 | // Output the time. 287 | printf(" %02d:%02d:%02d", dirent.mtime[3], dirent.mtime[2], dirent.mtime[1]); 288 | 289 | // Output the name. 290 | printf(" %s\n", dirent.name); 291 | 292 | // Update the counters. 293 | files++; size += ntohl(dirent.size); 294 | 295 | } 296 | 297 | // Output the display footer. 298 | printf("\n [%d Files - %d Bytes]\n\n", files, size); 299 | 300 | // Close the directory. 301 | result = ps2netfs_command_dclose(dd); 302 | if (result < 0) { printf("Error: Close directory failed. (%d)\n", result); return -1; } 303 | 304 | // End function. 305 | return 0; 306 | 307 | } 308 | 309 | int fsclient_mkdir(char *pathname) { int result = 0; 310 | 311 | // Make the directory. 312 | result = ps2netfs_command_mkdir(pathname, 0); 313 | if (result < 0) { printf("Error: Make directory failed. (%d)\n", result); return -1; } 314 | 315 | // End function. 316 | return 0; 317 | 318 | } 319 | 320 | int fsclient_mount(char *device, char *fsname) { int result = 0; 321 | 322 | // Mount the device. 323 | result = ps2netfs_command_mount(device, fsname, MOUNT_READWRITE, "", 0); 324 | if (result < 0) { printf("Error: Mount device failed. (%d)\n", result); return -1; } 325 | 326 | // End function. 327 | return 0; 328 | 329 | } 330 | 331 | int fsclient_rmdir(char *pathname) { int result = 0; 332 | 333 | // Remove the directory. 334 | result = ps2netfs_command_rmdir(pathname, 0); 335 | if (result < 0) { printf("Error: Remove directory failed. (%d)\n", result); return -1; } 336 | 337 | // End function. 338 | return 0; 339 | 340 | } 341 | 342 | int fsclient_sync(char *device) { int result = 0; 343 | 344 | // Sync the device. 345 | result = ps2netfs_command_sync(device, 0); 346 | if (result < 0) { printf("Error: Sync device failed. (%d)\n", result); return -1; } 347 | 348 | // End function. 349 | return 0; 350 | 351 | } 352 | 353 | int fsclient_umount(char *device) { int result = 0; 354 | 355 | // Umount the device. 356 | result = ps2netfs_command_umount(device, 0); 357 | if (result < 0) { printf("Error: Umount device failed. (%d)\n", result); return -1; } 358 | 359 | // End function. 360 | return 0; 361 | 362 | } 363 | -------------------------------------------------------------------------------- /src/fsclient.h: -------------------------------------------------------------------------------- 1 | #ifndef __FSCLIENT__ 2 | #define __FSCLIENT__ 3 | 4 | //////////////////////// 5 | // FSCLIENT FUNCTIONS // 6 | //////////////////////// 7 | 8 | int fsclient_copyfrom(char *source, char *destination); 9 | 10 | int fsclient_copyto(char *source, char *destination); 11 | 12 | int fsclient_delete(char *pathname); 13 | 14 | int fsclient_devlist(void); 15 | 16 | int fsclient_dir(char *pathname); 17 | 18 | int fsclient_mkdir(char *pathname); 19 | 20 | int fsclient_mount(char *device, char *fsname); 21 | 22 | int fsclient_rmdir(char *pathname); 23 | 24 | int fsclient_sync(char *device); 25 | 26 | int fsclient_umount(char *device); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/network.c: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _WIN32 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #endif 9 | 10 | #include "network.h" 11 | 12 | /////////////////////// 13 | // NETWORK FUNCTIONS // 14 | /////////////////////// 15 | 16 | #ifdef _WIN32 17 | int network_startup(void) { 18 | WSADATA wsaData; 19 | 20 | // Start up winsock. 21 | if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) { return -1; } 22 | 23 | // End function. 24 | return 0; 25 | 26 | } 27 | #endif 28 | 29 | int network_connect(char *hostname, int port, int type) { int sock = -1; 30 | struct sockaddr_in sockaddr; 31 | 32 | // Populate the sockaddr structure. 33 | sockaddr.sin_family = AF_INET; 34 | sockaddr.sin_port = htons(port); 35 | sockaddr.sin_addr = *(struct in_addr *)gethostbyname(hostname)->h_addr; 36 | 37 | // Open the socket. 38 | sock = socket(AF_INET, type, 0); if (sock < 0) { return -1; } 39 | 40 | // Connect the socket. 41 | if (connect(sock, (struct sockaddr *)&sockaddr, sizeof(struct sockaddr)) < 0) { return -2; } 42 | 43 | // Return the socket. 44 | return sock; 45 | 46 | } 47 | 48 | int network_listen(int port, int type) { int sock = -1; 49 | struct sockaddr_in sockaddr; 50 | 51 | // Populate the sockaddr structure. 52 | sockaddr.sin_family = AF_INET; 53 | sockaddr.sin_port = htons(port); 54 | sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); 55 | 56 | // Create the socket. 57 | sock = socket(AF_INET, type, 0); if (sock < 0) { return -1; } 58 | 59 | // Bind the socket. 60 | if (bind(sock, (struct sockaddr *)&sockaddr, sizeof(struct sockaddr)) < 0) { return -1; } 61 | 62 | // Return the socket. 63 | return sock; 64 | 65 | } 66 | 67 | int network_send(int sock, void *buffer, int size) { int total = 0; 68 | 69 | // Keep sending data until it has all been sent. 70 | while (total < size) { total += send(sock, &((char *)buffer)[total], size - total, 0); } 71 | 72 | // Return the total bytes sent. 73 | return total; 74 | 75 | } 76 | 77 | int network_wait(int sock, int timeout) { 78 | fd_set nfds; struct timeval tv; 79 | 80 | // Initialize the rdfs structure. 81 | FD_ZERO(&nfds); FD_SET(sock, &nfds); 82 | 83 | // Populate the tv structure. 84 | tv.tv_sec = timeout; tv.tv_usec = 0; 85 | 86 | // No timeout was specified, so wait forever. 87 | if (timeout < 0) { return select(FD_SETSIZE, &nfds, NULL, NULL, NULL); } 88 | 89 | // A timeout was specified, so wait until the time has elapsed. 90 | else { return select(FD_SETSIZE, &nfds, NULL, NULL, &tv); } 91 | 92 | // End function. 93 | return 0; 94 | 95 | } 96 | 97 | int network_receive(int sock, void *buffer, int size) { 98 | 99 | // Receive the data from the socket. 100 | return recvfrom(sock, buffer, size, 0, NULL, NULL); 101 | 102 | } 103 | 104 | int network_receive_all(int sock, void *buffer, int size) { int total = 0; 105 | 106 | // Receive the data from the socket. 107 | while (total < size) { total += recvfrom(sock, &((char *)buffer)[total], size - total, 0, NULL, NULL); } 108 | 109 | // Return the total bytes received. 110 | return total; 111 | 112 | } 113 | 114 | int network_disconnect(int sock) { 115 | 116 | // Close the socket. 117 | #ifdef _WIN32 118 | if (closesocket(sock) < 0) { return -1; } 119 | #else 120 | if (close(sock) < 0) { return -1; } 121 | #endif 122 | 123 | // End function. 124 | return 0; 125 | 126 | } 127 | -------------------------------------------------------------------------------- /src/network.h: -------------------------------------------------------------------------------- 1 | #ifndef __NETWORK_H__ 2 | #define __NETWORK_H__ 3 | 4 | #ifdef _WIN32 5 | #include 6 | #include 7 | #else 8 | #include 9 | #endif 10 | 11 | /////////////////////// 12 | // NETWORK FUNCTIONS // 13 | /////////////////////// 14 | 15 | #ifdef _WIN32 16 | int network_startup(void); 17 | #endif 18 | 19 | int network_connect(char *hostname, int port, int type); 20 | 21 | int network_listen(int port, int type); 22 | 23 | int network_accept(int sock); 24 | 25 | int network_send(int sock, void *buffer, int size); 26 | 27 | int network_wait(int sock, int timeout); 28 | 29 | int network_receive(int sock, void *buffer, int size); 30 | 31 | int network_receive_all(int sock, void *buffer, int size); 32 | 33 | int network_disconnect(int sock); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/ps2client.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "utility.h" 7 | #include "ps2link.h" 8 | #ifdef _WIN32 9 | #include "network.h" 10 | #endif 11 | 12 | char hostname[256] = { "192.168.0.10" }; 13 | 14 | int timeout = -1; 15 | 16 | int main(int argc, char **argv, char **env) { int loop0 = 0; 17 | 18 | // Turn off stdout buffering. 19 | setbuf(stdout, NULL); 20 | 21 | // Parse the environment list for optional arguments. 22 | for (loop0=0; env[loop0]; loop0++) { 23 | 24 | // A hostname has been specified... 25 | if (strncmp(env[loop0], "PS2HOSTNAME", 11) == 0) { strncpy(hostname, &env[loop0][12], sizeof(hostname)); } 26 | 27 | } 28 | 29 | // Check the number of arguments. 30 | if (argc < 2) { print_usage(); return -1; } 31 | 32 | // Parse the argument list for optional arguments. 33 | for (loop0=1; argv[loop0]; loop0++) { 34 | 35 | // If an optional hostname has been specified... 36 | if (strncmp(argv[loop0], "-h", 2) == 0) { loop0++; 37 | 38 | // Check to make sure the hostname value was actually supplied. 39 | if (argc == loop0) { printf("Error: No hostname was supplied the '-h' option.\n"); print_usage(); return -1; } 40 | 41 | // Set the hostname to the supplied value. 42 | strncpy(hostname, argv[loop0], sizeof(hostname)); 43 | 44 | } 45 | 46 | // Else, if an optional timeout has been specified... 47 | else if (strncmp(argv[loop0], "-t", 2) == 0) { loop0++; 48 | 49 | // Check to make sure a value was actually supplied. 50 | if (argc == loop0) { printf("Error: No timeout was supplied the '-t' option.\n"); print_usage(); return -1; } 51 | 52 | // Set the timeout to the supplied value. 53 | timeout = atoi(argv[loop0]); 54 | 55 | } 56 | 57 | // Else, the end of the options has been reached... 58 | else { break; } 59 | 60 | } 61 | 62 | // Increment the argument counters past any optional arguments. 63 | loop0++; argc -= loop0; argv += loop0; 64 | 65 | // Check to make sure a command was actually supplied. 66 | if (argc < 0) { printf("Error: No command was supplied.\n"); print_usage(); return -1; } 67 | 68 | #ifdef _WIN32 69 | 70 | // Startup network, under windows. 71 | if (network_startup() < 0) { printf("Error: Could not start up winsock.\n"); return 1; } 72 | 73 | #endif 74 | 75 | // Connect to the ps2link server. 76 | if (ps2link_connect(hostname) < 0) { printf("Error: Could not connect to the ps2link server. (%s)\n", hostname); return -1; } 77 | 78 | // Perform the requested command. 79 | if (strcmp(argv[-1], "reset") == 0) { ps2link_command_reset(); timeout = 0; } else 80 | if (strcmp(argv[-1], "execiop") == 0) { ps2link_command_execiop(argc, argv); } else 81 | if (strcmp(argv[-1], "execee") == 0) { ps2link_command_execee(argc, argv); } else 82 | if (strcmp(argv[-1], "poweroff") == 0) { ps2link_command_poweroff(); timeout = 0; } else 83 | if (strcmp(argv[-1], "scrdump") == 0) { ps2link_command_scrdump(); timeout = 0; } else 84 | if (strcmp(argv[-1], "netdump") == 0) { ps2link_command_netdump(); timeout = 0; } else 85 | if (strcmp(argv[-1], "dumpmem") == 0) { ps2link_command_dumpmem(atoi(argv[0]), atoi(argv[1]), argv[2]); } else 86 | if (strcmp(argv[-1], "startvu") == 0) { ps2link_command_startvu(atoi(argv[0])); timeout = 0; } else 87 | if (strcmp(argv[-1], "stopvu") == 0) { ps2link_command_stopvu(atoi(argv[0])); timeout = 0; } else 88 | if (strcmp(argv[-1], "dumpreg") == 0) { ps2link_command_dumpreg(atoi(argv[0]), argv[1]); } else 89 | if (strcmp(argv[-1], "gsexec") == 0) { ps2link_command_gsexec(atoi(argv[0]), argv[1]); } else 90 | if (strcmp(argv[-1], "writemem") == 0) { ps2link_command_writemem(atoi(argv[0]), atoi(argv[1]), argv[2]); } else 91 | if (strcmp(argv[-1], "iopexcep") == 0) { ps2link_command_iopexcep(); timeout = 0; } else 92 | if (strcmp(argv[-1], "listen") == 0) { } else 93 | 94 | // An unknown command was requested. 95 | { printf("Error: Unknown command requested. (%s)\n", argv[-1]); print_usage(); return -1; } 96 | 97 | // Enter the main loop. 98 | ps2link_mainloop(timeout); 99 | 100 | // Disconnect from the ps2link server. 101 | ps2link_disconnect(); 102 | 103 | // End program. 104 | return 0; 105 | 106 | } 107 | -------------------------------------------------------------------------------- /src/ps2link.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #ifndef _WIN32 12 | #include 13 | #else 14 | #include 15 | #define sleep(x) Sleep(x * 1000) 16 | #endif 17 | 18 | #include "network.h" 19 | #include "ps2link.h" 20 | #include "utility.h" 21 | 22 | int console_socket = -1; 23 | int request_socket = -1; 24 | int command_socket = -1; 25 | 26 | pthread_t console_thread_id; 27 | pthread_t request_thread_id; 28 | 29 | int ps2link_counter = 0; 30 | 31 | // ps2link_dd is now an array of structs 32 | struct { 33 | char *pathname; // remember to free when closing dir 34 | DIR *dir; 35 | } ps2link_dd[10] = { 36 | { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, 37 | { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL } 38 | }; 39 | 40 | /////////////////////// 41 | // PS2LINK FUNCTIONS // 42 | /////////////////////// 43 | 44 | int ps2link_connect(char *hostname) { 45 | 46 | // Connect to the console port. 47 | console_socket = network_listen(0x4712, SOCK_DGRAM); 48 | 49 | // Create the console thread. 50 | if (console_socket > 0) { pthread_create(&console_thread_id, NULL, ps2link_thread_console, (void *)&console_thread_id); } 51 | 52 | // Connect to the request port. 53 | request_socket = network_connect(hostname, 0x4711, SOCK_STREAM); 54 | 55 | // Create the request thread. 56 | if (request_socket > 0) { pthread_create(&request_thread_id, NULL, ps2link_thread_request, (void *)&request_thread_id); } 57 | 58 | // Connect to the command port. 59 | command_socket = network_connect(hostname, 0x4712, SOCK_DGRAM); 60 | 61 | // Delay for a moment to let ps2link finish setup. 62 | #ifdef _WIN32 63 | Sleep(1); 64 | #else 65 | sleep(1); 66 | #endif 67 | 68 | // End function. 69 | return 0; 70 | 71 | } 72 | 73 | int ps2link_mainloop(int timeout) { 74 | 75 | // Disconnect from the command port. 76 | if (network_disconnect(command_socket) < 0) { return -1; } 77 | 78 | // If no timeout was given, timeout immediately. 79 | if (timeout == 0) { return 0; } 80 | 81 | // If timeout was never, loop forever. 82 | if (timeout < 0) { for (;;) { sleep(600); } } 83 | 84 | // Increment the timeout counter until timeout is reached. 85 | while (ps2link_counter++ < timeout) { sleep(1); }; 86 | 87 | // End function. 88 | return 0; 89 | 90 | } 91 | 92 | int ps2link_disconnect(void) { 93 | 94 | // Disconnect from the command port. 95 | if (network_disconnect(command_socket) < 0) { return -1; } 96 | 97 | // Disconnect from the request port. 98 | if (network_disconnect(request_socket) < 0) { return -1; } 99 | 100 | // Disconnect from console port. 101 | if (network_disconnect(console_socket) < 0) { return -1; } 102 | 103 | // End function. 104 | return 0; 105 | 106 | } 107 | 108 | /////////////////////////////// 109 | // PS2LINK COMMAND FUNCTIONS // 110 | /////////////////////////////// 111 | 112 | int ps2link_command_reset(void) { 113 | struct { unsigned int number; unsigned short length; } PACKED command; 114 | 115 | // Build the command packet. 116 | command.number = htonl(PS2LINK_COMMAND_RESET); 117 | command.length = htons(sizeof(command)); 118 | 119 | // Send the command packet. 120 | return network_send(command_socket, &command, sizeof(command)); 121 | 122 | } 123 | 124 | int ps2link_command_execiop(int argc, char **argv) { 125 | struct { unsigned int number; unsigned short length; int argc; char argv[256]; } PACKED command; 126 | 127 | // Build the command packet. 128 | command.number = htonl(PS2LINK_COMMAND_EXECIOP); 129 | command.length = htons(sizeof(command)); 130 | command.argc = htonl(argc); 131 | fix_argv(command.argv, argv); 132 | 133 | // Send the command packet. 134 | return network_send(command_socket, &command, sizeof(command)); 135 | 136 | } 137 | 138 | int ps2link_command_execee(int argc, char **argv) { 139 | struct { unsigned int number; unsigned short length; int argc; char argv[256]; } PACKED command; 140 | 141 | // Build the command packet. 142 | command.number = htonl(PS2LINK_COMMAND_EXECEE); 143 | command.length = htons(sizeof(command)); 144 | command.argc = htonl(argc); 145 | fix_argv(command.argv, argv); 146 | 147 | // Send the command packet. 148 | return network_send(command_socket, &command, sizeof(command)); 149 | 150 | } 151 | 152 | int ps2link_command_poweroff(void) { 153 | struct { unsigned int number; unsigned short length; } PACKED command; 154 | 155 | // Build the command packet. 156 | command.number = htonl(PS2LINK_COMMAND_POWEROFF); 157 | command.length = htons(sizeof(command)); 158 | 159 | // Send the command packet. 160 | return network_send(command_socket, &command, sizeof(command)); 161 | 162 | } 163 | 164 | int ps2link_command_scrdump(void) { 165 | struct { unsigned int number; unsigned short length; } PACKED command; 166 | 167 | // Build the command packet. 168 | command.number = htonl(PS2LINK_COMMAND_SCRDUMP); 169 | command.length = htons(sizeof(command)); 170 | 171 | // Send the command packet. 172 | return network_send(command_socket, &command, sizeof(command)); 173 | 174 | } 175 | 176 | int ps2link_command_netdump(void) { 177 | struct { unsigned int number; unsigned short length; } PACKED command; 178 | 179 | // Build the command packet. 180 | command.number = htonl(PS2LINK_COMMAND_NETDUMP); 181 | command.length = htons(sizeof(command)); 182 | 183 | // Send the command packet. 184 | return network_send(command_socket, &command, sizeof(command)); 185 | 186 | } 187 | 188 | int ps2link_command_dumpmem(unsigned int offset, unsigned int size, char *pathname) { 189 | struct { unsigned int number; unsigned short length; unsigned int offset; unsigned int size; char pathname[256]; } PACKED command; 190 | 191 | // Build the command packet. 192 | command.number = htonl(PS2LINK_COMMAND_DUMPMEM); 193 | command.length = htons(sizeof(command)); 194 | command.offset = htonl(offset); 195 | command.size = htonl(size); 196 | if (pathname) { strncpy(command.pathname, pathname, 256); } 197 | 198 | // Send the command packet. 199 | return network_send(command_socket, &command, sizeof(command)); 200 | 201 | } 202 | 203 | int ps2link_command_startvu(int vu) { 204 | struct { unsigned int number; unsigned short length; int vu; } PACKED command; 205 | 206 | // Build the command packet. 207 | command.number = htonl(PS2LINK_COMMAND_STARTVU); 208 | command.length = htons(sizeof(command)); 209 | command.vu = htonl(vu); 210 | 211 | // Send the command packet. 212 | return network_send(command_socket, &command, sizeof(command)); 213 | 214 | } 215 | 216 | int ps2link_command_stopvu(int vu) { 217 | struct { unsigned int number; unsigned short length; int vu; } PACKED command; 218 | 219 | // Build the command packet. 220 | command.number = htonl(PS2LINK_COMMAND_STOPVU); 221 | command.length = htons(sizeof(command)); 222 | command.vu = htonl(vu); 223 | 224 | // Send the command packet. 225 | return network_send(command_socket, &command, sizeof(command)); 226 | 227 | } 228 | 229 | int ps2link_command_dumpreg(int type, char *pathname) { 230 | struct { unsigned int number; unsigned short length; int type; char pathname[256]; } PACKED command; 231 | 232 | // Build the command packet. 233 | command.number = htonl(PS2LINK_COMMAND_DUMPREG); 234 | command.length = htons(sizeof(command)); 235 | command.type = htonl(type); 236 | if (pathname) { strncpy(command.pathname, pathname, 256); } 237 | 238 | // Send the command packet. 239 | return network_send(command_socket, &command, sizeof(command)); 240 | 241 | } 242 | 243 | int ps2link_command_gsexec(unsigned short size, char *pathname) { 244 | struct { unsigned int number; unsigned short length; unsigned short size; char pathname[256]; } PACKED command; 245 | 246 | // Build the command packet.. 247 | command.number = htonl(PS2LINK_COMMAND_GSEXEC); 248 | command.length = htons(sizeof(command)); 249 | command.size = htonl(size); 250 | if (pathname) { strncpy(command.pathname, pathname, 256); } 251 | 252 | // Send the command packet. 253 | return network_send(command_socket, &command, sizeof(command)); 254 | 255 | } 256 | 257 | int ps2link_command_writemem(unsigned int offset, unsigned int size, char *pathname) { 258 | struct { unsigned int number; unsigned short length; unsigned int offset; unsigned int size; char pathname[256]; } PACKED command; 259 | 260 | // Build the command packet. 261 | command.number = htonl(PS2LINK_COMMAND_WRITEMEM); 262 | command.length = htons(sizeof(command)); 263 | command.offset = htonl(offset); 264 | command.size = htonl(size); 265 | if (pathname) { strncpy(command.pathname, pathname, 256); } 266 | 267 | // Send the command packet. 268 | return network_send(command_socket, &command, sizeof(command)); 269 | 270 | } 271 | 272 | int ps2link_command_iopexcep(void) { 273 | struct { unsigned int number; unsigned short length; } PACKED command; 274 | 275 | // Build the command packet. 276 | command.number = htonl(PS2LINK_COMMAND_IOPEXCEP); 277 | command.length = htons(sizeof(command)); 278 | 279 | // Send the command packet. 280 | return network_send(command_socket, &command, sizeof(command)); 281 | 282 | // End function. 283 | return 0; 284 | 285 | } 286 | 287 | /////////////////////////////// 288 | // PS2LINK REQUEST FUNCTIONS // 289 | /////////////////////////////// 290 | 291 | int ps2link_request_open(void *packet) { 292 | struct { unsigned int number; unsigned short length; int flags; char pathname[256]; } PACKED *request = packet; 293 | int result = -1; 294 | struct stat stats; 295 | 296 | // Fix the arguments. 297 | fix_pathname(request->pathname); 298 | request->flags = fix_flags(ntohl(request->flags)); 299 | 300 | if(((stat(request->pathname, &stats) == 0) && (!S_ISDIR(stats.st_mode))) || (request->flags & O_CREAT)) 301 | { 302 | // Perform the request. 303 | #if defined (__CYGWIN__) || defined (__MINGW32__) 304 | result = open(request->pathname, request->flags | O_BINARY, 0644); 305 | #else 306 | result = open(request->pathname, request->flags, 0644); 307 | #endif 308 | } 309 | 310 | // Send the response. 311 | return ps2link_response_open(result); 312 | 313 | } 314 | 315 | int ps2link_request_close(void *packet) { 316 | struct { unsigned int number; unsigned short length; int fd; } PACKED *request = packet; 317 | int result = -1; 318 | 319 | // Perform the request. 320 | result = close(ntohl(request->fd)); 321 | 322 | // Send the response. 323 | return ps2link_response_close(result); 324 | 325 | } 326 | 327 | int ps2link_request_read(void *packet) { 328 | struct { unsigned int number; unsigned short length; int fd; int size; } PACKED *request = packet; 329 | int result = -1, size = -1; char buffer[65536]; 330 | 331 | // If a big read is requested... 332 | if (ntohl(request->size) > sizeof(buffer)) { 333 | 334 | // Allocate the bigbuffer. 335 | char *bigbuffer = malloc(ntohl(request->size)); 336 | 337 | // Perform the request. 338 | result = size = read(ntohl(request->fd), bigbuffer, ntohl(request->size)); 339 | 340 | // Send the response. 341 | ps2link_response_read(result, size); 342 | 343 | // Send the response data. 344 | network_send(request_socket, bigbuffer, size); 345 | 346 | // Free the bigbuffer. 347 | free(bigbuffer); 348 | 349 | // Else, a normal read is requested... 350 | } else { 351 | 352 | // Perform the request. 353 | result = size = read(ntohl(request->fd), buffer, ntohl(request->size)); 354 | 355 | // Send the response. 356 | ps2link_response_read(result, size); 357 | 358 | // Send the response data. 359 | network_send(request_socket, buffer, size); 360 | 361 | } 362 | 363 | // End function. 364 | return 0; 365 | 366 | } 367 | 368 | int ps2link_request_write(void *packet) { 369 | struct { unsigned int number; unsigned short length; int fd; int size; } PACKED *request = packet; 370 | int result = -1; char buffer[65536]; 371 | 372 | // If a big write is requested... 373 | if (ntohl(request->size) > sizeof(buffer)) { 374 | 375 | // Allocate the bigbuffer. 376 | char *bigbuffer = malloc(ntohl(request->size)); 377 | 378 | // Read the request data. 379 | network_receive_all(request_socket, bigbuffer, ntohl(request->size)); 380 | 381 | // Perform the request. 382 | result = write(ntohl(request->fd), bigbuffer, ntohl(request->size)); 383 | 384 | // Send the response. 385 | ps2link_response_write(result); 386 | 387 | // Free the bigbuffer. 388 | free(bigbuffer); 389 | 390 | // Else, a normal write is requested... 391 | } else { 392 | 393 | // Read the request data. 394 | network_receive_all(request_socket, buffer, ntohl(request->size)); 395 | 396 | // Perform the request. 397 | result = write(ntohl(request->fd), buffer, ntohl(request->size)); 398 | 399 | // Send the response. 400 | ps2link_response_write(result); 401 | 402 | } 403 | 404 | // End function. 405 | return 0; 406 | 407 | } 408 | 409 | int ps2link_request_lseek(void *packet) { 410 | struct { unsigned int number; unsigned short length; int fd, offset, whence; } PACKED *request = packet; 411 | int result = -1; 412 | 413 | // Perform the request. 414 | result = lseek(ntohl(request->fd), ntohl(request->offset), ntohl(request->whence)); 415 | 416 | // Send the response. 417 | return ps2link_response_lseek(result); 418 | 419 | } 420 | 421 | int ps2link_request_opendir(void *packet) { 422 | struct { unsigned int command; unsigned short length; int flags; char pathname[256]; } PACKED *request = packet; 423 | int result = -1; 424 | struct stat stats; 425 | 426 | // Fix the arguments. 427 | fix_pathname(request->pathname); 428 | 429 | if((stat(request->pathname, &stats) == 0) && (S_ISDIR(stats.st_mode))) 430 | { 431 | // Allocate an available directory descriptor. 432 | for (int loop0=0; loop0<10; loop0++) { if (ps2link_dd[loop0].dir == NULL) { result = loop0; break; } } 433 | 434 | // Perform the request. 435 | if (result != -1) 436 | { 437 | ps2link_dd[result].pathname = (char *) malloc(strlen(request->pathname) + 1); 438 | strcpy(ps2link_dd[result].pathname, request->pathname); 439 | ps2link_dd[result].dir = opendir(request->pathname); 440 | } 441 | } 442 | 443 | // Send the response. 444 | return ps2link_response_opendir(result); 445 | } 446 | 447 | int ps2link_request_closedir(void *packet) { 448 | struct { unsigned int number; unsigned short length; int dd; } PACKED *request = packet; 449 | int result = -1; 450 | 451 | // Perform the request. 452 | result = closedir(ps2link_dd[ntohl(request->dd)].dir); 453 | 454 | if(ps2link_dd[ntohl(request->dd)].pathname) 455 | { 456 | free(ps2link_dd[ntohl(request->dd)].pathname); 457 | ps2link_dd[ntohl(request->dd)].pathname = NULL; 458 | } 459 | 460 | // Free the directory descriptor. 461 | ps2link_dd[ntohl(request->dd)].dir = NULL; 462 | 463 | // Send the response. 464 | return ps2link_response_closedir(result); 465 | 466 | } 467 | 468 | int ps2link_request_readdir(void *packet) { 469 | DIR *dir; 470 | struct { unsigned int number; unsigned short length; int dd; } PACKED *request = packet; 471 | struct dirent *dirent; struct stat stats; struct tm *loctime; 472 | unsigned int mode; unsigned char ctime[8]; unsigned char atime[8]; unsigned char mtime[8]; 473 | char tname[512]; 474 | 475 | dir = ps2link_dd[ntohl(request->dd)].dir; 476 | 477 | // Perform the request. 478 | dirent = readdir(dir); 479 | 480 | // If no more entries were found... 481 | if (dirent == NULL) { 482 | 483 | // Tell the user an entry wasn't found. 484 | return ps2link_response_readdir(0, 0, 0, 0, NULL, NULL, NULL, 0, NULL); 485 | 486 | } 487 | 488 | // need to specify the directory as well as file name otherwise uses CWD! 489 | sprintf(tname, "%s/%s", ps2link_dd[ntohl(request->dd)].pathname, dirent->d_name); 490 | 491 | // Fetch the entry's statistics. 492 | stat(tname, &stats); 493 | 494 | // Convert the mode. 495 | mode = (stats.st_mode & 0x07); 496 | if (S_ISDIR(stats.st_mode)) { mode |= 0x20; } 497 | #ifndef _WIN32 498 | if (S_ISLNK(stats.st_mode)) { mode |= 0x08; } 499 | #endif 500 | if (S_ISREG(stats.st_mode)) { mode |= 0x10; } 501 | 502 | // Convert the creation time. 503 | loctime = localtime(&(stats.st_ctime)); 504 | ctime[6] = (unsigned char)loctime->tm_year; 505 | ctime[5] = (unsigned char)loctime->tm_mon + 1; 506 | ctime[4] = (unsigned char)loctime->tm_mday; 507 | ctime[3] = (unsigned char)loctime->tm_hour; 508 | ctime[2] = (unsigned char)loctime->tm_min; 509 | ctime[1] = (unsigned char)loctime->tm_sec; 510 | 511 | // Convert the access time. 512 | loctime = localtime(&(stats.st_atime)); 513 | atime[6] = (unsigned char)loctime->tm_year; 514 | atime[5] = (unsigned char)loctime->tm_mon + 1; 515 | atime[4] = (unsigned char)loctime->tm_mday; 516 | atime[3] = (unsigned char)loctime->tm_hour; 517 | atime[2] = (unsigned char)loctime->tm_min; 518 | atime[1] = (unsigned char)loctime->tm_sec; 519 | 520 | // Convert the last modified time. 521 | loctime = localtime(&(stats.st_mtime)); 522 | mtime[6] = (unsigned char)loctime->tm_year; 523 | mtime[5] = (unsigned char)loctime->tm_mon + 1; 524 | mtime[4] = (unsigned char)loctime->tm_mday; 525 | mtime[3] = (unsigned char)loctime->tm_hour; 526 | mtime[2] = (unsigned char)loctime->tm_min; 527 | mtime[1] = (unsigned char)loctime->tm_sec; 528 | 529 | // Send the response. 530 | return ps2link_response_readdir(1, mode, 0, stats.st_size, ctime, atime, mtime, 0, dirent->d_name); 531 | 532 | } 533 | 534 | int ps2link_request_remove(void *packet) { 535 | struct { unsigned int number; unsigned short length; char name[256]; } PACKED *request = packet; 536 | int result = -1; 537 | 538 | // Fix the arguments. 539 | fix_pathname(request->name); 540 | 541 | // Perform the request. 542 | result = remove(request->name); 543 | 544 | // Send the response. 545 | return ps2link_response_remove(result); 546 | } 547 | 548 | int ps2link_request_mkdir(void *packet) { 549 | struct { unsigned int number; unsigned short length; int mode; char name[256]; } PACKED *request = packet; 550 | int result = -1; 551 | 552 | // Fix the arguments. 553 | fix_pathname(request->name); 554 | // request->flags = fix_flags(ntohl(request->flags)); 555 | 556 | // Perform the request. 557 | // do we need to use mode in here: request->mode ? 558 | 559 | #ifdef _WIN32 560 | result = mkdir(request->name); 561 | #else 562 | result = mkdir(request->name, request->mode); 563 | #endif 564 | 565 | // Send the response. 566 | return ps2link_response_mkdir(result); 567 | } 568 | 569 | int ps2link_request_rmdir(void *packet) { 570 | struct { unsigned int number; unsigned short length; char name[256]; } PACKED *request = packet; 571 | int result = -1; 572 | 573 | // Fix the arguments. 574 | fix_pathname(request->name); 575 | 576 | // Perform the request. 577 | result = rmdir(request->name); 578 | 579 | // Send the response. 580 | return ps2link_response_rmdir(result); 581 | } 582 | 583 | int ps2link_request_getstat(void *packet) { 584 | struct { unsigned int number; unsigned short length; char name[256]; } PACKED *request = packet; 585 | struct stat stats; struct tm *loctime; 586 | int ret; 587 | unsigned int mode = 0; 588 | unsigned char ctime[8]; unsigned char atime[8]; unsigned char mtime[8]; 589 | 590 | // Fix the arguments. 591 | fix_pathname(request->name); 592 | 593 | // Fetch the entry's statistics. 594 | ret = stat(request->name, &stats); 595 | 596 | if (ret == 0) { 597 | // Convert the mode. 598 | mode = (stats.st_mode & 0x07); 599 | if (S_ISDIR(stats.st_mode)) { mode |= 0x20; } 600 | #ifndef _WIN32 601 | if (S_ISLNK(stats.st_mode)) { mode |= 0x08; } 602 | #endif 603 | if (S_ISREG(stats.st_mode)) { mode |= 0x10; } 604 | 605 | // Convert the creation time. 606 | loctime = localtime(&(stats.st_ctime)); 607 | ctime[6] = (unsigned char)loctime->tm_year; 608 | ctime[5] = (unsigned char)loctime->tm_mon + 1; 609 | ctime[4] = (unsigned char)loctime->tm_mday; 610 | ctime[3] = (unsigned char)loctime->tm_hour; 611 | ctime[2] = (unsigned char)loctime->tm_min; 612 | ctime[1] = (unsigned char)loctime->tm_sec; 613 | 614 | // Convert the access time. 615 | loctime = localtime(&(stats.st_atime)); 616 | atime[6] = (unsigned char)loctime->tm_year; 617 | atime[5] = (unsigned char)loctime->tm_mon + 1; 618 | atime[4] = (unsigned char)loctime->tm_mday; 619 | atime[3] = (unsigned char)loctime->tm_hour; 620 | atime[2] = (unsigned char)loctime->tm_min; 621 | atime[1] = (unsigned char)loctime->tm_sec; 622 | 623 | // Convert the last modified time. 624 | loctime = localtime(&(stats.st_mtime)); 625 | mtime[6] = (unsigned char)loctime->tm_year; 626 | mtime[5] = (unsigned char)loctime->tm_mon + 1; 627 | mtime[4] = (unsigned char)loctime->tm_mday; 628 | mtime[3] = (unsigned char)loctime->tm_hour; 629 | mtime[2] = (unsigned char)loctime->tm_min; 630 | mtime[1] = (unsigned char)loctime->tm_sec; 631 | } 632 | 633 | return ps2link_response_getstat(ret, mode, 0, stats.st_size, ctime, atime, mtime, 0); 634 | } 635 | 636 | //////////////////////////////// 637 | // PS2LINK RESPONSE FUNCTIONS // 638 | //////////////////////////////// 639 | 640 | int ps2link_response_open(int result) { 641 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 642 | 643 | // Build the response packet. 644 | response.number = htonl(PS2LINK_RESPONSE_OPEN); 645 | response.length = htons(sizeof(response)); 646 | response.result = htonl(result); 647 | 648 | // Send the response packet. 649 | return network_send(request_socket, &response, sizeof(response)); 650 | 651 | } 652 | 653 | int ps2link_response_close(int result) { 654 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 655 | 656 | // Build the response packet. 657 | response.number = htonl(PS2LINK_RESPONSE_CLOSE); 658 | response.length = htons(sizeof(response)); 659 | response.result = htonl(result); 660 | 661 | // Send the response packet. 662 | return network_send(request_socket, &response, sizeof(response)); 663 | 664 | } 665 | 666 | int ps2link_response_read(int result, int size) { 667 | struct { unsigned int number; unsigned short length; int result; int size; } PACKED response; 668 | 669 | // Build the response packet. 670 | response.number = htonl(PS2LINK_RESPONSE_READ); 671 | response.length = htons(sizeof(response)); 672 | response.result = htonl(result); 673 | response.size = htonl(size); 674 | 675 | // Send the response packet. 676 | return network_send(request_socket, &response, sizeof(response)); 677 | 678 | } 679 | 680 | int ps2link_response_write(int result) { 681 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 682 | 683 | // Build the response packet. 684 | response.number = htonl(PS2LINK_RESPONSE_WRITE); 685 | response.length = htons(sizeof(response)); 686 | response.result = htonl(result); 687 | 688 | // Send the response packet. 689 | return network_send(request_socket, &response, sizeof(response)); 690 | 691 | } 692 | 693 | int ps2link_response_lseek(int result) { 694 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 695 | 696 | // Build the response packet. 697 | response.number = htonl(PS2LINK_RESPONSE_LSEEK); 698 | response.length = htons(sizeof(response)); 699 | response.result = htonl(result); 700 | 701 | // Send the response packet. 702 | return network_send(request_socket, &response, sizeof(response)); 703 | 704 | } 705 | 706 | int ps2link_response_opendir(int result) { 707 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 708 | 709 | // Build the response packet. 710 | response.number = htonl(PS2LINK_RESPONSE_OPENDIR); 711 | response.length = htons(sizeof(response)); 712 | response.result = htonl(result); 713 | 714 | // Send the response packet. 715 | return network_send(request_socket, &response, sizeof(response)); 716 | 717 | } 718 | 719 | int ps2link_response_closedir(int result) { 720 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 721 | 722 | // Build the response packet. 723 | response.number = htonl(PS2LINK_RESPONSE_CLOSEDIR); 724 | response.length = htons(sizeof(response)); 725 | response.result = htonl(result); 726 | 727 | // Send the response packet. 728 | return network_send(request_socket, &response, sizeof(response)); 729 | 730 | } 731 | 732 | int ps2link_response_readdir(int result, unsigned int mode, unsigned int attr, unsigned int size, unsigned char *ctime, unsigned char *atime, unsigned char *mtime, unsigned int hisize, char *name) { 733 | struct { unsigned int number; unsigned short length; int result; unsigned int mode; unsigned int attr; unsigned int size; unsigned char ctime[8]; unsigned char atime[8]; unsigned char mtime[8]; unsigned int hisize; char name[256]; } PACKED response; 734 | 735 | // Build the response packet. 736 | response.number = htonl(PS2LINK_RESPONSE_READDIR); 737 | response.length = htons(sizeof(response)); 738 | response.result = htonl(result); 739 | response.mode = htonl(mode); 740 | response.attr = htonl(attr); 741 | response.size = htonl(size); 742 | if (ctime) { memcpy(response.ctime, ctime, 8); } 743 | if (atime) { memcpy(response.atime, atime, 8); } 744 | if (mtime) { memcpy(response.mtime, mtime, 8); } 745 | response.hisize = htonl(hisize); 746 | #ifdef _WIN32 747 | if (name) { sprintf(response.name, "%s", name); } 748 | #else 749 | if (name) { snprintf(response.name, 256, "%s", name); } 750 | #endif 751 | 752 | // Send the response packet. 753 | return network_send(request_socket, &response, sizeof(response)); 754 | 755 | } 756 | 757 | int ps2link_response_remove(int result) { 758 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 759 | 760 | // Build the response packet. 761 | response.number = htonl(PS2LINK_RESPONSE_REMOVE); 762 | response.length = htons(sizeof(response)); 763 | response.result = htonl(result); 764 | 765 | // Send the response packet. 766 | return network_send(request_socket, &response, sizeof(response)); 767 | } 768 | 769 | int ps2link_response_mkdir(int result) { 770 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 771 | 772 | // Build the response packet. 773 | response.number = htonl(PS2LINK_RESPONSE_MKDIR); 774 | response.length = htons(sizeof(response)); 775 | response.result = htonl(result); 776 | 777 | // Send the response packet. 778 | return network_send(request_socket, &response, sizeof(response)); 779 | } 780 | 781 | int ps2link_response_rmdir(int result) { 782 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 783 | 784 | // Build the response packet. 785 | response.number = htonl(PS2LINK_RESPONSE_RMDIR); 786 | response.length = htons(sizeof(response)); 787 | response.result = htonl(result); 788 | 789 | // Send the response packet. 790 | return network_send(request_socket, &response, sizeof(response)); 791 | } 792 | 793 | int ps2link_response_getstat(int result, unsigned int mode, unsigned int attr, unsigned int size, unsigned char *ctime, unsigned char *atime, unsigned char *mtime, unsigned int hisize) { 794 | struct { unsigned int number; unsigned short length; int result; unsigned int mode; unsigned int attr; unsigned int size; unsigned char ctime[8]; unsigned char atime[8]; unsigned char mtime[8]; unsigned int hisize; } PACKED response; 795 | 796 | // Build the response packet. 797 | response.number = htonl(PS2LINK_RESPONSE_GETSTAT); 798 | response.length = htons(sizeof(response)); 799 | response.result = htonl(result); 800 | response.mode = htonl(mode); 801 | response.attr = htonl(attr); 802 | response.size = htonl(size); 803 | if (ctime) { memcpy(response.ctime, ctime, 8); } 804 | if (atime) { memcpy(response.atime, atime, 8); } 805 | if (mtime) { memcpy(response.mtime, mtime, 8); } 806 | response.hisize = htonl(hisize); 807 | 808 | // Send the response packet. 809 | return network_send(request_socket, &response, sizeof(response)); 810 | } 811 | 812 | ////////////////////////////// 813 | // PS2LINK THREAD FUNCTIONS // 814 | ////////////////////////////// 815 | 816 | void *ps2link_thread_console(void *thread_id) { 817 | char buffer[1024]; 818 | 819 | // If the socket isn't open, this thread isn't needed. 820 | if (console_socket < 0) { pthread_exit(thread_id); } 821 | 822 | // Loop forever... 823 | for (;;) { 824 | 825 | // Wait for network activity. 826 | network_wait(console_socket, -1); 827 | 828 | // Receive the console buffer. 829 | network_receive(console_socket, buffer, sizeof(buffer)); 830 | 831 | // Print out the console buffer. 832 | printf("%s", buffer); 833 | 834 | // Clear the console buffer. 835 | memset(buffer, 0, sizeof(buffer)); 836 | 837 | // Reset the timeout counter. 838 | ps2link_counter = 0; 839 | 840 | } 841 | 842 | // End function. 843 | return NULL; 844 | 845 | } 846 | 847 | void *ps2link_thread_request(void *thread_id) { 848 | struct { unsigned int number; unsigned short length; char buffer[512]; } PACKED packet; 849 | 850 | // If the socket isn't open, this thread isn't needed. 851 | if (request_socket < 0) { pthread_exit(thread_id); } 852 | 853 | // Loop forever... 854 | for (;;) { 855 | 856 | // Wait for network activity. 857 | network_wait(request_socket, -1); 858 | 859 | // Read in the request packet header. 860 | network_receive_all(request_socket, &packet, 6); 861 | 862 | // Read in the rest of the packet. 863 | network_receive_all(request_socket, packet.buffer, ntohs(packet.length) - 6); 864 | 865 | // Perform the requested action. 866 | if (ntohl(packet.number) == PS2LINK_REQUEST_OPEN) { ps2link_request_open(&packet); } else 867 | if (ntohl(packet.number) == PS2LINK_REQUEST_CLOSE) { ps2link_request_close(&packet); } else 868 | if (ntohl(packet.number) == PS2LINK_REQUEST_READ) { ps2link_request_read(&packet); } else 869 | if (ntohl(packet.number) == PS2LINK_REQUEST_WRITE) { ps2link_request_write(&packet); } else 870 | if (ntohl(packet.number) == PS2LINK_REQUEST_LSEEK) { ps2link_request_lseek(&packet); } else 871 | if (ntohl(packet.number) == PS2LINK_REQUEST_OPENDIR) { ps2link_request_opendir(&packet); } else 872 | if (ntohl(packet.number) == PS2LINK_REQUEST_CLOSEDIR) { ps2link_request_closedir(&packet); } else 873 | if (ntohl(packet.number) == PS2LINK_REQUEST_READDIR) { ps2link_request_readdir(&packet); } else 874 | if (ntohl(packet.number) == PS2LINK_REQUEST_REMOVE) { ps2link_request_remove(&packet); } else 875 | if (ntohl(packet.number) == PS2LINK_REQUEST_MKDIR) { ps2link_request_mkdir(&packet); } else 876 | if (ntohl(packet.number) == PS2LINK_REQUEST_RMDIR) { ps2link_request_rmdir(&packet); } else 877 | if (ntohl(packet.number) == PS2LINK_REQUEST_GETSTAT) { ps2link_request_getstat(&packet); } 878 | 879 | // Reset the timeout counter. 880 | ps2link_counter = 0; 881 | 882 | } 883 | 884 | // End function. 885 | return NULL; 886 | 887 | } 888 | -------------------------------------------------------------------------------- /src/ps2link.h: -------------------------------------------------------------------------------- 1 | #ifndef __PS2LINK_H__ 2 | #define __PS2LINK_H__ 3 | 4 | /////////////////////// 5 | // PS2LINK FUNCTIONS // 6 | /////////////////////// 7 | 8 | int ps2link_connect(char *hostname); 9 | 10 | int ps2link_mainloop(int timeout); 11 | 12 | int ps2link_disconnect(void); 13 | 14 | /////////////////////////////// 15 | // PS2LINK COMMAND FUNCTIONS // 16 | /////////////////////////////// 17 | 18 | #define PS2LINK_COMMAND_RESET 0xBABE0201 19 | #define PS2LINK_COMMAND_EXECIOP 0xBABE0202 20 | #define PS2LINK_COMMAND_EXECEE 0xBABE0203 21 | #define PS2LINK_COMMAND_POWEROFF 0xBABE0204 22 | #define PS2LINK_COMMAND_SCRDUMP 0xBABE0205 23 | #define PS2LINK_COMMAND_NETDUMP 0xBABE0206 24 | #define PS2LINK_COMMAND_DUMPMEM 0xBABE0207 25 | #define PS2LINK_COMMAND_STARTVU 0xBABE0208 26 | #define PS2LINK_COMMAND_STOPVU 0xBABE0209 27 | #define PS2LINK_COMMAND_DUMPREG 0xBABE020A 28 | #define PS2LINK_COMMAND_GSEXEC 0xBABE020B 29 | #define PS2LINK_COMMAND_WRITEMEM 0xBABE020C 30 | #define PS2LINK_COMMAND_IOPEXCEP 0xBABE020D 31 | 32 | int ps2link_command_reset(void); 33 | 34 | int ps2link_command_execiop(int argc, char **argv); 35 | 36 | int ps2link_command_execee(int argc, char **argv); 37 | 38 | int ps2link_command_poweroff(void); 39 | 40 | int ps2link_command_scrdump(void); 41 | 42 | int ps2link_command_netdump(void); 43 | 44 | int ps2link_command_dumpmem(unsigned int offset, unsigned int size, char *pathname); 45 | 46 | int ps2link_command_startvu(int vu); 47 | 48 | int ps2link_command_stopvu(int vu); 49 | 50 | int ps2link_command_dumpreg(int type, char *pathname); 51 | 52 | int ps2link_command_gsexec(unsigned short size, char *pathname); 53 | 54 | int ps2link_command_writemem(unsigned int offset, unsigned int size, char *pathname); 55 | 56 | int ps2link_command_iopexcep(void); 57 | 58 | /////////////////////////////// 59 | // PS2LINK REQUEST FUNCTIONS // 60 | /////////////////////////////// 61 | 62 | #define PS2LINK_REQUEST_OPEN 0xBABE0111 63 | #define PS2LINK_REQUEST_CLOSE 0xBABE0121 64 | #define PS2LINK_REQUEST_READ 0xBABE0131 65 | #define PS2LINK_REQUEST_WRITE 0xBABE0141 66 | #define PS2LINK_REQUEST_LSEEK 0xBABE0151 67 | #define PS2LINK_REQUEST_OPENDIR 0xBABE0161 68 | #define PS2LINK_REQUEST_CLOSEDIR 0xBABE0171 69 | #define PS2LINK_REQUEST_READDIR 0xBABE0181 70 | #define PS2LINK_REQUEST_REMOVE 0xBABE0191 71 | #define PS2LINK_REQUEST_MKDIR 0xBABE01A1 72 | #define PS2LINK_REQUEST_RMDIR 0xBABE01B1 73 | #define PS2LINK_REQUEST_GETSTAT 0xBABE01C1 74 | 75 | int ps2link_request_open(void *packet); 76 | 77 | int ps2link_request_close(void *packet); 78 | 79 | int ps2link_request_read(void *packet); 80 | 81 | int ps2link_request_write(void *packet); 82 | 83 | int ps2link_request_lseek(void *packet); 84 | 85 | int ps2link_request_opendir(void *packet); 86 | 87 | int ps2link_request_closedir(void *packet); 88 | 89 | int ps2link_request_readdir(void *packet); 90 | 91 | int ps2link_request_remove(void *packet); 92 | 93 | int ps2link_request_mkdir(void *packet); 94 | 95 | int ps2link_request_rmdir(void *packet); 96 | 97 | //////////////////////////////// 98 | // PS2LINK RESPONSE FUNCTIONS // 99 | //////////////////////////////// 100 | 101 | #define PS2LINK_RESPONSE_OPEN 0xBABE0112 102 | #define PS2LINK_RESPONSE_CLOSE 0xBABE0122 103 | #define PS2LINK_RESPONSE_READ 0xBABE0132 104 | #define PS2LINK_RESPONSE_WRITE 0xBABE0142 105 | #define PS2LINK_RESPONSE_LSEEK 0xBABE0152 106 | #define PS2LINK_RESPONSE_OPENDIR 0xBABE0162 107 | #define PS2LINK_RESPONSE_CLOSEDIR 0xBABE0172 108 | #define PS2LINK_RESPONSE_READDIR 0xBABE0182 109 | #define PS2LINK_RESPONSE_REMOVE 0xBABE0192 110 | #define PS2LINK_RESPONSE_MKDIR 0xBABE01A2 111 | #define PS2LINK_RESPONSE_RMDIR 0xBABE01B2 112 | #define PS2LINK_RESPONSE_GETSTAT 0xBABE01C2 113 | 114 | int ps2link_response_open(int result); 115 | 116 | int ps2link_response_close(int result); 117 | 118 | int ps2link_response_read(int result, int size); 119 | 120 | int ps2link_response_write(int result); 121 | 122 | int ps2link_response_lseek(int result); 123 | 124 | int ps2link_response_opendir(int result); 125 | 126 | int ps2link_response_closedir(int result); 127 | 128 | int ps2link_response_readdir(int result, unsigned int mode, unsigned int attr, unsigned int size, unsigned char *ctime, unsigned char *atime, unsigned char *mtime, unsigned int hisize, char *name); 129 | 130 | int ps2link_response_remove(int result); 131 | 132 | int ps2link_response_mkdir(int result); 133 | 134 | int ps2link_response_rmdir(int result); 135 | 136 | int ps2link_response_getstat( 137 | int result, 138 | unsigned int mode, 139 | unsigned int attr, 140 | unsigned int size, 141 | unsigned char *ctime, 142 | unsigned char *atime, 143 | unsigned char *mtime, 144 | unsigned int hisize 145 | ); 146 | 147 | ////////////////////////////// 148 | // PS2LINK THREAD FUNCTIONS // 149 | ////////////////////////////// 150 | 151 | void *ps2link_thread_console(void *thread_id); 152 | 153 | void *ps2link_thread_request(void *thread_id); 154 | 155 | #endif 156 | -------------------------------------------------------------------------------- /src/ps2netfs.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #ifndef _WIN32 5 | #include 6 | #endif 7 | #include "utility.h" 8 | #include "network.h" 9 | #include "ps2netfs.h" 10 | 11 | int ps2netfs_socket = -1; 12 | 13 | //////////////////////// 14 | // PS2NETFS FUNCTIONS // 15 | //////////////////////// 16 | 17 | int ps2netfs_connect(char *hostname) { 18 | 19 | // Connect to the ps2netfs server. 20 | if ((ps2netfs_socket = network_connect(hostname, 0x4713, SOCK_STREAM)) < 0) { return -1; } 21 | 22 | // End function. 23 | return 0; 24 | 25 | } 26 | 27 | int ps2netfs_disconnect(void) { 28 | 29 | // Disconnect from request. 30 | if (network_disconnect(ps2netfs_socket) < 0) { return -1; } 31 | 32 | // End function. 33 | return 0; 34 | 35 | } 36 | 37 | //////////////////////////////// 38 | // PS2NETFS COMMAND FUNCTIONS // 39 | //////////////////////////////// 40 | 41 | int ps2netfs_command_open(char *pathname, int flags) { 42 | struct { unsigned int number; unsigned short length; int flags; char pathname[256]; } PACKED command; 43 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 44 | 45 | // Build the command packet. 46 | command.number = htonl(PS2NETFS_COMMAND_OPEN); 47 | command.length = htons(sizeof(command)); 48 | command.flags = htonl(flags); 49 | if (pathname) { strcpy(command.pathname, pathname); } 50 | 51 | // Send the command packet. 52 | if (network_send(ps2netfs_socket, &command, sizeof(command)) < 0) { return -1; } 53 | 54 | // Receive the response packet. 55 | if (network_receive_all(ps2netfs_socket, &response, sizeof(response)) < 0) { return -1; } 56 | 57 | // End function. 58 | return ntohl(response.result); 59 | 60 | } 61 | 62 | int ps2netfs_command_close(int fd) { 63 | struct { unsigned int number; unsigned short length; int fd; } PACKED command; 64 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 65 | 66 | // Build the command packet. 67 | command.number = htonl(PS2NETFS_COMMAND_CLOSE); 68 | command.length = htons(sizeof(command)); 69 | command.fd = htonl(fd); 70 | 71 | // Send the command packet. 72 | if (network_send(ps2netfs_socket, &command, sizeof(command)) < 0) { return -1; } 73 | 74 | // Receive the response packet. 75 | if (network_receive_all(ps2netfs_socket, &response, sizeof(response)) < 0) { return -1; } 76 | 77 | // End function. 78 | return ntohl(response.result); 79 | 80 | } 81 | 82 | int ps2netfs_command_read(int fd, void *buffer, int size) { 83 | struct { unsigned int number; unsigned short length; int fd, size; } PACKED command; 84 | struct { unsigned int number; unsigned short length; int result, size; } PACKED response; 85 | 86 | // Build the command packet. 87 | command.number = htonl(PS2NETFS_COMMAND_READ); 88 | command.length = htons(sizeof(command)); 89 | command.fd = htonl(fd); 90 | command.size = htonl(size); 91 | 92 | // Send the command packet. 93 | if (network_send(ps2netfs_socket, &command, sizeof(command)) < 0) { return -1; } 94 | 95 | // Receive the response packet. 96 | if (network_receive_all(ps2netfs_socket, &response, sizeof(response)) < 0) { return -1; } 97 | 98 | // Receive the response data. 99 | if (network_receive_all(ps2netfs_socket, buffer, ntohl(response.result)) < 0) { return -1; } 100 | 101 | // End function. 102 | return ntohl(response.result); 103 | 104 | } 105 | 106 | int ps2netfs_command_write(int fd, void *buffer, int size) { 107 | struct { unsigned int number; unsigned short length; int fd; int size; } PACKED command; 108 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 109 | 110 | // Build the command packet. 111 | command.number = htonl(PS2NETFS_COMMAND_WRITE); 112 | command.length = htons(sizeof(command)); 113 | command.fd = htonl(fd); 114 | command.size = htonl(size); 115 | 116 | // Send the command packet. 117 | if (network_send(ps2netfs_socket, &command, sizeof(command)) < 0) { return -1; } 118 | 119 | // Send the command data. 120 | if (network_send(ps2netfs_socket, buffer, size) < 0) { return -1; } 121 | 122 | // Receive the response packet. 123 | if (network_receive_all(ps2netfs_socket, &response, sizeof(response)) < 0) { return -1; } 124 | 125 | // End function. 126 | return ntohl(response.result); 127 | 128 | } 129 | 130 | int ps2netfs_command_lseek(int fd, int offset, int whence) { 131 | struct { unsigned int number; unsigned short length; int fd; int offset; int whence; } PACKED command; 132 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 133 | 134 | // Build the command packet. 135 | command.number = htonl(PS2NETFS_COMMAND_LSEEK); 136 | command.length = htons(sizeof(command)); 137 | command.fd = htonl(fd); 138 | command.offset = htonl(offset); 139 | command.whence = htonl(whence); 140 | 141 | // Send the command packet. 142 | if (network_send(ps2netfs_socket, &command, sizeof(command)) < 0) { return -1; } 143 | 144 | // Receive the response packet. 145 | if (network_receive_all(ps2netfs_socket, &response, sizeof(response)) < 0) { return -1; } 146 | 147 | // End function. 148 | return ntohl(response.result); 149 | 150 | } 151 | 152 | // ioctl - unimplemented 153 | 154 | int ps2netfs_command_delete(char *pathname, int flags) { 155 | struct { unsigned int number; unsigned short length; int flags; char pathname[256]; } PACKED command; 156 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 157 | 158 | // Build the command packet. 159 | command.number = htonl(PS2NETFS_COMMAND_DELETE); 160 | command.length = htons(sizeof(command)); 161 | command.flags = htonl(flags); 162 | if (pathname) { strncpy(command.pathname, pathname, 256); } 163 | 164 | // Send the command packet. 165 | if (network_send(ps2netfs_socket, &command, sizeof(command)) < 0) { return -1; } 166 | 167 | // Receive the response packet. 168 | if (network_receive_all(ps2netfs_socket, &response, sizeof(response)) < 0) { return -1; } 169 | 170 | // End function. 171 | return ntohl(response.result); 172 | 173 | } 174 | 175 | int ps2netfs_command_mkdir(char *pathname, int flags) { 176 | struct { unsigned int number; unsigned short length; int flags; char pathname[256]; } PACKED command; 177 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 178 | 179 | // Build the command packet. 180 | command.number = htonl(PS2NETFS_COMMAND_MKDIR); 181 | command.length = htons(sizeof(command)); 182 | command.flags = htonl(flags); 183 | if (pathname) { strncpy(command.pathname, pathname, 256); } 184 | 185 | // Send the command packet. 186 | if (network_send(ps2netfs_socket, &command, sizeof(command)) < 0) { return -1; } 187 | 188 | // Receive the response packet. 189 | if (network_receive_all(ps2netfs_socket, &response, sizeof(response)) < 0) { return -1; } 190 | 191 | // End function. 192 | return ntohl(response.result); 193 | 194 | } 195 | 196 | int ps2netfs_command_rmdir(char *pathname, int flags) { 197 | struct { unsigned int number; unsigned short length; int flags; char pathname[256]; } PACKED command; 198 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 199 | 200 | // Build the command packet. 201 | command.number = htonl(PS2NETFS_COMMAND_RMDIR); 202 | command.length = htons(sizeof(command)); 203 | command.flags = htonl(flags); 204 | if (pathname) { strncpy(command.pathname, pathname, 256); } 205 | 206 | // Send the command packet. 207 | if (network_send(ps2netfs_socket, &command, sizeof(command)) < 0) { return -1; } 208 | 209 | // Receive the response packet. 210 | if (network_receive_all(ps2netfs_socket, &response, sizeof(response)) < 0) { return -1; } 211 | 212 | // End function. 213 | return ntohl(response.result); 214 | 215 | } 216 | 217 | int ps2netfs_command_dopen(char *pathname, int flags) { 218 | struct { unsigned int number; unsigned short length; int flags; char pathname[256]; } PACKED command; 219 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 220 | 221 | // Build the command packet. 222 | command.number = htonl(PS2NETFS_COMMAND_DOPEN); 223 | command.length = htons(sizeof(command)); 224 | command.flags = htonl(flags); 225 | if (pathname) { strncpy(command.pathname, pathname, 256); } 226 | 227 | // Send the command packet. 228 | if (network_send(ps2netfs_socket, &command, sizeof(command)) < 0) { return -1; } 229 | 230 | // Receive the response packet. 231 | if (network_receive_all(ps2netfs_socket, &response, sizeof(response)) < 0) { return -1; } 232 | 233 | // End function. 234 | return ntohl(response.result); 235 | 236 | } 237 | 238 | int ps2netfs_command_dclose(int dd) { 239 | struct { unsigned int number; unsigned short length; int dd; } PACKED command; 240 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 241 | 242 | // Build the command packet. 243 | command.number = htonl(PS2NETFS_COMMAND_DCLOSE); 244 | command.length = htons(sizeof(command)); 245 | command.dd = htonl(dd); 246 | 247 | // Send the command packet. 248 | if (network_send(ps2netfs_socket, &command, sizeof(command)) < 0) { return -1; } 249 | 250 | // Receive the response packet. 251 | if (network_receive_all(ps2netfs_socket, &response, sizeof(response)) < 0) { return -1; } 252 | 253 | // End function. 254 | return ntohl(response.result); 255 | 256 | } 257 | 258 | int ps2netfs_command_dread(int dd, DIRENT *dirent) { 259 | struct { unsigned int number; unsigned short length; int dd; } PACKED command; 260 | struct { unsigned int number; unsigned short length; int result; DIRENT dirent; } PACKED response; 261 | 262 | // Build the command packet. 263 | command.number = htonl(PS2NETFS_COMMAND_DREAD); 264 | command.length = htons(sizeof(command)); 265 | command.dd = htonl(dd); 266 | 267 | // Send the command packet. 268 | if (network_send(ps2netfs_socket, &command, sizeof(command)) < 0) { return -1; } 269 | 270 | // Receive the response packet. 271 | if (network_receive_all(ps2netfs_socket, &response, sizeof(response)) < 0) { return -1; } 272 | 273 | // Save the response data. 274 | memcpy(dirent, &response.dirent, sizeof(DIRENT)); 275 | 276 | // End function. 277 | return ntohl(response.result); 278 | 279 | } 280 | 281 | // getstat - unimplemented 282 | 283 | // chstat - unimplemented 284 | 285 | // format - unimplemented 286 | 287 | // rename - unimplemented 288 | 289 | // chdir - unimplemented 290 | 291 | int ps2netfs_command_sync(char *device, int flags) { 292 | struct { unsigned int number; unsigned short length; int flags; char device[256]; } PACKED command; 293 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 294 | 295 | // Build the command packet. 296 | command.number = htonl(PS2NETFS_COMMAND_SYNC); 297 | command.length = htons(sizeof(command)); 298 | command.flags = htonl(flags); 299 | if (device) { strncpy(command.device, device, 256); } 300 | 301 | // Send the command packet. 302 | if (network_send(ps2netfs_socket, &command, sizeof(command)) < 0) { return -1; } 303 | 304 | // Receive the response packet. 305 | if (network_receive_all(ps2netfs_socket, &response, sizeof(response)) < 0) { return -1; } 306 | 307 | // End function. 308 | return ntohl(response.result); 309 | 310 | } 311 | 312 | int ps2netfs_command_mount(char *device, char *fsname, int flags, char *argv, int argc) { 313 | struct { unsigned int number; unsigned short length; char device[256], fsname[256]; int flags; char argv[256]; int argc; } PACKED command; 314 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 315 | 316 | // Build the command packet. 317 | command.number = htonl(PS2NETFS_COMMAND_MOUNT); 318 | command.length = htons(sizeof(command)); 319 | command.flags = htonl(flags); 320 | command.argc = htonl(argc); 321 | if (device) { strncpy(command.device, device, 256); } 322 | if (fsname) { strncpy(command.fsname, fsname, 256); } 323 | if (argv) { strncpy(command.argv, argv, 256); } 324 | 325 | // Send the command packet. 326 | if (network_send(ps2netfs_socket, &command, sizeof(command)) < 0) { return -1; } 327 | 328 | // Receive the response packet. 329 | if (network_receive_all(ps2netfs_socket, &response, sizeof(response)) < 0) { return -1; } 330 | 331 | // End function. 332 | return ntohl(response.result); 333 | 334 | } 335 | 336 | int ps2netfs_command_umount(char *device, int flags) { 337 | struct { unsigned int number; unsigned short length; int flags; char device[256]; } PACKED command; 338 | struct { unsigned int number; unsigned short length; int result; } PACKED response; 339 | 340 | // Build the command packet. 341 | command.number = htonl(PS2NETFS_COMMAND_UMOUNT); 342 | command.length = htons(sizeof(command)); 343 | if (device) { strncpy(command.device, device, 256); } 344 | 345 | // Send the command packet. 346 | if (network_send(ps2netfs_socket, &command, sizeof(command)) < 0) { return -1; } 347 | 348 | // Receive the response packet. 349 | if (network_receive_all(ps2netfs_socket, &response, sizeof(response)) < 0) { return -1; } 350 | 351 | // End function. 352 | return ntohl(response.result); 353 | 354 | } 355 | 356 | // lseek64 - unimplemented 357 | 358 | // devctl - unimplemented 359 | 360 | // symlink - unimplemented 361 | 362 | // readlink - unimplemented 363 | 364 | // ioctl2 - unimplemented 365 | 366 | // info - unimplemented 367 | 368 | // fstype - unimplemented 369 | 370 | int ps2netfs_command_devlist(char *pathname, int flags, char *devlist) { 371 | struct { unsigned int number; unsigned short length; int flags; char pathname[256]; } PACKED command; 372 | struct { unsigned int number; unsigned short length; int result; int count; char devlist[256]; } PACKED response; 373 | 374 | // Build the command packet. 375 | command.number = htonl(PS2NETFS_COMMAND_DEVLIST); 376 | command.length = htons(sizeof(command)); 377 | command.flags = htonl(flags); 378 | if (pathname) { strncpy(command.pathname, pathname, 256); } 379 | 380 | // Send the command packet. 381 | if (network_send(ps2netfs_socket, &command, sizeof(command)) < 0) { return -1; } 382 | 383 | // Receive the response packet. 384 | if (network_receive_all(ps2netfs_socket, &response, sizeof(response)) < 0) { return -1; } 385 | 386 | // Save the response data. 387 | memcpy(devlist, response.devlist, 256); 388 | 389 | // End function. 390 | return ntohl(response.result); 391 | 392 | } 393 | -------------------------------------------------------------------------------- /src/ps2netfs.h: -------------------------------------------------------------------------------- 1 | #ifndef __PS2NETFS_H__ 2 | #define __PS2NETFS_H__ 3 | 4 | // Open flags. 5 | #define OPEN_READ 0x0001 6 | #define OPEN_WRITE 0x0002 7 | #define OPEN_NONBLOCK 0x0010 8 | #define OPEN_APPEND 0x0100 9 | #define OPEN_CREATE 0x0200 10 | #define OPEN_TRUNCATE 0x0400 11 | 12 | // Lseek flags. 13 | #define LSEEK_SET 0x0000 14 | #define LSEEK_CURRENT 0x0001 15 | #define LSEEK_END 0x0002 16 | 17 | // Mount flags. 18 | #define MOUNT_READWRITE 0x0000 19 | #define MOUNT_READONLY 0x0001 20 | 21 | // Dread structure. 22 | typedef struct { int mode, attr, size; char ctime[8], atime[8], mtime[8]; int hisize; char name[256]; } DIRENT; 23 | 24 | //////////////////////// 25 | // PS2NETFS FUNCTIONS // 26 | //////////////////////// 27 | 28 | int ps2netfs_connect(char *hostname); 29 | 30 | int ps2netfs_disconnect(void); 31 | 32 | //////////////////////////////// 33 | // PS2NETFS COMMAND FUNCTIONS // 34 | //////////////////////////////// 35 | 36 | #define PS2NETFS_COMMAND_OPEN 0xBEEF8011 37 | #define PS2NETFS_COMMAND_CLOSE 0xBEEF8021 38 | #define PS2NETFS_COMMAND_READ 0xBEEF8031 39 | #define PS2NETFS_COMMAND_WRITE 0xBEEF8041 40 | #define PS2NETFS_COMMAND_LSEEK 0xBEEF8051 41 | #define PS2NETFS_COMMAND_IOCTL 0xBEEF8061 42 | #define PS2NETFS_COMMAND_DELETE 0xBEEF8071 43 | #define PS2NETFS_COMMAND_MKDIR 0xBEEF8081 44 | #define PS2NETFS_COMMAND_RMDIR 0xBEEF8091 45 | #define PS2NETFS_COMMAND_DOPEN 0xBEEF80A1 46 | #define PS2NETFS_COMMAND_DCLOSE 0xBEEF80B1 47 | #define PS2NETFS_COMMAND_DREAD 0xBEEF80C1 48 | #define PS2NETFS_COMMAND_GETSTAT 0xBEEF80D1 49 | #define PS2NETFS_COMMAND_CHSTAT 0xBEEF80E1 50 | #define PS2NETFS_COMMAND_FORMAT 0xBEEF80F1 51 | #define PS2NETFS_COMMAND_RENAME 0xBEEF8111 52 | #define PS2NETFS_COMMAND_CHDIR 0xBEEF8121 53 | #define PS2NETFS_COMMAND_SYNC 0xBEEF8031 54 | #define PS2NETFS_COMMAND_MOUNT 0xBEEF8041 55 | #define PS2NETFS_COMMAND_UMOUNT 0xBEEF8051 56 | #define PS2NETFS_COMMAND_LSEEK64 0xBEEF8161 57 | #define PS2NETFS_COMMAND_DEVCTL 0xBEEF8171 58 | #define PS2NETFS_COMMAND_SYMLINK 0xBEEF8181 59 | #define PS2NETFS_COMMAND_READLINK 0xBEEF8191 60 | #define PS2NETFS_COMMAND_IOCTL2 0xBEEF81A1 61 | #define PS2NETFS_COMMAND_INFO 0xBEEF8F01 62 | #define PS2NETFS_COMMAND_FSTYPE 0xBEEF8F11 63 | #define PS2NETFS_COMMAND_DEVLIST 0xBEEF8F21 64 | 65 | int ps2netfs_command_open(char *pathname, int flags); 66 | 67 | int ps2netfs_command_close(int fd); 68 | 69 | int ps2netfs_command_read(int fd, void *buffer, int size); 70 | 71 | int ps2netfs_command_write(int fd, void *buffer, int size); 72 | 73 | int ps2netfs_command_lseek(int fd, int offset, int whence); 74 | 75 | // ioctl - unimplemented 76 | 77 | int ps2netfs_command_delete(char *pathname, int flags); 78 | 79 | int ps2netfs_command_mkdir(char *pathname, int flags); 80 | 81 | int ps2netfs_command_rmdir(char *pathname, int flags); 82 | 83 | int ps2netfs_command_dopen(char *pathname, int flags); 84 | 85 | int ps2netfs_command_dclose(int dd); 86 | 87 | int ps2netfs_command_dread(int dd, DIRENT *dirent); 88 | 89 | // getstat - unimplemented 90 | 91 | // chstat - unimplemented 92 | 93 | // format - unimplemented 94 | 95 | // rename - unimplemented 96 | 97 | // chdir - unimplemented 98 | 99 | int ps2netfs_command_sync(char *device, int flags); 100 | 101 | int ps2netfs_command_mount(char *device, char *fsname, int flags, char *argv, int argc); 102 | 103 | int ps2netfs_command_umount(char *device, int flags); 104 | 105 | // lseek64 - unimplemented 106 | 107 | // devctl - unimplemented 108 | 109 | // symlink - unimplemented 110 | 111 | // readlink - unimplemented 112 | 113 | // ioctl2 - unimplemented 114 | 115 | // info - unimplemented 116 | 117 | // fstype - unimplemented 118 | 119 | int ps2netfs_command_devlist(char *pathname, int flags, char *devlist); 120 | 121 | #endif 122 | -------------------------------------------------------------------------------- /src/utility.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include "utility.h" 7 | 8 | /////////////////////// 9 | // UTILITY FUNCTIONS // 10 | /////////////////////// 11 | 12 | int fix_flags(int flags) { int result = 0; 13 | 14 | // Fix the flags. 15 | if (flags & 0x0001) { result |= O_RDONLY; } 16 | if (flags & 0x0002) { result |= O_WRONLY | O_TRUNC; } // FIXME: Truncate is needed for some programs. 17 | #ifndef _WIN32 18 | if (flags & 0x0010) { result |= O_NONBLOCK; } 19 | #endif 20 | if (flags & 0x0100) { result |= O_APPEND; } 21 | if (flags & 0x0200) { result |= O_CREAT; } 22 | if (flags & 0x0400) { result |= O_TRUNC; } 23 | 24 | #ifdef _WIN32 25 | 26 | // Binary mode file access. 27 | result |= O_BINARY; 28 | 29 | #endif 30 | 31 | // End function. 32 | return result; 33 | 34 | } 35 | 36 | int fix_pathname(char *pathname) { int loop0 = 0; 37 | 38 | // If empty, set a pathname default. 39 | if (pathname[0] == 0) { strcpy(pathname, "."); } 40 | 41 | // Convert \ to / for unix compatibility. 42 | for (loop0=0; loop0 [arguments]\n\n"); 89 | printf(" Available commands:\n\n"); 90 | printf(" reset\n"); 91 | printf(" execiop [arguments]\n"); 92 | printf(" execee [arguments]\n"); 93 | printf(" poweroff\n"); 94 | printf(" scrdump\n"); 95 | printf(" netdump\n"); 96 | printf(" dumpmem \n"); 97 | printf(" startvu \n"); 98 | printf(" stopvu \n"); 99 | printf(" dumpreg \n"); 100 | printf(" gsexec \n"); 101 | printf(" writemem \n"); 102 | printf(" iopexcep\n"); 103 | printf(" listen\n\n"); 104 | 105 | // Print out the fsclient usage string. 106 | printf(" Usage: fsclient [-h hostname] [arguments]\n\n"); 107 | printf(" Available commands:\n\n"); 108 | printf(" copyfrom \n"); 109 | printf(" copyto \n"); 110 | printf(" delete \n"); 111 | printf(" devlist\n"); 112 | printf(" dir \n"); 113 | printf(" mkdir \n"); 114 | printf(" mount \n"); 115 | printf(" rmdir \n"); 116 | printf(" sync \n"); 117 | printf(" umount \n\n"); 118 | 119 | // End function. 120 | return 0; 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/utility.h: -------------------------------------------------------------------------------- 1 | #ifndef __UTILITY_H__ 2 | #define __UTILITY_H__ 3 | 4 | #define PACKED __attribute__((packed)) 5 | 6 | /////////////////////// 7 | // UTILITY FUNCTIONS // 8 | /////////////////////// 9 | 10 | int fix_flags(int flags); 11 | 12 | int fix_pathname(char *pathname); 13 | 14 | int fix_argv(char *destination, char **argv); 15 | 16 | int print_usage(void); 17 | 18 | #endif 19 | --------------------------------------------------------------------------------