-
Notifications
You must be signed in to change notification settings - Fork 3
/
HexEmulator.pas
243 lines (229 loc) · 7.77 KB
/
HexEmulator.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
unit HexEmulator;
interface
uses ADTrmEmu;
type
THexEmulatorShowAs = (NoStr,HexStr, Int8Str, Uint8Str, Int16Str, Uint16Str, BinaryStr,NibbleStr,Float4Str);
THexEmulator = object
private
ShowChar : boolean; {shows ascii chars}
UnprintablesBlank: boolean;
HasTrailingSpace : boolean; {uses a space between chars}
ShowAs : THexEmulatorShowAs;
// History: array [1..10] of byte;
// HistoryLength:integer;
// HistoryWrPos:integer;
HistoryString: shortstring;
SyncString: shortstring;
SyncLength:integer;
SyncAND, SyncXOR: shortstring;
SyncLeading:boolean;
IsFrameEnd:boolean;
fSyncCount:integer;
fSyncCountChanged:boolean;
procedure NewChar(C:char);
procedure SetSyncCount(Value:integer);
public
NumChars: byte; {the number of chars put on terminal for each incoming char}
InvertData : boolean;
MaskMSB:boolean;
GulpCount:integer;
BigEndian : boolean;
procedure Init(iShowChar,iUnPrintablesBlank,iHasTrailingSpace, iInvertData: boolean; iMaskMSB:boolean ;
iShowAs:THexEmulatorShowAs;iNumChars:byte);
procedure SetSync(inSync,inXOR, inAND:shortstring; inLeading:boolean); //sets the Sync values
procedure ProcessChar(Sender: TObject;
C: Char; var ReplaceWith: String; Commands: TAdEmuCommandList;
CharSource: TAdCharSource);
function IsSyncCountChanged:boolean;
property SyncCount:integer read fSyncCount write SetSyncCount;
end; //HexEmulator
implementation
uses SysUtils, StStrL, StStrS, StUtils, Realterm1;
{$J+} //D7
procedure THexEmulator.Init(iShowChar,iUnPrintablesBlank,iHasTrailingSpace, iInvertData: boolean; iMaskMSB:boolean;
iShowAs:THexEmulatorShowAs;iNumChars:byte);
begin
ShowChar:=iShowChar;
UnPrintablesBlank :=iUnPrintablesBlank;
HasTrailingSpace:=iHasTrailingSpace;
ShowAs:=iShowAs;
NumChars:=iNumChars;
InvertData:=iInvertData;
MaskMSB:=iMaskMSB;
//HistoryLength:=0;
//HistoryWrPos:=0;
HistoryString:='';
GulpCount:=0;
SetSync('','','',false);
fSyncCountChanged:=true;
fSyncCount:=0;
end;
procedure THexEmulator.SetSyncCount(Value:integer);
begin
fSyncCount:=value;
fSyncCountChanged:=true;
end;
function THexEmulator.IsSyncCountChanged:boolean;
begin
result:=fSyncCountChanged;
fSyncCountChanged:=false;
end;
procedure THexEmulator.NewChar(C:char);
var i:integer;
begin
SyncLength:=length(SyncString);
if SyncLength=0 then exit;
if length(HistoryString) < SyncLength //length(HexEmulator.SyncString)
then HistoryString:=HistoryString+C
else HistoryString:= copy(HistoryString,2,SyncLength)+C;
//FrameEnd:=(HexEmulator.HistoryString=HexEmulator.SyncString);
IsFrameEnd:=true;
for i:=1 to SyncLength do begin //do bytewise
IsFrameEnd:= IsFrameEnd and
(byte(SyncString[i]) = (byte(HistoryString[i]) xor byte(SyncXOR[i])) and byte(SyncAND[i]));
end;
if IsFrameEnd then begin
inc(fSyncCount);
fSyncCountChanged:=true;
end
end;
procedure THexEmulator.ProcessChar(Sender: TObject;
C: Char; var ReplaceWith: String; Commands: TAdEmuCommandList;
CharSource: TAdCharSource);
{procedure TForm1.AdEmulator_HexProcessCharOld(CP: TObject; C: Char;
var Command: TEmuCommand);}
var CShow:string; //char to actually display
BinStr: string;
//LeadingSpaces:byte;
FrameEnd:boolean;
const PendingChars:integer=0; //used where displayed numbers are multi-byte
const WordInFrameCount:integer=0; //used to allow formatted frames to be displayed
const LastC:Char=char(0);
procedure MakeFloat4String;
const V: array[1..4] of char='1234';
begin
assert(PendingChars>0);
if (PendingChars>4) then PendingChars:=4;
if BigEndian
then V[5-PendingChars]:=C
else V[PendingChars]:=C;
if (PendingChars>=4) then begin
BinStr:=FloatToStrF(single(V),ffGeneral,4,3){+' '};
PendingChars:=0;
end
else BinStr:='';
end;
begin
PendingChars:=PendingChars+1; //as at least C is pending
//we do a raw invert before any other processing at all
if ( InvertData ) then begin
C:= char(not byte(C));
end;
if MaskMSB then begin
C:=char(127 and byte(C));
end;
NewChar(C);
FrameEnd:=IsFrameEnd;
if ShowChar
then begin
if UnprintablesBlank
and ((byte(C)<32) or (byte(C)>127))
then CShow:=' ' //don't try to print control codes
else CShow:=C;
end
else CShow:='';
case ShowAs of
NoStr : BinStr:='';
HexStr : BinStr:=IntToHex(Byte(C),2);
BinaryStr : BinStr:=BinaryBL(Byte(C));
NibbleStr : begin // nibbles divided by "."
BinStr:=BinaryBL(Byte(C));
insert('.',BinStr,5);
end;
Int8Str : begin
BinStr:=IntToStr(shortint(C));
LeftPadS(BinStr,4); //was3
end;
Uint8Str: begin
BinStr:=IntToStr(byte(C)); //must have space enabled to work properly...
LeftPadS(BinStr,3); //was4
end;
Int16Str,UInt16Str: begin
if PendingChars>=2 //no chars ready
then begin //put a word together
if ShowAs=Int16Str
then begin
if BigEndian
then BinStr:=IntToStr(MakeInteger16(byte(LastC),byte(C)))
else BinStr:=IntToStr(MakeInteger16(byte(C),byte(LastC)));
BinStr:=LeftPadS(BinStr,6);
end
else begin //uint16
if BigEndian
then BinStr:=IntToStr(MakeWord(byte(LastC),byte(C)))
else BinStr:=IntToStr(MakeWord(byte(C),byte(LastC)));
BinStr:=LeftPadS(BinStr,5);
end;
PendingChars:=0; //used them
end; //pending
end;
Float4Str: begin
MakeFloat4String;
{if PendingChars>=4 //no chars ready
then begin //put a word together
MakeFloat4Str;
PendingChars:=0; //used them
end; //pending }
end;//
end; //case
//Command.OtherStr := CShow+BinStr;
ReplaceWith := CShow+BinStr;
if (HasTrailingSpace) {and not (ShowAs = Uint8str)}
then ReplaceWith := ReplaceWith + ' ' //Command.OtherStr:=Command.OtherStr+' '
else begin
// if (CharCount and 1)<>0 //trys to give alternating colors...
// then begin
// Command.FColor:=Command.Fcolor xor 255;
// Command.bColor:=Command.bcolor xor 255;
// end;
end;
//IncCharCount(1);
if FrameEnd
then begin
if SyncLeading
then ReplaceWith := char(13)+char(10) + ReplaceWith
else ReplaceWith := ReplaceWith + char(13)+char(10);//Command.OtherStr:=Command.OtherStr+char(13)+char(10);
end;
if GulpCount>=1
then begin
dec(GulpCount);
//Command.Cmd:=eNone; // swallow this char
ReplaceWith := '';
end;
//Command.Ch:=char(0); //try to prevent spurious screen resizing
//assert(length(Command.OtherStr)<=10); // is this valid or too late?
assert(length(ReplaceWith)<=12); // is this valid or too late?
LastC:=C;
if FrameEnd then begin
PendingChars:=0; // forces some sort of sync...
WordInFrameCount:=0;
end;
Form1.SetTerminalCharColor(Sender,CharSource);
end;
//-------------------
procedure THexEmulator.SetSync(inSync,inXOR, inAND:shortstring; inLeading:boolean); //sets the Sync values
begin
SyncString:=inSync;
SyncAnd:=inAND;
SyncXOR:=inXOR;
SyncLeading:=inLeading;
if length(SyncAND)<>length(SyncString) //sync must be same size or default to FF
then begin
SyncAND:=CharStrS(#255,length(SyncString));
end;
if length(SyncXOR)<>length(SyncAnd) //default to 00
then begin
SyncXOR:=CharStrS(#0,length(SyncAND));
end;
end;
end.