PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
screenshot.c
Go to the documentation of this file.
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
16#include "screenshot.h"
17#include <tamtypes.h>
18#include <kernel.h>
19#include <fcntl.h>
20#include <unistd.h>
21
22// These macros are kept local so the screenshot funcion can work without
23// interfering with other macros
24
25#define PS2SS_GIF_AD 0x0e
26
27#define PS2SS_GIFTAG(NLOOP,EOP,PRE,PRIM,FLG,NREG) \
28 ((u64)(NLOOP) << 0) | \
29 ((u64)(EOP) << 15) | \
30 ((u64)(PRE) << 46) | \
31 ((u64)(PRIM) << 47) | \
32 ((u64)(FLG) << 58) | \
33 ((u64)(NREG) << 60)
34
35#define PS2SS_GSBITBLTBUF_SET(sbp, sbw, spsm, dbp, dbw, dpsm) \
36 ((u64)(sbp) | ((u64)(sbw) << 16) | \
37 ((u64)(spsm) << 24) | ((u64)(dbp) << 32) | \
38 ((u64)(dbw) << 48) | ((u64)(dpsm) << 56))
39
40#define PS2SS_GSTRXREG_SET(rrw, rrh) \
41 ((u64)(rrw) | ((u64)(rrh) << 32))
42
43#define PS2SS_GSTRXPOS_SET(ssax, ssay, dsax, dsay, dir) \
44 ((u64)(ssax) | ((u64)(ssay) << 16) | \
45 ((u64)(dsax) << 32) | ((u64)(dsay) << 48) | \
46 ((u64)(dir) << 59))
47
48#define PS2SS_GSTRXDIR_SET(xdr) ((u64)(xdr))
49
50#define PS2SS_GSBITBLTBUF 0x50
51#define PS2SS_GSFINISH 0x61
52#define PS2SS_GSTRXPOS 0x51
53#define PS2SS_GSTRXREG 0x52
54#define PS2SS_GSTRXDIR 0x53
55
56#define PS2SS_GSPSMCT32 0
57#define PS2SS_GSPSMCT24 1
58#define PS2SS_GSPSMCT16 2
59
60#define PS2SS_D1_CHCR ((volatile unsigned int *)(0x10009000))
61#define PS2SS_D1_MADR ((volatile unsigned int *)(0x10009010))
62#define PS2SS_D1_QWC ((volatile unsigned int *)(0x10009020))
63#define PS2SS_D1_TADR ((volatile unsigned int *)(0x10009030))
64#define PS2SS_D1_ASR0 ((volatile unsigned int *)(0x10009040))
65#define PS2SS_D1_ASR1 ((volatile unsigned int *)(0x10009050))
66
67#define PS2SS_CSR_FINISH (1 << 1)
68#define PS2SS_GS_CSR ((volatile u64 *)(0x12001000))
69#define PS2SS_GS_BUSDIR ((volatile u64 *)(0x12001040))
70
71#define PS2SS_VIF1_STAT ((volatile u32 *)(0x10003c00))
72#define PS2SS_VIF1_STAT_FDR (1<< 23)
73#define PS2SS_VIF1_MSKPATH3(mask) ((u32)(mask) | ((u32)0x06 << 24))
74#define PS2SS_VIF1_NOP 0
75#define PS2SS_VIF1_FLUSHA (((u32)0x13 << 24))
76#define PS2SS_VIF1_DIRECT(count) ((u32)(count) | ((u32)(0x50) << 24))
77#define PS2SS_VIF1_FIFO ((volatile u128 *)(0x10005000))
78
79// Internal convfunctions
80
81void ps2_screenshot_16to32_buffer(void *pTemp, u32 w, u32 h);
82void ps2_screenshot_16to32_line(void *pTemp, u32 w);
83
84int ps2_screenshot_file( const char* pFilename,unsigned int VramAdress,
85 unsigned int Width, unsigned int Height, unsigned int Psm )
86{
87 s32 file_handle;
88 u32 y;
89 static u32 in_buffer[1024 * 4]; // max 1024*32bit for a line, should be ok
90 static u32 out_buffer[1024 * 4]; // max 1024*32bit for a line, should be ok
91
92 unsigned char header[18] =
93 {
94 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
95 0, 0, // Width
96 0, 0, // Heigth
97 32, 8
98 };
99
100 s16 *p_header = (s16 *)&header;
101
102 file_handle = open( pFilename, O_CREAT|O_WRONLY );
103
104 // make sure we could open the file for output
105
106 if (file_handle < 0)
107 return 0;
108
109 // setup tga header
110
111 p_header[6] = (s16) Width;
112 p_header[7] = (s16) Height;
113
114 write (file_handle, (void *)&header, 18);
115
116 // Check if we have a tempbuffer, if we do we use it
117
118 for (y = 0; y < Height; y++)
119 {
120 u32 *p_out = (u32 *)&out_buffer;
121 ps2_screenshot(in_buffer, VramAdress, 0, (Height - 1) - y, Width, 1, Psm);
122
123 if (Psm == PS2SS_GSPSMCT16)
124 {
125 u32 x;
126 u16* p_in = (u16*)&in_buffer;
127
128 for (x = 0; x < Width; x++)
129 {
130 u32 r = (p_in[x] & 31) << 3;
131 u32 g = ((p_in[x] >> 5) & 31) << 3;
132 u32 b = ((p_in[x] >> 10) & 31) << 3;
133 p_out[x] = (((u8)0xff)<<24)|(r<<16)|(g<<8)|b;
134 }
135 }
136 else
137 if (Psm == PS2SS_GSPSMCT24)
138 {
139 u32 x;
140 u8* p_in = (u8*)&in_buffer;
141
142 for( x = 0; x < Width; x++ )
143 {
144 u8 r = *p_in++;
145 u8 g = *p_in++;
146 u8 b = *p_in++;
147 p_out[x] = (((u8)0xff)<<24)|(r<<16)|(g<<8)|b;
148 }
149 }
150 else
151 {
152 u8 *p_in = (u8 *) &in_buffer;
153 u32 x;
154
155 for(x = 0; x < Width; x++)
156 {
157 u8 r = *p_in++;
158 u8 g = *p_in++;
159 u8 b = *p_in++;
160 u8 a = *p_in++;
161 p_out[x] = (a << 24) | (r << 16) | (g << 8) | b;
162 }
163 }
164
165 write(file_handle, p_out, Width * 4);
166 }
167
168 close(file_handle);
169
170 return 0;
171}
172
181int ps2_screenshot( void *pDest, unsigned int VramAdress, unsigned int x,
182 unsigned int y, unsigned int Width, unsigned int Height,
183 unsigned int Psm )
184{
185 static union {
186 u32 value_u32[4];
187 u128 value;
188 } enable_path3 ALIGNED(16) = {
189 {PS2SS_VIF1_MSKPATH3(0), PS2SS_VIF1_NOP, PS2SS_VIF1_NOP, PS2SS_VIF1_NOP}
190 };
191
192 u32 dma_chain[20*2] ALIGNED(16);
193 u32* p_dma32 = (u32*)&dma_chain;
194 u64 *p_dma64 = (u64*)(p_dma32 + 4);
195 u32 uQSize;
196 u32 prev_imr;
197 u32 prev_chcr;
198
199 // Calc size depending on Psm
200
201 if( Psm == PS2SS_GSPSMCT16 )
202 uQSize = ((Width*Height*2)/16);
203 else if( Psm == PS2SS_GSPSMCT24 )
204 uQSize = ((Width*Height*3)/16);
205 else
206 uQSize = (Width*Height*4)/16;
207
208 // Setup transfer texture back to memory
209
210 p_dma32[0] = PS2SS_VIF1_NOP;
211 p_dma32[1] = PS2SS_VIF1_MSKPATH3(0x8000);
212 p_dma32[2] = PS2SS_VIF1_FLUSHA;
213 p_dma32[3] = PS2SS_VIF1_DIRECT(6);
214
215 // Setup the blit
216
217 p_dma64[0] = PS2SS_GIFTAG(5, 1, 0, 0, 0, 1); // GIFTAG(NLOOP, EOP, PRE, PRIM, FLG, NREG)
218 p_dma64[1] = PS2SS_GIF_AD;
219
220 p_dma64[2] = PS2SS_GSBITBLTBUF_SET(VramAdress, Width/64, Psm, 0, 0, Psm);
221 p_dma64[3] = PS2SS_GSBITBLTBUF;
222
223 p_dma64[4] = PS2SS_GSTRXPOS_SET(x, y, 0, 0, 0); // SSAX, SSAY, DSAX, DSAY, DIR
224 p_dma64[5] = PS2SS_GSTRXPOS;
225
226 p_dma64[6] = PS2SS_GSTRXREG_SET(Width, Height); // RRW, RRh
227 p_dma64[7] = PS2SS_GSTRXREG;
228
229 p_dma64[8] = 0;
230 p_dma64[9] = PS2SS_GSFINISH;
231
232 p_dma64[10] = PS2SS_GSTRXDIR_SET(1); // XDIR
233 p_dma64[11] = PS2SS_GSTRXDIR;
234
235 prev_imr = GsPutIMR(GsGetIMR() | 0x0200);
236 prev_chcr = *PS2SS_D1_CHCR;
237
238 if( (*PS2SS_D1_CHCR & 0x0100) != 0 )
239 return 0;
240
241 // set the FINISH event
242
243 *PS2SS_GS_CSR = PS2SS_CSR_FINISH;
244
245 // DMA from memory and start DMA transfer
246
247 FlushCache(0);
248
249 *PS2SS_D1_QWC = 0x7;
250 *PS2SS_D1_MADR = (u32)p_dma32;
251 *PS2SS_D1_CHCR = 0x101;
252
253 asm __volatile__("sync.l\n");
254
255 // check if DMA is complete (STR=0)
256
257 while( *PS2SS_D1_CHCR & 0x0100 );
258 while( ( *PS2SS_GS_CSR & PS2SS_CSR_FINISH ) == 0 );
259
260 // Wait for viffifo to become empty
261
262 while( (*PS2SS_VIF1_STAT & (0x1f000000) ) );
263
264 // Reverse busdir and transfer image to host
265
266 *PS2SS_VIF1_STAT = PS2SS_VIF1_STAT_FDR;
267 *PS2SS_GS_BUSDIR = (u64)0x00000001;
268
269 FlushCache(0);
270
271 *PS2SS_D1_QWC = uQSize;
272 *PS2SS_D1_MADR = (u32)pDest;
273 *PS2SS_D1_CHCR = 0x100;
274
275 asm __volatile__(" sync.l\n");
276
277 // check if DMA is complete (STR=0)
278
279 while ( *PS2SS_D1_CHCR & 0x0100 );
280 *PS2SS_D1_CHCR = prev_chcr;
281 asm __volatile__(" sync.l\n");
282 *PS2SS_VIF1_STAT = 0;
283 *PS2SS_GS_BUSDIR = (u64)0;
284
285 // Put back prew imr and set finish event
286
287 GsPutIMR( prev_imr );
288 *PS2SS_GS_CSR = PS2SS_CSR_FINISH;
289
290 // Enable path3 again
291
292
293 *PS2SS_VIF1_FIFO = enable_path3.value;
294
295 return 1;
296}
297
300void ps2_screenshot_16to32_line(void *pTemp, u32 w)
301{
302 (void)pTemp;
303 (void)w;
304}
305
308void ps2_screenshot_16to32_buffer(void *pTemp, u32 w, u32 h)
309{
310 (void)pTemp;
311 (void)w;
312 (void)h;
313}
314
int ps2_screenshot(void *pDest, unsigned int VramAdress, unsigned int x, unsigned int y, unsigned int Width, unsigned int Height, unsigned int Psm)
Definition screenshot.c:181
void ps2_screenshot_16to32_buffer(void *pTemp, u32 w, u32 h)
Definition screenshot.c:308
void ps2_screenshot_16to32_line(void *pTemp, u32 w)
Definition screenshot.c:300