]> Shamusworld >> Repos - rmac/blobdiff - direct.c
Fix for slow .incbin performance.
[rmac] / direct.c
index b1c368a4d2c8bd5b91ae3303fa60d97d3bc7c487..100db425f7afe7bad4fad3a0e5e64603fcfbb587 100644 (file)
--- a/direct.c
+++ b/direct.c
@@ -79,6 +79,7 @@ int (*dirtab[])() = {
    d_equrundef,                        // 50 .equrundef/.regundef
    d_ccundef,                  // 51 .ccundef
    d_print,                            // 52 .print
+   d_cstruct,                  // 53 .cstruct
 };
 
 
@@ -297,15 +298,15 @@ int d_noclear(void)
 //
 int d_incbin(void)
 {
-       int i, j;
+       int fd;
        int bytes = 0;
-       long pos, size;
-       char buf;
+       long pos, size, bytesRead;
+       char msg[256];
 
        // Check to see if we're in BSS, and, if so, throw an error
        if (scattr & SBSS)
        {
-               errors("Cannot include binary file \"%s\" in BSS section", string[tok[1]]);
+               errors("cannot include binary file \"%s\" in BSS section", string[tok[1]]);
                return ERROR;
        }
 
@@ -315,7 +316,7 @@ int d_incbin(void)
                return ERROR;
        }
 
-//     if ((j = open((char *)tok[1],  _OPEN_INC)) >= 0)
+#if 0
        if ((j = open(string[tok[1]],  _OPEN_INC)) >= 0)
        {
                size = lseek(j, 0L, SEEK_END);
@@ -336,12 +337,57 @@ int d_incbin(void)
        }
        else
        {
-//             errors("cannot open include binary file (%s)", (char *)tok[1]);
                errors("cannot open include binary file (%s)", string[tok[1]]);
                return ERROR;
        }
+#else
+       if ((fd = open(string[tok[1]],  _OPEN_INC)) < 0)
+       {
+               errors("cannot open include binary file (%s)", string[tok[1]]);
+               return ERROR;
+       }
+
+       size = lseek(fd, 0L, SEEK_END);
+       pos = lseek(fd, 0L, SEEK_SET);
+       chcheck(size);
+
+       DEBUG
+       {
+               printf("INCBIN: File '%s' is %li bytes.\n", string[tok[1]], size);
+       }
+
+#if 0
+       for(i=0; i<size; i++)
+       {
+               buf = '\0';
+               bytes = read(j, &buf, 1);
+               D_byte(buf);
+       }
+#else
+       char * fileBuffer = (char *)malloc(size);
+       bytesRead = read(fd, fileBuffer, size);
+
+       if (bytesRead != size)
+       {
+               sprintf(msg, "was only able to read %li bytes from binary file (%s, %li bytes)", bytesRead, string[tok[1]], size);
+               error(msg);
+               return ERROR;
+       }
+
+//#define D_byte(b)    {*chptr++=(char)b; ++sloc; ++ch_size; if(orgactive) ++orgaddr;}
+       memcpy(chptr, fileBuffer, size);
+       chptr += size;
+       sloc += size;
+       ch_size += size;
 
-       close(j);
+       if (orgactive)
+               orgaddr += size;
+
+       free(fileBuffer);
+#endif
+#endif
+
+       close(fd);
        return 0;
 }
 
@@ -798,6 +844,9 @@ int d_bss(void)
 //
 int d_ds(WORD siz)
 {
+if (verb_flag)
+       printf("Directive: .ds.[size] = %u, sloc = $%X\n", siz, sloc);
+
        VALUE eval;
 
        // This gets kind of stupid.  This directive is disallowed in normal 68000
@@ -816,7 +865,7 @@ int d_ds(WORD siz)
        // In non-TDB section (BSS, ABS and M6502) just advance the location
        // counter appropriately. In TDB sections, deposit (possibly large) chunks
        //of zeroed memory....
-       if ((scattr & SBSS))
+       if (scattr & SBSS)
        {
                listvalue(eval);
                eval *= siz;
@@ -825,7 +874,7 @@ int d_ds(WORD siz)
        }
        else
        {
-               dep_block(eval, siz, (VALUE)0, (WORD)(DEFINED|ABS), NULL);
+               dep_block(eval, siz, (VALUE)0, (WORD)(DEFINED | ABS), NULL);
        }
 
        at_eol();
@@ -1278,7 +1327,8 @@ int d_dsp(void)
 //
 int d_cargs(void)
 {
-       VALUE eval;
+       VALUE eval = 4;         // Default to 4 if no offset specified (to account for
+                                               // return address)
        WORD rlist;
        SYM * symbol;
        char * p;
@@ -1299,9 +1349,6 @@ int d_cargs(void)
                if (*tok == ',')
                        tok++;
        }
-       else 
-               // Default to 4 if not specified (because PC is on stack according to GroovyBee)
-               eval = 4;
 
        for(;;)
        {
@@ -1391,6 +1438,139 @@ int d_cargs(void)
 }
 
 
+//
+// .cstruct [#offset], symbol[.size], ...
+// 
+// Lists of registers may also be mentioned; they just take up space. Good for
+// "documentation" purposes:
+// 
+// .cstruct a6, .arg1, .arg2, .arg3...
+// 
+// Symbols thus created are ABS and EQUATED. Note that this is for
+// compatibility with VBCC and the Remover's library. Thanks to GroovyBee for
+// the suggestion.
+//
+int d_cstruct(void)
+{
+       VALUE eval = 0;         // Default, if no offset specified, is zero
+       WORD rlist;
+       SYM * symbol;
+       char * symbolName;
+       int env;
+       int i;
+
+       if (rgpu || rdsp)
+               return error("directive forbidden in gpu/dsp mode");
+
+       if (*tok == '#')
+       {
+               tok++;
+
+               if (abs_expr(&eval) != OK)
+                       return 0;
+
+               // Eat the comma, if it's there
+               if (*tok == ',')
+                       tok++;
+       }
+
+       for(;;)
+       {
+               if (*tok == SYMBOL)
+               {
+                       symbolName = string[tok[1]];
+
+                       // Set env to either local (dot prefixed) or global scope
+                       env = (symbolName[0] == '.' ? curenv : 0);
+                       symbol = lookup(symbolName, LABEL, env);
+
+                       // If the symbol wasn't found, then define it. Otherwise, throw an
+                       // error.
+                       if (symbol == NULL)
+                       {
+                               symbol = NewSymbol(symbolName, LABEL, env);
+                               symbol->sattr = 0;
+                       }
+                       else if (symbol->sattr & DEFINED)
+                               return errors("multiply-defined label '%s'", symbolName);
+
+                       // Put symbol in "order of definition" list
+                       if (!(symbol->sattr & SDECLLIST))
+                               sym_decl(symbol);
+
+                       tok += 2;
+
+                       // Adjust label start address if it's a word or a long, as a byte
+                       // label might have left us on an odd address.
+                       switch ((int)*tok)
+                       {
+                       case DOTW:
+                       case DOTL:
+                               eval += eval & 0x01;
+                       }
+
+                       symbol->sattr |= (ABS | DEFINED | EQUATED);
+                       symbol->svalue = eval;
+
+                       // Check for dot suffixes and adjust space accordingly (longs and
+                       // words on an odd boundary get bumped to the next word aligned
+                       // address). If no suffix, then throw an error.
+                       switch ((int)*tok)
+                       {
+                       case DOTL:
+                               eval += 4;
+                               break;
+                       case DOTW:
+                               eval += 2;
+                               break;
+                       case DOTB:
+                               eval += 1;
+                               break;
+                       default:
+                               return error("Symbol missing dot suffix in .cstruct construct");
+                       }
+
+                       tok++;
+               }
+               else if (*tok >= KW_D0 && *tok <= KW_A7)
+               {
+                       if (reglist(&rlist) < 0)
+                               return 0;
+
+                       for(i=0; i<16; i++, rlist>>=1)
+                       {
+                               if (rlist & 1)
+                                       eval += 4;
+                       }
+               }
+               else
+               {
+                       switch ((int)*tok)
+                       {
+                       case KW_USP:
+                       case KW_SSP:
+                       case KW_PC:
+                               eval += 2;
+                               // FALLTHROUGH
+                       case KW_SR:
+                       case KW_CCR:
+                               eval += 2;
+                               tok++;
+                               break;
+                       case EOL:
+                               return 0;
+                       default:
+                               return error(".cstruct syntax");
+                       }
+               }
+
+               // Eat commas in between each argument, if they exist
+               if (*tok == ',')
+                       tok++;
+       }
+}
+
+
 //
 // Undefine a macro - .undefmac macname [, macname...]
 //