"magic" file entries for R'n'D

Discussion around programming R'n'D, its source code and its tools.

Moderators: Flumminator, Zomis

Post Reply
User avatar
Holger
Site Admin
Posts: 4073
Joined: Fri Jun 18, 2004 4:13 pm
Location: Germany
Contact:

"magic" file entries for R'n'D

Post by Holger »

Hi Unix folks! Ever wanted to identify R'n'D level and tape files by the "file" command?

Code: Select all

aeglos@fangorn:~/.rocksndiamonds$ file levels/testing/002.level
levels/testing/002.level: data
aeglos@fangorn:~/.rocksndiamonds$ file tapes/testing/002.tape
tapes/testing/002.tape: data
aeglos@fangorn:~/.rocksndiamonds$
Not very impressive. :-(

So here are some lines to add to "/etc/magic" to improve this:

Code: Select all

# ========== Rocks'n'Diamonds user data files (new IFF format) ================
0       string          RND1            Rocks'n'Diamonds data

# ---------- Rocks'n'Diamonds level file --------------------------------------
>8      string          CAVE            \b, level file
>>12    string          VERS            \b, version
>>>24   byte            x               %d
>>>25   byte            x               \b.%d
>>>26   byte            x               \b.%d
>>>27   byte            x               \b-%d
>>148   string          AUTH            \b, author
>>>156  string          >\0             "%s"
>>28    string          HEAD            \b, title
>>>42   string          >\0             "%s"
>>>36   byte            x               \b, size %d
>>>37   byte            x               x %d
>>>38   beshort         x               \b, time %d s

# ---------- Rocks'n'Diamonds tape file ---------------------------------------
>8      string          TAPE            \b, tape file
>>12    string          VERS            \b, version
>>>24   byte            x               %d
>>>25   byte            x               \b.%d
>>>26   byte            x               \b.%d
>>>27   byte            x               \b-%d
>>28    string          HEAD            \b, engine
>>>52   byte            x               %d
>>>53   byte            x               \b.%d
>>>54   byte            x               \b.%d
>>>55   byte            x               \b-%d
>>>40   belong          >700000         \b, date 19%06d
>>>40   belong          <700000         \b, date 20%06d
>>56    string          INFO            \b, level set
>>>66   string          >\0             "%s"
>>>>(64.S+66)   beshort x               \b, level %d

# ========== Rocks'n'Diamonds user data files (old, non-IFF format) ===========
0       string          ROCKSNDIAMONDS_ Rocks'n'Diamonds data

# ---------- Rocks'n'Diamonds level file --------------------------------------
>15     string          LEVEL_FILE_     \b, level file
>26     string          VERSION_        \b, version
>>34    string          >\0             %s
>>>44   string          >\0             \b, title "%s"

# ---------- Rocks'n'Diamonds tape file ---------------------------------------
>15     string          TAPE_FILE_      \b, tape file
>25     string          VERSION_        \b, version
>>33    string          >\0             %s
Now you would get the following:

Code: Select all

aeglos@fangorn:~/.rocksndiamonds$ file levels/testing/002.level
levels/testing/002.level: Rocks'n'Diamonds data, level file, version 3.2.0-3, author "Holger Schemel", title "nameless level", size 64 x 32, time 30 s
aeglos@fangorn:~/.rocksndiamonds$ file tapes/testing/002.tape
tapes/testing/002.tape: Rocks'n'Diamonds data, tape file, version 3.2.0-2, level set "testing", level 2
aeglos@fangorn:~/.rocksndiamonds$
Looks better, doesn't it? :-)

*EDIT*

I've updated the "magic" file above -- it was missing the (important) engine version for tape files (plus some minor tweaks). Use the "-b" option of "diff" to see the differences (as this forum seems to not allow decent formatting, and whitespaces will come out different on your side), which shows only the non-whitespace differences (so you don't have to re-format all lines (if you care at all about formatting in your "magic" file, that is ;-) )).
Last edited by Holger on Thu Dec 01, 2005 8:25 am, edited 1 time in total.
User avatar
bojster
Posts: 458
Joined: Fri Jun 18, 2004 7:42 pm
Location: Poland
Contact:

Post by bojster »

Thanks, great idea!
I implemented it and it works perfectly.
Only for 0.9 tapes it displays: "Rocks'n'Diamonds data", but it's still better than just 'data'. ;-)
User avatar
Holger
Site Admin
Posts: 4073
Joined: Fri Jun 18, 2004 4:13 pm
Location: Germany
Contact:

Post by Holger »

I've updated the magic file entry -- see "EDIT" changes above.
filbo
Posts: 647
Joined: Fri Jun 20, 2014 10:06 am

Re: "magic" file entries for R'n'D

Post by filbo »

Here's an updated version with a bunch of small additions (see changelog in comments).

$ file tapes/emc_haunted_mine_4/020.tape
tapes/emc_haunted_mine_4/020.tape: Rocks'n'Diamonds data, file format 3.0, tape file, game 4.3.0.0, engine 4.3.0.0, date 20211001, level set "emc_haunted_mine_4", level 20, actions 1388, player 1, [game_speed], [pause], [single_step], [replayed], [small_graphics]

Code: Select all

# From: http://www.artsoft.org/forum/viewtopic.php?t=588 version of 2005-12-01
#
# Modified by Bela Lubkin:
#
# - added RnD file (format) version
# - changed old 'w.x.y-z' version number format to 'w.x.y.z'
# - added 'actions' count to tape -- this is a crude measure, but
#   at least computable in this context, unlike frames or seconds
# - added player(s) indicator to tape -- note slightly wrong result
#   for 1-player tapes played by players 2/3/4 ('players 3')
# - added display of RnD 4.3.0.0 tape meta-flags
# - fixed display of titles of some old non-IFF levels
# - added recognition of Emerald Mine (version 3, 5, 6) level files
#   (V3 fake-matches the mildly encrypted steel top edge; it correctly
#   identifies all 102 levels of 'classic_emerald_mine$' levelset)

# ========== Rocks'n'Diamonds user data files (new IFF format) ================
0       string          RND1            Rocks'n'Diamonds data
>20     byte            >0              \b, file version %d.
>>21    byte            x               \b%d

# ---------- Rocks'n'Diamonds level file --------------------------------------
>8      string          CAVE            \b, level file
>>12    string          VERS            \b, version
>>>24   byte            x               %d
>>>25   byte            x               \b.%d
>>>26   byte            x               \b.%d
>>>27   byte            x               \b.%d
>>148   string          AUTH            \b, author
>>>156  string          >\0             "%s"
>>28    string          HEAD            \b, title
>>>42   string          >\0             "%s"
>>>36   byte            x               \b, size %d
>>>37   byte            x               x %d
>>>38   beshort         x               \b, time %d s

# ---------- Rocks'n'Diamonds tape file ---------------------------------------
>8      string          TAPE            \b, tape file
>>12    string          VERS            \b, version
>>>24   byte            x               %d
>>>25   byte            x               \b.%d
>>>26   byte            x               \b.%d
>>>27   byte            x               \b.%d
>>28    string          HEAD            \b, engine
>>>52   byte            x               %d
>>>53   byte            x               \b.%d
>>>54   byte            x               \b.%d
>>>55   byte            x               \b.%d
>>>40   belong          >700000         \b, date 19%06d
>>>40   belong          <700000         \b, date 20%06d
>>56    string          INFO            \b, level set
>>>66   string          >\0             "%s"
>>>>(64.S+66)   beshort x               \b, level %d
>>>44   belong          >0              \b, actions %d
>>>48   byte            1               \b, player
>>>48   byte            >1              \b, players
>>>48   byte            &1              \b 1
>>>48   byte            &2              \b 2
>>>48   byte            &4              \b 3
>>>48   byte            &8              \b 4
>>>50   byte            &1              \b, [em_random_bug]
>>>50   byte            &2              \b, [game_speed]
>>>50   byte            &4              \b, [pause]
>>>50   byte            &8              \b, [single_step]
>>>50   byte            &16             \b, [snapshot]
>>>50   byte            &32             \b, [replayed]
>>>50   byte            &64             \b, [tas_keys]
>>>50   byte            &128            \b, [small_graphics]

# ========== Rocks'n'Diamonds user data files (old, non-IFF format) ===========
0       string          ROCKSNDIAMONDS_ Rocks'n'Diamonds data

# ---------- Rocks'n'Diamonds level file --------------------------------------
>15     string          LEVEL_FILE_     \b, level file
>26     string          VERSION_        \b, version
>>34    string          >\0             %s
>>>44   string          >\0             \b, title "%s"
>>>44   string          \0
>>>>52  string          >\0             \b, title "%s"

# ---------- Rocks'n'Diamonds tape file ---------------------------------------
>15     string          TAPE_FILE_      \b, tape file
>25     string          VERSION_        \b, version
>>33    string          >\0             %s

# ========== Emerald Mine level files =========================================
2106    string          \xff600         Emerald Mine cave file, V6 file format
2106    string          \xff500         Emerald Mine cave file, V5 file format
9       string          0?&-TSZAHw~elk  Emerald Mine cave file, V3 file format
User avatar
Holger
Site Admin
Posts: 4073
Joined: Fri Jun 18, 2004 4:13 pm
Location: Germany
Contact:

Re: "magic" file entries for R'n'D

Post by Holger »

An old topic, updated with some cool new stuff! :-)

That looks all great, especially the detection of Emerald Mine level files, and the new tape flags!

In fact, I also did some tweaks and additions and cleanup to my own "magic" file for R'n'D file formats just recently (but I don't have the file accessible right now, unfortunately). So I will happily merge the two updated files, and I think I should add it to the Git repo, too.

However, there's one problem still left with it that I already googled to death to find a solution, but without success: The tape date is shown with a wrong month, because "struct tm" (as returned by localtime(), for example) has the following:

int tm_mon; /* month of year (0 - 11) */

Probably to make it easier to lookup textual month names from an array... But this gives dates like "date 20211001" in your example, which is in fact "2021-11-01". :-o

Unfortunately, there seems to be no way to do math in /etc/magic ... :-(

But wait: Maybe it's possible to fix that like this:

>>>40 belong >700000 \b, date 19%06d
>>>40 belong <700000 \b, date 20%06d

Would require twelve file entries though... but I think I will try this... :-)

Update: No, that does not work, unfortunately, as the date is stored in one (weirdly formatted/calculated) integer, so I can't access the month separately (as would be possible if I had just stored year, month and day in separate bytes). :-(
filbo
Posts: 647
Joined: Fri Jun 20, 2014 10:06 am

Re: "magic" file entries for R'n'D

Post by filbo »

>>>40 belong 700001 \b, date 1970-01-01
>>>40 belong 700002 \b, date 1970-01-02
...
>>>40 belong 700031 \b, date 1970-01-31
>>>40 belong 700101 \b, date 1970-02-01
...
>>>40 belong 380018 \b, date 2038-01-18

... is fewer than 25000 entries, and gives the opportunity to express dates in a nicer format :)

In point of fact, this works and generates 25202 lines -- and the resulting compiled .mgc file works. But is 6MiB larger than otherwise, so I don't think it's a good solution!

Code: Select all

awk '   
function leap_month(yyyy, mm) { return mm == 2 && !(yyyy % 4) && (yyyy % 100 || !(yyyy % 400)); }
BEGIN { 
    split("31 28 31 30 31 30 31 31 30 31 30 31", days_per_month)
    # Ends the year after end-of-unix-epoch; revisit some day?
    for (yyyy = 1970; ((yy0000 = (yyyy % 100) * 10000) != -1) && yyyy <= 2038; ++yyyy)
        for (mm = 01; mm <= 12 && (days = days_per_month[mm] + leap_month(yyyy, mm)); ++mm)
            for (dd = 01; dd <= days; ++dd) 
                printf ">>>40   belong          %-7d         \\b, date %4d-%02d-%02d\n",
                        yy0000 + (mm - 1) * 100 + dd,                 yyyy,  mm,  dd
}'
filbo
Posts: 647
Joined: Fri Jun 20, 2014 10:06 am

Re: "magic" file entries for R'n'D

Post by filbo »

(only 16060 lines and 4MiB if started in 1995, like RnD apparently was...)
filbo
Posts: 647
Joined: Fri Jun 20, 2014 10:06 am

Re: "magic" file entries for R'n'D

Post by filbo »

Here's an update with a bunch of improvements. But still shows dates off-by-a-month, because the fix for that is just too ugly...

This basically just makes it able to display most of the same info about older files, back to RnD save file version 1.0 (with more and more info available as the format improves over the years...)

Holger, you said you were going to merge some stuff, but I don't see it in the repo. (But I haven't touched the build.artsoft.org repo at all, maybe it's there?)

Code: Select all

# From: http://www.artsoft.org/forum/viewtopic.php?t=588 version of 2005-12-01
#
# Modified by Bela Lubkin:
#
# - added RnD file format version
# - changed old 'w.x.y-z' version number format to 'w.x.y.z'
# - changed 'version' to 'game' (game version which created the tape)
# - added 'actions' count to tape -- this is a crude measure, but
#   at least computable in this context, unlike frames or seconds
# - added player(s) indicator to tape -- note slightly wrong result
#   for 1-player tapes played by players 2/3/4 ('players 3')
# - added display of RnD 4.3.0.0 tape meta-flags
# - fixed display of titles of some old non-IFF levels
# - added recognition of Emerald Mine (version 3, 5, 6) level files
#   (V3 fake-matches the mildly encrypted steel top edge; it correctly
#   identifies all 102 levels of 'classic_emerald_mine$' levelset)
# - 2022-10-12 add level infos which were missing with file format 3.x;
#   uses magic(5) features only available in the standard 'darwinsys'
#   file(1) -- should work on all Linux, most BSD, maybe not OpenBSD;
#   Mac; Windows with any sort of embedded lobotomized Linux / Bash env
# - 2022-10-12 add author, dimensions, and time to pre-IFF level infos
# - 2022-10-12 display 'time 0 s' as 'untimed'

# ========== Rocks'n'Diamonds user data files (new IFF format) ================
0             string          RND1            Rocks'n'Diamonds data
>20           byte            >0              \b, file format %d.
>>21          byte            x               \b%d

# ---------- Rocks'n'Diamonds level file --------------------------------------
>8            string          CAVE            \b, level file
>>12          string          VERS            \b, game
>>>24         byte            x               %d
>>>25         byte            x               \b.%d
>>>26         byte            x               \b.%d
>>>27         byte            x               \b.%d

>>64          search/300      AUTH            \b, author
>>>&+4        string          >\0             "%s"

# file format 2.x chunks
>>16          search/60       HEAD
>>>&+10       string          >\0             \b, title "%s"
>>>&+4        ubyte           >0
>>>>&+0       ubyte           >0
>>>>>&-2      ubyte           x               \b, size %d
>>>>>>&+0     ubyte           x               x %d
>>>&+6        ubeshort        >0              \b, time %d s
>>>&+6        ubeshort        0               \b, untimed

# file format 3.x chunks
>>32          search/60       NAME
>>>&+4        string          >\0             \b, title "%s"
>>96          search/120      INFO
>>>&+6        string          A
>>>>&+2       string          B
>>>>>&-3      ubeshort        >0
>>>>>>&+1     ubeshort        >0
>>>>>>>&-5    ubeshort        x               \b, size %d
>>>>>>>>&+1   ubeshort        x               x %d
>>>&+12       string          C
>>>>&+0       ubeshort        >0              \b, time %d s
>>>>&+0       ubeshort        0               \b, untimed

# ---------- Rocks'n'Diamonds tape file ---------------------------------------
>8            string          TAPE            \b, tape file
>>12          string          VERS            \b, game
>>>24         byte            x               %d
>>>25         byte            x               \b.%d
>>>26         byte            x               \b.%d
>>>27         byte            x               \b.%d
>>28          string          HEAD            \b, engine
>>>52         byte            x               %d
>>>53         byte            x               \b.%d
>>>54         byte            x               \b.%d
>>>55         byte            x               \b.%d
>>>40         belong          >700000         \b, date 19%06d
>>>40         belong          <700000         \b, date 20%06d
>>56          string          INFO            \b, level set
>>>66         string          >\0             "%s"
>>>>(64.S+66) ubeshort        x               \b, level %d
>>>44         belong          >0              \b, actions %d
>>>48         byte            1               \b, player
>>>48         byte            >1              \b, players
>>>48         byte            &1              \b 1
>>>48         byte            &2              \b 2
>>>48         byte            &4              \b 3
>>>48         byte            &8              \b 4
>>>50         byte            &1              \b, [em_random_bug]
>>>50         byte            &2              \b, [game_speed]
>>>50         byte            &4              \b, [pause]
>>>50         byte            &8              \b, [single_step]
>>>50         byte            &16             \b, [snapshot]
>>>50         byte            &32             \b, [replayed]
>>>50         byte            &64             \b, [tas_keys]
>>>50         byte            &128            \b, [small_graphics]

# ========== Rocks'n'Diamonds user data files (old, non-IFF format) ===========
0             string          ROCKSNDIAMONDS_
>&+0          search/60       VERSION_        
>>&+0         string          >\0             Rocks'n'Diamonds data, file format %s

# ---------- Rocks'n'Diamonds level file (old, non-IFF format) ----------------
>>>15         string          LEVEL_FILE_     \b, level file

# file format 1.0 data
>>>>44        string          >\0             \b, title "%s"
>>>>38        string          !HEAD
>>>>>&-3      ubyte           >0
>>>>>>&-2     ubyte           >0              \b, size %d
>>>>>>>&+0    ubyte           >0              x %d
>>>>>&-2      ubeshort        >0              \b, time %d s
>>>>>&-2      ubeshort        0               \b, untimed

# file format 1.x data
>>>>64        search/100      AUTH            \b, author
>>>>>&+4      string          >\0             "%s"
>>>>44        string          \0
>>>>>52       string          >\0             \b, title "%s"
>>>>38        string          HEAD
>>>>>&+5      ubyte           >0
>>>>>>&-2     ubyte           >0              \b, size %d
>>>>>>>&+0    ubyte           >0              x %d
>>>>>&+6      ubeshort        >0              \b, time %d s
>>>>>&+6      ubeshort        0               \b, untimed

# ---------- Rocks'n'Diamonds tape file (old, non-IFF format) -----------------
>>>15         string          TAPE_FILE_      \b, tape file

# ========== Emerald Mine level files =========================================
9             string          0?&-TSZAHw~elk  Emerald Mine cave file, file format V3
2106          string          \xff500         Emerald Mine cave file, file format V5
2106          string          \xff600         Emerald Mine cave file, file format V6
Post Reply