[FFmpeg-devel] [PATCH] avformat, avcodec: add dfcmv demuxer and decoder

Ben Lubar ben at lubar.me
Tue Dec 3 08:34:17 EET 2019


A few example CMV files can be found in the data/initial_movies folder
of Dwarf Fortress (http://www.bay12games.com/dwarves/).

The demuxer does not currently handle audio cues. There are warning
messages logged for each audio file that should be played. As far as I
know, the only two existing CMV files with audio cues in them are in the
examples folder mentioned above.

Signed-off-by: Ben Lubar <ben at lubar.me>
---
 Changelog                |   1 +
 configure                |   1 +
 doc/general.texi         |   2 +
 libavcodec/Makefile      |   1 +
 libavcodec/allcodecs.c   |   1 +
 libavcodec/avcodec.h     |   1 +
 libavcodec/codec_desc.c  |   7 +
 libavcodec/dfcmv.c       | 383 +++++++++++++++++++++++++++++++++++++++
 libavcodec/version.h     |   4 +-
 libavformat/Makefile     |   1 +
 libavformat/allformats.c |   1 +
 libavformat/dfcmv.c      | 222 +++++++++++++++++++++++
 libavformat/version.h    |   2 +-
 13 files changed, 624 insertions(+), 3 deletions(-)
 create mode 100644 libavcodec/dfcmv.c
 create mode 100644 libavformat/dfcmv.c

diff --git a/Changelog b/Changelog
index f30f398a9f..eed4fa8a50 100644
--- a/Changelog
+++ b/Changelog
@@ -27,6 +27,7 @@ version <next>:
 - axcorrelate filter
 - mvdv decoder
 - mvha decoder
+- Dwarf Fortress CMV demuxer and decoder


 version 4.2:
diff --git a/configure b/configure
index ca7137f341..622deed689 100755
--- a/configure
+++ b/configure
@@ -3258,6 +3258,7 @@ caf_demuxer_select="iso_media riffdec"
 caf_muxer_select="iso_media"
 dash_muxer_select="mp4_muxer"
 dash_demuxer_deps="libxml2"
+dfcmv_demuxer_deps="zlib"
 dirac_demuxer_select="dirac_parser"
 dts_demuxer_select="dca_parser"
 dtshd_demuxer_select="dca_parser"
diff --git a/doc/general.texi b/doc/general.texi
index a5b77e0de1..bbc90a2f58 100644
--- a/doc/general.texi
+++ b/doc/general.texi
@@ -429,6 +429,7 @@ library:
     @tab Video format used by CD+G karaoke disks
 @item Phantom Cine              @tab   @tab X
 @item Cineform HD               @tab   @tab X
+ at item Dwarf Fortress Curses MoVie (.cmv files)  @tab   @tab X
 @item Commodore CDXL            @tab   @tab X
     @tab Amiga CD video format
 @item Core Audio Format         @tab X @tab X
@@ -843,6 +844,7 @@ following image formats are supported:
 @item Delphine Software International CIN video  @tab     @tab  X
     @tab Codec used in Delphine Software International games.
 @item Discworld II BMV Video @tab     @tab  X
+ at item Dwarf Fortess Curses MoVie (CMV)  @tab     @tab  X
 @item Canopus Lossless Codec @tab     @tab  X
 @item Cinepak                @tab     @tab  X
 @item Cirrus Logic AccuPak   @tab  X  @tab  X
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index c1f35b40d8..24e146e90f 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -267,6 +267,7 @@ OBJS-$(CONFIG_DDS_DECODER)             += dds.o
 OBJS-$(CONFIG_DIRAC_DECODER)           += diracdec.o dirac.o
diracdsp.o diractab.o \
                                           dirac_arith.o dirac_dwt.o dirac_vlc.o
 OBJS-$(CONFIG_DFA_DECODER)             += dfa.o
+OBJS-$(CONFIG_DFCMV_DECODER)           += dfcmv.o
 OBJS-$(CONFIG_DNXHD_DECODER)           += dnxhddec.o dnxhddata.o
 OBJS-$(CONFIG_DNXHD_ENCODER)           += dnxhdenc.o dnxhddata.o
 OBJS-$(CONFIG_DOLBY_E_DECODER)         += dolby_e.o kbdwin.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index c33edf23c9..8571cce906 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -83,6 +83,7 @@ extern AVCodec ff_cscd_decoder;
 extern AVCodec ff_cyuv_decoder;
 extern AVCodec ff_dds_decoder;
 extern AVCodec ff_dfa_decoder;
+extern AVCodec ff_dfcmv_decoder;
 extern AVCodec ff_dirac_decoder;
 extern AVCodec ff_dnxhd_encoder;
 extern AVCodec ff_dnxhd_decoder;
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 735a3c2d76..bd0446fe92 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -410,6 +410,7 @@ enum AVCodecID {
     AV_CODEC_ID_SCREENPRESSO,
     AV_CODEC_ID_RSCC,
     AV_CODEC_ID_AVS2,
+    AV_CODEC_ID_DFCMV,

     AV_CODEC_ID_Y41P = 0x8000,
     AV_CODEC_ID_AVRP,
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 570bd2f382..4ce8416b8e 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -1403,6 +1403,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("AVS2-P2/IEEE1857.4"),
         .props     = AV_CODEC_PROP_LOSSY,
     },
+    {
+        .id        = AV_CODEC_ID_DFCMV,
+        .type      = AVMEDIA_TYPE_VIDEO,
+        .name      = "dfcmv",
+        .long_name = NULL_IF_CONFIG_SMALL("Dwarf Fortress Curses MoVie"),
+        .props     = AV_CODEC_PROP_INTRA_ONLY,
+    },
     {
         .id        = AV_CODEC_ID_Y41P,
         .type      = AVMEDIA_TYPE_VIDEO,
diff --git a/libavcodec/dfcmv.c b/libavcodec/dfcmv.c
new file mode 100644
index 0000000000..2c692ca9bd
--- /dev/null
+++ b/libavcodec/dfcmv.c
@@ -0,0 +1,383 @@
+#include "avcodec.h"
+#include "internal.h"
+#include "thread.h"
+#include "libavutil/imgutils.h"
+
+typedef struct DFCMVCodecContext {
+    uint32_t width, height;
+    uint32_t half_frame_size;
+    uint32_t frame_size;
+} DFCMVCodecContext;
+
+static av_cold int dfcmv_init_decoder(AVCodecContext *avctx) {
+    DFCMVCodecContext *cmv = avctx->priv_data;
+    int ret;
+
+    ret = av_image_check_size(avctx->width, avctx->height, 0, avctx);
+    if (ret < 0) {
+        return ret;
+    }
+
+    cmv->width = avctx->width / 10;
+    cmv->height = avctx->height / 12;
+    cmv->half_frame_size = cmv->width * cmv->height;
+    cmv->frame_size = 2 * cmv->half_frame_size;
+    avctx->pix_fmt = AV_PIX_FMT_PAL8;
+
+    return 0;
+}
+
+static uint32_t dfcmv_palette[] = {
+    0xff000000,
+    0xff000080,
+    0xff008000,
+    0xff008080,
+    0xff800000,
+    0xff800080,
+    0xff808000,
+    0xffc0c0c0,
+    0xff808080,
+    0xff0000ff,
+    0xff00ff00,
+    0xff00ffff,
+    0xffff0000,
+    0xffff00ff,
+    0xffffff00,
+    0xffffffff,
+    0xff000000,
+    0xff000060,
+    0xff006000,
+    0xff006060,
+    0xff600000,
+    0xff600060,
+    0xff606000,
+    0xff909090,
+    0xff606060,
+    0xff0000c0,
+    0xff00c000,
+    0xff00c0c0,
+    0xffc00000,
+    0xffc000c0,
+    0xffc0c000,
+    0xffc0c0c0,
+};
+
+// 2 bpp, palette = bg,fg,fg_faded,unused; 10x12 pixels per sprite;
padded by 12 bits per row to 32 bits
+static uint32_t dfcmv_sprites[256][12] = {
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x005550, 0x010004, 0x010004, 0x011044, 0x020008,
0x02aaa8, 0x028528, 0x02aaa8, 0x00aaa0, 0x002a00, 0x002800},
+    {0x000000, 0x005550, 0x015554, 0x015554, 0x014514, 0x025558,
0x02aaa8, 0x029068, 0x02aaa8, 0x00aaa0, 0x002a00, 0x002800},
+    {0x000000, 0x000000, 0x001010, 0x005454, 0x005554, 0x005554,
0x005554, 0x001550, 0x000540, 0x000100, 0x000000, 0x000000},
+    {0x000000, 0x000100, 0x000540, 0x001550, 0x005554, 0x005554,
0x001550, 0x000540, 0x000100, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000500, 0x001540, 0x001540, 0x015554, 0x015054,
0x015054, 0x000500, 0x000500, 0x005550, 0x000000, 0x000000},
+    {0x000000, 0x000500, 0x001540, 0x005550, 0x015554, 0x015554,
0x005550, 0x000500, 0x000500, 0x005550, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x001540, 0x005550,
0x005550, 0x001540, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x055555, 0x055555, 0x055555, 0x055555, 0x054015, 0x050005,
0x050005, 0x054015, 0x055555, 0x055555, 0x055555, 0x055555},
+    {0x000000, 0x000000, 0x001540, 0x005550, 0x005050, 0x004010,
0x004010, 0x005050, 0x005550, 0x001540, 0x000000, 0x000000},
+    {0x055555, 0x055555, 0x054015, 0x050005, 0x050505, 0x051545,
0x051545, 0x050505, 0x050005, 0x054015, 0x055555, 0x055555},
+    {0x000000, 0x005540, 0x005400, 0x004540, 0x004150, 0x000554,
0x001414, 0x001414, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x000000, 0x001540, 0x005050, 0x005050, 0x005050, 0x001540,
0x000500, 0x005550, 0x000500, 0x000500, 0x000000, 0x000000},
+    {0x000000, 0x015500, 0x010500, 0x010500, 0x015500, 0x000500,
0x000500, 0x000550, 0x000554, 0x000150, 0x000000, 0x000000},
+    {0x000000, 0x015550, 0x014050, 0x015550, 0x014050, 0x014050,
0x014050, 0x015050, 0x015054, 0x005054, 0x000014, 0x000000},
+    {0x000000, 0x000000, 0x000500, 0x014514, 0x005550, 0x015054,
0x015054, 0x005550, 0x014514, 0x000500, 0x000000, 0x000000},
+    {0x000000, 0x000004, 0x000014, 0x000054, 0x000554, 0x005554,
0x000554, 0x000054, 0x000014, 0x000004, 0x000000, 0x000000},
+    {0x000000, 0x004000, 0x005000, 0x005400, 0x005540, 0x005554,
0x005540, 0x005400, 0x005000, 0x004000, 0x000000, 0x000000},
+    {0x000000, 0x000500, 0x001540, 0x005550, 0x000500, 0x000500,
0x000500, 0x005550, 0x001540, 0x000500, 0x000000, 0x000000},
+    {0x000000, 0x005050, 0x005050, 0x005050, 0x005050, 0x005050,
0x000000, 0x000000, 0x005050, 0x005050, 0x000000, 0x000000},
+    {0x000000, 0x015550, 0x014514, 0x014514, 0x014514, 0x014550,
0x014500, 0x014500, 0x014500, 0x014500, 0x000000, 0x000000},
+    {0x000000, 0x005550, 0x014050, 0x000140, 0x001540, 0x005050,
0x005050, 0x001540, 0x001400, 0x005014, 0x005550, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x005554, 0x005554, 0x005554, 0x000000, 0x000000},
+    {0x000000, 0x000500, 0x001540, 0x005550, 0x000500, 0x000500,
0x000500, 0x005550, 0x001540, 0x000500, 0x005550, 0x000000},
+    {0x000000, 0x000500, 0x001540, 0x005550, 0x000500, 0x000500,
0x000500, 0x000500, 0x000500, 0x000500, 0x000000, 0x000000},
+    {0x000000, 0x000500, 0x000500, 0x000500, 0x000500, 0x000500,
0x000500, 0x005550, 0x001540, 0x000500, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000500, 0x001400, 0x005554,
0x001400, 0x000500, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000140, 0x000050, 0x005554,
0x000050, 0x000140, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000014, 0x000014,
0x000014, 0x005554, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x001040, 0x005050, 0x015554,
0x005050, 0x001040, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000100, 0x000100, 0x000540, 0x000540,
0x001550, 0x001550, 0x005554, 0x005554, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x005554, 0x005554, 0x001550, 0x001550,
0x000540, 0x000540, 0x000100, 0x000100, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000140, 0x000550, 0x000550, 0x000550, 0x000140,
0x000140, 0x000000, 0x000140, 0x000140, 0x000000, 0x000000},
+    {0x000000, 0x005050, 0x005050, 0x005050, 0x001040, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x001450, 0x001450, 0x005554, 0x001450, 0x001450,
0x001450, 0x005554, 0x001450, 0x001450, 0x000000, 0x000000},
+    {0x000140, 0x000140, 0x001550, 0x000014, 0x000014, 0x000550,
0x001400, 0x001400, 0x000554, 0x000140, 0x000140, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x001014, 0x001414, 0x000500,
0x000140, 0x000050, 0x001414, 0x001404, 0x000000, 0x000000},
+    {0x000000, 0x000150, 0x000514, 0x000514, 0x000150, 0x004554,
0x005514, 0x001414, 0x001514, 0x005150, 0x000000, 0x000000},
+    {0x000000, 0x000140, 0x000140, 0x000140, 0x000050, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x001400, 0x000500, 0x000140, 0x000050, 0x000050,
0x000050, 0x000140, 0x000500, 0x001400, 0x000000, 0x000000},
+    {0x000000, 0x000050, 0x000140, 0x000500, 0x001400, 0x001400,
0x001400, 0x000500, 0x000140, 0x000050, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x005050, 0x001540, 0x015554,
0x001540, 0x005050, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000500, 0x000500, 0x005550,
0x000500, 0x000500, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000540, 0x000540, 0x000050, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x005555,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000540, 0x000540, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x004000, 0x005000, 0x001400, 0x000500,
0x000140, 0x000050, 0x000014, 0x000004, 0x000000, 0x000000},
+    {0x000000, 0x001550, 0x005014, 0x005414, 0x005514, 0x005114,
0x005154, 0x005054, 0x005014, 0x001550, 0x000000, 0x000000},
+    {0x000000, 0x000100, 0x000140, 0x000154, 0x000140, 0x000140,
0x000140, 0x000140, 0x000140, 0x001554, 0x000000, 0x000000},
+    {0x000000, 0x000550, 0x001414, 0x001414, 0x001400, 0x000500,
0x000140, 0x000050, 0x001414, 0x001554, 0x000000, 0x000000},
+    {0x000000, 0x000550, 0x001414, 0x001400, 0x001400, 0x000540,
0x001400, 0x001400, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x000000, 0x001400, 0x001500, 0x001540, 0x001450, 0x001414,
0x005554, 0x001400, 0x001400, 0x005500, 0x000000, 0x000000},
+    {0x000000, 0x001554, 0x000014, 0x000014, 0x000014, 0x000554,
0x001400, 0x001400, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x000000, 0x000540, 0x000050, 0x000014, 0x000014, 0x000554,
0x001414, 0x001414, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x000000, 0x005554, 0x005014, 0x005014, 0x005000, 0x001400,
0x000500, 0x000140, 0x000140, 0x000140, 0x000000, 0x000000},
+    {0x000000, 0x000550, 0x001414, 0x001414, 0x001454, 0x000550,
0x001514, 0x001414, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x000000, 0x000550, 0x001414, 0x001414, 0x001414, 0x001550,
0x000500, 0x000500, 0x000140, 0x000150, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000540, 0x000540, 0x000000,
0x000000, 0x000540, 0x000540, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000540, 0x000540, 0x000000,
0x000000, 0x000540, 0x000540, 0x000500, 0x000140, 0x000000},
+    {0x000000, 0x001400, 0x000500, 0x000140, 0x000050, 0x000014,
0x000050, 0x000140, 0x000500, 0x001400, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x005550, 0x000000,
0x005550, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000050, 0x000140, 0x000500, 0x001400, 0x005000,
0x001400, 0x000500, 0x000140, 0x000050, 0x000000, 0x000000},
+    {0x000000, 0x000550, 0x001414, 0x001400, 0x000500, 0x000140,
0x000140, 0x000000, 0x000140, 0x000140, 0x000000, 0x000000},
+    {0x000000, 0x001550, 0x005014, 0x005014, 0x005514, 0x005514,
0x005514, 0x000014, 0x000014, 0x001550, 0x000000, 0x000000},
+    {0x000000, 0x000140, 0x000550, 0x001414, 0x001414, 0x001414,
0x001554, 0x001414, 0x001414, 0x001414, 0x000000, 0x000000},
+    {0x000000, 0x001554, 0x005050, 0x005050, 0x005050, 0x001550,
0x005050, 0x005050, 0x005050, 0x001554, 0x000000, 0x000000},
+    {0x000000, 0x001540, 0x005050, 0x005014, 0x000014, 0x000014,
0x000014, 0x005014, 0x005050, 0x001540, 0x000000, 0x000000},
+    {0x000000, 0x000554, 0x001450, 0x005050, 0x005050, 0x005050,
0x005050, 0x005050, 0x001450, 0x000554, 0x000000, 0x000000},
+    {0x000000, 0x005554, 0x004050, 0x000050, 0x001050, 0x001550,
0x001050, 0x000050, 0x004050, 0x005554, 0x000000, 0x000000},
+    {0x000000, 0x005554, 0x005050, 0x004050, 0x001050, 0x001550,
0x001050, 0x000050, 0x000050, 0x000154, 0x000000, 0x000000},
+    {0x000000, 0x001540, 0x005050, 0x005014, 0x000014, 0x000014,
0x005414, 0x005014, 0x005050, 0x005540, 0x000000, 0x000000},
+    {0x000000, 0x001414, 0x001414, 0x001414, 0x001414, 0x001554,
0x001414, 0x001414, 0x001414, 0x001414, 0x000000, 0x000000},
+    {0x000000, 0x000550, 0x000140, 0x000140, 0x000140, 0x000140,
0x000140, 0x000140, 0x000140, 0x000550, 0x000000, 0x000000},
+    {0x000000, 0x005500, 0x001400, 0x001400, 0x001400, 0x001400,
0x001414, 0x001414, 0x001410, 0x000550, 0x000000, 0x000000},
+    {0x000000, 0x005054, 0x005050, 0x001450, 0x001450, 0x000550,
0x001450, 0x001450, 0x005050, 0x005054, 0x000000, 0x000000},
+    {0x000000, 0x000154, 0x000050, 0x000050, 0x000050, 0x000050,
0x004050, 0x005050, 0x005050, 0x005554, 0x000000, 0x000000},
+    {0x000000, 0x005014, 0x005454, 0x005554, 0x005554, 0x005114,
0x005014, 0x005014, 0x005014, 0x005014, 0x000000, 0x000000},
+    {0x000000, 0x005014, 0x005014, 0x005054, 0x005154, 0x005554,
0x005514, 0x005414, 0x005014, 0x005014, 0x000000, 0x000000},
+    {0x000000, 0x000540, 0x001450, 0x005014, 0x005014, 0x005014,
0x005014, 0x005014, 0x001450, 0x000540, 0x000000, 0x000000},
+    {0x000000, 0x001554, 0x005050, 0x005050, 0x005050, 0x001550,
0x000050, 0x000050, 0x000050, 0x000154, 0x000000, 0x000000},
+    {0x000000, 0x000540, 0x001450, 0x005014, 0x005014, 0x005014,
0x005414, 0x005514, 0x001550, 0x001400, 0x005500, 0x000000},
+    {0x000000, 0x001554, 0x005050, 0x005050, 0x005050, 0x001550,
0x001450, 0x005050, 0x005050, 0x005054, 0x000000, 0x000000},
+    {0x000000, 0x000550, 0x001414, 0x001414, 0x000014, 0x000150,
0x000500, 0x001414, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x000000, 0x001554, 0x001144, 0x000140, 0x000140, 0x000140,
0x000140, 0x000140, 0x000140, 0x000550, 0x000000, 0x000000},
+    {0x000000, 0x001414, 0x001414, 0x001414, 0x001414, 0x001414,
0x001414, 0x001414, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x000000, 0x001414, 0x001414, 0x001414, 0x001414, 0x001414,
0x001414, 0x001414, 0x000550, 0x000140, 0x000000, 0x000000},
+    {0x000000, 0x005014, 0x005014, 0x005014, 0x005014, 0x005114,
0x005114, 0x001450, 0x001450, 0x001450, 0x000000, 0x000000},
+    {0x000000, 0x001414, 0x001414, 0x001414, 0x000550, 0x000140,
0x000550, 0x001414, 0x001414, 0x001414, 0x000000, 0x000000},
+    {0x000000, 0x001414, 0x001414, 0x001414, 0x001410, 0x000550,
0x000140, 0x000140, 0x000140, 0x000550, 0x000000, 0x000000},
+    {0x000000, 0x005554, 0x005414, 0x000504, 0x000500, 0x000140,
0x000050, 0x004050, 0x005014, 0x005554, 0x000000, 0x000000},
+    {0x000000, 0x001540, 0x000140, 0x000140, 0x000140, 0x000140,
0x000140, 0x000140, 0x000140, 0x001540, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000004, 0x000014, 0x000050, 0x000140,
0x000500, 0x001400, 0x005000, 0x004000, 0x000000, 0x000000},
+    {0x000000, 0x001540, 0x001400, 0x001400, 0x001400, 0x001400,
0x001400, 0x001400, 0x001400, 0x001540, 0x000000, 0x000000},
+    {0x000100, 0x000540, 0x001450, 0x005014, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x055555, 0x000000},
+    {0x000140, 0x000140, 0x000500, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000550, 0x001400,
0x001550, 0x001414, 0x001414, 0x005150, 0x000000, 0x000000},
+    {0x000000, 0x000054, 0x000050, 0x000050, 0x001550, 0x005050,
0x005050, 0x005050, 0x005050, 0x001514, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000550, 0x001414,
0x000014, 0x000014, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x000000, 0x001500, 0x001400, 0x001400, 0x001550, 0x001414,
0x001414, 0x001414, 0x001414, 0x005150, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000550, 0x001414,
0x001554, 0x000014, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x000000, 0x000540, 0x001450, 0x000050, 0x000050, 0x000554,
0x000050, 0x000050, 0x000050, 0x000154, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x005150, 0x001414,
0x001414, 0x001414, 0x001550, 0x001400, 0x001414, 0x000550},
+    {0x000000, 0x000054, 0x000050, 0x000050, 0x001450, 0x005150,
0x005050, 0x005050, 0x005050, 0x005054, 0x000000, 0x000000},
+    {0x000000, 0x000500, 0x000500, 0x000000, 0x000550, 0x000500,
0x000500, 0x000500, 0x000500, 0x005550, 0x000000, 0x000000},
+    {0x000000, 0x001400, 0x001400, 0x000000, 0x001540, 0x001400,
0x001400, 0x001400, 0x001400, 0x001414, 0x001414, 0x000550},
+    {0x000000, 0x000054, 0x000050, 0x000050, 0x005050, 0x001450,
0x000550, 0x001450, 0x005050, 0x005054, 0x000000, 0x000000},
+    {0x000000, 0x000550, 0x000500, 0x000500, 0x000500, 0x000500,
0x000500, 0x000500, 0x000500, 0x005550, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x001554, 0x005114,
0x005114, 0x005114, 0x005114, 0x005014, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000554, 0x001414,
0x001414, 0x001414, 0x001414, 0x001414, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000550, 0x001414,
0x001414, 0x001414, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x001514, 0x005050,
0x005050, 0x005050, 0x005050, 0x001550, 0x000050, 0x000154},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x005150, 0x001414,
0x001414, 0x001414, 0x001414, 0x001550, 0x001400, 0x005500},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x001454, 0x005450,
0x005150, 0x000050, 0x000050, 0x000154, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000550, 0x001414,
0x000050, 0x000500, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000040, 0x000050, 0x001554, 0x000050,
0x000050, 0x000050, 0x001450, 0x000540, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x001414, 0x001414,
0x001414, 0x001414, 0x001414, 0x005150, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x001414, 0x001414,
0x001414, 0x001414, 0x000550, 0x000140, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x005014, 0x005014,
0x005114, 0x005114, 0x001450, 0x001450, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x005014, 0x001450,
0x000540, 0x000540, 0x001450, 0x005014, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x005050, 0x005050,
0x005050, 0x005050, 0x001540, 0x001400, 0x000500, 0x000154},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x001554, 0x001404,
0x000500, 0x000050, 0x001014, 0x001554, 0x000000, 0x000000},
+    {0x000000, 0x001500, 0x000140, 0x000140, 0x000050, 0x000014,
0x000050, 0x000140, 0x000140, 0x001500, 0x000000, 0x000000},
+    {0x000000, 0x000500, 0x000500, 0x000500, 0x000500, 0x000000,
0x000500, 0x000500, 0x000500, 0x000500, 0x000000, 0x000000},
+    {0x000000, 0x000054, 0x000140, 0x000140, 0x000500, 0x001400,
0x000500, 0x000140, 0x000140, 0x000054, 0x000000, 0x000000},
+    {0x000000, 0x014150, 0x004514, 0x005414, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000100, 0x000540, 0x001450,
0x005014, 0x005014, 0x005554, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000550, 0x001414, 0x001414, 0x000014, 0x000014,
0x000014, 0x001414, 0x001414, 0x000550, 0x000140, 0x000154},
+    {0x000000, 0x001414, 0x001414, 0x000000, 0x001414, 0x001414,
0x001414, 0x001414, 0x001414, 0x005150, 0x000000, 0x000000},
+    {0x001400, 0x000500, 0x000140, 0x000000, 0x000550, 0x001414,
0x001554, 0x000014, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x000140, 0x000550, 0x001414, 0x000000, 0x000550, 0x001400,
0x001550, 0x001414, 0x001414, 0x005150, 0x000000, 0x000000},
+    {0x000000, 0x001414, 0x001414, 0x000000, 0x000550, 0x001400,
0x001550, 0x001414, 0x001414, 0x005150, 0x000000, 0x000000},
+    {0x000014, 0x000050, 0x000140, 0x000000, 0x000550, 0x001400,
0x001550, 0x001414, 0x001414, 0x005150, 0x000000, 0x000000},
+    {0x000540, 0x001450, 0x001450, 0x000540, 0x000554, 0x001400,
0x001550, 0x001414, 0x001414, 0x005150, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000550, 0x001414,
0x000014, 0x000014, 0x001414, 0x000550, 0x000140, 0x000154},
+    {0x000140, 0x000550, 0x001414, 0x000000, 0x000550, 0x001414,
0x001554, 0x000014, 0x000014, 0x001550, 0x000000, 0x000000},
+    {0x000000, 0x001414, 0x001414, 0x000000, 0x000550, 0x001414,
0x001554, 0x000014, 0x000014, 0x001550, 0x000000, 0x000000},
+    {0x000014, 0x000050, 0x000140, 0x000000, 0x000550, 0x001414,
0x001554, 0x000014, 0x000014, 0x001550, 0x000000, 0x000000},
+    {0x000000, 0x001450, 0x001450, 0x000000, 0x000550, 0x000500,
0x000500, 0x000500, 0x000500, 0x005550, 0x000000, 0x000000},
+    {0x000100, 0x000540, 0x001450, 0x000000, 0x000550, 0x000500,
0x000500, 0x000500, 0x000500, 0x005550, 0x000000, 0x000000},
+    {0x000050, 0x000140, 0x000500, 0x000000, 0x000550, 0x000500,
0x000500, 0x000500, 0x000500, 0x005550, 0x000000, 0x000000},
+    {0x000000, 0x001414, 0x000000, 0x000140, 0x000550, 0x001414,
0x001414, 0x001554, 0x001414, 0x001414, 0x000000, 0x000000},
+    {0x000550, 0x001414, 0x001414, 0x000550, 0x000550, 0x001414,
0x001414, 0x001554, 0x001414, 0x001414, 0x000000, 0x000000},
+    {0x001400, 0x000500, 0x000140, 0x001554, 0x001014, 0x000014,
0x000554, 0x000014, 0x001014, 0x001554, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x005554, 0x014500,
0x015550, 0x000514, 0x000514, 0x015454, 0x000000, 0x000000},
+    {0x000000, 0x015540, 0x001550, 0x001414, 0x001414, 0x015554,
0x001414, 0x001414, 0x001414, 0x015414, 0x000000, 0x000000},
+    {0x000140, 0x000550, 0x001414, 0x000000, 0x000550, 0x001414,
0x001414, 0x001414, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x000000, 0x001414, 0x001414, 0x000000, 0x000550, 0x001414,
0x001414, 0x001414, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x000014, 0x000050, 0x000140, 0x000000, 0x000550, 0x001414,
0x001414, 0x001414, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x000140, 0x000550, 0x001414, 0x000000, 0x001414, 0x001414,
0x001414, 0x001414, 0x001414, 0x005150, 0x000000, 0x000000},
+    {0x000014, 0x000050, 0x000140, 0x000000, 0x001414, 0x001414,
0x001414, 0x001414, 0x001414, 0x005150, 0x000000, 0x000000},
+    {0x000000, 0x005050, 0x005050, 0x000000, 0x005050, 0x005050,
0x005050, 0x005050, 0x001540, 0x001400, 0x000500, 0x000154},
+    {0x001414, 0x000000, 0x000550, 0x001414, 0x001414, 0x001414,
0x001414, 0x001414, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x001414, 0x000000, 0x001414, 0x001414, 0x001414, 0x001414,
0x001414, 0x001414, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x000000, 0x000140, 0x000140, 0x000550, 0x001414, 0x000014,
0x000014, 0x001414, 0x000550, 0x000140, 0x000140, 0x000000},
+    {0x001540, 0x005050, 0x000050, 0x000050, 0x000050, 0x001554,
0x000050, 0x000050, 0x000014, 0x005554, 0x000000, 0x000000},
+    {0x001414, 0x001414, 0x001414, 0x001414, 0x000550, 0x001554,
0x000140, 0x001554, 0x000140, 0x000140, 0x000000, 0x000000},
+    {0x000154, 0x000404, 0x000404, 0x000404, 0x000154, 0x000404,
0x005504, 0x001404, 0x011404, 0x005004, 0x000000, 0x000000},
+    {0x005400, 0x014500, 0x000500, 0x000500, 0x005550, 0x000500,
0x000500, 0x000500, 0x000514, 0x000150, 0x000000, 0x000000},
+    {0x001400, 0x000500, 0x000140, 0x000000, 0x000550, 0x001400,
0x001550, 0x001414, 0x001414, 0x005150, 0x000000, 0x000000},
+    {0x001400, 0x000500, 0x000140, 0x000000, 0x000550, 0x000500,
0x000500, 0x000500, 0x000500, 0x005550, 0x000000, 0x000000},
+    {0x001400, 0x000500, 0x000140, 0x000000, 0x000550, 0x001414,
0x001414, 0x001414, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x001400, 0x000500, 0x000140, 0x000000, 0x001414, 0x001414,
0x001414, 0x001414, 0x001414, 0x005150, 0x000000, 0x000000},
+    {0x000000, 0x005150, 0x001514, 0x000000, 0x000554, 0x001414,
0x001414, 0x001414, 0x001414, 0x001414, 0x000000, 0x000000},
+    {0x005150, 0x001514, 0x000000, 0x005014, 0x005054, 0x005154,
0x005514, 0x005414, 0x005014, 0x005014, 0x000000, 0x000000},
+    {0x000000, 0x000550, 0x001414, 0x001414, 0x005550, 0x000000,
0x005554, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000550, 0x001414, 0x001414, 0x000550, 0x000000,
0x005554, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000140, 0x000140, 0x000000, 0x000140, 0x000050,
0x000014, 0x000014, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x001554,
0x000014, 0x000014, 0x000014, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x001554,
0x001400, 0x001400, 0x001400, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x004010, 0x005014, 0x001414, 0x000514, 0x000140,
0x005450, 0x014014, 0x005004, 0x001400, 0x015500, 0x000000},
+    {0x000000, 0x014050, 0x005054, 0x001450, 0x000550, 0x015140,
0x015450, 0x014514, 0x014144, 0x015540, 0x014000, 0x000000},
+    {0x000000, 0x000140, 0x000140, 0x000000, 0x000140, 0x000140,
0x000550, 0x000550, 0x000550, 0x000140, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x014140, 0x005050,
0x001414, 0x001414, 0x005050, 0x014140, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x001414, 0x005050,
0x014140, 0x014140, 0x005050, 0x001414, 0x000000, 0x000000},
+    {0x001041, 0x004104, 0x010410, 0x041041, 0x004104, 0x010410,
0x041041, 0x004104, 0x010410, 0x041041, 0x004104, 0x010410},
+    {0x011111, 0x044444, 0x011111, 0x044444, 0x011111, 0x044444,
0x011111, 0x044444, 0x011111, 0x044444, 0x011111, 0x044444},
+    {0x051451, 0x014514, 0x045145, 0x051451, 0x014514, 0x045145,
0x051451, 0x014514, 0x045145, 0x051451, 0x014514, 0x045145},
+    {0x000500, 0x000500, 0x000500, 0x000500, 0x000500, 0x000500,
0x000500, 0x000500, 0x000500, 0x000500, 0x000500, 0x000500},
+    {0x000500, 0x000500, 0x000500, 0x000500, 0x000500, 0x000555,
0x000500, 0x000500, 0x000500, 0x000500, 0x000500, 0x000500},
+    {0x000500, 0x000500, 0x000500, 0x000500, 0x000555, 0x000500,
0x000500, 0x000555, 0x000500, 0x000500, 0x000500, 0x000500},
+    {0x005050, 0x005050, 0x005050, 0x005050, 0x005050, 0x005055,
0x005050, 0x005050, 0x005050, 0x005050, 0x005050, 0x005050},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x005555,
0x005050, 0x005050, 0x005050, 0x005050, 0x005050, 0x005050},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000555, 0x000500,
0x000500, 0x000555, 0x000500, 0x000500, 0x000500, 0x000500},
+    {0x005050, 0x005050, 0x005050, 0x005050, 0x005055, 0x005000,
0x005000, 0x005055, 0x005050, 0x005050, 0x005050, 0x005050},
+    {0x005050, 0x005050, 0x005050, 0x005050, 0x005050, 0x005050,
0x005050, 0x005050, 0x005050, 0x005050, 0x005050, 0x005050},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x005555, 0x005000,
0x005000, 0x005055, 0x005050, 0x005050, 0x005050, 0x005050},
+    {0x005050, 0x005050, 0x005050, 0x005050, 0x005055, 0x005000,
0x005000, 0x005555, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x005050, 0x005050, 0x005050, 0x005050, 0x005050, 0x005555,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000500, 0x000500, 0x000500, 0x000500, 0x000555, 0x000500,
0x000500, 0x000555, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000555,
0x000500, 0x000500, 0x000500, 0x000500, 0x000500, 0x000500},
+    {0x000500, 0x000500, 0x000500, 0x000500, 0x000500, 0x055500,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000500, 0x000500, 0x000500, 0x000500, 0x000500, 0x055555,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x055555,
0x000500, 0x000500, 0x000500, 0x000500, 0x000500, 0x000500},
+    {0x000500, 0x000500, 0x000500, 0x000500, 0x000500, 0x055500,
0x000500, 0x000500, 0x000500, 0x000500, 0x000500, 0x000500},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x055555,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000500, 0x000500, 0x000500, 0x000500, 0x000500, 0x055555,
0x000500, 0x000500, 0x000500, 0x000500, 0x000500, 0x000500},
+    {0x000500, 0x000500, 0x000500, 0x000500, 0x055500, 0x000500,
0x000500, 0x055500, 0x000500, 0x000500, 0x000500, 0x000500},
+    {0x005050, 0x005050, 0x005050, 0x005050, 0x005050, 0x055050,
0x005050, 0x005050, 0x005050, 0x005050, 0x005050, 0x005050},
+    {0x005050, 0x005050, 0x005050, 0x005050, 0x055050, 0x000050,
0x000050, 0x055550, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x055550, 0x000050,
0x000050, 0x055050, 0x005050, 0x005050, 0x005050, 0x005050},
+    {0x005050, 0x005050, 0x005050, 0x005050, 0x055055, 0x000000,
0x000000, 0x055555, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x055555, 0x000000,
0x000000, 0x055055, 0x005050, 0x005050, 0x005050, 0x005050},
+    {0x005050, 0x005050, 0x005050, 0x005050, 0x055050, 0x000050,
0x000050, 0x055050, 0x005050, 0x005050, 0x005050, 0x005050},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x055555, 0x000000,
0x000000, 0x055555, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x005050, 0x005050, 0x005050, 0x005050, 0x055055, 0x000000,
0x000000, 0x055055, 0x005050, 0x005050, 0x005050, 0x005050},
+    {0x000500, 0x000500, 0x000500, 0x000500, 0x015555, 0x000000,
0x000000, 0x015555, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x005050, 0x005050, 0x005050, 0x005050, 0x005050, 0x055555,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x055555, 0x000000,
0x000000, 0x055555, 0x000500, 0x000500, 0x000500, 0x000500},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x055555,
0x005050, 0x005050, 0x005050, 0x005050, 0x005050, 0x005050},
+    {0x005050, 0x005050, 0x005050, 0x005050, 0x005050, 0x055550,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000500, 0x000500, 0x000500, 0x000500, 0x055500, 0x000500,
0x000500, 0x055500, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x055500, 0x000500,
0x000500, 0x055500, 0x000500, 0x000500, 0x000500, 0x000500},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x055550,
0x005050, 0x005050, 0x005050, 0x005050, 0x005050, 0x005050},
+    {0x005050, 0x005050, 0x005050, 0x005050, 0x005050, 0x055055,
0x005050, 0x005050, 0x005050, 0x005050, 0x005050, 0x005050},
+    {0x000500, 0x000500, 0x000500, 0x000500, 0x055555, 0x000000,
0x000000, 0x055555, 0x000500, 0x000500, 0x000500, 0x000500},
+    {0x000500, 0x000500, 0x000500, 0x000500, 0x000500, 0x000555,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x055500,
0x000500, 0x000500, 0x000500, 0x000500, 0x000500, 0x000500},
+    {0x055555, 0x055555, 0x055555, 0x055555, 0x055555, 0x055555,
0x055555, 0x055555, 0x055555, 0x055555, 0x055555, 0x055555},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x055555, 0x055555, 0x055555, 0x055555, 0x055555, 0x055555},
+    {0x000555, 0x000555, 0x000555, 0x000555, 0x000555, 0x000555,
0x000555, 0x000555, 0x000555, 0x000555, 0x000555, 0x000555},
+    {0x055400, 0x055400, 0x055400, 0x055400, 0x055400, 0x055400,
0x055400, 0x055400, 0x055400, 0x055400, 0x055400, 0x055400},
+    {0x055555, 0x055555, 0x055555, 0x055555, 0x055555, 0x055555,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x005150, 0x005514,
0x001414, 0x001414, 0x005514, 0x005150, 0x000000, 0x000000},
+    {0x000000, 0x000550, 0x001414, 0x001414, 0x000514, 0x001414,
0x001414, 0x001414, 0x000554, 0x000014, 0x000050, 0x000000},
+    {0x000000, 0x001554, 0x001414, 0x001414, 0x000014, 0x000014,
0x000014, 0x000014, 0x000014, 0x000014, 0x000000, 0x000000},
+    {0x000000, 0x005554, 0x001450, 0x001450, 0x001450, 0x001450,
0x001450, 0x001450, 0x001450, 0x005050, 0x000000, 0x000000},
+    {0x000000, 0x001554, 0x001014, 0x001050, 0x000050, 0x000140,
0x000050, 0x001050, 0x001014, 0x001554, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x005550, 0x000414,
0x001414, 0x001414, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x005050, 0x005050,
0x005050, 0x005050, 0x005050, 0x014550, 0x000050, 0x000014},
+    {0x000000, 0x000000, 0x000000, 0x005150, 0x001514, 0x000500,
0x000500, 0x000500, 0x000500, 0x005400, 0x000000, 0x000000},
+    {0x000000, 0x001554, 0x000140, 0x000550, 0x001414, 0x001414,
0x001414, 0x000550, 0x000140, 0x001554, 0x000000, 0x000000},
+    {0x000000, 0x001550, 0x005014, 0x005014, 0x005014, 0x005554,
0x005014, 0x005014, 0x005014, 0x001550, 0x000000, 0x000000},
+    {0x000000, 0x005550, 0x014014, 0x014014, 0x014014, 0x014014,
0x005050, 0x005050, 0x005050, 0x015054, 0x000000, 0x000000},
+    {0x000000, 0x001540, 0x000050, 0x000140, 0x000550, 0x001414,
0x001414, 0x001414, 0x001414, 0x000550, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x005150, 0x014514, 0x014514,
0x014514, 0x005450, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x005000, 0x001550, 0x005514, 0x005114,
0x005154, 0x001550, 0x000014, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x001540, 0x000050, 0x000014, 0x000014, 0x001554,
0x000014, 0x000014, 0x000050, 0x001540, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000550, 0x001414, 0x001414, 0x001414,
0x001414, 0x001414, 0x001414, 0x001414, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x001554, 0x000000, 0x000000, 0x001554,
0x000000, 0x000000, 0x001554, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000140, 0x000140, 0x001554, 0x000140,
0x000140, 0x000000, 0x001554, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000050, 0x000140, 0x000500, 0x000500, 0x000140,
0x000050, 0x000000, 0x001554, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000500, 0x000140, 0x000050, 0x000050, 0x000140,
0x000500, 0x000000, 0x001554, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x005400, 0x014500, 0x014500, 0x000500,
0x000500, 0x000500, 0x000500, 0x000500, 0x000500, 0x000500},
+    {0x000500, 0x000500, 0x000500, 0x000500, 0x000500, 0x000500,
0x000500, 0x000514, 0x000514, 0x000150, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000140, 0x000140, 0x000000, 0x001554,
0x000000, 0x000140, 0x000140, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x014150, 0x014514, 0x005414, 0x000000,
0x014150, 0x014514, 0x005414, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x005500, 0x014140, 0x014140, 0x014140, 0x005500,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x005400, 0x005400,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x001400,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x054000, 0x004000, 0x004000, 0x004000, 0x004040,
0x004140, 0x004500, 0x005400, 0x005000, 0x000000, 0x000000},
+    {0x000000, 0x001450, 0x005140, 0x005140, 0x005140, 0x005140,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x001540, 0x005000, 0x001400, 0x000500, 0x005540,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x005500, 0x005500, 0x005500, 0x005500,
0x005500, 0x005500, 0x005500, 0x005500, 0x000000, 0x000000},
+    {0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
+};
+
+static av_cold int dfcmv_close_decoder(AVCodecContext *avctx) {
+    return 0;
+}
+
+static int dfcmv_decode(AVCodecContext *avctx, void *data, int
*got_frame, AVPacket *avpkt) {
+    DFCMVCodecContext *cmv = avctx->priv_data;
+    ThreadFrame frame = { .f = data };
+    AVFrame *p = data;
+    uint8_t attr;
+    uint32_t sprite_row;
+    uint8_t palette[3];
+    int ret;
+    int x, y, x0, y0, x1, y1;
+
+    if (avpkt->size < cmv->frame_size) {
+        av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) {
+        return ret;
+    }
+
+    for (y = 0; y < cmv->height; y++) {
+        y0 = y * 12;
+        for (x = 0; x < cmv->width; x++) {
+            x0 = x * 10;
+            attr = avpkt->data[cmv->half_frame_size + x * cmv->height + y];
+            palette[0] = (attr >> 3) & 7;
+            palette[1] = (attr & 7) | ((attr >> 3) & (1 << 3));
+            palette[2] = palette[1] + 16;
+
+            for (y1 = 0; y1 < 12; y1++) {
+                sprite_row = dfcmv_sprites[avpkt->data[x *
cmv->height + y]][y1];
+                for (x1 = 0; x1 < 10; x1++) {
+                    p->data[0][(x0 + x1) + (y0 + y1) *
p->linesize[0]] = palette[sprite_row & 3];
+                    sprite_row = sprite_row >> 2;
+                }
+            }
+        }
+    }
+    memcpy(p->data[1], dfcmv_palette, sizeof(dfcmv_palette));
+    p->pict_type = AV_PICTURE_TYPE_I;
+    p->key_frame = 1;
+    *got_frame = 1;
+
+    return cmv->frame_size;
+}
+
+AVCodec ff_dfcmv_decoder = {
+    .name           = "dfcmv",
+    .long_name      = NULL_IF_CONFIG_SMALL("Dwarf Fortress Curses MoVie"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_DFCMV,
+    .priv_data_size = sizeof(DFCMVCodecContext),
+    .init           = dfcmv_init_decoder,
+    .close          = dfcmv_close_decoder,
+    .decode         = dfcmv_decode,
+};
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 8b9c27378c..94bcbae2d6 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -28,8 +28,8 @@
 #include "libavutil/version.h"

 #define LIBAVCODEC_VERSION_MAJOR  58
-#define LIBAVCODEC_VERSION_MINOR  64
-#define LIBAVCODEC_VERSION_MICRO 101
+#define LIBAVCODEC_VERSION_MINOR  65
+#define LIBAVCODEC_VERSION_MICRO 100

 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
                                                LIBAVCODEC_VERSION_MINOR, \
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 52f29b1a6d..5850ff3b1c 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -149,6 +149,7 @@ OBJS-$(CONFIG_DAUD_DEMUXER)              += dauddec.o
 OBJS-$(CONFIG_DAUD_MUXER)                += daudenc.o
 OBJS-$(CONFIG_DCSTR_DEMUXER)             += dcstr.o
 OBJS-$(CONFIG_DFA_DEMUXER)               += dfa.o
+OBJS-$(CONFIG_DFCMV_DEMUXER)             += dfcmv.o
 OBJS-$(CONFIG_DHAV_DEMUXER)              += dhav.o
 OBJS-$(CONFIG_DIRAC_DEMUXER)             += diracdec.o rawdec.o
 OBJS-$(CONFIG_DIRAC_MUXER)               += rawenc.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index ff9bdb906f..f2668ded74 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -111,6 +111,7 @@ extern AVInputFormat  ff_daud_demuxer;
 extern AVOutputFormat ff_daud_muxer;
 extern AVInputFormat  ff_dcstr_demuxer;
 extern AVInputFormat  ff_dfa_demuxer;
+extern AVInputFormat  ff_dfcmv_demuxer;
 extern AVInputFormat  ff_dhav_demuxer;
 extern AVInputFormat  ff_dirac_demuxer;
 extern AVOutputFormat ff_dirac_muxer;
diff --git a/libavformat/dfcmv.c b/libavformat/dfcmv.c
new file mode 100644
index 0000000000..01fc67b7c1
--- /dev/null
+++ b/libavformat/dfcmv.c
@@ -0,0 +1,222 @@
+#include <zlib.h>
+#include "libavutil/avstring.h"
+#include "libavutil/intreadwrite.h"
+#include "avformat.h"
+#include "internal.h"
+
+#define DFCMV_VERSION_0 10000
+#define DFCMV_VERSION_1 10001
+
+typedef struct DFCMVContext {
+    int64_t total_frames;
+    uint32_t frame_size;
+    AVBufferRef *buffered_frames;
+    int buf_start, buf_end;
+} DFCMVContext;
+
+static int dfcmv_probe(const AVProbeData *p)
+{
+    if (AV_RL32(p->buf) == DFCMV_VERSION_0 || AV_RL32(p->buf) ==
DFCMV_VERSION_1) {
+        return AVPROBE_SCORE_MAX;
+    }
+
+    return 0;
+}
+
+static int dfcmv_read_header(AVFormatContext *s)
+{
+    int i, j;
+    uint32_t version;
+    uint32_t columns, rows;
+    uint32_t delay_rate;
+    uint32_t sound_count;
+    uint8_t *sound_names;
+    uint32_t sound_timing[200][16];
+    AVStream *st;
+    DFCMVContext *cmv = s->priv_data;
+    AVIOContext *pb = s->pb;
+
+    version = avio_rl32(pb);
+    if (version != DFCMV_VERSION_0 && version != DFCMV_VERSION_1) {
+        av_log(s, AV_LOG_ERROR, "cmv file has invalid version number
%u\n", version);
+        return AVERROR_INVALIDDATA;
+    }
+
+    columns = avio_rl32(pb);
+    rows = avio_rl32(pb);
+    if (columns == 0 || rows == 0) {
+        av_log(s, AV_LOG_ERROR, "cmv file has invalid size %ux%u\n",
columns, rows);
+        return AVERROR_INVALIDDATA;
+    }
+    cmv->frame_size = columns * rows * 2;
+
+    delay_rate = avio_rl32(pb);
+    if (delay_rate == 0) {
+        av_log(s, AV_LOG_WARNING, "cmv file claims to have infinite
frames per second; assuming 50 frames per second\n");
+        delay_rate = 2;
+    }
+
+    st = avformat_new_stream(s, NULL);
+    if (!st) {
+        return AVERROR(ENOMEM);
+    }
+    avpriv_set_pts_info(st, 64, delay_rate, 100);
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id = AV_CODEC_ID_DFCMV;
+    st->codecpar->width = columns * 10;
+    st->codecpar->height = rows * 12;
+    st->start_time = 0;
+
+    if (version >= DFCMV_VERSION_1) {
+        sound_count = avio_rl32(pb);
+
+        sound_names = av_calloc(sound_count, 50);
+        if (!sound_names) {
+            return AVERROR(ENOMEM);
+        }
+
+        if (avio_read(pb, sound_names, sound_count * 50) != sound_count * 50) {
+            av_free(sound_names);
+            return AVERROR(EIO);
+        }
+
+        if (avio_read(pb, (uint8_t *)sound_timing, 4 * 200 * 16) != 4
* 200 * 16) {
+            av_free(sound_names);
+            return AVERROR(EIO);
+        }
+
+        for (i = 0; i < sound_count; i++) {
+            if (!sound_names[50 * i]) {
+                av_free(sound_names);
+                av_log(s, AV_LOG_WARNING, "cmv file contains empty
sound name\n");
+                return AVERROR_INVALIDDATA;
+            }
+            if (av_strnlen(&sound_names[50 * i], 50) == 50) {
+                av_free(sound_names);
+                av_log(s, AV_LOG_WARNING, "cmv file contains
unterminated sound name\n");
+                return AVERROR_INVALIDDATA;
+            }
+        }
+
+        for (i = 0; i < 200; i++) {
+            for (j = 0; j < 16; j++) {
+                if (sound_timing[i][j] < sound_count) {
+                    av_log(s, AV_LOG_WARNING, "cmv: todo: play sound
%s at frame %d (channel %d)\n", &sound_names[50 * sound_timing[i][j]],
i, j);
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int dfcmv_load_chunk(AVFormatContext *s) {
+    int ret;
+    int64_t pos;
+    uint32_t compressed_size, max_size;
+    DFCMVContext *cmv = s->priv_data;
+    AVIOContext *pb = s->pb;
+    AVBufferRef *buf;
+    z_stream zstream = { 0 };
+
+    pos = avio_tell(pb);
+
+    compressed_size = avio_rl32(pb);
+
+    if (avio_feof(pb)) {
+        return avio_tell(pb) == pos ? AVERROR_EOF : AVERROR(EIO);
+    }
+
+    max_size = cmv->frame_size * 200;
+
+    cmv->buffered_frames = av_buffer_alloc(max_size);
+    if (!cmv->buffered_frames) {
+        return AVERROR(ENOMEM);
+    }
+
+    buf = av_buffer_alloc(compressed_size);
+    if (!buf) {
+        return AVERROR(ENOMEM);
+    }
+
+    if (avio_read(pb, buf->data, compressed_size) != compressed_size) {
+        av_buffer_unref(&buf);
+        return AVERROR(EIO);
+    }
+
+    if (inflateInit(&zstream) != Z_OK) {
+        av_buffer_unref(&buf);
+        return -1;
+    }
+
+    zstream.next_in = buf->data;
+    zstream.avail_in = buf->size;
+    zstream.next_out = cmv->buffered_frames->data;
+    zstream.avail_out = max_size;
+
+    ret = inflate(&zstream, Z_FINISH);
+
+    inflateEnd(&zstream);
+    av_buffer_unref(&buf);
+
+    if (ret != Z_STREAM_END || zstream.avail_out % cmv->frame_size != 0) {
+        return -1;
+    }
+
+    cmv->buf_start = 0;
+    cmv->buf_end = (max_size - zstream.avail_out) / cmv->frame_size;
+
+    if (cmv->buf_end == 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+static int dfcmv_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+    DFCMVContext *cmv = s->priv_data;
+    int ret;
+
+    if (cmv->buf_start == cmv->buf_end) {
+        av_buffer_unref(&cmv->buffered_frames);
+
+        if ((ret = dfcmv_load_chunk(s)) < 0) {
+            return ret;
+        }
+    }
+
+    av_init_packet(pkt);
+    pkt->buf = av_buffer_ref(cmv->buffered_frames);
+    if (!pkt->buf) {
+        return AVERROR(ENOMEM);
+    }
+    pkt->data = pkt->buf->data + (cmv->frame_size * cmv->buf_start);
+    pkt->size = cmv->frame_size;
+    pkt->pts = cmv->total_frames;
+    pkt->duration = 0;
+    cmv->total_frames++;
+    cmv->buf_start++;
+
+    return 0;
+}
+
+static int dfcmv_close(AVFormatContext *s)
+{
+    DFCMVContext *cmv = s->priv_data;
+
+    av_buffer_unref(&cmv->buffered_frames);
+
+    return 0;
+}
+
+AVInputFormat ff_dfcmv_demuxer = {
+    .name           = "dfcmv",
+    .long_name      = NULL_IF_CONFIG_SMALL("Dwarf Fortress Curses MoVie"),
+    .priv_data_size = sizeof(DFCMVContext),
+    .read_probe     = dfcmv_probe,
+    .read_header    = dfcmv_read_header,
+    .read_packet    = dfcmv_read_packet,
+    .read_close     = dfcmv_close,
+    .extensions     = "cmv",
+};
diff --git a/libavformat/version.h b/libavformat/version.h
index bac54aed9d..f72fb9478a 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -32,7 +32,7 @@
 // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)
 // Also please add any ticket numbers that you believe might be affected here
 #define LIBAVFORMAT_VERSION_MAJOR  58
-#define LIBAVFORMAT_VERSION_MINOR  35
+#define LIBAVFORMAT_VERSION_MINOR  36
 #define LIBAVFORMAT_VERSION_MICRO 100

 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
-- 
2.24.0


More information about the ffmpeg-devel mailing list