00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020 #include "ConvertShape.h"
00021
00022 #include "IDataSource.h"
00023 #include "ODataSource.h"
00024
00025 #include <cstring>
00026
00027
00028
00029 #ifdef COMP_SHAPENUM
00030 extern int shapenum;
00031 #endif
00032
00033 void ConvertShape::Read(IDataSource *source, const ConvertShapeFormat *csf, uint32 real_len)
00034 {
00035
00036 uint32 start_pos = source->getPos();
00037
00038
00039 if (csf->bytes_ident)
00040 {
00041 char ident[4];
00042 source->read(ident, csf->bytes_ident);
00043
00044 if (std::memcmp (ident, csf->ident, csf->bytes_ident))
00045 {
00046 perr << "Warning: Corrupt shape!" << std::endl;
00047 return;
00048 }
00049 }
00050
00051
00052 uint8 special[256];
00053 if (csf->bytes_special) {
00054 memset(special, 0, 256);
00055 for (uint32 i = 0; i < csf->bytes_special; i++) special[source->read1()&0xFF] = i+2;
00056 }
00057
00058
00059 if (csf->bytes_header_unk) source->read(header_unknown, csf->bytes_header_unk);
00060
00061 #ifdef COMP_SHAPENUM
00062 if (shapenum == COMP_SHAPENUM) pout << std::hex;
00063 #endif
00064
00065
00066 num_frames = 1;
00067 if (csf->bytes_num_frames) num_frames = source->readX(csf->bytes_num_frames);
00068 if (num_frames == 0) num_frames = CalcNumFrames(source,csf,real_len,start_pos);
00069
00070 #ifdef COMP_SHAPENUM
00071 if (shapenum == COMP_SHAPENUM) pout << "num_frames " << num_frames << std::endl;
00072 #endif
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 frames = new ConvertShapeFrame[num_frames];
00084 std::memset (frames, 0, num_frames * sizeof(ConvertShapeFrame));
00085
00086
00087 for(uint32 f = 0; f < num_frames; ++f)
00088 {
00089 #ifdef COMP_SHAPENUM
00090 if (shapenum == COMP_SHAPENUM) pout << "Frame " << f << std::endl;
00091 #endif
00092 ConvertShapeFrame *frame = frames+f;
00093
00094 #ifdef COMP_SHAPENUM
00095 if (shapenum == COMP_SHAPENUM) pout << "Seeking to " << (csf->len_header + (csf->len_frameheader*f)) << std::endl;
00096 if (shapenum == COMP_SHAPENUM) pout << "Real " << (start_pos + csf->len_header + (csf->len_frameheader*f)) << std::endl;
00097 #endif
00098
00099 source->seek(start_pos + csf->len_header + (csf->len_frameheader*f));
00100
00101 #ifdef COMP_SHAPENUM
00102 if (shapenum == COMP_SHAPENUM) pout << "seeked to " << source->getPos() << std::endl;
00103 #endif
00104
00105
00106 uint32 frame_offset = csf->len_header + (csf->len_frameheader*f);
00107 if (csf->bytes_frame_offset) frame_offset = source->readX(csf->bytes_frame_offset);
00108 #ifdef COMP_SHAPENUM
00109 if (shapenum == COMP_SHAPENUM) pout << "frame_offset " << frame_offset << std::endl;
00110 #endif
00111
00112
00113 if (csf->bytes_frameheader_unk) source->read(frame->header_unknown, csf->bytes_frameheader_unk);
00114
00115
00116 uint32 frame_length = real_len-frame_offset;
00117 if (csf->bytes_frame_length) frame_length = source->readX(csf->bytes_frame_length) + csf->bytes_frame_length_kludge;
00118 #ifdef COMP_SHAPENUM
00119 if (shapenum == COMP_SHAPENUM) pout << "frame_length " << frame_length << std::endl;
00120 #endif
00121
00122
00123 source->seek(start_pos + frame_offset + csf->bytes_special);
00124
00125 if (csf->bytes_special)
00126 frame->ReadCmpFrame(source, csf, special, f>0?frames+f-1:0);
00127 else
00128 frame->Read(source, csf, frame_length);
00129 }
00130
00131 #ifdef COMP_SHAPENUM
00132 if (shapenum == COMP_SHAPENUM) pout << std::dec;
00133 #endif
00134 }
00135
00136 void ConvertShapeFrame::Read(IDataSource *source, const ConvertShapeFormat *csf, uint32 frame_length)
00137 {
00138
00139 if (csf->bytes_frame_unknown) source->read(unknown, csf->bytes_frame_unknown);
00140
00141
00142 compression = source->readX(csf->bytes_frame_compression);
00143 width = source->readXS(csf->bytes_frame_width);
00144 height = source->readXS(csf->bytes_frame_height);
00145 xoff = source->readXS(csf->bytes_frame_xoff);
00146 yoff = source->readXS(csf->bytes_frame_yoff);
00147
00148 #ifdef COMP_SHAPENUM
00149 if (width <= 0 || height <= 0 ||shapenum == COMP_SHAPENUM )
00150 {
00151 pout << "compression " << compression << std::endl;
00152 pout << "width " << width << std::endl;
00153 pout << "height " << height << std::endl;
00154 pout << "xoff " << xoff << std::endl;
00155 pout << "yoff " << yoff << std::endl;
00156 }
00157 #endif
00158
00159 if (compression != 0 && compression != 1) {
00160 compression = 0;
00161 width = 0;
00162 height = 0;
00163 xoff = 0;
00164 yoff = 0;
00165
00166 perr << "Corrupt frame?" << std::endl;
00167 }
00168
00169 if (height) {
00170
00171 line_offsets = new uint32 [height];
00172
00173 for(sint32 i = 0; i < height; ++i)
00174 {
00175 line_offsets[i] = source->readX(csf->bytes_line_offset);
00176
00177
00178
00179 if (!csf->line_offset_absolute)
00180 line_offsets[i] -= (height-i)*csf->bytes_line_offset;
00181 }
00182
00183
00184 bytes_rle = frame_length - (csf->len_frameheader2+(height*csf->bytes_line_offset));
00185
00186 #ifdef COMP_SHAPENUM
00187 if (bytes_rle < 0)
00188 {
00189 bytes_rle = 0;
00190 perr << "Corrupt frame?" << std::endl;
00191 }
00192
00193 #endif
00194 }
00195 else
00196 line_offsets = 0;
00197
00198
00199 if (bytes_rle) {
00200 rle_data = new uint8[bytes_rle];
00201 source->read(rle_data, bytes_rle);
00202 }
00203 else
00204 rle_data = 0;
00205 }
00206
00207 void ConvertShapeFrame::ReadCmpFrame(IDataSource *source, const ConvertShapeFormat *csf, const uint8 special[256], ConvertShapeFrame *prev)
00208 {
00209 static OAutoBufferDataSource *rlebuf = 0;
00210 uint8 outbuf[512];
00211
00212
00213 if (csf->bytes_frame_unknown) source->read(unknown, csf->bytes_frame_unknown);
00214
00215
00216 compression = source->readX(csf->bytes_frame_compression);
00217 width = source->readXS(csf->bytes_frame_width);
00218 height = source->readXS(csf->bytes_frame_height);
00219 xoff = source->readXS(csf->bytes_frame_xoff);
00220 yoff = source->readXS(csf->bytes_frame_yoff);
00221
00222 line_offsets = new uint32 [height];
00223
00224 if (!rlebuf) rlebuf = new OAutoBufferDataSource(1024);
00225 rlebuf->clear();
00226
00227 for(sint32 y = 0; y < height; ++y)
00228 {
00229 line_offsets[y] = rlebuf->getPos();
00230
00231 sint32 xpos = 0;
00232
00233 do
00234 {
00235 uint8 skip = source->read1();
00236 xpos += skip;
00237
00238 if (xpos > width) {
00239 source->skip(-1);
00240 skip = width-(xpos-skip);
00241 }
00242
00243 rlebuf->write1(skip);
00244
00245 if (xpos >= width) break;
00246
00247 uint32 dlen = source->read1();
00248 uint8 *o = outbuf;
00249
00250
00251 if (dlen == 0 || dlen == 1) {
00252 source->skip(-1);
00253 rlebuf->skip(-1);
00254 rlebuf->write1(skip+(width-xpos));
00255 break;
00256 }
00257
00258 int type = 0;
00259
00260 if (compression) {
00261 type = dlen & 1;
00262 dlen >>= 1;
00263 }
00264
00265 if (!type) {
00266
00267 uint32 extra = 0;
00268
00269 for (uint32 j = 0; j < dlen; j++) {
00270
00271 uint8 c = source->read1();
00272
00273 if (special[c] && prev) {
00274 sint32 count = special[c];
00275 prev->GetPixels(o,count,xpos-xoff,y-yoff);
00276 o+=count;
00277 extra += count-1;
00278 xpos += count;
00279 }
00280 else if (c == 0xFF && prev) {
00281 sint32 count = source->read1();
00282 prev->GetPixels(o,count,xpos-xoff,y-yoff);
00283 o+=count;
00284 extra += count-2;
00285 xpos += count;
00286 j++;
00287 }
00288 else {
00289 *o++ = c;
00290 xpos++;
00291 }
00292 }
00293
00294 if (((dlen+extra) << compression) > 255) {
00295 perr << "Error! Corrupt Frame. RLE dlen too large" << std::endl;
00296 }
00297
00298 rlebuf->write1((dlen+extra) << compression);
00299 rlebuf->write(outbuf,dlen+extra);
00300 }
00301 else {
00302 rlebuf->write1((dlen<<1)|1);
00303 rlebuf->write1(source->read1());
00304 xpos+=dlen;
00305 }
00306
00307 } while (xpos < width);
00308 }
00309
00310 bytes_rle = rlebuf->getPos();
00311 rle_data = new uint8[bytes_rle];
00312 memcpy (rle_data, rlebuf->getBuf(), bytes_rle);
00313 }
00314
00315 void ConvertShapeFrame::GetPixels(uint8 *buf, sint32 count, sint32 x, sint32 y)
00316 {
00317 x += xoff;
00318 y += yoff;
00319
00320 if (y > height) return;
00321
00322 sint32 xpos = 0;
00323 const uint8 * linedata = rle_data + line_offsets[y];
00324
00325 do {
00326 xpos += *linedata++;
00327
00328 if (xpos == width) break;
00329
00330 sint32 dlen = *linedata++;
00331 int type = 0;
00332
00333 if (compression)
00334 {
00335 type = dlen & 1;
00336 dlen >>= 1;
00337 }
00338
00339 if (x >= xpos && x < (xpos+dlen))
00340 {
00341 int diff = x-xpos;
00342 dlen-=diff;
00343 xpos = x;
00344
00345 int num = count;
00346 if (dlen < count) num = dlen;
00347
00348 if (!type) {
00349 const uint8 *l = (linedata+=diff);
00350
00351 while (num--) {
00352 *buf++ = *l++;
00353 count--;
00354 x++;
00355 }
00356 }
00357 else {
00358 uint8 l = *linedata;
00359
00360 while (num--) {
00361 *buf++ = l;
00362 count--;
00363 x++;
00364 }
00365 }
00366
00367 if (count == 0) return;
00368 }
00369
00370 if (!type) linedata+=dlen;
00371 else linedata++;
00372
00373 xpos += dlen;
00374
00375 } while (xpos < width);
00376 }
00377
00378 int ConvertShape::CalcNumFrames(IDataSource *source, const ConvertShapeFormat *csf, uint32 real_len, uint32 start_pos)
00379 {
00380 int f=0;
00381 uint32 first_offset = 0xFFFFFFFF;
00382
00383 uint32 save_pos = source->getPos();
00384
00385 for (f=0;;f++) {
00386
00387
00388 source->seek(start_pos + csf->len_header + (csf->len_frameheader*f));
00389
00390 if ((source->getPos()-start_pos) >= first_offset) break;
00391
00392
00393 uint32 frame_offset = csf->len_header + (csf->len_frameheader*f);
00394 if (csf->bytes_frame_offset) frame_offset = source->readX(csf->bytes_frame_offset) + csf->bytes_special;
00395
00396 if (frame_offset < first_offset) first_offset = frame_offset;
00397
00398
00399 if (csf->bytes_frameheader_unk) source->skip(csf->bytes_frameheader_unk);
00400
00401
00402 uint32 frame_length = real_len-frame_offset;
00403 if (csf->bytes_frame_length) frame_length = source->readX(csf->bytes_frame_length) + csf->bytes_frame_length_kludge;
00404 }
00405
00406 source->seek(save_pos);
00407
00408 return f;
00409 }
00410
00411 bool ConvertShape::Check(IDataSource *source, const ConvertShapeFormat *csf, uint32 real_len)
00412 {
00413 #if 0
00414 pout << "Testing " << csf->name << "..." << std::endl;
00415 #endif
00416 bool result = true;
00417
00418
00419 int start_pos = source->getPos();
00420
00421
00422 if (csf->bytes_ident)
00423 {
00424 char ident[5];
00425 ident[csf->bytes_ident] = 0;
00426 source->read(ident, csf->bytes_ident);
00427
00428 if (std::memcmp (ident, csf->ident, csf->bytes_ident))
00429 {
00430
00431 source->seek(start_pos);
00432 return false;
00433 }
00434 }
00435
00436
00437 if (csf->bytes_special) source->skip(csf->bytes_special);
00438
00439
00440 if (csf->bytes_header_unk) source->skip(csf->bytes_header_unk);
00441
00442
00443 int num_frames = 1;
00444 if (csf->bytes_num_frames) num_frames = source->readX(csf->bytes_num_frames);
00445 if (num_frames == 0) num_frames = CalcNumFrames(source,csf,real_len,start_pos);
00446
00447
00448 ConvertShapeFrame oneframe;
00449 std::memset (&oneframe, 0, sizeof(ConvertShapeFrame));
00450
00451
00452 for (int f = 0; f < num_frames; f++)
00453 {
00454 ConvertShapeFrame *frame = &oneframe;
00455
00456
00457 source->seek(start_pos + csf->len_header + (csf->len_frameheader*f));
00458
00459
00460 uint32 frame_offset = csf->len_header + (csf->len_frameheader*f);
00461 if (csf->bytes_frame_offset) frame_offset = source->readX(csf->bytes_frame_offset) + csf->bytes_special;
00462
00463
00464 if (csf->bytes_frameheader_unk) source->read(frame->header_unknown, csf->bytes_frameheader_unk);
00465
00466
00467 uint32 frame_length = real_len-frame_offset;
00468 if (csf->bytes_frame_length) frame_length = source->readX(csf->bytes_frame_length) + csf->bytes_frame_length_kludge;
00469
00470
00471 if ((frame_length + frame_offset) > real_len)
00472 {
00473 result = false;
00474 break;
00475 }
00476
00477
00478 source->seek(start_pos + frame_offset);
00479
00480
00481 if (csf->bytes_frame_unknown) source->read(frame->unknown, csf->bytes_frame_unknown);
00482
00483
00484 frame->compression = source->readX(csf->bytes_frame_compression);
00485 frame->width = source->readXS(csf->bytes_frame_width);
00486 frame->height = source->readXS(csf->bytes_frame_height);
00487 frame->xoff = source->readXS(csf->bytes_frame_xoff);
00488 frame->yoff = source->readXS(csf->bytes_frame_yoff);
00489
00490 if (frame->compression != 0 && frame->compression != 1 || frame->width < 0 || frame->height < 0)
00491 {
00492 frame->compression = 0;
00493 frame->width = 0;
00494 frame->height = 0;
00495 frame->xoff = 0;
00496 frame->yoff = 0;
00497 result = false;
00498 break;
00499 }
00500
00501 if (frame->height)
00502 {
00503
00504 sint32 highest_offset_byte = 0;
00505
00506
00507 frame->bytes_rle = frame_length - (csf->len_frameheader2+(frame->height*csf->bytes_line_offset));
00508
00509
00510 if (frame->bytes_rle < 0)
00511 {
00512 result = false;
00513 break;
00514 }
00515
00516
00517 if (!csf->bytes_special) {
00518
00519
00520 source->seek(start_pos + frame_offset + csf->len_frameheader2);
00521
00522
00523 for (int i = 0; i < frame->height; i++)
00524 {
00525 sint32 line_offset = source->readX(csf->bytes_line_offset);
00526
00527
00528
00529 if (!csf->line_offset_absolute)
00530 line_offset -= (frame->height-i)*csf->bytes_line_offset;
00531
00532 if (line_offset > frame->bytes_rle)
00533 {
00534 result = false;
00535 break;
00536 }
00537
00538 if (line_offset > highest_offset_byte) highest_offset_byte = line_offset;
00539 };
00540
00541
00542 if (result == false) break;
00543
00544
00545 source->seek(highest_offset_byte + start_pos + frame_offset + csf->len_frameheader2 + frame->height*csf->bytes_line_offset);
00546 int xpos = 0;
00547 uint32 dlen = 0;
00548
00549
00550 if (frame->compression) do
00551 {
00552 xpos += source->read1();
00553 if (xpos == frame->width) break;
00554
00555 dlen = source->read1();
00556 int type = dlen & 1;
00557 dlen >>= 1;
00558
00559 if (!type) source->skip(dlen);
00560 else source->skip(1);
00561
00562 xpos += dlen;
00563
00564 } while (xpos < frame->width);
00565
00566 else do
00567 {
00568 xpos += source->read1();
00569 if (xpos == frame->width) break;
00570
00571 dlen = source->read1();
00572 source->skip(dlen);
00573
00574 xpos += dlen;
00575 } while (xpos < frame->width);
00576
00577
00578 sint32 highest_rle_byte = source->getPos();
00579 highest_rle_byte -= start_pos + frame_offset + csf->len_frameheader2 + frame->height*csf->bytes_line_offset;
00580
00581
00582 if (highest_rle_byte > frame->bytes_rle)
00583 {
00584 result = false;
00585 break;
00586 }
00587 }
00588 }
00589 }
00590
00591
00592 oneframe.Free();
00593 num_frames = 0;
00594
00595
00596 source->seek(start_pos);
00597
00598 return result;
00599 }
00600
00601 bool ConvertShape::CheckUnsafe(IDataSource *source, const ConvertShapeFormat *csf, uint32 real_len)
00602 {
00603 #if 0
00604 pout << "Testing " << csf->name << "..." << std::endl;
00605 #endif
00606 bool result = true;
00607
00608
00609 int start_pos = source->getPos();
00610
00611
00612 if (csf->bytes_ident)
00613 {
00614 char ident[5];
00615 ident[csf->bytes_ident] = 0;
00616 source->read(ident, csf->bytes_ident);
00617
00618 if (std::memcmp (ident, csf->ident, csf->bytes_ident))
00619 {
00620
00621 source->seek(start_pos);
00622 return false;
00623 }
00624 }
00625
00626
00627 if (csf->bytes_special) source->skip(csf->bytes_special);
00628
00629
00630 if (csf->bytes_header_unk) source->skip(csf->bytes_header_unk);
00631
00632
00633 int num_frames = 1;
00634 if (csf->bytes_num_frames) num_frames = source->readX(csf->bytes_num_frames);
00635 if (num_frames == 0) num_frames = CalcNumFrames(source,csf,real_len,start_pos);
00636
00637
00638 ConvertShapeFrame oneframe;
00639 std::memset (&oneframe, 0, sizeof(ConvertShapeFrame));
00640
00641
00642 for (int f = 0; f < num_frames; f++)
00643 {
00644 ConvertShapeFrame *frame = &oneframe;
00645
00646
00647 source->seek(start_pos + csf->len_header + (csf->len_frameheader*f));
00648
00649
00650 uint32 frame_offset = csf->len_header + (csf->len_frameheader*f);
00651 if (csf->bytes_frame_offset) frame_offset = source->readX(csf->bytes_frame_offset) + csf->bytes_special;
00652
00653
00654 if (csf->bytes_frameheader_unk) source->read(frame->header_unknown, csf->bytes_frameheader_unk);
00655
00656
00657 uint32 frame_length = real_len-frame_offset;
00658 if (csf->bytes_frame_length) frame_length = source->readX(csf->bytes_frame_length) + csf->bytes_frame_length_kludge;
00659
00660
00661 if ((frame_length + frame_offset) > real_len)
00662 {
00663 result = false;
00664 break;
00665 }
00666
00667
00668 source->seek(start_pos + frame_offset);
00669
00670
00671 if (csf->bytes_frame_unknown) source->read(frame->unknown, csf->bytes_frame_unknown);
00672
00673
00674 frame->compression = source->readX(csf->bytes_frame_compression);
00675 frame->width = source->readXS(csf->bytes_frame_width);
00676 frame->height = source->readXS(csf->bytes_frame_height);
00677 frame->xoff = source->readXS(csf->bytes_frame_xoff);
00678 frame->yoff = source->readXS(csf->bytes_frame_yoff);
00679
00680 if (frame->compression != 0 && frame->compression != 1 || frame->width < 0 || frame->height < 0)
00681 {
00682 frame->compression = 0;
00683 frame->width = 0;
00684 frame->height = 0;
00685 frame->xoff = 0;
00686 frame->yoff = 0;
00687 result = false;
00688 break;
00689 }
00690
00691 if (frame->height)
00692 {
00693
00694 frame->bytes_rle = frame_length - (csf->len_frameheader2+(frame->height*csf->bytes_line_offset));
00695
00696
00697 if (frame->bytes_rle < 0)
00698 {
00699 result = false;
00700 break;
00701 }
00702 }
00703 }
00704
00705
00706 oneframe.Free();
00707 num_frames = 0;
00708
00709
00710 source->seek(start_pos);
00711
00712 return result;
00713 }
00714
00715 void ConvertShape::Write(ODataSource *dest, const ConvertShapeFormat *csf, uint32 &write_len)
00716 {
00717
00718 uint32 start_pos = dest->getPos();
00719
00720
00721 if (csf->bytes_ident) dest->write(csf->ident, csf->bytes_ident);
00722
00723
00724 if (csf->bytes_header_unk) dest->write(header_unknown, csf->bytes_header_unk);
00725
00726
00727 if (csf->bytes_num_frames) dest->writeX(num_frames, csf->bytes_num_frames);
00728 else if (!csf->bytes_num_frames && num_frames > 1)
00729 {
00730 perr << "Error: Unable to convert multiple frame shapes to " << csf->name << std::endl;
00731 return;
00732 }
00733
00734
00735 for (uint32 i = 0; i < num_frames*csf->len_frameheader; i++) dest->write1(0);
00736
00737
00738 for(uint32 f = 0; f < num_frames; f++)
00739 {
00740 ConvertShapeFrame *frame = frames+f;
00741
00742
00743 uint32 frame_offset = dest->getPos() - start_pos;
00744
00745
00746 dest->seek(start_pos + csf->len_header + (csf->len_frameheader*f));
00747
00748
00749 if (csf->bytes_frame_offset) dest->writeX(frame_offset, csf->bytes_frame_offset);
00750
00751
00752 if (csf->bytes_frameheader_unk) dest->write(frame->header_unknown, csf->bytes_frameheader_unk);
00753
00754
00755 if (csf->bytes_frame_length)
00756 {
00757 uint32 frame_length = csf->len_frameheader2 + (frame->height*csf->bytes_line_offset) + frame->bytes_rle;
00758 dest->writeX(frame_length - csf->bytes_frame_length_kludge, csf->bytes_frame_length);
00759 }
00760
00761
00762 dest->seek(start_pos + frame_offset);
00763
00764
00765 if (csf->bytes_frame_unknown) dest->write(frame->unknown, csf->bytes_frame_unknown);
00766
00767
00768 dest->writeX(frame->compression, csf->bytes_frame_compression);
00769 dest->writeX(frame->width, csf->bytes_frame_width);
00770 dest->writeX(frame->height, csf->bytes_frame_height);
00771 dest->writeX(frame->xoff, csf->bytes_frame_xoff);
00772 dest->writeX(frame->yoff, csf->bytes_frame_yoff);
00773
00774
00775 for (sint32 i = 0; i < frame->height; i++)
00776 {
00777 sint32 actual_offset = frame->line_offsets[i];
00778
00779
00780 if (!csf->line_offset_absolute)
00781 actual_offset += (frame->height-i)*csf->bytes_line_offset;
00782
00783 dest->writeX(actual_offset, csf->bytes_line_offset);
00784 }
00785
00786
00787 dest->write(frame->rle_data, frame->bytes_rle);
00788 }
00789
00790
00791 write_len = dest->getPos() - start_pos;
00792 }
00793
00794
00795
00796 const ConvertShapeFormat PentagramShapeFormat =
00797 {
00798 "Pentagram",
00799 8,
00800 "PSHP",
00801 4,
00802 0,
00803 0,
00804 4,
00805
00806 8,
00807 4,
00808 0,
00809 4,
00810 0,
00811
00812 20,
00813 0,
00814 4,
00815 4,
00816 4,
00817 4,
00818 4,
00819
00820 4,
00821 1
00822 };