Indeed you can, but I think it's still more elegant to have as much code cross-compatible as possible. Plus, wouldn't the logical extreme of a single OS version that would work properly on all the calculators be better anyway?

CALL Menu
.DB 2 ;Number of menus
.DB "Tit1", 0 ;Title of menu1
.DB "Tit2", 0 ;Title of menu2
.DB 3 ;Number of options in menu1
.DB 4 ;Number of options in menu2
.DB "Opt1", 0 \ .DW Lbl1 ;Optiontext + Lable to jump to when selected.
.DB "Opt2", 0 \ .DW Lbl2
.DB "Opt3", 0 \ .DW Lbl3
.DB "U", 0 \ .DW LblU
.DB "R", 0 \ .DW LblR
.DB "2", 0 \ .DW LblToo
.DB "Fat", 0 \ .DW LblFat ;Sorry, could not resist.
Lbl1: Code
Lbl2: Code
Lbl3: Code
LblU: Code
LblR: Code
LblToo: Code
LblFat: Code
Menu:
;- Objective: Create a scrollable menu, with multiple titles possible.
;- INPUT: Data from codestream.
;- Variables:
; - Current menu selected = IXL
; - Current option selected = B
; - Number of menus = IXH
; - Number of options = C
; - Current option at first row = D
RES AppAutoScroll, (IY + AppFlags)
POP HL ;Gain the baseaddress of the input data.
LD C, 1
LD IXL, C ;IXL = Current menu selected.
LD C, (HL)
LD IXH, C ;IXH = Number of menus.
INC HL
LD (MenuTitleAddress), HL
LD B, C
CALL MenuSkipMenus ;B = Number of menus; becomes 0.
LD (MenuNrOptionsAddress), HL
ADD HL, BC ;B = 0, C = Number of menus, so BC = number of menus
LD (MenuOptionsAddress), HL
;Now, HL is at the beginning of the optionslist.
MenuDrawMenu:
b_call(_ClrLCDFull)
b_call(_HomeUp)
LD HL, (MenuTitleAddress)
LD C, IXL ;Now C = Current menu selected.
LD B, IXH ;Now B = Number of menus.
LD A, " " ;Now A = A space, to put inbetween the menus.
MenuDrawMenuTitle:
DEC C
CALL NZ, TextInverseOff
CALL Z, TextInverseOn
b_call(_PutS) ;Draw the title
CALL TextInverseOff
b_call(_PutC) ;Put a space inbetween
DJNZ MenuDrawMenuTitle ;Do this "number of menus" times, B is left 0.
;Now to get the number of options etc.
LD HL, (MenuOptionsAddress)
LD C, IXL
DEC C
JR Z, MenuNoSkipMenu
LD DE, (MenuNrOptionsAddress)
MenuSkipMenu:
LD A, (DE)
LD B, A
CALL MenuSkipOptions ;Makes sure B = 0
INC DE
DEC C
JR NZ, MenuSkipMenu
MenuNoSkipMenu:
LD (Temp), HL
LD C, IXL
DEC C
LD HL, (MenuNrOptionsAddress)
ADD HL, BC ;B = 0, so BC = C = Number of menus.
LD C, (HL) ;C = Number of options.
LD B, 1 ;D = Current option at first row
LD D, B ;B = Current option selected
MenuDrawText:
LD HL, $0001
LD (CurRow), HL
LD HL, (Temp)
PUSH BC
LD B, D ;Now B = Option at row 1.
DEC B
CALL NZ, MenuSkipOptions ;If row 1 is not 1, then skip the options before the one at row1.
LD B, 7
LD E, D ;Start off with the option at row1.
MenuDrawTextOptions:
LD A, E
CP C ;If there is no more option to write, abort.
JR Z, MenuDrawTextOptionsCont
JR NC, MenuDrawTextNoMore
MenuDrawTextOptionsCont:
LD A, 2
LD (CurCol), A
b_call(_PutS) ;Wrtite em.
MenuDrawTextOptionsSpaces:
LD A, (CurCol)
OR A
JR Z, MenuDrawTextOptionsSpacesEnd
LD A, " "
b_call(_PutC)
JR MenuDrawTextOptionsSpaces
MenuDrawTextOptionsSpacesEnd:
INC E
INC HL
INC HL
DJNZ MenuDrawTextOptions ;7 times.
MenuDrawTextNoMore:
POP BC
MenuDrawOptions:
LD HL, $0001
LD (CurRow), HL
PUSH BC ;Save B and C temporarely, but copy B into E, because we want to use B again soon.
LD E, B
LD A, D ;Begin with the option at row1.
LD B, 7 ;7 options to write max.
MenuDrawOptionsLoop:
PUSH AF ;Save AF for further use (A = current option drawn).
PUSH AF
CP E
CALL Z, TextInverseOn
CALL NZ, TextInverseOff
ADD A, $30 ;Add the number of bytes to get to the correct symbols.
CP $3A
JR Z, MenuDrawOptionsZero
JR C, MenuDrawOptionsLoopNumber
ADD A, 6 ;6 to get to the lettersymbols.
JR MenuDrawOptionsLoopNumber
MenuDrawOptionsZero:
LD A, L0
MenuDrawOptionsLoopNumber:
b_call(_PutC)
POP AF
CP D ;If TopOption = CurOption, then top option is being drawn.
JR NZ, MenuDrawOptionsCont
CP 1 ;If TopOption = CurOption = 1, no uparrow.
JR Z, MenuDrawOptionsCont2
LD A, LUpArrow
JR MenuDrawOptionsLoopCont
MenuDrawOptionsCont:
CP C ;If CurOption = Number of options
JR Z, MenuDrawOptionsCont2
LD A, (CurRow)
CP 7
JR NZ, MenuDrawOptionsCont2
LD A, LDownArrow
JR MenuDrawOptionsLoopCont
MenuDrawOptionsCont2
LD A, ":"
MenuDrawOptionsLoopCont:
b_call(_PutC)
b_call(_NewLine)
POP AF
INC A
CP C
JR Z, MenuDrawOptionsLoopEnd
JR NC, MenuDrawOptionsEnd
MenuDrawOptionsLoopEnd:
DJNZ MenuDrawOptionsLoop
MenuDrawOptionsEnd:
POP BC
CALL TextInverseOff
MenuUserInput:
LD E, C
PUSH DE
b_call(_getKey)
POP DE
LD C, E
CP kDown
JR Z, MenuDown
CP kUp
JR Z, MenuUp
CP kLeft
JR Z, MenuLeft
CP kRight
JP Z, MenuRight
CP kEnter
JR Z, MenuEnter
CP kVarx
JR NC, MenuUserInput
SUB k0
JR C, MenuUserInput
JR NZ, MenuUserInputNotZero
LD A, 10
JR MenuUserInputNumber
MenuUserInputNotZero:
CP 10
JR C, MenuUserInputNumber
DEC A
MenuUserInputNumber:
CP C
JR Z, MenuUserInputNumberCont
JR NC, MenuUserInput
MenuUserInputNumberCont
LD B, A
MenuEnter:
LD HL, (MenuOptionsAddress)
PUSH BC
LD B, IXL
DEC B
JR Z, MenuEnterSkipSkipLoop
LD DE, (MenuNrOptionsAddress)
LD C, 0
MenuEnterSkipLoop:
LD A, (DE)
ADD A, C
LD C, A
INC DE
DJNZ MenuEnterSkipLoop
LD B, C
CALL MenuSkipOptions
MenuEnterSkipSkipLoop:
POP BC
CALL MenuSkipOptions
DEC HL
LD A, (HL)
LD D, A
DEC HL
LD A, (HL)
LD E, A
EX DE, HL
JP (HL) ;Exit routine.
MenuDown:
LD A, B
CP C
JR Z, MenuDownWrap
INC B
LD A, B
SUB D
CP 7
JP NZ, MenuDrawOptions
INC D
JP MenuDrawText
MenuDownWrap:
LD B, 1
LD D, B
JP MenuDrawText
MenuUp:
LD A, B
DEC A
JR Z, MenuUpWrap
LD A, B
CP D
PUSH AF
DEC B
POP AF
JP NZ, MenuDrawOptions
DEC D
JP MenuDrawText
MenuUpWrap:
LD B, C
LD A, C
SUB 6
LD D, A
JP NC, MenuDrawText
LD D, 1
JP MenuDrawText
MenuLeft:
LD D, 1
LD B, 0
DEC IXL
JR NZ, MenuLeftCont
LD IXL, IXH
MenuLeftCont:
LD C, IXL
DEC C
LD HL, (MenuNrOptionsAddress)
ADD HL, BC
LD C, (HL)
INC B
JP MenuDrawMenu
MenuRight:
LD D, 1
LD B, 0
LD A, IXL
CP IXH
JR NZ, MenuRightCont
LD IXL, 0
MenuRightCont:
INC IXL
LD C, IXL
DEC C
LD HL, (MenuNrOptionsAddress)
ADD HL, BC
LD C, (HL)
INC B
JP MenuDrawMenu
TextInverseOn:
SET TextInverse, (IY + TextFlags)
RET
TextInverseOff:
RES TextInverse, (IY + TextFlags)
RET
MenuSkipOptions:
LD A, (HL)
INC HL
OR A
JR NZ, MenuSkipOptions
INC HL
INC HL ;Skip labelbytes.
DJNZ MenuSkipOptions
RET
MenuSkipMenus:
LD A, (HL)
INC HL
OR A
JR NZ, MenuSkipMenus
DJNZ MenuSkipMenus
RET
MenuTitleAddress: .DW 0
MenuNrOptionsAddress: .DW 0
MenuOptionsAddress: .DW 0
Temp: .DW 0
<Usual crap>
.DB t2ByteTok, tAsmCmp
b_call(_ClrLCDFull)
b_call(_HomeUp)
JR Start
<InputISR goes here>
Start:
InputISR: ;$9D9D
EX AF, AF'
EXX
XOR A
OUT (3), A
LD HL, CurTime
INC (HL)
LD A, $32
CP (HL)
JR NZ, InputNoblink
LD (HL), 0
LD A, (IY + CurFlags)
XOR %00001000
LD (IY + CurFlags), A
InputNoblink:
LD A, %00001010
OUT (3), A
EXX
EX AF, AF'
EI
RET
Input:
;INPUTROUTINE: Asks user to enter characters.
;INPUT:
;- IX = Address of string (Constant)
;- C = Maximum amount of characters (Constant)
;VARIABLES:
;- Cursorplace: (CurRow)&(CurCol)
;- Length of string: B
;- Current character: E
;- 2nd & Alpha: Shiftflags
;- Cursorblink: (CurTime)
;OUTPUT:
;- String at InputData (DE = Crap at the end)
;- Carry if error
;PSEUDOCODE:
;- Wait for keypress
; - If Clear: Delete all
; - If Del: Delete current charachter
; - If Left: Move cursor left if possible
; - If Right: Move cursor right if possible
; - If Up: Move cursor up if possible
; - If Down: Move cursor down if possible
; - If Enter: Exit without error
;- Convert to charachter
;- Check insertflag
; - If Insert, insert the character
; - If not, overwrite the character
;- Return to begin
;OTHER DATA:
;- Keyport (1):
; +-------------------------------------------------------------------------------------------------------------------------------+
; ¦ Read: ¦
; +-------------------------------------------------------------------------------------------------------------------------------¦
; ¦$FE = %11111110¦$FD = %11111101¦$FB = %11111011¦$F7 = %11110111¦$EF = %11101111¦$DF = %11011111¦$BF = %10111111¦$7F = %01111111¦
;+-----------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------¦
;¦ ¦$BF = %10111111¦ [GRAPH] ¦ [TRACE] ¦ [ZOOM] ¦ [WINDOW] ¦ [Y=] ¦ [2nd] ¦ [MODE] ¦ [DEL] ¦
;¦W¦$DF = %11011111¦ ¦ [STO] ¦ [LN] ¦ [LOG] ¦ [X²] ¦ [X-1] ¦ [MATH] ¦ [ALPHA] ¦
;¦R¦$EF = %11101111¦ [0] ¦ [1] ¦ [4] ¦ [7] ¦ [,] ¦ [SIN] ¦ [APPS] ¦ [X,T,Q,n] ¦
;¦I¦$F7 = %11110111¦ [.] ¦ [2] ¦ [5] ¦ [8] ¦ [)] ¦ [COS] ¦ [PRGM] ¦ [STAT] ¦
;¦T¦$FB = %11111011¦ [(-)] ¦ [3] ¦ [6] ¦ [9] ¦ [(] ¦ [TAN] ¦ [VARS] ¦ ¦
;¦E¦$FD = %11111101¦ [ENTER] ¦ [+] ¦ [-] ¦ [X] ¦ [/] ¦ [^] ¦ [CLEAR] ¦ ¦
;¦ ¦$FE = %11111110¦ [DOWN] ¦ [LEFT] ¦ [RIGHT] ¦ [UP] ¦ ¦ ¦ ¦ ¦
;+-------------------------------------------------------------------------------------------------------------------------------------------------+
LD B, 0 ;String has 0 characters at first
LD E, 0 ;We have character 0 selected at first
PUSH BC ;Save settings
PUSH IX
PUSH DE
RES Shift2nd, (IY + ShiftFlags)
RES ShiftAlpha, (IY + ShiftFlags)
RES ShiftLwrAlph, (IY + ShiftFlags)
RES ShiftALock, (IY + ShiftFlags)
RES TextInsMode, (IY + TextFlags)
SET CurOn, (IY + CurFlags) ;Set up interrupt
DI
LD A, 0
LD (CurTime), A
LD A, $99 ;AppBackupScreen is at $9872
LD I, A
LD HL, $9900 ;Load Vector Table, $9900 - $99FF
LD (HL), $9D
LD D, H
LD E, 1
LD BC, 256
LDIR
LD A, %00001010
OUT (3), A
IM 2
EI ;Enable the interrupts again
InputKey:
BIT CurOn, (IY + CurFlags)
JR Z, InputNoCursor
BIT Shift2nd, (IY + ShiftFlags)
JR Z, InputNot2nd
BIT TextInsMode, (IY + TextFlags)
JR NZ, Input2ndIns
LD A, $E1 ;$E1 = Shiftcursor
JR InputCursorDisp
Input2ndIns:
LD A, $E5
JR InputCursorDisp
InputNot2nd:
BIT ShiftAlpha, (IY + ShiftFlags)
JR Z, InputNotAlpha
BIT TextInsMode, (IY + TextFlags)
JR NZ, InputAlphaIns
LD A, $E2 ;$E2 = Alphacursor
JR InputCursorDisp
InputAlphaIns:
LD A, $E6
JR InputCursorDisp
InputNotAlpha:
BIT ShiftLwrAlph, (IY + ShiftFlags)
JR Z, InputNotLwrAlph
BIT TextInsMode, (IY + TextFlags)
JR NZ, InputLwrAlphIns
LD A, $E3 ;$E3 = LwrAlphcursor
JR InputCursorDisp
InputLwrAlphIns:
LD A, $E7
JR InputCursorDisp
InputNotLwrAlph:
BIT TextInsMode, (IY + TextFlags)
JR NZ, InputNormIns
LD A, $E0 ;$E0 = Cursor
JR InputCursorDisp
InputNormIns:
LD A, $E4
JR InputCursorDisp
InputNoCursor:
POP DE
POP IX
LD A, (IX)
PUSH IX
PUSH DE
OR A
JR NZ, InputCursorDisp
LD A, " "
InputCursorDisp:
b_call(_PutMap) ;Disables interrupts
EI
LD C, 1 ;b_call(_GetCSC) doesn't work, so let's make our own
LD HL, KeyGroups
InputCheckKeyGroup:
LD A, (HL)
OUT (C), A
LD B, 8 ;7 Cycles, enough to let the keyport respond
IN A, (C)
InputCheckKey:
RLCA ;Load the reset bit into carry
JR NC, InputKeyRead
DJNZ InputCheckKey
INC HL
LD A, (HL)
OR A
JR NZ, InputCheckKeyGroup
JR InputCont
InputKeyRead:
LD DE, KeyGroups ;Let's find the key selected
XOR A ;Resets Carry flag
SBC HL, DE ;Find keygroup
LD A, L ;HL is not higher than 256, so load it into A
SLA A ;A * 8 --> A...
SLA A ;...because there are 8 keys per group
SLA A
ADD A, B ;Add B to A, to distinguish the key selected inside the group
;NOTE: A = the same as the scancodeequates now.
POP DE
CP D
PUSH DE
JP Z, InputKey ;If the key pressed is the same, restart
InputCont:
POP DE ;Save last key into D
LD D, A
PUSH DE
JP Z, InputKey ;If no key was pressed, restart
;--------------------Actual checking of keys--------------------
CP skEnter
JP Z, InputEnd
CP sk2nd
JP Z, Input2ndPressed
CP skLeft
JP Z, InputLeft
CP skRight
JP Z, InputRight
CP skUp
JP Z, InputUp
CP skDown
JP Z, InputDown
CP skClear
JP Z, InputClear
BIT Shift2nd, (IY + ShiftFlags)
JR NZ, Input2nd
CP skDel
JP Z, InputDel
BIT ShiftAlpha, (IY + ShiftFlags)
JR NZ, InputAlpha
BIT ShiftLwrAlph, (IY + ShiftFlags)
JR NZ, InputLwrAlph
CP skAlpha
JP Z, InputAlphaPressed
LD HL, NormalLUT
JR InputCharCheck
Input2nd:
CP skAlpha
JP Z, Input2ndAlphaPressed
CP skDel
JP Z, InputIns
LD HL, 2ndLUT
JR InputCharCheck
InputAlpha:
CP skAlpha
JP Z, InputAlphaAlphaPressed
LD HL, AlphaLUT
JR InputCharCheck
InputLwrAlph:
CP skAlpha
JP Z, InputLwrAlphAlphaPressed
LD HL, LwrAlphLUT
InputCharCheck:
SUB 10 ;Cut down size for the LUT
JP C, InputKey
CP 38
JP NC, InputKey
LD C, A ;Load the address for the LUT
LD B, 0
ADD HL, BC
LD A, (HL) ;Load character in A
OR A ;If character is not valid...
JP Z, InputKey ;Abort
POP DE
POP IX
POP BC
PUSH AF
LD A, E
CP C ;If the maximum characters is reached...
JR Z, InputCharAbort ;...Abort
CP B ;If we are dealing with the last character...
JR Z, InputCharCont2
BIT TextInsMode, (IY + TextFlags)
JR Z, InputCharCont
InputCharIns:
PUSH BC
PUSH IX
PUSH DE
LD A, B
SUB E
LD C, A
LD B, 0
ADD IX, BC
PUSH IX
POP DE
DEC IX
PUSH IX
POP HL
LDDR
POP DE
POP IX
POP BC
LD HL, (CurRow)
PUSH HL
PUSH BC
PUSH DE
LD A, " "
b_call(_PutC)
PUSH IX
POP HL
INC HL
b_call(_PutS)
POP DE
POP BC
POP HL
LD (CurRow), HL
InputCharCont2:
INC B ;...incline the length of the string
InputCharCont:
INC E ;Incline the letterpointer
POP AF
LD (IX), A ;Load character into string data
INC IX ;Go to next character in string data
b_call(_PutC) ;Display the character
InputResetFlags:
CALL InputResetCursor
RES Shift2nd, (IY + ShiftFlags)
BIT ShiftALock, (IY + ShiftFlags)
JR NZ, InputCharEnd
RES ShiftAlpha, (IY + ShiftFlags)
RES ShiftLwrAlph, (IY + ShiftFlags)
InputCharEnd:
PUSH BC
PUSH IX
PUSH DE
JP InputKey
InputCharAbort:
POP AF
JR InputCharEnd
Input2ndPressed:
LD A, (IY + ShiftFlags)
XOR 1 << Shift2nd
LD (IY + ShiftFlags), A
JR InputEndFlag
InputAlphaPressed:
SET ShiftAlpha, (IY + ShiftFlags)
JR InputEndFlag
Input2ndAlphaPressed:
LD A, (IY + ShiftFlags)
XOR 1 << ShiftAlock
LD (IY + ShiftFlags), A
RES Shift2nd, (IY + ShiftFlags)
BIT ShiftLwrAlph, (IY + ShiftFlags)
JR NZ, InputEndFlag
SET ShiftAlpha, (IY + ShiftFlags)
JR InputEndFlag
InputAlphaAlphaPressed:
RES ShiftAlpha, (IY + ShiftFlags)
SET ShiftLwrAlph, (IY + ShiftFlags)
JR InputEndFlag
InputLwrAlphAlphaPressed:
RES ShiftLwrAlph, (IY + ShiftFlags)
RES ShiftALock, (IY + ShiftFlags)
InputEndFlag:
CALL InputResetCursor
JP InputKey
InputDel:
RES TextInsMode, (IY + TextFlags)
POP DE
POP IX
POP BC
LD A, E
CP B
JR Z, InputCharEnd
LD HL, (CurRow)
PUSH HL
PUSH DE
PUSH BC
PUSH IX
PUSH IX
POP HL
POP DE
INC HL
InputDelMoveLoop:
LD A, (HL)
OR A
LDI
JR Z, InputDelMoveLoopEnd
b_call(_PutC)
JR InputDelMoveLoop
InputDelMoveLoopEnd:
LD A, " "
b_call(_PutMap)
EI
POP BC
POP DE
POP HL
LD (CurRow), HL
DEC B
CALL InputResetCursor
JR InputCharEnd
InputIns:
LD A, (IY + TextFlags)
XOR 1 << TextInsMode
LD (IY + TextFlags), A
CALL InputResetCursor
RES Shift2nd, (IY + ShiftFlags)
JP InputKey
InputClear:
POP DE
POP IX
POP BC
LD A, B
OR A
JP Z, InputClearEnd
SUB E
PUSH BC
LD C, A
LD B, 0
ADD IX, BC
LD HL, CurCol
LD B, (HL)
ADD A, B
LD B, 0
InputClearCheckWrap:
CP 16
JR C, InputClearWrapEnd
SUB 16
INC B
JR InputClearCheckWrap
InputClearWrapEnd:
LD (HL), A
DEC HL
LD A, (HL)
ADD A, B
LD (HL), A
POP BC
INC HL
InputClearLoop:
LD (IX), 0
DEC IX
LD A, " "
b_call(_PutMap)
LD A, (HL)
OR A
JR Z, InputClearLoopWrap
DEC (HL)
JR InputClearLoopEnd
InputClearLoopWrap:
LD (HL), 15
DEC HL
DEC (HL)
INC HL
InputClearLoopEnd:
DJNZ InputClearLoop
LD (IX), 0
LD E, 0
InputClearEnd:
RES TextInsMode, (IY + TextFlags)
JP InputResetFlags
InputLeft:
CALL InputResetCursor
POP DE
POP IX
LD A, (IX)
OR A
JR NZ, InputLeftNotZero
LD A, " "
InputLeftNotZero:
b_call(_PutMap)
EI
LD A, E
OR A
JR Z, InputLeftEnd
DEC E
DEC IX
LD HL, CurCol
LD A, (HL)
DEC (HL)
OR A
JR NZ, InputLeftEnd
LD (HL), 15
DEC HL
DEC (HL)
InputLeftEnd:
PUSH IX
PUSH DE
RES TextInsMode, (IY + TextFlags)
JP InputKey
InputRight:
CALL InputResetCursor
POP DE
POP IX
POP BC
LD A, (IX)
OR A
JR NZ, InputRightNotZero
LD A, " "
InputRightNotZero:
b_call(_PutMap)
EI
LD A, E
CP B
JR Z, InputRightEnd
INC E
INC IX
LD HL, CurCol
LD A, (HL)
INC (HL)
SUB 15
JR NZ, InputRightEnd
LD (HL), 0
DEC HL
INC (HL)
InputRightEnd:
PUSH BC
PUSH IX
PUSH DE
RES TextInsMode, (IY + TextFlags)
JP InputKey
InputUp:
CALL InputResetCursor
POP DE
POP IX
POP BC
LD A, (IX)
OR A
JR NZ, InputUpNotZero
LD A, " "
InputUpNotZero:
b_call(_PutMap)
EI
LD A, E
SRL A ;Divide by 16, to see if there is a row to go up
SRL A
SRL A
SRL A
JP Z, InputCharEnd ;Cancel if on the top row
LD A, E
SUB 16
LD E, A
PUSH DE
LD HL, CurRow
DEC (HL)
LD DE, 16
OR A
PUSH IX
POP HL
SBC HL, DE
PUSH HL
POP IX
POP DE
RES TextInsMode, (IY + TextFlags)
JP InputCharEnd
InputDown:
CALL InputResetCursor
POP DE
POP IX
POP BC
LD A, (IX) ;Erase the cursor
OR A
JR NZ, InputDownNotZero
LD A, " "
InputDownNotZero:
b_call(_PutMap)
EI
LD A, E ;Check if there is any row below the one you're on now
SRL A ;Devide E by 16 to see the current row and store it to H
SRL A
SRL A
SRL A
LD H, A
LD A, B ;Devide B by 16 to see the maximum amount of rows
SRL A
SRL A
SRL A
SRL A
SUB H
JP Z, InputCharEnd ;If they are the same, quit
LD HL, CurRow
INC (HL)
DEC A
JR NZ, InputDownNoShift ;If you are not on the last row, it'll never have to shift <<
LD A, B ;Check if the cursor should go << aswell
AND $0F ;Get the colomn of the final character
LD HL, CurCol ;Get the colomn of the cursor
SUB (HL) ;If ColFin - ColCur < 0, no <<
JR NC, InputDownNoShift
NEG
PUSH BC
LD C, A
LD B, 0
PUSH IX
POP HL
OR A
SBC HL, BC
PUSH HL
POP IX
LD A, (CurCol)
SUB C
LD (CurCol), A
LD BC, 16
ADD IX, BC
POP BC
LD A, B
LD E, A
JP InputCharEnd
InputDownNoShift:
PUSH DE
LD DE, 16
ADD IX, DE
POP DE
LD A, E
ADD A, 16
LD E, A
JP InputCharEnd
InputEnd:
POP DE
POP IX
POP BC
DI
LD A, %00010011
OUT (3), A
IM 1
EI
RET
InputResetCursor:
XOR A
LD (CurTime), A
SET CurOn, (IY + CurFlags)
RET
NormalLUT: .DB "+-*/^", 0, 0, Lneg, "369)", 0, 0, 0, ".258(", 0, 0, 0, "0147,", 0, 0, "X", 0, Lstore, 0, 0, Lsquare, LInverse, 0
2ndLUT: .DB 0, "][", Llne, Lpi, 0, 0, 0, 0, 0, "w}", 0, 0, 0, LimagI, 0, 0, "v{", 0, 0, 0, 0, 0, 0, "u", Lexponent, 0, 0, "X", 0, 0, 0, 0, 0, 0, 0
AlphaLUT: .DB LQuote, "WRMH", 0, 0, "?", LTheta, "VQLG", 0, 0, ":ZUPKFC", 0, " YTOJEBX", 0, "XSNIDA"
LwrAlphLUT: .DB LQuote, "wrmh", 0, 0, "?", LTheta, "vqlg", 0, 0, ":zupkfc", 0, " ytojebx", 0, "xsnida"
Keygroups: .DB $FE, $FD, $FB, $F7, $EF, $DF, $BF, 0
; Outputs: B: Value from 0-4 indicating battery level (0 is critical)
GetBatteryLevel:
push af
in a, (2)
rlca ;Roll bit 7 into carry.
jr c, GetBatteryLevel_Not3Plus
in a, (2)
and 1
ld b, a
pop af
ret
GetBatteryLevel_Not3Plus:
ld b,3
GetBatteryLevelLoop:
ld a,b
sla a
sla a
sla a
sla a
sla a
sla a
or %00000110
out (6), a
in a, (2)
bit 0, a
jr z, GetBatteryLevel_Done
djnz GetBatteryLevelLoop
ld b,4
GetBatteryLevel_Done:
ld a, %110
out (6), a
pop af
ret
rrca
rrca
and $C0
push hl
inc hl
dec hl
pop hl
A_Times_DE:
;Input:
; A,DE
;Outputs:
; A is 0
; BC is not changed
; DE is not changed
; HL is the result
; z flag is set
; c flag is set if the input A is not 0
;Notes:
; If A is 0, 29 cycles
;Speed: 145+6n+21b cycles
; n=floor(log(a)/log(2))
; b is the number of bits in the number
; Testing over all values of A from 1 to 255:
; 313.7058824 average cycles
; Worst: 355
; Best : 166 (non trivial)
;Size: 25 bytes
ld hl,0 ;10
or a \ ret z ;9
cpl \ scf ;8
adc a,a ;4
jp nc,$+7 ;10 ;45
Loop:
add a,a ;4
jp c,$-1 ;10 ;14(7-n)
add hl,de ;11 ;11 (the rest are counted below)
add a,a ;4 ;4b
ret z ;5|11 ;5b+6
add hl,hl ;11 ;11b-11
jp p,$-4 ;21|20 ;20n+b
jp $-7
DE_Times_A:
;Inputs:
; DE and A are factors
;Outputs:
; A is not changed
; B is 0
; C is not changed
; DE is not changed
; HL is the product
;Time:
; 342+6x
;
ld b,8 ;7 7
ld hl,0 ;10 10
add hl,hl ;11*8 88
rlca ;4*8 32
jr nc,$+3 ;(12|18)*8 96+6x
add hl,de ;-- --
djnz $-5 ;13*7+8 99
ret ;10 10
A_Times_DE: ;Cycles ;Bytes
LD HL, 0 ;10 ;3
LD B, 8 ;7 ;2
A_Times_DE_Loop:
RRA ;4 ;1
JR NC, NoMult ;12/7 ;2
ADD HL, DE ;11 ;1
NoMult:
SLA E ;8 ;1
RL D ;8 ;1
DJNZ A_Times_DE_Loop ;13/8 ;3
RET ;10 ;1
; convert from reg8 to string
; input: a - reg8, b - 1 if signed, 0 if unsigned, hl - place to output to
; output: original place to output to
ITOA_8:
push hl
pop ix
push hl
push af
xor a
cp b
jr z, {@}
pop af
ld d, 127
cp d
jr c, {2@}
ld d, '-'
pop hl
ld (hl), d
inc hl
push hl
neg
jr {2@}
@
pop af
@
ld l, a
ld h, 0
ld d, 100
push af
xor a
ld b, 16
@
add hl,hl
rla
cp d
jp c, {@}
sub d
inc l
@
djnz {-2@}
ld a, l
add a, a
add a, a
add a, a
ld h, a
add a, a
add a, h
add a, l
add a, a
add a, a
ld d, a
pop af
sub d
ld d, a
ld a, l
cp 0
jr z, {@}
pop hl
add a, '0'
ld (hl), a
inc hl
push hl
@
ld a, d
ld l, a
ld h, 0
ld d, 10
push af
xor a
ld b, 16
@
add hl,hl
rla
cp d
jp c, {@}
sub d
inc l
@
djnz {-2@}
ld a, l
add a, a
add a, a
add a, l
add a, a
ld d, a
pop af
sub d
ld d, a
ld a, l
cp 0
jr z, {@}
pop hl
add a, '0'
ld (hl), a
inc hl
push hl
@
ld a, d
add a, '0'
pop hl
ld (hl), a
xor a
inc hl
ld (hl), a
push ix
pop hl
ret
DispNumBase32:
;Inputs:
; C is the base
; DEHL is the number to display
;Outputs:
; A, B, D, E is 0
; C is not changed
; HL points to the string
ld b,32
xor a
add hl,hl
rl e \ rl d
rla
cp c
jr c,$+4
inc l
sub c
djnz $-11
push bc
push de
push hl
add a,30h
cp 3Ah
jr c,$+4
add a,7
ld hl,(TempWord1)
dec hl
ld (TempWord1),hl
ld (hl),a
pop hl
pop de
pop bc
ld a,h
or l \ or d \ or e
jr nz,DispNumBase32
ld hl,(TempWord1)
ret
atoui16:
;Input:
; DE points to the string
;Outputs:
; HL is the result
; DE points to the byte after the number
;Destroys:
; A
; BC
; if the string is non-empty, BC is HL/10
;Size: 24 bytes
;Speed: 42+d(104+{0,9})
; d is the number of digits in the number
; max is 640 cycles for a 5 digit number
;Assuming no leading zeros:
;1 digit: 146cc
;2 digit: 250cc
;3 digit: 354cc or 363cc (avg: 354.126cc)
;4 digit: 458cc or 467cc (avg: 458.27cc)
;5 digit: 562cc or 571cc or 580cc (avg: 562.4104cc)
;avg: 544.81158447265625cc (544+13297/16384)
;===============================================================
ld hl,0
_:
ld a,(de)
sub 30h
cp 10
ret nc
inc de
ld b,h
ld c,l
add hl,hl
add hl,hl
add hl,bc
add hl,hl
add a,l
ld l,a
jr nc,-_
inc h
jp -_
ShiftScreenRight4:
;Shifts the graph screen right 4 pixels
ld hl,plotSScreen
ld c,64
xor a
ld b,12
rrd
inc hl
djnz $-3
dec c
jr nz,$-9
ret
ShiftScreenLeft4:
;Shifts the graph screen left 4 pixels
ld hl,plotSScreen+767
ld c,64
xor a
ld b,12
rld
dec hl
djnz $-3
dec c
jr nz,$-9
ret
;=====================================
DrawLine:
; H is X1
; L is Y1
; D is width
; E is height
; A is the method
; 0 = Pxl-Off
; 1 = Pxl-On
; 2 = PxlInvert
; 3 =
; +4 = Draw with Merth pattern
; +8 = Draw with Ray pattern
; IX points to the draw pattern
; *Patterns are read backwards. This can be easily adjusted.
; *Patterns are terminated by a -1
; *Patterns are the number of pixels to draw, followed by the number of pixels to ignore for the Merth Pattern
; For the Ray pattern, it is the number of rows to draw followed by the number to ignore.
;=====================================
di
res 5,(iy+33)
res 6,(iy+33)
bit 2,a
jr z,$+6
set 5,(iy+33)
bit 3,a
jr z,$+6
set 6,(iy+33)
and $F3 ;3^5=243=$F3
.db 01h \ cpl \ and (hl)
dec a
jr nz,$+5
.db 01h \ or (hl) \ nop
dec a
jr nz,$+5
.db 01h \ xor (hl) \ nop
ld (PlotLinePix+1),bc
ld a,-1
ld (PatternIncVar2),a
res 7,(iy+33)
ld a,(ix)
bit 6,(iy+33)
jr nz,$+3
inc a
ld (PatternIncVar),a
or a
call z,PatternNext
ld c,0
ld a,d
bit 7,a
jr z,$+7
neg
set 6,c
ld d,a
ld a,e
bit 7,a
jr z,$+7
neg
set 7,c
ld e,a
ld b,a
ex af,af'
ld a,c
exx
rla
ld de,12
ld bc,1
jr nc,$+5
ld de,-12
rla
jr nc,$+4
dec bc \ dec bc
exx
ld a,h
push hl
push bc
ld h,0
ld b,h
ld c,l
add hl,hl
add hl,bc
add hl,hl
add hl,hl
ld c,a
sra c
sra c
sra c
jp p,$+4
dec b
add hl,bc
ld bc,(DrawBufPtr)
add hl,bc
and 7
ld b,a
ld a,80h
jr z,$+5
rrca
djnz $-1
push hl
exx
pop hl
exx
ex af,af'
pop bc
pop hl
sla e
jr nz,$+12
ld b,d
call DrawLinePixel
call ChangeX
djnz $-6
ret
sla d
;a is the width/2
;d is width
;e is height
;b is the height
;c is the method
;h is X
;l is Y
DrawLineLoop:
call DrawLinePixel
sub d
jr c,subline
call ChangeY
djnz DrawLineLoop
ret
subline:
call ChangeX
add a,e
jr c,$+8
call DrawLinePixel
jp subline
call ChangeY
djnz DrawLineLoop
ret
ChangeY:
bit RayPattern,(iy+33)
call nz,PatternInc
exx
add hl,de
exx
inc l
bit 7,c
jr z,$+4
dec l \ dec l
ret
ChangeX:
ex af,af'
rrca
inc h
bit 6,c
jr z,$+6
dec h \ dec h \ rlca \ rlca
jr nc,$+5
exx
add hl,bc
exx
ex af,af'
ret
DrawLinePixel:
bit MerthPattern,(iy+33)
call nz,PatternInc
bit 7,(iy+33)
ret nz
push af
ld a,l
cp 64
jr nc,ExitDrawPixel
ld a,h
cp 96
jr nc,ExitDrawPixel
ex af,af'
exx
call PlotLinePix
exx
ex af,af'
ExitDrawPixel:
pop af
ret
RAMCode:
PlotLinePix equ $-RAMCode+RAMCodeLoc
push af
nop
or (hl)
ld (hl),a
pop af
ret
PatternInc equ $-RAMCode+RAMCodeLoc
push hl
push af
PatternIncVar equ 1+$-RAMCode+RAMCodeLoc
ld a,0
dec a
jr nz,EndPatternInc
PatternNext:
ld a,80h
xor (iy+33)
ld (iy+33),a
ld hl,PatternIncVar2
PatternIncVar2 equ 2+$-RAMCode+RAMCodeLoc
ld a,(ix-1)
inc a
jr nz,$+6
ld (hl),0
jr $-8
dec (hl)
dec a
jr z,PatternNext
EndPatternInc:
ld (PatternIncVar),a
pop af
pop hl
ret
PseudoRandWord:
;Outputs:
; BC was the previous pseudorandom number
; HL is the pseudorandom number
;f(n+1)=(241f(n)+257) mod 65536 ;65536
;181 cycles, add 17 if called
ld hl,(randSeed)
ld c,l
ld b,h
add hl,hl
add hl,bc
add hl,hl
add hl,bc
add hl,hl
add hl,bc
add hl,hl
add hl,hl
add hl,hl
add hl,hl
add hl,bc
inc h
inc hl
ld (randSeed),hl
ret
Advertisement