; SECTION2: This program changes the user number on an RCP/M system in which 
;  the USER command has been removed (or renamed)
;  (The program is named SECTION@ because my origional section program was
;     a 4k disaster written in C (Moral: never send a high-level language to
;     do a low-level job). The name (Hopefully) won't confilict with other, 
;     similar programs)
;
;  By Nick Holland, 1-8-85, released to Public Domain 8-24.
;       ^
;       | <- Sysop of East Detroit Heath/Zenith BBS (313-772-0417 evenings only)
;
; PURPOSE: I origionaly wrote this program to make my bulletin board more 
;  useable. My board had files for CP/M, MS-DOS, CP/M-86, BASIC, Pascal, etc
;  all jumbled into two winchester partitions. Clearly, it was not very easy 
;  to find those files that interested the caller. At this time, I had renamed 
;  the USER command, so that only user 0 (for the general public) and user 15
;  (for my maintainence) were in use. I had tried a USER program, but the 
;  concept of user levels seemed to escape many of my MS-DOS users, who I tried 
;  to serve, not to mention that it can be hard to remember what is on what 
;  user level. What I needed was a program that was quick and easy to use, but 
;  ALSO would present a menu to the caller, telling him what was where, if 
;  neccessary. This is my solution to the problem. Typing in SECTION alone 
;  gives a menu, telling the user where he is, and where he can go from there.
;  Typing SECTION x, where 'x' is a decimal number, changes to the desired 
;  section number, returning the caller to RCP/M, without a warm boot making
;  the program quick in operation, even on floppy based systems. 
;
; MODIFICATION: I have much reason to believe that many people will want to 
;  change this program to suit their individual needs. I am distributing this
;  primarily to give other sysops ideas, and a possible base to work with. 
;   Ideas for expansion/extension:
;    1) More than 10 sections (0-9): I like the one key response to the menu, so
;       I did not incorporate that many sections into this program. The other
;       reason I did not do this my self is that I use the higher user levels 
;       for files that are uploaded. Each section has it's own upload area, so
;       I can sort out the files easier (is SD.OBJ for MS-DOS or CP/M?)
;    2) Change drive and user number: Perhaps not a bad idea if you suport 
;       machines that are not commonly used with more than one drive 
;       (Commadore, Apple...), since the caller may forget to check other 
;       drives.
;    3) Mneomics for sections instead of numbers: Some people like 'em, I don't
;       not. My twisted mind remembers single digits better than whole "words". 
;       When I use the SYSOP BBS, I have difficulty remembering if the section
;       name is RCP/M or RPCM, COMM or COM, etc. Numbers also make it easier to
;       check all areas for new files (Start at section 0 and work up) Numbers
;       are also better if the user can not type or spell (like me).
;
;
;     OPERATION:
;     ==========
;
;  A>SECTION        {displays menu, prompts for section.}
;  A>SECTION 3      {Changes to section 3, no other display}
;  A>SECTION <garbage> {Displays menu, like with no parameters **}
;          (** If there is a valid section number within the garbage, it is 
;                recognized, and used)
;
;  1/8/84    -N. Holland
;
        
BDOS:   EQU     0005H   ; BDOS call address
CONIN:  EQU     01H     ; BDOS Console in
CONOUT: EQU     02H     ; BDOS Console out
PRINTS: EQU     09H     ; BDOS PRINT STRING
USERNO: EQU     20H     ; BDOS Get/Set user #

LF      EQU     0AH     ; Line Feed
CR      EQU     0DH     ; Carrage Return
MAX     EQU     5       ; MAXIMUM user level

        ORG     100H
        NOP             ; This forces a 00h byte somewere in the program's 
                        ; search for a section number (that is how it quits 
                        ; looking). I know, it should not be necessary, but 
                        ; I am a little paranoid. (Also good for hacked CCP's)
        LXI     H,0080H ; This location has # of bytes entered after prog. name
LOOP1:  MOV     A,M     ; Get byte in command line
        ORA     A       ; Set flags
        JZ      MENU    ; No characters after command
        CALL    CHECK   ; Is it a good section?
        RNZ             ; If good (A <> 0), return to CP/M 
        INX     H       ; point to next byte
        JMP     LOOP1   ; check it...

; If program end up here, either no valid section number character was found, 
;  or there was no command tail. In either event, display the main menu.
; Whatever was on the command line (if anything), was not a valid SECTION #
;   so display menu
;
MENU:   MVI     C,PRINTS        
        LXI     D,DMENU ; point to begining part of menu.
        CALL    BDOS    ; Display menu.

        MVI     C, USERNO ; Tell the caller where he currently is (completing 
        MVI     E, 0FFH ;                                          the menu)
        CALL    BDOS    ; get user number
        ADI     '0'     ; make it an ASCII character
        MVI     C, CONOUT
        MOV     E, A    ; move it to A
        CALL    BDOS    ; Show it to the caller

PROMPT: MVI     C,PRINTS ; Prompt user to enter SECTION number
        LXI     D,DPROMPT
        CALL    BDOS    ; Display prompt message.

        MVI     C,CONIN
        CALL    BDOS    ; Get user's response
        CALL    CHECK   ; See if good SECTION number
        JZ      PROMPT  ; Bad Section number, so re-PROMPT user.

        RET             ; RETURN TO CP/M

; CHECK: Tests the ASCII character in register A. If in the range of '0' to
;   'MAX', changes to that user level, and returns FFh in A. If not valid, 
;   returns 00h in A, and takes no other action. May alter all registers.
;
CHECK:  SUI     '0'     ; If carry here, then A is too small
        JC      ERREXIT ; Exit with error
        CPI     MAX+1   ; If no carry, then A too big
        JNC     ERREXIT 

; The value in A is a valid user number, so change user number, and exit
; showing success.
; To change user levels, there are three ways to do it:
;  1) BDOS call: Lasts untill first warm boot.
;  2) Change byte at 0004h (drive/user): Takes effect only after Warm Boot
;  3) Do both of the above: Makes change last, but eliminates the wait for the 
;      Warm Boot. That is what I do in this program

        MOV     B,A     ; hide desired user level in B.
        LDA     0004H   ; Get drive/user byte
        ANI     0FH     ; Strip current user #, leave drive number.
        MOV     C,A     ; stash drive # in C
        MOV     A,B     ; restore user # (in form 0000uuuu)
        RLC             ; (000uuuu0)
        RLC             ; (00uuuu00)
        RLC             ; (0uuuu000)
        RLC             ; (uuuu0000): the desired position
        ADD     C       ; (uuuudddd): Re-created drive/user byte
        MVI     C,USERNO 
        MOV     E,B     ; Get the user number again
        CALL    BDOS    ; change user # through BDOS call also,
        ORI     0FFH    ; and return OK code
        RET
ERREXIT: XRA    A       ; Set A=0, and set zero flag.
        RET

; Text for menus, prompts: You will almost certainly wish to change this.

DMENU:  DB CR, LF, LF
        DB '         Available Sections:', CR, LF, LF
        DB '   0) Bulletin Board, General Interest', CR, LF
        DB '   1) CP/M-80 related files', CR, LF
        DB '   2) CP/M-86 files', CR, LF
        DB '   3) Generic MS-DOS files', CR, LF
        DB '   4) IBM & compatable files', CR, LF
        DB '   5) General High-level Language stuff', CR, LF, LF ; skip line
        DB ' Currently in Section $'

DPROMPT:
        DB CR, LF, LF, LF, ' Enter desired Section Number (0 - 5) ->$'

 
        END

                                                                 