~ubuntu-branches/ubuntu/saucy/mupen64plus-video-rice/saucy

« back to all changes in this revision

Viewing changes to src/FrameBuffer.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Sven Eckelmann
  • Date: 2011-01-22 11:05:28 UTC
  • Revision ID: james.westby@ubuntu.com-20110122110528-k6z84gdespqqd9zp
Tags: upstream-1.99.4
ImportĀ upstreamĀ versionĀ 1.99.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Copyright (C) 2005 Rice1964
 
3
 
 
4
This program is free software; you can redistribute it and/or
 
5
modify it under the terms of the GNU General Public License
 
6
as published by the Free Software Foundation; either version 2
 
7
of the License, or (at your option) any later version.
 
8
 
 
9
This program is distributed in the hope that it will be useful,
 
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
GNU General Public License for more details.
 
13
 
 
14
You should have received a copy of the GNU General Public License
 
15
along with this program; if not, write to the Free Software
 
16
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
17
 
 
18
*/
 
19
 
 
20
// ===========================================================================
 
21
 
 
22
#include <vector>
 
23
 
 
24
#include "ConvertImage.h"
 
25
#include "DeviceBuilder.h"
 
26
#include "FrameBuffer.h"
 
27
#include "UcodeDefs.h"
 
28
#include "RSP_Parser.h"
 
29
#include "Render.h"
 
30
 
 
31
extern TMEMLoadMapInfo g_tmemLoadAddrMap[0x200];    // Totally 4KB TMEM;
 
32
 
 
33
// 0 keeps the most recent CI info
 
34
// 1 keeps the frame buffer CI info which is being displayed now
 
35
// 2 keeps the older frame buffer CI info. This can be used if we are using triple buffer
 
36
/* Overview of framebuffer implementation
 
37
1) Check if backbuffer has changed, via different detection techniques
 
38
2) If changed, we copy the GFX card's backbuffer to main RAM
 
39
3) This is slow due to the reading process, not the writing
 
40
*/
 
41
 
 
42
 
 
43
 
 
44
RecentCIInfo g_RecentCIInfo[5];
 
45
RecentCIInfo *g_uRecentCIInfoPtrs[5] =
 
46
{
 
47
    &g_RecentCIInfo[0],
 
48
    &g_RecentCIInfo[1],
 
49
    &g_RecentCIInfo[2],
 
50
    &g_RecentCIInfo[3],
 
51
    &g_RecentCIInfo[4],
 
52
};
 
53
 
 
54
int numOfRecentCIInfos = 5;
 
55
 
 
56
RecentViOriginInfo g_RecentVIOriginInfo[5];
 
57
uint32 dwBackBufferSavedAtFrame=0;
 
58
 
 
59
RenderTextureInfo gRenderTextureInfos[20];
 
60
int numOfTxtBufInfos = sizeof(gRenderTextureInfos)/sizeof(RenderTextureInfo);
 
61
RenderTextureInfo *g_pRenderTextureInfo = NULL;
 
62
 
 
63
FrameBufferManager* g_pFrameBufferManager = NULL;
 
64
 
 
65
bool LastCIIsNewCI=false;
 
66
 
 
67
FrameBufferManager::FrameBufferManager() :
 
68
    m_isRenderingToTexture(false),
 
69
    m_curRenderTextureIndex(-1),
 
70
        m_lastTextureBufferIndex(-1)
 
71
{
 
72
}
 
73
 
 
74
FrameBufferManager::~FrameBufferManager()
 
75
{
 
76
}
 
77
 
 
78
void FrameBufferManager::CloseUp()
 
79
{
 
80
    for( int i=0; i<numOfTxtBufInfos; i++ )
 
81
    {
 
82
        SAFE_DELETE(gRenderTextureInfos[i].pRenderTexture);
 
83
    }
 
84
}
 
85
 
 
86
void FrameBufferManager::Initialize()
 
87
{
 
88
    m_isRenderingToTexture = false;
 
89
    m_lastTextureBufferIndex = -1;
 
90
    m_curRenderTextureIndex = -1;
 
91
    
 
92
    status.bCIBufferIsRendered = false;
 
93
    status.bN64IsDrawingTextureBuffer = false;
 
94
    status.bHandleN64RenderTexture = false;
 
95
    status.bN64FrameBufferIsUsed = false;
 
96
 
 
97
    memset(&gRenderTextureInfos[0], 0, sizeof(RenderTextureInfo)*numOfTxtBufInfos);
 
98
}
 
99
// ===========================================================================
 
100
 
 
101
uint16 ConvertRGBATo555(uint8 r, uint8 g, uint8 b, uint8 a)
 
102
{
 
103
    uint8 ar = a>=0x20?1:0;
 
104
    return ((r>>3)<<RGBA5551_RedShift) | ((g>>3)<<RGBA5551_GreenShift) | ((b>>3)<<RGBA5551_BlueShift) | ar;//(a>>7);
 
105
}
 
106
 
 
107
uint16 ConvertRGBATo555(uint32 color32)
 
108
{
 
109
    return (uint16)((((color32>>19)&0x1F)<<RGBA5551_RedShift) | (((color32>>11)&0x1F)<<RGBA5551_GreenShift) | (((color32>>3)&0x1F)<<RGBA5551_BlueShift) | ((color32>>31)));;
 
110
}
 
111
 
 
112
void FrameBufferManager::UpdateRecentCIAddr(SetImgInfo &ciinfo)
 
113
{
 
114
    if( ciinfo.dwAddr == g_uRecentCIInfoPtrs[0]->dwAddr )
 
115
        return;
 
116
 
 
117
    RecentCIInfo *temp;
 
118
 
 
119
        int i;
 
120
    for( i=1; i<numOfRecentCIInfos; i++ )
 
121
    {
 
122
        if( ciinfo.dwAddr == g_uRecentCIInfoPtrs[i]->dwAddr )
 
123
        {
 
124
            temp = g_uRecentCIInfoPtrs[i];
 
125
 
 
126
            for( int j=i; j>0; j-- )
 
127
            {
 
128
                g_uRecentCIInfoPtrs[j] = g_uRecentCIInfoPtrs[j-1];
 
129
            }
 
130
            break;
 
131
        }
 
132
    }
 
133
 
 
134
    if( i >= numOfRecentCIInfos )
 
135
    {
 
136
        temp = g_uRecentCIInfoPtrs[4];
 
137
        g_uRecentCIInfoPtrs[4] = g_uRecentCIInfoPtrs[3];
 
138
        g_uRecentCIInfoPtrs[3] = g_uRecentCIInfoPtrs[2];
 
139
        g_uRecentCIInfoPtrs[2] = g_uRecentCIInfoPtrs[1];
 
140
        g_uRecentCIInfoPtrs[1] = g_uRecentCIInfoPtrs[0];
 
141
        temp->dwCopiedAtFrame = 0;
 
142
        temp->bCopied = false;
 
143
    }
 
144
 
 
145
    g_uRecentCIInfoPtrs[0] = temp;
 
146
 
 
147
    // Fix me here for Mario Tennis
 
148
    temp->dwLastWidth = windowSetting.uViWidth;
 
149
    temp->dwLastHeight = windowSetting.uViHeight;
 
150
 
 
151
    temp->dwFormat = ciinfo.dwFormat;
 
152
    temp->dwAddr = ciinfo.dwAddr;
 
153
    temp->dwSize = ciinfo.dwSize;
 
154
    temp->dwWidth = ciinfo.dwWidth;
 
155
    temp->dwHeight = gRDP.scissor.bottom;
 
156
    temp->dwMemSize = (temp->dwWidth*temp->dwHeight/2)<<temp->dwSize;
 
157
    temp->bCopied = false;
 
158
    temp->lastUsedFrame = status.gDlistCount;
 
159
    temp->lastSetAtUcode = status.gUcodeCount;
 
160
}
 
161
 
 
162
 
 
163
/************************************************************************/
 
164
/* Mark the ciinfo entry that the ciinfo is used by VI origin register  */
 
165
/* in another word, this is a real frame buffer, not a fake frame buffer*/
 
166
/* Fake frame buffers are never really used by VI origin                */
 
167
/************************************************************************/
 
168
void FrameBufferManager::SetAddrBeDisplayed(uint32 addr)
 
169
{
 
170
    uint32 viwidth = *g_GraphicsInfo.VI_WIDTH_REG;
 
171
    addr &= (g_dwRamSize-1);
 
172
        int i;
 
173
    for( i=0; i<numOfRecentCIInfos; i++ )
 
174
    {
 
175
        if( g_uRecentCIInfoPtrs[i]->dwAddr+2*viwidth == addr )
 
176
        {
 
177
            g_uRecentCIInfoPtrs[i]->bUsedByVIAtFrame = status.gDlistCount;
 
178
        }
 
179
        else if( addr >= g_uRecentCIInfoPtrs[i]->dwAddr && addr < g_uRecentCIInfoPtrs[i]->dwAddr+0x1000 )
 
180
        {
 
181
            g_uRecentCIInfoPtrs[i]->bUsedByVIAtFrame = status.gDlistCount;
 
182
        }
 
183
    }
 
184
 
 
185
    for( i=0; i<numOfRecentCIInfos; i++ )
 
186
    {
 
187
        if( g_RecentVIOriginInfo[i].addr == addr )
 
188
        {
 
189
            g_RecentVIOriginInfo[i].FrameCount = status.gDlistCount;
 
190
            return;
 
191
        }
 
192
    }
 
193
 
 
194
    for( i=0; i<numOfRecentCIInfos; i++ )
 
195
    {
 
196
        if( g_RecentVIOriginInfo[i].addr == 0 )
 
197
        {
 
198
            // Never used
 
199
            g_RecentVIOriginInfo[i].addr = addr;
 
200
            g_RecentVIOriginInfo[i].FrameCount = status.gDlistCount;
 
201
            return;
 
202
        }
 
203
    }
 
204
 
 
205
    int index=0;
 
206
    uint32 minFrameCount = 0xffffffff;
 
207
 
 
208
    for( i=0; i<numOfRecentCIInfos; i++ )
 
209
    {
 
210
        if( g_RecentVIOriginInfo[i].FrameCount < minFrameCount )
 
211
        {
 
212
            index = i;
 
213
            minFrameCount = g_RecentVIOriginInfo[i].FrameCount;
 
214
        }
 
215
    }
 
216
 
 
217
    g_RecentVIOriginInfo[index].addr = addr;
 
218
    g_RecentVIOriginInfo[index].FrameCount = status.gDlistCount;
 
219
}
 
220
 
 
221
bool FrameBufferManager::HasAddrBeenDisplayed(uint32 addr, uint32 width)
 
222
{
 
223
    addr &= (g_dwRamSize-1);
 
224
        int i;
 
225
    for( i=0; i<numOfRecentCIInfos; i++ )
 
226
    {
 
227
        if( g_uRecentCIInfoPtrs[i]->dwAddr == 0 )
 
228
            continue;
 
229
 
 
230
        if( g_uRecentCIInfoPtrs[i]->dwAddr == addr )
 
231
        {
 
232
            if( status.gDlistCount-g_uRecentCIInfoPtrs[i]->bUsedByVIAtFrame < 20 )
 
233
                //if( g_uRecentCIInfoPtrs[i]->bUsedByVIAtFrame != 0 )
 
234
            {
 
235
                return true;
 
236
            }
 
237
            else
 
238
            {
 
239
                TXTRBUF_DUMP(TRACE0("This is a new buffer address, the addr is never a displayed buffer"););
 
240
                return false;
 
241
            }
 
242
        }
 
243
    }
 
244
 
 
245
    for( i=0; i<numOfRecentCIInfos; i++ )
 
246
    {
 
247
        if( g_RecentVIOriginInfo[i].addr != 0 )
 
248
        {
 
249
            if( g_RecentVIOriginInfo[i].addr > addr && 
 
250
                (g_RecentVIOriginInfo[i].addr - addr)%width == 0 &&
 
251
                (g_RecentVIOriginInfo[i].addr - addr)/width <= 4)
 
252
            {
 
253
                if( status.gDlistCount-g_RecentVIOriginInfo[i].FrameCount < 20 )
 
254
                    //if( g_RecentVIOriginInfo[i].FrameCount != 0 )
 
255
                {
 
256
                    return true;
 
257
                }
 
258
                else
 
259
                {
 
260
                    TXTRBUF_DUMP(DebuggerAppendMsg("This is a new buffer address, the addr is never a displayed buffer"););
 
261
                    return false;
 
262
                }
 
263
            }
 
264
        }
 
265
    }
 
266
 
 
267
    if( status.gDlistCount > 20 )
 
268
        return false;
 
269
    else
 
270
    {
 
271
        TXTRBUF_DUMP({DebuggerAppendMsg("This is a new buffer address, the addr is never a displayed buffer");});
 
272
        return true;
 
273
    }
 
274
}
 
275
 
 
276
int FrameBufferManager::FindRecentCIInfoIndex(uint32 addr)
 
277
{
 
278
    for( int i=0; i<numOfRecentCIInfos; i++ )
 
279
    {
 
280
        if( g_uRecentCIInfoPtrs[i]->dwAddr <= addr && addr < g_uRecentCIInfoPtrs[i]->dwAddr+g_uRecentCIInfoPtrs[i]->dwMemSize )
 
281
        {
 
282
            return i;
 
283
        }
 
284
    }
 
285
    return -1;
 
286
}
 
287
 
 
288
bool FrameBufferManager::IsDIaRenderTexture()
 
289
{
 
290
    // Knowing g_CI and g_ZI
 
291
 
 
292
    //if( g_CI.dwWidth )
 
293
 
 
294
    bool foundSetScissor=false;
 
295
    bool foundFillRect=false;
 
296
    bool foundSetFillColor=false;
 
297
    bool foundSetCImg=false;
 
298
    bool foundTxtRect=false;
 
299
    int height;
 
300
    uint32 newFillColor = 0;
 
301
 
 
302
    uint32 dwPC = gDlistStack[gDlistStackPointer].pc;       // This points to the next instruction
 
303
 
 
304
    for( int i=0; i<10; i++ )
 
305
    {
 
306
        uint32 w0 = *(uint32 *)(g_pRDRAMu8 + dwPC + i*8);
 
307
        uint32 w1 = *(uint32 *)(g_pRDRAMu8 + dwPC + 4 + i*8);
 
308
 
 
309
        if( (w0>>24) == RDP_SETSCISSOR )
 
310
        {
 
311
            height   = ((w1>>0 )&0xFFF)/4;
 
312
            foundSetScissor = true;
 
313
            continue;
 
314
        }
 
315
 
 
316
        if( (w0>>24) == RDP_SETFILLCOLOR )
 
317
        {
 
318
            height   = ((w1>>0 )&0xFFF)/4;
 
319
            foundSetFillColor = true;
 
320
            newFillColor = w1;
 
321
            continue;
 
322
        }
 
323
 
 
324
        if( (w0>>24) == RDP_FILLRECT )
 
325
        {
 
326
            uint32 x0   = ((w1>>12)&0xFFF)/4;
 
327
            uint32 y0   = ((w1>>0 )&0xFFF)/4;
 
328
            uint32 x1   = ((w0>>12)&0xFFF)/4;
 
329
            uint32 y1   = ((w0>>0 )&0xFFF)/4;
 
330
 
 
331
            if( x0 == 0 && y0 == 0 )
 
332
            {
 
333
                if( x1 == g_CI.dwWidth )
 
334
                {
 
335
                    height = y1;
 
336
                    foundFillRect = true;
 
337
                    continue;
 
338
                }
 
339
 
 
340
                if(x1 == (unsigned int)(g_CI.dwWidth-1))
 
341
                {
 
342
                    height = y1+1;
 
343
                    foundFillRect = true;
 
344
                    continue;
 
345
                }
 
346
            }
 
347
        }   
 
348
 
 
349
        if( (w0>>24) == RDP_TEXRECT )
 
350
        {
 
351
            foundTxtRect = true;
 
352
            break;
 
353
        }
 
354
 
 
355
        if( (w0>>24) == RDP_SETCIMG )
 
356
        {
 
357
            foundSetCImg = true;
 
358
            break;
 
359
        }
 
360
    }
 
361
 
 
362
    /*
 
363
    bool foundSetScissor=false;
 
364
    bool foundFillRect=false;
 
365
    bool foundSetFillColor=false;
 
366
    bool foundSetCImg=false;
 
367
    bool foundTxtRect=false;
 
368
    int ucodeLength=10;
 
369
    uint32 newFillColor;
 
370
    */
 
371
 
 
372
    if( foundFillRect )
 
373
    {
 
374
        if( foundSetFillColor )
 
375
        {
 
376
            if( newFillColor != 0xFFFCFFFC )
 
377
                return true;    // this is a render_texture
 
378
            else
 
379
                return false;
 
380
        }
 
381
 
 
382
        if( gRDP.fillColor != 0x00FFFFF7 )
 
383
            return true;    // this is a render_texture
 
384
        else
 
385
            return false;   // this is a normal ZImg
 
386
    }
 
387
    else if( foundSetFillColor && newFillColor == 0xFFFCFFFC && foundSetCImg )
 
388
    {
 
389
        return false;
 
390
    }
 
391
    else
 
392
        return true;
 
393
 
 
394
 
 
395
    if( !foundSetCImg )
 
396
        return true;
 
397
 
 
398
    if( foundSetScissor )
 
399
        return true;
 
400
}
 
401
 
 
402
int FrameBufferManager::CheckAddrInBackBuffers(uint32 addr, uint32 memsize, bool copyToRDRAM)
 
403
{
 
404
    int r = FindRecentCIInfoIndex(addr);
 
405
 
 
406
    if( r >= 0 )
 
407
    {
 
408
        // Also check if the address is overwritten by a recent render_texture
 
409
        //int t = CheckAddrInRenderTextures(addr,false);
 
410
        int t =-1;
 
411
        for( int i=0; i<numOfTxtBufInfos; i++ )
 
412
        {
 
413
            uint32 bufHeight = gRenderTextureInfos[i].knownHeight ? gRenderTextureInfos[i].N64Height : gRenderTextureInfos[i].maxUsedHeight;
 
414
            uint32 bufMemSize = gRenderTextureInfos[i].CI_Info.dwSize*gRenderTextureInfos[i].N64Width*bufHeight;
 
415
            if( addr >=gRenderTextureInfos[i].CI_Info.dwAddr && addr < gRenderTextureInfos[i].CI_Info.dwAddr+bufMemSize)
 
416
            {
 
417
                if( g_uRecentCIInfoPtrs[r]->lastSetAtUcode < gRenderTextureInfos[i].updateAtUcodeCount )
 
418
                {
 
419
                    t = i;
 
420
                    break;
 
421
                }
 
422
            }
 
423
        }
 
424
 
 
425
        if( t >= 0 )
 
426
            return -1;
 
427
    }
 
428
 
 
429
    if( r >= 0 && status.gDlistCount - g_uRecentCIInfoPtrs[r]->lastUsedFrame <= 3  && g_uRecentCIInfoPtrs[r]->bCopied == false )
 
430
    {
 
431
        DEBUGGER_IF_DUMP((logTextureBuffer&&r==1),TRACE2("Hit current front buffer at %08X, size=0x%X", addr, memsize));
 
432
        DEBUGGER_IF_DUMP((logTextureBuffer&&r==0),TRACE2("Hit current back buffer at %08X, size=0x%X", addr, memsize));
 
433
        DEBUGGER_IF_DUMP((logTextureBuffer&&r>1),TRACE2("Hit old back buffer at %08X, size=0x%X", addr, memsize));
 
434
 
 
435
        SaveBackBuffer(r, NULL, true);
 
436
    }       
 
437
 
 
438
    return r;
 
439
}
 
440
 
 
441
 
 
442
uint8 CIFindIndex(uint16 val)
 
443
{
 
444
    for( int i=0; i<=0xFF; i++ )
 
445
    {
 
446
        if( val == g_wRDPTlut[i] )
 
447
        {
 
448
            return (uint8)i;
 
449
        }
 
450
    }
 
451
    return 0;
 
452
}
 
453
 
 
454
 
 
455
void TexRectToFrameBuffer_8b(uint32 dwXL, uint32 dwYL, uint32 dwXH, uint32 dwYH, float t0u0, float t0v0, float t0u1, float t0v1, uint32 dwTile)
 
456
{
 
457
    // Copy the framebuffer texture into the N64 framebuffer memory
 
458
    // Used in Yoshi
 
459
 
 
460
    /*
 
461
    uint32 maxW = g_pRenderTextureInfo->CI_Info.dwWidth;
 
462
    uint32 maxH = maxW*3/4;
 
463
    if( status.dwTvSystem == TV_SYSTEM_PAL )
 
464
    {
 
465
    maxH = maxW*9/11;
 
466
    }
 
467
    */
 
468
 
 
469
    uint32 maxW = g_pRenderTextureInfo->N64Width;
 
470
    uint32 maxH = g_pRenderTextureInfo->N64Height;
 
471
 
 
472
    uint32 maxOff = maxW*maxH;
 
473
 
 
474
    TMEMLoadMapInfo &info = g_tmemLoadAddrMap[gRDP.tiles[dwTile].dwTMem];
 
475
    uint32 dwWidth = dwXH-dwXL;
 
476
    uint32 dwHeight = dwYH-dwYL;
 
477
 
 
478
    float xScale = (t0u1-t0u0)/dwWidth;
 
479
    float yScale = (t0v1-t0v0)/dwHeight;
 
480
 
 
481
    uint8* dwSrc = g_pRDRAMu8 + info.dwLoadAddress;
 
482
    uint8* dwDst = g_pRDRAMu8 + g_pRenderTextureInfo->CI_Info.dwAddr;
 
483
 
 
484
    uint32 dwSrcPitch = gRDP.tiles[dwTile].dwPitch;
 
485
    uint32 dwDstPitch = g_pRenderTextureInfo->CI_Info.dwWidth;
 
486
 
 
487
    uint32 dwSrcOffX = gRDP.tiles[dwTile].hilite_sl;
 
488
    uint32 dwSrcOffY = gRDP.tiles[dwTile].hilite_tl;
 
489
 
 
490
    uint32 dwLeft = dwXL;
 
491
    uint32 dwTop = dwYL;
 
492
 
 
493
    dwWidth = min(dwWidth,maxW-dwLeft);
 
494
    dwHeight = min(dwHeight, maxH-dwTop);
 
495
    if( maxH <= dwTop ) return;
 
496
 
 
497
    for (uint32 y = 0; y < dwHeight; y++)
 
498
    {
 
499
        uint32 dwByteOffset = (uint32)(((y*yScale+dwSrcOffY) * dwSrcPitch) + dwSrcOffX);
 
500
 
 
501
        for (uint32 x = 0; x < dwWidth; x++)
 
502
        {
 
503
            if( (((y+dwTop)*dwDstPitch+x+dwLeft)^0x3) > maxOff )
 
504
            {
 
505
#ifdef DEBUGGER
 
506
                TRACE0("Warning: Offset exceeds limit");
 
507
#endif
 
508
                continue;
 
509
            }
 
510
            dwDst[((y+dwTop)*dwDstPitch+x+dwLeft)^0x3] = dwSrc[(uint32)(dwByteOffset+x*xScale) ^ 0x3];
 
511
        }
 
512
    }
 
513
 
 
514
    TXTRBUF_DUMP(DebuggerAppendMsg("TexRect To FrameBuffer: X0=%d, Y0=%d, X1=%d, Y1=%d,\n\t\tfS0=%f, fT0=%f, fS1=%f, fT1=%f ",
 
515
        dwXL, dwYL, dwXH, dwYH, t0v0, t0v0, t0u1, t0v1););
 
516
}
 
517
 
 
518
void TexRectToN64FrameBuffer_16b(uint32 x0, uint32 y0, uint32 width, uint32 height, uint32 dwTile)
 
519
{
 
520
    // Copy the framebuffer texture into the N64 RDRAM framebuffer memory structure
 
521
 
 
522
    DrawInfo srcInfo;   
 
523
    if( g_textures[dwTile].m_pCTexture->StartUpdate(&srcInfo) == false )
 
524
    {
 
525
        DebuggerAppendMsg("Fail to lock texture:TexRectToN64FrameBuffer_16b" );
 
526
        return;
 
527
    }
 
528
 
 
529
    uint32 n64CIaddr = g_CI.dwAddr;
 
530
    uint32 n64CIwidth = g_CI.dwWidth;
 
531
 
 
532
    for (uint32 y = 0; y < height; y++)
 
533
    {
 
534
        uint32* pSrc = (uint32*)((uint8*)srcInfo.lpSurface + y * srcInfo.lPitch);
 
535
        uint16* pN64Buffer = (uint16*)(g_pRDRAMu8+(n64CIaddr&(g_dwRamSize-1)))+(y+y0)*n64CIwidth;
 
536
 
 
537
        for (uint32 x = 0; x < width; x++)
 
538
        {
 
539
            pN64Buffer[x+x0] = ConvertRGBATo555(pSrc[x]);
 
540
        }
 
541
    }
 
542
 
 
543
    g_textures[dwTile].m_pCTexture->EndUpdate(&srcInfo);
 
544
}
 
545
 
 
546
#define FAST_CRC_CHECKING_INC_X 13
 
547
#define FAST_CRC_CHECKING_INC_Y 11
 
548
#define FAST_CRC_MIN_Y_INC      2
 
549
#define FAST_CRC_MIN_X_INC      2
 
550
#define FAST_CRC_MAX_X_INC      7
 
551
#define FAST_CRC_MAX_Y_INC      3
 
552
extern uint32 dwAsmHeight;
 
553
extern uint32 dwAsmPitch;
 
554
extern uint32 dwAsmdwBytesPerLine;
 
555
extern uint32 dwAsmCRC;
 
556
extern uint8* pAsmStart;
 
557
 
 
558
uint32 CalculateRDRAMCRC(void *pPhysicalAddress, uint32 left, uint32 top, uint32 width, uint32 height, uint32 size, uint32 pitchInBytes )
 
559
{
 
560
    dwAsmCRC = 0;
 
561
    dwAsmdwBytesPerLine = ((width<<size)+1)/2;
 
562
 
 
563
    if( currentRomOptions.bFastTexCRC && !options.bLoadHiResTextures && (height>=32 || (dwAsmdwBytesPerLine>>2)>=16))
 
564
    {
 
565
        uint32 realWidthInDWORD = dwAsmdwBytesPerLine>>2;
 
566
        uint32 xinc = realWidthInDWORD / FAST_CRC_CHECKING_INC_X;   
 
567
        if( xinc < FAST_CRC_MIN_X_INC )
 
568
        {
 
569
            xinc = min(FAST_CRC_MIN_X_INC, width);
 
570
        }
 
571
        if( xinc > FAST_CRC_MAX_X_INC )
 
572
        {
 
573
            xinc = FAST_CRC_MAX_X_INC;
 
574
        }
 
575
 
 
576
        uint32 yinc = height / FAST_CRC_CHECKING_INC_Y; 
 
577
        if( yinc < FAST_CRC_MIN_Y_INC ) 
 
578
        {
 
579
            yinc = min(FAST_CRC_MIN_Y_INC, height);
 
580
        }
 
581
        if( yinc > FAST_CRC_MAX_Y_INC )
 
582
        {
 
583
            yinc = FAST_CRC_MAX_Y_INC;
 
584
        }
 
585
 
 
586
        uint32 pitch = pitchInBytes>>2;
 
587
        register uint32 *pStart = (uint32*)(pPhysicalAddress);
 
588
        pStart += (top * pitch) + (((left<<size)+1)>>3);
 
589
 
 
590
        // The original assembly code had a bug in it (it incremented pStart by 'pitch' in bytes, not in dwords)
 
591
        // This C code implements the same algorithm as the ASM but without the bug
 
592
        uint32 y = 0;
 
593
        while (y < height)
 
594
        {
 
595
          uint32 x = 0;
 
596
          while (x < realWidthInDWORD)
 
597
          {
 
598
            dwAsmCRC = (dwAsmCRC << 4) + ((dwAsmCRC >> 28) & 15);
 
599
            dwAsmCRC += pStart[x];
 
600
            x += xinc;
 
601
            dwAsmCRC += x;
 
602
          }
 
603
          dwAsmCRC ^= y;
 
604
          y += yinc;
 
605
          pStart += pitch;
 
606
        }
 
607
 
 
608
    }
 
609
    else
 
610
    {
 
611
        try{
 
612
            dwAsmdwBytesPerLine = ((width<<size)+1)/2;
 
613
 
 
614
            pAsmStart = (uint8*)(pPhysicalAddress);
 
615
            pAsmStart += (top * pitchInBytes) + (((left<<size)+1)>>1);
 
616
 
 
617
            dwAsmHeight = height - 1;
 
618
            dwAsmPitch = pitchInBytes;
 
619
 
 
620
#if !defined(__GNUC__) && !defined(NO_ASM)
 
621
            __asm 
 
622
            {
 
623
                push eax
 
624
                push ebx
 
625
                push ecx
 
626
                push edx
 
627
                push esi
 
628
 
 
629
                mov ecx, pAsmStart; // = pStart
 
630
                mov edx, 0          // The CRC
 
631
                mov eax, dwAsmHeight    // = y
 
632
l2:             mov ebx, dwAsmdwBytesPerLine    // = x
 
633
                sub ebx, 4
 
634
l1:             mov esi, [ecx+ebx]
 
635
                xor esi, ebx
 
636
                rol edx, 4
 
637
                add edx, esi
 
638
                sub ebx, 4
 
639
                jge l1
 
640
                xor esi, eax
 
641
                add edx, esi
 
642
                add ecx, dwAsmPitch
 
643
                dec eax
 
644
                jge l2
 
645
 
 
646
                mov dwAsmCRC, edx
 
647
 
 
648
                pop esi
 
649
                pop edx
 
650
                pop ecx
 
651
                pop ebx
 
652
                pop eax
 
653
            }
 
654
#elif defined(__GNUC__) && defined(__x86_64__) && !defined(NO_ASM)
 
655
        asm volatile(" xorl          %k2,      %k2           \n"
 
656
                     " movsxl        %k4,      %q4           \n"
 
657
                     "0:                                     \n"
 
658
                     " movsxl         %3,    %%rbx           \n"
 
659
                     " sub            $4,    %%rbx           \n"
 
660
                     "1:                                     \n"
 
661
                     " movl (%0,%%rbx,1),    %%eax           \n"
 
662
                     " xorl        %%ebx,    %%eax           \n"
 
663
                     " roll           $4,      %k2           \n"
 
664
                     " addl        %%eax,      %k2           \n"
 
665
                     " sub            $4,    %%rbx           \n"
 
666
                     " jge            1b                     \n"
 
667
                     " xorl          %k1,    %%eax           \n"
 
668
                     " addl        %%eax,      %k2           \n"
 
669
                     " add           %q4,       %0           \n"
 
670
                     " decl          %k1                     \n"
 
671
                     " jge            0b                     \n"
 
672
                     : "+r"(pAsmStart), "+r"(dwAsmHeight), "=&r"(dwAsmCRC)
 
673
                     : "m"(dwAsmdwBytesPerLine), "r"(dwAsmPitch)
 
674
                     : "%rbx", "%rax", "memory", "cc"
 
675
                     );
 
676
#elif !defined(NO_ASM)
 
677
# ifndef PIC
 
678
           asm volatile("pusha                             \n"
 
679
                "mov    pAsmStart, %%ecx           \n"  // = pStart
 
680
                "mov    $0, %%edx                  \n"          // The CRC
 
681
                "mov    dwAsmHeight, %%eax         \n"  // = y
 
682
                "0:                                \n" //l2:
 
683
                "mov    dwAsmdwBytesPerLine, %%ebx \n"  // = x
 
684
                "sub    $4, %%ebx                  \n"
 
685
                "1:                                \n" //l1:
 
686
                "mov    (%%ecx,%%ebx), %%esi       \n"
 
687
                "xor %%ebx, %%esi                  \n"
 
688
                "rol $4, %%edx                     \n"
 
689
                "add %%esi, %%edx                  \n"
 
690
                "sub    $4, %%ebx                  \n"
 
691
                "jge 1b                            \n" //jge l1
 
692
                "xor %%eax, %%esi                  \n"
 
693
                "add %%esi, %%edx                  \n"
 
694
                "add dwAsmPitch, %%ecx             \n"
 
695
                "dec %%eax                         \n"
 
696
                "jge 0b                            \n" //jge l2
 
697
                
 
698
                "mov    %%edx, dwAsmCRC            \n"
 
699
                "popa                              \n"
 
700
                :
 
701
                :
 
702
                : "memory", "cc"
 
703
                );
 
704
# else // PIC
 
705
           unsigned int saveEBX;
 
706
           unsigned int saveEAX;
 
707
           unsigned int saveECX;
 
708
           unsigned int saveEDX;
 
709
           unsigned int saveESI;
 
710
           unsigned int asmdwBytesPerLine = dwAsmdwBytesPerLine;
 
711
           unsigned int asmPitch = dwAsmPitch;
 
712
           unsigned int asmHeight = dwAsmHeight;
 
713
           unsigned int asmCRC;
 
714
           asm volatile("mov    %%ebx, %2                  \n"
 
715
                "mov    %%eax, %5                  \n"
 
716
                "mov    %%ecx, %7                  \n"
 
717
                "mov    %%edx, %8                  \n"
 
718
                "mov    %%esi, %9                  \n"
 
719
                "mov    %0, %%ecx                  \n"  // = pStart
 
720
                "mov    $0, %%edx                  \n"          // The CRC
 
721
                "mov    %1, %%eax                  \n"  // = y
 
722
                "0:                                \n" //l2:
 
723
                "mov    %3, %%ebx                  \n"  // = x
 
724
                "sub    $4, %%ebx                  \n"
 
725
                "1:                                \n" //l1:
 
726
                "mov    (%%ecx,%%ebx), %%esi       \n"
 
727
                "xor %%ebx, %%esi                  \n"
 
728
                "rol $4, %%edx                     \n"
 
729
                "add %%esi, %%edx                  \n"
 
730
                "sub    $4, %%ebx                  \n"
 
731
                "jge 1b                            \n" //jge l1
 
732
                "xor %%eax, %%esi                  \n"
 
733
                "add %%esi, %%edx                  \n"
 
734
                "add %4, %%ecx                     \n"
 
735
                "dec %%eax                         \n"
 
736
                "jge 0b                            \n" //jge l2
 
737
                
 
738
                "mov    %2, %%ebx                  \n"
 
739
                "mov    %%edx, %6                  \n"
 
740
                "mov    %5, %%eax                  \n"
 
741
                "mov    %7, %%ecx                  \n"
 
742
                "mov    %8, %%edx                  \n"
 
743
                "mov    %9, %%esi                  \n"
 
744
                :
 
745
                : "m"(pAsmStart), "m"(asmHeight), "m"(saveEBX), "m"(asmdwBytesPerLine), "m"(asmPitch), "m"(saveEAX), 
 
746
                "m"(asmCRC), "m"(saveECX), "m"(saveEDX), "m"(saveESI)
 
747
                : "memory", "cc"
 
748
                );
 
749
           dwAsmCRC = asmCRC;
 
750
# endif // PIC
 
751
#endif
 
752
        }
 
753
        catch(...)
 
754
        {
 
755
            TRACE0("Exception in texture CRC calculation");
 
756
        }
 
757
    }
 
758
    return dwAsmCRC;
 
759
}
 
760
unsigned char CalculateMaxCI(void *pPhysicalAddress, uint32 left, uint32 top, uint32 width, uint32 height, uint32 size, uint32 pitchInBytes )
 
761
{
 
762
    uint32 x, y;
 
763
    unsigned char *buf;
 
764
    unsigned char val = 0;
 
765
 
 
766
    if( TXT_SIZE_8b == size )
 
767
    {
 
768
        for( y = 0; y<height; y++ )
 
769
        {
 
770
            buf = (unsigned char*)pPhysicalAddress + left + pitchInBytes * (y+top);
 
771
            for( x=0; x<width; x++ )
 
772
            {
 
773
                if( buf[x] > val )  val = buf[x];
 
774
                if( val == 0xFF )
 
775
                    return 0xFF;
 
776
            }
 
777
        }
 
778
    }
 
779
    else
 
780
    {
 
781
        unsigned char val1,val2;
 
782
        left >>= 1;
 
783
        width >>= 1;
 
784
        for( y = 0; y<height; y++ )
 
785
        {
 
786
            buf = (unsigned char*)pPhysicalAddress + left + pitchInBytes * (y+top);
 
787
            for( x=0; x<width; x++ )
 
788
            {
 
789
                val1 = buf[x]>>4;
 
790
                val2 = buf[x]&0xF;
 
791
                if( val1 > val )    val = val1;
 
792
                if( val2 > val )    val = val2;
 
793
                if( val == 0xF )
 
794
                    return 0xF;
 
795
            }
 
796
        }
 
797
    }
 
798
 
 
799
    return val;
 
800
}
 
801
 
 
802
bool FrameBufferManager::FrameBufferInRDRAMCheckCRC()
 
803
{
 
804
    RecentCIInfo &p = *(g_uRecentCIInfoPtrs[0]);
 
805
    uint8 *pFrameBufferBase = (uint8*)(g_pRDRAMu8+p.dwAddr);
 
806
    uint32 pitch = (p.dwWidth << p.dwSize ) >> 1;
 
807
    uint32 crc = CalculateRDRAMCRC(pFrameBufferBase, 0, 0, p.dwWidth, p.dwHeight, p.dwSize, pitch);
 
808
    if( crc != p.dwCRC )
 
809
    {
 
810
        p.dwCRC = crc;
 
811
        TRACE0("Frame Buffer CRC mismitch, it is modified by CPU");
 
812
        return false;
 
813
    }
 
814
    else
 
815
    {
 
816
        return true;
 
817
    }
 
818
}
 
819
 
 
820
extern std::vector<uint32> frameWriteRecord;
 
821
void FrameBufferManager::FrameBufferWriteByCPU(uint32 addr, uint32 size)
 
822
{
 
823
    if( !frameBufferOptions.bProcessCPUWrite )  return;
 
824
    //WARNING(TRACE2("Frame Buffer Write, addr=%08X, CI Addr=%08X", addr, g_CI.dwAddr));
 
825
    status.frameWriteByCPU = TRUE;
 
826
    frameWriteRecord.push_back(addr&(g_dwRamSize-1));
 
827
}
 
828
 
 
829
extern RECT frameWriteByCPURect;
 
830
extern std::vector<RECT> frameWriteByCPURects;
 
831
extern RECT frameWriteByCPURectArray[20][20];
 
832
extern bool frameWriteByCPURectFlag[20][20];
 
833
#define FRAMEBUFFER_IN_BLOCK
 
834
bool FrameBufferManager::ProcessFrameWriteRecord()
 
835
{
 
836
    int size = frameWriteRecord.size();
 
837
    if( size == 0 ) return false;
 
838
 
 
839
    int index = FindRecentCIInfoIndex(frameWriteRecord[0]);
 
840
    if( index == -1 )
 
841
    {
 
842
        LOG_TEXTURE(TRACE1("Frame Buffer Write to non-record addr = %08X", frameWriteRecord[0]));
 
843
        frameWriteRecord.clear();
 
844
        return false;
 
845
    }
 
846
    else
 
847
    {
 
848
        uint32 base = g_uRecentCIInfoPtrs[index]->dwAddr;
 
849
        uint32 uwidth = g_uRecentCIInfoPtrs[index]->dwWidth;
 
850
        uint32 uheight = g_uRecentCIInfoPtrs[index]->dwHeight;
 
851
        uint32 upitch = uwidth<<1;
 
852
 
 
853
        frameWriteByCPURect.left=uwidth-1;
 
854
        frameWriteByCPURect.top = uheight-1;
 
855
 
 
856
        frameWriteByCPURect.right=0;
 
857
        frameWriteByCPURect.bottom = 0;
 
858
 
 
859
        int x, y, off;
 
860
 
 
861
        for( int i=0; i<size; i++ )
 
862
        {
 
863
            off = frameWriteRecord[i]-base;
 
864
            if( off < (int)g_uRecentCIInfoPtrs[index]->dwMemSize )
 
865
            {
 
866
                y = off/upitch;
 
867
                x = (off - y*upitch)>>1;
 
868
 
 
869
#ifdef FRAMEBUFFER_IN_BLOCK
 
870
                int xidx=x/32;
 
871
                int yidx=y/24;
 
872
 
 
873
                RECT &rect = frameWriteByCPURectArray[xidx][yidx];
 
874
 
 
875
                if( !frameWriteByCPURectFlag[xidx][yidx] )
 
876
                {
 
877
                    rect.left=rect.right=x;
 
878
                    rect.top=rect.bottom=y;
 
879
                    frameWriteByCPURectFlag[xidx][yidx]=true;
 
880
                }
 
881
                else
 
882
                {
 
883
                    if( x < rect.left ) rect.left = x;
 
884
                    if( x > rect.right ) rect.right = x;
 
885
                    if( y < rect.top )  rect.top = y;
 
886
                    if( y > rect.bottom ) rect.bottom = y;
 
887
                }
 
888
#else
 
889
                if( x < frameWriteByCPURect.left )  frameWriteByCPURect.left = x;
 
890
                if( x > frameWriteByCPURect.right ) frameWriteByCPURect.right = x;
 
891
                if( y < frameWriteByCPURect.top )   frameWriteByCPURect.top = y;
 
892
                if( y > frameWriteByCPURect.bottom ) frameWriteByCPURect.bottom = y;
 
893
#endif
 
894
            }
 
895
        }
 
896
 
 
897
        frameWriteRecord.clear();
 
898
        LOG_TEXTURE(TRACE4("Frame Buffer Write: Left=%d, Top=%d, Right=%d, Bottom=%d", frameWriteByCPURect.left,
 
899
            frameWriteByCPURect.top, frameWriteByCPURect.right, frameWriteByCPURect.bottom));
 
900
        return true;
 
901
    }
 
902
}
 
903
 
 
904
void FrameBufferManager::FrameBufferReadByCPU( uint32 addr )
 
905
{
 
906
    ///return;  // it does not work very well anyway
 
907
 
 
908
 
 
909
    if( !frameBufferOptions.bProcessCPURead )   return;
 
910
 
 
911
    addr &= (g_dwRamSize-1);
 
912
    int index = FindRecentCIInfoIndex(addr);
 
913
    if( index == -1 ) 
 
914
    {
 
915
        // Check if this is the depth buffer
 
916
        uint32 size = 2*g_RecentCIInfo[0].dwWidth*g_RecentCIInfo[0].dwHeight;
 
917
        addr &= 0x3FFFFFFF;
 
918
 
 
919
        if( addr >= g_ZI.dwAddr && addr < g_ZI.dwAddr + size )
 
920
        {
 
921
            TXTRBUF_OR_CI_DUMP(TRACE1("Depth Buffer read, reported by emulator, addr=%08X", addr));
 
922
        }
 
923
        else
 
924
        {
 
925
            return;
 
926
        }
 
927
    }
 
928
 
 
929
    if( status.gDlistCount - g_uRecentCIInfoPtrs[index]->lastUsedFrame > 3 )
 
930
    {
 
931
        // Ok, we don't have this frame anymore
 
932
        return;
 
933
    }
 
934
 
 
935
    //TXTRBUF_OR_CI_DUMP(TRACE1("FB Read By CPU at %08X", addr));
 
936
    if( g_uRecentCIInfoPtrs[index]->bCopied )   return;
 
937
    //if( addr != g_uRecentCIInfoPtrs[index]->dwAddr )  return;
 
938
 
 
939
    TXTRBUF_OR_CI_DUMP(TRACE1("Frame Buffer read, reported by emulator, addr=%08X", addr));
 
940
    uint32 size = 0x1000 - addr%0x1000;
 
941
    CheckAddrInBackBuffers(addr, size, true);
 
942
 
 
943
    DEBUGGER_IF_DUMP(pauseAtNext,{TRACE0("Frame Buffer read");});
 
944
    DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_RENDER_TEXTURE, 
 
945
    {DebuggerAppendMsg("Paused after setting Frame Buffer read:\n Cur CI Addr: 0x%08x, Fmt: %s Size: %s Width: %d",
 
946
    g_CI.dwAddr, pszImgFormat[g_CI.dwFormat], pszImgSize[g_CI.dwSize], g_CI.dwWidth);});
 
947
}
 
948
 
 
949
 
 
950
 
 
951
extern RECT frameWriteByCPURect;
 
952
extern std::vector<RECT> frameWriteByCPURects;
 
953
extern RECT frameWriteByCPURectArray[20][20];
 
954
extern bool frameWriteByCPURectFlag[20][20];
 
955
#define FRAMEBUFFER_IN_BLOCK
 
956
 
 
957
void FrameBufferManager::UpdateFrameBufferBeforeUpdateFrame()
 
958
{
 
959
    if( (frameBufferOptions.bProcessCPUWrite && status.frameWriteByCPU ) ||
 
960
        (frameBufferOptions.bLoadBackBufFromRDRAM && !FrameBufferInRDRAMCheckCRC() ) )      
 
961
        // Checks if frame buffer has been modified by CPU
 
962
        // Only happens to Dr. Mario
 
963
    {
 
964
        if( frameBufferOptions.bProcessCPUWrite )
 
965
        {
 
966
            if( ProcessFrameWriteRecord() )
 
967
            {
 
968
#ifdef FRAMEBUFFER_IN_BLOCK
 
969
                int i,j;
 
970
                for( i=0; i<20; i++)
 
971
                {
 
972
                    for( j=0; j<20; j++ )
 
973
                    {
 
974
                        if( frameWriteByCPURectFlag[i][j] )
 
975
                        {
 
976
                            CRender::GetRender()->DrawFrameBuffer(false, frameWriteByCPURectArray[i][j].left, frameWriteByCPURectArray[i][j].top,
 
977
                                frameWriteByCPURectArray[i][j].right-frameWriteByCPURectArray[i][j].left+1, frameWriteByCPURectArray[i][j].bottom-frameWriteByCPURectArray[i][j].top+1);
 
978
                        }
 
979
                    }
 
980
                }
 
981
                for( i=0; i<20; i++)
 
982
                {
 
983
                    for( j=0; j<20; j++ )
 
984
                    {
 
985
                        if( frameWriteByCPURectFlag[i][j] )
 
986
                        {
 
987
                            ClearN64FrameBufferToBlack(frameWriteByCPURectArray[i][j].left, frameWriteByCPURectArray[i][j].top,
 
988
                                frameWriteByCPURectArray[i][j].right-frameWriteByCPURectArray[i][j].left+1, frameWriteByCPURectArray[i][j].bottom-frameWriteByCPURectArray[i][j].top+1);
 
989
                            frameWriteByCPURectFlag[i][j] = false;
 
990
                        }
 
991
                    }
 
992
                }
 
993
                //memset(frameWriteByCPURectArray, 0, sizeof(frameWriteByCPURectArray));
 
994
                //memset(frameWriteByCPURectFlag, 0, sizeof(frameWriteByCPURectFlag));
 
995
#else
 
996
                CRender::GetRender()->DrawFrameBuffer(false, frameWriteByCPURect.left, frameWriteByCPURect.top,
 
997
                    frameWriteByCPURect.right-frameWriteByCPURect.left, frameWriteByCPURect.bottom-frameWriteByCPURect.top);
 
998
                ClearN64FrameBufferToBlack(frameWriteByCPURect.left, frameWriteByCPURect.top,
 
999
                    frameWriteByCPURect.right-frameWriteByCPURect.left+1, frameWriteByCPURect.bottom-frameWriteByCPURect.top+1);
 
1000
 
 
1001
                /*
 
1002
                int size = frameWriteByCPURects.size();
 
1003
                for( int i=0; i<size; i++)
 
1004
                {
 
1005
                CRender::GetRender()->DrawFrameBuffer(false, frameWriteByCPURects[i].left, frameWriteByCPURects[i].top,
 
1006
                frameWriteByCPURects[i].right-frameWriteByCPURects[i].left, frameWriteByCPURects[i].bottom-frameWriteByCPURects[i].top);
 
1007
                ClearN64FrameBufferToBlack(frameWriteByCPURects[i].left, frameWriteByCPURects[i].top,
 
1008
                frameWriteByCPURects[i].right-frameWriteByCPURects[i].left+1, frameWriteByCPURects[i].bottom-frameWriteByCPURects[i].top+1);
 
1009
                }
 
1010
                frameWriteByCPURects.clear();
 
1011
                */
 
1012
#endif
 
1013
            }
 
1014
            status.frameWriteByCPU = FALSE;
 
1015
        }
 
1016
        else
 
1017
        {
 
1018
            if (CRender::IsAvailable())
 
1019
            {
 
1020
                RecentCIInfo &p = *(g_uRecentCIInfoPtrs[0]);
 
1021
                CRender::GetRender()->DrawFrameBuffer(false, 0,0,p.dwWidth,p.dwHeight);
 
1022
                ClearN64FrameBufferToBlack();
 
1023
            }
 
1024
        }
 
1025
    }
 
1026
}
 
1027
 
 
1028
uint32 FrameBufferManager::ComputeCImgHeight(SetImgInfo &info, uint32 &height)
 
1029
{
 
1030
    uint32 dwPC = gDlistStack[gDlistStackPointer].pc;       // This points to the next instruction
 
1031
 
 
1032
    for( int i=0; i<10; i++ )
 
1033
    {
 
1034
        uint32 w0 = *(uint32 *)(g_pRDRAMu8 + dwPC + i*8);
 
1035
        uint32 w1 = *(uint32 *)(g_pRDRAMu8 + dwPC + 4 + i*8);
 
1036
 
 
1037
        if( (w0>>24) == RDP_SETSCISSOR )
 
1038
        {
 
1039
            height   = ((w1>>0 )&0xFFF)/4;
 
1040
            TXTRBUF_DETAIL_DUMP(TRACE1("buffer height = %d", height));
 
1041
            return RDP_SETSCISSOR;
 
1042
        }
 
1043
 
 
1044
        if( (w0>>24) == RDP_FILLRECT )
 
1045
        {
 
1046
            uint32 x0   = ((w1>>12)&0xFFF)/4;
 
1047
            uint32 y0   = ((w1>>0 )&0xFFF)/4;
 
1048
            uint32 x1   = ((w0>>12)&0xFFF)/4;
 
1049
            uint32 y1   = ((w0>>0 )&0xFFF)/4;
 
1050
 
 
1051
            if( x0 == 0 && y0 == 0 )
 
1052
            {
 
1053
                if( x1 == info.dwWidth )
 
1054
                {
 
1055
                    height = y1;
 
1056
                    TXTRBUF_DETAIL_DUMP(TRACE1("buffer height = %d", height));
 
1057
                    return RDP_FILLRECT;
 
1058
                }
 
1059
 
 
1060
                if(x1 == (unsigned int)(info.dwWidth-1))
 
1061
                {
 
1062
                    height = y1+1;
 
1063
                    TXTRBUF_DETAIL_DUMP(TRACE1("buffer height = %d", height));
 
1064
                    return RDP_FILLRECT;
 
1065
                }
 
1066
            }
 
1067
        }   
 
1068
 
 
1069
        if( (w0>>24) == RDP_SETCIMG )
 
1070
        {
 
1071
            goto step2;
 
1072
        }
 
1073
 
 
1074
        if( (w0>>24) == RDP_SETCIMG )
 
1075
        {
 
1076
            goto step2;
 
1077
        }
 
1078
    }
 
1079
 
 
1080
    if( gRDP.scissor.left == 0 && gRDP.scissor.top == 0 && (unsigned int)gRDP.scissor.right == info.dwWidth )
 
1081
    {
 
1082
        height = gRDP.scissor.bottom;
 
1083
        TXTRBUF_DETAIL_DUMP(TRACE1("buffer height = %d", height));
 
1084
        return RDP_SETSCISSOR+1;
 
1085
    }
 
1086
 
 
1087
step2:
 
1088
    TXTRBUF_DETAIL_DUMP(TRACE0("Not sure about buffer height"));
 
1089
 
 
1090
    height = info.dwWidth*3/4;
 
1091
    if( status.dwTvSystem == TV_SYSTEM_PAL )
 
1092
    {
 
1093
        height = info.dwWidth*9/11;
 
1094
    }
 
1095
 
 
1096
    if( gRDP.scissor.bottom < (int)height && gRDP.scissor.bottom != 0 )
 
1097
    {
 
1098
        height = gRDP.scissor.bottom;
 
1099
    }
 
1100
 
 
1101
    if( info.dwAddr + height*info.dwWidth*info.dwSize >= g_dwRamSize )
 
1102
    {
 
1103
        height = info.dwWidth*3/4;
 
1104
        if( status.dwTvSystem == TV_SYSTEM_PAL )
 
1105
        {
 
1106
            height = info.dwWidth*9/11;
 
1107
        }
 
1108
 
 
1109
        if( gRDP.scissor.bottom < (int)height && gRDP.scissor.bottom != 0 )
 
1110
        {
 
1111
            height = gRDP.scissor.bottom;
 
1112
        }
 
1113
 
 
1114
        if( info.dwAddr + height*info.dwWidth*info.dwSize >= g_dwRamSize )
 
1115
        {
 
1116
            height = ( g_dwRamSize - info.dwAddr ) / info.dwWidth;
 
1117
        }
 
1118
    }
 
1119
 
 
1120
    TXTRBUF_DETAIL_DUMP(TRACE1("render_texture height = %d", height));
 
1121
    return 0;
 
1122
}
 
1123
 
 
1124
int FrameBufferManager::CheckRenderTexturesWithNewCI(SetImgInfo &CIinfo, uint32 height, bool byNewTxtrBuf)
 
1125
{
 
1126
    int matchidx = -1;
 
1127
    uint32 memsize = ((height*CIinfo.dwWidth)>>1)<<CIinfo.dwSize;
 
1128
 
 
1129
    for( int i=0; i<numOfTxtBufInfos; i++ )
 
1130
    {
 
1131
        RenderTextureInfo &info = gRenderTextureInfos[i];
 
1132
        if( !info.isUsed )  continue;
 
1133
 
 
1134
        bool covered = false;
 
1135
 
 
1136
        if( info.CI_Info.dwAddr == CIinfo.dwAddr )
 
1137
        {
 
1138
            if( info.CI_Info.dwSize == CIinfo.dwSize &&
 
1139
                info.CI_Info.dwWidth == CIinfo.dwWidth &&
 
1140
                info.CI_Info.dwFormat == CIinfo.dwFormat &&
 
1141
                info.N64Height == height 
 
1142
                && info.CI_Info.dwAddr == CIinfo.dwAddr 
 
1143
                )
 
1144
            {
 
1145
                // This is the same texture at the same address
 
1146
                if( byNewTxtrBuf )
 
1147
                {
 
1148
                    matchidx = i;
 
1149
                    break;
 
1150
                }
 
1151
            }
 
1152
 
 
1153
            // At the same address, but not the same size
 
1154
            //SAFE_DELETE(info.psurf);
 
1155
            covered = true;
 
1156
        }
 
1157
 
 
1158
        if( !covered )
 
1159
        {
 
1160
            uint32 memsize2 = ((info.N64Height*info.N64Width)>>1)<<info.CI_Info.dwSize;
 
1161
 
 
1162
            if( info.CI_Info.dwAddr > CIinfo.dwAddr && info.CI_Info.dwAddr < CIinfo.dwAddr + memsize)
 
1163
                covered = true;
 
1164
            else if( info.CI_Info.dwAddr+memsize2 > CIinfo.dwAddr && info.CI_Info.dwAddr+memsize2 < CIinfo.dwAddr + memsize)
 
1165
                covered = true;
 
1166
            else if( CIinfo.dwAddr > info.CI_Info.dwAddr && CIinfo.dwAddr < info.CI_Info.dwAddr + memsize2 )
 
1167
                covered = true;
 
1168
            else if( CIinfo.dwAddr+ memsize > info.CI_Info.dwAddr && CIinfo.dwAddr+ memsize < info.CI_Info.dwAddr + memsize2 )
 
1169
                covered = true;
 
1170
        }
 
1171
 
 
1172
        if( covered )
 
1173
        {
 
1174
            //SAFE_DELETE(info.psurf);
 
1175
            if( info.pRenderTexture->IsBeingRendered() )
 
1176
            {
 
1177
                TRACE0("Error, covering a render_texture which is being rendered");
 
1178
                TRACE3("New addrr=%08X, width=%d, height=%d", CIinfo.dwAddr, CIinfo.dwWidth, height );
 
1179
                TRACE3("Old addrr=%08X, width=%d, height=%d", info.CI_Info.dwAddr, info.N64Width, info.N64Height );
 
1180
            }
 
1181
            info.isUsed = false;
 
1182
            TXTRBUF_DUMP(TRACE5("Delete txtr buf %d at %08X, covered by new CI at %08X, Width=%d, Height=%d", 
 
1183
                i, info.CI_Info.dwAddr, CIinfo.dwAddr, CIinfo.dwWidth, height ));
 
1184
            SAFE_DELETE(info.pRenderTexture);
 
1185
            info.txtEntry.pTexture = NULL;
 
1186
            continue;
 
1187
        }
 
1188
    }
 
1189
 
 
1190
    return matchidx;
 
1191
}
 
1192
 
 
1193
extern RecentCIInfo *g_uRecentCIInfoPtrs[5];
 
1194
RenderTextureInfo newRenderTextureInfo;
 
1195
 
 
1196
int FrameBufferManager::FindASlot(void)
 
1197
{
 
1198
    int idx;
 
1199
 
 
1200
    // Find an empty slot
 
1201
    bool found = false;
 
1202
    for( int i=0; i<numOfTxtBufInfos; i++ )
 
1203
    {
 
1204
        if( !gRenderTextureInfos[i].isUsed && gRenderTextureInfos[i].updateAtFrame < status.gDlistCount )
 
1205
        {
 
1206
            found = true;
 
1207
            idx = i;
 
1208
            break;
 
1209
        }
 
1210
    }
 
1211
 
 
1212
    // If cannot find an empty slot, find the oldest slot and reuse the slot
 
1213
    if( !found )
 
1214
    {
 
1215
        uint32 oldestCount=0xFFFFFFFF;
 
1216
        uint32 oldestIdx = 0;
 
1217
        for( int i=0; i<numOfTxtBufInfos; i++ )
 
1218
        {
 
1219
            if( gRenderTextureInfos[i].updateAtUcodeCount < oldestCount )
 
1220
            {
 
1221
                oldestCount = gRenderTextureInfos[i].updateAtUcodeCount;
 
1222
                oldestIdx = i;
 
1223
            }
 
1224
        }
 
1225
 
 
1226
        idx = oldestIdx;
 
1227
    }
 
1228
 
 
1229
    DEBUGGER_IF_DUMP((logTextureBuffer && gRenderTextureInfos[idx].pRenderTexture ),TRACE2("Delete txtr buf %d at %08X, to reuse it.", idx, gRenderTextureInfos[idx].CI_Info.dwAddr ));
 
1230
    SAFE_DELETE(gRenderTextureInfos[idx].pRenderTexture) ;
 
1231
 
 
1232
    return idx;
 
1233
}
 
1234
 
 
1235
 
 
1236
void FrameBufferManager::SetRenderTexture(void)
 
1237
{
 
1238
    memcpy(&(newRenderTextureInfo.CI_Info), &g_CI, sizeof(SetImgInfo));
 
1239
 
 
1240
    newRenderTextureInfo.N64Width = newRenderTextureInfo.CI_Info.dwWidth;
 
1241
    newRenderTextureInfo.knownHeight = ComputeCImgHeight(g_CI, newRenderTextureInfo.N64Height);
 
1242
 
 
1243
    status.bHandleN64RenderTexture = true;
 
1244
    newRenderTextureInfo.maxUsedHeight = 0;
 
1245
 
 
1246
    if( defaultRomOptions.bInN64Resolution )
 
1247
    {
 
1248
        newRenderTextureInfo.bufferWidth = newRenderTextureInfo.N64Width;
 
1249
        newRenderTextureInfo.bufferHeight = newRenderTextureInfo.N64Height;
 
1250
    }
 
1251
    else if( defaultRomOptions.bDoubleSizeForSmallTxtrBuf && newRenderTextureInfo.N64Width<=128 && newRenderTextureInfo.N64Height<=128)
 
1252
    {
 
1253
        newRenderTextureInfo.bufferWidth = newRenderTextureInfo.N64Width*2;
 
1254
        newRenderTextureInfo.bufferHeight = newRenderTextureInfo.N64Height*2;
 
1255
    }
 
1256
    else
 
1257
    {
 
1258
        newRenderTextureInfo.bufferWidth = newRenderTextureInfo.N64Width;
 
1259
        newRenderTextureInfo.bufferHeight = newRenderTextureInfo.N64Height;
 
1260
    }
 
1261
 
 
1262
    newRenderTextureInfo.scaleX = newRenderTextureInfo.bufferWidth / float(newRenderTextureInfo.N64Width);
 
1263
    newRenderTextureInfo.scaleY = newRenderTextureInfo.bufferHeight / float(newRenderTextureInfo.N64Height);
 
1264
 
 
1265
    status.bFrameBufferIsDrawn = false;
 
1266
    status.bFrameBufferDrawnByTriangles = false;
 
1267
 
 
1268
    newRenderTextureInfo.updateAtFrame = status.gDlistCount;
 
1269
    newRenderTextureInfo.updateAtUcodeCount = status.gUcodeCount;
 
1270
 
 
1271
    // Delay activation of the render_texture until the 1st rendering
 
1272
 
 
1273
    TXTRBUF_DUMP(TRACE1("Set render_texture: addr=%08X", g_CI.dwAddr));
 
1274
    DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_RENDER_TEXTURE, 
 
1275
    {DebuggerAppendMsg("Paused after setting render_texture:\nAddr: 0x%08x, Fmt: %s Size: %s Width: %d, Height:%d",
 
1276
    g_CI.dwAddr, pszImgFormat[g_CI.dwFormat], pszImgSize[g_CI.dwSize], g_CI.dwWidth, g_pRenderTextureInfo->N64Height);});
 
1277
}
 
1278
 
 
1279
int FrameBufferManager::SetBackBufferAsRenderTexture(SetImgInfo &CIinfo, int ciInfoIdx)
 
1280
{
 
1281
/* MUDLORD:
 
1282
OK, heres the drill!
 
1283
* We  set the graphics card's back buffer's contents as a render_texure
 
1284
* This is done due to how the current framebuffer implementation detects
 
1285
  changes to the backbuffer memory pointer and then we do a texture
 
1286
  copy. This might be slow since it doesnt use hardware auxillary buffers*/
 
1287
         
 
1288
 
 
1289
    RenderTextureInfo tempRenderTextureInfo;
 
1290
 
 
1291
    memcpy(&(tempRenderTextureInfo.CI_Info), &CIinfo, sizeof(SetImgInfo));
 
1292
 
 
1293
    tempRenderTextureInfo.N64Width = g_uRecentCIInfoPtrs[ciInfoIdx]->dwLastWidth;
 
1294
    tempRenderTextureInfo.N64Height = g_uRecentCIInfoPtrs[ciInfoIdx]->dwLastHeight;
 
1295
    tempRenderTextureInfo.knownHeight = true;
 
1296
    tempRenderTextureInfo.maxUsedHeight = 0;
 
1297
 
 
1298
    tempRenderTextureInfo.bufferWidth = windowSetting.uDisplayWidth;
 
1299
    tempRenderTextureInfo.bufferHeight = windowSetting.uDisplayHeight;
 
1300
 
 
1301
    tempRenderTextureInfo.scaleX = tempRenderTextureInfo.bufferWidth / float(tempRenderTextureInfo.N64Width);
 
1302
    tempRenderTextureInfo.scaleY = tempRenderTextureInfo.bufferHeight / float(tempRenderTextureInfo.N64Height);
 
1303
 
 
1304
    status.bFrameBufferIsDrawn = false;
 
1305
    status.bFrameBufferDrawnByTriangles = false;
 
1306
 
 
1307
    tempRenderTextureInfo.updateAtFrame = status.gDlistCount;
 
1308
    tempRenderTextureInfo.updateAtUcodeCount = status.gUcodeCount;
 
1309
 
 
1310
    // Checking against previous render_texture infos
 
1311
    //uint32 memsize = ((tempRenderTextureInfo.N64Height*tempRenderTextureInfo.N64Width)>>1)<<tempRenderTextureInfo.CI_Info.dwSize;
 
1312
    int matchidx = CheckRenderTexturesWithNewCI(CIinfo,tempRenderTextureInfo.N64Height,false);
 
1313
    int idxToUse = (matchidx >= 0) ? matchidx : FindASlot();
 
1314
 
 
1315
    if( gRenderTextureInfos[idxToUse].pRenderTexture == NULL || matchidx < 0 )
 
1316
    {
 
1317
        gRenderTextureInfos[idxToUse].pRenderTexture = 
 
1318
        new COGLRenderTexture(tempRenderTextureInfo.bufferWidth, tempRenderTextureInfo.bufferHeight, &gRenderTextureInfos[idxToUse], AS_BACK_BUFFER_SAVE);
 
1319
    }
 
1320
 
 
1321
    // Need to set all variables for gRenderTextureInfos[idxToUse]
 
1322
    CRenderTexture *pRenderTexture = gRenderTextureInfos[idxToUse].pRenderTexture;
 
1323
    memcpy(&gRenderTextureInfos[idxToUse], &tempRenderTextureInfo, sizeof(RenderTextureInfo) );
 
1324
    gRenderTextureInfos[idxToUse].pRenderTexture = pRenderTexture;
 
1325
    gRenderTextureInfos[idxToUse].isUsed = true;
 
1326
    gRenderTextureInfos[idxToUse].txtEntry.pTexture = pRenderTexture->m_pTexture;
 
1327
    gRenderTextureInfos[idxToUse].txtEntry.txtrBufIdx = idxToUse+1;
 
1328
 
 
1329
    TXTRBUF_DUMP(TRACE2("Set back buf as render_texture %d, addr=%08X", idxToUse, CIinfo.dwAddr));
 
1330
    DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_RENDER_TEXTURE, 
 
1331
    {DebuggerAppendMsg("Paused after setting render_texture:\nAddr: 0x%08x, Fmt: %s Size: %s Width: %d, Height:%d",
 
1332
    CIinfo.dwAddr, pszImgFormat[CIinfo.dwFormat], pszImgSize[CIinfo.dwSize], CIinfo.dwWidth, g_pRenderTextureInfo->N64Height);});
 
1333
 
 
1334
    return idxToUse;
 
1335
}
 
1336
 
 
1337
void FrameBufferManager::CloseRenderTexture(bool toSave)
 
1338
{
 
1339
    if( m_curRenderTextureIndex < 0 )   return;
 
1340
 
 
1341
    status.bHandleN64RenderTexture = false;
 
1342
    if( status.bDirectWriteIntoRDRAM )
 
1343
    {
 
1344
    }
 
1345
    else 
 
1346
    {
 
1347
        RestoreNormalBackBuffer();
 
1348
        if( !toSave || !status.bFrameBufferIsDrawn || !status.bFrameBufferDrawnByTriangles )
 
1349
        {
 
1350
            TXTRBUF_DUMP(TRACE0("Closing render_texture without save"););
 
1351
            SAFE_DELETE(gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture);
 
1352
            gRenderTextureInfos[m_curRenderTextureIndex].isUsed = false;
 
1353
            TXTRBUF_DUMP(TRACE1("Delete render_texture %d",m_curRenderTextureIndex););
 
1354
        }
 
1355
        else
 
1356
        {
 
1357
            TXTRBUF_DUMP(TRACE1("Closing render_texture %d", m_curRenderTextureIndex););
 
1358
            StoreRenderTextureToRDRAM();
 
1359
 
 
1360
            if( frameBufferOptions.bRenderTextureWriteBack )
 
1361
            {
 
1362
                SAFE_DELETE(gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture);
 
1363
                gRenderTextureInfos[m_curRenderTextureIndex].isUsed = false;
 
1364
                TXTRBUF_DUMP(TRACE1("Delete render_texture %d after writing back to RDRAM",m_curRenderTextureIndex););
 
1365
            }
 
1366
            else
 
1367
            {
 
1368
                g_pRenderTextureInfo->crcInRDRAM = ComputeRenderTextureCRCInRDRAM(m_curRenderTextureIndex);
 
1369
                g_pRenderTextureInfo->crcCheckedAtFrame = status.gDlistCount;
 
1370
            }
 
1371
        }
 
1372
    }
 
1373
 
 
1374
    SetScreenMult(windowSetting.uDisplayWidth/windowSetting.fViWidth, windowSetting.uDisplayHeight/windowSetting.fViHeight);
 
1375
    CRender::g_pRender->UpdateClipRectangle();
 
1376
    CRender::g_pRender->ApplyScissorWithClipRatio();
 
1377
 
 
1378
    DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_RENDER_TEXTURE, 
 
1379
    {
 
1380
        DebuggerAppendMsg("Paused after saving render_texture %d:\nAddr: 0x%08x, Fmt: %s Size: %s Width: %d", m_curRenderTextureIndex,
 
1381
            g_pRenderTextureInfo->CI_Info.dwAddr, pszImgFormat[g_pRenderTextureInfo->CI_Info.dwFormat], pszImgSize[g_pRenderTextureInfo->CI_Info.dwSize], g_pRenderTextureInfo->CI_Info.dwWidth);
 
1382
    });
 
1383
}
 
1384
 
 
1385
void FrameBufferManager::ClearN64FrameBufferToBlack(uint32 left, uint32 top, uint32 width, uint32 height)
 
1386
{
 
1387
    RecentCIInfo &p = *(g_uRecentCIInfoPtrs[0]);
 
1388
    uint16 *frameBufferBase = (uint16*)(g_pRDRAMu8+p.dwAddr);
 
1389
    uint32 pitch = p.dwWidth;
 
1390
 
 
1391
    if( width == 0 || height == 0 )
 
1392
    {
 
1393
        uint32 len = p.dwHeight*p.dwWidth*p.dwSize;
 
1394
        if( p.dwSize == TXT_SIZE_4b ) len = (p.dwHeight*p.dwWidth)>>1;
 
1395
        memset(frameBufferBase, 0, len);
 
1396
    }
 
1397
    else
 
1398
    {
 
1399
        for( uint32 y=0; y<height; y++)
 
1400
        {
 
1401
            for( uint32 x=0; x<width; x++ )
 
1402
            {
 
1403
                *(frameBufferBase+(y+top)*pitch+x+left) = 0;
 
1404
            }
 
1405
        }
 
1406
    }
 
1407
}
 
1408
 
 
1409
uint8 RevTlutTable[0x10000];
 
1410
bool RevTlutTableNeedUpdate = false;
 
1411
void InitTlutReverseLookup(void)
 
1412
{
 
1413
    if( RevTlutTableNeedUpdate )
 
1414
    {
 
1415
        memset(RevTlutTable, 0, 0x10000);
 
1416
        for( int i=0; i<=0xFF; i++ )
 
1417
        {
 
1418
            RevTlutTable[g_wRDPTlut[i]] = uint8(i);
 
1419
        }
 
1420
 
 
1421
        RevTlutTableNeedUpdate = false;
 
1422
    }
 
1423
}
 
1424
 
 
1425
 
 
1426
//copies backbuffer to N64 framebuffer by notification by emu core
 
1427
// **buggy**
 
1428
void FrameBufferManager::CopyBackToFrameBufferIfReadByCPU(uint32 addr)
 
1429
{
 
1430
    int i = FindRecentCIInfoIndex(addr);
 
1431
    if( i != -1 )
 
1432
    {
 
1433
        //if( i == 0 ) CGraphicsContext::Get()->UpdateFrame();
 
1434
        RecentCIInfo *info = g_uRecentCIInfoPtrs[i];
 
1435
        StoreBackBufferToRDRAM( info->dwAddr, info->dwFormat, info->dwSize, info->dwWidth, info->dwHeight, 
 
1436
            windowSetting.uDisplayWidth, windowSetting.uDisplayHeight, addr, 0x1000-addr%0x1000);
 
1437
        TRACE1("Copy back for CI Addr=%08X", info->dwAddr);
 
1438
    }
 
1439
}
 
1440
//we do this checks to see if a render_texture operation is occuring...
 
1441
void FrameBufferManager::CheckRenderTextureCRCInRDRAM(void)
 
1442
{
 
1443
    for( int i=0; i<numOfTxtBufInfos; i++ )
 
1444
    {
 
1445
        if( !gRenderTextureInfos[i].isUsed )    
 
1446
            continue;
 
1447
 
 
1448
        if( gRenderTextureInfos[i].pRenderTexture->IsBeingRendered() )
 
1449
            continue;
 
1450
 
 
1451
        if( gRenderTextureInfos[i].crcCheckedAtFrame < status.gDlistCount )
 
1452
        {
 
1453
            uint32 crc = ComputeRenderTextureCRCInRDRAM(i);
 
1454
            if( gRenderTextureInfos[i].crcInRDRAM != crc )
 
1455
            {
 
1456
                // RDRAM has been modified by CPU core
 
1457
                TXTRBUF_DUMP(TRACE2("Delete txtr buf %d at %08X, CRC in RDRAM changed", i, gRenderTextureInfos[i].CI_Info.dwAddr ));
 
1458
                SAFE_DELETE(gRenderTextureInfos[i].pRenderTexture);
 
1459
                gRenderTextureInfos[i].isUsed = false;
 
1460
                continue;
 
1461
            }
 
1462
            else
 
1463
            {
 
1464
                gRenderTextureInfos[i].crcCheckedAtFrame = status.gDlistCount;
 
1465
            }
 
1466
        }
 
1467
    }
 
1468
}
 
1469
 
 
1470
//check render_texture memory addresses
 
1471
int FrameBufferManager::CheckAddrInRenderTextures(uint32 addr, bool checkcrc)
 
1472
{
 
1473
    for( int i=0; i<numOfTxtBufInfos; i++ )
 
1474
    {
 
1475
        if( !gRenderTextureInfos[i].isUsed )    
 
1476
            continue;
 
1477
 
 
1478
        if( gRenderTextureInfos[i].pRenderTexture->IsBeingRendered() )
 
1479
            continue;
 
1480
 
 
1481
        uint32 bufHeight = gRenderTextureInfos[i].knownHeight ? gRenderTextureInfos[i].N64Height : gRenderTextureInfos[i].maxUsedHeight;
 
1482
        uint32 bufMemSize = gRenderTextureInfos[i].CI_Info.dwSize*gRenderTextureInfos[i].N64Width*bufHeight;
 
1483
        if( addr >=gRenderTextureInfos[i].CI_Info.dwAddr && addr < gRenderTextureInfos[i].CI_Info.dwAddr+bufMemSize)
 
1484
        {
 
1485
            if(checkcrc)
 
1486
            {
 
1487
                // Check the CRC in RDRAM
 
1488
                if( gRenderTextureInfos[i].crcCheckedAtFrame < status.gDlistCount )
 
1489
                {
 
1490
                    uint32 crc = ComputeRenderTextureCRCInRDRAM(i);
 
1491
                    if( gRenderTextureInfos[i].crcInRDRAM != crc )
 
1492
                    {
 
1493
                        // RDRAM has been modified by CPU core
 
1494
                        TRACE3("Buf %d CRC in RDRAM changed from %08X to %08X", i, gRenderTextureInfos[i].crcInRDRAM, crc );
 
1495
                        TXTRBUF_DUMP(TRACE2("Delete txtr buf %d at %08X, crcInRDRAM failed.", i, gRenderTextureInfos[i].CI_Info.dwAddr ));
 
1496
                        SAFE_DELETE(gRenderTextureInfos[i].pRenderTexture);
 
1497
                        gRenderTextureInfos[i].isUsed = false;
 
1498
                        continue;
 
1499
                    }
 
1500
                    else
 
1501
                    {
 
1502
                        gRenderTextureInfos[i].crcCheckedAtFrame = status.gDlistCount;
 
1503
                    }
 
1504
                }
 
1505
            }
 
1506
 
 
1507
            TXTRBUF_DUMP(TRACE2("Loading texture addr = %08X from txtr buf %d", addr, i));
 
1508
            return i;
 
1509
        }
 
1510
    }
 
1511
 
 
1512
    return -1;
 
1513
}
 
1514
 
 
1515
//load texture from render_texture buffer
 
1516
void FrameBufferManager::LoadTextureFromRenderTexture(TxtrCacheEntry* pEntry, int infoIdx)
 
1517
{
 
1518
    if( infoIdx < 0 || infoIdx >= numOfTxtBufInfos )
 
1519
    {
 
1520
        infoIdx = CheckAddrInRenderTextures(pEntry->ti.Address);
 
1521
    }
 
1522
 
 
1523
    if( infoIdx >= 0 && gRenderTextureInfos[infoIdx].isUsed && gRenderTextureInfos[infoIdx].pRenderTexture )
 
1524
    {
 
1525
        TXTRBUF_DUMP(TRACE1("Loading from render_texture %d", infoIdx));
 
1526
        gRenderTextureInfos[infoIdx].pRenderTexture->LoadTexture(pEntry);
 
1527
    }
 
1528
}
 
1529
 
 
1530
void FrameBufferManager::RestoreNormalBackBuffer()
 
1531
{
 
1532
    if( m_curRenderTextureIndex >= 0 && m_curRenderTextureIndex < numOfTxtBufInfos )
 
1533
    {
 
1534
        if( gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture )
 
1535
            gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture->SetAsRenderTarget(false);
 
1536
        m_isRenderingToTexture = false;
 
1537
        m_lastTextureBufferIndex = m_curRenderTextureIndex;
 
1538
    }
 
1539
 
 
1540
    if( !status.bFrameBufferIsDrawn || !status.bFrameBufferDrawnByTriangles )
 
1541
    {
 
1542
        gRenderTextureInfos[m_curRenderTextureIndex].isUsed = false;
 
1543
        TXTRBUF_DUMP(TRACE2("Delete txtr buf %d at %08X, it is never rendered", m_curRenderTextureIndex, gRenderTextureInfos[m_curRenderTextureIndex].CI_Info.dwAddr ));
 
1544
        SAFE_DELETE(gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture);
 
1545
    }
 
1546
}
 
1547
 
 
1548
uint32 FrameBufferManager::ComputeRenderTextureCRCInRDRAM(int infoIdx)
 
1549
{
 
1550
    if( infoIdx >= numOfTxtBufInfos || infoIdx < 0 || !gRenderTextureInfos[infoIdx].isUsed )
 
1551
        return 0;
 
1552
 
 
1553
    RenderTextureInfo &info = gRenderTextureInfos[infoIdx];
 
1554
    uint32 height = info.knownHeight ? info.N64Height : info.maxUsedHeight;
 
1555
    uint8 *pAddr = (uint8*)(g_pRDRAMu8+info.CI_Info.dwAddr);
 
1556
    uint32 pitch = (info.N64Width << info.CI_Info.dwSize ) >> 1;
 
1557
 
 
1558
    return CalculateRDRAMCRC(pAddr, 0, 0, info.N64Width, height, info.CI_Info.dwSize, pitch);
 
1559
}
 
1560
 
 
1561
//activates texture buffer for drawing
 
1562
void FrameBufferManager::ActiveTextureBuffer(void)
 
1563
{
 
1564
    status.bCIBufferIsRendered = true;
 
1565
 
 
1566
    if( status.bHandleN64RenderTexture )
 
1567
    {
 
1568
        // Checking against previous render_texture infos
 
1569
        int matchidx = -1;
 
1570
 
 
1571
        //uint32 memsize = ((newRenderTextureInfo.N64Height*newRenderTextureInfo.N64Width)>>1)<<newRenderTextureInfo.CI_Info.dwSize;
 
1572
 
 
1573
        matchidx = CheckRenderTexturesWithNewCI(g_CI,newRenderTextureInfo.N64Height,true);
 
1574
 
 
1575
        int idxToUse=-1;
 
1576
        if( matchidx >= 0 )
 
1577
        {
 
1578
            // Reuse the matched slot
 
1579
            idxToUse = matchidx;
 
1580
        }
 
1581
        else
 
1582
        {
 
1583
            idxToUse = FindASlot();
 
1584
        }
 
1585
 
 
1586
        if( gRenderTextureInfos[idxToUse].pRenderTexture == NULL || matchidx < 0 )
 
1587
        {
 
1588
            int w = newRenderTextureInfo.bufferWidth;
 
1589
            if( newRenderTextureInfo.knownHeight == RDP_SETSCISSOR && newRenderTextureInfo.CI_Info.dwAddr == g_ZI.dwAddr )
 
1590
            {
 
1591
                w = gRDP.scissor.right;
 
1592
            }
 
1593
 
 
1594
            gRenderTextureInfos[idxToUse].pRenderTexture = 
 
1595
                new COGLRenderTexture(w, newRenderTextureInfo.bufferHeight, &gRenderTextureInfos[idxToUse], AS_RENDER_TARGET);
 
1596
        }
 
1597
 
 
1598
        // Need to set all variables for gRenderTextureInfos[idxToUse]
 
1599
        CRenderTexture *pRenderTexture = gRenderTextureInfos[idxToUse].pRenderTexture;
 
1600
        memcpy(&gRenderTextureInfos[idxToUse], &newRenderTextureInfo, sizeof(RenderTextureInfo) );
 
1601
        gRenderTextureInfos[idxToUse].pRenderTexture = pRenderTexture;
 
1602
        gRenderTextureInfos[idxToUse].isUsed = true;
 
1603
        gRenderTextureInfos[idxToUse].txtEntry.pTexture = pRenderTexture->m_pTexture;
 
1604
        gRenderTextureInfos[idxToUse].txtEntry.txtrBufIdx = idxToUse+1;
 
1605
 
 
1606
        g_pRenderTextureInfo = &gRenderTextureInfos[idxToUse];
 
1607
 
 
1608
        // Active the render_texture
 
1609
        if( m_curRenderTextureIndex >= 0 && gRenderTextureInfos[m_curRenderTextureIndex].isUsed && gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture )
 
1610
        {
 
1611
            gRenderTextureInfos[m_curRenderTextureIndex].pRenderTexture->SetAsRenderTarget(false);
 
1612
            m_isRenderingToTexture = false;
 
1613
        }
 
1614
 
 
1615
        if( gRenderTextureInfos[idxToUse].pRenderTexture->SetAsRenderTarget(true) )
 
1616
        {
 
1617
            m_isRenderingToTexture = true;
 
1618
 
 
1619
            //Clear(CLEAR_COLOR_AND_DEPTH_BUFFER,0x80808080,1.0f);
 
1620
            if( frameBufferOptions.bFillRectNextTextureBuffer )
 
1621
                CGraphicsContext::g_pGraphicsContext->Clear(CLEAR_COLOR_BUFFER,gRDP.fillColor,1.0f);
 
1622
            else if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS && g_pRenderTextureInfo->N64Width > 64 && g_pRenderTextureInfo->N64Width < 300 )
 
1623
            {
 
1624
                CGraphicsContext::g_pGraphicsContext->Clear(CLEAR_COLOR_BUFFER,0,1.0f);
 
1625
            }
 
1626
            else if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS && g_pRenderTextureInfo->N64Width < 64 && g_pRenderTextureInfo->N64Width > 32 )
 
1627
            {
 
1628
                CGraphicsContext::g_pGraphicsContext->Clear(CLEAR_COLOR_BUFFER,0,1.0f);
 
1629
            }
 
1630
 
 
1631
            m_curRenderTextureIndex = idxToUse;
 
1632
 
 
1633
            status.bDirectWriteIntoRDRAM = false;
 
1634
 
 
1635
            //SetScreenMult(1, 1);
 
1636
            SetScreenMult(gRenderTextureInfos[m_curRenderTextureIndex].scaleX, gRenderTextureInfos[m_curRenderTextureIndex].scaleY);
 
1637
            CRender::g_pRender->UpdateClipRectangle();
 
1638
 
 
1639
            // If needed, draw RDRAM into the render_texture
 
1640
            //if( frameBufferOptions.bLoadRDRAMIntoRenderTexture )
 
1641
            //{
 
1642
            //  CRender::GetRender()->LoadTxtrBufFromRDRAM();
 
1643
            //}
 
1644
        }
 
1645
        else
 
1646
        {
 
1647
            if( CDeviceBuilder::m_deviceGeneralType == DIRECTX_DEVICE )
 
1648
            {
 
1649
                TRACE1("Error to set Render Target: %d", idxToUse);
 
1650
                TRACE1("Addr = %08X", gRenderTextureInfos[idxToUse].CI_Info.dwAddr);
 
1651
                TRACE2("Width = %d, Height=%d", gRenderTextureInfos[idxToUse].N64Width, gRenderTextureInfos[idxToUse].N64Height);
 
1652
            }
 
1653
        }   
 
1654
 
 
1655
 
 
1656
        TXTRBUF_DUMP(TRACE2("Rendering to render_texture %d, addr=%08X", idxToUse, g_CI.dwAddr));
 
1657
        DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_RENDER_TEXTURE, 
 
1658
        {DebuggerAppendMsg("Paused after activating render_texture:\nAddr: 0x%08x, Fmt: %s Size: %s Width: %d, Height:%d",
 
1659
        g_CI.dwAddr, pszImgFormat[g_CI.dwFormat], pszImgSize[g_CI.dwSize], g_CI.dwWidth, g_pRenderTextureInfo->N64Height);});
 
1660
    }
 
1661
    else
 
1662
    {
 
1663
        UpdateRecentCIAddr(g_CI);
 
1664
        CheckRenderTexturesWithNewCI(g_CI,gRDP.scissor.bottom,false);
 
1665
    }
 
1666
}
 
1667
 
 
1668
#define SAVE_CI {g_CI.dwAddr = newCI.dwAddr;g_CI.dwFormat = newCI.dwFormat;g_CI.dwSize = newCI.dwSize;g_CI.dwWidth = newCI.dwWidth;g_CI.bpl=newCI.bpl;}
 
1669
 
 
1670
//sets CI address for framebuffer copies
 
1671
void FrameBufferManager::Set_CI_addr(SetImgInfo &newCI)
 
1672
{
 
1673
    bool wasDrawingTextureBuffer = status.bN64IsDrawingTextureBuffer;
 
1674
    status.bN64IsDrawingTextureBuffer = ( newCI.dwSize != TXT_SIZE_16b || newCI.dwFormat != TXT_FMT_RGBA || newCI.dwWidth < 200 || ( newCI.dwAddr != g_ZI.dwAddr && newCI.dwWidth != 512 && !g_pFrameBufferManager->HasAddrBeenDisplayed(newCI.dwAddr, newCI.dwWidth)) );
 
1675
    status.bN64FrameBufferIsUsed = status.bN64IsDrawingTextureBuffer;
 
1676
 
 
1677
    if( !wasDrawingTextureBuffer && g_CI.dwAddr == g_ZI.dwAddr && status.bCIBufferIsRendered )
 
1678
    {
 
1679
        TXTRBUF_DUMP(TRACE0("ZI is rendered"));
 
1680
 
 
1681
        if( options.enableHackForGames != HACK_FOR_CONKER && g_uRecentCIInfoPtrs[0]->bCopied == false )
 
1682
        {
 
1683
            // Conker is not actually using a backbuffer
 
1684
            g_pFrameBufferManager->UpdateRecentCIAddr(g_CI);
 
1685
            if( status.leftRendered != -1 && status.topRendered != -1 && status.rightRendered != -1 && status.bottomRendered != -1 )
 
1686
            {
 
1687
                RECT rect={status.leftRendered,status.topRendered,status.rightRendered,status.bottomRendered};
 
1688
                g_pFrameBufferManager->SaveBackBuffer(0,&rect);
 
1689
            }
 
1690
            else
 
1691
            {
 
1692
                g_pFrameBufferManager->SaveBackBuffer(0,NULL);
 
1693
            }
 
1694
        }
 
1695
    }
 
1696
 
 
1697
    frameBufferOptions.bFillRectNextTextureBuffer = false;
 
1698
    if( g_CI.dwAddr == newCI.dwAddr && status.bHandleN64RenderTexture && (g_CI.dwFormat != newCI.dwFormat || g_CI.dwSize != newCI.dwSize || g_CI.dwWidth != newCI.dwWidth ) )
 
1699
    {
 
1700
        // Mario Tennis player shadow
 
1701
        g_pFrameBufferManager->CloseRenderTexture(true);
 
1702
        if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS )
 
1703
            frameBufferOptions.bFillRectNextTextureBuffer = true;   // Hack for Mario Tennis
 
1704
    }
 
1705
 
 
1706
    SAVE_CI;
 
1707
 
 
1708
    if( g_CI.dwAddr == g_ZI.dwAddr && !status.bN64IsDrawingTextureBuffer )
 
1709
    {
 
1710
        if( g_pFrameBufferManager->IsDIaRenderTexture() )
 
1711
        {
 
1712
            status.bN64IsDrawingTextureBuffer = true;
 
1713
            status.bN64FrameBufferIsUsed = status.bN64IsDrawingTextureBuffer;
 
1714
        }
 
1715
    }
 
1716
 
 
1717
    status.bCIBufferIsRendered = false;
 
1718
    status.leftRendered = status.topRendered = status.rightRendered = status.bottomRendered = -1;
 
1719
 
 
1720
    if( currentRomOptions.screenUpdateSetting==SCREEN_UPDATE_AT_CI_CHANGE && !status.bN64IsDrawingTextureBuffer )
 
1721
    {
 
1722
        if( status.curRenderBuffer == 0 )
 
1723
        {
 
1724
            status.curRenderBuffer = g_CI.dwAddr;
 
1725
        }
 
1726
        else if( status.curRenderBuffer != g_CI.dwAddr )
 
1727
        {
 
1728
            status.curDisplayBuffer = status.curRenderBuffer;
 
1729
            CGraphicsContext::Get()->UpdateFrame();
 
1730
            status.curRenderBuffer = g_CI.dwAddr;
 
1731
            DEBUGGER_IF_DUMP(pauseAtNext,{DebuggerAppendMsg("Screen Update because CI change to %08X, Display Buf=%08X", status.curRenderBuffer, status.curDisplayBuffer);});
 
1732
        }
 
1733
    }
 
1734
 
 
1735
    if( frameBufferOptions.bAtEachFrameUpdate && !status.bHandleN64RenderTexture )
 
1736
    {
 
1737
        if( status.curRenderBuffer != g_CI.dwAddr )
 
1738
        {
 
1739
            if( status.gDlistCount%(currentRomOptions.N64FrameBufferWriteBackControl+1) == 0 )
 
1740
            {
 
1741
                g_pFrameBufferManager->StoreBackBufferToRDRAM(status.curRenderBuffer, 
 
1742
                    newCI.dwFormat, newCI.dwSize, windowSetting.uViWidth, windowSetting.uViHeight,
 
1743
                    windowSetting.uDisplayWidth, windowSetting.uDisplayHeight);
 
1744
            }
 
1745
        }
 
1746
 
 
1747
        //status.curDisplayBuffer = status.curRenderBuffer;
 
1748
        status.curRenderBuffer = g_CI.dwAddr;
 
1749
    }
 
1750
 
 
1751
 
 
1752
    switch( currentRomOptions.N64RenderToTextureEmuType )
 
1753
    {
 
1754
    case TXT_BUF_NONE:
 
1755
        if( status.bHandleN64RenderTexture )
 
1756
            g_pFrameBufferManager->CloseRenderTexture(false);
 
1757
        status.bHandleN64RenderTexture = false; // Don't handle N64 render_texture stuffs
 
1758
        if( !status.bN64IsDrawingTextureBuffer )
 
1759
            g_pFrameBufferManager->UpdateRecentCIAddr(g_CI);
 
1760
        break;
 
1761
    default:
 
1762
        if( status.bHandleN64RenderTexture )
 
1763
        {
 
1764
#ifdef DEBUGGER
 
1765
            if( pauseAtNext && eventToPause == NEXT_RENDER_TEXTURE )
 
1766
            {
 
1767
                pauseAtNext = TRUE;
 
1768
                eventToPause = NEXT_RENDER_TEXTURE;
 
1769
            }
 
1770
#endif
 
1771
            g_pFrameBufferManager->CloseRenderTexture(true);
 
1772
        }
 
1773
 
 
1774
        status.bHandleN64RenderTexture = status.bN64IsDrawingTextureBuffer;
 
1775
        if( status.bHandleN64RenderTexture )
 
1776
        {
 
1777
            if( options.enableHackForGames != HACK_FOR_BANJO_TOOIE )
 
1778
            {
 
1779
                g_pFrameBufferManager->SetRenderTexture();
 
1780
            }
 
1781
        }
 
1782
        else
 
1783
        {
 
1784
#ifdef DEBUGGER
 
1785
            if( g_CI.dwWidth == 512 && pauseAtNext && (eventToPause==NEXT_OBJ_BG || eventToPause==NEXT_SET_CIMG) )
 
1786
            {
 
1787
                DebuggerAppendMsg("Warning SetCImg: new Addr=0x%08X, fmt:%s size=%sb, Width=%d\n", 
 
1788
                    g_CI.dwAddr, pszImgFormat[newCI.dwFormat], pszImgSize[newCI.dwSize], newCI.dwWidth);
 
1789
            }
 
1790
#endif
 
1791
            //g_pFrameBufferManager->UpdateRecentCIAddr(g_CI);      // Delay this until the CI buffer is actally drawn
 
1792
        }
 
1793
        break;
 
1794
    }
 
1795
 
 
1796
    TXTRBUF_DUMP(TRACE4("SetCImg : Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", 
 
1797
        g_CI.dwAddr, pszImgFormat[newCI.dwFormat], pszImgSize[newCI.dwSize], newCI.dwWidth));
 
1798
 
 
1799
    DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_SET_CIMG, 
 
1800
    {
 
1801
        DebuggerAppendMsg("Pause after SetCImg: Addr=0x%08X, Fmt:%s-%sb, Width=%d\n", 
 
1802
            g_CI.dwAddr, pszImgFormat[newCI.dwFormat], pszImgSize[newCI.dwSize], newCI.dwWidth);
 
1803
    }
 
1804
    );
 
1805
}
 
1806
 
 
1807
 
 
1808
void FrameBufferManager::StoreRenderTextureToRDRAM(int infoIdx)
 
1809
{
 
1810
    if( !frameBufferOptions.bRenderTextureWriteBack )   return;
 
1811
 
 
1812
    if( infoIdx < 0 )
 
1813
        infoIdx = m_lastTextureBufferIndex;
 
1814
 
 
1815
    if( !gRenderTextureInfos[infoIdx].pRenderTexture )
 
1816
        return;
 
1817
 
 
1818
    if( gRenderTextureInfos[infoIdx].pRenderTexture->IsBeingRendered() )
 
1819
    {
 
1820
        TXTRBUF_DUMP(TRACE1("Cannot SaveTextureBuffer %d, it is being rendered", infoIdx));
 
1821
        return;
 
1822
    }
 
1823
 
 
1824
    gRenderTextureInfos[infoIdx].pRenderTexture->StoreToRDRAM(infoIdx);
 
1825
}
 
1826
 
 
1827
 
 
1828
//does FB copy to N64 RDAM structure
 
1829
void FrameBufferManager::CopyBufferToRDRAM(uint32 addr, uint32 fmt, uint32 siz, uint32 width, uint32 height, uint32 bufWidth, uint32 bufHeight, uint32 startaddr, uint32 memsize, uint32 pitch, TextureFmt bufFmt, void *buffer, uint32 bufPitch)
 
1830
{
 
1831
    uint32 startline=0;
 
1832
    if( startaddr == 0xFFFFFFFF )   startaddr = addr;
 
1833
 
 
1834
    startline = (startaddr-addr)/siz/pitch;
 
1835
    if( startline >= height )
 
1836
    {
 
1837
        //TRACE0("Warning: check me");
 
1838
        startline = height;
 
1839
    }
 
1840
 
 
1841
    uint32 endline = height;
 
1842
    if( memsize != 0xFFFFFFFF )
 
1843
    {
 
1844
        endline = (startaddr+memsize-addr)/siz;
 
1845
        if( endline % pitch == 0 )
 
1846
            endline /= pitch;
 
1847
        else
 
1848
            endline = endline/pitch+1;
 
1849
    }
 
1850
    if( endline > height )
 
1851
    {
 
1852
        endline = height;
 
1853
    }
 
1854
 
 
1855
    if( memsize != 0xFFFFFFFF )
 
1856
    {
 
1857
        TXTRBUF_DUMP(DebuggerAppendMsg("Start at: 0x%X, from line %d to %d", startaddr-addr, startline, endline););
 
1858
    }
 
1859
 
 
1860
    int indexes[600];
 
1861
    {
 
1862
        float sx;
 
1863
        int sx0;
 
1864
        float ratio = bufWidth/(float)width;
 
1865
        for( uint32 j=0; j<width; j++ )
 
1866
        {
 
1867
            sx = j*ratio;
 
1868
            sx0 = int(sx+0.5);
 
1869
            indexes[j] = 4*sx0;
 
1870
        }
 
1871
    }
 
1872
 
 
1873
    if( siz == TXT_SIZE_16b )
 
1874
    {
 
1875
        uint16 *frameBufferBase = (uint16*)(g_pRDRAMu8+addr);
 
1876
 
 
1877
        if( bufFmt==TEXTURE_FMT_A8R8G8B8 )
 
1878
        {
 
1879
            int  sy0;
 
1880
            float ratio = bufHeight/(float)height;
 
1881
 
 
1882
            for( uint32 i=startline; i<endline; i++ )
 
1883
            {
 
1884
                sy0 = int(i*ratio+0.5);
 
1885
 
 
1886
                uint16 *pD = frameBufferBase + i * pitch;
 
1887
                uint8 *pS0 = (uint8 *)buffer + sy0 * bufPitch;
 
1888
 
 
1889
                for( uint32 j=0; j<width; j++ )
 
1890
                {
 
1891
                    // Point
 
1892
                    uint8 r = pS0[indexes[j]+2];
 
1893
                    uint8 g = pS0[indexes[j]+1];
 
1894
                    uint8 b = pS0[indexes[j]+0];
 
1895
                    uint8 a = pS0[indexes[j]+3];
 
1896
 
 
1897
                    // Liner
 
1898
                    *(pD+(j^1)) = ConvertRGBATo555( r, g, b, a);
 
1899
 
 
1900
                }
 
1901
            }
 
1902
        }
 
1903
        else
 
1904
        {
 
1905
            TRACE1("Copy %sb FrameBuffer to Rdram, not implemented", pszImgSize[siz]);
 
1906
        }
 
1907
    }
 
1908
    else if( siz == TXT_SIZE_8b && fmt == TXT_FMT_CI )
 
1909
    {
 
1910
        uint8 *frameBufferBase = (uint8*)(g_pRDRAMu8+addr);
 
1911
 
 
1912
        if( bufFmt==TEXTURE_FMT_A8R8G8B8 )
 
1913
        {
 
1914
            uint16 tempword;
 
1915
            InitTlutReverseLookup();
 
1916
 
 
1917
            for( uint32 i=startline; i<endline; i++ )
 
1918
            {
 
1919
                uint8 *pD = frameBufferBase + i * width;
 
1920
                uint8 *pS = (uint8 *)buffer + i*bufHeight/height * bufPitch;
 
1921
                for( uint32 j=0; j<width; j++ )
 
1922
                {
 
1923
                    int pos = 4*(j*bufWidth/width);
 
1924
                    tempword = ConvertRGBATo555((pS[pos+2]),        // Red
 
1925
                        (pS[pos+1]),        // G
 
1926
                        (pS[pos+0]),        // B
 
1927
                        (pS[pos+3]));       // Alpha
 
1928
                    //*pD = CIFindIndex(tempword);
 
1929
                    *(pD+(j^3)) = RevTlutTable[tempword];
 
1930
                }
 
1931
            }
 
1932
        }
 
1933
        else
 
1934
        {
 
1935
            TRACE1("Copy %sb FrameBuffer to Rdram, not implemented", pszImgSize[siz]);
 
1936
        }
 
1937
        DEBUGGER_IF_DUMP(pauseAtNext,{DebuggerAppendMsg("Copy %sb FrameBuffer to Rdram", pszImgSize[siz]);});
 
1938
    }
 
1939
    else if( siz == TXT_SIZE_8b && fmt == TXT_FMT_I )
 
1940
    {
 
1941
        uint8 *frameBufferBase = (uint8*)(g_pRDRAMu8+addr);
 
1942
 
 
1943
        if( bufFmt==TEXTURE_FMT_A8R8G8B8 )
 
1944
        {
 
1945
            int sy0;
 
1946
            float ratio = bufHeight/(float)height;
 
1947
 
 
1948
            for( uint32 i=startline; i<endline; i++ )
 
1949
            {
 
1950
                sy0 = int(i*ratio+0.5);
 
1951
 
 
1952
                uint8 *pD = frameBufferBase + i * width;
 
1953
                uint8 *pS0 = (uint8 *)buffer + sy0 * bufPitch;
 
1954
 
 
1955
                for( uint32 j=0; j<width; j++ )
 
1956
                {
 
1957
                    // Point
 
1958
                    uint32 r = pS0[indexes[j]+2];
 
1959
                    uint32 g = pS0[indexes[j]+1];
 
1960
                    uint32 b = pS0[indexes[j]+0];
 
1961
 
 
1962
                    // Liner
 
1963
                    *(pD+(j^3)) = (uint8)((r+b+g)/3);
 
1964
 
 
1965
                }
 
1966
            }
 
1967
        }
 
1968
        else
 
1969
        {
 
1970
            //DebuggerAppendMsg("Copy %sb FrameBuffer to Rdram, not implemented", pszImgSize[siz]);
 
1971
        }
 
1972
        DEBUGGER_IF_DUMP(pauseAtNext,{DebuggerAppendMsg("Copy %sb FrameBuffer to Rdram", pszImgSize[siz]);});
 
1973
    }
 
1974
}
 
1975
 
 
1976
 
 
1977
#ifdef DEBUGGER
 
1978
void FrameBufferManager::DisplayRenderTexture(int infoIdx)
 
1979
{
 
1980
    if( infoIdx < 0 )
 
1981
        infoIdx = m_lastTextureBufferIndex;
 
1982
 
 
1983
    if( gRenderTextureInfos[infoIdx].pRenderTexture )
 
1984
    {
 
1985
        if( gRenderTextureInfos[infoIdx].pRenderTexture->IsBeingRendered() )
 
1986
        {
 
1987
            TRACE1("Render texture %d is being rendered, cannot display", infoIdx);
 
1988
        }
 
1989
        else
 
1990
        {
 
1991
            TRACE1("Texture buffer %d:", infoIdx);
 
1992
            TRACE1("Addr=%08X", gRenderTextureInfos[infoIdx].CI_Info.dwAddr);
 
1993
            TRACE2("Width=%d, Created Height=%d", gRenderTextureInfos[infoIdx].N64Width,gRenderTextureInfos[infoIdx].N64Height);
 
1994
            TRACE2("Fmt=%d, Size=%d", gRenderTextureInfos[infoIdx].CI_Info.dwFormat,gRenderTextureInfos[infoIdx].CI_Info.dwSize);
 
1995
        }
 
1996
    }
 
1997
    else
 
1998
    {
 
1999
        TRACE1("Texture buffer %d is not used", infoIdx);
 
2000
    }
 
2001
}
 
2002
#endif
 
2003
 
 
2004
 
 
2005
 
 
2006
//Saves backbuffer
 
2007
//this is the core to the current framebuffer code
 
2008
//We need to save backbuffer when changed by framebuffer
 
2009
//so that we can use it for framebuffer effects
 
2010
void FrameBufferManager::SaveBackBuffer(int ciInfoIdx, RECT* pSrcRect, bool forceToSaveToRDRAM)
 
2011
{
 
2012
    RecentCIInfo &ciInfo = *g_uRecentCIInfoPtrs[ciInfoIdx];
 
2013
 
 
2014
    if( ciInfoIdx == 1 )    // to save the current front buffer
 
2015
    {
 
2016
        CGraphicsContext::g_pGraphicsContext->UpdateFrame(true);
 
2017
    }
 
2018
 
 
2019
    if( frameBufferOptions.bWriteBackBufToRDRAM || forceToSaveToRDRAM )
 
2020
    {
 
2021
        uint32 width = ciInfo.dwWidth;
 
2022
        uint32 height = ciInfo.dwHeight;
 
2023
 
 
2024
        if( ciInfo.dwWidth == *g_GraphicsInfo.VI_WIDTH_REG && ciInfo.dwWidth != windowSetting.uViWidth )
 
2025
        {
 
2026
            width = windowSetting.uViWidth;
 
2027
            height = windowSetting.uViHeight;
 
2028
        }
 
2029
 
 
2030
        StoreBackBufferToRDRAM( ciInfo.dwAddr, ciInfo.dwFormat, ciInfo.dwSize, width, height, 
 
2031
            windowSetting.uDisplayWidth, windowSetting.uDisplayHeight);
 
2032
 
 
2033
        g_uRecentCIInfoPtrs[ciInfoIdx]->bCopied = true;
 
2034
        if( ciInfoIdx == 1 )    // to save the current front buffer
 
2035
        {
 
2036
            CGraphicsContext::g_pGraphicsContext->UpdateFrame(true);
 
2037
        }
 
2038
        return;
 
2039
    }
 
2040
 
 
2041
 
 
2042
    SetImgInfo tempinfo;
 
2043
    tempinfo.dwAddr = ciInfo.dwAddr;
 
2044
    tempinfo.dwFormat = ciInfo.dwFormat;
 
2045
    tempinfo.dwSize = ciInfo.dwSize;
 
2046
    tempinfo.dwWidth = ciInfo.dwWidth;
 
2047
 
 
2048
    int idx = SetBackBufferAsRenderTexture(tempinfo, ciInfoIdx);
 
2049
 
 
2050
    CopyBackBufferToRenderTexture(idx, ciInfo, pSrcRect);
 
2051
 
 
2052
    gRenderTextureInfos[idx].crcCheckedAtFrame = status.gDlistCount;
 
2053
    gRenderTextureInfos[idx].crcInRDRAM = ComputeRenderTextureCRCInRDRAM(idx);
 
2054
 
 
2055
    DEBUGGER_IF_DUMP((logTextureBuffer&&pSrcRect==NULL),TRACE1("SaveBackBuffer at 0x%08X", ciInfo.dwAddr));
 
2056
    DEBUGGER_IF_DUMP((logTextureBuffer&&pSrcRect),TRACE5("SaveBackBuffer at 0x%08X, {%d,%d -%d,%d)", ciInfo.dwAddr,
 
2057
        pSrcRect->left,pSrcRect->top,pSrcRect->right,pSrcRect->bottom));
 
2058
    DEBUGGER_IF_DUMP(( pauseAtNext && eventToPause == NEXT_RENDER_TEXTURE),{g_pFrameBufferManager->DisplayRenderTexture(idx);});
 
2059
 
 
2060
    g_uRecentCIInfoPtrs[ciInfoIdx]->bCopied = true;
 
2061
}
 
2062