Changeset 220
- Timestamp:
- Oct 20, 2020, 1:10:09 AM (4 years ago)
- Location:
- branches/CpuSingleSize
- Files:
-
- 4 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/CpuSingleSize/CpuSingleSize.lpi
r217 r220 75 75 </Item2> 76 76 </RequiredPackages> 77 <Units Count=" 18">77 <Units Count="20"> 78 78 <Unit0> 79 79 <Filename Value="CpuSingleSize.lpr"/> … … 175 175 <IsPartOfProject Value="True"/> 176 176 </Unit17> 177 <Unit18> 178 <Filename Value="Forms/UFormDevices.pas"/> 179 <IsPartOfProject Value="True"/> 180 <ComponentName Value="FormDevices"/> 181 <HasResources Value="True"/> 182 <ResourceBaseClass Value="Form"/> 183 </Unit18> 184 <Unit19> 185 <Filename Value="Forms/UFormStorage.pas"/> 186 <IsPartOfProject Value="True"/> 187 <ComponentName Value="FormStorage"/> 188 <HasResources Value="True"/> 189 <ResourceBaseClass Value="Form"/> 190 </Unit19> 177 191 </Units> 178 192 </ProjectOptions> -
branches/CpuSingleSize/CpuSingleSize.lpr
r217 r220 10 10 Forms, UFormMain, UCpu, UAssembler, UInstructions, UFormScreen, UMachine, 11 11 UFormCpu, UFormConsole, UFormAssembler, UCore, UFormDisassembler, 12 UDisassembler, UMemory, UFormMessages, UMessages, SysUtils, UFormHelp, UParser; 12 UDisassembler, UMemory, UFormMessages, UMessages, SysUtils, UFormHelp, 13 UParser, UFormDevices, UFormStorage; 13 14 14 15 {$R *.res} … … 30 31 Application.CreateForm(TCore, Core); 31 32 Application.CreateForm(TFormMain, FormMain); 32 Application.CreateForm(TFormScreen, FormScreen);33 Application.CreateForm(TFormConsole, FormConsole);34 33 Application.CreateForm(TFormCpu, FormCpu); 35 34 Application.CreateForm(TFormAssembler, FormAssembler); … … 37 36 Application.CreateForm(TFormMessages, FormMessages); 38 37 Application.CreateForm(TFormHelp, FormHelp); 38 Application.CreateForm(TFormDevices, FormDevices); 39 39 Application.Run; 40 40 end. -
branches/CpuSingleSize/Forms/UFormConsole.pas
r216 r220 13 13 { TFormConsole } 14 14 15 TFormConsole = class(TForm )15 TFormConsole = class(TFormDevice) 16 16 MemoConsole: TMemo; 17 17 Timer1: TTimer; … … 20 20 procedure MemoConsoleKeyPress(Sender: TObject; var Key: char); 21 21 procedure Timer1Timer(Sender: TObject); 22 private 23 22 protected 23 function GetDevice: TDevice; override; 24 procedure SetDevice(AValue: TDevice); override; 24 25 public 25 26 Console: TConsole; … … 55 56 end; 56 57 58 function TFormConsole.GetDevice: TDevice; 59 begin 60 Result := Console; 61 end; 62 63 procedure TFormConsole.SetDevice(AValue: TDevice); 64 begin 65 if AValue is TConsole then 66 Console := TConsole(AValue); 67 end; 68 57 69 procedure TFormConsole.MemoConsoleKeyPress(Sender: TObject; var Key: char); 58 70 begin -
branches/CpuSingleSize/Forms/UFormMain.lfm
r216 r220 105 105 object MenuItem12: TMenuItem 106 106 Caption = 'View' 107 object MenuItem13: TMenuItem108 Action = Core.AConsole109 end110 107 object MenuItem14: TMenuItem 111 108 Action = Core.ACpu 112 109 end 113 110 object MenuItem15: TMenuItem 114 Action = Core.A Screen111 Action = Core.ADevices 115 112 end 116 113 object MenuItem16: TMenuItem -
branches/CpuSingleSize/Forms/UFormMain.pas
r216 r220 22 22 MenuItem11: TMenuItem; 23 23 MenuItem12: TMenuItem; 24 MenuItem13: TMenuItem;25 24 MenuItem14: TMenuItem; 26 25 MenuItem15: TMenuItem; -
branches/CpuSingleSize/Forms/UFormScreen.pas
r216 r220 12 12 { TFormScreen } 13 13 14 TFormScreen = class(TForm )14 TFormScreen = class(TFormDevice) 15 15 PaintBox1: TPaintBox; 16 16 Timer1: TTimer; … … 21 21 private 22 22 TempBitmap: TBitmap; 23 protected 24 function GetDevice: TDevice; override; 25 procedure SetDevice(AValue: TDevice); override; 23 26 public 24 27 Screen: TScreen; … … 46 49 P := TempBitmap.ScanLine[Y]; 47 50 for X := 0 to Screen.Size.X - 1 do begin 48 P^ := Screen. Data[Y * Screen.Size.Y + X] * $010101;51 P^ := Screen.VideoMem[Y * Screen.Size.Y + X] * $010101; 49 52 Inc(P); 50 53 end; … … 53 56 PaintBox1.Refresh; 54 57 end; 58 end; 59 60 function TFormScreen.GetDevice: TDevice; 61 begin 62 Result := Screen; 63 end; 64 65 procedure TFormScreen.SetDevice(AValue: TDevice); 66 begin 67 if AValue is TScreen then 68 Screen := TScreen(AValue); 55 69 end; 56 70 -
branches/CpuSingleSize/Sample.asm
r219 r220 3 3 NOP 4 4 NOP 5 6 VAR DeviceConsole 1 7 VAR ConsoleReadChar 0 8 VAR ConsoleWriteChar 0 9 10 VAR DeviceKeyboard 2 11 12 VAR DeviceScreen 3 13 VAR ScreenGetWidth 0 14 VAR ScreenGetHeight 1 15 VAR ScreenSetAddr 0 16 VAR ScreenWrite 1 5 17 6 18 ORG 16 … … 63 75 PUSH R2 64 76 PUSH R3 65 SET R3, 0 77 PUSH R4 78 SET R3, ConsoleWriteChar 79 SET R4, DeviceConsole 66 80 WriteStrLoop: 67 81 LD R2, (R0) 68 OUT (R 3), R282 OUT (R4: R3), R2 69 83 INC R0 70 84 DEC R1 71 85 JNZ R1, WriteStrLoop 86 POP R4 72 87 POP R3 73 88 POP R2 74 89 RET 75 90 76 91 ClearScreen: 77 92 PUSH R0 78 93 PUSH R1 79 94 PUSH R2 80 SET R0, 1 95 PUSH R3 96 SET R0, ScreenSetAddr 81 97 SET R1, 0 82 OUT (R0), R1 83 SET R0, 3 84 IN R1, (R0) 85 SET R0, 4 86 IN R2, (R0) 98 SET R3, DeviceScreen 99 OUT (R3: R0), R1 100 SET R0, ScreenGetWidth 101 IN R1, (R3: R0) 102 SET R0, ScreenGetHeight 103 IN R2, (R3: R0) 87 104 MUL R2, R1 88 SET R0, 2105 SET R0, ScreenWrite 89 106 SET R1, 120 90 107 ClearScreenLoop: 91 OUT (R 0), R1108 OUT (R3: R0), R1 92 109 DEC R2 93 110 JNZ R2, ClearScreenLoop 111 POP R3 94 112 POP R2 95 113 POP R1 … … 104 122 PUSH R3 105 123 PUSH R2 106 SET R3, 0 107 IN R2, (R3) 108 OUT (R3), R2 124 PUSH R4 125 SET R4, DeviceConsole 126 SET R3, ConsoleReadChar 127 IN R2, (R4: R3) 128 SET R3, ConsoleWriteChar 129 OUT (R4: R3), R2 130 POP R4 109 131 POP R2 110 132 POP R3 -
branches/CpuSingleSize/UAssembler.pas
r219 r220 25 25 FOnError: TErrorEvent; 26 26 Parser: TParser; 27 function ParseVar: Boolean; 27 28 function ParseDb: Boolean; 28 29 function ParseOrg: Boolean; … … 36 37 Labels: TDictionary<string, Integer>; 37 38 LabelRefs: TList<TLabelRef>; 39 Variables: TDictionary<string, Integer>; 38 40 Messages: TMessages; 39 41 procedure Error(Text: string; Pos: TPoint); … … 81 83 end else 82 84 if Token.Kind = tkIdentifier then begin; 85 if Variables.TryGetValue(Token.Value, Addr) then begin 86 Memory.Write(Addr); 87 end else 83 88 if Labels.TryGetValue(Token.Value, Addr) then begin 84 89 Memory.Write(Addr); … … 107 112 while not Parser.CheckNextKind(tkEof) do begin 108 113 ParseLabel; 114 if ParseVar then begin 115 end else 109 116 if ParseDb then begin 110 117 end else … … 119 126 UpdateLabelRefs; 120 127 Error('Compilation finished.', Point(0, 0)); 128 end; 129 130 function TAssembler.ParseVar: Boolean; 131 var 132 TokenName: TToken; 133 TokenValue: TToken; 134 Number: TInteger; 135 begin 136 Result := False; 137 if Parser.CheckNextAndRead(tkIdentifier, 'VAR') then begin 138 Result := True; 139 while True do begin 140 TokenName := Parser.ReadNext; 141 if TokenName.Kind = tkIdentifier then begin 142 TokenValue := Parser.ReadNext; 143 if TokenValue.Kind = tkNumber then begin 144 if not Labels.ContainsKey(TokenName.Value) then begin 145 if TryStrToInt(TokenValue.Value, Number) then 146 Variables.Add(TokenName.Value, Number) 147 else Error('Expected number', TokenValue.Pos); 148 end else Error('Duplicate variable name ' + TokenName.Value, TokenName.Pos); 149 end else Error('Expected variable value.', TokenValue.Pos); 150 end else Error('Expected variable name.', TokenName.Pos); 151 if Parser.CheckNextAndRead(tkSpecialSymbol, ',') then begin 152 Continue; 153 end; 154 Break; 155 end; 156 end; 121 157 end; 122 158 … … 212 248 Parser.Expect(tkSpecialSymbol, ')'); 213 249 end else 250 if InstructionInfo.Params[I] = ptRegIndirectGroup then begin 251 Parser.Expect(tkSpecialSymbol, '('); 252 Token := Parser.ReadNext; 253 if (Token.Value <> '') and (Token.Value[1] = 'R') then begin 254 Token.Value := Copy(Token.Value, 2, MaxInt); 255 if TryStrToInt(Token.Value, Number) then begin 256 Memory.Write(Number); 257 Parser.Expect(tkSpecialSymbol, ':'); 258 Token := Parser.ReadNext; 259 if (Token.Value <> '') and (Token.Value[1] = 'R') then begin 260 Token.Value := Copy(Token.Value, 2, MaxInt); 261 if TryStrToInt(Token.Value, Number) then begin 262 Memory.Write(Number); 263 end else Error('Expected numeric register index error', Token.Pos); 264 end else Error('Expected register name starting with R character.', Token.Pos); 265 end else Error('Expected numeric register index error', Token.Pos); 266 end else Error('Expected register name starting with R character.', Token.Pos); 267 Parser.Expect(tkSpecialSymbol, ')'); 268 end else 214 269 end; 215 270 end; … … 271 326 Labels := TDictionary<string, Integer>.Create; 272 327 LabelRefs := TList<TLabelRef>.Create; 328 Variables := TDictionary<string, Integer>.Create; 273 329 end; 274 330 275 331 destructor TAssembler.Destroy; 276 332 begin 333 FreeAndNil(Variables); 277 334 FreeAndNil(Labels); 278 335 FreeAndNil(LabelRefs); -
branches/CpuSingleSize/UCore.lfm
r216 r220 58 58 OnExecute = ACpuExecute 59 59 end 60 object AConsole: TAction 61 Caption = 'Console' 62 OnExecute = AConsoleExecute 63 end 64 object AScreen: TAction 65 Caption = 'Screen' 66 OnExecute = AScreenExecute 60 object ADevices: TAction 61 Caption = 'Devices' 62 OnExecute = ADevicesExecute 67 63 end 68 64 object AHelp: TAction -
branches/CpuSingleSize/UCore.pas
r216 r220 16 16 AHelp: TAction; 17 17 ADisassembler: TAction; 18 AConsole: TAction;19 18 ACpu: TAction; 20 A Screen: TAction;19 ADevices: TAction; 21 20 ARunToCursor: TAction; 22 21 AStop: TAction; … … 31 30 ImageList1: TImageList; 32 31 procedure ACompileExecute(Sender: TObject); 33 procedure AConsoleExecute(Sender: TObject);34 32 procedure ACpuExecute(Sender: TObject); 33 procedure ADevicesExecute(Sender: TObject); 35 34 procedure ADisassemblerExecute(Sender: TObject); 36 35 procedure AExitExecute(Sender: TObject); 37 36 procedure AHelpExecute(Sender: TObject); 38 37 procedure ARunExecute(Sender: TObject); 39 procedure AScreenExecute(Sender: TObject);40 38 procedure AStopExecute(Sender: TObject); 41 39 procedure DataModuleCreate(Sender: TObject); … … 60 58 uses 61 59 UFormScreen, UFormCpu, UFormAssembler, UFormConsole, UFormHelp, 62 UFormDisassembler, UFormMessages ;60 UFormDisassembler, UFormMessages, UFormDevices; 63 61 64 62 { TCore } … … 78 76 ACompile.Execute; 79 77 Machine.PowerOn; 80 end;81 82 procedure TCore.AScreenExecute(Sender: TObject);83 begin84 FormScreen.Screen := Machine.Screen;85 FormScreen.Show;86 78 end; 87 79 … … 120 112 end; 121 113 122 procedure TCore.AConsoleExecute(Sender: TObject);123 begin124 FormConsole.Console := Machine.Console;125 FormConsole.Show;126 end;127 128 114 procedure TCore.ACpuExecute(Sender: TObject); 129 115 begin 130 116 FormCpu.Cpu := Machine.Cpu; 131 117 FormCpu.Show; 118 end; 119 120 procedure TCore.ADevicesExecute(Sender: TObject); 121 begin 122 FormDevices.Devices := Machine.Devices; 123 FormDevices.Show; 132 124 end; 133 125 -
branches/CpuSingleSize/UCpu.pas
r219 r220 17 17 18 18 TCpuThread = class; 19 TOutputEvent = procedure ( Port: TInteger; Value: TInteger) of object;20 TInputEvent = function ( Port: TInteger): TInteger of object;19 TOutputEvent = procedure (Device, Port: TInteger; Value: TInteger) of object; 20 TInputEvent = function (Device, Port: TInteger): TInteger of object; 21 21 22 22 { TCpu } … … 115 115 Port: TInteger; 116 116 Dest: TInteger; 117 Device: TInteger; 117 118 begin 118 119 Instruction := TInstruction(ReadNext); … … 136 137 inIn: begin 137 138 Index := ReadNext; 139 Device := R[ReadNext]; 138 140 Port := R[ReadNext]; 139 if Assigned(FOnInput) then R[Index] := FOnInput( Port);141 if Assigned(FOnInput) then R[Index] := FOnInput(Device, Port); 140 142 end; 141 143 inOut: begin 144 Device := R[ReadNext]; 142 145 Port := R[ReadNext]; 143 if Assigned(FOnOutput) then FOnOutput( Port, R[ReadNext]);146 if Assigned(FOnOutput) then FOnOutput(Device, Port, R[ReadNext]); 144 147 end; 145 148 inJump: IP := ReadNext; -
branches/CpuSingleSize/UDisassembler.pas
r219 r220 66 66 InstBytes := InstBytes + IntToHex(Value, 2) + ' '; 67 67 InstText := InstText + ' + ' + IntToStr(Value) + ')'; 68 end else 69 if InstructionInfo.Params[J] = ptRegIndirectGroup then begin 70 InstText := InstText + '(R' + IntToStr(Value); 71 Value := Memory.Read; 72 InstBytes := InstBytes + IntToHex(Value, 2) + ' '; 73 InstText := InstText + ': R' + IntToStr(Value) + ')'; 68 74 end; 69 75 end; -
branches/CpuSingleSize/UInstructions.pas
r219 r220 9 9 10 10 type 11 TParamType = (ptNone, ptNumber, ptReg, ptRegIndirect, ptRegIndirectIndex); 11 TParamType = (ptNone, ptNumber, ptReg, ptRegIndirect, ptRegIndirectIndex, 12 ptRegIndirectGroup); 12 13 TParamTypeArray = array of TParamType; 13 14 … … 82 83 AddNew(inAdd, 'ADD', [ptReg, ptReg], 'Adds second register to first register.'); 83 84 AddNew(inSub, 'SUB', [ptReg, ptReg], 'Subtracts second register from first register.'); 84 AddNew(inIn, 'IN', [ptReg, ptRegIndirect ], 'Reads value from input port to register.');85 AddNew(inOut, 'OUT', [ptRegIndirect , ptReg], 'Writes value from register to output port.');85 AddNew(inIn, 'IN', [ptReg, ptRegIndirectGroup], 'Reads value from input port to register.'); 86 AddNew(inOut, 'OUT', [ptRegIndirectGroup, ptReg], 'Writes value from register to output port.'); 86 87 AddNew(inJumpZero, 'JZ', [ptReg, ptNumber], 'Jumps to given address if value of register is zero'); 87 88 AddNew(inJumpNotZero, 'JNZ', [ptReg, ptNumber], 'Jumps to given address if value of register is not zero'); -
branches/CpuSingleSize/UMachine.pas
r216 r220 6 6 7 7 uses 8 Classes, SysUtils, UCpu, Syncobjs, UMemory, Generics.Collections ;8 Classes, SysUtils, UCpu, Syncobjs, UMemory, Generics.Collections, Forms; 9 9 10 10 type 11 TInputPort = (ipConsoleReadChar, ipConsoleInputCount, ipKeyboardRead, 12 ipScreenGetWidth, ipScreenGetHeight, ipStorageGetSize, ipStorageRead); 13 TOutputPort = (opConsoleWriteChar, opScreenSetAddr, opScreenWrite, 14 opStorageSetAddr, opStorageWrite); 11 TDeviceClass = (dcNone, dcKeyboard, dcMouse, dcStorage, dcScreen, dcConsole); 12 TDeviceClassSet = set of TDeviceClass; 13 14 TDevice = class; 15 16 { TFormDevice } 17 18 TFormDevice = class(TForm) 19 protected 20 function GetDevice: TDevice; virtual; 21 procedure SetDevice(AValue: TDevice); virtual; 22 public 23 property Device: TDevice read GetDevice write SetDevice; 24 end; 25 26 TFormDeviceClass = class of TFormDevice; 27 28 { TDevice } 15 29 16 30 TDevice = class 31 Index: Integer; 32 Name: string; 33 DeviceClass: TDeviceClass; 17 34 Cpu: TCpu; 18 35 InterruptVector: Integer; 19 end; 36 Form: TFormDevice; 37 procedure OutputHandler(Port, Data: TInteger); virtual; 38 function InputHandler(Port: TInteger): TInteger; virtual; 39 end; 40 41 { TDevices } 42 43 TDevices = class(TObjectList<TDevice>) 44 function GetDevicesCountByClass(DeviceClass: TDeviceClass): Integer; 45 function GetDevicesByClass(DeviceClass: TDeviceClass): TDevices; 46 function GetClasses: TDeviceClassSet; 47 end; 48 49 TDeviceManagerOutputPort = (opDeviceManagerClass, opDeviceManagerFirst, opDeviceManagerNext); 50 TDeviceManagerInputPort = (ipDeviceManagerCount, ipDeviceManagerGet); 51 52 { TDeviceManager } 53 54 TDeviceManager = class(TDevice) 55 DeviceClassFilter: TDeviceClass; 56 Index: Integer; 57 Devices: TDevices; 58 constructor Create; 59 procedure OutputHandler(Port, Data: TInteger); override; 60 function InputHandler(Port: TInteger): TInteger; override; 61 end; 62 63 TConsoleInputPort = (ipConsoleReadChar, ipConsoleInputCount); 64 TConsoleOutputPort = (opConsoleWriteChar); 20 65 21 66 { TConsole } … … 27 72 constructor Create; 28 73 destructor Destroy; override; 29 end; 74 procedure OutputHandler(Port, Data: TInteger); override; 75 function InputHandler(Port: TInteger): TInteger; override; 76 end; 77 78 TScreenInputPort = (ipScreenGetWidth, ipScreenGetHeight); 79 TScreenOutputPort = (opScreenSetAddr, opScreenWrite); 30 80 31 81 { TScreen } … … 37 87 public 38 88 Address: Integer; 39 Data: array of Byte;89 VideoMem: array of Byte; 40 90 Modified: Boolean; 41 91 constructor Create; 92 procedure OutputHandler(Port, Data: TInteger); override; 93 function InputHandler(Port: TInteger): TInteger; override; 42 94 property Size: TPoint read FSize write SetSize; 43 95 end; 44 96 97 TKeyboardInputPort = (ipKeyboardRead); 98 45 99 { TKeyboard } 46 100 47 101 TKeyboard = class(TDevice) 102 constructor Create; 48 103 function ReadKey: TInteger; 49 end; 104 function InputHandler(Port: TInteger): TInteger; override; 105 end; 106 107 TStorageInputPort = (ipStorageGetSize, ipStorageRead); 108 TStorageOutputPort = (opStorageSetAddr, opStorageWrite); 109 110 { TStorage } 50 111 51 112 TStorage = class(TDevice) … … 53 114 F: TFileStream; 54 115 FileName: string; 116 constructor Create; 117 procedure OutputHandler(Port, Data: TInteger); override; 118 function InputHandler(Port: TInteger): TInteger; override; 119 end; 120 121 { TMouse } 122 123 TMouse = class(TDevice) 124 constructor Create; 55 125 end; 56 126 … … 59 129 TMachine = class 60 130 private 61 procedure OutputHandler( Port, Data: TInteger);62 function InputHandler( Port: TInteger): TInteger;131 procedure OutputHandler(Device, Port, Data: TInteger); 132 function InputHandler(Device, Port: TInteger): TInteger; 63 133 public 64 134 Memory: TMemory; 65 135 Cpu: TCpu; 66 Screen: TScreen; 67 Keyboard: TKeyboard; 68 Console: TConsole; 69 Storage: TStorage; 136 Devices: TDevices; 137 procedure RegisterDevice(Device: TDevice); 138 procedure InitDevices; 70 139 procedure PowerOn; 71 140 procedure PowerOff; … … 74 143 end; 75 144 145 const 146 DeviceClassText: array[TDeviceClass] of string = ('None', 'Keyboard', 'Mouse', 'Storage', 'Screen', 'Console'); 147 76 148 77 149 implementation 78 150 151 { TDeviceManager } 152 153 constructor TDeviceManager.Create; 154 begin 155 DeviceClass := dcNone; 156 end; 157 158 procedure TDeviceManager.OutputHandler(Port, Data: TInteger); 159 begin 160 case TDeviceManagerOutputPort(Port) of 161 opDeviceManagerClass: DeviceClassFilter := TDeviceClass(Data); 162 opDeviceManagerFirst: Index := 0; 163 opDeviceManagerNext: Inc(Index); 164 end; 165 end; 166 167 function TDeviceManager.InputHandler(Port: TInteger): TInteger; 168 var 169 ClassDevices: TDevices; 170 begin 171 case TDeviceManagerInputPort(Port) of 172 ipDeviceManagerCount: Result := Devices.Count; 173 ipDeviceManagerGet: begin 174 ClassDevices := Devices.GetDevicesByClass(DeviceClassFilter); 175 if (Index >= 0) and (Index < ClassDevices.Count) then 176 Result := ClassDevices[Index].Index 177 else Result := 0; 178 ClassDevices.Free; 179 end; 180 end; 181 end; 182 183 { TFormDevice } 184 185 function TFormDevice.GetDevice: TDevice; 186 begin 187 Result := nil; 188 end; 189 190 procedure TFormDevice.SetDevice(AValue: TDevice); 191 begin 192 end; 193 194 195 { TDevices } 196 197 function TDevices.GetDevicesCountByClass(DeviceClass: TDeviceClass): Integer; 198 var 199 I: Integer; 200 begin 201 Result := 0; 202 for I := 0 to Count - 1 do 203 if Items[I].DeviceClass = DeviceClass then Inc(Result); 204 end; 205 206 function TDevices.GetDevicesByClass(DeviceClass: TDeviceClass): TDevices; 207 var 208 I: Integer; 209 begin 210 Result := TDevices.Create(False); 211 for I := 0 to Count - 1 do 212 if Items[I].DeviceClass = DeviceClass then Result.Add(Items[I]) 213 end; 214 215 function TDevices.GetClasses: TDeviceClassSet; 216 var 217 I: Integer; 218 begin 219 Result := []; 220 for I := 0 to Count - 1 do 221 if not (Items[I].DeviceClass in Result) then 222 Result := Result + [Items[I].DeviceClass]; 223 end; 224 225 { TDevice } 226 227 procedure TDevice.OutputHandler(Port, Data: TInteger); 228 begin 229 end; 230 231 function TDevice.InputHandler(Port: TInteger): TInteger; 232 begin 233 Result := 0; 234 end; 235 236 { TMouse } 237 238 constructor TMouse.Create; 239 begin 240 DeviceClass := dcMouse; 241 end; 242 243 { TStorage } 244 245 constructor TStorage.Create; 246 begin 247 DeviceClass := dcStorage; 248 end; 249 250 procedure TStorage.OutputHandler(Port, Data: TInteger); 251 begin 252 case TStorageOutputPort(Port) of 253 opStorageSetAddr: F.Position := Data * SizeOf(TInteger); 254 opStorageWrite: begin 255 F.WriteBuffer(Data, SizeOf(TInteger)); 256 end; 257 end; 258 end; 259 260 function TStorage.InputHandler(Port: TInteger): TInteger; 261 begin 262 case TStorageInputPort(Port) of 263 ipStorageGetSize: Result := F.Size div 4; 264 ipStorageRead: begin 265 F.ReadBuffer(Result, SizeOf(TInteger)); 266 end; 267 end; 268 end; 269 79 270 { TConsole } 80 271 81 272 constructor TConsole.Create; 82 273 begin 274 DeviceClass := dcConsole; 83 275 Lock := TCriticalSection.Create; 84 276 InputBuffer := TQueue<TInteger>.Create; … … 94 286 end; 95 287 288 procedure TConsole.OutputHandler(Port, Data: TInteger); 289 begin 290 case TConsoleOutputPort(Port) of 291 opConsoleWriteChar: begin 292 Lock.Acquire; 293 try 294 OutputBuffer.Enqueue(Data); 295 finally 296 Lock.Release; 297 end; 298 end; 299 end; 300 end; 301 302 function TConsole.InputHandler(Port: TInteger): TInteger; 303 begin 304 case TConsoleInputPort(Port) of 305 ipConsoleReadChar: begin 306 Lock.Acquire; 307 try 308 if InputBuffer.Count > 0 then begin 309 Result := InputBuffer.Dequeue; 310 end else Result := 0; 311 finally 312 Lock.Release; 313 end; 314 end; 315 ipConsoleInputCount: begin 316 Lock.Acquire; 317 try 318 Result := InputBuffer.Count; 319 finally 320 Lock.Release; 321 end; 322 end; 323 end; 324 end; 325 96 326 { TScreen } 97 327 … … 100 330 if FSize = AValue then Exit; 101 331 FSize := AValue; 102 SetLength( Data, FSize.X * FSize.Y);332 SetLength(VideoMem, FSize.X * FSize.Y); 103 333 end; 104 334 105 335 constructor TScreen.Create; 106 336 begin 337 DeviceClass := dcScreen; 107 338 Size := Point(640, 480); 108 339 end; 109 340 341 procedure TScreen.OutputHandler(Port, Data: TInteger); 342 begin 343 case TScreenOutputPort(Port) of 344 opScreenSetAddr: Address := Data; 345 opScreenWrite: if (Address >= 0) and (Address < Length(VideoMem)) then begin 346 VideoMem[Address] := Data; 347 Inc(Address); 348 Modified := True; 349 end; 350 end; 351 end; 352 353 function TScreen.InputHandler(Port: TInteger): TInteger; 354 begin 355 case TScreenInputPort(Port) of 356 ipScreenGetWidth: Result := Size.X; 357 ipScreenGetHeight: Result := Size.Y; 358 end; 359 end; 360 110 361 { TKeyboard } 111 362 … … 115 366 end; 116 367 368 function TKeyboard.InputHandler(Port: TInteger): TInteger; 369 begin 370 case TKeyboardInputPort(Port) of 371 ipKeyboardRead: Result := ReadKey; 372 end; 373 end; 374 375 constructor TKeyboard.Create; 376 begin 377 DeviceClass := dcKeyboard; 378 end; 379 117 380 { TMachine } 118 381 119 procedure TMachine.OutputHandler( Port, Data: TInteger);120 begin 121 case TOutputPort(Port) of122 opConsoleWriteChar: begin123 Console.Lock.Acquire;124 try 125 Console.OutputBuffer.Enqueue(Data);126 finally 127 Console.Lock.Release;128 end;129 e nd;130 opScreenSetAddr: Screen.Address := Data;131 opScreenWrite: if (Screen.Address >= 0) and (Screen.Address < Length(Screen.Data)) then begin 132 Screen.Data[Screen.Address] := Data;133 Inc(Screen.Address); 134 Screen.Modified := True;135 end;136 opStorageSetAddr: Storage.F.Position := Data * SizeOf(TInteger);137 opStorageWrite: begin138 Storage.F.WriteBuffer(Data, SizeOf(TInteger));139 140 end; 141 end;142 143 function TMachine.InputHandler(Port: TInteger): TInteger;144 begin 145 case TInputPort(Port) of146 ipConsoleReadChar: begin147 Console.Lock.Acquire;148 try149 if Console.InputBuffer.Count > 0 thenbegin150 Result := Console.InputBuffer.Dequeue;151 end else Result := 0;152 finally153 Console.Lock.Release; 154 end;155 end;156 ipConsoleInputCount: begin157 Console.Lock.Acquire; 158 try159 Result := Console.InputBuffer.Count;160 finally 161 Console.Lock.Release;162 end;163 end; 164 ipKeyboardRead: Result := Keyboard.ReadKey;165 ipScreenGetWidth: Result := Screen.Size.X;166 ipScreenGetHeight: Result := Screen.Size.Y; 167 ipStorageGetSize: Result := Storage.F.Size div 4;168 ipStorageRead: begin169 Storage.F.ReadBuffer(Result, SizeOf(TInteger)); 170 end;171 end;382 procedure TMachine.OutputHandler(Device, Port, Data: TInteger); 383 begin 384 if (Device > 0) and (Device < Devices.Count) then 385 Devices[Device].OutputHandler(Port, Data); 386 end; 387 388 function TMachine.InputHandler(Device, Port: TInteger): TInteger; 389 begin 390 if (Device > 0) and (Device < Devices.Count) then 391 Result := Devices[Device].InputHandler(Port) 392 else Result := 0; 393 end; 394 395 procedure TMachine.RegisterDevice(Device: TDevice); 396 begin 397 Device.Index := Devices.Count; 398 Device.Cpu := Cpu; 399 Device.Name := DeviceClassText[Device.DeviceClass] + ' ' + 400 IntToStr(Devices.GetDevicesCountByClass(Device.DeviceClass) + 1); 401 Devices.Add(Device); 402 end; 403 404 procedure TMachine.InitDevices; 405 var 406 Screen: TScreen; 407 Keyboard: TKeyboard; 408 Console: TConsole; 409 Storage: TStorage; 410 Mouse: TMouse; 411 DeviceManager: TDeviceManager; 412 begin 413 DeviceManager := TDeviceManager.Create; 414 DeviceManager.Devices := Devices; 415 RegisterDevice(DeviceManager); 416 417 Console := TConsole.Create; 418 RegisterDevice(Console); 419 Console.InterruptVector := 1; 420 421 Keyboard := TKeyboard.Create; 422 RegisterDevice(Keyboard); 423 424 Screen := TScreen.Create; 425 RegisterDevice(Screen); 426 427 Storage := TStorage.Create; 428 RegisterDevice(Storage); 429 430 Storage := TStorage.Create; 431 RegisterDevice(Storage); 432 433 Mouse := TMouse.Create; 434 RegisterDevice(Mouse); 172 435 end; 173 436 … … 185 448 constructor TMachine.Create; 186 449 begin 450 Devices := TDevices.Create; 187 451 Memory := TMemory.Create; 188 452 Memory.Size := 10000; … … 190 454 Cpu.OnInput := InputHandler; 191 455 Cpu.OnOutput := OutputHandler; 192 Keyboard := TKeyboard.Create; 193 Keyboard.Cpu := Cpu; 194 Screen := TScreen.Create; 195 Screen.Cpu := Cpu; 196 Console := TConsole.Create; 197 Console.Cpu := Cpu; 198 Console.InterruptVector := 1; 199 Storage := TStorage.Create; 200 Storage.Cpu := Cpu; 456 InitDevices; 201 457 end; 202 458 … … 204 460 begin 205 461 PowerOff; 206 FreeAndNil(Storage); 207 FreeAndNil(Console); 208 FreeAndNil(Screen); 209 FreeAndNil(Keyboard); 210 FreeAndNil(Cpu); 211 FreeAndNil(Memory); 462 FreeAndNil(Devices); 212 463 inherited; 213 464 end;
Note:
See TracChangeset
for help on using the changeset viewer.