DisplayMode.hh 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. #ifndef DISPLAYMODE_HH
  2. #define DISPLAYMODE_HH
  3. #include "openmsx.hh"
  4. #include "one_of.hh"
  5. namespace openmsx {
  6. /** Represents a VDP display mode.
  7. * A display mode determines how bytes in the VRAM are converted to pixel
  8. * colors.
  9. * A display mode consists of a base mode with YJK filters on top.
  10. * Only the V9958 supports YJK filters.
  11. */
  12. class DisplayMode
  13. {
  14. private:
  15. constexpr explicit DisplayMode(byte mode_) : mode(mode_) {}
  16. /** Display mode flags: YAE YJK M5..M1.
  17. * The YAE flag indicates whether YAE is active, not just the value of
  18. * the corresponding mode bit; so if YJK is 0, YAE is 0 as well.
  19. */
  20. byte mode = 0;
  21. public:
  22. enum {
  23. GRAPHIC1 = 0x00, // Graphic 1
  24. TEXT1 = 0x01, // Text 1
  25. MULTICOLOR = 0x02, // Multicolor
  26. GRAPHIC2 = 0x04, // Graphic 2
  27. TEXT1Q = 0x05, // !!
  28. MULTIQ = 0x06, // !!
  29. GRAPHIC3 = 0x08, // Graphic 3
  30. TEXT2 = 0x09, // Text 2
  31. GRAPHIC4 = 0x0C, // Graphic 4
  32. GRAPHIC5 = 0x10, // Graphic 5
  33. GRAPHIC6 = 0x14, // Graphic 6
  34. GRAPHIC7 = 0x1C // Graphic 7
  35. };
  36. /** Bits of VDP register 0 that encode part of the display mode. */
  37. static constexpr byte REG0_MASK = 0x0E;
  38. /** Bits of VDP register 1 that encode part of the display mode. */
  39. static constexpr byte REG1_MASK = 0x18;
  40. /** Bits of VDP register 25 that encode part of the display mode. */
  41. static constexpr byte REG25_MASK = 0x18;
  42. /** Encoding of YJK flag. */
  43. static constexpr byte YJK = 0x20;
  44. /** Encoding of YAE flag. */
  45. static constexpr byte YAE = 0x40;
  46. /** Create the initial display mode.
  47. */
  48. constexpr DisplayMode() = default;
  49. /** Create a specific display mode.
  50. * @param reg0 The contents of VDP register 0.
  51. * @param reg1 The contents of VDP register 1.
  52. * @param reg25 The contents of VDP register 25;
  53. * on non-V9958 chips, pass 0.
  54. */
  55. constexpr DisplayMode(byte reg0, byte reg1, byte reg25) {
  56. if ((reg25 & 0x08) == 0) reg25 = 0; // If YJK is off, ignore YAE.
  57. mode = ((reg25 & 0x18) << 2) // YAE YJK
  58. | ((reg0 & 0x0E) << 1) // M5..M3
  59. | ((reg1 & 0x08) >> 2) // M2
  60. | ((reg1 & 0x10) >> 4); // M1
  61. }
  62. constexpr DisplayMode updateReg25(byte reg25) const {
  63. if ((reg25 & 0x08) == 0) reg25 = 0; // If YJK is off, ignore YAE.
  64. return DisplayMode(getBase() | ((reg25 & 0x18) << 2));
  65. }
  66. /** Bring the display mode to its initial state.
  67. */
  68. constexpr void reset() {
  69. *this = DisplayMode();
  70. }
  71. /** Equals operator.
  72. */
  73. constexpr bool operator==(const DisplayMode& otherMode) const {
  74. return mode == otherMode.mode;
  75. }
  76. /** Does-not-equal operator.
  77. */
  78. constexpr bool operator!=(const DisplayMode& otherMode) const {
  79. return mode != otherMode.mode;
  80. }
  81. /** Get the dispay mode as a byte: YAE YJK M5..M1 combined.
  82. * @return The byte representation of this display mode,
  83. * in the range [0..0x7F].
  84. */
  85. constexpr byte getByte() const {
  86. return mode;
  87. }
  88. /** Used for de-serialization. */
  89. constexpr void setByte(byte mode_) {
  90. mode = mode_;
  91. }
  92. /** Get the base dispay mode as an integer: M5..M1 combined.
  93. * If YJK is active, the base mode is the underlying display mode.
  94. * @return The integer representation of the base of this display mode,
  95. * in the range [0..0x1F].
  96. */
  97. constexpr byte getBase() const {
  98. return mode & 0x1F;
  99. }
  100. /** Was this mode introduced by the V9938?
  101. * @return True iff the base of this mode only is available on V9938/58.
  102. */
  103. constexpr bool isV9938Mode() const {
  104. return (mode & 0x18) != 0;
  105. }
  106. /** Is the current mode a text mode?
  107. * Text1 and Text2 are text modes.
  108. * @return True iff the current mode is a text mode.
  109. */
  110. constexpr bool isTextMode() const {
  111. return getBase() == one_of(TEXT1, TEXT2, TEXT1Q);
  112. }
  113. /** Is the current mode a bitmap mode?
  114. * Graphic4 and higher are bitmap modes.
  115. * @return True iff the current mode is a bitmap mode.
  116. */
  117. constexpr bool isBitmapMode() const {
  118. return getBase() >= 0x0C;
  119. }
  120. /** Is VRAM "planar" in the current display mode?
  121. * Graphic 6 and 7 spread their bytes over two VRAM ICs,
  122. * such that the even bytes go to the first half of the address
  123. * space and the odd bytes to the second half.
  124. * @return True iff the current display mode has planar VRAM.
  125. */
  126. constexpr bool isPlanar() const {
  127. // TODO: Is the display mode check OK? Profile undefined modes.
  128. return (mode & 0x14) == 0x14;
  129. }
  130. /** Are sprite pixels narrow?
  131. */
  132. constexpr bool isSpriteNarrow() const {
  133. // TODO: Check what happens to sprites in Graphic5 + YJK/YAE.
  134. return mode == GRAPHIC5;
  135. }
  136. /** Get the sprite mode of this display mode.
  137. * @return The current sprite mode:
  138. * 0 means no sprites,
  139. * 1 means sprite mode 1 (MSX1 display modes),
  140. * 2 means sprite mode 2 (MSX2 display modes).
  141. */
  142. constexpr int getSpriteMode(bool isMSX1) const {
  143. switch (getBase()) {
  144. case GRAPHIC1: case MULTICOLOR: case GRAPHIC2:
  145. return 1;
  146. case MULTIQ: // depends on VDP type
  147. return isMSX1 ? 1 : 0;
  148. case GRAPHIC3: case GRAPHIC4: case GRAPHIC5:
  149. case GRAPHIC6: case GRAPHIC7:
  150. return 2;
  151. case TEXT1: case TEXT1Q: case TEXT2:
  152. default: // and all other (bogus) modes
  153. // Verified on real V9958: none of the bogus modes
  154. // show sprites.
  155. // TODO check on TMSxxxx
  156. return 0;
  157. }
  158. }
  159. /** Get number of pixels on a display line in this mode.
  160. * @return 512 for Text 2, Graphic 5 and 6, 256 for all other modes.
  161. * TODO: Would it make more sense to treat Text 2 as 480 pixels?
  162. */
  163. constexpr unsigned getLineWidth() const {
  164. // Note: Testing "mode" instead of "base mode" ensures that YJK
  165. // modes are treated as 256 pixels wide.
  166. return mode == one_of(TEXT2, GRAPHIC5, GRAPHIC6)
  167. ? 512
  168. : 256;
  169. }
  170. };
  171. } // namespace openmsx
  172. #endif