Add-in development tools for fx-9860G and fx-CG 50, to use with GCC and gint.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

92 lines
2.3KB

  1. #include <endianness.h>
  2. #include <string.h>
  3. #include <fxos.h>
  4. #include <errors.h>
  5. #include <util.h>
  6. /* os_load(): Load an OS file and find out basic properties */
  7. int os_load(char const *path, struct os *os)
  8. {
  9. if(!path || !os) return 1;
  10. os->data = map(path, &os->fd, &os->len);
  11. if(!os->data) return 1;
  12. if(os->len < 0x10080)
  13. {
  14. err("too small for the OS format I know (min. 0x10080 bytes)",
  15. os->len);
  16. return 1;
  17. }
  18. /* Get the OS version */
  19. memcpy(os->version, os->data + 0x10020, 14);
  20. os->version[14] = 0;
  21. /* Guess the MPU type (or assume SH7305). Until version 03.00, the last
  22. digit of the version number indicated the presence of an SH7305 */
  23. os->mpu = MPU_SH7305;
  24. if(!strncmp(os->version, "02.", 3) && os->version[13] == '0')
  25. os->mpu = MPU_SH7705;
  26. /* Find the syscall table address */
  27. memcpy(&os->syscall_table, os->data + 0x1007c, 4);
  28. os->syscall_table = be32toh(os->syscall_table);
  29. /* Count the number of valid syscall entries */
  30. os->syscalls = 0;
  31. while(memory_region(os_syscall(os, os->syscalls))) os->syscalls++;
  32. /* Find the footer address (last occurrence of "CASIOABSLangdata") */
  33. char const *signature = "CASIOABSLangdata";
  34. void *occ = NULL, *next = memmem(os->data, os->len, signature, 16);
  35. void *end = os->data + os->len;
  36. while(next)
  37. {
  38. occ = next;
  39. next = memmem(next + 1, end - (next + 1), signature, 16);
  40. }
  41. os->footer = (occ) ? (occ - os->data) : (uint32_t)-1;
  42. return 0;
  43. }
  44. /* os_syscall(): Get the address of a syscall entry */
  45. uint32_t os_syscall(struct os const *os, int syscall)
  46. {
  47. uint32_t table_entry = (os->syscall_table & 0x1fffffff) + 4 * syscall;
  48. if(table_entry + 4 > os->len) return (uint32_t)-1;
  49. uint32_t address;
  50. memcpy(&address, os->data + table_entry, 4);
  51. address = be32toh(address);
  52. return address;
  53. }
  54. /* os_syscall_find(): Find a syscall which points to an address */
  55. int os_syscall_find(struct os const *os, uint32_t entry)
  56. {
  57. /* Try to make this slightly quicker */
  58. uint32_t table_entry = (os->syscall_table & 0x1fffffff);
  59. entry = htobe32(entry);
  60. uint32_t *entries = os->data + table_entry;
  61. for(int i = 0; i < os->syscalls; i++) if(entries[i] == entry) return i;
  62. return -1;
  63. }
  64. /* os_free(): Free an OS file opened with os_load() */
  65. void os_free(struct os const *os)
  66. {
  67. if(os && os->data) unmap(os->data, os->fd, os->len);
  68. }