Computers

Infocom copy protection

The first copy protection scheme I cracked on my Apple ][ was that of Zork. It wasn’t that difficult, the data prologue bits were changed from D5 AA AD to D5 AA BC. Copying the disk involved patching the standard copy program COPYA and then editing the disk so that it could read itself.

But today I’m interested in the IBM PC version of Zork. Like the Apple ][ version, the disk could not be copied by the standard tool (in this case diskcopy) but Copy II PC worked just fine. Interestingly, the disk allowed you to make one copy of the game for backup purposes.

The weak point of copy protected disks is that the standard BIOS must be able to read the first bit of the disk. This code is then executed to read the “uncopyable” part of the disk. Anyone can read the first sector, disassemble it, and work out how to read the rest of the disk. Granted, this process is sometimes extremely difficult. Not so in the case of Zork.

On the IBM PC, the BIOS reads track 0 sector 1 into segment 0, offset 7C00 and jumps to it.

0000:7C00 FA     CLI                   Disable interrupts

The first thing after disabling the interrupts (which is pretty standard) is to change the pointer (at 0000:0078) to the disk controller parameter block to point at the first location after this actual code, 0000:7C79.

0000:7C01 2BC0   SUB AX,AX             AX=0
0000:7C03 8ED8   MOV DS,AX             DS=AX=0
0000:7C05 BB7800 MOV BX,0078           DISK_POINTER, points to parameter block
0000:7C08 B97900 MOV CX,0079
0000:7C0B BAC007 MOV DX,07C0
0000:7C0E 8B37   MOV SI,[BX]           Save current pointer at 0000:0078 in SI
0000:7C10 8B7F02 MOV DI,[BX+02]        Save current pointer at 0000:007A in DI
0000:7C13 890F   MOV [BX],CX           0000:0078 = 0079
0000:7C15 895702 MOV [BX+02],DX        0000:007A = 07C0

0000:7C18 8CC8   MOV AX,CS
0000:7C1A 8ED8   MOV DS,AX             Set DS = CS

; Set stack to 0000:7C00               Fairly standard
0000:7C1C BA0000 MOV DX,0000
0000:7C1F 8ED2   MOV SS,DX
0000:7C21 BB007C MOV BX,7C00
0000:7C24 8BE3   MOV SP,BX

0000:7C26 FB     STI                   Enable interrupts
0000:7C27 B86000 MOV AX,0060
0000:7C2A 8ED8   MOV DS,AX             Set DS and ES to 0x0060
0000:7C2C 8EC0   MOV ES,AX

; Reset disk drive (AH=0)
0000:7C2E 2BC0   SUB AX,AX AX=0
0000:7C30 2BD2   SUB DX,DX DX=0
0000:7C32 CD13   INT 13

0000:7C34 BA0300 MOV DX,0003           DX=3
0000:7C37 2BDB   SUB BX,BX             BX=0
0000:7C39 B501   MOV CH,01             CH=1
0000:7C3B 52     PUSH DX               Save DX
0000:7C3C B101   MOV CL,01             CL=1
0000:7C3E 51     PUSH CX               Save CX (= 0101)
0000:7C3F 2BD2   SUB DX,DX             DX=0
0000:7C41 B80402 MOV AX,0204           AH=2, AL=4
0000:7C44 CD13   INT 13

INT 13 with AH=2 reads AL (=4) sectors from cylinder CH (=1), sector CL (=1) of head/drive DX (0/0) into ES:BX (0060:0000). This read uses the new parameter block further down, which differs from the standard parameter block in that it specifies 1024 byte sectors, four sectors per track.

0000:7C46 721C   JB 7C64               If INT13 returns error, print "ILL" and halt
0000:7C48 59     POP CX                Restore CX (I don't think INT13 corrupts CX, so I don't know why)
0000:7C49 FEC5   INC CH                Next cylinder
0000:7C4B 81C30010 ADD BX,1000         Move data pointer 4 kb ahead
0000:7C4F 5A     POP DX                Track (cylinder) counter, started at 3...
0000:7C50 4A     DEC DX                ...2...1...
0000:7C51 75E8   JNZ 7C3B              Loop back unless 0

So we have now read three tracks of four sectors of 1024 bytes each into 0060:0000, 0060:1000 and 0060:2000.

; Restore disk controller parameter block pointer
0000:7C53 2BC0   SUB AX,AX               AX=0
0000:7C55 8ED8   MOV DS,AX               DX=0
0000:7C57 BB7800 MOV BX,0078             BX=0078
0000:7C5A 8937   MOV [BX],SI
0000:7C5C 897F02 MOV [BX+02],DI
0000:7C5F 06     PUSH ES
0000:7C60 2BC0   SUB AX,AX
0000:7C62 50     PUSH AX
0000:7C63 CB     RETF                    POP IP = 0, POP CS = ES

RETF pulls an instruction pointer and code segment from the stack, and execution moves there (0060:0000).

; ERROR
0000:7C64 2BDB   SUB BX,BX               BX=0
0000:7C66 B049   MOV AL,49
0000:7C68 B40E   MOV AH,0E
0000:7C6A CD10   INT 10                  AH=0E, teletype output, 49 "I"
0000:7C6C B04C   MOV AL,4C
0000:7C6E B40E   MOV AH,0E
0000:7C70 CD10   INT 10                  "L"
0000:7C72 B04C   MOV AL,4C
0000:7C74 B40E   MOV AH,0E
0000:7C76 CD10   INT 10                  "L"
0000:7C78 F4     HLT

0000:7C79 CF 02 25 03 04 2A FF 50 F6 19 04

This is the modified parameter block, 03 = 1024 bytes/sector (normally 2 = 512 bytes/sector) , 04 = 4 sectors per track (normally 8).
Of course MSDOS diskcopy barfs at 1024 byte sectors and there’s your copy protection.

ZORKTOOLS will rewrite the 4×1024 byte sectors to 8×512 byte sectors and patch the bootloader to match.

Early in-line memory modules

IMG_9817r

Predecessor of the SIMM?

IMG_9816r

This comes from a piece of medical equipment made by the other S&W, Simonsen & Weel, Denmark, circa 1979.

IMG_9769r

Each module has 8 x AM2808PC 1024-bit dynamic shift registers, driven by a DS0025CN two-phase clock driver. That’s one kilobyte of storage per module, and you have to keep on clocking the data around the ring otherwise the capacitors making up the memory discharge and forget.

It’s a lot simpler than a mercury delay line memory, but functionally it’s not that much different.

 

 

 

Virgin no more

Windows30

I installed Windows 3.0 for the first time today* From seven 720 kilobyte stiffy** disks. And it worked first time.

 

* Windows 3.1, I’ve installed countless times. Windows 3.0, never.

** Yea that’s what we call them here.

Some code I wrote, years ago

Early eighties, to be more precise.

You see, there was Apple DOS (Disk Operating System). And then there were other Disk Operating Systems, faster and therefore better (OK, faster because very often they left out a whole lot of error checking that the Apple DOS performed — but if you have an error there’s not much you can do about it so why check :-)

One of these was Diversi-DOS. It had a splash screen, which of course was stored on the disk, along with display code.

So of course I promptly hacked the splash screen to display my own message. Recently came across a printout from way back then. So here we have some of the first machine code I ever wrote.

086C-   20 2F FB    JSR   $FB2F       JSR $FB2F and $FC58 clears the High-Res and normal text screens.
086F-   20 58 FC    JSR   $FC58
0872-   A0 00       LDY   #$00
0874-   B9 A2 08    LDA   $08A2,Y     Y=0, load from $08A2 (it's down there, 8D 8D 8D etc)
0877-   F0 07       BEQ   $0880       If the value you've loaded is zero, go to $0880 ($00 marks the end)
0879-   20 ED FD    JSR   $FDED       Otherwise print the character ($FDED prints the accumulator A), increment Y
087C-   C8          INY
087D-   4C 74 08    JMP   $0874       And get the next character
0880-   A0 04       LDY   #$04        Now, load Y with 4 and jump to the subroutine at $0895, below.
0882-   20 95 08    JSR   $0895
0885-   C8          INY
0886-   C0 20       CPY   #$20
0888-   D0 F8       BNE   $0882       Then, increment Y and loop, stop when Y reaches $20 (32 -- $ indicates base 16)
088A-   20 95 08    JSR   $0895
088D-   88          DEY               Now do the same thing, but from $20 down to 4.
088E-   C0 04       CPY   #$04
0890-   D0 F8       BNE   $088A
0892-   4C FD 08    JMP   $08FD       And then exit (back to Diversi-DOS)

                                      So here we are with Y=4..31, then 32..5
0895-   98          TYA               Move Y to X via A (because this is how a 6502 works) Second TYA maybe a bug*
0896-   AA          TAX
0897-   98          TYA
0898-   8D 30 C0    STA   $C030       Click the speaker by accessing $C030 (yes, one bit, on or off, no Soundblaster)
089B-   20 A8 FC    JSR   $FCA8       $FCA8 delays for some time dependent on the value in A
089E-   CA          DEX               Now decrement X and loop, i.e. do this as many times as the value in Y
089F-   D0 F6       BNE   $0897
08A1-   60          RTS               And return
08A2-   8D 8D 8D    STA   $8D8D       This is the text that gets displayed by the code up there from $872 to $87E
08A5-   8D 8D 8D    STA   $8D8D       Says "COPIED BY THE DIRTY DEVIL"** in the middle(-ish) of the 40 x 24 screen
08A8-   8D 8D 8D    STA   $8D8D
08AB-   8D 8D 8D    STA   $8D8D
08AE-   A0 A0       LDY   #$A0        $A0 = Spaces
08B0-   A0 A0       LDY   #$A0
08B2-   A0 A0       LDY   #$A0
08B4-   C3          ???               $C3 = C, $CF = O and so on.
08B5-   CF          ???
08B6-   D0 C9       BNE   $0881
08B8-   C5 C4       CMP   $C4
08BA-   A0 C2       LDY   #$C2
08BC-   D9 A0 D4    CMP   $D4A0,Y
08BF-   C8          INY
08C0-   C5 A0       CMP   $A0
08C2-   C4 C9       CPY   $C9
08C4-   D2          ???
08C5-   D4          ???
08C6-   D9 A0 C4    CMP   $C4A0,Y
08C9-   C5 D6       CMP   $D6
08CB-   C9 CC       CMP   #$CC
08CD-   00          BRK

* As I said, the second TYA is not needed, TAX doesn’t change A. But it’s from the earlier code, which didn’t vary the time of each “note”.

** Which is what I called myself waybackwhen.

The result is a sliding note that slows down as it gets lower, then speeds up again. At full volume (erm, there only was one volume) it’s guaranteed to get attention. Of course some guys were much much more into this than I was.

Stay tuned (might take a few years) for when I blog about the digitized voice I once hacked into the Diversi-DOS startup screen… yes, you can recognizably digitize a voice using only one bit.

 

Old friends, now obsolete

Ah yes, New Years’ resolutions. Gotta love ’em.

However, I have too much stuff. There. I said it. I mean, I firmly believe in the William Morris quote,  however, times have changed.

This collection of Elektor magazines I grew up with — obsolete.
A collection of GE Ham News that someone spent money on to have nicely bound — obsolete.

Byte magazines? Obsolete.

Creative Computing? Not quite yet obsolete.

And even if I can’t find it online, scanning and dumping* is better than storing the originals until my container is auctioned off one day.

Don’t get me wrong — I’m still keeping mountains of stuff. Just not… this stuff.

 

* Yes, Jason doesn’t like dumping. I’m not dumping anything that’s even slightly rare, so chill.

The Sixth Stage of Grief Is Retro-computing

Moore’s law, the speed at which technology moves forward, means that the digital past gets smaller every year. So this is what is left are the tracings of hundreds of people, or thousands, who, 20, 30, 40 years ago found each other and decided to fabricate all this…digital stuff. Glittering ephemera. They left these markings and moved on.

Who wouldn’t want to go back 20 years—to drive again into the office, to sit before the whiteboard in a beanbag chair, in a place of warmth and clarity, and give it another try?

Go read.

Windows 7 on the Dell 910

I suppose the URL of this blog gives it away, so nobody will be shocked to hear that I’m often slow to adopt technology.

So I only recently moved to Windows 7 from Windows 2000. You see, there’s nothing really wrong with Windows 2000.

What is wrong is that the latest ChromeFoxEra doesn’t run on Windows 2000 any more, and the latest Flash plugins don’t plug into the earlier versions of ChromeFoxEra, and the older Flash plugins won’t play Youtube movies any more because of a completely misguided opinion that one can make it impossible to download movies off the ‘net if you use the latest greatest features of Flash.

Or something like that.

And with both my home PC and my work PC now running Windows 7 (Classic desktop theme, animations and special effects very much “off”) it was time to upgrade the Mini 9 from XP to 7.

Google gives many hits on how to do this. But those websites / blogs don’t exist any more.

Fortunately we have the Wayback Machine, which saved a copy of multimolti‘s blog which is OK and a copy of Rick White’s blog which is excellent.

So I followed that, except that I used the very excellent Rufus to make a bootable USB stick.

Peeve: vlite is a nifty tool, but it needs the Windows Automated Installation Kit (WAIK). Download vlite, 1.4 megabytes. Download WAIK, 1.4 gigabytes. Microsoft needs to take some lessons from Steve Gibson.

 

Vendor 197B, Device 2382 / 2383 : Card Reader from JMicron, download drivers here.

ACPI\CPL0002: Battery meter, install R192569.EXE.

Touchpad driver: From Synaptics. Yes, you have to download the 118 megabyte file for Windows XP, Vista, 7 and 8, 32 and 64 bit. I guess it’s more convenient for them that way. And you then have to go to Device Settings / Settings to turn off tapping (which is the only reason I needed this driver anyway).

(http://www.mydellmini.com/forum/dell-mini-9-guides/2707-drivers-dell-inspiron-mini-9-910-a.html)

NIGHTMARE #6

One of the disks that came with my Apple ][ clone contained a little game called Nightmare #6. At the time it completely stumped me, there seemed to be no way to beat the game. I’d worked out that a move consisted of two letters, no more, no less, and that it was possible to lose points quite quickly, and also possible to not lose points, but I never worked out how to actually gain points.

For some reason I thought of this game again the other day, tried to find it. This was not easy, but plenty google later I found it in the Apple Software Bank Volume 1.

Of course my BASIC is better than it was in 1980. I learned that:

  • You get eleven moves
  • Each move consists of two letters
  • Using the same letter twice gives you a “nightmare #6”, which doubles the amount of points you lose on the next wrong move
  • Re-using the first letter of a previous move gives you “super zonk”, which quadruples the amount of points you lose on the next wrong move
  • Any other move gives you no points, except when the value of the two letters (A = 1, Z = 26) add up to a multiple of ten.
  • If the letters add up to a multiple of ten, you score that value, and the score associated with the second letter is set to this same value.

So, NZ (14 + 26 = 40) is a valid move. So is OY, PX, QW, RV and SU. After playing these, you can’t re-use N, O, P, Q, R or S, but U, V, W, X, Y and Z are all set to 40, so UV, WX and YZ are legal moves for 80 points each, and leaves V, X and Z set to 80.  VZ and XZ give you 160 points each, finishing the game with 1880 points out of a (claimed) possible 2080 points.

So I thought about it some more. Realised that while NZ is a good place to start, XZ (24 + 26 = 50) is better. Of course this means that PX is no longer a legal move, you can’t play the first letter again. OY, QW, RV and SU are still good for 40 points each, and YZ, WZ, VZ and UZ give 90, 130, 170 and 210 points (because the point value of Z increases every time). But this is only nine turns, and we need eleven. Fortunately we still have J (= 10) and T (= 20) to play TZ and JZ, for a total score of 2280 points.

I still don’t know how the author got to the “possible 2080” points.

Screen capture of end of Nightmare #6, with 2280 out of a possible 2080 points.

 

Oh yes, and this is why I’m with Jason Scott — we’re not huge Wikipedia fans because they delete perfectly good information.  Someone took the trouble to write something about Nightmare #6, and noted that it is possible to get more than 2080 points, but the editors decided that “WP is not a videogame guide“.

 

 

 

 

Streisand Effect

There’s a hoary old bit of Internet folklore, that in the mists of time when dinosaurs roamed the computer rooms, there existed a machine which could be upgraded by cutting a single wire.

In other words, the machine shipped with more power than you paid for, with some kind of a silicon handbrake to cripple the hardware until such time as you could afford to pay for an upgrade.

But that’s long ago and we do things differently now some people don’t learn from history.

Because apparently Tektronix sells equipment with built-in capabilities that costs money to enable, except if you can program an EEPROM. And not with some encrypted password or string, no, apparently plain text available straight off of Tektronix’ website will do the trick.

So after Hackaday linked to Oontz’ website, Tektronix got all butthurt and issued a DMCA takedown notice.

Notes to Tektronix:

1. Streisand Effect. I wouldn’t have written this post if you had not got all upset.

2. Wayback Machine. Jason saved it all for us. Including the original post.

3. Once the cat is out of the bag, it becomes trivial to replicate. Even if you DMCA the Wayback Machine, and me, and everyone else… you still lose. See Note 1.

So, learn from this and design better security next time.

 

The $25 Network

These days one can network a bunch of computers for $25 without breaking much of a sweat, since most if not all computers these days come with a network port right there on the motherboard, and if it’s a notebook there will be wi-fi right there as well.

But back in 1987 networks were a big deal. Arcnet came out in 1982 and Ethernet was standardized in 1983 — using almost-a-centimeter-thick coax cables with the delightfully named “vampire tap” connecting stations to the backbone. Yes, we’ve come a long way.

So being able to network two or three machines for $25 was a Big Deal. At around the same time you could get two Ethernet adapters and a cable from LANtastic for $699.

How? Point-to-point serial cables, with one machine acting as a hub in three-machine installations. According to the documentation, this is good for 80 feet at full speed (115 kbit/s). This and some very clever DOS software from D. Jindra and R Armstrong, calling themselves Information Modes and operating from a drawer in Texas. All drives (which in 1987 meant 360k to 1.2Mbyte floppies, and maybe a 20Mbyte hard drive somewhere) and printers could be accessed from all the machines in this network.

It was magic, I tell you. Kids of today, they don’t believe a word of it.

 

  • Link to the files I have (Time has not been kind. There’s some bitrot in the filenames I think)
  • The Data Packrat has a disk image of a different version of the $25 Network and delightfully odd ideas of how the internet works.