summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/video/atarirle.c
blob: 9b2a40d965e44bed57ceddeb8acfffe108018b5d (plain) (tree)
1
2
3
4
5
6
7
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
                                                                            




                                                                 
                                                                            










                                                                           
                                                                            
 
                


                     
                                                                            
                      
                                                                            

                                                                
                                           

                    


                                                                                          


                                                       
                                           

                    

                                      


                                                           
                                           

                    
                                      



                                       




                                                                   
                                           

                    



                                                                                                                
 

                                                                                                                                
 

                                                                                                      
 
                                                                                        
 








                                                                                          

                                                                                                




                                                                                                   
                                                                                                              





                                                                                              
                                              



  
                                                                            
          
                                                                            




                                                                                                    
                                    


 
                                                                            
                    
                                                                            
 




                            
                                                                            
                                
                                                                            
 
                                                       
                                                         
                                                            
                                                                         
                                                
                                                                                                    
                                                                             
                                                                     

                                                                       
                                                                           




                                                                       
                                                                            
                    
                                                                            
 








                                                                                





                                                                 
                      











                                   
      
























                                                                 
                      













                                                                  
      





                                                                 
                                                                           


































                                                                
                                                                            
                    
                                                                            






                                                                 
                               
 
                                                   
                                                     
                                                                                   
                                                                                  
                             
 
                                                   
                                  
























                                                                 
                                                                  

                                                               
                                                                   

















                                                                 
                                                                                   

                              



                                             
                                                                                           

                              

                                                  
 

                                                                                            

                                             



                                                  

                                                                                                    

                                                     


                                  
 
                                      


                                                                                                                   

                                   

                                                         
         




                                                      


 



















                                                                                                                                                      




                                                                 
                                                     
 
                                                   
                                                                








                                             
                                                                   














                                                                                                                          
                                                                                                
                                           
                                                                                                        








                                                                                 
                                                               










                                                                  
                                                          

                                                                 
                                                        
 
                                                   





                                                                 
                                          

                                                                 
                                   
 
         
                                                           












                                                                                                                                   
                                                                                                                 
                                                   
                                                                                                                         









                                                                                    













                                                                 

                                                                 
                                              
 

                                                      


                              
                                       

                                                 















                                                                 




                                                                 
                                                            

                                                                 
                                                
 


                                                      


                                   
                                   

                                                 


                                                             







                                                                 
                                                      
 
                                                   









                                                                                               
                                                      




                                   
                                                        











































































                                                                                  
                                                           
 
                                                  















































                                                                                                   
                                             


                                                       
                                               



                                                          
                                               


















                                                                 
                                               











                                                      
                                                      


            
                                                

                                             
                                                                                      
                            
                                                                                              







                                                                 
                                                                        
 

                                                                                           



                                            

              
                              























































                                                                                                                        
                                   




                                                 
                                                  









                                                                   
                                          























                                                                                    
                                                                                          

                                                                                  
                                                           





                                                                  



                                                    


                                                   


                                             


                                                    


                                           


                                                    


                                              


                                                    



                                                     

                                                                                        


                                                     

                                                                                        

















                                                                                                
                                                                                             


                                                                    
                                                    






                                                                             
                                                                   



























                                                                                                     
                                                              




























































































































































































                                                                                                   
                                                                    




























































































































































































































































































































































































































































































































































































































































                                                                                                   
/***************************************************************************

    atarirle.c

    RLE sprite handling for early-to-mid 90's Atari raster games.

****************************************************************************

    Description:

    Beginning with Hydra, and continuing through to Primal Rage, Atari used
    RLE-compressed sprites. These sprites were decoded, colored, and scaled
    on the fly using an AMD 29C101 ALU unit. The instructions for the ALU
    were read from 3 512-byte PROMs and fed into the instruction input.

    See the bottom of the source for more details on the operation of these
    components.

***************************************************************************/

#include "emu.h"
#include "atarirle.h"


/***************************************************************************
    TYPES & STRUCTURES
***************************************************************************/

/* internal structure containing a word index, shift and mask */
typedef struct atarirle_mask atarirle_mask;
struct atarirle_mask
{
	int				word;				/* word index */
	int				shift;				/* shift amount */
	int				mask;				/* final mask */
};

/* internal structure for sorting the motion objects */
typedef struct mo_sort_entry mo_sort_entry;
struct mo_sort_entry
{
	mo_sort_entry *	next;
	int 			entry;
};

/* internal structure describing each object in the ROMs */
typedef struct atarirle_info atarirle_info;
struct atarirle_info
{
	INT16			width;
	INT16			height;
	INT16			xoffs;
	INT16			yoffs;
	UINT8			bpp;
	const UINT16 *	table;
	const UINT16 *	data;
};

/* internal structure containing the state of the motion objects */
typedef struct atarirle_data atarirle_data;
struct atarirle_data
{
	int				bitmapwidth;		/* width of the full playfield bitmap */
	int				bitmapheight;		/* height of the full playfield bitmap */
	int				bitmapxmask;		/* x coordinate mask for the playfield bitmap */
	int				bitmapymask;		/* y coordinate mask for the playfield bitmap */

	int				spriterammask;		/* combined mask when accessing sprite RAM with raw addresses */
	int				spriteramsize;		/* total size of sprite RAM, in entries */

	int				palettebase;		/* base palette entry */
	int				maxcolors;			/* maximum number of colors */

	rectangle		cliprect;			/* clipping rectangle */

	atarirle_mask	codemask;			/* mask for the code index */
	atarirle_mask	colormask;			/* mask for the color */
	atarirle_mask	xposmask;			/* mask for the X position */
	atarirle_mask	yposmask;			/* mask for the Y position */
	atarirle_mask	scalemask;			/* mask for the scale factor */
	atarirle_mask	hflipmask;			/* mask for the horizontal flip */
	atarirle_mask	ordermask;			/* mask for the order */
	atarirle_mask	prioritymask;		/* mask for the priority */
	atarirle_mask	vrammask;			/* mask for the VRAM target */

	const UINT16 *	rombase;			/* pointer to the base of the GFX ROM */
	int				romlength;			/* length of the GFX ROM */
	int				objectcount;		/* number of objects in the ROM */
	atarirle_info *	info;				/* list of info records */
	atarirle_entry *spriteram;			/* pointer to sprite RAM */

	bitmap_t *		vram[2][2];			/* pointers to VRAM bitmaps and backbuffers */
	int				partial_scanline;	/* partial update scanline */

	UINT8			control_bits;		/* current control bits */
	UINT8			command;			/* current command */
	UINT8			is32bit;			/* 32-bit or 16-bit? */
	UINT16			checksums[256];		/* checksums for each 0x40000 bytes */
	UINT16			ram[0x1000/2];
};



/***************************************************************************
    MACROS
***************************************************************************/

/* data extraction */
#define EXTRACT_DATA(_input, _mask) (((_input)->data[(_mask).word] >> (_mask).shift) & (_mask).mask)


enum { atarirle_hilite_index = -1 };



/***************************************************************************
    STATIC VARIABLES
***************************************************************************/

static UINT8 rle_bpp[8];
static UINT16 *rle_table[8];



/***************************************************************************
    STATIC FUNCTION DECLARATIONS
***************************************************************************/

static void build_rle_tables(running_machine &machine);
static int count_objects(const UINT16 *base, int length);
static void prescan_rle(const atarirle_data *mo, int which);
static void sort_and_render(running_machine &machine, atarirle_data *mo);
static void compute_checksum(atarirle_data *mo);
static void draw_rle(atarirle_data *mo, bitmap_t *bitmap, int code, int color, int hflip, int vflip,
		int x, int y, int xscale, int yscale, const rectangle *clip);
static void draw_rle_zoom(bitmap_t *bitmap, const atarirle_info *gfx,
		UINT32 palette, int sx, int sy, int scalex, int scaley,
		const rectangle *clip);
static void draw_rle_zoom_hflip(bitmap_t *bitmap, const atarirle_info *gfx,
		UINT32 palette, int sx, int sy, int scalex, int scaley,
		const rectangle *clip);



/***************************************************************************
    INLINE FUNCTIONS
***************************************************************************/

INLINE atarirle_data *get_safe_token(device_t *device)
{
	assert(device != NULL);
	assert(device->type() == ATARIRLE);

	return (atarirle_data *)downcast<legacy_device_base *>(device)->token();
}


/*---------------------------------------------------------------
    compute_log: Computes the number of bits necessary to
    hold a given value. The input must be an even power of
    two.
---------------------------------------------------------------*/

#ifdef UNUSED_FUNCTION
INLINE int compute_log(int value)
{
	int log = 0;

	if (value == 0)
		return -1;
	while (!(value & 1))
		log++, value >>= 1;
	if (value != 1)
		return -1;
	return log;
}
#endif

/*---------------------------------------------------------------
    round_to_powerof2: Rounds a number up to the nearest
    power of 2. Even powers of 2 are rounded up to the
    next greatest power (e.g., 4 returns 8).
---------------------------------------------------------------*/

INLINE int round_to_powerof2(int value)
{
	int log = 0;

	if (value == 0)
		return 1;
	while ((value >>= 1) != 0)
		log++;
	return 1 << (log + 1);
}


/*---------------------------------------------------------------
    collapse_bits: Moving right-to-left, for each 1 bit in
    the mask, copy the corresponding bit from the input
    value into the result, packing the bits along the way.
---------------------------------------------------------------*/

#ifdef UNUSED_FUNCTION
INLINE int collapse_bits(int value, int mask)
{
	int testmask, ormask;
	int result = 0;

	for (testmask = ormask = 1; testmask != 0; testmask <<= 1)
		if (mask & testmask)
		{
			if (value & testmask)
				result |= ormask;
			ormask <<= 1;
		}
	return result;
}
#endif

/*---------------------------------------------------------------
    convert_mask: Converts a 4-word mask into a word index,
    shift, and adjusted mask. Returns 0 if invalid.
---------------------------------------------------------------*/

INLINE int convert_mask(const atarirle_entry *input, atarirle_mask *result)
{
	int i, temp;

	/* determine the word and make sure it's only 1 */
	result->word = -1;
	for (i = 0; i < 8; i++)
		if (input->data[i])
		{
			if (result->word == -1)
				result->word = i;
			else
				return 0;
		}

	/* if all-zero, it's valid */
	if (result->word == -1)
	{
		result->word = result->shift = result->mask = 0;
		return 1;
	}

	/* determine the shift and final mask */
	result->shift = 0;
	temp = input->data[result->word];
	while (!(temp & 1))
	{
		result->shift++;
		temp >>= 1;
	}
	result->mask = temp;
	return 1;
}



/***************************************************************************
    GLOBAL FUNCTIONS
***************************************************************************/

/*---------------------------------------------------------------
    atarirle_init: Configures the motion objects using the input
    description. Allocates all memory necessary and generates
    the attribute lookup table.
---------------------------------------------------------------*/

static DEVICE_START( atarirle )
{
	atarirle_data *mo = get_safe_token(device);
	running_machine &machine = device->machine();
	const atarirle_desc *desc = (const atarirle_desc *)device->static_config();
	const UINT16 *base = (const UINT16 *)machine.region(desc->region)->base();
	int i, width, height;

	/* build and allocate the generic tables */
	build_rle_tables(machine);

	/* determine the masks first */
	convert_mask(&desc->codemask,     &mo->codemask);
	convert_mask(&desc->colormask,    &mo->colormask);
	convert_mask(&desc->xposmask,     &mo->xposmask);
	convert_mask(&desc->yposmask,     &mo->yposmask);
	convert_mask(&desc->scalemask,    &mo->scalemask);
	convert_mask(&desc->hflipmask,    &mo->hflipmask);
	convert_mask(&desc->ordermask,    &mo->ordermask);
	convert_mask(&desc->prioritymask, &mo->prioritymask);
	convert_mask(&desc->vrammask,     &mo->vrammask);

	/* copy in the basic data */
	mo->bitmapwidth   = round_to_powerof2(mo->xposmask.mask);
	mo->bitmapheight  = round_to_powerof2(mo->yposmask.mask);
	mo->bitmapxmask   = mo->bitmapwidth - 1;
	mo->bitmapymask   = mo->bitmapheight - 1;

	mo->spriteramsize = desc->spriteramentries;
	mo->spriterammask = desc->spriteramentries - 1;

	mo->palettebase   = desc->palettebase;
	mo->maxcolors     = desc->maxcolors / 16;

	mo->rombase       = base;
	mo->romlength     = machine.region(desc->region)->bytes();
	mo->objectcount   = count_objects(base, mo->romlength);

	mo->cliprect      = machine.primary_screen->visible_area();
	if (desc->rightclip)
	{
		mo->cliprect.min_x = desc->leftclip;
		mo->cliprect.max_x = desc->rightclip;
	}

	/* compute the checksums */
	memset(mo->checksums, 0, sizeof(mo->checksums));
	for (i = 0; i < mo->romlength / 0x20000; i++)
	{
		const UINT16 *csbase = &mo->rombase[0x10000 * i];
		int cursum = 0, j;
		for (j = 0; j < 0x10000; j++)
			cursum += *csbase++;
		mo->checksums[i] = cursum;
	}

	/* allocate the object info */
	mo->info = auto_alloc_array_clear(machine, atarirle_info, mo->objectcount);

	/* fill in the data */
	for (i = 0; i < mo->objectcount; i++)
		prescan_rle(mo, i);

	/* allocate the spriteram */
	mo->spriteram = auto_alloc_array_clear(machine, atarirle_entry, mo->spriteramsize);

	/* allocate bitmaps */
	width = machine.primary_screen->width();
	height = machine.primary_screen->height();

	mo->vram[0][0] = auto_bitmap_alloc(machine, width, height, BITMAP_FORMAT_INDEXED16);
	mo->vram[0][1] = auto_bitmap_alloc(machine, width, height, BITMAP_FORMAT_INDEXED16);
	bitmap_fill(mo->vram[0][0], NULL, 0);
	bitmap_fill(mo->vram[0][1], NULL, 0);

	/* allocate alternate bitmaps if needed */
	if (mo->vrammask.mask != 0)
	{
		mo->vram[1][0] = auto_bitmap_alloc(machine, width, height, BITMAP_FORMAT_INDEXED16);
		mo->vram[1][1] = auto_bitmap_alloc(machine, width, height, BITMAP_FORMAT_INDEXED16);
		bitmap_fill(mo->vram[1][0], NULL, 0);
		bitmap_fill(mo->vram[1][1], NULL, 0);
	}

	mo->partial_scanline = -1;

	/* register for save states */
	device->save_pointer(NAME(mo->spriteram[0].data), ARRAY_LENGTH(mo->spriteram[0].data) * mo->spriteramsize);
	device->save_item(NAME(*mo->vram[0][0]));
	device->save_item(NAME(*mo->vram[0][1]));
	if (mo->vrammask.mask != 0)
	{
		device->save_item(NAME(*mo->vram[1][0]));
		device->save_item(NAME(*mo->vram[1][1]));
	}
	device->save_item(NAME(mo->partial_scanline));
	device->save_item(NAME(mo->control_bits));
	device->save_item(NAME(mo->command));
	device->save_item(NAME(mo->is32bit));
	device->save_item(NAME(mo->checksums));
}


DEVICE_GET_INFO( atarirle )
{
	switch (state)
	{
		/* --- the following bits of info are returned as 64-bit signed integers --- */
		case DEVINFO_INT_TOKEN_BYTES:			info->i = sizeof(atarirle_data);					break;

		/* --- the following bits of info are returned as pointers to data or functions --- */
		case DEVINFO_FCT_START:					info->start = DEVICE_START_NAME(atarirle);		break;

		/* --- the following bits of info are returned as NULL-terminated strings --- */
		case DEVINFO_STR_NAME:					strcpy(info->s, "Atari RLE");				break;
		case DEVINFO_STR_FAMILY:				strcpy(info->s, "Atari RLE Video IC");					break;
		case DEVINFO_STR_VERSION:				strcpy(info->s, "1.0");							break;
		case DEVINFO_STR_SOURCE_FILE:			strcpy(info->s, __FILE__);						break;
		case DEVINFO_STR_CREDITS:				strcpy(info->s, "Copyright MAME Team");			break;
	}
}

DEFINE_LEGACY_DEVICE(ATARIRLE, atarirle);

/*---------------------------------------------------------------
    atarirle_control_w: Write handler for MO control bits.
---------------------------------------------------------------*/

void atarirle_control_w(device_t *device, UINT8 bits)
{
	atarirle_data *mo = get_safe_token(device);
	int scanline = device->machine().primary_screen->vpos();
	int oldbits = mo->control_bits;

//logerror("atarirle_control_w(%d)\n", bits);

	/* do nothing if nothing changed */
	if (oldbits == bits)
		return;

	/* force a partial update first */
	device->machine().primary_screen->update_partial(scanline);

	/* if the erase flag was set, erase the front map */
	if (oldbits & ATARIRLE_CONTROL_ERASE)
	{
		rectangle cliprect = mo->cliprect;

		/* compute the top and bottom of the rect */
		if (mo->partial_scanline + 1 > cliprect.min_y)
			cliprect.min_y = mo->partial_scanline + 1;
		if (scanline < cliprect.max_y)
			cliprect.max_y = scanline;

//logerror("  partial erase %d-%d (frame %d)\n", cliprect.min_y, cliprect.max_y, (oldbits & ATARIRLE_CONTROL_FRAME) >> 2);

		/* erase the bitmap */
		bitmap_fill(mo->vram[0][(oldbits & ATARIRLE_CONTROL_FRAME) >> 2], &cliprect, 0);
		if (mo->vrammask.mask != 0)
			bitmap_fill(mo->vram[1][(oldbits & ATARIRLE_CONTROL_FRAME) >> 2], &cliprect, 0);
	}

	/* update the bits */
	mo->control_bits = bits;

	/* if mogo is set, do a render on the rising edge */
	if (!(oldbits & ATARIRLE_CONTROL_MOGO) && (bits & ATARIRLE_CONTROL_MOGO))
	{
		if (mo->command == ATARIRLE_COMMAND_DRAW)
			sort_and_render(device->machine(), mo);
		else if (mo->command == ATARIRLE_COMMAND_CHECKSUM)
			compute_checksum(mo);
	}

	/* remember where we left off */
	mo->partial_scanline = scanline;
}



/*---------------------------------------------------------------
    atarirle_command_w: Write handler for MO command bits.
---------------------------------------------------------------*/

void atarirle_command_w(device_t *device, UINT8 command)
{
	atarirle_data *mo = get_safe_token(device);
	mo->command = command;
}



/*---------------------------------------------------------------
    atarirle_eof: Flush remaining changes.
---------------------------------------------------------------*/

void atarirle_eof(device_t *device)
{
	{
		atarirle_data *mo = get_safe_token(device);

		/* if the erase flag is set, erase to the end of the screen */
		if (mo->control_bits & ATARIRLE_CONTROL_ERASE)
		{
			rectangle cliprect = mo->cliprect;

			/* compute top only; bottom is equal to visible_area */
			if (mo->partial_scanline + 1 > cliprect.min_y)
				cliprect.min_y = mo->partial_scanline + 1;

//logerror("  partial erase %d-%d (frame %d)\n", cliprect.min_y, cliprect.max_y, (mo->control_bits & ATARIRLE_CONTROL_FRAME) >> 2);

			/* erase the bitmap */
			bitmap_fill(mo->vram[0][(mo->control_bits & ATARIRLE_CONTROL_FRAME) >> 2], &cliprect, 0);
			if (mo->vrammask.mask != 0)
				bitmap_fill(mo->vram[1][(mo->control_bits & ATARIRLE_CONTROL_FRAME) >> 2], &cliprect, 0);
		}

		/* reset the partial scanline to -1 so we can detect full updates */
		mo->partial_scanline = -1;
	}
}



/*---------------------------------------------------------------
    atarirle_spriteram_r: Read handler for the spriteram.
---------------------------------------------------------------*/

READ16_DEVICE_HANDLER( atarirle_spriteram_r )
{
	atarirle_data *mo = get_safe_token(device);

	return mo->ram[offset];
}



/*---------------------------------------------------------------
    atarirle_spriteram_w: Write handler for the spriteram.
---------------------------------------------------------------*/

WRITE16_DEVICE_HANDLER( atarirle_spriteram_w )
{
	atarirle_data *mo = get_safe_token(device);
	int entry = (offset >> 3) & mo->spriterammask;
	int idx = offset & 7;

	/* combine raw data */
	COMBINE_DATA(&mo->ram[offset]);

	/* store a copy in our local spriteram */
	mo->spriteram[entry].data[idx] = mo->ram[offset];
	mo->is32bit = 0;
}



/*---------------------------------------------------------------
    atarirle_spriteram32_r: Read handler for the spriteram.
---------------------------------------------------------------*/

READ32_DEVICE_HANDLER( atarirle_spriteram32_r )
{
	atarirle_data *mo = get_safe_token(device);
	UINT32 *ram = (UINT32 *)mo->ram;

	return ram[offset];
}



/*---------------------------------------------------------------
    atarirle_spriteram32_w: Write handler for the spriteram.
---------------------------------------------------------------*/

WRITE32_DEVICE_HANDLER( atarirle_spriteram32_w )
{
	atarirle_data *mo = get_safe_token(device);
	UINT32 *ram = (UINT32 *)mo->ram;
	int entry = (offset >> 2) & mo->spriterammask;
	int idx = 2 * (offset & 3);

	/* combine raw data */
	COMBINE_DATA(&ram[offset]);

	/* store a copy in our local spriteram */
	mo->spriteram[entry].data[idx+0] = ram[offset] >> 16;
	mo->spriteram[entry].data[idx+1] = ram[offset];
	mo->is32bit = 1;
}



/*---------------------------------------------------------------
    atarirle_get_vram: Return the VRAM bitmap.
---------------------------------------------------------------*/

bitmap_t *atarirle_get_vram(device_t *device, int idx)
{
	atarirle_data *mo = get_safe_token(device);
//logerror("atarirle_get_vram (frame %d)\n", (mo->control_bits & ATARIRLE_CONTROL_FRAME) >> 2);
	return mo->vram[idx][(mo->control_bits & ATARIRLE_CONTROL_FRAME) >> 2];
}



/*---------------------------------------------------------------
    build_rle_tables: Builds internal table for RLE mapping.
---------------------------------------------------------------*/

static void build_rle_tables(running_machine &machine)
{
	UINT16 *base;
	int i;

	/* allocate all 5 tables */
	base = auto_alloc_array(machine, UINT16, 0x500);

	/* assign the tables */
	rle_table[0] = &base[0x000];
	rle_table[1] = &base[0x100];
	rle_table[2] = rle_table[3] = &base[0x200];
	rle_table[4] = rle_table[6] = &base[0x300];
	rle_table[5] = rle_table[7] = &base[0x400];

	/* set the bpps */
	rle_bpp[0] = 4;
	rle_bpp[1] = rle_bpp[2] = rle_bpp[3] = 5;
	rle_bpp[4] = rle_bpp[5] = rle_bpp[6] = rle_bpp[7] = 6;

	/* build the 4bpp table */
	for (i = 0; i < 256; i++)
		rle_table[0][i] = (((i & 0xf0) + 0x10) << 4) | (i & 0x0f);

	/* build the 5bpp table */
	for (i = 0; i < 256; i++)
		rle_table[2][i] = (((i & 0xe0) + 0x20) << 3) | (i & 0x1f);

	/* build the special 5bpp table */
	for (i = 0; i < 256; i++)
	{
		if ((i & 0x0f) == 0)
			rle_table[1][i] = (((i & 0xf0) + 0x10) << 4) | (i & 0x0f);
		else
			rle_table[1][i] = (((i & 0xe0) + 0x20) << 3) | (i & 0x1f);
	}

	/* build the 6bpp table */
	for (i = 0; i < 256; i++)
		rle_table[5][i] = (((i & 0xc0) + 0x40) << 2) | (i & 0x3f);

	/* build the special 6bpp table */
	for (i = 0; i < 256; i++)
	{
		if ((i & 0x0f) == 0)
			rle_table[4][i] = (((i & 0xf0) + 0x10) << 4) | (i & 0x0f);
		else
			rle_table[4][i] = (((i & 0xc0) + 0x40) << 2) | (i & 0x3f);
	}
}



/*---------------------------------------------------------------
    count_objects: Determines the number of objects in the
    motion object ROM.
---------------------------------------------------------------*/

int count_objects(const UINT16 *base, int length)
{
	int lowest_address = length;
	int i;

	/* first determine the lowest address of all objects */
	for (i = 0; i < lowest_address; i += 4)
	{
		int offset = ((base[i + 2] & 0xff) << 16) | base[i + 3];
//logerror("count_objects: i=%d offset=%08X\n", i, offset);
		if (offset > i && offset < lowest_address)
			lowest_address = offset;
	}

	/* that determines how many objects */
	return lowest_address / 4;
}



/*---------------------------------------------------------------
    prescan_rle: Prescans an RLE object, computing the
    width, height, and other goodies.
---------------------------------------------------------------*/

static void prescan_rle(const atarirle_data *mo, int which)
{
	atarirle_info *rledata = &mo->info[which];
	UINT16 *base = (UINT16 *)&mo->rombase[which * 4];
	const UINT16 *end = mo->rombase + mo->romlength / 2;
	int width = 0, height, flags, offset;
	const UINT16 *table;

	/* look up the offset */
	rledata->xoffs = (INT16)base[0];
	rledata->yoffs = (INT16)base[1];

	/* determine the depth and table */
	flags = base[2];
	rledata->bpp = rle_bpp[(flags >> 8) & 7];
	table = rledata->table = rle_table[(flags >> 8) & 7];

	/* determine the starting offset */
	offset = ((base[2] & 0xff) << 16) | base[3];
	rledata->data = base = (UINT16 *)&mo->rombase[offset];

	/* make sure it's valid */
	if (offset < which * 4 || offset >= mo->romlength)
	{
		memset(rledata, 0, sizeof(*rledata));
		return;
	}

	/* first pre-scan to determine the width and height */
	for (height = 0; height < 1024 && base < end; height++)
	{
		int tempwidth = 0;
		int entry_count = *base++;

		/* if the high bit is set, assume we're inverted */
		if (entry_count & 0x8000)
		{
			entry_count ^= 0xffff;

			/* also change the ROM data so we don't have to do this again at runtime */
			base[-1] ^= 0xffff;
		}

		/* we're done when we hit 0 */
		if (entry_count == 0)
			break;

		/* track the width */
		while (entry_count-- && base < end)
		{
			int word = *base++;
			int count/*, value*/;

			/* decode the low byte first */
			count = table[word & 0xff];
			//value = count & 0xff;
			tempwidth += count >> 8;

			/* decode the upper byte second */
			count = table[word >> 8];
			//value = count & 0xff;
			tempwidth += count >> 8;
		}

		/* only remember the max */
		if (tempwidth > width)
			width = tempwidth;
	}

	/* fill in the data */
	rledata->width = width;
	rledata->height = height;
}



/*---------------------------------------------------------------
    compute_checksum: Compute the checksum values on the ROMs.
---------------------------------------------------------------*/

static void compute_checksum(atarirle_data *mo)
{
	int reqsums = mo->spriteram[0].data[0] + 1;
	int i;

	/* number of checksums is in the first word */
	if (reqsums > 256)
		reqsums = 256;

	/* stuff them back */
	if (!mo->is32bit)
	{
		for (i = 0; i < reqsums; i++)
			mo->ram[i] = mo->checksums[i];
	}
	else
	{
		UINT32 *ram = (UINT32 *)mo->ram;
		for (i = 0; i < reqsums; i++)
			if (i & 1)
				ram[i/2] = (ram[i/2] & 0xffff0000) | mo->checksums[i];
			else
				ram[i/2] = (ram[i/2] & 0x0000ffff) | (mo->checksums[i] << 16);
	}
}


/*---------------------------------------------------------------
    sort_and_render: Render all motion objects in order.
---------------------------------------------------------------*/

static void sort_and_render(running_machine &machine, atarirle_data *mo)
{
	bitmap_t *bitmap1 = mo->vram[0][(~mo->control_bits & ATARIRLE_CONTROL_FRAME) >> 2];
	bitmap_t *bitmap2 = mo->vram[1][(~mo->control_bits & ATARIRLE_CONTROL_FRAME) >> 2];
	atarirle_entry *obj = mo->spriteram;
	mo_sort_entry sort_entry[256];
	mo_sort_entry *list_head[256];
	mo_sort_entry *current;
	int i;

atarirle_entry *hilite = NULL;
int count = 0;

	/* sort the motion objects into their proper priorities */
	memset(list_head, 0, sizeof(list_head));
	for (i = 0; i < 256; i++, obj++)
	{
		int order = EXTRACT_DATA(obj, mo->ordermask);
		sort_entry[i].entry = i;
		sort_entry[i].next = list_head[order];
		list_head[order] = &sort_entry[i];
	}

	/* now loop back and process */
	count = 0;
	for (i = 1; i < 256; i++)
		for (current = list_head[i]; current; current = current->next)
		{
			int scale, code;

			/* extract scale and code */
			obj = &mo->spriteram[current->entry];
			scale = EXTRACT_DATA(obj, mo->scalemask);
			code = EXTRACT_DATA(obj, mo->codemask);

			/* make sure they are in range */
			if (scale > 0 && code < mo->objectcount)
			{
				int hflip = EXTRACT_DATA(obj, mo->hflipmask);
				int color = EXTRACT_DATA(obj, mo->colormask);
				int priority = EXTRACT_DATA(obj, mo->prioritymask);
				int x = EXTRACT_DATA(obj, mo->xposmask);
				int y = EXTRACT_DATA(obj, mo->yposmask);
				int which = EXTRACT_DATA(obj, mo->vrammask);

if (count++ == atarirle_hilite_index)
	hilite = obj;

				if (x & ((mo->xposmask.mask + 1) >> 1))
					x = (INT16)(x | ~mo->xposmask.mask);
				if (y & ((mo->yposmask.mask + 1) >> 1))
					y = (INT16)(y | ~mo->yposmask.mask);
				x += mo->cliprect.min_x;

				/* merge priority and color */
				color = (color << 4) | (priority << ATARIRLE_PRIORITY_SHIFT);

				/* render to one or both bitmaps */
				if (which == 0)
					draw_rle(mo, bitmap1, code, color, hflip, 0, x, y, scale, scale, &mo->cliprect);
				if (bitmap2 && which != 0)
					draw_rle(mo, bitmap2, code, color, hflip, 0, x, y, scale, scale, &mo->cliprect);
			}
		}

if (hilite)
{
	int scale, code/*, which*/;

	/* extract scale and code */
	obj = hilite;
	scale = EXTRACT_DATA(obj, mo->scalemask);
	code = EXTRACT_DATA(obj, mo->codemask);
	//which = EXTRACT_DATA(obj, mo->vrammask);

	/* make sure they are in range */
	if (scale > 0 && code < mo->objectcount)
	{
		int hflip = EXTRACT_DATA(obj, mo->hflipmask);
		int color = EXTRACT_DATA(obj, mo->colormask);
		int priority = EXTRACT_DATA(obj, mo->prioritymask);
		int x = EXTRACT_DATA(obj, mo->xposmask);
		int y = EXTRACT_DATA(obj, mo->yposmask);
		int scaled_xoffs, scaled_yoffs;
		const atarirle_info *info;

		if (x & ((mo->xposmask.mask + 1) >> 1))
			x = (INT16)(x | ~mo->xposmask.mask);
		if (y & ((mo->yposmask.mask + 1) >> 1))
			y = (INT16)(y | ~mo->yposmask.mask);
		x += mo->cliprect.min_x;

		/* merge priority and color */
		color = (color << 4) | (priority << ATARIRLE_PRIORITY_SHIFT);

		info = &mo->info[code];
		scaled_xoffs = (scale * info->xoffs) >> 12;
		scaled_yoffs = (scale * info->yoffs) >> 12;

		/* we're hflipped, account for it */
		if (hflip)
			scaled_xoffs = ((scale * info->width) >> 12) - scaled_xoffs;

		/* adjust for the x and y offsets */
		x -= scaled_xoffs;
		y -= scaled_yoffs;

		do
		{
			const rectangle &visarea = machine.primary_screen->visible_area();
			int scaled_width = (scale * info->width + 0x7fff) >> 12;
			int scaled_height = (scale * info->height + 0x7fff) >> 12;
			int ex, ey, sx = x, sy = y, tx, ty;

			/* make sure we didn't end up with 0 */
			if (scaled_width == 0) scaled_width = 1;
			if (scaled_height == 0) scaled_height = 1;

			/* compute the remaining parameters */
			ex = sx + scaled_width - 1;
			ey = sy + scaled_height - 1;

			/* left edge clip */
			if (sx < visarea.min_x)
				sx = visarea.min_x;
			if (sx > visarea.max_x)
				break;

			/* right edge clip */
			if (ex > visarea.max_x)
				ex = visarea.max_x;
			else if (ex < visarea.min_x)
				break;

			/* top edge clip */
			if (sy < visarea.min_y)
				sy = visarea.min_y;
			else if (sy > visarea.max_y)
				break;

			/* bottom edge clip */
			if (ey > visarea.max_y)
				ey = visarea.max_y;
			else if (ey < visarea.min_y)
				break;

			for (ty = sy; ty <= ey; ty++)
			{
				*BITMAP_ADDR16(bitmap1, ty, sx) = machine.rand() & 0xff;
				*BITMAP_ADDR16(bitmap1, ty, ex) = machine.rand() & 0xff;
			}
			for (tx = sx; tx <= ex; tx++)
			{
				*BITMAP_ADDR16(bitmap1, sy, tx) = machine.rand() & 0xff;
				*BITMAP_ADDR16(bitmap1, ey, tx) = machine.rand() & 0xff;
			}
		} while (0);
fprintf(stderr, "   Sprite: c=%04X l=%04X h=%d X=%4d (o=%4d w=%3d) Y=%4d (o=%4d h=%d) s=%04X\n",
	code, color, hflip,
	x, -scaled_xoffs, (scale * info->width) >> 12,
	y, -scaled_yoffs, (scale * info->height) >> 12, scale);
	}

}
}



/*---------------------------------------------------------------
    draw_rle: Render a single RLE-compressed motion
    object.
---------------------------------------------------------------*/

void draw_rle(atarirle_data *mo, bitmap_t *bitmap, int code, int color, int hflip, int vflip,
	int x, int y, int xscale, int yscale, const rectangle *clip)
{
	UINT32 palettebase = mo->palettebase + color;
	const atarirle_info *info = &mo->info[code];
	int scaled_xoffs = (xscale * info->xoffs) >> 12;
	int scaled_yoffs = (yscale * info->yoffs) >> 12;

	/* we're hflipped, account for it */
	if (hflip)
		scaled_xoffs = ((xscale * info->width) >> 12) - scaled_xoffs;

//if (clip->min_y == Machine->primary_screen->visible_area().min_y)
//logerror("   Sprite: c=%04X l=%04X h=%d X=%4d (o=%4d w=%3d) Y=%4d (o=%4d h=%d) s=%04X\n",
//  code, color, hflip,
//  x, -scaled_xoffs, (xscale * info->width) >> 12,
//  y, -scaled_yoffs, (yscale * info->height) >> 12, xscale);

	/* adjust for the x and y offsets */
	x -= scaled_xoffs;
	y -= scaled_yoffs;

	/* bail on a NULL object */
	if (!info->data)
		return;

	/* 16-bit case */
	assert(bitmap->bpp == 16);
	if (!hflip)
		draw_rle_zoom(bitmap, info, palettebase, x, y, xscale << 4, yscale << 4, clip);
	else
		draw_rle_zoom_hflip(bitmap, info, palettebase, x, y, xscale << 4, yscale << 4, clip);
}



/*---------------------------------------------------------------
    draw_rle_zoom: Draw an RLE-compressed object to a 16-bit
    bitmap.
---------------------------------------------------------------*/

void draw_rle_zoom(bitmap_t *bitmap, const atarirle_info *gfx,
		UINT32 palette, int sx, int sy, int scalex, int scaley,
		const rectangle *clip)
{
	const UINT16 *row_start = gfx->data;
	const UINT16 *table = gfx->table;
	volatile int current_row = 0;

	int scaled_width = (scalex * gfx->width + 0x7fff) >> 16;
	int scaled_height = (scaley * gfx->height + 0x7fff) >> 16;

	int pixels_to_skip = 0, xclipped = 0;
	int dx, dy, ex, ey;
	int y, sourcey;

	/* make sure we didn't end up with 0 */
	if (scaled_width == 0) scaled_width = 1;
	if (scaled_height == 0) scaled_height = 1;

	/* compute the remaining parameters */
	dx = (gfx->width << 16) / scaled_width;
	dy = (gfx->height << 16) / scaled_height;
	ex = sx + scaled_width - 1;
	ey = sy + scaled_height - 1;
	sourcey = dy / 2;

	/* left edge clip */
	if (sx < clip->min_x)
		pixels_to_skip = clip->min_x - sx, xclipped = 1;
	if (sx > clip->max_x)
		return;

	/* right edge clip */
	if (ex > clip->max_x)
		ex = clip->max_x, xclipped = 1;
	else if (ex < clip->min_x)
		return;

	/* top edge clip */
	if (sy < clip->min_y)
	{
		sourcey += (clip->min_y - sy) * dy;
		sy = clip->min_y;
	}
	else if (sy > clip->max_y)
		return;

	/* bottom edge clip */
	if (ey > clip->max_y)
		ey = clip->max_y;
	else if (ey < clip->min_y)
		return;

	/* loop top to bottom */
	for (y = sy; y <= ey; y++, sourcey += dy)
	{
		UINT16 *dest = BITMAP_ADDR16(bitmap, y, sx);
		int j, sourcex = dx / 2, rle_end = 0;
		const UINT16 *base;
		int entry_count;

		/* loop until we hit the row we're on */
		for ( ; current_row != (sourcey >> 16); current_row++)
			row_start += 1 + *row_start;

		/* grab our starting parameters from this row */
		base = row_start;
		entry_count = *base++;

		/* non-clipped case */
		if (!xclipped)
		{
			/* decode the pixels */
			for (j = 0; j < entry_count; j++)
			{
				int word = *base++;
				int count, value;

				/* decode the low byte first */
				count = table[word & 0xff];
				value = count & 0xff;
				rle_end += (count & 0xff00) << 8;

				/* store copies of the value until we pass the end of this chunk */
				if (value)
				{
					value += palette;
					while (sourcex < rle_end)
						*dest++ = value, sourcex += dx;
				}
				else
				{
					while (sourcex < rle_end)
						dest++, sourcex += dx;
				}

				/* decode the upper byte second */
				count = table[word >> 8];
				value = count & 0xff;
				rle_end += (count & 0xff00) << 8;

				/* store copies of the value until we pass the end of this chunk */
				if (value)
				{
					value += palette;
					while (sourcex < rle_end)
						*dest++ = value, sourcex += dx;
				}
				else
				{
					while (sourcex < rle_end)
						dest++, sourcex += dx;
				}
			}
		}

		/* clipped case */
		else
		{
			const UINT16 *end = BITMAP_ADDR16(bitmap, y, ex);
			int to_be_skipped = pixels_to_skip;

			/* decode the pixels */
			for (j = 0; j < entry_count && dest <= end; j++)
			{
				int word = *base++;
				int count, value;

				/* decode the low byte first */
				count = table[word & 0xff];
				value = count & 0xff;
				rle_end += (count & 0xff00) << 8;

				/* store copies of the value until we pass the end of this chunk */
				if (to_be_skipped)
				{
					while (to_be_skipped && sourcex < rle_end)
						dest++, sourcex += dx, to_be_skipped--;
					if (to_be_skipped) goto next3;
				}
				if (value)
				{
					value += palette;
					while (sourcex < rle_end && dest <= end)
						*dest++ = value, sourcex += dx;
				}
				else
				{
					while (sourcex < rle_end)
						dest++, sourcex += dx;
				}

			next3:
				/* decode the upper byte second */
				count = table[word >> 8];
				value = count & 0xff;
				rle_end += (count & 0xff00) << 8;

				/* store copies of the value until we pass the end of this chunk */
				if (to_be_skipped)
				{
					while (to_be_skipped && sourcex < rle_end)
						dest++, sourcex += dx, to_be_skipped--;
					if (to_be_skipped) goto next4;
				}
				if (value)
				{
					value += palette;
					while (sourcex < rle_end && dest <= end)
						*dest++ = value, sourcex += dx;
				}
				else
				{
					while (sourcex < rle_end)
						dest++, sourcex += dx;
				}
			next4:
				;
			}
		}
	}
}



/*---------------------------------------------------------------
    draw_rle_zoom_hflip: Draw an RLE-compressed object to a
    16-bit bitmap with horizontal flip.
---------------------------------------------------------------*/

void draw_rle_zoom_hflip(bitmap_t *bitmap, const atarirle_info *gfx,
		UINT32 palette, int sx, int sy, int scalex, int scaley,
		const rectangle *clip)
{
	const UINT16 *row_start = gfx->data;
	const UINT16 *table = gfx->table;
	volatile int current_row = 0;

	int scaled_width = (scalex * gfx->width + 0x7fff) >> 16;
	int scaled_height = (scaley * gfx->height + 0x7fff) >> 16;
	int pixels_to_skip = 0, xclipped = 0;
	int dx, dy, ex, ey;
	int y, sourcey;

	/* make sure we didn't end up with 0 */
	if (scaled_width == 0) scaled_width = 1;
	if (scaled_height == 0) scaled_height = 1;

	/* compute the remaining parameters */
	dx = (gfx->width << 16) / scaled_width;
	dy = (gfx->height << 16) / scaled_height;
	ex = sx + scaled_width - 1;
	ey = sy + scaled_height - 1;
	sourcey = dy / 2;

	/* left edge clip */
	if (sx < clip->min_x)
		sx = clip->min_x, xclipped = 1;
	if (sx > clip->max_x)
		return;

	/* right edge clip */
	if (ex > clip->max_x)
		pixels_to_skip = ex - clip->max_x, xclipped = 1;
	else if (ex < clip->min_x)
		return;

	/* top edge clip */
	if (sy < clip->min_y)
	{
		sourcey += (clip->min_y - sy) * dy;
		sy = clip->min_y;
	}
	else if (sy > clip->max_y)
		return;

	/* bottom edge clip */
	if (ey > clip->max_y)
		ey = clip->max_y;
	else if (ey < clip->min_y)
		return;

	/* loop top to bottom */
	for (y = sy; y <= ey; y++, sourcey += dy)
	{
		UINT16 *dest = BITMAP_ADDR16(bitmap, y, ex);
		int j, sourcex = dx / 2, rle_end = 0;
		const UINT16 *base;
		int entry_count;

		/* loop until we hit the row we're on */
		for ( ; current_row != (sourcey >> 16); current_row++)
			row_start += 1 + *row_start;

		/* grab our starting parameters from this row */
		base = row_start;
		entry_count = *base++;

		/* non-clipped case */
		if (!xclipped)
		{
			/* decode the pixels */
			for (j = 0; j < entry_count; j++)
			{
				int word = *base++;
				int count, value;

				/* decode the low byte first */
				count = table[word & 0xff];
				value = count & 0xff;
				rle_end += (count & 0xff00) << 8;

				/* store copies of the value until we pass the end of this chunk */
				if (value)
				{
					value += palette;
					while (sourcex < rle_end)
						*dest-- = value, sourcex += dx;
				}
				else
				{
					while (sourcex < rle_end)
						dest--, sourcex += dx;
				}

				/* decode the upper byte second */
				count = table[word >> 8];
				value = count & 0xff;
				rle_end += (count & 0xff00) << 8;

				/* store copies of the value until we pass the end of this chunk */
				if (value)
				{
					value += palette;
					while (sourcex < rle_end)
						*dest-- = value, sourcex += dx;
				}
				else
				{
					while (sourcex < rle_end)
						dest--, sourcex += dx;
				}
			}
		}

		/* clipped case */
		else
		{
			const UINT16 *start = BITMAP_ADDR16(bitmap, y, sx);
			int to_be_skipped = pixels_to_skip;

			/* decode the pixels */
			for (j = 0; j < entry_count && dest >= start; j++)
			{
				int word = *base++;
				int count, value;

				/* decode the low byte first */
				count = table[word & 0xff];
				value = count & 0xff;
				rle_end += (count & 0xff00) << 8;

				/* store copies of the value until we pass the end of this chunk */
				if (to_be_skipped)
				{
					while (to_be_skipped && sourcex < rle_end)
						dest--, sourcex += dx, to_be_skipped--;
					if (to_be_skipped) goto next3;
				}
				if (value)
				{
					value += palette;
					while (sourcex < rle_end && dest >= start)
						*dest-- = value, sourcex += dx;
				}
				else
				{
					while (sourcex < rle_end)
						dest--, sourcex += dx;
				}

			next3:
				/* decode the upper byte second */
				count = table[word >> 8];
				value = count & 0xff;
				rle_end += (count & 0xff00) << 8;

				/* store copies of the value until we pass the end of this chunk */
				if (to_be_skipped)
				{
					while (to_be_skipped && sourcex < rle_end)
						dest--, sourcex += dx, to_be_skipped--;
					if (to_be_skipped) goto next4;
				}
				if (value)
				{
					value += palette;
					while (sourcex < rle_end && dest >= start)
						*dest-- = value, sourcex += dx;
				}
				else
				{
					while (sourcex < rle_end)
						dest--, sourcex += dx;
				}
			next4:
				;
			}
		}
	}
}


/***************************************************************************

    The mapping of the bits from the PROMs is like this:

        D23 ->
        D22 ->
        D21 ->
        D20 ->
        D19 ->
        D18 ->
        D17 -> instruction bit 8
        D16 -> instruction bit 7

        D15 -> instruction bit 6
        D14 -> instruction bit 5
        D13 -> instruction bit 4
        D12 -> instruction bit 3
        D11 -> instruction bit 2
        D10 -> instruction bit 1 (modified via a PAL)
        D9  -> instruction bit 0
        D8  -> carry in

        D7  -> A bit 3
        D6  -> A bit 2
        D5  -> A bit 1
        D4  -> A bit 0
        D3  -> B bit 3
        D2  -> B bit 2
        D1  -> B bit 1
        D0  -> B bit 0

    Although much of the logic is contained in the ALU, the program counter
    is fed externally. Jumps are decoded like this:

        if (D13 && D14)
        {
            switch (D11 | D10 | D9)
            {
                case 0: condition = true;
                case 1: condition = ALU.LT;
                case 2: condition = ALU.Z;
                case 3: condition = ALU.N;
                case 4: condition = BLT.HFLIP;
                case 5: condition = /BLT.SCAN;
                case 6: condition = ALU.C;
                case 7: condition = MOTIMEP;
            }
            condition ^= D12;
            if (condition)
                PC = D8 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0;
        }

    Here is the code from Guardians of the Hood:

                      I  C A B
                     --- - - -
    000: A0 C8 00 -> 064 0 0 0 (latch UC.RASCAS)
    001: 01 C8 66 -> 0E4 0 6 6
    002: 01 89 66 -> 0C4 1 6 6
    003: 03 82 66 -> 1C1 0 6 6
    004: 01 B8 65 -> 0DC 0 6 5
    005: 01 82 66 -> 0C1 0 6 6
    006: 01 89 55 -> 0C4 1 5 5
    007: 01 C8 77 -> 0E4 0 7 7
    008: 01 89 77 -> 0C4 1 7 7
    009: 03 82 77 -> 1C1 0 7 7
    00A: 03 82 77 -> 1C1 0 7 7
    00B: 03 82 77 -> 1C1 0 7 7
    00C: 03 82 77 -> 1C1 0 7 7
    00D: 01 C8 88 -> 0E4 0 8 8
    00E: 01 B8 79 -> 0DC 0 7 9
    00F: 03 82 99 -> 1C1 0 9 9
    010: 01 82 99 -> 0C1 0 9 9
    011: 01 B8 61 -> 0DC 0 6 1
    012: 01 82 11 -> 0C1 0 1 1
    013: 01 96 11 -> 0CB 0 1 1
    014: 03 82 11 -> 1C1 0 1 1
    015: 03 82 11 -> 1C1 0 1 1
    016: 03 82 11 -> 1C1 0 1 1
    017: 03 82 11 -> 1C1 0 1 1
    018: 00 EE 18 -> 077 0 1 8 if /MOTIMEP JUMP 018
    019: 84 B8 11 -> 05C 0 1 1
    01A: 01 B8 72 -> 0DC 0 7 2
    01B: 00 C8 00 -> 064 0 0 0
    01C: 9C B8 88 -> 05C 0 8 8
    01D: 98 B8 88 -> 05C 0 8 8
    01E: 01 96 22 -> 0CB 0 2 2
    01F: 00 F4 1C -> 07A 0 1 C if NZ JUMP 01C
    020: 00 38 11 -> 01C 0 1 1
    021: 03 34 00 -> 19A 0 0 0
    022: 03 34 00 -> 19A 0 0 0
    023: 03 34 00 -> 19A 0 0 0
    024: 00 11 99 -> 008 1 9 9
    025: 02 34 00 -> 11A 0 0 0
    026: 84 B4 00 -> 05A 0 0 0
    027: 00 C8 00 -> 064 0 0 0
    028: 00 C8 00 -> 064 0 0 0
    029: 10 3E 00 -> 01F 0 0 0
    02A: 00 E5 3B -> 072 1 3 B if Z JUMP 13B
    02B: 00 05 00 -> 002 1 0 0
    02C: 9C B4 00 -> 05A 0 0 0
    02D: 98 B4 00 -> 05A 0 0 0
    02E: 00 EE 2E -> 077 0 2 E if /MOTIMEP JUMP 02E
    02F: 10 3E 00 -> 01F 0 0 0
    030: 00 05 00 -> 002 1 0 0
    031: 00 F4 35 -> 07A 0 3 5 if NZ JUMP 035
    032: A8 B8 55 -> 05C 0 5 5 (latch UC.HFLIP)
    033: A8 FE 35 -> 07F 0 3 5 if MOTIMEP JUMP 035 (latch UC.HFLIP)
    034: 00 E1 47 -> 070 1 4 7 JUMP 147
    035: 01 B8 72 -> 0DC 0 7 2
    036: 01 B8 8F -> 0DC 0 8 F
    037: 01 83 5F -> 0C1 1 5 F
    038: 84 B8 FF -> 05C 0 F F
    039: 00 EE 39 -> 077 0 3 9 if /MOTIMEP JUMP 039
    03A: 19 BE FF -> 0DF 0 F F
    03B: 00 E4 68 -> 072 0 6 8 if Z JUMP 068
    03C: 84 B8 88 -> 05C 0 8 8
    03D: 00 EE 3D -> 077 0 3 D if /MOTIMEP JUMP 03D
    03E: 19 BE AA -> 0DF 0 A A
    03F: 00 EE 3F -> 077 0 3 F if /MOTIMEP JUMP 03F
    040: 19 BE BB -> 0DF 0 B B
    041: 00 EE 41 -> 077 0 4 1 if /MOTIMEP JUMP 041
    042: 19 BE CC -> 0DF 0 C C
    043: 00 EE 43 -> 077 0 4 3 if /MOTIMEP JUMP 043
    044: 19 BE DD -> 0DF 0 D D
    045: 00 EE 45 -> 077 0 4 5 if /MOTIMEP JUMP 045
    046: 19 BE EE -> 0DF 0 E E
    047: 00 C8 00 -> 064 0 0 0
    048: 01 82 1F -> 0C1 0 1 F
    049: 84 B8 FF -> 05C 0 F F
    04A: 11 BE FF -> 0DF 0 F F
    04B: 00 C8 00 -> 064 0 0 0
    04C: 00 C8 00 -> 064 0 0 0
    04D: 9C B8 99 -> 05C 0 9 9
    04E: 90 B8 99 -> 05C 0 9 9
    04F: 00 C8 00 -> 064 0 0 0
    050: 84 B8 99 -> 05C 0 9 9
    051: 9C B8 AA -> 05C 0 A A
    052: 98 B8 AA -> 05C 0 A A
    053: 00 C8 00 -> 064 0 0 0
    054: 00 C8 00 -> 064 0 0 0
    055: 9C B8 BB -> 05C 0 B B
    056: 98 B8 BB -> 05C 0 B B
    057: 00 C8 00 -> 064 0 0 0
    058: 00 C8 00 -> 064 0 0 0
    059: 9C B8 CC -> 05C 0 C C
    05A: 98 B8 CC -> 05C 0 C C
    05B: 00 C8 00 -> 064 0 0 0
    05C: 00 C8 00 -> 064 0 0 0
    05D: 9C B8 DD -> 05C 0 D D
    05E: 98 B8 DD -> 05C 0 D D
    05F: 00 C8 00 -> 064 0 0 0
    060: 00 C8 00 -> 064 0 0 0
    061: 9C B8 EE -> 05C 0 E E
    062: 98 B8 EE -> 05C 0 E E
    063: 00 C8 00 -> 064 0 0 0
    064: 00 C8 00 -> 064 0 0 0
    065: 9C B8 FF -> 05C 0 F F
    066: 98 B8 FF -> 05C 0 F F
    067: 01 82 69 -> 0C1 0 6 9
    068: 01 82 68 -> 0C1 0 6 8
    069: 01 96 22 -> 0CB 0 2 2
    06A: 00 F4 36 -> 07A 0 3 6 if NZ JUMP 036
    06B: 01 B8 72 -> 0DC 0 7 2
    06C: 01 96 22 -> 0CB 0 2 2
    06D: 01 C8 44 -> 0E4 0 4 4
    06E: 01 96 44 -> 0CB 0 4 4
    06F: 01 B8 43 -> 0DC 0 4 3
    070: 02 B8 44 -> 15C 0 4 4
    071: 02 B8 44 -> 15C 0 4 4
    072: 02 B8 44 -> 15C 0 4 4
    073: 02 B8 44 -> 15C 0 4 4
    074: 02 B8 33 -> 15C 0 3 3
    075: 01 93 43 -> 0C9 1 4 3
    076: 02 B8 33 -> 15C 0 3 3
    077: 00 38 33 -> 01C 0 3 3
    078: 01 C8 33 -> 0E4 0 3 3
    079: 01 89 33 -> 0C4 1 3 3
    07A: 01 82 33 -> 0C1 0 3 3
    07B: 01 C8 00 -> 0E4 0 0 0
    07C: 00 B8 00 -> 05C 0 0 0
    07D: 00 F4 87 -> 07A 0 8 7 if NZ JUMP 087
    07E: 01 89 11 -> 0C4 1 1 1
    07F: 84 B8 11 -> 05C 0 1 1
    080: 00 EE 80 -> 077 0 8 0 if /MOTIMEP JUMP 080
    081: 11 BE 00 -> 0DF 0 0 0
    082: A4 B8 22 -> 05C 0 2 2 (latch UC.COLOR)
    083: 01 96 22 -> 0CB 0 2 2
    084: 00 F6 7C -> 07B 0 7 C if P JUMP 07C
    085: 8C B8 22 -> 05C 0 2 2
    086: 00 E0 86 -> 070 0 8 6 JUMP 086
    087: 84 B8 00 -> 05C 0 0 0
    088: 00 EE 88 -> 077 0 8 8 if /MOTIMEP JUMP 088
    089: 19 BE 55 -> 0DF 0 5 5
    08A: A8 B8 55 -> 05C 0 5 5 (latch UC.HFLIP)
    08B: 03 82 55 -> 1C1 0 5 5
    08C: 00 C8 00 -> 064 0 0 0
    08D: 19 BE FF -> 0DF 0 F F
    08E: A4 B8 FF -> 05C 0 F F (latch UC.COLOR)
    08F: 00 C8 00 -> 064 0 0 0
    090: 00 C8 00 -> 064 0 0 0
    091: 19 BE 66 -> 0DF 0 6 6
    092: B0 C8 00 -> 064 0 0 0 (latch UC.FORMAT)
    093: 00 C8 00 -> 064 0 0 0
    094: 00 C8 00 -> 064 0 0 0
    095: 19 BE 77 -> 0DF 0 7 7
    096: 00 C8 00 -> 064 0 0 0
    097: 00 C8 00 -> 064 0 0 0
    098: 00 C8 00 -> 064 0 0 0
    099: 19 BE 88 -> 0DF 0 8 8
    09A: 00 C8 00 -> 064 0 0 0
    09B: 00 C8 00 -> 064 0 0 0
    09C: 00 C8 00 -> 064 0 0 0
    09D: 19 BE 00 -> 0DF 0 0 0
    09E: 84 B8 55 -> 05C 0 5 5
    09F: 00 C8 00 -> 064 0 0 0
    0A0: 00 C8 00 -> 064 0 0 0
    0A1: 09 BE DD -> 0DF 0 D D
    0A2: 00 C8 00 -> 064 0 0 0
    0A3: 00 C8 00 -> 064 0 0 0
    0A4: 09 BE EE -> 0DF 0 E E
    0A5: 01 C8 AA -> 0E4 0 A A
    0A6: 01 C8 BB -> 0E4 0 B B
    0A7: 09 BE 99 -> 0DF 0 9 9
    0A8: 01 B8 8F -> 0DC 0 8 F
    0A9: 01 82 FF -> 0C1 0 F F
    0AA: 09 BE 55 -> 0DF 0 5 5
    0AB: 01 C8 CC -> 0E4 0 C C
    0AC: 00 B8 DD -> 05C 0 D D
    0AD: 00 F6 B1 -> 07B 0 B 1 if P JUMP 0B1
    0AE: 01 A9 DD -> 0D4 1 D D
    0AF: 01 82 4C -> 0C1 0 4 C
    0B0: 01 89 CC -> 0C4 1 C C
    0B1: 01 82 CC -> 0C1 0 C C
    0B2: 00 B8 EE -> 05C 0 E E
    0B3: 00 F6 B7 -> 07B 0 B 7 if P JUMP 0B7
    0B4: 01 A9 EE -> 0D4 1 E E
    0B5: 01 82 4C -> 0C1 0 4 C
    0B6: 01 89 CC -> 0C4 1 C C
    0B7: 03 82 CC -> 1C1 0 C C
    0B8: 01 82 FF -> 0C1 0 F F
    0B9: 43 86 DA -> 1C3 0 D A
    0BA: 43 86 EB -> 1C3 0 E B
    0BB: 01 82 FF -> 0C1 0 F F
    0BC: 43 86 DA -> 1C3 0 D A
    0BD: 43 86 EB -> 1C3 0 E B
    0BE: 01 82 FF -> 0C1 0 F F
    0BF: 43 86 DA -> 1C3 0 D A
    0C0: 43 86 EB -> 1C3 0 E B
    0C1: 01 82 FF -> 0C1 0 F F
    0C2: 43 86 DA -> 1C3 0 D A
    0C3: 43 86 EB -> 1C3 0 E B
    0C4: 01 82 FF -> 0C1 0 F F
    0C5: 43 86 DA -> 1C3 0 D A
    0C6: 43 86 EB -> 1C3 0 E B
    0C7: 01 82 FF -> 0C1 0 F F
    0C8: 43 86 DA -> 1C3 0 D A
    0C9: 43 86 EB -> 1C3 0 E B
    0CA: 01 82 FF -> 0C1 0 F F
    0CB: 43 86 DA -> 1C3 0 D A
    0CC: 43 86 EB -> 1C3 0 E B
    0CD: 01 82 FF -> 0C1 0 F F
    0CE: 41 86 DA -> 0C3 0 D A
    0CF: 41 86 EB -> 0C3 0 E B
    0D0: 02 B8 DD -> 15C 0 D D
    0D1: 02 B8 EE -> 15C 0 E E
    0D2: 01 82 FF -> 0C1 0 F F
    0D3: 41 86 DA -> 0C3 0 D A
    0D4: 41 86 EB -> 0C3 0 E B
    0D5: 02 B8 DD -> 15C 0 D D
    0D6: 02 B8 EE -> 15C 0 E E
    0D7: 01 82 FF -> 0C1 0 F F
    0D8: 41 86 DA -> 0C3 0 D A
    0D9: 41 86 EB -> 0C3 0 E B
    0DA: 02 B8 DD -> 15C 0 D D
    0DB: 02 B8 EE -> 15C 0 E E
    0DC: 01 82 FF -> 0C1 0 F F
    0DD: 41 86 DA -> 0C3 0 D A
    0DE: 41 86 EB -> 0C3 0 E B
    0DF: 00 B8 CC -> 05C 0 C C
    0E0: 00 F6 E2 -> 07B 0 E 2 if P JUMP 0E2
    0E1: 01 A9 AA -> 0D4 1 A A
    0E2: 01 82 CC -> 0C1 0 C C
    0E3: 00 F6 E5 -> 07B 0 E 5 if P JUMP 0E5
    0E4: 01 A9 BB -> 0D4 1 B B
    0E5: 01 C8 CC -> 0E4 0 C C
    0E6: 01 89 CC -> 0C4 1 C C
    0E7: 03 82 CC -> 1C1 0 C C
    0E8: 03 82 CC -> 1C1 0 C C
    0E9: 03 82 CC -> 1C1 0 C C
    0EA: 01 B8 4F -> 0DC 0 4 F
    0EB: 03 82 FF -> 1C1 0 F F
    0EC: 00 D2 48 -> 069 0 4 8
    0ED: 00 E5 19 -> 072 1 1 9 if Z JUMP 119
    0EE: 02 B8 88 -> 15C 0 8 8
    0EF: 02 B8 88 -> 15C 0 8 8
    0F0: 02 B8 88 -> 15C 0 8 8
    0F1: 02 B8 88 -> 15C 0 8 8
    0F2: 01 80 88 -> 0C0 0 8 8
    0F3: 84 B8 88 -> 05C 0 8 8
    0F4: 00 EE F4 -> 077 0 F 4 if /MOTIMEP JUMP 0F4
    0F5: 19 BE 88 -> 0DF 0 8 8
    0F6: AC B8 88 -> 05C 0 8 8 (latch UC.RATE)
    0F7: 01 82 88 -> 0C1 0 8 8
    0F8: 02 B8 88 -> 15C 0 8 8
    0F9: 00 F8 FC -> 07C 0 F C if /BLT.HFLIP JUMP 0FC
    0FA: 01 82 A6 -> 0C1 0 A 6
    0FB: 00 E0 FD -> 070 0 F D JUMP 0FD
    0FC: 01 93 A6 -> 0C9 1 A 6
    0FD: 01 93 B7 -> 0C9 1 B 7
    0FE: B0 B8 99 -> 05C 0 9 9 (latch UC.FORMAT)
    0FF: 84 B8 55 -> 05C 0 5 5
    100: 01 C8 EE -> 0E4 0 E E
    101: 00 C8 00 -> 064 0 0 0
    102: 09 BE DD -> 0DF 0 D D
    103: 00 E6 7C -> 073 0 7 C if N JUMP 07C
    104: 00 93 F7 -> 049 1 F 7
    105: 00 ED 0B -> 076 1 0 B if C JUMP 10B
    106: B4 B8 DD -> 05C 0 D D (latch UC.TRANS)
    107: B8 B8 77 -> 05C 0 7 7 (latch UC.XYPOS)
    108: A0 B8 33 -> 05C 0 3 3 (latch UC.RASCAS)
    109: B8 B8 66 -> 05C 0 6 6 (latch UC.XYPOS)
    10A: BC C8 00 -> 064 0 0 0 (latch UC.SCAN)
    10B: 01 82 C7 -> 0C1 0 C 7
    10C: 01 82 8E -> 0C1 0 8 E
    10D: 00 D2 4E -> 069 0 4 E
    10E: 00 E5 14 -> 072 1 1 4 if Z JUMP 114
    10F: 01 93 4E -> 0C9 1 4 E
    110: 01 96 EE -> 0CB 0 E E
    111: 01 83 D5 -> 0C1 1 D 5
    112: 00 FD 14 -> 07E 1 1 4 if NC JUMP 114
    113: 01 89 99 -> 0C4 1 9 9
    114: 00 FB 14 -> 07D 1 1 4 if BLT.SCAN JUMP 114
    115: A0 C8 00 -> 064 0 0 0 (latch UC.RASCAS)
    116: 84 B8 55 -> 05C 0 5 5
    117: B0 B8 99 -> 05C 0 9 9 (latch UC.FORMAT)
    118: 00 E1 02 -> 070 1 0 2 JUMP 102
    119: AC B8 88 -> 05C 0 8 8 (latch UC.RATE)
    11A: 00 F9 1D -> 07C 1 1 D if /BLT.HFLIP JUMP 11D
    11B: 01 82 A6 -> 0C1 0 A 6
    11C: 00 E1 1E -> 070 1 1 E JUMP 11E
    11D: 01 93 A6 -> 0C9 1 A 6
    11E: 01 93 B7 -> 0C9 1 B 7
    11F: B0 B8 99 -> 05C 0 9 9 (latch UC.FORMAT)
    120: 84 B8 55 -> 05C 0 5 5
    121: 01 B8 4E -> 0DC 0 4 E
    122: 01 89 EE -> 0C4 1 E E
    123: 02 B8 EE -> 15C 0 E E
    124: 09 BE DD -> 0DF 0 D D
    125: 00 E6 7C -> 073 0 7 C if N JUMP 07C
    126: 01 82 8E -> 0C1 0 8 E
    127: 00 D2 4E -> 069 0 4 E
    128: 00 E5 33 -> 072 1 3 3 if Z JUMP 133
    129: 01 93 4E -> 0C9 1 4 E
    12A: 01 96 EE -> 0CB 0 E E
    12B: 00 93 F7 -> 049 1 F 7
    12C: 00 ED 32 -> 076 1 3 2 if C JUMP 132
    12D: B4 B8 DD -> 05C 0 D D (latch UC.TRANS)
    12E: B8 B8 77 -> 05C 0 7 7 (latch UC.XYPOS)
    12F: A0 B8 33 -> 05C 0 3 3 (latch UC.RASCAS)
    130: B8 B8 66 -> 05C 0 6 6 (latch UC.XYPOS)
    131: BC C8 00 -> 064 0 0 0 (latch UC.SCAN)
    132: 01 82 C7 -> 0C1 0 C 7
    133: 01 83 D5 -> 0C1 1 D 5
    134: 00 FD 36 -> 07E 1 3 6 if NC JUMP 136
    135: 01 89 99 -> 0C4 1 9 9
    136: 00 FB 36 -> 07D 1 3 6 if BLT.SCAN JUMP 136
    137: A0 C8 00 -> 064 0 0 0 (latch UC.RASCAS)
    138: 84 B8 55 -> 05C 0 5 5
    139: B0 B8 99 -> 05C 0 9 9 (latch UC.FORMAT)
    13A: 00 E1 24 -> 070 1 2 4 JUMP 124
    13B: 08 3E 00 -> 01F 0 0 0
    13C: 00 EF 3C -> 077 1 3 C if /MOTIMEP JUMP 13C
    13D: 18 3E 00 -> 01F 0 0 0
    13E: 00 E5 75 -> 072 1 7 5 if Z JUMP 175
    13F: 00 C8 00 -> 064 0 0 0
    140: 9C B8 44 -> 05C 0 4 4
    141: 98 B8 44 -> 05C 0 4 4
    142: 00 C8 00 -> 064 0 0 0
    143: 00 C8 00 -> 064 0 0 0
    144: 9C B8 11 -> 05C 0 1 1
    145: 98 B8 11 -> 05C 0 1 1
    146: 00 E1 5A -> 070 1 5 A JUMP 15A
    147: 00 38 11 -> 01C 0 1 1
    148: 03 34 00 -> 19A 0 0 0
    149: 03 34 00 -> 19A 0 0 0
    14A: 03 34 00 -> 19A 0 0 0
    14B: 00 11 99 -> 008 1 9 9
    14C: 00 EF 4C -> 077 1 4 C if /MOTIMEP JUMP 14C
    14D: 02 34 00 -> 11A 0 0 0
    14E: 84 B4 00 -> 05A 0 0 0
    14F: 01 C8 00 -> 0E4 0 0 0
    150: 9C B8 00 -> 05C 0 0 0
    151: 98 B8 00 -> 05C 0 0 0
    152: 00 C8 00 -> 064 0 0 0
    153: 00 C8 00 -> 064 0 0 0
    154: 9C B8 11 -> 05C 0 1 1
    155: 98 B8 11 -> 05C 0 1 1
    156: 00 C8 00 -> 064 0 0 0
    157: 00 C8 00 -> 064 0 0 0
    158: 9C B8 44 -> 05C 0 4 4
    159: 98 B8 44 -> 05C 0 4 4
    15A: 09 BE DD -> 0DF 0 D D
    15B: 01 82 8E -> 0C1 0 8 E
    15C: 00 D2 4E -> 069 0 4 E
    15D: 00 E5 67 -> 072 1 6 7 if Z JUMP 167
    15E: 01 93 4E -> 0C9 1 4 E
    15F: 01 96 EE -> 0CB 0 E E
    160: 00 93 F7 -> 049 1 F 7
    161: 00 ED 67 -> 076 1 6 7 if C JUMP 167
    162: B4 B8 DD -> 05C 0 D D (latch UC.TRANS)
    163: B8 B8 77 -> 05C 0 7 7 (latch UC.XYPOS)
    164: A0 B8 33 -> 05C 0 3 3 (latch UC.RASCAS)
    165: B8 B8 66 -> 05C 0 6 6 (latch UC.XYPOS)
    166: BC C8 00 -> 064 0 0 0 (latch UC.SCAN)
    167: 01 82 C7 -> 0C1 0 C 7
    168: 01 83 D5 -> 0C1 1 D 5
    169: 00 FD 6C -> 07E 1 6 C if NC JUMP 16C
    16A: 01 89 99 -> 0C4 1 9 9
    16B: 01 C8 00 -> 0E4 0 0 0
    16C: 01 96 00 -> 0CB 0 0 0
    16D: 00 F5 6C -> 07A 1 6 C if NZ JUMP 16C
    16E: A0 C8 00 -> 064 0 0 0 (latch UC.RASCAS)
    16F: 84 B8 55 -> 05C 0 5 5
    170: B0 B8 99 -> 05C 0 9 9 (latch UC.FORMAT)
    171: 01 C8 00 -> 0E4 0 0 0
    172: 01 96 00 -> 0CB 0 0 0
    173: 00 F5 72 -> 07A 1 7 2 if NZ JUMP 172
    174: 00 E1 5A -> 070 1 5 A JUMP 15A
    175: 84 B8 88 -> 05C 0 8 8
    176: 00 EF 76 -> 077 1 7 6 if /MOTIMEP JUMP 176
    177: 19 BE AA -> 0DF 0 A A
    178: B0 B8 AA -> 05C 0 A A (latch UC.FORMAT)
    179: 01 C8 77 -> 0E4 0 7 7
    17A: 84 B8 77 -> 05C 0 7 7
    17B: 01 C8 BB -> 0E4 0 B B
    17C: 00 C8 00 -> 064 0 0 0
    17D: 00 C8 00 -> 064 0 0 0
    17E: 00 C8 00 -> 064 0 0 0
    17F: 08 3E 00 -> 01F 0 0 0
    180: 01 80 BB -> 0C0 0 B B
    181: 01 89 77 -> 0C4 1 7 7
    182: 00 F5 7F -> 07A 1 7 F if NZ JUMP 17F
    183: 84 B8 AA -> 05C 0 A A
    184: 00 C8 00 -> 064 0 0 0
    185: 00 C8 00 -> 064 0 0 0
    186: 9C B8 BB -> 05C 0 B B
    187: 98 B8 BB -> 05C 0 B B
    188: 01 96 AA -> 0CB 0 A A
    189: 00 F7 8B -> 07B 1 8 B if P JUMP 18B
    18A: 00 E1 8A -> 070 1 8 A JUMP 18A
    18B: 00 C8 00 -> 064 0 0 0
    18C: 00 E1 78 -> 070 1 7 8 JUMP 178

***************************************************************************/