diff --git a/grmn/__init__.py b/grmn/__init__.py
index faab907..8fca0f9 100644
--- a/grmn/__init__.py
+++ b/grmn/__init__.py
@@ -1,4 +1,5 @@
 """Library for firmware reading/writing."""
 
 from .gcd import *
+from .rgn import *
 from .chksum import *
diff --git a/grmn/rgn.py b/grmn/rgn.py
new file mode 100644
index 0000000..8e22c62
--- /dev/null
+++ b/grmn/rgn.py
@@ -0,0 +1,138 @@
+# -*- coding: utf-8 -*-
+# Thanks to Herbert Oppmann (herby) for all your work!
+
+from .chksum import ChkSum
+from .rgnbin import RgnBin
+from struct import unpack
+import configparser
+
+RGN_SIG = b"KpGr"
+
+# RGN structure might be: RGN > BIN or RGN > RGN > BIN
+# RGN = outside hull
+# BIN = firmware + hwid + checksum
+
+class ParseException(Exception):
+    pass
+
+class Rgn:
+    def __init__(self, filename: str=None):
+        self.filename = filename
+        self.struct = []
+        if filename is not None:
+            self.load()
+
+    def load(self):
+        if self.filename is None:
+            return False
+        last_tlv6 = None
+        last_tlv7 = None
+        with open(self.filename, "rb") as f:
+            sig = f.read(4)
+            if sig != RGN_SIG:
+                raise ParseException("Signature mismatch ({}, should be {})!".format(repr(sig), repr(RGN_SIG)))
+            self.version = unpack("<H", f.read(2))[0]
+            print("Version: {}".format(self.version))
+            while True:
+                cur_offset = f.tell()
+                header = f.read(5)
+                if len(header) == 0:
+                    print("End of file reached.")
+                    break
+                (length, type_id) = unpack("<Lc", header)
+                print("Found record type: {} with {} Bytes length.".format(type_id, length))
+                rec = RgnRecord.factory(type_id, length, offset=cur_offset)
+                payload = f.read(length)
+                rec.set_payload(payload)
+                self.add_rec(rec)
+            f.close()
+
+    def add_rec(self, new_rec):
+        self.struct.append(new_rec)
+
+    def print_struct(self):
+        """
+        Prints the structure of the parsed GCD file
+        """
+        pass
+
+    def print_struct_full(self):
+        """
+        Prints the structure of the parsed GCD file
+        """
+        pass
+
+    def validate(self, print_stats: bool=False):
+        """
+        Checks and verifies all checksums in the GCD.
+        """
+        # RGN has no checksum, but embedded BIN has
+
+    def dump_to_files(self, output_basename: str):
+        pass
+
+    @staticmethod
+    def from_recipe(recipe_file: str):
+        pass
+
+    def save(self, filename):
+        pass
+
+class RgnRecord():
+    def __init__(self, type_id, expected_length, payload=None, offset=None):
+        self.type_id = type_id
+        self.length = expected_length
+        self.is_binary = False
+        self.payload = payload
+        self.offset = offset
+        self.is_parsed = False
+
+    def set_payload(self, new_payload):
+        self.payload = new_payload
+
+    @staticmethod
+    def factory(type_id, length: int = None, offset: int = None):
+        if type_id == b"D":
+            new_rec = RgnRecordD(type_id, length)
+        elif type_id == b"A":
+            new_rec = RgnRecordA(type_id, length)
+        elif type_id == b"R":
+            new_rec = RgnRecordR(type_id, length)
+            new_rec.is_binary = True
+        else:
+            raise ParseException("Unknown record type: {} at offset 0x{:0x}".format(type_id, offset))
+        new_rec.offset = offset
+        return new_rec
+
+class RgnRecordD(RgnRecord):
+    """
+    Data record (2 Bytes)
+    - ushort - Version
+    """
+
+    def parse(self):
+        self.is_parsed = True
+
+class RgnRecordA(RgnRecord):
+    """
+    Application record
+    - ushort - Application version
+    - string - Builder
+    - string - BuildDate
+    - string - BuildTime
+    """
+
+    def parse(self):
+        self.is_parsed = True
+
+class RgnRecordR(RgnRecord):
+    """
+    Region record
+    - ushort - Region ID
+    - uint   - Delay in ms
+    - uint   - Region size (is record length - 10)
+    - byte[Region size] - Contents
+    """
+
+    def parse(self):
+        self.is_parsed = True
diff --git a/grmn/rgnbin.py b/grmn/rgnbin.py
new file mode 100644
index 0000000..2d5014d
--- /dev/null
+++ b/grmn/rgnbin.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+# Thanks to Herbert Oppmann (herby) for all your work!
+
+from . import devices
+from .chksum import ChkSum
+from struct import unpack
+
+# RGN structure might be: RGN > BIN or RGN > RGN > BIN
+# RGN = outside hull
+# BIN = firmware + hwid + checksum
+
+class ParseException(Exception):
+    pass
+
+class RgnBin:
+    def __init__(self, filename: str=None):
+        self.filename = filename
+        self.struct = []
+        if filename is not None:
+            self.load()
+
+    def load(self):
+        if self.filename is None:
+            return False
+        with open(self.filename, "rb") as f:
+            f.close()
diff --git a/rgnstruct.py b/rgnstruct.py
new file mode 100644
index 0000000..ae0b140
--- /dev/null
+++ b/rgnstruct.py
@@ -0,0 +1,18 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+"""
+Prints out the structure of the given RGN file.
+"""
+
+from grmn import Rgn
+import sys
+
+FILE = sys.argv[1]
+
+print("Opening {}".format(FILE))
+
+rgn = Rgn(FILE)
+
+#rgn.print_struct()
+#rgn.validate(True)