@@ -6,14 +6,16 @@ interface |
| 6 |
|
6 |
|
| 7 |
uses |
7 |
uses |
| 8 |
Classes, SysUtils, Math, Instruments, Song, Utils, |
8 |
Classes, SysUtils, Math, Instruments, Song, Utils, |
| 9 |
HugeDatatypes, Constants, Dialogs, strutils, FileUtil, LazFileUtils, |
9 |
HugeDatatypes, Constants, Dialogs, strutils, FileUtil, LazFileUtils, process; |
| 10 |
lclintf, process; |
|
|
| 11 |
|
10 |
|
| 12 |
type |
11 |
type |
|
|
12 |
EAssemblyException = class(Exception); |
|
|
13 |
ECodegenRenameError = class(Exception); |
|
|
14 |
|
| 13 |
TExportMode = (emNormal, emPreview, emGBS); |
15 |
TExportMode = (emNormal, emPreview, emGBS); |
| 14 |
|
16 |
|
| 15 |
function RenderPreviewRom(Song: TSong): boolean; |
17 |
procedure RenderPreviewRom(Song: TSong); |
| 16 |
function RenderSongToFile(Song: TSong; Filename: string; Mode: TExportMode = emNormal): boolean; |
18 |
procedure RenderSongToFile(Song: TSong; Filename: string; Mode: TExportMode = emNormal); |
| 17 |
procedure RenderSongToGBDKC(Song: TSong; DescriptorName: String; Filename: string); |
19 |
procedure RenderSongToGBDKC(Song: TSong; DescriptorName: String; Filename: string); |
| 18 |
procedure RenderSongToRGBDSAsm(Song: TSong; DescriptorName: String; Filename: string); |
20 |
procedure RenderSongToRGBDSAsm(Song: TSong; DescriptorName: String; Filename: string); |
| 19 |
|
21 |
|
@@ -425,21 +427,32 @@ begin |
| 425 |
Stream.Free; |
427 |
Stream.Free; |
| 426 |
end; |
428 |
end; |
| 427 |
|
429 |
|
| 428 |
function RenderPreviewROM(Song: TSong): boolean; |
430 |
procedure RenderPreviewROM(Song: TSong); |
| 429 |
begin |
431 |
begin |
| 430 |
Result := RenderSongToFile(Song, 'preview.gb', emPreview); |
432 |
RenderSongToFile(Song, 'preview.gb', emPreview); |
| 431 |
end; |
433 |
end; |
| 432 |
|
434 |
|
| 433 |
function RenderSongToFile(Song: TSong; Filename: String; Mode: TExportMode = emNormal): boolean; |
435 |
procedure RenderSongToFile(Song: TSong; Filename: String; Mode: TExportMode = emNormal); |
| 434 |
{ TODO: Refactor this whole monstrosity. } |
|
|
| 435 |
var |
436 |
var |
| 436 |
OutFile: Text; |
437 |
OutFile: Text; |
| 437 |
I: integer; |
438 |
I: integer; |
| 438 |
Proc: TProcess; |
439 |
Proc: TProcess; |
| 439 |
OutSL: TStringList; |
|
|
| 440 |
FilePath: string; |
440 |
FilePath: string; |
| 441 |
RenameSucceeded: Boolean; |
441 |
RenameSucceeded: Boolean; |
| 442 |
|
442 |
|
|
|
443 |
procedure Die; |
|
|
444 |
var |
|
|
445 |
OutSL: TStringList; |
|
|
446 |
begin |
|
|
447 |
OutSL := TStringList.Create; |
|
|
448 |
try |
|
|
449 |
OutSL.LoadFromStream(Proc.Output); |
|
|
450 |
raise EAssemblyException.Create(OutSL.Text); |
|
|
451 |
finally |
|
|
452 |
OutSL.Free; |
|
|
453 |
end; |
|
|
454 |
end; |
|
|
455 |
|
| 443 |
procedure WriteHTT(F: string; S: string); |
456 |
procedure WriteHTT(F: string; S: string); |
| 444 |
begin |
457 |
begin |
| 445 |
AssignFile(OutFile, F); |
458 |
AssignFile(OutFile, F); |
@@ -495,9 +508,6 @@ var |
| 495 |
|
508 |
|
| 496 |
Result := Proc.ExitCode; |
509 |
Result := Proc.ExitCode; |
| 497 |
end; |
510 |
end; |
| 498 |
|
|
|
| 499 |
label |
|
|
| 500 |
AssemblyError, Cleanup; // Eh, screw good practice. How bad can it be? |
|
|
| 501 |
begin |
511 |
begin |
| 502 |
Song := OptimizeSong(Song); |
512 |
Song := OptimizeSong(Song); |
| 503 |
|
513 |
|
@@ -525,111 +535,103 @@ begin |
| 525 |
CloseFile(OutFile); |
535 |
CloseFile(OutFile); |
| 526 |
|
536 |
|
| 527 |
// Build the file |
537 |
// Build the file |
| 528 |
OutSL := TStringList.Create; |
|
|
| 529 |
Proc := TProcess.Create(nil); |
538 |
Proc := TProcess.Create(nil); |
| 530 |
Proc.Options := Proc.Options + [poWaitOnExit, poUsePipes, poStdErrToOutput, poNoConsole]; |
539 |
Proc.Options := Proc.Options + [poWaitOnExit, poUsePipes, poStdErrToOutput, poNoConsole]; |
| 531 |
|
540 |
|
| 532 |
// Assemble |
541 |
try |
| 533 |
if Mode = emPreview then |
542 |
// Assemble |
| 534 |
begin |
543 |
if Mode = emPreview then |
| 535 |
if Assemble(Filename + '_driver.obj', 'hUGEDriver/hUGEDriver.asm', ['PREVIEW_MODE']) <> 0 then |
544 |
begin |
| 536 |
goto AssemblyError; |
545 |
if Assemble(Filename + '_driver.obj', 'hUGEDriver/hUGEDriver.asm', ['PREVIEW_MODE']) <> 0 then |
| 537 |
end |
546 |
Die; |
| 538 |
else |
547 |
end |
| 539 |
begin |
548 |
else |
| 540 |
if Assemble(Filename + '_driver.obj', 'hUGEDriver/hUGEDriver.asm', []) <> 0 then |
549 |
begin |
| 541 |
goto AssemblyError; |
550 |
if Assemble(Filename + '_driver.obj', 'hUGEDriver/hUGEDriver.asm', []) <> 0 then |
| 542 |
end; |
551 |
Die; |
| 543 |
|
552 |
end; |
| 544 |
if Assemble(Filename + '_song.obj', |
|
|
| 545 |
'hUGEDriver/song.asm', |
|
|
| 546 |
['SONG_DESCRIPTOR=song', 'TICKS='+IntToStr(Song.TicksPerRow)]) <> 0 then |
|
|
| 547 |
goto AssemblyError; |
|
|
| 548 |
|
|
|
| 549 |
if Mode = emGBS then |
|
|
| 550 |
begin |
|
|
| 551 |
if Assemble( |
|
|
| 552 |
Filename + '_gbs.obj', 'hUGEDriver/gbs.asm', |
|
|
| 553 |
['SONG_DESCRIPTOR=song', |
|
|
| 554 |
'GBS_TITLE='+PadRight(Song.Name, 32), |
|
|
| 555 |
'GBS_AUTHOR='+PadRight(Song.Artist, 32), |
|
|
| 556 |
'GBS_COPYRIGHT='+PadRight(IntToStr(CurrentYear), 32)] |
|
|
| 557 |
) <> 0 then goto AssemblyError; |
|
|
| 558 |
end |
|
|
| 559 |
else |
|
|
| 560 |
begin |
|
|
| 561 |
if Assemble(Filename + '_player.obj', 'hUGEDriver/player.asm', ['SONG_DESCRIPTOR=song']) <> 0 then |
|
|
| 562 |
goto AssemblyError; |
|
|
| 563 |
end; |
|
|
| 564 |
|
|
|
| 565 |
// Link |
|
|
| 566 |
if Mode = emGBS then |
|
|
| 567 |
begin |
|
|
| 568 |
if Link(Filename + '.gbs', |
|
|
| 569 |
[Filename + '_driver.obj', |
|
|
| 570 |
Filename + '_song.obj', |
|
|
| 571 |
Filename + '_gbs.obj']) <> 0 then goto AssemblyError; |
|
|
| 572 |
end |
|
|
| 573 |
else |
|
|
| 574 |
begin |
|
|
| 575 |
if Link(Filename + '.gb', |
|
|
| 576 |
[Filename + '_driver.obj', |
|
|
| 577 |
Filename + '_song.obj', |
|
|
| 578 |
Filename + '_player.obj'], |
|
|
| 579 |
Filename + '.map', |
|
|
| 580 |
Filename + '.sym') <> 0 then goto AssemblyError; |
|
|
| 581 |
end; |
|
|
| 582 |
|
553 |
|
| 583 |
// Fix |
554 |
if Assemble(Filename + '_song.obj', |
| 584 |
if Mode = emGBS then |
555 |
'hUGEDriver/song.asm', |
| 585 |
RectifyGBSFile(Filename + '.gbs') |
556 |
['SONG_DESCRIPTOR=song', 'TICKS='+IntToStr(Song.TicksPerRow)]) <> 0 then |
| 586 |
else |
557 |
Die; |
| 587 |
begin |
|
|
| 588 |
if (Fix(Filename + '.gb') <> 0) then |
|
|
| 589 |
goto AssemblyError; |
|
|
| 590 |
end; |
|
|
| 591 |
|
558 |
|
| 592 |
// Move to destination |
559 |
if Mode = emGBS then |
| 593 |
if Mode <> emPreview then |
560 |
begin |
| 594 |
begin |
561 |
if Assemble( |
| 595 |
if FileExists(FilePath) then |
562 |
Filename + '_gbs.obj', 'hUGEDriver/gbs.asm', |
| 596 |
DeleteFile(FilePath); |
563 |
['SONG_DESCRIPTOR=song', |
|
|
564 |
'GBS_TITLE='+PadRight(Song.Name, 32), |
|
|
565 |
'GBS_AUTHOR='+PadRight(Song.Artist, 32), |
|
|
566 |
'GBS_COPYRIGHT='+PadRight(IntToStr(CurrentYear), 32)] |
|
|
567 |
) <> 0 then Die; |
|
|
568 |
end |
|
|
569 |
else |
|
|
570 |
begin |
|
|
571 |
if Assemble(Filename + '_player.obj', 'hUGEDriver/player.asm', ['SONG_DESCRIPTOR=song']) <> 0 then |
|
|
572 |
Die; |
|
|
573 |
end; |
| 597 |
|
574 |
|
| 598 |
case Mode of |
575 |
// Link |
| 599 |
emGBS: RenameSucceeded := RenameFile(Filename + '.gbs', FilePath); |
576 |
if Mode = emGBS then |
| 600 |
else RenameSucceeded := RenameFile(Filename + '.gb', FilePath); |
577 |
begin |
|
|
578 |
if Link(Filename + '.gbs', |
|
|
579 |
[Filename + '_driver.obj', |
|
|
580 |
Filename + '_song.obj', |
|
|
581 |
Filename + '_gbs.obj']) <> 0 then Die; |
|
|
582 |
end |
|
|
583 |
else |
|
|
584 |
begin |
|
|
585 |
if Link(Filename + '.gb', |
|
|
586 |
[Filename + '_driver.obj', |
|
|
587 |
Filename + '_song.obj', |
|
|
588 |
Filename + '_player.obj'], |
|
|
589 |
Filename + '.map', |
|
|
590 |
Filename + '.sym') <> 0 then Die; |
| 601 |
end; |
591 |
end; |
| 602 |
|
592 |
|
| 603 |
if not RenameSucceeded then |
593 |
// Fix |
|
|
594 |
if Mode = emGBS then |
|
|
595 |
RectifyGBSFile(Filename + '.gbs') |
|
|
596 |
else |
| 604 |
begin |
597 |
begin |
| 605 |
MessageDlg('Error!', |
598 |
if (Fix(Filename + '.gb') <> 0) then |
| 606 |
'Couldn''t create file at ' + FilePath + |
599 |
Die; |
| 607 |
'. Make sure your path is correct!', |
|
|
| 608 |
mtError, |
|
|
| 609 |
[mbOK], |
|
|
| 610 |
0); |
|
|
| 611 |
Result := False; |
|
|
| 612 |
goto Cleanup; |
|
|
| 613 |
end; |
600 |
end; |
| 614 |
{$ifdef DEVELOPMENT} |
|
|
| 615 |
RenameFile(Filename + '.sym', FilePath + '.sym'); |
|
|
| 616 |
RenameFile(Filename + '.map', FilePath + '.map'); |
|
|
| 617 |
{$endif} |
|
|
| 618 |
{$ifdef PRODUCTION} |
|
|
| 619 |
DeleteFile(Filename + '.sym'); |
|
|
| 620 |
DeleteFile(Filename + '.map'); |
|
|
| 621 |
{$endif} |
|
|
| 622 |
|
601 |
|
| 623 |
DeleteFile(Filename + '_driver.obj'); |
602 |
// Move to destination |
| 624 |
DeleteFile(Filename + '_song.obj'); |
603 |
if Mode <> emPreview then |
| 625 |
DeleteFile(Filename + '_player.obj'); |
604 |
begin |
| 626 |
DeleteFile(Filename + '_gbs.obj'); |
605 |
if FileExists(FilePath) then |
| 627 |
end; |
606 |
DeleteFile(FilePath); |
| 628 |
|
607 |
|
| 629 |
Result := True; |
608 |
case Mode of |
| 630 |
goto Cleanup; |
609 |
emGBS: RenameSucceeded := RenameFile(Filename + '.gbs', FilePath); |
|
|
610 |
else RenameSucceeded := RenameFile(Filename + '.gb', FilePath); |
|
|
611 |
end; |
| 631 |
|
612 |
|
| 632 |
AssemblyError: |
613 |
if not RenameSucceeded then |
|
|
614 |
raise ECodegenRenameError.Create(FilePath); |
|
|
615 |
|
|
|
616 |
{$ifdef DEVELOPMENT} |
|
|
617 |
RenameFile(Filename + '.sym', FilePath + '.sym'); |
|
|
618 |
RenameFile(Filename + '.map', FilePath + '.map'); |
|
|
619 |
{$endif} |
|
|
620 |
{$ifdef PRODUCTION} |
|
|
621 |
DeleteFile(Filename + '.sym'); |
|
|
622 |
DeleteFile(Filename + '.map'); |
|
|
623 |
{$endif} |
|
|
624 |
|
|
|
625 |
DeleteFile(Filename + '_driver.obj'); |
|
|
626 |
DeleteFile(Filename + '_song.obj'); |
|
|
627 |
DeleteFile(Filename + '_player.obj'); |
|
|
628 |
DeleteFile(Filename + '_gbs.obj'); |
|
|
629 |
end; |
|
|
630 |
finally |
|
|
631 |
Proc.Free; |
|
|
632 |
end; |
|
|
633 |
|
|
|
634 |
{AssemblyError: |
| 633 |
Result := False; |
635 |
Result := False; |
| 634 |
OutSL.LoadFromStream(Proc.Output); |
636 |
OutSL.LoadFromStream(Proc.Output); |
| 635 |
|
637 |
|
@@ -657,13 +659,7 @@ begin |
| 657 |
{$ifdef PRODUCTION} |
659 |
{$ifdef PRODUCTION} |
| 658 |
OpenURL('https://github.com/SuperDisk/hUGETracker/issues'); |
660 |
OpenURL('https://github.com/SuperDisk/hUGETracker/issues'); |
| 659 |
{$endif} |
661 |
{$endif} |
| 660 |
end; |
662 |
end;} |
| 661 |
|
|
|
| 662 |
Cleanup: |
|
|
| 663 |
// No need to destroy Song-- OptimizeSong's output has the same lifetime |
|
|
| 664 |
// as its argument. |
|
|
| 665 |
Proc.Free; |
|
|
| 666 |
OutSL.Free; |
|
|
| 667 |
end; |
663 |
end; |
| 668 |
|
664 |
|
| 669 |
end. |
665 |
end. |