]> git.sur5r.net Git - cc65/blob - src/da65/data.c
Revert "atari5200: fix COLOR defines' names"
[cc65] / src / da65 / data.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                  data.c                                   */
4 /*                                                                           */
5 /*                           Data output routines                            */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2000-2014, Ullrich von Bassewitz                                      */
10 /*                Roemerstrasse 52                                           */
11 /*                D-70794 Filderstadt                                        */
12 /* EMail:         uz@cc65.org                                                */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 /* da65 */
37 #include "attrtab.h"
38 #include "code.h"
39 #include "error.h"
40 #include "global.h"
41 #include "labels.h"
42 #include "output.h"
43 #include "data.h"
44
45
46
47 /*****************************************************************************/
48 /*                                   Code                                    */
49 /*****************************************************************************/
50
51
52
53 static unsigned GetSpan (attr_t Style)
54 /* Get the number of bytes for a given style */
55 {
56     /* Get the number of bytes still available */
57     unsigned RemainingBytes = GetRemainingBytes ();
58
59     /* Count how many bytes are available. This number is limited by the
60     ** number of remaining bytes, a label, a segment change, or the end of
61     ** the given Style attribute.
62     */
63     unsigned Count = 1;
64     while (Count < RemainingBytes) {
65         attr_t Attr;
66         if (MustDefLabel(PC+Count)) {
67             break;
68         }
69         Attr = GetAttr (PC+Count);
70         if ((Attr & atStyleMask) != Style) {
71             break;
72         }
73         if ((Attr & (atSegmentStart | atSegmentEnd))) {
74             break;
75         }
76         ++Count;
77     }
78
79     /* Return the number of bytes */
80     return Count;
81 }
82
83
84
85 static unsigned DoTable (attr_t Style, unsigned MemberSize, void (*TableFunc) (unsigned))
86 /* Output a table of bytes */
87 {
88     unsigned BytesLeft;
89
90     /* Count how many bytes may be output. */
91     unsigned Count = GetSpan (Style);
92
93     /* If the count is less than the member size, print a row of Count data
94     ** bytes. We assume here that there is no member with a size that is less
95     ** than BytesPerLine.
96     */
97     if (Count < MemberSize) {
98         DataByteLine (Count);
99         PC += Count;
100         return Count;
101     }
102
103     /* Make Count an even number of multiples of MemberSize */
104     Count &= ~(MemberSize-1);
105
106     /* Output as many data bytes lines as needed */
107     BytesLeft = Count;
108     while (BytesLeft > 0) {
109
110         /* Calculate the number of bytes for the next line */
111         unsigned Chunk = (BytesLeft > BytesPerLine)? BytesPerLine : BytesLeft;
112
113         /* Output a line with these bytes */
114         TableFunc (Chunk);
115
116         /* Next line */
117         BytesLeft -= Chunk;
118         PC        += Chunk;
119     }
120
121     /* If the next line is not the same style, add a separator */
122     if (CodeLeft() && GetStyleAttr (PC) != Style) {
123         SeparatorLine ();
124     }
125
126     /* Return the number of bytes output */
127     return Count;
128 }
129
130
131
132 unsigned ByteTable (void)
133 /* Output a table of bytes */
134 {
135     /* Call the low level function */
136     return DoTable (atByteTab, 1, DataByteLine);
137 }
138
139
140
141 unsigned DByteTable (void)
142 /* Output a table of dbytes */
143 {
144     /* Call the low level function */
145     return DoTable (atDByteTab, 2, DataDByteLine);
146 }
147
148
149
150 unsigned WordTable (void)
151 /* Output a table of words */
152 {
153     /* Call the low level function */
154     return DoTable (atWordTab, 2, DataWordLine);
155 }
156
157
158
159 unsigned DWordTable (void)
160 /* Output a table of double words */
161 {
162     /* Call the low level function */
163     return DoTable (atDWordTab, 4, DataDWordLine);
164 }
165
166
167
168 unsigned AddrTable (void)
169 /* Output a table of addresses */
170 {
171     unsigned long BytesLeft = GetRemainingBytes ();
172     unsigned long Start = PC;
173
174     /* Loop while table bytes left and we don't need to create a label at the
175     ** current position.
176     */
177     while (BytesLeft && GetStyleAttr (PC) == atAddrTab) {
178
179         unsigned Addr;
180
181         /* If just one byte is left, define it and bail out */
182         if (BytesLeft == 1 || GetStyleAttr (PC+1) != atAddrTab) {
183             DataByteLine (1);
184             ++PC;
185             break;
186         }
187
188         /* More than one byte left. Define a forward label if necessary */
189         ForwardLabel (1);
190
191         /* Now get the address from the PC */
192         Addr = GetCodeWord (PC);
193
194         /* In pass 1, define a label, in pass 2 output the line */
195         if (Pass == 1) {
196             if (!HaveLabel (Addr)) {
197                 AddIntLabel (Addr);
198             }
199         } else {
200             const char* Label = GetLabel (Addr, PC);
201             if (Label == 0) {
202                 /* OOPS! Should not happen */
203                 Internal ("OOPS - Label for address 0x%06X disappeard!", Addr);
204             }
205             Indent (MCol);
206             Output (".addr");
207             Indent (ACol);
208             Output ("%s", Label);
209             LineComment (PC, 2);
210             LineFeed ();
211         }
212
213         /* Next table entry */
214         PC        += 2;
215         BytesLeft -= 2;
216
217         /* If we must define a label here, bail out */
218         if (BytesLeft && MustDefLabel (PC)) {
219             break;
220         }
221     }
222
223     /* If the next line is not an address table line, add a separator */
224     if (CodeLeft() && GetStyleAttr (PC) != atAddrTab) {
225         SeparatorLine ();
226     }
227
228     /* Return the number of bytes output */
229     return PC - Start;
230 }
231
232
233
234 unsigned RtsTable (void)
235 /* Output a table of RTS addresses (address - 1) */
236 {
237     unsigned long BytesLeft = GetRemainingBytes ();
238     unsigned long Start = PC;
239
240     /* Loop while table bytes left and we don't need to create a label at the
241     ** current position.
242     */
243     while (BytesLeft && GetStyleAttr (PC) == atRtsTab) {
244
245         unsigned Addr;
246
247         /* If just one byte is left, define it and bail out */
248         if (BytesLeft == 1 || GetStyleAttr (PC+1) != atRtsTab) {
249             DataByteLine (1);
250             ++PC;
251             break;
252         }
253
254         /* More than one byte left. Define a forward label if necessary */
255         ForwardLabel (1);
256
257         /* Now get the address from the PC */
258         Addr = (GetCodeWord (PC) + 1) & 0xFFFF;
259
260         /* In pass 1, define a label, in pass 2 output the line */
261         if (Pass == 1) {
262             if (!HaveLabel (Addr)) {
263                 AddIntLabel (Addr);
264             }
265         } else {
266             const char* Label = GetLabel (Addr, PC);
267             if (Label == 0) {
268                 /* OOPS! Should not happen */
269                 Internal ("OOPS - Label for address 0x%06X disappeard!", Addr);
270             }
271             Indent (MCol);
272             Output (".word");
273             Indent (ACol);
274             Output ("%s-1", Label);
275             LineComment (PC, 2);
276             LineFeed ();
277         }
278
279         /* Next table entry */
280         PC        += 2;
281         BytesLeft -= 2;
282
283         /* If we must define a label here, bail out */
284         if (BytesLeft && MustDefLabel (PC)) {
285             break;
286         }
287     }
288
289     /* If the next line is not a return address table line, add a separator */
290     if (CodeLeft() && GetStyleAttr (PC) != atRtsTab) {
291         SeparatorLine ();
292     }
293
294     /* Return the number of bytes output */
295     return PC - Start;
296 }
297
298
299
300 unsigned TextTable (void)
301 /* Output a table of text messages */
302 {
303     /* Count how many bytes may be output. */
304     unsigned ByteCount = GetSpan (atTextTab);
305
306     /* Output as many data bytes lines as needed. */
307     unsigned BytesLeft = ByteCount;
308     while (BytesLeft > 0) {
309
310         unsigned I;
311
312         /* Count the number of characters that can be output as such */
313         unsigned Count = 0;
314         while (Count < BytesLeft && Count < BytesPerLine*4-1) {
315             unsigned char C = GetCodeByte (PC + Count);
316             if (C >= 0x20 && C <= 0x7E && C != '\"') {
317                 ++Count;
318             } else {
319                 break;
320             }
321         }
322
323         /* If we have text, output it */
324         if (Count > 0) {
325             unsigned CBytes;
326             Indent (MCol);
327             Output (".byte");
328             Indent (ACol);
329             Output ("\"");
330             for (I = 0; I < Count; ++I) {
331                 Output ("%c", GetCodeByte (PC+I));
332             }
333             Output ("\"");
334             CBytes = Count;
335             while (CBytes > 0) {
336                 unsigned Chunk = CBytes;
337                 if (Chunk > BytesPerLine) {
338                     Chunk = BytesPerLine;
339                 }
340                 LineComment (PC, Chunk);
341                 LineFeed ();
342                 CBytes -= Chunk;
343                 PC += Chunk;
344             }
345             BytesLeft -= Count;
346         }
347
348         /* Count the number of bytes that must be output as bytes */
349         Count = 0;
350         while (Count < BytesLeft && Count < BytesPerLine) {
351             unsigned char C = GetCodeByte (PC + Count);
352             if (C < 0x20 || C > 0x7E || C == '\"') {
353                 ++Count;
354             } else {
355                 break;
356             }
357         }
358
359         /* If we have raw output bytes, print them */
360         if (Count > 0) {
361             DataByteLine (Count);
362             PC += Count;
363             BytesLeft -= Count;
364         }
365
366     }
367
368     /* If the next line is not a byte table line, add a separator */
369     if (CodeLeft() && GetStyleAttr (PC) != atTextTab) {
370         SeparatorLine ();
371     }
372
373     /* Return the number of bytes output */
374     return ByteCount;
375 }