O disco AY Demos v. 9 contém uma nova versão do programa de menu que desenvolvi, o Beta Boot Menu 4.0.
Este sistema é um interpretador de linhas de comandos que, a partir dos dados armazenados a partir do endereço 50000 da RAM, constrói menus controlados pelo teclado ou joystick. Os comandos para especificar um menu podem ser digitados num PC com um editor de textos plano, desde que o arquivo seja salvo em codificação ISO 8851-1 (Latin-1). Depois este arquivo pode ser inserido na RAM do TK90X emulado através de carregamento de arquivo binário (no Fuse, use a opção do menu File > Load binary data...). Futuramente irei escrever com detalhes os comandos disponíveis.
O programa foi feito nas linguagens BASIC e assembly. A listagem BASIC é:
O programa foi feito nas linguagens BASIC e assembly. A listagem BASIC é:
10 CLEAR 65367
20 LET dos=15363: IF PEEK dos<>195 THEN LET dos=15619
30 RANDOMIZE USR dos: REM : LOAD "BOOT"CODE
40 RANDOMIZE USR dos: REM : LOAD "MENUDATA"CODE 5E4
100 LET lm=62000
200 LET arg=USR lm
210 LET lm=62003
220 LET c$=CHR$ PEEK arg
230 LET a$="": FOR n=1 TO 8: LET a$=a$+CHR$ PEEK (arg+n): NEXT n
1000 IF c$="O" OR c$="o" THEN RANDOMIZE USR (dos-3)
2000 IF c$<>"D" AND c$<>"d" THEN GO TO 3000
2010 RANDOMIZE USR dos: REM : CAT
2020 GO TO 9000
3000 IF c$<>"R" AND c$<>"r" THEN GO TO 4000
3010 POKE 23693,56: BORDER 7: CLS : RANDOMIZE USR dos: REM : LOAD a$
3020 GO TO 4020
4000 IF c$<>"G" OR c$<>"g" THEN GO TO 5000
4010 RANDOMIZE USR dos: REM : GO TO a$CODE
4020 BEEP 1,5: GO TO 9000
5000 IF c$<>"V" AND c$<>"v" THEN GO TO 200
5010 RANDOMIZE USR dos: REM : LOAD a$CODE 16384
9000 LET lm=62006: GO TO 200
e a listagem assembly:
; Beta Boot Menu v. 4.0
; =====================
;
;File: BootMenu4.0.asm
;Version: 4.0 - Sep/23/2012
;Author: Flávio
; reikainosuke-tk@yahoo.com.br, http://cantinhotk90x.blogspot.com.br
;
;Description:
; Auto-executable program (boot) for Beta disk drive interface.
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
; Headers
;=========
INCLUDE "Header_Basic.asm"
INCLUDE "Header_Print.asm"
INCLUDE "Header_Joystick.asm"
;
; Constants
;===========
; ROM routines.
PRINT_OUT: EQU 2548
_PO_FETCH: EQU 2819
_PO_ABLE: EQU 2777
BEEPER: EQU 949
;
; Entry Points
;=============
ORG 62000
JP Begin ; Jump to beginning of the program, executed
;only at first time.
JP Entry2 ; Second entry point (62003) used to return
;from BASIC.
JP Entry3 ; Third entry point (62006), like Entry2 but
;wait for user action on joystick/keyboard.
; Variables
;===========
;62009
MenuData: DEFW 50000 ; Address of menu data (thus, address of first
;menu too).
;620011
T_CHARS: DEFW Latin1-256 ; PrLatin1: address of secondary
;char set.
;62013
LastMenu: DEFS 2 ; Address of last menu.
;62015
NumMenu: DEFS 1 ; Number of menus.
;62016
CurMenu: DEFS 1 ; Current menu number.
;62017
CurMAdd: DEFS 2 ; Current menu address.
;62019
NumOpts: DEFS 1 ; Number of options in a menu.
;62020
CurOpt: DEFS 1 ; Current option.
;62021
DEFB 0 ; Scroller: variable no longer in use.
;62022
PixCount: DEFB 8 ; Scroller: counter, 8 pixels to be rotated.
;62023
Title: DEFS 2 ; Pointer for the title string.
;62025
STitle: DEFS 2 ; Pointer for the subtitle string.
;62027
OldErrsp: DEFS 2 ; PrLatin1: temporary place to save ERR_SP.
;62029
KempWait: DEFB 6 ; Number of repetitions before testing Kempston
;joystick again.
;62030
KempCount: DEFB 6 ; Counter.
;62031
JKAction: DEFS 1 ; ReadJK: result of joystick/keyborad reading.
MsgIni: DEFW Logo ; Scroller: start of scroll message.
MsgPtr: DEFW Logo ; Scroller: pointer for scroll message.
;
; Main program
;==============
Entry3:
HALT ; Wait.
CALL ReadJK ; Read joystick/keyboard.
LD A,(HL) ; While user did not take any action
AND 000111
JR Z,Entry3 ;repeat this loop.
JR Entry2 ; Jump to Entry2.
Begin:
; Define variables for the scroller. Only the first M command found will be
;considered.
LD HL,(MenuData) ; Seek inside MenuData.
GetScrMsg:
CALL StrLen ; Get a line.
LD A,(DE) ; A=Command.
RES 5,A ; Convert to upper case.
JR Z,InitMenus ; If end of data, jump forward.
CP "E"
JR Z,InitMenus
CP "M" ; If it's not M command, jump backward to
JR NZ,GetScrMsg ;analise next line.
INC DE ; Skip first character of the line.
LD (MsgIni),DE ; Define variables for the scroller.
LD (MsgPtr),DE
LD HL,ScrBuffer ; Clear buffer used by scroller.
LD B,0 ; Count 256 bytes.
ClrScrBuff:
LD (HL),0
INC HL
DJNZ ClrScrBuff
InitMenus:
XOR A ; Number of menus=0.
LD (NumMenu),A
INC A ; Current menu=1.
LD (CurMenu),A
LD HL,(MenuData) ; HL points to first menu.
InitMenu1:
CALL ScanMenu ; Get menu data.
EX AF,AF' ; Save CARRY flag.
LD A,(NumOpts) ; Jump forward if menu is empty.
AND A
JR Z,InitMenu2
LD (LastMenu),HL ; Menu pointer is stored in LastMenu and the
LD A,(NumMenu) ;menu counter is incremented.
INC A
LD (NumMenu),A
InitMenu2:
EX AF,AF' ; Restore CARRY flag.
JR NC,InitMenu1 ; While end of data was not found,repeat for the
;next line.
; Main loop.
Main:
LD HL,(MenuData) ; HL points to the first menu.
LD A,(CurMenu) ; Get value of counter for menus.
SeekMenu:
PUSH AF
LD (CurMAdd),HL ; Store current menu address.
CALL ScanMenu ; Get menu data.
POP AF
DEC A ; Decrement menu counter.
JR NZ,SeekMenu ; Repeat until menu is found.
Entry2:
CALL PrMenu ; Print current menu at screen.
LD A,1 ; Initialize current option to first option.
LD (CurOpt),A
Main1:
CALL SetCursor ; Put cursor on screen.
Main2:
CALL WaitJK ; Wait for user action and update scroll.
BIT 0,(HL) ; If 'down' command was not activated then
JR Z,Main3 ;jump forward
CALL SetCursor ;else remove cursor from screen.
LD HL,CurOpt ; HL will points to current option variable.
INC (HL) ; Increment current option value.
LD A,(NumOpts) ; If NumOpts+1<=CurOpt (there are NumOpts
INC A ;options plus "Menu anterior" and
CP (HL) ;"Menu seguinte")
JR NC,Main1 ;then jump back to the loop
LD (HL),0 ;else reset the CurOpt.
JR Main1 ; Jump back to the loop.
Main3:
BIT 1,(HL) ; If 'up' command was not activated then
JR Z,Main4 ;jump forward
CALL SetCursor ;else remove cursor from screen.
LD HL,CurOpt ; HL will points to current option variable.
DEC (HL) ; Decrement current option value.
JP P,Main1 ; If CurOpt>=0 then jump back to the loop
LD A,(NumOpts) ;else CurOpt=NumOpts+1 ("Menu seguinte").
INC A
LD (HL),A
JR Main1 ; Jump back to the loop.
Main4:
BIT 2,(HL) ; If fire button wasn't pressed
JR Z,Main2 ;jump back to the loop.
LD HL,CurMenu
LD A,(CurOpt) ; If CurOpt<>0 (not option 'Menu anterior') then
OR A
JR NZ,Main5 ;jump forward
DEC (HL) ;else decrement current menu number.
JR NZ,Main ; If first menu was passed
LD A,(NumMenu) ;then jump to last menu.
LD (HL),A
JR Main
Main5:
PUSH HL
LD HL,NumOpts ; If CurOpt>NumOpts (not option 'Menu seguinte')
DEC A
CP (HL)
POP HL
JR C,Main6 ;then jump forward
INC (HL) ;else increment current menu number.
LD A,(NumMenu) ; If NumMenu>=CurMenu
CP (HL)
JR NC,Main ;then repeat the loop
LD (HL),1 ;else CurMenu=1.
JR Main ; Repeat the loop.
Main6:
INC A ; Restore CurOpt value and
LD B,A ;store in B (counter).
LD HL,(CurMAdd) ; HL points to current menu data.
Main7:
PUSH BC ; Save counter.
Main8:
CALL StrLen ; Advance to next command line.
EX DE,HL ; HL=address of previous command line.
CALL TestOpt ; Test if command is a menu option.
EX DE,HL ; HL=address of next command line.
JR NZ,Main8 ; Repeat until menu option is found.
POP BC ; Restore counter.
DJNZ Main7 ; Repeat until desired option is found.
LD A,(DE) ; A=command.
RES 5,A ; Convert to upper case letter.
CP "L" ; If command is 'Line', jump back to the loop,
JR Z,Main2 ;since it has to do nothing.
LD C,E ; BC points to beginning of command line. This
LD B,D ;value is passed for the BASIC after returning.
CP "N" ; If command isn't 'New' then return to BASIC.
RET NZ
CALL ROM_CLS ; Create new menu to check if the user really
LD A,2 ;want to reset the computer. First screen is
CALL CHAN_OPEN ;cleared and "S" channel is opened.
LD A,Pr_At ; <PRINT AT 16,10;>;
RST 16
LD A,10
RST 16
XOR A
RST 16
LD HL,NoMsg ; Print the option "not erase RAM".
CALL PrCStr
LD HL,YesMsg ; Print the option "yes, erase RAM".
CALL PrCStr
New1:
CALL NewCurNo ; Put the cursor on first option.
New2:
CALL WaitJK ; Wait for user action and update scroll.
BIT 2,(HL) ; If fire button was pressed at first option
JP NZ,Main ;then return to main loop
BIT 0,(HL) ;else if user didn't select 'down'
JR Z,New2 ;then repeat the loop
CALL NewCurNo ;else remove cursor, put it at 11,0 and
CALL NewCurYes ;highlight second option.
New3:
CALL WaitJK ; Wait for user action and update scroll.
BIT 1,(HL) ; Test if user input is 'up'
PUSH AF ;and save the result.
CALL NZ,NewCurYes ; If user requested 'up' then remove cursor
POP AF
JR NZ,New1 ;and jump to first option.
BIT 2,(HL) ; If fire button wasn't pressed
JR Z,New3 ;then repeat the loop
RST 0 ;else reset computer.
;
NewCurNo:
LD HL,22848 ; Put cursor at 10,0;
JR NewCurNo1
NewCurYes:
LD HL,22880 ; Put cursor at 11,0;
NewCurNo1:
JP SetCurHL
;
NoMsg:
DEFM "Não quero apagar a RAM."
DEFB 0
YesMsg:
DEFM "Sim, limpe a RAM."
DEFB 0
;
; Sub-routines
;==============
; Wait Joystick/Keyboard (WaitJK)
;---------------------------------
; Description: WaitJK waits for any user intervention on joystick or keyboard.
;To prevent rapid repetitions, it waits until all controls are freed or the time
;is up. Scroll message is updated during sub-routine execution.
WaitJK:
LD B,15 ; Initialize time up counter.
WaitJK1:
PUSH BC ; Save counter.
CALL Scroller ; Print scroll message.
CALL ReadJK ; Read joystick and keyboard.
HALT ; Pause.
POP BC ; Restore counter.
DEC B ; Decrement counter and jump forward if
JR Z,WaitJK2 ;time is up.
LD A,(HL) ; If joystick or keyboard is activated then
AND 000111
JR NZ,WaitJK1 ;wait until it is released.
WaitJK2:
CALL ReadJK ; Read joystick and keyboard again.
PUSH HL
LD A,(HL)
AND 000111
LD HL,156 ; Play a tone in the beeper output.
LD DE,46
CALL NZ,BEEPER
POP HL
RET
;
; String Lenght (StrLen)
;------------------------
; Description: get length of a string terminated by one or two characters which
;codes are less than space (" ", 32 or #20). This routine can interpret text
;files from many modern operating systems.
; Input: HL=start of string
; Output: DE=start of string, HL=next address after string, BC=length, A=31
;
StrLen:
LD D,H ; DE=address of string.
LD E,L
LD A,31 ; A=" "-1.
StrLen1:
CP (HL)
INC HL ; Increments pointer.
JR C,StrLen1 ; If A<(HL) then jump to test next byte,
CP (HL) ;else verify next byte.
JR C,StrLen2 ; If A<(HL) then jump forward,
INC HL ;else increments pointer again.
StrLen2:
AND A ; BC=HL-DE,
SBC HL,DE ;the result is string length.
LD B,H
LD C,L
ADD HL,DE ; Recover HL (next address after string).
RET ; End.
;
; CaseA
;-------
; Description: implementation of CASE structure presents in high level
;languages. A is a character to be found in a table pointed by HL. The table
;consists in 3 bytes elements, which first byte represents a character and the
;next 2 bytes an address to jump to. The end of the table is marked by 0.
; Input: A=character to be found, HL=address of the table.
CaseA:
LD C,A ; Store character to be searched.
CaseA1:
LD A,(HL) ; Get character from the table.
AND A ; If it's 0, return.
RET Z
INC HL ; Get address from the table and put into DE.
LD E,(HL)
INC HL
LD D,(HL)
INC HL ; HL points to next table element.
CP C ; If the character was not found
JR NZ,CaseA1 ;jump to try next table element.
EX DE,HL ; Otherwise, jump to the specified address.
JP (HL)
;
; ScanMenu
;------------------
; Description: scan data of a menu and return its number of options. The commands
;Title, Subtitle, Paper, Ink, Border, borderinK are processed and the relevant
;variables are properly attributed.
; Input: HL=address of the menu
; Output: (NumOpts)=number of options of the menu, CARRY is set when HL reaches
;end of MenuData.
; AF, BC, DE, HL and IX are destroyed.
ScanMenu:
XOR A ; NumOpts=0
LD (NumOpts),A
ScanMenu1:
CALL StrLen ; Get a line from menu data.
LD A,(DE) ; A=command.
RES 5,A ; Convert to upper case.
PUSH AF ; Save registers.
PUSH HL
INC DE ; IX-1 points to start of command line and IX,
PUSH DE ;to the first byte of its argument.
POP IX
LD HL,ScanMTab ; Table with commands and their addresses.
CALL CaseA ; Search for the command and execute it.
POP HL ; Restore registers.
POP AF
CP "C" ; Repeat until command is 'Close' or
JR Z,ScanMenu2
CP "E" ;command is End or
JR Z,ScanMenu3
CP 32 ;command is invalid (less than 32) or
JR C,ScanMenu3
LD A,(NumOpts)
CP 18 ;NumOpts=18.
JR NZ,ScanMenu1
LD A,"C" ; If 18 options were found and
CP (HL) ;next command is 'Close'
CALL StrLen ;then skip next line.
ScanMenu2: AND A ; CARRY=0 indicates that there are more lines
RET ;in menu data.
ScanMenu3: SCF ; CARRY=1 indicates end of menu data.
RET
ScanMTab:
DEFB "T" ; Title.
DEFW ScanMenuT
DEFB "S" ; Subtitle.
DEFW ScanMenuS
DEFB "P" ; Paper.
DEFW ScanMenuP
DEFB "I" ; Ink.
DEFW ScanMenuI
DEFB "B" ; Border.
DEFW ScanMenuB
DEFB "K" ; borderinK.
DEFW ScanMenuK
DEFB "R" ; Run.
DEFW ScanMInc
DEFB "G" ; Goto.
DEFW ScanMInc
DEFB "V" ; View.
DEFW ScanMInc
DEFB "L" ; Line.
DEFW ScanMInc
DEFB "D" ; Dir.
DEFW ScanMInc
DEFB "N" ; New.
DEFW ScanMInc
DEFB "O" ; Out.
DEFW ScanMInc
DEFB 0 ; Table terminator.
ScanMenuT:
LD (Title),IX ; Title points to the string.
RET
ScanMenuS:
LD (STitle),IX ; Title points to the string.
RET
ScanMenuB:
LD HL,BORDCR ; Changes are applied to border attributes.
JR ScanMenB1
ScanMenuP:
LD HL,ATTR_P ; Changes are applied to main screen attributes.
ScanMenB1:
CALL ScanMColor ; Get argument from command line.
RLCA ; Transfer to bits 3-5.
RLCA
RLCA
LD B,A
LD A,(HL) ; Get current attributes.
AND %11000111 ; Reset bits 3-5.
OR B ; Put color on the bits 3-5.
LD (HL),A ; Store the new attributes.
RET ; End.
ScanMenuK:
LD HL,BORDCR ; Changes are applied to border attributes.
JR ScanMenK1
ScanMenuI:
LD HL,ATTR_P ; Changes are applied to main screen attributes.
ScanMenK1:
CALL ScanMColor ; Get argument from command line.
LD B,A
LD A,(HL) ; Get current attributes.
AND %11111000 ; Reset bits 0-2.
OR B ; Put color on the bits 0-2.
LD (HL),A ; Store the new attributes.
RET ; End.
ScanMColor:
LD A,(IX+0) ; Get argument from the command line.
SUB "0" ; Convert ASCII digit to number.
AND 000111 ; Restrict range to 0-7.
RET ; End.
ScanMInc:
LD HL,NumOpts ; Increment number of options of current menu.
INC (HL)
RET
;
; Print Menu (PrMenu)
;---------------------
; Description: PrMenu clears the screen and prints the titles and all current
;menu options.
; All registers are destroyed.
PrMenu:
CALL ROM_CLS ; Clear screen.
LD A,2 ; Open "S" channel.
CALL CHAN_OPEN
LD A,(BORDCR) ; Set same color attributes like border to
LD (ATTR_T),A ;print title and subtitle.
AND 111000
RRA
RRA
RRA
OUT (254),A
LD HL,(Title)
CALL PrCStr
LD HL,(STitle)
CALL PrCStr
LD A,(ATTR_P) ; Restore main screen attributes.
LD (ATTR_T),A
LD A,Pr_At
RST 16
LD A,(NumOpts) ; {PRINT AT 11-NumOpts/2,0;}
SRL A
NEG
ADD 11
RST 16
XOR A
RST 16
LD A,Pr_Inverse ; {INVERSE 1}
RST 16
LD A,1
RST 16
LD HL,PrMMsg1 ; Print "Menu anterior"
CALL PrCStr
LD A,Pr_Inverse ; {INVERSE 0}
RST 16
XOR A
RST 16
LD HL,(CurMAdd) ; HL is pointer of current menu.
LD A,(NumOpts) ; CurOpt is counter of menu options.
LD (CurOpt),A
PrMenu1:
CALL TestOpt ; Test if the command is menu option and
EX AF,AF' ;save Flags.
CALL StrLen ; Advance to next command line.
EX AF,AF' ; Recover Flags and
JR NZ,PrMenu1 ;jump backward if wasn't menu option.
PUSH HL ; Save address of next line.
EX DE,HL ; HL=DE+1, pointer for string to be printed.
CALL PrOpt ; Print option description.
LD HL,CurOpt ; Decrement counter of menu options.
DEC (HL)
POP HL ; Recover address of next line.
JR NZ,PrMenu1 ; Repeat until counter is 0.
LD A,Pr_Inverse ; {INVERSE 1}
RST 16
LD A,1
RST 16
LD HL,PrMMsg2 ; Print "Menu seguinte".
CALL PrCStr
LD A,Pr_Inverse ; {INVERSE 0}
RST 16
XOR A
RST 16
RET ; End.
PrMMsg1:
DEFM "<< Menu anterior <<"
DEFB 0
PrMMsg2:
DEFM ">> Menu seguinte >>"
DEFB 0
;
; Print Option (PrOpt)
;----------------------
; Description: PrOpt prints a menu option description. The command letter and,
;for Run and View, the TR-DOS file name are skipped.
PrOpt:
CALL TstOptFile
JR NZ,PrOpt1
LD BC,8
ADD HL,BC
PrOpt1: INC HL
JP PrCStr
;
; Test Option with File name (TstOptFile)
;----------------------------------------
; Description: TstOptFile reads command line pointed by HL and tests if it
;represents a menu option with TR-DOS file name embedded in it (Run, Goto and
;View).
; Input: HL=address of the line
; Output: ZERO=1 if line is menu option; A=code of command.
TstOptFile:
LD A,(HL)
RES 5,A ; Convert to upper case.
JR TstOptF1
;
; TestOption (TestOpt)
;-----------------------------
; Description: TestOption reads command line pointed by HL and tests if it
;represents a menu option.
; Input: HL=address of the line
; Output: ZERO=1 if line is menu option; A=code of command.
TestOpt:
LD A,(HL)
RES 5,A ; Convert to upper case.
CP "L" ; Line command.
RET Z
CP "D" ; Dir command.
RET Z
CP "N" ; New command.
RET Z
CP "O" ; Out command.
RET Z
TstOptF1:
CP "R" ; Run command.
RET Z
CP "G" ; Goto command.
RET Z
CP "V" ; View command.
RET ; End.
;
; SetCursor
;-----------
SetCursor:
LD A,(NumOpts)
SRL A
LD C,A
LD A,(CurOpt)
ADD A,11
SUB A,C
LD L,0
RRCA
RR L
RRCA
RR L
RRCA
RR L
AND 000011
OR %01011000
LD H,A
SetCurHL:
LD B,32
SetCurs1:
LD A,%11000000
XOR (HL)
LD (HL),A
INC HL
DJNZ SetCurs1
RET
;
; Read Joystick and Keyboard (ReadJK)
;-------------------------------------
ReadJK:
LD BC,0 ; BC initial value.
LD HL,JKAction
LD (HL),0
LD A,(KempCount) ; Test if Kempston was active.
OR A
JR Z,KempsOn ; If active then jump forward
DEC A ;else decrement counter
KempsOff:
LD (KempCount),A ;for new trying.
JR NoKempston ; Jump to proceed without Kempston.
KempsOn:
IN A,(KEMPS_PORT) ; Read Kempston port and store in E.
LD E,A
AND %11100000 ; Test if Kempston is active.
LD A,(KempWait) ; Initialize KempCount.
JR NZ,KempsOff ; If Kempston if off, jump to reset KempCount.
BIT 4,E ; Test fire button.
JR Z,KempNoF ; If not pressed then jump ahead
SET 2,(HL) ;else set the fire button flag.
KempNoF:
LD A,KEMPS_UP+KEMPS_RGHT
AND E ; If 'up' or 'right' was pressed then set the
JR Z,KempNoUR ;up flag, else jump forward.
SET 1,(HL)
KempNoUR:
LD A,KEMPS_DOWN+KEMPS_LEFT
AND E ; If 'down' or 'left' was pressed the set the
JR Z,NoKempston ;down flag, else jump forward.
SET 0,(HL)
NoKempston:
LD BC,$0FFE ; Read all rows of 5 rightmost keys.
IN E,(C) ; E=XXXLRDUF (Left, Right, Down, Up, Fire).
LD A,E
RRCA ; Now CARRY=F and A=FXXXLRDU.
JR C,I2J1_NoF ; If fire was not pressed then jump ahead
SET 2,(HL) ;else set the fire flag.
I2J1_NoF:
OR %11111010 ; Test 'right' or 'up' bits. If both were set,
INC A ;incrementing A will be 0.
JR Z,I2J1_NoRU ; Then jump forward,
SET 1,(HL) ;else, set the up flag.
I2J1_NoRU:
LD A,E
OR %11101011 ; Test 'left' and 'down' bits. If both were set,
INC A ;incrementing A will be 0.
JR Z,I2J2 ; Then jump forward,
SET 0,(HL) ;else set the down flag.
I2J2:
LD B,%11110111 ; Read keys 1-5.
IN E,(C) ; A=XXXFUDRL.
BIT 4,E ; If 'fire' bit is high
JR NZ,I2J2_NoF ;then jump forward,
SET 2,(HL) ;else set the fire flag.
I2J2_NoF:
LD A,%11110101 ; Test 'up' and 'right' bits. If both were high,
OR E
INC A ;incrementing A will be 0.
JR Z,I2J2_NoUR ; Then jump forward,
SET 1,(HL) ;else set the up flag.
I2J2_NoUR:
LD A,%11111010 ; Test 'down' and 'left' bits. If both were
OR E
INC A ;high, incrementing A will be 0.
JR Z,Keys_CapsB ; Then jump forward,
SET 0,(HL) ;else set the down flag.
Keys_CapsB:
LD B,%11111110 ; Read row of keys Caps-shift to B.
IN A,(C)
OR %11100000
INC A
JR Z,Keys_QT
SET 2,(HL)
Keys_QT:
LD B,%11111011 ; Read row of keys Q to T.
IN A,(C)
OR %11100000
INC A
JR Z,Keys_AG
SET 1,(HL)
Keys_AG:
LD B,%11111101 ; Read row of keys A to G.
IN A,(C)
OR %11100000
INC A
RET Z
SET 0,(HL)
RET
;
; Print Char (PrChar)
;---------------------
; Description: print one character. All registers are preserved, except AF, BC'
;and DE'.
; Input: A=character code
PrChar:
EXX ; Saves all general purpose registers and
PUSH HL ;HL'.
CALL PrLatin1 ; Print character.
POP HL ; Restore saved registers.
EXX
RET ; End.
;
; Print String (PrStr)
;----------------------
; Description: prints a string pointed by HL. The end of string is marked by
;byte value lesser than 32 (space).
; Input: HL=address of string.
; Output: HL=address of last byte of string, A=code of end of string marker.
PrStr:
LD A,(HL) ; Get character.
CP 32 ; If its code is lesser than 32
RET C ;returns.
CALL PrChar ; Print character.
INC HL ; Point to next address.
JR PrStr ; Repeat the loop.
;
; Print Centered String (PrCStr)
;--------------------------------
; Description: PrCStr prints strings pointed by HL, centered at screen line.
;String longer than 30 character will be truncated.
PrCStr:
PUSH HL ; Saves pointer.
LD B,30 ; Max. string length counter.
; Measure string length.
PrCStr1:
LD A,(HL) ; Get character.
INC HL ; Increment pointer.
CP 32 ; Jump forward if end mark was found.
JR C,PrCStr3
DJNZ PrCStr1 ; Repeat until max. length is found.
; Print one space, 30 characters and one space.
POP HL ; Recover pointer initial value.
LD A,32 ; Prints space.
RST 16
LD B,30 ; Counter for 30 characters.
PrCStr2:
LD A,(HL) ; Get character and print it.
CALL PrChar
INC HL ; Increment pointer and
DJNZ PrCStr2 ;repeat.
LD A,32 ; Print space.
RST 16
RET ; End.
; Calculate tabulation and print
PrCStr3: SRL B ; B=B/2-1, number of print positions to be
INC B ;skipped.
LD A,Pr_Tab ; {PRINT TAB B;}.
RST 16
LD A,B
RST 16
XOR A
RST 16
POP HL ; Recover pointer initial value.
CALL PrStr ; Print the string.
LD A,Comma_Tab ; Print until the end of the line with
RST 16 ;{PRINT ,}.
RET ; End.
;
; Print Latin 1 (PrLatin1)
;--------------------------
; Description: print character code contained in the accumulator at upper video
;area. The characters within 0-159 range are printed by the ROM routine
;PRINT_OUT; above ;this value (160-255), corresponding Latin-1 character
;(ISO8859-1) are printed.
; Input: A=character code (0-255)
PrLatin1:
RES 1,(IY+1) ; Reset flag to print to screen instead printer.
RES 0,(IY+2) ; Reset flag to print at upper video area.
CP 160 ; If character code<160
JP C,PRINT_OUT ;jump to ROM routine.
LD HL,(ERR_SP) ; Preserve ERR_SP.
LD (OldErrsp),HL
LD HL,PrLatRet ; Store sub-routine return address in the
PUSH HL ;stack.
LD (ERR_SP),SP ; Even when an error occurs, return to PrLatRet.
CALL ExChars ; Select Latin1 character set.
RES 7,A ; The character code gamma is changed from
; Convert characters from range 160-255 to 32-127.
CALL _PO_FETCH ; Parts of PRINT_OUT where different treatments
JP _PO_ABLE ;for <32 or >127 characters are omitted, to make
;possible printing in full 7 bit codes (0-127).
PrLatRet:
CALL ExChars ; Select normal character set.
LD HL,(OldErrsp) ; Restore old ERR_SP value.
LD (ERR_SP),HL
BIT 7,(IY+0) ; If ERR_NR signaled no error had been detected
RET NZ ;then return,
LD SP,(ERR_SP)
RET ;else jump to error handling routine of BASIC.
;
; Exchange CHARS
;----------------
; Exchange contents of CHARS and T_CHARS (temporary CHARS). Swap between
;alternate character sets.
ExChars:
LD HL,(CHARS)
LD DE,(T_CHARS)
LD (CHARS),DE
LD (T_CHARS),HL
RET
;
; Scroller
;----------
; Description: Scroller prints message at two bottom lines of the screen with
;double height characters. The scroller is synchronized with maskable interrupts
;that occurs 50 or 60 times per second. Thus, some interrupts must be skipped
;in order to make message visible for human eyes.
;
; Altered to scroll pixel by pixel.
;
; Input: MsgIni, MsgPtr
; Variables:
; PixCount=counter, 8 pixels to be rotated
; ChrBitmap=8 byte bitmap for rightmost character
; ScrBuffer=array of 32x8 bytes to store bitmap of bottom lines
; Print at line=22 and column=0.
ScrPrnPos: EQU 16384+(2*2048)+(6*32)
Scroller:
; Create bitmap for 32 characteres in screen buffer.
LD DE,ChrBitmap ; DE is pointer for first byte of character that
;is hidden after rightmost position.
LD HL,ScrBuffer+31 ; Rightmost postion of first line.
LD BC,256*32+8 ; Counters: B=32 bytes, C=8 lines.
Scroller1:
PUSH BC
LD A,(DE) ; Take byte from hidden character and rotate
RLCA ;1 bit leftwise.
LD (DE),A
INC DE ; DE is now pointing to next byte.
Scroller2:
RL (HL) ; Rotate 1 bit leftwise.
DEC HL ; HL is pointing to previous position of buffer.
DJNZ Scroller2 ; Repeat for 32 bytes of a line.
LD C,64 ; BC=64.
ADD HL,BC ; Rightmost position of next line of buffer.
POP BC
DEC C ; Repeat for 8 lines.
JR NZ,Scroller1
; Copy bitmap to screen.
LD HL,ScrBuffer ; Address of screen buffer.
LD DE,ScrPrnPos ; Address of video RAM buffer to copy to.
LD A,16 ; 16 pixel lines.
Scroller3:
PUSH DE
PUSH HL
LD BC,32 ; Copy 32 bytes.
LDIR
POP HL
POP DE
INC D ; Calculate adress of next line.
DEC A ; Decrement line counter.
JR Z,Scroller5 ; Jump outside loop if last line was printed.
BIT 0,A ; Copy same line to screen if line number in the
JR NZ,Scroller3 ;buffer is odd.
LD C,32 ; Calculate address of next line of buffer.
ADD HL,BC
EX AF,AF' ; Save line counter.
LD A,D ; Go to next pixel line if it is not the last
AND 000111 ;one.
JR NZ,Scroller4
LD DE,ScrPrnPos+32 ; Adress of text line 7 and pixel line 0.
Scroller4:
EX AF,AF' ; Fetch line counter.
JR Scroller3
; Verify if all bits were rotated.
Scroller5:
LD HL,PixCount ; Return if last pixel has been rotated.
DEC (HL)
RET NZ
LD (HL),8 ; Reinitialize pixel counter.
LD HL,(MsgPtr) ; Get character from scrolling message
LD A,(HL) ;memory.
INC HL
CP 32 ; Initialize scrolling message pointer if
JR NC,Scroller6 ;character code is less than 32 and
LD HL,(MsgIni)
LD A," " ;print space.
Scroller6:
LD (MsgPtr),HL ; Update message pointer.
LD HL,(CHARS) ; HL is address of character model table.
BIT 7,A ; Use alternative table if character code is
JR Z,Scroller7 ;greater or equal to 128.
LD HL,(T_CHARS)
RES 7,A ; Adjust character code within 32-127 range.
Scroller7:
LD D,0 ; Address of character model within table is
LD E,A ;given by following equation:
EX DE,HL ;HL=(table address)+8*(character code).
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,DE
LD DE,ChrBitmap ; Copy 8 bytes of character model.
LD BC,8
LDIR
RET
;
Latin1:
INCLUDE "Latin1.asm"
; Include bitmap models for Latin-1 charset.
;
; Default scroll message.
Logo: DEFM " "
DEFM "Beta Boot Menu "
Version: DEFM "v4.0 "
DEFM " "
DEFB 0
;
ScrBuffer: DEFS 256 ; 256 byte buffer for the scroller.
ChrBitmap: DEFS 8 ; 8 bytes space for character bitmap model.
;
; End of program
END
A novidade da versão 4 é o rolamento (scroll) suave da mensagem que fica nas linhas inferiores da tela. Nas versões anteriores o rolamento ocorria em passos de 1 caractere de largura (8 pixels), mas nesta os passos são de 1 pixel.
Nenhum comentário:
Postar um comentário
Seu comentário é bem vindo, mas peço que use este espaço adequadamente.