diff --git a/oscar/SleepLib/loader_plugins/prs1_loader.cpp b/oscar/SleepLib/loader_plugins/prs1_loader.cpp
index e4dd1275..cf830225 100644
--- a/oscar/SleepLib/loader_plugins/prs1_loader.cpp
+++ b/oscar/SleepLib/loader_plugins/prs1_loader.cpp
@@ -1615,6 +1615,24 @@ QMap<QString,QString> _PRS1ParsedEventContents(PRS1ParsedEvent* e)
 //********************************************************************************************
 
 
+static QString DumpEvent(int t, int code, const unsigned char* data, int size)
+{
+    int s = t;
+    int h = s / 3600; s -= h * 3600;
+    int m = s / 60; s -= m * 60;
+    QString dump = QString("%1:%2:%3")
+        .arg(h, 2, 10, QChar('0'))
+        .arg(m, 2, 10, QChar('0'))
+        .arg(s, 2, 10, QChar('0'));
+    dump = dump + " " + hex(code) + ":";
+    for (int i = 0; i < size; i++) {
+        dump = dump + QString(" %1").arg(data[i]);
+    }
+    return dump;
+}
+#define DUMP_EVENT() qWarning() << this->sessionid << DumpEvent(t, code, data + pos, size - (pos - startpos)) << "@" << pos
+
+
 void PRS1DataChunk::AddEvent(PRS1ParsedEvent* const event)
 {
     m_parsedData.push_back(event);
@@ -2104,67 +2122,62 @@ bool PRS1Import::ParseF5Events()
 // 950P is F5V0, 960P and 961P are F5V1, 960T is F5V2
 bool PRS1DataChunk::ParseEventsF5V012(void)
 {
-    EventDataType data0, data1, data4, data5;
+    if (this->family != 5 || this->familyVersion > 2) {
+        qWarning() << "ParseEventsF5V012 called with family" << this->family << "familyVersion" << this->familyVersion;
+        return false;
+    }
+    const unsigned char * data = (unsigned char *)this->m_data.constData();
+    int chunk_size = this->m_data.size();
+    QMap<int,int> event_sizes;
+    // TODO: This probably needs to be split into 3 functions.
+    switch (this->familyVersion) {
+        case 0: event_sizes = { {0,3}, {1,2}, {3,4},        {9,3}, {0xa,2}, {0xb,5}, {0xc,5},          {0xd,0xc}, {0xf,5}, {0x10,5}, {0x11,2}, {0x12,6} }; break;
+        case 1: event_sizes = { {0,4}, {1,2}, {3,4}, {8,4}, {9,3}, {0xa,2}, {0xb,5}, {0xc,5},          {0xd,0xd}, {0xf,5}, {0x10,5}, {0x11,2}, {0x12,6} }; break;
+        case 2: event_sizes = { {0,4}, {1,2}, {3,4},        {9,4}, {0xa,2}, {0xb,5}, {0xc,5}, {0xd,5}, {0xe,0xd}, {0xf,5}, {0x10,5}, {0x11,2}, {0x12,6} }; break;
+    }
 
+    if (chunk_size < 1) {
+        // This does occasionally happen in F0V6.
+        qDebug() << this->sessionid << "Empty event data";
+        return false;
+    }
+
+    bool ok = true;
+    int pos = 0, startpos;
+    int code, size;
     int t = 0;
-    int pos = 0;
-    int cnt = 0;
-    short delta;//,duration;
-    bool badcode = false;
-    unsigned char lastcode3 = 0, lastcode2 = 0, lastcode = 0, code = 0;
-    int lastpos = 0, startpos = 0, lastpos2 = 0, lastpos3 = 0;
+    EventDataType data0, data1, data4, data5;
+    //int elapsed, duration, value;
+    do {
+        code = data[pos++];
 
-    int size = this->m_data.size();
-    unsigned char * buffer = (unsigned char *)this->m_data.data();
-
-    while (pos < size) {
-        lastcode3 = lastcode2;
-        lastcode2 = lastcode;
-        lastcode = code;
-        lastpos3 = lastpos2;
-        lastpos2 = lastpos;
-        lastpos = startpos;
+        size = 3;  // default size = 2 bytes time delta + 1 byte data
+        if (event_sizes.contains(code)) {
+            size = event_sizes[code];
+        }
+        if (pos + size > chunk_size) {
+            qWarning() << this->sessionid << "event" << code << "@" << pos << "longer than remaining chunk";
+            ok = false;
+            break;
+        }
         startpos = pos;
-        code = buffer[pos++];
-
-        if (code >= 0x13) {
-            qDebug() << "Illegal PRS1 code " << hex << int(code) << " appeared at " << hex << startpos << "in" << this->sessionid;;
-            qDebug() << "1: (" << int(lastcode) << hex << lastpos << ")";
-            qDebug() << "2: (" << int(lastcode2) << hex << lastpos2 << ")";
-            qDebug() << "3: (" << int(lastcode3) << hex << lastpos3 << ")";
-            this->AddEvent(new PRS1UnknownDataEvent(m_data, startpos));
-            return false;
-        }
-
-        if (code == 0) {
-            // No delta
-        } else if (code != 0x12) {
-            delta = buffer[pos];
-            //duration=buffer[pos+1];
-            //delta=buffer[pos+1] << 8 | buffer[pos];
+        if (code != 0 && code != 0x12) {  // These two codes have no timestamp  TODO: verify this applies to F5V012
+            t += data[pos] /*| (data[pos+1] << 8)*/;  // TODO: Is this really only 1 byte?
             pos += 2;
-            t += delta;
         }
 
-        //EventDataType PS;
-        cnt++;
-        int fc = 0;
-
         switch (code) {
         case 0x00: // Unknown (ASV Pressure value)
             // offset?
-            data0 = buffer[pos++];
-            fc++;
+            data0 = data[pos++];
 
-            if (!buffer[pos - 1]) { // WTH???
-                data1 = buffer[pos++];
-                fc++;
+            if (!data[pos - 1]) { // WTH???
+                data1 = data[pos++];
             }
 
-            if (!buffer[pos - 1]) {
-                //data2 = buffer[pos++];
+            if (!data[pos - 1]) {
+                //data2 = data[pos++];
                 pos++;
-                fc++;
             }
 
             break;
@@ -2174,7 +2187,7 @@ bool PRS1DataChunk::ParseEventsF5V012(void)
             break;
 
         case 0x02: // Pressure ???
-            data0 = buffer[pos++];
+            data0 = data[pos++];
             //            if (!Code[2]) {
             //                if (!(Code[2]=session->AddEventList(cpapcode,EVL_Event,0.1))) return false;
             //            }
@@ -2183,8 +2196,8 @@ bool PRS1DataChunk::ParseEventsF5V012(void)
         case 0x03: // BIPAP Pressure
             qDebug() << "0x03 Observed in ASV data!!????";
 
-            data0 = buffer[pos++];
-            data1 = buffer[pos++];
+            data0 = data[pos++];
+            data1 = data[pos++];
             //            data0/=10.0;
             //            data1/=10.0;
             //            session->AddEvent(new Event(t,CPAP_EAP, 0, data, 1));
@@ -2192,31 +2205,33 @@ bool PRS1DataChunk::ParseEventsF5V012(void)
             break;
 
         case 0x04: // Timed Breath
-            data0 = buffer[pos++];
+            data0 = data[pos++];
 
             this->AddEvent(new PRS1TimedBreathEvent(t, data0));
             break;
 
         case 0x05:
             //code=CPAP_Obstructive;
-            data0 = buffer[pos++];
+            data0 = data[pos++];
             this->AddEvent(new PRS1ObstructiveApneaEvent(t - data0, data0));
             break;
 
         case 0x06:
             //code=CPAP_ClearAirway;
-            data0 = buffer[pos++];
+            data0 = data[pos++];
             this->AddEvent(new PRS1ClearAirwayEvent(t - data0, data0));
             break;
 
         case 0x07:
             //code=CPAP_Hypopnea;
-            data0 = buffer[pos++];
+            data0 = data[pos++];
             this->AddEvent(new PRS1HypopneaEvent(t - data0, data0));
             break;
 
         case 0x08: // ???
-            data0 = buffer[pos++];
+            // This was breaking parsing for F5V1 prior to using fixed lengths.
+            // That means it's probably very wrong.
+            data0 = data[pos++];
             //qDebug() << "Code 8 found at " << hex << pos - 1 << " " << tt;
 
             if (this->familyVersion>=2) {
@@ -2224,7 +2239,7 @@ bool PRS1DataChunk::ParseEventsF5V012(void)
             } else {
                 this->AddEvent(new PRS1UnknownValueEvent(code, t - data0, data0));
                 //????
-                //data1=buffer[pos++]; // ???
+                //data1=data[pos++]; // ???
                 //pos++;
             }
             break;
@@ -2232,18 +2247,18 @@ bool PRS1DataChunk::ParseEventsF5V012(void)
         case 0x09: // ASV Codes
             if (this->familyVersion<2) {
                 //code=CPAP_FlowLimit;
-                data0 = buffer[pos++];
+                data0 = data[pos++];
 
                 this->AddEvent(new PRS1FlowLimitationEvent(t - data0, data0));
             } else {
-                data0 = buffer[pos++];
-                data1 = buffer[pos++];
+                data0 = data[pos++];
+                data1 = data[pos++];
             }
 
             break;
 
         case 0x0a:
-            data0 = buffer[pos++];
+            data0 = data[pos++];
             if (this->familyVersion>=2) {
                 this->AddEvent(new PRS1FlowLimitationEvent(t - data0, data0));
             } else {
@@ -2253,10 +2268,10 @@ bool PRS1DataChunk::ParseEventsF5V012(void)
 
 
         case 0x0b: // Cheyne Stokes
-            data0 = ((unsigned char *)buffer)[pos + 1] << 8 | ((unsigned char *)buffer)[pos];
+            data0 = ((unsigned char *)data)[pos + 1] << 8 | ((unsigned char *)data)[pos];
             //data0*=2;
             pos += 2;
-            data1 = ((unsigned char *)buffer)[pos]; //|buffer[pos+1] << 8
+            data1 = ((unsigned char *)data)[pos]; //|data[pos+1] << 8
             pos += 1;
             //tt-=delta;
             this->AddEvent(new PRS1PeriodicBreathingEvent(t - data1, data0));
@@ -2265,14 +2280,14 @@ bool PRS1DataChunk::ParseEventsF5V012(void)
         case 0x0c:
 
             if (this->familyVersion>=2) {
-                data0 = (buffer[pos + 1] << 8 | buffer[pos]);
+                data0 = (data[pos + 1] << 8 | data[pos]);
                 data0 *= 2;
                 pos += 2;
-                data1 = buffer[pos++];
+                data1 = data[pos++];
                 this->AddEvent(new PRS1PeriodicBreathingEvent(t - data1, data0));
 
             } else {
-                data0 = buffer[pos++];
+                data0 = data[pos++];
                 qDebug() << "Code 12 found at " << hex << pos - 1 << " " << t - data0;
 
                 this->AddEvent(new PRS1UnknownValueEvent(code, t - data0, data0));
@@ -2283,29 +2298,29 @@ bool PRS1DataChunk::ParseEventsF5V012(void)
         case 0x0d: // All the other ASV graph stuff.
 
             if (this->familyVersion>=2) {
-                data0 = (buffer[pos + 1] << 8 | buffer[pos]);
+                data0 = (data[pos + 1] << 8 | data[pos]);
                 data0 *= 2;
                 pos += 2;
-                data1 = buffer[pos++];
+                data1 = data[pos++];
                 //tt = t - qint64(data1) * 1000L;
             } else {
-                this->AddEvent(new PRS1IPAPAverageEvent(t, buffer[pos++])); // 00=IAP
-                data4 = buffer[pos++];
+                this->AddEvent(new PRS1IPAPAverageEvent(t, data[pos++])); // 00=IAP
+                data4 = data[pos++];
                 this->AddEvent(new PRS1IPAPLowEvent(t, data4));               // 01=IAP Low
-                data5 = buffer[pos++];
+                data5 = data[pos++];
                 this->AddEvent(new PRS1IPAPHighEvent(t, data5));               // 02=IAP High
 
-                this->AddEvent(new PRS1TotalLeakEvent(t, buffer[pos++]));           // 03=LEAK
+                this->AddEvent(new PRS1TotalLeakEvent(t, data[pos++]));           // 03=LEAK
 
-                this->AddEvent(new PRS1RespiratoryRateEvent(t, buffer[pos++]));             // 04=Breaths Per Minute
-                this->AddEvent(new PRS1PatientTriggeredBreathsEvent(t, buffer[pos++]));            // 05=Patient Triggered Breaths
-                this->AddEvent(new PRS1MinuteVentilationEvent(t, buffer[pos++]));             // 06=Minute Ventilation
-                //tmp=buffer[pos++] * 10.0;
-                this->AddEvent(new PRS1TidalVolumeEvent(t, buffer[pos++]));             // 07=Tidal Volume
-                this->AddEvent(new PRS1SnoreEvent(t, buffer[pos++])); // 08=Snore
-                this->AddEvent(new PRS1EPAPAverageEvent(t, data1 = buffer[pos++])); // 09=EPAP
+                this->AddEvent(new PRS1RespiratoryRateEvent(t, data[pos++]));             // 04=Breaths Per Minute
+                this->AddEvent(new PRS1PatientTriggeredBreathsEvent(t, data[pos++]));            // 05=Patient Triggered Breaths
+                this->AddEvent(new PRS1MinuteVentilationEvent(t, data[pos++]));             // 06=Minute Ventilation
+                //tmp=data[pos++] * 10.0;
+                this->AddEvent(new PRS1TidalVolumeEvent(t, data[pos++]));             // 07=Tidal Volume
+                this->AddEvent(new PRS1SnoreEvent(t, data[pos++])); // 08=Snore
+                this->AddEvent(new PRS1EPAPAverageEvent(t, data1 = data[pos++])); // 09=EPAP
                 if (this->familyVersion >= 1) {
-                    data0 = buffer[pos++];
+                    data0 = data[pos++];
                 }
             }
             break;
@@ -2313,20 +2328,20 @@ bool PRS1DataChunk::ParseEventsF5V012(void)
         case 0x0e: // Unknown
             // Family 5.2 has this code
             if (this->familyVersion>=2) {
-                this->AddEvent(new PRS1IPAPAverageEvent(t, data1=buffer[pos+0])); // 0
-                this->AddEvent(new PRS1IPAPLowEvent(t, buffer[pos+1])); // 1
-                this->AddEvent(new PRS1IPAPHighEvent(t, buffer[pos+2])); // 2
-                this->AddEvent(new PRS1LeakEvent(t, buffer[pos+3])); // 3  // F5V2, is this really unintentional leak rather than total leak?
-                this->AddEvent(new PRS1TidalVolumeEvent(t, buffer[pos+7])); // 7
-                this->AddEvent(new PRS1RespiratoryRateEvent(t, buffer[pos+4])); // 4
-                this->AddEvent(new PRS1PatientTriggeredBreathsEvent(t, buffer[pos+5]));  // 5
-                this->AddEvent(new PRS1MinuteVentilationEvent(t,  buffer[pos+6])); //6
-                this->AddEvent(new PRS1SnoreEvent(t, buffer[pos+8])); //??
-                this->AddEvent(new PRS1EPAPAverageEvent(t, buffer[pos+9])); // 9
+                this->AddEvent(new PRS1IPAPAverageEvent(t, data1=data[pos+0])); // 0
+                this->AddEvent(new PRS1IPAPLowEvent(t, data[pos+1])); // 1
+                this->AddEvent(new PRS1IPAPHighEvent(t, data[pos+2])); // 2
+                this->AddEvent(new PRS1LeakEvent(t, data[pos+3])); // 3  // F5V2, is this really unintentional leak rather than total leak?
+                this->AddEvent(new PRS1TidalVolumeEvent(t, data[pos+7])); // 7
+                this->AddEvent(new PRS1RespiratoryRateEvent(t, data[pos+4])); // 4
+                this->AddEvent(new PRS1PatientTriggeredBreathsEvent(t, data[pos+5]));  // 5
+                this->AddEvent(new PRS1MinuteVentilationEvent(t,  data[pos+6])); //6
+                this->AddEvent(new PRS1SnoreEvent(t, data[pos+8])); //??
+                this->AddEvent(new PRS1EPAPAverageEvent(t, data[pos+9])); // 9
                 pos+=11;
             } else {
                 qDebug() << "0x0E Observed in ASV data!!????";
-                data0 = buffer[pos++]; // << 8) | buffer[pos];
+                data0 = data[pos++]; // << 8) | data[pos];
 
             }
             //session->AddEvent(new Event(t,cpapcode, 0, data, 1));
@@ -2334,25 +2349,25 @@ bool PRS1DataChunk::ParseEventsF5V012(void)
         case 0x0f:
             qDebug() << "0x0f Observed in ASV data!!????";
 
-            data0 = buffer[pos + 1] << 8 | buffer[pos];
+            data0 = data[pos + 1] << 8 | data[pos];
             pos += 2;
-            data1 = buffer[pos]; //|buffer[pos+1] << 8
+            data1 = data[pos]; //|data[pos+1] << 8
             pos += 1;
             //tt -= qint64(data1) * 1000L;
             //session->AddEvent(new Event(tt,cpapcode, 0, data, 2));
             break;
 
         case 0x10: // Unknown
-            data0 = buffer[pos + 1] << 8 | buffer[pos];
+            data0 = data[pos + 1] << 8 | data[pos];
             pos += 2;
-            data1 = buffer[pos++];
+            data1 = data[pos++];
 
             this->AddEvent(new PRS1LargeLeakEvent(t - data1, data0));
 
 //            qDebug() << "0x10 Observed in ASV data!!????";
-//            data0 = buffer[pos++]; // << 8) | buffer[pos];
-//            data1 = buffer[pos++];
-//            data2 = buffer[pos++];
+//            data0 = data[pos++]; // << 8) | data[pos];
+//            data1 = data[pos++];
+//            data2 = data[pos++];
             //session->AddEvent(new Event(t,cpapcode, 0, data, 3));
             break;
         case 0x11: // Not Leak Rate
@@ -2360,34 +2375,36 @@ bool PRS1DataChunk::ParseEventsF5V012(void)
             //if (!Code[24]) {
             //   Code[24]=new EventList(cpapcode,EVL_Event);
             //}
-            //Code[24]->AddEvent(t,buffer[pos++]);
+            //Code[24]->AddEvent(t,data[pos++]);
             break;
 
 
         case 0x12: // Summary
             qDebug() << "0x12 Observed in ASV data!!????";
-            data0 = buffer[pos++];
-            data1 = buffer[pos++];
-            //data2 = buffer[pos + 1] << 8 | buffer[pos];
+            data0 = data[pos++];
+            data1 = data[pos++];
+            //data2 = data[pos + 1] << 8 | data[pos];
             pos += 2;
             //session->AddEvent(new Event(t,cpapcode, 0, data,3));
             break;
 
-        default:  // ERROR!!!
-            qWarning() << "Some new fandangled PRS1 code detected " << hex << int(code) << " at " << pos - 1;
-            this->AddEvent(new PRS1UnknownDataEvent(m_data, startpos));
-            badcode = true;
-            break;
+            default:
+                DUMP_EVENT();
+                UNEXPECTED_VALUE(code, "known event code");
+                this->AddEvent(new PRS1UnknownDataEvent(m_data, startpos));
+                ok = false;  // unlike F0V6, we don't know the size of unknown slices, so we can't recover
+                break;
         }
+        pos = startpos + size;
+    } while (ok && pos < chunk_size);
 
-        if (badcode) {
-            break;
-        }
+    if (ok && pos != chunk_size) {
+        qWarning() << this->sessionid << (this->size() - pos) << "trailing event bytes";
     }
-    this->duration = t;  // The last event might start before t, so record the last delta timestamp.
 
-    return true;
+    this->duration = t;
 
+    return ok;
 }
 
 
@@ -3107,23 +3124,6 @@ bool PRS1Import::ParseF0Events()
     return true;
 }
 
-static QString DumpEvent(int t, int code, const unsigned char* data, int size)
-{
-    int s = t;
-    int h = s / 3600; s -= h * 3600;
-    int m = s / 60; s -= m * 60;
-    QString dump = QString("%1:%2:%3")
-        .arg(h, 2, 10, QChar('0'))
-        .arg(m, 2, 10, QChar('0'))
-        .arg(s, 2, 10, QChar('0'));
-    dump = dump + " " + hex(code) + ":";
-    for (int i = 0; i < size; i++) {
-        dump = dump + QString(" %1").arg(data[i]);
-    }
-    return dump;
-}
-#define DUMP_EVENT() qWarning() << this->sessionid << DumpEvent(t, code, data + pos, size - (pos - startpos)) << "@" << pos
-
 bool PRS1DataChunk::ParseEventsF0V23(CPAPMode /*mode*/)
 {
     if (this->family != 0 || this->familyVersion < 2 || this->familyVersion > 3) {