sub_F374 has caught my interest because it seems to be painting the LCD with the currently selected file's contents according to several state variables that I have not fully reverse-engineered.
The routine begins like this:
F374 sub_F374:
F374 BD F6 18 jsr clearHomeLCD_F618 ; Clear LCD set cursor pos 0
F377 FE 01 20 ldx word_120 ; XXX file related ???
F37A BD F3 D5 jsr sub_F3D5
F37D DF 4E stx word_4E ; scratch; /this/ keyboard scan column mask (rectus)
F37F FE 01 20 ldx word_120 ; XXX file related ???
...
word_120 has been vexing for me for some time. It's file-related and next to other file-related variables, but I haven't been able to make it out yet what it does. Maybe this will be an opportunity to find out.
...
0120 ?? ?? word_120: rmb 2 ; XXX file related ???
0122 ?? ?? curfileIns_122: rmb 2 ; XXX file related (current file insert ptr???) .0
0124 ?? ?? curfileEnd_124: rmb 2 ; XXX file related (current file ptr end char (one past last)???) .4
0126 ?? ?? curFileRgnLast_126:rmb 2 ; this file; file region end addr (inclusive)
0128 ?? ?? curFileRgnFirst_128:rmb 2 ; this file; file region start addr
012A ?? ?? ?? ??+aFileState_12A: rmb $30 ; XXX an array of 8 3-word file structures
...
These various file-related variables strike me as curious from a design perspective because they are essentially copies of stuff that is already in aFileState_12A and also in ROM in aFilePartitions_FB24, but just for the current file (as per thisFileNo_15D). I'm not sure why this apparent redundancy is done, but maybe that will become clearer later. (Or it may just be an oddity -- humans sometimes do inexplicable things.)
The sub_F3D5 is called early, just after loading X with the word_120 value, presumably as a parameter:
F3D5 sub_F3D5:
F3D5 DF 44 stx word_44 ; XXX scratch
F3D7 86 28 ldaa #40
F3D9 97 48 staa byte_48 ; XXX counter; 100/40
F3DB 18 FE 01 24 ldy curfileEnd_124 ; XXX file related (current file ptr end char (one past last)???) .4
F3DF 18 DF 42 sty word_42
F3E2 BD EC 80 jsr selectRAMpageForFile_EC80 ; select in the relevant RAM page based on file number (byte_15D)
F3E5 loop_F3E5:
F3E5 9C 42 cpx word_42
F3E7 27 2A beq loc_F413
F3E9 A6 00 ldaa 0,x
F3EB 81 0D cmpa #$D
F3ED 27 1E beq loc_F40D
F3EF 7A 00 48 dec byte_48 ; XXX counter; 100/40
F3F2 27 03 beq loc_F3F7
F3F4 08 inx
F3F5 20 EE bra loop_F3E5
F3F7 loc_F3F7:
F3F7 BD F4 1A jsr sub_F41A
F3FA 29 11 bvs loc_F40D
F3FC loc_F3FC:
F3FC 09 dex
F3FD A6 00 ldaa 0,x
F3FF BD F4 1A jsr sub_F41A
F402 29 09 bvs loc_F40D
F404 9C 44 cpx word_44 ; XXX scratch
F406 26 F4 bne loc_F3FC
F408 DE 44 ldx word_44 ; XXX scratch
F40A C6 27 ldab #$27 ; '''
F40C 3A abx
F40D loc_F40D:
F40D BD EC 79 jsr selectRAMPage0_EC79 ; select 32 KiB RAM page 0
F410 08 inx
F411 0A clv
F412 39 rts
F413 loc_F413:
F413 BD EC 79 jsr selectRAMPage0_EC79 ; select 32 KiB RAM page 0
F416 DE 44 ldx word_44 ; XXX scratch
F418 0B sev
F419 39 rts
As annotated, the byte_48 location seemed to be a counter of sorts based upon cross-references and was loaded either with 100 or 40. 40 seems coincidental with the 40 columns of LCD. I don't know what 100 is for.
But the loop "loop_F3E5" is particularly interesting since it seems to be whizzing through a file (starting at word_120) and looking for a carriage return (0x0d). If found, it will go one past that character and clear the V bit (a common technique in this firmware to indicate 'success') and leave.
If it does not find in within the 40 chars, then it starts to look backwards (up to the point at word_120) for some sort of characterization provided by sub_F41A:
F41A sub_F41A:
F41A 81 0D cmpa #$D
F41C 27 0E beq loc_F42C
F41E 81 09 cmpa #9
F420 27 0A beq loc_F42C
F422 81 20 cmpa #$20 ; ' '
F424 27 06 beq loc_F42C
F426 81 2D cmpa #$2D ; '-'
F428 27 02 beq loc_F42C
F42A 0A clv
F42B 39 rts
F42C loc_F42C:
F42C 0B sev
F42D 39 rts
Which is pretty clear to indicate 'tab, or cr, or space, or hyphen'. In other words, traditional line breaking characters.
So sub_F3D5 seems to actually be 'find end of display line'. It does it by first hunting for a CR within 40 chars, and if not found, search backwards for a line-breaking character, and if not found, just give up and break it at 40 characters.
So if one was to compose a document with the word: "pneumonoultramicroscopicsilicovolcanoconiosis" (a specific lung disease caused by inhaling quartz dust), or refer to Lake Chargoggagoggmanchauggauggagoggchaubunagungamaugg (in Michigan), then you'd have to suffer a hard break in the middle of the word. But even if you don't suffer "hippopotomonstrosesquippedaliophobia" (fear of long words) you'll almost always still be OK with a 40-char line. Though for the mid 90's I think they really should have tried to splurge for 80. 80 looks more like a typewritten page would be. Though such a display would have been a tight fit in this unit. On the other hand, you can't index an 80x4 display with one byte, so there would be a price to pay in code.
Getting back to sub_F374, the logic is a loop over characters in the file, spewing them to the LCD, starting with the location word_120, until the logical end-of-line is found, then advancing to the next line and continue spewing. This happens until 4 lines are filled, or until the end-of-file is reached. So it seems that word_120 is 'file position at start of screen'. Annotated, the function now looks like this:
F374 ; re-paint LCD for current file state
F374 displayCurFile_F374:
F374 BD F6 18 jsr clearHomeLCD_F618 ; Clear LCD set cursor pos 0
F377 FE 01 20 ldx curfileStartOfScreen_120 ; XXX file related (current file screen start ptr???) .2
F37A BD F3 D5 jsr findNextLineStart_F3D5 ; find start of next display line considering breaking chars; X = cur file.2; V if no more lines; clear if next line start valid
F37D DF 4E stx scratchw_4E ; save start of /next/ line
F37F FE 01 20 ldx curfileStartOfScreen_120 ; XXX file related (current file screen start ptr???) .2
F382 86 01 ldaa #1
F384 97 4C staa scratchby_4C ; (used for tracking row)
F386 loopLine_F386:
F386 86 01 ldaa #1
F388 97 60 staa scratchby_60 ; (used for tracking col)
F38A loopChar_F38A:
F38A BC 01 22 cpx curfileIns_122 ; is this char at the insertion point? remember (row,col) for it
F38D 26 08 bne cont_F397 ; nope; keep spewing chars
F38F 96 4C ldaa scratchby_4C ; row
F391 97 6C staa lcdcpRow1_6C ; 1-relative LCD cursor pos row
F393 96 60 ldaa scratchby_60 ; col
F395 97 6B staa lcdcpCol1_6B ; 1-relative LCD cursor pos col
F397 cont_F397:
F397 BC 01 24 cpx curfileEnd_124 ; finished entire file? leave
F39A 27 2A beq showCapLockLeave_F3C6
F39C BD EC 80 jsr selectRAMpageForFile_EC80 ; select in the relevant RAM page based on file number (byte_15D)
F39F A6 00 ldaa 0,x ; get char in file
F3A1 BD EC 79 jsr selectRAMPage0_EC79 ; select 32 KiB RAM page 0
F3A4 BD F6 2D jsr xlatShowChar_F62D ; put it on the LCD (cp will advance automatically)
F3A7 08 inx ; next char
F3A8 7C 00 60 inc scratchby_60 ; next col
F3AB 9C 4E cpx scratchw_4E ; is it now at the start of the next display line?
F3AD 26 DB bne loopChar_F38A ; nope; keep spewing chars
F3AF 96 4C ldaa scratchby_4C ; row
F3B1 81 04 cmpa #4 ; was this the 4th (last) line? leave if so
F3B3 27 11 beq showCapLockLeave_F3C6
F3B5 7C 00 4C inc scratchby_4C ; next row
F3B8 3C pshx ; save file ptr while we fiddle with things
F3B9 BD F4 2E jsr lcdSetCPatLineA ; set LCD cursor position at start of line A
F3BC DE 4E ldx scratchw_4E ; get the last end-of-line and hunt for next end-of-line
F3BE BD F3 D5 jsr findNextLineStart_F3D5 ; find start of next display line considering breaking chars; X = cur file.2; V if no more lines; clear if next line start valid
F3C1 DF 4E stx scratchw_4E ; save the next end-of-line
F3C3 38 pulx ; restore file ptr while we continue on the next line
F3C4 20 C0 bra loopLine_F386
F3C6 showCapLockLeave_F3C6:
F3C6 13 A1 01 0A brclr bCapsLock_A1 1 leave_F3D4 ; flag; CAPS lock in effect
F3CA C6 9F ldab #159 ; cursor at end of screen
F3CC BD F7 60 jsr commonSetCursorPosB_F760 ; common set cursor position (abs pos in B)
F3CF C6 0F ldab #$F ; solid block char
F3D1 BD F6 74 jsr sendLCDbyteB_F674 ; send byte in B to LCD (w/ctrl as per 0x5b)
F3D4 leave_F3D4:
F3D4 39 rts
And that is how we do that!
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.