Wednesday, August 30, 2017

Super Serial Makes a Personal Discovery

   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         *
*                  *
*  More at       *
          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
          JSR HOME       ; Clear screen, and top left start
          LDY #$00

************** Prints Message on top of screen
          JSR COUT
          CPY #$19

************** Init routine start at slot one and MSB C1
          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
          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
          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
          LDX #$00       ; Init X
          LDA NOTFOUND,X ; Print not found Label
          JSR COUT
          CPX #$0D
          BNE :PR
          JMP $3D0       ; Back to Basic

************** When an SSC is found
          LDX #$00       ; Init X
          LDA FOUNDLABEL,X ; Print found label
          JSR COUT
          CPX #$0D
          BNE :PR
          LDA SLOT
          JSR PRBYTE     ; Print slot num to screen
          LDA SLOT       ; Load SLOT into A
          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