Sign in Join
Wiki copytemporary

PlayStation 1: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: PlayStation 1

OldNewLine
1+## Overview
2+
3+Every Instruction on this page is for Linux.
4+
5+The PlayStation 1 port is currently under development in the Git "main" branch.
6+
7+If I use the word PSX it is equivalent to the PlayStation 1.
8+
9+## Requirements
10+
11+### GNU BinUtils
12+
13+Compiler needs GNU Binutils. Download a recent version from <https://ftp.gnu.org/gnu/binutils/> . Then run shell commands:
14+```
15+./tar -xf <binutils.tar.gz>
16+ ./cd <binutils>
17+ ./mkdir build
18+ ./cd build
19+ ../configure --prefix=/usr/local/mipsel-unknown-elf --target=mipsel-unknown-elf --with-float=soft
20+ make -j$(nproc)
21+ sudo make install
22+ export PATH="/usr/local/mipsel-unknown-elf/bin:$PATH"
23+```
24+
25+Now you can go two ways:
26+
27+1) Let the binaries as they are and always use the compiler option
28+```
29+-XP/usr/local/mipsel-unknown-elf/bin/mipsel-unknown-elf-
30+```
31+
32+
33+2) Create symlinks
34+```
35+sudo ln -s /usr/local/mipsel-unknown-elf/bin/mipsel-unknown-elf-as /usr/bin/mipsel-ps1-as
36+ sudo ln -s /usr/local/mipsel-unknown-elf/bin/mipsel-unknown-elf-ld /usr/bin/mipsel-ps1-ld
37+ sudo ln -s /usr/local/mipsel-unknown-elf/bin/mipsel-unknown-elf-objcopy /usr/bin/mipsel-ps1-objcopy
38+```
39+
40+### PSY-Q-SDK
41+
42+To compile something You need the converted PSY-Q-SDK to the ELF format
43+
44+You can go two ways:
45+
46+1) Clone it directly
47+```
48+git clone <https://key-real@git.code.sf.net/p/psy-q-sdk-elf/code> psy-q-sdk
49+```
50+
51+2) Use the original and convert it by your self
52+
53+\- Download the official SDK:
54+
55+<https://www.psxdev.net/downloads.html>
56+
57+\- Download the converter:
58+
59+<https://gitlab.com/jype/psyq2elf>
60+
61+
62+from now on I assume the SDK is in following Folder:
63+```
64+/home/ps1/psy-q-sdk
65+```
66+
67+### Real Hardware
68+
69+You need a PlayStation 1 with the MOD CHIP.
70+
71+### Emulator
72+
73+\- I recommend to use PCSX-REDUX <https://github.com/grumpycoders/pcsx-redux>
74+
75+(I use Arch Linux and it is in my AUR Repo: pcsx-redux-git)
76+
77+
78+\- DuckStation <https://github.com/stenzek/duckstation?tab=readme-ov-file#downloading-and-running>
79+
80+(I use Arch Linux and it is in my AUR Repo: duckstation-git)
81+
82+
83+\- ePSXe <https://www.epsxe.com/>
84+
85+(I use Arch Linux and it is in my AUR Repo: epsxe)
86+
87+
88+
89+#### PSX BIOS
90+
91+You can use
92+
93+a) the original Sony BIOS:
94+
95+<https://gist.github.com/juanbrujo/cf55d223ad01927a48f9ebac9f50bdee>
96+
97+b) OpenBIOS from the PCSX-REDUX project:
98+
99+<https://github.com/grumpycoders/pcsx-redux/tree/main/src/mips/openbios>
100+
101+## Building
102+
103+1) Get the newest version of FPC trunk:
104+```
105+git clone <https://gitlab.com/freepascal.org/fpc/source.git> fpc
106+```
107+
108+2) Compile and install the the compiler:
109+```
110+make clean
111+```
112+
113+If you created the symlinks to the mipsel binutils just do:
114+```
115+sudo make crossinstall OS_TARGET=ps1 CPU_TARGET=mipsel
116+```
117+
118+If not do:
119+```
120+sudo make crossinstall OS_TARGET=ps1 CPU_TARGET=mipsel CROSSOPT="-XP/usr/local/mipsel-unknown-elf/bin/mipsel-unknown-elf-"
121+```
122+
123+## Compiling programs
124+
125+When compiling programs, you should always enable smartlinking by adding an option to the compiler:
126+```
127+-XX
128+```
129+
130+and you have to specify the path to the PSY-Q-SDK:
131+```
132+-Fl/home/ps1/psy-q-sdk
133+```
134+
135+so your compile command should look like this:
136+```
137+ppcrossmipsel test.pas -Tps1 -XX -Fl/home/ps1/psy-q-sdk
138+```
139+
140+or if you have no symlinks to binutils:
141+```
142+ppcrossmipsel test.pas -Tps1 -XX -Fl/home/ps1/psy-q-sdk -XP/usr/local/mipsel-unknown-elf/bin/mipsel-unknown-elf-
143+```
144+
145+### Hello World example
146+```
147+{$MODE OBJFPC}
148+ uses libstd;
149+ begin
150+
151+ printf('HELLO from FPC'#10);
152+
153+ end.
154+```
155+
156+Here's what this program produces in the PCSX-Redux emulator when You switch MainMenu->Debug->Show Logs:
157+```
158+HELLO from FPC
159+```
160+
161+### Cube example
162+```
163+{$MODE OBJFPC}
164+ uses libstd, libetc, libgpu, libgte;
165+
166+ const
167+ MODE_NTSC = 0;
168+ MODE_PAL = 1;
169+
170+ OTSIZE = 4096; // Ordering table size
171+
172+ vertices : array [0..7] of SVECTOR = ( // Cube
173+ (vx: -128; vy: -128; vz: -128; pad: 0 ),
174+ (vx: 128; vy: -128; vz: -128; pad: 0 ),
175+ (vx: 128; vy: -128; vz: 128; pad: 0 ),
176+ (vx: -128; vy: -128; vz: 128; pad: 0 ),
177+ (vx: -128; vy: 128; vz: -128; pad: 0 ),
178+ (vx: 128; vy: 128; vz: -128; pad: 0 ),
179+ (vx: 128; vy: 128; vz: 128; pad: 0 ),
180+ (vx: -128; vy: 128; vz: 128; pad: 0 ));
181+
182+ faces : array [0..35] of smallint = ( // Cube
183+ 0, 3, 2, // top
184+ 0, 2, 1, // top
185+ 4, 0, 1, // front
186+ 4, 1, 5, // front
187+ 7, 4, 5, // bottom
188+ 7, 5, 6, // bottom
189+ 5, 1, 2, // right
190+ 5, 2, 6, // right
191+ 2, 3, 7, // back
192+ 2, 7, 6, // back
193+ 0, 4, 7, // left
194+ 0, 7, 3 // left
195+ );
196+
197+
198+ type
199+
200+ DoubleBuff = packed record // Screen
201+ draw : DRAWENV;
202+ disp : DISPENV;
203+ ot : array[0..OTSIZE] of dword; // Ordering table
204+ end;
205+
206+
207+ var
208+
209+ screen : array [0..1] of DoubleBuff; // Struct to hold the display & draw buffers
210+ currbuff : byte; // Holds the current buffer number (0 or 1)
211+
212+ i : longint;
213+ otz : longint; // Current Ordering table Entry
214+
215+ poly : array [0..11] of POLY_G3; // Cube
216+
217+ rotation : SVECTOR;
218+ translation : VECTOR;
219+ transform : MATRIX;
220+
221+ p : pointer;
222+ flg : pointer;
223+ nclip : longint; // Is cliped?
224+
225+
226+ procedure setRGB0(var c: DRAWENV; r, g, b: byte);
227+ begin
228+ c.r0:=r;
229+ c.g0:=g;
230+ c.b0:=b;
231+ end;
232+
233+
234+ procedure ScreenInit(width, height: dword);
235+ var
236+ mode : byte;
237+
238+ begin
239+
240+ // Init
241+ ResetGraph(0);
242+ InitGeom();
243+
244+ SetGraphDebug(0);
245+
246+ // Set Display Mode
247+ if height = 240 then mode:= MODE_NTSC;
248+ if height = 256 then mode:= MODE_PAL;
249+ SetVideoMode(mode);
250+
251+ // Init Buffers
252+ SetDefDispEnv(@screen[0].disp, 0, 0, width, height);
253+ SetDefDispEnv(@screen[1].disp, 0, height, width, height);
254+
255+ SetDefDrawEnv(@screen[0].draw, 0, height, width, height);
256+ SetDefDrawEnv(@screen[1].draw, 0, 0, width, height);
257+
258+ // Set screen Offset
259+ screen[0].disp.screen.x:= 0;
260+ screen[0].disp.screen.y:= 0;
261+ screen[1].disp.screen.x:= 0;
262+ screen[1].disp.screen.y:= 0;
263+
264+ screen[0].disp.screen.h:= height;
265+ screen[0].disp.screen.w:= 0;
266+ screen[1].disp.screen.h:= height;
267+ screen[1].disp.screen.w:= 0;
268+
269+ // Enable background clearing
270+ screen[0].draw.isbg:= 1;
271+ screen[1].draw.isbg:= 1;
272+
273+ // Set the background clear color
274+ setRGB0(screen[0].draw, 0, 0, 0);
275+ setRGB0(screen[1].draw, 0, 0, 0);
276+
277+
278+ // Initialize and setup the GTE geometry offsets
279+ SetGeomOffset(width div 2, height div 2);
280+ SetGeomScreen(100);
281+
282+ SetDispMask(1);
283+
284+ // Set the current initial buffer
285+ currbuff:= 0;
286+ PutDispEnv(@screen[currbuff].disp);
287+ PutDrawEnv(@screen[currbuff].draw);
288+
289+ end;
290+
291+
292+ procedure DisplayFrame;
293+ begin
294+
295+ // Set the current display & draw buffers
296+ PutDispEnv(@screen[currbuff].disp);
297+ PutDrawEnv(@screen[currbuff].draw);
298+
299+ // Draw Primetive
300+ DrawOTag(@screen[currbuff].ot[OTSIZE - 1]);
301+
302+ // Draw Font
303+ FntFlush(-1);
304+
305+ if currbuff = 0 then currbuff:= 1 else currbuff:= 0;
306+
307+ // Sync and wait for vertical blank
308+ DrawSync(0);
309+ VSync(0);
310+
311+ end;
312+
313+
314+ begin
315+
316+ ScreenInit(320, 256);
317+
318+ // Setup Font
319+ FntLoad(960, 256);
320+ SetDumpFnt(FntOpen(0, 100, 200, 200, 0, 512));
321+
322+ rotation.vx:= 0;
323+ rotation.vy:= 0;
324+ rotation.vz:= 0;
325+
326+ translation.vx:= 0;
327+ translation.vy:= 0;
328+ translation.vz:= 500;
329+
330+ repeat
331+
332+ // Clear Ordering table
333+ ClearOTagR(@screen[currbuff].ot[currbuff], OTSIZE);
334+
335+ // Transform
336+ rotation.vx += 6;
337+ rotation.vy += 8;
338+ rotation.vz += 12;
339+
340+ RotMatrix(@rotation, @transform);
341+ TransMatrix(@transform, @translation);
342+
343+ SetRotMatrix(@transform);
344+ SetTransMatrix(@transform);
345+
346+ // Draw Polys
347+ for i:= 0 to 11 do begin
348+ setPolyG3(@poly[i]);
349+
350+ poly[i].r0:= 255; poly[i].g0:=0; poly[i].b0:= 0;
351+ poly[i].r1:= 0; poly[i].g1:=255; poly[i].b1:= 0;
352+ poly[i].r2:= 0; poly[i].g2:=0; poly[i].b2:= 255;
353+
354+ nclip:= RotAverageNclip3(@vertices[faces[i * 3 + 0]], @vertices[faces[i * 3 + 1]], @vertices[faces[i * 3 + 2]], @poly[i].x0, @poly[i].x1, @poly[i].x2, @p, @otz, @flg);
355+ if nclip <= 0 then continue;
356+
357+ if (otz > 0) and (otz < OTSIZE) then addPrim(@screen[currbuff].ot[otz], @poly[i]);
358+ end;
359+
360+
361+ FntPrint('Hello from FPC');
362+
363+ DisplayFrame;
364+
365+ until false;
366+
367+ end.
368+```
369+
370+Here's what this program produces in the PCSX-Redux emulator:
371+
372+[![psx-cube.jpg](/wiki-images/d/d9/psx-cube.jpg)](</File:psx-cube.jpg>)
373+
374+## Create a PSX .iso
375+
376+You need:
377+
378+<https://github.com/Lameguy64/mkpsxiso>
379+
380+and run:
381+```
382+mkpsxiso iso.xml
383+```
384+
385+File iso.xml:
386+```
387+<?xml version="1.0" encoding="UTF-8"?>
388+ <iso_project image_name="myimage.iso" cue_sheet="myimage.cue">
389+ <track type="data">
390+ <identifiers system="PLAYSTATION" application="PLAYSTATION" volume="MYDISC" volume_set="MYDISC" publisher="MYPUBLISHER" data_preparer="MKPSXISO"/>
391+ <directory_tree>
392+ <file name="system.cnf" type="data" source="system.cnf"/>
393+ <file name="MAIN.PSX-EXE" type="data" source="test.psx-exe"/>
394+ </directory_tree>
395+ </track>
396+ </iso_project>
397+```
398+
399+File system.cnf:
400+```
401+BOOT=cdrom:\MAIN.PSX-EXE;1
402+ TCB=4
403+ EVENT=10
404+ STACK=801FFFF0
405+```
406+
407+this file describes the boot process.
408+
409+# Information Sources
410+
411+\- full specification: <https://psx-spx.consoledev.net/>
412+
413+\- Psy-Q-SDK reference doc: <https://psx.arthus.net/sdk/Psy-Q/DOCS/LibRef47.pdf>
414+
415+\- MIPS Assembly: <https://www.cs.unibo.it/~solmi/teaching/arch_2002-2003/AssemblyLanguageProgDoc.pdf>
416+
417+\- Cool Course: <https://pikuma.com/courses/ps1-programming-mips-assembly-language>
418+
419+\- Discord Server: PSX.Dev
420+
421+---
422+*From the Free Pascal wiki, page "PlayStation 1", as the Internet Archive kept it on 2026-02-10, last changed on 2024-11-10. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history