computer_interface.cs (5119B)
1 using Godot; 2 using System; 3 using static emulator; 4 5 public partial class computer_interface : Node { 6 7 const int INDEXES_BUTTON_DATA = 7; 8 const int INDEXES_BUTTON_ADDR = 15; 9 10 [Export] public Button[] buttons; 11 [Export] public Sprite2D[] lamp_current_instruction; 12 [Export] public Sprite2D[] lamp_addr; 13 14 [Export] public Color lamp_on = Colors.Red; 15 [Export] public Color lamp_off = Colors.DarkGray; 16 17 [Export] public Button button_off_on; 18 [Export] public Button button_stop; 19 [Export] public Button button_run; 20 [Export] public Button button_single_step; 21 [Export] public Button button_examine; 22 [Export] public Button button_examine_next; 23 [Export] public Button button_deposit; 24 [Export] public Button button_deposit_next; 25 [Export] public Button button_reset; 26 [Export] public Button button_clear; 27 28 IntPtr _emu; 29 ushort curr_addr; 30 byte curr_instr; 31 bool worked = false; 32 33 public override void _Ready() { 34 _emu = emu_create(); 35 36 int r = emu_load_program(_emu, "altair.bin"); 37 if (r != 0) { 38 GD.Print("error to load program: altair.bin"); 39 } 40 41 42 if (button_run != null) button_run.Pressed += run_pressed; 43 if (button_stop != null) button_stop.Pressed += stop_pressed; 44 if (button_single_step != null) button_single_step.Pressed += single_step_pressed; 45 if (button_examine != null) button_examine.Pressed += examine_pressed; 46 if (button_examine_next != null) button_examine_next.Pressed += examine_next_pressed; 47 if (button_deposit != null) button_deposit.Pressed += deposit_pressed; 48 if (button_deposit_next != null) button_deposit_next.Pressed += deposit_next_pressed; 49 if (button_reset != null) button_reset.Pressed += reset_pressed; 50 if (button_clear != null) button_clear.Pressed += clear_pressed; 51 52 if (buttons != null) { 53 for (int i = 0; i < buttons.Length; i++) { 54 if (buttons[i] != null) { 55 buttons[i].Pressed += bit_button_pressed; 56 } 57 } 58 } 59 60 update_lamps(); 61 } 62 63 public override void _Notification(int what) { 64 if (what == NotificationPredelete) { 65 emu_destroy(_emu); 66 } 67 } 68 69 public override void _Process(double delta) { 70 if (!worked) return; 71 72 int r = emu_step(_emu); 73 if (r > 0) { 74 worked = false; 75 return; 76 } 77 78 curr_addr = (ushort)emu_get_pc(_emu); 79 curr_instr = emu_mem_read(_emu, curr_addr); 80 81 update_lamps(); 82 83 byte reg_a = emu_get_reg(_emu, 0b111); 84 byte reg_b = emu_get_reg(_emu, 0b000); 85 byte reg_c = emu_get_reg(_emu, 0b001); 86 byte reg_d = emu_get_reg(_emu, 0b010); 87 GD.Print($"opcode=0x{curr_instr:X2}; pc=0x{curr_addr:X4}; a=0x{reg_a:X2}; b=0x{reg_b:X2}; c=0x{reg_c:X2}; d=0x{reg_d:X2}"); 88 } 89 90 void update_lamps() { 91 update_data_lamps(curr_instr); 92 update_addr_lamps(curr_addr); 93 } 94 95 ushort read_switches_addr() { 96 byte b0 = assem_byte(buttons, 0, 8); 97 byte b1 = assem_byte(buttons, 8, 8); 98 return (ushort)((b1 << 8) | b0); 99 } 100 101 byte read_switches_data() { 102 return assem_byte(buttons, 0, INDEXES_BUTTON_DATA + 1); 103 } 104 105 void bit_button_pressed() { 106 update_lamps(); 107 } 108 109 void run_pressed() { 110 worked = true; 111 } 112 113 void stop_pressed() { 114 worked = false; 115 } 116 117 void single_step_pressed() { 118 worked = false; 119 emu_step(_emu); 120 curr_addr = (ushort)emu_get_pc(_emu); 121 curr_instr = emu_mem_read(_emu, curr_addr); 122 update_lamps(); 123 } 124 125 void examine_pressed() { 126 worked = false; 127 curr_addr = read_switches_addr(); 128 emu_set_pc(_emu, curr_addr); 129 curr_instr = emu_mem_read(_emu, curr_addr); 130 update_lamps(); 131 132 GD.Print($"Examine at 0x{curr_addr:X4}: 0x{curr_instr:X2}"); 133 } 134 135 void examine_next_pressed() { 136 worked = false; 137 curr_addr++; 138 emu_set_pc(_emu, curr_addr); 139 curr_instr = emu_mem_read(_emu, curr_addr); 140 update_lamps(); 141 142 GD.Print($"Examine Next at 0x{curr_addr:X4}: 0x{curr_instr:X2}"); 143 } 144 145 void deposit_pressed() { 146 worked = false; 147 byte val = read_switches_data(); 148 149 emu_mem_write(_emu, curr_addr, val); 150 curr_instr = val; 151 update_lamps(); 152 153 GD.Print($"Deposit 0x{val:X2} at 0x{curr_addr:X4}"); 154 } 155 156 void deposit_next_pressed() { 157 worked = false; 158 159 curr_addr++; 160 emu_set_pc(_emu, curr_addr); 161 162 byte val = read_switches_data(); 163 emu_mem_write(_emu, curr_addr, val); 164 curr_instr = val; 165 update_lamps(); 166 167 GD.Print($"Deposit Next 0x{val:X2} at 0x{curr_addr:X4}"); 168 } 169 170 void reset_pressed() { 171 worked = false; 172 emu_set_pc(_emu, 0); 173 curr_addr = 0; 174 curr_instr = emu_mem_read(_emu, curr_addr); 175 update_lamps(); 176 } 177 178 void clear_pressed() { 179 update_lamps(); 180 } 181 182 void update_data_lamps(byte value) { 183 for (int i = 0; i < 8 && i < lamp_current_instruction.Length; i++) { 184 bool is_bit_set = (value & (1 << i)) != 0; 185 lamp_current_instruction[i].SelfModulate = is_bit_set ? lamp_on : lamp_off; 186 } 187 } 188 189 void update_addr_lamps(ushort value) { 190 for (int i = 0; i < 16 && i < lamp_addr.Length; i++) { 191 bool is_bit_set = (value & (1 << i)) != 0; 192 lamp_addr[i].SelfModulate = is_bit_set ? lamp_on : lamp_off; 193 } 194 } 195 196 byte assem_byte(Button[] btns, int offset, int count = 8) { 197 byte r = 0; 198 if (btns == null) return r; 199 200 for (int i = 0; i < count && i < 8; i++) { 201 int index = offset + i; 202 if (index < btns.Length && btns[index] != null && btns[index].ButtonPressed) { 203 r |= (byte)(1 << i); 204 } 205 } 206 return r; 207 } 208 209 }