📄 gfx.cpp
字号:
{ OffsetMask = 0x3ff; OffsetShift = 4; } else { OffsetMask = 0x1ff; OffsetShift = 3; } for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines) { uint32 VOffset = LineData [Y].BG[bg].VOffset; uint32 HOffset = LineData [Y].BG[bg].HOffset; uint32 MosaicOffset = Y % PPU.Mosaic; for (Lines = 1; Lines < PPU.Mosaic - MosaicOffset; Lines++) if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || (HOffset != LineData [Y + Lines].BG[bg].HOffset)) break; uint32 MosaicLine = VOffset + Y - MosaicOffset; if (Y + Lines > GFX.EndY) Lines = GFX.EndY + 1 - Y; uint32 VirtAlign = (MosaicLine & 7) << 3; uint16 *b1; uint16 *b2; uint32 ScreenLine = MosaicLine >> OffsetShift; uint32 Rem16 = MosaicLine & 15; if (ScreenLine & 0x20) b1 = SC2, b2 = SC3; else b1 = SC0, b2 = SC1; b1 += (ScreenLine & 0x1f) << 5; b2 += (ScreenLine & 0x1f) << 5; uint16 *t; uint32 Left = 0; uint32 Right = 256; uint32 ClipCount = GFX.pCurrentClip->Count [bg]; uint32 HPos = HOffset; uint32 PixWidth = PPU.Mosaic; if (!ClipCount) ClipCount = 1; for (uint32 clip = 0; clip < ClipCount; clip++) { if (GFX.pCurrentClip->Count [bg]) { Left = GFX.pCurrentClip->Left [clip][bg]; Right = GFX.pCurrentClip->Right [clip][bg]; uint32 r = Left % PPU.Mosaic; HPos = HOffset + Left; PixWidth = PPU.Mosaic - r; } uint32 s = Y * GFX.PPL + Left * GFX.PixSize; for (uint32 x = Left; x < Right; x += PixWidth, s += PixWidth * GFX.PixSize, HPos += PixWidth, PixWidth = PPU.Mosaic) { uint32 Quot = (HPos & OffsetMask) >> 3; if (x + PixWidth >= Right) PixWidth = Right - x; if (BG.TileSize == 8) { if (Quot > 31) t = b2 + (Quot & 0x1f); else t = b1 + Quot; } else { if (Quot > 63) t = b2 + ((Quot >> 1) & 0x1f); else t = b1 + (Quot >> 1); } Tile = READ_2BYTES (t); GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; // Draw tile... if (BG.TileSize != 8) { if (Tile & H_FLIP) { // Horizontal flip, but what about vertical flip ? if (Tile & V_FLIP) { // Both horzontal & vertical flip if (Rem16 < 8) { (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s, HPos & 7, PixWidth, VirtAlign, Lines); } else { (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s, HPos & 7, PixWidth, VirtAlign, Lines); } } else { // Horizontal flip only if (Rem16 > 7) { (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s, HPos & 7, PixWidth, VirtAlign, Lines); } else { (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s, HPos & 7, PixWidth, VirtAlign, Lines); } } } else { // No horizontal flip, but is there a vertical flip ? if (Tile & V_FLIP) { // Vertical flip only if (Rem16 < 8) { (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s, HPos & 7, PixWidth, VirtAlign, Lines); } else { (*DrawLargePixelPtr) (Tile + (Quot & 1), s, HPos & 7, PixWidth, VirtAlign, Lines); } } else { // Normal unflipped if (Rem16 > 7) { (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s, HPos & 7, PixWidth, VirtAlign, Lines); } else { (*DrawLargePixelPtr) (Tile + (Quot & 1), s, HPos & 7, PixWidth, VirtAlign, Lines); } } } } else (*DrawLargePixelPtr) (Tile, s, HPos & 7, PixWidth, VirtAlign, Lines); } } }}void DrawBackgroundOffset (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2){ CHECK_SOUND(); uint32 Tile; uint16 *SC0; uint16 *SC1; uint16 *SC2; uint16 *SC3; uint16 *BPS0; uint16 *BPS1; uint16 *BPS2; uint16 *BPS3; uint32 Width; int VOffsetOffset = BGMode == 4 ? 0 : 32; uint8 depths [2] = {Z1, Z2}; BG.StartPalette = 0; BPS0 = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1]; if (PPU.BG[2].SCSize & 1) BPS1 = BPS0 + 1024; else BPS1 = BPS0; if (PPU.BG[2].SCSize & 2) BPS2 = BPS1 + 1024; else BPS2 = BPS0; if (PPU.BG[2].SCSize & 1) BPS3 = BPS2 + 1024; else BPS3 = BPS2; SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; if (PPU.BG[bg].SCSize & 1) SC1 = SC0 + 1024; else SC1 = SC0; if (PPU.BG[bg].SCSize & 2) SC2 = SC1 + 1024; else SC2 = SC0; if (PPU.BG[bg].SCSize & 1) SC3 = SC2 + 1024; else SC3 = SC2; static const int Lines = 1; int OffsetMask; int OffsetShift; int OffsetEnableMask = 1 << (bg + 13); if (BG.TileSize == 16) { OffsetMask = 0x3ff; OffsetShift = 4; } else { OffsetMask = 0x1ff; OffsetShift = 3; } for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y++) { uint32 VOff = LineData [Y].BG[2].VOffset; uint32 HOff = LineData [Y].BG[2].HOffset; int VirtAlign; int ScreenLine = VOff >> 3; int t1; int t2; uint16 *s0; uint16 *s1; uint16 *s2; if (ScreenLine & 0x20) s1 = BPS2, s2 = BPS3; else s1 = BPS0, s2 = BPS1; s1 += (ScreenLine & 0x1f) << 5; s2 += (ScreenLine & 0x1f) << 5; int clipcount = GFX.pCurrentClip->Count [bg]; if (!clipcount) clipcount = 1; for (int clip = 0; clip < clipcount; clip++) { uint32 Left; uint32 Right; if (!GFX.pCurrentClip->Count [bg]) { Left = 0; Right = 256; } else { Left = GFX.pCurrentClip->Left [clip][bg]; Right = GFX.pCurrentClip->Right [clip][bg]; if (Right <= Left) continue; } uint32 VOffset; uint32 HOffset; uint32 Offset; uint32 HPos; uint32 Quot; uint32 Count; uint16 *t; uint32 Quot2; uint32 VCellOffset; uint32 HCellOffset; uint16 *b1; uint16 *b2; uint32 TotalCount = 0; uint32 MaxCount; uint32 s = Left * GFX.PixSize + Y * GFX.PPL; bool8 left_hand_edge = Left == 0; Width = Right - Left; MaxCount = 8; if (Left & 7) MaxCount = 8 - (Left & 7); while (Left < Right) { if (left_hand_edge) { // The SNES offset-per-tile background mode has a // hardware limitation that the offsets cannot be set // for the tile of the left-hand edge of the screen. VOffset = LineData [Y].BG[bg].VOffset; HOffset = LineData [Y].BG[bg].HOffset; } else { // All subsequent offset tile data is shifted left by one, // hence the - 1 below. Quot2 = ((HOff + Left - 1 + (LineData [Y].BG[bg].HOffset & 7)) & OffsetMask) >> 3; if (Quot2 > 31) s0 = s2 + (Quot2 & 0x1f); else s0 = s1 + Quot2; HCellOffset = READ_2BYTES (s0); if (BGMode == 4) { VOffset = LineData [Y].BG[bg].VOffset; HOffset = LineData [Y].BG[bg].HOffset; if ((HCellOffset & OffsetEnableMask)) { if (HCellOffset & 0x8000) VOffset = HCellOffset + 1; else HOffset = HCellOffset; } } else { VCellOffset = READ_2BYTES (s0 + VOffsetOffset); if ((VCellOffset & OffsetEnableMask)) VOffset = VCellOffset + 1; else VOffset = LineData [Y].BG[bg].VOffset; if ((HCellOffset & OffsetEnableMask)) HOffset = HCellOffset; else HOffset = LineData [Y].BG[bg].HOffset; } } VirtAlign = ((Y + VOffset) & 7) << 3; ScreenLine = (VOffset + Y) >> OffsetShift; if (((VOffset + Y) & 15) > 7) { t1 = 16; t2 = 0; } else { t1 = 0; t2 = 16; } if (ScreenLine & 0x20) b1 = SC2, b2 = SC3; else b1 = SC0, b2 = SC1; b1 += (ScreenLine & 0x1f) << 5; b2 += (ScreenLine & 0x1f) << 5; HPos = (HOffset + Left) & OffsetMask; Quot = HPos >> 3; if (BG.TileSize == 8) { if (Quot > 31) t = b2 + (Quot & 0x1f); else t = b1 + Quot; } else { if (Quot > 63) t = b2 + ((Quot >> 1) & 0x1f); else t = b1 + (Quot >> 1); } if (MaxCount + TotalCount > Width) MaxCount = Width - TotalCount; Offset = HPos & 7; if (MaxCount > 8 - Offset) MaxCount = 8 - Offset; Count = 8 - Offset; if (Count > MaxCount) Count = MaxCount; s -= Offset * GFX.PixSize; Tile = READ_2BYTES(t); GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; if (BG.TileSize == 8) (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); else { if (!(Tile & (V_FLIP | H_FLIP))) { // Normal, unflipped (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1), s, Offset, Count, VirtAlign, Lines); } else if (Tile & H_FLIP) { if (Tile & V_FLIP) { // H & V flip (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1), s, Offset, Count, VirtAlign, Lines); } else { // H flip only (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1), s, Offset, Count, VirtAlign, Lines); } } else { // V flip only (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1), s, Offset, Count, VirtAlign, Lines); } } Left += Count; TotalCount += Count; s += (Offset + Count) * GFX.PixSize; MaxCount = 8; left_hand_edge = FALSE; } } }}void DrawBackgroundMode5 (uint32 /* BGMODE */, uint32 bg, uint8 Z1, uint8 Z2){ CHECK_SOUND(); GFX.Pitch = GFX.RealPitch; GFX.PPL = GFX.PPLx2 >> 1; GFX.PixSize = 1; uint8 depths [2] = {Z1, Z2}; uint32 Tile; uint16 *SC0; uint16 *SC1; uint16 *SC2; uint16 *SC3; uint32 Width; BG.StartPalette = 0; SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; if ((PPU.BG[bg].SCSize & 1)) SC1 = SC0 + 1024; else SC1 = SC0; if ((PPU.BG[bg].SCSize & 2)) SC2 = SC1 + 1024; else SC2 = SC0; if ((PPU.BG[bg].SCSize & 1)) SC3 = SC2 + 1024; else SC3 = SC2; int Lines; int VOffsetMask; int VOffsetShift; if (BG.TileSize == 16) { VOffsetMask = 0x3ff; VOffsetShift = 4; } else { VOffsetMask = 0x1ff; VOffsetShift = 3; } int endy = IPPU.LatchedInterlace ? GFX.EndY << 1 : GFX.EndY; for (int Y = IPPU.LatchedInterlace ? GFX.StartY << 1 : GFX.StartY; Y <= endy; Y += Lines) { int y = IPPU.LatchedInterlace ? (Y >> 1) : Y; uint32 VOffset = LineData [y].BG[bg].VOffset; uint32 HOffset = LineData [y].BG[bg].HOffset; int VirtAlign = (Y + VOffset) & 7; for (Lines = 1; Lines < 8 - VirtAlign; Lines++) if ((VOffset != LineData [y + Lines].BG[bg].VOffset) || (HOffset != LineData [y + Lines].BG[bg].HOffset)) break; HOffset <<= 1; if (Y + Lines > endy) Lines = endy + 1 - Y; VirtAlign <<= 3; int ScreenLine = (VOffset + Y) >> VOffsetShift; int t1; int t2; if (((VOffset + Y) & 15) > 7) { t1 = 16; t2 = 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -