1 | unit UMachine;
|
---|
2 |
|
---|
3 | {$mode delphi}
|
---|
4 |
|
---|
5 | interface
|
---|
6 |
|
---|
7 | uses
|
---|
8 | Classes, SysUtils, UCpu, syncobjs;
|
---|
9 |
|
---|
10 | type
|
---|
11 | TScreen = class
|
---|
12 | Size: TPoint;
|
---|
13 | MemoryBase: Integer;
|
---|
14 | MemorySize: Integer;
|
---|
15 | ChangedAreaFrom: Integer;
|
---|
16 | ChangedAreaTo: Integer;
|
---|
17 | end;
|
---|
18 |
|
---|
19 | { TMachine }
|
---|
20 |
|
---|
21 | TMachine = class
|
---|
22 | private
|
---|
23 | FMemorySize: Integer;
|
---|
24 | function CpuInput(Port: TAddress): TRegister;
|
---|
25 | procedure CpuOutput(Port: TAddress; Value: TRegister);
|
---|
26 | function GetMemorySize: Integer;
|
---|
27 | procedure SetMemorySize(AValue: Integer);
|
---|
28 | public
|
---|
29 | Memory: Pointer;
|
---|
30 | Cpu: TCpu;
|
---|
31 | Screen: TScreen;
|
---|
32 | InputBuffer: string;
|
---|
33 | OutputBuffer: string;
|
---|
34 | LockInput: TCriticalSection;
|
---|
35 | LockOutput: TCriticalSection;
|
---|
36 | procedure ClearMemory;
|
---|
37 | constructor Create;
|
---|
38 | destructor Destroy; override;
|
---|
39 | property MemorySize: Integer read GetMemorySize write SetMemorySize;
|
---|
40 | end;
|
---|
41 |
|
---|
42 | implementation
|
---|
43 |
|
---|
44 | { TMachine }
|
---|
45 |
|
---|
46 | constructor TMachine.Create;
|
---|
47 | begin
|
---|
48 | LockInput := TCriticalSection.Create;
|
---|
49 | LockOutput := TCriticalSection.Create;
|
---|
50 | Cpu := TCpu.Create;
|
---|
51 | Cpu.OnInput := CpuInput;
|
---|
52 | Cpu.OnOutput := CpuOutput;
|
---|
53 | Cpu.DataSizeBase := bw32;
|
---|
54 | Cpu.AddrSizeBase := bw32;
|
---|
55 | Screen := TScreen.Create;
|
---|
56 | Screen.Size := Point(320, 240);
|
---|
57 | Screen.MemoryBase := $200;
|
---|
58 | MemorySize := $1000000;
|
---|
59 | Cpu.Memory := Memory;
|
---|
60 | end;
|
---|
61 |
|
---|
62 | destructor TMachine.Destroy;
|
---|
63 | begin
|
---|
64 | Screen.Free;
|
---|
65 | Cpu.Free;
|
---|
66 | LockInput.Free;
|
---|
67 | LockOutput.Free;
|
---|
68 | inherited Destroy;
|
---|
69 | end;
|
---|
70 |
|
---|
71 | function TMachine.CpuInput(Port: TAddress): TRegister;
|
---|
72 | begin
|
---|
73 | Result.Q := 0;
|
---|
74 | case Port of
|
---|
75 | 0: begin
|
---|
76 | LockInput.Acquire;
|
---|
77 | while (Length(InputBuffer) = 0) and not Cpu.Terminated do begin
|
---|
78 | LockInput.Release;
|
---|
79 | Sleep(100);
|
---|
80 | LockInput.Acquire;
|
---|
81 | end;
|
---|
82 | if Length(InputBuffer) > 0 then begin
|
---|
83 | Result.B := Ord(InputBuffer[1]);
|
---|
84 | Delete(InputBuffer, 1, 1);
|
---|
85 | end else Result.B := 0;
|
---|
86 | LockInput.Release;
|
---|
87 | end;
|
---|
88 | 1: case Cpu.DataSize of
|
---|
89 | bw8: Result.B := Screen.Size.X;
|
---|
90 | bw16: Result.W := Screen.Size.X;
|
---|
91 | bw32: Result.D := Screen.Size.X;
|
---|
92 | bw64: Result.Q := Screen.Size.X;
|
---|
93 | end;
|
---|
94 | 2: case Cpu.DataSize of
|
---|
95 | bw8: Result.B := Screen.Size.Y;
|
---|
96 | bw16: Result.W := Screen.Size.Y;
|
---|
97 | bw32: Result.D := Screen.Size.Y;
|
---|
98 | bw64: Result.Q := Screen.Size.Y;
|
---|
99 | end;
|
---|
100 | 3: case Cpu.DataSize of
|
---|
101 | bw8: Result.B := Screen.MemoryBase;
|
---|
102 | bw16: Result.W := Screen.MemoryBase;
|
---|
103 | bw32: Result.D := Screen.MemoryBase;
|
---|
104 | bw64: Result.Q := Screen.MemoryBase;
|
---|
105 | end;
|
---|
106 | end;
|
---|
107 | end;
|
---|
108 |
|
---|
109 | procedure TMachine.CpuOutput(Port: TAddress; Value: TRegister);
|
---|
110 | begin
|
---|
111 | case Port of
|
---|
112 | 0: begin
|
---|
113 | LockOutput.Acquire;
|
---|
114 | OutputBuffer := OutputBuffer + Char(Value.B);
|
---|
115 | LockOutput.Release;
|
---|
116 | end;
|
---|
117 | 1: case Cpu.DataSize of
|
---|
118 | bw8: Screen.Size.X := Value.B;
|
---|
119 | bw16: Screen.Size.X := Value.W;
|
---|
120 | bw32: Screen.Size.X := Value.D;
|
---|
121 | bw64: Screen.Size.X := Value.Q;
|
---|
122 | end;
|
---|
123 | 2: case Cpu.DataSize of
|
---|
124 | bw8: Screen.Size.Y := Value.B;
|
---|
125 | bw16: Screen.Size.Y := Value.W;
|
---|
126 | bw32: Screen.Size.Y := Value.D;
|
---|
127 | bw64: Screen.Size.Y := Value.Q;
|
---|
128 | end;
|
---|
129 | 3: case Cpu.DataSize of
|
---|
130 | bw8: Screen.MemoryBase := Value.B;
|
---|
131 | bw16: Screen.MemoryBase := Value.W;
|
---|
132 | bw32: Screen.MemoryBase := Value.D;
|
---|
133 | bw64: Screen.MemoryBase := Value.Q;
|
---|
134 | end;
|
---|
135 | 4: case Cpu.DataSize of
|
---|
136 | bw8: Screen.ChangedAreaFrom := Value.B;
|
---|
137 | bw16: Screen.ChangedAreaFrom := Value.W;
|
---|
138 | bw32: Screen.ChangedAreaFrom := Value.D;
|
---|
139 | bw64: Screen.ChangedAreaFrom := Value.Q;
|
---|
140 | end;
|
---|
141 | 5: case Cpu.DataSize of
|
---|
142 | bw8: Screen.ChangedAreaTo := Value.B;
|
---|
143 | bw16: Screen.ChangedAreaTo := Value.W;
|
---|
144 | bw32: Screen.ChangedAreaTo := Value.D;
|
---|
145 | bw64: Screen.ChangedAreaTo := Value.Q;
|
---|
146 | end;
|
---|
147 | end;
|
---|
148 | end;
|
---|
149 |
|
---|
150 | function TMachine.GetMemorySize: Integer;
|
---|
151 | begin
|
---|
152 | Result := FMemorySize;
|
---|
153 | end;
|
---|
154 |
|
---|
155 | procedure TMachine.SetMemorySize(AValue: Integer);
|
---|
156 | begin
|
---|
157 | if FMemorySize = AValue then Exit;
|
---|
158 | FMemorySize := AValue;
|
---|
159 | Memory := ReAllocMem(Memory, FMemorySize);
|
---|
160 | end;
|
---|
161 |
|
---|
162 | procedure TMachine.ClearMemory;
|
---|
163 | begin
|
---|
164 | FillChar(Memory^, MemorySize, $ff);
|
---|
165 | end;
|
---|
166 |
|
---|
167 |
|
---|
168 | end.
|
---|
169 |
|
---|