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.
 
 
 
 
 

146 lines
3.3 KiB

  1. /* Copyright (C) 2014-2017 Ben Kurtovic <ben.kurtovic@gmail.com>
  2. Released under the terms of the MIT License. See LICENSE for details. */
  3. #include "io.h"
  4. #include "logging.h"
  5. /*
  6. Initialize an IO object.
  7. */
  8. void io_init(IO *io, MMU *mmu, VDP *vdp, PSG *psg)
  9. {
  10. io->vdp = vdp;
  11. io->mmu = mmu;
  12. io->psg = psg;
  13. }
  14. /*
  15. "Power on" the IO object.
  16. */
  17. void io_power(IO *io)
  18. {
  19. io->ports[0x00] = 0xC0; // Overseas mode, NTSC
  20. io->ports[0x01] = 0x7F;
  21. io->ports[0x02] = 0xFF;
  22. io->ports[0x03] = 0x00;
  23. io->ports[0x04] = 0xFF;
  24. io->ports[0x05] = 0x00;
  25. io->buttons = 0xFF;
  26. io->start = true;
  27. }
  28. /*
  29. Return whether the IRQ line is currently active.
  30. */
  31. bool io_check_irq(IO *io)
  32. {
  33. return vdp_assert_irq(io->vdp);
  34. }
  35. /*
  36. Set the state of the given joystick button.
  37. */
  38. void io_set_button(IO *io, uint8_t button, bool state)
  39. {
  40. io->buttons = (io->buttons & ~(1 << button)) | ((!state) << button);
  41. }
  42. /*
  43. Set the state of the start button.
  44. */
  45. void io_set_start(IO *io, bool state)
  46. {
  47. io->start = !state;
  48. }
  49. /*
  50. Read from one of the system ports, which are numbered from 0x00 to 0x06.
  51. */
  52. static uint8_t read_system_port(IO *io, uint8_t port)
  53. {
  54. switch (port) {
  55. case 0x00:
  56. return (io->ports[port] & 0x7F) | (io->start << 7);
  57. case 0x01:
  58. case 0x02:
  59. case 0x03:
  60. case 0x04:
  61. case 0x05:
  62. return io->ports[port];
  63. }
  64. return 0xFF;
  65. }
  66. /*
  67. Write to one of the system ports, which are numbered from 0x00 to 0x06.
  68. */
  69. static void write_system_port(IO *io, uint8_t port, uint8_t value)
  70. {
  71. switch (port) {
  72. case 0x01:
  73. case 0x02:
  74. case 0x03:
  75. io->ports[port] = value;
  76. break;
  77. case 0x05:
  78. io->ports[port] = value & 0xF8;
  79. break;
  80. case 0x06:
  81. psg_stereo(io->psg, value);
  82. break;
  83. }
  84. }
  85. /*
  86. Write to the memory control port, $3E.
  87. */
  88. static void write_memory_control(IO *io, uint8_t value)
  89. {
  90. io->mmu->bios_enabled = !(value & 0x08);
  91. }
  92. /*
  93. Read and return a byte from the given port.
  94. */
  95. uint8_t io_port_read(IO *io, uint8_t port)
  96. {
  97. if (port <= 0x06)
  98. return read_system_port(io, port);
  99. else if (port <= 0x3F)
  100. return 0xFF;
  101. else if (port <= 0x7F && !(port % 2))
  102. return io->vdp->v_counter;
  103. else if (port <= 0x7F)
  104. return io->vdp->h_counter;
  105. else if (port <= 0xBF && !(port % 2))
  106. return vdp_read_data(io->vdp);
  107. else if (port <= 0xBF)
  108. return vdp_read_control(io->vdp);
  109. else if (port == 0xCD || port == 0xDC)
  110. return io->buttons;
  111. else if (port == 0xC1 || port == 0xDD)
  112. return 0xFF; // B/Misc port, always set (unless in SMS mode?)
  113. else
  114. return 0xFF;
  115. }
  116. /*
  117. Write a byte to the given port.
  118. */
  119. void io_port_write(IO *io, uint8_t port, uint8_t value)
  120. {
  121. if (port <= 0x06)
  122. write_system_port(io, port, value);
  123. else if (port <= 0x3F && !(port % 2))
  124. write_memory_control(io, value);
  125. else if (port <= 0x3F)
  126. return; // TODO: Write to I/O control register
  127. else if (port <= 0x7F)
  128. psg_write(io->psg, value);
  129. else if (port <= 0xBF && !(port % 2))
  130. vdp_write_data(io->vdp, value);
  131. else if (port <= 0xBF)
  132. vdp_write_control(io->vdp, value);
  133. }