diff --git a/src/CivGame/Game/Overlay_14.cs b/src/CivGame/Game/Overlay_14.cs index 4387a0c..6f8b926 100644 --- a/src/CivGame/Game/Overlay_14.cs +++ b/src/CivGame/Game/Overlay_14.cs @@ -148,176 +148,93 @@ public void F14_0000_014b_ScienceReport(short playerID) this.oCPU.Log.EnterBlock($"F14_0000_014b_ScienceReport({playerID})"); // 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, 0x12); - this.oCPU.PUSH_UInt16(this.oCPU.SI.Word); - F14_0000_0000(0x4762, 1); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x2), 0x0); - this.oCPU.AX.Word = (ushort)oParent.CivState.DifficultyLevel; - this.oCPU.AX.Word = this.oCPU.SHL_UInt16(this.oCPU.AX.Word, 0x1); - this.oCPU.AX.Word = this.oCPU.ADD_UInt16(this.oCPU.AX.Word, (ushort)((short)this.oParent.Var_d2de)); - this.oCPU.AX.Word = this.oCPU.ADD_UInt16(this.oCPU.AX.Word, 0x6); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0xe), this.oCPU.AX.Word); - - this.oCPU.AX.Word = 0xb; - this.oCPU.AX.Word -= (ushort)this.oParent.CivState.Players[playerID].DiscoveredTechnologyCount; - this.oCPU.SI.Word = this.oCPU.AX.Word; - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0xe)), this.oCPU.SI.Word); - if (this.oCPU.Flags.GE) goto L018b; - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0xe), this.oCPU.SI.Word); + int multiplier = (oParent.CivState.DifficultyLevel << 1) + this.oParent.Var_d2de + 6; - L018b: - if (this.oParent.CivState.Year >= 0) goto L0197; - this.oCPU.CX.Word = 0x1; - goto L019a; + Player player = this.oParent.CivState.Players[playerID]; - L0197: - this.oCPU.CX.Word = 0x2; + if (multiplier < 11 - player.DiscoveredTechnologyCount) + { + multiplier = 11 - player.DiscoveredTechnologyCount; + } - L019a: - this.oCPU.AX.Word = (ushort)this.oParent.CivState.Players[playerID].DiscoveredTechnologyCount; - this.oCPU.IMUL_UInt16(this.oCPU.AX, this.oCPU.DX, this.oCPU.CX.Word); - this.oCPU.IMUL_UInt16(this.oCPU.AX, this.oCPU.DX, this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0xe))); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0xc), this.oCPU.AX.Word); + int progressTotal = player.DiscoveredTechnologyCount * (this.oParent.CivState.Year >= 0 ? 2 : 1) * multiplier; + // Space between two lightbulb images along X axis, in pixels // Instruction address 0x0000:0x01be, size: 5 - this.oParent.Segment_2dc4.F0_2dc4_007c_CheckValueRange( - 2432 / (this.oCPU.ReadInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0xc)) + 1), - 1, 64); - - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x12), this.oCPU.AX.Word); + int progressBarSpacing = this.oParent.Segment_2dc4.F0_2dc4_007c_CheckValueRange(2432 / (progressTotal + 1), 1, 64); // Instruction address 0x0000:0x01e9, size: 5 - this.oParent.Segment_2dc4.F0_2dc4_007c_CheckValueRange( - ((this.oCPU.ReadInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x12)) * - this.oCPU.ReadInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0xc))) / 8) + 8, + int progressBarWidth = this.oParent.Segment_2dc4.F0_2dc4_007c_CheckValueRange( + (progressBarSpacing * progressTotal / 8) + 8, 8, 304); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x8), this.oCPU.AX.Word); - 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.AX.Word = this.oCPU.SUB_UInt16(this.oCPU.AX.Word, 0xa0); - this.oCPU.AX.Word = this.oCPU.NEG_UInt16(this.oCPU.AX.Word); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x4), this.oCPU.AX.Word); - this.oCPU.CMP_UInt16(this.oCPU.AX.Word, 0x28); - if (this.oCPU.Flags.LE) goto L022e; - - // Instruction address 0x0000:0x0226, size: 5 - this.oParent.Graphics.F0_VGA_07d8_DrawImage(this.oParent.Var_19e8_Rectangle, 280, 140, 40, 60, this.oParent.Var_aa_Rectangle, 278, 2); - - L022e: - // Instruction address 0x0000:0x0244, size: 5 - this.oParent.Segment_1000.F0_1000_0bfa_FillRectangle(this.oParent.Var_aa_Rectangle, - this.oCPU.ReadInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x4)), 25, - this.oCPU.ReadInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x8)), 16, 9); + int progressBarStartX = 160 - progressBarWidth / 2; - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), 0x0); - goto L0281; - - L0253: - // Instruction address 0x0000:0x0270, size: 5 - this.oParent.Segment_1000.F0_1000_084d_DrawBitmapToScreen(this.oParent.Var_aa_Rectangle, - (this.oCPU.ReadInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x2)) / 8) + - this.oCPU.ReadInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x4)), 33, - this.oCPU.ReadUInt16(this.oCPU.DS.Word, (ushort)((0xc << 1) + 0xd4ce))); + if (progressBarStartX > 40) + { + // Show science advisor image + // Instruction address 0x0000:0x0226, size: 5 + this.oParent.Graphics.F0_VGA_07d8_DrawImage(this.oParent.Var_19e8_Rectangle, 280, 140, 40, 60, this.oParent.Var_aa_Rectangle, 278, 2); + } - this.oCPU.AX.Word = this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x12)); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x2), this.oCPU.ADD_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x2)), this.oCPU.AX.Word)); - 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)))); + // Instruction address 0x0000:0x0244, size: 5 + this.oParent.Segment_1000.F0_1000_0bfa_FillRectangle(this.oParent.Var_aa_Rectangle, progressBarStartX, 25, progressBarWidth, 16, 9); - L0281: // Instruction address 0x0000:0x0290, size: 5 - this.oParent.Segment_2dc4.F0_2dc4_007c_CheckValueRange( - this.oParent.CivState.Players[playerID].ResearchProgress, - 0, this.oCPU.ReadInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0xc))); - - this.oCPU.CMP_UInt16(this.oCPU.AX.Word, this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))); - if (this.oCPU.Flags.G) goto L0253; - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0xa), 0x1a); - - if (this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].ResearchTechnologyID == -1) goto L02ff; - - // Instruction address 0x0000:0x02b1, size: 5 - this.oParent.MSCAPI.strcpy(0xba06, "Researching "); - - // Instruction address 0x0000:0x02c8, size: 5 - this.oParent.MSCAPI.strcat(0xba06, - this.oParent.CivState.TechnologyDefinitions[this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID].ResearchTechnologyID].Name); - - // Instruction address 0x0000:0x02df, size: 5 - this.oParent.Segment_1182.F0_1182_00b3_DrawCenteredStringToScreen0(0xba06, 161, 26, 0); - - // Instruction address 0x0000:0x02f7, size: 5 - this.oParent.Segment_1182.F0_1182_00b3_DrawCenteredStringToScreen0(0xba06, 160, 26, 15); - - L02ff: - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0xa), 0x2a); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x10), 0x0); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6), 0x0); - goto L0355; + int progress = this.oParent.Segment_2dc4.F0_2dc4_007c_CheckValueRange(player.ResearchProgress, 0, progressTotal); + for (int i = 0; i <= progress; ++i) + { + // Instruction address 0x0000:0x0270, size: 5 + this.oParent.Segment_1000.F0_1000_084d_DrawBitmapToScreen(this.oParent.Var_aa_Rectangle, + progressBarSpacing * i / 8 + progressBarStartX, + 33, + this.oCPU.ReadUInt16(this.oCPU.DS.Word, (ushort)(24 + 0xd4ce))); + } - L0310: - this.oCPU.AX.Word = 0xb; + Player humanPlayer = this.oParent.CivState.Players[this.oParent.CivState.HumanPlayerID]; + if (humanPlayer.ResearchTechnologyID != -1) + { + string text = $"Researching {this.oParent.CivState.TechnologyDefinitions[humanPlayer.ResearchTechnologyID].Name}"; - L0313: - // Instruction address 0x0000:0x032f, size: 5 - this.oParent.Segment_1182.F0_1182_005c_DrawStringToScreen0(0xba06, - ((this.oCPU.ReadInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x10)) % 3) * 100) + 8, - this.oCPU.ReadInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0xa)), - this.oCPU.AX.Low); + // Instruction address 0x0000:0x02df, size: 5 + this.oParent.Segment_1182.F0_1182_00b3_DrawCenteredStringToScreen0(text, 161, 26, 0); - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x10), this.oCPU.INC_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x10)))); - this.oCPU.AX.Word = this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x10)); - this.oCPU.CWD(this.oCPU.AX, this.oCPU.DX); - this.oCPU.CX.Word = 0x3; - 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.NE) goto L034b; - this.oCPU.WriteUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0xa), this.oCPU.ADD_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0xa)), 0x7)); + // Instruction address 0x0000:0x02f7, size: 5 + this.oParent.Segment_1182.F0_1182_00b3_DrawCenteredStringToScreen0(text, 160, 26, 15); + } - L034b: - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0xa)), 0xc0); - if (this.oCPU.Flags.G) goto L03a4; + int textY = 42; + int column = 0; - L0352: - 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)))); + for (TechnologyEnum i = TechnologyEnum.Alphabet; i < TechnologyEnum.FutureTechnology5 && textY <= 192; ++i) + { + // Instruction address 0x0000:0x0361, size: 5 + if (!this.oParent.Segment_1ade.F0_1ade_22b5_PlayerHasTechnology(playerID, i)) + { + continue; + } - L0355: - this.oCPU.CMP_UInt16(this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6)), 0x48); - if (this.oCPU.Flags.GE) goto L03a4; + // Instruction address 0x0000:0x037b, size: 5 + this.oParent.MSCAPI.strcpy(0xba06, this.oParent.CivState.TechnologyDefinitions[(int)i].Name); - // Instruction address 0x0000:0x0361, size: 5 - this.oCPU.AX.Word = (ushort)(this.oParent.Segment_1ade.F0_1ade_22b5_PlayerHasTechnology(playerID, - (TechnologyEnum)this.oCPU.ReadInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))) ? 1 : 0); - this.oCPU.AX.Word = this.oCPU.OR_UInt16(this.oCPU.AX.Word, this.oCPU.AX.Word); - if (this.oCPU.Flags.E) - goto L0352; + byte color = (byte)(((this.oParent.CivState.TechnologyFirstDiscoveredBy[(int)i] & 0x7) == playerID) ? 15 : 11); - // Instruction address 0x0000:0x037b, size: 5 - this.oParent.MSCAPI.strcpy(0xba06, - this.oParent.CivState.TechnologyDefinitions[this.oCPU.ReadInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))].Name); + // Instruction address 0x0000:0x032f, size: 5 + this.oParent.Segment_1182.F0_1182_005c_DrawStringToScreen0(0xba06, (column % 3 * 100) + 8, textY, color); - this.oCPU.AX.Low = (byte)this.oParent.CivState.TechnologyFirstDiscoveredBy[this.oCPU.ReadUInt16(this.oCPU.SS.Word, (ushort)(this.oCPU.BP.Word - 0x6))]; - this.oCPU.AX.High = 0; - this.oCPU.AX.Word = this.oCPU.AND_UInt16(this.oCPU.AX.Word, 0x7); - this.oCPU.CMP_UInt16(this.oCPU.AX.Word, (ushort)playerID); - if (this.oCPU.Flags.E) goto L039e; - goto L0310; + ++column; - L039e: - this.oCPU.AX.Word = 0xf; - goto L0313; + if (column % 3 == 0) + { + // Advance to the next line + textY += 7; + } + } - L03a4: F14_0000_013b(); - this.oCPU.SI.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("F14_0000_014b_ScienceReport"); }