diff options
Diffstat (limited to 'lib/lego')
| -rw-r--r-- | lib/lego/llp.h | 4 | ||||
| -rw-r--r-- | lib/lego/styx.c | 1113 | ||||
| -rw-r--r-- | lib/lego/styx.srec | 329 | ||||
| -rw-r--r-- | lib/lego/styx_abp.srec | 331 |
4 files changed, 1777 insertions, 0 deletions
diff --git a/lib/lego/llp.h b/lib/lego/llp.h new file mode 100644 index 00000000..db2c956f --- /dev/null +++ b/lib/lego/llp.h @@ -0,0 +1,4 @@ +#define LLP_ALTERNATING 0x01 +#define LLP_POLL_IMMEDIATE 0x02 +#define LLP_POLL_PERIODIC 0x04 +#define LLP_COMPRESSION 0x08 diff --git a/lib/lego/styx.c b/lib/lego/styx.c new file mode 100644 index 00000000..4c91953d --- /dev/null +++ b/lib/lego/styx.c @@ -0,0 +1,1113 @@ +/* + * styx.c + * + * A Styx fileserver for a Lego RCX + * + * Nigel Roles + * Vita Nuova + * + * This is a heavily modified version of test5.c + * + * I couldn't have done this without Kekoa... + * + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Librcx sample program code, released February 9, + * 1999. + * + * The Initial Developer of the Original Code is Kekoa Proudfoot. + * Portions created by Kekoa Proudfoot are Copyright (C) 1999 + * Kekoa Proudfoot. All Rights Reserved. + * + * Contributor(s): Kekoa Proudfoot <kekoa@graphics.stanford.edu> + */ + +//#include "stdlib.h" +#include "rom.h" + +#include "lib9.h" +#include "styx.h" + +#include "llp.h" + +#define ASSERT(cond) if (!(cond)) fatal(__LINE__) +#define FATAL fatal(__LINE__) +#define PROGRESS progress(__LINE__) + +#if 0 +#define ABP +#endif + +uchar *send_fid_reply_payload(void); +void send_fid_reply(uchar type, ushort tag, ushort fid, uchar *msg, short len); +void send_error_reply(unsigned short tag, char *msg); + +static unsigned short msgcount; +static unsigned char compressed_incoming[150]; +static unsigned char incoming[1024]; +static unsigned char compressed_reply[150]; +short compressed_reply_len; +static unsigned char reply[1024]; +unsigned short reply_len; +unsigned short transmitted_reply_len; +unsigned char alternating_bit; +static uchar dir[116]; +uchar prepared; +uchar reader_count; +uchar dispatch[6]; + +/* ROM pseudofunctions */ + +static inline void +set_data_pointer (void *ptr) +{ + play_sound_or_set_data_pointer(0x1771, (short)ptr, 0); +} + +static inline char +check_valid (void) +{ + char valid; + check_for_data(&valid, NULL); + return valid; +} + +static inline int +receive_message (void *ptr, int len) +{ + char bytes = 0; + receive_data(ptr, len, &bytes); + /* Bytes includes checksum, since we don't want that, return bytes-1 */ + return bytes - 1; +} + +static inline void +send_message (void *ptr, int len) +{ + if (len) + while (send_data(0x1776, 0, ptr, len)); +} + +int +poll_power(void) +{ + static short debounce = 0; + static short state = -1; + short status; + get_power_status(0x4000, &status); + if (state != status) + debounce = 0; + else if (debounce < 10) + debounce++; + state = status; + return debounce >= 10 ? state : -1; +} + +static void +progress(short line) +{ + set_lcd_number(LCD_UNSIGNED, line, LCD_DECIMAL_0); + refresh_display(); +} + +static void +fatal(short line) +{ + set_lcd_segment(LCD_STANDING); + progress(line); + while (poll_power() != 0) + ; +} + +typedef struct Reader { + ushort tag; + ushort fid; + ushort offset; + ushort count; + struct Reader *next; +} Reader; + +typedef struct DirectoryEntry { + char *name; + uchar qid; + const struct DirectoryEntry *sub; + short (*read)(const struct DirectoryEntry *dp, ushort tag, ushort fid, ushort offset, ushort count); + short (*write)(const struct DirectoryEntry *dp, ushort offset, ushort count, uchar *buf); +} DirectoryEntry; + +#define QID_ROOT 0 +#define QID_MOTOR 1 +#define QID_MOTOR_0 2 +#define QID_MOTOR_1 3 +#define QID_MOTOR_2 4 +#define QID_MOTOR_012 5 +#define QID_SENSOR 6 +#define QID_SENSOR_0 7 +#define QID_SENSOR_1 8 +#define QID_SENSOR_2 9 + +typedef struct Sensor { + sensor_t sensor; + uchar active; + uchar greater; + ushort thresh; + Reader *reader; +} Sensor; + +Sensor sensor[3]; + +short +atoin(char *s, short lim) +{ + short total = 0; + while (*s && lim) { + char c = *s++; + if (c >= '0' && c <= '9') + total = total * 10 + c - '0'; + else + break; + lim--; + } + return total; +} + +short +itoa(char *buf, short value) +{ + char *bp = buf; + short divisor; + if (value < 0) { + *bp++ = '-'; + value = -value; + } + if (value == 0) + *bp++ = '0'; + else { + divisor = 10000; + while (divisor > value) + divisor /= 10; + while (divisor) { + *bp++ = '0' + value / divisor; + value %= divisor; + divisor /= 10; + } + } + return bp - buf; +} + +Reader * +readercreate(ushort tag, ushort fid, ushort offset, ushort count) +{ + Reader *rp = malloc(sizeof(Reader)); + rp->tag = tag; + rp->fid = fid; + rp->offset = offset; + rp->count = count; + rp->next = 0; + reader_count++; + return rp; +} + +void +readerfree(Reader *rp) +{ + free(rp); + reader_count--; +} + +int +senderrorreset(Reader *rp, void *magic) +{ + send_error_reply(rp->tag, "reset"); + return 1; +} + +void +readerlistfindanddestroy(Reader **rpp, int (*action)(Reader *rp, void *magic), void *magic) +{ + while (*rpp) { + Reader *rp = *rpp; + if ((*action)(rp, magic)) { + *rpp = rp->next; + readerfree(rp); + } + else + rpp = &(rp->next); + } +} + +void +allreaderlistfindanddestroy(int (*action)(Reader *rp, void *magic), void *magic) +{ + short i; + for (i = 0; i < 3; i++) + readerlistfindanddestroy(&sensor[i].reader, action, magic); +} + +short +sensorwrite(const DirectoryEntry *dp, ushort offset, ushort count, uchar *data) +{ + short i; + Sensor *sp; + uchar greater; + short type, mode; + ushort k; + + if (offset != 0) + return -1; + i = dp->qid - QID_SENSOR_0; + sp = &sensor[i]; + k = count; + if (k == 0) + return -1; + switch (data[0]) { + case 'b': + type = SENSOR_TYPE_TOUCH; + mode = SENSOR_MODE_PULSE; + break; + case 'l': + type = SENSOR_TYPE_TOUCH; + mode = SENSOR_MODE_RAW; + break; + default: + return -1; + } + data++; k--; + if (k == 0) + return -1; + if (*data == '>') { + greater = 1; + data++; + k--; + } + else if (*data == '<') { + greater = 0; + data++; + k--; + } + else + greater = 1; + if (k == 0) + return -1; + readerlistfindanddestroy(&sp->reader, senderrorreset, 0); + set_sensor_passive(SENSOR_0 + i); + sp->sensor.type = type; + sp->sensor.mode = mode; + sp->thresh = atoin(data, k); + sp->sensor.raw = 0; + sp->sensor.value = 0; + sp->sensor.boolean = 0; + sp->active = 1; + sp->greater = greater; + set_sensor_active(SENSOR_0 + i); + return count; +} + +void +send_read_reply(ushort tag, ushort fid, ushort offset, ushort len, uchar *answer, short answerlen) +{ + uchar *out = send_fid_reply_payload(); + ushort actual; + if (offset < answerlen) { + actual = answerlen - offset; + if (actual > len) + actual = len; + memcpy(out + 3, answer + offset, actual); + } + else + actual = 0; + out[0] = actual; + out[1] = actual >> 8; + out[2] = 0; + send_fid_reply(Rread, tag, fid, 0, actual + 3); +} + +void +send_sensor_read_reply(ushort tag, ushort fid, ushort offset, ushort count, short value) +{ + short answerlen; + char answer[8]; + /* reply is countlow counthigh pad data[count] */ + answerlen = itoa(answer, value); + send_read_reply(tag, fid, offset, count, answer, answerlen); +} + +int +sensortriggered(Sensor *sp) +{ + if (sp->greater) + return sp->sensor.value >= sp->thresh; + else + return sp->sensor.value < sp->thresh; +} + +short +sensorread(const struct DirectoryEntry *dp, ushort tag, ushort fid, ushort offset, ushort count) +{ + short i; + Sensor *sp; + i = dp->qid - QID_SENSOR_0; + sp = sensor + i; + if (!sp->active) + return -1; + if (sensortriggered(sp)) + send_sensor_read_reply(tag, fid, offset, count, sp->sensor.value); + else { + /* add to queue */ + Reader *rp = readercreate(tag, fid, offset, count); + rp->next = sp->reader; + sp->reader = rp; + } + return 0; +} + +void +sensorpoll(void) +{ + short i; + Sensor *sp; + + if ((dispatch[0] & 0x80) == 0) { + return; + } + dispatch[0] &= 0x7f; + /* do the following every 3 ms with a following wind */ + for (i = 0; i < 3; i++) { + sp = sensor + i; + if (sp->active) { + /* + * read sensor 4 times to reduce debounce on each + * edge to effectively 25 counts, or 75ms + * allowing about 8 pulses a second + */ + read_sensor(SENSOR_0 + i, &sp->sensor); + read_sensor(SENSOR_0 + i, &sp->sensor); + read_sensor(SENSOR_0 + i, &sp->sensor); + read_sensor(SENSOR_0 + i, &sp->sensor); + if (sensortriggered(sp)) { + /* complete any outstanding reads */ + while (sp->reader) { + Reader *rp = sp->reader; + sp->reader = rp->next; + send_sensor_read_reply(rp->tag, rp->fid, rp->offset, rp->count, sp->sensor.value); + readerfree(rp); + } + } + } + } +} + +short +motorparse(uchar *flag, short *mode, short *power, uchar *data) +{ + switch (data[0]) { + case 'f': *mode = MOTOR_FWD; break; + case 'r': *mode = MOTOR_REV; break; + case 's': *mode = MOTOR_STOP; break; + case 'F': *mode = MOTOR_FLOAT; break; + case '-': return 1; + default: + return 0; + } + if (data[1] >= '0' && data[1] <= '7') + *power = data[1] - '0'; + else + return 0; + *flag = 1; + return 1; +} + +short +motorwrite(const DirectoryEntry *dp, ushort offset, ushort count, uchar *data) +{ + short mode[3], power[3]; + uchar flag[3]; + short i; + + if (offset != 0) + return -1; + flag[0] = flag[1] = flag[2] = 0; + if (dp->qid == QID_MOTOR_012) { + if (count != 6) + return -1; + if (!motorparse(flag, mode, power, data) + || !motorparse(flag + 1, mode + 1, power + 1, data + 2) + || !motorparse(flag + 2, mode + 2, power + 2, data + 4)) + return -1; + } + else { + if (count != 2) + return -1; + i = dp->qid - QID_MOTOR_0; + if (!motorparse(flag + i, mode + i, power + i, data)) + return -1; + } + for (i = 0; i < 3; i++) + if (flag[i]) + control_motor(MOTOR_0 + i, mode[i], power[i]); + return count; +} + +const uchar qid_root[8] = { QID_ROOT, 0, 0, 0x80 }; + +const DirectoryEntry dir_root[], dir_slash[]; + +const DirectoryEntry dir_motor[] = { + { "..", QID_ROOT, dir_root }, + { "0", QID_MOTOR_0, 0, 0, motorwrite }, + { "1", QID_MOTOR_1, 0, 0, motorwrite }, + { "2", QID_MOTOR_2, 0, 0, motorwrite }, + { "012", QID_MOTOR_012, 0, 0, motorwrite }, + { 0 } +}; + +const DirectoryEntry dir_sensor[] = { + { "..", QID_ROOT, dir_root }, + { "0", QID_SENSOR_0, 0, sensorread, sensorwrite }, + { "1", QID_SENSOR_1, 0, sensorread, sensorwrite }, + { "2", QID_SENSOR_2, 0, sensorread, sensorwrite }, + { 0 } +}; + +const DirectoryEntry dir_root[] = { + { "..", QID_ROOT, dir_slash }, + { "motor", QID_MOTOR, dir_motor }, + { "sensor", QID_SENSOR, dir_sensor }, + { 0 } +}; + +const DirectoryEntry dir_slash[] = { + { "/", QID_ROOT, dir_root }, + { 0 } +}; + +const DirectoryEntry *qid_map[] = { + /* QID_ROOT */ &dir_slash[0], + /* QID_MOTOR */ &dir_root[1], + /* QID_MOTOR_0 */ &dir_motor[1], + /* QID_MOTOR_1 */ &dir_motor[2], + /* QID_MOTOR_2 */ &dir_motor[3], + /* QID_MOTOR_012 */ &dir_motor[4], + /* QID_SENSOR */ &dir_root[2], + /* QID_SENSOR_0 */ &dir_sensor[1], + /* QID_SENSOR_1 */ &dir_sensor[2], + /* QID_SENSOR_2 */ &dir_sensor[3], +}; + +#define QID_MAP_MAX (sizeof(qid_map) / sizeof(qid_map[0])) + +typedef struct Fid { + struct Fid *next; + ushort fid; + uchar open; + uchar qid[8]; +} Fid; + +Fid *fids; + +Fid * +fidfind(ushort fid) +{ + Fid *fp; + for (fp = fids; fp && fp->fid != fid; fp = fp->next) + ; + return fp; +} + +Fid * +fidcreate(ushort fid, const uchar qid[8]) +{ + Fid *fp; + fp = malloc(sizeof(Fid)); + ASSERT(fp); + fp->open = 0; + fp->fid = fid; + fp->next = fids; + memcpy(fp->qid, qid, 8); + fids = fp; + return fp; +} + +int +matchfp(Reader *rp, void *magic) +{ + if (rp->fid == ((Fid *)magic)->fid) { + return 1; + } + return 0; +} + +void +fiddelete(Fid *fp) +{ + Fid **fpp; + /* clobber any outstanding reads on this fid */ + allreaderlistfindanddestroy(matchfp, fp); + /* now clobber the fid */ + for (fpp = &fids; *fpp; fpp = &(*fpp)->next) + if (*fpp == fp) { + *fpp = fp->next; + free(fp); + return; + } + FATAL; +} + +const DirectoryEntry * +nthentry(const DirectoryEntry *dp, ushort n) +{ + const DirectoryEntry *sdp; + ASSERT(dp->sub); + for (sdp = dp->sub; sdp->name; sdp++) + if (strcmp(sdp->name, "..") != 0) { + if (n == 0) + return sdp; + n--; + } + return 0; +} + +int +fidwalk(Fid *fp, char name[28]) +{ + const DirectoryEntry *sdp; + const DirectoryEntry *dp; + + if (fp->open) + return -1; + ASSERT(fp->qid[0] < QID_MAP_MAX); + dp = qid_map[fp->qid[0]]; + if (dp->sub == 0) + return -1; + for (sdp = dp->sub; sdp->name; sdp++) + if (strcmp(sdp->name, name) == 0) { + fp->qid[0] = sdp->qid; + fp->qid[3] = sdp->sub ? 0x80 : 0; + return 1; + } + return 0; +} + +void +mkdirent(const DirectoryEntry *dp, uchar *dir) +{ + memset(dir, 0, DIRLEN); + strcpy(dir, dp->name); + strcpy(dir + 28, "lego"); + strcpy(dir + 56, "lego"); + dir[84] = dp->qid; + dir[92] = dp->sub ? 0555 : 0666; + dir[93] = dp->sub ? (0555 >> 8) : (0666 >> 8); + dir[95] = dp->sub ? 0x80 : 0; +} + +int +fidstat(Fid *fp, uchar *dir) +{ + const DirectoryEntry *dp; + if (fp->open) + return -1; + ASSERT(fp->qid[0] < QID_MAP_MAX); + dp = qid_map[fp->qid[0]]; + mkdirent(dp, dir); + return 1; +} + +int +fidopen(Fid *fp, uchar mode) +{ + if (fp->open + || (mode & ORCLOSE) + /*|| (mode & OTRUNC) */) + return 0; + if (fp->qid[3] && (mode == OWRITE || mode == ORDWR)) + /* can't write directories */ + return 0; + fp->open = 1; + return 1; +} + +short +fidread(Fid *fp, ushort tag, ushort offset, ushort count) +{ + short k; + uchar *p; + const DirectoryEntry *dp; + uchar *buf; + + ASSERT(fp->qid[0] < QID_MAP_MAX); + dp = qid_map[fp->qid[0]]; + + if (fp->qid[3] & 0x80) { + if (!fp->open) + return -1; + if (count % DIRLEN != 0 || offset % DIRLEN != 0) + return -1; + count /= DIRLEN; + offset /= DIRLEN; + buf = send_fid_reply_payload(); + p = buf + 3; + for (k = 0; k < count; k++) { + const DirectoryEntry *sdp = nthentry(dp, offset + k); + if (sdp == 0) + break; + mkdirent(sdp, p); + p += DIRLEN; + } +/* a read beyond just returns 0 + if (k == 0 && count) + return -1; +*/ + k *= DIRLEN; + buf[0] = k; + buf[1] = k >> 8; + buf[2] = 0; + send_fid_reply(Rread, tag, fp->fid, 0, k + 3); + return 0; + } + /* right, that's that out of the way */ + if (!dp->read) + return -1; + return (*dp->read)(dp, tag, fp->fid, offset, count); +} + +short +fidwrite(Fid *fp, ushort offset, ushort count, uchar *buf) +{ + const DirectoryEntry *dp; + if (fp->qid[3] & 0x80) + return -1; /* can't write directories */ + if (!fp->open) + return -1; + ASSERT(fp->qid[0] < QID_MAP_MAX); + dp = qid_map[fp->qid[0]]; + if (!dp->write) + return -1; /* no write method */ + return (*dp->write)(dp, offset, count, buf); +} + +int +rlencode(unsigned char *out, int limit, unsigned char *in, int len) +{ + unsigned char *ip, *op; + int oc, zc; + + if (len == 0) + return -1; + ip = in; + op = out; + zc = 0; + + oc = 0; + + for (;;) { + int last = ip >= in + len; + if (*ip != 0 || last) + { + switch (zc) { + case 1: + if (oc >= len - 1) + return -1; + *op++ = 0; + oc++; + break; + case 2: + if (oc >= len - 2) + return -1; + *op++ = 0; + *op++ = 0; + oc += 2; + break; + case 0: + break; + default: + if (oc >= len - 2) + return -1; + *op++ = 0x88; + *op++ = zc - 2; + oc += 2; + break; + } + zc = 0; + } + if (last) + break; + if (*ip == 0x88) { + if (oc >= len - 2) + return -1; + *op++ = 0x88; + *op++ = 0x00; + oc += 2; + } + else if (*ip == 0x00) + { + zc++; + } + else { + if (oc >= len - 1) + return -1; + *op++ = *ip; + oc++; + } + ip++; + } + return oc; +} + +int +rldecode(unsigned char *out, unsigned char *in, int len) +{ + int oc, k; + + oc = 0; + + while (len) { + if (*in != 0x88) { + *out++ = *in++; + oc++; + len--; + continue; + } + in++; + switch (*in) { + case 0: + *out++ = 0x88; + oc++; + break; + default: + k = *in + 2; + oc += k; + while (k-- > 0) + *out++ = 0; + } + in++; + len -= 2; + } + return oc; +} + +void +prepare_transmission(void) +{ + if (prepared) + return; + compressed_reply_len = rlencode(compressed_reply + 3, sizeof(compressed_reply) - 3, reply, reply_len); + if (compressed_reply_len < 0) { + memcpy(compressed_reply + 3, reply, reply_len); + compressed_reply_len = reply_len; + compressed_reply[2] = 0x0; + } + else + compressed_reply[2] = LLP_COMPRESSION; + if (reader_count) + compressed_reply[2] |= LLP_POLL_PERIODIC; + compressed_reply[2] |= !alternating_bit; + compressed_reply_len++; + compressed_reply[0] = compressed_reply_len; + compressed_reply[1] = compressed_reply_len >> 8; + compressed_reply_len += 2; + prepared = 1; +} + +void +transmit(void) +{ + prepare_transmission(); + transmitted_reply_len = reply_len; + send_message(compressed_reply, compressed_reply_len); +} + +void +flush_reply_buffer(void) +{ + if (reply_len > transmitted_reply_len) + memcpy(reply, reply + transmitted_reply_len, reply_len - transmitted_reply_len); + reply_len -= transmitted_reply_len; + prepared = 0; +} + +void +send_reply(unsigned char type, unsigned short tag, unsigned char *msg, short len) +{ + uchar *p = reply + reply_len; + p[0] = type; + p[1] = tag & 0xff; + p[2] = tag >> 8; + if (msg) + memcpy(p + 3, msg, len); + reply_len += len + 3; + prepared = 0; +} + +void +send_error_reply(unsigned short tag, char *msg) +{ + short len; + uchar *p = reply + reply_len; + p[0] = Rerror; + p[1] = tag & 0xff; + p[2] = tag >> 8; + len = (short)strlen(msg); + if (len > 64) + len = 64; + memcpy(p + 3, msg, len); + reply_len += 67; + prepared = 0; +} + +uchar * +send_fid_reply_payload(void) +{ + return reply + reply_len + 5; +} + +void +send_fid_reply(uchar type, ushort tag, ushort fid, uchar *msg, short len) +{ + uchar *p = reply + reply_len; + p[0] = type; + p[1] = tag & 0xff; + p[2] = tag >> 8; + p[3] = fid & 0xff; + p[4] = fid >> 8; + if (msg) + memcpy(p + 5, msg, len); + reply_len += len + 5; + prepared = 0; +} + +int +matchtag(Reader *rp, void *oldtag) +{ + if (rp->tag == (ushort)oldtag) { + return 1; + } + return 0; +} + +void +flushtag(ushort oldtag) +{ + /* a little inefficient this - there can be at most one match! */ + allreaderlistfindanddestroy(matchtag, (void *)oldtag); +} + +void +process_styx_message(unsigned char *msg, short len) +{ + unsigned char type; + ushort tag, oldtag, fid, newfid; + ushort offset, count; + short extra; + Fid *fp, *nfp; + short written; + uchar buf[2]; + + ASSERT(len >= 3); + + type = *msg++; len--; + tag = (msg[1] << 8) | msg[0]; len -= 2; msg += 2; + + switch (type) { + case Tnop: + send_reply(Rnop, tag, 0, 0); + goto done; + case Tflush: + ASSERT(len == 2); + oldtag = (msg[1] << 8) | msg[0]; + flushtag(oldtag); + send_reply(Rflush, tag, 0, 0); + goto done; + } + /* all other messages take a fid as well */ + ASSERT(len >= 2); + fid = (msg[1] << 8) | msg[0]; len -= 2; msg += 2; + fp = fidfind(fid); + + switch (type) { + case Tattach: + ASSERT(len == 56); + if (fp) { + fid_in_use: + send_error_reply(tag, "fid in use"); + } + else { + fp = fidcreate(fid, qid_root); + send_fid_reply(Rattach, tag, fid, fp->qid, 8); + } + break; + case Tclunk: + case Tremove: + ASSERT(len == 0); + if (!fp) { + no_such_fid: + send_error_reply(tag, "no such fid"); + } + else { + fiddelete(fp); + if (type == Tremove) + send_error_reply(tag, "can't remove"); + else + send_fid_reply(Rclunk, tag, fid, 0, 0); + } + break; + case Tclone: + ASSERT(len == 2); + newfid = (msg[1] << 8) | msg[0]; + nfp = fidfind(newfid); + if (!fp) + goto no_such_fid; + if (fp->open) { + send_error_reply(tag, "can't clone"); + break; + } + if (nfp) + goto fid_in_use; + nfp = fidcreate(newfid, fp->qid); + send_fid_reply(Rclone, tag, fid, 0, 0); + break; + case Twalk: + ASSERT(len == 28); + if (!fidwalk(fp, msg)) + send_error_reply(tag, "no such name"); + else + send_fid_reply(Rwalk, tag, fid, fp->qid, 8); + break; + case Tstat: + ASSERT(len == 0); + if (!fidstat(fp, dir)) + send_error_reply(tag, "can't stat"); + else + send_fid_reply(Rstat, tag, fid, dir, 116); + break; + ASSERT(len == 0); + case Tcreate: + ASSERT(len == 33); + send_error_reply(tag, "can't create"); + break; + case Topen: + ASSERT(len == 1); + if (!fidopen(fp, msg[0])) + send_error_reply(tag, "can't open"); + else + send_fid_reply(Ropen, tag, fid, fp->qid, 8); + break; + case Tread: + ASSERT(len == 10); + offset = (msg[1] << 8) | msg[0]; + count = (msg[9] << 8) | msg[8]; + if (fidread(fp, tag, offset, count) < 0) + send_error_reply(tag, "can't read"); + break; + case Twrite: + ASSERT(len >= 11); + offset = (msg[1] << 8) | msg[0]; + count = (msg[9] << 8) | msg[8]; + msg += 11; + len -= 11; + ASSERT(count == len); + written = fidwrite(fp, offset, count, msg); + if (written < 0) + send_error_reply(tag, "can't write"); + else { + buf[0] = written; + buf[1] = written >> 8; + send_fid_reply(Rwrite, tag, fid, buf, 2); + } + break; + default: + FATAL; + } +done: + ; +} + +void +process_llp_message(unsigned char *msg, short len) +{ + short styxlen; + switch (msg[0]) { + case 0x45: + case 0x4d: + if (len != 5) + FATAL; + styxlen = compressed_incoming[0] | (compressed_incoming[1] << 8); + /* transfer the transmitted checksum to the end */ + compressed_incoming[styxlen + 2 - 1] = msg[3]; + /* check alternating bit */ +#ifdef ABP + if ((compressed_incoming[2] & 1) != alternating_bit || + ((msg[0] & 8) != 0) != alternating_bit) { + transmit(); + break; + } +#endif + alternating_bit = !alternating_bit; + flush_reply_buffer(); + if (styxlen > 1) { + if (compressed_incoming[2] & LLP_COMPRESSION) { + /* decompress everything but length and link header */ + styxlen = rldecode(incoming, compressed_incoming + 3, styxlen - 1); + process_styx_message(incoming, styxlen); + } + else + process_styx_message(compressed_incoming + 3, styxlen - 1); + } + transmit(); + break; + default: + FATAL; + } +} + +int +main (void) +{ + int count = 0; + char buf[16]; + char temp[64]; + + mem_init(); + memset(temp,0, sizeof(temp)); + + /* Initialize */ + + init_timer(&temp[6], &dispatch[0]); + init_power(); + init_sensors(); + init_serial(&temp[4], &temp[6], 1, 1); + + set_lcd_number(LCD_UNSIGNED, 0, LCD_DECIMAL_0); + set_lcd_segment(LCD_WALKING); + refresh_display(); + + set_data_pointer(compressed_incoming); + + alternating_bit = 0; + compressed_reply_len = 0; + reply_len = 0; + prepared = 0; + + while (poll_power() != 0) { + + /* If a message has arrived, send a response with opcode inverted */ + + if (check_valid()) { + int len = receive_message(buf, sizeof(buf)); + msgcount++; + process_llp_message(buf, len); + } + sensorpoll(); + } + + return 0; +} diff --git a/lib/lego/styx.srec b/lib/lego/styx.srec new file mode 100644 index 00000000..687a50aa --- /dev/null +++ b/lib/lego/styx.srec @@ -0,0 +1,329 @@ +S00C0000737479782E7372656340
+S11880006DF06DF16DF26DF35E00967E6D736D726D716D7054AD
+S118801570446F20796F7520627974652C207768656E20492057
+S10B802A6B6E6F636B3F0000F5
+S11880326DF60D761B870D621B8279014000790029F25E00965F
+S1188047AC6B039A0A6F62FFFE1D23470819226B829A084012E9
+S118805C6B039A08790200091D234E060B036B839A086F61FF76
+S1188071FE6B819A0A6B039A08790200097900FFFF1D234F02CC
+S11880860D100B876D7654706DF60D760D02790330026DF3790F
+S118809B01301F79001FF25E0096BC0B87790027C85E0096D480
+S11880B06D7654706DF60D766DF40D047901300679001B625EB4
+S11880C50096DE0D405E00808E5E0080320D0046F86D746D7656
+S11880DA54706DF60D766DF40D041900684B473C0D1147380B7A
+S11880EF040CBA8AD0AA09422E0CB8F00088D090FF1B01684BC7
+S118810447200D11471C0B040CBA8AD0AA0942120D0209220901
+S118811922092009000CBAF200092040D66D746D7654706DF617
+S118812E0D761B871B876DF46DF56FE0FFFE0D146FE0FFFC0DEA
+S1188143444C16FA2D688A6F62FFFE0D230B036FE3FFFC170CE8
+S118815817040B040D444610FA306F63FFFC68BA0B036FE3FFC5
+S118816DFC404C790527101D454F407901000A0D505E0096EA0C
+S11881820D051D454EF0402E0D510D405E0096EA0C8A8A306F7C
+S118819763FFFC68BA0B036FE3FFFC0D510D405E0096FC0D0448
+S11881AC7901000A0D505E0096EA0D050D5546CE6F62FFFC6F38
+S11881C163FFFE19326FE2FFFC6F60FFFC6D756D740B870B87FD
+S11881D66D7654706DF60D761B876DF46DF50D040D156FE2FF1B
+S11881EBFE7900000A5E00972269846F8500026F62FFFE6F8241
+S118820000046F6200046F82000619226F8200086A0AA40A8AB5
+S1188215016A8AA40A6D756D740B876D7654706DF60D765E006D
+S118822A979C6A0AA40A8AFF6A8AA40A6D7654706DF60D7669C5
+S118823F00790198885E008FD6790000016D7654706DF60D76C2
+S11882541B871B876DF46DF50D056FE1FFFE6FE2FFFC40266990
+S1188269546F61FFFC0D406F62FFFE5D200D00470E6F4200082A
+S118827E69D20D405E0082244006790500080945695246D66DFD
+S1188293756D740B870B876D7654706DF60D761B871B876DF426
+S11882A86DF56FE0FFFE6FE1FFFC19557904A3DC6F62FFFC6F1F
+S11882BD61FFFE0D405E0082508C0E94000B05790200021D25D0
+S11882D24FE46D756D740B870B876D7654706DF60D7679030070
+S11882E70C19376DF46DF56FE2FFFE6F6400040D1147045A0077
+S11882FC83FE6E080002F00088F990FF6FE0FFFC6F65FFFC094E
+S11883115509550955190509557902A3D009520D256F62FFFE7D
+S118832646045A0083FE684BF300790200621D23470C79020088
+S118833B6C1D23470A5A0083FE79020060400219226FE2FFF8B1
+S11883500B046F63FFFE1B030D3346045A0083FE684AAA3E46D3
+S118836504FA014006AA3C460C18AA6EEAFFFB0B041B034006FB
+S118837AFA016EEAFFFB0D3346045A0083FE7901823A0D50881D
+S118838F0C900019226FE3FFF45E0082506F62FFFC8A00921091
+S11883A46FE2FFF66F61FFF6790019C45E0096DEFA0168DA6EE2
+S11883B96AFFF96EDA00016F63FFF40D310D405E0080DC6FD0B7
+S11883CE000A19226FD200026FD200046EDA0006FA016EDA0038
+S11883E3086E6AFFFB6EDA00096F61FFF6790019465E0096DEE7
+S11883F86F60FFFE40047900FFFF6D756D747903000C09376DED
+S118840D7654706DF60D767903000619376DF46DF56FE0FFFE55
+S11884226FE1FFFC0D256F6400085E0090340D031D45443219C6
+S1188437546F6000041D0443046F6400046F62000609526FE243
+S118844C00060D300B800B000D426F6100066FE3FFFA5E0097D9
+S1188461AE6F63FFFA4002194468BC0D420C2A18226EBA0001DE
+S118847618AA6EBA00020B840B046DF419226DF26F62FFFC6F2D
+S118848B61FFFEF80F5E0090480B870B876D756D7479030006D4
+S11884A009376D7654706DF60D767903000C19376DF46DF56FEC
+S11884B5E0FFF66FE1FFF40D257904FFF809646F6100060D4060
+S11884CA5E00812C6DF06DF46F6200046DF20D526F61FFF46F0B
+S11884DF60FFF65E0084108F0697006D756D747903000C093786
+S11884F46D7654706DF60D766E0A0009471019116F0300046FFB
+S118850902000A1D234514400E19116F0300046F02000A1D230B
+S118851E4404790100010D106D7654706DF60D761B876DF46D67
+S1188533F56FE1FFFE0D256E0A0002F2008AF992FF0D240944BD
+S118854809440944192409447902A3D009420D246E4A00084686
+S118855D067900FFFF404E0D405E0084F80D0047206F420004AA
+S11885726DF26F6200066DF26F6200040D516F60FFFE5E00847A
+S1188587A60B870B8740226F6200066DF26F6200040D516F6077
+S118859CFFFE5E0081DA6F42000C6F8200086FC0000C0B871974
+S11885B1006D756D740B876D7654706DF60D761B876DF46DF56A
+S11885C67903A400683A4D045A008686EA7F68BA19440D4509E0
+S11885DB5509550955194509557902A3D009520D256E5A00086F
+S11885F00D430B036FE3FFFE0CAA46045A0086768C0094100D32
+S1188605520D41790014C05E0096AC0D520D41790014C05E0077
+S118861A96AC0D520D41790014C05E0096AC0D520D4179001431
+S118862FC05E0096AC0D505E0084F80D00473840306F54000CD0
+S11886446F4200086FD2000C6F41000269406F5200046DF26F29
+S11886594200066DF26F4200045E0084A60D405E0082240B8741
+S118866E0B876F52000C46CA6F64FFFE790200021D244E045A4A
+S11886830085D86D756D740B876D7654706DF60D766DF46DF5DC
+S11886980D050D246F600004680BF300790200661D2347244E73
+S11886AD127902002D1D234750790200461D23472440327902CA
+S11886C200721D23470E0B021D23470E4022790200014010794F
+S11886D7020002400A7902000340047902000469926E0A000187
+S11886EC8AD0AA074304190040146E0A0001F2008AD092FF69F7
+S1188701C2FA0168DA790000016D756D746D7654706DF60D7696
+S11887167903001A19376DF46DF56FE2FFEE0D1147045A008818
+S118872B1A6EE9FFF26EE9FFF16EE9FFF06E0A0002AA054704D2
+S11887405A0087CC790200066F60FFEE1D2047045A00881A7939
+S118875504FFF409647905FFFA09657902FFF009626FE2FFECB1
+S118876A6F6300046DF30D420D516F60FFEC5E0086900B870D46
+S118877F0046045A00881A0D611B811B817900FFF109606F6252
+S118879400040B826DF21B826FE200047902FFF609625E00862B
+S11887A9900B870D00476A0D611B817900FFF209606F63000424
+S11887BE0B830B836DF37902FFF809624044790200026F63FF77
+S11887D3EE1D2346426E0B0002F3001B837900FFF409606FE0A7
+S11887E8FFEA0D3209227905FFFA09650D5109217904FFF00943
+S11887FD640D4009306F6300046DF36F63FFEA09230D325E00BF
+S118881286900B870D0046067900FFFF405019337904FFF40980
+S1188827647900FFF009606FE0FFE86F60FFE86C0A6FE0FFE86B
+S118883C0CAA471E0D318900912069426DF2695279001A4E6F7B
+S1188851E3FFE65E0096BC0B876F63FFE60B840B850B037902A5
+S118886600021D234FC66F60FFEE6D756D747903001A09376DE0
+S118887B7654706DF60D760D036B00A408400269000D00470896
+S11888906F0200021D3246F26D7654706DF60D761B876DF46DD8
+S11888A5F50D056FE1FFFE7900000E5E0097220D0446087900F0
+S11888BA02135E0080B418AA6ECA00046FC500026B02A4086948
+S11888CFC20D4088059000790200086F61FFFE5E0097AE6B8482
+S11888E4A4080D406D756D740B876D7654706DF60D766F03002E
+S11888F9026F1200021D23470419004004790000016D765470D8
+S118890E6DF60D766DF40D04790088F20D415E00829E7903A419
+S118892308401269301D40460A690269B25E00979C400E0D0326
+S1188938693246EA790002325E0080B46D746D7654706DF60D24
+S118894D766DF46DF50D040D156F4200044608790002395E0090
+S118896280B46F440004401C6940790198DC5E0097D20D004703
+S11889770A0D5546040D40400C1B058C0A9400694246E0190064
+S118898C6D756D746D7654706DF60D761B876DF46DF50D056F9C
+S11889A1E1FFFE6E5A000446226E5A0005AA0943087900024B1A
+S11889B65E0080B46E5A0005F20009226F229A0C6F220004461A
+S11889CB067900FFFF403E0D20690247360D0469406F61FFFEFC
+S11889E05E0097D20D00461E6E4A00026EDA00056F4200041872
+S11889F5BB0D224702FB806EDB000879000001400A8C0A94007C
+S1188A0A694246CC19006D756D740B876D7654706DF60D761B80
+S1188A1F876DF46DF56FE0FFFE0D157902007419110D505E00B2
+S1188A3498086F62FFFE69210D505E00981E0D50881C900079B6
+S1188A490400050D427901995E5E0097AE0D50883890000D42AC
+S1188A5E7901995E5E0097AE6F63FFFE6E3A00026EDA00546F67
+S1188A73320004FBB60D224702FB6D6EDB005CFA016EDA005DDE
+S1188A886F63FFFE6F32000418BB0D224702FB806EDB005F6D86
+S1188A9D756D740B876D7654706DF60D766DF46DF50D040D1555
+S1188AB26E4A000447067900FFFF40266E4A0005AA0943087991
+S1188AC700026B5E0080B46E4A0005F20009226F209A0C0D512A
+S1188ADC5E008A1A790000016D756D746D7654706DF60D766E47
+S1188AF10A000446107369460C6E0A0008470A89FFA901420491
+S1188B061900400AFA016E8A0004790000016D7654706DF60D6B
+S1188B1B767903000A19376DF46DF56FE0FFFE6FE1FFFC6FE24A
+S1188B30FFFA6E0A0005AA094308790002875E0080B46F60FF56
+S1188B45FE6E0A0005F20009226F229A0C6FE2FFF86E0A000880
+S1188B5AEA8046045A008C3A6E0A00044720790100746F60008E
+S1188B6F045E0098320D004610790100746F60FFFA5E00983280
+S1188B840D0047087900FFFF5A008C6C790100746F6000045E94
+S1188B990098446FE00004790100746F60FFFA5E0098446FE055
+S1188BAEFFFA5E0090346FE0FFF66F64FFF60B840B041955403B
+S1188BC30C0D415E008A1A8C7494000B056F6200041D2544122C
+S1188BD86F61FFFA09516F60FFF85E00894A0D0046DA0D5209D5
+S1188BED22092209221952092209220925095509556F63FFF685
+S1188C0268BD0D520C2A10021E226EBA000118AA6EBA00020B2D
+S1188C17850B056DF519226DF26F63FFFE6F3200026F61FFFC76
+S1188C2CF80F5E00904819000B870B8740326F60FFF86F03000B
+S1188C410647246F6200046DF26F60FFFA6DF06F60FFFE6F0213
+S1188C5600026F61FFFC6F60FFF85D300B870B8740047900FF05
+S1188C6BFF6D756D747903000A09376D7654706DF60D761B8739
+S1188C806DF46DF50D046FE1FFFE0D256E4A0008EA8046066EA4
+S1188C954A000446067900FFFF403C6E4A0005AA094308790005
+S1188CAA02B35E0080B46E4A0005F20009226F209A0C6F0200EA
+S1188CBF0847166F6200046DF26F0300080D526F61FFFE5D30D0
+S1188CD40B8740047900FFFF6D756D740B876D7654706DF60DCE
+S1188CE9761B876DF46DF56F63000446087900FFFF5A008DD243
+S1188CFE0D25194419116F6300040D5209326FE2FFFE40386806
+S1188D135BAB8846186F6200041B821D214CD4688B0B0018AACB
+S1188D28688A0B000B8140180CBB46040B0440106F6200041BF1
+S1188D3D021D214CB4688B0B000B010B0519336F62FFFE1D2567
+S1188D52450479030001685A46040D3347B2790200011D2447F9
+S1188D67124E060D4447584038790200021D24471A402E6F62C7
+S1188D7C00041B021D214D045A008CF618AA688A0B000B014047
+S1188D91346F6200041B821D214D045A008CF618AA688A0B00F9
+S1188DA640186F6200041B821D214D045A008CF6FA88688A0B00
+S1188DBB000CCA8AFE688A0B000B8119440D3346045A008D12D8
+S1188DD00D106D756D740B876D7654706DF60D761B876DF46D1B
+S1188DE5F50D040D2519226FE2FFFE0D55475E681AAA8847149E
+S1188DFA68CA0B010B046F62FFFE0B026FE2FFFE1B0540E20B9D
+S1188E0F016818F0000D00461468CA0B046F62FFFE0B026FE205
+S1188E24FFFE0B011B8540C40D030B836F62FFFE09326FE2FF91
+S1188E39FE0D321B030B011B854FAC188868C80B040D321B03E2
+S1188E4E4EF6409E6F60FFFE6D756D740B876D7654706DF60DB1
+S1188E63766DF46DF56A0CA40E47045A008F0079059F586B027F
+S1188E78A4106DF20D527901009379009EC35E008CE66B80A429
+S1188E8D060B870D004C206B02A4100D5179009EC35E0097AEBF
+S1188EA26B02A4106B82A40679029EC268AC0D23400879039E7E
+S1188EB7C2FA0868BA6A0AA40A47047D3070206838F0006A0A0E
+S1188ECCA40F4602C80168B86B00A4060D020B026B82A4066A77
+S1188EE10BA4076A8B9EC00C2A10021E226A8A9EC10B800B00FE
+S1188EF66B80A406FA016A8AA40E6D756D746D7654706DF60D53
+S1188F0B766DF46DF55E008E606B02A4106B82A40C79059EC02E
+S1188F206B04A406471A6DF46DF51922790117767900343E5E70
+S1188F350098560B870B870C8846E66D756D746D7654706DF684
+S1188F4A0D766B02A4106B03A40C1D32430E79009F580D3109F5
+S1188F5F0119325E0097AE6B02A40C6B03A41019230D326B8263
+S1188F74A41018AA6A8AA40E6D7654706DF60D766DF46DF50D6B
+S1188F89246F6500046B03A41079029F5809320D2368B86EB98D
+S1188F9E00010C1918116EB900020D44470E0B830B030D520D94
+S1188FB3410D305E0097AE6B02A4100B820B0209526B82A410CD
+S1188FC818AA6A8AA40E6D756D746D7654706DF60D766DF46D0A
+S1188FDDF50D156B04A41079029F5809420D24FA0368CA6EC8EE
+S1188FF200010C0818006EC800020D505E009874790200401D62
+S1189007204F020D200B840B040D020D510D405E0097AE6B024A
+S118901CA4108A4392006B82A41018AA6A8AA40E6D756D746DEF
+S11890317654706DF60D766B00A41079029F5D09020D206D7655
+S118904654706DF60D766DF46DF56F6400046B03A41079059F8E
+S118905B5809350D5368B86EB900010C1918116EB900026EBA1F
+S118907000030C2A18226EBA00040D4447108B0593006F6200AC
+S1189085060D410D305E0097AE6B02A4108A0592006F60000687
+S118909A09026B82A41018AA6A8AA40E6D756D746D7654706DD2
+S11890AFF60D7669021D12470419004004790000016D765470CC
+S11890C46DF60D760D01790090AE5E00829E6D7654706DF60D53
+S11890D9767903000E19376DF46DF50D050D14790000021D049C
+S11890EE4E08790003935E0080B46C5A6EEAFFFD6E5B00010C82
+S1189103B318BB685AF20014AB14236FE3FFFA1B841B040B858A
+S11891186E6BFFFDF3000D33470A790200041D23470E40446DE0
+S118912DF319226F61FFFAF801402E790200021D244708790045
+S1189142039D5E0080B46E5800010C801888685AF20014A8146B
+S1189157205E0090C419226DF26F61FFFAF8055E008F800B87CE
+S118916C5A009496790200011D244E08790003A45E0080B46E33
+S11891815800010C801888685AF20014A814206FE0FFF81B84C7
+S11891960B855E00887E6FE0FFF46E6BFFFDF3008BFA93FF7932
+S11891AB0200161D2343045A00948E09336F3299DA592079024C
+S11891C000381D244708790003AA5E0080B46F63FFF447087989
+S11891D50199635A0094567901988E6F60FFF85E00889C6FE009
+S11891EAFFF4790200086DF2880590006DF06F62FFF86F61FF86
+S11891FFFAF81D5A0094840D444708790003B65E0080B46F62A1
+S1189214FFF446087901996E5A0094566F60FFF45E00890E6E16
+S11892296BFFFDAB1446087901997A5A00945619226DF26DF2EE
+S118923E6F62FFF86F61FFFAF8135A009484790200021D244704
+S118925308790003C45E0080B46E5C00010CC418CC685AF200F5
+S118926814AC14240D405E00887E6F62FFF446045A0092186EC4
+S118927D2A00044708790199875A0094560D0047045A0091D466
+S11892926F61FFF4890591000D405E00889C19226DF26DF26FAA
+S11892A762FFF86F61FFFAF8075A0094847902001C1D244708F4
+S11892BC790003D35E0080B40D516F60FFF45E0089940D0046CA
+S11892D108790199935A009456790200086DF26F63FFF48B055B
+S11892E693006DF36F62FFF86F61FFFAF8095A0094840D4447E0
+S11892FB08790003DA5E0080B47904A3580D416F60FFF45E0084
+S11893108AA60D004608790199A05A009456790200746DF26D07
+S1189325F46F62FFF86F61FFFAF8175A009484790200211D244C
+S118933A4708790003E25E0080B4790199AB5A0094567902005E
+S118934F011D244708790003E65E0080B468596F60FFF45E009F
+S11893648AEC0D004608790199B85A009456790200086DF26FBF
+S118937960FFF4880590006DF06F62FFF86F61FFFAF80B5A0020
+S118938E94847902000A1D244708790003ED5E0080B46E5A00D6
+S11893A3010CA218AA6859F1006E5B00090CB318BB6E5800085C
+S11893B8F000148B14036DF3149A14126F61FFFA6F60FFF45ED9
+S11893CD008B180B870D004D045A009496790199C35A00945656
+S11893E27902000A1D244E08790003F45E0080B46E5A00010C7F
+S11893F7A218AA6FE2FFF6685AF2006F60FFF614A814206FE0FC
+S118940CFFF66E5B00090CB318BB6E5A0008F20014AB14238DA9
+S11894210B95008CF594FF1D434710790003F96FE3FFF25E00B1
+S118943680B46F63FFF26DF50D326F61FFF66F60FFF45E008C14
+S118944B7A0B870D004C0E790199CE6F60FFFA5E008FD64036B3
+S11894606EE8FFFE0C0810001E006EE8FFFF790200026DF20D21
+S1189475621B826DF26F62FFF86F61FFFAF8115E0090480B871E
+S118948A0B874008790004045E0080B46D756D747903000E0986
+S118949F376D7654706DF60D766DF46DF50D04684BF3007902FB
+S11894B400451D23470C7902004D1D2347045A009548790200C2
+S11894C9051D214708790004125E0080B479039A28683DF500FF
+S11894DE6A0A9A290CA218AA14AD14250D5209326E4B00036E10
+S11894F3AB000118BB6A0AA40F4602FB016A8BA40F5E008F4899
+S1189508790200011D254F326A0A9A2AEA08471E79019A2B79C4
+S118951D049AC00D521B020D405E008DDC0D050D510D405E002C
+S118953290D6400C79009A2B0D511B015E0090D65E008F0840BD
+S1189547087900042C5E0080B46D756D746D7654706DF60D7678
+S118955C7903005219376DF45E00970E7900FFB0096079020068
+S11895714019115E0098087902A4007901FFB6096179003B9A73
+S11895865E0096AC790029645E0096D4790014985E0096D479F8
+S118959B0200016DF26DF27902FFB609627901FFB4096179004B
+S11895B030D05E0098560B870B87790230026DF2192279013041
+S11895C51F79001FF25E0096BC0B877901300779001B625E009D
+S11895DA96DE790027C85E0096D419446DF479029A2879011748
+S11895EF717900327C5E0096BC0B876A8CA40F6B84A4066B8458
+S1189604A4106A8CA40E405C19227901FFAF0961790034265E57
+S11896190096AC6E6AFFAFF2000CAA473E18AA6EEAFFAE790201
+S118962EFFAE09626DF2790200107901FFF00961790033B05E94
+S11896430096BC0B876E69FFAEF1006B029A200B026B829A20DA
+S11896581B017900FFF009605E0094A45E0085BC5E0080320DBA
+S114966D00469C19006D747903005209376D76547057
+S118967E6DF60D7679029A207903A4121D32470A188868A80B2B
+S1189693021D3246F85E009558FA016A8AFFCC6B0200005D2040
+S10796A86D76547013
+S11396AC6DF66DF20D165D000D600B876D765470C2
+S11896BC6DF66F7300046DF36DF20D165D000D600B870B876D0F
+S10696D176547058
+S10D96D46DF65D000D606D765470B4
+S10F96DE6DF60D165D000D606D76547085
+S11596EA6DF56DF60D060D155F520D606D766D755470C9
+S11596FC6DF56DF60D060D155F500D606D766D755470B9
+S118970E6DF60D767903A4127902EF00193269B26D7654706D46
+S1189723F60D766DF46DF50D040B04ECFE0B841D04455C79001D
+S1189738A4120D01404C69024D4209217902EEFF1D2142144068
+S118974D0E690209326982691209211D51420469134CEE6903E9
+S11897621D4345220D428A0692001D23450A0D02094219436908
+S1189777A369846902C28069820B804010E27F09210D107905B0
+S118978CEEFF1D5043AC19006D756D746D7654706DF60D766FA3
+S11097A102FFFEE27F6F82FFFE6D765470C2
+S11897AE6DF60D766DF40D140D010D0309231D31470A6C4A6833
+S11297C38A0B001D3046F60D106D746D765470D0
+S11897D26DF60D76401C680B681A1CAB430679000001401E1C43
+S11897E7AB44067900FFFF40140B000B01680A46E0681A19005F
+S10F97FC0CAA47047900FFFF6D7654703E
+S11898086DF60D760D0309231D3047066CB91D3046FA6D7654A2
+S104981D70D6
+S117981E6DF60D760D036C1A68BA0B030CAA46F66D765470ED
+S11598326DF56DF60D060D155F4C0D606D766D75547085
+S11598446DF56DF60D060D155F4E0D606D766D75547071
+S11898566DF66F7300066DF36F7300066DF36DF20D165D000D1A
+S10C986B608F0697006D765470BD
+S11798746DF60D76193340020B036C0A46FA0D306D765470C0
+S1189888726573657400000000800000000098DC000099120005
+S118989D00000098DA020000000000871298D803000000000032
+S11898B2871298D6040000000000871298D20500000000008703
+S11898C712000000000000000000003031320032003100300050
+S11898DC2E2E000098DC000099120000000098DA0700000085FA
+S11898F12A82E098D808000000852A82E098D609000000852A23
+S118990682E00000000000000000000098DC0000994800000091
+S118991B0099410100989600000000993A060098E000000000D9
+S11899300000000000000000000073656E736F72006D6F746FC5
+S1189945720000995C00009912000000000000000000000000F7
+S118995A00002F006C65676F0066696420696E20757365006E19
+S118996F6F2073756368206669640063616E27742072656D6FAA
+S118998476650063616E277420636C6F6E65006E6F20737563A9
+S118999968206E616D650063616E277420737461740063616EB1
+S11899AE2774206372656174650063616E2774206F70656E00D2
+S11899C363616E277420726561640063616E277420777269744F
+S11899D86500924C948E92B4948E934C948E9334948E93909408
+S11899ED8E93E2948E9206948E9206948E92F8948E948E948ED8
+S1099A02948E948E91BEC7
+S1189A080000FFFF9948991C98A098AA98B498BE992698EA98BC
+S1069A1DF498FEB8
+S90380007C
diff --git a/lib/lego/styx_abp.srec b/lib/lego/styx_abp.srec new file mode 100644 index 00000000..d7026013 --- /dev/null +++ b/lib/lego/styx_abp.srec @@ -0,0 +1,331 @@ +S0100000737479785F6162702E73726563AA
+S11880006DF06DF16DF26DF35E0096A66D736D726D716D705485
+S118801570446F20796F7520627974652C207768656E20492057
+S10B802A6B6E6F636B3F0000F5
+S11880326DF60D761B870D621B8279014000790029F25E00965F
+S1188047D46B039A326F62FFFE1D23470819226B829A30401271
+S118805C6B039A30790200091D234E060B036B839A306F61FF26
+S1188071FE6B819A326B039A30790200097900FFFF1D234F027C
+S11880860D100B876D7654706DF60D760D02790330026DF3790F
+S118809B01301F79001FF25E0096E40B87790027C85E0096FC30
+S11880B06D7654706DF60D766DF40D047901300679001B625EB4
+S11880C50097060D405E00808E5E0080320D0046F86D746D762D
+S11880DA54706DF60D766DF40D041900684B473C0D1147380B7A
+S11880EF040CBA8AD0AA09422E0CB8F00088D090FF1B01684BC7
+S118810447200D11471C0B040CBA8AD0AA0942120D0209220901
+S118811922092009000CBAF200092040D66D746D7654706DF617
+S118812E0D761B871B876DF46DF56FE0FFFE0D146FE0FFFC0DEA
+S1188143444C16FA2D688A6F62FFFE0D230B036FE3FFFC170CE8
+S118815817040B040D444610FA306F63FFFC68BA0B036FE3FFC5
+S118816DFC404C790527101D454F407901000A0D505E009712E3
+S11881820D051D454EF0402E0D510D405E0097120C8A8A306F53
+S118819763FFFC68BA0B036FE3FFFC0D510D405E0097240D041F
+S11881AC7901000A0D505E0097120D050D5546CE6F62FFFC6F0F
+S11881C163FFFE19326FE2FFFC6F60FFFC6D756D740B870B87FD
+S11881D66D7654706DF60D761B876DF46DF50D040D156FE2FF1B
+S11881EBFE7900000A5E00974A69846F8500026F62FFFE6F8219
+S118820000046F6200046F82000619226F8200086A0AA43A8A85
+S1188215016A8AA43A6D756D740B876D7654706DF60D765E003D
+S118822A97C46A0AA43A8AFF6A8AA43A6D7654706DF60D76693D
+S118823F00790198B05E008FD6790000016D7654706DF60D769A
+S11882541B871B876DF46DF50D056FE1FFFE6FE2FFFC40266990
+S1188269546F61FFFC0D406F62FFFE5D200D00470E6F4200082A
+S118827E69D20D405E0082244006790500080945695246D66DFD
+S1188293756D740B870B876D7654706DF60D761B871B876DF426
+S11882A86DF56FE0FFFE6FE1FFFC19557904A40C6F62FFFC6FEE
+S11882BD61FFFE0D405E0082508C0E94000B05790200021D25D0
+S11882D24FE46D756D740B870B876D7654706DF60D7679030070
+S11882E70C19376DF46DF56FE2FFFE6F6400040D1147045A0077
+S11882FC83FE6E080002F00088F990FF6FE0FFFC6F65FFFC094E
+S11883115509550955190509557902A40009520D256F62FFFE4C
+S118832646045A0083FE684BF300790200621D23470C79020088
+S118833B6C1D23470A5A0083FE79020060400219226FE2FFF8B1
+S11883500B046F63FFFE1B030D3346045A0083FE684AAA3E46D3
+S118836504FA014006AA3C460C18AA6EEAFFFB0B041B034006FB
+S118837AFA016EEAFFFB0D3346045A0083FE7901823A0D50881D
+S118838F0C900019226FE3FFF45E0082506F62FFFC8A00921091
+S11883A46FE2FFF66F61FFF6790019C45E009706FA0168DA6EB9
+S11883B96AFFF96EDA00016F63FFF40D310D405E0080DC6FD0B7
+S11883CE000A19226FD200026FD200046EDA0006FA016EDA0038
+S11883E3086E6AFFFB6EDA00096F61FFF6790019465E009706BE
+S11883F86F60FFFE40047900FFFF6D756D747903000C09376DED
+S118840D7654706DF60D767903000619376DF46DF56FE0FFFE55
+S11884226FE1FFFC0D256F6400085E0090340D031D45443219C6
+S1188437546F6000041D0443046F6400046F62000609526FE243
+S118844C00060D300B800B000D426F6100066FE3FFFA5E0097D9
+S1188461D66F63FFFA4002194468BC0D420C2A18226EBA0001B6
+S118847618AA6EBA00020B840B046DF419226DF26F62FFFC6F2D
+S118848B61FFFEF80F5E0090480B870B876D756D7479030006D4
+S11884A009376D7654706DF60D767903000C19376DF46DF56FEC
+S11884B5E0FFF66FE1FFF40D257904FFF809646F6100060D4060
+S11884CA5E00812C6DF06DF46F6200046DF20D526F61FFF46F0B
+S11884DF60FFF65E0084108F0697006D756D747903000C093786
+S11884F46D7654706DF60D766E0A0009471019116F0300046FFB
+S118850902000A1D234514400E19116F0300046F02000A1D230B
+S118851E4404790100010D106D7654706DF60D761B876DF46D67
+S1188533F56FE1FFFE0D256E0A0002F2008AF992FF0D240944BD
+S118854809440944192409447902A40009420D246E4A00084655
+S118855D067900FFFF404E0D405E0084F80D0047206F420004AA
+S11885726DF26F6200066DF26F6200040D516F60FFFE5E00847A
+S1188587A60B870B8740226F6200066DF26F6200040D516F6077
+S118859CFFFE5E0081DA6F42000C6F8200086FC0000C0B871974
+S11885B1006D756D740B876D7654706DF60D761B876DF46DF56A
+S11885C67903A430683A4D045A008686EA7F68BA19440D4509B0
+S11885DB5509550955194509557902A40009520D256E5A00083E
+S11885F00D430B036FE3FFFE0CAA46045A0086768C0094100D32
+S1188605520D41790014C05E0096D40D520D41790014C05E004F
+S118861A96D40D520D41790014C05E0096D40D520D41790014E1
+S118862FC05E0096D40D505E0084F80D00473840306F54000CA8
+S11886446F4200086FD2000C6F41000269406F5200046DF26F29
+S11886594200066DF26F4200045E0084A60D405E0082240B8741
+S118866E0B876F52000C46CA6F64FFFE790200021D244E045A4A
+S11886830085D86D756D740B876D7654706DF60D766DF46DF5DC
+S11886980D050D246F600004680BF300790200661D2347244E73
+S11886AD127902002D1D234750790200461D23472440327902CA
+S11886C200721D23470E0B021D23470E4022790200014010794F
+S11886D7020002400A7902000340047902000469926E0A000187
+S11886EC8AD0AA074304190040146E0A0001F2008AD092FF69F7
+S1188701C2FA0168DA790000016D756D746D7654706DF60D7696
+S11887167903001A19376DF46DF56FE2FFEE0D1147045A008818
+S118872B1A6EE9FFF26EE9FFF16EE9FFF06E0A0002AA054704D2
+S11887405A0087CC790200066F60FFEE1D2047045A00881A7939
+S118875504FFF409647905FFFA09657902FFF009626FE2FFECB1
+S118876A6F6300046DF30D420D516F60FFEC5E0086900B870D46
+S118877F0046045A00881A0D611B811B817900FFF109606F6252
+S118879400040B826DF21B826FE200047902FFF609625E00862B
+S11887A9900B870D00476A0D611B817900FFF209606F63000424
+S11887BE0B830B836DF37902FFF809624044790200026F63FF77
+S11887D3EE1D2346426E0B0002F3001B837900FFF409606FE0A7
+S11887E8FFEA0D3209227905FFFA09650D5109217904FFF00943
+S11887FD640D4009306F6300046DF36F63FFEA09230D325E00BF
+S118881286900B870D0046067900FFFF405019337904FFF40980
+S1188827647900FFF009606FE0FFE86F60FFE86C0A6FE0FFE86B
+S118883C0CAA471E0D318900912069426DF2695279001A4E6F7B
+S1188851E3FFE65E0096E40B876F63FFE60B840B850B0379027D
+S118886600021D234FC66F60FFEE6D756D747903001A09376DE0
+S118887B7654706DF60D760D036B00A438400269000D00470866
+S11888906F0200021D3246F26D7654706DF60D761B876DF46DD8
+S11888A5F50D056FE1FFFE7900000E5E00974A0D0446087900C8
+S11888BA02135E0080B418AA6ECA00046FC500026B02A4386918
+S11888CFC20D4088059000790200086F61FFFE5E0097D66B845A
+S11888E4A4380D406D756D740B876D7654706DF60D766F0300FE
+S11888F9026F1200021D23470419004004790000016D765470D8
+S118890E6DF60D766DF40D04790088F20D415E00829E7903A419
+S118892338401269301D40460A690269B25E0097C4400E0D03CE
+S1188938693246EA790002325E0080B46D746D7654706DF60D24
+S118894D766DF46DF50D040D156F4200044608790002395E0090
+S118896280B46F440004401C6940790199045E0097FA0D0047B2
+S11889770A0D5546040D40400C1B058C0A9400694246E0190064
+S118898C6D756D746D7654706DF60D761B876DF46DF50D056F9C
+S11889A1E1FFFE6E5A000446226E5A0005AA0943087900024B1A
+S11889B65E0080B46E5A0005F20009226F229A346F22000446F2
+S11889CB067900FFFF403E0D20690247360D0469406F61FFFEFC
+S11889E05E0097FA0D00461E6E4A00026EDA00056F420004184A
+S11889F5BB0D224702FB806EDB000879000001400A8C0A94007C
+S1188A0A694246CC19006D756D740B876D7654706DF60D761B80
+S1188A1F876DF46DF56FE0FFFE0D157902007419110D505E00B2
+S1188A3498306F62FFFE69210D505E0098460D50881C90007966
+S1188A490400050D42790199865E0097D60D50883890000D425C
+S1188A5E790199865E0097D66F63FFFE6E3A00026EDA00546F17
+S1188A73320004FBB60D224702FB6D6EDB005CFA016EDA005DDE
+S1188A886F63FFFE6F32000418BB0D224702FB806EDB005F6D86
+S1188A9D756D740B876D7654706DF60D766DF46DF50D040D1555
+S1188AB26E4A000447067900FFFF40266E4A0005AA0943087991
+S1188AC700026B5E0080B46E4A0005F20009226F209A340D5102
+S1188ADC5E008A1A790000016D756D746D7654706DF60D766E47
+S1188AF10A000446107369460C6E0A0008470A89FFA901420491
+S1188B061900400AFA016E8A0004790000016D7654706DF60D6B
+S1188B1B767903000A19376DF46DF56FE0FFFE6FE1FFFC6FE24A
+S1188B30FFFA6E0A0005AA094308790002875E0080B46F60FF56
+S1188B45FE6E0A0005F20009226F229A346FE2FFF86E0A000858
+S1188B5AEA8046045A008C3A6E0A00044720790100746F60008E
+S1188B6F045E00985A0D004610790100746F60FFFA5E00985A30
+S1188B840D0047087900FFFF5A008C6C790100746F6000045E94
+S1188B9900986C6FE00004790100746F60FFFA5E00986C6FE005
+S1188BAEFFFA5E0090346FE0FFF66F64FFF60B840B041955403B
+S1188BC30C0D415E008A1A8C7494000B056F6200041D2544122C
+S1188BD86F61FFFA09516F60FFF85E00894A0D0046DA0D5209D5
+S1188BED22092209221952092209220925095509556F63FFF685
+S1188C0268BD0D520C2A10021E226EBA000118AA6EBA00020B2D
+S1188C17850B056DF519226DF26F63FFFE6F3200026F61FFFC76
+S1188C2CF80F5E00904819000B870B8740326F60FFF86F03000B
+S1188C410647246F6200046DF26F60FFFA6DF06F60FFFE6F0213
+S1188C5600026F61FFFC6F60FFF85D300B870B8740047900FF05
+S1188C6BFF6D756D747903000A09376D7654706DF60D761B8739
+S1188C806DF46DF50D046FE1FFFE0D256E4A0008EA8046066EA4
+S1188C954A000446067900FFFF403C6E4A0005AA094308790005
+S1188CAA02B35E0080B46E4A0005F20009226F209A346F0200C2
+S1188CBF0847166F6200046DF26F0300080D526F61FFFE5D30D0
+S1188CD40B8740047900FFFF6D756D740B876D7654706DF60DCE
+S1188CE9761B876DF46DF56F63000446087900FFFF5A008DD243
+S1188CFE0D25194419116F6300040D5209326FE2FFFE40386806
+S1188D135BAB8846186F6200041B821D214CD4688B0B0018AACB
+S1188D28688A0B000B8140180CBB46040B0440106F6200041BF1
+S1188D3D021D214CB4688B0B000B010B0519336F62FFFE1D2567
+S1188D52450479030001685A46040D3347B2790200011D2447F9
+S1188D67124E060D4447584038790200021D24471A402E6F62C7
+S1188D7C00041B021D214D045A008CF618AA688A0B000B014047
+S1188D91346F6200041B821D214D045A008CF618AA688A0B00F9
+S1188DA640186F6200041B821D214D045A008CF6FA88688A0B00
+S1188DBB000CCA8AFE688A0B000B8119440D3346045A008D12D8
+S1188DD00D106D756D740B876D7654706DF60D761B876DF46D1B
+S1188DE5F50D040D2519226FE2FFFE0D55475E681AAA8847149E
+S1188DFA68CA0B010B046F62FFFE0B026FE2FFFE1B0540E20B9D
+S1188E0F016818F0000D00461468CA0B046F62FFFE0B026FE205
+S1188E24FFFE0B011B8540C40D030B836F62FFFE09326FE2FF91
+S1188E39FE0D321B030B011B854FAC188868C80B040D321B03E2
+S1188E4E4EF6409E6F60FFFE6D756D740B876D7654706DF60DB1
+S1188E63766DF46DF56A0CA43E47045A008F0079059F886B021F
+S1188E78A4406DF20D527901009379009EF35E008CE66B80A4C9
+S1188E8D360B870D004C206B02A4400D5179009EF35E0097D607
+S1188EA26B02A4406B82A43679029EF268AC0D23400879039EEE
+S1188EB7F2FA0868BA6A0AA43A47047D3070206838F0006A0AAE
+S1188ECCA43F4602C80168B86B00A4360D020B026B82A4366AE7
+S1188EE10BA4376A8B9EF00C2A10021E226A8A9EF10B800B006E
+S1188EF66B80A436FA016A8AA43E6D756D746D7654706DF60DF3
+S1188F0B766DF46DF55E008E606B02A4406B82A43C79059EF09E
+S1188F206B04A436471A6DF46DF51922790117767900343E5E40
+S1188F3500987E0B870B870C8846E66D756D746D7654706DF65C
+S1188F4A0D766B02A4406B03A43C1D32430E79009F880D310965
+S1188F5F0119325E0097D66B02A43C6B03A44019230D326B82DB
+S1188F74A44018AA6A8AA43E6D7654706DF60D766DF46DF50D0B
+S1188F89246F6500046B03A44079029F8809320D2368B86EB92D
+S1188F9E00010C1918116EB900020D44470E0B830B030D520D94
+S1188FB3410D305E0097D66B02A4400B820B0209526B82A44045
+S1188FC818AA6A8AA43E6D756D746D7654706DF60D766DF46DDA
+S1188FDDF50D156B04A44079029F8809420D24FA0368CA6EC88E
+S1188FF200010C0818006EC800020D505E00989C790200401D3A
+S1189007204F020D200B840B040D020D510D405E0097D66B0222
+S118901CA4408A4392006B82A44018AA6A8AA43E6D756D746D5F
+S11890317654706DF60D766B00A44079029F8D09020D206D76F5
+S118904654706DF60D766DF46DF56F6400046B03A44079059F5E
+S118905B8809350D5368B86EB900010C1918116EB900026EBAEF
+S118907000030C2A18226EBA00040D4447108B0593006F6200AC
+S1189085060D410D305E0097D66B02A4408A0592006F6000062F
+S118909A09026B82A44018AA6A8AA43E6D756D746D7654706D72
+S11890AFF60D7669021D12470419004004790000016D765470CC
+S11890C46DF60D760D01790090AE5E00829E6D7654706DF60D53
+S11890D9767903000E19376DF46DF50D050D14790000021D049C
+S11890EE4E08790003935E0080B46C5A6EEAFFFD6E5B00010C82
+S1189103B318BB685AF20014AB14236FE3FFFA1B841B040B858A
+S11891186E6BFFFDF3000D33470A790200041D23470E40446DE0
+S118912DF319226F61FFFAF801402E790200021D244708790045
+S1189142039D5E0080B46E5800010C801888685AF20014A8146B
+S1189157205E0090C419226DF26F61FFFAF8055E008F800B87CE
+S118916C5A009496790200011D244E08790003A45E0080B46E33
+S11891815800010C801888685AF20014A814206FE0FFF81B84C7
+S11891960B855E00887E6FE0FFF46E6BFFFDF3008BFA93FF7932
+S11891AB0200161D2343045A00948E09336F329A025920790223
+S11891C000381D244708790003AA5E0080B46F63FFF447087989
+S11891D501998B5A009456790198B66F60FFF85E00889C6FE0B9
+S11891EAFFF4790200086DF2880590006DF06F62FFF86F61FF86
+S11891FFFAF81D5A0094840D444708790003B65E0080B46F62A1
+S1189214FFF44608790199965A0094566F60FFF45E00890E6EEE
+S11892296BFFFDAB144608790199A25A00945619226DF26DF2C6
+S118923E6F62FFF86F61FFFAF8135A009484790200021D244704
+S118925308790003C45E0080B46E5C00010CC418CC685AF200F5
+S118926814AC14240D405E00887E6F62FFF446045A0092186EC4
+S118927D2A00044708790199AF5A0094560D0047045A0091D43E
+S11892926F61FFF4890591000D405E00889C19226DF26DF26FAA
+S11892A762FFF86F61FFFAF8075A0094847902001C1D244708F4
+S11892BC790003D35E0080B40D516F60FFF45E0089940D0046CA
+S11892D108790199BB5A009456790200086DF26F63FFF48B0533
+S11892E693006DF36F62FFF86F61FFFAF8095A0094840D4447E0
+S11892FB08790003DA5E0080B47904A3880D416F60FFF45E0054
+S11893108AA60D004608790199C85A009456790200746DF26DDF
+S1189325F46F62FFF86F61FFFAF8175A009484790200211D244C
+S118933A4708790003E25E0080B4790199D35A00945679020036
+S118934F011D244708790003E65E0080B468596F60FFF45E009F
+S11893648AEC0D004608790199E05A009456790200086DF26F97
+S118937960FFF4880590006DF06F62FFF86F61FFFAF80B5A0020
+S118938E94847902000A1D244708790003ED5E0080B46E5A00D6
+S11893A3010CA218AA6859F1006E5B00090CB318BB6E5800085C
+S11893B8F000148B14036DF3149A14126F61FFFA6F60FFF45ED9
+S11893CD008B180B870D004D045A009496790199EB5A0094562E
+S11893E27902000A1D244E08790003F45E0080B46E5A00010C7F
+S11893F7A218AA6FE2FFF6685AF2006F60FFF614A814206FE0FC
+S118940CFFF66E5B00090CB318BB6E5A0008F20014AB14238DA9
+S11894210B95008CF594FF1D434710790003F96FE3FFF25E00B1
+S118943680B46F63FFF26DF50D326F61FFF66F60FFF45E008C14
+S118944B7A0B870D004C0E790199F66F60FFFA5E008FD640368B
+S11894606EE8FFFE0C0810001E006EE8FFFF790200026DF20D21
+S1189475621B826DF26F62FFF86F61FFFAF8115E0090480B871E
+S118948A0B874008790004045E0080B46D756D747903000E0986
+S118949F376D7654706DF60D766DF46DF50D04684BF3007902FB
+S11894B400451D23470C7902004D1D2347045A0095707902009A
+S11894C9051D214708790004125E0080B479039A58683DF500CF
+S11894DE6A0A9A590CA218AA14AD14250D5209326E4B00036EE0
+S11894F3AB00016A089A5AE8016A0AA43F1CA84666684A1102D9
+S1189508130A1102130A1102130AEA01E2006A0BA43FF3001D98
+S118951D32464A18AA0C884602FA016A8AA43F5E008F48790253
+S118953200011D254F326A0A9A5A733A471E79019A5B79049A5C
+S1189547F00D521B020D405E008DDC0D050D510D405E0090D60A
+S118955C400C79009A5B0D511B015E0090D65E008F0840087948
+S118957100042C5E0080B46D756D746D7654706DF60D76790353
+S1189586005219376DF45E0097367900FFB00960790200401939
+S118959B115E0098307902A4307901FFB6096179003B9A5E00EC
+S11895B096D4790029645E0096FC790014985E0096FC790200B2
+S11895C5016DF26DF27902FFB609627901FFB40961790030D023
+S11895DA5E00987E0B870B87790230026DF219227901301F7957
+S11895EF001FF25E0096E40B877901300779001B625E00970646
+S1189604790027C85E0096FC19446DF479029A5879011771794F
+S118961900327C5E0096E40B876A8CA43F6B84A4366B84A440AB
+S118962E6A8CA43E405C19227901FFAF0961790034265E00961B
+S1189643D46E6AFFAFF2000CAA473E18AA6EEAFFAE7902FFAE98
+S118965809626DF2790200107901FFF00961790033B05E009681
+S118966DE40B876E69FFAEF1006B029A500B026B829A501B01A2
+S11896827900FFF009605E0094A45E0085BC5E0080320D004666
+S11296979C19006D747903005209376D76547075
+S11896A66DF60D7679029A507903A4421D32470A188868A80BA3
+S11896BB021D3246F85E009580FA016A8AFFCC6B0200005D20F0
+S10796D06D765470EB
+S11396D46DF66DF20D165D000D600B876D7654709A
+S11896E46DF66F7300046DF36DF20D165D000D600B870B876DE7
+S10696F976547030
+S10D96FC6DF65D000D606D7654708C
+S10F97066DF60D165D000D606D7654705C
+S11597126DF56DF60D060D155F520D606D766D755470A0
+S11597246DF56DF60D060D155F500D606D766D75547090
+S11897366DF60D767903A4427902EF00193269B26D7654706DEE
+S118974BF60D766DF46DF50D040B04ECFE0B841D04455C7900F5
+S1189760A4420D01404C69024D4209217902EEFF1D2142144010
+S11897750E690209326982691209211D51420469134CEE6903C1
+S118978A1D4345220D428A0692001D23450A0D020942194369E0
+S118979FA369846902C28069820B804010E27F09210D10790588
+S11897B4EEFF1D5043AC19006D756D746D7654706DF60D766F7B
+S11097C902FFFEE27F6F82FFFE6D7654709A
+S11897D66DF60D766DF40D140D010D0309231D31470A6C4A680B
+S11297EB8A0B001D3046F60D106D746D765470A8
+S11897FA6DF60D76401C680B681A1CAB430679000001401E1C1B
+S118980FAB44067900FFFF40140B000B01680A46E0681A190036
+S10F98240CAA47047900FFFF6D76547015
+S11898306DF60D760D0309231D3047066CB91D3046FA6D76547A
+S104984570AE
+S11798466DF60D760D036C1A68BA0B030CAA46F66D765470C5
+S115985A6DF56DF60D060D155F4C0D606D766D7554705D
+S115986C6DF56DF60D060D155F4E0D606D766D75547049
+S118987E6DF66F7300066DF36F7300066DF36DF20D165D000DF2
+S10C9893608F0697006D76547095
+S117989C6DF60D76193340020B036C0A46FA0D306D76547098
+S11898B0726573657400000000800000000099040000993A008C
+S11898C5000000990202000000000087129900030000000000B8
+S11898DA871298FE040000000000871298FA050000000000878B
+S11898EF12000000000000000000003031320032003100300028
+S11899042E2E000099040000993A000000009902070000008557
+S11899192A82E0990008000000852A82E098FE09000000852AA9
+S118992E82E00000000000000000000099040000997000000018
+S1189943009969010098BE000000009962060099080000000010
+S11899580000000000000000000073656E736F72006D6F746F9D
+S118996D72000099840000993A0000000000000000000000007F
+S118998200002F006C65676F0066696420696E20757365006EF1
+S11899976F2073756368206669640063616E27742072656D6F82
+S11899AC76650063616E277420636C6F6E65006E6F2073756381
+S11899C168206E616D650063616E277420737461740063616E89
+S11899D62774206372656174650063616E2774206F70656E00AA
+S11899EB63616E277420726561640063616E2774207772697427
+S1189A006500924C948E92B4948E934C948E9334948E939094DF
+S1189A158E93E2948E9206948E9206948E92F8948E948E948EAF
+S1099A2A948E948E91BE9F
+S1189A300000FFFF9970994498C898D298DC98E6994E99129952
+S1069A451C99263F
+S90380007C
|
