From b1761816a68f43e862cf9fb6741a8c638c37700b Mon Sep 17 00:00:00 2001 From: VladimirMakeev Date: Tue, 11 Nov 2025 15:37:21 +0300 Subject: [PATCH 01/10] Translate player help on first turn --- src/CivGame/Game/Segment_1238.cs | 84 ++++++++++++++++---------------- 1 file changed, 41 insertions(+), 43 deletions(-) diff --git a/src/CivGame/Game/Segment_1238.cs b/src/CivGame/Game/Segment_1238.cs index deca65a..e8f6775 100644 --- a/src/CivGame/Game/Segment_1238.cs +++ b/src/CivGame/Game/Segment_1238.cs @@ -87,64 +87,62 @@ public void F0_1238_0092() // Instruction address 0x1238:0x009f, size: 5 this.oParent.Segment_2dc4.F0_2dc4_0626(); - this.oCPU.AX.Word = (ushort)this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].Coins; - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x1a), this.oCPU.AX.Word); + short playerCoins = this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].Coins; this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0xd760, 0); this.oParent.Var_6b92 = 0; this.oParent.CivState.MaximumTechnologyCount = 0; + + // Active players = 0 this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0xde20, 0); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), 0); - L00c2: - this.oCPU.AX.Word = 0x1; - this.oCPU.CX.Low = this.oCPU.ReadUInt8(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)); - this.oCPU.AX.Word = this.oCPU.SHL_UInt16(this.oCPU.AX.Word, this.oCPU.CX.Low); - this.oCPU.TEST_UInt16(this.oCPU.AX.Word, (ushort)this.oParent.CivState.ActiveCivilizations); - if (this.oCPU.Flags.E) goto L00e7; - this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0xde20, this.oCPU.INC_UInt16(this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xde20))); - this.oCPU.SI.Word = (ushort)this.oParent.CivState.Players[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].DiscoveredTechnologyCount; + short playerID = 0; - if (this.oParent.CivState.MaximumTechnologyCount < (short)this.oCPU.SI.Word) + for (playerID = 0; playerID < 8; ++playerID) { - this.oParent.CivState.MaximumTechnologyCount = (short)this.oCPU.SI.Word; + if ((this.oParent.CivState.ActiveCivilizations & (1 << playerID)) == 0) + { + continue; + } + + // Count active players + this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0xde20, this.oCPU.INC_UInt16(this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xde20))); + + short discoveredCount = this.oParent.CivState.Players[playerID].DiscoveredTechnologyCount; + if (this.oParent.CivState.MaximumTechnologyCount < discoveredCount) + { + this.oParent.CivState.MaximumTechnologyCount = discoveredCount; + } } - L00e7: - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), - this.oCPU.INC_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)))); - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)), 0x8); - if (this.oCPU.Flags.L) goto L00c2; - if (this.oParent.CivState.TurnCount != 0) goto L0147; - - this.oCPU.AX.Word = 0x600; - this.oCPU.IMUL_UInt16(this.oCPU.AX, this.oCPU.DX, (ushort)this.oParent.CivState.HumanPlayerID); - this.oCPU.SI.Word = this.oCPU.AX.Word; - - this.oParent.Var_d4cc_XPos = - (short)(this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].Units[0].Position.X - 7); - - this.oParent.Var_d75e_YPos = - (short)(this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].Units[0].Position.Y - 6); + if (this.oParent.CivState.TurnCount == 0) + { + Player humanPlayer = this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID]; + Unit startingUnit = humanPlayer.Units[0]; - // Instruction address 0x1238:0x0119, size: 3 - F0_1238_1b44(); - - if (this.oParent.CivState.DifficultyLevel != 0) goto L013b; + // Center camera on starting unit + this.oParent.Var_d4cc_XPos = (short)(startingUnit.Position.X - 7); + this.oParent.Var_d75e_YPos = (short)(startingUnit.Position.Y - 6); - // Instruction address 0x1238:0x012a, size: 5 - this.oParent.Segment_1403.F0_1403_4060(this.oParent.CivState.HumanPlayerID, 0); + // Instruction address 0x1238:0x0119, size: 3 + F0_1238_1b44(); - this.oParent.MainIntro.F2_0000_17d9(); + if (this.oParent.CivState.DifficultyLevel == 0) + { + // Instruction address 0x1238:0x012a, size: 5 + this.oParent.Segment_1403.F0_1403_4060(this.oParent.CivState.HumanPlayerID, 0); - // Instruction address 0x1238:0x0138, size: 3 - F0_1238_1b44(); + // Show UI help on first turn + this.oParent.MainIntro.F2_0000_17d9(); - L013b: - // Instruction address 0x1238:0x013f, size: 5 - this.oParent.Segment_1000.F0_1000_0a32_PlayTune(1, 0); + // Instruction address 0x1238:0x0138, size: 3 + F0_1238_1b44(); + } + + // Instruction address 0x1238:0x013f, size: 5 + this.oParent.Segment_1000.F0_1000_0a32_PlayTune(1, 0); + } - L0147: this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), 0x0); goto L026a; @@ -324,7 +322,7 @@ public void F0_1238_0092() this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].Coins >= 100) goto L036d; this.oCPU.AX.Word = (ushort)this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].Coins; - this.oCPU.AX.Word = this.oCPU.SUB_UInt16(this.oCPU.AX.Word, this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x1a))); + this.oCPU.AX.Word = this.oCPU.SUB_UInt16(this.oCPU.AX.Word, (ushort)playerCoins); this.oCPU.CX.Word = 0xa; this.oCPU.IMUL_UInt16(this.oCPU.AX, this.oCPU.DX, this.oCPU.CX.Word); this.oCPU.AX.Word = this.oCPU.ADD_UInt16(this.oCPU.AX.Word, (ushort)this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].Coins); From 277f2d5df20998217e3277ed0ead35f6d0e47a95 Mon Sep 17 00:00:00 2001 From: VladimirMakeev Date: Wed, 12 Nov 2025 19:06:10 +0300 Subject: [PATCH 02/10] Translate player turns loop --- src/CivGame/Game/Segment_1238.cs | 197 +++++++++++++++---------------- 1 file changed, 94 insertions(+), 103 deletions(-) diff --git a/src/CivGame/Game/Segment_1238.cs b/src/CivGame/Game/Segment_1238.cs index e8f6775..6b058e0 100644 --- a/src/CivGame/Game/Segment_1238.cs +++ b/src/CivGame/Game/Segment_1238.cs @@ -143,136 +143,127 @@ public void F0_1238_0092() this.oParent.Segment_1000.F0_1000_0a32_PlayTune(1, 0); } - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), 0x0); - goto L026a; + for (playerID = 0; playerID < 8; ++playerID) + { + this.oParent.CivState.Players[playerID].Score = 0; - L014f: - // Instruction address 0x1238:0x0164, size: 5 - this.oParent.Segment_1000.F0_1000_0bfa_FillRectangle(this.oParent.Var_aa_Rectangle, 2, 192, 6, 6, 8); + if ((this.oParent.CivState.ActiveCivilizations & (1 << playerID)) == 0) + { + continue; + } - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x16), 0x0); - this.oCPU.AX.Word = (ushort)this.oParent.CivState.HumanPlayerID; - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)), this.oCPU.AX.Word); - if (this.oCPU.Flags.NE) goto L0183; + if (playerID < this.oParent.CivState.HumanPlayerID && this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdf60) != 0) + { + continue; + } - // Instruction address 0x1238:0x0179, size: 5 - this.oParent.Segment_11a8.F0_11a8_0250(); + // Blink 'wait' status at the bottom left corner of the screen + // Instruction address 0x1238:0x0164, size: 5 + this.oParent.Segment_1000.F0_1000_0bfa_FillRectangle(this.oParent.Var_aa_Rectangle, 2, 192, 6, 6, 8); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x16), 0x1); + bool playerIsHuman = false; - L0183: - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdf60), 0x0); - if (this.oCPU.Flags.NE) goto L0195; - - // Instruction address 0x1238:0x018d, size: 5 - this.oParent.Segment_1ade.F0_1ade_0006(this.oCPU.ReadInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))); - - L0195: - if (this.oParent.CivState.Players[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].Coins > 0x7530) - { - this.oParent.CivState.Players[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].Coins = 0x7530; - } + if (this.oParent.CivState.HumanPlayerID == playerID) + { + // Instruction address 0x1238:0x0179, size: 5 + this.oParent.Segment_11a8.F0_11a8_0250(); - // Instruction address 0x1238:0x01ab, size: 5 - this.oParent.Segment_2517.F0_2517_0004(this.oCPU.ReadInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))); + playerIsHuman = true; + } - // Instruction address 0x1238:0x01b6, size: 5 - this.oParent.Segment_25fb.F0_25fb_0004(this.oCPU.ReadInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))); + if (this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdf60) == 0) + { + // Instruction address 0x1238:0x018d, size: 5 + this.oParent.Segment_1ade.F0_1ade_0006(playerID); + } - // Instruction address 0x1238:0x01c1, size: 5 - this.oParent.Segment_25fb.F0_25fb_2fd7(this.oCPU.ReadInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))); + if (this.oParent.CivState.Players[playerID].Coins > 30000) + { + this.oParent.CivState.Players[playerID].Coins = 30000; + } - // Instruction address 0x1238:0x01de, size: 5 - this.oParent.Segment_1000.F0_1000_0bfa_FillRectangle(this.oParent.Var_aa_Rectangle, 2, 192, 6, 6, 15); + // Instruction address 0x1238:0x01ab, size: 5 + this.oParent.Segment_2517.F0_2517_0004(playerID); - this.oCPU.AX.Word = (ushort)this.oParent.CivState.HumanPlayerID; - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)), this.oCPU.AX.Word); - if (this.oCPU.Flags.NE) goto L0225; + // Instruction address 0x1238:0x01b6, size: 5 + this.oParent.Segment_25fb.F0_25fb_0004(playerID); - // Instruction address 0x1238:0x01ef, size: 3 - F0_1238_107e(); + // Instruction address 0x1238:0x01c1, size: 5 + this.oParent.Segment_25fb.F0_25fb_2fd7(playerID); - this.oCPU.SI.Word = this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)); - this.oCPU.SI.Word = this.oCPU.SHL_UInt16(this.oCPU.SI.Word, 0x1); - - if (this.oParent.CivState.Players[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].CityCount != 0 || - this.oParent.CivState.Players[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].SettlerCount != 0) - goto L021a; + // Blink 'wait' status + // Instruction address 0x1238:0x01de, size: 5 + this.oParent.Segment_1000.F0_1000_0bfa_FillRectangle(this.oParent.Var_aa_Rectangle, 2, 192, 6, 6, 15); - // Instruction address 0x1238:0x0205, size: 5 - this.oParent.Segment_11a8.F0_11a8_0268(); - - this.oParent.MainIntro.F2_0000_152a(); + if (playerID == this.oParent.CivState.HumanPlayerID) + { + // Instruction address 0x1238:0x01ef, size: 3 + F0_1238_107e(); - this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0xdc48, 0xffff); + if (this.oParent.CivState.Players[playerID].CityCount == 0 && this.oParent.CivState.Players[playerID].SettlerCount == 0) + { + // Human player lost the game - // Instruction address 0x1238:0x0215, size: 5 - this.oParent.Segment_11a8.F0_11a8_0250(); + // Instruction address 0x1238:0x0205, size: 5 + this.oParent.Segment_11a8.F0_11a8_0268(); - L021a: - if (this.oParent.CivState.Year <= 0) goto L0225; - oParent.CivState.PeaceTurnCount++; + this.oParent.MainIntro.F2_0000_152a(); - L0225: - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdc48), 0x0); - if (this.oCPU.Flags.NE) goto L0237; + // game state = player lost + this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0xdc48, 0xffff); - // Instruction address 0x1238:0x022f, size: 5 - this.oParent.Segment_1403.F0_1403_000e(this.oCPU.ReadInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))); + // Instruction address 0x1238:0x0215, size: 5 + this.oParent.Segment_11a8.F0_11a8_0250(); + } - L0237: - this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0xdf60, 0x0); - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x16)), 0x0); - if (this.oCPU.Flags.E) goto L0248; + if (this.oParent.CivState.Year > 0) + { + oParent.CivState.PeaceTurnCount++; + } + } - // Instruction address 0x1238:0x0243, size: 5 - this.oParent.Segment_11a8.F0_11a8_0268(); + // Check if game continues + if (this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdc48) == 0) + { + // Handles player turn. + // Handles human player input and waits for end of turn if option selected - L0248: - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdc48), 0x0); - if (this.oCPU.Flags.E) goto L0267; - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xb884), 0x0); - if (this.oCPU.Flags.NE) goto L0267; - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdc48), 0x2); - if (this.oCPU.Flags.E) goto L0260; - goto L089a; + // Instruction address 0x1238:0x022f, size: 5 + this.oParent.Segment_1403.F0_1403_000e(playerID); + } - L0260: - // Instruction address 0x1238:0x0261, size: 3 - F0_1238_08a0(); + this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0xdf60, 0x0); - goto L0896; + if (!playerIsHuman) + { + // Instruction address 0x1238:0x0243, size: 5 + this.oParent.Segment_11a8.F0_11a8_0268(); + } - L0267: - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), - this.oCPU.INC_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)))); + // Check if game should continue with the next player + if (this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdc48) == 0 || this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xb884) != 0) + { + continue; + } - L026a: - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)), 0x8); - if (this.oCPU.Flags.GE) goto L02a0; - this.oParent.CivState.Players[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].Score = 0; - this.oCPU.AX.Word = 0x1; - this.oCPU.CX.Low = this.oCPU.ReadUInt8(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)); - this.oCPU.AX.Word = this.oCPU.SHL_UInt16(this.oCPU.AX.Word, this.oCPU.CX.Low); - this.oCPU.TEST_UInt16(this.oCPU.AX.Word, (ushort)this.oParent.CivState.ActiveCivilizations); - if (this.oCPU.Flags.E) goto L0267; - this.oCPU.AX.Word = (ushort)this.oParent.CivState.HumanPlayerID; - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)), this.oCPU.AX.Word); - if (this.oCPU.Flags.L) goto L0294; - goto L014f; + if (this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdc48) == 2) + { + // Human player decided to retire + // Show power graph, civilization score and hall of fame - L0294: - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdf60), 0x0); - if (this.oCPU.Flags.NE) goto L029e; - goto L014f; + // Instruction address 0x1238:0x0261, size: 3 + F0_1238_08a0(); - L029e: - goto L0267; + goto showAds; + } - L02a0: + goto exit; + } + // Instruction address 0x1238:0x02a0, size: 5 this.oParent.Segment_11a8.F0_11a8_0250(); + // Process barbarian raids // Instruction address 0x1238:0x02a6, size: 3 F0_1238_0980(); @@ -652,7 +643,7 @@ public void F0_1238_0092() this.oCPU.AX.Word = this.oCPU.SUB_UInt16(this.oCPU.AX.Word, 0x834); this.oCPU.AX.Word = this.oCPU.NEG_UInt16(this.oCPU.AX.Word); if ((short)this.oCPU.AX.Word == this.oParent.CivState.Year) goto L073b; - goto L089a; + goto exit; L073b: // Instruction address 0x1238:0x073b, size: 5 @@ -747,13 +738,13 @@ public void F0_1238_0092() L088f: this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdc48), 0x0); - if (this.oCPU.Flags.E) goto L089a; + if (this.oCPU.Flags.E) goto exit; - L0896: + showAds: // Instruction address 0x1238:0x0897, size: 3 F0_1238_090a(); - L089a: + exit: this.oCPU.SI.Word = this.oCPU.POP_UInt16(); this.oCPU.DI.Word = this.oCPU.POP_UInt16(); this.oCPU.SP.Word = this.oCPU.BP.Word; From 14470799e641bb96636fcf23cad3774d82ad9b7d Mon Sep 17 00:00:00 2001 From: VladimirMakeev Date: Sat, 15 Nov 2025 23:37:02 +0300 Subject: [PATCH 03/10] Translate city disasters loop --- src/CivGame/Game/Segment_1238.cs | 46 +++++++++++++------------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/src/CivGame/Game/Segment_1238.cs b/src/CivGame/Game/Segment_1238.cs index 6b058e0..efd425f 100644 --- a/src/CivGame/Game/Segment_1238.cs +++ b/src/CivGame/Game/Segment_1238.cs @@ -270,37 +270,27 @@ public void F0_1238_0092() // Instruction address 0x1238:0x02aa, size: 3 F0_1238_1767(); - if (this.oParent.CivState.TurnCount <= 50) goto L0306; - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), 0x0); - goto L02c9; - - L02bb: - this.oParent.Overlay_20.F20_0000_0540(this.oCPU.ReadInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))); - - L02c6: - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), - this.oCPU.INC_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)))); - - L02c9: - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)), 0x2); - if (this.oCPU.Flags.GE) goto L0306; - - // Instruction address 0x1238:0x02d3, size: 5 - this.oCPU.AX.Word = (ushort)(this.oParent.MSCAPI.RNG.Next(128)); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), this.oCPU.AX.Word); + if (this.oParent.CivState.TurnCount > 50) + { + for (short cityID = 0; cityID < 2; ++cityID) + { + // Instruction address 0x1238:0x02d3, size: 5 + cityID = (short)this.oParent.MSCAPI.RNG.Next(128); - this.oCPU.AX.Word = 0x1c; - this.oCPU.IMUL_UInt16(this.oCPU.AX, this.oCPU.DX, this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))); - this.oCPU.SI.Word = this.oCPU.AX.Word; - - if (this.oParent.CivState.Cities[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].StatusFlag == 0xff || - this.oParent.CivState.Players[this.oParent.CivState.Cities[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].PlayerID].CityCount <= 1) - goto L02c6; + if (this.oParent.CivState.Cities[cityID].StatusFlag == 0xff || + this.oParent.CivState.Players[this.oParent.CivState.Cities[cityID].PlayerID].CityCount <= 1) + { + continue; + } - if (this.oParent.CivState.Cities[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].ActualSize >= 5) goto L02bb; - goto L02c6; + if (this.oParent.CivState.Cities[cityID].ActualSize >= 5) + { + // Process city disasters and riots + this.oParent.Overlay_20.F20_0000_0540(cityID); + } + } + } - L0306: // Instruction address 0x1238:0x0307, size: 3 F0_1238_0da1(); From 5bc6dcde2175ea9dd7ef9149aef39f3851a549ee Mon Sep 17 00:00:00 2001 From: VladimirMakeev Date: Mon, 17 Nov 2025 02:11:08 +0300 Subject: [PATCH 04/10] Translate low funds report logic --- src/CivGame/Game/Segment_1238.cs | 51 +++++++++++++------------------- 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/src/CivGame/Game/Segment_1238.cs b/src/CivGame/Game/Segment_1238.cs index efd425f..7e4f587 100644 --- a/src/CivGame/Game/Segment_1238.cs +++ b/src/CivGame/Game/Segment_1238.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using Avalonia.Media; using IRB.VirtualCPU; @@ -87,7 +88,8 @@ public void F0_1238_0092() // Instruction address 0x1238:0x009f, size: 5 this.oParent.Segment_2dc4.F0_2dc4_0626(); - short playerCoins = this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].Coins; + Player humanPlayer = this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID]; + short initialCoins = humanPlayer.Coins; this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0xd760, 0); this.oParent.Var_6b92 = 0; @@ -117,7 +119,6 @@ public void F0_1238_0092() if (this.oParent.CivState.TurnCount == 0) { - Player humanPlayer = this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID]; Unit startingUnit = humanPlayer.Units[0]; // Center camera on starting unit @@ -276,14 +277,14 @@ public void F0_1238_0092() { // Instruction address 0x1238:0x02d3, size: 5 cityID = (short)this.oParent.MSCAPI.RNG.Next(128); + City city = this.oParent.CivState.Cities[cityID]; - if (this.oParent.CivState.Cities[cityID].StatusFlag == 0xff || - this.oParent.CivState.Players[this.oParent.CivState.Cities[cityID].PlayerID].CityCount <= 1) + if (city.StatusFlag == 0xff || this.oParent.CivState.Players[city.PlayerID].CityCount <= 1) { continue; } - if (this.oParent.CivState.Cities[cityID].ActualSize >= 5) + if (city.ActualSize >= 5) { // Process city disasters and riots this.oParent.Overlay_20.F20_0000_0540(cityID); @@ -294,36 +295,24 @@ public void F0_1238_0092() // Instruction address 0x1238:0x0307, size: 3 F0_1238_0da1(); - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdc48), 0x0); - if (this.oCPU.Flags.NE) goto L036d; - this.oCPU.SI.Word = (ushort)this.oParent.CivState.HumanPlayerID; - this.oCPU.SI.Word = this.oCPU.SHL_UInt16(this.oCPU.SI.Word, 0x1); - - if (this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].CityCount <= 1 || - this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].Coins >= 100) goto L036d; + if (this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdc48) == 0 + && humanPlayer.CityCount > 1 && humanPlayer.Coins < 100 + && (humanPlayer.Coins - initialCoins) * 10 + humanPlayer.Coins < 0 + && (this.oParent.CivState.PlayerFlags & (1 << this.oParent.CivState.HumanPlayerID)) != 0) + { + this.oCPU.WriteUInt8(this.oCPU.DS.Word, 0xba06, 0x0); - this.oCPU.AX.Word = (ushort)this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].Coins; - this.oCPU.AX.Word = this.oCPU.SUB_UInt16(this.oCPU.AX.Word, (ushort)playerCoins); - this.oCPU.CX.Word = 0xa; - this.oCPU.IMUL_UInt16(this.oCPU.AX, this.oCPU.DX, this.oCPU.CX.Word); - this.oCPU.AX.Word = this.oCPU.ADD_UInt16(this.oCPU.AX.Word, (ushort)this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].Coins); - if (this.oCPU.Flags.NS) goto L036d; - this.oCPU.AX.Word = 0x1; - this.oCPU.CX.Low = (byte)(this.oParent.CivState.HumanPlayerID & 0xff); - this.oCPU.AX.Word = this.oCPU.SHL_UInt16(this.oCPU.AX.Word, this.oCPU.CX.Low); - this.oCPU.TEST_UInt16(this.oCPU.AX.Word, (ushort)this.oParent.CivState.PlayerFlags); - if (this.oCPU.Flags.E) goto L036d; - this.oCPU.WriteUInt8(this.oCPU.DS.Word, 0xba06, 0x0); + // Warning: Funds are running low... - // Instruction address 0x1238:0x034f, size: 5 - this.oParent.Segment_2f4d.F0_2f4d_044f(0x1c2a); + // Instruction address 0x1238:0x034f, size: 5 + this.oParent.Segment_2f4d.F0_2f4d_044f(0x1c2a); - this.oParent.Var_2f9e_MessageBoxStyle = ReportTypeEnum.DomesticAdvisor; + this.oParent.Var_2f9e_MessageBoxStyle = ReportTypeEnum.DomesticAdvisor; - // Instruction address 0x1238:0x0367, size: 3 - F0_1238_001e_ShowDialog(0xba06, 80, 80); + // Instruction address 0x1238:0x0367, size: 3 + F0_1238_001e_ShowDialog(0xba06, 80, 80); + } - L036d: oParent.CivState.TurnCount++; if (this.oParent.CivState.Year >= 1000) goto L0380; this.oParent.CivState.Year += 20; @@ -1217,7 +1206,7 @@ public void F0_1238_0980() /// /// ? /// - public void F0_1238_0da1() + private void F0_1238_0da1() { this.oCPU.Log.EnterBlock("F0_1238_0da1()"); From 645875184f6e90f33fa6a2815499e074d2fe934f Mon Sep 17 00:00:00 2001 From: VladimirMakeev Date: Mon, 1 Dec 2025 22:01:22 +0300 Subject: [PATCH 05/10] Translate some more --- src/CivGame/Game/Segment_1238.cs | 320 ++++++++++++++++--------------- 1 file changed, 166 insertions(+), 154 deletions(-) diff --git a/src/CivGame/Game/Segment_1238.cs b/src/CivGame/Game/Segment_1238.cs index af07d0b..6034fd6 100644 --- a/src/CivGame/Game/Segment_1238.cs +++ b/src/CivGame/Game/Segment_1238.cs @@ -98,9 +98,7 @@ public void F0_1238_0092() // Active players = 0 this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0xde20, 0); - short playerID = 0; - - for (playerID = 0; playerID < 8; ++playerID) + for (int playerID = 0; playerID < 8; ++playerID) { if ((this.oParent.CivState.ActiveCivilizations & (1 << playerID)) == 0) { @@ -138,12 +136,12 @@ public void F0_1238_0092() // Instruction address 0x1238:0x0138, size: 3 F0_1238_1b44(); } - + // Instruction address 0x1238:0x013f, size: 5 this.oParent.Segment_1000.F0_1000_0a32_PlayTune(1, 0); } - for (playerID = 0; playerID < 8; ++playerID) + for (short playerID = 0; playerID < 8; ++playerID) { this.oParent.CivState.Players[playerID].Score = 0; @@ -159,7 +157,7 @@ public void F0_1238_0092() // Blink 'wait' status at the bottom left corner of the screen // Instruction address 0x1238:0x0164, size: 5 - this.oParent.Segment_1000.F0_1000_0bfa_FillRectangle(this.oParent.Var_aa_Rectangle, 2, 192, 6, 6, 8); + this.oParent.Segment_1000.F0_1000_0bfa_FillRectangle(this.oParent.Var_aa_Rectangle, 2, 192, 6, 6, 8); bool playerIsHuman = false; @@ -193,7 +191,7 @@ public void F0_1238_0092() // Blink 'wait' status // Instruction address 0x1238:0x01de, size: 5 - this.oParent.Segment_1000.F0_1000_0bfa_FillRectangle(this.oParent.Var_aa_Rectangle, 2, 192, 6, 6, 15); + this.oParent.Segment_1000.F0_1000_0bfa_FillRectangle(this.oParent.Var_aa_Rectangle, 2, 192, 6, 6, 15); if (playerID == this.oParent.CivState.HumanPlayerID) { @@ -259,7 +257,7 @@ public void F0_1238_0092() goto exit; } - + // Instruction address 0x1238:0x02a0, size: 5 this.oParent.Segment_11a8.F0_11a8_0250(); @@ -313,176 +311,190 @@ public void F0_1238_0092() } oParent.CivState.TurnCount++; - if (this.oParent.CivState.Year >= 1000) goto L0380; - this.oParent.CivState.Year += 20; - goto L03b8; - - L0380: - if (this.oParent.CivState.Year >= 1500) goto L038f; - this.oParent.CivState.Year += 10; - goto L03b8; - - L038f: - if (this.oParent.CivState.Year >= 1750) goto L039e; - this.oParent.CivState.Year += 5; - goto L03b8; - - L039e: - if (this.oParent.CivState.Year >= 1850) goto L03b4; - this.oCPU.TEST_UInt8((byte)(this.oParent.CivState.SpaceshipFlags & 0xff), 0xfe); - if (this.oCPU.Flags.NE) goto L03b4; - this.oParent.CivState.Year += 2; - goto L03b8; - - L03b4: - this.oParent.CivState.Year += 1; - - L03b8: - if (oParent.CivState.Year != 0) goto L03dc; - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), 0x0); - - L03c4: - this.oCPU.BX.Word = this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)); - this.oCPU.BX.Word = this.oCPU.SHL_UInt16(this.oCPU.BX.Word, 0x1); - this.oParent.CivState.Players[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].ResearchProgress <<= 1; - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), - this.oCPU.INC_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)))); - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)), 0x8); - if (this.oCPU.Flags.L) goto L03c4; - this.oParent.CivState.Year = 1; - - L03dc: - if (this.oParent.CivState.Year != 21) goto L03e9; - this.oParent.CivState.Year = 20; - L03e9: - this.oCPU.AX.Word = (ushort)oParent.CivState.TurnCount; - this.oCPU.CWD(this.oCPU.AX, this.oCPU.DX); - this.oCPU.CX.Word = 0x32; - this.oCPU.IDIV_UInt16(this.oCPU.AX, this.oCPU.DX, this.oCPU.CX.Word); - this.oCPU.DX.Word = this.oCPU.OR_UInt16(this.oCPU.DX.Word, this.oCPU.DX.Word); - if (this.oCPU.Flags.E) goto L03f9; - goto L055e; - - L03f9: - this.oCPU.CMP_UInt16((ushort)this.oParent.CivState.HumanPlayerID, 0xffff); - if (this.oCPU.Flags.NE) goto L0416; - goto L055e; - - L0416: - if (!this.oParent.CivState.GameSettingFlags.AutoSave) goto L0439; + if (this.oParent.CivState.Year < 1000) + { + this.oParent.CivState.Year += 20; + } + else if (this.oParent.CivState.Year < 1500) + { + this.oParent.CivState.Year += 10; + } + else if (this.oParent.CivState.Year < 1750) + { + this.oParent.CivState.Year += 5; + } + else if (this.oParent.CivState.Year < 1850) + { + this.oParent.CivState.Year += (short)((((this.oParent.CivState.SpaceshipFlags & 0xff) & 0xfe) != 0) ? 1 : 2); + } + else + { + this.oParent.CivState.Year += 1; + } - this.oParent.GameLoadAndSave.F11_0000_036a((ushort)((((this.oParent.CivState.TurnCount / 50) - 1) % 6) + 4)); + if (oParent.CivState.Year == 0) + { + for (int playerID = 0; playerID < 8; ++playerID) + { + this.oParent.CivState.Players[playerID].ResearchProgress <<= 1; + } - L0439: - this.oParent.CivState.MaximumTechnologyCount = 0; - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), 0x1); + this.oParent.CivState.Year = 1; + } - L0444: - this.oCPU.SI.Word = (ushort)this.oParent.CivState.Players[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].DiscoveredTechnologyCount; - if (this.oParent.CivState.MaximumTechnologyCount < (short)this.oCPU.SI.Word) + if (this.oParent.CivState.Year == 21) { - this.oParent.CivState.MaximumTechnologyCount = (short)this.oCPU.SI.Word; + this.oParent.CivState.Year = 20; } - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), this.oCPU.INC_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)))); - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)), 0x8); - if (this.oCPU.Flags.L) goto L0444; + if (oParent.CivState.TurnCount % 50 == 0 && this.oParent.CivState.HumanPlayerID != -1) + { + if (this.oParent.CivState.GameSettingFlags.AutoSave) + { + this.oParent.GameLoadAndSave.F11_0000_036a((ushort)((((this.oParent.CivState.TurnCount / 50) - 1) % 6) + 4)); + } - this.oParent.Var_d2de = 0; - - if (this.oParent.CivState.Year < 0) goto L048f; + this.oParent.CivState.MaximumTechnologyCount = 0; - // Instruction address 0x1238:0x0484, size: 5 - this.oParent.Segment_2dc4.F0_2dc4_007c_CheckValueRange( - this.oParent.CivState.MaximumTechnologyCount - (this.oParent.CivState.TurnCount / 9), - 0, 6); + for (int i = 1; i < 8; ++i) + { + short techCount = this.oParent.CivState.Players[i].DiscoveredTechnologyCount; + if (this.oParent.CivState.MaximumTechnologyCount < techCount) + { + this.oParent.CivState.MaximumTechnologyCount = techCount; + } + } - this.oParent.Var_d2de = (short)this.oCPU.AX.Word; + // Instruction address 0x1238:0x0484, size: 5 + this.oParent.Var_d2de = this.oParent.CivState.Year >= 0 + ? this.oParent.Segment_2dc4.F0_2dc4_007c_CheckValueRange(this.oParent.CivState.MaximumTechnologyCount - (this.oParent.CivState.TurnCount / 9), 0, 6) + : 0; - L048f: - // Instruction address 0x1238:0x0493, size: 5 - this.oParent.Segment_2dc4.F0_2dc4_02cd(this.oParent.CivState.HumanPlayerID); + // Instruction address 0x1238:0x0493, size: 5 + ushort population = this.oParent.Segment_2dc4.F0_2dc4_02cd(this.oParent.CivState.HumanPlayerID); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x18), this.oCPU.AX.Word); + // Instruction address 0x1238:0x04c8, size: 5 + this.oParent.Segment_1866.F0_1866_250e_AddReplayData(11, + (byte)this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].CityCount, + (byte)((population & 0xff00) >> 8), + (byte)(population & 0xff)); - // Instruction address 0x1238:0x04c8, size: 5 - this.oParent.Segment_1866.F0_1866_250e_AddReplayData(11, - (byte)this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].CityCount, - (byte)((this.oCPU.ReadUInt8(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x18)) & 0xff00) >> 8), - (byte)(this.oCPU.ReadUInt8(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x18)) & 0xff)); + int playerID = 0; + int[] array = new int[4]; + //this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), 0x0); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), 0x0); + L04d5: + array[playerID] = 0; + //this.oCPU.SI.Word = this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)); + //this.oCPU.SI.Word = this.oCPU.SHL_UInt16(this.oCPU.SI.Word, 0x1); + //this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word + this.oCPU.SI.Word - 0x14), 0x0); - L04d5: - this.oCPU.SI.Word = this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)); - this.oCPU.SI.Word = this.oCPU.SHL_UInt16(this.oCPU.SI.Word, 0x1); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word + this.oCPU.SI.Word - 0x14), 0x0); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), this.oCPU.INC_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)))); - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)), 0x4); - if (this.oCPU.Flags.L) goto L04d5; - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), 0x1); - goto L050a; + playerID++; + //this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), this.oCPU.INC_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)))); - L04ef: - this.oCPU.AX.Word = (ushort)this.oParent.CivState.Players[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].Ranking; - this.oCPU.CWD(this.oCPU.AX, this.oCPU.DX); - this.oCPU.AX.Word = this.oCPU.SUB_UInt16(this.oCPU.AX.Word, this.oCPU.DX.Word); - this.oCPU.AX.Word = this.oCPU.SAR_UInt16(this.oCPU.AX.Word, 0x1); - this.oCPU.SI.Word = this.oCPU.AX.Word; - this.oCPU.SI.Word = this.oCPU.SHL_UInt16(this.oCPU.SI.Word, 0x1); - this.oCPU.AX.Word = this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word + this.oCPU.SI.Word - 0x14), - this.oCPU.OR_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word + this.oCPU.SI.Word - 0x14)), this.oCPU.AX.Word)); + if (playerID < 4) + { + goto L04d5; + } - L0507: - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), this.oCPU.INC_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)))); + //this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)), 0x4); + //if (this.oCPU.Flags.L) goto L04d5; - L050a: - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)), 0x8); - if (this.oCPU.Flags.GE) goto L0542; - this.oCPU.AX.Word = 0x1; - this.oCPU.CX.Low = this.oCPU.ReadUInt8(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)); - this.oCPU.AX.Word = this.oCPU.SHL_UInt16(this.oCPU.AX.Word, this.oCPU.CX.Low); - this.oCPU.TEST_UInt16(this.oCPU.AX.Word, (ushort)this.oParent.CivState.ActiveCivilizations); - if (this.oCPU.Flags.E) goto L0507; - this.oCPU.SI.Word = (ushort)this.oParent.CivState.Players[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].Ranking; - this.oCPU.AX.Word = this.oCPU.SI.Word; - this.oCPU.TEST_UInt8(this.oCPU.AX.Low, 0x1); - if (this.oCPU.Flags.E) goto L04ef; - this.oCPU.CWD(this.oCPU.AX, this.oCPU.DX); - this.oCPU.AX.Word = this.oCPU.SUB_UInt16(this.oCPU.AX.Word, this.oCPU.DX.Word); - this.oCPU.AX.Word = this.oCPU.SAR_UInt16(this.oCPU.AX.Word, 0x1); - this.oCPU.DI.Word = this.oCPU.AX.Word; - this.oCPU.DI.Word = this.oCPU.SHL_UInt16(this.oCPU.DI.Word, 0x1); - this.oCPU.AX.Word = this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)); - this.oCPU.CX.Low = 0x4; - this.oCPU.AX.Word = this.oCPU.SHL_UInt16(this.oCPU.AX.Word, this.oCPU.CX.Low); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word + this.oCPU.DI.Word - 0x14), - this.oCPU.OR_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word + this.oCPU.DI.Word - 0x14)), this.oCPU.AX.Word)); - goto L0507; + playerID = 1; + //this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), 0x1); + goto L050a; + + L04ef: + this.oCPU.AX.Word = (ushort)this.oParent.CivState.Players[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].Ranking; + this.oCPU.CWD(this.oCPU.AX, this.oCPU.DX); + this.oCPU.AX.Word = this.oCPU.SUB_UInt16(this.oCPU.AX.Word, this.oCPU.DX.Word); + this.oCPU.AX.Word = this.oCPU.SAR_UInt16(this.oCPU.AX.Word, 0x1); + this.oCPU.SI.Word = this.oCPU.AX.Word; + this.oCPU.SI.Word = this.oCPU.SHL_UInt16(this.oCPU.SI.Word, 0x1); + this.oCPU.AX.Word = this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)); + this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word + this.oCPU.SI.Word - 0x14), + this.oCPU.OR_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word + this.oCPU.SI.Word - 0x14)), this.oCPU.AX.Word)); + + L0507: + playerID++; + //this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), this.oCPU.INC_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)))); + + L050a: + if (playerID < 8) + { + //this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)), 0x8); + //if (this.oCPU.Flags.GE) goto L0542; + + //this.oCPU.AX.Word = 0x1; + //this.oCPU.CX.Low = this.oCPU.ReadUInt8(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)); + //this.oCPU.AX.Word = this.oCPU.SHL_UInt16(this.oCPU.AX.Word, this.oCPU.CX.Low); + + if (((1 << playerID) & this.oParent.CivState.ActiveCivilizations) == 0) + { + // continue; + goto L0507; + } + + //this.oCPU.TEST_UInt16(this.oCPU.AX.Word, (ushort)this.oParent.CivState.ActiveCivilizations); + //if (this.oCPU.Flags.E) goto L0507; + + if ((this.oParent.CivState.Players[playerID].Ranking & 1) == 0) + { + goto L04ef; + } + + //this.oCPU.SI.Word = (ushort)this.oParent.CivState.Players[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].Ranking; + //this.oCPU.AX.Word = this.oCPU.SI.Word; + //this.oCPU.TEST_UInt8(this.oCPU.AX.Low, 0x1); + //if (this.oCPU.Flags.E) goto L04ef; + + // TODO: what is this logic? + this.oCPU.AX.Word = (ushort)this.oParent.CivState.Players[playerID].Ranking; + this.oCPU.CWD(this.oCPU.AX, this.oCPU.DX); + this.oCPU.AX.Word = this.oCPU.SUB_UInt16(this.oCPU.AX.Word, this.oCPU.DX.Word); + this.oCPU.AX.Word = this.oCPU.SAR_UInt16(this.oCPU.AX.Word, 0x1); + + // TODO: check if this is the same as the asm above + int rankning = this.oParent.CivState.Players[playerID].Ranking; + if (rankning < 0) + { + // ranking = ranking - (-1) + rankning += 1; + } + + rankning >>= 1; - L0542: - // Instruction address 0x1238:0x0556, size: 5 - this.oParent.Segment_1866.F0_1866_250e_AddReplayData(12, - this.oCPU.ReadUInt8(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0xe)), - this.oCPU.ReadUInt8(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x10)), - this.oCPU.ReadUInt8(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x12)), - this.oCPU.ReadUInt8(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x14))); - L055e: - if (this.oParent.CivState.TurnCount < this.oParent.CivState.NextAnthologyTurn) goto L0582; + this.oCPU.DI.Word = this.oCPU.AX.Word; + this.oCPU.DI.Word = this.oCPU.SHL_UInt16(this.oCPU.DI.Word, 0x1); + this.oCPU.AX.Word = this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)); + this.oCPU.CX.Low = 0x4; + this.oCPU.AX.Word = this.oCPU.SHL_UInt16(this.oCPU.AX.Word, this.oCPU.CX.Low); + this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word + this.oCPU.DI.Word - 0x14), + this.oCPU.OR_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word + this.oCPU.DI.Word - 0x14)), this.oCPU.AX.Word)); + goto L0507; + } - // Instruction address 0x1238:0x056b, size: 5 - this.oCPU.AX.Word = (ushort)(this.oParent.MSCAPI.RNG.Next(40)); + //L0542: + // Instruction address 0x1238:0x0556, size: 5 + this.oParent.Segment_1866.F0_1866_250e_AddReplayData(12, + this.oCPU.ReadUInt8(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0xe)), + this.oCPU.ReadUInt8(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x10)), + this.oCPU.ReadUInt8(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x12)), + this.oCPU.ReadUInt8(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x14))); + } - this.oCPU.AX.Word = this.oCPU.ADD_UInt16(this.oCPU.AX.Word, (ushort)this.oParent.CivState.TurnCount); - this.oCPU.AX.Word = this.oCPU.ADD_UInt16(this.oCPU.AX.Word, 0x14); - oParent.CivState.NextAnthologyTurn = (short)this.oCPU.AX.Word; + //L055e: + if (this.oParent.CivState.TurnCount >= this.oParent.CivState.NextAnthologyTurn) + { + // Instruction address 0x1238:0x056b, size: 5 + oParent.CivState.NextAnthologyTurn = (short)(this.oParent.CivState.TurnCount + this.oParent.MSCAPI.RNG.Next(40) + 20); - this.oParent.WorldMap.F12_0000_09e2(); + // Shows anthology popup + this.oParent.WorldMap.F12_0000_09e2(); + } - L0582: this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), 0x1); L0587: From a2332d6255ac14b30adbd5986a5fce9b86ce81a1 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Mon, 1 Dec 2025 23:59:19 +0300 Subject: [PATCH 06/10] Translate rankings replay data --- src/CivGame/Game/Segment_1238.cs | 102 ++++--------------------------- 1 file changed, 11 insertions(+), 91 deletions(-) diff --git a/src/CivGame/Game/Segment_1238.cs b/src/CivGame/Game/Segment_1238.cs index 6034fd6..2fed590 100644 --- a/src/CivGame/Game/Segment_1238.cs +++ b/src/CivGame/Game/Segment_1238.cs @@ -379,113 +379,33 @@ public void F0_1238_0092() (byte)this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].CityCount, (byte)((population & 0xff00) >> 8), (byte)(population & 0xff)); - - int playerID = 0; - int[] array = new int[4]; - //this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), 0x0); - - L04d5: - array[playerID] = 0; - //this.oCPU.SI.Word = this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)); - //this.oCPU.SI.Word = this.oCPU.SHL_UInt16(this.oCPU.SI.Word, 0x1); - //this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word + this.oCPU.SI.Word - 0x14), 0x0); - - playerID++; - //this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), this.oCPU.INC_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)))); - - if (playerID < 4) + + ushort[] rankings = new ushort[4]; + Array.Fill(rankings, (ushort)0); + + for (ushort playerID = 1; playerID < 8; ++playerID) { - goto L04d5; - } - - //this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)), 0x4); - //if (this.oCPU.Flags.L) goto L04d5; - - playerID = 1; - //this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), 0x1); - goto L050a; - - L04ef: - this.oCPU.AX.Word = (ushort)this.oParent.CivState.Players[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].Ranking; - this.oCPU.CWD(this.oCPU.AX, this.oCPU.DX); - this.oCPU.AX.Word = this.oCPU.SUB_UInt16(this.oCPU.AX.Word, this.oCPU.DX.Word); - this.oCPU.AX.Word = this.oCPU.SAR_UInt16(this.oCPU.AX.Word, 0x1); - this.oCPU.SI.Word = this.oCPU.AX.Word; - this.oCPU.SI.Word = this.oCPU.SHL_UInt16(this.oCPU.SI.Word, 0x1); - this.oCPU.AX.Word = this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word + this.oCPU.SI.Word - 0x14), - this.oCPU.OR_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word + this.oCPU.SI.Word - 0x14)), this.oCPU.AX.Word)); - - L0507: - playerID++; - //this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), this.oCPU.INC_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)))); - - L050a: - if (playerID < 8) - { - //this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)), 0x8); - //if (this.oCPU.Flags.GE) goto L0542; - - //this.oCPU.AX.Word = 0x1; - //this.oCPU.CX.Low = this.oCPU.ReadUInt8(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)); - //this.oCPU.AX.Word = this.oCPU.SHL_UInt16(this.oCPU.AX.Word, this.oCPU.CX.Low); - if (((1 << playerID) & this.oParent.CivState.ActiveCivilizations) == 0) { - // continue; - goto L0507; + continue; } - //this.oCPU.TEST_UInt16(this.oCPU.AX.Word, (ushort)this.oParent.CivState.ActiveCivilizations); - //if (this.oCPU.Flags.E) goto L0507; + int index = this.oParent.CivState.Players[playerID].Ranking >> 1; if ((this.oParent.CivState.Players[playerID].Ranking & 1) == 0) { - goto L04ef; + rankings[index] |= playerID; } - - //this.oCPU.SI.Word = (ushort)this.oParent.CivState.Players[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].Ranking; - //this.oCPU.AX.Word = this.oCPU.SI.Word; - //this.oCPU.TEST_UInt8(this.oCPU.AX.Low, 0x1); - //if (this.oCPU.Flags.E) goto L04ef; - - // TODO: what is this logic? - this.oCPU.AX.Word = (ushort)this.oParent.CivState.Players[playerID].Ranking; - this.oCPU.CWD(this.oCPU.AX, this.oCPU.DX); - this.oCPU.AX.Word = this.oCPU.SUB_UInt16(this.oCPU.AX.Word, this.oCPU.DX.Word); - this.oCPU.AX.Word = this.oCPU.SAR_UInt16(this.oCPU.AX.Word, 0x1); - - // TODO: check if this is the same as the asm above - int rankning = this.oParent.CivState.Players[playerID].Ranking; - if (rankning < 0) + else { - // ranking = ranking - (-1) - rankning += 1; + rankings[index] |= (ushort)(playerID << 4); } - - rankning >>= 1; - - - this.oCPU.DI.Word = this.oCPU.AX.Word; - this.oCPU.DI.Word = this.oCPU.SHL_UInt16(this.oCPU.DI.Word, 0x1); - this.oCPU.AX.Word = this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)); - this.oCPU.CX.Low = 0x4; - this.oCPU.AX.Word = this.oCPU.SHL_UInt16(this.oCPU.AX.Word, this.oCPU.CX.Low); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word + this.oCPU.DI.Word - 0x14), - this.oCPU.OR_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word + this.oCPU.DI.Word - 0x14)), this.oCPU.AX.Word)); - goto L0507; } - //L0542: // Instruction address 0x1238:0x0556, size: 5 - this.oParent.Segment_1866.F0_1866_250e_AddReplayData(12, - this.oCPU.ReadUInt8(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0xe)), - this.oCPU.ReadUInt8(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x10)), - this.oCPU.ReadUInt8(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x12)), - this.oCPU.ReadUInt8(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x14))); + this.oParent.Segment_1866.F0_1866_250e_AddReplayData(12, (byte)rankings[3], (byte)rankings[2], (byte)rankings[1], (byte)rankings[0]); } - //L055e: if (this.oParent.CivState.TurnCount >= this.oParent.CivState.NextAnthologyTurn) { // Instruction address 0x1238:0x056b, size: 5 From f1458eb2fac477c833e80f792456cf55213645f8 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Tue, 2 Dec 2025 05:21:02 +0300 Subject: [PATCH 07/10] Translate wonders and pollution score counting --- src/CivGame/Game/Segment_1238.cs | 55 ++++++++++++-------------------- 1 file changed, 21 insertions(+), 34 deletions(-) diff --git a/src/CivGame/Game/Segment_1238.cs b/src/CivGame/Game/Segment_1238.cs index 2fed590..1d32911 100644 --- a/src/CivGame/Game/Segment_1238.cs +++ b/src/CivGame/Game/Segment_1238.cs @@ -415,42 +415,29 @@ public void F0_1238_0092() this.oParent.WorldMap.F12_0000_09e2(); } - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), 0x1); - - L0587: - this.oCPU.SI.Word = (ushort)this.oParent.CivState.WonderCityID[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))]; - this.oCPU.CMP_UInt16(this.oCPU.SI.Word, 0xffff); - if (this.oCPU.Flags.E) goto L05b0; - - this.oCPU.CMP_UInt16(this.oCPU.SI.Word, 0x80); - if (this.oCPU.Flags.E) goto L05b0; - - this.oCPU.AX.Word = 0x1c; - this.oCPU.IMUL_UInt16(this.oCPU.AX, this.oCPU.DX, this.oCPU.SI.Word); - this.oCPU.BX.Word = this.oCPU.AX.Word; - this.oParent.CivState.Players[this.oParent.CivState.Cities[this.oCPU.SI.Word].PlayerID].Score += 25; - - L05b0: - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), - this.oCPU.INC_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)))); - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)), 0x15); - if (this.oCPU.Flags.LE) goto L0587; - - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0x3484), 0xfffd); - if (this.oCPU.Flags.NE) goto L05c8; - - this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0x3484, 0xfffe); - goto L05e6; + for (WonderEnum wonderID = WonderEnum.Pyramids; wonderID <= WonderEnum.CureForCancer; ++wonderID) + { + int wonderCityID = this.oParent.CivState.WonderCityID[(int)wonderID]; + if (wonderCityID != -1 && wonderCityID != 128) + { + this.oParent.CivState.Players[this.oParent.CivState.Cities[wonderCityID].PlayerID].Score += 25; + } + } - L05c8: - this.oCPU.AX.Word = 0xa; - this.oCPU.IMUL_UInt16(this.oCPU.AX, this.oCPU.DX, (ushort)this.oParent.CivState.PollutedSquareCount); - this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].Score -= (short)this.oCPU.AX.Word; - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0x3484), 0xfffe); - if (this.oCPU.Flags.NE) goto L05e6; - this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0x3484, 0x0); + if (this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0x3484) == 0xfffd) + { + this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0x3484, 0xfffe); + } + else + { + humanPlayer.Score -= (short)(this.oParent.CivState.PollutedSquareCount * 10); + + if (this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0x3484) == 0xfffe) + { + this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0x3484, 0x0); + } + } - L05e6: this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x8), 0x0); this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), 0x0); From 6fe79efb40ee94df8e545175cc043800a17b1bf6 Mon Sep 17 00:00:00 2001 From: VladimirMakeev Date: Tue, 2 Dec 2025 22:28:25 +0300 Subject: [PATCH 08/10] Translate victory conditions --- src/CivGame/Game/Segment_1238.cs | 326 ++++++++++++++----------------- 1 file changed, 143 insertions(+), 183 deletions(-) diff --git a/src/CivGame/Game/Segment_1238.cs b/src/CivGame/Game/Segment_1238.cs index 1d32911..c37a7dc 100644 --- a/src/CivGame/Game/Segment_1238.cs +++ b/src/CivGame/Game/Segment_1238.cs @@ -76,12 +76,6 @@ public void F0_1238_0092() this.oCPU.Log.EnterBlock("F0_1238_0092()"); // function body - this.oCPU.PUSH_UInt16(this.oCPU.BP.Word); - this.oCPU.BP.Word = this.oCPU.SP.Word; - this.oCPU.SP.Word = this.oCPU.SUB_UInt16(this.oCPU.SP.Word, 0x1a); - this.oCPU.PUSH_UInt16(this.oCPU.DI.Word); - this.oCPU.PUSH_UInt16(this.oCPU.SI.Word); - // Instruction address 0x1238:0x009a, size: 5 this.oParent.Segment_11a8.F0_11a8_0268(); @@ -95,9 +89,6 @@ public void F0_1238_0092() this.oParent.Var_6b92 = 0; this.oParent.CivState.MaximumTechnologyCount = 0; - // Active players = 0 - this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0xde20, 0); - for (int playerID = 0; playerID < 8; ++playerID) { if ((this.oParent.CivState.ActiveCivilizations & (1 << playerID)) == 0) @@ -105,9 +96,6 @@ public void F0_1238_0092() continue; } - // Count active players - this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0xde20, this.oCPU.INC_UInt16(this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xde20))); - short discoveredCount = this.oParent.CivState.Players[playerID].DiscoveredTechnologyCount; if (this.oParent.CivState.MaximumTechnologyCount < discoveredCount) { @@ -118,7 +106,7 @@ public void F0_1238_0092() if (this.oParent.CivState.TurnCount == 0) { Unit startingUnit = humanPlayer.Units[0]; - // Center camera on starting unit + // Show map around starting unit this.oParent.Var_d4cc_MapViewX = (short)(startingUnit.Position.X - 7); this.oParent.Var_d75e_MapViewY = (short)(startingUnit.Position.Y - 6); @@ -143,14 +131,11 @@ public void F0_1238_0092() for (short playerID = 0; playerID < 8; ++playerID) { - this.oParent.CivState.Players[playerID].Score = 0; - - if ((this.oParent.CivState.ActiveCivilizations & (1 << playerID)) == 0) - { - continue; - } + Player player = this.oParent.CivState.Players[playerID]; + player.Score = 0; - if (playerID < this.oParent.CivState.HumanPlayerID && this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdf60) != 0) + if (((this.oParent.CivState.ActiveCivilizations & (1 << playerID)) == 0) + || (playerID < this.oParent.CivState.HumanPlayerID && this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdf60) != 0)) { continue; } @@ -175,9 +160,9 @@ public void F0_1238_0092() this.oParent.Segment_1ade.F0_1ade_0006(playerID); } - if (this.oParent.CivState.Players[playerID].Coins > 30000) + if (player.Coins > 30000) { - this.oParent.CivState.Players[playerID].Coins = 30000; + player.Coins = 30000; } // Instruction address 0x1238:0x01ab, size: 5 @@ -198,16 +183,15 @@ public void F0_1238_0092() // Instruction address 0x1238:0x01ef, size: 3 F0_1238_107e(); - if (this.oParent.CivState.Players[playerID].CityCount == 0 && this.oParent.CivState.Players[playerID].SettlerCount == 0) + if (player.CityCount == 0 && player.SettlerCount == 0) { // Human player lost the game - // Instruction address 0x1238:0x0205, size: 5 this.oParent.Segment_11a8.F0_11a8_0268(); this.oParent.MainIntro.F2_0000_152a(); - // game state = player lost + // Game state = player lost (-1) this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0xdc48, 0xffff); // Instruction address 0x1238:0x0215, size: 5 @@ -225,7 +209,6 @@ public void F0_1238_0092() { // Handles player turn. // Handles human player input and waits for end of turn if option selected - // Instruction address 0x1238:0x022f, size: 5 this.oParent.Segment_1403.F0_1403_000e(playerID); } @@ -248,11 +231,16 @@ public void F0_1238_0092() { // Human player decided to retire // Show power graph, civilization score and hall of fame - // Instruction address 0x1238:0x0261, size: 3 F0_1238_08a0(); - goto showAds; + // Show advertisements + // Instruction address 0x1238:0x0897, size: 3 + F0_1238_090a(); + + // Far return + this.oCPU.Log.ExitBlock("F0_1238_0092"); + return; } goto exit; @@ -300,7 +288,6 @@ public void F0_1238_0092() this.oCPU.WriteUInt8(this.oCPU.DS.Word, 0xba06, 0x0); // Warning: Funds are running low... - // Instruction address 0x1238:0x034f, size: 5 this.oParent.Segment_2f4d.F0_2f4d_044f(0x1c2a); @@ -379,10 +366,10 @@ public void F0_1238_0092() (byte)this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].CityCount, (byte)((population & 0xff00) >> 8), (byte)(population & 0xff)); - + ushort[] rankings = new ushort[4]; Array.Fill(rankings, (ushort)0); - + for (ushort playerID = 1; playerID < 8; ++playerID) { if (((1 << playerID) & this.oParent.CivState.ActiveCivilizations) == 0) @@ -431,221 +418,194 @@ public void F0_1238_0092() else { humanPlayer.Score -= (short)(this.oParent.CivState.PollutedSquareCount * 10); - + if (this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0x3484) == 0xfffe) { this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0x3484, 0x0); } } - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x8), 0x0); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), 0x0); - - L05f0: - this.oCPU.AX.Word = 0x1c; - this.oCPU.IMUL_UInt16(this.oCPU.AX, this.oCPU.DX, this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))); - this.oCPU.SI.Word = this.oCPU.AX.Word; - - if (this.oParent.CivState.Cities[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].StatusFlag == 0xff || - this.oParent.CivState.Cities[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].PlayerID != this.oParent.CivState.HumanPlayerID) - goto L0616; - this.oCPU.TEST_UInt16(this.oParent.CivState.Cities[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].ImprovementFlags0, 0x1); - if (this.oCPU.Flags.E) goto L0616; - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x8), 0x1); - - L0616: - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), - this.oCPU.INC_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)))); - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)), 0x80); - if (this.oCPU.Flags.L) goto L05f0; - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x8)), 0x0); - if (this.oCPU.Flags.E) goto L066e; + bool humanPlayerHasPalace = false; - if (!this.oParent.CivState.GameSettingFlags.Palace) goto L066e; - - this.oCPU.TEST_UInt16((ushort)this.oParent.CivState.SpaceshipFlags, 0x100); - if (this.oCPU.Flags.NE) goto L066e; - - // Instruction address 0x1238:0x063b, size: 3 - F0_1238_16e7((short)(this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].PalaceLevel + 1)); + for (int cityID = 0; cityID < 128; ++cityID) + { + City city = this.oParent.CivState.Cities[cityID]; - this.oCPU.SI.Word = this.oCPU.AX.Word; + if (city.StatusFlag != 0xff && city.PlayerID == this.oParent.CivState.HumanPlayerID && (city.ImprovementFlags0 & 1) != 0) + { + humanPlayerHasPalace = true; + // No need to check further + break; + } + } - this.oParent.Overlay_20.F20_0000_0ca9_ShowCivilizationScorePopup(this.oParent.CivState.HumanPlayerID, false); + if (humanPlayerHasPalace && this.oParent.CivState.GameSettingFlags.Palace && (this.oParent.CivState.SpaceshipFlags & 0x100) == 0) + { + // Instruction address 0x1238:0x063b, size: 3 + ushort value1 = F0_1238_16e7((short)(humanPlayer.PalaceLevel + 1)); + ushort value2 = this.oParent.Overlay_20.F20_0000_0ca9_ShowCivilizationScorePopup(this.oParent.CivState.HumanPlayerID, false); - this.oCPU.CMP_UInt16(this.oCPU.AX.Word, this.oCPU.SI.Word); - if (this.oCPU.Flags.L) goto L066e; + if (value2 >= value1) + { + humanPlayer.PalaceLevel++; - this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].PalaceLevel++; - if (this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].PalaceLevel > 37) - goto L066e; - - this.oParent.Palace.F17_0000_0000(); + if (humanPlayer.PalaceLevel <= 37) + { + this.oParent.Palace.F17_0000_0000(); + } + } + } - L066e: // Instruction address 0x1238:0x066f, size: 3 F0_1238_107e(); - this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0x1cf6, 0xffff); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), 0x1); - - L067d: - this.oCPU.AX.Word = 0x1; - this.oCPU.CX.Low = this.oCPU.ReadUInt8(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)); - this.oCPU.AX.Word = this.oCPU.SHL_UInt16(this.oCPU.AX.Word, this.oCPU.CX.Low); - this.oCPU.TEST_UInt16(this.oCPU.AX.Word, (ushort)this.oParent.CivState.SpaceshipFlags); - if (this.oCPU.Flags.E) goto L069f; + // ID of player that reached Alpha Centauri + int spaceVictoryPlayerID = -1; - if (this.oParent.CivState.Players[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].SpaceshipETAYear == this.oParent.CivState.Year) + for (int playerID = 1; playerID < 8; ++playerID) { - this.oCPU.AX.Word = this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)); - this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0x1cf6, this.oCPU.AX.Word); + if (((1 << playerID) & this.oParent.CivState.SpaceshipFlags) != 0 + && this.oParent.CivState.Players[playerID].SpaceshipETAYear == this.oParent.CivState.Year) + { + spaceVictoryPlayerID = playerID; + } } - L069f: - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), this.oCPU.INC_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)))); - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)), 0x8); - if (this.oCPU.Flags.L) goto L067d; - this.oCPU.AX.Word = 0x14; - this.oCPU.IMUL_UInt16(this.oCPU.AX, this.oCPU.DX, (ushort)this.oParent.CivState.DifficultyLevel); - this.oCPU.AX.Word = this.oCPU.SUB_UInt16(this.oCPU.AX.Word, 0x820); - this.oCPU.AX.Word = this.oCPU.NEG_UInt16(this.oCPU.AX.Word); - if ((short)this.oCPU.AX.Word != this.oParent.CivState.Year) goto L0718; - - this.oCPU.BX.Word = (ushort)this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].GovernmentType; - this.oCPU.BX.Word = this.oCPU.SHL_UInt16(this.oCPU.BX.Word, 0x1); - // Instruction address 0x1238:0x06ce, size: 5 - this.oParent.MSCAPI.strcpy(0xba06, this.oCPU.ReadUInt16(this.oCPU.DS.Word, (ushort)(this.oCPU.BX.Word + 0x19b2))); + int retirementYear = 2080 - this.oParent.CivState.DifficultyLevel * 20; - // Instruction address 0x1238:0x06de, size: 5 - this.oParent.MSCAPI.strcat(0xba06, " "); + if (retirementYear == this.oParent.CivState.Year) + { + // Instruction address 0x1238:0x06ce, size: 5 + this.oParent.MSCAPI.strcpy(0xba06, this.oCPU.ReadUInt16(this.oCPU.DS.Word, (ushort)(humanPlayer.GovernmentType * 2 + 0x19b2))); - // Instruction address 0x1238:0x06f4, size: 5 - this.oParent.MSCAPI.strcat(0xba06, this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].Name); + // Instruction address 0x1238:0x06de, size: 5 + this.oParent.MSCAPI.strcat(0xba06, " "); - // Instruction address 0x1238:0x0704, size: 5 - this.oParent.MSCAPI.strcat(0xba06, "\nplans retirement\nin 20 years.\n"); + // Instruction address 0x1238:0x06f4, size: 5 + this.oParent.MSCAPI.strcat(0xba06, humanPlayer.Name); - this.oParent.Overlay_21.F21_0000_0000(-1); + // Instruction address 0x1238:0x0704, size: 5 + this.oParent.MSCAPI.strcat(0xba06, "\nplans retirement\nin 20 years.\n"); - L0718: - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0x1cf6), 0xffff); - if (this.oCPU.Flags.NE) goto L073b; + this.oParent.Overlay_21.F21_0000_0000(-1); + } - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xb884), 0x0); - if (this.oCPU.Flags.NE) goto L073b; + int dynastyEndYear = 2100 - this.oParent.CivState.DifficultyLevel * 20; - this.oCPU.AX.Word = 0x14; - this.oCPU.IMUL_UInt16(this.oCPU.AX, this.oCPU.DX, (ushort)this.oParent.CivState.DifficultyLevel); - this.oCPU.AX.Word = this.oCPU.SUB_UInt16(this.oCPU.AX.Word, 0x834); - this.oCPU.AX.Word = this.oCPU.NEG_UInt16(this.oCPU.AX.Word); - if ((short)this.oCPU.AX.Word == this.oParent.CivState.Year) goto L073b; - goto exit; + if (spaceVictoryPlayerID == -1 + && this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xb884) == 0 + && dynastyEndYear != this.oParent.CivState.Year) + { + // Far return + //this.oCPU.Log.ExitBlock("F0_1238_0092"); + //return; + } - L073b: // Instruction address 0x1238:0x073b, size: 5 this.oParent.Segment_11a8.F0_11a8_0268(); // Instruction address 0x1238:0x0748, size: 5 this.oParent.MSCAPI.strcpy(0xba06, "*** GAME OVER ***\n"); - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xb884), 0x0); - if (this.oCPU.Flags.E) goto L077e; - - // Instruction address 0x1238:0x075f, size: 5 - this.oParent.MSCAPI.strcpy(0xba06, "Your civilization\nhas conquered\nthe entire planet!\n"); - - this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0x1cf6, 0xffff); + if (this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xb884) != 0) + { + // Instruction address 0x1238:0x075f, size: 5 + this.oParent.MSCAPI.strcpy(0xba06, "Your civilization\nhas conquered\nthe entire planet!\n"); - this.oParent.Overlay_21.F21_0000_0000(-1); + // Conquest victory, don't care about space race + spaceVictoryPlayerID = -1; - this.oParent.GameReplay.F9_0000_0dde(); + this.oParent.Overlay_21.F21_0000_0000(-1); - L077e: - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0x1cf6), 0xffff); - if (this.oCPU.Flags.E) goto L07c7; + this.oParent.GameReplay.F9_0000_0dde(); + } - this.oParent.MainIntro.F2_0000_0bd7(this.oCPU.ReadInt16(this.oCPU.DS.Word, 0x1cf6)); + if (spaceVictoryPlayerID != -1) + { + this.oParent.MainIntro.F2_0000_0bd7((short)spaceVictoryPlayerID); - // Instruction address 0x1238:0x0792, size: 3 - F0_1238_1b44(); + // Instruction address 0x1238:0x0792, size: 3 + F0_1238_1b44(); - // Instruction address 0x1238:0x07a3, size: 5 - this.oParent.MSCAPI.strcpy(0xba06, this.oParent.CivState.Players[this.oCPU.ReadInt16(this.oCPU.DS.Word, 0x1cf6)].Nationality); + // Instruction address 0x1238:0x07a3, size: 5 + this.oParent.MSCAPI.strcpy(0xba06, this.oParent.CivState.Players[spaceVictoryPlayerID].Nationality); - // Instruction address 0x1238:0x07b3, size: 5 - this.oParent.MSCAPI.strcat(0xba06, " spaceship\narrives at Alpha Centauri.\n"); + // Instruction address 0x1238:0x07b3, size: 5 + this.oParent.MSCAPI.strcat(0xba06, " spaceship\narrives at Alpha Centauri.\n"); - this.oParent.Overlay_21.F21_0000_0000(-1); + this.oParent.Overlay_21.F21_0000_0000(-1); + } - L07c7: - this.oCPU.AX.Word = 0x14; - this.oCPU.IMUL_UInt16(this.oCPU.AX, this.oCPU.DX, (ushort)this.oParent.CivState.DifficultyLevel); - this.oCPU.AX.Word = this.oCPU.SUB_UInt16(this.oCPU.AX.Word, 0x834); - this.oCPU.AX.Word = this.oCPU.NEG_UInt16(this.oCPU.AX.Word); - if ((short)this.oCPU.AX.Word != this.oParent.CivState.Year) goto L0836; + if (dynastyEndYear == this.oParent.CivState.Year) + { + // Instruction address 0x1238:0x07e7, size: 5 + this.oParent.MSCAPI.strcpy(0xba06, humanPlayer.Name); - // Instruction address 0x1238:0x07e7, size: 5 - this.oParent.MSCAPI.strcpy(0xba06, this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].Name); + // Instruction address 0x1238:0x07f7, size: 5 + this.oParent.MSCAPI.strcat(0xba06, " dynasty\nends after glorious\n6000 year reign!\n"); - // Instruction address 0x1238:0x07f7, size: 5 - this.oParent.MSCAPI.strcat(0xba06, " dynasty\nends after glorious\n6000 year reign!\n"); + // Instruction address 0x1238:0x0816, size: 5 + this.oParent.Segment_1000.F0_1000_0a32_PlayTune( + this.oParent.CivState.Nations[humanPlayer.NationalityID].LongTune, 3); - // Instruction address 0x1238:0x0816, size: 5 - this.oParent.Segment_1000.F0_1000_0a32_PlayTune( - this.oParent.CivState.Nations[this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].NationalityID].LongTune, 3); + this.oParent.Overlay_21.F21_0000_0000(-1); - this.oParent.Overlay_21.F21_0000_0000(-1); - - // Instruction address 0x1238:0x082e, size: 5 - this.oParent.Segment_1000.F0_1000_0a32_PlayTune(1, 0); + // Instruction address 0x1238:0x082e, size: 5 + this.oParent.Segment_1000.F0_1000_0a32_PlayTune(1, 0); + } - L0836: // Instruction address 0x1238:0x0836, size: 5 this.oParent.Segment_11a8.F0_11a8_0250(); - this.oCPU.TEST_UInt16((ushort)this.oParent.CivState.SpaceshipFlags, 0x100); - if (this.oCPU.Flags.NE) goto L084e; + if ((this.oParent.CivState.SpaceshipFlags & 0x100) == 0) + { + // Shows civilization powergraph - // Instruction address 0x1238:0x0848, size: 3 - F0_1238_08a0(); + // Instruction address 0x1238:0x0848, size: 3 + F0_1238_08a0(); + } - L084e: // Instruction address 0x1238:0x084f, size: 3 F0_1238_1b44(); this.oCPU.WriteUInt8(this.oCPU.DS.Word, 0x4cd9, this.oCPU.OR_UInt8(this.oCPU.ReadUInt8(this.oCPU.DS.Word, 0x4cd9), 0x1)); - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xb884), 0x0); - if (this.oCPU.Flags.NE) goto L0889; - this.oCPU.WriteUInt8(this.oCPU.DS.Word, 0xba06, 0x0); - // Instruction address 0x1238:0x0867, size: 5 - this.oParent.Segment_2f4d.F0_2f4d_044f(0x1cf0); - - // Instruction address 0x1238:0x0879, size: 3 - F0_1238_001e_ShowDialog(0xba06, 80, 80); + if (this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xb884) == 0) + { + this.oCPU.WriteUInt8(this.oCPU.DS.Word, 0xba06, 0x0); - this.oCPU.AX.Word = this.oCPU.SUB_UInt16(this.oCPU.AX.Word, 0x1); - this.oCPU.AX.Word = this.oCPU.NEG_UInt16(this.oCPU.AX.Word); - this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0xdc48, this.oCPU.AX.Word); - goto L088f; + // Your final score has entered - L0889: - this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0xdc48, 0x1); + // Instruction address 0x1238:0x0867, size: 5 + this.oParent.Segment_2f4d.F0_2f4d_044f(0x1cf0); - L088f: - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdc48), 0x0); - if (this.oCPU.Flags.E) goto exit; + // Instruction address 0x1238:0x0879, size: 3 + ushort selectedOption = F0_1238_001e_ShowDialog(0xba06, 80, 80); - showAds: - // Instruction address 0x1238:0x0897, size: 3 - F0_1238_090a(); + this.oCPU.AX.Word = this.oCPU.SUB_UInt16(this.oCPU.AX.Word, 0x1); + this.oCPU.AX.Word = this.oCPU.NEG_UInt16(this.oCPU.AX.Word); + + var val = (ushort)((0x10000 - (ushort)(selectedOption - 1)) & 0xffff); + + // option 0 --> writing value 1 + // option 1 --> writing value 0 + + this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0xdc48, /*this.oCPU.AX.Word*/val); + } + else + { + this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0xdc48, 0x1); + } + + if (this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdc48) != 0) + { + // Show advertisements + + // Instruction address 0x1238:0x0897, size: 3 + F0_1238_090a(); + } exit: - this.oCPU.SI.Word = this.oCPU.POP_UInt16(); - this.oCPU.DI.Word = this.oCPU.POP_UInt16(); - this.oCPU.SP.Word = this.oCPU.BP.Word; - this.oCPU.BP.Word = this.oCPU.POP_UInt16(); // Far return this.oCPU.Log.ExitBlock("F0_1238_0092"); } From bfdf32264ce4b5dde899a08eaa7e93cd7285ab94 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Wed, 3 Dec 2025 04:07:01 +0300 Subject: [PATCH 09/10] Finish translation of F0_1238_0092 --- src/CivGame/Game/Segment_11a8.cs | 2 +- src/CivGame/Game/Segment_1238.cs | 61 +++++++++++++------------------- 2 files changed, 25 insertions(+), 38 deletions(-) diff --git a/src/CivGame/Game/Segment_11a8.cs b/src/CivGame/Game/Segment_11a8.cs index 27756c0..038d737 100644 --- a/src/CivGame/Game/Segment_11a8.cs +++ b/src/CivGame/Game/Segment_11a8.cs @@ -144,7 +144,7 @@ public void F0_11a8_0008_Main() L0175: // Instruction address 0x11a8:0x0175, size: 5 - this.oParent.Segment_1238.F0_1238_0092(); + this.oParent.Segment_1238.F0_1238_0092_GameTurn(); this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdc48), 0x0); if (this.oCPU.Flags.E) goto L0175; diff --git a/src/CivGame/Game/Segment_1238.cs b/src/CivGame/Game/Segment_1238.cs index c37a7dc..07fa2ea 100644 --- a/src/CivGame/Game/Segment_1238.cs +++ b/src/CivGame/Game/Segment_1238.cs @@ -69,11 +69,12 @@ public ushort F0_1238_001e_ShowDialog(ushort stringPtr, int xPos, int yPos) } /// - /// ? + /// Handles a single game turn. + /// Performs active player's turns, checks for disasters, victory and loss conditions. /// - public void F0_1238_0092() + public void F0_1238_0092_GameTurn() { - this.oCPU.Log.EnterBlock("F0_1238_0092()"); + this.oCPU.Log.EnterBlock("F0_1238_0092_GameTurn()"); // function body // Instruction address 0x1238:0x009a, size: 5 @@ -222,7 +223,8 @@ public void F0_1238_0092() } // Check if game should continue with the next player - if (this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdc48) == 0 || this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xb884) != 0) + if (this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdc48) == 0 + || this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xb884) != 0) { continue; } @@ -234,16 +236,13 @@ public void F0_1238_0092() // Instruction address 0x1238:0x0261, size: 3 F0_1238_08a0(); - // Show advertisements // Instruction address 0x1238:0x0897, size: 3 - F0_1238_090a(); - - // Far return - this.oCPU.Log.ExitBlock("F0_1238_0092"); - return; + F0_1238_090a_ShowAdvertisementsPopup(); } - - goto exit; + + // Far return + this.oCPU.Log.ExitBlock("F0_1238_0092_GameTurn"); + return; } // Instruction address 0x1238:0x02a0, size: 5 @@ -497,8 +496,8 @@ public void F0_1238_0092() && dynastyEndYear != this.oParent.CivState.Year) { // Far return - //this.oCPU.Log.ExitBlock("F0_1238_0092"); - //return; + this.oCPU.Log.ExitBlock("F0_1238_0092_GameTurn"); + return; } // Instruction address 0x1238:0x073b, size: 5 @@ -559,8 +558,7 @@ public void F0_1238_0092() if ((this.oParent.CivState.SpaceshipFlags & 0x100) == 0) { - // Shows civilization powergraph - + // Show power graph, civilization score and hall of fame // Instruction address 0x1238:0x0848, size: 3 F0_1238_08a0(); } @@ -574,23 +572,15 @@ public void F0_1238_0092() { this.oCPU.WriteUInt8(this.oCPU.DS.Word, 0xba06, 0x0); - // Your final score has entered - + // Your final score has entered the Hall of Fame. + // Do you want to keep playing ? // Instruction address 0x1238:0x0867, size: 5 this.oParent.Segment_2f4d.F0_2f4d_044f(0x1cf0); // Instruction address 0x1238:0x0879, size: 3 - ushort selectedOption = F0_1238_001e_ShowDialog(0xba06, 80, 80); - - this.oCPU.AX.Word = this.oCPU.SUB_UInt16(this.oCPU.AX.Word, 0x1); - this.oCPU.AX.Word = this.oCPU.NEG_UInt16(this.oCPU.AX.Word); - - var val = (ushort)((0x10000 - (ushort)(selectedOption - 1)) & 0xffff); + int selectedOption = F0_1238_001e_ShowDialog(0xba06, 80, 80); - // option 0 --> writing value 1 - // option 1 --> writing value 0 - - this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0xdc48, /*this.oCPU.AX.Word*/val); + this.oCPU.WriteUInt16(this.oCPU.DS.Word, 0xdc48, (ushort)(-(selectedOption - 1))); } else { @@ -599,15 +589,12 @@ public void F0_1238_0092() if (this.oCPU.ReadUInt16(this.oCPU.DS.Word, 0xdc48) != 0) { - // Show advertisements - // Instruction address 0x1238:0x0897, size: 3 - F0_1238_090a(); + F0_1238_090a_ShowAdvertisementsPopup(); } - exit: // Far return - this.oCPU.Log.ExitBlock("F0_1238_0092"); + this.oCPU.Log.ExitBlock("F0_1238_0092_GameTurn"); } /// @@ -648,11 +635,11 @@ public void F0_1238_08a0() } /// - /// ? + /// Shows popup with Microprose game advertisements. /// - public void F0_1238_090a() + public void F0_1238_090a_ShowAdvertisementsPopup() { - this.oCPU.Log.EnterBlock("F0_1238_090a()"); + this.oCPU.Log.EnterBlock("F0_1238_090a_ShowAdvertisementsPopup()"); // function body // Instruction address 0x1238:0x090a, size: 5 @@ -680,7 +667,7 @@ public void F0_1238_090a() this.oParent.Segment_2459.F0_2459_0918_WaitForKeyPressOrMouseClick(); // Far return - this.oCPU.Log.ExitBlock("F0_1238_090a"); + this.oCPU.Log.ExitBlock("F0_1238_090a_ShowAdvertisementsPopup"); } /// From bae7bb2ce1df78246fff672d10e80e8481d690f9 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Wed, 3 Dec 2025 04:20:17 +0300 Subject: [PATCH 10/10] Remove wrong using --- src/CivGame/Game/Segment_1238.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/CivGame/Game/Segment_1238.cs b/src/CivGame/Game/Segment_1238.cs index 07fa2ea..2c9b79e 100644 --- a/src/CivGame/Game/Segment_1238.cs +++ b/src/CivGame/Game/Segment_1238.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics; using Avalonia.Media; using IRB.VirtualCPU;