This seems like the next possible task for such a device. I've kept a yellow post-it note under the monitor with a listing of what card resides in which slot and have often lost it. Having to then remove the monitor to retake inventory of the system. This seemed like a good time for the next evolution of code, definitely not as complicated as the IRQ issue, but requiring some thought, none the less.
I have a copy of Apples SSC manual, both versions of the manual which i refer to as the crappy consumer grade and the deluxe engineering version. They both discuss card identification by way of four bytes that will appear in predictable locations of memory. This further matches up with the Apple IIe technical reference manual on page 278; in short....
$Cs05 = 38
$Cs07 = 18
$Cs0B = 01
$Cs0C = 31 Where s = the slot number
I figured there must be code out there already, but I wanted to take a crack at this without influence. So I though to myself all I need is a process which starts at slot 1 and tries to read 38 from $C105 if it does, then it tries to read 18 from $C107. If that works try to read 01 from $C10B and finally 31 from $C10C. Should any of the expected values not come back during this test at any time go to the next slot and start this test all over, till you run out of slots, then give up. If you do make it through all four numbers, well then, you've found your SSC card!
As I started thinking about this I realized that there are 7 slots to test with four cycles each, that's a large volume of assembly code for slot detection. Actually 28 possible iterations. After getting one full cycle working in this longhand method I constructed a more efficient design. Quite clever actually.
In the INIT portion the value SLOT is set to 01 and the MSB is set to C1 for the first slot. The MSB need only be incremented along with the slot value to move to the next slot to test. So the next increment would have the SLOT at 02 and the MSB at C2. and so on until 07 and C7 as the last one.
At the bottom of the program is the storage of 8 bytes of data, its relevance is shown below
INDEX(X) 0 1 2 3
---------------------------------
SSCID 38 18 01 31 Expected return data from memory address
LSBVAL 05 07 0B 0C Least significant byte of that address
Now we see that labels LSB and MSB sit next to each other in the zeropage.
LSB = $08 ; Bottom half of memory address
MSB = $09 ; Top half of memory address
So with a small routine using the same X as an index to pull from SCCID as well as LSBVAL I can get both the answer im looking for as well as the other half of the memory address I need to pull that answer.
MSB = C1 already stored in $09 from INIT
LSB = 05 Pulled from LSBVAL index 0, stored in $08
SSCID = 38 Expected answer SSCID index 0
LDY #$00 ; no offset
LDA (LSB),Y = LDA (C1&05),0 = LDA $C105
The value coming back into a is stored in TESTBYTE so that SSCID loaded into a can be compared against TESTBYTE to see if they are the same value. If they are, in this case 38, ONLY X IS INCREMENTED and the cycle is repeated, this time...
MSB = C1 already stored in $09
LSB = 07 Pulled from LSBVAL index 1, stored in $08
SSCID = 18 Expected answer SSCID index 1
LDY #$00 ; no offset
LDA (LSB),Y = LDA (C1&07),0 = LDA $C107
Again, if X should make it to the 4th interval, then the card is found and the program will jump out to FOUND. If there is no match X will reset back to zero and the MSB and SLOT will be incremented, this process starts all over.
If the card is found, more code below displays the slot number to the screen and a simple indication that it has been found. also, 4 ROL multiply the slot number by 0x10 (dec16) and store it back into slot. All of the previously mentioned connections into to the ACIA are listed here without any offset onto of the program as shown
DATAREG = $C088 ; Needs slot added when called
STATUSREG = $C089 ; Needs slot added when called
COMMANDREG = $C08A ; Needs slot added when called
CONTROLREG = $C08B ; Needs slot added when called
To access them in a program, The offset in SLOT would have to be loaded into Y and then used as an offset in the call. Considering sending a byte to the ACIA as data:
LDY SLOT
STA DATAREG,Y
So was all of this worth it from a memory perspective? In consideration that almost half of the example program below is just printing some sort of output to the screen in the spirit of view-ability the total number of bytes ACTUALLY NEEDED to run this program, and assign the SLOT and move onto the next item is just 77 Bytes. By comparison, simply storing the text "Please specify the slot of your SSC card: " to memory takes up 42 bytes all by itself, the code to print it to the screen takes at least 12 bytes, now were at 54 bytes, then the KEYIN, strobe, associated validation checking of the human input, math to do all of the same conversion and assignment to the SLOT, testing and deployment. Also, what if the wrong number was given, is there exception handling? No doubt it would be way over 77 bytes for a program that has a manual entry no auto discovery and the propensity for human error.
Its worth noting that in either case, if such a program were being constructed that every last byte had to be accounted for, there is no reason why all of this detection code couldn't simply be copied over by the main program after the fact, having stored the correct location in SLOT, none of the detection code has any further practical use in memory once the task is completed. The last action in FOUND could tell PRODOS to load and execute a MAIN.bin application who's ORG = $2000 effectively copying directly over all of this on load.
Click here for PRODOS DSK file including Merlin source and executable
****************************************************
* **** COMMODORE 64 BASIC V2 **** *
* 64K RAM SYSTEM 38911 BASIC BYTES FREE *
* READY. *
* LOAD"SSCFINDER",8,1 *
****************************************************
* ---Auto detecting SSC card code--- *
* Written and compiled natively on Merlin 8 *
* No Emulators used...... TASM style formatting *
* Uses 4 known bytes of data that the SSC will *
* return if the offset for the memory address *
* matches the slot the SSC is in. Those SSCID's *
* & corresponding LSB's are loaded together in *
* the same loop iteration to keep the code very *
* small, only the MSB increments to change the *
* card. LSB and MSB are used as (LSB),msb to call *
* the individual addresses to read. *
* Once found SLOT is multiplied by 0x10 and then *
* Re-stored in SLOT for use as an offset value *
* for DATAREG, COMMAND and CONTROL *
* LDY SLOT *
* STA DATAREG,Y *
* Free for all to use - Jordan Rubin 2017 *
* http://technocoma.blogspot.com *
* More at www.youtube.com/c/JordanRubin6502 *
****************************************************
ORG $2000 ; HIRES area unused and safe
COUT = $FDED ; Like C64 $FFD2
PRBYTE = $FDDA ; HEXPRINT
TESTBYTE = $0A ; test byte area
LSB = $08 ; Bottom half of memory address
MSB = $09 ; Top half of memory address
HOME = $FC58 ; CLS & Cursor to top POS
SLOT = $07 ; Testing and storage of slot
DATAREG = $C088 ; Needs slot added when called
STATUSREG = $C089 ; Needs slot added when called
COMMANDREG = $C08A ; Needs slot added when called
CONTROLREG = $C08B ; Needs slot added when called
************** Start of program
START
JSR HOME ; Clear screen, and top left start
LDY #$00
************** Prints Message on top of screen
PRINTMESSAGE
LDA MESSAGELABEL,Y
JSR COUT
INY
CPY #$19
BNE PRINTMESSAGE
************** Init routine start at slot one and MSB C1
INIT
LDA #$01 ; Starting slot is 1
STA SLOT ; Store it
LDA #$C1 ; Starting MSB is C1
STA MSB ; Store it
LDX #$00 ; Init X
************** The main testing routine
ROUTINE
LDA LSBVAL,X ; LSB comes from data at at LSBVAL
STA LSB ; For each x - 05, 07, 0B, 0C
LDY #$00 ; We dont want an offset for this action
LDA (LSB),Y ; Cs05 content load, indirect index
STA TESTBYTE ; Store return to temp memory area
LDA SSCID,X ; Load expected SSCID value for x to a
CMP TESTBYTE ; Compare recieved value to a
BNE NEXTSLOT ; Not equal? Not an SSC, try next slot
INX ; Equal? X++
CPX #$03 ; All four bytes passed?
BEQ FOUND ; We have found the SSC!!!
JSR ROUTINE ; Not four yet, repeat routine....
************** Action to proceed to next slot to test
NEXTSLOT
LDX SLOT ; Load current slot into X
INX ; Increment it
CPX #$07 ; Passed the last slot to test
BEQ GIVEUP ; Give up, no SSC found....
STX SLOT ; Store new current slot value
LDX MSB ; load current MSB into X
INX ; Increment it
STX MSB ; Store it
LDX #$00 ; Init X
JSR ROUTINE ; Try Routine again
************** What to do when no SSC is found
GIVEUP
LDX #$00 ; Init X
:PR
LDA NOTFOUND,X ; Print not found Label
JSR COUT
INX
CPX #$0D
BNE :PR
JMP $3D0 ; Back to Basic
************** When an SSC is found
FOUND
LDX #$00 ; Init X
:PR
LDA FOUNDLABEL,X ; Print found label
JSR COUT
INX
CPX #$0D
BNE :PR
LDA SLOT
JSR PRBYTE ; Print slot num to screen
LDA SLOT ; Load SLOT into A
ROL
ROL
ROL
ROL ; Multiply by 0x10
STA SLOT ; Store slot into A, official slot value!
JMP $3D0 ; Back to Basic
MESSAGELABEL ASC "Checking for SSC Card... "
FOUNDLABEL ASC "Found in --> "
NOTFOUND ASC "Was not found"
SSCID HEX 38,18,01,31 ; 4 identifying bytes for SSC
LSBVAL HEX 05,07,0B,0C ; LSB for identifying memory areas
No comments:
Post a Comment