An emulator, assembler, and disassembler for the Sega Game Gear
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.
 
 
 
 
 

98 lines
2.2 KiB

  1. /* Copyright (C) 2014-2015 Ben Kurtovic <ben.kurtovic@gmail.com>
  2. Released under the terms of the MIT License. See LICENSE for details. */
  3. #include <errno.h>
  4. #include <stdbool.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <sys/stat.h>
  9. #include "rom.h"
  10. #include "logging.h"
  11. /*
  12. Return whether or not the given ROM image size is valid.
  13. */
  14. static bool validate_size(off_t size)
  15. {
  16. off_t kbytes = size >> 10;
  17. if (kbytes << 10 != size)
  18. return false;
  19. if (kbytes < 8 || kbytes > 1024)
  20. return false;
  21. return !(kbytes & (kbytes - 1));
  22. }
  23. /*
  24. Create and load a ROM image located at the given path.
  25. rom_ptr will point to the new object if created successfully, and NULL will
  26. be returned. Otherwise, rom_ptr will not be modified and an error string
  27. will be returned. The error string should not be freed.
  28. */
  29. const char* rom_open(ROM **rom_ptr, const char *path)
  30. {
  31. ROM *rom;
  32. FILE* fp;
  33. struct stat st;
  34. if (!(fp = fopen(path, "r")))
  35. return strerror(errno);
  36. if (fstat(fileno(fp), &st)) {
  37. fclose(fp);
  38. return strerror(errno);
  39. }
  40. if (!(st.st_mode & S_IFREG)) {
  41. fclose(fp);
  42. return (st.st_mode & S_IFDIR) ? rom_err_isdir : rom_err_notfile;
  43. }
  44. if (!(rom = malloc(sizeof(ROM))))
  45. OUT_OF_MEMORY()
  46. // Set defaults:
  47. rom->name = NULL;
  48. rom->data = NULL;
  49. rom->size = 0;
  50. // Set rom->name:
  51. if (!(rom->name = malloc(sizeof(char) * (strlen(path) + 1))))
  52. OUT_OF_MEMORY()
  53. strcpy(rom->name, path);
  54. // Set rom->size:
  55. if (!validate_size(st.st_size)) {
  56. rom_close(rom);
  57. fclose(fp);
  58. return rom_err_badsize;
  59. }
  60. rom->size = st.st_size;
  61. // Set rom->data:
  62. if (!(rom->data = malloc(sizeof(char) * st.st_size)))
  63. OUT_OF_MEMORY()
  64. if (!(fread(rom->data, st.st_size, 1, fp))) {
  65. rom_close(rom);
  66. fclose(fp);
  67. return rom_err_badread;
  68. }
  69. fclose(fp);
  70. *rom_ptr = rom;
  71. return NULL;
  72. }
  73. /*
  74. Free a ROM object previously created with rom_open().
  75. */
  76. void rom_close(ROM *rom)
  77. {
  78. if (rom->name)
  79. free(rom->name);
  80. if (rom->data)
  81. free(rom->data);
  82. free(rom);
  83. }