Showing posts with label apple2. Show all posts
Showing posts with label apple2. Show all posts

Wednesday, November 28, 2018

My first Apple IIgs hardware fix

So when I was a kid, my dad bought an Apple IIgs for Christmas of 1986 and I loved that thing and used it until I finally gave up around 1993 and moved to a MS-DOS 486.

I still have this original machine and it's a ROM 01 machine which means it may have more game compatibility.  Apple also released a ROM 03 version which is newer, has more memory, but may not play every game that the ROM 01 could.  I decided to purchase a ROM 03 a year or so ago so that if my siblings ever came and demanded the ROM 01 family machine back, I'd still have a IIgs that I could call my own :)

Well, the ROM 03 IIgs came and I left it in a box for many months.  Finally, last Father's Day, I opened it and tried to show my kids some games.  That's when I discovered that it had a sound problem!

Fast forward to a week ago.  An accelerator board and a power supply replacement that I paid for literally 7 months ago finally showed up and I was eager to install it in my ROM 03.  But I decided that I really wanted to fix the sound problem before messing with the accelerator.

So I did some basic troubleshooting and this stuff was happening:



My first attempt to fix the problem was to simply de-solder the sound chip and socket it.



I've done this sort of thing several times on arcade PCBs so not only was I familiar with how to do it, but I already had a de-soldering gun along with several 40 pin sockets so I didn't have to wait for any parts to arrive.

Unfortunately, it did not fix my problem.

I wanted to replace the sound chip, but didn't want to destroy a working Apple IIgs.  Fortunately, someone was selling a "battery acid destroyed" IIgs motherboard on ebay, so I got it for fairly cheap.

The acid damage was really bad but it looked like the sound chip was still okay, so I desoldered it.


I plugged the replacement sound chip into my ROM 03 IIgs ...


and fired up the self-test...



Wow!  Despite thinking that replacing the sound chip would likely fix the problem, I was still a bit giddy to see that it actually worked! :)

I fired up a game to test the sound ...


and everything sounds great!

I'm one happy camper.

Now... to install that accelerator board... :)

Saturday, January 21, 2017

Everything I ever wanted to know about the Apple IIgs RGB monitor signals

My favorite 80's computer by far is the Apple IIgs.  I had this machine as a kid growing up and thought it was awesome.  I think I was even more stubbornly loyal because so many of my peers refused to give it the respect that it deserved.

Well, the Apple IIgs stock RGB monitor is intriguing to me because it is relatively small and I do a lot of work with arcade game PCBs in a bench type setting.  I have a need of a nice compact RGB monitor for testing and so if I can somehow use the Apple IIgs monitor for this purpose, that would be awesome.

asked a question on Facebook about the Apple IIgs RGB signals and got no response.  Either no one knew the answer or no one knew why I possibly would want to know. :)

Never one to rely on other people to achieve my goals, I decided to take matters into my own hands and created a little break-out PCB so that I could 'sniff' the RGB signals myself and get my own answers.

The first step was to whip up the schematic in Eagle:


I whipped this up as fast as possible because I knew that I would only need this board once and then probably would never use it again.

I spent an equally short amount of time on the PCB layout:


This was a mistake to rush through this, but not a fatal one.

On a recommendation from a friend, I decided to use pcbway.com to make the PCB.  To my shock, I had the PCB in my hands in only 7 days after placing the order.  And it was from China!!  Only cost me $10 for 10 boards (why buy one when you can get ten? lol) and $20 for shipping which is a steal in my book.  Awesome!


After ordering the rest of the parts I needed from digikey.com, I whipped out my soldering iron and got to work.

It was then that I realized my mistake.  I wasn't paying close attention to the DB15 datasheet and ended up having the two connectors facing INWARD instead of outward.  That simply was not going to work!!!

Not to be defeated, I decided to solder on wires and hack the thing together enough to do what I wanted.




I plugged it in ...

and turned on my IIgs ...


it was working!! WOOHOO!!!

Once I got this far, I decided to hook up my Rigol scope to the CSYNC and BLUE signals to see what kind of voltage levels I was getting.


I decided to use a nice nearly solid blue screen so that I could see what the full blue intensity would be.

First I wanted to see what vsync looked like:
Interestingly, the blue signal seems to also contain sync information.  I really don't understand why they would do this and I strongly suspect that this monitor will probably work without the sync info being part of the color voltages.  But I guess I'll find out.  At any rate, I observed that the sync was a fairly typical negative composite sync signal going from 0-5V with hsync being mixed with vsync.  I've seen it both ways where the vsync is a solid low pulse and where vsync has hsync mixed in with it.  This is, I believe, what the jamma csync looks like (or is pretty close at least).

Next was to see what the voltage range of the blue signal was by going to a random line in the middle of the field/frame:

 It looked like the voltage was going from 0-1V.  I'm glad I checked this because I would've assumed it would've been from 0-5V.  If I do rig up arcade PCBs to talk to this monitor, I'll probably need to drop the voltage down to avoid damaging stuff.

Next I wanted to zoom in on an hsync pulse and see how wide it was:


Nothing earth-shattering here.  Just wanted to document it :)

Just to be sure I was seeing what I thought I was seeing, I decided to switch the screen to a black background with blue border:



This is what I was expecting.  By zooming in a single line, I was expecting to see 1V near the beginning of the line, followed by a drop in voltage to indicate black, followed by 1V again toward the end of the line, and that's exactly what I am seeing here.  Interestingly enough, black seems to be around 0.3V, not 0V.  It seems that 0V is reserved for sync signals.  This is pretty similar to how NTSC composite works.

Again, I suspect that it is not necessary for the sync signals to be part of the blue signal, but maybe I'm wrong.  Why would Apple go to the trouble of including it if they didn't have to?  Maybe it was part of the RGB encoder they used. *shrug*

The last thing I wanted to document was whether this signal had fields like an NTSC signal.  The NTSC signal's vsync pulse is slightly different depending on whether it is a top or bottom field.  I wanted to see whether this RGB sync had the same kind of characteristics.

Using a scope was probably not the best way since I didn't have a good way to trigger on vsync.  Therefore, I switched to using my Saleae logic analyzer to measure distance between vsync pulses:


Here's a logic analyzer capture zoomed in on a vsync pulse.  It looks similar to what it looked like on the scope except more well defined :)

Zooming out, I was able to put time markers on each vsync to see the intervals:


As you can see, the interval between each vsync pulses is "exactly" 16.689 ms with no variation.  This means that it is a ~60 Hz signal but that it not like NTSC composite where top and bottom field vary.  However, I am not sure what it _does_ mean :)  I don't  have a lot of experience with progressive signals, but if I were to guess, I'd say that this is a progressive signal and that the entire frame is being sent 60 times per second.  The hsync pulses were similar to NTSC (63.5uS apart) so I'd guess that this means that this signal is describing 525/2 lines just like NTSC (~262.5ish but without the decimal since it's progressive).  That would kinda make sense since the IIgs can display 200 vertical lines and it has this extra border on the top and bottom.  But I'm kinda just speculating at this point.

At any rate, I've concluded that in order to get this monitor to work with arcade games, I'm going to need to do a few things:

a) if arcade game has separate positive vsync and hsync, I'm going to need something like an xnor gate to combine them.  Otherwise if it's just a jamma csync signal, I may be able to use it unmodified.
b) if arcade game RGB voltages are 0-5V, I'll probably have to add some resistors to drop the voltage down to 0-1V.  This may be something that I play around with until I find values I like.

I hope you enjoyed my journey.

Monday, June 22, 2015

Reverse engineering Zany Golf (Apple IIgs version) just enough to be able to actually see the whole game :)


So yesterday was Father's Day, and I decided that I wanted to show my kids my old Apple IIgs games that I loved.  We pulled up Zany Golf but had a problem: my kids kept losing all their strokes (turns) immediately so they weren't having any fun!  I searched online for a cheat so that I could show them the whole game but found nothing.

Challenge accepted!

Tools used: KEGS debugger (setting breakpoints, etc), gdb, and IDA Pro

Why using an emulator is so much nicer: Using an emulator to reverse engineer these old pieces of software is so much more convenient than using a real Apple IIgs.  For one thing, it's a lot faster to start the game.  And for another things, its built-in debugger is much nicer for stepping through code than trying to hack the boot process of the game enough to do it with the built-in monitor (yuck!).

I decided to search for the message "Player 1, this is your last stroke." because I knew that somewhere near this message would be some logic to check to see what the current stroke count was.  And if I knew where the current stroke count was stored, I could set a breakpoint and catch when it gets changed (decremented).

First thing I did was searched for this string on disk.  I found it inside the file named "CODE" inside a Zany Golf subdirectory.  At this point, I realized that this wasn't very helpful because I did not know how CODE got loaded into memory.  I decided that I needed to run Zany Golf in KEGS and search the memory for this string to find where it got loaded.

Unfortunately, I discovered that KEGS (apparently!) does not have a memory search function.  After a few false starts down other paths, I decided to whip up a quick n' dirty memory search function that searches the entire emulated memory space for the string I was looking for.  On a modern PC, this brute force approach still completes very quickly so it's no big deal.

I tried to understand how KEGS actually managed the emulated memory and I got confused quickly.  As grateful as I am to have an emulator for the Apple IIgs, KEGS unfortunately is somewhat convoluted for me (although maybe others don't have as much trouble) with heavy use of global variables that look like local variables, and lots of macros.  So I ditched the idea of understanding how KEGS handles its own memory and instead just wrote a new search method that calls the get_memory_c method that KEGS provides and which the debugger uses to do memory dumps.  My custom method was tailored specifically to the search string and once I found the string, I wouldn't need it again.

Using this approach, I found the string at $01/736D.  On disk, it is at offset $726B inside the CODE file which is kinda weird.  This suggests that CODE is loaded at $01/0102.  I used IDA Pro to disassemble CODE at this starting address to give me some more visibility.  This succeeded with partial success although a lot of the 8/16 bit addressing modes were fouled up.

So the next task was to find when this memory location got read.  Since KEGS did not provide a memory breakpoint feature, I decided to use gdb instead.  First I had to find out where the native memory location for this emulated memory location was.  So I set a breakpoint on get_memory_c and inside KEGS debugger, I type "01/736d" so that only that memory location would grabbed.

I stepped through gdb at this point and after the GET_MEMORY8 macro was called, I typed "print ptr" to see the native memory location.

It came back as 0x7ffff647746d (ie a random number) and this value isn't that important because it may change each time the emulator is run (at least that is my impression).  What is important is that I set a memory breakpoint on it and then get the string about my last stroke to appear by playing through the game.

So I typed "rwatch 0x7ffff647746d" and then "continue" to return control to KEGS.  I then typed "g" to exit KEGs debugger and resume the game.  I played the game until I had one stroke left and sure enough, my memory breakpoint got hit! Woohoo!

'kpc' is the variable name inside KEGS that holds the Program Counter (PC) so I typed "print kpc".

kpc was set to $13e22 (which is $01/3e22).  Finally, a starting point to start stepping through the code!

I set a breakpoint on $01/3e20 and restarted the game.  But the breakpoint was getting hit too often so I concluded that it was part of the "Draw text" routines.  So I disabled the breakpoint, started a new game, and played until right before the message was to appear.  Then I entered KEGS debugger again and set the breakpoint.

I putted the ball and sure enough the breakpoint got hit again.  I set a new breakpoint on the RTS instruction which came shortly thereafter (because KEGS does not have a way to 'step out' of a function, so this is a poor man's equivalent).

This took me to $01/440C which made the JSR, but this is the beginning of a subroutine (according to IDA Pro) so I concluded that nothing interesting was here.  I set breakpoint on 4428 (right before RTS) to step out of this method.

This took me to $01/4437, which is still a small subroutine and did not appear to do any logic to check to see if it's the last stroke.  I set breakpoint on $01/4440 to step out of the function.

This took me to $01/6da2 which modifies $28 and $29 so this may be the subroutine that sets the message about it being the last stroke, as I noticed some references to these constants earlier.

I set a breakpoint at $01/6deb, right before the next RTS to step out of this method.

This took me to $01/73cb.

Ah ha!  I did a disassembly a little before this point and saw that $01/73b4 does "LDA $424E,X" and "CMP #1" and "BNE $73CB".  This is exactly what I've been looking for: something that checks to see if a value is equal to 1.  Therefore, $01/424E,X must hold the strokes for the current player!

Looking a little further back, at $01/73b1, I saw LDX $4218 right before the LDA $424E, X ; so $4218 must hold the current player (I assume it would be 0-3).

Returning from this function put me at $01/7473.  I saw that the previous call was JSR $7390.

I did not see anything that decrements the memory location jumping out at me so I went back to gdb's data breakpoint on this memory location ($01/424E) using the same technique that I described earlier.

Without even needing to start the game over again, I putted the ball again (which concluded with my game being over) and the memory breakpoint was hit... ($01/705E)

*BOOM*

Here's the code that decrements the stroke count! :)

ROM:7058                 LDX     word_4218
ROM:705B                 LDA     $424E,X
ROM:705E                 DEC
ROM:705F                 STA     $424E,X

Looks like a simple NOP at $705E should do the trick to give unlimited strokes.

Using a sector editor, such as Copy II Plus, search for AE 18 42  BD 4E 42  3A  9D 4E 42 (I found it on block $40)

Change the 3A (DEC) to EA (NOP)

You can now show your kids this game without making them get frustrated!! :) :) :)

I've tested through level 2 and have no idea if something REALLY BAD will happen if the stroke count gets too high later, so take that as a caveat.  Possible changes to this mod are to hard-code the stroke count to something like 5 instead of NOP'ing out the decrement.

-------------------

UPDATE 23 Oct 2015:

I wanted to try this trick again on a different disk but had forgotten how I hacked KEGS to do a memory search.  Here is the function I wrote for reference:

void find_zany()
{
        unsigned char array[] = { 0x50, 0x6C }; // "Pl"
//      unsigned char array[] = { 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72, 0x20 };   // "Player "
        unsigned char cmp[sizeof(array)];
        int iBank = 0;
        int iAddr = 0;
        int i = 0;

        // search all reasonable banks where it could be
        for (iBank = 0; iBank < 9; iBank++)
        {
                printf("Checking bank %02x\n", iBank);
                for (iAddr = 0; iAddr < (0xFFFF - sizeof(array)); iAddr++)
                {
                        for (i = 0; i < sizeof(array); i++)
                        {
                                cmp[i] = get_memory_c((iBank << 16) | (iAddr + i), 0);
                        }

                        // if we get a match
                        if (memcmp(array, cmp, sizeof(array)) == 0)
                        {
                                printf("Found a match at bank %02x, addr %04x\n", iBank, iAddr);
                        }
                }
        }
}

Inside dis.c, inside the function called do_debug_intfc(), I added this to the switch statement:

case 'k':       // zany golf
                                find_zany();
                                break;

Friday, April 17, 2015

Help me find out which RGB monitor this is

As a kid, I loved my Apple IIgs computer.  We had a non-Apple RGB monitor for it.  I am pretty sure it was an Amiga monitor and it looked very similar to the Commode 1084S monitor except that the power LED was green instead of red.  I have been looking for pictures of the monitor but so far, all I've been able to find are very grainy video stills from old Video8 (yes, Video8!) tapes!



Friday, August 5, 2011

Microzine #7 rescued!

Chip found Microzine #7 at his mom's house and mailed it to me. He had two copies of it which was a good thing because I had to use both copies in order to get a good read.
Enjoy it here.

Monday, April 25, 2011

Microzine #40 rescued!

I've been sitting on Microzine #40 for almost a month trying to figure out how to save it. The problem is it has failing sectors so typical copy programs like Copy ][+ or archival programs like Shrinkit will see an I/O error and either skip the bad sector or else abort entirely.

But I've had a belief that repeated reads of the bad sectors would eventually result in success.

So I finally wrote my own little sector copy program.

Or at least I intended to. I started writing a DOS 3.3 sector copy program only to realize that all of my development tools were in ProDOS so instead I decided to write a block copier. A block is merely 2 sectors which means I would need to get two good sector reads at a time instead of just one which is twice as "hard" on a disk full of errors, but still very doable.

I am pleased to report that by using my own copy program I was able to "brute force" copy Microzine #40 and save it. (at least, the disk checksums passed so I think I most likely got good reads)

For fun, here is the little ProDOS program that I wrote to accomplish this feat.



* matt copier

mli EQU $BF00
cout EQU $FDED
CLS EQU $FC58
prbyte EQU $FDDA
ptr equ $6

ORG $2000

start
jsr outstr
asc "Insert 5.25 disks to copy and press a key to start",8d,00
wait LDA $c000
bpl wait
sta $c010
loop
lda block_idx
sta readblock
sta writeblock
cmp #$18
bcc :1
lda block_idx+1
sta readblock+1
sta writeblock+1
cmp #$01
bcs :done
:1
jsr outstr
asc 8d,"Block: ",00
lda block_idx+1
jsr prbyte
lda block_idx
jsr prbyte

; read block
:read
jsr mli
db $80
da read_parms
bcs :error ; if no error, do the write

:write
jsr mli
db $81
da write_parms
bcc :next

:error
pha
jsr outstr
asc " Err code: ",00
pla
jsr prbyte
bra loop

:next
; increment block index
lda block_idx
inc
sta block_idx
cmp #$00 ; did we overflow?
bne loop ; if we didn't overflow
lda block_idx+1
inc
sta block_idx+1
bra loop
:done
jsr mli
db $65
da quitparms

block_idx ds 2

quitparms db 4
ds 6

read_parms
db 3 ; 3 parameters
db %01100000 ; drive 0, slot 6
da buf ; read buffer
readblock ds 2 ; block to read

write_parms
db 3
db %11100000 ; drive 1, slot 6
da buf ; write buffer
writeblock ds 2 ; block to write

outstr pla
sta ptr
pla
sta ptr+1
ldy #1
:1 lda (ptr),y
beq :4
jsr cout
iny
bra :1
:4 clc
tya
adc ptr
sta ptr
lda #0
adc ptr+1
pha
lda ptr
pha
rts

buf

typ #$ff
sav copy.system

Friday, March 11, 2011

Got the Sparkfun newbie tutorial completed

I followed this tutorial (after ordering the kit) and got it working. It was pretty exciting to have something to do with electronics actually work for me :)





Then I took it a step further and replaced the tutorial's power supply with a PC power supply.



Thursday, March 10, 2011

Two mysterious packages have arrived!







It's like Christmas morning! :)


The rough inventory:
- A sparkfun newbie starter kit with breadboard (yay!)
- Atmel AVR mega328 (VLDP-HW)
- MAX232 serial port chip (VLDP-HW)
- some resistors, capacitors and LEDs (whatever these are.. lol)
- little power supply
- LD-V1000 female connector (VLDP-HW)
- two female RCA jacks (VLDP-HW)
- TC7662 voltage convertor (Disk ][)
- LM1881N NTSC/PAL video sync separator (VLDP-HW)

Most of this stuff is to help me prototype my VLDP-HW interface. I did get the voltage convertor to help with my Disk ][ project since the Disk ][ stupidly needs -12V and +12V. I hope it works...

Wednesday, March 9, 2011

Stumped.. for now

I am pretty sure my code is sound and I am seeing some unpredictable behavior with the AVR so I am suspecting that perhaps the voltage from the disk drive is unstable. When I was getting readable intervals, I was getting all of them 200-400 cycles apart and some of those intervals should be 60 cycles (4 microseconds at 14.7 MHz) I won't be able to address this issue until some hardware that I've ordered in the mail arrives so for now the disk drive project is officially shelved.

Once the parts arrive, I'll probably start working on the VLDP project instead because that has much more potential for awesomeness. :)

Still getting all 1's...

I plugged in my new revamped assembly language routine and I am getting the same results as I was two days ago. Instead of being frustrated, however, I am starting to get really curious what's going on.

My next step is to time the intervals between pulses again and see if something has changed.

Assembly language routine written!

As I said yesterday, I decided that I needed to re-write my code in AVR assembly language in order to make it fast enough to be able to reliably detect the 4 microsecond bit cells send from the Apple 5.25" disk drive.

I now have ported both the bit detector function and the interrupt service routine (ISR) to assembly language. The ISR was the one that I was the most keen on optimizing because the C compiler added a bunch of wasteful stack pushes/pops that I didn't need, but I also benefited from optimizing the main loop also because I was able to move a global variable from memory into a register which saved a few cycles.. and when talking about microseconds at 14.7 MHz, a few cycles are worth a lot!

I am excited to test out my new routine on real hardware.

Here is the ISR routine below. As you can see, it's pretty short. It gets activated when a read pulse is received from the 5.25" disk drive.

// this interrupt is triggered when a pulse (connected to INT6 pin) starts (active low)
.global INT6_vect
INT6_vect:
in sreg_save, _SFR_IO_ADDR(SREG) ; preserve flags

; When we store this cycle value to the timer, it will be at most 1 cycle off so it is pretty accurate
; I got this value by counting cycles in the simulator/debugger.
; I want the timer to be relative to the start of the pulse so it's easier to visualize in my head.
; The timer will not overflow within the time that it is useful to us.
ldi u8Timer, 12
out _SFR_IO_ADDR(TCNT0), u8Timer

clr bPulseOccurred ; this register should already be 0 in every case but I want to be safe and this only uses 1 cycle
inc bPulseOccurred ; let main loop know that a pulse started

; we need to wait for the pulse to end or else this ISR will get triggered again immediately
wait_pulse_end:
sbis _SFR_IO_ADDR(PINE), 6
rjmp wait_pulse_end

out _SFR_IO_ADDR(SREG), sreg_save ; restore flags
reti

Tuesday, March 8, 2011

Pulling out my hair

So last night I ambitiously decided to take my AVR program to the next level and instead of just logging elapsed time between pulses from the Apple 5.25" drive, I would actually try to convert these time intervals into actual bits so that the emulation community can enjoy copy-protected disk images someday (I find the concept interesting). So I started writing my AVR program, using C. I carefully stepped through each instruction in AVR Studio's simulator and counted the cycles and I felt like I had come up with a pretty awesome solution if I do say so myself. Then I flashed the code to the real AVR and powered up my Apple //gs.

At first, nothing happened and I found and fixed a bug in one of my loops. Then I tried again.

For the next hour, my supposed-to-be-awesome program sat there insolently spitting out 1's at me, no 0's at all. And since I was expecting a healthy mix of 1's and 0's, I was not getting the correct data here that I wanted! I pulled out my hair for probably an hour, then sighed in defeat and decided to go to sleep.

Once I got upstairs, I realized that maybe the problem was that my C program was simply too slow. Also, it didn't help that I was trying to take the easy way out and not use any interrupt handling.

So now I am resigned to the fact that I will probably have to rewrite the program in assembly language and use one or more interrupt handlers to ensure that my timing is rock solid. I had wanted to avoid this because coding in C is so much faster, but I can't seem to tell the C compiler that I want every variable stored in a register instead of in memory. I came close... :)

Hopefully I will have some good news soon.

Monday, March 7, 2011

Wow, I'm closer than I thought


Looking at the AVR elapsed cycle timings in the terminal program was kind of depressing but once I plugged the numbers into a spreadsheet, they looked like I'm almost there as long as I can process the values in a minimal amount of cycles.

This screenshot will hopefully show that a human being (with a lot of knowledge about how the Disk ][ drive works and a spreadsheet) can manually compute the value of the bits that happened to be read at the snapshot in time that this log represents.

It's looking really good! :)

Setting up my AVR has been a real pain

So recently (within the last month), I decided that I needed to learn about micro-controllers (basically cheap mini CPUs) so I could move some of My Cool Projects forward. A friend recommended the Atmel STK600 as a good starter kit, so I got one. The good news is that the STK600 is pretty awesome, the bad news is that the documentation for it is abysmal. So I've been maintaining my own "getting started" guide to help anyone else who may want to tread these waters.

You can find my guide here.

Sunday, March 6, 2011

Getting closer ...


I am thinking that maybe the reason I was getting weird results earlier is because the disk had not had a chance to spin up fully. I created a longer delay and am getting the results I am expecting here, although there are still a few errors.
I will probably have to wait until I find a string of sync bytes before I know whether the drive is spun up properly.

Optimized code a little bit


I've optimized the AVR code a little bit so that the timing for when the disk drive is sending a "clock" signal is now really tight and I am getting the correct results. Since the AVR is clocked at 14.7456 MHz (so that it can send serial communications reliably), 1 microsecond is about 0xE cycles, and I am alternating between 0xC and 0xF cycles in my tests which is exactly what I would expect. Unfortunately, the lengths after the "1" bit are too long. Each bit field is 4 microseconds long, which is about 0x3A cycles, so I should be seeing values near 0x2C at least every 8 bits (because every nibble on the drive has the high bit set).

I'm not seeing that, so I'm wondering if I am missing the transition due to some of my code being too slow.

Attempt #2 on the Apple ][ disk drive

Still not much success, but getting closer...

Saturday, March 5, 2011

Apple ][ Disk Drive Project Started

Back in February, I suddenly got interested in the Apple ][ computer after probably 15 years of having not thought about it.

Specifically, I became interested in understanding how the old copy protection schemes worked. So I decided to see what I could do to figure this out. This video represents an early (failed) attempt at reading the raw bits off of an old 5.25" disk.



Hopefully I will be posting some success later.