OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [Open8 Tools/] [open8_src/] [open8_link/] [write.c] - Blame information for rev 266

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 178 jshamlet
 
2
#include <ctype.h>
3
#include <stdio.h>
4
#include <stdlib.h>
5
#include <string.h>
6
 
7
#include "defines.h"
8
#include "memory.h"
9
#include "write.h"
10
#include "files.h"
11
 
12
 
13
 
14
extern struct reference *reference_first, *reference_last;
15
extern struct label *labels_first, *labels_last;
16
extern struct object_file *obj_first, *obj_last, *obj_tmp;
17
extern struct section *sec_first, *sec_last, *sec_hd_first, sec_hd_last;
18
extern struct stack *stacks_first, *stacks_last;
19
extern struct slot slots[256];
20
extern unsigned char *rom, *rom_usage;
21
extern unsigned char *file_header, *file_footer;
22
extern int romsize, rombanks, banksize, verbose_mode, section_overwrite, symbol_mode;
23
extern int pc_bank, pc_full, pc_slot, pc_slot_max, snes_rom_mode;
24
extern int file_header_size, file_footer_size, *bankaddress, *banks;
25
extern int memory_file_id, memory_file_id_source, memory_line_number, output_mode;
26
extern int program_start, program_end, cpu_65816, snes_mode, smc_status;
27
extern int snes_sramsize;
28
 
29
 
30
 
31
static int _sections_sort(const void *a, const void *b) {
32
 
33
  if ((*((struct section **)a))->size < (*((struct section **)b))->size)
34
    return 1;
35
  return -1;
36
}
37
 
38
 
39
int smc_create_and_write(FILE *f) {
40
 
41
  int i;
42
 
43
 
44
  if (f == NULL)
45
    return FAILED;
46
 
47
  if (output_mode != OUTPUT_ROM)
48
    return FAILED;
49
 
50
  i = romsize/(8*1024);
51
 
52
  /* low byte of 8KB page count */
53
  fprintf(f, "%c", i & 0xFF);
54
  /* high byte of 8KB page count */
55
  fprintf(f, "%c", (i>>8) & 0xFF);
56
 
57
  /* emulation mode select (?) */
58
  i = 0;
59
  if (snes_rom_mode == SNES_ROM_MODE_HIROM)
60
    i |= (1<<5) | (1<<4);
61
  i |= (snes_sramsize ^ 3) << 2;
62
 
63
  fprintf(f, "%c", i);
64
 
65
  /* the rest of the header is zeroes */
66
  for (i = 0; i < 512-3; i++)
67
    fprintf(f, "%c", 0);
68
 
69
  return SUCCEEDED;
70
}
71
 
72
 
73
int insert_sections(void) {
74
 
75
  struct section *s, **sa;
76
  int d, f, i, x, t, q, sn, p;
77
  char *ram_slots[256], *c;
78
 
79
 
80
  /* initialize ram slots */
81
  for (i = 0; i < 256; i++)
82
    ram_slots[i] = NULL;
83
 
84
  /* find all touched slots */
85
  s = sec_first;
86
  while (s != NULL) {
87
    if (s->status == SECTION_STATUS_RAM && ram_slots[s->slot] == NULL) {
88
      ram_slots[s->slot] = malloc(slots[s->slot].size);
89
      if (ram_slots[s->slot] == NULL) {
90
        fprintf(stderr, "INSERT_SECTIONS: Out of memory error.\n");
91
        return FAILED;
92
      }
93
      memset(ram_slots[s->slot], 0, slots[s->slot].size);
94
    }
95
    s = s->next;
96
  }
97
 
98
  /* count the sections */
99
  i = 0;
100
  s = sec_first;
101
  while (s != NULL) {
102
    /* no references - skip it */
103
    if (s->alive == YES)
104
      i++;
105
    s = s->next;
106
  }
107
  sn = i;
108
 
109
  if (sn == 0)
110
    return SUCCEEDED;
111
 
112
  sa = malloc(sizeof(struct section *) * sn);
113
  if (sa == NULL) {
114
    fprintf(stderr, "INSERT_SECTIONS: Out of memory error.\n");
115
    return FAILED;
116
  }
117
 
118
  /* insert the sections into an array for sorting */
119
  i = 0;
120
  s = sec_first;
121
  while (s != NULL) {
122
    /* no references - skip it */
123
    if (s->alive == YES)
124
      sa[i++] = s;
125
    s = s->next;
126
  }
127
 
128
  /* sort the sections by size, biggest first */
129
  qsort(sa, sn, sizeof(struct section *), _sections_sort);
130
 
131
  /* print the sizes (DEBUG) */
132
  /*
133
  for (d = 0; d < i; d++)
134
    fprintf(stderr, "SIZE: %d\n", sa[d]->size);
135
  */
136
 
137
  /* ram sections */
138
  p = 0;
139
  while (p < sn) {
140
    s = sa[p++];
141
 
142
    /* search for free space */
143
    if (s->status == SECTION_STATUS_RAM) {
144
      c = ram_slots[s->slot];
145
      i = slots[s->slot].size;
146
      t = 0;
147
      for (x = 0; x < i; x++, c++) {
148
        if (*c == 0) {
149
          for (q = 0; x < i && q < s->size; x++, q++, c++) {
150
            if (*c != 0)
151
              break;
152
          }
153
          if (q == s->size) {
154
            t = 1;
155
            break;
156
          }
157
        }
158
      }
159
 
160
      if (t == 0) {
161
        fprintf(stderr, "INSERT_SECTIONS: No room for RAM section \"%s\" (%d bytes) in slot %d.\n", s->name, s->size, s->slot);
162
        return FAILED;
163
      }
164
 
165
      /* mark as used */
166
      c = c - s->size;
167
      for (i = 0; i < s->size; i++, c++)
168
        *c = 1;
169
 
170
      s->address = c - s->size - ram_slots[s->slot];
171
    }
172
  }
173
 
174
  /* free tmp memory */
175
  for (i = 0; i < 256; i++) {
176
    if (ram_slots[i] != NULL)
177
      free(ram_slots[i]);
178
  }
179
 
180
  /* force sections */
181
  p = 0;
182
  while (p < sn) {
183
    s = sa[p++];
184
    if (s->status == SECTION_STATUS_FORCE) {
185
      memory_file_id = s->file_id;
186
      banksize = banks[s->bank];
187
      pc_bank = s->address;
188
      pc_slot = slots[s->slot].address + pc_bank;
189
      pc_full = pc_bank + bankaddress[s->bank];
190
      pc_slot_max = slots[s->slot].address + slots[s->slot].size;
191
      d = pc_full;
192
      i = d + s->size;
193
      s->output_address = d;
194
      section_overwrite = OFF;
195
      if (i > romsize) {
196
        fprintf(stderr, "%s:%s: INSERT_SECTIONS: Section \"%s\" (%d bytes) goes beyond the ROM size.\n", get_file_name(s->file_id),
197
                get_source_file_name(s->file_id, s->file_id_source), s->name, s->size);
198
        return FAILED;
199
      }
200
      if (s->address + s->size > banksize) {
201
        fprintf(stderr, "%s:%s: INSERT_SECTIONS: Section \"%s\" (%d bytes) overflows from ROM bank %d.\n", get_file_name(s->file_id),
202
                get_source_file_name(s->file_id, s->file_id_source), s->name, s->size, s->bank);
203
        return FAILED;
204
      }
205
      for (; d < i; d++) {
206
        if (rom_usage[d] != 0 && rom[d] != s->data[d - pc_full])
207
          break;
208
      }
209
      if (d == i) {
210
        for (i = 0; i < s->size; i++) {
211
          if (mem_insert_pc(s->data[i], s->slot, s->bank) == FAILED)
212
            return FAILED;
213
        }
214
      }
215
      else {
216
        fprintf(stderr, "%s:%s: INSERT_SECTIONS: No room for section \"%s\" (%d bytes).\n", get_file_name(s->file_id),
217
                get_source_file_name(s->file_id, s->file_id_source), s->name, s->size);
218
        return FAILED;
219
      }
220
    }
221
  }
222
 
223
  /* absolute sections */
224
  p = 0;
225
  while (p < sn) {
226
    s = sa[p++];
227
    if (s->status == SECTION_STATUS_ABSOLUTE) {
228
      d = s->address;
229
      s->output_address = d;
230
      section_overwrite = ON;
231
      for (i = 0; i < s->size; i++) {
232
        if (mem_insert(d + i, s->data[i]) == FAILED)
233
          return FAILED;
234
      }
235
    }
236
  }
237
 
238
  /* free & semifree sections */
239
  p = 0;
240
  while (p < sn) {
241
    s = sa[p++];
242
    if (s->status == SECTION_STATUS_FREE || s->status == SECTION_STATUS_SEMIFREE) {
243
      pc_bank = s->address;
244
      d = bankaddress[s->bank];
245
 
246
      /* align the starting address */
247
      f = (pc_bank + d) % s->alignment;
248
      if (f > 0)
249
        pc_bank += s->alignment - f;
250
 
251
      i = FAILED;
252
      while (i == FAILED) {
253
        f = pc_bank;
254
        for (x = 0; pc_bank < banks[s->bank] && rom_usage[pc_bank + d] == 0 && x < s->size; pc_bank++, x++);
255
        if (x == s->size) {
256
          i = SUCCEEDED;
257
          break;
258
        }
259
        if (pc_bank == banks[s->bank]) {
260
          fprintf(stderr, "%s:%s: INSERT_SECTIONS: No room for section \"%s\" (%d bytes) in ROM bank %d.\n", get_file_name(s->file_id),
261
                  get_source_file_name(s->file_id, s->file_id_source), s->name, s->size, s->bank);
262
          return FAILED;
263
        }
264
 
265
        /* find the next starting address */
266
        f = (pc_bank + d) % s->alignment;
267
        if (f > 0)
268
          pc_bank += s->alignment - f;
269
        for (; pc_bank < banks[s->bank] && rom_usage[pc_bank + d] != 0; pc_bank += s->alignment);
270
      }
271
 
272
      memory_file_id = s->file_id;
273
      banksize = banks[s->bank];
274
      pc_bank = f;
275
      pc_slot = slots[s->slot].address + pc_bank;
276
      pc_full = pc_bank + bankaddress[s->bank];
277
      pc_slot_max = slots[s->slot].address + slots[s->slot].size;
278
      s->address = pc_bank;
279
      s->output_address = pc_full;
280
      section_overwrite = OFF;
281
      for (i = 0; i < s->size; i++) {
282
        if (mem_insert_pc(s->data[i], s->slot, s->bank) == FAILED)
283
          return FAILED;
284
      }
285
    }
286
  }
287
 
288
  /* superfree sections */
289
  p = 0;
290
  while (p < sn) {
291
    s = sa[p++];
292
    if (s->status == SECTION_STATUS_SUPERFREE) {
293
      /* go through all the banks */
294
      i = FAILED;
295
      f = 0;
296
 
297
      for (q = 0; i == FAILED && q < rombanks; q++) {
298
        pc_bank = 0;
299
        d = bankaddress[q];
300
 
301
        /* align the starting address */
302
        f = (pc_bank + d) % s->alignment;
303
        if (f > 0)
304
          pc_bank += s->alignment - f;
305
 
306
        /* if the slotsize and banksize differ -> try the next bank */
307
        if (banks[q] != slots[s->slot].size)
308
          continue;
309
 
310
        while (i == FAILED) {
311
          f = pc_bank;
312
          for (x = 0; pc_bank < banks[q] && rom_usage[pc_bank + d] == 0 && x < s->size; pc_bank++, x++);
313
          if (x == s->size) {
314
            i = SUCCEEDED;
315
            break;
316
          }
317
          if (pc_bank == banks[q])
318
            break;
319
 
320
          /* find the next starting address */
321
          f = (pc_bank + d) % s->alignment;
322
          if (f > 0)
323
            pc_bank += s->alignment - f;
324
          for (; pc_bank < banks[s->bank] && rom_usage[pc_bank + d] != 0; pc_bank += s->alignment);
325
        }
326
      }
327
 
328
      if (i == SUCCEEDED) {
329
        s->bank = q-1;
330
        memory_file_id = s->file_id;
331
        banksize = banks[s->bank];
332
        pc_bank = f;
333
        pc_slot = pc_bank;
334
        pc_full = pc_bank + bankaddress[s->bank];
335
        pc_slot_max = slots[s->slot].size;
336
        s->address = pc_bank;
337
        s->output_address = pc_full;
338
        section_overwrite = OFF;
339
 
340
        for (i = 0; i < s->size; i++)
341
          if (mem_insert_pc(s->data[i], s->slot, s->bank) == FAILED)
342
            return FAILED;
343
      }
344
      else {
345
        fprintf(stderr, "%s:%s: INSERT_SECTIONS: No room for section \"%s\" (%d bytes).\n", get_file_name(s->file_id),
346
                get_source_file_name(s->file_id, s->file_id_source), s->name, s->size);
347
        return FAILED;
348
      }
349
    }
350
  }
351
 
352
  /* overwrite sections */
353
  p = 0;
354
  while (p < sn) {
355
    s = sa[p++];
356
    if (s->status == SECTION_STATUS_OVERWRITE) {
357
      memory_file_id = s->file_id;
358
      banksize = banks[s->bank];
359
      pc_bank = s->address;
360
      pc_slot = slots[s->slot].address + pc_bank;
361
      pc_full = pc_bank + bankaddress[s->bank];
362
      pc_slot_max = slots[s->slot].address + slots[s->slot].size;
363
      s->output_address = pc_full;
364
      section_overwrite = ON;
365
      if (pc_full + s->size > romsize) {
366
        fprintf(stderr, "%s:%s: INSERT_SECTIONS: Section \"%s\" (%d bytes) goes beyond the ROM size.\n", get_file_name(s->file_id),
367
                get_source_file_name(s->file_id, s->file_id_source), s->name, s->size);
368
        return FAILED;
369
      }
370
      if (s->address + s->size > banksize) {
371
        fprintf(stderr, "%s:%s: INSERT_SECTIONS: Section \"%s\" (%d bytes) overflows from ROM bank %d.\n", get_file_name(s->file_id),
372
                get_source_file_name(s->file_id, s->file_id_source), s->name, s->size, s->bank);
373
        return FAILED;
374
      }
375
      for (i = 0; i < s->size; i++) {
376
        if (mem_insert_pc(s->data[i], s->slot, s->bank) == FAILED)
377
          return FAILED;
378
      }
379
    }
380
  }
381
 
382
  free(sa);
383
 
384
  return SUCCEEDED;
385
}
386
 
387
 
388
/* transform computation stack definitions to ordinary definitions */
389
int transform_stack_definitions(void) {
390
 
391
  struct label *l;
392
  struct stack *s;
393
 
394
 
395
  l = labels_first;
396
  while (l != NULL) {
397
    if (l->status == LABEL_STATUS_STACK) {
398
 
399
      /* DEBUG
400
      printf("--------------------------------------\n");
401
      printf("name: \"%s\"\n", l->name);
402
      printf("sect: \"%d\"\n", l->section);
403
      printf("slot: \"%d\"\n", l->slot);
404
      printf("status: \"%d\"\n", l->status);
405
      printf("file_id: \"%d\"\n", l->file_id);
406
      printf("value: \"%d\"\n", l->address);
407
      */
408
 
409
      s = stacks_first;
410
      /* find the stack associated with the definition */
411
      while (s != NULL) {
412
        if (s->file_id == l->file_id && s->id == l->address)
413
          break;
414
        s = s->next;
415
      }
416
      /* did we find it? */
417
      if (s == NULL) {
418
        fprintf(stderr, "TRANSFORM_STACK_DEFINITIONS: No computation stack associated with computation definition label \"%s\". This is a fatal internal error. Please send the WLA DX author a bug report.\n", l->name);
419
        return FAILED;
420
      }
421
      /* is it ok? */
422
      if (s->computed == 0) {
423
        fprintf(stderr, "TRANSFORM_STACK_DEFINITIONS: The computation of definition \"%s\" hasn't been solved. This is a fatal internal error. Please send the WLA DX author a bug report.\n", l->name);
424
        return FAILED;
425
      }
426
 
427
      /* do the transformation */
428
      l->status = LABEL_STATUS_DEFINE;
429
      l->address = s->result;
430
    }
431
    l = l->next;
432
  }
433
 
434
  return SUCCEEDED;
435
}
436
 
437
 
438
int fix_labels(void) {
439
 
440
  struct section *s = NULL;
441
  struct label *l, *m;
442
 
443
 
444
  /* fix labels' addresses */
445
  l = labels_first;
446
  while (l != NULL) {
447
    if (l->status == LABEL_STATUS_LABEL || l->status == LABEL_STATUS_SYMBOL || l->status == LABEL_STATUS_BREAKPOINT) {
448
      if (l->section_status == ON) {
449
        s = sec_first;
450
        while (s != NULL) {
451
          if (s->id == l->section) {
452
            l->bank = s->bank;
453
            l->address += s->address;
454
            l->rom_address = l->address + bankaddress[l->bank];
455
            if (s->status != SECTION_STATUS_ABSOLUTE)
456
              l->address += slots[l->slot].address;
457
            break;
458
          }
459
          s = s->next;
460
        }
461
      }
462
      else {
463
        l->rom_address = l->address + bankaddress[l->bank];
464
        l->address += slots[l->slot].address;
465
      }
466
    }
467
    l = l->next;
468
  }
469
 
470
  /* check out if a label exists more than once in a different place */
471
  l = labels_first;
472
  while (l != NULL) {
473
    if (is_label_anonymous(l->name) == FAILED && (l->status == LABEL_STATUS_LABEL || l->status == LABEL_STATUS_DEFINE)) {
474
      m = l->next;
475
      while (m != NULL) {
476
        if (strcmp(m->name, l->name) == 0) {
477
          if (l->address != m->address && !(m->name[0] == '*' || m->name[0] == '_')) {
478
            if (l->status == LABEL_STATUS_DEFINE)
479
              fprintf(stderr, "%s: FIX_LABELS: Definition \"%s\" was defined more than once.\n", get_file_name(l->file_id), l->name);
480
            else
481
              fprintf(stderr, "%s:%s:%d: FIX_LABELS: Label \"%s\" was defined more than once.\n", get_file_name(l->file_id),
482
                      get_source_file_name(l->file_id, l->file_id_source), l->linenumber, l->name);
483
            return FAILED;
484
          }
485
        }
486
        m = m->next;
487
      }
488
    }
489
    l = l->next;
490
  }
491
 
492
  return SUCCEEDED;
493
}
494
 
495
 
496
int fix_references(void) {
497
 
498
  struct reference *r;
499
  struct section *s = NULL;
500
  struct label *l, lt;
501
  int i, x;
502
 
503
 
504
  section_overwrite = OFF;
505
 
506
  /* insert references */
507
  r = reference_first;
508
  while (r != NULL) {
509
    x = r->address;
510
    /* search for the section of the reference and fix the address */
511
    if (r->section_status == ON) {
512
      s = sec_first;
513
      while (s != NULL) {
514
        if (s->id == r->section) {
515
          r->bank = s->bank;
516
          x += s->address;
517
          r->address += s->address;
518
          break;
519
        }
520
        s = s->next;
521
      }
522
      /* reference is inside a discarded section? */
523
      if (s != NULL && s->alive == NO) {
524
        r = r->next;
525
        continue;
526
      }
527
      if (s == NULL) {
528
        if (write_bank_header_references(r) == FAILED)
529
          return FAILED;
530
        r = r->next;
531
        continue;
532
      }
533
    }
534
 
535
    if (!(r->section_status == ON && s->status == SECTION_STATUS_ABSOLUTE)) {
536
      x += bankaddress[r->bank];
537
      r->address += slots[r->slot].address;
538
    }
539
 
540
    /* find the destination */
541
    l = labels_first;
542
    /* request for bank number? */
543
    if (r->name[0] == ':') {
544
      if (is_label_anonymous(&r->name[1]) == SUCCEEDED) {
545
        l = get_closest_anonymous_label(&r->name[1], x, r->file_id, l, r->section_status, r->section);
546
      }
547
      else if (strcmp(&r->name[1], "CADDR") == 0 || strcmp(&r->name[1], "caddr") == 0) {
548
        lt.status = LABEL_STATUS_LABEL;
549
        strcpy(lt.name, &r->name[1]);
550
        lt.address = r->address;
551
        lt.bank = r->bank;
552
        lt.section_status = OFF;
553
        l = &lt;
554
      }
555
      else {
556
        while (l != NULL) {
557
          if (strcmp(l->name, &r->name[1]) == 0 && l->status != LABEL_STATUS_SYMBOL && l->status != LABEL_STATUS_BREAKPOINT)
558
            break;
559
          l = l->next;
560
        }
561
      }
562
 
563
      if (l == NULL) {
564
        fprintf(stderr, "%s:%s:%d: FIX_REFERENCES: Bank number request for an unknown label \"%s\".\n",
565
                get_file_name(r->file_id), get_source_file_name(r->file_id, r->file_id_source), r->linenumber, &r->name[1]);
566
        return FAILED;
567
      }
568
 
569
      if (cpu_65816 != 0)
570
        i = get_snes_pc_bank(l) >> 16;
571
      else
572
        i = l->bank;
573
 
574
      memory_file_id = r->file_id;
575
      memory_file_id_source = r->file_id_source;
576
      memory_line_number = r->linenumber;
577
 
578
      /* direct 16bit */
579
      if (r->type == REFERENCE_TYPE_DIRECT_16BIT || r->type == REFERENCE_TYPE_RELATIVE_16BIT) {
580
        mem_insert_ref(x, i & 0xFF);
581
        mem_insert_ref(x + 1, (i >> 8) & 0xFF);
582
      }
583
      /* direct / relative 8bit with a definition */
584
      else if (l->status == LABEL_STATUS_DEFINE) {
585
        fprintf(stderr, "%s:%s:%d: FIX_REFERENCES: Bank number request for a definition \"%s\"?\n",
586
                get_file_name(r->file_id), get_source_file_name(r->file_id, r->file_id_source), r->linenumber, l->name);
587
        return FAILED;
588
      }
589
      /* direct 24bit */
590
      else if (r->type == REFERENCE_TYPE_DIRECT_24BIT) {
591
        mem_insert_ref(x, i & 0xFF);
592
        mem_insert_ref(x + 1, (i >> 8) & 0xFF);
593
        mem_insert_ref(x + 2, (i >> 16) & 0xFF);
594
      }
595
      /* relative/direct 8bit with a label */
596
      else {
597
        mem_insert_ref(x, i & 0xFF);
598
      }
599
    }
600
    /* normal reference */
601
    else {
602
      if (is_label_anonymous(r->name) == SUCCEEDED) {
603
        l = get_closest_anonymous_label(r->name, x, r->file_id, l, r->section_status, r->section);
604
      }
605
      else if (strcmp(r->name, "CADDR") == 0 || strcmp(r->name, "caddr") == 0) {
606
        lt.status = LABEL_STATUS_DEFINE;
607
        strcpy(lt.name, r->name);
608
        lt.address = r->address;
609
        lt.bank = r->bank;
610
        lt.section_status = OFF;
611
        l = &lt;
612
      }
613
      else {
614
        while (l != NULL) {
615
          if (strcmp(l->name, r->name) != 0 || l->status == LABEL_STATUS_SYMBOL || l->status == LABEL_STATUS_BREAKPOINT)
616
            l = l->next;
617
          else {
618
            /* search for the section of the referencee */
619
            if (r->name[0] == '_') {
620
              if (l->file_id == r->file_id) {
621
                if (l->section_status != r->section_status) {
622
                  l = l->next;
623
                  continue;
624
                }
625
                if (l->section_status == ON && l->section != r->section) {
626
                  l = l->next;
627
                  continue;
628
                }
629
              }
630
              else {
631
                l = l->next;
632
                continue;
633
              }
634
            }
635
            break;
636
          }
637
        }
638
      }
639
 
640
      if (l == NULL) {
641
        fprintf(stderr, "%s:%s:%d: FIX_REFERENCES: Reference to an unknown label \"%s\".\n",
642
                get_file_name(r->file_id), get_source_file_name(r->file_id, r->file_id_source), r->linenumber, r->name);
643
        return FAILED;
644
      }
645
 
646
      memory_file_id = r->file_id;
647
      memory_file_id_source = r->file_id_source;
648
      memory_line_number = r->linenumber;
649
 
650
      /* direct 16bit */
651
      if (r->type == REFERENCE_TYPE_DIRECT_16BIT) {
652
        i = l->address;
653
        mem_insert_ref(x, i & 0xFF);
654
        mem_insert_ref(x + 1, (i >> 8) & 0xFF);
655
      }
656
      /* direct / relative 8bit with a value definition */
657
      else if (l->status == LABEL_STATUS_DEFINE && (r->type == REFERENCE_TYPE_DIRECT_8BIT || r->type == REFERENCE_TYPE_RELATIVE_8BIT)) {
658
        i = ((int)l->address) & 0xFFFF;
659
        if (i > 255 || i < -127) {
660
          fprintf(stderr, "%s:%s:%d: FIX_REFERENCES: Value ($%x) of \"%s\" is too much to be a 8bit value.\n",
661
                  get_file_name(r->file_id), get_source_file_name(r->file_id, r->file_id_source), r->linenumber, i, l->name);
662
          return FAILED;
663
        }
664
        mem_insert_ref(x, i & 0xFF);
665
      }
666
      /* direct 24bit */
667
      else if (r->type == REFERENCE_TYPE_DIRECT_24BIT) {
668
        i = l->address;
669
        if (l->status == LABEL_STATUS_LABEL)
670
          i += get_snes_pc_bank(l);
671
        mem_insert_ref(x, i & 0xFF);
672
        mem_insert_ref(x + 1, (i >> 8) & 0xFF);
673
        mem_insert_ref(x + 2, (i >> 16) & 0xFF);
674
      }
675
      /* relative 8bit with a label */
676
      else if (r->type == REFERENCE_TYPE_RELATIVE_8BIT) {
677
        i = (((int)l->address) & 0xFFFF) - r->address - 1;
678
        if (i < -128 || i > 127) {
679
          fprintf(stderr, "%s:%s:%d: FIX_REFERENCES: Too large distance (%d bytes from $%x to $%x \"%s\") for a 8bit reference.\n",
680
                  get_file_name(r->file_id), get_source_file_name(r->file_id, r->file_id_source), r->linenumber, i, r->address, (int)l->address, l->name);
681
          return FAILED;
682
        }
683
        mem_insert_ref(x, i & 0xFF);
684
      }
685
      /* relative 16bit with a label */
686
      else if (r->type == REFERENCE_TYPE_RELATIVE_16BIT) {
687
        i = (((int)l->address) & 0xFFFF) - r->address - 2;
688
        if (i < -32768 || i > 65535) {
689
          fprintf(stderr, "%s:%s:%d: FIX_REFERENCES: Too large distance (%d bytes from $%x to $%x \"%s\") for a 16bit reference.\n",
690
                  get_file_name(r->file_id), get_source_file_name(r->file_id, r->file_id_source), r->linenumber, i, r->address, (int)l->address, l->name);
691
          return FAILED;
692
        }
693
        mem_insert_ref(x, i & 0xFF);
694
        mem_insert_ref(x + 1, (i >> 8) & 0xFF);
695
      }
696
      else {
697
        i = ((int)l->address) & 0xFFFF;
698
        if (i > 255) {
699
          fprintf(stderr, "%s:%s:%d: FIX_REFERENCES: Value ($%x) of \"%s\" is too much to be a 8bit value.\n",
700
                  get_file_name(r->file_id), get_source_file_name(r->file_id, r->file_id_source), r->linenumber, i, l->name);
701
          return FAILED;
702
        }
703
        mem_insert_ref(x, i & 0xFF);
704
      }
705
    }
706
 
707
    r = r->next;
708
  }
709
 
710
  return SUCCEEDED;
711
}
712
 
713
 
714
int write_symbol_file(char *outname, unsigned char mode) {
715
 
716
  struct section *s;
717
  struct label *l;
718
  char name[256], *p;
719
  FILE *f;
720
  int y;
721
 
722
 
723
  if (outname == NULL)
724
    return FAILED;
725
 
726
  strcpy(name, outname);
727
  p = name;
728
  for (y = 0; y < 255 && *p != '.' && *p != 0; y++, p++);
729
  *(p++) = '.';
730
  *(p++) = 's';
731
  *(p++) = 'y';
732
  *(p++) = 'm';
733
  *p = 0;
734
 
735
  f = fopen(name, "wb");
736
  if (f == NULL) {
737
    fprintf(stderr, "MAIN: Error opening file \"%s\".\n", name);
738
    return FAILED;
739
  }
740
 
741
  fprintf(f, "; this file was created with wlalink by ville helin <vhelin@iki.fi>.\n");
742
 
743
  if (mode == SYMBOL_MODE_NOCA5H) {
744
    /* NO$GMB SYMBOL FILE */
745
    fprintf(f, "; no$gmb symbolic information for \"%s\".\n", outname);
746
 
747
    l = labels_first;
748
    while (l != NULL) {
749
      if (is_label_anonymous(l->name) == SUCCEEDED || l->status == LABEL_STATUS_SYMBOL || l->status == LABEL_STATUS_BREAKPOINT) {
750
        l = l->next;
751
        continue;
752
      }
753
      /* skip all dropped section labels */
754
      if (l->section_status == ON) {
755
        s = sec_first;
756
        while (l->section != s->id)
757
          s = s->next;
758
        if (s->alive == NO) {
759
          l = l->next;
760
          continue;
761
        }
762
      }
763
      if (l->status == LABEL_STATUS_LABEL) {
764
        if (snes_mode == 0)
765
          fprintf(f, "%.4x:%.4x %s\n", l->bank, (int)l->address, l->name);
766
        else
767
          fprintf(f, "%.4x:%.4x %s\n", get_snes_pc_bank(l)>>16, (int)l->address, l->name);
768
      }
769
      else
770
        fprintf(f, "0000:%.4x %s\n", (int)l->address, l->name);
771
      l = l->next;
772
    }
773
  }
774
  else {
775
    /* WLA SYMBOL FILE */
776
    fprintf(f, "; wla symbolic information for \"%s\".\n", outname);
777
 
778
    /* labels */
779
    l = labels_first;
780
    while (l != NULL) {
781
      if (l->status != LABEL_STATUS_LABEL) {
782
        l = l->next;
783
        continue;
784
      }
785
      break;
786
    }
787
 
788
    if (l != NULL) {
789
      fprintf(f, "\n[labels]\n");
790
 
791
      l = labels_first;
792
      while (l != NULL) {
793
        if (l->status != LABEL_STATUS_LABEL) {
794
          l = l->next;
795
          continue;
796
        }
797
        if (is_label_anonymous(l->name) == SUCCEEDED) {
798
          l = l->next;
799
          continue;
800
        }
801
 
802
        /* skip all dropped section labels */
803
        if (l->section_status == ON) {
804
          s = sec_first;
805
          while (l->section != s->id)
806
            s = s->next;
807
          if (s->alive == NO) {
808
            l = l->next;
809
            continue;
810
          }
811
        }
812
 
813
        if (snes_mode == 0)
814
          fprintf(f, "%.4x:%.4x %s\n", l->bank, (int)l->address, l->name);
815
        else
816
          fprintf(f, "%.4x:%.4x %s\n", get_snes_pc_bank(l)>>16, (int)l->address, l->name);
817
 
818
        l = l->next;
819
      }
820
    }
821
 
822
    /* symbols */
823
    l = labels_first;
824
    while (l != NULL) {
825
      if (l->status != LABEL_STATUS_SYMBOL) {
826
        l = l->next;
827
        continue;
828
      }
829
      break;
830
    }
831
 
832
    if (l != NULL) {
833
      fprintf(f, "\n[symbols]\n");
834
 
835
      l = labels_first;
836
      while (l != NULL) {
837
        if (l->status != LABEL_STATUS_SYMBOL) {
838
          l = l->next;
839
          continue;
840
        }
841
 
842
        if (snes_mode == 0)
843
          fprintf(f, "%.4x:%.4x %s\n", l->bank, (int)l->address, l->name);
844
        else
845
          fprintf(f, "%.4x:%.4x %s\n", get_snes_pc_bank(l)>>16, (int)l->address, l->name);
846
 
847
        l = l->next;
848
      }
849
    }
850
 
851
    /* breakpoints */
852
    l = labels_first;
853
    while (l != NULL) {
854
      if (l->status != LABEL_STATUS_BREAKPOINT) {
855
        l = l->next;
856
        continue;
857
      }
858
      break;
859
    }
860
 
861
    if (l != NULL) {
862
      fprintf(f, "\n[breakpoints]\n");
863
 
864
      l = labels_first;
865
      while (l != NULL) {
866
        if (l->status != LABEL_STATUS_BREAKPOINT) {
867
          l = l->next;
868
          continue;
869
        }
870
 
871
        if (snes_mode == 0)
872
          fprintf(f, "%.4x:%.4x\n", l->bank, (int)l->address);
873
        else
874
          fprintf(f, "%.4x:%.4x\n", get_snes_pc_bank(l)>>16, (int)l->address);
875
 
876
        l = l->next;
877
      }
878
    }
879
 
880
    /* definitions */
881
    l = labels_first;
882
    while (l != NULL) {
883
      if (l->status != LABEL_STATUS_DEFINE) {
884
        l = l->next;
885
        continue;
886
      }
887
      break;
888
    }
889
 
890
    if (l != NULL) {
891
      fprintf(f, "\n[definitions]\n");
892
 
893
      l = labels_first;
894
      while (l != NULL) {
895
        if (l->status != LABEL_STATUS_DEFINE) {
896
          l = l->next;
897
          continue;
898
        }
899
        if (is_label_anonymous(l->name) == SUCCEEDED) {
900
          l = l->next;
901
          continue;
902
        }
903
 
904
        fprintf(f, "%.8x %s\n", (int)l->address, l->name);
905
 
906
        l = l->next;
907
      }
908
    }
909
  }
910
 
911
  fclose(f);
912
 
913
  return SUCCEEDED;
914
}
915
 
916
 
917
int write_rom_file(char *outname) {
918
 
919
  struct section *s;
920
  FILE *f;
921
  int i, b, e;
922
 
923
 
924
  f = fopen(outname, "wb");
925
  if (f == NULL) {
926
    fprintf(stderr, "WRITE_ROM_FILE: Error opening file \"%s\".\n", outname);
927
    return FAILED;
928
  }
929
 
930
  if (file_header != NULL)
931
    fwrite(file_header, 1, file_header_size, f);
932
 
933
  /* SMC header */
934
  if (smc_status != 0)
935
    smc_create_and_write(f);
936
 
937
  /* ROM output mode */
938
  if (output_mode == OUTPUT_ROM) {
939
    /* write bank by bank and bank header sections */
940
    for (i = 0; i < rombanks; i++) {
941
      s = sec_hd_first;
942
      while (s != NULL) {
943
        if (s->bank == i) {
944
          fwrite(s->data, 1, s->size, f);
945
          break;
946
        }
947
        s = s->next;
948
      }
949
 
950
      fwrite(rom + bankaddress[i], 1, banks[i], f);
951
    }
952
  }
953
  /* program file output mode */
954
  else {
955
    for (i = 0; i < romsize; i++)
956
      if (rom_usage[i] != 0)
957
        break;
958
    b = i;
959
    for (e = b; i < romsize; i++)
960
      if (rom_usage[i] != 0)
961
        e = i;
962
 
963
    s = sec_hd_first;
964
    while (s != NULL) {
965
      if (s->bank == 0) {
966
        fwrite(s->data, 1, s->size, f);
967
        break;
968
      }
969
      s = s->next;
970
    }
971
 
972
    fwrite(rom + b, 1, e - b + 1, f);
973
    program_start = b;
974
    program_end = e;
975
  }
976
 
977
  if (file_footer != NULL)
978
    fwrite(file_footer, 1, file_footer_size, f);
979
 
980
  fclose(f);
981
 
982
  return SUCCEEDED;
983
}
984
 
985
 
986
int compute_pending_calculations(void) {
987
 
988
  struct section *s;
989
  struct stack *sta;
990
  int k, a;
991
 
992
 
993
  section_overwrite = ON;
994
 
995
  /* first place the stacks into the output */
996
  sta = stacks_first;
997
  while (sta != NULL) {
998
 
999
    if (sta->position == STACK_POSITION_DEFINITION) {
1000
      /* skip definition stacks */
1001
      sta = sta->next;
1002
      continue;
1003
    }
1004
 
1005
    if (sta->section_status == ON) {
1006
      /* get section address */
1007
      s = sec_first;
1008
      while (s != NULL) {
1009
        if (sta->section == s->id) {
1010
          sta->bank = s->bank;
1011
          break;
1012
        }
1013
        s = s->next;
1014
      }
1015
      /* the computation is inside a discarded section? */
1016
      if (s != NULL && s->alive == NO) {
1017
        sta = sta->next;
1018
        continue;
1019
      }
1020
      /* it must be a bank header section! */
1021
      if (s == NULL) {
1022
        sta = sta->next;
1023
        continue;
1024
      }
1025
 
1026
      /* remember the memory address (for CADDR) */
1027
      sta->memory_address = s->address + sta->address + slots[sta->slot].address;
1028
 
1029
      if (s->status != SECTION_STATUS_ABSOLUTE)
1030
        sta->address += s->address + bankaddress[s->bank];
1031
      else
1032
        sta->address += s->address;
1033
    }
1034
    else {
1035
      /* remember the memory address (for CADDR) */
1036
      sta->memory_address = sta->address + slots[sta->slot].address;
1037
 
1038
      sta->address += bankaddress[sta->bank];
1039
    }
1040
 
1041
    sta = sta->next;
1042
  }
1043
 
1044
  /* next parse the stack items */
1045
  sta = stacks_first;
1046
  while (sta != NULL) {
1047
    if (sta->position == STACK_POSITION_DEFINITION)
1048
      k = 1;
1049
    else {
1050
      /* skip the calculations inside discarded sections */
1051
      if (sta->section_status == ON) {
1052
        /* get the section */
1053
        s = sec_first;
1054
        while (s != NULL) {
1055
          if (sta->section == s->id) {
1056
            break;
1057
          }
1058
          s = s->next;
1059
        }
1060
        if (s != NULL && s->alive == YES)
1061
          k = 1;
1062
        else
1063
          k = 0;
1064
      }
1065
      else
1066
        k = 1;
1067
    }
1068
    if (k == 1) {
1069
      if (parse_stack(sta) == FAILED)
1070
        return FAILED;
1071
    }
1072
    sta = sta->next;
1073
  }
1074
 
1075
  /* then compute and place the results */
1076
  sta = stacks_first;
1077
  while (sta != NULL) {
1078
 
1079
    /* is the stack inside a definition? */
1080
    if (sta->position == STACK_POSITION_DEFINITION) {
1081
      /* all the references have been decoded, now compute */
1082
      if (compute_stack(sta, &k) == FAILED)
1083
        return FAILED;
1084
      /* next stack computation */
1085
      sta = sta->next;
1086
      continue;
1087
    }
1088
 
1089
    /* find source address */
1090
    if (sta->section_status == ON) {
1091
      /* get section address */
1092
      s = sec_first;
1093
      while (s != NULL) {
1094
        if (sta->section == s->id) {
1095
          sta->bank = s->bank;
1096
          break;
1097
        }
1098
        s = s->next;
1099
      }
1100
      /* the computation is inside a discarded section? */
1101
      if (s != NULL && s->alive == NO) {
1102
        sta = sta->next;
1103
        continue;
1104
      }
1105
      /* it must be a bank header section! */
1106
      if (s == NULL) {
1107
        if (write_bank_header_calculations(sta) == FAILED)
1108
          return FAILED;
1109
        sta = sta->next;
1110
        continue;
1111
      }
1112
    }
1113
 
1114
    a = sta->address;
1115
 
1116
    /* all the references have been decoded, now compute */
1117
    if (compute_stack(sta, &k) == FAILED)
1118
      return FAILED;
1119
 
1120
    memory_file_id = sta->file_id;
1121
    memory_file_id_source = sta->file_id_source;
1122
    memory_line_number = sta->linenumber;
1123
 
1124
    if (sta->type == STACKS_TYPE_8BIT) {
1125
      if (k < -127 || k > 255) {
1126
        fprintf(stderr, "%s:%s:%d: COMPUTE_PENDING_CALCULATIONS: Result (%d/$%x) of a computation is out of 8bit range.\n",
1127
                get_file_name(sta->file_id), get_source_file_name(sta->file_id, sta->file_id_source), sta->linenumber, k, k);
1128
        return FAILED;
1129
      }
1130
      if (mem_insert_ref(a, k) == FAILED)
1131
        return FAILED;
1132
    }
1133
    else if (sta->type == STACKS_TYPE_16BIT) {
1134
      if (k < -32768 || k > 65535) {
1135
        fprintf(stderr, "%s:%s:%d: COMPUTE_PENDING_CALCULATIONS: Result (%d/$%x) of a computation is out of 16bit range.\n",
1136
                get_file_name(sta->file_id), get_source_file_name(sta->file_id, sta->file_id_source), sta->linenumber, k, k);
1137
        return FAILED;
1138
      }
1139
      if (mem_insert_ref(a, k & 0xFF) == FAILED)
1140
        return FAILED;
1141
      if (mem_insert_ref(a + 1, (k >> 8) & 0xFF) == FAILED)
1142
        return FAILED;
1143
    }
1144
    else {
1145
      if (k < -8388608 || k > 16777215) {
1146
        fprintf(stderr, "%s:%s:%d: COMPUTE_PENDING_CALCULATIONS: Result (%d/$%x) of a computation is out of 24bit range.\n",
1147
                get_file_name(sta->file_id), get_source_file_name(sta->file_id, sta->file_id_source), sta->linenumber, k, k);
1148
        return FAILED;
1149
      }
1150
      if (mem_insert_ref(a, k & 0xFF) == FAILED)
1151
        return FAILED;
1152
      if (mem_insert_ref(a + 1, (k >> 8) & 0xFF) == FAILED)
1153
        return FAILED;
1154
      if (mem_insert_ref(a + 2, (k >> 16) & 0xFF) == FAILED)
1155
        return FAILED;
1156
    }
1157
 
1158
    /* next stack computation */
1159
    sta = sta->next;
1160
  }
1161
 
1162
  return SUCCEEDED;
1163
}
1164
 
1165
 
1166
int compute_stack(struct stack *sta, int *result) {
1167
 
1168
  struct stackitem *s;
1169
  struct stack *st;
1170
  int r, t, z, x, res;
1171
  double v[256], q;
1172
 
1173
 
1174
  if (sta->under_work == YES) {
1175
    fprintf(stderr, "%s:%s:%d: COMPUTE_STACK: A loop found in computation.\n", get_file_name(sta->file_id),
1176
            get_source_file_name(sta->file_id, sta->file_id_source), sta->linenumber);
1177
    return FAILED;
1178
  }
1179
 
1180
  if (sta->computed == YES) {
1181
    *result = sta->result;
1182
    return SUCCEEDED;
1183
  }
1184
 
1185
  sta->under_work = YES;
1186
 
1187
  x = sta->stacksize;
1188
  s = sta->stack;
1189
  for (r = 0, t = 0; r < x; r++, s++) {
1190
    if (s->type == STACK_ITEM_TYPE_VALUE) {
1191
      if (s->sign == SI_SIGN_NEGATIVE)
1192
        v[t] = -s->value;
1193
      else
1194
        v[t] = s->value;
1195
      t++;
1196
    }
1197
    else if (s->type == STACK_ITEM_TYPE_STACK) {
1198
      /* we have a stack inside a stack! find the stack */
1199
      st = stacks_first;
1200
      while (st != NULL) {
1201
        if (st->id == s->value && st->file_id == s->sign)
1202
          break;
1203
        st = st->next;
1204
      }
1205
 
1206
      if (st == NULL) {
1207
        fprintf(stderr, "COMPUTE_STACK: A computation stack has gone missing. This is a fatal internal error. Please send the WLA DX author a bug report.\n");
1208
        return FAILED;
1209
      }
1210
 
1211
      if (compute_stack(st, &res) == FAILED)
1212
        return FAILED;
1213
 
1214
      v[t] = res;
1215
      t++;
1216
    }
1217
    else {
1218
      switch ((int)s->value) {
1219
      case SI_OP_PLUS:
1220
        v[t - 2] += v[t - 1];
1221
        t--;
1222
        break;
1223
      case SI_OP_MINUS:
1224
        v[t - 2] -= v[t - 1];
1225
        t--;
1226
        break;
1227
      case SI_OP_XOR:
1228
        /* 16bit XOR? */
1229
        if (v[t - 2] > 0xFF || v[t - 2] < -128 || v[t - 1] > 0xFF || v[t - 1] < -128)
1230
          v[t - 2] = ((int)v[t - 1] ^ (int)v[t - 2]) & 0xFFFF;
1231
        /* 8bit XOR */
1232
        else
1233
          v[t - 2] = ((int)v[t - 1] ^ (int)v[t - 2]) & 0xFF;
1234
        t--;
1235
        break;
1236
      case SI_OP_MULTIPLY:
1237
        v[t - 2] *= v[t - 1];
1238
        t--;
1239
        break;
1240
      case SI_OP_OR:
1241
        v[t - 2] = (int)v[t - 1] | (int)v[t - 2];
1242
        t--;
1243
        break;
1244
      case SI_OP_AND:
1245
        v[t - 2] = (int)v[t - 1] & (int)v[t - 2];
1246
        t--;
1247
        break;
1248
      case SI_OP_LOW_BYTE:
1249
        z = (int)v[t - 1];
1250
        v[t - 1] = z & 0xFF;
1251
        break;
1252
      case SI_OP_HIGH_BYTE:
1253
        z = (int)v[t - 1];
1254
        v[t - 1] = (z>>8) & 0xFF;
1255
        break;
1256
      case SI_OP_MODULO:
1257
        if (((int)v[t - 1]) == 0) {
1258
          fprintf(stderr, "%s:%s:%d: COMPUTE_STACK: Modulo by zero.\n", get_file_name(sta->file_id),
1259
                  get_source_file_name(sta->file_id, sta->file_id_source), sta->linenumber);
1260
          return FAILED;
1261
        }
1262
        v[t - 2] = (int)v[t - 2] % (int)v[t - 1];
1263
        t--;
1264
        break;
1265
      case SI_OP_DIVIDE:
1266
        if (((int)v[t - 1]) == 0) {
1267
          fprintf(stderr, "%s:%s:%d: COMPUTE_STACK: Division by zero.\n", get_file_name(sta->file_id),
1268
                  get_source_file_name(sta->file_id, sta->file_id_source), sta->linenumber);
1269
          return FAILED;
1270
        }
1271
        v[t - 2] /= v[t - 1];
1272
        t--;
1273
        break;
1274
      case SI_OP_POWER:
1275
        q = 1;
1276
        for (z = 0; z < v[t - 1]; z++)
1277
          q *= v[t - 2];
1278
        v[t - 2] = q;
1279
        t--;
1280
        break;
1281
      case SI_OP_SHIFT_LEFT:
1282
        v[t - 2] = (int)v[t - 2] << (int)v[t - 1];
1283
        t--;
1284
        break;
1285
      case SI_OP_SHIFT_RIGHT:
1286
        v[t - 2] = (int)v[t - 2] >> (int)v[t - 1];
1287
        t--;
1288
        break;
1289
      }
1290
    }
1291
  }
1292
 
1293
  *result = v[0];
1294
  sta->result = v[0];
1295
  sta->computed = YES;
1296
  sta->under_work = NO;
1297
 
1298
  return SUCCEEDED;
1299
}
1300
 
1301
 
1302
int write_bank_header_calculations(struct stack *sta) {
1303
 
1304
  struct section *s;
1305
  unsigned char *t;
1306
  int k;
1307
 
1308
 
1309
  /* parse stack items */
1310
  if (parse_stack(sta) == FAILED)
1311
    return FAILED;
1312
 
1313
  /* all the references have been decoded, now compute */
1314
  if (compute_stack(sta, &k) == FAILED)
1315
    return FAILED;
1316
 
1317
  s = sec_hd_first;
1318
  while (sta->section != s->id)
1319
    s = s->next;
1320
 
1321
  t = s->data + sta->address;
1322
 
1323
  if (sta->type == STACKS_TYPE_8BIT) {
1324
    if (k < -127 || k > 255) {
1325
      fprintf(stderr, "%s:%s:%d: WRITE_BANK_HEADER_CALCULATIONS: Result (%d/$%x) of a computation is out of 8bit range.\n",
1326
              get_file_name(sta->file_id), get_source_file_name(sta->file_id, sta->file_id_source), sta->linenumber, k, k);
1327
      return FAILED;
1328
    }
1329
    *t = k & 0xFF;
1330
  }
1331
  else if (sta->type == STACKS_TYPE_16BIT) {
1332
    if (k < -32768 || k > 65535) {
1333
      fprintf(stderr, "%s:%s:%d: WRITE_BANK_HEADER_CALCULATIONS: Result (%d/$%x) of a computation is out of 16bit range.\n",
1334
              get_file_name(sta->file_id), get_source_file_name(sta->file_id, sta->file_id_source), sta->linenumber, k, k);
1335
      return FAILED;
1336
    }
1337
    *t = k & 0xFF;
1338
    t++;
1339
    *t = (k >> 8) & 0xFF;
1340
  }
1341
  else {
1342
    if (k < -8388608 || k > 16777215) {
1343
      fprintf(stderr, "%s:%s:%d: WRITE_BANK_HEADER_CALCULATIONS: Result (%d/$%x) of a computation is out of 24bit range.\n",
1344
              get_file_name(sta->file_id), get_source_file_name(sta->file_id, sta->file_id_source), sta->linenumber, k, k);
1345
      return FAILED;
1346
    }
1347
    *t = k & 0xFF;
1348
    t++;
1349
    *t = (k >> 8) & 0xFF;
1350
    t++;
1351
    *t = (k >> 16) & 0xFF;
1352
  }
1353
 
1354
  return SUCCEEDED;
1355
}
1356
 
1357
 
1358
int write_bank_header_references(struct reference *r) {
1359
 
1360
  struct section *s;
1361
  struct label *l;
1362
  unsigned char *t;
1363
  int a;
1364
 
1365
 
1366
  s = sec_hd_first;
1367
  while (r->section != s->id)
1368
    s = s->next;
1369
 
1370
  t = s->data + r->address;
1371
 
1372
  /* find the destination */
1373
  l = labels_first;
1374
  while (l != NULL) {
1375
    if (strcmp(l->name, r->name) == 0) {
1376
      a = l->address;
1377
      /* direct 16bit */
1378
      if (r->type == REFERENCE_TYPE_DIRECT_16BIT) {
1379
        *t = a & 0xFF;
1380
        t++;
1381
        *t = (a >> 8) & 0xFF;
1382
        break;
1383
      }
1384
      /* direct 8bit */
1385
      else if (r->type == REFERENCE_TYPE_DIRECT_8BIT) {
1386
        if (a > 255 || a < -127) {
1387
          fprintf(stderr, "%s:%s:%d: WRITE_BANK_HEADER_REFERENCES: Value (%d/$%x) of \"%s\" is too much to be a 8bit value.\n",
1388
                  get_file_name(r->file_id), get_source_file_name(r->file_id, r->file_id_source), r->linenumber, a, a, l->name);
1389
          return FAILED;
1390
        }
1391
        *t = a & 0xFF;
1392
        break;
1393
      }
1394
      /* direct 24bit */
1395
      else if (r->type == REFERENCE_TYPE_DIRECT_24BIT) {
1396
        if (l->status == LABEL_STATUS_LABEL)
1397
          a += get_snes_pc_bank(l);
1398
        *t = a & 0xFF;
1399
        t++;
1400
        *t = (a >> 8) & 0xFF;
1401
        t++;
1402
        *t = (a >> 16) & 0xFF;
1403
        break;
1404
      }
1405
      else {
1406
        fprintf(stderr, "%s:%s:%d: WRITE_BANK_HEADER_REFERENCES: A relative reference (type %d) to label \"%s\".\n",
1407
                get_file_name(r->file_id), get_source_file_name(r->file_id, r->file_id_source), r->linenumber, r->type, l->name);
1408
        return FAILED;
1409
      }
1410
    }
1411
    l = l->next;
1412
  }
1413
  if (l == NULL) {
1414
    fprintf(stderr, "%s:%s:%d: WRITE_BANK_HEADER_REFERENCES: Reference to an unknown label \"%s\".\n",
1415
            get_file_name(r->file_id), get_source_file_name(r->file_id, r->file_id_source), r->linenumber, r->name);
1416
    return FAILED;
1417
  }
1418
 
1419
  return SUCCEEDED;
1420
}
1421
 
1422
 
1423
/* transform all string items inside a computation stack into corresponding numbers */
1424
int parse_stack(struct stack *sta) {
1425
 
1426
  struct stackitem *si;
1427
  struct label *l, lt;
1428
  double k;
1429
  int g;
1430
 
1431
 
1432
  si = sta->stack;
1433
  g = 0;
1434
  k = 0;
1435
  while (g != sta->stacksize) {
1436
    if (si->type == STACK_ITEM_TYPE_STRING) {
1437
      l = labels_first;
1438
 
1439
      /* bank number search */
1440
      if (si->string[0] == ':') {
1441
        if (is_label_anonymous(&si->string[1]) == SUCCEEDED) {
1442
          l = get_closest_anonymous_label(&si->string[1], sta->linenumber, sta->file_id, l, sta->section_status, sta->section);
1443
          k = l->address;
1444
        }
1445
        else if (strcmp(&si->string[1], "CADDR") == 0 || strcmp(&si->string[1], "caddr") == 0) {
1446
          k = sta->bank;
1447
          lt.status = LABEL_STATUS_DEFINE;
1448
          l = &lt;
1449
        }
1450
        else {
1451
          while (l != NULL) {
1452
            if (strcmp(l->name, &si->string[1]) == 0) {
1453
              if (cpu_65816 != 0)
1454
                k = get_snes_pc_bank(l) >> 16;
1455
              else
1456
                k = l->bank;
1457
              break;
1458
            }
1459
            l = l->next;
1460
          }
1461
        }
1462
      }
1463
      /* normal label address search */
1464
      else {
1465
        if (is_label_anonymous(si->string) == SUCCEEDED) {
1466
          l = get_closest_anonymous_label(si->string, sta->linenumber, sta->file_id, l, sta->section_status, sta->section);
1467
          k = l->address;
1468
        }
1469
        else if (strcmp(si->string, "CADDR") == 0 || strcmp(si->string, "caddr") == 0) {
1470
          k = sta->memory_address;
1471
          lt.status = LABEL_STATUS_DEFINE;
1472
          l = &lt;
1473
        }
1474
        else {
1475
          while (l != NULL) {
1476
            if (strcmp(l->name, si->string) == 0) {
1477
              if (si->string[0] == '_') {
1478
                if (sta->section == l->section) {
1479
                  k = l->address;
1480
                  break;
1481
                }
1482
                else {
1483
                  l = l->next;
1484
                  continue;
1485
                }
1486
              }
1487
              else {
1488
                k = l->address;
1489
                break;
1490
              }
1491
            }
1492
            l = l->next;
1493
          }
1494
        }
1495
      }
1496
 
1497
      if (l == NULL) {
1498
        fprintf(stderr, "%s:%s:%d: PARSE_STACK: Unresolved reference to \"%s\".\n", get_file_name(sta->file_id),
1499
                get_source_file_name(sta->file_id, sta->file_id_source), sta->linenumber, si->string);
1500
        return FAILED;
1501
      }
1502
 
1503
      /* 65816 cpu bank fix */
1504
      if (sta->type == STACKS_TYPE_24BIT && l->status == LABEL_STATUS_LABEL)
1505
        k += get_snes_pc_bank(l);
1506
 
1507
      if (l->status == LABEL_STATUS_STACK) {
1508
        /* here we abuse the stack item structure's members */
1509
        si->value = l->address;
1510
        si->sign = l->file_id;
1511
        si->type = STACK_ITEM_TYPE_STACK;
1512
      }
1513
      else {
1514
        si->value = k;
1515
        si->type = STACK_ITEM_TYPE_VALUE;
1516
      }
1517
    }
1518
    si++;
1519
    g++;
1520
  }
1521
 
1522
  return SUCCEEDED;
1523
}
1524
 
1525
 
1526
int get_snes_pc_bank(struct label *l) {
1527
 
1528
  int x, k;
1529
 
1530
 
1531
  /* do we override the user's banking scheme (.HIROM/.LOROM)? */
1532
  if (snes_mode != 0) {
1533
    /* use rom_address instead of address, as address points to
1534
       the position in destination machine's memory, not in rom */
1535
    k = l->rom_address;
1536
 
1537
    if (snes_rom_mode == SNES_ROM_MODE_HIROM)
1538
      x = k / 0x10000;
1539
    else
1540
      x = k / 0x8000;
1541
  }
1542
  /* or just use the user's banking chart */
1543
  else {
1544
    x = l->bank;
1545
  }
1546
 
1547
  x = (x + l->base) << 16;
1548
 
1549
  return x;
1550
}
1551
 
1552
 
1553
int correct_65816_library_sections(void) {
1554
 
1555
  struct section *s;
1556
  struct label *l;
1557
 
1558
 
1559
  s = sec_first;
1560
  while (s != NULL) {
1561
    if (s->library_status == ON && s->base_defined == ON) {
1562
      l = labels_first;
1563
      while (l != NULL) {
1564
        if (l->section_status == ON && l->section == s->id)
1565
          l->base = s->base;
1566
        l = l->next;
1567
      }
1568
    }
1569
    s = s->next;
1570
  }
1571
 
1572
  return SUCCEEDED;
1573
}
1574
 
1575
 
1576
/* is the label of form -, --, ---, +, ++, +++, ... ? */
1577
int is_label_anonymous(char *l) {
1578
 
1579
  int x, y;
1580
  char c;
1581
 
1582
 
1583
  if (strcmp(l, "_f") == 0 || strcmp(l, "_F") == 0 || strcmp(l, "_b") == 0 || strcmp(l, "_B") == 0 || strcmp(l, "__") == 0)
1584
    return SUCCEEDED;
1585
 
1586
  c = *l;
1587
  if (!(c == '-' || c == '+'))
1588
    return FAILED;
1589
  for (x = strlen(l), y = 0; y < x; y++) {
1590
    if (*(l + y) != c)
1591
      return FAILED;
1592
  }
1593
 
1594
  return SUCCEEDED;
1595
}
1596
 
1597
 
1598
struct label *get_closest_anonymous_label(char *name, int rom_address, int file_id, struct label *l, int section_status, int section) {
1599
 
1600
  struct label *closest = NULL;
1601
  int d = 999999, e;
1602
 
1603
 
1604
  if (strcmp(name, "_b") == 0 || strcmp(name, "_B") == 0) {
1605
    while (l != NULL) {
1606
      if (strcmp("__", l->name) == 0 && file_id == l->file_id && section_status == l->section_status) {
1607
        if (section_status == OFF || (section_status == ON && section == l->section)) {
1608
          e = rom_address - l->rom_address;
1609
          if (e >= 0 && e < d) {
1610
            closest = l;
1611
            d = e;
1612
          }
1613
        }
1614
      }
1615
      l = l->next;
1616
    }
1617
    return closest;
1618
  }
1619
 
1620
  if (strcmp(name, "_f") == 0 || strcmp(name, "_F") == 0) {
1621
    while (l != NULL) {
1622
      if (strcmp("__", l->name) == 0 && file_id == l->file_id && section_status == l->section_status) {
1623
        if (section_status == OFF || (section_status == ON && section == l->section)) {
1624
          e = l->rom_address - rom_address;
1625
          if (e > 0 && e < d) {
1626
            closest = l;
1627
            d = e;
1628
          }
1629
        }
1630
      }
1631
      l = l->next;
1632
    }
1633
    return closest;
1634
  }
1635
 
1636
  /* -, --, +, ++, ... */
1637
  while (l != NULL) {
1638
    if (strcmp(name, l->name) == 0 && file_id == l->file_id && section_status == l->section_status) {
1639
      if (section_status == OFF || (section_status == ON && section == l->section)) {
1640
        if (name[0] == '-') {
1641
          e = rom_address - l->rom_address;
1642
          if (e >= 0 && e < d) {
1643
            closest = l;
1644
            d = e;
1645
          }
1646
        }
1647
        else {
1648
          e = l->rom_address - rom_address;
1649
          if (e > 0 && e < d) {
1650
            closest = l;
1651
            d = e;
1652
          }
1653
        }
1654
      }
1655
    }
1656
    l = l->next;
1657
  }
1658
 
1659
  return closest;
1660
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.