From: koch@sylt.informatik.uni-kl.de (Peter Koch - DA Gesmann) Subject: Emulating an Apple ][ Disk Controller Organization: University of Kaiserslautern, Germany Date: Fri, 13 Aug 1993 12:11:02 GMT Lines: 58 Hi! Some month ago, i decided to write a Apple ][ emulator. Just for fun (and it was fun indeed)! My decision to use Unix and X-Windows as platform and C as programming language comes from the fact, that this is my favourite programming environment in general. Up to then, i had already learned about a few other emulators. For Unix, there were none, that could do graphics (especially hires). The emulators for IBM-PC did graphics, but i couldn't afford it to buy a IBM-PC. For today, i'll tell the story of my disk controller emulation. This was especially challenging, because the apple does all disk operation 'by itself', that is, there is NO controller-chip, that does the main work. This makes emulating so difficult: the interpretation of the bit-patterns on a disk is completely done in the apple's software. There are two ways to make the disk emulation: 1) open a hole in the apple emulation and transfer the disk data into memory magically and work around any apple software 2) feed the disk data into the right place, so the apple's software is fooled and thinks, it's data from the disk Option 1 is not as easy, as one might suspect: You have to trap the RWTS/RWTB (read/write track and sector (block) routine) entry of the operating system and to interpret his parameters. But there are more DOSes for the Apple, than stars on the sky: DOS 3.3 (and his clones like Z-DOS, Diversi-DOS, Superdos etc. etc.), ProDOS (from 1.0.1 up to ProDOS 8), UCSD (1.0 to 1.3), CP/M (remember: the I/O is done by the 6502, not the Z80!) and many many fast (or not so fast) loaders of programs (games!) not needing a full DOS. Therefore, i choosed option 2. I could have used a disk image format, that consists of the raw disk patterns. This is fairly simple but uses over 6000 bytes per track (over 210 kBytes for 35 tracks). But i used another approach: The disk image contains only the logical data: 256 bytes per sector, 16 sectors per track and 35 tracks per disk in the naive order (140kbytes). The data from the disk is converted (nibblized) on the fly and fed to the I/O-locations. Patterns coming from these locations are denibblized (on the fly) and stored in the disk image file. Syncronization and header bytes are added (or removed) from the bytestream where necessary. That means, the emulator reverses the actions of the RWTS/RWTB. So, my emulator will boot up any disk image, which is copyable by COPYA or FILER. A last remark: The emulator code for the disk controller doesn't use Unix- specific stuff anywhere. A disk change is simply sensed by a flag. But how to set this flag, when a disk change is necessary? I used Unix signals to do the job: if a SIGUSR1 signal is sent to the emulator, the signal is catched and the signal routine sets the flag. Done. This is simple and elegant, but it won't work with MS-DOS or Windows. But i don't have sleepless nights therefore ;-) Peter (koch@informatik.uni-kl.de) -- @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Peter Koch, Universitaet Kaiserslautern (AG Haerder, Raum 36/318) Postfach 3049, D-6750 Kaiserslautern (Germany) @@@@@@@@@@@@@@@@@@ koch@informatik.uni-kl.de @@@@@@@@@@@@@@@@@@ From: koch@sylt.informatik.uni-kl.de (Peter Koch - DA Gesmann) Subject: Apple Hires Graphics Organization: University of Kaiserslautern, Germany Date: Mon, 30 Aug 1993 15:10:49 GMT Lines: 44 Hi! Have you ever programmed graphic routines for the apple? Then of course you've already noticed, how weired the apple graphics (especially hires) works and how good one can use this weirdness for special effects (ever heard of the "vertical pink line" ???). Emulating the apple graphic is very interesting. How much effort is needed to do it "completely" ? And how much effort would you spent for the details? My implementation of the apple graphics is NOT very complete. But i've worked a lot on it (more than on the CPU) to make it "look like an apple". Of course there is a tradeoff between speed and "look like". For example: The color "white" on the hires screen occurs, if the bits of two adjacent pixels are set. This holds even for pixels, where the bits are in different bytes. Try it on my emulator: HGR:HCOLOR=3:HPLOT 0,0 TO 100,100 You will notice, that on each byte boundary the pixels are green and violet (instead of simply white). Not very anoying, but visible. Emulating this effect "correct" would be too complicated (and very slow). Another example is screen switching. Many programs avoid flickering by showing page 1 and drawing into page 2 of the hires screens. My emulator keeps a page (and does all drawings into the pixmap), while the other page is visible. But keeping all possible screens (2 text pixmaps, 2 lores pixmaps and 2 hires pixmaps) up to date is expensive: If the memory is used as data storage (not graphic), there would be much unnecessary traffic between the emulator and the X-server. To avoid this, i use a complicate scheme when to keep a pixmap (and updating it) and when to trash it (complete redraw, if it becomes visible). On the old Apple ][+, the eight bit of each byte determines the color set (green+violet or red+blue) for the other 7 bits. On a b&w monitor, this results in a half pixel shift. This effect can be used for a "swimming" or "color circulating" picture. My emulator does no "half pixel shift". Note, that on Apple //e or //c, the "half pixel shift" is gone. Ok, so far on graphics. Peter (koch@informatik.uni-kl.de) -- @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Peter Koch, Universitaet Kaiserslautern (AG Haerder, Raum 36/318) Postfach 3049, 67653 Kaiserslautern (Germany) @@@@@@@@@@@@@@@@@@ koch@informatik.uni-kl.de @@@@@@@@@@@@@@@@@@ Hi! > Another example is screen switching. Many programs avoid flickering by > showing page 1 and drawing into page 2 of the hires screens. My emulator > keeps a page (and does all drawings into the pixmap), while the other page > is visible. But keeping all possible screens (2 text pixmaps, 2 lores pixmaps > and 2 hires pixmaps) up to date is expensive: If the memory is used as > data storage (not graphic), there would be much unnecessary traffic between > the emulator and the X-server. To avoid this, i use a complicate scheme > when to keep a pixmap (and updating it) and when to trash it (complete > redraw, if it becomes visible). > >In most applications, text page 2 is not used, and programs use either >lores or hires graphics, so wouldn't it be a good idea to set these as >options when lauching the emulator, so that it speeds up things (and >maybe it prints a warning message when the program is selecting one of >the screens that isn't memorized)? My emulator has an option "-keep" to keep all pixmaps. If the option is not present, it discards all pixmaps, if another mode (text,lores,hires) is choosen. Only switching between page1 and page2 will leave a pixmap intact. If textpage2 is not selected at all, it's never created and so the range $0800-$0C00 will not make any invisible X drawings. But if a "dumb" program hit's textpage2 at any time, it will be created and updated invisibly. For example: ProDOS 8 (Ver 2.???) does this (dumb, dumb dumb!!!) and then, small BASIC programs will run much slower, because they will have variables below $0C00. The same effect will occur with assembly programs, that write into locations $0800-$0C00. To avoid this, i simply do a GR:TEXT and woooshhhh... the pixmap for textpage2 is gone. But fortunately, most programs stay friendly with my "keep"-algorithm. Hey folks! Do you know other graphic anomalies of the apple??? I'd like to hear of some (perhaps some, i don't know, eh?) Peter (koch@informatik.uni-kl.de) -- @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Peter Koch, Universitaet Kaiserslautern (AG Haerder, Raum 36/318) Postfach 3049, 67653 Kaiserslautern (Germany) @@@@@@@@@@@@@@@@@@ koch@informatik.uni-kl.de @@@@@@@@@@@@@@@@@@ Hi! In his article, Kurt Buecherl writes: >I just found a shareware apple-][-emulator for the pc. #FLAME ON He just discovered apl2em!!! >But neither I tried it out, nor did I ever use an apple. So I cannot tell, >wether this emulator is good or not ;(. It is :-) >I hope this helps you a bit ! #FLAME OFF Yes, it helped me writing my own emulator a bit. Especially, i stole the image format for the disks to be compatible with something already existing. Perhaps it is time to repost the FAQ. Ok, i'm getting serious again. The Apple ][+ is a wonderful machine for hardware hackers. It has 8 Slots at the back of the main board. Usually these slots are filled as follows (CP/M and UCSD required it): Slot 0: Language Card (or Ramcard) Slot 1: Printer Card (Serial or Centronics) Slot 2: Serial Card Slot 3: 80 Column Card Slot 4: Z80 Softcard Slot 5: Disk Controller (or Ramcard) Slot 6: Disk Controller (or harddisk controller) Slot 7: RGB Card For my emulator, i made a similar approach: it has eight "software slots" for slotcard emulations. At the moment, i only have slotcard emulations for Language Card, Disk Controller and an empty slot (huh?). But i'm working on a 80 Column Card and a Z80 Softcard emulation. A Printercard and a Serial Card emulation will follow later (when i've more time). To allow a slotcard emulation to go into any slot, it is necessary to configure it for a given slot before compiling. This is done via the makefile. The source file for the slotcard emulation is processed thru 'sed' and any occurence of the word SLOT is replaced by the slotnumber. A slotcare in the Apple is normally accessed via three memory areas: 16 bytes in the area $C0MX (where M is slotno+8), 256 bytes at $CNXX (where N is the slotno) and they all share the 2048 bytes at $C800-$CFFF. For each of these areas, access functions are provided by the emulation. If a memory location in the appropriate area is accessed, the access function is called. So the emulation needs the following access functions: getC0SLOTX, putC0SLOTX getCSLOTXX, putCSLOTXX getSLOTC8XX, putSLOTC8XX For the Language Card, there exists another interface: it inhibits the on- board rom of the Apple and overlays it with its ram: getSLOTinhibit, putSLOTinhibit Last, but not least, there is an initialization function: initslotSLOT This approach allows emulation of nearly all Apple slotcards in software. Only cards, which use the adress lines or make DMA cannot be emulated. Peter (koch@informatik.uni-kl.de) -- @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Peter Koch, Universitaet Kaiserslautern (AG Haerder, Raum 36/318) Postfach 3049, 67653 Kaiserslautern (Germany) @@@@@@@@@@@@@@@@@@ koch@informatik.uni-kl.de @@@@@@@@@@@@@@@@@@ Hi! First i wish to thank all people, who helped me fixing my good old videx. I had killed my character eprom, when i tried to read its contents :-( Now i've written an emulation of this card ready to use with my Apple ][+ emulator. It was mighty fun to get the videx emulation to run. And ProDOS is much nicer with 80 columns. Other folks urged me to make an Apple //e emulation (which should do 80 columns of course). But before i do that, i have to solve a big problem!!! My text (and graphic) emulation of the Apple ][+ is very slow. I use X-Windows for the emulation and whenever a byte is written which is visible on the apple screen, it is drawn onto the window. This is easy, accurate and very expensive (CPU and communication). The videx emulation has an advantage at this point: It is very fast (even on slow X-Displays), because scrolling is done very efficient. If i'd try to emulate an Apple //e with 80 columns, it would become even slower than with 40 columns. Before i start emulating an Apple //e, i need another concept of doing text (and graphic). Therfore my first question: Has anyone a good idea, how to emulate apple graphics with X-Windows? My ideas at this point are: a) use shared memory for the screen memory and a second process for the drawings (nice on multiprocessor machine!!!) b) buffering the drawn bytes, optimizing (eleminating double writings to the same byte) and drawing them in a single action (reduces communication) And now my second question: What do you mean about a) and b) ? Happy emulating! Peter (koch@informatik.uni-kl.de) P.S.: If you are interested in the videx emulation, send me an e-mail. I will include it in the next release of my Apple ][+ emulator, but this could take quite a while, because i want to add even more slotcard emulations to this release (Z80 Softcard, Printer, Serial, Ramcard). But these aren't working (existing) yet. P.K. -- @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Peter Koch, Universitaet Kaiserslautern (AG Haerder, Raum 36/318) Postfach 3049, 67653 Kaiserslautern (Germany) @@@@@@@@@@@@@@@@@@ koch@informatik.uni-kl.de @@@@@@@@@@@@@@@@@@ > >Therfore my first question: >Has anyone a good idea, how to emulate apple graphics with X-Windows? > >My ideas at this point are: > a) use shared memory for the screen memory and a second > process for the drawings (nice on multiprocessor machine!!!) > b) buffering the drawn bytes, optimizing (eleminating double writings > to the same byte) and drawing them in a single action (reduces > communication) > >And now my second question: >What do you mean about a) and b) ? > Method a is probably the easier. The way I would implement it is to have two shared memory arrays. One would represent the screen; writable by the emulator process, readable by the video process. The other would be a "change mask" (read/write for both processes) telling the video process which pixels had changed. The video process would scan through the "change mask" when it found a byte that had changed it would update it in the window, and reset the appropriate bit (or byte) in the change mask. This method has the advantage of including method b. If a byte is written multiple times, the video is still only changed once per scan. It also has the advantage of deteching emulator speed from the video speed. (OK, so this is a disadvantage for playing games. The video can end up pretty far behind.) The video speed can also be changed by altering the priority of the video process. Optimizing the "change mask" scan and the mapping of the screen memory to pixel position are the difficult part. Personally, I would put all of the video mode control (text, 80 column, lo-res, hi-res, double-res) into the video process (given that they all use the same memory area) and use the "change mask" scan method for all video updates. That means you need a third shared memory array for the I/O control bytes. I hope this helps out, and I wish you sucess. Eric -- Eric Korpela | The two most common things in the korpela@ssl.berkeley.edu | universe are Hydrogen and stupidity. | -Harlan Ellison