Merge remote-tracking branch 'origin/upstream' am: da962d0686 am: 41b390c0c7

Original change: undetermined

Change-Id: I83e08dc961b636da2dd956b9da4683f8d60b95b2
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7f1fdb7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+edid-decode
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..44b4a24
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,57 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["external_edid_decode_license"],
+}
+
+license {
+    name: "external_edid_decode_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-MIT",
+    ],
+    license_text: ["LICENSE"],
+}
+
+cc_binary {
+    name: "edid-decode",
+
+    srcs: [
+        "edid-decode.cpp",
+        "edid-decode.cpp",
+        "parse-base-block.cpp",
+        "parse-cta-block.cpp",
+        "parse-displayid-block.cpp",
+        "parse-ls-ext-block.cpp",
+        "parse-di-ext-block.cpp",
+        "parse-vtb-ext-block.cpp",
+        "calc-gtf-cvt.cpp",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Wno-missing-field-initializers",
+        "-Wno-unused-parameter",
+        "-Wno-implicit-fallthrough",
+        // edid-decode version = SHA + DATE
+        // Leave version blank by making SHA and DATE blank
+        "-DSHA=",
+        "-DDATE=",
+    ],
+
+    host_supported: true,
+
+}
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..6146137
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright 2006-2012 Red Hat, Inc.
+Copyright 2018-2020 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..6e50af2
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,17 @@
+name: "edid-decode"
+description:
+    "Decodes the Extended Display Identification Data (EDID) binary structure "
+    "into a human readable format."
+
+third_party {
+homepage: "https://git.linuxtv.org/edid-decode.git/"
+  identifier {
+    type: "Git"
+    value: "https://git.linuxtv.org/edid-decode.git/"
+    primary_source: true
+    version: "e908154d87394de9e84e900162a3035e6c398fb2"
+  }
+  version: "e908154d87394de9e84e900162a3035e6c398fb2"
+  license_type: NOTICE
+  last_upgrade_date { year: 2024 month: 8 day: 21 }
+}
diff --git a/MODULE_LICENSE_MIT b/MODULE_LICENSE_MIT
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_MIT
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..287b72d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,29 @@
+bindir ?= /usr/bin
+mandir ?= /usr/share/man
+
+EMXX ?= em++
+
+SOURCES = edid-decode.cpp parse-base-block.cpp parse-cta-block.cpp \
+	  parse-displayid-block.cpp parse-ls-ext-block.cpp \
+	  parse-di-ext-block.cpp parse-vtb-ext-block.cpp calc-gtf-cvt.cpp
+WARN_FLAGS = -Wall -Wextra -Wno-missing-field-initializers -Wno-unused-parameter
+
+all: edid-decode
+
+sha = -DSHA=$(shell if test -d .git ; then git rev-parse --short=12 HEAD ; fi)
+date = -DDATE=$(shell if test -d .git ; then printf '"'; TZ=UTC git show --quiet --date='format-local:%F %T"' --format="%cd"; fi)
+
+edid-decode: $(SOURCES) edid-decode.h Makefile
+	$(CXX) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(WARN_FLAGS) -g $(sha) $(date) -o $@ $(SOURCES) -lm
+
+edid-decode.js: $(SOURCES) edid-decode.h Makefile
+	$(EMXX) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(WARN_FLAGS) $(sha) $(date) -s EXPORTED_FUNCTIONS='["_parse_edid"]' -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' -o $@ $(SOURCES) -lm
+
+clean:
+	rm -f edid-decode
+
+install:
+	mkdir -p $(DESTDIR)$(bindir)
+	install -m 0755 edid-decode $(DESTDIR)$(bindir)
+	mkdir -p $(DESTDIR)$(mandir)/man1
+	install -m 0644 edid-decode.1 $(DESTDIR)$(mandir)/man1
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..3cabcaa
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,5 @@
+include platform/system/core:main:/janitors/OWNERS
+
+ddavenport@google.com
+sukoo@google.com
+seanpaul@google.com
diff --git a/README b/README
new file mode 100644
index 0000000..251587a
--- /dev/null
+++ b/README
@@ -0,0 +1,53 @@
+This utility is maintained here:
+
+https://git.linuxtv.org/edid-decode.git/
+
+To build this do:
+
+git clone git://linuxtv.org/edid-decode.git
+cd edid-decode
+make
+make install
+
+Patches and bug reports can be sent to the linux-media@vger.kernel.org
+mailinglist (see https://www.linuxtv.org/lists.php). Please make sure
+that 'edid-decode' appears in the subject line and don't forget to
+add a 'Signed-off-by' line when submitting patches!
+
+If you don't know what that is, then see:
+https://elinux.org/Developer_Certificate_Of_Origin
+
+New sample EDIDs are welcome. Please note that these must be real
+EDIDs read from real hardware, so no artificially constructed EDIDs.
+
+The naming of EDIDs in the data directory is:
+
+<vendor>-<model>-<port>[-tileX]
+
+<port> is one of dp, hdmi, vga, dvi
+When a tile is also specified, then dp should include the DP connector
+number, e.g. dp1-tile0, dp2-tile1.
+
+All lower case.
+
+If the EDID was modified by other devices in the chain (e.g. AV Receivers),
+then name the EDID as:
+
+<TV vendor>-<TV model>-<TV port>-<AV vendor>-<AV model>-<AV port>
+
+The test directory contains some special input files to verify the
+edid-decode parser and hand-crafted EDIDs to test rarely seen
+EDID features.
+
+You can find a very large collection of EDIDs here:
+https://github.com/linuxhw/EDID
+
+This collection has been used to test edid-decode.
+
+I can also be contacted directly:
+
+Hans Verkuil <hverkuil-cisco@xs4all.nl>
+
+Regards,
+
+	Hans
diff --git a/calc-gtf-cvt.cpp b/calc-gtf-cvt.cpp
new file mode 100644
index 0000000..bc32ea0
--- /dev/null
+++ b/calc-gtf-cvt.cpp
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2006-2012 Red Hat, Inc.
+ * Copyright 2018-2021 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ *
+ * Author: Adam Jackson <ajax@nwnk.net>
+ * Maintainer: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <time.h>
+
+#include "edid-decode.h"
+
+#define CELL_GRAN 8.0
+#define MARGIN_PERC 1.8
+#define GTF_MIN_PORCH 1.0
+#define GTF_V_SYNC_RQD 3.0
+#define GTF_H_SYNC_PERC 8.0
+#define GTF_MIN_VSYNC_BP 550.0
+
+timings edid_state::calc_gtf_mode(unsigned h_pixels, unsigned v_lines,
+				  double ip_freq_rqd, bool int_rqd,
+				  enum gtf_ip_parm ip_parm, bool margins_rqd,
+				  bool secondary, double C, double M, double K, double J)
+{
+	timings t = {};
+	/* C' and M' are part of the Blanking Duty Cycle computation */
+	double C_PRIME = ((C - J) * K / 256.0) + J;
+	double M_PRIME = K / 256.0 * M;
+
+	double h_pixels_rnd = round(h_pixels / CELL_GRAN) * CELL_GRAN;
+	double v_lines_rnd = int_rqd ? round(v_lines / 2.0) : v_lines;
+	unsigned hor_margin = margins_rqd ?
+		round(h_pixels_rnd * MARGIN_PERC / 100.0 / CELL_GRAN)  * CELL_GRAN : 0;
+	unsigned vert_margin = margins_rqd ? round(MARGIN_PERC / 100.0 * v_lines_rnd) : 0;
+	double interlace = int_rqd ? 0.5 : 0;
+	double total_active_pixels = h_pixels_rnd + hor_margin * 2;
+
+	t.hact = h_pixels_rnd;
+	t.vact = v_lines;
+	t.interlaced = int_rqd;
+
+	double pixel_freq;
+	double h_blank_pixels;
+	double total_pixels;
+	double v_sync_bp;
+
+	if (ip_parm == gtf_ip_vert_freq) {
+		// vertical frame frequency (Hz)
+		double v_field_rate_rqd = int_rqd ? ip_freq_rqd * 2 : ip_freq_rqd;
+		double h_period_est = ((1.0 / v_field_rate_rqd) - GTF_MIN_VSYNC_BP / 1000000.0) /
+			(v_lines_rnd + vert_margin * 2 + GTF_MIN_PORCH + interlace) * 1000000.0;
+		v_sync_bp = round(GTF_MIN_VSYNC_BP / h_period_est);
+		double total_v_lines = v_lines_rnd + vert_margin * 2 +
+			v_sync_bp + interlace + GTF_MIN_PORCH;
+		double v_field_rate_est = 1.0 / h_period_est / total_v_lines * 1000000.0;
+		double h_period = h_period_est / (v_field_rate_rqd / v_field_rate_est);
+		double ideal_duty_cycle = C_PRIME - (M_PRIME * h_period / 1000.0);
+		h_blank_pixels = round(total_active_pixels * ideal_duty_cycle /
+				       (100.0 - ideal_duty_cycle) /
+				       (2 * CELL_GRAN)) * 2 * CELL_GRAN;
+		total_pixels = total_active_pixels + h_blank_pixels;
+		pixel_freq = total_pixels / h_period;
+	} else if (ip_parm == gtf_ip_hor_freq) {
+		// horizontal frequency (kHz)
+		double h_freq = ip_freq_rqd;
+		v_sync_bp = round(GTF_MIN_VSYNC_BP * h_freq / 1000.0);
+		double ideal_duty_cycle = C_PRIME - (M_PRIME / h_freq);
+		h_blank_pixels = round(total_active_pixels * ideal_duty_cycle /
+				       (100.0 - ideal_duty_cycle) /
+				       (2 * CELL_GRAN)) * 2 * CELL_GRAN;
+		total_pixels = total_active_pixels + h_blank_pixels;
+		pixel_freq = total_pixels * h_freq / 1000.0;
+	} else {
+		// pixel clock rate (MHz)
+		pixel_freq = ip_freq_rqd;
+		double ideal_h_period =
+			((C_PRIME - 100.0) +
+			 sqrt(((100.0 - C_PRIME) * (100.0 - C_PRIME) +
+			       (0.4 * M_PRIME * (total_active_pixels + hor_margin * 2) /
+				pixel_freq)))) / 2.0 / M_PRIME * 1000.0;
+		double ideal_duty_cycle = C_PRIME - (M_PRIME * ideal_h_period) / 1000.0;
+		h_blank_pixels = round(total_active_pixels * ideal_duty_cycle /
+				       (100.0 - ideal_duty_cycle) /
+				       (2 * CELL_GRAN)) * 2 * CELL_GRAN;
+		total_pixels = total_active_pixels + h_blank_pixels;
+		double h_freq = pixel_freq / total_pixels * 1000.0;
+		v_sync_bp = round(GTF_MIN_VSYNC_BP * h_freq / 1000.0);
+	}
+
+	double v_back_porch = v_sync_bp - GTF_V_SYNC_RQD;
+
+	t.vbp = v_back_porch;
+	t.vsync = GTF_V_SYNC_RQD;
+	t.vfp = GTF_MIN_PORCH;
+	t.pixclk_khz = round(1000.0 * pixel_freq);
+	t.hsync = round(GTF_H_SYNC_PERC / 100.0 * total_pixels / CELL_GRAN) * CELL_GRAN;
+	t.hfp = (h_blank_pixels / 2.0) - t.hsync;
+	t.hbp = t.hfp + t.hsync;
+	t.hborder = hor_margin;
+	t.vborder = vert_margin;
+	t.pos_pol_hsync = secondary;
+	t.pos_pol_vsync = !secondary;
+	t.rb = secondary ? RB_GTF : RB_NONE;
+	return t;
+}
+
+void edid_state::edid_gtf_mode(unsigned refresh, struct timings &t)
+{
+	unsigned hratio = t.hratio;
+	unsigned vratio = t.vratio;
+	t = calc_gtf_mode(t.hact, t.vact, refresh, t.interlaced);
+	t.hratio = hratio;
+	t.vratio = vratio;
+}
+
+#define CVT_MIN_VSYNC_BP 550.0
+#define CVT_MIN_V_PORCH 3
+#define CVT_MIN_V_BPORCH 6
+#define CVT_C_PRIME 30.0
+#define CVT_M_PRIME 300.0
+#define CVT_RB_MIN_VBLANK 460.0
+
+// If rb == RB_CVT_V2, then alt means video-optimized (i.e. 59.94 instead of 60 Hz, etc.).
+// If rb == RB_CVT_V3, then alt means that rb_h_blank is 160 instead of 80.
+timings edid_state::calc_cvt_mode(unsigned h_pixels, unsigned v_lines,
+				  double ip_freq_rqd, unsigned rb, bool int_rqd,
+				  bool margins_rqd, bool alt, unsigned rb_h_blank)
+{
+	timings t = {};
+
+	t.hact = h_pixels;
+	t.vact = v_lines;
+	t.interlaced = int_rqd;
+
+	double cell_gran = rb == RB_CVT_V2 ? 1 : CELL_GRAN;
+	double h_pixels_rnd = floor(h_pixels / cell_gran) * cell_gran;
+	double v_lines_rnd = int_rqd ? floor(v_lines / 2.0) : v_lines;
+	unsigned hor_margin = margins_rqd ?
+		floor((h_pixels_rnd * MARGIN_PERC / 100.0) / cell_gran) * cell_gran : 0;
+	unsigned vert_margin = margins_rqd ? floor(MARGIN_PERC / 100.0 * v_lines_rnd) : 0;
+	double interlace = int_rqd ? 0.5 : 0;
+	double total_active_pixels = h_pixels_rnd + hor_margin * 2;
+	double v_field_rate_rqd = int_rqd ? ip_freq_rqd * 2 : ip_freq_rqd;
+	double clock_step = rb == RB_CVT_V2 ? 0.001 : 0.25;
+	double h_blank = (rb == RB_CVT_V1 || (rb == RB_CVT_V3 && alt)) ? 160 : 80;
+	double rb_v_fporch = rb == RB_CVT_V1 ? 3 : 1;
+	double refresh_multiplier = (rb == RB_CVT_V2 && alt) ? 1000.0 / 1001.0 : 1;
+	double h_sync = 32;
+
+	double v_sync;
+	double pixel_freq;
+	double v_blank;
+	double v_sync_bp;
+
+	if (rb == RB_CVT_V3 && rb_h_blank) {
+		h_blank = rb_h_blank & ~7;
+		if (h_blank < 80)
+			h_blank = 80;
+		else if (h_blank > 200)
+			h_blank = 200;
+	}
+
+	/* Determine VSync Width from aspect ratio */
+	if ((t.vact * 4 / 3) == t.hact)
+		v_sync = 4;
+	else if ((t.vact * 16 / 9) == t.hact)
+		v_sync = 5;
+	else if ((t.vact * 16 / 10) == t.hact)
+		v_sync = 6;
+	else if (!(t.vact % 4) && ((t.vact * 5 / 4) == t.hact))
+		v_sync = 7;
+	else if ((t.vact * 15 / 9) == t.hact)
+		v_sync = 7;
+	else                        /* Custom */
+		v_sync = 10;
+
+	if (rb >= RB_CVT_V2)
+		v_sync = 8;
+
+	if (rb == RB_NONE) {
+		double h_period_est = ((1.0 / v_field_rate_rqd) - CVT_MIN_VSYNC_BP / 1000000.0) /
+			(v_lines_rnd + vert_margin * 2 + CVT_MIN_V_PORCH + interlace) * 1000000.0;
+		v_sync_bp = floor(CVT_MIN_VSYNC_BP / h_period_est) + 1;
+		if (v_sync_bp < v_sync + CVT_MIN_V_BPORCH)
+			v_sync_bp = v_sync + CVT_MIN_V_BPORCH;
+		v_blank = v_sync_bp + CVT_MIN_V_PORCH;
+		double ideal_duty_cycle = CVT_C_PRIME - (CVT_M_PRIME * h_period_est / 1000.0);
+		if (ideal_duty_cycle < 20)
+			ideal_duty_cycle = 20;
+		h_blank = floor(total_active_pixels * ideal_duty_cycle /
+				(100.0 - ideal_duty_cycle) /
+				(2 * CELL_GRAN)) * 2 * CELL_GRAN;
+		double total_pixels = total_active_pixels + h_blank;
+		h_sync = floor(total_pixels * 0.08 / CELL_GRAN) * CELL_GRAN;
+		pixel_freq = floor((total_pixels / h_period_est) / clock_step) * clock_step;
+	} else {
+		double h_period_est = ((1000000.0 / v_field_rate_rqd) - CVT_RB_MIN_VBLANK) /
+					(v_lines_rnd + vert_margin * 2);
+		double vbi_lines = floor(CVT_RB_MIN_VBLANK / h_period_est) + 1;
+		double rb_min_vbi = rb_v_fporch + v_sync + CVT_MIN_V_BPORCH;
+		v_blank = vbi_lines < rb_min_vbi ? rb_min_vbi : vbi_lines;
+		double total_v_lines = v_blank + v_lines_rnd + vert_margin * 2 + interlace;
+		if (rb == RB_CVT_V1)
+			v_sync_bp = v_blank - rb_v_fporch;
+		else
+			v_sync_bp = v_sync + CVT_MIN_V_BPORCH;
+		double total_pixels = h_blank + total_active_pixels;
+		double freq = v_field_rate_rqd * total_v_lines * total_pixels * refresh_multiplier;
+		if (rb == RB_CVT_V3)
+			pixel_freq = ceil((freq / 1000000.0) / clock_step) * clock_step;
+		else
+			pixel_freq = floor((freq / 1000000.0) / clock_step) * clock_step;
+	}
+
+	t.vbp = v_sync_bp - v_sync;
+	t.vsync = v_sync;
+	t.vfp = v_blank - t.vbp - t.vsync;
+	t.pixclk_khz = round(1000.0 * pixel_freq);
+	t.hsync = h_sync;
+	if (rb == RB_CVT_V3)
+		t.hfp = 8;
+	else
+		t.hfp = (h_blank / 2.0) - t.hsync;
+	t.hbp = h_blank - t.hfp - t.hsync;
+	t.hborder = hor_margin;
+	t.vborder = vert_margin;
+	t.rb = rb;
+	if (alt && (rb == RB_CVT_V2 || rb == RB_CVT_V3))
+		t.rb |= RB_ALT;
+	t.pos_pol_hsync = t.rb;
+	t.pos_pol_vsync = !t.rb;
+	calc_ratio(&t);
+	return t;
+}
+
+void edid_state::edid_cvt_mode(unsigned refresh, struct timings &t)
+{
+	unsigned hratio = t.hratio;
+	unsigned vratio = t.vratio;
+
+	t = calc_cvt_mode(t.hact, t.vact, refresh, t.rb & ~RB_ALT, t.interlaced,
+			  false, t.rb & RB_ALT);
+	t.hratio = hratio;
+	t.vratio = vratio;
+}
diff --git a/data/acer-xv273k-dp b/data/acer-xv273k-dp
new file mode 100644
index 0000000..47c1528
--- /dev/null
+++ b/data/acer-xv273k-dp
Binary files differ
diff --git a/data/acer-xv273k-dp1-tile0 b/data/acer-xv273k-dp1-tile0
new file mode 100644
index 0000000..d93c5d2
--- /dev/null
+++ b/data/acer-xv273k-dp1-tile0
Binary files differ
diff --git a/data/acer-xv273k-dp2-tile1 b/data/acer-xv273k-dp2-tile1
new file mode 100644
index 0000000..8e41faf
--- /dev/null
+++ b/data/acer-xv273k-dp2-tile1
Binary files differ
diff --git a/data/apple-cinemahd-30-dvi b/data/apple-cinemahd-30-dvi
new file mode 100644
index 0000000..be6ae1c
--- /dev/null
+++ b/data/apple-cinemahd-30-dvi
Binary files differ
diff --git a/data/asus-vw246-hdmi b/data/asus-vw246-hdmi
new file mode 100644
index 0000000..e17f33c
--- /dev/null
+++ b/data/asus-vw246-hdmi
Binary files differ
diff --git a/data/dell-2408wfp-dp b/data/dell-2408wfp-dp
new file mode 100644
index 0000000..32ec2f6
--- /dev/null
+++ b/data/dell-2408wfp-dp
Binary files differ
diff --git a/data/dell-3007wfp-dvi b/data/dell-3007wfp-dvi
new file mode 100644
index 0000000..922bad5
--- /dev/null
+++ b/data/dell-3007wfp-dvi
Binary files differ
diff --git a/data/dell-e178wfp-vga b/data/dell-e178wfp-vga
new file mode 100644
index 0000000..7915446
--- /dev/null
+++ b/data/dell-e178wfp-vga
Binary files differ
diff --git a/data/dell-p2415q-dp b/data/dell-p2415q-dp
new file mode 100644
index 0000000..ffc77f0
--- /dev/null
+++ b/data/dell-p2415q-dp
Binary files differ
diff --git a/data/dell-p2415q-hdmi1.4 b/data/dell-p2415q-hdmi1.4
new file mode 100644
index 0000000..ada8d54
--- /dev/null
+++ b/data/dell-p2415q-hdmi1.4
Binary files differ
diff --git a/data/dell-p2415q-hdmi2.0 b/data/dell-p2415q-hdmi2.0
new file mode 100644
index 0000000..d9f3eca
--- /dev/null
+++ b/data/dell-p2415q-hdmi2.0
Binary files differ
diff --git a/data/dell-up2715k-dp b/data/dell-up2715k-dp
new file mode 100644
index 0000000..835aaa5
--- /dev/null
+++ b/data/dell-up2715k-dp
Binary files differ
diff --git a/data/dell-up2715k-dp-switchresx b/data/dell-up2715k-dp-switchresx
new file mode 100644
index 0000000..d0d425a
--- /dev/null
+++ b/data/dell-up2715k-dp-switchresx
Binary files differ
diff --git a/data/dell-up2715k-dp1-tile1 b/data/dell-up2715k-dp1-tile1
new file mode 100644
index 0000000..424394d
--- /dev/null
+++ b/data/dell-up2715k-dp1-tile1
Binary files differ
diff --git a/data/dell-up2715k-dp2-tile0 b/data/dell-up2715k-dp2-tile0
new file mode 100644
index 0000000..c95095f
--- /dev/null
+++ b/data/dell-up2715k-dp2-tile0
Binary files differ
diff --git a/data/dell-up2718q-dp b/data/dell-up2718q-dp
new file mode 100644
index 0000000..9c6667f
--- /dev/null
+++ b/data/dell-up2718q-dp
Binary files differ
diff --git a/data/dell-up3218k-dp1-tile0 b/data/dell-up3218k-dp1-tile0
new file mode 100644
index 0000000..fc8d3d0
--- /dev/null
+++ b/data/dell-up3218k-dp1-tile0
Binary files differ
diff --git a/data/dell-up3218k-dp2-tile1 b/data/dell-up3218k-dp2-tile1
new file mode 100644
index 0000000..35bf693
--- /dev/null
+++ b/data/dell-up3218k-dp2-tile1
Binary files differ
diff --git a/data/elo-4600l-hdmi b/data/elo-4600l-hdmi
new file mode 100644
index 0000000..2a2fa4c
--- /dev/null
+++ b/data/elo-4600l-hdmi
Binary files differ
diff --git a/data/hp-lp2275w-dp b/data/hp-lp2275w-dp
new file mode 100644
index 0000000..6bc442f
--- /dev/null
+++ b/data/hp-lp2275w-dp
Binary files differ
diff --git a/data/hp-lp2480zx-dp b/data/hp-lp2480zx-dp
new file mode 100644
index 0000000..15a8355
--- /dev/null
+++ b/data/hp-lp2480zx-dp
Binary files differ
diff --git a/data/hp-lp2480zx-hdmi b/data/hp-lp2480zx-hdmi
new file mode 100644
index 0000000..92185a3
--- /dev/null
+++ b/data/hp-lp2480zx-hdmi
Binary files differ
diff --git a/data/kogan-kaled24144f-dp b/data/kogan-kaled24144f-dp
new file mode 100644
index 0000000..ce340a6
--- /dev/null
+++ b/data/kogan-kaled24144f-dp
Binary files differ
diff --git a/data/kogan-kaled24144f-hdmi b/data/kogan-kaled24144f-hdmi
new file mode 100644
index 0000000..f3d4a0f
--- /dev/null
+++ b/data/kogan-kaled24144f-hdmi
Binary files differ
diff --git a/data/lg-32ud99-w-dp b/data/lg-32ud99-w-dp
new file mode 100644
index 0000000..b62a6b0
--- /dev/null
+++ b/data/lg-32ud99-w-dp
Binary files differ
diff --git a/data/lg-32ud99-w-hdmi b/data/lg-32ud99-w-hdmi
new file mode 100644
index 0000000..a19ccda
--- /dev/null
+++ b/data/lg-32ud99-w-hdmi
Binary files differ
diff --git a/data/lg-55uh5c-hdmi b/data/lg-55uh5c-hdmi
new file mode 100644
index 0000000..61c70d9
--- /dev/null
+++ b/data/lg-55uh5c-hdmi
Binary files differ
diff --git a/data/lg-75uh5c-hdmi b/data/lg-75uh5c-hdmi
new file mode 100644
index 0000000..ec96ddd
--- /dev/null
+++ b/data/lg-75uh5c-hdmi
Binary files differ
diff --git a/data/lg-88bh7d-hdmi b/data/lg-88bh7d-hdmi
new file mode 100644
index 0000000..0d411ae
--- /dev/null
+++ b/data/lg-88bh7d-hdmi
Binary files differ
diff --git a/data/lg-l206wu-usb-dvi b/data/lg-l206wu-usb-dvi
new file mode 100644
index 0000000..8a2681f
--- /dev/null
+++ b/data/lg-l206wu-usb-dvi
Binary files differ
diff --git a/data/lg-oled-c9-hdmi b/data/lg-oled-c9-hdmi
new file mode 100644
index 0000000..e46aa67
--- /dev/null
+++ b/data/lg-oled-c9-hdmi
Binary files differ
diff --git a/data/lg-oled-cx-hdmi b/data/lg-oled-cx-hdmi
new file mode 100644
index 0000000..a539057
--- /dev/null
+++ b/data/lg-oled-cx-hdmi
Binary files differ
diff --git a/data/lg-oled55b6v-hdmi b/data/lg-oled55b6v-hdmi
new file mode 100644
index 0000000..baebd80
--- /dev/null
+++ b/data/lg-oled55b6v-hdmi
Binary files differ
diff --git a/data/lg-oled55b6v-hdmi-denon-avr-x2300w-hdmi b/data/lg-oled55b6v-hdmi-denon-avr-x2300w-hdmi
new file mode 100644
index 0000000..9300a98
--- /dev/null
+++ b/data/lg-oled55b6v-hdmi-denon-avr-x2300w-hdmi
Binary files differ
diff --git a/data/lg-oled55e6v-hdmi b/data/lg-oled55e6v-hdmi
new file mode 100644
index 0000000..7524bef
--- /dev/null
+++ b/data/lg-oled55e6v-hdmi
Binary files differ
diff --git a/data/lg-ultrafine-5k-v2-thunderbolt-dp1-tile0 b/data/lg-ultrafine-5k-v2-thunderbolt-dp1-tile0
new file mode 100644
index 0000000..13ab607
--- /dev/null
+++ b/data/lg-ultrafine-5k-v2-thunderbolt-dp1-tile0
Binary files differ
diff --git a/data/lg-ultrafine-5k-v2-thunderbolt-dp2-tile1 b/data/lg-ultrafine-5k-v2-thunderbolt-dp2-tile1
new file mode 100644
index 0000000..abc93a4
--- /dev/null
+++ b/data/lg-ultrafine-5k-v2-thunderbolt-dp2-tile1
Binary files differ
diff --git a/data/matrox-triplehead2go-dvi b/data/matrox-triplehead2go-dvi
new file mode 100644
index 0000000..891471c
--- /dev/null
+++ b/data/matrox-triplehead2go-dvi
Binary files differ
diff --git a/data/oculus-rift-dk1-hdmi b/data/oculus-rift-dk1-hdmi
new file mode 100644
index 0000000..a677d6a
--- /dev/null
+++ b/data/oculus-rift-dk1-hdmi
Binary files differ
diff --git a/data/samsung-qm65h-hdmi b/data/samsung-qm65h-hdmi
new file mode 100644
index 0000000..a3c450a
--- /dev/null
+++ b/data/samsung-qm65h-hdmi
Binary files differ
diff --git a/data/samsung-qp82r-8k-hdmi4 b/data/samsung-qp82r-8k-hdmi4
new file mode 100644
index 0000000..6487a9f
--- /dev/null
+++ b/data/samsung-qp82r-8k-hdmi4
Binary files differ
diff --git a/data/samsung-ue40d8000yu-hmdi b/data/samsung-ue40d8000yu-hmdi
new file mode 100644
index 0000000..ba87cb0
--- /dev/null
+++ b/data/samsung-ue40d8000yu-hmdi
Binary files differ
diff --git a/data/samsung-ue40ku6070-hdmi b/data/samsung-ue40ku6070-hdmi
new file mode 100644
index 0000000..92dfe51
--- /dev/null
+++ b/data/samsung-ue40ku6070-hdmi
Binary files differ
diff --git a/data/samsung-ue48ju7090-hdmi b/data/samsung-ue48ju7090-hdmi
new file mode 100644
index 0000000..521ab8f
--- /dev/null
+++ b/data/samsung-ue48ju7090-hdmi
Binary files differ
diff --git a/data/samsung-ue49ks8005-hdmi b/data/samsung-ue49ks8005-hdmi
new file mode 100644
index 0000000..56084ee
--- /dev/null
+++ b/data/samsung-ue49ks8005-hdmi
Binary files differ
diff --git a/data/samsung-ue55ks-hdmi b/data/samsung-ue55ks-hdmi
new file mode 100644
index 0000000..e8247b6
--- /dev/null
+++ b/data/samsung-ue55ks-hdmi
Binary files differ
diff --git a/data/sharp-aquos-hdmi b/data/sharp-aquos-hdmi
new file mode 100644
index 0000000..e2a37bb
--- /dev/null
+++ b/data/sharp-aquos-hdmi
Binary files differ
diff --git a/data/sharp-pn465-dvi b/data/sharp-pn465-dvi
new file mode 100644
index 0000000..bd6c7f8
--- /dev/null
+++ b/data/sharp-pn465-dvi
Binary files differ
diff --git a/data/skyworth-50e780u-hdmi b/data/skyworth-50e780u-hdmi
new file mode 100644
index 0000000..b618a6f
--- /dev/null
+++ b/data/skyworth-50e780u-hdmi
Binary files differ
diff --git a/data/sony-kd55xd-hdmi b/data/sony-kd55xd-hdmi
new file mode 100644
index 0000000..3f203ae
--- /dev/null
+++ b/data/sony-kd55xd-hdmi
Binary files differ
diff --git a/edid-decode.1 b/edid-decode.1
new file mode 100644
index 0000000..ecd7fe3
--- /dev/null
+++ b/edid-decode.1
@@ -0,0 +1,336 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH edid-decode 1
+.SH NAME
+edid-decode - Decode EDID data in human-readable format
+.SH SYNOPSIS
+.B edid-decode <options> [in [out]]
+.SH DESCRIPTION
+.B edid-decode
+decodes EDID monitor description data in human-readable format.
+If [in] is not given, or [in] is '-', then the EDID will be read from
+standard input. If [out] is given then the EDID that was read from [in]
+is written to [out] or to standard output if [out] is '-'. By default
+the output is written as a hex dump when writing to standard output or
+a raw EDID if written to a file.
+
+If [out] is given then edid-decode only does the conversion, it will
+skip the decoding step.
+.PP
+Input files may be raw binaries or ASCII text.  ASCII input is scanned for
+hex dumps; heuristics are included to search for hexdumps in
+.B edid-decode(1)
+output (as long as the initial hex dump was included),
+.B xrandr(1)
+property output and
+.B Xorg(1)
+log file formats, otherwise the data is treated as a raw hexdump.  EDID blocks
+for connected monitors can be found in
+.B /sys/class/drm/*/edid
+on modern Linux systems with kernel modesetting support.
+
+All timings are shown in a short format, for example:
+
+    VIC  16:  1920x1080   60.000 Hz  16:9    67.500 kHz 148.500 MHz (native)
+    VIC   5:  1920x1080i  60.000 Hz  16:9    33.750 kHz  74.250 MHz
+    VIC  39:  1920x1080i  50.000 Hz  16:9    31.250 kHz  72.000 MHz
+
+Each format starts with a timings type prefix, the resolution, an optional
+interlaced indicator ('i'), the frame rate (field rate for interlaced formats),
+the picture aspect ratio, the horizontal frequency, the pixelclock
+frequency and optionally additional flags between parenthesis.
+
+Note that for interlaced formats the frame height is given, not the field
+height. So each field in a 1920x1080i format has 540 lines.
+
+Detailed timings have another 2-3 lines of data:
+
+    VIC  16:  1920x1080   60.000 Hz  16:9    67.500 kHz 148.500 MHz (native)
+                   Hfront   88 Hsync  44 Hback 148 Hpol P
+                   Vfront    4 Vsync   5 Vback  36 Vpol P
+    VIC   5:  1920x1080i  60.000 Hz  16:9    33.750 kHz  74.250 MHz
+                   Hfront   88 Hsync  44 Hback 148 Hpol P
+                   Vfront    2 Vsync   5 Vback  15 Vpol P Vfront +0.5 Odd Field
+                   Vfront    2 Vsync   5 Vback  15 Vpol P Vback  +0.5 Even Field
+    VIC  39:  1920x1080i  50.000 Hz  16:9    31.250 kHz  72.000 MHz
+                   Hfront   32 Hsync 168 Hback 184 Hpol P
+                   Vfront   23 Vsync   5 Vback  57 Vpol N Both Fields
+
+These describe the horizontal and vertical front porch, sync, backporch
+and sync polarity values. For interlaced formats there are two lines
+for the vertical information: one for the Odd Field (aka Field 1) and
+one for the Even Field (aka Field 2). The vertical front porch of the
+Odd Field is actually 2.5 (hence the 'Vfront +0.5' at the end of the
+line), and the back porch of the Even Field is actually 15.5 (hence
+the 'Vback  +0.5' at the end of the line).
+
+There is a special 'VIC 39' interlaced format where both fields have
+the same vertical timings, in that case this is marked with 'Both Fields'.
+
+The following timing types can be shown:
+
+.RS
+.TP
+DMT #: Discrete Monitor Timing (see DMT 1.3 standard). The number is the DMT ID in hexadecimal.
+.TP
+CVT: Coordinated Video Timings (formula-based, see CVT 1.2 standard)
+.TP
+GTF: Generalized Timing Formula (formula-based, see GTF 1.1 standard)
+.TP
+IBM: Old IBM Timings
+.TP
+Apple: Old Apple Timings
+.TP
+VIC #: Video Identification Code (see CTA-861 standard). The number is the actual
+VIC code.
+.TP
+HDMI VIC #: HDMI-specific Video Identification Code (see HDMI 2.1 standard). The number
+is the actual HDMI VIC code.
+.TP
+DTD #: Detailed Timings Descriptor (see EDID standard). Also used for
+DisplayID Video Timing Modes Types I, II, VI and VII. The number denotes that
+this is the Nth DTD in the EDID.
+.RE
+
+By default DTDs are shown in the long format while others are just shown in
+the short format. With the option \fB\-\-short\-timings\fR all timings are
+shown in short format only. With the option \fB\-\-long\-timings\fR all timings
+are shown in long format.
+
+Alternate formats for long timings can be chosen via the \fB\-\-xmodeline\fR or
+\fB\-\-fbmode\fR options.
+
+.SH STANDARDS
+.TP
+The following EDID standards are supported by edid-decode:
+.RS
+.TP
+EDID 1.3: VESA Enhanced Extended Display Identication Data Standard, Release A, Revision 1
+.TP
+EDID 1.4: VESA Enhanced Extended Display Identication Data Standard, Release A, Revision 2
+.TP
+DisplayID 1.3: VESA Display Identification Data (DisplayID) Standard, Version 1.3
+.TP
+DisplayID 2.0: VESA DisplayID Standard, Version 2.0
+.TP
+DisplayID 2.0: VESA DisplayID v2.0 Errata E7
+.TP
+DI-EXT: VESA Display Information Extension Block Standard, Release A
+.TP
+LS-EXT: VESA Enhanced EDID Localized String Extension Standard, Release A
+.TP
+VTB-EXT: VESA Video Timing Block Extension Data Standard, Release A
+.TP
+DTCDB: VESA Display Transfer Characteristics Data Block Standard, Version 1.0
+.TP
+DDDB: VESA Display Device Data Block (DDDB) Standard, Version 1
+.TP
+HDMI 1.4b: High-Definition Multimedia Interface, Version 1.4b
+.TP
+HDMI 2.1: High-Definition Multimedia Interface, Version 2.1
+.TP
+HDMI 2.1: Amendment A1 to HDMI Specification Version 2.1
+.TP
+CTA-861-H: A DTV Profile for Uncompressed High Speed Digital Interfaces
+.TP
+SPWG Notebook Panel Specification, Version 3.5
+.TP
+EPI Embedded Panel Interface, Revision 1.0
+.TP
+Microsoft EDID extension for head-mounted and specialized monitors, Version 3
+.RE
+
+.TP
+The following related standards are also used by edid-decode:
+.RS
+.TP
+DMT 1.3: VESA and Industry Standards and Guidelines for Computer Display Monitor Timing (DMT), Version 1.0, Rev. 13
+.TP
+CVT 1.2: VESA Coordinated Video Timings (CVT) Standard, Version 1.2
+.TP
+CVT 1.2: VESA CVT v1.2 Errata E1
+.TP
+GTF 1.1: VESA Generalized Timing Formula Standard, Version: 1.1
+.RE
+
+.SH OPTIONS
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Prints the help message.
+.TP
+\fB\-o\fR, \fB\-\-output\-format\fR \fI<fmt>\fR
+If [out] is specified, then write the EDID in format \fI<fmt>\fR.
+
+The output format can be one of:
+.br
+hex: hex numbers in ascii text (default for stdout)
+.br
+raw: binary data (default unless writing to stdout)
+.br
+carray: c-program struct
+.br
+xml: XML data
+.TP
+\fB\-c\fR, \fB\-\-check\fR
+Check if the EDID conforms to the standards. Warnings and failures are
+reported at the end.
+.TP
+\fB\-C\fR, \fB\-\-check\-inline\fR
+Check if the EDID conforms to the standards. Warnings and failures are
+reported as they happen.
+.TP
+\fB\-n\fR, \fB\-\-native\-timings\fR
+Report the native timings at the end. There may be multiple native timing reports
+depending on whether the Source only parses Block 0 (e.g. DVI outputs) or Block 0
+and the CTA-861 Extension Blocks (HDMI).
+.TP
+\fB\-p\fR, \fB\-\-preferred\-timings\fR
+Report the preferred timings at the end. There may be multiple native timing reports
+depending on whether the Source only parses Block 0 (e.g. DVI outputs), or Block 0
+and the CTA-861 Extension Blocks (HDMI), or Block 0 and the DisplayID Extension Blocks
+(typical for DisplayPort).
+.TP
+\fB\-P\fR, \fB\-\-physical\-address\fR
+Just report the HDMI Source Physical Address and nothing else. Reports f.f.f.f
+if the EDID could not be parsed, or if there was no CTA-861 Vendor-Specific Data Block
+with OUI 00-0C-03. Otherwise it reports the Source Physical Address as provided
+in that Data Block. This can be used as input to HDMI CEC utilities such as the
+linux cec-ctl(1) utility.
+.TP
+\fB\-S\fR, \fB\-\-short\-timings\fR
+Report all video timings in a short format.
+.TP
+\fB\-L\fR, \fB\-\-long\-timings\fR
+Report all video timings in a long format.
+.TP
+\fB\-X\fR, \fB\-\-xmodeline\fR
+Report all long video timings in the ModeLine format as defined in xorg.conf(5).
+This ModeLine can be used in the xorg.conf file or passed to xrandr(1) with the
+xrandr \fB\-\-newmode\fR option.
+.TP
+\fB\-F\fR, \fB\-\-fbmode\fR
+Report all long video timings in the video mode format as defined in fb.modes(5).
+.TP
+\fB\-V\fR, \fB\-\-v4l2\-timings\fR
+Report all long video timings in the video mode format as defined in the linux header v4l2-dv-timings.h
+for use with the V4L2 VIDIOC_S_DV_TIMINGS ioctl.
+.TP
+\fB\-s\fR, \fB\-\-skip\-hex\-dump\fR
+Skip the initial hex dump of the EDID.
+.TP
+\fB\-H\fR, \fB\-\-only\-hex\-dump\fR
+Only show the hex dump of the EDID, then exit.
+.TP
+\fB\-\-skip\-sha\fR
+Don't show the SHA hash. Normally edid-decode will show the SHA, i.e. the
+hash of the git commit used to compile edid-decode. This uniquely identifies
+the version of edid-decode that is used to generate the warnings and
+failures. But it will also change the output of edid-decode for every new commit
+in the git repository, even if nothing else changed in the edid-decode output.
+Use this option to avoid including the SHA in the edid-decode output.
+.TP
+\fB\-\-hide\-serial\-numbers\fR
+Replace any serial numbers in the human readable output by '...'.
+Note that they are still easily extracted from the EDID hex dump at
+the start.
+.TP
+\fB\-\-version\fR
+Show the SHA hash and the last commit date.
+
+.SH TIMING OPTIONS
+The following options report the timings for DMT, VIC and HDMI VIC codes and
+calculate the timings for CVT or GTF timings, based on the given parameters.
+The EDID will not be shown, although it can be used with the \fB\-\-gtf\fR
+option in order to read the secondary curve parameters.
+.TP
+\fB\-\-std\fR \fI<byte1>\fR,\fI<byte2>\fR
+Show the standard timing represented by these two bytes.
+.TP
+\fB\-\-dmt\fR \fI<dmt>\fR
+Show the timings for the DMT with the given DMT ID.
+.TP
+\fB\-\-vic\fR \fI<vic>\fR
+Show the timings for this VIC.
+.TP
+\fB\-\-hdmi\-vic\fR \fI<hdmivic>\fR
+Show the timings for this HDMI VIC.
+.TP
+\fB\-\-cvt\fR \fBw\fR=\fI<width>\fR,\fBh\fR=\fI<height>\fR,\fBfps\fR=\fI<fps>\fR[,\fBrb\fR=\fI<rb>\fR][,\fBinterlaced\fR][,\fBoverscan\fR][,\fBalt\fR][,\fBhblank\fR=\fI<hblank>\fR]
+.br
+Calculate the CVT timings for the given format.
+
+\fI<width>\fR is the width in pixels, \fI<height>\fR is the frame (not field!) height in lines.
+.br
+\fI<fps>\fR is frames per second for progressive timings and fields per second for interlaced timings.
+.br
+\fI<rb>\fR can be 0 (no reduced blanking, default), or 1-3 for the reduced blanking version.
+.br
+If \fBinterlaced\fR is given, then this is an interlaced format.
+.br
+If \fBoverscan\fR is given, then this is an overscanned format. I.e., margins are required.
+.br
+If \fBalt\fR is given and \fI<rb>\fR=2, then report the timings
+optimized for video: 1000 / 1001 * \fI<fps>\fR.
+.br
+If \fBalt\fR is given and \fI<rb>\fR=3, then the horizontal blanking
+is 160 instead of 80 pixels.
+.br
+If \fBhblank\fR is given and \fI<rb>\fR=3, then the horizontal blanking
+is \fI<hblank>\fR pixels (range of 80-200 and divisible by 8), overriding \fBalt\fR.
+.TP
+\fB\-\-gtf\fR \fBw\fR=\fI<width>\fR,\fBh\fR=\fI<height>\fR[,\fBfps\fR=\fI<fps>\fR][,\fBhorfreq\fR=\fI<horfreq>\fR][,\fBpixclk\fR=\fI<pixclk>\fR]
+[,\fBinterlaced\fR][,\fBoverscan\fR][,\fBsecondary\fR][,\fBC\fR=\fI<c>\fR][,\fBM\fR=\fI<m>\fR][,\fBK\fR=\fI<k>\fR][,\fBJ\fR=\fI<j>\fR]
+.br
+Calculate the GTF timings for the given format.
+
+\fI<width>\fR is the width in pixels, \fI<height>\fR is the frame (not field!) height in lines.
+.br
+\fI<fps>\fR is frames per second for progressive timings and fields per second for interlaced timings.
+.br
+\fI<horfreq>\fR is the horizontal frequency in kHz.
+.br
+\fI<pixclk>\fR is the pixel clock frequency in MHz.
+Only one of \fBfps\fR, \fBhorfreq\fR or \fBpixclk\fR must be given.
+.br
+If \fBinterlaced\fR is given, then this is an interlaced format.
+.br
+If \fBoverscan\fR is given, then this is an overscanned format. I.e., margins are required.
+.br
+If \fBsecondary\fR is given, then the secondary GTF is used for
+reduced blanking, where \fI<c>\fR, \fI<m>\fR, \fI<k>\fR and \fI<j>\fR are parameters
+for the secondary curve.  If none of the secondary curve parameters
+were set, and an EDID file is passed as command line option, then the
+secondary curve parameters are read from that EDID.
+.br
+The default secondary curve parameters are 40 for \fI<c>\fR, 600 for \fI<m>\fR,
+128 for \fI<k>\fR and 20 for \fI<j>\fR.
+These values correspond to the normal curve that GTF uses.
+.TP
+\fB\-\-list\-established\-timings\fR
+List all known Established Timings.
+.TP
+\fB\-\-list\-dmts\fR
+List all known DMTs.
+.TP
+\fB\-\-list\-vics\fR
+List all known VICs.
+.TP
+\fB\-\-list\-hdmi\-vics\fR
+List all known HDMI VICs.
+
+.PP
+.SH NOTES
+Not all fields are decoded, or decoded completely.
+.B edid-decode
+does attempt to validate its input against the relevant standards, but its
+opinions have not been double-checked with the relevant standards bodies,
+so they may be wrong.  Do not rely on the output format, as it will likely
+change in future versions of the tool as additional fields and extensions are
+added.
+.SH "SEE ALSO"
+Xorg(1), xrandr(1), cec-ctl(1), xorg.conf(5), fb.modes(5)
+.SH AUTHORS
+edid-decode was written by Adam Jackson, with contributions from Eric
+Anholt, Damien Lespiau, Hans Verkuil and others.  For complete history and the
+latest version, see
+.B http://git.linuxtv.org/cgit.cgi/edid-decode.git
diff --git a/edid-decode.cpp b/edid-decode.cpp
new file mode 100644
index 0000000..de70242
--- /dev/null
+++ b/edid-decode.cpp
@@ -0,0 +1,1794 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2006-2012 Red Hat, Inc.
+ * Copyright 2018-2020 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ *
+ * Author: Adam Jackson <ajax@nwnk.net>
+ * Maintainer: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+ */
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "edid-decode.h"
+
+#define STR(x) #x
+#define STRING(x) STR(x)
+
+static edid_state state;
+
+static unsigned char edid[EDID_PAGE_SIZE * EDID_MAX_BLOCKS];
+static bool odd_hex_digits;
+
+enum output_format {
+	OUT_FMT_DEFAULT,
+	OUT_FMT_HEX,
+	OUT_FMT_RAW,
+	OUT_FMT_CARRAY,
+	OUT_FMT_XML,
+};
+
+/*
+ * Options
+ * Please keep in alphabetical order of the short option.
+ * That makes it easier to see which options are still free.
+ */
+enum Option {
+	OptCheck = 'c',
+	OptCheckInline = 'C',
+	OptFBModeTimings = 'F',
+	OptHelp = 'h',
+	OptOnlyHexDump = 'H',
+	OptLongTimings = 'L',
+	OptNativeTimings = 'n',
+	OptOutputFormat = 'o',
+	OptPreferredTimings = 'p',
+	OptPhysicalAddress = 'P',
+	OptSkipHexDump = 's',
+	OptShortTimings = 'S',
+	OptV4L2Timings = 'V',
+	OptXModeLineTimings = 'X',
+	OptSkipSHA = 128,
+	OptHideSerialNumbers,
+	OptVersion,
+	OptSTD,
+	OptDMT,
+	OptVIC,
+	OptHDMIVIC,
+	OptCVT,
+	OptGTF,
+	OptListEstTimings,
+	OptListDMTs,
+	OptListVICs,
+	OptListHDMIVICs,
+	OptLast = 256
+};
+
+static char options[OptLast];
+
+static struct option long_options[] = {
+	{ "help", no_argument, 0, OptHelp },
+	{ "output-format", required_argument, 0, OptOutputFormat },
+	{ "native-timings", no_argument, 0, OptNativeTimings },
+	{ "preferred-timings", no_argument, 0, OptPreferredTimings },
+	{ "physical-address", no_argument, 0, OptPhysicalAddress },
+	{ "skip-hex-dump", no_argument, 0, OptSkipHexDump },
+	{ "only-hex-dump", no_argument, 0, OptOnlyHexDump },
+	{ "skip-sha", no_argument, 0, OptSkipSHA },
+	{ "hide-serial-numbers", no_argument, 0, OptHideSerialNumbers },
+	{ "version", no_argument, 0, OptVersion },
+	{ "check-inline", no_argument, 0, OptCheckInline },
+	{ "check", no_argument, 0, OptCheck },
+	{ "short-timings", no_argument, 0, OptShortTimings },
+	{ "long-timings", no_argument, 0, OptLongTimings },
+	{ "xmodeline", no_argument, 0, OptXModeLineTimings },
+	{ "fbmode", no_argument, 0, OptFBModeTimings },
+	{ "v4l2-timings", no_argument, 0, OptV4L2Timings },
+	{ "std", required_argument, 0, OptSTD },
+	{ "dmt", required_argument, 0, OptDMT },
+	{ "vic", required_argument, 0, OptVIC },
+	{ "hdmi-vic", required_argument, 0, OptHDMIVIC },
+	{ "cvt", required_argument, 0, OptCVT },
+	{ "gtf", required_argument, 0, OptGTF },
+	{ "list-established-timings", no_argument, 0, OptListEstTimings },
+	{ "list-dmts", no_argument, 0, OptListDMTs },
+	{ "list-vics", no_argument, 0, OptListVICs },
+	{ "list-hdmi-vics", no_argument, 0, OptListHDMIVICs },
+	{ 0, 0, 0, 0 }
+};
+
+static void usage(void)
+{
+	printf("Usage: edid-decode <options> [in [out]]\n"
+	       "  [in]                  EDID file to parse. Read from standard input if none given\n"
+	       "                        or if the input filename is '-'.\n"
+	       "  [out]                 Output the read EDID to this file. Write to standard output\n"
+	       "                        if the output filename is '-'.\n"
+	       "\nOptions:\n"
+	       "  -o, --output-format <fmt>\n"
+	       "                        If [out] is specified, then write the EDID in this format\n"
+	       "                        <fmt> is one of:\n"
+	       "                        hex:    hex numbers in ascii text (default for stdout)\n"
+	       "                        raw:    binary data (default unless writing to stdout)\n"
+	       "                        carray: c-program struct\n"
+	       "                        xml:    XML data\n"
+	       "  -c, --check           Check if the EDID conforms to the standards, failures and\n"
+	       "                        warnings are reported at the end.\n"
+	       "  -C, --check-inline    Check if the EDID conforms to the standards, failures and\n"
+	       "                        warnings are reported inline.\n"
+	       "  -n, --native-timings  Report the native timings.\n"
+	       "  -p, --preferred-timings Report the preferred timings.\n"
+	       "  -P, --physical-address Only report the CEC physical address.\n"
+	       "  -S, --short-timings   Report all video timings in a short format.\n"
+	       "  -L, --long-timings    Report all video timings in a long format.\n"
+	       "  -X, --xmodeline       Report all long video timings in Xorg.conf format.\n"
+	       "  -F, --fbmode          Report all long video timings in fb.modes format.\n"
+	       "  -V, --v4l2-timings    Report all long video timings in v4l2-dv-timings.h format.\n"
+	       "  -s, --skip-hex-dump   Skip the initial hex dump of the EDID.\n"
+	       "  -H, --only-hex-dump   Only output the hex dump of the EDID.\n"
+	       "  --skip-sha            Skip the SHA report.\n"
+	       "  --hide-serial-numbers Replace serial numbers with '...'\n"
+	       "  --version             show the edid-decode version (SHA)\n"
+	       "  --std <byte1>,<byte2> Show the standard timing represented by these two bytes.\n"
+	       "  --dmt <dmt>           Show the timings for the DMT with the given DMT ID.\n"
+	       "  --vic <vic>           Show the timings for this VIC.\n"
+	       "  --hdmi-vic <hdmivic>  Show the timings for this HDMI VIC.\n"
+	       "  --cvt w=<width>,h=<height>,fps=<fps>[,rb=<rb>][,interlaced][,overscan][,alt][,hblank=<hblank]\n"
+	       "                        Calculate the CVT timings for the given format.\n"
+	       "                        <fps> is frames per second for progressive timings,\n"
+	       "                        or fields per second for interlaced timings.\n"
+	       "                        <rb> can be 0 (no reduced blanking, default), or\n"
+	       "                        1-3 for the reduced blanking version.\n"
+	       "                        If 'interlaced' is given, then this is an interlaced format.\n"
+	       "                        If 'overscan' is given, then this is an overscanned format.\n"
+	       "                        If 'alt' is given and <rb>=2, then report the timings\n"
+	       "                        optimized for video: 1000 / 1001 * <fps>.\n"
+	       "                        If 'alt' is given and <rb>=3, then the horizontal blanking\n"
+	       "                        is 160 instead of 80 pixels.\n"
+	       "                        If 'hblank' is given and <rb>=3, then the horizontal blanking\n"
+	       "                        is <hblank> pixels (range of 80-200), overriding 'alt'.\n"
+	       "  --gtf w=<width>,h=<height>[,fps=<fps>][,horfreq=<horfreq>][,pixclk=<pixclk>][,interlaced]\n"
+	       "        [,overscan][,secondary][,C=<c>][,M=<m>][,K=<k>][,J=<j>]\n"
+	       "                        Calculate the GTF timings for the given format.\n"
+	       "                        <fps> is frames per second for progressive timings,\n"
+	       "                        or fields per second for interlaced timings.\n"
+	       "                        <horfreq> is the horizontal frequency in kHz.\n"
+	       "                        <pixclk> is the pixel clock frequency in MHz.\n"
+	       "                        Only one of fps, horfreq or pixclk must be given.\n"
+	       "                        If 'interlaced' is given, then this is an interlaced format.\n"
+	       "                        If 'overscan' is given, then this is an overscanned format.\n"
+	       "                        If 'secondary' is given, then the secondary GTF is used for\n"
+	       "                        reduced blanking, where <c>, <m>, <k> and <j> are parameters\n"
+	       "                        for the secondary curve.\n"
+	       "  --list-established-timings List all known Established Timings.\n"
+	       "  --list-dmts           List all known DMTs.\n"
+	       "  --list-vics           List all known VICs.\n"
+	       "  --list-hdmi-vics      List all known HDMI VICs.\n"
+	       "  -h, --help            Display this help message.\n");
+}
+
+static std::string s_msgs[EDID_MAX_BLOCKS + 1][2];
+
+void msg(bool is_warn, const char *fmt, ...)
+{
+	char buf[1024] = "";
+	va_list ap;
+
+	va_start(ap, fmt);
+	vsprintf(buf, fmt, ap);
+	va_end(ap);
+
+	if (is_warn)
+		state.warnings++;
+	else
+		state.failures++;
+	if (state.data_block.empty())
+		s_msgs[state.block_nr][is_warn] += std::string("  ") + buf;
+	else
+		s_msgs[state.block_nr][is_warn] += "  " + state.data_block + ": " + buf;
+
+	if (options[OptCheckInline])
+		printf("%s: %s", is_warn ? "WARN" : "FAIL", buf);
+}
+
+static void show_msgs(bool is_warn)
+{
+	printf("\n%s:\n\n", is_warn ? "Warnings" : "Failures");
+	for (unsigned i = 0; i < state.num_blocks; i++) {
+		if (s_msgs[i][is_warn].empty())
+			continue;
+		printf("Block %u, %s:\n%s",
+		       i, block_name(edid[i * EDID_PAGE_SIZE]).c_str(),
+		       s_msgs[i][is_warn].c_str());
+	}
+	if (s_msgs[EDID_MAX_BLOCKS][is_warn].empty())
+		return;
+	printf("EDID:\n%s",
+	       s_msgs[EDID_MAX_BLOCKS][is_warn].c_str());
+}
+
+
+void do_checksum(const char *prefix, const unsigned char *x, size_t len)
+{
+	unsigned char check = x[len - 1];
+	unsigned char sum = 0;
+	unsigned i;
+
+	printf("%sChecksum: 0x%02hhx", prefix, check);
+
+	for (i = 0; i < len-1; i++)
+		sum += x[i];
+
+	if ((unsigned char)(check + sum) != 0) {
+		printf(" (should be 0x%02x)\n", -sum & 0xff);
+		fail("Invalid checksum 0x%02x (should be 0x%02x).\n",
+		     check, -sum & 0xff);
+		return;
+	}
+	printf("\n");
+}
+
+static unsigned gcd(unsigned a, unsigned b)
+{
+	while (b) {
+		unsigned t = b;
+
+		b = a % b;
+		a = t;
+	}
+	return a;
+}
+
+void calc_ratio(struct timings *t)
+{
+	unsigned d = gcd(t->hact, t->vact);
+
+	if (d == 0) {
+		t->hratio = t->vratio = 0;
+		return;
+	}
+	t->hratio = t->hact / d;
+	t->vratio = t->vact / d;
+}
+
+std::string edid_state::dtd_type(unsigned cnt)
+{
+	unsigned len = std::to_string(cta.preparsed_total_dtds).length();
+	char buf[16];
+	sprintf(buf, "DTD %*u", len, cnt);
+	return buf;
+}
+
+bool edid_state::match_timings(const timings &t1, const timings &t2)
+{
+	if (t1.hact != t2.hact ||
+	    t1.vact != t2.vact ||
+	    t1.rb != t2.rb ||
+	    t1.interlaced != t2.interlaced ||
+	    t1.hfp != t2.hfp ||
+	    t1.hbp != t2.hbp ||
+	    t1.hsync != t2.hsync ||
+	    t1.pos_pol_hsync != t2.pos_pol_hsync ||
+	    t1.hratio != t2.hratio ||
+	    t1.vfp != t2.vfp ||
+	    t1.vbp != t2.vbp ||
+	    t1.vsync != t2.vsync ||
+	    t1.pos_pol_vsync != t2.pos_pol_vsync ||
+	    t1.vratio != t2.vratio ||
+	    t1.pixclk_khz != t2.pixclk_khz)
+		return false;
+	return true;
+}
+
+static void or_str(std::string &s, const std::string &flag, unsigned &num_flags)
+{
+	if (!num_flags)
+		s = flag;
+	else if (num_flags % 2 == 0)
+		s = s + " | \\\n\t\t" + flag;
+	else
+		s = s + " | " + flag;
+	num_flags++;
+}
+
+/*
+ * Return true if the timings are a close, but not identical,
+ * match. The only differences allowed are polarities and
+ * porches and syncs, provided the total blanking remains the
+ * same.
+ */
+bool timings_close_match(const timings &t1, const timings &t2)
+{
+	// We don't want to deal with borders, you're on your own
+	// if you are using those.
+	if (t1.hborder || t1.vborder ||
+	    t2.hborder || t2.vborder)
+		return false;
+	if (t1.hact != t2.hact || t1.vact != t2.vact ||
+	    t1.interlaced != t2.interlaced ||
+	    t1.pixclk_khz != t2.pixclk_khz ||
+	    t1.hfp + t1.hsync + t1.hbp != t2.hfp + t2.hsync + t2.hbp ||
+	    t1.vfp + t1.vsync + t1.vbp != t2.vfp + t2.vsync + t2.vbp)
+		return false;
+	if (t1.hfp == t2.hfp &&
+	    t1.hsync == t2.hsync &&
+	    t1.hbp == t2.hbp &&
+	    t1.pos_pol_hsync == t2.pos_pol_hsync &&
+	    t1.vfp == t2.vfp &&
+	    t1.vsync == t2.vsync &&
+	    t1.vbp == t2.vbp &&
+	    t1.pos_pol_vsync == t2.pos_pol_vsync)
+		return false;
+	return true;
+}
+
+static void print_modeline(unsigned indent, const struct timings *t, double refresh)
+{
+	unsigned offset = (!t->even_vtotal && t->interlaced) ? 1 : 0;
+	unsigned hfp = t->hborder + t->hfp;
+	unsigned hbp = t->hborder + t->hbp;
+	unsigned vfp = t->vborder + t->vfp;
+	unsigned vbp = t->vborder + t->vbp;
+
+	printf("%*sModeline \"%ux%u_%.2f%s\" %.3f  %u %u %u %u  %u %u %u %u  %cHSync",
+	       indent, "",
+	       t->hact, t->vact, refresh,
+	       t->interlaced ? "i" : "", t->pixclk_khz / 1000.0,
+	       t->hact, t->hact + hfp, t->hact + hfp + t->hsync,
+	       t->hact + hfp + t->hsync + hbp,
+	       t->vact, t->vact + vfp, t->vact + vfp + t->vsync,
+	       t->vact + vfp + t->vsync + vbp + offset,
+	       t->pos_pol_hsync ? '+' : '-');
+	if (!t->no_pol_vsync)
+		printf(" %cVSync", t->pos_pol_vsync ? '+' : '-');
+	if (t->interlaced)
+		printf(" Interlace");
+	printf("\n");
+}
+
+static void print_fbmode(unsigned indent, const struct timings *t,
+			 double refresh, double hor_freq_khz)
+{
+	printf("%*smode \"%ux%u-%u%s\"\n",
+	       indent, "",
+	       t->hact, t->vact,
+	       (unsigned)(0.5 + (t->interlaced ? refresh / 2.0 : refresh)),
+	       t->interlaced ? "-lace" : "");
+	printf("%*s# D: %.2f MHz, H: %.3f kHz, V: %.2f Hz\n",
+	       indent + 8, "",
+	       t->pixclk_khz / 1000.0, hor_freq_khz, refresh);
+	printf("%*sgeometry %u %u %u %u 32\n",
+	       indent + 8, "",
+	       t->hact, t->vact, t->hact, t->vact);
+	unsigned mult = t->interlaced ? 2 : 1;
+	unsigned offset = !t->even_vtotal && t->interlaced;
+	unsigned hfp = t->hborder + t->hfp;
+	unsigned hbp = t->hborder + t->hbp;
+	unsigned vfp = t->vborder + t->vfp;
+	unsigned vbp = t->vborder + t->vbp;
+	printf("%*stimings %llu %d %d %d %u %u %u\n",
+	       indent + 8, "",
+	       (unsigned long long)(1000000000.0 / (double)(t->pixclk_khz) + 0.5),
+	       hbp, hfp, mult * vbp, mult * vfp + offset, t->hsync, mult * t->vsync);
+	if (t->interlaced)
+		printf("%*slaced true\n", indent + 8, "");
+	if (t->pos_pol_hsync)
+		printf("%*shsync high\n", indent + 8, "");
+	if (t->pos_pol_vsync)
+		printf("%*svsync high\n", indent + 8, "");
+	printf("%*sendmode\n", indent, "");
+}
+
+static void print_v4l2_timing(const struct timings *t,
+			      double refresh, const char *type)
+{
+	printf("\t#define V4L2_DV_BT_%uX%u%c%u_%02u { \\\n",
+	       t->hact, t->vact, t->interlaced ? 'I' : 'P',
+	       (unsigned)refresh, (unsigned)(0.5 + 100.0 * (refresh - (unsigned)refresh)));
+	printf("\t\t.type = V4L2_DV_BT_656_1120, \\\n");
+	printf("\t\tV4L2_INIT_BT_TIMINGS(%u, %u, %u, ",
+	       t->hact, t->vact, t->interlaced);
+	if (!t->pos_pol_hsync && !t->pos_pol_vsync)
+		printf("0, \\\n");
+	else if (t->pos_pol_hsync && t->pos_pol_vsync)
+		printf("\\\n\t\t\tV4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \\\n");
+	else if (t->pos_pol_hsync)
+		printf("V4L2_DV_HSYNC_POS_POL, \\\n");
+	else
+		printf("V4L2_DV_VSYNC_POS_POL, \\\n");
+	unsigned hfp = t->hborder + t->hfp;
+	unsigned hbp = t->hborder + t->hbp;
+	unsigned vfp = t->vborder + t->vfp;
+	unsigned vbp = t->vborder + t->vbp;
+	printf("\t\t\t%lluULL, %d, %u, %d, %u, %u, %d, %u, %u, %d, \\\n",
+	       t->pixclk_khz * 1000ULL, hfp, t->hsync, hbp,
+	       vfp, t->vsync, vbp,
+	       t->interlaced ? vfp : 0,
+	       t->interlaced ? t->vsync : 0,
+	       t->interlaced ? vbp + !t->even_vtotal : 0);
+
+	std::string flags;
+	unsigned num_flags = 0;
+	unsigned vic = 0;
+	unsigned hdmi_vic = 0;
+	const char *std = "0";
+
+	if (t->interlaced && !t->even_vtotal)
+		or_str(flags, "V4L2_DV_FL_HALF_LINE", num_flags);
+	if (!memcmp(type, "VIC", 3)) {
+		or_str(flags, "V4L2_DV_FL_HAS_CEA861_VIC", num_flags);
+		or_str(flags, "V4L2_DV_FL_IS_CE_VIDEO", num_flags);
+		vic = strtoul(type + 4, 0, 0);
+	}
+	if (!memcmp(type, "HDMI VIC", 8)) {
+		or_str(flags, "V4L2_DV_FL_HAS_HDMI_VIC", num_flags);
+		or_str(flags, "V4L2_DV_FL_IS_CE_VIDEO", num_flags);
+		hdmi_vic = strtoul(type + 9, 0, 0);
+		vic = hdmi_vic_to_vic(hdmi_vic);
+		if (vic)
+			or_str(flags, "V4L2_DV_FL_HAS_CEA861_VIC", num_flags);
+	}
+	if (vic && (fmod(refresh, 6)) == 0.0)
+		or_str(flags, "V4L2_DV_FL_CAN_REDUCE_FPS", num_flags);
+	if (t->rb)
+		or_str(flags, "V4L2_DV_FL_REDUCED_BLANKING", num_flags);
+	if (t->hratio && t->vratio)
+		or_str(flags, "V4L2_DV_FL_HAS_PICTURE_ASPECT", num_flags);
+
+	if (!memcmp(type, "VIC", 3) || !memcmp(type, "HDMI VIC", 8))
+		std = "V4L2_DV_BT_STD_CEA861";
+	else if (!memcmp(type, "DMT", 3))
+		std = "V4L2_DV_BT_STD_DMT";
+	else if (!memcmp(type, "CVT", 3))
+		std = "V4L2_DV_BT_STD_CVT";
+	else if (!memcmp(type, "GTF", 3))
+		std = "V4L2_DV_BT_STD_GTF";
+	printf("\t\t\t%s, \\\n", std);
+	printf("\t\t\t%s, \\\n", flags.empty() ? "0" : flags.c_str());
+	printf("\t\t\t{ %u, %u }, %u, %u) \\\n",
+	       t->hratio, t->vratio, vic, hdmi_vic);
+	printf("\t}\n");
+}
+
+static void print_detailed_timing(unsigned indent, const struct timings *t)
+{
+	printf("%*sHfront %4d Hsync %3u Hback %3d Hpol %s",
+	       indent, "",
+	       t->hfp, t->hsync, t->hbp, t->pos_pol_hsync ? "P" : "N");
+	if (t->hborder)
+		printf(" Hborder %u", t->hborder);
+	printf("\n");
+
+	printf("%*sVfront %4u Vsync %3u Vback %3d",
+	       indent, "", t->vfp, t->vsync, t->vbp);
+	if (!t->no_pol_vsync)
+		printf(" Vpol %s", t->pos_pol_vsync ? "P" : "N");
+	if (t->vborder)
+		printf(" Vborder %u", t->vborder);
+	if (t->even_vtotal) {
+		printf(" Both Fields");
+	} else if (t->interlaced) {
+		printf(" Vfront +0.5 Odd Field\n");
+		printf("%*sVfront %4d Vsync %3u Vback %3d",
+		       indent, "", t->vfp, t->vsync, t->vbp);
+		if (!t->no_pol_vsync)
+			printf(" Vpol %s", t->pos_pol_vsync ? "P" : "N");
+		if (t->vborder)
+			printf(" Vborder %u", t->vborder);
+		printf(" Vback  +0.5 Even Field");
+	}
+	printf("\n");
+}
+
+bool edid_state::print_timings(const char *prefix, const struct timings *t,
+			       const char *type, const char *flags,
+			       bool detailed, bool do_checks)
+{
+	if (!t) {
+		// Should not happen
+		if (do_checks)
+			fail("Unknown video timings.\n");
+		return false;
+	}
+
+	if (detailed && options[OptShortTimings])
+		detailed = false;
+	if (options[OptLongTimings])
+		detailed = true;
+
+	unsigned vact = t->vact;
+	unsigned hbl = t->hfp + t->hsync + t->hbp + 2 * t->hborder;
+	unsigned vbl = t->vfp + t->vsync + t->vbp + 2 * t->vborder;
+	unsigned htotal = t->hact + hbl;
+	double hor_freq_khz = htotal ? (double)t->pixclk_khz / htotal : 0;
+
+	if (t->interlaced)
+		vact /= 2;
+
+	if (t->ycbcr420)
+		hor_freq_khz /= 2;
+
+	double vtotal = vact + vbl;
+
+	bool ok = true;
+
+	if (!t->hact || !hbl || !t->hfp || !t->hsync ||
+	    !vact || !vbl || (!t->vfp && !t->interlaced && !t->even_vtotal) || !t->vsync) {
+		if (do_checks)
+			fail("0 values in the video timing:\n"
+			     "    Horizontal Active/Blanking %u/%u\n"
+			     "    Horizontal Frontporch/Sync Width %u/%u\n"
+			     "    Vertical Active/Blanking %u/%u\n"
+			     "    Vertical Frontporch/Sync Width %u/%u\n",
+			     t->hact, hbl, t->hfp, t->hsync, vact, vbl, t->vfp, t->vsync);
+		ok = false;
+	}
+
+	if (t->even_vtotal)
+		vtotal = vact + t->vfp + t->vsync + t->vbp;
+	else if (t->interlaced)
+		vtotal = vact + t->vfp + t->vsync + t->vbp + 0.5;
+
+	double refresh = (double)t->pixclk_khz * 1000.0 / (htotal * vtotal);
+
+	std::string s;
+	unsigned rb = t->rb & ~RB_ALT;
+	if (rb) {
+		bool alt = t->rb & RB_ALT;
+		s = "RB";
+		if (rb == RB_CVT_V2)
+			s += std::string("v2") + (alt ? ",video-optimized" : "");
+		else if (rb == RB_CVT_V3)
+			s += std::string("v3") + (alt ? ",h-blank-160" : "");
+	}
+	add_str(s, flags);
+	if (t->hsize_mm || t->vsize_mm)
+		add_str(s, std::to_string(t->hsize_mm) + " mm x " + std::to_string(t->vsize_mm) + " mm");
+	if (t->hsize_mm > dtd_max_hsize_mm)
+		dtd_max_hsize_mm = t->hsize_mm;
+	if (t->vsize_mm > dtd_max_vsize_mm)
+		dtd_max_vsize_mm = t->vsize_mm;
+	if (!s.empty())
+		s = " (" + s + ")";
+	unsigned pixclk_khz = t->pixclk_khz / (t->ycbcr420 ? 2 : 1);
+
+	char buf[10];
+
+	sprintf(buf, "%u%s", t->vact, t->interlaced ? "i" : "");
+	printf("%s%s: %5ux%-5s %7.3f Hz %3u:%-3u %7.3f kHz %8.3f MHz%s\n",
+	       prefix, type,
+	       t->hact, buf,
+	       refresh,
+	       t->hratio, t->vratio,
+	       hor_freq_khz,
+	       pixclk_khz / 1000.0,
+	       s.c_str());
+
+	unsigned len = strlen(prefix) + 2;
+
+	if (!t->ycbcr420 && detailed && options[OptXModeLineTimings])
+		print_modeline(len, t, refresh);
+	else if (!t->ycbcr420 && detailed && options[OptFBModeTimings])
+		print_fbmode(len, t, refresh, hor_freq_khz);
+	else if (!t->ycbcr420 && detailed && options[OptV4L2Timings])
+		print_v4l2_timing(t, refresh, type);
+	else if (detailed)
+		print_detailed_timing(len + strlen(type) + 6, t);
+
+	if (!do_checks)
+		return ok;
+
+	if (!memcmp(type, "DTD", 3)) {
+		unsigned vic, dmt;
+		const timings *vic_t = cta_close_match_to_vic(*t, vic);
+
+		if (vic_t)
+			warn("DTD is similar but not identical to VIC %u.\n", vic);
+
+		const timings *dmt_t = close_match_to_dmt(*t, dmt);
+		if (!vic_t && dmt_t)
+			warn("DTD is similar but not identical to DMT 0x%02x.\n", dmt);
+	}
+
+	if (refresh) {
+		min_vert_freq_hz = min(min_vert_freq_hz, refresh);
+		max_vert_freq_hz = max(max_vert_freq_hz, refresh);
+	}
+	if (hor_freq_khz) {
+		min_hor_freq_hz = min(min_hor_freq_hz, hor_freq_khz * 1000.0);
+		max_hor_freq_hz = max(max_hor_freq_hz, hor_freq_khz * 1000.0);
+		max_pixclk_khz = max(max_pixclk_khz, pixclk_khz);
+		if (t->pos_pol_hsync && !t->pos_pol_vsync && t->vsync == 3)
+			base.max_pos_neg_hor_freq_khz = hor_freq_khz;
+	}
+
+	if (t->ycbcr420 && t->pixclk_khz < 590000)
+		warn_once("Some YCbCr 4:2:0 timings are invalid for HDMI (which requires an RGB timings pixel rate >= 590 MHz).\n");
+	if (t->hfp <= 0)
+		fail("0 or negative horizontal front porch.\n");
+	if (t->hbp <= 0)
+		fail("0 or negative horizontal back porch.\n");
+	if (t->vbp <= 0)
+		fail("0 or negative vertical back porch.\n");
+	if (!base.max_display_width_mm && !base.max_display_height_mm) {
+		/* this is valid */
+	} else if (!t->hsize_mm && !t->vsize_mm) {
+		/* this is valid */
+	} else if (t->hsize_mm > base.max_display_width_mm + 9 ||
+		   t->vsize_mm > base.max_display_height_mm + 9) {
+		fail("Mismatch of image size %ux%u mm vs display size %ux%u mm.\n",
+		     t->hsize_mm, t->vsize_mm, base.max_display_width_mm, base.max_display_height_mm);
+	} else if (t->hsize_mm < base.max_display_width_mm - 9 &&
+		   t->vsize_mm < base.max_display_height_mm - 9) {
+		fail("Mismatch of image size %ux%u mm vs display size %ux%u mm.\n",
+		     t->hsize_mm, t->vsize_mm, base.max_display_width_mm, base.max_display_height_mm);
+	}
+	return ok;
+}
+
+std::string containerid2s(const unsigned char *x)
+{
+	char buf[40];
+
+	sprintf(buf, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+		x[0], x[1], x[2], x[3],
+		x[4], x[5],
+		x[6], x[7],
+		x[8], x[9],
+		x[10], x[11], x[12], x[13], x[14], x[15]);
+	return buf;
+}
+
+std::string utohex(unsigned char x)
+{
+	char buf[10];
+
+	sprintf(buf, "0x%02hhx", x);
+	return buf;
+}
+
+const char *oui_name(unsigned oui, bool reverse)
+{
+	if (reverse)
+		oui = (oui >> 16) | (oui & 0xff00) | ((oui & 0xff) << 16);
+
+	switch (oui) {
+	case 0x00001a: return "AMD";
+	case 0x000c03: return "HDMI";
+	case 0x00044b: return "NVIDIA";
+	case 0x000c6e: return "ASUS";
+	case 0x0010fa: return "Apple";
+	case 0x0014b9: return "MSTAR";
+	case 0x00d046: return "Dolby";
+	case 0x00e047: return "InFocus";
+	case 0x3a0292: return "VESA";
+	case 0x90848b: return "HDR10+";
+	case 0xc45dd8: return "HDMI Forum";
+	case 0xca125c: return "Microsoft";
+	default: return NULL;
+	}
+}
+
+std::string ouitohex(unsigned oui)
+{
+	char buf[32];
+
+	sprintf(buf, "%02X-%02X-%02X", (oui >> 16) & 0xff, (oui >> 8) & 0xff, oui & 0xff);
+	return buf;
+}
+
+bool memchk(const unsigned char *x, unsigned len, unsigned char v)
+{
+	for (unsigned i = 0; i < len; i++)
+		if (x[i] != v)
+			return false;
+	return true;
+}
+
+void hex_block(const char *prefix, const unsigned char *x,
+	       unsigned length, bool show_ascii, unsigned step)
+{
+	unsigned i, j;
+
+	if (!length)
+		return;
+
+	for (i = 0; i < length; i += step) {
+		unsigned len = min(step, length - i);
+
+		printf("%s", prefix);
+		for (j = 0; j < len; j++)
+			printf("%s%02x", j ? " " : "", x[i + j]);
+
+		if (show_ascii) {
+			for (j = len; j < step; j++)
+				printf("   ");
+			printf(" '");
+			for (j = 0; j < len; j++)
+				printf("%c", x[i + j] >= ' ' && x[i + j] <= '~' ? x[i + j] : '.');
+			printf("'");
+		}
+		printf("\n");
+	}
+}
+
+static bool edid_add_byte(const char *s, bool two_digits = true)
+{
+	char buf[3];
+
+	if (state.edid_size == sizeof(edid))
+		return false;
+	buf[0] = s[0];
+	buf[1] = two_digits ? s[1] : 0;
+	buf[2] = 0;
+	edid[state.edid_size++] = strtoul(buf, NULL, 16);
+	return true;
+}
+
+static bool extract_edid_quantumdata(const char *start)
+{
+	/* Parse QuantumData 980 EDID files */
+	do {
+		start = strstr(start, ">");
+		if (!start)
+			return false;
+		start++;
+		for (unsigned i = 0; start[i] && start[i + 1] && i < 256; i += 2)
+			if (!edid_add_byte(start + i))
+				return false;
+		start = strstr(start, "<BLOCK");
+	} while (start);
+	return state.edid_size;
+}
+
+static const char *ignore_chars = ",:;";
+
+static bool extract_edid_hex(const char *s, bool require_two_digits = true)
+{
+	for (; *s; s++) {
+		if (isspace(*s) || strchr(ignore_chars, *s))
+			continue;
+
+		if (*s == '0' && tolower(s[1]) == 'x') {
+			s++;
+			continue;
+		}
+
+		/* Read one or two hex digits from the log */
+		if (!isxdigit(s[0])) {
+			if (state.edid_size && state.edid_size % 128 == 0)
+				break;
+			return false;
+		}
+		if (require_two_digits && !isxdigit(s[1])) {
+			odd_hex_digits = true;
+			return false;
+		}
+		if (!edid_add_byte(s, isxdigit(s[1])))
+			return false;
+		if (isxdigit(s[1]))
+			s++;
+	}
+	return state.edid_size;
+}
+
+static bool extract_edid_xrandr(const char *start)
+{
+	static const char indentation1[] = "                ";
+	static const char indentation2[] = "\t\t";
+	/* Used to detect that we've gone past the EDID property */
+	static const char half_indentation1[] = "        ";
+	static const char half_indentation2[] = "\t";
+	const char *indentation;
+	const char *s;
+
+	for (;;) {
+		unsigned j;
+
+		/* Get the next start of the line of EDID hex, assuming spaces for indentation */
+		s = strstr(start, indentation = indentation1);
+		/* Did we skip the start of another property? */
+		if (s && s > strstr(start, half_indentation1))
+			break;
+
+		/* If we failed, retry assuming tabs for indentation */
+		if (!s) {
+			s = strstr(start, indentation = indentation2);
+			/* Did we skip the start of another property? */
+			if (s && s > strstr(start, half_indentation2))
+				break;
+		}
+
+		if (!s)
+			break;
+
+		start = s + strlen(indentation);
+
+		for (j = 0; j < 16; j++, start += 2) {
+			/* Read a %02x from the log */
+			if (!isxdigit(start[0]) || !isxdigit(start[1])) {
+				if (j)
+					break;
+				return false;
+			}
+			if (!edid_add_byte(start))
+				return false;
+		}
+	}
+	return state.edid_size;
+}
+
+static bool extract_edid_xorg(const char *start)
+{
+	bool find_first_num = true;
+
+	for (; *start; start++) {
+		if (find_first_num) {
+			const char *s;
+
+			/* skip ahead to the : */
+			s = strstr(start, ": \t");
+			if (!s)
+				s = strstr(start, ":     ");
+			if (!s)
+				break;
+			start = s;
+			/* and find the first number */
+			while (!isxdigit(start[1]))
+				start++;
+			find_first_num = false;
+			continue;
+		} else {
+			/* Read a %02x from the log */
+			if (!isxdigit(*start)) {
+				find_first_num = true;
+				continue;
+			}
+			if (!edid_add_byte(start))
+				return false;
+			start++;
+		}
+	}
+	return state.edid_size;
+}
+
+static bool extract_edid(int fd, FILE *error)
+{
+	std::vector<char> edid_data;
+	char buf[EDID_PAGE_SIZE];
+
+	for (;;) {
+		ssize_t i = read(fd, buf, sizeof(buf));
+
+		if (i < 0)
+			return false;
+		if (i == 0)
+			break;
+		edid_data.insert(edid_data.end(), buf, buf + i);
+	}
+
+	if (edid_data.empty()) {
+		state.edid_size = 0;
+		return false;
+	}
+
+	const char *data = &edid_data[0];
+	const char *start;
+
+	/* Look for edid-decode output */
+	start = strstr(data, "EDID (hex):");
+	if (!start)
+		start = strstr(data, "edid-decode (hex):");
+	if (start)
+		return extract_edid_hex(strchr(start, ':'));
+
+	/* Look for C-array */
+	start = strstr(data, "unsigned char edid[] = {");
+	if (start)
+		return extract_edid_hex(strchr(start, '{') + 1, false);
+
+	/* Look for QuantumData EDID output */
+	start = strstr(data, "<BLOCK");
+	if (start)
+		return extract_edid_quantumdata(start);
+
+	/* Look for xrandr --verbose output (lines of 16 hex bytes) */
+	start = strstr(data, "EDID_DATA:");
+	if (!start)
+		start = strstr(data, "EDID:");
+	if (start)
+		return extract_edid_xrandr(start);
+
+	/* Look for an EDID in an Xorg.0.log file */
+	start = strstr(data, "EDID (in hex):");
+	if (start)
+		start = strstr(start, "(II)");
+	if (start)
+		return extract_edid_xorg(start);
+
+	unsigned i;
+
+	/* Is the EDID provided in hex? */
+	for (i = 0; i < 32 && (isspace(data[i]) || strchr(ignore_chars, data[i]) ||
+			       tolower(data[i]) == 'x' || isxdigit(data[i])); i++);
+
+	if (i == 32)
+		return extract_edid_hex(data);
+
+	/* Assume binary */
+	if (edid_data.size() > sizeof(edid)) {
+		fprintf(error, "Binary EDID length %zu is greater than %zu.\n",
+			edid_data.size(), sizeof(edid));
+		return false;
+	}
+	memcpy(edid, data, edid_data.size());
+	state.edid_size = edid_data.size();
+	return true;
+}
+
+static unsigned char crc_calc(const unsigned char *b)
+{
+	unsigned char sum = 0;
+	unsigned i;
+
+	for (i = 0; i < 127; i++)
+		sum += b[i];
+	return 256 - sum;
+}
+
+static int crc_ok(const unsigned char *b)
+{
+	return crc_calc(b) == b[127];
+}
+
+static void hexdumpedid(FILE *f, const unsigned char *edid, unsigned size)
+{
+	unsigned b, i, j;
+
+	for (b = 0; b < size / 128; b++) {
+		const unsigned char *buf = edid + 128 * b;
+
+		if (b)
+			fprintf(f, "\n");
+		for (i = 0; i < 128; i += 0x10) {
+			fprintf(f, "%02x", buf[i]);
+			for (j = 1; j < 0x10; j++) {
+				fprintf(f, " %02x", buf[i + j]);
+			}
+			fprintf(f, "\n");
+		}
+		if (!crc_ok(buf))
+			fprintf(f, "Block %u has a checksum error (should be 0x%02x).\n",
+				b, crc_calc(buf));
+	}
+}
+
+static void carraydumpedid(FILE *f, const unsigned char *edid, unsigned size)
+{
+	unsigned b, i, j;
+
+	fprintf(f, "const unsigned char edid[] = {\n");
+	for (b = 0; b < size / 128; b++) {
+		const unsigned char *buf = edid + 128 * b;
+
+		if (b)
+			fprintf(f, "\n");
+		for (i = 0; i < 128; i += 8) {
+			fprintf(f, "\t0x%02x,", buf[i]);
+			for (j = 1; j < 8; j++) {
+				fprintf(f, " 0x%02x,", buf[i + j]);
+			}
+			fprintf(f, "\n");
+		}
+		if (!crc_ok(buf))
+			fprintf(f, "\t/* Block %u has a checksum error (should be 0x%02x). */\n",
+				b, crc_calc(buf));
+	}
+	fprintf(f, "};\n");
+}
+
+// This format can be read by the QuantumData EDID editor
+static void xmldumpedid(FILE *f, const unsigned char *edid, unsigned size)
+{
+	fprintf(f, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
+	fprintf(f, "<DATAOBJ>\n");
+	fprintf(f, "    <HEADER TYPE=\"DID\" VERSION=\"1.0\"/>\n");
+	fprintf(f, "    <DATA>\n");
+	for (unsigned b = 0; b < size / 128; b++) {
+		const unsigned char *buf = edid + 128 * b;
+
+		fprintf(f, "        <BLOCK%u>", b);
+		for (unsigned i = 0; i < 128; i++)
+			fprintf(f, "%02X", buf[i]);
+		fprintf(f, "</BLOCK%u>\n", b);
+	}
+	fprintf(f, "    </DATA>\n");
+	fprintf(f, "</DATAOBJ>\n");
+}
+
+
+static int edid_to_file(const char *to_file, enum output_format out_fmt)
+{
+	FILE *out;
+
+	if (!strcmp(to_file, "-")) {
+		to_file = "stdout";
+		out = stdout;
+	} else if ((out = fopen(to_file, "w")) == NULL) {
+		perror(to_file);
+		return -1;
+	}
+	if (out_fmt == OUT_FMT_DEFAULT)
+		out_fmt = out == stdout ? OUT_FMT_HEX : OUT_FMT_RAW;
+
+	switch (out_fmt) {
+	default:
+	case OUT_FMT_HEX:
+		hexdumpedid(out, edid, state.edid_size);
+		break;
+	case OUT_FMT_RAW:
+		fwrite(edid, state.edid_size, 1, out);
+		break;
+	case OUT_FMT_CARRAY:
+		carraydumpedid(out, edid, state.edid_size);
+		break;
+	case OUT_FMT_XML:
+		xmldumpedid(out, edid, state.edid_size);
+		break;
+	}
+
+	if (out != stdout)
+		fclose(out);
+	return 0;
+}
+
+static int edid_from_file(const char *from_file, FILE *error)
+{
+#ifdef O_BINARY
+	// Windows compatibility
+	int flags = O_RDONLY | O_BINARY;
+#else
+	int flags = O_RDONLY;
+#endif
+	int fd;
+
+	if (!strcmp(from_file, "-")) {
+		from_file = "stdin";
+		fd = 0;
+	} else if ((fd = open(from_file, flags)) == -1) {
+		perror(from_file);
+		return -1;
+	}
+
+	odd_hex_digits = false;
+	if (!extract_edid(fd, error)) {
+		if (!state.edid_size) {
+			fprintf(error, "EDID of '%s' was empty.\n", from_file);
+			return -1;
+		}
+		fprintf(error, "EDID extract of '%s' failed: ", from_file);
+		if (odd_hex_digits)
+			fprintf(error, "odd number of hexadecimal digits.\n");
+		else
+			fprintf(error, "unknown format.\n");
+		return -1;
+	}
+	if (state.edid_size % EDID_PAGE_SIZE) {
+		fprintf(error, "EDID length %u is not a multiple of %u.\n",
+			state.edid_size, EDID_PAGE_SIZE);
+		return -1;
+	}
+	state.num_blocks = state.edid_size / EDID_PAGE_SIZE;
+	if (fd != 0)
+		close(fd);
+
+	if (memcmp(edid, "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00", 8)) {
+		fprintf(error, "No EDID header found in '%s'.\n", from_file);
+		return -1;
+	}
+	return 0;
+}
+
+/* generic extension code */
+
+std::string block_name(unsigned char block)
+{
+	char buf[10];
+
+	switch (block) {
+	case 0x00: return "Base EDID";
+	case 0x02: return "CTA-861 Extension Block";
+	case 0x10: return "Video Timing Extension Block";
+	case 0x20: return "EDID 2.0 Extension Block";
+	case 0x40: return "Display Information Extension Block";
+	case 0x50: return "Localized String Extension Block";
+	case 0x60: return "Microdisplay Interface Extension Block";
+	case 0x70: return "DisplayID Extension Block";
+	case 0xf0: return "Block Map Extension Block";
+	case 0xff: return "Manufacturer-Specific Extension Block";
+	default:
+		sprintf(buf, " 0x%02x", block);
+		return std::string("Unknown EDID Extension Block") + buf;
+	}
+}
+
+void edid_state::parse_block_map(const unsigned char *x)
+{
+	unsigned last_valid_block_tag = 0;
+	bool fail_once = false;
+	unsigned offset = 1;
+	unsigned i;
+
+	if (block_nr == 1)
+		block_map.saw_block_1 = true;
+	else if (!block_map.saw_block_1)
+		fail("No EDID Block Map Extension found in block 1.\n");
+	else if (block_nr == 128)
+		block_map.saw_block_128 = true;
+
+	if (block_nr > 1)
+		offset = 128;
+
+	for (i = 1; i < 127; i++) {
+		unsigned block = offset + i;
+
+		if (x[i]) {
+			last_valid_block_tag++;
+			if (i != last_valid_block_tag && !fail_once) {
+				fail("Valid block tags are not consecutive.\n");
+				fail_once = true;
+			}
+			printf("  Block %3u: %s\n", block, block_name(x[i]).c_str());
+			if (block >= num_blocks) {
+				if (!fail_once)
+					fail("Invalid block number %u.\n", block);
+				fail_once = true;
+			} else if (x[i] != edid[block * EDID_PAGE_SIZE]) {
+				fail("Block %u tag mismatch: expected 0x%02x, but got 0x%02x.\n",
+				     block, edid[block * EDID_PAGE_SIZE], x[i]);
+			}
+		} else if (block < num_blocks) {
+			fail("Block %u tag mismatch: expected 0x%02x, but got 0x00.\n",
+			     block, edid[block * EDID_PAGE_SIZE]);
+		}
+	}
+}
+
+void edid_state::preparse_extension(const unsigned char *x)
+{
+	switch (x[0]) {
+	case 0x02:
+		has_cta = true;
+		preparse_cta_block(x);
+		break;
+	case 0x70:
+		has_dispid = true;
+		preparse_displayid_block(x);
+		break;
+	}
+}
+
+void edid_state::parse_extension(const unsigned char *x)
+{
+	block = block_name(x[0]);
+	data_block.clear();
+
+	printf("\n");
+	if (block_nr && x[0] == 0)
+		block = "Unknown EDID Extension Block 0x00";
+	printf("Block %u, %s:\n", block_nr, block.c_str());
+
+	switch (x[0]) {
+	case 0x02:
+		parse_cta_block(x);
+		break;
+	case 0x10:
+		parse_vtb_ext_block(x);
+		break;
+	case 0x20:
+		fail("Deprecated extension block for EDID 2.0, do not use.\n");
+		break;
+	case 0x40:
+		parse_di_ext_block(x);
+		break;
+	case 0x50:
+		parse_ls_ext_block(x);
+		break;
+	case 0x70:
+		parse_displayid_block(x);
+		break;
+	case 0xf0:
+		parse_block_map(x);
+		if (block_nr != 1 && block_nr != 128)
+			fail("Must be used in block 1 and 128.\n");
+		break;
+	default:
+		hex_block("  ", x, EDID_PAGE_SIZE);
+		fail("Unknown Extension Block.\n");
+		break;
+	}
+
+	data_block.clear();
+	do_checksum("", x, EDID_PAGE_SIZE);
+}
+
+int edid_state::parse_edid()
+{
+	hide_serial_numbers = options[OptHideSerialNumbers];
+
+	for (unsigned i = 1; i < num_blocks; i++)
+		preparse_extension(edid + i * EDID_PAGE_SIZE);
+
+	if (options[OptPhysicalAddress]) {
+		printf("%x.%x.%x.%x\n",
+		       (cta.preparsed_phys_addr >> 12) & 0xf,
+		       (cta.preparsed_phys_addr >> 8) & 0xf,
+		       (cta.preparsed_phys_addr >> 4) & 0xf,
+		       cta.preparsed_phys_addr & 0xf);
+		return 0;
+	}
+
+	if (!options[OptSkipHexDump]) {
+		printf("edid-decode (hex):\n\n");
+		for (unsigned i = 0; i < num_blocks; i++) {
+			hex_block("", edid + i * EDID_PAGE_SIZE, EDID_PAGE_SIZE, false);
+			if (i == num_blocks - 1 && options[OptOnlyHexDump])
+				return 0;
+			printf("\n");
+		}
+		printf("----------------\n\n");
+	}
+
+	block = block_name(0x00);
+	printf("Block %u, %s:\n", block_nr, block.c_str());
+	parse_base_block(edid);
+
+	for (unsigned i = 1; i < num_blocks; i++) {
+		block_nr++;
+		printf("\n----------------\n");
+		parse_extension(edid + i * EDID_PAGE_SIZE);
+	}
+
+	block = "";
+	block_nr = EDID_MAX_BLOCKS;
+
+	if (has_cta)
+		cta_resolve_svrs();
+
+	if (options[OptPreferredTimings] && base.preferred_timing.is_valid()) {
+		printf("\n----------------\n");
+		printf("\nPreferred Video Timing if only Block 0 is parsed:\n");
+		print_timings("  ", base.preferred_timing, true, false);
+	}
+
+	if (options[OptNativeTimings] &&
+	    base.preferred_timing.is_valid() && base.preferred_is_also_native) {
+		printf("\n----------------\n");
+		printf("\nNative Video Timing if only Block 0 is parsed:\n");
+		print_timings("  ", base.preferred_timing, true, false);
+	}
+
+	if (options[OptPreferredTimings] && !cta.preferred_timings.empty()) {
+		printf("\n----------------\n");
+		printf("\nPreferred Video Timing%s if Block 0 and CTA-861 Blocks are parsed:\n",
+		       cta.preferred_timings.size() > 1 ? "s" : "");
+		for (vec_timings_ext::iterator iter = cta.preferred_timings.begin();
+		     iter != cta.preferred_timings.end(); ++iter)
+			print_timings("  ", *iter, true, false);
+	}
+
+	if (options[OptNativeTimings] && !cta.native_timings.empty()) {
+		printf("\n----------------\n");
+		printf("\nNative Video Timing%s if Block 0 and CTA-861 Blocks are parsed:\n",
+		       cta.native_timings.size() > 1 ? "s" : "");
+		for (vec_timings_ext::iterator iter = cta.native_timings.begin();
+		     iter != cta.native_timings.end(); ++iter)
+			print_timings("  ", *iter, true, false);
+	}
+
+	if (options[OptPreferredTimings] && !dispid.preferred_timings.empty()) {
+		printf("\n----------------\n");
+		printf("\nPreferred Video Timing%s if Block 0 and DisplayID Blocks are parsed:\n",
+		       dispid.preferred_timings.size() > 1 ? "s" : "");
+		for (vec_timings_ext::iterator iter = dispid.preferred_timings.begin();
+		     iter != dispid.preferred_timings.end(); ++iter)
+			print_timings("  ", *iter, true, false);
+	}
+
+	if (!options[OptCheck] && !options[OptCheckInline])
+		return 0;
+
+	check_base_block();
+	if (has_cta)
+		check_cta_blocks();
+	if (has_dispid)
+		check_displayid_blocks();
+
+	printf("\n----------------\n");
+
+	if (!options[OptSkipSHA] && strlen(STRING(SHA))) {
+		printf("\nedid-decode SHA: %s %s\n", STRING(SHA), STRING(DATE));
+	}
+
+	if (options[OptCheck]) {
+		if (warnings)
+			show_msgs(true);
+		if (failures)
+			show_msgs(false);
+	}
+	printf("\nEDID conformity: %s\n", failures ? "FAIL" : "PASS");
+	return failures ? -2 : 0;
+}
+
+enum cvt_opts {
+	CVT_WIDTH = 0,
+	CVT_HEIGHT,
+	CVT_FPS,
+	CVT_INTERLACED,
+	CVT_OVERSCAN,
+	CVT_RB,
+	CVT_ALT,
+	CVT_RB_H_BLANK,
+};
+
+static int parse_cvt_subopt(char **subopt_str, double *value)
+{
+	int opt;
+	char *opt_str;
+
+	static const char * const subopt_list[] = {
+		"w",
+		"h",
+		"fps",
+		"interlaced",
+		"overscan",
+		"rb",
+		"alt",
+		"hblank",
+		nullptr
+	};
+
+	opt = getsubopt(subopt_str, (char* const*) subopt_list, &opt_str);
+
+	if (opt == -1) {
+		fprintf(stderr, "Invalid suboptions specified.\n");
+		usage();
+		std::exit(EXIT_FAILURE);
+	}
+	if (opt_str == nullptr && opt != CVT_INTERLACED && opt != CVT_ALT &&
+	    opt != CVT_OVERSCAN) {
+		fprintf(stderr, "No value given to suboption <%s>.\n",
+				subopt_list[opt]);
+		usage();
+		std::exit(EXIT_FAILURE);
+	}
+
+	if (opt_str)
+		*value = strtod(opt_str, nullptr);
+	return opt;
+}
+
+static void parse_cvt(char *optarg)
+{
+	unsigned w = 0, h = 0;
+	double fps = 0;
+	unsigned rb = RB_NONE;
+	unsigned rb_h_blank = 0;
+	bool interlaced = false;
+	bool alt = false;
+	bool overscan = false;
+
+	while (*optarg != '\0') {
+		int opt;
+		double opt_val;
+
+		opt = parse_cvt_subopt(&optarg, &opt_val);
+
+		switch (opt) {
+		case CVT_WIDTH:
+			w = round(opt_val);
+			break;
+		case CVT_HEIGHT:
+			h = round(opt_val);
+			break;
+		case CVT_FPS:
+			fps = opt_val;
+			break;
+		case CVT_RB:
+			rb = opt_val;
+			break;
+		case CVT_OVERSCAN:
+			overscan = true;
+			break;
+		case CVT_INTERLACED:
+			interlaced = opt_val;
+			break;
+		case CVT_ALT:
+			alt = opt_val;
+			break;
+		case CVT_RB_H_BLANK:
+			rb_h_blank = opt_val;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (!w || !h || !fps) {
+		fprintf(stderr, "Missing width, height and/or fps.\n");
+		usage();
+		std::exit(EXIT_FAILURE);
+	}
+	if (interlaced)
+		fps /= 2;
+	timings t = state.calc_cvt_mode(w, h, fps, rb, interlaced, overscan, alt, rb_h_blank);
+	state.print_timings("", &t, "CVT", "", true, false);
+}
+
+struct gtf_parsed_data {
+	unsigned w, h;
+	double freq;
+	double C, M, K, J;
+	bool overscan;
+	bool interlaced;
+	bool secondary;
+	bool params_from_edid;
+	enum gtf_ip_parm ip_parm;
+};
+
+enum gtf_opts {
+	GTF_WIDTH = 0,
+	GTF_HEIGHT,
+	GTF_FPS,
+	GTF_HORFREQ,
+	GTF_PIXCLK,
+	GTF_INTERLACED,
+	GTF_OVERSCAN,
+	GTF_SECONDARY,
+	GTF_C2,
+	GTF_M,
+	GTF_K,
+	GTF_J2,
+};
+
+static int parse_gtf_subopt(char **subopt_str, double *value)
+{
+	int opt;
+	char *opt_str;
+
+	static const char * const subopt_list[] = {
+		"w",
+		"h",
+		"fps",
+		"horfreq",
+		"pixclk",
+		"interlaced",
+		"overscan",
+		"secondary",
+		"C",
+		"M",
+		"K",
+		"J",
+		nullptr
+	};
+
+	opt = getsubopt(subopt_str, (char * const *)subopt_list, &opt_str);
+
+	if (opt == -1) {
+		fprintf(stderr, "Invalid suboptions specified.\n");
+		usage();
+		std::exit(EXIT_FAILURE);
+	}
+	if (opt_str == nullptr && opt != GTF_INTERLACED && opt != GTF_OVERSCAN &&
+	    opt != GTF_SECONDARY) {
+		fprintf(stderr, "No value given to suboption <%s>.\n",
+				subopt_list[opt]);
+		usage();
+		std::exit(EXIT_FAILURE);
+	}
+
+	if (opt == GTF_C2 || opt == GTF_J2)
+		*value = round(2.0 * strtod(opt_str, nullptr));
+	else if (opt_str)
+		*value = strtod(opt_str, nullptr);
+	return opt;
+}
+
+static void parse_gtf(char *optarg, gtf_parsed_data &data)
+{
+	memset(&data, 0, sizeof(data));
+	data.params_from_edid = true;
+	data.C = 40;
+	data.M = 600;
+	data.K = 128;
+	data.J = 20;
+
+	while (*optarg != '\0') {
+		int opt;
+		double opt_val;
+
+		opt = parse_gtf_subopt(&optarg, &opt_val);
+
+		switch (opt) {
+		case GTF_WIDTH:
+			data.w = round(opt_val);
+			break;
+		case GTF_HEIGHT:
+			data.h = round(opt_val);
+			break;
+		case GTF_FPS:
+			data.freq = opt_val;
+			data.ip_parm = gtf_ip_vert_freq;
+			break;
+		case GTF_HORFREQ:
+			data.freq = opt_val;
+			data.ip_parm = gtf_ip_hor_freq;
+			break;
+		case GTF_PIXCLK:
+			data.freq = opt_val;
+			data.ip_parm = gtf_ip_clk_freq;
+			break;
+		case GTF_INTERLACED:
+			data.interlaced = true;
+			break;
+		case GTF_OVERSCAN:
+			data.overscan = true;
+			break;
+		case GTF_SECONDARY:
+			data.secondary = true;
+			break;
+		case GTF_C2:
+			data.C = opt_val / 2.0;
+			data.params_from_edid = false;
+			break;
+		case GTF_M:
+			data.M = round(opt_val);
+			data.params_from_edid = false;
+			break;
+		case GTF_K:
+			data.K = round(opt_val);
+			data.params_from_edid = false;
+			break;
+		case GTF_J2:
+			data.J = opt_val / 2.0;
+			data.params_from_edid = false;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (!data.w || !data.h) {
+		fprintf(stderr, "Missing width and/or height.\n");
+		usage();
+		std::exit(EXIT_FAILURE);
+	}
+	if (!data.freq) {
+		fprintf(stderr, "One of fps, horfreq or pixclk must be given.\n");
+		usage();
+		std::exit(EXIT_FAILURE);
+	}
+	if (!data.secondary)
+		data.params_from_edid = false;
+	if (data.interlaced && data.ip_parm == gtf_ip_vert_freq)
+		data.freq /= 2;
+}
+
+static void show_gtf(gtf_parsed_data &data)
+{
+	timings t;
+
+	t = state.calc_gtf_mode(data.w, data.h, data.freq, data.interlaced,
+				data.ip_parm, data.overscan, data.secondary,
+				data.C, data.M, data.K, data.J);
+	calc_ratio(&t);
+	state.print_timings("", &t, "GTF", "", true, false);
+}
+
+int main(int argc, char **argv)
+{
+	char short_options[26 * 2 * 2 + 1];
+	enum output_format out_fmt = OUT_FMT_DEFAULT;
+	gtf_parsed_data gtf_data;
+	int ret;
+
+	while (1) {
+		int option_index = 0;
+		unsigned idx = 0;
+		unsigned i, val;
+		const timings *t;
+		char buf[16];
+
+		for (i = 0; long_options[i].name; i++) {
+			if (!isalpha(long_options[i].val))
+				continue;
+			short_options[idx++] = long_options[i].val;
+			if (long_options[i].has_arg == required_argument)
+				short_options[idx++] = ':';
+		}
+		short_options[idx] = 0;
+		int ch = getopt_long(argc, argv, short_options,
+				     long_options, &option_index);
+		if (ch == -1)
+			break;
+
+		options[ch] = 1;
+		switch (ch) {
+		case OptHelp:
+			usage();
+			return -1;
+		case OptOutputFormat:
+			if (!strcmp(optarg, "hex")) {
+				out_fmt = OUT_FMT_HEX;
+			} else if (!strcmp(optarg, "raw")) {
+				out_fmt = OUT_FMT_RAW;
+			} else if (!strcmp(optarg, "carray")) {
+				out_fmt = OUT_FMT_CARRAY;
+			} else if (!strcmp(optarg, "xml")) {
+				out_fmt = OUT_FMT_XML;
+			} else {
+				usage();
+				exit(1);
+			}
+			break;
+		case OptSTD: {
+			unsigned char byte1, byte2 = 0;
+			char *endptr;
+
+			byte1 = strtoul(optarg, &endptr, 0);
+			if (*endptr == ',')
+				byte2 = strtoul(endptr + 1, NULL, 0);
+			state.print_standard_timing("", byte1, byte2, false, true);
+			break;
+		}
+		case OptDMT:
+			val = strtoul(optarg, NULL, 0);
+			t = find_dmt_id(val);
+			if (t) {
+				sprintf(buf, "DMT 0x%02x", val);
+				state.print_timings("", t, buf, "", true, false);
+			} else {
+				fprintf(stderr, "Unknown DMT code 0x%02x.\n", val);
+			}
+			break;
+		case OptVIC:
+			val = strtoul(optarg, NULL, 0);
+			t = find_vic_id(val);
+			if (t) {
+				sprintf(buf, "VIC %3u", val);
+				state.print_timings("", t, buf, "", true, false);
+			} else {
+				fprintf(stderr, "Unknown VIC code %u.\n", val);
+			}
+			break;
+		case OptHDMIVIC:
+			val = strtoul(optarg, NULL, 0);
+			t = find_hdmi_vic_id(val);
+			if (t) {
+				sprintf(buf, "HDMI VIC %u", val);
+				state.print_timings("", t, buf, "", true, false);
+			} else {
+				fprintf(stderr, "Unknown HDMI VIC code %u.\n", val);
+			}
+			break;
+		case OptCVT:
+			parse_cvt(optarg);
+			break;
+		case OptGTF:
+			parse_gtf(optarg, gtf_data);
+			break;
+		case ':':
+			fprintf(stderr, "Option '%s' requires a value.\n",
+				argv[optind]);
+			usage();
+			return -1;
+		case '?':
+			fprintf(stderr, "Unknown argument '%s'.\n",
+				argv[optind]);
+			usage();
+			return -1;
+		}
+	}
+	if (optind == argc && options[OptVersion]) {
+		if (strlen(STRING(SHA)))
+			printf("edid-decode SHA: %s %s\n", STRING(SHA), STRING(DATE));
+		else
+			printf("edid-decode SHA: not available\n");
+		return 0;
+	}
+
+	if (options[OptListEstTimings])
+		state.list_established_timings();
+	if (options[OptListDMTs])
+		state.list_dmts();
+	if (options[OptListVICs])
+		state.cta_list_vics();
+	if (options[OptListHDMIVICs])
+		state.cta_list_hdmi_vics();
+
+	if (options[OptListEstTimings] || options[OptListDMTs] ||
+	    options[OptListVICs] || options[OptListHDMIVICs])
+		return 0;
+
+	if (options[OptCVT] || options[OptDMT] || options[OptVIC] ||
+	    options[OptHDMIVIC] || options[OptSTD])
+		return 0;
+
+	if (options[OptGTF] && (!gtf_data.params_from_edid || optind == argc)) {
+		show_gtf(gtf_data);
+		return 0;
+	}
+
+	if (optind == argc)
+		ret = edid_from_file("-", stdout);
+	else
+		ret = edid_from_file(argv[optind], argv[optind + 1] ? stderr : stdout);
+
+	if (ret && options[OptPhysicalAddress]) {
+		printf("f.f.f.f\n");
+		return 0;
+	}
+	if (optind < argc - 1)
+		return ret ? ret : edid_to_file(argv[optind + 1], out_fmt);
+
+	if (options[OptGTF]) {
+		timings t;
+
+		// Find the Secondary Curve
+		state.preparse_detailed_block(edid + 0x36);
+		state.preparse_detailed_block(edid + 0x48);
+		state.preparse_detailed_block(edid + 0x5a);
+		state.preparse_detailed_block(edid + 0x6c);
+
+		t = state.calc_gtf_mode(gtf_data.w, gtf_data.h, gtf_data.freq,
+					gtf_data.interlaced, gtf_data.ip_parm,
+					gtf_data.overscan);
+		unsigned hbl = t.hfp + t.hsync + t.hbp;
+		unsigned htotal = t.hact + hbl;
+		double hor_freq_khz = htotal ? (double)t.pixclk_khz / htotal : 0;
+
+		if (state.base.supports_sec_gtf &&
+		    hor_freq_khz >= state.base.sec_gtf_start_freq) {
+			t = state.calc_gtf_mode(gtf_data.w, gtf_data.h, gtf_data.freq,
+						gtf_data.interlaced, gtf_data.ip_parm,
+						gtf_data.overscan, true,
+						state.base.C, state.base.M,
+						state.base.K, state.base.J);
+		}
+		calc_ratio(&t);
+		if (t.hfp <= 0)
+			state.print_timings("", &t, "GTF", "INVALID: Hfront <= 0", true, false);
+		else
+			state.print_timings("", &t, "GTF", "", true, false);
+		return 0;
+	}
+
+	return ret ? ret : state.parse_edid();
+}
+
+#ifdef __EMSCRIPTEN__
+/*
+ * The surrounding JavaScript implementation will call this function
+ * each time it wants to decode an EDID. So this should reset all the
+ * state and start over.
+ */
+extern "C" int parse_edid(const char *input)
+{
+	for (unsigned i = 0; i < EDID_MAX_BLOCKS + 1; i++) {
+		s_msgs[i][0].clear();
+		s_msgs[i][1].clear();
+	}
+	options[OptCheck] = 1;
+	options[OptPreferredTimings] = 1;
+	options[OptNativeTimings] = 1;
+	state = edid_state();
+	int ret = edid_from_file(input, stderr);
+	return ret ? ret : state.parse_edid();
+}
+#endif
diff --git a/edid-decode.h b/edid-decode.h
new file mode 100644
index 0000000..f3fdfd0
--- /dev/null
+++ b/edid-decode.h
@@ -0,0 +1,466 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2006-2012 Red Hat, Inc.
+ * Copyright 2018-2020 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ *
+ * Author: Adam Jackson <ajax@nwnk.net>
+ * Maintainer: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+ */
+
+#ifndef __EDID_DECODE_H_
+#define __EDID_DECODE_H_
+
+#include <string>
+#include <vector>
+#include <set>
+#include <string.h>
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+#define EDID_PAGE_SIZE 128U
+#define EDID_MAX_BLOCKS 256U
+
+#define RB_ALT		(1U << 7)
+
+#define RB_NONE		(0U)
+#define RB_CVT_V1	(1U)
+#define RB_CVT_V2	(2U)
+#define RB_CVT_V3	(3U)
+#define RB_GTF		(4U)
+
+// Video Timings
+// If interlaced is true, then the vertical blanking
+// for each field is (vfp + vsync + vbp + 0.5), except for
+// the VIC 39 timings that doesn't have the 0.5 constant.
+//
+// The sequence of the various video parameters is as follows:
+//
+// border - front porch - sync - back porch - border - active video
+//
+// Note: this is slightly different from EDID 1.4 which calls
+// 'active video' as 'addressable video' and the EDID 1.4 term
+// 'active video' includes the borders.
+//
+// But since borders are rarely used, the term 'active video' will
+// typically be the same as 'addressable video', and that's how I
+// use it.
+struct timings {
+	// Active horizontal and vertical frame height, excluding any
+	// borders, if present.
+	// Note: for interlaced formats the active field height is vact / 2
+	unsigned hact, vact;
+	unsigned hratio, vratio;
+	unsigned pixclk_khz;
+	// 0: no reduced blanking
+	// 1: CVT reduced blanking version 1
+	// 2: CVT reduced blanking version 2
+	// 2 | RB_ALT: CVT reduced blanking version 2 video-optimized (1000/1001 fps)
+	// 3: CVT reduced blanking version 3
+	// 3 | RB_ALT: v3 with a horizontal blank of 160
+	// 4: GTF Secondary Curve
+	unsigned rb;
+	bool interlaced;
+	// The horizontal frontporch may be negative in GTF calculations,
+	// so use int instead of unsigned for hfp. Example: 292x176@76.
+	int hfp;
+	unsigned hsync;
+	// The backporch may be negative in buggy detailed timings.
+	// So use int instead of unsigned for hbp and vbp.
+	int hbp;
+	bool pos_pol_hsync;
+	// For interlaced formats the vertical front porch of the Even Field
+	// is actually a half-line longer.
+	unsigned vfp, vsync;
+	// For interlaced formats the vertical back porch of the Odd Field
+	// is actually a half-line longer.
+	int vbp;
+	bool pos_pol_vsync;
+	unsigned hborder, vborder;
+	bool even_vtotal; // special for VIC 39
+	bool no_pol_vsync; // digital composite signals have no vsync polarity
+	unsigned hsize_mm, vsize_mm;
+	bool ycbcr420; // YCbCr 4:2:0 encoding
+};
+
+struct timings_ext {
+	timings_ext()
+	{
+		memset(&t, 0, sizeof(t));
+	}
+	timings_ext(unsigned svr, const std::string &_type)
+	{
+		memset(&t, 0, sizeof(t));
+		t.hact = svr;
+		type = _type;
+	}
+	timings_ext(const timings &_t, const std::string &_type, const std::string &_flags)
+	{
+		t = _t;
+		type = _type;
+		flags = _flags;
+	}
+
+	bool is_valid() const { return t.hact; }
+	bool has_svr() const { return t.hact && !t.vact; }
+	unsigned svr() const { return t.hact; }
+	timings t;
+	std::string type;
+	std::string flags;
+};
+
+enum gtf_ip_parm {
+	gtf_ip_vert_freq = 1,
+	gtf_ip_hor_freq,
+	gtf_ip_clk_freq,
+};
+
+typedef std::vector<timings_ext> vec_timings_ext;
+
+struct edid_state {
+	edid_state()
+	{
+		// Global state
+		edid_size = num_blocks = block_nr = 0;
+		max_hor_freq_hz = max_vert_freq_hz = max_pixclk_khz = 0;
+		min_hor_freq_hz = 0xffffff;
+		min_vert_freq_hz = 0xffffffff;
+		dtd_max_vsize_mm = dtd_max_hsize_mm = 0;
+		warnings = failures = 0;
+		has_cta = has_dispid = false;
+		hide_serial_numbers = false;
+
+		// Base block state
+		base.edid_minor = 0;
+		base.has_name_descriptor = base.has_display_range_descriptor =
+			base.has_serial_number = base.has_serial_string =
+			base.supports_continuous_freq = base.supports_gtf =
+			base.supports_cvt = base.seen_non_detailed_descriptor =
+			base.has_640x480p60_est_timing = base.has_spwg =
+			base.preferred_is_also_native = false;
+		base.supports_sec_gtf = false;
+		base.sec_gtf_start_freq = 0;
+		base.C = base.M = base.K = base.J = 0;
+		base.max_pos_neg_hor_freq_khz = 0;
+		base.detailed_block_cnt = base.dtd_cnt = 0;
+
+		base.min_display_hor_freq_hz = base.max_display_hor_freq_hz =
+			base.min_display_vert_freq_hz = base.max_display_vert_freq_hz =
+			base.max_display_pixclk_khz = base.max_display_width_mm =
+			base.max_display_height_mm = 0;
+
+		// CTA-861 block state
+		cta.has_vic_1 = cta.first_svd_might_be_preferred = cta.has_sldb =
+			cta.has_hdmi = cta.has_vcdb = cta.has_vfpdb = false;
+		cta.last_block_was_hdmi_vsdb = cta.have_hf_vsdb = cta.have_hf_scdb = false;
+		cta.first_block = cta.first_svd = true;
+		cta.supported_hdmi_vic_codes = cta.supported_hdmi_vic_vsb_codes = 0;
+		memset(cta.vics, 0, sizeof(cta.vics));
+		memset(cta.preparsed_has_vic, 0, sizeof(cta.preparsed_has_vic));
+		cta.preparsed_phys_addr = 0xffff;
+		cta.preparsed_speaker_count = 0;
+		cta.preparsed_sld = false;
+		cta.preparsed_sld_has_coord = false;
+		cta.preparsed_total_dtds = 0;
+		cta.preparsed_total_vtdbs = 0;
+		cta.preparsed_has_t8vtdb = false;
+
+		// DisplayID block state
+		dispid.version = 0;
+		dispid.native_width = dispid.native_height = 0;
+		dispid.preparsed_color_ids = dispid.preparsed_xfer_ids = 0;
+		dispid.preparsed_displayid_blocks = 0;
+		dispid.is_base_block = true;
+		dispid.is_display = dispid.has_product_identification =
+			dispid.has_display_parameters = dispid.has_type_1_7 =
+			dispid.has_display_interface_features = false;
+
+		// Block Map block state
+		block_map.saw_block_1 = false;
+		block_map.saw_block_128 = false;
+	}
+
+	// Global state
+	unsigned edid_size;
+	unsigned num_blocks;
+	unsigned block_nr;
+	std::string block;
+	std::string data_block;
+	bool has_cta;
+	bool has_dispid;
+	bool hide_serial_numbers;
+
+	unsigned min_hor_freq_hz;
+	unsigned max_hor_freq_hz;
+	double min_vert_freq_hz;
+	double max_vert_freq_hz;
+	unsigned max_pixclk_khz;
+	unsigned dtd_max_hsize_mm;
+	unsigned dtd_max_vsize_mm;
+
+	unsigned warnings;
+	unsigned failures;
+
+	// Base block state
+	struct {
+		unsigned edid_minor;
+		bool has_name_descriptor;
+		bool has_display_range_descriptor;
+		bool has_serial_number;
+		bool has_serial_string;
+		bool supports_continuous_freq;
+		bool supports_gtf;
+		bool supports_sec_gtf;
+		unsigned sec_gtf_start_freq;
+		double C, M, K, J;
+		bool supports_cvt;
+		bool has_spwg;
+		unsigned detailed_block_cnt;
+		unsigned dtd_cnt;
+		bool seen_non_detailed_descriptor;
+		bool has_640x480p60_est_timing;
+		bool preferred_is_also_native;
+		timings_ext preferred_timing;
+
+		unsigned min_display_hor_freq_hz;
+		unsigned max_display_hor_freq_hz;
+		unsigned min_display_vert_freq_hz;
+		unsigned max_display_vert_freq_hz;
+		unsigned max_display_pixclk_khz;
+		unsigned max_display_width_mm;
+		unsigned max_display_height_mm;
+		unsigned max_pos_neg_hor_freq_khz;
+	} base;
+
+	// CTA-861 block state
+	struct {
+		unsigned preparsed_total_dtds;
+		vec_timings_ext vec_dtds;
+		unsigned preparsed_total_vtdbs;
+		vec_timings_ext vec_vtdbs;
+		vec_timings_ext preferred_timings;
+		bool preparsed_has_t8vtdb;
+		// Keep track of the found Tag/Extended Tag pairs.
+		// The unsigned value is equal to: (tag << 8) | ext_tag
+		std::set<unsigned> found_tags;
+		timings_ext t8vtdb;
+		vec_timings_ext native_timings;
+		bool has_vic_1;
+		bool first_svd_might_be_preferred;
+		unsigned char byte3;
+		bool has_hdmi;
+		bool has_vcdb;
+		bool has_vfpdb;
+		unsigned preparsed_speaker_count;
+		bool preparsed_sld_has_coord;
+		bool preparsed_sld;
+		bool has_sldb;
+		unsigned short preparsed_phys_addr;
+		bool last_block_was_hdmi_vsdb;
+		bool have_hf_vsdb, have_hf_scdb;
+		bool first_block;
+		bool first_svd;
+		unsigned supported_hdmi_vic_codes;
+		unsigned supported_hdmi_vic_vsb_codes;
+		unsigned short vics[256][2];
+		bool preparsed_has_vic[2][256];
+		std::vector<unsigned char> preparsed_svds[2];
+	} cta;
+
+	// DisplayID block state
+	struct {
+		unsigned char version;
+		unsigned short preparsed_color_ids;
+		unsigned short preparsed_xfer_ids;
+		unsigned preparsed_displayid_blocks;
+		bool is_base_block;
+		bool is_display;
+		bool has_product_identification;
+		bool has_display_parameters;
+		bool has_type_1_7;
+		bool has_display_interface_features;
+		vec_timings_ext preferred_timings;
+		unsigned native_width, native_height;
+		// Keep track of the found CTA-861 Tag/Extended Tag pairs.
+		// The unsigned value is equal to: (tag << 8) | ext_tag
+		std::set<unsigned> found_tags;
+	} dispid;
+
+	// Block Map block state
+	struct {
+		bool saw_block_1;
+		bool saw_block_128;
+	} block_map;
+
+	std::string dtd_type(unsigned dtd);
+	std::string dtd_type() { return dtd_type(base.dtd_cnt); }
+	bool print_timings(const char *prefix, const struct timings *t,
+			   const char *type, const char *flags = "",
+			   bool detailed = false, bool do_checks = true);
+	bool print_timings(const char *prefix, const struct timings_ext &t,
+			   bool detailed = false, bool do_checks = true)
+	{
+		return print_timings(prefix, &t.t, t.type.c_str(), t.flags.c_str(),
+				     detailed, do_checks);
+	};
+	bool match_timings(const timings &t1, const timings &t2);
+	timings calc_gtf_mode(unsigned h_pixels, unsigned v_lines,
+			      double ip_freq_rqd, bool int_rqd = false,
+			      enum gtf_ip_parm ip_parm = gtf_ip_vert_freq,
+			      bool margins_rqd = false, bool secondary = false,
+			      double C = 40, double M = 600, double K = 128, double J = 20);
+	void edid_gtf_mode(unsigned refresh, struct timings &t);
+	timings calc_cvt_mode(unsigned h_pixels, unsigned v_lines,
+			      double ip_freq_rqd, unsigned rb, bool int_rqd = false,
+			      bool margins_rqd = false, bool alt = false,
+			      unsigned rb_h_blank = 0);
+	void edid_cvt_mode(unsigned refresh, struct timings &t);
+	void detailed_cvt_descriptor(const char *prefix, const unsigned char *x, bool first);
+	void print_standard_timing(const char *prefix, unsigned char b1, unsigned char b2,
+				   bool gtf_only = false, bool show_both = false);
+	void detailed_display_range_limits(const unsigned char *x);
+	void detailed_epi(const unsigned char *x);
+	void detailed_timings(const char *prefix, const unsigned char *x,
+			      bool base_or_cta = true);
+	void preparse_detailed_block(const unsigned char *x);
+	void detailed_block(const unsigned char *x);
+	void parse_base_block(const unsigned char *x);
+	void check_base_block();
+	void list_dmts();
+	void list_established_timings();
+
+	void print_vic_index(const char *prefix, unsigned idx, const char *suffix, bool ycbcr420 = false);
+	void hdmi_latency(unsigned char vid_lat, unsigned char aud_lat, bool is_ilaced);
+	void cta_vcdb(const unsigned char *x, unsigned length);
+	void cta_svd(const unsigned char *x, unsigned n, bool for_ycbcr420);
+	void cta_y420cmdb(const unsigned char *x, unsigned length);
+	void cta_vfpdb(const unsigned char *x, unsigned length);
+	void cta_rcdb(const unsigned char *x, unsigned length);
+	void cta_sldb(const unsigned char *x, unsigned length);
+	void cta_preparse_sldb(const unsigned char *x, unsigned length);
+	void cta_hdmi_block(const unsigned char *x, unsigned length);
+	void cta_displayid_type_7(const unsigned char *x, unsigned length);
+	void cta_displayid_type_8(const unsigned char *x, unsigned length);
+	void cta_displayid_type_10(const unsigned char *x, unsigned length);
+	void cta_ext_block(const unsigned char *x, unsigned length, bool duplicate);
+	void cta_block(const unsigned char *x, bool duplicate);
+	void preparse_cta_block(const unsigned char *x);
+	void parse_cta_block(const unsigned char *x);
+	void cta_resolve_svr(vec_timings_ext::iterator iter);
+	void cta_resolve_svrs();
+	void check_cta_blocks();
+	void cta_list_vics();
+	void cta_list_hdmi_vics();
+
+	void parse_digital_interface(const unsigned char *x);
+	void parse_display_device(const unsigned char *x);
+	void parse_display_caps(const unsigned char *x);
+	void parse_display_xfer(const unsigned char *x);
+	void parse_di_ext_block(const unsigned char *x);
+
+	void check_displayid_datablock_revision(unsigned char hdr,
+						unsigned char valid_flags = 0,
+						unsigned char rev = 0);
+	void parse_displayid_product_id(const unsigned char *x);
+	std::string product_type(unsigned char x, bool heading);
+	void parse_displayid_interface_features(const unsigned char *x);
+	void parse_displayid_parameters(const unsigned char *x);
+	void parse_displayid_parameters_v2(const unsigned char *x, unsigned block_rev);
+	void parse_displayid_display_intf(const unsigned char *x);
+	void parse_displayid_color_characteristics(const unsigned char *x);
+	void parse_displayid_transfer_characteristics(const unsigned char *x);
+	void parse_displayid_stereo_display_intf(const unsigned char *x);
+	void parse_displayid_type_1_7_timing(const unsigned char *x,
+					     bool type7, unsigned block_rev, bool is_cta = false);
+	void parse_displayid_type_2_timing(const unsigned char *x);
+	void parse_displayid_type_3_timing(const unsigned char *x);
+	void parse_displayid_type_4_8_timing(unsigned char type, unsigned short id, bool is_cta = false);
+	void parse_displayid_video_timing_range_limits(const unsigned char *x);
+	void parse_displayid_string(const unsigned char *x);
+	void parse_displayid_display_device(const unsigned char *x);
+	void parse_displayid_intf_power_sequencing(const unsigned char *x);
+	void parse_displayid_type_5_timing(const unsigned char *x);
+	void parse_displayid_tiled_display_topology(const unsigned char *x, bool is_v2);
+	void parse_displayid_type_6_timing(const unsigned char *x);
+	void parse_displayid_type_9_timing(const unsigned char *x);
+	void parse_displayid_dynamic_video_timings_range_limits(const unsigned char *x);
+	void parse_displayid_ContainerID(const unsigned char *x);
+	void parse_displayid_type_10_timing(const unsigned char *x, bool is_cta = false);
+	void preparse_displayid_block(const unsigned char *x);
+	void parse_displayid_block(const unsigned char *x);
+	void parse_displayid_vesa(const unsigned char *x);
+	void parse_displayid_cta_data_block(const unsigned char *x);
+	void check_displayid_blocks();
+
+	void parse_vtb_ext_block(const unsigned char *x);
+
+	void parse_string_table(const unsigned char *x);
+	void parse_ls_ext_block(const unsigned char *x);
+
+	void parse_block_map(const unsigned char *x);
+
+	void preparse_extension(const unsigned char *x);
+	void parse_extension(const unsigned char *x);
+	int parse_edid();
+};
+
+static inline void add_str(std::string &s, const std::string &add)
+{
+	if (s.empty())
+		s = add;
+	else if (!add.empty())
+		s = s + ", " + add;
+}
+
+void msg(bool is_warn, const char *fmt, ...);
+
+#ifdef _WIN32
+
+#define warn(fmt, ...) msg(true, fmt, __VA_ARGS__)
+#define warn_once(fmt, ...)				\
+	do {						\
+		static bool shown_warn;			\
+		if (!shown_warn) {			\
+			shown_warn = true;		\
+			msg(true, fmt, __VA_ARGS__);	\
+		}					\
+	} while (0)
+#define fail(fmt, ...) msg(false, fmt, __VA_ARGS__)
+
+#else
+
+#define warn(fmt, args...) msg(true, fmt, ##args)
+#define warn_once(fmt, args...)				\
+	do {						\
+		static bool shown_warn;			\
+		if (!shown_warn) {			\
+			shown_warn = true;		\
+			msg(true, fmt, ##args);		\
+		}					\
+	} while (0)
+#define fail(fmt, args...) msg(false, fmt, ##args)
+
+#endif
+
+void do_checksum(const char *prefix, const unsigned char *x, size_t len);
+std::string utohex(unsigned char x);
+std::string ouitohex(unsigned oui);
+std::string containerid2s(const unsigned char *x);
+bool memchk(const unsigned char *x, unsigned len, unsigned char v = 0);
+void hex_block(const char *prefix, const unsigned char *x, unsigned length,
+	       bool show_ascii = true, unsigned step = 16);
+std::string block_name(unsigned char block);
+void calc_ratio(struct timings *t);
+const char *oui_name(unsigned oui, bool reverse = false);
+
+bool timings_close_match(const timings &t1, const timings &t2);
+const struct timings *find_dmt_id(unsigned char dmt_id);
+const struct timings *close_match_to_dmt(const timings &t, unsigned &dmt);
+const struct timings *find_vic_id(unsigned char vic);
+const struct timings *find_hdmi_vic_id(unsigned char hdmi_vic);
+const struct timings *cta_close_match_to_vic(const timings &t, unsigned &vic);
+unsigned char hdmi_vic_to_vic(unsigned char hdmi_vic);
+char *extract_string(const unsigned char *x, unsigned len);
+
+#endif
diff --git a/parse-base-block.cpp b/parse-base-block.cpp
new file mode 100644
index 0000000..2b1a6e0
--- /dev/null
+++ b/parse-base-block.cpp
@@ -0,0 +1,1710 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2006-2012 Red Hat, Inc.
+ * Copyright 2018-2020 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ *
+ * Author: Adam Jackson <ajax@nwnk.net>
+ * Maintainer: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <time.h>
+
+#include "edid-decode.h"
+
+static char *manufacturer_name(const unsigned char *x)
+{
+	static char name[4];
+
+	name[0] = ((x[0] & 0x7c) >> 2) + '@';
+	name[1] = ((x[0] & 0x03) << 3) + ((x[1] & 0xe0) >> 5) + '@';
+	name[2] = (x[1] & 0x1f) + '@';
+	name[3] = 0;
+
+	if (!isupper(name[0]) || !isupper(name[1]) || !isupper(name[2]))
+		fail("Manufacturer name field contains garbage.\n");
+
+	return name;
+}
+
+static const struct {
+	unsigned dmt_id;
+	unsigned std_id;
+	unsigned cvt_id;
+	struct timings t;
+} dmt_timings[] = {
+	{ 0x01, 0x0000, 0x000000, { 640, 350, 64, 35, 31500, 0, false,
+				    32, 64, 96, true, 32, 3, 60, false } },
+
+	{ 0x02, 0x3119, 0x000000, { 640, 400, 16, 10, 31500, 0, false,
+				    32, 64, 96, false, 1, 3, 41, true } },
+
+	{ 0x03, 0x0000, 0x000000, { 720, 400, 9, 5, 35500, 0, false,
+				    36, 72, 108, false, 1, 3, 42, true } },
+
+	{ 0x04, 0x3140, 0x000000, { 640, 480, 4, 3, 25175, 0, false,
+				    8, 96, 40, false, 2, 2, 25, false, 8, 8 } },
+	{ 0x05, 0x314c, 0x000000, { 640, 480, 4, 3, 31500, 0, false,
+				    16, 40, 120, false, 1, 3, 20, false, 8, 8 } },
+	{ 0x06, 0x314f, 0x000000, { 640, 480, 4, 3, 31500, 0, false,
+				    16, 64, 120, false, 1, 3, 16, false } },
+	{ 0x07, 0x3159, 0x000000, { 640, 480, 4, 3, 36000, 0, false,
+				    56, 56, 80, false, 1, 3, 25, false } },
+
+	{ 0x08, 0x0000, 0x000000, { 800, 600, 4, 3, 36000, 0, false,
+				    24, 72, 128, true, 1, 2, 22, true } },
+	{ 0x09, 0x4540, 0x000000, { 800, 600, 4, 3, 40000, 0, false,
+				    40, 128, 88, true, 1, 4, 23, true } },
+	{ 0x0a, 0x454c, 0x000000, { 800, 600, 4, 3, 50000, 0, false,
+				    56, 120, 64, true, 37, 6, 23, true } },
+	{ 0x0b, 0x454f, 0x000000, { 800, 600, 4, 3, 49500, 0, false,
+				    16, 80, 160, true, 1, 3, 21, true } },
+	{ 0x0c, 0x4559, 0x000000, { 800, 600, 4, 3, 56250, 0, false,
+				    32, 64, 152, true, 1, 3, 27, true } },
+	{ 0x0d, 0x0000, 0x000000, { 800, 600, 4, 3, 73250, 1, false,
+				    48, 32, 80, true, 3, 4, 29, false } },
+
+	{ 0x0e, 0x0000, 0x000000, { 848, 480, 16, 9, 33750, 0, false,
+				    16, 112, 112, true, 6, 8, 23, true } },
+
+	{ 0x0f, 0x0000, 0x000000, { 1024, 768, 4, 3, 44900, 0, true,
+				    8, 176, 56, true, 0, 4, 20, true } },
+	{ 0x10, 0x6140, 0x000000, { 1024, 768, 4, 3, 65000, 0, false,
+				    24, 136, 160, false, 3, 6, 29, false } },
+	{ 0x11, 0x614c, 0x000000, { 1024, 768, 4, 3, 75000, 0, false,
+				    24, 136, 144, false, 3, 6, 29, false } },
+	{ 0x12, 0x614f, 0x000000, { 1024, 768, 4, 3, 78750, 0, false,
+				    16, 96, 176, true, 1, 3, 28, true } },
+	{ 0x13, 0x6159, 0x000000, { 1024, 768, 4, 3, 94500, 0, false,
+				    48, 96, 208, true, 1, 3, 36, true } },
+	{ 0x14, 0x0000, 0x000000, { 1024, 768, 4, 3, 115500, 1, false,
+				    48, 32, 80, true, 3, 4, 38, false } },
+
+	{ 0x15, 0x714f, 0x000000, { 1152, 864, 4, 3, 108000, 0, false,
+				    64, 128, 256, true, 1, 3, 32, true } },
+
+	{ 0x55, 0x81c0, 0x000000, { 1280, 720, 16, 9, 74250, 0, false,
+				    110, 40, 220, true, 5, 5, 20, true } },
+
+	{ 0x16, 0x0000, 0x7f1c21, { 1280, 768, 5, 3, 68250, 1, false,
+				    48, 32, 80, true, 3, 7, 12, false } },
+	{ 0x17, 0x0000, 0x7f1c28, { 1280, 768, 5, 3, 79500, 0, false,
+				    64, 128, 192, false, 3, 7, 20, true } },
+	{ 0x18, 0x0000, 0x7f1c44, { 1280, 768, 5, 3, 102250, 0, false,
+				    80, 128, 208, false, 3, 7, 27, true } },
+	{ 0x19, 0x0000, 0x7f1c62, { 1280, 768, 5, 3, 117500, 0, false,
+				    80, 136, 216, false, 3, 7, 31, true } },
+	{ 0x1a, 0x0000, 0x000000, { 1280, 768, 5, 3, 140250, 0, false,
+				    48, 32, 80, true, 3, 7, 35, false } },
+
+	{ 0x1b, 0x0000, 0x8f1821, { 1280, 800, 16, 10, 71000, 1, false,
+				    48, 32, 80, true, 3, 6, 14, false } },
+	{ 0x1c, 0x8100, 0x8f1828, { 1280, 800, 16, 10, 83500, 0, false,
+				    72, 128, 200, false, 3, 6, 22, true } },
+	{ 0x1d, 0x810f, 0x8f1844, { 1280, 800, 16, 10, 106500, 0, false,
+				    80, 128, 208, false, 3, 6, 29, true } },
+	{ 0x1e, 0x8119, 0x8f1862, { 1280, 800, 16, 10, 122500, 0, false,
+				    80, 136, 216, false, 3, 6, 34, true } },
+	{ 0x1f, 0x0000, 0x000000, { 1280, 800, 16, 10, 146250, 1, false,
+				    48, 32, 80, true, 3, 6, 38, false } },
+
+	{ 0x20, 0x8140, 0x000000, { 1280, 960, 4, 3, 108000, 0, false,
+				    96, 112, 312, true, 1, 3, 36, true } },
+	{ 0x21, 0x8159, 0x000000, { 1280, 960, 4, 3, 148500, 0, false,
+				    64, 160, 224, true, 1, 3, 47, true } },
+	{ 0x22, 0x0000, 0x000000, { 1280, 960, 4, 3, 175500, 1, false,
+				    48, 32, 80, true, 3, 4, 50, false } },
+
+	{ 0x23, 0x8180, 0x000000, { 1280, 1024, 5, 4, 108000, 0, false,
+				    48, 112, 248, true, 1, 3, 38, true } },
+	{ 0x24, 0x818f, 0x000000, { 1280, 1024, 5, 4, 135000, 0, false,
+				    16, 144, 248, true, 1, 3, 38, true } },
+	{ 0x25, 0x8199, 0x000000, { 1280, 1024, 5, 4, 157500, 0, false,
+				    64, 160, 224, true, 1, 3, 44, true } },
+	{ 0x26, 0x0000, 0x000000, { 1280, 1024, 5, 4, 187250, 1, false,
+				    48, 32, 80, true, 3, 7, 50, false } },
+
+	{ 0x27, 0x0000, 0x000000, { 1360, 768, 85, 48, 85500, 0, false,
+				    64, 112, 256, true, 3, 6, 18, true } },
+	{ 0x28, 0x0000, 0x000000, { 1360, 768, 85, 48, 148250, 1, false,
+				    48, 32, 80, true, 3, 5, 37, false } },
+
+	{ 0x51, 0x0000, 0x000000, { 1366, 768, 85, 48, 85500, 0, false,
+				    70, 143, 213, true, 3, 3, 24, true } },
+	{ 0x56, 0x0000, 0x000000, { 1366, 768, 85, 48, 72000, 1, false,
+				    14, 56, 64, true, 1, 3, 28, true } },
+
+	{ 0x29, 0x0000, 0x0c2021, { 1400, 1050, 4, 3, 101000, 1, false,
+				    48, 32, 80, true, 3, 4, 23, false } },
+	{ 0x2a, 0x9040, 0x0c2028, { 1400, 1050, 4, 3, 121750, 0, false,
+				    88, 144, 232, false, 3, 4, 32, true } },
+	{ 0x2b, 0x904f, 0x0c2044, { 1400, 1050, 4, 3, 156000, 0, false,
+				    104, 144, 248, false, 3, 4, 42, true } },
+	{ 0x2c, 0x9059, 0x0c2062, { 1400, 1050, 4, 3, 179500, 0, false,
+				    104, 152, 256, false, 3, 4, 48, true } },
+	{ 0x2d, 0x0000, 0x000000, { 1400, 1050, 4, 3, 208000, 1, false,
+				    48, 32, 80, true, 3, 4, 55, false } },
+
+	{ 0x2e, 0x0000, 0xc11821, { 1440, 900, 16, 10, 88750, 1, false,
+				    48, 32, 80, true, 3, 6, 17, false } },
+	{ 0x2f, 0x9500, 0xc11828, { 1440, 900, 16, 10, 106500, 0, false,
+				    80, 152, 232, false, 3, 6, 25, true } },
+	{ 0x30, 0x950f, 0xc11844, { 1440, 900, 16, 10, 136750, 0, false,
+				    96, 152, 248, false, 3, 6, 33, true } },
+	{ 0x31, 0x9519, 0xc11868, { 1440, 900, 16, 10, 157000, 0, false,
+				    104, 152, 256, false, 3, 6, 39, true } },
+	{ 0x32, 0x0000, 0x000000, { 1440, 900, 16, 10, 182750, 1, false,
+				    48, 32, 80, true, 3, 6, 44, false } },
+
+	{ 0x53, 0xa9c0, 0x000000, { 1600, 900, 16, 9, 108000, 1, false,
+				    24, 80, 96, true, 1, 3, 96, true } },
+
+	{ 0x33, 0xa940, 0x000000, { 1600, 1200, 4, 3, 162000, 0, false,
+				    64, 192, 304, true, 1, 3, 46, true } },
+	{ 0x34, 0xa945, 0x000000, { 1600, 1200, 4, 3, 175500, 0, false,
+				    64, 192, 304, true, 1, 3, 46, true } },
+	{ 0x35, 0xa94a, 0x000000, { 1600, 1200, 4, 3, 189000, 0, false,
+				    64, 192, 304, true, 1, 3, 46, true } },
+	{ 0x36, 0xa94f, 0x000000, { 1600, 1200, 4, 3, 202500, 0, false,
+				    64, 192, 304, true, 1, 3, 46, true } },
+	{ 0x37, 0xa959, 0x000000, { 1600, 1200, 4, 3, 229500, 0, false,
+				    64, 192, 304, true, 1, 3, 46, true } },
+	{ 0x38, 0x0000, 0x000000, { 1600, 1200, 4, 3, 268250, 1, false,
+				    48, 32, 80, true, 3, 4, 64, false } },
+
+	{ 0x39, 0x0000, 0x0c2821, { 1680, 1050, 16, 10, 119000, 1, false,
+				    48, 32, 80, true, 3, 6, 21, false } },
+	{ 0x3a, 0xb300, 0x0c2828, { 1680, 1050, 16, 10, 146250, 0, false,
+				    104, 176, 280, false, 3, 6, 30, true } },
+	{ 0x3b, 0xb30f, 0x0c2844, { 1680, 1050, 16, 10, 187000, 0, false,
+				    120, 176, 296, false, 3, 6, 40, true } },
+	{ 0x3c, 0xb319, 0x0c2868, { 1680, 1050, 16, 10, 214750, 0, false,
+				    128, 176, 304, false, 3, 6, 46, true } },
+	{ 0x3d, 0x0000, 0x000000, { 1680, 1050, 16, 10, 245500, 1, false,
+				    48, 32, 80, true, 3, 6, 53, false } },
+
+	{ 0x3e, 0xc140, 0x000000, { 1792, 1344, 4, 3, 204750, 0, false,
+				    128, 200, 328, false, 1, 3, 46, true } },
+	{ 0x3f, 0xc14f, 0x000000, { 1792, 1344, 4, 3, 261000, 0, false,
+				    96, 216, 352, false, 1, 3, 69, true } },
+	{ 0x40, 0x0000, 0x000000, { 1792, 1344, 4, 3, 333250, 1, false,
+				    48, 32, 80, true, 3, 4, 72, false } },
+
+	{ 0x41, 0xc940, 0x000000, { 1856, 1392, 4, 3, 218250, 0, false,
+				    96, 224, 352, false, 1, 3, 43, true } },
+	{ 0x42, 0xc94f, 0x000000, { 1856, 1392, 4, 3, 288000, 0, false,
+				    128, 224, 352, false, 1, 3, 104, true } },
+	{ 0x43, 0x0000, 0x000000, { 1856, 1392, 4, 3, 356500, 1, false,
+				    48, 32, 80, true, 3, 4, 74, false } },
+
+	{ 0x52, 0xd1c0, 0x000000, { 1920, 1080, 16, 9, 148500, 0, false,
+				    88, 44, 148, true, 4, 5, 36, true } },
+
+	{ 0x44, 0x0000, 0x572821, { 1920, 1200, 16, 10, 154000, 1, false,
+				    48, 32, 80, true, 3, 6, 26, false } },
+	{ 0x45, 0xd100, 0x572828, { 1920, 1200, 16, 10, 193250, 0, false,
+				    136, 200, 336, false, 3, 6, 36, true } },
+	{ 0x46, 0xd10f, 0x572844, { 1920, 1200, 16, 10, 245250, 0, false,
+				    136, 208, 344, false, 3, 6, 46, true } },
+	{ 0x47, 0xd119, 0x572862, { 1920, 1200, 16, 10, 281250, 0, false,
+				    144, 208, 352, false, 3, 6, 53, true } },
+	{ 0x48, 0x0000, 0x000000, { 1920, 1200, 16, 10, 317000, 1, false,
+				    48, 32, 80, true, 3, 6, 62, false } },
+
+	{ 0x49, 0xd140, 0x000000, { 1920, 1440, 4, 3, 234000, 0, false,
+				    128, 208, 344, false, 1, 3, 56, true } },
+	{ 0x4a, 0xd14f, 0x000000, { 1920, 1440, 4, 3, 297000, 0, false,
+				    144, 224, 352, false, 1, 3, 56, true } },
+	{ 0x4b, 0x0000, 0x000000, { 1920, 1440, 4, 3, 380500, 1, false,
+				    48, 32, 80, true, 2, 3, 78, false } },
+
+	{ 0x54, 0xe1c0, 0x000000, { 2048, 1152, 16, 9, 162000, 1, false,
+				    26, 80, 96, true, 1, 3, 44, true } },
+
+	{ 0x4c, 0x0000, 0x1f3821, { 2560, 1600, 16, 10, 268500, 1, false,
+				    48, 32, 80, true, 3, 6, 37, false } },
+	{ 0x4d, 0x0000, 0x1f3828, { 2560, 1600, 16, 10, 348500, 0, false,
+				    192, 280, 472, false, 3, 6, 49, true } },
+	{ 0x4e, 0x0000, 0x1f3844, { 2560, 1600, 16, 10, 443250, 0, false,
+				    208, 280, 488, false, 3, 6, 63, true } },
+	{ 0x4f, 0x0000, 0x1f3862, { 2560, 1600, 16, 10, 505250, 0, false,
+				    208, 280, 488, false, 3, 6, 73, true } },
+	{ 0x50, 0x0000, 0x000000, { 2560, 1600, 16, 10, 552750, 1, false,
+				    48, 32, 80, true, 3, 6, 85, false } },
+
+	{ 0x57, 0x0000, 0x000000, { 4096, 2160, 256, 135, 556744, 1, false,
+				    8, 32, 40, true, 48, 8, 6, false } },
+	{ 0x58, 0x0000, 0x000000, { 4096, 2160, 256, 135, 556188, 1, false,
+				    8, 32, 40, true, 48, 8, 6, false } },
+};
+
+// The timings for the IBM/Apple modes are copied from the linux
+// kernel timings in drivers/gpu/drm/drm_edid.c, except for the
+// 1152x870 Apple format, which is copied from
+// drivers/video/fbdev/macmodes.c since the drm_edid.c version
+// describes a 1152x864 format.
+static const struct {
+	unsigned dmt_id;
+	struct timings t;
+	const char *type;
+} established_timings12[] = {
+	/* 0x23 bit 7 - 0 */
+	{ 0x00, { 720, 400, 9, 5, 28320, 0, false,
+	          18, 108, 54, false, 21, 2, 26, true }, "IBM" },
+	{ 0x00, { 720, 400, 9, 5, 35500, 0, false,
+	          18, 108, 54, false, 12, 2, 35, true }, "IBM" },
+	{ 0x04 },
+	{ 0x00, { 640, 480, 4, 3, 30240, 0, false,
+	          64, 64, 96, false, 3, 3, 39, false }, "Apple" },
+	{ 0x05 },
+	{ 0x06 },
+	{ 0x08 },
+	{ 0x09 },
+	/* 0x24 bit 7 - 0 */
+	{ 0x0a },
+	{ 0x0b },
+	{ 0x00, { 832, 624, 4, 3, 57284, 0, false,
+	          32, 64, 224, false, 1, 3, 39, false }, "Apple" },
+	{ 0x0f },
+	{ 0x10 },
+	{ 0x11 },
+	{ 0x12 },
+	{ 0x24 },
+	/* 0x25 bit 7 */
+	{ 0x00, { 1152, 870, 192, 145, 100000, 0, false,
+	          48, 128, 128, true, 3, 3, 39, true }, "Apple" },
+};
+
+// The bits in the Established Timings III map to DMT timings,
+// this array has the DMT IDs.
+static const unsigned char established_timings3_dmt_ids[] = {
+	/* 0x06 bit 7 - 0 */
+	0x01, // 640x350@85
+	0x02, // 640x400@85
+	0x03, // 720x400@85
+	0x07, // 640x480@85
+	0x0e, // 848x480@60
+	0x0c, // 800x600@85
+	0x13, // 1024x768@85
+	0x15, // 1152x864@75
+	/* 0x07 bit 7 - 0 */
+	0x16, // 1280x768@60 RB
+	0x17, // 1280x768@60
+	0x18, // 1280x768@75
+	0x19, // 1280x768@85
+	0x20, // 1280x960@60
+	0x21, // 1280x960@85
+	0x23, // 1280x1024@60
+	0x25, // 1280x1024@85
+	/* 0x08 bit 7 - 0 */
+	0x27, // 1360x768@60
+	0x2e, // 1440x900@60 RB
+	0x2f, // 1440x900@60
+	0x30, // 1440x900@75
+	0x31, // 1440x900@85
+	0x29, // 1400x1050@60 RB
+	0x2a, // 1400x1050@60
+	0x2b, // 1400x1050@75
+	/* 0x09 bit 7 - 0 */
+	0x2c, // 1400x1050@85
+	0x39, // 1680x1050@60 RB
+	0x3a, // 1680x1050@60
+	0x3b, // 1680x1050@75
+	0x3c, // 1680x1050@85
+	0x33, // 1600x1200@60
+	0x34, // 1600x1200@65
+	0x35, // 1600x1200@70
+	/* 0x0a bit 7 - 0 */
+	0x36, // 1600x1200@75
+	0x37, // 1600x1200@85
+	0x3e, // 1792x1344@60
+	0x3f, // 1792x1344@75
+	0x41, // 1856x1392@60
+	0x42, // 1856x1392@75
+	0x44, // 1920x1200@60 RB
+	0x45, // 1920x1200@60
+	/* 0x0b bit 7 - 4 */
+	0x46, // 1920x1200@75
+	0x47, // 1920x1200@85
+	0x49, // 1920x1440@60
+	0x4a, // 1920x1440@75
+};
+
+const struct timings *find_dmt_id(unsigned char dmt_id)
+{
+	unsigned i;
+
+	for (i = 0; i < ARRAY_SIZE(dmt_timings); i++)
+		if (dmt_timings[i].dmt_id == dmt_id)
+			return &dmt_timings[i].t;
+	return NULL;
+}
+
+static const struct timings *find_std_id(unsigned short std_id, unsigned char &dmt_id)
+{
+	unsigned i;
+
+	for (i = 0; i < ARRAY_SIZE(dmt_timings); i++)
+		if (dmt_timings[i].std_id == std_id) {
+			dmt_id = dmt_timings[i].dmt_id;
+			return &dmt_timings[i].t;
+		}
+	return NULL;
+}
+
+void edid_state::list_established_timings()
+{
+	printf("Established Timings I & II, 'Byte' is the EDID address:\n\n");
+	for (unsigned i = 0; i < ARRAY_SIZE(established_timings12); i++) {
+		unsigned char dmt_id = established_timings12[i].dmt_id;
+		const struct timings *t;
+		char type[16];
+
+		if (dmt_id) {
+			sprintf(type, "DMT 0x%02x", dmt_id);
+			t = find_dmt_id(dmt_id);
+		} else {
+			t = &established_timings12[i].t;
+			sprintf(type, "%-8s", established_timings12[i].type);
+		}
+		printf("Byte 0x%02x, Bit %u: ", 0x23 + i / 8, 7 - i % 8);
+		print_timings("", t, type, "", false, false);
+	}
+	printf("\nEstablished timings III, 'Byte' is the offset from the start of the descriptor:\n\n");
+	for (unsigned i = 0; i < ARRAY_SIZE(established_timings3_dmt_ids); i++) {
+		unsigned char dmt_id = established_timings3_dmt_ids[i];
+		char type[16];
+
+		sprintf(type, "DMT 0x%02x", dmt_id);
+		printf("Byte 0x%02x, Bit %u: ", 6 + i / 8, 7 - i % 8);
+		print_timings("", find_dmt_id(dmt_id), type, "", false, false);
+	}
+}
+
+const struct timings *close_match_to_dmt(const timings &t, unsigned &dmt)
+{
+	for (unsigned i = 0; i < ARRAY_SIZE(dmt_timings); i++) {
+		if (timings_close_match(t, dmt_timings[i].t)) {
+			dmt = dmt_timings[i].dmt_id;
+			return &dmt_timings[i].t;
+		}
+	}
+	dmt = 0;
+	return NULL;
+}
+
+void edid_state::list_dmts()
+{
+	char type[16];
+
+	for (unsigned i = 0; i < ARRAY_SIZE(dmt_timings); i++) {
+		sprintf(type, "DMT 0x%02x", dmt_timings[i].dmt_id);
+		std::string flags;
+		if (dmt_timings[i].std_id)
+			flags += std::string("STD: ") +
+				utohex(dmt_timings[i].std_id >> 8) + " " +
+				utohex(dmt_timings[i].std_id & 0xff);
+		if (dmt_timings[i].cvt_id)
+			add_str(flags, std::string("CVT: ") +
+				utohex(dmt_timings[i].cvt_id >> 16) + " " +
+				utohex((dmt_timings[i].cvt_id >> 8) & 0xff) + " " +
+				utohex(dmt_timings[i].cvt_id & 0xff));
+		print_timings("", &dmt_timings[i].t, type, flags.c_str(), false, false);
+	}
+}
+
+void edid_state::detailed_cvt_descriptor(const char *prefix, const unsigned char *x, bool first)
+{
+	static const unsigned char empty[3] = { 0, 0, 0 };
+	struct timings cvt_t = {};
+	unsigned char preferred;
+
+	if (!first && !memcmp(x, empty, 3))
+		return;
+
+	cvt_t.vact = x[0];
+	if (!cvt_t.vact)
+		fail("CVT byte 0 is 0, which is a reserved value.\n");
+	cvt_t.vact |= (x[1] & 0xf0) << 4;
+	cvt_t.vact++;
+	cvt_t.vact *= 2;
+
+	switch (x[1] & 0x0c) {
+	case 0x00:
+	default: /* avoids 'width/ratio may be used uninitialized' warnings */
+		cvt_t.hratio = 4;
+		cvt_t.vratio = 3;
+		break;
+	case 0x04:
+		cvt_t.hratio = 16;
+		cvt_t.vratio = 9;
+		break;
+	case 0x08:
+		cvt_t.hratio = 16;
+		cvt_t.vratio = 10;
+		break;
+	case 0x0c:
+		cvt_t.hratio = 15;
+		cvt_t.vratio = 9;
+		break;
+	}
+	cvt_t.hact = 8 * (((cvt_t.vact * cvt_t.hratio) / cvt_t.vratio) / 8);
+
+	if (x[1] & 0x03)
+		fail("Reserved bits of CVT byte 1 are non-zero.\n");
+	if (x[2] & 0x80)
+		fail("Reserved bit of CVT byte 2 is non-zero.\n");
+	if (!(x[2] & 0x1f))
+		fail("CVT byte 2 does not support any vertical rates.\n");
+	preferred = (x[2] & 0x60) >> 5;
+	if (preferred == 1 && (x[2] & 0x01))
+		preferred = 4;
+	if (!(x[2] & (1 << (4 - preferred))))
+		fail("The preferred CVT Vertical Rate is not supported.\n");
+
+	static const char *s_pref = "preferred vertical rate";
+
+	if (x[2] & 0x10) {
+		edid_cvt_mode(50, cvt_t);
+		print_timings(prefix, &cvt_t, "CVT", preferred == 0 ? s_pref : "");
+	}
+	if (x[2] & 0x08) {
+		edid_cvt_mode(60, cvt_t);
+		print_timings(prefix, &cvt_t, "CVT", preferred == 1 ? s_pref : "");
+	}
+	if (x[2] & 0x04) {
+		edid_cvt_mode(75, cvt_t);
+		print_timings(prefix, &cvt_t, "CVT", preferred == 2 ? s_pref : "");
+	}
+	if (x[2] & 0x02) {
+		edid_cvt_mode(85, cvt_t);
+		print_timings(prefix, &cvt_t, "CVT", preferred == 3 ? s_pref : "");
+	}
+	if (x[2] & 0x01) {
+		cvt_t.rb = RB_CVT_V1;
+		edid_cvt_mode(60, cvt_t);
+		print_timings(prefix, &cvt_t, "CVT", preferred == 4 ? s_pref : "");
+	}
+}
+
+/* extract a string from a detailed subblock, checking for termination */
+char *extract_string(const unsigned char *x, unsigned len)
+{
+	static char s[EDID_PAGE_SIZE];
+	int seen_newline = 0;
+	unsigned i;
+
+	memset(s, 0, sizeof(s));
+
+	for (i = 0; i < len; i++) {
+		if (isgraph(x[i])) {
+			s[i] = x[i];
+		} else if (!seen_newline) {
+			if (x[i] == 0x0a) {
+				seen_newline = 1;
+				if (!i)
+					fail("Empty string.\n");
+				else if (s[i - 1] == 0x20)
+					fail("One or more trailing spaces.\n");
+			} else if (x[i] == 0x20) {
+				s[i] = x[i];
+			} else {
+				fail("Non-printable character.\n");
+				return s;
+			}
+		} else if (x[i] != 0x20) {
+			fail("Non-space after newline.\n");
+			return s;
+		}
+	}
+	/* Does the string end with a space? */
+	if (!seen_newline && s[len - 1] == 0x20)
+		fail("One or more trailing spaces.\n");
+
+	return s;
+}
+
+void edid_state::print_standard_timing(const char *prefix, unsigned char b1, unsigned char b2,
+				       bool gtf_only, bool show_both)
+{
+	const struct timings *t;
+	struct timings formula = {};
+	unsigned hratio, vratio;
+	unsigned hact, vact, refresh;
+	unsigned char dmt_id = 0;
+
+	if (b1 <= 0x01) {
+		if (b1 != 0x01 || b2 != 0x01)
+			fail("Use 0x0101 as the invalid Standard Timings code, not 0x%02x%02x.\n", b1, b2);
+		return;
+	}
+
+	t = find_std_id((b1 << 8) | b2, dmt_id);
+	if (t) {
+		char type[16];
+		sprintf(type, "DMT 0x%02x", dmt_id);
+		print_timings(prefix, t, type);
+		return;
+	}
+	hact = (b1 + 31) * 8;
+	switch ((b2 >> 6) & 0x3) {
+	case 0x00:
+		if (gtf_only || show_both || base.edid_minor >= 3) {
+			hratio = 16;
+			vratio = 10;
+		} else {
+			hratio = 1;
+			vratio = 1;
+		}
+		break;
+	case 0x01:
+		hratio = 4;
+		vratio = 3;
+		break;
+	case 0x02:
+		hratio = 5;
+		vratio = 4;
+		break;
+	case 0x03:
+		hratio = 16;
+		vratio = 9;
+		break;
+	}
+	vact = (double)hact * vratio / hratio;
+	vact = 8 * ((vact + 7) / 8);
+	refresh = (b2 & 0x3f) + 60;
+
+	formula.hact = hact;
+	formula.vact = vact;
+	formula.hratio = hratio;
+	formula.vratio = vratio;
+
+	if (!gtf_only && (show_both || base.edid_minor >= 4)) {
+		if (show_both || base.supports_cvt) {
+			edid_cvt_mode(refresh, formula);
+			print_timings(prefix, &formula, "CVT     ",
+				      show_both ? "" : "EDID 1.4 source");
+		}
+		/*
+		 * An EDID 1.3 source will assume GTF, so both GTF and CVT
+		 * have to be supported.
+		 */
+		edid_gtf_mode(refresh, formula);
+		if (base.supports_cvt)
+			print_timings(prefix, &formula, "GTF     ", "EDID 1.3 source");
+		else
+			print_timings(prefix, &formula, "GTF     ");
+	} else if (gtf_only || base.edid_minor >= 2) {
+		edid_gtf_mode(refresh, formula);
+		print_timings(prefix, &formula, "GTF     ");
+	} else {
+		printf("%sUnknown : %5ux%-5u %3u.000 Hz %3u:%u\n",
+		       prefix, hact, vact, refresh, hratio, vratio);
+		min_vert_freq_hz = min(min_vert_freq_hz, refresh);
+		max_vert_freq_hz = max(max_vert_freq_hz, refresh);
+	}
+}
+
+void edid_state::detailed_display_range_limits(const unsigned char *x)
+{
+	int h_max_offset = 0, h_min_offset = 0;
+	int v_max_offset = 0, v_min_offset = 0;
+	int is_cvt = 0;
+	bool has_sec_gtf = false;
+	std::string range_class;
+
+	data_block = "Display Range Limits";
+	printf("  %s:\n", data_block.c_str());
+	base.has_display_range_descriptor = 1;
+
+	if (base.edid_minor >= 4) {
+		if (x[4] & 0x02) {
+			v_max_offset = 255;
+			if (x[4] & 0x01) {
+				v_min_offset = 255;
+			}
+		}
+		if (x[4] & 0x08) {
+			h_max_offset = 255;
+			if (x[4] & 0x04) {
+				h_min_offset = 255;
+			}
+		}
+	}
+
+	/*
+	 * despite the values, this is not a bitfield.
+	 */
+	switch (x[10]) {
+	case 0x00: /* default gtf */
+		range_class = "GTF";
+		if (base.edid_minor >= 4 && !base.supports_continuous_freq)
+			fail("GTF can't be combined with non-continuous frequencies.\n");
+		if (base.edid_minor >= 4)
+			warn("GTF support is deprecated in EDID 1.4.\n");
+		break;
+	case 0x01: /* range limits only */
+		range_class = "Bare Limits";
+		if (base.edid_minor < 4)
+			fail("'%s' is not allowed for EDID < 1.4.\n", range_class.c_str());
+		break;
+	case 0x02: /* secondary gtf curve */
+		range_class = "Secondary GTF";
+		if (base.edid_minor >= 4 && !base.supports_continuous_freq)
+			fail("GTF can't be combined with non-continuous frequencies.\n");
+		if (base.edid_minor >= 4)
+			warn("GTF support is deprecated in EDID 1.4.\n");
+		has_sec_gtf = true;
+		break;
+	case 0x04: /* cvt */
+		range_class = "CVT";
+		is_cvt = 1;
+		if (base.edid_minor < 4)
+			fail("'%s' is not allowed for EDID < 1.4.\n", range_class.c_str());
+		else if (!base.supports_continuous_freq)
+			fail("CVT can't be combined with non-continuous frequencies.\n");
+		break;
+	default: /* invalid */
+		fail("Unknown range class (0x%02x).\n", x[10]);
+		range_class = std::string("Unknown (") + utohex(x[10]) + ")";
+		break;
+	}
+
+	if (x[5] + v_min_offset > x[6] + v_max_offset)
+		fail("Min vertical rate > max vertical rate.\n");
+	base.min_display_vert_freq_hz = x[5] + v_min_offset;
+	base.max_display_vert_freq_hz = x[6] + v_max_offset;
+	if (x[7] + h_min_offset > x[8] + h_max_offset)
+		fail("Min horizontal freq > max horizontal freq.\n");
+	base.min_display_hor_freq_hz = (x[7] + h_min_offset) * 1000;
+	base.max_display_hor_freq_hz = (x[8] + h_max_offset) * 1000;
+	printf("    Monitor ranges (%s): %d-%d Hz V, %d-%d kHz H",
+	       range_class.c_str(),
+	       x[5] + v_min_offset, x[6] + v_max_offset,
+	       x[7] + h_min_offset, x[8] + h_max_offset);
+
+	// For EDID 1.3 the horizontal frequency maxes out at 255 kHz.
+	// So to avoid false range-check warnings due to this limitation,
+	// just double the max_display_hor_freq_hz in this case.
+	if (base.edid_minor < 4 && x[8] == 0xff)
+		base.max_display_hor_freq_hz *= 2;
+
+	// For EDID 1.3 the vertical frequency maxes out at 255 Hz.
+	// So to avoid false range-check warnings due to this limitation,
+	// just double the max_display_vert_freq_hz in this case.
+	if (base.edid_minor < 4 && x[6] == 0xff)
+		base.max_display_vert_freq_hz *= 2;
+
+	if (x[9]) {
+		base.max_display_pixclk_khz = x[9] * 10000;
+		printf(", max dotclock %d MHz\n", x[9] * 10);
+	} else {
+		if (base.edid_minor >= 4)
+			fail("EDID 1.4 block does not set max dotclock.\n");
+		printf("\n");
+	}
+
+	if (has_sec_gtf) {
+		if (x[11])
+			fail("Byte 11 is 0x%02x instead of 0x00.\n", x[11]);
+		if (memchk(x + 12, 6)) {
+			fail("Zeroed Secondary Curve Block.\n");
+		} else {
+			printf("    GTF Secondary Curve Block:\n");
+			printf("      Start frequency: %u kHz\n", x[12] * 2);
+			printf("      C: %.1f%%\n", x[13] / 2.0);
+			printf("      M: %u%%/kHz\n", (x[15] << 8) | x[14]);
+			printf("      K: %u\n", x[16]);
+			printf("      J: %.1f%%\n", x[17] / 2.0);
+		}
+	} else if (is_cvt) {
+		int max_h_pixels = 0;
+
+		printf("    CVT version %d.%d\n", (x[11] & 0xf0) >> 4, x[11] & 0x0f);
+
+		if (x[12] & 0xfc) {
+			unsigned raw_offset = (x[12] & 0xfc) >> 2;
+
+			printf("    Real max dotclock: %.2f MHz\n",
+			       (x[9] * 10) - (raw_offset * 0.25));
+			if (raw_offset >= 40)
+				warn("CVT block corrects dotclock by more than 9.75 MHz.\n");
+		}
+
+		max_h_pixels = x[12] & 0x03;
+		max_h_pixels <<= 8;
+		max_h_pixels |= x[13];
+		max_h_pixels *= 8;
+		if (max_h_pixels)
+			printf("    Max active pixels per line: %d\n", max_h_pixels);
+
+		printf("    Supported aspect ratios:%s%s%s%s%s\n",
+		       x[14] & 0x80 ? " 4:3" : "",
+		       x[14] & 0x40 ? " 16:9" : "",
+		       x[14] & 0x20 ? " 16:10" : "",
+		       x[14] & 0x10 ? " 5:4" : "",
+		       x[14] & 0x08 ? " 15:9" : "");
+		if (x[14] & 0x07)
+			fail("Reserved bits of byte 14 are non-zero.\n");
+
+		printf("    Preferred aspect ratio: ");
+		switch ((x[15] & 0xe0) >> 5) {
+		case 0x00:
+			printf("4:3");
+			break;
+		case 0x01:
+			printf("16:9");
+			break;
+		case 0x02:
+			printf("16:10");
+			break;
+		case 0x03:
+			printf("5:4");
+			break;
+		case 0x04:
+			printf("15:9");
+			break;
+		default:
+			printf("Unknown (0x%02x)", (x[15] & 0xe0) >> 5);
+			fail("Invalid preferred aspect ratio 0x%02x.\n",
+			     (x[15] & 0xe0) >> 5);
+			break;
+		}
+		printf("\n");
+
+		if (x[15] & 0x08)
+			printf("    Supports CVT standard blanking\n");
+		if (x[15] & 0x10)
+			printf("    Supports CVT reduced blanking\n");
+
+		if (x[15] & 0x07)
+			fail("Reserved bits of byte 15 are non-zero.\n");
+
+		if (x[16] & 0xf0) {
+			printf("    Supported display scaling:\n");
+			if (x[16] & 0x80)
+				printf("      Horizontal shrink\n");
+			if (x[16] & 0x40)
+				printf("      Horizontal stretch\n");
+			if (x[16] & 0x20)
+				printf("      Vertical shrink\n");
+			if (x[16] & 0x10)
+				printf("      Vertical stretch\n");
+		}
+
+		if (x[16] & 0x0f)
+			fail("Reserved bits of byte 16 are non-zero.\n");
+
+		if (x[17])
+			printf("    Preferred vertical refresh: %d Hz\n", x[17]);
+		else
+			warn("CVT block does not set preferred refresh rate.\n");
+	} else {
+		if (x[11] != 0x0a)
+			fail("Byte 11 is 0x%02x instead of 0x0a.\n", x[11]);
+		for (unsigned i = 12; i <= 17; i++) {
+			if (x[i] != 0x20) {
+				fail("Bytes 12-17 must be 0x20.\n");
+				break;
+			}
+		}
+	}
+}
+
+void edid_state::detailed_epi(const unsigned char *x)
+{
+	data_block = "EPI Descriptor";
+	printf("    %s:\n", data_block.c_str());
+
+	unsigned v = x[5] & 0x07;
+
+	printf("      Bits per pixel: %u\n", 18 + v * 6);
+	if (v > 2)
+		fail("Invalid bits per pixel.\n");
+	v = (x[5] & 0x18) >> 3;
+	printf("      Pixels per clock: %u\n", 1 << v);
+	if (v > 2)
+		fail("Invalid pixels per clock.\n");
+	v = (x[5] & 0x60) >> 5;
+	printf("      Data color mapping: %sconventional\n", v ? "non-" : "");
+	if (v > 1)
+		fail("Unknown data color mapping (0x%02x).\n", v);
+	if (x[5] & 0x80)
+		fail("Non-zero reserved field in byte 5.\n");
+
+	v = x[6] & 0x0f;
+	printf("      Interface type: ");
+	switch (v) {
+	case 0x00: printf("LVDS TFT\n"); break;
+	case 0x01: printf("monoSTN 4/8 Bit\n"); break;
+	case 0x02: printf("colorSTN 8/16 Bit\n"); break;
+	case 0x03: printf("18 Bit TFT\n"); break;
+	case 0x04: printf("24 Bit TFT\n"); break;
+	case 0x05: printf("TMDS\n"); break;
+	default:
+		   printf("Unknown (0x%02x)\n", v);
+		   fail("Invalid interface type 0x%02x.\n", v);
+		   break;
+	}
+	printf("      DE polarity: DE %s active\n",
+	       (x[6] & 0x10) ? "low" : "high");
+	printf("      FPSCLK polarity: FPSCLK %sinverted\n",
+	       (x[6] & 0x20) ? "" : "not ");
+	if (x[6] & 0xc0)
+		fail("Non-zero reserved field in byte 6.\n");
+
+	printf("      Vertical display mode: %s\n",
+	       (x[7] & 0x01) ? "Up/Down reverse mode" : "normal");
+	printf("      Horizontal display mode: %s\n",
+	       (x[7] & 0x02) ? "Left/Right reverse mode" : "normal");
+	if (x[7] & 0xfc)
+		fail("Non-zero reserved field in byte 7.\n");
+
+	v = x[8] & 0x0f;
+	printf("      Total power on sequencing delay: ");
+	if (v)
+		printf("%u ms\n", v * 10);
+	else
+		printf("VGA controller default\n");
+	v = (x[8] & 0xf0) >> 4;
+	printf("      Total power off sequencing delay: ");
+	if (v)
+		printf("%u ms\n", v * 10);
+	else
+		printf("VGA controller default\n");
+
+	v = x[9] & 0x0f;
+	printf("      Contrast power on sequencing delay: ");
+	if (v)
+		printf("%u ms\n", v * 10);
+	else
+		printf("VGA controller default\n");
+	v = (x[9] & 0xf0) >> 4;
+	printf("      Contrast power off sequencing delay: ");
+	if (v)
+		printf("%u ms\n", v * 10);
+	else
+		printf("VGA controller default\n");
+
+	v = x[10] & 0x2f;
+	const char *s = (x[10] & 0x80) ? "" : " (ignored)";
+
+	printf("      Backlight brightness control: %u steps%s\n", v, s);
+	printf("      Backlight enable at boot: %s%s\n",
+	       (x[10] & 0x40) ? "off" : "on", s);
+	printf("      Backlight control enable: %s\n",
+	       (x[10] & 0x80) ? "enabled" : "disabled");
+
+	v = x[11] & 0x2f;
+	s = (x[11] & 0x80) ? "" : " (ignored)";
+
+	printf("      Contrast voltable control: %u steps%s\n", v, s);
+	if (x[11] & 0x40)
+		fail("Non-zero reserved field in byte 11.\n");
+	printf("      Contrast control enable: %s\n",
+	       (x[11] & 0x80) ? "enabled" : "disabled");
+
+	if (x[12] || x[13] || x[14] || x[15] || x[16])
+		fail("Non-zero values in reserved bytes 12-16.\n");
+
+	printf("      EPI Version: %u.%u\n", (x[17] & 0xf0) >> 4, x[17] & 0x0f);
+}
+
+void edid_state::detailed_timings(const char *prefix, const unsigned char *x,
+				  bool base_or_cta)
+{
+	struct timings t = {};
+	unsigned hbl, vbl;
+	std::string s_sync, s_flags;
+
+	// Only count DTDs in base block 0 or CTA-861 extension blocks
+	if (base_or_cta)
+		base.dtd_cnt++;
+	data_block = "Detailed Timing Descriptor #" + std::to_string(base.dtd_cnt);
+	t.pixclk_khz = (x[0] + (x[1] << 8)) * 10;
+	if (t.pixclk_khz < 10000) {
+		printf("%sDetailed mode: ", prefix);
+		hex_block("", x, 18, true, 18);
+		if (!t.pixclk_khz)
+			fail("First two bytes are 0, invalid data.\n");
+		else
+			fail("Pixelclock < 10 MHz, assuming invalid data 0x%02x 0x%02x.\n",
+			     x[0], x[1]);
+		return;
+	}
+
+	/*
+	 * If the borders are non-zero, then it is unclear how to interpret
+	 * the DTD blanking parameters.
+	 *
+	 * According to EDID 1.3 (3.12) the Hor/Vert Blanking includes the
+	 * borders, and so does the Hor/Vert Sync Offset.
+	 *
+	 * According to EDID 1.4 (3.12) the Hor/Vert Blanking excludes the
+	 * borders, and they are also excluded from the Hor/Vert Front Porch.
+	 *
+	 * But looking at what is really done in EDIDs is that the Hor/Vert
+	 * Blanking follows EDID 1.3, but the Hor/Vert Front Porch does not
+	 * include the border.
+	 *
+	 * So hbl/vbl includes the borders, so those need to be subtracted,
+	 * but hfp/vfp is used as-is.
+	 *
+	 * In practice you really shouldn't use non-zero borders in DTDs
+	 * since clearly nobody knows how to interpret the timing.
+	 */
+	t.hact = (x[2] + ((x[4] & 0xf0) << 4));
+	t.hborder = x[15];
+	hbl = (x[3] + ((x[4] & 0x0f) << 8)) - t.hborder * 2;
+	t.hfp = (x[8] + ((x[11] & 0xc0) << 2));
+	t.hsync = (x[9] + ((x[11] & 0x30) << 4));
+	t.hbp = hbl - t.hsync - t.hfp;
+	t.vact = (x[5] + ((x[7] & 0xf0) << 4));
+	t.vborder = x[16];
+	vbl = (x[6] + ((x[7] & 0x0f) << 8)) - t.vborder * 2;
+	t.vfp = ((x[10] >> 4) + ((x[11] & 0x0c) << 2));
+	t.vsync = ((x[10] & 0x0f) + ((x[11] & 0x03) << 4));
+	t.vbp = vbl - t.vsync - t.vfp;
+
+	unsigned char flags = x[17];
+
+	if (base.has_spwg && base.detailed_block_cnt == 2)
+		flags = *(x - 1);
+
+	switch ((flags & 0x18) >> 3) {
+	case 0x00:
+		s_flags = "analog composite";
+		/* fall-through */
+	case 0x01:
+		if (s_flags.empty())
+			s_flags = "bipolar analog composite";
+		switch ((flags & 0x06) >> 1) {
+		case 0x00:
+			add_str(s_flags, "sync-on-green");
+			break;
+		case 0x01:
+			break;
+		case 0x02:
+			add_str(s_flags, "serrate, sync-on-green");
+			break;
+		case 0x03:
+			add_str(s_flags, "serrate");
+			break;
+		}
+		break;
+	case 0x02:
+		if (flags & (1 << 1))
+			t.pos_pol_hsync = true;
+		t.no_pol_vsync = true;
+		s_flags = "digital composite";
+		if (flags & (1 << 2))
+		    add_str(s_flags, "serrate");
+		break;
+	case 0x03:
+		if (flags & (1 << 1))
+			t.pos_pol_hsync = true;
+		if (flags & (1 << 2))
+			t.pos_pol_vsync = true;
+		s_sync = t.pos_pol_hsync ? "+hsync " : "-hsync ";
+		s_sync += t.pos_pol_vsync ? "+vsync " : "-vsync ";
+		if (base.has_spwg && (flags & 0x01))
+			s_flags = "DE timing only";
+		break;
+	}
+	if (flags & 0x80) {
+		t.interlaced = true;
+		t.vact *= 2;
+		/*
+		 * Check if this DTD matches VIC code 39 with special
+		 * interlaced timings.
+		 */
+		if (t.hact == 1920 && t.vact == 1080 && t.pixclk_khz == 72000 &&
+		    t.hfp == 32 && t.hsync == 168 && t.hbp == 184 && !t.hborder &&
+		    t.vfp == 23 && t.vsync == 5 && t.vbp == 57 && !t.vborder &&
+		    !base.has_spwg && cta.preparsed_has_vic[0][39] && (flags & 0x1e) == 0x1a)
+			t.even_vtotal = true;
+	}
+	switch (flags & 0x61) {
+	case 0x20:
+		add_str(s_flags, "field sequential L/R");
+		break;
+	case 0x40:
+		add_str(s_flags, "field sequential R/L");
+		break;
+	case 0x21:
+		add_str(s_flags, "interleaved right even");
+		break;
+	case 0x41:
+		add_str(s_flags, "interleaved left even");
+		break;
+	case 0x60:
+		add_str(s_flags, "four way interleaved");
+		break;
+	case 0x61:
+		add_str(s_flags, "side by side interleaved");
+		break;
+	default:
+		break;
+	}
+
+	t.hsize_mm = x[12] + ((x[14] & 0xf0) << 4);
+	t.vsize_mm = x[13] + ((x[14] & 0x0f) << 8);
+
+	calc_ratio(&t);
+
+	std::string s_type = base_or_cta ? dtd_type() : "DTD";
+	bool ok = print_timings(prefix, &t, s_type.c_str(), s_flags.c_str(), true);
+	timings_ext te(t, s_type, s_flags);
+
+	if (block_nr == 0 && base.dtd_cnt == 1) {
+		te.type = "DTD   1";
+		base.preferred_timing = te;
+		if (has_cta) {
+			cta.preferred_timings.push_back(te);
+			cta.native_timings.push_back(te);
+		}
+	}
+	if (base_or_cta)
+		cta.vec_dtds.push_back(te);
+
+	if (t.hborder || t.vborder)
+		warn("The use of non-zero borders in a DTD is not recommended.\n");
+	if ((base.max_display_width_mm && !t.hsize_mm) ||
+	    (base.max_display_height_mm && !t.vsize_mm)) {
+		fail("Mismatch of image size vs display size: image size is not set, but display size is.\n");
+	}
+	if (base.has_spwg && base.detailed_block_cnt == 2)
+		printf("%sSPWG Module Revision: %hhu\n", prefix, x[17]);
+	if (!ok) {
+		std::string s = prefix;
+
+		s += "               ";
+		hex_block(s.c_str(), x, 18, true, 18);
+	}
+}
+
+void edid_state::preparse_detailed_block(const unsigned char *x)
+{
+	if (x[0] || x[1])
+		return;
+	if (x[3] != 0xfd)
+		return;
+
+	switch (x[10]) {
+	case 0x00: /* default gtf */
+		base.supports_gtf = true;
+		break;
+	case 0x02: /* secondary gtf curve */
+		base.supports_gtf = true;
+		base.supports_sec_gtf = !memchk(x + 12, 6);
+		base.sec_gtf_start_freq = x[12] * 2;
+		base.C = x[13] / 2.0;
+		base.M = (x[15] << 8) | x[14];
+		base.K = x[16];
+		base.J = x[17] / 2.0;
+		break;
+	case 0x04: /* cvt */
+		if (base.edid_minor >= 4) {
+			/* GTF is implied if CVT is signaled */
+			base.supports_gtf = true;
+			base.supports_cvt = true;
+		}
+		break;
+	}
+}
+
+void edid_state::detailed_block(const unsigned char *x)
+{
+	static const unsigned char zero_descr[18] = { 0 };
+	unsigned cnt;
+	unsigned i;
+
+	base.detailed_block_cnt++;
+	if (x[0] || x[1]) {
+		detailed_timings("    ", x);
+		if (base.seen_non_detailed_descriptor)
+			fail("Invalid detailed timing descriptor ordering.\n");
+		return;
+	}
+
+	data_block = "Display Descriptor #" + std::to_string(base.detailed_block_cnt);
+	/* Monitor descriptor block, not detailed timing descriptor. */
+	if (x[2] != 0) {
+		/* 1.3, 3.10.3 */
+		fail("Monitor descriptor block has byte 2 nonzero (0x%02x).\n", x[2]);
+	}
+	if ((base.edid_minor < 4 || x[3] != 0xfd) && x[4] != 0x00) {
+		/* 1.3, 3.10.3 */
+		fail("Monitor descriptor block has byte 4 nonzero (0x%02x).\n", x[4]);
+	}
+
+	base.seen_non_detailed_descriptor = true;
+	if (base.edid_minor == 0)
+		fail("Has descriptor blocks other than detailed timings.\n");
+
+	if (!memcmp(x, zero_descr, sizeof(zero_descr))) {
+		data_block = "Empty Descriptor";
+		printf("    %s\n", data_block.c_str());
+		fail("Use Dummy Descriptor instead of all zeroes.\n");
+		return;
+	}
+
+	switch (x[3]) {
+	case 0x0e:
+		detailed_epi(x);
+		return;
+	case 0x10:
+		data_block = "Dummy Descriptor";
+		printf("    %s:\n", data_block.c_str());
+		for (i = 5; i < 18; i++) {
+			if (x[i]) {
+				fail("Dummy block filled with garbage.\n");
+				break;
+			}
+		}
+		return;
+	case 0xf7:
+		data_block = "Established timings III";
+		printf("    %s:\n", data_block.c_str());
+		for (i = 0; i < ARRAY_SIZE(established_timings3_dmt_ids); i++)
+			if (x[6 + i / 8] & (1 << (7 - i % 8))) {
+				unsigned char dmt_id = established_timings3_dmt_ids[i];
+				char type[16];
+
+				sprintf(type, "DMT 0x%02x", dmt_id);
+				print_timings("      ", find_dmt_id(dmt_id), type);
+			}
+		return;
+	case 0xf8:
+		data_block = "CVT 3 Byte Timing Codes";
+		printf("    %s:\n", data_block.c_str());
+		if (x[5] != 0x01) {
+			fail("Invalid version number %u.\n", x[5]);
+			return;
+		}
+		for (i = 0; i < 4; i++)
+			detailed_cvt_descriptor("      ", x + 6 + (i * 3), !i);
+		return;
+	case 0xf9:
+		data_block = "Display Color Management Data";
+		printf("    %s:\n", data_block.c_str());
+		printf("      Version : %d\n", x[5]);
+		printf("      Red a3  : %.2f\n", (short)(x[6] | (x[7] << 8)) / 100.0);
+		printf("      Red a2  : %.2f\n", (short)(x[8] | (x[9] << 8)) / 100.0);
+		printf("      Green a3: %.2f\n", (short)(x[10] | (x[11] << 8)) / 100.0);
+		printf("      Green a2: %.2f\n", (short)(x[12] | (x[13] << 8)) / 100.0);
+		printf("      Blue a3 : %.2f\n", (short)(x[14] | (x[15] << 8)) / 100.0);
+		printf("      Blue a2 : %.2f\n", (short)(x[16] | (x[17] << 8)) / 100.0);
+		return;
+	case 0xfa:
+		data_block = "Standard Timing Identifications";
+		printf("    %s:\n", data_block.c_str());
+		for (cnt = i = 0; i < 6; i++) {
+			if (x[5 + i * 2] != 0x01 || x[5 + i * 2 + 1] != 0x01)
+				cnt++;
+			print_standard_timing("      ", x[5 + i * 2], x[5 + i * 2 + 1]);
+		}
+		if (!cnt)
+			warn("%s block without any timings.\n", data_block.c_str());
+		return;
+	case 0xfb: {
+		unsigned w_x, w_y;
+		unsigned gamma;
+
+		data_block = "Color Point Data";
+		printf("    %s:\n", data_block.c_str());
+		w_x = (x[7] << 2) | ((x[6] >> 2) & 3);
+		w_y = (x[8] << 2) | (x[6] & 3);
+		gamma = x[9];
+		printf("      Index: %u White: 0.%04u, 0.%04u", x[5],
+		       (w_x * 10000) / 1024, (w_y * 10000) / 1024);
+		if (gamma == 0xff)
+			printf(" Gamma: is defined in an extension block");
+		else
+			printf(" Gamma: %.2f", ((gamma + 100.0) / 100.0));
+		printf("\n");
+		if (x[10] == 0)
+			return;
+		w_x = (x[12] << 2) | ((x[11] >> 2) & 3);
+		w_y = (x[13] << 2) | (x[11] & 3);
+		gamma = x[14];
+		printf("      Index: %u White: 0.%04u, 0.%04u", x[10],
+		       (w_x * 10000) / 1024, (w_y * 10000) / 1024);
+		if (gamma == 0xff)
+			printf(" Gamma: is defined in an extension block");
+		else
+			printf(" Gamma: %.2f", ((gamma + 100.0) / 100.0));
+		printf("\n");
+		return;
+	}
+	case 0xfc:
+		data_block = "Display Product Name";
+		base.has_name_descriptor = 1;
+		printf("    %s: '%s'\n", data_block.c_str(), extract_string(x + 5, 13));
+		return;
+	case 0xfd:
+		detailed_display_range_limits(x);
+		return;
+	case 0xfe:
+		if (!base.has_spwg || base.detailed_block_cnt < 3) {
+			data_block = "Alphanumeric Data String";
+			printf("    %s: '%s'\n", data_block.c_str(),
+			       extract_string(x + 5, 13));
+			return;
+		}
+		if (base.detailed_block_cnt == 3) {
+			char buf[6] = { 0 };
+
+			data_block = "SPWG Descriptor #3";
+			printf("    %s:\n", data_block.c_str());
+			memcpy(buf, x + 5, 5);
+			if (strlen(buf) != 5)
+				fail("Invalid PC Maker P/N length.\n");
+			printf("      SPWG PC Maker P/N: '%s'\n", buf);
+			printf("      SPWG LCD Supplier EEDID Revision: %hhu\n", x[10]);
+			printf("      SPWG Manufacturer P/N: '%s'\n", extract_string(x + 11, 7));
+		} else {
+			data_block = "SPWG Descriptor #4";
+			printf("    %s:\n", data_block.c_str());
+			printf("      SMBUS Values: 0x%02hhx 0x%02hhx 0x%02hhx 0x%02hhx"
+			       " 0x%02hhx 0x%02hhx 0x%02hhx 0x%02hhx\n",
+			       x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12]);
+			printf("      LVDS Channels: %hhu\n", x[13]);
+			printf("      Panel Self Test %sPresent\n", x[14] ? "" : "Not ");
+			if (x[15] != 0x0a || x[16] != 0x20 || x[17] != 0x20)
+				fail("Invalid trailing data.\n");
+		}
+		return;
+	case 0xff: {
+		data_block = "Display Product Serial Number";
+		char *sn = extract_string(x + 5, 13);
+		if (hide_serial_numbers)
+			printf("    %s: ...\n", data_block.c_str());
+		else
+			printf("    %s: '%s'\n", data_block.c_str(), sn);
+		base.has_serial_string = 1;
+		return;
+	}
+	default:
+		printf("    %s Display Descriptor (0x%02hhx):",
+		       x[3] <= 0x0f ? "Manufacturer-Specified" : "Unknown", x[3]);
+		hex_block(" ", x + 2, 16);
+		if (x[3] > 0x0f)
+			fail("Unknown Type 0x%02hhx.\n", x[3]);
+		return;
+	}
+}
+
+void edid_state::parse_base_block(const unsigned char *x)
+{
+	time_t the_time;
+	struct tm *ptm;
+	int analog;
+	unsigned col_x, col_y;
+	bool has_preferred_timing = false;
+
+	data_block = "EDID Structure Version & Revision";
+	printf("  %s: %hhu.%hhu\n", data_block.c_str(), x[0x12], x[0x13]);
+	if (x[0x12] == 1) {
+		base.edid_minor = x[0x13];
+		if (base.edid_minor > 4)
+			warn("Unknown EDID minor version %u, assuming 1.4 conformance.\n", base.edid_minor);
+		if (base.edid_minor < 3)
+			warn("EDID 1.%u is deprecated, do not use.\n", base.edid_minor);
+	} else {
+		fail("Unknown EDID major version.\n");
+	}
+
+	data_block = "Vendor & Product Identification";
+	printf("  %s:\n", data_block.c_str());
+	printf("    Manufacturer: %s\n    Model: %u\n",
+	       manufacturer_name(x + 0x08),
+	       (unsigned short)(x[0x0a] + (x[0x0b] << 8)));
+	base.has_serial_number = x[0x0c] || x[0x0d] || x[0x0e] || x[0x0f];
+	if (base.has_serial_number) {
+		if (hide_serial_numbers)
+			printf("    Serial Number: ...\n");
+		else
+			printf("    Serial Number: %u\n",
+			       (unsigned)(x[0x0c] + (x[0x0d] << 8) +
+					  (x[0x0e] << 16) + (x[0x0f] << 24)));
+	}
+
+	time(&the_time);
+	ptm = localtime(&the_time);
+
+	unsigned char week = x[0x10];
+	int year = 1990 + x[0x11];
+
+	if (week) {
+		if (base.edid_minor <= 3 && week == 0xff)
+			fail("EDID 1.3 does not support week 0xff.\n");
+		// The max week is 53 in EDID 1.3 and 54 in EDID 1.4.
+		// No idea why there is a difference.
+		if (base.edid_minor <= 3 && week == 54)
+			fail("EDID 1.3 does not support week 54.\n");
+		if (week != 0xff && week > 54)
+			fail("Invalid week %u of manufacture.\n", week);
+		if (week != 0xff)
+			printf("    Made in: week %hhu of %d\n", week, year);
+	}
+	if (week == 0xff)
+		printf("    Model year: %d\n", year);
+	else if (!week)
+		printf("    Made in: %d\n", year);
+	if (year - 1 > ptm->tm_year + 1900)
+		fail("The year %d is more than one year in the future.\n", year);
+
+	/* display section */
+
+	data_block = "Basic Display Parameters & Features";
+	printf("  %s:\n", data_block.c_str());
+	if (x[0x14] & 0x80) {
+		analog = 0;
+		printf("    Digital display\n");
+		if (base.edid_minor >= 4) {
+			if ((x[0x14] & 0x70) == 0x00)
+				printf("    Color depth is undefined\n");
+			else if ((x[0x14] & 0x70) == 0x70)
+				fail("Color Bit Depth set to reserved value.\n");
+			else
+				printf("    Bits per primary color channel: %u\n",
+				       ((x[0x14] & 0x70) >> 3) + 4);
+
+			printf("    ");
+			switch (x[0x14] & 0x0f) {
+			case 0x00: printf("Digital interface is not defined\n"); break;
+			case 0x01: printf("DVI interface\n"); break;
+			case 0x02: printf("HDMI-a interface\n"); break;
+			case 0x03: printf("HDMI-b interface\n"); break;
+			case 0x04: printf("MDDI interface\n"); break;
+			case 0x05: printf("DisplayPort interface\n"); break;
+			default:
+				   printf("Unknown interface: 0x%02x\n", x[0x14] & 0x0f);
+				   fail("Digital Video Interface Standard set to reserved value 0x%02x.\n", x[0x14] & 0x0f);
+				   break;
+			}
+		} else if (base.edid_minor >= 2) {
+			if (x[0x14] & 0x01) {
+				printf("    DFP 1.x compatible TMDS\n");
+			}
+			if (x[0x14] & 0x7e)
+				fail("Digital Video Interface Standard set to reserved value 0x%02x.\n", x[0x14] & 0x7e);
+		} else if (x[0x14] & 0x7f) {
+			fail("Digital Video Interface Standard set to reserved value 0x%02x.\n", x[0x14] & 0x7f);
+		}
+	} else {
+		unsigned voltage = (x[0x14] & 0x60) >> 5;
+		unsigned sync = (x[0x14] & 0x0f);
+
+		analog = 1;
+		printf("    Analog display\n");
+		printf("    Input voltage level: %s V\n",
+		       voltage == 3 ? "0.7/0.7" :
+		       voltage == 2 ? "1.0/0.4" :
+		       voltage == 1 ? "0.714/0.286" :
+		       "0.7/0.3");
+
+		if (x[0x14] & 0x10)
+			printf("    Blank-to-black setup/pedestal\n");
+		else
+			printf("    Blank level equals black level\n");
+
+		if (sync)
+			printf("    Sync:%s%s%s%s\n",
+			       sync & 0x08 ? " Separate" : "",
+			       sync & 0x04 ? " Composite" : "",
+			       sync & 0x02 ? " SyncOnGreen" : "",
+			       sync & 0x01 ? " Serration" : "");
+	}
+
+	if (x[0x15] && x[0x16]) {
+		printf("    Maximum image size: %u cm x %u cm\n", x[0x15], x[0x16]);
+		base.max_display_width_mm = x[0x15] * 10;
+		base.max_display_height_mm = x[0x16] * 10;
+		if (x[0x15] < 10 || x[0x16] < 10)
+			warn("Dubious maximum image size (%ux%u is smaller than 10x10 cm).\n",
+			     x[0x15], x[0x16]);
+	}
+	else if (base.edid_minor >= 4 && (x[0x15] || x[0x16])) {
+		if (x[0x15])
+			printf("    Aspect ratio: %.2f (landscape)\n", (x[0x15] + 99) / 100.0);
+		else
+			printf("    Aspect ratio: %.2f (portrait)\n", 100.0 / (x[0x16] + 99));
+	} else {
+		/* Either or both can be zero for 1.3 and before */
+		printf("    Image size is variable\n");
+	}
+
+	if (x[0x17] == 0xff)
+		printf("    Gamma is defined in an extension block\n");
+	else
+		printf("    Gamma: %.2f\n", ((x[0x17] + 100.0) / 100.0));
+
+	if (x[0x18] & 0xe0) {
+		printf("    DPMS levels:");
+		if (x[0x18] & 0x80) printf(" Standby");
+		if (x[0x18] & 0x40) printf(" Suspend");
+		if (x[0x18] & 0x20) printf(" Off");
+		printf("\n");
+	}
+
+	if (analog || base.edid_minor < 4) {
+		printf("    ");
+		switch (x[0x18] & 0x18) {
+		case 0x00: printf("Monochrome or grayscale display\n"); break;
+		case 0x08: printf("RGB color display\n"); break;
+		case 0x10: printf("Non-RGB color display\n"); break;
+		case 0x18: printf("Undefined display color type\n");
+		}
+	} else {
+		printf("    Supported color formats: RGB 4:4:4");
+		if (x[0x18] & 0x08)
+			printf(", YCrCb 4:4:4");
+		if (x[0x18] & 0x10)
+			printf(", YCrCb 4:2:2");
+		printf("\n");
+	}
+
+	if (x[0x18] & 0x04) {
+		/*
+		 * The sRGB chromaticities are (x, y):
+		 * red:   0.640,  0.330
+		 * green: 0.300,  0.600
+		 * blue:  0.150,  0.060
+		 * white: 0.3127, 0.3290
+		 */
+		static const unsigned char srgb_chromaticity[10] = {
+			0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26, 0x0f, 0x50, 0x54
+		};
+		printf("    Default (sRGB) color space is primary color space\n");
+		if (memcmp(x + 0x19, srgb_chromaticity, sizeof(srgb_chromaticity)))
+			fail("sRGB is signaled, but the chromaticities do not match.\n");
+	}
+	if (base.edid_minor >= 4) {
+		/* 1.4 always has a preferred timing and this bit means something else. */
+		has_preferred_timing = true;
+		base.preferred_is_also_native = x[0x18] & 0x02;
+		printf("    First detailed timing %s the native pixel format and preferred refresh rate\n",
+		       base.preferred_is_also_native ? "includes" : "does not include");
+	} else {
+		if (x[0x18] & 0x02) {
+			printf("    First detailed timing is the preferred timing\n");
+			has_preferred_timing = true;
+			// 1.3 recommends that the preferred timing corresponds to the
+			// native timing, but it is not a requirement.
+			// That said, we continue with the assumption that it actually
+			// is the native timing.
+			base.preferred_is_also_native = true;
+		} else if (base.edid_minor == 3) {
+			fail("EDID 1.3 requires that the first detailed timing is the preferred timing.\n");
+		}
+	}
+
+	if (x[0x18] & 0x01) {
+		if (base.edid_minor >= 4) {
+			base.supports_continuous_freq = true;
+			printf("    Display is continuous frequency\n");
+		} else {
+			printf("    Supports GTF timings within operating range\n");
+			base.supports_gtf = true;
+		}
+	}
+
+	data_block = "Color Characteristics";
+	printf("  %s:\n", data_block.c_str());
+	col_x = (x[0x1b] << 2) | (x[0x19] >> 6);
+	col_y = (x[0x1c] << 2) | ((x[0x19] >> 4) & 3);
+	printf("    Red  : 0.%04u, 0.%04u\n",
+	       (col_x * 10000) / 1024, (col_y * 10000) / 1024);
+	col_x = (x[0x1d] << 2) | ((x[0x19] >> 2) & 3);
+	col_y = (x[0x1e] << 2) | (x[0x19] & 3);
+	printf("    Green: 0.%04u, 0.%04u\n",
+	       (col_x * 10000) / 1024, (col_y * 10000) / 1024);
+	col_x = (x[0x1f] << 2) | (x[0x1a] >> 6);
+	col_y = (x[0x20] << 2) | ((x[0x1a] >> 4) & 3);
+	printf("    Blue : 0.%04u, 0.%04u\n",
+	       (col_x * 10000) / 1024, (col_y * 10000) / 1024);
+	col_x = (x[0x21] << 2) | ((x[0x1a] >> 2) & 3);
+	col_y = (x[0x22] << 2) | (x[0x1a] & 3);
+	printf("    White: 0.%04u, 0.%04u\n",
+	       (col_x * 10000) / 1024, (col_y * 10000) / 1024);
+
+	data_block = "Established Timings I & II";
+	if (x[0x23] || x[0x24] || x[0x25]) {
+		printf("  %s:\n", data_block.c_str());
+		for (unsigned i = 0; i < ARRAY_SIZE(established_timings12); i++) {
+			if (x[0x23 + i / 8] & (1 << (7 - i % 8))) {
+				unsigned char dmt_id = established_timings12[i].dmt_id;
+				const struct timings *t;
+				char type[16];
+
+				if (dmt_id) {
+					sprintf(type, "DMT 0x%02x", dmt_id);
+					t = find_dmt_id(dmt_id);
+				} else {
+					t = &established_timings12[i].t;
+					sprintf(type, "%-8s", established_timings12[i].type);
+				}
+				print_timings("    ", t, type);
+			}
+		}
+	} else {
+		printf("  %s: none\n", data_block.c_str());
+	}
+	base.has_640x480p60_est_timing = x[0x23] & 0x20;
+
+	/*
+	 * Need to find the Display Range Limit info before reading
+	 * the standard timings.
+	 */
+	preparse_detailed_block(x + 0x36);
+	preparse_detailed_block(x + 0x48);
+	preparse_detailed_block(x + 0x5a);
+	preparse_detailed_block(x + 0x6c);
+
+	data_block = "Standard Timings";
+	bool found = false;
+	for (unsigned i = 0; i < 8; i++) {
+		if (x[0x26 + i * 2] != 0x01 || x[0x26 + i * 2 + 1] != 0x01) {
+			found = true;
+			break;
+		}
+	}
+	if (found) {
+		printf("  %s:\n", data_block.c_str());
+		for (unsigned i = 0; i < 8; i++)
+			print_standard_timing("    ", x[0x26 + i * 2], x[0x26 + i * 2 + 1]);
+	} else {
+		printf("  %s: none\n", data_block.c_str());
+	}
+
+	/* 18 byte descriptors */
+	if (has_preferred_timing && !x[0x36] && !x[0x37])
+		fail("Missing preferred timing.\n");
+
+	/* Look for SPWG Noteboook Panel EDID data blocks */
+	if ((x[0x36] || x[0x37]) &&
+	    (x[0x48] || x[0x49]) &&
+	    !x[0x5a] && !x[0x5b] && x[0x5d] == 0xfe &&
+	    !x[0x6c] && !x[0x6d] && x[0x6f] == 0xfe &&
+	    (x[0x79] == 1 || x[0x79] == 2) && x[0x7a] <= 1)
+		base.has_spwg = true;
+
+	for (unsigned i = 0; i < (base.has_spwg ? 2 : 4); i++)
+		if (x[0x36 + i * 18] || x[0x37 + i * 18])
+			cta.preparsed_total_dtds++;
+
+	data_block = "Detailed Timing Descriptors";
+	printf("  %s:\n", data_block.c_str());
+	detailed_block(x + 0x36);
+	detailed_block(x + 0x48);
+	detailed_block(x + 0x5a);
+	detailed_block(x + 0x6c);
+	base.has_spwg = false;
+	if (!base.preferred_is_also_native) {
+		cta.native_timings.clear();
+		base.preferred_timing = timings_ext();
+	}
+
+	data_block = block;
+	if (x[0x7e])
+		printf("  Extension blocks: %u\n", x[0x7e]);
+	if (x[0x7e] + 1U != num_blocks)
+		fail("EDID specified %u extension block(s), but found %u extension block(s).\n",
+		     x[0x7e], num_blocks - 1);
+
+	block = block_name(0x00);
+	data_block.clear();
+	do_checksum("", x, EDID_PAGE_SIZE);
+	if (base.edid_minor >= 3) {
+		if (!base.has_name_descriptor)
+			fail("Missing Display Product Name.\n");
+		if ((base.edid_minor == 3 || base.supports_continuous_freq) &&
+		    !base.has_display_range_descriptor)
+			fail("Missing Display Range Limits Descriptor.\n");
+	}
+}
+
+void edid_state::check_base_block()
+{
+	data_block = "Base EDID";
+
+	/*
+	 * Allow for regular rounding of vertical and horizontal frequencies.
+	 * The spec says that the pixelclock shall be rounded up, so there is
+	 * no need to take rounding into account.
+	 */
+	if (base.has_display_range_descriptor &&
+	    (min_vert_freq_hz + 0.5 < base.min_display_vert_freq_hz ||
+	     (max_vert_freq_hz >= base.max_display_vert_freq_hz + 0.5 && base.max_display_vert_freq_hz) ||
+	     min_hor_freq_hz + 500 < base.min_display_hor_freq_hz ||
+	     (max_hor_freq_hz >= base.max_display_hor_freq_hz + 500 && base.max_display_hor_freq_hz) ||
+	     (max_pixclk_khz > base.max_display_pixclk_khz && base.max_display_pixclk_khz))) {
+		/*
+		 * Check if it is really out of range, or if it could be a rounding error.
+		 * The EDID spec is not very clear about rounding.
+		 */
+		bool out_of_range =
+			min_vert_freq_hz + 1.0 <= base.min_display_vert_freq_hz ||
+			(max_vert_freq_hz >= base.max_display_vert_freq_hz + 1.0 && base.max_display_vert_freq_hz) ||
+			min_hor_freq_hz + 1000 <= base.min_display_hor_freq_hz ||
+			(max_hor_freq_hz >= base.max_display_hor_freq_hz + 1000 && base.max_display_hor_freq_hz) ||
+			(max_pixclk_khz >= base.max_display_pixclk_khz + 10000 && base.max_display_pixclk_khz);
+
+		std::string err("Some timings are out of range of the Monitor Ranges:\n");
+		char buf[512];
+
+		if (min_vert_freq_hz + 0.5 < base.min_display_vert_freq_hz ||
+		    (max_vert_freq_hz >= base.max_display_vert_freq_hz + 0.5 && base.max_display_vert_freq_hz)) {
+			sprintf(buf, "    Vertical Freq: %.3f - %.3f Hz (Monitor: %u.000 - %u.000 Hz)\n",
+				min_vert_freq_hz, max_vert_freq_hz,
+				base.min_display_vert_freq_hz, base.max_display_vert_freq_hz);
+			err += buf;
+		}
+
+		if (min_hor_freq_hz + 500 < base.min_display_hor_freq_hz ||
+		    (max_hor_freq_hz >= base.max_display_hor_freq_hz + 500 && base.max_display_hor_freq_hz)) {
+			sprintf(buf, "    Horizontal Freq: %.3f - %.3f kHz (Monitor: %.3f - %.3f kHz)\n",
+				min_hor_freq_hz / 1000.0, max_hor_freq_hz / 1000.0,
+				base.min_display_hor_freq_hz / 1000.0, base.max_display_hor_freq_hz / 1000.0);
+			err += buf;
+		}
+
+		if (max_pixclk_khz >= base.max_display_pixclk_khz && base.max_display_pixclk_khz) {
+			sprintf(buf, "    Maximum Clock: %.3f MHz (Monitor: %.3f MHz)\n",
+				max_pixclk_khz / 1000.0, base.max_display_pixclk_khz / 1000.0);
+			err += buf;
+		}
+
+		if (!out_of_range)
+			err += "    Could be due to a Monitor Range off-by-one rounding issue\n";
+
+		/*
+		 * EDID 1.4 states (in an Errata) that explicitly defined
+		 * timings supersede the monitor range definition.
+		 */
+		msg(!out_of_range || base.edid_minor >= 4, "%s", err.c_str());
+	}
+	// The base block will only go up to 255x255 cm for the display size,
+	// so don't fail if one or more image sizes exceeds that.
+	if (!base.max_display_width_mm && !base.max_display_height_mm &&
+	    dtd_max_hsize_mm && dtd_max_vsize_mm &&
+	    dtd_max_hsize_mm <= 2559 && dtd_max_vsize_mm <= 2559) {
+		fail("The DTD image sizes all fit inside 255x255cm, but no display size was set.\n");
+	}
+	// Secondary GTF curves start at a specific frequency. Any legacy timings
+	// that have a positive hsync and negative vsync must be less than that
+	// frequency to avoid confusion.
+	if (base.supports_sec_gtf && base.max_pos_neg_hor_freq_khz >= base.sec_gtf_start_freq)
+		fail("Second GTF start frequency %u is less than the highest P/N frequency %u.\n",
+		     base.sec_gtf_start_freq, base.max_pos_neg_hor_freq_khz);
+	if (base.edid_minor == 3 && num_blocks > 2 && !block_map.saw_block_1)
+		fail("EDID 1.3 requires a Block Map Extension in Block 1 if there are more than 2 blocks in the EDID.\n");
+	if (base.edid_minor == 3 && num_blocks > 128 && !block_map.saw_block_128)
+		fail("EDID 1.3 requires a Block Map Extension in Block 128 if there are more than 128 blocks in the EDID.\n");
+	if (block_map.saw_block_128 && num_blocks > 255)
+		fail("If there is a Block Map Extension in Block 128 then the maximum number of blocks is 255.\n");
+}
diff --git a/parse-cta-block.cpp b/parse-cta-block.cpp
new file mode 100644
index 0000000..6ce8e6c
--- /dev/null
+++ b/parse-cta-block.cpp
@@ -0,0 +1,2574 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2006-2012 Red Hat, Inc.
+ * Copyright 2018-2020 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ *
+ * Author: Adam Jackson <ajax@nwnk.net>
+ * Maintainer: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+ */
+
+#include <stdio.h>
+#include <math.h>
+
+#include "edid-decode.h"
+
+static const struct timings edid_cta_modes1[] = {
+	/* VIC 1 */
+	{  640,  480,   4,   3,   25175, 0, false,   16,  96,  48, false, 10,  2,  33, false },
+	{  720,  480,   4,   3,   27000, 0, false,   16,  62,  60, false,  9,  6,  30, false },
+	{  720,  480,  16,   9,   27000, 0, false,   16,  62,  60, false,  9,  6,  30, false },
+	{ 1280,  720,  16,   9,   74250, 0, false,  110,  40, 220, true,   5,  5,  20, true  },
+	{ 1920, 1080,  16,   9,   74250, 0, true,    88,  44, 148, true,   2,  5,  15, true  },
+	{ 1440,  480,   4,   3,   27000, 0, true,    38, 124, 114, false,  4,  3,  15, false },
+	{ 1440,  480,  16,   9,   27000, 0, true,    38, 124, 114, false,  4,  3,  15, false },
+	{ 1440,  240,   4,   3,   27000, 0, false,   38, 124, 114, false,  4,  3,  15, false },
+	{ 1440,  240,  16,   9,   27000, 0, false,   38, 124, 114, false,  4,  3,  15, false },
+	{ 2880,  480,   4,   3,   54000, 0, true,    76, 248, 228, false,  4,  3,  15, false },
+	/* VIC 11 */
+	{ 2880,  480,  16,   9,   54000, 0, true,    76, 248, 228, false,  4,  3,  15, false },
+	{ 2880,  240,   4,   3,   54000, 0, false,   76, 248, 228, false,  4,  3,  15, false },
+	{ 2880,  240,  16,   9,   54000, 0, false,   76, 248, 228, false,  4,  3,  15, false },
+	{ 1440,  480,   4,   3,   54000, 0, false,   32, 124, 120, false,  9,  6,  30, false },
+	{ 1440,  480,  16,   9,   54000, 0, false,   32, 124, 120, false,  9,  6,  30, false },
+	{ 1920, 1080,  16,   9,  148500, 0, false,   88,  44, 148, true,   4,  5,  36, true  },
+	{  720,  576,   4,   3,   27000, 0, false,   12,  64,  68, false,  5,  5,  39, false },
+	{  720,  576,  16,   9,   27000, 0, false,   12,  64,  68, false,  5,  5,  39, false },
+	{ 1280,  720,  16,   9,   74250, 0, false,  440,  40, 220, true,   5,  5,  20, true  },
+	{ 1920, 1080,  16,   9,   74250, 0, true,   528,  44, 148, true,   2,  5,  15, true  },
+	/* VIC 21 */
+	{ 1440,  576,   4,   3,   27000, 0, true,    24, 126, 138, false,  2,  3,  19, false },
+	{ 1440,  576,  16,   9,   27000, 0, true,    24, 126, 138, false,  2,  3,  19, false },
+	{ 1440,  288,   4,   3,   27000, 0, false,   24, 126, 138, false,  2,  3,  19, false },
+	{ 1440,  288,  16,   9,   27000, 0, false,   24, 126, 138, false,  2,  3,  19, false },
+	{ 2880,  576,   4,   3,   54000, 0, true,    48, 252, 276, false,  2,  3,  19, false },
+	{ 2880,  576,  16,   9,   54000, 0, true,    48, 252, 276, false,  2,  3,  19, false },
+	{ 2880,  288,   4,   3,   54000, 0, false,   48, 252, 276, false,  2,  3,  19, false },
+	{ 2880,  288,  16,   9,   54000, 0, false,   48, 252, 276, false,  2,  3,  19, false },
+	{ 1440,  576,   4,   3,   54000, 0, false,   24, 128, 136, false,  5,  5,  39, false },
+	{ 1440,  576,  16,   9,   54000, 0, false,   24, 128, 136, false,  5,  5,  39, false },
+	/* VIC 31 */
+	{ 1920, 1080,  16,   9,  148500, 0, false,  528,  44, 148, true,   4,  5,  36, true  },
+	{ 1920, 1080,  16,   9,   74250, 0, false,  638,  44, 148, true,   4,  5,  36, true  },
+	{ 1920, 1080,  16,   9,   74250, 0, false,  528,  44, 148, true,   4,  5,  36, true  },
+	{ 1920, 1080,  16,   9,   74250, 0, false,   88,  44, 148, true,   4,  5,  36, true  },
+	{ 2880,  480,   4,   3,  108000, 0, false,   64, 248, 240, false,  9,  6,  30, false },
+	{ 2880,  480,  16,   9,  108000, 0, false,   64, 248, 240, false,  9,  6,  30, false },
+	{ 2880,  576,   4,   3,  108000, 0, false,   48, 256, 272, false,  5,  5,  39, false },
+	{ 2880,  576,  16,   9,  108000, 0, false,   48, 256, 272, false,  5,  5,  39, false },
+	{ 1920, 1080,  16,   9,   72000, 0, true,    32, 168, 184, true,  23,  5,  57, false, 0, 0, true },
+	{ 1920, 1080,  16,   9,  148500, 0, true,   528,  44, 148, true,   2,  5,  15, true  },
+	/* VIC 41 */
+	{ 1280,  720,  16,   9,  148500, 0, false,  440,  40, 220, true,   5,  5,  20, true  },
+	{  720,  576,   4,   3,   54000, 0, false,   12,  64,  68, false,  5,  5,  39, false },
+	{  720,  576,  16,   9,   54000, 0, false,   12,  64,  68, false,  5,  5,  39, false },
+	{ 1440,  576,   4,   3,   54000, 0, true,    24, 126, 138, false,  2,  3,  19, false },
+	{ 1440,  576,  16,   9,   54000, 0, true,    24, 126, 138, false,  2,  3,  19, false },
+	{ 1920, 1080,  16,   9,  148500, 0, true,    88,  44, 148, true,   2,  5,  15, true  },
+	{ 1280,  720,  16,   9,  148500, 0, false,  110,  40, 220, true,   5,  5,  20, true  },
+	{  720,  480,   4,   3,   54000, 0, false,   16,  62,  60, false,  9,  6,  30, false },
+	{  720,  480,  16,   9,   54000, 0, false,   16,  62,  60, false,  9,  6,  30, false },
+	{ 1440,  480,   4,   3,   54000, 0, true,    38, 124, 114, false,  4,  3,  15, false },
+	/* VIC 51 */
+	{ 1440,  480,  16,   9,   54000, 0, true,    38, 124, 114, false,  4,  3,  15, false },
+	{  720,  576,   4,   3,  108000, 0, false,   12,  64,  68, false,  5,  5,  39, false },
+	{  720,  576,  16,   9,  108000, 0, false,   12,  64,  68, false,  5,  5,  39, false },
+	{ 1440,  576,   4,   3,  108000, 0, true,    24, 126, 138, false,  2,  3,  19, false },
+	{ 1440,  576,  16,   9,  108000, 0, true,    24, 126, 138, false,  2,  3,  19, false },
+	{  720,  480,   4,   3,  108000, 0, false,   16,  62,  60, false,  9,  6,  30, false },
+	{  720,  480,  16,   9,  108000, 0, false,   16,  62,  60, false,  9,  6,  30, false },
+	{ 1440,  480,   4,   3,  108000, 0, true,    38, 124, 114, false,  4,  3,  15, false },
+	{ 1440,  480,  16,   9,  108000, 0, true,    38, 124, 114, false,  4,  3,  15, false },
+	{ 1280,  720,  16,   9,   59400, 0, false, 1760,  40, 220, true,   5,  5,  20, true  },
+	/* VIC 61 */
+	{ 1280,  720,  16,   9,   74250, 0, false, 2420,  40, 220, true,   5,  5,  20, true  },
+	{ 1280,  720,  16,   9,   74250, 0, false, 1760,  40, 220, true,   5,  5,  20, true  },
+	{ 1920, 1080,  16,   9,  297000, 0, false,   88,  44, 148, true,   4,  5,  36, true  },
+	{ 1920, 1080,  16,   9,  297000, 0, false,  528,  44, 148, true,   4,  5,  36, true  },
+	{ 1280,  720,  64,  27,   59400, 0, false, 1760,  40, 220, true,   5,  5,  20, true  },
+	{ 1280,  720,  64,  27,   74250, 0, false, 2420,  40, 220, true,   5,  5,  20, true  },
+	{ 1280,  720,  64,  27,   74250, 0, false, 1760,  40, 220, true,   5,  5,  20, true  },
+	{ 1280,  720,  64,  27,   74250, 0, false,  440,  40, 220, true,   5,  5,  20, true  },
+	{ 1280,  720,  64,  27,   74250, 0, false,  110,  40, 220, true,   5,  5,  20, true  },
+	{ 1280,  720,  64,  27,  148500, 0, false,  440,  40, 220, true,   5,  5,  20, true  },
+	/* VIC 71 */
+	{ 1280,  720,  64,  27,  148500, 0, false,  110,  40, 220, true,   5,  5,  20, true  },
+	{ 1920, 1080,  64,  27,   74250, 0, false,  638,  44, 148, true,   4,  5,  36, true  },
+	{ 1920, 1080,  64,  27,   74250, 0, false,  528,  44, 148, true,   4,  5,  36, true  },
+	{ 1920, 1080,  64,  27,   74250, 0, false,   88,  44, 148, true,   4,  5,  36, true  },
+	{ 1920, 1080,  64,  27,  148500, 0, false,  528,  44, 148, true,   4,  5,  36, true  },
+	{ 1920, 1080,  64,  27,  148500, 0, false,   88,  44, 148, true,   4,  5,  36, true  },
+	{ 1920, 1080,  64,  27,  297000, 0, false,  528,  44, 148, true,   4,  5,  36, true  },
+	{ 1920, 1080,  64,  27,  297000, 0, false,   88,  44, 148, true,   4,  5,  36, true  },
+	{ 1680,  720,  64,  27,   59400, 0, false, 1360,  40, 220, true,   5,  5,  20, true  },
+	{ 1680,  720,  64,  27,   59400, 0, false, 1228,  40, 220, true,   5,  5,  20, true  },
+	/* VIC 81 */
+	{ 1680,  720,  64,  27,   59400, 0, false,  700,  40, 220, true,   5,  5,  20, true  },
+	{ 1680,  720,  64,  27,   82500, 0, false,  260,  40, 220, true,   5,  5,  20, true  },
+	{ 1680,  720,  64,  27,   99000, 0, false,  260,  40, 220, true,   5,  5,  20, true  },
+	{ 1680,  720,  64,  27,  165000, 0, false,   60,  40, 220, true,   5,  5,  95, true  },
+	{ 1680,  720,  64,  27,  198000, 0, false,   60,  40, 220, true,   5,  5,  95, true  },
+	{ 2560, 1080,  64,  27,   99000, 0, false,  998,  44, 148, true,   4,  5,  11, true  },
+	{ 2560, 1080,  64,  27,   90000, 0, false,  448,  44, 148, true,   4,  5,  36, true  },
+	{ 2560, 1080,  64,  27,  118800, 0, false,  768,  44, 148, true,   4,  5,  36, true  },
+	{ 2560, 1080,  64,  27,  185625, 0, false,  548,  44, 148, true,   4,  5,  36, true  },
+	{ 2560, 1080,  64,  27,  198000, 0, false,  248,  44, 148, true,   4,  5,  11, true  },
+	/* VIC 91 */
+	{ 2560, 1080,  64,  27,  371250, 0, false,  218,  44, 148, true,   4,  5, 161, true  },
+	{ 2560, 1080,  64,  27,  495000, 0, false,  548,  44, 148, true,   4,  5, 161, true  },
+	{ 3840, 2160,  16,   9,  297000, 0, false, 1276,  88, 296, true,   8, 10,  72, true  },
+	{ 3840, 2160,  16,   9,  297000, 0, false, 1056,  88, 296, true,   8, 10,  72, true  },
+	{ 3840, 2160,  16,   9,  297000, 0, false,  176,  88, 296, true,   8, 10,  72, true  },
+	{ 3840, 2160,  16,   9,  594000, 0, false, 1056,  88, 296, true,   8, 10,  72, true  },
+	{ 3840, 2160,  16,   9,  594000, 0, false,  176,  88, 296, true,   8, 10,  72, true  },
+	{ 4096, 2160, 256, 135,  297000, 0, false, 1020,  88, 296, true,   8, 10,  72, true  },
+	{ 4096, 2160, 256, 135,  297000, 0, false,  968,  88, 128, true,   8, 10,  72, true  },
+	{ 4096, 2160, 256, 135,  297000, 0, false,   88,  88, 128, true,   8, 10,  72, true  },
+	/* VIC 101 */
+	{ 4096, 2160, 256, 135,  594000, 0, false,  968,  88, 128, true,   8, 10,  72, true  },
+	{ 4096, 2160, 256, 135,  594000, 0, false,   88,  88, 128, true,   8, 10,  72, true  },
+	{ 3840, 2160,  64,  27,  297000, 0, false, 1276,  88, 296, true,   8, 10,  72, true  },
+	{ 3840, 2160,  64,  27,  297000, 0, false, 1056,  88, 296, true,   8, 10,  72, true  },
+	{ 3840, 2160,  64,  27,  297000, 0, false,  176,  88, 296, true,   8, 10,  72, true  },
+	{ 3840, 2160,  64,  27,  594000, 0, false, 1056,  88, 296, true,   8, 10,  72, true  },
+	{ 3840, 2160,  64,  27,  594000, 0, false,  176,  88, 296, true,   8, 10,  72, true  },
+	{ 1280,  720,  16,   9,   90000, 0, false,  960,  40, 220, true,   5,  5,  20, true  },
+	{ 1280,  720,  64,  27,   90000, 0, false,  960,  40, 220, true,   5,  5,  20, true  },
+	{ 1680,  720,  64,  27,   99000, 0, false,  810,  40, 220, true,   5,  5,  20, true  },
+	/* VIC 111 */
+	{ 1920, 1080,  16,   9,  148500, 0, false,  638,  44, 148, true,   4,  5,  36, true  },
+	{ 1920, 1080,  64,  27,  148500, 0, false,  638,  44, 148, true,   4,  5,  36, true  },
+	{ 2560, 1080,  64,  27,  198000, 0, false,  998,  44, 148, true,   4,  5,  11, true  },
+	{ 3840, 2160,  16,   9,  594000, 0, false, 1276,  88, 296, true,   8, 10,  72, true  },
+	{ 4096, 2160, 256, 135,  594000, 0, false, 1020,  88, 296, true,   8, 10,  72, true  },
+	{ 3840, 2160,  64,  27,  594000, 0, false, 1276,  88, 296, true,   8, 10,  72, true  },
+	{ 3840, 2160,  16,   9, 1188000, 0, false, 1056,  88, 296, true,   8, 10,  72, true  },
+	{ 3840, 2160,  16,   9, 1188000, 0, false,  176,  88, 296, true,   8, 10,  72, true  },
+	{ 3840, 2160,  64,  27, 1188000, 0, false, 1056,  88, 296, true,   8, 10,  72, true  },
+	{ 3840, 2160,  64,  27, 1188000, 0, false,  176,  88, 296, true,   8, 10,  72, true  },
+	/* VIC 121 */
+	{ 5120, 2160,  64,  27,  396000, 0, false, 1996,  88, 296, true,   8, 10,  22, true  },
+	{ 5120, 2160,  64,  27,  396000, 0, false, 1696,  88, 296, true,   8, 10,  22, true  },
+	{ 5120, 2160,  64,  27,  396000, 0, false,  664,  88, 128, true,   8, 10,  22, true  },
+	{ 5120, 2160,  64,  27,  742500, 0, false,  746,  88, 296, true,   8, 10, 297, true  },
+	{ 5120, 2160,  64,  27,  742500, 0, false, 1096,  88, 296, true,   8, 10,  72, true  },
+	{ 5120, 2160,  64,  27,  742500, 0, false,  164,  88, 128, true,   8, 10,  72, true  },
+	{ 5120, 2160,  64,  27, 1485000, 0, false, 1096,  88, 296, true,   8, 10,  72, true  },
+};
+
+static const struct timings edid_cta_modes2[] = {
+	/* VIC 193 */
+	{  5120, 2160,  64,  27, 1485000, 0, false,  164,  88, 128, true,   8, 10,  72, true  },
+	{  7680, 4320,  16,   9, 1188000, 0, false, 2552, 176, 592, true,  16, 20, 144, true  },
+	{  7680, 4320,  16,   9, 1188000, 0, false, 2352, 176, 592, true,  16, 20,  44, true  },
+	{  7680, 4320,  16,   9, 1188000, 0, false,  552, 176, 592, true,  16, 20,  44, true  },
+	{  7680, 4320,  16,   9, 2376000, 0, false, 2552, 176, 592, true,  16, 20, 144, true  },
+	{  7680, 4320,  16,   9, 2376000, 0, false, 2352, 176, 592, true,  16, 20,  44, true  },
+	{  7680, 4320,  16,   9, 2376000, 0, false,  552, 176, 592, true,  16, 20,  44, true  },
+	{  7680, 4320,  16,   9, 4752000, 0, false, 2112, 176, 592, true,  16, 20, 144, true  },
+	/* VIC 201 */
+	{  7680, 4320,  16,   9, 4752000, 0, false,  352, 176, 592, true,  16, 20, 144, true  },
+	{  7680, 4320,  64,  27, 1188000, 0, false, 2552, 176, 592, true,  16, 20, 144, true  },
+	{  7680, 4320,  64,  27, 1188000, 0, false, 2352, 176, 592, true,  16, 20,  44, true  },
+	{  7680, 4320,  64,  27, 1188000, 0, false,  552, 176, 592, true,  16, 20,  44, true  },
+	{  7680, 4320,  64,  27, 2376000, 0, false, 2552, 176, 592, true,  16, 20, 144, true  },
+	{  7680, 4320,  64,  27, 2376000, 0, false, 2352, 176, 592, true,  16, 20,  44, true  },
+	{  7680, 4320,  64,  27, 2376000, 0, false,  552, 176, 592, true,  16, 20,  44, true  },
+	{  7680, 4320,  64,  27, 4752000, 0, false, 2112, 176, 592, true,  16, 20, 144, true  },
+	{  7680, 4320,  64,  27, 4752000, 0, false,  352, 176, 592, true,  16, 20, 144, true  },
+	{ 10240, 4320,  64,  27, 1485000, 0, false, 1492, 176, 592, true,  16, 20, 594, true  },
+	/* VIC 211 */
+	{ 10240, 4320,  64,  27, 1485000, 0, false, 2492, 176, 592, true,  16, 20,  44, true  },
+	{ 10240, 4320,  64,  27, 1485000, 0, false,  288, 176, 296, true,  16, 20, 144, true  },
+	{ 10240, 4320,  64,  27, 2970000, 0, false, 1492, 176, 592, true,  16, 20, 594, true  },
+	{ 10240, 4320,  64,  27, 2970000, 0, false, 2492, 176, 592, true,  16, 20,  44, true  },
+	{ 10240, 4320,  64,  27, 2970000, 0, false,  288, 176, 296, true,  16, 20, 144, true  },
+	{ 10240, 4320,  64,  27, 5940000, 0, false, 2192, 176, 592, true,  16, 20, 144, true  },
+	{ 10240, 4320,  64,  27, 5940000, 0, false,  288, 176, 296, true,  16, 20, 144, true  },
+	{  4096, 2160, 256, 135, 1188000, 0, false,  800,  88, 296, true,   8, 10,  72, true  },
+	{  4096, 2160, 256, 135, 1188000, 0, false,   88,  88, 128, true,   8, 10,  72, true  },
+};
+
+static const unsigned char edid_hdmi_mode_map[] = { 95, 94, 93, 98 };
+
+unsigned char hdmi_vic_to_vic(unsigned char hdmi_vic)
+{
+	if (hdmi_vic > 0 && hdmi_vic <= ARRAY_SIZE(edid_hdmi_mode_map))
+		return edid_hdmi_mode_map[hdmi_vic - 1];
+	return 0;
+}
+
+const struct timings *find_vic_id(unsigned char vic)
+{
+	if (vic > 0 && vic <= ARRAY_SIZE(edid_cta_modes1))
+		return edid_cta_modes1 + vic - 1;
+	if (vic >= 193 && vic < ARRAY_SIZE(edid_cta_modes2) + 193)
+		return edid_cta_modes2 + vic - 193;
+	return NULL;
+}
+
+const struct timings *find_hdmi_vic_id(unsigned char hdmi_vic)
+{
+	if (hdmi_vic > 0 && hdmi_vic <= ARRAY_SIZE(edid_hdmi_mode_map))
+		return find_vic_id(edid_hdmi_mode_map[hdmi_vic - 1]);
+	return NULL;
+}
+
+const struct timings *cta_close_match_to_vic(const timings &t, unsigned &vic)
+{
+	for (vic = 1; vic <= ARRAY_SIZE(edid_cta_modes1); vic++) {
+		if (timings_close_match(t, edid_cta_modes1[vic - 1]))
+			return &edid_cta_modes1[vic - 1];
+	}
+	for (vic = 193; vic < ARRAY_SIZE(edid_cta_modes2) + 193; vic++) {
+		if (timings_close_match(t, edid_cta_modes1[vic - 193]))
+			return &edid_cta_modes1[vic - 193];
+	}
+	vic = 0;
+	return NULL;
+}
+
+void edid_state::cta_list_vics()
+{
+	char type[16];
+	for (unsigned vic = 1; vic <= ARRAY_SIZE(edid_cta_modes1); vic++) {
+		sprintf(type, "VIC %3u", vic);
+		print_timings("", &edid_cta_modes1[vic - 1], type, "", false, false);
+	}
+	for (unsigned vic = 193; vic < ARRAY_SIZE(edid_cta_modes2) + 193; vic++) {
+		sprintf(type, "VIC %3u", vic);
+		print_timings("", &edid_cta_modes2[vic - 193], type, "", false, false);
+	}
+}
+
+void edid_state::cta_list_hdmi_vics()
+{
+	for (unsigned i = 0; i < ARRAY_SIZE(edid_hdmi_mode_map); i++) {
+		unsigned vic = edid_hdmi_mode_map[i];
+		char type[16];
+
+		sprintf(type, "HDMI VIC %u", i + 1);
+		print_timings("", find_vic_id(vic), type, "", false, false);
+	}
+}
+
+static std::string audio_ext_format(unsigned char x)
+{
+	if (x >= 1 && x <= 3)
+		fail("Obsolete Audio Ext Format 0x%02x.\n", x);
+	switch (x) {
+	case 1: return "HE AAC (Obsolete)";
+	case 2: return "HE AAC v2 (Obsolete)";
+	case 3: return "MPEG Surround (Obsolete)";
+	case 4: return "MPEG-4 HE AAC";
+	case 5: return "MPEG-4 HE AAC v2";
+	case 6: return "MPEG-4 AAC LC";
+	case 7: return "DRA";
+	case 8: return "MPEG-4 HE AAC + MPEG Surround";
+	case 10: return "MPEG-4 AAC LC + MPEG Surround";
+	case 11: return "MPEG-H 3D Audio";
+	case 12: return "AC-4";
+	case 13: return "L-PCM 3D Audio";
+	default: break;
+	}
+	fail("Unknown Audio Ext Format 0x%02x.\n", x);
+	return std::string("Unknown Audio Ext Format (") + utohex(x) + ")";
+}
+
+static std::string audio_format(unsigned char x)
+{
+	switch (x) {
+	case 1: return "Linear PCM";
+	case 2: return "AC-3";
+	case 3: return "MPEG 1 (Layers 1 & 2)";
+	case 4: return "MPEG 1 Layer 3 (MP3)";
+	case 5: return "MPEG2 (multichannel)";
+	case 6: return "AAC LC";
+	case 7: return "DTS";
+	case 8: return "ATRAC";
+	case 9: return "One Bit Audio";
+	case 10: return "Enhanced AC-3 (DD+)";
+	case 11: return "DTS-HD";
+	case 12: return "MAT (MLP)";
+	case 13: return "DST";
+	case 14: return "WMA Pro";
+	default: break;
+	}
+	fail("Unknown Audio Format 0x%02x.\n", x);
+	return std::string("Unknown Audio Format (") + utohex(x) + ")";
+}
+
+static std::string mpeg_h_3d_audio_level(unsigned char x)
+{
+	switch (x) {
+	case 0: return "Unspecified";
+	case 1: return "Level 1";
+	case 2: return "Level 2";
+	case 3: return "Level 3";
+	case 4: return "Level 4";
+	case 5: return "Level 5";
+	default: break;
+	}
+	fail("Unknown MPEG-H 3D Audio Level 0x%02x.\n", x);
+	return std::string("Unknown MPEG-H 3D Audio Level (") + utohex(x) + ")";
+}
+
+static void cta_audio_block(const unsigned char *x, unsigned length)
+{
+	unsigned i, format, ext_format;
+
+	if (length % 3) {
+		fail("Broken CTA-861 audio block length %d.\n", length);
+		return;
+	}
+
+	for (i = 0; i < length; i += 3) {
+		format = (x[i] & 0x78) >> 3;
+		if (format == 0) {
+			printf("    Reserved (0x00)\n");
+			fail("Audio Format Code 0x00 is reserved.\n");
+			continue;
+		}
+		if (format != 15) {
+			ext_format = 0;
+			printf("    %s:\n", audio_format(format).c_str());
+		} else {
+			ext_format = (x[i + 2] & 0xf8) >> 3;
+			printf("    %s:\n", audio_ext_format(ext_format).c_str());
+		}
+		if (format != 15)
+			printf("      Max channels: %u\n", (x[i] & 0x07)+1);
+		else if (ext_format == 11)
+			printf("      MPEG-H 3D Audio Level: %s\n",
+			       mpeg_h_3d_audio_level(x[i] & 0x07).c_str());
+		else if (ext_format == 13)
+			printf("      Max channels: %u\n",
+			       (((x[i + 1] & 0x80) >> 3) | ((x[i] & 0x80) >> 4) |
+				(x[i] & 0x07))+1);
+		else
+			printf("      Max channels: %u\n", (x[i] & 0x07)+1);
+
+		printf("      Supported sample rates (kHz):%s%s%s%s%s%s%s\n",
+		       (x[i+1] & 0x40) ? " 192" : "",
+		       (x[i+1] & 0x20) ? " 176.4" : "",
+		       (x[i+1] & 0x10) ? " 96" : "",
+		       (x[i+1] & 0x08) ? " 88.2" : "",
+		       (x[i+1] & 0x04) ? " 48" : "",
+		       (x[i+1] & 0x02) ? " 44.1" : "",
+		       (x[i+1] & 0x01) ? " 32" : "");
+		if (format == 1 || ext_format == 13) {
+			printf("      Supported sample sizes (bits):%s%s%s\n",
+			       (x[i+2] & 0x04) ? " 24" : "",
+			       (x[i+2] & 0x02) ? " 20" : "",
+			       (x[i+2] & 0x01) ? " 16" : "");
+		} else if (format <= 8) {
+			printf("      Maximum bit rate: %u kb/s\n", x[i+2] * 8);
+		} else if (format == 10) {
+			// As specified by the "Dolby Audio and Dolby Atmos over HDMI"
+			// specification (v1.0).
+			if (x[i+2] & 1)
+				printf("      Supports Joint Object Coding\n");
+			if (x[i+2] & 2)
+				printf("      Supports Joint Object Coding with ACMOD28\n");
+		} else if (format == 12) {
+			if (x[i+2] & 1) {
+				printf("      Supports Dolby TrueHD, object audio PCM and channel-based PCM\n");
+				printf("      Hash calculation %srequired for object audio PCM or channel-based PCM\n",
+				       (x[i+2] & 2) ? "not " : "");
+			} else {
+				printf("      Supports only Dolby TrueHD\n");
+			}
+		} else if (format == 14) {
+			printf("      Profile: %u\n", x[i+2] & 7);
+		} else if (format >= 9 && format <= 13) {
+			printf("      Audio Format Code dependent value: 0x%02x\n", x[i+2]);
+		} else if (ext_format == 11 && (x[i+2] & 1)) {
+			printf("      Supports MPEG-H 3D Audio Low Complexity Profile\n");
+		} else if ((ext_format >= 4 && ext_format <= 6) ||
+			   ext_format == 8 || ext_format == 10) {
+			printf("      AAC audio frame lengths:%s%s\n",
+			       (x[i+2] & 4) ? " 1024_TL" : "",
+			       (x[i+2] & 2) ? " 960_TL" : "");
+			if (ext_format >= 8 && (x[i+2] & 1))
+				printf("      Supports %s signaled MPEG Surround data\n",
+				       (x[i+2] & 1) ? "implicitly and explicitly" : "only implicitly");
+			if (ext_format == 6 && (x[i+2] & 1))
+				printf("      Supports 22.2ch System H\n");
+		}
+	}
+}
+
+void edid_state::cta_svd(const unsigned char *x, unsigned n, bool for_ycbcr420)
+{
+	unsigned i;
+
+	for (i = 0; i < n; i++)  {
+		const struct timings *t = NULL;
+		unsigned char svd = x[i];
+		unsigned char native;
+		unsigned char vic;
+
+		if ((svd & 0x7f) == 0)
+			continue;
+
+		if ((svd - 1) & 0x40) {
+			vic = svd;
+			native = 0;
+		} else {
+			vic = svd & 0x7f;
+			native = svd & 0x80;
+		}
+
+		t = find_vic_id(vic);
+		if (t) {
+			switch (vic) {
+			case 95:
+				cta.supported_hdmi_vic_vsb_codes |= 1 << 0;
+				break;
+			case 94:
+				cta.supported_hdmi_vic_vsb_codes |= 1 << 1;
+				break;
+			case 93:
+				cta.supported_hdmi_vic_vsb_codes |= 1 << 2;
+				break;
+			case 98:
+				cta.supported_hdmi_vic_vsb_codes |= 1 << 3;
+				break;
+			}
+			bool first_svd = cta.first_svd && !for_ycbcr420;
+			bool override_pref = first_svd && cta.first_svd_might_be_preferred;
+
+			char type[16];
+			sprintf(type, "VIC %3u", vic);
+			const char *flags = native ? "native" : "";
+
+			if (for_ycbcr420) {
+				struct timings tmp = *t;
+				tmp.ycbcr420 = true;
+				print_timings("    ", &tmp, type, flags);
+			} else {
+				print_timings("    ", t, type, flags);
+			}
+			if (override_pref) {
+				if (!cta.preferred_timings.empty()) {
+					if (match_timings(cta.preferred_timings[0].t, *t))
+						warn("For improved preferred timing interoperability, set 'Native detailed modes' to 1.\n");
+					else
+						warn("VIC %u is the preferred timing, overriding the first detailed timings. Is this intended?\n", vic);
+				}
+				cta.preferred_timings.insert(cta.preferred_timings.begin(),
+							     timings_ext(*t, type, flags));
+			} else if (first_svd) {
+				cta.preferred_timings.push_back(timings_ext(*t, type, flags));
+			}
+			if (first_svd) {
+				cta.first_svd = false;
+				cta.first_svd_might_be_preferred = false;
+			}
+			if (native)
+				cta.native_timings.push_back(timings_ext(*t, type, flags));
+		} else {
+			printf("    Unknown (VIC %3u)\n", vic);
+			fail("Unknown VIC %u.\n", vic);
+		}
+
+		if (vic == 1 && !for_ycbcr420)
+			cta.has_vic_1 = 1;
+		if (++cta.vics[vic][for_ycbcr420] == 2)
+			fail("Duplicate %sVIC %u.\n", for_ycbcr420 ? "YCbCr 4:2:0 " : "", vic);
+		if (for_ycbcr420 && cta.preparsed_has_vic[0][vic])
+			fail("YCbCr 4:2:0-only VIC %u is also a regular VIC.\n", vic);
+	}
+}
+
+void edid_state::print_vic_index(const char *prefix, unsigned idx, const char *suffix, bool ycbcr420)
+{
+	if (!suffix)
+		suffix = "";
+	if (idx < cta.preparsed_svds[0].size()) {
+		unsigned char vic = cta.preparsed_svds[0][idx];
+		const struct timings *t = find_vic_id(vic);
+		char buf[16];
+
+		sprintf(buf, "VIC %3u", vic);
+
+		if (t) {
+			struct timings tmp = *t;
+			tmp.ycbcr420 = ycbcr420;
+			print_timings(prefix, &tmp, buf, suffix);
+		} else {
+			printf("%sUnknown (%s%s%s)\n", prefix, buf,
+			       *suffix ? ", " : "", suffix);
+		}
+	} else {
+		// Should not happen!
+		printf("%sSVD Index %u is out of range", prefix, idx + 1);
+		if (*suffix)
+			printf(" (%s)", suffix);
+		printf("\n");
+	}
+}
+
+void edid_state::cta_y420cmdb(const unsigned char *x, unsigned length)
+{
+	unsigned max_idx = 0;
+	unsigned i;
+
+	if (!length) {
+		printf("    All VDB SVDs\n");
+		return;
+	}
+
+	if (memchk(x, length)) {
+		printf("    Empty Capability Map\n");
+		fail("Empty Capability Map.\n");
+		return;
+	}
+
+	for (i = 0; i < length; i++) {
+		unsigned char v = x[i];
+		unsigned j;
+
+		for (j = 0; j < 8; j++) {
+			if (!(v & (1 << j)))
+				continue;
+
+			print_vic_index("    ", i * 8 + j, "", true);
+			max_idx = i * 8 + j;
+			if (max_idx < cta.preparsed_svds[0].size()) {
+				unsigned vic = cta.preparsed_svds[0][max_idx];
+				if (cta.preparsed_has_vic[1][vic])
+					fail("VIC %u is also a YCbCr 4:2:0-only VIC.\n", vic);
+			}
+		}
+	}
+	if (max_idx >= cta.preparsed_svds[0].size())
+		fail("Max index %u > %u (#SVDs).\n",
+		     max_idx + 1, cta.preparsed_svds[0].size());
+}
+
+void edid_state::cta_vfpdb(const unsigned char *x, unsigned length)
+{
+	unsigned i;
+
+	if (length == 0) {
+		fail("Empty Data Block with length %u.\n", length);
+		return;
+	}
+	cta.preferred_timings.clear();
+	for (i = 0; i < length; i++)  {
+		unsigned char svr = x[i];
+		char suffix[16];
+
+		if ((svr > 0 && svr < 128) || (svr > 192 && svr < 254)) {
+			const struct timings *t;
+			unsigned char vic = svr;
+
+			sprintf(suffix, "VIC %3u", vic);
+
+			t = find_vic_id(vic);
+			if (t) {
+				print_timings("    ", t, suffix);
+				cta.preferred_timings.push_back(timings_ext(*t, suffix, ""));
+			} else {
+				printf("    %s: Unknown\n", suffix);
+				fail("Unknown VIC %u.\n", vic);
+			}
+
+		} else if (svr >= 129 && svr <= 144) {
+			sprintf(suffix, "DTD %3u", svr - 128);
+			if (svr >= cta.preparsed_total_dtds + 129) {
+				printf("    %s: Invalid\n", suffix);
+				fail("Invalid DTD %u.\n", svr - 128);
+			} else {
+				printf("    %s\n", suffix);
+				cta.preferred_timings.push_back(timings_ext(svr, suffix));
+			}
+		} else if (svr >= 145 && svr <= 160) {
+			sprintf(suffix, "VTDB %3u", svr - 144);
+			if (svr >= cta.preparsed_total_vtdbs + 145) {
+				printf("    %s: Invalid\n", suffix);
+				fail("Invalid VTDB %u.\n", svr - 144);
+			} else {
+				printf("    %s\n", suffix);
+				cta.preferred_timings.push_back(timings_ext(svr, suffix));
+			}
+		} else if (svr == 254) {
+			sprintf(suffix, "T8VTDB");
+			if (!cta.preparsed_has_t8vtdb) {
+				printf("    %s: Invalid\n", suffix);
+				fail("Invalid T8VTDB.\n");
+			} else {
+				printf("    %s\n", suffix);
+				cta.preferred_timings.push_back(timings_ext(svr, suffix));
+			}
+		}
+	}
+}
+
+static std::string hdmi_latency2s(unsigned char l, bool is_video)
+{
+	if (!l)
+		return "Unknown";
+	if (l == 0xff)
+		return is_video ? "Video not supported" : "Audio not supported";
+	return std::to_string(1 + 2 * l) + " ms";
+}
+
+void edid_state::hdmi_latency(unsigned char vid_lat, unsigned char aud_lat,
+			      bool is_ilaced)
+{
+	const char *vid = is_ilaced ? "Interlaced video" : "Video";
+	const char *aud = is_ilaced ? "Interlaced audio" : "Audio";
+
+	printf("    %s latency: %s\n", vid, hdmi_latency2s(vid_lat, true).c_str());
+	printf("    %s latency: %s\n", aud, hdmi_latency2s(aud_lat, false).c_str());
+
+	if (vid_lat > 251 && vid_lat != 0xff)
+		fail("Invalid %s latency value %u.\n", vid, vid_lat);
+	if (aud_lat > 251 && aud_lat != 0xff)
+		fail("Invalid %s latency value %u.\n", aud, aud_lat);
+
+	if (!vid_lat || vid_lat > 251)
+		return;
+	if (!aud_lat || aud_lat > 251)
+		return;
+
+	unsigned vid_ms = 1 + 2 * vid_lat;
+	unsigned aud_ms = 1 + 2 * aud_lat;
+
+	// HDMI 2.0 latency checks for devices without HDMI output
+	if (aud_ms < vid_ms)
+		warn("%s latency < %s latency (%u ms < %u ms). This is discouraged for devices without HDMI output.\n",
+		     aud, vid, aud_ms, vid_ms);
+	else if (vid_ms + 20 < aud_ms)
+		warn("%s latency + 20 < %s latency (%u + 20 ms < %u ms). This is forbidden for devices without HDMI output.\n",
+		     vid, aud, vid_ms, aud_ms);
+	else if (vid_ms < aud_ms)
+		warn("%s latency < %s latency (%u ms < %u ms). This is discouraged for devices without HDMI output.\n",
+		     vid, aud, vid_ms, aud_ms);
+}
+
+void edid_state::cta_hdmi_block(const unsigned char *x, unsigned length)
+{
+	unsigned len_vic, len_3d;
+
+	if (length < 4) {
+		fail("Empty Data Block with length %u.\n", length);
+		return;
+	}
+	printf("    Source physical address: %x.%x.%x.%x\n", x[3] >> 4, x[3] & 0x0f,
+	       x[4] >> 4, x[4] & 0x0f);
+
+	if (length < 6)
+		return;
+
+	if (x[5] & 0x80)
+		printf("    Supports_AI\n");
+	if (x[5] & 0x40)
+		printf("    DC_48bit\n");
+	if (x[5] & 0x20)
+		printf("    DC_36bit\n");
+	if (x[5] & 0x10)
+		printf("    DC_30bit\n");
+	if (x[5] & 0x08)
+		printf("    DC_Y444\n");
+	/* two reserved bits */
+	if (x[5] & 0x01)
+		printf("    DVI_Dual\n");
+
+	if (length < 7)
+		return;
+
+	printf("    Maximum TMDS clock: %u MHz\n", x[6] * 5);
+	if (x[6] * 5 > 340)
+		fail("HDMI VSDB Max TMDS rate is > 340.\n");
+
+	if (length < 8)
+		return;
+
+	if (x[7] & 0x0f) {
+		printf("    Supported Content Types:\n");
+		if (x[7] & 0x01)
+			printf("      Graphics\n");
+		if (x[7] & 0x02)
+			printf("      Photo\n");
+		if (x[7] & 0x04)
+			printf("      Cinema\n");
+		if (x[7] & 0x08)
+			printf("      Game\n");
+	}
+
+	unsigned b = 8;
+	if (x[7] & 0x80) {
+		hdmi_latency(x[b], x[b + 1], false);
+
+		if (x[7] & 0x40) {
+			if (x[b] == x[b + 2] &&
+			    x[b + 1] == x[b + 3])
+				warn("Progressive and Interlaced latency values are identical, no need for both.\n");
+			b += 2;
+			hdmi_latency(x[b], x[b + 1], true);
+		}
+		b += 2;
+	}
+
+	if (!(x[7] & 0x20))
+		return;
+
+	bool mask = false;
+	bool formats = false;
+
+	printf("    Extended HDMI video details:\n");
+	if (x[b] & 0x80)
+		printf("      3D present\n");
+	if ((x[b] & 0x60) == 0x20) {
+		printf("      All advertised VICs are 3D-capable\n");
+		formats = true;
+	}
+	if ((x[b] & 0x60) == 0x40) {
+		printf("      3D-capable-VIC mask present\n");
+		formats = true;
+		mask = true;
+	}
+	switch (x[b] & 0x18) {
+	case 0x00: break;
+	case 0x08:
+		   printf("      Base EDID image size is aspect ratio\n");
+		   break;
+	case 0x10:
+		   printf("      Base EDID image size is in units of 1 cm\n");
+		   break;
+	case 0x18:
+		   printf("      Base EDID image size is in units of 5 cm\n");
+		   base.max_display_width_mm *= 5;
+		   base.max_display_height_mm *= 5;
+		   printf("        Recalculated image size: %u cm x %u cm\n",
+			  base.max_display_width_mm / 10, base.max_display_height_mm / 10);
+		   break;
+	}
+	b++;
+	len_vic = (x[b] & 0xe0) >> 5;
+	len_3d = (x[b] & 0x1f) >> 0;
+	b++;
+
+	if (len_vic) {
+		unsigned i;
+
+		printf("      HDMI VICs:\n");
+		for (i = 0; i < len_vic; i++) {
+			unsigned char vic = x[b + i];
+			const struct timings *t;
+
+			if (vic && vic <= ARRAY_SIZE(edid_hdmi_mode_map)) {
+				std::string suffix = "HDMI VIC " + std::to_string(vic);
+				cta.supported_hdmi_vic_codes |= 1 << (vic - 1);
+				t = find_vic_id(edid_hdmi_mode_map[vic - 1]);
+				print_timings("        ", t, suffix.c_str());
+			} else {
+				printf("         Unknown (HDMI VIC %u)\n", vic);
+				fail("Unknown HDMI VIC %u.\n", vic);
+			}
+		}
+
+		b += len_vic;
+	}
+
+	if (!len_3d)
+		return;
+
+	if (formats) {
+		/* 3D_Structure_ALL_15..8 */
+		if (x[b] & 0x80)
+			printf("      3D: Side-by-side (half, quincunx)\n");
+		if (x[b] & 0x01)
+			printf("      3D: Side-by-side (half, horizontal)\n");
+		/* 3D_Structure_ALL_7..0 */
+		b++;
+		if (x[b] & 0x40)
+			printf("      3D: Top-and-bottom\n");
+		if (x[b] & 0x20)
+			printf("      3D: L + depth + gfx + gfx-depth\n");
+		if (x[b] & 0x10)
+			printf("      3D: L + depth\n");
+		if (x[b] & 0x08)
+			printf("      3D: Side-by-side (full)\n");
+		if (x[b] & 0x04)
+			printf("      3D: Line-alternative\n");
+		if (x[b] & 0x02)
+			printf("      3D: Field-alternative\n");
+		if (x[b] & 0x01)
+			printf("      3D: Frame-packing\n");
+		b++;
+		len_3d -= 2;
+	}
+
+	if (mask) {
+		int max_idx = -1;
+		unsigned i;
+
+		printf("      3D VIC indices that support these capabilities:\n");
+		/* worst bit ordering ever */
+		for (i = 0; i < 8; i++)
+			if (x[b + 1] & (1 << i)) {
+				print_vic_index("        ", i, "");
+				max_idx = i;
+			}
+		for (i = 0; i < 8; i++)
+			if (x[b] & (1 << i)) {
+				print_vic_index("        ", i + 8, "");
+				max_idx = i + 8;
+			}
+		b += 2;
+		len_3d -= 2;
+		if (max_idx >= (int)cta.preparsed_svds[0].size())
+			fail("HDMI 3D VIC indices max index %d > %u (#SVDs).\n",
+			     max_idx + 1, cta.preparsed_svds[0].size());
+	}
+
+	/*
+	 * list of nibbles:
+	 * 2D_VIC_Order_X
+	 * 3D_Structure_X
+	 * (optionally: 3D_Detail_X and reserved)
+	 */
+	if (!len_3d)
+		return;
+
+	unsigned end = b + len_3d;
+	int max_idx = -1;
+
+	printf("      3D VIC indices with specific capabilities:\n");
+	while (b < end) {
+		unsigned char idx = x[b] >> 4;
+		std::string s;
+
+		if (idx > max_idx)
+			max_idx = idx;
+		switch (x[b] & 0x0f) {
+		case 0: s = "frame packing"; break;
+		case 1: s = "field alternative"; break;
+		case 2: s = "line alternative"; break;
+		case 3: s = "side-by-side (full)"; break;
+		case 4: s = "L + depth"; break;
+		case 5: s = "L + depth + gfx + gfx-depth"; break;
+		case 6: s = "top-and-bottom"; break;
+		case 8:
+			s = "side-by-side";
+			switch (x[b + 1] >> 4) {
+			case 0x00: s += ", any subsampling"; break;
+			case 0x01: s += ", horizontal"; break;
+			case 0x02: case 0x03: case 0x04: case 0x05:
+				   s += ", not in use";
+				   fail("not-in-use 3D_Detail_X value 0x%02x.\n",
+					x[b + 1] >> 4);
+				   break;
+			case 0x06: s += ", all quincunx combinations"; break;
+			case 0x07: s += ", quincunx odd/left, odd/right"; break;
+			case 0x08: s += ", quincunx odd/left, even/right"; break;
+			case 0x09: s += ", quincunx even/left, odd/right"; break;
+			case 0x0a: s += ", quincunx even/left, even/right"; break;
+			default:
+				   s += ", reserved";
+				   fail("reserved 3D_Detail_X value 0x%02x.\n",
+					x[b + 1] >> 4);
+				   break;
+			}
+			break;
+		default:
+			s = "unknown (";
+			s += utohex(x[b] & 0x0f) + ")";
+			fail("Unknown 3D_Structure_X value 0x%02x.\n", x[b] & 0x0f);
+			break;
+		}
+		print_vic_index("        ", idx, s.c_str());
+		if ((x[b] & 0x0f) >= 8)
+			b++;
+		b++;
+	}
+	if (max_idx >= (int)cta.preparsed_svds[0].size())
+		fail("HDMI 2D VIC indices max index %d > %u (#SVDs).\n",
+		     max_idx + 1, cta.preparsed_svds[0].size());
+}
+
+static const char *max_frl_rates[] = {
+	"Not Supported",
+	"3 Gbps per lane on 3 lanes",
+	"3 and 6 Gbps per lane on 3 lanes",
+	"3 and 6 Gbps per lane on 3 lanes, 6 Gbps on 4 lanes",
+	"3 and 6 Gbps per lane on 3 lanes, 6 and 8 Gbps on 4 lanes",
+	"3 and 6 Gbps per lane on 3 lanes, 6, 8 and 10 Gbps on 4 lanes",
+	"3 and 6 Gbps per lane on 3 lanes, 6, 8, 10 and 12 Gbps on 4 lanes",
+};
+
+static const char *dsc_max_slices[] = {
+	"Not Supported",
+	"up to 1 slice and up to (340 MHz/Ksliceadjust) pixel clock per slice",
+	"up to 2 slices and up to (340 MHz/Ksliceadjust) pixel clock per slice",
+	"up to 4 slices and up to (340 MHz/Ksliceadjust) pixel clock per slice",
+	"up to 8 slices and up to (340 MHz/Ksliceadjust) pixel clock per slice",
+	"up to 8 slices and up to (400 MHz/Ksliceadjust) pixel clock per slice",
+	"up to 12 slices and up to (400 MHz/Ksliceadjust) pixel clock per slice",
+	"up to 16 slices and up to (400 MHz/Ksliceadjust) pixel clock per slice",
+};
+
+static void cta_hf_eeodb(const unsigned char *x, unsigned length)
+{
+	printf("    EDID Extension Block Count: %u\n", x[0]);
+	if (length != 1 || x[0] == 0)
+		fail("Block is too long or reports a 0 block count.\n");
+}
+
+static void cta_hf_scdb(const unsigned char *x, unsigned length)
+{
+	unsigned rate = x[1] * 5;
+
+	printf("    Version: %u\n", x[0]);
+	if (rate) {
+		printf("    Maximum TMDS Character Rate: %u MHz\n", rate);
+		if (rate <= 340 || rate > 600)
+			fail("Max TMDS rate is > 0 and <= 340 or > 600.\n");
+	}
+	if (x[2] & 0x80)
+		printf("    SCDC Present\n");
+	if (x[2] & 0x40)
+		printf("    SCDC Read Request Capable\n");
+	if (x[2] & 0x10)
+		printf("    Supports Color Content Bits Per Component Indication\n");
+	if (x[2] & 0x08)
+		printf("    Supports scrambling for <= 340 Mcsc\n");
+	if (x[2] & 0x04)
+		printf("    Supports 3D Independent View signaling\n");
+	if (x[2] & 0x02)
+		printf("    Supports 3D Dual View signaling\n");
+	if (x[2] & 0x01)
+		printf("    Supports 3D OSD Disparity signaling\n");
+	if (x[3] & 0xf0) {
+		unsigned max_frl_rate = x[3] >> 4;
+
+		printf("    Max Fixed Rate Link: ");
+		if (max_frl_rate < ARRAY_SIZE(max_frl_rates)) {
+			printf("%s\n", max_frl_rates[max_frl_rate]);
+		} else {
+			printf("Unknown (0x%02x)\n", max_frl_rate);
+			fail("Unknown Max Fixed Rate Link (0x%02x).\n", max_frl_rate);
+		}
+		if (max_frl_rate == 1 && rate < 300)
+			fail("Max Fixed Rate Link is 1, but Max TMDS rate < 300.\n");
+		else if (max_frl_rate >= 2 && rate < 600)
+			fail("Max Fixed Rate Link is >= 2, but Max TMDS rate < 600.\n");
+	}
+	if (x[3] & 0x08)
+		printf("    Supports UHD VIC\n");
+	if (x[3] & 0x04)
+		printf("    Supports 16-bits/component Deep Color 4:2:0 Pixel Encoding\n");
+	if (x[3] & 0x02)
+		printf("    Supports 12-bits/component Deep Color 4:2:0 Pixel Encoding\n");
+	if (x[3] & 0x01)
+		printf("    Supports 10-bits/component Deep Color 4:2:0 Pixel Encoding\n");
+
+	if (length <= 4)
+		return;
+
+	if (x[4] & 0x20)
+		printf("    Supports Mdelta\n");
+	if (x[4] & 0x10)
+		printf("    Supports media rates below VRRmin (CinemaVRR)\n");
+	if (x[4] & 0x08)
+		printf("    Supports negative Mvrr values\n");
+	if (x[4] & 0x04)
+		printf("    Supports Fast Vactive\n");
+	if (x[4] & 0x02)
+		printf("    Supports Auto Low-Latency Mode\n");
+	if (x[4] & 0x01)
+		printf("    Supports a FAPA in blanking after first active video line\n");
+
+	if (length <= 5)
+		return;
+
+	printf("    VRRmin: %d Hz\n", x[5] & 0x3f);
+	printf("    VRRmax: %d Hz\n", (x[5] & 0xc0) << 2 | x[6]);
+
+	if (length <= 7)
+		return;
+
+	if (x[7] & 0x80)
+		printf("    Supports VESA DSC 1.2a compression\n");
+	if (x[7] & 0x40)
+		printf("    Supports Compressed Video Transport for 4:2:0 Pixel Encoding\n");
+	if (x[7] & 0x08)
+		printf("    Supports Compressed Video Transport at any valid 1/16th bit bpp\n");
+	if (x[7] & 0x04)
+		printf("    Supports 16 bpc Compressed Video Transport\n");
+	if (x[7] & 0x02)
+		printf("    Supports 12 bpc Compressed Video Transport\n");
+	if (x[7] & 0x01)
+		printf("    Supports 10 bpc Compressed Video Transport\n");
+	if (x[8] & 0xf) {
+		unsigned max_slices = x[8] & 0xf;
+
+		printf("    DSC Max Slices: ");
+		if (max_slices < ARRAY_SIZE(dsc_max_slices)) {
+			printf("%s\n", dsc_max_slices[max_slices]);
+		} else {
+			printf("Unknown (0x%02x)\n", max_slices);
+			fail("Unknown DSC Max Slices (0x%02x).\n", max_slices);
+		}
+	}
+	if (x[8] & 0xf0) {
+		unsigned max_frl_rate = x[8] >> 4;
+
+		printf("    DSC Max Fixed Rate Link: ");
+		if (max_frl_rate < ARRAY_SIZE(max_frl_rates)) {
+			printf("%s\n", max_frl_rates[max_frl_rate]);
+		} else {
+			printf("Unknown (0x%02x)\n", max_frl_rate);
+			fail("Unknown DSC Max Fixed Rate Link (0x%02x).\n", max_frl_rate);
+		}
+	}
+	if (x[9] & 0x3f)
+		printf("    Maximum number of bytes in a line of chunks: %u\n",
+		       1024 * (1 + (x[9] & 0x3f)));
+}
+
+static void cta_amd(const unsigned char *x, unsigned length)
+{
+	// These Freesync values are reversed engineered by looking
+	// at existing EDIDs.
+	printf("    Version: %u.%u\n", x[0], x[1]);
+	printf("    Minimum Refresh Rate: %u Hz\n", x[2]);
+	printf("    Maximum Refresh Rate: %u Hz\n", x[3]);
+	// Freesync 1.x flags
+	// One or more of the 0xe6 bits signal that the VESA MCCS
+	// protocol is used to switch the Freesync range
+	printf("    Flags 1.x: 0x%02x%s\n", x[4],
+	       (x[4] & 0xe6) ? " (MCCS)" : "");
+	if (length >= 10) {
+		// Freesync 2.x flags
+		// Bit 2 no doubt indicates if the monitor supports Local Dimming
+		// There are probably also bits to signal support of the
+		// FreeSync2_scRGB and FreeSync2_Gamma22 HDR display modes.
+		// I suspect bits 0 and 1.
+		printf("    Flags 2.x: 0x%02x\n", x[5]);
+		// The AMD tone mapping tutorial referred to in the URL below
+		// mentions that the Freesync HDR info reports max/min
+		// luminance of the monitor with and without local dimming.
+		//
+		// https://gpuopen.com/learn/using-amd-freesync-premium-pro-hdr-code-samples/
+		//
+		// So I assume that the first two luminance values are
+		// the max/min luminance of the display and the next two
+		// luminance values are the max/min luminance values when
+		// local dimming is disabled. The values I get seem to
+		// support that.
+		printf("    Maximum luminance: %u (%.3f cd/m^2)\n",
+		       x[6], 50.0 * pow(2, x[6] / 32.0));
+		printf("    Minimum luminance: %u (%.3f cd/m^2)\n",
+		       x[7], (50.0 * pow(2, x[6] / 32.0)) * pow(x[7] / 255.0, 2) / 100.0);
+		if (x[5] & 4) {
+			// One or both bytes can be 0. The meaning of that
+			// is unknown.
+			printf("    Maximum luminance (without local dimming): %u (%.3f cd/m^2)\n",
+			       x[8], 50.0 * pow(2, x[8] / 32.0));
+			printf("    Minimum luminance (without local dimming): %u (%.3f cd/m^2)\n",
+			       x[9], (50.0 * pow(2, x[8] / 32.0)) * pow(x[9] / 255.0, 2) / 100.0);
+		} else {
+			// These bytes are always 0x08 0x2f. If these values
+			// represent max/min luminance as well, then these
+			// would map to 59.460 and 0.020 cd/m^2 respectively.
+			// I wonder if this somehow relates to SDR.
+			printf("    Unknown: 0x%02x 0x%02x\n", x[8], x[9]);
+		}
+	}
+}
+
+static std::string display_use_case(unsigned char x)
+{
+	switch (x) {
+	case 1: return "Test equipment";
+	case 2: return "Generic display";
+	case 3: return "Television display";
+	case 4: return "Desktop productivity display";
+	case 5: return "Desktop gaming display";
+	case 6: return "Presentation display";
+	case 7: return "Virtual reality headset";
+	case 8: return "Augmented reality";
+	case 16: return "Video wall display";
+	case 17: return "Medical imaging display";
+	case 18: return "Dedicated gaming display";
+	case 19: return "Dedicated video monitor display";
+	case 20: return "Accessory display";
+	default: break;
+	}
+	fail("Unknown Display product primary use case 0x%02x.\n", x);
+	return std::string("Unknown display use case (") + utohex(x) + ")";
+}
+
+static void cta_microsoft(const unsigned char *x, unsigned length)
+{
+	// This VSDB is documented at:
+	// https://docs.microsoft.com/en-us/windows-hardware/drivers/display/specialized-monitors-edid-extension
+	printf("    Version: %u\n", x[0]);
+	if (x[0] > 2) {
+		// In version 1 and 2 these bits should always be set to 0.
+		printf("    Desktop Usage: %u\n", (x[1] >> 6) & 1);
+		printf("    Third-Party Usage: %u\n", (x[1] >> 5) & 1);
+	}
+	printf("    Display Product Primary Use Case: %u (%s)\n", x[1] & 0x1f,
+	       display_use_case(x[1] & 0x1f).c_str());
+	printf("    Container ID: %s\n", containerid2s(x + 2).c_str());
+}
+
+static void cta_hdr10plus(const unsigned char *x, unsigned length)
+{
+	printf("    Application Version: %u", x[0]);
+	if (length > 1)
+		hex_block("  ", x + 1, length - 1);
+	else
+		printf("\n");
+}
+
+static void cta_dolby_video(const unsigned char *x, unsigned length)
+{
+	unsigned char version = (x[0] >> 5) & 0x07;
+
+	printf("    Version: %u (%u bytes)\n", version, length + 5);
+	if (x[0] & 0x01)
+		printf("    Supports YUV422 12 bit\n");
+
+	if (version == 0) {
+		if (x[0] & 0x02)
+			printf("    Supports 2160p60\n");
+		if (x[0] & 0x04)
+			printf("    Supports global dimming\n");
+		unsigned char dm_version = x[16];
+		printf("    DM Version: %u.%u\n", dm_version >> 4, dm_version & 0xf);
+		printf("    Target Min PQ: %u\n", (x[14] << 4) | (x[13] >> 4));
+		printf("    Target Max PQ: %u\n", (x[15] << 4) | (x[13] & 0xf));
+		printf("    Rx, Ry: %.8f, %.8f\n",
+		       ((x[1] >> 4) | (x[2] << 4)) / 4096.0,
+		       ((x[1] & 0xf) | (x[3] << 4)) / 4096.0);
+		printf("    Gx, Gy: %.8f, %.8f\n",
+		       ((x[4] >> 4) | (x[5] << 4)) / 4096.0,
+		       ((x[4] & 0xf) | (x[6] << 4)) / 4096.0);
+		printf("    Bx, By: %.8f, %.8f\n",
+		       ((x[7] >> 4) | (x[8] << 4)) / 4096.0,
+		       ((x[7] & 0xf) | (x[9] << 4)) / 4096.0);
+		printf("    Wx, Wy: %.8f, %.8f\n",
+		       ((x[10] >> 4) | (x[11] << 4)) / 4096.0,
+		       ((x[10] & 0xf) | (x[12] << 4)) / 4096.0);
+		return;
+	}
+
+	if (version == 1) {
+		if (x[0] & 0x02)
+			printf("    Supports 2160p60\n");
+		if (x[1] & 0x01)
+			printf("    Supports global dimming\n");
+		unsigned char dm_version = (x[0] >> 2) & 0x07;
+		printf("    DM Version: %u.x\n", dm_version + 2);
+		printf("    Colorimetry: %s\n", (x[2] & 0x01) ? "P3-D65" : "ITU-R BT.709");
+		printf("    Low Latency: %s\n", (x[3] & 0x01) ? "Standard + Low Latency" : "Only Standard");
+		printf("    Target Max Luminance: %u cd/m^2\n", 100 + (x[1] >> 1) * 50);
+		double lm = (x[2] >> 1) / 127.0;
+		printf("    Target Min Luminance: %.8f cd/m^2\n", lm * lm);
+		if (length == 10) {
+			printf("    Rx, Ry: %.8f, %.8f\n", x[4] / 256.0, x[5] / 256.0);
+			printf("    Gx, Gy: %.8f, %.8f\n", x[6] / 256.0, x[7] / 256.0);
+			printf("    Bx, By: %.8f, %.8f\n", x[8] / 256.0, x[9] / 256.0);
+		} else {
+			double xmin = 0.625;
+			double xstep = (0.74609375 - xmin) / 31.0;
+			double ymin = 0.25;
+			double ystep = (0.37109375 - ymin) / 31.0;
+
+			printf("    Unique Rx, Ry: %.8f, %.8f\n",
+			       xmin + xstep * (x[6] >> 3),
+			       ymin + ystep * (((x[6] & 0x7) << 2) | (x[4] & 0x01) | ((x[5] & 0x01) << 1)));
+			xstep = 0.49609375 / 127.0;
+			ymin = 0.5;
+			ystep = (0.99609375 - ymin) / 127.0;
+			printf("    Unique Gx, Gy: %.8f, %.8f\n",
+			       xstep * (x[4] >> 1), ymin + ystep * (x[5] >> 1));
+			xmin = 0.125;
+			xstep = (0.15234375 - xmin) / 7.0;
+			ymin = 0.03125;
+			ystep = (0.05859375 - ymin) / 7.0;
+			printf("    Unique Bx, By: %.8f, %.8f\n",
+			       xmin + xstep * (x[3] >> 5),
+			       ymin + ystep * ((x[3] >> 2) & 0x07));
+		}
+		return;
+	}
+
+	if (version == 2) {
+		if (x[0] & 0x02)
+			printf("    Supports Backlight Control\n");
+		if (x[1] & 0x04)
+			printf("    Supports global dimming\n");
+		unsigned char dm_version = (x[0] >> 2) & 0x07;
+		printf("    DM Version: %u.x\n", dm_version + 2);
+		printf("    Backlt Min Luma: %u cd/m^2\n", 25 + (x[1] & 0x03) * 25);
+		printf("    Interface: ");
+		switch (x[2] & 0x03) {
+		case 0: printf("Low-Latency\n"); break;
+		case 1: printf("Low-Latency + Low-Latency-HDMI\n"); break;
+		case 2: printf("Standard + Low-Latency\n"); break;
+		case 3: printf("Standard + Low-Latency + Low-Latency-HDMI\n"); break;
+		}
+		printf("    Supports 10b 12b 444: ");
+		switch ((x[3] & 0x01) << 1 | (x[4] & 0x01)) {
+		case 0: printf("Not supported\n"); break;
+		case 1: printf("10 bit\n"); break;
+		case 2: printf("12 bit\n"); break;
+		case 3: printf("Reserved\n"); break;
+		}
+		printf("    Target Min PQ v2: %u\n", 20 * (x[1] >> 3));
+		printf("    Target Max PQ v2: %u\n", 2055 + 65 * (x[2] >> 3));
+
+		double xmin = 0.625;
+		double xstep = (0.74609375 - xmin) / 31.0;
+		double ymin = 0.25;
+		double ystep = (0.37109375 - ymin) / 31.0;
+
+		printf("    Unique Rx, Ry: %.8f, %.8f\n",
+		       xmin + xstep * (x[5] >> 3),
+		       ymin + ystep * (x[6] >> 3));
+		xstep = 0.49609375 / 127.0;
+		ymin = 0.5;
+		ystep = (0.99609375 - ymin) / 127.0;
+		printf("    Unique Gx, Gy: %.8f, %.8f\n",
+		       xstep * (x[3] >> 1), ymin + ystep * (x[4] >> 1));
+		xmin = 0.125;
+		xstep = (0.15234375 - xmin) / 7.0;
+		ymin = 0.03125;
+		ystep = (0.05859375 - ymin) / 7.0;
+		printf("    Unique Bx, By: %.8f, %.8f\n",
+		       xmin + xstep * (x[5] & 0x07),
+		       ymin + ystep * (x[6] & 0x07));
+	}
+}
+
+static void cta_dolby_audio(const unsigned char *x, unsigned length)
+{
+	unsigned char version = 1 + (x[0] & 0x07);
+
+	printf("    Version: %u (%u bytes)\n", version, length + 5);
+	if (x[0] & 0x80)
+		printf("    Headphone playback only\n");
+	if (x[0] & 0x40)
+		printf("    Height speaker zone present\n");
+	if (x[0] & 0x20)
+		printf("    Surround speaker zone present\n");
+	if (x[0] & 0x10)
+		printf("    Center speaker zone present\n");
+	if (x[1] & 0x01)
+		printf("    Supports Dolby MAT PCM decoding at 48 kHz only, does not support TrueHD\n");
+}
+
+static const char *speaker_map[] = {
+	"FL/FR - Front Left/Right",
+	"LFE1 - Low Frequency Effects 1",
+	"FC - Front Center",
+	"BL/BR - Back Left/Right",
+	"BC - Back Center",
+	"FLc/FRc - Front Left/Right of Center",
+	"RLC/RRC - Rear Left/Right of Center (Deprecated)",
+	"FLw/FRw - Front Left/Right Wide",
+	"TpFL/TpFR - Top Front Left/Right",
+	"TpC - Top Center",
+	"TpFC - Top Front Center",
+	"LS/RS - Left/Right Surround",
+	"LFE2 - Low Frequency Effects 2",
+	"TpBC - Top Back Center",
+	"SiL/SiR - Side Left/Right",
+	"TpSiL/TpSiR - Top Side Left/Right",
+	"TpBL/TpBR - Top Back Left/Right",
+	"BtFC - Bottom Front Center",
+	"BtFL/BtFR - Bottom Front Left/Right",
+	"TpLS/TpRS - Top Left/Right Surround (Deprecated for CTA-861)",
+	"LSd/RSd - Left/Right Surround Direct (HDMI only)",
+};
+
+static void cta_sadb(const unsigned char *x, unsigned length)
+{
+	unsigned sad;
+	unsigned i;
+
+	if (length < 3) {
+		fail("Empty Data Block with length %u.\n", length);
+		return;
+	}
+
+	sad = ((x[2] << 16) | (x[1] << 8) | x[0]);
+
+	for (i = 0; i < ARRAY_SIZE(speaker_map); i++) {
+		if ((sad >> i) & 1)
+			printf("    %s\n", speaker_map[i]);
+	}
+}
+
+static void cta_vesa_dtcdb(const unsigned char *x, unsigned length)
+{
+	if (length != 7 && length != 15 && length != 31) {
+		fail("Invalid length %u.\n", length);
+		return;
+	}
+
+	switch (x[0] >> 6) {
+	case 0: printf("    White"); break;
+	case 1: printf("    Red"); break;
+	case 2: printf("    Green"); break;
+	case 3: printf("    Blue"); break;
+	}
+	unsigned v = x[0] & 0x3f;
+	printf(" transfer characteristics: %u", v);
+	for (unsigned i = 1; i < length; i++)
+		printf(" %u", v += x[i]);
+	printf(" 1023\n");
+}
+
+static void cta_vesa_vdddb(const unsigned char *x, unsigned length)
+{
+	if (length != 30) {
+		fail("Invalid length %u.\n", length);
+		return;
+	}
+
+	printf("    Interface Type: ");
+	unsigned char v = x[0];
+	switch (v >> 4) {
+	case 0: printf("Analog (");
+		switch (v & 0xf) {
+		case 0: printf("15HD/VGA"); break;
+		case 1: printf("VESA NAVI-V (15HD)"); break;
+		case 2: printf("VESA NAVI-D"); break;
+		default: printf("Reserved"); break;
+		}
+		printf(")\n");
+		break;
+	case 1: printf("LVDS %u lanes", v & 0xf); break;
+	case 2: printf("RSDS %u lanes", v & 0xf); break;
+	case 3: printf("DVI-D %u channels", v & 0xf); break;
+	case 4: printf("DVI-I analog"); break;
+	case 5: printf("DVI-I digital %u channels", v & 0xf); break;
+	case 6: printf("HDMI-A"); break;
+	case 7: printf("HDMI-B"); break;
+	case 8: printf("MDDI %u channels", v & 0xf); break;
+	case 9: printf("DisplayPort %u channels", v & 0xf); break;
+	case 10: printf("IEEE-1394"); break;
+	case 11: printf("M1 analog"); break;
+	case 12: printf("M1 digital %u channels", v & 0xf); break;
+	default: printf("Reserved"); break;
+	}
+	printf("\n");
+
+	printf("    Interface Standard Version: %u.%u\n", x[1] >> 4, x[1] & 0xf);
+	printf("    Content Protection Support: ");
+	switch (x[2]) {
+	case 0: printf("None\n"); break;
+	case 1: printf("HDCP\n"); break;
+	case 2: printf("DTCP\n"); break;
+	case 3: printf("DPCP\n"); break;
+	default: printf("Reserved\n"); break;
+	}
+
+	printf("    Minimum Clock Frequency: %u MHz\n", x[3] >> 2);
+	printf("    Maximum Clock Frequency: %u MHz\n", ((x[3] & 0x03) << 8) | x[4]);
+	printf("    Device Native Pixel Format: %ux%u\n",
+	       x[5] | (x[6] << 8), x[7] | (x[8] << 8));
+	printf("    Aspect Ratio: %.2f\n", (100 + x[9]) / 100.0);
+	v = x[0x0a];
+	printf("    Default Orientation: ");
+	switch ((v & 0xc0) >> 6) {
+	case 0x00: printf("Landscape\n"); break;
+	case 0x01: printf("Portrait\n"); break;
+	case 0x02: printf("Not Fixed\n"); break;
+	case 0x03: printf("Undefined\n"); break;
+	}
+	printf("    Rotation Capability: ");
+	switch ((v & 0x30) >> 4) {
+	case 0x00: printf("None\n"); break;
+	case 0x01: printf("Can rotate 90 degrees clockwise\n"); break;
+	case 0x02: printf("Can rotate 90 degrees counterclockwise\n"); break;
+	case 0x03: printf("Can rotate 90 degrees in either direction)\n"); break;
+	}
+	printf("    Zero Pixel Location: ");
+	switch ((v & 0x0c) >> 2) {
+	case 0x00: printf("Upper Left\n"); break;
+	case 0x01: printf("Upper Right\n"); break;
+	case 0x02: printf("Lower Left\n"); break;
+	case 0x03: printf("Lower Right\n"); break;
+	}
+	printf("    Scan Direction: ");
+	switch (v & 0x03) {
+	case 0x00: printf("Not defined\n"); break;
+	case 0x01: printf("Fast Scan is on the Major (Long) Axis and Slow Scan is on the Minor Axis\n"); break;
+	case 0x02: printf("Fast Scan is on the Minor (Short) Axis and Slow Scan is on the Major Axis\n"); break;
+	case 0x03: printf("Reserved\n");
+		   fail("Scan Direction used the reserved value 0x03.\n");
+		   break;
+	}
+	printf("    Subpixel Information: ");
+	switch (x[0x0b]) {
+	case 0x00: printf("Not defined\n"); break;
+	case 0x01: printf("RGB vertical stripes\n"); break;
+	case 0x02: printf("RGB horizontal stripes\n"); break;
+	case 0x03: printf("Vertical stripes using primary order\n"); break;
+	case 0x04: printf("Horizontal stripes using primary order\n"); break;
+	case 0x05: printf("Quad sub-pixels, red at top left\n"); break;
+	case 0x06: printf("Quad sub-pixels, red at bottom left\n"); break;
+	case 0x07: printf("Delta (triad) RGB sub-pixels\n"); break;
+	case 0x08: printf("Mosaic\n"); break;
+	case 0x09: printf("Quad sub-pixels, RGB + 1 additional color\n"); break;
+	case 0x0a: printf("Five sub-pixels, RGB + 2 additional colors\n"); break;
+	case 0x0b: printf("Six sub-pixels, RGB + 3 additional colors\n"); break;
+	case 0x0c: printf("Clairvoyante, Inc. PenTile Matrix (tm) layout\n"); break;
+	default: printf("Reserved\n"); break;
+	}
+	printf("    Horizontal and vertical dot/pixel pitch: %.2f x %.2f mm\n",
+	       (double)(x[0x0c]) / 100.0, (double)(x[0x0d]) / 100.0);
+	v = x[0x0e];
+	printf("    Dithering: ");
+	switch (v >> 6) {
+	case 0: printf("None\n"); break;
+	case 1: printf("Spatial\n"); break;
+	case 2: printf("Temporal\n"); break;
+	case 3: printf("Spatial and Temporal\n"); break;
+	}
+	printf("    Direct Drive: %s\n", (v & 0x20) ? "Yes" : "No");
+	printf("    Overdrive %srecommended\n", (v & 0x10) ? "not " : "");
+	printf("    Deinterlacing: %s\n", (v & 0x08) ? "Yes" : "No");
+
+	v = x[0x0f];
+	printf("    Audio Support: %s\n", (v & 0x80) ? "Yes" : "No");
+	printf("    Separate Audio Inputs Provided: %s\n", (v & 0x40) ? "Yes" : "No");
+	printf("    Audio Input Override: %s\n", (v & 0x20) ? "Yes" : "No");
+	v = x[0x10];
+	if (v)
+		printf("    Audio Delay: %s%u ms\n", (v & 0x80) ? "" : "-", (v & 0x7f) * 2);
+	else
+		printf("    Audio Delay: no information provided\n");
+	v = x[0x11];
+	printf("    Frame Rate/Mode Conversion: ");
+	switch (v >> 6) {
+	case 0: printf("None\n"); break;
+	case 1: printf("Single Buffering\n"); break;
+	case 2: printf("Double Buffering\n"); break;
+	case 3: printf("Advanced Frame Rate Conversion\n"); break;
+	}
+	if (v & 0x3f)
+		printf("    Frame Rate Range: %u fps +/- %u fps\n",
+		       x[0x12], v & 0x3f);
+	else
+		printf("    Nominal Frame Rate: %u fps\n", x[0x12]);
+	printf("    Color Bit Depth: %u @ interface, %u @ display\n",
+	       (x[0x13] >> 4) + 1, (x[0x13] & 0xf) + 1);
+	v = x[0x15] & 3;
+	if (v) {
+		printf("    Additional Primary Chromaticities:\n");
+		unsigned col_x = (x[0x16] << 2) | (x[0x14] >> 6);
+		unsigned col_y = (x[0x17] << 2) | ((x[0x14] >> 4) & 3);
+		printf("      Primary 4:   0.%04u, 0.%04u\n",
+		       (col_x * 10000) / 1024, (col_y * 10000) / 1024);
+		if (v > 1) {
+			col_x = (x[0x18] << 2) | ((x[0x14] >> 2) & 3);
+			col_y = (x[0x19] << 2) | (x[0x14] & 3);
+			printf("      Primary 5:   0.%04u, 0.%04u\n",
+			       (col_x * 10000) / 1024, (col_y * 10000) / 1024);
+			if (v > 2) {
+				col_x = (x[0x1a] << 2) | (x[0x15] >> 6);
+				col_y = (x[0x1b] << 2) | ((x[0x15] >> 4) & 3);
+				printf("      Primary 6:   0.%04u, 0.%04u\n",
+				       (col_x * 10000) / 1024, (col_y * 10000) / 1024);
+			}
+		}
+	}
+
+	v = x[0x1c];
+	printf("    Response Time %s: %u ms\n",
+	       (v & 0x80) ? "White -> Black" : "Black -> White", v & 0x7f);
+	v = x[0x1d];
+	printf("    Overscan: %u%% x %u%%\n", v >> 4, v & 0xf);
+}
+
+static double decode_uchar_as_double(unsigned char x)
+{
+	signed char s = (signed char)x;
+
+	return s / 64.0;
+}
+
+void edid_state::cta_rcdb(const unsigned char *x, unsigned length)
+{
+	unsigned spm = ((x[3] << 16) | (x[2] << 8) | x[1]);
+	unsigned i;
+
+	if (length < 4) {
+		fail("Empty Data Block with length %u.\n", length);
+		return;
+	}
+
+	if ((x[0] & 0x20) && !cta.has_sldb)
+		fail("'SLD' flag is 1, but no Speaker Location Data Block is found.\n");
+	else if (!(x[0] & 0x20) && cta.has_sldb)
+		fail("'SLD' flag is 0, but a Speaker Location Data Block is present.\n");
+
+	if (x[0] & 0x40) {
+		printf("    Speaker count: %u\n", (x[0] & 0x1f) + 1);
+	} else {
+		if (x[0] & 0x1f)
+			fail("'Speaker' flag is 0, but 'Speaker Count' is != 0.\n");
+		if (x[0] & 0x20)
+			fail("'SLD' flag is 1, but 'Speaker' is 0.\n");
+	}
+
+	printf("    Speaker Presence Mask:\n");
+	for (i = 0; i < ARRAY_SIZE(speaker_map); i++) {
+		if ((spm >> i) & 1)
+			printf("      %s\n", speaker_map[i]);
+	}
+
+	if ((x[0] & 0xa0) == 0x80)
+		fail("'Display' flag set, but not the 'SLD' flag.\n");
+
+	bool valid_max = cta.preparsed_sld_has_coord || (x[0] & 0x80);
+
+	if (valid_max && length >= 7) {
+		printf("    Xmax: %u dm\n", x[4]);
+		printf("    Ymax: %u dm\n", x[5]);
+		printf("    Zmax: %u dm\n", x[6]);
+	} else if (!valid_max && length >= 7) {
+		// The RCDB should have been truncated.
+		warn("'Display' flag is 0 and 'Coord' is 0 for all SLDs, but the Max coordinates are still present.\n");
+	}
+	if ((x[0] & 0x80) && length >= 10) {
+		printf("    DisplayX: %.3f * Xmax\n", decode_uchar_as_double(x[7]));
+		printf("    DisplayY: %.3f * Ymax\n", decode_uchar_as_double(x[8]));
+		printf("    DisplayZ: %.3f * Zmax\n", decode_uchar_as_double(x[9]));
+	} else if (!(x[0] & 0x80) && length >= 10) {
+		// The RCDB should have been truncated.
+		warn("'Display' flag is 0, but the Display coordinates are still present.\n");
+	}
+}
+
+static const char *speaker_location[] = {
+	"FL - Front Left",
+	"FR - Front Right",
+	"FC - Front Center",
+	"LFE1 - Low Frequency Effects 1",
+	"BL - Back Left",
+	"BR - Back Right",
+	"FLC - Front Left of Center",
+	"FRC - Front Right of Center",
+	"BC - Back Center",
+	"LFE2 - Low Frequency Effects 2",
+	"SiL - Side Left",
+	"SiR - Side Right",
+	"TpFL - Top Front Left",
+	"TpFR - Top Front Right",
+	"TpFC - Top Front Center",
+	"TpC - Top Center",
+	"TpBL - Top Back Left",
+	"TpBR - Top Back Right",
+	"TpSiL - Top Side Left",
+	"TpSiR - Top Side Right",
+	"TpBC - Top Back Center",
+	"BtFC - Bottom Front Center",
+	"BtFL - Bottom Front Left",
+	"BtFR - Bottom Front Right",
+	"FLW - Front Left Wide",
+	"FRW - Front Right Wide",
+	"LS - Left Surround",
+	"RS - Right Surround",
+};
+
+void edid_state::cta_sldb(const unsigned char *x, unsigned length)
+{
+	if (length < 2) {
+		fail("Empty Data Block with length %u.\n", length);
+		return;
+	}
+
+	unsigned active_cnt = 0;
+	unsigned channel_is_active = 0;
+
+	while (length >= 2) {
+		printf("    Channel: %u (%sactive)\n", x[0] & 0x1f,
+		       (x[0] & 0x20) ? "" : "not ");
+		if (x[0] & 0x20) {
+			if (channel_is_active & (1U << (x[0] & 0x1f)))
+				fail("Channel Index %u was already marked 'Active'.\n",
+				     x[0] & 0x1f);
+			channel_is_active |= 1U << (x[0] & 0x1f);
+			active_cnt++;
+		}
+		if ((x[1] & 0x1f) < ARRAY_SIZE(speaker_location))
+			printf("      Speaker: %s\n", speaker_location[x[1] & 0x1f]);
+		if (length >= 5 && (x[0] & 0x40)) {
+			printf("      X: %.3f * Xmax\n", decode_uchar_as_double(x[2]));
+			printf("      Y: %.3f * Ymax\n", decode_uchar_as_double(x[3]));
+			printf("      Z: %.3f * Zmax\n", decode_uchar_as_double(x[4]));
+			length -= 3;
+			x += 3;
+		}
+
+		length -= 2;
+		x += 2;
+	}
+	if (active_cnt != cta.preparsed_speaker_count)
+		fail("There are %u active speakers, but 'Speaker Count' is %u.\n",
+		     active_cnt, cta.preparsed_speaker_count);
+}
+
+void edid_state::cta_preparse_sldb(const unsigned char *x, unsigned length)
+{
+	cta.has_sldb = true;
+	while (length >= 2) {
+		if (length >= 5 && (x[0] & 0x40)) {
+			cta.preparsed_sld_has_coord = true;
+			return;
+		}
+		length -= 2;
+		x += 2;
+	}
+}
+
+void edid_state::cta_vcdb(const unsigned char *x, unsigned length)
+{
+	unsigned char d = x[0];
+
+	cta.has_vcdb = true;
+	if (length < 1) {
+		fail("Empty Data Block with length %u.\n", length);
+		return;
+	}
+	printf("    YCbCr quantization: %s\n",
+	       (d & 0x80) ? "Selectable (via AVI YQ)" : "No Data");
+	printf("    RGB quantization: %s\n",
+	       (d & 0x40) ? "Selectable (via AVI Q)" : "No Data");
+	/*
+	 * If this bit is not set then that will result in interoperability
+	 * problems (specifically with PCs/laptops) that quite often do not
+	 * follow the default rules with respect to RGB Quantization Range
+	 * handling.
+	 *
+	 * Starting with the CTA-861-H spec this bit is now required to be
+	 * 1 for new designs.
+	 */
+	if (!(d & 0x40))
+		fail("Set Selectable RGB Quantization to avoid interop issues.\n");
+	/*
+	 * Since most YCbCr formats use limited range, the interop issues are
+	 * less noticable than for RGB formats.
+	 *
+	 * Starting with the CTA-861-H spec this bit is now required to be
+	 * 1 for new designs, but just warn about it (for now).
+	 */
+	if ((cta.byte3 & 0x30) && !(d & 0x80))
+		warn("Set Selectable YCbCr Quantization to avoid interop issues.\n");
+
+	unsigned char s_pt = (d >> 4) & 0x03;
+	unsigned char s_it = (d >> 2) & 0x03;
+	unsigned char s_ce = d & 0x03;
+
+	printf("    PT scan behavior: ");
+	switch (s_pt) {
+	case 0: printf("No Data\n"); break;
+	case 1: printf("Always Overscanned\n"); break;
+	case 2: printf("Always Underscanned\n"); break;
+	case 3: printf("Supports both over- and underscan\n"); break;
+	}
+	printf("    IT scan behavior: ");
+	switch (s_it) {
+	case 0: printf("IT video formats not supported\n"); break;
+	case 1:
+		printf("Always Overscanned\n");
+		// See Table 52 of CTA-861-G for a description of Byte 3
+		if (cta.byte3 & 0x80)
+			fail("IT video formats are always overscanned, but bit 7 of Byte 3 of the CTA-861 Extension header is set to underscanned.\n");
+		break;
+	case 2:
+		printf("Always Underscanned\n");
+		// See Table 52 of CTA-861-G for a description of Byte 3
+		if (!(cta.byte3 & 0x80))
+			fail("IT video formats are always underscanned, but bit 7 of Byte 3 of the CTA-861 Extension header is set to overscanned.\n");
+		break;
+	case 3: printf("Supports both over- and underscan\n"); break;
+	}
+	if (s_it < 2)
+		warn("IT scan behavior is expected to support underscanned.\n");
+	printf("    CE scan behavior: ");
+	switch (s_ce) {
+	case 0: printf("CE video formats not supported\n"); break;
+	case 1: printf("Always Overscanned\n"); break;
+	case 2: printf("Always Underscanned\n"); break;
+	case 3: printf("Supports both over- and underscan\n"); break;
+	}
+	if (s_ce == 0)
+		warn("'CE video formats not supported' makes no sense.\n");
+	else if (s_pt == s_it && s_pt == s_ce)
+		warn("S_PT is equal to S_IT and S_CE, so should be set to 0 instead.\n");
+}
+
+static const char *colorimetry_map[] = {
+	"xvYCC601",
+	"xvYCC709",
+	"sYCC601",
+	"opYCC601",
+	"opRGB",
+	"BT2020cYCC",
+	"BT2020YCC",
+	"BT2020RGB",
+};
+
+static void cta_colorimetry_block(const unsigned char *x, unsigned length)
+{
+	unsigned i;
+
+	if (length < 2) {
+		fail("Empty Data Block with length %u.\n", length);
+		return;
+	}
+	for (i = 0; i < ARRAY_SIZE(colorimetry_map); i++) {
+		if (x[0] & (1 << i))
+			printf("    %s\n", colorimetry_map[i]);
+	}
+	if (x[1] & 0x80)
+		printf("    DCI-P3\n");
+	if (x[1] & 0x40)
+		printf("    ICtCp\n");
+}
+
+static const char *eotf_map[] = {
+	"Traditional gamma - SDR luminance range",
+	"Traditional gamma - HDR luminance range",
+	"SMPTE ST2084",
+	"Hybrid Log-Gamma",
+};
+
+static void cta_hdr_static_metadata_block(const unsigned char *x, unsigned length)
+{
+	unsigned i;
+
+	if (length < 2) {
+		fail("Empty Data Block with length %u.\n", length);
+		return;
+	}
+	printf("    Electro optical transfer functions:\n");
+	for (i = 0; i < 6; i++) {
+		if (x[0] & (1 << i)) {
+			if (i < ARRAY_SIZE(eotf_map)) {
+				printf("      %s\n", eotf_map[i]);
+			} else {
+				printf("      Unknown (%u)\n", i);
+				fail("Unknown EOTF (%u).\n", i);
+			}
+		}
+	}
+	printf("    Supported static metadata descriptors:\n");
+	for (i = 0; i < 8; i++) {
+		if (x[1] & (1 << i))
+			printf("      Static metadata type %u\n", i + 1);
+	}
+
+	if (length >= 3)
+		printf("    Desired content max luminance: %u (%.3f cd/m^2)\n",
+		       x[2], 50.0 * pow(2, x[2] / 32.0));
+
+	if (length >= 4)
+		printf("    Desired content max frame-average luminance: %u (%.3f cd/m^2)\n",
+		       x[3], 50.0 * pow(2, x[3] / 32.0));
+
+	if (length >= 5)
+		printf("    Desired content min luminance: %u (%.3f cd/m^2)\n",
+		       x[4], (50.0 * pow(2, x[2] / 32.0)) * pow(x[4] / 255.0, 2) / 100.0);
+}
+
+static void cta_hdr_dyn_metadata_block(const unsigned char *x, unsigned length)
+{
+	if (length < 3) {
+		fail("Empty Data Block with length %u.\n", length);
+		return;
+	}
+	while (length >= 3) {
+		unsigned type_len = x[0];
+		unsigned type = x[1] | (x[2] << 8);
+
+		if (length < type_len + 1)
+			return;
+		printf("    HDR Dynamic Metadata Type %u\n", type);
+		switch (type) {
+		case 1:
+		case 4:
+			if (type_len > 2)
+				printf("      Version: %u\n", x[3] & 0xf);
+			break;
+		case 2:
+			if (type_len > 2) {
+				unsigned version = x[3] & 0xf;
+				printf("      Version: %u\n", version);
+				if (version >= 1) {
+					if (x[3] & 0x10) printf("      Supports SL-HDR1 (ETSI TS 103 433-1)\n");
+					if (x[3] & 0x20) printf("      Supports SL-HDR2 (ETSI TS 103 433-2)\n");
+					if (x[3] & 0x40) printf("      Supports SL-HDR3 (ETSI TS 103 433-3)\n");
+				}
+			}
+			break;
+		default:
+			break;
+		}
+		length -= type_len + 1;
+		x += type_len + 1;
+	}
+}
+
+static void cta_ifdb(const unsigned char *x, unsigned length)
+{
+	unsigned len_hdr = x[0] >> 5;
+
+	if (length < 2) {
+		fail("Empty Data Block with length %u.\n", length);
+		return;
+	}
+	printf("    VSIFs: %u\n", x[1]);
+	if (length < len_hdr + 2)
+		return;
+	length -= len_hdr + 2;
+	x += len_hdr + 2;
+	while (length > 0) {
+		int payload_len = x[0] >> 5;
+
+		if ((x[0] & 0x1f) == 1 && length >= 4) {
+			unsigned oui = (x[3] << 16) | (x[2] << 8) | x[1];
+
+			printf("    InfoFrame Type Code %u, OUI %s\n",
+			       x[0] & 0x1f, ouitohex(oui).c_str());
+			x += 4;
+			length -= 4;
+		} else {
+			printf("    InfoFrame Type Code %u\n", x[0] & 0x1f);
+			x++;
+			length--;
+		}
+		x += payload_len;
+		length -= payload_len;
+	}
+}
+
+void edid_state::cta_displayid_type_7(const unsigned char *x, unsigned length)
+{
+	check_displayid_datablock_revision(x[0], 0x00, 2);
+
+	if (length < 21U + ((x[0] & 0x70) >> 4)) {
+		fail("Empty Data Block with length %u.\n", length);
+		return;
+	}
+	parse_displayid_type_1_7_timing(x + 1, true, 2, true);
+}
+
+void edid_state::cta_displayid_type_8(const unsigned char *x, unsigned length)
+{
+	check_displayid_datablock_revision(x[0], 0xe8, 1);
+	if (length < ((x[0] & 0x08) ? 3 : 2)) {
+		fail("Empty Data Block with length %u.\n", length);
+		return;
+	}
+
+	unsigned sz = (x[0] & 0x08) ? 2 : 1;
+	unsigned type = x[0] >> 6;
+
+	if (type) {
+		fail("Only code type 0 is supported.\n");
+		return;
+	}
+
+	if (x[0] & 0x20)
+		printf("    Also supports YCbCr 4:2:0\n");
+
+	x++;
+	length--;
+	for (unsigned i = 0; i < length / sz; i++) {
+		unsigned id = x[i * sz];
+
+		if (sz == 2)
+			id |= x[i * sz + 1] << 8;
+		parse_displayid_type_4_8_timing(type, id, true);
+	}
+}
+
+void edid_state::cta_displayid_type_10(const unsigned char *x, unsigned length)
+{
+	check_displayid_datablock_revision(x[0], 0x70);
+	if (length < 7U + ((x[0] & 0x70) >> 4)) {
+		fail("Empty Data Block with length %u.\n", length);
+		return;
+	}
+
+	unsigned sz = 6U + ((x[0] & 0x70) >> 4);
+	x++;
+	length--;
+	for (unsigned i = 0; i < length / sz; i++)
+		parse_displayid_type_10_timing(x + i * sz, true);
+}
+
+static void cta_hdmi_audio_block(const unsigned char *x, unsigned length)
+{
+	unsigned num_descs;
+
+	if (length < 2) {
+		fail("Empty Data Block with length %u.\n", length);
+		return;
+	}
+	if (x[0] & 3)
+		printf("    Max Stream Count: %u\n", (x[0] & 3) + 1);
+	if (x[0] & 4)
+		printf("    Supports MS NonMixed\n");
+
+	num_descs = x[1] & 7;
+	if (num_descs == 0)
+		return;
+	length -= 2;
+	x += 2;
+	while (length >= 4) {
+		if (length > 4) {
+			unsigned format = x[0] & 0xf;
+
+			printf("    %s, max channels %u\n", audio_format(format).c_str(),
+			       (x[1] & 0x1f)+1);
+			printf("      Supported sample rates (kHz):%s%s%s%s%s%s%s\n",
+			       (x[2] & 0x40) ? " 192" : "",
+			       (x[2] & 0x20) ? " 176.4" : "",
+			       (x[2] & 0x10) ? " 96" : "",
+			       (x[2] & 0x08) ? " 88.2" : "",
+			       (x[2] & 0x04) ? " 48" : "",
+			       (x[2] & 0x02) ? " 44.1" : "",
+			       (x[2] & 0x01) ? " 32" : "");
+			if (format == 1)
+				printf("      Supported sample sizes (bits):%s%s%s\n",
+				       (x[3] & 0x04) ? " 24" : "",
+				       (x[3] & 0x02) ? " 20" : "",
+				       (x[3] & 0x01) ? " 16" : "");
+		} else {
+			unsigned sad = ((x[2] << 16) | (x[1] << 8) | x[0]);
+			unsigned i;
+
+			switch (x[3] >> 4) {
+			case 1:
+				printf("    Speaker Allocation for 10.2 channels:\n");
+				break;
+			case 2:
+				printf("    Speaker Allocation for 22.2 channels:\n");
+				break;
+			case 3:
+				printf("    Speaker Allocation for 30.2 channels:\n");
+				break;
+			default:
+				printf("    Unknown Speaker Allocation (0x%02x)\n", x[3] >> 4);
+				return;
+			}
+
+			for (i = 0; i < ARRAY_SIZE(speaker_map); i++) {
+				if ((sad >> i) & 1)
+					printf("      %s\n", speaker_map[i]);
+			}
+		}
+		length -= 4;
+		x += 4;
+	}
+}
+
+void edid_state::cta_ext_block(const unsigned char *x, unsigned length,
+			       bool duplicate)
+{
+	const char *name;
+	unsigned oui;
+	bool reverse = false;
+	bool audio_block = false;
+
+	switch (x[0]) {
+	case 0x00: data_block = "Video Capability Data Block"; break;
+	case 0x01: data_block.clear(); break;
+	case 0x02: data_block = "VESA Video Display Device Data Block"; break;
+	case 0x03: data_block = "VESA Video Timing Block Extension"; break;
+	case 0x04: data_block = "Reserved for HDMI Video Data Block"; break;
+	case 0x05: data_block = "Colorimetry Data Block"; break;
+	case 0x06: data_block = "HDR Static Metadata Data Block"; break;
+	case 0x07: data_block = "HDR Dynamic Metadata Data Block"; break;
+
+	case 0x0d: data_block = "Video Format Preference Data Block"; break;
+	case 0x0e: data_block = "YCbCr 4:2:0 Video Data Block"; break;
+	case 0x0f: data_block = "YCbCr 4:2:0 Capability Map Data Block"; break;
+	case 0x10: data_block = "Reserved for CTA-861 Miscellaneous Audio Fields"; break;
+	case 0x11: data_block.clear(); audio_block = true; break;
+	case 0x12: data_block = "HDMI Audio Data Block"; audio_block = true; break;
+	case 0x13: data_block = "Room Configuration Data Block"; audio_block = true; break;
+	case 0x14: data_block = "Speaker Location Data Block"; audio_block = true; break;
+
+	case 0x20: data_block = "InfoFrame Data Block"; break;
+
+	case 0x34: data_block = "DisplayID Type VII Video Timing Data Block"; break;
+	case 0x35: data_block = "DisplayID Type VIII Video Timing Data Block"; break;
+	case 0x42: data_block = "DisplayID Type X Video Timing Data Block"; break;
+
+	case 0x78: data_block = "HDMI Forum EDID Extension Override Data Block"; break;
+	case 0x79: data_block = "HDMI Forum Sink Capability Data Block"; break;
+	default:
+		if (x[0] <= 12)
+			printf("  Unknown CTA-861 Video-Related");
+		else if (x[0] <= 31)
+			printf("  Unknown CTA-861 Audio-Related");
+		else if (x[0] >= 120 && x[0] <= 127)
+			printf("  Unknown CTA-861 HDMI-Related");
+		else
+			printf("  Unknown CTA-861");
+		printf(" Data Block (extended tag 0x%02x, length %u)\n", x[0], length);
+		hex_block("    ", x + 1, length);
+		data_block.clear();
+		warn("Unknown Extended CTA-861 Data Block 0x%02x.\n", x[0]);
+		return;
+	}
+
+	switch (x[0]) {
+	case 0x00:
+	case 0x02:
+	case 0x05:
+	case 0x06:
+	case 0x0d:
+	case 0x0f:
+	case 0x12:
+	case 0x13:
+	case 0x78:
+	case 0x79:
+		if (duplicate)
+			fail("Only one instance of this Data Block is allowed.\n");
+		break;
+	}
+
+
+	// See Table 52 of CTA-861-G for a description of Byte 3
+	if (audio_block && !(cta.byte3 & 0x40))
+		fail("audio information is present, but bit 6 of Byte 3 of the CTA-861 Extension header indicates no Basic Audio support.\n");
+
+	if (data_block.length())
+		printf("  %s:\n", data_block.c_str());
+
+	switch (x[0]) {
+	case 0x00: cta_vcdb(x + 1, length); return;
+	case 0x01:
+		if (length < 3) {
+			data_block = std::string("Vendor-Specific Video Data Block");
+			fail("Invalid length %u < 3.\n", length);
+			return;
+		}
+		oui = (x[3] << 16) + (x[2] << 8) + x[1];
+		name = oui_name(oui);
+		if (!name) {
+			name = oui_name(oui, true);
+			if (name)
+				reverse = true;
+		}
+		if (!name) {
+			printf("  Vendor-Specific Video Data Block, OUI %s:\n",
+			       ouitohex(oui).c_str());
+			hex_block("    ", x + 4, length - 3);
+			data_block.clear();
+			warn("Unknown Extended Vendor-Specific Video Data Block, OUI %s.\n",
+			     ouitohex(oui).c_str());
+			return;
+		}
+		data_block = std::string("Vendor-Specific Video Data Block (") + name + ")";
+		if (reverse)
+			fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order\n").c_str());
+		printf("  %s, OUI %s:\n", data_block.c_str(), ouitohex(oui).c_str());
+		if (oui == 0x90848b)
+			cta_hdr10plus(x + 4, length - 3);
+		else if (oui == 0x00d046)
+			cta_dolby_video(x + 4, length - 3);
+		else
+			hex_block("    ", x + 4, length - 3);
+		return;
+	case 0x02: cta_vesa_vdddb(x + 1, length); return;
+	case 0x05: cta_colorimetry_block(x + 1, length); return;
+	case 0x06: cta_hdr_static_metadata_block(x + 1, length); return;
+	case 0x07: cta_hdr_dyn_metadata_block(x + 1, length); return;
+	case 0x0d: cta_vfpdb(x + 1, length); return;
+	case 0x0e: cta_svd(x + 1, length, true); return;
+	case 0x0f: cta_y420cmdb(x + 1, length); return;
+	case 0x11:
+		if (length < 3) {
+			data_block = std::string("Vendor-Specific Audio Data Block");
+			fail("Invalid length %u < 3.\n", length);
+			return;
+		}
+		oui = (x[3] << 16) + (x[2] << 8) + x[1];
+		name = oui_name(oui);
+		if (!name) {
+			name = oui_name(oui, true);
+			if (name)
+				reverse = true;
+		}
+		if (!name) {
+			printf("  Vendor-Specific Audio Data Block, OUI %s:\n",
+			       ouitohex(oui).c_str());
+			hex_block("    ", x + 4, length - 3);
+			data_block.clear();
+			warn("Unknown Extended Vendor-Specific Audio Data Block, OUI %s.\n",
+			     ouitohex(oui).c_str());
+			return;
+		}
+		data_block = std::string("Vendor-Specific Audio Data Block (") + name + ")";
+		if (reverse)
+			fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order\n").c_str());
+		printf("  %s, OUI %s:\n", data_block.c_str(), ouitohex(oui).c_str());
+		if (oui == 0x00d046)
+			cta_dolby_audio(x + 4, length - 3);
+		else
+			hex_block("    ", x + 4, length - 3);
+		return;
+	case 0x12: cta_hdmi_audio_block(x + 1, length); return;
+	case 0x13: cta_rcdb(x + 1, length); return;
+	case 0x14: cta_sldb(x + 1, length); return;
+	case 0x20: cta_ifdb(x + 1, length); return;
+	case 0x34: cta_displayid_type_7(x + 1, length); return;
+	case 0x35: cta_displayid_type_8(x + 1, length); return;
+	case 0x42: cta_displayid_type_10(x + 1, length); return;
+	case 0x78:
+		cta_hf_eeodb(x + 1, length);
+		// This must be the first CTA-861 block
+		if (!cta.first_block)
+			fail("Block starts at a wrong offset.\n");
+		return;
+	case 0x79:
+		if (!cta.last_block_was_hdmi_vsdb)
+			fail("HDMI Forum SCDB did not immediately follow the HDMI VSDB.\n");
+		if (cta.have_hf_scdb || cta.have_hf_vsdb)
+			fail("Duplicate HDMI Forum VSDB/SCDB.\n");
+		if (length < 2) {
+			data_block = std::string("HDMI Forum SCDB");
+			fail("Invalid length %u < 2.\n", length);
+			return;
+		}
+		if (x[1] || x[2])
+			printf("  Non-zero SCDB reserved fields!\n");
+		cta_hf_scdb(x + 3, length - 2);
+		cta.have_hf_scdb = 1;
+		return;
+	}
+
+	hex_block("    ", x + 1, length);
+}
+
+void edid_state::cta_block(const unsigned char *x, bool duplicate)
+{
+	unsigned length = x[0] & 0x1f;
+	const char *name;
+	unsigned oui;
+	bool reverse = false;
+	bool audio_block = false;
+
+	switch ((x[0] & 0xe0) >> 5) {
+	case 0x01:
+		data_block = "Audio Data Block";
+		printf("  %s:\n", data_block.c_str());
+		cta_audio_block(x + 1, length);
+		audio_block = true;
+		break;
+	case 0x02:
+		data_block = "Video Data Block";
+		printf("  %s:\n", data_block.c_str());
+		cta_svd(x + 1, length, false);
+		break;
+	case 0x03:
+		oui = (x[3] << 16) + (x[2] << 8) + x[1];
+		name = oui_name(oui);
+		if (!name) {
+			name = oui_name(oui, true);
+			if (name)
+				reverse = true;
+		}
+		if (!name) {
+			printf("  Vendor-Specific Data Block, OUI %s:\n", ouitohex(oui).c_str());
+			hex_block("    ", x + 4, length - 3);
+			data_block.clear();
+			warn("Unknown Vendor-Specific Data Block, OUI %s.\n",
+			     ouitohex(oui).c_str());
+			return;
+		}
+		data_block = std::string("Vendor-Specific Data Block (") + name + ")";
+		if (reverse)
+			fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order\n").c_str());
+		printf("  %s, OUI %s:\n", data_block.c_str(), ouitohex(oui).c_str());
+		if (oui == 0x000c03) {
+			cta_hdmi_block(x + 1, length);
+			cta.last_block_was_hdmi_vsdb = 1;
+			cta.first_block = 0;
+			// The HDMI OUI is present, so this EDID represents an HDMI
+			// interface. And HDMI interfaces must use EDID version 1.3
+			// according to the HDMI Specification, so check for this.
+			if (base.edid_minor != 3)
+				fail("The HDMI Specification requires EDID 1.3 instead of 1.%u.\n",
+				     base.edid_minor);
+			return;
+		}
+		if (oui == 0xc45dd8) {
+			if (!cta.last_block_was_hdmi_vsdb)
+				fail("HDMI Forum VSDB did not immediately follow the HDMI VSDB.\n");
+			if (cta.have_hf_scdb || cta.have_hf_vsdb)
+				fail("Duplicate HDMI Forum VSDB/SCDB.\n");
+			cta_hf_scdb(x + 4, length - 3);
+			cta.have_hf_vsdb = 1;
+			break;
+		}
+		if (oui == 0x00001a) {
+			cta_amd(x + 4, length - 3);
+			break;
+		}
+		if (oui == 0xca125c && length == 0x15) {
+			cta_microsoft(x + 4, length - 3);
+			break;
+		}
+		hex_block("    ", x + 4, length - 3);
+		break;
+	case 0x04:
+		data_block = "Speaker Allocation Data Block";
+		printf("  %s:\n", data_block.c_str());
+		cta_sadb(x + 1, length);
+		audio_block = true;
+		if (duplicate)
+			fail("Only one instance of this Data Block is allowed.\n");
+		break;
+	case 0x05:
+		data_block = "VESA Display Transfer Characteristics Data Block";
+		printf("  %s:\n", data_block.c_str());
+		cta_vesa_dtcdb(x + 1, length);
+		if (duplicate)
+			fail("Only one instance of this Data Block is allowed.\n");
+		break;
+	case 0x07:
+		cta_ext_block(x + 1, length - 1, duplicate);
+		break;
+	default: {
+		unsigned tag = (*x & 0xe0) >> 5;
+		unsigned length = *x & 0x1f;
+
+		printf("  Unknown CTA-861 tag 0x%02x, length %u\n", tag, length);
+		hex_block("    ", x + 1, length);
+		data_block.clear();
+		warn("Unknown CTA-861 Data Block %u.\n", tag);
+		break;
+	}
+	}
+
+	// See Table 52 of CTA-861-G for a description of Byte 3
+	if (audio_block && !(cta.byte3 & 0x40))
+		fail("audio information is present, but bit 6 of Byte 3 of the CTA-861 Extension header indicates no Basic Audio support.\n");
+	cta.first_block = 0;
+	cta.last_block_was_hdmi_vsdb = 0;
+}
+
+void edid_state::preparse_cta_block(const unsigned char *x)
+{
+	unsigned version = x[1];
+	unsigned offset = x[2];
+
+	if (offset >= 4) {
+		const unsigned char *detailed;
+
+		for (detailed = x + offset; detailed + 17 < x + 127; detailed += 18) {
+			if (memchk(detailed, 18))
+				break;
+			if (detailed[0] || detailed[1])
+				cta.preparsed_total_dtds++;
+		}
+	}
+
+	if (version < 3)
+		return;
+
+	for (unsigned i = 4; i < offset; i += (x[i] & 0x1f) + 1) {
+		bool for_ycbcr420 = false;
+		unsigned oui;
+
+		switch ((x[i] & 0xe0) >> 5) {
+		case 0x03:
+			oui = (x[i + 3] << 16) + (x[i + 2] << 8) + x[i + 1];
+			if (oui == 0x000c03) {
+				cta.has_hdmi = true;
+				cta.preparsed_phys_addr = (x[i + 4] << 8) | x[i + 5];
+			}
+			break;
+		case 0x07:
+			if (x[i + 1] == 0x0d)
+				cta.has_vfpdb = true;
+			if (x[i + 1] == 0x13 && (x[i + 2] & 0x40)) {
+				cta.preparsed_speaker_count = 1 + (x[i + 2] & 0x1f);
+				cta.preparsed_sld = x[i + 2] & 0x20;
+			}
+			if (x[i + 1] == 0x14)
+				cta_preparse_sldb(x + i + 2, (x[i] & 0x1f) - 1);
+			if (x[i + 1] == 0x22)
+				cta.preparsed_total_vtdbs++;
+			if (x[i + 1] == 0x23)
+				cta.preparsed_has_t8vtdb = true;
+			if (x[i + 1] == 0x32)
+				cta.preparsed_total_vtdbs +=
+					((x[i] & 0x1f) - 2) / (6 + ((x[i + 2] & 0x70) >> 4));
+			if (x[i + 1] != 0x0e)
+				continue;
+			for_ycbcr420 = true;
+			/* fall-through */
+		case 0x02:
+			for (unsigned j = 1 + for_ycbcr420; j <= (x[i] & 0x1f); j++) {
+				unsigned char vic = x[i + j];
+
+				if ((vic & 0x7f) <= 64)
+					vic &= 0x7f;
+				cta.preparsed_svds[for_ycbcr420].push_back(vic);
+				cta.preparsed_has_vic[for_ycbcr420][vic] = true;
+			}
+			break;
+		}
+	}
+}
+
+void edid_state::parse_cta_block(const unsigned char *x)
+{
+	unsigned version = x[1];
+	unsigned offset = x[2];
+	const unsigned char *detailed;
+
+	// See Table 52 of CTA-861-G for a description of Byte 3
+
+	printf("  Revision: %u\n", version);
+	if (version == 0)
+		fail("Invalid CTA-861 Extension revision 0.\n");
+	if (version == 2)
+		fail("Deprecated CTA-861 Extension revision 2.\n");
+	if (cta.has_hdmi && version != 3)
+		fail("The HDMI Specification requires CTA Extension revision 3.\n");
+	if (version > 3)
+		warn("Unknown CTA-861 Extension revision %u.\n", version);
+
+	if (version >= 1) do {
+		if (version == 1 && x[3] != 0)
+			fail("Non-zero byte 3.\n");
+
+		if (offset < 4)
+			break;
+
+		if (version < 3 && ((offset - 4) / 8)) {
+			printf("  8-byte timing descriptors: %u\n", (offset - 4) / 8);
+			fail("8-byte descriptors were never used.\n");
+		}
+
+		if (version >= 2) {
+			if (x[3] & 0x80)
+				printf("  Underscans IT Video Formats by default\n");
+			else
+				warn("IT Video Formats are overscanned by default, but normally this should be underscanned.\n");
+			if (x[3] & 0x40)
+				printf("  Basic audio support\n");
+			if (x[3] & 0x20)
+				printf("  Supports YCbCr 4:4:4\n");
+			if (x[3] & 0x10)
+				printf("  Supports YCbCr 4:2:2\n");
+			// Disable this test: this fails a lot of EDIDs, and there are
+			// also some corner cases where you only want to receive 4:4:4
+			// and refuse a fallback to 4:2:2.
+//			if ((x[3] & 0x30) && (x[3] & 0x30) != 0x30)
+//				msg(!cta.has_hdmi, "If YCbCr support is indicated, then both 4:2:2 and 4:4:4 %s be supported.\n",
+//				    cta.has_hdmi ? "shall" : "should");
+			printf("  Native detailed modes: %u\n", x[3] & 0x0f);
+			if (cta.first_block)
+				cta.byte3 = x[3];
+			else if (x[3] != cta.byte3)
+				fail("Byte 3 must be the same for all CTA-861 Extension Blocks.\n");
+			if (cta.first_block) {
+				unsigned native_dtds = x[3] & 0x0f;
+
+				cta.native_timings.clear();
+				if (!native_dtds && !cta.has_vfpdb) {
+					cta.first_svd_might_be_preferred = true;
+				} else if (native_dtds > cta.preparsed_total_dtds) {
+					fail("There are more Native DTDs (%u) than DTDs (%u).\n",
+					     native_dtds, cta.preparsed_total_dtds);
+				}
+				if (native_dtds > cta.preparsed_total_dtds)
+					native_dtds = cta.preparsed_total_dtds;
+				for (unsigned i = 0; i < native_dtds; i++) {
+					char type[16];
+
+					sprintf(type, "DTD %3u", i + 1);
+					cta.native_timings.push_back(timings_ext(i + 129, type));
+				}
+				if (cta.has_hdmi && block_nr != (block_map.saw_block_1 ? 2 : 1))
+					fail("The HDMI Specification requires that the first Extension Block (that is not a Block Map) is an CTA-861 Extension Block.\n");
+			}
+		}
+		if (version >= 3) {
+			unsigned i;
+
+			for (i = 4; i < offset; i += (x[i] & 0x1f) + 1) {
+				unsigned tag = (x[i] & 0xe0) << 3;
+
+				if (tag == 0x700)
+					tag |= x[i + 1];
+				bool duplicate = cta.found_tags.find(tag) != cta.found_tags.end();
+
+				cta_block(x + i, duplicate);
+				if (!duplicate)
+					cta.found_tags.insert(tag);
+			}
+
+			data_block.clear();
+			if (i != offset)
+				fail("Offset is %u, but should be %u.\n", offset, i);
+		}
+
+		data_block = "Detailed Timing Descriptors";
+		base.seen_non_detailed_descriptor = false;
+		bool first = true;
+		for (detailed = x + offset; detailed + 17 < x + 127; detailed += 18) {
+			if (memchk(detailed, 18))
+				break;
+			if (first) {
+				first = false;
+				printf("  %s:\n", data_block.c_str());
+			}
+			detailed_block(detailed);
+		}
+		if (!memchk(detailed, x + 127 - detailed)) {
+			data_block = "Padding";
+			fail("CTA-861 padding contains non-zero bytes.\n");
+		}
+	} while (0);
+
+	data_block.clear();
+	if (base.has_serial_number && base.has_serial_string)
+		warn("Display Product Serial Number is set, so the Serial Number in the Base EDID should be 0.\n");
+	if (!cta.has_vic_1 && !base.has_640x480p60_est_timing)
+		fail("Required 640x480p60 timings are missing in the established timings"
+		     " and the SVD list (VIC 1).\n");
+	if ((cta.supported_hdmi_vic_vsb_codes & cta.supported_hdmi_vic_codes) !=
+	    cta.supported_hdmi_vic_codes)
+		fail("HDMI VIC Codes must have their CTA-861 VIC equivalents in the VSB.\n");
+	if (!cta.has_vcdb)
+		fail("Missing VCDB, needed for Set Selectable RGB Quantization to avoid interop issues.\n");
+}
+
+void edid_state::cta_resolve_svr(vec_timings_ext::iterator iter)
+{
+	if (iter->svr() == 254) {
+		iter->flags = cta.t8vtdb.flags;
+		iter->t = cta.t8vtdb.t;
+	} else if (iter->svr() <= 144) {
+		iter->flags = cta.vec_dtds[iter->svr() - 129].flags;
+		iter->t = cta.vec_dtds[iter->svr() - 129].t;
+	} else {
+		iter->flags = cta.vec_vtdbs[iter->svr() - 145].flags;
+		iter->t = cta.vec_vtdbs[iter->svr() - 145].t;
+	}
+}
+
+void edid_state::cta_resolve_svrs()
+{
+	for (vec_timings_ext::iterator iter = cta.preferred_timings.begin();
+	     iter != cta.preferred_timings.end(); ++iter) {
+		if (iter->has_svr())
+			cta_resolve_svr(iter);
+	}
+
+	for (vec_timings_ext::iterator iter = cta.native_timings.begin();
+	     iter != cta.native_timings.end(); ++iter) {
+		if (iter->has_svr())
+			cta_resolve_svr(iter);
+	}
+}
+
+void edid_state::check_cta_blocks()
+{
+	unsigned max_pref_prog_hact = 0;
+	unsigned max_pref_prog_vact = 0;
+	unsigned max_pref_ilace_hact = 0;
+	unsigned max_pref_ilace_vact = 0;
+
+	data_block = "CTA-861";
+	for (vec_timings_ext::iterator iter = cta.preferred_timings.begin();
+	     iter != cta.preferred_timings.end(); ++iter) {
+		if (iter->t.interlaced &&
+		    (iter->t.vact > max_pref_ilace_vact ||
+		     (iter->t.vact == max_pref_ilace_vact && iter->t.hact >= max_pref_ilace_hact))) {
+			max_pref_ilace_hact = iter->t.hact;
+			max_pref_ilace_vact = iter->t.vact;
+		}
+		if (!iter->t.interlaced &&
+		    (iter->t.vact > max_pref_prog_vact ||
+		     (iter->t.vact == max_pref_prog_vact && iter->t.hact >= max_pref_prog_hact))) {
+			max_pref_prog_hact = iter->t.hact;
+			max_pref_prog_vact = iter->t.vact;
+		}
+	}
+
+	unsigned native_prog = 0;
+	unsigned native_prog_hact = 0;
+	unsigned native_prog_vact = 0;
+	bool native_prog_mixed_resolutions = false;
+	unsigned native_ilace = 0;
+	unsigned native_ilace_hact = 0;
+	unsigned native_ilace_vact = 0;
+	bool native_ilace_mixed_resolutions = false;
+
+	for (vec_timings_ext::iterator iter = cta.native_timings.begin();
+	     iter != cta.native_timings.end(); ++iter) {
+		if (iter->t.interlaced) {
+			native_ilace++;
+			if (!native_ilace_hact) {
+				native_ilace_hact = iter->t.hact;
+				native_ilace_vact = iter->t.vact;
+			} else if (native_ilace_hact != iter->t.hact ||
+				   native_ilace_vact != iter->t.vact) {
+				native_ilace_mixed_resolutions = true;
+			}
+		} else {
+			native_prog++;
+			if (!native_prog_hact) {
+				native_prog_hact = iter->t.hact;
+				native_prog_vact = iter->t.vact;
+			} else if (native_prog_hact != iter->t.hact ||
+				   native_prog_vact != iter->t.vact) {
+				native_prog_mixed_resolutions = true;
+			}
+		}
+	}
+
+	if (native_prog_mixed_resolutions)
+		fail("Native progressive timings are a mix of several resolutions.\n");
+	if (native_ilace_mixed_resolutions)
+		fail("Native interlaced timings are a mix of several resolutions.\n");
+	if (native_ilace && !native_prog)
+		fail("A native interlaced timing is present, but not a native progressive timing.\n");
+	if (!native_prog_mixed_resolutions && native_prog > 1)
+		warn("Multiple native progressive timings are defined.\n");
+	if (!native_ilace_mixed_resolutions && native_ilace > 1)
+		warn("Multiple native interlaced timings are defined.\n");
+
+	if (!native_prog_mixed_resolutions && native_prog_vact &&
+	    (max_pref_prog_vact > native_prog_vact ||
+	     (max_pref_prog_vact == native_prog_vact && max_pref_prog_hact > native_prog_hact)))
+		warn("Native progressive resolution of %ux%u is smaller than the max preferred progressive resolution %ux%u.\n",
+		     native_prog_hact, native_prog_vact,
+		     max_pref_prog_hact, max_pref_prog_vact);
+	if (!native_ilace_mixed_resolutions && native_ilace_vact &&
+	    (max_pref_ilace_vact > native_ilace_vact ||
+	     (max_pref_ilace_vact == native_ilace_vact && max_pref_ilace_hact > native_ilace_hact)))
+		warn("Native interlaced resolution of %ux%u is smaller than the max preferred interlaced resolution %ux%u.\n",
+		     native_ilace_hact, native_ilace_vact,
+		     max_pref_ilace_hact, max_pref_ilace_vact);
+
+	if (dispid.native_width && native_prog_hact &&
+	    !native_prog_mixed_resolutions) {
+		if (dispid.native_width != native_prog_hact ||
+		    dispid.native_height != native_prog_vact)
+			fail("Mismatch between CTA-861 and DisplayID native progressive resolution.\n");
+	}
+}
diff --git a/parse-di-ext-block.cpp b/parse-di-ext-block.cpp
new file mode 100644
index 0000000..9751363
--- /dev/null
+++ b/parse-di-ext-block.cpp
@@ -0,0 +1,499 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2020 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ *
+ * Author: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+ */
+
+#include "edid-decode.h"
+
+void edid_state::parse_digital_interface(const unsigned char *x)
+{
+	data_block = "Digital Interface";
+	printf("  %s:\n", data_block.c_str());
+
+	printf("    Supported Digital Interface: ");
+	unsigned short v = x[2];
+	switch (v) {
+	case 0x00:
+		printf("Analog Video Input\n");
+		if (!memchk(x + 2, 12))
+			fail("Bytes 0x02-0x0d should be 0.\n");
+		return;
+	case 0x01: printf("DVI\n"); break;
+	case 0x02: printf("DVI Single Link\n"); break;
+	case 0x03: printf("DVI Dual Link - High Resolution\n"); break;
+	case 0x04: printf("DVI Dual Link - High Color\n"); break;
+	case 0x05: printf("DVI - Consumer Electronics\n"); break;
+	case 0x06: printf("Plug & Display\n"); break;
+	case 0x07: printf("DFP\n"); break;
+	case 0x08: printf("Open LDI - Single Link\n"); break;
+	case 0x09: printf("Open LDI - Dual Link\n"); break;
+	case 0x0a: printf("Open LDI - Consumer Electronics\n"); break;
+	default:
+		   printf("Unknown (0x%02x)\n", v);
+		   fail("Unknown Digital Interface 0x%02x.\n", v);
+		   break;
+	}
+
+	switch ((x[3]) >> 6) {
+	case 0x00:
+		if (!memchk(x + 3, 4))
+			fail("Bytes 0x03-0x06 should be 0.\n");
+		break;
+	case 0x01:
+		printf("    Version: %u.%u\n    Release: %u.%u\n", x[3] & 0x3f, x[4], x[5], x[6]);
+		if (x[4] > 99)
+			fail("Version number > 99.\n");
+		if (x[6] > 99)
+			fail("Release number > 99.\n");
+		break;
+	case 0x02:
+		if (x[3] & 0x3f)
+			fail("Bits 5-0 of byte 0x03 should be 0.\n");
+		if (x[5] || x[6])
+			fail("Bytes 0x05-0x06 should be 0.\n");
+		printf("    Letter Designation: %c\n", x[4]);
+		break;
+	case 0x03:
+		if (x[3] & 0x3f)
+			fail("Bits 5-0 of byte 0x03 should be 0.\n");
+		printf("    Date Code: Year %u Week %u Day %u\n", 1990 + x[4], x[5], x[6]);
+		if (!x[5] || x[5] > 12)
+			fail("Bad month number.\n");
+		if (!x[6] || x[6] > 31)
+			fail("Bad day number.\n");
+		break;
+	}
+
+	v = x[7];
+	printf("    Data Enable Signal Usage %sAvailable\n",
+	       (v & 0x80) ? "" : "Not ");
+	if (v & 0x80)
+		printf("    Data Enable Signal %s\n",
+		       (v & 0x40) ? "High" : "Low");
+	else if (v & 0x40)
+		fail("Bit 6 of byte 0x07 should be 0.\n");
+	printf("    Edge of Shift Clock: ");
+	switch ((v >> 4) & 0x03) {
+	case 0: printf("Not specified\n"); break;
+	case 1: printf("Use rising edge of shift clock\n"); break;
+	case 2: printf("Use falling edge of shift clock\n"); break;
+	case 3: printf("Use both edges of shift clock\n"); break;
+	}
+	printf("    HDCP is %ssupported\n", (v & 0x08) ? "" : "not ");
+	printf("    Digital Receivers %ssupport Double Clocking of Input Data\n",
+	       (v & 0x04) ? "" : "do not ");
+	printf("    Packetized Digital Video is %ssupported\n", (v & 0x02) ? "" : "not ");
+	if (v & 0x01)
+		fail("Bit 0 of byte 0x07 should be 0.\n");
+
+	v = x[8];
+	printf("    Data Formats: ");
+	switch (v) {
+	case 0x15: printf("8-Bit Over 8-Bit RGB\n"); break;
+	case 0x19: printf("12-Bit Over 12-Bit RGB\n"); break;
+	case 0x24: printf("24-Bit MSB-Aligned RGB (Single Link)\n"); break;
+	case 0x48: printf("48-Bit MSB-Aligned RGB (Dual Link - High Resolution)\n"); break;
+	case 0x49: printf("48-Bit MSB-Aligned RGB (Dual Link - High Color)\n"); break;
+	default:
+		   printf("Unknown (0x%02x)\n", v);
+		   fail("Unknown Data Format 0x%02x.\n", v);
+		   break;
+	}
+	if (x[2] == 0x03 && v != 0x48)
+		fail("Data Format should be 0x48, not 0x%02x.\n", v);
+	if (x[2] == 0x04 && v != 0x49)
+		fail("Data Format should be 0x49, not 0x%02x.\n", v);
+
+	v = x[9];
+	if (v) {
+		printf("    Minimum Pixel Clock Frequency Per Link: %u MHz\n", v);
+		if (v == 0xff)
+			fail("Invalid Min-PCF 0x%02x.\n", v);
+	}
+
+	v = x[10] | (x[11] << 8);
+	if (v) {
+		printf("    Maximum Pixel Clock Frequency Per Link: %u MHz\n", v);
+		if (v == 0xffff)
+			fail("Invalid Max-PCF 0x%04x.\n", v);
+	}
+
+	v = x[12] | (x[13] << 8);
+	if (v == 0xffff)
+		printf("    Crossover Frequency: None - Single Link\n");
+	else if (v)
+		printf("    Crossover Frequency: %u MHz\n", v);
+}
+
+void edid_state::parse_display_device(const unsigned char *x)
+{
+	data_block = "Display Device";
+	printf("  %s:\n", data_block.c_str());
+
+	printf("    Sub-Pixel Layout: ");
+	unsigned char v = x[0x0e];
+	switch (v) {
+	case 0x00: printf("Not defined\n"); break;
+	case 0x01: printf("RGB\n"); break;
+	case 0x02: printf("BGR\n"); break;
+	case 0x03: printf("Quad Pixel - G at bottom left & top right\n"); break;
+	case 0x04: printf("Quad Pixel - G at bottom right & top left\n"); break;
+	default:
+		   printf("Unknown (0x%02x)\n", v);
+		   fail("Unknown Sub-Pixel Layout 0x%02x.\n", v);
+		   break;
+	}
+	printf("    Sub-Pixel Configuration: ");
+	v = x[0x0f];
+	switch (v) {
+	case 0x00: printf("Not defined\n"); break;
+	case 0x01: printf("Delta (Tri-ad)\n"); break;
+	case 0x02: printf("Stripe\n"); break;
+	case 0x03: printf("Stripe Offset\n"); break;
+	case 0x04: printf("Quad Pixel\n"); break;
+	default:
+		   printf("Unknown (0x%02x)\n", v);
+		   fail("Unknown Sub-Pixel Configuration 0x%02x.\n", v);
+		   break;
+	}
+	printf("    Sub-Pixel Shape: ");
+	v = x[0x10];
+	switch (v) {
+	case 0x00: printf("Not defined\n"); break;
+	case 0x01: printf("Round\n"); break;
+	case 0x02: printf("Square\n"); break;
+	case 0x03: printf("Rectangular\n"); break;
+	case 0x04: printf("Oval\n"); break;
+	case 0x05: printf("Elliptical\n"); break;
+	default:
+		   printf("Unknown (0x%02x)\n", v);
+		   fail("Unknown Sub-Pixel Shape 0x%02x.\n", v);
+		   break;
+	}
+	if (x[0x11])
+		printf("    Horizontal Dot/Pixel Pitch: %.2f mm\n",
+		       x[0x11] / 100.0);
+	if (x[0x12])
+		printf("    Vertical Dot/Pixel Pitch: %.2f mm\n",
+		       x[0x12] / 100.0);
+	v = x[0x13];
+	printf("    Display Device %s a Fixed Pixel Format\n",
+	       (v & 0x80) ? "has" : "does not have");
+	printf("    View Direction: ");
+	switch ((v & 0x60) >> 5) {
+	case 0x00: printf("Not specified\n"); break;
+	case 0x01: printf("Direct\n"); break;
+	case 0x02: printf("Reflected\n"); break;
+	case 0x03: printf("Direct & Reflected\n"); break;
+	}
+	printf("    Display Device uses %stransparent background\n",
+	       (v & 0x10) ? "" : "non-");
+	printf("    Physical Implementation: ");
+	switch ((v & 0x0c) >> 2) {
+	case 0x00: printf("Not specified\n"); break;
+	case 0x01: printf("Large Image device for group viewing\n"); break;
+	case 0x02: printf("Desktop or personal display\n"); break;
+	case 0x03: printf("Eyepiece type personal display\n"); break;
+	}
+	printf("    Monitor/display does %ssupport DDC/CI\n",
+	       (v & 0x02) ? "" : "not ");
+	if (v & 0x01)
+		fail("Bit 0 of byte 0x13 should be 0.\n");
+}
+
+void edid_state::parse_display_caps(const unsigned char *x)
+{
+	data_block = "Display Capabities & Feature Support Set";
+	printf("  %s:\n", data_block.c_str());
+
+	unsigned short v = x[0x14];
+
+	printf("    Legacy Modes: %s VGA/DOS Legacy Timing Modes are supported\n",
+	       (v & 0x80) ? "All" : "Not all");
+	printf("    Stereo Video: ");
+	switch ((v & 0x70) >> 4) {
+	case 0x00: printf("No direct stereo\n"); break;
+	case 0x01: printf("Field seq. stereo via stereo sync signal\n"); break;
+	case 0x02: printf("auto-stereoscopic, column interleave\n"); break;
+	case 0x03: printf("auto-stereoscopic, line interleave\n"); break;
+	default:
+		   printf("Unknown (0x%02x)\n", (v & 0x70) >> 4);
+		   fail("Unknown Stereo Video 0x%02x.\n", (v & 0x70) >> 4);
+		   break;
+	}
+	printf("    Scaler On Board: %s\n", (v & 0x08) ? "Yes" : "No");
+	printf("    Image Centering: %s\n", (v & 0x04) ? "Yes" : "No");
+	printf("    Conditional Update: %s\n", (v & 0x02) ? "Yes" : "No");
+	printf("    Interlaced Video: %s\n", (v & 0x01) ? "Yes" : "No");
+
+	v = x[0x15];
+	printf("    Frame Lock: %s\n", (v & 0x80) ? "Yes" : "No");
+	printf("    Frame Rate Conversion: ");
+	switch ((v & 0x60) >> 5) {
+	case 0x00: printf("Not supported\n"); break;
+	case 0x01: printf("Vertical is converted to a single frequency\n"); break;
+	case 0x02: printf("Horizontal is convertred to a single frequency\n"); break;
+	case 0x03: printf("Both Vertical & Horizontal are converted to single frequencies\n"); break;
+	}
+	if (v & 0x1f)
+		fail("Bits 4-0 of byte 0x15 should be 0.\n");
+	v = x[0x16] | (x[0x17] << 8);
+	printf("    Vertical Frequency: ");
+	if (!v) {
+		printf("Not available\n");
+	} else if (v == 0xffff) {
+		printf("Reserved\n");
+		fail("Vertical Frequency uses 0xffff (reserved value).\n");
+	} else {
+		printf("%.2f kHz\n", v / 100.0);
+	}
+	v = x[0x18] | (x[0x19] << 8);
+	printf("    Horizontal Frequency: ");
+	if (!v) {
+		printf("Not available\n");
+	} else if (v == 0xffff) {
+		printf("Reserved\n");
+		fail("Horizontal Frequency uses 0xffff (reserved value).\n");
+	} else {
+		printf("%.2f kHz\n", v / 100.0);
+	}
+
+	v = x[0x1a];
+	printf("    Display/Scan Orientation Definition Type: ");
+	switch ((v & 0xc0) >> 6) {
+	case 0x00: printf("Not defined\n"); break;
+	case 0x01: printf("Fixed Orientation\n"); break;
+	case 0x02: printf("Pivots: Default Orientation\n"); break;
+	case 0x03: printf("Pivots: Current Orientation (requires multiple EDID Extension Tables)\n"); break;
+	}
+	printf("    Screen Orientation: %s\n",
+	       (v & 0x20) ? "Portrait" : "Landscape");
+	printf("    Zero Pixel Location: ");
+	switch ((v & 0x18) >> 3) {
+	case 0x00: printf("Upper Left\n"); break;
+	case 0x01: printf("Upper Right\n"); break;
+	case 0x02: printf("Lower Left\n"); break;
+	case 0x03: printf("Lower Right\n"); break;
+	}
+	printf("    Scan Direction: ");
+	switch ((v & 0x06) >> 1) {
+	case 0x00: printf("Not defined\n"); break;
+	case 0x01: printf("Fast Scan is on the Major (Long) Axis and Slow Scan is on the Minor Axis\n"); break;
+	case 0x02: printf("Fast Scan is on the Minor (Short) Axis and Slow Scan is on the Major Axis\n"); break;
+	case 0x03:
+		   printf("Reserved\n");
+		   fail("Scan Direction used the reserved value 0x03.\n");
+		   break;
+	}
+	printf("    Standalone Projector: %s\n",
+	       (v & 0x01) ? "Yes" : "No");
+
+	v = x[0x1b];
+	printf("    Default Color/Luminance Decoding: ");
+	switch (v) {
+	case 0x00: printf("Not defined\n"); break;
+	case 0x01: printf("BGR\n"); break;
+	case 0x02: printf("Y/C (S-Video) NTSC\n"); break;
+	case 0x03: printf("Y/C (S-Video) PAL\n"); break;
+	case 0x04: printf("Y/C (S-Video) SECAM\n"); break;
+	case 0x05: printf("YCrCb 4:4:4 per SMPTE 293M & 294M\n"); break;
+	case 0x06: printf("YCrCb 4:2:2 per SMPTE 293M & 294M\n"); break;
+	case 0x07: printf("YCrCb 4:2:0 per SMPTE 293M & 294M\n"); break;
+	case 0x08: printf("YCrCb per SMPTE 260M (Legacy HDTV)\n"); break;
+	case 0x09: printf("YPbPr per SMPTE 240M (Legacy HDTV)\n"); break;
+	case 0x0a: printf("YCrCb per SMPTE 274M (Modern HDTV)\n"); break;
+	case 0x0b: printf("YPbPr per SMPTE 274M (Modern HDTV)\n"); break;
+	case 0x0c: printf("Y B-Y R-Y BetaCam (Sony)\n"); break;
+	case 0x0d: printf("Y B-Y R-Y M-2 (Matsushita)\n"); break;
+	case 0x0e: printf("Monochrome\n"); break;
+	default:
+		   printf("Unknown (0x%02x)\n", v);
+		   fail("Unknown Default Color/Luminance Decoding 0x%02x.\n", v);
+		   break;
+	}
+	v = x[0x1c];
+	printf("    Preferred Color/Luminance Decoder: ");
+	switch (v) {
+	case 0x00: printf("Uses Default Decoding\n"); break;
+	case 0x01: printf("BGR\n"); break;
+	case 0x02: printf("Y/C (S-Video)\n"); break;
+	case 0x03: printf("Yxx (SMPTE 2xxM)\n"); break;
+	case 0x04: printf("Monochrome\n"); break;
+	default:
+		   printf("Unknown (0x%02x)\n", v);
+		   fail("Unknown Preferred Color/Luminance Decoding 0x%02x.\n", v);
+		   break;
+	}
+	v = x[0x1d];
+	if (v && (x[0x1e] & 0xfc)) {
+		printf("    Color/Luminance Decoding Capabilities:\n");
+		printf("      BGR: %s\n", (v & 0x80) ? "Yes" : "No");
+		printf("      Y/C (S-Video) NTSC: %s\n", (v & 0x40) ? "Yes" : "No");
+		printf("      Y/C (S-Video) PAL: %s\n", (v & 0x20) ? "Yes" : "No");
+		printf("      Y/C (S-Video) SECAM: %s\n", (v & 0x10) ? "Yes" : "No");
+		printf("      YCrCb 4:4:4 per SMPTE 293M & 294M: %s\n", (v & 0x08) ? "Yes" : "No");
+		printf("      YCrCb 4:2:2 per SMPTE 293M & 294M: %s\n", (v & 0x04) ? "Yes" : "No");
+		printf("      YCrCb 4:2:0 per SMPTE 293M & 294M: %s\n", (v & 0x02) ? "Yes" : "No");
+		printf("      YCrCb per SMPTE 260M (Legacy HDTV): %s\n", (v & 0x01) ? "Yes" : "No");
+		v = x[0x1e];
+		printf("      YPbPr per SMPTE 240M (Legacy HDTV): %s\n", (v & 0x80) ? "Yes" : "No");
+		printf("      YCrCb per SMPTE 274M (Modern HDTV): %s\n", (v & 0x40) ? "Yes" : "No");
+		printf("      YPbPr per SMPTE 274M (Modern HDTV): %s\n", (v & 0x20) ? "Yes" : "No");
+		printf("      Y B-Y R-Y BetaCam (Sony): %s\n", (v & 0x10) ? "Yes" : "No");
+		printf("      Y B-Y R-Y M-2 (Matsushita): %s\n", (v & 0x08) ? "Yes" : "No");
+		printf("      Monochrome: %s\n", (v & 0x04) ? "Yes" : "No");
+	} else {
+		printf("    Color/Luminance Decoding Capabilities: None\n");
+	}
+	if (v & 0x03)
+		fail("Bits 1-0 of byte 0x1e should be 0.\n");
+
+	v = x[0x1f];
+	printf("    Dithering: %s\n", (v & 0x80) ? "Yes" : "No");
+	if (v & 0x7f)
+		fail("Bits 6-0 of byte 0x1f should be 0.\n");
+	v = x[0x20];
+	printf("    Supported Color Bit-Depth of Sub-Channel 0 (Blue): ");
+	if (!v) {
+		printf("No Information\n");
+	} else if (v <= 16) {
+		printf("%u\n", v);
+	} else {
+		printf("Reserved (0x%02x)\n", v);
+		fail("Supported Color Bit-Depth of Sub-Channel Blue value is 0x%02x.\n", v);
+	}
+	v = x[0x21];
+	printf("    Supported Color Bit-Depth of Sub-Channel 1 (Green): ");
+	if (!v) {
+		printf("No Information\n");
+	} else if (v <= 16) {
+		printf("%u\n", v);
+	} else {
+		printf("Reserved (0x%02x)\n", v);
+		fail("Supported Color Bit-Depth of Sub-Channel Green value is 0x%02x.\n", v);
+	}
+	v = x[0x22];
+	printf("    Supported Color Bit-Depth of Sub-Channel 2 (Red): ");
+	if (!v) {
+		printf("No Information\n");
+	} else if (v <= 16) {
+		printf("%u\n", v);
+	} else {
+		printf("Reserved (0x%02x)\n", v);
+		fail("Supported Color Bit-Depth of Sub-Channel Red value is 0x%02x.\n", v);
+	}
+	v = x[0x23];
+	printf("    Supported Color Bit-Depth of Sub-Channel 0 (Cb/Pb): ");
+	if (!v) {
+		printf("No Information\n");
+	} else if (v <= 16) {
+		printf("%u\n", v);
+	} else {
+		printf("Reserved (0x%02x)\n", v);
+		fail("Supported Color Bit-Depth of Sub-Channel Cb/Pb value is 0x%02x.\n", v);
+	}
+	v = x[0x24];
+	printf("    Supported Color Bit-Depth of Sub-Channel 1 (Y): ");
+	if (!v) {
+		printf("No Information\n");
+	} else if (v <= 16) {
+		printf("%u\n", v);
+	} else {
+		printf("Reserved (0x%02x)\n", v);
+		fail("Supported Color Bit-Depth of Sub-Channel Y value is 0x%02x.\n", v);
+	}
+	v = x[0x25];
+	printf("    Supported Color Bit-Depth of Sub-Channel 2 (Cr/Pr): ");
+	if (!v) {
+		printf("No Information\n");
+	} else if (v <= 16) {
+		printf("%u\n", v);
+	} else {
+		printf("Reserved (0x%02x)\n", v);
+		fail("Supported Color Bit-Depth of Sub-Channel Cr/Pr value is 0x%02x.\n", v);
+	}
+
+	v = x[0x26];
+	printf("    Aspect Ratio Conversion Modes:");
+	if (!v) {
+		printf(" None\n");
+	} else {
+		printf("\n");
+		printf("      Full Mode: %s\n", (v & 0x80) ? "Yes" : "No");
+		printf("      Zoom Mode: %s\n", (v & 0x40) ? "Yes" : "No");
+		printf("      Squeeze (Side Bars/Letterbox) Mode: %s\n", (v & 0x20) ? "Yes" : "No");
+		printf("      Variable (Expand/Shrink) Mode: %s\n", (v & 0x10) ? "Yes" : "No");
+	}
+	if (v & 0x0f)
+		fail("Bits 3-0 of byte 0x26 should be 0.\n");
+}
+
+void edid_state::parse_display_xfer(const unsigned char *x)
+{
+	data_block = "Display Transfer Characteristics - Gamma";
+	printf("  %s:\n", data_block.c_str());
+
+	unsigned char v = x[0x51];
+	unsigned num_entries = v & 0x3f;
+
+	switch ((v & 0xc0) >> 6) {
+	case 0x00:
+		printf("    No Display Transfer Characteristics\n");
+		if (!memchk(x + 0x51, 46))
+			fail("Bytes 0x51-0x7e should be 0.\n");
+		return;
+	case 0x03:
+		fail("Bits 7-6 of byte 0x51 cannot be 0x03.\n");
+		return;
+	default:
+		break;
+	}
+
+	if (((v & 0xc0) >> 6) == 0x01) {
+		if (!num_entries || num_entries > 45)
+			fail("White Curve with %u entries.\n", num_entries);
+		if (num_entries > 45)
+			num_entries = 45;
+		if (!memchk(x + 0x52 + num_entries, 45 - num_entries))
+			fail("Bytes 0x%02x-0x7e should be 0.\n", 0x52 + num_entries);
+		printf("    White Curve (%u entries):\n", num_entries);
+		hex_block("      ", x + 0x52, num_entries, false, 15);
+	} else {
+		if (!num_entries || num_entries > 15)
+			fail("Sub-Channel Curve with %u entries.\n", num_entries);
+		if (num_entries > 15)
+			num_entries = 15;
+		printf("    Sub-Channel 0 (Blue) Curve with %u entries:\n", num_entries);
+		hex_block("      ", x + 0x52, num_entries, false);
+		if (!memchk(x + 0x52 + num_entries, 15 - num_entries))
+			fail("Bytes 0x%02x-0x7e should be 0.\n", 0x52 + num_entries);
+		printf("    Sub-Channel 1 (Green) Curve with %u entries:\n", num_entries);
+		hex_block("      ", x + 0x52 + 15, num_entries, false);
+		if (!memchk(x + 0x52 + 15 + num_entries, 15 - num_entries))
+			fail("Bytes 0x%02x-0x7e should be 0.\n", 0x52 + 15 + num_entries);
+		printf("    Sub-Channel 2 (Red) Curve with %u entries:\n", num_entries);
+		hex_block("      ", x + 0x52 + 30, num_entries, false);
+		if (!memchk(x + 0x52 + 30 + num_entries, 15 - num_entries))
+			fail("Bytes 0x%02x-0x7e should be 0.\n", 0x52 + 30 + num_entries);
+	}
+}
+
+void edid_state::parse_di_ext_block(const unsigned char *x)
+{
+	printf("  Version: %u\n", x[1]);
+	if (!x[1])
+		fail("Invalid version 0.\n");
+
+	parse_digital_interface(x);
+	parse_display_device(x);
+	parse_display_caps(x);
+	if (!memchk(x + 0x27, 16))
+		fail("Bytes 0x27-0x36 should be 0.\n");
+	if (!memchk(x + 0x37, 17))
+		fail("Bytes 0x37-0x47 should be 0.\n");
+	if (!memchk(x + 0x48, 9))
+		fail("Bytes 0x48-0x50 should be 0.\n");
+	parse_display_xfer(x);
+}
diff --git a/parse-displayid-block.cpp b/parse-displayid-block.cpp
new file mode 100644
index 0000000..5bd9734
--- /dev/null
+++ b/parse-displayid-block.cpp
@@ -0,0 +1,1879 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2006-2012 Red Hat, Inc.
+ * Copyright 2018-2020 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ *
+ * Author: Adam Jackson <ajax@nwnk.net>
+ * Maintainer: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+ */
+
+#include <math.h>
+
+#include "edid-decode.h"
+
+static const char *bpc444[] = {"6", "8", "10", "12", "14", "16", NULL, NULL};
+static const char *bpc4xx[] = {"8", "10", "12", "14", "16", NULL, NULL, NULL};
+static const char *audiorates[] = {"32", "44.1", "48", NULL, NULL, NULL, NULL, NULL};
+
+// misc functions
+
+static void print_flags(const char *label, unsigned char flag_byte,
+			const char **flags, bool reverse = false)
+{
+	if (!flag_byte)
+		return;
+
+	unsigned countflags = 0;
+
+	printf("%s: ", label);
+	for (unsigned i = 0; i < 8; i++) {
+		if (flag_byte & (1 << (reverse ? 7 - i : i))) {
+			if (countflags)
+				printf(", ");
+			if (flags[i])
+				printf("%s", flags[i]);
+			else
+				printf("Undefined (%u)", i);
+			countflags++;
+		}
+	}
+	printf("\n");
+}
+
+void edid_state::check_displayid_datablock_revision(unsigned char hdr,
+						    unsigned char valid_flags,
+						    unsigned char rev)
+{
+	unsigned char revision = hdr & 7;
+	unsigned char flags = hdr & ~7 & ~valid_flags;
+
+	if (revision != rev)
+		warn("Unexpected revision (%u != %u).\n", revision, rev);
+	if (flags)
+		warn("Unexpected flags (0x%02x).\n", flags);
+}
+
+static bool check_displayid_datablock_length(const unsigned char *x,
+					     unsigned expectedlenmin = 0,
+					     unsigned expectedlenmax = 128 - 2 - 5 - 3,
+					     unsigned payloaddumpstart = 0)
+{
+	unsigned char len = x[2];
+
+	if (expectedlenmin == expectedlenmax && len != expectedlenmax)
+		fail("DisplayID payload length is different than expected (%d != %d).\n", len, expectedlenmax);
+	else if (len > expectedlenmax)
+		fail("DisplayID payload length is greater than expected (%d > %d).\n", len, expectedlenmax);
+	else if (len < expectedlenmin)
+		fail("DisplayID payload length is less than expected (%d < %d).\n", len, expectedlenmin);
+	else
+		return true;
+
+	if (len > payloaddumpstart)
+		hex_block("    ", x + 3 + payloaddumpstart, len - payloaddumpstart);
+	return false;
+}
+
+// tag 0x00 and 0x20
+
+void edid_state::parse_displayid_product_id(const unsigned char *x)
+{
+	check_displayid_datablock_revision(x[1]);
+
+	dispid.has_product_identification = true;
+	if (dispid.version >= 0x20) {
+		unsigned oui = (x[3] << 16) | (x[4] << 8) | x[5];
+		printf("    Vendor OUI %s\n", ouitohex(oui).c_str());
+	} else {
+		printf("    Vendor ID: %c%c%c\n", x[3], x[4], x[5]);
+	}
+	printf("    Product Code: %u\n", x[6] | (x[7] << 8));
+	unsigned sn = x[8] | (x[9] << 8) | (x[10] << 16) | (x[11] << 24);
+	if (sn) {
+		if (hide_serial_numbers)
+			printf("    Serial Number: ...\n");
+		else
+			printf("    Serial Number: %u\n", sn);
+	}
+	unsigned week = x[12];
+	unsigned year = 2000 + x[13];
+	printf("    %s: %u",
+	       week == 0xff ? "Model Year" : "Year of Manufacture", year);
+	if (week && week <= 0x36)
+		printf(", Week %u", week);
+	printf("\n");
+	if (x[14]) {
+		char buf[256];
+
+		memcpy(buf, x + 15, x[14]);
+		buf[x[14]] = 0;
+		printf("    Product ID: %s\n", buf);
+	}
+}
+
+// tag 0x01
+
+static const char *feature_support_flags[] = {
+	"De-interlacing",
+	"Support ACP, ISRC1, or ISRC2packets",
+	"Fixed pixel format",
+	"Fixed timing",
+	"Power management (DPM)",
+	"Audio input override",
+	"Separate audio inputs provided",
+	"Audio support on video interface"
+};
+
+static void print_flag_lines(const char *indent, const char *label,
+			     unsigned char flag_byte, const char **flags)
+{
+	if (flag_byte) {
+		printf("%s\n", label);
+
+		for (int i = 0; i < 8; i++)
+			if (flag_byte & (1 << i))
+				printf("%s%s\n", indent, flags[i]);
+	}
+}
+
+void edid_state::parse_displayid_parameters(const unsigned char *x)
+{
+	check_displayid_datablock_revision(x[1]);
+
+	if (!check_displayid_datablock_length(x, 12, 12))
+		return;
+
+	dispid.has_display_parameters = true;
+	printf("    Image size: %.1f mm x %.1f mm\n",
+	       ((x[4] << 8) + x[3]) / 10.0,
+	       ((x[6] << 8) + x[5]) / 10.0);
+	printf("    Pixels: %d x %d\n",
+	       (x[8] << 8) + x[7], (x[10] << 8) + x[9]);
+	print_flag_lines("      ", "    Feature support flags:",
+			 x[11], feature_support_flags);
+
+	if (x[12] != 0xff)
+		printf("    Gamma: %.2f\n", ((x[12] + 100.0) / 100.0));
+	printf("    Aspect ratio: %.2f\n", ((x[13] + 100.0) / 100.0));
+	printf("    Dynamic bpc native: %d\n", (x[14] & 0xf) + 1);
+	printf("    Dynamic bpc overall: %d\n", ((x[14] >> 4) & 0xf) + 1);
+}
+
+// tag 0x02
+
+static const char *std_colorspace_ids[] = {
+	"sRGB",
+	"BT.601",
+	"BT.709",
+	"Adobe RGB",
+	"DCI-P3",
+	"NTSC",
+	"EBU",
+	"Adobe Wide Gamut RGB",
+	"DICOM"
+};
+
+static double fp2d(unsigned short fp)
+{
+	return fp / 4096.0;
+}
+
+void edid_state::parse_displayid_color_characteristics(const unsigned char *x)
+{
+	check_displayid_datablock_revision(x[1], 0xf8, 1);
+
+	unsigned cie_year = (x[1] & 0x80) ? 1976 : 1931;
+	unsigned xfer_id = (x[1] >> 3) & 0x0f;
+	unsigned num_whitepoints = x[3] & 0x0f;
+	unsigned num_primaries = (x[3] >> 4) & 0x07;
+	bool temporal_color = x[3] & 0x80;
+	unsigned offset = 4;
+
+	printf("    Uses %s color\n", temporal_color ? "temporal" : "spatial");
+	printf("    Uses %u CIE (x, y) coordinates\n", cie_year);
+	if (xfer_id) {
+		printf("    Associated with Transfer Characteristics Data Block with Identifier %u\n", xfer_id);
+		if (!(dispid.preparsed_xfer_ids & (1 << xfer_id)))
+			fail("Missing Transfer Characteristics Data Block with Identifier %u.\n", xfer_id);
+	}
+	if (!num_primaries) {
+		printf("    Uses color space %s\n",
+		       x[4] >= ARRAY_SIZE(std_colorspace_ids) ? "Reserved" :
+								std_colorspace_ids[x[4]]);
+		offset++;
+	}
+	for (unsigned i = 0; i < num_primaries; i++) {
+		unsigned idx = offset + 3 * i;
+
+		printf("    Primary #%u: (%.4f, %.4f)\n", i,
+		       fp2d(x[idx] | ((x[idx + 1] & 0x0f) << 8)),
+		       fp2d(((x[idx + 1] & 0xf0) >> 4) | (x[idx + 2] << 4)));
+	}
+	offset += 3 * num_primaries;
+	for (unsigned i = 0; i < num_whitepoints; i++) {
+		unsigned idx = offset + 3 * i;
+
+		printf("    White point #%u: (%.4f, %.4f)\n", i,
+		       fp2d(x[idx] | ((x[idx + 1] & 0x0f) << 8)),
+		       fp2d(((x[idx + 1] & 0xf0) >> 4) | (x[idx + 2] << 4)));
+	}
+}
+
+// tag 0x03 and 0x22
+
+void edid_state::parse_displayid_type_1_7_timing(const unsigned char *x,
+						 bool type7, unsigned block_rev, bool is_cta)
+{
+	struct timings t = {};
+	unsigned hbl, vbl;
+	std::string s("aspect ");
+
+	dispid.has_type_1_7 = true;
+	t.pixclk_khz = (type7 ? 1 : 10) * (1 + (x[0] + (x[1] << 8) + (x[2] << 16)));
+	switch (x[3] & 0xf) {
+	case 0:
+		s += "1:1";
+		t.hratio = t.vratio = 1;
+		break;
+	case 1:
+		s += "5:4";
+		t.hratio = 5;
+		t.vratio = 4;
+		break;
+	case 2:
+		s += "4:3";
+		t.hratio = 4;
+		t.vratio = 3;
+		break;
+	case 3:
+		s += "15:9";
+		t.hratio = 15;
+		t.vratio = 9;
+		break;
+	case 4:
+		s += "16:9";
+		t.hratio = 16;
+		t.vratio = 9;
+		break;
+	case 5:
+		s += "16:10";
+		t.hratio = 16;
+		t.vratio = 10;
+		break;
+	case 6:
+		s += "64:27";
+		t.hratio = 64;
+		t.vratio = 27;
+		break;
+	case 7:
+		s += "256:135";
+		t.hratio = 256;
+		t.vratio = 135;
+		break;
+	default:
+		s += "undefined";
+		if ((x[3] & 0xf) > (dispid.version <= 0x12 ? 7 : 8))
+			fail("Unknown aspect 0x%02x.\n", x[3] & 0xf);
+		break;
+	}
+	switch ((x[3] >> 5) & 0x3) {
+	case 0:
+		s += ", no 3D stereo";
+		break;
+	case 1:
+		s += ", 3D stereo";
+		break;
+	case 2:
+		s += ", 3D stereo depends on user action";
+		break;
+	case 3:
+		s += ", reserved";
+		fail("Reserved stereo 0x03.\n");
+		break;
+	}
+	if (block_rev >= 2 && (x[3] & 0x80))
+		s += ", YCbCr 4:2:0";
+
+	t.hact = 1 + (x[4] | (x[5] << 8));
+	hbl = 1 + (x[6] | (x[7] << 8));
+	t.hfp = 1 + (x[8] | ((x[9] & 0x7f) << 8));
+	t.hsync = 1 + (x[10] | (x[11] << 8));
+	t.hbp = hbl - t.hfp - t.hsync;
+	if ((x[9] >> 7) & 0x1)
+		t.pos_pol_hsync = true;
+	t.vact = 1 + (x[12] | (x[13] << 8));
+	vbl = 1 + (x[14] | (x[15] << 8));
+	t.vfp = 1 + (x[16] | ((x[17] & 0x7f) << 8));
+	t.vsync = 1 + (x[18] | (x[19] << 8));
+	t.vbp = vbl - t.vfp - t.vsync;
+	if ((x[17] >> 7) & 0x1)
+		t.pos_pol_vsync = true;
+
+	if (x[3] & 0x10) {
+		t.interlaced = true;
+		t.vfp /= 2;
+		t.vsync /= 2;
+		t.vbp /= 2;
+	}
+	if (block_rev < 2 && (x[3] & 0x80)) {
+		s += ", preferred";
+		dispid.preferred_timings.push_back(timings_ext(t, "DTD", s));
+	}
+
+	print_timings("    ", &t, "DTD", s.c_str(), true);
+	if (is_cta) {
+		timings_ext te(t, "DTD", s);
+		cta.vec_vtdbs.push_back(te);
+
+		// Only use a T7VTDB if is cannot be expressed by a
+		// DTD or a T10VTDB.
+		if (t.hact <= 4095 && t.vact <= 4095 &&
+		    t.pixclk_khz <= 655360 && !(x[3] & 0xe0)) {
+			fail("This T7VTDB can be represented as an 18-byte DTD.\n");
+			return;
+		}
+		unsigned htot = t.hact + t.hfp + t.hsync + t.hbp;
+		unsigned vtot = t.vact + t.vfp + t.vsync + t.vbp;
+		unsigned refresh = (t.pixclk_khz * 1000ULL) / (htot * vtot);
+
+		for (unsigned rb = RB_NONE; rb <= RB_CVT_V3; rb++) {
+			timings cvt_t = calc_cvt_mode(t.hact, t.vact, refresh, rb);
+			if (match_timings(t, cvt_t)) {
+				fail("This T7VTDB can be represented as a T10VTDB.\n");
+				return;
+			}
+		}
+		timings cvt_t = calc_cvt_mode(t.hact, t.vact, refresh, RB_CVT_V3,
+					      false, false, true);
+		if (match_timings(t, cvt_t))
+			fail("This T7VTDB can be represented as a T10VTDB.\n");
+	}
+}
+
+// tag 0x04
+
+void edid_state::parse_displayid_type_2_timing(const unsigned char *x)
+{
+	struct timings t = {};
+	unsigned hbl, vbl;
+	std::string s("aspect ");
+
+	t.pixclk_khz = 10 * (1 + (x[0] + (x[1] << 8) + (x[2] << 16)));
+	t.hact = 8 + 8 * (x[4] | ((x[5] & 0x01) << 8));
+	hbl = 8 + 8 * ((x[5] & 0xfe) >> 1);
+	t.hfp = 8 + 8 * ((x[6] & 0xf0) >> 4);
+	t.hsync = 8 + 8 * (x[6] & 0xf);
+	t.hbp = hbl - t.hfp - t.hsync;
+	if ((x[3] >> 3) & 0x1)
+		t.pos_pol_hsync = true;
+	t.vact = 1 + (x[7] | ((x[8] & 0xf) << 8));
+	vbl = 1 + x[9];
+	t.vfp = 1 + (x[10] >> 4);
+	t.vsync = 1 + (x[10] & 0xf);
+	t.vbp = vbl - t.vfp - t.vsync;
+	if ((x[17] >> 2) & 0x1)
+		t.pos_pol_vsync = true;
+
+	if (x[3] & 0x10) {
+		t.interlaced = true;
+		t.vfp /= 2;
+		t.vsync /= 2;
+		t.vbp /= 2;
+	}
+
+	calc_ratio(&t);
+
+	s += std::to_string(t.hratio) + ":" + std::to_string(t.vratio);
+
+	switch ((x[3] >> 5) & 0x3) {
+	case 0:
+		s += ", no 3D stereo";
+		break;
+	case 1:
+		s += ", 3D stereo";
+		break;
+	case 2:
+		s += ", 3D stereo depends on user action";
+		break;
+	case 3:
+		s += ", reserved";
+		fail("Reserved stereo 0x03.\n");
+		break;
+	}
+	if (x[3] & 0x80) {
+		s += ", preferred";
+		dispid.preferred_timings.push_back(timings_ext(t, "DTD", s));
+	}
+
+	print_timings("    ", &t, "DTD", s.c_str(), true);
+}
+
+// tag 0x05
+
+void edid_state::parse_displayid_type_3_timing(const unsigned char *x)
+{
+	struct timings t = {};
+	std::string s("aspect ");
+
+	switch (x[0] & 0xf) {
+	case 0:
+		s += "1:1";
+		t.hratio = t.vratio = 1;
+		break;
+	case 1:
+		s += "5:4";
+		t.hratio = 5;
+		t.vratio = 4;
+		break;
+	case 2:
+		s += "4:3";
+		t.hratio = 4;
+		t.vratio = 3;
+		break;
+	case 3:
+		s += "15:9";
+		t.hratio = 15;
+		t.vratio = 9;
+		break;
+	case 4:
+		s += "16:9";
+		t.hratio = 16;
+		t.vratio = 9;
+		break;
+	case 5:
+		s += "16:10";
+		t.hratio = 16;
+		t.vratio = 10;
+		break;
+	case 6:
+		s += "64:27";
+		t.hratio = 64;
+		t.vratio = 27;
+		break;
+	case 7:
+		s += "256:135";
+		t.hratio = 256;
+		t.vratio = 135;
+		break;
+	default:
+		s += "undefined";
+		if ((x[3] & 0xf) > (dispid.version <= 0x12 ? 7 : 8))
+			fail("Unknown aspect 0x%02x.\n", x[3] & 0xf);
+		break;
+	}
+
+	t.rb = ((x[0] & 0x70) >> 4) == 1 ? RB_CVT_V1 : RB_NONE;
+	t.hact = 8 + 8 * x[1];
+	t.vact = t.hact * t.vratio / t.hratio;
+
+	edid_cvt_mode(1 + (x[2] & 0x7f), t);
+
+	if (x[0] & 0x80) {
+		s += ", preferred";
+		dispid.preferred_timings.push_back(timings_ext(t, "CVT", s));
+	}
+
+	print_timings("    ", &t, "CVT", s.c_str());
+}
+
+// tag 0x06 and 0x23
+
+void edid_state::parse_displayid_type_4_8_timing(unsigned char type, unsigned short id, bool is_cta)
+{
+	const struct timings *t = NULL;
+	char type_name[16];
+
+	switch (type) {
+	case 0: t = find_dmt_id(id); sprintf(type_name, "DMT 0x%02x", id); break;
+	case 1: t = find_vic_id(id); sprintf(type_name, "VIC %3u", id); break;
+	case 2: t = find_hdmi_vic_id(id); sprintf(type_name, "HDMI VIC %u", id); break;
+	default: break;
+	}
+	if (t)
+		print_timings("    ", t, type_name);
+	if (t && is_cta && !cta.t8vtdb.is_valid()) {
+		timings_ext te(*t, type_name, "");
+		cta.t8vtdb = te;
+	}
+}
+
+// tag 0x09
+
+void edid_state::parse_displayid_video_timing_range_limits(const unsigned char *x)
+{
+	check_displayid_datablock_revision(x[1]);
+
+	if (!check_displayid_datablock_length(x, 15, 15))
+		return;
+	printf("    Pixel Clock: %.3f-%.3f MHz\n",
+	       (double)((x[3] | (x[4] << 8) | (x[5] << 16)) + 1) / 100.0,
+	       (double)((x[6] | (x[7] << 8) | (x[8] << 16)) + 1) / 100.0);
+	printf("    Horizontal Frequency: %u-%u kHz\n", x[9], x[10]);
+	printf("    Minimum Horizontal Blanking: %u pixels\n", x[11] | (x[12] << 8));
+	printf("    Vertical Refresh: %u-%u Hz\n", x[13], x[14]);
+	printf("    Minimum Vertical Blanking: %u lines\n", x[15] | (x[16] << 8));
+	if (x[17] & 0x80)
+		printf("    Supports Interlaced\n");
+	if (x[17] & 0x40)
+		printf("    Supports CVT\n");
+	if (x[17] & 0x20)
+		printf("    Supports CVT Reduced Blanking\n");
+	if (x[17] & 0x10)
+		printf("    Discrete frequency display device\n");
+}
+
+// tag 0x0a and 0x0b
+
+void edid_state::parse_displayid_string(const unsigned char *x)
+{
+	check_displayid_datablock_revision(x[1]);
+	if (check_displayid_datablock_length(x))
+		printf("    Text: '%s'\n", extract_string(x + 3, x[2]));
+}
+
+// tag 0x0c
+
+void edid_state::parse_displayid_display_device(const unsigned char *x)
+{
+	check_displayid_datablock_revision(x[1]);
+
+	if (!check_displayid_datablock_length(x, 13, 13))
+		return;
+
+	printf("    Display Device Technology: ");
+	switch (x[3]) {
+	case 0x00: printf("Monochrome CRT\n"); break;
+	case 0x01: printf("Standard tricolor CRT\n"); break;
+	case 0x02: printf("Other/undefined CRT\n"); break;
+	case 0x10: printf("Passive matrix TN\n"); break;
+	case 0x11: printf("Passive matrix cholesteric LC\n"); break;
+	case 0x12: printf("Passive matrix ferroelectric LC\n"); break;
+	case 0x13: printf("Other passive matrix LC type\n"); break;
+	case 0x14: printf("Active-matrix TN\n"); break;
+	case 0x15: printf("Active-matrix IPS (all types)\n"); break;
+	case 0x16: printf("Active-matrix VA (all types)\n"); break;
+	case 0x17: printf("Active-matrix OCB\n"); break;
+	case 0x18: printf("Active-matrix ferroelectric\n"); break;
+	case 0x1f: printf("Other LC type\n"); break;
+	case 0x20: printf("DC plasma\n"); break;
+	case 0x21: printf("AC plasma\n"); break;
+	}
+	switch (x[3] & 0xf0) {
+	case 0x30: printf("Electroluminescent, except OEL/OLED\n"); break;
+	case 0x40: printf("Inorganic LED\n"); break;
+	case 0x50: printf("Organic LED/OEL\n"); break;
+	case 0x60: printf("FED or sim. \"cold-cathode,\" phosphor-based types\n"); break;
+	case 0x70: printf("Electrophoretic\n"); break;
+	case 0x80: printf("Electrochromic\n"); break;
+	case 0x90: printf("Electromechanical\n"); break;
+	case 0xa0: printf("Electrowetting\n"); break;
+	case 0xf0: printf("Other type not defined here\n"); break;
+	}
+	printf("    Display operating mode: ");
+	switch (x[4] >> 4) {
+	case 0x00: printf("Direct-view reflective, ambient light\n"); break;
+	case 0x01: printf("Direct-view reflective, ambient light, also has light source\n"); break;
+	case 0x02: printf("Direct-view reflective, uses light source\n"); break;
+	case 0x03: printf("Direct-view transmissive, ambient light\n"); break;
+	case 0x04: printf("Direct-view transmissive, ambient light, also has light source\n"); break;
+	case 0x05: printf("Direct-view transmissive, uses light source\n"); break;
+	case 0x06: printf("Direct-view emissive\n"); break;
+	case 0x07: printf("Direct-view transflective, backlight off by default\n"); break;
+	case 0x08: printf("Direct-view transflective, backlight on by default\n"); break;
+	case 0x09: printf("Transparent display, ambient light\n"); break;
+	case 0x0a: printf("Transparent emissive display\n"); break;
+	case 0x0b: printf("Projection device using reflective light modulator\n"); break;
+	case 0x0c: printf("Projection device using transmissive light modulator\n"); break;
+	case 0x0d: printf("Projection device using emissive image transducer\n"); break;
+	default: printf("Reserved\n"); break;
+	}
+	if (x[4] & 0x08)
+		printf("    The backlight may be switched on and off\n");
+	if (x[4] & 0x04)
+		printf("    The backlight's intensity can be controlled\n");
+	unsigned w = x[5] | (x[6] << 8);
+	unsigned h = x[7] | (x[8] << 8);
+	if (w && h) {
+		printf("    Display native pixel format: %ux%u\n", w + 1, h + 1);
+		dispid.native_width = w + 1;
+		dispid.native_height = h + 1;
+	} else if (w || h) {
+		fail("Invalid Native Pixel Format %ux%u.\n", w, h);
+	}
+	printf("    Aspect ratio and orientation:\n");
+	printf("      Aspect Ratio: %.2f\n", (100 + x[9]) / 100.0);
+	unsigned char v = x[0x0a];
+	printf("      Default Orientation: ");
+	switch ((v & 0xc0) >> 6) {
+	case 0x00: printf("Landscape\n"); break;
+	case 0x01: printf("Portrait\n"); break;
+	case 0x02: printf("Not Fixed\n"); break;
+	case 0x03: printf("Undefined\n"); break;
+	}
+	printf("      Rotation Capability: ");
+	switch ((v & 0x30) >> 4) {
+	case 0x00: printf("None\n"); break;
+	case 0x01: printf("Can rotate 90 degrees clockwise\n"); break;
+	case 0x02: printf("Can rotate 90 degrees counterclockwise\n"); break;
+	case 0x03: printf("Can rotate 90 degrees in either direction)\n"); break;
+	}
+	printf("      Zero Pixel Location: ");
+	switch ((v & 0x0c) >> 2) {
+	case 0x00: printf("Upper Left\n"); break;
+	case 0x01: printf("Upper Right\n"); break;
+	case 0x02: printf("Lower Left\n"); break;
+	case 0x03: printf("Lower Right\n"); break;
+	}
+	printf("      Scan Direction: ");
+	switch (v & 0x03) {
+	case 0x00: printf("Not defined\n"); break;
+	case 0x01: printf("Fast Scan is on the Major (Long) Axis and Slow Scan is on the Minor Axis\n"); break;
+	case 0x02: printf("Fast Scan is on the Minor (Short) Axis and Slow Scan is on the Major Axis\n"); break;
+	case 0x03: printf("Reserved\n");
+		   fail("Scan Direction used the reserved value 0x03.\n");
+		   break;
+	}
+	printf("    Sub-pixel layout/configuration/shape: ");
+	switch (x[0x0b]) {
+	case 0x00: printf("Not defined\n"); break;
+	case 0x01: printf("RGB vertical stripes\n"); break;
+	case 0x02: printf("RGB horizontal stripes\n"); break;
+	case 0x03: printf("Vertical stripes using primary order\n"); break;
+	case 0x04: printf("Horizontal stripes using primary order\n"); break;
+	case 0x05: printf("Quad sub-pixels, red at top left\n"); break;
+	case 0x06: printf("Quad sub-pixels, red at bottom left\n"); break;
+	case 0x07: printf("Delta (triad) RGB sub-pixels\n"); break;
+	case 0x08: printf("Mosaic\n"); break;
+	case 0x09: printf("Quad sub-pixels, RGB + 1 additional color\n"); break;
+	case 0x0a: printf("Five sub-pixels, RGB + 2 additional colors\n"); break;
+	case 0x0b: printf("Six sub-pixels, RGB + 3 additional colors\n"); break;
+	case 0x0c: printf("Clairvoyante, Inc. PenTile Matrix (tm) layout\n"); break;
+	default: printf("Reserved\n"); break;
+	}
+	printf("    Horizontal and vertical dot/pixel pitch: %.2fx%.2f mm\n",
+	       (double)(x[0x0c]) / 100.0, (double)(x[0x0d]) / 100.0);
+	printf("    Color bit depth: %u\n", x[0x0e] & 0x0f);
+	v = x[0x0f];
+	printf("    Response time for %s transition: %u ms\n",
+	       (v & 0x80) ? "white-to-black" : "black-to-white", v & 0x7f);
+}
+
+// tag 0x0d
+
+void edid_state::parse_displayid_intf_power_sequencing(const unsigned char *x)
+{
+	check_displayid_datablock_revision(x[1]);
+
+	if (!check_displayid_datablock_length(x, 6, 6))
+		return;
+
+	printf("    Power Sequence T1 Range: %.1f-%u.0 ms\n", (x[3] >> 4) / 10.0, (x[3] & 0xf) * 2);
+	printf("    Power Sequence T2 Range: 0.0-%u.0 ms\n", (x[4] & 0x3f) * 2);
+	printf("    Power Sequence T3 Range: 0.0-%u.0 ms\n", (x[5] & 0x3f) * 2);
+	printf("    Power Sequence T4 Min: %u.0 ms\n", (x[6] & 0x7f) * 10);
+	printf("    Power Sequence T5 Min: %u.0 ms\n", (x[7] & 0x3f) * 10);
+	printf("    Power Sequence T6 Min: %u.0 ms\n", (x[8] & 0x3f) * 10);
+}
+
+// tag 0x0e
+
+void edid_state::parse_displayid_transfer_characteristics(const unsigned char *x)
+{
+	check_displayid_datablock_revision(x[1], 0xf0, 1);
+
+	unsigned xfer_id = x[1] >> 4;
+	bool first_is_white = x[3] & 0x80;
+	bool four_param = x[3] & 0x20;
+
+	if (xfer_id) {
+		printf("    Transfer Characteristics Data Block Identifier: %u\n", xfer_id);
+		if (!(dispid.preparsed_color_ids & (1 << xfer_id)))
+			fail("Missing Color Characteristics Data Block using Identifier %u.\n", xfer_id);
+	}
+	if (first_is_white)
+		printf("    The first curve is the 'white' transfer characteristic\n");
+	if (x[3] & 0x40)
+		printf("    Individual response curves\n");
+
+	unsigned offset = 4;
+	unsigned len = x[2] - 1;
+
+	for (unsigned i = 0; len; i++) {
+		if ((x[3] & 0x80) && !i)
+			printf("    White curve:      ");
+		else
+			printf("    Response curve #%u:",
+			       i - first_is_white);
+		unsigned samples = x[offset];
+		if (four_param) {
+			if (samples != 5)
+				fail("Expected 5 samples.\n");
+			printf(" A0=%u A1=%u A2=%u A3=%u Gamma=%.2f\n",
+			       x[offset + 1], x[offset + 2], x[offset + 3], x[offset + 4],
+			       (double)(x[offset + 5] + 100.0) / 100.0);
+			samples++;
+		} else {
+			double sum = 0;
+
+			// The spec is not very clear about the number of samples:
+			// should this be interpreted as the actual number of
+			// samples stored in this Data Block, or as the number of
+			// samples in the curve, but where the last sample is not
+			// actually stored since it is always 0x3ff.
+			//
+			// The ATP Manager interprets this as the latter, so that's
+			// what we implement here.
+			for (unsigned j = offset + 1; j < offset + samples; j++) {
+				sum += x[j];
+				printf(" %.2f", sum * 100.0 / 1023.0);
+			}
+			printf(" 100.00\n");
+		}
+		offset += samples;
+		len -= samples;
+	}
+}
+
+// tag 0x0f
+
+void edid_state::parse_displayid_display_intf(const unsigned char *x)
+{
+	check_displayid_datablock_revision(x[1]);
+
+	if (!check_displayid_datablock_length(x, 10, 10))
+		return;
+
+	dispid.has_display_interface_features = true;
+	printf("    Interface Type: ");
+	switch (x[3] >> 4) {
+	case 0x00:
+		switch (x[3] & 0xf) {
+		case 0x00: printf("Analog 15HD/VGA\n"); break;
+		case 0x01: printf("Analog VESA NAVI-V (15HD)\n"); break;
+		case 0x02: printf("Analog VESA NAVI-D\n"); break;
+		default: printf("Reserved\n"); break;
+		}
+		break;
+	case 0x01: printf("LVDS\n"); break;
+	case 0x02: printf("TMDS\n"); break;
+	case 0x03: printf("RSDS\n"); break;
+	case 0x04: printf("DVI-D\n"); break;
+	case 0x05: printf("DVI-I, analog\n"); break;
+	case 0x06: printf("DVI-I, digital\n"); break;
+	case 0x07: printf("HDMI-A\n"); break;
+	case 0x08: printf("HDMI-B\n"); break;
+	case 0x09: printf("MDDI\n"); break;
+	case 0x0a: printf("DisplayPort\n"); break;
+	case 0x0b: printf("Proprietary Digital Interface\n"); break;
+	default: printf("Reserved\n"); break;
+	}
+	if (x[3] >> 4)
+		printf("    Number of Links: %u\n", x[3] & 0xf);
+	printf("    Interface Standard Version: %u.%u\n",
+	       x[4] >> 4, x[4] & 0xf);
+	print_flags("    Supported bpc for RGB encoding", x[5], bpc444);
+	print_flags("    Supported bpc for YCbCr 4:4:4 encoding", x[6], bpc444);
+	print_flags("    Supported bpc for YCbCr 4:2:2 encoding", x[7], bpc4xx);
+	printf("    Supported Content Protection: ");
+	switch (x[8] & 0xf) {
+	case 0x00: printf("None\n"); break;
+	case 0x01: printf("HDCP "); break;
+	case 0x02: printf("DTCP "); break;
+	case 0x03: printf("DPCP "); break;
+	default: printf("Reserved "); break;
+	}
+	if (x[8] & 0xf)
+		printf("%u.%u\n", x[9] >> 4, x[9] & 0xf);
+	unsigned char v = x[0x0a] & 0xf;
+	printf("    Spread Spectrum: ");
+	switch (x[0x0a] >> 6) {
+	case 0x00: printf("None\n"); break;
+	case 0x01: printf("Down Spread %.1f%%\n", v / 10.0); break;
+	case 0x02: printf("Center Spread %.1f%%\n", v / 10.0); break;
+	case 0x03: printf("Reserved\n"); break;
+	}
+	switch (x[3] >> 4) {
+	case 0x01:
+		printf("    LVDS Color Mapping: %s mode\n",
+		       (x[0x0b] & 0x10) ? "6 bit compatible" : "normal");
+		if (x[0x0b] & 0x08) printf("    LVDS supports 2.8V\n");
+		if (x[0x0b] & 0x04) printf("    LVDS supports 12V\n");
+		if (x[0x0b] & 0x02) printf("    LVDS supports 5V\n");
+		if (x[0x0b] & 0x01) printf("    LVDS supports 3.3V\n");
+		printf("    LVDS %s Mode\n", (x[0x0c] & 0x04) ? "Fixed" : "DE");
+		if (x[0x0c] & 0x04)
+			printf("    LVDS %s Signal Level\n", (x[0x0c] & 0x02) ? "Low" : "High");
+		else
+			printf("    LVDS DE Polarity Active %s\n", (x[0x0c] & 0x02) ? "Low" : "High");
+		printf("    LVDS Shift Clock Data Strobe at %s Edge\n", (x[0x0c] & 0x01) ? "Rising" : "Falling");
+		break;
+	case 0x0b:
+		printf("    PDI %s Mode\n", (x[0x0b] & 0x04) ? "Fixed" : "DE");
+		if (x[0x0b] & 0x04)
+			printf("    PDI %s Signal Level\n", (x[0x0b] & 0x02) ? "Low" : "High");
+		else
+			printf("    PDI DE Polarity Active %s\n", (x[0x0b] & 0x02) ? "Low" : "High");
+		printf("    PDI Shift Clock Data Strobe at %s Edge\n", (x[0x0b] & 0x01) ? "Rising" : "Falling");
+		break;
+	}
+}
+
+// tag 0x10 and 0x27
+
+void edid_state::parse_displayid_stereo_display_intf(const unsigned char *x)
+{
+	check_displayid_datablock_revision(x[1], 0xc0, 1);
+
+	switch (x[1] >> 6) {
+	case 0x00: printf("    Timings that explicitly report 3D capability\n"); break;
+	case 0x01: printf("    Timings that explicitly report 3D capability & Timing Codes listed here\n"); break;
+	case 0x02: printf("    All listed timings\n"); break;
+	case 0x03: printf("    Only Timings Codes listed here\n"); break;
+	}
+
+	unsigned len = x[2];
+
+	switch (x[4]) {
+	case 0x00:
+		printf("    Field Sequential Stereo (L/R Polarity: %s)\n",
+		       (x[5] & 1) ? "0/1" : "1/0");
+		break;
+	case 0x01:
+		printf("    Side-by-side Stereo (Left Half = %s Eye View)\n",
+		       (x[5] & 1) ? "Right" : "Left");
+		break;
+	case 0x02:
+		printf("    Pixel Interleaved Stereo:\n");
+		for (unsigned y = 0; y < 8; y++) {
+			unsigned char v = x[5 + y];
+
+			printf("      ");
+			for (int x = 7; x >= 0; x--)
+				printf("%c", (v & (1 << x)) ? 'L' : 'R');
+			printf("\n");
+		}
+		break;
+	case 0x03:
+		printf("    Dual Interface, Left and Right Separate\n");
+		printf("      Carries the %s-eye view\n",
+		       (x[5] & 1) ? "Right" : "Left");
+		printf("      ");
+		switch ((x[5] >> 1) & 3) {
+		case 0x00: printf("No mirroring\n"); break;
+		case 0x01: printf("Left/Right mirroring\n"); break;
+		case 0x02: printf("Top/Bottom mirroring\n"); break;
+		case 0x03: printf("Reserved\n"); break;
+		}
+		break;
+	case 0x04:
+		printf("    Multi-View: %u views, Interleaving Method Code: %u\n",
+		       x[5], x[6]);
+		break;
+	case 0x05:
+		printf("    Stacked Frame Stereo (Top Half = %s Eye View)\n",
+		       (x[5] & 1) ? "Right" : "Left");
+		break;
+	case 0xff:
+		printf("    Proprietary\n");
+		break;
+	default:
+		printf("    Reserved\n");
+		break;
+	}
+	if (!(x[1] & 0x40)) // Has No Timing Codes
+		return;
+	len -= 1 + x[3];
+	x += 4 + x[3];
+	while (1U + (x[0] & 0x1f) <= len) {
+		unsigned num_codes = x[0] & 0x1f;
+		unsigned type = x[0] >> 6;
+		char type_name[16];
+
+		for (unsigned i = 1; i <= num_codes; i++) {
+			switch (type) {
+			case 0x00:
+				sprintf(type_name, "DMT 0x%02x", x[i]);
+				print_timings("    ", find_dmt_id(x[i]), type_name);
+				break;
+			case 0x01:
+				sprintf(type_name, "VIC %3u", x[i]);
+				print_timings("    ", find_vic_id(x[i]), type_name);
+				break;
+			case 0x02:
+				sprintf(type_name, "HDMI VIC %u", x[i]);
+				print_timings("    ", find_hdmi_vic_id(x[i]), type_name);
+				break;
+			}
+		}
+
+		len -= 1 + num_codes;
+		x += 1 + num_codes;
+	}
+}
+
+// tag 0x11
+
+void edid_state::parse_displayid_type_5_timing(const unsigned char *x)
+{
+	struct timings t = {};
+	std::string s("aspect ");
+
+	t.hact = 1 + (x[2] | (x[3] << 8));
+	t.vact = 1 + (x[4] | (x[5] << 8));
+	calc_ratio(&t);
+	s += std::to_string(t.hratio) + ":" + std::to_string(t.vratio);
+	switch ((x[0] >> 5) & 0x3) {
+	case 0:
+		s += ", no 3D stereo";
+		break;
+	case 1:
+		s += ", 3D stereo";
+		break;
+	case 2:
+		s += ", 3D stereo depends on user action";
+		break;
+	case 3:
+		s += ", reserved";
+		fail("Reserved stereo 0x03.\n");
+		break;
+	}
+	if (x[0] & 0x10)
+		s += ", refresh rate * (1000/1001) supported";
+
+	t.rb = RB_CVT_V2;
+	if ((x[0] & 0x03) == 1)
+		warn("Unexpected use of 'custom reduced blanking'.\n");
+	else if ((x[0] & 0x03) > 1)
+		fail("Invalid Timing Formula.\n");
+
+	edid_cvt_mode(1 + x[6], t);
+
+	if (x[0] & 0x80) {
+		s += ", preferred";
+		dispid.preferred_timings.push_back(timings_ext(t, "CVT", s));
+	}
+
+	print_timings("    ", &t, "CVT", s.c_str());
+}
+
+// tag 0x12 and 0x28
+
+void edid_state::parse_displayid_tiled_display_topology(const unsigned char *x, bool is_v2)
+{
+	check_displayid_datablock_revision(x[1]);
+
+	if (!check_displayid_datablock_length(x, 22, 22))
+		return;
+
+	unsigned caps = x[3];
+	unsigned num_v_tile = (x[4] & 0xf) | (x[6] & 0x30);
+	unsigned num_h_tile = (x[4] >> 4) | ((x[6] >> 2) & 0x30);
+	unsigned tile_v_location = (x[5] & 0xf) | ((x[6] & 0x3) << 4);
+	unsigned tile_h_location = (x[5] >> 4) | (((x[6] >> 2) & 0x3) << 4);
+	unsigned tile_width = x[7] | (x[8] << 8);
+	unsigned tile_height = x[9] | (x[10] << 8);
+	unsigned pix_mult = x[11];
+
+	printf("    Capabilities:\n");
+	printf("      Behavior if it is the only tile: ");
+	switch (caps & 0x07) {
+	case 0x00: printf("Undefined\n"); break;
+	case 0x01: printf("Image is displayed at the Tile Location\n"); break;
+	case 0x02: printf("Image is scaled to fit the entire tiled display\n"); break;
+	case 0x03: printf("Image is cloned to all other tiles\n"); break;
+	default: printf("Reserved\n"); break;
+	}
+	printf("      Behavior if more than one tile and fewer than total number of tiles: ");
+	switch ((caps >> 3) & 0x03) {
+	case 0x00: printf("Undefined\n"); break;
+	case 0x01: printf("Image is displayed at the Tile Location\n"); break;
+	default: printf("Reserved\n"); break;
+	}
+	if (caps & 0x80)
+		printf("    Tiled display consists of a single physical display enclosure\n");
+	else
+		printf("    Tiled display consists of multiple physical display enclosures\n");
+	printf("    Num horizontal tiles: %u Num vertical tiles: %u\n",
+	       num_h_tile + 1, num_v_tile + 1);
+	printf("    Tile location: %u, %u\n", tile_h_location, tile_v_location);
+	printf("    Tile resolution: %ux%u\n", tile_width + 1, tile_height + 1);
+	if (caps & 0x40) {
+		if (pix_mult) {
+			printf("    Top bevel size: %.1f pixels\n",
+			       pix_mult * x[12] / 10.0);
+			printf("    Bottom bevel size: %.1f pixels\n",
+			       pix_mult * x[13] / 10.0);
+			printf("    Right bevel size: %.1f pixels\n",
+			       pix_mult * x[14] / 10.0);
+			printf("    Left bevel size: %.1f pixels\n",
+			       pix_mult * x[15] / 10.0);
+		} else {
+			fail("No bevel information, but the pixel multiplier is non-zero.\n");
+		}
+		printf("    Tile resolution: %ux%u\n", tile_width + 1, tile_height + 1);
+	} else if (pix_mult) {
+		fail("No bevel information, but the pixel multiplier is non-zero.\n");
+	}
+	if (is_v2)
+		printf("    Tiled Display Manufacturer/Vendor ID: %02X-%02X-%02X\n",
+		       x[0x10], x[0x11], x[0x12]);
+	else
+		printf("    Tiled Display Manufacturer/Vendor ID: %c%c%c\n",
+		       x[0x10], x[0x11], x[0x12]);
+	printf("    Tiled Display Product ID Code: %u\n",
+	       x[0x13] | (x[0x14] << 8));
+	if (hide_serial_numbers)
+		printf("    Tiled Display Serial Number: ...\n");
+	else
+		printf("    Tiled Display Serial Number: %u\n",
+		       x[0x15] | (x[0x16] << 8) | (x[0x17] << 16)| (x[0x18] << 24));
+}
+
+// tag 0x13
+
+void edid_state::parse_displayid_type_6_timing(const unsigned char *x)
+{
+	struct timings t = {};
+	std::string s("aspect ");
+
+	t.pixclk_khz = 1 + (x[0] + (x[1] << 8) + ((x[2] & 0x3f) << 16));
+	t.hact = 1 + (x[3] | ((x[4] & 0x3f) << 8));
+	if ((x[4] >> 7) & 0x1)
+		t.pos_pol_hsync = true;
+	unsigned hbl = 1 + (x[7] | ((x[9] & 0xf) << 8));
+	t.hfp = 1 + (x[8] | ((x[9] & 0xf0) << 4));
+	t.hsync = 1 + x[10];
+	t.hbp = hbl - t.hfp - t.hsync;
+	t.vact = 1 + (x[5] | ((x[6] & 0x3f) << 8));
+	if ((x[6] >> 7) & 0x1)
+		t.pos_pol_vsync = true;
+	unsigned vbl = 1 + x[11];
+	t.vfp = 1 + x[12];
+	t.vsync = 1 + (x[13] & 0x0f);
+	t.vbp = vbl - t.vfp - t.vsync;
+
+	if (x[13] & 0x80) {
+		t.interlaced = true;
+		t.vfp /= 2;
+		t.vsync /= 2;
+		t.vbp /= 2;
+	}
+	calc_ratio(&t);
+	s += std::to_string(t.hratio) + ":" + std::to_string(t.vratio);
+	if (x[2] & 0x40) {
+		double aspect_mult = x[14] * 3.0 / 256.0;
+		unsigned size_mult = 1 + (x[16] >> 4);
+
+		t.vsize_mm = size_mult * (1 + (x[15] | ((x[16] & 0xf) << 8)));
+		t.hsize_mm = t.vsize_mm * aspect_mult;
+	}
+
+	switch ((x[13] >> 5) & 0x3) {
+	case 0:
+		s += ", no 3D stereo";
+		break;
+	case 1:
+		s += ", 3D stereo";
+		break;
+	case 2:
+		s += ", 3D stereo depends on user action";
+		break;
+	case 3:
+		s += ", reserved";
+		fail("Reserved stereo 0x03.\n");
+		break;
+	}
+
+	if (x[2] & 0x80) {
+		s += ", preferred";
+		dispid.preferred_timings.push_back(timings_ext(t, "DTD", s));
+	}
+
+	print_timings("    ", &t, "DTD", s.c_str(), true);
+}
+
+static std::string ieee7542d(unsigned short fp)
+{
+	int exp = ((fp & 0x7c00) >> 10) - 15;
+	unsigned fract = (fp & 0x3ff) | 0x400;
+
+	if (fp == 0x8000)
+		return "do not use";
+	if (fp & 0x8000)
+		return "reserved";
+	return std::to_string(pow(2, exp) * fract / 1024.0) + " cd/m^2";
+}
+
+// tag 0x21
+
+void edid_state::parse_displayid_parameters_v2(const unsigned char *x,
+					       unsigned block_rev)
+{
+	if (!check_displayid_datablock_length(x, 29, 29))
+		return;
+
+	unsigned hor_size = (x[4] << 8) + x[3];
+	unsigned vert_size = (x[6] << 8) + x[5];
+
+	dispid.has_display_parameters = true;
+	if (x[1] & 0x80)
+		printf("    Image size: %u mm x %u mm\n",
+		       hor_size, vert_size);
+	else
+		printf("    Image size: %.1f mm x %.1f mm\n",
+		       hor_size / 10.0, vert_size / 10.0);
+	unsigned w = (x[8] << 8) + x[7];
+	unsigned h = (x[10] << 8) + x[9];
+	if (w && h) {
+		printf("    Native Format: %ux%u\n", w, h);
+		dispid.native_width = w;
+		dispid.native_height = h;
+	} else if (w || h) {
+		fail("Invalid Native Format %ux%u.\n", w, h);
+	}
+	unsigned char v = x[11];
+	printf("    Scan Orientation: ");
+	switch (v & 0x07) {
+	case 0x00: printf("Left to Right, Top to Bottom\n"); break;
+	case 0x01: printf("Right to Left, Top to Bottom\n"); break;
+	case 0x02: printf("Top to Bottom, Right to Left\n"); break;
+	case 0x03: printf("Bottom to Top, Right to Left\n"); break;
+	case 0x04: printf("Right to Left, Bottom to Top\n"); break;
+	case 0x05: printf("Left to Right, Bottom to Top\n"); break;
+	case 0x06: printf("Bottom to Top, Left to Right\n"); break;
+	case 0x07: printf("Top to Bottom, Left to Right\n"); break;
+	}
+	printf("    Luminance Information: ");
+	switch ((v >> 3) & 0x03) {
+	case 0x00: printf("Minimum guaranteed value\n"); break;
+	case 0x01: printf("Guidance for the Source device\n"); break;
+	default: printf("Reserved\n"); break;
+	}
+	printf("    Color Information: CIE %u\n",
+	       (v & 0x40) ? 1976 : 1931);
+	printf("    Audio Speaker Information: %sintegrated\n",
+	       (v & 0x80) ? "not " : "");
+	printf("    Native Color Chromaticity:\n");
+	printf("      Primary #1:  (%.6f, %.6f)\n",
+	       fp2d(x[0x0c] | ((x[0x0d] & 0x0f) << 8)),
+	       fp2d(((x[0x0d] & 0xf0) >> 4) | (x[0x0e] << 4)));
+	printf("      Primary #2:  (%.6f, %.6f)\n",
+	       fp2d(x[0x0f] | ((x[0x10] & 0x0f) << 8)),
+	       fp2d(((x[0x10] & 0xf0) >> 4) | (x[0x11] << 4)));
+	printf("      Primary #3:  (%.6f, %.6f)\n",
+	       fp2d(x[0x12] | ((x[0x13] & 0x0f) << 8)),
+	       fp2d(((x[0x13] & 0xf0) >> 4) | (x[0x14] << 4)));
+	printf("      White Point: (%.6f, %.6f)\n",
+	       fp2d(x[0x15] | ((x[0x16] & 0x0f) << 8)),
+	       fp2d(((x[0x16] & 0xf0) >> 4) | (x[0x17] << 4)));
+	printf("    Native Maximum Luminance (Full Coverage): %s\n",
+	       ieee7542d(x[0x18] | (x[0x19] << 8)).c_str());
+	printf("    Native Maximum Luminance (10%% Rectangular Coverage): %s\n",
+	       ieee7542d(x[0x1a] | (x[0x1b] << 8)).c_str());
+	printf("    Native Minimum Luminance: %s\n",
+	       ieee7542d(x[0x1c] | (x[0x1d] << 8)).c_str());
+	printf("    Native Color Depth: ");
+	if (!(x[0x1e] & 0x07))
+		printf("Not defined\n");
+	else if (bpc444[x[0x1e] & 0x07])
+		printf("%s bpc\n", bpc444[x[0x1e] & 0x07]);
+	else
+		printf("Reserved\n");
+	printf("    Display Device Technology: ");
+	switch ((x[0x1e] >> 4) & 0x07) {
+	case 0x00: printf("Not Specified\n"); break;
+	case 0x01: printf("Active Matrix LCD\n"); break;
+	case 0x02: printf("Organic LED\n"); break;
+	default: printf("Reserved\n"); break;
+	}
+	if (block_rev)
+		printf("    Display Device Theme Preference: %s\n",
+		       (x[0x1e] & 0x80) ? "Dark Theme Preferred" : "No Preference");
+	if (x[0x1f] != 0xff)
+		printf("    Native Gamma EOTF: %.2f\n",
+		       (100 + x[0x1f]) / 100.0);
+}
+
+// tag 0x24
+
+void edid_state::parse_displayid_type_9_timing(const unsigned char *x)
+{
+	struct timings t = {};
+	std::string s("aspect ");
+
+	t.hact = 1 + (x[1] | (x[2] << 8));
+	t.vact = 1 + (x[3] | (x[4] << 8));
+	calc_ratio(&t);
+	s += std::to_string(t.hratio) + ":" + std::to_string(t.vratio);
+	switch ((x[0] >> 5) & 0x3) {
+	case 0:
+		s += ", no 3D stereo";
+		break;
+	case 1:
+		s += ", 3D stereo";
+		break;
+	case 2:
+		s += ", 3D stereo depends on user action";
+		break;
+	case 3:
+		s += ", reserved";
+		fail("Reserved stereo 0x03.\n");
+		break;
+	}
+	if (x[0] & 0x10)
+		s += ", refresh rate * (1000/1001) supported";
+
+	switch (x[0] & 0x07) {
+	case 1: t.rb = RB_CVT_V1; break;
+	case 2: t.rb = RB_CVT_V2; break;
+	default: break;
+	}
+
+	edid_cvt_mode(1 + x[5], t);
+
+	print_timings("    ", &t, "CVT", s.c_str());
+}
+
+// tag 0x25
+
+void edid_state::parse_displayid_dynamic_video_timings_range_limits(const unsigned char *x)
+{
+	check_displayid_datablock_revision(x[1], 0, (x[1] & 7) == 1);
+
+	if (!check_displayid_datablock_length(x, 9, 9))
+		return;
+
+	printf("    Minimum Pixel Clock: %u kHz\n",
+	       1 + (x[3] | (x[4] << 8) | (x[5] << 16)));
+	printf("    Maximum Pixel Clock: %u kHz\n",
+	       1 + (x[6] | (x[7] << 8) | (x[8] << 16)));
+	printf("    Minimum Vertical Refresh Rate: %u Hz\n", x[9]);
+	if (x[1] & 7)
+		printf("    Maximum Vertical Refresh Rate: %u Hz\n", x[10] + ((x[11] & 3) << 8));
+	else
+		printf("    Maximum Vertical Refresh Rate: %u Hz\n", x[10]);
+	printf("    Seamless Dynamic Video Timing Support: %s\n",
+	       (x[11] & 0x80) ? "Yes" : "No");
+}
+
+// tag 0x26
+
+static const char *colorspace_eotf_combinations[] = {
+	"sRGB",
+	"BT.601",
+	"BT.709/BT.1886",
+	"Adobe RGB",
+	"DCI-P3",
+	"BT.2020",
+	"BT.2020/SMPTE ST 2084"
+};
+
+static const char *colorspace_eotf_reserved[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+
+static const char *colorspaces[] = {
+	"Undefined",
+	"sRGB",
+	"BT.601",
+	"BT.709",
+	"Adobe RGB",
+	"DCI-P3",
+	"BT.2020",
+	"Custom"
+};
+
+static const char *eotfs[] = {
+	"Undefined",
+	"sRGB",
+	"BT.601",
+	"BT.1886",
+	"Adobe RGB",
+	"DCI-P3",
+	"BT.2020",
+	"Gamma function",
+	"SMPTE ST 2084",
+	"Hybrid Log",
+	"Custom"
+};
+
+void edid_state::parse_displayid_interface_features(const unsigned char *x)
+{
+	check_displayid_datablock_revision(x[1]);
+
+	if (!check_displayid_datablock_length(x, 9))
+		return;
+
+	dispid.has_display_interface_features = true;
+	unsigned len = x[2];
+	if (len > 0) print_flags("    Supported bpc for RGB encoding", x[3], bpc444);
+	if (len > 1) print_flags("    Supported bpc for YCbCr 4:4:4 encoding", x[4], bpc444);
+	if (len > 2) print_flags("    Supported bpc for YCbCr 4:2:2 encoding", x[5], bpc4xx);
+	if (len > 3) print_flags("    Supported bpc for YCbCr 4:2:0 encoding", x[6], bpc4xx);
+	if (len > 4 && x[7])
+		printf("    Minimum pixel rate at which YCbCr 4:2:0 encoding is supported: %.3f MHz\n",
+		       74.25 * x[7]);
+	if (len > 5) print_flags("    Supported audio capability and features (kHz)",
+				 x[8], audiorates, true);
+	if (len > 6) print_flags("    Supported color space and EOTF standard combination 1",
+				 x[9], colorspace_eotf_combinations);
+	if (len > 7) print_flags("    Supported color space and EOTF standard combination 2",x[10], colorspace_eotf_reserved);
+
+	unsigned i = 0;
+
+	if (len > 8 && x[11]) {
+		printf("    Supported color space and EOTF additional combinations:");
+		for (i = 0; i < x[11]; i++) {
+			if (i > 6) {
+				printf("\n    Number of additional color space and EOTF combinations (%d) is greater than allowed (7).", x[11]);
+				break;
+			} else if (i + 10 > len) {
+				printf("\n    Number of additional color space and EOTF combinations (%d) is too many to fit in block (%d).", x[11], len - 9);
+				break;
+			}
+
+			const char *colorspace = "Out of range";
+			const char *eotf = "Out of range";
+			unsigned colorspace_index = (x[12 + i] >> 4) & 0xf;
+			unsigned eotf_index = x[12 + i] & 0xf;
+
+			if (colorspace_index < sizeof(colorspaces) / sizeof(colorspaces[0]))
+				colorspace = colorspaces[colorspace_index];
+			if (eotf_index < sizeof(eotfs) / sizeof(eotfs[0]))
+				eotf = eotfs[eotf_index];
+
+			if (i > 0)
+				printf(", ");
+			if (!strcmp(colorspace, eotf))
+				printf("%s", colorspace);
+			else
+				printf("%s/%s", colorspace, eotf);
+		}
+		printf("\n");
+	}
+	check_displayid_datablock_length(x, 9 + i, 9 + i, 9 + i);
+}
+
+// tag 0x29
+
+void edid_state::parse_displayid_ContainerID(const unsigned char *x)
+{
+	check_displayid_datablock_revision(x[1]);
+
+	if (check_displayid_datablock_length(x, 16, 16)) {
+		x += 3;
+		printf("    Container ID: %s\n", containerid2s(x).c_str());
+	}
+}
+
+// tag 0x32
+
+void edid_state::parse_displayid_type_10_timing(const unsigned char *x, bool is_cta)
+{
+	struct timings t = {};
+	std::string s("aspect ");
+
+	t.hact = 1 + (x[1] | (x[2] << 8));
+	t.vact = 1 + (x[3] | (x[4] << 8));
+	calc_ratio(&t);
+	s += std::to_string(t.hratio) + ":" + std::to_string(t.vratio);
+
+	switch ((x[0] >> 5) & 0x3) {
+	case 0:
+		s += ", no 3D stereo";
+		break;
+	case 1:
+		s += ", 3D stereo";
+		break;
+	case 2:
+		s += ", 3D stereo depends on user action";
+		break;
+	case 3:
+		s += ", reserved";
+		fail("Reserved stereo 0x03.\n");
+		break;
+	}
+
+	switch (x[0] & 0x07) {
+	case 1: t.rb = RB_CVT_V1; break;
+	case 2: t.rb = RB_CVT_V2; break;
+	case 3: t.rb = RB_CVT_V3; break;
+	default: break;
+	}
+
+	if (x[0] & 0x10) {
+		if (t.rb == RB_CVT_V2) {
+			s += ", refresh rate * (1000/1001) supported";
+			t.rb |= RB_ALT;
+		} else if (t.rb == RB_CVT_V3) {
+			s += ", hblank is 160 pixels";
+			t.rb |= RB_ALT;
+		} else {
+			fail("VR_HB must be 0.\n");
+		}
+	}
+	if (x[0] & 0x80)
+		s += ", YCbCr 4:2:0";
+
+	edid_cvt_mode(1 + x[5], t);
+
+	print_timings("    ", &t, "CVT", s.c_str());
+	if (is_cta) {
+		timings_ext te(t, "CVT", s);
+		cta.vec_vtdbs.push_back(te);
+	}
+}
+
+// tag 0x7e, OUI 3A-02-92 (VESA)
+
+void edid_state::parse_displayid_vesa(const unsigned char *x)
+{
+	check_displayid_datablock_revision(x[1]);
+
+	if (!check_displayid_datablock_length(x, 5, 7))
+		return;
+
+	unsigned len = x[2];
+	x += 6;
+	printf("    Data Structure Type: ");
+	switch (x[0] & 0x07) {
+	case 0x00: printf("eDP\n"); break;
+	case 0x01: printf("DP\n"); break;
+	default: printf("Reserved\n"); break;
+	}
+	printf("    Default Colorspace and EOTF Handling: %s\n",
+	       (x[0] & 0x80) ? "Native as specified in the Display Parameters DB" : "sRGB");
+	printf("    Number of Pixels in Hor Pix Cnt Overlapping an Adjacent Panel: %u\n",
+	       x[1] & 0xf);
+	printf("    Multi-SST Operation: ");
+	switch ((x[1] >> 5) & 0x03) {
+	case 0x00: printf("Not Supported\n"); break;
+	case 0x01: printf("Two Streams (number of links shall be 2 or 4)\n"); break;
+	case 0x02: printf("Four Streams (number of links shall be 4)\n"); break;
+	case 0x03: printf("Reserved\n"); break;
+	}
+	if (len >= 7) {
+		double bpp = (x[2] & 0x3f) + (x[3] & 0x0f) / 16.0;
+		printf("    Pass through timing's target DSC bits per pixel: %.4f\n", bpp);
+	}
+}
+
+// tag 0x81
+
+void edid_state::parse_displayid_cta_data_block(const unsigned char *x)
+{
+	check_displayid_datablock_revision(x[1]);
+
+	unsigned len = x[2];
+	unsigned i;
+
+	if (len > 248) {
+		fail("Length is > 248.\n");
+		len = 248;
+	}
+	x += 3;
+
+	for (i = 0; i < len; i += (x[i] & 0x1f) + 1) {
+		unsigned tag = (x[i] & 0xe0) << 3;
+
+		if (tag == 0x700)
+			tag |= x[i + 1];
+		bool duplicate = dispid.found_tags.find(tag) != dispid.found_tags.end();
+
+		cta_block(x + i, duplicate);
+		if (!duplicate)
+			dispid.found_tags.insert(tag);
+	}
+
+	if (i != len)
+		fail("Length is %u instead of %u.\n", len, i);
+}
+
+// DisplayID main
+
+std::string edid_state::product_type(unsigned char x, bool heading)
+{
+	std::string headingstr;
+
+	if (dispid.version < 0x20) {
+		headingstr = "Display Product Type";
+		if (heading) return headingstr;
+		dispid.is_display = x == 2 || x == 3 || x == 4 || x == 6;
+		switch (x) {
+		case 0: return "Extension Section";
+		case 1: return "Test Structure; test equipment only";
+		case 2: return "Display panel or other transducer, LCD or PDP module, etc.";
+		case 3: return "Standalone display device";
+		case 4: return "Television receiver";
+		case 5: return "Repeater/translator";
+		case 6: return "DIRECT DRIVE monitor";
+		default: break;
+		}
+	} else {
+		headingstr = "Display Product Primary Use Case";
+		if (heading) return headingstr;
+		dispid.is_display = x >= 2 && x <= 8;
+		switch (x) {
+		case 0: return "Same primary use case as the base section";
+		case 1: return "Test Structure; test equipment only";
+		case 2: return "None of the listed primary use cases; generic display";
+		case 3: return "Television (TV) display";
+		case 4: return "Desktop productivity display";
+		case 5: return "Desktop gaming display";
+		case 6: return "Presentation display";
+		case 7: return "Head-mounted Virtual Reality (VR) display";
+		case 8: return "Head-mounted Augmented Reality (AR) display";
+		default: break;
+		}
+	}
+	fail("Unknown %s 0x%02x.\n", headingstr.c_str(), x);
+	return std::string("Unknown " + headingstr + " (") + utohex(x) + ")";
+}
+
+void edid_state::preparse_displayid_block(const unsigned char *x)
+{
+	unsigned length = x[2];
+
+	if (length > 121)
+		length = 121;
+
+	unsigned offset = 5;
+
+	dispid.preparsed_displayid_blocks++;
+	while (length > 0) {
+		unsigned tag = x[offset];
+		unsigned len = x[offset + 2];
+
+		switch (tag) {
+		case 0x02:
+			dispid.preparsed_color_ids |= 1 << ((x[offset + 1] >> 3) & 0x0f);
+			break;
+		case 0x0e:
+			dispid.preparsed_xfer_ids |= 1 << ((x[offset + 1] >> 4) & 0x0f);
+			break;
+		default:
+			break;
+		}
+
+		if (length < 3)
+			break;
+
+		if (length < len + 3)
+			break;
+
+		if (!tag && !len)
+			break;
+
+		length -= len + 3;
+		offset += len + 3;
+	}
+}
+
+void edid_state::parse_displayid_block(const unsigned char *x)
+{
+	unsigned version = x[1];
+	unsigned length = x[2];
+	unsigned prod_type = x[3]; // future check: based on type, check for required data blocks
+	unsigned ext_count = x[4];
+	unsigned i;
+
+	printf("  Version: %u.%u\n  Extension Count: %u\n",
+	       version >> 4, version & 0xf, ext_count);
+
+	if (dispid.is_base_block) {
+		dispid.version = version;
+		printf("  %s: %s\n", product_type(prod_type, true).c_str(),
+		       product_type(prod_type, false).c_str());
+		if (!prod_type)
+			fail("DisplayID Base Block has no product type.\n");
+		if (ext_count != dispid.preparsed_displayid_blocks - 1)
+			fail("Expected %u DisplayID Extension Block%s, but got %u.\n",
+			     ext_count,
+			     ext_count > 1 ? "s" : "",
+			     dispid.preparsed_displayid_blocks - 1);
+	} else {
+		if (prod_type)
+			fail("Product Type should be 0 in extension block.\n");
+		if (ext_count)
+			fail("Extension Count should be 0 in extension block.\n");
+		if (version != dispid.version)
+			fail("Got version %u.%u, expected %u.%u.\n",
+			     version >> 4, version & 0xf,
+			     dispid.version >> 4, dispid.version & 0xf);
+	}
+
+	if (length > 121) {
+		fail("DisplayID length %d is greater than 121.\n", length);
+		length = 121;
+	}
+
+	unsigned offset = 5;
+	bool first_data_block = true;
+	while (length > 0) {
+		unsigned tag = x[offset];
+		unsigned oui = 0;
+
+		switch (tag) {
+		// DisplayID 1.3:
+		case 0x00: data_block = "Product Identification Data Block (" + utohex(tag) + ")"; break;
+		case 0x01: data_block = "Display Parameters Data Block (" + utohex(tag) + ")"; break;
+		case 0x02: data_block = "Color Characteristics Data Block"; break;
+		case 0x03: data_block = "Video Timing Modes Type 1 - Detailed Timings Data Block"; break;
+		case 0x04: data_block = "Video Timing Modes Type 2 - Detailed Timings Data Block"; break;
+		case 0x05: data_block = "Video Timing Modes Type 3 - Short Timings Data Block"; break;
+		case 0x06: data_block = "Video Timing Modes Type 4 - DMT Timings Data Block"; break;
+		case 0x07: data_block = "Supported Timing Modes Type 1 - VESA DMT Timings Data Block"; break;
+		case 0x08: data_block = "Supported Timing Modes Type 2 - CTA-861 Timings Data Block"; break;
+		case 0x09: data_block = "Video Timing Range Data Block"; break;
+		case 0x0a: data_block = "Product Serial Number Data Block"; break;
+		case 0x0b: data_block = "GP ASCII String Data Block"; break;
+		case 0x0c: data_block = "Display Device Data Data Block"; break;
+		case 0x0d: data_block = "Interface Power Sequencing Data Block"; break;
+		case 0x0e: data_block = "Transfer Characteristics Data Block"; break;
+		case 0x0f: data_block = "Display Interface Data Block"; break;
+		case 0x10: data_block = "Stereo Display Interface Data Block (" + utohex(tag) + ")"; break;
+		case 0x11: data_block = "Video Timing Modes Type 5 - Short Timings Data Block"; break;
+		case 0x12: data_block = "Tiled Display Topology Data Block (" + utohex(tag) + ")"; break;
+		case 0x13: data_block = "Video Timing Modes Type 6 - Detailed Timings Data Block"; break;
+		// 0x14 .. 0x7e RESERVED for Additional VESA-defined Data Blocks
+		// DisplayID 2.0
+		case 0x20: data_block = "Product Identification Data Block (" + utohex(tag) + ")"; break;
+		case 0x21: data_block = "Display Parameters Data Block (" + utohex(tag) + ")"; break;
+		case 0x22: data_block = "Video Timing Modes Type 7 - Detailed Timings Data Block"; break;
+		case 0x23: data_block = "Video Timing Modes Type 8 - Enumerated Timing Codes Data Block"; break;
+		case 0x24: data_block = "Video Timing Modes Type 9 - Formula-based Timings Data Block"; break;
+		case 0x25: data_block = "Dynamic Video Timing Range Limits Data Block"; break;
+		case 0x26: data_block = "Display Interface Features Data Block"; break;
+		case 0x27: data_block = "Stereo Display Interface Data Block (" + utohex(tag) + ")"; break;
+		case 0x28: data_block = "Tiled Display Topology Data Block (" + utohex(tag) + ")"; break;
+		case 0x29: data_block = "ContainerID Data Block"; break;
+		case 0x32: data_block = "Video Timing Modes Type 10 - Formula-based Timings Data Block"; break;
+		// 0x2a .. 0x7d RESERVED for Additional VESA-defined Data Blocks
+		case 0x7e: // DisplayID 2.0
+		case 0x7f: // DisplayID 1.3
+			if ((tag == 0x7e && version >= 0x20) ||
+			    (tag == 0x7f && version < 0x20)) {
+				oui = (x[offset + 3] << 16) + (x[offset + 4] << 8) + x[offset + 5];
+				const char *name = oui_name(oui);
+				bool reversed = false;
+
+				if (!name) {
+					name = oui_name(oui, true);
+					if (name)
+						reversed = true;
+				}
+				if (name)
+					data_block = std::string("Vendor-Specific Data Block (") + name + ")";
+				else
+					data_block = "Vendor-Specific Data Block, OUI " + ouitohex(oui);
+				if (reversed)
+					fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order.\n").c_str());
+			} else {
+				data_block = "Unknown DisplayID Data Block (" + utohex(tag) + ")";
+			}
+			break;
+		// 0x80 RESERVED
+		case 0x81: data_block = "CTA-861 DisplayID Data Block (" + utohex(tag) + ")"; break;
+		// 0x82 .. 0xff RESERVED
+		default:   data_block = "Unknown DisplayID Data Block (" + utohex(tag) + ")"; break;
+		}
+
+		if (version >= 0x20 && (tag < 0x20 || tag == 0x7f))
+			fail("Use of DisplayID v1.x tag for DisplayID v%u.%u.\n",
+			     version >> 4, version & 0xf);
+		if (version < 0x20 && tag >= 0x20 && tag <= 0x7e)
+			fail("Use of DisplayID v2.0 tag for DisplayID v%u.%u.\n",
+			     version >> 4, version & 0xf);
+
+		if (length < 3) {
+			// report a problem when the remaining bytes are not 0.
+			if (tag || x[offset + 1]) {
+				fail("Not enough bytes remain (%d) for a DisplayID data block or the DisplayID filler is non-0.\n", length);
+			}
+			break;
+		}
+
+		unsigned block_rev = x[offset + 1] & 0x07;
+		unsigned len = x[offset + 2];
+
+		if (length < len + 3) {
+			fail("The length of this DisplayID data block (%d) exceeds the number of bytes remaining (%d).\n", len + 3, length);
+			break;
+		}
+
+		if (!tag && !len) {
+			// A Product Identification Data Block with no payload bytes is not valid - assume this is the end.
+			if (!memchk(x + offset, length)) {
+				fail("Non-0 filler bytes in the DisplayID block.\n");
+			}
+			break;
+		}
+
+		printf("  %s:\n", data_block.c_str());
+
+		switch (tag) {
+		case 0x00: parse_displayid_product_id(x + offset); break;
+		case 0x01: parse_displayid_parameters(x + offset); break;
+		case 0x02: parse_displayid_color_characteristics(x + offset); break;
+		case 0x03:
+			   check_displayid_datablock_revision(x[offset + 1], 0, block_rev & 1);
+			   for (i = 0; i < len / 20; i++)
+				   parse_displayid_type_1_7_timing(&x[offset + 3 + (i * 20)], false, block_rev);
+			   break;
+		case 0x04:
+			   check_displayid_datablock_revision(x[offset + 1]);
+			   for (i = 0; i < len / 11; i++)
+				   parse_displayid_type_2_timing(&x[offset + 3 + (i * 11)]);
+			   break;
+		case 0x05:
+			   check_displayid_datablock_revision(x[offset + 1], 0, block_rev & 1);
+			   for (i = 0; i < len / 3; i++)
+				   parse_displayid_type_3_timing(&x[offset + 3 + (i * 3)]);
+			   break;
+		case 0x06:
+			   check_displayid_datablock_revision(x[offset + 1], 0xc0, 1);
+			   for (i = 0; i < len; i++)
+				   parse_displayid_type_4_8_timing((x[offset + 1] & 0xc0) >> 6, x[offset + 3 + i]);
+			   break;
+		case 0x07:
+			   check_displayid_datablock_revision(x[offset + 1]);
+			   for (i = 0; i < min(len, 10) * 8; i++)
+				   if (x[offset + 3 + i / 8] & (1 << (i % 8))) {
+					   char type[16];
+					   sprintf(type, "DMT 0x%02x", i + 1);
+					   print_timings("    ", find_dmt_id(i + 1), type);
+				   }
+			   break;
+		case 0x08:
+			   check_displayid_datablock_revision(x[offset + 1]);
+			   for (i = 0; i < min(len, 8) * 8; i++)
+				   if (x[offset + 3 + i / 8] & (1 << (i % 8))) {
+					   char type[16];
+					   sprintf(type, "VIC %3u", i + 1);
+					   print_timings("    ", find_vic_id(i + 1), type);
+				   }
+			   break;
+		case 0x09: parse_displayid_video_timing_range_limits(x + offset); break;
+		case 0x0a:
+		case 0x0b: parse_displayid_string(x + offset); break;
+		case 0x0c: parse_displayid_display_device(x + offset); break;
+		case 0x0d: parse_displayid_intf_power_sequencing(x + offset); break;
+		case 0x0e: parse_displayid_transfer_characteristics(x + offset); break;
+		case 0x0f: parse_displayid_display_intf(x + offset); break;
+		case 0x10: parse_displayid_stereo_display_intf(x + offset); break;
+		case 0x11:
+			   check_displayid_datablock_revision(x[offset + 1]);
+			   for (i = 0; i < len / 7; i++)
+				   parse_displayid_type_5_timing(&x[offset + 3 + (i * 7)]);
+			   break;
+		case 0x12: parse_displayid_tiled_display_topology(x + offset, false); break;
+		case 0x13:
+			   check_displayid_datablock_revision(x[offset + 1]);
+			   for (i = 0; i < len; i += (x[offset + 3 + i + 2] & 0x40) ? 17 : 14)
+				   parse_displayid_type_6_timing(&x[offset + 3 + i]);
+			   break;
+		case 0x20: parse_displayid_product_id(x + offset); break;
+		case 0x21:
+			   if (block_rev >= 1)
+				   check_displayid_datablock_revision(x[offset + 1], 0x80, 1);
+			   else
+				   check_displayid_datablock_revision(x[offset + 1], 0x80, 0);
+			   parse_displayid_parameters_v2(x + offset, block_rev);
+			   break;
+		case 0x22: {
+			   unsigned sz = 20;
+
+			   if (block_rev >= 2)
+				   check_displayid_datablock_revision(x[offset + 1], 0x08, 2);
+			   else if (block_rev == 1)
+				   check_displayid_datablock_revision(x[offset + 1], 0x08, 1);
+			   else
+				   check_displayid_datablock_revision(x[offset + 1]);
+			   sz += (x[offset + 1] & 0x70) >> 4;
+			   if (block_rev >= 1 && (x[offset + 1] & 0x08))
+				   printf("    These timings support DSC pass-through\n");
+			   for (i = 0; i < len / sz; i++)
+				   parse_displayid_type_1_7_timing(&x[offset + 3 + i * sz], true, block_rev);
+			   break;
+		}
+		case 0x23:
+			   if (block_rev)
+				   check_displayid_datablock_revision(x[offset + 1], 0xe8, 1);
+			   else
+				   check_displayid_datablock_revision(x[offset + 1], 0xc8);
+			   if (x[offset + 1] & 0x08) {
+				   for (i = 0; i < len / 2; i++)
+					   parse_displayid_type_4_8_timing((x[offset + 1] & 0xc0) >> 6,
+									   x[offset + 3 + i * 2] |
+									   (x[offset + 4 + i * 2] << 8));
+			   } else {
+				   for (i = 0; i < len; i++)
+					   parse_displayid_type_4_8_timing((x[offset + 1] & 0xc0) >> 6,
+									   x[offset + 3 + i]);
+			   }
+			   break;
+		case 0x24:
+			   check_displayid_datablock_revision(x[offset + 1]);
+			   for (i = 0; i < len / 6; i++)
+				   parse_displayid_type_9_timing(&x[offset + 3 + i * 6]);
+			   break;
+		case 0x25: parse_displayid_dynamic_video_timings_range_limits(x + offset); break;
+		case 0x26: parse_displayid_interface_features(x + offset); break;
+		case 0x27: parse_displayid_stereo_display_intf(x + offset); break;
+		case 0x28: parse_displayid_tiled_display_topology(x + offset, true); break;
+		case 0x29: parse_displayid_ContainerID(x + offset); break;
+		case 0x32: {
+			   unsigned sz = 6 + ((x[offset + 1] & 0x70) >> 4);
+
+			   check_displayid_datablock_revision(x[offset + 1], 0x10);
+			   for (i = 0; i < len / sz; i++)
+				   parse_displayid_type_10_timing(&x[offset + 3 + i * sz]);
+			   break;
+		}
+		case 0x81: parse_displayid_cta_data_block(x + offset); break;
+		case 0x7e:
+			if (oui == 0x3a0292) {
+				parse_displayid_vesa(x + offset);
+				break;
+			}
+			// fall-through
+		default: hex_block("    ", x + offset + 3, len); break;
+		}
+
+		if ((tag == 0x00 || tag == 0x20) &&
+		    (!dispid.is_base_block || !first_data_block))
+			fail("%s is required to be the first DisplayID Data Block.\n",
+			     data_block.c_str());
+		length -= len + 3;
+		offset += len + 3;
+		first_data_block = false;
+	}
+
+	/*
+	 * DisplayID length field is number of following bytes
+	 * but checksum is calculated over the entire structure
+	 * (excluding DisplayID-in-EDID magic byte)
+	 */
+	data_block.clear();
+	do_checksum("  ", x + 1, x[2] + 5);
+
+	if (!memchk(x + 1 + x[2] + 5, 0x7f - (1 + x[2] + 5))) {
+		data_block = "Padding";
+		fail("DisplayID padding contains non-zero bytes.\n");
+	}
+	dispid.is_base_block = false;
+}
+
+void edid_state::check_displayid_blocks()
+{
+	data_block = "DisplayID";
+	if (!dispid.has_product_identification)
+		fail("Missing DisplayID Product Identification Data Block.\n");
+	if (dispid.is_display && !dispid.has_display_parameters)
+		fail("Missing DisplayID Display Parameters Data Block.\n");
+	if (dispid.is_display && !dispid.has_display_interface_features)
+		fail("Missing DisplayID Display Interface Features Data Block.\n");
+	if (dispid.is_display && !dispid.has_type_1_7)
+		fail("Missing DisplayID Type %s Detailed Timing Data Block.\n",
+		     dispid.version >= 0x20 ? "VII" : "I");
+	if (dispid.preferred_timings.empty())
+		fail("DisplayID expects at least one preferred timing.\n");
+}
diff --git a/parse-ls-ext-block.cpp b/parse-ls-ext-block.cpp
new file mode 100644
index 0000000..1643f7d
--- /dev/null
+++ b/parse-ls-ext-block.cpp
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2019-2020 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ *
+ * Author: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+ */
+
+#include "edid-decode.h"
+
+static void parse_string(const char *name, const unsigned char *x)
+{
+	if (!*x)
+		return;
+	printf("  %s: ", name);
+	hex_block("", x + 1, *x, true, *x);
+}
+
+void edid_state::parse_string_table(const unsigned char *x)
+{
+	printf("  UTF Type: ");
+	switch (x[0] & 7) {
+	case 0: printf("UTF 8\n"); break;
+	case 1: printf("UTF 16BE\n"); break;
+	case 2: printf("UTF 32BE\n"); break;
+	default:
+		printf("Unknown (0x%02x)\n", x[0] & 7);
+		fail("Unknown UTF Type (0x%02x).\n", x[0] & 7);
+		break;
+	}
+	printf("  Country Code ID (ISO 3166-3): %u\n", ((x[1] & 0x3f) << 8) | x[2]);
+
+	if (x[3] || x[4]) {
+		char name[4];
+
+		name[0] = ((x[3] & 0x7c) >> 2) + '@';
+		name[1] = ((x[3] & 0x03) << 3) + ((x[4] & 0xe0) >> 5) + '@';
+		name[2] = (x[4] & 0x1f) + '@';
+		name[3] = 0;
+		if (name[0] == '@') name[0] = ' ';
+		if (name[1] == '@') name[1] = ' ';
+		if (name[2] == '@') name[2] = ' ';
+		printf("  Language ID: '%s'\n", name);
+	}
+	x += 5;
+	parse_string("Manufacturer Name", x);
+	x += x[0] + 1;
+	parse_string("Model Name", x);
+	x += x[0] + 1;
+	if (hide_serial_numbers)
+		printf("  Serial Number: ...\n");
+	else
+		parse_string("Serial Number", x);
+}
+
+void edid_state::parse_ls_ext_block(const unsigned char *x)
+{
+	const unsigned char *orig = x;
+
+	printf("  Version: %u.%u\n  Unicode Version: %u.%u.%u\n",
+	       x[1], x[2], (x[3] >> 4), x[3] & 0x0f, x[4]);
+	x += 5;
+
+	while (x[0] && x + x[0] < orig + 127) {
+		parse_string_table(x + 1);
+		x += x[0];
+	}
+	if (!memchk(x, orig + 127 - x)) {
+		data_block.clear();
+		fail("Non-zero values in unused space.\n");
+	}
+}
diff --git a/parse-vtb-ext-block.cpp b/parse-vtb-ext-block.cpp
new file mode 100644
index 0000000..05d54f4
--- /dev/null
+++ b/parse-vtb-ext-block.cpp
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2019-2020 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ *
+ * Author: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+ */
+
+#include "edid-decode.h"
+
+void edid_state::parse_vtb_ext_block(const unsigned char *x)
+{
+	printf("  Version: %u\n", x[1]);
+	if (x[1] != 1)
+		fail("Invalid version %u.\n", x[1]);
+
+	unsigned num_dtd = x[2];
+	unsigned num_cvt = x[3];
+	unsigned num_st = x[4];
+
+	x += 5;
+	if (num_dtd) {
+		printf("  Detailed Timing Descriptors:\n");
+		for (unsigned i = 0; i < num_dtd; i++, x += 18)
+			detailed_timings("    ", x, false);
+	}
+	if (num_cvt) {
+		printf("  Coordinated Video Timings:\n");
+		for (unsigned i = 0; i < num_cvt; i++, x += 3)
+			detailed_cvt_descriptor("    ", x, false);
+	}
+	if (num_st) {
+		// Note: the VTB-EXT standard has a mistake in the example EDID
+		// that it provides: there the refresh rate (bits 5-0 of the
+		// second byte) is set to 60 for 60 Hz, but this should be 0
+		// since the actual refresh rate is the value + 60.
+		//
+		// The documentation itself is correct, though.
+		printf("  Standard Timings:\n");
+		for (unsigned i = 0; i < num_st; i++, x += 2)
+			print_standard_timing("    ", x[0], x[1], true);
+	}
+}
diff --git a/test/256-blocks.test b/test/256-blocks.test
new file mode 100644
index 0000000..110b34c
--- /dev/null
+++ b/test/256-blocks.test
@@ -0,0 +1,2305 @@
+edid-decode (hex):
+
+00 ff ff ff ff ff ff 00 31 d8 34 12 00 00 00 00
+22 1a 01 04 a2 60 36 78 1f ee 91 a3 54 4c 99 26
+0f 50 54 ff ff 80 31 59 45 59 81 80 81 40 90 40
+95 00 a9 40 b3 00 08 e8 00 30 f2 70 5a 80 b0 58
+8a 00 c0 1c 32 00 00 1e 00 00 00 fd 00 18 58 0f
+87 3c 04 12 01 e0 f8 38 f0 3c 00 00 00 fc 00 30
+31 32 33 34 35 36 37 38 39 30 31 32 00 00 00 f7
+00 0a ff ff ff ff ff f0 00 00 00 00 00 00 ff d7
+
+02 03 24 f0 51 61 60 5f 5e 5d 10 1f 04 13 22 21
+20 05 14 02 11 01 23 09 07 07 e2 00 ea e6 0d 61
+81 82 6a 84 4d d0 00 a0 f0 70 3e 80 30 20 35 00
+c0 1c 32 00 00 1e 1a 36 80 a0 70 38 1f 40 30 20
+35 00 c0 1c 32 00 00 1a 1a 1d 00 80 51 d0 1c 20
+40 80 35 00 c0 1c 32 00 00 1c 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 b7
+
+70 20 5f 02 fd 20 00 10 00 00 00 01 00 01 00 00
+00 00 00 04 54 65 73 74 21 00 1d 80 3e 28 23 00
+0f 70 08 00 3c 8a 54 cc 84 99 68 42 0f 00 45 54
+00 00 00 00 00 00 00 ff 22 00 14 4f 10 09 80 ff
+0e 2f 02 27 81 57 00 6f 08 59 00 47 80 09 00 24
+00 06 12 7f 07 37 04 3b 26 00 09 02 02 01 01 00
+e0 07 00 00 3b 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
diff --git a/test/README b/test/README
new file mode 100644
index 0000000..978491b
--- /dev/null
+++ b/test/README
@@ -0,0 +1,43 @@
+This test directory contains some special test EDIDs:
+
+Three test files to check the edid-decode file parser:
+
+quantumdata.test: an EDID as generated by the QuantumData (nowadays
+	Teledyne LeCroy) software.
+
+xorg.test: an EDID as logged by xorg in /var/log/Xorg.0.log.
+
+xrandr.test: an EDID as reported by 'xrandr --props'.
+
+
+Five hand-crafted EDIDs to test rarely seen EDID extensions or data blocks:
+
+cta-vesa.test: has VESA Display Transfer Characteristics Data Block and
+	VESA Video Display Device Data Block in the CTA-861 block.
+
+ls-ext.test: has a Localized String Extension Block.
+
+blockmap-128.test: has a single Block Map extension and a total of
+	128 blocks.
+
+blockmap-255.test: has two Block Map extensions and a total of
+	255 blocks (the maximum possible EDID size when the second
+	Block Map is used).
+
+256-blocks.test: has the maximum number of 256 blocks.
+
+
+Examples of old EDID versions:
+
+edid-1.X.test: EDIDs with version 1.0, 1.1 and 1.2.
+
+
+Test EDIDs from several standards:
+
+cta-annex-a.test
+cta-annex-d.test
+vesa-edid-1.1.test
+vesa-edid-1.3.test
+vesa-edid-1.4-1.test
+vesa-edid-1.4-2.test
+vesa-edid-1.4-3.test
diff --git a/test/blockmap-128.test b/test/blockmap-128.test
new file mode 100644
index 0000000..cd57d0e
--- /dev/null
+++ b/test/blockmap-128.test
@@ -0,0 +1,1153 @@
+edid-decode (hex):
+
+00 ff ff ff ff ff ff 00 31 d8 34 12 00 00 00 00
+22 1a 01 04 a2 60 36 78 1f ee 91 a3 54 4c 99 26
+0f 50 54 ff ff 80 31 59 45 59 81 80 81 40 90 40
+95 00 a9 40 b3 00 08 e8 00 30 f2 70 5a 80 b0 58
+8a 00 c0 1c 32 00 00 1e 00 00 00 fd 00 18 58 0f
+87 3c 04 12 01 e0 f8 38 f0 3c 00 00 00 fc 00 30
+31 32 33 34 35 36 37 38 39 30 31 32 00 00 00 f7
+00 0a ff ff ff ff ff f0 00 00 00 00 00 00 7f 57
+
+f0 02 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 5e
+
+02 03 24 f1 51 61 60 5f 5e 5d 10 1f 04 13 22 21
+20 05 14 02 11 01 23 09 07 07 e2 00 ca e6 0d 61
+81 82 6a 84 4d d0 00 a0 f0 70 3e 80 30 20 35 00
+c0 1c 32 00 00 1e 1a 36 80 a0 70 38 1f 40 30 20
+35 00 c0 1c 32 00 00 1a 1a 1d 00 80 51 d0 1c 20
+40 80 35 00 c0 1c 32 00 00 1c 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 d6
+
+70 20 5f 02 7c 20 00 10 12 34 56 01 00 01 00 00
+00 00 00 04 54 65 73 74 21 00 1d 80 3e 28 23 00
+0f 70 08 00 3c 8a 54 cc 84 99 68 42 0f 00 45 54
+00 00 00 00 00 00 00 ff 22 00 14 4f 10 09 84 ff
+0e 2f 02 af 80 57 00 6f 08 59 00 07 80 09 00 24
+00 06 12 7f 07 37 04 3b 26 00 09 02 02 01 01 00
+e0 07 00 00 d5 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
diff --git a/test/blockmap-255.test b/test/blockmap-255.test
new file mode 100644
index 0000000..e42d3c3
--- /dev/null
+++ b/test/blockmap-255.test
@@ -0,0 +1,2296 @@
+edid-decode (hex):
+
+00 ff ff ff ff ff ff 00 31 d8 34 12 00 00 00 00
+22 1a 01 04 a2 60 36 78 1f ee 91 a3 54 4c 99 26
+0f 50 54 ff ff 80 31 59 45 59 81 80 81 40 90 40
+95 00 a9 40 b3 00 08 e8 00 30 f2 70 5a 80 b0 58
+8a 00 c0 1c 32 00 00 1e 00 00 00 fd 00 18 58 0f
+87 3c 04 12 01 e0 f8 38 f0 3c 00 00 00 fc 00 30
+31 32 33 34 35 36 37 38 39 30 31 32 00 00 00 f7
+00 0a ff ff ff ff ff f0 00 00 00 00 00 00 fe d8
+
+f0 02 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 5e
+
+02 03 24 f1 51 61 60 5f 5e 5d 10 1f 04 13 22 21
+20 05 14 02 11 01 23 09 07 07 e2 00 ca e6 0d 61
+81 82 6a 84 4d d0 00 a0 f0 70 3e 80 30 20 35 00
+c0 1c 32 00 00 1e 1a 36 80 a0 70 38 1f 40 30 20
+35 00 c0 1c 32 00 00 1a 1a 1d 00 80 51 d0 1c 20
+40 80 35 00 c0 1c 32 00 00 1c 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 d6
+
+70 20 5f 02 fa 20 00 10 12 34 56 01 00 01 00 00
+00 00 00 04 54 65 73 74 21 00 1d 80 3e 28 23 00
+0f 70 08 00 3c 8a 54 cc 84 99 68 42 0f 00 45 54
+00 00 00 00 00 00 00 ff 22 00 14 4f 10 09 84 ff
+0e 2f 02 af 80 57 00 6f 08 59 00 07 80 09 00 24
+00 06 12 7f 07 37 04 3b 26 00 09 02 02 01 01 00
+e0 07 00 00 57 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+f0 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70
+70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 f0
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
+
+70 20 04 00 00 23 00 01 02 b6 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90
diff --git a/test/cta-annex-a.test b/test/cta-annex-a.test
new file mode 100644
index 0000000..4159c54
--- /dev/null
+++ b/test/cta-annex-a.test
@@ -0,0 +1,17 @@
+00 ff ff ff ff ff ff 00 0c a1 00 00 00 00 00 00
+00 0c 01 03 80 50 2d 78 0a 0d c9 a0 57 47 98 27
+12 48 4c 20 00 00 01 01 01 01 01 01 01 01 01 01
+01 01 01 01 01 01 01 1d 80 18 71 1c 16 20 58 2c
+25 00 20 c2 31 00 00 9e 8c 0a d0 8a 20 e0 2d 10
+10 3e 96 00 58 c2 21 00 00 18 00 00 00 fc 00 4d
+59 20 48 44 54 56 0a 20 20 20 20 20 00 00 00 fd
+00 3b 3d 0f 2e 08 00 0a 20 20 20 20 20 20 01 c3
+
+02 01 04 00 01 1d 00 72 51 d0 1e 20 6e 28 55 00
+20 c2 31 00 00 1e 8c 0a a0 14 51 f0 16 00 26 7c
+43 00 58 c2 21 00 00 98 00 00 00 01 00 52 45 56
+31 2e 30 30 0a 00 00 00 00 00 00 00 00 ff 00 39
+39 46 43 35 30 30 30 31 0a 20 20 20 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 84
diff --git a/test/cta-annex-d.test b/test/cta-annex-d.test
new file mode 100644
index 0000000..e517bda
--- /dev/null
+++ b/test/cta-annex-d.test
@@ -0,0 +1,17 @@
+00 ff ff ff ff ff ff 00 0c a1 00 00 00 00 00 00
+00 0f 01 03 80 50 2d 78 0a 0d c9 a0 57 47 98 27
+12 48 4c 20 00 00 01 01 01 01 01 01 01 01 01 01
+01 01 01 01 01 01 01 1d 80 18 71 1c 16 20 58 2c
+25 00 20 c2 31 00 00 9e 8c 0a d0 8a 20 e0 2d 10
+10 3e 96 00 58 c2 21 00 00 18 00 00 00 fc 00 4d
+59 20 48 44 54 56 0a 20 20 20 20 20 00 00 00 fd
+00 3b 3d 0f 2e 08 00 0a 20 20 20 20 20 20 01 c0
+
+02 03 1a 71 47 85 02 03 04 06 07 01 23 09 07 07
+83 01 00 00 65 03 0c 00 10 00 01 1d 00 72 51 d0
+1e 20 6e 28 55 00 20 c2 31 00 00 1e 8c 0a a0 14
+51 f0 16 00 26 7c 43 00 58 c2 21 00 00 98 8c 0a
+d0 8a 20 e0 2d 10 10 3e 96 00 20 c2 31 00 00 18
+8c 0a a0 14 51 f0 16 00 26 7c 43 00 20 c2 31 00
+00 98 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 7a
diff --git a/test/cta-vesa.test b/test/cta-vesa.test
new file mode 100644
index 0000000..1526dc1
--- /dev/null
+++ b/test/cta-vesa.test
@@ -0,0 +1,17 @@
+00 ff ff ff ff ff ff 00 31 d8 34 12 00 00 00 00
+22 1a 01 03 80 60 36 78 1e ee 91 a3 54 4c 99 26
+0f 50 54 2f cf 00 31 59 45 59 81 80 81 40 90 40
+95 00 a9 40 b3 00 08 e8 00 30 f2 70 5a 80 b0 58
+8a 00 c0 1c 32 00 00 1e 00 00 00 fd 00 18 55 18
+87 3c 00 0a 20 20 20 20 20 20 00 00 00 fc 00 68
+64 6d 69 2d 34 6b 2d 36 30 30 0a 20 00 00 00 10
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 1d
+
+02 03 3d f0 41 61 23 09 07 07 e2 00 ea af 06 1b
+2c 34 3f 3c 60 43 4b 6c 44 82 4d 3b 42 ff 02 92
+11 03 00 00 00 0a 40 06 3c 11 0a 18 18 d0 80 83
+8f 3c 77 41 02 25 4a 7e 77 00 00 8c 57 4d d0 00
+a0 f0 70 3e 80 30 20 35 00 c0 8c 32 00 00 1e 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 78
diff --git a/test/edid-1.0.test b/test/edid-1.0.test
new file mode 100644
index 0000000..ea49217
--- /dev/null
+++ b/test/edid-1.0.test
@@ -0,0 +1,8 @@
+00 ff ff ff ff ff ff 00 34 38 c2 0b f1 01 00 00
+0f 0a 01 00 28 20 18 32 e8 7e 4e 9e 57 45 98 24
+10 47 4f a4 42 01 31 59 45 59 61 59 71 4f 81 80
+01 01 01 01 01 01 f9 15 20 f8 30 58 1f 20 20 40
+13 00 40 f0 10 00 00 1e a4 1a 20 10 31 58 24 20
+2f 55 33 00 40 f0 10 00 00 1e 30 2a 00 98 51 00
+2a 40 30 70 13 00 40 f0 10 00 00 1e ea 24 00 60
+41 00 28 30 30 60 13 00 40 f0 10 00 00 1e 00 fb
diff --git a/test/edid-1.1.test b/test/edid-1.1.test
new file mode 100644
index 0000000..b469995
--- /dev/null
+++ b/test/edid-1.1.test
@@ -0,0 +1,8 @@
+00 ff ff ff ff ff ff 00 34 ac 81 43 f9 14 00 00
+16 0a 01 01 0c 1f 17 a3 e8 67 a8 a0 56 47 99 26
+11 48 4c ff ef 80 31 59 45 59 61 59 71 4f 81 59
+81 99 a9 45 a9 4a 1a 4f 40 30 62 b0 32 40 40 c0
+13 00 38 ea 10 00 00 1e 00 00 00 fd 00 32 82 1e
+60 16 00 0a 20 20 20 20 20 20 00 00 00 fc 00 4e
+46 4e 39 37 30 35 0a 20 20 20 20 20 00 00 00 ff
+00 30 30 35 31 30 35 33 36 39 0a 20 20 20 00 6f
diff --git a/test/edid-1.2.test b/test/edid-1.2.test
new file mode 100644
index 0000000..e0d39a9
--- /dev/null
+++ b/test/edid-1.2.test
@@ -0,0 +1,8 @@
+00 ff ff ff ff ff ff 00 4c a3 46 36 00 00 00 00
+00 12 01 02 80 21 15 78 0a 87 f5 94 57 4f 8c 27
+27 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01
+01 01 01 01 01 01 e0 2e 90 c4 60 1a 0f 40 18 58
+13 00 4b cf 10 00 00 19 00 00 00 0f 00 00 00 00
+00 00 00 00 00 3c d2 02 64 00 00 00 00 fe 00 53
+41 4d 53 55 4e 47 0a 20 20 20 20 20 00 00 00 fe
+00 4c 54 4e 31 35 34 50 33 2d 4c 30 34 0a 00 e0
diff --git a/test/ls-ext.test b/test/ls-ext.test
new file mode 100644
index 0000000..ec09067
--- /dev/null
+++ b/test/ls-ext.test
@@ -0,0 +1,26 @@
+00 ff ff ff ff ff ff 00 31 d8 34 12 00 00 00 00
+22 1a 01 03 80 60 36 78 0f ee 91 a3 54 4c 99 26
+0f 50 54 2f cf 00 31 59 45 59 81 80 81 40 90 40
+95 00 a9 40 b3 00 08 e8 00 30 f2 70 5a 80 b0 58
+8a 00 c0 1c 32 00 00 1e 00 00 00 fd 00 18 55 18
+87 3c 00 0a 20 20 20 20 20 20 00 00 00 fc 00 68
+64 6d 69 2d 34 6b 2d 36 30 30 0a 20 00 00 00 10
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 2b
+
+02 03 3f f0 51 61 60 5f 5e 5d 10 1f 04 13 22 21
+20 05 14 02 11 01 23 09 07 07 83 01 00 00 6d 03
+0c 00 10 00 00 3c 21 00 60 01 02 03 67 d8 5d c4
+01 78 00 00 e2 00 ea e3 05 00 00 e3 06 01 00 4d
+d0 00 a0 f0 70 3e 80 30 20 35 00 c0 1c 32 00 00
+1e 1a 36 80 a0 70 38 1f 40 30 20 35 00 c0 1c 32
+00 00 1a 1a 1d 00 80 51 d0 1c 20 40 80 35 00 c0
+1c 32 00 00 1c 00 00 00 00 00 00 00 00 00 00 63
+
+50 01 00 30 00 22 00 02 10 39 84 09 46 61 62 72
+69 6b 61 6e 74 05 4d 6f 64 65 6c 0b 53 65 72 69
+65 6e 75 6d 6d 65 72 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 66
diff --git a/test/quantumdata.test b/test/quantumdata.test
new file mode 100644
index 0000000..a2e158e
--- /dev/null
+++ b/test/quantumdata.test
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+<DATAOBJ>

+    <HEADER TYPE="DID" VERSION="1.0"/>

+    <DATA>

+        <BLOCK0>00FFFFFFFFFFFF0031D8341200000000221A0103806036780FEE91A3544C99260F50542FCF00315945598180814090409500A940B30008E80030F2705A80B0588A00C01C3200001E000000FD00185518873C000A202020202020000000FC0068646D692D346B2D3630300A20000000100000000000000000000000000000012C</BLOCK0>

+        <BLOCK1>02033FF05161605F5E5D101F0413222120051402110123090707830100006D030C001000003C21006001020367D85DC401780000E200EAE3050000E30601004DD000A0F0703E8030203500C01C3200001E1A3680A070381F4030203500C01C3200001A1A1D008051D01C2040803500C01C3200001C0000000000000000000063</BLOCK1>

+    </DATA>

+</DATAOBJ>

diff --git a/test/vesa-edid-1.1.test b/test/vesa-edid-1.1.test
new file mode 100644
index 0000000..f90109d
--- /dev/null
+++ b/test/vesa-edid-1.1.test
@@ -0,0 +1,8 @@
+00 ff ff ff ff ff ff 00 24 4d 8e 19 00 00 00 00
+0a 05 01 01 08 28 1e b4 c8 00 b2 a0 57 49 9b 26
+10 48 4f a4 cf 7c 31 4a a9 40 a9 4a a9 4f 81 80
+01 01 01 01 01 01 10 0b d0 b4 20 5e 63 10 12 6c
+62 08 fa b8 00 00 00 1a 00 00 00 ff 00 33 30 39
+41 42 43 30 30 30 32 35 0a 20 00 00 00 fe 00 54
+48 49 53 20 49 53 20 41 0a 20 20 20 00 00 00 fe
+00 54 45 53 54 2c 20 54 48 45 20 45 4e 44 00 8f
diff --git a/test/vesa-edid-1.3.test b/test/vesa-edid-1.3.test
new file mode 100644
index 0000000..c114dbb
--- /dev/null
+++ b/test/vesa-edid-1.3.test
@@ -0,0 +1,9 @@
+00 ff ff ff ff ff ff 00 10 ac ab 50 00 00 00 00
+2a 09 01 03 0e 26 1d 96 ef ee 91 a3 54 4c 99 26
+0f 50 54 a5 43 00 a9 4f a9 59 71 59 61 59 45 59
+31 59 c2 8f 01 01 86 3d 00 c0 51 00 30 40 40 a0
+13 00 7c 22 11 00 00 1e 00 00 00 ff 00 35 35 33
+34 37 42 4f 4e 5a 48 34 37 0a 00 00 00 fc 00 44
+45 4c 4c 20 55 52 31 31 31 0a 20 20 00 00 00 fd
+00 30 a0 1e 79 1c 02 00 28 50 10 0e 80 46 00 8d
+
diff --git a/test/vesa-edid-1.4-1.test b/test/vesa-edid-1.4-1.test
new file mode 100644
index 0000000..e30915f
--- /dev/null
+++ b/test/vesa-edid-1.4-1.test
@@ -0,0 +1,8 @@
+00 ff ff ff ff ff ff 00 04 43 06 f2 01 00 00 00
+01 11 01 04 0f 2b 20 78 2b 9c 68 a0 57 4a 9b 26
+12 48 4c ff ff 80 a9 59 a9 4f a9 4a a9 45 81 99
+81 80 61 59 45 59 48 3f 40 30 62 b0 32 40 40 c0
+13 00 ab 40 11 00 00 1e 00 00 00 fd 00 32 5a 1e
+6e 17 04 11 00 c8 90 00 50 3c 00 00 00 f7 00 0a
+f7 0f 03 87 c0 00 00 00 00 00 00 00 00 00 00 fc
+00 41 42 43 20 4c 43 44 32 31 0a 20 20 20 00 9a
diff --git a/test/vesa-edid-1.4-2.test b/test/vesa-edid-1.4-2.test
new file mode 100644
index 0000000..b4b7d36
--- /dev/null
+++ b/test/vesa-edid-1.4-2.test
@@ -0,0 +1,17 @@
+00 ff ff ff ff ff ff 00 04 43 07 f2 01 00 00 00
+ff 11 01 04 a2 4f 00 78 1e ee 91 a3 54 4c 99 26
+0f 50 54 20 00 00 01 01 01 01 01 01 01 01 01 01
+01 01 01 01 01 01 02 3a 80 18 71 38 2d 40 58 2c
+04 05 0f 48 42 00 00 1e 01 1d 80 18 71 1c 16 20
+58 2c 25 00 0f 48 42 00 00 9e 01 1d 00 72 51 d0
+1e 20 6e 28 55 00 0f 48 42 00 00 1e 00 00 00 fc
+00 41 42 43 20 4c 43 44 34 37 77 0a 20 20 01 cb
+
+02 03 1a 72 47 90 85 04 03 02 07 06 23 09 07 07
+83 01 00 00 65 03 0c 00 10 00 8e 0a d0 8a 20 e0
+2d 10 10 3e 96 00 1f 09 00 00 00 18 8e 0a d0 8a
+20 e0 2d 10 10 3e 96 00 04 03 00 00 00 18 8e 0a
+a0 14 51 f0 16 00 26 7c 43 00 1f 09 00 00 00 98
+8e 0a a0 14 51 f0 16 00 26 7c 43 00 04 03 00 00
+00 98 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c7
diff --git a/test/vesa-edid-1.4-3.test b/test/vesa-edid-1.4-3.test
new file mode 100644
index 0000000..4c813ba
--- /dev/null
+++ b/test/vesa-edid-1.4-3.test
@@ -0,0 +1,17 @@
+00 ff ff ff ff ff ff 00 04 43 08 f2 01 00 00 00
+10 11 01 04 a2 79 44 78 1e ee 91 a3 54 4c 99 26
+0f 50 54 ff ef 80 81 99 81 80 81 59 81 40 61 59
+4b c0 45 59 31 59 66 21 50 b0 51 00 1b 30 40 70
+36 00 be ab 42 00 00 1e 01 1d 00 72 51 d0 1e 20
+6e 28 55 00 be ab 42 00 00 1e 00 00 00 f7 00 0a
+f7 0f 03 87 c0 00 00 00 00 00 00 00 00 00 00 fc
+00 41 42 43 20 50 4c 41 35 35 0a 20 20 20 01 0a
+
+02 03 19 f0 46 05 04 03 02 07 06 23 09 07 07 83
+01 00 00 65 03 0c 00 10 00 01 1d 80 18 71 1c 16
+20 58 2c 25 00 0f 48 42 00 00 9e 01 1d 00 72 51
+d0 1e 20 6e 28 55 00 0f 48 42 00 00 1e 8c 0a d0
+8a 20 e0 2d 10 10 3e 96 00 b9 88 21 00 00 18 8e
+0a a0 14 51 f0 16 00 26 7c 43 00 b9 88 21 00 00
+98 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 58
diff --git a/test/xorg.test b/test/xorg.test
new file mode 100644
index 0000000..093f500
--- /dev/null
+++ b/test/xorg.test
@@ -0,0 +1,1574 @@
+[     4.295] (--) Log file renamed from "/var/log/Xorg.pid-762.log" to "/var/log/Xorg.0.log"
+[     4.296] 
+X.Org X Server 1.20.4
+X Protocol Version 11, Revision 0
+[     4.296] Build Operating System: Linux 4.9.0-8-amd64 x86_64 Debian
+[     4.296] Current Operating System: Linux octomore 5.4.0-rc8-octomore #23 SMP PREEMPT Sat Nov 23 16:00:49 CET 2019 x86_64
+[     4.296] Kernel command line: BOOT_IMAGE=/boot/vmlinuz-5.4.0-rc8-octomore root=UUID=e227131b-ee41-479a-a25e-bce91b18a6ed ro
+[     4.296] Build Date: 05 March 2019  08:11:12PM
+[     4.296] xorg-server 2:1.20.4-1 (https://www.debian.org/support) 
+[     4.296] Current version of pixman: 0.36.0
+[     4.296] 	Before reporting problems, check http://wiki.x.org
+	to make sure that you have the latest version.
+[     4.296] Markers: (--) probed, (**) from config file, (==) default setting,
+	(++) from command line, (!!) notice, (II) informational,
+	(WW) warning, (EE) error, (NI) not implemented, (??) unknown.
+[     4.296] (==) Log file: "/var/log/Xorg.0.log", Time: Tue Nov 26 16:25:38 2019
+[     4.297] (==) Using system config directory "/usr/share/X11/xorg.conf.d"
+[     4.298] (==) No Layout section.  Using the first Screen section.
+[     4.298] (==) No screen section available. Using defaults.
+[     4.298] (**) |-->Screen "Default Screen Section" (0)
+[     4.298] (**) |   |-->Monitor "<default monitor>"
+[     4.298] (==) No monitor specified for screen "Default Screen Section".
+	Using a default monitor configuration.
+[     4.298] (==) Automatically adding devices
+[     4.298] (==) Automatically enabling devices
+[     4.298] (==) Automatically adding GPU devices
+[     4.298] (==) Max clients allowed: 256, resource mask: 0x1fffff
+[     4.299] (WW) The directory "/usr/share/fonts/X11/cyrillic" does not exist.
+[     4.299] 	Entry deleted from font path.
+[     4.301] (==) FontPath set to:
+	/usr/share/fonts/X11/misc,
+	/usr/share/fonts/X11/100dpi/:unscaled,
+	/usr/share/fonts/X11/75dpi/:unscaled,
+	/usr/share/fonts/X11/Type1,
+	/usr/share/fonts/X11/100dpi,
+	/usr/share/fonts/X11/75dpi,
+	built-ins
+[     4.301] (==) ModulePath set to "/usr/lib/xorg/modules"
+[     4.301] (II) The server relies on udev to provide the list of input devices.
+	If no devices become available, reconfigure udev or disable AutoAddDevices.
+[     4.301] (II) Loader magic: 0x55a9db113e20
+[     4.301] (II) Module ABI versions:
+[     4.301] 	X.Org ANSI C Emulation: 0.4
+[     4.301] 	X.Org Video Driver: 24.0
+[     4.301] 	X.Org XInput driver : 24.1
+[     4.301] 	X.Org Server Extension : 10.0
+[     4.301] (++) using VT number 7
+
+[     4.301] (II) systemd-logind: logind integration requires -keeptty and -keeptty was not provided, disabling logind integration
+[     4.302] (II) xfree86: Adding drm device (/dev/dri/card1)
+[     4.316] (II) xfree86: Adding drm device (/dev/dri/card0)
+[     4.318] (--) PCI:*(0@0:2:0) 8086:5917:17aa:225c rev 7, Mem @ 0x2ffa000000/16777216, 0x2fa0000000/268435456, I/O @ 0x0000e000/64, BIOS @ 0x????????/131072
+[     4.318] (II) LoadModule: "glx"
+[     4.319] (II) Loading /usr/lib/xorg/modules/extensions/libglx.so
+[     4.325] (II) Module glx: vendor="X.Org Foundation"
+[     4.325] 	compiled for 1.20.4, module version = 1.0.0
+[     4.325] 	ABI class: X.Org Server Extension, version 10.0
+[     4.325] (==) Matched modesetting as autoconfigured driver 0
+[     4.325] (==) Matched fbdev as autoconfigured driver 1
+[     4.325] (==) Matched vesa as autoconfigured driver 2
+[     4.325] (==) Assigned the driver to the xf86ConfigLayout
+[     4.325] (II) LoadModule: "modesetting"
+[     4.325] (II) Loading /usr/lib/xorg/modules/drivers/modesetting_drv.so
+[     4.326] (II) Module modesetting: vendor="X.Org Foundation"
+[     4.326] 	compiled for 1.20.4, module version = 1.20.4
+[     4.326] 	Module class: X.Org Video Driver
+[     4.326] 	ABI class: X.Org Video Driver, version 24.0
+[     4.326] (II) LoadModule: "fbdev"
+[     4.326] (II) Loading /usr/lib/xorg/modules/drivers/fbdev_drv.so
+[     4.327] (II) Module fbdev: vendor="X.Org Foundation"
+[     4.327] 	compiled for 1.20.0, module version = 0.5.0
+[     4.327] 	Module class: X.Org Video Driver
+[     4.327] 	ABI class: X.Org Video Driver, version 24.0
+[     4.327] (II) LoadModule: "vesa"
+[     4.327] (II) Loading /usr/lib/xorg/modules/drivers/vesa_drv.so
+[     4.327] (II) Module vesa: vendor="X.Org Foundation"
+[     4.327] 	compiled for 1.20.4, module version = 2.4.0
+[     4.327] 	Module class: X.Org Video Driver
+[     4.327] 	ABI class: X.Org Video Driver, version 24.0
+[     4.327] (II) modesetting: Driver for Modesetting Kernel Drivers: kms
+[     4.327] (II) FBDEV: driver for framebuffer: fbdev
+[     4.327] (II) VESA: driver for VESA chipsets: vesa
+[     4.350] (II) modeset(0): using drv /dev/dri/card1
+[     4.350] (WW) Falling back to old probe method for fbdev
+[     4.350] (II) Loading sub module "fbdevhw"
+[     4.350] (II) LoadModule: "fbdevhw"
+[     4.350] (II) Loading /usr/lib/xorg/modules/libfbdevhw.so
+[     4.350] (II) Module fbdevhw: vendor="X.Org Foundation"
+[     4.350] 	compiled for 1.20.4, module version = 0.0.2
+[     4.350] 	ABI class: X.Org Video Driver, version 24.0
+[     4.350] (II) modeset(0): Creating default Display subsection in Screen section
+	"Default Screen Section" for depth/fbbpp 24/32
+[     4.350] (==) modeset(0): Depth 24, (==) framebuffer bpp 32
+[     4.350] (==) modeset(0): RGB weight 888
+[     4.350] (==) modeset(0): Default visual is TrueColor
+[     4.350] (II) Loading sub module "glamoregl"
+[     4.350] (II) LoadModule: "glamoregl"
+[     4.350] (II) Loading /usr/lib/xorg/modules/libglamoregl.so
+[     4.356] (II) Module glamoregl: vendor="X.Org Foundation"
+[     4.356] 	compiled for 1.20.4, module version = 1.0.1
+[     4.356] 	ABI class: X.Org ANSI C Emulation, version 0.4
+[     4.395] (II) modeset(0): glamor X acceleration enabled on Mesa DRI Intel(R) UHD Graphics 620 (Kabylake GT2) 
+[     4.395] (II) modeset(0): glamor initialized
+[     4.396] (II) modeset(0): Output eDP-1 has no monitor section
+[     4.396] (II) modeset(0): Output DP-1 has no monitor section
+[     4.404] (II) modeset(0): Output HDMI-1 has no monitor section
+[     4.404] (II) modeset(0): Output DP-2 has no monitor section
+[     4.513] (II) modeset(0): Output HDMI-2 has no monitor section
+[     4.514] (II) modeset(0): EDID for output eDP-1
+[     4.514] (II) modeset(0): Manufacturer: AUO  Model: 313d  Serial#: 0
+[     4.514] (II) modeset(0): Year: 2016  Week: 0
+[     4.514] (II) modeset(0): EDID Version: 1.4
+[     4.514] (II) modeset(0): Digital Display Input
+[     4.514] (II) modeset(0): 8 bits per channel
+[     4.514] (II) modeset(0): Digital interface is DisplayPort
+[     4.514] (II) modeset(0): Max Image Size [cm]: horiz.: 31  vert.: 17
+[     4.514] (II) modeset(0): Gamma: 2.20
+[     4.514] (II) modeset(0): No DPMS capabilities specified
+[     4.514] (II) modeset(0): Supported color encodings: RGB 4:4:4 
+[     4.514] (II) modeset(0): First detailed timing is preferred mode
+[     4.514] (II) modeset(0): Preferred mode is native pixel format and refresh rate
+[     4.514] (II) modeset(0): redX: 0.631 redY: 0.336   greenX: 0.323 greenY: 0.614
+[     4.514] (II) modeset(0): blueX: 0.156 blueY: 0.040   whiteX: 0.313 whiteY: 0.329
+[     4.514] (II) modeset(0): Manufacturer's mask: 0
+[     4.514] (II) modeset(0): Supported detailed timing:
+[     4.514] (II) modeset(0): clock: 141.0 MHz   Image Size:  309 x 174 mm
+[     4.514] (II) modeset(0): h_active: 1920  h_sync: 1936  h_sync_end 1952 h_blank_end 2104 h_border: 0
+[     4.514] (II) modeset(0): v_active: 1080  v_sync: 1083  v_sync_end 1097 v_blanking: 1116 v_border: 0
+[     4.514] (II) modeset(0): Unknown vendor-specific block f
+[     4.514] (II) modeset(0):  AUO
+[     4.514] (II) modeset(0):  B140HAN03.1
+[     4.514] (II) modeset(0): EDID (in hex):
+[     4.514] (II) modeset(0): 	00ffffffffffff0006af3d3100000000
+[     4.514] (II) modeset(0): 	001a0104a51f1178028d15a156529d28
+[     4.514] (II) modeset(0): 	0a505400000001010101010101010101
+[     4.514] (II) modeset(0): 	010101010101143780b8703824401010
+[     4.514] (II) modeset(0): 	3e0035ae100000180000000f00000000
+[     4.514] (II) modeset(0): 	00000000000000000020000000fe0041
+[     4.514] (II) modeset(0): 	554f0a202020202020202020000000fe
+[     4.514] (II) modeset(0): 	004231343048414e30332e31200a003b
+[     4.514] (II) modeset(0): Printing probed modes for output eDP-1
+[     4.514] (II) modeset(0): Modeline "1920x1080"x60.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[     4.514] (II) modeset(0): Modeline "1920x1080"x120.0  356.38  1920 2080 2288 2656  1080 1081 1084 1118 doublescan -hsync +vsync (134.2 kHz d)
+[     4.514] (II) modeset(0): Modeline "1920x1080"x119.9  266.50  1920 1944 1960 2000  1080 1081 1084 1111 doublescan +hsync -vsync (133.2 kHz d)
+[     4.514] (II) modeset(0): Modeline "1920x1080"x60.0  173.00  1920 2048 2248 2576  1080 1083 1088 1120 -hsync +vsync (67.2 kHz d)
+[     4.514] (II) modeset(0): Modeline "1920x1080"x59.9  138.50  1920 1968 2000 2080  1080 1083 1088 1111 +hsync -vsync (66.6 kHz d)
+[     4.514] (II) modeset(0): Modeline "1680x1050"x60.0  146.25  1680 1784 1960 2240  1050 1053 1059 1089 -hsync +vsync (65.3 kHz d)
+[     4.514] (II) modeset(0): Modeline "1680x1050"x59.9  119.00  1680 1728 1760 1840  1050 1053 1059 1080 +hsync -vsync (64.7 kHz d)
+[     4.514] (II) modeset(0): Modeline "1600x1024"x60.2  103.12  1600 1600 1656 1664  1024 1024 1029 1030 +hsync +vsync (62.0 kHz d)
+[     4.514] (II) modeset(0): Modeline "1400x1050"x60.0  122.00  1400 1488 1640 1880  1050 1052 1064 1082 +hsync +vsync (64.9 kHz d)
+[     4.514] (II) modeset(0): Modeline "1600x900"x120.0  246.00  1600 1728 1900 2200  900 901 904 932 doublescan -hsync +vsync (111.8 kHz d)
+[     4.514] (II) modeset(0): Modeline "1600x900"x119.9  186.50  1600 1624 1640 1680  900 901 904 926 doublescan +hsync -vsync (111.0 kHz d)
+[     4.514] (II) modeset(0): Modeline "1600x900"x59.9  118.25  1600 1696 1856 2112  900 903 908 934 -hsync +vsync (56.0 kHz d)
+[     4.514] (II) modeset(0): Modeline "1600x900"x59.8   97.50  1600 1648 1680 1760  900 903 908 926 +hsync -vsync (55.4 kHz d)
+[     4.514] (II) modeset(0): Modeline "1280x1024"x60.0  108.00  1280 1328 1440 1688  1024 1025 1028 1066 +hsync +vsync (64.0 kHz d)
+[     4.514] (II) modeset(0): Modeline "1440x900"x59.9  106.50  1440 1520 1672 1904  900 903 909 934 -hsync +vsync (55.9 kHz d)
+[     4.514] (II) modeset(0): Modeline "1400x900"x60.0  103.50  1400 1480 1624 1848  900 903 913 934 -hsync +vsync (56.0 kHz d)
+[     4.514] (II) modeset(0): Modeline "1400x900"x59.9   86.50  1400 1448 1480 1560  900 903 913 926 +hsync -vsync (55.4 kHz d)
+[     4.514] (II) modeset(0): Modeline "1280x960"x60.0  108.00  1280 1376 1488 1800  960 961 964 1000 +hsync +vsync (60.0 kHz d)
+[     4.514] (II) modeset(0): Modeline "1440x810"x120.0  198.12  1440 1548 1704 1968  810 811 814 839 doublescan -hsync +vsync (100.7 kHz d)
+[     4.514] (II) modeset(0): Modeline "1440x810"x119.9  151.88  1440 1464 1480 1520  810 811 814 833 doublescan +hsync -vsync (99.9 kHz d)
+[     4.514] (II) modeset(0): Modeline "1368x768"x59.9   85.25  1368 1440 1576 1784  768 771 781 798 -hsync +vsync (47.8 kHz d)
+[     4.514] (II) modeset(0): Modeline "1368x768"x59.9   72.25  1368 1416 1448 1528  768 771 781 790 +hsync -vsync (47.3 kHz d)
+[     4.514] (II) modeset(0): Modeline "1360x768"x59.8   84.75  1360 1432 1568 1776  768 771 781 798 -hsync +vsync (47.7 kHz d)
+[     4.514] (II) modeset(0): Modeline "1360x768"x60.0   72.00  1360 1408 1440 1520  768 771 781 790 +hsync -vsync (47.4 kHz d)
+[     4.514] (II) modeset(0): Modeline "1280x800"x120.0  174.25  1280 1380 1516 1752  800 801 804 829 doublescan -hsync +vsync (99.5 kHz d)
+[     4.514] (II) modeset(0): Modeline "1280x800"x119.9  134.25  1280 1304 1320 1360  800 801 804 823 doublescan +hsync -vsync (98.7 kHz d)
+[     4.514] (II) modeset(0): Modeline "1280x800"x59.8   83.50  1280 1352 1480 1680  800 803 809 831 -hsync +vsync (49.7 kHz d)
+[     4.514] (II) modeset(0): Modeline "1280x800"x59.9   71.00  1280 1328 1360 1440  800 803 809 823 +hsync -vsync (49.3 kHz d)
+[     4.514] (II) modeset(0): Modeline "1152x864"x60.0   81.62  1152 1216 1336 1520  864 865 868 895 -hsync +vsync (53.7 kHz d)
+[     4.514] (II) modeset(0): Modeline "1280x720"x120.0  156.12  1280 1376 1512 1744  720 721 724 746 doublescan -hsync +vsync (89.5 kHz d)
+[     4.514] (II) modeset(0): Modeline "1280x720"x120.0  120.75  1280 1304 1320 1360  720 721 724 740 doublescan +hsync -vsync (88.8 kHz d)
+[     4.514] (II) modeset(0): Modeline "1280x720"x59.9   74.50  1280 1344 1472 1664  720 723 728 748 -hsync +vsync (44.8 kHz d)
+[     4.514] (II) modeset(0): Modeline "1280x720"x59.7   63.75  1280 1328 1360 1440  720 723 728 741 +hsync -vsync (44.3 kHz d)
+[     4.514] (II) modeset(0): Modeline "1024x768"x120.1  133.47  1024 1100 1212 1400  768 768 770 794 doublescan -hsync +vsync (95.3 kHz d)
+[     4.514] (II) modeset(0): Modeline "1024x768"x60.0   65.00  1024 1048 1184 1344  768 771 777 806 -hsync -vsync (48.4 kHz d)
+[     4.514] (II) modeset(0): Modeline "960x720"x120.0  117.00  960 1024 1128 1300  720 720 722 750 doublescan -hsync +vsync (90.0 kHz d)
+[     4.514] (II) modeset(0): Modeline "928x696"x120.1  109.15  928 976 1088 1264  696 696 698 719 doublescan -hsync +vsync (86.4 kHz d)
+[     4.514] (II) modeset(0): Modeline "896x672"x120.0  102.40  896 960 1060 1224  672 672 674 697 doublescan -hsync +vsync (83.7 kHz d)
+[     4.514] (II) modeset(0): Modeline "1024x576"x119.9   98.50  1024 1092 1200 1376  576 577 580 597 doublescan -hsync +vsync (71.6 kHz d)
+[     4.514] (II) modeset(0): Modeline "1024x576"x119.9   78.38  1024 1048 1064 1104  576 577 580 592 doublescan +hsync -vsync (71.0 kHz d)
+[     4.514] (II) modeset(0): Modeline "1024x576"x59.9   46.50  1024 1064 1160 1296  576 579 584 599 -hsync +vsync (35.9 kHz d)
+[     4.514] (II) modeset(0): Modeline "1024x576"x59.8   42.00  1024 1072 1104 1184  576 579 584 593 +hsync -vsync (35.5 kHz d)
+[     4.514] (II) modeset(0): Modeline "960x600"x119.9   96.62  960 1028 1128 1296  600 601 604 622 doublescan -hsync +vsync (74.6 kHz d)
+[     4.514] (II) modeset(0): Modeline "960x600"x120.0   77.00  960 984 1000 1040  600 601 604 617 doublescan +hsync -vsync (74.0 kHz d)
+[     4.514] (II) modeset(0): Modeline "960x540"x119.9   86.50  960 1024 1124 1288  540 541 544 560 doublescan -hsync +vsync (67.2 kHz d)
+[     4.514] (II) modeset(0): Modeline "960x540"x120.0   69.25  960 984 1000 1040  540 541 544 555 doublescan +hsync -vsync (66.6 kHz d)
+[     4.514] (II) modeset(0): Modeline "960x540"x59.6   40.75  960 992 1088 1216  540 543 548 562 -hsync +vsync (33.5 kHz d)
+[     4.514] (II) modeset(0): Modeline "960x540"x59.8   37.25  960 1008 1040 1120  540 543 548 556 +hsync -vsync (33.3 kHz d)
+[     4.514] (II) modeset(0): Modeline "800x600"x120.0   81.00  800 832 928 1080  600 600 602 625 doublescan +hsync +vsync (75.0 kHz d)
+[     4.514] (II) modeset(0): Modeline "800x600"x60.3   40.00  800 840 968 1056  600 601 605 628 +hsync +vsync (37.9 kHz d)
+[     4.514] (II) modeset(0): Modeline "800x600"x56.2   36.00  800 824 896 1024  600 601 603 625 +hsync +vsync (35.2 kHz d)
+[     4.514] (II) modeset(0): Modeline "840x525"x120.0   73.12  840 892 980 1120  525 526 529 544 doublescan -hsync +vsync (65.3 kHz d)
+[     4.514] (II) modeset(0): Modeline "840x525"x119.8   59.50  840 864 880 920  525 526 529 540 doublescan +hsync -vsync (64.7 kHz d)
+[     4.514] (II) modeset(0): Modeline "864x486"x59.9   32.50  864 888 968 1072  486 489 494 506 -hsync +vsync (30.3 kHz d)
+[     4.514] (II) modeset(0): Modeline "864x486"x59.6   30.50  864 912 944 1024  486 489 494 500 +hsync -vsync (29.8 kHz d)
+[     4.514] (II) modeset(0): Modeline "800x512"x120.3   51.56  800 800 828 832  512 512 514 515 doublescan +hsync +vsync (62.0 kHz d)
+[     4.514] (II) modeset(0): Modeline "700x525"x120.0   61.00  700 744 820 940  525 526 532 541 doublescan +hsync +vsync (64.9 kHz d)
+[     4.514] (II) modeset(0): Modeline "800x450"x119.9   59.12  800 848 928 1056  450 451 454 467 doublescan -hsync +vsync (56.0 kHz d)
+[     4.514] (II) modeset(0): Modeline "800x450"x119.6   48.75  800 824 840 880  450 451 454 463 doublescan +hsync -vsync (55.4 kHz d)
+[     4.514] (II) modeset(0): Modeline "640x512"x120.0   54.00  640 664 720 844  512 512 514 533 doublescan +hsync +vsync (64.0 kHz d)
+[     4.514] (II) modeset(0): Modeline "720x450"x119.8   53.25  720 760 836 952  450 451 454 467 doublescan -hsync +vsync (55.9 kHz d)
+[     4.514] (II) modeset(0): Modeline "700x450"x119.9   51.75  700 740 812 924  450 451 456 467 doublescan -hsync +vsync (56.0 kHz d)
+[     4.514] (II) modeset(0): Modeline "700x450"x119.8   43.25  700 724 740 780  450 451 456 463 doublescan +hsync -vsync (55.4 kHz d)
+[     4.514] (II) modeset(0): Modeline "640x480"x120.0   54.00  640 688 744 900  480 480 482 500 doublescan +hsync +vsync (60.0 kHz d)
+[     4.514] (II) modeset(0): Modeline "640x480"x59.9   25.18  640 656 752 800  480 490 492 525 -hsync -vsync (31.5 kHz d)
+[     4.514] (II) modeset(0): Modeline "720x405"x59.5   22.50  720 744 808 896  405 408 413 422 -hsync +vsync (25.1 kHz d)
+[     4.514] (II) modeset(0): Modeline "720x405"x59.0   21.75  720 768 800 880  405 408 413 419 +hsync -vsync (24.7 kHz d)
+[     4.514] (II) modeset(0): Modeline "684x384"x119.8   42.62  684 720 788 892  384 385 390 399 doublescan -hsync +vsync (47.8 kHz d)
+[     4.514] (II) modeset(0): Modeline "684x384"x119.7   36.12  684 708 724 764  384 385 390 395 doublescan +hsync -vsync (47.3 kHz d)
+[     4.514] (II) modeset(0): Modeline "680x384"x119.6   42.38  680 716 784 888  384 385 390 399 doublescan -hsync +vsync (47.7 kHz d)
+[     4.514] (II) modeset(0): Modeline "680x384"x119.9   36.00  680 704 720 760  384 385 390 395 doublescan +hsync -vsync (47.4 kHz d)
+[     4.514] (II) modeset(0): Modeline "640x400"x119.8   41.75  640 676 740 840  400 401 404 415 doublescan -hsync +vsync (49.7 kHz d)
+[     4.514] (II) modeset(0): Modeline "640x400"x120.0   35.50  640 664 680 720  400 401 404 411 doublescan +hsync -vsync (49.3 kHz d)
+[     4.514] (II) modeset(0): Modeline "576x432"x120.1   40.81  576 608 668 760  432 432 434 447 doublescan -hsync +vsync (53.7 kHz d)
+[     4.514] (II) modeset(0): Modeline "640x360"x119.7   37.25  640 672 736 832  360 361 364 374 doublescan -hsync +vsync (44.8 kHz d)
+[     4.514] (II) modeset(0): Modeline "640x360"x119.7   31.88  640 664 680 720  360 361 364 370 doublescan +hsync -vsync (44.3 kHz d)
+[     4.514] (II) modeset(0): Modeline "640x360"x59.8   18.00  640 664 720 800  360 363 368 376 -hsync +vsync (22.5 kHz d)
+[     4.514] (II) modeset(0): Modeline "640x360"x59.3   17.75  640 688 720 800  360 363 368 374 +hsync -vsync (22.2 kHz d)
+[     4.514] (II) modeset(0): Modeline "512x384"x120.0   32.50  512 524 592 672  384 385 388 403 doublescan -hsync -vsync (48.4 kHz d)
+[     4.514] (II) modeset(0): Modeline "512x288"x120.0   23.25  512 532 580 648  288 289 292 299 doublescan -hsync +vsync (35.9 kHz d)
+[     4.514] (II) modeset(0): Modeline "512x288"x119.8   21.00  512 536 552 592  288 289 292 296 doublescan +hsync -vsync (35.5 kHz d)
+[     4.514] (II) modeset(0): Modeline "480x270"x119.3   20.38  480 496 544 608  270 271 274 281 doublescan -hsync +vsync (33.5 kHz d)
+[     4.514] (II) modeset(0): Modeline "480x270"x119.6   18.62  480 504 520 560  270 271 274 278 doublescan +hsync -vsync (33.3 kHz d)
+[     4.514] (II) modeset(0): Modeline "400x300"x120.6   20.00  400 420 484 528  300 300 302 314 doublescan +hsync +vsync (37.9 kHz d)
+[     4.515] (II) modeset(0): Modeline "400x300"x112.7   18.00  400 412 448 512  300 300 301 312 doublescan +hsync +vsync (35.2 kHz d)
+[     4.515] (II) modeset(0): Modeline "432x243"x119.8   16.25  432 444 484 536  243 244 247 253 doublescan -hsync +vsync (30.3 kHz d)
+[     4.515] (II) modeset(0): Modeline "432x243"x119.1   15.25  432 456 472 512  243 244 247 250 doublescan +hsync -vsync (29.8 kHz d)
+[     4.515] (II) modeset(0): Modeline "320x240"x120.1   12.59  320 328 376 400  240 245 246 262 doublescan -hsync -vsync (31.5 kHz d)
+[     4.515] (II) modeset(0): Modeline "360x202"x119.0   11.25  360 372 404 448  202 204 206 211 doublescan -hsync +vsync (25.1 kHz d)
+[     4.515] (II) modeset(0): Modeline "360x202"x118.3   10.88  360 384 400 440  202 204 206 209 doublescan +hsync -vsync (24.7 kHz d)
+[     4.515] (II) modeset(0): Modeline "320x180"x119.7    9.00  320 332 360 400  180 181 184 188 doublescan -hsync +vsync (22.5 kHz d)
+[     4.515] (II) modeset(0): Modeline "320x180"x118.6    8.88  320 344 360 400  180 181 184 187 doublescan +hsync -vsync (22.2 kHz d)
+[     4.515] (II) modeset(0): EDID for output DP-1
+[     4.531] (II) modeset(0): EDID for output HDMI-1
+[     4.531] (II) modeset(0): EDID for output DP-2
+[     4.640] (II) modeset(0): EDID for output HDMI-2
+[     4.640] (II) modeset(0): Output eDP-1 connected
+[     4.640] (II) modeset(0): Output DP-1 disconnected
+[     4.640] (II) modeset(0): Output HDMI-1 disconnected
+[     4.640] (II) modeset(0): Output DP-2 disconnected
+[     4.640] (II) modeset(0): Output HDMI-2 disconnected
+[     4.640] (II) modeset(0): Using exact sizes for initial modes
+[     4.640] (II) modeset(0): Output eDP-1 using initial mode 1920x1080 +0+0
+[     4.641] (==) modeset(0): Using gamma correction (1.0, 1.0, 1.0)
+[     4.641] (==) modeset(0): DPI set to (96, 96)
+[     4.641] (II) Loading sub module "fb"
+[     4.641] (II) LoadModule: "fb"
+[     4.641] (II) Loading /usr/lib/xorg/modules/libfb.so
+[     4.642] (II) Module fb: vendor="X.Org Foundation"
+[     4.642] 	compiled for 1.20.4, module version = 1.0.0
+[     4.642] 	ABI class: X.Org ANSI C Emulation, version 0.4
+[     4.642] (II) UnloadModule: "fbdev"
+[     4.642] (II) Unloading fbdev
+[     4.642] (II) UnloadSubModule: "fbdevhw"
+[     4.642] (II) Unloading fbdevhw
+[     4.642] (II) UnloadModule: "vesa"
+[     4.642] (II) Unloading vesa
+[     4.651] (==) modeset(0): Backing store enabled
+[     4.651] (==) modeset(0): Silken mouse enabled
+[     4.716] (II) modeset(0): Initializing kms color map for depth 24, 8 bpc.
+[     4.716] (==) modeset(0): DPMS enabled
+[     4.717] (II) modeset(0): [DRI2] Setup complete
+[     4.717] (II) modeset(0): [DRI2]   DRI driver: i965
+[     4.717] (II) modeset(0): [DRI2]   VDPAU driver: i965
+[     4.717] (II) Initializing extension Generic Event Extension
+[     4.717] (II) Initializing extension SHAPE
+[     4.717] (II) Initializing extension MIT-SHM
+[     4.717] (II) Initializing extension XInputExtension
+[     4.718] (II) Initializing extension XTEST
+[     4.718] (II) Initializing extension BIG-REQUESTS
+[     4.718] (II) Initializing extension SYNC
+[     4.718] (II) Initializing extension XKEYBOARD
+[     4.718] (II) Initializing extension XC-MISC
+[     4.718] (II) Initializing extension SECURITY
+[     4.718] (II) Initializing extension XFIXES
+[     4.718] (II) Initializing extension RENDER
+[     4.718] (II) Initializing extension RANDR
+[     4.719] (II) Initializing extension COMPOSITE
+[     4.719] (II) Initializing extension DAMAGE
+[     4.719] (II) Initializing extension MIT-SCREEN-SAVER
+[     4.719] (II) Initializing extension DOUBLE-BUFFER
+[     4.719] (II) Initializing extension RECORD
+[     4.719] (II) Initializing extension DPMS
+[     4.719] (II) Initializing extension Present
+[     4.719] (II) Initializing extension DRI3
+[     4.719] (II) Initializing extension X-Resource
+[     4.719] (II) Initializing extension XVideo
+[     4.720] (II) Initializing extension XVideo-MotionCompensation
+[     4.720] (II) Initializing extension SELinux
+[     4.720] (II) SELinux: Disabled on system
+[     4.720] (II) Initializing extension GLX
+[     4.724] (II) AIGLX: Loaded and initialized i965
+[     4.724] (II) GLX: Initialized DRI2 GL provider for screen 0
+[     4.724] (II) Initializing extension XFree86-VidModeExtension
+[     4.724] (II) Initializing extension XFree86-DGA
+[     4.724] (II) Initializing extension XFree86-DRI
+[     4.724] (II) Initializing extension DRI2
+[     4.733] (II) modeset(0): Damage tracking initialized
+[     4.733] (II) modeset(0): Setting screen physical size to 508 x 285
+[     4.771] (II) config/udev: Adding input device Power Button (/dev/input/event2)
+[     4.771] (**) Power Button: Applying InputClass "libinput keyboard catchall"
+[     4.771] (II) LoadModule: "libinput"
+[     4.771] (II) Loading /usr/lib/xorg/modules/input/libinput_drv.so
+[     4.774] (II) Module libinput: vendor="X.Org Foundation"
+[     4.774] 	compiled for 1.20.4, module version = 0.29.0
+[     4.774] 	Module class: X.Org XInput Driver
+[     4.774] 	ABI class: X.Org XInput driver, version 24.1
+[     4.774] (II) Using input driver 'libinput' for 'Power Button'
+[     4.774] (**) Power Button: always reports core events
+[     4.774] (**) Option "Device" "/dev/input/event2"
+[     4.774] (**) Option "_source" "server/udev"
+[     4.776] (II) event2  - Power Button: is tagged by udev as: Keyboard
+[     4.776] (II) event2  - Power Button: device is a keyboard
+[     4.776] (II) event2  - Power Button: device removed
+[     4.796] (**) Option "config_info" "udev:/sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input2/event2"
+[     4.796] (II) XINPUT: Adding extended input device "Power Button" (type: KEYBOARD, id 6)
+[     4.796] (**) Option "xkb_model" "pc105"
+[     4.796] (**) Option "xkb_layout" "us"
+[     4.796] (II) event2  - Power Button: is tagged by udev as: Keyboard
+[     4.796] (II) event2  - Power Button: device is a keyboard
+[     4.797] (II) config/udev: Adding input device Video Bus (/dev/input/event5)
+[     4.797] (**) Video Bus: Applying InputClass "libinput keyboard catchall"
+[     4.797] (II) Using input driver 'libinput' for 'Video Bus'
+[     4.797] (**) Video Bus: always reports core events
+[     4.797] (**) Option "Device" "/dev/input/event5"
+[     4.797] (**) Option "_source" "server/udev"
+[     4.797] (II) event5  - Video Bus: is tagged by udev as: Keyboard
+[     4.797] (II) event5  - Video Bus: device is a keyboard
+[     4.797] (II) event5  - Video Bus: device removed
+[     4.819] (**) Option "config_info" "udev:/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/input/input7/event5"
+[     4.819] (II) XINPUT: Adding extended input device "Video Bus" (type: KEYBOARD, id 7)
+[     4.819] (**) Option "xkb_model" "pc105"
+[     4.819] (**) Option "xkb_layout" "us"
+[     4.819] (II) event5  - Video Bus: is tagged by udev as: Keyboard
+[     4.819] (II) event5  - Video Bus: device is a keyboard
+[     4.819] (II) config/udev: Adding input device Lid Switch (/dev/input/event1)
+[     4.819] (II) No input driver specified, ignoring this device.
+[     4.819] (II) This device may have been added with another device file.
+[     4.820] (II) config/udev: Adding input device Sleep Button (/dev/input/event0)
+[     4.820] (**) Sleep Button: Applying InputClass "libinput keyboard catchall"
+[     4.820] (II) Using input driver 'libinput' for 'Sleep Button'
+[     4.820] (**) Sleep Button: always reports core events
+[     4.820] (**) Option "Device" "/dev/input/event0"
+[     4.820] (**) Option "_source" "server/udev"
+[     4.820] (II) event0  - Sleep Button: is tagged by udev as: Keyboard
+[     4.820] (II) event0  - Sleep Button: device is a keyboard
+[     4.820] (II) event0  - Sleep Button: device removed
+[     4.834] (**) Option "config_info" "udev:/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0E:00/input/input0/event0"
+[     4.834] (II) XINPUT: Adding extended input device "Sleep Button" (type: KEYBOARD, id 8)
+[     4.834] (**) Option "xkb_model" "pc105"
+[     4.834] (**) Option "xkb_layout" "us"
+[     4.834] (II) event0  - Sleep Button: is tagged by udev as: Keyboard
+[     4.834] (II) event0  - Sleep Button: device is a keyboard
+[     4.835] (II) config/udev: Adding input device serio3 (/dev/input/event19)
+[     4.835] (**) serio3: Applying InputClass "libinput keyboard catchall"
+[     4.835] (II) Using input driver 'libinput' for 'serio3'
+[     4.835] (**) serio3: always reports core events
+[     4.835] (**) Option "Device" "/dev/input/event19"
+[     4.835] (**) Option "_source" "server/udev"
+[     4.836] (II) event19 - serio3: is tagged by udev as: Keyboard
+[     4.836] (II) event19 - serio3: device is a keyboard
+[     4.836] (II) event19 - serio3: device removed
+[     4.847] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/tty/ttyACM0/serio3/rc/rc0/input21/event19"
+[     4.847] (II) XINPUT: Adding extended input device "serio3" (type: KEYBOARD, id 9)
+[     4.847] (**) Option "xkb_model" "pc105"
+[     4.847] (**) Option "xkb_layout" "us"
+[     4.848] (II) event19 - serio3: is tagged by udev as: Keyboard
+[     4.848] (II) event19 - serio3: device is a keyboard
+[     4.848] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/event6)
+[     4.848] (**) Pulse-Eight CEC Adapter: Applying InputClass "libinput pointer catchall"
+[     4.848] (II) Using input driver 'libinput' for 'Pulse-Eight CEC Adapter'
+[     4.848] (**) Pulse-Eight CEC Adapter: always reports core events
+[     4.848] (**) Option "Device" "/dev/input/event6"
+[     4.848] (**) Option "_source" "server/udev"
+[     4.900] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[     4.900] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[     4.900] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[     4.915] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.2/0003:2548:1002.0001/input/input8/event6"
+[     4.915] (II) XINPUT: Adding extended input device "Pulse-Eight CEC Adapter" (type: MOUSE, id 10)
+[     4.915] (**) Option "AccelerationScheme" "none"
+[     4.915] (**) Pulse-Eight CEC Adapter: (accel) selected scheme none/0
+[     4.915] (**) Pulse-Eight CEC Adapter: (accel) acceleration factor: 2.000
+[     4.915] (**) Pulse-Eight CEC Adapter: (accel) acceleration threshold: 4
+[     4.967] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[     4.967] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[     4.968] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/mouse0)
+[     4.968] (II) No input driver specified, ignoring this device.
+[     4.968] (II) This device may have been added with another device file.
+[     4.968] (II) config/udev: Adding input device Integrated IR Camera: Integrate (/dev/input/event17)
+[     4.968] (**) Integrated IR Camera: Integrate: Applying InputClass "libinput keyboard catchall"
+[     4.968] (II) Using input driver 'libinput' for 'Integrated IR Camera: Integrate'
+[     4.968] (**) Integrated IR Camera: Integrate: always reports core events
+[     4.968] (**) Option "Device" "/dev/input/event17"
+[     4.968] (**) Option "_source" "server/udev"
+[     4.969] (II) event17 - Integrated IR Camera: Integrate: is tagged by udev as: Keyboard
+[     4.969] (II) event17 - Integrated IR Camera: Integrate: device is a keyboard
+[     4.969] (II) event17 - Integrated IR Camera: Integrate: device removed
+[     4.985] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5:1.0/input/input19/event17"
+[     4.985] (II) XINPUT: Adding extended input device "Integrated IR Camera: Integrate" (type: KEYBOARD, id 11)
+[     4.985] (**) Option "xkb_model" "pc105"
+[     4.985] (**) Option "xkb_layout" "us"
+[     4.985] (II) event17 - Integrated IR Camera: Integrate: is tagged by udev as: Keyboard
+[     4.985] (II) event17 - Integrated IR Camera: Integrate: device is a keyboard
+[     4.986] (II) config/udev: Adding input device Integrated Camera: Integrated C (/dev/input/event18)
+[     4.986] (**) Integrated Camera: Integrated C: Applying InputClass "libinput keyboard catchall"
+[     4.986] (II) Using input driver 'libinput' for 'Integrated Camera: Integrated C'
+[     4.986] (**) Integrated Camera: Integrated C: always reports core events
+[     4.986] (**) Option "Device" "/dev/input/event18"
+[     4.986] (**) Option "_source" "server/udev"
+[     4.986] (II) event18 - Integrated Camera: Integrated C: is tagged by udev as: Keyboard
+[     4.987] (II) event18 - Integrated Camera: Integrated C: device is a keyboard
+[     4.987] (II) event18 - Integrated Camera: Integrated C: device removed
+[     5.005] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8:1.0/input/input20/event18"
+[     5.005] (II) XINPUT: Adding extended input device "Integrated Camera: Integrated C" (type: KEYBOARD, id 12)
+[     5.005] (**) Option "xkb_model" "pc105"
+[     5.005] (**) Option "xkb_layout" "us"
+[     5.005] (II) event18 - Integrated Camera: Integrated C: is tagged by udev as: Keyboard
+[     5.005] (II) event18 - Integrated Camera: Integrated C: device is a keyboard
+[     5.006] (II) config/udev: Adding input device HDA Intel PCH Mic (/dev/input/event8)
+[     5.006] (II) No input driver specified, ignoring this device.
+[     5.006] (II) This device may have been added with another device file.
+[     5.006] (II) config/udev: Adding input device HDA Intel PCH Headphone (/dev/input/event9)
+[     5.006] (II) No input driver specified, ignoring this device.
+[     5.006] (II) This device may have been added with another device file.
+[     5.006] (II) config/udev: Adding input device HDA Intel PCH HDMI/DP,pcm=3 (/dev/input/event10)
+[     5.006] (II) No input driver specified, ignoring this device.
+[     5.006] (II) This device may have been added with another device file.
+[     5.006] (II) config/udev: Adding input device HDA Intel PCH HDMI/DP,pcm=7 (/dev/input/event11)
+[     5.006] (II) No input driver specified, ignoring this device.
+[     5.006] (II) This device may have been added with another device file.
+[     5.006] (II) config/udev: Adding input device HDA Intel PCH HDMI/DP,pcm=8 (/dev/input/event12)
+[     5.006] (II) No input driver specified, ignoring this device.
+[     5.006] (II) This device may have been added with another device file.
+[     5.007] (II) config/udev: Adding input device HDA Intel PCH HDMI/DP,pcm=9 (/dev/input/event13)
+[     5.007] (II) No input driver specified, ignoring this device.
+[     5.007] (II) This device may have been added with another device file.
+[     5.007] (II) config/udev: Adding input device HDA Intel PCH HDMI/DP,pcm=10 (/dev/input/event14)
+[     5.007] (II) No input driver specified, ignoring this device.
+[     5.007] (II) This device may have been added with another device file.
+[     5.007] (II) config/udev: Adding input device HDA Digital PCBeep (/dev/input/event7)
+[     5.007] (II) No input driver specified, ignoring this device.
+[     5.007] (II) This device may have been added with another device file.
+[     5.007] (II) config/udev: Adding input device AT Translated Set 2 keyboard (/dev/input/event4)
+[     5.007] (**) AT Translated Set 2 keyboard: Applying InputClass "libinput keyboard catchall"
+[     5.007] (II) Using input driver 'libinput' for 'AT Translated Set 2 keyboard'
+[     5.007] (**) AT Translated Set 2 keyboard: always reports core events
+[     5.007] (**) Option "Device" "/dev/input/event4"
+[     5.007] (**) Option "_source" "server/udev"
+[     5.008] (II) event4  - AT Translated Set 2 keyboard: is tagged by udev as: Keyboard
+[     5.008] (II) event4  - AT Translated Set 2 keyboard: device is a keyboard
+[     5.008] (II) event4  - AT Translated Set 2 keyboard: device removed
+[     5.017] (**) Option "config_info" "udev:/sys/devices/platform/i8042/serio0/input/input3/event4"
+[     5.017] (II) XINPUT: Adding extended input device "AT Translated Set 2 keyboard" (type: KEYBOARD, id 13)
+[     5.017] (**) Option "xkb_model" "pc105"
+[     5.017] (**) Option "xkb_layout" "us"
+[     5.017] (II) event4  - AT Translated Set 2 keyboard: is tagged by udev as: Keyboard
+[     5.017] (II) event4  - AT Translated Set 2 keyboard: device is a keyboard
+[     5.018] (II) config/udev: Adding input device PC Speaker (/dev/input/event3)
+[     5.018] (II) No input driver specified, ignoring this device.
+[     5.018] (II) This device may have been added with another device file.
+[     5.018] (II) config/udev: Adding input device Synaptics TM3289-021 (/dev/input/event15)
+[     5.018] (**) Synaptics TM3289-021: Applying InputClass "libinput touchpad catchall"
+[     5.018] (II) Using input driver 'libinput' for 'Synaptics TM3289-021'
+[     5.018] (**) Synaptics TM3289-021: always reports core events
+[     5.018] (**) Option "Device" "/dev/input/event15"
+[     5.018] (**) Option "_source" "server/udev"
+[     5.019] (II) event15 - Synaptics TM3289-021: is tagged by udev as: Touchpad
+[     5.019] (II) event15 - Synaptics TM3289-021: device is a touchpad
+[     5.019] (II) event15 - Synaptics TM3289-021: device removed
+[     5.037] (**) Option "config_info" "udev:/sys/devices/rmi4-00/input/input12/event15"
+[     5.037] (II) XINPUT: Adding extended input device "Synaptics TM3289-021" (type: TOUCHPAD, id 14)
+[     5.037] (**) Option "AccelerationScheme" "none"
+[     5.037] (**) Synaptics TM3289-021: (accel) selected scheme none/0
+[     5.037] (**) Synaptics TM3289-021: (accel) acceleration factor: 2.000
+[     5.037] (**) Synaptics TM3289-021: (accel) acceleration threshold: 4
+[     5.038] (II) event15 - Synaptics TM3289-021: is tagged by udev as: Touchpad
+[     5.038] (II) event15 - Synaptics TM3289-021: device is a touchpad
+[     5.039] (II) config/udev: Adding input device Synaptics TM3289-021 (/dev/input/mouse1)
+[     5.039] (II) No input driver specified, ignoring this device.
+[     5.039] (II) This device may have been added with another device file.
+[     5.039] (II) config/udev: Adding input device TPPS/2 Elan TrackPoint (/dev/input/event16)
+[     5.039] (**) TPPS/2 Elan TrackPoint: Applying InputClass "libinput pointer catchall"
+[     5.039] (II) Using input driver 'libinput' for 'TPPS/2 Elan TrackPoint'
+[     5.039] (**) TPPS/2 Elan TrackPoint: always reports core events
+[     5.039] (**) Option "Device" "/dev/input/event16"
+[     5.039] (**) Option "_source" "server/udev"
+[     5.040] (II) event16 - TPPS/2 Elan TrackPoint: is tagged by udev as: Mouse Pointingstick
+[     5.040] (II) event16 - TPPS/2 Elan TrackPoint: trackpoint multiplier is 0.40
+[     5.040] (II) event16 - TPPS/2 Elan TrackPoint: device is a pointer
+[     5.040] (II) event16 - TPPS/2 Elan TrackPoint: device removed
+[     5.062] (**) Option "config_info" "udev:/sys/devices/rmi4-00/rmi4-00.fn03/serio2/input/input18/event16"
+[     5.062] (II) XINPUT: Adding extended input device "TPPS/2 Elan TrackPoint" (type: MOUSE, id 15)
+[     5.062] (**) Option "AccelerationScheme" "none"
+[     5.062] (**) TPPS/2 Elan TrackPoint: (accel) selected scheme none/0
+[     5.062] (**) TPPS/2 Elan TrackPoint: (accel) acceleration factor: 2.000
+[     5.062] (**) TPPS/2 Elan TrackPoint: (accel) acceleration threshold: 4
+[     5.062] (II) event16 - TPPS/2 Elan TrackPoint: is tagged by udev as: Mouse Pointingstick
+[     5.062] (II) event16 - TPPS/2 Elan TrackPoint: trackpoint multiplier is 0.40
+[     5.063] (II) event16 - TPPS/2 Elan TrackPoint: device is a pointer
+[     5.063] (II) config/udev: Adding input device TPPS/2 Elan TrackPoint (/dev/input/mouse2)
+[     5.063] (II) No input driver specified, ignoring this device.
+[     5.063] (II) This device may have been added with another device file.
+[     5.132] (EE) Failed to open authorization file "/var/run/sddm/{f25a154d-0c5d-47a7-b540-6fc92b41d2f3}": No such file or directory
+[    12.176] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[    12.176] (II) modeset(0): Printing DDC gathered Modelines:
+[    12.176] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[    12.669] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[    12.670] (II) modeset(0): Printing DDC gathered Modelines:
+[    12.670] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[   148.238] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[   148.238] (II) modeset(0): Printing DDC gathered Modelines:
+[   148.238] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[   148.829] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[   149.714] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[   219.576] (II) config/udev: removing device serio3
+[   219.577] (II) event19 - serio3: device removed
+[   219.591] (II) UnloadModule: "libinput"
+[   219.591] (II) config/udev: removing device Pulse-Eight CEC Adapter
+[   219.591] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[   219.605] (II) UnloadModule: "libinput"
+[   222.688] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/mouse0)
+[   222.688] (II) No input driver specified, ignoring this device.
+[   222.688] (II) This device may have been added with another device file.
+[   222.770] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/event6)
+[   222.771] (**) Pulse-Eight CEC Adapter: Applying InputClass "libinput pointer catchall"
+[   222.771] (II) Using input driver 'libinput' for 'Pulse-Eight CEC Adapter'
+[   222.771] (**) Pulse-Eight CEC Adapter: always reports core events
+[   222.771] (**) Option "Device" "/dev/input/event6"
+[   222.771] (**) Option "_source" "server/udev"
+[   222.824] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[   222.824] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[   222.824] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[   222.854] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.2/0003:2548:1002.0002/input/input22/event6"
+[   222.854] (II) XINPUT: Adding extended input device "Pulse-Eight CEC Adapter" (type: MOUSE, id 9)
+[   222.854] (**) Option "AccelerationScheme" "none"
+[   222.854] (**) Pulse-Eight CEC Adapter: (accel) selected scheme none/0
+[   222.854] (**) Pulse-Eight CEC Adapter: (accel) acceleration factor: 2.000
+[   222.854] (**) Pulse-Eight CEC Adapter: (accel) acceleration threshold: 4
+[   222.910] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[   222.910] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[   222.913] (II) config/udev: Adding input device serio4 (/dev/input/event19)
+[   222.913] (**) serio4: Applying InputClass "libinput keyboard catchall"
+[   222.913] (II) Using input driver 'libinput' for 'serio4'
+[   222.913] (**) serio4: always reports core events
+[   222.913] (**) Option "Device" "/dev/input/event19"
+[   222.913] (**) Option "_source" "server/udev"
+[   222.917] (II) event19 - serio4: is tagged by udev as: Keyboard
+[   222.918] (II) event19 - serio4: device is a keyboard
+[   222.918] (II) event19 - serio4: device removed
+[   222.933] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/tty/ttyACM0/serio4/rc/rc0/input23/event19"
+[   222.933] (II) XINPUT: Adding extended input device "serio4" (type: KEYBOARD, id 10)
+[   222.933] (**) Option "xkb_model" "pc105"
+[   222.933] (**) Option "xkb_layout" "us"
+[   222.933] (WW) Option "xkb_variant" requires a string value
+[   222.933] (WW) Option "xkb_options" requires a string value
+[   222.938] (II) event19 - serio4: is tagged by udev as: Keyboard
+[   222.938] (II) event19 - serio4: device is a keyboard
+[   268.794] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[   268.794] (II) modeset(0): Printing DDC gathered Modelines:
+[   268.794] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[   269.884] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[   272.592] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[   272.592] (II) modeset(0): Printing DDC gathered Modelines:
+[   272.592] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[   272.927] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[   273.756] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[   282.930] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[   282.930] (II) modeset(0): Printing DDC gathered Modelines:
+[   282.930] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[   283.262] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[   307.150] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[   309.524] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[   309.524] (II) modeset(0): Printing DDC gathered Modelines:
+[   309.524] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[   309.860] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[   310.742] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[   325.273] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[   325.273] (II) modeset(0): Printing DDC gathered Modelines:
+[   325.273] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[   325.607] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[   361.491] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[   364.630] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[   364.630] (II) modeset(0): Printing DDC gathered Modelines:
+[   364.630] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[   364.965] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[   365.793] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[   740.130] (II) config/udev: removing device serio4
+[   740.130] (II) event19 - serio4: device removed
+[   740.144] (II) UnloadModule: "libinput"
+[   740.149] (II) config/udev: removing device Pulse-Eight CEC Adapter
+[   740.149] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[   740.160] (II) UnloadModule: "libinput"
+[   767.809] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/mouse0)
+[   767.809] (II) No input driver specified, ignoring this device.
+[   767.809] (II) This device may have been added with another device file.
+[   767.889] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/event6)
+[   767.889] (**) Pulse-Eight CEC Adapter: Applying InputClass "libinput pointer catchall"
+[   767.889] (II) Using input driver 'libinput' for 'Pulse-Eight CEC Adapter'
+[   767.889] (**) Pulse-Eight CEC Adapter: always reports core events
+[   767.889] (**) Option "Device" "/dev/input/event6"
+[   767.889] (**) Option "_source" "server/udev"
+[   767.945] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[   767.945] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[   767.946] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[   767.973] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.2/0003:2548:1002.0003/input/input24/event6"
+[   767.973] (II) XINPUT: Adding extended input device "Pulse-Eight CEC Adapter" (type: MOUSE, id 9)
+[   767.974] (**) Option "AccelerationScheme" "none"
+[   767.975] (**) Pulse-Eight CEC Adapter: (accel) selected scheme none/0
+[   767.975] (**) Pulse-Eight CEC Adapter: (accel) acceleration factor: 2.000
+[   767.975] (**) Pulse-Eight CEC Adapter: (accel) acceleration threshold: 4
+[   768.030] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[   768.030] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[   768.033] (II) config/udev: Adding input device serio5 (/dev/input/event19)
+[   768.033] (**) serio5: Applying InputClass "libinput keyboard catchall"
+[   768.033] (II) Using input driver 'libinput' for 'serio5'
+[   768.033] (**) serio5: always reports core events
+[   768.033] (**) Option "Device" "/dev/input/event19"
+[   768.033] (**) Option "_source" "server/udev"
+[   768.037] (II) event19 - serio5: is tagged by udev as: Keyboard
+[   768.038] (II) event19 - serio5: device is a keyboard
+[   768.039] (II) event19 - serio5: device removed
+[   768.049] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/tty/ttyACM0/serio5/rc/rc0/input25/event19"
+[   768.049] (II) XINPUT: Adding extended input device "serio5" (type: KEYBOARD, id 10)
+[   768.049] (**) Option "xkb_model" "pc105"
+[   768.049] (**) Option "xkb_layout" "us"
+[   768.049] (WW) Option "xkb_variant" requires a string value
+[   768.049] (WW) Option "xkb_options" requires a string value
+[   768.054] (II) event19 - serio5: is tagged by udev as: Keyboard
+[   768.054] (II) event19 - serio5: device is a keyboard
+[   854.957] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[   854.957] (II) modeset(0): Printing DDC gathered Modelines:
+[   854.957] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[   856.045] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[  1518.312] (II) config/udev: removing device serio5
+[  1518.312] (II) event19 - serio5: device removed
+[  1518.328] (II) UnloadModule: "libinput"
+[  1518.331] (II) config/udev: removing device Pulse-Eight CEC Adapter
+[  1518.331] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[  1518.343] (II) UnloadModule: "libinput"
+[  1524.043] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/mouse0)
+[  1524.043] (II) No input driver specified, ignoring this device.
+[  1524.043] (II) This device may have been added with another device file.
+[  1524.122] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/event6)
+[  1524.122] (**) Pulse-Eight CEC Adapter: Applying InputClass "libinput pointer catchall"
+[  1524.122] (II) Using input driver 'libinput' for 'Pulse-Eight CEC Adapter'
+[  1524.122] (**) Pulse-Eight CEC Adapter: always reports core events
+[  1524.122] (**) Option "Device" "/dev/input/event6"
+[  1524.122] (**) Option "_source" "server/udev"
+[  1524.175] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[  1524.175] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[  1524.176] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[  1524.208] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.2/0003:2548:1002.0004/input/input26/event6"
+[  1524.208] (II) XINPUT: Adding extended input device "Pulse-Eight CEC Adapter" (type: MOUSE, id 9)
+[  1524.209] (**) Option "AccelerationScheme" "none"
+[  1524.210] (**) Pulse-Eight CEC Adapter: (accel) selected scheme none/0
+[  1524.210] (**) Pulse-Eight CEC Adapter: (accel) acceleration factor: 2.000
+[  1524.210] (**) Pulse-Eight CEC Adapter: (accel) acceleration threshold: 4
+[  1524.265] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[  1524.265] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[  1524.268] (II) config/udev: Adding input device serio6 (/dev/input/event19)
+[  1524.268] (**) serio6: Applying InputClass "libinput keyboard catchall"
+[  1524.268] (II) Using input driver 'libinput' for 'serio6'
+[  1524.268] (**) serio6: always reports core events
+[  1524.268] (**) Option "Device" "/dev/input/event19"
+[  1524.268] (**) Option "_source" "server/udev"
+[  1524.273] (II) event19 - serio6: is tagged by udev as: Keyboard
+[  1524.273] (II) event19 - serio6: device is a keyboard
+[  1524.274] (II) event19 - serio6: device removed
+[  1524.292] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/tty/ttyACM0/serio6/rc/rc0/input27/event19"
+[  1524.292] (II) XINPUT: Adding extended input device "serio6" (type: KEYBOARD, id 10)
+[  1524.292] (**) Option "xkb_model" "pc105"
+[  1524.292] (**) Option "xkb_layout" "us"
+[  1524.292] (WW) Option "xkb_variant" requires a string value
+[  1524.292] (WW) Option "xkb_options" requires a string value
+[  1524.297] (II) event19 - serio6: is tagged by udev as: Keyboard
+[  1524.297] (II) event19 - serio6: device is a keyboard
+[  1536.974] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[  1536.974] (II) modeset(0): Printing DDC gathered Modelines:
+[  1536.974] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[  1537.311] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[  1538.189] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 15936.823] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 15936.823] (II) modeset(0): Printing DDC gathered Modelines:
+[ 15936.823] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 15937.913] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 67070.083] (II) config/udev: removing device serio6
+[ 67070.083] (II) event19 - serio6: device removed
+[ 67070.090] (II) UnloadModule: "libinput"
+[ 67070.100] (II) config/udev: removing device Pulse-Eight CEC Adapter
+[ 67070.100] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[ 67070.116] (II) UnloadModule: "libinput"
+[ 67074.730] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/mouse0)
+[ 67074.730] (II) No input driver specified, ignoring this device.
+[ 67074.730] (II) This device may have been added with another device file.
+[ 67074.811] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/event6)
+[ 67074.811] (**) Pulse-Eight CEC Adapter: Applying InputClass "libinput pointer catchall"
+[ 67074.811] (II) Using input driver 'libinput' for 'Pulse-Eight CEC Adapter'
+[ 67074.811] (**) Pulse-Eight CEC Adapter: always reports core events
+[ 67074.811] (**) Option "Device" "/dev/input/event6"
+[ 67074.811] (**) Option "_source" "server/udev"
+[ 67074.867] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[ 67074.867] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[ 67074.868] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[ 67074.890] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.2/0003:2548:1002.0005/input/input28/event6"
+[ 67074.890] (II) XINPUT: Adding extended input device "Pulse-Eight CEC Adapter" (type: MOUSE, id 9)
+[ 67074.891] (**) Option "AccelerationScheme" "none"
+[ 67074.892] (**) Pulse-Eight CEC Adapter: (accel) selected scheme none/0
+[ 67074.892] (**) Pulse-Eight CEC Adapter: (accel) acceleration factor: 2.000
+[ 67074.892] (**) Pulse-Eight CEC Adapter: (accel) acceleration threshold: 4
+[ 67074.947] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[ 67074.948] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[ 67095.126] (II) config/udev: removing device Pulse-Eight CEC Adapter
+[ 67095.126] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[ 67095.138] (II) UnloadModule: "libinput"
+[ 67100.773] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/mouse0)
+[ 67100.773] (II) No input driver specified, ignoring this device.
+[ 67100.773] (II) This device may have been added with another device file.
+[ 67100.854] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/event6)
+[ 67100.854] (**) Pulse-Eight CEC Adapter: Applying InputClass "libinput pointer catchall"
+[ 67100.854] (II) Using input driver 'libinput' for 'Pulse-Eight CEC Adapter'
+[ 67100.854] (**) Pulse-Eight CEC Adapter: always reports core events
+[ 67100.854] (**) Option "Device" "/dev/input/event6"
+[ 67100.854] (**) Option "_source" "server/udev"
+[ 67100.907] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[ 67100.907] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[ 67100.907] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[ 67100.926] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.2/0003:2548:1002.0006/input/input30/event6"
+[ 67100.926] (II) XINPUT: Adding extended input device "Pulse-Eight CEC Adapter" (type: MOUSE, id 9)
+[ 67100.926] (**) Option "AccelerationScheme" "none"
+[ 67100.927] (**) Pulse-Eight CEC Adapter: (accel) selected scheme none/0
+[ 67100.927] (**) Pulse-Eight CEC Adapter: (accel) acceleration factor: 2.000
+[ 67100.927] (**) Pulse-Eight CEC Adapter: (accel) acceleration threshold: 4
+[ 67100.982] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[ 67100.982] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[ 67100.985] (II) config/udev: Adding input device serio8 (/dev/input/event19)
+[ 67100.985] (**) serio8: Applying InputClass "libinput keyboard catchall"
+[ 67100.985] (II) Using input driver 'libinput' for 'serio8'
+[ 67100.985] (**) serio8: always reports core events
+[ 67100.985] (**) Option "Device" "/dev/input/event19"
+[ 67100.985] (**) Option "_source" "server/udev"
+[ 67100.990] (II) event19 - serio8: is tagged by udev as: Keyboard
+[ 67100.990] (II) event19 - serio8: device is a keyboard
+[ 67100.991] (II) event19 - serio8: device removed
+[ 67101.001] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/tty/ttyACM0/serio8/rc/rc0/input31/event19"
+[ 67101.001] (II) XINPUT: Adding extended input device "serio8" (type: KEYBOARD, id 10)
+[ 67101.001] (**) Option "xkb_model" "pc105"
+[ 67101.001] (**) Option "xkb_layout" "us"
+[ 67101.001] (WW) Option "xkb_variant" requires a string value
+[ 67101.001] (WW) Option "xkb_options" requires a string value
+[ 67101.006] (II) event19 - serio8: is tagged by udev as: Keyboard
+[ 67101.006] (II) event19 - serio8: device is a keyboard
+[ 67127.966] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 67127.966] (II) modeset(0): Printing DDC gathered Modelines:
+[ 67127.966] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 67128.302] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 67129.177] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 67359.952] (II) config/udev: removing device Integrated Camera: Integrated C
+[ 67359.952] (II) event18 - Integrated Camera: Integrated C: device removed
+[ 67359.965] (II) UnloadModule: "libinput"
+[ 67360.066] (II) config/udev: removing device Integrated IR Camera: Integrate
+[ 67360.066] (II) event17 - Integrated IR Camera: Integrate: device removed
+[ 67360.078] (II) UnloadModule: "libinput"
+[ 67360.125] (II) config/udev: removing device serio8
+[ 67360.125] (II) event19 - serio8: device removed
+[ 67360.140] (II) UnloadModule: "libinput"
+[ 67374.717] (II) config/udev: removing device Pulse-Eight CEC Adapter
+[ 67374.717] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[ 67374.729] (II) UnloadModule: "libinput"
+[ 67379.434] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/mouse0)
+[ 67379.434] (II) No input driver specified, ignoring this device.
+[ 67379.434] (II) This device may have been added with another device file.
+[ 67379.514] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/event6)
+[ 67379.514] (**) Pulse-Eight CEC Adapter: Applying InputClass "libinput pointer catchall"
+[ 67379.515] (II) Using input driver 'libinput' for 'Pulse-Eight CEC Adapter'
+[ 67379.515] (**) Pulse-Eight CEC Adapter: always reports core events
+[ 67379.515] (**) Option "Device" "/dev/input/event6"
+[ 67379.515] (**) Option "_source" "server/udev"
+[ 67379.568] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[ 67379.569] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[ 67379.569] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[ 67379.590] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.2/0003:2548:1002.0007/input/input32/event6"
+[ 67379.590] (II) XINPUT: Adding extended input device "Pulse-Eight CEC Adapter" (type: MOUSE, id 9)
+[ 67379.590] (**) Option "AccelerationScheme" "none"
+[ 67379.591] (**) Pulse-Eight CEC Adapter: (accel) selected scheme none/0
+[ 67379.591] (**) Pulse-Eight CEC Adapter: (accel) acceleration factor: 2.000
+[ 67379.591] (**) Pulse-Eight CEC Adapter: (accel) acceleration threshold: 4
+[ 67379.646] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[ 67379.646] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[ 67379.649] (II) config/udev: Adding input device serio9 (/dev/input/event17)
+[ 67379.649] (**) serio9: Applying InputClass "libinput keyboard catchall"
+[ 67379.649] (II) Using input driver 'libinput' for 'serio9'
+[ 67379.649] (**) serio9: always reports core events
+[ 67379.649] (**) Option "Device" "/dev/input/event17"
+[ 67379.649] (**) Option "_source" "server/udev"
+[ 67379.654] (II) event17 - serio9: is tagged by udev as: Keyboard
+[ 67379.654] (II) event17 - serio9: device is a keyboard
+[ 67379.655] (II) event17 - serio9: device removed
+[ 67379.672] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/tty/ttyACM0/serio9/rc/rc0/input33/event17"
+[ 67379.672] (II) XINPUT: Adding extended input device "serio9" (type: KEYBOARD, id 10)
+[ 67379.672] (**) Option "xkb_model" "pc105"
+[ 67379.672] (**) Option "xkb_layout" "us"
+[ 67379.672] (WW) Option "xkb_variant" requires a string value
+[ 67379.672] (WW) Option "xkb_options" requires a string value
+[ 67379.677] (II) event17 - serio9: is tagged by udev as: Keyboard
+[ 67379.677] (II) event17 - serio9: device is a keyboard
+[ 67466.307] (II) config/udev: removing device serio9
+[ 67466.307] (II) event17 - serio9: device removed
+[ 67466.313] (II) UnloadModule: "libinput"
+[ 67466.323] (II) config/udev: removing device Pulse-Eight CEC Adapter
+[ 67466.323] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[ 67466.335] (II) UnloadModule: "libinput"
+[ 67489.814] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/mouse0)
+[ 67489.814] (II) No input driver specified, ignoring this device.
+[ 67489.814] (II) This device may have been added with another device file.
+[ 67489.894] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/event6)
+[ 67489.895] (**) Pulse-Eight CEC Adapter: Applying InputClass "libinput pointer catchall"
+[ 67489.895] (II) Using input driver 'libinput' for 'Pulse-Eight CEC Adapter'
+[ 67489.895] (**) Pulse-Eight CEC Adapter: always reports core events
+[ 67489.895] (**) Option "Device" "/dev/input/event6"
+[ 67489.895] (**) Option "_source" "server/udev"
+[ 67489.950] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[ 67489.950] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[ 67489.951] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[ 67489.974] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.2/0003:2548:1002.0008/input/input34/event6"
+[ 67489.974] (II) XINPUT: Adding extended input device "Pulse-Eight CEC Adapter" (type: MOUSE, id 9)
+[ 67489.975] (**) Option "AccelerationScheme" "none"
+[ 67489.976] (**) Pulse-Eight CEC Adapter: (accel) selected scheme none/0
+[ 67489.976] (**) Pulse-Eight CEC Adapter: (accel) acceleration factor: 2.000
+[ 67489.976] (**) Pulse-Eight CEC Adapter: (accel) acceleration threshold: 4
+[ 67490.031] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[ 67490.031] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[ 67490.034] (II) config/udev: Adding input device serio10 (/dev/input/event17)
+[ 67490.034] (**) serio10: Applying InputClass "libinput keyboard catchall"
+[ 67490.034] (II) Using input driver 'libinput' for 'serio10'
+[ 67490.034] (**) serio10: always reports core events
+[ 67490.034] (**) Option "Device" "/dev/input/event17"
+[ 67490.034] (**) Option "_source" "server/udev"
+[ 67490.039] (II) event17 - serio10: is tagged by udev as: Keyboard
+[ 67490.039] (II) event17 - serio10: device is a keyboard
+[ 67490.040] (II) event17 - serio10: device removed
+[ 67490.051] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/tty/ttyACM0/serio10/rc/rc0/input35/event17"
+[ 67490.051] (II) XINPUT: Adding extended input device "serio10" (type: KEYBOARD, id 10)
+[ 67490.051] (**) Option "xkb_model" "pc105"
+[ 67490.051] (**) Option "xkb_layout" "us"
+[ 67490.051] (WW) Option "xkb_variant" requires a string value
+[ 67490.051] (WW) Option "xkb_options" requires a string value
+[ 67490.056] (II) event17 - serio10: is tagged by udev as: Keyboard
+[ 67490.056] (II) event17 - serio10: device is a keyboard
+[ 67517.542] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 67517.542] (II) modeset(0): Printing DDC gathered Modelines:
+[ 67517.542] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 67518.681] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 74816.397] (II) config/udev: removing device serio10
+[ 74816.398] (II) event17 - serio10: device removed
+[ 74816.415] (II) UnloadModule: "libinput"
+[ 74816.420] (II) config/udev: removing device Pulse-Eight CEC Adapter
+[ 74816.420] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[ 74816.432] (II) UnloadModule: "libinput"
+[ 74820.247] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/mouse0)
+[ 74820.247] (II) No input driver specified, ignoring this device.
+[ 74820.247] (II) This device may have been added with another device file.
+[ 74820.328] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/event6)
+[ 74820.328] (**) Pulse-Eight CEC Adapter: Applying InputClass "libinput pointer catchall"
+[ 74820.328] (II) Using input driver 'libinput' for 'Pulse-Eight CEC Adapter'
+[ 74820.328] (**) Pulse-Eight CEC Adapter: always reports core events
+[ 74820.328] (**) Option "Device" "/dev/input/event6"
+[ 74820.328] (**) Option "_source" "server/udev"
+[ 74820.384] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[ 74820.385] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[ 74820.386] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[ 74820.408] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.2/0003:2548:1002.0009/input/input36/event6"
+[ 74820.408] (II) XINPUT: Adding extended input device "Pulse-Eight CEC Adapter" (type: MOUSE, id 9)
+[ 74820.408] (**) Option "AccelerationScheme" "none"
+[ 74820.409] (**) Pulse-Eight CEC Adapter: (accel) selected scheme none/0
+[ 74820.409] (**) Pulse-Eight CEC Adapter: (accel) acceleration factor: 2.000
+[ 74820.409] (**) Pulse-Eight CEC Adapter: (accel) acceleration threshold: 4
+[ 74820.462] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[ 74820.463] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[ 74820.465] (II) config/udev: Adding input device serio11 (/dev/input/event17)
+[ 74820.465] (**) serio11: Applying InputClass "libinput keyboard catchall"
+[ 74820.465] (II) Using input driver 'libinput' for 'serio11'
+[ 74820.465] (**) serio11: always reports core events
+[ 74820.465] (**) Option "Device" "/dev/input/event17"
+[ 74820.465] (**) Option "_source" "server/udev"
+[ 74820.468] (II) event17 - serio11: is tagged by udev as: Keyboard
+[ 74820.468] (II) event17 - serio11: device is a keyboard
+[ 74820.469] (II) event17 - serio11: device removed
+[ 74820.484] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/tty/ttyACM0/serio11/rc/rc0/input37/event17"
+[ 74820.484] (II) XINPUT: Adding extended input device "serio11" (type: KEYBOARD, id 10)
+[ 74820.484] (**) Option "xkb_model" "pc105"
+[ 74820.484] (**) Option "xkb_layout" "us"
+[ 74820.484] (WW) Option "xkb_variant" requires a string value
+[ 74820.484] (WW) Option "xkb_options" requires a string value
+[ 74820.489] (II) event17 - serio11: is tagged by udev as: Keyboard
+[ 74820.489] (II) event17 - serio11: device is a keyboard
+[ 74844.099] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 74844.099] (II) modeset(0): Printing DDC gathered Modelines:
+[ 74844.099] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 74844.434] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 74845.241] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 75427.645] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 75427.645] (II) modeset(0): Printing DDC gathered Modelines:
+[ 75427.645] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 75428.764] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 75434.846] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 75434.846] (II) modeset(0): Printing DDC gathered Modelines:
+[ 75434.846] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 75435.181] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 75436.047] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 75439.476] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 75439.476] (II) modeset(0): Printing DDC gathered Modelines:
+[ 75439.476] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 75439.809] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 75480.334] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 75486.077] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 75486.077] (II) modeset(0): Printing DDC gathered Modelines:
+[ 75486.077] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 75486.414] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 75487.224] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 76141.668] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 76141.668] (II) modeset(0): Printing DDC gathered Modelines:
+[ 76141.668] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 76142.772] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 76145.989] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 76145.989] (II) modeset(0): Printing DDC gathered Modelines:
+[ 76145.989] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 76146.324] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 76147.204] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 76181.810] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 76181.811] (II) modeset(0): Printing DDC gathered Modelines:
+[ 76181.811] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 76182.899] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 76195.390] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 76195.390] (II) modeset(0): Printing DDC gathered Modelines:
+[ 76195.390] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 76195.726] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 76196.600] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 76204.061] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 76204.061] (II) modeset(0): Printing DDC gathered Modelines:
+[ 76204.061] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 76205.167] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 76213.216] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 76213.216] (II) modeset(0): Printing DDC gathered Modelines:
+[ 76213.216] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 76213.552] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 76214.382] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 76221.922] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 76221.922] (II) modeset(0): Printing DDC gathered Modelines:
+[ 76221.922] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 76222.989] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 76231.080] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 76231.080] (II) modeset(0): Printing DDC gathered Modelines:
+[ 76231.080] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 76231.415] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 76232.234] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 76242.944] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 76242.944] (II) modeset(0): Printing DDC gathered Modelines:
+[ 76242.944] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 76244.041] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 76252.117] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 76252.117] (II) modeset(0): Printing DDC gathered Modelines:
+[ 76252.117] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 76252.453] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 76253.267] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 76259.170] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 76259.170] (II) modeset(0): Printing DDC gathered Modelines:
+[ 76259.170] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 76260.333] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 76268.331] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 76268.331] (II) modeset(0): Printing DDC gathered Modelines:
+[ 76268.331] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 76268.666] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 76269.545] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 76275.429] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 76275.429] (II) modeset(0): Printing DDC gathered Modelines:
+[ 76275.429] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 76276.517] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 76284.585] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 76284.585] (II) modeset(0): Printing DDC gathered Modelines:
+[ 76284.585] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 76284.921] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 76285.767] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 76362.635] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 76362.635] (II) modeset(0): Printing DDC gathered Modelines:
+[ 76362.635] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 76363.754] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 76777.916] (II) config/udev: removing device serio11
+[ 76777.916] (II) event17 - serio11: device removed
+[ 76777.926] (II) UnloadModule: "libinput"
+[ 76777.928] (II) config/udev: removing device Pulse-Eight CEC Adapter
+[ 76777.929] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[ 76777.944] (II) UnloadModule: "libinput"
+[ 76791.743] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/mouse0)
+[ 76791.743] (II) No input driver specified, ignoring this device.
+[ 76791.743] (II) This device may have been added with another device file.
+[ 76791.824] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/event6)
+[ 76791.824] (**) Pulse-Eight CEC Adapter: Applying InputClass "libinput pointer catchall"
+[ 76791.824] (II) Using input driver 'libinput' for 'Pulse-Eight CEC Adapter'
+[ 76791.824] (**) Pulse-Eight CEC Adapter: always reports core events
+[ 76791.824] (**) Option "Device" "/dev/input/event6"
+[ 76791.824] (**) Option "_source" "server/udev"
+[ 76791.880] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[ 76791.880] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[ 76791.881] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[ 76791.904] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.2/0003:2548:1002.000A/input/input38/event6"
+[ 76791.904] (II) XINPUT: Adding extended input device "Pulse-Eight CEC Adapter" (type: MOUSE, id 9)
+[ 76791.905] (**) Option "AccelerationScheme" "none"
+[ 76791.906] (**) Pulse-Eight CEC Adapter: (accel) selected scheme none/0
+[ 76791.906] (**) Pulse-Eight CEC Adapter: (accel) acceleration factor: 2.000
+[ 76791.906] (**) Pulse-Eight CEC Adapter: (accel) acceleration threshold: 4
+[ 76791.961] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[ 76791.961] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[ 76791.964] (II) config/udev: Adding input device serio12 (/dev/input/event17)
+[ 76791.964] (**) serio12: Applying InputClass "libinput keyboard catchall"
+[ 76791.964] (II) Using input driver 'libinput' for 'serio12'
+[ 76791.964] (**) serio12: always reports core events
+[ 76791.964] (**) Option "Device" "/dev/input/event17"
+[ 76791.964] (**) Option "_source" "server/udev"
+[ 76791.969] (II) event17 - serio12: is tagged by udev as: Keyboard
+[ 76791.969] (II) event17 - serio12: device is a keyboard
+[ 76791.970] (II) event17 - serio12: device removed
+[ 76791.988] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/tty/ttyACM0/serio12/rc/rc0/input39/event17"
+[ 76791.988] (II) XINPUT: Adding extended input device "serio12" (type: KEYBOARD, id 10)
+[ 76791.988] (**) Option "xkb_model" "pc105"
+[ 76791.988] (**) Option "xkb_layout" "us"
+[ 76791.988] (WW) Option "xkb_variant" requires a string value
+[ 76791.988] (WW) Option "xkb_options" requires a string value
+[ 76791.993] (II) event17 - serio12: is tagged by udev as: Keyboard
+[ 76791.993] (II) event17 - serio12: device is a keyboard
+[ 76823.321] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 76823.321] (II) modeset(0): Printing DDC gathered Modelines:
+[ 76823.321] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 76823.656] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 76824.514] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 76830.683] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 76830.683] (II) modeset(0): Printing DDC gathered Modelines:
+[ 76830.683] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 76831.804] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 77846.982] (II) config/udev: removing device serio12
+[ 77846.982] (II) event17 - serio12: device removed
+[ 77846.997] (II) UnloadModule: "libinput"
+[ 77849.045] (II) config/udev: removing device Pulse-Eight CEC Adapter
+[ 77849.045] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[ 77849.066] (II) UnloadModule: "libinput"
+[ 77854.150] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/mouse0)
+[ 77854.150] (II) No input driver specified, ignoring this device.
+[ 77854.150] (II) This device may have been added with another device file.
+[ 77854.231] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/event6)
+[ 77854.231] (**) Pulse-Eight CEC Adapter: Applying InputClass "libinput pointer catchall"
+[ 77854.231] (II) Using input driver 'libinput' for 'Pulse-Eight CEC Adapter'
+[ 77854.231] (**) Pulse-Eight CEC Adapter: always reports core events
+[ 77854.231] (**) Option "Device" "/dev/input/event6"
+[ 77854.231] (**) Option "_source" "server/udev"
+[ 77854.286] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[ 77854.286] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[ 77854.287] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[ 77854.308] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.2/0003:2548:1002.000B/input/input40/event6"
+[ 77854.308] (II) XINPUT: Adding extended input device "Pulse-Eight CEC Adapter" (type: MOUSE, id 9)
+[ 77854.309] (**) Option "AccelerationScheme" "none"
+[ 77854.309] (**) Pulse-Eight CEC Adapter: (accel) selected scheme none/0
+[ 77854.309] (**) Pulse-Eight CEC Adapter: (accel) acceleration factor: 2.000
+[ 77854.309] (**) Pulse-Eight CEC Adapter: (accel) acceleration threshold: 4
+[ 77854.362] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[ 77854.362] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[ 77854.364] (II) config/udev: Adding input device serio13 (/dev/input/event17)
+[ 77854.364] (**) serio13: Applying InputClass "libinput keyboard catchall"
+[ 77854.364] (II) Using input driver 'libinput' for 'serio13'
+[ 77854.364] (**) serio13: always reports core events
+[ 77854.364] (**) Option "Device" "/dev/input/event17"
+[ 77854.364] (**) Option "_source" "server/udev"
+[ 77854.366] (II) event17 - serio13: is tagged by udev as: Keyboard
+[ 77854.366] (II) event17 - serio13: device is a keyboard
+[ 77854.366] (II) event17 - serio13: device removed
+[ 77854.375] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/tty/ttyACM0/serio13/rc/rc0/input41/event17"
+[ 77854.375] (II) XINPUT: Adding extended input device "serio13" (type: KEYBOARD, id 10)
+[ 77854.375] (**) Option "xkb_model" "pc105"
+[ 77854.375] (**) Option "xkb_layout" "us"
+[ 77854.375] (WW) Option "xkb_variant" requires a string value
+[ 77854.375] (WW) Option "xkb_options" requires a string value
+[ 77854.377] (II) event17 - serio13: is tagged by udev as: Keyboard
+[ 77854.378] (II) event17 - serio13: device is a keyboard
+[ 77875.697] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 77875.697] (II) modeset(0): Printing DDC gathered Modelines:
+[ 77875.697] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 77876.295] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 77877.173] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 77883.094] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 77883.094] (II) modeset(0): Printing DDC gathered Modelines:
+[ 77883.094] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 77884.250] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 77892.255] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 77892.255] (II) modeset(0): Printing DDC gathered Modelines:
+[ 77892.255] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 77892.589] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 77893.419] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 77899.589] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 77899.589] (II) modeset(0): Printing DDC gathered Modelines:
+[ 77899.589] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 77900.717] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 77963.554] (II) config/udev: removing device serio13
+[ 77963.554] (II) event17 - serio13: device removed
+[ 77963.565] (II) UnloadModule: "libinput"
+[ 77970.162] (II) config/udev: removing device Pulse-Eight CEC Adapter
+[ 77970.162] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[ 77970.174] (II) UnloadModule: "libinput"
+[ 77973.982] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/mouse0)
+[ 77973.982] (II) No input driver specified, ignoring this device.
+[ 77973.982] (II) This device may have been added with another device file.
+[ 77974.061] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/event6)
+[ 77974.061] (**) Pulse-Eight CEC Adapter: Applying InputClass "libinput pointer catchall"
+[ 77974.061] (II) Using input driver 'libinput' for 'Pulse-Eight CEC Adapter'
+[ 77974.061] (**) Pulse-Eight CEC Adapter: always reports core events
+[ 77974.061] (**) Option "Device" "/dev/input/event6"
+[ 77974.061] (**) Option "_source" "server/udev"
+[ 77974.116] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[ 77974.116] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[ 77974.117] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[ 77974.134] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.2/0003:2548:1002.000C/input/input42/event6"
+[ 77974.134] (II) XINPUT: Adding extended input device "Pulse-Eight CEC Adapter" (type: MOUSE, id 9)
+[ 77974.135] (**) Option "AccelerationScheme" "none"
+[ 77974.136] (**) Pulse-Eight CEC Adapter: (accel) selected scheme none/0
+[ 77974.136] (**) Pulse-Eight CEC Adapter: (accel) acceleration factor: 2.000
+[ 77974.136] (**) Pulse-Eight CEC Adapter: (accel) acceleration threshold: 4
+[ 77974.191] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[ 77974.191] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[ 77974.194] (II) config/udev: Adding input device serio14 (/dev/input/event17)
+[ 77974.194] (**) serio14: Applying InputClass "libinput keyboard catchall"
+[ 77974.194] (II) Using input driver 'libinput' for 'serio14'
+[ 77974.194] (**) serio14: always reports core events
+[ 77974.194] (**) Option "Device" "/dev/input/event17"
+[ 77974.194] (**) Option "_source" "server/udev"
+[ 77974.199] (II) event17 - serio14: is tagged by udev as: Keyboard
+[ 77974.199] (II) event17 - serio14: device is a keyboard
+[ 77974.200] (II) event17 - serio14: device removed
+[ 77974.211] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/tty/ttyACM0/serio14/rc/rc0/input43/event17"
+[ 77974.211] (II) XINPUT: Adding extended input device "serio14" (type: KEYBOARD, id 10)
+[ 77974.211] (**) Option "xkb_model" "pc105"
+[ 77974.211] (**) Option "xkb_layout" "us"
+[ 77974.211] (WW) Option "xkb_variant" requires a string value
+[ 77974.211] (WW) Option "xkb_options" requires a string value
+[ 77974.216] (II) event17 - serio14: is tagged by udev as: Keyboard
+[ 77974.216] (II) event17 - serio14: device is a keyboard
+[ 77993.113] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 77993.113] (II) modeset(0): Printing DDC gathered Modelines:
+[ 77993.113] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 77993.450] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 77994.265] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 78084.447] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78084.447] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78084.447] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78085.516] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 78098.033] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78098.033] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78098.033] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78098.368] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 78099.229] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 78192.777] (II) config/udev: removing device serio14
+[ 78192.777] (II) event17 - serio14: device removed
+[ 78192.794] (II) UnloadModule: "libinput"
+[ 78197.693] (II) config/udev: removing device Pulse-Eight CEC Adapter
+[ 78197.718] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[ 78197.739] (II) UnloadModule: "libinput"
+[ 78201.274] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/mouse0)
+[ 78201.274] (II) No input driver specified, ignoring this device.
+[ 78201.274] (II) This device may have been added with another device file.
+[ 78201.354] (II) config/udev: Adding input device Pulse-Eight CEC Adapter (/dev/input/event6)
+[ 78201.354] (**) Pulse-Eight CEC Adapter: Applying InputClass "libinput pointer catchall"
+[ 78201.354] (II) Using input driver 'libinput' for 'Pulse-Eight CEC Adapter'
+[ 78201.354] (**) Pulse-Eight CEC Adapter: always reports core events
+[ 78201.354] (**) Option "Device" "/dev/input/event6"
+[ 78201.354] (**) Option "_source" "server/udev"
+[ 78201.410] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[ 78201.410] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[ 78201.411] (II) event6  - Pulse-Eight CEC Adapter: device removed
+[ 78201.437] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.2/0003:2548:1002.000D/input/input44/event6"
+[ 78201.437] (II) XINPUT: Adding extended input device "Pulse-Eight CEC Adapter" (type: MOUSE, id 9)
+[ 78201.438] (**) Option "AccelerationScheme" "none"
+[ 78201.439] (**) Pulse-Eight CEC Adapter: (accel) selected scheme none/0
+[ 78201.439] (**) Pulse-Eight CEC Adapter: (accel) acceleration factor: 2.000
+[ 78201.439] (**) Pulse-Eight CEC Adapter: (accel) acceleration threshold: 4
+[ 78201.494] (II) event6  - Pulse-Eight CEC Adapter: is tagged by udev as: Mouse
+[ 78201.494] (II) event6  - Pulse-Eight CEC Adapter: device is a pointer
+[ 78201.497] (II) config/udev: Adding input device serio15 (/dev/input/event17)
+[ 78201.497] (**) serio15: Applying InputClass "libinput keyboard catchall"
+[ 78201.497] (II) Using input driver 'libinput' for 'serio15'
+[ 78201.497] (**) serio15: always reports core events
+[ 78201.497] (**) Option "Device" "/dev/input/event17"
+[ 78201.497] (**) Option "_source" "server/udev"
+[ 78201.502] (II) event17 - serio15: is tagged by udev as: Keyboard
+[ 78201.502] (II) event17 - serio15: device is a keyboard
+[ 78201.503] (II) event17 - serio15: device removed
+[ 78201.517] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/tty/ttyACM0/serio15/rc/rc0/input45/event17"
+[ 78201.517] (II) XINPUT: Adding extended input device "serio15" (type: KEYBOARD, id 10)
+[ 78201.517] (**) Option "xkb_model" "pc105"
+[ 78201.517] (**) Option "xkb_layout" "us"
+[ 78201.517] (WW) Option "xkb_variant" requires a string value
+[ 78201.517] (WW) Option "xkb_options" requires a string value
+[ 78201.522] (II) event17 - serio15: is tagged by udev as: Keyboard
+[ 78201.522] (II) event17 - serio15: device is a keyboard
+[ 78213.346] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78213.346] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78213.346] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78214.434] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 78226.951] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78226.951] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78226.951] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78227.287] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 78228.166] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 78277.188] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78277.188] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78277.188] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78278.321] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 78286.362] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78286.362] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78286.362] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78286.697] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 78287.575] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 78295.348] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78295.348] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78295.348] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78296.435] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 78304.505] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78304.505] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78304.505] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78304.840] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 78305.700] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 78352.203] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78352.203] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78352.203] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78353.314] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 78361.371] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78361.371] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78361.371] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78361.706] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 78362.580] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 78368.424] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78368.424] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78368.424] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78369.512] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 78377.605] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78377.605] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78377.605] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78377.941] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 78378.771] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 78384.669] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78384.669] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78384.669] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78385.788] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 78394.096] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78394.096] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78394.096] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78394.690] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 78395.570] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 78444.790] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78444.790] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78444.790] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78445.880] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 78453.945] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78453.945] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78453.945] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78454.281] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 78455.157] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 78464.542] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78464.542] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78464.542] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78465.678] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 78473.963] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78473.963] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78473.963] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78474.299] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 78475.176] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 78525.923] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78525.923] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78525.923] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78527.030] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 78535.100] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78535.100] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78535.100] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78535.436] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 78536.241] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 78548.356] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78548.356] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78548.356] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78549.443] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 78561.941] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78561.941] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78561.941] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78562.276] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 78563.155] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 78574.565] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78574.565] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78574.565] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78575.706] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 78588.167] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78588.167] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78588.167] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78588.503] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 78589.308] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 78641.884] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78641.884] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78641.884] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78642.953] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 78655.433] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78655.433] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78655.433] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78655.768] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 78656.628] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 78706.340] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78706.340] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78706.340] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78707.427] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 78720.183] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78720.183] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78720.183] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78720.776] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 78721.633] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 78733.986] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78733.986] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78733.986] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78735.098] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 78747.830] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78747.830] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78747.830] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78748.166] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 78749.028] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 78765.426] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78765.426] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78765.426] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78766.517] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 78779.033] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78779.033] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78779.033] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78779.370] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 78780.241] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 78833.447] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78833.447] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78833.447] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78834.517] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 78851.444] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78851.444] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78851.444] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78851.780] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 78852.640] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 78869.513] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78869.513] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78869.513] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78870.652] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 78887.543] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78887.543] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78887.543] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78887.879] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 78888.739] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 78936.478] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78936.478] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78936.478] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78937.596] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 78954.489] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 78954.489] (II) modeset(0): Printing DDC gathered Modelines:
+[ 78954.489] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 78954.825] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 78955.684] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 79147.422] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79147.422] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79147.422] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79148.512] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 79161.002] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79161.002] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79161.002] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79161.337] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 79162.216] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 79168.120] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79168.120] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79168.120] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79169.249] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 79177.275] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79177.275] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79177.275] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79177.610] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 79178.427] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 79184.695] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79184.695] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79184.695] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79185.827] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 79193.869] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79193.869] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79193.869] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79194.207] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 79195.068] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 79205.712] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79205.712] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79205.712] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79206.827] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 79214.870] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79214.870] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79214.870] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79215.205] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 79216.064] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 79227.200] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79227.200] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79227.200] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79228.316] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 79236.354] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79236.354] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79236.354] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79236.689] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 79237.562] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 79248.981] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79248.981] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79248.981] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79250.115] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 79258.142] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79258.142] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79258.142] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79258.476] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 79259.281] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 79308.283] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79308.283] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79308.283] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79309.351] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 79317.457] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79317.457] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79317.457] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79317.793] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 79318.659] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 79326.944] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79326.944] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79326.944] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79328.034] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 79336.108] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79336.108] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79336.108] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79336.444] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 79337.271] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 79386.976] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79386.976] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79386.976] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79388.115] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 79396.138] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79396.138] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79396.138] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79396.473] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 79397.282] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 79449.733] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79449.733] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79449.733] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79450.827] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 79459.162] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79459.162] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79459.162] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79459.497] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 79460.316] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 79510.506] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79510.506] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79510.506] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79511.646] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 79524.086] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79524.086] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79524.086] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79524.421] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 79525.239] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 79573.820] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79573.820] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79573.821] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79574.909] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 79587.400] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79587.400] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79587.400] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79587.736] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 79588.617] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 79637.896] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79637.896] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79637.896] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79638.965] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 79651.477] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79651.477] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79651.477] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79651.812] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 79652.666] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 79703.092] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79703.092] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79703.092] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79704.249] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 79716.657] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79716.657] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79716.657] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79717.250] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 79718.115] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 79766.974] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79766.974] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79766.974] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79768.115] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 79780.576] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79780.576] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79780.576] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79780.912] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 79781.743] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 79796.010] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79796.010] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79796.010] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79797.131] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 79814.279] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79814.279] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79814.279] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79814.614] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 79815.428] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 79834.672] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79834.672] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79834.672] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79835.791] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 79852.685] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79852.685] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79852.685] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79853.021] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 79853.830] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 79901.975] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79901.975] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79901.975] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79903.099] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 79920.246] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79920.246] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79920.246] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79920.581] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 79921.409] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 79928.145] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79928.145] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79928.145] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79929.287] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[ 79955.264] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79955.264] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79955.264] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79955.599] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[ 79956.425] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[ 79964.166] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[ 79964.166] (II) modeset(0): Printing DDC gathered Modelines:
+[ 79964.166] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[ 79965.303] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[244829.768] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[244829.768] (II) modeset(0): Printing DDC gathered Modelines:
+[244829.768] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[244854.926] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[244854.926] (II) modeset(0): Printing DDC gathered Modelines:
+[244854.926] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[244862.679] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[244862.679] (II) modeset(0): Printing DDC gathered Modelines:
+[244862.679] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[251356.090] (EE) event15 - Synaptics TM3289-021: kernel bug: Touch jump detected and discarded.
+See https://wayland.freedesktop.org/libinput/doc/1.14.3/touchpad-jumping-cursors.html for details
+[251356.764] (EE) event15 - Synaptics TM3289-021: kernel bug: Touch jump detected and discarded.
+See https://wayland.freedesktop.org/libinput/doc/1.14.3/touchpad-jumping-cursors.html for details
+[251381.276] (EE) event15 - Synaptics TM3289-021: kernel bug: Touch jump detected and discarded.
+See https://wayland.freedesktop.org/libinput/doc/1.14.3/touchpad-jumping-cursors.html for details
+[251381.334] (EE) event15 - Synaptics TM3289-021: kernel bug: Touch jump detected and discarded.
+See https://wayland.freedesktop.org/libinput/doc/1.14.3/touchpad-jumping-cursors.html for details
+[256669.045] (EE) event15 - Synaptics TM3289-021: kernel bug: Touch jump detected and discarded.
+See https://wayland.freedesktop.org/libinput/doc/1.14.3/touchpad-jumping-cursors.html for details
+[259363.543] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[259363.543] (II) modeset(0): Printing DDC gathered Modelines:
+[259363.543] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[259363.878] (--) modeset(0): HDMI max TMDS frequency 300000KHz
+[259368.816] (II) modeset(0): Allocate new frame buffer 5760x2160 stride
+[259466.484] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[259466.484] (II) modeset(0): Printing DDC gathered Modelines:
+[259466.484] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[259467.567] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
+[259508.601] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[259508.601] (II) modeset(0): Printing DDC gathered Modelines:
+[259508.601] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[259508.936] (--) modeset(0): HDMI max TMDS frequency 150000KHz
+[259509.763] (II) modeset(0): Allocate new frame buffer 3840x1080 stride
+[273910.770] (II) modeset(0): EDID vendor "AUO", prod id 12605
+[273910.770] (II) modeset(0): Printing DDC gathered Modelines:
+[273910.770] (II) modeset(0): Modeline "1920x1080"x0.0  141.00  1920 1936 1952 2104  1080 1083 1097 1116 -hsync -vsync (67.0 kHz eP)
+[273911.866] (II) modeset(0): Allocate new frame buffer 1920x1080 stride
diff --git a/test/xrandr.test b/test/xrandr.test
new file mode 100644
index 0000000..ba90e3a
--- /dev/null
+++ b/test/xrandr.test
@@ -0,0 +1,279 @@
+Screen 0: minimum 8 x 8, current 3840 x 2160, maximum 16384 x 16384
+DVI-I-0 disconnected (normal left inverted right x axis y axis)
+	Identifier: 0x1be
+	Timestamp:  99649
+	Subpixel:   unknown
+	Clones:    
+	CRTCs:      0 1 2 3
+	Transform:  1.000000 0.000000 0.000000
+	            0.000000 1.000000 0.000000
+	            0.000000 0.000000 1.000000
+	           filter: 
+	CscMatrix: 65536 0 0 0 0 65536 0 0 0 0 65536 0 
+	BorderDimensions: 4 
+		supported: 4
+	Border: 0 0 0 0 
+		range: (0, 65535)
+	SignalFormat: VGA 
+		supported: VGA
+	ConnectorType: DVI-I 
+	ConnectorNumber: 0 
+	_ConnectorLocation: 0 
+	non-desktop: 0 
+		supported: 0, 1
+DVI-I-1 disconnected (normal left inverted right x axis y axis)
+	Identifier: 0x1bf
+	Timestamp:  99649
+	Subpixel:   unknown
+	Clones:    
+	CRTCs:      0 1 2 3
+	Transform:  1.000000 0.000000 0.000000
+	            0.000000 1.000000 0.000000
+	            0.000000 0.000000 1.000000
+	           filter: 
+	CscMatrix: 65536 0 0 0 0 65536 0 0 0 0 65536 0 
+	BorderDimensions: 4 
+		supported: 4
+	Border: 0 0 0 0 
+		range: (0, 65535)
+	SignalFormat: TMDS 
+		supported: TMDS
+	ConnectorType: DVI-I 
+	ConnectorNumber: 0 
+	_ConnectorLocation: 0 
+	non-desktop: 0 
+		supported: 0, 1
+DP-0 disconnected (normal left inverted right x axis y axis)
+	Identifier: 0x1c0
+	Timestamp:  99649
+	Subpixel:   unknown
+	Clones:    
+	CRTCs:      0 1 2 3
+	Transform:  1.000000 0.000000 0.000000
+	            0.000000 1.000000 0.000000
+	            0.000000 0.000000 1.000000
+	           filter: 
+	CscMatrix: 65536 0 0 0 0 65536 0 0 0 0 65536 0 
+	BorderDimensions: 4 
+		supported: 4
+	Border: 0 0 0 0 
+		range: (0, 65535)
+	SignalFormat: DisplayPort 
+		supported: DisplayPort
+	ConnectorType: DisplayPort 
+	ConnectorNumber: 1 
+	_ConnectorLocation: 1 
+	non-desktop: 0 
+		supported: 0, 1
+DP-1 disconnected (normal left inverted right x axis y axis)
+	Identifier: 0x1c1
+	Timestamp:  99649
+	Subpixel:   unknown
+	Clones:    
+	CRTCs:      0 1 2 3
+	Transform:  1.000000 0.000000 0.000000
+	            0.000000 1.000000 0.000000
+	            0.000000 0.000000 1.000000
+	           filter: 
+	CscMatrix: 65536 0 0 0 0 65536 0 0 0 0 65536 0 
+	BorderDimensions: 4 
+		supported: 4
+	Border: 0 0 0 0 
+		range: (0, 65535)
+	SignalFormat: TMDS 
+		supported: TMDS
+	ConnectorType: DisplayPort 
+	ConnectorNumber: 1 
+	_ConnectorLocation: 1 
+	non-desktop: 0 
+		supported: 0, 1
+HDMI-0 connected primary 3840x2160+0+0 (0x1c3) normal (normal left inverted right x axis y axis) 1872mm x 1053mm
+	Identifier: 0x1c2
+	Timestamp:  99649
+	Subpixel:   unknown
+	Gamma:      1.0:1.0:1.0
+	Brightness: 1.0
+	Clones:    
+	CRTC:       0
+	CRTCs:      0 1 2 3
+	Transform:  1.000000 0.000000 0.000000
+	            0.000000 1.000000 0.000000
+	            0.000000 0.000000 1.000000
+	           filter: 
+	CscMatrix: 65536 0 0 0 0 65536 0 0 0 0 65536 0 
+	EDID: 
+		00ffffffffffff004c2d010c01060001
+		2a18010380693b780a23ada4544d9926
+		0f474abdef80714f81c0810081809500
+		a9c0b300010108e80030f2705a80b058
+		8a00501d7400001e023a801871382d40
+		582c4500501d7400001e000000fd0018
+		4b0f873c000a202020202020000000fc
+		0053414d53554e470a20202020200156
+		020358f15761101f041305142021225d
+		5e5f6065666263640716031229090707
+		1507503d04c083010000e2000fe305c0
+		0076030c001000b83c21d08801020304
+		01403fff5060809067d85dc401788003
+		e3060501e30f01e0011d80d0721c1620
+		102c2580501d7400009e662156aa5100
+		1e30468f3300501d7400001e000000a6
+	BorderDimensions: 4 
+		supported: 4
+	Border: 0 0 0 0 
+		range: (0, 65535)
+	SignalFormat: TMDS 
+		supported: TMDS
+	ConnectorType: HDMI 
+	ConnectorNumber: 2 
+	_ConnectorLocation: 2 
+	non-desktop: 0 
+		supported: 0, 1
+  3840x2160 (0x1c3) 594.000MHz +HSync +VSync *current +preferred
+        h: width  3840 start 4016 end 4104 total 4400 skew    0 clock 135.00KHz
+        v: height 2160 start 2168 end 2178 total 2250           clock  60.00Hz
+  4096x2160 (0x1c4) 593.410MHz +HSync +VSync
+        h: width  4096 start 4184 end 4272 total 4400 skew    0 clock 134.87KHz
+        v: height 2160 start 2168 end 2178 total 2250           clock  59.94Hz
+  4096x2160 (0x1c5) 594.000MHz +HSync +VSync
+        h: width  4096 start 5064 end 5152 total 5280 skew    0 clock 112.50KHz
+        v: height 2160 start 2168 end 2178 total 2250           clock  50.00Hz
+  4096x2160 (0x1c6) 296.700MHz +HSync +VSync
+        h: width  4096 start 4184 end 4272 total 4400 skew    0 clock  67.43KHz
+        v: height 2160 start 2168 end 2178 total 2250           clock  29.97Hz
+  4096x2160 (0x1c7) 297.000MHz +HSync +VSync
+        h: width  4096 start 5064 end 5152 total 5280 skew    0 clock  56.25KHz
+        v: height 2160 start 2168 end 2178 total 2250           clock  25.00Hz
+  4096x2160 (0x1c8) 297.000MHz +HSync +VSync
+        h: width  4096 start 5116 end 5204 total 5500 skew    0 clock  54.00KHz
+        v: height 2160 start 2168 end 2178 total 2250           clock  24.00Hz
+  4096x2160 (0x1c9) 296.750MHz +HSync +VSync
+        h: width  4096 start 5116 end 5204 total 5500 skew    0 clock  53.95KHz
+        v: height 2160 start 2168 end 2178 total 2250           clock  23.98Hz
+  3840x2160 (0x1ca) 593.410MHz +HSync +VSync
+        h: width  3840 start 4016 end 4104 total 4400 skew    0 clock 134.87KHz
+        v: height 2160 start 2168 end 2178 total 2250           clock  59.94Hz
+  3840x2160 (0x1cb) 594.000MHz +HSync +VSync
+        h: width  3840 start 4896 end 4984 total 5280 skew    0 clock 112.50KHz
+        v: height 2160 start 2168 end 2178 total 2250           clock  50.00Hz
+  3840x2160 (0x1cc) 296.700MHz +HSync +VSync
+        h: width  3840 start 4016 end 4104 total 4400 skew    0 clock  67.43KHz
+        v: height 2160 start 2168 end 2178 total 2250           clock  29.97Hz
+  3840x2160 (0x1cd) 297.000MHz +HSync +VSync
+        h: width  3840 start 4896 end 4984 total 5280 skew    0 clock  56.25KHz
+        v: height 2160 start 2168 end 2178 total 2250           clock  25.00Hz
+  3840x2160 (0x1ce) 296.750MHz +HSync +VSync
+        h: width  3840 start 5116 end 5204 total 5500 skew    0 clock  53.95KHz
+        v: height 2160 start 2168 end 2178 total 2250           clock  23.98Hz
+  1920x1080 (0x1cf) 148.500MHz +HSync +VSync
+        h: width  1920 start 2008 end 2052 total 2200 skew    0 clock  67.50KHz
+        v: height 1080 start 1084 end 1089 total 1125           clock  60.00Hz
+  1920x1080 (0x1d0) 148.350MHz +HSync +VSync
+        h: width  1920 start 2008 end 2052 total 2200 skew    0 clock  67.43KHz
+        v: height 1080 start 1084 end 1089 total 1125           clock  59.94Hz
+  1920x1080 (0x1d1) 148.500MHz +HSync +VSync
+        h: width  1920 start 2448 end 2492 total 2640 skew    0 clock  56.25KHz
+        v: height 1080 start 1084 end 1089 total 1125           clock  50.00Hz
+  1920x1080 (0x1d2) 74.180MHz +HSync +VSync
+        h: width  1920 start 2008 end 2052 total 2200 skew    0 clock  33.72KHz
+        v: height 1080 start 1084 end 1089 total 1125           clock  29.97Hz
+  1920x1080 (0x1d3) 74.250MHz +HSync +VSync
+        h: width  1920 start 2448 end 2492 total 2640 skew    0 clock  28.12KHz
+        v: height 1080 start 1084 end 1089 total 1125           clock  25.00Hz
+  1920x1080 (0x1d4) 74.180MHz +HSync +VSync
+        h: width  1920 start 2558 end 2602 total 2750 skew    0 clock  26.97KHz
+        v: height 1080 start 1084 end 1089 total 1125           clock  23.98Hz
+  1920x1080 (0x1d5) 74.180MHz +HSync +VSync Interlace
+        h: width  1920 start 2008 end 2052 total 2200 skew    0 clock  33.72KHz
+        v: height 1080 start 1084 end 1094 total 1124           clock  60.00Hz
+  1920x1080 (0x1d6) 74.250MHz +HSync +VSync Interlace
+        h: width  1920 start 2448 end 2492 total 2640 skew    0 clock  28.12KHz
+        v: height 1080 start 1084 end 1094 total 1124           clock  50.04Hz
+  1680x1050 (0x1d7) 146.250MHz -HSync +VSync
+        h: width  1680 start 1784 end 1960 total 2240 skew    0 clock  65.29KHz
+        v: height 1050 start 1053 end 1059 total 1089           clock  59.95Hz
+  1600x900 (0x1d8) 108.000MHz +HSync +VSync
+        h: width  1600 start 1624 end 1704 total 1800 skew    0 clock  60.00KHz
+        v: height  900 start  901 end  904 total 1000           clock  60.00Hz
+  1440x900 (0x1d9) 106.500MHz -HSync +VSync
+        h: width  1440 start 1520 end 1672 total 1904 skew    0 clock  55.93KHz
+        v: height  900 start  903 end  909 total  934           clock  59.89Hz
+  1366x768 (0x1da) 85.500MHz +HSync +VSync
+        h: width  1366 start 1436 end 1579 total 1792 skew    0 clock  47.71KHz
+        v: height  768 start  771 end  774 total  798           clock  59.79Hz
+  1280x1024 (0x1db) 135.000MHz +HSync +VSync
+        h: width  1280 start 1296 end 1440 total 1688 skew    0 clock  79.98KHz
+        v: height 1024 start 1025 end 1028 total 1066           clock  75.02Hz
+  1280x1024 (0x1dc) 108.000MHz +HSync +VSync
+        h: width  1280 start 1328 end 1440 total 1688 skew    0 clock  63.98KHz
+        v: height 1024 start 1025 end 1028 total 1066           clock  60.02Hz
+  1280x800 (0x1dd) 83.500MHz -HSync +VSync
+        h: width  1280 start 1352 end 1480 total 1680 skew    0 clock  49.70KHz
+        v: height  800 start  803 end  809 total  831           clock  59.81Hz
+  1280x720 (0x1de) 74.250MHz +HSync +VSync
+        h: width  1280 start 1390 end 1430 total 1650 skew    0 clock  45.00KHz
+        v: height  720 start  725 end  730 total  750           clock  60.00Hz
+  1280x720 (0x1df) 74.180MHz +HSync +VSync
+        h: width  1280 start 1390 end 1430 total 1650 skew    0 clock  44.96KHz
+        v: height  720 start  725 end  730 total  750           clock  59.94Hz
+  1280x720 (0x1e0) 74.250MHz +HSync +VSync
+        h: width  1280 start 1720 end 1760 total 1980 skew    0 clock  37.50KHz
+        v: height  720 start  725 end  730 total  750           clock  50.00Hz
+  1152x864 (0x1e1) 108.000MHz +HSync +VSync
+        h: width  1152 start 1216 end 1344 total 1600 skew    0 clock  67.50KHz
+        v: height  864 start  865 end  868 total  900           clock  75.00Hz
+  1024x768 (0x1e2) 78.750MHz +HSync +VSync
+        h: width  1024 start 1040 end 1136 total 1312 skew    0 clock  60.02KHz
+        v: height  768 start  769 end  772 total  800           clock  75.03Hz
+  1024x768 (0x1e3) 75.000MHz -HSync -VSync
+        h: width  1024 start 1048 end 1184 total 1328 skew    0 clock  56.48KHz
+        v: height  768 start  771 end  777 total  806           clock  70.07Hz
+  1024x768 (0x1e4) 65.000MHz -HSync -VSync
+        h: width  1024 start 1048 end 1184 total 1344 skew    0 clock  48.36KHz
+        v: height  768 start  771 end  777 total  806           clock  60.00Hz
+  800x600 (0x1e5) 49.500MHz +HSync +VSync
+        h: width   800 start  816 end  896 total 1056 skew    0 clock  46.88KHz
+        v: height  600 start  601 end  604 total  625           clock  75.00Hz
+  800x600 (0x1e6) 50.000MHz +HSync +VSync
+        h: width   800 start  856 end  976 total 1040 skew    0 clock  48.08KHz
+        v: height  600 start  637 end  643 total  666           clock  72.19Hz
+  800x600 (0x1e7) 40.000MHz +HSync +VSync
+        h: width   800 start  840 end  968 total 1056 skew    0 clock  37.88KHz
+        v: height  600 start  601 end  605 total  628           clock  60.32Hz
+  720x576 (0x1e8) 27.000MHz -HSync -VSync
+        h: width   720 start  732 end  796 total  864 skew    0 clock  31.25KHz
+        v: height  576 start  581 end  586 total  625           clock  50.00Hz
+  720x480 (0x1e9) 27.000MHz -HSync -VSync
+        h: width   720 start  736 end  798 total  858 skew    0 clock  31.47KHz
+        v: height  480 start  489 end  495 total  525           clock  59.94Hz
+  640x480 (0x1ea) 31.500MHz -HSync -VSync
+        h: width   640 start  656 end  720 total  840 skew    0 clock  37.50KHz
+        v: height  480 start  481 end  484 total  500           clock  75.00Hz
+  640x480 (0x1eb) 31.500MHz -HSync -VSync
+        h: width   640 start  656 end  696 total  832 skew    0 clock  37.86KHz
+        v: height  480 start  481 end  484 total  520           clock  72.81Hz
+  640x480 (0x1ec) 25.175MHz -HSync -VSync
+        h: width   640 start  656 end  752 total  800 skew    0 clock  31.47KHz
+        v: height  480 start  490 end  492 total  525           clock  59.94Hz
+DVI-D-0 disconnected (normal left inverted right x axis y axis)
+	Identifier: 0x1ed
+	Timestamp:  99649
+	Subpixel:   unknown
+	Clones:    
+	CRTCs:      0 1 2 3
+	Transform:  1.000000 0.000000 0.000000
+	            0.000000 1.000000 0.000000
+	            0.000000 0.000000 1.000000
+	           filter: 
+	CscMatrix: 65536 0 0 0 0 65536 0 0 0 0 65536 0 
+	BorderDimensions: 4 
+		supported: 4
+	Border: 0 0 0 0 
+		range: (0, 65535)
+	SignalFormat: TMDS 
+		supported: TMDS
+	ConnectorType: DVI-D 
+	ConnectorNumber: 3 
+	_ConnectorLocation: 3 
+	non-desktop: 0 
+		supported: 0, 1
diff --git a/vs/edid-decode.sln b/vs/edid-decode.sln
new file mode 100644
index 0000000..53fc406
--- /dev/null
+++ b/vs/edid-decode.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30011.22
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "edid-decode", "edid-decode.vcxproj", "{245F601B-02E4-43DF-B64C-B49088673764}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|x64 = Debug|x64
+		Release|x64 = Release|x64
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{245F601B-02E4-43DF-B64C-B49088673764}.Debug|x64.ActiveCfg = Debug|x64
+		{245F601B-02E4-43DF-B64C-B49088673764}.Debug|x64.Build.0 = Debug|x64
+		{245F601B-02E4-43DF-B64C-B49088673764}.Release|x64.ActiveCfg = Release|x64
+		{245F601B-02E4-43DF-B64C-B49088673764}.Release|x64.Build.0 = Release|x64
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {DDBA565E-4EC9-46DF-88E0-12F489BB3FCF}
+	EndGlobalSection
+EndGlobal
diff --git a/vs/edid-decode.vcxproj b/vs/edid-decode.vcxproj
new file mode 100644
index 0000000..c9213ab
--- /dev/null
+++ b/vs/edid-decode.vcxproj
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>16.0</VCProjectVersion>
+    <ProjectGuid>{245F601B-02E4-43DF-B64C-B49088673764}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>ediddecode</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v142</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v142</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <DisableSpecificWarnings>4244; 4018; 4267; 4996; 26451; 6385; 6001</DisableSpecificWarnings>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+    <PostBuildEvent>
+      <Command>
+      </Command>
+    </PostBuildEvent>
+    <PostBuildEvent>
+      <Message>
+      </Message>
+    </PostBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <DisableSpecificWarnings>4244; 4018; 4267; 4996; 26451; 6385; 6001</DisableSpecificWarnings>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="getopt.c" />
+    <ClCompile Include="..\edid-decode.cpp" />
+    <ClCompile Include="..\parse-base-block.cpp" />
+    <ClCompile Include="..\parse-cta-block.cpp" />
+    <ClCompile Include="..\parse-di-ext-block.cpp" />
+    <ClCompile Include="..\parse-displayid-block.cpp" />
+    <ClCompile Include="..\parse-ls-ext-block.cpp" />
+    <ClCompile Include="..\parse-vtb-ext-block.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="getopt.h" />
+    <ClInclude Include="unistd.h" />
+    <ClInclude Include="..\edid-decode.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/vs/edid-decode.vcxproj.filters b/vs/edid-decode.vcxproj.filters
new file mode 100644
index 0000000..68e8b7d
--- /dev/null
+++ b/vs/edid-decode.vcxproj.filters
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="windows-unix">
+      <UniqueIdentifier>{757b13a8-3e1d-43af-acf1-d03963acb2e6}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="edid-decode">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\parse-base-block.cpp">
+      <Filter>edid-decode</Filter>
+    </ClCompile>
+    <ClCompile Include="..\parse-cta-block.cpp">
+      <Filter>edid-decode</Filter>
+    </ClCompile>
+    <ClCompile Include="..\parse-di-ext-block.cpp">
+      <Filter>edid-decode</Filter>
+    </ClCompile>
+    <ClCompile Include="..\parse-displayid-block.cpp">
+      <Filter>edid-decode</Filter>
+    </ClCompile>
+    <ClCompile Include="..\parse-ls-ext-block.cpp">
+      <Filter>edid-decode</Filter>
+    </ClCompile>
+    <ClCompile Include="..\parse-vtb-ext-block.cpp">
+      <Filter>edid-decode</Filter>
+    </ClCompile>
+    <ClCompile Include="getopt.c">
+      <Filter>windows-unix</Filter>
+    </ClCompile>
+    <ClCompile Include="..\edid-decode.cpp">
+      <Filter>edid-decode</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\edid-decode.h">
+      <Filter>edid-decode</Filter>
+    </ClInclude>
+    <ClInclude Include="getopt.h">
+      <Filter>windows-unix</Filter>
+    </ClInclude>
+    <ClInclude Include="unistd.h">
+      <Filter>windows-unix</Filter>
+    </ClInclude>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/vs/getopt.c b/vs/getopt.c
new file mode 100644
index 0000000..d5868a5
--- /dev/null
+++ b/vs/getopt.c
@@ -0,0 +1,787 @@
+/**
+ * @file getopt.c
+ * @copy 2012 MinGW.org project
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Implementation of the `getopt', `getopt_long' and `getopt_long_only'
+ * APIs, for inclusion in the MinGW runtime library.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <getopt.h>
+
+/* Identify how to get the calling program name, for use in messages...
+ */
+#ifdef __CYGWIN__
+/*
+ * CYGWIN uses this DLL reference...
+ */
+# define PROGNAME  __progname
+extern char __declspec(dllimport) *__progname;
+#else
+/*
+ * ...while elsewhere, we simply use the first argument passed.
+ */
+# define PROGNAME  *argv
+# define __inline__ __inline
+#endif
+
+/* Initialise the public variables. */
+
+int optind = 1;				/* index for first non-option arg     */
+int opterr = 1;				/* enable built-in error messages     */
+
+char *optarg = NULL;			/* pointer to current option argument */
+
+#define CHAR  char			/* argument type selector */
+
+#define getopt_switchar         '-'	/* option prefix character in argv    */
+#define getopt_pluschar         '+'	/* prefix for POSIX mode in optstring */
+#define getopt_takes_argument   ':'	/* marker for optarg in optstring     */
+#define getopt_arg_assign       '='     /* longopt argument field separator   */
+#define getopt_unknown          '?'	/* return code for unmatched option   */
+#define getopt_ordered           1      /* return code for ordered non-option */
+
+#define getopt_all_done         -1	/* return code to indicate completion */
+
+enum
+{ /* All `getopt' API functions are implemented via calls to the
+   * common static function `getopt_parse()'; these `mode' selectors
+   * determine the behaviour of `getopt_parse()', to deliver the
+   * appropriate result in each case.
+   */
+  getopt_mode_standard = 0,	/* getopt()	      */
+  getopt_mode_long,		/* getopt_long()      */
+  getopt_mode_long_only		/* getopt_long_only() */
+};
+
+enum
+{ /* When attempting to match a command line argument to a long form option,
+   * these indicate the status of the match.
+   */
+  getopt_no_match = 0,		/* no successful match			     */
+  getopt_abbreviated_match,	/* argument is an abbreviation for an option */
+  getopt_exact_match		/* argument matches the full option name     */
+};
+
+int optopt = getopt_unknown;	/* return value for option being evaluated   */
+
+/* Some BSD applications expect to be able to reinitialise `getopt' parsing
+ * by setting a global variable called `optreset'.  We provide an obfuscated
+ * API, which allows applications to emulate this brain damage; however, any
+ * use of this is non-portable, and is strongly discouraged.
+ */
+#define optreset  __mingw_optreset
+int optreset = 0;
+
+static __inline__
+int getopt_missing_arg( const CHAR *optstring )
+{
+  /* Helper function to determine the appropriate return value,
+   * for the case where a required option argument is missing.
+   */
+  if( (*optstring == getopt_pluschar) || (*optstring == getopt_switchar) )
+    ++optstring;
+  return (*optstring == getopt_takes_argument)
+    ? getopt_takes_argument
+    : getopt_unknown;
+}
+
+/* `complain' macro facilitates the generation of simple built-in
+ * error messages, displayed on various fault conditions, provided
+ * `opterr' is non-zero.
+ */
+#define	complain( MSG, ARG )  if( opterr ) \
+  fprintf( stderr, "%s: "MSG"\n", PROGNAME, ARG )
+
+static __inline__
+int getopt_argerror( int mode, char *fmt, CHAR *prog, struct option *opt, int retval )
+{
+  /* Helper function, to generate more complex built-in error
+   * messages, for invalid arguments to long form options ...
+   */
+  if( opterr )
+  {
+    /* ... but, displayed only if `opterr' is non-zero.
+     */
+    char flag[] = "--";
+    if( mode != getopt_mode_long )
+      /*
+       * only display one hyphen, for implicit long form options,
+       * improperly resolved by `getopt_long_only()'.
+       */
+      flag[1] = 0;
+    /*
+     * always preface the program name ...
+     */
+    fprintf( stderr, "%s: ", prog );
+    /*
+     * to the appropriate, option specific message.
+     */
+    fprintf( stderr, fmt, flag, opt->name );
+  }
+  /* Whether displaying the message, or not, always set `optopt'
+   * to identify the faulty option ...
+   */
+  optopt = opt->val;
+  /*
+   * and return the `invalid option' indicator.
+   */
+  return retval;
+}
+
+/* `getopt_conventions' establish behavioural options, to control
+ * the operation of `getopt_parse()', e.g. to select between POSIX
+ * and GNU style argument parsing behaviour.
+ */
+#define getopt_set_conventions  0x1000
+#define getopt_posixly_correct  0x0010
+
+static __inline__
+int getopt_conventions( int flags )
+{
+  static int conventions = 0;
+
+  if( (conventions == 0) && ((flags & getopt_set_conventions) == 0) )
+  {
+    /* default conventions have not yet been established;
+     * initialise them now!
+     */
+    conventions = getopt_set_conventions;
+    if( (flags == getopt_pluschar) || (getenv( "POSIXLY_CORRECT" ) != NULL) )
+      conventions |= getopt_posixly_correct;
+  }
+
+  else if( flags & getopt_set_conventions )
+    /*
+     * default conventions may have already been established,
+     * but this is a specific request to augment them.
+     */
+    conventions |= flags;
+
+  /* in any event, return the currently established conventions.
+   */
+  return conventions;
+}
+
+static __inline__
+int is_switchar( CHAR flag )
+{
+  /* A simple helper function, used to identify the switch character
+   * introducing an optional command line argument.
+   */
+  return flag == getopt_switchar;
+}
+
+static __inline__
+const CHAR *getopt_match( CHAR lookup, const CHAR *opt_string )
+{
+  /* Helper function, used to identify short form options.
+   */
+  if( (*opt_string == getopt_pluschar) || (*opt_string == getopt_switchar) )
+    ++opt_string;
+  if( *opt_string == getopt_takes_argument )
+    ++opt_string;
+  do if( lookup == *opt_string ) return opt_string;
+     while( *++opt_string );
+  return NULL;
+}
+
+static __inline__
+int getopt_match_long( const CHAR *nextchar, const CHAR *optname )
+{
+  /* Helper function, used to identify potential matches for
+   * long form options.
+   */
+  CHAR matchchar;
+  while( (matchchar = *nextchar++) && (matchchar == *optname) )
+    /*
+     * skip over initial substring which DOES match.
+     */
+    ++optname;
+
+  if( matchchar )
+  {
+    /* did NOT match the entire argument to an initial substring
+     * of a defined option name ...
+     */
+    if( matchchar != getopt_arg_assign )
+      /*
+       * ... and didn't stop at an `=' internal field separator,
+       * so this is NOT a possible match.
+       */
+      return getopt_no_match;
+
+    /* DID stop at an `=' internal field separator,
+     * so this IS a possible match, and what follows is an
+     * argument to the possibly matched option.
+     */
+    optarg = (char *)(nextchar);
+  }
+  return *optname
+    /*
+     * if we DIDN'T match the ENTIRE text of the option name,
+     * then it's a possible abbreviated match ...
+     */
+    ? getopt_abbreviated_match
+    /*
+     * but if we DID match the entire option name,
+     * then it's a DEFINITE EXACT match.
+     */
+    : getopt_exact_match;
+}
+
+static __inline__
+int getopt_resolved( int mode, int argc, CHAR *const *argv, int *argind,
+struct option *opt, int index, int *retindex, const CHAR *optstring )
+{
+  /* Helper function to establish appropriate return conditions,
+   * on resolution of a long form option.
+   */
+  if( retindex != NULL )
+    *retindex = index;
+
+  /* On return, `optind' should normally refer to the argument, if any,
+   * which follows the current one; it is convenient to set this, before
+   * checking for the presence of any `optarg'.
+   */
+  optind = *argind + 1;
+
+  if( optarg && (opt[index].has_arg == no_argument) )
+    /*
+     * it is an error for the user to specify an option specific argument
+     * with an option which doesn't expect one!
+     */
+    return getopt_argerror( mode, "option `%s%s' doesn't accept an argument\n",
+	PROGNAME, opt + index, getopt_unknown );
+
+  else if( (optarg == NULL) && (opt[index].has_arg == required_argument) )
+  {
+    /* similarly, it is an error if no argument is specified
+     * with an option which requires one ...
+     */
+    if( optind < argc )
+      /*
+       * ... except that the requirement may be satisfied from
+       * the following command line argument, if any ...
+       */
+      optarg = argv[*argind = optind++];
+
+    else
+      /* so fail this case, only if no such argument exists!
+       */
+      return getopt_argerror( mode, "option `%s%s' requires an argument\n",
+	  PROGNAME, opt + index, getopt_missing_arg( optstring ) );
+  }
+
+  /* when the caller has provided a return buffer ...
+   */
+  if( opt[index].flag != NULL )
+  {
+    /* ... then we place the proper return value there,
+     * and return a status code of zero ...
+     */
+    *(opt[index].flag) = opt[index].val;
+    return 0;
+  }
+  /* ... otherwise, the return value becomes the status code.
+   */
+  return opt[index].val;
+}
+
+static __inline__
+int getopt_verify( const CHAR *nextchar, const CHAR *optstring )
+{
+  /* Helper function, called by getopt_parse() when invoked
+   * by getopt_long_only(), to verify when an unmatched or an
+   * ambiguously matched long form option string is valid as
+   * a short form option specification.
+   */
+  if( ! (nextchar && *nextchar && optstring && *optstring) )
+    /*
+     * There are no characters to be matched, or there are no
+     * valid short form option characters to which they can be
+     * matched, so this can never be valid.
+     */
+    return 0;
+
+  while( *nextchar )
+  {
+    /* For each command line character in turn ...
+     */
+    const CHAR *test;
+    if( (test = getopt_match( *nextchar++, optstring )) == NULL )
+      /*
+       * ... there is no short form option to match the current
+       * candidate, so the entire argument fails.
+       */
+      return 0;
+
+    if( test[1] == getopt_takes_argument )
+      /*
+       * The current candidate is valid, and it matches an option
+       * which takes an argument, so this command line argument is
+       * a valid short form option specification; accept it.
+       */
+      return 1;
+  }
+  /* If we get to here, then every character in the command line
+   * argument was valid as a short form option; accept it.
+   */
+  return 1;
+}
+
+static
+#define getopt_std_args int argc, CHAR *const argv[], const CHAR *optstring
+int getopt_parse( int mode, getopt_std_args, ... )
+{
+  /* Common core implementation for ALL `getopt' functions.
+   */
+  static int argind = 0;
+  static int optbase = 0;
+  static const CHAR *nextchar = NULL;
+  static int optmark = 0;
+
+  if( (optreset |= (optind < 1)) || (optind < optbase) )
+  {
+    /* POSIX does not prescribe any definitive mechanism for restarting
+     * a `getopt' scan, but some applications may require such capability.
+     * We will support it, by allowing the caller to adjust the value of
+     * `optind' downwards, (nominally setting it to zero).  Since POSIX
+     * wants `optind' to have an initial value of one, but we want all
+     * of our internal place holders to be initialised to zero, when we
+     * are called for the first time, we will handle such a reset by
+     * adjusting all of the internal place holders to one less than
+     * the adjusted `optind' value, (but never to less than zero).
+     */
+    if( optreset )
+    {
+      /* User has explicitly requested reinitialisation...
+       * We need to reset `optind' to it's normal initial value of 1,
+       * to avoid a potential infinitely recursive loop; by doing this
+       * up front, we also ensure that the remaining place holders
+       * will be correctly reinitialised to no less than zero.
+       */
+      optind = 1;
+
+      /* We also need to clear the `optreset' request...
+       */
+      optreset = 0;
+    }
+
+    /* Now, we may safely reinitialise the internal place holders, to
+     * one less than `optind', without fear of making them negative.
+     */
+    optmark = optbase = argind = optind - 1;
+    nextchar = NULL;
+  }
+
+  /* From a POSIX perspective, the following is `undefined behaviour';
+   * we implement it thus, for compatibility with GNU and BSD getopt.
+   */
+  else if( optind > (argind + 1) )
+  {
+    /* Some applications expect to be able to manipulate `optind',
+     * causing `getopt' to skip over one or more elements of `argv';
+     * POSIX doesn't require us to support this brain-damaged concept;
+     * (indeed, POSIX defines no particular behaviour, in the event of
+     *  such usage, so it must be considered a bug for an application
+     *  to rely on any particular outcome); nonetheless, Mac-OS-X and
+     * BSD actually provide *documented* support for this capability,
+     * so we ensure that our internal place holders keep track of
+     * external `optind' increments; (`argind' must lag by one).
+     */
+    argind = optind - 1;
+
+    /* When `optind' is misused, in this fashion, we also abandon any
+     * residual text in the argument we had been parsing; this is done
+     * without any further processing of such abandoned text, assuming
+     * that the caller is equipped to handle it appropriately.
+     */
+    nextchar = NULL;
+  }
+
+  if( nextchar && *nextchar )
+  {
+    /* we are parsing a standard, or short format, option argument ...
+     */
+    const CHAR *optchar;
+    if( (optchar = getopt_match( optopt = *nextchar++, optstring )) != NULL )
+    {
+      /* we have identified it as valid ...
+       */
+      if( optchar[1] == getopt_takes_argument )
+      {
+	/* and determined that it requires an associated argument ...
+	 */
+	if( ! *(optarg = (char *)(nextchar)) )
+	{
+	  /* the argument is NOT attached ...
+	   */
+	  if( optchar[2] == getopt_takes_argument )
+	    /*
+	     * but this GNU extension marks it as optional,
+	     * so we don't provide one on this occasion.
+	     */
+	    optarg = NULL;
+
+	  /* otherwise this option takes a mandatory argument,
+	   * so, provided there is one available ...
+	   */
+	  else if( (argc - argind) > 1 )
+	    /*
+	     * we take the following command line argument,
+	     * as the appropriate option argument.
+	     */
+	    optarg = argv[++argind];
+
+	  /* but if no further argument is available,
+	   * then there is nothing we can do, except for
+	   * issuing the requisite diagnostic message.
+	   */
+	  else
+	  {
+	    complain( "option requires an argument -- %c", optopt );
+	    return getopt_missing_arg( optstring );
+	  }
+	}
+	optind = argind + 1;
+	nextchar = NULL;
+      }
+      else
+	optarg = NULL;
+      optind = (nextchar && *nextchar) ? argind : argind + 1;
+      return optopt;
+    }
+    /* if we didn't find a valid match for the specified option character,
+     * then we fall through to here, so take appropriate diagnostic action.
+     */
+    if( mode == getopt_mode_long_only )
+    {
+      complain( "unrecognised option `-%s'", --nextchar );
+      nextchar = NULL;
+      optopt = 0;
+    }
+    else
+      complain( "invalid option -- %c", optopt );
+    optind = (nextchar && *nextchar) ? argind : argind + 1;
+    return getopt_unknown;
+  }
+
+  if( optmark > optbase )
+  {
+    /* This can happen, in GNU parsing mode ONLY, when we have
+     * skipped over non-option arguments, and found a subsequent
+     * option argument; in this case we permute the arguments.
+     */
+    int index;
+    /*
+     * `optspan' specifies the number of contiguous arguments
+     * which are spanned by the current option, and so must be
+     * moved together during permutation.
+     */
+    int optspan = argind - optmark + 1;
+    /*
+     * we use `this_arg' to store these temporarily.
+     */
+    CHAR **this_arg = (CHAR **)malloc(optspan * sizeof(CHAR *));
+    if( this_arg == NULL )
+      return getopt_unknown;
+    /*
+     * we cannot manipulate `argv' directly, since the `getopt'
+     * API prototypes it as `read-only'; this cast to `arglist'
+     * allows us to work around that restriction.
+     */
+    CHAR **arglist = (char **)(argv);
+
+    /* save temporary copies of the arguments which are associated
+     * with the current option ...
+     */
+    for( index = 0; index < optspan; ++index )
+      this_arg[index] = arglist[optmark + index];
+
+    /* move all preceding non-option arguments to the right,
+     * overwriting these saved arguments, while making space
+     * to replace them in their permuted location.
+     */
+    for( --optmark; optmark >= optbase; --optmark )
+      arglist[optmark + optspan] = arglist[optmark];
+
+    /* restore the temporarily saved option arguments to
+     * their permuted location.
+     */
+    for( index = 0; index < optspan; ++index )
+      arglist[optbase + index] = this_arg[index];
+
+    free(this_arg);
+
+    /* adjust `optbase', to account for the relocated option.
+     */
+    optbase += optspan;
+  }
+
+  else
+    /* no permutation occurred ...
+     * simply adjust `optbase' for all options parsed so far.
+     */
+    optbase = argind + 1;
+
+  /* enter main parsing loop ...
+   */
+  while( argc > ++argind )
+  {
+    /* inspect each argument in turn, identifying possible options ...
+     */
+    if( is_switchar( *(nextchar = argv[optmark = argind]) ) && *++nextchar )
+    {
+      /* we've found a candidate option argument ... */
+
+      if( is_switchar( *nextchar ) )
+      {
+	/* it's a double hyphen argument ... */
+
+	const CHAR *refchar = nextchar;
+	if( *++refchar )
+	{
+	  /* and it looks like a long format option ...
+	   * `getopt_long' mode must be active to accept it as such,
+	   * `getopt_long_only' also qualifies, but we must downgrade
+	   * it to force explicit handling as a long format option.
+	   */
+	  if( mode >= getopt_mode_long )
+	  {
+	    nextchar = refchar;
+	    mode = getopt_mode_long;
+	  }
+	}
+	else
+	{
+	  /* this is an explicit `--' end of options marker, so wrap up now!
+	   */
+	  if( optmark > optbase )
+	  {
+	    /* permuting the argument list as necessary ...
+	     * (note use of `this_arg' and `arglist', as above).
+	     */
+	    CHAR *this_arg = argv[optmark];
+	    CHAR **arglist = (CHAR **)(argv);
+
+	    /* move all preceding non-option arguments to the right ...
+	     */
+	    do arglist[optmark] = arglist[optmark - 1];
+	       while( optmark-- > optbase );
+
+	    /* reinstate the `--' marker, in its permuted location.
+	     */
+	    arglist[optbase] = this_arg;
+	  }
+	  /* ... before finally bumping `optbase' past the `--' marker,
+	   * and returning the `all done' completion indicator.
+	   */
+	  optind = ++optbase;
+	  return getopt_all_done;
+	}
+      }
+      else if( mode < getopt_mode_long_only )
+      {
+	/* it's not an explicit long option, and `getopt_long_only' isn't active,
+	 * so we must explicitly try to match it as a short option.
+	 */
+	mode = getopt_mode_standard;
+      }
+
+      if( mode >= getopt_mode_long )
+      {
+	/* the current argument is a long form option, (either explicitly,
+	 * introduced by a double hyphen, or implicitly because we were called
+	 * by `getopt_long_only'); this is where we parse it.
+	 */
+	int lookup;
+	int matched = -1;
+
+	/* we need to fetch the `extra' function arguments, which are
+	 * specified for the `getopt_long' APIs.
+	 */
+	va_list refptr;
+	va_start( refptr, optstring );
+	struct option *longopts = va_arg( refptr, struct option * );
+	int *optindex = va_arg( refptr, int * );
+	va_end( refptr );
+
+	/* ensuring that `optarg' does not inherit any junk, from parsing
+	 * preceding arguments ...
+	 */
+	optarg = NULL;
+	for( lookup = 0; longopts && longopts[lookup].name; ++lookup )
+	{
+	  /* scan the list of defined long form options ...
+	   */
+          switch( getopt_match_long( nextchar, longopts[lookup].name ) )
+          {
+	    /* looking for possible matches for the current argument.
+	     */
+            case getopt_exact_match:
+	      /*
+	       * when an exact match is found,
+	       * return it immediately, setting `nextchar' to NULL,
+	       * to ensure we don't mistakenly try to match any
+	       * subsequent characters as short form options.
+	       */
+	      nextchar = NULL;
+	      return getopt_resolved( mode, argc, argv, &argind,
+		  longopts, lookup, optindex, optstring );
+
+	    case getopt_abbreviated_match:
+	      /*
+	       * but, for a partial (initial substring) match ...
+	       */
+	      if( matched >= 0 )
+	      {
+		/* if this is not the first, then we have an ambiguity ...
+		 */
+		if( (mode == getopt_mode_long_only)
+		  /*
+		   * However, in the case of getopt_long_only(), if
+		   * the entire ambiguously matched string represents
+		   * a valid short option specification, then we may
+		   * proceed to interpret it as such.
+		   */
+		&&  getopt_verify( nextchar, optstring )  )
+		  return getopt_parse( mode, argc, argv, optstring );
+
+		/* If we get to here, then the ambiguously matched
+		 * partial long option isn't valid for short option
+		 * evaluation; reset parser context to resume with
+		 * the following command line argument, diagnose
+		 * ambiguity, and bail out.
+		 */
+		optopt = 0;
+		nextchar = NULL;
+		optind = argind + 1;
+		complain( "option `%s' is ambiguous", argv[argind] );
+		return getopt_unknown;
+	      }
+	      /* otherwise just note that we've found a possible match ...
+	       */
+	      matched = lookup;
+          }
+	}
+	if( matched >= 0 )
+	{
+	  /* if we get to here, then we found exactly one partial match,
+	   * so return it, as for an exact match.
+	   */
+	  nextchar = NULL;
+	  return getopt_resolved( mode, argc, argv, &argind,
+	      longopts, matched, optindex, optstring );
+	}
+	/* if here, then we had what SHOULD have been a long form option,
+	 * but it is unmatched ...
+	 */
+	if( (mode < getopt_mode_long_only)
+	  /*
+	   * ... although paradoxically, `mode == getopt_mode_long_only'
+	   * allows us to still try to match it as a short form option.
+	   */
+        ||  (getopt_verify( nextchar, optstring ) == 0)  )
+	{
+	  /* When it cannot be matched, reset the parsing context to
+	   * resume from the next argument, diagnose the failed match,
+	   * and bail out.
+	   */
+	  optopt = 0;
+	  nextchar = NULL;
+	  optind = argind + 1;
+	  complain( "unrecognised option `%s'", argv[argind] );
+	  return getopt_unknown;
+	}
+      }
+      /* fall through to handle standard short form options...
+       * when the option argument format is neither explictly identified
+       * as long, nor implicitly matched as such, and the argument isn't
+       * just a bare hyphen, (which isn't an option), then we make one
+       * recursive call to explicitly interpret it as short format.
+       */
+      if( *nextchar )
+	return getopt_parse( mode, argc, argv, optstring );
+    }
+    /* if we get to here, then we've parsed a non-option argument ...
+     * in GNU compatibility mode, we step over it, so we can permute
+     * any subsequent option arguments, but ...
+     */
+    if( *optstring == getopt_switchar )
+    {
+      /* if `optstring' begins with a `-' character, this special
+       * GNU specific behaviour requires us to return the non-option
+       * arguments in strict order, as pseudo-arguments to a special
+       * option, with return value defined as `getopt_ordered'.
+       */
+      nextchar = NULL;
+      optind = argind + 1;
+      optarg = argv[argind];
+      return getopt_ordered;
+    }
+    if( getopt_conventions( *optstring ) & getopt_posixly_correct )
+      /*
+       * otherwise ...
+       * for POSIXLY_CORRECT behaviour, or if `optstring' begins with
+       * a `+' character, then we break out of the parsing loop, so that
+       * the scan ends at the current argument, with no permutation.
+       */
+      break;
+  }
+  /* fall through when all arguments have been evaluated,
+   */
+  optind = optbase;
+  return getopt_all_done;
+}
+
+/* All three public API entry points are trivially defined,
+ * in terms of the internal `getopt_parse' function.
+ */
+int getopt( getopt_std_args )
+{
+  return getopt_parse( getopt_mode_standard, argc, argv, optstring );
+}
+
+int getopt_long( getopt_std_args, const struct option *opts, int *index )
+{
+  return getopt_parse( getopt_mode_long, argc, argv, optstring, opts, index );
+}
+
+int getopt_long_only( getopt_std_args, const struct option *opts, int *index )
+{
+  return getopt_parse( getopt_mode_long_only, argc, argv, optstring, opts, index );
+}
+
+#ifdef __weak_alias
+/*
+ * These Microsnot style uglified aliases are provided for compatibility
+ * with the previous MinGW implementation of the getopt API.
+ */
+__weak_alias( getopt, _getopt )
+__weak_alias( getopt_long, _getopt_long )
+__weak_alias( getopt_long_only, _getopt_long_only )
+#endif
diff --git a/vs/getopt.h b/vs/getopt.h
new file mode 100644
index 0000000..e34761d
--- /dev/null
+++ b/vs/getopt.h
@@ -0,0 +1,107 @@
+/**
+ * @file getopt.h
+ * @copy 2012 MinGW.org project
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#ifndef _GETOPT_H
+#define _GETOPT_H
+
+/*
+ * Defines constants and function prototypes required to implement
+ * the `getopt', `getopt_long' and `getopt_long_only' APIs.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int optind;		/* index of first non-option in argv      */
+extern int optopt;		/* single option character, as parsed     */
+extern int opterr;		/* flag to enable built-in diagnostics... */
+				/* (user may set to zero, to suppress)    */
+
+extern char *optarg;		/* pointer to argument of current option  */
+
+extern int getopt( int, char * const [], const char * );
+
+#ifdef _BSD_SOURCE
+/*
+ * BSD adds the non-standard `optreset' feature, for reinitialisation
+ * of `getopt' parsing.  We support this feature, for applications which
+ * proclaim their BSD heritage, before including this header; however,
+ * to maintain portability, developers are advised to avoid it.
+ */
+# define optreset  __mingw_optreset
+
+extern int optreset;
+#endif
+#ifdef __cplusplus
+}
+#endif
+/*
+ * POSIX requires the `getopt' API to be specified in `unistd.h';
+ * thus, `unistd.h' includes this header.  However, we do not want
+ * to expose the `getopt_long' or `getopt_long_only' APIs, when
+ * included in this manner.  Thus, close the standard __GETOPT_H__
+ * declarations block, and open an additional __GETOPT_LONG_H__
+ * specific block, only when *not* __UNISTD_H_SOURCED__, in which
+ * to declare the extended API.
+ */
+#endif /* !defined(__GETOPT_H__) */
+#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__)
+#define __GETOPT_LONG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct option		/* specification for a long form option...	*/
+{
+  const char *name;		/* option name, without leading hyphens */
+  int         has_arg;		/* does it take an argument?		*/
+  int        *flag;		/* where to save its status, or NULL	*/
+  int         val;		/* its associated status value		*/
+};
+
+enum    		/* permitted values for its `has_arg' field...	*/
+{
+  no_argument = 0,      	/* option never takes an argument	*/
+  required_argument,		/* option always requires an argument	*/
+  optional_argument		/* option may take an argument		*/
+};
+
+extern int getopt_long( int, char * const [], const char *, const struct option *, int * );
+extern int getopt_long_only( int, char * const [], const char *, const struct option *, int * );
+/*
+ * Previous MinGW implementation had...
+ */
+#ifndef HAVE_DECL_GETOPT
+/*
+ * ...for the long form API only; keep this for compatibility.
+ */
+# define HAVE_DECL_GETOPT	1
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */
diff --git a/vs/unistd.h b/vs/unistd.h
new file mode 100644
index 0000000..afa0d18
--- /dev/null
+++ b/vs/unistd.h
@@ -0,0 +1,10 @@
+#ifndef _UNISTD_H
+#define _UNISTD_H    1
+
+#include <stdlib.h>
+#include <io.h>
+#include <getopt.h>
+
+#define ssize_t int
+
+#endif /* unistd.h  */