/
iop_example.asm
339 lines (293 loc) · 7.24 KB
/
iop_example.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
.ps2_ee
.include "playstation2/registers_ee.inc"
.include "playstation2/registers_gs_gp.inc"
.include "playstation2/registers_gs_priv.inc"
.include "playstation2/system_calls.inc"
.include "playstation2/macros.inc"
.entry_point main
.export start
.export install_vsync_handler
.export interrupt_vsync
.export vsync_count
.export vsync_id
.org 0x100000
start:
main:
li $sp, 0x02000000
;ei
jal dma_reset
nop
;; Reset GS
li $v1, GS_CSR
li $v0, 0x200
sd $v0, ($v1)
;; Interrupt mask register
li $v1, _GsPutIMR
li $a0, 0xff00
syscall
nop
;; interlace { PS2_NONINTERLACED = 0, PS2_INTERLACED = 1 };
;; videotype { PS2_NTSC = 2, PS2_PAL = 3 };
;; frame { PS2_FRAME = 1, PS2_FIELD = 0 };
;; SetGsCrt(s16 interlace, s16 pal_ntsc, s16 field);
li $v1, _SetGsCrt
li $a0, 1
li $a1, 2
li $a2, 0
syscall
nop
;; Use framebuffer read circuit (1 or 2?)
li $v1, GS_PMODE
li $v0, 0xff62
sd $v0, ($v1)
;; interlaced on (bit 0), frame mode (bit 1), DPMS (bit 3:2) = 0
;; seems like this should already be set from the SetGsCrt call
;; UPDATE: this seems to get set to 3 no matter what.. remove later.
;li $v1, GS_SMODE2
;li $v0, 0x03
;sd $v0, ($v1)
;; GS_DISPFB2 with 0x1400
;; base pointer (fbp): 0x0 (0x0)
;; frame buffer width (fbw): 10 (640)
;; pixel storage format (psm): 0 (PSMCT32)
;; position x (dbx): 0 (0x0)
;; position y (dby): 0 (0x0)
li $v1, GS_DISPFB2
li $v0, 0x1400
sd $v0, ($v1)
;li $v1, GS_DISPFB1
;li $v0, 0x1200
;sd $v0, ($v1)
;; GS_DISPLAY2 with 0x000d_f9ff_0182_4290
;; x position vck units (dx): 656
;; y position raster units (dy): 36
;; horiz magnification (magh): 3 (x8)
;; vert magnification (magv): 0 (x1)
;; display width - 1 in vck (dw): 2559
;; display height - 1 in pixels (dh): 223
li $v1, GS_DISPLAY2
li $at, 0x1bf_9ff
dsll32 $at, $at, 0
li $v0, 0x0182_4290
or $at, $at, $v0
sd $at, ($v1)
;li $v1, GS_DISPLAY1
;li $at, 0xdf9ff
;dsll32 $at, $at, 0
;li $v0, 0x0182_4290
;or $at, $at, $v0
;sd $at, ($v1)
;; Send TO IOP (SIF1 sends to IOP)
li $v0, D6_CHCR
li $v1, iop_code_packet
sw $v1, 0x10($v0) ; DMA06 ADDRESS
li $v1, ((iop_code_end - iop_code_packet) / 16)
sw $v1, 0x20($v0) ; DMA06 SIZE
li $v1, 0x101
sw $v1, ($v0) ; start
jal dma06_wait
nop
while_1:
;; Draw picture
jal draw_screen
nop
;; Wait for vsync
li $v1, GS_CSR
li $v0, 8
sw $v0, ($v1)
vsync_wait:
lw $v0, ($v1)
andi $v0, $v0, 8
beqz $v0, vsync_wait
nop
b while_1
nop
draw_screen:
;; Save return address register
move $s3, $ra
;; Setup draw environment
jal dma02_wait
nop
li $v0, D2_CHCR
li $v1, red_screen
sw $v1, 0x10($v0) ; DMA02 ADDRESS
li $v1, (red_screen_end - red_screen) / 16
sw $v1, 0x20($v0) ; DMA02 SIZE
li $v1, 0x101
sw $v1, ($v0) ; start
;; Draw Triangle
jal dma02_wait
nop
li $v0, D2_CHCR
li $v1, draw_triangle
sw $v1, 0x10($v0) ; DMA02 ADDRESS
li $v1, (draw_triangle_end - draw_triangle) / 16
sw $v1, 0x20($v0) ; DMA02 SIZE
;lw $v1, ($v0) ; start
;ori $v1, $v1, 0x105
li $v1, 0x101
sw $v1, ($v0) ; start
jal dma02_wait
nop
;; Restore return address register
move $ra, $s3
jr $ra
nop
install_vsync_handler:
di
;; Add Vertical Blank End interrupt handler
li $v1, _AddIntcHandler
li $a0, INTC_VBLANK_E
li $a1, interrupt_vsync
li $a2, 0
syscall
nop
;; Save interrupt handler ID
li $v1, vsync_id
sw $v0, ($v1)
;; Enable Vercial Blank interrupt
li $v1, __EnableIntc
li $a0, INTC_VBLANK_E
syscall
nop
;; Reset counter
li $v1, vsync_count
li $v0, 0xff
sw $v0, ($v1)
ei
jr $ra
nop
interrupt_vsync:
;; Increment interrupt counter
li $s1, vsync_count
lw $s0, ($s1)
addi $s0, $s0, 1
sw $s0, ($s1)
li $s1, GS_CSR
li $s0, 8
sw $s0, ($s1)
jr $ra
nop
dma_reset:
li $s0, D2_CHCR
;sw $zero, 0x80($s0) ; um, why?
sw $zero, 0x00($s0) ; D2_CHCR
sw $zero, 0x30($s0) ; D2_TADR
sw $zero, 0x10($s0) ; D2_MADR
sw $zero, 0x50($s0) ; D2_ASR1
sw $zero, 0x40($s0) ; D2_ASR0
li $s0, D6_CHCR
;sw $zero, 0x80($s0) ; um, why?
sw $zero, 0x00($s0) ; D2_CHCR
sw $zero, 0x30($s0) ; D2_TADR
sw $zero, 0x10($s0) ; D2_MADR
sw $zero, 0x50($s0) ; D2_ASR1
sw $zero, 0x40($s0) ; D2_ASR0
li $s0, D_CTRL
li $s1, 0xff1f
sw $s1, 0x10($s0) ; DMA_STAT
;lw $s1, 0x10($s0) ; DMA_STAT
;li $s2, 0xff1f
;and $s1, $s1, $s2
;sw $s1, 0x10($s0) ; DMA_STAT
;sw $zero, 0x10($s0) ; DMA_STAT
sw $zero, 0x00($s0) ; DMA_CTRL
sw $zero, 0x20($s0) ; DMA_PCR
sw $zero, 0x30($s0) ; DMA_SQWC
sw $zero, 0x50($s0) ; DMA_RBOR
sw $zero, 0x40($s0) ; DMA_RBSR
lw $s1, 0x00($s0) ; DMA_CTRL
ori $s1, $s1, 1
nop
sw $s1, 0x00($s0) ; DMA_CTRL
nop
jr $ra
nop
dma02_wait:
li $s1, D2_CHCR
lw $s0, ($s1)
andi $s0, $s0, 0x100
bnez $s0, dma02_wait
nop
jr $ra
nop
dma06_wait:
li $s1, D6_CHCR
lw $s0, ($s1)
andi $s0, $s0, 0x100
bnez $s0, dma06_wait
nop
jr $ra
nop
.align 64
vsync_count:
dc64 0
vsync_id:
dc64 0
.align 128
draw_triangle:
dc64 GIF_TAG(7, 1, 0, 0, FLG_PACKED, 1), REG_A_D
dc64 SETREG_PRIM(PRIM_TRIANGLE_STRIP, 1, 0, 0, 0, 0, 0, 0, 0), REG_PRIM
dc64 SETREG_RGBAQ(0,255,0,0x80,0x3f80_0000), REG_RGBAQ
dc64 SETREG_XYZ2(1800 << 4, 2000 << 4, 128), REG_XYZ2
dc64 SETREG_RGBAQ(255,0,0,0x80,0x3f80_0000), REG_RGBAQ
dc64 SETREG_XYZ2(1800 << 4, 2110 << 4, 128), REG_XYZ2
dc64 SETREG_RGBAQ(0,0,255,0x80,0x3f80_0000), REG_RGBAQ
dc64 SETREG_XYZ2(1900 << 4, 2110 << 4, 128), REG_XYZ2
draw_triangle_end:
.align 128
red_screen:
dc64 GIF_TAG(14, 1, 0, 0, FLG_PACKED, 1), REG_A_D
dc64 0x00a0000, REG_FRAME_1 ; framebuffer width = 640/64
dc64 0x8c, REG_ZBUF_1 ; 0-8 Zbuffer base, 24-27 Z format (32bit)
dc64 SETREG_XYOFFSET(1728 << 4, 1936 << 4), REG_XYOFFSET_1
dc64 SETREG_SCISSOR(0,639,0,447), REG_SCISSOR_1
dc64 1, REG_PRMODECONT ; refer to prim attributes
dc64 1, REG_COLCLAMP
dc64 0, REG_DTHE ; Dither off
dc64 0x70000, REG_TEST_1
dc64 0x30000, REG_TEST_1
dc64 PRIM_SPRITE, REG_PRIM
dc64 0x3f80_0000_0000_0080, REG_RGBAQ ; Background RGBA (A, blue, green, red)
dc64 SETREG_XYZ2(1728 << 4, 1936 << 4, 0), REG_XYZ2
dc64 SETREG_XYZ2(2368 << 4, 2384 << 4, 0), REG_XYZ2
dc64 0x70000, REG_TEST_1
red_screen_end:
;; SIF1 packet is:
;; uint32_t IOP_ADDRESS (destination address)
;; uint32_t Length in 32 bit words
;; uint32_t EE DMA tag low (length in quadwords, and end packet)
;; uint32_t EE DMA tag hi (IOP address)
.align 128
iop_code_packet:
dc32 0x1_0000
dc32 4
dc32 (7 << 28) | (0 << 26) | 1
dc32 0x1_0000
iop_code_2:
li $at, 0x1bad
li $a0, 0xd00d
iop_code_loop:
b iop_code_loop
nop
.align 128
iop_code_end:
.if 0
.align 128
iop_junk_packet:
;dc32 ((iop_junk - iop_junk_packet) << 24) | ((iop_junk_end - iop_junk) << 24)
dc32 (16 << 24) | 16
dc32 0x10000
dc32 0x8000_000c
dc32 0
other_data_struct:
dc32 0, 0, 0, 0, iop_junk, 0x1000, 16
iop_junk:
li $at, 0x1bad
li $a0, 0xd00d
iop_junk_loop:
b iop_junk_loop
nop
.align 128
iop_junk_end:
.endif