PS1 Programming with MIPS Assembly & C
This course is a deep dive into the world of PlayStation programming! We'll explore the PS1 hardware, understand its sub-components, and learn how to code games using MIPS assembler & the C programming language. We'll also learn how to use a PS1 SDK library paired with a modern development toolchain to be more productive and push fast polygons out of our console.
More
We are about to enter the 5th generation of 32-bit consoles. This era brings with it many technology milestones, such as the adoption of CPUs based on RISC architecture and a preference for coding using a high-level language instead of writing games using plain assembly. We will start by learning the basics of MIPS assembly and evolve to use a C compiler with a PS1 SDK to develop our final project.
The tools you'll need
The original SDK was designed for Windows/PC, so you can either use the original 16/32-bit libraries on a 32-bit operating system (Windowx XP), or you can use a modern C compiler with Visual Studio Code on a 64-bit operating system (Windows 10/11). Emulating a Windows system on macOS or Linux is also possible!
Do I need a real PS1?
Not at all. You can easily run all the exercises and the final project on a PlayStation emulator. At the end, we will burn a CD ISO and test it on a real console, but that's optional.
Is this course for you?
This is a self-contained course teaching concepts from the ground up. However, it is expected from students a basic understanding of coding (if-else, loops, functions). If you like retro programming & want to learn more about the early days of 3D games, then this course is definitely for you!
Watch Online PS1 Programming with MIPS Assembly & C
# | Title | Duration |
---|---|---|
1 | Starting our Journey | 12:19 |
2 | How to Take this Course | 02:59 |
3 | Placing the PlayStation in History | 10:50 |
4 | PS1 Hardware Overview | 14:10 |
5 | The MIPS CPU | 09:54 |
6 | Memory & Endianness | 07:41 |
7 | Memory Map | 12:13 |
8 | CPU Registers & Load Instructions | 15:53 |
9 | Store, Add, & Subtract Instructions | 07:11 |
10 | Jump & Branch Instructions | 07:03 |
11 | Exercise: Our First MIPS Code | 02:47 |
12 | Going Over Our First MIPS Code | 05:11 |
13 | Installing the ARMIPS Assembler | 06:38 |
14 | Assembling our MIPS Code | 04:09 |
15 | PSX-EXE File Format | 04:43 |
16 | Emulator & Step-By-Step Execution | 08:03 |
17 | Fixing Off-By-One Error | 03:05 |
18 | Pseudo-Instructions | 07:53 |
19 | The MIPS Pipeline | 11:00 |
20 | Some Warm Up Exercises | 06:57 |
21 | Solving our Warm Up Exercises | 15:08 |
22 | Register Shorthand | 04:57 |
23 | Factorial Exercise | 05:40 |
24 | Solving our Factorial Exercise | 08:57 |
25 | Factorial Subroutine | 10:54 |
26 | Negative Numbers | 11:45 |
27 | Sign Extension | 06:24 |
28 | Logical Instructions | 06:07 |
29 | Bitshifting Instructions | 09:30 |
30 | Examples of CISC & RISC Machines | 06:46 |
31 | CISC vs RISC Instructions | 15:46 |
32 | The PlayStation Graphics System | 16:42 |
33 | Drawing Primitives | 05:10 |
34 | GPU Packets | 11:30 |
35 | Sending Display Control Packets to GP1 | 19:03 |
36 | Sending VRAM Access Packets to GP0 | 07:01 |
37 | Clear Display Area | 06:35 |
38 | Drawing a Flat-Shaded Triangle | 04:35 |
39 | Drawing a Flat-Shaded Quad | 02:39 |
40 | Drawing a Gouraud-Shaded Triangle | 01:54 |
41 | Flat-Shaded Triangle Subroutine | 13:08 |
42 | Coding our Flat Triangle Subroutine | 04:36 |
43 | Stack & Stack Pointer | 11:17 |
44 | Stack Parameters | 07:24 |
45 | Stack & Heap Space | 05:16 |
46 | Variables | 07:38 |
47 | Variable Alignment | 06:20 |
48 | Vector Alignment | 13:32 |
49 | Copying Image Data to VRAM | 24:40 |
50 | Using Bitshifting to Multiply & Divide | 06:57 |
51 | 24BPP Display Mode | 14:38 |
52 | Taking Advantage of our Delay Slots | 06:33 |
53 | Moving from MIPS Assembly to C | 05:37 |
54 | Installing Tools on Windows 11 | 14:17 |
55 | Installing Tools on Windows XP | 19:31 |
56 | Compiling a Simple Psy-Q Project | 12:38 |
57 | Double-Buffer Screen | 28:44 |
58 | Psy-Q Integer Data Types | 04:10 |
59 | Psy-Q Primitive Types | 07:30 |
60 | Ordering Table & Primitive Buffer | 17:27 |
61 | Sorting Primitives into the OT | 15:13 |
62 | Sorting a Gouraud Quad into the OT | 05:47 |
63 | A Review of Pointers | 12:14 |
64 | The Arrow Operator | 11:38 |
65 | A Review of 3D Projection | 15:39 |
66 | Vertices & Face Indices | 12:24 |
67 | The Geometry Transformation Engine | 07:11 |
68 | Basic 3D Transformations | 10:05 |
69 | RotTransPers Function | 15:21 |
70 | Coding a Rotating 3D Cube | 14:27 |
71 | Normal Clip | 06:33 |
72 | Coding Quads as Cube Faces | 03:12 |
73 | Reviewing Floating-Point Numbers | 15:10 |
74 | Fixed-Point Numbers | 15:28 |
75 | Implementing a Bouncing Cube | 10:52 |
76 | Different Transform Matrix per Object | 16:11 |
77 | Wait, Can I use Floats? | 02:50 |
78 | GTE Register Set | 10:25 |
79 | Inline GTE Instructions | 15:19 |
80 | RTPT vs. RTPS | 08:36 |
81 | Reading Joypad State | 17:36 |
82 | Joypad Input with BIOS Functions | 17:05 |
83 | Joypad Header & Implementation | 22:16 |
84 | Header File for OT & Primitive Buffer | 25:41 |
85 | Header File for Display Routines | 06:04 |
86 | Camera Space | 10:51 |
87 | The Look-At Transformation | 15:23 |
88 | The LookAt Function | 16:21 |
89 | Coding the Look-At Camera Model | 20:58 |
90 | CD-ROM Basics | 21:32 |
91 | Generating an ISO on Windows XP | 14:35 |
92 | Generating an ISO on Windows 11 | 09:19 |
93 | A Function to Read Files from the CD | 21:07 |
94 | Understanding the MODEL.BIN File | 07:07 |
95 | Dynamically Allocating Buffers | 08:23 |
96 | Heap Initialization on Windows 11 | 07:06 |
97 | Interpreting Bytes as Numbers | 15:03 |
98 | Handling Different Order of Bytes | 09:40 |
99 | Reading Vertices & Faces from a File | 13:20 |
100 | UV Coordinates, TPAGE, & CLUT | 17:28 |
101 | Installing TIM Tool | 03:18 |
102 | TIM File Format | 10:39 |
103 | Read TIM File from the CD | 19:42 |
104 | Textured Cube Faces | 17:44 |
105 | Wobbly Textures | 12:24 |
106 | Polygon Jitter | 02:54 |
107 | Dev Tools CD Samples | 08:33 |
108 | Intro to our Final Project | 09:04 |
109 | Importing Project Assets | 03:54 |
110 | PRM File Layout | 13:38 |
111 | Reading Object Name from PRM File | 14:35 |
112 | Reading Vertices from PRM File | 10:27 |
113 | Handling Different Primitive Types | 22:50 |
114 | Reading Primitives from PRM File | 13:23 |
115 | Drawing Flat-Shaded Object Faces | 24:45 |
116 | Using sizeof with Variable Name | 03:00 |
117 | CMP File Layout | 11:01 |
118 | Reading Number of Textures from File | 06:51 |
119 | Reading TIM Sizes from File | 12:32 |
120 | A Function to Extract LZSS Data | 10:47 |
121 | Texture Structs | 15:12 |
122 | Uploading CMP Textures to VRAM | 18:59 |
123 | Global Texture Store Array | 13:51 |
124 | Rendering Textured Triangles | 06:44 |
125 | Visualizing Textured 3D Objects | 06:56 |
126 | Loading Multiple CMP Files | 11:40 |
127 | Exercise: Linked List of Objects | 08:48 |
128 | Linked List Implementation | 14:36 |
129 | Joypad Press & Release | 02:33 |
130 | Reading Scene Objects from CD | 20:30 |
131 | Camera-Object Distance Check | 11:15 |
132 | Drawing Scene Objects | 08:10 |
133 | Track Sections & Faces | 14:31 |
134 | Structs for Sessions & Faces | 07:48 |
135 | Reading Vertices, Faces, & Sections | 20:46 |
136 | Function to Render Track Sections | 22:59 |
137 | Shrinking Track Vertices | 15:24 |
138 | Exercise: Testing Face Flags | 06:46 |
139 | Drawing Quad Lines | 05:39 |
140 | Avoiding the GTE 16-bit Limitation | 11:47 |
141 | Clamping Overflow Values | 18:20 |
142 | Loading Track Texture Tiles | 24:24 |
143 | Manually Position Textures in VRAM | 15:08 |
144 | Loading Track Face UV Coords | 10:12 |
145 | Flip Face Texture | 05:10 |
146 | Tessellation & Polygon Subdivision | 13:14 |
147 | Drawing Quads Recursively | 12:35 |
148 | A Function to Draw Quads Recursively | 15:29 |
149 | Subdividing UV Coordinates | 09:33 |
150 | T-junctions | 13:03 |
151 | Ship Struct | 08:02 |
152 | Adding the Ship Header File | 03:58 |
153 | Movement in Game Physics | 08:04 |
154 | Changing the Thrust Magnitude | 19:02 |
155 | Applying the Thrust Force | 16:08 |
156 | Yaw, Pitch, & Roll | 09:47 |
157 | Populating our Rotation Matrix | 15:59 |
158 | Coding the Object's Orientation | 14:27 |
159 | Drawing XYZ Axis | 06:15 |
160 | Accelerating in the Nose's Direction | 10:32 |
161 | Placing Camera Behind the Ship | 07:53 |
162 | Yaw Velocity | 19:20 |
163 | Maximum Yaw Velocity | 05:45 |
164 | Roll Left & Right | 11:01 |
165 | Rethinking Section Rendering | 09:33 |
166 | Initializing Ship's Nearest Section | 11:58 |
167 | Update Ship's Nearest Section | 07:44 |
168 | Rendering Track Ahead | 10:52 |
169 | Clamping Track Vertices to 16 bits | 03:24 |
170 | Loading Track Session Normals | 10:00 |
171 | Drawing Section Normals | 07:17 |
172 | Loading the Section Base Vertex | 10:02 |
173 | Projected Ship Height | 10:20 |
174 | Coding the Projected Ship Height | 09:46 |
175 | Track Attraction & Repulsion Forces | 08:20 |
176 | Preventing Negative Height Values | 04:01 |
177 | Audio & SPU | 15:37 |
178 | Converting WAV to VAG | 09:42 |
179 | Playing a VAG Sound Effect | 20:53 |
180 | Pitch & Sampling Frequency | 05:01 |
181 | Exercise: Countdown Audio | 01:36 |
182 | Countdown Sound Effects | 04:54 |
183 | Background Music | 09:32 |
184 | Recording an Audio Track | 06:23 |
185 | Adding Audio Track to ISO | 13:50 |
186 | Play Audio Track Implementation | 10:20 |
187 | Play Background Audio Track | 04:30 |
188 | Adding Scene Objects & Audio | 02:33 |
189 | Conclusion & Next Steps | 09:58 |
Read Book PS1 Programming with MIPS Assembly & C
# | Title |
---|---|
1 | GTE & Advanced Graphics |
2 | Inline Programming Reference |
3 | MIPS Instruction Set |
4 | MIPS32в„ў Architecture For Programmers |
5 | PlayStation Hardware |
6 | Pitch & Sampling Frequency |