; LUCKY.Z80 Version 1.3 By G.F.Reding 09/13/87 ;-------------------------------------------------------------- ; ; 09/13/87 Found a bug in GFDAT3 area, so I remarked out 2 ; v1.3 lines for now. Would not accept date of 870912 ; for the file-save date. Minor other changes in ; the same area. ; ; 06/08/87 Bug fix, changed SET 1,L to SET 0,L in the DVHD ; v1.2 routine. ; ; 04/16/87 Release version. Corrects a bug which was found ; v1.1 in (unreleased) version 1.0. ; ;-------------------------------------------------------------- ; ; A (hopefully) universal lottery number generator/checker that ; will create lottery numbers for fun and frollic. The numbers ; picked by this program may be displayed on the console, your ; printer, or both, and optionally, may be saved as a disk file ; with a name related to the draw date. This latter capability ; enables the program at a later date to be able to search for ; any "winning" combinations which if found may be displayed on ; the console, printer, or both. Any of the "number" files that ; may have been saved to disk by the program cannot be directly ; viewed by "TYPE"ing them as they are completely binary. This ; type of storage affords disk space conservation and provides ; some privacy security (although not guaranteed), such that an ; ordinary person cannot just sit down and view your numbers or ; easily know how many combinations are there. ; ; The binary numbers, which the program creates or reads from a ; file (when checking for "winners"), are placed into memory in ; their binary form just above the end of the program code. The ; binary form also allows many more number combinations to be ; created compared to a similar program written in basic, e.g., ; picking 2-thousand 6-number combinations will only use 12,000 ; bytes of memory. Saved to disk, the file size would be about ; 94 (128-byte) records. Speed of creation, or checking for any ; "winners", is optimized by usage of this binary format, e.g., ; creation of 2000 combinations took approximately 1.8 minutes ; and checking for 6-number "winners" took only about 0.5 sec. ; where 33 winners were found in the test run. Time, for lesser ; or greater quantities, will be respectively effected. Output ; of the combinations created to your console or printer are in ; a format which is dependent upon the quantity-of-numbers-per- ; combination and your console-screen-width so that the program ; may be used on Osborne's 52 character screen or any other odd ; width consoles. The format sent to the printer is the same as ; the console. For example, with 6-number combinations and a 80 ; character screen width the output is 4 combinations per line. ; Sorry, pagination for console or printer is not provided. ; ; PROGRAM USAGE ; ; To create numbers, simply input the quantity of combinations ; that you want and hit return. If a zero and return, or return ; only, is entered at the prompt for the quantity, you will be ; returned to the main menu. This quantity is only limited by ; the memory of your system (set by the maximum value specified ; at the beginning of the program code) and as is mentioned in ; this documentation. If the quantity entered is valid you are ; then prompted to hit any key to start the generation of your ; number combinations. The time it will take depends upon the ; quantity. You will next be prompted for the display location ; which will be your console, printer (LST device), or both. If ; the test mode is valid, an additional option to SKIP display ; and save to file is available. You are prompted for the date ; of the drawing in the format of year, month, day (two digits ; each) which becomes the file name, the default extent is LOT. ; For example: 870331 for the draw date saves the combinations ; to 87/03/31.LOT file. ; ; To check for winners, you are promted for the draw date which ; (or whatever 6 digits) that was used when you saved the data. ; You are prompted for the winning numbers which are entered as ; one-or-two digits followed by a return after each until they ; are all entered. You may backspace to correct the immediate ; number. If a return only is entered while it is waiting for ; the one or two digits of a number you will be returned to the ; main menu. You will also be prompted for a "bonus number" as ; one or two digits. If no bonus number is used, just enter a ; return only. No checking for duplication or range is done on ; the winning numbers you entered, as they would be unique and ; within the range of the combinations. If you made an error, ; just do it again. The winning numbers you entered do not have ; to be in numerical sequence as they are sorted order prior to ; checking the combinations in memory. Display of winners will ; be made on the console, printer, or both as desired. It will ; show the number of matches in each combination. The MINIMUM ; number of matching numbers required for a winning combination ; is dependent upon the value which you set at the beginning of ; the program code. ; ; Redisplay of memory is useful if you created combinations and ; displayed them on the console only, then decide that you want ; a printed copy. It is also used to redisplay combinations in ; the draw-date-file after you check for winners. ; ; LIMITATIONS ; ; Limitations and constraints on usage of this program are such ; that it must be used on a computer with a Z80 microprocessor ; as Z80 code is utilized frequently throughout the program but ; most importantly in the random number generator routine (from ; Microsystems magazine 10/83) which uses the refresh register. ; M80 and L80, or ZASM or similar z80 assembler is required for ; assembly, else you may have to write some equivilent macros. ; ; This program may not be sold in whole or part for any type of ; personal gain, nor may it be included in any software package ; which is sold in whole or part for any type of personal gain. ; No modifications may be made to any portions of this program, ; with exceptions to z80 code (personal assembly requirements) ; and those specified variables before the start of the program ; code. Users of this program assume any and all risks related ; to its usage. No guarantees of any type are provided. Other ; limitations may also exist. ; ; The program source code is placed into the "Public Domain" to ; enable the program to be used for most any lottery or similar ; game on most any machine. Request for exception to any of the ; limitations, comments, bugs, suggestions, or gratuity (if the ; program actually picks a major "winner" for you and if you so ; desire to provide same), etc should be directed to the author ; of this program. This documentation/notice should also remain ; with the program and/or its source code. By using, retaining, ; or possessing this program, source code, and/or documentation ; /notice you are in agreement with the author. ; ; George F. Reding (Author) ; P.O. Box 86386 ; North Vancouver, B.C. ; CANADA V7L 4K6 ; - - - - - - - - - - - - - - ; CompuServe user # 72436,45 ; ; ; Note: If a COM file is found with this documentation and the ; source code, it is configured for the British Columbia 6/49 ; Lottery game in which the user plays six number combinations ; where the unique numbers are in the range of 1 through 49. On ; the draw date 6 unique numbers plus a bonus number are drawn. ; To win the user must match 3, 4, 5, or 6 of those numbers, or ; match 5 of the main numbers plus the bonus. ; ;-------------------------------------------------------------- ; ; Thanks to David Bowerman who beta tested this program and for ; making some modfications/improvements to the program code and ; for making other suggestions. ; ;-------------------------------------------------------------- ; ; .Z80 ; Required for M80 and similar ; ASEG ; Absolute file ; TRUE EQU -1 ; For conditional assembly FALSE EQU 0 ; VERS EQU 13 ; Version number VERM EQU 09 ; Version month VERD EQU 13 ; Version day VERY EQU 87 ; Version year ; ; System and program equates - may be user modified. ; BDOS EQU 5 FCB EQU 5CH ; Fcb NR EQU 32 ; Next record field (rel) TPA EQU 100H ; Normal program start addr ; ; Bdos functions - no modifications. ; COUTF EQU 02 ; Con out LOUTF EQU 05 ; Lst out DCONF EQU 06 ; Direct con i/o CSTAF EQU 11 ; Con status OPENF EQU 15 ; Open file CLOSEF EQU 16 ; Close file DELTF EQU 19 ; Delete file READF EQU 20 ; Read record WRITEF EQU 21 ; Write record MAKEF EQU 22 ; Make file GTDSKF EQU 25 ; Get current disk SETDTF EQU 26 ; Set Disk Transfer Address ; ; Ascii equates - no modifications. ; CR EQU 0DH ; Carriage return LF EQU 0AH ; Linefeed BEL EQU 07H ; Bell BS EQU 08H ; Backspace TAB EQU 09H ; Tab SPC EQU 20H ; Space SLASH EQU 2FH ; Slash DEL EQU 7FH ; Delete char ; ; Program equates - may be user modified. ; TSTMODE EQU FALSE ; Normally is false ; HIGHNO EQU 49 ; 1 thru HIGHNO avail (max 99) DIGITS EQU 6 ; Digits per ticket/combo MXCOMB EQU 4000 ; Max # of combos (see notes) ; WINBNS EQU 5 ; Min match enables bonus check WINMIN EQU 3 ; Min match for a winner WINPLS EQU 02BH ; Bonus flag - don't modify ; ; Misc equate - may be user modified. ; WIDTH EQU 80 ; Con/lst width ; Set to <= your printer width ; ;-------------------------------------------------------------- ; ; .PHEX ; Output HEX file instead of binary ; .XLINK ; Suppress linkage info ; ORG TPA ; START: JP STRT1 ; Jump over credits ; TITLM: DEFB CR,LF,TAB,TAB ; Program name/credits DEFB 'LUCKY v ' DEFB VERS/10+'0','.',VERS MOD 10+'0',' ' DEFB VERM/10+'0',VERM MOD 10+'0','/' DEFB VERD/10+'0',VERD MOD 10+'0','/' DEFB VERY/10+'0',VERY MOD 10+'0' DEFB ' (c)G.F.Reding',CR,LF,0 DEFB 1AH ; Eof ; STRT1: LD (OLDSTK),SP ; Save old stack LD SP,STACK ; Use new stack ; XOR A ; Just to retain old value LD (MSTRT),A LD C,GTDSKF ; Return current disk CALL BDOS INC A ; Convert to 1 to 16 LD (DEFDSK),A ; Get default disk and save ; MENU: LD HL,TITLM ; Program name/credits CALL PRNTL LD HL,MNMENU ; Main menu msg CALL PRNTL LD A,1 ; Max 1 digit CALL INPNUM ; Get numerical input CALL PCRLF ; Cr/lf CP 0 ; If 0 JP Z,EXIT ; Then exit CP 1 ; If 1 JP Z,CREATE ; Then create new CP 2 ; If 2 JP Z,WINCK ; Then check for winners CP 3 ; If 3 JP Z,REDISP ; Then redisplay memory JP MENU ; Go to menu ; ;-------------------------------------------------------------- ; ; Create new numbers ; CREATE: LD HL,TIKETM ; Number of tickets msg CALL PRNTL LD A,4 ; Max 4 digits CALL INPNUM ; Get numerical input CALL PCRLF ; Cr/lf LD A,L ; Now test OR H ; For zero JP Z,MENU ; Return to to menu if 0 ; EX DE,HL ; Quantity desired to de LD HL,MXCOMB ; Get maximum allowable OR A ; Clear flags for subtr SBC HL,DE JP M,MENU ; If too many back to menu ; LD (TKN),DE ; Else store # of tickets LD (TKC),DE ; In counter too ; LD HL,STARTM ; Hit a key to start msg CALL PRNTL ; CALL RNDINI ; Init random mask & valdif CREAT1: CALL CONDIN ; Get console input JP Z,CREAT1 ; Loop if nothing CALL PCRLF ; Cr/lf CALL NEWNO ; Make the new tickets CALL SELDV0 ; Select output device ; IF TSTMODE CP 4 ; Check for disk save only JR Z,CREAT0 ; If 4, then do save only ENDIF ; CALL PCRLF ; Cr/lf CALL PCRLF2 ; Cr/lf CALL DISPLY ; Display on con/lst CALL PCRLF2 ; Cr/lf ; CREAT0: LD HL,SAVITM ; Save it msg CALL PRNTL CREAT2: CALL CONDIN ; Get console input JP Z,CREAT2 ; Loop if nothing CALL UPCASE ; Make upper case CP 'N' ; If n JP Z,CREAT3 ; Then no save CP 'Y' ; If y JP Z,CREAT4 CP CR ; Or cr JR NZ,CREAT2 ; Else try again ; Fall through on CR CREAT4: LD HL,SAIDYM ; Yes msg CALL PRNTL CALL PCRLF ; Cr/lf CALL GFDATE ; Get file date (name) JP C,MENU ; Go to menu if aborted CALL WTFIL ; Else save combinations JP MENU ; Go to menu ; CREAT3: LD HL,SAIDNM ; No msg CALL PRNTL JP MENU ; Go to menu ; ;-------------------------------------------------------------- ; ; Check for winning combinations ; ; Get date, read file, compute number of combinations ; WINCK: LD HL,MSTRT ; Get mem start addr LD (MADDR),HL ; Store next mem addr CALL PCRLF ; Cr/lf CALL GFDATE ; Get file date (name) JP C,MENU ; Go to menu if aborted ; CALL RDFIL ; Read file data to memory JP C,MENU ; If error go to menu ; LD HL,(MADDR) ; Get next mem addr LD DE,MSTRT ; Get mem start addr OR A ; Clear flags for subtr SBC HL,DE JP Z,MENU ; If zero go to menu ; LD DE,DIGITS ; Length of combos CALL DIVHD ; Div mem bytes (hl) by length (de) LD (MEMCNT),HL ; Store number of mem combos CALL PCRLF ; Cr/lf ; ; Get the winning numbers that we want to check for ; LD HL,WINR1M ; Winning numbers msg CALL PRNTL CALL WINNOS ; Get winning numbers JP C,MENU ; If aborted, go to menu ; CALL SORT ; Sort the winning numbers LD HL,WINR2M ; Bonus number msg CALL PRNTL LD DE,BONUSN ; Point to bonus number XOR A ; Zero LD (DE),A ; The bonus number LD B,1 ; Get 1 number CALL WINNO1 ; Get bonus number ; Ignore cy in case no bonus CALL SELDEV ; Select output device CALL PCRLF ; Cr/lf CALL PCRLF2 ; Cr/lf ; ; The following is for neatness of display ; XOR A ; Zero LD (WINFLG),A ; Winners flag LD HL,WINR1M ; Winning numbers msg CALL PRNTL2 LD HL,SRTNOS ; Point to sorted winners CALL WINDS4 PUSH HL ; Save last addr LD HL,WINR2M ; Bonus number msg CALL PRNTL2 LD A,SPC ; Space CALL PCHAR2 POP HL ; Get back last addr LD A,(HL) ; Get bonus number CALL PRDEC CALL PCRLF2 ; Cr/lf CALL PCRLF2 ; Cr/lf ; ; This is the "search and display" area ; LD HL,MSTRT ; Point to mem start addr WINCK2: LD BC,(MEMCNT) ; Get number of mem combos LD A,B ; Now test OR C ; For zero (end) JR Z,WINCK5 ; If 0, see if any won ; PUSH HL ; Save mem addr PUSH BC ; Save number of mem combos CALL WINMEM ; Do mem check for winners LD A,(MATCNT) ; Get match count/bonus flag CP WINPLS ; See if bonus flag JR Z,WINCK3 ; If yes display it CP WINMIN ; Else see if minimum matches JP C,WINCK4 ; If not, check next mem combo ; WINCK3: CALL WINDSP ; Display mem combo & matches LD A,0FFH ; Set LD (WINFLG),A ; Winners flag ; WINCK4: POP BC ; Restore number of mem combos DEC BC ; One less LD (MEMCNT),BC ; Store remaining mem combos POP HL ; Restore last start addr LD DE,DIGITS ; Length of a combo ADD HL,DE ; Add for next combo start addr JP WINCK2 ; And try to do next ; WINCK5: LD A,(WINFLG) ; Winners flag OR A ; If not zero JP NZ,MENU ; Then go to menu LD HL,WINR5M ; No winners msg CALL PRNTL2 JP MENU ; ;-------------------------------------------------------------- ; ; Redisplay the combinations in memory. For use after creation ; or after check for winners to display the memory combinations ; to console or printer in case you had forgotten to print them ; at time of creation, or misplaced the listing, etc. ; REDISP: LD HL,MSTRT ; Point to mem start XOR A ; Zero CP (HL) ; If mem <> 0, something there JP NZ,REDIS1 ; So continue ; LD HL,REDISM ; Else, memory is empty msg CALL PRNTL JP MENU ; Go back to menu ; REDIS1: CALL SELDEV ; Select output device CALL PCRLF ; Cr/lf CALL PCRLF2 ; Cr/lf CALL DISPLY ; Display on con/lst CALL PCRLF2 ; Cr/lf JP MENU ; Go to menu ; ;-------------------------------------------------------------- ; ; Exit from the program ; EXIT: LD SP,(OLDSTK) ; Get original stack RET ; ;-------------------------------------------------------------- ; ; Create desired number of tickets in binary. Store in memory. ; NEWNO: LD HL,MSTRT ; Point to memory start LD (MADDR),HL ; Store in memory storage addr CALL MEMINI ; Initialize memory to zeros ; NEWNO1: LD HL,(TKC) ; Get ticket count LD A,L ; Test OR H ; For zero RET Z ; If 0, we are done making DEC HL ; Show one less LD (TKC),HL ; Store new ticket count ; NEWNO2: CALL RNDNOS ; Create unsorted random numbers CALL SORT ; Sort combo in assending order ; ; Check for a duplicate of the new number in memory. ; LD HL,MSTRT ; Point to memory start NEWNO3: XOR A ; Zero CP (HL) ; If memory byte match JR Z,NEWNO4 ; Then at start, so store combo ; ; If it not 0, then it must be a number combination in memory ; PUSH HL ; Save memory addr LD DE,SRTNOS ; Point to sorted combo buffer LD B,DIGITS ; Length CALL MEMCMP ; See if we match it in memory POP HL ; Restore memory addr JR C,NEWNO2 ; If cy set (matched) remake it ; ; Else point to next mem start and go check memory again ; LD DE,DIGITS ; Length of combos ADD HL,DE ; Add to mem addr for next JP NEWNO3 ; Go check memory again ; ; Store new combination in mem, set next addr, try to do more ; NEWNO4: LD DE,(MADDR) ; Get memory storage addr LD HL,SRTNOS ; Point to sorted combo buffer LD BC,DIGITS ; Length LDIR ; Store it LD (MADDR),DE ; Save next mem storage addr JP NEWNO1 ; Try to do more ; ;-------------------------------------------------------------- ; ; Sort the random selection picked. We do this a bit backwards ; or you could say somewhat uniquely. It's the shortest amount ; of code I could work out for sorting the individual digits. ; SORT: LD HL,SRTNOS ; Destination sorted combo buffer LD DE,DIGITS-1 ; Offset to its end ADD HL,DE EX DE,HL ; Dest buffer end addr now in de ; LD B,HIGHNO ; Start with high # (a counter) SLOOK: PUSH BC ; Save number (counter) LD A,B ; Will looking for then number LD HL,TMPNOS ; Source unsorted combo buffer LD B,DIGITS ; Bytes in source to check SLKAGN: CP (HL) ; Look at source memory JR Z,SRTMAT ; If match, store, try next one INC HL ; No store, pnt to next source DJNZ SLKAGN ; Go check if loop <> 0 JP SRTNXT ; Else do a new digit ; SRTMAT: LD (DE),A ; Got match, store it DEC DE ; Back up to next destination ; SRTNXT: POP BC ; Restore number (counter) DJNZ SLOOK ; Decrement it, loop if <> 0 RET ; ;-------------------------------------------------------------- ; ; Compare new combination with one of the memory combinations. ; Enter with b=length, de=source string addr, hl=memory addr. ; Returns cy set if we match all, else clear cy if any do not. ; MEMCMP: XOR A ; Clear flags MEMCML: LD A,(DE) ; Length=bc, src=de, mem=hl CP (HL) ; Check memory byte for match JP NZ,MEMCM2 ; If no match, done here INC DE ; Bump to next source byte INC HL ; Bump to next memory byte DJNZ MEMCML ; Loop if more to do SCF ; All matched, so set carry RET ; MEMCM2: SCF ; No match of at least one CCF ; So clear the carry RET ; ;-------------------------------------------------------------- ; ; On entry reg A has max number of digits that we want to get. ; Input digit(s) from keyboard. Wait for return at end. May ; use BS or DEL key to back up. If ctrl-c is used during input ; return with with A=0 and hl=0, else return with low word of ; digits in reg A and word of digits in hl. ; INPNUM: PUSH DE ; Save de PUSH BC ; And bc LD HL,NUMBUF ; Ascii number buffer LD B,A ; Max allowable digits to b PUSH HL ; Save buffer start addr PUSH BC ; Save count INC B ; Count plus nul terminator ; INPNIN: LD (HL),0 ; Initialize to zero INC HL DJNZ INPNIN ; Loop if more to do ; POP BC ; Restore count POP HL ; Buffer start addr XOR A ; Zero LD (NUMCNT),A ; Digits typed count ; INPNLP: CALL CONDIN ; Get con status/input JP Z,INPNLP CP 3 ; Ctrl-c JR Z,INPABT ; Will return with a=0 ; CP CR ; Cr or lf JR Z,INPNCR CP LF JR Z,INPNCR ; Is end of line or abort ; CP BS ; Backspace or delete JR Z,INPNBS CP DEL JR Z,INPNBS ; Will do backspace ; CP '0' ; If < '0' or > '9' JR C,INPNLP CP '9'+1 JR NC,INPNLP ; Then loop ; LD C,A ; Else save in c LD A,(NUMCNT) ; Get digits typed count CP B ; If typed the limit JR Z,INPNLP ; Then just loop LD A,C ; Get char typed back CALL PCHAR ; Display it LD (HL),A ; Store in buffer INC HL ; Increment pointer LD A,(NUMCNT) ; Get digits typed count INC A ; Increment it LD (NUMCNT),A ; Store it JP INPNLP ; And loop ; INPABT: LD HL,0 ; And set hl to 0 JP INPNC2 ; Skip eval ; INPNCR: LD A,(NUMCNT) ; Get digits typed count ; LD DE,NUMBUF ; Ascii number buffer CALL EVAL10 ; Convert to decimal # in hl INPNC2: LD A,L ; Get low of evaluated number POP BC ; Restore bc POP DE ; And de RET ; And return with it in a ; INPNBS: LD A,(NUMCNT) ; Get digits typed count OR A ; If zero JR Z,INPNLP ; Then loop DEC A ; Decrement counter LD (NUMCNT),A ; Store it DEC HL ; Decrement pointer LD (HL),0 ; Null it out PUSH HL ; Save pointer LD HL,BSMSG ; Erase string CALL PRNTL POP HL ; Restore pointer JP INPNLP ; And loop ; ;-------------------------------------------------------------- ; ; Convert decimal ASCII number at DE to HL. Terminate number ; with a CR, comma, or a NUL. Spaces are ignored. ; EVAL10: PUSH DE ; Save regs PUSH BC ; LD HL,0 ; Init counters to 0 LD BC,0 ; EVL10: LD A,(DE) ; Get ascii number OR A ; If a null JR Z,EVD10 CP CR ; Or a cr JP Z,EVD10 CP ',' ; Or a comma JR Z,EVD10 ; Then we are all done CP ' ' ; If a space JR Z,EVS10 ; Then ignore it SUB '0' ; Make ascii digit binary JR C,EVER10 ; If < 0 CP 10 ; Or > 9 JR NC,EVER10 ; Then return LD B,H ; Put h,l in b,c LD C,L ; ADD HL,HL ; *2 ADD HL,HL ; *4 ADD HL,BC ; *5 ADD HL,HL ; *10 ; LD C,A ; Put current value in bc LD B,0 ADD HL,BC ; Add it into total ; EVS10: INC DE ; Increment pointer JP EVL10 ; And loop until done ; EVER10: LD HL,0 ; Invalid chars return hl=0 EVD10: POP BC ; Restore regs POP DE RET ; ;-------------------------------------------------------------- ; ; Select desired output device. 1=con 2=lst 3=both. ; 4 = skip display output (create only) ; SELDV0: LD HL,SELD0M CALL PRNTL LD A,5 JP SELDV1 ; SELDEV: LD HL,SELD1M ; Output device msg CALL PRNTL LD A,4 SELDV1: LD (SELDV3+1),A ; set max number SELDV2: LD HL,SELD2M ; Enter number msg CALL PRNTL LD A,1 ; Max 1 digit CALL INPNUM ; Get numerical input OR A ; If zero JR Z,SELDV2 ; Then try again SELDV3: CP 4 ; If > 3 or 4 JR NC,SELDV2 ; Then try again LD (DEVFLG),A ; Else store new RET ; ;-------------------------------------------------------------- ; ; Display picked numbers in memory on con or lst ; DISPLY: LD HL,MSTRT ; Point to mem start LD A,WIDTH ; Con/lst width LD (COLUMN),A ; Init column cnt ; DISPL1: XOR A ; Zero CP (HL) ; If mem byte zero RET Z ; Then we are done here ; ; If not zero, must be combinations in memory ; So print a combination on the line ; LD B,DIGITS ; Length DISPL2: LD A,SPC ; Space CALL PCHAR2 ; Preceeds each number LD A,(HL) ; Get mem char CALL PRDEC ; Go display it LD A,(COLUMN) ; Get column cnt SUB 3 ; -3 per number, eg _## LD (COLUMN),A ; Save new INC HL ; Point to next addr DJNZ DISPL2 ; Loop if more to do ; ; With delimiter (vertical bar & spaces) between combinations ; LD A,SPC ; Space CALL PCHAR2 LD A,(COLUMN) ; Get column # DEC A ; Less 1 LD (COLUMN),A ; Save new ; ; If next byte is end, print cr/lf, else just do next ; LD A,(COLUMN) ; Get current column DEC A ; Less 1 for a delimiter LD C,(DIGITS*3) ; Length SUB C ; Room for another combo JP C,DISPL3 ; Skip over if no room on line JP Z,DISPL3 ; XOR A ; Zero CP (HL) ; See if next memory is end JP Z,PCRLF2 ; If end then return via cr/lf ; LD A,'|' ; Delimiter CALL PCHAR2 LD A,(COLUMN) ; Get column # DEC A ; Less 1 LD (COLUMN),A ; Put back JP DISPL1 ; Go do more DISPL3: CALL PCRLF2 ; Cr/lf LD A,WIDTH ; Reset column cnt LD (COLUMN),A JP DISPL1 ; Try to do more ; ;-------------------------------------------------------------- ; ; Print cr/lf preserving all registers. ; PCRLF: PUSH AF ; Save reg LD A,CR ; Cr CALL PCHAR ; Send it LD A,LF ; Lf CALL PCHAR ; Send it POP AF ; Restore reg RET ; ;-------------------------------------------------------------- ; ; Print char in reg a. All registers preserved. ; PCHAR: PUSH AF ; Save reg CALL CONOUT ; Send it POP AF ; Restore reg RET ; ;-------------------------------------------------------------- ; ; Print nul terminated string pointed to by hl. Only hl used. ; All other registers preserved. ; PRNTL: LD A,(HL) ; Get char OR A ; Test for zero RET Z ; Return if 0 CALL CONOUT ; Send it INC HL ; Bump pointer JP PRNTL ; Try again ; ;-------------------------------------------------------------- ; ; Print a cr/lf on con or lst, dependent upon flag ; All regs preserved. ; PCRLF2: PUSH AF ; Save only reg a LD A,CR CALL PCHAR2 ; Other regs saved here LD A,LF CALL PCHAR2 POP AF ; Restore it RET ; ;-------------------------------------------------------------- ; ; Routine to print the char in reg a on con or lst. ; Output dev is binary flag, where 1=con 2=lst 3=both. ; PCHAR2: PUSH BC ; Save regs PUSH AF LD C,A ; Char to c LD A,(DEVFLG) ; Get device flag LD B,A ; Flag to b BIT 0,B LD A,C ; Get char back CALL NZ,CONOUT ; Z set if bit is 1 BIT 1,B CALL NZ,LSTOUT ; Z set if bit is 1 POP AF ; Restore regs POP BC RET ; ;-------------------------------------------------------------- ; ; Print nul terminated string pointed to by hl on con or lst. ; Only hl used. All other registers preserved. ; PRNTL2: LD A,(HL) ; Get char OR A ; Test for zero RET Z ; Return if 0 CALL PCHAR2 ; Send it INC HL ; Bump pointer JP PRNTL2 ; Try again ; ;-------------------------------------------------------------- ; ; Print reg a as decimal characters (1-100) in 2-char field ; on con or lst floating print, where two chars are used. ; PRDEC: PUSH DE ; Save regs PUSH BC PUSH AF LD D,1 ; Turn on lead space flag LD B,10 ; Print tens CALL PRDEC1 ADD A,'0' ; Convert to ascii CALL PCHAR2 ; Print POP AF ; Restore regs POP BC POP DE RET ; ; Print result of divide of A by B w/lead space (int division) ; PRDEC1: LD C,0 ; Init count PRDEC2: SUB B ; Compute count JR C,PRDEC3 INC C ; Incr count JP PRDEC2 PRDEC3: ADD A,B ; Add b back in LD E,A ; Save a LD A,C ; Get count OR A ; See if zero JR NZ,PRDEC4 ; If not, then print it OR D ; Else see if space flag on JR Z,PRDEC4 ; If not, then print it LD A,SPC ; If on, get space CALL PCHAR2 ; Print it LD A,E ; Restore a RET ; PRDEC4: LD D,0 ; Turn off leading space LD A,C ; Get count ADD A,'0' ; Convert to decimal CALL PCHAR2 ; Print it LD A,E ; Restore a RET ; ;-------------------------------------------------------------- ; ; Fill required memory with zeros plus nul terminator. ; MEMINI: LD DE,DIGITS LD HL,(TKN) CALL MULHD ; generate # of bytes to zero LD BC,80H ; make even 128 byte blocks ADD HL,BC LD A,L AND C ; cheap 80H LD C,A LD B,H LD HL,MSTRT ; Point to mem start LD (HL),0 ; Zero the first byte LD DE,MSTRT+1 ; Destination LDIR ; and zero the rest... RET ; ;-------------------------------------------------------------- ; ; Get the winning numbers that were drawn (and bonus number). ; Returns de pointing to last storage addr, carry set if user ; aborted entries with no entry or with ctrl c or esc. ; WINNOS: LD B,DIGITS ; Quantity to get LD DE,TMPNOS ; Point to home WINNO1: LD A,2 ; Maximum of 2 digits CALL INPNUM OR A ; If 0 JR Z,WINNO4 ; Then set abort flag CP HIGHNO+1 ; See if > high number JR NC,WINNO2 ; If so, clean up & retry ; LD (DE),A ; Else store it INC DE ; Point to next home LD A,SPC ; Space for neatness CALL PCHAR DJNZ WINNO1 ; Loop until done ; CALL PCRLF ; Cr/lf at end XOR A ; Clear carry to show ok RET ; WINNO2: PUSH BC ; Save loop counter LD A,(NUMCNT) ; Get digits typed LD B,A ; To b LD C,0 WINNO3: LD A,BS ; Backspace CALL PCHAR LD A,SPC ; Space CALL PCHAR LD A,BS ; Backspace CALL PCHAR DJNZ WINNO3 ; Loop until done POP BC ; Restore loop counter JP WINNO1 ; Try again ; WINNO4: CALL PCRLF ; Cr/lf at end SCF ; Set carry to show abort RET ; ;-------------------------------------------------------------- ; ; Check a memory combination for any matches to the winning ; numbers and bonus number (if any). MATCNT holds match count. ; On entry and exit - hl points to memory combo starting addr. ; All other registers are not preserved. ; WINMEM: XOR A ; Init to zero LD (MATCNT),A ; Match count/bonus flag LD DE,TMPNOS ; Point to start of winners LD B,DIGITS ; Number of winners to check ; WINME2: PUSH BC ; Save winners count PUSH DE ; Save winners start addr PUSH HL ; Save mem combo start addr LD BC,DIGITS ; Length of combo XOR A ; Clear any flags LD A,(DE) ; Winning number to look for CPIR ; Check for match JP NZ,WINME3 ; If no match skip over ; LD A,(MATCNT) ; Get match count/bonus flag INC A ; Bump it LD (MATCNT),A ; Save match count/bonus flag ; WINME3: POP HL ; Restore mem combo start addr POP DE ; Restore winners addr INC DE ; Point to the next one POP BC ; Restore winners count DJNZ WINME2 ; Decr it, if <> 0 do more ; ; Just do a return here if no bonus number checking is desired ; LD A,(MATCNT) ; Get match count/bonus flag CP DIGITS ; See if all digits matched RET Z ; If so, just return CP WINBNS ; Else see if equal to bonus RET NZ ; Return if not equal ; ; We have all-but-one of the numbers, so check bonus number too ; PUSH HL ; Else save mem combo addr LD BC,DIGITS ; Length of combo XOR A ; Clear any flags LD A,(DE) ; Get bonus number to look for CPIR ; Check for match POP HL ; Restore mem combo start addr RET NZ ; Return if no match ; LD A,WINPLS ; Store bonus number flag LD (MATCNT),A ; In match count/bonus flag RET ; ;-------------------------------------------------------------- ; ; Display winning combination numbers at hl on con or lst. ; WINDSP: LD A,TAB ; Tabs CALL PCHAR2 LD A,TAB ; For neatness CALL PCHAR2 ; PUSH HL ; Save mem combo addr LD A,(MATCNT) ; Get match count/bonus flag CP WINPLS ; If bonus flag JR Z,WINDS2 ; Then handle differently CALL PRDEC LD HL,WINR3M ; Nos found in msg JP WINDS3 ; Display combo ; WINDS2: LD A,WINBNS ; Bonus minimum number CALL PRDEC LD HL,WINR4M ; And bonus in msg ; WINDS3: CALL PRNTL2 POP HL ; Restore mem combo addr ; ; The following displays sorted numbers at hl on con or lst ; WINDS4: LD B,DIGITS ; Length WINDS5: LD A,SPC ; Space CALL PCHAR2 ; Preceeds each number LD A,(HL) ; Get mem char CALL PRDEC ; Go display it INC HL ; Point to next addr DJNZ WINDS5 ; Loop if more to do JP PCRLF2 ; Cr/lf and return ; ;-------------------------------------------------------------- ; ; Read file to memory buffer ; RDFIL: LD HL,MSTRT ; Point to mem start LD (MADDR),HL CALL OPEN ; Try to open specified file CP 0FFH ; Jump if file not found JR Z,RDFIL7 XOR A ; Else rewind file and continue LD (FCB+NR),A ; RDFIL1: LD DE,(MADDR) ; Get address to read to... CALL SETDTA ; Set Disk Transfer Address CALL READ ; Read next record into dbuf CP 1 ; Jump if end-of-file JR Z,RDFIL5 LD HL,128 ; Point to disk buf ADD HL,DE ; bump for next read LD (MADDR),HL ; Else store next addr ; CALL CONDIN ; Get con status/char JP Z,RDFIL1 ; If nothing, continue AND 7FH ; Else strip parity CP 'C'-40H ; If ctrl c JR Z,RDFIL8 ; Then abort ; JP RDFIL1 ; Then get next record from disk ; RDFIL5: CALL CLOSE ; Clean up act LD HL,READ1M ; Read complete msg CALL PRNTL SCF ; Clear error flag CCF RET ; RDFIL7: LD HL,READ2M ; No file msg JP RDFIL9 ; RDFIL8: CALL CLOSE ; Clean up act LD HL,READ3M ; Aborted msg RDFIL9: CALL PRNTL SCF ; Set error flag RET ; ;-------------------------------------------------------------- ; ; Write memory buffer to disk ; WTFIL: LD HL,(MADDR) ; Get next mem storage addr LD DE,MSTRT ; Get mem starting addr OR A ; Clear for subtr SBC HL,DE ; LD A,L ; Test for zero OR H JR Z,WTFIL7 ; If nothing, say so INC HL ; Add 1 for nul terminator LD (MSIZE),HL ; Size of memory data ; CALL DELT ; Delete old file, if any CALL MAKE ; Make new file XOR A ; Rewind file LD (FCB+NR),A ; LD HL,(MSIZE) ; Get size of mem data CALL SHFTLH ; H = # of Sectors to write LD B,H INC B LD HL,MSTRT ; Points to mem start LD (MADDR),HL ; WTFIL1: LD DE,(MADDR) ; Get current buffer pointer CALL SETDTA ; And set as disk transfer addr ; CALL WRITE ; Write full dbuf to disk OR A ; Did we have an error? JR NZ,WTFIL6 ; If so, bail out LD HL,128 ; buffer size ADD HL,DE ; bump memory pointer LD (MADDR),HL DJNZ WTFIL1 ; Loop until end of mem data ; CALL CLOSE ; Else clean up act ; LD HL,MSTRT ; Clear text buffer LD (MADDR),HL ; LD HL,0 ; Set the size to zero LD (MSIZE),HL LD HL,WRIT1M ; Saved, capture off msg CALL PRNTL RET ; WTFIL6: LD HL,WRIT2M ; Error writing - disk full msg CALL PRNTL JP WTFIL ; And try again ; WTFIL7: LD HL,WRIT3M ; Buffer empty msg CALL PRNTL RET ; ;-------------------------------------------------------------- ; ; Set up fcb, get date of draw into fcb as name ; GFDATE: XOR A ; Initialize fcb LD (FCB),A LD HL,FCB+12 ; Zero fcb to its end LD B,21 CALL ZEROM ; LD HL,FCB+1 ; Blank fill fn and ft fields LD B,11 GFDAT2: LD (HL),' ' INC HL DJNZ GFDAT2 ; LD A,(DEFDSK) ; Get default disk LD (FCB),A ; Store it ; GFDAT3: LD HL,DRAWDM ; Enter draw date msg CALL PRNTL LD A,6 ; Max 6 digits CALL INPNUM ; Get numerical input ;; OR A ; If zero ;; JR Z,GFDAT4 ; Then we aborted LD A,(NUMCNT) ; Get digits typed count OR A ; If zero JR Z,GFDAT4 ; Then we aborted CP 6 ; See if required amount JR NZ,GFDAT3 ; If not, try again ; LD HL,NUMBUF ; Point to ascii number buf LD DE,FCB+1 ; Destination fcb filename LD BC,2 ; Two bytes LDIR ; Move them LD A,SLASH ; Slash to a LD (DE),A ; Store it INC DE ; Point to next destination LD BC,2 ; Two bytes LDIR ; Move them LD A,SLASH ; Slash to a LD (DE),A ; Store it INC DE ; Point to next destination LD BC,2 ; Two bytes LDIR ; Move them LD HL,FILXT ; Point to default extension LD BC,3 ; Three bytes LDIR ; Move them ; SCF ; Clear error flag and return CCF RET ; GFDAT4: LD HL,DABT1M ; Abort prompt CALL PRNTL ; GFDAT5: CALL CONDIN ; Get console input JP Z,GFDAT5 ; Loop if nothing CALL UPCASE ; Make upper case CP 'Y' ; Must be y to confirm abort JP Z,GFDAT6 LD HL,CLEARM ; Clear the line CALL PRNTL JP GFDAT3 ; Else assume no & retry ; GFDAT6: LD HL,CLEARM ; Clear the line CALL PRNTL LD HL,DABT2M ; Abort msg CALL PRNTL SCF ; Set error flag and return RET ; ;-------------------------------------------------------------- ; ; Initialize rand number generator MASK and VALDIF values. ; RNDINI: LD A,(MAXVAL) ; Get highest number LD HL,MASK ; Point to storage for max mask LD B,A ; Put maxval into b LD A,0FH ; Get smallest possible mask ; RNDIN2: LD D,A ; Put mask in safe place SUB B ; Is it big enough? JR NC,RNDIN3 ; If big enough, use it LD A,D ; Else get mask back RLA ; Double it plus one JP RNDIN2 ; And loop to see if big enough ; RNDIN3: LD BC,VALDIF LD (BC),A ; Store value difference LD (HL),D ; And store mask value RET ; ; ; Create unsorted unique random numbers in the range of ; 1 thru HIGHNO. Store in TMPNOS for subsequent sort. ; RNDNOS: LD HL,TMPCTR ; Point to storage ctr LD (HL),0 ; Zero it ; RNDLOP: CALL RNDFUN ; Get a 16-bit random # onto stack POP DE ; Pop it into de register LD HL,HWMANY ; Point to # of selections needed LD E,(HL) ; Get # LD HL,MASK ; Point to mask LD B,(HL) ; Put it in b LD A,D ; Put 1/2 of random # in acc AND B ; Mask to eliminate unneeded binary digits LD HL,VALDIF LD B,(HL) SUB B ; Subtr to shift #s down ; From max of 63 decimal ; To max of 44 decimal JR C,RNDLOP ; If result neg, get new rand # LD D,A ; Save number just in case JR Z,RNDLOP ; If result is 0 get new rand # ; LD HL,TMPCTR ; Point to storage for numbers LD A,(HL) ; Get count of #s already stored CP E ; Compare to max # allowed RNDEXT: RET Z ; If max, we are done ; INC HL ; Bump to 1st storage position LD C,A ; Put counter value in c LD B,0 ; Zero b OR A ; If # stored is zero LD A,D ; Get random # back JR Z,RNDSAV ; And go store in 1st position ; ; Check for uniqueness ; RNDCHK: LD A,D ; Get random # back and CPIR ; Compare to #'s alread stored JR Z,RNDLOP ; If a dupe get another one ; We now point to 1st ; Empty position so RNDSAV: LD (HL),A ; Put rand # into storage LD HL,TMPCTR ; Point to counter LD A,(HL) ; Get it INC A ; Update it LD (HL),A ; Put it back JP RNDLOP ; And go do next random number ; ; ; Random number generator ; Based on a routine by Robert Zimmerer in Microsystems, Oct'83 ; ; Return random 16 bit number on top of stack. Uses z80 refresh ; reg R for a random number seed. This routine calls mulhd that ; multiplies the hl and de registers. ; RNDFUN: LD A,R ; Get a random byte LD E,A LD D,0 ; Make a 16 bit number RRCA ; Scramble & set carry randomly JR C,RNDFN1 ; Use rand # in a if carry = 1 LD E,A ; Else use scrambled value LD BC,RANB ; Point at random number b JP RNDFN2 RNDFN1: LD BC,RANA ; Point at random number a RNDFN2: LD A,(BC) ; Move previous random LD L,A ; Number into hl INC BC LD A,(BC) LD H,A ADD HL,DE ; Mix it up CALL MULHD ; Scramble bits again ; Hl = (hl+de)*de, bc=bc LD A,H ; And replace the previous ; Rand number with this new one LD (BC),A DEC BC LD A,L LD (BC),A EX (SP),HL ; Swap random number with ret PUSH HL ; Push back ret address RET ; Return with random # on stack ; ;-------------------------------------------------------------- ; ; Multiply hl by de, result in hl. ; carry set means overflow. a is destroyed ; MULHD: PUSH AF PUSH BC ; Save regs PUSH DE XOR A ; Set no ovfl LD (OVFFLG),A ; Store in overflow flag PUSH HL ; Save hl LD HL,0 ; Zero long acc LD (TMPACC),HL ; Store in temp accumulator POP HL ; Get hl LD B,16 ; 16 loops ; MLHD: CALL SHFTRH ; Shift right multiplier JR NC,MLHD1 ; Don't add in if lsb is zero PUSH HL ; Save value LD HL,(TMPACC) ; Get temp accumulator ADC HL,DE ; Add in multiplicand LD (TMPACC),HL ; New accumulated value JR NC,MLHD0 LD A,0FFH ; Set ovfl flag LD (OVFFLG),A ; Store in overflow flag ; MLHD0: POP HL ; Get value ; MLHD1: EX DE,HL ; Shift left multiplicand CALL SHFTLH EX DE,HL DJNZ MLHD ; Count down POP DE ; Restore regs POP BC LD HL,(TMPACC) ; Get result LD A,(OVFFLG) ; Get overflow flag OR A ; 0=no JR Z,OKRET ; OVFRET: POP AF ; Get psw SCF ; Set carry RET ; OKRET: POP AF OR A ; Clear carry RET ; ; ; Divide hl by de, result in hl ; DIVHD: PUSH AF PUSH BC PUSH HL ; Save hl LD HL,0 LD (TMPACC),HL ; Zero accumulator POP HL PUSH HL OR A ; Clear carry flag SBC HL,DE ; Subrtact DE from HL POP HL ; Restore DE JR C,DOVFL ; Carry says HL < DE ; DNOVFL: LD B,16 ; 16 loops DVHD: CALL SHFTLH ; Shift dividend left PUSH HL ; Save dividend LD HL,(TMPACC) ; Get acc CALL SHFLCH ; Rotate acc & move in carry LD (TMPACC),HL ; New acc OR A ; Clear carry flag again SBC HL,DE ; Subtract DE from HL JR C,DVHD0 LD (TMPACC),HL ; Save new acc POP HL ; Get dividend SET 0,L ; Place in a 1 to quotient JP DVHD1 ; DVHD0: POP HL ; Get dividend & leave lsb at 0 DVHD1: DJNZ DVHD ; Count down ; DVRET: POP BC POP AF RET ; DOVFL: LD HL,0 ; Result is zero JP DVRET ; ; ; Shift right routine ; SHFTRH: PUSH AF AND A ; Clear carry RR H ; Shift high (rotate r thru cy) RR L ; Shift low (rotate r thru cy) JR NC,OKRET JP OVFRET ; ; Shift left routine ; SHFTLH: PUSH AF AND A ; Clear carry SHFL: RL L ; Shift low (rotate l thru cy) RL H ; Shift high (rotate l thru cy) JR NC,OKRET JP OVFRET ; SHFLCH: PUSH AF ; Shift hl left JP SHFL ; But shift in carry flag ; ;-------------------------------------------------------------- ; ; ZEROM: LD (HL),0 ; Zero memory, length in b INC HL DJNZ ZEROM RET ; ;-------------------------------------------------------------- ; ; UPCASE: CP 61H ; If < small a RET C ; Just return CP 7AH+1 ; If not between small a & z RET NC ; Just return AND 5FH ; Else make upper case RET ; ;-------------------------------------------------------------- ; ; 1/10 second delay routine ; DELAY: PUSH BC LD BC,4167*4 ; 4167 * system clock mhz DELAY1: DEC BC LD A,B OR C JP NZ,DELAY1 POP BC RET ; ;-------------------------------------------------------------- ; BDOS FUNCTIONS ; ; Get console status. ; CONST: PUSH HL PUSH DE PUSH BC LD C,CSTAF ; Con status func CALL GBDOS OR A ; Set status flags RET ; ; Get console status or input character. ; CONDIN: PUSH HL PUSH DE PUSH BC LD E,0FFH ; Input/status LD C,DCONF ; Direct con i/o func CALL GBDOS OR A ; Set condition flags RET ; ; Print routine. Preserves all registers. ; CONOUT: PUSH AF PUSH HL PUSH DE PUSH BC LD E,A ; Char to e LD C,COUTF ; Con out func CALL GBDOS POP AF RET ; ; List/printer routine. Preserves all registers. ; LSTOUT: PUSH AF PUSH HL PUSH DE PUSH BC LD E,A ; Char to e LD C,LOUTF ; Lst out func CALL GBDOS POP AF RET ; ; ; set Disk Transfer Address ; SETDTA: PUSH HL PUSH DE PUSH BC LD C,SETDTF CALL GBDOS RET ; ; Open disk file ; OPEN: PUSH HL PUSH DE PUSH BC LD DE,FCB LD C,OPENF ; Open file CALL GBDOS RET ; ; Read record from disk file ; READ: PUSH HL PUSH DE PUSH BC LD DE,FCB LD C,READF ; Read record CALL GBDOS RET ; ; Close disk file ; CLOSE: PUSH HL PUSH DE PUSH BC LD DE,FCB LD C,CLOSEF ; Close file CALL GBDOS RET ; ; Delete disk file ; DELT: PUSH HL PUSH DE PUSH BC LD DE,FCB LD C,DELTF ; Delete file CALL GBDOS RET ; ; Write record to disk ; WRITE: PUSH HL PUSH DE PUSH BC LD DE,FCB LD C,WRITEF ; Write record CALL GBDOS RET ; ; Make new disk file ; MAKE: PUSH HL PUSH DE PUSH BC LD DE,FCB LD C,MAKEF ; Make file CALL GBDOS RET ; GBDOS: PUSH IX PUSH IY CALL BDOS POP IX POP IY EX (SP),HL ; Save return address in HL POP BC ; Scrap old HL value POP BC POP DE EX (SP),HL ; Swap HL for return address RET ; ;-------------------------------------------------------------- ; ; Messages ; MNMENU: DEFB CR,LF,TAB,TAB DEFB '1> Create ticket combinations' DEFB CR,LF,TAB,TAB DEFB '2> Check for winning tickets' DEFB CR,LF,TAB,TAB DEFB '3> Redisplay memory numbers' DEFB CR,LF,TAB,TAB DEFB '0> Exit program ',CR,LF DEFB CR,LF,TAB,TAB DEFB 'Enter function number: ',0 ; TIKETM: DEFB CR,LF,TAB,TAB DEFB 'Number of tickets desired: ',0 ; STARTM: DEFB TAB,TAB DEFB 'Hit any key to start ',0 ; REDISM: DEFB CR,LF,TAB,TAB DEFB 'No display, memory is empty.' DEFB CR,LF,0 ; SELD0M: DEFB CR,LF,TAB,TAB DEFB 'Output to device' DEFB CR,LF,TAB,TAB DEFB ' 1> console 2> printer 3> both' ; IF TSTMODE DEFB ' 4> skip output' ENDIF ; DEFB CR,LF,0 SELD1M: DEFB CR,LF,TAB,TAB DEFB 'Output to device' DEFB CR,LF,TAB,TAB DEFB ' 1> console 2> printer 3> both' DEFB CR,LF,0 SELD2M: DEFB CR,TAB,TAB DEFB 'Enter number: ',BS,0 ; SAIDNM: DEFB 'No ',CR,LF,0 SAIDYM: DEFB 'Yes',CR,LF,0 SAVITM: DEFB CR,TAB,TAB DEFB 'Save to numbers to disk (Y/n)? ',BS,0 ; DRAWDM: DEFB CR,TAB,TAB DEFB 'Enter draw date as YYMMDD' DEFB BS,BS,BS,BS,BS,BS,0 ; DABT1M: DEFB ' Abort (y/N) ' DEFB 0 DABT2M: DEFB CR,TAB,TAB,'Aborted' DEFB CR,LF,CR,LF,0 CLEARM: DEFB CR,TAB,TAB DEFB ' ' DEFB ' ' DEFB 0 FILXT: DEFB 'LOT' ; Default file extension ; ; File read messages ; READ1M: DEFB TAB,'Read ok',CR,LF,0 READ2M: DEFB TAB,'No file',CR,LF,0 READ3M: DEFB TAB,'Aborted',CR,LF,0 ; ; File save messages ; WRIT1M: DEFB TAB,'Saved',CR,LF,0 WRIT2M: DEFB CR,LF,TAB,TAB DEFB 'Write error - Disk full?' DEFB CR,LF,TAB,TAB DEFB 'Change disk or use other drive',BEL,CR,LF,0 WRIT3M: DEFB TAB,'Buffer empty',CR,LF,0 ; ; Winning numbers messages ; WINR1M: DEFB CR,TAB,TAB DEFB 'Winning numbers: ',0 WINR2M: DEFB CR,TAB,TAB DEFB 'Bonus number is: ',0 WINR3M: DEFB ' nos found in: ',0 WINR4M: DEFB ' and bonus in: ',0 WINR5M: DEFB TAB,TAB DEFB 'Sorry, no winners were found.',CR,LF,0 ; BSMSG: DEFB BS,' ',BS,0 ; ;-------------------------------------------------------------- ; ; Variable buffers ; DEVFLG: DEFB 01H ; Output device flag COLUMN: DEFB WIDTH ; Con/lst column position ; NUMCNT: DEFB 0 ; Digits typed count NUMBUF: DEFS 12 ; Ascii number buffer ; ; Following are used for creation and winner check ; TKN: DEFW 0 ; Ticket number quantity TKC: DEFW 0 ; Ticket number counter MATCNT: DEFB 0 ; Match count/bonus flag MEMCNT: DEFW 0 ; Number of mem combos WINFLG: DEFB 0 ; Winners flag ; TMPCTR: DEFB 0 ; Unsorted storage counter TMPNOS: DEFS DIGITS ; Unsorted combo/winners buf SRTNOS: DEFS DIGITS ; Sorted combo/winners buf BONUSN: DEFB 0 ; Bonus number ; ; Following are used by the random number generator ; MAXVAL: DEFB HIGHNO ; Highest number HWMANY: DEFB DIGITS ; Number of selections MASK: DEFB 0 ; For random numbers VALDIF: DEFB 0 ; For random numbers RANB: DEFW 1936H ; Initial random numbers RANA: DEFW 1936H ; Just to get started ; ; ; TMPACC: DEFS 2 ; Temp accum for mulhd/divhd OVFFLG: DEFS 1 ; Overflow flag for mulhd ; DEFDSK: DEFS 1 ; Default disk storage MSIZE: DEFS 2 ; Memory buffer size MADDR: DEFS 2 ; Memory storage addr ; ;-------------------------------------------------------------- ; ; Program buffers ; OLDSTK: DEFS 2 DEFS 64 ; 32 level stack (minimum) ; EVEN EQU ($+255)/256*256 ; Buffer starts on even page ; ORG EVEN ; STACK EQU $-2 ; Even page may increase stack MSTRT: DEFS 1 ; Memory for data starts here ; ; END