diff --git a/src/util/crc32.c b/src/util/crc32.c
index 9282bd4e4..afa54022e 100644
--- a/src/util/crc32.c
+++ b/src/util/crc32.c
@@ -42,6 +42,12 @@
 
 #include "util/crc32.h"
 
+#include "util/vfs.h"
+
+enum {
+	BUFFER_SIZE = 1024
+};
+
 static uint32_t crc32Table[] = {
 	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
 	0xe963a535, 0x9e6495a3,	0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
@@ -102,3 +108,26 @@ uint32_t updateCrc32(uint32_t crc, const void* buf, size_t size) {
 
 	return ~crc;
 }
+
+uint32_t fileCrc32(struct VFile* vf, size_t endOffset) {
+	char buffer[BUFFER_SIZE];
+	size_t blocksize;
+	size_t alreadyRead = 0;
+	if (vf->seek(vf, 0, SEEK_SET) < 0) {
+		return 0;
+	}
+	uint32_t crc = 0;
+	while (alreadyRead < endOffset) {
+		size_t toRead = sizeof(buffer);
+		if (toRead + alreadyRead > endOffset) {
+			toRead = endOffset - alreadyRead;
+		}
+		blocksize = vf->read(vf, buffer, toRead);
+		alreadyRead += blocksize;
+		crc = updateCrc32(crc, buffer, blocksize);
+		if (blocksize < toRead) {
+			return 0;
+		}
+	}
+	return crc;
+}
diff --git a/src/util/crc32.h b/src/util/crc32.h
index 5716e9782..3e8f2e643 100644
--- a/src/util/crc32.h
+++ b/src/util/crc32.h
@@ -4,7 +4,10 @@
 #include <stdint.h>
 #include <string.h>
 
+struct VFile;
+
 uint32_t crc32(const void* buf, size_t size);
 uint32_t updateCrc32(uint32_t crc, const void* buf, size_t size);
+uint32_t fileCrc32(struct VFile* file, size_t endOffset);
 
 #endif
diff --git a/src/util/patch-ups.c b/src/util/patch-ups.c
index 2fafffc2b..63ee8dcf7 100644
--- a/src/util/patch-ups.c
+++ b/src/util/patch-ups.c
@@ -8,8 +8,6 @@ enum {
 	IN_CHECKSUM = -12,
 	OUT_CHECKSUM = -8,
 	PATCH_CHECKSUM = -4,
-
-	BUFFER_SIZE = 1024
 };
 
 static size_t _UPSOutputSize(struct Patch* patch, size_t inSize);
@@ -19,7 +17,7 @@ static size_t _UPSDecodeLength(struct VFile* vf);
 bool loadPatchUPS(struct Patch* patch) {
 	patch->vf->seek(patch->vf, 0, SEEK_SET);
 
-	char buffer[BUFFER_SIZE];
+	char buffer[4];
 	if (patch->vf->read(patch->vf, buffer, 4) != 4) {
 		return false;
 	}
@@ -36,23 +34,7 @@ bool loadPatchUPS(struct Patch* patch) {
 		return false;
 	}
 
-	size_t blocksize;
-	size_t alreadyRead = 0;
-	patch->vf->seek(patch->vf, 0, SEEK_SET);
-	uint32_t crc = 0;
-	while (alreadyRead < filesize + PATCH_CHECKSUM) {
-		size_t toRead = sizeof(buffer);
-		if (toRead + alreadyRead > filesize + PATCH_CHECKSUM) {
-			toRead = filesize + PATCH_CHECKSUM - alreadyRead;
-		}
-		blocksize = patch->vf->read(patch->vf, buffer, toRead);
-		alreadyRead += blocksize;
-		crc = updateCrc32(crc, buffer, blocksize);
-		if (blocksize < toRead) {
-			return 0;
-		}
-	}
-
+	uint32_t crc = fileCrc32(patch->vf, filesize + PATCH_CHECKSUM);
 	if (crc != goodCrc32) {
 		return false;
 	}