-
20230220a -- Hardware whoopsie
02/23/2023 at 14:31 • 0 commentsWhile whizzing through the code looking for spots to fixup, I came across an error in my previous hardware inference. It is in the sendLCDnybble_F68F routine. I had believed that port D was used for the LCD OC2/1 lines on PDb1,0. However upon closer inspection I see that it is in fact in those positions of the keyboard column latch at $8000 -- /not/ Port D. Well, I supposed that answers my question about by the LCD R/~W line was on $8000 bit 2, and what might be at bits 1 and 0.
-
20230219c -- ROM test file
02/23/2023 at 00:01 • 3 commentsWhile whizzing through the code trying to scrounge verified keyboard scan codes and flags, I found some some buried treasure in the form of an undocumented test routine. It's not that exciting -- it just fills the current file with some sample text.
F76D ; load the ROM test file into the current file F76D spewROMtestFile_F76D: F76D BD F6 18 jsr clearHomeLCD_F618 ; Clear LCD set cursor pos 0 F770 CE FB D5 ldx #aAreYouSureYouWantToOverwrite ; "Are you sure you want to overwrite" F773 BD F6 69 jsr showText_F669 ; show nts text @ X F776 BD F7 4E jsr setcpLine1_F74E ; set cursor Line 1 F779 CE FB F8 ldx #aThisFileWithTheRomTestFile?YN ; "this file with the ROM test file? (y/n)" F77C BD F6 69 jsr showText_F669 ; show nts text @ X F77F waitKey_F77F: F77F BD E5 A0 jsr scanKbd_E5A0 ; do key scan and enqueue F782 BD EB EE jsr dequeueKbdScanCode_EBEE ; pull scan code A (rowno|colno) from keyboard buffer; V set if empty, clear if valid F785 29 F8 bvs waitKey_F77F F787 81 22 cmpa #$22 ; 'y' scan code F789 26 14 bne leave_F79F F78B BD EB 9B jsr clearThisFile_EB9B ; clear file by resetting pointers F78E CE FB 44 ldx #a1AlphasmartIsE ; "1 AlphaSmart is easy to use and rugged."... F791 loop_F791: F791 A6 00 ldaa 0,x F793 27 0A beq leave_F79F F795 08 inx F796 3C pshx F797 BD F3 07 jsr sub_F307 F79A 38 pulx F79B 29 02 bvs leave_F79F F79D 20 F2 bra loop_F791 F79F leave_F79F: F79F 39 rts
You get there from scan code 0x21 and with a flag byte_62 being set. Since this is undocumented, I can't figure out what 0x21 is here, but it's still interesting because the implementation of spewROMtestFile_F76D should give me some further clues about file related structures. In particular, the loop_F791 is just pulling a character from ROM until nul is found, and calling sub_F307 with it. So that almost certainly is a 'append character to file' routine. That will be interesting.
Also, long ago I had mentioned finding what looked like an ASCII table that might give a clue to key mapping, but I couldn't find references to it. That turns out to be a red herring; those ASCII sequences are just part of the ROM test file. So I'll fix up that stuff to reflect the new findings.
However, this has given me a new idea: this product emulates a keyboard. It does this to transfer files, but it also acts just like an ordinary keyboard when connected to the PC/Mac. I don't know anything about Mac ADB, but I do have some experience with PS/2 from my TRS-80 emulator days. So I think that maybe I can find the table of PS/2 scan codes and maybe work backwards from there to figure out the keyboard matrix better. Food for thought....
-
20230219b -- Actual File Sending
02/22/2023 at 16:19 • 0 commentsHaving found the send speed setting, I got a bit interested in the file sending process itself. Tracing back a reference to "Sending....Press any key to stop. " text, I find sub_F013:
F013 ; XXX prepare to send (flags and prompt) F013 sub_F013: F013 FE 01 28 ldx thisFileRgnFirst_128 ; this file; file region start addr F016 DF 67 stx word_67 ; XXX file sending related? ptr to next char to send? F018 14 6D FF bset byte_6D $FF ; XXX flag? is file sending??? F01B 13 8B 01 05 brclr byte_8B 1 loc_F024 ; XXX flag? F01F 14 8C FF bset byte_8C $FF ; XXX flag? F022 20 03 bra loc_F027 F024 loc_F024: F024 14 58 FF bset byte_58 $FF ; XXX flag? F027 loc_F027: F027 7F 00 A2 clr byte_A2 ; XXX flag? cleared in file sending??? F02A BD F7 4E jsr setcpLine1_F74E ; set cursor Line 1 F02D CE FE F9 ldx #aSending____pressAnyKeyToStop_ ; "Sending....Press any key to stop. " F030 BD F6 69 jsr showText_F669 ; show nts text @ X F033 39 rts
This sets up flags in a currently unknown manner prior to presenting the 'sending' prompt. The most interesting thing I found at this point is word_67 which seemed to be a 'current pointer in file' for the sending process.
F460 ; XXX get next char to send in A; V set if no more chars to send, clear if valid F460 getNextCharToSend_F460: F460 DE 67 ldx word_67 ; XXX file sending related? ptr to next char to send? F462 BC 01 24 cpx curfileEnd_124 ; XXX file related (current file ptr end char (one past last)???) .4 F465 27 15 beq leaveDone_F47C ; finished F467 BD EC 80 jsr selectRAMpageForFile_EC80 ; select in the relevant RAM page based on file number (byte_15D) F46A A6 00 ldaa 0,x ; get char for file F46C BD EC 79 jsr selectRAMPage0_EC79 ; select 32 KiB RAM page 0 F46F 08 inx F470 DF 67 stx word_67 ; update send pointer F472 81 09 cmpa #9 ; ascii < 9 translates to '?' F474 2D 08 blt translateUnusual_F47E F476 85 80 bita #$80 ; high ascii translates to '?' F478 26 04 bne translateUnusual_F47E F47A leaveValid_F47A: F47A 0A clv F47B 39 rts F47C leaveDone_F47C: F47C 0B sev F47D 39 rts F47E translateUnusual_F47E: F47E 86 3F ldaa #'?' F480 20 F8 bra leaveValid_F47A
This appears to be relatively straight-forward: verify not out-of-bounds, then get a character at the current 'send' location @ word_67, translate any weird ones (I don't think this should happen normally), and return. Overflow V is used to indicate failure (this is a common convention in these routines).
-
20230219a -- File Sending Speed
02/22/2023 at 13:51 • 0 commentsWhile whizzing through the keyboard stuff, there is some special handling of some keystrokes. This is by scan code, so it's difficult for me to puzzle out what they are. One exception, though, is for setting the 'send speed'. There is menu text showing the current speed and allowing changing the speed.
F034 changeSendSpeed_F034: F034 BD F6 18 jsr clearHomeLCD_F618 ; Clear LCD set cursor pos 0 F037 CE FD 76 ldx #aToChangeSendSp ; "To change Send speed, type 1, 2, 3 or 4"... F03A BD F6 69 jsr showText_F669 ; show nts text @ X F03D BD F7 4E jsr setcpLine1_F74E ; set cursor Line 1 F040 CE FD 9F ldx #a1VerySlow2Slow ; " 1: VERY Slow 2: Slow" F043 BD F6 69 jsr showText_F669 ; show nts text @ X F046 BD F7 54 jsr setcpLine2_F754 ; set cursor Line 2 F049 CE FD BF ldx #a3FastDefault4F ; " 3: Fast(default) 4: Fastest" F04C BD F6 69 jsr showText_F669 ; show nts text @ X F04F BD F7 5A jsr setcpLine3_F75A ; set cursor Line 3 F052 CE FD E2 ldx #aCurrentSetting ; "Current setting is " F055 BD F6 69 jsr showText_F669 ; show nts text @ X F058 B6 01 5C ldaa kbdemuSpeed_15C ; XXX keyboard transfer speed (0, 1, 2, c8???) F05B 81 00 cmpa #0 ; 0 is very slow F05D 26 04 bne cont_F063 F05F C6 31 ldab #'1' F061 20 16 bra showcurspeed_F079 F063 cont_F063: F063 81 01 cmpa #1 ; 1 is slow F065 26 04 bne cont_F06B F067 C6 32 ldab #'2' F069 20 0E bra showcurspeed_F079 F06B cont_F06B: F06B 81 02 cmpa #2 ; 2 is fast F06D 26 04 bne cont_F073 F06F C6 33 ldab #'3' F071 20 06 bra showcurspeed_F079 F073 cont_F073: F073 81 C8 cmpa #$C8 ; '+' ; c8 is fastest F075 26 19 bne loc_F090 ; unknown setting, force to 1, slow F077 C6 34 ldab #'4' F079 showcurspeed_F079: F079 BD F6 74 jsr sendLCDbyteB_F674 ; send byte in B to LCD (w/ctrl as per 0x5b) F07C waitKey_F07C: F07C BD E5 A0 jsr scanKbd_E5A0 ; do key scan and enqueue F07F BD EB EE jsr dequeueKbdScanCode_EBEE ; pull scan code A (rowno|colno) from keyboard buffer; V set if empty, clear if valid F082 29 F8 bvs waitKey_F07C F084 81 5E cmpa #$5E ; scan code for '1' F086 26 04 bne cont_F08C F088 86 00 ldaa #0 F08A 20 18 bra storeSpeed_F0A4 F08C cont_F08C: F08C 81 5D cmpa #$5D ; scan code for '2' F08E 26 04 bne cont_F094 F090 loc_F090: F090 86 01 ldaa #1 F092 20 10 bra storeSpeed_F0A4 F094 cont_F094: F094 81 5C cmpa #$5C ; scan code for '3' F096 26 04 bne cont_F09C F098 86 02 ldaa #2 F09A 20 08 bra storeSpeed_F0A4 F09C cont_F09C: F09C 81 51 cmpa #$51 ; scan code for '4' F09E 26 07 bne leave_F0A7 F0A0 86 C8 ldaa #$C8 ; '+' F0A2 20 00 bra *+2 F0A4 storeSpeed_F0A4: F0A4 B7 01 5C staa kbdemuSpeed_15C ; XXX keyboard transfer speed (0, 1, 2, c8???) F0A7 leave_F0A7: F0A7 39 rts
Most of this is simply emitting text, translating a setting value to a textual equivalent for presentation, and waiting for a keystroke to change the value. I am pretty sure that loc_15C is the current keyboard emulation speed, since it drives the text for the current setting and is updated when we change it. So I renamed it to kbdemuSpeed_15C.
Since in this limited case we have well-know keys that are switched on in a understandable way, we can learn at least a few key scan codes for '1' - '4'.
It's a curiosity as to why the setting value is 0, 1, 2, and 0xc8 (???). Maybe that will make sense later.
This routine is called from the keyboard handler at EE18:
EE08 loc_EE08: EE08 81 56 cmpa #$56 EE0A 27 25 beq loc_EE31 EE0C 81 21 cmpa #$21 EE0E 27 0E beq loc_EE1E EE10 81 61 cmpa #$61 EE12 27 17 beq loc_EE2B EE14 81 4D cmpa #$4D ; scan code for 'S' EE16 26 27 bne loc_EE3F EE18 BD F0 34 jsr changeSendSpeed_F034 EE1B 7E EE DA jmp loc_EEDA
and since the manual states that option-clover-S is the sequence to get into the speed menu, we can infer that 0x4D is likely the scan code for 'S'.
-
20230218b -- Here, here!
02/22/2023 at 04:21 • 0 commentsIt's a peculiar Apple-ism of using an output string of "Here" for printf()-style debugging. (The founders were ex-Apple, so I'm not surprised.) Interestingly, there are two routines in the code that print out 'Here1' and 'Here2'.
debugHere1_F5D5
debugHere2_F5DDDebug Here 1 is dead code -- no references. However Debug Here 2 is referenced in the scanKbd_E5A0 routine:
E5E0 BD F5 7B jsr colMaskToColNo_F57B ; XXX col mask to col no; X is col mask; ret A = col no; V set if no col (done scanning) E5E3 29 7A bvs bug_E65F ; XXX cannot convert col mask to col no; bug? ... E65F bug_E65F: E65F BD F5 DD jsr debugHere2_F5DD ; Here2 related; a bug found E662 7E E5 A8 jmp loopNextKbdCol_E5A8
So I guess the authors were still concerned about the possibility of colMaskToColNo failing, or just forgot to take it out.
-
20230218a -- 0x8000 double duty bit 2
02/22/2023 at 04:18 • 0 commentsOne thing unresolved bit of the LCD is the R/~W line. I had largely assumed that the display was write only in this product, but I was quite wrong as reading is needed at least to poll the 'busy' bit in the status register. I had found the readLCDnybble function a while back, but at that time 0x8000 was a mystery to me until I found that it was for keyboard column selection. So why is it used in the LCD routine. I believe that it serves double duty. In this case, bit 2 is also connected to LCD R/~W line.
EC45 ; LCD read nybble; return PD in A (shifted LCD data into b5-3) EC45 readLCDnybble_EC45: EC45 86 03 ldaa #3 EC47 97 09 staa DDRD_9 ; DDRD: b1, b0 output; others input EC49 86 04 ldaa #4 EC4B B7 80 00 staa $8000 ; XXX b2 of 8000 seems to do double-duty as R/~W for LCD EC4E 14 00 80 bset PORTA_0 $80 ; PORTA: b7 high EC51 96 08 ldaa PORTD_8 ; PORTD: all data bits EC53 15 00 80 bclr PORTA_0 $80 ; PORTA: b7 low EC56 14 09 FF bset DDRD_9 $FF ; DDRD: all pins output EC59 7F 80 00 clr $8000 ; XXX b2 of 8000 seems to do double-duty as R/~W for LCD EC5C 15 08 3C bclr PORTD_8 $3C ; PORTD: b5,4,3,2 low EC5F 39 rts
I don't know why bit 2 in particular; this might imply there being double duty on some of the other lines as well. Or maybe it was just convenient in laying out the traces.
-
20230217b -- Keyboard Indicators
02/22/2023 at 01:12 • 0 commentsWhile whizzing through the code, I did notice an interesting 'set cursor position' call to set it at the end of the screen (at position 159, or 9Fh). Once set, the character 0x0f is sent. The datasheet for the LCD indicates that 0x0f is a solid block.
F3C6 loc_F3C6: F3C6 13 A1 01 0A brclr byte_A1 1 leave_F3D4 ; F3CA C6 9F ldab #$9F ; cursor at end of screen F3CC BD F7 60 jsr commonSetCursorPos_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
The user manual shows that a solid block in the last screen position is the Caps Lock indicator. Since the code to put this char in this place is controlled by the state of byte_A1 (previously marked as a flag of sorts), I am concluding that this location is the Cap Lock flag. Aside from understanding this local bit of code, cross-referencing that location to other places should give some more insight into keyboard handling.
There are apparently meant to be other keyboard status indicators as well, but I haven't located them yet.
-
20230217a -- Flags
02/21/2023 at 15:22 • 0 commentsWhile whizzing through the code, I noticed a pattern in the IRAM section: a byte location that is cleared or set to 0xff (though either of two ways), and tests of bit 0. So I conclude that these are 'flags'. There's a bunch of them, so I went through the various byte sized locations and did a cross reference to find how they were used. If they fit into the pattern of 'clear, set to 0xff, branch test on set or clear' only, then I marked them as XXX flag??? so that would propagate through the listing.
A typical cross-reference example is for byte_6D:
Type Address Text ---- ------- ---- w sub_E068:loc_E07F clr byte_6D ; XXX flag? r sub_E489:loc_E4A0 brset byte_6D 1 loc_E4C5; XXX flag? r sub_E6BD+5E brclr byte_6D 1 loc_E74C; XXX flag? r sub_E6BD+9C brset byte_6D 1 loc_E760; XXX flag? w sub_E842 clr byte_6D ; XXX flag? r sub_F013+5 bset byte_6D $FF ; XXX flag? r sub_F26C+4 brset byte_6D 1 loc_F286; XXX flag?
It's interesting that these bools are typically set/cleared all bits on (bset 0xff) or off (clr), but are just tested at bit 0 (brset/brclr 1). This may just be a matter of taste. It's interesting also that with so many 'flag' bytes, that the authors didn't pack them into bits. The instructions to do so are there, and that would have liberated some RAM. Maybe there is a reason (it doesn't seem to be code size, though, since clr is 3 bytes, and bclr is also 3 bytes on this page 0 memory), or maybe just taste or there simply wasn't sufficient impetus. At any rate, it makes my job a bit easier to have one flag per address reference.
On the other hand, there are some examples of the alternative implementation, e.g. at location byte_58:
Type Address Text ---- ------- ---- r sub_E489:loc_E4C1 bset byte_58 1 ; XXX flag? r sub_E6BD:loc_E717 brclr byte_58 1 loc_E6ED; XXX flag? r sub_E84F+5F brclr byte_58 1 loc_E8C2; XXX flag? r sub_F013:loc_F024 bset byte_58 $FF ; XXX flag? r sub_F26C:loc_F2BE bset byte_58 $FF ; XXX flag? r sub_F26C+60 bset byte_58 $FF ; XXX flag? w sub_F26C:loc_F2D1 clr byte_58 ; XXX flag?
Here we can see a mixture of the '0xff' style and also the 'bset 1' style. Testing is still the 'brset/brclr 1' style, so it's the same concept of 'byte as bool'. So this could suggest different programmers working on different parts of the code (or reusing old code for parts written by a different programmer, or maybe yourself when you had different sensibilities). So there were many hands involved in the code base.
Other examples of the 'many hands' hypothesis are at byte_4a:
Type Address Text ---- ------- ---- r sub_E6BD+F2 bset byte_4A 1 ; XXX flag? w sub_EAA7+5 staa byte_4A ; XXX flag? r sub_F26C brclr byte_4A 1 loc_F2BE; XXX flag? w sub_F26C:loc_F2BB clr byte_4A ; XXX flag? w sub_F26C+5D clr byte_4A ; XXX flag? r sub_F2D6 brclr byte_4A 1 loc_F2EE; XXX flag? w sub_F2D6:loc_F2EB clr byte_4A ; XXX flag?
where an explicit staa is used to set the flag true. Though this one is possibly explainable because the surrounding code already had an 0xff in the A reg, so this save a byte of program space as opposed to the bset method. This might just be parsimony.
There's some other cases such as byte_a1 which uses explicit load/store instead of the bset/clr, and also byte_a3 which toggles with eor (although that particular flag seems to be unused by anything).
Differences in style like these are interesting to me because they are artifacts of the team that created the product.
-
20230216c -- File RAM Page Selection
02/20/2023 at 22:01 • 0 commentsEarlier I mentioned the discovery of the 'file partition table', but noted that there is not an indication of page number, and speculated that there must be some routine or table somewhere that provides that additional data. I also speculated that it might be based on a switch-like code structure. I was wrong on both accounts.
It turns out there is a little bit of cleverness in how a file number is translated to a RAM page, and it relies on the file number being human friendly and the file sizes being roughly a geometric progression.
The routine for mapping file no to RAM page number is here:
EC80 ; select in the relevant RAM page based on file number (byte_15D) EC80 selectRAMpageForFile_EC80: EC80 8D F7 bsr selectRAMPage0_EC79 ; select 32 KiB RAM page 0 EC82 B6 01 5D ldaa byte_15D ; current file number (1-8) EC85 81 08 cmpa #8 EC87 24 04 bcc oobFileNo_EC8D ; (file no is bonkers) EC89 44 lsra ; (translate 1-8, to 0-3 with nifty math) EC8A loc_EC8A: EC8A 8D D4 bsr selectRAMPageA_EC60 ; select 32 KiB RAM page as per A (0-3) EC8C 39 rts EC8D oobFileNo_EC8D: EC8D 86 03 ldaa #3 ; (saturate to page 3) EC8F 20 F9 bra loc_EC8A
So, RAM page 0 has one file, page 1 has two files, page 2 has two files, and page 3 has 3 files. Because the file numbers are human friendly and 1-relative, the numbers 1-8 when shifted down map to the sequence: 0,1,1,2,2,3,3,3. In a 'perfect' world this would mean that page 3 has 4 8 KiB 'files', but instead we have two ~ 12 KiB files and one residual ~ 8 KiB file and no 4th file.
So, pretty clever. In modernity we tend to do less of cleverness of this sort because it is brittle. What if the product design changed such that the various file sizes did not fit this convenient approximate progression? Is it also not scalable; what if we want 16 files? This design requires that file sizes ever diminish so as to preserve the logarithmic mapping, and to extend this design would imply going to a farcically small file size rather quickly.
-
20230216b -- "Files"
02/20/2023 at 16:34 • 1 commentThe gist of this unit is that you type text into a discrete 'file' and then you can edit and later transfer to a separate computer via the keyboard emulation. While whizzing through the code doing other things, various strings caught my eye, such as:
FCFD 50 65 72 66+aPerformingEmer:fcc "Performing emergency recovery of" FCFD 6E 67 20 65+ fcb 0 FD1E 66 69 6C 65+aFile: fcc "file " FD1E 20 00 fcb 0 FD29 46 69 6C 65+aFileIsFull_Use:fcc "File is full. Use another file or" FD29 66 75 6C 6C+ fcb 0 FD4C 73 65 6E 64+aSendDataToYour:fcc "send data to your computer." FD4C 61 20 74 6F+ fcb 0 FDF6 41 72 65 20+aAreYouSureYo_0:fcc "Are you sure you want to delete" FDF6 73 75 72 65+ fcb 0 FE16 61 6C 6C 20+aAllTheDataInThisFile?YN:fcc "all the data in this file?(y/n)" FE16 64 61 74 61+ fcb 0 FE36 41 72 65 20+aAreYouSureYouWantToPermanently:fcc "Are you sure you want to PERMANENTLY" FE36 73 75 72 65+ fcb 0 FE5B 65 72 61 73+aEraseAllTheDataInThisFile?YN:fcc "erase all the data in this file?(y/n)" FE5B 6C 20 74 68+ fcb 0
I had already associated all these with their referring locations in the code, but the file system itself has not been worked out. One thing I noticed in the 'start' initialization code (and one other place in the keyboard scan routine) is a call this:
EB74 sub_EB74: EB74 CE 01 2A ldx #$12A EB77 18 CE FB 24 ldy #$FB24 EB7B loop_EB7B: EB7B 18 EC 00 ldd 0,y EB7E ED 00 std 0,x EB80 ED 02 std 2,x EB82 ED 04 std 4,x EB84 C6 06 ldab #6 EB86 3A abx EB87 C6 04 ldab #4 EB89 18 3A aby EB8B 8C 01 58 cpx #$158 EB8E 25 EB bcs loop_EB7B EB90 86 01 ldaa #1 it EB92 B7 01 5D staa byte_15D EB95 BD EA F9 jsr sub_EAF9 ; XXX file open related EB98 8D 01 bsr sub_EB9B ; XXX file open related EB9A 39 rts
Which seems to be copying an array of 2-word structures in ROM to an array of 3-word structures in RAM. (And the elements might not be words; the code might just be trying to bulk transfer more efficiently. We'll find out later.) As per the terminating condition (less than $0158), this means there are eight entries.
The fact that the source is 2-word and the dest is 3-word suggests that the extra word is some ephemeral quantity, hence not in the ROM image.
FB24 word_FB24: FB24 01 60 fdb $160 FB26 7F FF fdb $7FFF FB28 01 00 fdb $100 FB2A 3F FF fdb $3FFF FB2C 40 00 fdb $4000 FB2E 7F FF fdb $7FFF FB30 01 00 fdb $100 FB32 3F FF fdb $3FFF FB34 40 00 fdb $4000 FB36 7F FF fdb $7FFF FB38 01 00 fdb $100 FB3A 2F FF fdb $2FFF FB3C 30 00 fdb $3000 FB3E 5F FF fdb $5FFF FB40 60 00 fdb $6000 FB42 7F DE fdb $7FDE
Just an intuition: knowing that the external RAM is mapped from 0x100-0x7fff, could these be the file partitions? In particular, the first one starts at 0x0160, which is the first byte after all referenced RAM that I have found so far. Whereas the others start at 0x0100, which is the start of external RAM disregarding the system usage. So my hypothesis is that these are the file partition definitions, as [start,end]. This jibes with my earlier observation of 'page 0 has system variables, and is usually selected in, except in specific, localized cases'. I know also that this device had some fixed number of 'files'.
I'm embarrassed to admit that in my enthusiasm to hack that it didn't occur to me to first download the user manual for this contraption! So, doing so, I find that yes there are 8 'files', of varying maximal sizes that you cannot change. The manual expresses them in terms of 'pages' of text, but later also states that there is "a total capacity of 64 pages, or 128,000 bytes". So the values are approximate, based on 2,000 char/page. Computing from this table:
File# Start End Size Manual Stated Size 1 0160 7FFF 32,416 16 pages (32,000 char) 2 0100 3FFF 16,128 8 pages (16,000 char) 3 4000 7FFF 16,384 8 pages (16,000 char) 4 0100 3FFF 16,128 8 pages (16,000 char) 5 4000 7FFF 16,384 8 pages (16,000 char) 6 0100 2FFF 12,032 6 pages (12,000 char) 7 3000 5FFF 12,288 6 pages (12,000 char) 8 6000 7FDE 8,158 4 pages ( 8,000 char)
This coincidence is too strong to ignore, so I think this is the file partition table. Some observations:
- only the first field from ROM (start address) is copied to RAM, and copied into all three RAM structure entries. The end address is not. This suggests to me that the three RAM file entries might be 'start', 'current end', 'current position'. This is purely a hunch. Further discoveries could negate that hypothesis.
- the first entry offsets at 0x0160, which as mentioned is the start of otherwise unreferenced RAM. So that 'file' is probably on RAM page 0. The others start at 0x0100. This is consistent with the first RAM page having system variables, and the others being just user data (files). It also is consistent with the hypothesis that the 'quiescent' state might be to keep page 0 selected so those variables are available in the general case. Maybe. Many of the system variables are in the IRAM 0x40-0xbf which doesn't require paging.
- this table does not indicate what RAM page these files are on. Our human biases will easily assume that these are sorted, and that file 1 is on page 0, files 2,3 are on page 1, files 4,5 are on page 2, and files 6,7,8 are on page 3. This is reasonable, but the computer does not share these biases, so somewhere there is some logic or a table mapping file number to mapped RAM page. As few files as there are, it could be done in logic rather than a table. I'll have to be on the lookout for some 'switch' like constructs that select RAM page mappings from file numbers.
Having the manual in-hand is useful also in that it lists all the control codes and F-key functions. Well, the documented ones. There are clearly two magic buttons that you can hold down when powering the unit on that do things that are not documented in the manual. Nothing too exciting -- invoking a memory test and clearing all memory. But still.
Also, the manual mentions password protection of files. This is default 'off', but you are meant to contact customer support to get the 'master password' that will unlock the feature. Then your files become password protected with a default of 'secret'. Now this is amusing! However I don't think that feature is in this firmware because the prompts referenced in the manual do not exist in the image. So maybe the manual I have is for a later version than this v2.03 device. Oh well. That scheme would have been fun to pick apart!