Skip to content

Commit ee63f79

Browse files
Fix: Assembler now allowed something like cmp ($124 + 4) * 10, previously rejected as "unsupported opcode"
Add: Quite a lot better TASS support
1 parent 56ac1c0 commit ee63f79

File tree

10 files changed

+401
-229
lines changed

10 files changed

+401
-229
lines changed

C64Models/C64Models.projitems

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
<Compile Include="$(MSBuildThisFileDirectory)Formats\Tap.cs" />
5858
<Compile Include="$(MSBuildThisFileDirectory)Machines\C128\C128.cs" />
5959
<Compile Include="$(MSBuildThisFileDirectory)Machines\C64\C64.cs" />
60+
<Compile Include="$(MSBuildThisFileDirectory)Parser\ASMFileParser.ParseContext.cs" />
61+
<Compile Include="$(MSBuildThisFileDirectory)Parser\ASMFileParser.PO.ConversionTab.cs" />
6062
<Compile Include="$(MSBuildThisFileDirectory)Parser\ASMFileParser.PO.CallMacro.cs" />
6163
<Compile Include="$(MSBuildThisFileDirectory)Parser\ASMFileParser.AssembleTarget.cs" />
6264
<Compile Include="$(MSBuildThisFileDirectory)Parser\ASMFileParser.PO.BASIC.cs" />
Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
using GR.Collections;
2+
using GR.Memory;
3+
using RetroDevStudio.Formats;
4+
using RetroDevStudio.Parser;
5+
using RetroDevStudio.Types;
6+
using System;
7+
using System.Collections.Generic;
8+
9+
namespace RetroDevStudio.Parser
10+
{
11+
public partial class ASMFileParser : ParserBase
12+
{
13+
private Map<byte, byte> POConversionTab( string PO, Map<byte, byte> textCodeMapping, int lineIndex, List<TokenInfo> lineTokenInfos )
14+
{
15+
if ( lineTokenInfos.Count < 2 )
16+
{
17+
AddError( lineIndex, Types.ErrorCode.E1302_MALFORMED_MACRO, $"Expected {PO} <Type = raw or scr or pet or mapping list>" );
18+
}
19+
else if ( lineTokenInfos[1].Content.ToUpper() == "RAW" )
20+
{
21+
textCodeMapping = m_TextCodeMappingRaw;
22+
}
23+
else if ( lineTokenInfos[1].Content.ToUpper() == "SCR" )
24+
{
25+
textCodeMapping = m_TextCodeMappingScr;
26+
}
27+
else if ( lineTokenInfos[1].Content.ToUpper() == "PET" )
28+
{
29+
textCodeMapping = m_TextCodeMappingPet;
30+
}
31+
else
32+
{
33+
// expecting mapping table
34+
if ( ( textCodeMapping == m_TextCodeMappingPet )
35+
|| ( textCodeMapping == m_TextCodeMappingRaw )
36+
|| ( textCodeMapping == m_TextCodeMappingScr ) )
37+
{
38+
// only reset mapping if previously mapping was a predefined one
39+
textCodeMapping = new GR.Collections.Map<byte, byte>();
40+
}
41+
else
42+
{
43+
// create new instance to avoid modifying previously stored mappings
44+
textCodeMapping = new GR.Collections.Map<byte, byte>( textCodeMapping );
45+
}
46+
47+
GR.Memory.ByteBuffer data = new GR.Memory.ByteBuffer();
48+
49+
int commaCount = 0;
50+
int startTokenIndex = 1;
51+
for ( int tokenIndex = 1; tokenIndex < lineTokenInfos.Count; ++tokenIndex )
52+
{
53+
string token = lineTokenInfos[tokenIndex].Content;
54+
55+
if ( ( tokenIndex == 1 )
56+
&& ( token == "#" ) )
57+
{
58+
// direct value?
59+
if ( ( lineTokenInfos.Count > 2 )
60+
&& ( lineTokenInfos[2].Content != "#" )
61+
&& ( lineTokenInfos[2].Content != "." ) )
62+
{
63+
// not a binary value
64+
continue;
65+
}
66+
}
67+
68+
if ( token == "," )
69+
{
70+
if ( startTokenIndex < tokenIndex )
71+
{
72+
if ( EvaluateTokens( lineIndex, lineTokenInfos, startTokenIndex, tokenIndex - startTokenIndex, textCodeMapping, out SymbolInfo aByte ) )
73+
{
74+
data.AppendU8( (byte)aByte.ToInteger() );
75+
}
76+
else
77+
{
78+
// could not fully parse
79+
AddError( lineIndex, Types.ErrorCode.E1000_SYNTAX_ERROR, "Could not parse " + TokensToExpression( lineTokenInfos, startTokenIndex, lineTokenInfos.Count - startTokenIndex ) );
80+
}
81+
}
82+
++commaCount;
83+
startTokenIndex = tokenIndex + 1;
84+
}
85+
}
86+
if ( startTokenIndex < lineTokenInfos.Count )
87+
{
88+
if ( EvaluateTokens( lineIndex, lineTokenInfos, startTokenIndex, lineTokenInfos.Count - startTokenIndex, textCodeMapping, out SymbolInfo aByte ) )
89+
{
90+
data.AppendU8( (byte)aByte.ToInteger() );
91+
}
92+
else
93+
{
94+
// could not fully parse
95+
AddError( lineIndex, Types.ErrorCode.E1000_SYNTAX_ERROR, "Could not parse " + TokensToExpression( lineTokenInfos, startTokenIndex, lineTokenInfos.Count - startTokenIndex ) );
96+
}
97+
}
98+
if ( ( data.Length % 2 ) != 0 )
99+
{
100+
AddError( lineIndex, Types.ErrorCode.E1000_SYNTAX_ERROR, "Mapping table must have pairs of bytes, found " + data.Length + " bytes" );
101+
}
102+
else
103+
{
104+
for ( int mapping = 0; mapping < data.Length / 2; ++mapping )
105+
{
106+
textCodeMapping[data.ByteAt( mapping * 2 )] = data.ByteAt( mapping * 2 + 1 );
107+
}
108+
}
109+
}
110+
111+
return textCodeMapping;
112+
}
113+
114+
115+
116+
private Map<byte, byte> POConversionTabTASS( string PO, Map<byte, byte> textCodeMapping, int lineIndex, List<TokenInfo> lineTokenInfos )
117+
{
118+
if ( lineTokenInfos.Count < 2 )
119+
{
120+
AddError( lineIndex, Types.ErrorCode.E1302_MALFORMED_MACRO, $@"Expected {PO} ""screen"", ""none""" );
121+
}
122+
else if ( lineTokenInfos[1].Content.ToUpper() == "\"NONE\"" )
123+
{
124+
textCodeMapping = m_TextCodeMappingRaw;
125+
}
126+
else if ( lineTokenInfos[1].Content.ToUpper() == "\"SCREEN\"" )
127+
{
128+
textCodeMapping = m_TextCodeMappingScr;
129+
}
130+
else
131+
{
132+
// expecting custom mapping table
133+
var encodingName = lineTokenInfos[1].Content.Substring( 1, lineTokenInfos[1].Content.Length - 1 );
134+
if ( !_ParseContext.TextMappings.ContainsKey( encodingName ) )
135+
{
136+
_ParseContext.TextMappings[encodingName] = new Map<byte, byte>();
137+
}
138+
textCodeMapping = _ParseContext.TextMappings[encodingName];
139+
}
140+
141+
return textCodeMapping;
142+
}
143+
144+
145+
146+
private ParseLineResult POConversionTabTASSEntry( string PO, Map<byte, byte> textCodeMapping, int lineIndex, List<TokenInfo> lineTokenInfos, out Map<byte, byte> ResultingMapping )
147+
{
148+
ResultingMapping = textCodeMapping;
149+
var parseResult = ParseLineInParameters( lineTokenInfos, 1, lineTokenInfos.Count - 1, lineIndex, out List<List<TokenInfo>> lineParams );
150+
if ( parseResult != ParseLineResult.OK )
151+
{
152+
return parseResult;
153+
}
154+
int firstIndex = 0;
155+
while ( firstIndex + 2 <= lineParams.Count )
156+
{
157+
if ( lineParams[firstIndex].Count == 1 )
158+
{
159+
// must be a string literal with two characters
160+
if ( ( lineParams[firstIndex][0].Type != TokenInfo.TokenType.LITERAL_STRING )
161+
|| ( lineParams[firstIndex][0].Content.Length != 4 ) )
162+
{
163+
AddError( lineIndex, Types.ErrorCode.E1302_MALFORMED_MACRO, $@"Expected a two character sized string literal" );
164+
return ParseLineResult.ERROR_ABORT;
165+
}
166+
// 2nd must be a byte value (or result in one)
167+
if ( !EvaluateTokens( lineIndex, lineParams[firstIndex + 1], 0, lineParams[firstIndex + 1].Count, textCodeMapping, out SymbolInfo aByte ) )
168+
{
169+
// could not fully parse
170+
AddError( lineIndex, Types.ErrorCode.E1000_SYNTAX_ERROR, "Could not parse " + TokensToExpression( lineParams[firstIndex + 1] ) );
171+
return ParseLineResult.ERROR_ABORT;
172+
}
173+
char firstChar = lineParams[firstIndex][0].Content[1];
174+
char lastChar = lineParams[firstIndex][0].Content[2];
175+
176+
for ( char c = firstChar; c <= lastChar; ++c )
177+
{
178+
textCodeMapping[(byte)c] = (byte)( aByte.ToInt32() + c - firstChar );
179+
}
180+
}
181+
firstIndex += 2;
182+
}
183+
if ( firstIndex < lineParams.Count )
184+
{
185+
AddError( lineIndex, Types.ErrorCode.E1302_MALFORMED_MACRO, $@"{PO} has incomplete mapping at the end" );
186+
return ParseLineResult.ERROR_ABORT;
187+
}
188+
/*
189+
else
190+
{
191+
// expecting mapping table
192+
if ( ( textCodeMapping == m_TextCodeMappingPet )
193+
|| ( textCodeMapping == m_TextCodeMappingRaw )
194+
|| ( textCodeMapping == m_TextCodeMappingScr ) )
195+
{
196+
// only reset mapping if previously mapping was a predefined one
197+
textCodeMapping = new GR.Collections.Map<byte, byte>();
198+
}
199+
else
200+
{
201+
// create new instance to avoid modifying previously stored mappings
202+
textCodeMapping = new GR.Collections.Map<byte, byte>( textCodeMapping );
203+
}
204+
205+
GR.Memory.ByteBuffer data = new GR.Memory.ByteBuffer();
206+
207+
int commaCount = 0;
208+
int startTokenIndex = 1;
209+
for ( int tokenIndex = 1; tokenIndex < lineTokenInfos.Count; ++tokenIndex )
210+
{
211+
string token = lineTokenInfos[tokenIndex].Content;
212+
213+
if ( ( tokenIndex == 1 )
214+
&& ( token == "#" ) )
215+
{
216+
// direct value?
217+
if ( ( lineTokenInfos.Count > 2 )
218+
&& ( lineTokenInfos[2].Content != "#" )
219+
&& ( lineTokenInfos[2].Content != "." ) )
220+
{
221+
// not a binary value
222+
continue;
223+
}
224+
}
225+
226+
if ( token == "," )
227+
{
228+
if ( startTokenIndex < tokenIndex )
229+
{
230+
if ( EvaluateTokens( lineIndex, lineTokenInfos, startTokenIndex, tokenIndex - startTokenIndex, textCodeMapping, out SymbolInfo aByte ) )
231+
{
232+
data.AppendU8( (byte)aByte.ToInteger() );
233+
}
234+
else
235+
{
236+
// could not fully parse
237+
AddError( lineIndex, Types.ErrorCode.E1000_SYNTAX_ERROR, "Could not parse " + TokensToExpression( lineTokenInfos, startTokenIndex, lineTokenInfos.Count - startTokenIndex ) );
238+
parseResult = ParseLineResult.ERROR_ABORT;
239+
}
240+
}
241+
++commaCount;
242+
startTokenIndex = tokenIndex + 1;
243+
}
244+
}
245+
if ( startTokenIndex < lineTokenInfos.Count )
246+
{
247+
if ( EvaluateTokens( lineIndex, lineTokenInfos, startTokenIndex, lineTokenInfos.Count - startTokenIndex, textCodeMapping, out SymbolInfo aByte ) )
248+
{
249+
data.AppendU8( (byte)aByte.ToInteger() );
250+
}
251+
else
252+
{
253+
// could not fully parse
254+
AddError( lineIndex, Types.ErrorCode.E1000_SYNTAX_ERROR, "Could not parse " + TokensToExpression( lineTokenInfos, startTokenIndex, lineTokenInfos.Count - startTokenIndex ) );
255+
parseResult = ParseLineResult.ERROR_ABORT;
256+
}
257+
}
258+
if ( ( data.Length % 2 ) != 0 )
259+
{
260+
AddError( lineIndex, Types.ErrorCode.E1000_SYNTAX_ERROR, "Mapping table must have pairs of bytes, found " + data.Length + " bytes" );
261+
parseResult = ParseLineResult.ERROR_ABORT;
262+
}
263+
else
264+
{
265+
for ( int mapping = 0; mapping < data.Length / 2; ++mapping )
266+
{
267+
textCodeMapping[data.ByteAt( mapping * 2 )] = data.ByteAt( mapping * 2 + 1 );
268+
}
269+
}
270+
}*/
271+
272+
ResultingMapping = textCodeMapping;
273+
return parseResult;
274+
}
275+
276+
277+
278+
}
279+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using GR.Memory;
2+
using RetroDevStudio.Formats;
3+
using RetroDevStudio.Parser;
4+
using RetroDevStudio.Types;
5+
using RetroDevStudio.Types.ASM;
6+
using System;
7+
using System.Collections.Generic;
8+
9+
10+
11+
namespace RetroDevStudio.Parser
12+
{
13+
public partial class ASMFileParser : ParserBase
14+
{
15+
public class ParseContext
16+
{
17+
public GR.Collections.Map<string,GR.Collections.Map<byte, byte>> TextMappings = new GR.Collections.Map<string, GR.Collections.Map<byte, byte>>();
18+
19+
}
20+
21+
22+
23+
}
24+
}

0 commit comments

Comments
 (0)