Newsgroups: comp.sys.apple2.programmer Path: news.uiowa.edu!news.physics.uiowa.edu!math.ohio-state.edu!howland.reston.ans.net!newsfeed.internetmci.com!in2.uu.net!comp.vuw.ac.nz!actrix.gen.nz!dempson From: dempson@atlantis.actrix.gen.nz (David Empson) Subject: Re: What do PR# and IN# do inside? Message-ID: Sender: news@actrix.gen.nz (News Administrator) Organization: Actrix - Internet Services Date: Thu, 4 Jan 1996 07:06:21 GMT References: <4cdsrc$cpi@yama.mcc.ac.uk> X-Nntp-Posting-Host: atlantis.actrix.gen.nz Lines: 146 In article <4cdsrc$cpi@yama.mcc.ac.uk>, Duncan Entwisle wrote: > I'm thinking of creating my own mouse card to mimic Apples. I just need > to know how IN# and PR# work. I know that they are meant to initialise > the card in the slot by calling Cn00, but.. IN# and PR# don't do anything to the card at all. They just change the I/O hooks (CSW, locations $36 and $37, points to the output routine, and KSW, locations $38 and $39, points to the input routine). If you use BASIC's built-in PR#/IN# commands, the I/O hooks are changed, and the disk operating system is disconnected (DOS and ProDOS use these hooks to retain control over BASIC). DOS 3.3 and ProDOS provide their own PR#/IN# commands which you use via PRINT CHR$(4), which work in the same way, but don't cause the operating system to be disconnected. With either method, the sequence of events is as follows: 1. The program uses PR# or IN# to set the output or input slot. This causes CSW or KSW to be changed to $Cn00, where n is the specifed slot. (If you use PR#0 or IN#0, the monitor's internal COUT1 and KEYIN routines are selected.) 2. When the program next using a PRINT statement which outputs anything (for PR#; INPUT or GET is used for IN#), the current output or input routine is called via the output/input hook. Assuming you had done PR#1, the next character printed will be sent to the routine at location $C100. With most I/O cards, this location is the initialization entry point. The firmware sets itself up, then outputs the character (or inputs a character - see below for details). In the process of doing this, the appropriate I/O vector is modified to point to the start of the actual output or input routine within the $CnXX page. Subsequent output (or input) goes directly to the appropriate routine and doesn't invoke the initialization routine again. 3. If you were using DOS or ProDOS's PR#/IN# commands, the operating system regains control after the firmware has been initialized. The output or input vector is copied elsewhere and DOS/ProDOS's own vector is restored. The I/O card doesn't need to know about this. On to your questions: > (1) How does it know whether called by IN or PR? The firmware checks the I/O vectors (CSW for output, KSW for input) and behaves according to whichever of them is pointing to $Cn00. e.g. if you used PR#1 followed by a PRINT statement, the sequence of events is (ignoring DOS/ProDOS): 1. PR#1: sets $36/$37 to $C100. 2. PRINT: calls $C100. This checks $36/$37 and sees $C100, meaning this is an output call. After initialization, the output vector is updated and the character in A is output. There is no rule about which vector to check first. If the programmer uses PR#1 followed by IN#1 without doing a PRINT first, then the card cannot tell whether this is an input or output call, so it will probably assume one or the other (depending on the order in which the vectors are checked). I think this sort of problem is avoided by using the DOS/ProDOS versions of the command. > (2) Where are the vectors located that my card software would > change for future accesses by input/print. $36/$37 (CSW) is the output vector, $38/$39 (KSW) is the input vector, both in the usual low/high order. You need to know which slot you are in, which can be determined by calling a known RTS instruction in the ROM, and looking back on the stack for the high byte of the return address. You must disable interrupts while doing this. The code goes something like this: PHP SEI JSR $FF58 TSX LDA $0100,X A now contains $Cn, where n is your slot number. This works because the stack pointer is the index into page 1 of the NEXT byte to be pushed onto the stack, so after a JSR/RTS, [$0100+S] contains the high order byte of the return address. This is accessed by transferring the stack pointer to the X register, and indexing into page 1 to get the byte. The reason that interrupts must be disabled is that if an interrupt occurred between the RTS and the LDA instruction, the byte at [$0100+S] would be overwritten. (You would have to PHA before doing any of this, to save the original value in the accumulator, which might be an output byte.) > (3) Would I need to deal with ascii characters, or would print/ > input automatically do the type conversions for me? It depends where the text is coming from. Applesoft BASIC will always output data through CSW with bit 7 set, as printed by the BASIC program, e.g. CR at the end of each line (same format as a DOS 3.3 text file). Bit 7 probably doesn't matter on input. A machine code program could output text with bit 7 in either state, and may decide to output other control characters (e.g. line feeds) though this is not likely. The X/Y registers don't matter. A is defined on entry for output, and must be set on exit for input. Note: this is only one of the I/O methods commonly supported by I/O cards in the Apple II. The other methods are the "Pascal 1.0 firmware interface" (somewhat rare, poorly documented, and hardly ever required) and the "Pascal 1.1 firmware interface" (much more common). The Pascal 1.1 firmware interface involves a series of identification bytes at known points in the ROM space, and a table of entry point offsets to INIT, READ, WRITE and STATUS routines. These are more flexible than the BASIC entry point, allowing non-blocking I/O, for example, by polling the STATUS routine to find out whether input is ready or the card is ready for output. The Apple Mouse supports these entry points, but they don't do anything. It extends the entry point table to provide a lot of additional routines for performing mouse operations such as setting the mode, positioning the mouse, getting the mouse status, handling interrupts, etc. Nearly all 8-bit programs that use the mouse expect this set of routines, so implementing the PR#/IN# "BASIC" interface will not get you very far. > Sorry if this is all basic "in-the-manual-stuff", but there aren't > many 8-bit apples in the UK, and decent documenatation is even rarer. Most of this is covered (rather more tersely) in the Apple IIe Technical Reference, which is not available any more. It is also covered in the 2nd edition of the Apple IIc Technical Reference, which IS available (from Byte Works), and the IIgs Firmware Reference (which isn't). -- David Empson dempson@actrix.gen.nz Snail mail: P.O. Box 27-103, Wellington, New Zealand