1 // license:BSD-3-Clause
2 // copyright-holders:smf
3 /*
4 * PlayStation Motion Decoder emulator
5 *
6 * Copyright 2003-2011 smf
7 *
8 * Thanks to Oliver Galibert for help figuring out IDCT
9 *
10 */
11
12 #include "emu.h"
13 #include "mdec.h"
14 #include "dma.h"
15
16 #define VERBOSE_LEVEL ( 0 )
17
verboselog(device_t & device,int n_level,const char * s_fmt,...)18 static inline void ATTR_PRINTF(3,4) verboselog( device_t& device, int n_level, const char *s_fmt, ... )
19 {
20 if( VERBOSE_LEVEL >= n_level )
21 {
22 va_list v;
23 char buf[ 32768 ];
24 va_start( v, s_fmt );
25 vsprintf( buf, s_fmt, v );
26 va_end( v );
27 device.logerror( "%s: %s", device.machine().describe_context(), buf );
28 }
29 }
30
31 DEFINE_DEVICE_TYPE(PSX_MDEC, psxmdec_device, "psxmdec", "Sony PSX MDEC")
32
psxmdec_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)33 psxmdec_device::psxmdec_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
34 : device_t(mconfig, PSX_MDEC, tag, owner, clock), n_decoded(0), n_offset(0), n_0_command(0), n_0_address(0), n_0_size(0), n_1_command(0), n_1_status(0)
35 {
36 }
37
device_reset()38 void psxmdec_device::device_reset()
39 {
40 n_0_command = 0;
41 n_0_address = 0;
42 n_0_size = 0;
43 n_1_command = 0;
44 n_1_status = 0;
45 n_offset = 0;
46 n_decoded = 0;
47 }
48
device_post_load()49 void psxmdec_device::device_post_load()
50 {
51 mdec_cos_precalc();
52 }
53
device_start()54 void psxmdec_device::device_start()
55 {
56 for( int n = 0; n < 256; n++ )
57 {
58 p_n_clamp8[ n ] = 0;
59 p_n_clamp8[ n + 256 ] = n;
60 p_n_clamp8[ n + 512 ] = 255;
61
62 p_n_r5[ n ] = 0;
63 p_n_r5[ n + 256 ] = ( n >> 3 );
64 p_n_r5[ n + 512 ] = ( 255 >> 3 );
65
66 p_n_g5[ n ] = 0;
67 p_n_g5[ n + 256 ] = ( n >> 3 ) << 5;
68 p_n_g5[ n + 512 ] = ( 255 >> 3 ) << 5;
69
70 p_n_b5[ n ] = 0;
71 p_n_b5[ n + 256 ] = ( n >> 3 ) << 10;
72 p_n_b5[ n + 512 ] = ( 255 >> 3 ) << 10;
73 }
74
75 save_item( NAME( n_0_command ) );
76 save_item( NAME( n_0_address ) );
77 save_item( NAME( n_0_size ) );
78 save_item( NAME( n_1_command ) );
79 save_item( NAME( n_1_status ) );
80 save_item( NAME( p_n_quantize_y ) );
81 save_item( NAME( p_n_quantize_uv ) );
82 save_item( NAME( p_n_cos ) );
83 }
84
85 #ifdef UNUSED_FUNCTION
psxwriteword(uint32_t * p_n_psxram,uint32_t n_address,uint16_t n_data)86 static inline void psxwriteword( uint32_t *p_n_psxram, uint32_t n_address, uint16_t n_data )
87 {
88 *( (uint16_t *)( (uint8_t *)p_n_psxram + WORD_XOR_LE( n_address ) ) ) = n_data;
89 }
90 #endif
91
psxreadword(uint32_t * p_n_psxram,uint32_t n_address)92 static inline uint16_t psxreadword( uint32_t *p_n_psxram, uint32_t n_address )
93 {
94 return *( (uint16_t *)( (uint8_t *)p_n_psxram + WORD_XOR_LE( n_address ) ) );
95 }
96
97 const uint32_t psxmdec_device::m_p_n_mdec_zigzag[ DCTSIZE2 ] =
98 {
99 0, 1, 8, 16, 9, 2, 3, 10,
100 17, 24, 32, 25, 18, 11, 4, 5,
101 12, 19, 26, 33, 40, 48, 41, 34,
102 27, 20, 13, 6, 7, 14, 21, 28,
103 35, 42, 49, 56, 57, 50, 43, 36,
104 29, 22, 15, 23, 30, 37, 44, 51,
105 58, 59, 52, 45, 38, 31, 39, 46,
106 53, 60, 61, 54, 47, 55, 62, 63
107 };
108
mdec_cos_precalc()109 void psxmdec_device::mdec_cos_precalc()
110 {
111 uint32_t n_x;
112 uint32_t n_y;
113 uint32_t n_u;
114 uint32_t n_v;
115 int32_t *p_n_precalc = p_n_cos_precalc;
116
117 for( n_y = 0; n_y < 8; n_y++ )
118 {
119 for( n_x = 0; n_x < 8; n_x++ )
120 {
121 for( n_v = 0; n_v < 8; n_v++ )
122 {
123 for( n_u = 0; n_u < 8; n_u++ )
124 {
125 *( p_n_precalc++ ) =
126 ( ( p_n_cos[ ( n_u * 8 ) + n_x ] *
127 p_n_cos[ ( n_v * 8 ) + n_y ] ) >> ( 30 - MDEC_COS_PRECALC_BITS ) );
128 }
129 }
130 }
131 }
132 }
133
mdec_idct(int32_t * p_n_src,int32_t * p_n_dst)134 void psxmdec_device::mdec_idct( int32_t *p_n_src, int32_t *p_n_dst )
135 {
136 int32_t *p_n_precalc = p_n_cos_precalc;
137
138 for( uint32_t n_yx = 0; n_yx < DCTSIZE2; n_yx++ )
139 {
140 int32_t p_n_z[ 8 ];
141 int32_t *p_n_data = p_n_src;
142
143 memset( p_n_z, 0, sizeof( p_n_z ) );
144
145 for( uint32_t n_vu = 0; n_vu < DCTSIZE2 / 8; n_vu++ )
146 {
147 p_n_z[ 0 ] += p_n_data[ 0 ] * p_n_precalc[ 0 ];
148 p_n_z[ 1 ] += p_n_data[ 1 ] * p_n_precalc[ 1 ];
149 p_n_z[ 2 ] += p_n_data[ 2 ] * p_n_precalc[ 2 ];
150 p_n_z[ 3 ] += p_n_data[ 3 ] * p_n_precalc[ 3 ];
151 p_n_z[ 4 ] += p_n_data[ 4 ] * p_n_precalc[ 4 ];
152 p_n_z[ 5 ] += p_n_data[ 5 ] * p_n_precalc[ 5 ];
153 p_n_z[ 6 ] += p_n_data[ 6 ] * p_n_precalc[ 6 ];
154 p_n_z[ 7 ] += p_n_data[ 7 ] * p_n_precalc[ 7 ];
155 p_n_data += 8;
156 p_n_precalc += 8;
157 }
158
159 *( p_n_dst++ ) = ( p_n_z[ 0 ] + p_n_z[ 1 ] + p_n_z[ 2 ] + p_n_z[ 3 ] +
160 p_n_z[ 4 ] + p_n_z[ 5 ] + p_n_z[ 6 ] + p_n_z[ 7 ] ) >> ( MDEC_COS_PRECALC_BITS + 2 );
161 }
162 }
163
mdec_unpack_run(uint16_t n_packed)164 static inline uint16_t mdec_unpack_run( uint16_t n_packed )
165 {
166 return n_packed >> 10;
167 }
168
mdec_unpack_val(uint16_t n_packed)169 static inline int32_t mdec_unpack_val( uint16_t n_packed )
170 {
171 return ( ( (int32_t)n_packed ) << 22 ) >> 22;
172 }
173
mdec_unpack(uint32_t * p_n_psxram,uint32_t n_address)174 uint32_t psxmdec_device::mdec_unpack( uint32_t *p_n_psxram, uint32_t n_address )
175 {
176 uint8_t n_z;
177 int32_t n_qscale;
178 uint16_t n_packed;
179 int32_t *p_n_block;
180 int32_t p_n_unpacked[ 64 ];
181 int32_t *p_n_q;
182
183 p_n_q = p_n_quantize_uv;
184 p_n_block = m_p_n_unpacked;
185
186 for( uint32_t n_block = 0; n_block < 6; n_block++ )
187 {
188 memset( p_n_unpacked, 0, sizeof( p_n_unpacked ) );
189
190 if( n_block == 2 )
191 {
192 p_n_q = p_n_quantize_y;
193 }
194 n_packed = psxreadword( p_n_psxram, n_address );
195 n_address += 2;
196 if( n_packed == 0xfe00 )
197 {
198 break;
199 }
200
201 n_qscale = mdec_unpack_run( n_packed );
202 p_n_unpacked[ 0 ] = mdec_unpack_val( n_packed ) * p_n_q[ 0 ];
203
204 n_z = 0;
205 for( ;; )
206 {
207 n_packed = psxreadword( p_n_psxram, n_address );
208 n_address += 2;
209
210 if( n_packed == 0xfe00 )
211 {
212 break;
213 }
214 n_z += mdec_unpack_run( n_packed ) + 1;
215 if( n_z > 63 )
216 {
217 break;
218 }
219 p_n_unpacked[ m_p_n_mdec_zigzag[ n_z ] ] = ( mdec_unpack_val( n_packed ) * p_n_q[ n_z ] * n_qscale ) / 8;
220 }
221 mdec_idct( p_n_unpacked, p_n_block );
222 p_n_block += DCTSIZE2;
223 }
224 return n_address;
225 }
226
mdec_cr_to_r(int32_t n_cr)227 static inline int32_t mdec_cr_to_r( int32_t n_cr )
228 {
229 return ( 1435 * n_cr ) >> 10;
230 }
231
mdec_cr_to_g(int32_t n_cr)232 static inline int32_t mdec_cr_to_g( int32_t n_cr )
233 {
234 return ( -731 * n_cr ) >> 10;
235 }
236
mdec_cb_to_g(int32_t n_cb)237 static inline int32_t mdec_cb_to_g( int32_t n_cb )
238 {
239 return ( -351 * n_cb ) >> 10;
240 }
241
mdec_cb_to_b(int32_t n_cb)242 static inline int32_t mdec_cb_to_b( int32_t n_cb )
243 {
244 return ( 1814 * n_cb ) >> 10;
245 }
246
mdec_clamp_r5(int32_t n_r) const247 uint16_t psxmdec_device::mdec_clamp_r5( int32_t n_r ) const
248 {
249 return p_n_r5[ n_r + 128 + 256 ];
250 }
251
mdec_clamp_g5(int32_t n_g) const252 uint16_t psxmdec_device::mdec_clamp_g5( int32_t n_g ) const
253 {
254 return p_n_g5[ n_g + 128 + 256 ];
255 }
256
mdec_clamp_b5(int32_t n_b) const257 uint16_t psxmdec_device::mdec_clamp_b5( int32_t n_b ) const
258 {
259 return p_n_b5[ n_b + 128 + 256 ];
260 }
261
mdec_makergb15(uint32_t n_address,int32_t n_r,int32_t n_g,int32_t n_b,int32_t * p_n_y,uint16_t n_stp)262 void psxmdec_device::mdec_makergb15( uint32_t n_address, int32_t n_r, int32_t n_g, int32_t n_b, int32_t *p_n_y, uint16_t n_stp )
263 {
264 p_n_output[ WORD_XOR_LE( n_address + 0 ) / 2 ] = n_stp |
265 mdec_clamp_r5( p_n_y[ 0 ] + n_r ) |
266 mdec_clamp_g5( p_n_y[ 0 ] + n_g ) |
267 mdec_clamp_b5( p_n_y[ 0 ] + n_b );
268
269 p_n_output[ WORD_XOR_LE( n_address + 2 ) / 2 ] = n_stp |
270 mdec_clamp_r5( p_n_y[ 1 ] + n_r ) |
271 mdec_clamp_g5( p_n_y[ 1 ] + n_g ) |
272 mdec_clamp_b5( p_n_y[ 1 ] + n_b );
273 }
274
mdec_yuv2_to_rgb15(void)275 void psxmdec_device::mdec_yuv2_to_rgb15( void )
276 {
277 int32_t n_r;
278 int32_t n_g;
279 int32_t n_b;
280 int32_t n_cb;
281 int32_t n_cr;
282 int32_t *p_n_cb;
283 int32_t *p_n_cr;
284 int32_t *p_n_y;
285 uint32_t n_x;
286 uint32_t n_y;
287 uint32_t n_z;
288 uint16_t n_stp;
289 int n_address = 0;
290
291 if( ( n_0_command & ( 1L << 25 ) ) != 0 )
292 {
293 n_stp = 0x8000;
294 }
295 else
296 {
297 n_stp = 0x0000;
298 }
299
300 p_n_cr = &m_p_n_unpacked[ 0 ];
301 p_n_cb = &m_p_n_unpacked[ DCTSIZE2 ];
302 p_n_y = &m_p_n_unpacked[ DCTSIZE2 * 2 ];
303
304 for( n_z = 0; n_z < 2; n_z++ )
305 {
306 for( n_y = 0; n_y < 4; n_y++ )
307 {
308 for( n_x = 0; n_x < 4; n_x++ )
309 {
310 n_cr = *( p_n_cr );
311 n_cb = *( p_n_cb );
312 n_r = mdec_cr_to_r( n_cr );
313 n_g = mdec_cr_to_g( n_cr ) + mdec_cb_to_g( n_cb );
314 n_b = mdec_cb_to_b( n_cb );
315
316 mdec_makergb15( ( n_address + 0 ), n_r, n_g, n_b, p_n_y, n_stp );
317 mdec_makergb15( ( n_address + 32 ), n_r, n_g, n_b, p_n_y + 8, n_stp );
318
319 n_cr = *( p_n_cr + 4 );
320 n_cb = *( p_n_cb + 4 );
321 n_r = mdec_cr_to_r( n_cr );
322 n_g = mdec_cr_to_g( n_cr ) + mdec_cb_to_g( n_cb );
323 n_b = mdec_cb_to_b( n_cb );
324
325 mdec_makergb15( ( n_address + 16 ), n_r, n_g, n_b, p_n_y + DCTSIZE2, n_stp );
326 mdec_makergb15( ( n_address + 48 ), n_r, n_g, n_b, p_n_y + DCTSIZE2 + 8, n_stp );
327
328 p_n_cr++;
329 p_n_cb++;
330 p_n_y += 2;
331 n_address += 4;
332 }
333 p_n_cr += 4;
334 p_n_cb += 4;
335 p_n_y += 8;
336 n_address += 48;
337 }
338 p_n_y += DCTSIZE2;
339 }
340 n_decoded = ( 16 * 16 ) / 2;
341 }
342
mdec_clamp8(int32_t n_r) const343 uint16_t psxmdec_device::mdec_clamp8( int32_t n_r ) const
344 {
345 return p_n_clamp8[ n_r + 128 + 256 ];
346 }
347
mdec_makergb24(uint32_t n_address,int32_t n_r,int32_t n_g,int32_t n_b,int32_t * p_n_y,uint32_t n_stp)348 void psxmdec_device::mdec_makergb24( uint32_t n_address, int32_t n_r, int32_t n_g, int32_t n_b, int32_t *p_n_y, uint32_t n_stp )
349 {
350 p_n_output[ WORD_XOR_LE( n_address + 0 ) / 2 ] = ( mdec_clamp8( p_n_y[ 0 ] + n_g ) << 8 ) | mdec_clamp8( p_n_y[ 0 ] + n_r );
351 p_n_output[ WORD_XOR_LE( n_address + 2 ) / 2 ] = ( mdec_clamp8( p_n_y[ 1 ] + n_r ) << 8 ) | mdec_clamp8( p_n_y[ 0 ] + n_b );
352 p_n_output[ WORD_XOR_LE( n_address + 4 ) / 2 ] = ( mdec_clamp8( p_n_y[ 1 ] + n_b ) << 8 ) | mdec_clamp8( p_n_y[ 1 ] + n_g );
353 }
354
mdec_yuv2_to_rgb24(void)355 void psxmdec_device::mdec_yuv2_to_rgb24( void )
356 {
357 int32_t n_r;
358 int32_t n_g;
359 int32_t n_b;
360 int32_t n_cb;
361 int32_t n_cr;
362 int32_t *p_n_cb;
363 int32_t *p_n_cr;
364 int32_t *p_n_y;
365 uint32_t n_x;
366 uint32_t n_y;
367 uint32_t n_z;
368 uint32_t n_stp;
369 int n_address = 0;
370
371 if( ( n_0_command & ( 1L << 25 ) ) != 0 )
372 {
373 n_stp = 0x80008000;
374 }
375 else
376 {
377 n_stp = 0x00000000;
378 }
379
380 p_n_cr = &m_p_n_unpacked[ 0 ];
381 p_n_cb = &m_p_n_unpacked[ DCTSIZE2 ];
382 p_n_y = &m_p_n_unpacked[ DCTSIZE2 * 2 ];
383
384 for( n_z = 0; n_z < 2; n_z++ )
385 {
386 for( n_y = 0; n_y < 4; n_y++ )
387 {
388 for( n_x = 0; n_x < 4; n_x++ )
389 {
390 n_cr = *( p_n_cr );
391 n_cb = *( p_n_cb );
392 n_r = mdec_cr_to_r( n_cr );
393 n_g = mdec_cr_to_g( n_cr ) + mdec_cb_to_g( n_cb );
394 n_b = mdec_cb_to_b( n_cb );
395
396 mdec_makergb24( ( n_address + 0 ), n_r, n_g, n_b, p_n_y, n_stp );
397 mdec_makergb24( ( n_address + 48 ), n_r, n_g, n_b, p_n_y + 8, n_stp );
398
399 n_cr = *( p_n_cr + 4 );
400 n_cb = *( p_n_cb + 4 );
401 n_r = mdec_cr_to_r( n_cr );
402 n_g = mdec_cr_to_g( n_cr ) + mdec_cb_to_g( n_cb );
403 n_b = mdec_cb_to_b( n_cb );
404
405 mdec_makergb24( ( n_address + 24 ), n_r, n_g, n_b, p_n_y + DCTSIZE2, n_stp );
406 mdec_makergb24( ( n_address + 72 ), n_r, n_g, n_b, p_n_y + DCTSIZE2 + 8, n_stp );
407
408 p_n_cr++;
409 p_n_cb++;
410 p_n_y += 2;
411 n_address += 6;
412 }
413 p_n_cr += 4;
414 p_n_cb += 4;
415 p_n_y += 8;
416 n_address += 72;
417 }
418 p_n_y += DCTSIZE2;
419 }
420 n_decoded = ( 24 * 16 ) / 2;
421 }
422
dma_write(uint32_t * p_n_psxram,uint32_t n_address,int32_t n_size)423 void psxmdec_device::dma_write( uint32_t *p_n_psxram, uint32_t n_address, int32_t n_size )
424 {
425 int n_index;
426
427 verboselog( *this, 2, "mdec0_write( %08x, %08x )\n", n_address, n_size );
428
429 switch( n_0_command >> 28 )
430 {
431 case 0x3:
432 verboselog( *this, 1, "mdec decode %08x %08x %08x\n", n_0_command, n_address, n_size );
433 n_0_address = n_address;
434 n_0_size = n_size * 4;
435 n_1_status |= ( 1L << 29 );
436 break;
437 case 0x4:
438 verboselog( *this, 1, "mdec quantize table %08x %08x %08x\n", n_0_command, n_address, n_size );
439 n_index = 0;
440 while( n_size > 0 )
441 {
442 if( n_index < DCTSIZE2 )
443 {
444 p_n_quantize_y[ n_index + 0 ] = ( p_n_psxram[ n_address / 4 ] >> 0 ) & 0xff;
445 p_n_quantize_y[ n_index + 1 ] = ( p_n_psxram[ n_address / 4 ] >> 8 ) & 0xff;
446 p_n_quantize_y[ n_index + 2 ] = ( p_n_psxram[ n_address / 4 ] >> 16 ) & 0xff;
447 p_n_quantize_y[ n_index + 3 ] = ( p_n_psxram[ n_address / 4 ] >> 24 ) & 0xff;
448 }
449 else if( n_index < DCTSIZE2 * 2 )
450 {
451 p_n_quantize_uv[ n_index + 0 - DCTSIZE2 ] = ( p_n_psxram[ n_address / 4 ] >> 0 ) & 0xff;
452 p_n_quantize_uv[ n_index + 1 - DCTSIZE2 ] = ( p_n_psxram[ n_address / 4 ] >> 8 ) & 0xff;
453 p_n_quantize_uv[ n_index + 2 - DCTSIZE2 ] = ( p_n_psxram[ n_address / 4 ] >> 16 ) & 0xff;
454 p_n_quantize_uv[ n_index + 3 - DCTSIZE2 ] = ( p_n_psxram[ n_address / 4 ] >> 24 ) & 0xff;
455 }
456 n_index += 4;
457 n_address += 4;
458 n_size--;
459 }
460 break;
461 case 0x6:
462 verboselog( *this, 1, "mdec cosine table %08x %08x %08x\n", n_0_command, n_address, n_size );
463 n_index = 0;
464 while( n_size > 0 )
465 {
466 p_n_cos[ n_index + 0 ] = (int16_t)( ( p_n_psxram[ n_address / 4 ] >> 0 ) & 0xffff );
467 p_n_cos[ n_index + 1 ] = (int16_t)( ( p_n_psxram[ n_address / 4 ] >> 16 ) & 0xffff );
468 n_index += 2;
469 n_address += 4;
470 n_size--;
471 }
472 mdec_cos_precalc();
473 break;
474 default:
475 verboselog( *this, 0, "mdec unknown command %08x %08x %08x\n", n_0_command, n_address, n_size );
476 break;
477 }
478 }
479
dma_read(uint32_t * p_n_psxram,uint32_t n_address,int32_t n_size)480 void psxmdec_device::dma_read( uint32_t *p_n_psxram, uint32_t n_address, int32_t n_size )
481 {
482 uint32_t n_this;
483 uint32_t n_nextaddress;
484
485 verboselog( *this, 2, "mdec1_read( %08x, %08x )\n", n_address, n_size );
486 if( ( n_0_command & ( 1L << 29 ) ) != 0 && n_0_size != 0 )
487 {
488 while( n_size > 0 )
489 {
490 if( n_decoded == 0 )
491 {
492 if( (int)n_0_size <= 0 )
493 {
494 osd_printf_debug( "ran out of data %08x\n", n_size );
495 n_0_size = 0;
496 break;
497 }
498
499 n_nextaddress = mdec_unpack( p_n_psxram, n_0_address );
500 n_0_size -= n_nextaddress - n_0_address;
501 n_0_address = n_nextaddress;
502
503 if( ( n_0_command & ( 1L << 27 ) ) != 0 )
504 {
505 mdec_yuv2_to_rgb15();
506 }
507 else
508 {
509 mdec_yuv2_to_rgb24();
510 }
511 n_offset = 0;
512 while((psxreadword( p_n_psxram, n_0_address ) == 0xfe00) && n_0_size)
513 {
514 n_0_address += 2; // eat up 0xfe00
515 n_0_size -= 2;
516 }
517 }
518
519 n_this = n_decoded;
520 if( n_this > n_size )
521 {
522 n_this = n_size;
523 }
524 n_decoded -= n_this;
525
526 memcpy( (uint8_t *)p_n_psxram + n_address, (uint8_t *)p_n_output + n_offset, n_this * 4 );
527 n_offset += n_this * 4;
528 n_address += n_this * 4;
529 n_size -= n_this;
530 }
531
532 if( (int)n_0_size < 0 )
533 {
534 osd_printf_debug( "ran out of data %d\n", n_0_size );
535 }
536 }
537 else
538 {
539 osd_printf_debug( "mdec1_read no conversion :%08x:%08x:\n", n_0_command, n_0_size );
540 }
541 if((int)n_0_size <= 0)
542 n_1_status &= ~( 1L << 29 );
543 }
544
write(offs_t offset,uint32_t data)545 void psxmdec_device::write(offs_t offset, uint32_t data)
546 {
547 switch( offset )
548 {
549 case 0:
550 verboselog( *this, 2, "mdec 0 command %08x\n", data );
551 n_0_command = data;
552 break;
553 case 1:
554 verboselog( *this, 2, "mdec 1 command %08x\n", data );
555 n_1_command = data;
556 break;
557 }
558 }
559
read(offs_t offset)560 uint32_t psxmdec_device::read(offs_t offset)
561 {
562 switch( offset )
563 {
564 case 0:
565 verboselog( *this, 2, "mdec 0 status %08x\n", 0 );
566 return 0;
567 case 1:
568 verboselog( *this, 2, "mdec 1 status %08x\n", n_1_status );
569 return n_1_status;
570 }
571 return 0;
572 }
573