Initial commit.

This commit is contained in:
bbraun 2011-12-03 01:31:42 +00:00
commit 919af0757e
13 changed files with 534 additions and 0 deletions

3
ChangeLog Normal file
View File

@ -0,0 +1,3 @@
devel
2011-12-02 Rob Braun bbraun@synack.net
* Initial creation. Includes ROMdisk driver installation, checksum calculation & update.

8
LICENSE Normal file
View File

@ -0,0 +1,8 @@
The MIT License (MIT)
Copyright (c) 2011 Rob Braun
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

7
Makefile Normal file
View File

@ -0,0 +1,7 @@
CFLAGS := -Wall -Werror "-Ilib/"
dir_names := lib cli
all: $(dir_names:%=%_all)
clean: $(dir_names:%=%_clean)
include $(dir_names:%=%/Makefile.inc)

3
README Normal file
View File

@ -0,0 +1,3 @@
This is a tool and associated library intended to apply known ROM modifications to 68k Macintosh ROMs.
It currently knows about Mac II, IIx, SE/30 ROMs as "24bit" ROMs, and IIsi/IIci and higher ROMs, although it is most tested with machines that have a ROM SIMM slot, such as the Mac II, IIx, SE/30, IIsi, IIci, Quadra 700, etc.

14
cli/Makefile.inc Normal file
View File

@ -0,0 +1,14 @@
ROMPATCHER_SRCS := main.c
ROMPATCHER_SRCS := $(patsubst %, cli/%, $(ROMPATCHER_SRCS))
ROMPATCHER_EXE := cli/macrompatcher
cli_all: $(ROMPATCHER_EXE)
cli_clean:
rm -f $(ROMPATCHER_SRCS:%.c=%.o)
rm -f $(ROMPATCHER_EXE)
$(ROMPATCHER_EXE): $(ROMPATCHER_SRCS:%.c=%.o) $(ROMLIB_A)
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(ROMLIB_A)
cli/%o: cli/%.c

162
cli/main.c Normal file
View File

@ -0,0 +1,162 @@
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <getopt.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include "macrompatcher.h"
#define MINROMSIZE 262144 /* 256k is the smallest we know how to use */
#define MAXROMSIZE 2097152 /* 2MB is the largest we know what to do with */
void usage(char *progname) {
fprintf(stderr, "Usage: %s [OPTION]\n", progname);
fprintf(stderr, "Options:\n");
fprintf(stderr, " -f, --infile=FILE Specify the ROM file to operate on\n");
fprintf(stderr, " -o, --outfile=FILE Specify the filename to write the modified ROM to\n");
fprintf(stderr, " -c, --checksum Compute and print the checksum\n");
fprintf(stderr, " -r, --romdiskdrvr Install the ROMdisk driver\n");
return;
}
int main(int argc, char *argv[]) {
char c;
int loptind;
int print_checksum = 0;
int apply_romdisk = 0;
char *romname = NULL;
int romfd;
char *outname = NULL;
RomErr err = 0;
struct option o[] = {
{"checksum", 0, 0, 'c'},
{"infile", 1, 0, 'f'},
{"outfile", 1, 0, 'o'},
{"romdiskdrvr", 0, 0, 'r'},
{"help", 0, 0, 'h'},
{0, 0, 0, 0}
};
RomCtx *rom = NULL;
struct stat sb;
if(argc < 2) {
usage(argv[0]);
exit(1);
}
while( (c = getopt_long(argc, argv, "chf:o:r", o, &loptind)) != -1 ) {
switch(c) {
case 'c': print_checksum = 1; break;
case 'f': romname = optarg; break;
case 'o': outname = optarg; break;
case 'r': apply_romdisk = 1; break;
case 'h':
default:
usage(argv[0]);
exit(1);
};
}
if(romname == NULL) {
fprintf(stderr, "No ROM file specified.\n");
usage(argv[0]);
exit(1);
}
romfd = open(romname, O_RDONLY);
if(romfd < 0) {
fprintf(stderr, "Could not open ROM %s: %d %s\n", romname, errno, strerror(errno));
exit(1);
}
rom = calloc(1, sizeof(RomCtx));
if(!rom) {
fprintf(stderr, "Could not allocate memory for ROM context\n");
exit(1);
}
if(fstat(romfd, &sb) < 0) {
fprintf(stderr, "Could not fstat ROM file descriptor\n");
exit(1);
}
if(sb.st_size < MINROMSIZE) {
fprintf(stderr, "ROM is too small. %d is smaller than minimum ROM size of %d\n", (int)sb.st_size, MINROMSIZE);
exit(1);
}
if(sb.st_size > MAXROMSIZE) {
fprintf(stderr, "ROM is too big. %d is bigger than maximum ROM size of %d\n", (int)sb.st_size, MAXROMSIZE);
exit(1);
}
rom->data = calloc(1, sb.st_size);
if(!rom->data) {
fprintf(stderr, "Could not allocate RAM for the ROM image\n");
exit(1);
}
rom->datasize = rom->filesize = sb.st_size;
if(sb.st_size < (512*1024)) {
rom->type = e24bit;
}else{
rom->type = e32bit;
}
errno = 0;
if(read(romfd, rom->data, rom->datasize) < rom->datasize) {
fprintf(stderr, "Could not read ROM image into RAM: %d %s\n", errno, strerror(errno));
exit(1);
}
close(romfd);
if(apply_romdisk) {
err = InstallRomdiskDrvr(rom);
if(err != eSuccess) {
fprintf(stderr, "Error installing ROMdisk driver: %s\n", GetROMErrString(err));
exit(1);
}
}
if(print_checksum) {
uint32_t checksum = 0;
err = GetChecksum(rom, &checksum);
if(err != eSuccess) {
fprintf(stderr, "Error computing checksum: %s\n", GetROMErrString(err));
} else {
printf("Checksum: %#x\n", checksum);
}
}
if(outname) {
do {
RomErr err = UpdateChecksum(rom);
if(err != eSuccess) {
fprintf(stderr, "Error updating checksum: %s\n", GetROMErrString(err));
break;
}
int outfd = open(outname, O_WRONLY | O_TRUNC | O_CREAT, 0644);
if(outfd < 0) {
fprintf(stderr, "Error opening output file %s: %d %s\n", outname, errno, strerror(errno));
break;
}
if(write(outfd, rom->data, rom->datasize) < rom->datasize) {
fprintf(stderr, "Error writing to output file %s: %d %s\n", outname, errno, strerror(errno));
}
close(outfd);
}while(0);
}
if(rom) {
free(rom->data);
free(rom);
}
exit(0);
}

18
lib/Makefile.inc Normal file
View File

@ -0,0 +1,18 @@
ROMLIB_SRCS := checksum.c err.c locate_drvr.c romdisk.c
ROMLIB_A := lib/libmacrom.a
ROMLIB_SRCS := $(patsubst %, lib/%, $(ROMLIB_SRCS))
lib_all: $(ROMLIB_A)
lib_clean:
rm -f $(ROMLIB_SRCS:%.c=%.o)
rm -f $(ROMLIB_A)
$(ROMLIB_A): $(ROMLIB_SRCS:%.c=%.o)
$(AR) cvr $@ $+
# $(RANLIB) $@
lib/%.o: lib/%.c
lib/%.c: lib/macrompatcher.h
lib/romdisk.c: lib/macrompatcher.h lib/romdrv.h

30
lib/checksum.c Normal file
View File

@ -0,0 +1,30 @@
#include <stdlib.h>
#include <arpa/inet.h>
#include "macrompatcher.h"
RomErr GetChecksum(RomCtx *rom, uint32_t *checksum) {
uint8_t *tmpptr = NULL;
size_t i;
if(!rom || !rom->data || !checksum) return eParmErr;
tmpptr = rom->data+4;
*checksum = 0;
for(i = 0; i < rom->filesize; i++) {
*checksum += tmpptr[i++] << 8;
*checksum += tmpptr[i];
}
return eSuccess;
}
RomErr UpdateChecksum(RomCtx *rom) {
uint32_t checksum;
RomErr ret;
ret = GetChecksum(rom, &checksum);
if(ret != eSuccess) return ret;
*(uint32_t*)(rom->data) = htonl(checksum);
return eSuccess;
}

11
lib/err.c Normal file
View File

@ -0,0 +1,11 @@
#include "macrompatcher.h"
const char *GetROMErrString(RomErr err) {
switch(err) {
case eSuccess: return "Success!";
case eNotSupp: return "Modification not supported for this ROM";
case eNotFound: return "Couldn't find where to apply the modification";
case eParmErr: return "Parameter error";
};
return "Unknown error";
}

98
lib/locate_drvr.c Normal file
View File

@ -0,0 +1,98 @@
#include <arpa/inet.h>
#include <stdio.h>
#include "macrompatcher.h"
RomErr GetDRVROffset(RomCtx *rom, uint16_t drvrid, uint32_t *offset) {
uint8_t *tmpptr;
RomErr ret = eNotFound;
if(!rom || !rom->data || !offset) return eParmErr;
// 0x1A stores the 4 byte location of the resources
tmpptr = rom->data + 0x1A;
uint32_t resourcesoffset = *(uint32_t*)tmpptr;
resourcesoffset = ntohl(resourcesoffset);
if(resourcesoffset > rom->datasize) return eNotFound;
tmpptr = rom->data + resourcesoffset;
if(rom->type == e32bit) {
uint32_t indirect = *(uint32_t*)tmpptr;
indirect = ntohl(indirect);
tmpptr = rom->data + indirect;
do {
uint32_t nextoff;
uint32_t data;
uint32_t type;
uint16_t resid;
data = *(uint32_t*)(tmpptr+12);
data = ntohl(data);
type = *(uint32_t*)(tmpptr+16);
type = ntohl(type);
resid = *(uint16_t*)(tmpptr+20);
resid = ntohs(resid);
if(type == 0x44525652 && resid == drvrid) {
*offset = data;
ret = eSuccess;
break;
}
nextoff = *(uint32_t*)(tmpptr+8);
nextoff = ntohl(nextoff);
if(nextoff > rom->datasize) break;
tmpptr = rom->data + nextoff;
}while(1);
} else if(rom->type == e24bit) {
uint16_t typelistoff = *(uint16_t*)(tmpptr+28);
typelistoff = ntohs(typelistoff);
tmpptr += 4;
tmpptr += typelistoff;
uint16_t numresourcetypes = *(uint16_t*)(tmpptr);;
numresourcetypes = ntohs(numresourcetypes);
tmpptr += 2;
uint16_t drvroff = 0;
uint16_t numdrvrs = 0;
int i;
for(i = 0; i < 11; i++) {
uint32_t resourceid;
uint16_t numresources;
uint16_t listoffset;
resourceid = *(uint32_t*)(tmpptr + (i*8));
resourceid = ntohl(resourceid);
if(resourceid != 0x44525652) continue; /* DRVR 4char const */
numresources = *(uint16_t*)(tmpptr + (i*8) + 4);
listoffset = *(uint16_t*)(tmpptr + (i*8) + 6);
numresources = ntohs(numresources);
listoffset = ntohs(listoffset);
numdrvrs = numresources;
drvroff = listoffset;
break;
}
if(!drvroff) return eNotFound;
tmpptr = rom->data + resourcesoffset + typelistoff + drvroff + 4;
for(i = 0; i <= numdrvrs; i++) {
uint16_t resid;
resid = *(uint16_t*)(tmpptr + (i*12));
resid = ntohs(resid);
if(resid == drvrid) {
uint32_t attroff;
attroff = *(uint32_t*)(tmpptr + (i*12) + 4);
attroff = ntohl(attroff);
attroff &= 0x00FFFFFF;
*offset = attroff;
ret = eSuccess;
break;
}
}
}
return ret;
}

65
lib/macrompatcher.h Normal file
View File

@ -0,0 +1,65 @@
#ifndef __MACROMPATCHER_H__
#define __MACROMPATCHER_H__ 1
#include <stdint.h>
/* Known types of ROM images. */
enum RomType {
eUnknown = 0,
/* 24bit ROMs are Mac II, IIx, SE/30 ROMs that are normally 256KB */
e24bit = 1,
/* 32bit ROMs are IIsi, IIci, and higher that are normally
* 512KB or larger.
*/
e32bit = 2
};
typedef enum RomType RomType;
struct romctx {
/* pointer to the in-memory instance of the ROM, ready to be modified.
* This pointer can change, if something needs to increase the size
* of the ROM, it can be realloc'd to be larger.
*/
uint8_t *data;
/* Size of the memory pointed to by data above. If the ROM image grows
* via realloc, this needs to be updated.
*/
uint32_t datasize;
/* The original filesize that was read in from disk. If the ROM image
* size hasn't changed in the modification proces, this will == datasize
*/
uint32_t filesize;
/* Represents what type the ROM is. Some ROMs are structured
* differently, so modification routines will need to key off this
* to determine how and if they can perform their modification.
*/
RomType type;
};
typedef struct romctx RomCtx;
/* Standard error types the ROM modification routines can return */
enum RomErr {
eSuccess = 0,
/* The modification is not supported for the given ROM */
eNotSupp = 1,
/* Couldn't find where to apply the patch in the given ROM */
eNotFound = 2,
/* Error with one of the parameters */
eParmErr = 3
};
typedef enum RomErr RomErr;
RomErr GetChecksum(RomCtx *rom, uint32_t *checksum);
RomErr UpdateChecksum(RomCtx *rom);
const char *GetROMErrString(RomErr err);
RomErr GetDRVROffset(RomCtx *rom, uint16_t drvrid, uint32_t *offset);
RomErr InstallRomdiskDrvr(RomCtx *rom);
#endif /* __MACROMPATCHER_H__ */

29
lib/romdisk.c Normal file
View File

@ -0,0 +1,29 @@
#include <stdlib.h>
#include <string.h>
#include "macrompatcher.h"
#include "romdrv.h"
/* romdrv.h defines a ROM disk driver that will present a disk image starting
* at 0x00880000 (512kb in to the ROM) and is 512kb in size, as a bootable
* drive.
* This function installs the driver in place of the .Sony floppy driver,
* DRVR resource ID 4.
*/
RomErr InstallRomdiskDrvr(RomCtx *rom) {
RomErr err;
uint32_t sonyoffset;
uint8_t *tmpptr;
if(!rom || !rom->data) return eParmErr;
err = GetDRVROffset(rom, 4, &sonyoffset);
if(err != eSuccess) return err;
tmpptr = rom->data + sonyoffset;
memcpy(tmpptr, romdrv, sizeof(romdrv));
return eSuccess;
}

86
lib/romdrv.h Normal file
View File

@ -0,0 +1,86 @@
unsigned char romdrv[] = {
79,0,0,0,0,0,0,0,0,50,0,54,0,58,0,62,0,66,5,46,83,111,110,121,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,112,0,96,14,112,1,96,34,112,
2,96,30,112,3,96,26,112,4,47,12,63,0,47,9,47,8,78,186,0,64,78,186,4,192,
79,239,0,10,40,95,78,117,72,231,0,200,63,0,47,9,47,8,78,186,0,38,78,186,
4,166,79,239,0,10,76,223,19,0,176,124,0,1,103,14,8,40,0,1,0,6,102,4,47,
56,8,252,78,117,112,0,78,117,65,250,255,162,209,252,0,0,133,84,32,8,160,
85,193,140,78,117,78,117,34,124,0,0,3,8,114,1,32,105,0,2,96,14,178,104,
0,6,110,6,50,40,0,6,82,65,32,80,32,8,102,238,48,1,78,117,78,86,0,0,66,
128,48,46,0,10,72,64,48,46,0,8,32,110,0,12,160,78,78,94,78,117,78,86,
255,252,47,10,45,124,0,0,1,52,255,252,36,124,0,0,8,238,32,10,103,8,74,
146,103,4,32,82,78,144,32,110,255,252,32,80,32,104,0,12,49,124,0,1,0,
10,36,95,78,94,78,117,78,86,0,0,72,231,24,48,38,46,0,12,40,60,0,0,1,66,
38,124,0,0,1,52,112,30,167,30,36,72,66,82,21,124,255,128,0,2,21,124,0,
8,0,3,66,42,0,4,66,42,0,5,66,170,0,6,53,124,0,1,0,10,78,186,255,76,53,
64,0,12,32,67,53,104,0,24,0,14,66,106,0,16,53,124,4,0,0,18,66,106,0,20,
112,16,167,34,34,67,35,72,0,20,32,67,32,104,0,20,160,41,32,67,32,104,
0,20,38,144,32,83,48,170,0,12,32,83,33,124,0,136,0,0,0,2,32,83,33,124,
0,8,0,0,0,6,32,83,66,104,0,10,112,14,167,30,34,83,35,72,0,12,32,83,32,
104,0,12,66,144,32,83,32,104,0,12,49,124,0,1,0,4,65,250,255,20,34,83,
34,105,0,12,35,72,0,6,32,83,32,104,0,12,49,124,0,1,0,10,32,83,32,104,
0,12,66,104,0,12,32,67,66,168,0,16,72,106,0,6,63,42,0,12,63,42,0,14,78,
186,254,196,32,83,32,104,0,12,160,51,32,110,0,8,66,104,0,16,32,68,66,
80,112,0,80,79,76,223,12,24,78,94,78,117,78,86,255,252,72,231,31,48,36,
110,0,8,46,46,0,12,45,124,0,0,1,66,255,252,122,0,124,0,48,42,0,44,2,64,
0,15,103,10,83,64,103,14,85,64,103,16,96,24,32,71,42,40,0,16,96,16,42,
42,0,46,96,10,32,71,42,40,0,16,218,170,0,46,74,133,108,4,124,206,96,120,
12,133,0,8,0,0,111,4,124,206,96,108,32,5,208,170,0,36,12,128,0,8,0,0,
111,4,124,206,96,90,48,42,0,6,2,64,0,255,85,64,103,6,83,64,103,72,96,
72,48,42,0,44,2,64,0,64,102,62,38,124,0,136,0,0,215,197,38,42,0,32,40,
42,0,36,96,6,32,67,82,131,16,155,32,4,83,132,74,128,102,242,37,106,0,
36,0,40,32,5,208,170,0,36,32,71,33,64,0,16,32,71,37,104,0,16,0,46,96,
2,124,213,53,70,0,16,32,110,255,252,48,134,48,42,0,6,2,64,2,0,103,4,0,
70,0,1,48,6,76,223,12,248,78,94,78,117,78,86,0,0,47,11,34,110,0,8,38,
124,0,0,1,66,36,60,0,0,1,52,114,239,12,105,0,1,0,26,102,6,112,1,96,0,
0,206,12,105,0,5,0,26,102,6,114,0,96,0,0,170,12,105,0,6,0,26,102,6,114,
0,96,0,0,156,12,105,0,9,0,26,102,6,114,0,96,0,0,142,12,105,0,8,0,26,102,
6,114,0,96,0,0,128,12,105,0,65,0,26,102,14,32,66,32,80,49,124,0,1,0,10,
114,0,96,104,12,105,0,7,0,26,102,4,114,239,96,92,12,105,0,21,0,26,102,
12,65,236,128,0,35,72,0,28,114,0,96,72,12,105,0,22,0,26,102,12,65,236,
129,2,35,72,0,28,114,0,96,52,12,105,0,23,0,26,102,16,51,124,0,1,0,28,
51,124,0,6,0,30,114,0,96,28,12,105,0,24,0,26,102,20,66,105,0,28,51,124,
0,4,0,30,66,105,0,32,66,105,0,34,114,0,51,65,0,16,54,129,48,41,0,6,2,
64,2,0,103,4,0,65,0,1,48,1,38,95,78,94,78,117,78,86,0,0,72,231,28,48,
36,110,0,8,40,60,0,0,1,52,118,238,42,60,0,0,1,66,48,42,0,26,93,64,103,
14,85,64,103,68,85,64,103,0,0,138,96,0,0,162,74,106,0,28,111,48,53,124,
0,1,0,28,66,106,0,30,66,106,0,32,53,124,0,4,0,34,66,106,0,36,66,106,0,
38,66,106,0,40,66,106,0,42,66,106,0,44,53,124,0,64,0,46,96,108,118,206,
96,104,38,74,71,235,0,28,66,83,23,124,255,128,0,2,23,124,0,8,0,3,66,43,
0,4,66,43,0,5,66,171,0,6,55,124,0,1,0,10,32,68,32,80,55,80,0,12,32,110,
0,12,55,104,0,24,0,14,66,107,0,16,55,124,4,0,0,18,66,107,0,20,118,0,96,
30,53,124,0,255,0,28,53,124,0,255,0,30,53,124,0,255,0,32,53,124,0,255,
0,34,118,0,96,2,118,238,53,67,0,16,32,69,48,131,48,42,0,6,2,64,2,0,103,
4,0,67,0,1,48,67,32,8,76,223,12,56,78,94,78,117,78,86,255,252,45,124,
0,0,1,66,255,252,32,110,255,252,66,80,112,0,78,94,78,117,78,86,0,0,72,
231,0,48,38,110,0,8,36,110,0,12,48,46,0,16,12,64,0,4,98,80,208,64,48,
59,0,6,78,251,0,2,0,10,0,22,0,34,0,46,0,58,47,10,47,11,78,186,251,208,
80,79,96,50,47,10,47,11,78,186,252,210,80,79,96,38,47,10,47,11,78,186,
253,176,80,79,96,26,47,10,47,11,78,186,254,156,80,79,96,14,47,10,47,11,
78,186,255,132,80,79,96,2,112,1,76,223,12,0,78,94,78,117,127,255,255,
248,129,0,1,4,129,0,113,2,129,0,137,1,129,0,137,1,129,0,137,1,129,0,137,
1,129,0,137,1,129,0,113,1,129,0,1,1,128,255,254,1,128,0,0,1,128,0,0,1,
128,0,0,1,128,0,0,1,128,0,0,1,128,0,0,1,128,0,0,1,135,255,255,225,136,
0,0,17,136,0,0,17,136,0,0,17,136,0,0,17,136,0,0,17,136,0,0,17,136,0,0,
17,136,0,0,17,136,0,0,17,136,0,0,17,136,0,0,17,136,0,0,17,127,255,255,
254,127,255,255,248,255,255,255,252,255,255,255,254,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,127,
255,255,254,0,0,127,255,255,248,129,0,1,4,129,0,113,2,129,0,137,1,129,
0,137,1,129,0,137,1,129,0,137,1,129,0,137,1,129,0,113,1,129,0,1,1,128,
255,254,1,128,0,0,1,128,0,0,1,128,0,0,1,128,0,0,1,128,0,0,1,128,0,0,1,
128,0,0,1,135,255,255,225,136,0,0,17,136,0,0,17,136,0,0,17,136,0,0,17,
136,0,0,17,136,0,0,17,136,0,0,17,136,0,0,17,136,0,0,17,136,0,0,17,136,
0,0,17,136,0,0,17,127,255,255,254,127,255,255,248,255,255,255,252,255,
255,255,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,127,255,255,254,0,0
};