Home | About | Collections | Stories | Help! | News & Links | Friends | Lets Talk! | Events & Visiting | Search

Canon Cat: Enabling Forth (by Dwight Elvey)

cat.jpg
Back to Main page on Canon Cat

The following is a nifty guide to enabling Forth on your Canon Cat, submitted by Dwight Elvey. Find the more readably formatted file in text here. Also don't miss Dwight's guided tour of the Cat movie.


Canon Cat, Starting Forth mode:

highlight the string:


Enable Forth Language


Then do: front, answer


Then: shift, usefront, space


You are now in Forth.


You need to do: -1 wheel! savesetup re


Front the editor, use the setup to set the keyboard to ascii
so that you can type the characters < and > with
shift , and shift .


Do a usefront disk.
It will save to the disk so that it will be ready
the next boot with just the: shift, usefront, space
to restart Forth.


To undo the Forth mode: Forth? off 0 wheel! re


 Use care while in Forth mode as usefront shift : will
format the disk ( a good idea to make a backup or
at least remove the disk while experimenting )


If you want to do a system check from Forth use
the word main-test.To break from the test mode,
one needs to reboot the machine.


 I recommend creating a clean new disk to store work
on. You can write code using the editor and then compile
the code by marking it and using
front answer while in Forth mode. You can clean the
dictionary of user words with empty or one at a time
with purge name.
 If you compile some code directly in the forth mode,
it will be saved to the disk when you re back to the
editor and do a front disk. Of course, if you directly
enter it, it'll be difficult to edit and modify while
if done from the editor, you can modify and recompile
at any time.


USE-FRONT EXPLAIN will display the rev 1.74


Enter press and hold LEAP, SHIFT then QWERASDFZXCV release
the SHIFT then LEAP, do a USE-FRONT EXPLAIN will
show credits.
 
 I am assuming that one already has some knowledge of
Forth. I'll describe those things that I think are
unique to the Cat or tForth. There are more things
that I don't understand. It is hoped that this document
will inspire others to look into things.
 tForth is a 32 bit values. Default base is hex.
 There are 2014 named heads of words and 582 named
integers.
 Most words are like fig Forth. Here are a few
related to the Cat:


W@ ( Addr - wordVal )
w! ( wordVal Addr - )
c@
c!
re ( - )  return to editor
"  ( - Adr N ) used " string"
ascii ( - Char ) used ascii A will return 41h
ctl ( - char ) used 'ctl a' returns ^A
' ( - tkn ) used ' word   returns token
decode ( Dic# - tkn )  Takes Dictionary Number to token
encode ( tkn - Dic# ) take token to value in dictionary header
+table ( tkn - Adr ) token to address points to compiled code.
see$  ( Adr n - ) diplays counted strings ascii
dump ( Adr n - ) displays values at address 16/line
hidden ( - ) vocabulary Dictionary from 2417 to 74c2
forth ( - ) vocabulary Dictionary from 3ea0b to 3ffe4
user ( - ) vocabulary used by user
existing ( - ) displays all vocabularies
searched ( - ) shows current search order
blit, wlit & lit  ( - n ) low level lit of diff sizes
name ( tkn - ) displays the name of the word that is tkn.
eta ( tkn - addr f ) if true, points to the dictionary table entry.
                     it points to the encoded number.
exa ( tkn - addr ) returns execution addr of token.
                    seems to be: +table @
n' ( - addr ) does ' name eta
c' ( - addr ) does ' name +table @
existing (-) displays all vocabularies.
searched ( - )  displays search order
addr ( n - addr ) fetches the address of the integer just used
                  to fetch n. n is not used. Built in integers
                  all seem to use the int0 to intf method while
                  new ones are only using normal tokens. Built in
                  ones are also spaced at every 4 so I suspect
                  there is a table of them. ( here addr = 40f800,
                  the last at 41011c )
empty ( - ) Clears any new user words.
purge ( - ) used purge name, will remove name from dictionary.
cls ( - ) clear screen
home ( - ) cursor to upper left of screen
goto ( Adr - ) goto execution address or code.
local ( - ) used 'local name' to create temporary locals that
     can be used by name like integer within definition. 
shr ( val cnt - val' ) shift right by count
inrange ( n l h - f ) true if inclusive range
integer ( n - | name ) used to create varibales and constants
to ( val int - ) Set new value for integer


There are a number of pointers used to point to string
that control the printer. If one wants to reconfigure
these for a different printer, one needs to change
them.


printertable ( - Addr ) each 2 byte location has 
                        a first byte is when the character requires
                        an accent character to print as is done for
                        foriegn characters
                        and the second is the character value.


There are pointers to strings used by the printer:
backspace" ( - a n ) Cause printer to back space
-bold" ( - a n ) Turn on bold 
+bold" ( - a n ) Turn off bold 
endline" ( - a n ) end of line 
endprint" ( - a n ) eject last page
evenhalfspace" ( - a n ) even half space
halfline" ( - a n )  half line advance of paper
hmi" ( - a n )  spacing for proportional
initprint" ( - a n ) initialize printer  
oddhalfspace" ( - a n ) odd half space
overstrike" ( - a n ) Over strike enable
unoverstirke ( - a n ) Over strike disable
printforward" ( - a n ) direction of print
printreverse" ( - a n ) direction of print
startline" ( - a n ) to the begining of a line
topofform" ( - a n ) top of form
-underline" ( - a n ) end underline
+underline" ( - a n ) end of underline
leftfoot" ( - a n ) left footer 
leftfrill" ( - a n ) left frill
rightfoot" ( - a n ) right footer
rightfrill" ( - a n ) right frill
userinit" ( - a n ) Any additional sequences to always send to
                    the printer. 


A few other variables that can effect above:
boustrophedon ( - f ) knows how to bidirectional
char/inch ( - n ) usually 10, 12 or 15
pageprint ( - f )  page or continuous ( I think )
knowstof? ( - f ) knows top of form
knowsbold ( - f ) knows how to do bold
knowsul? ( - f ) Knows how to under line
knowsos? ( - f ) knows over strike
knowshmi? ( - f ) knows hmi spacing
steps/inch ( - n ) used for hmi spacing
braindamaged ( - f ) unknown ???
paperpos ( - n ) Top of page location.
papershort ( - n ) less lines by 1/2 lines count
rightstop ( - n ) right stop in 1/2 char widths
diabolical ( - n ) For daisywheels that do Diablo mode.
'weirdprint ( - tkn ) Use when the international characters are printed
                     that require a preamble and postamble. See fx80magic
gutter ( - n ) Left margine in 1/2 chars from '3 printerinfo'


Example decompiled to show printer setups.
Note that "to adjusts the string space to match the size of the string.
Typically, setprinter will take what is in printercode and use that
for the final initialization of the printer strings. It does a few strings
but these can be overwritten as needed. Whichprinter selects between the
serial and parallel printer. printercode points to the printer type.
One should be able to patch the value in the +table for any of these
printers to initialize there own specific printer. The printer listed
as the Common printer in the setup menu is the fx80. The fx80 has unline
docs at:
https://files.support.epson.com/pdf/fx80__/fx80__uv.pdf
 This is useful in interpreting escape sequences used.


: setprinter ( - )
  whichprinter to
  7 printerinfo dup none <> and pageprint to
  3 printerinfo 2* gutter to
  1000 rightstop to
  paperpos off
  papershort off
  4 footpos to
  ['] printerror 'weirdprint to
  ['] noop 'docbreak to
  [ ' <"> c, 3 c, 1b c, 1f c, 1 c, ] unoverstrike" "to
  [ ' <"> c, 1 c, 0c c, ] toppfform" "to
  [ ' <"> c, 1 c, 0c c, ] endprint" "to
  braindamaged off
  boustrophedon off
  knowshmi? off
  knowstof? on
  ulinehack? off
  knowsbold? on
  knowsul? on
  knowsos? off
  printercode 2* printers + w@ execute
  vanilla.unbuild unbuildtable to ;


printercode(s)
 cat180setup 0
 lbp8setup 1
 newapsetup 2
 ap400setup 3 
 ap300setup 4
 ap100setup 5
 bj80setup 6
 fx80setup 7
 noprintersetup 8



: printerinfo ( n - Info )
  0 max 7 min 2* whichprinter
  if
    40f416
  else
    40f406
  then
  + w@ dup 6e65 =
  if 
    drop 6e6f6e65
  then ;


pinterinfo table:
 0 italics/underline
 1 font
 2 pitch
 3 left margin offset
 4 unidirectional/bidirectional
 5 daisy wheel country
 6 tray
 7 pause between sheets


cat180 
  daisy wheel US   info 5  0=us 1=canada 
  char/inch  10
  left mar offset 0 
  print mode bidir
  cut sheet feeder yes
  pause between sheets no
vp310311
  underline prints italics no
  char font  gothic pica elite courier info 1 gothic=0 to courier=3
  char / in  10p
  left mar off
NewAP
  Daisy  Wheel  us
  char/in  10 p
  printmode bidir
  cutsheet feed
  tray sel  a           info 6 = tray
  pause btwn sheets yes
AP400  AP300
  dw
  c/i
  left m o 0
  pm bidir
  cut sheet feeder no
  tray select A
  pause btwn sheet yes
bubblejet
  char set  us
  char/in 10
  left mar offset 0
  print mode bidir
  pause betwen sheet yes
CommonPrinter
  underline italics  no  info 0  1=yes
  char/in 10             info 2 10=0 12=1 16.8=2
  left mar offset 0      info 3  #chars
  print mode bidir       info 4  1=unidirectional
  pause between sheets no info 7  1=yes



: cat180setup ( - )
 2 paperpos to
 local ?name?
 [ ' <"> c, 1 c, 0a c, ] endline" "to
 [ ' <"> c, 1 c, 0d c, ] startline" "to
 [ ' <"> c, 2 c, 1b c, 45 c, ] +underline" "to
 [ ' <"> c, 2 c, 1b c, 52 c, ] -underline" "to
 [ ' <"> c, 2 c, 1b c, 4f c, ] +bold" "to
 [ ' <"> c, 2 c, 1b c, 26 c, ] -bold" "to
 [ ' <"> c, 1 c, 8 c, ] backspace" "to
 [ ' <"> c, 7 c, 1b c, 1e c, 5 c, 0a c, 1b c, 1e c, 9 c, ] halfline" "to
 [ ' <"> c, 2 c, 1b c, 35 c, ] printforward" "to
 [ ' <"> c, 2 c, 1b c, 36 c, ] printreverse" "to
 [ ' <"> c, 2 c, 1b c, 1f c, ] hmi" "to
 4 printerinfo 0= boustophedon to   ( prints both ways )
 <# 0d hold 5 printerinfo
 if
   6 printerinfo dup none = over 0= or  ( tray select )
   if
     31 31
   else
     dup 1 =
     if
       32 32
     else
       32 31 
     then
   then
   hold [ ' <"> c, 2 c, 1b c, 19 c, ] "hold
   ?name? to
   drop
   [ ' <"> c, 3 c, 1b c, 19 c, 52 c, ] endprint" "to
 else
   [ ' <"> c, 5 c, 0c c, 1b c, 1b c, 19 c, 45 c, 0d c, ] topofform" "to
   [ ' <"> c, 3 c, 1b c, 19 c, 45 c, ] "hold
 then
    2 printerinfo 0 =  ( pitch )
 if 
   [ ' <"> c, 3 c, 1b c, 1f c, 0d c, ] "hold
   0a 9e rightstop to
   [ ' <"> c, 7 c, 1b c, 1f c, 7 c, 20 c, 1b c, 1f c, d c, ]
 else
   2 printerinfo 1 = 
   if
      [ ' <"> c, 3 c, 1b c, 1f c, 0b c, ] "hold
      0c 0be rightstop to
      [ ' <"> c,  7 c, 1b c, 1f c, 6 c, 20 c, 1b c, 1f c, ob c, ]
   else
      2 printerinfo 2 =
      if 
         [ ' <"> c, 3 c, 1b c, 1f c, 9 c, ] "hold
         0f 0ed rightstop to
         [ ' <"> c, 7 c, 1b c, 1f c, 5 c, 20 c, 1b c, 1f c, 09 c, ]
      else
         printererror
      then
      2dup
   then
 then
 evenhalfspace" "to
 oddhalfspace" "to
 char/inch to
 diabolical not
 if
   [ ' <"> c, 2 c, 1b c, 3a c, ] "hold
   0 printerinfo wheel>iso + c@ 10 /mod
   swap 30 + hold 20 + hold
   [ ' <"> c, 6 c, 1b c, 3b c, 1b c, 1b c, 28 c, 26 c,] "hold
 then
 [ ' <"> c, 9 c, 1b c, 35 c, 1b c, 26 c, 1b c, 52 c, 1b c, 1e c, 09 c, ] "hold
 0 #> initprint" "to
 5 printerinfo  ( us or Canada )
 if
   <# 0d hold ?name? hold
   [ ' <"> c, 6 c, 0c c, 1b c, 19 c, 52 c, 1b c, 19 c, ] "hold
   0 #> topofform" "to
 then
 knowshmi? on
 78 steps/inch to   ( 120 step/inch in decimal )
 daisyoverstrike 6 footpos to
 ['] daisymagic 'weirdprint to
 ['] CATdocbreak 'docbreak to ;




: fx80setup ( - )
  [ ' <"> c, 1 c, 0a c, ] endline" "to
  [ ' <"> c, 3 c, 1b c, 4a c, 12 c, ] halfline" "to
  [ ' <"> c, 0 c, ] startline" "to
  0 printerinfo ( italics or underline )
  if 
    [ ' <"> c, 2 c, 1b c, 34 c, ] +underline" "to
    [ ' <"> c, 2 c, 1b c, 35 c, ] -underline" "to
  else 
    [ ' <"> c, 3 c, 1b c, 2d c, 1 c, ] +underline" "to
    [ ' <"> c, 3 c, 1b c, 2d c, 0 c, ] -underline" "to
  then
  [ ' <"> c, 2 c, 1b c, 47 c, ] +bold" "to
  [ ' <"> c, 2 c, 1b c, 48 c, ] -bold" "to
  [ ' <"> c, 1 c, 8 c, ] backspace" "to
  [ ' <"> c, 1 c, 20 c, ] evenhalfspace" "to
  [ ' <"> c, 0 c, ] oddhalfspace" "to
  <# 2 printerinfo ?dup ( pitch )
  if 
    1 =
    if 
      oc
      [ ' <"> c, 3 c, 1b c, 4d c, 12 c, ] ( elite mode )
    else
      10
      [ ' <"> c, 3 c, 1b c, 50 c, 0f c, ] ( pica )
    then
  else
    0a
    [ ' <"> c, 3 c, 1b c, 50 c, 12 c, ] ( pica )
  then
  "hold
  char/inch to
  4 printerinfo ( unidirectional? )
  if
    1
  else
    0
  then
  hold
  [ ' <"> c, 2 c, 1b c, 55 c, ] "hold    ( unidirectional mode select )
  [ ' <"> c, 4 c, 1b c, 40 c, 1b c, 36 c, ] "hold ( reset printer and enable controls )
  0 #> initprint" "to
  0c paperpos to
  ['] bj80docbreak 'docbreak to
  ['] fx80magic 'weirdprint to
  fx80.printer printertable to ;




: bj80setup
  7 paperpos to
  2 papershort to
  6 footpos to
  [ ' <"> c, 1 c, 0A c, ] endline" "to
  [ ' <"> c, 3 c, 1B c, 4A c, 12 c, ] halfline" "to
  [ ' <"> c, 0 c, ] startline" "to
  [ ' <"> c, 3 c, 1B c, 2D c, 1 C, ] +underline" "to
  [ ' <"> c, 3 c, 1B c, 2D c, 0 c, ] -underline" "to
  [ ' <"> c, 2 c, 1b c, 45 c, ] +bold" "to
  [ ' <"> c, 2 c, 1B c, 46 c, ] -bold" "to
  [ ' <"> c, 1 c, 8 c, ] backspace" "to
  [ ' <"> c, 1 c, 20 c, ] oddhalfspace" "to
  [ ' <"> c, 0 c, ] evenfalfspace" "to
  <# 2 printerinfo 0=
  if
    [ ' <"> c, 1 c, 12 c, ] "hold
    0A char/inch to 
  else 
    [ ' <"> c, 1 c, 0F c, ] "hold
    10 char/inch to
  then
  4 printerinfo
  if 
    1 
  else 
    0
  then
  hold
  [ ' <"> c, 2 c, 1b c, 55 c, ] "hold  ( set direction )
  [ ' <"> c, 7 c, 1B c, 46 c, 1B c, 2D c, 0 c, 1B c, 36 c, ] "hold
     ( cancel emphasis mode, cancel underscore, IBM chars set 2 )
  0 #> initprint" "to
  ulinehack? on
  BJ80.printer printertable to
  ['] bj80docbreak 'docbreak to ;


: lbp8setup
 local loc0 local loc1 local loc8
 base loc8 to
 decimal
 4 paperpos to
 4 papershort to
 [ ' <"> c, 3 c, 0C c, 1B c, 3A c, ] endprint" "to
 [ ' <"> c, 1 c, 0A c, ] endline" "to
 [ ' <"> c, 4 c, 9B c, 36 c, 30 c, 65 c, ] halfline" "to
 [ ' <"> c, 1 c, 0D c, ] startline" "to
 [ ' <"> c, 3 c, 9B c, 31 c, 6D ] +bold" "to
 [ ' <"> c, 3 c, 9B c, 32 c, 6D ] -bold" "to
 [ ' <"> c, 1 c, 08 c, ] backspace" "to
 0 printerinfo
 if
   [ ' <"> c, 3 c, 9b c, 33 c, 6D c, ]         ( Italic on )
   [ ' <"> c, 4 c, 9B c, 32 c, 33 c, 6D c, ]   ( Medium Char )
   ulinehack? off
 else
   ulinehack? on
   [ ' <"> c, 3 c, 9B c, 34 c, 6D c, ]         ( Underline On )
   [ ' <"> c, 4 c, 9B c, 32 c, 34 c, 6D c, ]   ( ???? Char )
 then
 -underline" "to
 +underline" "to
 <#
    2 printerinfo 0 =
    if
      0A 0 48
      [ ' <"> c, 4 c, 9B c, 33 c, 36 c, 61 c, ]
    else
      2 printerinfo 1 =
      if
        0C 04 3C
        [ ' <"> c, 4 c, 9b c, 33 c, 30 c, 61 c, ]
      else
        2 printerinfo 2 =
        if
          0E 08 30
          [ ' <"> c, 4 c,  9B c, 32 c, 34 c, 61 c, ]
        else
          printerror
        then
      then
    then
    2dup evenhalfspace" "to
    oddhalfspace" "to
    loc0 to
    loc1 to
    char/inch to
    [ ' <"> c, 2 c, 20 c, 47 c, ] "hold
    loc0 #s drop
    [ ' <"> c, 5 c, 9B c, 31 c, 32 c, 30 c, 3B c, ] "hold   ( set pitch )
    [ ' <"> c, 8 c, 9B c, 32 c, 32 c, 6D c, 9B c, 32 c, 33 c, 6D c, ] "hold  ( upright and medium char )
    1 printerinfo dup
    [ ' <"> c, 1 c, 79 c, ] "hold
    #s drop
    9B hold
    0C * loc1 + lbpsmarts + dup W@
    [ ' <"> c, 2 c, 20 c, 43 c, ] "hold
    #s drop
    9B hold
    2+ w@
    [ ' <"> c, 2 c, 20 c, 4B c, ] "hold
    dup #s drop 64 >
    if
      3F hold
    then
    9B hold 
    gutter off
    [ ' <"> c, 1C c, 1B c, 3B c,   ( init iso )
     1B c, 3D c,
     1B c, 28 c, 42 c,
     9B c, 3F c, 34 c, 3B c, 35 c, 6c c, 
     9B c, 31 c, 31 c, 68 c, 
     9B c, 3F c, 36 c, 3B c, 38 c, 68 c, 
     9B c, 30 c, 3B c, 31 c, 75 c, ] "hold
    0 
 #> initprint" "to
 <#
    [ ' <"> c, 2 c, 20 c, 47 c, ] "hold
    loc0 #s
    [ ' <"> c, 3 c, 1B c, 5B c, 3B c, ] "hold
 #> hmi" "to
 6 footpos to
 LBP.printer printertable to
 ['] LBPmagic 'weirdprint to
 ['] LBPdocbreak 'docbreak to
 loc8 base to ;



    
: LPBmagic ( Addr ChrSet - )
 dup 1D >
 if    
   1E =
   if   
     642    ( ['] mimlt  )
   else  
     641    ( ['] mimdpx  )
   then
   setcountry
   [ ' <"> c, 4 c, 0e c, 1b c, 3a c, 1b c, ] put"
   1+ c@ 
   [ ' <"> c, 3 c, 1b c, 3b c, 0f c, ] put"
 else 
   1- 2* countries + w@ dup setcountry
   swap 1+ c@ 
   2 motion 8000 and 
   if
     [ ' <"> c, 3 c, 1b c, 29 c, 42 c, ] put"
     oldcountry off
     hmi" put"
   then
  then ;



         


    


: fx80magic ( Addr ChrSet - )
  [ ' <"> c, 2 c, 1b c, 52 c, ] put"   ( select an international chr set )
  1+ c@ 
  [ ' <"> c, 3 c, 1b c, 52 c, 0 c, ] put" ;


: bj80docbreak
  [ ' <"> c, 2 c, 1b c, 43 c, ] put" ( Form length )
  paperlength papershort +
  2- 2/  ;



: "  ( - Addr Cnt | expect a string of char in input until " )
  22 scanfor
  -1 len +to
  1 str +to
  state nesting or 
  if
    compile <">
    len c,
    here
    len allot
    str swap
    len cmove
  else
    str len
  then ;



: Pickprinter ( - )
 printercode dup 8 = swap none =
 or
 if
   noprinter error abort
 then
 printerport ?dup
 if 
   0<
   if
     print.parallel
   else  bran
     noprinter error abort
   then
 else
   print.serial
 then ;


: makeprinttable
 printercode dup 2 5 inrange swap 0= or
 if
   daisy.printer trkbuf 214 move trkbuf printertable to
   0 printerinfo dup
   0 0d inrange
   if
     2* DW.countries + w@ execute
     patchprint 
   else
     printerror 
   then
 else
   printercode 6 = 0 printerinfo 1 = and
   if
     BJ80.printer trkbuf 214 move trkbuf printertable to
     bjsecond.dw patchprint
    then
 then ;


: patchprint ( Addr - ) ( table terminated with FFFF )
  begin
   dup w@ dup ffff <>
  while 
     over 2+ c@ 2* printertable + w!
     3 + 
  repeat
  2drop ;


: "to ( AddrFrom$ CntFrom AddrTo$ CntTo - )
  <"to>
  2drop ;


: <"to>
  local loc0 local loc1 local loc8 local locC local loc10
  loc0 to
  loc1 to
  loc8 to
  locC to
  loc1 6 - w@
  149 <>
  " not a string variable"
  abort"
  loc1 current exa here inrange
  loc1 strings origin inrange
  or not " can't assign to string in closed vocabulary"
  abort"
  loc8 loc0 - loc10 to
  loc10 froom?
  loc1 4 - @ 1 and
  if
    -1 loc10 +to 
  then 
  loc10 1 and
  if
    1 loc10 +to 
  then
  loc1 loc0 + dup dup loc10 + here rot - loc1 loc0 + here 1+ loc10
  move&adjust locC loc1 loc0 + here inrange
  if
    loc10 locC +to
  then
  locC loc1 loc8 move loc8 loc1 4 - ! loc1 loc8 ;
  
   
The words are in different tkn groups. 0 to 0fff would be tiers.
from 1000 to 1f00 would be values. These values are assigned,
using 4 token values. This means that there are only 2048
possible values. I don't yet know how to create values???
These seem to be created with the word: integer  ????



Some other useful values
ramstart
ramend
ramsize
screensize
screen
origin
here





Dict formats:
 2 byte, encoded value Use decode to get tkn
 1 byte  ( Imm,reserved,5BitsCharCnt)
 Bytes?  Count = 5BitCharCnt


Two special types of tokens:
 tier1 to tierf  ( 01 to 0f ) two byte compile
 int0 to intf  ( 10 to 1f ) integer values in teirs



some ways to emit
semit ( char - ) serial
pemit ( char - ) parallel
eemit ( char - ) editor ( placed at current cursor )
demit ( char - ) ??? disk ???




The dictionaries are in alphabetical order. It is difficult to
trace down related words so I've written words to display the
word names in token order. This seems more useful as many related
words are grouped together:


: tt ( tkn - ) dup 80 + swap do i name loop ;
( tkn is 0 to 0fff although 7DE is the last in the built in code.
  tkn can be used in 80 increments to display all 0, 80, 100, 180 ... )


This doesn't work well for built in integer tokens so I wrote:


: xx ( tkn - ) dup 200 + swap do i name 4 +loop ;
( tkn is the same as for tt but in 200 increments. 1000 to 1918 are valid )



A simple decompiler. It doesn't deal with strings, literals
or branches automatically yet but that could be added. If you come on a
, , , <0bran>,  or  enter letter b
<0branl>,  or  enter leter w
 enter letter l
<"> enter letter s
 The code could use some more clean up but is what I used
so far. Use the letter q to quit. This only works for token
threaded code. All token threaded code will have 4ED3 at
the start. This value will be displayed at the begining of see.
It is up to you to select q. Any other character like space
bar will continue to decompile,
 It took me a while to figure local. They would be used in the
form: local fred  local sam  local joe
 The compiled code would loose the names and have:  0C
Each local takes 4 locations so the 0c is 3 4 * .
When accessed, they are just like integer(s). They return the
value in them and are set with the word to or +to.
In the compiled code, fred would be  and sam would be 
but joe would be  8, as fred would be  0 if it wasn't
for the short word  and sam would be  4. I hope this
makes sense.
 To use the word see, you must first get the token.
As an example:   ' do$ see
would decompile the word do$.
The decompile words  and  do not have any inline values
attached and don't need the use of b,w or l.


: .1 ( Addr - Addr' ) dup c@ . 1+ ;
: .2 ( Addr - Addr' ) dup w@ . 2+ ;
: .4 ( Addr - Addr' ) dup @ . 4 + ;
: .spec ( Addr - Addr' )
  dup .2 swap w@ name ;
: craddr ( Addr Char - Addr Char )
   cr over . ;
: do$ ( Addr Char - Addr' Char )
   swap dup . dup c@ dup .
   0ff and ?dup if
                  0 do
                     1+ dup c@ . loop
                then
   1+ swap craddr ;


: see ( tkn - )
  exa .2
  begin
    key dup ascii q = if exit then
    dup ascii b = if swap .1 swap craddr then
    dup ascii w = if swap .2 swap craddr then
    dup ascii s = if do$ then
    ascii l = if .4 craddr then
    dup c@ 1 01f inrange
    if
      .spec
    else
      dup .1 swap c@ name
    then cr
  again ;



 Note that first two bytes of a word are a jump to.
An example:
 ' beep see   4ED3 9200 183 'beep
9202 17F sound.on
9204 182 ?sound
9206 3d not
9207 <0bran>
9208 FC                 ( hit letter b at this line )
9209 26 <;>
920A                    ( hit letter q to quit )


This would be reconstructed as:


: beep
   sound.on
   begin
     ?sound not
   until ;




A number of words start with m, like mYes. These are the
strings for various messages. ( try: mYes type )


There is more to explore. Someone familiar with 68K assembly
can dig more into things.



Here is what I have for the HP IIIsi and 4Si so far.
 There is a word RestoreP. Use this word to put things back to
normal. One should do this before using empty to clear the
Forth words, once one does a HP. Remmeber, once you save to
disk, and you've used the word HP, it will still be linked to
HPsetup and using empty will have the printer setup pointing
to empty space. A sure crash will follow. On my machine,
'fx80 .  will print 2C162. You should check yours because
if you accidentally load this twice, without an empty, you'll
have the same address as HPsetup would have 
 Make sure to make backup disk or you'll have a pain recovering
as I have had a couple times. Remember a save to disk saves
everything, including any mistake that crashes the machine.
It will be an endless loop of almost loading and then crashing
each time.
 Load the words that follow, either by direct entry into Forth
or when Forth is enabled highlight the Forth code in text and
do a front-answer.
 Once loaded from Forth use the word HP. This links the HP
setup in place of the FX80 setup that is used for the printer
called the 'Common Printer' in the printer setup.
 Also note, I've not tested everything yet and I've not done
anything yet for the wierdprint operations. wierdprint is for
some of the foriegn characters that require a pre and posamble
to print these characters.
 It does currently work for plain text. One might add propotional
print and do the patches for wiedprint.


' fx80setup +table dup integer setup'
                    @  integer 'fx80


: RestoreP
   'fx80 setup' ! ;


: HPdocbreak
   base decimal
   <# ascii F hold
   paperlength papershort + 2 2/ #s
   [' <"> c, 3 c, 1B c, 26 c, 6C c, ] "hold #> put"
   base to ;


: HPsetup
  [' <"> c, 1 c, 0a c, ] endline" "to
  [' <"> c, 2 c, 1B c, 3B c, ] halfline" "to
  [' <"> c, 1 c, 0D c, ] startline" "to
  0 printerinfo
  if
   [' <"> c, 5 c, 1B c, 28 c, 73 c, 31 c, 53 c, ] +underline" "to
   [' <"> c, 5 c, 1B c, 28 c, 73 c, 30 c, 53 c, ] -underline" "to
  else
   [' <"> c, 5 c, 1B c, 26 c, 64 c, 30 c, 44 c, ] +underline" "to
   [' <"> c, 4 c, 1B c, 26 c, 64 c, 40 c, ] -underline" "to
  then
   [' <"> c, 5 c, 1B c, 28 c, 73 c, 33 c, 42 c, ] +bold" "to
   [' <"> c, 5 c, 1B c, 28 c, 73 c, 30 c, 42 c, ] -bold" "to
   [' <"> c, 1 c, 8 c, ] backspace" "to
   [' <"> c, 1 c, 20 c, ] evenhalfspace" "to
   [' <"> c, 0 c, ] oddhalfspace" "to
   <# 2 printerinfo ?dup
   if
    1 =
    if
     0C [' <"> c, 5 c, 1B c, 26 c, 6B c, 34 c, 53 c, ]
    else
     10 [' <"> c, 5 c, 1B c, 26 c, 6B c, 32 c, 53 c, ]
    then
   else
    0A [' <"> c, 5 c, 1B c, 26 c, 6B c, 30 c, 53 c, ]
   then
   "hold char/inch to
   [ ' <"> c, 2 c, 1B c, 45 c, ] "hold 0 #>
   initprint" "to
   0C paperpos to
   ['] HPdocbreak 'docbreak to
   fx80.printer printertable to ;


: HP
  ['] HPsetup exa setup' ! ;

Dwight Elvey



Movies of Dwight Elvey giving us a guided tour of the Canon Cat
(including Forth internals)

cat.jpg
Back to Main page on Canon Cat

See Also:


Jef Raskin's Pages at the Digibarn

and photos of the Canon Cat design & team

Jef Raskin's homepage

David Craig's excellent article: Canon's Cat Computer: The Real Macintosh

Jef Raskin's Swyft system

Please send site comments to our Webmaster.
Please see our notices about the content of this site and its usage.
(cc) 1998- Digibarn Computer Museum, some rights reserved under this Creative Commons license.