Skip to content
This repository has been archived by the owner on Dec 24, 2020. It is now read-only.

Commit

Permalink
New blog post: adventures in copy protection
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffpar committed Jun 14, 2019
1 parent a884b18 commit 0bc0cd0
Show file tree
Hide file tree
Showing 26 changed files with 184 additions and 58 deletions.
8 changes: 4 additions & 4 deletions _posts/2019-04-10-copy-protection.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ disk images, where all the sectors are 512 bytes, all the sector IDs are consecu

Previously, the only way PCjs could run copy-protected software was to use patched binaries that bypassed any
copy-protection checks, so that's what I used in a few cases (e.g., [Lotus 1-2-3](/disks/pcx86/apps/lotus/123/1as/)).
But last year, I acquired a [Kryoflux](https://www.kryoflux.com/) device, which reads (and writes) all kinds of
But last year, I acquired a [KryoFlux](https://www.kryoflux.com/) device, which reads (and writes) all kinds of
diskettes, and -- in theory -- captures everything you need to know to reproduce a diskette.

I've only used the Kryoflux software a few times, because most of the diskettes I've collected aren't
I've only used the KryoFlux software a few times, because most of the diskettes I've collected aren't
copy-protected and can be perfectly reproduced with programs like [WinImage](http://www.winimage.com/download.htm).
But I did use it last year to read a set of original copy-protected [IBM Multiplan 1.00](/disks/pcx86/apps/ibm/multiplan/1.00/)
disks. And by using another program called [HxC](https://hxc2001.com/), I was able to inspect Kryoflux's raw data
disks. And by using another program called [HxC](https://hxc2001.com/), I was able to inspect KryoFlux's raw data
from IBM's Multiplan Program disk and discover what was unusual about it:

![HxC IBM Multiplan 1.00](/blog/images/hxc-multiplan-program.png)
Expand All @@ -41,7 +41,7 @@ In the case of IBM's Multiplan, all I had to do was to change the appropriate Se
### Microsoft Word 1.15

Early versions of Microsoft Word were also copy-protected, and since
[Kryoflux dumps](https://winworldpc.com/product/microsoft-word/1x-dos) of the original disks are available,
[KryoFlux dumps](https://winworldpc.com/product/microsoft-word/1x-dos) of the original disks are available,
I took a closer look with HxC:

![HxC Microsoft Word 1.15](/blog/images/word115-disk-image.png)
Expand Down
4 changes: 2 additions & 2 deletions _posts/2019-05-05-copy-protection-and-preservation.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ analysis failed, the application would report:

Unauthorized Duplicate

and terminate. In the Kryoflux visualization below, this "hole" appears on the **dBASE III 1.0 (Disk 1)**
and terminate. In the KryoFlux visualization below, this "hole" appears on the **dBASE III 1.0 (Disk 1)**
on track 39, sector 5 -- the orange arc immediately to the left of the two red rings.

![dBASE III 1.0](/blog/images/dbase-iii-disk-image.png)
Expand Down Expand Up @@ -99,7 +99,7 @@ Another concern is that such a process could be inadvertently destructive. Ther
about a duplication process that involves writing modifications to the original diskette.

I didn't have to wrestle with that concern, however, because I no longer have an original diskette. All I had was a
Kryoflux dump, which doesn't tell you much about the physical condition of the diskette. So I resorted to
KryoFlux dump, which doesn't tell you much about the physical condition of the diskette. So I resorted to
[debugging](/disks/pcx86/apps/other/dbase3/1.0/debugger/#debugging-notes) the software again (as I did [35 years ago](/docs/personal/)),
watching the reads and writes, observing what PROLok's expectations were, inferring that one of the 512-byte sectors
must have been physically damaged within +/-10 bytes of the 272nd byte, and then recording that in my annotated disk image.
Expand Down
57 changes: 57 additions & 0 deletions _posts/2019-06-13-adventures-in-copy-protection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
layout: post
title: Adventures in Copy Protection
date: 2019-06-13 10:00:00
permalink: /blog/2019/06/13/
preview: https://game-disks.pcjs.org/pcx86/microsoft/adventure/Adventure_Booklet_Cover.jpg
---

Thanks to a contribution from a PCjs user, I was able to examine a KryoFlux dump of an original
[Microsoft Adventure](/disks/pcx86/games/microsoft/adventure/) diskette:

![Microsoft Adventure Diskette]({{ site.games-disks.baseurl }}/pcx86/microsoft/adventure/Adventure_Diskette-HxC.png)

You can see that the first sector on the (outermost) track is a normal 512-byte sector -- which it must
be in order to function as a boot disk -- but the rest of the disk is primarily 256-byte sectors, along
with bad sectors and unusual sector IDs. Since this isn't a DOS-compatible diskette, it can (and does)
break all the rules.

Interestingly, this dump wasn't created with the KryoFlux software. Instead, starting with a TransCopy dump,
along with some advice on using the image conversion tools that come with [PCE](http://www.hampa.ch/pce/),
I was able to convert the TransCopy `.tc` file into a set of KryoFlux `.raw` track files and successfully
load them into [HxC](http://hxc2001.free.fr/).

The basic steps were:

- Use PCE's **PRI** utilty to convert the `.tc` file to a `.pri` (PCE Raw Image) file
- Use PCE's **PFI** utility to convert the `.pri` file to a `.pfi` (PCE Flux Image) file
- Use PCE's **PFI** utility again to convert the `.pfi` file to a set of `.raw` track files

For example:

pri MSADVENT.tc MSADVENT.pri
pfi -p encode pri MSADVENT.pri MSADVENT.pfi
pfi MSADVENT.pfi track00.0.raw

In the process, I also learned a bit about `.psi` (PCE Sector Image) files, which can be created
from `.pri` (PCE Raw Image) files; eg:

pri MSADVENT.pri -p decode mfm MSADVENT.psi -f -v

The nice thing about a `.psi` file is that the format is fairly straightforward, and with the help of
a little [documentation](https://github.com/jeffpar/pce/blob/master/doc/psi-format.txt), I was able to
update my [DiskDump](/modules/diskdump/) utility to read `.psi` files directly and create
JSON-encoded PCjs disk images that more or less replicate the structure of the original diskette.

There are now *two* Microsoft Adventure disk images in the PCjs Disk Library:

- "Microsoft Adventure", which contains a patched binary on a normally formatted diskette
- "Microsoft Adventure (Unmodified)", which contains the original binary on a copy-protected diskette

The first diskette is what we originally used before PCjs supported copy-protected disks. In theory, we
could have simply replaced the first diskette with the copy-protected version, but that would have broken
the saved machine state of anyone who had already started playing the game with the first diskette. Besides,
there may be some historical or diagnostic value in keeping both versions.

*[@jeffpar](https://jeffpar.com)*
*June 13, 2019*
2 changes: 1 addition & 1 deletion disks-demo
2 changes: 1 addition & 1 deletion disks-game
14 changes: 14 additions & 0 deletions disks/pcx86/dos/ibm/3.30/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,17 @@ New functions:
BASICA PIF 369 3-17-87 12:00p
MORTGAGE BAS 6251 3-17-87 12:00p
32 File(s) 43008 bytes free

### Directory of PC DOS 3.30 (TechRef)

Volume in drive A has no label
Directory of A:\

DEBUG COM 15897 03-17-87 12:00a
EXE2BIN EXE 3081 03-17-87 12:00a
LIB EXE 22912 03-17-87 12:00a
LINK EXE 39076 03-17-87 12:00a
VDISK ASM 75284 03-17-87 12:00a
VENDOR-# DO1 0 07-04-83 12:00a
6 file(s) 156250 bytes
202752 bytes free
14 changes: 14 additions & 0 deletions disks/pcx86/dos/ibm/4.00/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,17 @@ New functions:
DOS04L 400 0 06-17-88 12:00p
11 file(s) 349966 bytes
9216 bytes free

### Directory of PC DOS 4.00 (TechRef)

Volume in drive A has no label
Volume Serial Number is 18BD-1F2B
Directory of A:\

DEBUG COM 21606 06-17-88 12:00p
EXE2BIN EXE 7973 06-17-88 12:00p
LIB EXE 47107 06-17-88 12:00p
LINK EXE 105406 06-17-88 12:00p
VDISK ASM 75571 06-17-88 12:00p
5 file(s) 257663 bytes
102400 bytes free
7 changes: 5 additions & 2 deletions disks/pcx86/games/microsoft/adventure/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ Microsoft Adventure (1981)
--------------------------

UPDATE: There are now two "Microsoft Adventure" disk images in the PCjs Disk Library. The latest one is called
"Microsoft Adventure (Unmodified)", which replicates the original copy-protected diskette.
"Microsoft Adventure (Unmodified)", which recreates the original copy-protected diskette. See the PCjs blog post
"[Adventures in Copy Protection](/blog/2019/06/13/)" for more information.

A copy of the [Manual]({{ site.games-disks.baseurl }}/pcx86/microsoft/adventure/Adventure_Manual.pdf) is also available.

{% include machine.html id="ibm5150" %}

NOTE: You cannot use the PCjs "Save" feature to save a copy of a copy-protected diskette, because PCjs can save
only IMG disk images, which do not support copy protection.
only standard DOS-formatted disk images.

For more classic PC software experiences, see the PCjs collection of [IBM PC Application Demos](/apps/pcx86/).
Binary file not shown.
Binary file not shown.
4 changes: 2 additions & 2 deletions disks/pcx86/library.xml
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@
<disk path="/disks-demo/pcx86/dos/ibm/3.30/PCDOS330-DISK1.json">PC DOS 3.30 (Disk 1)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/3.30/PCDOS330-DISK2.json">PC DOS 3.30 (Disk 2)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/3.30/PCDOS330-DISK1-720K.json">PC DOS 3.30 (720K)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/3.30/PCDOS330-TECHREF.json">PC DOS 3.30 TechRef</disk>
<disk path="/disks-demo/pcx86/dos/ibm/3.30/PCDOS330-TECHREF.json">PC DOS 3.30 (TechRef)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/4.00/PCDOS400-DISK1.json">PC DOS 4.00 (Disk 1)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/4.00/PCDOS400-DISK2.json">PC DOS 4.00 (Disk 2)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/4.00/PCDOS400-DISK3.json">PC DOS 4.00 (Disk 3)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/4.00/PCDOS400-DISK4.json">PC DOS 4.00 (Disk 4)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/4.00/PCDOS400-DISK5.json">PC DOS 4.00 (Disk 5)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/4.00/PCDOS400-TECHREF.json">PC DOS 4.00 TechRef</disk>
<disk path="/disks-demo/pcx86/dos/ibm/4.00/PCDOS400-TECHREF.json">PC DOS 4.00 (TechRef)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/4.01/PCDOS401-DISK1.json">PC DOS 4.01 (Disk 1)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/4.01/PCDOS401-DISK2.json">PC DOS 4.01 (Disk 2)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/5.00/PCDOS500-DISK1-720K.json">PC DOS 5.00 (Disk 1)</disk>
Expand Down
4 changes: 2 additions & 2 deletions disks/pcx86/shareware/pcsig08/library.xml
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@
<disk path="/disks-demo/pcx86/dos/ibm/3.30/PCDOS330-DISK1.json">PC DOS 3.30 (Disk 1)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/3.30/PCDOS330-DISK2.json">PC DOS 3.30 (Disk 2)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/3.30/PCDOS330-DISK1-720K.json">PC DOS 3.30 (720K)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/3.30/PCDOS330-TECHREF.json">PC DOS 3.30 TechRef</disk>
<disk path="/disks-demo/pcx86/dos/ibm/3.30/PCDOS330-TECHREF.json">PC DOS 3.30 (TechRef)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/4.00/PCDOS400-DISK1.json">PC DOS 4.00 (Disk 1)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/4.00/PCDOS400-DISK2.json">PC DOS 4.00 (Disk 2)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/4.00/PCDOS400-DISK3.json">PC DOS 4.00 (Disk 3)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/4.00/PCDOS400-DISK4.json">PC DOS 4.00 (Disk 4)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/4.00/PCDOS400-DISK5.json">PC DOS 4.00 (Disk 5)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/4.00/PCDOS400-TECHREF.json">PC DOS 4.00 TechRef</disk>
<disk path="/disks-demo/pcx86/dos/ibm/4.00/PCDOS400-TECHREF.json">PC DOS 4.00 (TechRef)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/4.01/PCDOS401-DISK1.json">PC DOS 4.01 (Disk 1)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/4.01/PCDOS401-DISK2.json">PC DOS 4.01 (Disk 2)</disk>
<disk path="/disks-demo/pcx86/dos/ibm/5.00/PCDOS500-DISK1-720K.json">PC DOS 5.00 (Disk 1)</disk>
Expand Down
18 changes: 14 additions & 4 deletions modules/devices/tms1500.js
Original file line number Diff line number Diff line change
Expand Up @@ -650,13 +650,23 @@ class Chip extends Device {
{
if (opCode & 0x1000) {
if (opCode & 0x0800) { // BRC/BRNC
/*
* As TI patent 4078251 states:
*
* There being only ten bits in the address for the “branch on condition” instruction, when the
* branch is executed only the ten least significant bits are loaded into the 11 bit address register
* of program counter 32a. The most significant bit in the program counter remains unchanged.
*/
if (!!(opCode & 0x0400) == this.fCOND) {
/*
* TODO: Determine whether to use bit 10 from the original PC (addr) or the incremented PC (regPC)
*/
this.regPC = (addr & 0x0400) | (opCode & 0x03FF);
this.regPC = (this.regPC & 0x0400) | (opCode & 0x03FF);
}
} else { // CALL
/*
* As TI patent 4078251 states:
*
* Since the “branch unconditionally” address contains 11 bits and since the program counter 32a
* contains 11 bits, the “branch unconditionally” instruction can cause the branch anywhere within ROM.
*/
this.push(this.regPC);
this.regPC = opCode & 0x07FF;
}
Expand Down
7 changes: 3 additions & 4 deletions modules/pcx86/lib/disk.js
Original file line number Diff line number Diff line change
Expand Up @@ -1003,15 +1003,14 @@ class Disk extends Component {
if (bStatus == DiskAPI.MBR.PARTITIONS.STATUS.ACTIVE) {
dir.pbaVolume = this.getSectorData(sectorBoot, off + DiskAPI.MBR.PARTITIONS.ENTRY.LBA_FIRST, 4);
sectorBoot = this.getSector(dir.pbaVolume);
if (sectorBoot) {
if (this.getSectorData(sectorBoot, DiskAPI.BPB.SECTOR_BYTES, 2) != this.cbSector) {
sectorBoot = null;
}
if (sectorBoot && this.getSectorData(sectorBoot, DiskAPI.BPB.SECTOR_BYTES, 2) != this.cbSector) {
sectorBoot = null;
}
break;
}
off += DiskAPI.MBR.PARTITIONS.ENTRY_LENGTH;
}
if (i == 4) sectorBoot = null;
}
if (!sectorBoot) {
if (DEBUG && this.messageEnabled()) {
Expand Down
18 changes: 14 additions & 4 deletions versions/devices/1.21/ti42-uncompiled.js
Original file line number Diff line number Diff line change
Expand Up @@ -5176,13 +5176,23 @@ class Chip extends Device {
{
if (opCode & 0x1000) {
if (opCode & 0x0800) { // BRC/BRNC
/*
* As TI patent 4078251 states:
*
* There being only ten bits in the address for the “branch on condition” instruction, when the
* branch is executed only the ten least significant bits are loaded into the 11 bit address register
* of program counter 32a. The most significant bit in the program counter remains unchanged.
*/
if (!!(opCode & 0x0400) == this.fCOND) {
/*
* TODO: Determine whether to use bit 10 from the original PC (addr) or the incremented PC (regPC)
*/
this.regPC = (addr & 0x0400) | (opCode & 0x03FF);
this.regPC = (this.regPC & 0x0400) | (opCode & 0x03FF);
}
} else { // CALL
/*
* As TI patent 4078251 states:
*
* Since the “branch unconditionally” address contains 11 bits and since the program counter 32a
* contains 11 bits, the “branch unconditionally” instruction can cause the branch anywhere within ROM.
*/
this.push(this.regPC);
this.regPC = opCode & 0x07FF;
}
Expand Down
Loading

0 comments on commit 0bc0cd0

Please sign in to comment.