netplay code added from snes9x
[drnoksnes] / gfx_org.cpp
1 /*
2  * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3  *
4  * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
5  *                           Jerremy Koot (jkoot@snes9x.com)
6  *
7  * Super FX C emulator code 
8  * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
9  *                           Gary Henderson.
10  * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
11  *
12  * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
13  * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
14  * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
15  *
16  * DOS port code contains the works of other authors. See headers in
17  * individual files.
18  *
19  * Snes9x homepage: http://www.snes9x.com
20  *
21  * Permission to use, copy, modify and distribute Snes9x in both binary and
22  * source form, for non-commercial purposes, is hereby granted without fee,
23  * providing that this license information and copyright notice appear with
24  * all copies and any derived work.
25  *
26  * This software is provided 'as-is', without any express or implied
27  * warranty. In no event shall the authors be held liable for any damages
28  * arising from the use of this software.
29  *
30  * Snes9x is freeware for PERSONAL USE only. Commercial users should
31  * seek permission of the copyright holders first. Commercial use includes
32  * charging money for Snes9x or software derived from Snes9x.
33  *
34  * The copyright holders request that bug fixes and improvements to the code
35  * should be forwarded to them so everyone can benefit from the modifications
36  * in future versions.
37  *
38  * Super NES and Super Nintendo Entertainment System are trademarks of
39  * Nintendo Co., Limited and its subsidiary companies.
40  */
41 #include "snes9x.h"
42
43 #include "memmap.h"
44 #include "ppu.h"
45 #include "cpuexec.h"
46 #include "display.h"
47 #include "gfx.h"
48 #include "apu.h"
49 #include "cheats.h"
50
51 #define M7 19
52 #define M8 19
53
54 extern uint32 gp32_gammavalue;
55
56 void ComputeClipWindows ();
57
58 extern void S9xSetupOBJ(void);
59
60 extern uint8 BitShifts[8][4];
61 extern uint8 TileShifts[8][4];
62 extern uint8 PaletteShifts[8][4];
63 extern uint8 PaletteMasks[8][4];
64 extern uint8 Depths[8][4];
65 extern uint8 BGSizes [2];
66
67 extern NormalTileRenderer DrawTilePtr;
68 extern ClippedTileRenderer DrawClippedTilePtr;
69 extern NormalTileRenderer DrawHiResTilePtr;
70 extern ClippedTileRenderer DrawHiResClippedTilePtr;
71 extern LargePixelRenderer DrawLargePixelPtr;
72
73 extern struct SBG BG;
74
75 extern struct SLineData LineData[240];
76 extern struct SLineMatrixData LineMatrixData [240];
77
78 extern uint8  Mode7Depths [2];
79 extern unsigned char gammatab[10][32];
80 #define ON_MAIN(N) \
81 (GFX.r212c & (1 << (N)) && \
82  !(PPU.BG_Forced & (1 << (N))))
83
84 #define SUB_OR_ADD(N) \
85 (GFX.r2131 & (1 << (N)))
86
87 #define ON_SUB(N) \
88 ((GFX.r2130 & 0x30) != 0x30 && \
89  (GFX.r2130 & 2) && \
90  (GFX.r212d & (1 << N)) && \
91  !(PPU.BG_Forced & (1 << (N))))
92
93 #define ANYTHING_ON_SUB \
94 ((GFX.r2130 & 0x30) != 0x30 && \
95  (GFX.r2130 & 2) && \
96  (GFX.r212d & 0x1f))
97
98 #define ADD_OR_SUB_ON_ANYTHING \
99 (GFX.r2131 & 0x3f)
100
101 #define BLACK BUILD_PIXEL(0,0,0)
102
103 void orgDrawTileHi16 (uint32 Tile, uint32 Offset, uint32 StartLine,
104                  uint32 LineCount);
105 void orgDrawClippedTileHi16 (uint32 Tile, uint32 Offset,
106                         uint32 StartPixel, uint32 Width,
107                         uint32 StartLine, uint32 LineCount);
108
109 void orgDrawTile16 (uint32 Tile, uint32 Offset, uint32 StartLine,
110                  uint32 LineCount);
111 void orgDrawClippedTile16 (uint32 Tile, uint32 Offset,
112                         uint32 StartPixel, uint32 Width,
113                         uint32 StartLine, uint32 LineCount);
114 void orgDrawTile16x2 (uint32 Tile, uint32 Offset, uint32 StartLine,
115                    uint32 LineCount);
116 void orgDrawClippedTile16x2 (uint32 Tile, uint32 Offset,
117                           uint32 StartPixel, uint32 Width,
118                           uint32 StartLine, uint32 LineCount);
119 void orgDrawTile16x2x2 (uint32 Tile, uint32 Offset, uint32 StartLine,
120                      uint32 LineCount);
121 void orgDrawClippedTile16x2x2 (uint32 Tile, uint32 Offset,
122                             uint32 StartPixel, uint32 Width,
123                             uint32 StartLine, uint32 LineCount);
124 void orgDrawLargePixel16 (uint32 Tile, uint32 Offset,
125                        uint32 StartPixel, uint32 Pixels,
126                        uint32 StartLine, uint32 LineCount);
127
128 void orgDrawTile16Add (uint32 Tile, uint32 Offset, uint32 StartLine,
129                     uint32 LineCount);
130
131 void orgDrawClippedTile16Add (uint32 Tile, uint32 Offset,
132                            uint32 StartPixel, uint32 Width,
133                            uint32 StartLine, uint32 LineCount);
134
135 void orgDrawTile16Add1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
136                        uint32 LineCount);
137
138 void orgDrawClippedTile16Add1_2 (uint32 Tile, uint32 Offset,
139                               uint32 StartPixel, uint32 Width,
140                               uint32 StartLine, uint32 LineCount);
141
142 void orgDrawTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
143                             uint32 LineCount);
144
145 void orgDrawClippedTile16FixedAdd1_2 (uint32 Tile, uint32 Offset,
146                                    uint32 StartPixel, uint32 Width,
147                                    uint32 StartLine, uint32 LineCount);
148
149 void orgDrawTile16Sub (uint32 Tile, uint32 Offset, uint32 StartLine,
150                     uint32 LineCount);
151
152 void orgDrawClippedTile16Sub (uint32 Tile, uint32 Offset,
153                            uint32 StartPixel, uint32 Width,
154                            uint32 StartLine, uint32 LineCount);
155
156 void orgDrawTile16Sub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
157                        uint32 LineCount);
158
159 void orgDrawClippedTile16Sub1_2 (uint32 Tile, uint32 Offset,
160                               uint32 StartPixel, uint32 Width,
161                               uint32 StartLine, uint32 LineCount);
162
163 void orgDrawTile16FixedSub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
164                             uint32 LineCount);
165
166 void orgDrawClippedTile16FixedSub1_2 (uint32 Tile, uint32 Offset,
167                                    uint32 StartPixel, uint32 Width,
168                                    uint32 StartLine, uint32 LineCount);
169
170 void orgDrawLargePixel16Add (uint32 Tile, uint32 Offset,
171                           uint32 StartPixel, uint32 Pixels,
172                           uint32 StartLine, uint32 LineCount);
173
174 void orgDrawLargePixel16Add1_2 (uint32 Tile, uint32 Offset,
175                              uint32 StartPixel, uint32 Pixels,
176                              uint32 StartLine, uint32 LineCount);
177
178 void orgDrawLargePixel16Sub (uint32 Tile, uint32 Offset,
179                           uint32 StartPixel, uint32 Pixels,
180                           uint32 StartLine, uint32 LineCount);
181
182 void orgDrawLargePixel16Sub1_2 (uint32 Tile, uint32 Offset,
183                              uint32 StartPixel, uint32 Pixels,
184                              uint32 StartLine, uint32 LineCount);
185
186
187 bool8 S9xGraphicsInit ()
188 {
189     register uint32 PixelOdd = 1;
190     register uint32 PixelEven = 2;
191
192 #ifdef GFX_MULTI_FORMAT
193     if (GFX.BuildPixel == NULL)
194         S9xSetRenderPixelFormat (RGB565);
195 #endif
196
197     for (uint8 bitshift = 0; bitshift < 4; bitshift++)
198     {
199         for (register char i = 0; i < 16; i++)
200         {
201             register uint32 h = 0;
202             register uint32 l = 0;
203
204 #if defined(LSB_FIRST)
205             if (i & 8)
206                 h |= PixelOdd;
207             if (i & 4)
208                 h |= PixelOdd << 8;
209             if (i & 2)
210                 h |= PixelOdd << 16;
211             if (i & 1)
212                 h |= PixelOdd << 24;
213             if (i & 8)
214                 l |= PixelOdd;
215             if (i & 4)
216                 l |= PixelOdd << 8;
217             if (i & 2)
218                 l |= PixelOdd << 16;
219             if (i & 1)
220                 l |= PixelOdd << 24;
221 #else
222             if (i & 8)
223                 h |= (PixelOdd << 24);
224             if (i & 4)
225                 h |= (PixelOdd << 16);
226             if (i & 2)
227                 h |= (PixelOdd << 8);
228             if (i & 1)
229                 h |= PixelOdd;
230             if (i & 8)
231                 l |= (PixelOdd << 24);
232             if (i & 4)
233                 l |= (PixelOdd << 16);
234             if (i & 2)
235                 l |= (PixelOdd << 8);
236             if (i & 1)
237                 l |= PixelOdd;
238 #endif
239
240             odd_high[bitshift][i] = h;
241             odd_low[bitshift][i] = l;
242             h = l = 0;
243
244 #if defined(LSB_FIRST)
245             if (i & 8)
246                 h |= PixelEven;
247             if (i & 4)
248                 h |= PixelEven << 8;
249             if (i & 2)
250                 h |= PixelEven << 16;
251             if (i & 1)
252                 h |= PixelEven << 24;
253             if (i & 8)
254                 l |= PixelEven;
255             if (i & 4)
256                 l |= PixelEven << 8;
257             if (i & 2)
258                 l |= PixelEven << 16;
259             if (i & 1)
260                 l |= PixelEven << 24;
261 #else
262             if (i & 8)
263                 h |= (PixelEven << 24);
264             if (i & 4)
265                 h |= (PixelEven << 16);
266             if (i & 2)
267                 h |= (PixelEven << 8);
268             if (i & 1)
269                 h |= PixelEven;
270             if (i & 8)
271                 l |= (PixelEven << 24);
272             if (i & 4)
273                 l |= (PixelEven << 16);
274             if (i & 2)
275                 l |= (PixelEven << 8);
276             if (i & 1)
277                 l |= PixelEven;
278 #endif
279
280             even_high[bitshift][i] = h;
281             even_low[bitshift][i] = l;
282         }
283         PixelEven <<= 2;
284         PixelOdd <<= 2;
285     }
286
287     GFX.RealPitch = GFX.Pitch2 = GFX.Pitch;
288     GFX.ZPitch = GFX.Pitch;
289     if (Settings.SixteenBit)
290         GFX.ZPitch >>= 1;
291     GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1;
292     GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer;
293     //GFX.InfoStringTimeout = 0;
294     //GFX.InfoString = NULL;
295
296     PPU.BG_Forced = 0;
297     IPPU.OBJChanged = TRUE;
298     if (Settings.Transparency)
299         Settings.SixteenBit = TRUE;
300
301     IPPU.DirectColourMapsNeedRebuild = TRUE;
302     GFX.PixSize = 1;
303     if (Settings.SixteenBit)
304     {
305         GFX.PPL = GFX.Pitch >> 1;
306         GFX.PPLx2 = GFX.Pitch;
307     }
308     else
309     {
310         GFX.PPL = GFX.Pitch;
311         GFX.PPLx2 = GFX.Pitch * 2;
312     }
313     S9xFixColourBrightness ();
314
315 #ifdef _TRANSP_SUPPORT_ 
316         if (!(GFX.X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000)))
317             return (FALSE);
318
319         if ((!(GFX.ZERO_OR_X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000)))
320          ||!(GFX.ZERO = (uint16 *) malloc (sizeof (uint16) * 0x10000)))
321         {
322             if (GFX.ZERO_OR_X2)
323             {
324                 free ((char *) GFX.ZERO_OR_X2);
325                 GFX.ZERO_OR_X2 = NULL;
326             }
327             if (GFX.X2)
328             {
329                 free ((char *) GFX.X2);
330                 GFX.X2 = NULL;
331             }
332             return (FALSE);
333         }
334         uint32 r, g, b;
335
336         // Build a lookup table that multiplies a packed RGB value by 2 with
337         // saturation.
338         for (r = 0; r <= MAX_RED; r++)
339         {
340             uint32 r2 = r << 1;
341             if (r2 > MAX_RED)
342                 r2 = MAX_RED;
343             for (g = 0; g <= MAX_GREEN; g++)
344             {
345                 uint32 g2 = g << 1;
346                 if (g2 > MAX_GREEN)
347                     g2 = MAX_GREEN;
348                 for (b = 0; b <= MAX_BLUE; b++)
349                 {
350                     uint32 b2 = b << 1;
351                     if (b2 > MAX_BLUE)
352                         b2 = MAX_BLUE;
353                     GFX.X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2);
354                     GFX.X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2);
355                 }
356             }
357         }
358         ZeroMemory (GFX.ZERO, 0x10000 * sizeof (uint16));
359         ZeroMemory (GFX.ZERO_OR_X2, 0x10000 * sizeof (uint16));
360         // Build a lookup table that if the top bit of the color value is zero
361         // then the value is zero, otherwise multiply the value by 2. Used by
362         // the color subtraction code.
363
364 #if defined(OLD_COLOUR_BLENDING)
365         for (r = 0; r <= MAX_RED; r++)
366         {
367             uint32 r2 = r;
368             if ((r2 & 0x10) == 0)
369                 r2 = 0;
370             else
371                 r2 = (r2 << 1) & MAX_RED;
372
373             for (g = 0; g <= MAX_GREEN; g++)
374             {
375                 uint32 g2 = g;
376                 if ((g2 & GREEN_HI_BIT) == 0)
377                     g2 = 0;
378                 else
379                     g2 = (g2 << 1) & MAX_GREEN;
380
381                 for (b = 0; b <= MAX_BLUE; b++)
382                 {
383                     uint32 b2 = b;
384                     if ((b2 & 0x10) == 0)
385                         b2 = 0;
386                     else
387                         b2 = (b2 << 1) & MAX_BLUE;
388
389                     GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2);
390                     GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2);
391                 }
392             }
393         }
394 #else
395         for (r = 0; r <= MAX_RED; r++)
396         {
397             uint32 r2 = r;
398             if ((r2 & 0x10) == 0)
399                 r2 = 0;
400             else
401                 r2 = (r2 << 1) & MAX_RED;
402
403             if (r2 == 0)
404                 r2 = 1;
405             for (g = 0; g <= MAX_GREEN; g++)
406             {
407                 uint32 g2 = g;
408                 if ((g2 & GREEN_HI_BIT) == 0)
409                     g2 = 0;
410                 else
411                     g2 = (g2 << 1) & MAX_GREEN;
412
413                 if (g2 == 0)
414                     g2 = 1;
415                 for (b = 0; b <= MAX_BLUE; b++)
416                 {
417                     uint32 b2 = b;
418                     if ((b2 & 0x10) == 0)
419                         b2 = 0;
420                     else
421                         b2 = (b2 << 1) & MAX_BLUE;
422
423                     if (b2 == 0)
424                         b2 = 1;
425                     GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2);
426                     GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2);
427                 }
428             }
429         }
430 #endif
431
432         // Build a lookup table that if the top bit of the color value is zero
433         // then the value is zero, otherwise its just the value.
434         for (r = 0; r <= MAX_RED; r++)
435         {
436             uint32 r2 = r;
437             if ((r2 & 0x10) == 0)
438                 r2 = 0;
439             else
440                 r2 &= ~0x10;
441
442             for (g = 0; g <= MAX_GREEN; g++)
443             {
444                 uint32 g2 = g;
445                 if ((g2 & GREEN_HI_BIT) == 0)
446                     g2 = 0;
447                 else
448                     g2 &= ~GREEN_HI_BIT;
449                 for (b = 0; b <= MAX_BLUE; b++)
450                 {
451                     uint32 b2 = b;
452                     if ((b2 & 0x10) == 0)
453                         b2 = 0;
454                     else
455                         b2 &= ~0x10;
456
457                     GFX.ZERO [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2);
458                     GFX.ZERO [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2);
459                 }
460             }
461         }    
462 //      GFX.ZERO = NULL;
463 #else
464     {
465         GFX.X2 = NULL;
466         GFX.ZERO_OR_X2 = NULL;
467         GFX.ZERO = NULL;
468     }
469 #endif
470     return (TRUE);
471 }
472
473 void S9xGraphicsDeinit (void)
474 {
475     // Free any memory allocated in S9xGraphicsInit
476     if (GFX.X2)
477     {
478         free (GFX.X2);
479         GFX.X2 = NULL;
480     }
481     if (GFX.ZERO_OR_X2)
482     {
483         free (GFX.ZERO_OR_X2);
484         GFX.ZERO_OR_X2 = NULL;
485     }
486     if (GFX.ZERO)
487     {
488         free (GFX.ZERO);
489         GFX.ZERO = NULL;
490     }
491 }
492
493
494 void S9xBuildDirectColourMaps ()
495 {
496         uint8 *cgamma=(uint8*)gammatab[gp32_gammavalue];
497     for (uint32 p = 0; p < 8; p++)
498     {
499         for (uint32 c = 0; c < 256; c++)
500         {
501 // XXX: Brightness
502             DirectColourMaps [p][c] = BUILD_PIXEL (cgamma[((c & 7) << 2) | ((p & 1) << 1)],
503                                                    cgamma[((c & 0x38) >> 1) | (p & 2)],
504                                                    cgamma[((c & 0xc0) >> 3) | (p & 4)]);
505         }
506     }
507     IPPU.DirectColourMapsNeedRebuild = FALSE;
508 }
509
510 void S9xStartScreenRefresh ()
511 {
512     if (GFX.InfoStringTimeout > 0 && --GFX.InfoStringTimeout == 0)
513         GFX.InfoString = NULL;
514
515     if (IPPU.RenderThisFrame)
516     {
517         if (!S9xInitUpdate ())
518         {
519             IPPU.RenderThisFrame = FALSE;
520             return;
521         }
522         IPPU.RenderedFramesCount++;
523         IPPU.PreviousLine = IPPU.CurrentLine = 0;
524         IPPU.MaxBrightness = PPU.Brightness;
525         IPPU.LatchedBlanking = PPU.ForcedBlanking;
526         IPPU.LatchedInterlace = (Memory.FillRAM[0x2133] & 1);
527 //      IPPU.Interlace = (Memory.FillRAM[0x2133] & 1);
528         if (Settings.SupportHiRes && (PPU.BGMode == 5 || PPU.BGMode == 6 ||
529                                       IPPU.LatchedInterlace/*IPPU.Interlace*/))
530         {
531             if (PPU.BGMode == 5 || PPU.BGMode == 6)
532             {
533                 IPPU.RenderedScreenWidth = 512;
534                 IPPU.DoubleWidthPixels = TRUE;
535             }
536             if (/*IPPU.Interlace*/IPPU.LatchedInterlace)
537             {
538                 IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1;
539                 GFX.Pitch2 = GFX.RealPitch;
540                 GFX.Pitch = GFX.RealPitch * 2;
541                 if (Settings.SixteenBit)
542                     GFX.PPL = GFX.PPLx2 = GFX.RealPitch;
543                 else
544                     GFX.PPL = GFX.PPLx2 = GFX.RealPitch << 1;
545             }
546             else
547             {
548                 IPPU.RenderedScreenHeight = PPU.ScreenHeight;
549                 GFX.Pitch2 = GFX.Pitch = GFX.RealPitch;
550                 if (Settings.SixteenBit)
551                     GFX.PPL = GFX.Pitch >> 1;
552                 else
553                     GFX.PPL = GFX.Pitch;
554                 GFX.PPLx2 = GFX.PPL << 1;
555             }
556 #if defined(USE_GLIDE) || defined(USE_OPENGL)
557             GFX.ZPitch = GFX.RealPitch;
558             if (Settings.SixteenBit)
559                 GFX.ZPitch >>= 1;
560 #endif
561         }
562         else
563         {
564             IPPU.RenderedScreenWidth = 256;
565             IPPU.RenderedScreenHeight = PPU.ScreenHeight;
566             IPPU.DoubleWidthPixels = FALSE;
567             {
568                 GFX.Pitch2 = GFX.Pitch = GFX.RealPitch;
569                 GFX.PPL = GFX.PPLx2 >> 1;
570                 GFX.ZPitch = GFX.RealPitch;
571                 if (Settings.SixteenBit)
572                     GFX.ZPitch >>= 1;
573             }
574         }
575         PPU.RecomputeClipWindows = TRUE;
576         GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer;
577         GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1;
578     }
579     if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0)
580     {
581         IPPU.DisplayedRenderedFrameCount = IPPU.RenderedFramesCount;
582         IPPU.RenderedFramesCount = 0;
583         IPPU.FrameCount = 0;
584     }
585     
586 }
587
588 void RenderLine (uint8 C)
589 {
590     if (IPPU.RenderThisFrame)
591     {
592         LineData[C].BG[0].VOffset = PPU.BG[0].VOffset + 1;
593         LineData[C].BG[0].HOffset = PPU.BG[0].HOffset;
594         LineData[C].BG[1].VOffset = PPU.BG[1].VOffset + 1;
595         LineData[C].BG[1].HOffset = PPU.BG[1].HOffset;
596
597         if (PPU.BGMode == 7)
598         {
599             struct SLineMatrixData *p = &LineMatrixData [C];
600             p->MatrixA = PPU.MatrixA;
601             p->MatrixB = PPU.MatrixB;
602             p->MatrixC = PPU.MatrixC;
603             p->MatrixD = PPU.MatrixD;
604             p->CentreX = PPU.CentreX;
605             p->CentreY = PPU.CentreY;
606         }
607         else
608         {
609             if (Settings.StarfoxHack && PPU.BG[2].VOffset == 0 &&
610                 PPU.BG[2].HOffset == 0xe000)
611             {
612                 LineData[C].BG[2].VOffset = 0xe1;
613                 LineData[C].BG[2].HOffset = 0;
614             }
615             else
616             {
617                 LineData[C].BG[2].VOffset = PPU.BG[2].VOffset + 1;
618                 LineData[C].BG[2].HOffset = PPU.BG[2].HOffset;
619                 LineData[C].BG[3].VOffset = PPU.BG[3].VOffset + 1;
620                 LineData[C].BG[3].HOffset = PPU.BG[3].HOffset;
621             }
622         }
623         IPPU.CurrentLine = C + 1;
624     }
625 }
626
627 void S9xEndScreenRefresh ()
628 {
629     IPPU.HDMAStarted = FALSE;
630     if (IPPU.RenderThisFrame)
631     {
632         FLUSH_REDRAW ();
633         if (IPPU.ColorsChanged)
634         {
635             uint32 saved = PPU.CGDATA[0];
636             if (!Settings.SixteenBit)
637             {
638                 // Hack for Super Mario World - to get its sky blue
639                 // (It uses Fixed colour addition on the backdrop colour)
640                 if (!(Memory.FillRAM [0x2131] & 0x80) &&
641                     (Memory.FillRAM[0x2131] & 0x20) &&
642                     (PPU.FixedColourRed || PPU.FixedColourGreen ||
643                      PPU.FixedColourBlue))
644                 {
645                     PPU.CGDATA[0] = PPU.FixedColourRed |
646                                     (PPU.FixedColourGreen << 5) |
647                                     (PPU.FixedColourBlue << 10);
648                 }
649             }
650             IPPU.ColorsChanged = FALSE;
651             S9xSetPalette ();
652             PPU.CGDATA[0] = saved;
653         }
654             GFX.Pitch = GFX.Pitch2 = GFX.RealPitch;
655             GFX.PPL = GFX.PPLx2 >> 1;
656         
657
658 /*      if (Settings.DisplayFrameRate)
659             S9xDisplayFrameRate ();
660         if (GFX.InfoString)
661             S9xDisplayString (GFX.InfoString);*/
662
663         S9xDeinitUpdate (IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight,
664                          Settings.SixteenBit);
665     }
666 //    S9xApplyCheats ();
667 #ifdef DEBUGGER
668     if (CPU.Flags & FRAME_ADVANCE_FLAG)
669     {
670         if (ICPU.FrameAdvanceCount)
671         {
672             ICPU.FrameAdvanceCount--;
673             IPPU.RenderThisFrame = TRUE;
674             IPPU.FrameSkip = 0;
675         }
676         else
677         {
678             CPU.Flags &= ~FRAME_ADVANCE_FLAG;
679             CPU.Flags |= DEBUG_MODE_FLAG;
680         }
681     }
682 #endif
683     if (CPU.SRAMModified)
684     {
685         if (!CPU.AutoSaveTimer)
686         {
687             if (!(CPU.AutoSaveTimer = Settings.AutoSaveDelay * Memory.ROMFramesPerSecond))
688                 CPU.SRAMModified = FALSE;
689         }
690         else
691         {
692             if (!--CPU.AutoSaveTimer)
693             {
694                 S9xAutoSaveSRAM ();
695                 CPU.SRAMModified = FALSE;
696             }
697         }
698     }
699 }
700
701 void S9xSetInfoString (const char *string)
702 {
703     GFX.InfoString = string;
704     GFX.InfoStringTimeout = 120;
705 }
706
707
708
709
710 void S9xSetupOBJ ()
711 {
712     int SmallSize;
713     int LargeSize;
714
715     switch (PPU.OBJSizeSelect)
716     {
717     case 0:
718         SmallSize = 8;
719         LargeSize = 16;
720         break;
721     case 1:
722         SmallSize = 8;
723         LargeSize = 32;
724         break;
725     case 2:
726         SmallSize = 8;
727         LargeSize = 64;
728         break;
729     case 3:
730         SmallSize = 16;
731         LargeSize = 32;
732         break;
733     case 4:
734         SmallSize = 16;
735         LargeSize = 64;
736         break;
737     case 5:
738     default:
739         SmallSize = 32;
740         LargeSize = 64;
741         break;
742     }
743
744     int C = 0;
745     
746     int FirstSprite = PPU.FirstSprite & 0x7f;
747     int S = FirstSprite;
748     do
749     {
750         int Size;
751         if (PPU.OBJ [S].Size)
752             Size = LargeSize;
753         else
754             Size = SmallSize;
755
756         long VPos = PPU.OBJ [S].VPos;
757
758         if (VPos >= PPU.ScreenHeight)
759             VPos -= 256;
760         if (PPU.OBJ [S].HPos < 256 && PPU.OBJ [S].HPos > -Size &&
761             VPos < PPU.ScreenHeight && VPos > -Size)
762         {
763             GFX.OBJList [C++] = S;
764             GFX.Sizes[S] = Size;
765             GFX.VPositions[S] = VPos;
766         }
767         S = (S + 1) & 0x7f;
768     } while (S != FirstSprite);
769
770     // Terminate the list
771     GFX.OBJList [C] = -1;
772     IPPU.OBJChanged = FALSE;
773 }
774
775
776
777
778 inline void orgSelectTileRenderer (bool8 normal)
779 {
780         DrawHiResTilePtr= orgDrawTileHi16;
781         DrawHiResClippedTilePtr = orgDrawClippedTileHi16;
782
783
784     if (normal)
785     {
786         DrawTilePtr = orgDrawTile16;
787         DrawClippedTilePtr = orgDrawClippedTile16;
788         DrawLargePixelPtr = orgDrawLargePixel16;
789     }
790     else
791     {
792         if (GFX.r2131 & 0x80)
793         {
794             if (GFX.r2131 & 0x40)
795             {
796                 if (GFX.r2130 & 2)
797                 {
798                     DrawTilePtr = orgDrawTile16Sub1_2;
799                     DrawClippedTilePtr = orgDrawClippedTile16Sub1_2;
800                 }
801                 else
802                 {
803                     // Fixed colour substraction
804                     DrawTilePtr = orgDrawTile16FixedSub1_2;
805                     DrawClippedTilePtr = orgDrawClippedTile16FixedSub1_2;
806                 }
807                 DrawLargePixelPtr = orgDrawLargePixel16Sub1_2;
808             }
809             else
810             {
811                 DrawTilePtr = orgDrawTile16Sub;
812                 DrawClippedTilePtr = orgDrawClippedTile16Sub;
813                 DrawLargePixelPtr = orgDrawLargePixel16Sub;
814             }
815         }
816         else
817         {
818             if (GFX.r2131 & 0x40)
819             {
820                 if (GFX.r2130 & 2)
821                 {
822                     DrawTilePtr = orgDrawTile16Add1_2;
823                     DrawClippedTilePtr = orgDrawClippedTile16Add1_2;
824                 }
825                 else
826                 {
827                     // Fixed colour addition
828                     DrawTilePtr = orgDrawTile16FixedAdd1_2;
829                     DrawClippedTilePtr = orgDrawClippedTile16FixedAdd1_2;
830                 }
831                 DrawLargePixelPtr = orgDrawLargePixel16Add1_2;
832             }
833             else
834             {
835                 DrawTilePtr = orgDrawTile16Add;
836                 DrawClippedTilePtr = orgDrawClippedTile16Add;
837                 DrawLargePixelPtr = orgDrawLargePixel16Add;
838             }
839         }
840     }
841 }
842
843 void orgDrawOBJS (bool8 OnMain = FALSE, uint8 D = 0)
844 {
845     uint32 O;
846     uint32 BaseTile, Tile;
847
848     CHECK_SOUND();
849
850     BG.BitShift = 4;
851     BG.TileShift = 5;
852     BG.TileAddress = PPU.OBJNameBase;
853     BG.StartPalette = 128;
854     BG.PaletteShift = 4;
855     BG.PaletteMask = 7;
856     BG.Buffer = IPPU.TileCache [TILE_4BIT];
857     BG.Buffered = IPPU.TileCached [TILE_4BIT];
858     BG.NameSelect = PPU.OBJNameSelect;
859     BG.DirectColourMode = FALSE;
860
861     GFX.PixSize = 1;
862
863         
864         
865         DrawTilePtr = orgDrawTile16;
866         DrawClippedTilePtr = orgDrawClippedTile16;
867         
868     GFX.Z1 = D + 2;
869
870     int I = 0;
871     for (int S = GFX.OBJList [I++]; S >= 0; S = GFX.OBJList [I++])
872     {
873         int VPos = GFX.VPositions [S];
874         int Size = GFX.Sizes[S];
875         int TileInc = 1;
876         int Offset;
877
878         if (VPos + Size <= (int) GFX.StartY || VPos > (int) GFX.EndY)
879             continue;
880
881         if (OnMain && SUB_OR_ADD(4))
882         {
883             orgSelectTileRenderer (!GFX.Pseudo && PPU.OBJ [S].Palette < 4);
884         }
885
886         BaseTile = PPU.OBJ[S].Name | (PPU.OBJ[S].Palette << 10);
887
888         if (PPU.OBJ[S].HFlip)
889         {
890             BaseTile += ((Size >> 3) - 1) | H_FLIP;
891             TileInc = -1;
892         }
893         if (PPU.OBJ[S].VFlip)
894             BaseTile |= V_FLIP;
895
896         int clipcount = GFX.pCurrentClip->Count [4];
897         if (!clipcount)
898             clipcount = 1;
899         
900         GFX.Z2 = (PPU.OBJ[S].Priority + 1) * 4 + D;
901
902         for (int clip = 0; clip < clipcount; clip++)
903         {
904             int Left; 
905             int Right;
906             if (!GFX.pCurrentClip->Count [4])
907             {
908                 Left = 0;
909                 Right = 256;
910             }
911             else
912             {
913                 Left = GFX.pCurrentClip->Left [clip][4];
914                 Right = GFX.pCurrentClip->Right [clip][4];
915             }
916
917             if (Right <= Left || PPU.OBJ[S].HPos + Size <= Left ||
918                 PPU.OBJ[S].HPos >= Right)
919                 continue;
920
921             for (int Y = 0; Y < Size; Y += 8)
922             {
923                 if (VPos + Y + 7 >= (int) GFX.StartY && VPos + Y <= (int) GFX.EndY)
924                 {
925                     int StartLine;
926                     int TileLine;
927                     int LineCount;
928                     int Last;
929                     
930                     if ((StartLine = VPos + Y) < (int) GFX.StartY)
931                     {
932                         StartLine = GFX.StartY - StartLine;
933                         LineCount = 8 - StartLine;
934                     }
935                     else
936                     {
937                         StartLine = 0;
938                         LineCount = 8;
939                     }
940                     if ((Last = VPos + Y + 7 - GFX.EndY) > 0)
941                         if ((LineCount -= Last) <= 0)
942                             break;
943
944                     TileLine = StartLine << 3;
945                     O = (VPos + Y + StartLine) * GFX.PPL;
946                     if (!PPU.OBJ[S].VFlip)
947                         Tile = BaseTile + (Y << 1);
948                     else
949                         Tile = BaseTile + ((Size - Y - 8) << 1);
950
951                     int Middle = Size >> 3;
952                     if (PPU.OBJ[S].HPos < Left)
953                     {
954                         Tile += ((Left - PPU.OBJ[S].HPos) >> 3) * TileInc;
955                         Middle -= (Left - PPU.OBJ[S].HPos) >> 3;
956                         O += Left * GFX.PixSize;
957                         if ((Offset = (Left - PPU.OBJ[S].HPos) & 7))
958                         {
959                             O -= Offset * GFX.PixSize;
960                             int W = 8 - Offset;
961                             int Width = Right - Left;
962                             if (W > Width)
963                                 W = Width;
964                             (*DrawClippedTilePtr) (Tile, O, Offset, W,
965                                                    TileLine, LineCount);
966                             
967                             if (W >= Width)
968                                 continue;
969                             Tile += TileInc;
970                             Middle--;
971                             O += 8 * GFX.PixSize;
972                         }
973                     }
974                     else
975                         O += PPU.OBJ[S].HPos * GFX.PixSize;
976
977                     if (PPU.OBJ[S].HPos + Size >= Right)
978                     {
979                         Middle -= ((PPU.OBJ[S].HPos + Size + 7) -
980                                    Right) >> 3;
981                         Offset = (Right - (PPU.OBJ[S].HPos + Size)) & 7;
982                     }
983                     else
984                         Offset = 0;
985
986                     for (int X = 0; X < Middle; X++, O += 8 * GFX.PixSize,
987                          Tile += TileInc)
988                     {
989                         (*DrawTilePtr) (Tile, O, TileLine, LineCount);
990                     }
991                     if (Offset)
992                     {
993                         (*DrawClippedTilePtr) (Tile, O, 0, Offset,
994                                                TileLine, LineCount);
995                     }
996                 }
997             }
998         }
999     }
1000 }
1001
1002 void orgDrawBackgroundMosaic (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
1003 {
1004     CHECK_SOUND();
1005
1006     uint32 Tile;
1007     uint16 *SC0;
1008     uint16 *SC1;
1009     uint16 *SC2;
1010     uint16 *SC3;
1011     uint8 depths [2] = {Z1, Z2};
1012     
1013     if (BGMode == 0)
1014         BG.StartPalette = bg << 5;
1015     else
1016         BG.StartPalette = 0;
1017
1018     SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
1019
1020     if (PPU.BG[bg].SCSize & 1)
1021         SC1 = SC0 + 1024;
1022     else
1023         SC1 = SC0;
1024
1025         if((SC1-(unsigned short*)Memory.VRAM)>0x10000)
1026                 SC1-=0x10000;
1027
1028
1029     if (PPU.BG[bg].SCSize & 2)
1030         SC2 = SC1 + 1024;
1031     else
1032         SC2 = SC0;
1033
1034         if((SC2-(unsigned short*)Memory.VRAM)>0x10000)
1035                 SC2-=0x10000;
1036
1037
1038     if (PPU.BG[bg].SCSize & 1)
1039         SC3 = SC2 + 1024;
1040     else
1041         SC3 = SC2;
1042
1043         if((SC3-(unsigned short*)Memory.VRAM)>0x10000)
1044                 SC3-=0x10000;
1045
1046     uint32 Lines;
1047     uint32 OffsetMask;
1048     uint32 OffsetShift;
1049
1050     if (BG.TileSize == 16)
1051     {
1052         OffsetMask = 0x3ff;
1053         OffsetShift = 4;
1054     }
1055     else
1056     {
1057         OffsetMask = 0x1ff;
1058         OffsetShift = 3;
1059     }
1060
1061     for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines)
1062     {
1063         uint32 VOffset = LineData [Y].BG[bg].VOffset;
1064         uint32 HOffset = LineData [Y].BG[bg].HOffset;
1065         uint32 MosaicOffset = Y % PPU.Mosaic;
1066
1067         for (Lines = 1; Lines < PPU.Mosaic - MosaicOffset; Lines++)
1068             if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) ||
1069                 (HOffset != LineData [Y + Lines].BG[bg].HOffset))
1070                 break;
1071         
1072         uint32 MosaicLine = VOffset + Y - MosaicOffset;
1073
1074         if (Y + Lines > GFX.EndY)
1075             Lines = GFX.EndY + 1 - Y;
1076         uint32 VirtAlign = (MosaicLine & 7) << 3;
1077         
1078         uint16 *b1;
1079         uint16 *b2;
1080
1081         uint32 ScreenLine = MosaicLine >> OffsetShift;
1082         uint32 Rem16 = MosaicLine & 15;
1083
1084         if (ScreenLine & 0x20)
1085             b1 = SC2, b2 = SC3;
1086         else
1087             b1 = SC0, b2 = SC1;
1088
1089         b1 += (ScreenLine & 0x1f) << 5;
1090         b2 += (ScreenLine & 0x1f) << 5;
1091         uint16 *t;
1092         uint32 Left = 0;
1093         uint32 Right = 256;
1094
1095         uint32 ClipCount = GFX.pCurrentClip->Count [bg];
1096         uint32 HPos = HOffset;
1097         uint32 PixWidth = PPU.Mosaic;
1098
1099         if (!ClipCount)
1100             ClipCount = 1;
1101
1102         for (uint32 clip = 0; clip < ClipCount; clip++)
1103         {
1104             if (GFX.pCurrentClip->Count [bg])
1105             {
1106                 Left = GFX.pCurrentClip->Left [clip][bg];
1107                 Right = GFX.pCurrentClip->Right [clip][bg];
1108                 uint32 r = Left % PPU.Mosaic;
1109                 HPos = HOffset + Left;
1110                 PixWidth = PPU.Mosaic - r;
1111             }
1112             uint32 s = Y * GFX.PPL + Left * GFX.PixSize;
1113             for (uint32 x = Left; x < Right; x += PixWidth, 
1114                  s += PixWidth * GFX.PixSize,
1115                  HPos += PixWidth, PixWidth = PPU.Mosaic)
1116             {
1117                 uint32 Quot = (HPos & OffsetMask) >> 3;
1118
1119                 if (x + PixWidth >= Right)
1120                     PixWidth = Right - x;
1121
1122                 if (BG.TileSize == 8)
1123                 {
1124                     if (Quot > 31)
1125                         t = b2 + (Quot & 0x1f);
1126                     else
1127                         t = b1 + Quot;
1128                 }
1129                 else
1130                 {
1131                     if (Quot > 63)
1132                         t = b2 + ((Quot >> 1) & 0x1f);
1133                     else
1134                         t = b1 + (Quot >> 1);
1135                 }
1136
1137                 Tile = READ_2BYTES (t);
1138                 GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
1139
1140                 // orgDraw tile...
1141                 if (BG.TileSize != 8)
1142                 {
1143                     if (Tile & H_FLIP)
1144                     {
1145                         // Horizontal flip, but what about vertical flip ?
1146                         if (Tile & V_FLIP)
1147                         {
1148                             // Both horzontal & vertical flip
1149                             if (Rem16 < 8)
1150                             {
1151                                 (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s,
1152                                                       HPos & 7, PixWidth,
1153                                                       VirtAlign, Lines);
1154                             }
1155                             else
1156                             {
1157                                 (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s,
1158                                                       HPos & 7, PixWidth,
1159                                                       VirtAlign, Lines);
1160                             }
1161                         }
1162                         else
1163                         {
1164                             // Horizontal flip only
1165                             if (Rem16 > 7)
1166                             {
1167                                 (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s,
1168                                                       HPos & 7, PixWidth,
1169                                                       VirtAlign, Lines);
1170                             }
1171                             else
1172                             {
1173                                 (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s,
1174                                                       HPos & 7, PixWidth,
1175                                                       VirtAlign, Lines);
1176                             }
1177                         }
1178                     }
1179                     else
1180                     {
1181                         // No horizontal flip, but is there a vertical flip ?
1182                         if (Tile & V_FLIP)
1183                         {
1184                             // Vertical flip only
1185                             if (Rem16 < 8)
1186                             {
1187                                 (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s,
1188                                                       HPos & 7, PixWidth,
1189                                                       VirtAlign, Lines);
1190                             }
1191                             else
1192                             {
1193                                 (*DrawLargePixelPtr) (Tile + (Quot & 1), s,
1194                                                       HPos & 7, PixWidth,
1195                                                       VirtAlign, Lines);
1196                             }
1197                         }
1198                         else
1199                         {
1200                             // Normal unflipped
1201                             if (Rem16 > 7)
1202                             {
1203                                 (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s,
1204                                                       HPos & 7, PixWidth,
1205                                                       VirtAlign, Lines);
1206                             }
1207                             else
1208                             {
1209                                 (*DrawLargePixelPtr) (Tile + (Quot & 1), s,
1210                                                       HPos & 7, PixWidth,
1211                                                       VirtAlign, Lines);
1212                             }
1213                         }
1214                     }
1215                 }
1216                 else
1217                     (*DrawLargePixelPtr) (Tile, s, HPos & 7, PixWidth,
1218                                           VirtAlign, Lines);
1219             }
1220         }
1221     }
1222 }
1223
1224 void orgDrawBackgroundOffset (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
1225 {
1226     CHECK_SOUND();
1227
1228     uint32 Tile;
1229     uint16 *SC0;
1230     uint16 *SC1;
1231     uint16 *SC2;
1232     uint16 *SC3;
1233     uint16 *BPS0;
1234     uint16 *BPS1;
1235     uint16 *BPS2;
1236     uint16 *BPS3;
1237     uint32 Width;
1238     int VOffsetOffset = BGMode == 4 ? 0 : 32;
1239     uint8 depths [2] = {Z1, Z2};
1240     
1241     BG.StartPalette = 0;
1242
1243     BPS0 = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1];
1244
1245     if (PPU.BG[2].SCSize & 1)
1246         BPS1 = BPS0 + 1024;
1247     else
1248         BPS1 = BPS0;
1249
1250     if (PPU.BG[2].SCSize & 2)
1251         BPS2 = BPS1 + 1024;
1252     else
1253         BPS2 = BPS0;
1254
1255     if (PPU.BG[2].SCSize & 1)
1256         BPS3 = BPS2 + 1024;
1257     else
1258         BPS3 = BPS2;
1259     
1260     SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
1261
1262     if (PPU.BG[bg].SCSize & 1)
1263         SC1 = SC0 + 1024;
1264     else
1265         SC1 = SC0;
1266
1267         if((SC1-(unsigned short*)Memory.VRAM)>0x10000)
1268                 SC1-=0x10000;
1269
1270
1271     if (PPU.BG[bg].SCSize & 2)
1272         SC2 = SC1 + 1024;
1273     else
1274         SC2 = SC0;
1275
1276         if((SC2-(unsigned short*)Memory.VRAM)>0x10000)
1277                 SC2-=0x10000;
1278
1279
1280     if (PPU.BG[bg].SCSize & 1)
1281         SC3 = SC2 + 1024;
1282     else
1283         SC3 = SC2;
1284
1285         if((SC3-(unsigned short*)Memory.VRAM)>0x10000)
1286                 SC3-=0x10000;
1287
1288
1289     static const int Lines = 1;
1290     int OffsetMask;
1291     int OffsetShift;
1292     int OffsetEnableMask = 1 << (bg + 13);
1293
1294     if (BG.TileSize == 16)
1295     {
1296         OffsetMask = 0x3ff;
1297         OffsetShift = 4;
1298     }
1299     else
1300     {
1301         OffsetMask = 0x1ff;
1302         OffsetShift = 3;
1303     }
1304
1305     for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y++)
1306     {
1307                 uint32 VOff = LineData [Y].BG[2].VOffset - 1;
1308 //              uint32 VOff = LineData [Y].BG[2].VOffset;
1309         uint32 HOff = LineData [Y].BG[2].HOffset;
1310
1311         int VirtAlign;
1312         int ScreenLine = VOff >> 3;
1313         int t1;
1314         int t2;
1315         uint16 *s0;
1316         uint16 *s1;
1317         uint16 *s2;
1318
1319         if (ScreenLine & 0x20)
1320             s1 = BPS2, s2 = BPS3;
1321         else
1322             s1 = BPS0, s2 = BPS1;
1323
1324         s1 += (ScreenLine & 0x1f) << 5;
1325         s2 += (ScreenLine & 0x1f) << 5;
1326
1327                 if(BGMode != 4)
1328                 {
1329                         if((ScreenLine & 0x1f) == 0x1f)
1330                         {
1331                                 if(ScreenLine & 0x20)
1332                                         VOffsetOffset = BPS0 - BPS2 - 0x1f*32;
1333                                 else
1334                                         VOffsetOffset = BPS2 - BPS0 - 0x1f*32;
1335                         }
1336                         else
1337                         {
1338                                 VOffsetOffset = 32;
1339                         }
1340                 }
1341         
1342         int clipcount = GFX.pCurrentClip->Count [bg];
1343         if (!clipcount)
1344             clipcount = 1;
1345
1346         for (int clip = 0; clip < clipcount; clip++)
1347         {
1348             uint32 Left;
1349             uint32 Right;
1350
1351             if (!GFX.pCurrentClip->Count [bg])
1352             {
1353                 Left = 0;
1354                 Right = 256;
1355             }
1356             else
1357             {
1358                 Left = GFX.pCurrentClip->Left [clip][bg];
1359                 Right = GFX.pCurrentClip->Right [clip][bg];
1360
1361                 if (Right <= Left)
1362                     continue;
1363             }
1364
1365             uint32 VOffset;
1366             uint32 HOffset;
1367                         //added:
1368                         uint32 LineHOffset=LineData [Y].BG[bg].HOffset;
1369         
1370             uint32 Offset;
1371             uint32 HPos;
1372             uint32 Quot;
1373             uint32 Count;
1374             uint16 *t;
1375             uint32 Quot2;
1376             uint32 VCellOffset;
1377             uint32 HCellOffset;
1378             uint16 *b1;
1379             uint16 *b2;
1380             uint32 TotalCount = 0;
1381             uint32 MaxCount = 8;
1382
1383             uint32 s = Left * GFX.PixSize + Y * GFX.PPL;
1384             bool8 left_hand_edge = (Left == 0);
1385             Width = Right - Left;
1386
1387             if (Left & 7)
1388                 MaxCount = 8 - (Left & 7);
1389
1390             while (Left < Right) 
1391             {
1392                 if (left_hand_edge)
1393                 {
1394                     // The SNES offset-per-tile background mode has a
1395                     // hardware limitation that the offsets cannot be set
1396                     // for the tile at the left-hand edge of the screen.
1397                     VOffset = LineData [Y].BG[bg].VOffset;
1398
1399                                         //MKendora; use temp var to reduce memory accesses
1400                                         //HOffset = LineData [Y].BG[bg].HOffset;
1401
1402                                         HOffset = LineHOffset;
1403                                         //End MK
1404
1405                     left_hand_edge = FALSE;
1406                 }
1407                 else
1408
1409                 {
1410                     // All subsequent offset tile data is shifted left by one,
1411                     // hence the - 1 below.
1412
1413                     Quot2 = ((HOff + Left - 1) & OffsetMask) >> 3;
1414
1415                     if (Quot2 > 31)
1416                         s0 = s2 + (Quot2 & 0x1f);
1417                     else
1418                         s0 = s1 + Quot2;
1419
1420                     HCellOffset = READ_2BYTES (s0);
1421
1422                     if (BGMode == 4)
1423                     {
1424                         VOffset = LineData [Y].BG[bg].VOffset;
1425                                                 
1426                                                 //MKendora another mem access hack
1427                                                 //HOffset = LineData [Y].BG[bg].HOffset;
1428                                                 HOffset=LineHOffset;
1429                                                 //end MK
1430
1431                         if ((HCellOffset & OffsetEnableMask))
1432                         {
1433                             if (HCellOffset & 0x8000)
1434                                 VOffset = HCellOffset + 1;
1435                             else
1436                                 HOffset = HCellOffset;
1437                         }
1438                     }
1439                     else
1440                     {
1441                         VCellOffset = READ_2BYTES (s0 + VOffsetOffset);
1442                         if ((VCellOffset & OffsetEnableMask))
1443                             VOffset = VCellOffset + 1;
1444                         else
1445                             VOffset = LineData [Y].BG[bg].VOffset;
1446
1447                                                 //MKendora Strike Gunner fix
1448                         if ((HCellOffset & OffsetEnableMask))
1449                                                 {
1450                                                         //HOffset= HCellOffset;
1451                                                         
1452                                                         HOffset = (HCellOffset & ~7)|(LineHOffset&7);
1453                                                         //HOffset |= LineData [Y].BG[bg].HOffset&7;
1454                                                 }
1455                         else
1456                                                         HOffset=LineHOffset;
1457                                                         //HOffset = LineData [Y].BG[bg].HOffset - 
1458                                                         //Settings.StrikeGunnerOffsetHack;
1459                                                 //HOffset &= (~7);
1460                                                 //end MK
1461                     }
1462                 }
1463                 VirtAlign = ((Y + VOffset) & 7) << 3;
1464                 ScreenLine = (VOffset + Y) >> OffsetShift;
1465
1466                 if (((VOffset + Y) & 15) > 7)
1467                 {
1468                     t1 = 16;
1469                     t2 = 0;
1470                 }
1471                 else
1472                 {
1473                     t1 = 0;
1474                     t2 = 16;
1475                 }
1476
1477                 if (ScreenLine & 0x20)
1478                     b1 = SC2, b2 = SC3;
1479                 else
1480                     b1 = SC0, b2 = SC1;
1481
1482                 b1 += (ScreenLine & 0x1f) << 5;
1483                 b2 += (ScreenLine & 0x1f) << 5;
1484
1485                 HPos = (HOffset + Left) & OffsetMask;
1486
1487                 Quot = HPos >> 3;
1488
1489                 if (BG.TileSize == 8)
1490                 {
1491                     if (Quot > 31)
1492                         t = b2 + (Quot & 0x1f);
1493                     else
1494                         t = b1 + Quot;
1495                 }
1496                 else
1497                 {
1498                     if (Quot > 63)
1499                         t = b2 + ((Quot >> 1) & 0x1f);
1500                     else
1501                         t = b1 + (Quot >> 1);
1502                 }
1503
1504                 if (MaxCount + TotalCount > Width)
1505                     MaxCount = Width - TotalCount;
1506
1507                 Offset = HPos & 7;
1508
1509                                 //Count =1;
1510                 Count = 8 - Offset;
1511                 if (Count > MaxCount)
1512                     Count = MaxCount;
1513
1514                 s -= Offset * GFX.PixSize;
1515                 Tile = READ_2BYTES(t);
1516                 GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
1517
1518                 if (BG.TileSize == 8)
1519                     (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines);
1520                 else
1521                 {
1522                     if (!(Tile & (V_FLIP | H_FLIP)))
1523                     {
1524                         // Normal, unflipped
1525                         (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1),
1526                                                s, Offset, Count, VirtAlign, Lines);
1527                     }
1528                     else
1529                     if (Tile & H_FLIP)
1530                     {
1531                         if (Tile & V_FLIP)
1532                         {
1533                             // H & V flip
1534                             (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
1535                                                    s, Offset, Count, VirtAlign, Lines);
1536                         }
1537                         else
1538                         {
1539                             // H flip only
1540                             (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
1541                                                    s, Offset, Count, VirtAlign, Lines);
1542                         }
1543                     }
1544                     else
1545                     {
1546                         // V flip only
1547                         (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1),
1548                                                s, Offset, Count, VirtAlign, Lines);
1549                     }
1550                 }
1551
1552                 Left += Count;
1553                 TotalCount += Count;
1554                 s += (Offset + Count) * GFX.PixSize;
1555                 MaxCount = 8;
1556             }
1557         }
1558     }
1559 }
1560
1561 void orgDrawBackgroundMode5 (uint32 /* BGMODE */, uint32 bg, uint8 Z1, uint8 Z2)
1562 {
1563     CHECK_SOUND();
1564
1565     GFX.Pitch = GFX.RealPitch;
1566     GFX.PPL = GFX.PPLx2 >> 1;
1567     GFX.PixSize = 1;
1568     uint8 depths [2] = {Z1, Z2};
1569
1570     uint32 Tile;
1571     uint16 *SC0;
1572     uint16 *SC1;
1573     uint16 *SC2;
1574     uint16 *SC3;
1575     uint32 Width;
1576     
1577     BG.StartPalette = 0;
1578
1579     SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
1580
1581     if ((PPU.BG[bg].SCSize & 1))
1582         SC1 = SC0 + 1024;
1583     else
1584         SC1 = SC0;
1585
1586         if((SC1-(unsigned short*)Memory.VRAM)>0x10000)
1587                 SC1=(uint16*)&Memory.VRAM[(((uint8*)SC1)-Memory.VRAM)%0x10000];
1588
1589     if ((PPU.BG[bg].SCSize & 2))
1590         SC2 = SC1 + 1024;
1591     else
1592         SC2 = SC0;
1593
1594                 if((SC2-(unsigned short*)Memory.VRAM)>0x10000)
1595                 SC2=(uint16*)&Memory.VRAM[(((uint8*)SC2)-Memory.VRAM)%0x10000];
1596
1597
1598     if ((PPU.BG[bg].SCSize & 1))
1599         SC3 = SC2 + 1024;
1600     else
1601         SC3 = SC2;
1602     
1603         if((SC3-(unsigned short*)Memory.VRAM)>0x10000)
1604                 SC3=(uint16*)&Memory.VRAM[(((uint8*)SC3)-Memory.VRAM)%0x10000];
1605
1606
1607     int Lines;
1608     int VOffsetMask;
1609     int VOffsetShift;
1610
1611     if (BG.TileSize == 16)
1612     {
1613         VOffsetMask = 0x3ff;
1614         VOffsetShift = 4;
1615     }
1616     else
1617     {
1618         VOffsetMask = 0x1ff;
1619         VOffsetShift = 3;
1620     }
1621     int endy = GFX.EndY;
1622
1623     for (int Y = GFX.StartY; Y <= endy; Y += Lines)
1624     {
1625         int y = Y;
1626         uint32 VOffset = LineData [y].BG[bg].VOffset;
1627         uint32 HOffset = LineData [y].BG[bg].HOffset;
1628         int VirtAlign = (Y + VOffset) & 7;
1629         
1630         for (Lines = 1; Lines < 8 - VirtAlign; Lines++)
1631             if ((VOffset != LineData [y + Lines].BG[bg].VOffset) ||
1632                 (HOffset != LineData [y + Lines].BG[bg].HOffset))
1633                 break;
1634
1635         HOffset <<= 1;
1636         if (Y + Lines > endy)
1637             Lines = endy + 1 - Y;
1638 //      VirtAlign <<= 3;
1639         
1640         int ScreenLine = (VOffset + Y) >> VOffsetShift;
1641         int t1;
1642         int t2;
1643         if (((VOffset + Y) & 15) > 7)
1644         {
1645             t1 = 16;
1646             t2 = 0;
1647         }
1648         else
1649         {
1650             t1 = 0;
1651             t2 = 16;
1652         }
1653         uint16 *b1;
1654         uint16 *b2;
1655
1656         if (ScreenLine & 0x20)
1657             b1 = SC2, b2 = SC3;
1658         else
1659             b1 = SC0, b2 = SC1;
1660
1661         b1 += (ScreenLine & 0x1f) << 5;
1662         b2 += (ScreenLine & 0x1f) << 5;
1663
1664         int clipcount = GFX.pCurrentClip->Count [bg];
1665         if (!clipcount)
1666             clipcount = 1;
1667         for (int clip = 0; clip < clipcount; clip++)
1668         {
1669             int Left;
1670             int Right;
1671
1672             if (!GFX.pCurrentClip->Count [bg])
1673             {
1674                 Left = 0;
1675                 Right = 512;
1676             }
1677             else
1678             {
1679                 Left = GFX.pCurrentClip->Left [clip][bg]* 2;
1680                 Right = GFX.pCurrentClip->Right [clip][bg] * 2;
1681
1682                 if (Right <= Left)
1683                     continue;
1684             }
1685
1686             uint32 s = (Left>>1) /** GFX.PixSize*/ + Y * 256;//GFX.PPL;
1687             uint32 HPos = (HOffset + Left /** GFX.PixSize*/) & 0x3ff;
1688
1689             uint32 Quot = HPos >> 3;
1690             uint32 Count = 0;
1691             
1692             uint16 *t;
1693             if (Quot > 63)
1694                 t = b2 + ((Quot >> 1) & 0x1f);
1695             else
1696                 t = b1 + (Quot >> 1);
1697
1698             Width = Right - Left;
1699             // Left hand edge clipped tile
1700             if (HPos & 7)
1701             {
1702                 int Offset = (HPos & 7);
1703                 Count = 8 - Offset;
1704                 if (Count > Width)
1705                     Count = Width;
1706                 s -= Offset>>1;
1707                 Tile = READ_2BYTES (t);
1708                 GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
1709
1710                 if (BG.TileSize == 8)
1711                 {
1712                     if (!(Tile & H_FLIP))
1713                     {
1714                         // Normal, unflipped
1715                         (*DrawHiResClippedTilePtr) (Tile + (Quot & 1),
1716                                                     s, Offset, Count, VirtAlign, Lines);
1717                     }
1718                     else
1719                     {
1720                         // H flip
1721                         (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1),
1722                                                     s, Offset, Count, VirtAlign, Lines);
1723                     }
1724                 }
1725                 else
1726                 {
1727                     if (!(Tile & (V_FLIP | H_FLIP)))
1728                     {
1729                         // Normal, unflipped
1730                         (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1),
1731                                                     s, Offset, Count, VirtAlign, Lines);
1732                     }
1733                     else
1734                     if (Tile & H_FLIP)
1735                     {
1736                         if (Tile & V_FLIP)
1737                         {
1738                             // H & V flip
1739                             (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
1740                                                         s, Offset, Count, VirtAlign, Lines);
1741                         }
1742                         else
1743                         {
1744                             // H flip only
1745                             (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
1746                                                         s, Offset, Count, VirtAlign, Lines);
1747                         }
1748                     }
1749                     else
1750                     {
1751                         // V flip only
1752                         (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1),
1753                                                     s, Offset, Count, VirtAlign, Lines);
1754                     }
1755                 }
1756
1757                 t += Quot & 1;
1758                 if (Quot == 63)
1759                     t = b2;
1760                 else if (Quot == 127)
1761                     t = b1;
1762                 Quot++;
1763                 s += /*8*/4;
1764             }
1765
1766             // Middle, unclipped tiles
1767             Count = Width - Count;
1768             int Middle = Count >> 3;
1769             Count &= 7;
1770             for (int C = Middle; C > 0; s += /*8*/4, Quot++, C--)
1771             {
1772                 Tile = READ_2BYTES(t);
1773                 GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
1774                 if (BG.TileSize == 8)
1775                 {
1776                     if (!(Tile & H_FLIP))
1777                     {
1778                         // Normal, unflipped
1779                         (*DrawHiResTilePtr) (Tile + (Quot & 1),
1780                                              s, VirtAlign, Lines);
1781                     }
1782                     else
1783                     {
1784                         // H flip
1785                         (*DrawHiResTilePtr) (Tile + 1 - (Quot & 1),
1786                                             s, VirtAlign, Lines);
1787                     }
1788                 }
1789                 else
1790                 {
1791                     if (!(Tile & (V_FLIP | H_FLIP)))
1792                     {
1793                         // Normal, unflipped
1794                         (*DrawHiResTilePtr) (Tile + t1 + (Quot & 1),
1795                                              s, VirtAlign, Lines);
1796                     }
1797                     else
1798                     if (Tile & H_FLIP)
1799                     {
1800                         if (Tile & V_FLIP)
1801                         {
1802                             // H & V flip
1803                             (*DrawHiResTilePtr) (Tile + t2 + 1 - (Quot & 1),
1804                                                  s, VirtAlign, Lines);
1805                         }
1806                         else
1807                         {
1808                             // H flip only
1809                             (*DrawHiResTilePtr) (Tile + t1 + 1 - (Quot & 1),
1810                                                  s, VirtAlign, Lines);
1811                         }
1812                     }
1813                     else
1814                     {
1815                         // V flip only
1816                         (*DrawHiResTilePtr) (Tile + t2 + (Quot & 1),
1817                                              s, VirtAlign, Lines);
1818                     }
1819                 }
1820
1821                 t += Quot & 1;
1822                 if (Quot == 63)
1823                     t = b2;
1824                 else
1825                 if (Quot == 127)
1826                     t = b1;
1827             }
1828
1829             // Right-hand edge clipped tiles
1830             if (Count)
1831             {
1832                 Tile = READ_2BYTES(t);
1833                 GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
1834                 if (BG.TileSize == 8)
1835                 {
1836                     if (!(Tile & H_FLIP))
1837                     {
1838                         // Normal, unflipped
1839                         (*DrawHiResClippedTilePtr) (Tile + (Quot & 1),
1840                                                     s, 0, Count, VirtAlign, Lines);
1841                     }
1842                     else
1843                     {
1844                         // H flip
1845                         (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1),
1846                                                     s, 0, Count, VirtAlign, Lines);
1847                     }
1848                 }
1849                 else
1850                 {
1851                     if (!(Tile & (V_FLIP | H_FLIP)))
1852                     {
1853                         // Normal, unflipped
1854                         (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1),
1855                                                     s, 0, Count, VirtAlign, Lines);
1856                     }
1857                     else
1858                     if (Tile & H_FLIP)
1859                     {
1860                         if (Tile & V_FLIP)
1861                         {
1862                             // H & V flip
1863                             (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
1864                                                         s, 0, Count, VirtAlign, Lines);
1865                         }
1866                         else
1867                         {
1868                             // H flip only
1869                             (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
1870                                                         s, 0, Count, VirtAlign, Lines);
1871                         }
1872                     }
1873                     else
1874                     {
1875                         // V flip only
1876                         (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1),
1877                                                     s, 0, Count, VirtAlign, Lines);
1878                     }
1879                 }
1880             }
1881         }
1882     }
1883     GFX.Pitch = GFX.RealPitch;
1884     GFX.PPL = GFX.PPLx2 >> 1;
1885 }
1886
1887 void orgDrawBackground (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
1888 {
1889     GFX.PixSize = 1;
1890
1891     BG.TileSize = BGSizes [PPU.BG[bg].BGSize];
1892     BG.BitShift = BitShifts[BGMode][bg];
1893     BG.TileShift = TileShifts[BGMode][bg];
1894     BG.TileAddress = PPU.BG[bg].NameBase << 1;
1895     BG.NameSelect = 0;
1896     BG.Buffer = IPPU.TileCache [Depths [BGMode][bg]];
1897     BG.Buffered = IPPU.TileCached [Depths [BGMode][bg]];
1898     BG.PaletteShift = PaletteShifts[BGMode][bg];
1899     BG.PaletteMask = PaletteMasks[BGMode][bg];
1900     BG.DirectColourMode = (BGMode == 3 || BGMode == 4) && bg == 0 &&
1901                           (GFX.r2130 & 1);
1902
1903     if (PPU.BGMosaic [bg] && PPU.Mosaic > 1)
1904     {
1905         orgDrawBackgroundMosaic (BGMode, bg, Z1, Z2);
1906         return;
1907
1908     }
1909     switch (BGMode)
1910     {
1911     case 2:
1912         if (Settings.WrestlemaniaArcade)
1913             break;
1914     case 4: // Used by Puzzle Bobble
1915         orgDrawBackgroundOffset (BGMode, bg, Z1, Z2);
1916         return;
1917
1918     case 5:
1919     case 6: // XXX: is also offset per tile.
1920 //      if (Settings.SupportHiRes)
1921         {
1922             orgDrawBackgroundMode5 (BGMode, bg, Z1, Z2);
1923             return;
1924         }
1925         break;
1926     }
1927     CHECK_SOUND();
1928
1929     uint32 Tile;
1930     uint16 *SC0;
1931     uint16 *SC1;
1932     uint16 *SC2;
1933     uint16 *SC3;
1934     uint32 Width;
1935     uint8 depths [2] = {Z1, Z2};
1936     
1937     if (BGMode == 0)
1938         BG.StartPalette = bg << 5;
1939     else
1940         BG.StartPalette = 0;
1941
1942     SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
1943
1944     if (PPU.BG[bg].SCSize & 1)
1945         SC1 = SC0 + 1024;
1946     else
1947         SC1 = SC0;
1948
1949         if(SC1>=(unsigned short*)(Memory.VRAM+0x10000))
1950                 SC1=(uint16*)&Memory.VRAM[((uint8*)SC1-&Memory.VRAM[0])%0x10000];
1951
1952     if (PPU.BG[bg].SCSize & 2)
1953         SC2 = SC1 + 1024;
1954     else
1955         SC2 = SC0;
1956
1957                 if((SC2-(unsigned short*)Memory.VRAM)>0x10000)
1958                 SC2-=0x10000;
1959
1960
1961     if (PPU.BG[bg].SCSize & 1)
1962         SC3 = SC2 + 1024;
1963     else
1964         SC3 = SC2;
1965     
1966         if((SC3-(unsigned short*)Memory.VRAM)>0x10000)
1967                 SC3-=0x10000;
1968
1969
1970     int Lines;
1971     int OffsetMask;
1972     int OffsetShift;
1973
1974     if (BG.TileSize == 16)
1975     {
1976         OffsetMask = 0x3ff;
1977         OffsetShift = 4;
1978     }
1979     else
1980     {
1981         OffsetMask = 0x1ff;
1982         OffsetShift = 3;
1983     }
1984
1985     for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines)
1986     {
1987         uint32 VOffset = LineData [Y].BG[bg].VOffset;
1988         uint32 HOffset = LineData [Y].BG[bg].HOffset;
1989         int VirtAlign = (Y + VOffset) & 7;
1990         
1991         for (Lines = 1; Lines < 8 - VirtAlign; Lines++)
1992             if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) ||
1993                 (HOffset != LineData [Y + Lines].BG[bg].HOffset))
1994                 break;
1995
1996         if (Y + Lines > GFX.EndY)
1997             Lines = GFX.EndY + 1 - Y;
1998
1999         VirtAlign <<= 3;
2000         
2001         uint32 ScreenLine = (VOffset + Y) >> OffsetShift;
2002         uint32 t1;
2003         uint32 t2;
2004         if (((VOffset + Y) & 15) > 7)
2005         {
2006             t1 = 16;
2007             t2 = 0;
2008         }
2009         else
2010         {
2011             t1 = 0;
2012             t2 = 16;
2013         }
2014         uint16 *b1;
2015         uint16 *b2;
2016
2017         if (ScreenLine & 0x20)
2018             b1 = SC2, b2 = SC3;
2019         else
2020             b1 = SC0, b2 = SC1;
2021
2022         b1 += (ScreenLine & 0x1f) << 5;
2023         b2 += (ScreenLine & 0x1f) << 5;
2024
2025         int clipcount = GFX.pCurrentClip->Count [bg];
2026         if (!clipcount)
2027             clipcount = 1;
2028         for (int clip = 0; clip < clipcount; clip++)
2029         {
2030             uint32 Left;
2031             uint32 Right;
2032
2033             if (!GFX.pCurrentClip->Count [bg])
2034             {
2035                 Left = 0;
2036                 Right = 256;
2037             }
2038             else
2039             {
2040                 Left = GFX.pCurrentClip->Left [clip][bg];
2041                 Right = GFX.pCurrentClip->Right [clip][bg];
2042
2043                 if (Right <= Left)
2044                     continue;
2045             }
2046
2047             uint32 s = Left * GFX.PixSize + Y * GFX.PPL;
2048             uint32 HPos = (HOffset + Left) & OffsetMask;
2049
2050             uint32 Quot = HPos >> 3;
2051             uint32 Count = 0;
2052             
2053             uint16 *t;
2054             if (BG.TileSize == 8)
2055             {
2056                 if (Quot > 31)
2057                     t = b2 + (Quot & 0x1f);
2058                 else
2059                     t = b1 + Quot;
2060             }
2061             else
2062             {
2063                 if (Quot > 63)
2064                     t = b2 + ((Quot >> 1) & 0x1f);
2065                 else
2066                     t = b1 + (Quot >> 1);
2067             }
2068
2069             Width = Right - Left;
2070             // Left hand edge clipped tile
2071             if (HPos & 7)
2072             {
2073                 uint32 Offset = (HPos & 7);
2074                 Count = 8 - Offset;
2075                 if (Count > Width)
2076                     Count = Width;
2077                 s -= Offset * GFX.PixSize;
2078                 Tile = READ_2BYTES(t);
2079                 GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
2080
2081                 if (BG.TileSize == 8)
2082                 {
2083                     (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign,
2084                                            Lines);
2085                 }
2086                 else
2087                 {
2088                     if (!(Tile & (V_FLIP | H_FLIP)))
2089                     {
2090                         // Normal, unflipped
2091                         (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1),
2092                                                s, Offset, Count, VirtAlign, Lines);
2093                     }
2094                     else
2095                     if (Tile & H_FLIP)
2096                     {
2097                         if (Tile & V_FLIP)
2098                         {
2099                             // H & V flip
2100                             (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
2101                                                    s, Offset, Count, VirtAlign, Lines);
2102                         }
2103                         else
2104                         {
2105                             // H flip only
2106                             (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
2107                                                    s, Offset, Count, VirtAlign, Lines);
2108                         }
2109                     }
2110                     else
2111                     {
2112                         // V flip only
2113                         (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1), s, 
2114                                                Offset, Count, VirtAlign, Lines);
2115                     }
2116                 }
2117
2118                 if (BG.TileSize == 8)
2119                 {
2120                     t++;
2121                     if (Quot == 31)
2122                         t = b2;
2123                     else if (Quot == 63)
2124                         t = b1;
2125                 }
2126                 else
2127                 {
2128                     t += Quot & 1;
2129                     if (Quot == 63)
2130                         t = b2;
2131                     else if (Quot == 127)
2132                         t = b1;
2133                 }
2134                 Quot++;
2135                 s += 8 * GFX.PixSize;
2136             }
2137
2138             // Middle, unclipped tiles
2139             Count = Width - Count;
2140             int Middle = Count >> 3;
2141             Count &= 7;
2142             for (int C = Middle; C > 0; s += 8 * GFX.PixSize, Quot++, C--)
2143             {
2144                 Tile = READ_2BYTES(t);
2145                 GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
2146
2147                 if (BG.TileSize != 8)
2148                 {
2149                     if (Tile & H_FLIP)
2150                     {
2151                         // Horizontal flip, but what about vertical flip ?
2152                         if (Tile & V_FLIP)
2153                         {
2154                             // Both horzontal & vertical flip
2155                             (*DrawTilePtr) (Tile + t2 + 1 - (Quot & 1), s, 
2156                                             VirtAlign, Lines);
2157                         }
2158                         else
2159                         {
2160                             // Horizontal flip only
2161                             (*DrawTilePtr) (Tile + t1 + 1 - (Quot & 1), s, 
2162                                             VirtAlign, Lines);
2163                         }
2164                     }
2165                     else
2166                     {
2167                         // No horizontal flip, but is there a vertical flip ?
2168                         if (Tile & V_FLIP)
2169                         {
2170                             // Vertical flip only
2171                             (*DrawTilePtr) (Tile + t2 + (Quot & 1), s,
2172                                             VirtAlign, Lines);
2173                         }
2174                         else
2175                         {
2176                             // Normal unflipped
2177                             (*DrawTilePtr) (Tile + t1 + (Quot & 1), s,
2178                                             VirtAlign, Lines);
2179                         }
2180                     }
2181                 }
2182                 else
2183                 {
2184                     (*DrawTilePtr) (Tile, s, VirtAlign, Lines);
2185                 }
2186
2187                 if (BG.TileSize == 8)
2188                 {
2189                     t++;
2190                     if (Quot == 31)
2191                         t = b2;
2192                     else
2193                     if (Quot == 63)
2194                         t = b1;
2195                 }
2196                 else
2197                 {
2198                     t += Quot & 1;
2199                     if (Quot == 63)
2200                         t = b2;
2201                     else
2202                     if (Quot == 127)
2203                         t = b1;
2204                 }
2205             }
2206             // Right-hand edge clipped tiles
2207             if (Count)
2208             {
2209                 Tile = READ_2BYTES(t);
2210                 GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
2211
2212                 if (BG.TileSize == 8)
2213                     (*DrawClippedTilePtr) (Tile, s, 0, Count, VirtAlign, 
2214                                            Lines);
2215                 else
2216                 {
2217                     if (!(Tile & (V_FLIP | H_FLIP)))
2218                     {
2219                         // Normal, unflipped
2220                         (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1), s, 0, 
2221                                                Count, VirtAlign, Lines);
2222                     }
2223                     else
2224                     if (Tile & H_FLIP)
2225                     {
2226                         if (Tile & V_FLIP)
2227                         {
2228                             // H & V flip
2229                             (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
2230                                                    s, 0, Count, VirtAlign, 
2231                                                    Lines);
2232                         }
2233                         else
2234                         {
2235                             // H flip only
2236                             (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
2237                                                    s, 0, Count, VirtAlign,
2238                                                    Lines);
2239                         }
2240                     }
2241                     else
2242                     {
2243                         // V flip only
2244                         (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1),
2245                                                s, 0, Count, VirtAlign, 
2246                                                Lines);
2247                     }
2248                 }
2249             }
2250         }
2251     }
2252 }
2253
2254 #define RENDER_BACKGROUND_MODE7(TYPE,FUNC) \
2255     CHECK_SOUND(); \
2256 \
2257     uint8 *VRAM1 = Memory.VRAM + 1; \
2258     if (GFX.r2130 & 1) \
2259     { \
2260         if (IPPU.DirectColourMapsNeedRebuild) \
2261             S9xBuildDirectColourMaps (); \
2262         GFX.ScreenColors = DirectColourMaps [0]; \
2263     } \
2264     else \
2265         GFX.ScreenColors = IPPU.ScreenColors; \
2266 \
2267     int aa, cc; \
2268     int dir; \
2269     int startx, endx; \
2270     uint32 Left = 0; \
2271     uint32 Right = 256; \
2272     uint32 ClipCount = GFX.pCurrentClip->Count [bg]; \
2273 \
2274     if (!ClipCount) \
2275         ClipCount = 1; \
2276 \
2277     Screen += GFX.StartY * GFX.Pitch; \
2278     uint8 *Depth = GFX.DB + GFX.StartY * GFX.PPL; \
2279     struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; \
2280 \
2281     for (uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX.Pitch, Depth += GFX.PPL, l++) \
2282     { \
2283         int yy; \
2284 \
2285         int32 HOffset = ((int32) LineData [Line].BG[0].HOffset << M7) >> M7; \
2286         int32 VOffset = ((int32) LineData [Line].BG[0].VOffset << M7) >> M7; \
2287 \
2288         int32 CentreX = ((int32) l->CentreX << M7) >> M7; \
2289         int32 CentreY = ((int32) l->CentreY << M7) >> M7; \
2290 \
2291         if (PPU.Mode7VFlip) \
2292             yy = 261 - (int) Line; \
2293         else \
2294             yy = Line; \
2295 \
2296         if (PPU.Mode7Repeat == 0) \
2297             yy += (VOffset - CentreY) % 1023; \
2298         else \
2299             yy += VOffset - CentreY; \
2300         int BB = l->MatrixB * yy + (CentreX << 8); \
2301         int DD = l->MatrixD * yy + (CentreY << 8); \
2302 \
2303         for (uint32 clip = 0; clip < ClipCount; clip++) \
2304         { \
2305             if (GFX.pCurrentClip->Count [bg]) \
2306             { \
2307                 Left = GFX.pCurrentClip->Left [clip][bg]; \
2308                 Right = GFX.pCurrentClip->Right [clip][bg]; \
2309                 if (Right <= Left) \
2310                     continue; \
2311             } \
2312             TYPE *p = (TYPE *) Screen + Left; \
2313             uint8 *d = Depth + Left; \
2314 \
2315             if (PPU.Mode7HFlip) \
2316             { \
2317                 startx = Right - 1; \
2318                 endx = Left - 1; \
2319                 dir = -1; \
2320                 aa = -l->MatrixA; \
2321                 cc = -l->MatrixC; \
2322             } \
2323             else \
2324             { \
2325                 startx = Left; \
2326                 endx = Right; \
2327                 dir = 1; \
2328                 aa = l->MatrixA; \
2329                 cc = l->MatrixC; \
2330             } \
2331             int xx; \
2332             if (PPU.Mode7Repeat == 0) \
2333                 xx = startx + (HOffset - CentreX) % 1023; \
2334             else \
2335                 xx = startx + HOffset - CentreX; \
2336             int AA = l->MatrixA * xx; \
2337             int CC = l->MatrixC * xx; \
2338 \
2339             if (!PPU.Mode7Repeat) \
2340             { \
2341                 for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \
2342                 { \
2343                     int X = ((AA + BB) >> 8) & 0x3ff; \
2344                     int Y = ((CC + DD) >> 8) & 0x3ff; \
2345                     uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
2346                     uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \
2347                     GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
2348                     if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \
2349                     { \
2350                         *p = (FUNC); \
2351                         *d = GFX.Z1; \
2352                     } \
2353                 } \
2354             } \
2355             else \
2356             { \
2357                 for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \
2358                 { \
2359                     int X = ((AA + BB) >> 8); \
2360                     int Y = ((CC + DD) >> 8); \
2361 \
2362                     if (Settings.Dezaemon && PPU.Mode7Repeat == 2) \
2363                     { \
2364                         X &= 0x7ff; \
2365                         Y &= 0x7ff; \
2366                     } \
2367 \
2368                     if (((X | Y) & ~0x3ff) == 0) \
2369                     { \
2370                         uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
2371                         uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \
2372                         GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
2373                         if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \
2374                         { \
2375                             *p = (FUNC); \
2376                             *d = GFX.Z1; \
2377                         } \
2378                     } \
2379                     else \
2380                     { \
2381                         if (PPU.Mode7Repeat == 3) \
2382                         { \
2383                             X = (x + HOffset) & 7; \
2384                             Y = (yy + CentreY) & 7; \
2385                             uint32 b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \
2386                             GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
2387                             if (GFX.Z1 > *d && (b & GFX.Mode7Mask) ) \
2388                             { \
2389                                 *p = (FUNC); \
2390                                 *d = GFX.Z1; \
2391                             } \
2392                         } \
2393                     } \
2394                 } \
2395             } \
2396         } \
2397     }
2398
2399
2400 void orgDrawBGMode7Background16 (uint8 *Screen, int bg)
2401 {
2402     RENDER_BACKGROUND_MODE7 (uint16, GFX.ScreenColors [b & GFX.Mode7Mask]);
2403 }
2404
2405 void orgDrawBGMode7Background16Add (uint8 *Screen, int bg)
2406 {
2407     RENDER_BACKGROUND_MODE7 (uint16, *(d + GFX.DepthDelta) ?
2408                                         (*(d + GFX.DepthDelta) != 1 ?
2409                                             COLOR_ADD (GFX.ScreenColors [b & GFX.Mode7Mask],
2410                                                        p [GFX.Delta]) :
2411                                             COLOR_ADD (GFX.ScreenColors [b & GFX.Mode7Mask],
2412                                                        GFX.FixedColour)) :
2413                                          GFX.ScreenColors [b & GFX.Mode7Mask]);
2414 }
2415
2416 void orgDrawBGMode7Background16Add1_2 (uint8 *Screen, int bg)
2417 {
2418     RENDER_BACKGROUND_MODE7 (uint16, *(d + GFX.DepthDelta) ?
2419                                         (*(d + GFX.DepthDelta) != 1 ?
2420                                             COLOR_ADD1_2 (GFX.ScreenColors [b & GFX.Mode7Mask],
2421                                                        p [GFX.Delta]) :
2422                                             COLOR_ADD (GFX.ScreenColors [b & GFX.Mode7Mask],
2423                                                        GFX.FixedColour)) :
2424                                          GFX.ScreenColors [b & GFX.Mode7Mask]);
2425 }
2426
2427 void orgDrawBGMode7Background16Sub (uint8 *Screen, int bg)
2428 {
2429     RENDER_BACKGROUND_MODE7 (uint16, *(d + GFX.DepthDelta) ?
2430                                         (*(d + GFX.DepthDelta) != 1 ?
2431                                             COLOR_SUB (GFX.ScreenColors [b & GFX.Mode7Mask],
2432                                                        p [GFX.Delta]) :
2433                                             COLOR_SUB (GFX.ScreenColors [b & GFX.Mode7Mask],
2434                                                        GFX.FixedColour)) :
2435                                          GFX.ScreenColors [b & GFX.Mode7Mask]);
2436 }
2437
2438 void orgDrawBGMode7Background16Sub1_2 (uint8 *Screen, int bg)
2439 {
2440     RENDER_BACKGROUND_MODE7 (uint16, *(d + GFX.DepthDelta) ?
2441                                         (*(d + GFX.DepthDelta) != 1 ?
2442                                             COLOR_SUB1_2 (GFX.ScreenColors [b & GFX.Mode7Mask],
2443                                                        p [GFX.Delta]) :
2444                                             COLOR_SUB (GFX.ScreenColors [b & GFX.Mode7Mask],
2445                                                        GFX.FixedColour)) :
2446                                          GFX.ScreenColors [b & GFX.Mode7Mask]);
2447 }
2448
2449
2450 #define _BUILD_SETUP(F) \
2451 GFX.BuildPixel = BuildPixel##F; \
2452 GFX.BuildPixel2 = BuildPixel2##F; \
2453 GFX.DecomposePixel = DecomposePixel##F; \
2454 RED_LOW_BIT_MASK = RED_LOW_BIT_MASK_##F; \
2455 GREEN_LOW_BIT_MASK = GREEN_LOW_BIT_MASK_##F; \
2456 BLUE_LOW_BIT_MASK = BLUE_LOW_BIT_MASK_##F; \
2457 RED_HI_BIT_MASK = RED_HI_BIT_MASK_##F; \
2458 GREEN_HI_BIT_MASK = GREEN_HI_BIT_MASK_##F; \
2459 BLUE_HI_BIT_MASK = BLUE_HI_BIT_MASK_##F; \
2460 MAX_RED = MAX_RED_##F; \
2461 MAX_GREEN = MAX_GREEN_##F; \
2462 MAX_BLUE = MAX_BLUE_##F; \
2463 GREEN_HI_BIT = ((MAX_GREEN_##F + 1) >> 1); \
2464 SPARE_RGB_BIT_MASK = SPARE_RGB_BIT_MASK_##F; \
2465 RGB_LOW_BITS_MASK = (RED_LOW_BIT_MASK_##F | \
2466                      GREEN_LOW_BIT_MASK_##F | \
2467                      BLUE_LOW_BIT_MASK_##F); \
2468 RGB_HI_BITS_MASK = (RED_HI_BIT_MASK_##F | \
2469                     GREEN_HI_BIT_MASK_##F | \
2470                     BLUE_HI_BIT_MASK_##F); \
2471 RGB_HI_BITS_MASKx2 = ((RED_HI_BIT_MASK_##F | \
2472                        GREEN_HI_BIT_MASK_##F | \
2473                        BLUE_HI_BIT_MASK_##F) << 1); \
2474 RGB_REMOVE_LOW_BITS_MASK = ~RGB_LOW_BITS_MASK; \
2475 FIRST_COLOR_MASK = FIRST_COLOR_MASK_##F; \
2476 SECOND_COLOR_MASK = SECOND_COLOR_MASK_##F; \
2477 THIRD_COLOR_MASK = THIRD_COLOR_MASK_##F; \
2478 ALPHA_BITS_MASK = ALPHA_BITS_MASK_##F; \
2479 FIRST_THIRD_COLOR_MASK = FIRST_COLOR_MASK | THIRD_COLOR_MASK; \
2480 TWO_LOW_BITS_MASK = RGB_LOW_BITS_MASK | (RGB_LOW_BITS_MASK << 1); \
2481 HIGH_BITS_SHIFTED_TWO_MASK = (( (FIRST_COLOR_MASK | SECOND_COLOR_MASK | THIRD_COLOR_MASK) & \
2482                                 ~TWO_LOW_BITS_MASK ) >> 2);
2483
2484 void RenderScreen (uint8 *Screen, bool8 sub, bool8 force_no_add, uint8 D)
2485 {
2486     bool8 BG0;
2487     bool8 BG1;
2488     bool8 BG2;
2489     bool8 BG3;
2490     bool8 OB;
2491
2492     GFX.S = Screen;
2493
2494     if (!sub)
2495     {
2496         GFX.pCurrentClip = &IPPU.Clip [0];
2497         BG0 = ON_MAIN (0);
2498         BG1 = ON_MAIN (1);
2499         BG2 = ON_MAIN (2);
2500         BG3 = ON_MAIN (3);
2501         OB  = ON_MAIN (4);
2502     }
2503     else
2504     {
2505         GFX.pCurrentClip = &IPPU.Clip [1];
2506         BG0 = ON_SUB (0);
2507         BG1 = ON_SUB (1);
2508         BG2 = ON_SUB (2);
2509         BG3 = ON_SUB (3);
2510         OB  = ON_SUB (4);
2511     }
2512
2513     sub |= force_no_add;
2514
2515     if (PPU.BGMode <= 1)
2516     {
2517         if (OB)
2518         {
2519             orgSelectTileRenderer (sub || !SUB_OR_ADD(4));
2520             orgDrawOBJS (!sub, D);
2521         }
2522         if (BG0)
2523         {
2524             orgSelectTileRenderer (sub || !SUB_OR_ADD(0));
2525             orgDrawBackground (PPU.BGMode, 0, D + 10, D + 14);
2526         }
2527         if (BG1)
2528         {
2529             orgSelectTileRenderer (sub || !SUB_OR_ADD(1));
2530             orgDrawBackground (PPU.BGMode, 1, D + 9, D + 13);
2531         }
2532         if (BG2)
2533         {
2534             orgSelectTileRenderer (sub || !SUB_OR_ADD(2));
2535             orgDrawBackground (PPU.BGMode, 2, D + 3, 
2536                             (Memory.FillRAM [0x2105] & 8) == 0 ? D + 6 : D + 17);
2537         }
2538         if (BG3 && PPU.BGMode == 0)
2539         {
2540             orgSelectTileRenderer (sub || !SUB_OR_ADD(3));
2541             orgDrawBackground (PPU.BGMode, 3, D + 2, D + 5);
2542         }
2543     }
2544     else if (PPU.BGMode != 7)
2545     {
2546         if (OB)
2547         {
2548             orgSelectTileRenderer (sub || !SUB_OR_ADD(4));
2549             orgDrawOBJS (!sub, D);
2550         }
2551         if (BG0)
2552         {
2553             orgSelectTileRenderer (sub || !SUB_OR_ADD(0));
2554             orgDrawBackground (PPU.BGMode, 0, D + 5, D + 13);
2555         }
2556         if (PPU.BGMode != 6 && BG1)
2557         {
2558             orgSelectTileRenderer (sub || !SUB_OR_ADD(1));
2559             orgDrawBackground (PPU.BGMode, 1, D + 2, D + 9);
2560         }
2561     }
2562     else
2563     {
2564         if (OB)
2565         {
2566             orgSelectTileRenderer (sub || !SUB_OR_ADD(4));
2567             orgDrawOBJS (!sub, D);
2568         }
2569         if (BG0 || ((Memory.FillRAM [0x2133] & 0x40) && BG1))
2570         {
2571             int bg;
2572
2573             if (Memory.FillRAM [0x2133] & 0x40)
2574             {
2575                 GFX.Mode7Mask = 0x7f;
2576                 GFX.Mode7PriorityMask = 0x80;
2577                 Mode7Depths [0] = 5 + D;
2578                 Mode7Depths [1] = 9 + D;
2579                 bg = 1;
2580             }
2581             else
2582             {
2583                 GFX.Mode7Mask = 0xff;
2584                 GFX.Mode7PriorityMask = 0;
2585                 Mode7Depths [0] = 5 + D;
2586                 Mode7Depths [1] = 5 + D;
2587                 bg = 0;
2588             }
2589             if (sub || !SUB_OR_ADD(0))
2590             {
2591
2592                     orgDrawBGMode7Background16 (Screen, bg);
2593             }
2594             else
2595             {
2596                 if (GFX.r2131 & 0x80)
2597                 {
2598                     if (GFX.r2131 & 0x40)
2599                     {
2600                             orgDrawBGMode7Background16Sub1_2 (Screen, bg);
2601                     }
2602                     else
2603                     {
2604                             orgDrawBGMode7Background16Sub (Screen, bg);
2605                     }
2606                 }
2607                 else
2608                 {
2609                     if (GFX.r2131 & 0x40)
2610                     {
2611                             orgDrawBGMode7Background16Add1_2 (Screen, bg);
2612                     }
2613                     else
2614                     {
2615
2616                             orgDrawBGMode7Background16Add (Screen, bg);
2617                     }
2618                 }
2619             }
2620         }
2621     }
2622 }
2623
2624
2625 void orgS9xUpdateScreen ()
2626 {
2627   int32 x2 = 1;
2628
2629   GFX.S = GFX.Screen;
2630   GFX.r2131 = Memory.FillRAM [0x2131];
2631   GFX.r212c = Memory.FillRAM [0x212c];
2632   GFX.r212d = Memory.FillRAM [0x212d];
2633   GFX.r2130 = Memory.FillRAM [0x2130];
2634   GFX.Pseudo = (Memory.FillRAM [0x2133] & 8) != 0 &&
2635     (GFX.r212c & 15) != (GFX.r212d & 15) &&
2636     (GFX.r2131 & 0x3f) == 0;
2637
2638   if (IPPU.OBJChanged)
2639     S9xSetupOBJ ();
2640
2641   if (PPU.RecomputeClipWindows)
2642     {
2643       ComputeClipWindows ();
2644       PPU.RecomputeClipWindows = FALSE;
2645     }
2646
2647   GFX.StartY = IPPU.PreviousLine;
2648   if ((GFX.EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight)
2649     GFX.EndY = PPU.ScreenHeight - 1;
2650
2651   uint32 starty = GFX.StartY;
2652   uint32 endy = GFX.EndY;
2653
2654   uint32 black = BLACK | (BLACK << 16);
2655
2656  
2657  
2658       if (GFX.Pseudo)
2659         {
2660           GFX.r2131 = 0x5f;
2661           GFX.r212d = (Memory.FillRAM [0x212c] ^
2662                        Memory.FillRAM [0x212d]) & 15;
2663           GFX.r212c &= ~GFX.r212d;
2664           GFX.r2130 |= 2;
2665         }
2666
2667       if (!PPU.ForcedBlanking && ADD_OR_SUB_ON_ANYTHING &&
2668           (GFX.r2130 & 0x30) != 0x30 &&
2669           !((GFX.r2130 & 0x30) == 0x10 && IPPU.Clip[1].Count[5] == 0))
2670         {
2671           struct ClipData *pClip;
2672
2673           GFX.FixedColour = BUILD_PIXEL (IPPU.XB [PPU.FixedColourRed],
2674                                          IPPU.XB [PPU.FixedColourGreen],
2675                                          IPPU.XB [PPU.FixedColourBlue]);
2676
2677           // Clear the z-buffer, marking areas 'covered' by the fixed
2678           // colour as depth 1.
2679           pClip = &IPPU.Clip [1];
2680
2681           // Clear the z-buffer
2682           if (pClip->Count [5])
2683             {
2684               // Colour window enabled.
2685               for (uint32 y = starty; y <= endy; y++)
2686                 {
2687                   ZeroMemory (GFX.SubZBuffer + y * GFX.ZPitch,
2688                               IPPU.RenderedScreenWidth);
2689                   ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch,
2690                               IPPU.RenderedScreenWidth);
2691                   if (IPPU.Clip [0].Count [5])
2692                     {
2693                       uint32 *p = (uint32 *) (GFX.SubScreen + y * GFX.Pitch2);
2694                       uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth);
2695                       while (p < q)
2696                         *p++ = black;
2697                     }
2698                   for (uint32 c = 0; c < pClip->Count [5]; c++)
2699                     {
2700                       if (pClip->Right [c][5] > pClip->Left [c][5])
2701                         {
2702                           memset (GFX.SubZBuffer + y * GFX.ZPitch + pClip->Left [c][5] * x2,
2703                                   1, (pClip->Right [c][5] - pClip->Left [c][5]) * x2);
2704                           if (IPPU.Clip [0].Count [5])
2705                             {
2706                               // Blast, have to clear the sub-screen to the fixed-colour
2707                               // because there is a colour window in effect clipping
2708                               // the main screen that will allow the sub-screen
2709                               // 'underneath' to show through.
2710
2711                               uint16 *p = (uint16 *) (GFX.SubScreen + y * GFX.Pitch2);
2712                               uint16 *q = p + pClip->Right [c][5] * x2;
2713                               p += pClip->Left [c][5] * x2;
2714
2715                               while (p < q)
2716                                 *p++ = (uint16) GFX.FixedColour;
2717                             }
2718                         }
2719                     }
2720                 }
2721             }
2722           else
2723             {
2724               for (uint32 y = starty; y <= endy; y++)
2725                 {
2726                   ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch,
2727                               IPPU.RenderedScreenWidth);
2728                   memset (GFX.SubZBuffer + y * GFX.ZPitch, 1,
2729                           IPPU.RenderedScreenWidth);
2730
2731                   if (IPPU.Clip [0].Count [5])
2732                     {
2733                       // Blast, have to clear the sub-screen to the fixed-colour
2734                       // because there is a colour window in effect clipping
2735                       // the main screen that will allow the sub-screen
2736                       // 'underneath' to show through.
2737
2738                       uint32 b = GFX.FixedColour | (GFX.FixedColour << 16);
2739                       uint32 *p = (uint32 *) (GFX.SubScreen + y * GFX.Pitch2);
2740                       uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth);
2741
2742                       while (p < q)
2743                         *p++ = b;
2744                     }
2745                 }
2746             }
2747           if (ANYTHING_ON_SUB)
2748             {
2749               GFX.DB = GFX.SubZBuffer;
2750               RenderScreen (GFX.SubScreen, TRUE, TRUE, SUB_SCREEN_DEPTH);
2751             }
2752
2753           if (IPPU.Clip [0].Count [5])
2754             {
2755              
2756               for (uint32 y = starty; y <= endy; y++)
2757                 {
2758                   register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2);
2759                   register uint8 *d = GFX.SubZBuffer + y * GFX.ZPitch;
2760                   register uint8 *e = d + IPPU.RenderedScreenWidth;
2761                                 
2762                   while (d < e)
2763                     {
2764                       if (*d > 1)
2765                         *p = *(p + GFX.Delta);
2766                       else
2767                         *p = BLACK;
2768                       d++;
2769                       p++;
2770                     }
2771                 }
2772             }
2773
2774           GFX.DB = GFX.ZBuffer;
2775           RenderScreen (GFX.Screen, FALSE, FALSE, MAIN_SCREEN_DEPTH);
2776
2777           if (SUB_OR_ADD(5))
2778             {
2779               uint32 back = IPPU.ScreenColors [0];
2780               uint32 Left = 0;
2781               uint32 Right = 256;
2782               uint32 Count;
2783
2784               pClip = &IPPU.Clip [0];
2785               for (uint32 y = starty; y <= endy; y++)
2786                 {
2787                   if (!(Count = pClip->Count [5]))
2788                     {
2789                       Left = 0;
2790                       Right = 256 * x2;
2791                       Count = 1;
2792                     }
2793
2794                   for (uint32 b = 0; b < Count; b++)
2795                     {
2796                       if (pClip->Count [5])
2797                         {
2798                           Left = pClip->Left [b][5] * x2;
2799                           Right = pClip->Right [b][5] * x2;
2800                           if (Right <= Left)
2801                             continue;
2802                         }
2803
2804                       if (GFX.r2131 & 0x80)
2805                         {
2806                           if (GFX.r2131 & 0x40)
2807                             {
2808                               // Subtract, halving the result.
2809                               register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
2810                               register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
2811                               register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left;
2812                               register uint8 *e = d + Right;
2813                               uint16 back_fixed = COLOR_SUB (back, GFX.FixedColour);
2814
2815                               d += Left;
2816                               while (d < e)
2817                                 {
2818                                   if (*d == 0)
2819                                     {
2820                                       if (*s)
2821                                         {
2822                                           if (*s != 1)
2823                                             *p = COLOR_SUB1_2 (back, *(p + GFX.Delta));
2824                                           else
2825                                             *p = back_fixed;
2826                                         }
2827                                       else
2828                                         *p = (uint16) back;
2829                                     }
2830                                   d++;
2831                                   p++;
2832                                   s++;
2833                                 }
2834                             }
2835                           else
2836                             {
2837                               // Subtract
2838                               register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
2839                               register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left;
2840                               register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
2841                               register uint8 *e = d + Right;
2842                               uint16 back_fixed = COLOR_SUB (back, GFX.FixedColour);
2843
2844                               d += Left;
2845                               while (d < e)
2846                                 {
2847                                   if (*d == 0)
2848                                     {
2849                                       if (*s)
2850                                         {
2851                                           if (*s != 1)
2852                                             *p = COLOR_SUB (back, *(p + GFX.Delta));
2853                                           else
2854                                             *p = back_fixed;
2855                                         }
2856                                       else
2857                                         *p = (uint16) back;
2858                                     }
2859                                   d++;
2860                                   p++;
2861                                   s++;
2862                                 }
2863                             }
2864                         }
2865                       else
2866                         if (GFX.r2131 & 0x40)
2867                           {
2868                             register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
2869                             register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
2870                             register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left;
2871                             register uint8 *e = d + Right;
2872                             uint16 back_fixed = COLOR_ADD (back, GFX.FixedColour);
2873                             d += Left;
2874                             while (d < e)
2875                               {
2876                                 if (*d == 0)
2877                                   {
2878                                     if (*s)
2879                                       {
2880                                         if (*s != 1)
2881                                           *p = COLOR_ADD1_2 (back, *(p + GFX.Delta));
2882                                         else
2883                                           *p = back_fixed;
2884                                       }
2885                                     else
2886                                       *p = (uint16) back;
2887                                   }
2888                                 d++;
2889                                 p++;
2890                                 s++;
2891                               }
2892                           }
2893                         else
2894                           if (back != 0)
2895                             {
2896                               register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
2897                               register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
2898                               register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left;
2899                               register uint8 *e = d + Right;
2900                               uint16 back_fixed = COLOR_ADD (back, GFX.FixedColour);
2901                               d += Left;
2902                               while (d < e)
2903                                 {
2904                                   if (*d == 0)
2905                                     {
2906                                       if (*s)
2907                                         {
2908                                           if (*s != 1)
2909                                             *p = COLOR_ADD (back, *(p + GFX.Delta));
2910                                           else  
2911                                             *p = back_fixed;
2912                                         }
2913                                       else
2914                                         *p = (uint16) back;
2915                                     }
2916                                   d++;
2917                                   p++;
2918                                   s++;
2919                                 }
2920                             }
2921                           else
2922                             {
2923                               if (!pClip->Count [5])
2924                                 {
2925                                   // The backdrop has not been cleared yet - so
2926                                   // copy the sub-screen to the main screen
2927                                   // or fill it with the back-drop colour if the
2928                                   // sub-screen is clear.
2929                                   register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
2930                                   register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
2931                                   register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left;
2932                                   register uint8 *e = d + Right;
2933                                   d += Left;
2934                                   while (d < e)
2935                                     {
2936                                       if (*d == 0)
2937                                         {
2938                                           if (*s)
2939                                             {
2940                                               if (*s != 1)
2941                                                 *p = *(p + GFX.Delta);
2942                                               else      
2943                                                 *p = GFX.FixedColour;
2944                                             }
2945                                           else
2946                                             *p = (uint16) back;
2947                                         }
2948                                       d++;
2949                                       p++;
2950                                       s++;
2951                                     }
2952                                 }
2953                             }
2954                     }
2955                 }
2956             }
2957           else
2958             {
2959               // Subscreen not being added to back
2960               uint32 back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16);
2961               pClip = &IPPU.Clip [0];
2962
2963               if (pClip->Count [5])
2964                 {
2965                   for (uint32 y = starty; y <= endy; y++)
2966                     {
2967                       for (uint32 b = 0; b < pClip->Count [5]; b++)
2968                         {
2969                           uint32 Left = pClip->Left [b][5] * x2;
2970                           uint32 Right = pClip->Right [b][5] * x2;
2971                           uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
2972                           uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
2973                           uint8 *e = d + Right;
2974                           d += Left;
2975
2976                           while (d < e)
2977                             {
2978                               if (*d == 0)
2979                                 *p = (int16) back;
2980                               d++;
2981                               p++;
2982                             }
2983                         }
2984                     }
2985                 }
2986               else
2987                 {
2988                   for (uint32 y = starty; y <= endy; y++)
2989                     {
2990                       uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2);
2991                       uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
2992                       uint8 *e = d + 256 * x2;
2993
2994                       while (d < e)
2995                         {
2996                           if (*d == 0)
2997                             *p = (int16) back;
2998                           d++;
2999                           p++;
3000                         }
3001                     }
3002                 }
3003             }
3004         }
3005       else
3006         {
3007           // 16bit and transparency but currently no transparency effects in
3008           // operation.
3009
3010           uint32 back = IPPU.ScreenColors [0] | 
3011             (IPPU.ScreenColors [0] << 16);
3012
3013           if (PPU.ForcedBlanking)
3014             back = black;
3015
3016           if (IPPU.Clip [0].Count[5])
3017             {
3018               for (uint32 y = starty; y <= endy; y++)
3019                 {
3020                   uint32 *p = (uint32 *) (GFX.Screen + y * GFX.Pitch2);
3021                   uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth);
3022
3023                   while (p < q)
3024                     *p++ = black;
3025
3026                   for (uint32 c = 0; c < IPPU.Clip [0].Count [5]; c++)
3027                     {
3028                       if (IPPU.Clip [0].Right [c][5] > IPPU.Clip [0].Left [c][5])
3029                         {
3030                           uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2);
3031                           uint16 *q = p + IPPU.Clip [0].Right [c][5] * x2;
3032                           p += IPPU.Clip [0].Left [c][5] * x2;
3033
3034                           while (p < q)
3035                             *p++ = (uint16) back;
3036                         }
3037                     }
3038                 }
3039             }
3040           else
3041             {
3042               for (uint32 y = starty; y <= endy; y++)
3043                 {
3044                   uint32 *p = (uint32 *) (GFX.Screen + y * GFX.Pitch2);
3045                   uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth);
3046                   while (p < q)
3047                     *p++ = back;
3048                 }
3049             }
3050           if (!PPU.ForcedBlanking)
3051             {
3052               for (uint32 y = starty; y <= endy; y++)
3053                 {
3054                   ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch,
3055                               IPPU.RenderedScreenWidth);
3056                 }
3057               GFX.DB = GFX.ZBuffer;
3058               RenderScreen (GFX.Screen, FALSE, TRUE, SUB_SCREEN_DEPTH);
3059             }
3060         }
3061     
3062
3063   IPPU.PreviousLine = IPPU.CurrentLine;
3064 }
3065
3066 #ifdef GFX_MULTI_FORMAT
3067
3068 #define _BUILD_PIXEL(F) \
3069 uint32 BuildPixel##F(uint32 R, uint32 G, uint32 B) \
3070 { \
3071     return (BUILD_PIXEL_##F(R,G,B)); \
3072 }\
3073 uint32 BuildPixel2##F(uint32 R, uint32 G, uint32 B) \
3074 { \
3075     return (BUILD_PIXEL2_##F(R,G,B)); \
3076 } \
3077 void DecomposePixel##F(uint32 pixel, uint32 &R, uint32 &G, uint32 &B) \
3078 { \
3079     DECOMPOSE_PIXEL_##F(pixel,R,G,B); \
3080 }
3081
3082 _BUILD_PIXEL(RGB565)
3083 _BUILD_PIXEL(RGB555)
3084 _BUILD_PIXEL(BGR565)
3085 _BUILD_PIXEL(BGR555)
3086 _BUILD_PIXEL(GBR565)
3087 _BUILD_PIXEL(GBR555)
3088 _BUILD_PIXEL(RGB5551)
3089
3090 bool8 S9xSetRenderPixelFormat (int format)
3091 {
3092     extern uint32 current_graphic_format;
3093
3094     current_graphic_format = format;
3095
3096     switch (format)
3097     {
3098     case RGB565:
3099         _BUILD_SETUP(RGB565)
3100         return (TRUE);
3101     case RGB555:
3102         _BUILD_SETUP(RGB555)
3103         return (TRUE);
3104     case BGR565:
3105         _BUILD_SETUP(BGR565)
3106         return (TRUE);
3107     case BGR555:
3108         _BUILD_SETUP(BGR555)
3109         return (TRUE);
3110     case GBR565:
3111         _BUILD_SETUP(GBR565)
3112         return (TRUE);
3113     case GBR555:
3114         _BUILD_SETUP(GBR555)
3115         return (TRUE);
3116     case RGB5551:
3117         _BUILD_SETUP(RGB5551)
3118         return (TRUE);
3119     default:
3120         break;
3121     }
3122     return (FALSE);
3123 }
3124 #endif
3125
3126
3127 void S9xUpdateScreen ()
3128 {
3129     int32 x2 = 1;
3130         
3131     GFX.S = GFX.Screen;
3132     GFX.r2131 = Memory.FillRAM [0x2131];
3133     GFX.r212c = Memory.FillRAM [0x212c];
3134     GFX.r212d = Memory.FillRAM [0x212d];
3135     GFX.r2130 = Memory.FillRAM [0x2130];
3136
3137 #ifdef JP_FIX
3138
3139     GFX.Pseudo = (Memory.FillRAM [0x2133] & 8) != 0 &&
3140                                  (GFX.r212c & 15) != (GFX.r212d & 15) &&
3141                                  (GFX.r2131 == 0x3f);
3142
3143 #else
3144
3145     GFX.Pseudo = (Memory.FillRAM [0x2133] & 8) != 0 &&
3146                 (GFX.r212c & 15) != (GFX.r212d & 15) &&
3147                 (GFX.r2131 & 0x3f) == 0;
3148
3149 #endif
3150         
3151     if (IPPU.OBJChanged)
3152                 S9xSetupOBJ ();
3153         
3154     if (PPU.RecomputeClipWindows)
3155     {
3156                 ComputeClipWindows ();
3157                 PPU.RecomputeClipWindows = FALSE;
3158     }
3159         
3160     GFX.StartY = IPPU.PreviousLine;
3161     if ((GFX.EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight)
3162                 GFX.EndY = PPU.ScreenHeight - 1;
3163
3164         // XXX: Check ForceBlank? Or anything else?
3165         //PPU.RangeTimeOver |= GFX.OBJLines[GFX.EndY].RTOFlags;
3166         
3167     uint32 starty = GFX.StartY;
3168     uint32 endy = GFX.EndY;
3169         
3170     /*if (Settings.SupportHiRes &&
3171                 (PPU.BGMode == 5 || PPU.BGMode == 6 ||
3172                 //IPPU.Interlace || IPPU.DoubleHeightPixels))
3173     {
3174                 if (PPU.BGMode == 5 || PPU.BGMode == 6|| IPPU.Interlace)
3175                 {
3176                         IPPU.RenderedScreenWidth = 512;
3177                         x2 = 2;
3178                 }
3179                 if (IPPU.DoubleHeightPixels)
3180                 {
3181                         starty = GFX.StartY * 2;
3182                         endy = GFX.EndY * 2 + 1;
3183                 }
3184                 if ((PPU.BGMode == 5 || PPU.BGMode == 6) && !IPPU.DoubleWidthPixels)
3185                 {
3186                         // The game has switched from lo-res to hi-res mode part way down
3187                         // the screen. Scale any existing lo-res pixels on screen
3188                         if (Settings.SixteenBit)
3189                         {
3190 #if defined (USE_GLIDE) || defined (USE_OPENGL)
3191                 if (
3192 #ifdef USE_GLIDE
3193                     (Settings.GlideEnable && GFX.Pitch == 512) ||
3194 #endif
3195 #ifdef USE_OPENGL
3196                     (Settings.OpenGLEnable && GFX.Pitch == 512) ||
3197 #endif
3198                     0)
3199                                 {
3200                                         // Have to back out of the speed up hack where the low res.
3201                                         // SNES image was rendered into a 256x239 sized buffer,
3202                                         // ignoring the true, larger size of the buffer.
3203                                         for (register int32 y = (int32) starty - 1; y >= 0; y--)
3204                                         {
3205                                                 register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + 255;
3206                                                 register uint16 *q = (uint16 *) (GFX.Screen + y * GFX.RealPitch) + 510;
3207                                                 for (register int x = 255; x >= 0; x--, p--, q -= 2)
3208                                                         *q = *(q + 1) = *p;
3209                                         }
3210                                         
3211                                         GFX.Pitch = GFX.Pitch2 = GFX.RealPitch;
3212                     GFX.PPL = GFX.Pitch >> 1;
3213                     GFX.PPLx2 = GFX.Pitch;
3214                     GFX.ZPitch = GFX.PPL;
3215                                 }
3216                                 else
3217 #endif
3218                                         for (register uint32 y = 0; y < starty; y++)
3219                                         {
3220                                                 register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + 255;
3221                                                 register uint16 *q = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + 510;
3222                                                 
3223                                                 for (register int x = 255; x >= 0; x--, p--, q -= 2)
3224                                                         *q = *(q + 1) = *p;
3225                                         }
3226                         }
3227                         else
3228                         {
3229                                 for (register uint32 y = 0; y < starty; y++)
3230                                 {
3231                                         register uint8 *p = GFX.Screen + y * GFX.Pitch2 + 255;
3232                                         register uint8 *q = GFX.Screen + y * GFX.Pitch2 + 510;
3233                                         for (register int x = 255; x >= 0; x--, p--, q -= 2)
3234                                                 *q = *(q + 1) = *p;
3235                                 }
3236                         }
3237                         IPPU.DoubleWidthPixels = TRUE;
3238                 }
3239         // BJ: And we have to change the height if Interlace gets set,
3240         //     too.
3241                 if (IPPU.Interlace && !IPPU.DoubleHeightPixels)
3242                 {
3243                         starty = GFX.StartY * 2;
3244                         endy = GFX.EndY * 2 + 1;
3245             IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1;
3246             IPPU.DoubleHeightPixels = TRUE;
3247             GFX.Pitch2 = GFX.RealPitch;
3248             GFX.Pitch = GFX.RealPitch * 2;
3249             if (Settings.SixteenBit)
3250                 GFX.PPL = GFX.PPLx2 = GFX.RealPitch;
3251             else
3252                 GFX.PPL = GFX.PPLx2 = GFX.RealPitch << 1;
3253                         
3254             // The game has switched from non-interlaced to interlaced mode
3255             // part way down the screen. Scale everything.
3256             for (register int32 y = (int32) GFX.StartY - 1; y >= 0; y--)
3257                         {
3258                                 memmove (GFX.Screen + y * 2 * GFX.Pitch2,
3259                                         GFX.Screen + y * GFX.Pitch2,
3260                                         GFX.Pitch2);
3261                                 memmove (GFX.Screen + (y * 2 + 1) * GFX.Pitch2,
3262                                         GFX.Screen + y * GFX.Pitch2,
3263                                         GFX.Pitch2);
3264                         }
3265                 }
3266                 
3267     }*/
3268         
3269     uint32 black = BLACK | (BLACK << 16);
3270         
3271     if (Settings.Transparency && Settings.SixteenBit)
3272     {
3273                 if (GFX.Pseudo)
3274                 {
3275                         GFX.r2131 = 0x5f;
3276             GFX.r212c &= (Memory.FillRAM [0x212d] | 0xf0);
3277             GFX.r212d |= (Memory.FillRAM [0x212c] & 0x0f);
3278                         GFX.r2130 |= 2;
3279                 }
3280                 
3281                 if (!PPU.ForcedBlanking && ADD_OR_SUB_ON_ANYTHING &&
3282                         (GFX.r2130 & 0x30) != 0x30 &&
3283                         !((GFX.r2130 & 0x30) == 0x10 && IPPU.Clip[1].Count[5] == 0))
3284                 {
3285                         struct ClipData *pClip;
3286                         
3287                         GFX.FixedColour = BUILD_PIXEL (IPPU.XB [PPU.FixedColourRed],
3288                                 IPPU.XB [PPU.FixedColourGreen],
3289                                 IPPU.XB [PPU.FixedColourBlue]);
3290                         
3291                         // Clear the z-buffer, marking areas 'covered' by the fixed
3292                         // colour as depth 1.
3293                         pClip = &IPPU.Clip [1];
3294                         
3295                         // Clear the z-buffer
3296                         if (pClip->Count [5])
3297                         {
3298                                 // Colour window enabled.
3299                                 for (uint32 y = starty; y <= endy; y++)
3300                                 {
3301                                         ZeroMemory (GFX.SubZBuffer + y * GFX.ZPitch,
3302                                                 IPPU.RenderedScreenWidth);
3303                                         ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch,
3304                                                 IPPU.RenderedScreenWidth);
3305                                         if (IPPU.Clip [0].Count [5])
3306                                         {
3307                                                 uint32 *p = (uint32 *) (GFX.SubScreen + y * GFX.Pitch2);
3308                                                 uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth);
3309                                                 while (p < q)
3310                                                         *p++ = black;
3311                                         }
3312                                         for (uint32 c = 0; c < pClip->Count [5]; c++)
3313                                         {
3314                                                 if (pClip->Right [c][5] > pClip->Left [c][5])
3315                                                 {
3316                                                         memset (GFX.SubZBuffer + y * GFX.ZPitch + pClip->Left [c][5] * x2,
3317                                                                 1, (pClip->Right [c][5] - pClip->Left [c][5]) * x2);
3318                                                         if (IPPU.Clip [0].Count [5])
3319                                                         {
3320                                                                 // Blast, have to clear the sub-screen to the fixed-colour
3321                                                                 // because there is a colour window in effect clipping
3322                                                                 // the main screen that will allow the sub-screen
3323                                                                 // 'underneath' to show through.
3324                                                                 
3325                                                                 uint16 *p = (uint16 *) (GFX.SubScreen + y * GFX.Pitch2);
3326                                                                 uint16 *q = p + pClip->Right [c][5] * x2;
3327                                                                 p += pClip->Left [c][5] * x2;
3328                                                                 
3329                                                                 while (p < q)
3330                                                                         *p++ = (uint16) GFX.FixedColour;
3331                                                         }
3332                                                 }
3333                                         }
3334                                 }
3335                         }
3336                         else
3337                         {
3338                                 for (uint32 y = starty; y <= endy; y++)
3339                                 {
3340                                         ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch,
3341                                                 IPPU.RenderedScreenWidth);
3342                                         memset (GFX.SubZBuffer + y * GFX.ZPitch, 1,
3343                                                 IPPU.RenderedScreenWidth);
3344                                         
3345                                         if (IPPU.Clip [0].Count [5])
3346                                         {
3347                                                 // Blast, have to clear the sub-screen to the fixed-colour
3348                                                 // because there is a colour window in effect clipping
3349                                                 // the main screen that will allow the sub-screen
3350                                                 // 'underneath' to show through.
3351                                                 
3352                                                 uint32 b = GFX.FixedColour | (GFX.FixedColour << 16);
3353                                                 uint32 *p = (uint32 *) (GFX.SubScreen + y * GFX.Pitch2);
3354                                                 uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth);
3355                                                 
3356                                                 while (p < q)
3357                                                         *p++ = b;
3358                                         }
3359                                 }
3360                         }
3361                         if (ANYTHING_ON_SUB)
3362                         {
3363                                 GFX.DB = GFX.SubZBuffer;
3364                                 RenderScreen (GFX.SubScreen, TRUE, TRUE, SUB_SCREEN_DEPTH);
3365                         }
3366                         
3367                         if (IPPU.Clip [0].Count [5])
3368                         {
3369                                 for (uint32 y = starty; y <= endy; y++)
3370                                 {
3371                                         register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2);
3372                                         register uint8 *d = GFX.SubZBuffer + y * GFX.ZPitch;
3373                                         register uint8 *e = d + IPPU.RenderedScreenWidth;
3374                                         
3375                                         while (d < e)
3376                                         {
3377                                                 if (*d > 1)
3378                                                         *p = *(p + GFX.Delta);
3379                                                 else
3380                                                         *p = BLACK;
3381                                                 d++;
3382                                                 p++;
3383                                         }
3384                                 }
3385                         }
3386                         
3387                         GFX.DB = GFX.ZBuffer;
3388                         RenderScreen (GFX.Screen, FALSE, FALSE, MAIN_SCREEN_DEPTH);
3389                         
3390                         if (SUB_OR_ADD(5))
3391                         {
3392                                 uint32 back = IPPU.ScreenColors [0];
3393                                 uint32 Left = 0;
3394                                 uint32 Right = 256;
3395                                 uint32 Count;
3396                                 
3397                                 pClip = &IPPU.Clip [0];
3398                                 for (uint32 y = starty; y <= endy; y++)
3399                                 {
3400                                         if (!(Count = pClip->Count [5]))
3401                                         {
3402                                                 Left = 0;
3403                                                 Right = 256 * x2;
3404                                                 Count = 1;
3405                                         }
3406                                         
3407                                         for (uint32 b = 0; b < Count; b++)
3408                                         {
3409                                                 if (pClip->Count [5])
3410                                                 {
3411                                                         Left = pClip->Left [b][5] * x2;
3412                                                         Right = pClip->Right [b][5] * x2;
3413                                                         if (Right <= Left)
3414                                                                 continue;
3415                                                 }
3416                                                 
3417                                                 if (GFX.r2131 & 0x80)
3418                                                 {
3419                                                         if (GFX.r2131 & 0x40)
3420                                                         {
3421                                                                 // Subtract, halving the result.
3422                                                                 register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
3423                                                                 register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
3424                                                                 register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left;
3425                                                                 register uint8 *e = d + Right;
3426                                                                 uint16 back_fixed = COLOR_SUB (back, GFX.FixedColour);
3427                                                                 
3428                                                                 d += Left;
3429                                                                 while (d < e)
3430                                                                 {
3431                                                                         if (*d == 0)
3432                                                                         {
3433                                                                                 if (*s)
3434                                                                                 {
3435                                                                                         if (*s != 1)
3436                                                                                                 *p = COLOR_SUB1_2 (back, *(p + GFX.Delta));
3437                                                                                         else
3438                                                                                                 *p = back_fixed;
3439                                                                                 }
3440                                                                                 else
3441                                                                                         *p = (uint16) back;
3442                                                                         }
3443                                                                         d++;
3444                                                                         p++;
3445                                                                         s++;
3446                                                                 }
3447                                                         }
3448                                                         else
3449                                                         {
3450                                                                 // Subtract
3451                                                                 register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
3452                                                                 register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left;
3453                                                                 register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
3454                                                                 register uint8 *e = d + Right;
3455                                                                 uint16 back_fixed = COLOR_SUB (back, GFX.FixedColour);
3456                                                                 
3457                                                                 d += Left;
3458                                                                 while (d < e)
3459                                                                 {
3460                                                                         if (*d == 0)
3461                                                                         {
3462                                                                                 if (*s)
3463                                                                                 {
3464                                                                                         if (*s != 1)
3465                                                                                                 *p = COLOR_SUB (back, *(p + GFX.Delta));
3466                                                                                         else
3467                                                                                                 *p = back_fixed;
3468                                                                                 }
3469                                                                                 else
3470                                                                                         *p = (uint16) back;
3471                                                                         }
3472                                                                         d++;
3473                                                                         p++;
3474                                                                         s++;
3475                                                                 }
3476                                                         }
3477                                                 }
3478                                                 else
3479                                                         if (GFX.r2131 & 0x40)
3480                                                         {
3481                                                                 register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
3482                                                                 register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
3483                                                                 register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left;
3484                                                                 register uint8 *e = d + Right;
3485                                                                 uint16 back_fixed = COLOR_ADD (back, GFX.FixedColour);
3486                                                                 d += Left;
3487                                                                 while (d < e)
3488                                                                 {
3489                                                                         if (*d == 0)
3490                                                                         {
3491                                                                                 if (*s)
3492                                                                                 {
3493                                                                                         if (*s != 1)
3494                                                                                                 *p = COLOR_ADD1_2 (back, *(p + GFX.Delta));
3495                                                                                         else
3496                                                                                                 *p = back_fixed;
3497                                                                                 }
3498                                                                                 else
3499                                                                                         *p = (uint16) back;
3500                                                                         }
3501                                                                         d++;
3502                                                                         p++;
3503                                                                         s++;
3504                                                                 }
3505                                                         }
3506                                                         else
3507                                                                 if (back != 0)
3508                                                                 {
3509                                                                         register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
3510                                                                         register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
3511                                                                         register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left;
3512                                                                         register uint8 *e = d + Right;
3513                                                                         uint16 back_fixed = COLOR_ADD (back, GFX.FixedColour);
3514                                                                         d += Left;
3515                                                                         while (d < e)
3516                                                                         {
3517                                                                                 if (*d == 0)
3518                                                                                 {
3519                                                                                         if (*s)
3520                                                                                         {
3521                                                                                                 if (*s != 1)
3522                                                                                                         *p = COLOR_ADD (back, *(p + GFX.Delta));
3523                                                                                                 else    
3524                                                                                                         *p = back_fixed;
3525                                                                                         }
3526                                                                                         else
3527                                                                                                 *p = (uint16) back;
3528                                                                                 }
3529                                                                                 d++;
3530                                                                                 p++;
3531                                                                                 s++;
3532                                                                         }
3533                                                                 }
3534                                                                 else
3535                                                                 {
3536                                                                         if (!pClip->Count [5])
3537                                                                         {
3538                                                                                 // The backdrop has not been cleared yet - so
3539                                                                                 // copy the sub-screen to the main screen
3540                                                                                 // or fill it with the back-drop colour if the
3541                                                                                 // sub-screen is clear.
3542                                                                                 register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
3543                                                                                 register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
3544                                                                                 register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left;
3545                                                                                 register uint8 *e = d + Right;
3546                                                                                 d += Left;
3547                                                                                 while (d < e)
3548                                                                                 {
3549                                                                                         if (*d == 0)
3550                                                                                         {
3551                                                                                                 if (*s)
3552                                                                                                 {
3553                                                                                                         if (*s != 1)
3554                                                                                                                 *p = *(p + GFX.Delta);
3555                                                                                                         else    
3556                                                                                                                 *p = GFX.FixedColour;
3557                                                                                                 }
3558                                                                                                 else
3559                                                                                                         *p = (uint16) back;
3560                                                                                         }
3561                                                                                         d++;
3562                                                                                         p++;
3563                                                                                         s++;
3564                                                                                 }
3565                                                                         }
3566                                                                 }
3567                         }
3568                 }
3569                 }
3570                 else
3571                 {
3572                         // Subscreen not being added to back
3573                         uint32 back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16);
3574                         pClip = &IPPU.Clip [0];
3575                         
3576                         if (pClip->Count [5])
3577                         {
3578                                 for (uint32 y = starty; y <= endy; y++)
3579                                 {
3580                                         for (uint32 b = 0; b < pClip->Count [5]; b++)
3581                                         {
3582                                                 uint32 Left = pClip->Left [b][5] * x2;
3583                                                 uint32 Right = pClip->Right [b][5] * x2;
3584                                                 uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
3585                                                 uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
3586                                                 uint8 *e = d + Right;
3587                                                 d += Left;
3588                                                 
3589                                                 while (d < e)
3590                                                 {
3591                                                         if (*d == 0)
3592                                                                 *p = (int16) back;
3593                                                         d++;
3594                                                         p++;
3595                                                 }
3596                                         }
3597                                 }
3598                         }
3599                         else
3600                         {
3601                                 for (uint32 y = starty; y <= endy; y++)
3602                                 {
3603                                         uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2);
3604                                         uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
3605                                         uint8 *e = d + 256 * x2;
3606                                         
3607                                         while (d < e)
3608                                         {
3609                                                 if (*d == 0)
3610                                                         *p = (int16) back;
3611                                                 d++;
3612                                                 p++;
3613                                         }
3614                                 }
3615                         }
3616                 }
3617         }
3618         else
3619         {
3620                 // 16bit and transparency but currently no transparency effects in
3621                 // operation.
3622                 
3623                 uint32 back = IPPU.ScreenColors [0] | 
3624                         (IPPU.ScreenColors [0] << 16);
3625                 
3626                 if (PPU.ForcedBlanking)
3627                         back = black;
3628                 
3629                 if (IPPU.Clip [0].Count[5])
3630                 {
3631                         for (uint32 y = starty; y <= endy; y++)
3632                         {
3633                                 uint32 *p = (uint32 *) (GFX.Screen + y * GFX.Pitch2);
3634                                 uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth);
3635                                 
3636                                 while (p < q)
3637                                         *p++ = black;
3638                                 
3639                                 for (uint32 c = 0; c < IPPU.Clip [0].Count [5]; c++)
3640                                 {
3641                                         if (IPPU.Clip [0].Right [c][5] > IPPU.Clip [0].Left [c][5])
3642                                         {
3643                                                 uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2);
3644                                                 uint16 *q = p + IPPU.Clip [0].Right [c][5] * x2;
3645                                                 p += IPPU.Clip [0].Left [c][5] * x2;
3646                                                 
3647                                                 while (p < q)
3648                                                         *p++ = (uint16) back;
3649                                         }
3650                                 }
3651                         }
3652                 }
3653                 else
3654                 {
3655                         for (uint32 y = starty; y <= endy; y++)
3656                         {
3657                                 uint32 *p = (uint32 *) (GFX.Screen + y * GFX.Pitch2);
3658                                 uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth);
3659                                 while (p < q)
3660                                         *p++ = back;
3661                         }
3662                 }
3663                 if (!PPU.ForcedBlanking)
3664                 {
3665                         for (uint32 y = starty; y <= endy; y++)
3666                         {
3667                                 ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch,
3668                                         IPPU.RenderedScreenWidth);
3669                         }
3670                         GFX.DB = GFX.ZBuffer;
3671                         RenderScreen (GFX.Screen, FALSE, TRUE, SUB_SCREEN_DEPTH);
3672                 }
3673         }
3674     }
3675     else
3676     {
3677                 if (Settings.SixteenBit)
3678                 {
3679                         uint32 back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16);
3680                         if (PPU.ForcedBlanking)
3681                                 back = black;
3682                         else
3683                                 orgSelectTileRenderer (TRUE);
3684                         
3685                         for (uint32 y = starty; y <= endy; y++)
3686                         {
3687                                 uint32 *p = (uint32 *) (GFX.Screen + y * GFX.Pitch2);
3688                                 uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth);
3689                                 while (p < q)
3690                                         *p++ = back;
3691                         }
3692                 }
3693                 else
3694                 {
3695                         for (uint32 y = starty; y <= endy; y++)
3696                         {
3697                                 ZeroMemory (GFX.Screen + y * GFX.Pitch2,
3698                                         IPPU.RenderedScreenWidth);
3699                         }
3700                 }
3701                 if (!PPU.ForcedBlanking)
3702                 {
3703                         for (uint32 y = starty; y <= endy; y++)
3704                         {
3705                                 ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch,
3706                                         IPPU.RenderedScreenWidth);
3707                         }
3708                         GFX.DB = GFX.ZBuffer;
3709                         GFX.pCurrentClip = &IPPU.Clip [0];
3710                         
3711 #define FIXCLIP(n)\
3712         if (GFX.r212c & (1 << (n))) \
3713     GFX.pCurrentClip = &IPPU.Clip [0]; \
3714         else \
3715                         GFX.pCurrentClip = &IPPU.Clip [1]
3716                         
3717                         
3718 #define DISPLAY(n)\
3719     (!(PPU.BG_Forced & n) && \
3720         (GFX.r212c & n) || \
3721                         ((GFX.r212d & n) && subadd))
3722                         
3723                         uint8 subadd = GFX.r2131 & 0x3f;
3724                         
3725                         bool8 BG0 = DISPLAY(1);
3726                         bool8 BG1 = DISPLAY(2);
3727                         bool8 BG2 = DISPLAY(4);
3728                         bool8 BG3 = DISPLAY(8);
3729                         bool8 OB  = DISPLAY(16);
3730                         
3731                         if (PPU.BGMode <= 1)
3732                         {
3733                                 if (OB)
3734                                 {
3735                                         FIXCLIP(4);
3736                                         orgDrawOBJS ();
3737                                 }
3738                                 if (BG0)
3739                                 {
3740                                         FIXCLIP(0);
3741                                         orgDrawBackground (PPU.BGMode, 0, 10, 14);
3742                                 }
3743                                 if (BG1)
3744                                 {
3745                                         FIXCLIP(1);
3746                                         orgDrawBackground (PPU.BGMode, 1, 9, 13);
3747                                 }
3748                                 if (BG2)
3749                                 {
3750                                         FIXCLIP(2);
3751                                         orgDrawBackground (PPU.BGMode, 2, 3,
3752                                                 PPU.BG3Priority ? 17 : 6);
3753                                 }
3754                                 if (BG3 && PPU.BGMode == 0)
3755                                 {
3756                                         FIXCLIP(3);
3757                                         orgDrawBackground (PPU.BGMode, 3, 2, 5);
3758                                 }
3759                         }
3760                         else if (PPU.BGMode != 7)
3761                         {
3762                                 if (OB)
3763                                 {
3764                                         FIXCLIP(4);
3765                                         orgDrawOBJS ();
3766                                 }
3767                                 if (BG0)
3768                                 {
3769                                         FIXCLIP(0);
3770                                         orgDrawBackground (PPU.BGMode, 0, 5, 13);
3771                                 }
3772                                 if (BG1 && PPU.BGMode != 6)
3773                                 {
3774                                         FIXCLIP(1);
3775                                         orgDrawBackground (PPU.BGMode, 1, 2, 9);
3776                                 }
3777                         }
3778                         else
3779                         {
3780                                 if (OB)
3781                                 {
3782                                         FIXCLIP(4);
3783                                         orgDrawOBJS ();
3784                                 }
3785                                 if (BG0 || ((Memory.FillRAM [0x2133] & 0x40) && BG1))
3786                                 {
3787                                         int bg;
3788                                         FIXCLIP(0);
3789                                         if ((Memory.FillRAM [0x2133] & 0x40) && BG1)
3790                                         {
3791                                                 GFX.Mode7Mask = 0x7f;
3792                                                 GFX.Mode7PriorityMask = 0x80;
3793                                                 Mode7Depths [0] = (BG0?5:1);
3794                                                 Mode7Depths [1] = 9;
3795                                                 bg = 1;
3796                                         }
3797                                         else
3798                                         {
3799                                                 GFX.Mode7Mask = 0xff;
3800                                                 GFX.Mode7PriorityMask = 0;
3801                                                 Mode7Depths [0] = 5;
3802                                                 Mode7Depths [1] = 5;
3803                                                 bg = 0;
3804                                         }
3805                                         
3806                                         if (!Settings.SixteenBit)
3807                                                 orgDrawBGMode7Background16 (GFX.Screen, bg);
3808                                         else
3809                                         {
3810                                                 //if (!Settings.Mode7Interpolate)
3811                                                         orgDrawBGMode7Background16 (GFX.Screen, bg);
3812                                                 //else
3813                                                 //      DrawBGMode7Background16_i (GFX.Screen, bg);
3814                                         }
3815                                 }
3816                         }
3817         }
3818     }
3819     if (Settings.SupportHiRes)
3820     {
3821                 if (PPU.BGMode != 5 && PPU.BGMode != 6 && IPPU.DoubleWidthPixels)
3822                 {
3823                         // Mixure of background modes used on screen - scale width
3824                         // of all non-mode 5 and 6 pixels.
3825                         if (Settings.SixteenBit)
3826                         {
3827                                 for (register uint32 y = starty; y <= endy; y++)
3828                                 {
3829                                         register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + 255;
3830                                         register uint16 *q = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + 510;
3831                                         for (register int x = 255; x >= 0; x--, p--, q -= 2)
3832                                                 *q = *(q + 1) = *p;
3833                                 }
3834                         }
3835                         else
3836                         {
3837                                 for (register uint32 y = starty; y <= endy; y++)
3838                                 {
3839                                         register uint8 *p = GFX.Screen + y * GFX.Pitch2 + 255;
3840                                         register uint8 *q = GFX.Screen + y * GFX.Pitch2 + 510;
3841                                         for (register int x = 255; x >= 0; x--, p--, q -= 2)
3842                                                 *q = *(q + 1) = *p;
3843                                 }
3844                         }
3845                 }
3846                 
3847         // Double the height of the pixels just drawn
3848                 //FIX_INTERLACE(GFX.Screen, FALSE, GFX.ZBuffer);
3849                 
3850     }
3851     IPPU.PreviousLine = IPPU.CurrentLine;
3852 }
3853
3854
3855
3856
3857