diff --git a/OSBindings/Mac/Clock Signal/Info.plist b/OSBindings/Mac/Clock Signal/Info.plist
index bd6e68c48..eb8a76d93 100644
--- a/OSBindings/Mac/Clock Signal/Info.plist	
+++ b/OSBindings/Mac/Clock Signal/Info.plist	
@@ -184,6 +184,7 @@
 			<array>
 				<string>p</string>
 				<string>81</string>
+				<string>p81</string>
 			</array>
 			<key>CFBundleTypeIconFile</key>
 			<string>cassette</string>
diff --git a/StaticAnalyser/StaticAnalyser.cpp b/StaticAnalyser/StaticAnalyser.cpp
index 2d42fffbe..0d437a692 100644
--- a/StaticAnalyser/StaticAnalyser.cpp
+++ b/StaticAnalyser/StaticAnalyser.cpp
@@ -104,7 +104,8 @@ std::list<Target> StaticAnalyser::GetTargets(const char *file_name)
 		Format("dsk", disks, Disk::OricMFMDSK, TargetPlatform::Oric)					// DSK
 		Format("g64", disks, Disk::G64, TargetPlatform::Commodore)						// G64
 		Format("o", tapes, Tape::ZX80O81P, TargetPlatform::ZX8081)						// O
-		Format("p", tapes, Tape::ZX80O81P, TargetPlatform::ZX8081)						// O
+		Format("p", tapes, Tape::ZX80O81P, TargetPlatform::ZX8081)						// P
+		Format("p81", tapes, Tape::ZX80O81P, TargetPlatform::ZX8081)					// P81
 
 		// PRG
 		if(!strcmp(lowercase_extension, "prg"))
diff --git a/Storage/FileHolder.cpp b/Storage/FileHolder.cpp
index bd4c47305..f447fadd8 100644
--- a/Storage/FileHolder.cpp
+++ b/Storage/FileHolder.cpp
@@ -12,26 +12,22 @@
 
 using namespace Storage;
 
-FileHolder::~FileHolder()
-{
+FileHolder::~FileHolder() {
 	if(file_) fclose(file_);
 }
 
-FileHolder::FileHolder(const char *file_name) : file_(nullptr)
-{
-	stat(file_name, &file_stats_);
+FileHolder::FileHolder(const std::string &file_name) : file_(nullptr), name_(file_name) {
+	stat(file_name.c_str(), &file_stats_);
 	is_read_only_ = false;
-	file_ = fopen(file_name, "rb+");
-	if(!file_)
-	{
+	file_ = fopen(file_name.c_str(), "rb+");
+	if(!file_) {
 		is_read_only_ = true;
-		file_ = fopen(file_name, "rb");
+		file_ = fopen(file_name.c_str(), "rb");
 	}
 	if(!file_) throw ErrorCantOpen;
 }
 
-bool FileHolder::check_signature(const char *signature, size_t length)
-{
+bool FileHolder::check_signature(const char *signature, size_t length) {
 	if(!length) length = strlen(signature)+1;
 
 	// read and check the file signature
@@ -41,8 +37,7 @@ bool FileHolder::check_signature(const char *signature, size_t length)
 	return true;
 }
 
-uint32_t FileHolder::fgetc32le()
-{
+uint32_t FileHolder::fgetc32le() {
 	uint32_t result = (uint32_t)fgetc(file_);
 	result |= (uint32_t)(fgetc(file_) << 8);
 	result |= (uint32_t)(fgetc(file_) << 16);
@@ -51,8 +46,7 @@ uint32_t FileHolder::fgetc32le()
 	return result;
 }
 
-uint32_t FileHolder::fgetc24le()
-{
+uint32_t FileHolder::fgetc24le() {
 	uint32_t result = (uint32_t)fgetc(file_);
 	result |= (uint32_t)(fgetc(file_) << 8);
 	result |= (uint32_t)(fgetc(file_) << 16);
@@ -60,16 +54,14 @@ uint32_t FileHolder::fgetc24le()
 	return result;
 }
 
-uint16_t FileHolder::fgetc16le()
-{
+uint16_t FileHolder::fgetc16le() {
 	uint16_t result = (uint16_t)fgetc(file_);
 	result |= (uint16_t)(fgetc(file_) << 8);
 
 	return result;
 }
 
-uint32_t FileHolder::fgetc32be()
-{
+uint32_t FileHolder::fgetc32be() {
 	uint32_t result = (uint32_t)(fgetc(file_) << 24);
 	result |= (uint32_t)(fgetc(file_) << 16);
 	result |= (uint32_t)(fgetc(file_) << 8);
@@ -78,16 +70,14 @@ uint32_t FileHolder::fgetc32be()
 	return result;
 }
 
-uint16_t FileHolder::fgetc16be()
-{
+uint16_t FileHolder::fgetc16be() {
 	uint16_t result = (uint16_t)(fgetc(file_) << 8);
 	result |= (uint16_t)fgetc(file_);
 
 	return result;
 }
 
-void FileHolder::ensure_file_is_at_least_length(long length)
-{
+void FileHolder::ensure_file_is_at_least_length(long length) {
 	fseek(file_, 0, SEEK_END);
 	long bytes_to_write = length - ftell(file_);
 	if(bytes_to_write > 0)
@@ -98,3 +88,13 @@ void FileHolder::ensure_file_is_at_least_length(long length)
 		delete[] empty;
 	}
 }
+
+std::string FileHolder::extension() {
+	size_t pointer = name_.size() - 1;
+	while(pointer > 0 && name_[pointer] != '.') pointer--;
+	if(name_[pointer] == '.') pointer++;
+
+	std::string extension = name_.substr(pointer);
+	std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
+	return extension;
+}
diff --git a/Storage/FileHolder.hpp b/Storage/FileHolder.hpp
index a2be837bd..217e14721 100644
--- a/Storage/FileHolder.hpp
+++ b/Storage/FileHolder.hpp
@@ -12,6 +12,7 @@
 #include <sys/stat.h>
 #include <cstdio>
 #include <cstdint>
+#include <string>
 
 namespace Storage {
 
@@ -24,7 +25,7 @@ class FileHolder {
 		virtual ~FileHolder();
 
 	protected:
-		FileHolder(const char *file_name);
+		FileHolder(const std::string &file_name);
 
 		/*!
 			Reads @c length bytes from the file and compares them to the first
@@ -65,6 +66,12 @@ class FileHolder {
 		*/
 		uint16_t fgetc16be();
 
+		/*!
+			Determines and returns the file extension — everything from the final character
+			back to the first dot. The string is converted to lowercase before being returned.
+		*/
+		std::string extension();
+
 		/*!
 			Ensures the file is at least @c length bytes long, appending 0s until it is
 			if necessary.
@@ -117,6 +124,8 @@ class FileHolder {
 		FILE *file_;
 		struct stat file_stats_;
 		bool is_read_only_;
+
+		const std::string name_;
 };
 
 }
diff --git a/Storage/Tape/Formats/ZX80O81P.cpp b/Storage/Tape/Formats/ZX80O81P.cpp
index 50a005260..65e508019 100644
--- a/Storage/Tape/Formats/ZX80O81P.cpp
+++ b/Storage/Tape/Formats/ZX80O81P.cpp
@@ -19,8 +19,8 @@ ZX80O81P::ZX80O81P(const char *file_name) :
 	fread(data_.data(), 1, (size_t)file_stats_.st_size, file_);
 
 	// If it's a ZX81 file, prepend a file name.
-	char type = (char)tolower(file_name[strlen(file_name) - 1]);
-	if(type == 'p' || type == '1') {
+	std::string type = extension();
+	if(type == "p" || type == "81") {
 		// TODO, maybe: prefix a proper file name; this is leaving the file nameless.
 		data_.insert(data_.begin(), 0x80);
 	}