1 /*****************************************************************************/
5 /* Data output routines */
9 /* (C) 2000-2007 Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
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. */
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: */
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 */
32 /*****************************************************************************/
47 /*****************************************************************************/
49 /*****************************************************************************/
53 static unsigned GetSpan (attr_t Style)
54 /* Get the number of bytes for a given style */
56 /* Get the number of bytes still available */
57 unsigned RemainingBytes = GetRemainingBytes ();
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.
64 while (Count < RemainingBytes) {
66 if (MustDefLabel(PC+Count)) {
69 Attr = GetAttr (PC+Count);
70 if ((Attr & atStyleMask) != Style) {
73 if ((Attr & atSegmentChange)) {
79 /* Return the number of bytes */
85 static unsigned DoTable (attr_t Style, unsigned MemberSize, void (*TableFunc) (unsigned))
86 /* Output a table of bytes */
90 /* Count how many bytes may be output. */
91 unsigned Count = GetSpan (Style);
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
97 if (Count < MemberSize) {
103 /* Make Count an even number of multiples of MemberSize */
104 Count &= ~(MemberSize-1);
106 /* Output as many data bytes lines as needed */
108 while (BytesLeft > 0) {
110 /* Calculate the number of bytes for the next line */
111 unsigned Chunk = (BytesLeft > BytesPerLine)? BytesPerLine : BytesLeft;
113 /* Output a line with these bytes */
121 /* If the next line is not the same style, add a separator */
122 if (CodeLeft() && GetStyleAttr (PC) != Style) {
126 /* Return the number of bytes output */
132 unsigned ByteTable (void)
133 /* Output a table of bytes */
135 /* Call the low level function */
136 return DoTable (atByteTab, 1, DataByteLine);
141 unsigned DByteTable (void)
142 /* Output a table of dbytes */
144 /* Call the low level function */
145 return DoTable (atDByteTab, 2, DataDByteLine);
150 unsigned WordTable (void)
151 /* Output a table of words */
153 /* Call the low level function */
154 return DoTable (atWordTab, 2, DataWordLine);
159 unsigned DWordTable (void)
160 /* Output a table of double words */
162 /* Call the low level function */
163 return DoTable (atDWordTab, 4, DataDWordLine);
168 unsigned AddrTable (void)
169 /* Output a table of addresses */
171 unsigned long BytesLeft = GetRemainingBytes ();
172 unsigned long Start = PC;
174 /* Loop while table bytes left and we don't need to create a label at the
177 while (BytesLeft && GetStyleAttr (PC) == atAddrTab) {
181 /* If just one byte is left, define it and bail out */
182 if (BytesLeft == 1 || GetStyleAttr (PC+1) != atAddrTab) {
188 /* More than one byte left. Define a forward label if necessary */
191 /* Now get the address from the PC */
192 Addr = GetCodeWord (PC);
194 /* In pass 1, define a label, in pass 2 output the line */
196 if (!HaveLabel (Addr)) {
200 const char* Label = GetLabel (Addr, PC);
202 /* OOPS! Should not happen */
203 Internal ("OOPS - Label for address 0x%06X disappeard!", Addr);
208 Output ("%s", Label);
213 /* Next table entry */
217 /* If we must define a label here, bail out */
218 if (BytesLeft && MustDefLabel (PC)) {
223 /* If the next line is not an address table line, add a separator */
224 if (CodeLeft() && GetStyleAttr (PC) != atAddrTab) {
228 /* Return the number of bytes output */
234 unsigned RtsTable (void)
235 /* Output a table of RTS addresses (address - 1) */
237 unsigned long BytesLeft = GetRemainingBytes ();
238 unsigned long Start = PC;
240 /* Loop while table bytes left and we don't need to create a label at the
243 while (BytesLeft && GetStyleAttr (PC) == atRtsTab) {
247 /* If just one byte is left, define it and bail out */
248 if (BytesLeft == 1 || GetStyleAttr (PC+1) != atRtsTab) {
254 /* More than one byte left. Define a forward label if necessary */
257 /* Now get the address from the PC */
258 Addr = (GetCodeWord (PC) + 1) & 0xFFFF;
260 /* In pass 1, define a label, in pass 2 output the line */
262 if (!HaveLabel (Addr)) {
266 const char* Label = GetLabel (Addr, PC);
268 /* OOPS! Should not happen */
269 Internal ("OOPS - Label for address 0x%06X disappeard!", Addr);
274 Output ("%s-1", Label);
279 /* Next table entry */
283 /* If we must define a label here, bail out */
284 if (BytesLeft && MustDefLabel (PC)) {
289 /* If the next line is not a return address table line, add a separator */
290 if (CodeLeft() && GetStyleAttr (PC) != atRtsTab) {
294 /* Return the number of bytes output */
300 unsigned TextTable (void)
301 /* Output a table of text messages */
303 /* Count how many bytes may be output. */
304 unsigned ByteCount = GetSpan (atTextTab);
306 /* Output as many data bytes lines as needed. */
307 unsigned BytesLeft = ByteCount;
308 while (BytesLeft > 0) {
312 /* Count the number of characters that can be output as such */
314 while (Count < BytesLeft && Count < BytesPerLine*4-1) {
315 unsigned char C = GetCodeByte (PC + Count);
316 if (C >= 0x20 && C <= 0x7E && C != '\"') {
323 /* If we have text, output it */
330 for (I = 0; I < Count; ++I) {
331 Output ("%c", GetCodeByte (PC+I));
336 unsigned Chunk = CBytes;
337 if (Chunk > BytesPerLine) {
338 Chunk = BytesPerLine;
340 LineComment (PC, Chunk);
348 /* Count the number of bytes that must be output as bytes */
350 while (Count < BytesLeft && Count < BytesPerLine) {
351 unsigned char C = GetCodeByte (PC + Count);
352 if (C < 0x20 || C > 0x7E || C == '\"') {
359 /* If we have raw output bytes, print them */
361 DataByteLine (Count);
368 /* If the next line is not a byte table line, add a separator */
369 if (CodeLeft() && GetStyleAttr (PC) != atTextTab) {
373 /* Return the number of bytes output */