Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

New patch - Support for raw samples

J Phelps
2007-03-11
2013-03-25
  • J Phelps
    J Phelps
    2007-03-11

    The older trackers on DOS would treat any unknown sample type as a raw sample. This allowed you to load samples that were of unknown format. Since almost all samples are simply PCM data with some headers in front of it, this usually worked.

    When I imported my library of samples from Impulse Tracker, the first thing I noticed was that I couldn't load most of the samples into Cheese Tracker, because Cheese Tracker couldn't recognize the format.

    This patch fixes that problem, once and for all (and also makes an extension or two to the internal API of the program). It creates a new sample loader, Loader_RAW, and modifies all the other files required to get the new loader recognized by Cheese Tracker.

    Loader_RAW is registered last in the Loader_List, which means that it is only activated if all other sample loaders fail. Raw samples are loaded as 8 bit mono. I can't tell if the rest of Cheese Tracker will think of the samples as signed or unsigned (the data is read as Uint8, but must be cast to Sint16 to be passed into the Sample_Data class).

    I imitated the convention of the WAV loader and allocated the buffer for the PCM data with malloc(3) and then passed the result to Sample_Data::set_data_ptr(). I never looked at the Sample_Data class and I am assuming that it uses free() and not delete[].

    Without further ado, here is the patch:

    ===================================================================================
    diff -r -C 4 -N cheesetracker-0.9.9/SConstruct cheesetracker-0.9.9.new/SConstruct
    *** cheesetracker-0.9.9/SConstruct    Fri Apr 23 01:51:57 2004
    --- cheesetracker-0.9.9.new/SConstruct    Sun Mar 11 00:31:11 2007
    ***************
    *** 74,85 ****
     
      #detect OSS
     
      env.Append(CXXFLAGS=['-DPOSIX_ENABLED']);
    !
    !
    ! if (env['debug'] and not env['optimize']):
    !     env.Append(CXXFLAGS=['-g','-Wall']);
     
      if os.environ.has_key('USE_STACK_CHECK'):
          env.Append(CXXFLAGS=['-fstack-check']);
     
    --- 74,82 ----
     
      #detect OSS
     
      env.Append(CXXFLAGS=['-DPOSIX_ENABLED']);
    ! env.Append(CXXFLAGS=['-g','-Wall']);
     
      if os.environ.has_key('USE_STACK_CHECK'):
          env.Append(CXXFLAGS=['-fstack-check']);
     
    diff -r -C 4 -N cheesetracker-0.9.9/cheesetracker/interface_binds/tracker_instance.cpp cheesetracker-0.9.9.new/cheesetracker/interface_binds/tracker_instance.cpp
    *** cheesetracker-0.9.9/cheesetracker/interface_binds/tracker_instance.cpp    Thu Apr 22 23:21:29 2004
    --- cheesetracker-0.9.9.new/cheesetracker/interface_binds/tracker_instance.cpp    Sun Mar 11 00:31:22 2007
    ***************
    *** 171,180 ****
          format_manager.register_loader(&loader_ct);
          format_manager.register_loader(&loader_it);
          format_manager.register_loader(&loader_xm);
          format_manager.register_loader(&loader_s3m);
    -
          format_manager.register_loader(&loader_wav);
     
          saver_ct.set_mixer(&mixer);
          format_manager.register_saver(&saver_ct);
          format_manager.register_saver(&saver_it);
    --- 171,180 ----
          format_manager.register_loader(&loader_ct);
          format_manager.register_loader(&loader_it);
          format_manager.register_loader(&loader_xm);
          format_manager.register_loader(&loader_s3m);
          format_manager.register_loader(&loader_wav);
    +     format_manager.register_loader(&loader_raw);
     
          saver_ct.set_mixer(&mixer);
          format_manager.register_saver(&saver_ct);
          format_manager.register_saver(&saver_it);
    diff -r -C 4 -N cheesetracker-0.9.9/cheesetracker/interface_binds/tracker_instance.h cheesetracker-0.9.9.new/cheesetracker/interface_binds/tracker_instance.h
    *** cheesetracker-0.9.9/cheesetracker/interface_binds/tracker_instance.h    Thu Apr 22 23:21:29 2004
    --- cheesetracker-0.9.9.new/cheesetracker/interface_binds/tracker_instance.h    Sun Mar 11 00:31:22 2007
    ***************
    *** 20,27 ****
    --- 20,28 ----
      #include "loaders/loader_xm.h"
      #include "loaders/loader_s3m.h"
      #include "loaders/loader_wav.h"
      #include "loaders/loader_ct.h"
    + #include "loaders/loader_raw.h"
      #include "savers/saver_it.h"
      #include "savers/saver_ct.h"
      #include "savers/saver_raw.h"
      #include "savers/saver_wav.h"
    ***************
    *** 95,102 ****
    --- 96,104 ----
          Loader_CT loader_ct;
          Loader_XM loader_xm;
          Loader_S3M loader_s3m;
          Loader_WAV loader_wav;
    +     Loader_RAW loader_raw;
     
     
          Saver_IT saver_it;
          Saver_CT saver_ct;
    diff -r -C 4 -N cheesetracker-0.9.9/cheesetracker/loaders/SCsub cheesetracker-0.9.9.new/cheesetracker/loaders/SCsub
    *** cheesetracker-0.9.9/cheesetracker/loaders/SCsub    Thu Apr 22 23:21:29 2004
    --- cheesetracker-0.9.9.new/cheesetracker/loaders/SCsub    Sun Mar 11 00:31:11 2007
    ***************
    *** 12,18 ****
    --- 12,19 ----
      'loader_s3m.cpp',\   'loader_wav.cpp',\   'loader_xm.cpp',\   'loader_ct.cpp',\ + 'loader_raw.cpp',\   ]
     
      env2.Library('lib_loaders.a', file_list);
    diff -r -C 4 -N cheesetracker-0.9.9/cheesetracker/loaders/loader_raw.cpp cheesetracker-0.9.9.new/cheesetracker/loaders/loader_raw.cpp
    *** cheesetracker-0.9.9/cheesetracker/loaders/loader_raw.cpp    Wed Dec 31 19:00:00 1969
    --- cheesetracker-0.9.9.new/cheesetracker/loaders/loader_raw.cpp    Sun Mar 11 01:08:28 2007
    ***************
    *** 0 ****
    --- 1,166 ----
    + /***************************************************************************
    +     This file is part of the CheeseTronic Music Tools
    +     url                  : http://reduz.com.ar/cheesetronic
    +     copyright            : (C) 2003 by Juan Linietsky
    +     email                : coding@reduz.com.ar
    +  ***************************************************************************/
    +
    + /***************************************************************************
    +  *                                                                         *
    +  *   This program is free software; you can redistribute it and/or modify  *
    +  *   it under the terms of the GNU General Public License as published by  *
    +  *   the Free Software Foundation; either version 2 of the License, or     *
    +  *   (at your option) any later version.                                   *
    +  *                                                                         *
    +  ***************************************************************************/
    +
    + #define ISNT16BIT false
    + #include "loader_raw.h"
    + #include <iostream>
    + #include <cstdio>
    +
    +
    + int Loader_RAW::load_sample_func(const char *p_filename, Sample_Data *SD) {
    +     int status;
    +     fprintf(stderr, "Loader_RAW::load_sample_func: Called with args(%s, %p)\n",
    +             p_filename, SD);
    +
    +     if(status = file_read.open(p_filename)) {
    +         fprintf(stderr, "Loader_RAW::load_sample_func:%d: Status %d:", __LINE__, status);
    +         perror(p_filename);
    +         return -1;
    +     }
    +
    +     SD->set_c5_freq(8363);
    +
    +     int size = file_read.get_size();
    +     if(size == -1) {
    +         fprintf(stderr, "Loader_RAW::load_sample_func: Invalid filesize %d\n", size);
    +         perror(p_filename);
    +         file_read.close();
    +         return -1;
    +     }
    +     Uint8 *data = (Uint8*)malloc(size);
    +     if(data == NULL)
    +     {
    +         fprintf(stderr, "Loader_RAW::load_sample_func: Out of memory\n");
    +         file_read.close();
    +         return -1;
    +     }
    +
    +     // Load the data.
    +
    +     file_read.get_byte_array(data, size);
    +
    +     SD->set_data_ptr((Sint16*)data, size, ISNT16BIT);
    +    
    +     SD->change_sign();
    +
    +     fprintf(stderr, "Loader_RAW::load_sample_func: Success! SD = %p\n", SD);
    +     file_read.close();
    +     return 0;
    + }
    +
    + Sample_Data *Loader_RAW::load_sample(const char *p_filename)
    + {
    +     Sample_Data *SD = new Sample_Data;
    +     int status;
    +
    +     status = load_sample_func(p_filename, SD);
    +     if(status == -1)
    +     {
    +         delete SD;
    +         fprintf(stderr, "RAW loader failed\n");
    +         return NULL;
    +     }
    +     return SD;
    + }
    +
    + Loader::Error Loader_RAW::load_sample(const char *p_filename, int p_dest_index)
    + {
    +     Sample *sample = song->get_sample(p_dest_index);
    +     int status;
    +
    +     sample->reset();
    +     sample->name = p_filename;
    +     sample->in_use = true;
    +     status = load_sample_func(p_filename, &sample->data);
    +
    +     if(status == -1)
    +         return FILE_ERROR;
    +
    +     return SUCCESS;
    + }
    +
    +
    + void Loader_RAW::free_info(bool free_sampledata) {
    +
    +    ERROR("free_info: unexpected method invocation");
    + };
    +
    +
    + Loader_RAW::Loader_RAW() {
    +     format_name = "Raw";
    + }
    +
    + Loader_RAW::~Loader_RAW() {
    + };
    +
    + void Loader_RAW::transfer_data_to_song() {
    +
    +    ERROR("transfer_data_to_song: unexpected method invocation");
    + };
    +
    +
    +
    + bool Loader_RAW::test(const char *p_filename) {
    +
    +    return false;
    + };
    +
    + // the following methods shouldn't be called since this is just a sample loader
    + // (test returns false letting the tracker know that we don't load songs)
    +
    + Loader::Error Loader_RAW::load(const char *p_filename,bool p_load_patterns) {
    +
    +    ERROR("load: unexpected method invocation");
    +    return FILE_FORMAT_NOT_RECOGNIZED; // not valid to load a song file as a sample
    + };
    +
    + int Loader_RAW::get_amount_of_samples() {
    +
    +    ERROR("get_amount_of_samples: unexpected method invocation");
    +    return 0;
    + };
    +
    + Sample_Data *Loader_RAW::get_sample_data(int p_sample_index) {
    +
    +    ERROR("get_sample_data: unexpected method invocation");
    +    return NULL;
    + };
    +
    + string Loader_RAW::get_sample_name(int p_sample_index) {
    +
    +    ERROR("get_sample_name: unexpected method invocation");
    +    return "";
    + };
    +
    + void Loader_RAW::add_sample_to_song(int p_sample_index,int p_dest_index,bool create_instrument) {
    +
    +    ERROR("add_sample_to_song: unexpected method invocation");
    + };
    +
    + Loader::Error Loader_RAW::load_samples_from_instrument(const char *p_filename)
    + {
    +
    +    ERROR("load_samples_from_instrument: unexpected method invocation");
    +    return FILE_ERROR;
    + };
    +
    + Loader::Error Loader_RAW::load_instrument(const char *p_filename,int p_dest_index) {
    +
    +    ERROR("load_instrument: unexpected method invocation");
    +    return FILE_ERROR;
    + };
    +
    +
    diff -r -C 4 -N cheesetracker-0.9.9/cheesetracker/loaders/loader_raw.h cheesetracker-0.9.9.new/cheesetracker/loaders/loader_raw.h
    *** cheesetracker-0.9.9/cheesetracker/loaders/loader_raw.h    Wed Dec 31 19:00:00 1969
    --- cheesetracker-0.9.9.new/cheesetracker/loaders/loader_raw.h    Sun Mar 11 00:31:11 2007
    ***************
    *** 0 ****
    --- 1,70 ----
    + /***************************************************************************
    +     This file is part of the CheeseTronic Music Tools
    +     url                  : http://reduz.com.ar/cheesetronic
    +     copyright            : (C) 2003 by Juan Linietsky
    +     email                : coding@reduz.com.ar
    +  ***************************************************************************/
    +
    + /***************************************************************************
    +  *                                                                         *
    +  *   This program is free software; you can redistribute it and/or modify  *
    +  *   it under the terms of the GNU General Public License as published by  *
    +  *   the Free Software Foundation; either version 2 of the License, or     *
    +  *   (at your option) any later version.                                   *
    +  *                                                                         *
    +  ***************************************************************************/
    +
    +
    +
    + /***************************************************************************
    +                       loader_wav.h  -  simple wav loader
    +                              -------------------
    +     begin                : Tue Apr 24 2001
    +     copyright            : (C) 2001 by Calvin French
    +     email                : frenchc@home.com
    +  ***************************************************************************/
    +
    + /***************************************************************************
    +  *                                                                         *
    +  *   This program is free software; you can redistribute it and/or modify  *
    +  *   it under the terms of the GNU General Public License as published by  *
    +  *   the Free Software Foundation; either version 2 of the License, or     *
    +  *   (at your option) any later version.                                   *
    +  *                                                                         *
    +  ***************************************************************************/
    +
    + #ifndef LOADER_RAW_H
    + #define LOADER_RAW_H
    +
    + #include "loader.h"
    +
    +
    +
    +
    + struct Loader_RAW : public Loader  {
    +
    +    int load_sample_func(const char *p_filename, Sample_Data *SD);
    +    virtual Error load_sample(const char *p_filename, int p_dest_index);
    +    virtual Sample_Data* load_sample(const char *p_filename);
    +
    +    // test always returns false
    +    virtual bool test(const char *p_filename);
    +
    +    // these shouldn't be called (according to reduz) but we implement them anyway
    +    virtual Error load(const char *p_filename,bool p_load_patterns);
    +    virtual int get_amount_of_samples();
    +    virtual Sample_Data *get_sample_data(int p_sample_index);
    +    virtual string get_sample_name(int p_sample_index);
    +    virtual void add_sample_to_song(int p_sample_index,int p_dest_index,bool create_instrument);
    +    virtual Error load_samples_from_instrument(const char *p_filename);
    +    virtual Error load_instrument(const char *p_filename,int p_dest_index);
    +    virtual void transfer_data_to_song();
    +    virtual void free_info(bool free_sampledata=false);
    +
    +    Loader_RAW();
    +    ~Loader_RAW();
    + };
    +
    +
    +
    + #endif
    diff -r -C 4 -N cheesetracker-0.9.9/cheesetracker/trackercore/file_reader.cpp cheesetracker-0.9.9.new/cheesetracker/trackercore/file_reader.cpp
    *** cheesetracker-0.9.9/cheesetracker/trackercore/file_reader.cpp    Thu Apr 22 23:21:32 2004
    --- cheesetracker-0.9.9.new/cheesetracker/trackercore/file_reader.cpp    Sun Mar 11 00:31:23 2007
    ***************
    *** 40,47 ****
    --- 40,69 ----
     
      File_Reader::~File_Reader(){
      }
     
    + int File_Reader::get_size() {
    +     int retval;
    +     int current_pos;
    +     int status;
    +
    +     current_pos = get_file_pos();
    +     if(current_pos == -1) {
    +         check_for_errors();
    +         return -1;
    +     }
    +     status=fseek(f, 0, SEEK_END);
    +     if(status == -1) {
    +         check_for_errors();
    +         return -1;
    +     }
    +     retval = get_file_pos();
    +     if(fseek(f, current_pos, SEEK_SET) == -1)
    +         check_for_errors();
    +     if(!error_ocurred)
    +         return retval;
    +     return -1;
    + }
     
      void File_Reader::check_for_errors() {
     
          if ( !feof(f) ) {
    diff -r -C 4 -N cheesetracker-0.9.9/cheesetracker/trackercore/file_reader.h cheesetracker-0.9.9.new/cheesetracker/trackercore/file_reader.h
    *** cheesetracker-0.9.9/cheesetracker/trackercore/file_reader.h    Thu Apr 22 23:21:32 2004
    --- cheesetracker-0.9.9.new/cheesetracker/trackercore/file_reader.h    Sun Mar 11 00:31:23 2007
    ***************
    *** 72,79 ****
    --- 72,80 ----
          int open(const char *p_filename);
          void close();
          void seek(Uint32 p_position);   
              int get_file_pos() { return ftell(f); };
    +     int get_size();
          bool eof_reached();
          bool error_loading();
     
          Uint8 get_byte();

     
    • J Phelps
      J Phelps
      2007-03-11

      Here is the patch again, this time uuencoded so that the indentation is preserved.

      begin 644 cheesetracker-0.9.9-raw-samples.diff.gz
      M'XL("':?\T4``V-H965S971R86-K97(M,"XY+CDM<F%W+7-A;7!L97,N9&EF
      M9@#M&VMSFTCRL_TK.DXE0HK>=NQ8/J?6*\M97QQ[RRB7U.UN42,8),X(N`'L
      M**GDMU_/#`B00!8ZY;9N*Q05F:&GW]W3TT,,RS2AP:#1AP-H7(,^H=2G`2/Z
      M'66-=O.X>=Q2^Z[C!RS4@[S738<^I$!V:[7:(UAV+I@%9QZ#[CZT.[V7>!]!
      MM]T^V&TT&FN0V%%#!]X1!IT.M-N]_4X/_\#Y1YQV^A*\'!W47[T$\0B`]U.#
      M!A1%N5%5.4"=^^:9YU''4/H?/UY<G;U13W^K-,Y_O5$O/VJ#Z[.?KP;GE3^J
      M)[M/0-Z6"0K.^JUBT%$XKOP!Q#'`<0,0@ZX76%/K,\4I/03>*<`_KM0KC0_$
      MM@5JP0GB=?TFPEO,=9H3XFMW=*94WJL#31V>]=]J_5\&amp;_;<51`N%:$T_0,TU
      M4(OZ78R9JY6KH0OX5V,+:OCS13+6\-O,6,MR`LI,HE-M9#F&WXK&-0N]BC@Z
      M;>J>5^A\Y5$5QD%Y5#O#22CCI8LAT^MV>MWCQ^-E`SI+<<4)%L55YZA3[[QJ
      MQY&U8[IL2@)M2APRIJS)Z-CRD:9FN\2@3'DN?S4]$`9<%]PJ!_YI6@K<W^?P
      M#2@QY8'<Q[Z]XY-[(5$3]:Q-K4\&lt;3/RL9D),4Y['LTL`"VUPH\?*C^+Y_UCY
      M937_8FUX1A[^9$M]AR0UV5:\3[:5H";_D_0T*9><NNUZ]TBF)LX$?WP5!\M3
      MR]'MT*"P)QW%;\W]MSG96P6`'OL(!/KH(Q#H@PCPHA@`W781A7`IOQ5[ULK7
      M^NK7CV&/!,C3Z?'+>J?=391Z?(C/!_,4="79[P]A+NE):OSC.YBK.3VN[L]?
      MH'K3;SZ<_0,2M8K(C][<GGV`1%M1C/.9JI#A<@BQJDZ2T7X\RODJ'YFQE=2^
      M'X[6].K,G#7C+3-G&Z&515BJ=.YT<9%)#,X?CV-[5U(Q@;5#I?Y[:I![T=+@
      MIQQ`]-9H[,5\C+OH'/"/>7':;5Y9(T885H^V-8J2O=\DE3J8EDTU&[/P1CDW
      M)_[6+P7S)Y>T=7;RS@=JP#G58;\#G>,>FJG=QC\.CS<P^@+FM/4[O?:K'F;%
      M0NNW4Y:O=PX/I>5?0*NVO0O1\6LXL7QA1<!?C[``7!.""86^D&J(>P=+AW>A
      MC_\.7=?VHWDALV'IZL$D"+Q>J\6H$7YNZNZT2=A</QQ3-%MWO1FSQI,@.UOI
      M5[E2]F$T@[^'Q($KR[%HX-_-HGET2JPENCU$9UC.^*<T53YAB]IJ(;[O8(#:
      ML@XWO.;HA$$]YHX9F7*;FHQ2\%TS>"",GL#,#4%'S:*N,&J9-0H#-'W`]]$M
      ME\$4-6G.4NCP5>B@(PN?P$IAZL<.\N;Z/;RA#F7$AE_#D8T.<F7IU/$I$.2`
      MC_@3C*=1&AV?>,$Y4B..X,)%_"2P7.<$J(7O&?!%$9^A&Y.*\-8!.<P(JY"`
      M2\2`[_Q=IXIBS,`F08*D649WVS3%]J[(]YX:U+0<"I?J];!S^#,NM2:Q?9I3
      MT,2E1NK-WRP7K4W)]'5F5/<#PW)?2P)X8S$(R4K?ZW%\6%U//<SR9NCHBLX[
      M09@),9/5/(WG#8=,T3"JA#DG`8&:>EZ%+[QHX.BPB@Q"7^X>/(8CIH)$*6-U
      MV%M%J@=]8MOH/P_H%$#8V%>>^75XYE5_=_;J'%VL[PP?YV*C(HAS0IPVG,IE
      M"L4WFJY''26948TX+<G;,Z,'JD2.?^[50=.N+J\'FE:/Y)7;I1T/<;DL34^.
      M,QJ$S(%&1SQ^C3A6SQNO^2Y)?ZEAU/Y;>;5_N)^(PW5I?:89:<8(S0<5B9>+
      M+$!.$?5FDL&E<T]LRQ!$!+)G!E>XH/V(5`E?NNWZ,5,YPNZ\1XZPO#&XNYR"
      M(AYKU2D:W-65A!+*(T%.X?K]U565CVTDU$THUK4IG;ILAN*499C_MEHB-$1"
      MXEPUH_&L-4:S@&J$,3(3K*?TEK8P?Z5Y`5,4%<7H'-:J"7`]B7#)3SP1H\X9
      M4[3WV%'F&$LJ0@UUG?K^$PP45/PS3Y@V"IH"=43::/.'2!>9:"\@6)`JN`V%
      M"1<R!G*#M50:\\ER!N$C\YA>RDTY>2"=!$1,)!YD4)OBTJ>>G^0[5++3P3R+
      M>(W$;2*-<)=,7#H:E/@B/4G5]'H#'B]%B;4PIW+9/<V@?H";<8-^6E`=U.1\ M5(7O.N/&:Y$,),K,M")%"M#&:\:+L\C6\1AG`/$FW&3>6HX6^OQ]P,+HS5I&
      M>1XCX,Z>EZ?G)HJU>7%Y-=`&M[<WMS%TK.;W_?Y`55.ZQOO>Q;R5UC*O?5`)
      MIJN,L'05I5#$G.!`:%-6EH*&LC>?T,.JAW[RJ![@"C2EP<0UT![WKBXJ%>D(
      M7T_FE--$D[^5*`5';:M(J7NWY&%OR4GDW&]+DV,B2[+A?L/Q37P2N21P->X$
      M2HY,N8`EY<-;:###`'I849"GN(@,)FJ5-%9,ISR3FB[F_`>LWB,N?/`G;F@;
      M3B6`$<525=0`/E8L6'[RTA;O?X5(DT#D_C)()4:%,Q61]"5-P#`/.'Y1P,I-
      M&MPY[@,.8/7X@,G<Y<0X&A%(?G6=X"V*6J$F3^R1-8\$6(DZ?HY1^/MU;)`H
      M4(3"Q<WMN[.A=GTSU&X'_9LWUY?_')R?<,GY&9A<N`-7RD*$-')OAP5YK*^4
      M"1:K/9Y`R!3K\4!SS2A0_#R7R@4L)TX[[0N%ZTF2TH3W*C(E1B,RN^5SEYI4
      MCJ\XJ<>L\3T2:K&`*6[RTDSQ2>68VMM+L[24"H@QS[EQ'ECFJ;ZXG$A7U7&]
      M#ZCH]K)P2IT@A_=E_&72QUJ+H(\5KSM-L?%(^;`43$5X-@BR^7JSI@2/,KVD
      M^H*$L&6VM].06_?8(V_J;FW39MSD.[7B<@XS5K5A,XVXH_://MSNCS[<ZNM'
      M'^ZOWH?[/AZ8>Z6/-@$:@'6P*'EQ("E[5UZ-Y2N:,J)CRUD$[\$PI/+8ZX!G
      M@,Y:>:+#?:M/['M$B$[EZ)/5:<(4,/I/$W=*>9KXD2-^Y(B_5HYX:IEH"!.N
      M;L[.![>\5M1^V4U:^`O#N\LM?-F^3]_19Z"I<_B>-)P>C4&JJ.0%Y\:]^ZBV
      MO+=8$**_R*IWHX;5`J84H=H:".,.$5Z\6<!W]L1^(#,_N\'/TA";FE6MB2S2
      M"59$N1T'A>BZRPS1.'!!5#15P`#D#0.1A'F5SN=/N1\C5T5**]4H6%`85VC!
      MIKQ8M5!;8]>\,#W:Y:ZQLUV8*/:BV]U_/N9^:V\5BQ%ML&/+D[N@!9<'NKH3
      M>2H<.>6:Z39@A.[;XEBV/?>4.K@:;+#EBW[1V6EK?@"`"6C]#S%68-BMK;4!
      M7(%A^3N<_6[9[W!6H5_^MFV_>#MXT*X?I+YMP\?#X]2'W1<<]RV5S8)OJ2>E
      M^@5??^50LNN6@4P.\9)34\QP]\2>=^[UD&'-%&B>ZQ=T\U,0<"H"64B*C\G9
      M8`8F?40HON_63)=IXF3/7W%R)ZF>FCZE=XI9AS:N'X/!6VUP77#B4IZ$E+U0
      MBCGIE#@1$^I@6$V?(A00121/Q(#F"AQ&YLPAI?H,<U^ED44X9^RW3`6^1%_%
      M\?^N`$],ZB+;5>#CVPO0=1LSA?/_R^#,^?IT>Z&9]]'IBL`\ZM:/CI/`Q,?4
      M%]H\6,2Q?^$Z@4#"K/-CSWA`N!H_G4;)/.YHEBA=3W9VDQ(R7J033X4O\U./
      M@-HVFOY$9NN=&#8^LT<Z8CU`!^&2HVZ,S+!P4KYD67)AD5XE3\_CTV8^_A^8
      '+.HH3#0`````
      `
      end