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.
 
 
 
 
 

137 lines
3.0 KiB

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