1 /*****************************************************************************/
5 /* Data output routines */
9 /* (C) 2000-2004 Ullrich von Bassewitz */
10 /* Römerstrasse 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, or the end of the given Style
64 while (Count < RemainingBytes) {
65 if (MustDefLabel(PC+Count) || GetStyleAttr (PC+Count) != Style) {
71 /* Return the number of bytes */
77 static unsigned DoTable (attr_t Style, unsigned MemberSize, void (*TableFunc) (unsigned))
78 /* Output a table of bytes */
82 /* Count how many bytes may be output. */
83 unsigned Count = GetSpan (Style);
85 /* If the count is less than the member size, print a row of Count data
86 * bytes. We assume here that there is no member with a size that is less
89 if (Count < MemberSize) {
94 /* Make Count an even number of multiples of MemberSize */
95 Count &= ~(MemberSize-1);
97 /* Output as many data bytes lines as needed */
99 while (BytesLeft > 0) {
101 /* Calculate the number of bytes for the next line */
102 unsigned Chunk = (BytesLeft > BytesPerLine)? BytesPerLine : BytesLeft;
104 /* Output a line with these bytes */
112 /* If the next line is not the same style, add a separator */
113 if (CodeLeft() && GetStyleAttr (PC) != Style) {
117 /* Return the number of bytes output */
123 unsigned ByteTable (void)
124 /* Output a table of bytes */
126 /* Call the low level function */
127 return DoTable (atByteTab, 1, DataByteLine);
132 unsigned DByteTable (void)
133 /* Output a table of dbytes */
135 /* Call the low level function */
136 return DoTable (atDByteTab, 2, DataDByteLine);
141 unsigned WordTable (void)
142 /* Output a table of words */
144 /* Call the low level function */
145 return DoTable (atWordTab, 2, DataWordLine);
150 unsigned DWordTable (void)
151 /* Output a table of double words */
153 /* Call the low level function */
154 return DoTable (atDWordTab, 4, DataDWordLine);
159 unsigned AddrTable (void)
160 /* Output a table of addresses */
162 unsigned long BytesLeft = GetRemainingBytes ();
163 unsigned long Start = PC;
165 /* Loop while table bytes left and we don't need to create a label at the
168 while (BytesLeft && GetStyleAttr (PC) == atAddrTab) {
172 /* If just one byte is left, define it and bail out */
173 if (BytesLeft == 1 || GetStyleAttr (PC+1) != atAddrTab) {
178 /* More than one byte left. Define a forward label if necessary */
181 /* Now get the address from the PC */
182 Addr = GetCodeWord (PC);
184 /* In pass 1, define a label, in pass 2 output the line */
186 if (!HaveLabel (Addr)) {
190 const char* Label = GetLabel (Addr, PC);
192 /* OOPS! Should not happen */
193 Internal ("OOPS - Label for address 0x%06X disappeard!", Addr);
198 Output ("%s", Label);
203 /* Next table entry */
207 /* If we must define a label here, bail out */
208 if (BytesLeft && MustDefLabel (PC)) {
213 /* If the next line is not an address table line, add a separator */
214 if (CodeLeft() && GetStyleAttr (PC) != atAddrTab) {
218 /* Return the number of bytes output */
224 unsigned RtsTable (void)
225 /* Output a table of RTS addresses (address - 1) */
227 unsigned long BytesLeft = GetRemainingBytes ();
228 unsigned long Start = PC;
230 /* Loop while table bytes left and we don't need to create a label at the
233 while (BytesLeft && GetStyleAttr (PC) == atRtsTab) {
237 /* If just one byte is left, define it and bail out */
238 if (BytesLeft == 1 || GetStyleAttr (PC+1) != atRtsTab) {
243 /* More than one byte left. Define a forward label if necessary */
246 /* Now get the address from the PC */
247 Addr = (GetCodeWord (PC) + 1) & 0xFFFF;
249 /* In pass 1, define a label, in pass 2 output the line */
251 if (!HaveLabel (Addr)) {
255 const char* Label = GetLabel (Addr, PC);
257 /* OOPS! Should not happen */
258 Internal ("OOPS - Label for address 0x%06X disappeard!", Addr);
263 Output ("%s-1", Label);
268 /* Next table entry */
272 /* If we must define a label here, bail out */
273 if (BytesLeft && MustDefLabel (PC)) {
278 /* If the next line is not a return address table line, add a separator */
279 if (CodeLeft() && GetStyleAttr (PC) != atRtsTab) {
283 /* Return the number of bytes output */
289 unsigned TextTable (void)
290 /* Output a table of text messages */
292 /* Count how many bytes may be output. */
293 unsigned ByteCount = GetSpan (atTextTab);
295 /* Output as many data bytes lines as needed. */
296 unsigned BytesLeft = ByteCount;
297 while (BytesLeft > 0) {
301 /* Count the number of characters that can be output as such */
303 while (Count < BytesLeft && Count < BytesPerLine*4-1) {
304 unsigned char C = GetCodeByte (PC + Count);
305 if (C >= 0x20 && C <= 0x7E && C != '\"') {
312 /* If we have text, output it */
319 for (I = 0; I < Count; ++I) {
320 Output ("%c", GetCodeByte (PC+I));
325 unsigned Chunk = CBytes;
326 if (Chunk > BytesPerLine) {
327 Chunk = BytesPerLine;
329 LineComment (PC, Chunk);
337 /* Count the number of bytes that must be output as bytes */
339 while (Count < BytesLeft && Count < BytesPerLine) {
340 unsigned char C = GetCodeByte (PC + Count);
341 if (C < 0x20 || C > 0x7E || C == '\"') {
348 /* If we have raw output bytes, print them */
350 DataByteLine (Count);
357 /* If the next line is not a byte table line, add a separator */
358 if (CodeLeft() && GetStyleAttr (PC) != atTextTab) {
362 /* Return the number of bytes output */