diff -ruN wsjtx-orig/lib/77bit/packjt77.f90 wsjtx/lib/77bit/packjt77.f90
--- wsjtx-orig/lib/77bit/packjt77.f90	2022-12-31 16:41:45.000000000 -0500
+++ wsjtx/lib/77bit/packjt77.f90	2023-05-12 14:37:43.045560052 -0400
@@ -15,6 +15,38 @@
 
   contains
 
+subroutine readhash(filename)
+   character(len=*), intent(in) :: filename
+   logical :: file_exists
+
+   inquire(file=filename, exist=file_exists)
+   if (file_exists) then
+      open(unit=10, file=filename, access='STREAM', form='UNFORMATTED', STATUS='OLD')
+
+      READ(10) calls10
+      READ(10) calls12
+      READ(10) calls22
+      READ(10) ihash22
+      READ(10) nzhash
+      close(unit=10)
+   endif
+
+end subroutine readhash
+
+subroutine writehash(filename)
+   character(len=*), intent(in) :: filename
+
+   open(unit=10, file=filename, access='STREAM', form='UNFORMATTED', STATUS='REPLACE')
+   
+   WRITE(10) calls10
+   WRITE(10) calls12
+   WRITE(10) calls22
+   WRITE(10) ihash22
+   WRITE(10) nzhash
+   close(unit=10)
+
+end subroutine writehash
+
 subroutine hash10(n10,c13)
 
   character*13 c13
diff -ruN wsjtx-orig/lib/jt9.f90 wsjtx/lib/jt9.f90
--- wsjtx-orig/lib/jt9.f90	2022-12-31 16:41:45.000000000 -0500
+++ wsjtx/lib/jt9.f90	2023-05-12 14:36:23.662572827 -0400
@@ -10,7 +10,8 @@
   use timer_module, only: timer
   use timer_impl, only: init_timer, fini_timer
   use readwav
-
+  use packjt77
+    
   include 'jt9com.f90'
 
   integer*2 id2a(180000)
@@ -26,8 +27,8 @@
        fhigh=4000,nrxfreq=1500,ndepth=1,nexp_decode=0,nQSOProg=0
   logical :: read_files = .true., tx9 = .false., display_help = .false.,     &
        bLowSidelobes = .false., nexp_decode_set = .false.,                   &
-       have_ntol = .false.
-  type (option) :: long_options(31) = [                                      &
+       have_ntol = .false., persist_hash = .false.
+  type (option) :: long_options(32) = [                                      &
     option ('help', .false., 'h', 'Display this help message', ''),          &
     option ('shmem',.true.,'s','Use shared memory for sample data','KEY'),   &
     option ('tr-period', .true., 'p', 'Tx/Rx period, default SECONDS=60',    &
@@ -73,6 +74,8 @@
     option ('my-grid', .true., 'G', 'my grid locator', 'GRID'),              &
     option ('his-call', .true., 'x', 'his callsign', 'CALL'),                &
     option ('his-grid', .true., 'g', 'his grid locator', 'GRID'),            &
+    option ('persist-hash', .true.,                                          &
+       'P', 'persist hashcodes', 'PATH'),                                    &
     option ('experience-decode', .true., 'X',                                &
         'experience based decoding flags (1..n), default FLAGS=0',           &
         'FLAGS') ]
@@ -91,7 +94,7 @@
   TRperiod=60.d0
 
   do
-     call getopt('hs:e:a:b:r:m:p:d:f:F:w:t:9876543WqTL:S:H:c:G:x:g:X:Q:',     &
+     call getopt('hs:e:a:b:r:m:p:d:f:F:w:t:9876543WqTL:S:H:c:G:x:g:P:X:Q:',   &
           long_options,c,optarg,arglen,stat,offset,remain,.true.)
      if (stat .ne. 0) then
         exit
@@ -161,6 +164,9 @@
            read (optarg(:arglen), *) hiscall
         case ('g')
            read (optarg(:arglen), *) hisgrid
+        case ('P')
+           hash_file = optarg(:arglen)
+           persist_hash = .true.
         case ('X')
            read (optarg(:arglen), *) nexp_decode
            nexp_decode_set = .true.
@@ -185,6 +191,10 @@
      go to 999
   endif
 
+  if (persist_hash) then
+     call readhash(hash_file)
+  end if
+  
   iret=fftwf_init_threads()            !Initialize FFTW threading 
 
 ! Default to 1 thread, but use nthreads for the big ones
@@ -370,4 +380,9 @@
   call filbig(a,-1,1,0.0,0,0,0,0,0)        !used for FFT plans
   call fftwf_cleanup_threads()
   call fftwf_cleanup()
+
+  if (persist_hash) then
+     call writehash(hash_file)
+  end if
+  
 end program jt9
diff -ruN wsjtx-orig/lib/prog_args.f90 wsjtx/lib/prog_args.f90
--- wsjtx-orig/lib/prog_args.f90	2022-12-31 16:41:45.000000000 -0500
+++ wsjtx/lib/prog_args.f90	2023-05-12 14:37:05.746033262 -0400
@@ -1,4 +1,5 @@
 MODULE prog_args
   CHARACTER(len=80) :: shm_key
   CHARACTER(len=500) :: exe_dir = '.', data_dir = '.', temp_dir = '.'
+  CHARACTER(len=500) :: hash_file = 'hash.dat'
 END MODULE prog_args
