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.
 
 
 
 
 

120 lines
3.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 <stdlib.h>
  4. #include "gamegear.h"
  5. #include "logging.h"
  6. #include "util.h"
  7. /* Clock speed in Hz was taken from the official Sega GG documentation */
  8. #define CPU_CLOCK_SPEED 3579545
  9. /*
  10. Create and return a pointer to a new GameGear object.
  11. If memory could not be allocated, OUT_OF_MEMORY() is triggered.
  12. */
  13. GameGear* gamegear_create()
  14. {
  15. GameGear *gg = malloc(sizeof(GameGear));
  16. if (!gg)
  17. OUT_OF_MEMORY()
  18. // mmu_init(&gg->mmu, ...);
  19. z80_init(&gg->cpu, &gg->mmu);
  20. gg->powered = false;
  21. return gg;
  22. }
  23. /*
  24. Destroy a previously-allocated GameGear object.
  25. Does *not* destroy any loaded ROM objects.
  26. */
  27. void gamegear_destroy(GameGear *gg)
  28. {
  29. // mmu_free(&gg->mmu);
  30. free(gg);
  31. }
  32. /*
  33. Load a ROM image into the GameGear object.
  34. Does *not* steal a reference to the ROM object. Calling this function while
  35. the GameGear is powered on has no effect.
  36. */
  37. void gamegear_load(GameGear *gg, ROM *rom)
  38. {
  39. if (gg->powered)
  40. return;
  41. // mmu_hard_map(&gg->mmu, rom->data, ..., ...);
  42. }
  43. /*
  44. Set the GameGear object's power state (true = on; false = off).
  45. Powering on the GameGear executes boot code (e.g. clearing memory and
  46. setting initial register values) and starts the clock. Powering it off
  47. stops the clock.
  48. Setting the power state to its current value has no effect.
  49. */
  50. void gamegear_power(GameGear *gg, bool state)
  51. {
  52. if (gg->powered == state)
  53. return;
  54. if (state) {
  55. // mmu_power(&gg->mmu);
  56. z80_power(&gg->cpu);
  57. gg->last_tick = get_time_ns();
  58. } else {
  59. // TODO: free exception buffer
  60. }
  61. gg->powered = state;
  62. }
  63. /*
  64. Update the simulation of the GameGear.
  65. This function simulates the number of clock cycles corresponding to the
  66. time since the last call to gamegear_simulate() or gamegear_power() if the
  67. system was just powered on. If the system is powered off, this function
  68. does nothing.
  69. The return value indicates whether an exception flag has been set
  70. somewhere. If true, emulation must be stopped. gamegear_get_exception() can
  71. be used to fetch exception information. Power-cycling the GameGear with
  72. gamegear_power(gg, false) followed by gamegear_power(gg, true) will reset
  73. the exception flag and allow emulation to restart normally.
  74. */
  75. bool gamegear_simulate(GameGear *gg)
  76. {
  77. if (!gg->powered)
  78. return false;
  79. uint64_t last = gg->last_tick, tick;
  80. tick = gg->last_tick = get_time_ns();
  81. return z80_do_cycles(&gg->cpu, (tick - last) * CPU_CLOCK_SPEED / 1e9);
  82. }
  83. /*
  84. If an exception flag has been set in the GameGear, return the reason.
  85. This function returns a const pointer to a buffer holding a human-readable
  86. exception string (although it may be cryptic to an end-user). The buffer is
  87. owned by the GameGear object and should not be freed - it lasts until the
  88. GameGear's power state is changed. If no exception flag is set, this
  89. function returns NULL.
  90. */
  91. const char* gamegear_get_exception(GameGear *gg)
  92. {
  93. if (!gg->powered)
  94. return NULL;
  95. // TODO: return ptr to exception buffer
  96. return "Unknown exception";
  97. }