diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,34 @@
+The Haskell bindings for libcdio follow the Haskell-standard [Package
+Versioning Policy](https://pvp.haskell.org), where the first three numbers
+indicate version (types/presence of exported symbols), the fourth number
+indicates patch (underlying behaviour and/or backend code), and the fifth
+indicates revision (docs, packaging, etc.)  This is in contrast to the C
+libcdio itself, which (recently) uses Semantic Versioning; the only real
+difference is that the first *two* numbers of the bindings signal a breaking
+change, while the base library signals that with only *one*.
+
+
+## v/0.1.0.0.  Unreleased
+
+Initial release with nearly all of 'cdio/cdio.h' translated, but not necessarily
+tested, documented, or stabilized.
+
+
+### Added
+
+* f/1.1.1.  Translate all core symbols brought in by simply using `#include "cdio/cdio.h`.
+  For the full list of headers this includes, see `FEATURES`.
+  Also note that several symbols were left untranslated; see the documentation of `Foreign.Libcdio` for the list.
+	* f/1.1.3.1.  Translate `cdio/cd_types.h` as it's used in some bitmasks above.
+	* f/1.1.3.2.  Integrate log messages with the monad rather than (impurely) printing output.
+	* f/1.1.4.2.  Translate `cdio/util.h` as it provides the conversion functions for `Bcd` values.
+* f/1.3.1. f/1.3.3.1. f/1.3.3.2. f/1.3.4.2.  Rewrite the documentation of the above to be more clear, more comprehensive, and (occasionally) more correct.
+* (some of) f/1.4.1.  Just enough of the upstream tests to be sure the bindings are not going *completely* off the rails.
+* f/3.1. f/3.3. i/008.  Provide a smoother means of accessing the library to Haskell users.
+* i/002.  Close the low-hanging memory leaks from being returned allocated strings, without obfuscating the type system.
+* i/003. i/009.  Enforce a bit more type safety by binding integral/string types with typesafe wrappers.
+
+### Known issues
+
+* i/011.  On some systems, opening a Cdio session stops the drive from recognizing a manual (push-button) request to open the drive.  This also occurs with other libraries, so it's not purely a libcdio problem, Haskell bindings or otherwise, but I come across it much more frequently with the bindings than anywhere else.
+* i/021.  A `readLog` call will occasionally return unexpected entries.
diff --git a/FEATURES b/FEATURES
new file mode 100644
--- /dev/null
+++ b/FEATURES
@@ -0,0 +1,111 @@
+The numeric code may be used to search the version control log by prefixing it
+with `f/`; for example, to find all of the documentation edits, `f/1.3.`
+
+Lines prefixed with an asterisk (*) are considered complete -- though edits for
+refactoring or bugfixes are always still possibilities -- while ones with an
+exclamation point (!) are in progress.
+
+  0.    Infrastructure and metadata for code structure, rather than program behaviour
+  0.1.    Maintain a README with a high-level overview of the library
+  0.2.    Explicit tracking of what has been and what will be done
+  0.2.1.    FEATURES
+  0.2.2.    CHANGELOG
+  0.2.3.    ROADMAP
+  0.3.    Track bug reports and feature requests
+
+  1.    Provide a direct Haskell interface to libcdio and libcdio-paranoia
+  1.1.    Export all symbols the libcdio public C headers do
+* 1.1.1.    Translate the "primary" headers #included directly by `cdio/cdio.h`
+* 1.1.1.1.    `cdio/version.h`
+* 1.1.1.2.    `cdio/types.h`
+* 1.1.1.3.    `cdio/sector.h`
+* 1.1.1.4.    `cdio/device.h`
+* 1.1.1.5.    `cdio/cdtext.h`
+* 1.1.1.6.    `cdio/disc.h`
+* 1.1.1.7.    `cdio/read.h`
+* 1.1.1.8.    `cdio/track.h`
+* 1.1.1.9.    `cdio/memory.h`
+  1.1.2.    Translate the headers #included by `cdio/mmc_cmds.h`
+  1.1.2.1.    `cdio/mmc.h`
+  1.1.2.1.1.    `cdio/audio.h
+  1.1.2.1.2.    `cdio/dvd.h`
+  1.1.2.1.3.    `cdio/mmc_util.h`
+  1.1.2.2.    `cdio/mmc_ll_cmds.h`
+  1.1.2.3.    `cdio/mmc_hl_cmds.h`
+  1.1.3.    Translate the remainder of those public headers
+* 1.1.3.1.    `cdio/cd_types.h`
+* 1.1.3.2.    `cdio/logging.h`
+  1.1.3.3.    `cdio/utf8.h`
+  1.1.3.4.    `cdio/posix.h`
+  1.1.4.    Translate the deprecated headers for "backwards compatibility"
+  1.1.4.1.    `cdio/ds.h`
+* 1.1.4.2.    `cdio/util.h`
+  1.1.5.    Translate the libcdio-paranoia headers
+  1.1.5.1.    `cdio/paranoia/cdda.h`
+  1.1.5.2.    `cdio/paranoia/paranoia.h`
+  1.1.6.    Translate headers for handling non-audio data
+  1.1.6.1.    `cdio/iso9660.h`
+  1.1.6.1.1.    `cdio/rock.h`
+  1.1.6.1.1.    `cdio/xa.h`
+  1.1.6.2.    `cdio/udf.h`
+  1.1.6.2.1.    `cdio/udf_file.h`
+  1.1.6.2.2.    `cdio/udf_time.h`
+  1.1.6.2.3.    `cdio/ecma_167.h`
+  1.3.    Improve the documentation from that copied from the headers
+* 1.3.1.    "Primary" headers #included directly by `cdio/cdio.h`
+* 1.3.1.1.    `cdio/version.h`
+* 1.3.1.2.    `cdio/types.h`
+* 1.3.1.3.    `cdio/sector.h`
+* 1.3.1.4.    `cdio/device.h`
+* 1.3.1.5.    `cdio/cdtext.h`
+* 1.3.1.6.    `cdio/disc.h`
+* 1.3.1.7.    `cdio/read.h`
+* 1.3.1.8.    `cdio/track.h`
+* 1.3.1.9.    `cdio/memory.h`
+  1.3.2.    Headers #included by `cdio/mmc_cmds.h`
+  1.3.2.1.    `cdio/mmc.h`
+  1.3.2.1.1.    `cdio/audio.h
+  1.3.2.1.2.    `cdio/dvd.h`
+  1.3.2.1.3.    `cdio/mmc_util.h`
+  1.3.2.2.    `cdio/mmc_ll_cmds.h`
+  1.3.2.3.    `cdio/mmc_hl_cmds.h`
+  1.3.3.    Other public headers
+* 1.3.3.1.    `cdio/cd_types.h`
+* 1.3.3.2.    `cdio/logging.h`
+  1.3.3.3.    `cdio/utf8.h`
+  1.3.3.4.    `cdio/posix.h`
+  1.3.4.    Deprecated headers for "backwards compatibility"
+  1.3.4.1.    `cdio/ds.h`
+* 1.3.4.2.    `cdio/util.h`
+  1.3.5.    libcdio-paranoia headers
+  1.3.5.1.    `cdio/paranoia/cdda.h`
+  1.3.5.2.    `cdio/paranoia/paranoia.h`
+  1.3.6.    Non-audio data
+  1.3.6.1.    `cdio/iso9660.h`
+  1.3.6.1.1.    `cdio/rock.h`
+  1.3.6.1.1.    `cdio/xa.h`
+  1.3.6.2.    `cdio/udf.h`
+  1.3.6.2.1.    `cdio/udf_file.h`
+  1.3.6.2.2.    `cdio/udf_time.h`
+  1.3.6.2.3.    `cdio/ecma_167.h`
+  1.4.    Copy and translate library tests
+! 1.4.1.    libcdio tests
+  1.4.2.    libcdio-paranoia tests
+
+  2.    Provide Haskell reimplementations of the packaged binaries
+  2.1.    `cd-drive`
+  2.2.    `cd-info`
+  2.3.    `cd-read`
+  2.4.    `cdda-player`
+  2.5.    `iso-info`
+  2.6.    `iso-read`
+  2.7.    `mmc-tool`
+  2.8.    `libcdio-paranoia`
+
+! 3.    Provide alternate idomatic (custom-Monad-based) interface for libcdio functions
+* 3.1.    "Primary" headers #included directly by `cdio/cdio.h`
+  3.2.    Headers #included by `cdio/mmc_cmds.h`
+! 3.3.    Other public headers
+  3.4.    Deprecated headers for "backwards compatibility"
+  3.5.    libcdio-paranoia headers
+  3.6.    Non-audio data file access
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,129 @@
+# About
+In C, [libcdio](https://www.gnu.org/software/libcdio/) provides a widely-ported 
+and highly-usable library for retrieving data from CDs (and disc images).  This 
+is an area which Haskell has thus far been lacking a solution for; while modern 
+technology has admittedly been moving away from discs in favour of downloading 
+files over the internet, there is still some utility in the medium for any 
+programmers whose projects might involve external storage (note, however, that 
+`libcdio` only allows /reading/ discs, and leaves /authoring/ to other 
+libraries).
+
+While the majority of the core library has been translated, many supplemental 
+headers (MMC commands, CD-Paranoia, etc.) are not yet available; for the 
+current progress see the [FEATURES](./FEATURES) file and the 
+[ROADMAP](./ROADMAP.md) for the rough order in which those are planned to be 
+developed, and please do report any bugs you find (or even fix them yourself!)
+
+
+# License
+
+The original `libcdio` is licensed under the GPL, and these bindings, of 
+course, follow suit.  If you do use this in your own project, therefore, you 
+are subject to the ambiguity of whether linking to a GPL library then requires 
+your own code to also be released under the GPL.  Look elsewhere for a full 
+discussion on what arguments are given in that debate, but in short, the GPL 
+says that "a work based on the Program" must *also* be released under the GPL.
+
+To err on the side of caution, if you use this library, release your code under 
+the GPL.  To do otherwise is to take a firm stance against the linking argument 
+at best, violate the copyright at worst, and make GPL proponents angry at you 
+either way.
+
+
+# Installation
+
+## Requirements
+
+As with nearly every Haskell project, the `.cabal` file maintains the list of 
+dependencies, and that should be taken as authoritative over anywhere else 
+except Hackage revisions, and I'll try to keep the code up to date with those.
+
+Notably, the actual core of this package is the C `libcdio` library.  All 
+bindings should fail gracefully for any version within the supported range, and 
+so should be safe to call blindly, but this is accomplished via preprocessor 
+commands, and so *this package must be recompiled whenever the base libcdio 
+version changes*.  Minor version bumps to the underlying library (and certainly 
+patch releases) should still run safely after being recompiled, but there may 
+be some unexpected behaviour: version 2.1 added a few meta-values to the 
+`Language` enum, for example, at values greater than 255, while the previous 
+maximum value was below that.  It is possible for a C compiler to have used a 
+byte representation for <2.1 and a larger one for >=2.1; something like that 
+could *possibly* result in things being set at/referenced from the wrong memory 
+offset.
+
+	* libcdio: >= 0.93 && < 2.2
+	* c2hs: >= 0.26
+	* ghc: >= 8.0
+
+## c2hs + ghc
+
+Some parts of the bindings have been written for the `c2hs` preprocessor, and 
+while manual compilation is technically possible, it's much more involved than 
+necessary.  Instead, just use `cabal-install` or `stack` as usual.  If you 
+really do have to invoke `gcc` manually, however, run that preprocessor first:
+
+	c2hs --cppopts=-E --cppopts=-Iinclude/ --include=.../ src/Foreign/Libcdio/Types/Enums.chs
+	c2hs --cppopts=-E --cppopts=-Iinclude/ --include=.../ src/Foreign/Libcdio/Types/Offsets.chs
+
+
+# Usage
+
+The original implementation revolves around a classically-C architecture of 
+threading a mutable (though opaque) pointer through through many function 
+calls.  For those used to that or who are following pre-existing guides, a 
+set of low-level bindings mirroring that architecture may be found under 
+the "Foreign.Libcdio" tree; for anyone used to Haskell, the monadic 
+bindings under "Sound.Libcdio" are recommended instead.  A lookup table for 
+translating existing code and/or knowledge into each progressively higher-level 
+interface is provided in the documentation of the `Foreign.Libcdio.*` modules.
+
+As a general rule, any project should /only/ import modules from a single set 
+of bindings, not both, as while the datatypes can frequently be passed between 
+them, several function names have been reused and so may collide.
+
+
+# Contributing
+
+I welcome any patches, whether for bug fixes, new features, or anything else.  
+If you just want to point out a bug or ask for some yet-unmentioned feature, I 
+maintain that list in [ISSUES](./ISSUES/); see the [README](./ISSUES/README.md) 
+in that directory for the format if you want to submit something in a more 
+complete form or contribute to any ongoing discussion, but otherwise feel free 
+to simply [email me](mailto:ag@eitilt.life) and I'll wrangle it into the 
+right form.
+
+If you decide to contribute yourself, please enable the `dev` build flag.  
+For the moment, it just enables all warnings I want to enforce in the code, but 
+it might provide other aids in the future as well.  I've avoided enabling them 
+during everyday building as while an end user seeing a warning *might* feel 
+inclined to fix the program, chances are it's just going to be ignored as the 
+list of built files scrolls by.
+
+	cabal configure -fdev
+
+Depending on the size of your hack, I welcome either a diff file, or you can 
+bundle your complete darcs patches with `darcs send`.  Either way, attach the 
+changes to an email addressed to ag@eitilt.life and I'll see about adding it to 
+the codebase.
+
+## Patch format
+
+If you do send the latter, every patch should have a comment with a (at least 
+mildly) descriptive name prefixed with a tag indicating the general category 
+addressed by the patch: for fixing issues, that is an "i/" followed by the 
+issue number (padded with leading zeros to three digits); for general 
+development, "f/" followed by the best topic in the `FEATURES` key; for 
+completeness, version tags are "v/" followed by the package reference followed 
+by the version.  All are terminated with a final period.
+
+Please do not squash patches.  Each patch should represent a minimal but 
+complete change: certainly enough context to successfully compile, hopefully 
+enough context to not break any previously-passing tests, and potentially 
+combining closely-related changes at your discretion, but if you wind up trying 
+to decide between multiple tags or you're adding all of your work over the 
+entire day, you should probably look closely at whether you can break the patch 
+apart any farther.
+
+Additionally, make good use of the `--ask-deps` flag.  Until I get a CI 
+integration together, it's easy to miss a dependency, but do your best to 
+select anything which your patch may require to build successfully.
diff --git a/ROADMAP.md b/ROADMAP.md
new file mode 100644
--- /dev/null
+++ b/ROADMAP.md
@@ -0,0 +1,58 @@
+# Version roadmap
+
+While the `FEATURES` file provides a checklist and rough progress indication,
+it does not give any indication of priority.  This document, then, is a means
+of sorting those features into a rough order of implementation.  Future version
+numbers here are only a rough indication of expectations; intermediate breaking
+changes and partial releases may require they be incremented.
+
+
+## Core library
+
+* f/1.1.1.
+* f/1.1.3.1.
+* f/1.3.1.
+* f/1.3.3.1.
+* f/1.1.3.2.
+* f/1.4.1.  *(those which may be implemented at this point)*
+* f/3.1.
+
+
+## Re-implement binaries for testing
+
+* f/2.1.
+* f/2.2.
+* f/2.3.
+* f/2.5.
+* f/2.6.
+
+
+## libcdio-paranoia
+
+* f/1.1.5.
+* f/1.3.5.
+* f/1.4.2.
+* f/2.8.
+* f/3.5.
+
+
+## MMC commands
+
+* f/1.1.2.
+* f/1.3.2.
+* f/1.4.1.  *(those which may be implemented at this point)*
+* f/2.7.
+* f/3.2.
+
+
+## Non-audio data
+
+* f/1.1.3.3.
+* f/1.1.3.4.
+* f/1.1.4.1.
+* f/1.1.6.
+* f/1.3.3.3.
+* f/1.3.3.4.
+* f/1.3.4.1.
+* f/1.3.6.
+* f/3.6.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/bin/Sound/Libcdio/PackCdText.hs b/bin/Sound/Libcdio/PackCdText.hs
new file mode 100644
--- /dev/null
+++ b/bin/Sound/Libcdio/PackCdText.hs
@@ -0,0 +1,73 @@
+{-# LANGUAGE CPP #-}
+
+module Main where
+
+
+import qualified Options.Applicative as O
+
+import qualified Data.ByteString as BS
+
+import qualified System.IO as IO
+
+import Sound.Libcdio
+import Sound.Libcdio.Read.CdText
+
+#if MIN_VERSION_base(4,11,0)
+#else
+import Data.Monoid ( (<>) )
+#endif
+
+import Options.Applicative ( (<|>), (<**>) )
+
+
+data Options = Options
+    { source :: FilePath
+    , sink :: Maybe FilePath
+    , help :: Bool
+    }
+  deriving ( Eq, Ord, Show, Read )
+
+
+options :: O.Parser Options
+options = Options
+    <$> O.strArgument (O.metavar "FILE")
+    <*> output
+    <*> O.switch
+        (   O.long "help"
+         <> O.short 'h'
+         <> O.help "Print this help message"
+        )
+
+output :: O.Parser (Maybe FilePath)
+output = O.flag' Nothing
+        (   O.long "stdout"
+         <> O.short 'O'
+         <> O.help "Echo the resulting binary blob to stdout"
+        )
+    <|> Just <$> O.strOption
+        (   O.long "output"
+         <> O.short 'o'
+         <> O.metavar "FILE"
+         <> O.value "cdtext.dat"
+         <> O.help "Where to save the resulting CDTEXT blob"
+        )
+
+description :: O.InfoMod a
+description = O.fullDesc
+     <> O.progDesc "Generate a binary CDTEXT file from readable data"
+
+
+main :: IO ()
+main = do
+    os <- O.execParser $ O.info (options <**> O.helper) description
+    if help os
+    then putStrLn "TODO: Print the help"
+    else do
+        let write p = case sink os of
+                Just f -> IO.withBinaryFile f IO.WriteMode $ flip BS.hPut p
+                Nothing -> BS.putStr p
+        bs <- open (Just $ source os) False cdTextRaw
+        case bs of
+            Right (Just bs') -> write bs'
+            Right Nothing -> IO.hPutStrLn IO.stderr "No CDTEXT on disc"
+            _ -> IO.hPutStrLn IO.stderr "Unable to open device"
diff --git a/hscdio.cabal b/hscdio.cabal
new file mode 100644
--- /dev/null
+++ b/hscdio.cabal
@@ -0,0 +1,277 @@
+cabal-version:      2.4
+
+name:               hscdio
+author:             Sam May
+category:           Sound
+synopsis:           Haskell bindings to the libcdio disc-reading library.
+
+version:            0.1.0.0
+stability:          provisional
+maintainer:         sam@eitilt.life
+
+copyright:          (c) 2018-2021 Sam May
+license:            GPL-3.0-or-later
+license-file:       LICENSE
+extra-source-files: CHANGELOG.md
+                  , FEATURES
+                  , README.md
+                  , ROADMAP.md
+                  , include/cdio/compat/*.h
+                    -- The test suites will run relative to the source directory
+                  , test/datafiles/**/*.bin
+                  , test/datafiles/**/*.cdtext
+                  , test/datafiles/**/*.cue
+                  , test/datafiles/**/*.nrg
+                  , test/datafiles/**/*.toc
+                  , test/datafiles/**/*.txt
+
+homepage:           https://ag.eitilt.life/hscdio
+bug-reports:        mailto:ag@eitilt.life
+
+description:
+    The C library "libcdio" provides unified functions for reading data from
+    CDs and disc images across an impressive range of operating sysems.  This
+    package provides Haskell bindings for those functions, in both a format
+    familiar to anyone who has used the original library, and a format more
+    native to the Haskell ecosystem.
+
+build-type:         Simple
+tested-with:        GHC ==8.0.2, GHC ==8.2.2, GHC ==8.4.4, GHC ==8.6.5, GHC ==8.8.4, GHC ==8.10.4
+
+
+source-repository head
+  type:             darcs
+  location:         https://darcs.eitilt.life/hscdio
+
+source-repository this
+  type:             darcs
+  location:         https://darcs.eitilt.life/hscdio
+  tag:              v/0.1.0.0.
+
+
+source-repository head
+  type:             darcs
+  location:         https://hub.darcs.net/ag.eitilt/hscdio
+
+source-repository this
+  type:             darcs
+  location:         https://hub.darcs.net/ag.eitilt/hscdio
+  tag:              v/0.1.0.0.
+
+
+flag dev
+  description:      Trigger stricter behaviour for development
+  default:          False
+  manual:           True
+
+flag tools
+  description:      Build developers' aids
+  default:          False
+  manual:           True
+
+
+common flags-ghc
+  if flag(dev)
+    ghc-options:    -Weverything
+                    -Wno-unrecognised-pragmas
+                    -Wno-implicit-prelude -Wno-missing-import-lists
+                    -Wno-missing-exported-signatures -Wno-missing-local-signatures
+                    -Wno-missed-specialisations -Wno-all-missed-specialisations
+                    -Wno-safe -Wno-unsafe
+                    -Wno-monomorphism-restriction
+    if impl(ghc >= 8.4.1)
+      ghc-options:  -Wno-missing-export-lists
+    if impl(ghc >= 8.8.1)
+      ghc-options:  -Wno-missing-deriving-strategies
+    if impl(ghc >= 8.10.1)
+      ghc-options:  -Wno-missing-safe-haskell-mode
+                    -Wno-prepositive-qualified-module
+  else
+    ghc-options:    -Wno-unrecognised-pragmas
+
+
+library
+  import:           flags-ghc
+  hs-source-dirs:   src
+  exposed-modules:  Data.Text.Encoding.MsJIS
+                  , Foreign.Libcdio.CdText
+                  , Foreign.Libcdio.CdTypes
+                  , Foreign.Libcdio.Device
+                  , Foreign.Libcdio.Disc
+                  , Foreign.Libcdio.Logging
+                  , Foreign.Libcdio.Read
+                  , Foreign.Libcdio.Sector
+                  , Foreign.Libcdio.Track
+                  , Foreign.Libcdio.Types
+                  , Foreign.Libcdio.Util
+                  , Foreign.Libcdio.Version
+                  , Foreign.Libcdio
+                  , Sound.Libcdio
+                  , Sound.Libcdio.Device
+                  , Sound.Libcdio.Logging
+                  , Sound.Libcdio.Read.CdText
+                  , Sound.Libcdio.Read.Data
+                  , Sound.Libcdio.Read.Filesystem
+                  , Sound.Libcdio.Track
+                  , Sound.Libcdio.Types
+  other-modules:    Foreign.Libcdio.Marshal
+                  , Foreign.Libcdio.CdText.Binary
+                  , Foreign.Libcdio.Types.Enums
+                  , Foreign.Libcdio.Types.Internal
+                  , Foreign.Libcdio.Types.Offsets
+                  , Sound.Libcdio.Common
+                  , Sound.Libcdio.Types.Cdio
+  -- Be sure to keep pkg/gentoo/dev-haskell/*.ebuild up to date
+  build-depends:    base >=4.9 && <4.15
+                  , bitwise >=0.1 && <1.1
+                  , bytestring >=0.9 && <0.12
+                  , containers <0.7
+                  , mtl <2.3
+                  , text >=0.3 && <1.3
+                  , vector <0.13
+  build-tool-depends: c2hs:c2hs >=0.26 && <0.29
+  include-dirs:     include
+  includes:         cdio/cdtext.h
+                  , cdio/cdio.h
+                  , cdio/cd_types.h
+                  , cdio/device.h
+                  , cdio/disc.h
+                  , cdio/memory.h
+                  , cdio/mmc.h
+                  , cdio/track.h
+                  , cdio/types.h
+                  , cdio/sector.h
+                  , cdio/util.h
+                  , cdio/compat/cdtext.h
+                  , cdio/compat/cd_types.h
+                  , cdio/compat/cycle_break.h
+                  , cdio/compat/device.h
+                  , cdio/compat/disc.h
+                  , cdio/compat/logging.h
+                  , cdio/compat/mmc.h
+                  , cdio/compat/read.h
+                  , cdio/compat/sector.h
+                  , cdio/compat/track.h
+                  , cdio/compat/types.h
+                  , cdio/compat/version.h
+                  , stdint.h
+                  , stdlib.h
+                  , string.h
+                  , unistd.h
+  c-sources:        src/c/cdio/compat/cdtext.c
+                  , src/c/cdio/compat/device.c
+                  , src/c/cdio/compat/disc.c
+                  , src/c/cdio/compat/logging.c
+                  , src/c/cdio/compat/read.c
+                  , src/c/cdio/compat/sector.c
+                  , src/c/cdio/compat/track.c
+                  , src/c/cdio/compat/types.c
+                  , src/c/cdio/compat/version.c
+  extra-libraries:  cdio
+  default-language: Haskell2010
+  other-extensions: CPP
+                  , ForeignFunctionInterface
+                  , MultiParamTypeClasses
+                  , OverloadedStrings
+                  , Trustworthy
+
+test-suite property
+  import:           flags-ghc
+  type:             exitcode-stdio-1.0
+  hs-source-dirs:   test
+  if impl(ghc < 8.6.1)
+    -- hedgehog-classes requires base>=4.12.0.0
+    buildable:      False
+  main-is:          Test/Libcdio/Property.hs
+  other-modules:    Data.Text.Encoding.MsJIS.Test.Classes
+                  , Foreign.Libcdio.CdText.Test.Classes
+                  , Foreign.Libcdio.CdTypes.Test.Classes
+                  , Foreign.Libcdio.Device.Test.Classes
+                  , Foreign.Libcdio.Disc.Test.Classes
+                  , Foreign.Libcdio.Logging.Test.Classes
+                  , Foreign.Libcdio.Logging.Test.Property
+                  , Foreign.Libcdio.Read.Test.Classes
+                  , Foreign.Libcdio.Sector.Test.Classes
+                  , Foreign.Libcdio.Track.Test.Classes
+                  , Foreign.Libcdio.Util.Test.Classes
+                  , Sound.Libcdio.Cdio.Test.Classes
+                  , Sound.Libcdio.CdText.Test.Classes
+                  , Test.Libcdio.Property.Common
+  build-depends:    base
+                  , hscdio
+                  , hedgehog <1.1
+                  , hedgehog-classes >=0.1.1.0 && <0.3
+                  , text
+  default-language: Haskell2010
+  other-extensions: CPP
+                  , OverloadedStrings
+
+test-suite unit
+  import:           flags-ghc
+  type:             exitcode-stdio-1.0
+  hs-source-dirs:   test
+  main-is:          Test/Libcdio/Unit.hs
+  other-modules:    Paths_hscdio
+                  , Data.Text.Encoding.MsJIS.Test.Unit
+                  , Test.Libcdio.Unit.Common
+                  , Test.Libcdio.Unit.Foreign.CarolusRex
+                  , Test.Libcdio.Unit.Foreign.DeeperDance
+                  , Test.Libcdio.Unit.Foreign.RevolutionDays
+                  , Test.Libcdio.Unit.Sound.Common
+                  , Test.Libcdio.Unit.Sound.CarolusRex
+                  , Test.Libcdio.Unit.Sound.DeeperDance
+                  , Test.Libcdio.Unit.Sound.RevolutionDays
+  autogen-modules:  Paths_hscdio
+  build-depends:    base
+                  , hscdio
+                  , HUnit >=1.1 && <1.7
+                  , base-compat >= 0.9.3 && <0.12
+                  , bytestring
+                  , text
+  default-language: Haskell2010
+
+test-suite upstream
+  import:           flags-ghc
+  type:             exitcode-stdio-1.0
+  hs-source-dirs:   test
+  main-is:          Test/Libcdio/Upstream.hs
+  other-modules:    Paths_hscdio
+                  , Test.Libcdio.Upstream.Foreign.Common
+                  , Test.Libcdio.Upstream.Foreign.BinCue
+                  , Test.Libcdio.Upstream.Foreign.CdrDao
+                  , Test.Libcdio.Upstream.Foreign.FreeBsd
+                  , Test.Libcdio.Upstream.Foreign.Linux
+                  , Test.Libcdio.Upstream.Foreign.Nrg
+                  , Test.Libcdio.Upstream.Foreign.OsX
+                  , Test.Libcdio.Upstream.Foreign.Pregap
+                  , Test.Libcdio.Upstream.Foreign.Solaris
+                  , Test.Libcdio.Upstream.Foreign.SizeOf
+                  , Test.Libcdio.Upstream.Foreign.Track
+                  , Test.Libcdio.Upstream.Foreign.Win32
+                  , Test.Libcdio.Upstream.Sound.Common
+                  , Test.Libcdio.Upstream.Sound.Image
+                  , Test.Libcdio.Upstream.Sound.System
+                  , Test.Libcdio.Upstream.Sound.Track
+  autogen-modules:  Paths_hscdio
+  build-depends:    base
+                  , hscdio
+                  , HUnit >=1.1 && <1.7
+                  , base-compat >= 0.9.3 && <0.12
+                  , directory >=1.2.3 && <1.4
+                  , text
+  default-language: Haskell2010
+  other-extensions: CPP
+                  , OverloadedStrings
+
+executable pack-cdtext
+  import:           flags-ghc
+  hs-source-dirs:   bin
+  if !flag(tools)
+    buildable:      False
+  main-is:          Sound/Libcdio/PackCdText.hs
+  build-depends:    base
+                  , hscdio
+                  , bytestring
+                  , optparse-applicative
+  default-language: Haskell2010
+  other-extensions: CPP
diff --git a/include/cdio/compat/cd_types.h b/include/cdio/compat/cd_types.h
new file mode 100644
--- /dev/null
+++ b/include/cdio/compat/cd_types.h
@@ -0,0 +1,29 @@
+#ifndef __CDIO_COMPAT_CD_TYPES__
+#define __CDIO_COMPAT_CD_TYPES__
+
+
+#include "cdio/compat/types.h"
+#include "cdio/cd_types.h"
+
+#include "stdint.h"
+
+
+// c2hs can't handle the `~` in CDIO_FS_MATCH_ALL
+typedef enum {
+    FS_ANAL_XA           = CDIO_FS_ANAL_XA,
+    FS_ANAL_MULTISESSION = CDIO_FS_ANAL_MULTISESSION,
+    FS_ANAL_PHOTO_CD     = CDIO_FS_ANAL_PHOTO_CD,
+    FS_ANAL_HIDDEN_TRACK = CDIO_FS_ANAL_HIDDEN_TRACK,
+    FS_ANAL_CDTV         = CDIO_FS_ANAL_CDTV,
+    FS_ANAL_BOOTABLE     = CDIO_FS_ANAL_BOOTABLE,
+    FS_ANAL_VIDEOCD      = CDIO_FS_ANAL_VIDEOCD,
+    FS_ANAL_ROCKRIDGE    = CDIO_FS_ANAL_ROCKRIDGE,
+    FS_ANAL_JOLIET       = CDIO_FS_ANAL_JOLIET,
+    FS_ANAL_SVCD         = CDIO_FS_ANAL_SVCD,
+    FS_ANAL_CVD          = CDIO_FS_ANAL_CVD,
+    FS_ANAL_XISO         = CDIO_FS_ANAL_XISO,
+    FS_ANAL_ISO9660_ANY  = CDIO_FS_ANAL_ISO9660_ANY
+} fs_cap_t;
+
+
+#endif
diff --git a/include/cdio/compat/cdtext.h b/include/cdio/compat/cdtext.h
new file mode 100644
--- /dev/null
+++ b/include/cdio/compat/cdtext.h
@@ -0,0 +1,36 @@
+#ifndef __CDIO_COMPAT_CDTEXT__
+#define __CDIO_COMPAT_CDTEXT__
+
+
+#include "cdio/cdtext.h"
+
+#include "stdint.h"
+
+// Required for 'DriverReturnCode' for some reason
+#include "cdio/cdio.h"
+
+
+// Defined in a private header
+#define CDTEXT_NUM_BLOCKS_MAX 8
+
+
+// FFI-compatible wrappers
+
+cdtext_genre_t genre_unused();
+
+cdtext_lang_t language_unknown();
+cdtext_lang_t language_invalid();
+cdtext_lang_t language_unused();
+
+
+// Symbol compatibility definitions
+
+cdtext_lang_t cdtext_str2lang_safe(const char*);
+
+int cdtext_data_init_safe(cdtext_t*, uint8_t*, size_t);
+
+cdtext_lang_t* cdtext_list_languages_v2_safe(cdtext_t*);
+bool cdtext_set_language_index_safe(cdtext_t*, int);
+
+
+#endif
diff --git a/include/cdio/compat/cycle_break.h b/include/cdio/compat/cycle_break.h
new file mode 100644
--- /dev/null
+++ b/include/cdio/compat/cycle_break.h
@@ -0,0 +1,14 @@
+#ifndef __CDIO_COMPAT_CYCLE_BREAK__
+#define __CDIO_COMPAT_CYCLE_BREAK__
+
+
+// Several cdio headers don't support direct inclusion (they invoke cdio.h,
+// which in turn brings in read.h before the device definitions that one needs)
+// so short-circuit that loop by pretending cdio.h has already been processed.
+#define __CDIO_H__
+
+// That then requires the one symbol defined in cdio.h be created manually:
+typedef struct _CdIo CdIo_t;
+
+
+#endif
diff --git a/include/cdio/compat/device.h b/include/cdio/compat/device.h
new file mode 100644
--- /dev/null
+++ b/include/cdio/compat/device.h
@@ -0,0 +1,42 @@
+#ifndef __CDIO_COMPAT_DEVICE__
+#define __CDIO_COMPAT_DEVICE__
+
+
+#include "cdio/compat/cycle_break.h"
+#include "cdio/device.h"
+
+
+// FFI-compatible wrappers
+
+const unsigned int vendor_len();
+const unsigned int model_len();
+const unsigned int revision_len();
+
+bitfield_t drive_cap_error();
+bitfield_t drive_cap_unknown();
+
+const driver_id_t* get_drivers();
+const driver_id_t* get_device_drivers();
+const driver_id_t get_os_driver();
+
+
+// Symbol compatibility definitions
+
+#if LIBCDIO_SINCE_VERSION_1_0
+// Keep the old enum values around, for broader compatibility.
+#define DRIVER_BSDI (DRIVER_DEVICE+1)
+#define DRIVER_OS2 (DRIVER_DEVICE+2)
+#endif
+
+CdIo_t* cdio_open_bsdi_safe(const char*);
+CdIo_t* cdio_open_am_bsdi_safe(const char*, const char*);
+char* cdio_get_default_device_bsdi_safe();
+char** cdio_get_devices_bsdi_safe();
+
+CdIo_t* cdio_open_os2_safe(const char*);
+CdIo_t* cdio_open_am_os2_safe(const char*, const char*);
+char* cdio_get_default_device_os2_safe();
+char** cdio_get_devices_os2_safe();
+
+
+#endif
diff --git a/include/cdio/compat/disc.h b/include/cdio/compat/disc.h
new file mode 100644
--- /dev/null
+++ b/include/cdio/compat/disc.h
@@ -0,0 +1,25 @@
+#ifndef __CDIO_COMPAT_DISC__
+#define __CDIO_COMPAT_DISC__
+
+
+#include "cdio/compat/cycle_break.h"
+#include "cdio/compat/cdtext.h"
+#include "cdio/disc.h"
+
+#include "cdio/compat/track.h"
+#include "cdio/compat/types.h"
+
+
+// FFI-compatible wrappers
+
+const char* discmode_string(discmode_t);
+
+discmode_t discmode_error();
+
+
+// Marshalling aids
+
+void get_cdtext_raw_len(CdIo_t*, uint8_t**, unsigned int*);
+
+
+#endif
diff --git a/include/cdio/compat/logging.h b/include/cdio/compat/logging.h
new file mode 100644
--- /dev/null
+++ b/include/cdio/compat/logging.h
@@ -0,0 +1,33 @@
+#ifndef __CDIO_COMPAT_LOGGING__
+#define __CDIO_COMPAT_LOGGING__
+
+// Custom in-memory log management
+
+
+#include "cdio/compat/cycle_break.h"
+#include "cdio/logging.h"
+
+
+// Combination log entry and linked list
+typedef struct cdio_log_entry_s {
+    cdio_log_level_t level;
+    const char* message;
+    struct cdio_log_entry_s* prev;
+} cdio_log_entry_t;
+
+// Root of the afore-mentioned linked list
+cdio_log_entry_t* haskell_log;
+
+// Register the custom handler with libcdio
+void setup_cdio_logger();
+
+// Control message filtering
+cdio_log_level_t get_cdio_log_level();
+void set_cdio_log_level(cdio_log_level_t);
+
+// Access/clear the accumulated list
+cdio_log_entry_t** read_cdio_log();
+void free_cdio_log();
+
+
+#endif
diff --git a/include/cdio/compat/mmc.h b/include/cdio/compat/mmc.h
new file mode 100644
--- /dev/null
+++ b/include/cdio/compat/mmc.h
@@ -0,0 +1,9 @@
+#ifndef __CDIO_COMPAT_MMC__
+#define __CDIO_COMPAT_MMC__
+
+
+#include "cdio/compat/device.h"
+#include "cdio/mmc.h"
+
+
+#endif
diff --git a/include/cdio/compat/read.h b/include/cdio/compat/read.h
new file mode 100644
--- /dev/null
+++ b/include/cdio/compat/read.h
@@ -0,0 +1,39 @@
+#ifndef __CDIO_COMPAT_READ__
+#define __CDIO_COMPAT_READ__
+
+
+#include "cdio/compat/device.h"
+#include "cdio/read.h"
+
+#include "unistd.h"
+
+
+// FFI-compatible wrappings
+
+typedef enum {
+    WHENCE_SEEK_START = SEEK_SET,
+    WHENCE_SEEK_CURRENT = SEEK_CUR,
+    WHENCE_SEEK_END = SEEK_END
+} whence_t;
+
+
+// Marshalling aids
+
+void read_bytes(const CdIo_t*, void**, ssize_t*, size_t);
+
+driver_return_code_t read_sector(const CdIo_t*, void**, uint32_t*, lsn_t, cdio_read_mode_t);
+driver_return_code_t read_sectors(const CdIo_t*, void**, uint32_t*, lsn_t, cdio_read_mode_t, uint32_t);
+
+driver_return_code_t read_data_sectors(const CdIo_t*, void**, uint32_t*, lsn_t, uint16_t, uint32_t);
+
+driver_return_code_t read_audio_sector(const CdIo_t*, void**, uint32_t*, lsn_t);
+driver_return_code_t read_audio_sectors(const CdIo_t*, void**, uint32_t*, lsn_t, uint32_t);
+
+driver_return_code_t read_mode1_sector(const CdIo_t*, void**, uint32_t*, lsn_t, bool);
+driver_return_code_t read_mode1_sectors(const CdIo_t*, void**, uint32_t*, lsn_t, bool, uint32_t);
+
+driver_return_code_t read_mode2_sector(const CdIo_t*, void**, uint32_t*, lsn_t, bool);
+driver_return_code_t read_mode2_sectors(const CdIo_t*, void**, uint32_t*, lsn_t, bool, uint32_t);
+
+
+#endif
diff --git a/include/cdio/compat/sector.h b/include/cdio/compat/sector.h
new file mode 100644
--- /dev/null
+++ b/include/cdio/compat/sector.h
@@ -0,0 +1,60 @@
+#ifndef __CDIO_COMPAT_SECTOR__
+#define __CDIO_COMPAT_SECTOR__
+
+
+#include "cdio/sector.h"
+
+#include "stdint.h"
+
+
+// FFI-compatible wrappings
+
+lsn_t min_lsn();
+lsn_t max_lsn();
+
+lba_t invalid_lba();
+lsn_t invalid_lsn();
+
+size_t sizeof_msf();
+
+unsigned int pregap_sectors();
+unsigned int postgap_sectors();
+
+unsigned int cd_mins();
+unsigned int secs_per_min();
+unsigned int frames_per_min();
+unsigned int frames_per_sec();
+unsigned int chunks_per_frame();
+
+unsigned int min_session();
+unsigned int max_session();
+
+unsigned int sync_size();
+unsigned int chunk_size();
+unsigned int framesize_sub();
+
+unsigned int header_size();
+unsigned int subheader_size();
+unsigned int edc_size();
+unsigned int mode1_pad_size();
+unsigned int ecc_size();
+
+unsigned int framesize();
+unsigned int framesize_raw();
+unsigned int framesize_rawer();
+unsigned int framesize_raw0();
+unsigned int framesize_raw1();
+
+unsigned int header_size_xa();
+unsigned int tail_size_xa();
+unsigned int sync_size_xa();
+unsigned int data_size_xa();
+unsigned int tagged_size_xa();
+
+
+const uint8_t* sector_sync_header();
+
+cdio_cd_minutes_sectors max_sectors();
+
+
+#endif
diff --git a/include/cdio/compat/track.h b/include/cdio/compat/track.h
new file mode 100644
--- /dev/null
+++ b/include/cdio/compat/track.h
@@ -0,0 +1,21 @@
+#ifndef __CDIO_COMPAT_TRACK__
+#define __CDIO_COMPAT_TRACK__
+
+
+#include "cdio/compat/types.h"
+#include "cdio/track.h"
+
+
+// FFI-compatible wrappings
+
+const char* track_format_string(track_format_t);
+
+track_t invalid_track();
+track_t leadout_track();
+track_t min_tracks();
+track_t max_tracks();
+
+track_format_t track_format_error();
+
+
+#endif
diff --git a/include/cdio/compat/types.h b/include/cdio/compat/types.h
new file mode 100644
--- /dev/null
+++ b/include/cdio/compat/types.h
@@ -0,0 +1,13 @@
+#ifndef __CDIO_COMPAT_TYPES__
+#define __CDIO_COMPAT_TYPES__
+
+
+#include "cdio/compat/cycle_break.h"
+#include "cdio/types.h"
+
+
+unsigned char mcn_length();
+unsigned char isrc_length();
+
+
+#endif
diff --git a/include/cdio/compat/version.h b/include/cdio/compat/version.h
new file mode 100644
--- /dev/null
+++ b/include/cdio/compat/version.h
@@ -0,0 +1,25 @@
+#ifndef __CDIO_COMPAT_VERSION__
+#define __CDIO_COMPAT_VERSION__
+
+
+#include "cdio/cdio.h"
+#include "cdio/version.h"
+
+
+// FFI-compatible wrappings
+
+const char* get_cdio_version_string();
+const unsigned int get_cdio_version_num();
+const unsigned int get_cdio_version_api();
+
+
+// Base library compatibility testing
+
+#define LIBCDIO_SINCE_VERSION_0_94   (LIBCDIO_VERSION_NUM >= 94    || LIBCDIO_VERSION_NUM == 1)
+#define LIBCDIO_SINCE_VERSION_1_0    (LIBCDIO_VERSION_NUM >= 10000 || LIBCDIO_VERSION_NUM == 1)
+#define LIBCDIO_SINCE_VERSION_1_1    (LIBCDIO_VERSION_NUM >= 10100)
+#define LIBCDIO_SINCE_VERSION_2_0    (LIBCDIO_VERSION_NUM >= 20000)
+#define LIBCDIO_SINCE_VERSION_2_1    (LIBCDIO_VERSION_NUM >= 20100)
+
+
+#endif
diff --git a/src/Data/Text/Encoding/MsJIS.hs b/src/Data/Text/Encoding/MsJIS.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Text/Encoding/MsJIS.hs
@@ -0,0 +1,1566 @@
+{-# LANGUAGE Trustworthy #-}
+
+{-|
+Description:    Basic support for the Microsoft extension of Shift JIS.
+
+Copyright:      (c) 2020-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    portable
+
+The CdText standard technically allows for data encoded as Shift JIS; I am
+unaware of any discs produced with such data as no member of the libcdio-dev
+mailing list (or any of the very few other resources) have Japanese imports,
+but for completion the ability to read that encoding is required.  This module
+provides a light-weight implementation modeled on the "Data.Text.Encoding"
+UTF-8 interface.
+-}
+module Data.Text.Encoding.MsJIS
+    ( -- * Types
+      JISChar ( .. )
+    , JISDecodeError ( .. )
+    , JISEncodeError ( .. )
+      -- * Transformations
+      -- ** Decode
+    , decodeMsJIS'
+    , decodeMsJISWith
+      -- ** Encode
+    , encodeMsJIS'
+    , encodeMsJISWith
+    ) where
+
+
+import qualified Data.ByteString as BS
+import qualified Data.IntMap as M
+import qualified Data.Maybe as Y
+import qualified Data.Text as T
+import qualified Data.Text.Encoding.Error as T
+import qualified Data.Vector as V
+import qualified Data.Word as W
+
+import Data.Vector ( (!) )
+
+
+-- | A shorthand categorization scheme for representing the effect of a single
+-- byte in the absence of existing context.
+data First
+    = None
+        -- ^ The byte is invalid, perhaps unless preceded by a lead byte.
+    | Lone Char
+        -- ^ It represents the given character when not preceded by a lead
+        -- byte.
+    | Lead
+        -- ^ The representation is dependant on the next byte in the stream.
+  deriving ( Eq, Ord, Show, Read )
+
+-- | The characters which may be represented under the Shift JIS encoding.
+-- Note that this type is only exposed as part of error reporting or recovery
+-- functions, and is not intended as a replacement of 'Char'.
+data JISChar
+    = Single W.Word8
+    | Double W.Word8 W.Word8
+  deriving ( Eq, Ord, Show, Read )
+instance Bounded JISChar where
+    minBound = Single minBound
+    maxBound = Double 0xFC 0xFC
+-- | Ignores the three invalid single-byte characters @"\xFD\xFE\xFF"@, and any
+-- double-byte characters outside the primary range
+-- @([0x81..0x9F]++[0xE0..0xFC], [0x40..0xFC])@.  'fromEnum' any such "invalid"
+-- characters will overlap with the canonical characters, and the result should
+-- not be relied upon to remain consistent between versions.
+-- 
+-- >>> succ $ Single 0xFC
+-- Double 0x81 0x40
+-- 
+-- >>> succ $ Double 0x9F 0xFC
+-- Double 0xE0 0x40
+instance Enum JISChar where
+    toEnum i
+        | i <= 0xFC = Single $ fromIntegral i
+        | otherwise = Double l t
+      where (d, m) = divMod (i - 0xFD) 0xBC
+            l = fromIntegral d + if d >= 0x1F
+                -- First index of second table group (0xE0) minus first value of d here (0x1F)
+                then 0xC1
+                -- First index of first table group
+                else 0x81
+            -- First byte in trail tables
+            t = fromIntegral m + 0x40
+    fromEnum (Single c) = fromIntegral c
+    -- Underlying: @s + (l' * x) + (t - y) + 1@
+    -- 
+    -- s = Last single char (0xFC)
+    -- l' = Table index (in [0x81..0x9F]++[0xE0..0xFC]): @l - w@
+    -- l = Lead byte
+    -- w = First byte of either first group (0x81) or second (0xE0)
+    -- x = Length of tables (0xBC)
+    -- t = Trail byte
+    -- y = First byte in trail tables (0x40)
+    -- 
+    -- s - y + 1 = 0xBD
+    fromEnum (Double l t) = (l' * 0xBC) + fromIntegral t + 0xBD
+      where l' = fromIntegral l - if l > 0x9F then 0xE0 else 0x81
+
+
+-- | The given one- or two- byte sequence was unable to be decoded; the error
+-- may be described by the unstructured text.
+data JISDecodeError = JISDecodeError String (Maybe JISChar)
+  deriving ( Eq, Show, Read )
+
+-- | The given character was unable to be serialized in binary form; this is
+-- almost certainly due to it not being included in Shift JIS, but the error is
+-- described by the unstructured text anyway.
+data JISEncodeError = JISEncodeError String (Maybe Char)
+  deriving ( Eq, Show, Read )
+
+
+-- | Lookup table for the broad category a byte falls into when not preceded
+-- by a lead byte.
+type FirstByteTable = V.Vector First
+
+-- | The characters a two-byte sequence may decode to under the context of a
+-- given lead byte.
+type SecondByteTable = V.Vector (Maybe Char)
+
+
+-- | Transform a 'BS.ByteString' into unambiguous 'Char's according to
+-- Microsoft's extension of the Shift JIS encoding scheme.
+--
+-- If the input contains any invalid sequences under that scheme, the first
+-- byte(s) which triggered an error will be returned instead.
+decodeMsJIS' :: BS.ByteString -> Either JISDecodeError T.Text
+decodeMsJIS' = fmap T.pack . decodeMsJIS'' . BS.unpack
+
+-- | Iterate through the byte stream, consuming one or two bytes each cycle as
+-- required to decode a Shift JIS character.
+--
+-- If the input contains any invalid sequences under that scheme, the first
+-- byte(s) which triggered an error will be returned instead.
+decodeMsJIS'' :: [W.Word8] -> Either JISDecodeError String
+decodeMsJIS'' [] = Right ""
+decodeMsJIS'' (b1:bs) = case lookupJIS b1 $ Y.listToMaybe bs of
+    (Left err, _) -> Left err
+    (Right c, w) -> fmap (c :) . decodeMsJIS'' $ if w then drop 1 bs else bs
+
+
+-- | Transform a 'BS.ByteString' into unambiguous 'Char's according to
+-- Microsoft's extension of the Shift JIS encoding scheme.
+decodeMsJISWith :: T.OnError JISChar Char -> BS.ByteString -> T.Text
+decodeMsJISWith e = T.pack . decodeMsJISWith' e . BS.unpack
+
+-- | Iterate through the byte stream, consuming one or two bytes each cycle as
+-- required to decode a Shift JIS character.
+decodeMsJISWith' :: T.OnError JISChar Char -> [W.Word8] -> String
+decodeMsJISWith' _ [] = ""
+decodeMsJISWith' e (b1:bs) = case lookupJIS b1 $ Y.listToMaybe bs of
+    (Left (JISDecodeError msg err), w) -> maybe (loop w) (: loop w) $ e msg err
+    (Right c, w) -> c : loop w
+  where loop _ | null bs = ""
+        loop w = decodeMsJISWith' e $ if w then drop 1 bs else bs
+
+
+-- | Transform an unambiguous string into a binary stream according to
+-- Microsoft's extension of the Shift JIS encoding scheme.
+--
+-- If the input contains any characters without an associated binary sequence
+-- under that scheme, the first such character which triggers the error will be
+-- returned instead.
+encodeMsJIS' :: T.Text -> Either JISEncodeError BS.ByteString
+encodeMsJIS' = T.foldl' (\bs -> throwEncode bs . flatten . lookupUnicode) (Right BS.empty)
+  where throwEncode e@(Left _) _ = e
+        throwEncode _ (Left c) = Left $ JISEncodeError (encodeErrorString "encodeMsJIS'") c
+        throwEncode (Right bs) (Right bs') = Right $ mappend bs bs'
+
+-- | Transform an unambiguous string into a binary stream according to
+-- Microsoft's extension of the Shift JIS encoding scheme.
+encodeMsJISWith :: T.OnError Char BS.ByteString -> T.Text -> BS.ByteString
+encodeMsJISWith e = T.foldl' (\bs -> throwEncode bs . flatten . lookupUnicode) BS.empty
+  where throwEncode bs (Left c) = Y.fromMaybe bs $ e (encodeErrorString "encodeMsJISWith") c
+        throwEncode bs (Right bs') = mappend bs bs'
+
+-- | There is only a single reason why encoding to Shift JIS may fail.
+encodeErrorString :: String -> String
+encodeErrorString func = func ++ ": Character not in MS JIS"
+
+-- | Rewrap the result of a character-to-binary lookup into a form suitable for
+-- 'JISEncodeError'.
+flatten :: Either Char [BS.ByteString] -> Either (Maybe Char) BS.ByteString
+flatten (Right []) = Left Nothing
+flatten (Right (bs:_)) = Right bs
+flatten (Left e) = Left $ Just e
+
+
+-- | The broad categories defining the behaviour of a byte in the Shift JIS
+-- encoding scheme, in the absence of any existing context.  May be safely
+-- indexed using any integer fitting into eight bits:
+--
+-- >>> length firstBytes
+-- 255
+firstBytes :: FirstByteTable
+firstBytes = V.fromList $
+    {-0x00..0x7F-}  map Lone ['\NUL'..'\DEL'] ++
+    {-0x80..0x9F-}  None : replicate 0x1F Lead ++
+    {-0xA0..0xDF-}  None : map Lone ['\xFF61'..'\xFF9F'] ++
+    {-0xE0..0xFC-}  replicate 0x1D Lead ++
+    {-0xFD..0xFF-}  replicate 3 None
+
+-- | The lookup tables describing the representation of any valid two-byte
+-- sequence in the Shift JIS encoding scheme.  As not every byte is a valid
+-- lead byte (and thus may not have an indexed table), @lookupTrailTable@ is
+-- recommended rather than direct indexing.  The presence or absence of a valid
+-- character does not affect whether the subtable may be safely indexed:
+--
+-- >>> V.all ((==) 0xBC . length) secondBytes
+-- True
+secondBytes :: V.Vector SecondByteTable
+secondBytes = V.fromList $
+    [ second81, second82, second83, second84, second85, second86, second87 ] ++
+    [ second88, second89, second8A, second8B, second8C, second8D, second8E, second8F ] ++
+    [ second90, second91, second92, second93, second94, second95, second96, second97 ] ++
+    [ second98, second99, second9A, second9B, second9C, second9D, second9E, second9F ] ++
+    [ secondE0, secondE1, secondE2, secondE3, secondE4, secondE5, secondE6, secondE7 ] ++
+    [ secondE8, secondE9, secondEA, secondEB, secondEC, secondED, secondEE, secondEF ] ++
+    [ secondF0, secondF1, secondF2, secondF3, secondF4, secondF5, secondF6, secondF7 ] ++
+    [ secondF8, secondF9, secondFA, secondFB, secondFC ]
+
+-- | Try to decode a one- or two-byte sequence to an unambiguous character
+-- according to the Shift JIS encoding scheme.  Returns a 'Bool' indicating
+-- whether the second byte was used in decoding the 'Char' (i.e., 'False'
+-- indicates that the next character starts /on/ the second byte given rather
+-- than /after/ it).
+lookupJIS :: W.Word8 -> Maybe W.Word8 -> (Either JISDecodeError Char, Bool)
+lookupJIS l t' = case (lookupLead l, t') of
+    (SingleByte c, _) -> (Right c, False)
+    (MultiByte _, Nothing) -> (err "Input ended without trail byte" $ Single l, False)
+    (MultiByte ts, Just t) ->
+        let found = ts ! (fromIntegral t - 0x40)
+        in (maybe (err "Unassigned trail byte" $ Double l t) Right found, True)
+    (NoChar e, _) -> (Left e, False)
+  where err msg char = Left . JISDecodeError ("lookupJIS: " ++ msg) $ Just char
+
+-- | Given the first byte in a (potentially multibyte) Shift JIS binary
+-- representation, try to retrieve the associated character.
+lookupLead :: W.Word8 -> LeadResult
+lookupLead w = case firstBytes ! fromIntegral w of
+    Lone c -> SingleByte c
+    Lead -> maybe (err "Invalid lead byte") MultiByte $ lookupTrailTable w
+    None -> err "Unassigned lead byte"
+  where err msg = NoChar . JISDecodeError ("lookupJIS: " ++ msg) . Just $ Single w
+
+-- | The potential values which may result from looking up a single byte in the
+-- Shift JIS scheme without any preceding context.
+data LeadResult
+    = SingleByte Char
+        -- ^ The byte represents a complete character.
+    | MultiByte SecondByteTable
+        -- ^ The byte indicates one of a set of characters which may only be
+        -- disambiguated by the next byte in the stream.
+    | NoChar JISDecodeError
+        -- ^ The byte itself is invalid.
+
+-- | Given the first byte in a multibyte Shift JIS binary representation, look
+-- up what characters may be represented depending on the following byte in the
+-- stream.  If the input is not a valid lead byte, 'Nothing' is returned
+-- instead.  The presence or absence of a valid character does not affect
+-- whether the subtable may be safely indexed (but note that position @0@ is
+-- associated with byte @0x40@):
+--
+-- >>> maybe True ((==) 0xBC . length) $ lookupTrailTable b
+-- True
+lookupTrailTable :: W.Word8 -> Maybe SecondByteTable
+lookupTrailTable l
+    | l < 0x81 ||
+        (l > 0x9F && l < 0xE0) ||
+        l > 0xFC = Nothing
+    | l <= 0x9F = Just $ secondBytes ! (fromIntegral l - 0x81)
+    | otherwise = Just $ secondBytes ! (fromIntegral l - 0xC1)
+
+
+
+-- | The lookup table from Unicode character reference number to Shift JIS
+-- binary representation.
+unicodeMap :: M.IntMap [JISChar]
+unicodeMap = M.fromListWith (++) . V.toList $
+    V.imapMaybe keyFirsts firstBytes V.++ V.concat (V.toList $ V.imap keySeconds secondBytes)
+
+-- | Transformation function to obtain a lookup-tuple from a single-byte Shift
+-- JIS representation.
+keyFirsts
+    :: Int
+        -- ^ The index (i.e., the byte itself) in the list of single- and
+        -- lead-byte categories.
+    -> First
+        -- ^ The category associated with that byte; everything /except/ @Lone@
+        -- bytes will be ignored.
+    -> Maybe (M.Key, [JISChar])
+keyFirsts l (Lone j) = Just (fromEnum j, [Single $ fromIntegral l])
+keyFirsts _ _ = Nothing
+
+-- | Transformation function to obtain all lookup-tuples of double-byte Shift
+-- JIS representations beginning with the given byte.
+keySeconds
+    :: Int
+        -- ^ The index (i.e., the byte itself) in the list of single- and
+        -- lead-byte categories.
+    -> SecondByteTable
+        -- ^ The trailing-byte lookup table associated with that lead byte.
+    -> V.Vector (M.Key, [JISChar])
+keySeconds l = V.imapMaybe (\t j -> m (Double l' $ fromIntegral t + 0x40) <$> j)
+  where l' = fromIntegral $ l + if l < 0x1F then 0x81 else 0xC1
+        m t' j' = (fromEnum j', [t'])
+
+
+-- | Given a particular character, retrieve all its potential binary
+-- representations in the Shift JIS encoding scheme.
+lookupUnicode :: Char -> Either Char [BS.ByteString]
+lookupUnicode c = case M.lookup (fromEnum c) unicodeMap of
+    Just js -> Right $ map pack js
+    Nothing -> Left c
+  where pack (Single w) = BS.singleton w
+        pack (Double l t) = BS.pack [l, t]
+
+
+-- * Multi-byte lookup tables
+
+-- | A continuous sequence of valid multibyte characters.
+chars :: String -> [Maybe Char]
+chars = map Just
+
+-- | A continuous sequence of unassigned multibyte characters.
+nothings :: Int -> [Maybe Char]
+nothings = flip replicate Nothing
+
+-- | Generate an entire table of "valid" multibyte characters, without any
+-- actual assigned characters.
+nothingSecond :: SecondByteTable
+nothingSecond = V.replicate 0xC0 Nothing
+
+-- | Generate an entire table of multibyte characters which map to a portion of
+-- the Private Use Area (i.e., are reserved for program- or company-internal
+-- use).
+privateUseSecond :: W.Word16 -> SecondByteTable
+privateUseSecond b = V.fromList $
+    {-0x40..0x7F-}  map (Just . toEnum . fromIntegral) [b..b + 0x3E] ++ Nothing :
+    {-0x80..0xFC-}  map (Just . toEnum . fromIntegral) [b + 0x3F..b + 0xBB]
+
+
+-- | The multibyte characters with a lead byte of @0x81@.
+second81 :: SecondByteTable
+second81 = V.fromList $
+    {-0x40-}  chars "\x3000\x3001\x3002\xFF0C\xFF0E\x30FB\xFF1A\xFF1B" ++
+    {-0x48-}  chars "\xFF1F\xFF01\x309B\x309C\x00B4\xFF40\x00A8\xFF3E" ++
+    {-0x50-}  chars "\xFFE3\xFF3F\x30FD\x30FE\x309D\x309E\x3003\x4EDD" ++
+    {-0x58-}  chars "\x3005\x3006\x3007\x30FC\x2015\x2010\xFF0F\xFF3C" ++
+    {-0x60-}  chars "\xFF5E\x2225\xFF5C\x2026\x2025\x2018\x2019\x201C" ++
+    {-0x68-}  chars "\x201D\xFF08\xFF09\x3014\x3015\xFF3B\xFF3D\xFF5B" ++
+    {-0x70-}  chars "\xFF5D\x3008\x3009\x300A\x300B\x300C\x300D\x300E" ++
+    {-0x78-}  chars "\x300F\x3010\x3011\xFF0B\xFF0D\x00B1\x00D7" ++ Nothing :
+    {-0x80-}  chars "\x00F7\xFF1D\x2260\xFF1C\xFF1E\x2266\x2267\x221E" ++
+    {-0x88-}  chars "\x2234\x2642\x2640\x00B0\x2032\x2033\x2103\xFFE5" ++
+    {-0x90-}  chars "\xFF04\xFFE0\xFFE1\xFF05\xFF03\xFF06\xFF0A\xFF20" ++
+    {-0x98-}  chars "\x00A7\x2606\x2605\x25CB\x25CF\x25CE\x25C7\x25C6" ++
+    {-0xA0-}  chars "\x25A1\x25A0\x25B3\x25B2\x25BD\x25BC\x203B\x3012" ++
+    {-0xA8-}  chars "\x2192\x2190\x2191\x2193\x3013" ++ nothings 3 ++
+    {-0xB0-}  nothings 8 ++
+    {-0xB8-}  chars "\x2208\x220B\x2286\x2287\x2282\x2283\x222A\x2229" ++
+    {-0xC0-}  nothings 8 ++
+    {-0xC8-}  chars "\x2227\x2228\xFFE2\x21D2\x21D4\x2200\x2203" ++ Nothing :
+    {-0xD0-}  nothings 8 ++
+    {-0xD8-}  nothings 2 ++ chars "\x2220\x22A5\x2312\x2202\x2207\x2261" ++
+    {-0xE0-}  chars "\x2252\x226A\x226B\x221A\x223D\x221D\x2235\x222B" ++
+    {-0xE8-}  Just '\x222C' : nothings 7 ++
+    {-0xF0-}  chars "\x212B\x2030\x266F\x266D\x266A\x2020\x2021\x00B6" ++
+    {-0xF8-}  nothings 4 ++ [Just '\x25EF']
+
+-- | The multibyte characters with a lead byte of @0x82@.
+second82 :: SecondByteTable
+second82 = V.fromList $
+    {-0x40..0x4E-}  nothings 15 ++
+    {-0x4F..0x58-}  chars ['\xFF10'..'\xFF19'] ++
+    {-0x59..0x5F-}  nothings 7 ++
+    {-0x60..0x79-}  chars ['\xFF21'..'\xFF3A'] ++
+    {-0x7A..0x80-}  nothings 7 ++
+    {-0x81..0x9A-}  chars ['\xFF41'..'\xFF5A'] ++
+    {-0x9B..0x9E-}  nothings 4 ++
+    {-0x9F..0xF1-}  chars ['\x3041'..'\x3093'] ++
+    {-0xF2..0xFC-}  nothings 11
+
+-- | The multibyte characters with a lead byte of @0x83@.
+second83 :: SecondByteTable
+second83 = V.fromList $
+    {-0x40..0x7F-}  chars ['\x30A1'..'\x30DF'] ++ Nothing :
+    {-0x80..0x96-}  chars ['\x30E0'..'\x30F6'] ++
+    {-0x97..0x9E-}  nothings 8 ++
+    {-0x9F..0xAF-}  chars ['\x0391'..'\x03A1'] ++
+    {-0xB0..0xB6-}  chars ['\x03A3'..'\x03A9'] ++
+    {-0xB7..0xBE-}  nothings 8 ++
+    {-0xBF..0xCF-}  chars ['\x03B1'..'\x03C1'] ++
+    {-0xD0..0xD6-}  chars ['\x03C3'..'\x03C9'] ++
+    {-0xD7..0xFC-}  nothings 0x26
+
+-- | The multibyte characters with a lead byte of @0x84@.
+second84 :: SecondByteTable
+second84 = V.fromList $
+    {-0x40..0x46-}  chars ['\x0410'..'\x0415'] ++ Just '\x0401' :
+    {-0x47..0x60-}  chars ['\x0416'..'\x042F'] ++
+    {-0x61..0x6F-}  nothings 15 ++
+    {-0x60..0x66-}  chars ['\x0430'..'\x0435'] ++ Just '\x0451' :
+    {-0x67..0x7F-}  chars ['\x0436'..'\x043D'] ++ Nothing :
+    {-0x80..0x91-}  chars ['\x043E'..'\x044F'] ++
+    {-0x92..0x9F-}  nothings 13 ++ Just '\x2500' :
+    {-0xA0-}  chars "\x2502\x250C\x2510\x2518\x2514\x251C\x252C\x2524" ++
+    {-0xA8-}  chars "\x2534\x253C\x2501\x2503\x250F\x2513\x251B\x2517" ++
+    {-0xB0-}  chars "\x2523\x2533\x252B\x253B\x254B\x2520\x252F\x2528" ++
+    {-0xB8-}  chars "\x2537\x253F\x251D\x2530\x2525\x2538\x2542" ++
+    {-0xBF..0xFC-}  nothings 0x3E
+
+-- | The multibyte characters with a lead byte of @0x85@.
+second85 :: SecondByteTable
+second85 = nothingSecond
+
+-- | The multibyte characters with a lead byte of @0x86@.
+second86 :: SecondByteTable
+second86 = nothingSecond
+
+-- | The multibyte characters with a lead byte of @0x87@.
+second87 :: SecondByteTable
+second87 = V.fromList $
+    {-0x40..0x53-}  chars ['\x2460'..'\x2473'] ++
+    {-0x54..0x5F-}  chars ['\x2160'..'\x2169'] ++ Nothing : Just '\x3349' :
+    {-0x60-}  chars "\x3314\x3322\x334D\x3318\x3327\x3303\x3336\x3351" ++
+    {-0x68-}  chars "\x3357\x330D\x3326\x3323\x332B\x334A\x333B\x339C" ++
+    {-0x70-}  chars "\x339D\x339E\x338E\x338F\x33C4\x33A1" ++
+    {-0x76..0x7F-}  nothings 8 ++ Just '\x337B' : Nothing :
+    {-0x80-}  chars "\x301D\x301F\x2116\x33CD\x2121\x32A4\x32A5\x32A6" ++
+    {-0x88-}  chars "\x32A7\x32A8\x3231\x3232\x3239\x337E\x337D\x337C" ++
+    {-0x90-}  chars "\x2252\x2261\x222B\x222E\x2211\x221A\x22A5\x2220" ++
+    {-0x98-}  chars "\x221F\x22BF\x2235\x2229\x222A" ++
+    {-0x9D..0xFC-}  nothings 0x60
+
+-- | The multibyte characters with a lead byte of @0x88@.
+second88 :: SecondByteTable
+second88 = V.fromList $
+    {-0x40..0x9F-}  nothings 0x5F ++ Just '\x4E9C' :
+    {-0xA0-}  chars "\x5516\x5A03\x963F\x54C0\x611B\x6328\x59F6\x9022" ++
+    {-0xA8-}  chars "\x8475\x831C\x7A50\x60AA\x63E1\x6E25\x65ED\x8466" ++
+    {-0xB0-}  chars "\x82A6\x9BF5\x6893\x5727\x65A1\x6271\x5B9B\x59D0" ++
+    {-0xB8-}  chars "\x867B\x98F4\x7D62\x7DBE\x9B8E\x6216\x7C9F\x88B7" ++
+    {-0xC0-}  chars "\x5B89\x5EB5\x6309\x6697\x6848\x95C7\x978D\x674F" ++
+    {-0xC8-}  chars "\x4EE5\x4F0A\x4F4D\x4F9D\x5049\x56F2\x5937\x59D4" ++
+    {-0xD0-}  chars "\x5A01\x5C09\x60DF\x610F\x6170\x6613\x6905\x70BA" ++
+    {-0xD8-}  chars "\x754F\x7570\x79FB\x7DAD\x7DEF\x80C3\x840E\x8863" ++
+    {-0xE0-}  chars "\x8B02\x9055\x907A\x533B\x4E95\x4EA5\x57DF\x80B2" ++
+    {-0xE8-}  chars "\x90C1\x78EF\x4E00\x58F1\x6EA2\x9038\x7A32\x8328" ++
+    {-0xF0-}  chars "\x828B\x9C2F\x5141\x5370\x54BD\x54E1\x56E0\x59FB" ++
+    {-0xF8-}  chars "\x5F15\x98F2\x6DEB\x80E4\x852D"
+
+-- | The multibyte characters with a lead byte of @0x89@.
+second89 :: SecondByteTable
+second89 = V.fromList $
+    {-0x40-}  chars "\x9662\x9670\x96A0\x97FB\x540B\x53F3\x5B87\x70CF" ++
+    {-0x48-}  chars "\x7FBD\x8FC2\x96E8\x536F\x9D5C\x7ABA\x4E11\x7893" ++
+    {-0x50-}  chars "\x81FC\x6E26\x5618\x5504\x6B1D\x851A\x9C3B\x59E5" ++
+    {-0x58-}  chars "\x53A9\x6D66\x74DC\x958F\x5642\x4E91\x904B\x96F2" ++
+    {-0x60-}  chars "\x834F\x990C\x53E1\x55B6\x5B30\x5F71\x6620\x66F3" ++
+    {-0x68-}  chars "\x6804\x6C38\x6CF3\x6D29\x745B\x76C8\x7A4E\x9834" ++
+    {-0x70-}  chars "\x82F1\x885B\x8A60\x92ED\x6DB2\x75AB\x76CA\x99C5" ++
+    {-0x78-}  chars "\x60A6\x8B01\x8D8A\x95B2\x698E\x53AD\x5186" ++ Nothing :
+    {-0x80-}  chars "\x5712\x5830\x5944\x5BB4\x5EF6\x6028\x63A9\x63F4" ++
+    {-0x88-}  chars "\x6CBF\x6F14\x708E\x7114\x7159\x71D5\x733F\x7E01" ++
+    {-0x90-}  chars "\x8276\x82D1\x8597\x9060\x925B\x9D1B\x5869\x65BC" ++
+    {-0x98-}  chars "\x6C5A\x7525\x51F9\x592E\x5965\x5F80\x5FDC\x62BC" ++
+    {-0xA0-}  chars "\x65FA\x6A2A\x6B27\x6BB4\x738B\x7FC1\x8956\x9D2C" ++
+    {-0xA8-}  chars "\x9D0E\x9EC4\x5CA1\x6C96\x837B\x5104\x5C4B\x61B6" ++
+    {-0xB0-}  chars "\x81C6\x6876\x7261\x4E59\x4FFA\x5378\x6069\x6E29" ++
+    {-0xB8-}  chars "\x7A4F\x97F3\x4E0B\x5316\x4EEE\x4F55\x4F3D\x4FA1" ++
+    {-0xC0-}  chars "\x4F73\x52A0\x53EF\x5609\x590F\x5AC1\x5BB6\x5BE1" ++
+    {-0xC8-}  chars "\x79D1\x6687\x679C\x67B6\x6B4C\x6CB3\x706B\x73C2" ++
+    {-0xD0-}  chars "\x798D\x79BE\x7A3C\x7B87\x82B1\x82DB\x8304\x8377" ++
+    {-0xD8-}  chars "\x83EF\x83D3\x8766\x8AB2\x5629\x8CA8\x8FE6\x904E" ++
+    {-0xE0-}  chars "\x971E\x868A\x4FC4\x5CE8\x6211\x7259\x753B\x81E5" ++
+    {-0xE8-}  chars "\x82BD\x86FE\x8CC0\x96C5\x9913\x99D5\x4ECB\x4F1A" ++
+    {-0xF0-}  chars "\x89E3\x56DE\x584A\x58CA\x5EFB\x5FEB\x602A\x6094" ++
+    {-0xF8-}  chars "\x6062\x61D0\x6212\x62D0\x6539"
+
+-- | The multibyte characters with a lead byte of @0x8A@.
+second8A :: SecondByteTable
+second8A = V.fromList $
+    {-0x40-}  chars "\x9B41\x6666\x68B0\x6D77\x7070\x754C\x7686\x7D75" ++
+    {-0x48-}  chars "\x82A5\x87F9\x958B\x968E\x8C9D\x51F1\x52BE\x5916" ++
+    {-0x50-}  chars "\x54B3\x5BB3\x5D16\x6168\x6982\x6DAF\x788D\x84CB" ++
+    {-0x58-}  chars "\x8857\x8A72\x93A7\x9AB8\x6D6C\x99A8\x86D9\x57A3" ++
+    {-0x60-}  chars "\x67FF\x86CE\x920E\x5283\x5687\x5404\x5ED3\x62E1" ++
+    {-0x68-}  chars "\x64B9\x683C\x6838\x6BBB\x7372\x78BA\x7A6B\x899A" ++
+    {-0x70-}  chars "\x89D2\x8D6B\x8F03\x90ED\x95A3\x9694\x9769\x5B66" ++
+    {-0x78-}  chars "\x5CB3\x697D\x984D\x984E\x639B\x7B20\x6A2B" ++ Nothing :
+    {-0x80-}  chars "\x6A7F\x68B6\x9C0D\x6F5F\x5272\x559D\x6070\x62EC" ++
+    {-0x88-}  chars "\x6D3B\x6E07\x6ED1\x845B\x8910\x8F44\x4E14\x9C39" ++
+    {-0x90-}  chars "\x53F6\x691B\x6A3A\x9784\x682A\x515C\x7AC3\x84B2" ++
+    {-0x98-}  chars "\x91DC\x938C\x565B\x9D28\x6822\x8305\x8431\x7CA5" ++
+    {-0xA0-}  chars "\x5208\x82C5\x74E6\x4E7E\x4F83\x51A0\x5BD2\x520A" ++
+    {-0xA8-}  chars "\x52D8\x52E7\x5DFB\x559A\x582A\x59E6\x5B8C\x5B98" ++
+    {-0xB0-}  chars "\x5BDB\x5E72\x5E79\x60A3\x611F\x6163\x61BE\x63DB" ++
+    {-0xB8-}  chars "\x6562\x67D1\x6853\x68FA\x6B3E\x6B53\x6C57\x6F22" ++
+    {-0xC0-}  chars "\x6F97\x6F45\x74B0\x7518\x76E3\x770B\x7AFF\x7BA1" ++
+    {-0xC8-}  chars "\x7C21\x7DE9\x7F36\x7FF0\x809D\x8266\x839E\x89B3" ++
+    {-0xD0-}  chars "\x8ACC\x8CAB\x9084\x9451\x9593\x9591\x95A2\x9665" ++
+    {-0xD8-}  chars "\x97D3\x9928\x8218\x4E38\x542B\x5CB8\x5DCC\x73A9" ++
+    {-0xE0-}  chars "\x764C\x773C\x5CA9\x7FEB\x8D0B\x96C1\x9811\x9854" ++
+    {-0xE8-}  chars "\x9858\x4F01\x4F0E\x5371\x559C\x5668\x57FA\x5947" ++
+    {-0xF0-}  chars "\x5B09\x5BC4\x5C90\x5E0C\x5E7E\x5FCC\x63EE\x673A" ++
+    {-0xF8-}  chars "\x65D7\x65E2\x671F\x68CB\x68C4"
+
+-- | The multibyte characters with a lead byte of @0x8B@.
+second8B :: SecondByteTable
+second8B = V.fromList $
+    {-0x40-}  chars "\x6A5F\x5E30\x6BC5\x6C17\x6C7D\x757F\x7948\x5B63" ++
+    {-0x48-}  chars "\x7A00\x7D00\x5FBD\x898F\x8A18\x8CB4\x8D77\x8ECC" ++
+    {-0x50-}  chars "\x8F1D\x98E2\x9A0E\x9B3C\x4E80\x507D\x5100\x5993" ++
+    {-0x58-}  chars "\x5B9C\x622F\x6280\x64EC\x6B3A\x72A0\x7591\x7947" ++
+    {-0x60-}  chars "\x7FA9\x87FB\x8ABC\x8B70\x63AC\x83CA\x97A0\x5409" ++
+    {-0x68-}  chars "\x5403\x55AB\x6854\x6A58\x8A70\x7827\x6775\x9ECD" ++
+    {-0x70-}  chars "\x5374\x5BA2\x811A\x8650\x9006\x4E18\x4E45\x4EC7" ++
+    {-0x78-}  chars "\x4F11\x53CA\x5438\x5BAE\x5F13\x6025\x6551" ++ Nothing :
+    {-0x80-}  chars "\x673D\x6C42\x6C72\x6CE3\x7078\x7403\x7A76\x7AAE" ++
+    {-0x88-}  chars "\x7B08\x7D1A\x7CFE\x7D66\x65E7\x725B\x53BB\x5C45" ++
+    {-0x90-}  chars "\x5DE8\x62D2\x62E0\x6319\x6E20\x865A\x8A31\x8DDD" ++
+    {-0x98-}  chars "\x92F8\x6F01\x79A6\x9B5A\x4EA8\x4EAB\x4EAC\x4F9B" ++
+    {-0xA0-}  chars "\x4FA0\x50D1\x5147\x7AF6\x5171\x51F6\x5354\x5321" ++
+    {-0xA8-}  chars "\x537F\x53EB\x55AC\x5883\x5CE1\x5F37\x5F4A\x602F" ++
+    {-0xB0-}  chars "\x6050\x606D\x631F\x6559\x6A4B\x6CC1\x72C2\x72ED" ++
+    {-0xB8-}  chars "\x77EF\x80F8\x8105\x8208\x854E\x90F7\x93E1\x97FF" ++
+    {-0xC0-}  chars "\x9957\x9A5A\x4EF0\x51DD\x5C2D\x6681\x696D\x5C40" ++
+    {-0xC8-}  chars "\x66F2\x6975\x7389\x6850\x7C81\x50C5\x52E4\x5747" ++
+    {-0xD0-}  chars "\x5DFE\x9326\x65A4\x6B23\x6B3D\x7434\x7981\x79BD" ++
+    {-0xD8-}  chars "\x7B4B\x7DCA\x82B9\x83CC\x887F\x895F\x8B39\x8FD1" ++
+    {-0xE0-}  chars "\x91D1\x541F\x9280\x4E5D\x5036\x53E5\x533A\x72D7" ++
+    {-0xE8-}  chars "\x7396\x77E9\x82E6\x8EAF\x99C6\x99C8\x99D2\x5177" ++
+    {-0xF0-}  chars "\x611A\x865E\x55B0\x7A7A\x5076\x5BD3\x9047\x9685" ++
+    {-0xF8-}  chars "\x4E32\x6ADB\x91E7\x5C51\x5C48"
+
+-- | The multibyte characters with a lead byte of @0x8C@.
+second8C :: SecondByteTable
+second8C = V.fromList $
+    {-0x40-}  chars "\x6398\x7A9F\x6C93\x9774\x8F61\x7AAA\x718A\x9688" ++
+    {-0x48-}  chars "\x7C82\x6817\x7E70\x6851\x936C\x52F2\x541B\x85AB" ++
+    {-0x50-}  chars "\x8A13\x7FA4\x8ECD\x90E1\x5366\x8888\x7941\x4FC2" ++
+    {-0x58-}  chars "\x50BE\x5211\x5144\x5553\x572D\x73EA\x578B\x5951" ++
+    {-0x60-}  chars "\x5F62\x5F84\x6075\x6176\x6167\x61A9\x63B2\x643A" ++
+    {-0x68-}  chars "\x656C\x666F\x6842\x6E13\x7566\x7A3D\x7CFB\x7D4C" ++
+    {-0x70-}  chars "\x7D99\x7E4B\x7F6B\x830E\x834A\x86CD\x8A08\x8A63" ++
+    {-0x78-}  chars "\x8B66\x8EFD\x981A\x9D8F\x82B8\x8FCE\x9BE8" ++ Nothing :
+    {-0x80-}  chars "\x5287\x621F\x6483\x6FC0\x9699\x6841\x5091\x6B20" ++
+    {-0x88-}  chars "\x6C7A\x6F54\x7A74\x7D50\x8840\x8A23\x6708\x4EF6" ++
+    {-0x90-}  chars "\x5039\x5026\x5065\x517C\x5238\x5263\x55A7\x570F" ++
+    {-0x98-}  chars "\x5805\x5ACC\x5EFA\x61B2\x61F8\x62F3\x6372\x691C" ++
+    {-0xA0-}  chars "\x6A29\x727D\x72AC\x732E\x7814\x786F\x7D79\x770C" ++
+    {-0xA8-}  chars "\x80A9\x898B\x8B19\x8CE2\x8ED2\x9063\x9375\x967A" ++
+    {-0xB0-}  chars "\x9855\x9A13\x9E78\x5143\x539F\x53B3\x5E7B\x5F26" ++
+    {-0xB8-}  chars "\x6E1B\x6E90\x7384\x73FE\x7D43\x8237\x8A00\x8AFA" ++
+    {-0xC0-}  chars "\x9650\x4E4E\x500B\x53E4\x547C\x56FA\x59D1\x5B64" ++
+    {-0xC8-}  chars "\x5DF1\x5EAB\x5F27\x6238\x6545\x67AF\x6E56\x72D0" ++
+    {-0xD0-}  chars "\x7CCA\x88B4\x80A1\x80E1\x83F0\x864E\x8A87\x8DE8" ++
+    {-0xD8-}  chars "\x9237\x96C7\x9867\x9F13\x4E94\x4E92\x4F0D\x5348" ++
+    {-0xE0-}  chars "\x5449\x543E\x5A2F\x5F8C\x5FA1\x609F\x68A7\x6A8E" ++
+    {-0xE8-}  chars "\x745A\x7881\x8A9E\x8AA4\x8B77\x9190\x4E5E\x9BC9" ++
+    {-0xF0-}  chars "\x4EA4\x4F7C\x4FAF\x5019\x5016\x5149\x516C\x529F" ++
+    {-0xF8-}  chars "\x52B9\x52FE\x539A\x53E3\x5411"
+
+-- | The multibyte characters with a lead byte of @0x8D@.
+second8D :: SecondByteTable
+second8D = V.fromList $
+    {-0x40-}  chars "\x540E\x5589\x5751\x57A2\x597D\x5B54\x5B5D\x5B8F" ++
+    {-0x48-}  chars "\x5DE5\x5DE7\x5DF7\x5E78\x5E83\x5E9A\x5EB7\x5F18" ++
+    {-0x50-}  chars "\x6052\x614C\x6297\x62D8\x63A7\x653B\x6602\x6643" ++
+    {-0x58-}  chars "\x66F4\x676D\x6821\x6897\x69CB\x6C5F\x6D2A\x6D69" ++
+    {-0x60-}  chars "\x6E2F\x6E9D\x7532\x7687\x786C\x7A3F\x7CE0\x7D05" ++
+    {-0x68-}  chars "\x7D18\x7D5E\x7DB1\x8015\x8003\x80AF\x80B1\x8154" ++
+    {-0x70-}  chars "\x818F\x822A\x8352\x884C\x8861\x8B1B\x8CA2\x8CFC" ++
+    {-0x78-}  chars "\x90CA\x9175\x9271\x783F\x92FC\x95A4\x964D" ++ Nothing :
+    {-0x80-}  chars "\x9805\x9999\x9AD8\x9D3B\x525B\x52AB\x53F7\x5408" ++
+    {-0x88-}  chars "\x58D5\x62F7\x6FE0\x8C6A\x8F5F\x9EB9\x514B\x523B" ++
+    {-0x90-}  chars "\x544A\x56FD\x7A40\x9177\x9D60\x9ED2\x7344\x6F09" ++
+    {-0x98-}  chars "\x8170\x7511\x5FFD\x60DA\x9AA8\x72DB\x8FBC\x6B64" ++
+    {-0xA0-}  chars "\x9803\x4ECA\x56F0\x5764\x58BE\x5A5A\x6068\x61C7" ++
+    {-0xA8-}  chars "\x660F\x6606\x6839\x68B1\x6DF7\x75D5\x7D3A\x826E" ++
+    {-0xB0-}  chars "\x9B42\x4E9B\x4F50\x53C9\x5506\x5D6F\x5DE6\x5DEE" ++
+    {-0xB8-}  chars "\x67FB\x6C99\x7473\x7802\x8A50\x9396\x88DF\x5750" ++
+    {-0xC0-}  chars "\x5EA7\x632B\x50B5\x50AC\x518D\x6700\x54C9\x585E" ++
+    {-0xC8-}  chars "\x59BB\x5BB0\x5F69\x624D\x63A1\x683D\x6B73\x6E08" ++
+    {-0xD0-}  chars "\x707D\x91C7\x7280\x7815\x7826\x796D\x658E\x7D30" ++
+    {-0xD8-}  chars "\x83DC\x88C1\x8F09\x969B\x5264\x5728\x6750\x7F6A" ++
+    {-0xE0-}  chars "\x8CA1\x51B4\x5742\x962A\x583A\x698A\x80B4\x54B2" ++
+    {-0xE8-}  chars "\x5D0E\x57FC\x7895\x9DFA\x4F5C\x524A\x548B\x643E" ++
+    {-0xF0-}  chars "\x6628\x6714\x67F5\x7A84\x7B56\x7D22\x932F\x685C" ++
+    {-0xF8-}  chars "\x9BAD\x7B39\x5319\x518A\x5237"
+
+-- | The multibyte characters with a lead byte of @0x8E@.
+second8E :: SecondByteTable
+second8E = V.fromList $
+    {-0x40-}  chars "\x5BDF\x62F6\x64AE\x64E6\x672D\x6BBA\x85A9\x96D1" ++
+    {-0x48-}  chars "\x7690\x9BD6\x634C\x9306\x9BAB\x76BF\x6652\x4E09" ++
+    {-0x50-}  chars "\x5098\x53C2\x5C71\x60E8\x6492\x6563\x685F\x71E6" ++
+    {-0x58-}  chars "\x73CA\x7523\x7B97\x7E82\x8695\x8B83\x8CDB\x9178" ++
+    {-0x60-}  chars "\x9910\x65AC\x66AB\x6B8B\x4ED5\x4ED4\x4F3A\x4F7F" ++
+    {-0x68-}  chars "\x523A\x53F8\x53F2\x55E3\x56DB\x58EB\x59CB\x59C9" ++
+    {-0x70-}  chars "\x59FF\x5B50\x5C4D\x5E02\x5E2B\x5FD7\x601D\x6307" ++
+    {-0x78-}  chars "\x652F\x5B5C\x65AF\x65BD\x65E8\x679D\x6B62" ++ Nothing :
+    {-0x80-}  chars "\x6B7B\x6C0F\x7345\x7949\x79C1\x7CF8\x7D19\x7D2B" ++
+    {-0x88-}  chars "\x80A2\x8102\x81F3\x8996\x8A5E\x8A69\x8A66\x8A8C" ++
+    {-0x90-}  chars "\x8AEE\x8CC7\x8CDC\x96CC\x98FC\x6B6F\x4E8B\x4F3C" ++
+    {-0x98-}  chars "\x4F8D\x5150\x5B57\x5BFA\x6148\x6301\x6642\x6B21" ++
+    {-0xA0-}  chars "\x6ECB\x6CBB\x723E\x74BD\x75D4\x78C1\x793A\x800C" ++
+    {-0xA8-}  chars "\x8033\x81EA\x8494\x8F9E\x6C50\x9E7F\x5F0F\x8B58" ++
+    {-0xB0-}  chars "\x9D2B\x7AFA\x8EF8\x5B8D\x96EB\x4E03\x53F1\x57F7" ++
+    {-0xB8-}  chars "\x5931\x5AC9\x5BA4\x6089\x6E7F\x6F06\x75BE\x8CEA" ++
+    {-0xC0-}  chars "\x5B9F\x8500\x7BE0\x5072\x67F4\x829D\x5C61\x854A" ++
+    {-0xC8-}  chars "\x7E1E\x820E\x5199\x5C04\x6368\x8D66\x659C\x716E" ++
+    {-0xD0-}  chars "\x793E\x7D17\x8005\x8B1D\x8ECA\x906E\x86C7\x90AA" ++
+    {-0xD8-}  chars "\x501F\x52FA\x5C3A\x6753\x707C\x7235\x914C\x91C8" ++
+    {-0xE0-}  chars "\x932B\x82E5\x5BC2\x5F31\x60F9\x4E3B\x53D6\x5B88" ++
+    {-0xE8-}  chars "\x624B\x6731\x6B8A\x72E9\x73E0\x7A2E\x816B\x8DA3" ++
+    {-0xF0-}  chars "\x9152\x9996\x5112\x53D7\x546A\x5BFF\x6388\x6A39" ++
+    {-0xF8-}  chars "\x7DAC\x9700\x56DA\x53CE\x5468"
+
+-- | The multibyte characters with a lead byte of @0x8F@.
+second8F :: SecondByteTable
+second8F = V.fromList $
+    {-0x40-}  chars "\x5B97\x5C31\x5DDE\x4FEE\x6101\x62FE\x6D32\x79C0" ++
+    {-0x48-}  chars "\x79CB\x7D42\x7E4D\x7FD2\x81ED\x821F\x8490\x8846" ++
+    {-0x50-}  chars "\x8972\x8B90\x8E74\x8F2F\x9031\x914B\x916C\x96C6" ++
+    {-0x58-}  chars "\x919C\x4EC0\x4F4F\x5145\x5341\x5F93\x620E\x67D4" ++
+    {-0x60-}  chars "\x6C41\x6E0B\x7363\x7E26\x91CD\x9283\x53D4\x5919" ++
+    {-0x68-}  chars "\x5BBF\x6DD1\x795D\x7E2E\x7C9B\x587E\x719F\x51FA" ++
+    {-0x70-}  chars "\x8853\x8FF0\x4FCA\x5CFB\x6625\x77AC\x7AE3\x821C" ++
+    {-0x78-}  chars "\x99FF\x51C6\x5FAA\x65EC\x696F\x6B89\x6DF3" ++ Nothing :
+    {-0x80-}  chars "\x6E96\x6F64\x76FE\x7D14\x5DE1\x9075\x9187\x9806" ++
+    {-0x88-}  chars "\x51E6\x521D\x6240\x6691\x66D9\x6E1A\x5EB6\x7DD2" ++
+    {-0x90-}  chars "\x7F72\x66F8\x85AF\x85F7\x8AF8\x52A9\x53D9\x5973" ++
+    {-0x98-}  chars "\x5E8F\x5F90\x6055\x92E4\x9664\x50B7\x511F\x52DD" ++
+    {-0xA0-}  chars "\x5320\x5347\x53EC\x54E8\x5546\x5531\x5617\x5968" ++
+    {-0xA8-}  chars "\x59BE\x5A3C\x5BB5\x5C06\x5C0F\x5C11\x5C1A\x5E84" ++
+    {-0xB0-}  chars "\x5E8A\x5EE0\x5F70\x627F\x6284\x62DB\x638C\x6377" ++
+    {-0xB8-}  chars "\x6607\x660C\x662D\x6676\x677E\x68A2\x6A1F\x6A35" ++
+    {-0xC0-}  chars "\x6CBC\x6D88\x6E09\x6E58\x713C\x7126\x7167\x75C7" ++
+    {-0xC8-}  chars "\x7701\x785D\x7901\x7965\x79F0\x7AE0\x7B11\x7CA7" ++
+    {-0xD0-}  chars "\x7D39\x8096\x83D6\x848B\x8549\x885D\x88F3\x8A1F" ++
+    {-0xD8-}  chars "\x8A3C\x8A54\x8A73\x8C61\x8CDE\x91A4\x9266\x937E" ++
+    {-0xE0-}  chars "\x9418\x969C\x9798\x4E0A\x4E08\x4E1E\x4E57\x5197" ++
+    {-0xE8-}  chars "\x5270\x57CE\x5834\x58CC\x5B22\x5E38\x60C5\x64FE" ++
+    {-0xF0-}  chars "\x6761\x6756\x6D44\x72B6\x7573\x7A63\x84B8\x8B72" ++
+    {-0xF8-}  chars "\x91B8\x9320\x5631\x57F4\x98FE"
+
+-- | The multibyte characters with a lead byte of @0x90@.
+second90 :: SecondByteTable
+second90 = V.fromList $
+    {-0x40-}  chars "\x62ED\x690D\x6B96\x71ED\x7E54\x8077\x8272\x89E6" ++
+    {-0x48-}  chars "\x98DF\x8755\x8FB1\x5C3B\x4F38\x4FE1\x4FB5\x5507" ++
+    {-0x50-}  chars "\x5A20\x5BDD\x5BE9\x5FC3\x614E\x632F\x65B0\x664B" ++
+    {-0x58-}  chars "\x68EE\x699B\x6D78\x6DF1\x7533\x75B9\x771F\x795E" ++
+    {-0x60-}  chars "\x79E6\x7D33\x81E3\x82AF\x85AA\x89AA\x8A3A\x8EAB" ++
+    {-0x68-}  chars "\x8F9B\x9032\x91DD\x9707\x4EBA\x4EC1\x5203\x5875" ++
+    {-0x70-}  chars "\x58EC\x5C0B\x751A\x5C3D\x814E\x8A0A\x8FC5\x9663" ++
+    {-0x78-}  chars "\x976D\x7B25\x8ACF\x9808\x9162\x56F3\x53A8" ++ Nothing :
+    {-0x80-}  chars "\x9017\x5439\x5782\x5E25\x63A8\x6C34\x708A\x7761" ++
+    {-0x88-}  chars "\x7C8B\x7FE0\x8870\x9042\x9154\x9310\x9318\x968F" ++
+    {-0x90-}  chars "\x745E\x9AC4\x5D07\x5D69\x6570\x67A2\x8DA8\x96DB" ++
+    {-0x98-}  chars "\x636E\x6749\x6919\x83C5\x9817\x96C0\x88FE\x6F84" ++
+    {-0xA0-}  chars "\x647A\x5BF8\x4E16\x702C\x755D\x662F\x51C4\x5236" ++
+    {-0xA8-}  chars "\x52E2\x59D3\x5F81\x6027\x6210\x653F\x6574\x661F" ++
+    {-0xB0-}  chars "\x6674\x68F2\x6816\x6B63\x6E05\x7272\x751F\x76DB" ++
+    {-0xB8-}  chars "\x7CBE\x8056\x58F0\x88FD\x897F\x8AA0\x8A93\x8ACB" ++
+    {-0xC0-}  chars "\x901D\x9192\x9752\x9759\x6589\x7A0E\x8106\x96BB" ++
+    {-0xC8-}  chars "\x5E2D\x60DC\x621A\x65A5\x6614\x6790\x77F3\x7A4D" ++
+    {-0xD0-}  chars "\x7C4D\x7E3E\x810A\x8CAC\x8D64\x8DE1\x8E5F\x78A9" ++
+    {-0xD8-}  chars "\x5207\x62D9\x63A5\x6442\x6298\x8A2D\x7A83\x7BC0" ++
+    {-0xE0-}  chars "\x8AAC\x96EA\x7D76\x820C\x8749\x4ED9\x5148\x5343" ++
+    {-0xE8-}  chars "\x5360\x5BA3\x5C02\x5C16\x5DDD\x6226\x6247\x64B0" ++
+    {-0xF0-}  chars "\x6813\x6834\x6CC9\x6D45\x6D17\x67D3\x6F5C\x714E" ++
+    {-0xF8-}  chars "\x717D\x65CB\x7A7F\x7BAD\x7DDA"
+
+-- | The multibyte characters with a lead byte of @0x91@.
+second91 :: SecondByteTable
+second91 = V.fromList $
+    {-0x40-}  chars "\x7E4A\x7FA8\x817A\x821B\x8239\x85A6\x8A6E\x8CCE" ++
+    {-0x48-}  chars "\x8DF5\x9078\x9077\x92AD\x9291\x9583\x9BAE\x524D" ++
+    {-0x50-}  chars "\x5584\x6F38\x7136\x5168\x7985\x7E55\x81B3\x7CCE" ++
+    {-0x58-}  chars "\x564C\x5851\x5CA8\x63AA\x66FE\x66FD\x695A\x72D9" ++
+    {-0x60-}  chars "\x758F\x758E\x790E\x7956\x79DF\x7C97\x7D20\x7D44" ++
+    {-0x68-}  chars "\x8607\x8A34\x963B\x9061\x9F20\x50E7\x5275\x53CC" ++
+    {-0x70-}  chars "\x53E2\x5009\x55AA\x58EE\x594F\x723D\x5B8B\x5C64" ++
+    {-0x78-}  chars "\x531D\x60E3\x60F3\x635C\x6383\x633F\x63BB" ++ Nothing :
+    {-0x80-}  chars "\x64CD\x65E9\x66F9\x5DE3\x69CD\x69FD\x6F15\x71E5" ++
+    {-0x88-}  chars "\x4E89\x75E9\x76F8\x7A93\x7CDF\x7DCF\x7D9C\x8061" ++
+    {-0x90-}  chars "\x8349\x8358\x846C\x84BC\x85FB\x88C5\x8D70\x9001" ++
+    {-0x98-}  chars "\x906D\x9397\x971C\x9A12\x50CF\x5897\x618E\x81D3" ++
+    {-0xA0-}  chars "\x8535\x8D08\x9020\x4FC3\x5074\x5247\x5373\x606F" ++
+    {-0xA8-}  chars "\x6349\x675F\x6E2C\x8DB3\x901F\x4FD7\x5C5E\x8CCA" ++
+    {-0xB0-}  chars "\x65CF\x7D9A\x5352\x8896\x5176\x63C3\x5B58\x5B6B" ++
+    {-0xB8-}  chars "\x5C0A\x640D\x6751\x905C\x4ED6\x591A\x592A\x6C70" ++
+    {-0xC0-}  chars "\x8A51\x553E\x5815\x59A5\x60F0\x6253\x67C1\x8235" ++
+    {-0xC8-}  chars "\x6955\x9640\x99C4\x9A28\x4F53\x5806\x5BFE\x8010" ++
+    {-0xD0-}  chars "\x5CB1\x5E2F\x5F85\x6020\x614B\x6234\x66FF\x6CF0" ++
+    {-0xD8-}  chars "\x6EDE\x80CE\x817F\x82D4\x888B\x8CB8\x9000\x902E" ++
+    {-0xE0-}  chars "\x968A\x9EDB\x9BDB\x4EE3\x53F0\x5927\x7B2C\x918D" ++
+    {-0xE8-}  chars "\x984C\x9DF9\x6EDD\x7027\x5353\x5544\x5B85\x6258" ++
+    {-0xF0-}  chars "\x629E\x62D3\x6CA2\x6FEF\x7422\x8A17\x9438\x6FC1" ++
+    {-0xF8-}  chars "\x8AFE\x8338\x51E7\x86F8\x53EA"
+
+-- | The multibyte characters with a lead byte of @0x92@.
+second92 :: SecondByteTable
+second92 = V.fromList $
+    {-0x40-}  chars "\x53E9\x4F46\x9054\x8FB0\x596A\x8131\x5DFD\x7AEA" ++
+    {-0x48-}  chars "\x8FBF\x68DA\x8C37\x72F8\x9C48\x6A3D\x8AB0\x4E39" ++
+    {-0x50-}  chars "\x5358\x5606\x5766\x62C5\x63A2\x65E6\x6B4E\x6DE1" ++
+    {-0x58-}  chars "\x6E5B\x70AD\x77ED\x7AEF\x7BAA\x7DBB\x803D\x80C6" ++
+    {-0x60-}  chars "\x86CB\x8A95\x935B\x56E3\x58C7\x5F3E\x65AD\x6696" ++
+    {-0x68-}  chars "\x6A80\x6BB5\x7537\x8AC7\x5024\x77E5\x5730\x5F1B" ++
+    {-0x70-}  chars "\x6065\x667A\x6C60\x75F4\x7A1A\x7F6E\x81F4\x8718" ++
+    {-0x78-}  chars "\x9045\x99B3\x7BC9\x755C\x7AF9\x7B51\x84C4" ++ Nothing :
+    {-0x80-}  chars "\x9010\x79E9\x7A92\x8336\x5AE1\x7740\x4E2D\x4EF2" ++
+    {-0x88-}  chars "\x5B99\x5FE0\x62BD\x663C\x67F1\x6CE8\x866B\x8877" ++
+    {-0x90-}  chars "\x8A3B\x914E\x92F3\x99D0\x6A17\x7026\x732A\x82E7" ++
+    {-0x98-}  chars "\x8457\x8CAF\x4E01\x5146\x51CB\x558B\x5BF5\x5E16" ++
+    {-0xA0-}  chars "\x5E33\x5E81\x5F14\x5F35\x5F6B\x5FB4\x61F2\x6311" ++
+    {-0xA8-}  chars "\x66A2\x671D\x6F6E\x7252\x753A\x773A\x8074\x8139" ++
+    {-0xB0-}  chars "\x8178\x8776\x8ABF\x8ADC\x8D85\x8DF3\x929A\x9577" ++
+    {-0xB8-}  chars "\x9802\x9CE5\x52C5\x6357\x76F4\x6715\x6C88\x73CD" ++
+    {-0xC0-}  chars "\x8CC3\x93AE\x9673\x6D25\x589C\x690E\x69CC\x8FFD" ++
+    {-0xC8-}  chars "\x939A\x75DB\x901A\x585A\x6802\x63B4\x69FB\x4F43" ++
+    {-0xD0-}  chars "\x6F2C\x67D8\x8FBB\x8526\x7DB4\x9354\x693F\x6F70" ++
+    {-0xD8-}  chars "\x576A\x58F7\x5B2C\x7D2C\x722A\x540A\x91E3\x9DB4" ++
+    {-0xE0-}  chars "\x4EAD\x4F4E\x505C\x5075\x5243\x8C9E\x5448\x5824" ++
+    {-0xE8-}  chars "\x5B9A\x5E1D\x5E95\x5EAD\x5EF7\x5F1F\x608C\x62B5" ++
+    {-0xF0-}  chars "\x633A\x63D0\x68AF\x6C40\x7887\x798E\x7A0B\x7DE0" ++
+    {-0xF8-}  chars "\x8247\x8A02\x8AE6\x8E44\x9013"
+
+-- | The multibyte characters with a lead byte of @0x93@.
+second93 :: SecondByteTable
+second93 = V.fromList $
+    {-0x40-}  chars "\x90B8\x912D\x91D8\x9F0E\x6CE5\x6458\x64E2\x6575" ++
+    {-0x48-}  chars "\x6EF4\x7684\x7B1B\x9069\x93D1\x6EBA\x54F2\x5FB9" ++
+    {-0x50-}  chars "\x64A4\x8F4D\x8FED\x9244\x5178\x586B\x5929\x5C55" ++
+    {-0x58-}  chars "\x5E97\x6DFB\x7E8F\x751C\x8CBC\x8EE2\x985B\x70B9" ++
+    {-0x60-}  chars "\x4F1D\x6BBF\x6FB1\x7530\x96FB\x514E\x5410\x5835" ++
+    {-0x68-}  chars "\x5857\x59AC\x5C60\x5F92\x6597\x675C\x6E21\x767B" ++
+    {-0x70-}  chars "\x83DF\x8CED\x9014\x90FD\x934D\x7825\x783A\x52AA" ++
+    {-0x78-}  chars "\x5EA6\x571F\x5974\x6012\x5012\x515A\x51AC" ++ Nothing :
+    {-0x80-}  chars "\x51CD\x5200\x5510\x5854\x5858\x5957\x5B95\x5CF6" ++
+    {-0x88-}  chars "\x5D8B\x60BC\x6295\x642D\x6771\x6843\x68BC\x68DF" ++
+    {-0x90-}  chars "\x76D7\x6DD8\x6E6F\x6D9B\x706F\x71C8\x5F53\x75D8" ++
+    {-0x98-}  chars "\x7977\x7B49\x7B54\x7B52\x7CD6\x7D71\x5230\x8463" ++
+    {-0xA0-}  chars "\x8569\x85E4\x8A0E\x8B04\x8C46\x8E0F\x9003\x900F" ++
+    {-0xA8-}  chars "\x9419\x9676\x982D\x9A30\x95D8\x50CD\x52D5\x540C" ++
+    {-0xB0-}  chars "\x5802\x5C0E\x61A7\x649E\x6D1E\x77B3\x7AE5\x80F4" ++
+    {-0xB8-}  chars "\x8404\x9053\x9285\x5CE0\x9D07\x533F\x5F97\x5FB3" ++
+    {-0xC0-}  chars "\x6D9C\x7279\x7763\x79BF\x7BE4\x6BD2\x72EC\x8AAD" ++
+    {-0xC8-}  chars "\x6803\x6A61\x51F8\x7A81\x6934\x5C4A\x9CF6\x82EB" ++
+    {-0xD0-}  chars "\x5BC5\x9149\x701E\x5678\x5C6F\x60C7\x6566\x6C8C" ++
+    {-0xD8-}  chars "\x8C5A\x9041\x9813\x5451\x66C7\x920D\x5948\x90A3" ++
+    {-0xE0-}  chars "\x5185\x4E4D\x51EA\x8599\x8B0E\x7058\x637A\x934B" ++
+    {-0xE8-}  chars "\x6962\x99B4\x7E04\x7577\x5357\x6960\x8EDF\x96E3" ++
+    {-0xF0-}  chars "\x6C5D\x4E8C\x5C3C\x5F10\x8FE9\x5302\x8CD1\x8089" ++
+    {-0xF8-}  chars "\x8679\x5EFF\x65E5\x4E73\x5165"
+
+-- | The multibyte characters with a lead byte of @0x94@.
+second94 :: SecondByteTable
+second94 = V.fromList $
+    {-0x40-}  chars "\x5982\x5C3F\x97EE\x4EFB\x598A\x5FCD\x8A8D\x6FE1" ++
+    {-0x48-}  chars "\x79B0\x7962\x5BE7\x8471\x732B\x71B1\x5E74\x5FF5" ++
+    {-0x50-}  chars "\x637B\x649A\x71C3\x7C98\x4E43\x5EFC\x4E4B\x57DC" ++
+    {-0x58-}  chars "\x56A2\x60A9\x6FC3\x7D0D\x80FD\x8133\x81BF\x8FB2" ++
+    {-0x60-}  chars "\x8997\x86A4\x5DF4\x628A\x64AD\x8987\x6777\x6CE2" ++
+    {-0x68-}  chars "\x6D3E\x7436\x7834\x5A46\x7F75\x82AD\x99AC\x4FF3" ++
+    {-0x70-}  chars "\x5EC3\x62DD\x6392\x6557\x676F\x76C3\x724C\x80CC" ++
+    {-0x78-}  chars "\x80BA\x8F29\x914D\x500D\x57F9\x5A92\x6885" ++ Nothing :
+    {-0x80-}  chars "\x6973\x7164\x72FD\x8CB7\x58F2\x8CE0\x966A\x9019" ++
+    {-0x88-}  chars "\x877F\x79E4\x77E7\x8429\x4F2F\x5265\x535A\x62CD" ++
+    {-0x90-}  chars "\x67CF\x6CCA\x767D\x7B94\x7C95\x8236\x8584\x8FEB" ++
+    {-0x98-}  chars "\x66DD\x6F20\x7206\x7E1B\x83AB\x99C1\x9EA6\x51FD" ++
+    {-0xA0-}  chars "\x7BB1\x7872\x7BB8\x8087\x7B48\x6AE8\x5E61\x808C" ++
+    {-0xA8-}  chars "\x7551\x7560\x516B\x9262\x6E8C\x767A\x9197\x9AEA" ++
+    {-0xB0-}  chars "\x4F10\x7F70\x629C\x7B4F\x95A5\x9CE9\x567A\x5859" ++
+    {-0xB8-}  chars "\x86E4\x96BC\x4F34\x5224\x534A\x53CD\x53DB\x5E06" ++
+    {-0xC0-}  chars "\x642C\x6591\x677F\x6C3E\x6C4E\x7248\x72AF\x73ED" ++
+    {-0xC8-}  chars "\x7554\x7E41\x822C\x85E9\x8CA9\x7BC4\x91C6\x7169" ++
+    {-0xD0-}  chars "\x9812\x98EF\x633D\x6669\x756A\x76E4\x78D0\x8543" ++
+    {-0xD8-}  chars "\x86EE\x532A\x5351\x5426\x5983\x5E87\x5F7C\x60B2" ++
+    {-0xE0-}  chars "\x6249\x6279\x62AB\x6590\x6BD4\x6CCC\x75B2\x76AE" ++
+    {-0xE8-}  chars "\x7891\x79D8\x7DCB\x7F77\x80A5\x88AB\x8AB9\x8CBB" ++
+    {-0xF0-}  chars "\x907F\x975E\x98DB\x6A0B\x7C38\x5099\x5C3E\x5FAE" ++
+    {-0xF8-}  chars "\x6787\x6BD8\x7435\x7709\x7F8E"
+
+-- | The multibyte characters with a lead byte of @0x95@.
+second95 :: SecondByteTable
+second95 = V.fromList $
+    {-0x40-}  chars "\x9F3B\x67CA\x7A17\x5339\x758B\x9AED\x5F66\x819D" ++
+    {-0x48-}  chars "\x83F1\x8098\x5F3C\x5FC5\x7562\x7B46\x903C\x6867" ++
+    {-0x50-}  chars "\x59EB\x5A9B\x7D10\x767E\x8B2C\x4FF5\x5F6A\x6A19" ++
+    {-0x58-}  chars "\x6C37\x6F02\x74E2\x7968\x8868\x8A55\x8C79\x5EDF" ++
+    {-0x60-}  chars "\x63CF\x75C5\x79D2\x82D7\x9328\x92F2\x849C\x86ED" ++
+    {-0x68-}  chars "\x9C2D\x54C1\x5F6C\x658C\x6D5C\x7015\x8CA7\x8CD3" ++
+    {-0x70-}  chars "\x983B\x654F\x74F6\x4E0D\x4ED8\x57E0\x592B\x5A66" ++
+    {-0x78-}  chars "\x5BCC\x51A8\x5E03\x5E9C\x6016\x6276\x6577" ++ Nothing :
+    {-0x80-}  chars "\x65A7\x666E\x6D6E\x7236\x7B26\x8150\x819A\x8299" ++
+    {-0x88-}  chars "\x8B5C\x8CA0\x8CE6\x8D74\x961C\x9644\x4FAE\x64AB" ++
+    {-0x90-}  chars "\x6B66\x821E\x8461\x856A\x90E8\x5C01\x6953\x98A8" ++
+    {-0x98-}  chars "\x847A\x8557\x4F0F\x526F\x5FA9\x5E45\x670D\x798F" ++
+    {-0xA0-}  chars "\x8179\x8907\x8986\x6DF5\x5F17\x6255\x6CB8\x4ECF" ++
+    {-0xA8-}  chars "\x7269\x9B92\x5206\x543B\x5674\x58B3\x61A4\x626E" ++
+    {-0xB0-}  chars "\x711A\x596E\x7C89\x7CDE\x7D1B\x96F0\x6587\x805E" ++
+    {-0xB8-}  chars "\x4E19\x4F75\x5175\x5840\x5E63\x5E73\x5F0A\x67C4" ++
+    {-0xC0-}  chars "\x4E26\x853D\x9589\x965B\x7C73\x9801\x50FB\x58C1" ++
+    {-0xC8-}  chars "\x7656\x78A7\x5225\x77A5\x8511\x7B86\x504F\x5909" ++
+    {-0xD0-}  chars "\x7247\x7BC7\x7DE8\x8FBA\x8FD4\x904D\x4FBF\x52C9" ++
+    {-0xD8-}  chars "\x5A29\x5F01\x97AD\x4FDD\x8217\x92EA\x5703\x6355" ++
+    {-0xE0-}  chars "\x6B69\x752B\x88DC\x8F14\x7A42\x52DF\x5893\x6155" ++
+    {-0xE8-}  chars "\x620A\x66AE\x6BCD\x7C3F\x83E9\x5023\x4FF8\x5305" ++
+    {-0xF0-}  chars "\x5446\x5831\x5949\x5B9D\x5CF0\x5CEF\x5D29\x5E96" ++
+    {-0xF8-}  chars "\x62B1\x6367\x653E\x65B9\x670B"
+
+-- | The multibyte characters with a lead byte of @0x96@.
+second96 :: SecondByteTable
+second96 = V.fromList $
+    {-0x40-}  chars "\x6CD5\x6CE1\x70F9\x7832\x7E2B\x80DE\x82B3\x840C" ++
+    {-0x48-}  chars "\x84EC\x8702\x8912\x8A2A\x8C4A\x90A6\x92D2\x98FD" ++
+    {-0x50-}  chars "\x9CF3\x9D6C\x4E4F\x4EA1\x508D\x5256\x574A\x59A8" ++
+    {-0x58-}  chars "\x5E3D\x5FD8\x5FD9\x623F\x66B4\x671B\x67D0\x68D2" ++
+    {-0x60-}  chars "\x5192\x7D21\x80AA\x81A8\x8B00\x8C8C\x8CBF\x927E" ++
+    {-0x68-}  chars "\x9632\x5420\x982C\x5317\x50D5\x535C\x58A8\x64B2" ++
+    {-0x70-}  chars "\x6734\x7267\x7766\x7A46\x91E6\x52C3\x6CA1\x6B86" ++
+    {-0x78-}  chars "\x5800\x5E4C\x5954\x672C\x7FFB\x51E1\x76C6" ++ Nothing :
+    {-0x80-}  chars "\x6469\x78E8\x9B54\x9EBB\x57CB\x59B9\x6627\x679A" ++
+    {-0x88-}  chars "\x6BCE\x54E9\x69D9\x5E55\x819C\x6795\x9BAA\x67FE" ++
+    {-0x90-}  chars "\x9C52\x685D\x4EA6\x4FE3\x53C8\x62B9\x672B\x6CAB" ++
+    {-0x98-}  chars "\x8FC4\x4FAD\x7E6D\x9EBF\x4E07\x6162\x6E80\x6F2B" ++
+    {-0xA0-}  chars "\x8513\x5473\x672A\x9B45\x5DF3\x7B95\x5CAC\x5BC6" ++
+    {-0xA8-}  chars "\x871C\x6E4A\x84D1\x7A14\x8108\x5999\x7C8D\x6C11" ++
+    {-0xB0-}  chars "\x7720\x52D9\x5922\x7121\x725F\x77DB\x9727\x9D61" ++
+    {-0xB8-}  chars "\x690B\x5A7F\x5A18\x51A5\x540D\x547D\x660E\x76DF" ++
+    {-0xC0-}  chars "\x8FF7\x9298\x9CF4\x59EA\x725D\x6EC5\x514D\x68C9" ++
+    {-0xC8-}  chars "\x7DBF\x7DEC\x9762\x9EBA\x6478\x6A21\x8302\x5984" ++
+    {-0xD0-}  chars "\x5B5F\x6BDB\x731B\x76F2\x7DB2\x8017\x8499\x5132" ++
+    {-0xD8-}  chars "\x6728\x9ED9\x76EE\x6762\x52FF\x9905\x5C24\x623B" ++
+    {-0xE0-}  chars "\x7C7E\x8CB0\x554F\x60B6\x7D0B\x9580\x5301\x4E5F" ++
+    {-0xE8-}  chars "\x51B6\x591C\x723A\x8036\x91CE\x5F25\x77E2\x5384" ++
+    {-0xF0-}  chars "\x5F79\x7D04\x85AC\x8A33\x8E8D\x9756\x67F3\x85AE" ++
+    {-0xF8-}  chars "\x9453\x6109\x6108\x6CB9\x7652"
+
+-- | The multibyte characters with a lead byte of @0x97@.
+second97 :: SecondByteTable
+second97 = V.fromList $
+    {-0x40-}  chars "\x8AED\x8F38\x552F\x4F51\x512A\x52C7\x53CB\x5BA5" ++
+    {-0x48-}  chars "\x5E7D\x60A0\x6182\x63D6\x6709\x67DA\x6E67\x6D8C" ++
+    {-0x50-}  chars "\x7336\x7337\x7531\x7950\x88D5\x8A98\x904A\x9091" ++
+    {-0x58-}  chars "\x90F5\x96C4\x878D\x5915\x4E88\x4F59\x4E0E\x8A89" ++
+    {-0x60-}  chars "\x8F3F\x9810\x50AD\x5E7C\x5996\x5BB9\x5EB8\x63DA" ++
+    {-0x68-}  chars "\x63FA\x64C1\x66DC\x694A\x69D8\x6D0B\x6EB6\x7194" ++
+    {-0x70-}  chars "\x7528\x7AAF\x7F8A\x8000\x8449\x84C9\x8981\x8B21" ++
+    {-0x78-}  chars "\x8E0A\x9065\x967D\x990A\x617E\x6291\x6B32" ++ Nothing :
+    {-0x80-}  chars "\x6C83\x6D74\x7FCC\x7FFC\x6DC0\x7F85\x87BA\x88F8" ++
+    {-0x88-}  chars "\x6765\x83B1\x983C\x96F7\x6D1B\x7D61\x843D\x916A" ++
+    {-0x90-}  chars "\x4E71\x5375\x5D50\x6B04\x6FEB\x85CD\x862D\x89A7" ++
+    {-0x98-}  chars "\x5229\x540F\x5C65\x674E\x68A8\x7406\x7483\x75E2" ++
+    {-0xA0-}  chars "\x88CF\x88E1\x91CC\x96E2\x9678\x5F8B\x7387\x7ACB" ++
+    {-0xA8-}  chars "\x844E\x63A0\x7565\x5289\x6D41\x6E9C\x7409\x7559" ++
+    {-0xB0-}  chars "\x786B\x7C92\x9686\x7ADC\x9F8D\x4FB6\x616E\x65C5" ++
+    {-0xB8-}  chars "\x865C\x4E86\x4EAE\x50DA\x4E21\x51CC\x5BEE\x6599" ++
+    {-0xC0-}  chars "\x6881\x6DBC\x731F\x7642\x77AD\x7A1C\x7CE7\x826F" ++
+    {-0xC8-}  chars "\x8AD2\x907C\x91CF\x9675\x9818\x529B\x7DD1\x502B" ++
+    {-0xD0-}  chars "\x5398\x6797\x6DCB\x71D0\x7433\x81E8\x8F2A\x96A3" ++
+    {-0xD8-}  chars "\x9C57\x9E9F\x7460\x5841\x6D99\x7D2F\x985E\x4EE4" ++
+    {-0xE0-}  chars "\x4F36\x4F8B\x51B7\x52B1\x5DBA\x601C\x73B2\x793C" ++
+    {-0xE8-}  chars "\x82D3\x9234\x96B7\x96F6\x970A\x9E97\x9F62\x66A6" ++
+    {-0xF0-}  chars "\x6B74\x5217\x52A3\x70C8\x88C2\x5EC9\x604B\x6190" ++
+    {-0xF8-}  chars "\x6F23\x7149\x7C3E\x7DF4\x806F"
+
+-- | The multibyte characters with a lead byte of @0x98@.
+second98 :: SecondByteTable
+second98 = V.fromList $
+    {-0x40-}  chars "\x84EE\x9023\x932C\x5442\x9B6F\x6AD3\x7089\x8CC2" ++
+    {-0x48-}  chars "\x8DEF\x9732\x52B4\x5A41\x5ECA\x5F04\x6717\x697C" ++
+    {-0x50-}  chars "\x6994\x6D6A\x6F0F\x7262\x72FC\x7BED\x8001\x807E" ++
+    {-0x58-}  chars "\x874B\x90CE\x516D\x9E93\x7984\x808B\x9332\x8AD6" ++
+    {-0x60-}  chars "\x502D\x548C\x8A71\x6B6A\x8CC4\x8107\x60D1\x67A0" ++
+    {-0x68-}  chars "\x9DF2\x4E99\x4E98\x9C10\x8A6B\x85C1\x8568\x6900" ++
+    {-0x70-}  chars "\x6E7E\x7897\x8155" ++
+    {-0x73..0x9F-} nothings 0x2C ++ Just '\x5F0C' :
+    {-0xA0-}  chars "\x4E10\x4E15\x4E2A\x4E31\x4E36\x4E3C\x4E3F\x4E42" ++
+    {-0xA8-}  chars "\x4E56\x4E58\x4E82\x4E85\x8C6B\x4E8A\x8212\x5F0D" ++
+    {-0xB0-}  chars "\x4E8E\x4E9E\x4E9F\x4EA0\x4EA2\x4EB0\x4EB3\x4EB6" ++
+    {-0xB8-}  chars "\x4ECE\x4ECD\x4EC4\x4EC6\x4EC2\x4ED7\x4EDE\x4EED" ++
+    {-0xC0-}  chars "\x4EDF\x4EF7\x4F09\x4F5A\x4F30\x4F5B\x4F5D\x4F57" ++
+    {-0xC8-}  chars "\x4F47\x4F76\x4F88\x4F8F\x4F98\x4F7B\x4F69\x4F70" ++
+    {-0xD0-}  chars "\x4F91\x4F6F\x4F86\x4F96\x5118\x4FD4\x4FDF\x4FCE" ++
+    {-0xD8-}  chars "\x4FD8\x4FDB\x4FD1\x4FDA\x4FD0\x4FE4\x4FE5\x501A" ++
+    {-0xE0-}  chars "\x5028\x5014\x502A\x5025\x5005\x4F1C\x4FF6\x5021" ++
+    {-0xE8-}  chars "\x5029\x502C\x4FFE\x4FEF\x5011\x5006\x5043\x5047" ++
+    {-0xF0-}  chars "\x6703\x5055\x5050\x5048\x505A\x5056\x506C\x5078" ++
+    {-0xF8-}  chars "\x5080\x509A\x5085\x50B4\x50B2"
+
+-- | The multibyte characters with a lead byte of @0x99@.
+second99 :: SecondByteTable
+second99 = V.fromList $
+    {-0x40-}  chars "\x50C9\x50CA\x50B3\x50C2\x50D6\x50DE\x50E5\x50ED" ++
+    {-0x48-}  chars "\x50E3\x50EE\x50F9\x50F5\x5109\x5101\x5102\x5116" ++
+    {-0x50-}  chars "\x5115\x5114\x511A\x5121\x513A\x5137\x513C\x513B" ++
+    {-0x58-}  chars "\x513F\x5140\x5152\x514C\x5154\x5162\x7AF8\x5169" ++
+    {-0x60-}  chars "\x516A\x516E\x5180\x5182\x56D8\x518C\x5189\x518F" ++
+    {-0x68-}  chars "\x5191\x5193\x5195\x5196\x51A4\x51A6\x51A2\x51A9" ++
+    {-0x70-}  chars "\x51AA\x51AB\x51B3\x51B1\x51B2\x51B0\x51B5\x51BD" ++
+    {-0x78-}  chars "\x51C5\x51C9\x51DB\x51E0\x8655\x51E9\x51ED" ++ Nothing :
+    {-0x80-}  chars "\x51F0\x51F5\x51FE\x5204\x520B\x5214\x520E\x5227" ++
+    {-0x88-}  chars "\x522A\x522E\x5233\x5239\x524F\x5244\x524B\x524C" ++
+    {-0x90-}  chars "\x525E\x5254\x526A\x5274\x5269\x5273\x527F\x527D" ++
+    {-0x98-}  chars "\x528D\x5294\x5292\x5271\x5288\x5291\x8FA8\x8FA7" ++
+    {-0xA0-}  chars "\x52AC\x52AD\x52BC\x52B5\x52C1\x52CD\x52D7\x52DE" ++
+    {-0xA8-}  chars "\x52E3\x52E6\x98ED\x52E0\x52F3\x52F5\x52F8\x52F9" ++
+    {-0xB0-}  chars "\x5306\x5308\x7538\x530D\x5310\x530F\x5315\x531A" ++
+    {-0xB8-}  chars "\x5323\x532F\x5331\x5333\x5338\x5340\x5346\x5345" ++
+    {-0xC0-}  chars "\x4E17\x5349\x534D\x51D6\x535E\x5369\x536E\x5918" ++
+    {-0xC8-}  chars "\x537B\x5377\x5382\x5396\x53A0\x53A6\x53A5\x53AE" ++
+    {-0xD0-}  chars "\x53B0\x53B6\x53C3\x7C12\x96D9\x53DF\x66FC\x71EE" ++
+    {-0xD8-}  chars "\x53EE\x53E8\x53ED\x53FA\x5401\x543D\x5440\x542C" ++
+    {-0xE0-}  chars "\x542D\x543C\x542E\x5436\x5429\x541D\x544E\x548F" ++
+    {-0xE8-}  chars "\x5475\x548E\x545F\x5471\x5477\x5470\x5492\x547B" ++
+    {-0xF0-}  chars "\x5480\x5476\x5484\x5490\x5486\x54C7\x54A2\x54B8" ++
+    {-0xF8-}  chars "\x54A5\x54AC\x54C4\x54C8\x54A8"
+
+-- | The multibyte characters with a lead byte of @0x9A@.
+second9A :: SecondByteTable
+second9A = V.fromList $
+    {-0x40-}  chars "\x54AB\x54C2\x54A4\x54BE\x54BC\x54D8\x54E5\x54E6" ++
+    {-0x48-}  chars "\x550F\x5514\x54FD\x54EE\x54ED\x54FA\x54E2\x5539" ++
+    {-0x50-}  chars "\x5540\x5563\x554C\x552E\x555C\x5545\x5556\x5557" ++
+    {-0x58-}  chars "\x5538\x5533\x555D\x5599\x5580\x54AF\x558A\x559F" ++
+    {-0x60-}  chars "\x557B\x557E\x5598\x559E\x55AE\x557C\x5583\x55A9" ++
+    {-0x68-}  chars "\x5587\x55A8\x55DA\x55C5\x55DF\x55C4\x55DC\x55E4" ++
+    {-0x70-}  chars "\x55D4\x5614\x55F7\x5616\x55FE\x55FD\x561B\x55F9" ++
+    {-0x78-}  chars "\x564E\x5650\x71DF\x5634\x5636\x5632\x5638" ++ Nothing :
+    {-0x80-}  chars "\x566B\x5664\x562F\x566C\x566A\x5686\x5680\x568A" ++
+    {-0x88-}  chars "\x56A0\x5694\x568F\x56A5\x56AE\x56B6\x56B4\x56C2" ++
+    {-0x90-}  chars "\x56BC\x56C1\x56C3\x56C0\x56C8\x56CE\x56D1\x56D3" ++
+    {-0x98-}  chars "\x56D7\x56EE\x56F9\x5700\x56FF\x5704\x5709\x5708" ++
+    {-0xA0-}  chars "\x570B\x570D\x5713\x5718\x5716\x55C7\x571C\x5726" ++
+    {-0xA8-}  chars "\x5737\x5738\x574E\x573B\x5740\x574F\x5769\x57C0" ++
+    {-0xB0-}  chars "\x5788\x5761\x577F\x5789\x5793\x57A0\x57B3\x57A4" ++
+    {-0xB8-}  chars "\x57AA\x57B0\x57C3\x57C6\x57D4\x57D2\x57D3\x580A" ++
+    {-0xC0-}  chars "\x57D6\x57E3\x580B\x5819\x581D\x5872\x5821\x5862" ++
+    {-0xC8-}  chars "\x584B\x5870\x6BC0\x5852\x583D\x5879\x5885\x58B9" ++
+    {-0xD0-}  chars "\x589F\x58AB\x58BA\x58DE\x58BB\x58B8\x58AE\x58C5" ++
+    {-0xD8-}  chars "\x58D3\x58D1\x58D7\x58D9\x58D8\x58E5\x58DC\x58E4" ++
+    {-0xE0-}  chars "\x58DF\x58EF\x58FA\x58F9\x58FB\x58FC\x58FD\x5902" ++
+    {-0xE8-}  chars "\x590A\x5910\x591B\x68A6\x5925\x592C\x592D\x5932" ++
+    {-0xF0-}  chars "\x5938\x593E\x7AD2\x5955\x5950\x594E\x595A\x5958" ++
+    {-0xF8-}  chars "\x5962\x5960\x5967\x596C\x5969"
+
+-- | The multibyte characters with a lead byte of @0x9B@.
+second9B :: SecondByteTable
+second9B = V.fromList $
+    {-0x40-}  chars "\x5978\x5981\x599D\x4F5E\x4FAB\x59A3\x59B2\x59C6" ++
+    {-0x48-}  chars "\x59E8\x59DC\x598D\x59D9\x59DA\x5A25\x5A1F\x5A11" ++
+    {-0x50-}  chars "\x5A1C\x5A09\x5A1A\x5A40\x5A6C\x5A49\x5A35\x5A36" ++
+    {-0x58-}  chars "\x5A62\x5A6A\x5A9A\x5ABC\x5ABE\x5ACB\x5AC2\x5ABD" ++
+    {-0x60-}  chars "\x5AE3\x5AD7\x5AE6\x5AE9\x5AD6\x5AFA\x5AFB\x5B0C" ++
+    {-0x68-}  chars "\x5B0B\x5B16\x5B32\x5AD0\x5B2A\x5B36\x5B3E\x5B43" ++
+    {-0x70-}  chars "\x5B45\x5B40\x5B51\x5B55\x5B5A\x5B5B\x5B65\x5B69" ++
+    {-0x78-}  chars "\x5B70\x5B73\x5B75\x5B78\x6588\x5B7A\x5B80" ++ Nothing :
+    {-0x80-}  chars "\x5B83\x5BA6\x5BB8\x5BC3\x5BC7\x5BC9\x5BD4\x5BD0" ++
+    {-0x88-}  chars "\x5BE4\x5BE6\x5BE2\x5BDE\x5BE5\x5BEB\x5BF0\x5BF6" ++
+    {-0x90-}  chars "\x5BF3\x5C05\x5C07\x5C08\x5C0D\x5C13\x5C20\x5C22" ++
+    {-0x98-}  chars "\x5C28\x5C38\x5C39\x5C41\x5C46\x5C4E\x5C53\x5C50" ++
+    {-0xA0-}  chars "\x5C4F\x5B71\x5C6C\x5C6E\x4E62\x5C76\x5C79\x5C8C" ++
+    {-0xA8-}  chars "\x5C91\x5C94\x599B\x5CAB\x5CBB\x5CB6\x5CBC\x5CB7" ++
+    {-0xB0-}  chars "\x5CC5\x5CBE\x5CC7\x5CD9\x5CE9\x5CFD\x5CFA\x5CED" ++
+    {-0xB8-}  chars "\x5D8C\x5CEA\x5D0B\x5D15\x5D17\x5D5C\x5D1F\x5D1B" ++
+    {-0xC0-}  chars "\x5D11\x5D14\x5D22\x5D1A\x5D19\x5D18\x5D4C\x5D52" ++
+    {-0xC8-}  chars "\x5D4E\x5D4B\x5D6C\x5D73\x5D76\x5D87\x5D84\x5D82" ++
+    {-0xD0-}  chars "\x5DA2\x5D9D\x5DAC\x5DAE\x5DBD\x5D90\x5DB7\x5DBC" ++
+    {-0xD8-}  chars "\x5DC9\x5DCD\x5DD3\x5DD2\x5DD6\x5DDB\x5DEB\x5DF2" ++
+    {-0xE0-}  chars "\x5DF5\x5E0B\x5E1A\x5E19\x5E11\x5E1B\x5E36\x5E37" ++
+    {-0xE8-}  chars "\x5E44\x5E43\x5E40\x5E4E\x5E57\x5E54\x5E5F\x5E62" ++
+    {-0xF0-}  chars "\x5E64\x5E47\x5E75\x5E76\x5E7A\x9EBC\x5E7F\x5EA0" ++
+    {-0xF8-}  chars "\x5EC1\x5EC2\x5EC8\x5ED0\x5ECF"
+
+-- | The multibyte characters with a lead byte of @0x9C@.
+second9C :: SecondByteTable
+second9C = V.fromList $
+    {-0x40-}  chars "\x5ED6\x5EE3\x5EDD\x5EDA\x5EDB\x5EE2\x5EE1\x5EE8" ++
+    {-0x48-}  chars "\x5EE9\x5EEC\x5EF1\x5EF3\x5EF0\x5EF4\x5EF8\x5EFE" ++
+    {-0x50-}  chars "\x5F03\x5F09\x5F5D\x5F5C\x5F0B\x5F11\x5F16\x5F29" ++
+    {-0x58-}  chars "\x5F2D\x5F38\x5F41\x5F48\x5F4C\x5F4E\x5F2F\x5F51" ++
+    {-0x60-}  chars "\x5F56\x5F57\x5F59\x5F61\x5F6D\x5F73\x5F77\x5F83" ++
+    {-0x68-}  chars "\x5F82\x5F7F\x5F8A\x5F88\x5F91\x5F87\x5F9E\x5F99" ++
+    {-0x70-}  chars "\x5F98\x5FA0\x5FA8\x5FAD\x5FBC\x5FD6\x5FFB\x5FE4" ++
+    {-0x78-}  chars "\x5FF8\x5FF1\x5FDD\x60B3\x5FFF\x6021\x6060" ++ Nothing :
+    {-0x80-}  chars "\x6019\x6010\x6029\x600E\x6031\x601B\x6015\x602B" ++
+    {-0x88-}  chars "\x6026\x600F\x603A\x605A\x6041\x606A\x6077\x605F" ++
+    {-0x90-}  chars "\x604A\x6046\x604D\x6063\x6043\x6064\x6042\x606C" ++
+    {-0x98-}  chars "\x606B\x6059\x6081\x608D\x60E7\x6083\x609A\x6084" ++
+    {-0xA0-}  chars "\x609B\x6096\x6097\x6092\x60A7\x608B\x60E1\x60B8" ++
+    {-0xA8-}  chars "\x60E0\x60D3\x60B4\x5FF0\x60BD\x60C6\x60B5\x60D8" ++
+    {-0xB0-}  chars "\x614D\x6115\x6106\x60F6\x60F7\x6100\x60F4\x60FA" ++
+    {-0xB8-}  chars "\x6103\x6121\x60FB\x60F1\x610D\x610E\x6147\x613E" ++
+    {-0xC0-}  chars "\x6128\x6127\x614A\x613F\x613C\x612C\x6134\x613D" ++
+    {-0xC8-}  chars "\x6142\x6144\x6173\x6177\x6158\x6159\x615A\x616B" ++
+    {-0xD0-}  chars "\x6174\x616F\x6165\x6171\x615F\x615D\x6153\x6175" ++
+    {-0xD8-}  chars "\x6199\x6196\x6187\x61AC\x6194\x619A\x618A\x6191" ++
+    {-0xE0-}  chars "\x61AB\x61AE\x61CC\x61CA\x61C9\x61F7\x61C8\x61C3" ++
+    {-0xE8-}  chars "\x61C6\x61BA\x61CB\x7F79\x61CD\x61E6\x61E3\x61F6" ++
+    {-0xF0-}  chars "\x61FA\x61F4\x61FF\x61FD\x61FC\x61FE\x6200\x6208" ++
+    {-0xF8-}  chars "\x6209\x620D\x620C\x6214\x621B"
+
+-- | The multibyte characters with a lead byte of @0x9D@.
+second9D :: SecondByteTable
+second9D = V.fromList $
+    {-0x40-}  chars "\x621E\x6221\x622A\x622E\x6230\x6232\x6233\x6241" ++
+    {-0x48-}  chars "\x624E\x625E\x6263\x625B\x6260\x6268\x627C\x6282" ++
+    {-0x50-}  chars "\x6289\x627E\x6292\x6293\x6296\x62D4\x6283\x6294" ++
+    {-0x58-}  chars "\x62D7\x62D1\x62BB\x62CF\x62FF\x62C6\x64D4\x62C8" ++
+    {-0x60-}  chars "\x62DC\x62CC\x62CA\x62C2\x62C7\x629B\x62C9\x630C" ++
+    {-0x68-}  chars "\x62EE\x62F1\x6327\x6302\x6308\x62EF\x62F5\x6350" ++
+    {-0x70-}  chars "\x633E\x634D\x641C\x634F\x6396\x638E\x6380\x63AB" ++
+    {-0x78-}  chars "\x6376\x63A3\x638F\x6389\x639F\x63B5\x636B" ++ Nothing :
+    {-0x80-}  chars "\x6369\x63BE\x63E9\x63C0\x63C6\x63E3\x63C9\x63D2" ++
+    {-0x88-}  chars "\x63F6\x63C4\x6416\x6434\x6406\x6413\x6426\x6436" ++
+    {-0x90-}  chars "\x651D\x6417\x6428\x640F\x6467\x646F\x6476\x644E" ++
+    {-0x98-}  chars "\x652A\x6495\x6493\x64A5\x64A9\x6488\x64BC\x64DA" ++
+    {-0xA0-}  chars "\x64D2\x64C5\x64C7\x64BB\x64D8\x64C2\x64F1\x64E7" ++
+    {-0xA8-}  chars "\x8209\x64E0\x64E1\x62AC\x64E3\x64EF\x652C\x64F6" ++
+    {-0xB0-}  chars "\x64F4\x64F2\x64FA\x6500\x64FD\x6518\x651C\x6505" ++
+    {-0xB8-}  chars "\x6524\x6523\x652B\x6534\x6535\x6537\x6536\x6538" ++
+    {-0xC0-}  chars "\x754B\x6548\x6556\x6555\x654D\x6558\x655E\x655D" ++
+    {-0xC8-}  chars "\x6572\x6578\x6582\x6583\x8B8A\x659B\x659F\x65AB" ++
+    {-0xD0-}  chars "\x65B7\x65C3\x65C6\x65C1\x65C4\x65CC\x65D2\x65DB" ++
+    {-0xD8-}  chars "\x65D9\x65E0\x65E1\x65F1\x6772\x660A\x6603\x65FB" ++
+    {-0xE0-}  chars "\x6773\x6635\x6636\x6634\x661C\x664F\x6644\x6649" ++
+    {-0xE8-}  chars "\x6641\x665E\x665D\x6664\x6667\x6668\x665F\x6662" ++
+    {-0xF0-}  chars "\x6670\x6683\x6688\x668E\x6689\x6684\x6698\x669D" ++
+    {-0xF8-}  chars "\x66C1\x66B9\x66C9\x66BE\x66BC"
+
+-- | The multibyte characters with a lead byte of @0x9E@.
+second9E :: SecondByteTable
+second9E = V.fromList $
+    {-0x40-}  chars "\x66C4\x66B8\x66D6\x66DA\x66E0\x663F\x66E6\x66E9" ++
+    {-0x48-}  chars "\x66F0\x66F5\x66F7\x670F\x6716\x671E\x6726\x6727" ++
+    {-0x50-}  chars "\x9738\x672E\x673F\x6736\x6741\x6738\x6737\x6746" ++
+    {-0x58-}  chars "\x675E\x6760\x6759\x6763\x6764\x6789\x6770\x67A9" ++
+    {-0x60-}  chars "\x677C\x676A\x678C\x678B\x67A6\x67A1\x6785\x67B7" ++
+    {-0x68-}  chars "\x67EF\x67B4\x67EC\x67B3\x67E9\x67B8\x67E4\x67DE" ++
+    {-0x70-}  chars "\x67DD\x67E2\x67EE\x67B9\x67CE\x67C6\x67E7\x6A9C" ++
+    {-0x78-}  chars "\x681E\x6846\x6829\x6840\x684D\x6832\x684E" ++ Nothing :
+    {-0x80-}  chars "\x68B3\x682B\x6859\x6863\x6877\x687F\x689F\x688F" ++
+    {-0x88-}  chars "\x68AD\x6894\x689D\x689B\x6883\x6AAE\x68B9\x6874" ++
+    {-0x90-}  chars "\x68B5\x68A0\x68BA\x690F\x688D\x687E\x6901\x68CA" ++
+    {-0x98-}  chars "\x6908\x68D8\x6922\x6926\x68E1\x690C\x68CD\x68D4" ++
+    {-0xA0-}  chars "\x68E7\x68D5\x6936\x6912\x6904\x68D7\x68E3\x6925" ++
+    {-0xA8-}  chars "\x68F9\x68E0\x68EF\x6928\x692A\x691A\x6923\x6921" ++
+    {-0xB0-}  chars "\x68C6\x6979\x6977\x695C\x6978\x696B\x6954\x697E" ++
+    {-0xB8-}  chars "\x696E\x6939\x6974\x693D\x6959\x6930\x6961\x695E" ++
+    {-0xC0-}  chars "\x695D\x6981\x696A\x69B2\x69AE\x69D0\x69BF\x69C1" ++
+    {-0xC8-}  chars "\x69D3\x69BE\x69CE\x5BE8\x69CA\x69DD\x69BB\x69C3" ++
+    {-0xD0-}  chars "\x69A7\x6A2E\x6991\x69A0\x699C\x6995\x69B4\x69DE" ++
+    {-0xD8-}  chars "\x69E8\x6A02\x6A1B\x69FF\x6B0A\x69F9\x69F2\x69E7" ++
+    {-0xE0-}  chars "\x6A05\x69B1\x6A1E\x69ED\x6A14\x69EB\x6A0A\x6A12" ++
+    {-0xE8-}  chars "\x6AC1\x6A23\x6A13\x6A44\x6A0C\x6A72\x6A36\x6A78" ++
+    {-0xF0-}  chars "\x6A47\x6A62\x6A59\x6A66\x6A48\x6A38\x6A22\x6A90" ++
+    {-0xF8-}  chars "\x6A8D\x6AA0\x6A84\x6AA2\x6AA3"
+
+-- | The multibyte characters with a lead byte of @0x9F@.
+second9F :: SecondByteTable
+second9F = V.fromList $
+    {-0x40-}  chars "\x6A97\x8617\x6ABB\x6AC3\x6AC2\x6AB8\x6AB3\x6AAC" ++
+    {-0x48-}  chars "\x6ADE\x6AD1\x6ADF\x6AAA\x6ADA\x6AEA\x6AFB\x6B05" ++
+    {-0x50-}  chars "\x8616\x6AFA\x6B12\x6B16\x9B31\x6B1F\x6B38\x6B37" ++
+    {-0x58-}  chars "\x76DC\x6B39\x98EE\x6B47\x6B43\x6B49\x6B50\x6B59" ++
+    {-0x60-}  chars "\x6B54\x6B5B\x6B5F\x6B61\x6B78\x6B79\x6B7F\x6B80" ++
+    {-0x68-}  chars "\x6B84\x6B83\x6B8D\x6B98\x6B95\x6B9E\x6BA4\x6BAA" ++
+    {-0x70-}  chars "\x6BAB\x6BAF\x6BB2\x6BB1\x6BB3\x6BB7\x6BBC\x6BC6" ++
+    {-0x78-}  chars "\x6BCB\x6BD3\x6BDF\x6BEC\x6BEB\x6BF3\x6BEF" ++ Nothing :
+    {-0x80-}  chars "\x9EBE\x6C08\x6C13\x6C14\x6C1B\x6C24\x6C23\x6C5E" ++
+    {-0x88-}  chars "\x6C55\x6C62\x6C6A\x6C82\x6C8D\x6C9A\x6C81\x6C9B" ++
+    {-0x90-}  chars "\x6C7E\x6C68\x6C73\x6C92\x6C90\x6CC4\x6CF1\x6CD3" ++
+    {-0x98-}  chars "\x6CBD\x6CD7\x6CC5\x6CDD\x6CAE\x6CB1\x6CBE\x6CBA" ++
+    {-0xA0-}  chars "\x6CDB\x6CEF\x6CD9\x6CEA\x6D1F\x884D\x6D36\x6D2B" ++
+    {-0xA8-}  chars "\x6D3D\x6D38\x6D19\x6D35\x6D33\x6D12\x6D0C\x6D63" ++
+    {-0xB0-}  chars "\x6D93\x6D64\x6D5A\x6D79\x6D59\x6D8E\x6D95\x6FE4" ++
+    {-0xB8-}  chars "\x6D85\x6DF9\x6E15\x6E0A\x6DB5\x6DC7\x6DE6\x6DB8" ++
+    {-0xC0-}  chars "\x6DC6\x6DEC\x6DDE\x6DCC\x6DE8\x6DD2\x6DC5\x6DFA" ++
+    {-0xC8-}  chars "\x6DD9\x6DE4\x6DD5\x6DEA\x6DEE\x6E2D\x6E6E\x6E2E" ++
+    {-0xD0-}  chars "\x6E19\x6E72\x6E5F\x6E3E\x6E23\x6E6B\x6E2B\x6E76" ++
+    {-0xD8-}  chars "\x6E4D\x6E1F\x6E43\x6E3A\x6E4E\x6E24\x6EFF\x6E1D" ++
+    {-0xE0-}  chars "\x6E38\x6E82\x6EAA\x6E98\x6EC9\x6EB7\x6ED3\x6EBD" ++
+    {-0xE8-}  chars "\x6EAF\x6EC4\x6EB2\x6ED4\x6ED5\x6E8F\x6EA5\x6EC2" ++
+    {-0xF0-}  chars "\x6E9F\x6F41\x6F11\x704C\x6EEC\x6EF8\x6EFE\x6F3F" ++
+    {-0xF8-}  chars "\x6EF2\x6F31\x6EEF\x6F32\x6ECC"
+
+-- | The multibyte characters with a lead byte of @0xE0@.
+secondE0 :: SecondByteTable
+secondE0 = V.fromList $
+    {-0x40-}  chars "\x6F3E\x6F13\x6EF7\x6F86\x6F7A\x6F78\x6F81\x6F80" ++
+    {-0x48-}  chars "\x6F6F\x6F5B\x6FF3\x6F6D\x6F82\x6F7C\x6F58\x6F8E" ++
+    {-0x50-}  chars "\x6F91\x6FC2\x6F66\x6FB3\x6FA3\x6FA1\x6FA4\x6FB9" ++
+    {-0x58-}  chars "\x6FC6\x6FAA\x6FDF\x6FD5\x6FEC\x6FD4\x6FD8\x6FF1" ++
+    {-0x60-}  chars "\x6FEE\x6FDB\x7009\x700B\x6FFA\x7011\x7001\x700F" ++
+    {-0x68-}  chars "\x6FFE\x701B\x701A\x6F74\x701D\x7018\x701F\x7030" ++
+    {-0x70-}  chars "\x703E\x7032\x7051\x7063\x7099\x7092\x70AF\x70F1" ++
+    {-0x78-}  chars "\x70AC\x70B8\x70B3\x70AE\x70DF\x70CB\x70DD" ++ Nothing :
+    {-0x80-}  chars "\x70D9\x7109\x70FD\x711C\x7119\x7165\x7155\x7188" ++
+    {-0x88-}  chars "\x7166\x7162\x714C\x7156\x716C\x718F\x71FB\x7184" ++
+    {-0x90-}  chars "\x7195\x71A8\x71AC\x71D7\x71B9\x71BE\x71D2\x71C9" ++
+    {-0x98-}  chars "\x71D4\x71CE\x71E0\x71EC\x71E7\x71F5\x71FC\x71F9" ++
+    {-0xA0-}  chars "\x71FF\x720D\x7210\x721B\x7228\x722D\x722C\x7230" ++
+    {-0xA8-}  chars "\x7232\x723B\x723C\x723F\x7240\x7246\x724B\x7258" ++
+    {-0xB0-}  chars "\x7274\x727E\x7282\x7281\x7287\x7292\x7296\x72A2" ++
+    {-0xB8-}  chars "\x72A7\x72B9\x72B2\x72C3\x72C6\x72C4\x72CE\x72D2" ++
+    {-0xC0-}  chars "\x72E2\x72E0\x72E1\x72F9\x72F7\x500F\x7317\x730A" ++
+    {-0xC8-}  chars "\x731C\x7316\x731D\x7334\x732F\x7329\x7325\x733E" ++
+    {-0xD0-}  chars "\x734E\x734F\x9ED8\x7357\x736A\x7368\x7370\x7378" ++
+    {-0xD8-}  chars "\x7375\x737B\x737A\x73C8\x73B3\x73CE\x73BB\x73C0" ++
+    {-0xE0-}  chars "\x73E5\x73EE\x73DE\x74A2\x7405\x746F\x7425\x73F8" ++
+    {-0xE8-}  chars "\x7432\x743A\x7455\x743F\x745F\x7459\x7441\x745C" ++
+    {-0xF0-}  chars "\x7469\x7470\x7463\x746A\x7476\x747E\x748B\x749E" ++
+    {-0xF8-}  chars "\x74A7\x74CA\x74CF\x74D4\x73F1"
+
+-- | The multibyte characters with a lead byte of @0xE1@.
+secondE1 :: SecondByteTable
+secondE1 = V.fromList $
+    {-0x40-}  chars "\x74E0\x74E3\x74E7\x74E9\x74EE\x74F2\x74F0\x74F1" ++
+    {-0x48-}  chars "\x74F8\x74F7\x7504\x7503\x7505\x750C\x750E\x750D" ++
+    {-0x50-}  chars "\x7515\x7513\x751E\x7526\x752C\x753C\x7544\x754D" ++
+    {-0x58-}  chars "\x754A\x7549\x755B\x7546\x755A\x7569\x7564\x7567" ++
+    {-0x60-}  chars "\x756B\x756D\x7578\x7576\x7586\x7587\x7574\x758A" ++
+    {-0x68-}  chars "\x7589\x7582\x7594\x759A\x759D\x75A5\x75A3\x75C2" ++
+    {-0x70-}  chars "\x75B3\x75C3\x75B5\x75BD\x75B8\x75BC\x75B1\x75CD" ++
+    {-0x78-}  chars "\x75CA\x75D2\x75D9\x75E3\x75DE\x75FE\x75FF" ++ Nothing :
+    {-0x80-}  chars "\x75FC\x7601\x75F0\x75FA\x75F2\x75F3\x760B\x760D" ++
+    {-0x88-}  chars "\x7609\x761F\x7627\x7620\x7621\x7622\x7624\x7634" ++
+    {-0x90-}  chars "\x7630\x763B\x7647\x7648\x7646\x765C\x7658\x7661" ++
+    {-0x98-}  chars "\x7662\x7668\x7669\x766A\x7667\x766C\x7670\x7672" ++
+    {-0xA0-}  chars "\x7676\x7678\x767C\x7680\x7683\x7688\x768B\x768E" ++
+    {-0xA8-}  chars "\x7696\x7693\x7699\x769A\x76B0\x76B4\x76B8\x76B9" ++
+    {-0xB0-}  chars "\x76BA\x76C2\x76CD\x76D6\x76D2\x76DE\x76E1\x76E5" ++
+    {-0xB8-}  chars "\x76E7\x76EA\x862F\x76FB\x7708\x7707\x7704\x7729" ++
+    {-0xC0-}  chars "\x7724\x771E\x7725\x7726\x771B\x7737\x7738\x7747" ++
+    {-0xC8-}  chars "\x775A\x7768\x776B\x775B\x7765\x777F\x777E\x7779" ++
+    {-0xD0-}  chars "\x778E\x778B\x7791\x77A0\x779E\x77B0\x77B6\x77B9" ++
+    {-0xD8-}  chars "\x77BF\x77BC\x77BD\x77BB\x77C7\x77CD\x77D7\x77DA" ++
+    {-0xE0-}  chars "\x77DC\x77E3\x77EE\x77FC\x780C\x7812\x7926\x7820" ++
+    {-0xE8-}  chars "\x792A\x7845\x788E\x7874\x7886\x787C\x789A\x788C" ++
+    {-0xF0-}  chars "\x78A3\x78B5\x78AA\x78AF\x78D1\x78C6\x78CB\x78D4" ++
+    {-0xF8-}  chars "\x78BE\x78BC\x78C5\x78CA\x78EC"
+
+-- | The multibyte characters with a lead byte of @0xE2@.
+secondE2 :: SecondByteTable
+secondE2 = V.fromList $
+    {-0x40-}  chars "\x78E7\x78DA\x78FD\x78F4\x7907\x7912\x7911\x7919" ++
+    {-0x48-}  chars "\x792C\x792B\x7940\x7960\x7957\x795F\x795A\x7955" ++
+    {-0x50-}  chars "\x7953\x797A\x797F\x798A\x799D\x79A7\x9F4B\x79AA" ++
+    {-0x58-}  chars "\x79AE\x79B3\x79B9\x79BA\x79C9\x79D5\x79E7\x79EC" ++
+    {-0x60-}  chars "\x79E1\x79E3\x7A08\x7A0D\x7A18\x7A19\x7A20\x7A1F" ++
+    {-0x68-}  chars "\x7980\x7A31\x7A3B\x7A3E\x7A37\x7A43\x7A57\x7A49" ++
+    {-0x70-}  chars "\x7A61\x7A62\x7A69\x9F9D\x7A70\x7A79\x7A7D\x7A88" ++
+    {-0x78-}  chars "\x7A97\x7A95\x7A98\x7A96\x7AA9\x7AC8\x7AB0" ++ Nothing :
+    {-0x80-}  chars "\x7AB6\x7AC5\x7AC4\x7ABF\x9083\x7AC7\x7ACA\x7ACD" ++
+    {-0x88-}  chars "\x7ACF\x7AD5\x7AD3\x7AD9\x7ADA\x7ADD\x7AE1\x7AE2" ++
+    {-0x90-}  chars "\x7AE6\x7AED\x7AF0\x7B02\x7B0F\x7B0A\x7B06\x7B33" ++
+    {-0x98-}  chars "\x7B18\x7B19\x7B1E\x7B35\x7B28\x7B36\x7B50\x7B7A" ++
+    {-0xA0-}  chars "\x7B04\x7B4D\x7B0B\x7B4C\x7B45\x7B75\x7B65\x7B74" ++
+    {-0xA8-}  chars "\x7B67\x7B70\x7B71\x7B6C\x7B6E\x7B9D\x7B98\x7B9F" ++
+    {-0xB0-}  chars "\x7B8D\x7B9C\x7B9A\x7B8B\x7B92\x7B8F\x7B5D\x7B99" ++
+    {-0xB8-}  chars "\x7BCB\x7BC1\x7BCC\x7BCF\x7BB4\x7BC6\x7BDD\x7BE9" ++
+    {-0xC0-}  chars "\x7C11\x7C14\x7BE6\x7BE5\x7C60\x7C00\x7C07\x7C13" ++
+    {-0xC8-}  chars "\x7BF3\x7BF7\x7C17\x7C0D\x7BF6\x7C23\x7C27\x7C2A" ++
+    {-0xD0-}  chars "\x7C1F\x7C37\x7C2B\x7C3D\x7C4C\x7C43\x7C54\x7C4F" ++
+    {-0xD8-}  chars "\x7C40\x7C50\x7C58\x7C5F\x7C64\x7C56\x7C65\x7C6C" ++
+    {-0xE0-}  chars "\x7C75\x7C83\x7C90\x7CA4\x7CAD\x7CA2\x7CAB\x7CA1" ++
+    {-0xE8-}  chars "\x7CA8\x7CB3\x7CB2\x7CB1\x7CAE\x7CB9\x7CBD\x7CC0" ++
+    {-0xF0-}  chars "\x7CC5\x7CC2\x7CD8\x7CD2\x7CDC\x7CE2\x9B3B\x7CEF" ++
+    {-0xF8-}  chars "\x7CF2\x7CF4\x7CF6\x7CFA\x7D06"
+
+-- | The multibyte characters with a lead byte of @0xE3@.
+secondE3 :: SecondByteTable
+secondE3 = V.fromList $
+    {-0x40-}  chars "\x7D02\x7D1C\x7D15\x7D0A\x7D45\x7D4B\x7D2E\x7D32" ++
+    {-0x48-}  chars "\x7D3F\x7D35\x7D46\x7D73\x7D56\x7D4E\x7D72\x7D68" ++
+    {-0x50-}  chars "\x7D6E\x7D4F\x7D63\x7D93\x7D89\x7D5B\x7D8F\x7D7D" ++
+    {-0x58-}  chars "\x7D9B\x7DBA\x7DAE\x7DA3\x7DB5\x7DC7\x7DBD\x7DAB" ++
+    {-0x60-}  chars "\x7E3D\x7DA2\x7DAF\x7DDC\x7DB8\x7D9F\x7DB0\x7DD8" ++
+    {-0x68-}  chars "\x7DDD\x7DE4\x7DDE\x7DFB\x7DF2\x7DE1\x7E05\x7E0A" ++
+    {-0x70-}  chars "\x7E23\x7E21\x7E12\x7E31\x7E1F\x7E09\x7E0B\x7E22" ++
+    {-0x78-}  chars "\x7E46\x7E66\x7E3B\x7E35\x7E39\x7E43\x7E37" ++ Nothing :
+    {-0x80-}  chars "\x7E32\x7E3A\x7E67\x7E5D\x7E56\x7E5E\x7E59\x7E5A" ++
+    {-0x88-}  chars "\x7E79\x7E6A\x7E69\x7E7C\x7E7B\x7E83\x7DD5\x7E7D" ++
+    {-0x90-}  chars "\x8FAE\x7E7F\x7E88\x7E89\x7E8C\x7E92\x7E90\x7E93" ++
+    {-0x98-}  chars "\x7E94\x7E96\x7E8E\x7E9B\x7E9C\x7F38\x7F3A\x7F45" ++
+    {-0xA0-}  chars "\x7F4C\x7F4D\x7F4E\x7F50\x7F51\x7F55\x7F54\x7F58" ++
+    {-0xA8-}  chars "\x7F5F\x7F60\x7F68\x7F69\x7F67\x7F78\x7F82\x7F86" ++
+    {-0xB0-}  chars "\x7F83\x7F88\x7F87\x7F8C\x7F94\x7F9E\x7F9D\x7F9A" ++
+    {-0xB8-}  chars "\x7FA3\x7FAF\x7FB2\x7FB9\x7FAE\x7FB6\x7FB8\x8B71" ++
+    {-0xC0-}  chars "\x7FC5\x7FC6\x7FCA\x7FD5\x7FD4\x7FE1\x7FE6\x7FE9" ++
+    {-0xC8-}  chars "\x7FF3\x7FF9\x98DC\x8006\x8004\x800B\x8012\x8018" ++
+    {-0xD0-}  chars "\x8019\x801C\x8021\x8028\x803F\x803B\x804A\x8046" ++
+    {-0xD8-}  chars "\x8052\x8058\x805A\x805F\x8062\x8068\x8073\x8072" ++
+    {-0xE0-}  chars "\x8070\x8076\x8079\x807D\x807F\x8084\x8086\x8085" ++
+    {-0xE8-}  chars "\x809B\x8093\x809A\x80AD\x5190\x80AC\x80DB\x80E5" ++
+    {-0xF0-}  chars "\x80D9\x80DD\x80C4\x80DA\x80D6\x8109\x80EF\x80F1" ++
+    {-0xF8-}  chars "\x811B\x8129\x8123\x812F\x814B"
+
+-- | The multibyte characters with a lead byte of @0xE4@.
+secondE4 :: SecondByteTable
+secondE4 = V.fromList $
+    {-0x40-}  chars "\x968B\x8146\x813E\x8153\x8151\x80FC\x8171\x816E" ++
+    {-0x48-}  chars "\x8165\x8166\x8174\x8183\x8188\x818A\x8180\x8182" ++
+    {-0x50-}  chars "\x81A0\x8195\x81A4\x81A3\x815F\x8193\x81A9\x81B0" ++
+    {-0x58-}  chars "\x81B5\x81BE\x81B8\x81BD\x81C0\x81C2\x81BA\x81C9" ++
+    {-0x60-}  chars "\x81CD\x81D1\x81D9\x81D8\x81C8\x81DA\x81DF\x81E0" ++
+    {-0x68-}  chars "\x81E7\x81FA\x81FB\x81FE\x8201\x8202\x8205\x8207" ++
+    {-0x70-}  chars "\x820A\x820D\x8210\x8216\x8229\x822B\x8238\x8233" ++
+    {-0x78-}  chars "\x8240\x8259\x8258\x825D\x825A\x825F\x8264" ++ Nothing :
+    {-0x80-}  chars "\x8262\x8268\x826A\x826B\x822E\x8271\x8277\x8278" ++
+    {-0x88-}  chars "\x827E\x828D\x8292\x82AB\x829F\x82BB\x82AC\x82E1" ++
+    {-0x90-}  chars "\x82E3\x82DF\x82D2\x82F4\x82F3\x82FA\x8393\x8303" ++
+    {-0x98-}  chars "\x82FB\x82F9\x82DE\x8306\x82DC\x8309\x82D9\x8335" ++
+    {-0xA0-}  chars "\x8334\x8316\x8332\x8331\x8340\x8339\x8350\x8345" ++
+    {-0xA8-}  chars "\x832F\x832B\x8317\x8318\x8385\x839A\x83AA\x839F" ++
+    {-0xB0-}  chars "\x83A2\x8396\x8323\x838E\x8387\x838A\x837C\x83B5" ++
+    {-0xB8-}  chars "\x8373\x8375\x83A0\x8389\x83A8\x83F4\x8413\x83EB" ++
+    {-0xC0-}  chars "\x83CE\x83FD\x8403\x83D8\x840B\x83C1\x83F7\x8407" ++
+    {-0xC8-}  chars "\x83E0\x83F2\x840D\x8422\x8420\x83BD\x8438\x8506" ++
+    {-0xD0-}  chars "\x83FB\x846D\x842A\x843C\x855A\x8484\x8477\x846B" ++
+    {-0xD8-}  chars "\x84AD\x846E\x8482\x8469\x8446\x842C\x846F\x8479" ++
+    {-0xE0-}  chars "\x8435\x84CA\x8462\x84B9\x84BF\x849F\x84D9\x84CD" ++
+    {-0xE8-}  chars "\x84BB\x84DA\x84D0\x84C1\x84C6\x84D6\x84A1\x8521" ++
+    {-0xF0-}  chars "\x84FF\x84F4\x8517\x8518\x852C\x851F\x8515\x8514" ++
+    {-0xF8-}  chars "\x84FC\x8540\x8563\x8558\x8548"
+
+-- | The multibyte characters with a lead byte of @0xE5@.
+secondE5 :: SecondByteTable
+secondE5 = V.fromList $
+    {-0x40-}  chars "\x8541\x8602\x854B\x8555\x8580\x85A4\x8588\x8591" ++
+    {-0x48-}  chars "\x858A\x85A8\x856D\x8594\x859B\x85EA\x8587\x859C" ++
+    {-0x50-}  chars "\x8577\x857E\x8590\x85C9\x85BA\x85CF\x85B9\x85D0" ++
+    {-0x58-}  chars "\x85D5\x85DD\x85E5\x85DC\x85F9\x860A\x8613\x860B" ++
+    {-0x60-}  chars "\x85FE\x85FA\x8606\x8622\x861A\x8630\x863F\x864D" ++
+    {-0x68-}  chars "\x4E55\x8654\x865F\x8667\x8671\x8693\x86A3\x86A9" ++
+    {-0x70-}  chars "\x86AA\x868B\x868C\x86B6\x86AF\x86C4\x86C6\x86B0" ++
+    {-0x78-}  chars "\x86C9\x8823\x86AB\x86D4\x86DE\x86E9\x86EC" ++ Nothing :
+    {-0x80-}  chars "\x86DF\x86DB\x86EF\x8712\x8706\x8708\x8700\x8703" ++
+    {-0x88-}  chars "\x86FB\x8711\x8709\x870D\x86F9\x870A\x8734\x873F" ++
+    {-0x90-}  chars "\x8737\x873B\x8725\x8729\x871A\x8760\x875F\x8778" ++
+    {-0x98-}  chars "\x874C\x874E\x8774\x8757\x8768\x876E\x8759\x8753" ++
+    {-0xA0-}  chars "\x8763\x876A\x8805\x87A2\x879F\x8782\x87AF\x87CB" ++
+    {-0xA8-}  chars "\x87BD\x87C0\x87D0\x96D6\x87AB\x87C4\x87B3\x87C7" ++
+    {-0xB0-}  chars "\x87C6\x87BB\x87EF\x87F2\x87E0\x880F\x880D\x87FE" ++
+    {-0xB8-}  chars "\x87F6\x87F7\x880E\x87D2\x8811\x8816\x8815\x8822" ++
+    {-0xC0-}  chars "\x8821\x8831\x8836\x8839\x8827\x883B\x8844\x8842" ++
+    {-0xC8-}  chars "\x8852\x8859\x885E\x8862\x886B\x8881\x887E\x889E" ++
+    {-0xD0-}  chars "\x8875\x887D\x88B5\x8872\x8882\x8897\x8892\x88AE" ++
+    {-0xD8-}  chars "\x8899\x88A2\x888D\x88A4\x88B0\x88BF\x88B1\x88C3" ++
+    {-0xE0-}  chars "\x88C4\x88D4\x88D8\x88D9\x88DD\x88F9\x8902\x88FC" ++
+    {-0xE8-}  chars "\x88F4\x88E8\x88F2\x8904\x890C\x890A\x8913\x8943" ++
+    {-0xF0-}  chars "\x891E\x8925\x892A\x892B\x8941\x8944\x893B\x8936" ++
+    {-0xF8-}  chars "\x8938\x894C\x891D\x8960\x895E"
+
+-- | The multibyte characters with a lead byte of @0xE6@.
+secondE6 :: SecondByteTable
+secondE6 = V.fromList $
+    {-0x40-}  chars "\x8966\x8964\x896D\x896A\x896F\x8974\x8977\x897E" ++
+    {-0x48-}  chars "\x8983\x8988\x898A\x8993\x8998\x89A1\x89A9\x89A6" ++
+    {-0x50-}  chars "\x89AC\x89AF\x89B2\x89BA\x89BD\x89BF\x89C0\x89DA" ++
+    {-0x58-}  chars "\x89DC\x89DD\x89E7\x89F4\x89F8\x8A03\x8A16\x8A10" ++
+    {-0x60-}  chars "\x8A0C\x8A1B\x8A1D\x8A25\x8A36\x8A41\x8A5B\x8A52" ++
+    {-0x68-}  chars "\x8A46\x8A48\x8A7C\x8A6D\x8A6C\x8A62\x8A85\x8A82" ++
+    {-0x70-}  chars "\x8A84\x8AA8\x8AA1\x8A91\x8AA5\x8AA6\x8A9A\x8AA3" ++
+    {-0x78-}  chars "\x8AC4\x8ACD\x8AC2\x8ADA\x8AEB\x8AF3\x8AE7" ++ Nothing :
+    {-0x80-}  chars "\x8AE4\x8AF1\x8B14\x8AE0\x8AE2\x8AF7\x8ADE\x8ADB" ++
+    {-0x88-}  chars "\x8B0C\x8B07\x8B1A\x8AE1\x8B16\x8B10\x8B17\x8B20" ++
+    {-0x90-}  chars "\x8B33\x97AB\x8B26\x8B2B\x8B3E\x8B28\x8B41\x8B4C" ++
+    {-0x98-}  chars "\x8B4F\x8B4E\x8B49\x8B56\x8B5B\x8B5A\x8B6B\x8B5F" ++
+    {-0xA0-}  chars "\x8B6C\x8B6F\x8B74\x8B7D\x8B80\x8B8C\x8B8E\x8B92" ++
+    {-0xA8-}  chars "\x8B93\x8B96\x8B99\x8B9A\x8C3A\x8C41\x8C3F\x8C48" ++
+    {-0xB0-}  chars "\x8C4C\x8C4E\x8C50\x8C55\x8C62\x8C6C\x8C78\x8C7A" ++
+    {-0xB8-}  chars "\x8C82\x8C89\x8C85\x8C8A\x8C8D\x8C8E\x8C94\x8C7C" ++
+    {-0xC0-}  chars "\x8C98\x621D\x8CAD\x8CAA\x8CBD\x8CB2\x8CB3\x8CAE" ++
+    {-0xC8-}  chars "\x8CB6\x8CC8\x8CC1\x8CE4\x8CE3\x8CDA\x8CFD\x8CFA" ++
+    {-0xD0-}  chars "\x8CFB\x8D04\x8D05\x8D0A\x8D07\x8D0F\x8D0D\x8D10" ++
+    {-0xD8-}  chars "\x9F4E\x8D13\x8CCD\x8D14\x8D16\x8D67\x8D6D\x8D71" ++
+    {-0xE0-}  chars "\x8D73\x8D81\x8D99\x8DC2\x8DBE\x8DBA\x8DCF\x8DDA" ++
+    {-0xE8-}  chars "\x8DD6\x8DCC\x8DDB\x8DCB\x8DEA\x8DEB\x8DDF\x8DE3" ++
+    {-0xF0-}  chars "\x8DFC\x8E08\x8E09\x8DFF\x8E1D\x8E1E\x8E10\x8E1F" ++
+    {-0xF8-}  chars "\x8E42\x8E35\x8E30\x8E34\x8E4A"
+
+-- | The multibyte characters with a lead byte of @0xE7@.
+secondE7 :: SecondByteTable
+secondE7 = V.fromList $
+    {-0x40-}  chars "\x8E47\x8E49\x8E4C\x8E50\x8E48\x8E59\x8E64\x8E60" ++
+    {-0x48-}  chars "\x8E2A\x8E63\x8E55\x8E76\x8E72\x8E7C\x8E81\x8E87" ++
+    {-0x50-}  chars "\x8E85\x8E84\x8E8B\x8E8A\x8E93\x8E91\x8E94\x8E99" ++
+    {-0x58-}  chars "\x8EAA\x8EA1\x8EAC\x8EB0\x8EC6\x8EB1\x8EBE\x8EC5" ++
+    {-0x60-}  chars "\x8EC8\x8ECB\x8EDB\x8EE3\x8EFC\x8EFB\x8EEB\x8EFE" ++
+    {-0x68-}  chars "\x8F0A\x8F05\x8F15\x8F12\x8F19\x8F13\x8F1C\x8F1F" ++
+    {-0x70-}  chars "\x8F1B\x8F0C\x8F26\x8F33\x8F3B\x8F39\x8F45\x8F42" ++
+    {-0x78-}  chars "\x8F3E\x8F4C\x8F49\x8F46\x8F4E\x8F57\x8F5C" ++ Nothing :
+    {-0x80-}  chars "\x8F62\x8F63\x8F64\x8F9C\x8F9F\x8FA3\x8FAD\x8FAF" ++
+    {-0x88-}  chars "\x8FB7\x8FDA\x8FE5\x8FE2\x8FEA\x8FEF\x9087\x8FF4" ++
+    {-0x90-}  chars "\x9005\x8FF9\x8FFA\x9011\x9015\x9021\x900D\x901E" ++
+    {-0x98-}  chars "\x9016\x900B\x9027\x9036\x9035\x9039\x8FF8\x904F" ++
+    {-0xA0-}  chars "\x9050\x9051\x9052\x900E\x9049\x903E\x9056\x9058" ++
+    {-0xA8-}  chars "\x905E\x9068\x906F\x9076\x96A8\x9072\x9082\x907D" ++
+    {-0xB0-}  chars "\x9081\x9080\x908A\x9089\x908F\x90A8\x90AF\x90B1" ++
+    {-0xB8-}  chars "\x90B5\x90E2\x90E4\x6248\x90DB\x9102\x9112\x9119" ++
+    {-0xC0-}  chars "\x9132\x9130\x914A\x9156\x9158\x9163\x9165\x9169" ++
+    {-0xC8-}  chars "\x9173\x9172\x918B\x9189\x9182\x91A2\x91AB\x91AF" ++
+    {-0xD0-}  chars "\x91AA\x91B5\x91B4\x91BA\x91C0\x91C1\x91C9\x91CB" ++
+    {-0xD8-}  chars "\x91D0\x91D6\x91DF\x91E1\x91DB\x91FC\x91F5\x91F6" ++
+    {-0xE0-}  chars "\x921E\x91FF\x9214\x922C\x9215\x9211\x925E\x9257" ++
+    {-0xE8-}  chars "\x9245\x9249\x9264\x9248\x9295\x923F\x924B\x9250" ++
+    {-0xF0-}  chars "\x929C\x9296\x9293\x929B\x925A\x92CF\x92B9\x92B7" ++
+    {-0xF8-}  chars "\x92E9\x930F\x92FA\x9344\x932E"
+
+-- | The multibyte characters with a lead byte of @0xE8@.
+secondE8 :: SecondByteTable
+secondE8 = V.fromList $
+    {-0x40-}  chars "\x9319\x9322\x931A\x9323\x933A\x9335\x933B\x935C" ++
+    {-0x48-}  chars "\x9360\x937C\x936E\x9356\x93B0\x93AC\x93AD\x9394" ++
+    {-0x50-}  chars "\x93B9\x93D6\x93D7\x93E8\x93E5\x93D8\x93C3\x93DD" ++
+    {-0x58-}  chars "\x93D0\x93C8\x93E4\x941A\x9414\x9413\x9403\x9407" ++
+    {-0x60-}  chars "\x9410\x9436\x942B\x9435\x9421\x943A\x9441\x9452" ++
+    {-0x68-}  chars "\x9444\x945B\x9460\x9462\x945E\x946A\x9229\x9470" ++
+    {-0x70-}  chars "\x9475\x9477\x947D\x945A\x947C\x947E\x9481\x947F" ++
+    {-0x78-}  chars "\x9582\x9587\x958A\x9594\x9596\x9598\x9599" ++ Nothing :
+    {-0x80-}  chars "\x95A0\x95A8\x95A7\x95AD\x95BC\x95BB\x95B9\x95BE" ++
+    {-0x88-}  chars "\x95CA\x6FF6\x95C3\x95CD\x95CC\x95D5\x95D4\x95D6" ++
+    {-0x90-}  chars "\x95DC\x95E1\x95E5\x95E2\x9621\x9628\x962E\x962F" ++
+    {-0x98-}  chars "\x9642\x964C\x964F\x964B\x9677\x965C\x965E\x965D" ++
+    {-0xA0-}  chars "\x965F\x9666\x9672\x966C\x968D\x9698\x9695\x9697" ++
+    {-0xA8-}  chars "\x96AA\x96A7\x96B1\x96B2\x96B0\x96B4\x96B6\x96B8" ++
+    {-0xB0-}  chars "\x96B9\x96CE\x96CB\x96C9\x96CD\x894D\x96DC\x970D" ++
+    {-0xB8-}  chars "\x96D5\x96F9\x9704\x9706\x9708\x9713\x970E\x9711" ++
+    {-0xC0-}  chars "\x970F\x9716\x9719\x9724\x972A\x9730\x9739\x973D" ++
+    {-0xC8-}  chars "\x973E\x9744\x9746\x9748\x9742\x9749\x975C\x9760" ++
+    {-0xD0-}  chars "\x9764\x9766\x9768\x52D2\x976B\x9771\x9779\x9785" ++
+    {-0xD8-}  chars "\x977C\x9781\x977A\x9786\x978B\x978F\x9790\x979C" ++
+    {-0xE0-}  chars "\x97A8\x97A6\x97A3\x97B3\x97B4\x97C3\x97C6\x97C8" ++
+    {-0xE8-}  chars "\x97CB\x97DC\x97ED\x9F4F\x97F2\x7ADF\x97F6\x97F5" ++
+    {-0xF0-}  chars "\x980F\x980C\x9838\x9824\x9821\x9837\x983D\x9846" ++
+    {-0xF8-}  chars "\x984F\x984B\x986B\x986F\x9870"
+
+-- | The multibyte characters with a lead byte of @0xE9@.
+secondE9 :: SecondByteTable
+secondE9 = V.fromList $
+    {-0x40-}  chars "\x9871\x9874\x9873\x98AA\x98AF\x98B1\x98B6\x98C4" ++
+    {-0x48-}  chars "\x98C3\x98C6\x98E9\x98EB\x9903\x9909\x9912\x9914" ++
+    {-0x50-}  chars "\x9918\x9921\x991D\x991E\x9924\x9920\x992C\x992E" ++
+    {-0x58-}  chars "\x993D\x993E\x9942\x9949\x9945\x9950\x994B\x9951" ++
+    {-0x60-}  chars "\x9952\x994C\x9955\x9997\x9998\x99A5\x99AD\x99AE" ++
+    {-0x68-}  chars "\x99BC\x99DF\x99DB\x99DD\x99D8\x99D1\x99ED\x99EE" ++
+    {-0x70-}  chars "\x99F1\x99F2\x99FB\x99F8\x9A01\x9A0F\x9A05\x99E2" ++
+    {-0x78-}  chars "\x9A19\x9A2B\x9A37\x9A45\x9A42\x9A40\x9A43" ++ Nothing :
+    {-0x80-}  chars "\x9A3E\x9A55\x9A4D\x9A5B\x9A57\x9A5F\x9A62\x9A65" ++
+    {-0x88-}  chars "\x9A64\x9A69\x9A6B\x9A6A\x9AAD\x9AB0\x9ABC\x9AC0" ++
+    {-0x90-}  chars "\x9ACF\x9AD1\x9AD3\x9AD4\x9ADE\x9ADF\x9AE2\x9AE3" ++
+    {-0x98-}  chars "\x9AE6\x9AEF\x9AEB\x9AEE\x9AF4\x9AF1\x9AF7\x9AFB" ++
+    {-0xA0-}  chars "\x9B06\x9B18\x9B1A\x9B1F\x9B22\x9B23\x9B25\x9B27" ++
+    {-0xA8-}  chars "\x9B28\x9B29\x9B2A\x9B2E\x9B2F\x9B32\x9B44\x9B43" ++
+    {-0xB0-}  chars "\x9B4F\x9B4D\x9B4E\x9B51\x9B58\x9B74\x9B93\x9B83" ++
+    {-0xB8-}  chars "\x9B91\x9B96\x9B97\x9B9F\x9BA0\x9BA8\x9BB4\x9BC0" ++
+    {-0xC0-}  chars "\x9BCA\x9BB9\x9BC6\x9BCF\x9BD1\x9BD2\x9BE3\x9BE2" ++
+    {-0xC8-}  chars "\x9BE4\x9BD4\x9BE1\x9C3A\x9BF2\x9BF1\x9BF0\x9C15" ++
+    {-0xD0-}  chars "\x9C14\x9C09\x9C13\x9C0C\x9C06\x9C08\x9C12\x9C0A" ++
+    {-0xD8-}  chars "\x9C04\x9C2E\x9C1B\x9C25\x9C24\x9C21\x9C30\x9C47" ++
+    {-0xE0-}  chars "\x9C32\x9C46\x9C3E\x9C5A\x9C60\x9C67\x9C76\x9C78" ++
+    {-0xE8-}  chars "\x9CE7\x9CEC\x9CF0\x9D09\x9D08\x9CEB\x9D03\x9D06" ++
+    {-0xF0-}  chars "\x9D2A\x9D26\x9DAF\x9D23\x9D1F\x9D44\x9D15\x9D12" ++
+    {-0xF8-}  chars "\x9D41\x9D3F\x9D3E\x9D46\x9D48"
+
+-- | The multibyte characters with a lead byte of @0xEA@.
+secondEA :: SecondByteTable
+secondEA = V.fromList $
+    {-0x40-}  chars "\x9D5D\x9D5E\x9D64\x9D51\x9D50\x9D59\x9D72\x9D89" ++
+    {-0x48-}  chars "\x9D87\x9DAB\x9D6F\x9D7A\x9D9A\x9DA4\x9DA9\x9DB2" ++
+    {-0x50-}  chars "\x9DC4\x9DC1\x9DBB\x9DB8\x9DBA\x9DC6\x9DCF\x9DC2" ++
+    {-0x58-}  chars "\x9DD9\x9DD3\x9DF8\x9DE6\x9DED\x9DEF\x9DFD\x9E1A" ++
+    {-0x60-}  chars "\x9E1B\x9E1E\x9E75\x9E79\x9E7D\x9E81\x9E88\x9E8B" ++
+    {-0x68-}  chars "\x9E8C\x9E92\x9E95\x9E91\x9E9D\x9EA5\x9EA9\x9EB8" ++
+    {-0x70-}  chars "\x9EAA\x9EAD\x9761\x9ECC\x9ECE\x9ECF\x9ED0\x9ED4" ++
+    {-0x78-}  chars "\x9EDC\x9EDE\x9EDD\x9EE0\x9EE5\x9EE8\x9EEF" ++ Nothing :
+    {-0x80-}  chars "\x9EF4\x9EF6\x9EF7\x9EF9\x9EFB\x9EFC\x9EFD\x9F07" ++
+    {-0x88-}  chars "\x9F08\x76B7\x9F15\x9F21\x9F2C\x9F3E\x9F4A\x9F52" ++
+    {-0x90-}  chars "\x9F54\x9F63\x9F5F\x9F60\x9F61\x9F66\x9F67\x9F6C" ++
+    {-0x98-}  chars "\x9F6A\x9F77\x9F72\x9F76\x9F95\x9F9C\x9FA0\x582F" ++
+    {-0xA0-}  chars "\x69C7\x9059\x7464\x51DC\x7199" ++
+    {-0xA5..0xFC-} nothings 0x58
+
+-- | The multibyte characters with a lead byte of @0xEB@.
+secondEB :: SecondByteTable
+secondEB = nothingSecond
+
+-- | The multibyte characters with a lead byte of @0xEC@.
+secondEC :: SecondByteTable
+secondEC = nothingSecond
+
+-- | The multibyte characters with a lead byte of @0xED@.
+secondED :: SecondByteTable
+secondED = V.fromList $
+    {-0x40-}  chars "\x7E8A\x891C\x9348\x9288\x84DC\x4FC9\x70BB\x6631" ++
+    {-0x48-}  chars "\x68C8\x92F9\x66FB\x5F45\x4E28\x4EE1\x4EFC\x4F00" ++
+    {-0x50-}  chars "\x4F03\x4F39\x4F56\x4F92\x4F8A\x4F9A\x4F94\x4FCD" ++
+    {-0x58-}  chars "\x5040\x5022\x4FFF\x501E\x5046\x5070\x5042\x5094" ++
+    {-0x60-}  chars "\x50F4\x50D8\x514A\x5164\x519D\x51BE\x51EC\x5215" ++
+    {-0x68-}  chars "\x529C\x52A6\x52C0\x52DB\x5300\x5307\x5324\x5372" ++
+    {-0x70-}  chars "\x5393\x53B2\x53DD\xFA0E\x549C\x548A\x54A9\x54FF" ++
+    {-0x78-}  chars "\x5586\x5759\x5765\x57AC\x57C8\x57C7\xFA0F" ++ Nothing :
+    {-0x80-}  chars "\xFA10\x589E\x58B2\x590B\x5953\x595B\x595D\x5963" ++
+    {-0x88-}  chars "\x59A4\x59BA\x5B56\x5BC0\x752F\x5BD8\x5BEC\x5C1E" ++
+    {-0x90-}  chars "\x5CA6\x5CBA\x5CF5\x5D27\x5D53\xFA11\x5D42\x5D6D" ++
+    {-0x98-}  chars "\x5DB8\x5DB9\x5DD0\x5F21\x5F34\x5F67\x5FB7\x5FDE" ++
+    {-0xA0-}  chars "\x605D\x6085\x608A\x60DE\x60D5\x6120\x60F2\x6111" ++
+    {-0xA8-}  chars "\x6137\x6130\x6198\x6213\x62A6\x63F5\x6460\x649D" ++
+    {-0xB0-}  chars "\x64CE\x654E\x6600\x6615\x663B\x6609\x662E\x661E" ++
+    {-0xB8-}  chars "\x6624\x6665\x6657\x6659\xFA12\x6673\x6699\x66A0" ++
+    {-0xC0-}  chars "\x66B2\x66BF\x66FA\x670E\xF929\x6766\x67BB\x6852" ++
+    {-0xC8-}  chars "\x67C0\x6801\x6844\x68CF\xFA13\x6968\xFA14\x6998" ++
+    {-0xD0-}  chars "\x69E2\x6A30\x6A6B\x6A46\x6A73\x6A7E\x6AE2\x6AE4" ++
+    {-0xD8-}  chars "\x6BD6\x6C3F\x6C5C\x6C86\x6C6F\x6CDA\x6D04\x6D87" ++
+    {-0xE0-}  chars "\x6D6F\x6D96\x6DAC\x6DCF\x6DF8\x6DF2\x6DFC\x6E39" ++
+    {-0xE8-}  chars "\x6E5C\x6E27\x6E3C\x6EBF\x6F88\x6FB5\x6FF5\x7005" ++
+    {-0xF0-}  chars "\x7007\x7028\x7085\x70AB\x710F\x7104\x715C\x7146" ++
+    {-0xF8-}  chars "\x7147\xFA15\x71C1\x71FE\x72B1"
+
+-- | The multibyte characters with a lead byte of @0xEE@.
+secondEE :: SecondByteTable
+secondEE = V.fromList $
+    {-0x40-}  chars "\x72BE\x7324\xFA16\x7377\x73BD\x73C9\x73D6\x73E3" ++
+    {-0x48-}  chars "\x73D2\x7407\x73F5\x7426\x742A\x7429\x742E\x7462" ++
+    {-0x50-}  chars "\x7489\x749F\x7501\x756F\x7682\x769C\x769E\x769B" ++
+    {-0x58-}  chars "\x76A6\xFA17\x7746\x52AF\x7821\x784E\x7864\x787A" ++
+    {-0x40-}  chars "\x7930\xFA18\xFA19\xFA1A\x7994\xFA1B\x799B\x7AD1" ++
+    {-0x68-}  chars "\x7AE7\xFA1C\x7AEB\x7B9E\xFA1D\x7D48\x7D5C\x7DB7" ++
+    {-0x70-}  chars "\x7DA0\x7DD6\x7E52\x7F47\x7FA1\xFA1E\x8301\x8362" ++
+    {-0x78-}  chars "\x837F\x83C7\x83F6\x8448\x84B4\x8553\x8559" ++ Nothing :
+    {-0x80-}  chars "\x856B\xFA1F\x85B0\xFA20\xFA21\x8807\x88F5\x8A12" ++
+    {-0x88-}  chars "\x8A37\x8A79\x8AA7\x8ABE\x8ADF\xFA22\x8AF6\x8B53" ++
+    {-0x90-}  chars "\x8B7F\x8CF0\x8CF4\x8D12\x8D76\xFA23\x8ECF\xFA24" ++
+    {-0x98-}  chars "\xFA25\x9067\x90DE\xFA26\x9115\x9127\x91DA\x91D7" ++
+    {-0xA0-}  chars "\x91DE\x91ED\x91EE\x91E4\x91E5\x9206\x9210\x920A" ++
+    {-0xA8-}  chars "\x923A\x9240\x923C\x924E\x9259\x9251\x9239\x9267" ++
+    {-0xB0-}  chars "\x92A7\x9277\x9278\x92E7\x92D7\x92D9\x92D0\xFA27" ++
+    {-0xB8-}  chars "\x92D5\x92E0\x92D3\x9325\x9321\x92FB\xFA28\x931E" ++
+    {-0xC0-}  chars "\x92FF\x931D\x9302\x9370\x9357\x93A4\x93C6\x93DE" ++
+    {-0xC8-}  chars "\x93F8\x9431\x9445\x9448\x9592\xF9DC\xFA29\x969D" ++
+    {-0xD0-}  chars "\x96AF\x9733\x973B\x9743\x974D\x974F\x9751\x9755" ++
+    {-0xD8-}  chars "\x9857\x9865\xFA2A\xFA2B\x9927\xFA2C\x999E\x9A4E" ++
+    {-0xE0-}  chars "\x9AD9\x9ADC\x9B75\x9B72\x9B8F\x9BB1\x9BBB\x9C00" ++
+    {-0xE8-}  chars "\x9D70\x9D6B\xFA2D\x9E19\x9ED1" ++ nothings 2 ++
+    {-0xEF..0xF8-}  chars ['\x2170'..'\x2179'] ++
+    {-0xF9-}  chars "\xFFE2\xFFE4\xFF07\xFF02"
+
+-- | The multibyte characters with a lead byte of @0xEF@.
+secondEF :: SecondByteTable
+secondEF = nothingSecond
+
+-- | The multibyte characters with a lead byte of @0xF0@.
+secondF0 :: SecondByteTable
+secondF0 = privateUseSecond 0xE000
+
+-- | The multibyte characters with a lead byte of @0xF1@.
+secondF1 :: SecondByteTable
+secondF1 = privateUseSecond 0xE0BC
+
+-- | The multibyte characters with a lead byte of @0xF2@.
+secondF2 :: SecondByteTable
+secondF2 = privateUseSecond 0xE178
+
+-- | The multibyte characters with a lead byte of @0xF3@.
+secondF3 :: SecondByteTable
+secondF3 = privateUseSecond 0xE234
+
+-- | The multibyte characters with a lead byte of @0xF4@.
+secondF4 :: SecondByteTable
+secondF4 = privateUseSecond 0xE2F0
+
+-- | The multibyte characters with a lead byte of @0xF5@.
+secondF5 :: SecondByteTable
+secondF5 = privateUseSecond 0xE3AC
+
+-- | The multibyte characters with a lead byte of @0xF6@.
+secondF6 :: SecondByteTable
+secondF6 = privateUseSecond 0xE468
+
+-- | The multibyte characters with a lead byte of @0xF7@.
+secondF7 :: SecondByteTable
+secondF7 = privateUseSecond 0xE524
+
+-- | The multibyte characters with a lead byte of @0xF8@.
+secondF8 :: SecondByteTable
+secondF8 = privateUseSecond 0xE5E0
+
+-- | The multibyte characters with a lead byte of @0xF9@.
+secondF9 :: SecondByteTable
+secondF9 = privateUseSecond 0xE69C
+
+-- | The multibyte characters with a lead byte of @0xFA@.
+secondFA :: SecondByteTable
+secondFA = V.fromList $
+    {-0x40..0x49-}  chars ['\x2170'..'\x2179'] ++
+    {-0x4A..0x53-}  chars ['\x2160'..'\x2169'] ++
+    {-0x54-}  chars "\xFFE2\xFFE4\xFF07\xFF02" ++
+    {-0x58-}  chars "\x3231\x2116\x2121\x2235\x7E8A\x891C\x9348\x9288" ++
+    {-0x60-}  chars "\x84DC\x4FC9\x70BB\x6631\x68C8\x92F9\x66FB\x5F45" ++
+    {-0x68-}  chars "\x4E28\x4EE1\x4EFC\x4F00\x4F03\x4F39\x4F56\x4F92" ++
+    {-0x70-}  chars "\x4F8A\x4F9A\x4F94\x4FCD\x5040\x5022\x4FFF\x501E" ++
+    {-0x78-}  chars "\x5046\x5070\x5042\x5094\x50F4\x50D8\x514A" ++ Nothing :
+    {-0x80-}  chars "\x5164\x519D\x51BE\x51EC\x5215\x529C\x52A6\x52C0" ++
+    {-0x88-}  chars "\x52DB\x5300\x5307\x5324\x5372\x5393\x53B2\x53DD" ++
+    {-0x90-}  chars "\xFA0E\x549C\x548A\x54A9\x54FF\x5586\x5759\x5765" ++
+    {-0x98-}  chars "\x57AC\x57C8\x57C7\xFA0F\xFA10\x589E\x58B2\x590B" ++
+    {-0xA0-}  chars "\x5953\x595B\x595D\x5963\x59A4\x59BA\x5B56\x5BC0" ++
+    {-0xA8-}  chars "\x752F\x5BD8\x5BEC\x5C1E\x5CA6\x5CBA\x5CF5\x5D27" ++
+    {-0xB0-}  chars "\x5D53\xFA11\x5D42\x5D6D\x5DB8\x5DB9\x5DD0\x5F21" ++
+    {-0xB8-}  chars "\x5F34\x5F67\x5FB7\x5FDE\x605D\x6085\x608A\x60DE" ++
+    {-0xC0-}  chars "\x60D5\x6120\x60F2\x6111\x6137\x6130\x6198\x6213" ++
+    {-0xC8-}  chars "\x62A6\x63F5\x6460\x649D\x64CE\x654E\x6600\x6615" ++
+    {-0xD0-}  chars "\x663B\x6609\x662E\x661E\x6624\x6665\x6657\x6659" ++
+    {-0xD8-}  chars "\xFA12\x6673\x6699\x66A0\x66B2\x66BF\x66FA\x670E" ++
+    {-0xE0-}  chars "\xF929\x6766\x67BB\x6852\x67C0\x6801\x6844\x68CF" ++
+    {-0xE8-}  chars "\xFA13\x6968\xFA14\x6998\x69E2\x6A30\x6A6B\x6A46" ++
+    {-0xF0-}  chars "\x6A73\x6A7E\x6AE2\x6AE4\x6BD6\x6C3F\x6C5C\x6C86" ++
+    {-0xF8-}  chars "\x6C6F\x6CDA\x6D04\x6D87\x6D6F"
+
+-- | The multibyte characters with a lead byte of @0xFB@.
+secondFB :: SecondByteTable
+secondFB = V.fromList $
+    {-0x40-}  chars "\x6D96\x6DAC\x6DCF\x6DF8\x6DF2\x6DFC\x6E39\x6E5C" ++
+    {-0x48-}  chars "\x6E27\x6E3C\x6EBF\x6F88\x6FB5\x6FF5\x7005\x7007" ++
+    {-0x50-}  chars "\x7028\x7085\x70AB\x710F\x7104\x715C\x7146\x7147" ++
+    {-0x58-}  chars "\xFA15\x71C1\x71FE\x72B1\x72BE\x7324\xFA16\x7377" ++
+    {-0x60-}  chars "\x73BD\x73C9\x73D6\x73E3\x73D2\x7407\x73F5\x7426" ++
+    {-0x68-}  chars "\x742A\x7429\x742E\x7462\x7489\x749F\x7501\x756F" ++
+    {-0x70-}  chars "\x7682\x769C\x769E\x769B\x76A6\xFA17\x7746\x52AF" ++
+    {-0x78-}  chars "\x7821\x784E\x7864\x787A\x7930\xFA18\xFA19" ++ Nothing :
+    {-0x80-}  chars "\xFA1A\x7994\xFA1B\x799B\x7AD1\x7AE7\xFA1C\x7AEB" ++
+    {-0x88-}  chars "\x7B9E\xFA1D\x7D48\x7D5C\x7DB7\x7DA0\x7DD6\x7E52" ++
+    {-0x90-}  chars "\x7F47\x7FA1\xFA1E\x8301\x8362\x837F\x83C7\x83F6" ++
+    {-0x98-}  chars "\x8448\x84B4\x8553\x8559\x856B\xFA1F\x85B0\xFA20" ++
+    {-0xA0-}  chars "\xFA21\x8807\x88F5\x8A12\x8A37\x8A79\x8AA7\x8ABE" ++
+    {-0xA8-}  chars "\x8ADF\xFA22\x8AF6\x8B53\x8B7F\x8CF0\x8CF4\x8D12" ++
+    {-0xB0-}  chars "\x8D76\xFA23\x8ECF\xFA24\xFA25\x9067\x90DE\xFA26" ++
+    {-0xB8-}  chars "\x9115\x9127\x91DA\x91D7\x91DE\x91ED\x91EE\x91E4" ++
+    {-0xC0-}  chars "\x91E5\x9206\x9210\x920A\x923A\x9240\x923C\x924E" ++
+    {-0xC8-}  chars "\x9259\x9251\x9239\x9267\x92A7\x9277\x9278\x92E7" ++
+    {-0xD0-}  chars "\x92D7\x92D9\x92D0\xFA27\x92D5\x92E0\x92D3\x9325" ++
+    {-0xD8-}  chars "\x9321\x92FB\xFA28\x931E\x92FF\x931D\x9302\x9370" ++
+    {-0xE0-}  chars "\x9357\x93A4\x93C6\x93DE\x93F8\x9431\x9445\x9448" ++
+    {-0xE8-}  chars "\x9592\xF9DC\xFA29\x969D\x96AF\x9733\x973B\x9743" ++
+    {-0xF0-}  chars "\x974D\x974F\x9751\x9755\x9857\x9865\xFA2A\xFA2B" ++
+    {-0xF8-}  chars "\x9927\xFA2C\x999E\x9A4E\x9AD9"
+
+-- | The multibyte characters with a lead byte of @0xFC@.
+secondFC :: SecondByteTable
+secondFC = V.fromList $
+    {-0x40-}  chars "\x9ADC\x9B75\x9B72\x9B8F\x9BB1\x9BBB\x9C00\x9D70" ++
+    {-0x48-}  chars "\x9D6B\xFA2D\x9E19\x9ED1" ++
+    {-0x4C..0xFC-} nothings 0xB1
diff --git a/src/Foreign/Libcdio.hs b/src/Foreign/Libcdio.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Libcdio.hs
@@ -0,0 +1,74 @@
+{-|
+Description:    Bindings directly mirroring the C interface of libcdio.
+
+Copyright:      (c) 2018-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+Modules in this tree are designed so users familiar with working with the
+original libcdio should be able to write essentially the same code they're
+used to, in the 'IO' monad.  There have, however, been some changes made (beyond
+mapping the types to ones more native to Haskell), mostly to take advantage of
+the type safety.  These have then been adapted further into the modules under
+"Sound.Libcdio", which aim to provide much of the same functionality but in a
+form the library might have taken if it had been originally written for
+Haskell.
+
+As /this/ interface does mirror the structure of the C library, each header
+file is translated into a separate module, as follows.  Any changes from those
+original headers which might not be easily guessed are noted in the
+documentation for each module, along with similar equivalencies to the
+higher-level interface.
+
+* @cdio.h@ -> "Foreign.Libcdio"
+* @cd_types.h@ -> "Foreign.Libcdio.CdTypes" (not reexported by @cdio.h@, or this module)
+* @cdtext.h@ -> "Foreign.Libcdio.CdText"
+* @device.h@ -> "Foreign.Libcdio.Device"
+* @disc.h@ -> "Foreign.Libcdio.Disc"
+* @logging.h@ -> "Foreign.Libcdio.Logging" (not reexported by @cdio.h@, or this module)
+* @memory.h@ (removed; the only exported symbol @cdio_free@ is encapsulated
+  into the Haskell garbage collection)
+* @read.h@ -> "Foreign.Libcdio.Read"
+* @sector.h@ -> "Foreign.Libcdio.Sector"
+* @track.h@ -> "Foreign.Libcdio.Track"
+* @types.h@ -> "Foreign.Libcdio.Types"
+
+    * The original header was an interesting collection of some (but not all)
+      types used by the library.  The module is both more universal by
+      exporting all types in the interface, and less required as each relevant
+      type is exported by the various modules themselves.
+
+* @util.h@ -> "Foreign.Libcdio.Util" (not reexported by @cdio.h@, or this module)
+* @version.h@ -> "Foreign.Libcdio.Version"
+
+
+= @cdio.h@
+
+== Defines
+* @CDIO_API_VERSION@                -> 'apiVersion' (primarily exported from "Foreign.Libcdio.Version")
+
+== Types
+* @CdIo_t@                          -> 'Cdio' (primarily exported from "Foreign.Libcdio.Device")
+-}
+module Foreign.Libcdio
+    ( module Foreign.Libcdio.CdText
+    , module Foreign.Libcdio.Device
+    , module Foreign.Libcdio.Disc
+    , module Foreign.Libcdio.Read
+    , module Foreign.Libcdio.Sector
+    , module Foreign.Libcdio.Track
+    , module Foreign.Libcdio.Version
+    ) where
+
+
+import Foreign.Libcdio.Version
+import Foreign.Libcdio.Sector
+
+import Foreign.Libcdio.Device
+import Foreign.Libcdio.CdText
+import Foreign.Libcdio.Disc
+import Foreign.Libcdio.Read
+import Foreign.Libcdio.Track
diff --git a/src/Foreign/Libcdio/CdText.hs b/src/Foreign/Libcdio/CdText.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Libcdio/CdText.hs
@@ -0,0 +1,310 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+{-|
+Description:    Functions and types providing metadata about the disc contents.
+
+Copyright:      (c) 2018-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+Metadata is stored in a binary format both library-internally and on the disc.
+Most audio archivists will recognize it as "those information fields in a CUE
+file" (though there are [other
+formats](https://www.gnu.org/software/libcdio/cd-text-format.html#Sony-Text-File-Format-_0028Input-Sheet-Version-0_002e7T_0029)
+as well), and casual listeners will recognize it as the scrolling text that
+you're always happy to see, on the rare times your music player shows it.
+Little-used and even-less-known, however, is that a single disc can
+theoretically contain metadata in up to eight different languages; because of
+the complexity that introduces, no unifying datatype is provided in favour of a
+function-based interface.
+
+
+= @cdtext.h@
+
+== Defines
+* @MIN_CDTEXT_FIELD@                (removed; identical to @'minBound' :: 'Field'@)
+* @MAX_CDTEXT_FIELD@                (removed; identical to @'maxBound' :: 'Field'@)
+
+== Types
+* @cdtext_field_t@                  -> 'Field'
+
+    - @CDTEXT_FIELD_INVALID@        (removed; handled via 'Nothing')
+
+* @cdtext_genre_t@                  -> 'Genre'
+
+    - @CDTEXT_GENRE_UNUSED@         (removed; handled via 'Nothing')
+
+* @cdtext_lang_t@                   -> 'Language'
+
+    - @CDTEXT_LANGUAGE_UNKNOWN@     -> 'UnknownLanguage'
+
+        - /Before libcdio 2.1.0:  (often effectively removed; handled via 'Nothing')/
+
+    - @CDTEXT_LANGUAGE_INVALID@     (removed; handled via 'Nothing')
+    - @CDTEXT_LANGUAGE_BLOCK_UNUSED@ (removed; handled via 'Nothing')
+
+* @cdtext_t@                        (removed; merged into 'Cdio' objects)
+
+== Symbols
+* @cdtext_data_init@                -> 'cdTextDataInit'
+* @cdtext_destroy@                  (removed; handled via the garbage collector)
+* @cdtext_field2str@                -> 'fieldString'
+* @cdtext_genre2str@                -> 'genreString'
+* @cdtext_get@                      (removed; type conversion makes it identical to @cdtext_get_const@)
+* @cdtext_get_const@                -> 'cdTextGet'
+* @cdtext_get_first_track@          -> 'firstTrack'
+* @cdtext_get_genre@                -> 'genre'
+* @cdtext_get_language@             -> 'language'
+* @cdtext_get_last_track@           -> 'lastTrack'
+* @cdtext_init@                     (removed; internal function without much external occasion)
+* @cdtext_lang2str@                 -> 'languageString'
+* @cdtext_list_languages@           -> 'listLanguages'
+* @cdtext_list_languages_v2@        -> 'listAllLanguages'
+* @cdtext_select_language@          -> 'selectLanguage'
+* @cdtext_set@                      (removed; primarily intended for internal use, and is more limited than would be expected)
+* @cdtext_set_language_index@       -> 'selectLanguageIndex'
+* @cdtext_str2lang@                 -> 'parseLanguage'
+
+
+= "Sound.Libcdio.Read.CdText"
+While similar functionality is provided, the
+@"Sound.Libcdio.Read".'Sound.Libcdio.Read.CdText'@ is written as a separate
+monadic interface rather than in the 'Cdio'-bound style used here.
+
+* 'cdTextDataInit'                  -> 'Sound.Libcdio.Read.CdText.parseCdText'
+* 'cdTextGet'                       -> 'Sound.Libcdio.Read.CdText.discId', @'snd' 'Sound.Libcdio.Read.CdText.genre'@, and 'Sound.Libcdio.Read.CdText.info'
+* 'genre'                           -> @'fst' 'Sound.Libcdio.Read.CdText.genre'@
+* 'listAllLanguages'                -> 'Sound.Libcdio.Read.CdText.languages'
+* 'listLanguages'                   (removed; obsolete and imprecise)
+* 'selectLanguage'                  -> 'Sound.Libcdio.Read.CdText.withLanguage'
+* 'selectLanguageIndex'             -> 'Sound.Libcdio.Read.CdText.withIndex'
+-}
+module Foreign.Libcdio.CdText
+    ( -- * Types
+      Cdio
+    , Field ( .. )
+    , Genre ( .. )
+    , Language ( .. )
+      -- * Description
+    , fieldString
+    , languageString
+    , parseLanguage
+    , genreString
+      -- * Management
+    , cdTextDataInit
+    , listLanguages
+    , listAllLanguages
+    , selectLanguage
+    , selectLanguageIndex
+      -- * Access
+    , cdTextGet
+    , genre
+    , language
+    , firstTrack
+    , lastTrack
+    ) where
+
+
+import qualified Data.List as L
+import qualified Data.Maybe as Y
+
+import qualified Foreign.C.String as C
+import qualified Foreign.C.Types as C
+import qualified Foreign.Ptr as C
+
+import qualified Foreign.Marshal.Array as M
+import qualified Foreign.Marshal.Utils as M
+
+import qualified System.IO.Unsafe as IO.Unsafe
+
+import Foreign.Libcdio.Device
+import Foreign.Libcdio.Marshal
+import Foreign.Libcdio.Track
+import Foreign.Libcdio.Types.Enums
+import Foreign.Libcdio.Types.Internal
+import Foreign.Libcdio.Version
+
+import Sound.Libcdio.Common
+
+
+-- | Return a canonical English name of the given genre, as opposed to the
+-- machine representation returned by the 'Show' instance.
+genreString :: Genre -> String
+genreString = IO.Unsafe.unsafePerformIO .
+    C.peekCString . genreString' . fromIntegral . fromEnum
+
+foreign import ccall safe "cdio/compat/cdtext.h cdtext_genre2str"
+  genreString' :: CGenre -> C.CString
+
+-- | Return a canonical English name of the given language, as opposed to the
+-- machine representation returned by the 'Show' instance.
+languageString :: Language -> String
+languageString = IO.Unsafe.unsafePerformIO .
+    C.peekCString . languageString' . fromIntegral . fromEnum
+
+foreign import ccall safe "cdio/compat/cdtext.h cdtext_lang2str"
+  languageString' :: CLanguage -> C.CString
+
+-- | Transform a string returned by 'languageString' back into its
+-- 'Language' representation.
+-- 
+-- /Before libcdio 2.1.0:  Always returns 'Nothing'/
+parseLanguage :: String -> Maybe Language
+parseLanguage s
+    | libcdioVersionNum >= makeVersion [2,1] = IO.Unsafe.unsafePerformIO $ do
+        i <- C.withCString s parseLanguage'
+        return . fmap (toEnum . fromIntegral) $ maybeError [languageInvalid, languageUnused] i
+    | otherwise = Nothing
+
+foreign import ccall safe "cdio/compat/cdtext.h cdtext_str2lang_safe"
+  parseLanguage' :: C.CString -> IO CLanguage
+
+foreign import ccall safe "cdio/compat/cdtext.h language_unknown"
+  languageUnknown :: CLanguage
+
+foreign import ccall safe "cdio/compat/cdtext.h language_invalid"
+  languageInvalid :: CLanguage
+
+foreign import ccall safe "cdio/compat/cdtext.h language_unused"
+  languageUnused :: CLanguage
+
+-- | Describe the type of data in a human-readable manner, as opposed to the
+-- machine representation returned by the 'Show' instance.
+fieldString :: Field -> String
+fieldString = IO.Unsafe.unsafePerformIO .
+    C.peekCString . fieldString' . fromIntegral . fromEnum
+
+foreign import ccall safe "cdio/compat/cdtext.h cdtext_field2str"
+  fieldString' :: CField -> C.CString
+
+
+-- | Attempt to retrieve the value of a given field from the disc (if
+-- 'Nothing') or track (if 'Just') metadata, in the currently-active language.
+-- Note that 'GenreName' and 'DiscId' will /always/ refer to the disc-level
+-- data.
+cdTextGet :: Cdio -> Field -> Maybe Track -> IO (Maybe String)
+cdTextGet _ _ (Just DiscPregap) = return Nothing
+cdTextGet _ _ (Just DiscLeadout) = return Nothing
+cdTextGet c GenreName _ = cdTextGet_ c GenreName 0
+cdTextGet c DiscId _ = cdTextGet_ c DiscId 0
+cdTextGet c f Nothing = cdTextGet_ c f 0
+cdTextGet c f (Just t) = cdTextGet_ c f t
+
+cdTextGet_ :: Cdio -> Field -> Track -> IO (Maybe String)
+cdTextGet_ c f t = withCdText' Nothing c $ \x ->
+    cdTextGet' x (fromIntegral $ fromEnum f) (fromIntegral $ fromEnum t) >>= M.maybePeek C.peekCString
+
+foreign import ccall safe "cdio/compat/cdtext.h cdtext_get_const"
+  cdTextGet' :: C.Ptr CdText -> CField -> CTrack -> IO C.CString
+
+
+-- | The machine-readable genre describing the music on this disc.  For any
+-- associated human-readable name or subgenre, use @'cdTextGet' c 'GenreName'
+-- 'Nothing'@.
+genre :: Cdio -> IO (Maybe Genre)
+genre c = do
+    g <- withCdText c genre'
+    return $ if g == Just 0 then Nothing else toEnum . fromIntegral <$> g
+
+foreign import ccall safe "cdio/compat/cdtext.h cdtext_get_genre"
+  genre' :: C.Ptr CdText -> IO CGenre
+
+-- | Indicate which language results will (currently) be returned in.  See
+-- 'selectLanguage' to change this.
+language :: Cdio -> IO (Maybe Language)
+language c = fmap (toEnum . fromIntegral) <$> withCdText c language'
+
+foreign import ccall safe "cdio/compat/cdtext.h cdtext_get_language"
+  language' :: C.Ptr CdText -> IO CLanguage
+
+
+-- | The earliest track with any associated metadata in the current language.
+-- Note that this may differ from 'minTrack'.
+firstTrack :: Cdio -> IO (Maybe Track)
+firstTrack c = fmap (toEnum . fromIntegral) . maybeError [0] <$> withCdText' 0 c firstTrack'
+
+foreign import ccall safe "cdio/compat/cdtext.h cdtext_get_first_track"
+  firstTrack' :: C.Ptr CdText -> IO CTrack
+
+-- | The final track with any associated metadata in the current language.
+-- Note that this may differ from 'maxTrack'.
+lastTrack :: Cdio -> IO (Maybe Track)
+lastTrack c = fmap (toEnum . fromIntegral) . maybeError [0] <$> withCdText' 0 c lastTrack'
+
+foreign import ccall safe "cdio/compat/cdtext.h cdtext_get_last_track"
+  lastTrack' :: C.Ptr CdText -> IO CTrack
+
+
+-- | Try to set the data associated with the given language as active for
+-- future calls to 'cdTextGet' and similar.  If passed 'UnknownLanguage' or the
+-- CDTEXT does not provide the one requested, selects the first (default) data
+-- set instead, and returns 'False'.
+selectLanguage :: Cdio -> Language -> IO Bool
+selectLanguage c l = fmap M.toBool . withCdText' 0 c $ \x ->
+    selectLanguage' x . fromIntegral $ fromEnum l
+
+foreign import ccall safe "cdio/compat/cdtext.h cdtext_select_language"
+  selectLanguage' :: C.Ptr CdText -> CLanguage -> IO CBool
+
+-- | Retrieve the languages included in the disc metadata.  Note that this does
+-- not save the index position or any duplicate language blocks (if that is
+-- desired, see 'listAllLanguages' instead).
+listLanguages :: Cdio -> IO [Language]
+listLanguages c = withCdText' [] c $ \x -> do
+    l' <- listLanguages' x
+    ls <- peekLanguages l' [languageUnknown, languageInvalid, languageUnused]
+    return . L.nub $ Y.catMaybes ls
+
+foreign import ccall safe "cdio/compat/cdtext.h cdtext_list_languages"
+  listLanguages' :: C.Ptr CdText -> IO (C.Ptr CLanguage)
+
+-- | Retrieve the languages included in the disc metadata, in the order they
+-- occur, and respecting any empty language blocks if there's a valid language
+-- after them (empty blocks at the end are cleaned away).
+-- 
+-- /Before libcdio 2.1.0:  Acts as 'listLanguages'/
+listAllLanguages :: Cdio -> IO [Maybe Language]
+listAllLanguages c = withCdText' [] c $ \x -> do
+    l' <- listAllLanguages' x
+    ls <- peekLanguages l' [languageInvalid, languageUnused]
+    return $ case L.dropWhileEnd Y.isNothing ls of
+        [] -> [Just UnknownLanguage]
+        ls' -> ls'
+
+foreign import ccall safe "cdio/compat/cdtext.h cdtext_list_languages_v2_safe"
+  listAllLanguages' :: C.Ptr CdText -> IO (C.Ptr CLanguage)
+
+peekLanguages :: C.Ptr CLanguage -> [CLanguage] -> IO [Maybe Language]
+peekLanguages p es
+    | p == C.nullPtr = return []
+    | otherwise = map (fmap (toEnum . fromIntegral) . maybeError es) <$> M.peekArray 8 p
+
+-- | Select the language at the given index of 'listAllLanguages' for future
+-- data retrieval.  If the index is out of bounds or corresponds to a 'Nothing'
+-- in 'listAllLanguages', the first (default) data set is selected instead and
+-- 'False is returned.
+selectLanguageIndex :: Cdio -> Word -> IO Bool
+selectLanguageIndex c i = M.toBool <$> withCdText' 0 c (flip selectLanguageIndex' $ fromIntegral i)
+
+foreign import ccall safe "cdio/compat/cdtext.h cdtext_set_language_index_safe"
+  selectLanguageIndex' :: C.Ptr CdText -> C.CInt -> IO CBool
+
+
+{- Primarily intended as an internal function
+-- | Set the given field at the given track to the given value.
+cdTextSet :: Cdio -> Field -> Maybe String -> Maybe Track -> IO ()
+cdTextSet _ _ _ (Just DiscPregap) = mempty
+cdTextSet _ _ _ (Just DiscLeadout) = mempty
+cdTextSet c f v Nothing = cdTextSet_ c f v 0
+cdTextSet c f v (Just t) = cdTextSet_ c f v t
+
+cdTextSet_ :: Cdio -> Field -> Maybe String -> Track -> IO ()
+cdTextSet_ c f v t = withCdText_ c $ \x -> M.maybeWith C.withCString v $ \s ->
+    cdTextSet' x (toCEnum f) s (withTrack t) C.nullPtr
+
+foreign import ccall safe "cdio/compat/cdtext.h cdtext_set"
+  cdTextSet' :: C.Ptr CdText -> CField -> C.CString -> CTrack -> C.CString -> IO ()
+-}
diff --git a/src/Foreign/Libcdio/CdText/Binary.hs b/src/Foreign/Libcdio/CdText/Binary.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Libcdio/CdText/Binary.hs
@@ -0,0 +1,409 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
+{-# OPTIONS_GHC -Wno-unused-imports #-}
+
+{-|
+Description:    
+
+Copyright:      (c) 2020-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+-}
+module Foreign.Libcdio.CdText.Binary
+    ( Info ( .. )
+    , emptyCdTextRaw
+    , packCdTextBlock
+    , joinBlockInfo
+    , checksum
+    ) where
+
+
+import qualified Data.Bits as B
+import qualified Data.Bifunctor as F.B
+import qualified Data.ByteString as BS
+import qualified Data.ByteString.Char8 as BS.C
+import qualified Data.Char as C
+import qualified Data.List as L
+import qualified Data.Maybe as Y
+import qualified Data.Word as W
+
+import qualified Data.Text as T
+import qualified Data.Text.Encoding.Error as T
+import qualified Data.Text.Encoding.MsJIS as T
+
+import Data.Bits ( (.&.), (.|.) )
+
+import Foreign.Libcdio.Track
+import Foreign.Libcdio.Types.Enums
+
+import Sound.Libcdio.Common
+
+
+type TrackId = W.Word8
+type PackType = W.Word8
+type BlockId = Word
+type BlockSize = W.Word8
+
+
+-- | Textual data used for describing tracks on a disc (as well as the disc
+-- itself).
+data Info = Info
+    { title      :: Maybe String
+    , performer  :: Maybe String
+    , songwriter :: Maybe String
+    , composer   :: Maybe String
+    , arranger   :: Maybe String
+    , message    :: Maybe String
+    , code       :: Maybe String
+    }
+  deriving ( Eq, Show, Read )
+
+
+emptyCdTextRaw :: [Maybe Language] -> BS.ByteString
+emptyCdTextRaw [] = emptyCdTextRaw [Nothing]
+emptyCdTextRaw ls =
+    BS.concat . concat . flip map (zip [0..] ls) $ \(i, _) -> map checksum .
+    joinBlockInfo ls [3 | _ <- ls] .
+    generateBlockInfo i Iso8859_1 0 0 $
+    replicate 15 0 ++ [3]
+
+
+data Encoding
+    = Iso8859_1
+    | ASCII
+    | MS_JIS
+  deriving ( Eq, Ord, Bounded, Show, Read )
+instance Enum Encoding where
+    toEnum 0x00 = Iso8859_1
+    toEnum 0x01 = ASCII
+    toEnum 0x80 = MS_JIS
+    toEnum _ = ASCII
+    fromEnum Iso8859_1 = 0x00
+    fromEnum ASCII = 0x01
+    fromEnum MS_JIS = 0x80
+
+data Pack
+    = TitlePack
+    | PerformerPack
+    | SongwriterPack
+    | ComposerPack
+    | ArrangerPack
+    | MessagePack
+    | DiscIdPack
+    | GenrePack
+    | TocPack
+    | Toc2Pack
+    | ClosedPack
+    | CodePack
+    | InfoPack
+  deriving ( Eq, Ord, Bounded, Enum, Show, Read )
+
+
+-- | Generate the binary data representing a CDTEXT language block.
+packCdTextBlock
+    :: BlockId
+    -> Maybe String
+    -> Track
+    -> Maybe Genre
+    -> Maybe String
+    -> Info
+    -> [Info]
+    -> [BS.ByteString]
+packCdTextBlock blockIndex catalogue startTrack@(Track _) genreCode genreName disc tracks =
+    allPacks <> generateBlockInfo blockIndex encoding startTrackId endTrackId allLengths
+  where (titles, tt) = text title TitlePack (0 :: Int)
+        (performers, tp) = text performer PerformerPack ip
+        (songwriters, ts) = text songwriter SongwriterPack is
+        (composers, tc) = text composer ComposerPack ic
+        (arrangers, ta) = text arranger ArrangerPack ia
+        (messages, tm) = text message MessagePack im
+        (catalogueB, _) = pack' DiscIdPack False il (prepareSingleText ASCII catalogue, 0 :: Int)
+        (genreB, _) = pack' GenrePack False ig (prepareGenre genreCode genreName, 0 :: Int)
+     -- (tocB, _) = pack' TocPack False it _
+     -- (toc2B, ) = pack' Toc2Pack False i2 _
+     -- (closedB, ) = pack' ClosedPack False ix $ prepareSingleText Iso8859_1 _
+        (codes, to) = pack' CodePack False io $ prepareText' ASCII code
+        lt = length titles
+        (ip, lp) = (     lt, length performers)
+        (is, ls) = (ip + lp, length songwriters)
+        (ic, lc) = (is + ls, length composers)
+        (ia, la) = (ic + lc, length arrangers)
+        (im, lm) = (ia + la, length messages)
+        (il, ll) = (im + lm, length catalogueB)
+        (ig, lg) = (il + ll, length genreB)
+        (io, lo) = (ig + lg, length codes)
+        allLengths = reverse . (3 :) . snd $ L.foldl'
+            (\(acc, as) a -> if acc + a > 0xFC then (0xFC, (0xFC - acc) : as) else (acc + a, a : as))
+            (0, [])
+            [lt, lp, ls, lc, la, lm, ll, lg, 0, 0, 0, 0, 0, 0, lo]
+        allPacks = take 0xFC
+             $ titles
+            <> performers
+            <> songwriters
+            <> composers
+            <> arrangers
+            <> messages
+            <> catalogueB
+            <> genreB
+            <> codes
+        encoding = guessEncoding . Y.catMaybes . concat $ infoList disc : map infoList tracks
+        wideChars = encoding == MS_JIS
+        infoList i = [f i | f <- [title, performer, songwriter, composer, arranger, message, code]]
+        startTrackId = fromIntegral $ fromEnum startTrack
+        endTrackId = foldr max 0 [tt, tp, ts, tc, ta, tm, to]
+        text f p i = F.B.first (pack p wideChars blockIndex $ fromIntegral i) $
+            prepareText' encoding f
+        prepareSingleText _ Nothing = []
+        prepareSingleText e (Just t) = (\t' -> [(0, t')]) $ encodeText e t
+        prepareText' e f = (t', foldr (max . fst) 0 t')
+          where t' = prepareText e startTrackId (f disc) (map f tracks)
+        pack' p w i = F.B.first . pack p w blockIndex $ fromIntegral i
+packCdTextBlock blockIndex catalogue DiscPregap genreCode genreName _ tracks =
+    packCdTextBlock blockIndex catalogue 1 genreCode genreName disc tracks'
+  where (disc, tracks') = case tracks of
+            [] -> (Info Nothing Nothing Nothing Nothing Nothing Nothing Nothing, [])
+            (t:ts) -> (t, ts)
+packCdTextBlock blockIndex catalogue DiscLeadout genreCode genreName disc _ =
+    packCdTextBlock blockIndex catalogue 1 genreCode genreName disc []
+
+-- | Generate the local block info.  Note that this does /not/ result in full
+-- payloads for the last two packs; @packInfo@ adds them automatically.
+generateBlockInfo :: BlockId -> Encoding -> TrackId -> TrackId -> [Int] -> [BS.ByteString]
+generateBlockInfo blockIndex encoding startTrack endTrack lengths =
+    pack InfoPack False blockIndex (fromIntegral $ sum lengths - 3) . packTuple $
+        [fromIntegral $ fromEnum encoding, startTrack, endTrack, 0x00] ++
+        take 16 (map fromIntegral lengths ++ repeat 0)
+  where packTuple bs = [(0, BS.pack bs)]
+
+
+-- | Use the minimal encoding based on the characters used by the strings.  If
+-- any character outside ISO 8859-1 ("Latin-1") is found, 'MS_JIS' is used as a
+-- fallback; this isn't strictly comprehensive, but it is a lot harder to test
+-- for (i.e. I'd have to write a function for it).
+guessEncoding :: [String] -> Encoding
+guessEncoding [] = Iso8859_1
+guessEncoding ts
+    | all (all C.isAscii) ts = ASCII
+    | all (all C.isLatin1) ts = Iso8859_1
+    | otherwise = MS_JIS
+
+
+-- | Collapse the track texts to their minimal size if allowed (if present for
+-- disc-level info, all tracks must be represented).
+prepareText :: Encoding -> TrackId -> Maybe String -> [Maybe String] -> [(TrackId, BS.ByteString)]
+prepareText e _ (Just d) [] = [(0, encodeText e d)]
+prepareText e i d'@(Just d) ta@(t:_)
+    | d' == t = case prepareTrackTexts e i' $ d' : trim ta of
+        [] -> []
+        ((_, bs):bss) -> (0, bs) : bss
+    | otherwise = (0, encodeText e d) : uncurry (prepareTrackTexts e) (trimTexts i ta)
+  where trim = L.dropWhileEnd Y.isNothing . dropWhile Y.isNothing
+        i' = i - 1 + fromIntegral (length $ takeWhile Y.isNothing ta)
+{- This block forces track info if it's present for the disc, as required by
+ - the libcdio docs.  It doesn't look like that's actually required in these
+ - references, but I don't trust them enough to take it out entirely.
+prepareText e i d'@(Just d) ta@(t:_)
+    | d' == t = case prepareTrackTexts e (i - 1) $ d' : ta of
+        [] -> []
+        ((_, bs):bss) -> (0, bs) : bss
+    | otherwise = (0, encodeText e d) : prepareTrackTexts e i ta
+-}
+prepareText e i Nothing ts = uncurry (prepareTrackTexts e) $ trimTexts i ts
+
+trimTexts :: TrackId -> [Maybe String] -> (TrackId, [Maybe String])
+trimTexts i' [] = (i', [])
+trimTexts i' (Nothing:ts') = trimTexts (i' + 1) ts'
+trimTexts i' ts' = (i', L.dropWhileEnd Y.isNothing ts')
+
+-- | Collapse the texts further by making use of the tab-replacement shortcut
+-- for repeated values.
+prepareTrackTexts :: Encoding -> TrackId -> [Maybe String] -> [(TrackId, BS.ByteString)]
+prepareTrackTexts _ _ [] = []
+prepareTrackTexts e i ts = encodeTrackTexts e i . reverse $ L.foldl' deduplicate [] ts
+  where deduplicate [] (Just s) = [s]
+        deduplicate ts' Nothing = "" : ts'
+        deduplicate ts' (Just s) =
+            let ss = takeWhile (== s) ts'
+            in  s : map (const "\t") ss ++ deduplicate' (drop (length ss) ts')
+        deduplicate' [] = []
+        deduplicate' (t':ts') = deduplicate ts' $ Just t'
+
+-- | Combine the genre code and description into a single bytestring.
+prepareGenre :: Maybe Genre -> Maybe String -> [(TrackId, BS.ByteString)]
+prepareGenre Nothing Nothing = []
+prepareGenre gc gt = [(0, encodeGenre gc <> encodeText ASCII (Y.fromMaybe "" gt))]
+
+
+-- | Conduct text to the proper encoder and append the proper terminator.
+encodeText :: Encoding -> String -> BS.ByteString
+encodeText MS_JIS "\t" = BS.pack [0x09,0x09,0x00,0x00]
+encodeText ASCII t = BS.map (.&. 0x7F) $ encodeText Iso8859_1 t
+encodeText Iso8859_1 t = BS.C.pack $ t ++ ['\NUL']
+encodeText MS_JIS t = T.encodeMsJISWith T.ignore (T.pack t) <> BS.C.pack ['\NUL', '\NUL']
+
+-- | Encode all members of a given textual category, pairing them with their
+-- track index or 0 if one applies to the disc as a whole.
+encodeTrackTexts :: Encoding -> TrackId -> [String] -> [(TrackId, BS.ByteString)]
+encodeTrackTexts e i ts = zip [i ..] $ map (encodeText e) ts
+
+-- | Store the genre code in a two-byte string.
+encodeGenre :: Maybe Genre -> BS.ByteString
+encodeGenre g = BS.pack [gh, gc]
+  where gc = maybe 0x00 (fromIntegral . fromEnum) g
+        -- Futureproofing decades-old technology
+        gh = if gc <= 0xFF then 0x00 else B.shiftR gc 8
+
+
+-- | Prevent index overflow for any single pack type.
+pack :: Pack -> Bool -> BlockId -> BlockSize -> [(TrackId, BS.ByteString)] -> [BS.ByteString]
+pack p w b i bss = take 0xFF $ pack_ p w b i bss
+
+-- | Conduct binary data and starting track to the proper packers.
+pack_ :: Pack -> Bool -> BlockId -> BlockSize -> [(TrackId, BS.ByteString)] -> [BS.ByteString]
+pack_ TitlePack = packText 0x80
+pack_ PerformerPack = packText 0x81
+pack_ SongwriterPack = packText 0x82
+pack_ ComposerPack = packText 0x83
+pack_ ArrangerPack = packText 0x84
+pack_ MessagePack = packText 0x85
+pack_ DiscIdPack = packText 0x86
+pack_ GenrePack = packGenre
+pack_ ClosedPack = packText 0x8D
+pack_ TocPack = const4 []
+pack_ Toc2Pack = const4 []
+pack_ CodePack = packText 0x8E
+pack_ InfoPack = packBlockInfo
+
+const4 :: a -> b -> c -> d -> e -> a
+const4 a _ _ _ _ = a
+
+packText
+    :: PackType
+    -> Bool
+    -> BlockId
+    -> BlockSize
+    -> [(TrackId, BS.ByteString)] -> [BS.ByteString]
+packText p w b i bss = zipWith (curry $ addHeader p w b) [i ..] .
+    reverse $ L.foldl' splitText [] bss
+
+packGenre :: Bool -> BlockId -> BlockSize -> [(TrackId, BS.ByteString)] -> [BS.ByteString]
+packGenre _ _ _ [] = []
+packGenre w b i ((_, bs):_) = zipWith (curry $ addHeader 0x87 w b) [i ..] $ splitGenre bs
+
+-- | Create the skeleton block info packs, leaving out counts and languages.
+packBlockInfo :: Bool -> BlockId -> BlockSize -> [(TrackId, BS.ByteString)] -> [BS.ByteString]
+packBlockInfo w b i [] =
+    [ addHeader 0x8F w b (i + p, (p, 0, BS.empty))
+    | p <- [0 .. 2]
+    ]
+packBlockInfo w b i ((_, bs):_) =
+    [ addHeader 0x8F w b (i, (0, 0, p1))
+    , addHeader 0x8F w b (i + 1, (1, 0, p2))
+    , addHeader 0x8F w b (i + 2, (2, 0, BS.empty))
+    ]
+  where (p1, p2) = BS.splitAt 12 bs
+
+-- | Generate the four-byte identifying and metadata-carrying header.
+-- 
+-- NOTE: While the libcdio documentation on the CDTEXT format says that byte 3
+-- (@l'@) is 15 if the text starts at any point before the previous pack,
+-- that's not the case in any of my (admittedly limited and unverified)
+-- reference blobs: it's capped at 15, yes, but if one pack has two characters,
+-- the next has the full twelve, and the text still continues into a third,
+-- that third will have a third byte of 14.
+addHeader
+    :: PackType
+        -- ^ Pack type
+    -> Bool
+        -- ^ Two-byte characters?
+    -> BlockId
+        -- ^ Language index
+    -> (BlockSize, (TrackId, Word, BS.ByteString))
+                        -- ^ Starting pack index, track number, characters in previous block, and payload
+    -> BS.ByteString
+addHeader p w b (i, (t, l, bs)) = BS.pack [p, t, i, f] <> bs
+  where l' = if l > 15 then 0x0F else 0x0F .&. fromIntegral l
+        b' = 0x70 .&. B.shiftL (fromIntegral b) 4
+        w' = if w then 0x80 else 0x00
+        f = w' .|. b' .|. l'
+
+-- | Takes tuples of (track index, track data) and adds them (initial track,
+-- initial length in previous packs, packed data), where the packed data is
+-- /no more than/ 12 bytes long.  Note that the final list will have to be
+-- 'reverse'd.
+splitText :: [(TrackId, Word, BS.ByteString)] -> (TrackId, BS.ByteString) -> [(TrackId, Word, BS.ByteString)]
+splitText [] bst@(t, _) = splitText [(t, 0, BS.empty)] bst
+splitText csa@((u, l, cs):css) (t, bs)
+    | cl == 12 =
+        [ (t, l', bs')
+        | (l', bs') <- reverse . zip [0, 12 ..] $ splitAtEvery 12 bs
+        ] ++ csa
+    -- Will have incorrect t, l' if @BS.length cs > 12@, but as that shouldn't
+    -- happen anyway, it's not an issue.
+    | otherwise =
+        let (cs':bss) = splitAtEvery 12 $ cs <> bs
+        in  [ (t, l', bs')
+            | (l', bs') <- reverse $ zip [(12 - cl), (24 - cl) ..] bss
+            ] ++ (u, l, cs') : css
+  where cl = fromIntegral $ BS.length cs
+
+-- | Takes the genre string prefixed by a single, two-byte genre code
+-- identifier, splits the string, and prepends the code to every pack.
+splitGenre :: BS.ByteString -> [(TrackId, Word, BS.ByteString)]
+splitGenre bs =
+    [ (0, l', gc <> bs')
+    | (l', bs') <- zip [0, 10 ..] . splitAtEvery 10 $ BS.drop 2 bs
+    ]
+  where gc = BS.take 2 bs
+
+-- | Extend the builtin 'BS.splitAt' to return an entire list of substrings.
+splitAtEvery :: Int -> BS.ByteString -> [BS.ByteString]
+splitAtEvery i bs
+    | i <= 0 = []
+    | i >= BS.length bs = [bs]
+    | otherwise = recurse $ BS.splitAt i bs
+  where recurse (h, t) = h : splitAtEvery i t
+
+
+-- | Now that we have the languages and sizes of all blocks, update the info
+-- packs to include them.  Note that this requires that the info packs are
+-- located at the end of the block.
+joinBlockInfo :: [Maybe Language] -> [BlockSize] -> [BS.ByteString] -> [BS.ByteString]
+joinBlockInfo _ _ [] = []
+joinBlockInfo _ _ [b] = [b]
+joinBlockInfo ls ss bss = h ++ [p2, p3]
+  where (h, t) = splitAt (length bss - 2) bss
+        ls' = take 8 $ map (maybe 0 $ fromIntegral . fromEnum) ls ++ repeat 0
+        ss' = take 8 $ ss ++ repeat 0
+        p2 = head t <> BS.pack (take 4 ss')
+        p3 = head (tail t) <> BS.pack (drop 4 ss' ++ ls')
+
+
+-- | Generate a checksum over the first 16 (including header) bytes of a data
+-- pack, zero-padding /or truncating/ as necessary.
+checksum :: BS.ByteString -> BS.ByteString
+checksum bs = checksum' $ case compare 16 $ BS.length bs of
+    GT -> BS.take 16 $ bs <> BS.replicate 16 0
+    EQ -> bs
+    LT -> BS.take 16 bs
+
+-- | Actually run the checksum function on all the bytes of the input.  Note
+-- that this doesn't verify that the length is actually the proper 16.
+checksum' :: BS.ByteString -> BS.ByteString
+checksum' bs = bs <> (BS.pack . split . finalize . BS.foldl' checksumBytes h' $ t <> BS.singleton 0)
+  where split i = map fromIntegral [B.shiftR i 8, i]
+        finalize i = B.xor i 0xFFFF
+        (h, t) = Y.fromMaybe (0, BS.empty) $ BS.uncons bs
+        h' = B.shiftL (fromIntegral h) 8
+
+checksumBytes :: W.Word16 -> W.Word8 -> W.Word16
+checksumBytes acc a = checksumBits 8 . B.xor acc $ fromIntegral a
+
+checksumBits :: Word -> W.Word16 -> W.Word16
+checksumBits 0 i = i
+checksumBits c i = checksumBits (c - 1) i'
+  where i'  | B.testBit i 15 = B.xor 0x1021 $ B.shiftL i 1
+            | otherwise = B.shiftL i 1
diff --git a/src/Foreign/Libcdio/CdTypes.hs b/src/Foreign/Libcdio/CdTypes.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Libcdio/CdTypes.hs
@@ -0,0 +1,193 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+{-|
+Description:    Objects used to describe the CD and filesystem format.
+
+Copyright:      (c) 2019-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+Like any drive, discs may store their data according to many different
+filesystem structures.  These are abstracted to a degree in libcdio, but as
+each track may store its data differently, and at the very least 'Audio' is
+handled differently than any of the file-oriented layouts, it is still helpful
+to know the underlying structure.
+
+
+= @cd_types.h@
+
+== Defines
+* CDIO_FSTYPE                       (removed; cdio_fs_anal_t represented differently in Haskell)
+* CDIO_FS_UNKNOWN                   (removed; handled via 'Nothing')
+
+== Types
+* @cdio_fs_t@                       -> 'Foreign.Libcdio.CdTypes.Filesystem'
+
+    - @CDIO_FS_INTERACTIVE@         -> 'Foreign.Libcdio.CdTypes.CdI'
+    - @CDIO_FS_ISO_HFS@             -> 'Foreign.Libcdio.CdTypes.Hfs' with a 'Just' 'Foreign.Libcdio.CdTypes.IsoAnalysis'
+    - @CDIO_FS_ISO_9660_INTERACTIVE@ -> 'Foreign.Libcdio.CdTypes.CdI' with a 'Just' 'Foreign.Libcdio.CdTypes.IsoAnalysis'
+    - @CDIO_FS_ISO_UDF@             -> 'Foreign.Libcdio.CdTypes.Udf' with a 'Just' 'Foreign.Libcdio.CdTypes.IsoAnalysis'
+    - @CDIO_FS_ISO_XISO@            -> 'Foreign.Libcdio.CdTypes.XboxIso'
+    - @CDIO_FS_ISO_UDFX@            -> 'Foreign.Libcdio.CdTypes.XboxUdf'
+
+* @cdio_fs_cap_t@                   -> 'Foreign.Libcdio.CdTypes.FilesystemClass'
+
+    Note that some values are not included in the Haskell type, as the indexing
+    implementation is stricter than the equivalent bit operations in C.
+
+    - @CDIO_FS_MASK@                (removed; cdio_fs_anal_t represented differently in Haskell)
+    - @CDIO_FS_ANAL_VCD_ANY@        -> 'Foreign.Libcdio.CdTypes.fsAnyVcd'
+    - @CDIO_FS_MATCH_ALL@           -> 'Foreign.Libcdio.CdTypes.fsAny'
+    - @CDIO_FS_ANAL_CDTV@           -> 'Foreign.Libcdio.CdTypes.CommodoreCdtv'
+    - @CDIO_FS_ANAL_SVCD@           -> 'Foreign.Libcdio.CdTypes.SuperVideoCd'
+    - @CDIO_FS_ANAL_CVD@            -> 'Foreign.Libcdio.CdTypes.ChoijiVideoCd'
+    - @CDIO_FS_ANAL_XISO@           -> 'Foreign.Libcdio.CdTypes.XboxIsoClass'
+
+* @cdio_iso_analysis_t@             -> 'Foreign.Libcdio.CdTypes.IsoAnalysis'
+
+    - @joliet_level@                -> 'Foreign.Libcdio.CdTypes.jolietLevel'
+    - @iso_label@                   -> 'Foreign.Libcdio.CdTypes.label'
+    - @isofs_size@                  -> 'Foreign.Libcdio.CdTypes.fsSize'
+    - @UDFVerMajor@                 -> 'fst' 'Foreign.Libcdio.CdTypes.udfVersion'
+    - @UDFVerMinor@                 -> 'snd' 'Foreign.Libcdio.CdTypes.udfVersion'
+
+== Symbols
+* @cdio_guess_cd_type@              -> 'Foreign.Libcdio.CdTypes.trackType'
+
+
+= "Sound.Libcdio.Read.Filesystem"
+
+* 'trackType'                       -> 'Sound.Libcdio.Read.Filesystem.filesystemType'
+-}
+module Foreign.Libcdio.CdTypes
+    ( -- * Types
+      Filesystem ( .. )
+    , FilesystemClass ( .. )
+    , FilesystemClasses
+    , fsAny, fsAnyVcd
+    , IsoAnalysis ( .. )
+      -- * Access
+    , trackType
+    ) where
+
+
+import qualified Data.Maybe as Y
+import qualified Data.Word as W
+
+import qualified Data.Array.BitArray as A
+
+import qualified Foreign.C.String as C
+import qualified Foreign.C.Types as C
+import qualified Foreign.Ptr as C
+
+import qualified Foreign.Marshal.Alloc as M
+import qualified Foreign.Storable as S
+
+import Foreign.Libcdio.Marshal
+import Foreign.Libcdio.Track
+import Foreign.Libcdio.Types.Enums
+import Foreign.Libcdio.Types.Offsets
+import Foreign.Libcdio.Types.Internal
+
+
+-- | Types of filesystem which may be read from a disc.
+data Filesystem
+    = Audio
+    | HighSierra
+    | Iso9660
+    | CdI
+    | Cd3do
+    | Ext2
+    | Hfs
+    | Ufs
+    | Udf
+    | XboxIso
+    | XboxUdf
+  deriving ( Eq, Show, Read, Ord, Enum, Bounded )
+
+
+-- | A collection of disc/filesystem descriptions.
+type FilesystemClasses = A.BitArray FilesystemClass
+
+-- | Any sort of Video CD.
+fsAnyVcd :: FilesystemClasses
+fsAnyVcd = genBitArray
+    [ VideoCd
+    , SuperVideoCd
+    , ChoijiVideoCd
+    ]
+
+-- | The set of every 'FilesystemClass'.
+fsAny :: FilesystemClasses
+fsAny = genBitArray [minBound .. maxBound]
+
+
+-- | A collection of data describing a disc using the ISO 9660 standard.
+data IsoAnalysis = IsoAnalysis
+    { jolietLevel :: Maybe Word
+    , label       :: String
+    , fsSize      :: Word
+    , udfVersion  :: Maybe (W.Word8, W.Word8)
+    }
+  deriving ( Eq, Show, Read )
+instance S.Storable IsoAnalysis where
+    sizeOf _    = iaSizeOf
+    alignment _ = iaAlign
+    peek c = do
+        j <- S.peekByteOff c iaJolietLevel :: IO C.CUInt
+        l <- C.peekCString $ C.plusPtr c iaLabel
+        s <- S.peekByteOff c iaIsoSize :: IO C.CUInt
+        a <- S.peekByteOff c iaUDFMajor
+        i <- S.peekByteOff c iaUDFMinor
+        return $ IsoAnalysis
+            { jolietLevel = if j == 0 then Nothing else Just $ fromIntegral j
+            , label = l
+            , fsSize = fromIntegral s
+            , udfVersion = if a == 0 then Nothing else Just (a, i)
+            }
+    poke c hs = do
+        let (a, i) = Y.fromMaybe (0, 0) $ udfVersion hs
+        S.pokeByteOff c iaJolietLevel . maybe (0 :: C.CUInt) fromIntegral $ jolietLevel hs
+        pokeCString (label hs) 33 $ C.plusPtr c iaLabel
+        S.pokeByteOff c iaIsoSize (fromIntegral $ fsSize hs :: C.CUInt)
+        S.pokeByteOff c iaUDFMajor a
+        S.pokeByteOff c iaUDFMinor i
+
+
+-- | Determine what type of file system is stored in the given track of a disc.
+trackType :: Cdio -> Track -> IO (Maybe Filesystem, FilesystemClasses, Maybe IsoAnalysis)
+trackType c t = do
+    l' <- trackLsn c t
+    (fs, iso') <- case l' of
+        Just l -> withCdio' defaultCdType $ \c' -> M.alloca $ \i' -> do
+            e' <- cdType_ c' l (withTrack t) i'
+            iso <- S.peek i'
+            return (modEnumFlags e', iso)
+        Nothing -> return defaultCdType
+    let fc = snd fs
+        iso = Just iso' { udfVersion = Nothing }
+        isoUdf = Just iso'
+    return $ case fst fs of
+        Nothing -> (Nothing, fc, isoUdf)
+        Just Fs3do -> (Just Cd3do, fc, iso)
+        Just FsAudio -> (Just Audio, fc, Nothing)
+        Just FsExt2 -> (Just Ext2, fc, iso)
+        Just FsHfs -> (Just Hfs, fc, Nothing)
+        Just FsIsoHfs -> (Just Hfs, fc, iso)
+        Just FsHighSierra -> (Just HighSierra, fc, iso)
+        Just FsInteractive -> (Just CdI, fc, Nothing)
+        Just FsIso9660Interactive -> (Just CdI, fc, iso)
+        Just FsIso9660 -> (Just Iso9660, fc, iso)
+        Just FsUdf -> (Just Udf, fc, Nothing)
+        Just FsIsoUdf -> (Just Udf, fc, isoUdf)
+        Just FsUdfx -> (Just Udf, fc, isoUdf)
+        Just FsUfs -> (Just Ufs, fc, iso)
+        Just FsXiso -> (Just XboxIso, fc, iso)
+  where defaultCdType = ((Nothing, genBitArray []), IsoAnalysis Nothing "" 0 Nothing)
+        withCdio' b = fmap (Y.fromMaybe b) . withCdio c
+
+foreign import ccall safe "cdio/compat/cd_types.h cdio_guess_cd_type"
+  cdType_ :: C.Ptr Cdio -> Lsn -> CTrack -> C.Ptr IsoAnalysis -> IO C.CInt
diff --git a/src/Foreign/Libcdio/Device.hs b/src/Foreign/Libcdio/Device.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Libcdio/Device.hs
@@ -0,0 +1,1380 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+{-|
+Description:    Various device-management functions, including session initialization.
+
+Copyright:      (c) 2018-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+The entire library architecture revolves around the concept of a device—not the
+disc, but the drive containing it.  A function to read a segment of data is not
+just a lookup from memory, but an instruction to the device to move the read
+arm into position and begin interpreting the pits and ridges.  With that
+understanding, it makes sense that this module provides not just the means to
+determine what any particular drive is capable of, but also the only means to
+obtain the 'Cdio' object the everything else revolves around.
+
+
+= @device.h@
+
+== Types
+* @cdio_drive_cap_misc_t@           -> 'DriveCapabilityMisc'
+
+    - @CDIO_DRIVE_CAP_ERROR@        (removed; handled via 'Nothing')
+    - @CDIO_DRIVE_CAP_UNKNOWN@      (removed; handled via 'Nothing')
+
+* @cdio_drive_cap_read_t@           -> 'DriveCapabilityRead'
+
+    - @CDIO_DRIVE_CAP_READ_AUDIO@   -> 'ReadAnalogAudio'
+    - @CDIO_DRIVE_CAP_READ_CD_DA@   -> 'ReadDigitalAudio'
+    - @CDIO_DRIVE_CAP_READ_CD_R@    -> 'ReadCdRecordable'
+    - @CDIO_DRIVE_CAP_READ_CD_RW@   -> 'ReadCdReWritable'
+    - @CDIO_DRIVE_CAP_READ_DVD_R@   -> 'ReadDvdRecordable'
+    - @CDIO_DRIVE_CAP_READ_DVD_PR@  -> 'ReadDvdPlusRecordable'
+    - @CDIO_DRIVE_CAP_READ_DVD_RW@   -> 'ReadDvdReWritable'
+    - @CDIO_DRIVE_CAP_READ_DVD_PRW@  -> 'ReadDvdPlusReWritable'
+    - @CDIO_DRIVE_CAP_READ_C2_ERRS@ -> 'ReadC2ErrorCorrection'
+
+* @cdio_drive_cap_write_t@          -> 'DriveCapabilityWrite'
+
+    Note that some values are not included in the Haskell type, as the indexing
+    implementation is stricter than the equivalent bit operations in C.
+
+    - @CDIO_DRIVE_CAP_WRITE_CD_R@    -> 'WriteCdRecordable'
+    - @CDIO_DRIVE_CAP_WRITE_CD_RW@   -> 'WriteCdReWritable'
+    - @CDIO_DRIVE_CAP_WRITE_DVD_R@   -> 'WriteDvdRecordable'
+    - @CDIO_DRIVE_CAP_WRITE_DVD_PR@  -> 'WriteDvdPlusRecordable'
+    - @CDIO_DRIVE_CAP_WRITE_DVD_RW@   -> 'WriteDvdReWritable'
+    - @CDIO_DRIVE_CAP_WRITE_DVD_PRW@  -> 'WriteDvdPlusReWritable'
+    - @CDIO_DRIVE_CAP_WRITE_CD@     -> 'capsWriteCd'
+    - @CDIO_DRIVE_CAP_WRITE_DVD@    -> 'capsWriteDvd'
+    - @CDIO_DRIVE_CAP_WRITE@        -> 'capsWrite'
+
+* @cdio_drive_misc_cap_t@           -> 'DriveMiscCaps'
+* @cdio_drive_read_cap_t@           -> 'DriveReadCaps'
+* @cdio_drive_write_cap_t@          -> 'DriveWriteCaps'
+* @cdio_hwinfo_t@                   -> 'HardwareInfo'
+
+    - @psz_vendor@                  -> 'vendor'
+    - @psz_model@                   -> 'model'
+    - @psz_revision@                -> 'revision'
+
+* @cdio_mmc_hw_len_t@               (type removed; values are structural constants rather than an actual enum)
+
+    - @CDIO_MMC_HW_VENDOR_LEN@      -> 'vendorLength'
+    - @CDIO_MMC_HW_MODEL_LEN@       -> 'modelLength'
+    - @CDIO_MMC_HW_REVISION_LEN@    -> 'revisionLength'
+
+* @cdio_src_category_mask_t@        (removed; never used in the public interface)
+* @driver_id_t@                     -> 'DriverId'
+* @driver_return_code_t@            -> 'DriverReturnCode'
+
+== Symbols
+* @cdio_close_tray@                 -> 'closeTray'
+* @cdio_destroy@                    (removed; handled via garbage collector)
+* @cdio_device_drivers@             -> 'deviceDrivers'
+* @cdio_driver_describe@            -> 'driverDescribe'
+* @cdio_driver_errmsg@              -> 'driverErrmsg'
+* @cdio_drivers@                    -> 'drivers'
+* @cdio_eject_media@                -> 'ejectMedia'
+* @cdio_eject_media_drive@          -> 'ejectDrive'
+* @cdio_free_device_list@           (removed; handled via garbage collector)
+* @cdio_get_arg@                    -> 'getArg' and 'getAccessMode'
+* @cdio_get_default_device@         -> 'defaultDevice' (@CdIo_t*@ argument dropped as no non-redundant path to get one exists)
+* @cdio_get_default_device_*@       -> @defaultDevice*@ (eg. 'defaultDeviceLinux')
+* @cdio_get_devices@                -> 'devices'
+* @cdio_get_devices_*@              -> @devices*@ (eg. 'devicesLinux')
+* @cdio_get_devices_with_cap@       -> 'devicesWithFilesystem'
+* @cdio_get_devices_with_cap_ret@   -> 'devicesWithFilesystemRet'
+* @cdio_get_drive_cap@              -> 'driveCap'
+* @cdio_get_drive_cap_dev@          -> 'driveCapDevice'
+* @cdio_get_driver_id@              -> 'driverId'
+* @cdio_get_driver_name@            -> 'driverName'
+* @cdio_get_hwinfo@                 -> 'hwinfo'
+* @cdio_get_last_session@           -> 'lastSession'
+* @cdio_get_media_changed@          -> 'isMediaChanged'
+* @cdio_have_atapi@                 -> 'haveAtapi'
+* @cdio_have_driver@                -> 'haveDriver'
+* @cdio_init@                       (removed; internal function without much external occasion for use)
+* @cdio_is_binfile@                 -> 'cueFromBin'
+* @cdio_is_cuefile@                 -> 'binFromCue'
+* @cdio_is_device@                  -> 'isDevice'
+* @cdio_is_nrg@                     -> 'isNrg'
+* @cdio_is_tocfile@                 -> 'isToc'
+* @cdio_open@                       -> 'cdioOpen'
+* @cdio_open_*@                     -> @cdioOpen*@ (eg. 'cdioOpenLinux')
+* @cdio_open_am@                    -> 'cdioOpenAm'
+* @cdio_open_am_*@                  -> @cdioOpenAm*@ (eg. 'cdioOpenAmLinux')
+* @cdio_os_driver@                  -> 'osDriver'
+* @cdio_set_arg@                    (removed; primarily intended for internal use, and is more limited than would be expected)
+* @cdio_set_blocksize@              -> 'setBlocksize'
+* @cdio_set_speed@                  -> 'setSpeed'
+
+
+= "Sound.Libcdio.Device"
+
+* 'Cdio'                            -> @"Sound.Libcdio".'Sound.Libcdio.Cdio'@ (note, however, that the latter is a more abstracted 'Monad')
+
+* 'binFromCue'                      -> 'Sound.Libcdio.Device.isCue'
+* 'cdioOpen'                        -> @"Sound.Libcdio".'Sound.Libcdio.open'@ and 'Sound.Libcdio.openDefault'
+* 'cdioOpenAm'                      -> @"Sound.Libcdio".'Sound.Libcdio.openMode'@ and 'Sound.Libcdio.openModeDefault'
+* @cdioOpen*@                       (removed; @"Sound.Libcdio".'Sound.Libcdio.open'@ handles the auto-detection)
+* 'closeTray'                       -> 'Sound.Libcdio.Device.closeDeviceTray' and 'Sound.Libcdio.Device.closeDeviceTray''
+* 'cueFromBin'                      (removed; this and 'Foreign.binFromCue' just replace the file extension after validation, they don't go searching)
+* @defaultDevice*@                  (removed; driver type isn't a public part of device opening)
+* 'deviceDrivers'                   -> @'not' 'Sound.Libcdio.Device.isImageDriver'@
+* 'devicesRet'                      (removed; @"Sound.Libcdio".'Sound.Libcdio.open'@ doesn't require a specific 'Foreign.DriverId' to be passed)
+* 'devicesWithFilesystem'           (removed; can't think of a use case for searching for discs of a specific data layout)
+* 'devicesWithFilesystemRet'        (removed; can't think of a use case for searching for discs of a specific data layout)
+* @devices*@                        (removed; 'Sound.Libcdio.Device.devices' delegates via the 'Foreign.DriverId' parameter)
+* 'driveCap'                        -> 'Sound.Libcdio.Device.capabilities'
+* 'driveCapDevice'                  -> 'Sound.Libcdio.Device.deviceCapabilities'
+* 'driverId'                        -> 'Sound.Libcdio.Device.driver'
+* 'ejectDrive'                      -> 'Sound.Libcdio.Device.ejectDevice'
+* 'ejectMedia'                      (removed; argument to e.g. @"Sound.Libcdio".'Sound.Libcdio.open'@)
+* 'getArg'                          -> @"Sound.Libcdio".'Sound.Libcdio.getArg'@
+* 'getAccessMode'                   -> @"Sound.Libcdio".'Sound.Libcdio.getAccessMode'@
+* 'haveDriver'                      (removed; use @`'elem'` 'Sound.Libcdio.Device.drivers'@)
+* 'hwinfo'                          -> 'Sound.Libcdio.Device.hardware'
+* 'lastSession'                     -> @"Sound.Libcdio.Read.Data".'Sound.Libcdio.Read.Data.lastSessionOffset'@
+* 'modelLength'                     (removed; unnecessary low-level detail)
+* 'revisionLength'                  (removed; unnecessary low-level detail)
+* 'vendorLength'                    (removed; unnecessary low-level detail)
+-}
+module Foreign.Libcdio.Device
+    ( -- * Types
+      Cdio
+    , HardwareInfo ( .. )
+    , vendorLength
+    , modelLength
+    , revisionLength
+    , emptyHardwareInfo
+    , DriverId ( .. )
+    , DriverReturnCode ( .. )
+    , SessionArg ( .. )
+    , AccessMode ( .. )
+      -- ** Capabilities
+    , DriveCapabilityRead ( .. )
+    , DriveReadCaps
+    , DriveCapabilityWrite ( .. )
+    , DriveWriteCaps
+    , capsWriteCd
+    , capsWriteDvd
+    , capsWrite
+    , DriveCapabilityMisc ( .. )
+    , DriveMiscCaps
+    , DriveCaps
+      -- * Drivers
+    , drivers
+    , deviceDrivers
+    , osDriver
+    , driverName
+    , driverId
+    , driverDescribe
+    , driverErrmsg
+    , haveDriver
+      -- * Devices
+    , devices
+    , devicesRet
+    , devicesWithFilesystem
+    , devicesWithFilesystemRet
+    , defaultDevice
+    , defaultDeviceDriver
+    , hwinfo
+    , driveCap
+    , driveCapDevice
+    , haveAtapi
+    , ejectMedia
+    , ejectDrive
+    , closeTray
+      -- * Session
+    , getArg
+    , getAccessMode
+    , isMediaChanged
+    , setBlocksize
+    , setSpeed
+    , lastSession
+      -- * Device paths
+    , cdioOpen
+    , cdioOpenAm
+      -- ** Hardware
+    , isDevice
+    , cdioOpenCd
+    , cdioOpenAmCd
+      -- ** Images
+    , cueFromBin
+    , binFromCue
+    , isNrg
+    , isToc
+    {-
+      -- *** BIN/CUE
+    , cdioOpenBinCue
+    , cdioOpenCue
+    , cdioOpenAmBinCue
+    , defaultDeviceBinCue
+    , devicesBinCue
+      -- *** cdrdao
+    , cdioOpenCdrDao
+    , cdioOpenAmCdrDao
+    , defaultDeviceCdrDao
+    , devicesCdrDao
+      -- *** Nero
+    , cdioOpenNero
+    , cdioOpenAmNero
+    , defaultDeviceNero
+    , devicesNero
+      -- ** Hardware
+      -- *** BSDI
+    , cdioOpenBsdi
+    , cdioOpenAmBsdi
+    , defaultDeviceBsdi
+    , devicesBsdi
+      -- *** FreeBSD
+    , cdioOpenFreeBsd
+    , cdioOpenAmFreeBsd
+    , defaultDeviceFreeBsd
+    , devicesFreeBsd
+      -- *** Linux
+    , cdioOpenLinux
+    , cdioOpenAmLinux
+    , defaultDeviceLinux
+    , devicesLinux
+      -- *** OS/2
+    , cdioOpenOs2
+    , cdioOpenAmOs2
+    , defaultDeviceOs2
+    , devicesOs2
+      -- *** Solaris
+    , cdioOpenSolaris
+    , cdioOpenAmSolaris
+    , defaultDeviceSolaris
+    , devicesSolaris
+      -- *** Windows
+    , cdioOpenWin32
+    , cdioOpenAmWin32
+    , defaultDeviceWin32
+    , devicesWin32
+    -}
+    ) where
+
+
+import qualified Control.Monad as N
+
+import qualified Data.Array.BitArray as A
+import qualified Data.Maybe as Y
+
+import qualified Foreign.C.String as C
+import qualified Foreign.C.Types as C
+import qualified Foreign.Ptr as C
+
+import qualified Foreign.Marshal.Alloc as M
+import qualified Foreign.Marshal.Array as M
+import qualified Foreign.Marshal.Utils as M
+import qualified Foreign.Storable as S
+
+import qualified System.IO.Unsafe as IO.Unsafe
+
+import Data.Ix ( Ix )
+import Data.Bits ( (.&.) )
+
+import Foreign.Libcdio.CdTypes
+import Foreign.Libcdio.Marshal
+import Foreign.Libcdio.Types.Enums
+import Foreign.Libcdio.Types.Internal
+import Foreign.Libcdio.Types.Offsets
+
+import Sound.Libcdio.Common
+
+
+toDriverReturnCode :: Maybe CDriverReturnCode -> DriverReturnCode
+toDriverReturnCode = maybe Uninitialized $ toEnum . fromIntegral
+
+
+-- | The collection of features for reading discs a device provides.
+type DriveReadCaps = A.BitArray DriveCapabilityRead
+-- | The collection of features for writing discs a device provides.
+type DriveWriteCaps = A.BitArray DriveCapabilityWrite
+-- | The collection of hardware features a device was built with.
+type DriveMiscCaps = A.BitArray DriveCapabilityMisc
+
+-- | The three types are usually passed around together, so we can simplify the
+-- type signatures using them.
+type DriveCaps = (DriveReadCaps, DriveWriteCaps, DriveMiscCaps)
+
+
+-- | Capabilites indicating a device has some sort of CD-writing ability.
+capsWriteCd :: DriveWriteCaps
+capsWriteCd = genBitArray
+    [ WriteCdRecordable
+    , WriteCdReWritable
+    ]
+
+-- | Capabilites indicating a device has some sort of DVD-writing ability.
+capsWriteDvd :: DriveWriteCaps
+capsWriteDvd = genBitArray
+    [ WriteDvdRecordable
+    , WriteDvdPlusRecordable
+    , WriteDvdRam
+    , WriteDvdReWritable
+    , WriteDvdPlusReWritable
+    ]
+
+-- | Capabilites indicating a device has some sort of disc-writing ability.
+capsWrite :: DriveWriteCaps
+capsWrite = A.zipWith (||) capsWriteCd capsWriteDvd
+
+
+-- | Length of the drive vendor name in returned in a 'HardwareInfo' query.
+vendorLength :: Word
+vendorLength = fromIntegral vendorLength'
+
+foreign import ccall safe "cdio/compat/device.h vendor_len"
+  vendorLength' :: C.CUInt
+
+
+-- | Length of the drive model name in returned in a 'HardwareInfo' query.
+modelLength :: Word
+modelLength = fromIntegral modelLength'
+
+foreign import ccall safe "cdio/compat/device.h model_len"
+  modelLength' :: C.CUInt
+
+-- | Length of the drive revision number in returned in a 'HardwareInfo' query.
+revisionLength :: Word
+revisionLength = fromIntegral revisionLength'
+
+foreign import ccall safe "cdio/compat/device.h revision_len"
+  revisionLength' :: C.CUInt
+
+
+-- | Information defining the make and model of a (typically physical) device.
+data HardwareInfo = HardwareInfo
+    { vendor    :: String
+        -- ^ The company who designed and/or built the drive.
+    , model     :: String
+        -- ^ The name of the specific drive design.
+    , revision  :: String
+        -- ^ The version number for hardware/firmware following a series.
+    }
+  deriving ( Eq, Show, Read )
+instance S.Storable HardwareInfo where
+    sizeOf _    = hiSizeOf
+    alignment _ = hiAlign
+    peek c = do
+        v <- decode vendorLength hiVendor
+        m <- decode modelLength hiModel
+        r <- decode revisionLength hiRevision
+        return $ HardwareInfo v m r
+      where decode l o = C.peekCStringLen (C.plusPtr c o, fromIntegral l)
+    poke c hs = do
+        pokeCString (vendor hs) (fromIntegral vendorLength + 1) (C.plusPtr c hiVendor)
+        pokeCString (model hs) (fromIntegral modelLength + 1) (C.plusPtr c hiModel)
+        pokeCString (revision hs) (fromIntegral revisionLength + 1) (C.plusPtr c hiRevision)
+
+-- | A 'HardwareInfo' object with values suitable as defaults.
+emptyHardwareInfo :: HardwareInfo
+emptyHardwareInfo = HardwareInfo
+    { vendor = replicate (fromIntegral vendorLength) '\NUL'
+    , model = replicate (fromIntegral modelLength) '\NUL'
+    , revision = replicate (fromIntegral revisionLength) '\NUL'
+    }
+
+
+{- Barely even used internally.
+-- | Which type(s) of device describe a particular drive.
+type SrcCategories = A.BitArray SrcCategoryMask
+-}
+
+
+-- | Unmarshall a C-style list of drivers.
+peekDriverIdArray :: (Integral a, S.Storable a) => C.Ptr a -> IO [DriverId]
+peekDriverIdArray is' = do
+    is <- M.peekArray0 (fromIntegral $ fromEnum DriverUnknown) is'
+    return $ map (toEnum . fromIntegral) is
+
+
+-- | All supported drivers, listed in order of preference.
+drivers :: [DriverId]
+drivers = filter haveDriver <$> IO.Unsafe.unsafePerformIO $ peekDriverIdArray drivers'
+
+foreign import ccall safe "cdio/compat/device.h get_drivers"
+  drivers' :: C.Ptr CDriverId
+
+-- | All supported drivers for physical devices, listed in order of preference.
+deviceDrivers :: [DriverId]
+deviceDrivers = IO.Unsafe.unsafePerformIO $ peekDriverIdArray deviceDrivers'
+
+foreign import ccall safe "cdio/compat/device.h get_device_drivers"
+  deviceDrivers' :: C.Ptr CDriverId
+
+-- | The particular driver for the current operating system, or 'DriverUnknown'
+-- if no device driver exists.
+osDriver :: DriverId
+osDriver = toEnum $ fromIntegral osDriver'
+
+foreign import ccall safe "cdio/compat/device.h get_os_driver"
+  osDriver' :: CDriverId
+
+
+-- | Close a CD drive, if the device supports doing so.
+closeTray
+    :: Maybe FilePath
+        -- ^ The name of the drive to use, or 'Nothing' to use 'defaultDeviceDriver'.
+    -> DriverId
+    -> IO (DriverReturnCode, DriverId)
+        -- ^ Any errors, along with the actual driver used if passed
+        -- 'DriverUnknown' or 'DriverDevice'.
+closeTray f d = M.maybeWith C.withCString f $ \f' -> M.with (fromIntegral $ fromEnum d) $ \d' -> do
+    r <- closeTray' f' d'
+    d'' <- S.peek d'
+    return (toEnum $ fromIntegral r, toEnum $ fromIntegral d'')
+
+foreign import ccall safe "cdio/compat/device.h cdio_close_tray"
+  closeTray' :: C.CString -> C.Ptr CDriverId -> IO CDriverReturnCode
+
+
+-- | Describe the driver-level error in a human-readable manner, as opposed to
+-- the machine representation returned by the 'Show' instance.
+driverErrmsg :: DriverReturnCode -> String
+driverErrmsg = IO.Unsafe.unsafePerformIO .
+    C.peekCString . driverErrmsg' . fromIntegral . fromEnum
+
+foreign import ccall safe "cdio/compat/device.h cdio_driver_errmsg"
+  driverErrmsg' :: CDriverReturnCode -> C.CString
+
+
+-- | Eject the media represented by the session identifier, if the device
+-- supports doing so.
+-- 
+-- __Warning:__  Assuming this succeeds, the 'Cdio' object is destroyed and any
+-- further operations on it will fail!
+ejectMedia :: Cdio -> IO DriverReturnCode
+ejectMedia = fmap toDriverReturnCode . flip withCdioPtr ejectMedia'
+
+foreign import ccall safe "cdio/compat/device.h cdio_eject_media"
+  ejectMedia' :: C.Ptr (C.Ptr Cdio) -> IO CDriverReturnCode
+
+-- | Eject media in a CD drive, if the device supports doing so.  If a 'Cdio'
+-- session has already been opened on the drive, 'ejectMedia' is strongly
+-- recommended instead.
+ejectDrive
+    :: Maybe FilePath
+        -- ^ The name of the device to eject, or 'Nothing' to use the default
+        -- drive for the machine.
+    -> IO DriverReturnCode
+ejectDrive = fmap (toEnum . fromIntegral) . flip (M.maybeWith C.withCString) ejectDrive'
+
+foreign import ccall safe "cdio/compat/device.h cdio_eject_media_drive"
+  ejectDrive' :: C.CString -> IO CDriverReturnCode
+
+
+-- | Find the default disc device for the system, if one exists.
+-- 
+-- The C library allows getting the default device from a 'Cdio' object, but
+-- since that seems to only be initialized from either the default device
+-- itself or with an explicit path, doing so seems rather redundant.
+defaultDevice :: IO (Maybe FilePath)
+defaultDevice = defaultDevice' C.nullPtr >>= M.maybePeek C.peekCString
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_default_device"
+  defaultDevice' :: C.Ptr Cdio -> IO C.CString
+
+-- | Find the default disc device for a given driver, if one exists.
+defaultDeviceDriver
+    :: DriverId
+    -> IO (Maybe FilePath, DriverId)
+        -- ^ The name of the device, along with the associated driver if
+        -- passed 'DriverUnknown' or 'DriverDevice'.
+defaultDeviceDriver d = M.with (fromIntegral $ fromEnum d) $ \d' -> do
+    f <- defaultDeviceDriver' d' >>= M.maybePeek C.peekCString
+    d'' <- S.peek d'
+    return (f, toEnum $ fromIntegral d'')
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_driver"
+  defaultDeviceDriver' :: C.Ptr CDriverId -> IO C.CString
+
+
+-- | List (static) available devices on the system which can be accessed with a
+-- particular driver; some file devices (e.g.  with 'DriverBinCue') might be
+-- returned, but an exhaustive list should not be expected in that case.
+-- 
+-- If passed 'DriverDevice', the returned value will list any type of hardware
+-- device, but no image files.  Likewise, if passed 'DriverUnknown', all
+-- hardware devices will be returned along with any already-known images.
+devices :: DriverId -> IO [FilePath]
+devices d = devices' (fromIntegral $ fromEnum d) >>= peekFStringArray
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_devices"
+  devices' :: CDriverId -> IO (C.Ptr C.CString)
+
+-- | Like 'devices', but if 'DriverDevice' or 'DriverUnknown' is passed, the
+-- second return value reflects the driver the library would use by default.
+-- If any other 'DriverId' is passed, that value is returned unchanged.
+devicesRet :: DriverId -> IO ([FilePath], DriverId)
+devicesRet d = M.with (fromIntegral $ fromEnum d) $ \d' -> do
+    fs <- devicesRet' d' >>= peekFStringArray
+    d'' <- S.peek d'
+    return (fs, toEnum $ fromIntegral d'')
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_devices_ret"
+  devicesRet' :: C.Ptr CDriverId -> IO (C.Ptr C.CString)
+
+-- | Determine which of the devices may read discs fitting the given
+-- description.
+devicesWithFilesystem
+    :: [FilePath]
+        -- ^ If empty, then search all possible drives.
+    -> Maybe Filesystem
+    -> FilesystemClasses
+    -> Bool
+        -- ^ If 'True', then a device matching any of the capabilities
+        -- succeeds; if 'False' then it must match every capability given
+        -- (empty capabilities always match).
+    -> IO [FilePath]
+devicesWithFilesystem ps fs fc b = allocaStringArray ps $ \ps' ->
+    devicesWithFilesystem' ps' (joinEnumFlags fs' fc) (M.fromBool b) >>= peekFStringArray
+  where fs' = maybe 0 fromEnum fs
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_devices_with_cap"
+  devicesWithFilesystem' :: C.Ptr C.CString -> C.CInt -> CBool -> IO (C.Ptr C.CString)
+
+-- | Like 'devicesWithFilesystem', but returning the type of driver found as with
+-- 'devicesRet'.  This is only helpful if the device list is empty; otherwise
+-- it simply returns 'DriverDevice'.
+devicesWithFilesystemRet
+    :: [FilePath]
+        -- ^ If empty, then search all possible drives.
+    -> Maybe Filesystem
+    -> FilesystemClasses
+    -> Bool
+        -- ^ If 'True', then a device matching any of the capabilities
+        -- succeeds; if 'False' then it must match every capability given
+        -- (empty capabilities always match).
+    -> IO ([FilePath], DriverId)
+devicesWithFilesystemRet ps fs fc b = M.alloca $ \d -> allocaStringArray ps $ \ps' -> do
+    ds <- devicesWithFilesystemRet' ps' (joinEnumFlags fs' fc) (M.fromBool b) d
+    ds' <- peekFStringArray ds
+    d' <- S.peek d
+    return (ds', toEnum $ fromIntegral d')
+  where fs' = maybe 0 fromEnum fs
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_devices_with_cap_ret"
+  devicesWithFilesystemRet' :: C.Ptr C.CString -> C.CInt -> CBool -> C.Ptr CDriverId -> IO (C.Ptr C.CString)
+
+
+-- | Get the drive capabilities for the default device.
+driveCap :: Cdio -> IO DriveCaps
+driveCap c = M.alloca $ \x -> M.alloca $ \y -> M.alloca $ \z -> do
+    withCdio_ c $ \c' -> driveCap' c' x y z
+    peekDriveCaps x y z
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_drive_cap"
+  driveCap' :: C.Ptr Cdio -> C.Ptr CBitfield -> C.Ptr CBitfield -> C.Ptr CBitfield -> IO ()
+
+-- | Get the drive capabilities for a specified device.
+driveCapDevice :: FilePath -> IO DriveCaps
+driveCapDevice f = C.withCString f $ \f' -> M.alloca $ \x -> M.alloca $ \y -> M.alloca $ \z -> do
+    driveCapDevice' f' x y z
+    peekDriveCaps x y z
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_drive_cap_dev"
+  driveCapDevice' :: C.CString -> C.Ptr CBitfield -> C.Ptr CBitfield -> C.Ptr CBitfield -> IO ()
+
+-- | The value indicating an error occurring during the retrieval of drive
+-- capabilities.
+foreign import ccall safe "cdio/compat/device.h drive_cap_error"
+  capError :: CBitfield
+
+-- | The value used for initializing drive capabilities.
+foreign import ccall safe "cdio/compat/device.h drive_cap_unknown"
+  capUnknown :: CBitfield
+
+peekDriveCaps :: C.Ptr CBitfield -> C.Ptr CBitfield -> C.Ptr CBitfield -> IO DriveCaps
+peekDriveCaps x y z = do
+    x' <- S.peek x
+    y' <- S.peek y
+    z' <- S.peek z
+    return $ extractCapError x' y' z'
+
+-- | Process each capability collection, and if all are
+-- @CDIO_DRIVE_CAP_UNKNOWN@ (uninitialized) or @CDIO_DRIVE_CAP_ERROR@, then
+-- collapse them.
+extractCapError :: CBitfield -> CBitfield -> CBitfield -> DriveCaps
+extractCapError rs ws ms = case (packMay rs, packMay ws, packMay ms) of
+    (Nothing, Nothing, Nothing) -> (pack empty, pack empty, pack empty)
+    (rs', ws', ms') -> (orEmpty rs', orEmpty ws', orEmpty ms')
+  where testEnumBit :: (Integral c, Enum i) => c -> i -> (i, Bool)
+        testEnumBit c i = (i, (fromIntegral c .&. fromEnum i) /= 0)
+        pack bs = A.array (minBound, maxBound) $ map (testEnumBit bs) [minBound .. maxBound]
+        packMay bs
+            | bs .&. capError == 0 = Nothing
+            | bs .&. capUnknown == 0 = Nothing
+            | otherwise = Just $ pack bs
+        orEmpty :: (Bounded a, Enum a, Ix a) => Maybe (A.BitArray a) -> A.BitArray a
+        orEmpty = Y.fromMaybe $ pack empty
+        empty = 0x0 :: CBitfield
+
+
+-- | Describe the driver used by the session in a human-readable (English)
+-- manner.  See also 'driverId'.
+driverName :: Cdio -> IO (Maybe String)
+driverName c = withCdio c driverName' >>= maybe (return Nothing) (M.maybePeek C.peekCString)
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_driver_name"
+  driverName' :: C.Ptr Cdio -> IO C.CString
+
+{- Not exported
+-- | Describe the IO driver in a human-readable manner, as opposed to the
+-- machine representation returned by the 'Show' instance.
+driverNameFromId :: DriverId -> String
+driverNameFromId d = IO.Unsafe.unsafePerformIO $ driverNameFromId d >>= C.peekCString
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_driver_name_from_id"
+  driverNameFromId' :: DriverId -> C.CString
+-}
+
+-- | The machine-readable identifier of the driver used by the session.  This
+-- should be preferred to 'driverName' wherever possible.
+-- 
+-- Returns 'Nothing' if the 'Cdio' object has already been closed.
+driverId :: Cdio -> IO (Maybe DriverId)
+driverId c = fmap (toEnum . fromIntegral) <$> withCdio c driverId'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_driver_id"
+  driverId' :: C.Ptr Cdio -> IO CDriverId
+
+-- | Get a description of the hardware associated with a particular session.
+-- 
+-- Returns 'Nothing' if the 'Cdio' object has already been closed, or if an
+-- error occurred in retrieval.
+hwinfo :: Cdio -> IO (Maybe HardwareInfo)
+hwinfo c = M.alloca $ \h -> do
+    b <- withCdio c $ flip hwinfo' h
+    case M.toBool <$> b of
+        Just True -> M.maybePeek S.peek h
+        _ -> return Nothing
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_hwinfo"
+  hwinfo' :: C.Ptr Cdio -> C.Ptr HardwareInfo -> IO CBool
+
+
+-- | Get the starting address of the last write session of a disc.
+lastSession :: Cdio -> IO (Either DriverReturnCode Lsn)
+lastSession c = M.alloca $ \l -> do
+    r <- withCdio c $ flip lastSession' l
+    l' <- S.peek l
+    return $ case toEnum . fromIntegral <$> r of
+        Just Success -> Right l'
+        Just e -> Left e
+        Nothing -> Left Uninitialized
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_last_session"
+  lastSession' :: C.Ptr Cdio -> C.Ptr Lsn -> IO CDriverReturnCode
+
+
+-- | Find out if the media has changed since the last call.
+isMediaChanged :: Cdio -> IO (Either DriverReturnCode Bool)
+isMediaChanged c = maybe (Left Uninitialized) errorOrBool <$> withCdio c isMediaChanged'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_media_changed"
+  isMediaChanged' :: C.Ptr Cdio -> IO CDriverReturnCode
+
+
+-- | Determine if the device understands ATAPI commands.
+-- 
+-- Returns 'Nothing' if the 'Cdio' object has already been closed, or if the
+-- capability can't be determined.
+haveAtapi :: Cdio -> IO (Maybe Bool)
+haveAtapi c = fmap N.join . withCdio c $ fmap bool3 . haveAtapi'
+
+foreign import ccall safe "cdio/compat/device.h cdio_have_atapi"
+  haveAtapi' :: C.Ptr Cdio -> IO C.CInt
+
+
+-- | Determine whether the system provides a particular driver.
+haveDriver :: DriverId -> Bool
+haveDriver = M.toBool . haveDriver' . fromIntegral . fromEnum
+
+foreign import ccall safe "cdio/compat/device.h cdio_have_driver"
+  haveDriver' :: CDriverId -> CBool
+
+
+{- Encapsulated into the 'ForeignPtr Cdio'.
+-- | Free any resources associated with a reading session.
+cdioDestroy :: Cdio -> IO ()
+cdioDestroy = flip withCdio cdioDestroy'
+
+foreign import ccall safe "cdio/compat/device.h cdio_destroy"
+  cdioDestroy' :: C.Ptr Cdio -> IO ()
+-}
+
+
+-- | Describe the IO driver in a human-readable manner, as opposed to the
+-- machine representation returned by the 'Show' instance.
+driverDescribe :: DriverId -> String
+driverDescribe = IO.Unsafe.unsafePerformIO .
+    C.peekCString . driverDescribe' . fromIntegral . fromEnum
+
+foreign import ccall safe "cdio/compat/device.h cdio_driver_describe"
+  driverDescribe' :: CDriverId -> C.CString
+
+
+-- | Open a session referencing the given location, or the default device if
+-- passed 'Nothing'.
+cdioOpen :: Maybe FilePath -> DriverId -> IO (Maybe Cdio)
+cdioOpen f d = M.maybeWith C.withCString f $ \f' -> do
+    setupLogger
+    c' <- cdioOpen' f' (fromIntegral $ fromEnum d)
+    M.maybePeek peekCdio c'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open"
+  cdioOpen' :: C.CString -> CDriverId -> IO (C.Ptr Cdio)
+
+-- | Open a session referencing the given location, or the default device if
+-- passed 'Nothing', with the desired access mode.
+cdioOpenAm :: Maybe FilePath -> DriverId -> AccessMode -> IO (Maybe Cdio)
+cdioOpenAm f d m = M.maybeWith C.withCString f $ \f' -> C.withCString (serializeAccessMode m) $ \m' -> do
+    setupLogger
+    c' <- cdioOpenAm' f' (fromIntegral $ fromEnum d) m'
+    M.maybePeek peekCdio c'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_am"
+  cdioOpenAm' :: C.CString -> CDriverId -> C.CString -> IO (C.Ptr Cdio)
+
+
+open'
+    :: (C.CString -> IO (C.Ptr Cdio))
+    -> Maybe FilePath
+    -> IO (Maybe Cdio)
+open' f p = withCStringNull p $ \p' -> do
+    setupLogger
+    f p' >>= M.maybePeek peekCdio
+
+openAm'
+    :: (C.CString -> C.CString -> IO (C.Ptr Cdio))
+    -> Maybe FilePath
+    -> AccessMode
+    -> IO (Maybe Cdio)
+openAm' f p m = withCStringNull p $ \p' -> C.withCString (serializeAccessMode m) $ \m' -> do
+    setupLogger
+    f p' m' >>= M.maybePeek peekCdio
+
+withCStringNull :: Maybe String -> (C.CString -> IO a) -> IO a
+withCStringNull Nothing f = f C.nullPtr
+withCStringNull (Just str) f = C.withCString str f
+
+
+-- | Set up the specified CD-ROM device for reading.
+cdioOpenCd :: Maybe FilePath -> IO (Maybe Cdio)
+cdioOpenCd = open' cdioOpenCd'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_cd"
+  cdioOpenCd' :: C.CString -> IO (C.Ptr Cdio)
+
+-- | Set up the specified CD-ROM device for reading, with the desired access
+-- mode.
+cdioOpenAmCd :: Maybe FilePath -> AccessMode -> IO (Maybe Cdio)
+cdioOpenAmCd = openAm' cdioOpenAmCd'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_am_cd"
+  cdioOpenAmCd' :: C.CString -> C.CString -> IO (C.Ptr Cdio)
+
+
+{- All the official bindings hide these, which makes me think they're not as reliable.
+defaultPath' :: IO C.CString -> IO (Maybe FilePath)
+defaultPath' p = p >>= M.maybePeek C.peekCString
+
+deviceList' :: IO (C.Ptr C.CString) -> IO [FilePath]
+deviceList' ps = ps >>= peekFStringArray
+
+
+-- | Set up a BIN/CUE disc image for reading.
+cdioOpenBinCue
+    :: Maybe FilePath
+        -- ^ The path to either the @*.bin@ or the @*.cue@ file.
+    -> IO (Maybe Cdio)
+cdioOpenBinCue = open' cdioOpenBinCue'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_bincue"
+  cdioOpenBinCue' :: C.CString -> IO (C.Ptr Cdio)
+
+-- | Set up a BIN/CUE disc image for reading, with the desired access mode.
+cdioOpenAmBinCue
+    :: Maybe FilePath
+        -- ^ The path to either the @*.bin@ or the @*.cue@ file.
+    -> AccessMode
+    -> IO (Maybe Cdio)
+cdioOpenAmBinCue = openAm' cdioOpenAmBinCue'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_am_bincue"
+  cdioOpenAmBinCue' :: C.CString -> C.CString -> IO (C.Ptr Cdio)
+
+-- | The default CUE file that would be used if none is specified.
+defaultDeviceBinCue :: IO (Maybe FilePath)
+defaultDeviceBinCue = defaultPath' defaultDeviceBinCue'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_bincue"
+  defaultDeviceBinCue' :: IO C.CString
+
+-- | The CUE files contained in the current directory.
+devicesBinCue :: IO [FilePath]
+devicesBinCue = deviceList' devicesBinCue'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_devices_bincue"
+  devicesBinCue' :: IO (C.Ptr C.CString)
+
+
+-- | Set up a cdrdao disc image for reading.
+cdioOpenCdrDao
+    :: Maybe FilePath
+        -- ^ The path to the @*.toc@ file.
+    -> IO (Maybe Cdio)
+cdioOpenCdrDao = open' cdioOpenCdrDao'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_cdrdao"
+  cdioOpenCdrDao' :: C.CString -> IO (C.Ptr Cdio)
+
+-- | Set up a cdrdao disc image for reading, with the desired access mode.
+cdioOpenAmCdrDao
+    :: Maybe FilePath
+        -- ^ The path to the @*.toc@ file.
+    -> AccessMode
+    -> IO (Maybe Cdio)
+cdioOpenAmCdrDao = openAm' cdioOpenAmCdrDao'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_am_cdrdao"
+  cdioOpenAmCdrDao' :: C.CString -> C.CString -> IO (C.Ptr Cdio)
+
+-- | The default TOC file that would be used if none is specified.
+defaultDeviceCdrDao :: IO (Maybe FilePath)
+defaultDeviceCdrDao = defaultPath' defaultDeviceCdrDao'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_cdrdao"
+  defaultDeviceCdrDao' :: IO C.CString
+
+-- | Paths to potential TOC disc images.
+devicesCdrDao :: IO [FilePath]
+devicesCdrDao = deviceList' devicesCdrDao'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_devices_cdrdao"
+  devicesCdrDao' :: IO (C.Ptr C.CString)
+
+
+-- | Set up a BIN/CUE disc image for reading.  Unlike 'cdioOpenBinCue' which
+-- may reference either, this path /must/ point to the @*.cue@ file.
+cdioOpenCue :: Maybe FilePath -> IO (Maybe Cdio)
+cdioOpenCue = open' cdioOpenCue'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_cue"
+  cdioOpenCue' :: C.CString -> IO (C.Ptr Cdio)
+
+
+-- | Set up a device for reading using the AIX driver.
+cdioOpenAix :: Maybe FilePath -> IO (Maybe Cdio)
+cdioOpenAix = open' cdioOpenAix'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_aix"
+  cdioOpenAix' :: C.CString -> IO (C.Ptr Cdio)
+
+-- | Set up a device for reading using the AIX driver, with the desired access
+-- mode.
+cdioOpenAmAix :: Maybe FilePath -> AccessMode -> IO (Maybe Cdio)
+cdioOpenAmAix = openAm' cdioOpenAmAix'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_am_aix"
+  cdioOpenAmAix' :: C.CString -> C.CString -> IO (C.Ptr Cdio)
+
+-- | The default device name that the AIX driver would use if none is
+-- specified.
+defaultDeviceAix :: IO (Maybe FilePath)
+defaultDeviceAix = defaultPath' defaultDeviceAix'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_aix"
+  defaultDeviceAix' :: IO C.CString
+
+-- | All of the devices that the AIX driver can find.  This may require a disc
+-- to be inserted in order for the system to recognize the drive.
+devicesAix :: IO [FilePath]
+devicesAix = deviceList' devicesAix'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_devices_aix"
+  devicesAix' :: IO (C.Ptr C.CString)
+
+
+-- | Set up a device for reading using the FreeBSD driver.
+cdioOpenFreeBsd :: Maybe FilePath -> IO (Maybe Cdio)
+cdioOpenFreeBsd = open' cdioOpenFreeBsd'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_freebsd"
+  cdioOpenFreeBsd' :: C.CString -> IO (C.Ptr Cdio)
+
+-- | Set up a device for reading using the FreeBSD driver, with the desired
+-- access mode.
+cdioOpenAmFreeBsd :: Maybe FilePath -> AccessMode -> IO (Maybe Cdio)
+cdioOpenAmFreeBsd = openAm' cdioOpenAmFreeBsd'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_am_freebsd"
+  cdioOpenAmFreeBsd' :: C.CString -> C.CString -> IO (C.Ptr Cdio)
+
+-- | The default device name that the FreeBSD driver would use if none is
+-- specified.
+defaultDeviceFreeBsd :: IO (Maybe FilePath)
+defaultDeviceFreeBsd = defaultPath' defaultDeviceFreeBsd'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_freebsd"
+  defaultDeviceFreeBsd' :: IO C.CString
+
+-- | All of the devices that the FreeBSD driver can find.  This may require a
+-- disc to be inserted in order for the system to recognize the drive.
+devicesFreeBsd :: IO [FilePath]
+devicesFreeBsd = deviceList' devicesFreeBsd'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_devices_freebsd"
+  devicesFreeBsd' :: IO (C.Ptr C.CString)
+
+
+-- | Set up a device for reading using the BSDI driver.
+-- 
+-- /Since libcdio 1.0:  Always returns 'Nothing'/
+cdioOpenBsdi :: Maybe FilePath -> IO (Maybe Cdio)
+cdioOpenBsdi = open' cdioOpenBsdi'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_bsdi_safe"
+  cdioOpenBsdi' :: C.CString -> IO (C.Ptr Cdio)
+
+-- | Set up a device for reading using the BSDI driver, with the desired access
+-- mode.
+-- 
+-- /Since libcdio 1.0:  Always returns 'Nothing'/
+cdioOpenAmBsdi :: Maybe FilePath -> AccessMode -> IO (Maybe Cdio)
+cdioOpenAmBsdi = openAm' cdioOpenAmBsdi'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_am_bsdi_safe"
+  cdioOpenAmBsdi' :: C.CString -> C.CString -> IO (C.Ptr Cdio)
+
+-- | The default device name that the BSDI driver would use if none is
+-- specified.
+-- 
+-- /Since libcdio 1.0:  Always returns 'Nothing'/
+defaultDeviceBsdi :: IO (Maybe FilePath)
+defaultDeviceBsdi = defaultPath' defaultDeviceBsdi'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_bsdi_safe"
+  defaultDeviceBsdi' :: IO C.CString
+
+-- | All of the devices that the BSDI driver can find.  This may require a disc
+-- to be inserted in order for the system to recognize the drive.
+-- 
+-- /Since libcdio 1.0:  Always returns @[]@/
+devicesBsdi :: IO [FilePath]
+devicesBsdi = deviceList' devicesBsdi'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_devices_bsdi_safe"
+  devicesBsdi' :: IO (C.Ptr C.CString)
+
+
+-- | Set up a device for reading using the GNU/Linux driver.  This may require
+-- a disc to be inserted in order for the system to recognize the drive.
+cdioOpenLinux :: Maybe FilePath -> IO (Maybe Cdio)
+cdioOpenLinux = open' cdioOpenLinux'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_linux"
+  cdioOpenLinux' :: C.CString -> IO (C.Ptr Cdio)
+
+-- | Set up a device for reading using the GNU/Linux driver, with the desired
+-- access mode.
+cdioOpenAmLinux :: Maybe FilePath -> AccessMode -> IO (Maybe Cdio)
+cdioOpenAmLinux = openAm' cdioOpenAmLinux'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_am_linux"
+  cdioOpenAmLinux' :: C.CString -> C.CString -> IO (C.Ptr Cdio)
+
+-- | The default device name that the GNU/Linux driver would use if none is
+-- specified.  This may require a disc to be inserted in order for the system to
+-- recognize the drive.
+defaultDeviceLinux :: IO (Maybe FilePath)
+defaultDeviceLinux = defaultPath' defaultDeviceLinux'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_linux"
+  defaultDeviceLinux' :: IO C.CString
+
+-- | All of the devices that the GNU/Linux driver can find.
+devicesLinux :: IO [FilePath]
+devicesLinux = deviceList' devicesLinux'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_devices_linux"
+  devicesLinux' :: IO (C.Ptr C.CString)
+
+
+-- | Set up a device for reading using the Sun Solaris driver.  This may
+-- require a disc to be inserted in order for the system to recognize the
+-- drive.
+cdioOpenSolaris :: Maybe FilePath -> IO (Maybe Cdio)
+cdioOpenSolaris = open' cdioOpenSolaris'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_solaris"
+  cdioOpenSolaris' :: C.CString -> IO (C.Ptr Cdio)
+
+-- | Set up a device for reading using the Sun Solaris driver, with the desired
+-- access mode.
+cdioOpenAmSolaris :: Maybe FilePath -> AccessMode -> IO (Maybe Cdio)
+cdioOpenAmSolaris = openAm' cdioOpenAmSolaris'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_am_solaris"
+  cdioOpenAmSolaris' :: C.CString -> C.CString -> IO (C.Ptr Cdio)
+
+-- | The default device name that the Solaris driver would use if none is
+-- specified.  This may require a disc to be inserted in order for the system
+-- to recognize the drive.
+defaultDeviceSolaris :: IO (Maybe FilePath)
+defaultDeviceSolaris = defaultPath' defaultDeviceSolaris'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_solaris"
+  defaultDeviceSolaris' :: IO C.CString
+
+-- | All of the devices that the Solaris driver can find.
+devicesSolaris :: IO [FilePath]
+devicesSolaris = deviceList' devicesSolaris'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_devices_solaris"
+  devicesSolaris' :: IO (C.Ptr C.CString)
+
+
+-- | Set up a device for reading using the Apple OSX driver.  This may require
+-- a disc to be inserted in order for the system to recognize the drive.
+cdioOpenOsX :: Maybe FilePath -> IO (Maybe Cdio)
+cdioOpenOsX = open' cdioOpenOsX'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_osx"
+  cdioOpenOsX' :: C.CString -> IO (C.Ptr Cdio)
+
+-- | Set up a device for reading using the Apple OSX driver, with the desired
+-- access mode.
+cdioOpenAmOsX :: Maybe FilePath -> AccessMode -> IO (Maybe Cdio)
+cdioOpenAmOsX = openAm' cdioOpenAmOsX'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_am_osx"
+  cdioOpenAmOsX' :: C.CString -> C.CString -> IO (C.Ptr Cdio)
+
+-- | The default device name that the OSX driver would use if none is
+-- specified.  This may require a disc to be inserted in order for the system
+-- to recognize the drive.
+defaultDeviceOsX :: IO (Maybe FilePath)
+defaultDeviceOsX = defaultPath' defaultDeviceOsX'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_osx"
+  defaultDeviceOsX' :: IO C.CString
+
+-- | All of the devices that the OSX driver can find.
+devicesOsX :: IO [FilePath]
+devicesOsX = deviceList' devicesOsX'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_devices_osx"
+  devicesOsX' :: IO (C.Ptr C.CString)
+
+
+-- | Set up a device for reading using the Microsoft Windows driver.  This may
+-- require a disc to be inserted in order for the system to recognize the
+-- drive.
+cdioOpenWin32 :: Maybe FilePath -> IO (Maybe Cdio)
+cdioOpenWin32 = open' cdioOpenWin32'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_win32"
+  cdioOpenWin32' :: C.CString -> IO (C.Ptr Cdio)
+
+-- | Set up a device for reading using the Microsoft Windows driver, with the
+-- desired access mode.
+cdioOpenAmWin32 :: Maybe FilePath -> AccessMode -> IO (Maybe Cdio)
+cdioOpenAmWin32 = openAm' cdioOpenAmWin32'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_am_win32"
+  cdioOpenAmWin32' :: C.CString -> C.CString -> IO (C.Ptr Cdio)
+
+-- | The default device name that the Microsoft Windows driver would use if
+-- none is specified.  This may require a disc to be inserted in order for the
+-- system to recognize the drive.
+defaultDeviceWin32 :: IO (Maybe FilePath)
+defaultDeviceWin32 = defaultPath' defaultDeviceWin32'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_win32"
+  defaultDeviceWin32' :: IO C.CString
+
+-- | All of the devices that the Microsoft Windows driver can find.
+devicesWin32 :: IO [FilePath]
+devicesWin32 = deviceList' devicesWin32'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_devices_win32"
+  devicesWin32' :: IO (C.Ptr C.CString)
+
+
+-- | Set up a device for reading using the IBM OS/2 driver.  This may require a
+-- disc to be inserted in order for the system to recognize the drive.
+-- 
+-- /Since libcdio 1.0:  Always returns 'Nothing'/
+cdioOpenOs2 :: Maybe FilePath -> IO (Maybe Cdio)
+cdioOpenOs2 = open' cdioOpenOs2'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_os2_safe"
+  cdioOpenOs2' :: C.CString -> IO (C.Ptr Cdio)
+
+-- | Set up a device for reading using the IBM OS/2 driver, with the desired
+-- access mode.
+-- 
+-- /Since libcdio 1.0:  Always returns 'Nothing'/
+cdioOpenAmOs2 :: Maybe FilePath -> AccessMode -> IO (Maybe Cdio)
+cdioOpenAmOs2 = openAm' cdioOpenAmOs2'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_am_os2_safe"
+  cdioOpenAmOs2' :: C.CString -> C.CString -> IO (C.Ptr Cdio)
+
+-- | The default device name that the OS/2 driver would use if none is
+-- specified.  This may require a disc to be inserted in order for the system
+-- to recognize the drive.
+-- 
+-- /Since libcdio 1.0:  Always returns 'Nothing'/
+defaultDeviceOs2 :: IO (Maybe FilePath)
+defaultDeviceOs2 = defaultPath' defaultDeviceOs2'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_os2_safe"
+  defaultDeviceOs2' :: IO C.CString
+
+-- | All of the devices that the OS/2 driver can find.
+-- 
+-- /Since libcdio 1.0:  Always returns @[]@/
+devicesOs2 :: IO [FilePath]
+devicesOs2 = deviceList' devicesOs2'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_devices_os2_safe"
+  devicesOs2' :: IO (C.Ptr C.CString)
+
+
+-- | Set up a Nero disc image for reading.
+cdioOpenNero :: Maybe FilePath -> IO (Maybe Cdio)
+cdioOpenNero = open' cdioOpenNero'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_nrg"
+  cdioOpenNero' :: C.CString -> IO (C.Ptr Cdio)
+
+-- | Set up a Nero disc image for reading, with the desired access mode.
+cdioOpenAmNero :: Maybe FilePath -> AccessMode -> IO (Maybe Cdio)
+cdioOpenAmNero = openAm' cdioOpenAmNero'
+
+foreign import ccall safe "cdio/compat/device.h cdio_open_am_nrg"
+  cdioOpenAmNero' :: C.CString -> C.CString -> IO (C.Ptr Cdio)
+
+-- | The default image file that the Nero driver would use if none is
+-- specified.
+defaultDeviceNero :: IO (Maybe FilePath)
+defaultDeviceNero = defaultPath' defaultDeviceNero'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_nrg"
+  defaultDeviceNero' :: IO C.CString
+
+-- | Paths to potential Nero disc images.
+devicesNero :: IO [FilePath]
+devicesNero = deviceList' devicesNero'
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_devices_nrg"
+  devicesNero' :: IO (C.Ptr C.CString)
+-}
+
+
+-- | If the given file is a BIN disc image (determined by file extension),
+-- return the corresponding CUE file.  Note that this simply replaces the
+-- extension to obtain the new file name.
+cueFromBin :: FilePath -> IO (Maybe FilePath)
+cueFromBin f = C.withCString f cueFromBin' >>= M.maybePeek C.peekCString
+
+foreign import ccall safe "cdio/compat/device.h cdio_is_binfile"
+  cueFromBin' :: C.CString -> IO C.CString
+
+-- | If the given file is a valid CUE disc description, return the
+-- corresponding BIN file.  Note that this simply replaces the file extension
+-- to obtain the new file name.
+binFromCue :: FilePath -> IO (Maybe FilePath)
+binFromCue f = C.withCString f binFromCue' >>= M.maybePeek C.peekCString
+
+foreign import ccall safe "cdio/compat/device.h cdio_is_cuefile"
+  binFromCue' :: C.CString -> IO C.CString
+
+-- | Check that a Nero disc image file is valid.
+isNrg :: FilePath -> IO Bool
+isNrg = fmap M.toBool . flip C.withCString isNrg'
+
+foreign import ccall safe "cdio/compat/device.h cdio_is_nrg"
+  isNrg' :: C.CString -> IO CBool
+
+-- | Check that a cdrdao-style TOC description file is valid.
+isToc :: FilePath -> IO Bool
+isToc = fmap M.toBool . flip C.withCString isToc'
+
+foreign import ccall safe "cdio/compat/device.h cdio_is_tocfile"
+  isToc' :: C.CString -> IO CBool
+
+-- | Determine whether the given path refers to a hardware device, according to
+-- the given driver.  'DriverUnknown' or 'DriverDevice' may be passed if the
+-- system is unknown.
+isDevice :: FilePath -> DriverId -> IO Bool
+isDevice f d = M.toBool <$> C.withCString f (flip isDevice' . fromIntegral $ fromEnum d)
+
+foreign import ccall safe "cdio/compat/device.h cdio_is_device"
+  isDevice' :: C.CString -> CDriverId -> IO CBool
+
+
+-- | Set the blocksize for subsequent reads.
+setBlocksize
+    :: Cdio
+        -- ^ The CdText object is mutated as a result of the function.
+    -> Int
+    -> IO DriverReturnCode
+setBlocksize c s = toDriverReturnCode <$> withCdio c (flip setBlocksize' $ fromIntegral s)
+
+foreign import ccall safe "cdio/compat/device.h cdio_set_blocksize"
+  setBlocksize' :: C.Ptr Cdio -> C.CInt -> IO CDriverReturnCode
+
+-- | Set the drive speed.  With many devices, if a value above their maximum
+-- speed is given, it will be silently capped.
+--
+-- Note that, unlike 'MMC.setSpeed', this uses a unit unique to disc drives,
+-- which depends on the type of disc; to convert to or from Kb/s, use the
+-- formula @dt * cds = kbs@ where @dt@ is either @176@ for raw data or @150@
+-- for filesystem data, and @cds@ is the 'Int' passed to this function.
+setSpeed
+    :: Cdio
+        -- ^ The CdText object is mutated as a result of the function.
+    -> Int
+    -> IO DriverReturnCode
+setSpeed c v = toDriverReturnCode <$> withCdio c (flip setSpeed' $ fromIntegral v)
+
+foreign import ccall safe "cdio/compat/device.h cdio_set_speed"
+  setSpeed' :: C.Ptr Cdio -> C.CInt -> IO CDriverReturnCode
+
+
+-- | Retrieve the session value associated with the given key.  The particular
+-- case of @"access-mode"@ is instead handled by 'getAccessMode'.
+getArg :: Cdio -> SessionArg -> IO (Maybe String)
+getArg c k = C.withCString (serializeSessionArg k) $ \k' ->
+    withCdio c (`getArg'` k') >>= maybe (return Nothing) (M.maybePeek C.peekCString)
+
+-- | Check what instruction set is in use for reading the disc.  Other session
+-- values are handled by 'getArg'.
+getAccessMode :: Cdio -> IO (Maybe AccessMode)
+getAccessMode c = C.withCString "access-mode" $ \k' -> do
+    str <- withCdio c (`getArg'` k') >>= maybe (return Nothing) (M.maybePeek C.peekCString)
+    return $ fmap unserializeAccessMode str
+
+foreign import ccall safe "cdio/compat/device.h cdio_get_arg"
+  getArg' :: C.Ptr Cdio -> C.CString -> IO C.CString
+
+{- This is very likely intended for internal use only
+-- | Change the session value associated with the given key.
+setArg
+    :: Cdio
+        -- ^ The CdText object is mutated as a result of the function.
+    -> SessionArg
+    -> String
+        -- ^ The new property value.
+    -> IO DriverReturnCode
+setArg c k v = C.withCString (serializeSessionArg k) $ \k' -> C.withCString v $ \v' ->
+    toDriverReturnCode <$> withCdio c (\c' -> setArg' c' k' v')
+
+foreign import ccall safe "cdio/compat/device.h cdio_set_arg"
+  setArg' :: C.Ptr Cdio -> C.CString -> C.CString -> IO CDriverReturnCode
+-}
+
+-- | Metadata about the session in the form of (often freeform) text, providing
+-- a type-safe index to 'getArg'.  Note that not every driver type supports
+-- every item.
+--
+-- The key @"access-mode"@ is handled separately by 'getAccessMode', to better
+-- reflect its restricted outputs.
+data SessionArg
+    = Source
+    | Cue
+    | ScsiTuple
+    | MmcSupported
+  deriving ( Eq, Ord, Bounded, Enum, Show, Read )
+instance S.Storable SessionArg where
+    sizeOf _ = S.sizeOf (undefined :: C.CString)
+    alignment _ = S.alignment (undefined :: C.CString)
+    peek p = do
+        p' <- S.peek $ C.castPtr p
+        if p' == C.nullPtr
+            then error "Storable(SessionArg).peek: NULL reference"
+            else do
+                str <- C.peekCString p'
+                return $ case str of
+                    "source" -> Source
+                    "cue" -> Cue
+                    "scsi-tuple" -> ScsiTuple
+                    "mmc-supported?" -> MmcSupported
+                    _ -> error $ "Storable(SessionArg).peek: unknown key '" ++ str ++ "'"
+    poke p hs = C.newCString (serializeSessionArg hs) >>= S.poke (C.castPtr p)
+
+serializeSessionArg :: SessionArg -> String
+serializeSessionArg Source = "source"
+serializeSessionArg Cue = "cue"
+serializeSessionArg ScsiTuple = "scsi-tuple"
+serializeSessionArg MmcSupported = "mmc-supported?"
+
+
+-- | Which instruction set should be used to communicate with the driver,
+-- providing a type-safe input for session initialization.  Note that not every
+-- driver type supports every item.
+data AccessMode
+    = Image
+    | Ioctl
+        -- ^ The 'DriverLinux' and 'DriverBsdi' drivers use a different
+        -- internal representation for 'Ioctl_'.
+    | Ioctl_
+        -- ^ The 'DriverFreeBsd' and 'DriverWin32' drivers use a different
+        -- internal representation for 'Ioctl'.
+    | Aspi
+    | Atapi
+    | Cam
+    | Scsi
+    | ReadCd
+    | Read10
+    | MmcReadWrite
+    | MmcReadWriteExclusive
+  deriving ( Eq, Ord, Bounded, Enum, Show, Read )
+instance S.Storable AccessMode where
+    sizeOf _ = S.sizeOf (undefined :: C.CString)
+    alignment _ = S.alignment (undefined :: C.CString)
+    peek p = do
+        p' <- S.peek $ C.castPtr p
+        if p' == C.nullPtr
+            then error "Storable(AccessMode).peek: NULL reference"
+            else unserializeAccessMode <$> C.peekCString p'
+    poke p hs = C.newCString (serializeAccessMode hs) >>= S.poke (C.castPtr p)
+
+serializeAccessMode :: AccessMode -> String
+serializeAccessMode Image = "image"
+serializeAccessMode Ioctl = "IOCTL"
+serializeAccessMode Ioctl_ = "ioctl"
+serializeAccessMode Aspi = "ASPI"
+serializeAccessMode Atapi = "ATAPI"
+serializeAccessMode Cam = "CAM"
+serializeAccessMode Scsi = "SCSI"
+serializeAccessMode ReadCd = "READ_CD"
+serializeAccessMode Read10 = "READ_10"
+serializeAccessMode MmcReadWrite = "MMC_RDWR"
+serializeAccessMode MmcReadWriteExclusive = "MMC_RDWR_EXCL"
+
+unserializeAccessMode :: String -> AccessMode
+unserializeAccessMode "image" = Image
+unserializeAccessMode "IOCTL" = Ioctl
+unserializeAccessMode "ioctl" = Ioctl_
+unserializeAccessMode "ASPI" = Aspi
+unserializeAccessMode "ATAPI" = Atapi
+unserializeAccessMode "CAM" = Cam
+unserializeAccessMode "SCSI" = Scsi
+unserializeAccessMode "READ_CD" = ReadCd
+unserializeAccessMode "READ_10" = Read10
+unserializeAccessMode "MMC_RDRW" = MmcReadWrite
+unserializeAccessMode "MMC_RDRW_EXCL" = MmcReadWriteExclusive
+unserializeAccessMode str = error $ "Storable(AccessMode).peek: unknown key '" ++ str ++ "'"
diff --git a/src/Foreign/Libcdio/Disc.hs b/src/Foreign/Libcdio/Disc.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Libcdio/Disc.hs
@@ -0,0 +1,256 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+{-|
+Description:    The top-level header for disc-related libcdio calls.
+
+Copyright:      (c) 2018-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+This module provides informational and metadata functions primarily related to
+the layout of data on a physical disc.  While both "Foreign.Libcdio.Read" and
+"Foreign.Libcdio.CdText" provide more exciting access to the actual data, this
+still provides a critical intermediate step between those and the physical
+hardware of "Foreign.Libcdio.Device".
+
+
+= @disc.h@
+
+== Types
+* @discmode_t@                      -> 'DiscMode'
+
+    - @CDIO_DISC_MODE_CD_DA@        -> 'AudioCdMode'
+    - @CDIO_DISC_MODE_CD_DATA@      -> 'DataCdMode'
+    - @CDIO_DISC_MODE_CD_XA@        -> 'XaCdMode'
+    - @CDIO_DISC_MODE_CD_MIXED@     -> 'MixedCdMode'
+    - @CDIO_DISC_MODE_DVD_ROM@      -> 'DvdRomMode'
+    - @CDIO_DISC_MODE_DVD_RAM@      -> 'DvdRamMode'
+    - @CDIO_DISC_MODE_DVD_R@        -> 'DvdRecordableMode'
+    - @CDIO_DISC_MODE_DVD_RW@       -> 'DvdReWritableMode'
+    - @CDIO_DISC_MODE_HD_DVD_ROM@   -> 'HighDefinitionDvdRomMode'
+    - @CDIO_DISC_MODE_HD_DVD_RAM@   -> 'HighDefinitionDvdRamMode'
+    - @CDIO_DISC_MODE_HD_DVD_R@     -> 'HighDefinitionDvdRecordableMode'
+    - @CDIO_DISC_MODE_DVD_PR@       -> 'DvdPlusRecordableMode'
+    - @CDIO_DISC_MODE_DVD_PRW@      -> 'DvdPlusReWritableMode'
+    - @CDIO_DISC_MODE_DVD_PR_DL@    -> 'DoubleLayerDvdPlusRecordableMode'
+    - @CDIO_DISC_MODE_DVD_PRW_DL@   -> 'DoubleLayerDvdPlusReWritableMode'
+    - @CDIO_DISC_MODE_DVD_OTHER@    -> 'OtherDvdMode'
+    - @CDIO_DISC_MODE_NO_INFO@      -> 'NoModeInfo'
+    - @CDIO_DISC_MODE_CD_I@         -> 'CdIMode'
+    - @CDIO_DISC_MODE_ERROR@        (removed; handled via 'Nothing')
+
+== Symbols
+* @cdio_get_cdtext@                 (removed; merged into 'Cdio' objects due to pointer lifespan issues)
+* @cdio_get_cdtext_raw@             -> 'cdTextRaw'
+* @cdio_get_disc_last_lsn@          -> 'lastLsn'
+* @cdio_get_discmode@               -> 'discMode'
+* @cdio_get_joliet_level@           -> 'discJolietLevel'
+* @cdio_get_mcn@                    -> 'cdMcn'
+* @cdio_get_num_tracks@             -> 'numTracks'
+* @cdio_is_discmode_cdrom@          -> 'isCdRom'
+* @cdio_is_discmode_dvd@            -> 'isDvd'
+* @discmode2str@                    -> 'discModeString'
+
+
+= "Sound.Libcdio.Read.Data"
+
+* @cdio_get_cdtext@                 -> @"Sound.Libcdio.Read.CdText".'Sound.Libcdio.Read.Data.cdText'@
+* 'cdMcn'                           -> 'Sound.Libcdio.Read.Data.catalogue'
+* 'cdTextRaw'                       -> @"Sound.Libcdio.Read.CdText".'Sound.Libcdio.Read.Data.cdTextRaw'@
+* 'lastLsn'                         -> 'Sound.Libcdio.Read.Data.lastAddress'
+* 'mcnLength'                       (removed; unnecessary low-level detail)
+* 'numTracks'                       -> @"Sound.Libcdio.Track".'Sound.Libcdio.Track.tracks'@
+-}
+module Foreign.Libcdio.Disc
+    ( -- * Types
+      DiscMode ( .. )
+    , discModeString
+    , isCdRom, isDvd
+      -- * Data
+    , discMode
+    , numTracks
+    , lastLsn
+    , discJolietLevel
+    , hasCdText
+    , cdTextRaw
+    , cdMcn
+    , mcnLength
+    ) where
+
+
+import qualified Control.Monad as N
+
+import qualified Data.ByteString as BS
+import qualified Data.Maybe as Y
+import qualified Data.Word as W
+
+import qualified Foreign.C.String as C
+import qualified Foreign.C.Types as C
+import qualified Foreign.Ptr as C
+
+import qualified Foreign.Marshal.Alloc as M
+import qualified Foreign.Marshal.Utils as M
+import qualified Foreign.Storable as S
+
+import qualified System.IO.Unsafe as IO.Unsafe
+
+import Foreign.Libcdio.CdText
+import Foreign.Libcdio.CdText.Binary
+import Foreign.Libcdio.Marshal
+import Foreign.Libcdio.Track
+import Foreign.Libcdio.Types.Enums
+import Foreign.Libcdio.Types.Internal
+
+
+-- | Filter out @CDIO_DISC_MODE_ERROR@ values to fit the 'Enum'.
+invalidDiscMode :: CDiscMode -> Maybe DiscMode
+invalidDiscMode = fmap (toEnum . fromIntegral) . maybeError [invalidDiscMode']
+
+foreign import ccall safe "cdio/compat/disc.h discmode_error"
+  invalidDiscMode' :: CDiscMode
+
+
+-- | Describe a type a disc according to its official name, as opposed to the
+-- machine representation returned by the 'Show' instance.
+discModeString :: DiscMode -> String
+discModeString = IO.Unsafe.unsafePerformIO .
+    C.peekCString . discModeString' . fromIntegral . fromEnum
+
+foreign import ccall safe "cdio/compat/disc.h discmode_string"
+  discModeString' :: CDiscMode -> C.CString
+
+
+-- | Get the raw CD-Text binary data contained on a disc.
+cdTextRaw :: Cdio -> IO (Maybe BS.ByteString)
+cdTextRaw c = withCdTextBlob c cdTextRaw' >>= maybe (serialize c) (return . Just)
+
+foreign import ccall safe "cdio/compat/disc.h get_cdtext_raw_len"
+  cdTextRaw' :: C.Ptr Cdio -> C.Ptr (C.Ptr C.CChar) -> C.Ptr C.CInt -> IO ()
+
+-- | Allocate a dummy pointer to have somewhere to store the return value.
+withCdTextBlob :: Cdio -> (C.Ptr Cdio -> C.Ptr (C.Ptr C.CChar) -> C.Ptr C.CInt -> IO ()) -> IO (Maybe BS.ByteString)
+withCdTextBlob c f = M.alloca $ \p' -> M.alloca $ \i' -> do
+    y <- withCdio c $ \c' -> f c' p' i'
+    if Y.isNothing y
+    then return Nothing
+    else do
+        p <- S.peek p'
+        i <- S.peek i'
+        if p == C.nullPtr
+        then return Nothing
+        else do
+            bs <- BS.packCStringLen (C.plusPtr p 4, fromIntegral i)
+            M.free p
+            return $ Just bs
+
+-- | If the @cdio_get_cdtext_raw@ call fails to provide a valid
+-- 'BS.ByteString', but we can access the stringified CDTEXT, generate one
+-- ourselves.  This is necessary as, if the CDTEXT wasn't binary to begin with
+-- (i.e. in an image file), libcdio is a bit lazy and doesn't return anything.
+serialize :: Cdio -> IO (Maybe BS.ByteString)
+serialize x = do
+    ls <- listAllLanguages x
+    ps <- N.forM [0 .. fromIntegral (length ls) - 1] $ \i -> do
+        b <- selectLanguageIndex x i
+        if b then serializeLanguage x i else return (0, [])
+    let (ss, bss) = unzip ps
+    return $ case map checksum $ concatMap (joinBlockInfo ls ss) bss of
+        [] -> Nothing
+        bs -> Just $ BS.concat bs
+
+-- | Retrieve all data from the current CDTEXT block and render it to the pack
+-- format used by the binary representation.  For convenience, the highest
+-- sequence number used by this block is also returned.
+serializeLanguage :: Cdio -> Word -> IO (W.Word8, [BS.ByteString])
+serializeLanguage x i = do
+    t1 <- Y.fromMaybe 1 <$> firstTrack x
+    tl <- Y.fromMaybe 0 <$> lastTrack x
+    di <- serializeInfo x Nothing
+    tis <- mapM (serializeInfo x . Just) [t1..tl]
+    c <- cdTextGet x DiscId Nothing
+    g <- genre x
+    gs <- cdTextGet x GenreName Nothing
+    let ps = packCdTextBlock i c t1 g gs di tis
+    return (fromIntegral . max 0 $ length ps - 1, ps)
+
+-- | Retrieve all text packs defined in the current block for the given track,
+-- and pack them into an easy-to-pass-around datatype.
+serializeInfo :: Cdio -> Maybe Track -> IO Info
+serializeInfo x t = do
+    n <- cdTextGet x Title t
+    p <- cdTextGet x Performer t
+    s <- cdTextGet x Songwriter t
+    c <- cdTextGet x Composer t
+    a <- cdTextGet x Arranger t
+    m <- cdTextGet x Message t
+    o <- cdTextGet x (if Y.isNothing t then UpcEan else Isrc) t
+    return $ Info n p s c a m o
+
+
+-- | Determine which type of disc is being accessed.  Note that while this
+-- provides a general direction, it shouldn't be relied upon for actual reading
+-- of data; use 'Foreign.Libcdio.Track.trackFormat' for more granular info.
+discMode :: Cdio -> IO (Maybe DiscMode)
+discMode c = (>>= invalidDiscMode) <$> withCdio c discMode'
+
+foreign import ccall safe "cdio/compat/disc.h cdio_get_discmode"
+  discMode' :: C.Ptr Cdio -> IO CDiscMode
+
+
+-- | Get the size of a disc in blocks, or equivalently the address of the end
+-- of the readable data.
+lastLsn :: Cdio -> IO (Maybe Lsn)
+lastLsn c = (>>= invalidZeroLsn) <$> withCdio c lastLsn'
+
+foreign import ccall safe "cdio/compat/disc.h cdio_get_disc_last_lsn"
+  lastLsn' :: C.Ptr Cdio -> IO C.CInt
+
+
+-- | The original ISO 9660 (data) filesystem specification was rather
+-- restrictive in what files could be named; the Joliet extensions allow such
+-- exciting features as lowercase letters, not to mention full Unicode support.
+discJolietLevel :: Cdio -> IO (Maybe Word)
+discJolietLevel c = (>>= maybeError [0] . fromIntegral) <$> withCdio c discJolietLevel'
+
+foreign import ccall safe "cdio/compat/disc.h cdio_get_joliet_level"
+  discJolietLevel' :: C.Ptr Cdio -> IO C.CUChar
+
+
+-- | Get the media catalog number from a disc.  This may also be retrieved
+-- by @'Foreign.Libcdio.CdText.getField' 'Foreign.Libcdio.CdText.UpcEan'
+-- 'Nothing'@, though that references a different source and thus may not have
+-- the same return value.
+cdMcn :: Cdio -> IO (Maybe String)
+cdMcn c = withCdio c cdMcn' >>= maybe (return Nothing) (M.maybePeek peekFString)
+
+foreign import ccall safe "cdio/compat/disc.h cdio_get_mcn"
+  cdMcn' :: C.Ptr Cdio -> IO C.CString
+
+
+-- | Get the number of tracks on a CD.
+-- 
+-- Returns 'Nothing' if the 'Cdio' object has already been closed, or if the
+-- disc table of contents can't be read.
+numTracks :: Cdio -> IO (Maybe Track)
+numTracks c = (>>= invalidTrack) <$> withCdio c numTracks'
+
+foreign import ccall safe "cdio/compat/disc.h cdio_get_num_tracks"
+  numTracks' :: C.Ptr Cdio -> IO C.CUChar
+
+
+-- | Return true if a 'DiscMode' refers to some sort of CD.
+isCdRom :: DiscMode -> Bool
+isCdRom = M.toBool . isCdRom' . fromIntegral . fromEnum
+
+foreign import ccall safe "cdio/compat/disc.h cdio_is_discmode_cdrom"
+  isCdRom' :: CDiscMode -> C.CUChar
+
+-- | Return true if a 'DiscMode' refers to some sort of DVD.
+isDvd :: DiscMode -> Bool
+isDvd = M.toBool . isDvd' . fromIntegral . fromEnum
+
+foreign import ccall safe "cdio/compat/disc.h cdio_is_discmode_dvd"
+  isDvd' :: CDiscMode -> C.CUChar
diff --git a/src/Foreign/Libcdio/Logging.hs b/src/Foreign/Libcdio/Logging.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Libcdio/Logging.hs
@@ -0,0 +1,166 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+{-|
+Description:    Control over and access to library log output.
+
+Copyright:      (c) 2020-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+The underlying library is rather loud in its error and warning messages,
+potentially emitting a lot of impure terminal clutter even on some
+otherwise-pure functions.  Very helpfully, it also provides a mechanism for
+integrating the logs with whatever framework is in place for the larger
+project; that mechanism can be leveraged to cache the logs in memory until
+specifically asked for, at which point they can be packaged into Haskell types.
+Some of the immediacy—and therefore user ability to match note to source—is
+unfortunately lost, but the apparent purity is worth it.
+
+
+= @logging.h@
+
+== Types
+* @cdio_log_level_t@                -> 'Foreign.Libcdio.Logging.LogLevel'
+
+== Symbols
+* @cdio_default_log_handler@        (removed; always handled through 'Foreign.Libcdio.Logging.readLog')
+* @cdio_assert@                     -> @'Foreign.Libcdio.Logging.putLog' 'Forign.Libcdio.Logging.LogAssert'@
+* @cdio_debug@                      -> @'Foreign.Libcdio.Logging.putLog' 'Forign.Libcdio.Logging.LogDebug'@
+* @cdio_error@                      -> @'Foreign.Libcdio.Logging.putLog' 'Forign.Libcdio.Logging.LogError'@
+* @cdio_info@                       -> @'Foreign.Libcdio.Logging.putLog' 'Forign.Libcdio.Logging.LogInfo'@
+* @cdio_log@                        -> 'Foreign.Libcdio.Logging.putLog'
+* @cdio_log_set_handler@            (removed; always handled through 'Foreign.Libcdio.Logging.readLog')
+* @cdio_loglevel_default@           -> 'Foreign.Libcdio.Logging.logCutoff' and 'Foreign.Libcdio.Logging.setLogCutoff'
+* @cdio_warn@                       -> @'Foreign.Libcdio.Logging.putLog' 'Forign.Libcdio.Logging.LogWarn'@
+
+
+= "Sound.Libcdio.Logging"
+Most functions have been re-contextulized as being provided through a
+'Sound.Libcdio.Logging.LibcdioLogger' instance, but the interface is otherwise
+unchanged.
+-}
+module Foreign.Libcdio.Logging
+    ( -- * Types
+      LogEntry ( .. )
+    , LogLevel ( .. )
+      -- * Message interaction
+    , putLog
+    , readLog
+    , clearLog
+      -- * Management
+    , logCutoff
+    , setLogCutoff
+    , setupLogger
+    ) where
+
+
+import qualified Control.Monad as N
+
+import qualified Data.Maybe as Y
+
+import qualified Foreign.C.String as C
+import qualified Foreign.C.Types as C
+import qualified Foreign.Ptr as C
+
+import qualified Foreign.Marshal.Array as M
+import qualified Foreign.Marshal.Utils as M
+import qualified Foreign.Storable as S
+
+import Foreign.Libcdio.Marshal
+import Foreign.Libcdio.Types.Enums
+import Foreign.Libcdio.Types.Offsets
+
+
+-- | Check the current minimum severity which will be recorded in the logs.
+--
+-- See 'setLogCutoff'.
+logCutoff :: IO LogLevel
+logCutoff = toEnum . fromIntegral <$> logCutoff'
+
+foreign import ccall safe "cdio/compat/logging.h get_cdio_log_level"
+  logCutoff' :: IO CLogLevel
+
+
+-- | Set the minimum severity required for a message to be recorded in the
+-- logs.
+--
+-- See 'logCutoff'.
+setLogCutoff :: LogLevel -> IO ()
+setLogCutoff = setLogCutoff' . fromIntegral . fromEnum
+
+foreign import ccall safe "cdio/compat/logging.h set_cdio_log_level"
+  setLogCutoff' :: CLogLevel -> IO ()
+
+
+-- | An unstructured message emitted from the library to let the user know
+-- what's going on behind the scenes.
+data LogEntry = LogEntry
+    { logLevel :: LogLevel
+        -- ^ How critical it is that the user receive this particular message.
+    , logMessage :: String
+        -- ^ The text of the message itself.
+    }
+  deriving ( Eq, Show, Read )
+instance S.Storable LogEntry where
+    sizeOf _    = leSizeOf
+    alignment _ = leAlign
+    peek c = do
+        l <- S.peekByteOff c leLevel :: IO CLogLevel
+        m' <- S.peekByteOff c leMessage
+        m <- if m' == C.nullPtr
+            then return ""
+            else C.peekCString m'
+        return $ LogEntry
+            { logLevel = toEnum $ fromIntegral l
+            , logMessage = m
+            }
+    poke c hs = do
+        S.pokeByteOff c leLevel (fromIntegral . fromEnum $ logLevel hs :: CLogLevel)
+        m <- C.newCString $ logMessage hs
+        S.pokeByteOff c leMessage m
+        S.pokeByteOff c lePrevious C.nullPtr
+
+
+-- | Retrieve all messages currently in the log for further processing.  Note
+-- that this retains the contents of the log for future calls; to remove them,
+-- a separate call to 'clearLog' must be made.
+--
+-- >>> setupLogger
+-- >>> putLog $ LogEntry LogWarn "Testing log reading"
+-- >>> readLog
+-- [LogEntry LogWarn "Testing log reading"]
+-- >>> readLog
+-- [LogEntry LogWarn "Testing log reading"]
+-- >>> clearLog
+-- >>> readLog
+-- []
+readLog :: IO [LogEntry]
+readLog = do
+    es' <- readLog'
+    es <- Y.fromMaybe [] <$> M.maybePeek (M.peekArray0 C.nullPtr) es'
+    N.forM es S.peek
+
+foreign import ccall safe "cdio/compat/logging.h read_cdio_log"
+  readLog' :: IO (C.Ptr (C.Ptr LogEntry))
+
+
+-- | Empty all messages currently in the log.  There is no way to selectively
+-- remove only some messages; if that is desired, call 'readLog' first:
+--
+-- >>> setupLogger
+-- >>> msgs <- readLog
+-- >>> clearLog
+-- >>> mapM_ putLog $ filter p msgs
+foreign import ccall safe "cdio/compat/logging.h free_cdio_log"
+  clearLog :: IO ()
+
+
+-- | Append a message to the logs.
+putLog :: LogEntry -> IO ()
+putLog e = C.withCString (logMessage e) $ putLog' (fromIntegral . fromEnum $ logLevel e)
+
+foreign import ccall safe "cdio/compat/logging.h cdio_log"
+  putLog' :: CLogLevel -> C.CString -> IO ()
diff --git a/src/Foreign/Libcdio/Marshal.hs b/src/Foreign/Libcdio/Marshal.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Libcdio/Marshal.hs
@@ -0,0 +1,295 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+{-|
+Description:    Utility functions for the libcdio FFI.
+
+Copyright:      (c) 2018-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      provisional
+Portability:    portable
+-}
+module Foreign.Libcdio.Marshal
+    ( -- * Types
+      -- ** Cdio
+      Cdio
+    , withCdio
+    , withCdio_
+    , withCdioPtr
+    , peekCdio
+      -- ** CdText
+    , CdText
+    , withCdText
+    , withCdText'
+    , withCdText_
+    , hasCdText
+    , cdTextDataInit
+      -- * Management
+    , setupLogger
+    , genBitArray
+      -- * Marshalling
+      -- ** Bool
+    , errorOrBool
+    , bool3
+      -- ** Int
+    , errorOrInt
+    , maybeError
+      -- ** Enum a
+    , joinEnumFlags
+    , modEnumFlags
+      -- ** ByteString
+    , peekByteStringLen
+      -- ** String
+    , allocaStringArray
+      -- ** FString
+    , peekFString
+    , peekFStringArray
+    ) where
+
+
+import qualified Data.Array.BitArray as A
+import qualified Data.Bits as B
+import qualified Data.ByteString as BS
+import qualified Data.Ix as I
+import qualified Data.Maybe as Y
+
+import qualified Foreign.C.String as C
+import qualified Foreign.C.Types as C
+import qualified Foreign.ForeignPtr as C
+import qualified Foreign.Ptr as C
+
+import qualified Foreign.Marshal.Alloc as M
+import qualified Foreign.Marshal.Array as M
+import qualified Foreign.Marshal.Utils as M
+
+import qualified Foreign.Storable as S
+
+
+-- | Helper to convert device capabilities to a bitfield.
+genBitArray :: (Bounded a, I.Ix a) => [a] -> A.BitArray a
+genBitArray [] = A.false (minBound, maxBound)
+genBitArray cs = A.array (minBound, maxBound) $ map (\i -> (i, True)) cs
+
+
+-- | A particular disc reading/writing device, along with the data contained
+-- on the loaded disc.  Note well that this is always a mutable object, and is
+-- not thread-safe; moreover, any function this is passed to may wind up
+-- silently modifying the data.
+data Cdio = Cdio (Maybe (C.ForeignPtr Cdio)) (Maybe (C.ForeignPtr CdText))
+
+-- | Free all memory used by a reference to a device.
+foreign import ccall "cdio/compat/device.h &cdio_destroy"
+  cdioDestroy :: C.FinalizerPtr Cdio
+
+-- | Convert the (foreign) reference to a device to something the FFI can use.
+withCdio :: Cdio -> (C.Ptr Cdio -> IO b) -> IO (Maybe b)
+withCdio (Cdio Nothing _) = const $ return Nothing
+withCdio (Cdio (Just c) _) = fmap Just . C.withForeignPtr c
+
+withCdio_ :: Cdio -> (C.Ptr Cdio -> IO ()) -> IO ()
+withCdio_ c f = withCdio c f >> mempty
+
+-- | Marshall a device reference with an extra layer of indirection.
+withCdioPtr :: Cdio -> (C.Ptr (C.Ptr Cdio) -> IO b) -> IO (Maybe b)
+withCdioPtr (Cdio Nothing _) _ = return Nothing
+withCdioPtr (Cdio (Just c) _) f = M.alloca $ \p ->
+    C.withForeignPtr c $ \c' -> do
+        S.poke p c'
+        Just <$> f p
+
+-- | Un-marshall a newly-allocated pointer to a drive.
+peekCdio :: C.Ptr Cdio -> IO Cdio
+peekCdio c = do
+    -- All public methods of opening 'Cdio' objects already have this earlier to
+    -- catch any logs from opening the disc, but add it again just to be safe.
+    setupLogger
+    x <- M.maybePeek getCdText' c
+    x' <- case x of
+        Just x' -> Just <$> C.newForeignPtr_ x'
+        Nothing -> return Nothing
+    p' <- C.newForeignPtr cdioDestroy c
+    return $ Cdio (Just p') x'
+
+foreign import ccall "cdio/compat/disc.h cdio_get_cdtext"
+  getCdText' :: C.Ptr Cdio -> IO (C.Ptr CdText)
+
+
+-- | Initialize the log-management backend to use the mechanisms provided by
+-- this library instead of just printing to standard output.  While this will
+-- usually be taken care of automatically, it may still be necessary to call
+-- this explicitly if messages are being recorded before any disc session is
+-- opened.
+foreign import ccall "cdio/compat/logging.h setup_cdio_logger"
+  setupLogger :: IO ()
+
+
+-- | The metadata describing the contents of a disc.
+-- 
+-- This type is not exported, and is mainly here to catch copy-paste errors on
+-- my end.
+data CdText
+
+-- | Free all memory used by a reference to a device.
+foreign import ccall "cdio/compat/cdtext.h &cdtext_destroy"
+  cdTextDestroy :: C.FinalizerPtr CdText
+
+-- | Convert the (foreign) reference to a device to something the FFI can use.
+withCdText :: Cdio -> (C.Ptr CdText -> IO b) -> IO (Maybe b)
+withCdText (Cdio _ Nothing) = const $ return Nothing
+withCdText (Cdio _ (Just x)) = fmap Just <$> C.withForeignPtr x
+
+withCdText' :: b -> Cdio -> (C.Ptr CdText -> IO b) -> IO b
+withCdText' b c = fmap (Y.fromMaybe b) . withCdText c
+
+withCdText_ :: Cdio -> (C.Ptr CdText -> IO ()) -> IO ()
+withCdText_ c f = withCdText c f >> mempty
+
+-- | Whether the various functions in "Foreign.Libcdio.CdText" will have any
+-- effect, or simply return 'mempty'.
+hasCdText :: Cdio -> Bool
+hasCdText (Cdio _ x) = Y.isJust x
+
+
+-- | Read binary CD-TEXT data into a structured datatype.
+--
+-- Note that binary CdText dumps will frequently include four bytes at the
+-- beginning indicating the size of the file; this implementation expects that
+-- those bytes /are not/ included.  If your dump does include them, @'BS.drop'
+-- 4@ before passing the 'BS.ByteString' to this function.
+-- 
+-- /Before libcdio 0.94:  Always returns 'Nothing'/
+cdTextDataInit :: BS.ByteString -> IO (Maybe Cdio)
+cdTextDataInit bs = do
+    setupLogger
+    x <- cdTextInit' >>= C.newForeignPtr cdTextDestroy
+    b <- BS.useAsCStringLen bs $ \(bs', l) -> withCdText (Cdio Nothing $ Just x) $ \x' ->
+        cdTextDataInit' x' bs' $ fromIntegral l
+    return $ if b == Just 0
+        then Just . Cdio Nothing $ Just x
+        else Nothing
+
+-- | Create a new empty CDTEXT object.
+foreign import ccall "cdio/compat/cdtext.h cdtext_init"
+  cdTextInit' :: IO (C.Ptr CdText)
+
+foreign import ccall safe "cdio/compat/cdtext.h cdtext_data_init_safe"
+  cdTextDataInit' :: C.Ptr CdText -> C.Ptr C.CChar -> C.CSize -> IO C.CInt
+
+
+-- | Free the memory indicated by a C-style pointer, avoiding a segfault if
+-- passed a @NULL@ pointer.
+cdioFree :: C.Ptr a -> IO ()
+cdioFree = mkFree cdioFree'
+
+foreign import ccall "cdio/memory.h &cdio_free"
+  cdioFree' :: C.FunPtr (C.Ptr a -> IO ())
+
+-- | Retrieve the actual function with a @free@-style signature.
+foreign import ccall "dynamic"
+  mkFree :: C.FunPtr (C.Ptr a -> IO ()) -> C.Ptr a -> IO ()
+
+
+-- | Convert a return code indicating an error or success/failure into a
+-- type-safe representation.
+errorOrBool :: (Integral a, Enum b) => a -> Either b Bool
+errorOrBool = fmap M.toBool . errorOrInt
+
+
+-- | Convert the custom indeterminate boolean to more ideomatic Haskell.
+bool3 :: C.CInt -> Maybe Bool
+bool3 0 = Just False
+bool3 1 = Just True
+bool3 _ = Nothing
+
+
+-- | Convert a return code indicating an error or a numeric value into a
+-- type-safe representation.
+errorOrInt :: (Integral a, Enum b) => a -> Either b a
+errorOrInt i
+    | i < 0 = Left . toEnum $ fromIntegral i
+    | otherwise = Right i
+
+-- | Filter out an error value expressed as part of a C-style enum.
+maybeError :: Eq a => [a] -> a -> Maybe a
+maybeError es i
+    | elem i es = Nothing
+    | otherwise = Just i
+
+
+-- | Unmarshall a block of binary data from a C-style array with an explicit
+-- length.  Returns 'Nothing' if the returned size is negative.
+peekByteStringLen
+    :: (Integral b, S.Storable b)
+    => C.Ptr (C.Ptr a)
+    -> C.Ptr b
+    -> IO (Maybe BS.ByteString)
+peekByteStringLen p l = do
+    p' <- S.peek p
+    l' <- S.peek l
+    if l' < 0 || p' == C.nullPtr
+         then return Nothing
+         else Just <$> BS.packCStringLen (C.castPtr p', fromIntegral l')
+
+
+-- | Combine an ordered value and an array of bit flags into a single value.
+joinEnumFlags
+    :: (Enum a, Enum b, Bounded b, I.Ix b, Integral c, B.Bits c)
+    => a
+    -> A.BitArray b
+    -> c
+joinEnumFlags a bs = fromIntegral (fromEnum a) + bs'
+  where bs' = foldr set 0x0 . zip [fst bnds .. snd bnds] $ drop fstBit [0..]
+        bnds = (minBound, maxBound)
+        set (e, i) b = case bs A.!? e of
+            Just True -> B.setBit b i
+            _ -> b
+        fstBit = B.countTrailingZeros . fromEnum $ fst bnds
+
+-- | Split a number into an ordered value (below the 'minBound') and an array
+-- of bit flags.
+modEnumFlags
+    :: (Integral a, B.Bits a, Enum b, Bounded b, Enum c, Bounded c, I.Ix c)
+    => a
+    -> (Maybe b, A.BitArray c)
+modEnumFlags i = (toEnumMaybe $ fromIntegral fs, bs)
+  where fs = mod i . fromIntegral . fromEnum $ fst bnds
+        bs = A.listArray bnds . map (B.testBit i) . drop fstBit $ take lstBit [0..]
+        bnds = (minBound, maxBound)
+        fstBit = B.countTrailingZeros . fromEnum $ fst bnds
+        lstBit = B.countTrailingZeros . fromEnum $ snd bnds
+
+
+-- | Will not work if the 'Enum' instance has been redefined to not be
+-- sequential.
+-- 
+-- From <https://stackoverflow.com/a/2744712/7634517>
+toEnumMaybe :: (Enum a, Bounded a) => Int -> Maybe a
+toEnumMaybe i = if i < fromEnum n || i > fromEnum x
+    then Nothing
+    else Just e
+  where e = toEnum i
+        n = asTypeOf minBound e
+        x = asTypeOf maxBound e
+
+
+-- | Temporarily copy a list of 'String's to pass them to a C function as a
+-- @NULL@-terminated array, cleaning up the allocated memory afterward.
+allocaStringArray :: [String] -> (C.Ptr C.CString -> IO a) -> IO a
+allocaStringArray [] f = f C.nullPtr
+allocaStringArray ss f = M.withMany C.withCString ss $ \ss' -> M.withArray0 C.nullPtr ss' f
+
+
+-- | Retrieve the value of a C-style string which needs to be manually freed.
+peekFString :: C.CString -> IO String
+peekFString c = do
+    s <- C.peekCString c
+    cdioFree c
+    return s
+
+-- | Retrieve the values of an array of C-style strings which all need to be
+-- manually freed.
+peekFStringArray :: C.Ptr C.CString -> IO [String]
+peekFStringArray p = do
+    ss <- M.maybePeek (M.peekArray0 C.nullPtr) p
+    maybe (return []) (mapM peekFString) ss
diff --git a/src/Foreign/Libcdio/Read.hs b/src/Foreign/Libcdio/Read.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Libcdio/Read.hs
@@ -0,0 +1,253 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+{-|
+Description:    Functions providing a means to retrieve the data stored on a disc.
+
+Copyright:      (c) 2018-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+After obtaining landmarks through "Foreign.Libcdio.Disc" (and likely
+"Foreign.Libcdio.Track"), this module provides the functions required to
+actually retrive the primary data from the disc.  Some knowledge of its
+physical layout is required, which may be determined through
+'Foreign.Libcdio.Track.trackFormat'.
+
+
+= @read.h@
+
+== Types
+* @cdio_read_mode_t@                -> 'ReadMode'
+
+    - @CDIO_READ_MODE_M1F1@         -> 'Mode1Form1'
+    - @CDIO_READ_MODE_M1F2@         -> 'Mode1Form2'
+    - @CDIO_READ_MODE_M2F1@         -> 'Mode2Form1'
+    - @CDIO_READ_MODE_M2F2@         -> 'Mode2Form2'
+
+== Symbols
+* @cdio_lseek@                      -> 'seek'
+* @cdio_read@                       -> 'readBytes'
+* @cdio_read_audio_sector@          -> 'readAudioSector'
+* @cdio_read_audio_sectors@         -> 'readAudioSectors'
+* @cdio_read_data_sectors@          -> 'readDataSectors'
+* @cdio_read_mode1_sector@          -> 'readDataModeSector'
+* @cdio_read_mode1_sectors@         -> 'readDataModeSectors'
+* @cdio_read_mode2_sector@          -> 'readXaModeSector'
+* @cdio_read_mode2_sectors@         -> 'readXaModeSectors'
+* @cdio_read_sector@                -> 'readSector'
+* @cdio_read_sectors@               -> 'readSectors'
+
+
+= "Sound.Libcdio.Read.Data"
+Each of the single-sector @read*@ aliases have been removed for consistency.
+
+* 'ReadMode'                        (removed; unnecessary low-level detail)
+
+* 'readAudioSectors'                -> 'Sound.Libcdio.Read.Data.readAudio'
+* 'readBytes'                       -> 'Sound.Libcdio.Read.Data.readRaw' (note that the count is now the number of /sectors/ rather than bytes)
+* 'readDataModeSectors'             -> 'Sound.Libcdio.Read.Data.readData'
+* 'readDataSectors'                 (removed; unnecessary low-level detail)
+* 'readXaModeSectors'               -> 'Sound.Libcdio.Read.Data.readXa'
+-}
+module Foreign.Libcdio.Read
+    ( -- * Types
+      ReadMode ( .. )
+    , Whence ( .. )
+      -- * Functions
+      -- ** Raw
+    , seek
+    , readBytes
+      -- ** Sector
+    , readSector, readSectors
+    , readAudioSector, readAudioSectors
+    , readDataSectors
+    , readDataModeSector, readDataModeSectors
+    , readXaModeSector, readXaModeSectors
+    ) where
+
+
+import qualified Control.Monad as N
+
+import qualified Data.ByteString as BS
+import qualified Data.Maybe as Y
+
+import qualified Foreign.C.Types as C
+import qualified Foreign.Ptr as C
+import qualified Foreign.Storable as S
+
+import qualified Foreign.Marshal.Alloc as M
+import qualified Foreign.Marshal.Utils as M
+
+import Foreign.Libcdio.Device
+import Foreign.Libcdio.Marshal
+import Foreign.Libcdio.Types.Enums
+import Foreign.Libcdio.Types.Internal
+
+
+-- | Reposition the read pointer in the 'Cdio' session for a future call to
+-- 'readBytes'.
+seek :: Cdio -> Int -> Whence -> IO (Either DriverReturnCode Word)
+seek c o w = do
+    o' <- withCdio c $ \c' -> seek' c' (fromIntegral o) (fromIntegral $ fromEnum w)
+    return . fmap fromIntegral $ maybe (Left Uninitialized) errorOrInt o'
+
+foreign import ccall safe "cdio/compat/read.h cdio_lseek"
+  seek' :: C.Ptr Cdio -> C.CLong -> C.CInt -> IO C.CLong
+
+
+collapseReturnCode :: Maybe DriverReturnCode -> a -> Either DriverReturnCode a
+collapseReturnCode (Just Success) a = Right a
+collapseReturnCode (Just e) _ = Left e
+collapseReturnCode Nothing _ = Left Uninitialized
+
+
+withCdioByteString
+    :: Cdio
+    -> (C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> IO a)
+        -- ^ A foreign function which will read a given number of bytes into a
+        -- referenced buffer, potentially returning a numeric error code.  Note
+        -- that this marshalling /will/ try to free the inner pointer of the
+        -- second argument, so the function should @malloc@ a temporary value
+        -- accordingly.
+    -> IO (Maybe a, Maybe BS.ByteString)
+withCdioByteString c g = M.alloca $ \bs' -> M.alloca $ \s' -> do
+    a <- withCdio c $ \c' -> g c' bs' s'
+    bs <- peekByteStringLen bs' s'
+    p <- S.peek bs'
+    N.unless (p == C.nullPtr) $ M.free p
+    return (a, bs)
+
+-- | Marshalling function for handling read instructions operating on a given
+-- number of whole-sector blocks.
+readCdioSectors
+    :: Cdio
+    -> (C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> IO C.CInt)
+    -> IO (Either DriverReturnCode BS.ByteString)
+readCdioSectors c f = do
+    (r, bs) <- withCdioByteString c f
+    return $ collapseReturnCode (toEnum . fromIntegral <$> r) (Y.fromMaybe BS.empty bs)
+
+
+-- | Read a given number of bytes from the disc.  With data of a known
+-- structure, use 'readSectors' or similar instead, which /don't/ include the
+-- headers and footers described in "Foreign.Libcdio.Sector".
+readBytes :: Cdio -> Word -> IO (Maybe BS.ByteString)
+readBytes c l = fmap snd <$> withCdioByteString c $ \c' bs' s' ->
+    readBytes' c' bs' s' $ fromIntegral l
+
+foreign import ccall safe "cdio/compat/read.h read_bytes"
+  readBytes' :: C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> C.CULong -> IO ()
+
+
+-- | Read the data contained in a specific sector from the disc.
+readSector :: Cdio -> Lsn -> ReadMode -> IO (Either DriverReturnCode BS.ByteString)
+readSector c o m = readCdioSectors c $ \c' bs' s' ->
+    readSector' c' bs' s' o (fromIntegral $ fromEnum m)
+
+foreign import ccall safe "cdio/compat/read.h read_sector"
+  readSector' :: C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> Lsn -> C.CInt -> IO C.CInt
+
+-- | Read the data contained in the given number of sectors from the disc,
+-- beginning with the specified sector.
+readSectors :: Cdio -> Lsn -> ReadMode -> Word -> IO (Either DriverReturnCode BS.ByteString)
+readSectors c o m l = readCdioSectors c $ \c' bs' s' ->
+    readSectors' c' bs' s' o (fromIntegral $ fromEnum m) (fromIntegral l)
+
+foreign import ccall safe "cdio/compat/read.h read_sectors"
+  readSectors' :: C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> Lsn -> C.CInt -> C.CUInt -> IO C.CInt
+
+
+-- | Similar to calling 'readSector' with 'AudioMode', depending on the driver
+-- implementation.
+readAudioSector :: Cdio -> Lsn -> IO (Either DriverReturnCode BS.ByteString)
+readAudioSector c o = readCdioSectors c $ \c' bs' s' ->
+    readAudioSector' c' bs' s' o
+
+foreign import ccall safe "cdio/compat/read.h read_audio_sector"
+  readAudioSector' :: C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> Lsn -> IO C.CInt
+
+-- | Similar to calling 'readSectors' with 'AudioMode', depending on the driver
+-- implementation.
+readAudioSectors :: Cdio -> Lsn -> Word -> IO (Either DriverReturnCode BS.ByteString)
+readAudioSectors c o l = readCdioSectors c $ \c' bs' s' ->
+    readAudioSectors' c' bs' s' o $ fromIntegral l
+
+foreign import ccall safe "cdio/compat/read.h read_audio_sectors"
+  readAudioSectors' :: C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> Lsn -> C.CUInt -> IO C.CInt
+
+
+-- | Read the raw data from a given number of sectors on the disc, beginning
+-- with the specified sector.
+readDataSectors
+    :: Cdio
+    -> Lsn
+    -> Word
+        -- ^ Sector size (e.g. 'Foreign.Libcdio.Sector.dataSize' or
+        -- 'Foreign.Libcdio.Sector.dataSizeRawXa').
+    -> Word
+        -- ^ Number of sectors to read.
+    -> IO (Either DriverReturnCode BS.ByteString)
+readDataSectors c o z l = readCdioSectors c $ \c' bs' s' ->
+    readDataSectors' c' bs' s' o (fromIntegral z) (fromIntegral l)
+
+foreign import ccall safe "cdio/compat/read.h read_data_sectors"
+  readDataSectors' :: C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> Lsn -> C.CUShort -> C.CUInt -> IO C.CInt
+
+
+-- | Similar to calling 'readSector', depending on the driver implementation.
+readDataModeSector
+    :: Cdio
+    -> Lsn
+    -> Bool
+        -- ^ If 'True' Form 2, otherwise Form 1 (see "Foreign.Libcdio.Sector").
+    -> IO (Either DriverReturnCode BS.ByteString)
+readDataModeSector c o m = readCdioSectors c $ \c' bs' s' ->
+    readDataModeSector' c' bs' s' o $ M.fromBool m
+
+foreign import ccall safe "cdio/compat/read.h read_mode1_sector"
+  readDataModeSector' :: C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> Lsn -> C.CUChar -> IO C.CInt
+
+-- | Similar to calling 'readSectors', depending on the driver implementation.
+readDataModeSectors
+    :: Cdio
+    -> Lsn
+    -> Bool
+        -- ^ If 'True' Form 2, otherwise Form 1 (see "Foreign.Libcdio.Sector").
+    -> Word
+    -> IO (Either DriverReturnCode BS.ByteString)
+readDataModeSectors c o m l = readCdioSectors c $ \c' bs' s' ->
+    readDataModeSectors' c' bs' s' o (M.fromBool m) (fromIntegral l)
+
+foreign import ccall safe "cdio/compat/read.h read_mode1_sectors"
+  readDataModeSectors' :: C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> Lsn -> C.CUChar -> C.CUInt -> IO C.CInt
+
+
+-- | Similar to calling 'readSector', depending on the driver implementation.
+readXaModeSector
+    :: Cdio
+    -> Lsn
+    -> Bool
+        -- ^ If 'True' Form 2, otherwise Form 1 (see "Foreign.Libcdio.Sector").
+    -> IO (Either DriverReturnCode BS.ByteString)
+readXaModeSector c o m = readCdioSectors c $ \c' bs' s' ->
+    readXaModeSector' c' bs' s' o $ M.fromBool m
+
+foreign import ccall safe "cdio/compat/read.h read_mode2_sector"
+  readXaModeSector' :: C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> Lsn -> C.CUChar -> IO C.CInt
+
+-- | Similar to calling 'readSectors', depending on the driver implementation.
+readXaModeSectors
+    :: Cdio
+    -> Lsn
+    -> Bool
+        -- ^ If 'True' Form 2, otherwise Form 1 (see "Foreign.Libcdio.Sector").
+    -> Word
+    -> IO (Either DriverReturnCode BS.ByteString)
+readXaModeSectors c o m l = readCdioSectors c $ \c' bs' s' ->
+    readXaModeSectors' c' bs' s' o (M.fromBool m) (fromIntegral l)
+
+foreign import ccall safe "cdio/compat/read.h read_mode2_sectors"
+  readXaModeSectors' :: C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> Lsn -> C.CUChar -> C.CUInt -> IO C.CInt
diff --git a/src/Foreign/Libcdio/Sector.hs b/src/Foreign/Libcdio/Sector.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Libcdio/Sector.hs
@@ -0,0 +1,674 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+{-|
+Description:    Values related to on-disc data layout: track boundaries, sector sizes, address formats, etc.
+
+Copyright:      (c) 2018-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+The bulk of this module deals with the sizes of various parts of disc sectors,
+and so a brief description of each is likely helpful; for more information, see
+the libcdio user guide, or any of the other various documentation that people
+have written.  Depending on the accuracy required, multiple methods of encoding
+data onto discs were developed enabling different degrees of error detection
+and recovery.  For ease of implementation, these check regions are spaced
+evenly throughout the data, effectively dividing it into blocks of 'sectorSize'
+bytes.  The inner structure of each block is thus:
+
+= Sector layout
+
+== Audio
+
+As audio CDs are intended to be listened to by human ears, often in noisy
+environments, byte-perfect fidelity was deemed unnecessary; data fills the
+entire sector without leaving room for checksums or synchronization points.
+This structure is more technically described as "CD-DA" (Digital Audio).
+
+@
+|- 'sectorSize' -|
+@
+
+== Data (Mode 1)
+
+The original structure described in the /Yellow Book/ standard.  Mode 1, Form 1
+is notably the layout used for CD-ROMs.  It would be most correct to describe
+these as "Mode 1" and "Mode 2" with no reference to form, but the libcdio
+documentation has adopted the practice below as a parallel to the XA names.
+
+=== Mode 1, Form 1
+
+@
+|------------------------------------ 'sectorSize' -------------------------------------|
+ 'syncSize' + 'headerSize' + __'dataSize'__ + 'errorDetectionSize' + 'padSize' + 'errorCorrectionSize'
+           |------------------------------- 'syncedSize' -------------------------------|
+                                   |-------------------- 'tailSize' --------------------|
+@
+
+=== Mode 1, Form 2
+
+@
+|------------ 'sectorSize' -----------|
+ 'syncSize' + 'headerSize' + __'dataSizeRaw'__
+           |------ 'syncedSize' ------|
+@
+
+
+== XA (Mode 2)
+
+Developed as a later extension to the Mode 1, Form 2 (technically just "Mode
+2") standard above to allow different data to be interleaved.
+
+=== Mode 2, Form 1
+
+@
+|--------------------------------------- 'sectorSize' ----------------------------------------|
+ 'syncSize' + 'headerSize' + 'subheaderSize' + __'dataSize'__ + 'errorDetectionSize' + 'errorCorrectionSize'
+|---------- 'syncHeaderSizeXa' ---------|            |-------------- 'tailSizeXa' --------------|
+           |------ 'headerSizeXa' ------|
+           |---------------------------------- 'syncedSize' ----------------------------------|
+                        |--------------------------- 'dataSizeRaw' ---------------------------|
+@
+
+=== Mode 2, Form 2
+
+@
+|--------------------------- 'sectorSize' --------------------------|
+ 'syncSize' + 'headerSize' + 'subheaderSize' + __'dataSizeRawXa'__ + 'padSizeXa'
+|---------- 'syncHeaderSizeXa' ---------|
+           |------ 'headerSizeXa' ------|
+           |--------------------- 'syncedSize' ---------------------|
+                        |-------------- 'dataSizeRaw' --------------|
+                        |----- 'taggedDataSizeRaw' -----|
+@
+
+
+= @sector.h@
+
+== Defines
+* @CDIO_CD_CHUNK_SIZE@              -> 'chunkSize'
+* @CDIO_CD_ECC_SIZE@                -> 'errorCorrectionSize'
+* @CDIO_CD_EDC_SIZE@                -> 'errorDetectionSize'
+* @CDIO_CD_FRAMESIZE@               -> 'dataSize'
+* @CDIO_CD_FRAMESIZE_RAW@           -> 'sectorSize'
+* @CDIO_CD_FRAMESIZE_RAW0@          -> 'dataSizeRaw'
+* @CDIO_CD_FRAMESIZE_RAW1@          -> 'syncedSize'
+* @CDIO_CD_FRAMESIZE_RAWER@         -> 'sectorSizeMax'
+* @CDIO_CD_FRAMESIZE_SUB@           -> 'framesizeSub'
+* @CDIO_CD_FRAMES_PER_MIN@          -> 'framesPerMin'
+* @CDIO_CD_FRAMES_PER_SEC@          -> 'framesPerSec'
+* @CDIO_CD_HEADER_SIZE@             -> 'headerSize'
+* @CDIO_CD_M1F1_ZERO_SIZE@          -> 'padSize'
+* @CDIO_CD_MAX_LSN@                 (removed; identical to @'maxBound' :: 'Lsn'@)
+* @CDIO_CD_MAX_SESSIONS@            -> 'maxSessions'
+* @CDIO_CD_MINS@                    -> 'cdMins'
+* @CDIO_CD_MIN_LSN@                 (removed; identical to @'minBound' :: 'Lsn'@)
+* @CDIO_CD_MIN_SESSION_NO@          -> 'minSessionNo'
+* @CDIO_CD_NUM_OF_CHUNKS@           -> 'chunksPerSector'
+* @CDIO_CD_SECS_PER_MIN@            -> 'secsPerMin'
+* @CDIO_CD_SUBHEADER_SIZE@          -> 'subheaderSize'
+* @CDIO_CD_SYNC_SIZE@               -> 'syncSize'
+* @CDIO_CD_XA_HEADER@               -> 'headerSizeXa'
+* @CDIO_CD_XA_SYNC_HEADER@          -> 'syncHeaderSizeXa'
+* @CDIO_CD_XA_TAIL@                 -> 'tailSizeXa'
+* @CDIO_POSTGAP_SECTORS@            -> 'postgapSectors'
+* @CDIO_PREGAP_SECTORS@             -> 'pregapSectors'
+* @M2F2_SECTOR_SIZE@                -> 'dataSizeRawXa'
+* @M2RAW_SECTOR_SIZE@               (removed; identical to 'dataSizeRaw')
+* @M2SUB_SECTOR_SIZE@               -> 'taggedDataSizeRaw'
+* @msf_t_SIZEOF@                    (removed; structural constant not required for Haskell)
+
+== Types
+* @cdio_cd_minutes_sectors@         (removed; most values were simple calculations on @CDIO_CD_FRAMES_PER_MIN@, which can be done manually)
+
+    - @CDIO_CD_MAX_SECTORS@         -> 'maxSectors'
+
+* @cdio_subchannel@                 -> 'SubchannelData'
+
+    - @CDIO_SUBCHANNEL_SUBQ_DATA@   -> 'QChannelData'
+
+* @flag_t@                          -> 'Flags' and 'Flag'
+
+    - @SCMS@                        -> 'SerialCopyManagement'
+
+== Symbols
+* @CDIO_SECTOR_SYNC_HEADER@         -> 'sectorSyncHeader'
+* @cdio_lba_to_lsn@                 -> 'lbaToLsn'
+* @cdio_lba_to_msf@                 -> 'lbaToMsf'
+* @cdio_lba_to_msf_str@             -> 'lbaToMsfStr'
+* @cdio_lsn_to_lba@                 -> 'lsnToLba'
+* @cdio_lsn_to_msf@                 -> 'lsnToMsf'
+* @cdio_msf_to_lba@                 -> 'msfToLba'
+* @cdio_msf_to_lsn@                 -> 'msfToLsn'
+* @cdio_msf_to_str@                 -> 'msfToStr'
+
+
+= "Sound.Libcdio.Read.Data"
+
+* 'Flag'                            (currently removed; unused in the translated portion of the interface)
+* 'Flags'                           (currently removed; unused in the translated portion of the interface)
+* 'Lba'                             (removed; only one address format is needed, and 'Lsn' is more widespread)
+* 'Msf'                             (removed; only one address format is needed, and timestamps can be confusing for non-audio data)
+* 'SubchannelData'                  (currently removed; unused in the translated portion of the interface)
+
+* 'cdMins'                          -> 'Sound.Libcdio.Read.Data.maxCdMinutes'
+* 'chunkSize'                       (removed; unnecessary low-level detail)
+* 'chunksPerSector'                 (removed; unnecessary low-level detail)
+* 'framesizeSub'                    (removed; unnecessary low-level detail)
+* 'lbaToLsn'                        (removed; only 'Lsn' is used in @Sound@)
+* 'lbaToMsf'                        (removed; only 'Lsn' is used in @Sound@)
+* 'lbaToMsfStr'                     -> 'Sound.Libcdio.Read.Data.audioTimestamp'
+* 'lsnToLba'                        (removed; only 'Lsn' is used in @Sound@)
+* 'lsnToMsf'                        (removed; only 'Lsn' is used in @Sound@)
+* 'maxSectors'                      -> 'Sound.Libcdio.Read.Data.maxSectors'
+* 'maxSessions'                     (removed; explicit session handling not yet implemented by libcdio)
+* 'minSessionNo'                    (removed; explicit session handling not yet implemented by libcdio)
+* 'msfToLba'                        (removed; only 'Lsn' is used in @Sound@)
+* 'msfToLsn'                        (removed; only 'Lsn' is used in @Sound@)
+* 'msfToStr'                        (removed; only 'Lsn' is used in @Sound@)
+* 'postgapSectors'                  -> 'Sound.Libcdio.Read.Data.defaultPostgapSectors'
+* 'pregapSectors'                   -> 'Sound.Libcdio.Read.Data.defaultPregapSectors'
+* 'secsPerMin'                      (removed; real-world constant)
+* 'sectorSyncHeader'                (removed; unnecessary low-level detail)
+* 'framesPerMin'                    (removed; simple arithmatic of 'framesPerSec'
+
+All size constants (e.g. 'sectorSize') likewise removed as unnecessary.
+-}
+module Foreign.Libcdio.Sector
+    ( -- * Types
+      SubchannelData ( .. )
+    , Flags
+    , Flag ( .. )
+    , Lba
+    , Lsn
+    , Msf ( .. )
+      -- * Conversions
+    , lbaToLsn
+    , lsnToLba
+    , lbaToMsf
+    , msfToLba
+    , lsnToMsf
+    , msfToLsn
+    , lbaToMsfStr
+    , msfToStr
+      -- * Basic counts
+    , chunkSize
+    , minSessionNo, maxSessions
+    , pregapSectors, postgapSectors
+    , maxSectors
+    , framesizeSub
+      -- ** Units of time
+    , chunksPerSector
+    , framesPerSec
+    , secsPerMin
+    , framesPerMin
+    , cdMins
+      -- * Sector blocks
+    , sectorSize
+    , syncedSize
+    , sectorSizeMax
+      -- ** Headers
+    , sectorSyncHeader
+    , syncSize
+    , headerSize
+    , subheaderSize
+    , headerSizeXa
+    , syncHeaderSizeXa
+      -- ** Data
+    , dataSize
+    , dataSizeRaw
+    , dataSizeRawXa
+    , taggedDataSizeRaw
+      -- ** Error correction
+    , errorDetectionSize
+    , errorCorrectionSize
+    , padSize
+    , padSizeXa
+    , tailSize
+    , tailSizeXa
+    ) where
+
+
+import qualified Data.Array.BitArray as A
+import qualified Data.ByteString as BS
+
+import qualified Foreign.C.String as C
+import qualified Foreign.C.Types as C
+import qualified Foreign.Ptr as C
+
+import qualified Foreign.Marshal.Alloc as M
+import qualified Foreign.Marshal.Utils as M
+import qualified Foreign.Storable as S
+
+import qualified System.IO.Unsafe as IO.Unsafe
+
+
+import Foreign.Libcdio.Marshal
+import Foreign.Libcdio.Types.Enums
+import Foreign.Libcdio.Types.Internal
+import Foreign.Libcdio.Types.Offsets
+import Foreign.Libcdio.Util
+
+
+-- | The collection of metadata describing a particular track.
+type Flags = A.BitArray Flag
+
+
+-- | The number of sectors spanned by a track pre-gap by default.
+pregapSectors :: Word
+pregapSectors = fromIntegral pregapSectors'
+
+foreign import ccall safe "cdio/compat/sector.h pregap_sectors"
+  pregapSectors' :: C.CUInt
+
+-- | The number of sectors spanned by a track post-gap by default.
+postgapSectors :: Word
+postgapSectors = fromIntegral postgapSectors'
+
+foreign import ccall safe "cdio/compat/sector.h postgap_sectors"
+  postgapSectors' :: C.CUInt
+
+
+-- | The typical maximum length of a disc, though it's not a strict limit.
+cdMins :: Word
+cdMins = fromIntegral cdMins'
+
+foreign import ccall safe "cdio/compat/sector.h cd_mins"
+  cdMins' :: C.CUInt
+
+-- | The number of seconds in a minute.
+secsPerMin :: Word
+secsPerMin = fromIntegral secsPerMin'
+
+foreign import ccall safe "cdio/compat/sector.h secs_per_min"
+  secsPerMin' :: C.CUInt
+
+-- | The number of disc sectors comprising a second of audio data.
+framesPerSec :: Word
+framesPerSec = fromIntegral framesPerSec'
+
+foreign import ccall safe "cdio/compat/sector.h frames_per_sec"
+  framesPerSec' :: C.CUInt
+
+-- | The number of bytes in a disc sector's sync header.
+syncSize :: Word
+syncSize = fromIntegral syncSize'
+
+foreign import ccall safe "cdio/compat/sector.h sync_size"
+  syncSize' :: C.CUInt
+
+-- | The size of the smallest meaningful segment of data, in bytes.
+chunkSize :: Word
+chunkSize = fromIntegral chunkSize'
+
+foreign import ccall safe "cdio/compat/sector.h chunk_size"
+  chunkSize' :: C.CUInt
+
+-- | The number of data chunks comprising a disc sector.
+chunksPerSector :: Word
+chunksPerSector = fromIntegral chunksPerSector'
+
+foreign import ccall safe "cdio/compat/sector.h chunks_per_frame"
+  chunksPerSector' :: C.CUInt
+
+-- | The size of a segment of data in the subchannel, in bytes.
+framesizeSub :: Word
+framesizeSub = fromIntegral framesizeSub'
+
+foreign import ccall safe "cdio/compat/sector.h framesize_sub"
+  framesizeSub' :: C.CUInt
+
+
+-- | The size of the address of a data sector, in bytes.
+headerSize :: Word
+headerSize = fromIntegral headerSize'
+
+foreign import ccall safe "cdio/compat/sector.h header_size"
+  headerSize' :: C.CUInt
+
+-- | The size of the subheader of an XA sector, in bytes.
+subheaderSize :: Word
+subheaderSize = fromIntegral subheaderSize'
+
+foreign import ccall safe "cdio/compat/sector.h subheader_size"
+  subheaderSize' :: C.CUInt
+
+-- | The size of the EDC error correction segment, in bytes.
+errorDetectionSize :: Word
+errorDetectionSize = fromIntegral errorDetectionSize'
+
+foreign import ccall safe "cdio/compat/sector.h edc_size"
+  errorDetectionSize' :: C.CUInt
+
+-- | The amount of padding between the EDC and ECC segments in a Mode 1 sector,
+-- in bytes.
+padSize :: Word
+padSize = fromIntegral padSize'
+
+foreign import ccall safe "cdio/compat/sector.h mode1_pad_size"
+  padSize' :: C.CUInt
+
+-- | The size of the ECC error correction segment, in bytes.
+errorCorrectionSize :: Word
+errorCorrectionSize = fromIntegral errorCorrectionSize'
+
+foreign import ccall safe "cdio/compat/sector.h ecc_size"
+  errorCorrectionSize' :: C.CUInt
+
+
+-- | The amount of data which may be contained in a disc sector /with/ error
+-- correction, in bytes.
+dataSize :: Word
+dataSize = fromIntegral dataSize'
+
+foreign import ccall safe "cdio/compat/sector.h framesize"
+  dataSize' :: C.CUInt
+
+-- | The size of an entire disc sector, in bytes.
+sectorSize :: Word
+sectorSize = fromIntegral sectorSize'
+
+foreign import ccall safe "cdio/compat/sector.h framesize_raw"
+  sectorSize' :: C.CUInt
+
+-- | The maximum number of bytes that may be returned from a single call.
+sectorSizeMax :: Word
+sectorSizeMax = fromIntegral sectorSizeMax'
+
+foreign import ccall safe "cdio/compat/sector.h framesize_rawer"
+  sectorSizeMax' :: C.CUInt
+
+-- | The size of a disc sector in bytes, ignoring the sync header.
+syncedSize :: Word
+syncedSize = fromIntegral syncedSize'
+
+foreign import ccall safe "cdio/compat/sector.h framesize_raw1"
+  syncedSize' :: C.CUInt
+
+-- | The amount of data which may be contained in a disc sector /without/ error
+-- correction, in bytes.
+dataSizeRaw :: Word
+dataSizeRaw = fromIntegral dataSizeRaw'
+
+foreign import ccall safe "cdio/compat/sector.h framesize_raw0"
+  dataSizeRaw' :: C.CUInt
+
+
+-- | The total size of the meaningful XA sector headers, in bytes.
+headerSizeXa :: Word
+headerSizeXa = fromIntegral headerSizeXa'
+
+foreign import ccall safe "cdio/compat/sector.h header_size_xa"
+  headerSizeXa' :: C.CUInt
+
+-- | The total size of all data sector error correction segments, in bytes.
+tailSize :: Word
+tailSize = errorDetectionSize + padSize + errorCorrectionSize
+
+-- | The total size of all XA sector error correction segments, in bytes.
+tailSizeXa :: Word
+tailSizeXa = fromIntegral tailSizeXa'
+
+foreign import ccall safe "cdio/compat/sector.h tail_size_xa"
+  tailSizeXa' :: C.CUInt
+
+-- | The total size of all headers in an XA sector, including the sync marker.
+syncHeaderSizeXa :: Word
+syncHeaderSizeXa = fromIntegral syncHeaderSizeXa'
+
+foreign import ccall safe "cdio/compat/sector.h sync_size_xa"
+  syncHeaderSizeXa' :: C.CUInt
+
+-- | The amount of padding at the end of an XA sector without error correction,
+-- in bytes.
+padSizeXa :: Word
+padSizeXa = dataSizeRaw - taggedDataSizeRaw
+
+
+-- | The byte sequence used to mark the start of a disc sector, to allow
+-- correcting drift while reading.
+sectorSyncHeader :: BS.ByteString
+sectorSyncHeader = IO.Unsafe.unsafePerformIO $
+    BS.packCStringLen (sectorSyncHeader', fromIntegral syncSize)
+
+foreign import ccall safe "cdio/compat/sector.h sector_sync_header"
+  sectorSyncHeader' :: C.Ptr C.CChar
+
+
+-- | The amount of data contained in an XA sector without error correction, in
+-- bytes.
+dataSizeRawXa :: Word
+dataSizeRawXa = fromIntegral dataSizeRawXa'
+
+foreign import ccall safe "cdio/compat/sector.h data_size_xa"
+  dataSizeRawXa' :: C.CUInt
+
+-- | The size of tagged data (counting the subheader) contained in an XA sector
+-- without error correction, in bytes.
+taggedDataSizeRaw :: Word
+taggedDataSizeRaw = fromIntegral taggedDataSizeRaw'
+
+foreign import ccall safe "cdio/compat/sector.h tagged_size_xa"
+  taggedDataSizeRaw' :: C.CUInt
+
+
+-- | How many sessions are allowed on a disc.
+maxSessions :: Word
+maxSessions = fromIntegral maxSessions'
+
+foreign import ccall safe "cdio/compat/sector.h max_session"
+  maxSessions' :: C.CUInt
+
+-- | The smallest session number on a disc.
+minSessionNo :: Word
+minSessionNo = fromIntegral minSessionNo'
+
+foreign import ccall safe "cdio/compat/sector.h min_session"
+  minSessionNo' :: C.CUInt
+
+
+-- | A shortcut for calculating @'framesPerSec' * 'secsPerMin'@
+framesPerMin :: Word
+framesPerMin = fromIntegral framesPerMin'
+
+foreign import ccall safe "cdio/compat/sector.h frames_per_min"
+  framesPerMin' :: C.CUInt
+
+
+-- | The maximum number of sectors allowed to be stored on a disc.
+maxSectors :: Word
+maxSectors = fromIntegral maxSectors'
+
+foreign import ccall safe "cdio/compat/sector.h max_sectors"
+  maxSectors' :: C.CUInt
+
+
+-- | Minute\/second\/frame structure for addresses.  Generally only makes sense
+-- for audio discs.
+data Msf = Msf
+    { minute :: Word
+    , second :: Word
+        -- ^ 'secsPerMin'
+    , frame :: Word
+        -- ^ 'framesPerSec'
+    }
+  deriving ( Show, Read )
+instance Eq Msf where
+    l == r = compare l r == EQ
+instance Ord Msf where
+    compare l r = case minute l' `compare` minute r' of
+        EQ -> case second l' `compare` second r' of
+            EQ -> frame l' `compare` frame r'
+            x -> x
+        x -> x
+      where l' = normalize l
+            r' = normalize r
+            normalize msf@(Msf m s f)
+                | f >= framesPerSec = normalize $ Msf m (s + div f framesPerSec) (mod f framesPerSec)
+                | s >= secsPerMin = Msf (m + div s secsPerMin) (mod s secsPerMin) f
+                | otherwise = msf
+instance Bounded Msf where
+    minBound = Msf 0 0 0
+    maxBound = Msf maxBound (secsPerMin - 1) (framesPerSec - 1)
+instance S.Storable Msf where
+    sizeOf _    = msfSizeOf
+    alignment _ = msfAlign
+    peek c = do
+        m <- S.peekByteOff c msfM
+        s <- S.peekByteOff c msfS
+        f <- S.peekByteOff c msfF
+        return $ Msf (fromBcd8 m) (fromBcd8 s) (fromBcd8 f)
+    poke c hs = do
+        S.pokeByteOff c msfM . toBcd8 $ minute hs
+        S.pokeByteOff c msfS . toBcd8 $ second hs
+        S.pokeByteOff c msfF . toBcd8 $ frame hs
+instance Enum Msf where
+    fromEnum msf = fromInteger
+        $ toInteger (frame msf)
+        + toInteger (second msf) * fromIntegral framesPerSec
+        + toInteger (minute msf) * fromIntegral framesPerMin
+    toEnum i = Msf
+        { minute = div i' framesPerMin
+        , second = flip mod secsPerMin $ div i' framesPerSec
+        , frame = mod i' framesPerSec
+        }
+      where i' = fromIntegral i
+    pred (Msf 0 0 0) = error "Enum.pred(Msf): tried to take `pred' of minBound"
+    pred (Msf m s f)
+        | f >= framesPerSec = pred $ Msf m (s + div f framesPerSec) (mod f framesPerSec)
+        | s >= secsPerMin = pred $ Msf (m + div s secsPerMin) (mod s secsPerMin) f
+        | f == 0 && s == 0 = Msf (m - 1) (secsPerMin - 1) (framesPerSec - 1)
+        | f == 0 = Msf m (s - 1) (framesPerSec - 1)
+        | otherwise = Msf m s (f - 1)
+    succ msf@(Msf m s f)
+        | msf >= maxBound = error "Enum.succ(Msf): tried to take `succ' of maxBound"
+        | otherwise = let (fd, fm) = overflow f 1 framesPerSec
+                          (sd, sm) = overflow s fd secsPerMin
+                      in Msf (m + sd) sm fm
+      where -- Relies on unsigned type, and @y + b < maxBound@
+            overflow x y b
+                | x > maxBound - y = (div (x - b + y) b + 1, mod (x - b + y) b)
+                | otherwise = (div (x + y) b, mod (x + y) b)
+
+{- Use @sizeOf Msf@
+msfSizeof :: Word
+msfSizeof = fromIntegral msfSizeof'
+
+foreign import ccall safe "cdio/compat/sector.h sizeof_msf_const"
+  msfSizeof' :: C.CSize
+-}
+
+
+{- Never used after definition.
+-- | Address in one of the two primary address formats.
+data CdromAddr
+    = MsfAddr Msf
+    | LbaAddr Lba
+  deriving ( Eq, Show, Read, Ord )
+-- | Note that, while the 'peek' implementation attempts to detect which form
+-- the address takes, it may get it wrong and read a 'Msf' address as an 'Lba'
+-- or vice versa.  If the type is otherwise known, it may be better to read
+-- the pointer as that type directly, and wrap into the union manually.
+instance S.Storable CdromAddr where
+    sizeOf _    = adrSizeOf
+    alignment _ = adrAlign
+    peek c = do
+        msf <- S.peek $ C.castPtr c
+        lba <- S.peek $ C.castPtr c
+        -- Barring uncleared bits, an LBA has an extra byte.
+        if mod 0x100 lba /= 0
+           || second msf >= secsPerMin
+           || frame msf >= framesPerSec
+        then return $ LbaAddr lba
+        else return $ MsfAddr msf
+    poke c (MsfAddr hs) = S.poke (C.castPtr c) hs
+    poke c (LbaAddr hs) = S.poke (C.castPtr c) hs
+-}
+
+
+-- | Print a logical address as the corresponding timestamp, assuming audio
+-- data.
+lbaToMsfStr :: Lba -> String
+lbaToMsfStr l = IO.Unsafe.unsafePerformIO $
+    lbaToMsfStr' (fromIntegral l) >>= peekFString
+
+foreign import ccall safe "cdio/compat/sector.h cdio_lba_to_msf_str"
+  lbaToMsfStr' :: CLba -> IO C.CString
+
+-- | Print a disc timestamp in the standard "MM:SS:FF" format.
+msfToStr :: Msf -> String
+msfToStr msf = IO.Unsafe.unsafePerformIO $
+    M.with msf msfToStr' >>= C.peekCString
+
+foreign import ccall safe "cdio/compat/sector.h cdio_msf_to_str"
+  msfToStr' :: C.Ptr Msf -> IO C.CString
+
+-- | Convert an LBA address into the corresponding LSN.
+lbaToLsn :: Lba -> Lsn
+lbaToLsn = fromIntegral . lbaToLsn' . fromIntegral
+
+-- C erroneously returns @lba_t@.
+foreign import ccall safe "cdio/compat/sector.h cdio_lba_to_lsn"
+  lbaToLsn' :: CLba -> CLba
+
+-- | Convert an LBA address into the corresponding timestamp, assuming audio
+-- data.
+lbaToMsf :: Lba -> Msf
+lbaToMsf l = IO.Unsafe.unsafePerformIO . M.alloca $ \m' ->
+    lbaToMsf' (fromIntegral l) m' >> S.peek m'
+
+foreign import ccall safe "cdio/compat/sector.h cdio_lba_to_msf"
+  lbaToMsf' :: CLba -> C.Ptr Msf -> IO ()
+
+-- | Convert an LSN address into the corresponding LBA.
+lsnToLba :: Lsn -> Lba
+lsnToLba = fromIntegral . lsnToLba' . fromIntegral
+
+foreign import ccall safe "cdio/compat/sector.h cdio_lsn_to_lba"
+  lsnToLba' :: CLsn -> CLba
+
+-- | Convert an LSN address into the corresponding timestamp, assuming audio
+-- data.
+lsnToMsf :: Lsn -> Msf
+lsnToMsf l = IO.Unsafe.unsafePerformIO . M.alloca $ \m' ->
+    lsnToMsf' (fromIntegral l) m' >> S.peek m'
+
+foreign import ccall safe "cdio/compat/sector.h cdio_lsn_to_msf"
+  lsnToMsf' :: CLsn -> C.Ptr Msf -> IO ()
+
+-- | Convert a timestamp into the corresponding LBA address, assuming audio
+-- data.
+msfToLba :: Msf -> Lba
+msfToLba = fromIntegral . IO.Unsafe.unsafePerformIO . flip M.with msfToLba'
+
+foreign import ccall safe "cdio/compat/sector.h cdio_msf_to_lba"
+  msfToLba' :: C.Ptr Msf -> IO CLsn
+
+-- | Convert a timestamp into the corresponding LSN address, assuming audio
+-- data.
+msfToLsn :: Msf -> Lsn
+msfToLsn = fromIntegral . IO.Unsafe.unsafePerformIO . flip M.with msfToLsn'
+
+foreign import ccall safe "cdio/compat/sector.h cdio_msf_to_lsn"
+  msfToLsn' :: C.Ptr Msf -> IO CLsn
+
+{- Not exported
+-- | Convert a split timestamp into the corresponding LBA address, assuming
+-- audio data.
+msf3ToLba :: Word -> Word -> Word -> Lba
+msf3ToLba m s f = fromIntegral $ msf3ToLba' (fromIntegral m) (fromIntegral s) (fromIntegral f)
+
+foreign import ccall safe "cdio/compat/sector.h cdio_msf3_to_lba"
+  msf3ToLba' :: C.CUInt -> C.CUInt -> C.CUInt -> CLba
+
+-- | Read a timestamp in the form MM:SS:FF into the corresponding LBA address,
+-- assuming audio data.
+mmssffToLba :: String -> Maybe Lba
+mmssffToLba s = invalidLba . IO.Unsafe.unsafePerformIO $ C.withCString s mmssffToLba
+
+foreign import ccall safe "cdio/compat/sector.h cdio_mmssff_to_lba"
+  mmssffToLba' :: C.CString -> IO CLba
+-}
diff --git a/src/Foreign/Libcdio/Track.hs b/src/Foreign/Libcdio/Track.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Libcdio/Track.hs
@@ -0,0 +1,315 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+{-|
+Description:    Information-gathering on the location and form of disc tracks.
+
+Copyright:      (c) 2018-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+What many people would think of as the most important division on a CD isn't
+quite as an integral a part of the physical data layout: they are described in
+a table of contents before the first track of any recording session, and may
+have lower-resolution "echoes" in the subchannels alongside the data, but it
+would be hard to otherwise recover the track boundaries from the data itself.
+This module, then, provides the functions to retrieve that metadata from the
+table of contents and from the subchannels.
+
+
+= @track.h@
+
+== Defines
+* @CDIO_CDROM_CDI_TRACK@            (removed; only has utility in library code)
+* @CDIO_CDROM_DATA_TRACK@           (removed; only has utility in library code)
+* @CDIO_INVALID_TRACK@              (removed; handled via 'Nothing')
+* @CDIO_CDROM_LBA@                  (removed; only has utility in library code)
+* @CDIO_CDROM_LEADOUT_TRACK@        -> 'DiscLeadout'
+* @CDIO_CDROM_MSF@                  (removed; only has utility in library code)
+* @CDIO_CDROM_XA_TRACK@             (removed; only has utility in library code)
+* @CDIO_CD_MAX_TRACKS@              -> 'maxTrack'
+* @CDIO_CD_MIN_TRACK_NO@            -> 'minTrack'
+
+== Types
+* @track_flag_t@                    -> 'Maybe' 'Bool' (CDIO_TRACK_FLAG_ERROR is never used in library code)
+* @track_flags_t@                   (removed; never used in the public interface)
+* @track_format_t@                  -> 'TrackFormat'
+
+    -@TRACK_FORMAT_PSX@             -> 'FormatPlaystation'
+    -@TRACK_FORMAT_ERROR@           (removed; handled via 'Nothing')
+
+* @trackmode_t@                     (removed; never used in the public API)
+
+== Symbols
+* @cdio_get_first_track_num@        -> 'firstTrackNum'
+* @cdio_get_last_track_num@         -> 'lastTrackNum'
+* @cdio_get_track@                  -> 'trackAt'
+* @cdio_get_track_channels@         -> 'numChannels'
+* @cdio_get_track_copy_permit@      -> 'copyPermit'
+* @cdio_get_track_format@           -> 'trackFormat'
+* @cdio_get_track_green@            -> 'isGreen'
+* @cdio_get_track_isrc@             -> 'trackIsrc'
+* @cdio_get_track_last_lsn@         -> 'trackLastLsn'
+* @cdio_get_track_lba@              -> 'trackLba'
+* @cdio_get_track_lsn@              -> 'trackLsn'
+* @cdio_get_track_msf@              -> 'trackMsf'
+* @cdio_get_track_preemphasis@      -> 'hasPreemphasis'
+* @cdio_get_track_pregap_lba@       -> 'pregapLba'
+* @cdio_get_track_pregap_lsn@       -> 'pregapLsn'
+* @cdio_get_track_sec_count@        -> 'sectorCount'
+* @track_format2str@                -> 'trackFormatString'
+
+
+= "Sound.Libcdio.Track"
+
+* 'firstTrackNum'                   -> 'Sound.Libcdio.Track.firstDiscTrack'
+* 'isrcLength'                      (removed; unnecessary low-level detail)
+* 'lastTrackNum'                    -> 'Sound.Libcdio.Track.lastDiscTrack'
+* 'numChannels'                     -> 'Sound.Libcdio.Track.quadAudio'
+* 'pregapLba'                       (removed; only 'Lsn' is used in @Sound@)
+* 'pregapLsn'                       -> 'Sound.Libcdio.Track.pregap'
+* 'sectorCount'                     -> 'Sound.Libcdio.Track.totalLength'
+* 'trackFormat'                     -> 'Sound.Libcdio.Track.format'
+* 'trackIsrc'                       -> @"Sound.Libcdio.Read.Data".'Sound.Libcdio.Read.Data.isrc'@
+* 'trackLastLsn'                    -> 'Sound.Libcdio.Track.offsetEnd'
+* 'trackLba'                        (removed; only 'Lsn' is used in @Sound@)
+* 'trackLsn'                        -> 'Sound.Libcdio.Track.offset'
+* 'trackMsf'                        (removed; only 'Lsn' is used in @Sound@)
+-}
+module Foreign.Libcdio.Track
+    ( -- * Types
+      Track ( .. )
+    , TrackNum
+    , minTrack
+    , maxTrack
+    , TrackFormat ( .. )
+    , trackFormatString
+      -- * Location
+    , firstTrackNum
+    , lastTrackNum
+    , trackAt
+    , trackLba, trackLsn
+    , trackMsf
+    , trackLastLsn
+    , pregapLba, pregapLsn
+    , sectorCount
+      -- * Data
+    , trackFormat, isGreen
+    , hasPreemphasis
+    , copyPermit
+    , numChannels
+    , trackIsrc
+    , isrcLength
+    ) where
+
+
+import qualified Foreign.C.String as C
+import qualified Foreign.C.Types as C
+import qualified Foreign.Ptr as C
+
+import qualified Foreign.Marshal.Alloc as M
+import qualified Foreign.Marshal.Utils as M
+import qualified Foreign.Storable as S
+
+import qualified System.IO.Unsafe as IO.Unsafe
+
+import Foreign.Libcdio.Marshal
+import Foreign.Libcdio.Sector
+import Foreign.Libcdio.Types.Enums
+import Foreign.Libcdio.Types.Internal
+
+import Sound.Libcdio.Common
+
+
+withCdioTrack :: (C.Ptr Cdio -> CTrack -> IO a) -> (a -> Maybe b) -> Cdio -> Track -> IO (Maybe b)
+withCdioTrack f g c = fmap (>>= g) . withCdio c . flip f . withTrack
+
+
+-- | Filter out @TRACK_FORMAT_ERROR@ values to fit the 'Enum'.
+invalidFormat :: CTrackFormat -> Maybe TrackFormat
+invalidFormat = fmap (toEnum . fromIntegral) . maybeError [trackFormatError]
+
+foreign import ccall safe "cdio/compat/track.h track_format_error"
+  trackFormatError :: CTrackFormat
+
+-- | Describe the data layout of a 'Track' in a human-readable manner, as
+-- opposed to the machine representation returned by the 'Show' instance.
+trackFormatString :: TrackFormat -> String
+trackFormatString = IO.Unsafe.unsafePerformIO .
+    C.peekCString . trackFormatString' . fromIntegral . fromEnum
+
+foreign import ccall safe "cdio/compat/track.h track_format_string"
+  trackFormatString' :: CTrackFormat -> C.CString
+
+
+-- | Give up a small amount of nuance in order to use standard types.
+fromTrackFlagStatus :: Integral a => a -> Maybe Bool
+fromTrackFlagStatus c = case toEnum $ fromIntegral c of
+    FlagTrue  -> Just True
+    FlagFalse -> Just False
+    _         -> Nothing
+
+
+-- | The number of the first track on the disc.  This will almost always be 1,
+-- but that is not strictly guaranteed; the (perhaps theoretical) example is of
+-- a multi-disc set, where later discs pick the numbering back up where the
+-- previous one left off.
+-- 
+-- Returns 'Nothing' if the 'Cdio' object has already been closed, or if the
+-- disc table of contents can't be read.
+firstTrackNum :: Cdio -> IO (Maybe Track)
+firstTrackNum c = (>>= invalidTrack) <$> withCdio c firstTrackNum'
+
+foreign import ccall safe "cdio/compat/track.h cdio_get_first_track_num"
+  firstTrackNum' :: C.Ptr Cdio -> IO CTrack
+
+-- | The number of the last track on the disc.
+-- 
+-- Returns 'Nothing' if the 'Cdio' object has already been closed, or if the
+-- disc table of contents can't be read.
+lastTrackNum :: Cdio -> IO (Maybe Track)
+lastTrackNum c = (>>= invalidTrack) <$> withCdio c lastTrackNum'
+
+foreign import ccall safe "cdio/compat/track.h cdio_get_last_track_num"
+  lastTrackNum' :: C.Ptr Cdio -> IO CTrack
+
+
+-- | The track which contains the given address.
+-- 
+-- Returns 'Nothing' if the 'Cdio' object has already been closed, or if the
+-- address is beyond the written data on the disc.  Note that 'DiscLeadout' is
+-- treated as if it were a single sector long:
+-- 
+-- >>> Just endTrack <- lastTrackNum cdio
+-- >>> Just endAddr <- trackLastLsn cdio endTrack
+-- >>> trackAt cdio $ endAddr + 1
+-- Just DiscLeadout
+-- >>> trackAt cdio $ endAddr + 2
+-- Nothing
+trackAt :: Cdio -> Lsn -> IO (Maybe Track)
+trackAt c = fmap (>>= invalidTrack) . withCdio c . flip trackAt' . fromIntegral
+
+foreign import ccall safe "cdio/compat/track.h cdio_get_track"
+  trackAt' :: C.Ptr Cdio -> C.CInt -> IO CTrack
+
+
+-- | The number of channels in the given track; either 2 or 4 per the standard.
+numChannels :: Cdio -> Track -> IO (Maybe Word)
+numChannels = withCdioTrack numChannels' numChannelsError
+
+-- | The user doesn't care about which type of error it is here.
+numChannelsError :: (Integral a, Integral b) => a -> Maybe b
+numChannelsError i
+    | i < 0 = Nothing
+    | otherwise = Just $ fromIntegral i
+
+foreign import ccall safe "cdio/compat/track.h cdio_get_track_channels"
+  numChannels' :: C.Ptr Cdio -> CTrack -> IO C.CInt
+
+
+-- | Whether the track may be legally copied.
+copyPermit :: Cdio -> Track -> IO (Maybe Bool)
+copyPermit = withCdioTrack copyPermit' fromTrackFlagStatus
+
+foreign import ccall safe "cdio/compat/track.h cdio_get_track_copy_permit"
+  copyPermit' :: C.Ptr Cdio -> CTrack -> IO C.CInt
+
+
+-- | Whether preemphasis has been applied to the track for noise reduction.
+hasPreemphasis :: Cdio -> Track -> IO (Maybe Bool)
+hasPreemphasis = withCdioTrack hasPreemphasis' fromTrackFlagStatus
+
+foreign import ccall safe "cdio/compat/track.h cdio_get_track_preemphasis"
+  hasPreemphasis' :: C.Ptr Cdio -> CTrack -> IO C.CInt
+
+
+-- | The raw data structure of a track.
+trackFormat :: Cdio -> Track -> IO (Maybe TrackFormat)
+trackFormat = withCdioTrack trackFormat' invalidFormat
+
+foreign import ccall safe "cdio/compat/track.h cdio_get_track_format"
+  trackFormat' :: C.Ptr Cdio -> CTrack -> IO C.CInt
+
+
+-- | Whether the track data was stored using the Green Book (CD-i) standard.
+isGreen :: Cdio -> Track -> IO (Maybe Bool)
+isGreen c t = do
+    f <- firstTrackNum c
+    l <- lastTrackNum c
+    if Just t < f || Just t > l
+    then return Nothing
+    else withCdioTrack isGreen' (Just . M.toBool) c t
+
+foreign import ccall safe "cdio/compat/track.h cdio_get_track_green"
+  isGreen' :: C.Ptr Cdio -> CTrack -> IO C.CUChar
+
+
+-- | The address of the end of the given track.
+trackLastLsn :: Cdio -> Track -> IO (Maybe Lsn)
+trackLastLsn = withCdioTrack trackLastLsn' invalidLsn
+
+foreign import ccall safe "cdio/compat/track.h cdio_get_track_last_lsn"
+  trackLastLsn' :: C.Ptr Cdio -> CTrack -> IO C.CInt
+
+-- | The address of the start of the given track.
+trackLba :: Cdio -> Track -> IO (Maybe Lba)
+trackLba = withCdioTrack trackLba' invalidLba
+
+foreign import ccall safe "cdio/compat/track.h cdio_get_track_lba"
+  trackLba' :: C.Ptr Cdio -> CTrack -> IO C.CInt
+
+-- | The address of the start of the given track.
+trackLsn :: Cdio -> Track -> IO (Maybe Lsn)
+trackLsn = withCdioTrack trackLsn' invalidLsn
+
+foreign import ccall safe "cdio/compat/track.h cdio_get_track_lsn"
+  trackLsn' :: C.Ptr Cdio -> CTrack -> IO C.CInt
+
+-- | The address of the start of any pregap before the given track.
+pregapLba :: Cdio -> Track -> IO (Maybe Lba)
+pregapLba = withCdioTrack pregapLba' invalidLba
+
+foreign import ccall safe "cdio/compat/track.h cdio_get_track_pregap_lba"
+  pregapLba' :: C.Ptr Cdio -> CTrack -> IO C.CInt
+
+-- | The address of the start of any pregap before the given track.
+pregapLsn :: Cdio -> Track -> IO (Maybe Lsn)
+pregapLsn = withCdioTrack pregapLsn' invalidLsn
+
+foreign import ccall safe "cdio/compat/track.h cdio_get_track_pregap_lsn"
+  pregapLsn' :: C.Ptr Cdio -> CTrack -> IO C.CInt
+
+
+-- | The International Standard Recording Code the given track.  This may also
+-- be retrieved by @'Foreign.Libcdio.CdText.getField'
+-- 'Foreign.Libcdio.CdText.Isrc' $ 'Just' t@, though that references a
+-- different source and thus may not have the same return value.
+trackIsrc :: Cdio -> Track -> IO (Maybe String)
+trackIsrc c t = withCdio c (flip trackIsrc' $ withTrack t) >>=
+    maybe (return Nothing) (M.maybePeek peekFString)
+
+foreign import ccall safe "cdio/compat/track.h cdio_get_track_isrc"
+  trackIsrc' :: C.Ptr Cdio -> CTrack -> IO C.CString
+
+
+-- | The timestamp at which the given track begins.
+trackMsf :: Cdio -> Track -> IO (Maybe Msf)
+trackMsf c t = M.alloca $ \m' -> do
+    b <- withCdio c $ \c' -> trackMsf' c' (withTrack t) m'
+    case M.toBool <$> b of
+        Just True -> M.maybePeek S.peek m'
+        _ -> return Nothing
+
+foreign import ccall safe "cdio/compat/track.h cdio_get_track_msf"
+  trackMsf' :: C.Ptr Cdio -> CTrack -> C.Ptr Msf -> IO CBool
+
+
+-- | The number of sectors "assigned" to the specified track, including any in
+-- the pregap between it and the following one.
+sectorCount :: Cdio -> Track -> IO (Maybe Word)
+sectorCount = withCdioTrack sectorCount' $ maybeError [0] . fromIntegral
+
+foreign import ccall safe "cdio/compat/track.h cdio_get_track_sec_count"
+  sectorCount' :: C.Ptr Cdio -> CTrack -> IO C.CUInt
diff --git a/src/Foreign/Libcdio/Types.hs b/src/Foreign/Libcdio/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Libcdio/Types.hs
@@ -0,0 +1,115 @@
+{-# OPTIONS_HADDOCK not-home #-}
+
+{-|
+Description:    Common types used in the module-mirroring interface.
+
+Copyright:      (c) 2020-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+The original header defined a rather heterogeneous collection of typedefs,
+enums, and preprocessor macros, none of which provide much utility when
+separated from their associated functions.  Instead of following that design
+decision (which only makes sense under the C @#include@ model), this module
+instead exports every type used by the interface /without/ any constructors or
+associated functions, for any type signatures which may expose an object only
+in passing it along.
+
+
+= @types.h@
+
+== Defines
+* @CDIO_INVALID_LBA@                (removed; handled via 'Nothing')
+* @CDIO_INVALID_LSN@                (removed; handled via 'Nothing')
+* @CDIO_INVALID_SESSION@            (removed; handled via 'Nothing')
+* @CDIO_ISRC_SIZE@                  -> @"Foreign.Libcdio.Track".'isrcLength'@
+* @CDIO_MCN_SIZE@                   -> @"Foreign.Libcdio.Disc".'mcnLength'@
+* @__cd_offsetof@                   (removed; structural calculation encapsulated behind the scenes)
+
+== Types
+* @CdioDataFree_t@                  (removed; pointer handling is encapsulated behind the scenes)
+* @bitfield_t@                      (removed; accomplished with greater safety through "Data.Array.BitArray")
+* @bool_3way_t@                     -> 'Maybe' 'Bool'
+
+    - @nope@                        -> 'Just' 'False'
+    - @yep@                         -> 'Just' 'True'
+    - @dunno@                       -> 'Nothing'
+
+* @cdio_cdrom_addr@                 (removed; never used in library code)
+* @cdio_fs_anal_t@                  -> @"Foreign.Libcdio.CdTypes".'Filesystem'@, 'FilesystemClasses', and 'IsoAnalysis'
+* @cdio_isrc_t@                     (removed; never used in library code)
+* @cdio_mcn_t@                      (removed; never used in library code)
+* @cdio_track_flag@                 (removed; identical in all but name to 'Flag')
+* @cdio_utf8_t@                     (removed; 'Char' already serves this purpose)
+* @lba_t@                           -> @"Foreign.Libcdio.Sector".'Lba'@
+* @lsn_t@                           -> @"Foreign.Libcdio.Sector".'Lsn'@
+* @msf_t@                           -> @"Foreign.Libcdio.Sector".'Msf'@
+
+    - @m@                           -> 'minute'
+    - @s@                           -> 'second'
+    - @f@                           -> 'frame'
+
+* @session_t@                       (removed: only used internally)
+* @track_t@                         -> @"Foreign.Libcdio.Track".'Track'@
+
+
+= "Sound.Libcdio.Types"
+The exact collection of exported types has been changed to reflect those used
+by the higher-level interface, but the modules are otherwise very similar; many
+types are shared between the two.
+-}
+module Foreign.Libcdio.Types
+    ( -- * Disc
+      Cdio
+    , Whence
+    , Lba
+    , Lsn
+    , Msf
+    , Bcd
+    , Track
+    , TrackNum
+    , TrackFormat
+    , ReadMode
+    , SessionArg
+      -- * CdText
+    , SubchannelData
+    , Field
+    , Genre
+    , Language
+    , Flag
+    , Flags
+      -- * Hardware
+    , DriverId
+    , DriverReturnCode
+    , HardwareInfo
+    , DriveCapabilityRead
+    , DriveReadCaps
+    , DriveCapabilityWrite
+    , DriveWriteCaps
+    , DriveCapabilityMisc
+    , DriveMiscCaps
+    , DriveCaps
+    , DiscMode
+      -- * Data
+    , Filesystem
+    , FilesystemClass
+    , FilesystemClasses
+    , IsoAnalysis
+      -- * Logging
+    , LogEntry
+    , LogLevel
+    ) where
+
+
+import Foreign.Libcdio.CdText
+import Foreign.Libcdio.CdTypes
+import Foreign.Libcdio.Device
+import Foreign.Libcdio.Disc
+import Foreign.Libcdio.Logging
+import Foreign.Libcdio.Read
+import Foreign.Libcdio.Sector
+import Foreign.Libcdio.Track
+import Foreign.Libcdio.Util
diff --git a/src/Foreign/Libcdio/Types/Enums.chs b/src/Foreign/Libcdio/Types/Enums.chs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Libcdio/Types/Enums.chs
@@ -0,0 +1,453 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# OPTIONS_HADDOCK not-home #-}
+
+#include "cdio/compat/version.h"
+
+{-|
+Description:    c2hs-generated types for re-export by more relevant modules.
+
+Copyright:      (c) 2018-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+Many of the enums in the C library are large things with explicit numeric
+representation, and maintaining them in pure Haskell would be a nightmare.  On
+the other hand, keeping them in their natural modules means those can never be
+analyzed for coverage.  Splitting the former out here allows the best of both
+worlds — losing typeclass coverage reports on the enums is a small price.  Just
+note that since this isn't exposed, it /can not/ be used directly by any other
+c2hs-generated modules.
+-}
+module Foreign.Libcdio.Types.Enums
+    ( -- * "Foreign.Libcdio.CdText"
+      CField
+    , Field ( .. )
+    , CGenre
+    , Genre ( .. )
+    , CLanguage
+    , Language ( .. )
+      -- * "Foreign.Libcdio.CdTypes"
+    , Filesystem_ ( .. )
+    , FilesystemClass ( .. )
+      -- * "Foreign.Libcdio.Device"
+    , DriveCapabilityMisc ( .. )
+    , DriveCapabilityRead ( .. )
+    , DriveCapabilityWrite ( .. )
+    , CDriverId
+    , DriverId ( .. )
+    , CDriverReturnCode
+    , DriverReturnCode ( .. )
+      -- * "Foreign.Libcdio.Disc"
+    , CDiscMode
+    , DiscMode ( .. )
+      -- * "Foreign.Libcdio.Logging"
+    , CLogLevel
+    , LogLevel ( .. )
+      -- * "Foreign.Libcdio.Read"
+    , ReadMode ( .. )
+    , Whence ( .. )
+      -- * "Foreign.Libcdio.Sector"
+    , SubchannelData ( .. )
+    , Flag ( .. )
+      -- * "Foreign.Libcdio.Track"
+    , CTrackFormat
+    , TrackFormat ( .. )
+    , TrackFlagStatus ( .. )
+    ) where
+
+
+import Data.Ix ( Ix )
+
+
+#include "cdio/compat/cdtext.h"
+
+
+-- | The underlying type of the C @cdtext_field_t@, i.e. 'Field'.
+type CField = {#type cdtext_field_t#}
+
+-- | Descriptions of the content contained in an associated CD Text field.
+{#enum cdtext_field_t as Field
+    { underscoreToCase
+    , CDTEXT_FIELD_DISCID as DiscId
+    , CDTEXT_FIELD_GENRE as GenreName
+    } omit ( CDTEXT_FIELD_INVALID )
+    with prefix = "cdtext_field"
+    deriving ( Eq, Show, Read, Ord, Bounded )
+#}
+
+
+-- | The underlying type of the C @cdtext_genre_t@, i.e. 'Genre'.
+type CGenre = {#type cdtext_genre_t#}
+
+-- | Genres recognized in the CD Text standard.
+{#enum cdtext_genre_t as Genre
+    { underscoreToCase
+    , CDTEXT_GENRE_ADULT_CONTEMP as AdultContemporary
+    , CDTEXT_GENRE_CHRIST_CONTEMP as ChristianContemporary
+    , CDTEXT_GENRE_HIPHOP as HipHop
+    , CDTEXT_GENRE_LATIN as LatinMusic
+    , CDTEXT_GENRE_NEWAGE as NewAge
+    , CDTEXT_GENRE_RYTHMANDBLUES as RhythmAndBlues
+    , CDTEXT_GENRE_SOUNDEFFECTS as SoundEffects
+    } omit ( CDTEXT_GENRE_UNUSED )
+    with prefix = "cdtext_genre"
+    deriving ( Eq, Show, Read, Ord, Bounded )
+#}
+
+
+-- | The underlying type of the C @cdtext_lang_t@, i.e. 'Language'.
+type CLanguage = {#type cdtext_lang_t#}
+
+-- | Written languages recognized in the CD Text standard.
+#if LIBCDIO_SINCE_VERSION_2_1
+{#enum cdtext_lang_t as Language
+    { underscoreToCase
+    , CDTEXT_LANGUAGE_UNKNOWN as UnknownLanguage
+    , CDTEXT_LANGUAGE_SERBO_CROAT as SerboCroatian
+    , CDTEXT_LANGUAGE_SRANANTONGO as SrananTongo
+    } omit
+    ( CDTEXT_LANGUAGE_INVALID
+    , CDTEXT_LANGUAGE_BLOCK_UNUSED
+    )
+    with prefix = "cdtext_language"
+    deriving ( Eq, Show, Read, Ord, Bounded )
+#}
+#else
+{#enum cdtext_lang_t as Language
+    { underscoreToCase
+    , CDTEXT_LANGUAGE_UNKNOWN as UnknownLanguage
+    , CDTEXT_LANGUAGE_SERBO_CROAT as SerboCroatian
+    , CDTEXT_LANGUAGE_SRANANTONGO as SrananTongo
+    }
+    with prefix = "cdtext_language"
+    deriving ( Eq, Show, Read, Ord, Bounded )
+#}
+#endif
+
+
+
+#include "cdio/compat/cd_types.h"
+
+
+-- | Internal filesystem type, including ones that conflate
+-- 'Foreign.Libcdio.CdTypes.Filesystem' with
+-- 'Foreign.Libcdio.CdTypes.IsoAnalysis'; these are separated in
+-- 'Foreign.Libcdio.CdTypes.cdType'.
+{#enum cdio_fs_t as Filesystem_
+    {underscoreToCase}
+    with prefix = "cdio"
+    deriving ( Eq, Show, Read, Ord, Bounded )
+#}
+
+
+-- | Higher-level descriptions of discs/filesystems.
+{#enum fs_cap_t as FilesystemClass
+    { underscoreToCase
+    , FS_ANAL_CDTV as CommodoreCdtv
+    , FS_ANAL_VIDEOCD as VideoCd
+    , FS_ANAL_ROCKRIDGE as RockRidge
+    , FS_ANAL_SVCD as SuperVideoCd
+    , FS_ANAL_CVD as ChoijiVideoCd
+    , FS_ANAL_XISO as XboxIsoClass
+    , FS_ANAL_ISO9660_ANY as Iso9660Class
+    }
+    with prefix = "fs_anal"
+    deriving ( Eq, Show, Read, Ord, Bounded, Ix )
+#}
+
+
+
+#include "cdio/compat/device.h"
+
+
+-- | Miscellaneous properties a device can have, typically describing hardware
+-- features, which are collected in 'Foreign.Libcdio.Device.DriveMiscCaps'.
+{#enum cdio_drive_cap_misc_t as DriveCapabilityMisc
+    { underscoreToCase
+    } omit
+    ( CDIO_DRIVE_CAP_ERROR
+    , CDIO_DRIVE_CAP_UNKNOWN
+    )
+    with prefix = "cdio_drive_cap"
+    deriving ( Eq, Show, Read, Ord, Bounded, Ix )
+#}
+
+-- | Read-related properties a device can have, mostly describing what formats
+-- it understands, which are collected in 'Foreign.Libcdio.Device.DriveReadCaps'.
+-- 
+-- The difference between 'ReadAnalogAudio' and 'ReadDigitalAudio' is poorly
+-- documented in libcdio; they have been named here according to their assumed
+-- meanings (see <https://www.cdrfaq.org/faq02.html#S2-4-3>), but that pattern
+-- may not be completely accurate.
+{#enum cdio_drive_cap_read_t as DriveCapabilityRead
+    { underscoreToCase
+    , CDIO_DRIVE_CAP_READ_AUDIO as ReadAnalogAudio
+    , CDIO_DRIVE_CAP_READ_CD_DA as ReadDigitalAudio
+    , CDIO_DRIVE_CAP_READ_CD_G as ReadCdGraphics
+    , CDIO_DRIVE_CAP_READ_CD_R as ReadCdRecordable
+    , CDIO_DRIVE_CAP_READ_CD_RW as ReadCdReWritable
+    , CDIO_DRIVE_CAP_READ_DVD_R as ReadDvdRecordable
+    , CDIO_DRIVE_CAP_READ_DVD_PR as ReadDvdPlusRecordable
+    , CDIO_DRIVE_CAP_READ_DVD_RW as ReadDvdReWritable
+    , CDIO_DRIVE_CAP_READ_DVD_RPW as ReadDvdPlusReWritable
+    , CDIO_DRIVE_CAP_READ_C2_ERRS as ReadC2ErrorCorrection
+    }
+    with prefix = "cdio_drive_cap"
+    deriving ( Eq, Show, Read, Ord, Bounded, Ix )
+#}
+
+-- | Write-related properties a device can have, mostly describing what formats
+-- it can burn, which are collected in 'Foreign.Libcdio.Device.DriveWriteCaps'.
+{#enum cdio_drive_cap_write_t as DriveCapabilityWrite
+    { underscoreToCase
+    , CDIO_DRIVE_CAP_WRITE_CD_R as WriteCdRecordable
+    , CDIO_DRIVE_CAP_WRITE_CD_RW as WriteCdReWritable
+    , CDIO_DRIVE_CAP_WRITE_DVD_R as WriteDvdRecordable
+    , CDIO_DRIVE_CAP_WRITE_DVD_PR as WriteDvdPlusRecordable
+    , CDIO_DRIVE_CAP_WRITE_DVD_RW as WriteDvdReWritable
+    , CDIO_DRIVE_CAP_WRITE_DVD_RPW as WriteDvdPlusReWritable
+    } omit
+    ( CDIO_DRIVE_CAP_WRITE_CD
+    , CDIO_DRIVE_CAP_WRITE_DVD
+    , CDIO_DRIVE_CAP_WRITE
+    )
+    with prefix = "cdio_drive_cap"
+    deriving ( Eq, Show, Read, Ord, Bounded, Ix )
+#}
+
+
+{- Barely even used internally.
+-- | Different types of device that can be read, which are collected in
+-- 'Foreign.Libcdio.Device.SrcCategories'.
+{#enum cdio_src_category_mask_t as SrcCategoryMask
+    {underscoreToCase}
+    with prefix = "cdio"
+    deriving ( Eq, Show, Read, Ord, Bounded, Ix )
+#}
+-}
+
+
+-- | The underlying type of the C @driver_id_t@, i.e. 'DriverId'.
+type CDriverId = {#type driver_id_t#}
+
+-- | Devices or file types supported by the library.
+{#enum define DriverId
+    { DRIVER_UNKNOWN as DriverUnknown
+    , DRIVER_AIX as DriverAix
+    , DRIVER_BSDI as DriverBsdi
+    , DRIVER_FREEBSD as DriverFreeBsd
+    , DRIVER_NETBSD as DriverNetBsd
+    , DRIVER_LINUX as DriverLinux
+    , DRIVER_SOLARIS as DriverSolaris
+    , DRIVER_OS2 as DriverOs2
+    , DRIVER_OSX as DriverOsX
+    , DRIVER_WIN32 as DriverWin32
+    , DRIVER_CDRDAO as DriverCdrDao
+    , DRIVER_BINCUE as DriverBinCue
+    , DRIVER_NRG as DriverNrg
+    , DRIVER_DEVICE as DriverDevice
+    }
+    deriving ( Eq, Show, Read, Ord, Bounded )
+#}
+
+
+-- | The underlying type of the C @driver_return_code_t@, i.e.
+-- 'DriverReturnCode'.
+type CDriverReturnCode = {#type driver_return_code_t#}
+
+-- | Descriptions of various error states which may be returned by driver
+-- functions.
+{#enum driver_return_code_t as DriverReturnCode
+    { underscoreToCase
+    , DRIVER_OP_ERROR as DriverError
+    , DRIVER_OP_UNINIT as Uninitialized
+    } with prefix = "driver_op"
+    deriving ( Eq, Show, Read, Ord, Bounded )
+#}
+
+
+
+#include "cdio/compat/disc.h"
+
+
+-- | The underlying type of the C @discmode_t@, i.e. 'DiscMode'.
+type CDiscMode = {#type discmode_t#}
+
+-- | Different types of disc.  Modes are combined from several sources, along
+-- with some libcdio-specific additions:
+--
+-- * MMC-5 6.33.3.13 (Send CUESHEET)
+-- * MMC-5 Table 400 "DVD Book"
+-- * GNU/Linux @\/usr\/include\/linux\/cdrom.h@
+--
+-- As C2HS and Haddock don't yet interact well enough to document Enum fields,
+-- some of the less obvious mappings include:
+--
+-- * 'DataCdMode': CD-ROM form 1
+-- * 'MixedCdMode': some combination of 'AudioCdMode', 'DataCdMode', and 'XaCdMode'
+-- * 'DvdPlusRecordableMode': DVD+R
+-- * 'DvdPlusReWritableMode': DVD+RW
+{#enum discmode_t as DiscMode
+    { underscoreToCase
+    , CDIO_DISC_MODE_CD_DA as AudioCdMode
+    , CDIO_DISC_MODE_CD_DATA as DataCdMode
+    , CDIO_DISC_MODE_CD_XA as XaCdMode
+    , CDIO_DISC_MODE_CD_MIXED as MixedCdMode
+    , CDIO_DISC_MODE_DVD_ROM as DvdRomMode
+    , CDIO_DISC_MODE_DVD_RAM as DvdRamMode
+    , CDIO_DISC_MODE_DVD_R as DvdRecordableMode
+    , CDIO_DISC_MODE_DVD_RW as DvdReWritableMode
+    , CDIO_DISC_MODE_HD_DVD_ROM as HighDefinitionDvdRomMode
+    , CDIO_DISC_MODE_HD_DVD_RAM as HighDefinitionDvdRamMode
+    , CDIO_DISC_MODE_HD_DVD_R as HighDefinitionDvdRecordableMode
+    , CDIO_DISC_MODE_DVD_PR as DvdPlusRecordableMode
+    , CDIO_DISC_MODE_DVD_PRW as DvdPlusReWritableMode
+    , CDIO_DISC_MODE_DVD_PR_DL as DoubleLayerDvdPlusRecordableMode
+    , CDIO_DISC_MODE_DVD_PRW_DL as DoubleLayerDvdPlusReWritableMode
+    , CDIO_DISC_MODE_DVD_OTHER as OtherDvdMode
+    , CDIO_DISC_MODE_NO_INFO as NoModeInfo
+    , CDIO_DISC_MODE_CD_I as CdIMode
+    } omit ( CDIO_DISC_MODE_ERROR )
+    with prefix = "cdio_disc_mode"
+    deriving ( Eq, Show, Read, Ord, Bounded )
+#}
+
+
+
+#include "cdio/compat/logging.h"
+
+
+-- | The underlying type of the C @cdio_log_level_t@, i.e. 'LogLevel'.
+type CLogLevel = {#type cdio_log_level_t#}
+
+-- | How much detail should be recorded in the logs.
+{#enum cdio_log_level_t as LogLevel
+    {underscoreToCase}
+    with prefix = "cdio"
+    deriving ( Eq, Show, Read, Ord, Bounded )
+#}
+
+
+
+#include "cdio/compat/read.h"
+
+
+-- | How data is laid out on a disc.
+{#enum cdio_read_mode_t as ReadMode
+    { underscoreToCase
+    , CDIO_READ_MODE_AUDIO as AudioMode
+    , CDIO_READ_MODE_M1F1 as Mode1Form1
+    , CDIO_READ_MODE_M1F2 as Mode1Form2
+    , CDIO_READ_MODE_M2F1 as Mode2Form1
+    , CDIO_READ_MODE_M2F2 as Mode2Form2
+    }
+    with prefix = "cdio_read_mode"
+    deriving ( Eq, Show, Read, Ord, Bounded )
+#}
+
+
+-- | Which location an offset passed to 'Foreign.Libcdio.Read.seek' should be
+-- based on.
+{#enum whence_t as Whence
+    {underscoreToCase}
+    with prefix = "whence"
+    deriving ( Eq, Show, Read, Ord, Bounded )
+#}
+
+
+
+#include "cdio/compat/sector.h"
+
+
+-- | Types of information stored on disc subchannels.
+{#enum cdio_subchannel as SubchannelData
+    { underscoreToCase
+    , CDIO_SUBCHANNEL_SUBQ_DATA as QChannelData
+    }
+    with prefix = "cdio_subchannel"
+    deriving ( Eq, Show, Read, Ord, Bounded )
+#}
+
+
+-- | Metadata describing the layout or type of data on a track.
+{#enum flag_t as Flag
+    { underscoreToCase
+    , DATA as DataTrack
+    , SCMS as SerialCopyManagement
+    } omit ( NONE )
+    deriving ( Eq, Show, Read, Ord, Bounded, Ix )
+#}
+
+
+{- Not actually an 'Enum', but rather shortcuts for basic multiplications.
+-- | How many sectors are contained in various lengths of disc.
+{#enum cdio_cd_minutes_sectors as CdMinutesSectors
+    {underscoreToCase}
+    with prefix = "cdio"
+    deriving ( Eq, Show, Read, Ord, Bounded )
+#}
+-}
+
+
+
+#include "cdio/compat/track.h"
+
+
+-- | The underlying type of the C @track_format_t@, i.e. 'TrackFormat'.
+type CTrackFormat = {#type track_format_t#}
+
+-- | The structure in which data is stored on a segment of a disc.  The exact
+-- representation of these values is discussed in "Foreign.Libcdio.Sector".
+{#enum track_format_t as TrackFormat
+    { underscoreToCase
+    , TRACK_FORMAT_CDI as FormatCdI
+    , TRACK_FORMAT_PSX as FormatPlaystation
+    } omit ( TRACK_FORMAT_ERROR )
+    with prefix = "track"
+    deriving ( Eq, Show, Read, Ord, Bounded )
+#}
+
+
+{- Barely even used internally.
+-- | The block format in which the data is saved in a track on disc.
+{#enum trackmode_t as TrackMode
+    {underscoreToCase}
+    deriving ( Eq, Show, Read, Ord, Bounded )
+#}
+-}
+
+
+-- | Whether a track has a particular flag specified.
+{#enum track_flag_t as TrackFlagStatus
+    {underscoreToCase}
+    with prefix = "cdio_track"
+    deriving ( Eq, Show, Read, Ord, Bounded )
+#}
+
+
+
+#include "cdio/util.h"
+
+
+{- Similar semantics from 'Maybe Bool'.
+-- | A version of 'Bool' which also provides a third, non-definitive state.
+{#enum bool_3way_t as Bool3
+    {nope as No, yep as Yes, dunno as Unknown}
+    deriving ( Eq, Show, Read, Ix )
+#}
+-- Need to explicitly instance Ord and Bounded as the below is the logical
+-- order, but @dunno@ is assigned @3@ in the C code.
+instance Ord Bool3 where
+    No <= _             = True
+    _ <= Yes            = True
+    Unknown <= Unknown  = True
+    _ <= _              = False
+instance Bounded Bool3 where
+    minBound = No
+    maxBound = Yes
+-- Needs: Bits, FiniteBits, Generic, Rep, Data, Storable for parity with Bool
+-}
diff --git a/src/Foreign/Libcdio/Types/Internal.hs b/src/Foreign/Libcdio/Types/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Libcdio/Types/Internal.hs
@@ -0,0 +1,409 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+{-|
+Description:    Common type definitions used pervasively in libcdio, along with
+                low-level features intended for internal use.
+
+Copyright:      (c) 2018-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+While most of @types.h@ is user-facing, it's undesirable to export the
+@newtype@ constructors, for type safety.  Hiding them breaks c2hs automatic
+marshalling, which means that we have to write custom marshalling functions.
+Exporting those clutters the user surface with unnecessary and
+likely-never-used code, so the types in this module got split off for use
+internally — at which point the constructors may as well be exported anyway.
+-}
+module Foreign.Libcdio.Types.Internal
+    ( -- * Addresses
+      Lba ( .. )
+    , CLba
+    , Lsn ( .. )
+    , CLsn
+      -- * Segments
+    , Track ( .. )
+    , CTrack
+    , TrackNum
+    , minTrack
+    , maxTrack
+      -- * Data
+    , CBitfield
+    , isrcLength
+    , mcnLength
+      -- * Marshalling
+    , invalidLba
+    , invalidLsn
+    , invalidZeroLsn
+    , invalidTrack
+    , invalidZeroTrack
+    , withLba
+    , withLsn
+    , withTrack
+    ) where
+
+
+import qualified Data.Bits as B
+import qualified Data.Ix as I
+import qualified Data.List as L
+import qualified Data.Maybe as Y
+
+import qualified Foreign.C.Types as C
+import qualified Foreign.Ptr as C
+import qualified Foreign.Storable as S
+
+import qualified Text.Printf as P
+
+import Data.Bits ((.&.), (.|.))
+
+import Foreign.Libcdio.Marshal
+
+
+{- 'Char' is already native.
+type CUtf8 = C.CChar
+
+-- | A character explicitly encoded as UTF-8.
+newtype Utf8 = Utf8 CUtf8
+  deriving ( Eq, Ord, Show, Read, Bounded )
+-}
+
+
+-- | The representation of the various @DriveCaps*@ at the C boundary.
+type CBitfield = C.CUInt
+
+{- Accomplished with "Data.Array.BitArray".
+-- | The type used for bit-fields in structs with eight or less flags.
+newtype Bitfield = Bitfield CBitfield
+  deriving ( Eq, Ord, Show, Read, Bounded )
+-}
+
+
+-- | Marshal an address to a type which pins the required size of the C
+-- representation, rather than the polymorphism of 'fromIntegral'.
+withLba :: Lba -> CLba
+withLba (Lba i) = i
+
+type CLba = C.CInt
+
+-- | The type-safe representation of a Logical Block Address, counting sectors
+-- from the very beginning of the write session.  See also 'Lsn'.
+newtype Lba = Lba CLba
+  deriving ( Eq, Ord, Show, Read )
+instance Bounded Lba where
+    minBound = Lba . lsnToLba $ fromIntegral (minBound :: Lsn)
+    maxBound = Lba . lsnToLba $ fromIntegral (maxBound :: Lsn)
+instance Enum Lba where
+    toEnum = Lba . toEnum
+    fromEnum (Lba i) = fromEnum i
+instance I.Ix Lba where
+    range (Lba a, Lba b) = map Lba [a..b]
+    inRange (a, b) i = a <= i && i <= b
+    index r@(a, b) i = Y.fromMaybe (error $ "Ix(Lba).index: Index (" ++ show i ++ ") out of range (" ++ show r ++ ")")
+                     $ L.elemIndex i [a..b]
+instance Num Lba where
+    Lba a + Lba b = Lba $ a + b
+    Lba a - Lba b = Lba $ a - b
+    Lba a * Lba b = Lba $ a * b
+    abs (Lba i) = Lba $ abs i
+    signum (Lba i) = Lba $ signum i
+    fromInteger = Lba . fromInteger
+instance Real Lba where
+    toRational (Lba i) = toRational i
+instance Integral Lba where
+    quotRem (Lba i) (Lba d) = (Lba q, Lba r)
+      where (q, r) = quotRem i d
+    toInteger (Lba i) = toInteger i
+instance B.Bits Lba where
+    (Lba a) .&. (Lba b) = Lba $ a .&. b
+    (Lba a) .|. (Lba b) = Lba $ a .|. b
+    xor (Lba a) (Lba b) = Lba $ B.xor a b
+    complement (Lba i) = Lba $ B.complement i
+    shift (Lba i) = Lba . B.shift i
+    rotate (Lba i) = Lba . B.rotate i
+    bitSize (Lba i) = B.finiteBitSize i
+    bitSizeMaybe (Lba i) = B.bitSizeMaybe i
+    isSigned (Lba i) = B.isSigned i
+    testBit (Lba i) = B.testBit i
+    bit = Lba . B.bit
+    popCount (Lba i) = B.popCount i
+instance B.FiniteBits Lba where
+    finiteBitSize (Lba i) = B.finiteBitSize i
+instance P.PrintfArg Lba where
+    formatArg = P.formatArg . (fromIntegral :: Lba -> Int)
+instance S.Storable Lba where
+    sizeOf (Lba i)    = S.sizeOf i
+    alignment (Lba i) = S.alignment i
+    peek p            = Lba <$> S.peek (C.castPtr p)
+    poke p (Lba i)    = S.poke (C.castPtr p) i
+
+foreign import ccall safe "cdio/compat/sector.h cdio_lsn_to_lba"
+  lsnToLba :: CLsn -> CLba
+
+foreign import ccall safe "cdio/compat/disc.h invalid_lba"
+  invalidLba' :: CLba
+
+-- | Filter out @CDIO_INVALID_LBA@ values for type-safe errors.
+invalidLba :: CLba -> Maybe Lba
+invalidLba = fmap fromIntegral . maybeError [invalidLba']
+
+
+-- | Marshal an address to a type which pins the required size of the C
+-- representation, rather than the polymorphism of 'fromIntegral'.
+withLsn :: Lsn -> CLsn
+withLsn (Lsn i) = i
+
+type CLsn = C.CInt
+
+-- | The type-safe representation of a Logical Sector Number, counting sectors
+-- from the start of track 1; this notably excludes the blank session lead-in.
+-- See also 'Lba'.
+newtype Lsn = Lsn CLsn
+  deriving ( Eq, Ord, Show, Read )
+instance Bounded Lsn where
+    minBound = Lsn minLsn
+    maxBound = Lsn maxLsn
+instance Enum Lsn where
+    toEnum = Lsn . toEnum
+    fromEnum (Lsn i) = fromEnum i
+instance I.Ix Lsn where
+    range (Lsn a, Lsn b) = map Lsn [a..b]
+    inRange (a, b) i = a <= i && i <= b
+    index r@(a, b) i = Y.fromMaybe (error $ "Ix(Lsn).index: Index (" ++ show i ++ ") out of range (" ++ show r ++ ")")
+                     $ L.elemIndex i [a..b]
+instance Num Lsn where
+    Lsn a + Lsn b = Lsn $ a + b
+    Lsn a - Lsn b = Lsn $ a - b
+    Lsn a * Lsn b = Lsn $ a * b
+    abs (Lsn i) = Lsn $ abs i
+    signum (Lsn i) = Lsn $ signum i
+    fromInteger = Lsn . fromInteger
+instance Real Lsn where
+    toRational (Lsn i) = toRational i
+instance Integral Lsn where
+    quotRem (Lsn i) (Lsn d) = (Lsn q, Lsn r)
+      where (q, r) = quotRem i d
+    toInteger (Lsn i) = toInteger i
+instance B.Bits Lsn where
+    (Lsn a) .&. (Lsn b) = Lsn $ a .&. b
+    (Lsn a) .|. (Lsn b) = Lsn $ a .|. b
+    xor (Lsn a) (Lsn b) = Lsn $ B.xor a b
+    complement (Lsn i) = Lsn $ B.complement i
+    shift (Lsn i) = Lsn . B.shift i
+    rotate (Lsn i) = Lsn . B.rotate i
+    bitSize (Lsn i) = B.finiteBitSize i
+    bitSizeMaybe (Lsn i) = B.bitSizeMaybe i
+    isSigned (Lsn i) = B.isSigned i
+    testBit (Lsn i) = B.testBit i
+    bit = Lsn . B.bit
+    popCount (Lsn i) = B.popCount i
+instance B.FiniteBits Lsn where
+    finiteBitSize (Lsn i) = B.finiteBitSize i
+instance P.PrintfArg Lsn where
+    formatArg = P.formatArg . (fromIntegral :: Lsn -> Int)
+instance S.Storable Lsn where
+    sizeOf (Lsn i)    = S.sizeOf i
+    alignment (Lsn i) = S.alignment i
+    peek p            = Lsn <$> S.peek (C.castPtr p)
+    poke p (Lsn i)    = S.poke (C.castPtr p) i
+
+foreign import ccall safe "cdio/compat/sector.h min_lsn"
+  minLsn :: CLsn
+
+foreign import ccall safe "cdio/compat/sector.h max_lsn"
+  maxLsn :: CLsn
+
+foreign import ccall safe "cdio/compat/disc.h invalid_lsn"
+  invalidLsn' :: CLsn
+
+-- | Filter out @CDIO_INVALID_LSN@ values for type-safe errors.
+invalidLsn :: CLsn -> Maybe Lsn
+invalidLsn = fmap fromIntegral . maybeError [invalidLsn']
+
+-- | Filter out both @0@ and @CDIO_INVALID_LSN@ values for type-safe errors.
+invalidZeroLsn :: CLsn -> Maybe Lsn
+invalidZeroLsn = fmap fromIntegral . maybeError [0, invalidLsn']
+
+
+-- | Marshal a track number to a type which pins the required size of the C
+-- representation, rather than the polymorphism of 'fromIntegral'.  Note that
+-- @withTrack 'DiscLeadout' /= fromIntegral (fromEnum 'DiscLeadout')@
+withTrack :: Track -> CTrack
+withTrack DiscPregap = 0
+withTrack (Track (TrackNum i)) = fromIntegral i + minTrack'
+withTrack DiscLeadout = leadoutTrack'
+
+type CTrack = C.CUChar
+
+-- | Opaque newtype representing the numeric index of a 'Track', while
+-- enforcing the invariants inherant to the specification.  Of very limited
+-- utility outside that context.
+newtype TrackNum = TrackNum Word
+  deriving ( Eq, Ord )
+instance Bounded TrackNum where
+    minBound = TrackNum 0
+    maxBound = TrackNum $ maxTrackW - minTrackW
+instance Show TrackNum where
+    show (TrackNum i) = show $ i + minTrackW
+instance Read TrackNum where
+    readsPrec d = \str -> do
+        (i, str') <- readsPrec d str
+        return (TrackNum $ i - minTrackW, str')
+
+-- | An index into the segmentation within a write session on a disc.
+data Track
+    = DiscPregap
+        -- ^ The (usually buffer) data located before the first track on a
+        -- disc.
+    | Track TrackNum
+        -- ^ The common understanding of a CD track: a segment of the data on
+        -- the disc containing (usually) a single song.
+    | DiscLeadout
+        -- ^ Any (usually buffer) data located after the end of the last track
+        -- on a disc.
+  deriving ( Eq, Ord, Show )
+instance Bounded Track where
+    minBound = DiscPregap
+    maxBound = DiscLeadout
+-- | Note that @'fromEnum' 'DiscLeadout'@ uses a value (== 100) chosen to be
+-- contiguous to the rest of the datatype rather than that used internally
+-- (== 0xAA).  'toEnum' accepts both values.
+instance Enum Track where
+    toEnum i
+        | i < fromIntegral minTrack' = DiscPregap
+        | i > fromIntegral maxTrack' = DiscLeadout
+        | otherwise = Track . TrackNum $ fromIntegral i - minTrackW
+    fromEnum DiscPregap = fromIntegral minTrack' - 1
+    fromEnum (Track (TrackNum i)) = fromIntegral $ i + minTrackW
+    fromEnum DiscLeadout = fromIntegral maxTrack' + 1
+    pred DiscPregap = error "Enum.pred(Track): tried to take `pred' of DiscPregap"
+    pred (Track n@(TrackNum i))
+        | n == minBound = DiscPregap
+        | n > maxBound = DiscLeadout
+        | otherwise = Track . TrackNum $ i - 1
+    pred DiscLeadout = Track maxBound
+    succ DiscPregap = Track minBound
+    succ (Track n@(TrackNum i))
+        | n >= maxBound = DiscLeadout
+        | otherwise = Track . TrackNum $ i + 1
+    succ DiscLeadout = error "Enum.succ(Track): tried to take `succ' of DiscLeadout"
+instance Read Track where
+    readsPrec d = \s ->
+        [ (DiscPregap, s')
+        | ("DiscPregap", s') <- lex s
+        ] ++
+        [ (DiscLeadout, s')
+        | ("DiscLeadout", s') <- lex s
+        ] ++
+        [ (packTrack i, s')
+        | (i, s') <- readParen (d > 10) readsTrack s
+        ]
+      where packTrack i
+                | i < minTrackW = DiscPregap
+                | i > maxTrackW = DiscLeadout
+                | otherwise = Track . TrackNum $ i - minTrackW
+            readsTrack s =
+                [ (i, s'')
+                | ("Track", s') <- lex s
+                , (i, s'') <- readsPrec 10 s'
+                ]
+instance I.Ix Track where
+    range (a, b) = map toEnum [fromEnum a..fromEnum b]
+    inRange (a, b) i = a <= i && i <= b
+    index r@(a, b) i = Y.fromMaybe (error $ "Ix(Track).index: Index (" ++ show i ++ ") out of range (" ++ show r ++ ")")
+                     $ L.elemIndex i [a..b]
+instance Num Track where
+    a + b = toEnum $ fromEnum a + fromEnum b
+    a - b = toEnum $ fromEnum a - fromEnum b
+    a * b = toEnum $ fromEnum a * fromEnum b
+    abs t = t
+    signum _ = DiscPregap
+    fromInteger = toEnum . fromInteger
+instance P.PrintfArg Track where
+    formatArg t = P.formatInt $ withTrack t
+-- | Note that 'S.poke' uses the official representation of 'DiscLeadout'
+-- (@CDIO_CDROM_LEADOUT_TRACK == 0xAA@, as used by libcdio) rather than the
+-- hscdio @'fromEnum' 'DiscLeadout'@ (== 100), as the latter was chosen for
+-- proximity to the other constructors.
+instance S.Storable Track where
+    sizeOf _    = S.sizeOf leadoutTrack'
+    alignment _ = S.alignment leadoutTrack'
+    peek p      = toEnum . fromIntegral <$> S.peek (C.castPtr p :: C.Ptr CTrack)
+    poke p      = S.poke (C.castPtr p) . withTrack
+
+-- | The first data track on a disc (i.e. @'Track' 1@).
+minTrack :: Track
+minTrack = fromIntegral minTrack'
+
+minTrackW :: Word
+minTrackW = fromIntegral minTrack'
+
+foreign import ccall safe "cdio/compat/track.h min_tracks"
+  minTrack' :: CTrack
+
+-- | The highest data track allowed by the specifications (i.e. @'Track' 99@).
+maxTrack :: Track
+maxTrack = fromIntegral maxTrack'
+
+maxTrackW :: Word
+maxTrackW = fromIntegral maxTrack'
+
+foreign import ccall safe "cdio/compat/track.h max_tracks"
+  maxTrack' :: CTrack
+
+foreign import ccall safe "cdio/compat/track.h leadout_track"
+  leadoutTrack' :: CTrack
+
+foreign import ccall safe "cdio/compat/track.h invalid_track"
+  invalidTrack' :: CTrack
+
+-- | Filter out @CDIO_INVALID_TRACK@ values for type-safe errors.
+invalidTrack :: CTrack -> Maybe Track
+invalidTrack = fmap (toEnum . fromIntegral) . maybeError [invalidTrack']
+
+-- | Filter out @CDIO_INVALID_TRACK@ and 'DiscPregap' values for type-safe
+-- errors.
+invalidZeroTrack :: CTrack -> Maybe Track
+invalidZeroTrack = fmap (toEnum . fromIntegral) . maybeError [0, invalidTrack']
+
+
+-- | Number of ASCII bytes in a media catalog number.
+mcnLength :: Word
+mcnLength = fromIntegral mcnLength'
+
+foreign import ccall safe "cdio/compat/types.h mcn_length"
+  mcnLength' :: C.CUChar
+
+{- Never used after definition.
+-- | Some Media Catalog Number which identifies a disc; in practice usually a
+-- UPC/EAN bar code.
+newtype Mcn = Mcn String
+  deriving ( Eq, Ord, Show, Read, Bounded )
+instance S.Storable Mcn where
+    sizeOf _       = S.sizeOf C.nullPtr
+    alignment _    = S.alignment C.nullPtr
+    peek p         = Mcn <$> C.peekCStringLen (C.castPtr p, mcnLength)
+    poke p (Mcn s) = undefined
+--}
+
+
+-- | Number of ASCII characters in an International Standard Recording Code.
+isrcLength :: Word
+isrcLength = fromIntegral isrcLength'
+
+foreign import ccall safe "cdio/compat/types.h isrc_length"
+  isrcLength' :: C.CUChar
+
+{- Never used after definition.
+-- | The International Standard Recording Code attached to a track of a disc,
+-- as assigned by a central agency.
+newtype Isrc = Isrc String
+  deriving ( Eq, Ord, Show, Read, Bounded )
+instance S.Storable Isrc where
+    sizeOf _        = S.sizeOf C.nullPtr
+    alignment _     = S.alignment C.nullPtr
+    peek p          = Isrc <$> C.peekCStringLen (C.castPtr p, isrcLength)
+    poke p (Isrc s) = undefined
+-}
diff --git a/src/Foreign/Libcdio/Types/Offsets.chs b/src/Foreign/Libcdio/Types/Offsets.chs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Libcdio/Types/Offsets.chs
@@ -0,0 +1,127 @@
+{-|
+Description:    c2hs-generated byte offsets for members of C structs.
+
+Copyright:      (c) 2020 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+Since this library already handles marshalling to and from C types itself, the
+only remaining benefit to using c2hs for datatypes is not having to worry about
+tracking the internal byte arrangement of C structs.  That can be done just as
+easily externally here, with the added benefit of being able to analyze
+coverage of the primary modules.  Just note that since this isn't exposed, it
+/can not/ be used directly by any other c2hs-generated modules.
+-}
+module Foreign.Libcdio.Types.Offsets where
+
+
+import qualified Foreign.C.String as C
+import qualified Foreign.Ptr as C
+
+import qualified Foreign.Marshal.Array as M
+import qualified Foreign.Storable as S
+
+
+pokeCString :: String -> Int -> C.CString -> IO ()
+pokeCString s l p = C.withCStringLen (s ++ "\NUL") $ \(c, cl) ->
+    if l < cl
+    then M.copyArray p c (l - 1) >> S.poke (C.plusPtr p $ l - 1) '\NUL'
+    else M.copyArray p c cl
+
+
+#include "cdio/compat/cd_types.h"
+
+
+iaSizeOf :: Int
+iaSizeOf = {#sizeof cdio_iso_analysis_t#}
+
+iaAlign :: Int
+iaAlign = {#alignof cdio_iso_analysis_t#}
+
+iaJolietLevel :: Int
+iaJolietLevel = {#offsetof cdio_iso_analysis_t->joliet_level#}
+
+iaLabel :: Int
+iaLabel = {#offsetof cdio_iso_analysis_t->iso_label#}
+
+iaIsoSize :: Int
+iaIsoSize = {#offsetof cdio_iso_analysis_t->isofs_size#}
+
+iaUDFMajor :: Int
+iaUDFMajor = {#offsetof cdio_iso_analysis_t->UDFVerMajor#}
+
+iaUDFMinor :: Int
+iaUDFMinor = {#offsetof cdio_iso_analysis_t->UDFVerMinor#}
+
+
+
+#include "cdio/compat/device.h"
+
+
+hiSizeOf :: Int
+hiSizeOf = {#sizeof cdio_hwinfo#}
+
+hiAlign :: Int
+hiAlign = {#alignof cdio_hwinfo#}
+
+hiVendor :: Int
+hiVendor = {#offsetof cdio_hwinfo->psz_vendor#}
+
+hiModel :: Int
+hiModel = {#offsetof cdio_hwinfo->psz_model#}
+
+hiRevision :: Int
+hiRevision = {#offsetof cdio_hwinfo->psz_revision#}
+
+
+
+#include "cdio/compat/logging.h"
+
+
+leSizeOf :: Int
+leSizeOf = {#sizeof cdio_log_entry_t#}
+
+leAlign :: Int
+leAlign = {#alignof cdio_log_entry_t#}
+
+leLevel :: Int
+leLevel = {#offsetof cdio_log_entry_t->level#}
+
+leMessage :: Int
+leMessage = {#offsetof cdio_log_entry_t->message#}
+
+lePrevious :: Int
+lePrevious = {#offsetof cdio_log_entry_t->prev#}
+
+
+
+#include "cdio/compat/sector.h"
+
+
+-- c2hs can't handle the packed datatype, so get the values from C itself.
+msfSizeOf :: Int
+msfSizeOf = fromIntegral $ {#call pure sizeof_msf#}
+
+msfAlign :: Int
+msfAlign = {#alignof msf_t#}
+
+msfM :: Int
+msfM = {#offsetof msf_t->m#}
+
+msfS :: Int
+msfS = {#offsetof msf_t->s#}
+
+msfF :: Int
+msfF = {#offsetof msf_t->f#}
+
+
+{- Never used after definition.
+adrSizeOf :: Int
+adrSizeOf = {#sizeof cdio_cdrom_addr#}
+
+adrAlign :: Int
+adrAlign = {#alignof cdio_cdrom_addr#}
+-}
diff --git a/src/Foreign/Libcdio/Util.hs b/src/Foreign/Libcdio/Util.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Libcdio/Util.hs
@@ -0,0 +1,289 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+{-|
+Description:    Miscellaneous utility functions, of limited utility.
+
+Copyright:      (c) 2018-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+Most functions defined by the C header either encapsulate math to perform on
+an object or the system state, or edit `String's in some (barring allocations)
+pure manner, including a few with general utility rather than being specific to
+libcdio.  However, most are also restricted to internal use, and not provided
+as symbols exported by the library itself; those internal functions are still
+present in the Haskell source as well, for anyone interested.  As such, this
+module and the functions it provides should rarely need to be used.
+
+
+= @util.h@
+
+== Defines
+* @CDIO_FREE_IF_NOT_NULL@           (removed; Haskell handles its own memory management)
+* @CLAMP@                           (removed; preprocessor logic isn't required in Haskell)
+* @IN@                              (removed; preprocessor logic isn't required in Haskell)
+* @MAX@                             (removed; preprocessor logic isn't required in Haskell)
+* @MAX@                             (removed; preprocessor logic isn't required in Haskell)
+
+== Symbols
+* @_cdio_strfreev@                  (removed; list is automatically freed)
+* @_cdio_strsplit@                  -> 'Foreign.Libcdio.Util.strsplit'
+* @cdio_from_bcd8@                  -> 'Foreign.Libcdio.Util.fromBcd8'
+* @cdio_realpath@                   -> 'Foreign.Libcdio.Util.realpath'
+* @cdio_to_bcd8@                    -> 'Foreign.Libcdio.Util.toBcd8'
+-}
+module Foreign.Libcdio.Util
+    ( Bcd
+    , toBcd8, fromBcd8
+    , strsplit
+    , realpath
+    ) where
+
+
+{- Used only by not exported symbols
+import qualified Foreign.ForeignPtr as C
+
+import qualified Foreign.Marshal.Alloc as M
+import qualified Foreign.Marshal.Array as M
+import qualified Foreign.Marshal.Utils as M
+
+import qualified System.IO.Unsafe as IO.Unsafe
+
+import Foreign.Libcdio.Types.Internal
+-}
+
+import qualified Data.Word as W
+
+
+import qualified Data.Ix as I
+
+import qualified Foreign.C.String as C
+import qualified Foreign.C.Types as C
+import qualified Foreign.Ptr as C
+
+import qualified Foreign.Marshal.Utils as M
+import qualified Foreign.Storable as S
+
+import qualified Numeric as NM
+
+import qualified Text.Printf as P
+
+
+import Foreign.Libcdio.Marshal
+
+
+{- Not exported
+-- | Calculate how many blocks of a given size are required to contain the
+-- given number of bytes.
+len2blocks
+    :: W.Word32
+        -- ^ The number of bytes to fit.
+    -> W.Word16
+        -- ^ The size of each block.
+    -> Lsn
+len2blocks b s = fromIntegral $ len2blocks' (fromIntegral b) (fromIntegral s)
+
+foreign import ccall safe "cdio/util.h _cdio_len2blocks"
+  len2blocks' :: C.CUInt -> C.CUShort -> C.CInt
+
+-- | Round up to the next block boundery after a given offset.
+ceil2block
+    :: Int
+        -- ^ The base address to round.
+    -> W.Word16
+        -- ^ The size of each block.
+    -> Int
+ceil2block p s = fromIntegral $ ceil2block' (fromIntegral p) (fromIntegral s)
+
+foreign import ccall safe "cdio/util.h _cdio_ceil2block"
+  ceil2block' :: C.CInt -> C.CUShort -> C.CInt
+
+
+-- | Add a given length after a given address, potentially putting it at the
+-- start of a new block if there is not enough space remaining in the one in
+-- which the address is located.
+ofsAdd
+    :: Int
+        -- ^ The base addres.
+    -> Int
+        -- ^ The number of bytes to add.
+    -> W.Word16
+        -- ^ The size of each block.
+    -> Int
+ofsAdd p a s = fromIntegral $ ofsAdd' (fromIntegral p) (fromIntegral a) (fromIntegral s)
+
+foreign import ccall safe "cdio/util.h _cdio_ofs_add"
+  ofsAdd' :: C.CInt -> C.CInt -> C.CUShort -> C.CInt
+
+
+-- | Print a 'True'/'False' value as "yes"/"no".
+--
+-- A similar, but not identical, result may be obtained with 'show'.
+boolStr :: Bool -> String
+boolStr = IO.Unsafe.unsafePerformIO . C.peekCString . boolStr' . M.fromBool
+
+foreign import ccall safe "cdio/util.h _cdio_bool_str"
+  boolStr' :: C.CInt -> C.CString
+
+
+-- | Copy the contents of one memory address to another, newly allocated one.
+memdup :: C.Ptr a -> Word
+    -> IO (Maybe (C.ForeignPtr a))
+        -- ^ 'Nothing' if the source is 'nullPtr',
+                                    -- or a pointer to the new memory.
+memdup p s = do
+    p' <- memdup' p (fromIntegral s)
+    if p == C.nullPtr
+    then return Nothing
+    else Just <$> C.newForeignPtr cdioFreePtr p'
+
+foreign import ccall safe "cdio/util.h _cdio_memdup"
+  memdup' :: C.Ptr a -> C.CSize -> IO (C.Ptr a)
+
+
+-- | Create a copy of a string with all characters transformed to upper case.
+--
+-- This should be functionally identical to @map toUpper@.
+strdupUpper :: String -> IO String
+strdupUpper s = C.withCString s strdupUpper' >>= peekFString
+
+foreign import ccall safe "cdio/util.h _cdio_strdup_upper"
+  strdupUpper' :: C.CString -> IO C.CString
+
+-- | Duplicate a path and make it platform compliant.  Typically needed for
+-- MinGW\/MSYS where a "\/c\/..." path must be translated to "c:\/...".
+strdupFixpath :: String -> IO (Maybe String)
+strdupFixpath s = C.withCString s strdupFixpath' >>= peekNullFString
+
+foreign import ccall safe "cdio/util.h _cdio_strdup_fixpath"
+  strdupFixpath' :: C.CString -> IO C.CString
+
+
+-- | Count the number of C-style string pointers in a NULL-terminated array.
+--
+-- As we are already know the list is fully populated, this offers no benefit
+-- over 'length'; Haskell's type system will not insert anything acting like a
+-- string which is actually @NULL@.
+strlenv :: [String] -> IO Word
+strlenv ss = M.withMany C.withCString ss $ \ss' ->
+    fromIntegral <$> M.withArray0 C.nullPtr ss' strlenv'
+
+foreign import ccall safe "cdio/util.h _cdio_strlenv"
+  strlenv' :: C.Ptr C.CString -> IO C.CSize
+-}
+
+
+-- | Return the substrings between a given delimiter, dropping any empty ones.
+--
+-- The Haskell repositories provide this via
+-- [split](https://hackage.haskell.org/package/split).
+--
+-- > strsplit str d == Data.List.Split.wordsBy (== d) str
+strsplit :: String -> Char -> IO [String]
+strsplit s c = C.withCString s (flip strsplit' . fromIntegral $ fromEnum c) >>= peekFStringArray
+
+foreign import ccall safe "cdio/util.h _cdio_strsplit"
+  strsplit' :: C.CString -> C.CChar -> IO (C.Ptr C.CString)
+
+
+-- | A bitwise encoding where the lower four bits encode a number modulo 10,
+-- and the upper encode the same divided by 10.
+newtype Bcd = Bcd W.Word8
+instance Eq Bcd where
+    a == b = fromBcd8 a == fromBcd8 b
+instance Ord Bcd where
+    compare a b = compare (fromBcd8 a) (fromBcd8 b)
+instance Show Bcd where
+    showsPrec p i@(Bcd w)
+        | mod w 0x10 >= 0xA = showParen (p > application) $
+            showString ("Bcd 0x" ++ pad) . NM.showHex w
+        | otherwise = showsPrec p $ fromBcd8 i
+      where application = 10
+            pad | i >= 0x10 = ""
+                | otherwise = "0"
+instance Read Bcd where
+    readsPrec p s =
+           map toBcd8Fst (readsPrec p s)
+        ++ readParen (p > application)
+            (\r -> [ (Bcd i, v ++ ' ' : u)
+                   | ("Bcd", t) <- lex r
+                   , ('0':'x':l, u) <- lex t
+                   , (i, v) <- NM.readHex l
+                   ]) s
+      where toBcd8Fst (w, b) = (toBcd8 w, b)
+            application = 10
+-- | >>> map fromBcd8 [minBound, maxBound]
+-- [0, 159]
+instance Bounded Bcd where
+    minBound = Bcd 0
+    maxBound = Bcd 0xF9
+instance Enum Bcd where
+    toEnum i = toBcd8 $ toEnum i
+    fromEnum b = fromEnum $ fromBcd8 b
+    succ i
+        | i >= maxBound = error "Enum.succ(Bcd): tried to take `succ' of maxBound"
+        | otherwise = toBcd8 . succ $ fromBcd8 i
+    pred i
+        | i <= minBound = error "Enum.pred(Bcd): tried to take `pred' of minBound"
+        | otherwise = toBcd8 . pred $ fromBcd8 i
+instance I.Ix Bcd where
+    range (a, b) = map toBcd8 $ I.range (fromBcd8 a, fromBcd8 b)
+    inRange (a, b) i = I.inRange (fromBcd8 a, fromBcd8 b) $ fromBcd8 i
+    index (a, b) i = I.index (fromBcd8 a, fromBcd8 b) $ fromBcd8 i
+instance Num Bcd where
+    a + b = toBcd8 $ fromBcd8 a + fromBcd8 b
+    a - b = toBcd8 $ fromBcd8 a - fromBcd8 b
+    a * b = toBcd8 $ fromBcd8 a * fromBcd8 b
+    abs i = i
+    signum b = toBcd8 . signum $ fromBcd8 b
+    fromInteger i = toBcd8 $ fromInteger i
+instance Real Bcd where
+    toRational b = toRational $ fromBcd8 b
+instance Integral Bcd where
+    quotRem dividend divisor = (toBcd8 q, toBcd8 r)
+      where (q, r) = quotRem (fromBcd8 dividend) (fromBcd8 divisor)
+    toInteger b = toInteger $ fromBcd8 b
+instance P.PrintfArg Bcd where
+    formatArg = P.formatArg . fromBcd8
+instance S.Storable Bcd where
+    sizeOf (Bcd i)    = S.sizeOf i
+    alignment (Bcd i) = S.alignment i
+    peek p            = Bcd <$> S.peek (C.castPtr p)
+    poke p (Bcd i)    = S.poke (C.castPtr p) i
+
+-- | Encode a number according to the libcdio BCD encoding.  If the value is
+-- greater than @'maxBound' :: 'Bcd'@, it wraps back around to @0@.
+toBcd8 :: Word -> Bcd
+toBcd8 = Bcd . fromIntegral . toBcd8' . fromIntegral
+
+foreign import ccall safe "cdio/util.h cdio_to_bcd8"
+  toBcd8' :: C.CUInt -> C.CUInt
+
+-- | Decode a number in the libcdio BCD encoding.
+fromBcd8 :: Bcd -> Word
+fromBcd8 (Bcd i) = fromIntegral . fromBcd8' $ fromIntegral i
+
+foreign import ccall safe "cdio/util.h cdio_from_bcd8"
+  fromBcd8' :: C.CUInt -> C.CUInt
+
+
+-- | Same as POSIX.1-2001 realpath, if the system provides it.  If not,
+-- libcdio's "poor-man's simulation" of its behavior.
+--
+-- The Haskell repositories provide a similar alternative in
+-- @System.Directory.canonicalizePath@ from
+-- [directory](https://hackage.haskell.org/package/directory).
+realpath :: String -> IO (Maybe String)
+realpath s = C.withCString s (`realpath'` C.nullPtr) >>= M.maybePeek peekFString
+
+foreign import ccall safe "cdio/util.h cdio_realpath"
+  realpath' :: C.CString -> C.CString -> IO C.CString
+
+
+{- Pointer logic is not exposed.
+-- | Some function which matches the free() prototype.
+type DataFree = C.FunPtr (C.Ptr () -> IO ())
+-}
diff --git a/src/Foreign/Libcdio/Version.hs b/src/Foreign/Libcdio/Version.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Libcdio/Version.hs
@@ -0,0 +1,90 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+{-|
+Description:    Objects used to determine which version of the C library is used.
+
+Copyright:      (c) 2018-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+The values in this module are best treated as informational; it may be helpful
+to use 'cdioVersionString' in printing copyright, for example, and
+'libcdioVersionNum' does serve a purpose in the tests, but all are of little
+value outside of such very particular situations.  Instead, an effort has been
+made to have all version differences in the base library degrade gracefully,
+and those fallback values are able to be handled transparently.  For example,
+rather than explicitly testing whether libcdio is new enough to have exposed
+@cdtext_data_init@, simply call 'Foreign.Libcdio.CdText.cdTextDataInit' and
+have a plan for if it returns 'Nothing' rather than a @'Just'
+'Foreign.Libcdio.CdText.CdText'@.
+
+
+= @version.h@
+
+== Defines
+* @CDIO_VERSION@                    (removed; identical to 'cdioVersionString')
+* @LIBCDIO_VERSION_NUM@             (removed; identical to 'libcdioVersionNum')
+
+== Symbols
+* @cdio_version_string@             -> 'cdioVersionString'
+* @libcdio_version_num@             -> 'libcdioVersionNum'
+
+
+= "Sound.Libcdio"
+Re-exported unchanged as there is little reason for it to be a separate module,
+and no changes need to be made to the types.
+-}
+module Foreign.Libcdio.Version
+    ( V.Version
+    , V.makeVersion
+    , cdioVersionString
+    , libcdioVersionNum
+    , apiVersion
+    ) where
+
+
+import qualified Data.Version as V
+
+import qualified Foreign.C.String as C
+import qualified Foreign.C.Types as C
+
+import qualified System.IO.Unsafe as IO.Unsafe
+
+
+-- | The value of the preprocessor macro @CDIO_VERSION@, listing both the
+-- SemVar-style version of libcdio and the full architecture of the system
+-- which compiled it (e.g. @2.0.0 x86_64-pc-linux-gnu@).
+cdioVersionString :: String
+cdioVersionString = IO.Unsafe.unsafePerformIO $ C.peekCString cdioVersionString'
+
+foreign import ccall safe "cdio/compat/version.h get_cdio_version_string"
+  cdioVersionString' :: C.CString
+
+
+-- | The value of the preprocessor macro @LIBCDIO_VERSION_NUM@, containing a
+-- numeric representation of the version suitable for arithmetic testing.
+libcdioVersionNum :: V.Version
+libcdioVersionNum
+    | v <= 94 = V.makeVersion [0, v]
+    | v == 1 = V.makeVersion [1]
+    | otherwise = V.makeVersion [j, n, p]
+  where v = fromIntegral cdioVersionNum'
+        (j, v') = divMod v 10000
+        (n, p) = divMod v' 100
+
+foreign import ccall safe "cdio/compat/version.h get_cdio_version_num"
+  cdioVersionNum' :: C.CUInt
+
+
+-- | The value of the preprocessor macro @CDIO_API_VERSION@, containing a
+-- single, monotonically increasing constant representing changes to the public
+-- interface.  However, as it's somewhat unclear what changes warrant bumping
+-- this number, it is typically better to use 'libcdioVersionNum' instead.
+apiVersion :: Word
+apiVersion = fromIntegral apiVersion'
+
+foreign import ccall safe "cdio/compat/version.h get_cdio_version_api"
+  apiVersion' :: C.CUInt
diff --git a/src/Sound/Libcdio.hs b/src/Sound/Libcdio.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/Libcdio.hs
@@ -0,0 +1,48 @@
+{-# OPTIONS_HADDOCK not-home #-}
+
+{-|
+Description:    High-level bindings providing a idiomatic Haskell interface to libcdio.
+
+Copyright:      (c) 2019-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+One of the goals of these bindings is to make it not only possible to interface
+with the libcdio library, but to do so as comfortably and safely as possible.
+In that, the "Foreign.Libcdio" interface is a bit lacking, due to its mutable
+state and requirement of threading 'IO' through computations.  The modules in
+this namespace provide an alternative which builds on that base, with a more
+native style.  As a general rule, a project should /only/ import modules from
+the @Sound@ or the @Foreign@ namespaces, not both, as while the types can often
+be interchanged, several function names have been reused and so may collide.
+-}
+module Sound.Libcdio
+    ( -- * Types
+      -- ** Session
+      Cdio
+    , CdioError ( .. )
+    , CdioErrorType ( .. )
+    , SessionArg ( .. )
+    , AccessMode ( .. )
+      -- ** Version
+    , Foreign.Version
+    , Foreign.makeVersion
+      -- * Evaluation
+    , open
+    , openMode
+    , runCdio
+    , getArg
+    , getAccessMode
+      -- * Library data
+    , Foreign.cdioVersionString
+    , Foreign.libcdioVersionNum
+    , Foreign.apiVersion
+    ) where
+
+
+import qualified Foreign.Libcdio.Version as Foreign
+
+import Sound.Libcdio.Types.Cdio
diff --git a/src/Sound/Libcdio/Common.hs b/src/Sound/Libcdio/Common.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/Libcdio/Common.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE CPP #-}
+
+module Sound.Libcdio.Common
+    ( (<>)
+    , CBool
+    ) where
+
+
+#if MIN_VERSION_base(4,11,0)
+#else
+import Data.Monoid ( (<>) )
+#endif
+
+
+#if MIN_VERSION_base(4,10,0)
+import Foreign.C.Types ( CBool )
+#else
+import qualified Foreign.C.Types as C
+type CBool = C.CUChar
+#endif
diff --git a/src/Sound/Libcdio/Device.hs b/src/Sound/Libcdio/Device.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/Libcdio/Device.hs
@@ -0,0 +1,143 @@
+{-|
+Description:    Information and procedures related to a system's (usually) physical disc drives.
+
+Copyright:      (c) 2019-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+Any software dealing with CDs has to deal with the fact that they are,
+ultimately, a physical medium and thus reading from them requires interfacing
+with system hardware.  This module provides the means to do just that.  Note
+that, unlike the C and "Foreign.Libcdio" interfaces, however, this /doesn't/
+provide any means to open a read session; that functionality is instead
+exported directly from "Sound.Libcdio".
+-}
+module Sound.Libcdio.Device
+    ( -- * Types
+      Foreign.HardwareInfo ( .. )
+    , Foreign.emptyHardwareInfo
+    , Foreign.DriverId ( .. )
+    , Foreign.DriverReturnCode ( .. )
+      -- ** Capabilities
+    , Foreign.DriveCaps
+    , Foreign.DriveCapabilityRead ( .. )
+    , Foreign.DriveReadCaps
+    , Foreign.DriveCapabilityWrite ( .. )
+    , Foreign.DriveWriteCaps
+    , Foreign.capsWriteCd
+    , Foreign.capsWriteDvd
+    , Foreign.capsWrite
+    , Foreign.DriveCapabilityMisc ( .. )
+    , Foreign.DriveMiscCaps
+      -- * Drivers
+    , driver
+    , Foreign.drivers
+    , Foreign.osDriver
+    , isImageDriver
+    , isDevice
+      -- * Session
+    , setBlocksize
+    , setSpeed
+    , isMediaChanged
+      -- * Devices
+    , Foreign.devices
+    , Foreign.defaultDevice
+    , Foreign.defaultDeviceDriver
+    , capabilities
+    , deviceCapabilities
+      -- ** Images
+    , isCue
+    , Foreign.isToc
+    , Foreign.isNrg
+      -- ** Hardware
+    , hardware
+    , haveAtapi
+    , ejectDevice
+    , closeDeviceTray
+    , closeDeviceTray'
+    ) where
+
+
+import qualified Data.Maybe as Y
+
+import qualified Foreign.Libcdio.Device as Foreign
+
+import Sound.Libcdio.Types.Cdio
+
+
+-- | Get the driver through which the disc is being read.
+driver :: Cdio Foreign.DriverId
+driver = liftCdio $ fmap (Y.fromMaybe Foreign.DriverUnknown) . Foreign.driverId
+
+-- | Whether a particular driver deals with image files saved to disc, or a CD
+-- drive itself.
+isImageDriver :: Foreign.DriverId -> Bool
+isImageDriver = not . flip elem Foreign.deviceDrivers
+
+
+-- | Get a description of the device in use.
+hardware :: Cdio Foreign.HardwareInfo
+hardware = liftCdio $ fmap (Y.fromMaybe Foreign.emptyHardwareInfo) . Foreign.hwinfo
+
+-- | Which features are provided by the current device.  See
+-- 'deviceCapabilities' when a session has not yet been opened.
+capabilities :: Cdio Foreign.DriveCaps
+capabilities = liftCdio Foreign.driveCap
+
+-- | Whether ATAPI commands are understood by the current device.
+-- 
+-- Returns 'Nothing' if the capability can't be determined.
+haveAtapi :: Cdio (Maybe Bool)
+haveAtapi = liftCdio Foreign.haveAtapi
+
+
+-- | Which features are provided by a particular device.  See 'capabilities'
+-- for accessing these within a 'Cdio' session.
+deviceCapabilities :: FilePath -> IO Foreign.DriveCaps
+deviceCapabilities = Foreign.driveCapDevice
+
+
+-- | Open a particular device's tray or otherwise free any disc it holds for
+-- removal, replacement, or insertion.
+ejectDevice :: Maybe FilePath -> IO Foreign.DriverReturnCode
+ejectDevice = Foreign.ejectDrive
+
+-- | If a device supports discs on an extending, motorized tray (i.e. a
+-- standard CD drive), close it.
+closeDeviceTray :: Maybe FilePath -> IO Foreign.DriverReturnCode
+closeDeviceTray = fmap fst . flip Foreign.closeTray Foreign.DriverUnknown
+
+-- | As 'closeDeviceTray'', but specify the driver to use in case of ambiguity.
+closeDeviceTray' :: Maybe FilePath -> Foreign.DriverId -> IO Foreign.DriverReturnCode
+closeDeviceTray' p = fmap fst . Foreign.closeTray p
+
+
+-- | Specify how much data should be read from a disc at once.  Note that this
+-- only affects the transport; any reading functions operate on independant
+-- byte counts or other sizes derived from such.
+setBlocksize :: Int -> Cdio Foreign.DriverReturnCode
+setBlocksize s = liftCdio $ flip Foreign.setBlocksize s
+
+-- | Specify the speed at which the disc is read.  Lower values result in
+-- slower IO, but better accuracy.
+setSpeed :: Int -> Cdio Foreign.DriverReturnCode
+setSpeed s = liftCdio $ flip Foreign.setSpeed s
+
+
+-- | Check if any data in the read session has been changed since the last call
+-- of this function.  This is most helpful when multiple 'Cdio' computations
+-- are run on a partial call of 'Sound.Libcdio.Types.Cdio.open' or similar.
+isMediaChanged :: Cdio (Either Foreign.DriverReturnCode Bool)
+isMediaChanged = liftCdio Foreign.isMediaChanged
+
+
+-- | Whether a file is valid according to the (loose) CUE standard.
+isCue :: FilePath -> IO Bool
+isCue = fmap Y.isJust . Foreign.binFromCue
+
+-- | Whether the path represents a physical disc drive in the system.
+isDevice :: FilePath -> IO Bool
+isDevice = flip Foreign.isDevice Foreign.DriverDevice
diff --git a/src/Sound/Libcdio/Logging.hs b/src/Sound/Libcdio/Logging.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/Libcdio/Logging.hs
@@ -0,0 +1,92 @@
+{-|
+Description:    Control over and access to library log output.
+
+Copyright:      (c) 2020-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+The underlying library is rather loud in its error and warning messages,
+potentially emitting a lot of impure terminal clutter even on some
+otherwise-pure functions.  Very helpfully, it also provides a mechanism for
+integrating the logs with whatever framework is in place for the larger
+project; that mechanism can be leveraged to cache the logs in memory until
+specifically asked for, at which point they can be packaged into Haskell types.
+Some of the immediacy—and therefore user ability to match note to source—is
+unfortunately lost, but the apparent purity is worth it.
+-}
+module Sound.Libcdio.Logging
+    ( -- * Types
+      LibcdioLogger ( .. )
+    , Foreign.LogEntry ( .. )
+    , Foreign.LogLevel ( .. )
+      -- * Utility
+    , isolateLogs
+    , Foreign.setupLogger
+    ) where
+
+
+import qualified Foreign.Libcdio.Logging as Foreign
+
+
+-- | An environment which integrates the libcdio logging interface; will almost
+-- always be a 'Monad', but as an 'Applicative' might technically be able to
+-- implement these, that constraint isn't enforced.
+class LibcdioLogger m where
+    logCutoff :: m Foreign.LogLevel
+        -- ^ Check the current minimum severity which will be recorded in the
+        -- logs.
+    setLogCutoff :: Foreign.LogLevel -> m ()
+        -- ^ Set the minimum severity required for a message to be recorded in
+        -- the logs.
+    readLog :: m [Foreign.LogEntry]
+        -- ^ Retrieve all messages currently in the log for further processing.
+        -- Note that this retains the contents of the log for future calls; to
+        -- remove them, a separate call to 'clearLog' must be made.
+        --
+        -- >>> putLog $ LogEntry LogWarn "Testing log reading" >>= readLog
+        -- [LogEntry LogWarn "Testing log reading"]
+        --
+        -- >>> clearLog >>= readLog
+        -- []
+    clearLog :: m ()
+        -- ^ Empty all messages currently in the log.  There is no way to
+        -- selectively remove only some messages; if that is desired, call
+        -- 'readLog' first:
+        --
+        -- >>> setupLogger
+        -- >>> msgs <- readLog
+        -- >>> clearLog
+        -- >>> mapM_ putLog $ filter p msgs
+    putLog :: Foreign.LogEntry -> m ()
+        -- ^ Append a message to the logs.
+
+-- | The required initialization function 'Foreign.setupLogger' isn't called
+-- automatically; /make sure/ to do so manually before using any of these.
+instance LibcdioLogger IO where
+    logCutoff = Foreign.logCutoff
+    setLogCutoff = Foreign.setLogCutoff
+    readLog = Foreign.readLog
+    clearLog = Foreign.clearLog
+    putLog = Foreign.putLog
+
+
+-- | Keep the monad pure by preventing it from reading stale logs, but since
+-- the outer IO might still care about them, restore the entire stack after.
+--
+-- Note that the logs are /not/ thread-safe; messages from other threads may be
+-- interwoven with those from the passed computation even after this function
+-- is called.
+isolateLogs :: (Monad m, LibcdioLogger m) => m a -> m a
+isolateLogs a' = do
+    es <- readLog
+    clearLog
+
+    a <- a'
+    es' <- readLog
+    clearLog
+
+    mapM_ putLog $ es ++ es'
+    return a
diff --git a/src/Sound/Libcdio/Read/CdText.hs b/src/Sound/Libcdio/Read/CdText.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/Libcdio/Read/CdText.hs
@@ -0,0 +1,415 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+
+{-|
+Description:    Functions providing metadata about the contents of a disc.
+
+Copyright:      (c) 2019-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+Metadata is stored in a binary format both library-internally and on the disc.
+Most audio archivists will recognize it as "those information fields in a CUE
+file" (though there are [other
+formats](https://www.gnu.org/software/libcdio/cd-text-format.html#Sony-Text-File-Format-_0028Input-Sheet-Version-0_002e7T_0029)
+as well), and casual listeners will recognize it as the scrolling text that
+you're always happy to see, on the rare times your music player shows it.
+Little-used and even-less-known, however, is that a single disc can
+theoretically contain metadata in up to eight different languages; because of
+the complexity that introduces, it makes more sense to use a second monadic
+interface than to try to provide a single monolithic datatype within 'Cdio'.
+-}
+module Sound.Libcdio.Read.CdText
+    ( -- * Types
+      CdText
+    , CdTextError ( .. )
+    , CdTextErrorType ( .. )
+    , Info ( .. )
+    , emptyInfo
+    , Foreign.Genre ( .. )
+    , Foreign.Language ( .. )
+      -- * Evaluation
+    , cdText
+    , parseCdText
+    , withLanguage
+    , withIndex
+    , withAll
+    , runCdText
+      -- * Data
+    , language
+    , languages
+    , firstTrack
+    , lastTrack
+    , info
+    , discId
+    , genre
+    , cdTextRaw
+    ) where
+
+
+import qualified Control.Applicative as A
+#if MIN_VERSION_mtl(2,2,1)
+import qualified Control.Monad.Except as N.E
+#else
+import qualified Control.Monad.Error as N.E
+#endif
+import qualified Control.Monad.Fail as N.F
+
+import qualified Data.ByteString as BS
+import qualified Data.Maybe as Y
+import qualified Data.Text as T
+
+import qualified Foreign.Libcdio.CdText as Foreign
+import qualified Foreign.Libcdio.Disc as Foreign
+import qualified Foreign.Libcdio.Logging as Foreign
+
+import qualified Text.Show as R
+
+import Sound.Libcdio.Logging
+import Sound.Libcdio.Track
+import Sound.Libcdio.Types.Cdio
+
+import Control.Applicative ( (<|>) )
+import Data.Functor ( ($>) )
+
+
+-- | A computation within the environment of metadata (in a particular
+-- language) stored on a CD.  The options for affecting that environment
+-- from within are limited by design, as this library is intended for /reading/
+-- discs rather than /authoring/ them.
+newtype CdText a = CdText (Maybe InitialLanguage -> Foreign.Cdio -> IO (Either CdTextError a))
+instance Functor CdText where
+    fmap f (CdText a) = CdText $ \l c -> fmap f <$> a l c
+instance Applicative CdText where
+    pure a = CdText $ \_ _ -> return $ Right a
+    CdText f <*> CdText a = CdText $ \l c -> do
+        f' <- f l c
+        a' <- a l c
+        return $ f' <*> a'
+-- | 'A.empty' fails with 'CdTextEmpty'.
+instance A.Alternative CdText where
+    empty = CdText $ \_ _ -> return . Left . CdTextError CdTextEmpty $ T.pack "empty"
+    CdText f <|> CdText g = CdText $ \l c -> f l c <|> g l c
+instance Monad CdText where
+    CdText a >>= f = CdText $ \l c -> do
+        a' <- a l c
+        let bind' a'' = let CdText b = f a'' in b l c
+        either (return . Left) bind' a'
+-- | Wraps the text in a 'FreeformCdTextError', for recovery with 'N.E.catchError'.
+instance N.F.MonadFail CdText where
+    fail e = CdText $ \_ _ ->
+        return . Left $ CdTextError (FreeformCdTextError $ T.pack e) (T.pack "fail")
+instance N.E.MonadError CdTextError CdText where
+    throwError err = CdText $ \_ _ -> return $ Left err
+    catchError (CdText f) e = CdText $ \l c -> f l c >>= \a' -> case a' of
+        Left err ->
+            let CdText g = e err
+            in  g l c
+        Right a -> return $ Right a
+instance LibcdioLogger CdText where
+    logCutoff = CdText $ \_ _ -> Right <$> Foreign.logCutoff
+    setLogCutoff l = CdText $ \_ _ -> Right <$> Foreign.setLogCutoff l
+    readLog = CdText $ \_ _ -> Right <$> Foreign.readLog
+    clearLog = CdText $ \_ _ -> Right <$> Foreign.clearLog
+    putLog e = CdText $ \_ _ -> Right <$> Foreign.putLog e
+
+-- | Lift a metadata computation from the C-style "Foreign.Libcdio" interface
+-- into the monadic "Sound.Libcdio".
+liftCdText :: (Foreign.Cdio -> IO a) -> CdText a
+liftCdText f = CdText $ \_ c -> Right <$> f c
+
+
+-- | Associates a well-typed error with human-readable context information.
+data CdTextError = CdTextError CdTextErrorType T.Text
+  deriving ( Eq, Show, Read )
+
+-- | Potential situations which may cause a computation to fail.
+data CdTextErrorType
+    = InvalidBlock Word
+        -- ^ The requested language index is outside of the bounds accessible
+        -- by the library (@[0..7]@ in libcdio 2.1 and after, or the smaller
+        -- range of languages returned by 'languages' before that version).
+    | LanguageNotFound Foreign.Language
+        -- ^ The CdText data does not contain the requested language, or
+        -- 'Foreign.UnknownLanguage' was requested (prior to libcdio 2.1 there
+        -- was no way to select the latter blocks; even after that version,
+        -- 'withIndex' must be used instead).
+    | BadBinaryRead
+        -- ^ The binary data can not be parsed into a CdText object.
+    | NoCdText
+        -- ^ The CD contains no CdText data.
+    | CdTextEmpty
+        -- ^ 'A.empty' was called and no better alternative was encountered.
+    | FreeformCdTextError T.Text
+        -- ^ Escape hatch from structured typing to allow user-specified
+        -- (and user-triggered) errors.
+  deriving ( Eq, Show, Read )
+
+
+-- | The language which was active at the beginning of the 'CdText'
+-- computation.
+data InitialLanguage
+    = Lang Foreign.Language
+        -- ^ The language was chosen specifically.
+    | Index Word
+        -- ^ The language was chosen by index.
+    | Default
+        -- ^ No language was explicitly set.
+
+-- | Restore the active language to whatever it was before a 'CdText'
+-- computation was run.
+resetLanguage :: Maybe InitialLanguage -> Foreign.Cdio -> IO ()
+resetLanguage Nothing _ = mempty
+resetLanguage (Just (Lang l)) c = Foreign.selectLanguage c l >> mempty
+resetLanguage (Just (Index i)) c = Foreign.selectLanguageIndex c i >> mempty
+resetLanguage (Just Default) c = Foreign.selectLanguageIndex c 0 >> mempty
+
+
+-- | Textual metadata describing a single track on a disc, or the disc itself.
+data Info = Info
+    { title      :: Maybe T.Text
+    , performer  :: Maybe T.Text
+    , songwriter :: Maybe T.Text
+    , composer   :: Maybe T.Text
+    , arranger   :: Maybe T.Text
+    , message    :: Maybe T.Text
+        -- ^ An otherwise-uncategorized comment.
+    , code       :: Maybe T.Text
+        -- ^ Either a UPC/EAN (for the disc) or an ISRC (for a track).
+    }
+  deriving ( Eq )
+-- | Modeled after the standard record syntax, but omitting any 'Nothing'
+-- fields for space reasons.
+instance Show Info where
+    showsPrec d ts = R.showParen (d > 10)
+        $ R.showString "Info { "
+        . maybeShows title "title"
+        . maybeShows performer "performer"
+        . maybeShows songwriter "songwriter"
+        . maybeShows composer "composer"
+        . maybeShows arranger "arranger"
+        . maybeShows message "message"
+        . maybeShows code "code"
+        . R.showString "}"
+      where maybeShows f n
+                | Just t <- f ts =
+                      R.showString (n ++ " = ")
+                    . shows t
+                    . R.showString ", "
+                | otherwise = id
+instance Read Info where
+    readsPrec p =
+           readParen (p > 10) $ \r ->
+            [ (Info t f w c a m o, r10)
+            | ("Info", r1) <- lex r
+            , ("{", r2) <- lex r1
+            , (t, r3) <- maybeLex "title" r2
+            , (f, r4) <- maybeLex "performer" r3
+            , (w, r5) <- maybeLex "songwriter" r4
+            , (c, r6) <- maybeLex "composer" r5
+            , (a, r7) <- maybeLex "arranger" r6
+            , (m, r8) <- maybeLex "message" r7
+            , (o, r9) <- maybeLex "code" r8
+            , ("}", r10) <- lex r9
+            ]
+      where maybeLex t s' = do
+                (t', s1) <- lex s'
+                if t == t'
+                then do
+                    ("=", s2) <- lex s1
+                    (x, s3) <- reads s2
+                    (",", s4) <- lex s3
+                    return (Just x, s4)
+                else return (Nothing, s')
+
+-- | An 'Info' object with values suitable as defaults.
+emptyInfo :: Info
+emptyInfo = Info
+    { title      = Nothing
+    , performer  = Nothing
+    , songwriter = Nothing
+    , composer   = Nothing
+    , arranger   = Nothing
+    , message    = Nothing
+    , code       = Nothing
+    }
+
+
+-- | Use a C-style 'Foreign.Cdio' object as the base to run a Haskell-style
+-- 'CdText' computation.
+-- 
+-- Note that some invariants of the monadic interface may not work as expected
+-- when used with the mutable objects, usually due to changing the active
+-- language block:
+-- 
+-- @
+-- l  <- 'Foreign.language' cdio
+-- _  <- 'runCdText' cdio $ 'withIndex' i g
+-- l' <- 'Foreign.language' cdio
+-- (l == l') == undefined
+-- @
+runCdText :: Foreign.Cdio -> CdText a -> IO (Either CdTextError a)
+runCdText c (CdText f) = isolateLogs $ f Nothing c
+
+
+-- | Run the given computation within the CdText data associated with the
+-- 'Cdio' session.  At this top level, a @'withIndex' 0@ specifically will
+-- almost always have the same effect as running the computation directly.
+-- Fails with 'NoCdText' if the disc doesn't provide any metadata.
+cdText :: CdText a -> Cdio (Either CdTextError a)
+cdText (CdText f) = liftCdio $ \c' -> if Foreign.hasCdText c'
+    then isolateLogs $ f (Just Default) c'
+    else return . Left . CdTextError NoCdText $ T.pack "cdText"
+
+-- | Given a binary stream, attempt to parse it as a CdText block and run the
+-- given computation.  Returns @'Left' 'BadBinaryRead'@ if that parse fails.
+-- At this top level, a @'withIndex' 0@ specifically will almost always have
+-- the same effect as running the computation directly.
+--
+-- Note that binary CdText dumps will frequently include four bytes at the
+-- beginning indicating the size of the file; this implementation expects that
+-- those bytes /are not/ included.  If your dump does indeed begin with them,
+-- @'BS.drop' 4@ before passing the 'BS.ByteString' to this function.
+--
+-- /Before libcdio 0.94:  Always returns @'Left' 'BadBinaryRead'@/
+parseCdText :: BS.ByteString -> CdText a -> IO (Either CdTextError a)
+parseCdText bs (CdText f) = isolateLogs $ do
+    c <- Foreign.cdTextDataInit bs
+    case c of
+        Just c' -> f (Just Default) c'
+        Nothing -> return . Left . CdTextError BadBinaryRead $ T.pack "parseCdText"
+
+
+-- | Try to use a specific language as the context for the given computation;
+-- as this will frequently fail with 'LanguageNotFound' if given anything other
+-- than 'Foreign.English', it is recommended that you provide a fallback with
+-- 'A.<|>' or at least allow recovery with 'A.optional'.  Note that
+-- 'Foreign.UnknownLanguage' will always fail.
+withLanguage :: Foreign.Language -> CdText a -> CdText a
+withLanguage l (CdText f) = CdText $ \l' c -> isolateLogs $ do
+    b <- Foreign.selectLanguage c l
+    a <- if b
+        then f (Just $ Lang l) c
+        else return . Left . CdTextError (LanguageNotFound l) $ T.pack "withLanguage"
+    resetLanguage l' c
+    return a
+
+-- | Run the given computation over the data in a specific block.  Fails with
+-- 'InvalidBlock' if the index can't be accessed.
+withIndex :: Word -> CdText a -> CdText a
+withIndex i x = CdText $ \l c -> do
+    a <- withIndex' "withIndex" c x i
+    resetLanguage l c
+    return a
+
+-- | Underlying logic for index-based block selection.  Fails with
+-- 'InvalidBlock' if the index can't be accessed.
+withIndex'
+    :: String
+        -- ^ The function calling this, for error printing.
+    -> Foreign.Cdio
+        -- ^ The underlying disc session.
+    -> CdText a
+        -- ^ The computation to run.
+    -> Word
+        -- ^ The index to select.
+    -> IO (Either CdTextError a)
+withIndex' s c (CdText f) i = do
+    b <- Foreign.selectLanguageIndex c i
+    if b
+    then f (Just $ Index i) c
+    else return . Left . CdTextError (InvalidBlock i) $ T.pack s
+
+-- | Run the given computation over /all/ of the accessible languages in the
+-- CdText data.  When successful, the resulting list can be associated exactly
+-- with the list of 'languages':
+--
+-- >>> ls <- 'languages'
+-- >>> Right ls' <- 'cdText' $ 'withAll' 'language'
+-- >>> ls == ls'
+-- True
+withAll :: CdText a -> CdText [Maybe a]
+withAll x = CdText $ \l c -> do
+    ls <- Foreign.listAllLanguages c
+    let is = zipWith ($>) ls [0..]
+    as <- mapM (withBlock c) is
+    resetLanguage l c
+    return $ sequence as
+  where withBlock c (Just i) = fmap Just <$> withIndex' "withAll" c x i
+        withBlock _ Nothing = return $ Right Nothing
+
+
+-- | Get the raw binary data making up the CdText data, if any exists on the
+-- disc.
+cdTextRaw :: Cdio (Maybe BS.ByteString)
+cdTextRaw = liftCdio Foreign.cdTextRaw
+
+
+-- | Get the language in which any info is currently being retrieved.
+language :: CdText Foreign.Language
+language = liftCdText $ fmap (Y.fromMaybe Foreign.UnknownLanguage) . Foreign.language
+
+-- | List every language with associated data in the CdText data associated
+-- with the session.  Drops any 'Foreign.UnknownLanguage' values from the end
+-- of the list.  For a version which operates within the 'CdText' monad, the
+-- construction @'withAll' 'language'@ will have an identical effect.
+--
+-- /Before libcdio 2.1.0:  Silently drops any 'Nothing' or/
+-- /@'Just' 'Foreign.UnknownLanguage'@ values, even in the middle of the list,/
+-- /and only lists any single language a maximum of one time./
+languages :: Cdio [Maybe Foreign.Language]
+languages = liftCdio Foreign.listAllLanguages
+
+
+-- | The earliest track with any associated metadata in the current language.
+-- Note that this may differ from 'Sound.Libcdio.Track.minTrack' which gives
+-- the first track on the disk, CDTEXT or not.
+firstTrack :: CdText Track
+firstTrack = liftCdText $ fmap (Y.fromMaybe 1) . Foreign.firstTrack
+
+-- | The final track with any associated metadata in the current language.
+-- Note that this may differ from 'Sound.Libcdio.Track.maxTrack' which gives
+-- the last track on the disc, CDTEXT or not.
+lastTrack :: CdText Track
+lastTrack = liftCdText $ fmap (Y.fromMaybe 1) . Foreign.lastTrack
+
+
+-- | Publisher-specific catalogue number, or some other context-specific
+-- identifier.  Note that this may be different than @'code' $ 'info'
+-- 'Nothing'@ which is (assumed to be) the unambiguous bar code unique to this
+-- disc release.
+discId :: CdText (Maybe T.Text)
+discId = liftCdText $ \c -> fmap T.pack <$> Foreign.cdTextGet c Foreign.DiscId Nothing
+
+-- | The genre describing the music on this disc, and any associated
+-- human-readable name or subgenre.
+genre :: CdText (Maybe Foreign.Genre, Maybe T.Text)
+genre = liftCdText $ \c -> do
+    g <- Foreign.genre c
+    s <- Foreign.cdTextGet c Foreign.GenreName Nothing
+    return (g, T.pack <$> s)
+
+
+-- | Retrieve the collection of data associated with a specific track, or if
+-- 'Nothing', the disc itself.
+info :: Maybe Track -> CdText Info
+info t = liftCdText $ \c -> do
+    l <- Foreign.cdTextGet c Foreign.Title t
+    p <- Foreign.cdTextGet c Foreign.Performer t
+    s <- Foreign.cdTextGet c Foreign.Songwriter t
+    w <- Foreign.cdTextGet c Foreign.Composer t
+    a <- Foreign.cdTextGet c Foreign.Arranger t
+    m <- Foreign.cdTextGet c Foreign.Message t
+    o <- Foreign.cdTextGet c (if Y.isNothing t then Foreign.UpcEan else Foreign.Isrc) t
+    return $ Info
+        { title = T.pack <$> l
+        , performer = T.pack <$> p
+        , songwriter = T.pack <$> s
+        , composer = T.pack <$> w
+        , arranger = T.pack <$> a
+        , message = T.pack <$> m
+        , code = T.pack <$> o
+        }
diff --git a/src/Sound/Libcdio/Read/Data.hs b/src/Sound/Libcdio/Read/Data.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/Libcdio/Read/Data.hs
@@ -0,0 +1,173 @@
+{-|
+Description:    Methods of retreaving the actual stored data.
+
+Copyright:      (c) 2019-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+This module is likely what most usage of the library revolves around:
+retrieving the data stored on a CD.  For more discussion of the layout, see
+"Foreign.Libcdio.Sector".
+-}
+module Sound.Libcdio.Read.Data
+    ( -- * Types
+      Foreign.Lsn
+    , Foreign.Whence ( .. )
+    , Foreign.DiscMode ( .. )
+    , Foreign.isCdRom
+    , Foreign.isDvd
+      -- * Info
+    , discMode
+    , discJolietLevel
+    , lastAddress
+    , lastSessionAddress
+    , audioTimestamp
+    , catalogue
+    , isrc
+      -- * Read
+      -- $read-design
+    , seek
+    , readRaw
+    , readAudio
+    , readData
+    , readXa
+      -- * Basic counts
+    , Foreign.framesPerSec
+    , maxCdSectors
+    , maxCdMinutes
+    , defaultPregapSectors
+    , defaultPostgapSectors
+    ) where
+
+
+import qualified Data.ByteString as BS
+import qualified Data.Text as T
+
+import qualified Foreign.Libcdio.Device as Foreign
+import qualified Foreign.Libcdio.Disc as Foreign
+import qualified Foreign.Libcdio.Read as Foreign
+import qualified Foreign.Libcdio.Sector as Foreign
+import qualified Foreign.Libcdio.Track as Foreign
+
+import Sound.Libcdio.Device
+import Sound.Libcdio.Types.Cdio
+
+
+-- | Determine which type of disc is being accessed.
+discMode :: Cdio (Maybe Foreign.DiscMode)
+discMode = liftCdio Foreign.discMode
+
+-- | The original ISO 9660 (data) filesystem specification was rather
+-- restrictive in what files could be named; the Joliet extensions allow such
+-- exciting features as lowercase letters, not to mention full Unicode support.
+discJolietLevel :: Cdio (Maybe Word)
+discJolietLevel = liftCdio Foreign.discJolietLevel
+
+
+-- | Get the size of a disc in blocks, or equivalently the address of the end
+-- of the readable data.
+lastAddress :: Cdio (Maybe Foreign.Lsn)
+lastAddress = liftCdio Foreign.lastLsn
+
+-- | Get the starting address of the last write session of a disc.
+lastSessionAddress :: Cdio (Either DriverReturnCode Foreign.Lsn)
+lastSessionAddress = liftCdio Foreign.lastSession
+
+
+-- | The number of sectors spanned by a track pre-gap by default.
+defaultPregapSectors :: Word
+defaultPregapSectors = Foreign.pregapSectors
+
+-- | The number of sectors spanned by a track post-gap by default.
+defaultPostgapSectors :: Word
+defaultPostgapSectors = Foreign.postgapSectors
+
+
+-- | Print a disc timestamp in the standard "MM:SS:FF" format, assuming the
+-- address refers to audio data.
+audioTimestamp :: Foreign.Lsn -> T.Text
+audioTimestamp = T.pack . Foreign.msfToStr . Foreign.lsnToMsf
+
+-- | The maximum number of sectors allowed to be stored on a disc.
+maxCdSectors :: Word
+maxCdSectors = Foreign.maxSectors
+
+-- | The typical maximum length of a disc, though it's not a strict limit.
+maxCdMinutes :: Word
+maxCdMinutes = Foreign.cdMins
+
+
+-- | Get the media catalog number from a disc.  This may also be retrieved
+-- by @'Sound.Libcdio.Read.CdText.code' $ 'Sound.Libcdio.Read.CdText.info'
+-- 'Nothing'@, though that references a different source and thus may not have
+-- the same return value.
+catalogue :: Cdio (Maybe T.Text)
+catalogue = liftCdio $ \c -> fmap T.pack <$> Foreign.cdMcn c
+
+-- | The International Standard Recording Code the given track.  This may also
+-- be retrieved by @'Sound.Libcdio.Read.CdText.code' .
+-- 'Sound.Libcdio.Read.CdText.info' $ 'Just' t@, though that references a
+-- different source and thus may not have the same return value.
+isrc :: Foreign.Track -> Cdio (Maybe T.Text)
+isrc t = liftCdio $ \c -> fmap T.pack <$> Foreign.trackIsrc c t
+
+
+-- $read-design
+-- For now, the library isn't able to automatically determine which @read*@
+-- function should be used; refer to 'Sound.Libcdio.Track.format', and switch
+-- on its return value.  For more info on the various data layouts, see the
+-- intro to "Foreign.Libcdio.Sector".
+--
+-- Compared to the C and @Foreign@ interfaces, /all/ read functions have been
+-- tweaked for better internal consistency.  Where a @cdio_read@ or
+-- 'Foreign.readBytes' call would ask for the number of bytes to read, here it
+-- asks for the number of /sectors/.  On the other hand, the formerly
+-- sector-oriented commands operate from the current 'seek' position rather
+-- than, effectively, hiding a 'seek' behind the scenes.
+
+
+-- | Reposition the read pointer in the 'Cdio' session for a future call to
+-- one of the @read*@ functions.
+seek :: Int -> Foreign.Whence -> Cdio Foreign.Lsn
+seek o w = liftCdioError $ \c -> do 
+    o' <- Foreign.seek c (o * fromIntegral Foreign.sectorSize) w
+    pos <- case flip mod Foreign.sectorSize <$> o' of
+        Right drift | drift /= 0 -> Foreign.seek c (fromIntegral $ negate drift) Foreign.SeekCurrent
+        _ -> return o'
+    return . packCdioError' "seek" $ fromIntegral . flip div Foreign.sectorSize <$> pos
+
+
+-- | Read a given number of sectors from the disc.  With data of a known
+-- structure, use 'readAudio', 'readData', or 'readXa', which /don't/ include
+-- the headers and footers described in "Foreign.Libcdio.Sector".
+readRaw :: Word -> Cdio BS.ByteString
+readRaw l = liftCdioError $ \c -> do
+    bs <- Foreign.readBytes c (l * Foreign.sectorSize)
+    return . packCdioError' "readAudio" $ maybe (Left Foreign.DriverError) Right bs
+
+-- | Read a given number of sectors stored as CD-DA from the disc.
+readAudio :: Word -> Cdio BS.ByteString
+readAudio l = seek 0 Foreign.SeekCurrent >>= liftCdioError' (\c o ->
+    packCdioError' "readAudio" <$> Foreign.readAudioSectors c o l)
+
+-- | Read a given number of sectors stored as Mode 1 data from the disc.
+readData
+    :: Bool
+        -- ^ If 'True' Form 2, otherwise Form 1 (see "Foreign.Libcdio.Sector").
+    -> Word
+    -> Cdio BS.ByteString
+readData m l = seek 0 Foreign.SeekCurrent >>= liftCdioError' (\c o ->
+    packCdioError' "readData" <$> Foreign.readDataModeSectors c o m l)
+
+-- | Read a given number of sectors stored according to the Mode 2 extension
+-- from the disc.
+readXa
+    :: Bool
+        -- ^ If 'True' Form 2, otherwise Form 1 (see "Foreign.Libcdio.Sector").
+    -> Word
+    -> Cdio BS.ByteString
+readXa f l = seek 0 Foreign.SeekCurrent >>= liftCdioError' (\c o ->
+    packCdioError' "readXA" <$> Foreign.readXaModeSectors c o f l)
diff --git a/src/Sound/Libcdio/Read/Filesystem.hs b/src/Sound/Libcdio/Read/Filesystem.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/Libcdio/Read/Filesystem.hs
@@ -0,0 +1,40 @@
+{-|
+Description:    Objects used to describe the CD and filesystem format.
+
+Copyright:      (c) 2020-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+Like any drive, discs may store their data according to many different
+filesystem structures.  These are abstracted to a degree in libcdio, but as
+each track may store its data differently, and at the very least
+'Foreign.Audio' is handled differently than any of the file-oriented layouts,
+it is still helpful to know the underlying structure.  This module, then, is a
+counterpart to "Sound.Libcdio.Read.Data", providing information about the
+/structure/ for the latter's retrieval of /data/.
+-}
+module Sound.Libcdio.Read.Filesystem
+    ( -- * Types
+      Foreign.Filesystem ( .. )
+    , Foreign.FilesystemClass ( .. )
+    , Foreign.FilesystemClasses
+    , Foreign.fsAny
+    , Foreign.fsAnyVcd
+    , Foreign.IsoAnalysis ( .. )
+      -- * Query
+    , trackType
+    ) where
+
+
+import qualified Foreign.Libcdio.CdTypes as Foreign
+
+import Sound.Libcdio.Track
+import Sound.Libcdio.Types.Cdio
+
+
+-- | Determine what type of file system is stored in the given track of a disc.
+trackType :: Track -> Cdio (Maybe Foreign.Filesystem, Foreign.FilesystemClasses, Maybe Foreign.IsoAnalysis)
+trackType = liftCdio . flip Foreign.trackType
diff --git a/src/Sound/Libcdio/Track.hs b/src/Sound/Libcdio/Track.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/Libcdio/Track.hs
@@ -0,0 +1,128 @@
+{-|
+Description:    Information about the division of a single disc into tracks.
+
+Copyright:      (c) 2019-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+
+What many people would think of as the most important division on a CD isn't
+quite as an integral a part of the physical data layout: they are described in
+a table of contents before the first track of any recording session, and may
+have lower-resolution "echoes" in the subchannels alongside the data, but it
+would be hard to otherwise recover the track boundaries from the data itself.
+This module, then, provides the functions to retrieve that metadata from the
+table of contents and from the subchannels.
+-}
+module Sound.Libcdio.Track
+    ( -- * Types
+      Foreign.Track ( .. )
+    , Foreign.minTrack
+    , Foreign.maxTrack
+    , Foreign.TrackNum
+    , Foreign.TrackFormat ( .. )
+      -- * Location
+    , firstDiscTrack
+    , lastDiscTrack
+    , tracks
+      -- ** Address
+    , trackAt
+    , pregap
+    , offset
+    , offsetEnd
+    , totalLength
+      -- * Data
+    , format
+    , isGreen
+    , hasPreemphasis
+    , copyPermit
+    , quadAudio
+    ) where
+
+
+import qualified Foreign.Libcdio.Disc as Foreign
+import qualified Foreign.Libcdio.Track as Foreign
+
+import Sound.Libcdio.Read.Data
+import Sound.Libcdio.Types.Cdio
+
+
+-- | The number of the first track on the disc.  This will almost always be 1,
+-- but that is not strictly guaranteed; the (perhaps theoretical) example is of
+-- a multi-disc set, where later discs pick the numbering back up where the
+-- previous one left off.
+-- 
+-- Returns 'Nothing' if the disc table of contents can't be read.
+firstDiscTrack :: Cdio (Maybe Foreign.Track)
+firstDiscTrack = liftCdio Foreign.firstTrackNum
+
+-- | The number of the last track on the disc.
+-- 
+-- Returns 'Nothing' if the disc table of contents can't be read.
+lastDiscTrack :: Cdio (Maybe Foreign.Track)
+lastDiscTrack = liftCdio Foreign.lastTrackNum
+
+
+-- | Get the number of tracks on a CD.
+-- 
+-- Returns 'Nothing' if the disc table of contents can't be read.
+tracks :: Cdio (Maybe Foreign.Track)
+tracks = liftCdio Foreign.numTracks
+
+-- | The track which contains the given address.
+-- 
+-- Returns 'Nothing' if the address is beyond the written data on the disc.
+-- Note that 'Foreign.DiscLeadout' is treated as if it were a single sector
+-- long:
+-- 
+-- >>> Just endTrack <- lastDiscTrack
+-- >>> Just endAddr <- offsetEnd endTrack
+-- >>> trackAt $ endAddr + 1
+-- Just DiscLeadout
+-- >>> trackAt $ endAddr + 2
+-- Nothing
+trackAt :: Lsn -> Cdio (Maybe Foreign.Track)
+trackAt = liftCdio . flip Foreign.trackAt
+
+
+-- | The address of the start of any pregap before the given track.
+pregap :: Foreign.Track -> Cdio (Maybe Lsn)
+pregap = liftCdio . flip Foreign.pregapLsn
+
+-- | The address of the start of the given track.
+offset :: Foreign.Track -> Cdio (Maybe Lsn)
+offset = liftCdio . flip Foreign.trackLsn
+
+-- | The address of the end of the given track.
+offsetEnd :: Foreign.Track -> Cdio (Maybe Lsn)
+offsetEnd = liftCdio . flip Foreign.trackLastLsn
+
+-- | The number of sectors "assigned" to the specified track, including any in
+-- the pregap between it and the following one.
+totalLength :: Foreign.Track -> Cdio (Maybe Word)
+totalLength = liftCdio . flip Foreign.sectorCount
+
+
+-- | The raw data structure of a track.
+format :: Foreign.Track -> Cdio (Maybe Foreign.TrackFormat)
+format = liftCdio . flip Foreign.trackFormat
+
+-- | Whether the track data was stored using the Green Book (CD-i) standard.
+isGreen :: Foreign.Track -> Cdio (Maybe Bool)
+isGreen = liftCdio . flip Foreign.isGreen
+
+
+-- | Whether preemphasis has been applied to the track for noise reduction.
+hasPreemphasis :: Foreign.Track -> Cdio (Maybe Bool)
+hasPreemphasis = liftCdio . flip Foreign.hasPreemphasis
+
+-- | Whether the track may be legally copied.
+copyPermit :: Foreign.Track -> Cdio (Maybe Bool)
+copyPermit = liftCdio . flip Foreign.copyPermit
+
+-- | Whether the track was encoded with a richer 4-channel structure, or
+-- whether it just includes the standard stereo (2-channel) layout.
+quadAudio :: Foreign.Track -> Cdio (Maybe Bool)
+quadAudio t = liftCdio $ \c -> fmap (> 2) <$> Foreign.numChannels c t
diff --git a/src/Sound/Libcdio/Types.hs b/src/Sound/Libcdio/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/Libcdio/Types.hs
@@ -0,0 +1,61 @@
+{-# OPTIONS_HADDOCK not-home #-}
+
+{-|
+Description:    Common types used in the high-level interface.
+
+Copyright:      (c) 2019-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+-}
+module Sound.Libcdio.Types
+    ( -- * Disc
+      Cdio
+    , CdioError
+    , CdioErrorType
+    , Whence
+    , Lsn
+    , Track
+    , TrackNum
+    , TrackFormat
+    , SessionArg
+      -- * CdText
+    , CdText
+    , CdTextError
+    , CdTextErrorType
+    , Info
+    , Genre
+    , Language
+      -- * Hardware
+    , DriverId
+    , DriverReturnCode
+    , HardwareInfo
+    , DriveCapabilityRead
+    , DriveReadCaps
+    , DriveCapabilityWrite
+    , DriveWriteCaps
+    , DriveCapabilityMisc
+    , DriveMiscCaps
+    , DriveCaps
+    , DiscMode
+      -- * Data
+    , Filesystem
+    , FilesystemClass
+    , FilesystemClasses
+    , IsoAnalysis
+      -- * Logging
+    , LibcdioLogger
+    , LogEntry
+    , LogLevel
+    ) where
+
+
+import Sound.Libcdio.Device
+import Sound.Libcdio.Logging
+import Sound.Libcdio.Read.CdText
+import Sound.Libcdio.Read.Data
+import Sound.Libcdio.Read.Filesystem
+import Sound.Libcdio.Track
+import Sound.Libcdio.Types.Cdio
diff --git a/src/Sound/Libcdio/Types/Cdio.hs b/src/Sound/Libcdio/Types/Cdio.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/Libcdio/Types/Cdio.hs
@@ -0,0 +1,243 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+
+{-|
+Description:    Internal module to allow constructor access without pollution.
+
+Copyright:      (c) 2019-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      stable
+Portability:    non-portable (requires libcdio)
+-}
+module Sound.Libcdio.Types.Cdio
+    ( Cdio
+    , CdioError ( .. )
+    , CdioErrorType ( .. )
+    , Foreign.SessionArg ( .. )
+    , Foreign.AccessMode ( .. )
+    , liftCdio
+    , liftCdio'
+    , liftCdioError
+    , liftCdioError'
+    , packCdioError
+    , packCdioError'
+    , open
+    , openMode
+    , getArg
+    , getAccessMode
+    , runCdio
+    ) where
+
+
+import qualified Control.Applicative as A
+#if MIN_VERSION_mtl(2,2,1)
+import qualified Control.Monad.Except as N.E
+#else
+import qualified Control.Monad.Error as N.E
+#endif
+import qualified Control.Monad.Fail as N.F
+
+import qualified Data.Text as T
+
+import qualified Foreign.Libcdio.Device as Foreign
+import qualified Foreign.Libcdio.Logging as Foreign
+
+import Sound.Libcdio.Logging
+
+import Control.Applicative ( (<|>) )
+import Data.Array.BitArray ( (!) )
+
+
+-- | A computation within the environment of the data (music or file) stored on
+-- a CD.  The options for affecting that environment from within are limited by
+-- design, as this library is intended for /reading/ discs rather than
+-- /authoring/ them.
+newtype Cdio a = Cdio (Foreign.Cdio -> IO (Either CdioError a))
+instance Functor Cdio where
+    fmap f (Cdio a) = Cdio $ \c -> fmap f <$> a c
+instance Applicative Cdio where
+    pure a = Cdio . const . return $ Right a
+    Cdio f <*> Cdio a = Cdio $ \c -> do
+        f' <- f c
+        a' <- a c
+        return $ f' <*> a'
+-- | 'A.empty' fails with 'CdioEmpty'.
+instance A.Alternative Cdio where
+    empty = Cdio $ \_ -> return . Left . CdioError CdioEmpty $ T.pack "empty"
+    Cdio f <|> Cdio g = Cdio $ \c -> f c <|> g c
+instance Monad Cdio where
+    Cdio a >>= f = Cdio $ \c -> do
+        a' <- a c
+        case a' of
+            Left e -> return $ Left e
+            Right x -> let Cdio b = f x in b c
+-- | Wraps the text in a 'FreeformCdioError', for recovery with 'N.E.catchError'.
+instance N.F.MonadFail Cdio where
+    fail e = Cdio . const . return . flip errorText "fail" . FreeformCdioError $ T.pack e
+instance N.E.MonadError CdioError Cdio where
+    throwError err = Cdio . const . return $ Left err
+    catchError (Cdio f) e = Cdio $ \c -> f c >>= \a' -> case a' of
+        Left err ->
+            let Cdio g = e err
+            in  g c
+        Right a -> return $ Right a
+instance LibcdioLogger Cdio where
+    logCutoff = Cdio $ \_ -> Right <$> Foreign.logCutoff
+    setLogCutoff l = Cdio $ \_ -> Right <$> Foreign.setLogCutoff l
+    readLog = Cdio $ \_ -> Right <$> Foreign.readLog
+    clearLog = Cdio $ \_ -> Right <$> Foreign.clearLog
+    putLog e = Cdio $ \_ -> Right <$> Foreign.putLog e
+
+-- | Lift a computation from the C-style "Foreign.Libcdio" interface into the
+-- monadic "Sound.Libcdio".
+liftCdio :: (Foreign.Cdio -> IO a) -> Cdio a
+liftCdio f = Cdio $ fmap Right . f
+
+-- | As 'liftCdio', but for functions which take a second argument alongside
+-- the read session.
+liftCdio' :: (Foreign.Cdio -> a -> IO b) -> a -> Cdio b
+liftCdio' f a = Cdio $ fmap Right . flip f a
+
+-- | As 'liftCdio', but for functions which may return an error code indicating
+-- failure.
+liftCdioError :: (Foreign.Cdio -> IO (Either CdioError a)) -> Cdio a
+{-# INLINE liftCdioError #-}
+liftCdioError = Cdio
+
+-- | As 'liftCdio'', but for functions which may return an error code indicating
+-- failure.
+liftCdioError' :: (Foreign.Cdio -> a -> IO (Either CdioError b)) -> a -> Cdio b
+liftCdioError' f a = Cdio $ flip f a
+
+
+-- | Associates a well-typed error with human-readable context information.
+data CdioError = CdioError CdioErrorType T.Text
+  deriving ( Eq, Show, Read )
+
+-- | Potential situations which may cause a computation to fail.
+data CdioErrorType
+    = DriverError
+        -- ^ A requested operation failed for some unknown reason, or the
+        -- operating system doesn't support the 'Sound.Libcdio.Device.DriverId'
+        -- in use.
+    | BadParameter
+        -- ^ Some value passed to a requested operation was rejected as
+        -- nonsensical or otherwise breaking the value-level invariants.
+    | NotPermitted
+        -- ^ The ability to perform a requested operation has been restricted
+        -- (e.g., the user doesn't have permission to access the disc drive).
+    | SessionClosed
+        -- ^ The underlying library closed the 'Cdio' session prematurely.
+    | Unsupported
+        -- ^ A requested operation isn't available with driver used by the
+        -- 'Cdio' session.  Refer to 'Sound.Libcdio.Device.capabilities' and
+        -- 'Sound.Libcdio.Device.deviceCapabilities' to reduce these.
+    | CdioEmpty
+        -- ^ 'A.empty' was called and no better alternative was encountered.
+    | FreeformCdioError T.Text
+        -- ^ Escape hatch from structured typing to allow user-specified
+        -- (and user-triggered) errors.
+  deriving ( Eq, Show, Read )
+
+errorText :: CdioErrorType -> String -> Either CdioError a
+errorText e = Left . CdioError e . T.pack
+
+packCdioError :: String -> Foreign.DriverReturnCode -> a -> Either CdioError a
+packCdioError _ Foreign.Success = Right
+packCdioError s Foreign.DriverError = const $ errorText DriverError s
+packCdioError s Foreign.Unsupported = const $ errorText Unsupported s
+packCdioError s Foreign.Uninitialized = const $ errorText BadParameter s
+packCdioError s Foreign.NotPermitted = const $ errorText NotPermitted s
+packCdioError s Foreign.BadParameter = const $ errorText BadParameter s
+packCdioError s Foreign.BadPointer = const $ errorText BadParameter s
+packCdioError s Foreign.NoDriver = const $ errorText DriverError s
+packCdioError _ Foreign.MmcSenseData = Right
+
+packCdioError' :: String -> Either Foreign.DriverReturnCode a -> Either CdioError a
+packCdioError' _ (Right a) = Right a
+packCdioError' s (Left Foreign.Success) = errorText DriverError s
+packCdioError' s (Left e) = packCdioError s e undefined
+
+
+-- | Use a C-style @"Foreign.Libcdio".'Foreign.Cdio'@ object as the base to run
+-- a Haskell-style @"Sound.Libcdio".'Cdio'@ computation.
+-- 
+-- Note that some invariants of the monadic interface may not work as expected
+-- when used with the mutable objects.
+runCdio :: Foreign.Cdio -> Cdio a -> IO (Either CdioError a)
+runCdio c (Cdio f) = isolateLogs $ f c
+
+
+-- | Open a session to read data from the disc drive/image at the given
+-- location.  If passed 'Nothing' instead, uses the path considered "default";
+-- on operating systems with a concept of numbered devices (e.g., Window's @D:@
+-- drive, FreeBSD's @\/dev\/cd0@) will usually return the first such device
+-- found to be suitable.
+open
+    :: Maybe FilePath
+    -> Bool
+        -- ^ Whether the disc should be ejected after the computation.
+    -> Cdio a
+    -> IO (Either CdioError a)
+open = open' "open" Nothing
+
+
+-- | Open a session to read data from the disc drive/image at the given
+-- location, using a specific instruction set.  If passed 'Nothing' instead,
+-- uses the path considered "default"; on operating systems with a concept of
+-- numbered devices (e.g., Window's @D:@ drive, FreeBSD's @\/dev\/cd0@) will
+-- usually return the first such device found to be suitable.
+openMode
+    :: Foreign.AccessMode
+    -> Maybe FilePath
+    -> Bool
+        -- ^ Whether the disc should be ejected after the computation.
+    -> Cdio a
+    -> IO (Either CdioError a)
+openMode = open' "openMode" . Just
+
+
+open'
+    :: String
+        -- ^ The name of the calling function, for error reporting.
+    -> Maybe Foreign.AccessMode
+    -> Maybe FilePath
+    -> Bool
+        -- ^ Whether the disc should be ejected after the computation.
+    -> Cdio a
+    -> IO (Either CdioError a)
+open' s m p e (Cdio f) = isolateLogs $ do
+    -- Rely on the driver autodetect behaviour.
+    c <-  case m of
+        Just m' -> Foreign.cdioOpenAm p Foreign.DriverUnknown m'
+        Nothing -> Foreign.cdioOpen p Foreign.DriverUnknown
+    case c of
+        Just c' -> do
+            a <- f c'
+            -- This isn't actually necessary since the failure code is ignored,
+            -- but it's a small cost to be sure nothing weird happens (e.g.
+            -- printing a warning message).
+            (_, _, cap) <- Foreign.driveCap c'
+            let e' = if e && cap ! Foreign.MiscEject
+                then Foreign.ejectMedia c'
+                else return Foreign.Success
+            e' >> return a
+        -- There may be a chance memory allocation fails, but far and away the
+        -- most common is a path which is not actually a device.
+        Nothing -> do
+            return $ errorText BadParameter s
+
+
+-- | Retrieve the session value associated with the given key.  The particular
+-- case of @"access-mode"@ is instead handled by 'getAccessMode'.
+getArg :: Foreign.SessionArg -> Cdio (Maybe T.Text)
+getArg k = liftCdio $ \c -> do
+    v <- Foreign.getArg c k
+    return $ T.pack <$> v
+
+-- | Check what instruction set is in use for reading the disc.  Other session
+-- values are handled by 'getArg'.
+getAccessMode :: Cdio (Maybe Foreign.AccessMode)
+getAccessMode = liftCdio Foreign.getAccessMode
diff --git a/src/c/cdio/compat/cdtext.c b/src/c/cdio/compat/cdtext.c
new file mode 100644
--- /dev/null
+++ b/src/c/cdio/compat/cdtext.c
@@ -0,0 +1,100 @@
+#include "cdio/compat/cdtext.h"
+
+#include "stdlib.h"
+#include "string.h"
+
+#include "cdio/compat/device.h"
+#include "cdio/memory.h"
+#include "cdio/compat/track.h"
+#include "cdio/compat/version.h"
+
+
+// FFI-compatible wrappers
+
+cdtext_genre_t genre_unused() {
+    return CDTEXT_GENRE_UNUSED;
+}
+
+cdtext_lang_t language_unknown() {
+    return CDTEXT_LANGUAGE_UNKNOWN;
+}
+
+cdtext_lang_t language_invalid() {
+#if LIBCDIO_SINCE_VERSION_2_1
+    return CDTEXT_LANGUAGE_INVALID;
+#else
+    return CDTEXT_LANGUAGE_UNKNOWN;
+#endif
+}
+
+cdtext_lang_t language_unused() {
+#if LIBCDIO_SINCE_VERSION_2_1
+    return CDTEXT_LANGUAGE_BLOCK_UNUSED;
+#else
+    return CDTEXT_LANGUAGE_UNKNOWN;
+#endif
+}
+
+
+// Symbol compatibility definitions
+
+cdtext_lang_t cdtext_str2lang_safe(const char* str) {
+#if LIBCDIO_SINCE_VERSION_2_1
+    return cdtext_str2lang(str);
+#else
+    return CDTEXT_LANGUAGE_UNKNOWN;
+#endif
+}
+
+
+int cdtext_data_init_safe(cdtext_t* cdtext, uint8_t* data, size_t len) {
+#if LIBCDIO_SINCE_VERSION_0_94
+    return cdtext_data_init(cdtext, data, len);
+#else
+    return -1;
+#endif
+}
+
+
+cdtext_lang_t* cdtext_list_languages_v2_safe(cdtext_t* cdtext) {
+#if LIBCDIO_SINCE_VERSION_2_1
+    return cdtext_list_languages_v2(cdtext);
+#else
+    return cdtext_list_languages(cdtext);
+#endif
+}
+
+bool cdtext_set_language_index_safe(cdtext_t* cdtext, int i) {
+#if LIBCDIO_SINCE_VERSION_2_1
+    return cdtext_set_language_index(cdtext, i);
+#else
+    // If we don't have a builtin index function, fall back on the list of
+    // languages we *do* have, and derive an index from that.
+
+    cdtext_lang_t* langs = cdtext_list_languages(cdtext);
+    cdtext_lang_t nub_langs[CDTEXT_NUM_BLOCKS_MAX];
+
+    // The Haskell interface drops both blocks without a known language and
+    // blocks with a language which was already used (since
+    // `cdtext_select_language` is unable to select either), but the C list is
+    // messier and needs to be cleaned for the index to be predictable.
+    int found = 0;
+    for (int j = 0; j < CDTEXT_NUM_BLOCKS_MAX; ++j) {
+        if (langs[j] == CDTEXT_LANGUAGE_UNKNOWN)
+            continue;
+        for (int k = 0; k <= found; ++k) {
+            if (k == found) {
+                nub_langs[found] = langs[j];
+                ++found;
+                break;
+            } else if (langs[k] == langs[j])
+                break;
+        }
+    }
+
+    if (i < 0 || i >= found)
+        return cdtext_select_language(cdtext, CDTEXT_LANGUAGE_UNKNOWN);
+    else
+        return cdtext_select_language(cdtext, nub_langs[i]);
+#endif
+}
diff --git a/src/c/cdio/compat/device.c b/src/c/cdio/compat/device.c
new file mode 100644
--- /dev/null
+++ b/src/c/cdio/compat/device.c
@@ -0,0 +1,110 @@
+#include "cdio/compat/device.h"
+
+#include "cdio/compat/version.h"
+
+#include "stdlib.h"
+
+
+// FFI-compatible wrappers
+
+const unsigned int vendor_len() {
+    return CDIO_MMC_HW_VENDOR_LEN;
+}
+
+const unsigned int model_len() {
+    return CDIO_MMC_HW_MODEL_LEN;
+}
+
+const unsigned int revision_len() {
+    return CDIO_MMC_HW_REVISION_LEN;
+}
+
+
+bitfield_t drive_cap_error() {
+    return CDIO_DRIVE_CAP_ERROR;
+}
+
+bitfield_t drive_cap_unknown() {
+    return CDIO_DRIVE_CAP_UNKNOWN;
+}
+
+
+const driver_id_t* get_drivers() {
+    return cdio_drivers;
+}
+
+const driver_id_t* get_device_drivers() {
+    return cdio_device_drivers;
+}
+
+const driver_id_t get_os_driver() {
+    return cdio_os_driver;
+}
+
+
+// Symbol compatibility definitions
+
+CdIo_t* cdio_open_bsdi_safe(const char* src) {
+#if LIBCDIO_SINCE_VERSION_1_0
+    return NULL;
+#else
+    return cdio_open_bsdi(src);
+#endif
+}
+
+CdIo_t* cdio_open_am_bsdi_safe(const char* src, const char* mode) {
+#if LIBCDIO_SINCE_VERSION_1_0
+    return NULL;
+#else
+    return cdio_open_am_bsdi(src, mode);
+#endif
+}
+
+char* cdio_get_default_device_bsdi_safe() {
+#if LIBCDIO_SINCE_VERSION_1_0
+    return NULL;
+#else
+    return cdio_get_default_device_bsdi();
+#endif
+}
+
+char** cdio_get_devices_bsdi_safe() {
+#if LIBCDIO_SINCE_VERSION_1_0
+    return NULL;
+#else
+    return cdio_get_devices_bsdi();
+#endif
+}
+
+
+CdIo_t* cdio_open_os2_safe(const char* src) {
+#if LIBCDIO_SINCE_VERSION_1_0
+    return NULL;
+#else
+    return cdio_open_os2(src);
+#endif
+}
+
+CdIo_t* cdio_open_am_os2_safe(const char* src, const char* mode) {
+#if LIBCDIO_SINCE_VERSION_1_0
+    return NULL;
+#else
+    return cdio_open_am_os2(src, mode);
+#endif
+}
+
+char* cdio_get_default_device_os2_safe() {
+#if LIBCDIO_SINCE_VERSION_1_0
+    return NULL;
+#else
+    return cdio_get_default_device_os2();
+#endif
+}
+
+char** cdio_get_devices_os2_safe() {
+#if LIBCDIO_SINCE_VERSION_1_0
+    return NULL;
+#else
+    return cdio_get_devices_os2();
+#endif
+}
diff --git a/src/c/cdio/compat/disc.c b/src/c/cdio/compat/disc.c
new file mode 100644
--- /dev/null
+++ b/src/c/cdio/compat/disc.c
@@ -0,0 +1,32 @@
+#include "cdio/compat/disc.h"
+
+#include "cdio/compat/mmc.h"
+
+
+// FFI-compatible wrappers
+
+const char* discmode_string(discmode_t dm) {
+    if (dm > CDIO_DISC_MODE_CD_I || dm < CDIO_DISC_MODE_CD_DA)
+        return discmode2str[CDIO_DISC_MODE_ERROR];
+    else
+        return discmode2str[dm];
+}
+
+
+discmode_t discmode_error() {
+    return CDIO_DISC_MODE_ERROR;
+}
+
+
+// Marshalling aids
+
+void get_cdtext_raw_len(CdIo_t* cdio, uint8_t** data, unsigned int* length) {
+    *data = cdio_get_cdtext_raw(cdio);
+    // Source diving to lib/driver/generic.h:read_cdtext_generic()
+    if (data && *data)
+        // The CDTEXT length includes the two always-null bytes before the
+        // data, but *not* the two length bytes themselves.
+        *length = CDIO_MMC_GET_LEN16(*data) - 2;
+    else
+        *length = 0;
+}
diff --git a/src/c/cdio/compat/logging.c b/src/c/cdio/compat/logging.c
new file mode 100644
--- /dev/null
+++ b/src/c/cdio/compat/logging.c
@@ -0,0 +1,91 @@
+#include "cdio/compat/logging.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+// Avoid unnecessary repeated calls; don't seem to mess anything up, but may as
+// well keep clean.
+bool replaced_cdio_logger = false;
+
+
+cdio_log_level_t get_cdio_log_level() {
+    return cdio_loglevel_default;
+}
+
+void set_cdio_log_level(cdio_log_level_t l) {
+    // The `_default` refers to the default handler, but it has explicitly been
+    // opened up to alternate implementations as well.
+    cdio_loglevel_default = l;
+}
+
+
+void haskell_log_handler(cdio_log_level_t lvl, const char* msg) {
+    if (lvl >= cdio_loglevel_default) {
+        cdio_log_entry_t* entry = (cdio_log_entry_t*) malloc(sizeof(cdio_log_entry_t));
+        if (!entry)
+            return;
+
+        // The Haskell garbage collector could easily clean anything logged
+        // from the bindings before it's read.
+        char* message = malloc(strlen(msg) + 1);
+        if (!message) {
+            free(entry);
+            return;
+        }
+        else
+            strcpy(message, msg);
+
+        entry->level = lvl;
+        entry->prev = haskell_log;
+        entry->message = message;
+
+        haskell_log = entry;
+    }
+}
+
+void setup_cdio_logger() {
+    if (!replaced_cdio_logger) {
+        cdio_log_set_handler(*haskell_log_handler);
+        haskell_log = NULL;
+        replaced_cdio_logger = true;
+    }
+}
+
+
+cdio_log_entry_t** read_cdio_log() {
+    if (!haskell_log)
+        return NULL;
+
+    // We need the total number of entries for determining allocation size.
+    int count = 0;
+    cdio_log_entry_t* entry = haskell_log;
+    while (entry) {
+        ++count;
+        entry = entry->prev;
+    }
+
+    cdio_log_entry_t** out = (cdio_log_entry_t**) calloc(count + 1, sizeof(cdio_log_entry_t*));
+    if (!out)
+        return NULL;
+
+    // ...and since we have the total anyway, may as well reverse the FILO into
+    // chronological order now.
+    entry = haskell_log;
+    for (int i = count - 1; i >= 0; --i) {
+        out[i] = entry;
+        entry = entry->prev;
+    }
+
+    return out;
+}
+
+void free_cdio_log() {
+    while (haskell_log) {
+        cdio_log_entry_t* entry = haskell_log;
+        haskell_log = entry->prev;
+        if (entry->message)
+            free((void *)entry->message);
+        free(entry);
+    }
+}
diff --git a/src/c/cdio/compat/read.c b/src/c/cdio/compat/read.c
new file mode 100644
--- /dev/null
+++ b/src/c/cdio/compat/read.c
@@ -0,0 +1,89 @@
+#include "cdio/compat/read.h"
+
+#include "stdlib.h"
+
+#include "cdio/compat/sector.h"
+
+
+// Allocate the proper sizes in C, as Haskell marshalling for anything but
+// simple `Storable` types is a bit awkward.
+
+void read_bytes(const CdIo_t* cdio, void** buf, ssize_t* out, size_t bytes) {
+    *buf = malloc(bytes);
+    *out = cdio_read(cdio, *buf, bytes);
+}
+
+
+uint16_t sector_size(cdio_read_mode_t mode) {
+    switch (mode) {
+        case CDIO_READ_MODE_AUDIO:
+            return CDIO_CD_FRAMESIZE_RAW;
+        case CDIO_READ_MODE_M1F1:
+            return CDIO_CD_FRAMESIZE;
+        case CDIO_READ_MODE_M1F2:
+            return CDIO_CD_FRAMESIZE_RAW0;
+        case CDIO_READ_MODE_M2F1:
+            return CDIO_CD_FRAMESIZE;
+        case CDIO_READ_MODE_M2F2:
+            return M2F2_SECTOR_SIZE;
+        default:
+            return 0;
+    }
+}
+
+void setup_read(void** buff, uint32_t* bytes, uint16_t blocksize, uint32_t blocks) {
+    *bytes = blocksize * blocks;
+    *buff = malloc(*bytes);
+}
+
+
+// Marshalling aids
+
+driver_return_code_t read_sector(const CdIo_t* cdio, void** buff, uint32_t* bytes, lsn_t lsn, cdio_read_mode_t mode) {
+    setup_read(buff, bytes, sector_size(mode), 1);
+    return cdio_read_sector(cdio, *buff, lsn, mode);
+}
+
+driver_return_code_t read_sectors(const CdIo_t* cdio, void** buff, uint32_t* bytes, lsn_t lsn, cdio_read_mode_t mode, uint32_t blocks) {
+    setup_read(buff, bytes, sector_size(mode), blocks);
+    return cdio_read_sectors(cdio, *buff, lsn, mode, blocks);
+}
+
+
+driver_return_code_t read_data_sectors(const CdIo_t* cdio, void** buff, uint32_t* bytes, lsn_t lsn, uint16_t blocksize, uint32_t blocks) {
+    setup_read(buff, bytes, blocksize, blocks);
+    return cdio_read_data_sectors(cdio, *buff, lsn, blocksize, blocks);
+}
+
+
+driver_return_code_t read_audio_sector(const CdIo_t* cdio, void** buff, uint32_t* bytes, lsn_t lsn) {
+    setup_read(buff, bytes, sector_size(CDIO_READ_MODE_AUDIO), 1);
+    return cdio_read_audio_sector(cdio, *buff, lsn);
+}
+
+driver_return_code_t read_audio_sectors(const CdIo_t* cdio, void** buff, uint32_t* bytes, lsn_t lsn, uint32_t blocks) {
+    setup_read(buff, bytes, sector_size(CDIO_READ_MODE_AUDIO), blocks);
+    return cdio_read_audio_sectors(cdio, *buff, lsn, blocks);
+}
+
+
+driver_return_code_t read_mode1_sector(const CdIo_t* cdio, void** buff, uint32_t* bytes, lsn_t lsn, bool form2) {
+    setup_read(buff, bytes, sector_size((form2 ? CDIO_READ_MODE_M1F2 : CDIO_READ_MODE_M1F1)), 1);
+    return cdio_read_mode1_sector(cdio, *buff, lsn, form2);
+}
+
+driver_return_code_t read_mode1_sectors(const CdIo_t* cdio, void** buff, uint32_t* bytes, lsn_t lsn, bool form2, uint32_t blocks) {
+    setup_read(buff, bytes, sector_size((form2 ? CDIO_READ_MODE_M1F2 : CDIO_READ_MODE_M1F1)), blocks);
+    return cdio_read_mode1_sectors(cdio, *buff, lsn, form2, blocks);
+}
+
+
+driver_return_code_t read_mode2_sector(const CdIo_t* cdio, void** buff, uint32_t* bytes, lsn_t lsn, bool form2) {
+    setup_read(buff, bytes, sector_size((form2 ? CDIO_READ_MODE_M2F2 : CDIO_READ_MODE_M2F1)), 1);
+    return cdio_read_mode2_sector(cdio, *buff, lsn, form2);
+}
+
+driver_return_code_t read_mode2_sectors(const CdIo_t* cdio, void** buff, uint32_t* bytes, lsn_t lsn, bool form2, uint32_t blocks) {
+    setup_read(buff, bytes, sector_size((form2 ? CDIO_READ_MODE_M2F2 : CDIO_READ_MODE_M2F1)), blocks);
+    return cdio_read_mode2_sectors(cdio, *buff, lsn, form2, blocks);
+}
diff --git a/src/c/cdio/compat/sector.c b/src/c/cdio/compat/sector.c
new file mode 100644
--- /dev/null
+++ b/src/c/cdio/compat/sector.c
@@ -0,0 +1,152 @@
+#include "cdio/compat/sector.h"
+
+#include "string.h"
+
+
+// FFI-compatible wrappings
+
+lsn_t min_lsn() {
+    return CDIO_CD_MIN_LSN;
+}
+
+lsn_t max_lsn() {
+    return CDIO_CD_MAX_LSN;
+}
+
+
+lba_t invalid_lba() {
+    return CDIO_INVALID_LBA;
+}
+
+lsn_t invalid_lsn() {
+    return CDIO_INVALID_LSN;
+}
+
+
+size_t sizeof_msf() {
+    return sizeof(msf_t);
+}
+
+
+unsigned int pregap_sectors() {
+    return CDIO_PREGAP_SECTORS;
+}
+
+unsigned int postgap_sectors() {
+    return CDIO_POSTGAP_SECTORS;
+}
+
+
+unsigned int cd_mins() {
+    return CDIO_CD_MINS;
+}
+
+unsigned int secs_per_min() {
+    return CDIO_CD_SECS_PER_MIN;
+}
+
+unsigned int frames_per_min() {
+    return CDIO_CD_FRAMES_PER_MIN;
+}
+
+unsigned int frames_per_sec() {
+    return CDIO_CD_FRAMES_PER_SEC;
+}
+
+unsigned int chunks_per_frame() {
+    return CDIO_CD_NUM_OF_CHUNKS;
+}
+
+
+unsigned int min_session() {
+    return CDIO_CD_MIN_SESSION_NO;
+}
+
+unsigned int max_session() {
+    return CDIO_CD_MAX_SESSIONS;
+}
+
+
+unsigned int sync_size() {
+    return CDIO_CD_SYNC_SIZE;
+}
+
+unsigned int chunk_size() {
+    return CDIO_CD_CHUNK_SIZE;
+}
+
+unsigned int framesize_sub() {
+    return CDIO_CD_FRAMESIZE_SUB;
+}
+
+unsigned int header_size() {
+    return CDIO_CD_HEADER_SIZE;
+}
+
+unsigned int subheader_size() {
+    return CDIO_CD_SUBHEADER_SIZE;
+}
+
+unsigned int edc_size() {
+    return CDIO_CD_EDC_SIZE;
+}
+
+unsigned int mode1_pad_size() {
+    return CDIO_CD_M1F1_ZERO_SIZE;
+}
+
+unsigned int ecc_size() {
+    return CDIO_CD_ECC_SIZE;
+}
+
+
+unsigned int framesize() {
+    return CDIO_CD_FRAMESIZE;
+}
+
+unsigned int framesize_raw() {
+    return CDIO_CD_FRAMESIZE_RAW;
+}
+
+unsigned int framesize_rawer() {
+    return CDIO_CD_FRAMESIZE_RAWER;
+}
+
+unsigned int framesize_raw0() {
+    return CDIO_CD_FRAMESIZE_RAW0;
+}
+
+unsigned int framesize_raw1() {
+    return CDIO_CD_FRAMESIZE_RAW1;
+}
+
+
+unsigned int header_size_xa() {
+    return CDIO_CD_XA_HEADER;
+}
+
+unsigned int tail_size_xa() {
+    return CDIO_CD_XA_TAIL;
+}
+
+unsigned int sync_size_xa() {
+    return CDIO_CD_XA_SYNC_HEADER;
+}
+
+unsigned int data_size_xa() {
+    return M2F2_SECTOR_SIZE;
+}
+
+unsigned int tagged_size_xa() {
+    return M2SUB_SECTOR_SIZE;
+}
+
+
+const uint8_t* sector_sync_header() {
+    return CDIO_SECTOR_SYNC_HEADER;
+}
+
+
+cdio_cd_minutes_sectors max_sectors() {
+    return CDIO_CD_MAX_SECTORS;
+}
diff --git a/src/c/cdio/compat/track.c b/src/c/cdio/compat/track.c
new file mode 100644
--- /dev/null
+++ b/src/c/cdio/compat/track.c
@@ -0,0 +1,31 @@
+#include "cdio/compat/track.h"
+
+
+// FFI-compatible wrappings
+
+const char* track_format_string(track_format_t tf) {
+    if (tf > TRACK_FORMAT_ERROR || tf < TRACK_FORMAT_AUDIO)
+        return track_format2str[TRACK_FORMAT_ERROR];
+    else
+        return track_format2str[tf];
+}
+
+track_t invalid_track() {
+    return CDIO_INVALID_TRACK;
+}
+
+track_t leadout_track() {
+    return CDIO_CDROM_LEADOUT_TRACK;
+}
+
+track_format_t track_format_error() {
+    return TRACK_FORMAT_ERROR;
+}
+
+track_t min_tracks() {
+    return CDIO_CD_MIN_TRACK_NO;
+}
+
+track_t max_tracks() {
+    return CDIO_CD_MAX_TRACKS;
+}
diff --git a/src/c/cdio/compat/types.c b/src/c/cdio/compat/types.c
new file mode 100644
--- /dev/null
+++ b/src/c/cdio/compat/types.c
@@ -0,0 +1,10 @@
+#include "cdio/compat/types.h"
+
+
+unsigned char mcn_length() {
+    return CDIO_MCN_SIZE;
+}
+
+unsigned char isrc_length() {
+    return CDIO_ISRC_SIZE;
+}
diff --git a/src/c/cdio/compat/version.c b/src/c/cdio/compat/version.c
new file mode 100644
--- /dev/null
+++ b/src/c/cdio/compat/version.c
@@ -0,0 +1,16 @@
+#include "cdio/compat/version.h"
+
+
+// FFI-compatible wrappings
+
+const char* get_cdio_version_string() {
+    return cdio_version_string;
+}
+
+const unsigned int get_cdio_version_num() {
+    return libcdio_version_num;
+}
+
+const unsigned int get_cdio_version_api() {
+    return CDIO_API_VERSION;
+}
diff --git a/test/Data/Text/Encoding/MsJIS/Test/Classes.hs b/test/Data/Text/Encoding/MsJIS/Test/Classes.hs
new file mode 100644
--- /dev/null
+++ b/test/Data/Text/Encoding/MsJIS/Test/Classes.hs
@@ -0,0 +1,65 @@
+{-|
+Description:    
+
+Copyright:      (c) 2020-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Data.Text.Encoding.MsJIS.Test.Classes
+    ( laws
+    , genJISChar
+    , genDecodeError
+    , genEncodeError
+    ) where
+
+
+import qualified Hedgehog as H
+import qualified Hedgehog.Gen as H.G
+import qualified Hedgehog.Classes as H.C
+
+import qualified Data.Text as T
+
+import Data.Text.Encoding.MsJIS
+
+import Test.Libcdio.Property.Common
+
+
+laws :: [LawsGroup]
+laws =
+    [ ("JISChar", map (\f -> f genJISChar)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        ]
+    ), ("JISDecodeError", map (\f -> f genDecodeError)
+        [ H.C.eqLaws
+        , H.C.showLaws
+        , H.C.showReadLaws
+        ]
+    ), ("JISEncodeError", map (\f -> f genEncodeError)
+        [ H.C.eqLaws
+        , H.C.showLaws
+        , H.C.showReadLaws
+        ]
+    )]
+
+
+genJISChar :: H.Gen JISChar
+genJISChar = H.G.enumBounded
+
+genDecodeError :: H.Gen JISDecodeError
+genDecodeError = do
+    s <- genSample
+    c <- H.G.maybe genJISChar
+    return $ JISDecodeError (T.unpack s) c
+
+genEncodeError :: H.Gen JISEncodeError
+genEncodeError = do
+    s <- genSample
+    c <- H.G.maybe H.G.unicode
+    return $ JISEncodeError (T.unpack s) c
diff --git a/test/Data/Text/Encoding/MsJIS/Test/Unit.hs b/test/Data/Text/Encoding/MsJIS/Test/Unit.hs
new file mode 100644
--- /dev/null
+++ b/test/Data/Text/Encoding/MsJIS/Test/Unit.hs
@@ -0,0 +1,107 @@
+{-|
+Description:    
+
+Copyright:      (c) 2020 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Data.Text.Encoding.MsJIS.Test.Unit (tests) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (@=?), (@?=), (~:) )
+
+import qualified Data.ByteString as BS
+import qualified Data.Maybe as Y
+import qualified Data.Text as T
+
+import qualified System.IO.Unsafe as IO.U
+
+import Data.Text.Encoding.MsJIS
+
+import Test.Libcdio.Unit.Common
+
+
+testFile :: FilePath
+testFile = dataFile "CP932.txt"
+
+charRef :: [(JISChar, T.Text)]
+charRef = IO.U.unsafePerformIO $ do
+    ls <- lines <$> readFile testFile
+    return . flip Y.mapMaybe ls $ \l -> case words l of
+        [] -> Nothing
+        [_] -> Nothing
+        (('#':_):_) -> Nothing
+        (_:('#':_):_) -> Nothing
+        (j:u:_) -> Just (toJIS $ read j, T.singleton . toEnum $ read u)
+  where toJIS i
+            | i > 0xFF = uncurry Double . mapBoth fromIntegral $ divMod i (0x100 :: Word)
+            | otherwise = Single $ fromIntegral i
+
+
+tests :: U.Test
+tests = "Data.Text.Encoding.MsJIS" ~: U.TestList
+    [ decode
+    , encode
+    , duplicatesDuplicated
+    ]
+
+
+decode :: U.Test
+decode = "JIS characters are read correctly" ~: U.TestList
+    [ show j ++ " -> " ++ T.unpack u ~: U.TestCase (decodeMsJIS' (unpack j) @?= Right u)
+    | (j, u) <- charRef
+    ]
+
+encode :: U.Test
+encode = "JIS characters are encoded correctly" ~: U.TestList
+    [ T.unpack u ++ " -> " ++ show j ~: U.TestCase (Right (unpack j) @=? encodeMsJIS' u)
+    | (j, u) <- charRef
+    , notElem j duplicateChars
+    ]
+
+duplicatesDuplicated :: U.Test
+duplicatesDuplicated = "Duplicate JIS characters roundtrip to something else" ~: U.TestList
+    [ U.TestCase $ do
+        c <- either decodeFailure return $ decodeMsJIS' bs
+        bs' <- either encodeFailure return $ encodeMsJIS' c
+        U.assert $ bs /= bs'
+    | bs <- map unpack duplicateChars
+    ]
+  where decodeFailure = U.assertFailure . mappend "JIS decode failed with " . show
+        encodeFailure = U.assertFailure . mappend "JIS encode failed with " . show
+
+unpack :: JISChar -> BS.ByteString
+unpack (Single w) = BS.singleton w
+unpack (Double l t) = BS.pack [l, t]
+
+duplicateChars :: [JISChar]
+duplicateChars =
+    [ Double 0x81 0xBE
+    , Double 0x81 0xBF
+    , Double 0x81 0xCA
+    , Double 0x81 0xDA
+    , Double 0x81 0xDB
+    , Double 0x81 0xDF
+    , Double 0x81 0xE0
+    , Double 0x81 0xE3
+    , Double 0x81 0xE6
+    , Double 0x81 0xE7
+    ] ++
+    [ Double 0x87 t
+    | t <- [0x54..0x5D]
+    ] ++
+    [ Double 0x87 0x82
+    , Double 0x87 0x84
+    , Double 0x87 0x8A
+    , Double 0x87 0x9A
+    ] ++
+    [ Double 0xED t
+    | t <- [0x40..0x7E] ++ [0x80..0xFC]
+    ] ++
+    [ Double 0xEE t
+    | t <- [0x40..0x7E] ++ [0x80..0xEC] ++ [0xEF..0xFC]
+    ]
diff --git a/test/Foreign/Libcdio/CdText/Test/Classes.hs b/test/Foreign/Libcdio/CdText/Test/Classes.hs
new file mode 100644
--- /dev/null
+++ b/test/Foreign/Libcdio/CdText/Test/Classes.hs
@@ -0,0 +1,60 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Foreign.Libcdio.CdText.Test.Classes
+    ( laws
+    , genGenre
+    , genLanguage
+    ) where
+
+
+import qualified Hedgehog as H
+import qualified Hedgehog.Gen as H.G
+import qualified Hedgehog.Classes as H.C
+
+import Test.Libcdio.Property.Common
+
+import Foreign.Libcdio.CdText
+
+
+laws :: [LawsGroup]
+laws =
+    [ ("Field", map (\f -> f genField)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        ]
+    ), ("Genre", map (\f -> f genGenre)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        ]
+    ), ("Language", map (\f -> f genLanguage)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        ]
+    )]
+
+
+genField :: H.Gen Field
+genField = H.G.enumBounded
+
+genGenre :: H.Gen Genre
+genGenre = H.G.enumBounded
+
+genLanguage :: H.Gen Language
+genLanguage = enumSparse
diff --git a/test/Foreign/Libcdio/CdTypes/Test/Classes.hs b/test/Foreign/Libcdio/CdTypes/Test/Classes.hs
new file mode 100644
--- /dev/null
+++ b/test/Foreign/Libcdio/CdTypes/Test/Classes.hs
@@ -0,0 +1,84 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Foreign.Libcdio.CdTypes.Test.Classes
+    ( laws
+    , genFilesystem
+    , genFilesystemClass
+    , genIsoAnalysis
+    ) where
+
+
+import qualified Hedgehog as H
+import qualified Hedgehog.Gen as H.G
+import qualified Hedgehog.Range as H.R
+import qualified Hedgehog.Classes as H.C
+
+import qualified Data.Text as T
+
+import qualified Foreign.C.Types as C
+
+import Foreign.Libcdio.CdTypes
+
+import Test.Libcdio.Property.Common
+
+
+laws :: [LawsGroup]
+laws =
+    [ ("Filesystem", map (\f -> f genFilesystem)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        ]
+    ), ("FilesystemClass", map (\f -> f genFilesystemClass)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        ]
+    ), ("IsoAnalysis", map (\f -> f genIsoAnalysis)
+        [ H.C.eqLaws
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , storableLaws'
+        ]
+    )]
+
+
+genFilesystem :: H.Gen Filesystem
+genFilesystem = H.G.enumBounded
+
+genFilesystemClass :: H.Gen FilesystemClass
+genFilesystemClass = enumSparse
+
+genIsoAnalysis :: H.Gen IsoAnalysis
+genIsoAnalysis = do
+    j <- H.G.maybe . H.G.word $ H.R.constant 1 3
+    l <- genSample
+    s <- H.G.integral (H.R.linearBounded :: H.R.Range C.CUInt)
+    v <- H.G.maybe $ H.G.element
+        [ (1, 0)
+        , (1, 1)
+        , (1, 2)
+        , (1, 50)
+        , (2, 0)
+        , (2, 1)
+        , (2, 50)
+        , (2, 60)
+        ]
+    return $ IsoAnalysis
+        { jolietLevel = j
+        , label = T.unpack l
+        , fsSize = fromIntegral s
+        , udfVersion = v
+        }
diff --git a/test/Foreign/Libcdio/Device/Test/Classes.hs b/test/Foreign/Libcdio/Device/Test/Classes.hs
new file mode 100644
--- /dev/null
+++ b/test/Foreign/Libcdio/Device/Test/Classes.hs
@@ -0,0 +1,127 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Foreign.Libcdio.Device.Test.Classes
+    ( laws
+    , genDriveCapabilityRead
+    , genDriveCapabilityWrite
+    , genDriveCapabilityMisc
+    , genHardwareInfo
+    , genDriverId
+    , genDriverReturnCode
+    , genSessionArg
+    , genAccessMode
+    ) where
+
+
+import qualified Hedgehog as H
+import qualified Hedgehog.Gen as H.G
+import qualified Hedgehog.Range as H.R
+import qualified Hedgehog.Classes as H.C
+
+import Foreign.Libcdio.Device
+
+import Test.Libcdio.Property.Common
+
+
+laws :: [LawsGroup]
+laws =
+    [ ("DriveCapabilityRead", map (\f -> f genDriveCapabilityRead)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        ]
+    ), ("DriveCapabilityWrite", map (\f -> f genDriveCapabilityWrite)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        ]
+    ), ("DriveCapabilityMisc", map (\f -> f genDriveCapabilityMisc)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        ]
+    ), ("HardwareInfo", map (\f -> f genHardwareInfo)
+        [ H.C.eqLaws
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , storableLaws'
+        ]
+    ), ("DriverId", map (\f -> f genDriverId)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        ]
+    ), ("DriverReturnCode", map (\f -> f genDriverReturnCode)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        ]
+    ), ("SessionArg", map (\f -> f genSessionArg)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        , storableLaws'
+        ]
+    ), ("AccessMode", map (\f -> f genAccessMode)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        , storableLaws'
+        ]
+    )]
+
+
+genDriveCapabilityRead :: H.Gen DriveCapabilityRead
+genDriveCapabilityRead = enumSparse
+
+genDriveCapabilityWrite :: H.Gen DriveCapabilityWrite
+genDriveCapabilityWrite = enumSparse
+
+genDriveCapabilityMisc :: H.Gen DriveCapabilityMisc
+genDriveCapabilityMisc = enumSparse
+
+genHardwareInfo :: H.Gen HardwareInfo
+genHardwareInfo = do
+    --TODO: Test other string lengths
+    v <- H.G.string (H.R.singleton $ fromIntegral vendorLength) H.G.ascii
+    m <- H.G.string (H.R.singleton $ fromIntegral modelLength) H.G.ascii
+    r <- H.G.string (H.R.singleton $ fromIntegral revisionLength) H.G.ascii
+    return $ HardwareInfo
+        { vendor = v
+        , model = m
+        , revision = r
+        }
+
+genDriverId :: H.Gen DriverId
+genDriverId = enumSparse
+
+genDriverReturnCode :: H.Gen DriverReturnCode
+genDriverReturnCode = enumSparse
+
+genSessionArg :: H.Gen SessionArg
+genSessionArg = H.G.enumBounded
+
+genAccessMode :: H.Gen AccessMode
+genAccessMode = H.G.enumBounded
diff --git a/test/Foreign/Libcdio/Disc/Test/Classes.hs b/test/Foreign/Libcdio/Disc/Test/Classes.hs
new file mode 100644
--- /dev/null
+++ b/test/Foreign/Libcdio/Disc/Test/Classes.hs
@@ -0,0 +1,39 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Foreign.Libcdio.Disc.Test.Classes
+    ( laws
+    , genDiscMode
+    ) where
+
+
+import qualified Hedgehog as H
+import qualified Hedgehog.Gen as H.G
+import qualified Hedgehog.Classes as H.C
+
+import Foreign.Libcdio.Disc
+
+import Test.Libcdio.Property.Common
+
+
+laws :: [LawsGroup]
+laws =
+    [ ("DiscMode", map (\f -> f genDiscMode)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        ]
+    )]
+
+
+genDiscMode :: H.Gen DiscMode
+genDiscMode = H.G.enumBounded
diff --git a/test/Foreign/Libcdio/Logging/Test/Classes.hs b/test/Foreign/Libcdio/Logging/Test/Classes.hs
new file mode 100644
--- /dev/null
+++ b/test/Foreign/Libcdio/Logging/Test/Classes.hs
@@ -0,0 +1,57 @@
+{-|
+Description:    
+
+Copyright:      (c) 2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Foreign.Libcdio.Logging.Test.Classes
+    ( laws
+    , genLogEntry
+    , genLogLevel
+    ) where
+
+
+import qualified Hedgehog as H
+import qualified Hedgehog.Gen as H.G
+import qualified Hedgehog.Classes as H.C
+
+import qualified Data.Text as T
+
+import Foreign.Libcdio.Logging
+
+import Test.Libcdio.Property.Common
+
+
+laws :: [LawsGroup]
+laws =
+    [ ("LogLevel", map (\f -> f genLogLevel)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        ]
+    ), ("LogEntry", map (\f -> f genLogEntry)
+        [ H.C.eqLaws
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , storableLaws'
+        ]
+    )]
+
+
+genLogLevel :: H.Gen LogLevel
+genLogLevel = H.G.enumBounded
+
+genLogEntry :: H.Gen LogEntry
+genLogEntry = do
+    l <- genLogLevel
+    m <- genSample
+    return $ LogEntry
+        { logLevel = l
+        , logMessage = T.unpack m
+        }
diff --git a/test/Foreign/Libcdio/Logging/Test/Property.hs b/test/Foreign/Libcdio/Logging/Test/Property.hs
new file mode 100644
--- /dev/null
+++ b/test/Foreign/Libcdio/Logging/Test/Property.hs
@@ -0,0 +1,82 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+{-|
+Description:    
+
+Copyright:      (c) 2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Foreign.Libcdio.Logging.Test.Property
+    ( properties
+    ) where
+
+
+import qualified Hedgehog as H
+import qualified Hedgehog.Gen as H.G
+import qualified Hedgehog.Range as H.R
+
+import Foreign.Libcdio.Logging
+import Foreign.Libcdio.Logging.Test.Classes
+
+import Test.Libcdio.Property.Common
+
+import Hedgehog ( (===) )
+
+
+properties :: H.Group
+properties = H.Group "Foreign.Libcdio.Logging"
+    [ setGetCutoff
+    , filtered
+ -- , retrieval
+    , persistance
+    , clear
+    ]
+
+
+setGetCutoff :: Test
+setGetCutoff = packTest "Cutoff level is successfully recovered" $ do
+    H.evalIO setupLogger
+    l <- H.forAll genLogLevel
+    H.evalIO $ setLogCutoff l
+    l' <- H.evalIO logCutoff
+    l === l'
+
+
+logTest :: ([LogEntry] -> LogLevel -> H.PropertyT IO ()) -> H.PropertyT IO ()
+logTest prop = do
+    H.evalIO setupLogger
+    H.evalIO clearLog
+    minLevel <- H.forAll genLogLevel
+    msgs <- H.forAll $ H.G.list (H.R.linear 0 16) genLogEntry
+    H.evalIO $ setLogCutoff minLevel
+    H.evalIO $ mapM_ putLog msgs
+    prop msgs minLevel
+    H.evalIO clearLog
+
+
+filtered :: Test
+filtered = packTest "Log entries below the cutoff are hidden" . logTest $ \_ minLevel -> do
+    msgs <- H.evalIO readLog
+    H.annotateShow msgs
+    H.assert . flip all msgs $ \msg -> logLevel msg >= minLevel
+
+retrieval :: Test
+retrieval = packTest "Log entries are read unchanged" . logTest $ \msgs minLevel -> do
+    msgs' <- H.evalIO readLog
+    filter (\msg -> logLevel msg >= minLevel) msgs === msgs'
+
+persistance :: Test
+persistance = packTest "'readLog' doesn't modify the logs" . logTest $ \_ _ -> do
+    msgs <- H.evalIO readLog
+    msgs' <- H.evalIO readLog
+    msgs === msgs'
+
+clear :: Test
+clear = packTest "Clearing removes the entire log" . logTest $ \_ _ -> do
+    H.evalIO clearLog
+    msgs' <- H.evalIO readLog
+    msgs' === []
diff --git a/test/Foreign/Libcdio/Read/Test/Classes.hs b/test/Foreign/Libcdio/Read/Test/Classes.hs
new file mode 100644
--- /dev/null
+++ b/test/Foreign/Libcdio/Read/Test/Classes.hs
@@ -0,0 +1,50 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Foreign.Libcdio.Read.Test.Classes
+    ( laws
+    , genReadMode
+    , genWhence
+    ) where
+
+
+import qualified Hedgehog as H
+import qualified Hedgehog.Gen as H.G
+import qualified Hedgehog.Classes as H.C
+
+import Foreign.Libcdio.Read
+
+import Test.Libcdio.Property.Common
+
+
+laws :: [LawsGroup]
+laws =
+    [ ("ReadMode", map (\f -> f genReadMode)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        ]
+    ), ("Whence", map (\f -> f genWhence)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        ]
+    )]
+
+
+genReadMode :: H.Gen ReadMode
+genReadMode = H.G.enumBounded
+
+genWhence :: H.Gen Whence
+genWhence = H.G.enumBounded
diff --git a/test/Foreign/Libcdio/Sector/Test/Classes.hs b/test/Foreign/Libcdio/Sector/Test/Classes.hs
new file mode 100644
--- /dev/null
+++ b/test/Foreign/Libcdio/Sector/Test/Classes.hs
@@ -0,0 +1,91 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Foreign.Libcdio.Sector.Test.Classes
+    ( laws
+    , genSubchannelData
+    , genFlag
+    , genLba
+    , genLsn
+    , genMsf
+    ) where
+
+
+import qualified Hedgehog as H
+import qualified Hedgehog.Gen as H.G
+import qualified Hedgehog.Classes as H.C
+import qualified Hedgehog.Range as H.R
+
+import Foreign.Libcdio.Sector
+
+import Test.Libcdio.Property.Common
+
+
+laws :: [LawsGroup]
+laws =
+    [ ("SubchannelData", map (\f -> f genSubchannelData)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        ]
+    ), ("Flag", map (\f -> f genFlag)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        ]
+    ), ("Lba", map (\f -> f genLba)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        , H.C.bitsLaws
+        , storableLaws'
+        ]
+    ), ("Integral Lba", [H.C.integralLaws $ nonZero genLba]
+    ), ("Lsn", map (\f -> f genLsn)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        , H.C.bitsLaws
+        , storableLaws'
+        ]
+    ), ("Integral Lsn", [H.C.integralLaws $ nonZero genLsn]
+    ), ("Msf", map (\f -> f genMsf)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        , storableLaws'
+        ]
+    )]
+
+
+genSubchannelData :: H.Gen SubchannelData
+genSubchannelData = H.G.enumBounded
+
+genFlag :: H.Gen Flag
+genFlag = enumSparse
+
+genLba :: H.Gen Lba
+genLba = H.G.integral (H.R.linearBounded :: H.R.Range Lba)
+
+genLsn :: H.Gen Lsn
+genLsn = H.G.integral (H.R.linearBounded :: H.R.Range Lsn)
+
+genMsf :: H.Gen Msf
+genMsf = H.G.enumBounded
diff --git a/test/Foreign/Libcdio/Track/Test/Classes.hs b/test/Foreign/Libcdio/Track/Test/Classes.hs
new file mode 100644
--- /dev/null
+++ b/test/Foreign/Libcdio/Track/Test/Classes.hs
@@ -0,0 +1,63 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Foreign.Libcdio.Track.Test.Classes
+    ( laws
+    , genTrack
+    , genTrackNum
+    , genTrackFormat
+    ) where
+
+
+import qualified Hedgehog as H
+import qualified Hedgehog.Gen as H.G
+import qualified Hedgehog.Classes as H.C
+
+import Foreign.Libcdio.Track
+
+import Test.Libcdio.Property.Common
+
+
+laws :: [LawsGroup]
+laws =
+    [ ("Track", map (\f -> f genTrack)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        , storableLaws'
+        ]
+    ), ("TrackNum", map (\f -> f genTrackNum)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        ]
+    ), ("TrackFormat", map (\f -> f genTrackFormat)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        ]
+    )]
+
+
+genTrack :: H.Gen Track
+genTrack = H.G.enumBounded
+
+genTrackNum :: H.Gen TrackNum
+genTrackNum = do
+    Track t <- H.G.enum minTrack maxTrack
+    return t
+
+genTrackFormat :: H.Gen TrackFormat
+genTrackFormat = H.G.enumBounded
diff --git a/test/Foreign/Libcdio/Util/Test/Classes.hs b/test/Foreign/Libcdio/Util/Test/Classes.hs
new file mode 100644
--- /dev/null
+++ b/test/Foreign/Libcdio/Util/Test/Classes.hs
@@ -0,0 +1,41 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019-2020 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Foreign.Libcdio.Util.Test.Classes
+    ( laws
+    , genBcd
+    ) where
+
+
+import qualified Hedgehog as H
+import qualified Hedgehog.Gen as H.G
+import qualified Hedgehog.Classes as H.C
+
+import Foreign.Libcdio.Types
+
+import Test.Libcdio.Property.Common
+
+
+laws :: [LawsGroup]
+laws =
+    [ ("Bcd", map (\f -> f genBcd)
+        [ H.C.eqLaws
+        , ordLaws'
+        , H.C.showLaws
+        , H.C.showReadLaws
+        , H.C.boundedEnumLaws
+        , storableLaws'
+        ]
+    ), ("Integral Bcd", [H.C.integralLaws $ nonZero genBcd]
+    )]
+
+
+genBcd :: H.Gen Bcd
+genBcd = H.G.enumBounded
diff --git a/test/Sound/Libcdio/CdText/Test/Classes.hs b/test/Sound/Libcdio/CdText/Test/Classes.hs
new file mode 100644
--- /dev/null
+++ b/test/Sound/Libcdio/CdText/Test/Classes.hs
@@ -0,0 +1,78 @@
+{-|
+Description:    
+
+Copyright:      (c) 2020 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Sound.Libcdio.CdText.Test.Classes
+    ( laws
+    , genCdTextError
+    , genCdTextErrorType
+    , genInfo
+    ) where
+
+
+import qualified Hedgehog as H
+import qualified Hedgehog.Gen as H.G
+import qualified Hedgehog.Range as H.R
+import qualified Hedgehog.Classes as H.C
+
+import Sound.Libcdio.Read.CdText
+
+import Foreign.Libcdio.CdText.Test.Classes hiding ( laws )
+import Test.Libcdio.Property.Common
+
+
+laws :: [LawsGroup]
+laws =
+    [ ("Info", map (\f -> f genInfo)
+        [ H.C.eqLaws
+        , H.C.showLaws
+        , H.C.showReadLaws
+        ]
+    ), ("CdTextErrrorType", map (\f -> f genCdTextErrorType)
+        [ H.C.eqLaws
+        , H.C.showLaws
+        , H.C.showReadLaws
+        ]
+    ), ("CdTextErrror", map (\f -> f genCdTextError)
+        [ H.C.eqLaws
+        , H.C.showLaws
+        , H.C.showReadLaws
+        ]
+    )]
+
+
+genCdTextErrorType :: H.Gen CdTextErrorType
+genCdTextErrorType = H.G.choice
+    [ InvalidBlock <$> H.G.word H.R.linearBounded
+    , LanguageNotFound <$> genLanguage
+    , H.G.constant BadBinaryRead
+    , FreeformCdTextError <$> genSample
+    ]
+
+genCdTextError :: H.Gen CdTextError
+genCdTextError = CdTextError <$> genCdTextErrorType <*> genSample
+
+genInfo :: H.Gen Info
+genInfo = do
+    t <- H.G.maybe genSample
+    p <- H.G.maybe genSample
+    s <- H.G.maybe genSample
+    c <- H.G.maybe genSample
+    a <- H.G.maybe genSample
+    m <- H.G.maybe genSample
+    o <- H.G.maybe genSample
+    return $ Info
+        { title = t
+        , performer = p
+        , songwriter = s
+        , composer = c
+        , arranger = a
+        , message = m
+        , code = o
+        }
diff --git a/test/Sound/Libcdio/Cdio/Test/Classes.hs b/test/Sound/Libcdio/Cdio/Test/Classes.hs
new file mode 100644
--- /dev/null
+++ b/test/Sound/Libcdio/Cdio/Test/Classes.hs
@@ -0,0 +1,55 @@
+{-|
+Description:    
+
+Copyright:      (c) 2020-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Sound.Libcdio.Cdio.Test.Classes
+    ( laws
+    , genCdioError
+    , genCdioErrorType
+    ) where
+
+
+import qualified Hedgehog as H
+import qualified Hedgehog.Gen as H.G
+import qualified Hedgehog.Classes as H.C
+
+import Sound.Libcdio
+
+import Test.Libcdio.Property.Common
+
+
+laws :: [LawsGroup]
+laws =
+    [ ("CdioErrrorType", map (\f -> f genCdioErrorType)
+        [ H.C.eqLaws
+        , H.C.showLaws
+        , H.C.showReadLaws
+        ]
+    ), ("CdioErrror", map (\f -> f genCdioError)
+        [ H.C.eqLaws
+        , H.C.showLaws
+        , H.C.showReadLaws
+        ]
+    )]
+
+
+genCdioErrorType :: H.Gen CdioErrorType
+genCdioErrorType = H.G.frequency
+    [ (6, H.G.element
+        [ DriverError
+        , BadParameter
+        , NotPermitted
+        , SessionClosed
+        , Unsupported
+        ])
+    , (1, FreeformCdioError <$> genSample)
+    ]
+
+genCdioError :: H.Gen CdioError
+genCdioError = CdioError <$> genCdioErrorType <*> genSample
diff --git a/test/Test/Libcdio/Property.hs b/test/Test/Libcdio/Property.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Property.hs
@@ -0,0 +1,79 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    non-portable (requires "GHC.IO.Encoding")
+-}
+module Main where
+
+
+import qualified Data.Bool as B
+
+import qualified GHC.IO.Encoding as GIO
+
+import qualified Hedgehog as H
+import qualified Hedgehog.Classes as H.C
+
+import qualified System.Exit as E
+import qualified System.IO as IO
+
+import qualified Data.Text.Encoding.MsJIS.Test.Classes as MsJIS
+
+import qualified Foreign.Libcdio.CdText.Test.Classes as CdText
+import qualified Foreign.Libcdio.CdTypes.Test.Classes as CdTypes
+import qualified Foreign.Libcdio.Device.Test.Classes as Device
+import qualified Foreign.Libcdio.Disc.Test.Classes as Disc
+import qualified Foreign.Libcdio.Logging.Test.Classes as Logging
+import qualified Foreign.Libcdio.Read.Test.Classes as Read
+import qualified Foreign.Libcdio.Sector.Test.Classes as Sector
+import qualified Foreign.Libcdio.Track.Test.Classes as Track
+import qualified Foreign.Libcdio.Util.Test.Classes as Util
+
+import qualified Sound.Libcdio.Cdio.Test.Classes as S.Cdio
+import qualified Sound.Libcdio.CdText.Test.Classes as S.CdText
+
+import qualified Foreign.Libcdio.Logging.Test.Property as Logging
+
+import Test.Libcdio.Property.Common
+
+
+laws :: [LawsGroup]
+laws = concat
+    [ MsJIS.laws
+    , CdText.laws
+    , CdTypes.laws
+    , Device.laws
+    , Disc.laws
+    , Logging.laws
+    , Read.laws
+    , Sector.laws
+    , Track.laws
+    , Util.laws
+    , S.Cdio.laws
+    , S.CdText.laws
+    ]
+
+
+parallelProperties :: [H.Group]
+parallelProperties =
+    [
+    ]
+
+sequentialProperties :: [H.Group]
+sequentialProperties =
+    [ Logging.properties
+    ]
+
+
+main :: IO ()
+main = do
+    GIO.setLocaleEncoding IO.utf8
+    lawsResult <- H.C.lawsCheckMany laws
+    parallelResults <- mapM H.checkParallel parallelProperties
+    sequentialResults <- mapM H.checkSequential sequentialProperties
+    B.bool E.exitFailure E.exitSuccess . and $
+        lawsResult : parallelResults ++ sequentialResults
diff --git a/test/Test/Libcdio/Property/Common.hs b/test/Test/Libcdio/Property/Common.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Property/Common.hs
@@ -0,0 +1,61 @@
+{-# LANGUAGE CPP #-}
+{-# OPTIONS_GHC -Wno-redundant-constraints #-}
+
+{-|
+Description:    
+
+Copyright:      (c) 2019-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Test.Libcdio.Property.Common where
+
+
+import qualified Data.String as S
+import qualified Data.Text as T
+
+import qualified Hedgehog as H
+import qualified Hedgehog.Gen as H.G
+import qualified Hedgehog.Classes as H.C
+import qualified Hedgehog.Range as H.R
+
+import qualified Foreign.Storable as S
+
+
+type Test = (H.PropertyName, H.Property)
+type LawsGroup = (String, [H.C.Laws])
+
+
+enumSparse :: (Enum a, Bounded a) => H.Gen a
+enumSparse = H.G.element [minBound..maxBound]
+
+nonZero :: (Eq a, Num a) => H.Gen a -> H.Gen a
+nonZero = H.G.filter (/= 0)
+
+
+packTest :: String -> H.PropertyT IO () -> Test
+packTest name prop = (S.fromString name, H.property prop)
+
+
+genSample :: H.Gen T.Text
+genSample = H.G.text (H.R.linear 1 12) $ H.G.frequency [c7, c8]
+  where c7 = (0x5F, H.G.enum ' ' '~')
+        c8 = (0x60, H.G.enum '\xA0' '\xFF')
+
+
+ordLaws' :: (Ord a, Show a) => H.Gen a -> H.C.Laws
+#if MIN_VERSION_hedgehog_classes(0,2,1)
+ordLaws' = H.C.ordLaws
+#else
+ordLaws' = const $ H.C.Laws "Ord" []
+#endif
+
+storableLaws' :: (Eq a, Show a, S.Storable a) => H.Gen a -> H.C.Laws
+#if MIN_VERSION_hedgehog_classes(0,2,6)
+storableLaws' = H.C.storableLaws
+#else
+storableLaws' = const $ H.C.Laws "Storable" []
+#endif
diff --git a/test/Test/Libcdio/Unit.hs b/test/Test/Libcdio/Unit.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Unit.hs
@@ -0,0 +1,41 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Main where
+
+
+import qualified Control.Monad as M
+import qualified System.Exit as E
+import qualified Test.HUnit as U
+
+import qualified Data.Text.Encoding.MsJIS.Test.Unit as MsJIS
+
+import qualified Test.Libcdio.Unit.Foreign.CarolusRex as Rex
+import qualified Test.Libcdio.Unit.Foreign.DeeperDance as Dance
+import qualified Test.Libcdio.Unit.Foreign.RevolutionDays as Revolution
+
+import qualified Test.Libcdio.Unit.Sound.CarolusRex as S.Rex
+import qualified Test.Libcdio.Unit.Sound.DeeperDance as S.Dance
+import qualified Test.Libcdio.Unit.Sound.RevolutionDays as S.Revolution
+
+
+main :: IO ()
+main = do
+    results <- U.runTestTT $ U.TestList
+        [ MsJIS.tests
+        , Dance.tests
+        , Revolution.tests
+        , Rex.tests
+        , S.Dance.tests
+        , S.Rex.tests
+        , S.Revolution.tests
+        ]
+    
+    M.unless (U.errors results == 0 && U.failures results == 0) E.exitFailure
diff --git a/test/Test/Libcdio/Unit/Common.hs b/test/Test/Libcdio/Unit/Common.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Unit/Common.hs
@@ -0,0 +1,22 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019-2020 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Test.Libcdio.Unit.Common where
+
+
+dataDir :: FilePath
+dataDir = "test/datafiles/unit/"
+
+dataFile :: FilePath -> FilePath
+dataFile = (++) dataDir
+
+
+mapBoth :: (a -> b) -> (a, a) -> (b, b)
+mapBoth f (l, r) = (f l, f r)
diff --git a/test/Test/Libcdio/Unit/Foreign/CarolusRex.hs b/test/Test/Libcdio/Unit/Foreign/CarolusRex.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Unit/Foreign/CarolusRex.hs
@@ -0,0 +1,102 @@
+{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
+
+{-|
+Description:    Tests of multi-block CDTEXT in the Foreign interface.
+
+Copyright:      (c) 2019-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+
+The CDTEXT file used in this module was generated using the tool written by
+Pigeon at <https://pigeonsnest.co.uk/stuff/cdtext.html> (warning for a /lot/ of
+swearing).  The encoding was later manually set to ASCII.
+-}
+module Test.Libcdio.Unit.Foreign.CarolusRex (tests) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (@?), (@?=), (~:) )
+
+import qualified Data.ByteString as BS
+import qualified Data.Maybe as Y
+
+import Foreign.Libcdio.CdText
+
+import Test.Libcdio.Unit.Common
+
+
+testFile :: FilePath
+testFile = dataFile "carolus-rex.cdtext"
+
+
+tests :: U.Test
+tests = "Foreign.Libcdio.Test.CarolusRex" ~: U.TestList
+    [ parse
+    ]
+
+parse :: U.Test
+parse = "Binary CDTEXT is read properly" ~: U.TestCase $ do
+    bs <- BS.readFile testFile
+    x' <- cdTextDataInit bs
+    
+    Y.isJust x' @? "Failed to read binary CdText"
+    let Just x = x'
+    
+    checkLanguage x English
+    checkLanguage x Swedish
+
+checkLanguage :: Cdio -> Language -> U.Assertion
+checkLanguage x l = do
+    b <- selectLanguage x l
+    b @? "Unable to change language to " ++ show l
+    
+    l' <- language x
+    l' @?= Just l
+    
+    t1 <- firstTrack x
+    t1 @?= Just 1
+    
+    tl <- lastTrack x
+    tl @?= Just (fromIntegral $ length titlesEnglish)
+    
+    t <- cdTextGet x Title Nothing
+    t @?= Just "Carolus Rex"
+    
+    p <- cdTextGet x Performer Nothing
+    p @?= Just "Sabaton"
+    
+    ts <- mapM (cdTextGet x Title . Just . fromIntegral) [1 .. length titlesEnglish]
+    ts @?= if l == English then titlesEnglish else titlesSwedish
+
+titlesEnglish :: [Maybe String]
+titlesEnglish = map Just
+        [ "Dominium maris Baltici"
+        , "The Lion from the North"
+        , "Gott mit uns"
+        , "A Lifetime of War"
+        , "1648"
+        , "The Carolean's Prayer"
+        , "Carolus Rex"
+        , "Killing Ground"
+        , "Poltava"
+        , "Long Live the King"
+        , "Ruina Imperii"
+        ]
+
+titlesSwedish :: [Maybe String]
+titlesSwedish = map Just
+    [ "Dominium maris Baltici"
+    , "Lejonet fraan Norden"
+    , "Gott mit uns"
+    , "En Livstid i krig"
+    , "1648"
+    , "Karolinens bo:n"
+    , "Carolus Rex"
+    , "Ett slag fa:rgat ro:tt"
+    , "Poltava"
+    , "Konungens likfa:rd"
+    , "Ruina Imperii"
+    ]
diff --git a/test/Test/Libcdio/Unit/Foreign/DeeperDance.hs b/test/Test/Libcdio/Unit/Foreign/DeeperDance.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Unit/Foreign/DeeperDance.hs
@@ -0,0 +1,85 @@
+{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
+
+{-|
+Description:    
+
+Copyright:      (c) 2019-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+
+The CDTEXT file used in this module comes via James Olin Oden at
+<https://bugzilla.redhat.com/show_bug.cgi?id=1321677#c3>.
+-}
+module Test.Libcdio.Unit.Foreign.DeeperDance (tests) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (@?), (@?=), (~:) )
+
+import qualified Control.Monad as M
+
+import qualified Data.ByteString as BS
+import qualified Data.Maybe as Y
+
+import Foreign.Libcdio.CdText
+
+import Test.Libcdio.Unit.Common
+
+
+testFile :: FilePath
+testFile = dataFile "deeper-dance.cdtext"
+
+
+tests :: U.Test
+tests = "Foreign.Libcdio.Test.DeeperDance" ~: U.TestList
+    [ parse
+    ]
+
+parse :: U.Test
+parse = "Binary CDTEXT is read properly" ~: U.TestCase $ do
+    bs <- BS.readFile testFile
+    x' <- cdTextDataInit bs
+
+    Y.isJust x' @? "Failed to read binary CdText"
+    let Just x = x'
+
+    l <- language x
+    l @?= Just English
+
+    t1 <- firstTrack x
+    t1 @?= Just 1
+
+    tl <- lastTrack x
+    tl @?= Just (fromIntegral $ length titles)
+
+    t <- cdTextGet x Title Nothing
+    t @?= Just "Deeper Dance"
+
+    p <- cdTextGet x Performer Nothing
+    p @?= performer
+
+    ts <- M.forM [1 .. length titles] $ \i -> do
+         t' <- cdTextGet x Title . Just $ fromIntegral i
+         p' <- cdTextGet x Performer . Just $ fromIntegral i
+         return (t', p')
+    ts @?= zip titles (repeat performer)
+
+performer :: Maybe String
+performer = Just "James Olin Oden"
+
+titles :: [Maybe String]
+titles = map Just
+    [ "Deeper Dance"
+    , "The Hunt"
+    , "Harold's Dream"
+    , "Jazz Fusion No. 9"
+    , "Love's Tattoo"
+    , "The Day I Told Her Micheal Domhnaill Died"
+    , "The Fool Amongst the Keeners"
+    , "Love Is Not Tame"
+    , "Dear John and the Big Red Pickup Truck"
+    , "Dance Right Out of My Grave"
+    ]
diff --git a/test/Test/Libcdio/Unit/Foreign/RevolutionDays.hs b/test/Test/Libcdio/Unit/Foreign/RevolutionDays.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Unit/Foreign/RevolutionDays.hs
@@ -0,0 +1,77 @@
+{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
+
+{-|
+Description:    
+
+Copyright:      (c) 2019-2020 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+
+The CDTEXT file used in this module comes via Pigeon at
+<https://pigeonsnest.co.uk/stuff/cdtext.html> (warning for a /lot/ of
+swearing).  The encoding was later manually set to ASCII.
+-}
+module Test.Libcdio.Unit.Foreign.RevolutionDays (tests) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (@?), (@?=), (~:) )
+
+import qualified Data.ByteString as BS
+import qualified Data.Maybe as Y
+
+import Foreign.Libcdio.CdText
+
+import Test.Libcdio.Unit.Common
+
+
+testFile :: FilePath
+testFile = dataFile "revolution-days.cdtext"
+
+
+tests :: U.Test
+tests = "Foreign.Libcdio.Test.RevolutionDays" ~: U.TestList
+    [ parse
+    ]
+
+parse :: U.Test
+parse = "Binary CDTEXT is read properly" ~: U.TestCase $ do
+    bs <- BS.readFile testFile
+    x' <- cdTextDataInit bs
+
+    Y.isJust x' @? "Failed to read binary CdText"
+    let Just x = x'
+
+    t1 <- firstTrack x
+    t1 @?= Just 1
+
+    tl <- lastTrack x
+    tl @?= Just (fromIntegral $ length titles)
+
+    t <- cdTextGet x Title Nothing
+    t @?= Just "REVOLUTION DAYS"
+
+    p <- cdTextGet x Performer Nothing
+    p @?= Just "BARCLAY JAMES HARVEST FEATURING LES HOLROYD"
+
+    ts <- mapM (cdTextGet x Title . Just . fromIntegral) [1 .. length titles]
+    ts @?= titles
+
+titles :: [Maybe String]
+titles = map Just
+    [ "IT'S MY LIFE"
+    , "MISSING YOU"
+    , "THAT WAS THEN... THIS IS NOW"
+    , "PRELUDE"
+    , "JANUARY MORNING"
+    , "LOVE ON THE LINE"
+    , "QUIERO EL SOL"
+    , "TOTALLY COOL"
+    , "LIFE IS FOR LIVING"
+    , "SLEEPY SUNDAY"
+    , "REVOLUTION DAY"
+    , "MARLENE (from the BERLIN SUITE)"
+    ]
diff --git a/test/Test/Libcdio/Unit/Sound/CarolusRex.hs b/test/Test/Libcdio/Unit/Sound/CarolusRex.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Unit/Sound/CarolusRex.hs
@@ -0,0 +1,92 @@
+{-|
+Description:    Tests of multi-block CDTEXT in the Sound interface.
+
+Copyright:      (c) 2020-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+
+The CDTEXT file used in this module was generated using the tool written by
+Pigeon at <https://pigeonsnest.co.uk/stuff/cdtext.html> (warning for a /lot/ of
+swearing).  The encoding was later manually set to ASCII.
+-}
+module Test.Libcdio.Unit.Sound.CarolusRex (tests) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (@?=), (~:) )
+
+import qualified Data.ByteString as BS
+import qualified Data.Maybe as Y
+import qualified Data.Text as T
+
+import Sound.Libcdio.Read.CdText
+
+import Test.Libcdio.Unit.Sound.Common
+
+
+testFile :: FilePath
+testFile = dataFile "carolus-rex.cdtext"
+
+
+tests :: U.Test
+tests = "Sound.Libcdio.Test.CarolusRex" ~: U.TestList
+    [ binary
+    ]
+
+binary :: U.Test
+binary = "Binary CDTEXT is read properly" ~: U.TestCase $ do
+    bs <- BS.readFile testFile
+    x <- parseCdText bs . withAll $ do
+        l <- language
+        a <- checkLanguage $ zip langs [infoEnglish, infoSwedish]
+        return (l, a)
+    either (const $ U.assertFailure "Could not parse binary data") runAssertions x
+
+runAssertions :: [Maybe (Language, U.Assertion)] -> IO ()
+runAssertions xs = do
+    let (ls, as) = unzip $ Y.catMaybes xs
+    ls @?= langs
+    sequence_ as
+
+
+langs :: [Language]
+langs = [English, Swedish]
+
+infoEnglish :: [Info]
+infoEnglish = emptyInfo
+    { title = Just $ T.pack "Carolus Rex"
+    , performer = Just $ T.pack "Sabaton"
+    } : map (\t -> emptyInfo { title = Just $ T.pack t })
+        [ "Dominium maris Baltici"
+        , "The Lion from the North"
+        , "Gott mit uns"
+        , "A Lifetime of War"
+        , "1648"
+        , "The Carolean's Prayer"
+        , "Carolus Rex"
+        , "Killing Ground"
+        , "Poltava"
+        , "Long Live the King"
+        , "Ruina Imperii"
+        ]
+
+infoSwedish :: [Info]
+infoSwedish = emptyInfo
+    { title = Just $ T.pack "Carolus Rex"
+    , performer = Just $ T.pack "Sabaton"
+    } : map (\t -> emptyInfo { title = Just $ T.pack t })
+        [ "Dominium maris Baltici"
+        , "Lejonet fraan Norden"
+        , "Gott mit uns"
+        , "En Livstid i krig"
+        , "1648"
+        , "Karolinens bo:n"
+        , "Carolus Rex"
+        , "Ett slag fa:rgat ro:tt"
+        , "Poltava"
+        , "Konungens likfa:rd"
+        , "Ruina Imperii"
+        ]
diff --git a/test/Test/Libcdio/Unit/Sound/Common.hs b/test/Test/Libcdio/Unit/Sound/Common.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Unit/Sound/Common.hs
@@ -0,0 +1,38 @@
+{-|
+Description:    
+
+Copyright:      (c) 2020-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Test.Libcdio.Unit.Sound.Common
+    ( module Test.Libcdio.Unit.Common
+    , checkLanguage
+    ) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (@?=) )
+
+import Sound.Libcdio.Read.CdText
+
+import Test.Libcdio.Unit.Common
+
+
+checkLanguage :: [(Language, [Info])] -> CdText U.Assertion
+checkLanguage ls = do
+    l <- language
+    let is' = lookup l ls
+    t1 <- firstTrack
+    tl <- lastTrack
+    i <- info Nothing
+    is <- mapM (info . Just) [t1..tl]
+    return $ case is' of
+        Just is'' -> do
+            t1 @?= 1
+            tl @?= fromIntegral (length is)
+            i : is @?= is''
+        Nothing -> U.assertFailure "Unexpected language in CdText"
diff --git a/test/Test/Libcdio/Unit/Sound/DeeperDance.hs b/test/Test/Libcdio/Unit/Sound/DeeperDance.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Unit/Sound/DeeperDance.hs
@@ -0,0 +1,66 @@
+{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
+
+{-|
+Description:    
+
+Copyright:      (c) 2020-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+
+The CDTEXT file used in this module comes via James Olin Oden at
+<https://bugzilla.redhat.com/show_bug.cgi?id=1321677#c3>.
+-}
+module Test.Libcdio.Unit.Sound.DeeperDance (tests) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (~:) )
+
+import qualified Data.ByteString as BS
+import qualified Data.Either.Compat as E
+import qualified Data.Text as T
+
+import Sound.Libcdio.Read.CdText
+
+import Test.Libcdio.Unit.Sound.Common
+
+
+testFile :: FilePath
+testFile = dataFile "deeper-dance.cdtext"
+
+
+tests :: U.Test
+tests = "Sound.Libcdio.Test.DeeperDance" ~: U.TestList
+    [ binary
+    ]
+
+binary :: U.Test
+binary = "Binary CDTEXT is read properly" ~: U.TestCase $ do
+    bs <- BS.readFile testFile
+    x <- parseCdText bs $ checkLanguage [(English, infos)]
+    E.fromRight (U.assertFailure "Could not parse binary data") x
+
+
+performer' :: Maybe T.Text
+performer' = Just $ T.pack "James Olin Oden"
+
+infos :: [Info]
+infos = map (\t -> emptyInfo
+    { title = Just $ T.pack t
+    , performer = performer'
+    })
+    [ "Deeper Dance"
+    , "Deeper Dance"
+    , "The Hunt"
+    , "Harold's Dream"
+    , "Jazz Fusion No. 9"
+    , "Love's Tattoo"
+    , "The Day I Told Her Micheal Domhnaill Died"
+    , "The Fool Amongst the Keeners"
+    , "Love Is Not Tame"
+    , "Dear John and the Big Red Pickup Truck"
+    , "Dance Right Out of My Grave"
+    ]
diff --git a/test/Test/Libcdio/Unit/Sound/RevolutionDays.hs b/test/Test/Libcdio/Unit/Sound/RevolutionDays.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Unit/Sound/RevolutionDays.hs
@@ -0,0 +1,63 @@
+{-|
+Description:    
+
+Copyright:      (c) 2020-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+
+The CDTEXT file used in this module comes via Pigeon at
+<https://pigeonsnest.co.uk/stuff/cdtext.html> (warning for a /lot/ of
+swearing).  The encoding was later manually set to ASCII.
+-}
+module Test.Libcdio.Unit.Sound.RevolutionDays (tests) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (~:) )
+
+import qualified Data.ByteString as BS
+import qualified Data.Either.Compat as E
+import qualified Data.Text as T
+
+import Sound.Libcdio.Read.CdText
+
+import Test.Libcdio.Unit.Sound.Common
+
+
+testFile :: FilePath
+testFile = dataFile "revolution-days.cdtext"
+
+
+tests :: U.Test
+tests = "Sound.Libcdio.Test.RevolutionDays" ~: U.TestList
+    [ binary
+    ]
+
+binary :: U.Test
+binary = "Binary CDTEXT is read properly" ~: U.TestCase $ do
+    bs <- BS.readFile testFile
+    x <- parseCdText bs . withLanguage English $ checkLanguage [(English, infos)]
+    E.fromRight (U.assertFailure "Could not read binary data") x
+
+
+infos :: [Info]
+infos = emptyInfo
+    { title = Just $ T.pack "REVOLUTION DAYS"
+    , performer = Just $ T.pack "BARCLAY JAMES HARVEST FEATURING LES HOLROYD"
+    } : map (\t -> emptyInfo { title = Just $ T.pack t })
+        [ "IT'S MY LIFE"
+        , "MISSING YOU"
+        , "THAT WAS THEN... THIS IS NOW"
+        , "PRELUDE"
+        , "JANUARY MORNING"
+        , "LOVE ON THE LINE"
+        , "QUIERO EL SOL"
+        , "TOTALLY COOL"
+        , "LIFE IS FOR LIVING"
+        , "SLEEPY SUNDAY"
+        , "REVOLUTION DAY"
+        , "MARLENE (from the BERLIN SUITE)"
+        ]
diff --git a/test/Test/Libcdio/Upstream.hs b/test/Test/Libcdio/Upstream.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Upstream.hs
@@ -0,0 +1,54 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Main where
+
+
+import qualified Control.Monad as M
+import qualified System.Exit as E
+import qualified Test.HUnit as U
+
+import qualified Test.Libcdio.Upstream.Foreign.BinCue as BinCue
+import qualified Test.Libcdio.Upstream.Foreign.CdrDao as CdrDao
+import qualified Test.Libcdio.Upstream.Foreign.FreeBsd as FreeBsd
+import qualified Test.Libcdio.Upstream.Foreign.Linux as Linux
+import qualified Test.Libcdio.Upstream.Foreign.Nrg as Nrg
+import qualified Test.Libcdio.Upstream.Foreign.OsX as OsX
+import qualified Test.Libcdio.Upstream.Foreign.Pregap as Pregap
+import qualified Test.Libcdio.Upstream.Foreign.Solaris as Solaris
+import qualified Test.Libcdio.Upstream.Foreign.SizeOf as SizeOf
+import qualified Test.Libcdio.Upstream.Foreign.Track as Track
+import qualified Test.Libcdio.Upstream.Foreign.Win32 as Win32
+
+import qualified Test.Libcdio.Upstream.Sound.Image as Sound.Image
+import qualified Test.Libcdio.Upstream.Sound.System as Sound.System
+import qualified Test.Libcdio.Upstream.Sound.Track as Sound.Track
+
+
+main :: IO ()
+main = do
+    results <- U.runTestTT $ U.TestList
+        [ BinCue.tests
+        , CdrDao.tests
+        , FreeBsd.tests
+        , Linux.tests
+        , Nrg.tests
+        , OsX.tests
+        , Pregap.tests
+        , Solaris.tests
+        , SizeOf.tests
+        , Track.tests
+        , Win32.tests
+        , Sound.Image.tests
+        , Sound.System.tests
+        , Sound.Track.tests
+        ]
+    
+    M.unless (U.errors results == 0 && U.failures results == 0) E.exitFailure
diff --git a/test/Test/Libcdio/Upstream/Foreign/BinCue.hs b/test/Test/Libcdio/Upstream/Foreign/BinCue.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Upstream/Foreign/BinCue.hs
@@ -0,0 +1,86 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019-2020 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Test.Libcdio.Upstream.Foreign.BinCue
+    ( tests
+    , goodCues
+    , badCues
+    ) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (@?), (@?=), (~:) )
+
+import qualified Data.Maybe as Y
+
+-- import qualified System.Directory as D
+
+import Foreign.Libcdio.Device
+
+import Test.Libcdio.Upstream.Foreign.Common
+
+
+tests :: U.Test
+tests = "Foreign.Libcdio.Test.BinCue" ~: U.TestList
+    [ parse
+    , open
+    ]
+
+
+parse :: U.Test
+parse = "Distinguish valid and invalid CUE files" ~: U.TestList
+    (map good goodCues ++ map bad badCues)
+  where good = cueTest Y.isJust "is not recognized as a CUE file"
+        bad = cueTest Y.isNothing "should not be recognized as a CUE file"
+        cueTest t s f = U.TestCase $ t <$> binFromCue (dataFile f) @? "'" ++ f ++ "' " ++ s
+
+goodCues :: [FilePath]
+goodCues =
+    [ "cdda.cue"
+    , "isofs-m1.cue"
+    ]
+
+badCues :: [FilePath]
+badCues =
+    [ "bad-cat1.cue"
+    , "bad-cat2.cue"
+    , "bad-cat3.cue"
+    , "bad-mode1.cue"
+    , "bad-msf-1.cue"
+    , "bad-msf-2.cue"
+    , "bad-msf-3.cue"
+    ]
+
+
+open :: U.Test
+open = "CUE files open the associated device correctly" ~: U.TestCase $ do
+    c <- cdioOpen (Just $ dataFile "cdda.cue") DriverUnknown
+    cdio <- case c of
+        Nothing -> U.assertFailure "Can't open the CUE file"
+        Just c' -> return c'
+    
+    b <- setBlocksize cdio 2048
+    b @?= Unsupported
+    
+    checkMmc cdio $ Just False
+    checkAccessMode cdio [Image]
+    
+    {- Seems to be either an unimplemented or a reverted equivalence
+    d <- D.withCurrentDirectory dataDir . defaultDevice $ Just cdio
+    device <- case d of
+        Nothing -> U.assertFailure "No default device returned for the CUE file"
+        Just d' -> return d'
+    checkSource cdio [device]
+    -}
+    
+    s <- setSpeed cdio 5
+    s @?= Unsupported
+    
+    return ()
diff --git a/test/Test/Libcdio/Upstream/Foreign/CdrDao.hs b/test/Test/Libcdio/Upstream/Foreign/CdrDao.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Upstream/Foreign/CdrDao.hs
@@ -0,0 +1,85 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Test.Libcdio.Upstream.Foreign.CdrDao
+    ( tests
+    , goodToc
+    , badToc
+    ) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (@?), (~:) )
+
+import qualified System.Directory as D
+
+import Foreign.Libcdio.Device
+
+import Test.Libcdio.Upstream.Foreign.Common
+
+
+tests :: U.Test
+tests = "Foreign.Libcdio.Test.CdrDao" ~: U.TestList
+    [ parse
+    , open
+    ]
+
+
+parse :: U.Test
+parse = "Distinguish valid and invalid TOC files" ~: U.TestList
+    (map good goodToc ++ map bad badToc)
+  where good = tocTest id "is not recognized as a TOC file"
+        bad = tocTest not "should not be recognized as a TOC file"
+        tocTest t s f = U.TestCase . D.withCurrentDirectory dataDir $ fmap t (isToc f) @? "'" ++ f ++ "' " ++ s
+
+goodToc :: [FilePath]
+goodToc =
+    [ "cdtext.toc"
+    , "t1.toc"
+    , "t2.toc"
+    , "t3.toc"
+    , "t4.toc"
+    , "t5.toc"
+    , "t6.toc"
+    , "t7.toc"
+    , "t8.toc"
+    , "t9.toc"
+    , "t10.toc"
+    , "data1.toc"
+    , "data2.toc"
+    , "data5.toc"
+    , "data6.toc"
+    , "data7.toc"
+    , "vcd2.toc"
+    ]
+
+badToc :: [FilePath]
+badToc =
+    [ "bad-cat1.toc"
+    , "bad-cat2.toc"
+    , "bad-cat3.toc"
+    , "bad-file.toc"
+    , "bad-mode1.toc"
+    , "bad-msf-1.toc"
+    , "bad-msf-2.toc"
+    , "bad-msf-3.toc"
+    ]
+
+
+open :: U.Test
+open = "TOC files open the associated device correctly" ~: U.TestCase $ do
+    c <- cdioOpen (Just $ dataFile "cdtext.toc") DriverUnknown
+    cdio <- case c of
+        Nothing -> U.assertFailure "Can't open the TOC file"
+        Just c' -> return c'
+    
+    checkMmc cdio $ Just False
+    checkAccessMode cdio [Image]
+    checkSource cdio [dataFile "cdtext.toc"]
diff --git a/test/Test/Libcdio/Upstream/Foreign/Common.hs b/test/Test/Libcdio/Upstream/Foreign/Common.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Upstream/Foreign/Common.hs
@@ -0,0 +1,84 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+
+The semantics of several functions in this module were copied from
+@test/driver/helper.*@ in the libcdio source, but their implementation was
+rewritten for the Haskell wrapper.
+-}
+module Test.Libcdio.Upstream.Foreign.Common where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (@?), (@=?), (~:) )
+
+import qualified Control.Monad as M
+
+import qualified Data.Char as C
+import qualified Data.Maybe as Y
+
+import Foreign.Libcdio.Device
+
+
+dataDir :: String
+dataDir = "test/datafiles/upstream/"
+
+dataFile :: String -> String
+dataFile = (++) dataDir
+
+
+checkArg :: SessionArg -> Cdio -> [String] -> U.Assertion
+checkArg k c ss = do
+    v <- getArg c k
+    value <- case v of
+        Nothing -> U.assertFailure $ show k ++ "' isn't assigned"
+        Just v' -> return v'
+    null ss || elem value ss @? show k ++ "' has invalid value '" ++ value ++ "'"
+
+checkAccessMode :: Cdio -> [AccessMode] -> U.Assertion
+checkAccessMode c ms = do
+    v <- getAccessMode c
+    value <- case v of
+        Nothing -> U.assertFailure "'access-mode' isn't assigned"
+        Just v' -> return v'
+    null ms || elem value ms @? "'access-mode' has invalid value '" ++ show value ++ "'"
+
+checkSource :: Cdio -> [String] -> U.Assertion
+checkSource = checkArg Source
+
+
+-- | Whether the session advertises MMC support.  A 'Nothing' value indicates
+-- that the actual state doesn't matter, just that it's advertised at all.
+-- 
+-- The C function takes a numeric value translating to the following:
+-- 
+--   * @1@ -> 'Just' 'False'
+--   * @2@ -> 'Just' 'True'
+--   * @3@ -> 'Nothing'
+checkMmc :: Cdio -> Maybe Bool -> U.Assertion
+checkMmc c b = do
+    v <- getArg c MmcSupported
+    Y.isJust v @? "Session does not describe MMC status."
+    case b of
+        Just _ -> map C.toLower . show <$> b @=? v
+        Nothing -> return ()
+
+
+find :: DriverId -> Maybe AccessMode -> ((Cdio, String) -> U.Assertion) -> U.Test
+find d m f = "The driver is able to find its devices" ~: U.TestCase $ do
+    ss <- devices d
+    not (null ss) @? "Can't find a device"
+    let open s = case m of
+            Nothing -> cdioOpen s d
+            Just m' -> cdioOpenAm s d m'
+    cs <- mapM (open . Just) ss
+    cs' <- M.forM (zip ss cs) $ \(s, c) -> case c of
+        Nothing -> U.assertFailure $ "Can't open device '" ++ s ++ "'"
+        Just c' -> return c'
+    mapM_ f $ zip cs' ss
diff --git a/test/Test/Libcdio/Upstream/Foreign/FreeBsd.hs b/test/Test/Libcdio/Upstream/Foreign/FreeBsd.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Upstream/Foreign/FreeBsd.hs
@@ -0,0 +1,38 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Test.Libcdio.Upstream.Foreign.FreeBsd (tests) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (~:) )
+
+import Foreign.Libcdio.Device
+
+import Test.Libcdio.Upstream.Foreign.Common
+
+
+tests :: U.Test
+tests = "Foreign.Libcdio.Test.FreeBsd" ~: U.TestList tests'
+  where tests' | haveDriver DriverFreeBsd =
+                    [ open
+                    , find DriverFreeBsd Nothing $ \(c, s) -> checkSource c [s]
+                    ]
+               | otherwise = []
+
+open :: U.Test
+open = "The driver opens devices correctly" ~: U.TestCase $ do
+    c <- cdioOpen Nothing DriverFreeBsd
+    cdio <- case c of
+        Nothing -> U.assertFailure "Can't open the default device"
+        Just c' -> return c'
+    
+    checkAccessMode cdio [Ioctl_, Cam]
+    checkMmc cdio $ Just False
diff --git a/test/Test/Libcdio/Upstream/Foreign/Linux.hs b/test/Test/Libcdio/Upstream/Foreign/Linux.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Upstream/Foreign/Linux.hs
@@ -0,0 +1,47 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Test.Libcdio.Upstream.Foreign.Linux (tests) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (~:) )
+
+import Foreign.Libcdio.Device
+
+import Test.Libcdio.Upstream.Foreign.Common
+
+
+tests :: U.Test
+tests = "Foreign.Libcdio.Test.Linux" ~: U.TestList tests'
+  where tests' | haveDriver DriverLinux =
+                  [ find DriverLinux (Just MmcReadWrite) check
+                  ]
+               | otherwise = []
+
+check :: (Cdio, String) -> U.Assertion
+check (cdio, source) = do
+    {- Exact behaviour dependant on whether there's a disc in the drive
+    tc <- lastTrackNum cdio
+    if Y.fromMaybe maxTrack tc >= maxTrack - 1
+    then mempty
+    else do
+        l <- trackLsn cdio maxTrack
+        Y.isNothing l @? "Overlarge track not detected"
+    -}
+    
+    checkSource cdio [source]
+    checkMmc cdio Nothing
+    
+    checkArg ScsiTuple cdio []
+    
+    {- Access mode doesn't seem implemented
+    checkAccessMode cdio [MmcReadWrite]
+    -}
diff --git a/test/Test/Libcdio/Upstream/Foreign/Nrg.hs b/test/Test/Libcdio/Upstream/Foreign/Nrg.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Upstream/Foreign/Nrg.hs
@@ -0,0 +1,50 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019-2020 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Test.Libcdio.Upstream.Foreign.Nrg
+    ( tests
+    , goodNrg
+    ) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (@=?), (~:) )
+
+import Foreign.Libcdio.CdText
+import Foreign.Libcdio.Device
+
+import Test.Libcdio.Upstream.Foreign.Common
+
+
+tests :: U.Test
+tests = "Foreign.Libcdio.Test.Nrg" ~: U.TestList $ map open goodNrg
+
+
+goodNrg :: [FilePath]
+goodNrg
+    | haveDriver DriverNrg = ["p1.nrg"]
+    | otherwise = []
+
+
+open :: FilePath -> U.Test
+open f = "Nero images open the associated device correctly" ~: U.TestCase $ do
+    c <- cdioOpen (Just $ dataFile f) DriverUnknown
+    cdio <- case c of
+        Nothing -> U.assertFailure "Can't open the Nero file"
+        Just c' -> return c'
+    
+    p <- cdTextGet cdio Performer Nothing
+    Just "Richard Stallman" @=? p
+    t <- cdTextGet cdio Title Nothing
+    Just "Join us now we have the software" @=? t
+    
+    checkMmc cdio $ Just False
+    checkAccessMode cdio [Image]
+    checkSource cdio [dataFile f]
diff --git a/test/Test/Libcdio/Upstream/Foreign/OsX.hs b/test/Test/Libcdio/Upstream/Foreign/OsX.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Upstream/Foreign/OsX.hs
@@ -0,0 +1,39 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Test.Libcdio.Upstream.Foreign.OsX (tests) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (@?), (~:) )
+
+import qualified Data.Maybe as Y
+
+import Foreign.Libcdio.Device
+import Foreign.Libcdio.Disc
+
+import Test.Libcdio.Upstream.Foreign.Common
+
+
+tests :: U.Test
+tests = "Foreign.Libcdio.Test.OsX" ~: U.TestList tests'
+  where tests' | haveDriver DriverOsX =
+                  [ find DriverOsX Nothing check
+                  ]
+               | otherwise = []
+
+check :: (Cdio, String) -> U.Assertion
+check (cdio, source) = do
+    checkSource cdio [source]
+    -- can't supply arbitrary access modes
+    --checkAccessMode cdio ["OS X"]
+    
+    m <- discMode cdio
+    Y.isJust m @? "Error getting disc mode for device '" ++ source ++ "'"
diff --git a/test/Test/Libcdio/Upstream/Foreign/Pregap.hs b/test/Test/Libcdio/Upstream/Foreign/Pregap.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Upstream/Foreign/Pregap.hs
@@ -0,0 +1,54 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019-2020 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Test.Libcdio.Upstream.Foreign.Pregap
+    ( tests
+    , gaps
+    ) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (@=?), (~:) )
+
+import qualified Control.Monad as M
+
+import qualified System.Directory as D
+
+import Foreign.Libcdio.Device
+import Foreign.Libcdio.Track
+import Foreign.Libcdio.Types
+
+import Test.Libcdio.Upstream.Foreign.Common
+
+
+tests :: U.Test
+tests = "Foreign.Libcdio.Test.Pregap" ~: map ((\f (a,b,c)->f a b c) checkGap) gaps
+
+gaps :: [(DriverId, FilePath, [(Track, Maybe Lsn)])]
+gaps =
+    [ (DriverCdrDao, "t2.toc", [(1, Just 4425), (2, Nothing)])
+    , (DriverBinCue, "p1.cue", [(1, Just 0), (2, Just 150), (3, Nothing)])
+    ] ++
+    [ (DriverNrg, "p1.nrg", [(2, Just 225), (3, Nothing)])
+    | haveDriver DriverNrg
+    ]
+
+checkGap :: DriverId -> FilePath -> [(Track, Maybe Lsn)] -> U.Assertion
+checkGap d s gs
+    | haveDriver d = do
+        c <- D.withCurrentDirectory dataDir $ cdioOpen (Just s) d
+        cdio <- case c of
+            Nothing -> U.assertFailure $ "Can't open the disc image '" ++ s ++ "'"
+            Just c' -> return c'
+        
+        M.forM_ gs $ \(t, g) -> do
+            p <- pregapLsn cdio t
+            g @=? p
+    | otherwise = return ()
diff --git a/test/Test/Libcdio/Upstream/Foreign/SizeOf.hs b/test/Test/Libcdio/Upstream/Foreign/SizeOf.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Upstream/Foreign/SizeOf.hs
@@ -0,0 +1,26 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Test.Libcdio.Upstream.Foreign.SizeOf (tests) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (~=?), (~:) )
+
+import qualified Foreign.Storable as S
+
+import Foreign.Libcdio.Sector
+
+
+tests :: U.Test
+tests = "Foreign.Libcdio.Test.SizeOf" ~: U.TestList
+    [ 3 ~=? S.sizeOf (Msf 0 0 0)
+    --TODO: More from iso9660_private.h
+    ]
diff --git a/test/Test/Libcdio/Upstream/Foreign/Solaris.hs b/test/Test/Libcdio/Upstream/Foreign/Solaris.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Upstream/Foreign/Solaris.hs
@@ -0,0 +1,32 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Test.Libcdio.Upstream.Foreign.Solaris (tests) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (~:) )
+
+import Foreign.Libcdio.Device
+
+import Test.Libcdio.Upstream.Foreign.Common
+
+
+tests :: U.Test
+tests = "Foreign.Libcdio.Test.Solaris" ~: U.TestList tests'
+  where tests' | haveDriver DriverSolaris =
+                  [ find DriverSolaris (Just Scsi) check
+                  ]
+               | otherwise = []
+
+check :: (Cdio, String) -> U.Assertion
+check (cdio, source) = do
+    checkSource cdio [source]
+    checkAccessMode cdio [Scsi]
diff --git a/test/Test/Libcdio/Upstream/Foreign/Track.hs b/test/Test/Libcdio/Upstream/Foreign/Track.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Upstream/Foreign/Track.hs
@@ -0,0 +1,44 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Test.Libcdio.Upstream.Foreign.Track (tests) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (@?), (@=?), (~:) )
+
+import qualified Data.Maybe as Y
+
+import Foreign.Libcdio.Device
+import Foreign.Libcdio.Track
+
+import Test.Libcdio.Upstream.Foreign.Common
+
+
+tests :: U.Test
+tests = "Foreign.Libcdio.Test.Track" ~: U.TestList
+    [ open
+    ]
+
+open :: U.Test
+open = "Track accessing works correctly" ~: U.TestCase $ do
+    c <- cdioOpen (Just . dataFile $ "cdda.cue") DriverUnknown
+    cdio <- case c of
+        Nothing -> U.assertFailure "Can't open the image file"
+        Just c' -> return c'
+    
+    t <- trackAt cdio 1000
+    Y.isNothing t @? "Overlarge addresses aren't caught"
+    
+    ts <- mapM (trackAt cdio) $ 301 : [0..9]
+    mapM_ (Just 1 @=?) ts
+    
+    l <- trackAt cdio 302
+    Just DiscLeadout @=? l
diff --git a/test/Test/Libcdio/Upstream/Foreign/Win32.hs b/test/Test/Libcdio/Upstream/Foreign/Win32.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Upstream/Foreign/Win32.hs
@@ -0,0 +1,36 @@
+{-|
+Description:    
+
+Copyright:      (c) 2019-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Test.Libcdio.Upstream.Foreign.Win32 (tests) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (~:) )
+
+import Foreign.Libcdio.Device
+
+import Test.Libcdio.Upstream.Foreign.Common
+
+
+tests :: U.Test
+tests = "Foreign.Libcdio.Test.Win32" ~: U.TestList tests'
+  where tests' | haveDriver DriverWin32 =
+                  [ find DriverWin32 Nothing $ \(c, s) -> checkSource c [s]
+                  , find DriverWin32 (Just Aspi) $ flip checkAccessMode [Aspi] . fst
+                  , find DriverWin32 (Just Ioctl_) checkIoctl
+                  ]
+               | otherwise = []
+
+checkIoctl :: (Cdio, String) -> U.Assertion
+checkIoctl (cdio, _) = do
+    checkArg ScsiTuple cdio []
+    
+    checkAccessMode cdio [Ioctl_]
+    checkMmc cdio $ Just True
diff --git a/test/Test/Libcdio/Upstream/Sound/Common.hs b/test/Test/Libcdio/Upstream/Sound/Common.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Upstream/Sound/Common.hs
@@ -0,0 +1,88 @@
+{-# LANGUAGE CPP #-}
+
+{-|
+Description:    
+
+Copyright:      (c) 2020-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Test.Libcdio.Upstream.Sound.Common
+    ( Foreign.dataDir
+    , checkArg
+    , checkAccessMode
+    , checkSource
+    , checkMmc
+    , testCdio
+    , testCdioMode
+    ) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (~:), (@=?) )
+
+import qualified Data.Maybe as Y
+import qualified Data.Text as T
+
+import qualified System.Directory as D
+
+import Sound.Libcdio
+
+import qualified Test.Libcdio.Upstream.Foreign.Common as Foreign
+
+
+-- | Whether the session argument is one of the allowed values.  An empty list
+-- indicates that the actual value doesn't matter, just that it exists.
+checkArg :: SessionArg -> [T.Text] -> Cdio U.Assertion
+checkArg k ss = do
+    v <- getArg k
+    return $ case v of
+        Nothing -> U.assertFailure $ show k ++ "' isn't assigned"
+        Just v' -> if null ss || elem v' ss
+            then return ()
+            else U.assertFailure $ show k ++ "' has invalid value '" ++ T.unpack v' ++ "'"
+
+checkAccessMode :: [AccessMode] -> Cdio U.Assertion
+checkAccessMode ms = do
+    v <- getAccessMode
+    return $ case v of
+        Nothing -> U.assertFailure "'access-mode' isn't assigned"
+        Just v' -> if null ms || elem v' ms
+            then return ()
+            else U.assertFailure $ "'access-mode' has invalid value '" ++ show v' ++ "'"
+
+checkSource :: [FilePath] -> Cdio U.Assertion
+checkSource = checkArg Source . map T.pack
+
+
+-- | Whether the session advertises MMC support.  A 'Nothing' value indicates
+-- that the actual state doesn't matter, just that it's advertised at all.
+-- 
+-- The C function takes a numeric value translating to the following:
+-- 
+--   * @1@ -> 'Just' 'False'
+--   * @2@ -> 'Just' 'True'
+--   * @3@ -> 'Nothing'
+checkMmc :: Maybe Bool -> Cdio U.Assertion
+checkMmc b = do
+    v <- getArg MmcSupported
+    return $ if Y.isJust v
+        then case b of
+            Just _ -> (T.toLower . T.pack . show <$> b) @=? v
+            Nothing -> return ()
+        else U.assertFailure "Session does not describe MMC status."
+
+
+testCdio :: [FilePath] -> (FilePath -> Cdio [U.Assertion]) -> U.Test
+testCdio = testCdioMode Nothing
+
+testCdioMode :: Maybe AccessMode -> [FilePath] -> (FilePath -> Cdio [U.Assertion]) -> U.Test
+testCdioMode m fs c = U.TestList . flip map fs $ \f -> f ~: U.TestCase $ do
+    o <- D.withCurrentDirectory Foreign.dataDir . open' (Just f) False $ c f
+    either (const $ U.assertFailure "Can't open the image or device") sequence_ o
+  where open' = case m of
+            Just m' -> openMode m'
+            Nothing -> open
diff --git a/test/Test/Libcdio/Upstream/Sound/Image.hs b/test/Test/Libcdio/Upstream/Sound/Image.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Upstream/Sound/Image.hs
@@ -0,0 +1,134 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# OPTIONS_GHC -Wno-unused-local-binds #-}
+
+{-|
+Description:    
+
+Copyright:      (c) 2020-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Test.Libcdio.Upstream.Sound.Image (tests) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (@=?), (~:) )
+
+import qualified Data.Either.Compat as E
+import qualified Data.Maybe as Y
+import qualified Data.Text as T
+
+import qualified System.Directory as D
+
+import Sound.Libcdio
+import Sound.Libcdio.Device
+import Sound.Libcdio.Read.CdText
+
+import Test.Libcdio.Upstream.Sound.Common
+
+import qualified Test.Libcdio.Upstream.Foreign.BinCue as Foreign
+import qualified Test.Libcdio.Upstream.Foreign.CdrDao as Foreign
+import qualified Test.Libcdio.Upstream.Foreign.Nrg as Foreign
+
+
+tests :: U.Test
+tests = "Sound.Libcdio.Test.Image" ~: U.TestList
+    [ parseTests
+    , run
+    ]
+
+
+parseTests :: U.Test
+parseTests = "Distinguish valid and invalid image files" ~: U.TestList
+    [ parseCue
+    , parseToc
+    ]
+
+parseCue :: U.Test
+parseCue = "CUE" ~: U.TestList
+    (map good Foreign.goodCues ++ map bad Foreign.badCues)
+  where good = parseTest "CUE" True
+        bad = parseTest "CUE" False
+
+parseToc :: U.Test
+parseToc = "TOC" ~: U.TestList
+    (map good Foreign.goodToc ++ map bad Foreign.badToc)
+  where good = parseTest "TOC" True
+        bad = parseTest "TOC" False
+
+parseTest :: String -> Bool -> FilePath -> U.Test
+parseTest i y f = msg ~: U.TestCase . D.withCurrentDirectory dataDir $ do
+    o <- open (Just f) False $ return ()
+    y @=? E.isRight o
+  where msg | y = f' ++ "is not recognized as a " ++ i'
+            | otherwise = f' ++ "should not be recognized as a " ++ i'
+        f' = "'" ++ f ++ "' "
+        i' = i ++ " file"
+
+
+goodAll :: [FilePath]
+goodAll = Foreign.goodCues ++ Foreign.goodToc ++ Foreign.goodNrg
+
+goodCdText :: [FilePath]
+goodCdText = ["cdda.cue", "cdtext.toc"] ++ Foreign.goodNrg
+
+
+run :: U.Test
+run = U.TestList
+    [ runAll
+    , testCdText
+    ]
+
+runAll :: U.Test
+runAll = "Expected session behaviour" ~: testCdio goodAll $ \f -> do
+    _ <- setBlocksize 2048
+    
+    m <- checkMmc $ Just False
+    a <- checkAccessMode [Image]
+    
+    let f' = T.unpack . T.replace ".cue" ".bin" $ T.pack f
+    s <- checkSource [f']
+    
+    _ <- setSpeed 5
+    
+    return [m, a, s]
+
+testCdText :: U.Test
+testCdText = "Properly-formed CDTEXT" ~: testCdio goodCdText . const $ do
+    is <- cdText . withAll $ do
+        i <- info Nothing
+        i1 <- info $ Just 1
+        l' <- discId
+        g' <- genre
+        return (i, i1, l', g')
+    let is' = E.fromRight [] is
+    
+    let checkCdText (i, i1, _, _) = map (\f -> f i) discTests ++ map (\f -> f i1) trackTests
+        --checkCdText (i, i1, l', g') = map (\f -> f i) discTests ++ [l l', g g'] ++ map (\f -> f i1) trackTests
+        p i = Just "Richard Stallman" @=? performer i
+        t i = Just "Join us now we have the software" @=? title i
+        s i = Nothing @=? songwriter i
+        c i = Nothing @=? composer i
+        a i = Nothing @=? arranger i
+        m i = Nothing @=? message i
+        o i = Nothing @=? code i
+        l l' = Just "0000010271955" @=? l'
+        g g' = (Nothing, Nothing) @=? g'
+        --discTests = [p, t, s, c, a, m, o]
+        discTests = [p, t]
+        p1 i1 = Just "Richard S" @=?  performer i1
+        t1 i1 = Just "Soft" @=? title i1
+        s1 i1 = Nothing @=? songwriter i1
+        c1 i1 = Nothing @=? composer i1
+        a1 i1 = Nothing @=? arranger i1
+        m1 i1 = Nothing @=? message i1
+        o1 i1 = Just "US-XX1-98-01234" @=? code i1
+        --trackTests = [p1, t1, s1, c1, a1, m1, o1]
+        trackTests = []
+    return $ case length is' of
+        0 -> [U.assertFailure "Can't access the CD Text"]
+        1 -> checkCdText . head $ Y.catMaybes is'
+        _ -> [U.assertFailure "Trailing CD Text languages"]
diff --git a/test/Test/Libcdio/Upstream/Sound/System.hs b/test/Test/Libcdio/Upstream/Sound/System.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Upstream/Sound/System.hs
@@ -0,0 +1,104 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+{-|
+Description:    
+
+Copyright:      (c) 2020-2021 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Test.Libcdio.Upstream.Sound.System (tests) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (@?), (~:) )
+
+import qualified Data.Maybe as Y
+
+import Sound.Libcdio
+import Sound.Libcdio.Device
+import Sound.Libcdio.Read.Data
+
+import Test.Libcdio.Upstream.Sound.Common
+
+
+tests :: U.Test
+tests = "Sound.Libcdio.Test.System" ~: U.TestList
+    [ haveSystemDriver d ts
+    | (d, ts) <-
+        [ (DriverFreeBsd, testsBsd)
+        , (DriverLinux, testsLinux)
+        , (DriverOsX, testsOsx)
+        , (DriverSolaris, testsSolaris)
+        , (DriverWin32, testsWin32)
+        ]
+    ]
+
+testsBsd :: U.Test
+testsBsd = find DriverFreeBsd Nothing $ \p -> do
+    s <- checkSource [p]
+    a <- checkAccessMode [Ioctl_, Cam]
+    m <- checkMmc $ Just False
+    return [s, a, m]
+
+testsLinux :: U.Test
+testsLinux = find DriverLinux (Just MmcReadWrite) $ \p -> do
+    s <- checkSource [p]
+    m <- checkMmc Nothing
+    t <- checkArg ScsiTuple []
+    return [s, m, t]
+
+testsOsx :: U.Test
+testsOsx = find DriverOsX Nothing $ \p -> do
+    s <- checkSource [p]
+    -- can't supply arbitrary access modes
+    --a <- checkAccessMode ["OS X"]
+    
+    d <- discMode
+    let d' = Y.isJust d @? "Error getting disc mode"
+    
+    return [s, d']
+
+testsSolaris :: U.Test
+testsSolaris = find DriverSolaris (Just Scsi) $ \p -> do
+    s <- checkSource [p]
+    a <- checkAccessMode [Scsi]
+    return [s, a]
+
+testsWin32 :: U.Test
+testsWin32 = U.TestList $ map (uncurry $ find DriverWin32)
+    [ ( Nothing, \p -> do
+        s <- checkSource [p]
+        return [s]
+      )
+    , ( Just Aspi, \p -> do
+        s <- checkSource [p]
+        a <- checkAccessMode [Aspi]
+        return [s, a]
+      )
+    , ( Just Ioctl_, \p -> do
+        s <- checkSource [p]
+        t <- checkArg ScsiTuple []
+        a <- checkAccessMode [Ioctl_]
+        m <- checkMmc $ Just True
+        return [s, t, a, m]
+      )
+    ]
+
+
+haveSystemDriver :: DriverId -> U.Test -> U.Test
+haveSystemDriver d ts
+    | elem d drivers = drop 6 (show d) ~: ts
+    | otherwise = U.TestList []
+
+find :: DriverId -> Maybe AccessMode -> (FilePath -> Cdio [U.Assertion]) -> U.Test
+find d m c = U.TestCase $ do
+    ps <- devices d
+    -- Don't actually want to fail on no device, for systems without CD drives
+    sequence_ . unwrap $ testCdioMode m ps c
+  where unwrap (U.TestCase a) = [a]
+        unwrap (U.TestList ts) = concatMap unwrap ts
+        unwrap (U.TestLabel _ t) = unwrap t
diff --git a/test/Test/Libcdio/Upstream/Sound/Track.hs b/test/Test/Libcdio/Upstream/Sound/Track.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Libcdio/Upstream/Sound/Track.hs
@@ -0,0 +1,51 @@
+{-|
+Description:    
+
+Copyright:      (c) 2020 Sam May
+License:        GPL-3.0-or-later
+Maintainer:     ag@eitilt.life
+
+Stability:      experimental
+Portability:    portable
+-}
+module Test.Libcdio.Upstream.Sound.Track (tests) where
+
+
+import qualified Test.HUnit as U
+import Test.HUnit ( (@?), (@=?), (~:) )
+
+import qualified Control.Monad as M
+
+import qualified Data.Maybe as Y
+
+import Sound.Libcdio.Track
+
+import Test.Libcdio.Upstream.Sound.Common
+
+import qualified Test.Libcdio.Upstream.Foreign.Pregap as Foreign
+
+
+tests :: U.Test
+tests = "Sound.Libcdio.Test.Track" ~: U.TestList
+    [ gaps
+    , address
+    ]
+
+gaps :: U.Test
+gaps = "Pregap lengths" ~: U.TestList $ map (\(_,b,c) -> checkGap b c) Foreign.gaps
+  where checkGap f gs = testCdio [f] . const . M.forM gs $ \(t, g) -> do
+            p <- pregap t
+            return $ g @=? p
+
+address :: U.Test
+address = "Sector addressing" ~: testCdio ["cdda.cue"] . const $ do
+    t <- trackAt 1000
+    let t' = Y.isNothing t @? "Overlarge addresses aren't caught"
+    
+    ts <- mapM trackAt $ 301 : [0..9]
+    let ts' = mapM_ (Just 1 @=?) ts
+    
+    l <- trackAt 302
+    let l' = Just DiscLeadout @=? l
+    
+    return [t', ts', l']
diff --git a/test/datafiles/unit/CP932.txt b/test/datafiles/unit/CP932.txt
new file mode 100644
--- /dev/null
+++ b/test/datafiles/unit/CP932.txt
@@ -0,0 +1,7998 @@
+#
+#    Name:     cp932 to Unicode table
+#    Unicode version: 2.0
+#    Table version: 2.01
+#    Table format:  Format A
+#    Date:          04/15/98
+#
+#    Contact:       Shawn.Steele@microsoft.com
+#
+#    General notes: none
+#
+#    Format: Three tab-separated columns
+#        Column #1 is the cp932 code (in hex)
+#        Column #2 is the Unicode (in hex as 0xXXXX)
+#        Column #3 is the Unicode name (follows a comment sign, '#')
+#
+#    The entries are in cp932 order
+#
+0x00	0x0000	#NULL
+0x01	0x0001	#START OF HEADING
+0x02	0x0002	#START OF TEXT
+0x03	0x0003	#END OF TEXT
+0x04	0x0004	#END OF TRANSMISSION
+0x05	0x0005	#ENQUIRY
+0x06	0x0006	#ACKNOWLEDGE
+0x07	0x0007	#BELL
+0x08	0x0008	#BACKSPACE
+0x09	0x0009	#HORIZONTAL TABULATION
+0x0A	0x000A	#LINE FEED
+0x0B	0x000B	#VERTICAL TABULATION
+0x0C	0x000C	#FORM FEED
+0x0D	0x000D	#CARRIAGE RETURN
+0x0E	0x000E	#SHIFT OUT
+0x0F	0x000F	#SHIFT IN
+0x10	0x0010	#DATA LINK ESCAPE
+0x11	0x0011	#DEVICE CONTROL ONE
+0x12	0x0012	#DEVICE CONTROL TWO
+0x13	0x0013	#DEVICE CONTROL THREE
+0x14	0x0014	#DEVICE CONTROL FOUR
+0x15	0x0015	#NEGATIVE ACKNOWLEDGE
+0x16	0x0016	#SYNCHRONOUS IDLE
+0x17	0x0017	#END OF TRANSMISSION BLOCK
+0x18	0x0018	#CANCEL
+0x19	0x0019	#END OF MEDIUM
+0x1A	0x001A	#SUBSTITUTE
+0x1B	0x001B	#ESCAPE
+0x1C	0x001C	#FILE SEPARATOR
+0x1D	0x001D	#GROUP SEPARATOR
+0x1E	0x001E	#RECORD SEPARATOR
+0x1F	0x001F	#UNIT SEPARATOR
+0x20	0x0020	#SPACE
+0x21	0x0021	#EXCLAMATION MARK
+0x22	0x0022	#QUOTATION MARK
+0x23	0x0023	#NUMBER SIGN
+0x24	0x0024	#DOLLAR SIGN
+0x25	0x0025	#PERCENT SIGN
+0x26	0x0026	#AMPERSAND
+0x27	0x0027	#APOSTROPHE
+0x28	0x0028	#LEFT PARENTHESIS
+0x29	0x0029	#RIGHT PARENTHESIS
+0x2A	0x002A	#ASTERISK
+0x2B	0x002B	#PLUS SIGN
+0x2C	0x002C	#COMMA
+0x2D	0x002D	#HYPHEN-MINUS
+0x2E	0x002E	#FULL STOP
+0x2F	0x002F	#SOLIDUS
+0x30	0x0030	#DIGIT ZERO
+0x31	0x0031	#DIGIT ONE
+0x32	0x0032	#DIGIT TWO
+0x33	0x0033	#DIGIT THREE
+0x34	0x0034	#DIGIT FOUR
+0x35	0x0035	#DIGIT FIVE
+0x36	0x0036	#DIGIT SIX
+0x37	0x0037	#DIGIT SEVEN
+0x38	0x0038	#DIGIT EIGHT
+0x39	0x0039	#DIGIT NINE
+0x3A	0x003A	#COLON
+0x3B	0x003B	#SEMICOLON
+0x3C	0x003C	#LESS-THAN SIGN
+0x3D	0x003D	#EQUALS SIGN
+0x3E	0x003E	#GREATER-THAN SIGN
+0x3F	0x003F	#QUESTION MARK
+0x40	0x0040	#COMMERCIAL AT
+0x41	0x0041	#LATIN CAPITAL LETTER A
+0x42	0x0042	#LATIN CAPITAL LETTER B
+0x43	0x0043	#LATIN CAPITAL LETTER C
+0x44	0x0044	#LATIN CAPITAL LETTER D
+0x45	0x0045	#LATIN CAPITAL LETTER E
+0x46	0x0046	#LATIN CAPITAL LETTER F
+0x47	0x0047	#LATIN CAPITAL LETTER G
+0x48	0x0048	#LATIN CAPITAL LETTER H
+0x49	0x0049	#LATIN CAPITAL LETTER I
+0x4A	0x004A	#LATIN CAPITAL LETTER J
+0x4B	0x004B	#LATIN CAPITAL LETTER K
+0x4C	0x004C	#LATIN CAPITAL LETTER L
+0x4D	0x004D	#LATIN CAPITAL LETTER M
+0x4E	0x004E	#LATIN CAPITAL LETTER N
+0x4F	0x004F	#LATIN CAPITAL LETTER O
+0x50	0x0050	#LATIN CAPITAL LETTER P
+0x51	0x0051	#LATIN CAPITAL LETTER Q
+0x52	0x0052	#LATIN CAPITAL LETTER R
+0x53	0x0053	#LATIN CAPITAL LETTER S
+0x54	0x0054	#LATIN CAPITAL LETTER T
+0x55	0x0055	#LATIN CAPITAL LETTER U
+0x56	0x0056	#LATIN CAPITAL LETTER V
+0x57	0x0057	#LATIN CAPITAL LETTER W
+0x58	0x0058	#LATIN CAPITAL LETTER X
+0x59	0x0059	#LATIN CAPITAL LETTER Y
+0x5A	0x005A	#LATIN CAPITAL LETTER Z
+0x5B	0x005B	#LEFT SQUARE BRACKET
+0x5C	0x005C	#REVERSE SOLIDUS
+0x5D	0x005D	#RIGHT SQUARE BRACKET
+0x5E	0x005E	#CIRCUMFLEX ACCENT
+0x5F	0x005F	#LOW LINE
+0x60	0x0060	#GRAVE ACCENT
+0x61	0x0061	#LATIN SMALL LETTER A
+0x62	0x0062	#LATIN SMALL LETTER B
+0x63	0x0063	#LATIN SMALL LETTER C
+0x64	0x0064	#LATIN SMALL LETTER D
+0x65	0x0065	#LATIN SMALL LETTER E
+0x66	0x0066	#LATIN SMALL LETTER F
+0x67	0x0067	#LATIN SMALL LETTER G
+0x68	0x0068	#LATIN SMALL LETTER H
+0x69	0x0069	#LATIN SMALL LETTER I
+0x6A	0x006A	#LATIN SMALL LETTER J
+0x6B	0x006B	#LATIN SMALL LETTER K
+0x6C	0x006C	#LATIN SMALL LETTER L
+0x6D	0x006D	#LATIN SMALL LETTER M
+0x6E	0x006E	#LATIN SMALL LETTER N
+0x6F	0x006F	#LATIN SMALL LETTER O
+0x70	0x0070	#LATIN SMALL LETTER P
+0x71	0x0071	#LATIN SMALL LETTER Q
+0x72	0x0072	#LATIN SMALL LETTER R
+0x73	0x0073	#LATIN SMALL LETTER S
+0x74	0x0074	#LATIN SMALL LETTER T
+0x75	0x0075	#LATIN SMALL LETTER U
+0x76	0x0076	#LATIN SMALL LETTER V
+0x77	0x0077	#LATIN SMALL LETTER W
+0x78	0x0078	#LATIN SMALL LETTER X
+0x79	0x0079	#LATIN SMALL LETTER Y
+0x7A	0x007A	#LATIN SMALL LETTER Z
+0x7B	0x007B	#LEFT CURLY BRACKET
+0x7C	0x007C	#VERTICAL LINE
+0x7D	0x007D	#RIGHT CURLY BRACKET
+0x7E	0x007E	#TILDE
+0x7F	0x007F	#DELETE
+0x80	      	#UNDEFINED
+0x81	      	#DBCS LEAD BYTE
+0x82	      	#DBCS LEAD BYTE
+0x83	      	#DBCS LEAD BYTE
+0x84	      	#DBCS LEAD BYTE
+0x85	      	#DBCS LEAD BYTE
+0x86	      	#DBCS LEAD BYTE
+0x87	      	#DBCS LEAD BYTE
+0x88	      	#DBCS LEAD BYTE
+0x89	      	#DBCS LEAD BYTE
+0x8A	      	#DBCS LEAD BYTE
+0x8B	      	#DBCS LEAD BYTE
+0x8C	      	#DBCS LEAD BYTE
+0x8D	      	#DBCS LEAD BYTE
+0x8E	      	#DBCS LEAD BYTE
+0x8F	      	#DBCS LEAD BYTE
+0x90	      	#DBCS LEAD BYTE
+0x91	      	#DBCS LEAD BYTE
+0x92	      	#DBCS LEAD BYTE
+0x93	      	#DBCS LEAD BYTE
+0x94	      	#DBCS LEAD BYTE
+0x95	      	#DBCS LEAD BYTE
+0x96	      	#DBCS LEAD BYTE
+0x97	      	#DBCS LEAD BYTE
+0x98	      	#DBCS LEAD BYTE
+0x99	      	#DBCS LEAD BYTE
+0x9A	      	#DBCS LEAD BYTE
+0x9B	      	#DBCS LEAD BYTE
+0x9C	      	#DBCS LEAD BYTE
+0x9D	      	#DBCS LEAD BYTE
+0x9E	      	#DBCS LEAD BYTE
+0x9F	      	#DBCS LEAD BYTE
+0xA0	      	#UNDEFINED
+0xA1	0xFF61	#HALFWIDTH IDEOGRAPHIC FULL STOP
+0xA2	0xFF62	#HALFWIDTH LEFT CORNER BRACKET
+0xA3	0xFF63	#HALFWIDTH RIGHT CORNER BRACKET
+0xA4	0xFF64	#HALFWIDTH IDEOGRAPHIC COMMA
+0xA5	0xFF65	#HALFWIDTH KATAKANA MIDDLE DOT
+0xA6	0xFF66	#HALFWIDTH KATAKANA LETTER WO
+0xA7	0xFF67	#HALFWIDTH KATAKANA LETTER SMALL A
+0xA8	0xFF68	#HALFWIDTH KATAKANA LETTER SMALL I
+0xA9	0xFF69	#HALFWIDTH KATAKANA LETTER SMALL U
+0xAA	0xFF6A	#HALFWIDTH KATAKANA LETTER SMALL E
+0xAB	0xFF6B	#HALFWIDTH KATAKANA LETTER SMALL O
+0xAC	0xFF6C	#HALFWIDTH KATAKANA LETTER SMALL YA
+0xAD	0xFF6D	#HALFWIDTH KATAKANA LETTER SMALL YU
+0xAE	0xFF6E	#HALFWIDTH KATAKANA LETTER SMALL YO
+0xAF	0xFF6F	#HALFWIDTH KATAKANA LETTER SMALL TU
+0xB0	0xFF70	#HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK
+0xB1	0xFF71	#HALFWIDTH KATAKANA LETTER A
+0xB2	0xFF72	#HALFWIDTH KATAKANA LETTER I
+0xB3	0xFF73	#HALFWIDTH KATAKANA LETTER U
+0xB4	0xFF74	#HALFWIDTH KATAKANA LETTER E
+0xB5	0xFF75	#HALFWIDTH KATAKANA LETTER O
+0xB6	0xFF76	#HALFWIDTH KATAKANA LETTER KA
+0xB7	0xFF77	#HALFWIDTH KATAKANA LETTER KI
+0xB8	0xFF78	#HALFWIDTH KATAKANA LETTER KU
+0xB9	0xFF79	#HALFWIDTH KATAKANA LETTER KE
+0xBA	0xFF7A	#HALFWIDTH KATAKANA LETTER KO
+0xBB	0xFF7B	#HALFWIDTH KATAKANA LETTER SA
+0xBC	0xFF7C	#HALFWIDTH KATAKANA LETTER SI
+0xBD	0xFF7D	#HALFWIDTH KATAKANA LETTER SU
+0xBE	0xFF7E	#HALFWIDTH KATAKANA LETTER SE
+0xBF	0xFF7F	#HALFWIDTH KATAKANA LETTER SO
+0xC0	0xFF80	#HALFWIDTH KATAKANA LETTER TA
+0xC1	0xFF81	#HALFWIDTH KATAKANA LETTER TI
+0xC2	0xFF82	#HALFWIDTH KATAKANA LETTER TU
+0xC3	0xFF83	#HALFWIDTH KATAKANA LETTER TE
+0xC4	0xFF84	#HALFWIDTH KATAKANA LETTER TO
+0xC5	0xFF85	#HALFWIDTH KATAKANA LETTER NA
+0xC6	0xFF86	#HALFWIDTH KATAKANA LETTER NI
+0xC7	0xFF87	#HALFWIDTH KATAKANA LETTER NU
+0xC8	0xFF88	#HALFWIDTH KATAKANA LETTER NE
+0xC9	0xFF89	#HALFWIDTH KATAKANA LETTER NO
+0xCA	0xFF8A	#HALFWIDTH KATAKANA LETTER HA
+0xCB	0xFF8B	#HALFWIDTH KATAKANA LETTER HI
+0xCC	0xFF8C	#HALFWIDTH KATAKANA LETTER HU
+0xCD	0xFF8D	#HALFWIDTH KATAKANA LETTER HE
+0xCE	0xFF8E	#HALFWIDTH KATAKANA LETTER HO
+0xCF	0xFF8F	#HALFWIDTH KATAKANA LETTER MA
+0xD0	0xFF90	#HALFWIDTH KATAKANA LETTER MI
+0xD1	0xFF91	#HALFWIDTH KATAKANA LETTER MU
+0xD2	0xFF92	#HALFWIDTH KATAKANA LETTER ME
+0xD3	0xFF93	#HALFWIDTH KATAKANA LETTER MO
+0xD4	0xFF94	#HALFWIDTH KATAKANA LETTER YA
+0xD5	0xFF95	#HALFWIDTH KATAKANA LETTER YU
+0xD6	0xFF96	#HALFWIDTH KATAKANA LETTER YO
+0xD7	0xFF97	#HALFWIDTH KATAKANA LETTER RA
+0xD8	0xFF98	#HALFWIDTH KATAKANA LETTER RI
+0xD9	0xFF99	#HALFWIDTH KATAKANA LETTER RU
+0xDA	0xFF9A	#HALFWIDTH KATAKANA LETTER RE
+0xDB	0xFF9B	#HALFWIDTH KATAKANA LETTER RO
+0xDC	0xFF9C	#HALFWIDTH KATAKANA LETTER WA
+0xDD	0xFF9D	#HALFWIDTH KATAKANA LETTER N
+0xDE	0xFF9E	#HALFWIDTH KATAKANA VOICED SOUND MARK
+0xDF	0xFF9F	#HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
+0xE0	      	#DBCS LEAD BYTE
+0xE1	      	#DBCS LEAD BYTE
+0xE2	      	#DBCS LEAD BYTE
+0xE3	      	#DBCS LEAD BYTE
+0xE4	      	#DBCS LEAD BYTE
+0xE5	      	#DBCS LEAD BYTE
+0xE6	      	#DBCS LEAD BYTE
+0xE7	      	#DBCS LEAD BYTE
+0xE8	      	#DBCS LEAD BYTE
+0xE9	      	#DBCS LEAD BYTE
+0xEA	      	#DBCS LEAD BYTE
+0xEB	      	#DBCS LEAD BYTE
+0xEC	      	#DBCS LEAD BYTE
+0xED	      	#DBCS LEAD BYTE
+0xEE	      	#DBCS LEAD BYTE
+0xEF	      	#DBCS LEAD BYTE
+0xF0	      	#DBCS LEAD BYTE
+0xF1	      	#DBCS LEAD BYTE
+0xF2	      	#DBCS LEAD BYTE
+0xF3	      	#DBCS LEAD BYTE
+0xF4	      	#DBCS LEAD BYTE
+0xF5	      	#DBCS LEAD BYTE
+0xF6	      	#DBCS LEAD BYTE
+0xF7	      	#DBCS LEAD BYTE
+0xF8	      	#DBCS LEAD BYTE
+0xF9	      	#DBCS LEAD BYTE
+0xFA	      	#DBCS LEAD BYTE
+0xFB	      	#DBCS LEAD BYTE
+0xFC	      	#DBCS LEAD BYTE
+0xFD	      	#UNDEFINED
+0xFE	      	#UNDEFINED
+0xFF	      	#UNDEFINED
+0x8140	0x3000	#IDEOGRAPHIC SPACE
+0x8141	0x3001	#IDEOGRAPHIC COMMA
+0x8142	0x3002	#IDEOGRAPHIC FULL STOP
+0x8143	0xFF0C	#FULLWIDTH COMMA
+0x8144	0xFF0E	#FULLWIDTH FULL STOP
+0x8145	0x30FB	#KATAKANA MIDDLE DOT
+0x8146	0xFF1A	#FULLWIDTH COLON
+0x8147	0xFF1B	#FULLWIDTH SEMICOLON
+0x8148	0xFF1F	#FULLWIDTH QUESTION MARK
+0x8149	0xFF01	#FULLWIDTH EXCLAMATION MARK
+0x814A	0x309B	#KATAKANA-HIRAGANA VOICED SOUND MARK
+0x814B	0x309C	#KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+0x814C	0x00B4	#ACUTE ACCENT
+0x814D	0xFF40	#FULLWIDTH GRAVE ACCENT
+0x814E	0x00A8	#DIAERESIS
+0x814F	0xFF3E	#FULLWIDTH CIRCUMFLEX ACCENT
+0x8150	0xFFE3	#FULLWIDTH MACRON
+0x8151	0xFF3F	#FULLWIDTH LOW LINE
+0x8152	0x30FD	#KATAKANA ITERATION MARK
+0x8153	0x30FE	#KATAKANA VOICED ITERATION MARK
+0x8154	0x309D	#HIRAGANA ITERATION MARK
+0x8155	0x309E	#HIRAGANA VOICED ITERATION MARK
+0x8156	0x3003	#DITTO MARK
+0x8157	0x4EDD	#CJK UNIFIED IDEOGRAPH
+0x8158	0x3005	#IDEOGRAPHIC ITERATION MARK
+0x8159	0x3006	#IDEOGRAPHIC CLOSING MARK
+0x815A	0x3007	#IDEOGRAPHIC NUMBER ZERO
+0x815B	0x30FC	#KATAKANA-HIRAGANA PROLONGED SOUND MARK
+0x815C	0x2015	#HORIZONTAL BAR
+0x815D	0x2010	#HYPHEN
+0x815E	0xFF0F	#FULLWIDTH SOLIDUS
+0x815F	0xFF3C	#FULLWIDTH REVERSE SOLIDUS
+0x8160	0xFF5E	#FULLWIDTH TILDE
+0x8161	0x2225	#PARALLEL TO
+0x8162	0xFF5C	#FULLWIDTH VERTICAL LINE
+0x8163	0x2026	#HORIZONTAL ELLIPSIS
+0x8164	0x2025	#TWO DOT LEADER
+0x8165	0x2018	#LEFT SINGLE QUOTATION MARK
+0x8166	0x2019	#RIGHT SINGLE QUOTATION MARK
+0x8167	0x201C	#LEFT DOUBLE QUOTATION MARK
+0x8168	0x201D	#RIGHT DOUBLE QUOTATION MARK
+0x8169	0xFF08	#FULLWIDTH LEFT PARENTHESIS
+0x816A	0xFF09	#FULLWIDTH RIGHT PARENTHESIS
+0x816B	0x3014	#LEFT TORTOISE SHELL BRACKET
+0x816C	0x3015	#RIGHT TORTOISE SHELL BRACKET
+0x816D	0xFF3B	#FULLWIDTH LEFT SQUARE BRACKET
+0x816E	0xFF3D	#FULLWIDTH RIGHT SQUARE BRACKET
+0x816F	0xFF5B	#FULLWIDTH LEFT CURLY BRACKET
+0x8170	0xFF5D	#FULLWIDTH RIGHT CURLY BRACKET
+0x8171	0x3008	#LEFT ANGLE BRACKET
+0x8172	0x3009	#RIGHT ANGLE BRACKET
+0x8173	0x300A	#LEFT DOUBLE ANGLE BRACKET
+0x8174	0x300B	#RIGHT DOUBLE ANGLE BRACKET
+0x8175	0x300C	#LEFT CORNER BRACKET
+0x8176	0x300D	#RIGHT CORNER BRACKET
+0x8177	0x300E	#LEFT WHITE CORNER BRACKET
+0x8178	0x300F	#RIGHT WHITE CORNER BRACKET
+0x8179	0x3010	#LEFT BLACK LENTICULAR BRACKET
+0x817A	0x3011	#RIGHT BLACK LENTICULAR BRACKET
+0x817B	0xFF0B	#FULLWIDTH PLUS SIGN
+0x817C	0xFF0D	#FULLWIDTH HYPHEN-MINUS
+0x817D	0x00B1	#PLUS-MINUS SIGN
+0x817E	0x00D7	#MULTIPLICATION SIGN
+0x8180	0x00F7	#DIVISION SIGN
+0x8181	0xFF1D	#FULLWIDTH EQUALS SIGN
+0x8182	0x2260	#NOT EQUAL TO
+0x8183	0xFF1C	#FULLWIDTH LESS-THAN SIGN
+0x8184	0xFF1E	#FULLWIDTH GREATER-THAN SIGN
+0x8185	0x2266	#LESS-THAN OVER EQUAL TO
+0x8186	0x2267	#GREATER-THAN OVER EQUAL TO
+0x8187	0x221E	#INFINITY
+0x8188	0x2234	#THEREFORE
+0x8189	0x2642	#MALE SIGN
+0x818A	0x2640	#FEMALE SIGN
+0x818B	0x00B0	#DEGREE SIGN
+0x818C	0x2032	#PRIME
+0x818D	0x2033	#DOUBLE PRIME
+0x818E	0x2103	#DEGREE CELSIUS
+0x818F	0xFFE5	#FULLWIDTH YEN SIGN
+0x8190	0xFF04	#FULLWIDTH DOLLAR SIGN
+0x8191	0xFFE0	#FULLWIDTH CENT SIGN
+0x8192	0xFFE1	#FULLWIDTH POUND SIGN
+0x8193	0xFF05	#FULLWIDTH PERCENT SIGN
+0x8194	0xFF03	#FULLWIDTH NUMBER SIGN
+0x8195	0xFF06	#FULLWIDTH AMPERSAND
+0x8196	0xFF0A	#FULLWIDTH ASTERISK
+0x8197	0xFF20	#FULLWIDTH COMMERCIAL AT
+0x8198	0x00A7	#SECTION SIGN
+0x8199	0x2606	#WHITE STAR
+0x819A	0x2605	#BLACK STAR
+0x819B	0x25CB	#WHITE CIRCLE
+0x819C	0x25CF	#BLACK CIRCLE
+0x819D	0x25CE	#BULLSEYE
+0x819E	0x25C7	#WHITE DIAMOND
+0x819F	0x25C6	#BLACK DIAMOND
+0x81A0	0x25A1	#WHITE SQUARE
+0x81A1	0x25A0	#BLACK SQUARE
+0x81A2	0x25B3	#WHITE UP-POINTING TRIANGLE
+0x81A3	0x25B2	#BLACK UP-POINTING TRIANGLE
+0x81A4	0x25BD	#WHITE DOWN-POINTING TRIANGLE
+0x81A5	0x25BC	#BLACK DOWN-POINTING TRIANGLE
+0x81A6	0x203B	#REFERENCE MARK
+0x81A7	0x3012	#POSTAL MARK
+0x81A8	0x2192	#RIGHTWARDS ARROW
+0x81A9	0x2190	#LEFTWARDS ARROW
+0x81AA	0x2191	#UPWARDS ARROW
+0x81AB	0x2193	#DOWNWARDS ARROW
+0x81AC	0x3013	#GETA MARK
+0x81B8	0x2208	#ELEMENT OF
+0x81B9	0x220B	#CONTAINS AS MEMBER
+0x81BA	0x2286	#SUBSET OF OR EQUAL TO
+0x81BB	0x2287	#SUPERSET OF OR EQUAL TO
+0x81BC	0x2282	#SUBSET OF
+0x81BD	0x2283	#SUPERSET OF
+0x81BE	0x222A	#UNION
+0x81BF	0x2229	#INTERSECTION
+0x81C8	0x2227	#LOGICAL AND
+0x81C9	0x2228	#LOGICAL OR
+0x81CA	0xFFE2	#FULLWIDTH NOT SIGN
+0x81CB	0x21D2	#RIGHTWARDS DOUBLE ARROW
+0x81CC	0x21D4	#LEFT RIGHT DOUBLE ARROW
+0x81CD	0x2200	#FOR ALL
+0x81CE	0x2203	#THERE EXISTS
+0x81DA	0x2220	#ANGLE
+0x81DB	0x22A5	#UP TACK
+0x81DC	0x2312	#ARC
+0x81DD	0x2202	#PARTIAL DIFFERENTIAL
+0x81DE	0x2207	#NABLA
+0x81DF	0x2261	#IDENTICAL TO
+0x81E0	0x2252	#APPROXIMATELY EQUAL TO OR THE IMAGE OF
+0x81E1	0x226A	#MUCH LESS-THAN
+0x81E2	0x226B	#MUCH GREATER-THAN
+0x81E3	0x221A	#SQUARE ROOT
+0x81E4	0x223D	#REVERSED TILDE
+0x81E5	0x221D	#PROPORTIONAL TO
+0x81E6	0x2235	#BECAUSE
+0x81E7	0x222B	#INTEGRAL
+0x81E8	0x222C	#DOUBLE INTEGRAL
+0x81F0	0x212B	#ANGSTROM SIGN
+0x81F1	0x2030	#PER MILLE SIGN
+0x81F2	0x266F	#MUSIC SHARP SIGN
+0x81F3	0x266D	#MUSIC FLAT SIGN
+0x81F4	0x266A	#EIGHTH NOTE
+0x81F5	0x2020	#DAGGER
+0x81F6	0x2021	#DOUBLE DAGGER
+0x81F7	0x00B6	#PILCROW SIGN
+0x81FC	0x25EF	#LARGE CIRCLE
+0x824F	0xFF10	#FULLWIDTH DIGIT ZERO
+0x8250	0xFF11	#FULLWIDTH DIGIT ONE
+0x8251	0xFF12	#FULLWIDTH DIGIT TWO
+0x8252	0xFF13	#FULLWIDTH DIGIT THREE
+0x8253	0xFF14	#FULLWIDTH DIGIT FOUR
+0x8254	0xFF15	#FULLWIDTH DIGIT FIVE
+0x8255	0xFF16	#FULLWIDTH DIGIT SIX
+0x8256	0xFF17	#FULLWIDTH DIGIT SEVEN
+0x8257	0xFF18	#FULLWIDTH DIGIT EIGHT
+0x8258	0xFF19	#FULLWIDTH DIGIT NINE
+0x8260	0xFF21	#FULLWIDTH LATIN CAPITAL LETTER A
+0x8261	0xFF22	#FULLWIDTH LATIN CAPITAL LETTER B
+0x8262	0xFF23	#FULLWIDTH LATIN CAPITAL LETTER C
+0x8263	0xFF24	#FULLWIDTH LATIN CAPITAL LETTER D
+0x8264	0xFF25	#FULLWIDTH LATIN CAPITAL LETTER E
+0x8265	0xFF26	#FULLWIDTH LATIN CAPITAL LETTER F
+0x8266	0xFF27	#FULLWIDTH LATIN CAPITAL LETTER G
+0x8267	0xFF28	#FULLWIDTH LATIN CAPITAL LETTER H
+0x8268	0xFF29	#FULLWIDTH LATIN CAPITAL LETTER I
+0x8269	0xFF2A	#FULLWIDTH LATIN CAPITAL LETTER J
+0x826A	0xFF2B	#FULLWIDTH LATIN CAPITAL LETTER K
+0x826B	0xFF2C	#FULLWIDTH LATIN CAPITAL LETTER L
+0x826C	0xFF2D	#FULLWIDTH LATIN CAPITAL LETTER M
+0x826D	0xFF2E	#FULLWIDTH LATIN CAPITAL LETTER N
+0x826E	0xFF2F	#FULLWIDTH LATIN CAPITAL LETTER O
+0x826F	0xFF30	#FULLWIDTH LATIN CAPITAL LETTER P
+0x8270	0xFF31	#FULLWIDTH LATIN CAPITAL LETTER Q
+0x8271	0xFF32	#FULLWIDTH LATIN CAPITAL LETTER R
+0x8272	0xFF33	#FULLWIDTH LATIN CAPITAL LETTER S
+0x8273	0xFF34	#FULLWIDTH LATIN CAPITAL LETTER T
+0x8274	0xFF35	#FULLWIDTH LATIN CAPITAL LETTER U
+0x8275	0xFF36	#FULLWIDTH LATIN CAPITAL LETTER V
+0x8276	0xFF37	#FULLWIDTH LATIN CAPITAL LETTER W
+0x8277	0xFF38	#FULLWIDTH LATIN CAPITAL LETTER X
+0x8278	0xFF39	#FULLWIDTH LATIN CAPITAL LETTER Y
+0x8279	0xFF3A	#FULLWIDTH LATIN CAPITAL LETTER Z
+0x8281	0xFF41	#FULLWIDTH LATIN SMALL LETTER A
+0x8282	0xFF42	#FULLWIDTH LATIN SMALL LETTER B
+0x8283	0xFF43	#FULLWIDTH LATIN SMALL LETTER C
+0x8284	0xFF44	#FULLWIDTH LATIN SMALL LETTER D
+0x8285	0xFF45	#FULLWIDTH LATIN SMALL LETTER E
+0x8286	0xFF46	#FULLWIDTH LATIN SMALL LETTER F
+0x8287	0xFF47	#FULLWIDTH LATIN SMALL LETTER G
+0x8288	0xFF48	#FULLWIDTH LATIN SMALL LETTER H
+0x8289	0xFF49	#FULLWIDTH LATIN SMALL LETTER I
+0x828A	0xFF4A	#FULLWIDTH LATIN SMALL LETTER J
+0x828B	0xFF4B	#FULLWIDTH LATIN SMALL LETTER K
+0x828C	0xFF4C	#FULLWIDTH LATIN SMALL LETTER L
+0x828D	0xFF4D	#FULLWIDTH LATIN SMALL LETTER M
+0x828E	0xFF4E	#FULLWIDTH LATIN SMALL LETTER N
+0x828F	0xFF4F	#FULLWIDTH LATIN SMALL LETTER O
+0x8290	0xFF50	#FULLWIDTH LATIN SMALL LETTER P
+0x8291	0xFF51	#FULLWIDTH LATIN SMALL LETTER Q
+0x8292	0xFF52	#FULLWIDTH LATIN SMALL LETTER R
+0x8293	0xFF53	#FULLWIDTH LATIN SMALL LETTER S
+0x8294	0xFF54	#FULLWIDTH LATIN SMALL LETTER T
+0x8295	0xFF55	#FULLWIDTH LATIN SMALL LETTER U
+0x8296	0xFF56	#FULLWIDTH LATIN SMALL LETTER V
+0x8297	0xFF57	#FULLWIDTH LATIN SMALL LETTER W
+0x8298	0xFF58	#FULLWIDTH LATIN SMALL LETTER X
+0x8299	0xFF59	#FULLWIDTH LATIN SMALL LETTER Y
+0x829A	0xFF5A	#FULLWIDTH LATIN SMALL LETTER Z
+0x829F	0x3041	#HIRAGANA LETTER SMALL A
+0x82A0	0x3042	#HIRAGANA LETTER A
+0x82A1	0x3043	#HIRAGANA LETTER SMALL I
+0x82A2	0x3044	#HIRAGANA LETTER I
+0x82A3	0x3045	#HIRAGANA LETTER SMALL U
+0x82A4	0x3046	#HIRAGANA LETTER U
+0x82A5	0x3047	#HIRAGANA LETTER SMALL E
+0x82A6	0x3048	#HIRAGANA LETTER E
+0x82A7	0x3049	#HIRAGANA LETTER SMALL O
+0x82A8	0x304A	#HIRAGANA LETTER O
+0x82A9	0x304B	#HIRAGANA LETTER KA
+0x82AA	0x304C	#HIRAGANA LETTER GA
+0x82AB	0x304D	#HIRAGANA LETTER KI
+0x82AC	0x304E	#HIRAGANA LETTER GI
+0x82AD	0x304F	#HIRAGANA LETTER KU
+0x82AE	0x3050	#HIRAGANA LETTER GU
+0x82AF	0x3051	#HIRAGANA LETTER KE
+0x82B0	0x3052	#HIRAGANA LETTER GE
+0x82B1	0x3053	#HIRAGANA LETTER KO
+0x82B2	0x3054	#HIRAGANA LETTER GO
+0x82B3	0x3055	#HIRAGANA LETTER SA
+0x82B4	0x3056	#HIRAGANA LETTER ZA
+0x82B5	0x3057	#HIRAGANA LETTER SI
+0x82B6	0x3058	#HIRAGANA LETTER ZI
+0x82B7	0x3059	#HIRAGANA LETTER SU
+0x82B8	0x305A	#HIRAGANA LETTER ZU
+0x82B9	0x305B	#HIRAGANA LETTER SE
+0x82BA	0x305C	#HIRAGANA LETTER ZE
+0x82BB	0x305D	#HIRAGANA LETTER SO
+0x82BC	0x305E	#HIRAGANA LETTER ZO
+0x82BD	0x305F	#HIRAGANA LETTER TA
+0x82BE	0x3060	#HIRAGANA LETTER DA
+0x82BF	0x3061	#HIRAGANA LETTER TI
+0x82C0	0x3062	#HIRAGANA LETTER DI
+0x82C1	0x3063	#HIRAGANA LETTER SMALL TU
+0x82C2	0x3064	#HIRAGANA LETTER TU
+0x82C3	0x3065	#HIRAGANA LETTER DU
+0x82C4	0x3066	#HIRAGANA LETTER TE
+0x82C5	0x3067	#HIRAGANA LETTER DE
+0x82C6	0x3068	#HIRAGANA LETTER TO
+0x82C7	0x3069	#HIRAGANA LETTER DO
+0x82C8	0x306A	#HIRAGANA LETTER NA
+0x82C9	0x306B	#HIRAGANA LETTER NI
+0x82CA	0x306C	#HIRAGANA LETTER NU
+0x82CB	0x306D	#HIRAGANA LETTER NE
+0x82CC	0x306E	#HIRAGANA LETTER NO
+0x82CD	0x306F	#HIRAGANA LETTER HA
+0x82CE	0x3070	#HIRAGANA LETTER BA
+0x82CF	0x3071	#HIRAGANA LETTER PA
+0x82D0	0x3072	#HIRAGANA LETTER HI
+0x82D1	0x3073	#HIRAGANA LETTER BI
+0x82D2	0x3074	#HIRAGANA LETTER PI
+0x82D3	0x3075	#HIRAGANA LETTER HU
+0x82D4	0x3076	#HIRAGANA LETTER BU
+0x82D5	0x3077	#HIRAGANA LETTER PU
+0x82D6	0x3078	#HIRAGANA LETTER HE
+0x82D7	0x3079	#HIRAGANA LETTER BE
+0x82D8	0x307A	#HIRAGANA LETTER PE
+0x82D9	0x307B	#HIRAGANA LETTER HO
+0x82DA	0x307C	#HIRAGANA LETTER BO
+0x82DB	0x307D	#HIRAGANA LETTER PO
+0x82DC	0x307E	#HIRAGANA LETTER MA
+0x82DD	0x307F	#HIRAGANA LETTER MI
+0x82DE	0x3080	#HIRAGANA LETTER MU
+0x82DF	0x3081	#HIRAGANA LETTER ME
+0x82E0	0x3082	#HIRAGANA LETTER MO
+0x82E1	0x3083	#HIRAGANA LETTER SMALL YA
+0x82E2	0x3084	#HIRAGANA LETTER YA
+0x82E3	0x3085	#HIRAGANA LETTER SMALL YU
+0x82E4	0x3086	#HIRAGANA LETTER YU
+0x82E5	0x3087	#HIRAGANA LETTER SMALL YO
+0x82E6	0x3088	#HIRAGANA LETTER YO
+0x82E7	0x3089	#HIRAGANA LETTER RA
+0x82E8	0x308A	#HIRAGANA LETTER RI
+0x82E9	0x308B	#HIRAGANA LETTER RU
+0x82EA	0x308C	#HIRAGANA LETTER RE
+0x82EB	0x308D	#HIRAGANA LETTER RO
+0x82EC	0x308E	#HIRAGANA LETTER SMALL WA
+0x82ED	0x308F	#HIRAGANA LETTER WA
+0x82EE	0x3090	#HIRAGANA LETTER WI
+0x82EF	0x3091	#HIRAGANA LETTER WE
+0x82F0	0x3092	#HIRAGANA LETTER WO
+0x82F1	0x3093	#HIRAGANA LETTER N
+0x8340	0x30A1	#KATAKANA LETTER SMALL A
+0x8341	0x30A2	#KATAKANA LETTER A
+0x8342	0x30A3	#KATAKANA LETTER SMALL I
+0x8343	0x30A4	#KATAKANA LETTER I
+0x8344	0x30A5	#KATAKANA LETTER SMALL U
+0x8345	0x30A6	#KATAKANA LETTER U
+0x8346	0x30A7	#KATAKANA LETTER SMALL E
+0x8347	0x30A8	#KATAKANA LETTER E
+0x8348	0x30A9	#KATAKANA LETTER SMALL O
+0x8349	0x30AA	#KATAKANA LETTER O
+0x834A	0x30AB	#KATAKANA LETTER KA
+0x834B	0x30AC	#KATAKANA LETTER GA
+0x834C	0x30AD	#KATAKANA LETTER KI
+0x834D	0x30AE	#KATAKANA LETTER GI
+0x834E	0x30AF	#KATAKANA LETTER KU
+0x834F	0x30B0	#KATAKANA LETTER GU
+0x8350	0x30B1	#KATAKANA LETTER KE
+0x8351	0x30B2	#KATAKANA LETTER GE
+0x8352	0x30B3	#KATAKANA LETTER KO
+0x8353	0x30B4	#KATAKANA LETTER GO
+0x8354	0x30B5	#KATAKANA LETTER SA
+0x8355	0x30B6	#KATAKANA LETTER ZA
+0x8356	0x30B7	#KATAKANA LETTER SI
+0x8357	0x30B8	#KATAKANA LETTER ZI
+0x8358	0x30B9	#KATAKANA LETTER SU
+0x8359	0x30BA	#KATAKANA LETTER ZU
+0x835A	0x30BB	#KATAKANA LETTER SE
+0x835B	0x30BC	#KATAKANA LETTER ZE
+0x835C	0x30BD	#KATAKANA LETTER SO
+0x835D	0x30BE	#KATAKANA LETTER ZO
+0x835E	0x30BF	#KATAKANA LETTER TA
+0x835F	0x30C0	#KATAKANA LETTER DA
+0x8360	0x30C1	#KATAKANA LETTER TI
+0x8361	0x30C2	#KATAKANA LETTER DI
+0x8362	0x30C3	#KATAKANA LETTER SMALL TU
+0x8363	0x30C4	#KATAKANA LETTER TU
+0x8364	0x30C5	#KATAKANA LETTER DU
+0x8365	0x30C6	#KATAKANA LETTER TE
+0x8366	0x30C7	#KATAKANA LETTER DE
+0x8367	0x30C8	#KATAKANA LETTER TO
+0x8368	0x30C9	#KATAKANA LETTER DO
+0x8369	0x30CA	#KATAKANA LETTER NA
+0x836A	0x30CB	#KATAKANA LETTER NI
+0x836B	0x30CC	#KATAKANA LETTER NU
+0x836C	0x30CD	#KATAKANA LETTER NE
+0x836D	0x30CE	#KATAKANA LETTER NO
+0x836E	0x30CF	#KATAKANA LETTER HA
+0x836F	0x30D0	#KATAKANA LETTER BA
+0x8370	0x30D1	#KATAKANA LETTER PA
+0x8371	0x30D2	#KATAKANA LETTER HI
+0x8372	0x30D3	#KATAKANA LETTER BI
+0x8373	0x30D4	#KATAKANA LETTER PI
+0x8374	0x30D5	#KATAKANA LETTER HU
+0x8375	0x30D6	#KATAKANA LETTER BU
+0x8376	0x30D7	#KATAKANA LETTER PU
+0x8377	0x30D8	#KATAKANA LETTER HE
+0x8378	0x30D9	#KATAKANA LETTER BE
+0x8379	0x30DA	#KATAKANA LETTER PE
+0x837A	0x30DB	#KATAKANA LETTER HO
+0x837B	0x30DC	#KATAKANA LETTER BO
+0x837C	0x30DD	#KATAKANA LETTER PO
+0x837D	0x30DE	#KATAKANA LETTER MA
+0x837E	0x30DF	#KATAKANA LETTER MI
+0x8380	0x30E0	#KATAKANA LETTER MU
+0x8381	0x30E1	#KATAKANA LETTER ME
+0x8382	0x30E2	#KATAKANA LETTER MO
+0x8383	0x30E3	#KATAKANA LETTER SMALL YA
+0x8384	0x30E4	#KATAKANA LETTER YA
+0x8385	0x30E5	#KATAKANA LETTER SMALL YU
+0x8386	0x30E6	#KATAKANA LETTER YU
+0x8387	0x30E7	#KATAKANA LETTER SMALL YO
+0x8388	0x30E8	#KATAKANA LETTER YO
+0x8389	0x30E9	#KATAKANA LETTER RA
+0x838A	0x30EA	#KATAKANA LETTER RI
+0x838B	0x30EB	#KATAKANA LETTER RU
+0x838C	0x30EC	#KATAKANA LETTER RE
+0x838D	0x30ED	#KATAKANA LETTER RO
+0x838E	0x30EE	#KATAKANA LETTER SMALL WA
+0x838F	0x30EF	#KATAKANA LETTER WA
+0x8390	0x30F0	#KATAKANA LETTER WI
+0x8391	0x30F1	#KATAKANA LETTER WE
+0x8392	0x30F2	#KATAKANA LETTER WO
+0x8393	0x30F3	#KATAKANA LETTER N
+0x8394	0x30F4	#KATAKANA LETTER VU
+0x8395	0x30F5	#KATAKANA LETTER SMALL KA
+0x8396	0x30F6	#KATAKANA LETTER SMALL KE
+0x839F	0x0391	#GREEK CAPITAL LETTER ALPHA
+0x83A0	0x0392	#GREEK CAPITAL LETTER BETA
+0x83A1	0x0393	#GREEK CAPITAL LETTER GAMMA
+0x83A2	0x0394	#GREEK CAPITAL LETTER DELTA
+0x83A3	0x0395	#GREEK CAPITAL LETTER EPSILON
+0x83A4	0x0396	#GREEK CAPITAL LETTER ZETA
+0x83A5	0x0397	#GREEK CAPITAL LETTER ETA
+0x83A6	0x0398	#GREEK CAPITAL LETTER THETA
+0x83A7	0x0399	#GREEK CAPITAL LETTER IOTA
+0x83A8	0x039A	#GREEK CAPITAL LETTER KAPPA
+0x83A9	0x039B	#GREEK CAPITAL LETTER LAMDA
+0x83AA	0x039C	#GREEK CAPITAL LETTER MU
+0x83AB	0x039D	#GREEK CAPITAL LETTER NU
+0x83AC	0x039E	#GREEK CAPITAL LETTER XI
+0x83AD	0x039F	#GREEK CAPITAL LETTER OMICRON
+0x83AE	0x03A0	#GREEK CAPITAL LETTER PI
+0x83AF	0x03A1	#GREEK CAPITAL LETTER RHO
+0x83B0	0x03A3	#GREEK CAPITAL LETTER SIGMA
+0x83B1	0x03A4	#GREEK CAPITAL LETTER TAU
+0x83B2	0x03A5	#GREEK CAPITAL LETTER UPSILON
+0x83B3	0x03A6	#GREEK CAPITAL LETTER PHI
+0x83B4	0x03A7	#GREEK CAPITAL LETTER CHI
+0x83B5	0x03A8	#GREEK CAPITAL LETTER PSI
+0x83B6	0x03A9	#GREEK CAPITAL LETTER OMEGA
+0x83BF	0x03B1	#GREEK SMALL LETTER ALPHA
+0x83C0	0x03B2	#GREEK SMALL LETTER BETA
+0x83C1	0x03B3	#GREEK SMALL LETTER GAMMA
+0x83C2	0x03B4	#GREEK SMALL LETTER DELTA
+0x83C3	0x03B5	#GREEK SMALL LETTER EPSILON
+0x83C4	0x03B6	#GREEK SMALL LETTER ZETA
+0x83C5	0x03B7	#GREEK SMALL LETTER ETA
+0x83C6	0x03B8	#GREEK SMALL LETTER THETA
+0x83C7	0x03B9	#GREEK SMALL LETTER IOTA
+0x83C8	0x03BA	#GREEK SMALL LETTER KAPPA
+0x83C9	0x03BB	#GREEK SMALL LETTER LAMDA
+0x83CA	0x03BC	#GREEK SMALL LETTER MU
+0x83CB	0x03BD	#GREEK SMALL LETTER NU
+0x83CC	0x03BE	#GREEK SMALL LETTER XI
+0x83CD	0x03BF	#GREEK SMALL LETTER OMICRON
+0x83CE	0x03C0	#GREEK SMALL LETTER PI
+0x83CF	0x03C1	#GREEK SMALL LETTER RHO
+0x83D0	0x03C3	#GREEK SMALL LETTER SIGMA
+0x83D1	0x03C4	#GREEK SMALL LETTER TAU
+0x83D2	0x03C5	#GREEK SMALL LETTER UPSILON
+0x83D3	0x03C6	#GREEK SMALL LETTER PHI
+0x83D4	0x03C7	#GREEK SMALL LETTER CHI
+0x83D5	0x03C8	#GREEK SMALL LETTER PSI
+0x83D6	0x03C9	#GREEK SMALL LETTER OMEGA
+0x8440	0x0410	#CYRILLIC CAPITAL LETTER A
+0x8441	0x0411	#CYRILLIC CAPITAL LETTER BE
+0x8442	0x0412	#CYRILLIC CAPITAL LETTER VE
+0x8443	0x0413	#CYRILLIC CAPITAL LETTER GHE
+0x8444	0x0414	#CYRILLIC CAPITAL LETTER DE
+0x8445	0x0415	#CYRILLIC CAPITAL LETTER IE
+0x8446	0x0401	#CYRILLIC CAPITAL LETTER IO
+0x8447	0x0416	#CYRILLIC CAPITAL LETTER ZHE
+0x8448	0x0417	#CYRILLIC CAPITAL LETTER ZE
+0x8449	0x0418	#CYRILLIC CAPITAL LETTER I
+0x844A	0x0419	#CYRILLIC CAPITAL LETTER SHORT I
+0x844B	0x041A	#CYRILLIC CAPITAL LETTER KA
+0x844C	0x041B	#CYRILLIC CAPITAL LETTER EL
+0x844D	0x041C	#CYRILLIC CAPITAL LETTER EM
+0x844E	0x041D	#CYRILLIC CAPITAL LETTER EN
+0x844F	0x041E	#CYRILLIC CAPITAL LETTER O
+0x8450	0x041F	#CYRILLIC CAPITAL LETTER PE
+0x8451	0x0420	#CYRILLIC CAPITAL LETTER ER
+0x8452	0x0421	#CYRILLIC CAPITAL LETTER ES
+0x8453	0x0422	#CYRILLIC CAPITAL LETTER TE
+0x8454	0x0423	#CYRILLIC CAPITAL LETTER U
+0x8455	0x0424	#CYRILLIC CAPITAL LETTER EF
+0x8456	0x0425	#CYRILLIC CAPITAL LETTER HA
+0x8457	0x0426	#CYRILLIC CAPITAL LETTER TSE
+0x8458	0x0427	#CYRILLIC CAPITAL LETTER CHE
+0x8459	0x0428	#CYRILLIC CAPITAL LETTER SHA
+0x845A	0x0429	#CYRILLIC CAPITAL LETTER SHCHA
+0x845B	0x042A	#CYRILLIC CAPITAL LETTER HARD SIGN
+0x845C	0x042B	#CYRILLIC CAPITAL LETTER YERU
+0x845D	0x042C	#CYRILLIC CAPITAL LETTER SOFT SIGN
+0x845E	0x042D	#CYRILLIC CAPITAL LETTER E
+0x845F	0x042E	#CYRILLIC CAPITAL LETTER YU
+0x8460	0x042F	#CYRILLIC CAPITAL LETTER YA
+0x8470	0x0430	#CYRILLIC SMALL LETTER A
+0x8471	0x0431	#CYRILLIC SMALL LETTER BE
+0x8472	0x0432	#CYRILLIC SMALL LETTER VE
+0x8473	0x0433	#CYRILLIC SMALL LETTER GHE
+0x8474	0x0434	#CYRILLIC SMALL LETTER DE
+0x8475	0x0435	#CYRILLIC SMALL LETTER IE
+0x8476	0x0451	#CYRILLIC SMALL LETTER IO
+0x8477	0x0436	#CYRILLIC SMALL LETTER ZHE
+0x8478	0x0437	#CYRILLIC SMALL LETTER ZE
+0x8479	0x0438	#CYRILLIC SMALL LETTER I
+0x847A	0x0439	#CYRILLIC SMALL LETTER SHORT I
+0x847B	0x043A	#CYRILLIC SMALL LETTER KA
+0x847C	0x043B	#CYRILLIC SMALL LETTER EL
+0x847D	0x043C	#CYRILLIC SMALL LETTER EM
+0x847E	0x043D	#CYRILLIC SMALL LETTER EN
+0x8480	0x043E	#CYRILLIC SMALL LETTER O
+0x8481	0x043F	#CYRILLIC SMALL LETTER PE
+0x8482	0x0440	#CYRILLIC SMALL LETTER ER
+0x8483	0x0441	#CYRILLIC SMALL LETTER ES
+0x8484	0x0442	#CYRILLIC SMALL LETTER TE
+0x8485	0x0443	#CYRILLIC SMALL LETTER U
+0x8486	0x0444	#CYRILLIC SMALL LETTER EF
+0x8487	0x0445	#CYRILLIC SMALL LETTER HA
+0x8488	0x0446	#CYRILLIC SMALL LETTER TSE
+0x8489	0x0447	#CYRILLIC SMALL LETTER CHE
+0x848A	0x0448	#CYRILLIC SMALL LETTER SHA
+0x848B	0x0449	#CYRILLIC SMALL LETTER SHCHA
+0x848C	0x044A	#CYRILLIC SMALL LETTER HARD SIGN
+0x848D	0x044B	#CYRILLIC SMALL LETTER YERU
+0x848E	0x044C	#CYRILLIC SMALL LETTER SOFT SIGN
+0x848F	0x044D	#CYRILLIC SMALL LETTER E
+0x8490	0x044E	#CYRILLIC SMALL LETTER YU
+0x8491	0x044F	#CYRILLIC SMALL LETTER YA
+0x849F	0x2500	#BOX DRAWINGS LIGHT HORIZONTAL
+0x84A0	0x2502	#BOX DRAWINGS LIGHT VERTICAL
+0x84A1	0x250C	#BOX DRAWINGS LIGHT DOWN AND RIGHT
+0x84A2	0x2510	#BOX DRAWINGS LIGHT DOWN AND LEFT
+0x84A3	0x2518	#BOX DRAWINGS LIGHT UP AND LEFT
+0x84A4	0x2514	#BOX DRAWINGS LIGHT UP AND RIGHT
+0x84A5	0x251C	#BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0x84A6	0x252C	#BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0x84A7	0x2524	#BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0x84A8	0x2534	#BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0x84A9	0x253C	#BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0x84AA	0x2501	#BOX DRAWINGS HEAVY HORIZONTAL
+0x84AB	0x2503	#BOX DRAWINGS HEAVY VERTICAL
+0x84AC	0x250F	#BOX DRAWINGS HEAVY DOWN AND RIGHT
+0x84AD	0x2513	#BOX DRAWINGS HEAVY DOWN AND LEFT
+0x84AE	0x251B	#BOX DRAWINGS HEAVY UP AND LEFT
+0x84AF	0x2517	#BOX DRAWINGS HEAVY UP AND RIGHT
+0x84B0	0x2523	#BOX DRAWINGS HEAVY VERTICAL AND RIGHT
+0x84B1	0x2533	#BOX DRAWINGS HEAVY DOWN AND HORIZONTAL
+0x84B2	0x252B	#BOX DRAWINGS HEAVY VERTICAL AND LEFT
+0x84B3	0x253B	#BOX DRAWINGS HEAVY UP AND HORIZONTAL
+0x84B4	0x254B	#BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL
+0x84B5	0x2520	#BOX DRAWINGS VERTICAL HEAVY AND RIGHT LIGHT
+0x84B6	0x252F	#BOX DRAWINGS DOWN LIGHT AND HORIZONTAL HEAVY
+0x84B7	0x2528	#BOX DRAWINGS VERTICAL HEAVY AND LEFT LIGHT
+0x84B8	0x2537	#BOX DRAWINGS UP LIGHT AND HORIZONTAL HEAVY
+0x84B9	0x253F	#BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY
+0x84BA	0x251D	#BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY
+0x84BB	0x2530	#BOX DRAWINGS DOWN HEAVY AND HORIZONTAL LIGHT
+0x84BC	0x2525	#BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY
+0x84BD	0x2538	#BOX DRAWINGS UP HEAVY AND HORIZONTAL LIGHT
+0x84BE	0x2542	#BOX DRAWINGS VERTICAL HEAVY AND HORIZONTAL LIGHT
+0x8740	0x2460	#CIRCLED DIGIT ONE
+0x8741	0x2461	#CIRCLED DIGIT TWO
+0x8742	0x2462	#CIRCLED DIGIT THREE
+0x8743	0x2463	#CIRCLED DIGIT FOUR
+0x8744	0x2464	#CIRCLED DIGIT FIVE
+0x8745	0x2465	#CIRCLED DIGIT SIX
+0x8746	0x2466	#CIRCLED DIGIT SEVEN
+0x8747	0x2467	#CIRCLED DIGIT EIGHT
+0x8748	0x2468	#CIRCLED DIGIT NINE
+0x8749	0x2469	#CIRCLED NUMBER TEN
+0x874A	0x246A	#CIRCLED NUMBER ELEVEN
+0x874B	0x246B	#CIRCLED NUMBER TWELVE
+0x874C	0x246C	#CIRCLED NUMBER THIRTEEN
+0x874D	0x246D	#CIRCLED NUMBER FOURTEEN
+0x874E	0x246E	#CIRCLED NUMBER FIFTEEN
+0x874F	0x246F	#CIRCLED NUMBER SIXTEEN
+0x8750	0x2470	#CIRCLED NUMBER SEVENTEEN
+0x8751	0x2471	#CIRCLED NUMBER EIGHTEEN
+0x8752	0x2472	#CIRCLED NUMBER NINETEEN
+0x8753	0x2473	#CIRCLED NUMBER TWENTY
+0x8754	0x2160	#ROMAN NUMERAL ONE
+0x8755	0x2161	#ROMAN NUMERAL TWO
+0x8756	0x2162	#ROMAN NUMERAL THREE
+0x8757	0x2163	#ROMAN NUMERAL FOUR
+0x8758	0x2164	#ROMAN NUMERAL FIVE
+0x8759	0x2165	#ROMAN NUMERAL SIX
+0x875A	0x2166	#ROMAN NUMERAL SEVEN
+0x875B	0x2167	#ROMAN NUMERAL EIGHT
+0x875C	0x2168	#ROMAN NUMERAL NINE
+0x875D	0x2169	#ROMAN NUMERAL TEN
+0x875F	0x3349	#SQUARE MIRI
+0x8760	0x3314	#SQUARE KIRO
+0x8761	0x3322	#SQUARE SENTI
+0x8762	0x334D	#SQUARE MEETORU
+0x8763	0x3318	#SQUARE GURAMU
+0x8764	0x3327	#SQUARE TON
+0x8765	0x3303	#SQUARE AARU
+0x8766	0x3336	#SQUARE HEKUTAARU
+0x8767	0x3351	#SQUARE RITTORU
+0x8768	0x3357	#SQUARE WATTO
+0x8769	0x330D	#SQUARE KARORII
+0x876A	0x3326	#SQUARE DORU
+0x876B	0x3323	#SQUARE SENTO
+0x876C	0x332B	#SQUARE PAASENTO
+0x876D	0x334A	#SQUARE MIRIBAARU
+0x876E	0x333B	#SQUARE PEEZI
+0x876F	0x339C	#SQUARE MM
+0x8770	0x339D	#SQUARE CM
+0x8771	0x339E	#SQUARE KM
+0x8772	0x338E	#SQUARE MG
+0x8773	0x338F	#SQUARE KG
+0x8774	0x33C4	#SQUARE CC
+0x8775	0x33A1	#SQUARE M SQUARED
+0x877E	0x337B	#SQUARE ERA NAME HEISEI
+0x8780	0x301D	#REVERSED DOUBLE PRIME QUOTATION MARK
+0x8781	0x301F	#LOW DOUBLE PRIME QUOTATION MARK
+0x8782	0x2116	#NUMERO SIGN
+0x8783	0x33CD	#SQUARE KK
+0x8784	0x2121	#TELEPHONE SIGN
+0x8785	0x32A4	#CIRCLED IDEOGRAPH HIGH
+0x8786	0x32A5	#CIRCLED IDEOGRAPH CENTRE
+0x8787	0x32A6	#CIRCLED IDEOGRAPH LOW
+0x8788	0x32A7	#CIRCLED IDEOGRAPH LEFT
+0x8789	0x32A8	#CIRCLED IDEOGRAPH RIGHT
+0x878A	0x3231	#PARENTHESIZED IDEOGRAPH STOCK
+0x878B	0x3232	#PARENTHESIZED IDEOGRAPH HAVE
+0x878C	0x3239	#PARENTHESIZED IDEOGRAPH REPRESENT
+0x878D	0x337E	#SQUARE ERA NAME MEIZI
+0x878E	0x337D	#SQUARE ERA NAME TAISYOU
+0x878F	0x337C	#SQUARE ERA NAME SYOUWA
+0x8790	0x2252	#APPROXIMATELY EQUAL TO OR THE IMAGE OF
+0x8791	0x2261	#IDENTICAL TO
+0x8792	0x222B	#INTEGRAL
+0x8793	0x222E	#CONTOUR INTEGRAL
+0x8794	0x2211	#N-ARY SUMMATION
+0x8795	0x221A	#SQUARE ROOT
+0x8796	0x22A5	#UP TACK
+0x8797	0x2220	#ANGLE
+0x8798	0x221F	#RIGHT ANGLE
+0x8799	0x22BF	#RIGHT TRIANGLE
+0x879A	0x2235	#BECAUSE
+0x879B	0x2229	#INTERSECTION
+0x879C	0x222A	#UNION
+0x889F	0x4E9C	#CJK UNIFIED IDEOGRAPH
+0x88A0	0x5516	#CJK UNIFIED IDEOGRAPH
+0x88A1	0x5A03	#CJK UNIFIED IDEOGRAPH
+0x88A2	0x963F	#CJK UNIFIED IDEOGRAPH
+0x88A3	0x54C0	#CJK UNIFIED IDEOGRAPH
+0x88A4	0x611B	#CJK UNIFIED IDEOGRAPH
+0x88A5	0x6328	#CJK UNIFIED IDEOGRAPH
+0x88A6	0x59F6	#CJK UNIFIED IDEOGRAPH
+0x88A7	0x9022	#CJK UNIFIED IDEOGRAPH
+0x88A8	0x8475	#CJK UNIFIED IDEOGRAPH
+0x88A9	0x831C	#CJK UNIFIED IDEOGRAPH
+0x88AA	0x7A50	#CJK UNIFIED IDEOGRAPH
+0x88AB	0x60AA	#CJK UNIFIED IDEOGRAPH
+0x88AC	0x63E1	#CJK UNIFIED IDEOGRAPH
+0x88AD	0x6E25	#CJK UNIFIED IDEOGRAPH
+0x88AE	0x65ED	#CJK UNIFIED IDEOGRAPH
+0x88AF	0x8466	#CJK UNIFIED IDEOGRAPH
+0x88B0	0x82A6	#CJK UNIFIED IDEOGRAPH
+0x88B1	0x9BF5	#CJK UNIFIED IDEOGRAPH
+0x88B2	0x6893	#CJK UNIFIED IDEOGRAPH
+0x88B3	0x5727	#CJK UNIFIED IDEOGRAPH
+0x88B4	0x65A1	#CJK UNIFIED IDEOGRAPH
+0x88B5	0x6271	#CJK UNIFIED IDEOGRAPH
+0x88B6	0x5B9B	#CJK UNIFIED IDEOGRAPH
+0x88B7	0x59D0	#CJK UNIFIED IDEOGRAPH
+0x88B8	0x867B	#CJK UNIFIED IDEOGRAPH
+0x88B9	0x98F4	#CJK UNIFIED IDEOGRAPH
+0x88BA	0x7D62	#CJK UNIFIED IDEOGRAPH
+0x88BB	0x7DBE	#CJK UNIFIED IDEOGRAPH
+0x88BC	0x9B8E	#CJK UNIFIED IDEOGRAPH
+0x88BD	0x6216	#CJK UNIFIED IDEOGRAPH
+0x88BE	0x7C9F	#CJK UNIFIED IDEOGRAPH
+0x88BF	0x88B7	#CJK UNIFIED IDEOGRAPH
+0x88C0	0x5B89	#CJK UNIFIED IDEOGRAPH
+0x88C1	0x5EB5	#CJK UNIFIED IDEOGRAPH
+0x88C2	0x6309	#CJK UNIFIED IDEOGRAPH
+0x88C3	0x6697	#CJK UNIFIED IDEOGRAPH
+0x88C4	0x6848	#CJK UNIFIED IDEOGRAPH
+0x88C5	0x95C7	#CJK UNIFIED IDEOGRAPH
+0x88C6	0x978D	#CJK UNIFIED IDEOGRAPH
+0x88C7	0x674F	#CJK UNIFIED IDEOGRAPH
+0x88C8	0x4EE5	#CJK UNIFIED IDEOGRAPH
+0x88C9	0x4F0A	#CJK UNIFIED IDEOGRAPH
+0x88CA	0x4F4D	#CJK UNIFIED IDEOGRAPH
+0x88CB	0x4F9D	#CJK UNIFIED IDEOGRAPH
+0x88CC	0x5049	#CJK UNIFIED IDEOGRAPH
+0x88CD	0x56F2	#CJK UNIFIED IDEOGRAPH
+0x88CE	0x5937	#CJK UNIFIED IDEOGRAPH
+0x88CF	0x59D4	#CJK UNIFIED IDEOGRAPH
+0x88D0	0x5A01	#CJK UNIFIED IDEOGRAPH
+0x88D1	0x5C09	#CJK UNIFIED IDEOGRAPH
+0x88D2	0x60DF	#CJK UNIFIED IDEOGRAPH
+0x88D3	0x610F	#CJK UNIFIED IDEOGRAPH
+0x88D4	0x6170	#CJK UNIFIED IDEOGRAPH
+0x88D5	0x6613	#CJK UNIFIED IDEOGRAPH
+0x88D6	0x6905	#CJK UNIFIED IDEOGRAPH
+0x88D7	0x70BA	#CJK UNIFIED IDEOGRAPH
+0x88D8	0x754F	#CJK UNIFIED IDEOGRAPH
+0x88D9	0x7570	#CJK UNIFIED IDEOGRAPH
+0x88DA	0x79FB	#CJK UNIFIED IDEOGRAPH
+0x88DB	0x7DAD	#CJK UNIFIED IDEOGRAPH
+0x88DC	0x7DEF	#CJK UNIFIED IDEOGRAPH
+0x88DD	0x80C3	#CJK UNIFIED IDEOGRAPH
+0x88DE	0x840E	#CJK UNIFIED IDEOGRAPH
+0x88DF	0x8863	#CJK UNIFIED IDEOGRAPH
+0x88E0	0x8B02	#CJK UNIFIED IDEOGRAPH
+0x88E1	0x9055	#CJK UNIFIED IDEOGRAPH
+0x88E2	0x907A	#CJK UNIFIED IDEOGRAPH
+0x88E3	0x533B	#CJK UNIFIED IDEOGRAPH
+0x88E4	0x4E95	#CJK UNIFIED IDEOGRAPH
+0x88E5	0x4EA5	#CJK UNIFIED IDEOGRAPH
+0x88E6	0x57DF	#CJK UNIFIED IDEOGRAPH
+0x88E7	0x80B2	#CJK UNIFIED IDEOGRAPH
+0x88E8	0x90C1	#CJK UNIFIED IDEOGRAPH
+0x88E9	0x78EF	#CJK UNIFIED IDEOGRAPH
+0x88EA	0x4E00	#CJK UNIFIED IDEOGRAPH
+0x88EB	0x58F1	#CJK UNIFIED IDEOGRAPH
+0x88EC	0x6EA2	#CJK UNIFIED IDEOGRAPH
+0x88ED	0x9038	#CJK UNIFIED IDEOGRAPH
+0x88EE	0x7A32	#CJK UNIFIED IDEOGRAPH
+0x88EF	0x8328	#CJK UNIFIED IDEOGRAPH
+0x88F0	0x828B	#CJK UNIFIED IDEOGRAPH
+0x88F1	0x9C2F	#CJK UNIFIED IDEOGRAPH
+0x88F2	0x5141	#CJK UNIFIED IDEOGRAPH
+0x88F3	0x5370	#CJK UNIFIED IDEOGRAPH
+0x88F4	0x54BD	#CJK UNIFIED IDEOGRAPH
+0x88F5	0x54E1	#CJK UNIFIED IDEOGRAPH
+0x88F6	0x56E0	#CJK UNIFIED IDEOGRAPH
+0x88F7	0x59FB	#CJK UNIFIED IDEOGRAPH
+0x88F8	0x5F15	#CJK UNIFIED IDEOGRAPH
+0x88F9	0x98F2	#CJK UNIFIED IDEOGRAPH
+0x88FA	0x6DEB	#CJK UNIFIED IDEOGRAPH
+0x88FB	0x80E4	#CJK UNIFIED IDEOGRAPH
+0x88FC	0x852D	#CJK UNIFIED IDEOGRAPH
+0x8940	0x9662	#CJK UNIFIED IDEOGRAPH
+0x8941	0x9670	#CJK UNIFIED IDEOGRAPH
+0x8942	0x96A0	#CJK UNIFIED IDEOGRAPH
+0x8943	0x97FB	#CJK UNIFIED IDEOGRAPH
+0x8944	0x540B	#CJK UNIFIED IDEOGRAPH
+0x8945	0x53F3	#CJK UNIFIED IDEOGRAPH
+0x8946	0x5B87	#CJK UNIFIED IDEOGRAPH
+0x8947	0x70CF	#CJK UNIFIED IDEOGRAPH
+0x8948	0x7FBD	#CJK UNIFIED IDEOGRAPH
+0x8949	0x8FC2	#CJK UNIFIED IDEOGRAPH
+0x894A	0x96E8	#CJK UNIFIED IDEOGRAPH
+0x894B	0x536F	#CJK UNIFIED IDEOGRAPH
+0x894C	0x9D5C	#CJK UNIFIED IDEOGRAPH
+0x894D	0x7ABA	#CJK UNIFIED IDEOGRAPH
+0x894E	0x4E11	#CJK UNIFIED IDEOGRAPH
+0x894F	0x7893	#CJK UNIFIED IDEOGRAPH
+0x8950	0x81FC	#CJK UNIFIED IDEOGRAPH
+0x8951	0x6E26	#CJK UNIFIED IDEOGRAPH
+0x8952	0x5618	#CJK UNIFIED IDEOGRAPH
+0x8953	0x5504	#CJK UNIFIED IDEOGRAPH
+0x8954	0x6B1D	#CJK UNIFIED IDEOGRAPH
+0x8955	0x851A	#CJK UNIFIED IDEOGRAPH
+0x8956	0x9C3B	#CJK UNIFIED IDEOGRAPH
+0x8957	0x59E5	#CJK UNIFIED IDEOGRAPH
+0x8958	0x53A9	#CJK UNIFIED IDEOGRAPH
+0x8959	0x6D66	#CJK UNIFIED IDEOGRAPH
+0x895A	0x74DC	#CJK UNIFIED IDEOGRAPH
+0x895B	0x958F	#CJK UNIFIED IDEOGRAPH
+0x895C	0x5642	#CJK UNIFIED IDEOGRAPH
+0x895D	0x4E91	#CJK UNIFIED IDEOGRAPH
+0x895E	0x904B	#CJK UNIFIED IDEOGRAPH
+0x895F	0x96F2	#CJK UNIFIED IDEOGRAPH
+0x8960	0x834F	#CJK UNIFIED IDEOGRAPH
+0x8961	0x990C	#CJK UNIFIED IDEOGRAPH
+0x8962	0x53E1	#CJK UNIFIED IDEOGRAPH
+0x8963	0x55B6	#CJK UNIFIED IDEOGRAPH
+0x8964	0x5B30	#CJK UNIFIED IDEOGRAPH
+0x8965	0x5F71	#CJK UNIFIED IDEOGRAPH
+0x8966	0x6620	#CJK UNIFIED IDEOGRAPH
+0x8967	0x66F3	#CJK UNIFIED IDEOGRAPH
+0x8968	0x6804	#CJK UNIFIED IDEOGRAPH
+0x8969	0x6C38	#CJK UNIFIED IDEOGRAPH
+0x896A	0x6CF3	#CJK UNIFIED IDEOGRAPH
+0x896B	0x6D29	#CJK UNIFIED IDEOGRAPH
+0x896C	0x745B	#CJK UNIFIED IDEOGRAPH
+0x896D	0x76C8	#CJK UNIFIED IDEOGRAPH
+0x896E	0x7A4E	#CJK UNIFIED IDEOGRAPH
+0x896F	0x9834	#CJK UNIFIED IDEOGRAPH
+0x8970	0x82F1	#CJK UNIFIED IDEOGRAPH
+0x8971	0x885B	#CJK UNIFIED IDEOGRAPH
+0x8972	0x8A60	#CJK UNIFIED IDEOGRAPH
+0x8973	0x92ED	#CJK UNIFIED IDEOGRAPH
+0x8974	0x6DB2	#CJK UNIFIED IDEOGRAPH
+0x8975	0x75AB	#CJK UNIFIED IDEOGRAPH
+0x8976	0x76CA	#CJK UNIFIED IDEOGRAPH
+0x8977	0x99C5	#CJK UNIFIED IDEOGRAPH
+0x8978	0x60A6	#CJK UNIFIED IDEOGRAPH
+0x8979	0x8B01	#CJK UNIFIED IDEOGRAPH
+0x897A	0x8D8A	#CJK UNIFIED IDEOGRAPH
+0x897B	0x95B2	#CJK UNIFIED IDEOGRAPH
+0x897C	0x698E	#CJK UNIFIED IDEOGRAPH
+0x897D	0x53AD	#CJK UNIFIED IDEOGRAPH
+0x897E	0x5186	#CJK UNIFIED IDEOGRAPH
+0x8980	0x5712	#CJK UNIFIED IDEOGRAPH
+0x8981	0x5830	#CJK UNIFIED IDEOGRAPH
+0x8982	0x5944	#CJK UNIFIED IDEOGRAPH
+0x8983	0x5BB4	#CJK UNIFIED IDEOGRAPH
+0x8984	0x5EF6	#CJK UNIFIED IDEOGRAPH
+0x8985	0x6028	#CJK UNIFIED IDEOGRAPH
+0x8986	0x63A9	#CJK UNIFIED IDEOGRAPH
+0x8987	0x63F4	#CJK UNIFIED IDEOGRAPH
+0x8988	0x6CBF	#CJK UNIFIED IDEOGRAPH
+0x8989	0x6F14	#CJK UNIFIED IDEOGRAPH
+0x898A	0x708E	#CJK UNIFIED IDEOGRAPH
+0x898B	0x7114	#CJK UNIFIED IDEOGRAPH
+0x898C	0x7159	#CJK UNIFIED IDEOGRAPH
+0x898D	0x71D5	#CJK UNIFIED IDEOGRAPH
+0x898E	0x733F	#CJK UNIFIED IDEOGRAPH
+0x898F	0x7E01	#CJK UNIFIED IDEOGRAPH
+0x8990	0x8276	#CJK UNIFIED IDEOGRAPH
+0x8991	0x82D1	#CJK UNIFIED IDEOGRAPH
+0x8992	0x8597	#CJK UNIFIED IDEOGRAPH
+0x8993	0x9060	#CJK UNIFIED IDEOGRAPH
+0x8994	0x925B	#CJK UNIFIED IDEOGRAPH
+0x8995	0x9D1B	#CJK UNIFIED IDEOGRAPH
+0x8996	0x5869	#CJK UNIFIED IDEOGRAPH
+0x8997	0x65BC	#CJK UNIFIED IDEOGRAPH
+0x8998	0x6C5A	#CJK UNIFIED IDEOGRAPH
+0x8999	0x7525	#CJK UNIFIED IDEOGRAPH
+0x899A	0x51F9	#CJK UNIFIED IDEOGRAPH
+0x899B	0x592E	#CJK UNIFIED IDEOGRAPH
+0x899C	0x5965	#CJK UNIFIED IDEOGRAPH
+0x899D	0x5F80	#CJK UNIFIED IDEOGRAPH
+0x899E	0x5FDC	#CJK UNIFIED IDEOGRAPH
+0x899F	0x62BC	#CJK UNIFIED IDEOGRAPH
+0x89A0	0x65FA	#CJK UNIFIED IDEOGRAPH
+0x89A1	0x6A2A	#CJK UNIFIED IDEOGRAPH
+0x89A2	0x6B27	#CJK UNIFIED IDEOGRAPH
+0x89A3	0x6BB4	#CJK UNIFIED IDEOGRAPH
+0x89A4	0x738B	#CJK UNIFIED IDEOGRAPH
+0x89A5	0x7FC1	#CJK UNIFIED IDEOGRAPH
+0x89A6	0x8956	#CJK UNIFIED IDEOGRAPH
+0x89A7	0x9D2C	#CJK UNIFIED IDEOGRAPH
+0x89A8	0x9D0E	#CJK UNIFIED IDEOGRAPH
+0x89A9	0x9EC4	#CJK UNIFIED IDEOGRAPH
+0x89AA	0x5CA1	#CJK UNIFIED IDEOGRAPH
+0x89AB	0x6C96	#CJK UNIFIED IDEOGRAPH
+0x89AC	0x837B	#CJK UNIFIED IDEOGRAPH
+0x89AD	0x5104	#CJK UNIFIED IDEOGRAPH
+0x89AE	0x5C4B	#CJK UNIFIED IDEOGRAPH
+0x89AF	0x61B6	#CJK UNIFIED IDEOGRAPH
+0x89B0	0x81C6	#CJK UNIFIED IDEOGRAPH
+0x89B1	0x6876	#CJK UNIFIED IDEOGRAPH
+0x89B2	0x7261	#CJK UNIFIED IDEOGRAPH
+0x89B3	0x4E59	#CJK UNIFIED IDEOGRAPH
+0x89B4	0x4FFA	#CJK UNIFIED IDEOGRAPH
+0x89B5	0x5378	#CJK UNIFIED IDEOGRAPH
+0x89B6	0x6069	#CJK UNIFIED IDEOGRAPH
+0x89B7	0x6E29	#CJK UNIFIED IDEOGRAPH
+0x89B8	0x7A4F	#CJK UNIFIED IDEOGRAPH
+0x89B9	0x97F3	#CJK UNIFIED IDEOGRAPH
+0x89BA	0x4E0B	#CJK UNIFIED IDEOGRAPH
+0x89BB	0x5316	#CJK UNIFIED IDEOGRAPH
+0x89BC	0x4EEE	#CJK UNIFIED IDEOGRAPH
+0x89BD	0x4F55	#CJK UNIFIED IDEOGRAPH
+0x89BE	0x4F3D	#CJK UNIFIED IDEOGRAPH
+0x89BF	0x4FA1	#CJK UNIFIED IDEOGRAPH
+0x89C0	0x4F73	#CJK UNIFIED IDEOGRAPH
+0x89C1	0x52A0	#CJK UNIFIED IDEOGRAPH
+0x89C2	0x53EF	#CJK UNIFIED IDEOGRAPH
+0x89C3	0x5609	#CJK UNIFIED IDEOGRAPH
+0x89C4	0x590F	#CJK UNIFIED IDEOGRAPH
+0x89C5	0x5AC1	#CJK UNIFIED IDEOGRAPH
+0x89C6	0x5BB6	#CJK UNIFIED IDEOGRAPH
+0x89C7	0x5BE1	#CJK UNIFIED IDEOGRAPH
+0x89C8	0x79D1	#CJK UNIFIED IDEOGRAPH
+0x89C9	0x6687	#CJK UNIFIED IDEOGRAPH
+0x89CA	0x679C	#CJK UNIFIED IDEOGRAPH
+0x89CB	0x67B6	#CJK UNIFIED IDEOGRAPH
+0x89CC	0x6B4C	#CJK UNIFIED IDEOGRAPH
+0x89CD	0x6CB3	#CJK UNIFIED IDEOGRAPH
+0x89CE	0x706B	#CJK UNIFIED IDEOGRAPH
+0x89CF	0x73C2	#CJK UNIFIED IDEOGRAPH
+0x89D0	0x798D	#CJK UNIFIED IDEOGRAPH
+0x89D1	0x79BE	#CJK UNIFIED IDEOGRAPH
+0x89D2	0x7A3C	#CJK UNIFIED IDEOGRAPH
+0x89D3	0x7B87	#CJK UNIFIED IDEOGRAPH
+0x89D4	0x82B1	#CJK UNIFIED IDEOGRAPH
+0x89D5	0x82DB	#CJK UNIFIED IDEOGRAPH
+0x89D6	0x8304	#CJK UNIFIED IDEOGRAPH
+0x89D7	0x8377	#CJK UNIFIED IDEOGRAPH
+0x89D8	0x83EF	#CJK UNIFIED IDEOGRAPH
+0x89D9	0x83D3	#CJK UNIFIED IDEOGRAPH
+0x89DA	0x8766	#CJK UNIFIED IDEOGRAPH
+0x89DB	0x8AB2	#CJK UNIFIED IDEOGRAPH
+0x89DC	0x5629	#CJK UNIFIED IDEOGRAPH
+0x89DD	0x8CA8	#CJK UNIFIED IDEOGRAPH
+0x89DE	0x8FE6	#CJK UNIFIED IDEOGRAPH
+0x89DF	0x904E	#CJK UNIFIED IDEOGRAPH
+0x89E0	0x971E	#CJK UNIFIED IDEOGRAPH
+0x89E1	0x868A	#CJK UNIFIED IDEOGRAPH
+0x89E2	0x4FC4	#CJK UNIFIED IDEOGRAPH
+0x89E3	0x5CE8	#CJK UNIFIED IDEOGRAPH
+0x89E4	0x6211	#CJK UNIFIED IDEOGRAPH
+0x89E5	0x7259	#CJK UNIFIED IDEOGRAPH
+0x89E6	0x753B	#CJK UNIFIED IDEOGRAPH
+0x89E7	0x81E5	#CJK UNIFIED IDEOGRAPH
+0x89E8	0x82BD	#CJK UNIFIED IDEOGRAPH
+0x89E9	0x86FE	#CJK UNIFIED IDEOGRAPH
+0x89EA	0x8CC0	#CJK UNIFIED IDEOGRAPH
+0x89EB	0x96C5	#CJK UNIFIED IDEOGRAPH
+0x89EC	0x9913	#CJK UNIFIED IDEOGRAPH
+0x89ED	0x99D5	#CJK UNIFIED IDEOGRAPH
+0x89EE	0x4ECB	#CJK UNIFIED IDEOGRAPH
+0x89EF	0x4F1A	#CJK UNIFIED IDEOGRAPH
+0x89F0	0x89E3	#CJK UNIFIED IDEOGRAPH
+0x89F1	0x56DE	#CJK UNIFIED IDEOGRAPH
+0x89F2	0x584A	#CJK UNIFIED IDEOGRAPH
+0x89F3	0x58CA	#CJK UNIFIED IDEOGRAPH
+0x89F4	0x5EFB	#CJK UNIFIED IDEOGRAPH
+0x89F5	0x5FEB	#CJK UNIFIED IDEOGRAPH
+0x89F6	0x602A	#CJK UNIFIED IDEOGRAPH
+0x89F7	0x6094	#CJK UNIFIED IDEOGRAPH
+0x89F8	0x6062	#CJK UNIFIED IDEOGRAPH
+0x89F9	0x61D0	#CJK UNIFIED IDEOGRAPH
+0x89FA	0x6212	#CJK UNIFIED IDEOGRAPH
+0x89FB	0x62D0	#CJK UNIFIED IDEOGRAPH
+0x89FC	0x6539	#CJK UNIFIED IDEOGRAPH
+0x8A40	0x9B41	#CJK UNIFIED IDEOGRAPH
+0x8A41	0x6666	#CJK UNIFIED IDEOGRAPH
+0x8A42	0x68B0	#CJK UNIFIED IDEOGRAPH
+0x8A43	0x6D77	#CJK UNIFIED IDEOGRAPH
+0x8A44	0x7070	#CJK UNIFIED IDEOGRAPH
+0x8A45	0x754C	#CJK UNIFIED IDEOGRAPH
+0x8A46	0x7686	#CJK UNIFIED IDEOGRAPH
+0x8A47	0x7D75	#CJK UNIFIED IDEOGRAPH
+0x8A48	0x82A5	#CJK UNIFIED IDEOGRAPH
+0x8A49	0x87F9	#CJK UNIFIED IDEOGRAPH
+0x8A4A	0x958B	#CJK UNIFIED IDEOGRAPH
+0x8A4B	0x968E	#CJK UNIFIED IDEOGRAPH
+0x8A4C	0x8C9D	#CJK UNIFIED IDEOGRAPH
+0x8A4D	0x51F1	#CJK UNIFIED IDEOGRAPH
+0x8A4E	0x52BE	#CJK UNIFIED IDEOGRAPH
+0x8A4F	0x5916	#CJK UNIFIED IDEOGRAPH
+0x8A50	0x54B3	#CJK UNIFIED IDEOGRAPH
+0x8A51	0x5BB3	#CJK UNIFIED IDEOGRAPH
+0x8A52	0x5D16	#CJK UNIFIED IDEOGRAPH
+0x8A53	0x6168	#CJK UNIFIED IDEOGRAPH
+0x8A54	0x6982	#CJK UNIFIED IDEOGRAPH
+0x8A55	0x6DAF	#CJK UNIFIED IDEOGRAPH
+0x8A56	0x788D	#CJK UNIFIED IDEOGRAPH
+0x8A57	0x84CB	#CJK UNIFIED IDEOGRAPH
+0x8A58	0x8857	#CJK UNIFIED IDEOGRAPH
+0x8A59	0x8A72	#CJK UNIFIED IDEOGRAPH
+0x8A5A	0x93A7	#CJK UNIFIED IDEOGRAPH
+0x8A5B	0x9AB8	#CJK UNIFIED IDEOGRAPH
+0x8A5C	0x6D6C	#CJK UNIFIED IDEOGRAPH
+0x8A5D	0x99A8	#CJK UNIFIED IDEOGRAPH
+0x8A5E	0x86D9	#CJK UNIFIED IDEOGRAPH
+0x8A5F	0x57A3	#CJK UNIFIED IDEOGRAPH
+0x8A60	0x67FF	#CJK UNIFIED IDEOGRAPH
+0x8A61	0x86CE	#CJK UNIFIED IDEOGRAPH
+0x8A62	0x920E	#CJK UNIFIED IDEOGRAPH
+0x8A63	0x5283	#CJK UNIFIED IDEOGRAPH
+0x8A64	0x5687	#CJK UNIFIED IDEOGRAPH
+0x8A65	0x5404	#CJK UNIFIED IDEOGRAPH
+0x8A66	0x5ED3	#CJK UNIFIED IDEOGRAPH
+0x8A67	0x62E1	#CJK UNIFIED IDEOGRAPH
+0x8A68	0x64B9	#CJK UNIFIED IDEOGRAPH
+0x8A69	0x683C	#CJK UNIFIED IDEOGRAPH
+0x8A6A	0x6838	#CJK UNIFIED IDEOGRAPH
+0x8A6B	0x6BBB	#CJK UNIFIED IDEOGRAPH
+0x8A6C	0x7372	#CJK UNIFIED IDEOGRAPH
+0x8A6D	0x78BA	#CJK UNIFIED IDEOGRAPH
+0x8A6E	0x7A6B	#CJK UNIFIED IDEOGRAPH
+0x8A6F	0x899A	#CJK UNIFIED IDEOGRAPH
+0x8A70	0x89D2	#CJK UNIFIED IDEOGRAPH
+0x8A71	0x8D6B	#CJK UNIFIED IDEOGRAPH
+0x8A72	0x8F03	#CJK UNIFIED IDEOGRAPH
+0x8A73	0x90ED	#CJK UNIFIED IDEOGRAPH
+0x8A74	0x95A3	#CJK UNIFIED IDEOGRAPH
+0x8A75	0x9694	#CJK UNIFIED IDEOGRAPH
+0x8A76	0x9769	#CJK UNIFIED IDEOGRAPH
+0x8A77	0x5B66	#CJK UNIFIED IDEOGRAPH
+0x8A78	0x5CB3	#CJK UNIFIED IDEOGRAPH
+0x8A79	0x697D	#CJK UNIFIED IDEOGRAPH
+0x8A7A	0x984D	#CJK UNIFIED IDEOGRAPH
+0x8A7B	0x984E	#CJK UNIFIED IDEOGRAPH
+0x8A7C	0x639B	#CJK UNIFIED IDEOGRAPH
+0x8A7D	0x7B20	#CJK UNIFIED IDEOGRAPH
+0x8A7E	0x6A2B	#CJK UNIFIED IDEOGRAPH
+0x8A80	0x6A7F	#CJK UNIFIED IDEOGRAPH
+0x8A81	0x68B6	#CJK UNIFIED IDEOGRAPH
+0x8A82	0x9C0D	#CJK UNIFIED IDEOGRAPH
+0x8A83	0x6F5F	#CJK UNIFIED IDEOGRAPH
+0x8A84	0x5272	#CJK UNIFIED IDEOGRAPH
+0x8A85	0x559D	#CJK UNIFIED IDEOGRAPH
+0x8A86	0x6070	#CJK UNIFIED IDEOGRAPH
+0x8A87	0x62EC	#CJK UNIFIED IDEOGRAPH
+0x8A88	0x6D3B	#CJK UNIFIED IDEOGRAPH
+0x8A89	0x6E07	#CJK UNIFIED IDEOGRAPH
+0x8A8A	0x6ED1	#CJK UNIFIED IDEOGRAPH
+0x8A8B	0x845B	#CJK UNIFIED IDEOGRAPH
+0x8A8C	0x8910	#CJK UNIFIED IDEOGRAPH
+0x8A8D	0x8F44	#CJK UNIFIED IDEOGRAPH
+0x8A8E	0x4E14	#CJK UNIFIED IDEOGRAPH
+0x8A8F	0x9C39	#CJK UNIFIED IDEOGRAPH
+0x8A90	0x53F6	#CJK UNIFIED IDEOGRAPH
+0x8A91	0x691B	#CJK UNIFIED IDEOGRAPH
+0x8A92	0x6A3A	#CJK UNIFIED IDEOGRAPH
+0x8A93	0x9784	#CJK UNIFIED IDEOGRAPH
+0x8A94	0x682A	#CJK UNIFIED IDEOGRAPH
+0x8A95	0x515C	#CJK UNIFIED IDEOGRAPH
+0x8A96	0x7AC3	#CJK UNIFIED IDEOGRAPH
+0x8A97	0x84B2	#CJK UNIFIED IDEOGRAPH
+0x8A98	0x91DC	#CJK UNIFIED IDEOGRAPH
+0x8A99	0x938C	#CJK UNIFIED IDEOGRAPH
+0x8A9A	0x565B	#CJK UNIFIED IDEOGRAPH
+0x8A9B	0x9D28	#CJK UNIFIED IDEOGRAPH
+0x8A9C	0x6822	#CJK UNIFIED IDEOGRAPH
+0x8A9D	0x8305	#CJK UNIFIED IDEOGRAPH
+0x8A9E	0x8431	#CJK UNIFIED IDEOGRAPH
+0x8A9F	0x7CA5	#CJK UNIFIED IDEOGRAPH
+0x8AA0	0x5208	#CJK UNIFIED IDEOGRAPH
+0x8AA1	0x82C5	#CJK UNIFIED IDEOGRAPH
+0x8AA2	0x74E6	#CJK UNIFIED IDEOGRAPH
+0x8AA3	0x4E7E	#CJK UNIFIED IDEOGRAPH
+0x8AA4	0x4F83	#CJK UNIFIED IDEOGRAPH
+0x8AA5	0x51A0	#CJK UNIFIED IDEOGRAPH
+0x8AA6	0x5BD2	#CJK UNIFIED IDEOGRAPH
+0x8AA7	0x520A	#CJK UNIFIED IDEOGRAPH
+0x8AA8	0x52D8	#CJK UNIFIED IDEOGRAPH
+0x8AA9	0x52E7	#CJK UNIFIED IDEOGRAPH
+0x8AAA	0x5DFB	#CJK UNIFIED IDEOGRAPH
+0x8AAB	0x559A	#CJK UNIFIED IDEOGRAPH
+0x8AAC	0x582A	#CJK UNIFIED IDEOGRAPH
+0x8AAD	0x59E6	#CJK UNIFIED IDEOGRAPH
+0x8AAE	0x5B8C	#CJK UNIFIED IDEOGRAPH
+0x8AAF	0x5B98	#CJK UNIFIED IDEOGRAPH
+0x8AB0	0x5BDB	#CJK UNIFIED IDEOGRAPH
+0x8AB1	0x5E72	#CJK UNIFIED IDEOGRAPH
+0x8AB2	0x5E79	#CJK UNIFIED IDEOGRAPH
+0x8AB3	0x60A3	#CJK UNIFIED IDEOGRAPH
+0x8AB4	0x611F	#CJK UNIFIED IDEOGRAPH
+0x8AB5	0x6163	#CJK UNIFIED IDEOGRAPH
+0x8AB6	0x61BE	#CJK UNIFIED IDEOGRAPH
+0x8AB7	0x63DB	#CJK UNIFIED IDEOGRAPH
+0x8AB8	0x6562	#CJK UNIFIED IDEOGRAPH
+0x8AB9	0x67D1	#CJK UNIFIED IDEOGRAPH
+0x8ABA	0x6853	#CJK UNIFIED IDEOGRAPH
+0x8ABB	0x68FA	#CJK UNIFIED IDEOGRAPH
+0x8ABC	0x6B3E	#CJK UNIFIED IDEOGRAPH
+0x8ABD	0x6B53	#CJK UNIFIED IDEOGRAPH
+0x8ABE	0x6C57	#CJK UNIFIED IDEOGRAPH
+0x8ABF	0x6F22	#CJK UNIFIED IDEOGRAPH
+0x8AC0	0x6F97	#CJK UNIFIED IDEOGRAPH
+0x8AC1	0x6F45	#CJK UNIFIED IDEOGRAPH
+0x8AC2	0x74B0	#CJK UNIFIED IDEOGRAPH
+0x8AC3	0x7518	#CJK UNIFIED IDEOGRAPH
+0x8AC4	0x76E3	#CJK UNIFIED IDEOGRAPH
+0x8AC5	0x770B	#CJK UNIFIED IDEOGRAPH
+0x8AC6	0x7AFF	#CJK UNIFIED IDEOGRAPH
+0x8AC7	0x7BA1	#CJK UNIFIED IDEOGRAPH
+0x8AC8	0x7C21	#CJK UNIFIED IDEOGRAPH
+0x8AC9	0x7DE9	#CJK UNIFIED IDEOGRAPH
+0x8ACA	0x7F36	#CJK UNIFIED IDEOGRAPH
+0x8ACB	0x7FF0	#CJK UNIFIED IDEOGRAPH
+0x8ACC	0x809D	#CJK UNIFIED IDEOGRAPH
+0x8ACD	0x8266	#CJK UNIFIED IDEOGRAPH
+0x8ACE	0x839E	#CJK UNIFIED IDEOGRAPH
+0x8ACF	0x89B3	#CJK UNIFIED IDEOGRAPH
+0x8AD0	0x8ACC	#CJK UNIFIED IDEOGRAPH
+0x8AD1	0x8CAB	#CJK UNIFIED IDEOGRAPH
+0x8AD2	0x9084	#CJK UNIFIED IDEOGRAPH
+0x8AD3	0x9451	#CJK UNIFIED IDEOGRAPH
+0x8AD4	0x9593	#CJK UNIFIED IDEOGRAPH
+0x8AD5	0x9591	#CJK UNIFIED IDEOGRAPH
+0x8AD6	0x95A2	#CJK UNIFIED IDEOGRAPH
+0x8AD7	0x9665	#CJK UNIFIED IDEOGRAPH
+0x8AD8	0x97D3	#CJK UNIFIED IDEOGRAPH
+0x8AD9	0x9928	#CJK UNIFIED IDEOGRAPH
+0x8ADA	0x8218	#CJK UNIFIED IDEOGRAPH
+0x8ADB	0x4E38	#CJK UNIFIED IDEOGRAPH
+0x8ADC	0x542B	#CJK UNIFIED IDEOGRAPH
+0x8ADD	0x5CB8	#CJK UNIFIED IDEOGRAPH
+0x8ADE	0x5DCC	#CJK UNIFIED IDEOGRAPH
+0x8ADF	0x73A9	#CJK UNIFIED IDEOGRAPH
+0x8AE0	0x764C	#CJK UNIFIED IDEOGRAPH
+0x8AE1	0x773C	#CJK UNIFIED IDEOGRAPH
+0x8AE2	0x5CA9	#CJK UNIFIED IDEOGRAPH
+0x8AE3	0x7FEB	#CJK UNIFIED IDEOGRAPH
+0x8AE4	0x8D0B	#CJK UNIFIED IDEOGRAPH
+0x8AE5	0x96C1	#CJK UNIFIED IDEOGRAPH
+0x8AE6	0x9811	#CJK UNIFIED IDEOGRAPH
+0x8AE7	0x9854	#CJK UNIFIED IDEOGRAPH
+0x8AE8	0x9858	#CJK UNIFIED IDEOGRAPH
+0x8AE9	0x4F01	#CJK UNIFIED IDEOGRAPH
+0x8AEA	0x4F0E	#CJK UNIFIED IDEOGRAPH
+0x8AEB	0x5371	#CJK UNIFIED IDEOGRAPH
+0x8AEC	0x559C	#CJK UNIFIED IDEOGRAPH
+0x8AED	0x5668	#CJK UNIFIED IDEOGRAPH
+0x8AEE	0x57FA	#CJK UNIFIED IDEOGRAPH
+0x8AEF	0x5947	#CJK UNIFIED IDEOGRAPH
+0x8AF0	0x5B09	#CJK UNIFIED IDEOGRAPH
+0x8AF1	0x5BC4	#CJK UNIFIED IDEOGRAPH
+0x8AF2	0x5C90	#CJK UNIFIED IDEOGRAPH
+0x8AF3	0x5E0C	#CJK UNIFIED IDEOGRAPH
+0x8AF4	0x5E7E	#CJK UNIFIED IDEOGRAPH
+0x8AF5	0x5FCC	#CJK UNIFIED IDEOGRAPH
+0x8AF6	0x63EE	#CJK UNIFIED IDEOGRAPH
+0x8AF7	0x673A	#CJK UNIFIED IDEOGRAPH
+0x8AF8	0x65D7	#CJK UNIFIED IDEOGRAPH
+0x8AF9	0x65E2	#CJK UNIFIED IDEOGRAPH
+0x8AFA	0x671F	#CJK UNIFIED IDEOGRAPH
+0x8AFB	0x68CB	#CJK UNIFIED IDEOGRAPH
+0x8AFC	0x68C4	#CJK UNIFIED IDEOGRAPH
+0x8B40	0x6A5F	#CJK UNIFIED IDEOGRAPH
+0x8B41	0x5E30	#CJK UNIFIED IDEOGRAPH
+0x8B42	0x6BC5	#CJK UNIFIED IDEOGRAPH
+0x8B43	0x6C17	#CJK UNIFIED IDEOGRAPH
+0x8B44	0x6C7D	#CJK UNIFIED IDEOGRAPH
+0x8B45	0x757F	#CJK UNIFIED IDEOGRAPH
+0x8B46	0x7948	#CJK UNIFIED IDEOGRAPH
+0x8B47	0x5B63	#CJK UNIFIED IDEOGRAPH
+0x8B48	0x7A00	#CJK UNIFIED IDEOGRAPH
+0x8B49	0x7D00	#CJK UNIFIED IDEOGRAPH
+0x8B4A	0x5FBD	#CJK UNIFIED IDEOGRAPH
+0x8B4B	0x898F	#CJK UNIFIED IDEOGRAPH
+0x8B4C	0x8A18	#CJK UNIFIED IDEOGRAPH
+0x8B4D	0x8CB4	#CJK UNIFIED IDEOGRAPH
+0x8B4E	0x8D77	#CJK UNIFIED IDEOGRAPH
+0x8B4F	0x8ECC	#CJK UNIFIED IDEOGRAPH
+0x8B50	0x8F1D	#CJK UNIFIED IDEOGRAPH
+0x8B51	0x98E2	#CJK UNIFIED IDEOGRAPH
+0x8B52	0x9A0E	#CJK UNIFIED IDEOGRAPH
+0x8B53	0x9B3C	#CJK UNIFIED IDEOGRAPH
+0x8B54	0x4E80	#CJK UNIFIED IDEOGRAPH
+0x8B55	0x507D	#CJK UNIFIED IDEOGRAPH
+0x8B56	0x5100	#CJK UNIFIED IDEOGRAPH
+0x8B57	0x5993	#CJK UNIFIED IDEOGRAPH
+0x8B58	0x5B9C	#CJK UNIFIED IDEOGRAPH
+0x8B59	0x622F	#CJK UNIFIED IDEOGRAPH
+0x8B5A	0x6280	#CJK UNIFIED IDEOGRAPH
+0x8B5B	0x64EC	#CJK UNIFIED IDEOGRAPH
+0x8B5C	0x6B3A	#CJK UNIFIED IDEOGRAPH
+0x8B5D	0x72A0	#CJK UNIFIED IDEOGRAPH
+0x8B5E	0x7591	#CJK UNIFIED IDEOGRAPH
+0x8B5F	0x7947	#CJK UNIFIED IDEOGRAPH
+0x8B60	0x7FA9	#CJK UNIFIED IDEOGRAPH
+0x8B61	0x87FB	#CJK UNIFIED IDEOGRAPH
+0x8B62	0x8ABC	#CJK UNIFIED IDEOGRAPH
+0x8B63	0x8B70	#CJK UNIFIED IDEOGRAPH
+0x8B64	0x63AC	#CJK UNIFIED IDEOGRAPH
+0x8B65	0x83CA	#CJK UNIFIED IDEOGRAPH
+0x8B66	0x97A0	#CJK UNIFIED IDEOGRAPH
+0x8B67	0x5409	#CJK UNIFIED IDEOGRAPH
+0x8B68	0x5403	#CJK UNIFIED IDEOGRAPH
+0x8B69	0x55AB	#CJK UNIFIED IDEOGRAPH
+0x8B6A	0x6854	#CJK UNIFIED IDEOGRAPH
+0x8B6B	0x6A58	#CJK UNIFIED IDEOGRAPH
+0x8B6C	0x8A70	#CJK UNIFIED IDEOGRAPH
+0x8B6D	0x7827	#CJK UNIFIED IDEOGRAPH
+0x8B6E	0x6775	#CJK UNIFIED IDEOGRAPH
+0x8B6F	0x9ECD	#CJK UNIFIED IDEOGRAPH
+0x8B70	0x5374	#CJK UNIFIED IDEOGRAPH
+0x8B71	0x5BA2	#CJK UNIFIED IDEOGRAPH
+0x8B72	0x811A	#CJK UNIFIED IDEOGRAPH
+0x8B73	0x8650	#CJK UNIFIED IDEOGRAPH
+0x8B74	0x9006	#CJK UNIFIED IDEOGRAPH
+0x8B75	0x4E18	#CJK UNIFIED IDEOGRAPH
+0x8B76	0x4E45	#CJK UNIFIED IDEOGRAPH
+0x8B77	0x4EC7	#CJK UNIFIED IDEOGRAPH
+0x8B78	0x4F11	#CJK UNIFIED IDEOGRAPH
+0x8B79	0x53CA	#CJK UNIFIED IDEOGRAPH
+0x8B7A	0x5438	#CJK UNIFIED IDEOGRAPH
+0x8B7B	0x5BAE	#CJK UNIFIED IDEOGRAPH
+0x8B7C	0x5F13	#CJK UNIFIED IDEOGRAPH
+0x8B7D	0x6025	#CJK UNIFIED IDEOGRAPH
+0x8B7E	0x6551	#CJK UNIFIED IDEOGRAPH
+0x8B80	0x673D	#CJK UNIFIED IDEOGRAPH
+0x8B81	0x6C42	#CJK UNIFIED IDEOGRAPH
+0x8B82	0x6C72	#CJK UNIFIED IDEOGRAPH
+0x8B83	0x6CE3	#CJK UNIFIED IDEOGRAPH
+0x8B84	0x7078	#CJK UNIFIED IDEOGRAPH
+0x8B85	0x7403	#CJK UNIFIED IDEOGRAPH
+0x8B86	0x7A76	#CJK UNIFIED IDEOGRAPH
+0x8B87	0x7AAE	#CJK UNIFIED IDEOGRAPH
+0x8B88	0x7B08	#CJK UNIFIED IDEOGRAPH
+0x8B89	0x7D1A	#CJK UNIFIED IDEOGRAPH
+0x8B8A	0x7CFE	#CJK UNIFIED IDEOGRAPH
+0x8B8B	0x7D66	#CJK UNIFIED IDEOGRAPH
+0x8B8C	0x65E7	#CJK UNIFIED IDEOGRAPH
+0x8B8D	0x725B	#CJK UNIFIED IDEOGRAPH
+0x8B8E	0x53BB	#CJK UNIFIED IDEOGRAPH
+0x8B8F	0x5C45	#CJK UNIFIED IDEOGRAPH
+0x8B90	0x5DE8	#CJK UNIFIED IDEOGRAPH
+0x8B91	0x62D2	#CJK UNIFIED IDEOGRAPH
+0x8B92	0x62E0	#CJK UNIFIED IDEOGRAPH
+0x8B93	0x6319	#CJK UNIFIED IDEOGRAPH
+0x8B94	0x6E20	#CJK UNIFIED IDEOGRAPH
+0x8B95	0x865A	#CJK UNIFIED IDEOGRAPH
+0x8B96	0x8A31	#CJK UNIFIED IDEOGRAPH
+0x8B97	0x8DDD	#CJK UNIFIED IDEOGRAPH
+0x8B98	0x92F8	#CJK UNIFIED IDEOGRAPH
+0x8B99	0x6F01	#CJK UNIFIED IDEOGRAPH
+0x8B9A	0x79A6	#CJK UNIFIED IDEOGRAPH
+0x8B9B	0x9B5A	#CJK UNIFIED IDEOGRAPH
+0x8B9C	0x4EA8	#CJK UNIFIED IDEOGRAPH
+0x8B9D	0x4EAB	#CJK UNIFIED IDEOGRAPH
+0x8B9E	0x4EAC	#CJK UNIFIED IDEOGRAPH
+0x8B9F	0x4F9B	#CJK UNIFIED IDEOGRAPH
+0x8BA0	0x4FA0	#CJK UNIFIED IDEOGRAPH
+0x8BA1	0x50D1	#CJK UNIFIED IDEOGRAPH
+0x8BA2	0x5147	#CJK UNIFIED IDEOGRAPH
+0x8BA3	0x7AF6	#CJK UNIFIED IDEOGRAPH
+0x8BA4	0x5171	#CJK UNIFIED IDEOGRAPH
+0x8BA5	0x51F6	#CJK UNIFIED IDEOGRAPH
+0x8BA6	0x5354	#CJK UNIFIED IDEOGRAPH
+0x8BA7	0x5321	#CJK UNIFIED IDEOGRAPH
+0x8BA8	0x537F	#CJK UNIFIED IDEOGRAPH
+0x8BA9	0x53EB	#CJK UNIFIED IDEOGRAPH
+0x8BAA	0x55AC	#CJK UNIFIED IDEOGRAPH
+0x8BAB	0x5883	#CJK UNIFIED IDEOGRAPH
+0x8BAC	0x5CE1	#CJK UNIFIED IDEOGRAPH
+0x8BAD	0x5F37	#CJK UNIFIED IDEOGRAPH
+0x8BAE	0x5F4A	#CJK UNIFIED IDEOGRAPH
+0x8BAF	0x602F	#CJK UNIFIED IDEOGRAPH
+0x8BB0	0x6050	#CJK UNIFIED IDEOGRAPH
+0x8BB1	0x606D	#CJK UNIFIED IDEOGRAPH
+0x8BB2	0x631F	#CJK UNIFIED IDEOGRAPH
+0x8BB3	0x6559	#CJK UNIFIED IDEOGRAPH
+0x8BB4	0x6A4B	#CJK UNIFIED IDEOGRAPH
+0x8BB5	0x6CC1	#CJK UNIFIED IDEOGRAPH
+0x8BB6	0x72C2	#CJK UNIFIED IDEOGRAPH
+0x8BB7	0x72ED	#CJK UNIFIED IDEOGRAPH
+0x8BB8	0x77EF	#CJK UNIFIED IDEOGRAPH
+0x8BB9	0x80F8	#CJK UNIFIED IDEOGRAPH
+0x8BBA	0x8105	#CJK UNIFIED IDEOGRAPH
+0x8BBB	0x8208	#CJK UNIFIED IDEOGRAPH
+0x8BBC	0x854E	#CJK UNIFIED IDEOGRAPH
+0x8BBD	0x90F7	#CJK UNIFIED IDEOGRAPH
+0x8BBE	0x93E1	#CJK UNIFIED IDEOGRAPH
+0x8BBF	0x97FF	#CJK UNIFIED IDEOGRAPH
+0x8BC0	0x9957	#CJK UNIFIED IDEOGRAPH
+0x8BC1	0x9A5A	#CJK UNIFIED IDEOGRAPH
+0x8BC2	0x4EF0	#CJK UNIFIED IDEOGRAPH
+0x8BC3	0x51DD	#CJK UNIFIED IDEOGRAPH
+0x8BC4	0x5C2D	#CJK UNIFIED IDEOGRAPH
+0x8BC5	0x6681	#CJK UNIFIED IDEOGRAPH
+0x8BC6	0x696D	#CJK UNIFIED IDEOGRAPH
+0x8BC7	0x5C40	#CJK UNIFIED IDEOGRAPH
+0x8BC8	0x66F2	#CJK UNIFIED IDEOGRAPH
+0x8BC9	0x6975	#CJK UNIFIED IDEOGRAPH
+0x8BCA	0x7389	#CJK UNIFIED IDEOGRAPH
+0x8BCB	0x6850	#CJK UNIFIED IDEOGRAPH
+0x8BCC	0x7C81	#CJK UNIFIED IDEOGRAPH
+0x8BCD	0x50C5	#CJK UNIFIED IDEOGRAPH
+0x8BCE	0x52E4	#CJK UNIFIED IDEOGRAPH
+0x8BCF	0x5747	#CJK UNIFIED IDEOGRAPH
+0x8BD0	0x5DFE	#CJK UNIFIED IDEOGRAPH
+0x8BD1	0x9326	#CJK UNIFIED IDEOGRAPH
+0x8BD2	0x65A4	#CJK UNIFIED IDEOGRAPH
+0x8BD3	0x6B23	#CJK UNIFIED IDEOGRAPH
+0x8BD4	0x6B3D	#CJK UNIFIED IDEOGRAPH
+0x8BD5	0x7434	#CJK UNIFIED IDEOGRAPH
+0x8BD6	0x7981	#CJK UNIFIED IDEOGRAPH
+0x8BD7	0x79BD	#CJK UNIFIED IDEOGRAPH
+0x8BD8	0x7B4B	#CJK UNIFIED IDEOGRAPH
+0x8BD9	0x7DCA	#CJK UNIFIED IDEOGRAPH
+0x8BDA	0x82B9	#CJK UNIFIED IDEOGRAPH
+0x8BDB	0x83CC	#CJK UNIFIED IDEOGRAPH
+0x8BDC	0x887F	#CJK UNIFIED IDEOGRAPH
+0x8BDD	0x895F	#CJK UNIFIED IDEOGRAPH
+0x8BDE	0x8B39	#CJK UNIFIED IDEOGRAPH
+0x8BDF	0x8FD1	#CJK UNIFIED IDEOGRAPH
+0x8BE0	0x91D1	#CJK UNIFIED IDEOGRAPH
+0x8BE1	0x541F	#CJK UNIFIED IDEOGRAPH
+0x8BE2	0x9280	#CJK UNIFIED IDEOGRAPH
+0x8BE3	0x4E5D	#CJK UNIFIED IDEOGRAPH
+0x8BE4	0x5036	#CJK UNIFIED IDEOGRAPH
+0x8BE5	0x53E5	#CJK UNIFIED IDEOGRAPH
+0x8BE6	0x533A	#CJK UNIFIED IDEOGRAPH
+0x8BE7	0x72D7	#CJK UNIFIED IDEOGRAPH
+0x8BE8	0x7396	#CJK UNIFIED IDEOGRAPH
+0x8BE9	0x77E9	#CJK UNIFIED IDEOGRAPH
+0x8BEA	0x82E6	#CJK UNIFIED IDEOGRAPH
+0x8BEB	0x8EAF	#CJK UNIFIED IDEOGRAPH
+0x8BEC	0x99C6	#CJK UNIFIED IDEOGRAPH
+0x8BED	0x99C8	#CJK UNIFIED IDEOGRAPH
+0x8BEE	0x99D2	#CJK UNIFIED IDEOGRAPH
+0x8BEF	0x5177	#CJK UNIFIED IDEOGRAPH
+0x8BF0	0x611A	#CJK UNIFIED IDEOGRAPH
+0x8BF1	0x865E	#CJK UNIFIED IDEOGRAPH
+0x8BF2	0x55B0	#CJK UNIFIED IDEOGRAPH
+0x8BF3	0x7A7A	#CJK UNIFIED IDEOGRAPH
+0x8BF4	0x5076	#CJK UNIFIED IDEOGRAPH
+0x8BF5	0x5BD3	#CJK UNIFIED IDEOGRAPH
+0x8BF6	0x9047	#CJK UNIFIED IDEOGRAPH
+0x8BF7	0x9685	#CJK UNIFIED IDEOGRAPH
+0x8BF8	0x4E32	#CJK UNIFIED IDEOGRAPH
+0x8BF9	0x6ADB	#CJK UNIFIED IDEOGRAPH
+0x8BFA	0x91E7	#CJK UNIFIED IDEOGRAPH
+0x8BFB	0x5C51	#CJK UNIFIED IDEOGRAPH
+0x8BFC	0x5C48	#CJK UNIFIED IDEOGRAPH
+0x8C40	0x6398	#CJK UNIFIED IDEOGRAPH
+0x8C41	0x7A9F	#CJK UNIFIED IDEOGRAPH
+0x8C42	0x6C93	#CJK UNIFIED IDEOGRAPH
+0x8C43	0x9774	#CJK UNIFIED IDEOGRAPH
+0x8C44	0x8F61	#CJK UNIFIED IDEOGRAPH
+0x8C45	0x7AAA	#CJK UNIFIED IDEOGRAPH
+0x8C46	0x718A	#CJK UNIFIED IDEOGRAPH
+0x8C47	0x9688	#CJK UNIFIED IDEOGRAPH
+0x8C48	0x7C82	#CJK UNIFIED IDEOGRAPH
+0x8C49	0x6817	#CJK UNIFIED IDEOGRAPH
+0x8C4A	0x7E70	#CJK UNIFIED IDEOGRAPH
+0x8C4B	0x6851	#CJK UNIFIED IDEOGRAPH
+0x8C4C	0x936C	#CJK UNIFIED IDEOGRAPH
+0x8C4D	0x52F2	#CJK UNIFIED IDEOGRAPH
+0x8C4E	0x541B	#CJK UNIFIED IDEOGRAPH
+0x8C4F	0x85AB	#CJK UNIFIED IDEOGRAPH
+0x8C50	0x8A13	#CJK UNIFIED IDEOGRAPH
+0x8C51	0x7FA4	#CJK UNIFIED IDEOGRAPH
+0x8C52	0x8ECD	#CJK UNIFIED IDEOGRAPH
+0x8C53	0x90E1	#CJK UNIFIED IDEOGRAPH
+0x8C54	0x5366	#CJK UNIFIED IDEOGRAPH
+0x8C55	0x8888	#CJK UNIFIED IDEOGRAPH
+0x8C56	0x7941	#CJK UNIFIED IDEOGRAPH
+0x8C57	0x4FC2	#CJK UNIFIED IDEOGRAPH
+0x8C58	0x50BE	#CJK UNIFIED IDEOGRAPH
+0x8C59	0x5211	#CJK UNIFIED IDEOGRAPH
+0x8C5A	0x5144	#CJK UNIFIED IDEOGRAPH
+0x8C5B	0x5553	#CJK UNIFIED IDEOGRAPH
+0x8C5C	0x572D	#CJK UNIFIED IDEOGRAPH
+0x8C5D	0x73EA	#CJK UNIFIED IDEOGRAPH
+0x8C5E	0x578B	#CJK UNIFIED IDEOGRAPH
+0x8C5F	0x5951	#CJK UNIFIED IDEOGRAPH
+0x8C60	0x5F62	#CJK UNIFIED IDEOGRAPH
+0x8C61	0x5F84	#CJK UNIFIED IDEOGRAPH
+0x8C62	0x6075	#CJK UNIFIED IDEOGRAPH
+0x8C63	0x6176	#CJK UNIFIED IDEOGRAPH
+0x8C64	0x6167	#CJK UNIFIED IDEOGRAPH
+0x8C65	0x61A9	#CJK UNIFIED IDEOGRAPH
+0x8C66	0x63B2	#CJK UNIFIED IDEOGRAPH
+0x8C67	0x643A	#CJK UNIFIED IDEOGRAPH
+0x8C68	0x656C	#CJK UNIFIED IDEOGRAPH
+0x8C69	0x666F	#CJK UNIFIED IDEOGRAPH
+0x8C6A	0x6842	#CJK UNIFIED IDEOGRAPH
+0x8C6B	0x6E13	#CJK UNIFIED IDEOGRAPH
+0x8C6C	0x7566	#CJK UNIFIED IDEOGRAPH
+0x8C6D	0x7A3D	#CJK UNIFIED IDEOGRAPH
+0x8C6E	0x7CFB	#CJK UNIFIED IDEOGRAPH
+0x8C6F	0x7D4C	#CJK UNIFIED IDEOGRAPH
+0x8C70	0x7D99	#CJK UNIFIED IDEOGRAPH
+0x8C71	0x7E4B	#CJK UNIFIED IDEOGRAPH
+0x8C72	0x7F6B	#CJK UNIFIED IDEOGRAPH
+0x8C73	0x830E	#CJK UNIFIED IDEOGRAPH
+0x8C74	0x834A	#CJK UNIFIED IDEOGRAPH
+0x8C75	0x86CD	#CJK UNIFIED IDEOGRAPH
+0x8C76	0x8A08	#CJK UNIFIED IDEOGRAPH
+0x8C77	0x8A63	#CJK UNIFIED IDEOGRAPH
+0x8C78	0x8B66	#CJK UNIFIED IDEOGRAPH
+0x8C79	0x8EFD	#CJK UNIFIED IDEOGRAPH
+0x8C7A	0x981A	#CJK UNIFIED IDEOGRAPH
+0x8C7B	0x9D8F	#CJK UNIFIED IDEOGRAPH
+0x8C7C	0x82B8	#CJK UNIFIED IDEOGRAPH
+0x8C7D	0x8FCE	#CJK UNIFIED IDEOGRAPH
+0x8C7E	0x9BE8	#CJK UNIFIED IDEOGRAPH
+0x8C80	0x5287	#CJK UNIFIED IDEOGRAPH
+0x8C81	0x621F	#CJK UNIFIED IDEOGRAPH
+0x8C82	0x6483	#CJK UNIFIED IDEOGRAPH
+0x8C83	0x6FC0	#CJK UNIFIED IDEOGRAPH
+0x8C84	0x9699	#CJK UNIFIED IDEOGRAPH
+0x8C85	0x6841	#CJK UNIFIED IDEOGRAPH
+0x8C86	0x5091	#CJK UNIFIED IDEOGRAPH
+0x8C87	0x6B20	#CJK UNIFIED IDEOGRAPH
+0x8C88	0x6C7A	#CJK UNIFIED IDEOGRAPH
+0x8C89	0x6F54	#CJK UNIFIED IDEOGRAPH
+0x8C8A	0x7A74	#CJK UNIFIED IDEOGRAPH
+0x8C8B	0x7D50	#CJK UNIFIED IDEOGRAPH
+0x8C8C	0x8840	#CJK UNIFIED IDEOGRAPH
+0x8C8D	0x8A23	#CJK UNIFIED IDEOGRAPH
+0x8C8E	0x6708	#CJK UNIFIED IDEOGRAPH
+0x8C8F	0x4EF6	#CJK UNIFIED IDEOGRAPH
+0x8C90	0x5039	#CJK UNIFIED IDEOGRAPH
+0x8C91	0x5026	#CJK UNIFIED IDEOGRAPH
+0x8C92	0x5065	#CJK UNIFIED IDEOGRAPH
+0x8C93	0x517C	#CJK UNIFIED IDEOGRAPH
+0x8C94	0x5238	#CJK UNIFIED IDEOGRAPH
+0x8C95	0x5263	#CJK UNIFIED IDEOGRAPH
+0x8C96	0x55A7	#CJK UNIFIED IDEOGRAPH
+0x8C97	0x570F	#CJK UNIFIED IDEOGRAPH
+0x8C98	0x5805	#CJK UNIFIED IDEOGRAPH
+0x8C99	0x5ACC	#CJK UNIFIED IDEOGRAPH
+0x8C9A	0x5EFA	#CJK UNIFIED IDEOGRAPH
+0x8C9B	0x61B2	#CJK UNIFIED IDEOGRAPH
+0x8C9C	0x61F8	#CJK UNIFIED IDEOGRAPH
+0x8C9D	0x62F3	#CJK UNIFIED IDEOGRAPH
+0x8C9E	0x6372	#CJK UNIFIED IDEOGRAPH
+0x8C9F	0x691C	#CJK UNIFIED IDEOGRAPH
+0x8CA0	0x6A29	#CJK UNIFIED IDEOGRAPH
+0x8CA1	0x727D	#CJK UNIFIED IDEOGRAPH
+0x8CA2	0x72AC	#CJK UNIFIED IDEOGRAPH
+0x8CA3	0x732E	#CJK UNIFIED IDEOGRAPH
+0x8CA4	0x7814	#CJK UNIFIED IDEOGRAPH
+0x8CA5	0x786F	#CJK UNIFIED IDEOGRAPH
+0x8CA6	0x7D79	#CJK UNIFIED IDEOGRAPH
+0x8CA7	0x770C	#CJK UNIFIED IDEOGRAPH
+0x8CA8	0x80A9	#CJK UNIFIED IDEOGRAPH
+0x8CA9	0x898B	#CJK UNIFIED IDEOGRAPH
+0x8CAA	0x8B19	#CJK UNIFIED IDEOGRAPH
+0x8CAB	0x8CE2	#CJK UNIFIED IDEOGRAPH
+0x8CAC	0x8ED2	#CJK UNIFIED IDEOGRAPH
+0x8CAD	0x9063	#CJK UNIFIED IDEOGRAPH
+0x8CAE	0x9375	#CJK UNIFIED IDEOGRAPH
+0x8CAF	0x967A	#CJK UNIFIED IDEOGRAPH
+0x8CB0	0x9855	#CJK UNIFIED IDEOGRAPH
+0x8CB1	0x9A13	#CJK UNIFIED IDEOGRAPH
+0x8CB2	0x9E78	#CJK UNIFIED IDEOGRAPH
+0x8CB3	0x5143	#CJK UNIFIED IDEOGRAPH
+0x8CB4	0x539F	#CJK UNIFIED IDEOGRAPH
+0x8CB5	0x53B3	#CJK UNIFIED IDEOGRAPH
+0x8CB6	0x5E7B	#CJK UNIFIED IDEOGRAPH
+0x8CB7	0x5F26	#CJK UNIFIED IDEOGRAPH
+0x8CB8	0x6E1B	#CJK UNIFIED IDEOGRAPH
+0x8CB9	0x6E90	#CJK UNIFIED IDEOGRAPH
+0x8CBA	0x7384	#CJK UNIFIED IDEOGRAPH
+0x8CBB	0x73FE	#CJK UNIFIED IDEOGRAPH
+0x8CBC	0x7D43	#CJK UNIFIED IDEOGRAPH
+0x8CBD	0x8237	#CJK UNIFIED IDEOGRAPH
+0x8CBE	0x8A00	#CJK UNIFIED IDEOGRAPH
+0x8CBF	0x8AFA	#CJK UNIFIED IDEOGRAPH
+0x8CC0	0x9650	#CJK UNIFIED IDEOGRAPH
+0x8CC1	0x4E4E	#CJK UNIFIED IDEOGRAPH
+0x8CC2	0x500B	#CJK UNIFIED IDEOGRAPH
+0x8CC3	0x53E4	#CJK UNIFIED IDEOGRAPH
+0x8CC4	0x547C	#CJK UNIFIED IDEOGRAPH
+0x8CC5	0x56FA	#CJK UNIFIED IDEOGRAPH
+0x8CC6	0x59D1	#CJK UNIFIED IDEOGRAPH
+0x8CC7	0x5B64	#CJK UNIFIED IDEOGRAPH
+0x8CC8	0x5DF1	#CJK UNIFIED IDEOGRAPH
+0x8CC9	0x5EAB	#CJK UNIFIED IDEOGRAPH
+0x8CCA	0x5F27	#CJK UNIFIED IDEOGRAPH
+0x8CCB	0x6238	#CJK UNIFIED IDEOGRAPH
+0x8CCC	0x6545	#CJK UNIFIED IDEOGRAPH
+0x8CCD	0x67AF	#CJK UNIFIED IDEOGRAPH
+0x8CCE	0x6E56	#CJK UNIFIED IDEOGRAPH
+0x8CCF	0x72D0	#CJK UNIFIED IDEOGRAPH
+0x8CD0	0x7CCA	#CJK UNIFIED IDEOGRAPH
+0x8CD1	0x88B4	#CJK UNIFIED IDEOGRAPH
+0x8CD2	0x80A1	#CJK UNIFIED IDEOGRAPH
+0x8CD3	0x80E1	#CJK UNIFIED IDEOGRAPH
+0x8CD4	0x83F0	#CJK UNIFIED IDEOGRAPH
+0x8CD5	0x864E	#CJK UNIFIED IDEOGRAPH
+0x8CD6	0x8A87	#CJK UNIFIED IDEOGRAPH
+0x8CD7	0x8DE8	#CJK UNIFIED IDEOGRAPH
+0x8CD8	0x9237	#CJK UNIFIED IDEOGRAPH
+0x8CD9	0x96C7	#CJK UNIFIED IDEOGRAPH
+0x8CDA	0x9867	#CJK UNIFIED IDEOGRAPH
+0x8CDB	0x9F13	#CJK UNIFIED IDEOGRAPH
+0x8CDC	0x4E94	#CJK UNIFIED IDEOGRAPH
+0x8CDD	0x4E92	#CJK UNIFIED IDEOGRAPH
+0x8CDE	0x4F0D	#CJK UNIFIED IDEOGRAPH
+0x8CDF	0x5348	#CJK UNIFIED IDEOGRAPH
+0x8CE0	0x5449	#CJK UNIFIED IDEOGRAPH
+0x8CE1	0x543E	#CJK UNIFIED IDEOGRAPH
+0x8CE2	0x5A2F	#CJK UNIFIED IDEOGRAPH
+0x8CE3	0x5F8C	#CJK UNIFIED IDEOGRAPH
+0x8CE4	0x5FA1	#CJK UNIFIED IDEOGRAPH
+0x8CE5	0x609F	#CJK UNIFIED IDEOGRAPH
+0x8CE6	0x68A7	#CJK UNIFIED IDEOGRAPH
+0x8CE7	0x6A8E	#CJK UNIFIED IDEOGRAPH
+0x8CE8	0x745A	#CJK UNIFIED IDEOGRAPH
+0x8CE9	0x7881	#CJK UNIFIED IDEOGRAPH
+0x8CEA	0x8A9E	#CJK UNIFIED IDEOGRAPH
+0x8CEB	0x8AA4	#CJK UNIFIED IDEOGRAPH
+0x8CEC	0x8B77	#CJK UNIFIED IDEOGRAPH
+0x8CED	0x9190	#CJK UNIFIED IDEOGRAPH
+0x8CEE	0x4E5E	#CJK UNIFIED IDEOGRAPH
+0x8CEF	0x9BC9	#CJK UNIFIED IDEOGRAPH
+0x8CF0	0x4EA4	#CJK UNIFIED IDEOGRAPH
+0x8CF1	0x4F7C	#CJK UNIFIED IDEOGRAPH
+0x8CF2	0x4FAF	#CJK UNIFIED IDEOGRAPH
+0x8CF3	0x5019	#CJK UNIFIED IDEOGRAPH
+0x8CF4	0x5016	#CJK UNIFIED IDEOGRAPH
+0x8CF5	0x5149	#CJK UNIFIED IDEOGRAPH
+0x8CF6	0x516C	#CJK UNIFIED IDEOGRAPH
+0x8CF7	0x529F	#CJK UNIFIED IDEOGRAPH
+0x8CF8	0x52B9	#CJK UNIFIED IDEOGRAPH
+0x8CF9	0x52FE	#CJK UNIFIED IDEOGRAPH
+0x8CFA	0x539A	#CJK UNIFIED IDEOGRAPH
+0x8CFB	0x53E3	#CJK UNIFIED IDEOGRAPH
+0x8CFC	0x5411	#CJK UNIFIED IDEOGRAPH
+0x8D40	0x540E	#CJK UNIFIED IDEOGRAPH
+0x8D41	0x5589	#CJK UNIFIED IDEOGRAPH
+0x8D42	0x5751	#CJK UNIFIED IDEOGRAPH
+0x8D43	0x57A2	#CJK UNIFIED IDEOGRAPH
+0x8D44	0x597D	#CJK UNIFIED IDEOGRAPH
+0x8D45	0x5B54	#CJK UNIFIED IDEOGRAPH
+0x8D46	0x5B5D	#CJK UNIFIED IDEOGRAPH
+0x8D47	0x5B8F	#CJK UNIFIED IDEOGRAPH
+0x8D48	0x5DE5	#CJK UNIFIED IDEOGRAPH
+0x8D49	0x5DE7	#CJK UNIFIED IDEOGRAPH
+0x8D4A	0x5DF7	#CJK UNIFIED IDEOGRAPH
+0x8D4B	0x5E78	#CJK UNIFIED IDEOGRAPH
+0x8D4C	0x5E83	#CJK UNIFIED IDEOGRAPH
+0x8D4D	0x5E9A	#CJK UNIFIED IDEOGRAPH
+0x8D4E	0x5EB7	#CJK UNIFIED IDEOGRAPH
+0x8D4F	0x5F18	#CJK UNIFIED IDEOGRAPH
+0x8D50	0x6052	#CJK UNIFIED IDEOGRAPH
+0x8D51	0x614C	#CJK UNIFIED IDEOGRAPH
+0x8D52	0x6297	#CJK UNIFIED IDEOGRAPH
+0x8D53	0x62D8	#CJK UNIFIED IDEOGRAPH
+0x8D54	0x63A7	#CJK UNIFIED IDEOGRAPH
+0x8D55	0x653B	#CJK UNIFIED IDEOGRAPH
+0x8D56	0x6602	#CJK UNIFIED IDEOGRAPH
+0x8D57	0x6643	#CJK UNIFIED IDEOGRAPH
+0x8D58	0x66F4	#CJK UNIFIED IDEOGRAPH
+0x8D59	0x676D	#CJK UNIFIED IDEOGRAPH
+0x8D5A	0x6821	#CJK UNIFIED IDEOGRAPH
+0x8D5B	0x6897	#CJK UNIFIED IDEOGRAPH
+0x8D5C	0x69CB	#CJK UNIFIED IDEOGRAPH
+0x8D5D	0x6C5F	#CJK UNIFIED IDEOGRAPH
+0x8D5E	0x6D2A	#CJK UNIFIED IDEOGRAPH
+0x8D5F	0x6D69	#CJK UNIFIED IDEOGRAPH
+0x8D60	0x6E2F	#CJK UNIFIED IDEOGRAPH
+0x8D61	0x6E9D	#CJK UNIFIED IDEOGRAPH
+0x8D62	0x7532	#CJK UNIFIED IDEOGRAPH
+0x8D63	0x7687	#CJK UNIFIED IDEOGRAPH
+0x8D64	0x786C	#CJK UNIFIED IDEOGRAPH
+0x8D65	0x7A3F	#CJK UNIFIED IDEOGRAPH
+0x8D66	0x7CE0	#CJK UNIFIED IDEOGRAPH
+0x8D67	0x7D05	#CJK UNIFIED IDEOGRAPH
+0x8D68	0x7D18	#CJK UNIFIED IDEOGRAPH
+0x8D69	0x7D5E	#CJK UNIFIED IDEOGRAPH
+0x8D6A	0x7DB1	#CJK UNIFIED IDEOGRAPH
+0x8D6B	0x8015	#CJK UNIFIED IDEOGRAPH
+0x8D6C	0x8003	#CJK UNIFIED IDEOGRAPH
+0x8D6D	0x80AF	#CJK UNIFIED IDEOGRAPH
+0x8D6E	0x80B1	#CJK UNIFIED IDEOGRAPH
+0x8D6F	0x8154	#CJK UNIFIED IDEOGRAPH
+0x8D70	0x818F	#CJK UNIFIED IDEOGRAPH
+0x8D71	0x822A	#CJK UNIFIED IDEOGRAPH
+0x8D72	0x8352	#CJK UNIFIED IDEOGRAPH
+0x8D73	0x884C	#CJK UNIFIED IDEOGRAPH
+0x8D74	0x8861	#CJK UNIFIED IDEOGRAPH
+0x8D75	0x8B1B	#CJK UNIFIED IDEOGRAPH
+0x8D76	0x8CA2	#CJK UNIFIED IDEOGRAPH
+0x8D77	0x8CFC	#CJK UNIFIED IDEOGRAPH
+0x8D78	0x90CA	#CJK UNIFIED IDEOGRAPH
+0x8D79	0x9175	#CJK UNIFIED IDEOGRAPH
+0x8D7A	0x9271	#CJK UNIFIED IDEOGRAPH
+0x8D7B	0x783F	#CJK UNIFIED IDEOGRAPH
+0x8D7C	0x92FC	#CJK UNIFIED IDEOGRAPH
+0x8D7D	0x95A4	#CJK UNIFIED IDEOGRAPH
+0x8D7E	0x964D	#CJK UNIFIED IDEOGRAPH
+0x8D80	0x9805	#CJK UNIFIED IDEOGRAPH
+0x8D81	0x9999	#CJK UNIFIED IDEOGRAPH
+0x8D82	0x9AD8	#CJK UNIFIED IDEOGRAPH
+0x8D83	0x9D3B	#CJK UNIFIED IDEOGRAPH
+0x8D84	0x525B	#CJK UNIFIED IDEOGRAPH
+0x8D85	0x52AB	#CJK UNIFIED IDEOGRAPH
+0x8D86	0x53F7	#CJK UNIFIED IDEOGRAPH
+0x8D87	0x5408	#CJK UNIFIED IDEOGRAPH
+0x8D88	0x58D5	#CJK UNIFIED IDEOGRAPH
+0x8D89	0x62F7	#CJK UNIFIED IDEOGRAPH
+0x8D8A	0x6FE0	#CJK UNIFIED IDEOGRAPH
+0x8D8B	0x8C6A	#CJK UNIFIED IDEOGRAPH
+0x8D8C	0x8F5F	#CJK UNIFIED IDEOGRAPH
+0x8D8D	0x9EB9	#CJK UNIFIED IDEOGRAPH
+0x8D8E	0x514B	#CJK UNIFIED IDEOGRAPH
+0x8D8F	0x523B	#CJK UNIFIED IDEOGRAPH
+0x8D90	0x544A	#CJK UNIFIED IDEOGRAPH
+0x8D91	0x56FD	#CJK UNIFIED IDEOGRAPH
+0x8D92	0x7A40	#CJK UNIFIED IDEOGRAPH
+0x8D93	0x9177	#CJK UNIFIED IDEOGRAPH
+0x8D94	0x9D60	#CJK UNIFIED IDEOGRAPH
+0x8D95	0x9ED2	#CJK UNIFIED IDEOGRAPH
+0x8D96	0x7344	#CJK UNIFIED IDEOGRAPH
+0x8D97	0x6F09	#CJK UNIFIED IDEOGRAPH
+0x8D98	0x8170	#CJK UNIFIED IDEOGRAPH
+0x8D99	0x7511	#CJK UNIFIED IDEOGRAPH
+0x8D9A	0x5FFD	#CJK UNIFIED IDEOGRAPH
+0x8D9B	0x60DA	#CJK UNIFIED IDEOGRAPH
+0x8D9C	0x9AA8	#CJK UNIFIED IDEOGRAPH
+0x8D9D	0x72DB	#CJK UNIFIED IDEOGRAPH
+0x8D9E	0x8FBC	#CJK UNIFIED IDEOGRAPH
+0x8D9F	0x6B64	#CJK UNIFIED IDEOGRAPH
+0x8DA0	0x9803	#CJK UNIFIED IDEOGRAPH
+0x8DA1	0x4ECA	#CJK UNIFIED IDEOGRAPH
+0x8DA2	0x56F0	#CJK UNIFIED IDEOGRAPH
+0x8DA3	0x5764	#CJK UNIFIED IDEOGRAPH
+0x8DA4	0x58BE	#CJK UNIFIED IDEOGRAPH
+0x8DA5	0x5A5A	#CJK UNIFIED IDEOGRAPH
+0x8DA6	0x6068	#CJK UNIFIED IDEOGRAPH
+0x8DA7	0x61C7	#CJK UNIFIED IDEOGRAPH
+0x8DA8	0x660F	#CJK UNIFIED IDEOGRAPH
+0x8DA9	0x6606	#CJK UNIFIED IDEOGRAPH
+0x8DAA	0x6839	#CJK UNIFIED IDEOGRAPH
+0x8DAB	0x68B1	#CJK UNIFIED IDEOGRAPH
+0x8DAC	0x6DF7	#CJK UNIFIED IDEOGRAPH
+0x8DAD	0x75D5	#CJK UNIFIED IDEOGRAPH
+0x8DAE	0x7D3A	#CJK UNIFIED IDEOGRAPH
+0x8DAF	0x826E	#CJK UNIFIED IDEOGRAPH
+0x8DB0	0x9B42	#CJK UNIFIED IDEOGRAPH
+0x8DB1	0x4E9B	#CJK UNIFIED IDEOGRAPH
+0x8DB2	0x4F50	#CJK UNIFIED IDEOGRAPH
+0x8DB3	0x53C9	#CJK UNIFIED IDEOGRAPH
+0x8DB4	0x5506	#CJK UNIFIED IDEOGRAPH
+0x8DB5	0x5D6F	#CJK UNIFIED IDEOGRAPH
+0x8DB6	0x5DE6	#CJK UNIFIED IDEOGRAPH
+0x8DB7	0x5DEE	#CJK UNIFIED IDEOGRAPH
+0x8DB8	0x67FB	#CJK UNIFIED IDEOGRAPH
+0x8DB9	0x6C99	#CJK UNIFIED IDEOGRAPH
+0x8DBA	0x7473	#CJK UNIFIED IDEOGRAPH
+0x8DBB	0x7802	#CJK UNIFIED IDEOGRAPH
+0x8DBC	0x8A50	#CJK UNIFIED IDEOGRAPH
+0x8DBD	0x9396	#CJK UNIFIED IDEOGRAPH
+0x8DBE	0x88DF	#CJK UNIFIED IDEOGRAPH
+0x8DBF	0x5750	#CJK UNIFIED IDEOGRAPH
+0x8DC0	0x5EA7	#CJK UNIFIED IDEOGRAPH
+0x8DC1	0x632B	#CJK UNIFIED IDEOGRAPH
+0x8DC2	0x50B5	#CJK UNIFIED IDEOGRAPH
+0x8DC3	0x50AC	#CJK UNIFIED IDEOGRAPH
+0x8DC4	0x518D	#CJK UNIFIED IDEOGRAPH
+0x8DC5	0x6700	#CJK UNIFIED IDEOGRAPH
+0x8DC6	0x54C9	#CJK UNIFIED IDEOGRAPH
+0x8DC7	0x585E	#CJK UNIFIED IDEOGRAPH
+0x8DC8	0x59BB	#CJK UNIFIED IDEOGRAPH
+0x8DC9	0x5BB0	#CJK UNIFIED IDEOGRAPH
+0x8DCA	0x5F69	#CJK UNIFIED IDEOGRAPH
+0x8DCB	0x624D	#CJK UNIFIED IDEOGRAPH
+0x8DCC	0x63A1	#CJK UNIFIED IDEOGRAPH
+0x8DCD	0x683D	#CJK UNIFIED IDEOGRAPH
+0x8DCE	0x6B73	#CJK UNIFIED IDEOGRAPH
+0x8DCF	0x6E08	#CJK UNIFIED IDEOGRAPH
+0x8DD0	0x707D	#CJK UNIFIED IDEOGRAPH
+0x8DD1	0x91C7	#CJK UNIFIED IDEOGRAPH
+0x8DD2	0x7280	#CJK UNIFIED IDEOGRAPH
+0x8DD3	0x7815	#CJK UNIFIED IDEOGRAPH
+0x8DD4	0x7826	#CJK UNIFIED IDEOGRAPH
+0x8DD5	0x796D	#CJK UNIFIED IDEOGRAPH
+0x8DD6	0x658E	#CJK UNIFIED IDEOGRAPH
+0x8DD7	0x7D30	#CJK UNIFIED IDEOGRAPH
+0x8DD8	0x83DC	#CJK UNIFIED IDEOGRAPH
+0x8DD9	0x88C1	#CJK UNIFIED IDEOGRAPH
+0x8DDA	0x8F09	#CJK UNIFIED IDEOGRAPH
+0x8DDB	0x969B	#CJK UNIFIED IDEOGRAPH
+0x8DDC	0x5264	#CJK UNIFIED IDEOGRAPH
+0x8DDD	0x5728	#CJK UNIFIED IDEOGRAPH
+0x8DDE	0x6750	#CJK UNIFIED IDEOGRAPH
+0x8DDF	0x7F6A	#CJK UNIFIED IDEOGRAPH
+0x8DE0	0x8CA1	#CJK UNIFIED IDEOGRAPH
+0x8DE1	0x51B4	#CJK UNIFIED IDEOGRAPH
+0x8DE2	0x5742	#CJK UNIFIED IDEOGRAPH
+0x8DE3	0x962A	#CJK UNIFIED IDEOGRAPH
+0x8DE4	0x583A	#CJK UNIFIED IDEOGRAPH
+0x8DE5	0x698A	#CJK UNIFIED IDEOGRAPH
+0x8DE6	0x80B4	#CJK UNIFIED IDEOGRAPH
+0x8DE7	0x54B2	#CJK UNIFIED IDEOGRAPH
+0x8DE8	0x5D0E	#CJK UNIFIED IDEOGRAPH
+0x8DE9	0x57FC	#CJK UNIFIED IDEOGRAPH
+0x8DEA	0x7895	#CJK UNIFIED IDEOGRAPH
+0x8DEB	0x9DFA	#CJK UNIFIED IDEOGRAPH
+0x8DEC	0x4F5C	#CJK UNIFIED IDEOGRAPH
+0x8DED	0x524A	#CJK UNIFIED IDEOGRAPH
+0x8DEE	0x548B	#CJK UNIFIED IDEOGRAPH
+0x8DEF	0x643E	#CJK UNIFIED IDEOGRAPH
+0x8DF0	0x6628	#CJK UNIFIED IDEOGRAPH
+0x8DF1	0x6714	#CJK UNIFIED IDEOGRAPH
+0x8DF2	0x67F5	#CJK UNIFIED IDEOGRAPH
+0x8DF3	0x7A84	#CJK UNIFIED IDEOGRAPH
+0x8DF4	0x7B56	#CJK UNIFIED IDEOGRAPH
+0x8DF5	0x7D22	#CJK UNIFIED IDEOGRAPH
+0x8DF6	0x932F	#CJK UNIFIED IDEOGRAPH
+0x8DF7	0x685C	#CJK UNIFIED IDEOGRAPH
+0x8DF8	0x9BAD	#CJK UNIFIED IDEOGRAPH
+0x8DF9	0x7B39	#CJK UNIFIED IDEOGRAPH
+0x8DFA	0x5319	#CJK UNIFIED IDEOGRAPH
+0x8DFB	0x518A	#CJK UNIFIED IDEOGRAPH
+0x8DFC	0x5237	#CJK UNIFIED IDEOGRAPH
+0x8E40	0x5BDF	#CJK UNIFIED IDEOGRAPH
+0x8E41	0x62F6	#CJK UNIFIED IDEOGRAPH
+0x8E42	0x64AE	#CJK UNIFIED IDEOGRAPH
+0x8E43	0x64E6	#CJK UNIFIED IDEOGRAPH
+0x8E44	0x672D	#CJK UNIFIED IDEOGRAPH
+0x8E45	0x6BBA	#CJK UNIFIED IDEOGRAPH
+0x8E46	0x85A9	#CJK UNIFIED IDEOGRAPH
+0x8E47	0x96D1	#CJK UNIFIED IDEOGRAPH
+0x8E48	0x7690	#CJK UNIFIED IDEOGRAPH
+0x8E49	0x9BD6	#CJK UNIFIED IDEOGRAPH
+0x8E4A	0x634C	#CJK UNIFIED IDEOGRAPH
+0x8E4B	0x9306	#CJK UNIFIED IDEOGRAPH
+0x8E4C	0x9BAB	#CJK UNIFIED IDEOGRAPH
+0x8E4D	0x76BF	#CJK UNIFIED IDEOGRAPH
+0x8E4E	0x6652	#CJK UNIFIED IDEOGRAPH
+0x8E4F	0x4E09	#CJK UNIFIED IDEOGRAPH
+0x8E50	0x5098	#CJK UNIFIED IDEOGRAPH
+0x8E51	0x53C2	#CJK UNIFIED IDEOGRAPH
+0x8E52	0x5C71	#CJK UNIFIED IDEOGRAPH
+0x8E53	0x60E8	#CJK UNIFIED IDEOGRAPH
+0x8E54	0x6492	#CJK UNIFIED IDEOGRAPH
+0x8E55	0x6563	#CJK UNIFIED IDEOGRAPH
+0x8E56	0x685F	#CJK UNIFIED IDEOGRAPH
+0x8E57	0x71E6	#CJK UNIFIED IDEOGRAPH
+0x8E58	0x73CA	#CJK UNIFIED IDEOGRAPH
+0x8E59	0x7523	#CJK UNIFIED IDEOGRAPH
+0x8E5A	0x7B97	#CJK UNIFIED IDEOGRAPH
+0x8E5B	0x7E82	#CJK UNIFIED IDEOGRAPH
+0x8E5C	0x8695	#CJK UNIFIED IDEOGRAPH
+0x8E5D	0x8B83	#CJK UNIFIED IDEOGRAPH
+0x8E5E	0x8CDB	#CJK UNIFIED IDEOGRAPH
+0x8E5F	0x9178	#CJK UNIFIED IDEOGRAPH
+0x8E60	0x9910	#CJK UNIFIED IDEOGRAPH
+0x8E61	0x65AC	#CJK UNIFIED IDEOGRAPH
+0x8E62	0x66AB	#CJK UNIFIED IDEOGRAPH
+0x8E63	0x6B8B	#CJK UNIFIED IDEOGRAPH
+0x8E64	0x4ED5	#CJK UNIFIED IDEOGRAPH
+0x8E65	0x4ED4	#CJK UNIFIED IDEOGRAPH
+0x8E66	0x4F3A	#CJK UNIFIED IDEOGRAPH
+0x8E67	0x4F7F	#CJK UNIFIED IDEOGRAPH
+0x8E68	0x523A	#CJK UNIFIED IDEOGRAPH
+0x8E69	0x53F8	#CJK UNIFIED IDEOGRAPH
+0x8E6A	0x53F2	#CJK UNIFIED IDEOGRAPH
+0x8E6B	0x55E3	#CJK UNIFIED IDEOGRAPH
+0x8E6C	0x56DB	#CJK UNIFIED IDEOGRAPH
+0x8E6D	0x58EB	#CJK UNIFIED IDEOGRAPH
+0x8E6E	0x59CB	#CJK UNIFIED IDEOGRAPH
+0x8E6F	0x59C9	#CJK UNIFIED IDEOGRAPH
+0x8E70	0x59FF	#CJK UNIFIED IDEOGRAPH
+0x8E71	0x5B50	#CJK UNIFIED IDEOGRAPH
+0x8E72	0x5C4D	#CJK UNIFIED IDEOGRAPH
+0x8E73	0x5E02	#CJK UNIFIED IDEOGRAPH
+0x8E74	0x5E2B	#CJK UNIFIED IDEOGRAPH
+0x8E75	0x5FD7	#CJK UNIFIED IDEOGRAPH
+0x8E76	0x601D	#CJK UNIFIED IDEOGRAPH
+0x8E77	0x6307	#CJK UNIFIED IDEOGRAPH
+0x8E78	0x652F	#CJK UNIFIED IDEOGRAPH
+0x8E79	0x5B5C	#CJK UNIFIED IDEOGRAPH
+0x8E7A	0x65AF	#CJK UNIFIED IDEOGRAPH
+0x8E7B	0x65BD	#CJK UNIFIED IDEOGRAPH
+0x8E7C	0x65E8	#CJK UNIFIED IDEOGRAPH
+0x8E7D	0x679D	#CJK UNIFIED IDEOGRAPH
+0x8E7E	0x6B62	#CJK UNIFIED IDEOGRAPH
+0x8E80	0x6B7B	#CJK UNIFIED IDEOGRAPH
+0x8E81	0x6C0F	#CJK UNIFIED IDEOGRAPH
+0x8E82	0x7345	#CJK UNIFIED IDEOGRAPH
+0x8E83	0x7949	#CJK UNIFIED IDEOGRAPH
+0x8E84	0x79C1	#CJK UNIFIED IDEOGRAPH
+0x8E85	0x7CF8	#CJK UNIFIED IDEOGRAPH
+0x8E86	0x7D19	#CJK UNIFIED IDEOGRAPH
+0x8E87	0x7D2B	#CJK UNIFIED IDEOGRAPH
+0x8E88	0x80A2	#CJK UNIFIED IDEOGRAPH
+0x8E89	0x8102	#CJK UNIFIED IDEOGRAPH
+0x8E8A	0x81F3	#CJK UNIFIED IDEOGRAPH
+0x8E8B	0x8996	#CJK UNIFIED IDEOGRAPH
+0x8E8C	0x8A5E	#CJK UNIFIED IDEOGRAPH
+0x8E8D	0x8A69	#CJK UNIFIED IDEOGRAPH
+0x8E8E	0x8A66	#CJK UNIFIED IDEOGRAPH
+0x8E8F	0x8A8C	#CJK UNIFIED IDEOGRAPH
+0x8E90	0x8AEE	#CJK UNIFIED IDEOGRAPH
+0x8E91	0x8CC7	#CJK UNIFIED IDEOGRAPH
+0x8E92	0x8CDC	#CJK UNIFIED IDEOGRAPH
+0x8E93	0x96CC	#CJK UNIFIED IDEOGRAPH
+0x8E94	0x98FC	#CJK UNIFIED IDEOGRAPH
+0x8E95	0x6B6F	#CJK UNIFIED IDEOGRAPH
+0x8E96	0x4E8B	#CJK UNIFIED IDEOGRAPH
+0x8E97	0x4F3C	#CJK UNIFIED IDEOGRAPH
+0x8E98	0x4F8D	#CJK UNIFIED IDEOGRAPH
+0x8E99	0x5150	#CJK UNIFIED IDEOGRAPH
+0x8E9A	0x5B57	#CJK UNIFIED IDEOGRAPH
+0x8E9B	0x5BFA	#CJK UNIFIED IDEOGRAPH
+0x8E9C	0x6148	#CJK UNIFIED IDEOGRAPH
+0x8E9D	0x6301	#CJK UNIFIED IDEOGRAPH
+0x8E9E	0x6642	#CJK UNIFIED IDEOGRAPH
+0x8E9F	0x6B21	#CJK UNIFIED IDEOGRAPH
+0x8EA0	0x6ECB	#CJK UNIFIED IDEOGRAPH
+0x8EA1	0x6CBB	#CJK UNIFIED IDEOGRAPH
+0x8EA2	0x723E	#CJK UNIFIED IDEOGRAPH
+0x8EA3	0x74BD	#CJK UNIFIED IDEOGRAPH
+0x8EA4	0x75D4	#CJK UNIFIED IDEOGRAPH
+0x8EA5	0x78C1	#CJK UNIFIED IDEOGRAPH
+0x8EA6	0x793A	#CJK UNIFIED IDEOGRAPH
+0x8EA7	0x800C	#CJK UNIFIED IDEOGRAPH
+0x8EA8	0x8033	#CJK UNIFIED IDEOGRAPH
+0x8EA9	0x81EA	#CJK UNIFIED IDEOGRAPH
+0x8EAA	0x8494	#CJK UNIFIED IDEOGRAPH
+0x8EAB	0x8F9E	#CJK UNIFIED IDEOGRAPH
+0x8EAC	0x6C50	#CJK UNIFIED IDEOGRAPH
+0x8EAD	0x9E7F	#CJK UNIFIED IDEOGRAPH
+0x8EAE	0x5F0F	#CJK UNIFIED IDEOGRAPH
+0x8EAF	0x8B58	#CJK UNIFIED IDEOGRAPH
+0x8EB0	0x9D2B	#CJK UNIFIED IDEOGRAPH
+0x8EB1	0x7AFA	#CJK UNIFIED IDEOGRAPH
+0x8EB2	0x8EF8	#CJK UNIFIED IDEOGRAPH
+0x8EB3	0x5B8D	#CJK UNIFIED IDEOGRAPH
+0x8EB4	0x96EB	#CJK UNIFIED IDEOGRAPH
+0x8EB5	0x4E03	#CJK UNIFIED IDEOGRAPH
+0x8EB6	0x53F1	#CJK UNIFIED IDEOGRAPH
+0x8EB7	0x57F7	#CJK UNIFIED IDEOGRAPH
+0x8EB8	0x5931	#CJK UNIFIED IDEOGRAPH
+0x8EB9	0x5AC9	#CJK UNIFIED IDEOGRAPH
+0x8EBA	0x5BA4	#CJK UNIFIED IDEOGRAPH
+0x8EBB	0x6089	#CJK UNIFIED IDEOGRAPH
+0x8EBC	0x6E7F	#CJK UNIFIED IDEOGRAPH
+0x8EBD	0x6F06	#CJK UNIFIED IDEOGRAPH
+0x8EBE	0x75BE	#CJK UNIFIED IDEOGRAPH
+0x8EBF	0x8CEA	#CJK UNIFIED IDEOGRAPH
+0x8EC0	0x5B9F	#CJK UNIFIED IDEOGRAPH
+0x8EC1	0x8500	#CJK UNIFIED IDEOGRAPH
+0x8EC2	0x7BE0	#CJK UNIFIED IDEOGRAPH
+0x8EC3	0x5072	#CJK UNIFIED IDEOGRAPH
+0x8EC4	0x67F4	#CJK UNIFIED IDEOGRAPH
+0x8EC5	0x829D	#CJK UNIFIED IDEOGRAPH
+0x8EC6	0x5C61	#CJK UNIFIED IDEOGRAPH
+0x8EC7	0x854A	#CJK UNIFIED IDEOGRAPH
+0x8EC8	0x7E1E	#CJK UNIFIED IDEOGRAPH
+0x8EC9	0x820E	#CJK UNIFIED IDEOGRAPH
+0x8ECA	0x5199	#CJK UNIFIED IDEOGRAPH
+0x8ECB	0x5C04	#CJK UNIFIED IDEOGRAPH
+0x8ECC	0x6368	#CJK UNIFIED IDEOGRAPH
+0x8ECD	0x8D66	#CJK UNIFIED IDEOGRAPH
+0x8ECE	0x659C	#CJK UNIFIED IDEOGRAPH
+0x8ECF	0x716E	#CJK UNIFIED IDEOGRAPH
+0x8ED0	0x793E	#CJK UNIFIED IDEOGRAPH
+0x8ED1	0x7D17	#CJK UNIFIED IDEOGRAPH
+0x8ED2	0x8005	#CJK UNIFIED IDEOGRAPH
+0x8ED3	0x8B1D	#CJK UNIFIED IDEOGRAPH
+0x8ED4	0x8ECA	#CJK UNIFIED IDEOGRAPH
+0x8ED5	0x906E	#CJK UNIFIED IDEOGRAPH
+0x8ED6	0x86C7	#CJK UNIFIED IDEOGRAPH
+0x8ED7	0x90AA	#CJK UNIFIED IDEOGRAPH
+0x8ED8	0x501F	#CJK UNIFIED IDEOGRAPH
+0x8ED9	0x52FA	#CJK UNIFIED IDEOGRAPH
+0x8EDA	0x5C3A	#CJK UNIFIED IDEOGRAPH
+0x8EDB	0x6753	#CJK UNIFIED IDEOGRAPH
+0x8EDC	0x707C	#CJK UNIFIED IDEOGRAPH
+0x8EDD	0x7235	#CJK UNIFIED IDEOGRAPH
+0x8EDE	0x914C	#CJK UNIFIED IDEOGRAPH
+0x8EDF	0x91C8	#CJK UNIFIED IDEOGRAPH
+0x8EE0	0x932B	#CJK UNIFIED IDEOGRAPH
+0x8EE1	0x82E5	#CJK UNIFIED IDEOGRAPH
+0x8EE2	0x5BC2	#CJK UNIFIED IDEOGRAPH
+0x8EE3	0x5F31	#CJK UNIFIED IDEOGRAPH
+0x8EE4	0x60F9	#CJK UNIFIED IDEOGRAPH
+0x8EE5	0x4E3B	#CJK UNIFIED IDEOGRAPH
+0x8EE6	0x53D6	#CJK UNIFIED IDEOGRAPH
+0x8EE7	0x5B88	#CJK UNIFIED IDEOGRAPH
+0x8EE8	0x624B	#CJK UNIFIED IDEOGRAPH
+0x8EE9	0x6731	#CJK UNIFIED IDEOGRAPH
+0x8EEA	0x6B8A	#CJK UNIFIED IDEOGRAPH
+0x8EEB	0x72E9	#CJK UNIFIED IDEOGRAPH
+0x8EEC	0x73E0	#CJK UNIFIED IDEOGRAPH
+0x8EED	0x7A2E	#CJK UNIFIED IDEOGRAPH
+0x8EEE	0x816B	#CJK UNIFIED IDEOGRAPH
+0x8EEF	0x8DA3	#CJK UNIFIED IDEOGRAPH
+0x8EF0	0x9152	#CJK UNIFIED IDEOGRAPH
+0x8EF1	0x9996	#CJK UNIFIED IDEOGRAPH
+0x8EF2	0x5112	#CJK UNIFIED IDEOGRAPH
+0x8EF3	0x53D7	#CJK UNIFIED IDEOGRAPH
+0x8EF4	0x546A	#CJK UNIFIED IDEOGRAPH
+0x8EF5	0x5BFF	#CJK UNIFIED IDEOGRAPH
+0x8EF6	0x6388	#CJK UNIFIED IDEOGRAPH
+0x8EF7	0x6A39	#CJK UNIFIED IDEOGRAPH
+0x8EF8	0x7DAC	#CJK UNIFIED IDEOGRAPH
+0x8EF9	0x9700	#CJK UNIFIED IDEOGRAPH
+0x8EFA	0x56DA	#CJK UNIFIED IDEOGRAPH
+0x8EFB	0x53CE	#CJK UNIFIED IDEOGRAPH
+0x8EFC	0x5468	#CJK UNIFIED IDEOGRAPH
+0x8F40	0x5B97	#CJK UNIFIED IDEOGRAPH
+0x8F41	0x5C31	#CJK UNIFIED IDEOGRAPH
+0x8F42	0x5DDE	#CJK UNIFIED IDEOGRAPH
+0x8F43	0x4FEE	#CJK UNIFIED IDEOGRAPH
+0x8F44	0x6101	#CJK UNIFIED IDEOGRAPH
+0x8F45	0x62FE	#CJK UNIFIED IDEOGRAPH
+0x8F46	0x6D32	#CJK UNIFIED IDEOGRAPH
+0x8F47	0x79C0	#CJK UNIFIED IDEOGRAPH
+0x8F48	0x79CB	#CJK UNIFIED IDEOGRAPH
+0x8F49	0x7D42	#CJK UNIFIED IDEOGRAPH
+0x8F4A	0x7E4D	#CJK UNIFIED IDEOGRAPH
+0x8F4B	0x7FD2	#CJK UNIFIED IDEOGRAPH
+0x8F4C	0x81ED	#CJK UNIFIED IDEOGRAPH
+0x8F4D	0x821F	#CJK UNIFIED IDEOGRAPH
+0x8F4E	0x8490	#CJK UNIFIED IDEOGRAPH
+0x8F4F	0x8846	#CJK UNIFIED IDEOGRAPH
+0x8F50	0x8972	#CJK UNIFIED IDEOGRAPH
+0x8F51	0x8B90	#CJK UNIFIED IDEOGRAPH
+0x8F52	0x8E74	#CJK UNIFIED IDEOGRAPH
+0x8F53	0x8F2F	#CJK UNIFIED IDEOGRAPH
+0x8F54	0x9031	#CJK UNIFIED IDEOGRAPH
+0x8F55	0x914B	#CJK UNIFIED IDEOGRAPH
+0x8F56	0x916C	#CJK UNIFIED IDEOGRAPH
+0x8F57	0x96C6	#CJK UNIFIED IDEOGRAPH
+0x8F58	0x919C	#CJK UNIFIED IDEOGRAPH
+0x8F59	0x4EC0	#CJK UNIFIED IDEOGRAPH
+0x8F5A	0x4F4F	#CJK UNIFIED IDEOGRAPH
+0x8F5B	0x5145	#CJK UNIFIED IDEOGRAPH
+0x8F5C	0x5341	#CJK UNIFIED IDEOGRAPH
+0x8F5D	0x5F93	#CJK UNIFIED IDEOGRAPH
+0x8F5E	0x620E	#CJK UNIFIED IDEOGRAPH
+0x8F5F	0x67D4	#CJK UNIFIED IDEOGRAPH
+0x8F60	0x6C41	#CJK UNIFIED IDEOGRAPH
+0x8F61	0x6E0B	#CJK UNIFIED IDEOGRAPH
+0x8F62	0x7363	#CJK UNIFIED IDEOGRAPH
+0x8F63	0x7E26	#CJK UNIFIED IDEOGRAPH
+0x8F64	0x91CD	#CJK UNIFIED IDEOGRAPH
+0x8F65	0x9283	#CJK UNIFIED IDEOGRAPH
+0x8F66	0x53D4	#CJK UNIFIED IDEOGRAPH
+0x8F67	0x5919	#CJK UNIFIED IDEOGRAPH
+0x8F68	0x5BBF	#CJK UNIFIED IDEOGRAPH
+0x8F69	0x6DD1	#CJK UNIFIED IDEOGRAPH
+0x8F6A	0x795D	#CJK UNIFIED IDEOGRAPH
+0x8F6B	0x7E2E	#CJK UNIFIED IDEOGRAPH
+0x8F6C	0x7C9B	#CJK UNIFIED IDEOGRAPH
+0x8F6D	0x587E	#CJK UNIFIED IDEOGRAPH
+0x8F6E	0x719F	#CJK UNIFIED IDEOGRAPH
+0x8F6F	0x51FA	#CJK UNIFIED IDEOGRAPH
+0x8F70	0x8853	#CJK UNIFIED IDEOGRAPH
+0x8F71	0x8FF0	#CJK UNIFIED IDEOGRAPH
+0x8F72	0x4FCA	#CJK UNIFIED IDEOGRAPH
+0x8F73	0x5CFB	#CJK UNIFIED IDEOGRAPH
+0x8F74	0x6625	#CJK UNIFIED IDEOGRAPH
+0x8F75	0x77AC	#CJK UNIFIED IDEOGRAPH
+0x8F76	0x7AE3	#CJK UNIFIED IDEOGRAPH
+0x8F77	0x821C	#CJK UNIFIED IDEOGRAPH
+0x8F78	0x99FF	#CJK UNIFIED IDEOGRAPH
+0x8F79	0x51C6	#CJK UNIFIED IDEOGRAPH
+0x8F7A	0x5FAA	#CJK UNIFIED IDEOGRAPH
+0x8F7B	0x65EC	#CJK UNIFIED IDEOGRAPH
+0x8F7C	0x696F	#CJK UNIFIED IDEOGRAPH
+0x8F7D	0x6B89	#CJK UNIFIED IDEOGRAPH
+0x8F7E	0x6DF3	#CJK UNIFIED IDEOGRAPH
+0x8F80	0x6E96	#CJK UNIFIED IDEOGRAPH
+0x8F81	0x6F64	#CJK UNIFIED IDEOGRAPH
+0x8F82	0x76FE	#CJK UNIFIED IDEOGRAPH
+0x8F83	0x7D14	#CJK UNIFIED IDEOGRAPH
+0x8F84	0x5DE1	#CJK UNIFIED IDEOGRAPH
+0x8F85	0x9075	#CJK UNIFIED IDEOGRAPH
+0x8F86	0x9187	#CJK UNIFIED IDEOGRAPH
+0x8F87	0x9806	#CJK UNIFIED IDEOGRAPH
+0x8F88	0x51E6	#CJK UNIFIED IDEOGRAPH
+0x8F89	0x521D	#CJK UNIFIED IDEOGRAPH
+0x8F8A	0x6240	#CJK UNIFIED IDEOGRAPH
+0x8F8B	0x6691	#CJK UNIFIED IDEOGRAPH
+0x8F8C	0x66D9	#CJK UNIFIED IDEOGRAPH
+0x8F8D	0x6E1A	#CJK UNIFIED IDEOGRAPH
+0x8F8E	0x5EB6	#CJK UNIFIED IDEOGRAPH
+0x8F8F	0x7DD2	#CJK UNIFIED IDEOGRAPH
+0x8F90	0x7F72	#CJK UNIFIED IDEOGRAPH
+0x8F91	0x66F8	#CJK UNIFIED IDEOGRAPH
+0x8F92	0x85AF	#CJK UNIFIED IDEOGRAPH
+0x8F93	0x85F7	#CJK UNIFIED IDEOGRAPH
+0x8F94	0x8AF8	#CJK UNIFIED IDEOGRAPH
+0x8F95	0x52A9	#CJK UNIFIED IDEOGRAPH
+0x8F96	0x53D9	#CJK UNIFIED IDEOGRAPH
+0x8F97	0x5973	#CJK UNIFIED IDEOGRAPH
+0x8F98	0x5E8F	#CJK UNIFIED IDEOGRAPH
+0x8F99	0x5F90	#CJK UNIFIED IDEOGRAPH
+0x8F9A	0x6055	#CJK UNIFIED IDEOGRAPH
+0x8F9B	0x92E4	#CJK UNIFIED IDEOGRAPH
+0x8F9C	0x9664	#CJK UNIFIED IDEOGRAPH
+0x8F9D	0x50B7	#CJK UNIFIED IDEOGRAPH
+0x8F9E	0x511F	#CJK UNIFIED IDEOGRAPH
+0x8F9F	0x52DD	#CJK UNIFIED IDEOGRAPH
+0x8FA0	0x5320	#CJK UNIFIED IDEOGRAPH
+0x8FA1	0x5347	#CJK UNIFIED IDEOGRAPH
+0x8FA2	0x53EC	#CJK UNIFIED IDEOGRAPH
+0x8FA3	0x54E8	#CJK UNIFIED IDEOGRAPH
+0x8FA4	0x5546	#CJK UNIFIED IDEOGRAPH
+0x8FA5	0x5531	#CJK UNIFIED IDEOGRAPH
+0x8FA6	0x5617	#CJK UNIFIED IDEOGRAPH
+0x8FA7	0x5968	#CJK UNIFIED IDEOGRAPH
+0x8FA8	0x59BE	#CJK UNIFIED IDEOGRAPH
+0x8FA9	0x5A3C	#CJK UNIFIED IDEOGRAPH
+0x8FAA	0x5BB5	#CJK UNIFIED IDEOGRAPH
+0x8FAB	0x5C06	#CJK UNIFIED IDEOGRAPH
+0x8FAC	0x5C0F	#CJK UNIFIED IDEOGRAPH
+0x8FAD	0x5C11	#CJK UNIFIED IDEOGRAPH
+0x8FAE	0x5C1A	#CJK UNIFIED IDEOGRAPH
+0x8FAF	0x5E84	#CJK UNIFIED IDEOGRAPH
+0x8FB0	0x5E8A	#CJK UNIFIED IDEOGRAPH
+0x8FB1	0x5EE0	#CJK UNIFIED IDEOGRAPH
+0x8FB2	0x5F70	#CJK UNIFIED IDEOGRAPH
+0x8FB3	0x627F	#CJK UNIFIED IDEOGRAPH
+0x8FB4	0x6284	#CJK UNIFIED IDEOGRAPH
+0x8FB5	0x62DB	#CJK UNIFIED IDEOGRAPH
+0x8FB6	0x638C	#CJK UNIFIED IDEOGRAPH
+0x8FB7	0x6377	#CJK UNIFIED IDEOGRAPH
+0x8FB8	0x6607	#CJK UNIFIED IDEOGRAPH
+0x8FB9	0x660C	#CJK UNIFIED IDEOGRAPH
+0x8FBA	0x662D	#CJK UNIFIED IDEOGRAPH
+0x8FBB	0x6676	#CJK UNIFIED IDEOGRAPH
+0x8FBC	0x677E	#CJK UNIFIED IDEOGRAPH
+0x8FBD	0x68A2	#CJK UNIFIED IDEOGRAPH
+0x8FBE	0x6A1F	#CJK UNIFIED IDEOGRAPH
+0x8FBF	0x6A35	#CJK UNIFIED IDEOGRAPH
+0x8FC0	0x6CBC	#CJK UNIFIED IDEOGRAPH
+0x8FC1	0x6D88	#CJK UNIFIED IDEOGRAPH
+0x8FC2	0x6E09	#CJK UNIFIED IDEOGRAPH
+0x8FC3	0x6E58	#CJK UNIFIED IDEOGRAPH
+0x8FC4	0x713C	#CJK UNIFIED IDEOGRAPH
+0x8FC5	0x7126	#CJK UNIFIED IDEOGRAPH
+0x8FC6	0x7167	#CJK UNIFIED IDEOGRAPH
+0x8FC7	0x75C7	#CJK UNIFIED IDEOGRAPH
+0x8FC8	0x7701	#CJK UNIFIED IDEOGRAPH
+0x8FC9	0x785D	#CJK UNIFIED IDEOGRAPH
+0x8FCA	0x7901	#CJK UNIFIED IDEOGRAPH
+0x8FCB	0x7965	#CJK UNIFIED IDEOGRAPH
+0x8FCC	0x79F0	#CJK UNIFIED IDEOGRAPH
+0x8FCD	0x7AE0	#CJK UNIFIED IDEOGRAPH
+0x8FCE	0x7B11	#CJK UNIFIED IDEOGRAPH
+0x8FCF	0x7CA7	#CJK UNIFIED IDEOGRAPH
+0x8FD0	0x7D39	#CJK UNIFIED IDEOGRAPH
+0x8FD1	0x8096	#CJK UNIFIED IDEOGRAPH
+0x8FD2	0x83D6	#CJK UNIFIED IDEOGRAPH
+0x8FD3	0x848B	#CJK UNIFIED IDEOGRAPH
+0x8FD4	0x8549	#CJK UNIFIED IDEOGRAPH
+0x8FD5	0x885D	#CJK UNIFIED IDEOGRAPH
+0x8FD6	0x88F3	#CJK UNIFIED IDEOGRAPH
+0x8FD7	0x8A1F	#CJK UNIFIED IDEOGRAPH
+0x8FD8	0x8A3C	#CJK UNIFIED IDEOGRAPH
+0x8FD9	0x8A54	#CJK UNIFIED IDEOGRAPH
+0x8FDA	0x8A73	#CJK UNIFIED IDEOGRAPH
+0x8FDB	0x8C61	#CJK UNIFIED IDEOGRAPH
+0x8FDC	0x8CDE	#CJK UNIFIED IDEOGRAPH
+0x8FDD	0x91A4	#CJK UNIFIED IDEOGRAPH
+0x8FDE	0x9266	#CJK UNIFIED IDEOGRAPH
+0x8FDF	0x937E	#CJK UNIFIED IDEOGRAPH
+0x8FE0	0x9418	#CJK UNIFIED IDEOGRAPH
+0x8FE1	0x969C	#CJK UNIFIED IDEOGRAPH
+0x8FE2	0x9798	#CJK UNIFIED IDEOGRAPH
+0x8FE3	0x4E0A	#CJK UNIFIED IDEOGRAPH
+0x8FE4	0x4E08	#CJK UNIFIED IDEOGRAPH
+0x8FE5	0x4E1E	#CJK UNIFIED IDEOGRAPH
+0x8FE6	0x4E57	#CJK UNIFIED IDEOGRAPH
+0x8FE7	0x5197	#CJK UNIFIED IDEOGRAPH
+0x8FE8	0x5270	#CJK UNIFIED IDEOGRAPH
+0x8FE9	0x57CE	#CJK UNIFIED IDEOGRAPH
+0x8FEA	0x5834	#CJK UNIFIED IDEOGRAPH
+0x8FEB	0x58CC	#CJK UNIFIED IDEOGRAPH
+0x8FEC	0x5B22	#CJK UNIFIED IDEOGRAPH
+0x8FED	0x5E38	#CJK UNIFIED IDEOGRAPH
+0x8FEE	0x60C5	#CJK UNIFIED IDEOGRAPH
+0x8FEF	0x64FE	#CJK UNIFIED IDEOGRAPH
+0x8FF0	0x6761	#CJK UNIFIED IDEOGRAPH
+0x8FF1	0x6756	#CJK UNIFIED IDEOGRAPH
+0x8FF2	0x6D44	#CJK UNIFIED IDEOGRAPH
+0x8FF3	0x72B6	#CJK UNIFIED IDEOGRAPH
+0x8FF4	0x7573	#CJK UNIFIED IDEOGRAPH
+0x8FF5	0x7A63	#CJK UNIFIED IDEOGRAPH
+0x8FF6	0x84B8	#CJK UNIFIED IDEOGRAPH
+0x8FF7	0x8B72	#CJK UNIFIED IDEOGRAPH
+0x8FF8	0x91B8	#CJK UNIFIED IDEOGRAPH
+0x8FF9	0x9320	#CJK UNIFIED IDEOGRAPH
+0x8FFA	0x5631	#CJK UNIFIED IDEOGRAPH
+0x8FFB	0x57F4	#CJK UNIFIED IDEOGRAPH
+0x8FFC	0x98FE	#CJK UNIFIED IDEOGRAPH
+0x9040	0x62ED	#CJK UNIFIED IDEOGRAPH
+0x9041	0x690D	#CJK UNIFIED IDEOGRAPH
+0x9042	0x6B96	#CJK UNIFIED IDEOGRAPH
+0x9043	0x71ED	#CJK UNIFIED IDEOGRAPH
+0x9044	0x7E54	#CJK UNIFIED IDEOGRAPH
+0x9045	0x8077	#CJK UNIFIED IDEOGRAPH
+0x9046	0x8272	#CJK UNIFIED IDEOGRAPH
+0x9047	0x89E6	#CJK UNIFIED IDEOGRAPH
+0x9048	0x98DF	#CJK UNIFIED IDEOGRAPH
+0x9049	0x8755	#CJK UNIFIED IDEOGRAPH
+0x904A	0x8FB1	#CJK UNIFIED IDEOGRAPH
+0x904B	0x5C3B	#CJK UNIFIED IDEOGRAPH
+0x904C	0x4F38	#CJK UNIFIED IDEOGRAPH
+0x904D	0x4FE1	#CJK UNIFIED IDEOGRAPH
+0x904E	0x4FB5	#CJK UNIFIED IDEOGRAPH
+0x904F	0x5507	#CJK UNIFIED IDEOGRAPH
+0x9050	0x5A20	#CJK UNIFIED IDEOGRAPH
+0x9051	0x5BDD	#CJK UNIFIED IDEOGRAPH
+0x9052	0x5BE9	#CJK UNIFIED IDEOGRAPH
+0x9053	0x5FC3	#CJK UNIFIED IDEOGRAPH
+0x9054	0x614E	#CJK UNIFIED IDEOGRAPH
+0x9055	0x632F	#CJK UNIFIED IDEOGRAPH
+0x9056	0x65B0	#CJK UNIFIED IDEOGRAPH
+0x9057	0x664B	#CJK UNIFIED IDEOGRAPH
+0x9058	0x68EE	#CJK UNIFIED IDEOGRAPH
+0x9059	0x699B	#CJK UNIFIED IDEOGRAPH
+0x905A	0x6D78	#CJK UNIFIED IDEOGRAPH
+0x905B	0x6DF1	#CJK UNIFIED IDEOGRAPH
+0x905C	0x7533	#CJK UNIFIED IDEOGRAPH
+0x905D	0x75B9	#CJK UNIFIED IDEOGRAPH
+0x905E	0x771F	#CJK UNIFIED IDEOGRAPH
+0x905F	0x795E	#CJK UNIFIED IDEOGRAPH
+0x9060	0x79E6	#CJK UNIFIED IDEOGRAPH
+0x9061	0x7D33	#CJK UNIFIED IDEOGRAPH
+0x9062	0x81E3	#CJK UNIFIED IDEOGRAPH
+0x9063	0x82AF	#CJK UNIFIED IDEOGRAPH
+0x9064	0x85AA	#CJK UNIFIED IDEOGRAPH
+0x9065	0x89AA	#CJK UNIFIED IDEOGRAPH
+0x9066	0x8A3A	#CJK UNIFIED IDEOGRAPH
+0x9067	0x8EAB	#CJK UNIFIED IDEOGRAPH
+0x9068	0x8F9B	#CJK UNIFIED IDEOGRAPH
+0x9069	0x9032	#CJK UNIFIED IDEOGRAPH
+0x906A	0x91DD	#CJK UNIFIED IDEOGRAPH
+0x906B	0x9707	#CJK UNIFIED IDEOGRAPH
+0x906C	0x4EBA	#CJK UNIFIED IDEOGRAPH
+0x906D	0x4EC1	#CJK UNIFIED IDEOGRAPH
+0x906E	0x5203	#CJK UNIFIED IDEOGRAPH
+0x906F	0x5875	#CJK UNIFIED IDEOGRAPH
+0x9070	0x58EC	#CJK UNIFIED IDEOGRAPH
+0x9071	0x5C0B	#CJK UNIFIED IDEOGRAPH
+0x9072	0x751A	#CJK UNIFIED IDEOGRAPH
+0x9073	0x5C3D	#CJK UNIFIED IDEOGRAPH
+0x9074	0x814E	#CJK UNIFIED IDEOGRAPH
+0x9075	0x8A0A	#CJK UNIFIED IDEOGRAPH
+0x9076	0x8FC5	#CJK UNIFIED IDEOGRAPH
+0x9077	0x9663	#CJK UNIFIED IDEOGRAPH
+0x9078	0x976D	#CJK UNIFIED IDEOGRAPH
+0x9079	0x7B25	#CJK UNIFIED IDEOGRAPH
+0x907A	0x8ACF	#CJK UNIFIED IDEOGRAPH
+0x907B	0x9808	#CJK UNIFIED IDEOGRAPH
+0x907C	0x9162	#CJK UNIFIED IDEOGRAPH
+0x907D	0x56F3	#CJK UNIFIED IDEOGRAPH
+0x907E	0x53A8	#CJK UNIFIED IDEOGRAPH
+0x9080	0x9017	#CJK UNIFIED IDEOGRAPH
+0x9081	0x5439	#CJK UNIFIED IDEOGRAPH
+0x9082	0x5782	#CJK UNIFIED IDEOGRAPH
+0x9083	0x5E25	#CJK UNIFIED IDEOGRAPH
+0x9084	0x63A8	#CJK UNIFIED IDEOGRAPH
+0x9085	0x6C34	#CJK UNIFIED IDEOGRAPH
+0x9086	0x708A	#CJK UNIFIED IDEOGRAPH
+0x9087	0x7761	#CJK UNIFIED IDEOGRAPH
+0x9088	0x7C8B	#CJK UNIFIED IDEOGRAPH
+0x9089	0x7FE0	#CJK UNIFIED IDEOGRAPH
+0x908A	0x8870	#CJK UNIFIED IDEOGRAPH
+0x908B	0x9042	#CJK UNIFIED IDEOGRAPH
+0x908C	0x9154	#CJK UNIFIED IDEOGRAPH
+0x908D	0x9310	#CJK UNIFIED IDEOGRAPH
+0x908E	0x9318	#CJK UNIFIED IDEOGRAPH
+0x908F	0x968F	#CJK UNIFIED IDEOGRAPH
+0x9090	0x745E	#CJK UNIFIED IDEOGRAPH
+0x9091	0x9AC4	#CJK UNIFIED IDEOGRAPH
+0x9092	0x5D07	#CJK UNIFIED IDEOGRAPH
+0x9093	0x5D69	#CJK UNIFIED IDEOGRAPH
+0x9094	0x6570	#CJK UNIFIED IDEOGRAPH
+0x9095	0x67A2	#CJK UNIFIED IDEOGRAPH
+0x9096	0x8DA8	#CJK UNIFIED IDEOGRAPH
+0x9097	0x96DB	#CJK UNIFIED IDEOGRAPH
+0x9098	0x636E	#CJK UNIFIED IDEOGRAPH
+0x9099	0x6749	#CJK UNIFIED IDEOGRAPH
+0x909A	0x6919	#CJK UNIFIED IDEOGRAPH
+0x909B	0x83C5	#CJK UNIFIED IDEOGRAPH
+0x909C	0x9817	#CJK UNIFIED IDEOGRAPH
+0x909D	0x96C0	#CJK UNIFIED IDEOGRAPH
+0x909E	0x88FE	#CJK UNIFIED IDEOGRAPH
+0x909F	0x6F84	#CJK UNIFIED IDEOGRAPH
+0x90A0	0x647A	#CJK UNIFIED IDEOGRAPH
+0x90A1	0x5BF8	#CJK UNIFIED IDEOGRAPH
+0x90A2	0x4E16	#CJK UNIFIED IDEOGRAPH
+0x90A3	0x702C	#CJK UNIFIED IDEOGRAPH
+0x90A4	0x755D	#CJK UNIFIED IDEOGRAPH
+0x90A5	0x662F	#CJK UNIFIED IDEOGRAPH
+0x90A6	0x51C4	#CJK UNIFIED IDEOGRAPH
+0x90A7	0x5236	#CJK UNIFIED IDEOGRAPH
+0x90A8	0x52E2	#CJK UNIFIED IDEOGRAPH
+0x90A9	0x59D3	#CJK UNIFIED IDEOGRAPH
+0x90AA	0x5F81	#CJK UNIFIED IDEOGRAPH
+0x90AB	0x6027	#CJK UNIFIED IDEOGRAPH
+0x90AC	0x6210	#CJK UNIFIED IDEOGRAPH
+0x90AD	0x653F	#CJK UNIFIED IDEOGRAPH
+0x90AE	0x6574	#CJK UNIFIED IDEOGRAPH
+0x90AF	0x661F	#CJK UNIFIED IDEOGRAPH
+0x90B0	0x6674	#CJK UNIFIED IDEOGRAPH
+0x90B1	0x68F2	#CJK UNIFIED IDEOGRAPH
+0x90B2	0x6816	#CJK UNIFIED IDEOGRAPH
+0x90B3	0x6B63	#CJK UNIFIED IDEOGRAPH
+0x90B4	0x6E05	#CJK UNIFIED IDEOGRAPH
+0x90B5	0x7272	#CJK UNIFIED IDEOGRAPH
+0x90B6	0x751F	#CJK UNIFIED IDEOGRAPH
+0x90B7	0x76DB	#CJK UNIFIED IDEOGRAPH
+0x90B8	0x7CBE	#CJK UNIFIED IDEOGRAPH
+0x90B9	0x8056	#CJK UNIFIED IDEOGRAPH
+0x90BA	0x58F0	#CJK UNIFIED IDEOGRAPH
+0x90BB	0x88FD	#CJK UNIFIED IDEOGRAPH
+0x90BC	0x897F	#CJK UNIFIED IDEOGRAPH
+0x90BD	0x8AA0	#CJK UNIFIED IDEOGRAPH
+0x90BE	0x8A93	#CJK UNIFIED IDEOGRAPH
+0x90BF	0x8ACB	#CJK UNIFIED IDEOGRAPH
+0x90C0	0x901D	#CJK UNIFIED IDEOGRAPH
+0x90C1	0x9192	#CJK UNIFIED IDEOGRAPH
+0x90C2	0x9752	#CJK UNIFIED IDEOGRAPH
+0x90C3	0x9759	#CJK UNIFIED IDEOGRAPH
+0x90C4	0x6589	#CJK UNIFIED IDEOGRAPH
+0x90C5	0x7A0E	#CJK UNIFIED IDEOGRAPH
+0x90C6	0x8106	#CJK UNIFIED IDEOGRAPH
+0x90C7	0x96BB	#CJK UNIFIED IDEOGRAPH
+0x90C8	0x5E2D	#CJK UNIFIED IDEOGRAPH
+0x90C9	0x60DC	#CJK UNIFIED IDEOGRAPH
+0x90CA	0x621A	#CJK UNIFIED IDEOGRAPH
+0x90CB	0x65A5	#CJK UNIFIED IDEOGRAPH
+0x90CC	0x6614	#CJK UNIFIED IDEOGRAPH
+0x90CD	0x6790	#CJK UNIFIED IDEOGRAPH
+0x90CE	0x77F3	#CJK UNIFIED IDEOGRAPH
+0x90CF	0x7A4D	#CJK UNIFIED IDEOGRAPH
+0x90D0	0x7C4D	#CJK UNIFIED IDEOGRAPH
+0x90D1	0x7E3E	#CJK UNIFIED IDEOGRAPH
+0x90D2	0x810A	#CJK UNIFIED IDEOGRAPH
+0x90D3	0x8CAC	#CJK UNIFIED IDEOGRAPH
+0x90D4	0x8D64	#CJK UNIFIED IDEOGRAPH
+0x90D5	0x8DE1	#CJK UNIFIED IDEOGRAPH
+0x90D6	0x8E5F	#CJK UNIFIED IDEOGRAPH
+0x90D7	0x78A9	#CJK UNIFIED IDEOGRAPH
+0x90D8	0x5207	#CJK UNIFIED IDEOGRAPH
+0x90D9	0x62D9	#CJK UNIFIED IDEOGRAPH
+0x90DA	0x63A5	#CJK UNIFIED IDEOGRAPH
+0x90DB	0x6442	#CJK UNIFIED IDEOGRAPH
+0x90DC	0x6298	#CJK UNIFIED IDEOGRAPH
+0x90DD	0x8A2D	#CJK UNIFIED IDEOGRAPH
+0x90DE	0x7A83	#CJK UNIFIED IDEOGRAPH
+0x90DF	0x7BC0	#CJK UNIFIED IDEOGRAPH
+0x90E0	0x8AAC	#CJK UNIFIED IDEOGRAPH
+0x90E1	0x96EA	#CJK UNIFIED IDEOGRAPH
+0x90E2	0x7D76	#CJK UNIFIED IDEOGRAPH
+0x90E3	0x820C	#CJK UNIFIED IDEOGRAPH
+0x90E4	0x8749	#CJK UNIFIED IDEOGRAPH
+0x90E5	0x4ED9	#CJK UNIFIED IDEOGRAPH
+0x90E6	0x5148	#CJK UNIFIED IDEOGRAPH
+0x90E7	0x5343	#CJK UNIFIED IDEOGRAPH
+0x90E8	0x5360	#CJK UNIFIED IDEOGRAPH
+0x90E9	0x5BA3	#CJK UNIFIED IDEOGRAPH
+0x90EA	0x5C02	#CJK UNIFIED IDEOGRAPH
+0x90EB	0x5C16	#CJK UNIFIED IDEOGRAPH
+0x90EC	0x5DDD	#CJK UNIFIED IDEOGRAPH
+0x90ED	0x6226	#CJK UNIFIED IDEOGRAPH
+0x90EE	0x6247	#CJK UNIFIED IDEOGRAPH
+0x90EF	0x64B0	#CJK UNIFIED IDEOGRAPH
+0x90F0	0x6813	#CJK UNIFIED IDEOGRAPH
+0x90F1	0x6834	#CJK UNIFIED IDEOGRAPH
+0x90F2	0x6CC9	#CJK UNIFIED IDEOGRAPH
+0x90F3	0x6D45	#CJK UNIFIED IDEOGRAPH
+0x90F4	0x6D17	#CJK UNIFIED IDEOGRAPH
+0x90F5	0x67D3	#CJK UNIFIED IDEOGRAPH
+0x90F6	0x6F5C	#CJK UNIFIED IDEOGRAPH
+0x90F7	0x714E	#CJK UNIFIED IDEOGRAPH
+0x90F8	0x717D	#CJK UNIFIED IDEOGRAPH
+0x90F9	0x65CB	#CJK UNIFIED IDEOGRAPH
+0x90FA	0x7A7F	#CJK UNIFIED IDEOGRAPH
+0x90FB	0x7BAD	#CJK UNIFIED IDEOGRAPH
+0x90FC	0x7DDA	#CJK UNIFIED IDEOGRAPH
+0x9140	0x7E4A	#CJK UNIFIED IDEOGRAPH
+0x9141	0x7FA8	#CJK UNIFIED IDEOGRAPH
+0x9142	0x817A	#CJK UNIFIED IDEOGRAPH
+0x9143	0x821B	#CJK UNIFIED IDEOGRAPH
+0x9144	0x8239	#CJK UNIFIED IDEOGRAPH
+0x9145	0x85A6	#CJK UNIFIED IDEOGRAPH
+0x9146	0x8A6E	#CJK UNIFIED IDEOGRAPH
+0x9147	0x8CCE	#CJK UNIFIED IDEOGRAPH
+0x9148	0x8DF5	#CJK UNIFIED IDEOGRAPH
+0x9149	0x9078	#CJK UNIFIED IDEOGRAPH
+0x914A	0x9077	#CJK UNIFIED IDEOGRAPH
+0x914B	0x92AD	#CJK UNIFIED IDEOGRAPH
+0x914C	0x9291	#CJK UNIFIED IDEOGRAPH
+0x914D	0x9583	#CJK UNIFIED IDEOGRAPH
+0x914E	0x9BAE	#CJK UNIFIED IDEOGRAPH
+0x914F	0x524D	#CJK UNIFIED IDEOGRAPH
+0x9150	0x5584	#CJK UNIFIED IDEOGRAPH
+0x9151	0x6F38	#CJK UNIFIED IDEOGRAPH
+0x9152	0x7136	#CJK UNIFIED IDEOGRAPH
+0x9153	0x5168	#CJK UNIFIED IDEOGRAPH
+0x9154	0x7985	#CJK UNIFIED IDEOGRAPH
+0x9155	0x7E55	#CJK UNIFIED IDEOGRAPH
+0x9156	0x81B3	#CJK UNIFIED IDEOGRAPH
+0x9157	0x7CCE	#CJK UNIFIED IDEOGRAPH
+0x9158	0x564C	#CJK UNIFIED IDEOGRAPH
+0x9159	0x5851	#CJK UNIFIED IDEOGRAPH
+0x915A	0x5CA8	#CJK UNIFIED IDEOGRAPH
+0x915B	0x63AA	#CJK UNIFIED IDEOGRAPH
+0x915C	0x66FE	#CJK UNIFIED IDEOGRAPH
+0x915D	0x66FD	#CJK UNIFIED IDEOGRAPH
+0x915E	0x695A	#CJK UNIFIED IDEOGRAPH
+0x915F	0x72D9	#CJK UNIFIED IDEOGRAPH
+0x9160	0x758F	#CJK UNIFIED IDEOGRAPH
+0x9161	0x758E	#CJK UNIFIED IDEOGRAPH
+0x9162	0x790E	#CJK UNIFIED IDEOGRAPH
+0x9163	0x7956	#CJK UNIFIED IDEOGRAPH
+0x9164	0x79DF	#CJK UNIFIED IDEOGRAPH
+0x9165	0x7C97	#CJK UNIFIED IDEOGRAPH
+0x9166	0x7D20	#CJK UNIFIED IDEOGRAPH
+0x9167	0x7D44	#CJK UNIFIED IDEOGRAPH
+0x9168	0x8607	#CJK UNIFIED IDEOGRAPH
+0x9169	0x8A34	#CJK UNIFIED IDEOGRAPH
+0x916A	0x963B	#CJK UNIFIED IDEOGRAPH
+0x916B	0x9061	#CJK UNIFIED IDEOGRAPH
+0x916C	0x9F20	#CJK UNIFIED IDEOGRAPH
+0x916D	0x50E7	#CJK UNIFIED IDEOGRAPH
+0x916E	0x5275	#CJK UNIFIED IDEOGRAPH
+0x916F	0x53CC	#CJK UNIFIED IDEOGRAPH
+0x9170	0x53E2	#CJK UNIFIED IDEOGRAPH
+0x9171	0x5009	#CJK UNIFIED IDEOGRAPH
+0x9172	0x55AA	#CJK UNIFIED IDEOGRAPH
+0x9173	0x58EE	#CJK UNIFIED IDEOGRAPH
+0x9174	0x594F	#CJK UNIFIED IDEOGRAPH
+0x9175	0x723D	#CJK UNIFIED IDEOGRAPH
+0x9176	0x5B8B	#CJK UNIFIED IDEOGRAPH
+0x9177	0x5C64	#CJK UNIFIED IDEOGRAPH
+0x9178	0x531D	#CJK UNIFIED IDEOGRAPH
+0x9179	0x60E3	#CJK UNIFIED IDEOGRAPH
+0x917A	0x60F3	#CJK UNIFIED IDEOGRAPH
+0x917B	0x635C	#CJK UNIFIED IDEOGRAPH
+0x917C	0x6383	#CJK UNIFIED IDEOGRAPH
+0x917D	0x633F	#CJK UNIFIED IDEOGRAPH
+0x917E	0x63BB	#CJK UNIFIED IDEOGRAPH
+0x9180	0x64CD	#CJK UNIFIED IDEOGRAPH
+0x9181	0x65E9	#CJK UNIFIED IDEOGRAPH
+0x9182	0x66F9	#CJK UNIFIED IDEOGRAPH
+0x9183	0x5DE3	#CJK UNIFIED IDEOGRAPH
+0x9184	0x69CD	#CJK UNIFIED IDEOGRAPH
+0x9185	0x69FD	#CJK UNIFIED IDEOGRAPH
+0x9186	0x6F15	#CJK UNIFIED IDEOGRAPH
+0x9187	0x71E5	#CJK UNIFIED IDEOGRAPH
+0x9188	0x4E89	#CJK UNIFIED IDEOGRAPH
+0x9189	0x75E9	#CJK UNIFIED IDEOGRAPH
+0x918A	0x76F8	#CJK UNIFIED IDEOGRAPH
+0x918B	0x7A93	#CJK UNIFIED IDEOGRAPH
+0x918C	0x7CDF	#CJK UNIFIED IDEOGRAPH
+0x918D	0x7DCF	#CJK UNIFIED IDEOGRAPH
+0x918E	0x7D9C	#CJK UNIFIED IDEOGRAPH
+0x918F	0x8061	#CJK UNIFIED IDEOGRAPH
+0x9190	0x8349	#CJK UNIFIED IDEOGRAPH
+0x9191	0x8358	#CJK UNIFIED IDEOGRAPH
+0x9192	0x846C	#CJK UNIFIED IDEOGRAPH
+0x9193	0x84BC	#CJK UNIFIED IDEOGRAPH
+0x9194	0x85FB	#CJK UNIFIED IDEOGRAPH
+0x9195	0x88C5	#CJK UNIFIED IDEOGRAPH
+0x9196	0x8D70	#CJK UNIFIED IDEOGRAPH
+0x9197	0x9001	#CJK UNIFIED IDEOGRAPH
+0x9198	0x906D	#CJK UNIFIED IDEOGRAPH
+0x9199	0x9397	#CJK UNIFIED IDEOGRAPH
+0x919A	0x971C	#CJK UNIFIED IDEOGRAPH
+0x919B	0x9A12	#CJK UNIFIED IDEOGRAPH
+0x919C	0x50CF	#CJK UNIFIED IDEOGRAPH
+0x919D	0x5897	#CJK UNIFIED IDEOGRAPH
+0x919E	0x618E	#CJK UNIFIED IDEOGRAPH
+0x919F	0x81D3	#CJK UNIFIED IDEOGRAPH
+0x91A0	0x8535	#CJK UNIFIED IDEOGRAPH
+0x91A1	0x8D08	#CJK UNIFIED IDEOGRAPH
+0x91A2	0x9020	#CJK UNIFIED IDEOGRAPH
+0x91A3	0x4FC3	#CJK UNIFIED IDEOGRAPH
+0x91A4	0x5074	#CJK UNIFIED IDEOGRAPH
+0x91A5	0x5247	#CJK UNIFIED IDEOGRAPH
+0x91A6	0x5373	#CJK UNIFIED IDEOGRAPH
+0x91A7	0x606F	#CJK UNIFIED IDEOGRAPH
+0x91A8	0x6349	#CJK UNIFIED IDEOGRAPH
+0x91A9	0x675F	#CJK UNIFIED IDEOGRAPH
+0x91AA	0x6E2C	#CJK UNIFIED IDEOGRAPH
+0x91AB	0x8DB3	#CJK UNIFIED IDEOGRAPH
+0x91AC	0x901F	#CJK UNIFIED IDEOGRAPH
+0x91AD	0x4FD7	#CJK UNIFIED IDEOGRAPH
+0x91AE	0x5C5E	#CJK UNIFIED IDEOGRAPH
+0x91AF	0x8CCA	#CJK UNIFIED IDEOGRAPH
+0x91B0	0x65CF	#CJK UNIFIED IDEOGRAPH
+0x91B1	0x7D9A	#CJK UNIFIED IDEOGRAPH
+0x91B2	0x5352	#CJK UNIFIED IDEOGRAPH
+0x91B3	0x8896	#CJK UNIFIED IDEOGRAPH
+0x91B4	0x5176	#CJK UNIFIED IDEOGRAPH
+0x91B5	0x63C3	#CJK UNIFIED IDEOGRAPH
+0x91B6	0x5B58	#CJK UNIFIED IDEOGRAPH
+0x91B7	0x5B6B	#CJK UNIFIED IDEOGRAPH
+0x91B8	0x5C0A	#CJK UNIFIED IDEOGRAPH
+0x91B9	0x640D	#CJK UNIFIED IDEOGRAPH
+0x91BA	0x6751	#CJK UNIFIED IDEOGRAPH
+0x91BB	0x905C	#CJK UNIFIED IDEOGRAPH
+0x91BC	0x4ED6	#CJK UNIFIED IDEOGRAPH
+0x91BD	0x591A	#CJK UNIFIED IDEOGRAPH
+0x91BE	0x592A	#CJK UNIFIED IDEOGRAPH
+0x91BF	0x6C70	#CJK UNIFIED IDEOGRAPH
+0x91C0	0x8A51	#CJK UNIFIED IDEOGRAPH
+0x91C1	0x553E	#CJK UNIFIED IDEOGRAPH
+0x91C2	0x5815	#CJK UNIFIED IDEOGRAPH
+0x91C3	0x59A5	#CJK UNIFIED IDEOGRAPH
+0x91C4	0x60F0	#CJK UNIFIED IDEOGRAPH
+0x91C5	0x6253	#CJK UNIFIED IDEOGRAPH
+0x91C6	0x67C1	#CJK UNIFIED IDEOGRAPH
+0x91C7	0x8235	#CJK UNIFIED IDEOGRAPH
+0x91C8	0x6955	#CJK UNIFIED IDEOGRAPH
+0x91C9	0x9640	#CJK UNIFIED IDEOGRAPH
+0x91CA	0x99C4	#CJK UNIFIED IDEOGRAPH
+0x91CB	0x9A28	#CJK UNIFIED IDEOGRAPH
+0x91CC	0x4F53	#CJK UNIFIED IDEOGRAPH
+0x91CD	0x5806	#CJK UNIFIED IDEOGRAPH
+0x91CE	0x5BFE	#CJK UNIFIED IDEOGRAPH
+0x91CF	0x8010	#CJK UNIFIED IDEOGRAPH
+0x91D0	0x5CB1	#CJK UNIFIED IDEOGRAPH
+0x91D1	0x5E2F	#CJK UNIFIED IDEOGRAPH
+0x91D2	0x5F85	#CJK UNIFIED IDEOGRAPH
+0x91D3	0x6020	#CJK UNIFIED IDEOGRAPH
+0x91D4	0x614B	#CJK UNIFIED IDEOGRAPH
+0x91D5	0x6234	#CJK UNIFIED IDEOGRAPH
+0x91D6	0x66FF	#CJK UNIFIED IDEOGRAPH
+0x91D7	0x6CF0	#CJK UNIFIED IDEOGRAPH
+0x91D8	0x6EDE	#CJK UNIFIED IDEOGRAPH
+0x91D9	0x80CE	#CJK UNIFIED IDEOGRAPH
+0x91DA	0x817F	#CJK UNIFIED IDEOGRAPH
+0x91DB	0x82D4	#CJK UNIFIED IDEOGRAPH
+0x91DC	0x888B	#CJK UNIFIED IDEOGRAPH
+0x91DD	0x8CB8	#CJK UNIFIED IDEOGRAPH
+0x91DE	0x9000	#CJK UNIFIED IDEOGRAPH
+0x91DF	0x902E	#CJK UNIFIED IDEOGRAPH
+0x91E0	0x968A	#CJK UNIFIED IDEOGRAPH
+0x91E1	0x9EDB	#CJK UNIFIED IDEOGRAPH
+0x91E2	0x9BDB	#CJK UNIFIED IDEOGRAPH
+0x91E3	0x4EE3	#CJK UNIFIED IDEOGRAPH
+0x91E4	0x53F0	#CJK UNIFIED IDEOGRAPH
+0x91E5	0x5927	#CJK UNIFIED IDEOGRAPH
+0x91E6	0x7B2C	#CJK UNIFIED IDEOGRAPH
+0x91E7	0x918D	#CJK UNIFIED IDEOGRAPH
+0x91E8	0x984C	#CJK UNIFIED IDEOGRAPH
+0x91E9	0x9DF9	#CJK UNIFIED IDEOGRAPH
+0x91EA	0x6EDD	#CJK UNIFIED IDEOGRAPH
+0x91EB	0x7027	#CJK UNIFIED IDEOGRAPH
+0x91EC	0x5353	#CJK UNIFIED IDEOGRAPH
+0x91ED	0x5544	#CJK UNIFIED IDEOGRAPH
+0x91EE	0x5B85	#CJK UNIFIED IDEOGRAPH
+0x91EF	0x6258	#CJK UNIFIED IDEOGRAPH
+0x91F0	0x629E	#CJK UNIFIED IDEOGRAPH
+0x91F1	0x62D3	#CJK UNIFIED IDEOGRAPH
+0x91F2	0x6CA2	#CJK UNIFIED IDEOGRAPH
+0x91F3	0x6FEF	#CJK UNIFIED IDEOGRAPH
+0x91F4	0x7422	#CJK UNIFIED IDEOGRAPH
+0x91F5	0x8A17	#CJK UNIFIED IDEOGRAPH
+0x91F6	0x9438	#CJK UNIFIED IDEOGRAPH
+0x91F7	0x6FC1	#CJK UNIFIED IDEOGRAPH
+0x91F8	0x8AFE	#CJK UNIFIED IDEOGRAPH
+0x91F9	0x8338	#CJK UNIFIED IDEOGRAPH
+0x91FA	0x51E7	#CJK UNIFIED IDEOGRAPH
+0x91FB	0x86F8	#CJK UNIFIED IDEOGRAPH
+0x91FC	0x53EA	#CJK UNIFIED IDEOGRAPH
+0x9240	0x53E9	#CJK UNIFIED IDEOGRAPH
+0x9241	0x4F46	#CJK UNIFIED IDEOGRAPH
+0x9242	0x9054	#CJK UNIFIED IDEOGRAPH
+0x9243	0x8FB0	#CJK UNIFIED IDEOGRAPH
+0x9244	0x596A	#CJK UNIFIED IDEOGRAPH
+0x9245	0x8131	#CJK UNIFIED IDEOGRAPH
+0x9246	0x5DFD	#CJK UNIFIED IDEOGRAPH
+0x9247	0x7AEA	#CJK UNIFIED IDEOGRAPH
+0x9248	0x8FBF	#CJK UNIFIED IDEOGRAPH
+0x9249	0x68DA	#CJK UNIFIED IDEOGRAPH
+0x924A	0x8C37	#CJK UNIFIED IDEOGRAPH
+0x924B	0x72F8	#CJK UNIFIED IDEOGRAPH
+0x924C	0x9C48	#CJK UNIFIED IDEOGRAPH
+0x924D	0x6A3D	#CJK UNIFIED IDEOGRAPH
+0x924E	0x8AB0	#CJK UNIFIED IDEOGRAPH
+0x924F	0x4E39	#CJK UNIFIED IDEOGRAPH
+0x9250	0x5358	#CJK UNIFIED IDEOGRAPH
+0x9251	0x5606	#CJK UNIFIED IDEOGRAPH
+0x9252	0x5766	#CJK UNIFIED IDEOGRAPH
+0x9253	0x62C5	#CJK UNIFIED IDEOGRAPH
+0x9254	0x63A2	#CJK UNIFIED IDEOGRAPH
+0x9255	0x65E6	#CJK UNIFIED IDEOGRAPH
+0x9256	0x6B4E	#CJK UNIFIED IDEOGRAPH
+0x9257	0x6DE1	#CJK UNIFIED IDEOGRAPH
+0x9258	0x6E5B	#CJK UNIFIED IDEOGRAPH
+0x9259	0x70AD	#CJK UNIFIED IDEOGRAPH
+0x925A	0x77ED	#CJK UNIFIED IDEOGRAPH
+0x925B	0x7AEF	#CJK UNIFIED IDEOGRAPH
+0x925C	0x7BAA	#CJK UNIFIED IDEOGRAPH
+0x925D	0x7DBB	#CJK UNIFIED IDEOGRAPH
+0x925E	0x803D	#CJK UNIFIED IDEOGRAPH
+0x925F	0x80C6	#CJK UNIFIED IDEOGRAPH
+0x9260	0x86CB	#CJK UNIFIED IDEOGRAPH
+0x9261	0x8A95	#CJK UNIFIED IDEOGRAPH
+0x9262	0x935B	#CJK UNIFIED IDEOGRAPH
+0x9263	0x56E3	#CJK UNIFIED IDEOGRAPH
+0x9264	0x58C7	#CJK UNIFIED IDEOGRAPH
+0x9265	0x5F3E	#CJK UNIFIED IDEOGRAPH
+0x9266	0x65AD	#CJK UNIFIED IDEOGRAPH
+0x9267	0x6696	#CJK UNIFIED IDEOGRAPH
+0x9268	0x6A80	#CJK UNIFIED IDEOGRAPH
+0x9269	0x6BB5	#CJK UNIFIED IDEOGRAPH
+0x926A	0x7537	#CJK UNIFIED IDEOGRAPH
+0x926B	0x8AC7	#CJK UNIFIED IDEOGRAPH
+0x926C	0x5024	#CJK UNIFIED IDEOGRAPH
+0x926D	0x77E5	#CJK UNIFIED IDEOGRAPH
+0x926E	0x5730	#CJK UNIFIED IDEOGRAPH
+0x926F	0x5F1B	#CJK UNIFIED IDEOGRAPH
+0x9270	0x6065	#CJK UNIFIED IDEOGRAPH
+0x9271	0x667A	#CJK UNIFIED IDEOGRAPH
+0x9272	0x6C60	#CJK UNIFIED IDEOGRAPH
+0x9273	0x75F4	#CJK UNIFIED IDEOGRAPH
+0x9274	0x7A1A	#CJK UNIFIED IDEOGRAPH
+0x9275	0x7F6E	#CJK UNIFIED IDEOGRAPH
+0x9276	0x81F4	#CJK UNIFIED IDEOGRAPH
+0x9277	0x8718	#CJK UNIFIED IDEOGRAPH
+0x9278	0x9045	#CJK UNIFIED IDEOGRAPH
+0x9279	0x99B3	#CJK UNIFIED IDEOGRAPH
+0x927A	0x7BC9	#CJK UNIFIED IDEOGRAPH
+0x927B	0x755C	#CJK UNIFIED IDEOGRAPH
+0x927C	0x7AF9	#CJK UNIFIED IDEOGRAPH
+0x927D	0x7B51	#CJK UNIFIED IDEOGRAPH
+0x927E	0x84C4	#CJK UNIFIED IDEOGRAPH
+0x9280	0x9010	#CJK UNIFIED IDEOGRAPH
+0x9281	0x79E9	#CJK UNIFIED IDEOGRAPH
+0x9282	0x7A92	#CJK UNIFIED IDEOGRAPH
+0x9283	0x8336	#CJK UNIFIED IDEOGRAPH
+0x9284	0x5AE1	#CJK UNIFIED IDEOGRAPH
+0x9285	0x7740	#CJK UNIFIED IDEOGRAPH
+0x9286	0x4E2D	#CJK UNIFIED IDEOGRAPH
+0x9287	0x4EF2	#CJK UNIFIED IDEOGRAPH
+0x9288	0x5B99	#CJK UNIFIED IDEOGRAPH
+0x9289	0x5FE0	#CJK UNIFIED IDEOGRAPH
+0x928A	0x62BD	#CJK UNIFIED IDEOGRAPH
+0x928B	0x663C	#CJK UNIFIED IDEOGRAPH
+0x928C	0x67F1	#CJK UNIFIED IDEOGRAPH
+0x928D	0x6CE8	#CJK UNIFIED IDEOGRAPH
+0x928E	0x866B	#CJK UNIFIED IDEOGRAPH
+0x928F	0x8877	#CJK UNIFIED IDEOGRAPH
+0x9290	0x8A3B	#CJK UNIFIED IDEOGRAPH
+0x9291	0x914E	#CJK UNIFIED IDEOGRAPH
+0x9292	0x92F3	#CJK UNIFIED IDEOGRAPH
+0x9293	0x99D0	#CJK UNIFIED IDEOGRAPH
+0x9294	0x6A17	#CJK UNIFIED IDEOGRAPH
+0x9295	0x7026	#CJK UNIFIED IDEOGRAPH
+0x9296	0x732A	#CJK UNIFIED IDEOGRAPH
+0x9297	0x82E7	#CJK UNIFIED IDEOGRAPH
+0x9298	0x8457	#CJK UNIFIED IDEOGRAPH
+0x9299	0x8CAF	#CJK UNIFIED IDEOGRAPH
+0x929A	0x4E01	#CJK UNIFIED IDEOGRAPH
+0x929B	0x5146	#CJK UNIFIED IDEOGRAPH
+0x929C	0x51CB	#CJK UNIFIED IDEOGRAPH
+0x929D	0x558B	#CJK UNIFIED IDEOGRAPH
+0x929E	0x5BF5	#CJK UNIFIED IDEOGRAPH
+0x929F	0x5E16	#CJK UNIFIED IDEOGRAPH
+0x92A0	0x5E33	#CJK UNIFIED IDEOGRAPH
+0x92A1	0x5E81	#CJK UNIFIED IDEOGRAPH
+0x92A2	0x5F14	#CJK UNIFIED IDEOGRAPH
+0x92A3	0x5F35	#CJK UNIFIED IDEOGRAPH
+0x92A4	0x5F6B	#CJK UNIFIED IDEOGRAPH
+0x92A5	0x5FB4	#CJK UNIFIED IDEOGRAPH
+0x92A6	0x61F2	#CJK UNIFIED IDEOGRAPH
+0x92A7	0x6311	#CJK UNIFIED IDEOGRAPH
+0x92A8	0x66A2	#CJK UNIFIED IDEOGRAPH
+0x92A9	0x671D	#CJK UNIFIED IDEOGRAPH
+0x92AA	0x6F6E	#CJK UNIFIED IDEOGRAPH
+0x92AB	0x7252	#CJK UNIFIED IDEOGRAPH
+0x92AC	0x753A	#CJK UNIFIED IDEOGRAPH
+0x92AD	0x773A	#CJK UNIFIED IDEOGRAPH
+0x92AE	0x8074	#CJK UNIFIED IDEOGRAPH
+0x92AF	0x8139	#CJK UNIFIED IDEOGRAPH
+0x92B0	0x8178	#CJK UNIFIED IDEOGRAPH
+0x92B1	0x8776	#CJK UNIFIED IDEOGRAPH
+0x92B2	0x8ABF	#CJK UNIFIED IDEOGRAPH
+0x92B3	0x8ADC	#CJK UNIFIED IDEOGRAPH
+0x92B4	0x8D85	#CJK UNIFIED IDEOGRAPH
+0x92B5	0x8DF3	#CJK UNIFIED IDEOGRAPH
+0x92B6	0x929A	#CJK UNIFIED IDEOGRAPH
+0x92B7	0x9577	#CJK UNIFIED IDEOGRAPH
+0x92B8	0x9802	#CJK UNIFIED IDEOGRAPH
+0x92B9	0x9CE5	#CJK UNIFIED IDEOGRAPH
+0x92BA	0x52C5	#CJK UNIFIED IDEOGRAPH
+0x92BB	0x6357	#CJK UNIFIED IDEOGRAPH
+0x92BC	0x76F4	#CJK UNIFIED IDEOGRAPH
+0x92BD	0x6715	#CJK UNIFIED IDEOGRAPH
+0x92BE	0x6C88	#CJK UNIFIED IDEOGRAPH
+0x92BF	0x73CD	#CJK UNIFIED IDEOGRAPH
+0x92C0	0x8CC3	#CJK UNIFIED IDEOGRAPH
+0x92C1	0x93AE	#CJK UNIFIED IDEOGRAPH
+0x92C2	0x9673	#CJK UNIFIED IDEOGRAPH
+0x92C3	0x6D25	#CJK UNIFIED IDEOGRAPH
+0x92C4	0x589C	#CJK UNIFIED IDEOGRAPH
+0x92C5	0x690E	#CJK UNIFIED IDEOGRAPH
+0x92C6	0x69CC	#CJK UNIFIED IDEOGRAPH
+0x92C7	0x8FFD	#CJK UNIFIED IDEOGRAPH
+0x92C8	0x939A	#CJK UNIFIED IDEOGRAPH
+0x92C9	0x75DB	#CJK UNIFIED IDEOGRAPH
+0x92CA	0x901A	#CJK UNIFIED IDEOGRAPH
+0x92CB	0x585A	#CJK UNIFIED IDEOGRAPH
+0x92CC	0x6802	#CJK UNIFIED IDEOGRAPH
+0x92CD	0x63B4	#CJK UNIFIED IDEOGRAPH
+0x92CE	0x69FB	#CJK UNIFIED IDEOGRAPH
+0x92CF	0x4F43	#CJK UNIFIED IDEOGRAPH
+0x92D0	0x6F2C	#CJK UNIFIED IDEOGRAPH
+0x92D1	0x67D8	#CJK UNIFIED IDEOGRAPH
+0x92D2	0x8FBB	#CJK UNIFIED IDEOGRAPH
+0x92D3	0x8526	#CJK UNIFIED IDEOGRAPH
+0x92D4	0x7DB4	#CJK UNIFIED IDEOGRAPH
+0x92D5	0x9354	#CJK UNIFIED IDEOGRAPH
+0x92D6	0x693F	#CJK UNIFIED IDEOGRAPH
+0x92D7	0x6F70	#CJK UNIFIED IDEOGRAPH
+0x92D8	0x576A	#CJK UNIFIED IDEOGRAPH
+0x92D9	0x58F7	#CJK UNIFIED IDEOGRAPH
+0x92DA	0x5B2C	#CJK UNIFIED IDEOGRAPH
+0x92DB	0x7D2C	#CJK UNIFIED IDEOGRAPH
+0x92DC	0x722A	#CJK UNIFIED IDEOGRAPH
+0x92DD	0x540A	#CJK UNIFIED IDEOGRAPH
+0x92DE	0x91E3	#CJK UNIFIED IDEOGRAPH
+0x92DF	0x9DB4	#CJK UNIFIED IDEOGRAPH
+0x92E0	0x4EAD	#CJK UNIFIED IDEOGRAPH
+0x92E1	0x4F4E	#CJK UNIFIED IDEOGRAPH
+0x92E2	0x505C	#CJK UNIFIED IDEOGRAPH
+0x92E3	0x5075	#CJK UNIFIED IDEOGRAPH
+0x92E4	0x5243	#CJK UNIFIED IDEOGRAPH
+0x92E5	0x8C9E	#CJK UNIFIED IDEOGRAPH
+0x92E6	0x5448	#CJK UNIFIED IDEOGRAPH
+0x92E7	0x5824	#CJK UNIFIED IDEOGRAPH
+0x92E8	0x5B9A	#CJK UNIFIED IDEOGRAPH
+0x92E9	0x5E1D	#CJK UNIFIED IDEOGRAPH
+0x92EA	0x5E95	#CJK UNIFIED IDEOGRAPH
+0x92EB	0x5EAD	#CJK UNIFIED IDEOGRAPH
+0x92EC	0x5EF7	#CJK UNIFIED IDEOGRAPH
+0x92ED	0x5F1F	#CJK UNIFIED IDEOGRAPH
+0x92EE	0x608C	#CJK UNIFIED IDEOGRAPH
+0x92EF	0x62B5	#CJK UNIFIED IDEOGRAPH
+0x92F0	0x633A	#CJK UNIFIED IDEOGRAPH
+0x92F1	0x63D0	#CJK UNIFIED IDEOGRAPH
+0x92F2	0x68AF	#CJK UNIFIED IDEOGRAPH
+0x92F3	0x6C40	#CJK UNIFIED IDEOGRAPH
+0x92F4	0x7887	#CJK UNIFIED IDEOGRAPH
+0x92F5	0x798E	#CJK UNIFIED IDEOGRAPH
+0x92F6	0x7A0B	#CJK UNIFIED IDEOGRAPH
+0x92F7	0x7DE0	#CJK UNIFIED IDEOGRAPH
+0x92F8	0x8247	#CJK UNIFIED IDEOGRAPH
+0x92F9	0x8A02	#CJK UNIFIED IDEOGRAPH
+0x92FA	0x8AE6	#CJK UNIFIED IDEOGRAPH
+0x92FB	0x8E44	#CJK UNIFIED IDEOGRAPH
+0x92FC	0x9013	#CJK UNIFIED IDEOGRAPH
+0x9340	0x90B8	#CJK UNIFIED IDEOGRAPH
+0x9341	0x912D	#CJK UNIFIED IDEOGRAPH
+0x9342	0x91D8	#CJK UNIFIED IDEOGRAPH
+0x9343	0x9F0E	#CJK UNIFIED IDEOGRAPH
+0x9344	0x6CE5	#CJK UNIFIED IDEOGRAPH
+0x9345	0x6458	#CJK UNIFIED IDEOGRAPH
+0x9346	0x64E2	#CJK UNIFIED IDEOGRAPH
+0x9347	0x6575	#CJK UNIFIED IDEOGRAPH
+0x9348	0x6EF4	#CJK UNIFIED IDEOGRAPH
+0x9349	0x7684	#CJK UNIFIED IDEOGRAPH
+0x934A	0x7B1B	#CJK UNIFIED IDEOGRAPH
+0x934B	0x9069	#CJK UNIFIED IDEOGRAPH
+0x934C	0x93D1	#CJK UNIFIED IDEOGRAPH
+0x934D	0x6EBA	#CJK UNIFIED IDEOGRAPH
+0x934E	0x54F2	#CJK UNIFIED IDEOGRAPH
+0x934F	0x5FB9	#CJK UNIFIED IDEOGRAPH
+0x9350	0x64A4	#CJK UNIFIED IDEOGRAPH
+0x9351	0x8F4D	#CJK UNIFIED IDEOGRAPH
+0x9352	0x8FED	#CJK UNIFIED IDEOGRAPH
+0x9353	0x9244	#CJK UNIFIED IDEOGRAPH
+0x9354	0x5178	#CJK UNIFIED IDEOGRAPH
+0x9355	0x586B	#CJK UNIFIED IDEOGRAPH
+0x9356	0x5929	#CJK UNIFIED IDEOGRAPH
+0x9357	0x5C55	#CJK UNIFIED IDEOGRAPH
+0x9358	0x5E97	#CJK UNIFIED IDEOGRAPH
+0x9359	0x6DFB	#CJK UNIFIED IDEOGRAPH
+0x935A	0x7E8F	#CJK UNIFIED IDEOGRAPH
+0x935B	0x751C	#CJK UNIFIED IDEOGRAPH
+0x935C	0x8CBC	#CJK UNIFIED IDEOGRAPH
+0x935D	0x8EE2	#CJK UNIFIED IDEOGRAPH
+0x935E	0x985B	#CJK UNIFIED IDEOGRAPH
+0x935F	0x70B9	#CJK UNIFIED IDEOGRAPH
+0x9360	0x4F1D	#CJK UNIFIED IDEOGRAPH
+0x9361	0x6BBF	#CJK UNIFIED IDEOGRAPH
+0x9362	0x6FB1	#CJK UNIFIED IDEOGRAPH
+0x9363	0x7530	#CJK UNIFIED IDEOGRAPH
+0x9364	0x96FB	#CJK UNIFIED IDEOGRAPH
+0x9365	0x514E	#CJK UNIFIED IDEOGRAPH
+0x9366	0x5410	#CJK UNIFIED IDEOGRAPH
+0x9367	0x5835	#CJK UNIFIED IDEOGRAPH
+0x9368	0x5857	#CJK UNIFIED IDEOGRAPH
+0x9369	0x59AC	#CJK UNIFIED IDEOGRAPH
+0x936A	0x5C60	#CJK UNIFIED IDEOGRAPH
+0x936B	0x5F92	#CJK UNIFIED IDEOGRAPH
+0x936C	0x6597	#CJK UNIFIED IDEOGRAPH
+0x936D	0x675C	#CJK UNIFIED IDEOGRAPH
+0x936E	0x6E21	#CJK UNIFIED IDEOGRAPH
+0x936F	0x767B	#CJK UNIFIED IDEOGRAPH
+0x9370	0x83DF	#CJK UNIFIED IDEOGRAPH
+0x9371	0x8CED	#CJK UNIFIED IDEOGRAPH
+0x9372	0x9014	#CJK UNIFIED IDEOGRAPH
+0x9373	0x90FD	#CJK UNIFIED IDEOGRAPH
+0x9374	0x934D	#CJK UNIFIED IDEOGRAPH
+0x9375	0x7825	#CJK UNIFIED IDEOGRAPH
+0x9376	0x783A	#CJK UNIFIED IDEOGRAPH
+0x9377	0x52AA	#CJK UNIFIED IDEOGRAPH
+0x9378	0x5EA6	#CJK UNIFIED IDEOGRAPH
+0x9379	0x571F	#CJK UNIFIED IDEOGRAPH
+0x937A	0x5974	#CJK UNIFIED IDEOGRAPH
+0x937B	0x6012	#CJK UNIFIED IDEOGRAPH
+0x937C	0x5012	#CJK UNIFIED IDEOGRAPH
+0x937D	0x515A	#CJK UNIFIED IDEOGRAPH
+0x937E	0x51AC	#CJK UNIFIED IDEOGRAPH
+0x9380	0x51CD	#CJK UNIFIED IDEOGRAPH
+0x9381	0x5200	#CJK UNIFIED IDEOGRAPH
+0x9382	0x5510	#CJK UNIFIED IDEOGRAPH
+0x9383	0x5854	#CJK UNIFIED IDEOGRAPH
+0x9384	0x5858	#CJK UNIFIED IDEOGRAPH
+0x9385	0x5957	#CJK UNIFIED IDEOGRAPH
+0x9386	0x5B95	#CJK UNIFIED IDEOGRAPH
+0x9387	0x5CF6	#CJK UNIFIED IDEOGRAPH
+0x9388	0x5D8B	#CJK UNIFIED IDEOGRAPH
+0x9389	0x60BC	#CJK UNIFIED IDEOGRAPH
+0x938A	0x6295	#CJK UNIFIED IDEOGRAPH
+0x938B	0x642D	#CJK UNIFIED IDEOGRAPH
+0x938C	0x6771	#CJK UNIFIED IDEOGRAPH
+0x938D	0x6843	#CJK UNIFIED IDEOGRAPH
+0x938E	0x68BC	#CJK UNIFIED IDEOGRAPH
+0x938F	0x68DF	#CJK UNIFIED IDEOGRAPH
+0x9390	0x76D7	#CJK UNIFIED IDEOGRAPH
+0x9391	0x6DD8	#CJK UNIFIED IDEOGRAPH
+0x9392	0x6E6F	#CJK UNIFIED IDEOGRAPH
+0x9393	0x6D9B	#CJK UNIFIED IDEOGRAPH
+0x9394	0x706F	#CJK UNIFIED IDEOGRAPH
+0x9395	0x71C8	#CJK UNIFIED IDEOGRAPH
+0x9396	0x5F53	#CJK UNIFIED IDEOGRAPH
+0x9397	0x75D8	#CJK UNIFIED IDEOGRAPH
+0x9398	0x7977	#CJK UNIFIED IDEOGRAPH
+0x9399	0x7B49	#CJK UNIFIED IDEOGRAPH
+0x939A	0x7B54	#CJK UNIFIED IDEOGRAPH
+0x939B	0x7B52	#CJK UNIFIED IDEOGRAPH
+0x939C	0x7CD6	#CJK UNIFIED IDEOGRAPH
+0x939D	0x7D71	#CJK UNIFIED IDEOGRAPH
+0x939E	0x5230	#CJK UNIFIED IDEOGRAPH
+0x939F	0x8463	#CJK UNIFIED IDEOGRAPH
+0x93A0	0x8569	#CJK UNIFIED IDEOGRAPH
+0x93A1	0x85E4	#CJK UNIFIED IDEOGRAPH
+0x93A2	0x8A0E	#CJK UNIFIED IDEOGRAPH
+0x93A3	0x8B04	#CJK UNIFIED IDEOGRAPH
+0x93A4	0x8C46	#CJK UNIFIED IDEOGRAPH
+0x93A5	0x8E0F	#CJK UNIFIED IDEOGRAPH
+0x93A6	0x9003	#CJK UNIFIED IDEOGRAPH
+0x93A7	0x900F	#CJK UNIFIED IDEOGRAPH
+0x93A8	0x9419	#CJK UNIFIED IDEOGRAPH
+0x93A9	0x9676	#CJK UNIFIED IDEOGRAPH
+0x93AA	0x982D	#CJK UNIFIED IDEOGRAPH
+0x93AB	0x9A30	#CJK UNIFIED IDEOGRAPH
+0x93AC	0x95D8	#CJK UNIFIED IDEOGRAPH
+0x93AD	0x50CD	#CJK UNIFIED IDEOGRAPH
+0x93AE	0x52D5	#CJK UNIFIED IDEOGRAPH
+0x93AF	0x540C	#CJK UNIFIED IDEOGRAPH
+0x93B0	0x5802	#CJK UNIFIED IDEOGRAPH
+0x93B1	0x5C0E	#CJK UNIFIED IDEOGRAPH
+0x93B2	0x61A7	#CJK UNIFIED IDEOGRAPH
+0x93B3	0x649E	#CJK UNIFIED IDEOGRAPH
+0x93B4	0x6D1E	#CJK UNIFIED IDEOGRAPH
+0x93B5	0x77B3	#CJK UNIFIED IDEOGRAPH
+0x93B6	0x7AE5	#CJK UNIFIED IDEOGRAPH
+0x93B7	0x80F4	#CJK UNIFIED IDEOGRAPH
+0x93B8	0x8404	#CJK UNIFIED IDEOGRAPH
+0x93B9	0x9053	#CJK UNIFIED IDEOGRAPH
+0x93BA	0x9285	#CJK UNIFIED IDEOGRAPH
+0x93BB	0x5CE0	#CJK UNIFIED IDEOGRAPH
+0x93BC	0x9D07	#CJK UNIFIED IDEOGRAPH
+0x93BD	0x533F	#CJK UNIFIED IDEOGRAPH
+0x93BE	0x5F97	#CJK UNIFIED IDEOGRAPH
+0x93BF	0x5FB3	#CJK UNIFIED IDEOGRAPH
+0x93C0	0x6D9C	#CJK UNIFIED IDEOGRAPH
+0x93C1	0x7279	#CJK UNIFIED IDEOGRAPH
+0x93C2	0x7763	#CJK UNIFIED IDEOGRAPH
+0x93C3	0x79BF	#CJK UNIFIED IDEOGRAPH
+0x93C4	0x7BE4	#CJK UNIFIED IDEOGRAPH
+0x93C5	0x6BD2	#CJK UNIFIED IDEOGRAPH
+0x93C6	0x72EC	#CJK UNIFIED IDEOGRAPH
+0x93C7	0x8AAD	#CJK UNIFIED IDEOGRAPH
+0x93C8	0x6803	#CJK UNIFIED IDEOGRAPH
+0x93C9	0x6A61	#CJK UNIFIED IDEOGRAPH
+0x93CA	0x51F8	#CJK UNIFIED IDEOGRAPH
+0x93CB	0x7A81	#CJK UNIFIED IDEOGRAPH
+0x93CC	0x6934	#CJK UNIFIED IDEOGRAPH
+0x93CD	0x5C4A	#CJK UNIFIED IDEOGRAPH
+0x93CE	0x9CF6	#CJK UNIFIED IDEOGRAPH
+0x93CF	0x82EB	#CJK UNIFIED IDEOGRAPH
+0x93D0	0x5BC5	#CJK UNIFIED IDEOGRAPH
+0x93D1	0x9149	#CJK UNIFIED IDEOGRAPH
+0x93D2	0x701E	#CJK UNIFIED IDEOGRAPH
+0x93D3	0x5678	#CJK UNIFIED IDEOGRAPH
+0x93D4	0x5C6F	#CJK UNIFIED IDEOGRAPH
+0x93D5	0x60C7	#CJK UNIFIED IDEOGRAPH
+0x93D6	0x6566	#CJK UNIFIED IDEOGRAPH
+0x93D7	0x6C8C	#CJK UNIFIED IDEOGRAPH
+0x93D8	0x8C5A	#CJK UNIFIED IDEOGRAPH
+0x93D9	0x9041	#CJK UNIFIED IDEOGRAPH
+0x93DA	0x9813	#CJK UNIFIED IDEOGRAPH
+0x93DB	0x5451	#CJK UNIFIED IDEOGRAPH
+0x93DC	0x66C7	#CJK UNIFIED IDEOGRAPH
+0x93DD	0x920D	#CJK UNIFIED IDEOGRAPH
+0x93DE	0x5948	#CJK UNIFIED IDEOGRAPH
+0x93DF	0x90A3	#CJK UNIFIED IDEOGRAPH
+0x93E0	0x5185	#CJK UNIFIED IDEOGRAPH
+0x93E1	0x4E4D	#CJK UNIFIED IDEOGRAPH
+0x93E2	0x51EA	#CJK UNIFIED IDEOGRAPH
+0x93E3	0x8599	#CJK UNIFIED IDEOGRAPH
+0x93E4	0x8B0E	#CJK UNIFIED IDEOGRAPH
+0x93E5	0x7058	#CJK UNIFIED IDEOGRAPH
+0x93E6	0x637A	#CJK UNIFIED IDEOGRAPH
+0x93E7	0x934B	#CJK UNIFIED IDEOGRAPH
+0x93E8	0x6962	#CJK UNIFIED IDEOGRAPH
+0x93E9	0x99B4	#CJK UNIFIED IDEOGRAPH
+0x93EA	0x7E04	#CJK UNIFIED IDEOGRAPH
+0x93EB	0x7577	#CJK UNIFIED IDEOGRAPH
+0x93EC	0x5357	#CJK UNIFIED IDEOGRAPH
+0x93ED	0x6960	#CJK UNIFIED IDEOGRAPH
+0x93EE	0x8EDF	#CJK UNIFIED IDEOGRAPH
+0x93EF	0x96E3	#CJK UNIFIED IDEOGRAPH
+0x93F0	0x6C5D	#CJK UNIFIED IDEOGRAPH
+0x93F1	0x4E8C	#CJK UNIFIED IDEOGRAPH
+0x93F2	0x5C3C	#CJK UNIFIED IDEOGRAPH
+0x93F3	0x5F10	#CJK UNIFIED IDEOGRAPH
+0x93F4	0x8FE9	#CJK UNIFIED IDEOGRAPH
+0x93F5	0x5302	#CJK UNIFIED IDEOGRAPH
+0x93F6	0x8CD1	#CJK UNIFIED IDEOGRAPH
+0x93F7	0x8089	#CJK UNIFIED IDEOGRAPH
+0x93F8	0x8679	#CJK UNIFIED IDEOGRAPH
+0x93F9	0x5EFF	#CJK UNIFIED IDEOGRAPH
+0x93FA	0x65E5	#CJK UNIFIED IDEOGRAPH
+0x93FB	0x4E73	#CJK UNIFIED IDEOGRAPH
+0x93FC	0x5165	#CJK UNIFIED IDEOGRAPH
+0x9440	0x5982	#CJK UNIFIED IDEOGRAPH
+0x9441	0x5C3F	#CJK UNIFIED IDEOGRAPH
+0x9442	0x97EE	#CJK UNIFIED IDEOGRAPH
+0x9443	0x4EFB	#CJK UNIFIED IDEOGRAPH
+0x9444	0x598A	#CJK UNIFIED IDEOGRAPH
+0x9445	0x5FCD	#CJK UNIFIED IDEOGRAPH
+0x9446	0x8A8D	#CJK UNIFIED IDEOGRAPH
+0x9447	0x6FE1	#CJK UNIFIED IDEOGRAPH
+0x9448	0x79B0	#CJK UNIFIED IDEOGRAPH
+0x9449	0x7962	#CJK UNIFIED IDEOGRAPH
+0x944A	0x5BE7	#CJK UNIFIED IDEOGRAPH
+0x944B	0x8471	#CJK UNIFIED IDEOGRAPH
+0x944C	0x732B	#CJK UNIFIED IDEOGRAPH
+0x944D	0x71B1	#CJK UNIFIED IDEOGRAPH
+0x944E	0x5E74	#CJK UNIFIED IDEOGRAPH
+0x944F	0x5FF5	#CJK UNIFIED IDEOGRAPH
+0x9450	0x637B	#CJK UNIFIED IDEOGRAPH
+0x9451	0x649A	#CJK UNIFIED IDEOGRAPH
+0x9452	0x71C3	#CJK UNIFIED IDEOGRAPH
+0x9453	0x7C98	#CJK UNIFIED IDEOGRAPH
+0x9454	0x4E43	#CJK UNIFIED IDEOGRAPH
+0x9455	0x5EFC	#CJK UNIFIED IDEOGRAPH
+0x9456	0x4E4B	#CJK UNIFIED IDEOGRAPH
+0x9457	0x57DC	#CJK UNIFIED IDEOGRAPH
+0x9458	0x56A2	#CJK UNIFIED IDEOGRAPH
+0x9459	0x60A9	#CJK UNIFIED IDEOGRAPH
+0x945A	0x6FC3	#CJK UNIFIED IDEOGRAPH
+0x945B	0x7D0D	#CJK UNIFIED IDEOGRAPH
+0x945C	0x80FD	#CJK UNIFIED IDEOGRAPH
+0x945D	0x8133	#CJK UNIFIED IDEOGRAPH
+0x945E	0x81BF	#CJK UNIFIED IDEOGRAPH
+0x945F	0x8FB2	#CJK UNIFIED IDEOGRAPH
+0x9460	0x8997	#CJK UNIFIED IDEOGRAPH
+0x9461	0x86A4	#CJK UNIFIED IDEOGRAPH
+0x9462	0x5DF4	#CJK UNIFIED IDEOGRAPH
+0x9463	0x628A	#CJK UNIFIED IDEOGRAPH
+0x9464	0x64AD	#CJK UNIFIED IDEOGRAPH
+0x9465	0x8987	#CJK UNIFIED IDEOGRAPH
+0x9466	0x6777	#CJK UNIFIED IDEOGRAPH
+0x9467	0x6CE2	#CJK UNIFIED IDEOGRAPH
+0x9468	0x6D3E	#CJK UNIFIED IDEOGRAPH
+0x9469	0x7436	#CJK UNIFIED IDEOGRAPH
+0x946A	0x7834	#CJK UNIFIED IDEOGRAPH
+0x946B	0x5A46	#CJK UNIFIED IDEOGRAPH
+0x946C	0x7F75	#CJK UNIFIED IDEOGRAPH
+0x946D	0x82AD	#CJK UNIFIED IDEOGRAPH
+0x946E	0x99AC	#CJK UNIFIED IDEOGRAPH
+0x946F	0x4FF3	#CJK UNIFIED IDEOGRAPH
+0x9470	0x5EC3	#CJK UNIFIED IDEOGRAPH
+0x9471	0x62DD	#CJK UNIFIED IDEOGRAPH
+0x9472	0x6392	#CJK UNIFIED IDEOGRAPH
+0x9473	0x6557	#CJK UNIFIED IDEOGRAPH
+0x9474	0x676F	#CJK UNIFIED IDEOGRAPH
+0x9475	0x76C3	#CJK UNIFIED IDEOGRAPH
+0x9476	0x724C	#CJK UNIFIED IDEOGRAPH
+0x9477	0x80CC	#CJK UNIFIED IDEOGRAPH
+0x9478	0x80BA	#CJK UNIFIED IDEOGRAPH
+0x9479	0x8F29	#CJK UNIFIED IDEOGRAPH
+0x947A	0x914D	#CJK UNIFIED IDEOGRAPH
+0x947B	0x500D	#CJK UNIFIED IDEOGRAPH
+0x947C	0x57F9	#CJK UNIFIED IDEOGRAPH
+0x947D	0x5A92	#CJK UNIFIED IDEOGRAPH
+0x947E	0x6885	#CJK UNIFIED IDEOGRAPH
+0x9480	0x6973	#CJK UNIFIED IDEOGRAPH
+0x9481	0x7164	#CJK UNIFIED IDEOGRAPH
+0x9482	0x72FD	#CJK UNIFIED IDEOGRAPH
+0x9483	0x8CB7	#CJK UNIFIED IDEOGRAPH
+0x9484	0x58F2	#CJK UNIFIED IDEOGRAPH
+0x9485	0x8CE0	#CJK UNIFIED IDEOGRAPH
+0x9486	0x966A	#CJK UNIFIED IDEOGRAPH
+0x9487	0x9019	#CJK UNIFIED IDEOGRAPH
+0x9488	0x877F	#CJK UNIFIED IDEOGRAPH
+0x9489	0x79E4	#CJK UNIFIED IDEOGRAPH
+0x948A	0x77E7	#CJK UNIFIED IDEOGRAPH
+0x948B	0x8429	#CJK UNIFIED IDEOGRAPH
+0x948C	0x4F2F	#CJK UNIFIED IDEOGRAPH
+0x948D	0x5265	#CJK UNIFIED IDEOGRAPH
+0x948E	0x535A	#CJK UNIFIED IDEOGRAPH
+0x948F	0x62CD	#CJK UNIFIED IDEOGRAPH
+0x9490	0x67CF	#CJK UNIFIED IDEOGRAPH
+0x9491	0x6CCA	#CJK UNIFIED IDEOGRAPH
+0x9492	0x767D	#CJK UNIFIED IDEOGRAPH
+0x9493	0x7B94	#CJK UNIFIED IDEOGRAPH
+0x9494	0x7C95	#CJK UNIFIED IDEOGRAPH
+0x9495	0x8236	#CJK UNIFIED IDEOGRAPH
+0x9496	0x8584	#CJK UNIFIED IDEOGRAPH
+0x9497	0x8FEB	#CJK UNIFIED IDEOGRAPH
+0x9498	0x66DD	#CJK UNIFIED IDEOGRAPH
+0x9499	0x6F20	#CJK UNIFIED IDEOGRAPH
+0x949A	0x7206	#CJK UNIFIED IDEOGRAPH
+0x949B	0x7E1B	#CJK UNIFIED IDEOGRAPH
+0x949C	0x83AB	#CJK UNIFIED IDEOGRAPH
+0x949D	0x99C1	#CJK UNIFIED IDEOGRAPH
+0x949E	0x9EA6	#CJK UNIFIED IDEOGRAPH
+0x949F	0x51FD	#CJK UNIFIED IDEOGRAPH
+0x94A0	0x7BB1	#CJK UNIFIED IDEOGRAPH
+0x94A1	0x7872	#CJK UNIFIED IDEOGRAPH
+0x94A2	0x7BB8	#CJK UNIFIED IDEOGRAPH
+0x94A3	0x8087	#CJK UNIFIED IDEOGRAPH
+0x94A4	0x7B48	#CJK UNIFIED IDEOGRAPH
+0x94A5	0x6AE8	#CJK UNIFIED IDEOGRAPH
+0x94A6	0x5E61	#CJK UNIFIED IDEOGRAPH
+0x94A7	0x808C	#CJK UNIFIED IDEOGRAPH
+0x94A8	0x7551	#CJK UNIFIED IDEOGRAPH
+0x94A9	0x7560	#CJK UNIFIED IDEOGRAPH
+0x94AA	0x516B	#CJK UNIFIED IDEOGRAPH
+0x94AB	0x9262	#CJK UNIFIED IDEOGRAPH
+0x94AC	0x6E8C	#CJK UNIFIED IDEOGRAPH
+0x94AD	0x767A	#CJK UNIFIED IDEOGRAPH
+0x94AE	0x9197	#CJK UNIFIED IDEOGRAPH
+0x94AF	0x9AEA	#CJK UNIFIED IDEOGRAPH
+0x94B0	0x4F10	#CJK UNIFIED IDEOGRAPH
+0x94B1	0x7F70	#CJK UNIFIED IDEOGRAPH
+0x94B2	0x629C	#CJK UNIFIED IDEOGRAPH
+0x94B3	0x7B4F	#CJK UNIFIED IDEOGRAPH
+0x94B4	0x95A5	#CJK UNIFIED IDEOGRAPH
+0x94B5	0x9CE9	#CJK UNIFIED IDEOGRAPH
+0x94B6	0x567A	#CJK UNIFIED IDEOGRAPH
+0x94B7	0x5859	#CJK UNIFIED IDEOGRAPH
+0x94B8	0x86E4	#CJK UNIFIED IDEOGRAPH
+0x94B9	0x96BC	#CJK UNIFIED IDEOGRAPH
+0x94BA	0x4F34	#CJK UNIFIED IDEOGRAPH
+0x94BB	0x5224	#CJK UNIFIED IDEOGRAPH
+0x94BC	0x534A	#CJK UNIFIED IDEOGRAPH
+0x94BD	0x53CD	#CJK UNIFIED IDEOGRAPH
+0x94BE	0x53DB	#CJK UNIFIED IDEOGRAPH
+0x94BF	0x5E06	#CJK UNIFIED IDEOGRAPH
+0x94C0	0x642C	#CJK UNIFIED IDEOGRAPH
+0x94C1	0x6591	#CJK UNIFIED IDEOGRAPH
+0x94C2	0x677F	#CJK UNIFIED IDEOGRAPH
+0x94C3	0x6C3E	#CJK UNIFIED IDEOGRAPH
+0x94C4	0x6C4E	#CJK UNIFIED IDEOGRAPH
+0x94C5	0x7248	#CJK UNIFIED IDEOGRAPH
+0x94C6	0x72AF	#CJK UNIFIED IDEOGRAPH
+0x94C7	0x73ED	#CJK UNIFIED IDEOGRAPH
+0x94C8	0x7554	#CJK UNIFIED IDEOGRAPH
+0x94C9	0x7E41	#CJK UNIFIED IDEOGRAPH
+0x94CA	0x822C	#CJK UNIFIED IDEOGRAPH
+0x94CB	0x85E9	#CJK UNIFIED IDEOGRAPH
+0x94CC	0x8CA9	#CJK UNIFIED IDEOGRAPH
+0x94CD	0x7BC4	#CJK UNIFIED IDEOGRAPH
+0x94CE	0x91C6	#CJK UNIFIED IDEOGRAPH
+0x94CF	0x7169	#CJK UNIFIED IDEOGRAPH
+0x94D0	0x9812	#CJK UNIFIED IDEOGRAPH
+0x94D1	0x98EF	#CJK UNIFIED IDEOGRAPH
+0x94D2	0x633D	#CJK UNIFIED IDEOGRAPH
+0x94D3	0x6669	#CJK UNIFIED IDEOGRAPH
+0x94D4	0x756A	#CJK UNIFIED IDEOGRAPH
+0x94D5	0x76E4	#CJK UNIFIED IDEOGRAPH
+0x94D6	0x78D0	#CJK UNIFIED IDEOGRAPH
+0x94D7	0x8543	#CJK UNIFIED IDEOGRAPH
+0x94D8	0x86EE	#CJK UNIFIED IDEOGRAPH
+0x94D9	0x532A	#CJK UNIFIED IDEOGRAPH
+0x94DA	0x5351	#CJK UNIFIED IDEOGRAPH
+0x94DB	0x5426	#CJK UNIFIED IDEOGRAPH
+0x94DC	0x5983	#CJK UNIFIED IDEOGRAPH
+0x94DD	0x5E87	#CJK UNIFIED IDEOGRAPH
+0x94DE	0x5F7C	#CJK UNIFIED IDEOGRAPH
+0x94DF	0x60B2	#CJK UNIFIED IDEOGRAPH
+0x94E0	0x6249	#CJK UNIFIED IDEOGRAPH
+0x94E1	0x6279	#CJK UNIFIED IDEOGRAPH
+0x94E2	0x62AB	#CJK UNIFIED IDEOGRAPH
+0x94E3	0x6590	#CJK UNIFIED IDEOGRAPH
+0x94E4	0x6BD4	#CJK UNIFIED IDEOGRAPH
+0x94E5	0x6CCC	#CJK UNIFIED IDEOGRAPH
+0x94E6	0x75B2	#CJK UNIFIED IDEOGRAPH
+0x94E7	0x76AE	#CJK UNIFIED IDEOGRAPH
+0x94E8	0x7891	#CJK UNIFIED IDEOGRAPH
+0x94E9	0x79D8	#CJK UNIFIED IDEOGRAPH
+0x94EA	0x7DCB	#CJK UNIFIED IDEOGRAPH
+0x94EB	0x7F77	#CJK UNIFIED IDEOGRAPH
+0x94EC	0x80A5	#CJK UNIFIED IDEOGRAPH
+0x94ED	0x88AB	#CJK UNIFIED IDEOGRAPH
+0x94EE	0x8AB9	#CJK UNIFIED IDEOGRAPH
+0x94EF	0x8CBB	#CJK UNIFIED IDEOGRAPH
+0x94F0	0x907F	#CJK UNIFIED IDEOGRAPH
+0x94F1	0x975E	#CJK UNIFIED IDEOGRAPH
+0x94F2	0x98DB	#CJK UNIFIED IDEOGRAPH
+0x94F3	0x6A0B	#CJK UNIFIED IDEOGRAPH
+0x94F4	0x7C38	#CJK UNIFIED IDEOGRAPH
+0x94F5	0x5099	#CJK UNIFIED IDEOGRAPH
+0x94F6	0x5C3E	#CJK UNIFIED IDEOGRAPH
+0x94F7	0x5FAE	#CJK UNIFIED IDEOGRAPH
+0x94F8	0x6787	#CJK UNIFIED IDEOGRAPH
+0x94F9	0x6BD8	#CJK UNIFIED IDEOGRAPH
+0x94FA	0x7435	#CJK UNIFIED IDEOGRAPH
+0x94FB	0x7709	#CJK UNIFIED IDEOGRAPH
+0x94FC	0x7F8E	#CJK UNIFIED IDEOGRAPH
+0x9540	0x9F3B	#CJK UNIFIED IDEOGRAPH
+0x9541	0x67CA	#CJK UNIFIED IDEOGRAPH
+0x9542	0x7A17	#CJK UNIFIED IDEOGRAPH
+0x9543	0x5339	#CJK UNIFIED IDEOGRAPH
+0x9544	0x758B	#CJK UNIFIED IDEOGRAPH
+0x9545	0x9AED	#CJK UNIFIED IDEOGRAPH
+0x9546	0x5F66	#CJK UNIFIED IDEOGRAPH
+0x9547	0x819D	#CJK UNIFIED IDEOGRAPH
+0x9548	0x83F1	#CJK UNIFIED IDEOGRAPH
+0x9549	0x8098	#CJK UNIFIED IDEOGRAPH
+0x954A	0x5F3C	#CJK UNIFIED IDEOGRAPH
+0x954B	0x5FC5	#CJK UNIFIED IDEOGRAPH
+0x954C	0x7562	#CJK UNIFIED IDEOGRAPH
+0x954D	0x7B46	#CJK UNIFIED IDEOGRAPH
+0x954E	0x903C	#CJK UNIFIED IDEOGRAPH
+0x954F	0x6867	#CJK UNIFIED IDEOGRAPH
+0x9550	0x59EB	#CJK UNIFIED IDEOGRAPH
+0x9551	0x5A9B	#CJK UNIFIED IDEOGRAPH
+0x9552	0x7D10	#CJK UNIFIED IDEOGRAPH
+0x9553	0x767E	#CJK UNIFIED IDEOGRAPH
+0x9554	0x8B2C	#CJK UNIFIED IDEOGRAPH
+0x9555	0x4FF5	#CJK UNIFIED IDEOGRAPH
+0x9556	0x5F6A	#CJK UNIFIED IDEOGRAPH
+0x9557	0x6A19	#CJK UNIFIED IDEOGRAPH
+0x9558	0x6C37	#CJK UNIFIED IDEOGRAPH
+0x9559	0x6F02	#CJK UNIFIED IDEOGRAPH
+0x955A	0x74E2	#CJK UNIFIED IDEOGRAPH
+0x955B	0x7968	#CJK UNIFIED IDEOGRAPH
+0x955C	0x8868	#CJK UNIFIED IDEOGRAPH
+0x955D	0x8A55	#CJK UNIFIED IDEOGRAPH
+0x955E	0x8C79	#CJK UNIFIED IDEOGRAPH
+0x955F	0x5EDF	#CJK UNIFIED IDEOGRAPH
+0x9560	0x63CF	#CJK UNIFIED IDEOGRAPH
+0x9561	0x75C5	#CJK UNIFIED IDEOGRAPH
+0x9562	0x79D2	#CJK UNIFIED IDEOGRAPH
+0x9563	0x82D7	#CJK UNIFIED IDEOGRAPH
+0x9564	0x9328	#CJK UNIFIED IDEOGRAPH
+0x9565	0x92F2	#CJK UNIFIED IDEOGRAPH
+0x9566	0x849C	#CJK UNIFIED IDEOGRAPH
+0x9567	0x86ED	#CJK UNIFIED IDEOGRAPH
+0x9568	0x9C2D	#CJK UNIFIED IDEOGRAPH
+0x9569	0x54C1	#CJK UNIFIED IDEOGRAPH
+0x956A	0x5F6C	#CJK UNIFIED IDEOGRAPH
+0x956B	0x658C	#CJK UNIFIED IDEOGRAPH
+0x956C	0x6D5C	#CJK UNIFIED IDEOGRAPH
+0x956D	0x7015	#CJK UNIFIED IDEOGRAPH
+0x956E	0x8CA7	#CJK UNIFIED IDEOGRAPH
+0x956F	0x8CD3	#CJK UNIFIED IDEOGRAPH
+0x9570	0x983B	#CJK UNIFIED IDEOGRAPH
+0x9571	0x654F	#CJK UNIFIED IDEOGRAPH
+0x9572	0x74F6	#CJK UNIFIED IDEOGRAPH
+0x9573	0x4E0D	#CJK UNIFIED IDEOGRAPH
+0x9574	0x4ED8	#CJK UNIFIED IDEOGRAPH
+0x9575	0x57E0	#CJK UNIFIED IDEOGRAPH
+0x9576	0x592B	#CJK UNIFIED IDEOGRAPH
+0x9577	0x5A66	#CJK UNIFIED IDEOGRAPH
+0x9578	0x5BCC	#CJK UNIFIED IDEOGRAPH
+0x9579	0x51A8	#CJK UNIFIED IDEOGRAPH
+0x957A	0x5E03	#CJK UNIFIED IDEOGRAPH
+0x957B	0x5E9C	#CJK UNIFIED IDEOGRAPH
+0x957C	0x6016	#CJK UNIFIED IDEOGRAPH
+0x957D	0x6276	#CJK UNIFIED IDEOGRAPH
+0x957E	0x6577	#CJK UNIFIED IDEOGRAPH
+0x9580	0x65A7	#CJK UNIFIED IDEOGRAPH
+0x9581	0x666E	#CJK UNIFIED IDEOGRAPH
+0x9582	0x6D6E	#CJK UNIFIED IDEOGRAPH
+0x9583	0x7236	#CJK UNIFIED IDEOGRAPH
+0x9584	0x7B26	#CJK UNIFIED IDEOGRAPH
+0x9585	0x8150	#CJK UNIFIED IDEOGRAPH
+0x9586	0x819A	#CJK UNIFIED IDEOGRAPH
+0x9587	0x8299	#CJK UNIFIED IDEOGRAPH
+0x9588	0x8B5C	#CJK UNIFIED IDEOGRAPH
+0x9589	0x8CA0	#CJK UNIFIED IDEOGRAPH
+0x958A	0x8CE6	#CJK UNIFIED IDEOGRAPH
+0x958B	0x8D74	#CJK UNIFIED IDEOGRAPH
+0x958C	0x961C	#CJK UNIFIED IDEOGRAPH
+0x958D	0x9644	#CJK UNIFIED IDEOGRAPH
+0x958E	0x4FAE	#CJK UNIFIED IDEOGRAPH
+0x958F	0x64AB	#CJK UNIFIED IDEOGRAPH
+0x9590	0x6B66	#CJK UNIFIED IDEOGRAPH
+0x9591	0x821E	#CJK UNIFIED IDEOGRAPH
+0x9592	0x8461	#CJK UNIFIED IDEOGRAPH
+0x9593	0x856A	#CJK UNIFIED IDEOGRAPH
+0x9594	0x90E8	#CJK UNIFIED IDEOGRAPH
+0x9595	0x5C01	#CJK UNIFIED IDEOGRAPH
+0x9596	0x6953	#CJK UNIFIED IDEOGRAPH
+0x9597	0x98A8	#CJK UNIFIED IDEOGRAPH
+0x9598	0x847A	#CJK UNIFIED IDEOGRAPH
+0x9599	0x8557	#CJK UNIFIED IDEOGRAPH
+0x959A	0x4F0F	#CJK UNIFIED IDEOGRAPH
+0x959B	0x526F	#CJK UNIFIED IDEOGRAPH
+0x959C	0x5FA9	#CJK UNIFIED IDEOGRAPH
+0x959D	0x5E45	#CJK UNIFIED IDEOGRAPH
+0x959E	0x670D	#CJK UNIFIED IDEOGRAPH
+0x959F	0x798F	#CJK UNIFIED IDEOGRAPH
+0x95A0	0x8179	#CJK UNIFIED IDEOGRAPH
+0x95A1	0x8907	#CJK UNIFIED IDEOGRAPH
+0x95A2	0x8986	#CJK UNIFIED IDEOGRAPH
+0x95A3	0x6DF5	#CJK UNIFIED IDEOGRAPH
+0x95A4	0x5F17	#CJK UNIFIED IDEOGRAPH
+0x95A5	0x6255	#CJK UNIFIED IDEOGRAPH
+0x95A6	0x6CB8	#CJK UNIFIED IDEOGRAPH
+0x95A7	0x4ECF	#CJK UNIFIED IDEOGRAPH
+0x95A8	0x7269	#CJK UNIFIED IDEOGRAPH
+0x95A9	0x9B92	#CJK UNIFIED IDEOGRAPH
+0x95AA	0x5206	#CJK UNIFIED IDEOGRAPH
+0x95AB	0x543B	#CJK UNIFIED IDEOGRAPH
+0x95AC	0x5674	#CJK UNIFIED IDEOGRAPH
+0x95AD	0x58B3	#CJK UNIFIED IDEOGRAPH
+0x95AE	0x61A4	#CJK UNIFIED IDEOGRAPH
+0x95AF	0x626E	#CJK UNIFIED IDEOGRAPH
+0x95B0	0x711A	#CJK UNIFIED IDEOGRAPH
+0x95B1	0x596E	#CJK UNIFIED IDEOGRAPH
+0x95B2	0x7C89	#CJK UNIFIED IDEOGRAPH
+0x95B3	0x7CDE	#CJK UNIFIED IDEOGRAPH
+0x95B4	0x7D1B	#CJK UNIFIED IDEOGRAPH
+0x95B5	0x96F0	#CJK UNIFIED IDEOGRAPH
+0x95B6	0x6587	#CJK UNIFIED IDEOGRAPH
+0x95B7	0x805E	#CJK UNIFIED IDEOGRAPH
+0x95B8	0x4E19	#CJK UNIFIED IDEOGRAPH
+0x95B9	0x4F75	#CJK UNIFIED IDEOGRAPH
+0x95BA	0x5175	#CJK UNIFIED IDEOGRAPH
+0x95BB	0x5840	#CJK UNIFIED IDEOGRAPH
+0x95BC	0x5E63	#CJK UNIFIED IDEOGRAPH
+0x95BD	0x5E73	#CJK UNIFIED IDEOGRAPH
+0x95BE	0x5F0A	#CJK UNIFIED IDEOGRAPH
+0x95BF	0x67C4	#CJK UNIFIED IDEOGRAPH
+0x95C0	0x4E26	#CJK UNIFIED IDEOGRAPH
+0x95C1	0x853D	#CJK UNIFIED IDEOGRAPH
+0x95C2	0x9589	#CJK UNIFIED IDEOGRAPH
+0x95C3	0x965B	#CJK UNIFIED IDEOGRAPH
+0x95C4	0x7C73	#CJK UNIFIED IDEOGRAPH
+0x95C5	0x9801	#CJK UNIFIED IDEOGRAPH
+0x95C6	0x50FB	#CJK UNIFIED IDEOGRAPH
+0x95C7	0x58C1	#CJK UNIFIED IDEOGRAPH
+0x95C8	0x7656	#CJK UNIFIED IDEOGRAPH
+0x95C9	0x78A7	#CJK UNIFIED IDEOGRAPH
+0x95CA	0x5225	#CJK UNIFIED IDEOGRAPH
+0x95CB	0x77A5	#CJK UNIFIED IDEOGRAPH
+0x95CC	0x8511	#CJK UNIFIED IDEOGRAPH
+0x95CD	0x7B86	#CJK UNIFIED IDEOGRAPH
+0x95CE	0x504F	#CJK UNIFIED IDEOGRAPH
+0x95CF	0x5909	#CJK UNIFIED IDEOGRAPH
+0x95D0	0x7247	#CJK UNIFIED IDEOGRAPH
+0x95D1	0x7BC7	#CJK UNIFIED IDEOGRAPH
+0x95D2	0x7DE8	#CJK UNIFIED IDEOGRAPH
+0x95D3	0x8FBA	#CJK UNIFIED IDEOGRAPH
+0x95D4	0x8FD4	#CJK UNIFIED IDEOGRAPH
+0x95D5	0x904D	#CJK UNIFIED IDEOGRAPH
+0x95D6	0x4FBF	#CJK UNIFIED IDEOGRAPH
+0x95D7	0x52C9	#CJK UNIFIED IDEOGRAPH
+0x95D8	0x5A29	#CJK UNIFIED IDEOGRAPH
+0x95D9	0x5F01	#CJK UNIFIED IDEOGRAPH
+0x95DA	0x97AD	#CJK UNIFIED IDEOGRAPH
+0x95DB	0x4FDD	#CJK UNIFIED IDEOGRAPH
+0x95DC	0x8217	#CJK UNIFIED IDEOGRAPH
+0x95DD	0x92EA	#CJK UNIFIED IDEOGRAPH
+0x95DE	0x5703	#CJK UNIFIED IDEOGRAPH
+0x95DF	0x6355	#CJK UNIFIED IDEOGRAPH
+0x95E0	0x6B69	#CJK UNIFIED IDEOGRAPH
+0x95E1	0x752B	#CJK UNIFIED IDEOGRAPH
+0x95E2	0x88DC	#CJK UNIFIED IDEOGRAPH
+0x95E3	0x8F14	#CJK UNIFIED IDEOGRAPH
+0x95E4	0x7A42	#CJK UNIFIED IDEOGRAPH
+0x95E5	0x52DF	#CJK UNIFIED IDEOGRAPH
+0x95E6	0x5893	#CJK UNIFIED IDEOGRAPH
+0x95E7	0x6155	#CJK UNIFIED IDEOGRAPH
+0x95E8	0x620A	#CJK UNIFIED IDEOGRAPH
+0x95E9	0x66AE	#CJK UNIFIED IDEOGRAPH
+0x95EA	0x6BCD	#CJK UNIFIED IDEOGRAPH
+0x95EB	0x7C3F	#CJK UNIFIED IDEOGRAPH
+0x95EC	0x83E9	#CJK UNIFIED IDEOGRAPH
+0x95ED	0x5023	#CJK UNIFIED IDEOGRAPH
+0x95EE	0x4FF8	#CJK UNIFIED IDEOGRAPH
+0x95EF	0x5305	#CJK UNIFIED IDEOGRAPH
+0x95F0	0x5446	#CJK UNIFIED IDEOGRAPH
+0x95F1	0x5831	#CJK UNIFIED IDEOGRAPH
+0x95F2	0x5949	#CJK UNIFIED IDEOGRAPH
+0x95F3	0x5B9D	#CJK UNIFIED IDEOGRAPH
+0x95F4	0x5CF0	#CJK UNIFIED IDEOGRAPH
+0x95F5	0x5CEF	#CJK UNIFIED IDEOGRAPH
+0x95F6	0x5D29	#CJK UNIFIED IDEOGRAPH
+0x95F7	0x5E96	#CJK UNIFIED IDEOGRAPH
+0x95F8	0x62B1	#CJK UNIFIED IDEOGRAPH
+0x95F9	0x6367	#CJK UNIFIED IDEOGRAPH
+0x95FA	0x653E	#CJK UNIFIED IDEOGRAPH
+0x95FB	0x65B9	#CJK UNIFIED IDEOGRAPH
+0x95FC	0x670B	#CJK UNIFIED IDEOGRAPH
+0x9640	0x6CD5	#CJK UNIFIED IDEOGRAPH
+0x9641	0x6CE1	#CJK UNIFIED IDEOGRAPH
+0x9642	0x70F9	#CJK UNIFIED IDEOGRAPH
+0x9643	0x7832	#CJK UNIFIED IDEOGRAPH
+0x9644	0x7E2B	#CJK UNIFIED IDEOGRAPH
+0x9645	0x80DE	#CJK UNIFIED IDEOGRAPH
+0x9646	0x82B3	#CJK UNIFIED IDEOGRAPH
+0x9647	0x840C	#CJK UNIFIED IDEOGRAPH
+0x9648	0x84EC	#CJK UNIFIED IDEOGRAPH
+0x9649	0x8702	#CJK UNIFIED IDEOGRAPH
+0x964A	0x8912	#CJK UNIFIED IDEOGRAPH
+0x964B	0x8A2A	#CJK UNIFIED IDEOGRAPH
+0x964C	0x8C4A	#CJK UNIFIED IDEOGRAPH
+0x964D	0x90A6	#CJK UNIFIED IDEOGRAPH
+0x964E	0x92D2	#CJK UNIFIED IDEOGRAPH
+0x964F	0x98FD	#CJK UNIFIED IDEOGRAPH
+0x9650	0x9CF3	#CJK UNIFIED IDEOGRAPH
+0x9651	0x9D6C	#CJK UNIFIED IDEOGRAPH
+0x9652	0x4E4F	#CJK UNIFIED IDEOGRAPH
+0x9653	0x4EA1	#CJK UNIFIED IDEOGRAPH
+0x9654	0x508D	#CJK UNIFIED IDEOGRAPH
+0x9655	0x5256	#CJK UNIFIED IDEOGRAPH
+0x9656	0x574A	#CJK UNIFIED IDEOGRAPH
+0x9657	0x59A8	#CJK UNIFIED IDEOGRAPH
+0x9658	0x5E3D	#CJK UNIFIED IDEOGRAPH
+0x9659	0x5FD8	#CJK UNIFIED IDEOGRAPH
+0x965A	0x5FD9	#CJK UNIFIED IDEOGRAPH
+0x965B	0x623F	#CJK UNIFIED IDEOGRAPH
+0x965C	0x66B4	#CJK UNIFIED IDEOGRAPH
+0x965D	0x671B	#CJK UNIFIED IDEOGRAPH
+0x965E	0x67D0	#CJK UNIFIED IDEOGRAPH
+0x965F	0x68D2	#CJK UNIFIED IDEOGRAPH
+0x9660	0x5192	#CJK UNIFIED IDEOGRAPH
+0x9661	0x7D21	#CJK UNIFIED IDEOGRAPH
+0x9662	0x80AA	#CJK UNIFIED IDEOGRAPH
+0x9663	0x81A8	#CJK UNIFIED IDEOGRAPH
+0x9664	0x8B00	#CJK UNIFIED IDEOGRAPH
+0x9665	0x8C8C	#CJK UNIFIED IDEOGRAPH
+0x9666	0x8CBF	#CJK UNIFIED IDEOGRAPH
+0x9667	0x927E	#CJK UNIFIED IDEOGRAPH
+0x9668	0x9632	#CJK UNIFIED IDEOGRAPH
+0x9669	0x5420	#CJK UNIFIED IDEOGRAPH
+0x966A	0x982C	#CJK UNIFIED IDEOGRAPH
+0x966B	0x5317	#CJK UNIFIED IDEOGRAPH
+0x966C	0x50D5	#CJK UNIFIED IDEOGRAPH
+0x966D	0x535C	#CJK UNIFIED IDEOGRAPH
+0x966E	0x58A8	#CJK UNIFIED IDEOGRAPH
+0x966F	0x64B2	#CJK UNIFIED IDEOGRAPH
+0x9670	0x6734	#CJK UNIFIED IDEOGRAPH
+0x9671	0x7267	#CJK UNIFIED IDEOGRAPH
+0x9672	0x7766	#CJK UNIFIED IDEOGRAPH
+0x9673	0x7A46	#CJK UNIFIED IDEOGRAPH
+0x9674	0x91E6	#CJK UNIFIED IDEOGRAPH
+0x9675	0x52C3	#CJK UNIFIED IDEOGRAPH
+0x9676	0x6CA1	#CJK UNIFIED IDEOGRAPH
+0x9677	0x6B86	#CJK UNIFIED IDEOGRAPH
+0x9678	0x5800	#CJK UNIFIED IDEOGRAPH
+0x9679	0x5E4C	#CJK UNIFIED IDEOGRAPH
+0x967A	0x5954	#CJK UNIFIED IDEOGRAPH
+0x967B	0x672C	#CJK UNIFIED IDEOGRAPH
+0x967C	0x7FFB	#CJK UNIFIED IDEOGRAPH
+0x967D	0x51E1	#CJK UNIFIED IDEOGRAPH
+0x967E	0x76C6	#CJK UNIFIED IDEOGRAPH
+0x9680	0x6469	#CJK UNIFIED IDEOGRAPH
+0x9681	0x78E8	#CJK UNIFIED IDEOGRAPH
+0x9682	0x9B54	#CJK UNIFIED IDEOGRAPH
+0x9683	0x9EBB	#CJK UNIFIED IDEOGRAPH
+0x9684	0x57CB	#CJK UNIFIED IDEOGRAPH
+0x9685	0x59B9	#CJK UNIFIED IDEOGRAPH
+0x9686	0x6627	#CJK UNIFIED IDEOGRAPH
+0x9687	0x679A	#CJK UNIFIED IDEOGRAPH
+0x9688	0x6BCE	#CJK UNIFIED IDEOGRAPH
+0x9689	0x54E9	#CJK UNIFIED IDEOGRAPH
+0x968A	0x69D9	#CJK UNIFIED IDEOGRAPH
+0x968B	0x5E55	#CJK UNIFIED IDEOGRAPH
+0x968C	0x819C	#CJK UNIFIED IDEOGRAPH
+0x968D	0x6795	#CJK UNIFIED IDEOGRAPH
+0x968E	0x9BAA	#CJK UNIFIED IDEOGRAPH
+0x968F	0x67FE	#CJK UNIFIED IDEOGRAPH
+0x9690	0x9C52	#CJK UNIFIED IDEOGRAPH
+0x9691	0x685D	#CJK UNIFIED IDEOGRAPH
+0x9692	0x4EA6	#CJK UNIFIED IDEOGRAPH
+0x9693	0x4FE3	#CJK UNIFIED IDEOGRAPH
+0x9694	0x53C8	#CJK UNIFIED IDEOGRAPH
+0x9695	0x62B9	#CJK UNIFIED IDEOGRAPH
+0x9696	0x672B	#CJK UNIFIED IDEOGRAPH
+0x9697	0x6CAB	#CJK UNIFIED IDEOGRAPH
+0x9698	0x8FC4	#CJK UNIFIED IDEOGRAPH
+0x9699	0x4FAD	#CJK UNIFIED IDEOGRAPH
+0x969A	0x7E6D	#CJK UNIFIED IDEOGRAPH
+0x969B	0x9EBF	#CJK UNIFIED IDEOGRAPH
+0x969C	0x4E07	#CJK UNIFIED IDEOGRAPH
+0x969D	0x6162	#CJK UNIFIED IDEOGRAPH
+0x969E	0x6E80	#CJK UNIFIED IDEOGRAPH
+0x969F	0x6F2B	#CJK UNIFIED IDEOGRAPH
+0x96A0	0x8513	#CJK UNIFIED IDEOGRAPH
+0x96A1	0x5473	#CJK UNIFIED IDEOGRAPH
+0x96A2	0x672A	#CJK UNIFIED IDEOGRAPH
+0x96A3	0x9B45	#CJK UNIFIED IDEOGRAPH
+0x96A4	0x5DF3	#CJK UNIFIED IDEOGRAPH
+0x96A5	0x7B95	#CJK UNIFIED IDEOGRAPH
+0x96A6	0x5CAC	#CJK UNIFIED IDEOGRAPH
+0x96A7	0x5BC6	#CJK UNIFIED IDEOGRAPH
+0x96A8	0x871C	#CJK UNIFIED IDEOGRAPH
+0x96A9	0x6E4A	#CJK UNIFIED IDEOGRAPH
+0x96AA	0x84D1	#CJK UNIFIED IDEOGRAPH
+0x96AB	0x7A14	#CJK UNIFIED IDEOGRAPH
+0x96AC	0x8108	#CJK UNIFIED IDEOGRAPH
+0x96AD	0x5999	#CJK UNIFIED IDEOGRAPH
+0x96AE	0x7C8D	#CJK UNIFIED IDEOGRAPH
+0x96AF	0x6C11	#CJK UNIFIED IDEOGRAPH
+0x96B0	0x7720	#CJK UNIFIED IDEOGRAPH
+0x96B1	0x52D9	#CJK UNIFIED IDEOGRAPH
+0x96B2	0x5922	#CJK UNIFIED IDEOGRAPH
+0x96B3	0x7121	#CJK UNIFIED IDEOGRAPH
+0x96B4	0x725F	#CJK UNIFIED IDEOGRAPH
+0x96B5	0x77DB	#CJK UNIFIED IDEOGRAPH
+0x96B6	0x9727	#CJK UNIFIED IDEOGRAPH
+0x96B7	0x9D61	#CJK UNIFIED IDEOGRAPH
+0x96B8	0x690B	#CJK UNIFIED IDEOGRAPH
+0x96B9	0x5A7F	#CJK UNIFIED IDEOGRAPH
+0x96BA	0x5A18	#CJK UNIFIED IDEOGRAPH
+0x96BB	0x51A5	#CJK UNIFIED IDEOGRAPH
+0x96BC	0x540D	#CJK UNIFIED IDEOGRAPH
+0x96BD	0x547D	#CJK UNIFIED IDEOGRAPH
+0x96BE	0x660E	#CJK UNIFIED IDEOGRAPH
+0x96BF	0x76DF	#CJK UNIFIED IDEOGRAPH
+0x96C0	0x8FF7	#CJK UNIFIED IDEOGRAPH
+0x96C1	0x9298	#CJK UNIFIED IDEOGRAPH
+0x96C2	0x9CF4	#CJK UNIFIED IDEOGRAPH
+0x96C3	0x59EA	#CJK UNIFIED IDEOGRAPH
+0x96C4	0x725D	#CJK UNIFIED IDEOGRAPH
+0x96C5	0x6EC5	#CJK UNIFIED IDEOGRAPH
+0x96C6	0x514D	#CJK UNIFIED IDEOGRAPH
+0x96C7	0x68C9	#CJK UNIFIED IDEOGRAPH
+0x96C8	0x7DBF	#CJK UNIFIED IDEOGRAPH
+0x96C9	0x7DEC	#CJK UNIFIED IDEOGRAPH
+0x96CA	0x9762	#CJK UNIFIED IDEOGRAPH
+0x96CB	0x9EBA	#CJK UNIFIED IDEOGRAPH
+0x96CC	0x6478	#CJK UNIFIED IDEOGRAPH
+0x96CD	0x6A21	#CJK UNIFIED IDEOGRAPH
+0x96CE	0x8302	#CJK UNIFIED IDEOGRAPH
+0x96CF	0x5984	#CJK UNIFIED IDEOGRAPH
+0x96D0	0x5B5F	#CJK UNIFIED IDEOGRAPH
+0x96D1	0x6BDB	#CJK UNIFIED IDEOGRAPH
+0x96D2	0x731B	#CJK UNIFIED IDEOGRAPH
+0x96D3	0x76F2	#CJK UNIFIED IDEOGRAPH
+0x96D4	0x7DB2	#CJK UNIFIED IDEOGRAPH
+0x96D5	0x8017	#CJK UNIFIED IDEOGRAPH
+0x96D6	0x8499	#CJK UNIFIED IDEOGRAPH
+0x96D7	0x5132	#CJK UNIFIED IDEOGRAPH
+0x96D8	0x6728	#CJK UNIFIED IDEOGRAPH
+0x96D9	0x9ED9	#CJK UNIFIED IDEOGRAPH
+0x96DA	0x76EE	#CJK UNIFIED IDEOGRAPH
+0x96DB	0x6762	#CJK UNIFIED IDEOGRAPH
+0x96DC	0x52FF	#CJK UNIFIED IDEOGRAPH
+0x96DD	0x9905	#CJK UNIFIED IDEOGRAPH
+0x96DE	0x5C24	#CJK UNIFIED IDEOGRAPH
+0x96DF	0x623B	#CJK UNIFIED IDEOGRAPH
+0x96E0	0x7C7E	#CJK UNIFIED IDEOGRAPH
+0x96E1	0x8CB0	#CJK UNIFIED IDEOGRAPH
+0x96E2	0x554F	#CJK UNIFIED IDEOGRAPH
+0x96E3	0x60B6	#CJK UNIFIED IDEOGRAPH
+0x96E4	0x7D0B	#CJK UNIFIED IDEOGRAPH
+0x96E5	0x9580	#CJK UNIFIED IDEOGRAPH
+0x96E6	0x5301	#CJK UNIFIED IDEOGRAPH
+0x96E7	0x4E5F	#CJK UNIFIED IDEOGRAPH
+0x96E8	0x51B6	#CJK UNIFIED IDEOGRAPH
+0x96E9	0x591C	#CJK UNIFIED IDEOGRAPH
+0x96EA	0x723A	#CJK UNIFIED IDEOGRAPH
+0x96EB	0x8036	#CJK UNIFIED IDEOGRAPH
+0x96EC	0x91CE	#CJK UNIFIED IDEOGRAPH
+0x96ED	0x5F25	#CJK UNIFIED IDEOGRAPH
+0x96EE	0x77E2	#CJK UNIFIED IDEOGRAPH
+0x96EF	0x5384	#CJK UNIFIED IDEOGRAPH
+0x96F0	0x5F79	#CJK UNIFIED IDEOGRAPH
+0x96F1	0x7D04	#CJK UNIFIED IDEOGRAPH
+0x96F2	0x85AC	#CJK UNIFIED IDEOGRAPH
+0x96F3	0x8A33	#CJK UNIFIED IDEOGRAPH
+0x96F4	0x8E8D	#CJK UNIFIED IDEOGRAPH
+0x96F5	0x9756	#CJK UNIFIED IDEOGRAPH
+0x96F6	0x67F3	#CJK UNIFIED IDEOGRAPH
+0x96F7	0x85AE	#CJK UNIFIED IDEOGRAPH
+0x96F8	0x9453	#CJK UNIFIED IDEOGRAPH
+0x96F9	0x6109	#CJK UNIFIED IDEOGRAPH
+0x96FA	0x6108	#CJK UNIFIED IDEOGRAPH
+0x96FB	0x6CB9	#CJK UNIFIED IDEOGRAPH
+0x96FC	0x7652	#CJK UNIFIED IDEOGRAPH
+0x9740	0x8AED	#CJK UNIFIED IDEOGRAPH
+0x9741	0x8F38	#CJK UNIFIED IDEOGRAPH
+0x9742	0x552F	#CJK UNIFIED IDEOGRAPH
+0x9743	0x4F51	#CJK UNIFIED IDEOGRAPH
+0x9744	0x512A	#CJK UNIFIED IDEOGRAPH
+0x9745	0x52C7	#CJK UNIFIED IDEOGRAPH
+0x9746	0x53CB	#CJK UNIFIED IDEOGRAPH
+0x9747	0x5BA5	#CJK UNIFIED IDEOGRAPH
+0x9748	0x5E7D	#CJK UNIFIED IDEOGRAPH
+0x9749	0x60A0	#CJK UNIFIED IDEOGRAPH
+0x974A	0x6182	#CJK UNIFIED IDEOGRAPH
+0x974B	0x63D6	#CJK UNIFIED IDEOGRAPH
+0x974C	0x6709	#CJK UNIFIED IDEOGRAPH
+0x974D	0x67DA	#CJK UNIFIED IDEOGRAPH
+0x974E	0x6E67	#CJK UNIFIED IDEOGRAPH
+0x974F	0x6D8C	#CJK UNIFIED IDEOGRAPH
+0x9750	0x7336	#CJK UNIFIED IDEOGRAPH
+0x9751	0x7337	#CJK UNIFIED IDEOGRAPH
+0x9752	0x7531	#CJK UNIFIED IDEOGRAPH
+0x9753	0x7950	#CJK UNIFIED IDEOGRAPH
+0x9754	0x88D5	#CJK UNIFIED IDEOGRAPH
+0x9755	0x8A98	#CJK UNIFIED IDEOGRAPH
+0x9756	0x904A	#CJK UNIFIED IDEOGRAPH
+0x9757	0x9091	#CJK UNIFIED IDEOGRAPH
+0x9758	0x90F5	#CJK UNIFIED IDEOGRAPH
+0x9759	0x96C4	#CJK UNIFIED IDEOGRAPH
+0x975A	0x878D	#CJK UNIFIED IDEOGRAPH
+0x975B	0x5915	#CJK UNIFIED IDEOGRAPH
+0x975C	0x4E88	#CJK UNIFIED IDEOGRAPH
+0x975D	0x4F59	#CJK UNIFIED IDEOGRAPH
+0x975E	0x4E0E	#CJK UNIFIED IDEOGRAPH
+0x975F	0x8A89	#CJK UNIFIED IDEOGRAPH
+0x9760	0x8F3F	#CJK UNIFIED IDEOGRAPH
+0x9761	0x9810	#CJK UNIFIED IDEOGRAPH
+0x9762	0x50AD	#CJK UNIFIED IDEOGRAPH
+0x9763	0x5E7C	#CJK UNIFIED IDEOGRAPH
+0x9764	0x5996	#CJK UNIFIED IDEOGRAPH
+0x9765	0x5BB9	#CJK UNIFIED IDEOGRAPH
+0x9766	0x5EB8	#CJK UNIFIED IDEOGRAPH
+0x9767	0x63DA	#CJK UNIFIED IDEOGRAPH
+0x9768	0x63FA	#CJK UNIFIED IDEOGRAPH
+0x9769	0x64C1	#CJK UNIFIED IDEOGRAPH
+0x976A	0x66DC	#CJK UNIFIED IDEOGRAPH
+0x976B	0x694A	#CJK UNIFIED IDEOGRAPH
+0x976C	0x69D8	#CJK UNIFIED IDEOGRAPH
+0x976D	0x6D0B	#CJK UNIFIED IDEOGRAPH
+0x976E	0x6EB6	#CJK UNIFIED IDEOGRAPH
+0x976F	0x7194	#CJK UNIFIED IDEOGRAPH
+0x9770	0x7528	#CJK UNIFIED IDEOGRAPH
+0x9771	0x7AAF	#CJK UNIFIED IDEOGRAPH
+0x9772	0x7F8A	#CJK UNIFIED IDEOGRAPH
+0x9773	0x8000	#CJK UNIFIED IDEOGRAPH
+0x9774	0x8449	#CJK UNIFIED IDEOGRAPH
+0x9775	0x84C9	#CJK UNIFIED IDEOGRAPH
+0x9776	0x8981	#CJK UNIFIED IDEOGRAPH
+0x9777	0x8B21	#CJK UNIFIED IDEOGRAPH
+0x9778	0x8E0A	#CJK UNIFIED IDEOGRAPH
+0x9779	0x9065	#CJK UNIFIED IDEOGRAPH
+0x977A	0x967D	#CJK UNIFIED IDEOGRAPH
+0x977B	0x990A	#CJK UNIFIED IDEOGRAPH
+0x977C	0x617E	#CJK UNIFIED IDEOGRAPH
+0x977D	0x6291	#CJK UNIFIED IDEOGRAPH
+0x977E	0x6B32	#CJK UNIFIED IDEOGRAPH
+0x9780	0x6C83	#CJK UNIFIED IDEOGRAPH
+0x9781	0x6D74	#CJK UNIFIED IDEOGRAPH
+0x9782	0x7FCC	#CJK UNIFIED IDEOGRAPH
+0x9783	0x7FFC	#CJK UNIFIED IDEOGRAPH
+0x9784	0x6DC0	#CJK UNIFIED IDEOGRAPH
+0x9785	0x7F85	#CJK UNIFIED IDEOGRAPH
+0x9786	0x87BA	#CJK UNIFIED IDEOGRAPH
+0x9787	0x88F8	#CJK UNIFIED IDEOGRAPH
+0x9788	0x6765	#CJK UNIFIED IDEOGRAPH
+0x9789	0x83B1	#CJK UNIFIED IDEOGRAPH
+0x978A	0x983C	#CJK UNIFIED IDEOGRAPH
+0x978B	0x96F7	#CJK UNIFIED IDEOGRAPH
+0x978C	0x6D1B	#CJK UNIFIED IDEOGRAPH
+0x978D	0x7D61	#CJK UNIFIED IDEOGRAPH
+0x978E	0x843D	#CJK UNIFIED IDEOGRAPH
+0x978F	0x916A	#CJK UNIFIED IDEOGRAPH
+0x9790	0x4E71	#CJK UNIFIED IDEOGRAPH
+0x9791	0x5375	#CJK UNIFIED IDEOGRAPH
+0x9792	0x5D50	#CJK UNIFIED IDEOGRAPH
+0x9793	0x6B04	#CJK UNIFIED IDEOGRAPH
+0x9794	0x6FEB	#CJK UNIFIED IDEOGRAPH
+0x9795	0x85CD	#CJK UNIFIED IDEOGRAPH
+0x9796	0x862D	#CJK UNIFIED IDEOGRAPH
+0x9797	0x89A7	#CJK UNIFIED IDEOGRAPH
+0x9798	0x5229	#CJK UNIFIED IDEOGRAPH
+0x9799	0x540F	#CJK UNIFIED IDEOGRAPH
+0x979A	0x5C65	#CJK UNIFIED IDEOGRAPH
+0x979B	0x674E	#CJK UNIFIED IDEOGRAPH
+0x979C	0x68A8	#CJK UNIFIED IDEOGRAPH
+0x979D	0x7406	#CJK UNIFIED IDEOGRAPH
+0x979E	0x7483	#CJK UNIFIED IDEOGRAPH
+0x979F	0x75E2	#CJK UNIFIED IDEOGRAPH
+0x97A0	0x88CF	#CJK UNIFIED IDEOGRAPH
+0x97A1	0x88E1	#CJK UNIFIED IDEOGRAPH
+0x97A2	0x91CC	#CJK UNIFIED IDEOGRAPH
+0x97A3	0x96E2	#CJK UNIFIED IDEOGRAPH
+0x97A4	0x9678	#CJK UNIFIED IDEOGRAPH
+0x97A5	0x5F8B	#CJK UNIFIED IDEOGRAPH
+0x97A6	0x7387	#CJK UNIFIED IDEOGRAPH
+0x97A7	0x7ACB	#CJK UNIFIED IDEOGRAPH
+0x97A8	0x844E	#CJK UNIFIED IDEOGRAPH
+0x97A9	0x63A0	#CJK UNIFIED IDEOGRAPH
+0x97AA	0x7565	#CJK UNIFIED IDEOGRAPH
+0x97AB	0x5289	#CJK UNIFIED IDEOGRAPH
+0x97AC	0x6D41	#CJK UNIFIED IDEOGRAPH
+0x97AD	0x6E9C	#CJK UNIFIED IDEOGRAPH
+0x97AE	0x7409	#CJK UNIFIED IDEOGRAPH
+0x97AF	0x7559	#CJK UNIFIED IDEOGRAPH
+0x97B0	0x786B	#CJK UNIFIED IDEOGRAPH
+0x97B1	0x7C92	#CJK UNIFIED IDEOGRAPH
+0x97B2	0x9686	#CJK UNIFIED IDEOGRAPH
+0x97B3	0x7ADC	#CJK UNIFIED IDEOGRAPH
+0x97B4	0x9F8D	#CJK UNIFIED IDEOGRAPH
+0x97B5	0x4FB6	#CJK UNIFIED IDEOGRAPH
+0x97B6	0x616E	#CJK UNIFIED IDEOGRAPH
+0x97B7	0x65C5	#CJK UNIFIED IDEOGRAPH
+0x97B8	0x865C	#CJK UNIFIED IDEOGRAPH
+0x97B9	0x4E86	#CJK UNIFIED IDEOGRAPH
+0x97BA	0x4EAE	#CJK UNIFIED IDEOGRAPH
+0x97BB	0x50DA	#CJK UNIFIED IDEOGRAPH
+0x97BC	0x4E21	#CJK UNIFIED IDEOGRAPH
+0x97BD	0x51CC	#CJK UNIFIED IDEOGRAPH
+0x97BE	0x5BEE	#CJK UNIFIED IDEOGRAPH
+0x97BF	0x6599	#CJK UNIFIED IDEOGRAPH
+0x97C0	0x6881	#CJK UNIFIED IDEOGRAPH
+0x97C1	0x6DBC	#CJK UNIFIED IDEOGRAPH
+0x97C2	0x731F	#CJK UNIFIED IDEOGRAPH
+0x97C3	0x7642	#CJK UNIFIED IDEOGRAPH
+0x97C4	0x77AD	#CJK UNIFIED IDEOGRAPH
+0x97C5	0x7A1C	#CJK UNIFIED IDEOGRAPH
+0x97C6	0x7CE7	#CJK UNIFIED IDEOGRAPH
+0x97C7	0x826F	#CJK UNIFIED IDEOGRAPH
+0x97C8	0x8AD2	#CJK UNIFIED IDEOGRAPH
+0x97C9	0x907C	#CJK UNIFIED IDEOGRAPH
+0x97CA	0x91CF	#CJK UNIFIED IDEOGRAPH
+0x97CB	0x9675	#CJK UNIFIED IDEOGRAPH
+0x97CC	0x9818	#CJK UNIFIED IDEOGRAPH
+0x97CD	0x529B	#CJK UNIFIED IDEOGRAPH
+0x97CE	0x7DD1	#CJK UNIFIED IDEOGRAPH
+0x97CF	0x502B	#CJK UNIFIED IDEOGRAPH
+0x97D0	0x5398	#CJK UNIFIED IDEOGRAPH
+0x97D1	0x6797	#CJK UNIFIED IDEOGRAPH
+0x97D2	0x6DCB	#CJK UNIFIED IDEOGRAPH
+0x97D3	0x71D0	#CJK UNIFIED IDEOGRAPH
+0x97D4	0x7433	#CJK UNIFIED IDEOGRAPH
+0x97D5	0x81E8	#CJK UNIFIED IDEOGRAPH
+0x97D6	0x8F2A	#CJK UNIFIED IDEOGRAPH
+0x97D7	0x96A3	#CJK UNIFIED IDEOGRAPH
+0x97D8	0x9C57	#CJK UNIFIED IDEOGRAPH
+0x97D9	0x9E9F	#CJK UNIFIED IDEOGRAPH
+0x97DA	0x7460	#CJK UNIFIED IDEOGRAPH
+0x97DB	0x5841	#CJK UNIFIED IDEOGRAPH
+0x97DC	0x6D99	#CJK UNIFIED IDEOGRAPH
+0x97DD	0x7D2F	#CJK UNIFIED IDEOGRAPH
+0x97DE	0x985E	#CJK UNIFIED IDEOGRAPH
+0x97DF	0x4EE4	#CJK UNIFIED IDEOGRAPH
+0x97E0	0x4F36	#CJK UNIFIED IDEOGRAPH
+0x97E1	0x4F8B	#CJK UNIFIED IDEOGRAPH
+0x97E2	0x51B7	#CJK UNIFIED IDEOGRAPH
+0x97E3	0x52B1	#CJK UNIFIED IDEOGRAPH
+0x97E4	0x5DBA	#CJK UNIFIED IDEOGRAPH
+0x97E5	0x601C	#CJK UNIFIED IDEOGRAPH
+0x97E6	0x73B2	#CJK UNIFIED IDEOGRAPH
+0x97E7	0x793C	#CJK UNIFIED IDEOGRAPH
+0x97E8	0x82D3	#CJK UNIFIED IDEOGRAPH
+0x97E9	0x9234	#CJK UNIFIED IDEOGRAPH
+0x97EA	0x96B7	#CJK UNIFIED IDEOGRAPH
+0x97EB	0x96F6	#CJK UNIFIED IDEOGRAPH
+0x97EC	0x970A	#CJK UNIFIED IDEOGRAPH
+0x97ED	0x9E97	#CJK UNIFIED IDEOGRAPH
+0x97EE	0x9F62	#CJK UNIFIED IDEOGRAPH
+0x97EF	0x66A6	#CJK UNIFIED IDEOGRAPH
+0x97F0	0x6B74	#CJK UNIFIED IDEOGRAPH
+0x97F1	0x5217	#CJK UNIFIED IDEOGRAPH
+0x97F2	0x52A3	#CJK UNIFIED IDEOGRAPH
+0x97F3	0x70C8	#CJK UNIFIED IDEOGRAPH
+0x97F4	0x88C2	#CJK UNIFIED IDEOGRAPH
+0x97F5	0x5EC9	#CJK UNIFIED IDEOGRAPH
+0x97F6	0x604B	#CJK UNIFIED IDEOGRAPH
+0x97F7	0x6190	#CJK UNIFIED IDEOGRAPH
+0x97F8	0x6F23	#CJK UNIFIED IDEOGRAPH
+0x97F9	0x7149	#CJK UNIFIED IDEOGRAPH
+0x97FA	0x7C3E	#CJK UNIFIED IDEOGRAPH
+0x97FB	0x7DF4	#CJK UNIFIED IDEOGRAPH
+0x97FC	0x806F	#CJK UNIFIED IDEOGRAPH
+0x9840	0x84EE	#CJK UNIFIED IDEOGRAPH
+0x9841	0x9023	#CJK UNIFIED IDEOGRAPH
+0x9842	0x932C	#CJK UNIFIED IDEOGRAPH
+0x9843	0x5442	#CJK UNIFIED IDEOGRAPH
+0x9844	0x9B6F	#CJK UNIFIED IDEOGRAPH
+0x9845	0x6AD3	#CJK UNIFIED IDEOGRAPH
+0x9846	0x7089	#CJK UNIFIED IDEOGRAPH
+0x9847	0x8CC2	#CJK UNIFIED IDEOGRAPH
+0x9848	0x8DEF	#CJK UNIFIED IDEOGRAPH
+0x9849	0x9732	#CJK UNIFIED IDEOGRAPH
+0x984A	0x52B4	#CJK UNIFIED IDEOGRAPH
+0x984B	0x5A41	#CJK UNIFIED IDEOGRAPH
+0x984C	0x5ECA	#CJK UNIFIED IDEOGRAPH
+0x984D	0x5F04	#CJK UNIFIED IDEOGRAPH
+0x984E	0x6717	#CJK UNIFIED IDEOGRAPH
+0x984F	0x697C	#CJK UNIFIED IDEOGRAPH
+0x9850	0x6994	#CJK UNIFIED IDEOGRAPH
+0x9851	0x6D6A	#CJK UNIFIED IDEOGRAPH
+0x9852	0x6F0F	#CJK UNIFIED IDEOGRAPH
+0x9853	0x7262	#CJK UNIFIED IDEOGRAPH
+0x9854	0x72FC	#CJK UNIFIED IDEOGRAPH
+0x9855	0x7BED	#CJK UNIFIED IDEOGRAPH
+0x9856	0x8001	#CJK UNIFIED IDEOGRAPH
+0x9857	0x807E	#CJK UNIFIED IDEOGRAPH
+0x9858	0x874B	#CJK UNIFIED IDEOGRAPH
+0x9859	0x90CE	#CJK UNIFIED IDEOGRAPH
+0x985A	0x516D	#CJK UNIFIED IDEOGRAPH
+0x985B	0x9E93	#CJK UNIFIED IDEOGRAPH
+0x985C	0x7984	#CJK UNIFIED IDEOGRAPH
+0x985D	0x808B	#CJK UNIFIED IDEOGRAPH
+0x985E	0x9332	#CJK UNIFIED IDEOGRAPH
+0x985F	0x8AD6	#CJK UNIFIED IDEOGRAPH
+0x9860	0x502D	#CJK UNIFIED IDEOGRAPH
+0x9861	0x548C	#CJK UNIFIED IDEOGRAPH
+0x9862	0x8A71	#CJK UNIFIED IDEOGRAPH
+0x9863	0x6B6A	#CJK UNIFIED IDEOGRAPH
+0x9864	0x8CC4	#CJK UNIFIED IDEOGRAPH
+0x9865	0x8107	#CJK UNIFIED IDEOGRAPH
+0x9866	0x60D1	#CJK UNIFIED IDEOGRAPH
+0x9867	0x67A0	#CJK UNIFIED IDEOGRAPH
+0x9868	0x9DF2	#CJK UNIFIED IDEOGRAPH
+0x9869	0x4E99	#CJK UNIFIED IDEOGRAPH
+0x986A	0x4E98	#CJK UNIFIED IDEOGRAPH
+0x986B	0x9C10	#CJK UNIFIED IDEOGRAPH
+0x986C	0x8A6B	#CJK UNIFIED IDEOGRAPH
+0x986D	0x85C1	#CJK UNIFIED IDEOGRAPH
+0x986E	0x8568	#CJK UNIFIED IDEOGRAPH
+0x986F	0x6900	#CJK UNIFIED IDEOGRAPH
+0x9870	0x6E7E	#CJK UNIFIED IDEOGRAPH
+0x9871	0x7897	#CJK UNIFIED IDEOGRAPH
+0x9872	0x8155	#CJK UNIFIED IDEOGRAPH
+0x989F	0x5F0C	#CJK UNIFIED IDEOGRAPH
+0x98A0	0x4E10	#CJK UNIFIED IDEOGRAPH
+0x98A1	0x4E15	#CJK UNIFIED IDEOGRAPH
+0x98A2	0x4E2A	#CJK UNIFIED IDEOGRAPH
+0x98A3	0x4E31	#CJK UNIFIED IDEOGRAPH
+0x98A4	0x4E36	#CJK UNIFIED IDEOGRAPH
+0x98A5	0x4E3C	#CJK UNIFIED IDEOGRAPH
+0x98A6	0x4E3F	#CJK UNIFIED IDEOGRAPH
+0x98A7	0x4E42	#CJK UNIFIED IDEOGRAPH
+0x98A8	0x4E56	#CJK UNIFIED IDEOGRAPH
+0x98A9	0x4E58	#CJK UNIFIED IDEOGRAPH
+0x98AA	0x4E82	#CJK UNIFIED IDEOGRAPH
+0x98AB	0x4E85	#CJK UNIFIED IDEOGRAPH
+0x98AC	0x8C6B	#CJK UNIFIED IDEOGRAPH
+0x98AD	0x4E8A	#CJK UNIFIED IDEOGRAPH
+0x98AE	0x8212	#CJK UNIFIED IDEOGRAPH
+0x98AF	0x5F0D	#CJK UNIFIED IDEOGRAPH
+0x98B0	0x4E8E	#CJK UNIFIED IDEOGRAPH
+0x98B1	0x4E9E	#CJK UNIFIED IDEOGRAPH
+0x98B2	0x4E9F	#CJK UNIFIED IDEOGRAPH
+0x98B3	0x4EA0	#CJK UNIFIED IDEOGRAPH
+0x98B4	0x4EA2	#CJK UNIFIED IDEOGRAPH
+0x98B5	0x4EB0	#CJK UNIFIED IDEOGRAPH
+0x98B6	0x4EB3	#CJK UNIFIED IDEOGRAPH
+0x98B7	0x4EB6	#CJK UNIFIED IDEOGRAPH
+0x98B8	0x4ECE	#CJK UNIFIED IDEOGRAPH
+0x98B9	0x4ECD	#CJK UNIFIED IDEOGRAPH
+0x98BA	0x4EC4	#CJK UNIFIED IDEOGRAPH
+0x98BB	0x4EC6	#CJK UNIFIED IDEOGRAPH
+0x98BC	0x4EC2	#CJK UNIFIED IDEOGRAPH
+0x98BD	0x4ED7	#CJK UNIFIED IDEOGRAPH
+0x98BE	0x4EDE	#CJK UNIFIED IDEOGRAPH
+0x98BF	0x4EED	#CJK UNIFIED IDEOGRAPH
+0x98C0	0x4EDF	#CJK UNIFIED IDEOGRAPH
+0x98C1	0x4EF7	#CJK UNIFIED IDEOGRAPH
+0x98C2	0x4F09	#CJK UNIFIED IDEOGRAPH
+0x98C3	0x4F5A	#CJK UNIFIED IDEOGRAPH
+0x98C4	0x4F30	#CJK UNIFIED IDEOGRAPH
+0x98C5	0x4F5B	#CJK UNIFIED IDEOGRAPH
+0x98C6	0x4F5D	#CJK UNIFIED IDEOGRAPH
+0x98C7	0x4F57	#CJK UNIFIED IDEOGRAPH
+0x98C8	0x4F47	#CJK UNIFIED IDEOGRAPH
+0x98C9	0x4F76	#CJK UNIFIED IDEOGRAPH
+0x98CA	0x4F88	#CJK UNIFIED IDEOGRAPH
+0x98CB	0x4F8F	#CJK UNIFIED IDEOGRAPH
+0x98CC	0x4F98	#CJK UNIFIED IDEOGRAPH
+0x98CD	0x4F7B	#CJK UNIFIED IDEOGRAPH
+0x98CE	0x4F69	#CJK UNIFIED IDEOGRAPH
+0x98CF	0x4F70	#CJK UNIFIED IDEOGRAPH
+0x98D0	0x4F91	#CJK UNIFIED IDEOGRAPH
+0x98D1	0x4F6F	#CJK UNIFIED IDEOGRAPH
+0x98D2	0x4F86	#CJK UNIFIED IDEOGRAPH
+0x98D3	0x4F96	#CJK UNIFIED IDEOGRAPH
+0x98D4	0x5118	#CJK UNIFIED IDEOGRAPH
+0x98D5	0x4FD4	#CJK UNIFIED IDEOGRAPH
+0x98D6	0x4FDF	#CJK UNIFIED IDEOGRAPH
+0x98D7	0x4FCE	#CJK UNIFIED IDEOGRAPH
+0x98D8	0x4FD8	#CJK UNIFIED IDEOGRAPH
+0x98D9	0x4FDB	#CJK UNIFIED IDEOGRAPH
+0x98DA	0x4FD1	#CJK UNIFIED IDEOGRAPH
+0x98DB	0x4FDA	#CJK UNIFIED IDEOGRAPH
+0x98DC	0x4FD0	#CJK UNIFIED IDEOGRAPH
+0x98DD	0x4FE4	#CJK UNIFIED IDEOGRAPH
+0x98DE	0x4FE5	#CJK UNIFIED IDEOGRAPH
+0x98DF	0x501A	#CJK UNIFIED IDEOGRAPH
+0x98E0	0x5028	#CJK UNIFIED IDEOGRAPH
+0x98E1	0x5014	#CJK UNIFIED IDEOGRAPH
+0x98E2	0x502A	#CJK UNIFIED IDEOGRAPH
+0x98E3	0x5025	#CJK UNIFIED IDEOGRAPH
+0x98E4	0x5005	#CJK UNIFIED IDEOGRAPH
+0x98E5	0x4F1C	#CJK UNIFIED IDEOGRAPH
+0x98E6	0x4FF6	#CJK UNIFIED IDEOGRAPH
+0x98E7	0x5021	#CJK UNIFIED IDEOGRAPH
+0x98E8	0x5029	#CJK UNIFIED IDEOGRAPH
+0x98E9	0x502C	#CJK UNIFIED IDEOGRAPH
+0x98EA	0x4FFE	#CJK UNIFIED IDEOGRAPH
+0x98EB	0x4FEF	#CJK UNIFIED IDEOGRAPH
+0x98EC	0x5011	#CJK UNIFIED IDEOGRAPH
+0x98ED	0x5006	#CJK UNIFIED IDEOGRAPH
+0x98EE	0x5043	#CJK UNIFIED IDEOGRAPH
+0x98EF	0x5047	#CJK UNIFIED IDEOGRAPH
+0x98F0	0x6703	#CJK UNIFIED IDEOGRAPH
+0x98F1	0x5055	#CJK UNIFIED IDEOGRAPH
+0x98F2	0x5050	#CJK UNIFIED IDEOGRAPH
+0x98F3	0x5048	#CJK UNIFIED IDEOGRAPH
+0x98F4	0x505A	#CJK UNIFIED IDEOGRAPH
+0x98F5	0x5056	#CJK UNIFIED IDEOGRAPH
+0x98F6	0x506C	#CJK UNIFIED IDEOGRAPH
+0x98F7	0x5078	#CJK UNIFIED IDEOGRAPH
+0x98F8	0x5080	#CJK UNIFIED IDEOGRAPH
+0x98F9	0x509A	#CJK UNIFIED IDEOGRAPH
+0x98FA	0x5085	#CJK UNIFIED IDEOGRAPH
+0x98FB	0x50B4	#CJK UNIFIED IDEOGRAPH
+0x98FC	0x50B2	#CJK UNIFIED IDEOGRAPH
+0x9940	0x50C9	#CJK UNIFIED IDEOGRAPH
+0x9941	0x50CA	#CJK UNIFIED IDEOGRAPH
+0x9942	0x50B3	#CJK UNIFIED IDEOGRAPH
+0x9943	0x50C2	#CJK UNIFIED IDEOGRAPH
+0x9944	0x50D6	#CJK UNIFIED IDEOGRAPH
+0x9945	0x50DE	#CJK UNIFIED IDEOGRAPH
+0x9946	0x50E5	#CJK UNIFIED IDEOGRAPH
+0x9947	0x50ED	#CJK UNIFIED IDEOGRAPH
+0x9948	0x50E3	#CJK UNIFIED IDEOGRAPH
+0x9949	0x50EE	#CJK UNIFIED IDEOGRAPH
+0x994A	0x50F9	#CJK UNIFIED IDEOGRAPH
+0x994B	0x50F5	#CJK UNIFIED IDEOGRAPH
+0x994C	0x5109	#CJK UNIFIED IDEOGRAPH
+0x994D	0x5101	#CJK UNIFIED IDEOGRAPH
+0x994E	0x5102	#CJK UNIFIED IDEOGRAPH
+0x994F	0x5116	#CJK UNIFIED IDEOGRAPH
+0x9950	0x5115	#CJK UNIFIED IDEOGRAPH
+0x9951	0x5114	#CJK UNIFIED IDEOGRAPH
+0x9952	0x511A	#CJK UNIFIED IDEOGRAPH
+0x9953	0x5121	#CJK UNIFIED IDEOGRAPH
+0x9954	0x513A	#CJK UNIFIED IDEOGRAPH
+0x9955	0x5137	#CJK UNIFIED IDEOGRAPH
+0x9956	0x513C	#CJK UNIFIED IDEOGRAPH
+0x9957	0x513B	#CJK UNIFIED IDEOGRAPH
+0x9958	0x513F	#CJK UNIFIED IDEOGRAPH
+0x9959	0x5140	#CJK UNIFIED IDEOGRAPH
+0x995A	0x5152	#CJK UNIFIED IDEOGRAPH
+0x995B	0x514C	#CJK UNIFIED IDEOGRAPH
+0x995C	0x5154	#CJK UNIFIED IDEOGRAPH
+0x995D	0x5162	#CJK UNIFIED IDEOGRAPH
+0x995E	0x7AF8	#CJK UNIFIED IDEOGRAPH
+0x995F	0x5169	#CJK UNIFIED IDEOGRAPH
+0x9960	0x516A	#CJK UNIFIED IDEOGRAPH
+0x9961	0x516E	#CJK UNIFIED IDEOGRAPH
+0x9962	0x5180	#CJK UNIFIED IDEOGRAPH
+0x9963	0x5182	#CJK UNIFIED IDEOGRAPH
+0x9964	0x56D8	#CJK UNIFIED IDEOGRAPH
+0x9965	0x518C	#CJK UNIFIED IDEOGRAPH
+0x9966	0x5189	#CJK UNIFIED IDEOGRAPH
+0x9967	0x518F	#CJK UNIFIED IDEOGRAPH
+0x9968	0x5191	#CJK UNIFIED IDEOGRAPH
+0x9969	0x5193	#CJK UNIFIED IDEOGRAPH
+0x996A	0x5195	#CJK UNIFIED IDEOGRAPH
+0x996B	0x5196	#CJK UNIFIED IDEOGRAPH
+0x996C	0x51A4	#CJK UNIFIED IDEOGRAPH
+0x996D	0x51A6	#CJK UNIFIED IDEOGRAPH
+0x996E	0x51A2	#CJK UNIFIED IDEOGRAPH
+0x996F	0x51A9	#CJK UNIFIED IDEOGRAPH
+0x9970	0x51AA	#CJK UNIFIED IDEOGRAPH
+0x9971	0x51AB	#CJK UNIFIED IDEOGRAPH
+0x9972	0x51B3	#CJK UNIFIED IDEOGRAPH
+0x9973	0x51B1	#CJK UNIFIED IDEOGRAPH
+0x9974	0x51B2	#CJK UNIFIED IDEOGRAPH
+0x9975	0x51B0	#CJK UNIFIED IDEOGRAPH
+0x9976	0x51B5	#CJK UNIFIED IDEOGRAPH
+0x9977	0x51BD	#CJK UNIFIED IDEOGRAPH
+0x9978	0x51C5	#CJK UNIFIED IDEOGRAPH
+0x9979	0x51C9	#CJK UNIFIED IDEOGRAPH
+0x997A	0x51DB	#CJK UNIFIED IDEOGRAPH
+0x997B	0x51E0	#CJK UNIFIED IDEOGRAPH
+0x997C	0x8655	#CJK UNIFIED IDEOGRAPH
+0x997D	0x51E9	#CJK UNIFIED IDEOGRAPH
+0x997E	0x51ED	#CJK UNIFIED IDEOGRAPH
+0x9980	0x51F0	#CJK UNIFIED IDEOGRAPH
+0x9981	0x51F5	#CJK UNIFIED IDEOGRAPH
+0x9982	0x51FE	#CJK UNIFIED IDEOGRAPH
+0x9983	0x5204	#CJK UNIFIED IDEOGRAPH
+0x9984	0x520B	#CJK UNIFIED IDEOGRAPH
+0x9985	0x5214	#CJK UNIFIED IDEOGRAPH
+0x9986	0x520E	#CJK UNIFIED IDEOGRAPH
+0x9987	0x5227	#CJK UNIFIED IDEOGRAPH
+0x9988	0x522A	#CJK UNIFIED IDEOGRAPH
+0x9989	0x522E	#CJK UNIFIED IDEOGRAPH
+0x998A	0x5233	#CJK UNIFIED IDEOGRAPH
+0x998B	0x5239	#CJK UNIFIED IDEOGRAPH
+0x998C	0x524F	#CJK UNIFIED IDEOGRAPH
+0x998D	0x5244	#CJK UNIFIED IDEOGRAPH
+0x998E	0x524B	#CJK UNIFIED IDEOGRAPH
+0x998F	0x524C	#CJK UNIFIED IDEOGRAPH
+0x9990	0x525E	#CJK UNIFIED IDEOGRAPH
+0x9991	0x5254	#CJK UNIFIED IDEOGRAPH
+0x9992	0x526A	#CJK UNIFIED IDEOGRAPH
+0x9993	0x5274	#CJK UNIFIED IDEOGRAPH
+0x9994	0x5269	#CJK UNIFIED IDEOGRAPH
+0x9995	0x5273	#CJK UNIFIED IDEOGRAPH
+0x9996	0x527F	#CJK UNIFIED IDEOGRAPH
+0x9997	0x527D	#CJK UNIFIED IDEOGRAPH
+0x9998	0x528D	#CJK UNIFIED IDEOGRAPH
+0x9999	0x5294	#CJK UNIFIED IDEOGRAPH
+0x999A	0x5292	#CJK UNIFIED IDEOGRAPH
+0x999B	0x5271	#CJK UNIFIED IDEOGRAPH
+0x999C	0x5288	#CJK UNIFIED IDEOGRAPH
+0x999D	0x5291	#CJK UNIFIED IDEOGRAPH
+0x999E	0x8FA8	#CJK UNIFIED IDEOGRAPH
+0x999F	0x8FA7	#CJK UNIFIED IDEOGRAPH
+0x99A0	0x52AC	#CJK UNIFIED IDEOGRAPH
+0x99A1	0x52AD	#CJK UNIFIED IDEOGRAPH
+0x99A2	0x52BC	#CJK UNIFIED IDEOGRAPH
+0x99A3	0x52B5	#CJK UNIFIED IDEOGRAPH
+0x99A4	0x52C1	#CJK UNIFIED IDEOGRAPH
+0x99A5	0x52CD	#CJK UNIFIED IDEOGRAPH
+0x99A6	0x52D7	#CJK UNIFIED IDEOGRAPH
+0x99A7	0x52DE	#CJK UNIFIED IDEOGRAPH
+0x99A8	0x52E3	#CJK UNIFIED IDEOGRAPH
+0x99A9	0x52E6	#CJK UNIFIED IDEOGRAPH
+0x99AA	0x98ED	#CJK UNIFIED IDEOGRAPH
+0x99AB	0x52E0	#CJK UNIFIED IDEOGRAPH
+0x99AC	0x52F3	#CJK UNIFIED IDEOGRAPH
+0x99AD	0x52F5	#CJK UNIFIED IDEOGRAPH
+0x99AE	0x52F8	#CJK UNIFIED IDEOGRAPH
+0x99AF	0x52F9	#CJK UNIFIED IDEOGRAPH
+0x99B0	0x5306	#CJK UNIFIED IDEOGRAPH
+0x99B1	0x5308	#CJK UNIFIED IDEOGRAPH
+0x99B2	0x7538	#CJK UNIFIED IDEOGRAPH
+0x99B3	0x530D	#CJK UNIFIED IDEOGRAPH
+0x99B4	0x5310	#CJK UNIFIED IDEOGRAPH
+0x99B5	0x530F	#CJK UNIFIED IDEOGRAPH
+0x99B6	0x5315	#CJK UNIFIED IDEOGRAPH
+0x99B7	0x531A	#CJK UNIFIED IDEOGRAPH
+0x99B8	0x5323	#CJK UNIFIED IDEOGRAPH
+0x99B9	0x532F	#CJK UNIFIED IDEOGRAPH
+0x99BA	0x5331	#CJK UNIFIED IDEOGRAPH
+0x99BB	0x5333	#CJK UNIFIED IDEOGRAPH
+0x99BC	0x5338	#CJK UNIFIED IDEOGRAPH
+0x99BD	0x5340	#CJK UNIFIED IDEOGRAPH
+0x99BE	0x5346	#CJK UNIFIED IDEOGRAPH
+0x99BF	0x5345	#CJK UNIFIED IDEOGRAPH
+0x99C0	0x4E17	#CJK UNIFIED IDEOGRAPH
+0x99C1	0x5349	#CJK UNIFIED IDEOGRAPH
+0x99C2	0x534D	#CJK UNIFIED IDEOGRAPH
+0x99C3	0x51D6	#CJK UNIFIED IDEOGRAPH
+0x99C4	0x535E	#CJK UNIFIED IDEOGRAPH
+0x99C5	0x5369	#CJK UNIFIED IDEOGRAPH
+0x99C6	0x536E	#CJK UNIFIED IDEOGRAPH
+0x99C7	0x5918	#CJK UNIFIED IDEOGRAPH
+0x99C8	0x537B	#CJK UNIFIED IDEOGRAPH
+0x99C9	0x5377	#CJK UNIFIED IDEOGRAPH
+0x99CA	0x5382	#CJK UNIFIED IDEOGRAPH
+0x99CB	0x5396	#CJK UNIFIED IDEOGRAPH
+0x99CC	0x53A0	#CJK UNIFIED IDEOGRAPH
+0x99CD	0x53A6	#CJK UNIFIED IDEOGRAPH
+0x99CE	0x53A5	#CJK UNIFIED IDEOGRAPH
+0x99CF	0x53AE	#CJK UNIFIED IDEOGRAPH
+0x99D0	0x53B0	#CJK UNIFIED IDEOGRAPH
+0x99D1	0x53B6	#CJK UNIFIED IDEOGRAPH
+0x99D2	0x53C3	#CJK UNIFIED IDEOGRAPH
+0x99D3	0x7C12	#CJK UNIFIED IDEOGRAPH
+0x99D4	0x96D9	#CJK UNIFIED IDEOGRAPH
+0x99D5	0x53DF	#CJK UNIFIED IDEOGRAPH
+0x99D6	0x66FC	#CJK UNIFIED IDEOGRAPH
+0x99D7	0x71EE	#CJK UNIFIED IDEOGRAPH
+0x99D8	0x53EE	#CJK UNIFIED IDEOGRAPH
+0x99D9	0x53E8	#CJK UNIFIED IDEOGRAPH
+0x99DA	0x53ED	#CJK UNIFIED IDEOGRAPH
+0x99DB	0x53FA	#CJK UNIFIED IDEOGRAPH
+0x99DC	0x5401	#CJK UNIFIED IDEOGRAPH
+0x99DD	0x543D	#CJK UNIFIED IDEOGRAPH
+0x99DE	0x5440	#CJK UNIFIED IDEOGRAPH
+0x99DF	0x542C	#CJK UNIFIED IDEOGRAPH
+0x99E0	0x542D	#CJK UNIFIED IDEOGRAPH
+0x99E1	0x543C	#CJK UNIFIED IDEOGRAPH
+0x99E2	0x542E	#CJK UNIFIED IDEOGRAPH
+0x99E3	0x5436	#CJK UNIFIED IDEOGRAPH
+0x99E4	0x5429	#CJK UNIFIED IDEOGRAPH
+0x99E5	0x541D	#CJK UNIFIED IDEOGRAPH
+0x99E6	0x544E	#CJK UNIFIED IDEOGRAPH
+0x99E7	0x548F	#CJK UNIFIED IDEOGRAPH
+0x99E8	0x5475	#CJK UNIFIED IDEOGRAPH
+0x99E9	0x548E	#CJK UNIFIED IDEOGRAPH
+0x99EA	0x545F	#CJK UNIFIED IDEOGRAPH
+0x99EB	0x5471	#CJK UNIFIED IDEOGRAPH
+0x99EC	0x5477	#CJK UNIFIED IDEOGRAPH
+0x99ED	0x5470	#CJK UNIFIED IDEOGRAPH
+0x99EE	0x5492	#CJK UNIFIED IDEOGRAPH
+0x99EF	0x547B	#CJK UNIFIED IDEOGRAPH
+0x99F0	0x5480	#CJK UNIFIED IDEOGRAPH
+0x99F1	0x5476	#CJK UNIFIED IDEOGRAPH
+0x99F2	0x5484	#CJK UNIFIED IDEOGRAPH
+0x99F3	0x5490	#CJK UNIFIED IDEOGRAPH
+0x99F4	0x5486	#CJK UNIFIED IDEOGRAPH
+0x99F5	0x54C7	#CJK UNIFIED IDEOGRAPH
+0x99F6	0x54A2	#CJK UNIFIED IDEOGRAPH
+0x99F7	0x54B8	#CJK UNIFIED IDEOGRAPH
+0x99F8	0x54A5	#CJK UNIFIED IDEOGRAPH
+0x99F9	0x54AC	#CJK UNIFIED IDEOGRAPH
+0x99FA	0x54C4	#CJK UNIFIED IDEOGRAPH
+0x99FB	0x54C8	#CJK UNIFIED IDEOGRAPH
+0x99FC	0x54A8	#CJK UNIFIED IDEOGRAPH
+0x9A40	0x54AB	#CJK UNIFIED IDEOGRAPH
+0x9A41	0x54C2	#CJK UNIFIED IDEOGRAPH
+0x9A42	0x54A4	#CJK UNIFIED IDEOGRAPH
+0x9A43	0x54BE	#CJK UNIFIED IDEOGRAPH
+0x9A44	0x54BC	#CJK UNIFIED IDEOGRAPH
+0x9A45	0x54D8	#CJK UNIFIED IDEOGRAPH
+0x9A46	0x54E5	#CJK UNIFIED IDEOGRAPH
+0x9A47	0x54E6	#CJK UNIFIED IDEOGRAPH
+0x9A48	0x550F	#CJK UNIFIED IDEOGRAPH
+0x9A49	0x5514	#CJK UNIFIED IDEOGRAPH
+0x9A4A	0x54FD	#CJK UNIFIED IDEOGRAPH
+0x9A4B	0x54EE	#CJK UNIFIED IDEOGRAPH
+0x9A4C	0x54ED	#CJK UNIFIED IDEOGRAPH
+0x9A4D	0x54FA	#CJK UNIFIED IDEOGRAPH
+0x9A4E	0x54E2	#CJK UNIFIED IDEOGRAPH
+0x9A4F	0x5539	#CJK UNIFIED IDEOGRAPH
+0x9A50	0x5540	#CJK UNIFIED IDEOGRAPH
+0x9A51	0x5563	#CJK UNIFIED IDEOGRAPH
+0x9A52	0x554C	#CJK UNIFIED IDEOGRAPH
+0x9A53	0x552E	#CJK UNIFIED IDEOGRAPH
+0x9A54	0x555C	#CJK UNIFIED IDEOGRAPH
+0x9A55	0x5545	#CJK UNIFIED IDEOGRAPH
+0x9A56	0x5556	#CJK UNIFIED IDEOGRAPH
+0x9A57	0x5557	#CJK UNIFIED IDEOGRAPH
+0x9A58	0x5538	#CJK UNIFIED IDEOGRAPH
+0x9A59	0x5533	#CJK UNIFIED IDEOGRAPH
+0x9A5A	0x555D	#CJK UNIFIED IDEOGRAPH
+0x9A5B	0x5599	#CJK UNIFIED IDEOGRAPH
+0x9A5C	0x5580	#CJK UNIFIED IDEOGRAPH
+0x9A5D	0x54AF	#CJK UNIFIED IDEOGRAPH
+0x9A5E	0x558A	#CJK UNIFIED IDEOGRAPH
+0x9A5F	0x559F	#CJK UNIFIED IDEOGRAPH
+0x9A60	0x557B	#CJK UNIFIED IDEOGRAPH
+0x9A61	0x557E	#CJK UNIFIED IDEOGRAPH
+0x9A62	0x5598	#CJK UNIFIED IDEOGRAPH
+0x9A63	0x559E	#CJK UNIFIED IDEOGRAPH
+0x9A64	0x55AE	#CJK UNIFIED IDEOGRAPH
+0x9A65	0x557C	#CJK UNIFIED IDEOGRAPH
+0x9A66	0x5583	#CJK UNIFIED IDEOGRAPH
+0x9A67	0x55A9	#CJK UNIFIED IDEOGRAPH
+0x9A68	0x5587	#CJK UNIFIED IDEOGRAPH
+0x9A69	0x55A8	#CJK UNIFIED IDEOGRAPH
+0x9A6A	0x55DA	#CJK UNIFIED IDEOGRAPH
+0x9A6B	0x55C5	#CJK UNIFIED IDEOGRAPH
+0x9A6C	0x55DF	#CJK UNIFIED IDEOGRAPH
+0x9A6D	0x55C4	#CJK UNIFIED IDEOGRAPH
+0x9A6E	0x55DC	#CJK UNIFIED IDEOGRAPH
+0x9A6F	0x55E4	#CJK UNIFIED IDEOGRAPH
+0x9A70	0x55D4	#CJK UNIFIED IDEOGRAPH
+0x9A71	0x5614	#CJK UNIFIED IDEOGRAPH
+0x9A72	0x55F7	#CJK UNIFIED IDEOGRAPH
+0x9A73	0x5616	#CJK UNIFIED IDEOGRAPH
+0x9A74	0x55FE	#CJK UNIFIED IDEOGRAPH
+0x9A75	0x55FD	#CJK UNIFIED IDEOGRAPH
+0x9A76	0x561B	#CJK UNIFIED IDEOGRAPH
+0x9A77	0x55F9	#CJK UNIFIED IDEOGRAPH
+0x9A78	0x564E	#CJK UNIFIED IDEOGRAPH
+0x9A79	0x5650	#CJK UNIFIED IDEOGRAPH
+0x9A7A	0x71DF	#CJK UNIFIED IDEOGRAPH
+0x9A7B	0x5634	#CJK UNIFIED IDEOGRAPH
+0x9A7C	0x5636	#CJK UNIFIED IDEOGRAPH
+0x9A7D	0x5632	#CJK UNIFIED IDEOGRAPH
+0x9A7E	0x5638	#CJK UNIFIED IDEOGRAPH
+0x9A80	0x566B	#CJK UNIFIED IDEOGRAPH
+0x9A81	0x5664	#CJK UNIFIED IDEOGRAPH
+0x9A82	0x562F	#CJK UNIFIED IDEOGRAPH
+0x9A83	0x566C	#CJK UNIFIED IDEOGRAPH
+0x9A84	0x566A	#CJK UNIFIED IDEOGRAPH
+0x9A85	0x5686	#CJK UNIFIED IDEOGRAPH
+0x9A86	0x5680	#CJK UNIFIED IDEOGRAPH
+0x9A87	0x568A	#CJK UNIFIED IDEOGRAPH
+0x9A88	0x56A0	#CJK UNIFIED IDEOGRAPH
+0x9A89	0x5694	#CJK UNIFIED IDEOGRAPH
+0x9A8A	0x568F	#CJK UNIFIED IDEOGRAPH
+0x9A8B	0x56A5	#CJK UNIFIED IDEOGRAPH
+0x9A8C	0x56AE	#CJK UNIFIED IDEOGRAPH
+0x9A8D	0x56B6	#CJK UNIFIED IDEOGRAPH
+0x9A8E	0x56B4	#CJK UNIFIED IDEOGRAPH
+0x9A8F	0x56C2	#CJK UNIFIED IDEOGRAPH
+0x9A90	0x56BC	#CJK UNIFIED IDEOGRAPH
+0x9A91	0x56C1	#CJK UNIFIED IDEOGRAPH
+0x9A92	0x56C3	#CJK UNIFIED IDEOGRAPH
+0x9A93	0x56C0	#CJK UNIFIED IDEOGRAPH
+0x9A94	0x56C8	#CJK UNIFIED IDEOGRAPH
+0x9A95	0x56CE	#CJK UNIFIED IDEOGRAPH
+0x9A96	0x56D1	#CJK UNIFIED IDEOGRAPH
+0x9A97	0x56D3	#CJK UNIFIED IDEOGRAPH
+0x9A98	0x56D7	#CJK UNIFIED IDEOGRAPH
+0x9A99	0x56EE	#CJK UNIFIED IDEOGRAPH
+0x9A9A	0x56F9	#CJK UNIFIED IDEOGRAPH
+0x9A9B	0x5700	#CJK UNIFIED IDEOGRAPH
+0x9A9C	0x56FF	#CJK UNIFIED IDEOGRAPH
+0x9A9D	0x5704	#CJK UNIFIED IDEOGRAPH
+0x9A9E	0x5709	#CJK UNIFIED IDEOGRAPH
+0x9A9F	0x5708	#CJK UNIFIED IDEOGRAPH
+0x9AA0	0x570B	#CJK UNIFIED IDEOGRAPH
+0x9AA1	0x570D	#CJK UNIFIED IDEOGRAPH
+0x9AA2	0x5713	#CJK UNIFIED IDEOGRAPH
+0x9AA3	0x5718	#CJK UNIFIED IDEOGRAPH
+0x9AA4	0x5716	#CJK UNIFIED IDEOGRAPH
+0x9AA5	0x55C7	#CJK UNIFIED IDEOGRAPH
+0x9AA6	0x571C	#CJK UNIFIED IDEOGRAPH
+0x9AA7	0x5726	#CJK UNIFIED IDEOGRAPH
+0x9AA8	0x5737	#CJK UNIFIED IDEOGRAPH
+0x9AA9	0x5738	#CJK UNIFIED IDEOGRAPH
+0x9AAA	0x574E	#CJK UNIFIED IDEOGRAPH
+0x9AAB	0x573B	#CJK UNIFIED IDEOGRAPH
+0x9AAC	0x5740	#CJK UNIFIED IDEOGRAPH
+0x9AAD	0x574F	#CJK UNIFIED IDEOGRAPH
+0x9AAE	0x5769	#CJK UNIFIED IDEOGRAPH
+0x9AAF	0x57C0	#CJK UNIFIED IDEOGRAPH
+0x9AB0	0x5788	#CJK UNIFIED IDEOGRAPH
+0x9AB1	0x5761	#CJK UNIFIED IDEOGRAPH
+0x9AB2	0x577F	#CJK UNIFIED IDEOGRAPH
+0x9AB3	0x5789	#CJK UNIFIED IDEOGRAPH
+0x9AB4	0x5793	#CJK UNIFIED IDEOGRAPH
+0x9AB5	0x57A0	#CJK UNIFIED IDEOGRAPH
+0x9AB6	0x57B3	#CJK UNIFIED IDEOGRAPH
+0x9AB7	0x57A4	#CJK UNIFIED IDEOGRAPH
+0x9AB8	0x57AA	#CJK UNIFIED IDEOGRAPH
+0x9AB9	0x57B0	#CJK UNIFIED IDEOGRAPH
+0x9ABA	0x57C3	#CJK UNIFIED IDEOGRAPH
+0x9ABB	0x57C6	#CJK UNIFIED IDEOGRAPH
+0x9ABC	0x57D4	#CJK UNIFIED IDEOGRAPH
+0x9ABD	0x57D2	#CJK UNIFIED IDEOGRAPH
+0x9ABE	0x57D3	#CJK UNIFIED IDEOGRAPH
+0x9ABF	0x580A	#CJK UNIFIED IDEOGRAPH
+0x9AC0	0x57D6	#CJK UNIFIED IDEOGRAPH
+0x9AC1	0x57E3	#CJK UNIFIED IDEOGRAPH
+0x9AC2	0x580B	#CJK UNIFIED IDEOGRAPH
+0x9AC3	0x5819	#CJK UNIFIED IDEOGRAPH
+0x9AC4	0x581D	#CJK UNIFIED IDEOGRAPH
+0x9AC5	0x5872	#CJK UNIFIED IDEOGRAPH
+0x9AC6	0x5821	#CJK UNIFIED IDEOGRAPH
+0x9AC7	0x5862	#CJK UNIFIED IDEOGRAPH
+0x9AC8	0x584B	#CJK UNIFIED IDEOGRAPH
+0x9AC9	0x5870	#CJK UNIFIED IDEOGRAPH
+0x9ACA	0x6BC0	#CJK UNIFIED IDEOGRAPH
+0x9ACB	0x5852	#CJK UNIFIED IDEOGRAPH
+0x9ACC	0x583D	#CJK UNIFIED IDEOGRAPH
+0x9ACD	0x5879	#CJK UNIFIED IDEOGRAPH
+0x9ACE	0x5885	#CJK UNIFIED IDEOGRAPH
+0x9ACF	0x58B9	#CJK UNIFIED IDEOGRAPH
+0x9AD0	0x589F	#CJK UNIFIED IDEOGRAPH
+0x9AD1	0x58AB	#CJK UNIFIED IDEOGRAPH
+0x9AD2	0x58BA	#CJK UNIFIED IDEOGRAPH
+0x9AD3	0x58DE	#CJK UNIFIED IDEOGRAPH
+0x9AD4	0x58BB	#CJK UNIFIED IDEOGRAPH
+0x9AD5	0x58B8	#CJK UNIFIED IDEOGRAPH
+0x9AD6	0x58AE	#CJK UNIFIED IDEOGRAPH
+0x9AD7	0x58C5	#CJK UNIFIED IDEOGRAPH
+0x9AD8	0x58D3	#CJK UNIFIED IDEOGRAPH
+0x9AD9	0x58D1	#CJK UNIFIED IDEOGRAPH
+0x9ADA	0x58D7	#CJK UNIFIED IDEOGRAPH
+0x9ADB	0x58D9	#CJK UNIFIED IDEOGRAPH
+0x9ADC	0x58D8	#CJK UNIFIED IDEOGRAPH
+0x9ADD	0x58E5	#CJK UNIFIED IDEOGRAPH
+0x9ADE	0x58DC	#CJK UNIFIED IDEOGRAPH
+0x9ADF	0x58E4	#CJK UNIFIED IDEOGRAPH
+0x9AE0	0x58DF	#CJK UNIFIED IDEOGRAPH
+0x9AE1	0x58EF	#CJK UNIFIED IDEOGRAPH
+0x9AE2	0x58FA	#CJK UNIFIED IDEOGRAPH
+0x9AE3	0x58F9	#CJK UNIFIED IDEOGRAPH
+0x9AE4	0x58FB	#CJK UNIFIED IDEOGRAPH
+0x9AE5	0x58FC	#CJK UNIFIED IDEOGRAPH
+0x9AE6	0x58FD	#CJK UNIFIED IDEOGRAPH
+0x9AE7	0x5902	#CJK UNIFIED IDEOGRAPH
+0x9AE8	0x590A	#CJK UNIFIED IDEOGRAPH
+0x9AE9	0x5910	#CJK UNIFIED IDEOGRAPH
+0x9AEA	0x591B	#CJK UNIFIED IDEOGRAPH
+0x9AEB	0x68A6	#CJK UNIFIED IDEOGRAPH
+0x9AEC	0x5925	#CJK UNIFIED IDEOGRAPH
+0x9AED	0x592C	#CJK UNIFIED IDEOGRAPH
+0x9AEE	0x592D	#CJK UNIFIED IDEOGRAPH
+0x9AEF	0x5932	#CJK UNIFIED IDEOGRAPH
+0x9AF0	0x5938	#CJK UNIFIED IDEOGRAPH
+0x9AF1	0x593E	#CJK UNIFIED IDEOGRAPH
+0x9AF2	0x7AD2	#CJK UNIFIED IDEOGRAPH
+0x9AF3	0x5955	#CJK UNIFIED IDEOGRAPH
+0x9AF4	0x5950	#CJK UNIFIED IDEOGRAPH
+0x9AF5	0x594E	#CJK UNIFIED IDEOGRAPH
+0x9AF6	0x595A	#CJK UNIFIED IDEOGRAPH
+0x9AF7	0x5958	#CJK UNIFIED IDEOGRAPH
+0x9AF8	0x5962	#CJK UNIFIED IDEOGRAPH
+0x9AF9	0x5960	#CJK UNIFIED IDEOGRAPH
+0x9AFA	0x5967	#CJK UNIFIED IDEOGRAPH
+0x9AFB	0x596C	#CJK UNIFIED IDEOGRAPH
+0x9AFC	0x5969	#CJK UNIFIED IDEOGRAPH
+0x9B40	0x5978	#CJK UNIFIED IDEOGRAPH
+0x9B41	0x5981	#CJK UNIFIED IDEOGRAPH
+0x9B42	0x599D	#CJK UNIFIED IDEOGRAPH
+0x9B43	0x4F5E	#CJK UNIFIED IDEOGRAPH
+0x9B44	0x4FAB	#CJK UNIFIED IDEOGRAPH
+0x9B45	0x59A3	#CJK UNIFIED IDEOGRAPH
+0x9B46	0x59B2	#CJK UNIFIED IDEOGRAPH
+0x9B47	0x59C6	#CJK UNIFIED IDEOGRAPH
+0x9B48	0x59E8	#CJK UNIFIED IDEOGRAPH
+0x9B49	0x59DC	#CJK UNIFIED IDEOGRAPH
+0x9B4A	0x598D	#CJK UNIFIED IDEOGRAPH
+0x9B4B	0x59D9	#CJK UNIFIED IDEOGRAPH
+0x9B4C	0x59DA	#CJK UNIFIED IDEOGRAPH
+0x9B4D	0x5A25	#CJK UNIFIED IDEOGRAPH
+0x9B4E	0x5A1F	#CJK UNIFIED IDEOGRAPH
+0x9B4F	0x5A11	#CJK UNIFIED IDEOGRAPH
+0x9B50	0x5A1C	#CJK UNIFIED IDEOGRAPH
+0x9B51	0x5A09	#CJK UNIFIED IDEOGRAPH
+0x9B52	0x5A1A	#CJK UNIFIED IDEOGRAPH
+0x9B53	0x5A40	#CJK UNIFIED IDEOGRAPH
+0x9B54	0x5A6C	#CJK UNIFIED IDEOGRAPH
+0x9B55	0x5A49	#CJK UNIFIED IDEOGRAPH
+0x9B56	0x5A35	#CJK UNIFIED IDEOGRAPH
+0x9B57	0x5A36	#CJK UNIFIED IDEOGRAPH
+0x9B58	0x5A62	#CJK UNIFIED IDEOGRAPH
+0x9B59	0x5A6A	#CJK UNIFIED IDEOGRAPH
+0x9B5A	0x5A9A	#CJK UNIFIED IDEOGRAPH
+0x9B5B	0x5ABC	#CJK UNIFIED IDEOGRAPH
+0x9B5C	0x5ABE	#CJK UNIFIED IDEOGRAPH
+0x9B5D	0x5ACB	#CJK UNIFIED IDEOGRAPH
+0x9B5E	0x5AC2	#CJK UNIFIED IDEOGRAPH
+0x9B5F	0x5ABD	#CJK UNIFIED IDEOGRAPH
+0x9B60	0x5AE3	#CJK UNIFIED IDEOGRAPH
+0x9B61	0x5AD7	#CJK UNIFIED IDEOGRAPH
+0x9B62	0x5AE6	#CJK UNIFIED IDEOGRAPH
+0x9B63	0x5AE9	#CJK UNIFIED IDEOGRAPH
+0x9B64	0x5AD6	#CJK UNIFIED IDEOGRAPH
+0x9B65	0x5AFA	#CJK UNIFIED IDEOGRAPH
+0x9B66	0x5AFB	#CJK UNIFIED IDEOGRAPH
+0x9B67	0x5B0C	#CJK UNIFIED IDEOGRAPH
+0x9B68	0x5B0B	#CJK UNIFIED IDEOGRAPH
+0x9B69	0x5B16	#CJK UNIFIED IDEOGRAPH
+0x9B6A	0x5B32	#CJK UNIFIED IDEOGRAPH
+0x9B6B	0x5AD0	#CJK UNIFIED IDEOGRAPH
+0x9B6C	0x5B2A	#CJK UNIFIED IDEOGRAPH
+0x9B6D	0x5B36	#CJK UNIFIED IDEOGRAPH
+0x9B6E	0x5B3E	#CJK UNIFIED IDEOGRAPH
+0x9B6F	0x5B43	#CJK UNIFIED IDEOGRAPH
+0x9B70	0x5B45	#CJK UNIFIED IDEOGRAPH
+0x9B71	0x5B40	#CJK UNIFIED IDEOGRAPH
+0x9B72	0x5B51	#CJK UNIFIED IDEOGRAPH
+0x9B73	0x5B55	#CJK UNIFIED IDEOGRAPH
+0x9B74	0x5B5A	#CJK UNIFIED IDEOGRAPH
+0x9B75	0x5B5B	#CJK UNIFIED IDEOGRAPH
+0x9B76	0x5B65	#CJK UNIFIED IDEOGRAPH
+0x9B77	0x5B69	#CJK UNIFIED IDEOGRAPH
+0x9B78	0x5B70	#CJK UNIFIED IDEOGRAPH
+0x9B79	0x5B73	#CJK UNIFIED IDEOGRAPH
+0x9B7A	0x5B75	#CJK UNIFIED IDEOGRAPH
+0x9B7B	0x5B78	#CJK UNIFIED IDEOGRAPH
+0x9B7C	0x6588	#CJK UNIFIED IDEOGRAPH
+0x9B7D	0x5B7A	#CJK UNIFIED IDEOGRAPH
+0x9B7E	0x5B80	#CJK UNIFIED IDEOGRAPH
+0x9B80	0x5B83	#CJK UNIFIED IDEOGRAPH
+0x9B81	0x5BA6	#CJK UNIFIED IDEOGRAPH
+0x9B82	0x5BB8	#CJK UNIFIED IDEOGRAPH
+0x9B83	0x5BC3	#CJK UNIFIED IDEOGRAPH
+0x9B84	0x5BC7	#CJK UNIFIED IDEOGRAPH
+0x9B85	0x5BC9	#CJK UNIFIED IDEOGRAPH
+0x9B86	0x5BD4	#CJK UNIFIED IDEOGRAPH
+0x9B87	0x5BD0	#CJK UNIFIED IDEOGRAPH
+0x9B88	0x5BE4	#CJK UNIFIED IDEOGRAPH
+0x9B89	0x5BE6	#CJK UNIFIED IDEOGRAPH
+0x9B8A	0x5BE2	#CJK UNIFIED IDEOGRAPH
+0x9B8B	0x5BDE	#CJK UNIFIED IDEOGRAPH
+0x9B8C	0x5BE5	#CJK UNIFIED IDEOGRAPH
+0x9B8D	0x5BEB	#CJK UNIFIED IDEOGRAPH
+0x9B8E	0x5BF0	#CJK UNIFIED IDEOGRAPH
+0x9B8F	0x5BF6	#CJK UNIFIED IDEOGRAPH
+0x9B90	0x5BF3	#CJK UNIFIED IDEOGRAPH
+0x9B91	0x5C05	#CJK UNIFIED IDEOGRAPH
+0x9B92	0x5C07	#CJK UNIFIED IDEOGRAPH
+0x9B93	0x5C08	#CJK UNIFIED IDEOGRAPH
+0x9B94	0x5C0D	#CJK UNIFIED IDEOGRAPH
+0x9B95	0x5C13	#CJK UNIFIED IDEOGRAPH
+0x9B96	0x5C20	#CJK UNIFIED IDEOGRAPH
+0x9B97	0x5C22	#CJK UNIFIED IDEOGRAPH
+0x9B98	0x5C28	#CJK UNIFIED IDEOGRAPH
+0x9B99	0x5C38	#CJK UNIFIED IDEOGRAPH
+0x9B9A	0x5C39	#CJK UNIFIED IDEOGRAPH
+0x9B9B	0x5C41	#CJK UNIFIED IDEOGRAPH
+0x9B9C	0x5C46	#CJK UNIFIED IDEOGRAPH
+0x9B9D	0x5C4E	#CJK UNIFIED IDEOGRAPH
+0x9B9E	0x5C53	#CJK UNIFIED IDEOGRAPH
+0x9B9F	0x5C50	#CJK UNIFIED IDEOGRAPH
+0x9BA0	0x5C4F	#CJK UNIFIED IDEOGRAPH
+0x9BA1	0x5B71	#CJK UNIFIED IDEOGRAPH
+0x9BA2	0x5C6C	#CJK UNIFIED IDEOGRAPH
+0x9BA3	0x5C6E	#CJK UNIFIED IDEOGRAPH
+0x9BA4	0x4E62	#CJK UNIFIED IDEOGRAPH
+0x9BA5	0x5C76	#CJK UNIFIED IDEOGRAPH
+0x9BA6	0x5C79	#CJK UNIFIED IDEOGRAPH
+0x9BA7	0x5C8C	#CJK UNIFIED IDEOGRAPH
+0x9BA8	0x5C91	#CJK UNIFIED IDEOGRAPH
+0x9BA9	0x5C94	#CJK UNIFIED IDEOGRAPH
+0x9BAA	0x599B	#CJK UNIFIED IDEOGRAPH
+0x9BAB	0x5CAB	#CJK UNIFIED IDEOGRAPH
+0x9BAC	0x5CBB	#CJK UNIFIED IDEOGRAPH
+0x9BAD	0x5CB6	#CJK UNIFIED IDEOGRAPH
+0x9BAE	0x5CBC	#CJK UNIFIED IDEOGRAPH
+0x9BAF	0x5CB7	#CJK UNIFIED IDEOGRAPH
+0x9BB0	0x5CC5	#CJK UNIFIED IDEOGRAPH
+0x9BB1	0x5CBE	#CJK UNIFIED IDEOGRAPH
+0x9BB2	0x5CC7	#CJK UNIFIED IDEOGRAPH
+0x9BB3	0x5CD9	#CJK UNIFIED IDEOGRAPH
+0x9BB4	0x5CE9	#CJK UNIFIED IDEOGRAPH
+0x9BB5	0x5CFD	#CJK UNIFIED IDEOGRAPH
+0x9BB6	0x5CFA	#CJK UNIFIED IDEOGRAPH
+0x9BB7	0x5CED	#CJK UNIFIED IDEOGRAPH
+0x9BB8	0x5D8C	#CJK UNIFIED IDEOGRAPH
+0x9BB9	0x5CEA	#CJK UNIFIED IDEOGRAPH
+0x9BBA	0x5D0B	#CJK UNIFIED IDEOGRAPH
+0x9BBB	0x5D15	#CJK UNIFIED IDEOGRAPH
+0x9BBC	0x5D17	#CJK UNIFIED IDEOGRAPH
+0x9BBD	0x5D5C	#CJK UNIFIED IDEOGRAPH
+0x9BBE	0x5D1F	#CJK UNIFIED IDEOGRAPH
+0x9BBF	0x5D1B	#CJK UNIFIED IDEOGRAPH
+0x9BC0	0x5D11	#CJK UNIFIED IDEOGRAPH
+0x9BC1	0x5D14	#CJK UNIFIED IDEOGRAPH
+0x9BC2	0x5D22	#CJK UNIFIED IDEOGRAPH
+0x9BC3	0x5D1A	#CJK UNIFIED IDEOGRAPH
+0x9BC4	0x5D19	#CJK UNIFIED IDEOGRAPH
+0x9BC5	0x5D18	#CJK UNIFIED IDEOGRAPH
+0x9BC6	0x5D4C	#CJK UNIFIED IDEOGRAPH
+0x9BC7	0x5D52	#CJK UNIFIED IDEOGRAPH
+0x9BC8	0x5D4E	#CJK UNIFIED IDEOGRAPH
+0x9BC9	0x5D4B	#CJK UNIFIED IDEOGRAPH
+0x9BCA	0x5D6C	#CJK UNIFIED IDEOGRAPH
+0x9BCB	0x5D73	#CJK UNIFIED IDEOGRAPH
+0x9BCC	0x5D76	#CJK UNIFIED IDEOGRAPH
+0x9BCD	0x5D87	#CJK UNIFIED IDEOGRAPH
+0x9BCE	0x5D84	#CJK UNIFIED IDEOGRAPH
+0x9BCF	0x5D82	#CJK UNIFIED IDEOGRAPH
+0x9BD0	0x5DA2	#CJK UNIFIED IDEOGRAPH
+0x9BD1	0x5D9D	#CJK UNIFIED IDEOGRAPH
+0x9BD2	0x5DAC	#CJK UNIFIED IDEOGRAPH
+0x9BD3	0x5DAE	#CJK UNIFIED IDEOGRAPH
+0x9BD4	0x5DBD	#CJK UNIFIED IDEOGRAPH
+0x9BD5	0x5D90	#CJK UNIFIED IDEOGRAPH
+0x9BD6	0x5DB7	#CJK UNIFIED IDEOGRAPH
+0x9BD7	0x5DBC	#CJK UNIFIED IDEOGRAPH
+0x9BD8	0x5DC9	#CJK UNIFIED IDEOGRAPH
+0x9BD9	0x5DCD	#CJK UNIFIED IDEOGRAPH
+0x9BDA	0x5DD3	#CJK UNIFIED IDEOGRAPH
+0x9BDB	0x5DD2	#CJK UNIFIED IDEOGRAPH
+0x9BDC	0x5DD6	#CJK UNIFIED IDEOGRAPH
+0x9BDD	0x5DDB	#CJK UNIFIED IDEOGRAPH
+0x9BDE	0x5DEB	#CJK UNIFIED IDEOGRAPH
+0x9BDF	0x5DF2	#CJK UNIFIED IDEOGRAPH
+0x9BE0	0x5DF5	#CJK UNIFIED IDEOGRAPH
+0x9BE1	0x5E0B	#CJK UNIFIED IDEOGRAPH
+0x9BE2	0x5E1A	#CJK UNIFIED IDEOGRAPH
+0x9BE3	0x5E19	#CJK UNIFIED IDEOGRAPH
+0x9BE4	0x5E11	#CJK UNIFIED IDEOGRAPH
+0x9BE5	0x5E1B	#CJK UNIFIED IDEOGRAPH
+0x9BE6	0x5E36	#CJK UNIFIED IDEOGRAPH
+0x9BE7	0x5E37	#CJK UNIFIED IDEOGRAPH
+0x9BE8	0x5E44	#CJK UNIFIED IDEOGRAPH
+0x9BE9	0x5E43	#CJK UNIFIED IDEOGRAPH
+0x9BEA	0x5E40	#CJK UNIFIED IDEOGRAPH
+0x9BEB	0x5E4E	#CJK UNIFIED IDEOGRAPH
+0x9BEC	0x5E57	#CJK UNIFIED IDEOGRAPH
+0x9BED	0x5E54	#CJK UNIFIED IDEOGRAPH
+0x9BEE	0x5E5F	#CJK UNIFIED IDEOGRAPH
+0x9BEF	0x5E62	#CJK UNIFIED IDEOGRAPH
+0x9BF0	0x5E64	#CJK UNIFIED IDEOGRAPH
+0x9BF1	0x5E47	#CJK UNIFIED IDEOGRAPH
+0x9BF2	0x5E75	#CJK UNIFIED IDEOGRAPH
+0x9BF3	0x5E76	#CJK UNIFIED IDEOGRAPH
+0x9BF4	0x5E7A	#CJK UNIFIED IDEOGRAPH
+0x9BF5	0x9EBC	#CJK UNIFIED IDEOGRAPH
+0x9BF6	0x5E7F	#CJK UNIFIED IDEOGRAPH
+0x9BF7	0x5EA0	#CJK UNIFIED IDEOGRAPH
+0x9BF8	0x5EC1	#CJK UNIFIED IDEOGRAPH
+0x9BF9	0x5EC2	#CJK UNIFIED IDEOGRAPH
+0x9BFA	0x5EC8	#CJK UNIFIED IDEOGRAPH
+0x9BFB	0x5ED0	#CJK UNIFIED IDEOGRAPH
+0x9BFC	0x5ECF	#CJK UNIFIED IDEOGRAPH
+0x9C40	0x5ED6	#CJK UNIFIED IDEOGRAPH
+0x9C41	0x5EE3	#CJK UNIFIED IDEOGRAPH
+0x9C42	0x5EDD	#CJK UNIFIED IDEOGRAPH
+0x9C43	0x5EDA	#CJK UNIFIED IDEOGRAPH
+0x9C44	0x5EDB	#CJK UNIFIED IDEOGRAPH
+0x9C45	0x5EE2	#CJK UNIFIED IDEOGRAPH
+0x9C46	0x5EE1	#CJK UNIFIED IDEOGRAPH
+0x9C47	0x5EE8	#CJK UNIFIED IDEOGRAPH
+0x9C48	0x5EE9	#CJK UNIFIED IDEOGRAPH
+0x9C49	0x5EEC	#CJK UNIFIED IDEOGRAPH
+0x9C4A	0x5EF1	#CJK UNIFIED IDEOGRAPH
+0x9C4B	0x5EF3	#CJK UNIFIED IDEOGRAPH
+0x9C4C	0x5EF0	#CJK UNIFIED IDEOGRAPH
+0x9C4D	0x5EF4	#CJK UNIFIED IDEOGRAPH
+0x9C4E	0x5EF8	#CJK UNIFIED IDEOGRAPH
+0x9C4F	0x5EFE	#CJK UNIFIED IDEOGRAPH
+0x9C50	0x5F03	#CJK UNIFIED IDEOGRAPH
+0x9C51	0x5F09	#CJK UNIFIED IDEOGRAPH
+0x9C52	0x5F5D	#CJK UNIFIED IDEOGRAPH
+0x9C53	0x5F5C	#CJK UNIFIED IDEOGRAPH
+0x9C54	0x5F0B	#CJK UNIFIED IDEOGRAPH
+0x9C55	0x5F11	#CJK UNIFIED IDEOGRAPH
+0x9C56	0x5F16	#CJK UNIFIED IDEOGRAPH
+0x9C57	0x5F29	#CJK UNIFIED IDEOGRAPH
+0x9C58	0x5F2D	#CJK UNIFIED IDEOGRAPH
+0x9C59	0x5F38	#CJK UNIFIED IDEOGRAPH
+0x9C5A	0x5F41	#CJK UNIFIED IDEOGRAPH
+0x9C5B	0x5F48	#CJK UNIFIED IDEOGRAPH
+0x9C5C	0x5F4C	#CJK UNIFIED IDEOGRAPH
+0x9C5D	0x5F4E	#CJK UNIFIED IDEOGRAPH
+0x9C5E	0x5F2F	#CJK UNIFIED IDEOGRAPH
+0x9C5F	0x5F51	#CJK UNIFIED IDEOGRAPH
+0x9C60	0x5F56	#CJK UNIFIED IDEOGRAPH
+0x9C61	0x5F57	#CJK UNIFIED IDEOGRAPH
+0x9C62	0x5F59	#CJK UNIFIED IDEOGRAPH
+0x9C63	0x5F61	#CJK UNIFIED IDEOGRAPH
+0x9C64	0x5F6D	#CJK UNIFIED IDEOGRAPH
+0x9C65	0x5F73	#CJK UNIFIED IDEOGRAPH
+0x9C66	0x5F77	#CJK UNIFIED IDEOGRAPH
+0x9C67	0x5F83	#CJK UNIFIED IDEOGRAPH
+0x9C68	0x5F82	#CJK UNIFIED IDEOGRAPH
+0x9C69	0x5F7F	#CJK UNIFIED IDEOGRAPH
+0x9C6A	0x5F8A	#CJK UNIFIED IDEOGRAPH
+0x9C6B	0x5F88	#CJK UNIFIED IDEOGRAPH
+0x9C6C	0x5F91	#CJK UNIFIED IDEOGRAPH
+0x9C6D	0x5F87	#CJK UNIFIED IDEOGRAPH
+0x9C6E	0x5F9E	#CJK UNIFIED IDEOGRAPH
+0x9C6F	0x5F99	#CJK UNIFIED IDEOGRAPH
+0x9C70	0x5F98	#CJK UNIFIED IDEOGRAPH
+0x9C71	0x5FA0	#CJK UNIFIED IDEOGRAPH
+0x9C72	0x5FA8	#CJK UNIFIED IDEOGRAPH
+0x9C73	0x5FAD	#CJK UNIFIED IDEOGRAPH
+0x9C74	0x5FBC	#CJK UNIFIED IDEOGRAPH
+0x9C75	0x5FD6	#CJK UNIFIED IDEOGRAPH
+0x9C76	0x5FFB	#CJK UNIFIED IDEOGRAPH
+0x9C77	0x5FE4	#CJK UNIFIED IDEOGRAPH
+0x9C78	0x5FF8	#CJK UNIFIED IDEOGRAPH
+0x9C79	0x5FF1	#CJK UNIFIED IDEOGRAPH
+0x9C7A	0x5FDD	#CJK UNIFIED IDEOGRAPH
+0x9C7B	0x60B3	#CJK UNIFIED IDEOGRAPH
+0x9C7C	0x5FFF	#CJK UNIFIED IDEOGRAPH
+0x9C7D	0x6021	#CJK UNIFIED IDEOGRAPH
+0x9C7E	0x6060	#CJK UNIFIED IDEOGRAPH
+0x9C80	0x6019	#CJK UNIFIED IDEOGRAPH
+0x9C81	0x6010	#CJK UNIFIED IDEOGRAPH
+0x9C82	0x6029	#CJK UNIFIED IDEOGRAPH
+0x9C83	0x600E	#CJK UNIFIED IDEOGRAPH
+0x9C84	0x6031	#CJK UNIFIED IDEOGRAPH
+0x9C85	0x601B	#CJK UNIFIED IDEOGRAPH
+0x9C86	0x6015	#CJK UNIFIED IDEOGRAPH
+0x9C87	0x602B	#CJK UNIFIED IDEOGRAPH
+0x9C88	0x6026	#CJK UNIFIED IDEOGRAPH
+0x9C89	0x600F	#CJK UNIFIED IDEOGRAPH
+0x9C8A	0x603A	#CJK UNIFIED IDEOGRAPH
+0x9C8B	0x605A	#CJK UNIFIED IDEOGRAPH
+0x9C8C	0x6041	#CJK UNIFIED IDEOGRAPH
+0x9C8D	0x606A	#CJK UNIFIED IDEOGRAPH
+0x9C8E	0x6077	#CJK UNIFIED IDEOGRAPH
+0x9C8F	0x605F	#CJK UNIFIED IDEOGRAPH
+0x9C90	0x604A	#CJK UNIFIED IDEOGRAPH
+0x9C91	0x6046	#CJK UNIFIED IDEOGRAPH
+0x9C92	0x604D	#CJK UNIFIED IDEOGRAPH
+0x9C93	0x6063	#CJK UNIFIED IDEOGRAPH
+0x9C94	0x6043	#CJK UNIFIED IDEOGRAPH
+0x9C95	0x6064	#CJK UNIFIED IDEOGRAPH
+0x9C96	0x6042	#CJK UNIFIED IDEOGRAPH
+0x9C97	0x606C	#CJK UNIFIED IDEOGRAPH
+0x9C98	0x606B	#CJK UNIFIED IDEOGRAPH
+0x9C99	0x6059	#CJK UNIFIED IDEOGRAPH
+0x9C9A	0x6081	#CJK UNIFIED IDEOGRAPH
+0x9C9B	0x608D	#CJK UNIFIED IDEOGRAPH
+0x9C9C	0x60E7	#CJK UNIFIED IDEOGRAPH
+0x9C9D	0x6083	#CJK UNIFIED IDEOGRAPH
+0x9C9E	0x609A	#CJK UNIFIED IDEOGRAPH
+0x9C9F	0x6084	#CJK UNIFIED IDEOGRAPH
+0x9CA0	0x609B	#CJK UNIFIED IDEOGRAPH
+0x9CA1	0x6096	#CJK UNIFIED IDEOGRAPH
+0x9CA2	0x6097	#CJK UNIFIED IDEOGRAPH
+0x9CA3	0x6092	#CJK UNIFIED IDEOGRAPH
+0x9CA4	0x60A7	#CJK UNIFIED IDEOGRAPH
+0x9CA5	0x608B	#CJK UNIFIED IDEOGRAPH
+0x9CA6	0x60E1	#CJK UNIFIED IDEOGRAPH
+0x9CA7	0x60B8	#CJK UNIFIED IDEOGRAPH
+0x9CA8	0x60E0	#CJK UNIFIED IDEOGRAPH
+0x9CA9	0x60D3	#CJK UNIFIED IDEOGRAPH
+0x9CAA	0x60B4	#CJK UNIFIED IDEOGRAPH
+0x9CAB	0x5FF0	#CJK UNIFIED IDEOGRAPH
+0x9CAC	0x60BD	#CJK UNIFIED IDEOGRAPH
+0x9CAD	0x60C6	#CJK UNIFIED IDEOGRAPH
+0x9CAE	0x60B5	#CJK UNIFIED IDEOGRAPH
+0x9CAF	0x60D8	#CJK UNIFIED IDEOGRAPH
+0x9CB0	0x614D	#CJK UNIFIED IDEOGRAPH
+0x9CB1	0x6115	#CJK UNIFIED IDEOGRAPH
+0x9CB2	0x6106	#CJK UNIFIED IDEOGRAPH
+0x9CB3	0x60F6	#CJK UNIFIED IDEOGRAPH
+0x9CB4	0x60F7	#CJK UNIFIED IDEOGRAPH
+0x9CB5	0x6100	#CJK UNIFIED IDEOGRAPH
+0x9CB6	0x60F4	#CJK UNIFIED IDEOGRAPH
+0x9CB7	0x60FA	#CJK UNIFIED IDEOGRAPH
+0x9CB8	0x6103	#CJK UNIFIED IDEOGRAPH
+0x9CB9	0x6121	#CJK UNIFIED IDEOGRAPH
+0x9CBA	0x60FB	#CJK UNIFIED IDEOGRAPH
+0x9CBB	0x60F1	#CJK UNIFIED IDEOGRAPH
+0x9CBC	0x610D	#CJK UNIFIED IDEOGRAPH
+0x9CBD	0x610E	#CJK UNIFIED IDEOGRAPH
+0x9CBE	0x6147	#CJK UNIFIED IDEOGRAPH
+0x9CBF	0x613E	#CJK UNIFIED IDEOGRAPH
+0x9CC0	0x6128	#CJK UNIFIED IDEOGRAPH
+0x9CC1	0x6127	#CJK UNIFIED IDEOGRAPH
+0x9CC2	0x614A	#CJK UNIFIED IDEOGRAPH
+0x9CC3	0x613F	#CJK UNIFIED IDEOGRAPH
+0x9CC4	0x613C	#CJK UNIFIED IDEOGRAPH
+0x9CC5	0x612C	#CJK UNIFIED IDEOGRAPH
+0x9CC6	0x6134	#CJK UNIFIED IDEOGRAPH
+0x9CC7	0x613D	#CJK UNIFIED IDEOGRAPH
+0x9CC8	0x6142	#CJK UNIFIED IDEOGRAPH
+0x9CC9	0x6144	#CJK UNIFIED IDEOGRAPH
+0x9CCA	0x6173	#CJK UNIFIED IDEOGRAPH
+0x9CCB	0x6177	#CJK UNIFIED IDEOGRAPH
+0x9CCC	0x6158	#CJK UNIFIED IDEOGRAPH
+0x9CCD	0x6159	#CJK UNIFIED IDEOGRAPH
+0x9CCE	0x615A	#CJK UNIFIED IDEOGRAPH
+0x9CCF	0x616B	#CJK UNIFIED IDEOGRAPH
+0x9CD0	0x6174	#CJK UNIFIED IDEOGRAPH
+0x9CD1	0x616F	#CJK UNIFIED IDEOGRAPH
+0x9CD2	0x6165	#CJK UNIFIED IDEOGRAPH
+0x9CD3	0x6171	#CJK UNIFIED IDEOGRAPH
+0x9CD4	0x615F	#CJK UNIFIED IDEOGRAPH
+0x9CD5	0x615D	#CJK UNIFIED IDEOGRAPH
+0x9CD6	0x6153	#CJK UNIFIED IDEOGRAPH
+0x9CD7	0x6175	#CJK UNIFIED IDEOGRAPH
+0x9CD8	0x6199	#CJK UNIFIED IDEOGRAPH
+0x9CD9	0x6196	#CJK UNIFIED IDEOGRAPH
+0x9CDA	0x6187	#CJK UNIFIED IDEOGRAPH
+0x9CDB	0x61AC	#CJK UNIFIED IDEOGRAPH
+0x9CDC	0x6194	#CJK UNIFIED IDEOGRAPH
+0x9CDD	0x619A	#CJK UNIFIED IDEOGRAPH
+0x9CDE	0x618A	#CJK UNIFIED IDEOGRAPH
+0x9CDF	0x6191	#CJK UNIFIED IDEOGRAPH
+0x9CE0	0x61AB	#CJK UNIFIED IDEOGRAPH
+0x9CE1	0x61AE	#CJK UNIFIED IDEOGRAPH
+0x9CE2	0x61CC	#CJK UNIFIED IDEOGRAPH
+0x9CE3	0x61CA	#CJK UNIFIED IDEOGRAPH
+0x9CE4	0x61C9	#CJK UNIFIED IDEOGRAPH
+0x9CE5	0x61F7	#CJK UNIFIED IDEOGRAPH
+0x9CE6	0x61C8	#CJK UNIFIED IDEOGRAPH
+0x9CE7	0x61C3	#CJK UNIFIED IDEOGRAPH
+0x9CE8	0x61C6	#CJK UNIFIED IDEOGRAPH
+0x9CE9	0x61BA	#CJK UNIFIED IDEOGRAPH
+0x9CEA	0x61CB	#CJK UNIFIED IDEOGRAPH
+0x9CEB	0x7F79	#CJK UNIFIED IDEOGRAPH
+0x9CEC	0x61CD	#CJK UNIFIED IDEOGRAPH
+0x9CED	0x61E6	#CJK UNIFIED IDEOGRAPH
+0x9CEE	0x61E3	#CJK UNIFIED IDEOGRAPH
+0x9CEF	0x61F6	#CJK UNIFIED IDEOGRAPH
+0x9CF0	0x61FA	#CJK UNIFIED IDEOGRAPH
+0x9CF1	0x61F4	#CJK UNIFIED IDEOGRAPH
+0x9CF2	0x61FF	#CJK UNIFIED IDEOGRAPH
+0x9CF3	0x61FD	#CJK UNIFIED IDEOGRAPH
+0x9CF4	0x61FC	#CJK UNIFIED IDEOGRAPH
+0x9CF5	0x61FE	#CJK UNIFIED IDEOGRAPH
+0x9CF6	0x6200	#CJK UNIFIED IDEOGRAPH
+0x9CF7	0x6208	#CJK UNIFIED IDEOGRAPH
+0x9CF8	0x6209	#CJK UNIFIED IDEOGRAPH
+0x9CF9	0x620D	#CJK UNIFIED IDEOGRAPH
+0x9CFA	0x620C	#CJK UNIFIED IDEOGRAPH
+0x9CFB	0x6214	#CJK UNIFIED IDEOGRAPH
+0x9CFC	0x621B	#CJK UNIFIED IDEOGRAPH
+0x9D40	0x621E	#CJK UNIFIED IDEOGRAPH
+0x9D41	0x6221	#CJK UNIFIED IDEOGRAPH
+0x9D42	0x622A	#CJK UNIFIED IDEOGRAPH
+0x9D43	0x622E	#CJK UNIFIED IDEOGRAPH
+0x9D44	0x6230	#CJK UNIFIED IDEOGRAPH
+0x9D45	0x6232	#CJK UNIFIED IDEOGRAPH
+0x9D46	0x6233	#CJK UNIFIED IDEOGRAPH
+0x9D47	0x6241	#CJK UNIFIED IDEOGRAPH
+0x9D48	0x624E	#CJK UNIFIED IDEOGRAPH
+0x9D49	0x625E	#CJK UNIFIED IDEOGRAPH
+0x9D4A	0x6263	#CJK UNIFIED IDEOGRAPH
+0x9D4B	0x625B	#CJK UNIFIED IDEOGRAPH
+0x9D4C	0x6260	#CJK UNIFIED IDEOGRAPH
+0x9D4D	0x6268	#CJK UNIFIED IDEOGRAPH
+0x9D4E	0x627C	#CJK UNIFIED IDEOGRAPH
+0x9D4F	0x6282	#CJK UNIFIED IDEOGRAPH
+0x9D50	0x6289	#CJK UNIFIED IDEOGRAPH
+0x9D51	0x627E	#CJK UNIFIED IDEOGRAPH
+0x9D52	0x6292	#CJK UNIFIED IDEOGRAPH
+0x9D53	0x6293	#CJK UNIFIED IDEOGRAPH
+0x9D54	0x6296	#CJK UNIFIED IDEOGRAPH
+0x9D55	0x62D4	#CJK UNIFIED IDEOGRAPH
+0x9D56	0x6283	#CJK UNIFIED IDEOGRAPH
+0x9D57	0x6294	#CJK UNIFIED IDEOGRAPH
+0x9D58	0x62D7	#CJK UNIFIED IDEOGRAPH
+0x9D59	0x62D1	#CJK UNIFIED IDEOGRAPH
+0x9D5A	0x62BB	#CJK UNIFIED IDEOGRAPH
+0x9D5B	0x62CF	#CJK UNIFIED IDEOGRAPH
+0x9D5C	0x62FF	#CJK UNIFIED IDEOGRAPH
+0x9D5D	0x62C6	#CJK UNIFIED IDEOGRAPH
+0x9D5E	0x64D4	#CJK UNIFIED IDEOGRAPH
+0x9D5F	0x62C8	#CJK UNIFIED IDEOGRAPH
+0x9D60	0x62DC	#CJK UNIFIED IDEOGRAPH
+0x9D61	0x62CC	#CJK UNIFIED IDEOGRAPH
+0x9D62	0x62CA	#CJK UNIFIED IDEOGRAPH
+0x9D63	0x62C2	#CJK UNIFIED IDEOGRAPH
+0x9D64	0x62C7	#CJK UNIFIED IDEOGRAPH
+0x9D65	0x629B	#CJK UNIFIED IDEOGRAPH
+0x9D66	0x62C9	#CJK UNIFIED IDEOGRAPH
+0x9D67	0x630C	#CJK UNIFIED IDEOGRAPH
+0x9D68	0x62EE	#CJK UNIFIED IDEOGRAPH
+0x9D69	0x62F1	#CJK UNIFIED IDEOGRAPH
+0x9D6A	0x6327	#CJK UNIFIED IDEOGRAPH
+0x9D6B	0x6302	#CJK UNIFIED IDEOGRAPH
+0x9D6C	0x6308	#CJK UNIFIED IDEOGRAPH
+0x9D6D	0x62EF	#CJK UNIFIED IDEOGRAPH
+0x9D6E	0x62F5	#CJK UNIFIED IDEOGRAPH
+0x9D6F	0x6350	#CJK UNIFIED IDEOGRAPH
+0x9D70	0x633E	#CJK UNIFIED IDEOGRAPH
+0x9D71	0x634D	#CJK UNIFIED IDEOGRAPH
+0x9D72	0x641C	#CJK UNIFIED IDEOGRAPH
+0x9D73	0x634F	#CJK UNIFIED IDEOGRAPH
+0x9D74	0x6396	#CJK UNIFIED IDEOGRAPH
+0x9D75	0x638E	#CJK UNIFIED IDEOGRAPH
+0x9D76	0x6380	#CJK UNIFIED IDEOGRAPH
+0x9D77	0x63AB	#CJK UNIFIED IDEOGRAPH
+0x9D78	0x6376	#CJK UNIFIED IDEOGRAPH
+0x9D79	0x63A3	#CJK UNIFIED IDEOGRAPH
+0x9D7A	0x638F	#CJK UNIFIED IDEOGRAPH
+0x9D7B	0x6389	#CJK UNIFIED IDEOGRAPH
+0x9D7C	0x639F	#CJK UNIFIED IDEOGRAPH
+0x9D7D	0x63B5	#CJK UNIFIED IDEOGRAPH
+0x9D7E	0x636B	#CJK UNIFIED IDEOGRAPH
+0x9D80	0x6369	#CJK UNIFIED IDEOGRAPH
+0x9D81	0x63BE	#CJK UNIFIED IDEOGRAPH
+0x9D82	0x63E9	#CJK UNIFIED IDEOGRAPH
+0x9D83	0x63C0	#CJK UNIFIED IDEOGRAPH
+0x9D84	0x63C6	#CJK UNIFIED IDEOGRAPH
+0x9D85	0x63E3	#CJK UNIFIED IDEOGRAPH
+0x9D86	0x63C9	#CJK UNIFIED IDEOGRAPH
+0x9D87	0x63D2	#CJK UNIFIED IDEOGRAPH
+0x9D88	0x63F6	#CJK UNIFIED IDEOGRAPH
+0x9D89	0x63C4	#CJK UNIFIED IDEOGRAPH
+0x9D8A	0x6416	#CJK UNIFIED IDEOGRAPH
+0x9D8B	0x6434	#CJK UNIFIED IDEOGRAPH
+0x9D8C	0x6406	#CJK UNIFIED IDEOGRAPH
+0x9D8D	0x6413	#CJK UNIFIED IDEOGRAPH
+0x9D8E	0x6426	#CJK UNIFIED IDEOGRAPH
+0x9D8F	0x6436	#CJK UNIFIED IDEOGRAPH
+0x9D90	0x651D	#CJK UNIFIED IDEOGRAPH
+0x9D91	0x6417	#CJK UNIFIED IDEOGRAPH
+0x9D92	0x6428	#CJK UNIFIED IDEOGRAPH
+0x9D93	0x640F	#CJK UNIFIED IDEOGRAPH
+0x9D94	0x6467	#CJK UNIFIED IDEOGRAPH
+0x9D95	0x646F	#CJK UNIFIED IDEOGRAPH
+0x9D96	0x6476	#CJK UNIFIED IDEOGRAPH
+0x9D97	0x644E	#CJK UNIFIED IDEOGRAPH
+0x9D98	0x652A	#CJK UNIFIED IDEOGRAPH
+0x9D99	0x6495	#CJK UNIFIED IDEOGRAPH
+0x9D9A	0x6493	#CJK UNIFIED IDEOGRAPH
+0x9D9B	0x64A5	#CJK UNIFIED IDEOGRAPH
+0x9D9C	0x64A9	#CJK UNIFIED IDEOGRAPH
+0x9D9D	0x6488	#CJK UNIFIED IDEOGRAPH
+0x9D9E	0x64BC	#CJK UNIFIED IDEOGRAPH
+0x9D9F	0x64DA	#CJK UNIFIED IDEOGRAPH
+0x9DA0	0x64D2	#CJK UNIFIED IDEOGRAPH
+0x9DA1	0x64C5	#CJK UNIFIED IDEOGRAPH
+0x9DA2	0x64C7	#CJK UNIFIED IDEOGRAPH
+0x9DA3	0x64BB	#CJK UNIFIED IDEOGRAPH
+0x9DA4	0x64D8	#CJK UNIFIED IDEOGRAPH
+0x9DA5	0x64C2	#CJK UNIFIED IDEOGRAPH
+0x9DA6	0x64F1	#CJK UNIFIED IDEOGRAPH
+0x9DA7	0x64E7	#CJK UNIFIED IDEOGRAPH
+0x9DA8	0x8209	#CJK UNIFIED IDEOGRAPH
+0x9DA9	0x64E0	#CJK UNIFIED IDEOGRAPH
+0x9DAA	0x64E1	#CJK UNIFIED IDEOGRAPH
+0x9DAB	0x62AC	#CJK UNIFIED IDEOGRAPH
+0x9DAC	0x64E3	#CJK UNIFIED IDEOGRAPH
+0x9DAD	0x64EF	#CJK UNIFIED IDEOGRAPH
+0x9DAE	0x652C	#CJK UNIFIED IDEOGRAPH
+0x9DAF	0x64F6	#CJK UNIFIED IDEOGRAPH
+0x9DB0	0x64F4	#CJK UNIFIED IDEOGRAPH
+0x9DB1	0x64F2	#CJK UNIFIED IDEOGRAPH
+0x9DB2	0x64FA	#CJK UNIFIED IDEOGRAPH
+0x9DB3	0x6500	#CJK UNIFIED IDEOGRAPH
+0x9DB4	0x64FD	#CJK UNIFIED IDEOGRAPH
+0x9DB5	0x6518	#CJK UNIFIED IDEOGRAPH
+0x9DB6	0x651C	#CJK UNIFIED IDEOGRAPH
+0x9DB7	0x6505	#CJK UNIFIED IDEOGRAPH
+0x9DB8	0x6524	#CJK UNIFIED IDEOGRAPH
+0x9DB9	0x6523	#CJK UNIFIED IDEOGRAPH
+0x9DBA	0x652B	#CJK UNIFIED IDEOGRAPH
+0x9DBB	0x6534	#CJK UNIFIED IDEOGRAPH
+0x9DBC	0x6535	#CJK UNIFIED IDEOGRAPH
+0x9DBD	0x6537	#CJK UNIFIED IDEOGRAPH
+0x9DBE	0x6536	#CJK UNIFIED IDEOGRAPH
+0x9DBF	0x6538	#CJK UNIFIED IDEOGRAPH
+0x9DC0	0x754B	#CJK UNIFIED IDEOGRAPH
+0x9DC1	0x6548	#CJK UNIFIED IDEOGRAPH
+0x9DC2	0x6556	#CJK UNIFIED IDEOGRAPH
+0x9DC3	0x6555	#CJK UNIFIED IDEOGRAPH
+0x9DC4	0x654D	#CJK UNIFIED IDEOGRAPH
+0x9DC5	0x6558	#CJK UNIFIED IDEOGRAPH
+0x9DC6	0x655E	#CJK UNIFIED IDEOGRAPH
+0x9DC7	0x655D	#CJK UNIFIED IDEOGRAPH
+0x9DC8	0x6572	#CJK UNIFIED IDEOGRAPH
+0x9DC9	0x6578	#CJK UNIFIED IDEOGRAPH
+0x9DCA	0x6582	#CJK UNIFIED IDEOGRAPH
+0x9DCB	0x6583	#CJK UNIFIED IDEOGRAPH
+0x9DCC	0x8B8A	#CJK UNIFIED IDEOGRAPH
+0x9DCD	0x659B	#CJK UNIFIED IDEOGRAPH
+0x9DCE	0x659F	#CJK UNIFIED IDEOGRAPH
+0x9DCF	0x65AB	#CJK UNIFIED IDEOGRAPH
+0x9DD0	0x65B7	#CJK UNIFIED IDEOGRAPH
+0x9DD1	0x65C3	#CJK UNIFIED IDEOGRAPH
+0x9DD2	0x65C6	#CJK UNIFIED IDEOGRAPH
+0x9DD3	0x65C1	#CJK UNIFIED IDEOGRAPH
+0x9DD4	0x65C4	#CJK UNIFIED IDEOGRAPH
+0x9DD5	0x65CC	#CJK UNIFIED IDEOGRAPH
+0x9DD6	0x65D2	#CJK UNIFIED IDEOGRAPH
+0x9DD7	0x65DB	#CJK UNIFIED IDEOGRAPH
+0x9DD8	0x65D9	#CJK UNIFIED IDEOGRAPH
+0x9DD9	0x65E0	#CJK UNIFIED IDEOGRAPH
+0x9DDA	0x65E1	#CJK UNIFIED IDEOGRAPH
+0x9DDB	0x65F1	#CJK UNIFIED IDEOGRAPH
+0x9DDC	0x6772	#CJK UNIFIED IDEOGRAPH
+0x9DDD	0x660A	#CJK UNIFIED IDEOGRAPH
+0x9DDE	0x6603	#CJK UNIFIED IDEOGRAPH
+0x9DDF	0x65FB	#CJK UNIFIED IDEOGRAPH
+0x9DE0	0x6773	#CJK UNIFIED IDEOGRAPH
+0x9DE1	0x6635	#CJK UNIFIED IDEOGRAPH
+0x9DE2	0x6636	#CJK UNIFIED IDEOGRAPH
+0x9DE3	0x6634	#CJK UNIFIED IDEOGRAPH
+0x9DE4	0x661C	#CJK UNIFIED IDEOGRAPH
+0x9DE5	0x664F	#CJK UNIFIED IDEOGRAPH
+0x9DE6	0x6644	#CJK UNIFIED IDEOGRAPH
+0x9DE7	0x6649	#CJK UNIFIED IDEOGRAPH
+0x9DE8	0x6641	#CJK UNIFIED IDEOGRAPH
+0x9DE9	0x665E	#CJK UNIFIED IDEOGRAPH
+0x9DEA	0x665D	#CJK UNIFIED IDEOGRAPH
+0x9DEB	0x6664	#CJK UNIFIED IDEOGRAPH
+0x9DEC	0x6667	#CJK UNIFIED IDEOGRAPH
+0x9DED	0x6668	#CJK UNIFIED IDEOGRAPH
+0x9DEE	0x665F	#CJK UNIFIED IDEOGRAPH
+0x9DEF	0x6662	#CJK UNIFIED IDEOGRAPH
+0x9DF0	0x6670	#CJK UNIFIED IDEOGRAPH
+0x9DF1	0x6683	#CJK UNIFIED IDEOGRAPH
+0x9DF2	0x6688	#CJK UNIFIED IDEOGRAPH
+0x9DF3	0x668E	#CJK UNIFIED IDEOGRAPH
+0x9DF4	0x6689	#CJK UNIFIED IDEOGRAPH
+0x9DF5	0x6684	#CJK UNIFIED IDEOGRAPH
+0x9DF6	0x6698	#CJK UNIFIED IDEOGRAPH
+0x9DF7	0x669D	#CJK UNIFIED IDEOGRAPH
+0x9DF8	0x66C1	#CJK UNIFIED IDEOGRAPH
+0x9DF9	0x66B9	#CJK UNIFIED IDEOGRAPH
+0x9DFA	0x66C9	#CJK UNIFIED IDEOGRAPH
+0x9DFB	0x66BE	#CJK UNIFIED IDEOGRAPH
+0x9DFC	0x66BC	#CJK UNIFIED IDEOGRAPH
+0x9E40	0x66C4	#CJK UNIFIED IDEOGRAPH
+0x9E41	0x66B8	#CJK UNIFIED IDEOGRAPH
+0x9E42	0x66D6	#CJK UNIFIED IDEOGRAPH
+0x9E43	0x66DA	#CJK UNIFIED IDEOGRAPH
+0x9E44	0x66E0	#CJK UNIFIED IDEOGRAPH
+0x9E45	0x663F	#CJK UNIFIED IDEOGRAPH
+0x9E46	0x66E6	#CJK UNIFIED IDEOGRAPH
+0x9E47	0x66E9	#CJK UNIFIED IDEOGRAPH
+0x9E48	0x66F0	#CJK UNIFIED IDEOGRAPH
+0x9E49	0x66F5	#CJK UNIFIED IDEOGRAPH
+0x9E4A	0x66F7	#CJK UNIFIED IDEOGRAPH
+0x9E4B	0x670F	#CJK UNIFIED IDEOGRAPH
+0x9E4C	0x6716	#CJK UNIFIED IDEOGRAPH
+0x9E4D	0x671E	#CJK UNIFIED IDEOGRAPH
+0x9E4E	0x6726	#CJK UNIFIED IDEOGRAPH
+0x9E4F	0x6727	#CJK UNIFIED IDEOGRAPH
+0x9E50	0x9738	#CJK UNIFIED IDEOGRAPH
+0x9E51	0x672E	#CJK UNIFIED IDEOGRAPH
+0x9E52	0x673F	#CJK UNIFIED IDEOGRAPH
+0x9E53	0x6736	#CJK UNIFIED IDEOGRAPH
+0x9E54	0x6741	#CJK UNIFIED IDEOGRAPH
+0x9E55	0x6738	#CJK UNIFIED IDEOGRAPH
+0x9E56	0x6737	#CJK UNIFIED IDEOGRAPH
+0x9E57	0x6746	#CJK UNIFIED IDEOGRAPH
+0x9E58	0x675E	#CJK UNIFIED IDEOGRAPH
+0x9E59	0x6760	#CJK UNIFIED IDEOGRAPH
+0x9E5A	0x6759	#CJK UNIFIED IDEOGRAPH
+0x9E5B	0x6763	#CJK UNIFIED IDEOGRAPH
+0x9E5C	0x6764	#CJK UNIFIED IDEOGRAPH
+0x9E5D	0x6789	#CJK UNIFIED IDEOGRAPH
+0x9E5E	0x6770	#CJK UNIFIED IDEOGRAPH
+0x9E5F	0x67A9	#CJK UNIFIED IDEOGRAPH
+0x9E60	0x677C	#CJK UNIFIED IDEOGRAPH
+0x9E61	0x676A	#CJK UNIFIED IDEOGRAPH
+0x9E62	0x678C	#CJK UNIFIED IDEOGRAPH
+0x9E63	0x678B	#CJK UNIFIED IDEOGRAPH
+0x9E64	0x67A6	#CJK UNIFIED IDEOGRAPH
+0x9E65	0x67A1	#CJK UNIFIED IDEOGRAPH
+0x9E66	0x6785	#CJK UNIFIED IDEOGRAPH
+0x9E67	0x67B7	#CJK UNIFIED IDEOGRAPH
+0x9E68	0x67EF	#CJK UNIFIED IDEOGRAPH
+0x9E69	0x67B4	#CJK UNIFIED IDEOGRAPH
+0x9E6A	0x67EC	#CJK UNIFIED IDEOGRAPH
+0x9E6B	0x67B3	#CJK UNIFIED IDEOGRAPH
+0x9E6C	0x67E9	#CJK UNIFIED IDEOGRAPH
+0x9E6D	0x67B8	#CJK UNIFIED IDEOGRAPH
+0x9E6E	0x67E4	#CJK UNIFIED IDEOGRAPH
+0x9E6F	0x67DE	#CJK UNIFIED IDEOGRAPH
+0x9E70	0x67DD	#CJK UNIFIED IDEOGRAPH
+0x9E71	0x67E2	#CJK UNIFIED IDEOGRAPH
+0x9E72	0x67EE	#CJK UNIFIED IDEOGRAPH
+0x9E73	0x67B9	#CJK UNIFIED IDEOGRAPH
+0x9E74	0x67CE	#CJK UNIFIED IDEOGRAPH
+0x9E75	0x67C6	#CJK UNIFIED IDEOGRAPH
+0x9E76	0x67E7	#CJK UNIFIED IDEOGRAPH
+0x9E77	0x6A9C	#CJK UNIFIED IDEOGRAPH
+0x9E78	0x681E	#CJK UNIFIED IDEOGRAPH
+0x9E79	0x6846	#CJK UNIFIED IDEOGRAPH
+0x9E7A	0x6829	#CJK UNIFIED IDEOGRAPH
+0x9E7B	0x6840	#CJK UNIFIED IDEOGRAPH
+0x9E7C	0x684D	#CJK UNIFIED IDEOGRAPH
+0x9E7D	0x6832	#CJK UNIFIED IDEOGRAPH
+0x9E7E	0x684E	#CJK UNIFIED IDEOGRAPH
+0x9E80	0x68B3	#CJK UNIFIED IDEOGRAPH
+0x9E81	0x682B	#CJK UNIFIED IDEOGRAPH
+0x9E82	0x6859	#CJK UNIFIED IDEOGRAPH
+0x9E83	0x6863	#CJK UNIFIED IDEOGRAPH
+0x9E84	0x6877	#CJK UNIFIED IDEOGRAPH
+0x9E85	0x687F	#CJK UNIFIED IDEOGRAPH
+0x9E86	0x689F	#CJK UNIFIED IDEOGRAPH
+0x9E87	0x688F	#CJK UNIFIED IDEOGRAPH
+0x9E88	0x68AD	#CJK UNIFIED IDEOGRAPH
+0x9E89	0x6894	#CJK UNIFIED IDEOGRAPH
+0x9E8A	0x689D	#CJK UNIFIED IDEOGRAPH
+0x9E8B	0x689B	#CJK UNIFIED IDEOGRAPH
+0x9E8C	0x6883	#CJK UNIFIED IDEOGRAPH
+0x9E8D	0x6AAE	#CJK UNIFIED IDEOGRAPH
+0x9E8E	0x68B9	#CJK UNIFIED IDEOGRAPH
+0x9E8F	0x6874	#CJK UNIFIED IDEOGRAPH
+0x9E90	0x68B5	#CJK UNIFIED IDEOGRAPH
+0x9E91	0x68A0	#CJK UNIFIED IDEOGRAPH
+0x9E92	0x68BA	#CJK UNIFIED IDEOGRAPH
+0x9E93	0x690F	#CJK UNIFIED IDEOGRAPH
+0x9E94	0x688D	#CJK UNIFIED IDEOGRAPH
+0x9E95	0x687E	#CJK UNIFIED IDEOGRAPH
+0x9E96	0x6901	#CJK UNIFIED IDEOGRAPH
+0x9E97	0x68CA	#CJK UNIFIED IDEOGRAPH
+0x9E98	0x6908	#CJK UNIFIED IDEOGRAPH
+0x9E99	0x68D8	#CJK UNIFIED IDEOGRAPH
+0x9E9A	0x6922	#CJK UNIFIED IDEOGRAPH
+0x9E9B	0x6926	#CJK UNIFIED IDEOGRAPH
+0x9E9C	0x68E1	#CJK UNIFIED IDEOGRAPH
+0x9E9D	0x690C	#CJK UNIFIED IDEOGRAPH
+0x9E9E	0x68CD	#CJK UNIFIED IDEOGRAPH
+0x9E9F	0x68D4	#CJK UNIFIED IDEOGRAPH
+0x9EA0	0x68E7	#CJK UNIFIED IDEOGRAPH
+0x9EA1	0x68D5	#CJK UNIFIED IDEOGRAPH
+0x9EA2	0x6936	#CJK UNIFIED IDEOGRAPH
+0x9EA3	0x6912	#CJK UNIFIED IDEOGRAPH
+0x9EA4	0x6904	#CJK UNIFIED IDEOGRAPH
+0x9EA5	0x68D7	#CJK UNIFIED IDEOGRAPH
+0x9EA6	0x68E3	#CJK UNIFIED IDEOGRAPH
+0x9EA7	0x6925	#CJK UNIFIED IDEOGRAPH
+0x9EA8	0x68F9	#CJK UNIFIED IDEOGRAPH
+0x9EA9	0x68E0	#CJK UNIFIED IDEOGRAPH
+0x9EAA	0x68EF	#CJK UNIFIED IDEOGRAPH
+0x9EAB	0x6928	#CJK UNIFIED IDEOGRAPH
+0x9EAC	0x692A	#CJK UNIFIED IDEOGRAPH
+0x9EAD	0x691A	#CJK UNIFIED IDEOGRAPH
+0x9EAE	0x6923	#CJK UNIFIED IDEOGRAPH
+0x9EAF	0x6921	#CJK UNIFIED IDEOGRAPH
+0x9EB0	0x68C6	#CJK UNIFIED IDEOGRAPH
+0x9EB1	0x6979	#CJK UNIFIED IDEOGRAPH
+0x9EB2	0x6977	#CJK UNIFIED IDEOGRAPH
+0x9EB3	0x695C	#CJK UNIFIED IDEOGRAPH
+0x9EB4	0x6978	#CJK UNIFIED IDEOGRAPH
+0x9EB5	0x696B	#CJK UNIFIED IDEOGRAPH
+0x9EB6	0x6954	#CJK UNIFIED IDEOGRAPH
+0x9EB7	0x697E	#CJK UNIFIED IDEOGRAPH
+0x9EB8	0x696E	#CJK UNIFIED IDEOGRAPH
+0x9EB9	0x6939	#CJK UNIFIED IDEOGRAPH
+0x9EBA	0x6974	#CJK UNIFIED IDEOGRAPH
+0x9EBB	0x693D	#CJK UNIFIED IDEOGRAPH
+0x9EBC	0x6959	#CJK UNIFIED IDEOGRAPH
+0x9EBD	0x6930	#CJK UNIFIED IDEOGRAPH
+0x9EBE	0x6961	#CJK UNIFIED IDEOGRAPH
+0x9EBF	0x695E	#CJK UNIFIED IDEOGRAPH
+0x9EC0	0x695D	#CJK UNIFIED IDEOGRAPH
+0x9EC1	0x6981	#CJK UNIFIED IDEOGRAPH
+0x9EC2	0x696A	#CJK UNIFIED IDEOGRAPH
+0x9EC3	0x69B2	#CJK UNIFIED IDEOGRAPH
+0x9EC4	0x69AE	#CJK UNIFIED IDEOGRAPH
+0x9EC5	0x69D0	#CJK UNIFIED IDEOGRAPH
+0x9EC6	0x69BF	#CJK UNIFIED IDEOGRAPH
+0x9EC7	0x69C1	#CJK UNIFIED IDEOGRAPH
+0x9EC8	0x69D3	#CJK UNIFIED IDEOGRAPH
+0x9EC9	0x69BE	#CJK UNIFIED IDEOGRAPH
+0x9ECA	0x69CE	#CJK UNIFIED IDEOGRAPH
+0x9ECB	0x5BE8	#CJK UNIFIED IDEOGRAPH
+0x9ECC	0x69CA	#CJK UNIFIED IDEOGRAPH
+0x9ECD	0x69DD	#CJK UNIFIED IDEOGRAPH
+0x9ECE	0x69BB	#CJK UNIFIED IDEOGRAPH
+0x9ECF	0x69C3	#CJK UNIFIED IDEOGRAPH
+0x9ED0	0x69A7	#CJK UNIFIED IDEOGRAPH
+0x9ED1	0x6A2E	#CJK UNIFIED IDEOGRAPH
+0x9ED2	0x6991	#CJK UNIFIED IDEOGRAPH
+0x9ED3	0x69A0	#CJK UNIFIED IDEOGRAPH
+0x9ED4	0x699C	#CJK UNIFIED IDEOGRAPH
+0x9ED5	0x6995	#CJK UNIFIED IDEOGRAPH
+0x9ED6	0x69B4	#CJK UNIFIED IDEOGRAPH
+0x9ED7	0x69DE	#CJK UNIFIED IDEOGRAPH
+0x9ED8	0x69E8	#CJK UNIFIED IDEOGRAPH
+0x9ED9	0x6A02	#CJK UNIFIED IDEOGRAPH
+0x9EDA	0x6A1B	#CJK UNIFIED IDEOGRAPH
+0x9EDB	0x69FF	#CJK UNIFIED IDEOGRAPH
+0x9EDC	0x6B0A	#CJK UNIFIED IDEOGRAPH
+0x9EDD	0x69F9	#CJK UNIFIED IDEOGRAPH
+0x9EDE	0x69F2	#CJK UNIFIED IDEOGRAPH
+0x9EDF	0x69E7	#CJK UNIFIED IDEOGRAPH
+0x9EE0	0x6A05	#CJK UNIFIED IDEOGRAPH
+0x9EE1	0x69B1	#CJK UNIFIED IDEOGRAPH
+0x9EE2	0x6A1E	#CJK UNIFIED IDEOGRAPH
+0x9EE3	0x69ED	#CJK UNIFIED IDEOGRAPH
+0x9EE4	0x6A14	#CJK UNIFIED IDEOGRAPH
+0x9EE5	0x69EB	#CJK UNIFIED IDEOGRAPH
+0x9EE6	0x6A0A	#CJK UNIFIED IDEOGRAPH
+0x9EE7	0x6A12	#CJK UNIFIED IDEOGRAPH
+0x9EE8	0x6AC1	#CJK UNIFIED IDEOGRAPH
+0x9EE9	0x6A23	#CJK UNIFIED IDEOGRAPH
+0x9EEA	0x6A13	#CJK UNIFIED IDEOGRAPH
+0x9EEB	0x6A44	#CJK UNIFIED IDEOGRAPH
+0x9EEC	0x6A0C	#CJK UNIFIED IDEOGRAPH
+0x9EED	0x6A72	#CJK UNIFIED IDEOGRAPH
+0x9EEE	0x6A36	#CJK UNIFIED IDEOGRAPH
+0x9EEF	0x6A78	#CJK UNIFIED IDEOGRAPH
+0x9EF0	0x6A47	#CJK UNIFIED IDEOGRAPH
+0x9EF1	0x6A62	#CJK UNIFIED IDEOGRAPH
+0x9EF2	0x6A59	#CJK UNIFIED IDEOGRAPH
+0x9EF3	0x6A66	#CJK UNIFIED IDEOGRAPH
+0x9EF4	0x6A48	#CJK UNIFIED IDEOGRAPH
+0x9EF5	0x6A38	#CJK UNIFIED IDEOGRAPH
+0x9EF6	0x6A22	#CJK UNIFIED IDEOGRAPH
+0x9EF7	0x6A90	#CJK UNIFIED IDEOGRAPH
+0x9EF8	0x6A8D	#CJK UNIFIED IDEOGRAPH
+0x9EF9	0x6AA0	#CJK UNIFIED IDEOGRAPH
+0x9EFA	0x6A84	#CJK UNIFIED IDEOGRAPH
+0x9EFB	0x6AA2	#CJK UNIFIED IDEOGRAPH
+0x9EFC	0x6AA3	#CJK UNIFIED IDEOGRAPH
+0x9F40	0x6A97	#CJK UNIFIED IDEOGRAPH
+0x9F41	0x8617	#CJK UNIFIED IDEOGRAPH
+0x9F42	0x6ABB	#CJK UNIFIED IDEOGRAPH
+0x9F43	0x6AC3	#CJK UNIFIED IDEOGRAPH
+0x9F44	0x6AC2	#CJK UNIFIED IDEOGRAPH
+0x9F45	0x6AB8	#CJK UNIFIED IDEOGRAPH
+0x9F46	0x6AB3	#CJK UNIFIED IDEOGRAPH
+0x9F47	0x6AAC	#CJK UNIFIED IDEOGRAPH
+0x9F48	0x6ADE	#CJK UNIFIED IDEOGRAPH
+0x9F49	0x6AD1	#CJK UNIFIED IDEOGRAPH
+0x9F4A	0x6ADF	#CJK UNIFIED IDEOGRAPH
+0x9F4B	0x6AAA	#CJK UNIFIED IDEOGRAPH
+0x9F4C	0x6ADA	#CJK UNIFIED IDEOGRAPH
+0x9F4D	0x6AEA	#CJK UNIFIED IDEOGRAPH
+0x9F4E	0x6AFB	#CJK UNIFIED IDEOGRAPH
+0x9F4F	0x6B05	#CJK UNIFIED IDEOGRAPH
+0x9F50	0x8616	#CJK UNIFIED IDEOGRAPH
+0x9F51	0x6AFA	#CJK UNIFIED IDEOGRAPH
+0x9F52	0x6B12	#CJK UNIFIED IDEOGRAPH
+0x9F53	0x6B16	#CJK UNIFIED IDEOGRAPH
+0x9F54	0x9B31	#CJK UNIFIED IDEOGRAPH
+0x9F55	0x6B1F	#CJK UNIFIED IDEOGRAPH
+0x9F56	0x6B38	#CJK UNIFIED IDEOGRAPH
+0x9F57	0x6B37	#CJK UNIFIED IDEOGRAPH
+0x9F58	0x76DC	#CJK UNIFIED IDEOGRAPH
+0x9F59	0x6B39	#CJK UNIFIED IDEOGRAPH
+0x9F5A	0x98EE	#CJK UNIFIED IDEOGRAPH
+0x9F5B	0x6B47	#CJK UNIFIED IDEOGRAPH
+0x9F5C	0x6B43	#CJK UNIFIED IDEOGRAPH
+0x9F5D	0x6B49	#CJK UNIFIED IDEOGRAPH
+0x9F5E	0x6B50	#CJK UNIFIED IDEOGRAPH
+0x9F5F	0x6B59	#CJK UNIFIED IDEOGRAPH
+0x9F60	0x6B54	#CJK UNIFIED IDEOGRAPH
+0x9F61	0x6B5B	#CJK UNIFIED IDEOGRAPH
+0x9F62	0x6B5F	#CJK UNIFIED IDEOGRAPH
+0x9F63	0x6B61	#CJK UNIFIED IDEOGRAPH
+0x9F64	0x6B78	#CJK UNIFIED IDEOGRAPH
+0x9F65	0x6B79	#CJK UNIFIED IDEOGRAPH
+0x9F66	0x6B7F	#CJK UNIFIED IDEOGRAPH
+0x9F67	0x6B80	#CJK UNIFIED IDEOGRAPH
+0x9F68	0x6B84	#CJK UNIFIED IDEOGRAPH
+0x9F69	0x6B83	#CJK UNIFIED IDEOGRAPH
+0x9F6A	0x6B8D	#CJK UNIFIED IDEOGRAPH
+0x9F6B	0x6B98	#CJK UNIFIED IDEOGRAPH
+0x9F6C	0x6B95	#CJK UNIFIED IDEOGRAPH
+0x9F6D	0x6B9E	#CJK UNIFIED IDEOGRAPH
+0x9F6E	0x6BA4	#CJK UNIFIED IDEOGRAPH
+0x9F6F	0x6BAA	#CJK UNIFIED IDEOGRAPH
+0x9F70	0x6BAB	#CJK UNIFIED IDEOGRAPH
+0x9F71	0x6BAF	#CJK UNIFIED IDEOGRAPH
+0x9F72	0x6BB2	#CJK UNIFIED IDEOGRAPH
+0x9F73	0x6BB1	#CJK UNIFIED IDEOGRAPH
+0x9F74	0x6BB3	#CJK UNIFIED IDEOGRAPH
+0x9F75	0x6BB7	#CJK UNIFIED IDEOGRAPH
+0x9F76	0x6BBC	#CJK UNIFIED IDEOGRAPH
+0x9F77	0x6BC6	#CJK UNIFIED IDEOGRAPH
+0x9F78	0x6BCB	#CJK UNIFIED IDEOGRAPH
+0x9F79	0x6BD3	#CJK UNIFIED IDEOGRAPH
+0x9F7A	0x6BDF	#CJK UNIFIED IDEOGRAPH
+0x9F7B	0x6BEC	#CJK UNIFIED IDEOGRAPH
+0x9F7C	0x6BEB	#CJK UNIFIED IDEOGRAPH
+0x9F7D	0x6BF3	#CJK UNIFIED IDEOGRAPH
+0x9F7E	0x6BEF	#CJK UNIFIED IDEOGRAPH
+0x9F80	0x9EBE	#CJK UNIFIED IDEOGRAPH
+0x9F81	0x6C08	#CJK UNIFIED IDEOGRAPH
+0x9F82	0x6C13	#CJK UNIFIED IDEOGRAPH
+0x9F83	0x6C14	#CJK UNIFIED IDEOGRAPH
+0x9F84	0x6C1B	#CJK UNIFIED IDEOGRAPH
+0x9F85	0x6C24	#CJK UNIFIED IDEOGRAPH
+0x9F86	0x6C23	#CJK UNIFIED IDEOGRAPH
+0x9F87	0x6C5E	#CJK UNIFIED IDEOGRAPH
+0x9F88	0x6C55	#CJK UNIFIED IDEOGRAPH
+0x9F89	0x6C62	#CJK UNIFIED IDEOGRAPH
+0x9F8A	0x6C6A	#CJK UNIFIED IDEOGRAPH
+0x9F8B	0x6C82	#CJK UNIFIED IDEOGRAPH
+0x9F8C	0x6C8D	#CJK UNIFIED IDEOGRAPH
+0x9F8D	0x6C9A	#CJK UNIFIED IDEOGRAPH
+0x9F8E	0x6C81	#CJK UNIFIED IDEOGRAPH
+0x9F8F	0x6C9B	#CJK UNIFIED IDEOGRAPH
+0x9F90	0x6C7E	#CJK UNIFIED IDEOGRAPH
+0x9F91	0x6C68	#CJK UNIFIED IDEOGRAPH
+0x9F92	0x6C73	#CJK UNIFIED IDEOGRAPH
+0x9F93	0x6C92	#CJK UNIFIED IDEOGRAPH
+0x9F94	0x6C90	#CJK UNIFIED IDEOGRAPH
+0x9F95	0x6CC4	#CJK UNIFIED IDEOGRAPH
+0x9F96	0x6CF1	#CJK UNIFIED IDEOGRAPH
+0x9F97	0x6CD3	#CJK UNIFIED IDEOGRAPH
+0x9F98	0x6CBD	#CJK UNIFIED IDEOGRAPH
+0x9F99	0x6CD7	#CJK UNIFIED IDEOGRAPH
+0x9F9A	0x6CC5	#CJK UNIFIED IDEOGRAPH
+0x9F9B	0x6CDD	#CJK UNIFIED IDEOGRAPH
+0x9F9C	0x6CAE	#CJK UNIFIED IDEOGRAPH
+0x9F9D	0x6CB1	#CJK UNIFIED IDEOGRAPH
+0x9F9E	0x6CBE	#CJK UNIFIED IDEOGRAPH
+0x9F9F	0x6CBA	#CJK UNIFIED IDEOGRAPH
+0x9FA0	0x6CDB	#CJK UNIFIED IDEOGRAPH
+0x9FA1	0x6CEF	#CJK UNIFIED IDEOGRAPH
+0x9FA2	0x6CD9	#CJK UNIFIED IDEOGRAPH
+0x9FA3	0x6CEA	#CJK UNIFIED IDEOGRAPH
+0x9FA4	0x6D1F	#CJK UNIFIED IDEOGRAPH
+0x9FA5	0x884D	#CJK UNIFIED IDEOGRAPH
+0x9FA6	0x6D36	#CJK UNIFIED IDEOGRAPH
+0x9FA7	0x6D2B	#CJK UNIFIED IDEOGRAPH
+0x9FA8	0x6D3D	#CJK UNIFIED IDEOGRAPH
+0x9FA9	0x6D38	#CJK UNIFIED IDEOGRAPH
+0x9FAA	0x6D19	#CJK UNIFIED IDEOGRAPH
+0x9FAB	0x6D35	#CJK UNIFIED IDEOGRAPH
+0x9FAC	0x6D33	#CJK UNIFIED IDEOGRAPH
+0x9FAD	0x6D12	#CJK UNIFIED IDEOGRAPH
+0x9FAE	0x6D0C	#CJK UNIFIED IDEOGRAPH
+0x9FAF	0x6D63	#CJK UNIFIED IDEOGRAPH
+0x9FB0	0x6D93	#CJK UNIFIED IDEOGRAPH
+0x9FB1	0x6D64	#CJK UNIFIED IDEOGRAPH
+0x9FB2	0x6D5A	#CJK UNIFIED IDEOGRAPH
+0x9FB3	0x6D79	#CJK UNIFIED IDEOGRAPH
+0x9FB4	0x6D59	#CJK UNIFIED IDEOGRAPH
+0x9FB5	0x6D8E	#CJK UNIFIED IDEOGRAPH
+0x9FB6	0x6D95	#CJK UNIFIED IDEOGRAPH
+0x9FB7	0x6FE4	#CJK UNIFIED IDEOGRAPH
+0x9FB8	0x6D85	#CJK UNIFIED IDEOGRAPH
+0x9FB9	0x6DF9	#CJK UNIFIED IDEOGRAPH
+0x9FBA	0x6E15	#CJK UNIFIED IDEOGRAPH
+0x9FBB	0x6E0A	#CJK UNIFIED IDEOGRAPH
+0x9FBC	0x6DB5	#CJK UNIFIED IDEOGRAPH
+0x9FBD	0x6DC7	#CJK UNIFIED IDEOGRAPH
+0x9FBE	0x6DE6	#CJK UNIFIED IDEOGRAPH
+0x9FBF	0x6DB8	#CJK UNIFIED IDEOGRAPH
+0x9FC0	0x6DC6	#CJK UNIFIED IDEOGRAPH
+0x9FC1	0x6DEC	#CJK UNIFIED IDEOGRAPH
+0x9FC2	0x6DDE	#CJK UNIFIED IDEOGRAPH
+0x9FC3	0x6DCC	#CJK UNIFIED IDEOGRAPH
+0x9FC4	0x6DE8	#CJK UNIFIED IDEOGRAPH
+0x9FC5	0x6DD2	#CJK UNIFIED IDEOGRAPH
+0x9FC6	0x6DC5	#CJK UNIFIED IDEOGRAPH
+0x9FC7	0x6DFA	#CJK UNIFIED IDEOGRAPH
+0x9FC8	0x6DD9	#CJK UNIFIED IDEOGRAPH
+0x9FC9	0x6DE4	#CJK UNIFIED IDEOGRAPH
+0x9FCA	0x6DD5	#CJK UNIFIED IDEOGRAPH
+0x9FCB	0x6DEA	#CJK UNIFIED IDEOGRAPH
+0x9FCC	0x6DEE	#CJK UNIFIED IDEOGRAPH
+0x9FCD	0x6E2D	#CJK UNIFIED IDEOGRAPH
+0x9FCE	0x6E6E	#CJK UNIFIED IDEOGRAPH
+0x9FCF	0x6E2E	#CJK UNIFIED IDEOGRAPH
+0x9FD0	0x6E19	#CJK UNIFIED IDEOGRAPH
+0x9FD1	0x6E72	#CJK UNIFIED IDEOGRAPH
+0x9FD2	0x6E5F	#CJK UNIFIED IDEOGRAPH
+0x9FD3	0x6E3E	#CJK UNIFIED IDEOGRAPH
+0x9FD4	0x6E23	#CJK UNIFIED IDEOGRAPH
+0x9FD5	0x6E6B	#CJK UNIFIED IDEOGRAPH
+0x9FD6	0x6E2B	#CJK UNIFIED IDEOGRAPH
+0x9FD7	0x6E76	#CJK UNIFIED IDEOGRAPH
+0x9FD8	0x6E4D	#CJK UNIFIED IDEOGRAPH
+0x9FD9	0x6E1F	#CJK UNIFIED IDEOGRAPH
+0x9FDA	0x6E43	#CJK UNIFIED IDEOGRAPH
+0x9FDB	0x6E3A	#CJK UNIFIED IDEOGRAPH
+0x9FDC	0x6E4E	#CJK UNIFIED IDEOGRAPH
+0x9FDD	0x6E24	#CJK UNIFIED IDEOGRAPH
+0x9FDE	0x6EFF	#CJK UNIFIED IDEOGRAPH
+0x9FDF	0x6E1D	#CJK UNIFIED IDEOGRAPH
+0x9FE0	0x6E38	#CJK UNIFIED IDEOGRAPH
+0x9FE1	0x6E82	#CJK UNIFIED IDEOGRAPH
+0x9FE2	0x6EAA	#CJK UNIFIED IDEOGRAPH
+0x9FE3	0x6E98	#CJK UNIFIED IDEOGRAPH
+0x9FE4	0x6EC9	#CJK UNIFIED IDEOGRAPH
+0x9FE5	0x6EB7	#CJK UNIFIED IDEOGRAPH
+0x9FE6	0x6ED3	#CJK UNIFIED IDEOGRAPH
+0x9FE7	0x6EBD	#CJK UNIFIED IDEOGRAPH
+0x9FE8	0x6EAF	#CJK UNIFIED IDEOGRAPH
+0x9FE9	0x6EC4	#CJK UNIFIED IDEOGRAPH
+0x9FEA	0x6EB2	#CJK UNIFIED IDEOGRAPH
+0x9FEB	0x6ED4	#CJK UNIFIED IDEOGRAPH
+0x9FEC	0x6ED5	#CJK UNIFIED IDEOGRAPH
+0x9FED	0x6E8F	#CJK UNIFIED IDEOGRAPH
+0x9FEE	0x6EA5	#CJK UNIFIED IDEOGRAPH
+0x9FEF	0x6EC2	#CJK UNIFIED IDEOGRAPH
+0x9FF0	0x6E9F	#CJK UNIFIED IDEOGRAPH
+0x9FF1	0x6F41	#CJK UNIFIED IDEOGRAPH
+0x9FF2	0x6F11	#CJK UNIFIED IDEOGRAPH
+0x9FF3	0x704C	#CJK UNIFIED IDEOGRAPH
+0x9FF4	0x6EEC	#CJK UNIFIED IDEOGRAPH
+0x9FF5	0x6EF8	#CJK UNIFIED IDEOGRAPH
+0x9FF6	0x6EFE	#CJK UNIFIED IDEOGRAPH
+0x9FF7	0x6F3F	#CJK UNIFIED IDEOGRAPH
+0x9FF8	0x6EF2	#CJK UNIFIED IDEOGRAPH
+0x9FF9	0x6F31	#CJK UNIFIED IDEOGRAPH
+0x9FFA	0x6EEF	#CJK UNIFIED IDEOGRAPH
+0x9FFB	0x6F32	#CJK UNIFIED IDEOGRAPH
+0x9FFC	0x6ECC	#CJK UNIFIED IDEOGRAPH
+0xE040	0x6F3E	#CJK UNIFIED IDEOGRAPH
+0xE041	0x6F13	#CJK UNIFIED IDEOGRAPH
+0xE042	0x6EF7	#CJK UNIFIED IDEOGRAPH
+0xE043	0x6F86	#CJK UNIFIED IDEOGRAPH
+0xE044	0x6F7A	#CJK UNIFIED IDEOGRAPH
+0xE045	0x6F78	#CJK UNIFIED IDEOGRAPH
+0xE046	0x6F81	#CJK UNIFIED IDEOGRAPH
+0xE047	0x6F80	#CJK UNIFIED IDEOGRAPH
+0xE048	0x6F6F	#CJK UNIFIED IDEOGRAPH
+0xE049	0x6F5B	#CJK UNIFIED IDEOGRAPH
+0xE04A	0x6FF3	#CJK UNIFIED IDEOGRAPH
+0xE04B	0x6F6D	#CJK UNIFIED IDEOGRAPH
+0xE04C	0x6F82	#CJK UNIFIED IDEOGRAPH
+0xE04D	0x6F7C	#CJK UNIFIED IDEOGRAPH
+0xE04E	0x6F58	#CJK UNIFIED IDEOGRAPH
+0xE04F	0x6F8E	#CJK UNIFIED IDEOGRAPH
+0xE050	0x6F91	#CJK UNIFIED IDEOGRAPH
+0xE051	0x6FC2	#CJK UNIFIED IDEOGRAPH
+0xE052	0x6F66	#CJK UNIFIED IDEOGRAPH
+0xE053	0x6FB3	#CJK UNIFIED IDEOGRAPH
+0xE054	0x6FA3	#CJK UNIFIED IDEOGRAPH
+0xE055	0x6FA1	#CJK UNIFIED IDEOGRAPH
+0xE056	0x6FA4	#CJK UNIFIED IDEOGRAPH
+0xE057	0x6FB9	#CJK UNIFIED IDEOGRAPH
+0xE058	0x6FC6	#CJK UNIFIED IDEOGRAPH
+0xE059	0x6FAA	#CJK UNIFIED IDEOGRAPH
+0xE05A	0x6FDF	#CJK UNIFIED IDEOGRAPH
+0xE05B	0x6FD5	#CJK UNIFIED IDEOGRAPH
+0xE05C	0x6FEC	#CJK UNIFIED IDEOGRAPH
+0xE05D	0x6FD4	#CJK UNIFIED IDEOGRAPH
+0xE05E	0x6FD8	#CJK UNIFIED IDEOGRAPH
+0xE05F	0x6FF1	#CJK UNIFIED IDEOGRAPH
+0xE060	0x6FEE	#CJK UNIFIED IDEOGRAPH
+0xE061	0x6FDB	#CJK UNIFIED IDEOGRAPH
+0xE062	0x7009	#CJK UNIFIED IDEOGRAPH
+0xE063	0x700B	#CJK UNIFIED IDEOGRAPH
+0xE064	0x6FFA	#CJK UNIFIED IDEOGRAPH
+0xE065	0x7011	#CJK UNIFIED IDEOGRAPH
+0xE066	0x7001	#CJK UNIFIED IDEOGRAPH
+0xE067	0x700F	#CJK UNIFIED IDEOGRAPH
+0xE068	0x6FFE	#CJK UNIFIED IDEOGRAPH
+0xE069	0x701B	#CJK UNIFIED IDEOGRAPH
+0xE06A	0x701A	#CJK UNIFIED IDEOGRAPH
+0xE06B	0x6F74	#CJK UNIFIED IDEOGRAPH
+0xE06C	0x701D	#CJK UNIFIED IDEOGRAPH
+0xE06D	0x7018	#CJK UNIFIED IDEOGRAPH
+0xE06E	0x701F	#CJK UNIFIED IDEOGRAPH
+0xE06F	0x7030	#CJK UNIFIED IDEOGRAPH
+0xE070	0x703E	#CJK UNIFIED IDEOGRAPH
+0xE071	0x7032	#CJK UNIFIED IDEOGRAPH
+0xE072	0x7051	#CJK UNIFIED IDEOGRAPH
+0xE073	0x7063	#CJK UNIFIED IDEOGRAPH
+0xE074	0x7099	#CJK UNIFIED IDEOGRAPH
+0xE075	0x7092	#CJK UNIFIED IDEOGRAPH
+0xE076	0x70AF	#CJK UNIFIED IDEOGRAPH
+0xE077	0x70F1	#CJK UNIFIED IDEOGRAPH
+0xE078	0x70AC	#CJK UNIFIED IDEOGRAPH
+0xE079	0x70B8	#CJK UNIFIED IDEOGRAPH
+0xE07A	0x70B3	#CJK UNIFIED IDEOGRAPH
+0xE07B	0x70AE	#CJK UNIFIED IDEOGRAPH
+0xE07C	0x70DF	#CJK UNIFIED IDEOGRAPH
+0xE07D	0x70CB	#CJK UNIFIED IDEOGRAPH
+0xE07E	0x70DD	#CJK UNIFIED IDEOGRAPH
+0xE080	0x70D9	#CJK UNIFIED IDEOGRAPH
+0xE081	0x7109	#CJK UNIFIED IDEOGRAPH
+0xE082	0x70FD	#CJK UNIFIED IDEOGRAPH
+0xE083	0x711C	#CJK UNIFIED IDEOGRAPH
+0xE084	0x7119	#CJK UNIFIED IDEOGRAPH
+0xE085	0x7165	#CJK UNIFIED IDEOGRAPH
+0xE086	0x7155	#CJK UNIFIED IDEOGRAPH
+0xE087	0x7188	#CJK UNIFIED IDEOGRAPH
+0xE088	0x7166	#CJK UNIFIED IDEOGRAPH
+0xE089	0x7162	#CJK UNIFIED IDEOGRAPH
+0xE08A	0x714C	#CJK UNIFIED IDEOGRAPH
+0xE08B	0x7156	#CJK UNIFIED IDEOGRAPH
+0xE08C	0x716C	#CJK UNIFIED IDEOGRAPH
+0xE08D	0x718F	#CJK UNIFIED IDEOGRAPH
+0xE08E	0x71FB	#CJK UNIFIED IDEOGRAPH
+0xE08F	0x7184	#CJK UNIFIED IDEOGRAPH
+0xE090	0x7195	#CJK UNIFIED IDEOGRAPH
+0xE091	0x71A8	#CJK UNIFIED IDEOGRAPH
+0xE092	0x71AC	#CJK UNIFIED IDEOGRAPH
+0xE093	0x71D7	#CJK UNIFIED IDEOGRAPH
+0xE094	0x71B9	#CJK UNIFIED IDEOGRAPH
+0xE095	0x71BE	#CJK UNIFIED IDEOGRAPH
+0xE096	0x71D2	#CJK UNIFIED IDEOGRAPH
+0xE097	0x71C9	#CJK UNIFIED IDEOGRAPH
+0xE098	0x71D4	#CJK UNIFIED IDEOGRAPH
+0xE099	0x71CE	#CJK UNIFIED IDEOGRAPH
+0xE09A	0x71E0	#CJK UNIFIED IDEOGRAPH
+0xE09B	0x71EC	#CJK UNIFIED IDEOGRAPH
+0xE09C	0x71E7	#CJK UNIFIED IDEOGRAPH
+0xE09D	0x71F5	#CJK UNIFIED IDEOGRAPH
+0xE09E	0x71FC	#CJK UNIFIED IDEOGRAPH
+0xE09F	0x71F9	#CJK UNIFIED IDEOGRAPH
+0xE0A0	0x71FF	#CJK UNIFIED IDEOGRAPH
+0xE0A1	0x720D	#CJK UNIFIED IDEOGRAPH
+0xE0A2	0x7210	#CJK UNIFIED IDEOGRAPH
+0xE0A3	0x721B	#CJK UNIFIED IDEOGRAPH
+0xE0A4	0x7228	#CJK UNIFIED IDEOGRAPH
+0xE0A5	0x722D	#CJK UNIFIED IDEOGRAPH
+0xE0A6	0x722C	#CJK UNIFIED IDEOGRAPH
+0xE0A7	0x7230	#CJK UNIFIED IDEOGRAPH
+0xE0A8	0x7232	#CJK UNIFIED IDEOGRAPH
+0xE0A9	0x723B	#CJK UNIFIED IDEOGRAPH
+0xE0AA	0x723C	#CJK UNIFIED IDEOGRAPH
+0xE0AB	0x723F	#CJK UNIFIED IDEOGRAPH
+0xE0AC	0x7240	#CJK UNIFIED IDEOGRAPH
+0xE0AD	0x7246	#CJK UNIFIED IDEOGRAPH
+0xE0AE	0x724B	#CJK UNIFIED IDEOGRAPH
+0xE0AF	0x7258	#CJK UNIFIED IDEOGRAPH
+0xE0B0	0x7274	#CJK UNIFIED IDEOGRAPH
+0xE0B1	0x727E	#CJK UNIFIED IDEOGRAPH
+0xE0B2	0x7282	#CJK UNIFIED IDEOGRAPH
+0xE0B3	0x7281	#CJK UNIFIED IDEOGRAPH
+0xE0B4	0x7287	#CJK UNIFIED IDEOGRAPH
+0xE0B5	0x7292	#CJK UNIFIED IDEOGRAPH
+0xE0B6	0x7296	#CJK UNIFIED IDEOGRAPH
+0xE0B7	0x72A2	#CJK UNIFIED IDEOGRAPH
+0xE0B8	0x72A7	#CJK UNIFIED IDEOGRAPH
+0xE0B9	0x72B9	#CJK UNIFIED IDEOGRAPH
+0xE0BA	0x72B2	#CJK UNIFIED IDEOGRAPH
+0xE0BB	0x72C3	#CJK UNIFIED IDEOGRAPH
+0xE0BC	0x72C6	#CJK UNIFIED IDEOGRAPH
+0xE0BD	0x72C4	#CJK UNIFIED IDEOGRAPH
+0xE0BE	0x72CE	#CJK UNIFIED IDEOGRAPH
+0xE0BF	0x72D2	#CJK UNIFIED IDEOGRAPH
+0xE0C0	0x72E2	#CJK UNIFIED IDEOGRAPH
+0xE0C1	0x72E0	#CJK UNIFIED IDEOGRAPH
+0xE0C2	0x72E1	#CJK UNIFIED IDEOGRAPH
+0xE0C3	0x72F9	#CJK UNIFIED IDEOGRAPH
+0xE0C4	0x72F7	#CJK UNIFIED IDEOGRAPH
+0xE0C5	0x500F	#CJK UNIFIED IDEOGRAPH
+0xE0C6	0x7317	#CJK UNIFIED IDEOGRAPH
+0xE0C7	0x730A	#CJK UNIFIED IDEOGRAPH
+0xE0C8	0x731C	#CJK UNIFIED IDEOGRAPH
+0xE0C9	0x7316	#CJK UNIFIED IDEOGRAPH
+0xE0CA	0x731D	#CJK UNIFIED IDEOGRAPH
+0xE0CB	0x7334	#CJK UNIFIED IDEOGRAPH
+0xE0CC	0x732F	#CJK UNIFIED IDEOGRAPH
+0xE0CD	0x7329	#CJK UNIFIED IDEOGRAPH
+0xE0CE	0x7325	#CJK UNIFIED IDEOGRAPH
+0xE0CF	0x733E	#CJK UNIFIED IDEOGRAPH
+0xE0D0	0x734E	#CJK UNIFIED IDEOGRAPH
+0xE0D1	0x734F	#CJK UNIFIED IDEOGRAPH
+0xE0D2	0x9ED8	#CJK UNIFIED IDEOGRAPH
+0xE0D3	0x7357	#CJK UNIFIED IDEOGRAPH
+0xE0D4	0x736A	#CJK UNIFIED IDEOGRAPH
+0xE0D5	0x7368	#CJK UNIFIED IDEOGRAPH
+0xE0D6	0x7370	#CJK UNIFIED IDEOGRAPH
+0xE0D7	0x7378	#CJK UNIFIED IDEOGRAPH
+0xE0D8	0x7375	#CJK UNIFIED IDEOGRAPH
+0xE0D9	0x737B	#CJK UNIFIED IDEOGRAPH
+0xE0DA	0x737A	#CJK UNIFIED IDEOGRAPH
+0xE0DB	0x73C8	#CJK UNIFIED IDEOGRAPH
+0xE0DC	0x73B3	#CJK UNIFIED IDEOGRAPH
+0xE0DD	0x73CE	#CJK UNIFIED IDEOGRAPH
+0xE0DE	0x73BB	#CJK UNIFIED IDEOGRAPH
+0xE0DF	0x73C0	#CJK UNIFIED IDEOGRAPH
+0xE0E0	0x73E5	#CJK UNIFIED IDEOGRAPH
+0xE0E1	0x73EE	#CJK UNIFIED IDEOGRAPH
+0xE0E2	0x73DE	#CJK UNIFIED IDEOGRAPH
+0xE0E3	0x74A2	#CJK UNIFIED IDEOGRAPH
+0xE0E4	0x7405	#CJK UNIFIED IDEOGRAPH
+0xE0E5	0x746F	#CJK UNIFIED IDEOGRAPH
+0xE0E6	0x7425	#CJK UNIFIED IDEOGRAPH
+0xE0E7	0x73F8	#CJK UNIFIED IDEOGRAPH
+0xE0E8	0x7432	#CJK UNIFIED IDEOGRAPH
+0xE0E9	0x743A	#CJK UNIFIED IDEOGRAPH
+0xE0EA	0x7455	#CJK UNIFIED IDEOGRAPH
+0xE0EB	0x743F	#CJK UNIFIED IDEOGRAPH
+0xE0EC	0x745F	#CJK UNIFIED IDEOGRAPH
+0xE0ED	0x7459	#CJK UNIFIED IDEOGRAPH
+0xE0EE	0x7441	#CJK UNIFIED IDEOGRAPH
+0xE0EF	0x745C	#CJK UNIFIED IDEOGRAPH
+0xE0F0	0x7469	#CJK UNIFIED IDEOGRAPH
+0xE0F1	0x7470	#CJK UNIFIED IDEOGRAPH
+0xE0F2	0x7463	#CJK UNIFIED IDEOGRAPH
+0xE0F3	0x746A	#CJK UNIFIED IDEOGRAPH
+0xE0F4	0x7476	#CJK UNIFIED IDEOGRAPH
+0xE0F5	0x747E	#CJK UNIFIED IDEOGRAPH
+0xE0F6	0x748B	#CJK UNIFIED IDEOGRAPH
+0xE0F7	0x749E	#CJK UNIFIED IDEOGRAPH
+0xE0F8	0x74A7	#CJK UNIFIED IDEOGRAPH
+0xE0F9	0x74CA	#CJK UNIFIED IDEOGRAPH
+0xE0FA	0x74CF	#CJK UNIFIED IDEOGRAPH
+0xE0FB	0x74D4	#CJK UNIFIED IDEOGRAPH
+0xE0FC	0x73F1	#CJK UNIFIED IDEOGRAPH
+0xE140	0x74E0	#CJK UNIFIED IDEOGRAPH
+0xE141	0x74E3	#CJK UNIFIED IDEOGRAPH
+0xE142	0x74E7	#CJK UNIFIED IDEOGRAPH
+0xE143	0x74E9	#CJK UNIFIED IDEOGRAPH
+0xE144	0x74EE	#CJK UNIFIED IDEOGRAPH
+0xE145	0x74F2	#CJK UNIFIED IDEOGRAPH
+0xE146	0x74F0	#CJK UNIFIED IDEOGRAPH
+0xE147	0x74F1	#CJK UNIFIED IDEOGRAPH
+0xE148	0x74F8	#CJK UNIFIED IDEOGRAPH
+0xE149	0x74F7	#CJK UNIFIED IDEOGRAPH
+0xE14A	0x7504	#CJK UNIFIED IDEOGRAPH
+0xE14B	0x7503	#CJK UNIFIED IDEOGRAPH
+0xE14C	0x7505	#CJK UNIFIED IDEOGRAPH
+0xE14D	0x750C	#CJK UNIFIED IDEOGRAPH
+0xE14E	0x750E	#CJK UNIFIED IDEOGRAPH
+0xE14F	0x750D	#CJK UNIFIED IDEOGRAPH
+0xE150	0x7515	#CJK UNIFIED IDEOGRAPH
+0xE151	0x7513	#CJK UNIFIED IDEOGRAPH
+0xE152	0x751E	#CJK UNIFIED IDEOGRAPH
+0xE153	0x7526	#CJK UNIFIED IDEOGRAPH
+0xE154	0x752C	#CJK UNIFIED IDEOGRAPH
+0xE155	0x753C	#CJK UNIFIED IDEOGRAPH
+0xE156	0x7544	#CJK UNIFIED IDEOGRAPH
+0xE157	0x754D	#CJK UNIFIED IDEOGRAPH
+0xE158	0x754A	#CJK UNIFIED IDEOGRAPH
+0xE159	0x7549	#CJK UNIFIED IDEOGRAPH
+0xE15A	0x755B	#CJK UNIFIED IDEOGRAPH
+0xE15B	0x7546	#CJK UNIFIED IDEOGRAPH
+0xE15C	0x755A	#CJK UNIFIED IDEOGRAPH
+0xE15D	0x7569	#CJK UNIFIED IDEOGRAPH
+0xE15E	0x7564	#CJK UNIFIED IDEOGRAPH
+0xE15F	0x7567	#CJK UNIFIED IDEOGRAPH
+0xE160	0x756B	#CJK UNIFIED IDEOGRAPH
+0xE161	0x756D	#CJK UNIFIED IDEOGRAPH
+0xE162	0x7578	#CJK UNIFIED IDEOGRAPH
+0xE163	0x7576	#CJK UNIFIED IDEOGRAPH
+0xE164	0x7586	#CJK UNIFIED IDEOGRAPH
+0xE165	0x7587	#CJK UNIFIED IDEOGRAPH
+0xE166	0x7574	#CJK UNIFIED IDEOGRAPH
+0xE167	0x758A	#CJK UNIFIED IDEOGRAPH
+0xE168	0x7589	#CJK UNIFIED IDEOGRAPH
+0xE169	0x7582	#CJK UNIFIED IDEOGRAPH
+0xE16A	0x7594	#CJK UNIFIED IDEOGRAPH
+0xE16B	0x759A	#CJK UNIFIED IDEOGRAPH
+0xE16C	0x759D	#CJK UNIFIED IDEOGRAPH
+0xE16D	0x75A5	#CJK UNIFIED IDEOGRAPH
+0xE16E	0x75A3	#CJK UNIFIED IDEOGRAPH
+0xE16F	0x75C2	#CJK UNIFIED IDEOGRAPH
+0xE170	0x75B3	#CJK UNIFIED IDEOGRAPH
+0xE171	0x75C3	#CJK UNIFIED IDEOGRAPH
+0xE172	0x75B5	#CJK UNIFIED IDEOGRAPH
+0xE173	0x75BD	#CJK UNIFIED IDEOGRAPH
+0xE174	0x75B8	#CJK UNIFIED IDEOGRAPH
+0xE175	0x75BC	#CJK UNIFIED IDEOGRAPH
+0xE176	0x75B1	#CJK UNIFIED IDEOGRAPH
+0xE177	0x75CD	#CJK UNIFIED IDEOGRAPH
+0xE178	0x75CA	#CJK UNIFIED IDEOGRAPH
+0xE179	0x75D2	#CJK UNIFIED IDEOGRAPH
+0xE17A	0x75D9	#CJK UNIFIED IDEOGRAPH
+0xE17B	0x75E3	#CJK UNIFIED IDEOGRAPH
+0xE17C	0x75DE	#CJK UNIFIED IDEOGRAPH
+0xE17D	0x75FE	#CJK UNIFIED IDEOGRAPH
+0xE17E	0x75FF	#CJK UNIFIED IDEOGRAPH
+0xE180	0x75FC	#CJK UNIFIED IDEOGRAPH
+0xE181	0x7601	#CJK UNIFIED IDEOGRAPH
+0xE182	0x75F0	#CJK UNIFIED IDEOGRAPH
+0xE183	0x75FA	#CJK UNIFIED IDEOGRAPH
+0xE184	0x75F2	#CJK UNIFIED IDEOGRAPH
+0xE185	0x75F3	#CJK UNIFIED IDEOGRAPH
+0xE186	0x760B	#CJK UNIFIED IDEOGRAPH
+0xE187	0x760D	#CJK UNIFIED IDEOGRAPH
+0xE188	0x7609	#CJK UNIFIED IDEOGRAPH
+0xE189	0x761F	#CJK UNIFIED IDEOGRAPH
+0xE18A	0x7627	#CJK UNIFIED IDEOGRAPH
+0xE18B	0x7620	#CJK UNIFIED IDEOGRAPH
+0xE18C	0x7621	#CJK UNIFIED IDEOGRAPH
+0xE18D	0x7622	#CJK UNIFIED IDEOGRAPH
+0xE18E	0x7624	#CJK UNIFIED IDEOGRAPH
+0xE18F	0x7634	#CJK UNIFIED IDEOGRAPH
+0xE190	0x7630	#CJK UNIFIED IDEOGRAPH
+0xE191	0x763B	#CJK UNIFIED IDEOGRAPH
+0xE192	0x7647	#CJK UNIFIED IDEOGRAPH
+0xE193	0x7648	#CJK UNIFIED IDEOGRAPH
+0xE194	0x7646	#CJK UNIFIED IDEOGRAPH
+0xE195	0x765C	#CJK UNIFIED IDEOGRAPH
+0xE196	0x7658	#CJK UNIFIED IDEOGRAPH
+0xE197	0x7661	#CJK UNIFIED IDEOGRAPH
+0xE198	0x7662	#CJK UNIFIED IDEOGRAPH
+0xE199	0x7668	#CJK UNIFIED IDEOGRAPH
+0xE19A	0x7669	#CJK UNIFIED IDEOGRAPH
+0xE19B	0x766A	#CJK UNIFIED IDEOGRAPH
+0xE19C	0x7667	#CJK UNIFIED IDEOGRAPH
+0xE19D	0x766C	#CJK UNIFIED IDEOGRAPH
+0xE19E	0x7670	#CJK UNIFIED IDEOGRAPH
+0xE19F	0x7672	#CJK UNIFIED IDEOGRAPH
+0xE1A0	0x7676	#CJK UNIFIED IDEOGRAPH
+0xE1A1	0x7678	#CJK UNIFIED IDEOGRAPH
+0xE1A2	0x767C	#CJK UNIFIED IDEOGRAPH
+0xE1A3	0x7680	#CJK UNIFIED IDEOGRAPH
+0xE1A4	0x7683	#CJK UNIFIED IDEOGRAPH
+0xE1A5	0x7688	#CJK UNIFIED IDEOGRAPH
+0xE1A6	0x768B	#CJK UNIFIED IDEOGRAPH
+0xE1A7	0x768E	#CJK UNIFIED IDEOGRAPH
+0xE1A8	0x7696	#CJK UNIFIED IDEOGRAPH
+0xE1A9	0x7693	#CJK UNIFIED IDEOGRAPH
+0xE1AA	0x7699	#CJK UNIFIED IDEOGRAPH
+0xE1AB	0x769A	#CJK UNIFIED IDEOGRAPH
+0xE1AC	0x76B0	#CJK UNIFIED IDEOGRAPH
+0xE1AD	0x76B4	#CJK UNIFIED IDEOGRAPH
+0xE1AE	0x76B8	#CJK UNIFIED IDEOGRAPH
+0xE1AF	0x76B9	#CJK UNIFIED IDEOGRAPH
+0xE1B0	0x76BA	#CJK UNIFIED IDEOGRAPH
+0xE1B1	0x76C2	#CJK UNIFIED IDEOGRAPH
+0xE1B2	0x76CD	#CJK UNIFIED IDEOGRAPH
+0xE1B3	0x76D6	#CJK UNIFIED IDEOGRAPH
+0xE1B4	0x76D2	#CJK UNIFIED IDEOGRAPH
+0xE1B5	0x76DE	#CJK UNIFIED IDEOGRAPH
+0xE1B6	0x76E1	#CJK UNIFIED IDEOGRAPH
+0xE1B7	0x76E5	#CJK UNIFIED IDEOGRAPH
+0xE1B8	0x76E7	#CJK UNIFIED IDEOGRAPH
+0xE1B9	0x76EA	#CJK UNIFIED IDEOGRAPH
+0xE1BA	0x862F	#CJK UNIFIED IDEOGRAPH
+0xE1BB	0x76FB	#CJK UNIFIED IDEOGRAPH
+0xE1BC	0x7708	#CJK UNIFIED IDEOGRAPH
+0xE1BD	0x7707	#CJK UNIFIED IDEOGRAPH
+0xE1BE	0x7704	#CJK UNIFIED IDEOGRAPH
+0xE1BF	0x7729	#CJK UNIFIED IDEOGRAPH
+0xE1C0	0x7724	#CJK UNIFIED IDEOGRAPH
+0xE1C1	0x771E	#CJK UNIFIED IDEOGRAPH
+0xE1C2	0x7725	#CJK UNIFIED IDEOGRAPH
+0xE1C3	0x7726	#CJK UNIFIED IDEOGRAPH
+0xE1C4	0x771B	#CJK UNIFIED IDEOGRAPH
+0xE1C5	0x7737	#CJK UNIFIED IDEOGRAPH
+0xE1C6	0x7738	#CJK UNIFIED IDEOGRAPH
+0xE1C7	0x7747	#CJK UNIFIED IDEOGRAPH
+0xE1C8	0x775A	#CJK UNIFIED IDEOGRAPH
+0xE1C9	0x7768	#CJK UNIFIED IDEOGRAPH
+0xE1CA	0x776B	#CJK UNIFIED IDEOGRAPH
+0xE1CB	0x775B	#CJK UNIFIED IDEOGRAPH
+0xE1CC	0x7765	#CJK UNIFIED IDEOGRAPH
+0xE1CD	0x777F	#CJK UNIFIED IDEOGRAPH
+0xE1CE	0x777E	#CJK UNIFIED IDEOGRAPH
+0xE1CF	0x7779	#CJK UNIFIED IDEOGRAPH
+0xE1D0	0x778E	#CJK UNIFIED IDEOGRAPH
+0xE1D1	0x778B	#CJK UNIFIED IDEOGRAPH
+0xE1D2	0x7791	#CJK UNIFIED IDEOGRAPH
+0xE1D3	0x77A0	#CJK UNIFIED IDEOGRAPH
+0xE1D4	0x779E	#CJK UNIFIED IDEOGRAPH
+0xE1D5	0x77B0	#CJK UNIFIED IDEOGRAPH
+0xE1D6	0x77B6	#CJK UNIFIED IDEOGRAPH
+0xE1D7	0x77B9	#CJK UNIFIED IDEOGRAPH
+0xE1D8	0x77BF	#CJK UNIFIED IDEOGRAPH
+0xE1D9	0x77BC	#CJK UNIFIED IDEOGRAPH
+0xE1DA	0x77BD	#CJK UNIFIED IDEOGRAPH
+0xE1DB	0x77BB	#CJK UNIFIED IDEOGRAPH
+0xE1DC	0x77C7	#CJK UNIFIED IDEOGRAPH
+0xE1DD	0x77CD	#CJK UNIFIED IDEOGRAPH
+0xE1DE	0x77D7	#CJK UNIFIED IDEOGRAPH
+0xE1DF	0x77DA	#CJK UNIFIED IDEOGRAPH
+0xE1E0	0x77DC	#CJK UNIFIED IDEOGRAPH
+0xE1E1	0x77E3	#CJK UNIFIED IDEOGRAPH
+0xE1E2	0x77EE	#CJK UNIFIED IDEOGRAPH
+0xE1E3	0x77FC	#CJK UNIFIED IDEOGRAPH
+0xE1E4	0x780C	#CJK UNIFIED IDEOGRAPH
+0xE1E5	0x7812	#CJK UNIFIED IDEOGRAPH
+0xE1E6	0x7926	#CJK UNIFIED IDEOGRAPH
+0xE1E7	0x7820	#CJK UNIFIED IDEOGRAPH
+0xE1E8	0x792A	#CJK UNIFIED IDEOGRAPH
+0xE1E9	0x7845	#CJK UNIFIED IDEOGRAPH
+0xE1EA	0x788E	#CJK UNIFIED IDEOGRAPH
+0xE1EB	0x7874	#CJK UNIFIED IDEOGRAPH
+0xE1EC	0x7886	#CJK UNIFIED IDEOGRAPH
+0xE1ED	0x787C	#CJK UNIFIED IDEOGRAPH
+0xE1EE	0x789A	#CJK UNIFIED IDEOGRAPH
+0xE1EF	0x788C	#CJK UNIFIED IDEOGRAPH
+0xE1F0	0x78A3	#CJK UNIFIED IDEOGRAPH
+0xE1F1	0x78B5	#CJK UNIFIED IDEOGRAPH
+0xE1F2	0x78AA	#CJK UNIFIED IDEOGRAPH
+0xE1F3	0x78AF	#CJK UNIFIED IDEOGRAPH
+0xE1F4	0x78D1	#CJK UNIFIED IDEOGRAPH
+0xE1F5	0x78C6	#CJK UNIFIED IDEOGRAPH
+0xE1F6	0x78CB	#CJK UNIFIED IDEOGRAPH
+0xE1F7	0x78D4	#CJK UNIFIED IDEOGRAPH
+0xE1F8	0x78BE	#CJK UNIFIED IDEOGRAPH
+0xE1F9	0x78BC	#CJK UNIFIED IDEOGRAPH
+0xE1FA	0x78C5	#CJK UNIFIED IDEOGRAPH
+0xE1FB	0x78CA	#CJK UNIFIED IDEOGRAPH
+0xE1FC	0x78EC	#CJK UNIFIED IDEOGRAPH
+0xE240	0x78E7	#CJK UNIFIED IDEOGRAPH
+0xE241	0x78DA	#CJK UNIFIED IDEOGRAPH
+0xE242	0x78FD	#CJK UNIFIED IDEOGRAPH
+0xE243	0x78F4	#CJK UNIFIED IDEOGRAPH
+0xE244	0x7907	#CJK UNIFIED IDEOGRAPH
+0xE245	0x7912	#CJK UNIFIED IDEOGRAPH
+0xE246	0x7911	#CJK UNIFIED IDEOGRAPH
+0xE247	0x7919	#CJK UNIFIED IDEOGRAPH
+0xE248	0x792C	#CJK UNIFIED IDEOGRAPH
+0xE249	0x792B	#CJK UNIFIED IDEOGRAPH
+0xE24A	0x7940	#CJK UNIFIED IDEOGRAPH
+0xE24B	0x7960	#CJK UNIFIED IDEOGRAPH
+0xE24C	0x7957	#CJK UNIFIED IDEOGRAPH
+0xE24D	0x795F	#CJK UNIFIED IDEOGRAPH
+0xE24E	0x795A	#CJK UNIFIED IDEOGRAPH
+0xE24F	0x7955	#CJK UNIFIED IDEOGRAPH
+0xE250	0x7953	#CJK UNIFIED IDEOGRAPH
+0xE251	0x797A	#CJK UNIFIED IDEOGRAPH
+0xE252	0x797F	#CJK UNIFIED IDEOGRAPH
+0xE253	0x798A	#CJK UNIFIED IDEOGRAPH
+0xE254	0x799D	#CJK UNIFIED IDEOGRAPH
+0xE255	0x79A7	#CJK UNIFIED IDEOGRAPH
+0xE256	0x9F4B	#CJK UNIFIED IDEOGRAPH
+0xE257	0x79AA	#CJK UNIFIED IDEOGRAPH
+0xE258	0x79AE	#CJK UNIFIED IDEOGRAPH
+0xE259	0x79B3	#CJK UNIFIED IDEOGRAPH
+0xE25A	0x79B9	#CJK UNIFIED IDEOGRAPH
+0xE25B	0x79BA	#CJK UNIFIED IDEOGRAPH
+0xE25C	0x79C9	#CJK UNIFIED IDEOGRAPH
+0xE25D	0x79D5	#CJK UNIFIED IDEOGRAPH
+0xE25E	0x79E7	#CJK UNIFIED IDEOGRAPH
+0xE25F	0x79EC	#CJK UNIFIED IDEOGRAPH
+0xE260	0x79E1	#CJK UNIFIED IDEOGRAPH
+0xE261	0x79E3	#CJK UNIFIED IDEOGRAPH
+0xE262	0x7A08	#CJK UNIFIED IDEOGRAPH
+0xE263	0x7A0D	#CJK UNIFIED IDEOGRAPH
+0xE264	0x7A18	#CJK UNIFIED IDEOGRAPH
+0xE265	0x7A19	#CJK UNIFIED IDEOGRAPH
+0xE266	0x7A20	#CJK UNIFIED IDEOGRAPH
+0xE267	0x7A1F	#CJK UNIFIED IDEOGRAPH
+0xE268	0x7980	#CJK UNIFIED IDEOGRAPH
+0xE269	0x7A31	#CJK UNIFIED IDEOGRAPH
+0xE26A	0x7A3B	#CJK UNIFIED IDEOGRAPH
+0xE26B	0x7A3E	#CJK UNIFIED IDEOGRAPH
+0xE26C	0x7A37	#CJK UNIFIED IDEOGRAPH
+0xE26D	0x7A43	#CJK UNIFIED IDEOGRAPH
+0xE26E	0x7A57	#CJK UNIFIED IDEOGRAPH
+0xE26F	0x7A49	#CJK UNIFIED IDEOGRAPH
+0xE270	0x7A61	#CJK UNIFIED IDEOGRAPH
+0xE271	0x7A62	#CJK UNIFIED IDEOGRAPH
+0xE272	0x7A69	#CJK UNIFIED IDEOGRAPH
+0xE273	0x9F9D	#CJK UNIFIED IDEOGRAPH
+0xE274	0x7A70	#CJK UNIFIED IDEOGRAPH
+0xE275	0x7A79	#CJK UNIFIED IDEOGRAPH
+0xE276	0x7A7D	#CJK UNIFIED IDEOGRAPH
+0xE277	0x7A88	#CJK UNIFIED IDEOGRAPH
+0xE278	0x7A97	#CJK UNIFIED IDEOGRAPH
+0xE279	0x7A95	#CJK UNIFIED IDEOGRAPH
+0xE27A	0x7A98	#CJK UNIFIED IDEOGRAPH
+0xE27B	0x7A96	#CJK UNIFIED IDEOGRAPH
+0xE27C	0x7AA9	#CJK UNIFIED IDEOGRAPH
+0xE27D	0x7AC8	#CJK UNIFIED IDEOGRAPH
+0xE27E	0x7AB0	#CJK UNIFIED IDEOGRAPH
+0xE280	0x7AB6	#CJK UNIFIED IDEOGRAPH
+0xE281	0x7AC5	#CJK UNIFIED IDEOGRAPH
+0xE282	0x7AC4	#CJK UNIFIED IDEOGRAPH
+0xE283	0x7ABF	#CJK UNIFIED IDEOGRAPH
+0xE284	0x9083	#CJK UNIFIED IDEOGRAPH
+0xE285	0x7AC7	#CJK UNIFIED IDEOGRAPH
+0xE286	0x7ACA	#CJK UNIFIED IDEOGRAPH
+0xE287	0x7ACD	#CJK UNIFIED IDEOGRAPH
+0xE288	0x7ACF	#CJK UNIFIED IDEOGRAPH
+0xE289	0x7AD5	#CJK UNIFIED IDEOGRAPH
+0xE28A	0x7AD3	#CJK UNIFIED IDEOGRAPH
+0xE28B	0x7AD9	#CJK UNIFIED IDEOGRAPH
+0xE28C	0x7ADA	#CJK UNIFIED IDEOGRAPH
+0xE28D	0x7ADD	#CJK UNIFIED IDEOGRAPH
+0xE28E	0x7AE1	#CJK UNIFIED IDEOGRAPH
+0xE28F	0x7AE2	#CJK UNIFIED IDEOGRAPH
+0xE290	0x7AE6	#CJK UNIFIED IDEOGRAPH
+0xE291	0x7AED	#CJK UNIFIED IDEOGRAPH
+0xE292	0x7AF0	#CJK UNIFIED IDEOGRAPH
+0xE293	0x7B02	#CJK UNIFIED IDEOGRAPH
+0xE294	0x7B0F	#CJK UNIFIED IDEOGRAPH
+0xE295	0x7B0A	#CJK UNIFIED IDEOGRAPH
+0xE296	0x7B06	#CJK UNIFIED IDEOGRAPH
+0xE297	0x7B33	#CJK UNIFIED IDEOGRAPH
+0xE298	0x7B18	#CJK UNIFIED IDEOGRAPH
+0xE299	0x7B19	#CJK UNIFIED IDEOGRAPH
+0xE29A	0x7B1E	#CJK UNIFIED IDEOGRAPH
+0xE29B	0x7B35	#CJK UNIFIED IDEOGRAPH
+0xE29C	0x7B28	#CJK UNIFIED IDEOGRAPH
+0xE29D	0x7B36	#CJK UNIFIED IDEOGRAPH
+0xE29E	0x7B50	#CJK UNIFIED IDEOGRAPH
+0xE29F	0x7B7A	#CJK UNIFIED IDEOGRAPH
+0xE2A0	0x7B04	#CJK UNIFIED IDEOGRAPH
+0xE2A1	0x7B4D	#CJK UNIFIED IDEOGRAPH
+0xE2A2	0x7B0B	#CJK UNIFIED IDEOGRAPH
+0xE2A3	0x7B4C	#CJK UNIFIED IDEOGRAPH
+0xE2A4	0x7B45	#CJK UNIFIED IDEOGRAPH
+0xE2A5	0x7B75	#CJK UNIFIED IDEOGRAPH
+0xE2A6	0x7B65	#CJK UNIFIED IDEOGRAPH
+0xE2A7	0x7B74	#CJK UNIFIED IDEOGRAPH
+0xE2A8	0x7B67	#CJK UNIFIED IDEOGRAPH
+0xE2A9	0x7B70	#CJK UNIFIED IDEOGRAPH
+0xE2AA	0x7B71	#CJK UNIFIED IDEOGRAPH
+0xE2AB	0x7B6C	#CJK UNIFIED IDEOGRAPH
+0xE2AC	0x7B6E	#CJK UNIFIED IDEOGRAPH
+0xE2AD	0x7B9D	#CJK UNIFIED IDEOGRAPH
+0xE2AE	0x7B98	#CJK UNIFIED IDEOGRAPH
+0xE2AF	0x7B9F	#CJK UNIFIED IDEOGRAPH
+0xE2B0	0x7B8D	#CJK UNIFIED IDEOGRAPH
+0xE2B1	0x7B9C	#CJK UNIFIED IDEOGRAPH
+0xE2B2	0x7B9A	#CJK UNIFIED IDEOGRAPH
+0xE2B3	0x7B8B	#CJK UNIFIED IDEOGRAPH
+0xE2B4	0x7B92	#CJK UNIFIED IDEOGRAPH
+0xE2B5	0x7B8F	#CJK UNIFIED IDEOGRAPH
+0xE2B6	0x7B5D	#CJK UNIFIED IDEOGRAPH
+0xE2B7	0x7B99	#CJK UNIFIED IDEOGRAPH
+0xE2B8	0x7BCB	#CJK UNIFIED IDEOGRAPH
+0xE2B9	0x7BC1	#CJK UNIFIED IDEOGRAPH
+0xE2BA	0x7BCC	#CJK UNIFIED IDEOGRAPH
+0xE2BB	0x7BCF	#CJK UNIFIED IDEOGRAPH
+0xE2BC	0x7BB4	#CJK UNIFIED IDEOGRAPH
+0xE2BD	0x7BC6	#CJK UNIFIED IDEOGRAPH
+0xE2BE	0x7BDD	#CJK UNIFIED IDEOGRAPH
+0xE2BF	0x7BE9	#CJK UNIFIED IDEOGRAPH
+0xE2C0	0x7C11	#CJK UNIFIED IDEOGRAPH
+0xE2C1	0x7C14	#CJK UNIFIED IDEOGRAPH
+0xE2C2	0x7BE6	#CJK UNIFIED IDEOGRAPH
+0xE2C3	0x7BE5	#CJK UNIFIED IDEOGRAPH
+0xE2C4	0x7C60	#CJK UNIFIED IDEOGRAPH
+0xE2C5	0x7C00	#CJK UNIFIED IDEOGRAPH
+0xE2C6	0x7C07	#CJK UNIFIED IDEOGRAPH
+0xE2C7	0x7C13	#CJK UNIFIED IDEOGRAPH
+0xE2C8	0x7BF3	#CJK UNIFIED IDEOGRAPH
+0xE2C9	0x7BF7	#CJK UNIFIED IDEOGRAPH
+0xE2CA	0x7C17	#CJK UNIFIED IDEOGRAPH
+0xE2CB	0x7C0D	#CJK UNIFIED IDEOGRAPH
+0xE2CC	0x7BF6	#CJK UNIFIED IDEOGRAPH
+0xE2CD	0x7C23	#CJK UNIFIED IDEOGRAPH
+0xE2CE	0x7C27	#CJK UNIFIED IDEOGRAPH
+0xE2CF	0x7C2A	#CJK UNIFIED IDEOGRAPH
+0xE2D0	0x7C1F	#CJK UNIFIED IDEOGRAPH
+0xE2D1	0x7C37	#CJK UNIFIED IDEOGRAPH
+0xE2D2	0x7C2B	#CJK UNIFIED IDEOGRAPH
+0xE2D3	0x7C3D	#CJK UNIFIED IDEOGRAPH
+0xE2D4	0x7C4C	#CJK UNIFIED IDEOGRAPH
+0xE2D5	0x7C43	#CJK UNIFIED IDEOGRAPH
+0xE2D6	0x7C54	#CJK UNIFIED IDEOGRAPH
+0xE2D7	0x7C4F	#CJK UNIFIED IDEOGRAPH
+0xE2D8	0x7C40	#CJK UNIFIED IDEOGRAPH
+0xE2D9	0x7C50	#CJK UNIFIED IDEOGRAPH
+0xE2DA	0x7C58	#CJK UNIFIED IDEOGRAPH
+0xE2DB	0x7C5F	#CJK UNIFIED IDEOGRAPH
+0xE2DC	0x7C64	#CJK UNIFIED IDEOGRAPH
+0xE2DD	0x7C56	#CJK UNIFIED IDEOGRAPH
+0xE2DE	0x7C65	#CJK UNIFIED IDEOGRAPH
+0xE2DF	0x7C6C	#CJK UNIFIED IDEOGRAPH
+0xE2E0	0x7C75	#CJK UNIFIED IDEOGRAPH
+0xE2E1	0x7C83	#CJK UNIFIED IDEOGRAPH
+0xE2E2	0x7C90	#CJK UNIFIED IDEOGRAPH
+0xE2E3	0x7CA4	#CJK UNIFIED IDEOGRAPH
+0xE2E4	0x7CAD	#CJK UNIFIED IDEOGRAPH
+0xE2E5	0x7CA2	#CJK UNIFIED IDEOGRAPH
+0xE2E6	0x7CAB	#CJK UNIFIED IDEOGRAPH
+0xE2E7	0x7CA1	#CJK UNIFIED IDEOGRAPH
+0xE2E8	0x7CA8	#CJK UNIFIED IDEOGRAPH
+0xE2E9	0x7CB3	#CJK UNIFIED IDEOGRAPH
+0xE2EA	0x7CB2	#CJK UNIFIED IDEOGRAPH
+0xE2EB	0x7CB1	#CJK UNIFIED IDEOGRAPH
+0xE2EC	0x7CAE	#CJK UNIFIED IDEOGRAPH
+0xE2ED	0x7CB9	#CJK UNIFIED IDEOGRAPH
+0xE2EE	0x7CBD	#CJK UNIFIED IDEOGRAPH
+0xE2EF	0x7CC0	#CJK UNIFIED IDEOGRAPH
+0xE2F0	0x7CC5	#CJK UNIFIED IDEOGRAPH
+0xE2F1	0x7CC2	#CJK UNIFIED IDEOGRAPH
+0xE2F2	0x7CD8	#CJK UNIFIED IDEOGRAPH
+0xE2F3	0x7CD2	#CJK UNIFIED IDEOGRAPH
+0xE2F4	0x7CDC	#CJK UNIFIED IDEOGRAPH
+0xE2F5	0x7CE2	#CJK UNIFIED IDEOGRAPH
+0xE2F6	0x9B3B	#CJK UNIFIED IDEOGRAPH
+0xE2F7	0x7CEF	#CJK UNIFIED IDEOGRAPH
+0xE2F8	0x7CF2	#CJK UNIFIED IDEOGRAPH
+0xE2F9	0x7CF4	#CJK UNIFIED IDEOGRAPH
+0xE2FA	0x7CF6	#CJK UNIFIED IDEOGRAPH
+0xE2FB	0x7CFA	#CJK UNIFIED IDEOGRAPH
+0xE2FC	0x7D06	#CJK UNIFIED IDEOGRAPH
+0xE340	0x7D02	#CJK UNIFIED IDEOGRAPH
+0xE341	0x7D1C	#CJK UNIFIED IDEOGRAPH
+0xE342	0x7D15	#CJK UNIFIED IDEOGRAPH
+0xE343	0x7D0A	#CJK UNIFIED IDEOGRAPH
+0xE344	0x7D45	#CJK UNIFIED IDEOGRAPH
+0xE345	0x7D4B	#CJK UNIFIED IDEOGRAPH
+0xE346	0x7D2E	#CJK UNIFIED IDEOGRAPH
+0xE347	0x7D32	#CJK UNIFIED IDEOGRAPH
+0xE348	0x7D3F	#CJK UNIFIED IDEOGRAPH
+0xE349	0x7D35	#CJK UNIFIED IDEOGRAPH
+0xE34A	0x7D46	#CJK UNIFIED IDEOGRAPH
+0xE34B	0x7D73	#CJK UNIFIED IDEOGRAPH
+0xE34C	0x7D56	#CJK UNIFIED IDEOGRAPH
+0xE34D	0x7D4E	#CJK UNIFIED IDEOGRAPH
+0xE34E	0x7D72	#CJK UNIFIED IDEOGRAPH
+0xE34F	0x7D68	#CJK UNIFIED IDEOGRAPH
+0xE350	0x7D6E	#CJK UNIFIED IDEOGRAPH
+0xE351	0x7D4F	#CJK UNIFIED IDEOGRAPH
+0xE352	0x7D63	#CJK UNIFIED IDEOGRAPH
+0xE353	0x7D93	#CJK UNIFIED IDEOGRAPH
+0xE354	0x7D89	#CJK UNIFIED IDEOGRAPH
+0xE355	0x7D5B	#CJK UNIFIED IDEOGRAPH
+0xE356	0x7D8F	#CJK UNIFIED IDEOGRAPH
+0xE357	0x7D7D	#CJK UNIFIED IDEOGRAPH
+0xE358	0x7D9B	#CJK UNIFIED IDEOGRAPH
+0xE359	0x7DBA	#CJK UNIFIED IDEOGRAPH
+0xE35A	0x7DAE	#CJK UNIFIED IDEOGRAPH
+0xE35B	0x7DA3	#CJK UNIFIED IDEOGRAPH
+0xE35C	0x7DB5	#CJK UNIFIED IDEOGRAPH
+0xE35D	0x7DC7	#CJK UNIFIED IDEOGRAPH
+0xE35E	0x7DBD	#CJK UNIFIED IDEOGRAPH
+0xE35F	0x7DAB	#CJK UNIFIED IDEOGRAPH
+0xE360	0x7E3D	#CJK UNIFIED IDEOGRAPH
+0xE361	0x7DA2	#CJK UNIFIED IDEOGRAPH
+0xE362	0x7DAF	#CJK UNIFIED IDEOGRAPH
+0xE363	0x7DDC	#CJK UNIFIED IDEOGRAPH
+0xE364	0x7DB8	#CJK UNIFIED IDEOGRAPH
+0xE365	0x7D9F	#CJK UNIFIED IDEOGRAPH
+0xE366	0x7DB0	#CJK UNIFIED IDEOGRAPH
+0xE367	0x7DD8	#CJK UNIFIED IDEOGRAPH
+0xE368	0x7DDD	#CJK UNIFIED IDEOGRAPH
+0xE369	0x7DE4	#CJK UNIFIED IDEOGRAPH
+0xE36A	0x7DDE	#CJK UNIFIED IDEOGRAPH
+0xE36B	0x7DFB	#CJK UNIFIED IDEOGRAPH
+0xE36C	0x7DF2	#CJK UNIFIED IDEOGRAPH
+0xE36D	0x7DE1	#CJK UNIFIED IDEOGRAPH
+0xE36E	0x7E05	#CJK UNIFIED IDEOGRAPH
+0xE36F	0x7E0A	#CJK UNIFIED IDEOGRAPH
+0xE370	0x7E23	#CJK UNIFIED IDEOGRAPH
+0xE371	0x7E21	#CJK UNIFIED IDEOGRAPH
+0xE372	0x7E12	#CJK UNIFIED IDEOGRAPH
+0xE373	0x7E31	#CJK UNIFIED IDEOGRAPH
+0xE374	0x7E1F	#CJK UNIFIED IDEOGRAPH
+0xE375	0x7E09	#CJK UNIFIED IDEOGRAPH
+0xE376	0x7E0B	#CJK UNIFIED IDEOGRAPH
+0xE377	0x7E22	#CJK UNIFIED IDEOGRAPH
+0xE378	0x7E46	#CJK UNIFIED IDEOGRAPH
+0xE379	0x7E66	#CJK UNIFIED IDEOGRAPH
+0xE37A	0x7E3B	#CJK UNIFIED IDEOGRAPH
+0xE37B	0x7E35	#CJK UNIFIED IDEOGRAPH
+0xE37C	0x7E39	#CJK UNIFIED IDEOGRAPH
+0xE37D	0x7E43	#CJK UNIFIED IDEOGRAPH
+0xE37E	0x7E37	#CJK UNIFIED IDEOGRAPH
+0xE380	0x7E32	#CJK UNIFIED IDEOGRAPH
+0xE381	0x7E3A	#CJK UNIFIED IDEOGRAPH
+0xE382	0x7E67	#CJK UNIFIED IDEOGRAPH
+0xE383	0x7E5D	#CJK UNIFIED IDEOGRAPH
+0xE384	0x7E56	#CJK UNIFIED IDEOGRAPH
+0xE385	0x7E5E	#CJK UNIFIED IDEOGRAPH
+0xE386	0x7E59	#CJK UNIFIED IDEOGRAPH
+0xE387	0x7E5A	#CJK UNIFIED IDEOGRAPH
+0xE388	0x7E79	#CJK UNIFIED IDEOGRAPH
+0xE389	0x7E6A	#CJK UNIFIED IDEOGRAPH
+0xE38A	0x7E69	#CJK UNIFIED IDEOGRAPH
+0xE38B	0x7E7C	#CJK UNIFIED IDEOGRAPH
+0xE38C	0x7E7B	#CJK UNIFIED IDEOGRAPH
+0xE38D	0x7E83	#CJK UNIFIED IDEOGRAPH
+0xE38E	0x7DD5	#CJK UNIFIED IDEOGRAPH
+0xE38F	0x7E7D	#CJK UNIFIED IDEOGRAPH
+0xE390	0x8FAE	#CJK UNIFIED IDEOGRAPH
+0xE391	0x7E7F	#CJK UNIFIED IDEOGRAPH
+0xE392	0x7E88	#CJK UNIFIED IDEOGRAPH
+0xE393	0x7E89	#CJK UNIFIED IDEOGRAPH
+0xE394	0x7E8C	#CJK UNIFIED IDEOGRAPH
+0xE395	0x7E92	#CJK UNIFIED IDEOGRAPH
+0xE396	0x7E90	#CJK UNIFIED IDEOGRAPH
+0xE397	0x7E93	#CJK UNIFIED IDEOGRAPH
+0xE398	0x7E94	#CJK UNIFIED IDEOGRAPH
+0xE399	0x7E96	#CJK UNIFIED IDEOGRAPH
+0xE39A	0x7E8E	#CJK UNIFIED IDEOGRAPH
+0xE39B	0x7E9B	#CJK UNIFIED IDEOGRAPH
+0xE39C	0x7E9C	#CJK UNIFIED IDEOGRAPH
+0xE39D	0x7F38	#CJK UNIFIED IDEOGRAPH
+0xE39E	0x7F3A	#CJK UNIFIED IDEOGRAPH
+0xE39F	0x7F45	#CJK UNIFIED IDEOGRAPH
+0xE3A0	0x7F4C	#CJK UNIFIED IDEOGRAPH
+0xE3A1	0x7F4D	#CJK UNIFIED IDEOGRAPH
+0xE3A2	0x7F4E	#CJK UNIFIED IDEOGRAPH
+0xE3A3	0x7F50	#CJK UNIFIED IDEOGRAPH
+0xE3A4	0x7F51	#CJK UNIFIED IDEOGRAPH
+0xE3A5	0x7F55	#CJK UNIFIED IDEOGRAPH
+0xE3A6	0x7F54	#CJK UNIFIED IDEOGRAPH
+0xE3A7	0x7F58	#CJK UNIFIED IDEOGRAPH
+0xE3A8	0x7F5F	#CJK UNIFIED IDEOGRAPH
+0xE3A9	0x7F60	#CJK UNIFIED IDEOGRAPH
+0xE3AA	0x7F68	#CJK UNIFIED IDEOGRAPH
+0xE3AB	0x7F69	#CJK UNIFIED IDEOGRAPH
+0xE3AC	0x7F67	#CJK UNIFIED IDEOGRAPH
+0xE3AD	0x7F78	#CJK UNIFIED IDEOGRAPH
+0xE3AE	0x7F82	#CJK UNIFIED IDEOGRAPH
+0xE3AF	0x7F86	#CJK UNIFIED IDEOGRAPH
+0xE3B0	0x7F83	#CJK UNIFIED IDEOGRAPH
+0xE3B1	0x7F88	#CJK UNIFIED IDEOGRAPH
+0xE3B2	0x7F87	#CJK UNIFIED IDEOGRAPH
+0xE3B3	0x7F8C	#CJK UNIFIED IDEOGRAPH
+0xE3B4	0x7F94	#CJK UNIFIED IDEOGRAPH
+0xE3B5	0x7F9E	#CJK UNIFIED IDEOGRAPH
+0xE3B6	0x7F9D	#CJK UNIFIED IDEOGRAPH
+0xE3B7	0x7F9A	#CJK UNIFIED IDEOGRAPH
+0xE3B8	0x7FA3	#CJK UNIFIED IDEOGRAPH
+0xE3B9	0x7FAF	#CJK UNIFIED IDEOGRAPH
+0xE3BA	0x7FB2	#CJK UNIFIED IDEOGRAPH
+0xE3BB	0x7FB9	#CJK UNIFIED IDEOGRAPH
+0xE3BC	0x7FAE	#CJK UNIFIED IDEOGRAPH
+0xE3BD	0x7FB6	#CJK UNIFIED IDEOGRAPH
+0xE3BE	0x7FB8	#CJK UNIFIED IDEOGRAPH
+0xE3BF	0x8B71	#CJK UNIFIED IDEOGRAPH
+0xE3C0	0x7FC5	#CJK UNIFIED IDEOGRAPH
+0xE3C1	0x7FC6	#CJK UNIFIED IDEOGRAPH
+0xE3C2	0x7FCA	#CJK UNIFIED IDEOGRAPH
+0xE3C3	0x7FD5	#CJK UNIFIED IDEOGRAPH
+0xE3C4	0x7FD4	#CJK UNIFIED IDEOGRAPH
+0xE3C5	0x7FE1	#CJK UNIFIED IDEOGRAPH
+0xE3C6	0x7FE6	#CJK UNIFIED IDEOGRAPH
+0xE3C7	0x7FE9	#CJK UNIFIED IDEOGRAPH
+0xE3C8	0x7FF3	#CJK UNIFIED IDEOGRAPH
+0xE3C9	0x7FF9	#CJK UNIFIED IDEOGRAPH
+0xE3CA	0x98DC	#CJK UNIFIED IDEOGRAPH
+0xE3CB	0x8006	#CJK UNIFIED IDEOGRAPH
+0xE3CC	0x8004	#CJK UNIFIED IDEOGRAPH
+0xE3CD	0x800B	#CJK UNIFIED IDEOGRAPH
+0xE3CE	0x8012	#CJK UNIFIED IDEOGRAPH
+0xE3CF	0x8018	#CJK UNIFIED IDEOGRAPH
+0xE3D0	0x8019	#CJK UNIFIED IDEOGRAPH
+0xE3D1	0x801C	#CJK UNIFIED IDEOGRAPH
+0xE3D2	0x8021	#CJK UNIFIED IDEOGRAPH
+0xE3D3	0x8028	#CJK UNIFIED IDEOGRAPH
+0xE3D4	0x803F	#CJK UNIFIED IDEOGRAPH
+0xE3D5	0x803B	#CJK UNIFIED IDEOGRAPH
+0xE3D6	0x804A	#CJK UNIFIED IDEOGRAPH
+0xE3D7	0x8046	#CJK UNIFIED IDEOGRAPH
+0xE3D8	0x8052	#CJK UNIFIED IDEOGRAPH
+0xE3D9	0x8058	#CJK UNIFIED IDEOGRAPH
+0xE3DA	0x805A	#CJK UNIFIED IDEOGRAPH
+0xE3DB	0x805F	#CJK UNIFIED IDEOGRAPH
+0xE3DC	0x8062	#CJK UNIFIED IDEOGRAPH
+0xE3DD	0x8068	#CJK UNIFIED IDEOGRAPH
+0xE3DE	0x8073	#CJK UNIFIED IDEOGRAPH
+0xE3DF	0x8072	#CJK UNIFIED IDEOGRAPH
+0xE3E0	0x8070	#CJK UNIFIED IDEOGRAPH
+0xE3E1	0x8076	#CJK UNIFIED IDEOGRAPH
+0xE3E2	0x8079	#CJK UNIFIED IDEOGRAPH
+0xE3E3	0x807D	#CJK UNIFIED IDEOGRAPH
+0xE3E4	0x807F	#CJK UNIFIED IDEOGRAPH
+0xE3E5	0x8084	#CJK UNIFIED IDEOGRAPH
+0xE3E6	0x8086	#CJK UNIFIED IDEOGRAPH
+0xE3E7	0x8085	#CJK UNIFIED IDEOGRAPH
+0xE3E8	0x809B	#CJK UNIFIED IDEOGRAPH
+0xE3E9	0x8093	#CJK UNIFIED IDEOGRAPH
+0xE3EA	0x809A	#CJK UNIFIED IDEOGRAPH
+0xE3EB	0x80AD	#CJK UNIFIED IDEOGRAPH
+0xE3EC	0x5190	#CJK UNIFIED IDEOGRAPH
+0xE3ED	0x80AC	#CJK UNIFIED IDEOGRAPH
+0xE3EE	0x80DB	#CJK UNIFIED IDEOGRAPH
+0xE3EF	0x80E5	#CJK UNIFIED IDEOGRAPH
+0xE3F0	0x80D9	#CJK UNIFIED IDEOGRAPH
+0xE3F1	0x80DD	#CJK UNIFIED IDEOGRAPH
+0xE3F2	0x80C4	#CJK UNIFIED IDEOGRAPH
+0xE3F3	0x80DA	#CJK UNIFIED IDEOGRAPH
+0xE3F4	0x80D6	#CJK UNIFIED IDEOGRAPH
+0xE3F5	0x8109	#CJK UNIFIED IDEOGRAPH
+0xE3F6	0x80EF	#CJK UNIFIED IDEOGRAPH
+0xE3F7	0x80F1	#CJK UNIFIED IDEOGRAPH
+0xE3F8	0x811B	#CJK UNIFIED IDEOGRAPH
+0xE3F9	0x8129	#CJK UNIFIED IDEOGRAPH
+0xE3FA	0x8123	#CJK UNIFIED IDEOGRAPH
+0xE3FB	0x812F	#CJK UNIFIED IDEOGRAPH
+0xE3FC	0x814B	#CJK UNIFIED IDEOGRAPH
+0xE440	0x968B	#CJK UNIFIED IDEOGRAPH
+0xE441	0x8146	#CJK UNIFIED IDEOGRAPH
+0xE442	0x813E	#CJK UNIFIED IDEOGRAPH
+0xE443	0x8153	#CJK UNIFIED IDEOGRAPH
+0xE444	0x8151	#CJK UNIFIED IDEOGRAPH
+0xE445	0x80FC	#CJK UNIFIED IDEOGRAPH
+0xE446	0x8171	#CJK UNIFIED IDEOGRAPH
+0xE447	0x816E	#CJK UNIFIED IDEOGRAPH
+0xE448	0x8165	#CJK UNIFIED IDEOGRAPH
+0xE449	0x8166	#CJK UNIFIED IDEOGRAPH
+0xE44A	0x8174	#CJK UNIFIED IDEOGRAPH
+0xE44B	0x8183	#CJK UNIFIED IDEOGRAPH
+0xE44C	0x8188	#CJK UNIFIED IDEOGRAPH
+0xE44D	0x818A	#CJK UNIFIED IDEOGRAPH
+0xE44E	0x8180	#CJK UNIFIED IDEOGRAPH
+0xE44F	0x8182	#CJK UNIFIED IDEOGRAPH
+0xE450	0x81A0	#CJK UNIFIED IDEOGRAPH
+0xE451	0x8195	#CJK UNIFIED IDEOGRAPH
+0xE452	0x81A4	#CJK UNIFIED IDEOGRAPH
+0xE453	0x81A3	#CJK UNIFIED IDEOGRAPH
+0xE454	0x815F	#CJK UNIFIED IDEOGRAPH
+0xE455	0x8193	#CJK UNIFIED IDEOGRAPH
+0xE456	0x81A9	#CJK UNIFIED IDEOGRAPH
+0xE457	0x81B0	#CJK UNIFIED IDEOGRAPH
+0xE458	0x81B5	#CJK UNIFIED IDEOGRAPH
+0xE459	0x81BE	#CJK UNIFIED IDEOGRAPH
+0xE45A	0x81B8	#CJK UNIFIED IDEOGRAPH
+0xE45B	0x81BD	#CJK UNIFIED IDEOGRAPH
+0xE45C	0x81C0	#CJK UNIFIED IDEOGRAPH
+0xE45D	0x81C2	#CJK UNIFIED IDEOGRAPH
+0xE45E	0x81BA	#CJK UNIFIED IDEOGRAPH
+0xE45F	0x81C9	#CJK UNIFIED IDEOGRAPH
+0xE460	0x81CD	#CJK UNIFIED IDEOGRAPH
+0xE461	0x81D1	#CJK UNIFIED IDEOGRAPH
+0xE462	0x81D9	#CJK UNIFIED IDEOGRAPH
+0xE463	0x81D8	#CJK UNIFIED IDEOGRAPH
+0xE464	0x81C8	#CJK UNIFIED IDEOGRAPH
+0xE465	0x81DA	#CJK UNIFIED IDEOGRAPH
+0xE466	0x81DF	#CJK UNIFIED IDEOGRAPH
+0xE467	0x81E0	#CJK UNIFIED IDEOGRAPH
+0xE468	0x81E7	#CJK UNIFIED IDEOGRAPH
+0xE469	0x81FA	#CJK UNIFIED IDEOGRAPH
+0xE46A	0x81FB	#CJK UNIFIED IDEOGRAPH
+0xE46B	0x81FE	#CJK UNIFIED IDEOGRAPH
+0xE46C	0x8201	#CJK UNIFIED IDEOGRAPH
+0xE46D	0x8202	#CJK UNIFIED IDEOGRAPH
+0xE46E	0x8205	#CJK UNIFIED IDEOGRAPH
+0xE46F	0x8207	#CJK UNIFIED IDEOGRAPH
+0xE470	0x820A	#CJK UNIFIED IDEOGRAPH
+0xE471	0x820D	#CJK UNIFIED IDEOGRAPH
+0xE472	0x8210	#CJK UNIFIED IDEOGRAPH
+0xE473	0x8216	#CJK UNIFIED IDEOGRAPH
+0xE474	0x8229	#CJK UNIFIED IDEOGRAPH
+0xE475	0x822B	#CJK UNIFIED IDEOGRAPH
+0xE476	0x8238	#CJK UNIFIED IDEOGRAPH
+0xE477	0x8233	#CJK UNIFIED IDEOGRAPH
+0xE478	0x8240	#CJK UNIFIED IDEOGRAPH
+0xE479	0x8259	#CJK UNIFIED IDEOGRAPH
+0xE47A	0x8258	#CJK UNIFIED IDEOGRAPH
+0xE47B	0x825D	#CJK UNIFIED IDEOGRAPH
+0xE47C	0x825A	#CJK UNIFIED IDEOGRAPH
+0xE47D	0x825F	#CJK UNIFIED IDEOGRAPH
+0xE47E	0x8264	#CJK UNIFIED IDEOGRAPH
+0xE480	0x8262	#CJK UNIFIED IDEOGRAPH
+0xE481	0x8268	#CJK UNIFIED IDEOGRAPH
+0xE482	0x826A	#CJK UNIFIED IDEOGRAPH
+0xE483	0x826B	#CJK UNIFIED IDEOGRAPH
+0xE484	0x822E	#CJK UNIFIED IDEOGRAPH
+0xE485	0x8271	#CJK UNIFIED IDEOGRAPH
+0xE486	0x8277	#CJK UNIFIED IDEOGRAPH
+0xE487	0x8278	#CJK UNIFIED IDEOGRAPH
+0xE488	0x827E	#CJK UNIFIED IDEOGRAPH
+0xE489	0x828D	#CJK UNIFIED IDEOGRAPH
+0xE48A	0x8292	#CJK UNIFIED IDEOGRAPH
+0xE48B	0x82AB	#CJK UNIFIED IDEOGRAPH
+0xE48C	0x829F	#CJK UNIFIED IDEOGRAPH
+0xE48D	0x82BB	#CJK UNIFIED IDEOGRAPH
+0xE48E	0x82AC	#CJK UNIFIED IDEOGRAPH
+0xE48F	0x82E1	#CJK UNIFIED IDEOGRAPH
+0xE490	0x82E3	#CJK UNIFIED IDEOGRAPH
+0xE491	0x82DF	#CJK UNIFIED IDEOGRAPH
+0xE492	0x82D2	#CJK UNIFIED IDEOGRAPH
+0xE493	0x82F4	#CJK UNIFIED IDEOGRAPH
+0xE494	0x82F3	#CJK UNIFIED IDEOGRAPH
+0xE495	0x82FA	#CJK UNIFIED IDEOGRAPH
+0xE496	0x8393	#CJK UNIFIED IDEOGRAPH
+0xE497	0x8303	#CJK UNIFIED IDEOGRAPH
+0xE498	0x82FB	#CJK UNIFIED IDEOGRAPH
+0xE499	0x82F9	#CJK UNIFIED IDEOGRAPH
+0xE49A	0x82DE	#CJK UNIFIED IDEOGRAPH
+0xE49B	0x8306	#CJK UNIFIED IDEOGRAPH
+0xE49C	0x82DC	#CJK UNIFIED IDEOGRAPH
+0xE49D	0x8309	#CJK UNIFIED IDEOGRAPH
+0xE49E	0x82D9	#CJK UNIFIED IDEOGRAPH
+0xE49F	0x8335	#CJK UNIFIED IDEOGRAPH
+0xE4A0	0x8334	#CJK UNIFIED IDEOGRAPH
+0xE4A1	0x8316	#CJK UNIFIED IDEOGRAPH
+0xE4A2	0x8332	#CJK UNIFIED IDEOGRAPH
+0xE4A3	0x8331	#CJK UNIFIED IDEOGRAPH
+0xE4A4	0x8340	#CJK UNIFIED IDEOGRAPH
+0xE4A5	0x8339	#CJK UNIFIED IDEOGRAPH
+0xE4A6	0x8350	#CJK UNIFIED IDEOGRAPH
+0xE4A7	0x8345	#CJK UNIFIED IDEOGRAPH
+0xE4A8	0x832F	#CJK UNIFIED IDEOGRAPH
+0xE4A9	0x832B	#CJK UNIFIED IDEOGRAPH
+0xE4AA	0x8317	#CJK UNIFIED IDEOGRAPH
+0xE4AB	0x8318	#CJK UNIFIED IDEOGRAPH
+0xE4AC	0x8385	#CJK UNIFIED IDEOGRAPH
+0xE4AD	0x839A	#CJK UNIFIED IDEOGRAPH
+0xE4AE	0x83AA	#CJK UNIFIED IDEOGRAPH
+0xE4AF	0x839F	#CJK UNIFIED IDEOGRAPH
+0xE4B0	0x83A2	#CJK UNIFIED IDEOGRAPH
+0xE4B1	0x8396	#CJK UNIFIED IDEOGRAPH
+0xE4B2	0x8323	#CJK UNIFIED IDEOGRAPH
+0xE4B3	0x838E	#CJK UNIFIED IDEOGRAPH
+0xE4B4	0x8387	#CJK UNIFIED IDEOGRAPH
+0xE4B5	0x838A	#CJK UNIFIED IDEOGRAPH
+0xE4B6	0x837C	#CJK UNIFIED IDEOGRAPH
+0xE4B7	0x83B5	#CJK UNIFIED IDEOGRAPH
+0xE4B8	0x8373	#CJK UNIFIED IDEOGRAPH
+0xE4B9	0x8375	#CJK UNIFIED IDEOGRAPH
+0xE4BA	0x83A0	#CJK UNIFIED IDEOGRAPH
+0xE4BB	0x8389	#CJK UNIFIED IDEOGRAPH
+0xE4BC	0x83A8	#CJK UNIFIED IDEOGRAPH
+0xE4BD	0x83F4	#CJK UNIFIED IDEOGRAPH
+0xE4BE	0x8413	#CJK UNIFIED IDEOGRAPH
+0xE4BF	0x83EB	#CJK UNIFIED IDEOGRAPH
+0xE4C0	0x83CE	#CJK UNIFIED IDEOGRAPH
+0xE4C1	0x83FD	#CJK UNIFIED IDEOGRAPH
+0xE4C2	0x8403	#CJK UNIFIED IDEOGRAPH
+0xE4C3	0x83D8	#CJK UNIFIED IDEOGRAPH
+0xE4C4	0x840B	#CJK UNIFIED IDEOGRAPH
+0xE4C5	0x83C1	#CJK UNIFIED IDEOGRAPH
+0xE4C6	0x83F7	#CJK UNIFIED IDEOGRAPH
+0xE4C7	0x8407	#CJK UNIFIED IDEOGRAPH
+0xE4C8	0x83E0	#CJK UNIFIED IDEOGRAPH
+0xE4C9	0x83F2	#CJK UNIFIED IDEOGRAPH
+0xE4CA	0x840D	#CJK UNIFIED IDEOGRAPH
+0xE4CB	0x8422	#CJK UNIFIED IDEOGRAPH
+0xE4CC	0x8420	#CJK UNIFIED IDEOGRAPH
+0xE4CD	0x83BD	#CJK UNIFIED IDEOGRAPH
+0xE4CE	0x8438	#CJK UNIFIED IDEOGRAPH
+0xE4CF	0x8506	#CJK UNIFIED IDEOGRAPH
+0xE4D0	0x83FB	#CJK UNIFIED IDEOGRAPH
+0xE4D1	0x846D	#CJK UNIFIED IDEOGRAPH
+0xE4D2	0x842A	#CJK UNIFIED IDEOGRAPH
+0xE4D3	0x843C	#CJK UNIFIED IDEOGRAPH
+0xE4D4	0x855A	#CJK UNIFIED IDEOGRAPH
+0xE4D5	0x8484	#CJK UNIFIED IDEOGRAPH
+0xE4D6	0x8477	#CJK UNIFIED IDEOGRAPH
+0xE4D7	0x846B	#CJK UNIFIED IDEOGRAPH
+0xE4D8	0x84AD	#CJK UNIFIED IDEOGRAPH
+0xE4D9	0x846E	#CJK UNIFIED IDEOGRAPH
+0xE4DA	0x8482	#CJK UNIFIED IDEOGRAPH
+0xE4DB	0x8469	#CJK UNIFIED IDEOGRAPH
+0xE4DC	0x8446	#CJK UNIFIED IDEOGRAPH
+0xE4DD	0x842C	#CJK UNIFIED IDEOGRAPH
+0xE4DE	0x846F	#CJK UNIFIED IDEOGRAPH
+0xE4DF	0x8479	#CJK UNIFIED IDEOGRAPH
+0xE4E0	0x8435	#CJK UNIFIED IDEOGRAPH
+0xE4E1	0x84CA	#CJK UNIFIED IDEOGRAPH
+0xE4E2	0x8462	#CJK UNIFIED IDEOGRAPH
+0xE4E3	0x84B9	#CJK UNIFIED IDEOGRAPH
+0xE4E4	0x84BF	#CJK UNIFIED IDEOGRAPH
+0xE4E5	0x849F	#CJK UNIFIED IDEOGRAPH
+0xE4E6	0x84D9	#CJK UNIFIED IDEOGRAPH
+0xE4E7	0x84CD	#CJK UNIFIED IDEOGRAPH
+0xE4E8	0x84BB	#CJK UNIFIED IDEOGRAPH
+0xE4E9	0x84DA	#CJK UNIFIED IDEOGRAPH
+0xE4EA	0x84D0	#CJK UNIFIED IDEOGRAPH
+0xE4EB	0x84C1	#CJK UNIFIED IDEOGRAPH
+0xE4EC	0x84C6	#CJK UNIFIED IDEOGRAPH
+0xE4ED	0x84D6	#CJK UNIFIED IDEOGRAPH
+0xE4EE	0x84A1	#CJK UNIFIED IDEOGRAPH
+0xE4EF	0x8521	#CJK UNIFIED IDEOGRAPH
+0xE4F0	0x84FF	#CJK UNIFIED IDEOGRAPH
+0xE4F1	0x84F4	#CJK UNIFIED IDEOGRAPH
+0xE4F2	0x8517	#CJK UNIFIED IDEOGRAPH
+0xE4F3	0x8518	#CJK UNIFIED IDEOGRAPH
+0xE4F4	0x852C	#CJK UNIFIED IDEOGRAPH
+0xE4F5	0x851F	#CJK UNIFIED IDEOGRAPH
+0xE4F6	0x8515	#CJK UNIFIED IDEOGRAPH
+0xE4F7	0x8514	#CJK UNIFIED IDEOGRAPH
+0xE4F8	0x84FC	#CJK UNIFIED IDEOGRAPH
+0xE4F9	0x8540	#CJK UNIFIED IDEOGRAPH
+0xE4FA	0x8563	#CJK UNIFIED IDEOGRAPH
+0xE4FB	0x8558	#CJK UNIFIED IDEOGRAPH
+0xE4FC	0x8548	#CJK UNIFIED IDEOGRAPH
+0xE540	0x8541	#CJK UNIFIED IDEOGRAPH
+0xE541	0x8602	#CJK UNIFIED IDEOGRAPH
+0xE542	0x854B	#CJK UNIFIED IDEOGRAPH
+0xE543	0x8555	#CJK UNIFIED IDEOGRAPH
+0xE544	0x8580	#CJK UNIFIED IDEOGRAPH
+0xE545	0x85A4	#CJK UNIFIED IDEOGRAPH
+0xE546	0x8588	#CJK UNIFIED IDEOGRAPH
+0xE547	0x8591	#CJK UNIFIED IDEOGRAPH
+0xE548	0x858A	#CJK UNIFIED IDEOGRAPH
+0xE549	0x85A8	#CJK UNIFIED IDEOGRAPH
+0xE54A	0x856D	#CJK UNIFIED IDEOGRAPH
+0xE54B	0x8594	#CJK UNIFIED IDEOGRAPH
+0xE54C	0x859B	#CJK UNIFIED IDEOGRAPH
+0xE54D	0x85EA	#CJK UNIFIED IDEOGRAPH
+0xE54E	0x8587	#CJK UNIFIED IDEOGRAPH
+0xE54F	0x859C	#CJK UNIFIED IDEOGRAPH
+0xE550	0x8577	#CJK UNIFIED IDEOGRAPH
+0xE551	0x857E	#CJK UNIFIED IDEOGRAPH
+0xE552	0x8590	#CJK UNIFIED IDEOGRAPH
+0xE553	0x85C9	#CJK UNIFIED IDEOGRAPH
+0xE554	0x85BA	#CJK UNIFIED IDEOGRAPH
+0xE555	0x85CF	#CJK UNIFIED IDEOGRAPH
+0xE556	0x85B9	#CJK UNIFIED IDEOGRAPH
+0xE557	0x85D0	#CJK UNIFIED IDEOGRAPH
+0xE558	0x85D5	#CJK UNIFIED IDEOGRAPH
+0xE559	0x85DD	#CJK UNIFIED IDEOGRAPH
+0xE55A	0x85E5	#CJK UNIFIED IDEOGRAPH
+0xE55B	0x85DC	#CJK UNIFIED IDEOGRAPH
+0xE55C	0x85F9	#CJK UNIFIED IDEOGRAPH
+0xE55D	0x860A	#CJK UNIFIED IDEOGRAPH
+0xE55E	0x8613	#CJK UNIFIED IDEOGRAPH
+0xE55F	0x860B	#CJK UNIFIED IDEOGRAPH
+0xE560	0x85FE	#CJK UNIFIED IDEOGRAPH
+0xE561	0x85FA	#CJK UNIFIED IDEOGRAPH
+0xE562	0x8606	#CJK UNIFIED IDEOGRAPH
+0xE563	0x8622	#CJK UNIFIED IDEOGRAPH
+0xE564	0x861A	#CJK UNIFIED IDEOGRAPH
+0xE565	0x8630	#CJK UNIFIED IDEOGRAPH
+0xE566	0x863F	#CJK UNIFIED IDEOGRAPH
+0xE567	0x864D	#CJK UNIFIED IDEOGRAPH
+0xE568	0x4E55	#CJK UNIFIED IDEOGRAPH
+0xE569	0x8654	#CJK UNIFIED IDEOGRAPH
+0xE56A	0x865F	#CJK UNIFIED IDEOGRAPH
+0xE56B	0x8667	#CJK UNIFIED IDEOGRAPH
+0xE56C	0x8671	#CJK UNIFIED IDEOGRAPH
+0xE56D	0x8693	#CJK UNIFIED IDEOGRAPH
+0xE56E	0x86A3	#CJK UNIFIED IDEOGRAPH
+0xE56F	0x86A9	#CJK UNIFIED IDEOGRAPH
+0xE570	0x86AA	#CJK UNIFIED IDEOGRAPH
+0xE571	0x868B	#CJK UNIFIED IDEOGRAPH
+0xE572	0x868C	#CJK UNIFIED IDEOGRAPH
+0xE573	0x86B6	#CJK UNIFIED IDEOGRAPH
+0xE574	0x86AF	#CJK UNIFIED IDEOGRAPH
+0xE575	0x86C4	#CJK UNIFIED IDEOGRAPH
+0xE576	0x86C6	#CJK UNIFIED IDEOGRAPH
+0xE577	0x86B0	#CJK UNIFIED IDEOGRAPH
+0xE578	0x86C9	#CJK UNIFIED IDEOGRAPH
+0xE579	0x8823	#CJK UNIFIED IDEOGRAPH
+0xE57A	0x86AB	#CJK UNIFIED IDEOGRAPH
+0xE57B	0x86D4	#CJK UNIFIED IDEOGRAPH
+0xE57C	0x86DE	#CJK UNIFIED IDEOGRAPH
+0xE57D	0x86E9	#CJK UNIFIED IDEOGRAPH
+0xE57E	0x86EC	#CJK UNIFIED IDEOGRAPH
+0xE580	0x86DF	#CJK UNIFIED IDEOGRAPH
+0xE581	0x86DB	#CJK UNIFIED IDEOGRAPH
+0xE582	0x86EF	#CJK UNIFIED IDEOGRAPH
+0xE583	0x8712	#CJK UNIFIED IDEOGRAPH
+0xE584	0x8706	#CJK UNIFIED IDEOGRAPH
+0xE585	0x8708	#CJK UNIFIED IDEOGRAPH
+0xE586	0x8700	#CJK UNIFIED IDEOGRAPH
+0xE587	0x8703	#CJK UNIFIED IDEOGRAPH
+0xE588	0x86FB	#CJK UNIFIED IDEOGRAPH
+0xE589	0x8711	#CJK UNIFIED IDEOGRAPH
+0xE58A	0x8709	#CJK UNIFIED IDEOGRAPH
+0xE58B	0x870D	#CJK UNIFIED IDEOGRAPH
+0xE58C	0x86F9	#CJK UNIFIED IDEOGRAPH
+0xE58D	0x870A	#CJK UNIFIED IDEOGRAPH
+0xE58E	0x8734	#CJK UNIFIED IDEOGRAPH
+0xE58F	0x873F	#CJK UNIFIED IDEOGRAPH
+0xE590	0x8737	#CJK UNIFIED IDEOGRAPH
+0xE591	0x873B	#CJK UNIFIED IDEOGRAPH
+0xE592	0x8725	#CJK UNIFIED IDEOGRAPH
+0xE593	0x8729	#CJK UNIFIED IDEOGRAPH
+0xE594	0x871A	#CJK UNIFIED IDEOGRAPH
+0xE595	0x8760	#CJK UNIFIED IDEOGRAPH
+0xE596	0x875F	#CJK UNIFIED IDEOGRAPH
+0xE597	0x8778	#CJK UNIFIED IDEOGRAPH
+0xE598	0x874C	#CJK UNIFIED IDEOGRAPH
+0xE599	0x874E	#CJK UNIFIED IDEOGRAPH
+0xE59A	0x8774	#CJK UNIFIED IDEOGRAPH
+0xE59B	0x8757	#CJK UNIFIED IDEOGRAPH
+0xE59C	0x8768	#CJK UNIFIED IDEOGRAPH
+0xE59D	0x876E	#CJK UNIFIED IDEOGRAPH
+0xE59E	0x8759	#CJK UNIFIED IDEOGRAPH
+0xE59F	0x8753	#CJK UNIFIED IDEOGRAPH
+0xE5A0	0x8763	#CJK UNIFIED IDEOGRAPH
+0xE5A1	0x876A	#CJK UNIFIED IDEOGRAPH
+0xE5A2	0x8805	#CJK UNIFIED IDEOGRAPH
+0xE5A3	0x87A2	#CJK UNIFIED IDEOGRAPH
+0xE5A4	0x879F	#CJK UNIFIED IDEOGRAPH
+0xE5A5	0x8782	#CJK UNIFIED IDEOGRAPH
+0xE5A6	0x87AF	#CJK UNIFIED IDEOGRAPH
+0xE5A7	0x87CB	#CJK UNIFIED IDEOGRAPH
+0xE5A8	0x87BD	#CJK UNIFIED IDEOGRAPH
+0xE5A9	0x87C0	#CJK UNIFIED IDEOGRAPH
+0xE5AA	0x87D0	#CJK UNIFIED IDEOGRAPH
+0xE5AB	0x96D6	#CJK UNIFIED IDEOGRAPH
+0xE5AC	0x87AB	#CJK UNIFIED IDEOGRAPH
+0xE5AD	0x87C4	#CJK UNIFIED IDEOGRAPH
+0xE5AE	0x87B3	#CJK UNIFIED IDEOGRAPH
+0xE5AF	0x87C7	#CJK UNIFIED IDEOGRAPH
+0xE5B0	0x87C6	#CJK UNIFIED IDEOGRAPH
+0xE5B1	0x87BB	#CJK UNIFIED IDEOGRAPH
+0xE5B2	0x87EF	#CJK UNIFIED IDEOGRAPH
+0xE5B3	0x87F2	#CJK UNIFIED IDEOGRAPH
+0xE5B4	0x87E0	#CJK UNIFIED IDEOGRAPH
+0xE5B5	0x880F	#CJK UNIFIED IDEOGRAPH
+0xE5B6	0x880D	#CJK UNIFIED IDEOGRAPH
+0xE5B7	0x87FE	#CJK UNIFIED IDEOGRAPH
+0xE5B8	0x87F6	#CJK UNIFIED IDEOGRAPH
+0xE5B9	0x87F7	#CJK UNIFIED IDEOGRAPH
+0xE5BA	0x880E	#CJK UNIFIED IDEOGRAPH
+0xE5BB	0x87D2	#CJK UNIFIED IDEOGRAPH
+0xE5BC	0x8811	#CJK UNIFIED IDEOGRAPH
+0xE5BD	0x8816	#CJK UNIFIED IDEOGRAPH
+0xE5BE	0x8815	#CJK UNIFIED IDEOGRAPH
+0xE5BF	0x8822	#CJK UNIFIED IDEOGRAPH
+0xE5C0	0x8821	#CJK UNIFIED IDEOGRAPH
+0xE5C1	0x8831	#CJK UNIFIED IDEOGRAPH
+0xE5C2	0x8836	#CJK UNIFIED IDEOGRAPH
+0xE5C3	0x8839	#CJK UNIFIED IDEOGRAPH
+0xE5C4	0x8827	#CJK UNIFIED IDEOGRAPH
+0xE5C5	0x883B	#CJK UNIFIED IDEOGRAPH
+0xE5C6	0x8844	#CJK UNIFIED IDEOGRAPH
+0xE5C7	0x8842	#CJK UNIFIED IDEOGRAPH
+0xE5C8	0x8852	#CJK UNIFIED IDEOGRAPH
+0xE5C9	0x8859	#CJK UNIFIED IDEOGRAPH
+0xE5CA	0x885E	#CJK UNIFIED IDEOGRAPH
+0xE5CB	0x8862	#CJK UNIFIED IDEOGRAPH
+0xE5CC	0x886B	#CJK UNIFIED IDEOGRAPH
+0xE5CD	0x8881	#CJK UNIFIED IDEOGRAPH
+0xE5CE	0x887E	#CJK UNIFIED IDEOGRAPH
+0xE5CF	0x889E	#CJK UNIFIED IDEOGRAPH
+0xE5D0	0x8875	#CJK UNIFIED IDEOGRAPH
+0xE5D1	0x887D	#CJK UNIFIED IDEOGRAPH
+0xE5D2	0x88B5	#CJK UNIFIED IDEOGRAPH
+0xE5D3	0x8872	#CJK UNIFIED IDEOGRAPH
+0xE5D4	0x8882	#CJK UNIFIED IDEOGRAPH
+0xE5D5	0x8897	#CJK UNIFIED IDEOGRAPH
+0xE5D6	0x8892	#CJK UNIFIED IDEOGRAPH
+0xE5D7	0x88AE	#CJK UNIFIED IDEOGRAPH
+0xE5D8	0x8899	#CJK UNIFIED IDEOGRAPH
+0xE5D9	0x88A2	#CJK UNIFIED IDEOGRAPH
+0xE5DA	0x888D	#CJK UNIFIED IDEOGRAPH
+0xE5DB	0x88A4	#CJK UNIFIED IDEOGRAPH
+0xE5DC	0x88B0	#CJK UNIFIED IDEOGRAPH
+0xE5DD	0x88BF	#CJK UNIFIED IDEOGRAPH
+0xE5DE	0x88B1	#CJK UNIFIED IDEOGRAPH
+0xE5DF	0x88C3	#CJK UNIFIED IDEOGRAPH
+0xE5E0	0x88C4	#CJK UNIFIED IDEOGRAPH
+0xE5E1	0x88D4	#CJK UNIFIED IDEOGRAPH
+0xE5E2	0x88D8	#CJK UNIFIED IDEOGRAPH
+0xE5E3	0x88D9	#CJK UNIFIED IDEOGRAPH
+0xE5E4	0x88DD	#CJK UNIFIED IDEOGRAPH
+0xE5E5	0x88F9	#CJK UNIFIED IDEOGRAPH
+0xE5E6	0x8902	#CJK UNIFIED IDEOGRAPH
+0xE5E7	0x88FC	#CJK UNIFIED IDEOGRAPH
+0xE5E8	0x88F4	#CJK UNIFIED IDEOGRAPH
+0xE5E9	0x88E8	#CJK UNIFIED IDEOGRAPH
+0xE5EA	0x88F2	#CJK UNIFIED IDEOGRAPH
+0xE5EB	0x8904	#CJK UNIFIED IDEOGRAPH
+0xE5EC	0x890C	#CJK UNIFIED IDEOGRAPH
+0xE5ED	0x890A	#CJK UNIFIED IDEOGRAPH
+0xE5EE	0x8913	#CJK UNIFIED IDEOGRAPH
+0xE5EF	0x8943	#CJK UNIFIED IDEOGRAPH
+0xE5F0	0x891E	#CJK UNIFIED IDEOGRAPH
+0xE5F1	0x8925	#CJK UNIFIED IDEOGRAPH
+0xE5F2	0x892A	#CJK UNIFIED IDEOGRAPH
+0xE5F3	0x892B	#CJK UNIFIED IDEOGRAPH
+0xE5F4	0x8941	#CJK UNIFIED IDEOGRAPH
+0xE5F5	0x8944	#CJK UNIFIED IDEOGRAPH
+0xE5F6	0x893B	#CJK UNIFIED IDEOGRAPH
+0xE5F7	0x8936	#CJK UNIFIED IDEOGRAPH
+0xE5F8	0x8938	#CJK UNIFIED IDEOGRAPH
+0xE5F9	0x894C	#CJK UNIFIED IDEOGRAPH
+0xE5FA	0x891D	#CJK UNIFIED IDEOGRAPH
+0xE5FB	0x8960	#CJK UNIFIED IDEOGRAPH
+0xE5FC	0x895E	#CJK UNIFIED IDEOGRAPH
+0xE640	0x8966	#CJK UNIFIED IDEOGRAPH
+0xE641	0x8964	#CJK UNIFIED IDEOGRAPH
+0xE642	0x896D	#CJK UNIFIED IDEOGRAPH
+0xE643	0x896A	#CJK UNIFIED IDEOGRAPH
+0xE644	0x896F	#CJK UNIFIED IDEOGRAPH
+0xE645	0x8974	#CJK UNIFIED IDEOGRAPH
+0xE646	0x8977	#CJK UNIFIED IDEOGRAPH
+0xE647	0x897E	#CJK UNIFIED IDEOGRAPH
+0xE648	0x8983	#CJK UNIFIED IDEOGRAPH
+0xE649	0x8988	#CJK UNIFIED IDEOGRAPH
+0xE64A	0x898A	#CJK UNIFIED IDEOGRAPH
+0xE64B	0x8993	#CJK UNIFIED IDEOGRAPH
+0xE64C	0x8998	#CJK UNIFIED IDEOGRAPH
+0xE64D	0x89A1	#CJK UNIFIED IDEOGRAPH
+0xE64E	0x89A9	#CJK UNIFIED IDEOGRAPH
+0xE64F	0x89A6	#CJK UNIFIED IDEOGRAPH
+0xE650	0x89AC	#CJK UNIFIED IDEOGRAPH
+0xE651	0x89AF	#CJK UNIFIED IDEOGRAPH
+0xE652	0x89B2	#CJK UNIFIED IDEOGRAPH
+0xE653	0x89BA	#CJK UNIFIED IDEOGRAPH
+0xE654	0x89BD	#CJK UNIFIED IDEOGRAPH
+0xE655	0x89BF	#CJK UNIFIED IDEOGRAPH
+0xE656	0x89C0	#CJK UNIFIED IDEOGRAPH
+0xE657	0x89DA	#CJK UNIFIED IDEOGRAPH
+0xE658	0x89DC	#CJK UNIFIED IDEOGRAPH
+0xE659	0x89DD	#CJK UNIFIED IDEOGRAPH
+0xE65A	0x89E7	#CJK UNIFIED IDEOGRAPH
+0xE65B	0x89F4	#CJK UNIFIED IDEOGRAPH
+0xE65C	0x89F8	#CJK UNIFIED IDEOGRAPH
+0xE65D	0x8A03	#CJK UNIFIED IDEOGRAPH
+0xE65E	0x8A16	#CJK UNIFIED IDEOGRAPH
+0xE65F	0x8A10	#CJK UNIFIED IDEOGRAPH
+0xE660	0x8A0C	#CJK UNIFIED IDEOGRAPH
+0xE661	0x8A1B	#CJK UNIFIED IDEOGRAPH
+0xE662	0x8A1D	#CJK UNIFIED IDEOGRAPH
+0xE663	0x8A25	#CJK UNIFIED IDEOGRAPH
+0xE664	0x8A36	#CJK UNIFIED IDEOGRAPH
+0xE665	0x8A41	#CJK UNIFIED IDEOGRAPH
+0xE666	0x8A5B	#CJK UNIFIED IDEOGRAPH
+0xE667	0x8A52	#CJK UNIFIED IDEOGRAPH
+0xE668	0x8A46	#CJK UNIFIED IDEOGRAPH
+0xE669	0x8A48	#CJK UNIFIED IDEOGRAPH
+0xE66A	0x8A7C	#CJK UNIFIED IDEOGRAPH
+0xE66B	0x8A6D	#CJK UNIFIED IDEOGRAPH
+0xE66C	0x8A6C	#CJK UNIFIED IDEOGRAPH
+0xE66D	0x8A62	#CJK UNIFIED IDEOGRAPH
+0xE66E	0x8A85	#CJK UNIFIED IDEOGRAPH
+0xE66F	0x8A82	#CJK UNIFIED IDEOGRAPH
+0xE670	0x8A84	#CJK UNIFIED IDEOGRAPH
+0xE671	0x8AA8	#CJK UNIFIED IDEOGRAPH
+0xE672	0x8AA1	#CJK UNIFIED IDEOGRAPH
+0xE673	0x8A91	#CJK UNIFIED IDEOGRAPH
+0xE674	0x8AA5	#CJK UNIFIED IDEOGRAPH
+0xE675	0x8AA6	#CJK UNIFIED IDEOGRAPH
+0xE676	0x8A9A	#CJK UNIFIED IDEOGRAPH
+0xE677	0x8AA3	#CJK UNIFIED IDEOGRAPH
+0xE678	0x8AC4	#CJK UNIFIED IDEOGRAPH
+0xE679	0x8ACD	#CJK UNIFIED IDEOGRAPH
+0xE67A	0x8AC2	#CJK UNIFIED IDEOGRAPH
+0xE67B	0x8ADA	#CJK UNIFIED IDEOGRAPH
+0xE67C	0x8AEB	#CJK UNIFIED IDEOGRAPH
+0xE67D	0x8AF3	#CJK UNIFIED IDEOGRAPH
+0xE67E	0x8AE7	#CJK UNIFIED IDEOGRAPH
+0xE680	0x8AE4	#CJK UNIFIED IDEOGRAPH
+0xE681	0x8AF1	#CJK UNIFIED IDEOGRAPH
+0xE682	0x8B14	#CJK UNIFIED IDEOGRAPH
+0xE683	0x8AE0	#CJK UNIFIED IDEOGRAPH
+0xE684	0x8AE2	#CJK UNIFIED IDEOGRAPH
+0xE685	0x8AF7	#CJK UNIFIED IDEOGRAPH
+0xE686	0x8ADE	#CJK UNIFIED IDEOGRAPH
+0xE687	0x8ADB	#CJK UNIFIED IDEOGRAPH
+0xE688	0x8B0C	#CJK UNIFIED IDEOGRAPH
+0xE689	0x8B07	#CJK UNIFIED IDEOGRAPH
+0xE68A	0x8B1A	#CJK UNIFIED IDEOGRAPH
+0xE68B	0x8AE1	#CJK UNIFIED IDEOGRAPH
+0xE68C	0x8B16	#CJK UNIFIED IDEOGRAPH
+0xE68D	0x8B10	#CJK UNIFIED IDEOGRAPH
+0xE68E	0x8B17	#CJK UNIFIED IDEOGRAPH
+0xE68F	0x8B20	#CJK UNIFIED IDEOGRAPH
+0xE690	0x8B33	#CJK UNIFIED IDEOGRAPH
+0xE691	0x97AB	#CJK UNIFIED IDEOGRAPH
+0xE692	0x8B26	#CJK UNIFIED IDEOGRAPH
+0xE693	0x8B2B	#CJK UNIFIED IDEOGRAPH
+0xE694	0x8B3E	#CJK UNIFIED IDEOGRAPH
+0xE695	0x8B28	#CJK UNIFIED IDEOGRAPH
+0xE696	0x8B41	#CJK UNIFIED IDEOGRAPH
+0xE697	0x8B4C	#CJK UNIFIED IDEOGRAPH
+0xE698	0x8B4F	#CJK UNIFIED IDEOGRAPH
+0xE699	0x8B4E	#CJK UNIFIED IDEOGRAPH
+0xE69A	0x8B49	#CJK UNIFIED IDEOGRAPH
+0xE69B	0x8B56	#CJK UNIFIED IDEOGRAPH
+0xE69C	0x8B5B	#CJK UNIFIED IDEOGRAPH
+0xE69D	0x8B5A	#CJK UNIFIED IDEOGRAPH
+0xE69E	0x8B6B	#CJK UNIFIED IDEOGRAPH
+0xE69F	0x8B5F	#CJK UNIFIED IDEOGRAPH
+0xE6A0	0x8B6C	#CJK UNIFIED IDEOGRAPH
+0xE6A1	0x8B6F	#CJK UNIFIED IDEOGRAPH
+0xE6A2	0x8B74	#CJK UNIFIED IDEOGRAPH
+0xE6A3	0x8B7D	#CJK UNIFIED IDEOGRAPH
+0xE6A4	0x8B80	#CJK UNIFIED IDEOGRAPH
+0xE6A5	0x8B8C	#CJK UNIFIED IDEOGRAPH
+0xE6A6	0x8B8E	#CJK UNIFIED IDEOGRAPH
+0xE6A7	0x8B92	#CJK UNIFIED IDEOGRAPH
+0xE6A8	0x8B93	#CJK UNIFIED IDEOGRAPH
+0xE6A9	0x8B96	#CJK UNIFIED IDEOGRAPH
+0xE6AA	0x8B99	#CJK UNIFIED IDEOGRAPH
+0xE6AB	0x8B9A	#CJK UNIFIED IDEOGRAPH
+0xE6AC	0x8C3A	#CJK UNIFIED IDEOGRAPH
+0xE6AD	0x8C41	#CJK UNIFIED IDEOGRAPH
+0xE6AE	0x8C3F	#CJK UNIFIED IDEOGRAPH
+0xE6AF	0x8C48	#CJK UNIFIED IDEOGRAPH
+0xE6B0	0x8C4C	#CJK UNIFIED IDEOGRAPH
+0xE6B1	0x8C4E	#CJK UNIFIED IDEOGRAPH
+0xE6B2	0x8C50	#CJK UNIFIED IDEOGRAPH
+0xE6B3	0x8C55	#CJK UNIFIED IDEOGRAPH
+0xE6B4	0x8C62	#CJK UNIFIED IDEOGRAPH
+0xE6B5	0x8C6C	#CJK UNIFIED IDEOGRAPH
+0xE6B6	0x8C78	#CJK UNIFIED IDEOGRAPH
+0xE6B7	0x8C7A	#CJK UNIFIED IDEOGRAPH
+0xE6B8	0x8C82	#CJK UNIFIED IDEOGRAPH
+0xE6B9	0x8C89	#CJK UNIFIED IDEOGRAPH
+0xE6BA	0x8C85	#CJK UNIFIED IDEOGRAPH
+0xE6BB	0x8C8A	#CJK UNIFIED IDEOGRAPH
+0xE6BC	0x8C8D	#CJK UNIFIED IDEOGRAPH
+0xE6BD	0x8C8E	#CJK UNIFIED IDEOGRAPH
+0xE6BE	0x8C94	#CJK UNIFIED IDEOGRAPH
+0xE6BF	0x8C7C	#CJK UNIFIED IDEOGRAPH
+0xE6C0	0x8C98	#CJK UNIFIED IDEOGRAPH
+0xE6C1	0x621D	#CJK UNIFIED IDEOGRAPH
+0xE6C2	0x8CAD	#CJK UNIFIED IDEOGRAPH
+0xE6C3	0x8CAA	#CJK UNIFIED IDEOGRAPH
+0xE6C4	0x8CBD	#CJK UNIFIED IDEOGRAPH
+0xE6C5	0x8CB2	#CJK UNIFIED IDEOGRAPH
+0xE6C6	0x8CB3	#CJK UNIFIED IDEOGRAPH
+0xE6C7	0x8CAE	#CJK UNIFIED IDEOGRAPH
+0xE6C8	0x8CB6	#CJK UNIFIED IDEOGRAPH
+0xE6C9	0x8CC8	#CJK UNIFIED IDEOGRAPH
+0xE6CA	0x8CC1	#CJK UNIFIED IDEOGRAPH
+0xE6CB	0x8CE4	#CJK UNIFIED IDEOGRAPH
+0xE6CC	0x8CE3	#CJK UNIFIED IDEOGRAPH
+0xE6CD	0x8CDA	#CJK UNIFIED IDEOGRAPH
+0xE6CE	0x8CFD	#CJK UNIFIED IDEOGRAPH
+0xE6CF	0x8CFA	#CJK UNIFIED IDEOGRAPH
+0xE6D0	0x8CFB	#CJK UNIFIED IDEOGRAPH
+0xE6D1	0x8D04	#CJK UNIFIED IDEOGRAPH
+0xE6D2	0x8D05	#CJK UNIFIED IDEOGRAPH
+0xE6D3	0x8D0A	#CJK UNIFIED IDEOGRAPH
+0xE6D4	0x8D07	#CJK UNIFIED IDEOGRAPH
+0xE6D5	0x8D0F	#CJK UNIFIED IDEOGRAPH
+0xE6D6	0x8D0D	#CJK UNIFIED IDEOGRAPH
+0xE6D7	0x8D10	#CJK UNIFIED IDEOGRAPH
+0xE6D8	0x9F4E	#CJK UNIFIED IDEOGRAPH
+0xE6D9	0x8D13	#CJK UNIFIED IDEOGRAPH
+0xE6DA	0x8CCD	#CJK UNIFIED IDEOGRAPH
+0xE6DB	0x8D14	#CJK UNIFIED IDEOGRAPH
+0xE6DC	0x8D16	#CJK UNIFIED IDEOGRAPH
+0xE6DD	0x8D67	#CJK UNIFIED IDEOGRAPH
+0xE6DE	0x8D6D	#CJK UNIFIED IDEOGRAPH
+0xE6DF	0x8D71	#CJK UNIFIED IDEOGRAPH
+0xE6E0	0x8D73	#CJK UNIFIED IDEOGRAPH
+0xE6E1	0x8D81	#CJK UNIFIED IDEOGRAPH
+0xE6E2	0x8D99	#CJK UNIFIED IDEOGRAPH
+0xE6E3	0x8DC2	#CJK UNIFIED IDEOGRAPH
+0xE6E4	0x8DBE	#CJK UNIFIED IDEOGRAPH
+0xE6E5	0x8DBA	#CJK UNIFIED IDEOGRAPH
+0xE6E6	0x8DCF	#CJK UNIFIED IDEOGRAPH
+0xE6E7	0x8DDA	#CJK UNIFIED IDEOGRAPH
+0xE6E8	0x8DD6	#CJK UNIFIED IDEOGRAPH
+0xE6E9	0x8DCC	#CJK UNIFIED IDEOGRAPH
+0xE6EA	0x8DDB	#CJK UNIFIED IDEOGRAPH
+0xE6EB	0x8DCB	#CJK UNIFIED IDEOGRAPH
+0xE6EC	0x8DEA	#CJK UNIFIED IDEOGRAPH
+0xE6ED	0x8DEB	#CJK UNIFIED IDEOGRAPH
+0xE6EE	0x8DDF	#CJK UNIFIED IDEOGRAPH
+0xE6EF	0x8DE3	#CJK UNIFIED IDEOGRAPH
+0xE6F0	0x8DFC	#CJK UNIFIED IDEOGRAPH
+0xE6F1	0x8E08	#CJK UNIFIED IDEOGRAPH
+0xE6F2	0x8E09	#CJK UNIFIED IDEOGRAPH
+0xE6F3	0x8DFF	#CJK UNIFIED IDEOGRAPH
+0xE6F4	0x8E1D	#CJK UNIFIED IDEOGRAPH
+0xE6F5	0x8E1E	#CJK UNIFIED IDEOGRAPH
+0xE6F6	0x8E10	#CJK UNIFIED IDEOGRAPH
+0xE6F7	0x8E1F	#CJK UNIFIED IDEOGRAPH
+0xE6F8	0x8E42	#CJK UNIFIED IDEOGRAPH
+0xE6F9	0x8E35	#CJK UNIFIED IDEOGRAPH
+0xE6FA	0x8E30	#CJK UNIFIED IDEOGRAPH
+0xE6FB	0x8E34	#CJK UNIFIED IDEOGRAPH
+0xE6FC	0x8E4A	#CJK UNIFIED IDEOGRAPH
+0xE740	0x8E47	#CJK UNIFIED IDEOGRAPH
+0xE741	0x8E49	#CJK UNIFIED IDEOGRAPH
+0xE742	0x8E4C	#CJK UNIFIED IDEOGRAPH
+0xE743	0x8E50	#CJK UNIFIED IDEOGRAPH
+0xE744	0x8E48	#CJK UNIFIED IDEOGRAPH
+0xE745	0x8E59	#CJK UNIFIED IDEOGRAPH
+0xE746	0x8E64	#CJK UNIFIED IDEOGRAPH
+0xE747	0x8E60	#CJK UNIFIED IDEOGRAPH
+0xE748	0x8E2A	#CJK UNIFIED IDEOGRAPH
+0xE749	0x8E63	#CJK UNIFIED IDEOGRAPH
+0xE74A	0x8E55	#CJK UNIFIED IDEOGRAPH
+0xE74B	0x8E76	#CJK UNIFIED IDEOGRAPH
+0xE74C	0x8E72	#CJK UNIFIED IDEOGRAPH
+0xE74D	0x8E7C	#CJK UNIFIED IDEOGRAPH
+0xE74E	0x8E81	#CJK UNIFIED IDEOGRAPH
+0xE74F	0x8E87	#CJK UNIFIED IDEOGRAPH
+0xE750	0x8E85	#CJK UNIFIED IDEOGRAPH
+0xE751	0x8E84	#CJK UNIFIED IDEOGRAPH
+0xE752	0x8E8B	#CJK UNIFIED IDEOGRAPH
+0xE753	0x8E8A	#CJK UNIFIED IDEOGRAPH
+0xE754	0x8E93	#CJK UNIFIED IDEOGRAPH
+0xE755	0x8E91	#CJK UNIFIED IDEOGRAPH
+0xE756	0x8E94	#CJK UNIFIED IDEOGRAPH
+0xE757	0x8E99	#CJK UNIFIED IDEOGRAPH
+0xE758	0x8EAA	#CJK UNIFIED IDEOGRAPH
+0xE759	0x8EA1	#CJK UNIFIED IDEOGRAPH
+0xE75A	0x8EAC	#CJK UNIFIED IDEOGRAPH
+0xE75B	0x8EB0	#CJK UNIFIED IDEOGRAPH
+0xE75C	0x8EC6	#CJK UNIFIED IDEOGRAPH
+0xE75D	0x8EB1	#CJK UNIFIED IDEOGRAPH
+0xE75E	0x8EBE	#CJK UNIFIED IDEOGRAPH
+0xE75F	0x8EC5	#CJK UNIFIED IDEOGRAPH
+0xE760	0x8EC8	#CJK UNIFIED IDEOGRAPH
+0xE761	0x8ECB	#CJK UNIFIED IDEOGRAPH
+0xE762	0x8EDB	#CJK UNIFIED IDEOGRAPH
+0xE763	0x8EE3	#CJK UNIFIED IDEOGRAPH
+0xE764	0x8EFC	#CJK UNIFIED IDEOGRAPH
+0xE765	0x8EFB	#CJK UNIFIED IDEOGRAPH
+0xE766	0x8EEB	#CJK UNIFIED IDEOGRAPH
+0xE767	0x8EFE	#CJK UNIFIED IDEOGRAPH
+0xE768	0x8F0A	#CJK UNIFIED IDEOGRAPH
+0xE769	0x8F05	#CJK UNIFIED IDEOGRAPH
+0xE76A	0x8F15	#CJK UNIFIED IDEOGRAPH
+0xE76B	0x8F12	#CJK UNIFIED IDEOGRAPH
+0xE76C	0x8F19	#CJK UNIFIED IDEOGRAPH
+0xE76D	0x8F13	#CJK UNIFIED IDEOGRAPH
+0xE76E	0x8F1C	#CJK UNIFIED IDEOGRAPH
+0xE76F	0x8F1F	#CJK UNIFIED IDEOGRAPH
+0xE770	0x8F1B	#CJK UNIFIED IDEOGRAPH
+0xE771	0x8F0C	#CJK UNIFIED IDEOGRAPH
+0xE772	0x8F26	#CJK UNIFIED IDEOGRAPH
+0xE773	0x8F33	#CJK UNIFIED IDEOGRAPH
+0xE774	0x8F3B	#CJK UNIFIED IDEOGRAPH
+0xE775	0x8F39	#CJK UNIFIED IDEOGRAPH
+0xE776	0x8F45	#CJK UNIFIED IDEOGRAPH
+0xE777	0x8F42	#CJK UNIFIED IDEOGRAPH
+0xE778	0x8F3E	#CJK UNIFIED IDEOGRAPH
+0xE779	0x8F4C	#CJK UNIFIED IDEOGRAPH
+0xE77A	0x8F49	#CJK UNIFIED IDEOGRAPH
+0xE77B	0x8F46	#CJK UNIFIED IDEOGRAPH
+0xE77C	0x8F4E	#CJK UNIFIED IDEOGRAPH
+0xE77D	0x8F57	#CJK UNIFIED IDEOGRAPH
+0xE77E	0x8F5C	#CJK UNIFIED IDEOGRAPH
+0xE780	0x8F62	#CJK UNIFIED IDEOGRAPH
+0xE781	0x8F63	#CJK UNIFIED IDEOGRAPH
+0xE782	0x8F64	#CJK UNIFIED IDEOGRAPH
+0xE783	0x8F9C	#CJK UNIFIED IDEOGRAPH
+0xE784	0x8F9F	#CJK UNIFIED IDEOGRAPH
+0xE785	0x8FA3	#CJK UNIFIED IDEOGRAPH
+0xE786	0x8FAD	#CJK UNIFIED IDEOGRAPH
+0xE787	0x8FAF	#CJK UNIFIED IDEOGRAPH
+0xE788	0x8FB7	#CJK UNIFIED IDEOGRAPH
+0xE789	0x8FDA	#CJK UNIFIED IDEOGRAPH
+0xE78A	0x8FE5	#CJK UNIFIED IDEOGRAPH
+0xE78B	0x8FE2	#CJK UNIFIED IDEOGRAPH
+0xE78C	0x8FEA	#CJK UNIFIED IDEOGRAPH
+0xE78D	0x8FEF	#CJK UNIFIED IDEOGRAPH
+0xE78E	0x9087	#CJK UNIFIED IDEOGRAPH
+0xE78F	0x8FF4	#CJK UNIFIED IDEOGRAPH
+0xE790	0x9005	#CJK UNIFIED IDEOGRAPH
+0xE791	0x8FF9	#CJK UNIFIED IDEOGRAPH
+0xE792	0x8FFA	#CJK UNIFIED IDEOGRAPH
+0xE793	0x9011	#CJK UNIFIED IDEOGRAPH
+0xE794	0x9015	#CJK UNIFIED IDEOGRAPH
+0xE795	0x9021	#CJK UNIFIED IDEOGRAPH
+0xE796	0x900D	#CJK UNIFIED IDEOGRAPH
+0xE797	0x901E	#CJK UNIFIED IDEOGRAPH
+0xE798	0x9016	#CJK UNIFIED IDEOGRAPH
+0xE799	0x900B	#CJK UNIFIED IDEOGRAPH
+0xE79A	0x9027	#CJK UNIFIED IDEOGRAPH
+0xE79B	0x9036	#CJK UNIFIED IDEOGRAPH
+0xE79C	0x9035	#CJK UNIFIED IDEOGRAPH
+0xE79D	0x9039	#CJK UNIFIED IDEOGRAPH
+0xE79E	0x8FF8	#CJK UNIFIED IDEOGRAPH
+0xE79F	0x904F	#CJK UNIFIED IDEOGRAPH
+0xE7A0	0x9050	#CJK UNIFIED IDEOGRAPH
+0xE7A1	0x9051	#CJK UNIFIED IDEOGRAPH
+0xE7A2	0x9052	#CJK UNIFIED IDEOGRAPH
+0xE7A3	0x900E	#CJK UNIFIED IDEOGRAPH
+0xE7A4	0x9049	#CJK UNIFIED IDEOGRAPH
+0xE7A5	0x903E	#CJK UNIFIED IDEOGRAPH
+0xE7A6	0x9056	#CJK UNIFIED IDEOGRAPH
+0xE7A7	0x9058	#CJK UNIFIED IDEOGRAPH
+0xE7A8	0x905E	#CJK UNIFIED IDEOGRAPH
+0xE7A9	0x9068	#CJK UNIFIED IDEOGRAPH
+0xE7AA	0x906F	#CJK UNIFIED IDEOGRAPH
+0xE7AB	0x9076	#CJK UNIFIED IDEOGRAPH
+0xE7AC	0x96A8	#CJK UNIFIED IDEOGRAPH
+0xE7AD	0x9072	#CJK UNIFIED IDEOGRAPH
+0xE7AE	0x9082	#CJK UNIFIED IDEOGRAPH
+0xE7AF	0x907D	#CJK UNIFIED IDEOGRAPH
+0xE7B0	0x9081	#CJK UNIFIED IDEOGRAPH
+0xE7B1	0x9080	#CJK UNIFIED IDEOGRAPH
+0xE7B2	0x908A	#CJK UNIFIED IDEOGRAPH
+0xE7B3	0x9089	#CJK UNIFIED IDEOGRAPH
+0xE7B4	0x908F	#CJK UNIFIED IDEOGRAPH
+0xE7B5	0x90A8	#CJK UNIFIED IDEOGRAPH
+0xE7B6	0x90AF	#CJK UNIFIED IDEOGRAPH
+0xE7B7	0x90B1	#CJK UNIFIED IDEOGRAPH
+0xE7B8	0x90B5	#CJK UNIFIED IDEOGRAPH
+0xE7B9	0x90E2	#CJK UNIFIED IDEOGRAPH
+0xE7BA	0x90E4	#CJK UNIFIED IDEOGRAPH
+0xE7BB	0x6248	#CJK UNIFIED IDEOGRAPH
+0xE7BC	0x90DB	#CJK UNIFIED IDEOGRAPH
+0xE7BD	0x9102	#CJK UNIFIED IDEOGRAPH
+0xE7BE	0x9112	#CJK UNIFIED IDEOGRAPH
+0xE7BF	0x9119	#CJK UNIFIED IDEOGRAPH
+0xE7C0	0x9132	#CJK UNIFIED IDEOGRAPH
+0xE7C1	0x9130	#CJK UNIFIED IDEOGRAPH
+0xE7C2	0x914A	#CJK UNIFIED IDEOGRAPH
+0xE7C3	0x9156	#CJK UNIFIED IDEOGRAPH
+0xE7C4	0x9158	#CJK UNIFIED IDEOGRAPH
+0xE7C5	0x9163	#CJK UNIFIED IDEOGRAPH
+0xE7C6	0x9165	#CJK UNIFIED IDEOGRAPH
+0xE7C7	0x9169	#CJK UNIFIED IDEOGRAPH
+0xE7C8	0x9173	#CJK UNIFIED IDEOGRAPH
+0xE7C9	0x9172	#CJK UNIFIED IDEOGRAPH
+0xE7CA	0x918B	#CJK UNIFIED IDEOGRAPH
+0xE7CB	0x9189	#CJK UNIFIED IDEOGRAPH
+0xE7CC	0x9182	#CJK UNIFIED IDEOGRAPH
+0xE7CD	0x91A2	#CJK UNIFIED IDEOGRAPH
+0xE7CE	0x91AB	#CJK UNIFIED IDEOGRAPH
+0xE7CF	0x91AF	#CJK UNIFIED IDEOGRAPH
+0xE7D0	0x91AA	#CJK UNIFIED IDEOGRAPH
+0xE7D1	0x91B5	#CJK UNIFIED IDEOGRAPH
+0xE7D2	0x91B4	#CJK UNIFIED IDEOGRAPH
+0xE7D3	0x91BA	#CJK UNIFIED IDEOGRAPH
+0xE7D4	0x91C0	#CJK UNIFIED IDEOGRAPH
+0xE7D5	0x91C1	#CJK UNIFIED IDEOGRAPH
+0xE7D6	0x91C9	#CJK UNIFIED IDEOGRAPH
+0xE7D7	0x91CB	#CJK UNIFIED IDEOGRAPH
+0xE7D8	0x91D0	#CJK UNIFIED IDEOGRAPH
+0xE7D9	0x91D6	#CJK UNIFIED IDEOGRAPH
+0xE7DA	0x91DF	#CJK UNIFIED IDEOGRAPH
+0xE7DB	0x91E1	#CJK UNIFIED IDEOGRAPH
+0xE7DC	0x91DB	#CJK UNIFIED IDEOGRAPH
+0xE7DD	0x91FC	#CJK UNIFIED IDEOGRAPH
+0xE7DE	0x91F5	#CJK UNIFIED IDEOGRAPH
+0xE7DF	0x91F6	#CJK UNIFIED IDEOGRAPH
+0xE7E0	0x921E	#CJK UNIFIED IDEOGRAPH
+0xE7E1	0x91FF	#CJK UNIFIED IDEOGRAPH
+0xE7E2	0x9214	#CJK UNIFIED IDEOGRAPH
+0xE7E3	0x922C	#CJK UNIFIED IDEOGRAPH
+0xE7E4	0x9215	#CJK UNIFIED IDEOGRAPH
+0xE7E5	0x9211	#CJK UNIFIED IDEOGRAPH
+0xE7E6	0x925E	#CJK UNIFIED IDEOGRAPH
+0xE7E7	0x9257	#CJK UNIFIED IDEOGRAPH
+0xE7E8	0x9245	#CJK UNIFIED IDEOGRAPH
+0xE7E9	0x9249	#CJK UNIFIED IDEOGRAPH
+0xE7EA	0x9264	#CJK UNIFIED IDEOGRAPH
+0xE7EB	0x9248	#CJK UNIFIED IDEOGRAPH
+0xE7EC	0x9295	#CJK UNIFIED IDEOGRAPH
+0xE7ED	0x923F	#CJK UNIFIED IDEOGRAPH
+0xE7EE	0x924B	#CJK UNIFIED IDEOGRAPH
+0xE7EF	0x9250	#CJK UNIFIED IDEOGRAPH
+0xE7F0	0x929C	#CJK UNIFIED IDEOGRAPH
+0xE7F1	0x9296	#CJK UNIFIED IDEOGRAPH
+0xE7F2	0x9293	#CJK UNIFIED IDEOGRAPH
+0xE7F3	0x929B	#CJK UNIFIED IDEOGRAPH
+0xE7F4	0x925A	#CJK UNIFIED IDEOGRAPH
+0xE7F5	0x92CF	#CJK UNIFIED IDEOGRAPH
+0xE7F6	0x92B9	#CJK UNIFIED IDEOGRAPH
+0xE7F7	0x92B7	#CJK UNIFIED IDEOGRAPH
+0xE7F8	0x92E9	#CJK UNIFIED IDEOGRAPH
+0xE7F9	0x930F	#CJK UNIFIED IDEOGRAPH
+0xE7FA	0x92FA	#CJK UNIFIED IDEOGRAPH
+0xE7FB	0x9344	#CJK UNIFIED IDEOGRAPH
+0xE7FC	0x932E	#CJK UNIFIED IDEOGRAPH
+0xE840	0x9319	#CJK UNIFIED IDEOGRAPH
+0xE841	0x9322	#CJK UNIFIED IDEOGRAPH
+0xE842	0x931A	#CJK UNIFIED IDEOGRAPH
+0xE843	0x9323	#CJK UNIFIED IDEOGRAPH
+0xE844	0x933A	#CJK UNIFIED IDEOGRAPH
+0xE845	0x9335	#CJK UNIFIED IDEOGRAPH
+0xE846	0x933B	#CJK UNIFIED IDEOGRAPH
+0xE847	0x935C	#CJK UNIFIED IDEOGRAPH
+0xE848	0x9360	#CJK UNIFIED IDEOGRAPH
+0xE849	0x937C	#CJK UNIFIED IDEOGRAPH
+0xE84A	0x936E	#CJK UNIFIED IDEOGRAPH
+0xE84B	0x9356	#CJK UNIFIED IDEOGRAPH
+0xE84C	0x93B0	#CJK UNIFIED IDEOGRAPH
+0xE84D	0x93AC	#CJK UNIFIED IDEOGRAPH
+0xE84E	0x93AD	#CJK UNIFIED IDEOGRAPH
+0xE84F	0x9394	#CJK UNIFIED IDEOGRAPH
+0xE850	0x93B9	#CJK UNIFIED IDEOGRAPH
+0xE851	0x93D6	#CJK UNIFIED IDEOGRAPH
+0xE852	0x93D7	#CJK UNIFIED IDEOGRAPH
+0xE853	0x93E8	#CJK UNIFIED IDEOGRAPH
+0xE854	0x93E5	#CJK UNIFIED IDEOGRAPH
+0xE855	0x93D8	#CJK UNIFIED IDEOGRAPH
+0xE856	0x93C3	#CJK UNIFIED IDEOGRAPH
+0xE857	0x93DD	#CJK UNIFIED IDEOGRAPH
+0xE858	0x93D0	#CJK UNIFIED IDEOGRAPH
+0xE859	0x93C8	#CJK UNIFIED IDEOGRAPH
+0xE85A	0x93E4	#CJK UNIFIED IDEOGRAPH
+0xE85B	0x941A	#CJK UNIFIED IDEOGRAPH
+0xE85C	0x9414	#CJK UNIFIED IDEOGRAPH
+0xE85D	0x9413	#CJK UNIFIED IDEOGRAPH
+0xE85E	0x9403	#CJK UNIFIED IDEOGRAPH
+0xE85F	0x9407	#CJK UNIFIED IDEOGRAPH
+0xE860	0x9410	#CJK UNIFIED IDEOGRAPH
+0xE861	0x9436	#CJK UNIFIED IDEOGRAPH
+0xE862	0x942B	#CJK UNIFIED IDEOGRAPH
+0xE863	0x9435	#CJK UNIFIED IDEOGRAPH
+0xE864	0x9421	#CJK UNIFIED IDEOGRAPH
+0xE865	0x943A	#CJK UNIFIED IDEOGRAPH
+0xE866	0x9441	#CJK UNIFIED IDEOGRAPH
+0xE867	0x9452	#CJK UNIFIED IDEOGRAPH
+0xE868	0x9444	#CJK UNIFIED IDEOGRAPH
+0xE869	0x945B	#CJK UNIFIED IDEOGRAPH
+0xE86A	0x9460	#CJK UNIFIED IDEOGRAPH
+0xE86B	0x9462	#CJK UNIFIED IDEOGRAPH
+0xE86C	0x945E	#CJK UNIFIED IDEOGRAPH
+0xE86D	0x946A	#CJK UNIFIED IDEOGRAPH
+0xE86E	0x9229	#CJK UNIFIED IDEOGRAPH
+0xE86F	0x9470	#CJK UNIFIED IDEOGRAPH
+0xE870	0x9475	#CJK UNIFIED IDEOGRAPH
+0xE871	0x9477	#CJK UNIFIED IDEOGRAPH
+0xE872	0x947D	#CJK UNIFIED IDEOGRAPH
+0xE873	0x945A	#CJK UNIFIED IDEOGRAPH
+0xE874	0x947C	#CJK UNIFIED IDEOGRAPH
+0xE875	0x947E	#CJK UNIFIED IDEOGRAPH
+0xE876	0x9481	#CJK UNIFIED IDEOGRAPH
+0xE877	0x947F	#CJK UNIFIED IDEOGRAPH
+0xE878	0x9582	#CJK UNIFIED IDEOGRAPH
+0xE879	0x9587	#CJK UNIFIED IDEOGRAPH
+0xE87A	0x958A	#CJK UNIFIED IDEOGRAPH
+0xE87B	0x9594	#CJK UNIFIED IDEOGRAPH
+0xE87C	0x9596	#CJK UNIFIED IDEOGRAPH
+0xE87D	0x9598	#CJK UNIFIED IDEOGRAPH
+0xE87E	0x9599	#CJK UNIFIED IDEOGRAPH
+0xE880	0x95A0	#CJK UNIFIED IDEOGRAPH
+0xE881	0x95A8	#CJK UNIFIED IDEOGRAPH
+0xE882	0x95A7	#CJK UNIFIED IDEOGRAPH
+0xE883	0x95AD	#CJK UNIFIED IDEOGRAPH
+0xE884	0x95BC	#CJK UNIFIED IDEOGRAPH
+0xE885	0x95BB	#CJK UNIFIED IDEOGRAPH
+0xE886	0x95B9	#CJK UNIFIED IDEOGRAPH
+0xE887	0x95BE	#CJK UNIFIED IDEOGRAPH
+0xE888	0x95CA	#CJK UNIFIED IDEOGRAPH
+0xE889	0x6FF6	#CJK UNIFIED IDEOGRAPH
+0xE88A	0x95C3	#CJK UNIFIED IDEOGRAPH
+0xE88B	0x95CD	#CJK UNIFIED IDEOGRAPH
+0xE88C	0x95CC	#CJK UNIFIED IDEOGRAPH
+0xE88D	0x95D5	#CJK UNIFIED IDEOGRAPH
+0xE88E	0x95D4	#CJK UNIFIED IDEOGRAPH
+0xE88F	0x95D6	#CJK UNIFIED IDEOGRAPH
+0xE890	0x95DC	#CJK UNIFIED IDEOGRAPH
+0xE891	0x95E1	#CJK UNIFIED IDEOGRAPH
+0xE892	0x95E5	#CJK UNIFIED IDEOGRAPH
+0xE893	0x95E2	#CJK UNIFIED IDEOGRAPH
+0xE894	0x9621	#CJK UNIFIED IDEOGRAPH
+0xE895	0x9628	#CJK UNIFIED IDEOGRAPH
+0xE896	0x962E	#CJK UNIFIED IDEOGRAPH
+0xE897	0x962F	#CJK UNIFIED IDEOGRAPH
+0xE898	0x9642	#CJK UNIFIED IDEOGRAPH
+0xE899	0x964C	#CJK UNIFIED IDEOGRAPH
+0xE89A	0x964F	#CJK UNIFIED IDEOGRAPH
+0xE89B	0x964B	#CJK UNIFIED IDEOGRAPH
+0xE89C	0x9677	#CJK UNIFIED IDEOGRAPH
+0xE89D	0x965C	#CJK UNIFIED IDEOGRAPH
+0xE89E	0x965E	#CJK UNIFIED IDEOGRAPH
+0xE89F	0x965D	#CJK UNIFIED IDEOGRAPH
+0xE8A0	0x965F	#CJK UNIFIED IDEOGRAPH
+0xE8A1	0x9666	#CJK UNIFIED IDEOGRAPH
+0xE8A2	0x9672	#CJK UNIFIED IDEOGRAPH
+0xE8A3	0x966C	#CJK UNIFIED IDEOGRAPH
+0xE8A4	0x968D	#CJK UNIFIED IDEOGRAPH
+0xE8A5	0x9698	#CJK UNIFIED IDEOGRAPH
+0xE8A6	0x9695	#CJK UNIFIED IDEOGRAPH
+0xE8A7	0x9697	#CJK UNIFIED IDEOGRAPH
+0xE8A8	0x96AA	#CJK UNIFIED IDEOGRAPH
+0xE8A9	0x96A7	#CJK UNIFIED IDEOGRAPH
+0xE8AA	0x96B1	#CJK UNIFIED IDEOGRAPH
+0xE8AB	0x96B2	#CJK UNIFIED IDEOGRAPH
+0xE8AC	0x96B0	#CJK UNIFIED IDEOGRAPH
+0xE8AD	0x96B4	#CJK UNIFIED IDEOGRAPH
+0xE8AE	0x96B6	#CJK UNIFIED IDEOGRAPH
+0xE8AF	0x96B8	#CJK UNIFIED IDEOGRAPH
+0xE8B0	0x96B9	#CJK UNIFIED IDEOGRAPH
+0xE8B1	0x96CE	#CJK UNIFIED IDEOGRAPH
+0xE8B2	0x96CB	#CJK UNIFIED IDEOGRAPH
+0xE8B3	0x96C9	#CJK UNIFIED IDEOGRAPH
+0xE8B4	0x96CD	#CJK UNIFIED IDEOGRAPH
+0xE8B5	0x894D	#CJK UNIFIED IDEOGRAPH
+0xE8B6	0x96DC	#CJK UNIFIED IDEOGRAPH
+0xE8B7	0x970D	#CJK UNIFIED IDEOGRAPH
+0xE8B8	0x96D5	#CJK UNIFIED IDEOGRAPH
+0xE8B9	0x96F9	#CJK UNIFIED IDEOGRAPH
+0xE8BA	0x9704	#CJK UNIFIED IDEOGRAPH
+0xE8BB	0x9706	#CJK UNIFIED IDEOGRAPH
+0xE8BC	0x9708	#CJK UNIFIED IDEOGRAPH
+0xE8BD	0x9713	#CJK UNIFIED IDEOGRAPH
+0xE8BE	0x970E	#CJK UNIFIED IDEOGRAPH
+0xE8BF	0x9711	#CJK UNIFIED IDEOGRAPH
+0xE8C0	0x970F	#CJK UNIFIED IDEOGRAPH
+0xE8C1	0x9716	#CJK UNIFIED IDEOGRAPH
+0xE8C2	0x9719	#CJK UNIFIED IDEOGRAPH
+0xE8C3	0x9724	#CJK UNIFIED IDEOGRAPH
+0xE8C4	0x972A	#CJK UNIFIED IDEOGRAPH
+0xE8C5	0x9730	#CJK UNIFIED IDEOGRAPH
+0xE8C6	0x9739	#CJK UNIFIED IDEOGRAPH
+0xE8C7	0x973D	#CJK UNIFIED IDEOGRAPH
+0xE8C8	0x973E	#CJK UNIFIED IDEOGRAPH
+0xE8C9	0x9744	#CJK UNIFIED IDEOGRAPH
+0xE8CA	0x9746	#CJK UNIFIED IDEOGRAPH
+0xE8CB	0x9748	#CJK UNIFIED IDEOGRAPH
+0xE8CC	0x9742	#CJK UNIFIED IDEOGRAPH
+0xE8CD	0x9749	#CJK UNIFIED IDEOGRAPH
+0xE8CE	0x975C	#CJK UNIFIED IDEOGRAPH
+0xE8CF	0x9760	#CJK UNIFIED IDEOGRAPH
+0xE8D0	0x9764	#CJK UNIFIED IDEOGRAPH
+0xE8D1	0x9766	#CJK UNIFIED IDEOGRAPH
+0xE8D2	0x9768	#CJK UNIFIED IDEOGRAPH
+0xE8D3	0x52D2	#CJK UNIFIED IDEOGRAPH
+0xE8D4	0x976B	#CJK UNIFIED IDEOGRAPH
+0xE8D5	0x9771	#CJK UNIFIED IDEOGRAPH
+0xE8D6	0x9779	#CJK UNIFIED IDEOGRAPH
+0xE8D7	0x9785	#CJK UNIFIED IDEOGRAPH
+0xE8D8	0x977C	#CJK UNIFIED IDEOGRAPH
+0xE8D9	0x9781	#CJK UNIFIED IDEOGRAPH
+0xE8DA	0x977A	#CJK UNIFIED IDEOGRAPH
+0xE8DB	0x9786	#CJK UNIFIED IDEOGRAPH
+0xE8DC	0x978B	#CJK UNIFIED IDEOGRAPH
+0xE8DD	0x978F	#CJK UNIFIED IDEOGRAPH
+0xE8DE	0x9790	#CJK UNIFIED IDEOGRAPH
+0xE8DF	0x979C	#CJK UNIFIED IDEOGRAPH
+0xE8E0	0x97A8	#CJK UNIFIED IDEOGRAPH
+0xE8E1	0x97A6	#CJK UNIFIED IDEOGRAPH
+0xE8E2	0x97A3	#CJK UNIFIED IDEOGRAPH
+0xE8E3	0x97B3	#CJK UNIFIED IDEOGRAPH
+0xE8E4	0x97B4	#CJK UNIFIED IDEOGRAPH
+0xE8E5	0x97C3	#CJK UNIFIED IDEOGRAPH
+0xE8E6	0x97C6	#CJK UNIFIED IDEOGRAPH
+0xE8E7	0x97C8	#CJK UNIFIED IDEOGRAPH
+0xE8E8	0x97CB	#CJK UNIFIED IDEOGRAPH
+0xE8E9	0x97DC	#CJK UNIFIED IDEOGRAPH
+0xE8EA	0x97ED	#CJK UNIFIED IDEOGRAPH
+0xE8EB	0x9F4F	#CJK UNIFIED IDEOGRAPH
+0xE8EC	0x97F2	#CJK UNIFIED IDEOGRAPH
+0xE8ED	0x7ADF	#CJK UNIFIED IDEOGRAPH
+0xE8EE	0x97F6	#CJK UNIFIED IDEOGRAPH
+0xE8EF	0x97F5	#CJK UNIFIED IDEOGRAPH
+0xE8F0	0x980F	#CJK UNIFIED IDEOGRAPH
+0xE8F1	0x980C	#CJK UNIFIED IDEOGRAPH
+0xE8F2	0x9838	#CJK UNIFIED IDEOGRAPH
+0xE8F3	0x9824	#CJK UNIFIED IDEOGRAPH
+0xE8F4	0x9821	#CJK UNIFIED IDEOGRAPH
+0xE8F5	0x9837	#CJK UNIFIED IDEOGRAPH
+0xE8F6	0x983D	#CJK UNIFIED IDEOGRAPH
+0xE8F7	0x9846	#CJK UNIFIED IDEOGRAPH
+0xE8F8	0x984F	#CJK UNIFIED IDEOGRAPH
+0xE8F9	0x984B	#CJK UNIFIED IDEOGRAPH
+0xE8FA	0x986B	#CJK UNIFIED IDEOGRAPH
+0xE8FB	0x986F	#CJK UNIFIED IDEOGRAPH
+0xE8FC	0x9870	#CJK UNIFIED IDEOGRAPH
+0xE940	0x9871	#CJK UNIFIED IDEOGRAPH
+0xE941	0x9874	#CJK UNIFIED IDEOGRAPH
+0xE942	0x9873	#CJK UNIFIED IDEOGRAPH
+0xE943	0x98AA	#CJK UNIFIED IDEOGRAPH
+0xE944	0x98AF	#CJK UNIFIED IDEOGRAPH
+0xE945	0x98B1	#CJK UNIFIED IDEOGRAPH
+0xE946	0x98B6	#CJK UNIFIED IDEOGRAPH
+0xE947	0x98C4	#CJK UNIFIED IDEOGRAPH
+0xE948	0x98C3	#CJK UNIFIED IDEOGRAPH
+0xE949	0x98C6	#CJK UNIFIED IDEOGRAPH
+0xE94A	0x98E9	#CJK UNIFIED IDEOGRAPH
+0xE94B	0x98EB	#CJK UNIFIED IDEOGRAPH
+0xE94C	0x9903	#CJK UNIFIED IDEOGRAPH
+0xE94D	0x9909	#CJK UNIFIED IDEOGRAPH
+0xE94E	0x9912	#CJK UNIFIED IDEOGRAPH
+0xE94F	0x9914	#CJK UNIFIED IDEOGRAPH
+0xE950	0x9918	#CJK UNIFIED IDEOGRAPH
+0xE951	0x9921	#CJK UNIFIED IDEOGRAPH
+0xE952	0x991D	#CJK UNIFIED IDEOGRAPH
+0xE953	0x991E	#CJK UNIFIED IDEOGRAPH
+0xE954	0x9924	#CJK UNIFIED IDEOGRAPH
+0xE955	0x9920	#CJK UNIFIED IDEOGRAPH
+0xE956	0x992C	#CJK UNIFIED IDEOGRAPH
+0xE957	0x992E	#CJK UNIFIED IDEOGRAPH
+0xE958	0x993D	#CJK UNIFIED IDEOGRAPH
+0xE959	0x993E	#CJK UNIFIED IDEOGRAPH
+0xE95A	0x9942	#CJK UNIFIED IDEOGRAPH
+0xE95B	0x9949	#CJK UNIFIED IDEOGRAPH
+0xE95C	0x9945	#CJK UNIFIED IDEOGRAPH
+0xE95D	0x9950	#CJK UNIFIED IDEOGRAPH
+0xE95E	0x994B	#CJK UNIFIED IDEOGRAPH
+0xE95F	0x9951	#CJK UNIFIED IDEOGRAPH
+0xE960	0x9952	#CJK UNIFIED IDEOGRAPH
+0xE961	0x994C	#CJK UNIFIED IDEOGRAPH
+0xE962	0x9955	#CJK UNIFIED IDEOGRAPH
+0xE963	0x9997	#CJK UNIFIED IDEOGRAPH
+0xE964	0x9998	#CJK UNIFIED IDEOGRAPH
+0xE965	0x99A5	#CJK UNIFIED IDEOGRAPH
+0xE966	0x99AD	#CJK UNIFIED IDEOGRAPH
+0xE967	0x99AE	#CJK UNIFIED IDEOGRAPH
+0xE968	0x99BC	#CJK UNIFIED IDEOGRAPH
+0xE969	0x99DF	#CJK UNIFIED IDEOGRAPH
+0xE96A	0x99DB	#CJK UNIFIED IDEOGRAPH
+0xE96B	0x99DD	#CJK UNIFIED IDEOGRAPH
+0xE96C	0x99D8	#CJK UNIFIED IDEOGRAPH
+0xE96D	0x99D1	#CJK UNIFIED IDEOGRAPH
+0xE96E	0x99ED	#CJK UNIFIED IDEOGRAPH
+0xE96F	0x99EE	#CJK UNIFIED IDEOGRAPH
+0xE970	0x99F1	#CJK UNIFIED IDEOGRAPH
+0xE971	0x99F2	#CJK UNIFIED IDEOGRAPH
+0xE972	0x99FB	#CJK UNIFIED IDEOGRAPH
+0xE973	0x99F8	#CJK UNIFIED IDEOGRAPH
+0xE974	0x9A01	#CJK UNIFIED IDEOGRAPH
+0xE975	0x9A0F	#CJK UNIFIED IDEOGRAPH
+0xE976	0x9A05	#CJK UNIFIED IDEOGRAPH
+0xE977	0x99E2	#CJK UNIFIED IDEOGRAPH
+0xE978	0x9A19	#CJK UNIFIED IDEOGRAPH
+0xE979	0x9A2B	#CJK UNIFIED IDEOGRAPH
+0xE97A	0x9A37	#CJK UNIFIED IDEOGRAPH
+0xE97B	0x9A45	#CJK UNIFIED IDEOGRAPH
+0xE97C	0x9A42	#CJK UNIFIED IDEOGRAPH
+0xE97D	0x9A40	#CJK UNIFIED IDEOGRAPH
+0xE97E	0x9A43	#CJK UNIFIED IDEOGRAPH
+0xE980	0x9A3E	#CJK UNIFIED IDEOGRAPH
+0xE981	0x9A55	#CJK UNIFIED IDEOGRAPH
+0xE982	0x9A4D	#CJK UNIFIED IDEOGRAPH
+0xE983	0x9A5B	#CJK UNIFIED IDEOGRAPH
+0xE984	0x9A57	#CJK UNIFIED IDEOGRAPH
+0xE985	0x9A5F	#CJK UNIFIED IDEOGRAPH
+0xE986	0x9A62	#CJK UNIFIED IDEOGRAPH
+0xE987	0x9A65	#CJK UNIFIED IDEOGRAPH
+0xE988	0x9A64	#CJK UNIFIED IDEOGRAPH
+0xE989	0x9A69	#CJK UNIFIED IDEOGRAPH
+0xE98A	0x9A6B	#CJK UNIFIED IDEOGRAPH
+0xE98B	0x9A6A	#CJK UNIFIED IDEOGRAPH
+0xE98C	0x9AAD	#CJK UNIFIED IDEOGRAPH
+0xE98D	0x9AB0	#CJK UNIFIED IDEOGRAPH
+0xE98E	0x9ABC	#CJK UNIFIED IDEOGRAPH
+0xE98F	0x9AC0	#CJK UNIFIED IDEOGRAPH
+0xE990	0x9ACF	#CJK UNIFIED IDEOGRAPH
+0xE991	0x9AD1	#CJK UNIFIED IDEOGRAPH
+0xE992	0x9AD3	#CJK UNIFIED IDEOGRAPH
+0xE993	0x9AD4	#CJK UNIFIED IDEOGRAPH
+0xE994	0x9ADE	#CJK UNIFIED IDEOGRAPH
+0xE995	0x9ADF	#CJK UNIFIED IDEOGRAPH
+0xE996	0x9AE2	#CJK UNIFIED IDEOGRAPH
+0xE997	0x9AE3	#CJK UNIFIED IDEOGRAPH
+0xE998	0x9AE6	#CJK UNIFIED IDEOGRAPH
+0xE999	0x9AEF	#CJK UNIFIED IDEOGRAPH
+0xE99A	0x9AEB	#CJK UNIFIED IDEOGRAPH
+0xE99B	0x9AEE	#CJK UNIFIED IDEOGRAPH
+0xE99C	0x9AF4	#CJK UNIFIED IDEOGRAPH
+0xE99D	0x9AF1	#CJK UNIFIED IDEOGRAPH
+0xE99E	0x9AF7	#CJK UNIFIED IDEOGRAPH
+0xE99F	0x9AFB	#CJK UNIFIED IDEOGRAPH
+0xE9A0	0x9B06	#CJK UNIFIED IDEOGRAPH
+0xE9A1	0x9B18	#CJK UNIFIED IDEOGRAPH
+0xE9A2	0x9B1A	#CJK UNIFIED IDEOGRAPH
+0xE9A3	0x9B1F	#CJK UNIFIED IDEOGRAPH
+0xE9A4	0x9B22	#CJK UNIFIED IDEOGRAPH
+0xE9A5	0x9B23	#CJK UNIFIED IDEOGRAPH
+0xE9A6	0x9B25	#CJK UNIFIED IDEOGRAPH
+0xE9A7	0x9B27	#CJK UNIFIED IDEOGRAPH
+0xE9A8	0x9B28	#CJK UNIFIED IDEOGRAPH
+0xE9A9	0x9B29	#CJK UNIFIED IDEOGRAPH
+0xE9AA	0x9B2A	#CJK UNIFIED IDEOGRAPH
+0xE9AB	0x9B2E	#CJK UNIFIED IDEOGRAPH
+0xE9AC	0x9B2F	#CJK UNIFIED IDEOGRAPH
+0xE9AD	0x9B32	#CJK UNIFIED IDEOGRAPH
+0xE9AE	0x9B44	#CJK UNIFIED IDEOGRAPH
+0xE9AF	0x9B43	#CJK UNIFIED IDEOGRAPH
+0xE9B0	0x9B4F	#CJK UNIFIED IDEOGRAPH
+0xE9B1	0x9B4D	#CJK UNIFIED IDEOGRAPH
+0xE9B2	0x9B4E	#CJK UNIFIED IDEOGRAPH
+0xE9B3	0x9B51	#CJK UNIFIED IDEOGRAPH
+0xE9B4	0x9B58	#CJK UNIFIED IDEOGRAPH
+0xE9B5	0x9B74	#CJK UNIFIED IDEOGRAPH
+0xE9B6	0x9B93	#CJK UNIFIED IDEOGRAPH
+0xE9B7	0x9B83	#CJK UNIFIED IDEOGRAPH
+0xE9B8	0x9B91	#CJK UNIFIED IDEOGRAPH
+0xE9B9	0x9B96	#CJK UNIFIED IDEOGRAPH
+0xE9BA	0x9B97	#CJK UNIFIED IDEOGRAPH
+0xE9BB	0x9B9F	#CJK UNIFIED IDEOGRAPH
+0xE9BC	0x9BA0	#CJK UNIFIED IDEOGRAPH
+0xE9BD	0x9BA8	#CJK UNIFIED IDEOGRAPH
+0xE9BE	0x9BB4	#CJK UNIFIED IDEOGRAPH
+0xE9BF	0x9BC0	#CJK UNIFIED IDEOGRAPH
+0xE9C0	0x9BCA	#CJK UNIFIED IDEOGRAPH
+0xE9C1	0x9BB9	#CJK UNIFIED IDEOGRAPH
+0xE9C2	0x9BC6	#CJK UNIFIED IDEOGRAPH
+0xE9C3	0x9BCF	#CJK UNIFIED IDEOGRAPH
+0xE9C4	0x9BD1	#CJK UNIFIED IDEOGRAPH
+0xE9C5	0x9BD2	#CJK UNIFIED IDEOGRAPH
+0xE9C6	0x9BE3	#CJK UNIFIED IDEOGRAPH
+0xE9C7	0x9BE2	#CJK UNIFIED IDEOGRAPH
+0xE9C8	0x9BE4	#CJK UNIFIED IDEOGRAPH
+0xE9C9	0x9BD4	#CJK UNIFIED IDEOGRAPH
+0xE9CA	0x9BE1	#CJK UNIFIED IDEOGRAPH
+0xE9CB	0x9C3A	#CJK UNIFIED IDEOGRAPH
+0xE9CC	0x9BF2	#CJK UNIFIED IDEOGRAPH
+0xE9CD	0x9BF1	#CJK UNIFIED IDEOGRAPH
+0xE9CE	0x9BF0	#CJK UNIFIED IDEOGRAPH
+0xE9CF	0x9C15	#CJK UNIFIED IDEOGRAPH
+0xE9D0	0x9C14	#CJK UNIFIED IDEOGRAPH
+0xE9D1	0x9C09	#CJK UNIFIED IDEOGRAPH
+0xE9D2	0x9C13	#CJK UNIFIED IDEOGRAPH
+0xE9D3	0x9C0C	#CJK UNIFIED IDEOGRAPH
+0xE9D4	0x9C06	#CJK UNIFIED IDEOGRAPH
+0xE9D5	0x9C08	#CJK UNIFIED IDEOGRAPH
+0xE9D6	0x9C12	#CJK UNIFIED IDEOGRAPH
+0xE9D7	0x9C0A	#CJK UNIFIED IDEOGRAPH
+0xE9D8	0x9C04	#CJK UNIFIED IDEOGRAPH
+0xE9D9	0x9C2E	#CJK UNIFIED IDEOGRAPH
+0xE9DA	0x9C1B	#CJK UNIFIED IDEOGRAPH
+0xE9DB	0x9C25	#CJK UNIFIED IDEOGRAPH
+0xE9DC	0x9C24	#CJK UNIFIED IDEOGRAPH
+0xE9DD	0x9C21	#CJK UNIFIED IDEOGRAPH
+0xE9DE	0x9C30	#CJK UNIFIED IDEOGRAPH
+0xE9DF	0x9C47	#CJK UNIFIED IDEOGRAPH
+0xE9E0	0x9C32	#CJK UNIFIED IDEOGRAPH
+0xE9E1	0x9C46	#CJK UNIFIED IDEOGRAPH
+0xE9E2	0x9C3E	#CJK UNIFIED IDEOGRAPH
+0xE9E3	0x9C5A	#CJK UNIFIED IDEOGRAPH
+0xE9E4	0x9C60	#CJK UNIFIED IDEOGRAPH
+0xE9E5	0x9C67	#CJK UNIFIED IDEOGRAPH
+0xE9E6	0x9C76	#CJK UNIFIED IDEOGRAPH
+0xE9E7	0x9C78	#CJK UNIFIED IDEOGRAPH
+0xE9E8	0x9CE7	#CJK UNIFIED IDEOGRAPH
+0xE9E9	0x9CEC	#CJK UNIFIED IDEOGRAPH
+0xE9EA	0x9CF0	#CJK UNIFIED IDEOGRAPH
+0xE9EB	0x9D09	#CJK UNIFIED IDEOGRAPH
+0xE9EC	0x9D08	#CJK UNIFIED IDEOGRAPH
+0xE9ED	0x9CEB	#CJK UNIFIED IDEOGRAPH
+0xE9EE	0x9D03	#CJK UNIFIED IDEOGRAPH
+0xE9EF	0x9D06	#CJK UNIFIED IDEOGRAPH
+0xE9F0	0x9D2A	#CJK UNIFIED IDEOGRAPH
+0xE9F1	0x9D26	#CJK UNIFIED IDEOGRAPH
+0xE9F2	0x9DAF	#CJK UNIFIED IDEOGRAPH
+0xE9F3	0x9D23	#CJK UNIFIED IDEOGRAPH
+0xE9F4	0x9D1F	#CJK UNIFIED IDEOGRAPH
+0xE9F5	0x9D44	#CJK UNIFIED IDEOGRAPH
+0xE9F6	0x9D15	#CJK UNIFIED IDEOGRAPH
+0xE9F7	0x9D12	#CJK UNIFIED IDEOGRAPH
+0xE9F8	0x9D41	#CJK UNIFIED IDEOGRAPH
+0xE9F9	0x9D3F	#CJK UNIFIED IDEOGRAPH
+0xE9FA	0x9D3E	#CJK UNIFIED IDEOGRAPH
+0xE9FB	0x9D46	#CJK UNIFIED IDEOGRAPH
+0xE9FC	0x9D48	#CJK UNIFIED IDEOGRAPH
+0xEA40	0x9D5D	#CJK UNIFIED IDEOGRAPH
+0xEA41	0x9D5E	#CJK UNIFIED IDEOGRAPH
+0xEA42	0x9D64	#CJK UNIFIED IDEOGRAPH
+0xEA43	0x9D51	#CJK UNIFIED IDEOGRAPH
+0xEA44	0x9D50	#CJK UNIFIED IDEOGRAPH
+0xEA45	0x9D59	#CJK UNIFIED IDEOGRAPH
+0xEA46	0x9D72	#CJK UNIFIED IDEOGRAPH
+0xEA47	0x9D89	#CJK UNIFIED IDEOGRAPH
+0xEA48	0x9D87	#CJK UNIFIED IDEOGRAPH
+0xEA49	0x9DAB	#CJK UNIFIED IDEOGRAPH
+0xEA4A	0x9D6F	#CJK UNIFIED IDEOGRAPH
+0xEA4B	0x9D7A	#CJK UNIFIED IDEOGRAPH
+0xEA4C	0x9D9A	#CJK UNIFIED IDEOGRAPH
+0xEA4D	0x9DA4	#CJK UNIFIED IDEOGRAPH
+0xEA4E	0x9DA9	#CJK UNIFIED IDEOGRAPH
+0xEA4F	0x9DB2	#CJK UNIFIED IDEOGRAPH
+0xEA50	0x9DC4	#CJK UNIFIED IDEOGRAPH
+0xEA51	0x9DC1	#CJK UNIFIED IDEOGRAPH
+0xEA52	0x9DBB	#CJK UNIFIED IDEOGRAPH
+0xEA53	0x9DB8	#CJK UNIFIED IDEOGRAPH
+0xEA54	0x9DBA	#CJK UNIFIED IDEOGRAPH
+0xEA55	0x9DC6	#CJK UNIFIED IDEOGRAPH
+0xEA56	0x9DCF	#CJK UNIFIED IDEOGRAPH
+0xEA57	0x9DC2	#CJK UNIFIED IDEOGRAPH
+0xEA58	0x9DD9	#CJK UNIFIED IDEOGRAPH
+0xEA59	0x9DD3	#CJK UNIFIED IDEOGRAPH
+0xEA5A	0x9DF8	#CJK UNIFIED IDEOGRAPH
+0xEA5B	0x9DE6	#CJK UNIFIED IDEOGRAPH
+0xEA5C	0x9DED	#CJK UNIFIED IDEOGRAPH
+0xEA5D	0x9DEF	#CJK UNIFIED IDEOGRAPH
+0xEA5E	0x9DFD	#CJK UNIFIED IDEOGRAPH
+0xEA5F	0x9E1A	#CJK UNIFIED IDEOGRAPH
+0xEA60	0x9E1B	#CJK UNIFIED IDEOGRAPH
+0xEA61	0x9E1E	#CJK UNIFIED IDEOGRAPH
+0xEA62	0x9E75	#CJK UNIFIED IDEOGRAPH
+0xEA63	0x9E79	#CJK UNIFIED IDEOGRAPH
+0xEA64	0x9E7D	#CJK UNIFIED IDEOGRAPH
+0xEA65	0x9E81	#CJK UNIFIED IDEOGRAPH
+0xEA66	0x9E88	#CJK UNIFIED IDEOGRAPH
+0xEA67	0x9E8B	#CJK UNIFIED IDEOGRAPH
+0xEA68	0x9E8C	#CJK UNIFIED IDEOGRAPH
+0xEA69	0x9E92	#CJK UNIFIED IDEOGRAPH
+0xEA6A	0x9E95	#CJK UNIFIED IDEOGRAPH
+0xEA6B	0x9E91	#CJK UNIFIED IDEOGRAPH
+0xEA6C	0x9E9D	#CJK UNIFIED IDEOGRAPH
+0xEA6D	0x9EA5	#CJK UNIFIED IDEOGRAPH
+0xEA6E	0x9EA9	#CJK UNIFIED IDEOGRAPH
+0xEA6F	0x9EB8	#CJK UNIFIED IDEOGRAPH
+0xEA70	0x9EAA	#CJK UNIFIED IDEOGRAPH
+0xEA71	0x9EAD	#CJK UNIFIED IDEOGRAPH
+0xEA72	0x9761	#CJK UNIFIED IDEOGRAPH
+0xEA73	0x9ECC	#CJK UNIFIED IDEOGRAPH
+0xEA74	0x9ECE	#CJK UNIFIED IDEOGRAPH
+0xEA75	0x9ECF	#CJK UNIFIED IDEOGRAPH
+0xEA76	0x9ED0	#CJK UNIFIED IDEOGRAPH
+0xEA77	0x9ED4	#CJK UNIFIED IDEOGRAPH
+0xEA78	0x9EDC	#CJK UNIFIED IDEOGRAPH
+0xEA79	0x9EDE	#CJK UNIFIED IDEOGRAPH
+0xEA7A	0x9EDD	#CJK UNIFIED IDEOGRAPH
+0xEA7B	0x9EE0	#CJK UNIFIED IDEOGRAPH
+0xEA7C	0x9EE5	#CJK UNIFIED IDEOGRAPH
+0xEA7D	0x9EE8	#CJK UNIFIED IDEOGRAPH
+0xEA7E	0x9EEF	#CJK UNIFIED IDEOGRAPH
+0xEA80	0x9EF4	#CJK UNIFIED IDEOGRAPH
+0xEA81	0x9EF6	#CJK UNIFIED IDEOGRAPH
+0xEA82	0x9EF7	#CJK UNIFIED IDEOGRAPH
+0xEA83	0x9EF9	#CJK UNIFIED IDEOGRAPH
+0xEA84	0x9EFB	#CJK UNIFIED IDEOGRAPH
+0xEA85	0x9EFC	#CJK UNIFIED IDEOGRAPH
+0xEA86	0x9EFD	#CJK UNIFIED IDEOGRAPH
+0xEA87	0x9F07	#CJK UNIFIED IDEOGRAPH
+0xEA88	0x9F08	#CJK UNIFIED IDEOGRAPH
+0xEA89	0x76B7	#CJK UNIFIED IDEOGRAPH
+0xEA8A	0x9F15	#CJK UNIFIED IDEOGRAPH
+0xEA8B	0x9F21	#CJK UNIFIED IDEOGRAPH
+0xEA8C	0x9F2C	#CJK UNIFIED IDEOGRAPH
+0xEA8D	0x9F3E	#CJK UNIFIED IDEOGRAPH
+0xEA8E	0x9F4A	#CJK UNIFIED IDEOGRAPH
+0xEA8F	0x9F52	#CJK UNIFIED IDEOGRAPH
+0xEA90	0x9F54	#CJK UNIFIED IDEOGRAPH
+0xEA91	0x9F63	#CJK UNIFIED IDEOGRAPH
+0xEA92	0x9F5F	#CJK UNIFIED IDEOGRAPH
+0xEA93	0x9F60	#CJK UNIFIED IDEOGRAPH
+0xEA94	0x9F61	#CJK UNIFIED IDEOGRAPH
+0xEA95	0x9F66	#CJK UNIFIED IDEOGRAPH
+0xEA96	0x9F67	#CJK UNIFIED IDEOGRAPH
+0xEA97	0x9F6C	#CJK UNIFIED IDEOGRAPH
+0xEA98	0x9F6A	#CJK UNIFIED IDEOGRAPH
+0xEA99	0x9F77	#CJK UNIFIED IDEOGRAPH
+0xEA9A	0x9F72	#CJK UNIFIED IDEOGRAPH
+0xEA9B	0x9F76	#CJK UNIFIED IDEOGRAPH
+0xEA9C	0x9F95	#CJK UNIFIED IDEOGRAPH
+0xEA9D	0x9F9C	#CJK UNIFIED IDEOGRAPH
+0xEA9E	0x9FA0	#CJK UNIFIED IDEOGRAPH
+0xEA9F	0x582F	#CJK UNIFIED IDEOGRAPH
+0xEAA0	0x69C7	#CJK UNIFIED IDEOGRAPH
+0xEAA1	0x9059	#CJK UNIFIED IDEOGRAPH
+0xEAA2	0x7464	#CJK UNIFIED IDEOGRAPH
+0xEAA3	0x51DC	#CJK UNIFIED IDEOGRAPH
+0xEAA4	0x7199	#CJK UNIFIED IDEOGRAPH
+0xED40	0x7E8A	#CJK UNIFIED IDEOGRAPH
+0xED41	0x891C	#CJK UNIFIED IDEOGRAPH
+0xED42	0x9348	#CJK UNIFIED IDEOGRAPH
+0xED43	0x9288	#CJK UNIFIED IDEOGRAPH
+0xED44	0x84DC	#CJK UNIFIED IDEOGRAPH
+0xED45	0x4FC9	#CJK UNIFIED IDEOGRAPH
+0xED46	0x70BB	#CJK UNIFIED IDEOGRAPH
+0xED47	0x6631	#CJK UNIFIED IDEOGRAPH
+0xED48	0x68C8	#CJK UNIFIED IDEOGRAPH
+0xED49	0x92F9	#CJK UNIFIED IDEOGRAPH
+0xED4A	0x66FB	#CJK UNIFIED IDEOGRAPH
+0xED4B	0x5F45	#CJK UNIFIED IDEOGRAPH
+0xED4C	0x4E28	#CJK UNIFIED IDEOGRAPH
+0xED4D	0x4EE1	#CJK UNIFIED IDEOGRAPH
+0xED4E	0x4EFC	#CJK UNIFIED IDEOGRAPH
+0xED4F	0x4F00	#CJK UNIFIED IDEOGRAPH
+0xED50	0x4F03	#CJK UNIFIED IDEOGRAPH
+0xED51	0x4F39	#CJK UNIFIED IDEOGRAPH
+0xED52	0x4F56	#CJK UNIFIED IDEOGRAPH
+0xED53	0x4F92	#CJK UNIFIED IDEOGRAPH
+0xED54	0x4F8A	#CJK UNIFIED IDEOGRAPH
+0xED55	0x4F9A	#CJK UNIFIED IDEOGRAPH
+0xED56	0x4F94	#CJK UNIFIED IDEOGRAPH
+0xED57	0x4FCD	#CJK UNIFIED IDEOGRAPH
+0xED58	0x5040	#CJK UNIFIED IDEOGRAPH
+0xED59	0x5022	#CJK UNIFIED IDEOGRAPH
+0xED5A	0x4FFF	#CJK UNIFIED IDEOGRAPH
+0xED5B	0x501E	#CJK UNIFIED IDEOGRAPH
+0xED5C	0x5046	#CJK UNIFIED IDEOGRAPH
+0xED5D	0x5070	#CJK UNIFIED IDEOGRAPH
+0xED5E	0x5042	#CJK UNIFIED IDEOGRAPH
+0xED5F	0x5094	#CJK UNIFIED IDEOGRAPH
+0xED60	0x50F4	#CJK UNIFIED IDEOGRAPH
+0xED61	0x50D8	#CJK UNIFIED IDEOGRAPH
+0xED62	0x514A	#CJK UNIFIED IDEOGRAPH
+0xED63	0x5164	#CJK UNIFIED IDEOGRAPH
+0xED64	0x519D	#CJK UNIFIED IDEOGRAPH
+0xED65	0x51BE	#CJK UNIFIED IDEOGRAPH
+0xED66	0x51EC	#CJK UNIFIED IDEOGRAPH
+0xED67	0x5215	#CJK UNIFIED IDEOGRAPH
+0xED68	0x529C	#CJK UNIFIED IDEOGRAPH
+0xED69	0x52A6	#CJK UNIFIED IDEOGRAPH
+0xED6A	0x52C0	#CJK UNIFIED IDEOGRAPH
+0xED6B	0x52DB	#CJK UNIFIED IDEOGRAPH
+0xED6C	0x5300	#CJK UNIFIED IDEOGRAPH
+0xED6D	0x5307	#CJK UNIFIED IDEOGRAPH
+0xED6E	0x5324	#CJK UNIFIED IDEOGRAPH
+0xED6F	0x5372	#CJK UNIFIED IDEOGRAPH
+0xED70	0x5393	#CJK UNIFIED IDEOGRAPH
+0xED71	0x53B2	#CJK UNIFIED IDEOGRAPH
+0xED72	0x53DD	#CJK UNIFIED IDEOGRAPH
+0xED73	0xFA0E	#CJK COMPATIBILITY IDEOGRAPH
+0xED74	0x549C	#CJK UNIFIED IDEOGRAPH
+0xED75	0x548A	#CJK UNIFIED IDEOGRAPH
+0xED76	0x54A9	#CJK UNIFIED IDEOGRAPH
+0xED77	0x54FF	#CJK UNIFIED IDEOGRAPH
+0xED78	0x5586	#CJK UNIFIED IDEOGRAPH
+0xED79	0x5759	#CJK UNIFIED IDEOGRAPH
+0xED7A	0x5765	#CJK UNIFIED IDEOGRAPH
+0xED7B	0x57AC	#CJK UNIFIED IDEOGRAPH
+0xED7C	0x57C8	#CJK UNIFIED IDEOGRAPH
+0xED7D	0x57C7	#CJK UNIFIED IDEOGRAPH
+0xED7E	0xFA0F	#CJK COMPATIBILITY IDEOGRAPH
+0xED80	0xFA10	#CJK COMPATIBILITY IDEOGRAPH
+0xED81	0x589E	#CJK UNIFIED IDEOGRAPH
+0xED82	0x58B2	#CJK UNIFIED IDEOGRAPH
+0xED83	0x590B	#CJK UNIFIED IDEOGRAPH
+0xED84	0x5953	#CJK UNIFIED IDEOGRAPH
+0xED85	0x595B	#CJK UNIFIED IDEOGRAPH
+0xED86	0x595D	#CJK UNIFIED IDEOGRAPH
+0xED87	0x5963	#CJK UNIFIED IDEOGRAPH
+0xED88	0x59A4	#CJK UNIFIED IDEOGRAPH
+0xED89	0x59BA	#CJK UNIFIED IDEOGRAPH
+0xED8A	0x5B56	#CJK UNIFIED IDEOGRAPH
+0xED8B	0x5BC0	#CJK UNIFIED IDEOGRAPH
+0xED8C	0x752F	#CJK UNIFIED IDEOGRAPH
+0xED8D	0x5BD8	#CJK UNIFIED IDEOGRAPH
+0xED8E	0x5BEC	#CJK UNIFIED IDEOGRAPH
+0xED8F	0x5C1E	#CJK UNIFIED IDEOGRAPH
+0xED90	0x5CA6	#CJK UNIFIED IDEOGRAPH
+0xED91	0x5CBA	#CJK UNIFIED IDEOGRAPH
+0xED92	0x5CF5	#CJK UNIFIED IDEOGRAPH
+0xED93	0x5D27	#CJK UNIFIED IDEOGRAPH
+0xED94	0x5D53	#CJK UNIFIED IDEOGRAPH
+0xED95	0xFA11	#CJK COMPATIBILITY IDEOGRAPH
+0xED96	0x5D42	#CJK UNIFIED IDEOGRAPH
+0xED97	0x5D6D	#CJK UNIFIED IDEOGRAPH
+0xED98	0x5DB8	#CJK UNIFIED IDEOGRAPH
+0xED99	0x5DB9	#CJK UNIFIED IDEOGRAPH
+0xED9A	0x5DD0	#CJK UNIFIED IDEOGRAPH
+0xED9B	0x5F21	#CJK UNIFIED IDEOGRAPH
+0xED9C	0x5F34	#CJK UNIFIED IDEOGRAPH
+0xED9D	0x5F67	#CJK UNIFIED IDEOGRAPH
+0xED9E	0x5FB7	#CJK UNIFIED IDEOGRAPH
+0xED9F	0x5FDE	#CJK UNIFIED IDEOGRAPH
+0xEDA0	0x605D	#CJK UNIFIED IDEOGRAPH
+0xEDA1	0x6085	#CJK UNIFIED IDEOGRAPH
+0xEDA2	0x608A	#CJK UNIFIED IDEOGRAPH
+0xEDA3	0x60DE	#CJK UNIFIED IDEOGRAPH
+0xEDA4	0x60D5	#CJK UNIFIED IDEOGRAPH
+0xEDA5	0x6120	#CJK UNIFIED IDEOGRAPH
+0xEDA6	0x60F2	#CJK UNIFIED IDEOGRAPH
+0xEDA7	0x6111	#CJK UNIFIED IDEOGRAPH
+0xEDA8	0x6137	#CJK UNIFIED IDEOGRAPH
+0xEDA9	0x6130	#CJK UNIFIED IDEOGRAPH
+0xEDAA	0x6198	#CJK UNIFIED IDEOGRAPH
+0xEDAB	0x6213	#CJK UNIFIED IDEOGRAPH
+0xEDAC	0x62A6	#CJK UNIFIED IDEOGRAPH
+0xEDAD	0x63F5	#CJK UNIFIED IDEOGRAPH
+0xEDAE	0x6460	#CJK UNIFIED IDEOGRAPH
+0xEDAF	0x649D	#CJK UNIFIED IDEOGRAPH
+0xEDB0	0x64CE	#CJK UNIFIED IDEOGRAPH
+0xEDB1	0x654E	#CJK UNIFIED IDEOGRAPH
+0xEDB2	0x6600	#CJK UNIFIED IDEOGRAPH
+0xEDB3	0x6615	#CJK UNIFIED IDEOGRAPH
+0xEDB4	0x663B	#CJK UNIFIED IDEOGRAPH
+0xEDB5	0x6609	#CJK UNIFIED IDEOGRAPH
+0xEDB6	0x662E	#CJK UNIFIED IDEOGRAPH
+0xEDB7	0x661E	#CJK UNIFIED IDEOGRAPH
+0xEDB8	0x6624	#CJK UNIFIED IDEOGRAPH
+0xEDB9	0x6665	#CJK UNIFIED IDEOGRAPH
+0xEDBA	0x6657	#CJK UNIFIED IDEOGRAPH
+0xEDBB	0x6659	#CJK UNIFIED IDEOGRAPH
+0xEDBC	0xFA12	#CJK COMPATIBILITY IDEOGRAPH
+0xEDBD	0x6673	#CJK UNIFIED IDEOGRAPH
+0xEDBE	0x6699	#CJK UNIFIED IDEOGRAPH
+0xEDBF	0x66A0	#CJK UNIFIED IDEOGRAPH
+0xEDC0	0x66B2	#CJK UNIFIED IDEOGRAPH
+0xEDC1	0x66BF	#CJK UNIFIED IDEOGRAPH
+0xEDC2	0x66FA	#CJK UNIFIED IDEOGRAPH
+0xEDC3	0x670E	#CJK UNIFIED IDEOGRAPH
+0xEDC4	0xF929	#CJK COMPATIBILITY IDEOGRAPH
+0xEDC5	0x6766	#CJK UNIFIED IDEOGRAPH
+0xEDC6	0x67BB	#CJK UNIFIED IDEOGRAPH
+0xEDC7	0x6852	#CJK UNIFIED IDEOGRAPH
+0xEDC8	0x67C0	#CJK UNIFIED IDEOGRAPH
+0xEDC9	0x6801	#CJK UNIFIED IDEOGRAPH
+0xEDCA	0x6844	#CJK UNIFIED IDEOGRAPH
+0xEDCB	0x68CF	#CJK UNIFIED IDEOGRAPH
+0xEDCC	0xFA13	#CJK COMPATIBILITY IDEOGRAPH
+0xEDCD	0x6968	#CJK UNIFIED IDEOGRAPH
+0xEDCE	0xFA14	#CJK COMPATIBILITY IDEOGRAPH
+0xEDCF	0x6998	#CJK UNIFIED IDEOGRAPH
+0xEDD0	0x69E2	#CJK UNIFIED IDEOGRAPH
+0xEDD1	0x6A30	#CJK UNIFIED IDEOGRAPH
+0xEDD2	0x6A6B	#CJK UNIFIED IDEOGRAPH
+0xEDD3	0x6A46	#CJK UNIFIED IDEOGRAPH
+0xEDD4	0x6A73	#CJK UNIFIED IDEOGRAPH
+0xEDD5	0x6A7E	#CJK UNIFIED IDEOGRAPH
+0xEDD6	0x6AE2	#CJK UNIFIED IDEOGRAPH
+0xEDD7	0x6AE4	#CJK UNIFIED IDEOGRAPH
+0xEDD8	0x6BD6	#CJK UNIFIED IDEOGRAPH
+0xEDD9	0x6C3F	#CJK UNIFIED IDEOGRAPH
+0xEDDA	0x6C5C	#CJK UNIFIED IDEOGRAPH
+0xEDDB	0x6C86	#CJK UNIFIED IDEOGRAPH
+0xEDDC	0x6C6F	#CJK UNIFIED IDEOGRAPH
+0xEDDD	0x6CDA	#CJK UNIFIED IDEOGRAPH
+0xEDDE	0x6D04	#CJK UNIFIED IDEOGRAPH
+0xEDDF	0x6D87	#CJK UNIFIED IDEOGRAPH
+0xEDE0	0x6D6F	#CJK UNIFIED IDEOGRAPH
+0xEDE1	0x6D96	#CJK UNIFIED IDEOGRAPH
+0xEDE2	0x6DAC	#CJK UNIFIED IDEOGRAPH
+0xEDE3	0x6DCF	#CJK UNIFIED IDEOGRAPH
+0xEDE4	0x6DF8	#CJK UNIFIED IDEOGRAPH
+0xEDE5	0x6DF2	#CJK UNIFIED IDEOGRAPH
+0xEDE6	0x6DFC	#CJK UNIFIED IDEOGRAPH
+0xEDE7	0x6E39	#CJK UNIFIED IDEOGRAPH
+0xEDE8	0x6E5C	#CJK UNIFIED IDEOGRAPH
+0xEDE9	0x6E27	#CJK UNIFIED IDEOGRAPH
+0xEDEA	0x6E3C	#CJK UNIFIED IDEOGRAPH
+0xEDEB	0x6EBF	#CJK UNIFIED IDEOGRAPH
+0xEDEC	0x6F88	#CJK UNIFIED IDEOGRAPH
+0xEDED	0x6FB5	#CJK UNIFIED IDEOGRAPH
+0xEDEE	0x6FF5	#CJK UNIFIED IDEOGRAPH
+0xEDEF	0x7005	#CJK UNIFIED IDEOGRAPH
+0xEDF0	0x7007	#CJK UNIFIED IDEOGRAPH
+0xEDF1	0x7028	#CJK UNIFIED IDEOGRAPH
+0xEDF2	0x7085	#CJK UNIFIED IDEOGRAPH
+0xEDF3	0x70AB	#CJK UNIFIED IDEOGRAPH
+0xEDF4	0x710F	#CJK UNIFIED IDEOGRAPH
+0xEDF5	0x7104	#CJK UNIFIED IDEOGRAPH
+0xEDF6	0x715C	#CJK UNIFIED IDEOGRAPH
+0xEDF7	0x7146	#CJK UNIFIED IDEOGRAPH
+0xEDF8	0x7147	#CJK UNIFIED IDEOGRAPH
+0xEDF9	0xFA15	#CJK COMPATIBILITY IDEOGRAPH
+0xEDFA	0x71C1	#CJK UNIFIED IDEOGRAPH
+0xEDFB	0x71FE	#CJK UNIFIED IDEOGRAPH
+0xEDFC	0x72B1	#CJK UNIFIED IDEOGRAPH
+0xEE40	0x72BE	#CJK UNIFIED IDEOGRAPH
+0xEE41	0x7324	#CJK UNIFIED IDEOGRAPH
+0xEE42	0xFA16	#CJK COMPATIBILITY IDEOGRAPH
+0xEE43	0x7377	#CJK UNIFIED IDEOGRAPH
+0xEE44	0x73BD	#CJK UNIFIED IDEOGRAPH
+0xEE45	0x73C9	#CJK UNIFIED IDEOGRAPH
+0xEE46	0x73D6	#CJK UNIFIED IDEOGRAPH
+0xEE47	0x73E3	#CJK UNIFIED IDEOGRAPH
+0xEE48	0x73D2	#CJK UNIFIED IDEOGRAPH
+0xEE49	0x7407	#CJK UNIFIED IDEOGRAPH
+0xEE4A	0x73F5	#CJK UNIFIED IDEOGRAPH
+0xEE4B	0x7426	#CJK UNIFIED IDEOGRAPH
+0xEE4C	0x742A	#CJK UNIFIED IDEOGRAPH
+0xEE4D	0x7429	#CJK UNIFIED IDEOGRAPH
+0xEE4E	0x742E	#CJK UNIFIED IDEOGRAPH
+0xEE4F	0x7462	#CJK UNIFIED IDEOGRAPH
+0xEE50	0x7489	#CJK UNIFIED IDEOGRAPH
+0xEE51	0x749F	#CJK UNIFIED IDEOGRAPH
+0xEE52	0x7501	#CJK UNIFIED IDEOGRAPH
+0xEE53	0x756F	#CJK UNIFIED IDEOGRAPH
+0xEE54	0x7682	#CJK UNIFIED IDEOGRAPH
+0xEE55	0x769C	#CJK UNIFIED IDEOGRAPH
+0xEE56	0x769E	#CJK UNIFIED IDEOGRAPH
+0xEE57	0x769B	#CJK UNIFIED IDEOGRAPH
+0xEE58	0x76A6	#CJK UNIFIED IDEOGRAPH
+0xEE59	0xFA17	#CJK COMPATIBILITY IDEOGRAPH
+0xEE5A	0x7746	#CJK UNIFIED IDEOGRAPH
+0xEE5B	0x52AF	#CJK UNIFIED IDEOGRAPH
+0xEE5C	0x7821	#CJK UNIFIED IDEOGRAPH
+0xEE5D	0x784E	#CJK UNIFIED IDEOGRAPH
+0xEE5E	0x7864	#CJK UNIFIED IDEOGRAPH
+0xEE5F	0x787A	#CJK UNIFIED IDEOGRAPH
+0xEE60	0x7930	#CJK UNIFIED IDEOGRAPH
+0xEE61	0xFA18	#CJK COMPATIBILITY IDEOGRAPH
+0xEE62	0xFA19	#CJK COMPATIBILITY IDEOGRAPH
+0xEE63	0xFA1A	#CJK COMPATIBILITY IDEOGRAPH
+0xEE64	0x7994	#CJK UNIFIED IDEOGRAPH
+0xEE65	0xFA1B	#CJK COMPATIBILITY IDEOGRAPH
+0xEE66	0x799B	#CJK UNIFIED IDEOGRAPH
+0xEE67	0x7AD1	#CJK UNIFIED IDEOGRAPH
+0xEE68	0x7AE7	#CJK UNIFIED IDEOGRAPH
+0xEE69	0xFA1C	#CJK COMPATIBILITY IDEOGRAPH
+0xEE6A	0x7AEB	#CJK UNIFIED IDEOGRAPH
+0xEE6B	0x7B9E	#CJK UNIFIED IDEOGRAPH
+0xEE6C	0xFA1D	#CJK COMPATIBILITY IDEOGRAPH
+0xEE6D	0x7D48	#CJK UNIFIED IDEOGRAPH
+0xEE6E	0x7D5C	#CJK UNIFIED IDEOGRAPH
+0xEE6F	0x7DB7	#CJK UNIFIED IDEOGRAPH
+0xEE70	0x7DA0	#CJK UNIFIED IDEOGRAPH
+0xEE71	0x7DD6	#CJK UNIFIED IDEOGRAPH
+0xEE72	0x7E52	#CJK UNIFIED IDEOGRAPH
+0xEE73	0x7F47	#CJK UNIFIED IDEOGRAPH
+0xEE74	0x7FA1	#CJK UNIFIED IDEOGRAPH
+0xEE75	0xFA1E	#CJK COMPATIBILITY IDEOGRAPH
+0xEE76	0x8301	#CJK UNIFIED IDEOGRAPH
+0xEE77	0x8362	#CJK UNIFIED IDEOGRAPH
+0xEE78	0x837F	#CJK UNIFIED IDEOGRAPH
+0xEE79	0x83C7	#CJK UNIFIED IDEOGRAPH
+0xEE7A	0x83F6	#CJK UNIFIED IDEOGRAPH
+0xEE7B	0x8448	#CJK UNIFIED IDEOGRAPH
+0xEE7C	0x84B4	#CJK UNIFIED IDEOGRAPH
+0xEE7D	0x8553	#CJK UNIFIED IDEOGRAPH
+0xEE7E	0x8559	#CJK UNIFIED IDEOGRAPH
+0xEE80	0x856B	#CJK UNIFIED IDEOGRAPH
+0xEE81	0xFA1F	#CJK COMPATIBILITY IDEOGRAPH
+0xEE82	0x85B0	#CJK UNIFIED IDEOGRAPH
+0xEE83	0xFA20	#CJK COMPATIBILITY IDEOGRAPH
+0xEE84	0xFA21	#CJK COMPATIBILITY IDEOGRAPH
+0xEE85	0x8807	#CJK UNIFIED IDEOGRAPH
+0xEE86	0x88F5	#CJK UNIFIED IDEOGRAPH
+0xEE87	0x8A12	#CJK UNIFIED IDEOGRAPH
+0xEE88	0x8A37	#CJK UNIFIED IDEOGRAPH
+0xEE89	0x8A79	#CJK UNIFIED IDEOGRAPH
+0xEE8A	0x8AA7	#CJK UNIFIED IDEOGRAPH
+0xEE8B	0x8ABE	#CJK UNIFIED IDEOGRAPH
+0xEE8C	0x8ADF	#CJK UNIFIED IDEOGRAPH
+0xEE8D	0xFA22	#CJK COMPATIBILITY IDEOGRAPH
+0xEE8E	0x8AF6	#CJK UNIFIED IDEOGRAPH
+0xEE8F	0x8B53	#CJK UNIFIED IDEOGRAPH
+0xEE90	0x8B7F	#CJK UNIFIED IDEOGRAPH
+0xEE91	0x8CF0	#CJK UNIFIED IDEOGRAPH
+0xEE92	0x8CF4	#CJK UNIFIED IDEOGRAPH
+0xEE93	0x8D12	#CJK UNIFIED IDEOGRAPH
+0xEE94	0x8D76	#CJK UNIFIED IDEOGRAPH
+0xEE95	0xFA23	#CJK COMPATIBILITY IDEOGRAPH
+0xEE96	0x8ECF	#CJK UNIFIED IDEOGRAPH
+0xEE97	0xFA24	#CJK COMPATIBILITY IDEOGRAPH
+0xEE98	0xFA25	#CJK COMPATIBILITY IDEOGRAPH
+0xEE99	0x9067	#CJK UNIFIED IDEOGRAPH
+0xEE9A	0x90DE	#CJK UNIFIED IDEOGRAPH
+0xEE9B	0xFA26	#CJK COMPATIBILITY IDEOGRAPH
+0xEE9C	0x9115	#CJK UNIFIED IDEOGRAPH
+0xEE9D	0x9127	#CJK UNIFIED IDEOGRAPH
+0xEE9E	0x91DA	#CJK UNIFIED IDEOGRAPH
+0xEE9F	0x91D7	#CJK UNIFIED IDEOGRAPH
+0xEEA0	0x91DE	#CJK UNIFIED IDEOGRAPH
+0xEEA1	0x91ED	#CJK UNIFIED IDEOGRAPH
+0xEEA2	0x91EE	#CJK UNIFIED IDEOGRAPH
+0xEEA3	0x91E4	#CJK UNIFIED IDEOGRAPH
+0xEEA4	0x91E5	#CJK UNIFIED IDEOGRAPH
+0xEEA5	0x9206	#CJK UNIFIED IDEOGRAPH
+0xEEA6	0x9210	#CJK UNIFIED IDEOGRAPH
+0xEEA7	0x920A	#CJK UNIFIED IDEOGRAPH
+0xEEA8	0x923A	#CJK UNIFIED IDEOGRAPH
+0xEEA9	0x9240	#CJK UNIFIED IDEOGRAPH
+0xEEAA	0x923C	#CJK UNIFIED IDEOGRAPH
+0xEEAB	0x924E	#CJK UNIFIED IDEOGRAPH
+0xEEAC	0x9259	#CJK UNIFIED IDEOGRAPH
+0xEEAD	0x9251	#CJK UNIFIED IDEOGRAPH
+0xEEAE	0x9239	#CJK UNIFIED IDEOGRAPH
+0xEEAF	0x9267	#CJK UNIFIED IDEOGRAPH
+0xEEB0	0x92A7	#CJK UNIFIED IDEOGRAPH
+0xEEB1	0x9277	#CJK UNIFIED IDEOGRAPH
+0xEEB2	0x9278	#CJK UNIFIED IDEOGRAPH
+0xEEB3	0x92E7	#CJK UNIFIED IDEOGRAPH
+0xEEB4	0x92D7	#CJK UNIFIED IDEOGRAPH
+0xEEB5	0x92D9	#CJK UNIFIED IDEOGRAPH
+0xEEB6	0x92D0	#CJK UNIFIED IDEOGRAPH
+0xEEB7	0xFA27	#CJK COMPATIBILITY IDEOGRAPH
+0xEEB8	0x92D5	#CJK UNIFIED IDEOGRAPH
+0xEEB9	0x92E0	#CJK UNIFIED IDEOGRAPH
+0xEEBA	0x92D3	#CJK UNIFIED IDEOGRAPH
+0xEEBB	0x9325	#CJK UNIFIED IDEOGRAPH
+0xEEBC	0x9321	#CJK UNIFIED IDEOGRAPH
+0xEEBD	0x92FB	#CJK UNIFIED IDEOGRAPH
+0xEEBE	0xFA28	#CJK COMPATIBILITY IDEOGRAPH
+0xEEBF	0x931E	#CJK UNIFIED IDEOGRAPH
+0xEEC0	0x92FF	#CJK UNIFIED IDEOGRAPH
+0xEEC1	0x931D	#CJK UNIFIED IDEOGRAPH
+0xEEC2	0x9302	#CJK UNIFIED IDEOGRAPH
+0xEEC3	0x9370	#CJK UNIFIED IDEOGRAPH
+0xEEC4	0x9357	#CJK UNIFIED IDEOGRAPH
+0xEEC5	0x93A4	#CJK UNIFIED IDEOGRAPH
+0xEEC6	0x93C6	#CJK UNIFIED IDEOGRAPH
+0xEEC7	0x93DE	#CJK UNIFIED IDEOGRAPH
+0xEEC8	0x93F8	#CJK UNIFIED IDEOGRAPH
+0xEEC9	0x9431	#CJK UNIFIED IDEOGRAPH
+0xEECA	0x9445	#CJK UNIFIED IDEOGRAPH
+0xEECB	0x9448	#CJK UNIFIED IDEOGRAPH
+0xEECC	0x9592	#CJK UNIFIED IDEOGRAPH
+0xEECD	0xF9DC	#CJK COMPATIBILITY IDEOGRAPH
+0xEECE	0xFA29	#CJK COMPATIBILITY IDEOGRAPH
+0xEECF	0x969D	#CJK UNIFIED IDEOGRAPH
+0xEED0	0x96AF	#CJK UNIFIED IDEOGRAPH
+0xEED1	0x9733	#CJK UNIFIED IDEOGRAPH
+0xEED2	0x973B	#CJK UNIFIED IDEOGRAPH
+0xEED3	0x9743	#CJK UNIFIED IDEOGRAPH
+0xEED4	0x974D	#CJK UNIFIED IDEOGRAPH
+0xEED5	0x974F	#CJK UNIFIED IDEOGRAPH
+0xEED6	0x9751	#CJK UNIFIED IDEOGRAPH
+0xEED7	0x9755	#CJK UNIFIED IDEOGRAPH
+0xEED8	0x9857	#CJK UNIFIED IDEOGRAPH
+0xEED9	0x9865	#CJK UNIFIED IDEOGRAPH
+0xEEDA	0xFA2A	#CJK COMPATIBILITY IDEOGRAPH
+0xEEDB	0xFA2B	#CJK COMPATIBILITY IDEOGRAPH
+0xEEDC	0x9927	#CJK UNIFIED IDEOGRAPH
+0xEEDD	0xFA2C	#CJK COMPATIBILITY IDEOGRAPH
+0xEEDE	0x999E	#CJK UNIFIED IDEOGRAPH
+0xEEDF	0x9A4E	#CJK UNIFIED IDEOGRAPH
+0xEEE0	0x9AD9	#CJK UNIFIED IDEOGRAPH
+0xEEE1	0x9ADC	#CJK UNIFIED IDEOGRAPH
+0xEEE2	0x9B75	#CJK UNIFIED IDEOGRAPH
+0xEEE3	0x9B72	#CJK UNIFIED IDEOGRAPH
+0xEEE4	0x9B8F	#CJK UNIFIED IDEOGRAPH
+0xEEE5	0x9BB1	#CJK UNIFIED IDEOGRAPH
+0xEEE6	0x9BBB	#CJK UNIFIED IDEOGRAPH
+0xEEE7	0x9C00	#CJK UNIFIED IDEOGRAPH
+0xEEE8	0x9D70	#CJK UNIFIED IDEOGRAPH
+0xEEE9	0x9D6B	#CJK UNIFIED IDEOGRAPH
+0xEEEA	0xFA2D	#CJK COMPATIBILITY IDEOGRAPH
+0xEEEB	0x9E19	#CJK UNIFIED IDEOGRAPH
+0xEEEC	0x9ED1	#CJK UNIFIED IDEOGRAPH
+0xEEEF	0x2170	#SMALL ROMAN NUMERAL ONE
+0xEEF0	0x2171	#SMALL ROMAN NUMERAL TWO
+0xEEF1	0x2172	#SMALL ROMAN NUMERAL THREE
+0xEEF2	0x2173	#SMALL ROMAN NUMERAL FOUR
+0xEEF3	0x2174	#SMALL ROMAN NUMERAL FIVE
+0xEEF4	0x2175	#SMALL ROMAN NUMERAL SIX
+0xEEF5	0x2176	#SMALL ROMAN NUMERAL SEVEN
+0xEEF6	0x2177	#SMALL ROMAN NUMERAL EIGHT
+0xEEF7	0x2178	#SMALL ROMAN NUMERAL NINE
+0xEEF8	0x2179	#SMALL ROMAN NUMERAL TEN
+0xEEF9	0xFFE2	#FULLWIDTH NOT SIGN
+0xEEFA	0xFFE4	#FULLWIDTH BROKEN BAR
+0xEEFB	0xFF07	#FULLWIDTH APOSTROPHE
+0xEEFC	0xFF02	#FULLWIDTH QUOTATION MARK
+0xFA40	0x2170	#SMALL ROMAN NUMERAL ONE
+0xFA41	0x2171	#SMALL ROMAN NUMERAL TWO
+0xFA42	0x2172	#SMALL ROMAN NUMERAL THREE
+0xFA43	0x2173	#SMALL ROMAN NUMERAL FOUR
+0xFA44	0x2174	#SMALL ROMAN NUMERAL FIVE
+0xFA45	0x2175	#SMALL ROMAN NUMERAL SIX
+0xFA46	0x2176	#SMALL ROMAN NUMERAL SEVEN
+0xFA47	0x2177	#SMALL ROMAN NUMERAL EIGHT
+0xFA48	0x2178	#SMALL ROMAN NUMERAL NINE
+0xFA49	0x2179	#SMALL ROMAN NUMERAL TEN
+0xFA4A	0x2160	#ROMAN NUMERAL ONE
+0xFA4B	0x2161	#ROMAN NUMERAL TWO
+0xFA4C	0x2162	#ROMAN NUMERAL THREE
+0xFA4D	0x2163	#ROMAN NUMERAL FOUR
+0xFA4E	0x2164	#ROMAN NUMERAL FIVE
+0xFA4F	0x2165	#ROMAN NUMERAL SIX
+0xFA50	0x2166	#ROMAN NUMERAL SEVEN
+0xFA51	0x2167	#ROMAN NUMERAL EIGHT
+0xFA52	0x2168	#ROMAN NUMERAL NINE
+0xFA53	0x2169	#ROMAN NUMERAL TEN
+0xFA54	0xFFE2	#FULLWIDTH NOT SIGN
+0xFA55	0xFFE4	#FULLWIDTH BROKEN BAR
+0xFA56	0xFF07	#FULLWIDTH APOSTROPHE
+0xFA57	0xFF02	#FULLWIDTH QUOTATION MARK
+0xFA58	0x3231	#PARENTHESIZED IDEOGRAPH STOCK
+0xFA59	0x2116	#NUMERO SIGN
+0xFA5A	0x2121	#TELEPHONE SIGN
+0xFA5B	0x2235	#BECAUSE
+0xFA5C	0x7E8A	#CJK UNIFIED IDEOGRAPH
+0xFA5D	0x891C	#CJK UNIFIED IDEOGRAPH
+0xFA5E	0x9348	#CJK UNIFIED IDEOGRAPH
+0xFA5F	0x9288	#CJK UNIFIED IDEOGRAPH
+0xFA60	0x84DC	#CJK UNIFIED IDEOGRAPH
+0xFA61	0x4FC9	#CJK UNIFIED IDEOGRAPH
+0xFA62	0x70BB	#CJK UNIFIED IDEOGRAPH
+0xFA63	0x6631	#CJK UNIFIED IDEOGRAPH
+0xFA64	0x68C8	#CJK UNIFIED IDEOGRAPH
+0xFA65	0x92F9	#CJK UNIFIED IDEOGRAPH
+0xFA66	0x66FB	#CJK UNIFIED IDEOGRAPH
+0xFA67	0x5F45	#CJK UNIFIED IDEOGRAPH
+0xFA68	0x4E28	#CJK UNIFIED IDEOGRAPH
+0xFA69	0x4EE1	#CJK UNIFIED IDEOGRAPH
+0xFA6A	0x4EFC	#CJK UNIFIED IDEOGRAPH
+0xFA6B	0x4F00	#CJK UNIFIED IDEOGRAPH
+0xFA6C	0x4F03	#CJK UNIFIED IDEOGRAPH
+0xFA6D	0x4F39	#CJK UNIFIED IDEOGRAPH
+0xFA6E	0x4F56	#CJK UNIFIED IDEOGRAPH
+0xFA6F	0x4F92	#CJK UNIFIED IDEOGRAPH
+0xFA70	0x4F8A	#CJK UNIFIED IDEOGRAPH
+0xFA71	0x4F9A	#CJK UNIFIED IDEOGRAPH
+0xFA72	0x4F94	#CJK UNIFIED IDEOGRAPH
+0xFA73	0x4FCD	#CJK UNIFIED IDEOGRAPH
+0xFA74	0x5040	#CJK UNIFIED IDEOGRAPH
+0xFA75	0x5022	#CJK UNIFIED IDEOGRAPH
+0xFA76	0x4FFF	#CJK UNIFIED IDEOGRAPH
+0xFA77	0x501E	#CJK UNIFIED IDEOGRAPH
+0xFA78	0x5046	#CJK UNIFIED IDEOGRAPH
+0xFA79	0x5070	#CJK UNIFIED IDEOGRAPH
+0xFA7A	0x5042	#CJK UNIFIED IDEOGRAPH
+0xFA7B	0x5094	#CJK UNIFIED IDEOGRAPH
+0xFA7C	0x50F4	#CJK UNIFIED IDEOGRAPH
+0xFA7D	0x50D8	#CJK UNIFIED IDEOGRAPH
+0xFA7E	0x514A	#CJK UNIFIED IDEOGRAPH
+0xFA80	0x5164	#CJK UNIFIED IDEOGRAPH
+0xFA81	0x519D	#CJK UNIFIED IDEOGRAPH
+0xFA82	0x51BE	#CJK UNIFIED IDEOGRAPH
+0xFA83	0x51EC	#CJK UNIFIED IDEOGRAPH
+0xFA84	0x5215	#CJK UNIFIED IDEOGRAPH
+0xFA85	0x529C	#CJK UNIFIED IDEOGRAPH
+0xFA86	0x52A6	#CJK UNIFIED IDEOGRAPH
+0xFA87	0x52C0	#CJK UNIFIED IDEOGRAPH
+0xFA88	0x52DB	#CJK UNIFIED IDEOGRAPH
+0xFA89	0x5300	#CJK UNIFIED IDEOGRAPH
+0xFA8A	0x5307	#CJK UNIFIED IDEOGRAPH
+0xFA8B	0x5324	#CJK UNIFIED IDEOGRAPH
+0xFA8C	0x5372	#CJK UNIFIED IDEOGRAPH
+0xFA8D	0x5393	#CJK UNIFIED IDEOGRAPH
+0xFA8E	0x53B2	#CJK UNIFIED IDEOGRAPH
+0xFA8F	0x53DD	#CJK UNIFIED IDEOGRAPH
+0xFA90	0xFA0E	#CJK COMPATIBILITY IDEOGRAPH
+0xFA91	0x549C	#CJK UNIFIED IDEOGRAPH
+0xFA92	0x548A	#CJK UNIFIED IDEOGRAPH
+0xFA93	0x54A9	#CJK UNIFIED IDEOGRAPH
+0xFA94	0x54FF	#CJK UNIFIED IDEOGRAPH
+0xFA95	0x5586	#CJK UNIFIED IDEOGRAPH
+0xFA96	0x5759	#CJK UNIFIED IDEOGRAPH
+0xFA97	0x5765	#CJK UNIFIED IDEOGRAPH
+0xFA98	0x57AC	#CJK UNIFIED IDEOGRAPH
+0xFA99	0x57C8	#CJK UNIFIED IDEOGRAPH
+0xFA9A	0x57C7	#CJK UNIFIED IDEOGRAPH
+0xFA9B	0xFA0F	#CJK COMPATIBILITY IDEOGRAPH
+0xFA9C	0xFA10	#CJK COMPATIBILITY IDEOGRAPH
+0xFA9D	0x589E	#CJK UNIFIED IDEOGRAPH
+0xFA9E	0x58B2	#CJK UNIFIED IDEOGRAPH
+0xFA9F	0x590B	#CJK UNIFIED IDEOGRAPH
+0xFAA0	0x5953	#CJK UNIFIED IDEOGRAPH
+0xFAA1	0x595B	#CJK UNIFIED IDEOGRAPH
+0xFAA2	0x595D	#CJK UNIFIED IDEOGRAPH
+0xFAA3	0x5963	#CJK UNIFIED IDEOGRAPH
+0xFAA4	0x59A4	#CJK UNIFIED IDEOGRAPH
+0xFAA5	0x59BA	#CJK UNIFIED IDEOGRAPH
+0xFAA6	0x5B56	#CJK UNIFIED IDEOGRAPH
+0xFAA7	0x5BC0	#CJK UNIFIED IDEOGRAPH
+0xFAA8	0x752F	#CJK UNIFIED IDEOGRAPH
+0xFAA9	0x5BD8	#CJK UNIFIED IDEOGRAPH
+0xFAAA	0x5BEC	#CJK UNIFIED IDEOGRAPH
+0xFAAB	0x5C1E	#CJK UNIFIED IDEOGRAPH
+0xFAAC	0x5CA6	#CJK UNIFIED IDEOGRAPH
+0xFAAD	0x5CBA	#CJK UNIFIED IDEOGRAPH
+0xFAAE	0x5CF5	#CJK UNIFIED IDEOGRAPH
+0xFAAF	0x5D27	#CJK UNIFIED IDEOGRAPH
+0xFAB0	0x5D53	#CJK UNIFIED IDEOGRAPH
+0xFAB1	0xFA11	#CJK COMPATIBILITY IDEOGRAPH
+0xFAB2	0x5D42	#CJK UNIFIED IDEOGRAPH
+0xFAB3	0x5D6D	#CJK UNIFIED IDEOGRAPH
+0xFAB4	0x5DB8	#CJK UNIFIED IDEOGRAPH
+0xFAB5	0x5DB9	#CJK UNIFIED IDEOGRAPH
+0xFAB6	0x5DD0	#CJK UNIFIED IDEOGRAPH
+0xFAB7	0x5F21	#CJK UNIFIED IDEOGRAPH
+0xFAB8	0x5F34	#CJK UNIFIED IDEOGRAPH
+0xFAB9	0x5F67	#CJK UNIFIED IDEOGRAPH
+0xFABA	0x5FB7	#CJK UNIFIED IDEOGRAPH
+0xFABB	0x5FDE	#CJK UNIFIED IDEOGRAPH
+0xFABC	0x605D	#CJK UNIFIED IDEOGRAPH
+0xFABD	0x6085	#CJK UNIFIED IDEOGRAPH
+0xFABE	0x608A	#CJK UNIFIED IDEOGRAPH
+0xFABF	0x60DE	#CJK UNIFIED IDEOGRAPH
+0xFAC0	0x60D5	#CJK UNIFIED IDEOGRAPH
+0xFAC1	0x6120	#CJK UNIFIED IDEOGRAPH
+0xFAC2	0x60F2	#CJK UNIFIED IDEOGRAPH
+0xFAC3	0x6111	#CJK UNIFIED IDEOGRAPH
+0xFAC4	0x6137	#CJK UNIFIED IDEOGRAPH
+0xFAC5	0x6130	#CJK UNIFIED IDEOGRAPH
+0xFAC6	0x6198	#CJK UNIFIED IDEOGRAPH
+0xFAC7	0x6213	#CJK UNIFIED IDEOGRAPH
+0xFAC8	0x62A6	#CJK UNIFIED IDEOGRAPH
+0xFAC9	0x63F5	#CJK UNIFIED IDEOGRAPH
+0xFACA	0x6460	#CJK UNIFIED IDEOGRAPH
+0xFACB	0x649D	#CJK UNIFIED IDEOGRAPH
+0xFACC	0x64CE	#CJK UNIFIED IDEOGRAPH
+0xFACD	0x654E	#CJK UNIFIED IDEOGRAPH
+0xFACE	0x6600	#CJK UNIFIED IDEOGRAPH
+0xFACF	0x6615	#CJK UNIFIED IDEOGRAPH
+0xFAD0	0x663B	#CJK UNIFIED IDEOGRAPH
+0xFAD1	0x6609	#CJK UNIFIED IDEOGRAPH
+0xFAD2	0x662E	#CJK UNIFIED IDEOGRAPH
+0xFAD3	0x661E	#CJK UNIFIED IDEOGRAPH
+0xFAD4	0x6624	#CJK UNIFIED IDEOGRAPH
+0xFAD5	0x6665	#CJK UNIFIED IDEOGRAPH
+0xFAD6	0x6657	#CJK UNIFIED IDEOGRAPH
+0xFAD7	0x6659	#CJK UNIFIED IDEOGRAPH
+0xFAD8	0xFA12	#CJK COMPATIBILITY IDEOGRAPH
+0xFAD9	0x6673	#CJK UNIFIED IDEOGRAPH
+0xFADA	0x6699	#CJK UNIFIED IDEOGRAPH
+0xFADB	0x66A0	#CJK UNIFIED IDEOGRAPH
+0xFADC	0x66B2	#CJK UNIFIED IDEOGRAPH
+0xFADD	0x66BF	#CJK UNIFIED IDEOGRAPH
+0xFADE	0x66FA	#CJK UNIFIED IDEOGRAPH
+0xFADF	0x670E	#CJK UNIFIED IDEOGRAPH
+0xFAE0	0xF929	#CJK COMPATIBILITY IDEOGRAPH
+0xFAE1	0x6766	#CJK UNIFIED IDEOGRAPH
+0xFAE2	0x67BB	#CJK UNIFIED IDEOGRAPH
+0xFAE3	0x6852	#CJK UNIFIED IDEOGRAPH
+0xFAE4	0x67C0	#CJK UNIFIED IDEOGRAPH
+0xFAE5	0x6801	#CJK UNIFIED IDEOGRAPH
+0xFAE6	0x6844	#CJK UNIFIED IDEOGRAPH
+0xFAE7	0x68CF	#CJK UNIFIED IDEOGRAPH
+0xFAE8	0xFA13	#CJK COMPATIBILITY IDEOGRAPH
+0xFAE9	0x6968	#CJK UNIFIED IDEOGRAPH
+0xFAEA	0xFA14	#CJK COMPATIBILITY IDEOGRAPH
+0xFAEB	0x6998	#CJK UNIFIED IDEOGRAPH
+0xFAEC	0x69E2	#CJK UNIFIED IDEOGRAPH
+0xFAED	0x6A30	#CJK UNIFIED IDEOGRAPH
+0xFAEE	0x6A6B	#CJK UNIFIED IDEOGRAPH
+0xFAEF	0x6A46	#CJK UNIFIED IDEOGRAPH
+0xFAF0	0x6A73	#CJK UNIFIED IDEOGRAPH
+0xFAF1	0x6A7E	#CJK UNIFIED IDEOGRAPH
+0xFAF2	0x6AE2	#CJK UNIFIED IDEOGRAPH
+0xFAF3	0x6AE4	#CJK UNIFIED IDEOGRAPH
+0xFAF4	0x6BD6	#CJK UNIFIED IDEOGRAPH
+0xFAF5	0x6C3F	#CJK UNIFIED IDEOGRAPH
+0xFAF6	0x6C5C	#CJK UNIFIED IDEOGRAPH
+0xFAF7	0x6C86	#CJK UNIFIED IDEOGRAPH
+0xFAF8	0x6C6F	#CJK UNIFIED IDEOGRAPH
+0xFAF9	0x6CDA	#CJK UNIFIED IDEOGRAPH
+0xFAFA	0x6D04	#CJK UNIFIED IDEOGRAPH
+0xFAFB	0x6D87	#CJK UNIFIED IDEOGRAPH
+0xFAFC	0x6D6F	#CJK UNIFIED IDEOGRAPH
+0xFB40	0x6D96	#CJK UNIFIED IDEOGRAPH
+0xFB41	0x6DAC	#CJK UNIFIED IDEOGRAPH
+0xFB42	0x6DCF	#CJK UNIFIED IDEOGRAPH
+0xFB43	0x6DF8	#CJK UNIFIED IDEOGRAPH
+0xFB44	0x6DF2	#CJK UNIFIED IDEOGRAPH
+0xFB45	0x6DFC	#CJK UNIFIED IDEOGRAPH
+0xFB46	0x6E39	#CJK UNIFIED IDEOGRAPH
+0xFB47	0x6E5C	#CJK UNIFIED IDEOGRAPH
+0xFB48	0x6E27	#CJK UNIFIED IDEOGRAPH
+0xFB49	0x6E3C	#CJK UNIFIED IDEOGRAPH
+0xFB4A	0x6EBF	#CJK UNIFIED IDEOGRAPH
+0xFB4B	0x6F88	#CJK UNIFIED IDEOGRAPH
+0xFB4C	0x6FB5	#CJK UNIFIED IDEOGRAPH
+0xFB4D	0x6FF5	#CJK UNIFIED IDEOGRAPH
+0xFB4E	0x7005	#CJK UNIFIED IDEOGRAPH
+0xFB4F	0x7007	#CJK UNIFIED IDEOGRAPH
+0xFB50	0x7028	#CJK UNIFIED IDEOGRAPH
+0xFB51	0x7085	#CJK UNIFIED IDEOGRAPH
+0xFB52	0x70AB	#CJK UNIFIED IDEOGRAPH
+0xFB53	0x710F	#CJK UNIFIED IDEOGRAPH
+0xFB54	0x7104	#CJK UNIFIED IDEOGRAPH
+0xFB55	0x715C	#CJK UNIFIED IDEOGRAPH
+0xFB56	0x7146	#CJK UNIFIED IDEOGRAPH
+0xFB57	0x7147	#CJK UNIFIED IDEOGRAPH
+0xFB58	0xFA15	#CJK COMPATIBILITY IDEOGRAPH
+0xFB59	0x71C1	#CJK UNIFIED IDEOGRAPH
+0xFB5A	0x71FE	#CJK UNIFIED IDEOGRAPH
+0xFB5B	0x72B1	#CJK UNIFIED IDEOGRAPH
+0xFB5C	0x72BE	#CJK UNIFIED IDEOGRAPH
+0xFB5D	0x7324	#CJK UNIFIED IDEOGRAPH
+0xFB5E	0xFA16	#CJK COMPATIBILITY IDEOGRAPH
+0xFB5F	0x7377	#CJK UNIFIED IDEOGRAPH
+0xFB60	0x73BD	#CJK UNIFIED IDEOGRAPH
+0xFB61	0x73C9	#CJK UNIFIED IDEOGRAPH
+0xFB62	0x73D6	#CJK UNIFIED IDEOGRAPH
+0xFB63	0x73E3	#CJK UNIFIED IDEOGRAPH
+0xFB64	0x73D2	#CJK UNIFIED IDEOGRAPH
+0xFB65	0x7407	#CJK UNIFIED IDEOGRAPH
+0xFB66	0x73F5	#CJK UNIFIED IDEOGRAPH
+0xFB67	0x7426	#CJK UNIFIED IDEOGRAPH
+0xFB68	0x742A	#CJK UNIFIED IDEOGRAPH
+0xFB69	0x7429	#CJK UNIFIED IDEOGRAPH
+0xFB6A	0x742E	#CJK UNIFIED IDEOGRAPH
+0xFB6B	0x7462	#CJK UNIFIED IDEOGRAPH
+0xFB6C	0x7489	#CJK UNIFIED IDEOGRAPH
+0xFB6D	0x749F	#CJK UNIFIED IDEOGRAPH
+0xFB6E	0x7501	#CJK UNIFIED IDEOGRAPH
+0xFB6F	0x756F	#CJK UNIFIED IDEOGRAPH
+0xFB70	0x7682	#CJK UNIFIED IDEOGRAPH
+0xFB71	0x769C	#CJK UNIFIED IDEOGRAPH
+0xFB72	0x769E	#CJK UNIFIED IDEOGRAPH
+0xFB73	0x769B	#CJK UNIFIED IDEOGRAPH
+0xFB74	0x76A6	#CJK UNIFIED IDEOGRAPH
+0xFB75	0xFA17	#CJK COMPATIBILITY IDEOGRAPH
+0xFB76	0x7746	#CJK UNIFIED IDEOGRAPH
+0xFB77	0x52AF	#CJK UNIFIED IDEOGRAPH
+0xFB78	0x7821	#CJK UNIFIED IDEOGRAPH
+0xFB79	0x784E	#CJK UNIFIED IDEOGRAPH
+0xFB7A	0x7864	#CJK UNIFIED IDEOGRAPH
+0xFB7B	0x787A	#CJK UNIFIED IDEOGRAPH
+0xFB7C	0x7930	#CJK UNIFIED IDEOGRAPH
+0xFB7D	0xFA18	#CJK COMPATIBILITY IDEOGRAPH
+0xFB7E	0xFA19	#CJK COMPATIBILITY IDEOGRAPH
+0xFB80	0xFA1A	#CJK COMPATIBILITY IDEOGRAPH
+0xFB81	0x7994	#CJK UNIFIED IDEOGRAPH
+0xFB82	0xFA1B	#CJK COMPATIBILITY IDEOGRAPH
+0xFB83	0x799B	#CJK UNIFIED IDEOGRAPH
+0xFB84	0x7AD1	#CJK UNIFIED IDEOGRAPH
+0xFB85	0x7AE7	#CJK UNIFIED IDEOGRAPH
+0xFB86	0xFA1C	#CJK COMPATIBILITY IDEOGRAPH
+0xFB87	0x7AEB	#CJK UNIFIED IDEOGRAPH
+0xFB88	0x7B9E	#CJK UNIFIED IDEOGRAPH
+0xFB89	0xFA1D	#CJK COMPATIBILITY IDEOGRAPH
+0xFB8A	0x7D48	#CJK UNIFIED IDEOGRAPH
+0xFB8B	0x7D5C	#CJK UNIFIED IDEOGRAPH
+0xFB8C	0x7DB7	#CJK UNIFIED IDEOGRAPH
+0xFB8D	0x7DA0	#CJK UNIFIED IDEOGRAPH
+0xFB8E	0x7DD6	#CJK UNIFIED IDEOGRAPH
+0xFB8F	0x7E52	#CJK UNIFIED IDEOGRAPH
+0xFB90	0x7F47	#CJK UNIFIED IDEOGRAPH
+0xFB91	0x7FA1	#CJK UNIFIED IDEOGRAPH
+0xFB92	0xFA1E	#CJK COMPATIBILITY IDEOGRAPH
+0xFB93	0x8301	#CJK UNIFIED IDEOGRAPH
+0xFB94	0x8362	#CJK UNIFIED IDEOGRAPH
+0xFB95	0x837F	#CJK UNIFIED IDEOGRAPH
+0xFB96	0x83C7	#CJK UNIFIED IDEOGRAPH
+0xFB97	0x83F6	#CJK UNIFIED IDEOGRAPH
+0xFB98	0x8448	#CJK UNIFIED IDEOGRAPH
+0xFB99	0x84B4	#CJK UNIFIED IDEOGRAPH
+0xFB9A	0x8553	#CJK UNIFIED IDEOGRAPH
+0xFB9B	0x8559	#CJK UNIFIED IDEOGRAPH
+0xFB9C	0x856B	#CJK UNIFIED IDEOGRAPH
+0xFB9D	0xFA1F	#CJK COMPATIBILITY IDEOGRAPH
+0xFB9E	0x85B0	#CJK UNIFIED IDEOGRAPH
+0xFB9F	0xFA20	#CJK COMPATIBILITY IDEOGRAPH
+0xFBA0	0xFA21	#CJK COMPATIBILITY IDEOGRAPH
+0xFBA1	0x8807	#CJK UNIFIED IDEOGRAPH
+0xFBA2	0x88F5	#CJK UNIFIED IDEOGRAPH
+0xFBA3	0x8A12	#CJK UNIFIED IDEOGRAPH
+0xFBA4	0x8A37	#CJK UNIFIED IDEOGRAPH
+0xFBA5	0x8A79	#CJK UNIFIED IDEOGRAPH
+0xFBA6	0x8AA7	#CJK UNIFIED IDEOGRAPH
+0xFBA7	0x8ABE	#CJK UNIFIED IDEOGRAPH
+0xFBA8	0x8ADF	#CJK UNIFIED IDEOGRAPH
+0xFBA9	0xFA22	#CJK COMPATIBILITY IDEOGRAPH
+0xFBAA	0x8AF6	#CJK UNIFIED IDEOGRAPH
+0xFBAB	0x8B53	#CJK UNIFIED IDEOGRAPH
+0xFBAC	0x8B7F	#CJK UNIFIED IDEOGRAPH
+0xFBAD	0x8CF0	#CJK UNIFIED IDEOGRAPH
+0xFBAE	0x8CF4	#CJK UNIFIED IDEOGRAPH
+0xFBAF	0x8D12	#CJK UNIFIED IDEOGRAPH
+0xFBB0	0x8D76	#CJK UNIFIED IDEOGRAPH
+0xFBB1	0xFA23	#CJK COMPATIBILITY IDEOGRAPH
+0xFBB2	0x8ECF	#CJK UNIFIED IDEOGRAPH
+0xFBB3	0xFA24	#CJK COMPATIBILITY IDEOGRAPH
+0xFBB4	0xFA25	#CJK COMPATIBILITY IDEOGRAPH
+0xFBB5	0x9067	#CJK UNIFIED IDEOGRAPH
+0xFBB6	0x90DE	#CJK UNIFIED IDEOGRAPH
+0xFBB7	0xFA26	#CJK COMPATIBILITY IDEOGRAPH
+0xFBB8	0x9115	#CJK UNIFIED IDEOGRAPH
+0xFBB9	0x9127	#CJK UNIFIED IDEOGRAPH
+0xFBBA	0x91DA	#CJK UNIFIED IDEOGRAPH
+0xFBBB	0x91D7	#CJK UNIFIED IDEOGRAPH
+0xFBBC	0x91DE	#CJK UNIFIED IDEOGRAPH
+0xFBBD	0x91ED	#CJK UNIFIED IDEOGRAPH
+0xFBBE	0x91EE	#CJK UNIFIED IDEOGRAPH
+0xFBBF	0x91E4	#CJK UNIFIED IDEOGRAPH
+0xFBC0	0x91E5	#CJK UNIFIED IDEOGRAPH
+0xFBC1	0x9206	#CJK UNIFIED IDEOGRAPH
+0xFBC2	0x9210	#CJK UNIFIED IDEOGRAPH
+0xFBC3	0x920A	#CJK UNIFIED IDEOGRAPH
+0xFBC4	0x923A	#CJK UNIFIED IDEOGRAPH
+0xFBC5	0x9240	#CJK UNIFIED IDEOGRAPH
+0xFBC6	0x923C	#CJK UNIFIED IDEOGRAPH
+0xFBC7	0x924E	#CJK UNIFIED IDEOGRAPH
+0xFBC8	0x9259	#CJK UNIFIED IDEOGRAPH
+0xFBC9	0x9251	#CJK UNIFIED IDEOGRAPH
+0xFBCA	0x9239	#CJK UNIFIED IDEOGRAPH
+0xFBCB	0x9267	#CJK UNIFIED IDEOGRAPH
+0xFBCC	0x92A7	#CJK UNIFIED IDEOGRAPH
+0xFBCD	0x9277	#CJK UNIFIED IDEOGRAPH
+0xFBCE	0x9278	#CJK UNIFIED IDEOGRAPH
+0xFBCF	0x92E7	#CJK UNIFIED IDEOGRAPH
+0xFBD0	0x92D7	#CJK UNIFIED IDEOGRAPH
+0xFBD1	0x92D9	#CJK UNIFIED IDEOGRAPH
+0xFBD2	0x92D0	#CJK UNIFIED IDEOGRAPH
+0xFBD3	0xFA27	#CJK COMPATIBILITY IDEOGRAPH
+0xFBD4	0x92D5	#CJK UNIFIED IDEOGRAPH
+0xFBD5	0x92E0	#CJK UNIFIED IDEOGRAPH
+0xFBD6	0x92D3	#CJK UNIFIED IDEOGRAPH
+0xFBD7	0x9325	#CJK UNIFIED IDEOGRAPH
+0xFBD8	0x9321	#CJK UNIFIED IDEOGRAPH
+0xFBD9	0x92FB	#CJK UNIFIED IDEOGRAPH
+0xFBDA	0xFA28	#CJK COMPATIBILITY IDEOGRAPH
+0xFBDB	0x931E	#CJK UNIFIED IDEOGRAPH
+0xFBDC	0x92FF	#CJK UNIFIED IDEOGRAPH
+0xFBDD	0x931D	#CJK UNIFIED IDEOGRAPH
+0xFBDE	0x9302	#CJK UNIFIED IDEOGRAPH
+0xFBDF	0x9370	#CJK UNIFIED IDEOGRAPH
+0xFBE0	0x9357	#CJK UNIFIED IDEOGRAPH
+0xFBE1	0x93A4	#CJK UNIFIED IDEOGRAPH
+0xFBE2	0x93C6	#CJK UNIFIED IDEOGRAPH
+0xFBE3	0x93DE	#CJK UNIFIED IDEOGRAPH
+0xFBE4	0x93F8	#CJK UNIFIED IDEOGRAPH
+0xFBE5	0x9431	#CJK UNIFIED IDEOGRAPH
+0xFBE6	0x9445	#CJK UNIFIED IDEOGRAPH
+0xFBE7	0x9448	#CJK UNIFIED IDEOGRAPH
+0xFBE8	0x9592	#CJK UNIFIED IDEOGRAPH
+0xFBE9	0xF9DC	#CJK COMPATIBILITY IDEOGRAPH
+0xFBEA	0xFA29	#CJK COMPATIBILITY IDEOGRAPH
+0xFBEB	0x969D	#CJK UNIFIED IDEOGRAPH
+0xFBEC	0x96AF	#CJK UNIFIED IDEOGRAPH
+0xFBED	0x9733	#CJK UNIFIED IDEOGRAPH
+0xFBEE	0x973B	#CJK UNIFIED IDEOGRAPH
+0xFBEF	0x9743	#CJK UNIFIED IDEOGRAPH
+0xFBF0	0x974D	#CJK UNIFIED IDEOGRAPH
+0xFBF1	0x974F	#CJK UNIFIED IDEOGRAPH
+0xFBF2	0x9751	#CJK UNIFIED IDEOGRAPH
+0xFBF3	0x9755	#CJK UNIFIED IDEOGRAPH
+0xFBF4	0x9857	#CJK UNIFIED IDEOGRAPH
+0xFBF5	0x9865	#CJK UNIFIED IDEOGRAPH
+0xFBF6	0xFA2A	#CJK COMPATIBILITY IDEOGRAPH
+0xFBF7	0xFA2B	#CJK COMPATIBILITY IDEOGRAPH
+0xFBF8	0x9927	#CJK UNIFIED IDEOGRAPH
+0xFBF9	0xFA2C	#CJK COMPATIBILITY IDEOGRAPH
+0xFBFA	0x999E	#CJK UNIFIED IDEOGRAPH
+0xFBFB	0x9A4E	#CJK UNIFIED IDEOGRAPH
+0xFBFC	0x9AD9	#CJK UNIFIED IDEOGRAPH
+0xFC40	0x9ADC	#CJK UNIFIED IDEOGRAPH
+0xFC41	0x9B75	#CJK UNIFIED IDEOGRAPH
+0xFC42	0x9B72	#CJK UNIFIED IDEOGRAPH
+0xFC43	0x9B8F	#CJK UNIFIED IDEOGRAPH
+0xFC44	0x9BB1	#CJK UNIFIED IDEOGRAPH
+0xFC45	0x9BBB	#CJK UNIFIED IDEOGRAPH
+0xFC46	0x9C00	#CJK UNIFIED IDEOGRAPH
+0xFC47	0x9D70	#CJK UNIFIED IDEOGRAPH
+0xFC48	0x9D6B	#CJK UNIFIED IDEOGRAPH
+0xFC49	0xFA2D	#CJK COMPATIBILITY IDEOGRAPH
+0xFC4A	0x9E19	#CJK UNIFIED IDEOGRAPH
+0xFC4B	0x9ED1	#CJK UNIFIED IDEOGRAPH
diff --git a/test/datafiles/unit/carolus-rex.cdtext b/test/datafiles/unit/carolus-rex.cdtext
new file mode 100644
Binary files /dev/null and b/test/datafiles/unit/carolus-rex.cdtext differ
diff --git a/test/datafiles/unit/deeper-dance.cdtext b/test/datafiles/unit/deeper-dance.cdtext
new file mode 100644
Binary files /dev/null and b/test/datafiles/unit/deeper-dance.cdtext differ
diff --git a/test/datafiles/unit/pearl-jam.cdtext b/test/datafiles/unit/pearl-jam.cdtext
new file mode 100644
Binary files /dev/null and b/test/datafiles/unit/pearl-jam.cdtext differ
diff --git a/test/datafiles/unit/revolution-days.cdtext b/test/datafiles/unit/revolution-days.cdtext
new file mode 100644
Binary files /dev/null and b/test/datafiles/unit/revolution-days.cdtext differ
diff --git a/test/datafiles/upstream/bad-cat1.cue b/test/datafiles/upstream/bad-cat1.cue
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/bad-cat1.cue
@@ -0,0 +1,9 @@
+REM $Id: bad-cat1.cue,v 1.1 2004/07/12 03:59:59 rocky Exp $
+REM test catalog number - no catalog after word CATALOG
+
+CATALOG
+
+FILE "cdda.bin" BINARY
+
+TRACK 01 AUDIO
+    INDEX 01 00:00:00
diff --git a/test/datafiles/upstream/bad-cat1.toc b/test/datafiles/upstream/bad-cat1.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/bad-cat1.toc
@@ -0,0 +1,8 @@
+// $Id: bad-cat1.toc,v 1.1 2004/05/08 20:36:02 rocky Exp $
+// test catalog number - no catalog after word CATALOG
+
+CATALOG
+
+TRACK AUDIO
+NO COPY
+FILE "cdda.bin" 1:0:0
diff --git a/test/datafiles/upstream/bad-cat2.cue b/test/datafiles/upstream/bad-cat2.cue
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/bad-cat2.cue
@@ -0,0 +1,9 @@
+REM $Id: bad-cat2.cue,v 1.1 2004/07/09 20:47:08 rocky Exp $
+REM test catalog number. -- not enough digits
+
+CATALOG "167890123"
+
+FILE "cdda.bin" BINARY
+
+TRACK 01 AUDIO
+    INDEX 01 00:00:00
diff --git a/test/datafiles/upstream/bad-cat2.toc b/test/datafiles/upstream/bad-cat2.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/bad-cat2.toc
@@ -0,0 +1,8 @@
+// $Id: bad-cat2.toc,v 1.2 2004/07/09 20:47:08 rocky Exp $
+// test catalog number. -- not enough digits
+
+CATALOG 167890123  // Should be 13 digits
+
+TRACK AUDIO
+NO COPY
+FILE "cdda.bin" 1:0:0
diff --git a/test/datafiles/upstream/bad-cat3.cue b/test/datafiles/upstream/bad-cat3.cue
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/bad-cat3.cue
@@ -0,0 +1,9 @@
+REM $Id: bad-cat3.cue,v 1.2 2004/07/10 01:18:02 rocky Exp $
+REM test catalog number. -- invalid decimal digit
+
+CATALOG 123456789b123
+
+FILE "cdda.bin" BINARY
+
+TRACK 01 AUDIO
+    INDEX 01 00:00:00
diff --git a/test/datafiles/upstream/bad-cat3.toc b/test/datafiles/upstream/bad-cat3.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/bad-cat3.toc
@@ -0,0 +1,8 @@
+// $Id: bad-cat3.toc,v 1.1 2004/05/08 20:36:02 rocky Exp $
+// test catalog number - non-digit catalog name
+
+CATALOG "123456789A123"
+
+TRACK AUDIO
+NO COPY
+FILE "cdda.bin" 1:0:0
diff --git a/test/datafiles/upstream/bad-file.toc b/test/datafiles/upstream/bad-file.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/bad-file.toc
@@ -0,0 +1,13 @@
+// $Id: bad-file.toc,v 1.1 2005/01/23 00:45:57 rocky Exp $
+// XA disk 
+// 
+
+CD_ROM_XA
+
+TRACK MODE2_FORM2
+FILE "foo.bin" 00:00:00 00:13:57
+
+TRACK MODE2_FORM1
+PREGAP 0:2:0
+FILE "foo.bin" 00:20:71 00:00:00
+
diff --git a/test/datafiles/upstream/bad-mode1.cue b/test/datafiles/upstream/bad-mode1.cue
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/bad-mode1.cue
@@ -0,0 +1,7 @@
+REM $Id: bad-mode1.cue,v 1.1 2004/07/10 01:18:02 rocky Exp $
+REM "MODE1_FORM45" is not a valid mode.
+
+FILE "cdda.bin" BINARY
+
+TRACK 01 MODE3_FORM1
+    INDEX 01 00:00:00
diff --git a/test/datafiles/upstream/bad-mode1.toc b/test/datafiles/upstream/bad-mode1.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/bad-mode1.toc
@@ -0,0 +1,5 @@
+// $Id: bad-mode1.toc,v 1.1 2004/05/07 10:57:50 rocky Exp $
+CD_DA
+
+TRACK MODE1_FORM45  // "MODE1_FORM45" is not a valid mode.
+SILENCE 10:0:0
diff --git a/test/datafiles/upstream/bad-msf-1.cue b/test/datafiles/upstream/bad-msf-1.cue
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/bad-msf-1.cue
@@ -0,0 +1,7 @@
+REM $Id: bad-msf-1.cue,v 1.1 2004/07/12 03:57:28 rocky Exp $
+REM bad MSF in second field - frame should be less than 75
+
+FILE "cdda.bin" BINARY
+
+TRACK 01 AUDIO
+    INDEX 01 00:00:100
diff --git a/test/datafiles/upstream/bad-msf-1.toc b/test/datafiles/upstream/bad-msf-1.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/bad-msf-1.toc
@@ -0,0 +1,6 @@
+// $Id: bad-msf-1.toc,v 1.1 2004/05/07 10:57:50 rocky Exp $
+// bad MSF in second field
+
+TRACK AUDIO
+NO COPY       // so that all CTL flags are 0
+FILE "cdda.bin" 0:0:75  // frame should be less than 75
diff --git a/test/datafiles/upstream/bad-msf-2.cue b/test/datafiles/upstream/bad-msf-2.cue
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/bad-msf-2.cue
@@ -0,0 +1,7 @@
+REM $Id: bad-msf-2.cue,v 1.1 2004/07/10 01:18:02 rocky Exp $
+REM bad MSF in second field - seconds should be less than 60
+
+FILE "cdda.bin" BINARY
+
+TRACK 01 AUDIO
+    INDEX 01 00:90:00
diff --git a/test/datafiles/upstream/bad-msf-2.toc b/test/datafiles/upstream/bad-msf-2.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/bad-msf-2.toc
@@ -0,0 +1,6 @@
+// $Id: bad-msf-2.toc,v 1.1 2004/05/07 10:57:50 rocky Exp $
+// bad MSF in second field
+
+TRACK AUDIO
+NO COPY       // so that all CTL flags are 0
+FILE "cdda.bin" 0:60:0  // seconds should be less than 60
diff --git a/test/datafiles/upstream/bad-msf-3.cue b/test/datafiles/upstream/bad-msf-3.cue
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/bad-msf-3.cue
@@ -0,0 +1,7 @@
+REM $Id: bad-msf-3.cue,v 1.1 2004/07/12 03:58:55 rocky Exp $
+REM bad MSF in second field 
+
+FILE "cdda.bin" BINARY
+
+TRACK 01 AUDIO
+    INDEX 01 xx:yy:0
diff --git a/test/datafiles/upstream/bad-msf-3.toc b/test/datafiles/upstream/bad-msf-3.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/bad-msf-3.toc
@@ -0,0 +1,6 @@
+// $Id: bad-msf-3.toc,v 1.1 2004/07/10 01:18:02 rocky Exp $
+// bad MSF in second field
+
+TRACK AUDIO
+NO COPY       // so that all CTL flags are 0
+FILE "cdda.bin" xx:yy:zz  // Should be digits
diff --git a/test/datafiles/upstream/cdda.bin b/test/datafiles/upstream/cdda.bin
new file mode 100644
Binary files /dev/null and b/test/datafiles/upstream/cdda.bin differ
diff --git a/test/datafiles/upstream/cdda.cue b/test/datafiles/upstream/cdda.cue
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/cdda.cue
@@ -0,0 +1,9 @@
+TITLE "Join us now we have the software"
+CATALOG 0000010271955
+PERFORMER "Richard Stallman"
+FILE "CDDA.BIN" BINARY
+  TRACK 01 AUDIO
+    TITLE "Soft"
+    PERFORMER "Richard S"
+    FLAGS DCP
+    INDEX 01 00:00:00
diff --git a/test/datafiles/upstream/cdtext.toc b/test/datafiles/upstream/cdtext.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/cdtext.toc
@@ -0,0 +1,48 @@
+CD_DA
+
+// global CD-TEXT data
+
+CD_TEXT {
+
+  // Mapping from language number (0..7) used in 'LANGUAGE' statements 
+  // to language code.
+///  LANGUAGE_MAP {
+///    0 : EN  // 9 is the code for ENGLISH,
+///            // I don't know any other language code, yet
+///  }
+
+  // Language number should always start with 0
+  LANGUAGE 0 {
+    // Required fields - at least all CD-TEXT CDs I've seen so far have them.
+    TITLE "Join us now we have the software"
+    PERFORMER "Richard Stallman"
+    DISC_ID "0000010271955"
+    UPC_EAN "" // usually empty
+
+    // Further possible items, all of them are optional
+    ARRANGER ""
+    SONGWRITER ""
+    MESSAGE "" 
+    GENRE "" // I'm not sure if this should be really ascii data
+  }
+}
+
+
+TRACK AUDIO
+// track specific CD-TEXT data
+CD_TEXT {
+  LANGUAGE 0 {
+    // if an item is defined for one track it should be defined for all tracks
+    TITLE "Soft"
+
+    PERFORMER "Richard S"
+    ISRC "US-XX1-98-01234"
+
+    ARRANGER ""
+    SONGWRITER ""
+    MESSAGE "" 
+  }
+}
+
+SILENCE 1:0:0
+
diff --git a/test/datafiles/upstream/data1.toc b/test/datafiles/upstream/data1.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/data1.toc
@@ -0,0 +1,8 @@
+// $Id: data1.toc,v 1.1 2004/05/08 20:36:02 rocky Exp $
+// Just a single MODE1 track.
+
+CD_ROM
+
+TRACK MODE1
+SILENCE 0:59:74
+
diff --git a/test/datafiles/upstream/data2.toc b/test/datafiles/upstream/data2.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/data2.toc
@@ -0,0 +1,13 @@
+// $Id
+// MODE1 track followed by an AUDIO track
+
+CD_ROM
+
+TRACK MODE1
+FILE "isofs-m1.bin" 00:00:00 
+ZERO 1:0:0
+
+TRACK AUDIO
+PREGAP 0:2:0
+FILE "cdda.bin" 00:00:00 
+
diff --git a/test/datafiles/upstream/data5.toc b/test/datafiles/upstream/data5.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/data5.toc
@@ -0,0 +1,13 @@
+// $Id: data5.toc,v 1.2 2005/01/23 00:45:57 rocky Exp $
+// XA disk 
+// 
+
+CD_ROM_XA
+
+TRACK MODE2_FORM2
+FILE "isofs-m1.bin" 00:00:00 00:01:57
+
+TRACK MODE2_FORM1
+PREGAP 0:2:0
+FILE "isofs-m1.bin" 00:20:71 00:00:10
+
diff --git a/test/datafiles/upstream/data6.toc b/test/datafiles/upstream/data6.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/data6.toc
@@ -0,0 +1,8 @@
+// $Id: data6.toc,v 1.2 2005/01/23 00:45:57 rocky Exp $
+// MODE2 track
+// 
+
+CD_ROM
+
+TRACK MODE2
+FILE "isofs-m1.bin" 00:00:00 00:01:57
diff --git a/test/datafiles/upstream/data7.toc b/test/datafiles/upstream/data7.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/data7.toc
@@ -0,0 +1,13 @@
+// $Id: data7.toc,v 1.2 2005/01/23 00:45:57 rocky Exp $
+// Video CD
+// 
+
+CD_ROM_XA
+
+TRACK MODE1 // ISO filesystem
+FILE "isofs-m1.bin" 00:00:00 00:03:57
+
+TRACK MODE2_FORM_MIX // XA track with form 1 and form 2 sectors
+PREGAP 0:2:0
+FILE "isofs-m1.bin" 00:20:71 00:00:00
+
diff --git a/test/datafiles/upstream/isofs-m1.bin b/test/datafiles/upstream/isofs-m1.bin
new file mode 100644
Binary files /dev/null and b/test/datafiles/upstream/isofs-m1.bin differ
diff --git a/test/datafiles/upstream/isofs-m1.cue b/test/datafiles/upstream/isofs-m1.cue
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/isofs-m1.cue
@@ -0,0 +1,4 @@
+CATALOG 0000012101954
+FILE "ISOFS-M1.BIN" BINARY
+  TRACK 01 MODE1/2352
+    INDEX 01 00:00:00
diff --git a/test/datafiles/upstream/p1.bin b/test/datafiles/upstream/p1.bin
new file mode 100644
Binary files /dev/null and b/test/datafiles/upstream/p1.bin differ
diff --git a/test/datafiles/upstream/p1.cue b/test/datafiles/upstream/p1.cue
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/p1.cue
@@ -0,0 +1,12 @@
+TITLE "Join us now we have the software"
+CATALOG 0000010271955
+PERFORMER "Richard Stallman"
+FILE "BOING.BIN" BINARY
+  TRACK 01 AUDIO
+    FLAGS DCP
+    INDEX 00 00:00:00
+    INDEX 01 00:01:00
+  TRACK 02 AUDIO
+    FLAGS DCP
+    INDEX 00 00:02:00
+    INDEX 01 00:03:00
diff --git a/test/datafiles/upstream/p1.nrg b/test/datafiles/upstream/p1.nrg
new file mode 100644
Binary files /dev/null and b/test/datafiles/upstream/p1.nrg differ
diff --git a/test/datafiles/upstream/t1.toc b/test/datafiles/upstream/t1.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/t1.toc
@@ -0,0 +1,5 @@
+// simplest cue sheet
+
+TRACK AUDIO
+NO COPY // so that all CTL flags are 0
+SILENCE 0:0:74  // frames are just under 75
diff --git a/test/datafiles/upstream/t10.toc b/test/datafiles/upstream/t10.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/t10.toc
@@ -0,0 +1,8 @@
+// non default CTL flag of track 1 
+
+TRACK AUDIO
+COPY
+NO PRE_EMPHASIS
+FOUR_CHANNEL_AUDIO
+FILE "cdda.bin" 1:0:0
+
diff --git a/test/datafiles/upstream/t2.toc b/test/datafiles/upstream/t2.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/t2.toc
@@ -0,0 +1,6 @@
+// additional pre-gap for track 1
+
+TRACK AUDIO
+NO COPY       // so that all CTL flags are 0
+FILE "cdda.bin" 0:59:0  // Seconds are just under 60
+START 0:10:0  // 10 second pre-gap
diff --git a/test/datafiles/upstream/t3.toc b/test/datafiles/upstream/t3.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/t3.toc
@@ -0,0 +1,11 @@
+// simplest cue sheet for two tracks
+
+TRACK AUDIO
+NO COPY       // so that all CTL flags are 0
+FILE "cdda.bin" 180:0:0  // 180 for number of minutes is okay, although
+                         // it is not for a second or a frame value.
+
+TRACK AUDIO
+NO COPY       // so that all CTL flags are 0
+FILE "cdda.bin" 1:0:0
+
diff --git a/test/datafiles/upstream/t4.toc b/test/datafiles/upstream/t4.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/t4.toc
@@ -0,0 +1,8 @@
+// non default CTL flag of track 1 
+
+TRACK AUDIO
+COPY
+PRE_EMPHASIS
+FOUR_CHANNEL_AUDIO
+FILE "cdda.bin" 1:0:0
+
diff --git a/test/datafiles/upstream/t5.toc b/test/datafiles/upstream/t5.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/t5.toc
@@ -0,0 +1,8 @@
+// test catalog number
+
+CATALOG "1234567890123"
+
+TRACK AUDIO
+NO COPY
+FILE "cdda.bin" 1:0:0
+
diff --git a/test/datafiles/upstream/t6.toc b/test/datafiles/upstream/t6.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/t6.toc
@@ -0,0 +1,7 @@
+// test ISRC code
+
+
+TRACK AUDIO
+NO COPY
+ISRC "DEMUA9800001"
+FILE "cdda.bin" 1:0:0
diff --git a/test/datafiles/upstream/t7.toc b/test/datafiles/upstream/t7.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/t7.toc
@@ -0,0 +1,12 @@
+// check two tracks with pre-gap and ISRC
+
+
+TRACK AUDIO
+NO COPY
+FILE "cdda.bin" 1:0:0
+
+TRACK AUDIO
+NO COPY
+ISRC "DEMUA9800001"
+FILE "cdda.bin" 1:0:0
+START 0:5:0   // pre-gap
diff --git a/test/datafiles/upstream/t8.toc b/test/datafiles/upstream/t8.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/t8.toc
@@ -0,0 +1,14 @@
+// check index increments
+
+
+TRACK AUDIO
+NO COPY
+FILE "cdda.bin" 0:10:0
+INDEX 1:0:0
+INDEX 2:0:0
+
+
+TRACK AUDIO
+NO COPY
+FILE "cdda.bin" 0:10:0
+START 0:5:0   // pre-gap
diff --git a/test/datafiles/upstream/t9.toc b/test/datafiles/upstream/t9.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/t9.toc
@@ -0,0 +1,31 @@
+CD_DA
+// check mulitple tracks
+CATALOG "0724385356926"
+
+TRACK AUDIO
+ISRC "USEM39600078"
+COPY
+FILE "cdda.bin" 0:10:0
+START 0:5:0
+
+TRACK AUDIO
+NO COPY
+ISRC "USEM39600079"
+FILE "cdda.bin" 0:10:0
+START 0:2:0
+
+TRACK AUDIO
+COPY
+FILE "cdda.bin" 0:10:0
+START 0:1:30
+
+TRACK AUDIO
+NO COPY
+START 0:0:0
+FILE "cdda.bin" 0:10:0
+
+TRACK AUDIO
+ISRC "EDUMA9892346"
+NO COPY
+FILE "cdda.bin" 0:10:0
+START 0:2:1
diff --git a/test/datafiles/upstream/vcd2.toc b/test/datafiles/upstream/vcd2.toc
new file mode 100644
--- /dev/null
+++ b/test/datafiles/upstream/vcd2.toc
@@ -0,0 +1,22 @@
+// Taken from one of Steve Schultz's VCD collection. 
+// The .bin and offsets have been changed and are wrong. 
+CD_ROM_XA
+
+
+// Track 1
+TRACK MODE2_FORM_MIX
+COPY
+DATAFILE "cdda.bin" 00:00:00 // comment
+
+
+// Track 2
+TRACK MODE2_FORM_MIX
+COPY
+DATAFILE "cdda.bin" #100 00:00:03 
+
+
+// Track 3
+TRACK MODE2_FORM_MIX
+COPY
+DATAFILE "cdda.bin" #200 00:00:25 
+
