dsp2_op.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #ifdef DSP2_CPP
  2. //convert bitmap to bitplane tile
  3. void DSP2::op01() {
  4. //op01 size is always 32 bytes input and output
  5. //the hardware does strange things if you vary the size
  6. unsigned char c0, c1, c2, c3;
  7. unsigned char *p1 = status.parameters;
  8. unsigned char *p2a = status.output;
  9. unsigned char *p2b = status.output + 16; //halfway
  10. //process 8 blocks of 4 bytes each
  11. for(int j = 0; j < 8; j++) {
  12. c0 = *p1++;
  13. c1 = *p1++;
  14. c2 = *p1++;
  15. c3 = *p1++;
  16. *p2a++ = (c0 & 0x10) << 3 |
  17. (c0 & 0x01) << 6 |
  18. (c1 & 0x10) << 1 |
  19. (c1 & 0x01) << 4 |
  20. (c2 & 0x10) >> 1 |
  21. (c2 & 0x01) << 2 |
  22. (c3 & 0x10) >> 3 |
  23. (c3 & 0x01);
  24. *p2a++ = (c0 & 0x20) << 2 |
  25. (c0 & 0x02) << 5 |
  26. (c1 & 0x20) |
  27. (c1 & 0x02) << 3 |
  28. (c2 & 0x20) >> 2 |
  29. (c2 & 0x02) << 1 |
  30. (c3 & 0x20) >> 4 |
  31. (c3 & 0x02) >> 1;
  32. *p2b++ = (c0 & 0x40) << 1 |
  33. (c0 & 0x04) << 4 |
  34. (c1 & 0x40) >> 1 |
  35. (c1 & 0x04) << 2 |
  36. (c2 & 0x40) >> 3 |
  37. (c2 & 0x04) |
  38. (c3 & 0x40) >> 5 |
  39. (c3 & 0x04) >> 2;
  40. *p2b++ = (c0 & 0x80) |
  41. (c0 & 0x08) << 3 |
  42. (c1 & 0x80) >> 2 |
  43. (c1 & 0x08) << 1 |
  44. (c2 & 0x80) >> 4 |
  45. (c2 & 0x08) >> 1 |
  46. (c3 & 0x80) >> 6 |
  47. (c3 & 0x08) >> 3;
  48. }
  49. }
  50. //set transparent color
  51. void DSP2::op03() {
  52. status.op05transparent = status.parameters[0];
  53. }
  54. //replace bitmap using transparent color
  55. void DSP2::op05() {
  56. uint8 color;
  57. // Overlay bitmap with transparency.
  58. // Input:
  59. //
  60. // Bitmap 1: i[0] <=> i[size-1]
  61. // Bitmap 2: i[size] <=> i[2*size-1]
  62. //
  63. // Output:
  64. //
  65. // Bitmap 3: o[0] <=> o[size-1]
  66. //
  67. // Processing:
  68. //
  69. // Process all 4-bit pixels (nibbles) in the bitmap
  70. //
  71. // if ( BM2_pixel == transparent_color )
  72. // pixelout = BM1_pixel
  73. // else
  74. // pixelout = BM2_pixel
  75. // The max size bitmap is limited to 255 because the size parameter is a byte
  76. // I think size=0 is an error. The behavior of the chip on size=0 is to
  77. // return the last value written to DR if you read DR on Op05 with
  78. // size = 0. I don't think it's worth implementing this quirk unless it's
  79. // proven necessary.
  80. unsigned char c1, c2;
  81. unsigned char *p1 = status.parameters;
  82. unsigned char *p2 = status.parameters + status.op05len;
  83. unsigned char *p3 = status.output;
  84. color = status.op05transparent & 0x0f;
  85. for(int n = 0; n < status.op05len; n++) {
  86. c1 = *p1++;
  87. c2 = *p2++;
  88. *p3++ = ( ((c2 >> 4) == color ) ? c1 & 0xf0 : c2 & 0xf0 ) |
  89. ( ((c2 & 0x0f) == color ) ? c1 & 0x0f : c2 & 0x0f );
  90. }
  91. }
  92. //reverse bitmap
  93. void DSP2::op06() {
  94. // Input:
  95. // size
  96. // bitmap
  97. int i, j;
  98. for(i = 0, j = status.op06len - 1; i < status.op06len; i++, j--) {
  99. status.output[j] = (status.parameters[i] << 4) | (status.parameters[i] >> 4);
  100. }
  101. }
  102. //multiply
  103. void DSP2::op09() {
  104. status.out_count = 4;
  105. status.op09word1 = status.parameters[0] | (status.parameters[1] << 8);
  106. status.op09word2 = status.parameters[2] | (status.parameters[3] << 8);
  107. uint32 r;
  108. r = status.op09word1 * status.op09word2;
  109. status.output[0] = r;
  110. status.output[1] = r >> 8;
  111. status.output[2] = r >> 16;
  112. status.output[3] = r >> 24;
  113. }
  114. //scale bitmap
  115. void DSP2::op0d() {
  116. // Bit accurate hardware algorithm - uses fixed point math
  117. // This should match the DSP2 Op0D output exactly
  118. // I wouldn't recommend using this unless you're doing hardware debug.
  119. // In some situations it has small visual artifacts that
  120. // are not readily apparent on a TV screen but show up clearly
  121. // on a monitor. Use Overload's scaling instead.
  122. // This is for hardware verification testing.
  123. //
  124. // One note: the HW can do odd byte scaling but since we divide
  125. // by two to get the count of bytes this won't work well for
  126. // odd byte scaling (in any of the current algorithm implementations).
  127. // So far I haven't seen Dungeon Master use it.
  128. // If it does we can adjust the parameters and code to work with it
  129. uint32 multiplier; // Any size int >= 32-bits
  130. uint32 pixloc; // match size of multiplier
  131. int i, j;
  132. uint8 pixelarray[512];
  133. if(status.op0dinlen <= status.op0doutlen) {
  134. multiplier = 0x10000; // In our self defined fixed point 0x10000 == 1
  135. } else {
  136. multiplier = (status.op0dinlen << 17) / ((status.op0doutlen << 1) + 1);
  137. }
  138. pixloc = 0;
  139. for(i = 0; i < status.op0doutlen * 2; i++) {
  140. j = pixloc >> 16;
  141. if(j & 1) {
  142. pixelarray[i] = (status.parameters[j >> 1] & 0x0f);
  143. } else {
  144. pixelarray[i] = (status.parameters[j >> 1] & 0xf0) >> 4;
  145. }
  146. pixloc += multiplier;
  147. }
  148. for(i = 0; i < status.op0doutlen; i++) {
  149. status.output[i] = (pixelarray[i << 1] << 4) | pixelarray[(i << 1) + 1];
  150. }
  151. }
  152. #endif