/[pcsx2_0.9.7]/trunk/plugins/zzogl-pg/opengl/HostMemory.cpp
ViewVC logotype

Contents of /trunk/plugins/zzogl-pg/opengl/HostMemory.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 185 - (show annotations) (download)
Mon Sep 13 19:49:07 2010 UTC (9 years, 4 months ago) by william
File size: 14513 byte(s)
Auto Commited Import of: pcsx2-0.9.7-DEBUG (upstream: v0.9.7.3761 local: v0.9.7.165-latest) in ./trunk
1 /* ZZ Open GL graphics plugin
2 * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
3 * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20 #include "GS.h"
21 #include <Cg/cg.h>
22 #include <Cg/cgGL.h>
23
24 #include <stdlib.h>
25 #include "Mem.h"
26 #include "x86.h"
27 #include "zerogs.h"
28 #include "targets.h"
29
30
31 u8* g_pbyGSMemory = NULL; // 4Mb GS system mem
32
33 void GSMemory::init()
34 {
35 const u32 mem_size = MEMORY_END + 0x10000; // leave some room for out of range accesses (saves on the checks)
36
37 // clear
38 g_pbyGSMemory = (u8*)_aligned_malloc(mem_size, 1024);
39 memset(g_pbyGSMemory, 0, mem_size);
40 }
41
42 void GSMemory::destroy()
43 {
44 _aligned_free(g_pbyGSMemory);
45 g_pbyGSMemory = NULL;
46 }
47
48 u8* GSMemory::get() { return g_pbyGSMemory; }
49
50 u8* GSMemory::get(u32 addr) { return &g_pbyGSMemory[addr*8]; }
51 u8* GSMemory::get_raw(u32 addr) { return &g_pbyGSMemory[addr]; }
52
53 u8* g_pbyGSClut = NULL; // ZZ
54
55 void GSClut::init()
56 {
57 g_pbyGSClut = (u8*)_aligned_malloc(256 * 8, 1024); // need 512 alignment!
58 memset(g_pbyGSClut, 0, 256*8);
59 }
60
61 void GSClut::destroy()
62 {
63 _aligned_free(g_pbyGSClut);
64 g_pbyGSClut = NULL;
65 }
66
67 u8* GSClut::get() { return g_pbyGSClut; }
68
69 u8* GSClut::get(u32 addr) { return &g_pbyGSClut[addr*8]; }
70 u8* GSClut::get_raw(u32 addr) { return &g_pbyGSClut[addr]; }
71
72 extern _getPixelAddress getPixelFun[64];
73
74 namespace ZeroGS
75 {
76 extern CRangeManager s_RangeMngr; // manages overwritten memory
77 extern void ResolveInRange(int start, int end);
78
79 static vector<u8> s_vTempBuffer, s_vTransferCache;
80 static int gs_imageEnd = 0;
81
82 void GetRectMemAddress(int& start, int& end, int psm, int x, int y, int w, int h, int bp, int bw)
83 {
84 FUNCLOG
85 u32 bits = 0;
86
87 if (m_Blocks[psm].bpp == 0)
88 {
89 ZZLog::Error_Log("ZeroGS: Bad psm 0x%x.", psm);
90 start = 0;
91 end = MEMORY_END;
92 return;
93 }
94
95 if (PSMT_ISZTEX(psm))
96 {
97 // Somehow, I doubt this code is right. I'll have to look into it. For the moment, I'm keeping it the
98 // way it was. --arcum42
99
100 const BLOCK& b = m_Blocks[psm];
101
102 bw = (bw + b.width - 1) / b.width;
103 start = bp * 256 + ((y / b.height) * bw + (x / b.width)) * 0x2000;
104 end = bp * 256 + (((y + h - 1) / b.height) * bw + (x + w + b.width - 1) / b.width) * 0x2000;
105 return;
106 }
107
108 bits = PSMT_BITS_NUM(psm);
109 start = getPixelFun[psm](x, y, bp, bw);
110 end = getPixelFun[psm](x + w - 1, y + h - 1, bp, bw) + 1;
111
112 if (bits > 0)
113 {
114 start *= bits;
115 end *= bits;
116 }
117 else
118 {
119 // This is what it used to do, which doesn't seem right.
120 // Keeping it for reference, in case removing it breaks anything.
121
122 //int newx = ((x + w - 1 + 31) & ~31) - 1;
123 //int newy = ((y + h - 1 + 15) & ~15) - 1;
124 //start = getPixelAddress4(x, y, bp, bw) / 2;
125 //end = (getPixelAddress4(max(newx, x), max(newy, y), bp, bw) + 2) / 2;
126
127 start /= 2;
128 end /= 2;
129 }
130 }
131
132 void InitTransferHostLocal()
133 {
134 FUNCLOG
135
136 #if defined(ZEROGS_DEVBUILD)
137 if (gs.trxpos.dx + gs.imageWnew > gs.dstbuf.bw)
138 ZZLog::Warn_Log("Transfer error, width exceeded.");
139
140 #endif
141
142 //bool bHasFlushed = false;
143
144 gs.imageX = gs.trxpos.dx;
145 gs.imageY = gs.trxpos.dy;
146
147 gs.imageEndX = gs.imageX + gs.imageWnew;
148 gs.imageEndY = gs.imageY + gs.imageHnew;
149
150 assert(gs.imageEndX < 2048 && gs.imageEndY < 2048);
151
152 // This needs to be looked in to, since psm should *not* be 63.
153 // hack! viewful joe
154 if (gs.dstbuf.psm == 63) gs.dstbuf.psm = 0;
155
156 int start, end;
157
158 GetRectMemAddress(start, end, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw);
159
160 if (end > MEMORY_END)
161 {
162 ZZLog::Warn_Log("Host local out of bounds!");
163 //gs.imageTransfer = -1;
164 end = MEMORY_END;
165 }
166
167 gs_imageEnd = end;
168
169 if (vb[0].nCount > 0) Flush(0);
170 if (vb[1].nCount > 0) Flush(1);
171
172 //ZZLog::Prim_Log("trans: bp:%x x:%x y:%x w:%x h:%x\n", gs.dstbuf.bp, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew);
173 }
174
175 void TransferHostLocal(const void* pbyMem, u32 nQWordSize)
176 {
177 FUNCLOG
178
179 int start, end;
180
181 GetRectMemAddress(start, end, gs.dstbuf.psm, gs.imageX, gs.imageY, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw);
182
183 assert(start < gs_imageEnd);
184
185 end = gs_imageEnd;
186
187 // sometimes games can decompress to alpha channel of render target only, in this case
188 // do a resolve right away. wolverine x2
189 if (((gs.dstbuf.psm == PSMT8H) || (gs.dstbuf.psm == PSMT4HL) || (gs.dstbuf.psm == PSMT4HH)) && !(conf.settings().gust))
190 {
191 list<CRenderTarget*> listTransmissionUpdateTargs;
192 s_RTs.GetTargs(start, end, listTransmissionUpdateTargs);
193
194 for (list<CRenderTarget*>::iterator it = listTransmissionUpdateTargs.begin(); it != listTransmissionUpdateTargs.end(); ++it)
195 {
196 CRenderTarget* ptarg = *it;
197
198 if ((ptarg->status & CRenderTarget::TS_Virtual)) continue;
199
200 //ZZLog::Error_Log("Resolving to alpha channel.");
201 ptarg->Resolve();
202 }
203 }
204
205 s_RangeMngr.Insert(start, min(end, start + (int)nQWordSize*16));
206
207 const u8* porgend = (const u8*)pbyMem + 4 * nQWordSize;
208
209 if (s_vTransferCache.size() > 0)
210 {
211
212 int imagecache = s_vTransferCache.size();
213 s_vTempBuffer.resize(imagecache + nQWordSize*4);
214 memcpy(&s_vTempBuffer[0], &s_vTransferCache[0], imagecache);
215 memcpy(&s_vTempBuffer[imagecache], pbyMem, nQWordSize*4);
216
217 pbyMem = (const void*) & s_vTempBuffer[0];
218 porgend = &s_vTempBuffer[0] + s_vTempBuffer.size();
219
220 int wordinc = imagecache / 4;
221
222 if ((nQWordSize * 4 + imagecache) / 3 == ((nQWordSize + wordinc) * 4) / 3)
223 {
224 // can use the data
225 nQWordSize += wordinc;
226 }
227 }
228
229 int leftover = m_Blocks[gs.dstbuf.psm].TransferHostLocal(pbyMem, nQWordSize);
230
231 if (leftover > 0)
232 {
233 // copy the last gs.image24bitOffset to the cache
234 s_vTransferCache.resize(leftover);
235 memcpy(&s_vTransferCache[0], porgend - leftover, leftover);
236 }
237 else
238 {
239 s_vTransferCache.resize(0);
240 }
241
242 #if defined(_DEBUG)
243 if (g_bSaveTrans)
244 {
245 tex0Info t;
246 t.tbp0 = gs.dstbuf.bp;
247 t.tw = gs.imageWnew;
248 t.th = gs.imageHnew;
249 t.tbw = gs.dstbuf.bw;
250 t.psm = gs.dstbuf.psm;
251 SaveTex(&t, 0);
252 }
253
254 #endif
255 }
256
257 void InitTransferLocalHost()
258 {
259 FUNCLOG
260 assert(gs.trxpos.sx + gs.imageWnew <= 2048 && gs.trxpos.sy + gs.imageHnew <= 2048);
261
262 #if defined(ZEROGS_DEVBUILD)
263
264 if (gs.trxpos.sx + gs.imageWnew > gs.srcbuf.bw)
265 ZZLog::Warn_Log("Transfer error, width exceeded.");
266
267 #endif
268
269 gs.imageX = gs.trxpos.sx;
270 gs.imageY = gs.trxpos.sy;
271
272 gs.imageEndX = gs.imageX + gs.imageWnew;
273 gs.imageEndY = gs.imageY + gs.imageHnew;
274
275 s_vTransferCache.resize(0);
276
277 int start, end;
278
279 GetRectMemAddress(start, end, gs.srcbuf.psm, gs.trxpos.sx, gs.trxpos.sy, gs.imageWnew, gs.imageHnew, gs.srcbuf.bp, gs.srcbuf.bw);
280
281 ResolveInRange(start, end);
282 }
283
284 template <class T>
285 void TransferLocalHost(void* pbyMem, u32 nQWordSize, int& x, int& y, u8 *pstart)
286 {
287 _readPixel_0 rp = readPixelFun_0[gs.srcbuf.psm];
288
289 int i = x, j = y;
290 T* pbuf = (T*)pbyMem;
291 u32 nSize = nQWordSize * 16 / sizeof(T);
292
293 for (; i < gs.imageEndY; ++i)
294 {
295 for (; j < gs.imageEndX && nSize > 0; ++j, --nSize)
296 {
297 *pbuf++ = rp(pstart, j % 2048, i % 2048, gs.srcbuf.bw);
298 }
299
300 if (j >= gs.imageEndX)
301 {
302 assert(j == gs.imageEndX);
303 j = gs.trxpos.sx;
304 }
305 else
306 {
307 assert(nSize == 0);
308 break;
309 }
310 }
311 }
312
313 void TransferLocalHost_24(void* pbyMem, u32 nQWordSize, int& x, int& y, u8 *pstart)
314 {
315 _readPixel_0 rp = readPixelFun_0[gs.srcbuf.psm];
316
317 int i = x, j = y;
318 u8* pbuf = (u8*)pbyMem;
319 u32 nSize = nQWordSize * 16 / 3;
320
321 for (; i < gs.imageEndY; ++i)
322 {
323 for (; j < gs.imageEndX && nSize > 0; ++j, --nSize)
324 {
325 u32 p = rp(pstart, j % 2048, i % 2048, gs.srcbuf.bw);
326 pbuf[0] = (u8)p;
327 pbuf[1] = (u8)(p >> 8);
328 pbuf[2] = (u8)(p >> 16);
329 pbuf += 3;
330 }
331
332 if (j >= gs.imageEndX)
333 {
334 assert(j == gs.imageEndX);
335 j = gs.trxpos.sx;
336 }
337 else
338 {
339 assert(nSize == 0);
340 break;
341 }
342 }
343 }
344
345 // left/right, top/down
346 void TransferLocalHost(void* pbyMem, u32 nQWordSize)
347 {
348 FUNCLOG
349 assert(gs.imageTransfer == 1);
350
351 u8* pstart = g_pbyGSMemory + 256 * gs.srcbuf.bp;
352
353 switch(PSMT_BITMODE(gs.srcbuf.psm))
354 {
355 case 0: TransferLocalHost<u32>(pbyMem, nQWordSize, gs.imageY, gs.imageX, pstart); break;
356 case 1: TransferLocalHost_24(pbyMem, nQWordSize, gs.imageY, gs.imageX, pstart); break;
357 case 2: TransferLocalHost<u16>(pbyMem, nQWordSize, gs.imageY, gs.imageX, pstart); break;
358 case 3: TransferLocalHost<u8>(pbyMem, nQWordSize, gs.imageY, gs.imageX, pstart); break;
359 default: assert(0); break;
360 }
361
362 if (gs.imageY >= gs.imageEndY)
363 {
364 ZZLog::Error_Log("gs.imageY >= gs.imageEndY!");
365 assert(gs.imageY == gs.imageEndY);
366 gs.imageTransfer = -1;
367 }
368 }
369
370 __forceinline void _TransferLocalLocal()
371 {
372 //ZZLog::Error_Log("TransferLocalLocal(0x%x, 0x%x)", gs.srcbuf.psm, gs.dstbuf.psm);
373 _writePixel_0 wp = writePixelFun_0[gs.srcbuf.psm];
374 _readPixel_0 rp = readPixelFun_0[gs.dstbuf.psm];
375 u8* pSrcBuf = g_pbyGSMemory + gs.srcbuf.bp * 256;
376 u8* pDstBuf = g_pbyGSMemory + gs.dstbuf.bp * 256;
377 u32 widthlimit = 4;
378 u32 maxX = gs.trxpos.sx + gs.imageWnew;
379 u32 maxY = gs.trxpos.sy + gs.imageHnew;
380
381 if (PSMT_BITMODE(gs.srcbuf.psm) == 0) widthlimit = 2;
382 if ((gs.imageWnew & widthlimit) != 0) return;
383
384 for(int i = gs.trxpos.sy, i2 = gs.trxpos.dy; i < maxY; i++, i2++)
385 {
386 for(int j = gs.trxpos.sx, j2 = gs.trxpos.dx; j < maxX; j += widthlimit, j2 += widthlimit)
387 {
388 wp(pDstBuf, j2%2048, i2%2048,
389 rp(pSrcBuf, j%2048, i%2048, gs.srcbuf.bw), gs.dstbuf.bw);
390
391 wp(pDstBuf, (j2+1)%2048, i2%2048,
392 rp(pSrcBuf, (j+1)%2048, i%2048, gs.srcbuf.bw), gs.dstbuf.bw);
393
394 if (widthlimit > 2)
395 {
396 // Then widthlimit == 4.
397 wp(pDstBuf, (j2+2)%2048, i2%2048,
398 rp(pSrcBuf, (j+2)%2048, i%2048, gs.srcbuf.bw), gs.dstbuf.bw);
399
400 wp(pDstBuf, (j2+3)%2048, i2%2048,
401 rp(pSrcBuf, (j+3)%2048, i%2048, gs.srcbuf.bw), gs.dstbuf.bw);
402 }
403 }
404 }
405 }
406
407 __forceinline void _TransferLocalLocal_4()
408 {
409 //ZZLog::Error_Log("TransferLocalLocal_4(0x%x, 0x%x)", gs.srcbuf.psm, gs.dstbuf.psm);
410 _getPixelAddress_0 gsp = getPixelFun_0[gs.srcbuf.psm];
411 _getPixelAddress_0 gdp = getPixelFun_0[gs.dstbuf.psm];
412 u8* pSrcBuf = g_pbyGSMemory + gs.srcbuf.bp * 256;
413 u8* pDstBuf = g_pbyGSMemory + gs.dstbuf.bp * 256;
414 u32 maxX = gs.trxpos.sx + gs.imageWnew;
415 u32 maxY = gs.trxpos.sy + gs.imageHnew;
416
417 assert((gs.imageWnew % 8) == 0);
418
419 for(int i = gs.trxpos.sy, i2 = gs.trxpos.dy; i < maxY; ++i, ++i2)
420 {
421 for(int j = gs.trxpos.sx, j2 = gs.trxpos.dx; j < maxX; j += 8, j2 += 8)
422 {
423 /* NOTE: the 2 conseq 4bit values are in NOT in the same byte */
424 u32 read = gsp(j%2048, i%2048, gs.srcbuf.bw);
425 u32 write = gdp(j2%2048, i2%2048, gs.dstbuf.bw);
426 pDstBuf[write] = (pDstBuf[write]&0xf0)|(pSrcBuf[read]&0x0f);
427
428 read = gsp((j+1)%2048, i%2048, gs.srcbuf.bw);
429 write = gdp((j2+1)%2048, i2%2048, gs.dstbuf.bw);
430 pDstBuf[write] = (pDstBuf[write]&0x0f)|(pSrcBuf[read]&0xf0);
431
432 read = gsp((j+2)%2048, i%2048, gs.srcbuf.bw);
433 write = gdp((j2+2)%2048, i2%2048, gs.dstbuf.bw);
434 pDstBuf[write] = (pDstBuf[write]&0xf0)|(pSrcBuf[read]&0x0f);
435
436 read = gsp((j+3)%2048, i%2048, gs.srcbuf.bw);
437 write = gdp((j2+3)%2048, i2%2048, gs.dstbuf.bw);
438 pDstBuf[write] = (pDstBuf[write]&0x0f)|(pSrcBuf[read]&0xf0);
439
440 read = gsp((j+2)%2048, i%2048, gs.srcbuf.bw);
441 write = gdp((j2+2)%2048, i2%2048, gs.dstbuf.bw);
442 pDstBuf[write] = (pDstBuf[write]&0xf0)|(pSrcBuf[read]&0x0f);
443
444 read = gsp((j+3)%2048, i%2048, gs.srcbuf.bw);
445 write = gdp((j2+3)%2048, i2%2048, gs.dstbuf.bw);
446 pDstBuf[write] = (pDstBuf[write]&0x0f)|(pSrcBuf[read]&0xf0);
447
448 read = gsp((j+2)%2048, i%2048, gs.srcbuf.bw);
449 write = gdp((j2+2)%2048, i2%2048, gs.dstbuf.bw);
450 pDstBuf[write] = (pDstBuf[write]&0xf0)|(pSrcBuf[read]&0x0f);
451
452 read = gsp((j+3)%2048, i%2048, gs.srcbuf.bw);
453 write = gdp((j2+3)%2048, i2%2048, gs.dstbuf.bw);
454 pDstBuf[write] = (pDstBuf[write]&0x0f)|(pSrcBuf[read]&0xf0);
455 }
456 }
457 }
458
459 // dir depends on trxpos.dirx & trxpos.diry
460 void TransferLocalLocal()
461 {
462 FUNCLOG
463
464 //ZZLog::Error_Log("I'z in your code, transferring your memory...");
465 assert(gs.imageTransfer == 2);
466 assert(gs.trxpos.sx + gs.imageWnew < 2048 && gs.trxpos.sy + gs.imageHnew < 2048);
467 assert(gs.trxpos.dx + gs.imageWnew < 2048 && gs.trxpos.dy + gs.imageHnew < 2048);
468 assert((gs.srcbuf.psm&0x7) == (gs.dstbuf.psm&0x7));
469
470 if (gs.trxpos.sx + gs.imageWnew > gs.srcbuf.bw)
471 ZZLog::Warn_Log("Transfer error, src width exceeded.");
472
473 if (gs.trxpos.dx + gs.imageWnew > gs.dstbuf.bw)
474 ZZLog::Warn_Log("Transfer error, dst width exceeded.");
475
476 int srcstart, srcend, dststart, dstend;
477
478 GetRectMemAddress(srcstart, srcend, gs.srcbuf.psm, gs.trxpos.sx, gs.trxpos.sy, gs.imageWnew, gs.imageHnew, gs.srcbuf.bp, gs.srcbuf.bw);
479 GetRectMemAddress(dststart, dstend, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw);
480
481 // resolve the targs
482 ResolveInRange(srcstart, srcend);
483
484 list<CRenderTarget*> listTargs;
485
486 s_RTs.GetTargs(dststart, dstend, listTargs);
487
488 for (list<CRenderTarget*>::iterator it = listTargs.begin(); it != listTargs.end(); ++it)
489 {
490 if (!((*it)->status & CRenderTarget::TS_Virtual))
491 {
492 (*it)->Resolve();
493 //(*it)->status |= CRenderTarget::TS_NeedUpdate;
494 }
495 }
496
497 if (PSMT_BITMODE(gs.srcbuf.psm) != 4)
498 {
499 _TransferLocalLocal();
500 }
501 else
502 {
503 _TransferLocalLocal_4();
504 }
505
506 g_MemTargs.ClearRange(dststart, dstend);
507
508 #ifdef ZEROGS_DEVBUILD
509
510 if (g_bSaveTrans)
511 {
512 tex0Info t;
513 t.tbp0 = gs.dstbuf.bp;
514 t.tw = gs.imageWnew;
515 t.th = gs.imageHnew;
516 t.tbw = gs.dstbuf.bw;
517 t.psm = gs.dstbuf.psm;
518 SaveTex(&t, 0);
519
520 t.tbp0 = gs.srcbuf.bp;
521 t.tw = gs.imageWnew;
522 t.th = gs.imageHnew;
523 t.tbw = gs.srcbuf.bw;
524 t.psm = gs.srcbuf.psm;
525 SaveTex(&t, 0);
526 }
527
528 #endif
529 }
530
531 }

  ViewVC Help
Powered by ViewVC 1.1.22