public Bitmap DrawOverview(LevelBlueprint level) { Bitmap img; try { img = Draw(level, -1); } catch (Exception) { img = Draw(null, -1); } Bitmap r = new Bitmap(img.Width + 16, img.Height + 48 + 48 + 16); using (Graphics g = Graphics.FromImage(r)) { g.Clear(Color.White); g.DrawImageUnscaled(img, 0, 16 + 48); g.DrawString(level.Name + ": " + level.FullName, new Font("Calibri", 28, FontStyle.Bold), Brushes.DarkRed, 24, 16 + 8); g.DrawString("{" + $"{ByteMath.SplitGuid(level.UniqueID).Item5:X12}" + "}", new Font("Courier New", 28, FontStyle.Bold), Brushes.DarkRed, 24, 16 + 8 + img.Height + 48); var kitRect = new RectangleF(img.Width - 16, 48, 32, 32); g.FillEllipse(COLORS_KITYPE[level.KIType - 10], kitRect); g.DrawString((level.KIType - 10).ToString(), new Font("Courier New", 24, FontStyle.Bold), Brushes.Black, kitRect, new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }); } return(r); }
public ushort Pop16() { var lower = this.Pop8(); var upper = this.Pop8(); return(ByteMath.MergeBytes(upper, lower)); }
public static byte Cast(object value, Dictionary <string, byte> variables) { try { return((byte)value); } catch (Exception e) { var math = new ByteMath(); return(math.TryCount(value, variables)); } }
public ReplayDoubleRegister( string upperName, string lowerName, ushort defaultValue, LockState defaultLockState = LockState.LOCKED) { this.name_ = "" + upperName + lowerName; var(upperDefaultValue, lowerDefaultValue) = ByteMath.SplitShort(defaultValue); this.Upper_R = new ReplaySingleRegister(upperName, upperDefaultValue, defaultLockState); this.Lower_R = new ReplaySingleRegister(lowerName, lowerDefaultValue, defaultLockState); this.registers_ = new[] { this.Upper_R, this.Lower_R }; }
private void TestFile_(string fileName) { var lcd = new Lcd { Active = false }; var serialBus = new SerialBus(); var ioAddresses = new IoAddresses(serialBus); var memoryMap = new MemoryMap(ioAddresses); var registers = new Registers(); var memory = new Mmu(memoryMap, registers); var cpu = new Cpu(lcd, memory, new Opcodes(memory)); ushort initialPc = 0; ushort finalPc = 0; var maxCycleCount = 100000000; LinkedList <Expected?>?expecteds = null; if (BlarggTest.COMPARE_TO_BINJGB_) { var expectedTracePath = "R:/Documents/CSharpWorkspace/FinCSharp/FinCSharpTests/tst/emulation/gb/blargg/" + fileName + ".txt"; expecteds = new LinkedList <Expected?>(); try { using (var sr = new StreamReader(expectedTracePath)) { string line; while ((line = sr.ReadLine()) != null) { var words = line.Split(' '); var expectedAHex = words[0].Substring(2); var expectedA = byte.Parse(expectedAHex, NumberStyles.HexNumber); var expectedFText = words[1].Substring(2); var expectedF = 0; if (expectedFText[0] != '-') { expectedF |= 1 << 7; } if (expectedFText[1] != '-') { expectedF |= 1 << 6; } if (expectedFText[2] != '-') { expectedF |= 1 << 5; } if (expectedFText[3] != '-') { expectedF |= 1 << 4; } var expectedAf = ByteMath.MergeBytes(expectedA, (byte)expectedF); var expectedBcHex = words[2].Substring(3); var expectedBc = ushort.Parse(expectedBcHex, NumberStyles.HexNumber); var expectedDeHex = words[3].Substring(3); var expectedDe = ushort.Parse(expectedDeHex, NumberStyles.HexNumber); var expectedHlHex = words[4].Substring(3); var expectedHl = ushort.Parse(expectedHlHex, NumberStyles.HexNumber); var expectedPcHex = words[6].Substring(3); //var expectedPcHex = line.Substring(47, 4); var expectedPc = ushort.Parse(expectedPcHex, NumberStyles.HexNumber); var expectedCyclesText = line.Substring(57, line.IndexOf( ')', 57) - 57); var expectedCycles = int.Parse(expectedCyclesText); var expectedSclText = words[9].Substring(4); var expectedScl = int.Parse(expectedSclText); var expectedPpuModeText = words[12].Substring(5); var expectedPpuMode = int.Parse(expectedPpuModeText); expecteds.AddLast(new Expected(expectedAf, expectedBc, expectedDe, expectedHl, expectedPc, expectedCycles, expectedScl, expectedPpuMode)); } } } catch (Exception e) { expecteds.Clear(); expecteds = null; } } var romPath = "R:/Documents/CSharpWorkspace/FinCSharp/FinCSharpTests/tst/emulation/gb/blargg/" + fileName + ".gb"; var romFile = LocalFile.At(romPath); var romData = LocalFileUtil.ReadBytes(romFile); memoryMap.Rom = new Rom(romData); var output = ""; serialBus.Bytes.Subscribe(b => { output += Convert.ToChar(b); }); var outputPath = "R:/Documents/CSharpWorkspace/FinCSharp/FinCSharpTests/tst/emulation/gb/blargg/output_" + fileName + ".txt"; using var writer = (BlarggTest.LOG_TRACE_) ? new StreamWriter(outputPath) : null; var pc = registers.Pc; initialPc = 0; finalPc = 0; var shouldGetPpuMode = BlarggTest.LOG_TRACE_ || BlarggTest.COMPARE_TO_BINJGB_; var lcdc = ioAddresses.Lcdc; var ly = ioAddresses.Ly; var instruction = 0; var cycles = 0; //try { var enumerator = expecteds?.GetEnumerator(); for (var i = 0; i < maxCycleCount; ++i) { var expected = enumerator?.Current; enumerator?.MoveNext(); var ppuMode = shouldGetPpuMode ? cpu.PpuMode : 0; initialPc = pc.Value; if (BlarggTest.LOG_TRACE_) { StringBuilder line = new StringBuilder(); line.AppendFormat("0x{0:x4}: ", initialPc); line.AppendFormat("{0:x2} |", memoryMap[initialPc]); line.AppendFormat(" af={0:x4}", registers.Af.Value); line.AppendFormat(" bc={0:x4}", registers.Bc.Value); line.AppendFormat(" de={0:x4}", registers.De.Value); line.AppendFormat(" hl={0:x4}", registers.Hl.Value); line.AppendFormat(" sp={0:x4}", registers.Sp.Value); line.AppendFormat(" pc={0:x4} |", registers.Pc.Value); line.AppendFormat(" tot={0} |", cycles); line.AppendFormat(" scl={0}", cpu.UpwardScanlineCycleCounter); line.AppendFormat(" st={0}", cpu.PpuModeCycleCount); line.AppendFormat(" cnt={0} |", cpu.ScanlineCycleCounter / 2); line.AppendFormat(" lcdc={0:x2}", lcdc.Value); line.AppendFormat(" ly={0:x2}", ly.Value); line.AppendFormat(" ppu={0:x1} |", ppuMode); line.AppendFormat(" div={0:x2}", ioAddresses.Div); line.AppendFormat(" tima={0:x2}", ioAddresses.Tima); line.AppendFormat(" tma={0:x2}", ioAddresses.Tma); line.AppendFormat(" tac={0:x2}", ioAddresses.Tac); writer.WriteLine(line.ToString()); } if (expected != null && (expected.Pc != initialPc || expected.Cycles != cycles || expected.Af != registers.Af.Value || expected.Bc != registers.Bc.Value || expected.De != registers.De.Value || expected.Hl != registers.Hl.Value || expected.Scl != cpu.UpwardScanlineCycleCounter || expected.PpuMode != ppuMode)) { var errorBuilder = new StringBuilder(); errorBuilder.Append("Difference at instruction: " + instruction + "\n"); errorBuilder.AppendFormat("Af: {0:x4}/{1:x4}\n", expected.Af, registers.Af.Value); errorBuilder.AppendFormat("Bc: {0:x4}/{1:x4}\n", expected.Bc, registers.Bc.Value); errorBuilder.AppendFormat("De: {0:x4}/{1:x4}\n", expected.De, registers.De.Value); errorBuilder.AppendFormat("Hl: {0:x4}/{1:x4}\n", expected.Hl, registers.Hl.Value); errorBuilder.AppendFormat("Pc: {0:x4}/{1:x4}\n", expected.Pc, initialPc); errorBuilder.AppendFormat("Cycles: {0}/{1}\n", expected.Cycles, cycles); errorBuilder.AppendFormat("Scl: {0}/{1}\n", expected.Scl, cpu.UpwardScanlineCycleCounter); errorBuilder.AppendFormat("Ppu Mode: {0}/{1}\n", expected.PpuMode, ppuMode); Assert.Fail(errorBuilder.ToString()); } cycles += cpu.ExecuteCycles(1); instruction++; finalPc = pc.Value; if (initialPc == finalPc && memory.HaltState != HaltState.HALTED) { break; } } /*} catch (Exception e) { * output = cycles + ", " + registers.Pc.Value + ": " + output; * throw e; * }*/ output = cycles + ", " + registers.Pc.Value + ": " + output; if (!output.Contains("Passed")) { Asserts.Fail(output); } }
public void BinaryDeserialize(BinaryReader br) { CustomMeta_MinLevelIntVersion = 0; CustomMeta_UserID = -1; CustomMeta_LevelID = -1; CustomMeta_Timestamp = DateTimeOffset.MinValue; byte schema = 0; var eof = false; byte[] id = new byte[1]; while (br.Read(id, 0, 1) > 0) { switch (id[0]) { case SERIALIZE_ID_SCHEMA: schema = br.ReadByte(); if (schema > SCHEMA_VERSION) { throw new Exception($"schema not supported ({schema} > {SCHEMA_VERSION})"); } break; case SERIALIZE_ID_CANNON: BlueprintCannons.Add(CannonBlueprint.Deserialize(br)); break; case SERIALIZE_ID_VOIDWALL: BlueprintVoidWalls.Add(VoidWallBlueprint.Deserialize(br)); break; case SERIALIZE_ID_VOIDCIRCLE: BlueprintVoidCircles.Add(VoidCircleBlueprint.Deserialize(br)); break; case SERIALIZE_ID_GLASSBLOCK: BlueprintGlassBlocks.Add(GlassBlockBlueprint.Deserialize(br)); break; case SERIALIZE_ID_BLACKHOLE: BlueprintBlackHoles.Add(BlackHoleBlueprint.Deserialize(br)); break; case SERIALIZE_ID_PORTAL: BlueprintPortals.Add(PortalBlueprint.Deserialize(br)); break; case SERIALIZE_ID_LASERCANNON: BlueprintLaserCannons.Add(LaserCannonBlueprint.Deserialize(br)); break; case SERIALIZE_ID_MIRRORBLOCK: BlueprintMirrorBlocks.Add(MirrorBlockBlueprint.Deserialize(br)); break; case SERIALIZE_ID_MIRRORCIRCLE: BlueprintMirrorCircles.Add(MirrorCircleBlueprint.Deserialize(br)); break; case SERIALIZE_ID_BACKGROUNDTEXT: BlueprintBackgroundText.Add(BackgroundTextBlueprint.Deserialize(br)); break; case SERIALIZE_ID_MINIGUN: BlueprintMinigun.Add(MinigunBlueprint.Deserialize(br)); break; case SERIALIZE_ID_SHIELDPROJECTOR: BlueprintShieldProjector.Add(ShieldProjectorBlueprint.Deserialize(br)); break; case SERIALIZE_ID_RELAY: BlueprintRelayCannon.Add(RelayCannonBlueprint.Deserialize(br)); break; case SERIALIZE_ID_TRISHOT: BlueprintTrishotCannon.Add(TrishotCannonBlueprint.Deserialize(br)); break; case SERIALIZE_ID_META: Name = br.ReadString(); FullName = br.ReadString(); UniqueID = new Guid(br.ReadBytes(16)); KIType = br.ReadByte(); WrapMode = br.ReadByte(); LevelWidth = br.ReadSingle(); LevelHeight = br.ReadSingle(); LevelViewX = br.ReadSingle(); LevelViewY = br.ReadSingle(); break; case SERIALIZE_ID_META_CUSTOM: CustomMusic = br.ReadInt32(); CustomMeta_MinLevelIntVersion = br.ReadUInt64(); CustomMeta_UserID = br.ReadInt32(); CustomMeta_Timestamp = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(br.ReadInt64()); CustomMeta_LevelID = br.ReadInt64(); break; case SERIALIZE_ID_EOF: if (br.ReadByte() != 0xB1) { throw new Exception("Missing footer byte 1"); } if (br.ReadByte() != 0x6B) { throw new Exception("Missing footer byte 2"); } if (br.ReadByte() != 0x00) { throw new Exception("Missing footer byte 3"); } if (br.ReadByte() != 0xB5) { throw new Exception("Missing footer byte 4"); } eof = true; break; default: throw new Exception("Unknown binary ID:" + id[0]); } if (eof) { break; } } if (!eof) { throw new Exception("Unexpected binary file end"); } if (schema == 0) { // no schema } else if (schema == 1) { if (CustomMeta_LevelID > 0) { // Fix wrong LevelID Serialization in schema-1 :/ var uid = ByteMath.SplitGuid(UniqueID); var a = uid.Item1; var b = uid.Item2; var c = uid.Item3; var d = uid.Item4; var e = uid.Item5; e = Convert.ToUInt64($"{e:X}", 10); UniqueID = ByteMath.JoinGuid(a, b, c, d, e); } } }
public void Push16(ushort value) { var(upper, lower) = ByteMath.SplitShort(value); this.Push8(upper); this.Push8(lower); }
private void DrawBg_() { var memoryMap = this.MemoryMap; var ioAddresses = this.IoAddresses; var lcdc = ioAddresses.Lcdc.Value; var wy = ioAddresses.Wy.Value; var ly = ioAddresses.Ly.Value; //window enabled and scanline within window ? var useWindow = (lcdc & (1 << 5)) != 0 && wy <= ly; byte y; int backgroundAddress; if (useWindow) { y = (byte)(ly - wy); //Window Tile Map Display Select backgroundAddress = ((lcdc & (1 << 6)) != 0) //0x9c00 ? 0x1C00 //0x9800 : 0x1800; } //not using window else { y = (byte)(ioAddresses.ScrollY.Value + ly); //Window Tile Map Display Select backgroundAddress = ((lcdc & (1 << 3)) != 0) //0x9c00 ? 0x1C00 //0x9800 : 0x1800; } // each vertical line takes up two bytes of memory var tileLine = (byte)((y & 7) * 2); //TODO: testing divide by 8 == multiply by 0.125 //rowPos o current scanline (of the 8 pixels) var tileRow = (ushort)(y / 8 * 32); var scX = ioAddresses.ScrollX.Value; var wX = (byte)(ioAddresses.Wx.Value - 7); var areTileAddressesSigned = (lcdc & (1 << 4)) == 0; byte upper = 0; byte lower = 0; var bgp = ioAddresses.Bgp.Value; var vram = memoryMap.Vram; //draw de 160 pixels in current line TODO: (4 by 4) for (var p = 0; p < 160; p++) { var x = useWindow && p > wX ? (byte)(p - wX) : (byte)(p + scX); if ((p & 7) == 0 || ((p + scX) & 7) == 0) { var tileCol = (ushort)(x / 8); var tileNumber = vram[(ushort)(backgroundAddress + tileRow + tileCol)]; ushort tileAddress; if (!areTileAddressesSigned) { tileAddress = (ushort)(0x000 + tileNumber * 16); } else { tileAddress = (ushort)(0x800 + (128 + ByteMath.ByteToSByte(tileNumber)) * 16); } var vramAddress = (ushort)(tileAddress + tileLine); lower = vram[vramAddress]; upper = vram[(ushort)(vramAddress + 1)]; } var colorBit = (byte)(7 - (x & 7)); var colorId = this.GetColorId_(colorBit, lower, upper); var color = this.GetColor_(bgp, colorId); //draw this.lcd_.SetPixel(p, ly, color); } }