Commit 8678735

Nick committed on
Remove rgb2sdas, fix instrument bug, remove obj export
commit 86787356cbf4ee4fd6dc2345b8b231a6ca5a6737 parent 004bfb4
7 changed files +39−940
ModifiedGBEmu.lpi +1−5
@@ -230,7 +230,7 @@
230 <PackageName Value="LCL"/> 230 <PackageName Value="LCL"/>
231 </Item5> 231 </Item5>
232 </RequiredPackages> 232 </RequiredPackages>
233 <Units Count="26"> 233 <Units Count="25">
234 <Unit0> 234 <Unit0>
235 <Filename Value="GBEmu.lpr"/> 235 <Filename Value="GBEmu.lpr"/>
236 <IsPartOfProject Value="True"/> 236 <IsPartOfProject Value="True"/>
@@ -362,10 +362,6 @@
362 <IsPartOfProject Value="True"/> 362 <IsPartOfProject Value="True"/>
363 <UnitName Value="hUGESettings"/> 363 <UnitName Value="hUGESettings"/>
364 </Unit24> 364 </Unit24>
365 <Unit25>
366 <Filename Value="rgb2sdas.pas"/>
367 <IsPartOfProject Value="True"/>
368 </Unit25>
369 </Units> 365 </Units>
370 </ProjectOptions> 366 </ProjectOptions>
371 <CompilerOptions> 367 <CompilerOptions>
Modifiedcodegen.pas +3−9
@@ -10,7 +10,7 @@ uses
10 lclintf, process, rgb2sdas; 10 lclintf, process, rgb2sdas;
11 11
12 type 12 type
13 TExportMode = (emNormal, emPreview, emGBS, emRGBDSObj, emGBDKObj); 13 TExportMode = (emNormal, emPreview, emGBS);
14 14
15 function RenderPreviewRom(Song: TSong): boolean; 15 function RenderPreviewRom(Song: TSong): boolean;
16 function RenderSongToFile(Song: TSong; Filename: string; 16 function RenderSongToFile(Song: TSong; Filename: string;
@@ -504,12 +504,12 @@ begin
504 // Assemble 504 // Assemble
505 if Mode = emPreview then 505 if Mode = emPreview then
506 begin 506 begin
507 if Assemble(Filename + '_driver.obj', 'driver.z80', ['PREVIEW_MODE']) <> 0 then 507 if Assemble(Filename + '_driver.obj', 'hUGEDriver.z80', ['PREVIEW_MODE']) <> 0 then
508 goto AssemblyError; 508 goto AssemblyError;
509 end 509 end
510 else 510 else
511 begin 511 begin
512 if Assemble(Filename + '_driver.obj', 'driver.z80', []) <> 0 then 512 if Assemble(Filename + '_driver.obj', 'hUGEDriver.z80', []) <> 0 then
513 goto AssemblyError; 513 goto AssemblyError;
514 end; 514 end;
515 515
@@ -561,12 +561,6 @@ begin
561 561
562 case Mode of 562 case Mode of
563 emGBS: RenameSucceeded := RenameFile(Filename + '.gbs', FilePath); 563 emGBS: RenameSucceeded := RenameFile(Filename + '.gbs', FilePath);
564 emRGBDSObj: RenameSucceeded := RenameFile(Filename + '_song.obj', FilePath);
565 emGBDKObj: begin
566 RenameSucceeded := RenameFile(Filename + '_song.obj', FilePath+'bj');
567 ConvertRGB2SDAS(FilePath+'bj', FilePath);
568 DeleteFile(FilePath+'bj');
569 end
570 else RenameSucceeded := RenameFile(Filename + '.gb', FilePath); 564 else RenameSucceeded := RenameFile(Filename + '.gb', FilePath);
571 end; 565 end;
572 566
ModifiedhUGEDriver +1−1
@@ -1 +1 @@
1 Subproject commit 46acb7e8d0a1b5027dca0cb782011dd52e6b804e 1 Subproject commit 25a1e40b7bdb3849e5a8c408d531e640b8cb18ff
Deletedrgb2sdas.pas +0−861
@@ -1,861 +0,0 @@
1 unit rgb2sdas;
2
3 { TODO: This unit needs to be refactored, really bad. }
4
5 {$mode objfpc}{$H+}
6
7 interface
8
9 uses
10 {$IFDEF UNIX}{$IFDEF UseCThreads}
11 cthreads,
12 {$ENDIF}{$ENDIF}
13 Classes, SysUtils, strutils, Math
14 { you can add units after this };
15
16 type
17 TRSymbol = packed record
18 ID: integer;
19 Name: string;
20 SymType: byte;
21
22 No: integer;
23
24 FileName: string;
25 LineNum, SectionID, Value: longint;
26 end;
27
28 TRPatch = packed record
29 SourceFile: string;
30 Offset: longint;
31 PCSectionID: longint;
32 PCOffset: longint;
33 PatchType: byte;
34 RPNSize: longint;
35 RPN: array of byte;
36 end;
37
38 TRSection = packed record
39 ID: integer;
40 Name: string;
41 Size: longint;
42 SectType: byte;
43 Org: longint;
44 Bank: longint;
45 Align: byte;
46 Ofs: longint;
47
48 Data: array of byte;
49 NumberOfPatches: longint;
50 Patches: array of TRPatch;
51 end;
52
53 TRObj = packed record
54 ID: array[0..3] of AnsiChar;
55 RevisionNumber: longint;
56 NumberOfSymbols: longint;
57 NumberOfSections: longint;
58
59 Symbols: array of TRSymbol;
60 Sections: array of TRSection;
61 end;
62
63 TRPNTag = (
64 rpnPlus,
65 rpnMinus,
66 rpnTimes,
67 rpnDiv,
68 rpnMod,
69 rpnNegate,
70 rpnOr,
71 rpnAnd,
72 rpnXor,
73 rpnComplement,
74 rpnBoolAnd,
75 rpnBoolOr,
76 rpnBoolNeg,
77 rpnEqual,
78 rpnNotEqual,
79 rpnGreater,
80 rpnLess,
81 rpnGreaterEqual,
82 rpnLessEqual,
83 rpnShl,
84 rpnShr,
85 rpnBankSymbol,
86 rpnBankSection,
87 rpnCurrentBank,
88 rpnHramCheck,
89 rpnRstCheck,
90 rpnInteger,
91 rpnSymbol);
92
93 TRPNNode = record
94 case Tag: TRPNTag of
95 rpnBankSymbol: (BankSymbol: integer);
96 rpnBankSection: (BankSection: integer);
97 rpnInteger: (IntValue: integer);
98 rpnSymbol: (SymbolID: integer);
99 end;
100 TRPN = array of TRPNNode;
101
102 type
103 TObjFileStream = class(TFileStream)
104 function ReadNullTerm: string; virtual;
105 end;
106
107 EObjectConversionException = class(Exception);
108
109 procedure ConvertRGB2SDAS(SourceName, DestName: string);
110
111 implementation
112
113 function TObjFileStream.ReadNullTerm: string;
114 var
115 B: byte;
116 begin
117 Result := '';
118 while True do
119 begin
120 B := ReadByte;
121 if B = 0 then
122 Exit;
123 Result += Chr(B);
124 end;
125 end;
126
127 const
128 WRAM0 = 0;
129 VRAM = 1;
130 ROMX = 2;
131 ROM0 = 3;
132 HRAM = 4;
133 WRAMX = 5;
134 SRAM = 6;
135 OAM = 7;
136
137 const
138 SYM_LOCAL = 0;
139 SYM_IMPORT = 1;
140 SYM_EXPORT = 2;
141
142 const
143 PATCH_BYTE = 0;
144 PATCH_LE_WORD = 1;
145 PATCH_LE_LONG = 2;
146 PATCH_JR = 3;
147
148 procedure Die(const S: string); overload;
149 begin
150 raise EObjectConversionException.Create(S);
151 end;
152
153 procedure Die(const fmt: string; const params: array of const); overload;
154 begin
155 Die(format(fmt, params));
156 end;
157
158 function ReadObjFile(const afilename: string): TRObj;
159 const
160 Sign: array[0..3] of AnsiChar = 'RGB9';
161 var
162 I, J: integer;
163 begin
164 with TObjFileStream.Create(afilename, fmOpenRead) do
165 try
166 Read(Result, SizeOf(TRObj) - SizeOf(Result.Symbols) - SizeOf(Result.Sections));
167 if not (CompareMem(@Result.ID, @Sign, sizeof(Result.ID)) and
168 (Result.RevisionNumber = 5)) then
169 Die('Unsupported object file version!');
170 SetLength(Result.Symbols, Result.NumberOfSymbols);
171 SetLength(Result.Sections, Result.NumberOfSections);
172
173 for I := 0 to Result.NumberOfSymbols - 1 do
174 begin
175 Result.Symbols[I] := Default(TRSymbol);
176 with Result.Symbols[I] do
177 begin
178 ID := I;
179 Name := ReadNullTerm;
180 Read(SymType, 1);
181 if ((SymType and $7F) <> SYM_IMPORT) then
182 begin
183 FileName := ReadNullTerm;
184 Read(LineNum, SizeOf(LineNum));
185 Read(SectionID, SizeOf(SectionID));
186 Read(Value, SizeOf(Value));
187 end;
188 end;
189 end;
190
191 for I := 0 to Result.NumberOfSections - 1 do
192 begin
193 Result.Sections[I] := Default(TRSection);
194 with Result.Sections[I] do
195 begin
196 ID := I;
197 Name := ReadNullTerm;
198 Read(Size, SizeOf(Size));
199 Read(SectType, SizeOf(SectType));
200 Read(Org, SizeOf(Org));
201 Read(Bank, SizeOf(Bank));
202 Read(Align, SizeOf(Align));
203 Read(Ofs, SizeOf(Ofs));
204 if ((SectType = ROMX) or (SectType = ROM0)) then
205 begin
206 SetLength(Data, Size);
207 Read(Data[0], Size);
208 Read(NumberOfPatches, SizeOf(NumberOfPatches));
209 SetLength(Patches, NumberOfPatches);
210 end;
211 end;
212
213 for J := 0 to Result.Sections[I].NumberOfPatches - 1 do
214 begin
215 with Result.Sections[I].Patches[J] do
216 begin
217 SourceFile := ReadNullTerm;
218 Read(Offset, SizeOf(Offset));
219 Read(PCSectionID, SizeOf(PCSectionID));
220 Read(PCOffset, SizeOf(PCOffset));
221 Read(PatchType, SizeOf(PatchType));
222 Read(RPNSize, SizeOf(RPNSize));
223 SetLength(RPN, RPNSize);
224 Read(RPN[0], RPNSize);
225 end;
226 end;
227 end;
228 finally
229 Free;
230 end;
231 end;
232
233 function RPNToString(const RPN: array of byte; const Syms: array of TRSymbol): string;
234 var
235 I: integer;
236
237 function ReadLong: longword;
238 begin
239 Inc(I);
240 Result := RPN[I];
241 Inc(I);
242 Result := (Result shl 8) or RPN[I];
243 Inc(I);
244 Result := (Result shl 8) or RPN[I];
245 Inc(I);
246 Result := (Result shl 8) or RPN[I];
247 Inc(I);
248 Result := SwapEndian(Result);
249 end;
250
251 begin
252 Result := '';
253
254 I := Low(RPN);
255 while I <= High(RPN) do
256 begin
257 case RPN[I] of
258 $00:
259 begin
260 Result += '+ ';
261 Inc(I);
262 end;
263 $01:
264 begin
265 Result += '- ';
266 Inc(I);
267 end;
268 $02:
269 begin
270 Result += '* ';
271 Inc(I);
272 end;
273 $03:
274 begin
275 Result += '/ ';
276 Inc(I);
277 end;
278 $04:
279 begin
280 Result += '% ';
281 Inc(I);
282 end;
283 $05:
284 begin
285 Result += 'neg ';
286 Inc(I);
287 end;
288 $10:
289 begin
290 Result += '| ';
291 Inc(I);
292 end;
293 $11:
294 begin
295 Result += '& ';
296 Inc(I);
297 end;
298 $12:
299 begin
300 Result += '^ ';
301 Inc(I);
302 end;
303 $13:
304 begin
305 Result += '~ ';
306 Inc(I);
307 end;
308 $21:
309 begin
310 Result += '&& ';
311 Inc(I);
312 end;
313 $22:
314 begin
315 Result += '|| ';
316 Inc(I);
317 end;
318 $23:
319 begin
320 Result += '! ';
321 Inc(I);
322 end;
323 $30:
324 begin
325 Result += '== ';
326 Inc(I);
327 end;
328 $31:
329 begin
330 Result += '!= ';
331 Inc(I);
332 end;
333 $32:
334 begin
335 Result += '> ';
336 Inc(I);
337 end;
338 $33:
339 begin
340 Result += '< ';
341 Inc(I);
342 end;
343 $34:
344 begin
345 Result += '>= ';
346 Inc(I);
347 end;
348 $35:
349 begin
350 Result += '<= ';
351 Inc(I);
352 end;
353 $40:
354 begin
355 Result += '<< ';
356 Inc(I);
357 end;
358 $41:
359 begin
360 Result += '>> ';
361 Inc(I);
362 end;
363 $50:
364 begin
365 Result += '(bank-sym ' + IntToStr(ReadLong) + ') ';
366 end;
367 $51:
368 begin
369 Result += '(bank-section ' + IntToStr(ReadLong) + ') ';
370 end;
371 $52:
372 begin
373 Result += 'current-bank';
374 Inc(I);
375 end;
376 $60:
377 begin
378 Result += 'hram-check';
379 Inc(I);
380 end;
381 $61:
382 begin
383 Result += 'rst-check';
384 Inc(I);
385 end;
386 $80:
387 begin
388 Result += '(int ' + IntToStr(ReadLong) + ') ';
389 end;
390 $81:
391 begin
392 Result += '(sym ' + Syms[ReadLong].Name + ') ';
393 end;
394 else
395 Exit('INVALID!');
396 end;
397 end;
398 end;
399
400 function ParseRPN(const RPN: array of byte): TRPN;
401 var
402 I: integer;
403 Node: TRPNNode;
404
405 function ReadLong: longword;
406 begin
407 Inc(I);
408 Result := RPN[I];
409 Inc(I);
410 Result := (Result shl 8) or RPN[I];
411 Inc(I);
412 Result := (Result shl 8) or RPN[I];
413 Inc(I);
414 Result := (Result shl 8) or RPN[I];
415 Inc(I);
416 Result := SwapEndian(Result);
417 end;
418
419 function nd(Tag: TRPNTag): TRPNNode;
420 begin
421 Result.Tag := Tag;
422 end;
423
424 procedure PushRPN(Node: TRPNNode);
425 begin
426 SetLength(Result, Length(Result) + 1);
427 Result[High(Result)] := Node;
428 end;
429
430 begin
431 SetLength(Result, 0);
432 I := Low(RPN);
433 while I <= High(RPN) do
434 begin
435 //Writeln(Format('Parsing %x, len=%d', [RPN[I], Length(Result)]));
436 case RPN[I] of
437 $00:
438 begin
439 PushRPN(Nd(rpnPlus));
440 Inc(I);
441 end;
442 $01:
443 begin
444 PushRPN(Nd(rpnMinus));
445 Inc(I);
446 end;
447 $02:
448 begin
449 PushRPN(Nd(rpnTimes));
450 Inc(I);
451 end;
452 $03:
453 begin
454 PushRPN(Nd(rpnDiv));
455 Inc(I);
456 end;
457 $04:
458 begin
459 PushRPN(Nd(rpnMod));
460 Inc(I);
461 end;
462 $05:
463 begin
464 PushRPN(Nd(rpnNegate));
465 Inc(I);
466 end;
467 $10:
468 begin
469 PushRPN(Nd(rpnOr));
470 Inc(I);
471 end;
472 $11:
473 begin
474 PushRPN(Nd(rpnAnd));
475 Inc(I);
476 end;
477 $12:
478 begin
479 PushRPN(Nd(rpnXor));
480 Inc(I);
481 end;
482 $13:
483 begin
484 PushRPN(Nd(rpnComplement));
485 Inc(I);
486 end;
487 $21:
488 begin
489 PushRPN(Nd(rpnBoolAnd));
490 Inc(I);
491 end;
492 $22:
493 begin
494 PushRPN(Nd(rpnBoolOr));
495 Inc(I);
496 end;
497 $23:
498 begin
499 PushRPN(Nd(rpnBoolNeg));
500 Inc(I);
501 end;
502 $30:
503 begin
504 PushRPN(Nd(rpnEqual));
505 Inc(I);
506 end;
507 $31:
508 begin
509 PushRPN(Nd(rpnNotEqual));
510 Inc(I);
511 end;
512 $32:
513 begin
514 PushRPN(Nd(rpnGreater));
515 Inc(I);
516 end;
517 $33:
518 begin
519 PushRPN(Nd(rpnLess));
520 Inc(I);
521 end;
522 $34:
523 begin
524 PushRPN(Nd(rpnGreaterEqual));
525 Inc(I);
526 end;
527 $35:
528 begin
529 PushRPN(Nd(rpnLessEqual));
530 Inc(I);
531 end;
532 $40:
533 begin
534 PushRPN(Nd(rpnShl));
535 Inc(I);
536 end;
537 $41:
538 begin
539 PushRPN(Nd(rpnShr));
540 Inc(I);
541 end;
542 $50:
543 begin
544 Node.Tag := rpnBankSymbol;
545 Node.BankSymbol := ReadLong;
546 PushRPN(Node);
547 end;
548 $51:
549 begin
550 Node.Tag := rpnBankSection;
551 Node.BankSection := ReadLong;
552 PushRPN(Node);
553 end;
554 $52:
555 begin
556 PushRPN(Nd(rpnCurrentBank));
557 Inc(I);
558 end;
559 $60:
560 begin
561 PushRPN(Nd(rpnHramCheck));
562 Inc(I);
563 end;
564 $61:
565 begin
566 PushRPN(Nd(rpnRstCheck));
567 Inc(I);
568 end;
569 $80:
570 begin
571 Node.Tag := rpnInteger;
572 Node.IntValue := ReadLong;
573 PushRPN(Node);
574 end;
575 $81:
576 begin
577 Node.Tag := rpnSymbol;
578 Node.SymbolID := ReadLong;
579 PushRPN(Node);
580 end;
581 else
582 Die('Got malformed RPN!');
583 end;
584 end;
585 end;
586
587
588 procedure PrintObjFile(O: TRObj);
589 var
590 Sym: TRSymbol;
591 Sect: TRSection;
592 Patch: TRPatch;
593 SectSize: integer;
594 begin
595 WriteLn('Symbols:');
596 for Sym in O.Symbols do
597 Writeln(Format(' %s on %d: type=%d, section=%d, value=%d',
598 [Sym.Name, Sym.LineNum, Sym.SymType, Sym.SectionID, Sym.Value]));
599
600 SectSize := 0;
601 for Sect in O.Sections do
602 if (Sect.Org <> -1) and ((Sect.SectType = ROM0) or (Sect.SectType = ROMX)) then
603 Inc(SectSize, Sect.Size);
604 Writeln('Absolute sections: ', SectSize, ' bytes');
605
606 SectSize := 0;
607 for Sect in O.Sections do
608 if (Sect.Org = -1) and ((Sect.SectType = ROM0) or (Sect.SectType = ROMX)) then
609 Inc(SectSize, Sect.Size);
610 Writeln('Relative sections: ', SectSize, ' bytes');
611
612 WriteLn('Sections:');
613 for Sect in O.Sections do
614 begin
615 Writeln(Format(' %s with size %d: offset=%d, patches=%d, bank=%d',
616 [Sect.Name, Sect.Size, Sect.Org, Sect.NumberOfPatches, Sect.Bank]));
617
618 for Patch in Sect.Patches do
619 Writeln(Format(' %s: %d ; %s', [Patch.SourceFile, Patch.PatchType,
620 RPNToString(Patch.RPN, O.Symbols)]));
621 end;
622 end;
623
624 function FindPatch(const Section: TRSection; Index: integer;
625 out Patch: TRPatch): boolean;
626 var
627 I: integer;
628 begin
629 for I := Low(Section.Patches) to High(Section.Patches) do
630 if Section.Patches[I].Offset = Index then
631 begin
632 Patch := Section.Patches[I];
633 Exit(True);
634 end;
635
636 Result := False;
637 end;
638
639 procedure ConvertRGB2SDAS(SourceName, DestName: String);
640 var
641 RObj: TRObj;
642
643 Symbol: TRSymbol;
644 Section: TRSection;
645 Patch: TRPatch;
646
647 F: Text;
648
649 ValueToWrite: word;
650 RPN: TRPN;
651 I: word;
652 Sct: word;
653 WritePos: word;
654 Idx: integer;
655 CODESEG: string;
656 DefaultBank: integer = 1;
657 tmp: string;
658
659 old_sym, new_sym: string;
660
661 verbose: boolean = False;
662
663 export_all: boolean = False;
664 begin
665 if not FileExists(sourcename) then
666 Die('File not found: %s', [sourcename]);
667
668 old_sym := '';
669 new_sym := '';
670
671 CODESEG := '_CODE';
672 {for I:= 1 to ParamCount() - 1 do begin
673 tmp:= ParamStr(i);
674 if (CompareText(tmp, '-v') = 0) then
675 verbose:= true
676 else if (CompareText(copy(tmp, 1, 2), '-e') = 0) then
677 export_all:= true
678 else if (CompareText(copy(tmp, 1, 2), '-c') = 0) then begin
679 CODESEG:= copy(tmp, 3, length(tmp));
680 if length(CODESEG) = 0 then CODESEG:= '_CODE';
681 if verbose then writeln('Using CODESEG: ', CODESEG);
682 end else if (CompareText(copy(tmp, 1, 2), '-b') = 0) then begin
683 DefaultBank:= StrToIntDef(copy(tmp, 3, length(tmp)), DefaultBank);
684 if verbose then writeln('Using DefaultBank: ', DefaultBank);
685 end else if (CompareText(copy(tmp, 1, 2), '-r') = 0) then begin
686 tmp:= copy(tmp, 3, length(tmp));
687 Idx:= pos('=', tmp);
688 if (idx > 0) then begin
689 old_sym:= copy(tmp, 1, idx - 1);
690 new_sym:= copy(tmp, idx + 1, length(tmp));
691 end;
692 end;
693 end;}
694
695 RObj := ReadObjFile(sourcename);
696 if verbose then
697 PrintObjFile(RObj);
698
699 Assign(F, DestName);
700 Rewrite(F);
701 try
702 Idx := 0;
703 // pass 1: all imports first
704 for I := Low(RObj.Symbols) to High(RObj.Symbols) do
705 with RObj.Symbols[I] do
706 begin
707 if ((SymType and $7f) = SYM_IMPORT) then
708 begin
709 No := Idx;
710 Inc(Idx);
711 end
712 else
713 No := -1;
714 end;
715 // pass 2: all other (export local only when forced)
716 for I := Low(RObj.Symbols) to High(RObj.Symbols) do
717 with RObj.Symbols[I] do
718 begin
719 case (SymType and $7f) of
720 SYM_LOCAL: if export_all then
721 begin
722 No := Idx;
723 Inc(Idx);
724 end;
725 SYM_IMPORT: ;
726 SYM_EXPORT:
727 begin
728 // rename exported symbol if requested
729 if (length(old_sym) > 0) and (Name = old_sym) then
730 Name := new_sym;
731 No := Idx;
732 Inc(Idx);
733 end;
734 else
735 Die('Unsupported symbol type: %d', [SymType and $7f]);
736 end;
737 end;
738
739 // output object header
740 Writeln(F, 'XL2');
741 Writeln(F, Format('H %x areas %x global symbols', [RObj.NumberOfSections, idx]));
742 Writeln(F, Format('M %s', [StringReplace(ExtractFileName(sourcename),
743 '.', '_', [rfReplaceAll])]));
744 Writeln(F, 'O -mgbz80');
745
746 // output all imported symbols
747 for I := Low(RObj.Symbols) to High(RObj.Symbols) do
748 with RObj.Symbols[I] do
749 if (SymType = SYM_IMPORT) then
750 Writeln(F, Format('S %s Ref%.4x',
751 [StringReplace(Name, '.', '____', [rfReplaceAll]), 0]));
752
753 // output all sections and other symbols
754 for Section in RObj.Sections do
755 begin
756 if Section.Org = -1 then
757 case Section.SectType of
758 ROM0: Writeln(F, Format('A %s size %x flags 0 addr 0',
759 [CODESEG, Section.Size]));
760 ROMX: if (DefaultBank = 0) then
761 Writeln(F, Format('A %s size %x flags 0 addr 0', [CODESEG, Section.Size]))
762 else
763 Writeln(F, Format('A _CODE_%d size %x flags 0 addr 0',
764 [max(DefaultBank, Section.Bank), Section.Size]));
765 else
766 Writeln(F, Format('A _DATA size %x flags 0 addr 0', [Section.Size]));
767 end
768 else
769 Die('absolute sections currently unsupported: %s', [Section.Name]);
770
771 for Symbol in RObj.Symbols do
772 if Symbol.SectionID = Section.ID then
773 begin
774 if (Symbol.SymType <> SYM_IMPORT) and (Symbol.No >= 0) then
775 Writeln(F, Format('S %s Def%.4x',
776 [StringReplace(Symbol.Name, '.', '____', [rfReplaceAll]), Symbol.Value]));
777 end;
778 end;
779
780 // convert object itself
781 for Sct := Low(RObj.Sections) to High(RObj.Sections) do
782 begin
783 Section := RObj.Sections[Sct];
784
785 if (Section.SectType <> ROMX) and (Section.SectType <> ROM0) then
786 Continue;
787 if Length(Section.Data) <= 0 then
788 Continue;
789
790 I := Low(Section.Data);
791 while I <= High(Section.Data) do
792 begin
793 WritePos := I;
794 if (Section.Org <> -1) then
795 Inc(WritePos, Section.Org);
796
797 if FindPatch(Section, I, Patch) then
798 begin
799 case Patch.PatchType of
800 PATCH_LE_WORD:
801 begin
802 RPN := ParseRPN(Patch.RPN);
803 Symbol := RObj.Symbols[RPN[0].SymbolID];
804 ValueToWrite := Symbol.Value;
805 if RPN[High(RPN)].Tag = rpnPlus then
806 Inc(ValueToWrite, RPN[1].IntValue);
807
808 if (Symbol.SymType = SYM_IMPORT) then
809 begin
810 if (Symbol.No < 0) then
811 Die('Trying to reference eliminated symbol');
812 Writeln(F, Format('T %.2x %.2x %.2x %.2x',
813 [lo(WritePos), hi(WritePos), lo(ValueToWrite), hi(ValueToWrite)]));
814 Writeln(F,
815 Format('R 00 00 %.2x %.2x 02 02 %.2x %.2x', [lo(Sct), hi(Sct),
816 lo(Symbol.No), hi(Symbol.No)]));
817 end
818 else
819 begin
820 Writeln(F, Format('T %.2x %.2x %.2x %.2x',
821 [lo(WritePos), hi(WritePos), lo(ValueToWrite), hi(ValueToWrite)]));
822 Writeln(F,
823 Format('R 00 00 %.2x %.2x 00 02 %.2x %.2x', [lo(Sct), hi(Sct),
824 lo(Symbol.SectionID), hi(Symbol.SectionID)]));
825 end;
826 Inc(I, 2);
827 end;
828 PATCH_JR:
829 begin
830 RPN := ParseRPN(Patch.RPN);
831 if Length(RPN) > 1 then
832 Die('Not handling bigger RPN on JR');
833 Symbol := RObj.Symbols[RPN[0].SymbolID];
834 Writeln(F, Format('T %.2x %.2x %.2x',
835 [lo(WritePos), hi(WritePos), byte(Symbol.Value - I - 1)]));
836 Writeln(F, Format('R 00 00 %.2x %.2x',
837 [lo(Sct), hi(Sct)]));
838 Inc(I);
839 end
840 else
841 Die('Unsupported patch type: %d', [Patch.PatchType]);
842 end;
843 end
844 else
845 begin
846 Writeln(F, Format('T %.2x %.2x %.2x',
847 [lo(WritePos), hi(WritePos), Section.Data[I]]));
848 Writeln(F, Format('R 00 00 %.2x %.2x', [lo(Sct), hi(Sct)]));
849 Inc(I);
850 end;
851 end;
852 end;
853
854 //Writeln('rgb2sdas converting ',sourcename,' --> ',sourcename,'.o result: success!');
855 finally
856 Close(F);
857 end;
858 end;
859
860 begin
861 end.
Modifiedtracker.lfm +23−29
@@ -211,11 +211,12 @@ object frmTracker: TfrmTracker
211 Height = 815 211 Height = 815
212 Top = 53 212 Top = 53
213 Width = 1407 213 Width = 1407
214 HorzScrollBar.Increment = 5 214 HorzScrollBar.Increment = 3
215 HorzScrollBar.Page = 56 215 HorzScrollBar.Page = 32
216 HorzScrollBar.Smooth = True 216 HorzScrollBar.Smooth = True
217 HorzScrollBar.Tracking = True 217 HorzScrollBar.Tracking = True
218 VertScrollBar.Page = 88 218 VertScrollBar.Increment = 5
219 VertScrollBar.Page = 50
219 VertScrollBar.Smooth = True 220 VertScrollBar.Smooth = True
220 VertScrollBar.Tracking = True 221 VertScrollBar.Tracking = True
221 Align = alClient 222 Align = alClient
@@ -1722,7 +1723,7 @@ object frmTracker: TfrmTracker
1722 ParentShowHint = False 1723 ParentShowHint = False
1723 end 1724 end
1724 object PanicToolButton: TToolButton 1725 object PanicToolButton: TToolButton
1725 Left = 551 1726 Left = 557
1726 Hint = 'Stops all sound output' 1727 Hint = 'Stops all sound output'
1727 Top = 0 1728 Top = 0
1728 AutoSize = True 1729 AutoSize = True
@@ -1733,17 +1734,17 @@ object frmTracker: TfrmTracker
1733 ShowHint = True 1734 ShowHint = True
1734 end 1735 end
1735 object ToolButton2: TToolButton 1736 object ToolButton2: TToolButton
1736 Left = 145 1737 Left = 147
1737 Top = 0 1738 Top = 0
1738 Action = PlayCursorAction 1739 Action = PlayCursorAction
1739 end 1740 end
1740 object ToolButton4: TToolButton 1741 object ToolButton4: TToolButton
1741 Left = 219 1742 Left = 221
1742 Top = 0 1743 Top = 0
1743 Action = StopAction 1744 Action = StopAction
1744 end 1745 end
1745 object ExportGBButton: TToolButton 1746 object ExportGBButton: TToolButton
1746 Left = 287 1747 Left = 291
1747 Hint = 'Export the song as a standalone ROM' 1748 Hint = 'Export the song as a standalone ROM'
1748 Top = 0 1749 Top = 0
1749 AutoSize = True 1750 AutoSize = True
@@ -1759,21 +1760,21 @@ object frmTracker: TfrmTracker
1759 Style = tbsDivider 1760 Style = tbsDivider
1760 end 1761 end
1761 object ToolButton6: TToolButton 1762 object ToolButton6: TToolButton
1762 Left = 284 1763 Left = 286
1763 Height = 22 1764 Height = 22
1764 Top = 0 1765 Top = 0
1765 Caption = 'ToolButton6' 1766 Caption = 'ToolButton6'
1766 Style = tbsDivider 1767 Style = tbsDivider
1767 end 1768 end
1768 object ToolButton7: TToolButton 1769 object ToolButton7: TToolButton
1769 Left = 1088 1770 Left = 1097
1770 Height = 22 1771 Height = 22
1771 Top = 0 1772 Top = 0
1772 Caption = 'ToolButton7' 1773 Caption = 'ToolButton7'
1773 Style = tbsSeparator 1774 Style = tbsSeparator
1774 end 1775 end
1775 object OctaveSpinEdit: TSpinEdit 1776 object OctaveSpinEdit: TSpinEdit
1776 Left = 654 1777 Left = 663
1777 Height = 23 1778 Height = 23
1778 Hint = 'The octave offset for entering new notes' 1779 Hint = 'The octave offset for entering new notes'
1779 Top = 0 1780 Top = 0
@@ -1784,14 +1785,14 @@ object frmTracker: TfrmTracker
1784 TabOrder = 0 1785 TabOrder = 0
1785 end 1786 end
1786 object ToolButton9: TToolButton 1787 object ToolButton9: TToolButton
1787 Left = 606 1788 Left = 612
1788 Height = 22 1789 Height = 22
1789 Top = 0 1790 Top = 0
1790 Caption = 'ToolButton9' 1791 Caption = 'ToolButton9'
1791 Style = tbsSeparator 1792 Style = tbsSeparator
1792 end 1793 end
1793 object Label22: TLabel 1794 object Label22: TLabel
1794 Left = 611 1795 Left = 620
1795 Height = 22 1796 Height = 22
1796 Top = 0 1797 Top = 0
1797 Width = 43 1798 Width = 43
@@ -1802,7 +1803,7 @@ object frmTracker: TfrmTracker
1802 ParentFont = False 1803 ParentFont = False
1803 end 1804 end
1804 object Label23: TLabel 1805 object Label23: TLabel
1805 Left = 719 1806 Left = 728
1806 Height = 22 1807 Height = 22
1807 Top = 0 1808 Top = 0
1808 Width = 70 1809 Width = 70
@@ -1813,7 +1814,7 @@ object frmTracker: TfrmTracker
1813 ParentFont = False 1814 ParentFont = False
1814 end 1815 end
1815 object InstrumentComboBox: TComboBox 1816 object InstrumentComboBox: TComboBox
1816 Left = 789 1817 Left = 798
1817 Height = 23 1818 Height = 23
1818 Hint = 'The selected instrument for new notes' 1819 Hint = 'The selected instrument for new notes'
1819 Top = 0 1820 Top = 0
@@ -1831,7 +1832,7 @@ object frmTracker: TfrmTracker
1831 Text = '(no instrument)' 1832 Text = '(no instrument)'
1832 end 1833 end
1833 object Label24: TLabel 1834 object Label24: TLabel
1834 Left = 1003 1835 Left = 1012
1835 Height = 22 1836 Height = 22
1836 Top = 0 1837 Top = 0
1837 Width = 35 1838 Width = 35
@@ -1842,7 +1843,7 @@ object frmTracker: TfrmTracker
1842 ParentFont = False 1843 ParentFont = False
1843 end 1844 end
1844 object StepSpinEdit: TSpinEdit 1845 object StepSpinEdit: TSpinEdit
1845 Left = 1038 1846 Left = 1047
1846 Height = 23 1847 Height = 23
1847 Hint = 'How many rows to step down after entering a new note' 1848 Hint = 'How many rows to step down after entering a new note'
1848 Top = 0 1849 Top = 0
@@ -1853,12 +1854,12 @@ object frmTracker: TfrmTracker
1853 TabOrder = 2 1854 TabOrder = 2
1854 end 1855 end
1855 object ToolButton3: TToolButton 1856 object ToolButton3: TToolButton
1856 Left = 82 1857 Left = 84
1857 Top = 0 1858 Top = 0
1858 Action = PlayStartAction 1859 Action = PlayStartAction
1859 end 1860 end
1860 object ExportGBSButton: TToolButton 1861 object ExportGBSButton: TToolButton
1861 Left = 368 1862 Left = 372
1862 Hint = 'Export the song as a GBS soundtrack' 1863 Hint = 'Export the song as a GBS soundtrack'
1863 Top = 0 1864 Top = 0
1864 Caption = 'Export .GBS' 1865 Caption = 'Export .GBS'
@@ -1866,14 +1867,14 @@ object frmTracker: TfrmTracker
1866 OnClick = ExportGBSButtonClick 1867 OnClick = ExportGBSButtonClick
1867 end 1868 end
1868 object ToolButton5: TToolButton 1869 object ToolButton5: TToolButton
1869 Left = 548 1870 Left = 552
1870 Height = 22 1871 Height = 22
1871 Top = 0 1872 Top = 0
1872 Caption = 'ToolButton5' 1873 Caption = 'ToolButton5'
1873 Style = tbsDivider 1874 Style = tbsDivider
1874 end 1875 end
1875 object ToolButton10: TToolButton 1876 object ToolButton10: TToolButton
1876 Left = 455 1877 Left = 459
1877 Hint = 'Export the song as WAV or MP3' 1878 Hint = 'Export the song as WAV or MP3'
1878 Top = 0 1879 Top = 0
1879 Caption = 'Render Song' 1880 Caption = 'Render Song'
@@ -1925,15 +1926,8 @@ object frmTracker: TfrmTracker
1925 object MenuItem40: TMenuItem 1926 object MenuItem40: TMenuItem
1926 Caption = '-' 1927 Caption = '-'
1927 end 1928 end
1928 object ExportRGBDSMenuItem: TMenuItem 1929 object MenuItem41: TMenuItem
1929 Caption = 'Export RGBDS .obj ...' 1930 Caption = 'Export RGBDS .htt ...'
1930 Hint = 'Export an object suitable for an RGBDS-based project'
1931 OnClick = ExportRGBDSMenuItemClick
1932 end
1933 object ExportGBDKMenuItem: TMenuItem
1934 Caption = 'Export GBDK .o ...'
1935 Hint = 'Export an object suitable for a GBDK-based project'
1936 OnClick = ExportGBDKMenuItemClick
1937 end 1931 end
1938 object ExportCMenuItem: TMenuItem 1932 object ExportCMenuItem: TMenuItem
1939 Caption = 'Export GBDK .c ...' 1933 Caption = 'Export GBDK .c ...'
Modifiedtracker.pas +6−24
@@ -30,9 +30,8 @@ type
30 InsertRowAction: TAction; 30 InsertRowAction: TAction;
31 MenuItem39: TMenuItem; 31 MenuItem39: TMenuItem;
32 ExportCMenuItem: TMenuItem; 32 ExportCMenuItem: TMenuItem;
33 ExportGBDKMenuItem: TMenuItem;
34 ExportRGBDSMenuItem: TMenuItem;
35 MenuItem40: TMenuItem; 33 MenuItem40: TMenuItem;
34 MenuItem41: TMenuItem;
36 MenuItem43: TMenuItem; 35 MenuItem43: TMenuItem;
37 MenuItem44: TMenuItem; 36 MenuItem44: TMenuItem;
38 MenuItem54: TMenuItem; 37 MenuItem54: TMenuItem;
@@ -258,8 +257,6 @@ type
258 procedure DeleteRowForAllActionUpdate(Sender: TObject); 257 procedure DeleteRowForAllActionUpdate(Sender: TObject);
259 procedure Duty1VisualizerClick(Sender: TObject); 258 procedure Duty1VisualizerClick(Sender: TObject);
260 procedure ExportCMenuItemClick(Sender: TObject); 259 procedure ExportCMenuItemClick(Sender: TObject);
261 procedure ExportGBDKMenuItemClick(Sender: TObject);
262 procedure ExportRGBDSMenuItemClick(Sender: TObject);
263 procedure FileSaveAs1BeforeExecute(Sender: TObject); 260 procedure FileSaveAs1BeforeExecute(Sender: TObject);
264 procedure FormCloseQuery(Sender: TObject; var CanClose: boolean); 261 procedure FormCloseQuery(Sender: TObject; var CanClose: boolean);
265 procedure FormDropFiles(Sender: TObject; const FileNames: array of String); 262 procedure FormDropFiles(Sender: TObject; const FileNames: array of String);
@@ -517,7 +514,8 @@ begin
517 for I := Low(Song.Instruments.Noise) to High(song.Instruments.Noise) do 514 for I := Low(Song.Instruments.Noise) to High(song.Instruments.Noise) do
518 InstrumentComboBox.Items.Add('Noise '+IntToStr(I)+': '+Song.Instruments.Noise[ModInst(I)].Name); 515 InstrumentComboBox.Items.Add('Noise '+IntToStr(I)+': '+Song.Instruments.Noise[ModInst(I)].Name);
519 516
520 InstrumentComboBox.ItemIndex := 0; 517 InstrumentComboBox.ItemIndex := 1;
518 TrackerGrid.SelectedInstrument := ModInst(InstrumentComboBox.ItemIndex);
521 519
522 for I := Low(TInstrumentBank) to High(TInstrumentBank) do begin 520 for I := Low(TInstrumentBank) to High(TInstrumentBank) do begin
523 DutyInstrumentsNode.Items[I-1].Text := IntToStr(I)+': '+Song.Instruments.Duty[I].Name; 521 DutyInstrumentsNode.Items[I-1].Text := IntToStr(I)+': '+Song.Instruments.Duty[I].Name;
@@ -1623,6 +1621,7 @@ end;
1623 procedure TfrmTracker.IncrementCurrentInstrumentActionExecute(Sender: TObject); 1621 procedure TfrmTracker.IncrementCurrentInstrumentActionExecute(Sender: TObject);
1624 begin 1622 begin
1625 InstrumentComboBox.ItemIndex := EnsureRange(InstrumentComboBox.ItemIndex+1, 0, InstrumentComboBox.Items.Count-1); 1623 InstrumentComboBox.ItemIndex := EnsureRange(InstrumentComboBox.ItemIndex+1, 0, InstrumentComboBox.Items.Count-1);
1624 TrackerGrid.SelectedInstrument := ModInst(InstrumentComboBox.ItemIndex);
1626 end; 1625 end;
1627 1626
1628 procedure TfrmTracker.InsertRowActionExecute(Sender: TObject); 1627 procedure TfrmTracker.InsertRowActionExecute(Sender: TObject);
@@ -1800,7 +1799,8 @@ end;
1800 1799
1801 procedure TfrmTracker.DecrementCurrentInstrumentActionExecute(Sender: TObject); 1800 procedure TfrmTracker.DecrementCurrentInstrumentActionExecute(Sender: TObject);
1802 begin 1801 begin
1803 InstrumentComboBox.ItemIndex := EnsureRange(InstrumentComboBox.ItemIndex-1, 0, InstrumentComboBox.Items.Count-1); 1802 InstrumentComboBox.ItemIndex := EnsureRange(InstrumentComboBox.ItemIndex-1, 0, InstrumentComboBox.Items.Count-1);
1803 TrackerGrid.SelectedInstrument := ModInst(InstrumentComboBox.ItemIndex);
1804 end; 1804 end;
1805 1805
1806 procedure TfrmTracker.DeleteRowActionExecute(Sender: TObject); 1806 procedure TfrmTracker.DeleteRowActionExecute(Sender: TObject);
@@ -1849,24 +1849,6 @@ begin
1849 ); 1849 );
1850 end; 1850 end;
1851 1851
1852 procedure TfrmTracker.ExportGBDKMenuItemClick(Sender: TObject);
1853 var
1854 S: String;
1855 begin
1856 S := InputBox('Song descriptor', 'Enter the song descriptor (must be a valid C symbol):', 'song_descriptor');
1857 if GBDKObjSaveDialog.Execute then
1858 RenderSongToFile(Song, GBDKObjSaveDialog.FileName, emGBDKObj, S);
1859 end;
1860
1861 procedure TfrmTracker.ExportRGBDSMenuItemClick(Sender: TObject);
1862 var
1863 S: String;
1864 begin
1865 S := InputBox('Song descriptor', 'Enter the song descriptor (must be a valid RGBDS symbol):', 'song_descriptor');
1866 if RGBDSObjSaveDialog.Execute then
1867 RenderSongToFile(Song, RGBDSObjSaveDialog.FileName, emRGBDSObj, S);
1868 end;
1869
1870 procedure TfrmTracker.PasteActionExecute(Sender: TObject); 1852 procedure TfrmTracker.PasteActionExecute(Sender: TObject);
1871 begin 1853 begin
1872 PostMessage(Screen.ActiveControl.Handle, LM_PASTE, 0, 0); 1854 PostMessage(Screen.ActiveControl.Handle, LM_PASTE, 0, 0);
Modifiedtrackergrid.pas +5−11
@@ -822,19 +822,13 @@ begin
822 Temp := -1; 822 Temp := -1;
823 823
824 with Patterns[Cursor.X]^[Cursor.Y] do 824 with Patterns[Cursor.X]^[Cursor.Y] do
825 if Key = VK_DELETE then 825 if Keybindings.TryGetData(Key, Temp) then begin
826 Note := NO_NOTE 826 Note := Min(HIGHEST_NOTE, Temp+(SelectedOctave*12));
827 else begin 827 if SelectedInstrument <> 0 then
828 if Keybindings.TryGetData(Key, Temp) then begin
829 Note := Min(HIGHEST_NOTE, Temp+(SelectedOctave*12));
830 Instrument := SelectedInstrument; 828 Instrument := SelectedInstrument;
831 829
832 Inc(Cursor.Y, Step); 830 Inc(Cursor.Y, Step);
833 ClampCursors; 831 ClampCursors;
834
835 {if Instrument > 0 then
836 SendMessage(frmTracker.Handle, LM_PREVIEW_NOTE, Note, Instrument);}
837 end;
838 end; 832 end;
839 833
840 Invalidate; 834 Invalidate;