2 * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
4 * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
5 * Jerremy Koot (jkoot@snes9x.com)
7 * Super FX C emulator code
8 * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
10 * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
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).
16 * DOS port code contains the works of other authors. See headers in
19 * Snes9x homepage: http://www.snes9x.com
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.
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.
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.
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
38 * Super NES and Super Nintendo Entertainment System are trademarks of
39 * Nintendo Co., Limited and its subsidiary companies.
54 extern uint32 gp32_gammavalue;
56 void ComputeClipWindows ();
58 extern void S9xSetupOBJ(void);
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];
67 extern NormalTileRenderer DrawTilePtr;
68 extern ClippedTileRenderer DrawClippedTilePtr;
69 extern NormalTileRenderer DrawHiResTilePtr;
70 extern ClippedTileRenderer DrawHiResClippedTilePtr;
71 extern LargePixelRenderer DrawLargePixelPtr;
75 extern struct SLineData LineData[240];
76 extern struct SLineMatrixData LineMatrixData [240];
78 extern uint8 Mode7Depths [2];
79 extern unsigned char gammatab[10][32];
81 (GFX.r212c & (1 << (N)) && \
82 !(PPU.BG_Forced & (1 << (N))))
84 #define SUB_OR_ADD(N) \
85 (GFX.r2131 & (1 << (N)))
88 ((GFX.r2130 & 0x30) != 0x30 && \
90 (GFX.r212d & (1 << N)) && \
91 !(PPU.BG_Forced & (1 << (N))))
93 #define ANYTHING_ON_SUB \
94 ((GFX.r2130 & 0x30) != 0x30 && \
98 #define ADD_OR_SUB_ON_ANYTHING \
101 #define BLACK BUILD_PIXEL(0,0,0)
103 void orgDrawTileHi16 (uint32 Tile, uint32 Offset, uint32 StartLine,
105 void orgDrawClippedTileHi16 (uint32 Tile, uint32 Offset,
106 uint32 StartPixel, uint32 Width,
107 uint32 StartLine, uint32 LineCount);
109 void orgDrawTile16 (uint32 Tile, uint32 Offset, uint32 StartLine,
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,
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,
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);
128 void orgDrawTile16Add (uint32 Tile, uint32 Offset, uint32 StartLine,
131 void orgDrawClippedTile16Add (uint32 Tile, uint32 Offset,
132 uint32 StartPixel, uint32 Width,
133 uint32 StartLine, uint32 LineCount);
135 void orgDrawTile16Add1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
138 void orgDrawClippedTile16Add1_2 (uint32 Tile, uint32 Offset,
139 uint32 StartPixel, uint32 Width,
140 uint32 StartLine, uint32 LineCount);
142 void orgDrawTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
145 void orgDrawClippedTile16FixedAdd1_2 (uint32 Tile, uint32 Offset,
146 uint32 StartPixel, uint32 Width,
147 uint32 StartLine, uint32 LineCount);
149 void orgDrawTile16Sub (uint32 Tile, uint32 Offset, uint32 StartLine,
152 void orgDrawClippedTile16Sub (uint32 Tile, uint32 Offset,
153 uint32 StartPixel, uint32 Width,
154 uint32 StartLine, uint32 LineCount);
156 void orgDrawTile16Sub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
159 void orgDrawClippedTile16Sub1_2 (uint32 Tile, uint32 Offset,
160 uint32 StartPixel, uint32 Width,
161 uint32 StartLine, uint32 LineCount);
163 void orgDrawTile16FixedSub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
166 void orgDrawClippedTile16FixedSub1_2 (uint32 Tile, uint32 Offset,
167 uint32 StartPixel, uint32 Width,
168 uint32 StartLine, uint32 LineCount);
170 void orgDrawLargePixel16Add (uint32 Tile, uint32 Offset,
171 uint32 StartPixel, uint32 Pixels,
172 uint32 StartLine, uint32 LineCount);
174 void orgDrawLargePixel16Add1_2 (uint32 Tile, uint32 Offset,
175 uint32 StartPixel, uint32 Pixels,
176 uint32 StartLine, uint32 LineCount);
178 void orgDrawLargePixel16Sub (uint32 Tile, uint32 Offset,
179 uint32 StartPixel, uint32 Pixels,
180 uint32 StartLine, uint32 LineCount);
182 void orgDrawLargePixel16Sub1_2 (uint32 Tile, uint32 Offset,
183 uint32 StartPixel, uint32 Pixels,
184 uint32 StartLine, uint32 LineCount);
187 bool8 S9xGraphicsInit ()
189 register uint32 PixelOdd = 1;
190 register uint32 PixelEven = 2;
192 #ifdef GFX_MULTI_FORMAT
193 if (GFX.BuildPixel == NULL)
194 S9xSetRenderPixelFormat (RGB565);
197 for (uint8 bitshift = 0; bitshift < 4; bitshift++)
199 for (register char i = 0; i < 16; i++)
201 register uint32 h = 0;
202 register uint32 l = 0;
204 #if defined(LSB_FIRST)
223 h |= (PixelOdd << 24);
225 h |= (PixelOdd << 16);
227 h |= (PixelOdd << 8);
231 l |= (PixelOdd << 24);
233 l |= (PixelOdd << 16);
235 l |= (PixelOdd << 8);
240 odd_high[bitshift][i] = h;
241 odd_low[bitshift][i] = l;
244 #if defined(LSB_FIRST)
250 h |= PixelEven << 16;
252 h |= PixelEven << 24;
258 l |= PixelEven << 16;
260 l |= PixelEven << 24;
263 h |= (PixelEven << 24);
265 h |= (PixelEven << 16);
267 h |= (PixelEven << 8);
271 l |= (PixelEven << 24);
273 l |= (PixelEven << 16);
275 l |= (PixelEven << 8);
280 even_high[bitshift][i] = h;
281 even_low[bitshift][i] = l;
287 GFX.RealPitch = GFX.Pitch2 = GFX.Pitch;
288 GFX.ZPitch = GFX.Pitch;
289 if (Settings.SixteenBit)
291 GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1;
292 GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer;
293 //GFX.InfoStringTimeout = 0;
294 //GFX.InfoString = NULL;
297 IPPU.OBJChanged = TRUE;
298 if (Settings.Transparency)
299 Settings.SixteenBit = TRUE;
301 IPPU.DirectColourMapsNeedRebuild = TRUE;
303 if (Settings.SixteenBit)
305 GFX.PPL = GFX.Pitch >> 1;
306 GFX.PPLx2 = GFX.Pitch;
311 GFX.PPLx2 = GFX.Pitch * 2;
313 S9xFixColourBrightness ();
315 #ifdef _TRANSP_SUPPORT_
316 if (!(GFX.X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000)))
319 if ((!(GFX.ZERO_OR_X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000)))
320 ||!(GFX.ZERO = (uint16 *) malloc (sizeof (uint16) * 0x10000)))
324 free ((char *) GFX.ZERO_OR_X2);
325 GFX.ZERO_OR_X2 = NULL;
329 free ((char *) GFX.X2);
336 // Build a lookup table that multiplies a packed RGB value by 2 with
338 for (r = 0; r <= MAX_RED; r++)
343 for (g = 0; g <= MAX_GREEN; g++)
348 for (b = 0; b <= MAX_BLUE; b++)
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);
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.
364 #if defined(OLD_COLOUR_BLENDING)
365 for (r = 0; r <= MAX_RED; r++)
368 if ((r2 & 0x10) == 0)
371 r2 = (r2 << 1) & MAX_RED;
373 for (g = 0; g <= MAX_GREEN; g++)
376 if ((g2 & GREEN_HI_BIT) == 0)
379 g2 = (g2 << 1) & MAX_GREEN;
381 for (b = 0; b <= MAX_BLUE; b++)
384 if ((b2 & 0x10) == 0)
387 b2 = (b2 << 1) & MAX_BLUE;
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);
395 for (r = 0; r <= MAX_RED; r++)
398 if ((r2 & 0x10) == 0)
401 r2 = (r2 << 1) & MAX_RED;
405 for (g = 0; g <= MAX_GREEN; g++)
408 if ((g2 & GREEN_HI_BIT) == 0)
411 g2 = (g2 << 1) & MAX_GREEN;
415 for (b = 0; b <= MAX_BLUE; b++)
418 if ((b2 & 0x10) == 0)
421 b2 = (b2 << 1) & MAX_BLUE;
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);
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++)
437 if ((r2 & 0x10) == 0)
442 for (g = 0; g <= MAX_GREEN; g++)
445 if ((g2 & GREEN_HI_BIT) == 0)
449 for (b = 0; b <= MAX_BLUE; b++)
452 if ((b2 & 0x10) == 0)
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);
466 GFX.ZERO_OR_X2 = NULL;
473 void S9xGraphicsDeinit (void)
475 // Free any memory allocated in S9xGraphicsInit
483 free (GFX.ZERO_OR_X2);
484 GFX.ZERO_OR_X2 = NULL;
494 void S9xBuildDirectColourMaps ()
496 uint8 *cgamma=(uint8*)gammatab[gp32_gammavalue];
497 for (uint32 p = 0; p < 8; p++)
499 for (uint32 c = 0; c < 256; c++)
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)]);
507 IPPU.DirectColourMapsNeedRebuild = FALSE;
510 void S9xStartScreenRefresh ()
512 if (GFX.InfoStringTimeout > 0 && --GFX.InfoStringTimeout == 0)
513 GFX.InfoString = NULL;
515 if (IPPU.RenderThisFrame)
517 if (!S9xInitUpdate ())
519 IPPU.RenderThisFrame = FALSE;
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*/))
531 if (PPU.BGMode == 5 || PPU.BGMode == 6)
533 IPPU.RenderedScreenWidth = 512;
534 IPPU.DoubleWidthPixels = TRUE;
536 if (/*IPPU.Interlace*/IPPU.LatchedInterlace)
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;
544 GFX.PPL = GFX.PPLx2 = GFX.RealPitch << 1;
548 IPPU.RenderedScreenHeight = PPU.ScreenHeight;
549 GFX.Pitch2 = GFX.Pitch = GFX.RealPitch;
550 if (Settings.SixteenBit)
551 GFX.PPL = GFX.Pitch >> 1;
554 GFX.PPLx2 = GFX.PPL << 1;
556 #if defined(USE_GLIDE) || defined(USE_OPENGL)
557 GFX.ZPitch = GFX.RealPitch;
558 if (Settings.SixteenBit)
564 IPPU.RenderedScreenWidth = 256;
565 IPPU.RenderedScreenHeight = PPU.ScreenHeight;
566 IPPU.DoubleWidthPixels = FALSE;
568 GFX.Pitch2 = GFX.Pitch = GFX.RealPitch;
569 GFX.PPL = GFX.PPLx2 >> 1;
570 GFX.ZPitch = GFX.RealPitch;
571 if (Settings.SixteenBit)
575 PPU.RecomputeClipWindows = TRUE;
576 GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer;
577 GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1;
579 if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0)
581 IPPU.DisplayedRenderedFrameCount = IPPU.RenderedFramesCount;
582 IPPU.RenderedFramesCount = 0;
588 void RenderLine (uint8 C)
590 if (IPPU.RenderThisFrame)
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;
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;
609 if (Settings.StarfoxHack && PPU.BG[2].VOffset == 0 &&
610 PPU.BG[2].HOffset == 0xe000)
612 LineData[C].BG[2].VOffset = 0xe1;
613 LineData[C].BG[2].HOffset = 0;
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;
623 IPPU.CurrentLine = C + 1;
627 void S9xEndScreenRefresh ()
629 IPPU.HDMAStarted = FALSE;
630 if (IPPU.RenderThisFrame)
633 if (IPPU.ColorsChanged)
635 uint32 saved = PPU.CGDATA[0];
636 if (!Settings.SixteenBit)
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))
645 PPU.CGDATA[0] = PPU.FixedColourRed |
646 (PPU.FixedColourGreen << 5) |
647 (PPU.FixedColourBlue << 10);
650 IPPU.ColorsChanged = FALSE;
652 PPU.CGDATA[0] = saved;
654 GFX.Pitch = GFX.Pitch2 = GFX.RealPitch;
655 GFX.PPL = GFX.PPLx2 >> 1;
658 /* if (Settings.DisplayFrameRate)
659 S9xDisplayFrameRate ();
661 S9xDisplayString (GFX.InfoString);*/
663 S9xDeinitUpdate (IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight,
664 Settings.SixteenBit);
666 // S9xApplyCheats ();
668 if (CPU.Flags & FRAME_ADVANCE_FLAG)
670 if (ICPU.FrameAdvanceCount)
672 ICPU.FrameAdvanceCount--;
673 IPPU.RenderThisFrame = TRUE;
678 CPU.Flags &= ~FRAME_ADVANCE_FLAG;
679 CPU.Flags |= DEBUG_MODE_FLAG;
683 if (CPU.SRAMModified)
685 if (!CPU.AutoSaveTimer)
687 if (!(CPU.AutoSaveTimer = Settings.AutoSaveDelay * Memory.ROMFramesPerSecond))
688 CPU.SRAMModified = FALSE;
692 if (!--CPU.AutoSaveTimer)
695 CPU.SRAMModified = FALSE;
701 void S9xSetInfoString (const char *string)
703 GFX.InfoString = string;
704 GFX.InfoStringTimeout = 120;
715 switch (PPU.OBJSizeSelect)
746 int FirstSprite = PPU.FirstSprite & 0x7f;
751 if (PPU.OBJ [S].Size)
756 long VPos = PPU.OBJ [S].VPos;
758 if (VPos >= PPU.ScreenHeight)
760 if (PPU.OBJ [S].HPos < 256 && PPU.OBJ [S].HPos > -Size &&
761 VPos < PPU.ScreenHeight && VPos > -Size)
763 GFX.OBJList [C++] = S;
765 GFX.VPositions[S] = VPos;
768 } while (S != FirstSprite);
770 // Terminate the list
771 GFX.OBJList [C] = -1;
772 IPPU.OBJChanged = FALSE;
778 inline void orgSelectTileRenderer (bool8 normal)
780 DrawHiResTilePtr= orgDrawTileHi16;
781 DrawHiResClippedTilePtr = orgDrawClippedTileHi16;
786 DrawTilePtr = orgDrawTile16;
787 DrawClippedTilePtr = orgDrawClippedTile16;
788 DrawLargePixelPtr = orgDrawLargePixel16;
792 if (GFX.r2131 & 0x80)
794 if (GFX.r2131 & 0x40)
798 DrawTilePtr = orgDrawTile16Sub1_2;
799 DrawClippedTilePtr = orgDrawClippedTile16Sub1_2;
803 // Fixed colour substraction
804 DrawTilePtr = orgDrawTile16FixedSub1_2;
805 DrawClippedTilePtr = orgDrawClippedTile16FixedSub1_2;
807 DrawLargePixelPtr = orgDrawLargePixel16Sub1_2;
811 DrawTilePtr = orgDrawTile16Sub;
812 DrawClippedTilePtr = orgDrawClippedTile16Sub;
813 DrawLargePixelPtr = orgDrawLargePixel16Sub;
818 if (GFX.r2131 & 0x40)
822 DrawTilePtr = orgDrawTile16Add1_2;
823 DrawClippedTilePtr = orgDrawClippedTile16Add1_2;
827 // Fixed colour addition
828 DrawTilePtr = orgDrawTile16FixedAdd1_2;
829 DrawClippedTilePtr = orgDrawClippedTile16FixedAdd1_2;
831 DrawLargePixelPtr = orgDrawLargePixel16Add1_2;
835 DrawTilePtr = orgDrawTile16Add;
836 DrawClippedTilePtr = orgDrawClippedTile16Add;
837 DrawLargePixelPtr = orgDrawLargePixel16Add;
843 void orgDrawOBJS (bool8 OnMain = FALSE, uint8 D = 0)
846 uint32 BaseTile, Tile;
852 BG.TileAddress = PPU.OBJNameBase;
853 BG.StartPalette = 128;
856 BG.Buffer = IPPU.TileCache [TILE_4BIT];
857 BG.Buffered = IPPU.TileCached [TILE_4BIT];
858 BG.NameSelect = PPU.OBJNameSelect;
859 BG.DirectColourMode = FALSE;
865 DrawTilePtr = orgDrawTile16;
866 DrawClippedTilePtr = orgDrawClippedTile16;
871 for (int S = GFX.OBJList [I++]; S >= 0; S = GFX.OBJList [I++])
873 int VPos = GFX.VPositions [S];
874 int Size = GFX.Sizes[S];
878 if (VPos + Size <= (int) GFX.StartY || VPos > (int) GFX.EndY)
881 if (OnMain && SUB_OR_ADD(4))
883 orgSelectTileRenderer (!GFX.Pseudo && PPU.OBJ [S].Palette < 4);
886 BaseTile = PPU.OBJ[S].Name | (PPU.OBJ[S].Palette << 10);
888 if (PPU.OBJ[S].HFlip)
890 BaseTile += ((Size >> 3) - 1) | H_FLIP;
893 if (PPU.OBJ[S].VFlip)
896 int clipcount = GFX.pCurrentClip->Count [4];
900 GFX.Z2 = (PPU.OBJ[S].Priority + 1) * 4 + D;
902 for (int clip = 0; clip < clipcount; clip++)
906 if (!GFX.pCurrentClip->Count [4])
913 Left = GFX.pCurrentClip->Left [clip][4];
914 Right = GFX.pCurrentClip->Right [clip][4];
917 if (Right <= Left || PPU.OBJ[S].HPos + Size <= Left ||
918 PPU.OBJ[S].HPos >= Right)
921 for (int Y = 0; Y < Size; Y += 8)
923 if (VPos + Y + 7 >= (int) GFX.StartY && VPos + Y <= (int) GFX.EndY)
930 if ((StartLine = VPos + Y) < (int) GFX.StartY)
932 StartLine = GFX.StartY - StartLine;
933 LineCount = 8 - StartLine;
940 if ((Last = VPos + Y + 7 - GFX.EndY) > 0)
941 if ((LineCount -= Last) <= 0)
944 TileLine = StartLine << 3;
945 O = (VPos + Y + StartLine) * GFX.PPL;
946 if (!PPU.OBJ[S].VFlip)
947 Tile = BaseTile + (Y << 1);
949 Tile = BaseTile + ((Size - Y - 8) << 1);
951 int Middle = Size >> 3;
952 if (PPU.OBJ[S].HPos < Left)
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))
959 O -= Offset * GFX.PixSize;
961 int Width = Right - Left;
964 (*DrawClippedTilePtr) (Tile, O, Offset, W,
965 TileLine, LineCount);
971 O += 8 * GFX.PixSize;
975 O += PPU.OBJ[S].HPos * GFX.PixSize;
977 if (PPU.OBJ[S].HPos + Size >= Right)
979 Middle -= ((PPU.OBJ[S].HPos + Size + 7) -
981 Offset = (Right - (PPU.OBJ[S].HPos + Size)) & 7;
986 for (int X = 0; X < Middle; X++, O += 8 * GFX.PixSize,
989 (*DrawTilePtr) (Tile, O, TileLine, LineCount);
993 (*DrawClippedTilePtr) (Tile, O, 0, Offset,
994 TileLine, LineCount);
1002 void orgDrawBackgroundMosaic (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
1011 uint8 depths [2] = {Z1, Z2};
1014 BG.StartPalette = bg << 5;
1016 BG.StartPalette = 0;
1018 SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
1020 if (PPU.BG[bg].SCSize & 1)
1025 if((SC1-(unsigned short*)Memory.VRAM)>0x10000)
1029 if (PPU.BG[bg].SCSize & 2)
1034 if((SC2-(unsigned short*)Memory.VRAM)>0x10000)
1038 if (PPU.BG[bg].SCSize & 1)
1043 if((SC3-(unsigned short*)Memory.VRAM)>0x10000)
1050 if (BG.TileSize == 16)
1061 for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines)
1063 uint32 VOffset = LineData [Y].BG[bg].VOffset;
1064 uint32 HOffset = LineData [Y].BG[bg].HOffset;
1065 uint32 MosaicOffset = Y % PPU.Mosaic;
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))
1072 uint32 MosaicLine = VOffset + Y - MosaicOffset;
1074 if (Y + Lines > GFX.EndY)
1075 Lines = GFX.EndY + 1 - Y;
1076 uint32 VirtAlign = (MosaicLine & 7) << 3;
1081 uint32 ScreenLine = MosaicLine >> OffsetShift;
1082 uint32 Rem16 = MosaicLine & 15;
1084 if (ScreenLine & 0x20)
1089 b1 += (ScreenLine & 0x1f) << 5;
1090 b2 += (ScreenLine & 0x1f) << 5;
1095 uint32 ClipCount = GFX.pCurrentClip->Count [bg];
1096 uint32 HPos = HOffset;
1097 uint32 PixWidth = PPU.Mosaic;
1102 for (uint32 clip = 0; clip < ClipCount; clip++)
1104 if (GFX.pCurrentClip->Count [bg])
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;
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)
1117 uint32 Quot = (HPos & OffsetMask) >> 3;
1119 if (x + PixWidth >= Right)
1120 PixWidth = Right - x;
1122 if (BG.TileSize == 8)
1125 t = b2 + (Quot & 0x1f);
1132 t = b2 + ((Quot >> 1) & 0x1f);
1134 t = b1 + (Quot >> 1);
1137 Tile = READ_2BYTES (t);
1138 GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
1141 if (BG.TileSize != 8)
1145 // Horizontal flip, but what about vertical flip ?
1148 // Both horzontal & vertical flip
1151 (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s,
1157 (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s,
1164 // Horizontal flip only
1167 (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s,
1173 (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s,
1181 // No horizontal flip, but is there a vertical flip ?
1184 // Vertical flip only
1187 (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s,
1193 (*DrawLargePixelPtr) (Tile + (Quot & 1), s,
1203 (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s,
1209 (*DrawLargePixelPtr) (Tile + (Quot & 1), s,
1217 (*DrawLargePixelPtr) (Tile, s, HPos & 7, PixWidth,
1224 void orgDrawBackgroundOffset (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
1238 int VOffsetOffset = BGMode == 4 ? 0 : 32;
1239 uint8 depths [2] = {Z1, Z2};
1241 BG.StartPalette = 0;
1243 BPS0 = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1];
1245 if (PPU.BG[2].SCSize & 1)
1250 if (PPU.BG[2].SCSize & 2)
1255 if (PPU.BG[2].SCSize & 1)
1260 SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
1262 if (PPU.BG[bg].SCSize & 1)
1267 if((SC1-(unsigned short*)Memory.VRAM)>0x10000)
1271 if (PPU.BG[bg].SCSize & 2)
1276 if((SC2-(unsigned short*)Memory.VRAM)>0x10000)
1280 if (PPU.BG[bg].SCSize & 1)
1285 if((SC3-(unsigned short*)Memory.VRAM)>0x10000)
1289 static const int Lines = 1;
1292 int OffsetEnableMask = 1 << (bg + 13);
1294 if (BG.TileSize == 16)
1305 for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y++)
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;
1312 int ScreenLine = VOff >> 3;
1319 if (ScreenLine & 0x20)
1320 s1 = BPS2, s2 = BPS3;
1322 s1 = BPS0, s2 = BPS1;
1324 s1 += (ScreenLine & 0x1f) << 5;
1325 s2 += (ScreenLine & 0x1f) << 5;
1329 if((ScreenLine & 0x1f) == 0x1f)
1331 if(ScreenLine & 0x20)
1332 VOffsetOffset = BPS0 - BPS2 - 0x1f*32;
1334 VOffsetOffset = BPS2 - BPS0 - 0x1f*32;
1342 int clipcount = GFX.pCurrentClip->Count [bg];
1346 for (int clip = 0; clip < clipcount; clip++)
1351 if (!GFX.pCurrentClip->Count [bg])
1358 Left = GFX.pCurrentClip->Left [clip][bg];
1359 Right = GFX.pCurrentClip->Right [clip][bg];
1368 uint32 LineHOffset=LineData [Y].BG[bg].HOffset;
1380 uint32 TotalCount = 0;
1381 uint32 MaxCount = 8;
1383 uint32 s = Left * GFX.PixSize + Y * GFX.PPL;
1384 bool8 left_hand_edge = (Left == 0);
1385 Width = Right - Left;
1388 MaxCount = 8 - (Left & 7);
1390 while (Left < Right)
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;
1399 //MKendora; use temp var to reduce memory accesses
1400 //HOffset = LineData [Y].BG[bg].HOffset;
1402 HOffset = LineHOffset;
1405 left_hand_edge = FALSE;
1410 // All subsequent offset tile data is shifted left by one,
1411 // hence the - 1 below.
1413 Quot2 = ((HOff + Left - 1) & OffsetMask) >> 3;
1416 s0 = s2 + (Quot2 & 0x1f);
1420 HCellOffset = READ_2BYTES (s0);
1424 VOffset = LineData [Y].BG[bg].VOffset;
1426 //MKendora another mem access hack
1427 //HOffset = LineData [Y].BG[bg].HOffset;
1428 HOffset=LineHOffset;
1431 if ((HCellOffset & OffsetEnableMask))
1433 if (HCellOffset & 0x8000)
1434 VOffset = HCellOffset + 1;
1436 HOffset = HCellOffset;
1441 VCellOffset = READ_2BYTES (s0 + VOffsetOffset);
1442 if ((VCellOffset & OffsetEnableMask))
1443 VOffset = VCellOffset + 1;
1445 VOffset = LineData [Y].BG[bg].VOffset;
1447 //MKendora Strike Gunner fix
1448 if ((HCellOffset & OffsetEnableMask))
1450 //HOffset= HCellOffset;
1452 HOffset = (HCellOffset & ~7)|(LineHOffset&7);
1453 //HOffset |= LineData [Y].BG[bg].HOffset&7;
1456 HOffset=LineHOffset;
1457 //HOffset = LineData [Y].BG[bg].HOffset -
1458 //Settings.StrikeGunnerOffsetHack;
1463 VirtAlign = ((Y + VOffset) & 7) << 3;
1464 ScreenLine = (VOffset + Y) >> OffsetShift;
1466 if (((VOffset + Y) & 15) > 7)
1477 if (ScreenLine & 0x20)
1482 b1 += (ScreenLine & 0x1f) << 5;
1483 b2 += (ScreenLine & 0x1f) << 5;
1485 HPos = (HOffset + Left) & OffsetMask;
1489 if (BG.TileSize == 8)
1492 t = b2 + (Quot & 0x1f);
1499 t = b2 + ((Quot >> 1) & 0x1f);
1501 t = b1 + (Quot >> 1);
1504 if (MaxCount + TotalCount > Width)
1505 MaxCount = Width - TotalCount;
1511 if (Count > MaxCount)
1514 s -= Offset * GFX.PixSize;
1515 Tile = READ_2BYTES(t);
1516 GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
1518 if (BG.TileSize == 8)
1519 (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines);
1522 if (!(Tile & (V_FLIP | H_FLIP)))
1524 // Normal, unflipped
1525 (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1),
1526 s, Offset, Count, VirtAlign, Lines);
1534 (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
1535 s, Offset, Count, VirtAlign, Lines);
1540 (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
1541 s, Offset, Count, VirtAlign, Lines);
1547 (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1),
1548 s, Offset, Count, VirtAlign, Lines);
1553 TotalCount += Count;
1554 s += (Offset + Count) * GFX.PixSize;
1561 void orgDrawBackgroundMode5 (uint32 /* BGMODE */, uint32 bg, uint8 Z1, uint8 Z2)
1565 GFX.Pitch = GFX.RealPitch;
1566 GFX.PPL = GFX.PPLx2 >> 1;
1568 uint8 depths [2] = {Z1, Z2};
1577 BG.StartPalette = 0;
1579 SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
1581 if ((PPU.BG[bg].SCSize & 1))
1586 if((SC1-(unsigned short*)Memory.VRAM)>0x10000)
1587 SC1=(uint16*)&Memory.VRAM[(((uint8*)SC1)-Memory.VRAM)%0x10000];
1589 if ((PPU.BG[bg].SCSize & 2))
1594 if((SC2-(unsigned short*)Memory.VRAM)>0x10000)
1595 SC2=(uint16*)&Memory.VRAM[(((uint8*)SC2)-Memory.VRAM)%0x10000];
1598 if ((PPU.BG[bg].SCSize & 1))
1603 if((SC3-(unsigned short*)Memory.VRAM)>0x10000)
1604 SC3=(uint16*)&Memory.VRAM[(((uint8*)SC3)-Memory.VRAM)%0x10000];
1611 if (BG.TileSize == 16)
1613 VOffsetMask = 0x3ff;
1618 VOffsetMask = 0x1ff;
1621 int endy = GFX.EndY;
1623 for (int Y = GFX.StartY; Y <= endy; Y += Lines)
1626 uint32 VOffset = LineData [y].BG[bg].VOffset;
1627 uint32 HOffset = LineData [y].BG[bg].HOffset;
1628 int VirtAlign = (Y + VOffset) & 7;
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))
1636 if (Y + Lines > endy)
1637 Lines = endy + 1 - Y;
1640 int ScreenLine = (VOffset + Y) >> VOffsetShift;
1643 if (((VOffset + Y) & 15) > 7)
1656 if (ScreenLine & 0x20)
1661 b1 += (ScreenLine & 0x1f) << 5;
1662 b2 += (ScreenLine & 0x1f) << 5;
1664 int clipcount = GFX.pCurrentClip->Count [bg];
1667 for (int clip = 0; clip < clipcount; clip++)
1672 if (!GFX.pCurrentClip->Count [bg])
1679 Left = GFX.pCurrentClip->Left [clip][bg]* 2;
1680 Right = GFX.pCurrentClip->Right [clip][bg] * 2;
1686 uint32 s = (Left>>1) /** GFX.PixSize*/ + Y * 256;//GFX.PPL;
1687 uint32 HPos = (HOffset + Left /** GFX.PixSize*/) & 0x3ff;
1689 uint32 Quot = HPos >> 3;
1694 t = b2 + ((Quot >> 1) & 0x1f);
1696 t = b1 + (Quot >> 1);
1698 Width = Right - Left;
1699 // Left hand edge clipped tile
1702 int Offset = (HPos & 7);
1707 Tile = READ_2BYTES (t);
1708 GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
1710 if (BG.TileSize == 8)
1712 if (!(Tile & H_FLIP))
1714 // Normal, unflipped
1715 (*DrawHiResClippedTilePtr) (Tile + (Quot & 1),
1716 s, Offset, Count, VirtAlign, Lines);
1721 (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1),
1722 s, Offset, Count, VirtAlign, Lines);
1727 if (!(Tile & (V_FLIP | H_FLIP)))
1729 // Normal, unflipped
1730 (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1),
1731 s, Offset, Count, VirtAlign, Lines);
1739 (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
1740 s, Offset, Count, VirtAlign, Lines);
1745 (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
1746 s, Offset, Count, VirtAlign, Lines);
1752 (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1),
1753 s, Offset, Count, VirtAlign, Lines);
1760 else if (Quot == 127)
1766 // Middle, unclipped tiles
1767 Count = Width - Count;
1768 int Middle = Count >> 3;
1770 for (int C = Middle; C > 0; s += /*8*/4, Quot++, C--)
1772 Tile = READ_2BYTES(t);
1773 GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
1774 if (BG.TileSize == 8)
1776 if (!(Tile & H_FLIP))
1778 // Normal, unflipped
1779 (*DrawHiResTilePtr) (Tile + (Quot & 1),
1780 s, VirtAlign, Lines);
1785 (*DrawHiResTilePtr) (Tile + 1 - (Quot & 1),
1786 s, VirtAlign, Lines);
1791 if (!(Tile & (V_FLIP | H_FLIP)))
1793 // Normal, unflipped
1794 (*DrawHiResTilePtr) (Tile + t1 + (Quot & 1),
1795 s, VirtAlign, Lines);
1803 (*DrawHiResTilePtr) (Tile + t2 + 1 - (Quot & 1),
1804 s, VirtAlign, Lines);
1809 (*DrawHiResTilePtr) (Tile + t1 + 1 - (Quot & 1),
1810 s, VirtAlign, Lines);
1816 (*DrawHiResTilePtr) (Tile + t2 + (Quot & 1),
1817 s, VirtAlign, Lines);
1829 // Right-hand edge clipped tiles
1832 Tile = READ_2BYTES(t);
1833 GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
1834 if (BG.TileSize == 8)
1836 if (!(Tile & H_FLIP))
1838 // Normal, unflipped
1839 (*DrawHiResClippedTilePtr) (Tile + (Quot & 1),
1840 s, 0, Count, VirtAlign, Lines);
1845 (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1),
1846 s, 0, Count, VirtAlign, Lines);
1851 if (!(Tile & (V_FLIP | H_FLIP)))
1853 // Normal, unflipped
1854 (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1),
1855 s, 0, Count, VirtAlign, Lines);
1863 (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
1864 s, 0, Count, VirtAlign, Lines);
1869 (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
1870 s, 0, Count, VirtAlign, Lines);
1876 (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1),
1877 s, 0, Count, VirtAlign, Lines);
1883 GFX.Pitch = GFX.RealPitch;
1884 GFX.PPL = GFX.PPLx2 >> 1;
1887 void orgDrawBackground (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
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;
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 &&
1903 if (PPU.BGMosaic [bg] && PPU.Mosaic > 1)
1905 orgDrawBackgroundMosaic (BGMode, bg, Z1, Z2);
1912 if (Settings.WrestlemaniaArcade)
1914 case 4: // Used by Puzzle Bobble
1915 orgDrawBackgroundOffset (BGMode, bg, Z1, Z2);
1919 case 6: // XXX: is also offset per tile.
1920 // if (Settings.SupportHiRes)
1922 orgDrawBackgroundMode5 (BGMode, bg, Z1, Z2);
1935 uint8 depths [2] = {Z1, Z2};
1938 BG.StartPalette = bg << 5;
1940 BG.StartPalette = 0;
1942 SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
1944 if (PPU.BG[bg].SCSize & 1)
1949 if(SC1>=(unsigned short*)(Memory.VRAM+0x10000))
1950 SC1=(uint16*)&Memory.VRAM[((uint8*)SC1-&Memory.VRAM[0])%0x10000];
1952 if (PPU.BG[bg].SCSize & 2)
1957 if((SC2-(unsigned short*)Memory.VRAM)>0x10000)
1961 if (PPU.BG[bg].SCSize & 1)
1966 if((SC3-(unsigned short*)Memory.VRAM)>0x10000)
1974 if (BG.TileSize == 16)
1985 for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines)
1987 uint32 VOffset = LineData [Y].BG[bg].VOffset;
1988 uint32 HOffset = LineData [Y].BG[bg].HOffset;
1989 int VirtAlign = (Y + VOffset) & 7;
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))
1996 if (Y + Lines > GFX.EndY)
1997 Lines = GFX.EndY + 1 - Y;
2001 uint32 ScreenLine = (VOffset + Y) >> OffsetShift;
2004 if (((VOffset + Y) & 15) > 7)
2017 if (ScreenLine & 0x20)
2022 b1 += (ScreenLine & 0x1f) << 5;
2023 b2 += (ScreenLine & 0x1f) << 5;
2025 int clipcount = GFX.pCurrentClip->Count [bg];
2028 for (int clip = 0; clip < clipcount; clip++)
2033 if (!GFX.pCurrentClip->Count [bg])
2040 Left = GFX.pCurrentClip->Left [clip][bg];
2041 Right = GFX.pCurrentClip->Right [clip][bg];
2047 uint32 s = Left * GFX.PixSize + Y * GFX.PPL;
2048 uint32 HPos = (HOffset + Left) & OffsetMask;
2050 uint32 Quot = HPos >> 3;
2054 if (BG.TileSize == 8)
2057 t = b2 + (Quot & 0x1f);
2064 t = b2 + ((Quot >> 1) & 0x1f);
2066 t = b1 + (Quot >> 1);
2069 Width = Right - Left;
2070 // Left hand edge clipped tile
2073 uint32 Offset = (HPos & 7);
2077 s -= Offset * GFX.PixSize;
2078 Tile = READ_2BYTES(t);
2079 GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
2081 if (BG.TileSize == 8)
2083 (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign,
2088 if (!(Tile & (V_FLIP | H_FLIP)))
2090 // Normal, unflipped
2091 (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1),
2092 s, Offset, Count, VirtAlign, Lines);
2100 (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
2101 s, Offset, Count, VirtAlign, Lines);
2106 (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
2107 s, Offset, Count, VirtAlign, Lines);
2113 (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1), s,
2114 Offset, Count, VirtAlign, Lines);
2118 if (BG.TileSize == 8)
2123 else if (Quot == 63)
2131 else if (Quot == 127)
2135 s += 8 * GFX.PixSize;
2138 // Middle, unclipped tiles
2139 Count = Width - Count;
2140 int Middle = Count >> 3;
2142 for (int C = Middle; C > 0; s += 8 * GFX.PixSize, Quot++, C--)
2144 Tile = READ_2BYTES(t);
2145 GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
2147 if (BG.TileSize != 8)
2151 // Horizontal flip, but what about vertical flip ?
2154 // Both horzontal & vertical flip
2155 (*DrawTilePtr) (Tile + t2 + 1 - (Quot & 1), s,
2160 // Horizontal flip only
2161 (*DrawTilePtr) (Tile + t1 + 1 - (Quot & 1), s,
2167 // No horizontal flip, but is there a vertical flip ?
2170 // Vertical flip only
2171 (*DrawTilePtr) (Tile + t2 + (Quot & 1), s,
2177 (*DrawTilePtr) (Tile + t1 + (Quot & 1), s,
2184 (*DrawTilePtr) (Tile, s, VirtAlign, Lines);
2187 if (BG.TileSize == 8)
2206 // Right-hand edge clipped tiles
2209 Tile = READ_2BYTES(t);
2210 GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
2212 if (BG.TileSize == 8)
2213 (*DrawClippedTilePtr) (Tile, s, 0, Count, VirtAlign,
2217 if (!(Tile & (V_FLIP | H_FLIP)))
2219 // Normal, unflipped
2220 (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1), s, 0,
2221 Count, VirtAlign, Lines);
2229 (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
2230 s, 0, Count, VirtAlign,
2236 (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
2237 s, 0, Count, VirtAlign,
2244 (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1),
2245 s, 0, Count, VirtAlign,
2254 #define RENDER_BACKGROUND_MODE7(TYPE,FUNC) \
2257 uint8 *VRAM1 = Memory.VRAM + 1; \
2258 if (GFX.r2130 & 1) \
2260 if (IPPU.DirectColourMapsNeedRebuild) \
2261 S9xBuildDirectColourMaps (); \
2262 GFX.ScreenColors = DirectColourMaps [0]; \
2265 GFX.ScreenColors = IPPU.ScreenColors; \
2271 uint32 Right = 256; \
2272 uint32 ClipCount = GFX.pCurrentClip->Count [bg]; \
2277 Screen += GFX.StartY * GFX.Pitch; \
2278 uint8 *Depth = GFX.DB + GFX.StartY * GFX.PPL; \
2279 struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; \
2281 for (uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX.Pitch, Depth += GFX.PPL, l++) \
2285 int32 HOffset = ((int32) LineData [Line].BG[0].HOffset << M7) >> M7; \
2286 int32 VOffset = ((int32) LineData [Line].BG[0].VOffset << M7) >> M7; \
2288 int32 CentreX = ((int32) l->CentreX << M7) >> M7; \
2289 int32 CentreY = ((int32) l->CentreY << M7) >> M7; \
2291 if (PPU.Mode7VFlip) \
2292 yy = 261 - (int) Line; \
2296 if (PPU.Mode7Repeat == 0) \
2297 yy += (VOffset - CentreY) % 1023; \
2299 yy += VOffset - CentreY; \
2300 int BB = l->MatrixB * yy + (CentreX << 8); \
2301 int DD = l->MatrixD * yy + (CentreY << 8); \
2303 for (uint32 clip = 0; clip < ClipCount; clip++) \
2305 if (GFX.pCurrentClip->Count [bg]) \
2307 Left = GFX.pCurrentClip->Left [clip][bg]; \
2308 Right = GFX.pCurrentClip->Right [clip][bg]; \
2309 if (Right <= Left) \
2312 TYPE *p = (TYPE *) Screen + Left; \
2313 uint8 *d = Depth + Left; \
2315 if (PPU.Mode7HFlip) \
2317 startx = Right - 1; \
2332 if (PPU.Mode7Repeat == 0) \
2333 xx = startx + (HOffset - CentreX) % 1023; \
2335 xx = startx + HOffset - CentreX; \
2336 int AA = l->MatrixA * xx; \
2337 int CC = l->MatrixC * xx; \
2339 if (!PPU.Mode7Repeat) \
2341 for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \
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) ) \
2357 for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \
2359 int X = ((AA + BB) >> 8); \
2360 int Y = ((CC + DD) >> 8); \
2362 if (Settings.Dezaemon && PPU.Mode7Repeat == 2) \
2368 if (((X | Y) & ~0x3ff) == 0) \
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) ) \
2381 if (PPU.Mode7Repeat == 3) \
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) ) \
2400 void orgDrawBGMode7Background16 (uint8 *Screen, int bg)
2402 RENDER_BACKGROUND_MODE7 (uint16, GFX.ScreenColors [b & GFX.Mode7Mask]);
2405 void orgDrawBGMode7Background16Add (uint8 *Screen, int bg)
2407 RENDER_BACKGROUND_MODE7 (uint16, *(d + GFX.DepthDelta) ?
2408 (*(d + GFX.DepthDelta) != 1 ?
2409 COLOR_ADD (GFX.ScreenColors [b & GFX.Mode7Mask],
2411 COLOR_ADD (GFX.ScreenColors [b & GFX.Mode7Mask],
2413 GFX.ScreenColors [b & GFX.Mode7Mask]);
2416 void orgDrawBGMode7Background16Add1_2 (uint8 *Screen, int bg)
2418 RENDER_BACKGROUND_MODE7 (uint16, *(d + GFX.DepthDelta) ?
2419 (*(d + GFX.DepthDelta) != 1 ?
2420 COLOR_ADD1_2 (GFX.ScreenColors [b & GFX.Mode7Mask],
2422 COLOR_ADD (GFX.ScreenColors [b & GFX.Mode7Mask],
2424 GFX.ScreenColors [b & GFX.Mode7Mask]);
2427 void orgDrawBGMode7Background16Sub (uint8 *Screen, int bg)
2429 RENDER_BACKGROUND_MODE7 (uint16, *(d + GFX.DepthDelta) ?
2430 (*(d + GFX.DepthDelta) != 1 ?
2431 COLOR_SUB (GFX.ScreenColors [b & GFX.Mode7Mask],
2433 COLOR_SUB (GFX.ScreenColors [b & GFX.Mode7Mask],
2435 GFX.ScreenColors [b & GFX.Mode7Mask]);
2438 void orgDrawBGMode7Background16Sub1_2 (uint8 *Screen, int bg)
2440 RENDER_BACKGROUND_MODE7 (uint16, *(d + GFX.DepthDelta) ?
2441 (*(d + GFX.DepthDelta) != 1 ?
2442 COLOR_SUB1_2 (GFX.ScreenColors [b & GFX.Mode7Mask],
2444 COLOR_SUB (GFX.ScreenColors [b & GFX.Mode7Mask],
2446 GFX.ScreenColors [b & GFX.Mode7Mask]);
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);
2484 void RenderScreen (uint8 *Screen, bool8 sub, bool8 force_no_add, uint8 D)
2496 GFX.pCurrentClip = &IPPU.Clip [0];
2505 GFX.pCurrentClip = &IPPU.Clip [1];
2513 sub |= force_no_add;
2515 if (PPU.BGMode <= 1)
2519 orgSelectTileRenderer (sub || !SUB_OR_ADD(4));
2520 orgDrawOBJS (!sub, D);
2524 orgSelectTileRenderer (sub || !SUB_OR_ADD(0));
2525 orgDrawBackground (PPU.BGMode, 0, D + 10, D + 14);
2529 orgSelectTileRenderer (sub || !SUB_OR_ADD(1));
2530 orgDrawBackground (PPU.BGMode, 1, D + 9, D + 13);
2534 orgSelectTileRenderer (sub || !SUB_OR_ADD(2));
2535 orgDrawBackground (PPU.BGMode, 2, D + 3,
2536 (Memory.FillRAM [0x2105] & 8) == 0 ? D + 6 : D + 17);
2538 if (BG3 && PPU.BGMode == 0)
2540 orgSelectTileRenderer (sub || !SUB_OR_ADD(3));
2541 orgDrawBackground (PPU.BGMode, 3, D + 2, D + 5);
2544 else if (PPU.BGMode != 7)
2548 orgSelectTileRenderer (sub || !SUB_OR_ADD(4));
2549 orgDrawOBJS (!sub, D);
2553 orgSelectTileRenderer (sub || !SUB_OR_ADD(0));
2554 orgDrawBackground (PPU.BGMode, 0, D + 5, D + 13);
2556 if (PPU.BGMode != 6 && BG1)
2558 orgSelectTileRenderer (sub || !SUB_OR_ADD(1));
2559 orgDrawBackground (PPU.BGMode, 1, D + 2, D + 9);
2566 orgSelectTileRenderer (sub || !SUB_OR_ADD(4));
2567 orgDrawOBJS (!sub, D);
2569 if (BG0 || ((Memory.FillRAM [0x2133] & 0x40) && BG1))
2573 if (Memory.FillRAM [0x2133] & 0x40)
2575 GFX.Mode7Mask = 0x7f;
2576 GFX.Mode7PriorityMask = 0x80;
2577 Mode7Depths [0] = 5 + D;
2578 Mode7Depths [1] = 9 + D;
2583 GFX.Mode7Mask = 0xff;
2584 GFX.Mode7PriorityMask = 0;
2585 Mode7Depths [0] = 5 + D;
2586 Mode7Depths [1] = 5 + D;
2589 if (sub || !SUB_OR_ADD(0))
2592 orgDrawBGMode7Background16 (Screen, bg);
2596 if (GFX.r2131 & 0x80)
2598 if (GFX.r2131 & 0x40)
2600 orgDrawBGMode7Background16Sub1_2 (Screen, bg);
2604 orgDrawBGMode7Background16Sub (Screen, bg);
2609 if (GFX.r2131 & 0x40)
2611 orgDrawBGMode7Background16Add1_2 (Screen, bg);
2616 orgDrawBGMode7Background16Add (Screen, bg);
2625 void orgS9xUpdateScreen ()
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;
2638 if (IPPU.OBJChanged)
2641 if (PPU.RecomputeClipWindows)
2643 ComputeClipWindows ();
2644 PPU.RecomputeClipWindows = FALSE;
2647 GFX.StartY = IPPU.PreviousLine;
2648 if ((GFX.EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight)
2649 GFX.EndY = PPU.ScreenHeight - 1;
2651 uint32 starty = GFX.StartY;
2652 uint32 endy = GFX.EndY;
2654 uint32 black = BLACK | (BLACK << 16);
2661 GFX.r212d = (Memory.FillRAM [0x212c] ^
2662 Memory.FillRAM [0x212d]) & 15;
2663 GFX.r212c &= ~GFX.r212d;
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))
2671 struct ClipData *pClip;
2673 GFX.FixedColour = BUILD_PIXEL (IPPU.XB [PPU.FixedColourRed],
2674 IPPU.XB [PPU.FixedColourGreen],
2675 IPPU.XB [PPU.FixedColourBlue]);
2677 // Clear the z-buffer, marking areas 'covered' by the fixed
2678 // colour as depth 1.
2679 pClip = &IPPU.Clip [1];
2681 // Clear the z-buffer
2682 if (pClip->Count [5])
2684 // Colour window enabled.
2685 for (uint32 y = starty; y <= endy; y++)
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])
2693 uint32 *p = (uint32 *) (GFX.SubScreen + y * GFX.Pitch2);
2694 uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth);
2698 for (uint32 c = 0; c < pClip->Count [5]; c++)
2700 if (pClip->Right [c][5] > pClip->Left [c][5])
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])
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.
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;
2716 *p++ = (uint16) GFX.FixedColour;
2724 for (uint32 y = starty; y <= endy; y++)
2726 ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch,
2727 IPPU.RenderedScreenWidth);
2728 memset (GFX.SubZBuffer + y * GFX.ZPitch, 1,
2729 IPPU.RenderedScreenWidth);
2731 if (IPPU.Clip [0].Count [5])
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.
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);
2747 if (ANYTHING_ON_SUB)
2749 GFX.DB = GFX.SubZBuffer;
2750 RenderScreen (GFX.SubScreen, TRUE, TRUE, SUB_SCREEN_DEPTH);
2753 if (IPPU.Clip [0].Count [5])
2756 for (uint32 y = starty; y <= endy; y++)
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;
2765 *p = *(p + GFX.Delta);
2774 GFX.DB = GFX.ZBuffer;
2775 RenderScreen (GFX.Screen, FALSE, FALSE, MAIN_SCREEN_DEPTH);
2779 uint32 back = IPPU.ScreenColors [0];
2784 pClip = &IPPU.Clip [0];
2785 for (uint32 y = starty; y <= endy; y++)
2787 if (!(Count = pClip->Count [5]))
2794 for (uint32 b = 0; b < Count; b++)
2796 if (pClip->Count [5])
2798 Left = pClip->Left [b][5] * x2;
2799 Right = pClip->Right [b][5] * x2;
2804 if (GFX.r2131 & 0x80)
2806 if (GFX.r2131 & 0x40)
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);
2823 *p = COLOR_SUB1_2 (back, *(p + GFX.Delta));
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);
2852 *p = COLOR_SUB (back, *(p + GFX.Delta));
2866 if (GFX.r2131 & 0x40)
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);
2881 *p = COLOR_ADD1_2 (back, *(p + GFX.Delta));
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);
2909 *p = COLOR_ADD (back, *(p + GFX.Delta));
2923 if (!pClip->Count [5])
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;
2941 *p = *(p + GFX.Delta);
2943 *p = GFX.FixedColour;
2959 // Subscreen not being added to back
2960 uint32 back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16);
2961 pClip = &IPPU.Clip [0];
2963 if (pClip->Count [5])
2965 for (uint32 y = starty; y <= endy; y++)
2967 for (uint32 b = 0; b < pClip->Count [5]; b++)
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;
2988 for (uint32 y = starty; y <= endy; y++)
2990 uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2);
2991 uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
2992 uint8 *e = d + 256 * x2;
3007 // 16bit and transparency but currently no transparency effects in
3010 uint32 back = IPPU.ScreenColors [0] |
3011 (IPPU.ScreenColors [0] << 16);
3013 if (PPU.ForcedBlanking)
3016 if (IPPU.Clip [0].Count[5])
3018 for (uint32 y = starty; y <= endy; y++)
3020 uint32 *p = (uint32 *) (GFX.Screen + y * GFX.Pitch2);
3021 uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth);
3026 for (uint32 c = 0; c < IPPU.Clip [0].Count [5]; c++)
3028 if (IPPU.Clip [0].Right [c][5] > IPPU.Clip [0].Left [c][5])
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;
3035 *p++ = (uint16) back;
3042 for (uint32 y = starty; y <= endy; y++)
3044 uint32 *p = (uint32 *) (GFX.Screen + y * GFX.Pitch2);
3045 uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth);
3050 if (!PPU.ForcedBlanking)
3052 for (uint32 y = starty; y <= endy; y++)
3054 ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch,
3055 IPPU.RenderedScreenWidth);
3057 GFX.DB = GFX.ZBuffer;
3058 RenderScreen (GFX.Screen, FALSE, TRUE, SUB_SCREEN_DEPTH);
3063 IPPU.PreviousLine = IPPU.CurrentLine;
3066 #ifdef GFX_MULTI_FORMAT
3068 #define _BUILD_PIXEL(F) \
3069 uint32 BuildPixel##F(uint32 R, uint32 G, uint32 B) \
3071 return (BUILD_PIXEL_##F(R,G,B)); \
3073 uint32 BuildPixel2##F(uint32 R, uint32 G, uint32 B) \
3075 return (BUILD_PIXEL2_##F(R,G,B)); \
3077 void DecomposePixel##F(uint32 pixel, uint32 &R, uint32 &G, uint32 &B) \
3079 DECOMPOSE_PIXEL_##F(pixel,R,G,B); \
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)
3090 bool8 S9xSetRenderPixelFormat (int format)
3092 extern uint32 current_graphic_format;
3094 current_graphic_format = format;
3099 _BUILD_SETUP(RGB565)
3102 _BUILD_SETUP(RGB555)
3105 _BUILD_SETUP(BGR565)
3108 _BUILD_SETUP(BGR555)
3111 _BUILD_SETUP(GBR565)
3114 _BUILD_SETUP(GBR555)
3117 _BUILD_SETUP(RGB5551)
3127 void S9xUpdateScreen ()
3132 GFX.r2131 = Memory.FillRAM [0x2131];
3133 GFX.r212c = Memory.FillRAM [0x212c];
3134 GFX.r212d = Memory.FillRAM [0x212d];
3135 GFX.r2130 = Memory.FillRAM [0x2130];
3139 GFX.Pseudo = (Memory.FillRAM [0x2133] & 8) != 0 &&
3140 (GFX.r212c & 15) != (GFX.r212d & 15) &&
3141 (GFX.r2131 == 0x3f);
3145 GFX.Pseudo = (Memory.FillRAM [0x2133] & 8) != 0 &&
3146 (GFX.r212c & 15) != (GFX.r212d & 15) &&
3147 (GFX.r2131 & 0x3f) == 0;
3151 if (IPPU.OBJChanged)
3154 if (PPU.RecomputeClipWindows)
3156 ComputeClipWindows ();
3157 PPU.RecomputeClipWindows = FALSE;
3160 GFX.StartY = IPPU.PreviousLine;
3161 if ((GFX.EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight)
3162 GFX.EndY = PPU.ScreenHeight - 1;
3164 // XXX: Check ForceBlank? Or anything else?
3165 //PPU.RangeTimeOver |= GFX.OBJLines[GFX.EndY].RTOFlags;
3167 uint32 starty = GFX.StartY;
3168 uint32 endy = GFX.EndY;
3170 /*if (Settings.SupportHiRes &&
3171 (PPU.BGMode == 5 || PPU.BGMode == 6 ||
3172 //IPPU.Interlace || IPPU.DoubleHeightPixels))
3174 if (PPU.BGMode == 5 || PPU.BGMode == 6|| IPPU.Interlace)
3176 IPPU.RenderedScreenWidth = 512;
3179 if (IPPU.DoubleHeightPixels)
3181 starty = GFX.StartY * 2;
3182 endy = GFX.EndY * 2 + 1;
3184 if ((PPU.BGMode == 5 || PPU.BGMode == 6) && !IPPU.DoubleWidthPixels)
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)
3190 #if defined (USE_GLIDE) || defined (USE_OPENGL)
3193 (Settings.GlideEnable && GFX.Pitch == 512) ||
3196 (Settings.OpenGLEnable && GFX.Pitch == 512) ||
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--)
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)
3211 GFX.Pitch = GFX.Pitch2 = GFX.RealPitch;
3212 GFX.PPL = GFX.Pitch >> 1;
3213 GFX.PPLx2 = GFX.Pitch;
3214 GFX.ZPitch = GFX.PPL;
3218 for (register uint32 y = 0; y < starty; y++)
3220 register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + 255;
3221 register uint16 *q = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + 510;
3223 for (register int x = 255; x >= 0; x--, p--, q -= 2)
3229 for (register uint32 y = 0; y < starty; y++)
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)
3237 IPPU.DoubleWidthPixels = TRUE;
3239 // BJ: And we have to change the height if Interlace gets set,
3241 if (IPPU.Interlace && !IPPU.DoubleHeightPixels)
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;
3252 GFX.PPL = GFX.PPLx2 = GFX.RealPitch << 1;
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--)
3258 memmove (GFX.Screen + y * 2 * GFX.Pitch2,
3259 GFX.Screen + y * GFX.Pitch2,
3261 memmove (GFX.Screen + (y * 2 + 1) * GFX.Pitch2,
3262 GFX.Screen + y * GFX.Pitch2,
3269 uint32 black = BLACK | (BLACK << 16);
3271 if (Settings.Transparency && Settings.SixteenBit)
3276 GFX.r212c &= (Memory.FillRAM [0x212d] | 0xf0);
3277 GFX.r212d |= (Memory.FillRAM [0x212c] & 0x0f);
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))
3285 struct ClipData *pClip;
3287 GFX.FixedColour = BUILD_PIXEL (IPPU.XB [PPU.FixedColourRed],
3288 IPPU.XB [PPU.FixedColourGreen],
3289 IPPU.XB [PPU.FixedColourBlue]);
3291 // Clear the z-buffer, marking areas 'covered' by the fixed
3292 // colour as depth 1.
3293 pClip = &IPPU.Clip [1];
3295 // Clear the z-buffer
3296 if (pClip->Count [5])
3298 // Colour window enabled.
3299 for (uint32 y = starty; y <= endy; y++)
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])
3307 uint32 *p = (uint32 *) (GFX.SubScreen + y * GFX.Pitch2);
3308 uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth);
3312 for (uint32 c = 0; c < pClip->Count [5]; c++)
3314 if (pClip->Right [c][5] > pClip->Left [c][5])
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])
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.
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;
3330 *p++ = (uint16) GFX.FixedColour;
3338 for (uint32 y = starty; y <= endy; y++)
3340 ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch,
3341 IPPU.RenderedScreenWidth);
3342 memset (GFX.SubZBuffer + y * GFX.ZPitch, 1,
3343 IPPU.RenderedScreenWidth);
3345 if (IPPU.Clip [0].Count [5])
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.
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);
3361 if (ANYTHING_ON_SUB)
3363 GFX.DB = GFX.SubZBuffer;
3364 RenderScreen (GFX.SubScreen, TRUE, TRUE, SUB_SCREEN_DEPTH);
3367 if (IPPU.Clip [0].Count [5])
3369 for (uint32 y = starty; y <= endy; y++)
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;
3378 *p = *(p + GFX.Delta);
3387 GFX.DB = GFX.ZBuffer;
3388 RenderScreen (GFX.Screen, FALSE, FALSE, MAIN_SCREEN_DEPTH);
3392 uint32 back = IPPU.ScreenColors [0];
3397 pClip = &IPPU.Clip [0];
3398 for (uint32 y = starty; y <= endy; y++)
3400 if (!(Count = pClip->Count [5]))
3407 for (uint32 b = 0; b < Count; b++)
3409 if (pClip->Count [5])
3411 Left = pClip->Left [b][5] * x2;
3412 Right = pClip->Right [b][5] * x2;
3417 if (GFX.r2131 & 0x80)
3419 if (GFX.r2131 & 0x40)
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);
3436 *p = COLOR_SUB1_2 (back, *(p + GFX.Delta));
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);
3465 *p = COLOR_SUB (back, *(p + GFX.Delta));
3479 if (GFX.r2131 & 0x40)
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);
3494 *p = COLOR_ADD1_2 (back, *(p + GFX.Delta));
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);
3522 *p = COLOR_ADD (back, *(p + GFX.Delta));
3536 if (!pClip->Count [5])
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;
3554 *p = *(p + GFX.Delta);
3556 *p = GFX.FixedColour;
3572 // Subscreen not being added to back
3573 uint32 back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16);
3574 pClip = &IPPU.Clip [0];
3576 if (pClip->Count [5])
3578 for (uint32 y = starty; y <= endy; y++)
3580 for (uint32 b = 0; b < pClip->Count [5]; b++)
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;
3601 for (uint32 y = starty; y <= endy; y++)
3603 uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2);
3604 uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
3605 uint8 *e = d + 256 * x2;
3620 // 16bit and transparency but currently no transparency effects in
3623 uint32 back = IPPU.ScreenColors [0] |
3624 (IPPU.ScreenColors [0] << 16);
3626 if (PPU.ForcedBlanking)
3629 if (IPPU.Clip [0].Count[5])
3631 for (uint32 y = starty; y <= endy; y++)
3633 uint32 *p = (uint32 *) (GFX.Screen + y * GFX.Pitch2);
3634 uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth);
3639 for (uint32 c = 0; c < IPPU.Clip [0].Count [5]; c++)
3641 if (IPPU.Clip [0].Right [c][5] > IPPU.Clip [0].Left [c][5])
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;
3648 *p++ = (uint16) back;
3655 for (uint32 y = starty; y <= endy; y++)
3657 uint32 *p = (uint32 *) (GFX.Screen + y * GFX.Pitch2);
3658 uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth);
3663 if (!PPU.ForcedBlanking)
3665 for (uint32 y = starty; y <= endy; y++)
3667 ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch,
3668 IPPU.RenderedScreenWidth);
3670 GFX.DB = GFX.ZBuffer;
3671 RenderScreen (GFX.Screen, FALSE, TRUE, SUB_SCREEN_DEPTH);
3677 if (Settings.SixteenBit)
3679 uint32 back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16);
3680 if (PPU.ForcedBlanking)
3683 orgSelectTileRenderer (TRUE);
3685 for (uint32 y = starty; y <= endy; y++)
3687 uint32 *p = (uint32 *) (GFX.Screen + y * GFX.Pitch2);
3688 uint32 *q = (uint32 *) ((uint16 *) p + IPPU.RenderedScreenWidth);
3695 for (uint32 y = starty; y <= endy; y++)
3697 ZeroMemory (GFX.Screen + y * GFX.Pitch2,
3698 IPPU.RenderedScreenWidth);
3701 if (!PPU.ForcedBlanking)
3703 for (uint32 y = starty; y <= endy; y++)
3705 ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch,
3706 IPPU.RenderedScreenWidth);
3708 GFX.DB = GFX.ZBuffer;
3709 GFX.pCurrentClip = &IPPU.Clip [0];
3712 if (GFX.r212c & (1 << (n))) \
3713 GFX.pCurrentClip = &IPPU.Clip [0]; \
3715 GFX.pCurrentClip = &IPPU.Clip [1]
3719 (!(PPU.BG_Forced & n) && \
3720 (GFX.r212c & n) || \
3721 ((GFX.r212d & n) && subadd))
3723 uint8 subadd = GFX.r2131 & 0x3f;
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);
3731 if (PPU.BGMode <= 1)
3741 orgDrawBackground (PPU.BGMode, 0, 10, 14);
3746 orgDrawBackground (PPU.BGMode, 1, 9, 13);
3751 orgDrawBackground (PPU.BGMode, 2, 3,
3752 PPU.BG3Priority ? 17 : 6);
3754 if (BG3 && PPU.BGMode == 0)
3757 orgDrawBackground (PPU.BGMode, 3, 2, 5);
3760 else if (PPU.BGMode != 7)
3770 orgDrawBackground (PPU.BGMode, 0, 5, 13);
3772 if (BG1 && PPU.BGMode != 6)
3775 orgDrawBackground (PPU.BGMode, 1, 2, 9);
3785 if (BG0 || ((Memory.FillRAM [0x2133] & 0x40) && BG1))
3789 if ((Memory.FillRAM [0x2133] & 0x40) && BG1)
3791 GFX.Mode7Mask = 0x7f;
3792 GFX.Mode7PriorityMask = 0x80;
3793 Mode7Depths [0] = (BG0?5:1);
3794 Mode7Depths [1] = 9;
3799 GFX.Mode7Mask = 0xff;
3800 GFX.Mode7PriorityMask = 0;
3801 Mode7Depths [0] = 5;
3802 Mode7Depths [1] = 5;
3806 if (!Settings.SixteenBit)
3807 orgDrawBGMode7Background16 (GFX.Screen, bg);
3810 //if (!Settings.Mode7Interpolate)
3811 orgDrawBGMode7Background16 (GFX.Screen, bg);
3813 // DrawBGMode7Background16_i (GFX.Screen, bg);
3819 if (Settings.SupportHiRes)
3821 if (PPU.BGMode != 5 && PPU.BGMode != 6 && IPPU.DoubleWidthPixels)
3823 // Mixure of background modes used on screen - scale width
3824 // of all non-mode 5 and 6 pixels.
3825 if (Settings.SixteenBit)
3827 for (register uint32 y = starty; y <= endy; y++)
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)
3837 for (register uint32 y = starty; y <= endy; y++)
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)
3847 // Double the height of the pixels just drawn
3848 //FIX_INTERLACE(GFX.Screen, FALSE, GFX.ZBuffer);
3851 IPPU.PreviousLine = IPPU.CurrentLine;