diff --git a/BizHawk.Emulation/CPUs/68000/Diassembler.cs b/BizHawk.Emulation/CPUs/68000/Diassembler.cs index 697ff0a2bd..bbbbe0399a 100644 --- a/BizHawk.Emulation/CPUs/68000/Diassembler.cs +++ b/BizHawk.Emulation/CPUs/68000/Diassembler.cs @@ -62,6 +62,7 @@ namespace BizHawk.Emulation.CPUs.M68000 else if (Opcodes[op] == Scc) Scc_Disasm(info); else if (Opcodes[op] == RTE) RTE_Disasm(info); else if (Opcodes[op] == RTS) RTS_Disasm(info); + else if (Opcodes[op] == RTR) RTR_Disasm(info); else if (Opcodes[op] == TST) TST_Disasm(info); else if (Opcodes[op] == BTSTi) BTSTi_Disasm(info); else if (Opcodes[op] == BTSTr) BTSTr_Disasm(info); diff --git a/BizHawk.Emulation/CPUs/68000/Instructions/ProgramFlow.cs b/BizHawk.Emulation/CPUs/68000/Instructions/ProgramFlow.cs index 767487c100..af64da7a0d 100644 --- a/BizHawk.Emulation/CPUs/68000/Instructions/ProgramFlow.cs +++ b/BizHawk.Emulation/CPUs/68000/Instructions/ProgramFlow.cs @@ -204,6 +204,27 @@ namespace BizHawk.Emulation.CPUs.M68000 info.Args = ""; } + void RTR() + { + ushort sr = (ushort)ReadWord(A[7].s32); + A[7].s32 += 2; + C = (sr & 0x0001) != 0; + V = (sr & 0x0002) != 0; + Z = (sr & 0x0004) != 0; + N = (sr & 0x0008) != 0; + X = (sr & 0x0010) != 0; + + PC = ReadLong(A[7].s32); + A[7].s32 += 4; + PendingCycles -= 20; + } + + void RTR_Disasm(DisassemblyInfo info) + { + info.Mnemonic = "rtr"; + info.Args = ""; + } + void RTE() { short newSR = ReadWord(A[7].s32); diff --git a/BizHawk.Emulation/CPUs/68000/OpcodeTable.cs b/BizHawk.Emulation/CPUs/68000/OpcodeTable.cs index d08417499b..3387396be8 100644 --- a/BizHawk.Emulation/CPUs/68000/OpcodeTable.cs +++ b/BizHawk.Emulation/CPUs/68000/OpcodeTable.cs @@ -49,6 +49,7 @@ namespace BizHawk.Emulation.CPUs.M68000 Assign("dbcc", DBcc, "0101", "CondAll", "11001", "Xn"); Assign("rte", RTE, "0100111001110011"); Assign("rts", RTS, "0100111001110101"); + Assign("rtr", RTR, "0100111001110111"); Assign("tst", TST, "01001010", "Size2_1", "AmXn"); Assign("btst", BTSTi, "0000100000", "AmXn"); Assign("btst", BTSTr, "0000", "Xn", "100", "AmXn"); diff --git a/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.Render.cs b/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.Render.cs index 8d83c05c4d..107f344cb7 100644 --- a/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.Render.cs +++ b/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.Render.cs @@ -4,18 +4,25 @@ namespace BizHawk.Emulation.Consoles.Sega { public partial class GenVDP { + byte[] PriorityBuffer = new byte[320]; + + // TODO, should provide startup register values. public void RenderLine() { - if (ScanLine == 0) - { - Array.Clear(FrameBuffer, 0, FrameBuffer.Length); + Array.Clear(PriorityBuffer, 0, 320); + int bgcolor = BackgroundColor; + for (int ofs = ScanLine * FrameWidth, i = 0; i < FrameWidth; i++, ofs++) + FrameBuffer[ofs] = bgcolor; - //RenderPatterns(); - RenderPalette(); + if (DisplayEnabled) + { RenderScrollA(); RenderScrollB(); + RenderSpritesScanline(); } - RenderSprites(); + + if (ScanLine == 223) // shrug + RenderPalette(); } void RenderPalette() @@ -25,60 +32,64 @@ namespace BizHawk.Emulation.Consoles.Sega FrameBuffer[(p*FrameWidth) + i] = Palette[(p*16) + i]; } - void RenderPatterns() + void RenderBackgroundScanline(int xScroll, int yScroll, int nameTableBase, int lowPriority, int highPriority) { - for (int yi=0; yi<28; yi++) - for (int xi=0; xi<(Display40Mode?40:32); xi++) - RenderPattern(xi * 8, yi * 8, (yi * (Display40Mode ? 40 : 32)) + xi, 0); - } + int yTile = ((ScanLine + yScroll) / 8) % NameTableHeight; + int yOfs = (ScanLine + yScroll) % 8; - void RenderPattern(int x, int y, int pattern, int palette) - { - for (int yi = 0; yi < 8; yi++) + // this is hellllla slow. but not optimizing until we implement & understand + // all scrolling modes, shadow & hilight, etc. + // in thinking about this, you could convince me to optimize the PCE background renderer now. + // Its way simple in comparison. But the PCE sprite renderer is way worse than gen. + for (int x = 0; x < FrameWidth; x++) { - for (int xi = 0; xi < 8; xi++) - { - byte c = PatternBuffer[(pattern*64) + (yi*8) + xi]; - if (c != 0) - FrameBuffer[((y + yi)*FrameWidth) + xi + x] = Palette[(palette*16) + c]; - } + int xTile = Math.Abs(((x - xScroll) / 8) % NameTableWidth); + int xOfs = Math.Abs(x - xScroll) & 7; + int cellOfs = nameTableBase + (yTile * NameTableWidth * 2) + (xTile * 2); + int nameTableEntry = VRAM[cellOfs] | (VRAM[cellOfs+1] << 8); + int patternNo = nameTableEntry & 0x7FF; + bool hFlip = ((nameTableEntry >> 11) & 1) != 0; + bool vFlip = ((nameTableEntry >> 12) & 1) != 0; + bool priority = ((nameTableEntry >> 15) & 1) != 0; + int palette = (nameTableEntry >> 13) & 3; + + if (priority && PriorityBuffer[x] >= highPriority) continue; + if (PriorityBuffer[x] >= lowPriority) continue; + + if (vFlip) yOfs = 7 - yOfs; + if (hFlip) xOfs = 7 - xOfs; + + int texel = PatternBuffer[(patternNo * 64) + (yOfs * 8) + (xOfs)]; + if (texel == 0) continue; + int pixel = Palette[(palette * 16) + texel]; + FrameBuffer[(ScanLine * FrameWidth) + x] = pixel; + PriorityBuffer[x] = (byte) (priority ? highPriority : lowPriority); } } void RenderScrollA() { - for (int yc=0; yc<24; yc++) - { - for (int xc=0; xc<32; xc++) - { - int cellOfs = NameTableAddrA + (yc*NameTableWidth*2) + (xc*2); - int info = (VRAM[cellOfs+1] << 8) | VRAM[cellOfs]; - int pattern = info & 0x7FF; - int palette = (info >> 13) & 3; - RenderPattern(xc*8, yc*8, pattern,palette); - } - } + // todo scroll values + int hscroll = VRAM[HScrollTableAddr + 0] | (VRAM[HScrollTableAddr + 1] << 8); + hscroll &= 0x3FFF; + //hscroll = 24; + int vscroll = VSRAM[0] & 0x3FFF; + RenderBackgroundScanline(hscroll, vscroll, NameTableAddrA, 2, 5); } void RenderScrollB() { - for (int yc = 0; yc < 24; yc++) - { - for (int xc = 0; xc < 40; xc++) - { - int cellOfs = NameTableAddrB + (yc * NameTableWidth * 2) + (xc * 2); - int info = (VRAM[cellOfs+1] << 8) | VRAM[cellOfs]; - int pattern = info & 0x7FF; - int palette = (info >> 13) & 3; - RenderPattern(xc * 8, yc * 8, pattern, palette); - } - } + int hscroll = VRAM[HScrollTableAddr + 2] | (VRAM[HScrollTableAddr + 3] << 8); + hscroll &= 0x3FFF; + //hscroll = 24; + int vscroll = VSRAM[1] & 0x3FFF; + RenderBackgroundScanline(hscroll, vscroll, NameTableAddrB, 1, 4); } static readonly int[] SpriteSizeTable = { 8, 16, 24, 32 }; Sprite sprite; - void RenderSprites() + void RenderSpritesScanline() { int scanLineBase = ScanLine * FrameWidth; int processedSprites = 0; @@ -105,24 +116,36 @@ namespace BizHawk.Emulation.Consoles.Sega for (int xi = 0; xi < sprite.WidthPixels; xi++) { - if (sprite.X + xi < 0 || sprite.X + xi > FrameWidth) + if (sprite.X + xi < 0 || sprite.X + xi >= FrameWidth) continue; + if (sprite.Priority && PriorityBuffer[sprite.X + xi] >= 6) continue; + if (PriorityBuffer[sprite.X + xi] >= 3) continue; + int pixel = PatternBuffer[((pattern + ((xi / 8) * sprite.HeightCells)) * 64) + ((yline & 7) * 8) + (xi & 7)]; if (pixel != 0) + { FrameBuffer[scanLineBase + sprite.X + xi] = Palette[paletteBase + pixel]; + PriorityBuffer[sprite.X + xi] = sprite.Priority ? (byte) 6 : (byte) 3; + } } } else { // HFlip int pattern = sprite.PatternIndex + ((yline / 8)) + (sprite.HeightCells * (sprite.WidthCells - 1)); for (int xi = 0; xi < sprite.WidthPixels; xi++) { - if (sprite.X + xi < 0 || sprite.X + xi > FrameWidth) + if (sprite.X + xi < 0 || sprite.X + xi >= FrameWidth) continue; + if (sprite.Priority && PriorityBuffer[sprite.X + xi] >= 6) continue; + if (PriorityBuffer[sprite.X + xi] >= 3) continue; + int pixel = PatternBuffer[((pattern + ((-xi / 8) * sprite.HeightCells)) * 64) + ((yline & 7) * 8) + (7 - (xi & 7))]; if (pixel != 0) + { FrameBuffer[scanLineBase + sprite.X + xi] = Palette[paletteBase + pixel]; + PriorityBuffer[sprite.X + xi] = sprite.Priority ? (byte) 6 : (byte) 3; + } } } diff --git a/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.cs b/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.cs index 04f30d7f54..f3b2d2380c 100644 --- a/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.cs +++ b/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.cs @@ -29,8 +29,8 @@ namespace BizHawk.Emulation.Consoles.Sega ushort NameTableAddrWindow; ushort SpriteAttributeTableAddr; ushort HScrollTableAddr; - byte NameTableWidth; - byte NameTableHeight; + int NameTableWidth = 32; + int NameTableHeight = 32; bool ControlWordPending; ushort VdpDataAddr;