1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Mupen64plus-rsp-hle - jpeg.c *
3 * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
4 * Copyright (C) 2012 Bobby Smiles *
5 * Copyright (C) 2009 Richard Goedeken *
6 * Copyright (C) 2002 Hacktarux *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
22 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
28 #define M64P_PLUGIN_PROTOTYPES 1
29 #include "m64p_types.h"
30 #include "m64p_plugin.h"
33 #define SUBBLOCK_SIZE 64
35 typedef void (*tile_line_emitter_t)(const int16_t *y, const int16_t *u, uint32_t address);
36 typedef void (*std_macroblock_decoder_t)(int16_t *macroblock, unsigned int subblock_count, const int16_t qtables[3][SUBBLOCK_SIZE]);
38 /* rdram operations */
39 // FIXME: these functions deserve their own module
40 static void rdram_read_many_u16(uint16_t *dst, uint32_t address, unsigned int count);
41 static void rdram_write_many_u16(const uint16_t *src, uint32_t address, unsigned int count);
42 static uint32_t rdram_read_u32(uint32_t address);
43 static void rdram_write_many_u32(const uint32_t *src, uint32_t address, unsigned int count);
45 /* standard jpeg ucode decoder */
46 static void jpeg_decode_std(const char * const version, const std_macroblock_decoder_t decode_mb, const tile_line_emitter_t emit_line);
48 /* helper functions */
49 static uint8_t clamp_u8(int16_t x);
50 static int16_t clamp_s12(int16_t x);
51 static int16_t clamp_s16(int32_t x);
52 static uint16_t clamp_RGBA_component(int16_t x);
54 /* pixel conversion & foratting */
55 static uint32_t GetUYVY(int16_t y1, int16_t y2, int16_t u, int16_t v);
56 static uint16_t GetRGBA(int16_t y, int16_t u, int16_t v);
58 /* tile line emitters */
59 static void EmitYUVTileLine(const int16_t *y, const int16_t *u, uint32_t address);
60 static void EmitRGBATileLine(const int16_t *y, const int16_t *u, uint32_t address);
62 /* macroblocks operations */
63 static void DecodeMacroblock1(int16_t *macroblock, int32_t *y_dc, int32_t *u_dc, int32_t *v_dc, const int16_t *qtable);
64 static void DecodeMacroblock2(int16_t *macroblock, unsigned int subblock_count, const int16_t qtables[3][SUBBLOCK_SIZE]);
65 static void DecodeMacroblock3(int16_t *macroblock, unsigned int subblock_count, const int16_t qtables[3][SUBBLOCK_SIZE]);
66 static void EmitTilesMode0(const tile_line_emitter_t emit_line, const int16_t *macroblock, uint32_t address);
67 static void EmitTilesMode2(const tile_line_emitter_t emit_line, const int16_t *macroblock, uint32_t address);
69 /* subblocks operations */
70 static void TransposeSubBlock(int16_t *dst, const int16_t *src);
71 static void ZigZagSubBlock(int16_t *dst, const int16_t *src);
72 static void ReorderSubBlock(int16_t *dst, const int16_t *src, const unsigned int *table);
73 static void MultSubBlocks(int16_t *dst, const int16_t *src1, const int16_t *src2, unsigned int shift);
74 static void ScaleSubBlock(int16_t *dst, const int16_t *src, int16_t scale);
75 static void RShiftSubBlock(int16_t *dst, const int16_t *src, unsigned int shift);
76 static void InverseDCT1D(const float * const x, float *dst, unsigned int stride);
77 static void InverseDCTSubBlock(int16_t *dst, const int16_t *src);
78 static void RescaleYSubBlock(int16_t *dst, const int16_t *src);
79 static void RescaleUVSubBlock(int16_t *dst, const int16_t *src);
81 /* transposed dequantization table */
82 static const int16_t DEFAULT_QTABLE[SUBBLOCK_SIZE] =
84 16, 12, 14, 14, 18, 24, 49, 72,
85 11, 12, 13, 17, 22, 35, 64, 92,
86 10, 14, 16, 22, 37, 55, 78, 95,
87 16, 19, 24, 29, 56, 64, 87, 98,
88 24, 26, 40, 51, 68, 81, 103, 112,
89 40, 58, 57, 87, 109, 104, 121, 100,
90 51, 60, 69, 80, 103, 113, 120, 103,
91 61, 55, 56, 62, 77, 92, 101, 99
95 static const unsigned int ZIGZAG_TABLE[SUBBLOCK_SIZE] =
97 0, 1, 5, 6, 14, 15, 27, 28,
98 2, 4, 7, 13, 16, 26, 29, 42,
99 3, 8, 12, 17, 25, 30, 41, 43,
100 9, 11, 18, 24, 31, 40, 44, 53,
101 10, 19, 23, 32, 39, 45, 52, 54,
102 20, 22, 33, 38, 46, 51, 55, 60,
103 21, 34, 37, 47, 50, 56, 59, 61,
104 35, 36, 48, 49, 57, 58, 62, 63
107 /* transposition indices */
108 static const unsigned int TRANSPOSE_TABLE[SUBBLOCK_SIZE] =
110 0, 8, 16, 24, 32, 40, 48, 56,
111 1, 9, 17, 25, 33, 41, 49, 57,
112 2, 10, 18, 26, 34, 42, 50, 58,
113 3, 11, 19, 27, 35, 43, 51, 59,
114 4, 12, 20, 28, 36, 44, 52, 60,
115 5, 13, 21, 29, 37, 45, 53, 61,
116 6, 14, 22, 30, 38, 46, 54, 62,
117 7, 15, 23, 31, 39, 47, 55, 63
122 /* IDCT related constants
123 * Cn = alpha * cos(n * PI / 16) (alpha is chosen such as C4 = 1) */
124 static const float IDCT_C3 = 1.175875602f;
125 static const float IDCT_C6 = 0.541196100f;
126 static const float IDCT_K[10] =
128 0.765366865f, /* C2-C6 */
129 -1.847759065f, /* -C2-C6 */
130 -0.390180644f, /* C5-C3 */
131 -1.961570561f, /* -C5-C3 */
132 1.501321110f, /* C1+C3-C5-C7 */
133 2.053119869f, /* C1+C3-C5+C7 */
134 3.072711027f, /* C1+C3+C5-C7 */
135 0.298631336f, /* -C1+C3+C5-C7 */
136 -0.899976223f, /* C7-C3 */
137 -2.562915448f /* -C1-C3 */
141 /* global functions */
143 /***************************************************************************
144 * JPEG decoding ucode found in Japanese exclusive version of Pokemon Stadium.
145 **************************************************************************/
146 void jpeg_decode_PS0()
148 jpeg_decode_std("PS0", DecodeMacroblock3, EmitYUVTileLine);
151 /***************************************************************************
152 * JPEG decoding ucode found in Ocarina of Time, Pokemon Stadium 1 and
154 **************************************************************************/
155 void jpeg_decode_PS()
157 jpeg_decode_std("PS", DecodeMacroblock2, EmitRGBATileLine);
160 /***************************************************************************
161 * JPEG decoding ucode found in Ogre Battle and Bottom of the 9th.
162 **************************************************************************/
163 void jpeg_decode_OB()
165 int16_t qtable[SUBBLOCK_SIZE];
172 const OSTask_t * const task = get_task();
174 uint32_t address = task->data_ptr;
175 const unsigned int macroblock_count = task->data_size;
176 const int qscale = task->yield_data_size;
178 DebugMessage(M64MSG_VERBOSE, "jpeg_decode_OB: *buffer=%x, #MB=%d, qscale=%d",
187 ScaleSubBlock(qtable, DEFAULT_QTABLE, qscale);
191 RShiftSubBlock(qtable, DEFAULT_QTABLE, -qscale);
195 for (mb = 0; mb < macroblock_count; ++mb)
197 int16_t macroblock[6*SUBBLOCK_SIZE];
199 rdram_read_many_u16((uint16_t*)macroblock, address, 6*SUBBLOCK_SIZE);
200 DecodeMacroblock1(macroblock, &y_dc, &u_dc, &v_dc, (qscale != 0) ? qtable : NULL);
201 EmitTilesMode2(EmitYUVTileLine, macroblock, address);
203 address += (2*6*SUBBLOCK_SIZE);
208 /* local functions */
209 static void jpeg_decode_std(const char * const version, const std_macroblock_decoder_t decode_mb, const tile_line_emitter_t emit_line)
211 int16_t qtables[3][SUBBLOCK_SIZE];
214 uint32_t macroblock_count;
216 uint32_t qtableY_ptr;
217 uint32_t qtableU_ptr;
218 uint32_t qtableV_ptr;
219 unsigned int subblock_count;
220 unsigned int macroblock_size;
222 const OSTask_t * const task = get_task();
224 if (task->flags & 0x1)
226 DebugMessage(M64MSG_WARNING, "jpeg_decode_%s: task yielding not implemented", version);
230 address = rdram_read_u32(task->data_ptr);
231 macroblock_count = rdram_read_u32(task->data_ptr + 4);
232 mode = rdram_read_u32(task->data_ptr + 8);
233 qtableY_ptr = rdram_read_u32(task->data_ptr + 12);
234 qtableU_ptr = rdram_read_u32(task->data_ptr + 16);
235 qtableV_ptr = rdram_read_u32(task->data_ptr + 20);
237 DebugMessage(M64MSG_VERBOSE, "jpeg_decode_%s: *buffer=%x, #MB=%d, mode=%d, *Qy=%x, *Qu=%x, *Qv=%x",
246 if (mode != 0 && mode != 2)
248 DebugMessage(M64MSG_WARNING, "jpeg_decode_%s: invalid mode %d", version, mode);
252 subblock_count = mode + 4;
253 macroblock_size = 2*subblock_count*SUBBLOCK_SIZE;
255 rdram_read_many_u16((uint16_t*)qtables[0], qtableY_ptr, SUBBLOCK_SIZE);
256 rdram_read_many_u16((uint16_t*)qtables[1], qtableU_ptr, SUBBLOCK_SIZE);
257 rdram_read_many_u16((uint16_t*)qtables[2], qtableV_ptr, SUBBLOCK_SIZE);
259 macroblock = malloc(sizeof(*macroblock) * macroblock_size);
262 DebugMessage(M64MSG_WARNING, "jpeg_decode_%s: could not allocate macroblock", version);
266 for (mb = 0; mb < macroblock_count; ++mb)
268 rdram_read_many_u16((uint16_t*)macroblock, address, macroblock_size >> 1);
269 decode_mb(macroblock, subblock_count, (const int16_t (*)[SUBBLOCK_SIZE])qtables);
273 EmitTilesMode0(emit_line, macroblock, address);
277 EmitTilesMode2(emit_line, macroblock, address);
280 address += macroblock_size;
285 static uint8_t clamp_u8(int16_t x)
287 return (x & (0xff00)) ? ((-x) >> 15) & 0xff : x;
290 static int16_t clamp_s12(int16_t x)
292 if (x < -0x800) { x = -0x800; } else if (x > 0x7f0) { x = 0x7f0; }
296 static int16_t clamp_s16(int32_t x)
298 if (x > 32767) { x = 32767; } else if (x < -32768) { x = -32768; }
302 static uint16_t clamp_RGBA_component(int16_t x)
304 if (x > 0xff0) { x = 0xff0; } else if (x < 0) { x = 0; }
308 static uint32_t GetUYVY(int16_t y1, int16_t y2, int16_t u, int16_t v)
310 return (uint32_t)clamp_u8(u) << 24
311 | (uint32_t)clamp_u8(y1) << 16
312 | (uint32_t)clamp_u8(v) << 8
313 | (uint32_t)clamp_u8(y2);
316 static uint16_t GetRGBA(int16_t y, int16_t u, int16_t v)
318 const float fY = (float)y + 2048.0f;
319 const float fU = (float)u;
320 const float fV = (float)v;
322 const uint16_t r = clamp_RGBA_component((int16_t)(fY + 1.4025*fV));
323 const uint16_t g = clamp_RGBA_component((int16_t)(fY - 0.3443*fU - 0.7144*fV));
324 const uint16_t b = clamp_RGBA_component((int16_t)(fY + 1.7729*fU ));
326 return (r << 4) | (g >> 1) | (b >> 6) | 1;
329 static void EmitYUVTileLine(const int16_t *y, const int16_t *u, uint32_t address)
333 const int16_t * const v = u + SUBBLOCK_SIZE;
334 const int16_t * const y2 = y + SUBBLOCK_SIZE;
336 uyvy[0] = GetUYVY(y[0], y[1], u[0], v[0]);
337 uyvy[1] = GetUYVY(y[2], y[3], u[1], v[1]);
338 uyvy[2] = GetUYVY(y[4], y[5], u[2], v[2]);
339 uyvy[3] = GetUYVY(y[6], y[7], u[3], v[3]);
340 uyvy[4] = GetUYVY(y2[0], y2[1], u[4], v[4]);
341 uyvy[5] = GetUYVY(y2[2], y2[3], u[5], v[5]);
342 uyvy[6] = GetUYVY(y2[4], y2[5], u[6], v[6]);
343 uyvy[7] = GetUYVY(y2[6], y2[7], u[7], v[7]);
345 rdram_write_many_u32(uyvy, address, 8);
348 static void EmitRGBATileLine(const int16_t *y, const int16_t *u, uint32_t address)
352 const int16_t * const v = u + SUBBLOCK_SIZE;
353 const int16_t * const y2 = y + SUBBLOCK_SIZE;
355 rgba[0] = GetRGBA(y[0], u[0], v[0]);
356 rgba[1] = GetRGBA(y[1], u[0], v[0]);
357 rgba[2] = GetRGBA(y[2], u[1], v[1]);
358 rgba[3] = GetRGBA(y[3], u[1], v[1]);
359 rgba[4] = GetRGBA(y[4], u[2], v[2]);
360 rgba[5] = GetRGBA(y[5], u[2], v[2]);
361 rgba[6] = GetRGBA(y[6], u[3], v[3]);
362 rgba[7] = GetRGBA(y[7], u[3], v[3]);
363 rgba[8] = GetRGBA(y2[0], u[4], v[4]);
364 rgba[9] = GetRGBA(y2[1], u[4], v[4]);
365 rgba[10] = GetRGBA(y2[2], u[5], v[5]);
366 rgba[11] = GetRGBA(y2[3], u[5], v[5]);
367 rgba[12] = GetRGBA(y2[4], u[6], v[6]);
368 rgba[13] = GetRGBA(y2[5], u[6], v[6]);
369 rgba[14] = GetRGBA(y2[6], u[7], v[7]);
370 rgba[15] = GetRGBA(y2[7], u[7], v[7]);
372 rdram_write_many_u16(rgba, address, 16);
375 static void EmitTilesMode0(const tile_line_emitter_t emit_line, const int16_t *macroblock, uint32_t address)
379 unsigned int y_offset = 0;
380 unsigned int u_offset = 2*SUBBLOCK_SIZE;
382 for (i = 0; i < 8; ++i)
384 emit_line(¯oblock[y_offset], ¯oblock[u_offset], address);
392 static void EmitTilesMode2(const tile_line_emitter_t emit_line, const int16_t *macroblock, uint32_t address)
396 unsigned int y_offset = 0;
397 unsigned int u_offset = 4*SUBBLOCK_SIZE;
399 for (i = 0; i < 8; ++i)
401 emit_line(¯oblock[y_offset], ¯oblock[u_offset], address);
402 emit_line(¯oblock[y_offset + 8], ¯oblock[u_offset], address + 32);
404 y_offset += (i == 3) ? SUBBLOCK_SIZE+16 : 16;
410 static void DecodeMacroblock1(int16_t *macroblock, int32_t *y_dc, int32_t *u_dc, int32_t *v_dc, const int16_t *qtable)
414 for (sb = 0; sb < 6; ++sb)
416 int16_t tmp_sb[SUBBLOCK_SIZE];
419 int32_t dc = (int32_t)macroblock[0];
422 case 0: case 1: case 2: case 3:
423 *y_dc += dc; macroblock[0] = *y_dc & 0xffff; break;
424 case 4: *u_dc += dc; macroblock[0] = *u_dc & 0xffff; break;
425 case 5: *v_dc += dc; macroblock[0] = *v_dc & 0xffff; break;
428 ZigZagSubBlock(tmp_sb, macroblock);
429 if (qtable != NULL) { MultSubBlocks(tmp_sb, tmp_sb, qtable, 0); }
430 TransposeSubBlock(macroblock, tmp_sb);
431 InverseDCTSubBlock(macroblock, macroblock);
433 macroblock += SUBBLOCK_SIZE;
437 static void DecodeMacroblock2(int16_t *macroblock, unsigned int subblock_count, const int16_t qtables[3][SUBBLOCK_SIZE])
442 for (sb = 0; sb < subblock_count; ++sb)
444 int16_t tmp_sb[SUBBLOCK_SIZE];
445 const int isChromaSubBlock = (subblock_count - sb <= 2);
447 if (isChromaSubBlock) { ++q; }
449 MultSubBlocks(macroblock, macroblock, qtables[q], 4);
450 ZigZagSubBlock(tmp_sb, macroblock);
451 InverseDCTSubBlock(macroblock, tmp_sb);
453 macroblock += SUBBLOCK_SIZE;
458 static void DecodeMacroblock3(int16_t *macroblock, unsigned int subblock_count, const int16_t qtables[3][SUBBLOCK_SIZE])
463 for (sb = 0; sb < subblock_count; ++sb)
465 int16_t tmp_sb[SUBBLOCK_SIZE];
466 const int isChromaSubBlock = (subblock_count - sb <= 2);
468 if (isChromaSubBlock) { ++q; }
470 MultSubBlocks(macroblock, macroblock, qtables[q], 4);
471 ZigZagSubBlock(tmp_sb, macroblock);
472 InverseDCTSubBlock(macroblock, tmp_sb);
474 if (isChromaSubBlock)
476 RescaleUVSubBlock(macroblock, macroblock);
480 RescaleYSubBlock(macroblock, macroblock);
483 macroblock += SUBBLOCK_SIZE;
487 static void TransposeSubBlock(int16_t *dst, const int16_t *src)
489 ReorderSubBlock(dst, src, TRANSPOSE_TABLE);
492 static void ZigZagSubBlock(int16_t *dst, const int16_t *src)
494 ReorderSubBlock(dst, src, ZIGZAG_TABLE);
497 static void ReorderSubBlock(int16_t *dst, const int16_t *src, const unsigned int *table)
501 /* source and destination sublocks cannot overlap */
502 assert(abs(dst - src) > SUBBLOCK_SIZE);
504 for (i = 0; i < SUBBLOCK_SIZE; ++i)
506 dst[i] = src[table[i]];
510 static void MultSubBlocks(int16_t *dst, const int16_t *src1, const int16_t *src2, unsigned int shift)
514 for (i = 0; i < SUBBLOCK_SIZE; ++i)
516 int32_t v = src1[i] * src2[i];
517 dst[i] = clamp_s16(v) << shift;
521 static void ScaleSubBlock(int16_t *dst, const int16_t *src, int16_t scale)
525 for (i = 0; i < SUBBLOCK_SIZE; ++i)
527 int32_t v = src[i] * scale;
528 dst[i] = clamp_s16(v);
532 static void RShiftSubBlock(int16_t *dst, const int16_t *src, unsigned int shift)
536 for (i = 0; i < SUBBLOCK_SIZE; ++i)
538 dst[i] = src[i] >> shift;
542 /***************************************************************************
543 * Fast 2D IDCT using separable formulation and normalization
544 * Computations use single precision floats
545 * Implementation based on Wikipedia :
546 * http://fr.wikipedia.org/wiki/Transform%C3%A9e_en_cosinus_discr%C3%A8te
547 **************************************************************************/
548 static void InverseDCT1D(const float * const x, float *dst, unsigned int stride)
552 float x26, x1357, x15, x37, x17, x35;
554 x15 = IDCT_K[2] * (x[1] + x[5]);
555 x37 = IDCT_K[3] * (x[3] + x[7]);
556 x17 = IDCT_K[8] * (x[1] + x[7]);
557 x35 = IDCT_K[9] * (x[3] + x[5]);
558 x1357 = IDCT_C3 * (x[1] + x[3] + x[5] + x[7]);
559 x26 = IDCT_C6 * (x[2] + x[6]);
563 f[2] = x26 + IDCT_K[0]*x[2];
564 f[3] = x26 + IDCT_K[1]*x[6];
566 e[0] = x1357 + x15 + IDCT_K[4]*x[1] + x17;
567 e[1] = x1357 + x37 + IDCT_K[6]*x[3] + x35;
568 e[2] = x1357 + x15 + IDCT_K[5]*x[5] + x35;
569 e[3] = x1357 + x37 + IDCT_K[7]*x[7] + x17;
571 *dst = f[0] + f[2] + e[0]; dst += stride;
572 *dst = f[1] + f[3] + e[1]; dst += stride;
573 *dst = f[1] - f[3] + e[2]; dst += stride;
574 *dst = f[0] - f[2] + e[3]; dst += stride;
575 *dst = f[0] - f[2] - e[3]; dst += stride;
576 *dst = f[1] - f[3] - e[2]; dst += stride;
577 *dst = f[1] + f[3] - e[1]; dst += stride;
578 *dst = f[0] + f[2] - e[0]; dst += stride;
581 static void InverseDCTSubBlock(int16_t *dst, const int16_t *src)
584 float block[SUBBLOCK_SIZE];
587 /* idct 1d on rows (+transposition) */
588 for (i = 0; i < 8; ++i)
590 for (j = 0; j < 8; ++j)
592 x[j] = (float)src[i*8+j];
595 InverseDCT1D(x, &block[i], 8);
598 /* idct 1d on columns (thanks to previous transposition) */
599 for (i = 0; i < 8; ++i)
601 InverseDCT1D(&block[i*8], x, 1);
603 /* C4 = 1 normalization implies a division by 8 */
604 for (j = 0; j < 8; ++j)
606 dst[i+j*8] = (int16_t)x[j] >> 3;
611 static void RescaleYSubBlock(int16_t *dst, const int16_t *src)
615 for (i = 0; i < SUBBLOCK_SIZE; ++i)
617 dst[i] = (((uint32_t)(clamp_s12(src[i]) + 0x800) * 0xdb0) >> 16) + 0x10;
621 static void RescaleUVSubBlock(int16_t *dst, const int16_t *src)
625 for (i = 0; i < SUBBLOCK_SIZE; ++i)
627 dst[i] = (((int)clamp_s12(src[i]) * 0xe00) >> 16) + 0x80;
633 /* FIXME: assume presence of expansion pack */
634 #define MEMMASK 0x7fffff
636 static void rdram_read_many_u16(uint16_t *dst, uint32_t address, unsigned int count)
640 uint16_t s = rsp.RDRAM[((address++)^S8) & MEMMASK];
642 s |= rsp.RDRAM[((address++)^S8) & MEMMASK];
650 static void rdram_write_many_u16(const uint16_t *src, uint32_t address, unsigned int count)
654 rsp.RDRAM[((address++)^S8) & MEMMASK] = (uint8_t)(*src >> 8);
655 rsp.RDRAM[((address++)^S8) & MEMMASK] = (uint8_t)(*(src++) & 0xff);
661 static uint32_t rdram_read_u32(uint32_t address)
663 uint32_t r = rsp.RDRAM[((address++) ^ S8) & MEMMASK]; r <<= 8;
664 r |= rsp.RDRAM[((address++) ^ S8) & MEMMASK]; r <<= 8;
665 r |= rsp.RDRAM[((address++) ^ S8) & MEMMASK]; r <<= 8;
666 r |= rsp.RDRAM[((address++) ^ S8) & MEMMASK];
671 static void rdram_write_many_u32(const uint32_t *src, uint32_t address, unsigned int count)
675 rsp.RDRAM[((address++)^S8) & MEMMASK] = (uint8_t)(*src >> 24);
676 rsp.RDRAM[((address++)^S8) & MEMMASK] = (uint8_t)(*src >> 16);
677 rsp.RDRAM[((address++)^S8) & MEMMASK] = (uint8_t)(*src >> 8);
678 rsp.RDRAM[((address++)^S8) & MEMMASK] = (uint8_t)(*(src++) & 0xff);