exp_os.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /* exp_os.c: Routines to export to a Flash OS
  2. Copyright (C) 2004 Billy Charvet
  3. Copyright (C) 2004-2008 Kevin Kofler
  4. Copyright (C) 2004 Sebastian Reichelt
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software Foundation,
  15. Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  16. #include "exp_os.h"
  17. #ifdef FLASH_OS_SUPPORT
  18. #include "../manip.h"
  19. #include "../special.h"
  20. // Get the file size needed to export the program into a Flash OS.
  21. // Returns 0 on failure.
  22. // Call this function once to receive necessary error messages.
  23. SIZE GetFlashOSFileSize (const PROGRAM *Program)
  24. {
  25. // Get a pointer to the main section.
  26. SECTION *MainSection = Program->MainSection;
  27. if (!MainSection)
  28. {
  29. Error (NULL, "No main section.");
  30. return 0;
  31. }
  32. {
  33. SIZE Size = MainSection->Size;
  34. if (Size & 0x1)
  35. Size++;
  36. return Size;
  37. }
  38. }
  39. // Export the internal data structures into a Flash OS.
  40. BOOLEAN ExportFlashOSFile (const PROGRAM *Program, EXP_FILE *File, SIZE FileSize, ProgramCalcs DestCalc)
  41. {
  42. // A simple macro to make the code more readable.
  43. #define FailWithError(Err...) ({ Error (Err); return FALSE; })
  44. // Get a pointer to the main section.
  45. const char *SectionFileName = NULL;
  46. OFFSET DataStart, DataEnd;
  47. I4 ROMBase;
  48. const I1 ZeroByte = 0;
  49. SECTION *MainSection = Program->MainSection;
  50. switch (DestCalc)
  51. {
  52. case CALC_TI89:
  53. case CALC_V200:
  54. ROMBase = 0x200000;
  55. break;
  56. case CALC_TI92PLUS:
  57. ROMBase = 0x400000;
  58. break;
  59. case CALC_TI89 | CALC_FLAG_TITANIUM:
  60. ROMBase = 0x800000;
  61. break;
  62. case CALC_TI92:
  63. FailWithError (NULL, "Flash upgrades are not available for the TI-92.");
  64. default:
  65. FailWithError (NULL, "Unknown calculator model.");
  66. }
  67. if (!MainSection)
  68. FailWithError (NULL, "No main section.");
  69. SectionFileName = MainSection->FileName;
  70. if (!(MainSection->StartupNumber || (Program->Type == PT_NOSTUB)))
  71. FailWithError (SectionFileName, "No startup section(s) defined.");
  72. if (!(MainSection->Data))
  73. FailWithError (SectionFileName, "No section contents.");
  74. // Write out the section contents first.
  75. DataStart = ExportTell (File);
  76. ExportWrite (File, MainSection->Data, MainSection->Size, 1);
  77. // Pad the main section to an even length.
  78. if (MainSection->Size & 0x1)
  79. ExportWrite (File, &ZeroByte, 1, 1);
  80. DataEnd = ExportTell (File);
  81. if (!(IsEmpty (MainSection->Relocs)))
  82. {
  83. RELOC *Reloc;
  84. // Write out the relocation entries.
  85. for (Reloc = GetLast (MainSection->Relocs); Reloc; Reloc = GetPrev (Reloc))
  86. {
  87. // Get the current file name for error messages.
  88. const char *CurFileName = GetFileName (MainSection, Reloc->Location);
  89. // If this can be resolved to a calculator-dependent value, write the
  90. // value into the section data.
  91. if (EmitCalcBuiltinValue (Reloc, DestCalc, File, FileSize, DataStart))
  92. continue;
  93. // We can only emit relocs with a target symbol in the same section.
  94. if (!(Reloc->Target.Symbol))
  95. FailWithError (CurFileName, "Unresolved reference to `%s'.", Reloc->Target.SymbolName);
  96. if (Reloc->Target.Symbol->Parent != MainSection)
  97. FailWithError (CurFileName, "Cannot emit reloc to `%s' in different section.", Reloc->Target.SymbolName);
  98. // We can only emit 4-byte absolute relocs.
  99. if (Reloc->Relative || (Reloc->Size != 4))
  100. FailWithError (CurFileName, "Cannot emit %ld byte %s reloc to `%s'.", (long) Reloc->Size, Reloc->Relative ? "relative" : "absolute", Reloc->Target.SymbolName);
  101. {
  102. OFFSET TargetLocation = GetLocationOffset (MainSection, &(Reloc->Target)) + Reloc->FixedOffset;
  103. TargetLocation += (OFFSET) (ROMBase + 0x12000);
  104. ExportSeek (File, DataStart + Reloc->Location);
  105. ExportWriteTI (File, TargetLocation, Reloc->Size, TRUE, TRUE);
  106. // Do not increase the statistics, since that would give a false
  107. // impression that the relocation entries actually take up some
  108. // space in the OS.
  109. }
  110. }
  111. ExportSeek (File, DataEnd);
  112. }
  113. if ((!(IsEmpty (MainSection->ROMCalls))) && (!(MainSection->ROMCalls.Handled)))
  114. FailWithError (SectionFileName, "ROM calls are not supported in Flash OSs.");
  115. if ((!(IsEmpty (MainSection->RAMCalls))) && (!(MainSection->RAMCalls.Handled)))
  116. FailWithError (SectionFileName, "RAM calls are not supported in Flash OSs.");
  117. if ((!(IsEmpty (MainSection->LibCalls))) && (!(MainSection->LibCalls.Handled)))
  118. FailWithError (SectionFileName, "Library calls are not supported in Flash OSs.");
  119. return TRUE;
  120. #undef FailWithError
  121. }
  122. #endif /* FLASH_OS_SUPPORT */