Skip to content

Commit

Permalink
Merge pull request #119 from kamiyaowl/issue_24
Browse files Browse the repository at this point in the history
close #24
  • Loading branch information
kamiyaowl committed Jul 24, 2020
2 parents 53958be + 33d147d commit f700311
Show file tree
Hide file tree
Showing 9 changed files with 172 additions and 95 deletions.
2 changes: 1 addition & 1 deletion BlazeSnes.Core.Test/Common/ExtensionTest.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Collections.Generic;

using BlazeSnes.Core.Common;
using BlazeSnes.Core.Cpu;
Expand Down
6 changes: 3 additions & 3 deletions BlazeSnes.Core.Test/Tool/DisassemblerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,8 @@ public class DisassemblerTest {
// Reset Vector後の挙動を順番に確認する
var cpu = new CpuRegister();
cpu.Reset();
var target = cartridge.Disassemble(cpu).Zip(expectOpcodes, (actual, expect) => new { Actual = actual, Expect = expect});
foreach(var dst in target) {
var target = cartridge.Disassemble(cpu).Zip(expectOpcodes, (actual, expect) => new { Actual = actual, Expect = expect });
foreach (var dst in target) {
var expectInst = dst.Expect.Item1;
var expectArgs = dst.Expect.Item2;
var expectSysAddr = (uint)(dst.Expect.Item3 + cartridge.ResetAddrInEmulation); // Reset Vectorの指している位置からのオフセット
Expand All @@ -246,6 +246,6 @@ public class DisassemblerTest {

}
}

}
}
2 changes: 1 addition & 1 deletion BlazeSnes.Core/Common/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public static class Extension {
b.Serialize(ms, src);
// deserialize
ms.Seek(0, SeekOrigin.Begin);
return (T)b.Deserialize(ms);
return (T)b.Deserialize(ms);
}
}
}
Expand Down
146 changes: 73 additions & 73 deletions BlazeSnes.Core/Cpu/OpCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -268,35 +268,35 @@ public enum CycleOption {
throw new NotImplementedException("TODO: Implement Clear");
/********************* Set *********************/
case Instruction.SEC: { // C
Debug.Assert(this.AddressingMode == Addressing.Implied);
Debug.Assert(this.AddressingMode == Addressing.Implied);

cpu.P.UpdateFlag(ProcessorStatusFlag.C, true);
cpu.PC += (ushort)this.GetTotalArrangeBytes(cpu);
break;
}
cpu.P.UpdateFlag(ProcessorStatusFlag.C, true);
cpu.PC += (ushort)this.GetTotalArrangeBytes(cpu);
break;
}
case Instruction.SED: {// D
Debug.Assert(this.AddressingMode == Addressing.Implied);
cpu.P.UpdateFlag(ProcessorStatusFlag.D, true);
cpu.PC += (ushort)this.GetTotalArrangeBytes(cpu);
break;
}
Debug.Assert(this.AddressingMode == Addressing.Implied);

cpu.P.UpdateFlag(ProcessorStatusFlag.D, true);
cpu.PC += (ushort)this.GetTotalArrangeBytes(cpu);
break;
}
case Instruction.SEI: { // I
Debug.Assert(this.AddressingMode == Addressing.Implied);
cpu.P.UpdateFlag(ProcessorStatusFlag.I, true);
cpu.PC += (ushort)this.GetTotalArrangeBytes(cpu);
break;
}
Debug.Assert(this.AddressingMode == Addressing.Implied);

cpu.P.UpdateFlag(ProcessorStatusFlag.I, true);
cpu.PC += (ushort)this.GetTotalArrangeBytes(cpu);
break;
}
case Instruction.SEP: {// NVMXDIZC
// Immediate 1byteで、フラグが立っている部分を反映
Debug.Assert(this.AddressingMode == Addressing.Immediate);
var srcData = read();
cpu.P.UpdateFlag((ProcessorStatusFlag)(srcData & 0xff), true);
cpu.PC += (ushort)this.GetTotalArrangeBytes(cpu);
break;
}
// Immediate 1byteで、フラグが立っている部分を反映
Debug.Assert(this.AddressingMode == Addressing.Immediate);
var srcData = read();

cpu.P.UpdateFlag((ProcessorStatusFlag)(srcData & 0xff), true);
cpu.PC += (ushort)this.GetTotalArrangeBytes(cpu);
break;
}
/********************* Compare *********************/
case Instruction.CMP: // NZC
case Instruction.CPX: // NZC
Expand Down Expand Up @@ -369,60 +369,60 @@ public enum CycleOption {
throw new NotImplementedException("TODO: Implement Transfer");
/********************* Load *********************/
case Instruction.LDA: { // NZ
// 取得した値をA regに読み込み
var srcData = read();
cpu.AConsideringMemoryReg = srcData;
// CPU Flag, PCを更新
cpu.P.UpdateNegativeFlag(srcData, cpu.Is16bitMemoryAccess);
cpu.P.UpdateZeroFlag(srcData);
cpu.PC += (ushort)this.GetTotalArrangeBytes(cpu);
break;
}
// 取得した値をA regに読み込み
var srcData = read();
cpu.AConsideringMemoryReg = srcData;
// CPU Flag, PCを更新
cpu.P.UpdateNegativeFlag(srcData, cpu.Is16bitMemoryAccess);
cpu.P.UpdateZeroFlag(srcData);
cpu.PC += (ushort)this.GetTotalArrangeBytes(cpu);
break;
}
case Instruction.LDX: { // NZ
// 取得した値をX regに読み込み
var srcData = read();
cpu.XConsideringIndexReg = srcData;
// CPU Flag, PCを更新
cpu.P.UpdateNegativeFlag(srcData, cpu.Is16bitMemoryAccess);
cpu.P.UpdateZeroFlag(srcData);
cpu.PC += (ushort)this.GetTotalArrangeBytes(cpu);
break;
}
// 取得した値をX regに読み込み
var srcData = read();
cpu.XConsideringIndexReg = srcData;
// CPU Flag, PCを更新
cpu.P.UpdateNegativeFlag(srcData, cpu.Is16bitMemoryAccess);
cpu.P.UpdateZeroFlag(srcData);
cpu.PC += (ushort)this.GetTotalArrangeBytes(cpu);
break;
}
case Instruction.LDY: { // NZ
// 取得した値をY regに読み込み
var srcData = read();
cpu.YConsideringIndexReg = srcData;
// CPU Flag, PCを更新
cpu.P.UpdateNegativeFlag(srcData, cpu.Is16bitMemoryAccess);
cpu.P.UpdateZeroFlag(srcData);
cpu.PC += (ushort)this.GetTotalArrangeBytes(cpu);
break;
}
// 取得した値をY regに読み込み
var srcData = read();
cpu.YConsideringIndexReg = srcData;
// CPU Flag, PCを更新
cpu.P.UpdateNegativeFlag(srcData, cpu.Is16bitMemoryAccess);
cpu.P.UpdateZeroFlag(srcData);
cpu.PC += (ushort)this.GetTotalArrangeBytes(cpu);
break;
}
/********************* Store *********************/
case Instruction.STA: {
// Aの値を指定されたアドレスに記録
var dstData = cpu.AConsideringMemoryReg;
write(dstData);
// フラグ操作はなし
cpu.PC += (ushort)this.GetTotalArrangeBytes(cpu);
break;
}
// Aの値を指定されたアドレスに記録
var dstData = cpu.AConsideringMemoryReg;
write(dstData);
// フラグ操作はなし
cpu.PC += (ushort)this.GetTotalArrangeBytes(cpu);
break;
}
case Instruction.STX: {
// Xの値を指定されたアドレスに記録
var dstData = cpu.XConsideringIndexReg;
write(dstData);
// フラグ操作はなし
cpu.PC += (ushort)this.GetTotalArrangeBytes(cpu);
break;
}
// Xの値を指定されたアドレスに記録
var dstData = cpu.XConsideringIndexReg;
write(dstData);
// フラグ操作はなし
cpu.PC += (ushort)this.GetTotalArrangeBytes(cpu);
break;
}
case Instruction.STY: {
// Yの値を指定されたアドレスに記録
var dstData = cpu.YConsideringIndexReg;
write(dstData);
// フラグ操作はなし
cpu.PC += (ushort)this.GetTotalArrangeBytes(cpu);
break;
}
// Yの値を指定されたアドレスに記録
var dstData = cpu.YConsideringIndexReg;
write(dstData);
// フラグ操作はなし
cpu.PC += (ushort)this.GetTotalArrangeBytes(cpu);
break;
}
case Instruction.STZ:
throw new NotImplementedException("TODO: Implement Store");
}
Expand Down
2 changes: 1 addition & 1 deletion BlazeSnes.Core/Tool/Disassembler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public static class DisassemblerExtension {
/// systemAddrにResetAddrを使用します。引数のCpuRegisterは内容が変更されるのでCopyされたものを指定します
/// </summary>
/// <param name="c"></param>
public static IEnumerable<(OpCode, byte[], uint, uint)> Disassemble(this Cartridge cartridge, CpuRegister cpu) => cartridge.Disassemble(cpu, cartridge.ResetAddrInEmulation);
public static IEnumerable<(OpCode, byte[], uint, uint)> Disassemble(this Cartridge cartridge, CpuRegister cpu) => cartridge.Disassemble(cpu, cartridge.ResetAddrInEmulation);
public static IEnumerable<(OpCode, byte[], uint, uint)> Disassemble(this Cartridge cartridge, CpuRegister cpu, uint startSysAddr) {
// ResetVectorのLocalAddrに展開済サイズを足す
var startBinAddr = cartridge.ConvertToLocalAddr(startSysAddr).Item2;
Expand Down
83 changes: 70 additions & 13 deletions BlazeSnes/Pages/Index.razor
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@page "/"
@inject Blazored.LocalStorage.ISyncLocalStorageService localStorage
@inject IJSRuntime CurrentJSRuntime
@inject Blazored.LocalStorage.ISyncLocalStorageService LocalStorage
@inject IJSRuntime JSRuntime

<Jumbotron Margin="Margin.Is4.FromBottom" Background="Background.Primary">
<JumbotronTitle Size="JumbotronTitleSize.Is4">BlazeSnes</JumbotronTitle>
Expand All @@ -21,7 +21,8 @@
<Tooltip Text='@($"Display Size: {canvasWidth}x{canvasHeight}")'>
<Slider Color="Primary" TValue="float" Min="1.0f" Max="5.0f" Step="0.1f" ValueChanged="@((e) => ChangeCanvasSize(e))"/>
</Tooltip>
<BECanvas Width="@canvasWidth" Height="@canvasHeight" @ref="canvasReference"></BECanvas>
<canvas id="emulatorCanvas" width="@canvasWidth" height="@canvasHeight" tabindex="1" @onkeydown="OnCanvasKeyDown" @onkeyup="OnCanvasKeyUp"
@onmousemove="OnCanvasMouseMove" @onmousedown="OnCanvasMouseDown" @onmouseup="OnCanvasMouseUp" />
</CardBody>
</Card>
</Column>
Expand Down Expand Up @@ -293,33 +294,89 @@
</Snackbar>

@code {
// canvas関連
// TODO: .razor.csファイルに分離(これに限らず全て)
// 固定値関連
readonly int BASE_WIDTH = 256;
readonly int BASE_HEIGHT = 224;
readonly double FPS = 60;
readonly int BYTE_PER_PIXEL = 4;
// canvas関連
int canvasWidth = 256;
int canvasHeight = 224;
Canvas2DContext context;
BECanvasComponent canvasReference;
// snackbarでのメッセージ表示
Snackbar snackbar;
string snackbarMessage;

// デバッガ表示フラグ
// TODO: 最終的にはDefault Disableにする
bool isVisibleCpuDebug = true;
bool isVisibleCpuDebug = true; // TODO: 最終的にはDefault Disableにする
bool isVisiblePpuDebug = false;
bool isVisibleApuDebug = false;
bool isVisibleRomDebug = true;

// 読み込んだカセット
// Emulation関係
int counter = 0;
byte[] frameBuffer;
System.Timers.Timer emulateTimer;
Cartridge cartridge;

protected override async Task OnInitializedAsync() {
this.frameBuffer = new byte[BASE_WIDTH * BASE_HEIGHT * BYTE_PER_PIXEL]; // RGBA32
this.emulateTimer = new System.Timers.Timer(1.0 / FPS * 1000);
this.emulateTimer.Elapsed += OnEmulate;
this.emulateTimer.Start();

await base.OnInitializedAsync();
}

protected override async Task OnAfterRenderAsync(bool firstRender) {
this.context = await this.canvasReference.CreateCanvas2DAsync();
await this.context.SetFillStyleAsync("black");
await this.context.FillRectAsync(0, 0, canvasWidth, canvasHeight);
await JSRuntime.InvokeAsync<object>("initEmulatorCanvas", null);

await base.OnAfterRenderAsync(firstRender);
}

private void OnEmulate(object sender, EventArgs e) {
var startMs = Environment.TickCount;
// TODO: Emulate here
var diffMs = Environment.TickCount - startMs;

// TODO: sound update
// TODO: 適当な頻度でcanvas更新を間引く
// TEST: とりあえず適当なFrameBufferのデータを作る
for (int j = 0; j < BASE_HEIGHT; j++) {
for (int i = 0; i < BASE_WIDTH; i++) {
var ptr = (j * BASE_WIDTH * BYTE_PER_PIXEL) + (i * BYTE_PER_PIXEL);
frameBuffer[ptr + 0] = (byte)((counter + i) & 0xff);
frameBuffer[ptr + 1] = (byte)((counter + j) & 0xff);
frameBuffer[ptr + 2] = (byte)((counter + i + j) & 0xff);
frameBuffer[ptr + 3] = 0xff;
}
}
// GCに移動されないよう固定してJSに渡す。終わったら捨てる
var gch = System.Runtime.InteropServices.GCHandle.Alloc(frameBuffer, System.Runtime.InteropServices.GCHandleType.Pinned);
var pinnedAddr = gch.AddrOfPinnedObject();
var jsRuntime = JSRuntime as Microsoft.JSInterop.WebAssembly.WebAssemblyJSRuntime;
jsRuntime.InvokeUnmarshalled<IntPtr,string>("drawEmulatorCanvas", pinnedAddr);
gch.Free();

counter++;
}
private void OnCanvasMouseMove(MouseEventArgs e) {
}

private void OnCanvasMouseDown(MouseEventArgs e) {
}

private void OnCanvasMouseUp(MouseEventArgs e) {
}

private void OnCanvasKeyDown(KeyboardEventArgs e) {
}

private void OnCanvasKeyUp(KeyboardEventArgs e) {
}

private void ChangeCanvasSize(float ratio) {
this.canvasWidth = (int)(ratio * BASE_WIDTH);
this.canvasHeight = (int)(ratio * BASE_HEIGHT);
Expand Down
5 changes: 2 additions & 3 deletions BlazeSnes/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ public class Program {
public static async Task Main(string[] args) {
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.Services
.AddBlazorise( options =>
{
.AddBlazorise(options => {
options.ChangeTextOnKeyPress = true;
} )
})
.AddFrolicProviders()
.AddFontAwesomeIcons()
.AddBlazorContextMenu()
Expand Down
2 changes: 2 additions & 0 deletions BlazeSnes/wwwroot/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
<script src="_content/Blazor.ContextMenu/blazorContextMenu.min.js"></script>
<script src="_content/Blazor.Extensions.Canvas/blazor.extensions.canvas.js"></script>

<script src="js/index.razor.js"></script>

<script src="_framework/blazor.webassembly.js"></script>
</body>

Expand Down
19 changes: 19 additions & 0 deletions BlazeSnes/wwwroot/js/index.razor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const baseWidth = 256;
const baseHeight = 224;
let canvas;
let context;
let imageData;

window.initEmulatorCanvas = function(e) {
canvas = document.getElementById('emulatorCanvas');
context = canvas.getContext('2d');
imageData = context.createImageData(baseWidth, baseHeight);
}
window.drawEmulatorCanvas = function(dataPtr) {
// console.log('drawEmulatorCanvas', dataPtr);
// convert from C# data
imageData.data.set(Uint8ClampedArray.from(Module.HEAPU8.subarray(dataPtr, dataPtr + imageData.data.length)));
context.putImageData(imageData, 0, 0);
// draw
context.drawImage(canvas, 0, 0, baseWidth, baseHeight, 0, 0, canvas.width, canvas.height);
};

0 comments on commit f700311

Please sign in to comment.