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.
 
 
 
 
 

174 lines
4.6 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 "logging.h"
  4. #include "z80.h"
  5. #define FLAG_CARRY 0
  6. #define FLAG_SUBTRACT 1
  7. #define FLAG_PARITY 2
  8. #define FLAG_OVERFLOW 2
  9. #define FLAG_HALFCARRY 4
  10. #define FLAG_ZERO 6
  11. #define FLAG_SIGN 7
  12. /*
  13. Initialize a Z80 object.
  14. Register values are invalid until z80_power() is called. No other Z80
  15. functions should be called before it.
  16. */
  17. void z80_init(Z80 *z80, MMU *mmu)
  18. {
  19. z80->mmu = mmu;
  20. z80->except = true;
  21. }
  22. /*
  23. Power on the Z80, setting registers to their default values.
  24. This also clears the exception flag, which is necessary before the Z80 can
  25. begin emulation.
  26. */
  27. void z80_power(Z80 *z80)
  28. {
  29. Z80RegFile *regfile = &z80->regfile;
  30. regfile->a = regfile->f = 0xFF;
  31. regfile->b = regfile->c = 0xFF;
  32. regfile->d = regfile->e = 0xFF;
  33. regfile->h = regfile->l = 0xFF;
  34. regfile->a_ = regfile->f_ = 0xFF;
  35. regfile->b_ = regfile->c_ = 0xFF;
  36. regfile->d_ = regfile->e_ = 0xFF;
  37. regfile->h_ = regfile->l_ = 0xFF;
  38. regfile->ix = 0xFFFF;
  39. regfile->iy = 0xFFFF;
  40. regfile->sp = 0xFFFF;
  41. regfile->pc = 0x0000;
  42. regfile->i = 0xFF;
  43. regfile->r = 0xFF;
  44. regfile->im_a = regfile->im_b = 0;
  45. regfile->iff1 = regfile->iff2 = 0;
  46. z80->except = false;
  47. z80->pending_cycles = 0;
  48. }
  49. /*
  50. Return whether a particular flag is set in the F register.
  51. */
  52. static inline bool get_flag(Z80 *z80, uint8_t flag)
  53. {
  54. return z80->regfile.f & (1 << flag);
  55. }
  56. /*
  57. Return whether a particular flag is set in the F' register.
  58. */
  59. static inline bool get_shadow_flag(Z80 *z80, uint8_t flag)
  60. {
  61. return z80->regfile.f_ & (1 << flag);
  62. }
  63. /*
  64. Return the CPU's current interrupt mode.
  65. */
  66. static inline uint8_t get_interrupt_mode(Z80 *z80)
  67. {
  68. if (!z80->regfile.im_a)
  69. return 0;
  70. if (!z80->regfile.im_b)
  71. return 1;
  72. return 2;
  73. }
  74. /* ------------------------------------------------------------------------- */
  75. static uint8_t z80_inst_nop(Z80 *z80) {
  76. z80->regfile.pc++;
  77. return 4;
  78. }
  79. static uint8_t (*instruction_lookup_table[256])(Z80*) = {
  80. z80_inst_nop
  81. };
  82. /* ------------------------------------------------------------------------- */
  83. /*
  84. Emulate the given number of cycles of the Z80, or until an exception.
  85. The return value indicates whether the exception flag is set. If it is,
  86. then emulation must be stopped because further calls to z80_do_cycles()
  87. will have no effect. The exception flag can be reset with z80_power().
  88. */
  89. bool z80_do_cycles(Z80 *z80, double cycles)
  90. {
  91. if (z80->except)
  92. return true;
  93. cycles -= z80->pending_cycles;
  94. while (cycles > 0) {
  95. // uint8_t opcode = mmu_read_byte(&z80->mmu, z80->regfile.pc);
  96. uint8_t opcode = 0x00;
  97. cycles -= (*instruction_lookup_table[opcode])(z80) - 2;
  98. }
  99. z80->pending_cycles = -cycles;
  100. return false;
  101. }
  102. #ifdef DEBUG_MODE
  103. /*
  104. DEBUG FUNCTION: Print out all register values to stdout.
  105. */
  106. void z80_dump_registers(Z80 *z80)
  107. {
  108. Z80RegFile *regfile = &z80->regfile;
  109. DEBUG("Dumping Z80 register values:")
  110. DEBUG("- AF: 0x%02X%02X (C: %u, N: %u, P/V: %u, H: %u, Z: %u, S: %u)",
  111. regfile->a, regfile->f,
  112. get_flag(z80, FLAG_CARRY),
  113. get_flag(z80, FLAG_SUBTRACT),
  114. get_flag(z80, FLAG_PARITY),
  115. get_flag(z80, FLAG_HALFCARRY),
  116. get_flag(z80, FLAG_ZERO),
  117. get_flag(z80, FLAG_SIGN))
  118. DEBUG("- BC: 0x%02X%02X", regfile->b, regfile->c)
  119. DEBUG("- DE: 0x%02X%02X", regfile->d, regfile->e)
  120. DEBUG("- HL: 0x%02X%02X", regfile->h, regfile->l)
  121. DEBUG("- AF': 0x%02X%02X (C: %u, N: %u, P/V: %u, H: %u, Z: %u, S: %u)",
  122. regfile->a_, regfile->f_,
  123. get_shadow_flag(z80, FLAG_CARRY),
  124. get_shadow_flag(z80, FLAG_SUBTRACT),
  125. get_shadow_flag(z80, FLAG_PARITY),
  126. get_shadow_flag(z80, FLAG_HALFCARRY),
  127. get_shadow_flag(z80, FLAG_ZERO),
  128. get_shadow_flag(z80, FLAG_SIGN))
  129. DEBUG("- BC': 0x%02X%02X", regfile->b_, regfile->c_)
  130. DEBUG("- DE': 0x%02X%02X", regfile->d_, regfile->e_)
  131. DEBUG("- HL': 0x%02X%02X", regfile->h_, regfile->l_)
  132. DEBUG("- IX: 0x%04X", regfile->ix)
  133. DEBUG("- IY: 0x%04X", regfile->iy)
  134. DEBUG("- SP: 0x%04X", regfile->sp)
  135. DEBUG("- PC: 0x%04X", regfile->pc)
  136. DEBUG("- I: 0x%2X", regfile->i)
  137. DEBUG("- R: 0x%2X", regfile->r)
  138. DEBUG("- IM: 0b%u%u (mode: %u)", regfile->im_a, regfile->im_b,
  139. get_interrupt_mode(z80))
  140. DEBUG("- IFF1: %u", regfile->iff1)
  141. DEBUG("- IFF2: %u", regfile->iff2)
  142. }
  143. #endif