diff --git a/Core/Cpu/Z80.cs b/Core/Cpu/Z80.cs index 23e27d5..8bb241c 100644 --- a/Core/Cpu/Z80.cs +++ b/Core/Cpu/Z80.cs @@ -190,6 +190,7 @@ namespace Core.Cpu // Fetch the next opcode and increment the Program Counter byte opcode = ReadMemory(PC++); + R = (byte)((R + 1) & 0x7F); int tStates = ExecuteOpcode(opcode); TotalTStates += tStates; diff --git a/Core/Video/SmsVdp.cs b/Core/Video/SmsVdp.cs index 0547b8f..3a3451a 100644 --- a/Core/Video/SmsVdp.cs +++ b/Core/Video/SmsVdp.cs @@ -18,9 +18,12 @@ namespace Core.Video private int _tStateCounter = 0; private int _currentScanline = 0; + private int _lineCounter = 0; private byte _statusRegister = 0x00; - public bool InterruptPending => (_statusRegister & 0x80) != 0 && (Registers[1] & 0x20) != 0; + public bool InterruptPending => + ((_statusRegister & 0x80) != 0 && (Registers[1] & 0x20) != 0) || // VBlank + ((_statusRegister & 0x40) != 0 && (Registers[0] & 0x10) != 0); // Line Interrupt public byte ReadDataPort() // Port 0xBE { @@ -110,6 +113,20 @@ namespace Core.Video if (_tStateCounter >= 228) { _tStateCounter -= 228; + //// --- LINE INTERRUPT LOGIC --- + //if (_currentScanline <= 192) + //{ + // _lineCounter--; + // if (_lineCounter < 0) + // { + // _lineCounter = Registers[10]; // Reload counter + // _statusRegister |= 0x40; // Set Line Interrupt Flag (Bit 6) + // } + //} + //else + //{ + // _lineCounter = Registers[10]; // Reload outside active display + //} _currentScanline++; // Line 192 is the exact moment the screen finishes drawing! @@ -117,8 +134,16 @@ namespace Core.Video { _statusRegister |= 0x80; // Set Bit 7 (VBlank Flag) to 1 - RenderBackground(); // <--- DRAW THE FRAME! - RenderSprites(); + if ((Registers[1] & 0x40) != 0) + { + RenderBackground(); + RenderSprites(); + } + else + { + // Screen is off! Fill it with black (or the background color) + Array.Fill(FrameBuffer, unchecked((int)0xFF000000)); + } } // End of the NTSC frame (262 lines) @@ -220,6 +245,7 @@ namespace Core.Video // 3. Register 1 determines sprite size (8x8 or 8x16) bool is8x16 = (Registers[1] & 0x02) != 0; + bool shiftSpritesLeft = (Registers[0] & 0x08) != 0; // The SMS can draw a maximum of 64 sprites for (int i = 0; i < 64; i++) @@ -261,6 +287,11 @@ namespace Core.Video for (int px = 0; px < 8; px++) { int screenX = x + px; + // THE FIX: Shift the pixel left if commanded! + if (shiftSpritesLeft) screenX -= 8; + + // If it shifted off the left edge, skip it! + if (screenX < 0 || screenX >= 256) continue; // If this pixel is off the right side of the screen, skip it if (screenX >= 256) continue; diff --git a/Desktop/Desktop.csproj b/Desktop/Desktop.csproj index 8cd674b..ea2517e 100644 --- a/Desktop/Desktop.csproj +++ b/Desktop/Desktop.csproj @@ -11,8 +11,11 @@ + + + @@ -22,12 +25,21 @@ Always + + Always + Always Always + + Always + + + Always + diff --git a/Desktop/Form1.Designer.cs b/Desktop/Form1.Designer.cs index 4543a60..9e9b85d 100644 --- a/Desktop/Form1.Designer.cs +++ b/Desktop/Form1.Designer.cs @@ -28,7 +28,6 @@ /// private void InitializeComponent() { - pbScreen = new PictureBox(); menuStrip1 = new MenuStrip(); fileToolStripMenuItem = new ToolStripMenuItem(); openToolStripMenuItem = new ToolStripMenuItem(); @@ -41,19 +40,9 @@ resetToolStripMenuItem = new ToolStripMenuItem(); helpToolStripMenuItem = new ToolStripMenuItem(); aboutToolStripMenuItem = new ToolStripMenuItem(); - ((System.ComponentModel.ISupportInitialize)pbScreen).BeginInit(); menuStrip1.SuspendLayout(); SuspendLayout(); // - // pbScreen - // - pbScreen.Location = new Point(12, 36); - pbScreen.Name = "pbScreen"; - pbScreen.Size = new Size(768, 576); - pbScreen.SizeMode = PictureBoxSizeMode.Zoom; - pbScreen.TabIndex = 1; - pbScreen.TabStop = false; - // // menuStrip1 // menuStrip1.ImageScalingSize = new Size(24, 24); @@ -145,13 +134,11 @@ AutoScaleDimensions = new SizeF(10F, 25F); AutoScaleMode = AutoScaleMode.Font; ClientSize = new Size(791, 622); - Controls.Add(pbScreen); Controls.Add(menuStrip1); MainMenuStrip = menuStrip1; Margin = new Padding(4); Name = "ParsonsForm1"; Text = "Form1"; - ((System.ComponentModel.ISupportInitialize)pbScreen).EndInit(); menuStrip1.ResumeLayout(false); menuStrip1.PerformLayout(); ResumeLayout(false); @@ -159,7 +146,6 @@ } #endregion - private PictureBox pbScreen; private MenuStrip menuStrip1; private ToolStripMenuItem fileToolStripMenuItem; private ToolStripMenuItem openToolStripMenuItem; diff --git a/Desktop/Form1.cs b/Desktop/Form1.cs index 55ef98f..f9d2d33 100644 --- a/Desktop/Form1.cs +++ b/Desktop/Form1.cs @@ -40,6 +40,8 @@ namespace Desktop this.KeyPreview = true; this.KeyDown += Form1_KeyDown; this.KeyUp += Form1_KeyUp; + this.DoubleBuffered = true; + this.ResizeRedraw = true; } private void DrawScreen() @@ -48,11 +50,34 @@ namespace Desktop var data = _screenBitmap.LockBits(new Rectangle(0, 0, 256, 192), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); Marshal.Copy(_machine.VideoProcessor.FrameBuffer, 0, data.Scan0, _machine.VideoProcessor.FrameBuffer.Length); _screenBitmap.UnlockBits(data); - - // Update the PictureBox - pbScreen.Image = _screenBitmap; + this.Invalidate(); TotalFrameCount++; } + protected override void OnPaint(PaintEventArgs e) + { + // Always call the base method so Windows can draw your MenuStrip! + base.OnPaint(e); + + if (_screenBitmap != null) + { + // 1. Set the rendering mode for perfect, chunky retro pixels! + e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; + e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half; + + // 2. Calculate the drawing area. + // We start drawing BELOW the MenuStrip so it doesn't get covered up. + int topOffset = menuStrip1.Height; // Change 'menuStrip1' if your menu has a different (Name) + Rectangle renderArea = new Rectangle( + 0, + topOffset, + this.ClientSize.Width, + this.ClientSize.Height - topOffset + ); + + // 3. Blast the bitmap directly onto the graphics card buffer! + e.Graphics.DrawImage(_screenBitmap, renderArea); + } + } public void StartEmulator() { diff --git a/Desktop/ROMS/SMSTestSuite.sms b/Desktop/ROMS/SMSTestSuite.sms new file mode 100644 index 0000000..9105845 Binary files /dev/null and b/Desktop/ROMS/SMSTestSuite.sms differ diff --git a/Desktop/ROMS/zexall.sms b/Desktop/ROMS/zexall.sms new file mode 100644 index 0000000..906d615 Binary files /dev/null and b/Desktop/ROMS/zexall.sms differ diff --git a/Desktop/ROMS/zexdoc.sms b/Desktop/ROMS/zexdoc.sms new file mode 100644 index 0000000..8440311 Binary files /dev/null and b/Desktop/ROMS/zexdoc.sms differ