Commercial pack not yet archived: AccuPEN GOLD

Many of these are still available on line, add your comments, reviews, observations and suggestions for each in this section
okto
Posts: 59
Joined: Sun Apr 23, 2023 5:14 am

Re: Commercial pack not yet archived: AccuPEN GOLD

Post by okto »

Pernod wrote: Wed Jul 12, 2023 5:34 pm As a newcomer to the Organiser why are pack owners not dumping the actual ROM contents, instead of producing these opk images?
Because it requires desoldering to do so, OPK is the standard image format, and there's not really any need to.

What problem are you looking to solve?
Pernod
Posts: 6
Joined: Wed May 24, 2023 12:41 pm

Re: Commercial pack not yet archived: AccuPEN GOLD

Post by Pernod »

okto wrote: Thu Jul 20, 2023 4:02 pm Because it requires desoldering to do so, OPK is the standard image format, and there's not really any need to.
When I first asked the question I incorrectly assumed the ROM was socketed and easily removed for reading.
- Nigel

MAME Developer
User avatar
Martin
Global Admin
Posts: 220
Joined: Mon Jan 02, 2023 5:18 pm

inspecting similarities in OPK's

Post by Martin »

Hi Nigel

I'd be interested to have a look at the two OPK's especially if you think they might be the same but 'different'..

If you don't want to post them publicly but are up for it you could attach them to a PM or you can email them to me at the Organiser Forum Registration Confirmation address.

Sincerely
Martin
MartinP
Posts: 46
Joined: Wed Jan 04, 2023 7:51 pm

Re: Commercial pack not yet archived: AccuPEN GOLD

Post by MartinP »

The only difference between an opk file and a true 'rom dump' is the initial 6 bytes. An opk file starts with the ascii for "OPK" followed by the size of the pack image in 3 bytes, starting with the highest byte first. This is followed by a rom dump of the pack up to the image size.
Any differences in opk files can only be due to differences in the packs when they were dumped.
When a pack is dumped it's also 'sized', to see when the data ends, this prevents saving blank bytes to the opk.
Boris Cornet's DumpPack skips the sizing and dumps the whole pack, which could be useful for a corrupted pack which doesn't 'size' correctly.

I've created a few tools for reading opk files, available at: https://github.com/martinprest/Psion2-D ... der-writer
Particularly useful might be: ls_opk.py, a python file to catalogue the pack. I wrote it whilst developing my Arduino datapak reader-writer:
Psion2_Rampak_read_write_1.jpg
Some of my Arduino software has been incorporated into Andrew's Datapak tool, which is written in C, see viewtopic.php?t=56
I've been gradually trying to develop the code a bit further, but life keeps getting in the way.
I've also created a fully commented copy of Jaap's "sendpack" disassembled machine code, so I've listed it below in case anyone is interested to see how it was written, there might be a few small errors in how I've decoded it, but I stopped when I got to the point where I could understand it.
Thanks to Andrew M. for the disassembly.
Martin P.

Code: Select all

SENDPACK:
LOCAL MC1$(72),MC2$(140),A$(255),A%(3)
LOCAL N%,M%,P%,L1%,L2%,C%,A

CLS
PRINT "Loading...";
REM MC1 is sizing, MC2 is pack read
REM CONV$:() converts hex codes to bytes in a string
MC1$=CONV$:("18EC00FF22804F3F62253A5FCE000A3F6025323F5F188C0280270C082711185D27F15A164F20023F5F3F63251820E43F5C1883000218C2003CFE22806F02E7033233ED045F4F1839")
MC2$=CONV$:("18EC04FD2284EC02FD2282EC00FD2280FF227EF622824F3F622527FE2284F622833F60251DFE2280E60008374F3F5E251033FE227E4FE304ED0424026C035F2001324F1839")
N%=ADDR(MC2$)+1 :REM +1 because first byte of string is length
M%=ADDR(A%()) :REM pointer to A%(), will load into 2 byte D register

DO
 DO
  CLS
  PRINT "Pack? (B,C,D)";
  P%=ASC(UPPER$(GET$))
  IF P%=1
   RETURN
  ENDIF
 UNTIL P%>=%B AND P%<=%D :REM %B gives ASCII value of 'B'
 CLS
 P%=P%-%A :REM make P% a num from 2 to 4 B: is 2, C: is 3
 A%(1)=P%
 C%=USR(ADDR(MC1$)+1,M%) :REM call MC1 sizing, with D as pointer to A%. A%(1) = pack no., returns X register value to C%
UNTIL C%<>246 : REM 246??
IF C%
 RAISE C% :REM C% is error num
ENDIF

ONERR E:: :REM error handling, see label E:: at end of code
XFOPEN:("PACK.OPK",1,0) :REM open file on remote computer via serial
A$="OPK"+CHR$(A%(2))+CHR$(PEEKB(ADDR(A%())+4))+CHR$(A%(3) AND 255) :REM write OPK header, with size in A%(2) -high high, A%(0)+4 -> A%(3)-high, A%(3) AND 255 -> A%(3)-low,   byte order is high-low
XFPUT:(A$)     :REM write to OPK via serial
A$=REPT$(" ",255) :REM page buffer
A=65536.*A%(2)+A%(3) :REM A is pack size, A%(2)-topByte, + add A%(3) - pack size is 24 bit - topByte is top 8 bits
IF A%(3)<0
 A=A+65536
ENDIF
L1%=INT(A/255) :REM L1% = no. of full pages in A
L2%=A-255.*L1% :REM L2% = length of last partial page
IF L2%<=253    :REM add 2 bytes to L2% if fit on page - to read 2x 0xFF bytes at end of pack, beyond size
 L2%=L2%+2
ELSE
 L2%=L2%-253   :REM if L2% is 254, subtract 253 (so L2% = 1)
 L1%=L1%+1     :REM add one page to length, with one byte in it ( i.e. add 2 bytes) 
ENDIF
A%(1)=ADDR(A$) :REM A$() buffer address, points to length byte followed by string
A%(2)=P%*256+0 :REM pack no. in high byte of A%(2)
A%(3)=0        :REM will be used to count pack address during read (with topByte byte in A%(2) low byte)
WHILE L1%      :REM loop whilst page_count > 0, keeps reading pages and reducing page count
 C%=USR(N%,M%) :REM call MC2 with D as addr of A%() (N%-addr of code, M%-addr of A%), read page or partial page, returns X register value to C%
 IF C%=0
  XFPUT:(A$)   :REM if no errors, write A$ to serial
 ELSE
  RAISE C%     :REM else, raise error
 ENDIF
 AT 1,1
 PRINT L1%,    :REM print no. of pages remaining
 L1%=L1%-1     :REM reduce page count
ENDWH
A$=REPT$(" ",L2%) :REM A$ buffer for partial page
C%=USR(N%,M%)  :REM read partial page with D as addr of A% (N%-addr of code, M%-addr of A%()), returns X register value to C%
IF C%=0
 XFPUT:(A$)    :REM if no errors, write A$ to serial
ELSEIF C%
 RAISE C%      :REM else, raise error
ENDIF
XFCLOSE:       :REM close serial port
CLS
PRINT "Done";
PAUSE -20
RETURN

E::
ONERR OFF
C%=ERR
XFCLOSE:
RAISE C%


                             //
                             // RAM 
                             // RAM:0000-RAM:008c
                             //
                             // sendpack machine code disassembled
			     // A is high byte of D, B is low byte of D  
                             **************************************************************
                             * MC1                                                        *
                             * pack sizing				                  *
				short record - length, type (type FF is invalid length)
				long record - 02 80 highbyte lowbyte (of length)
                             **************************************************************
            0000 18              XGDX										// exchange D and X (move call value D - addr of A%() into X)
            0001 ec 00           LDD        0x0,X								// load D with value in X+0 (slot no.)
            0003 ff 22 80        STX        DAT_2280								// store X in 2280 (store addr of A%() within run time data store)
            0006 4f              CLRA										// clear A
            0007 3f 62           OS         PK$SETP=>SUB_fffa							// setpack slot to value in B (0-3 A: to D:, A: is internal memory storage)
            0009 25 3a           BCS        LAB_0045								// if error, exit
            000b 5f              CLRB										// clear B
            000c ce 00 0a        LDX        #0xa								// load X with 000A - skip header to 1st data record
            000f 3f 60           OS         PK$SADD=>SUB_fffa							// set pack addr B-topByte, X-lowest 2 bytes
            0011 25 32           BCS        LAB_0045								// if error, exit
                             LAB_0013                                        XREF[2]:     0020(j), 002d(j)  	// LAB_0013 - start of main loop
            0013 3f 5f           OS         PK$RWRD=>SUB_fffa							// read a word from pack (2 bytes) to D
            0015 18              XGDX										// exchange D and X (D -> X)
            0016 8c 02 80        CMPX       #0x280								// compare X to 0280 - long record?
            0019 27 0c           BEQ        LAB_0027								// branch if zero set (long record) to LAB__0027 - found long record
            001b 08              INX										// increase X
            001c 27 11           BEQ        LAB_002f								// branch if zero set (word was FFFF) to LAB_002f - found end of pack
            001e 18              XGDX										// exchange D and X (X -> D)
            001f 5d              TSTB								 		// test B for zero (low byte zero? word was xxFF?) found one FF byte - invalid short record length
            0020 27 f1           BEQ        LAB_0013								// branch if zero set (low byte FF) to LAB_0013 - back to main loop
            0022 5a              DECB										// decrease B (?? B gets over written - clear zero flag?)
            0023 16              TAB										// transfer (copy) A to B (high byte to low byte)
            0024 4f              CLRA										// clear A (low byte only for short record length)
            0025 20 02           BRA        LAB_0029								// branch to LAB_0029 (jump over read long record length)
                             LAB_0027                                        XREF[1]:     0019(j)  		// LAB_0027 - long record
            0027 3f 5f           OS         PK$RWRD=>SUB_fffa							// read a word from pack to D - length of record
                             LAB_0029                                        XREF[1]:     0025(j)  		// LAB_0029
            0029 3f 63           OS         PK$SKIP=>SUB_fffa							// skip D bytes forward - skip record length
            002b 25 18           BCS        LAB_0045								// branch if carry set to LAB_0045 - error & exit
            002d 20 e4           BRA        LAB_0013								// branch to LAB_0013 + back to main loop
                             LAB_002f                                        XREF[1]:     001c(j)  		// LAB_002f - found end of pack
            002f 3f 5c           OS         PK$QADD=>SUB_fffa							// read pack address to B-high X-low
            0031 18              XGDX										// exchange D and X (X to D, D to X) 
            0032 83 00 02        SUBD       #0x2								// subtract 2 from low byte of addr (pack address before FFFF)
            0035 18              XGDX										// exchange D and X (D to X, X to D, B now has high byte of addr)
            0036 c2 00           SBCB       #0x0								// subtract 0 and carry from B (if carry, from subtracting 2, reduce high byte, B stays in D)
            0038 3c              PSHX										// push X to stack (low byte of end addr to stack)
            0039 fe 22 80        LDX        DAT_2280								// load X from 2280 - addr of A%()
            003c 6f 02           CLR        0x2,X								// clear value in X+2
            003e e7 03           STB        0x3,X								// store B at X+3 (topByte byte of end of pack) at A%(2)-low
            0040 32              PULA										// pull A from stack (high byte of D)
            0041 33              PULB										// pull B from stack (low byte of D, low byte of addr)
            0042 ed 04           STD        0x4,X								// store D at X+4, store in A%(3) - high,low
            0044 5f              CLRB										// clear B
                             LAB_0045                            XREF[3]:     0009(j), 0011(j), 002b(j) 	// LAB_0045 - error & exit
            0045 4f              CLRA										// clear A
            0046 18              XGDX										// exchange D and X - X is returned by USR (0 if ok)
            0047 39              RTS										// return
                             **************************************************************
                             * MC2                                                        *
                             * pack read 1 page at a time                                 * B -low of D, A -high of word register D
                             **************************************************************
sets pack address on each call - maybe pack address gets lost when data sent via serial over pack datalines?
can't guarantee pack address is preserved when control passes back to OPL and serial is used?
            0048 18              XGDX										// exchange D and X (move call value D - addr of A%() into X) X reg also a word
            0049 ec 04           LDD        0x4,X								// Load D with value in addr X+4 (& X+5) A%(3) - storage of pack address: high,low
            004b fd 22 84        STD        DAT_2284								// store D in 2284 - pack address (starts at zero), byte order: high, low
            004e ec 02           LDD        0x2,X								// load D with value in addr X+2 (& X+3) A%(2) - pack slot in high byte (X+2) 2282, X+3 topByte of address
            0050 fd 22 82        STD        DAT_2282								// store D in 2282 - pack slot no., 2283 is topByte
            0053 ec 00           LDD        0x0,X								// load D with value in addr X (& X+1) A%(1) - address of data buffer A$() (255 bytes or final partial page)
            0055 fd 22 80        STD        DAT_2280								// store D in 2280 - pointer to A$() buffer
            0058 ff 22 7e        STX        DAT_227e								// store X in 227E (& 227F) - pointer to A%()
            005b f6 22 82        LDB        DAT_2282								// load B from 2282 (load value in X+2) - pack no. to B (low byte of D)
            005e 4f              CLRA										// clear A (high byte of D)
            005f 3f 62           OS         PK$SETP=>SUB_fffa							// set pack slot to value in D (set to value from X+2, A%(2)-high)
            0061 25 27           BCS        LAB_008a								// branch is carry set to LAB_008A - if error, exit
            0063 fe 22 84        LDX        DAT_2284								// load X from 2284 (load word from addr X+4) - restore X - pack address: high,low
            0066 f6 22 83        LDB        DAT_2283								// load B from 2283 (load high byte of value in addr X+3) - topByte
            0069 3f 60           OS         PK$SADD=>SUB_fffa							// set pack address to value in B and X, set pack addr B-topByte, X-high,low of pack addr
            006b 25 1d           BCS        LAB_008a								// branch if carry set to LAB__008A - if error, exit
            006d fe 22 80        LDX        DAT_2280								// load X from 2280 (load X with value in 2280) load A$() pointer
            0070 e6 00           LDB        0x0,X								// load B with value in addr X (get value from A$() pointer address) - A$(0) is buffer length: 255 or less
            0072 08              INX										// increase X by 1, A$() pointer +1, move past length byte
            0073 37              PSHB										// push B to stack -value in A$(0) to stack
            0074 4f              CLRA										// clear A (clear high byte of D) D is A,B: high,low 
            0075 3f 5e           OS         PK$READ=>SUB_fffa							// read D pack bytes to address beginning at X, fill A$ from 2nd element (255 or less)
            0077 25 10           BCS        LAB_0089								// branch if carry set to LAB_0089, if error, pull A from stack, exit
            0079 33              PULB										// pull B from stack get A$(0) length value back from stack, D will now have buffer length
            007a fe 22 7e        LDX        DAT_227e								// load X from 227E - restore A%() pointer
            007d 4f              CLRA										// clear A - clear high byte of D
            007e e3 04           ADDD       0x4,X								// add value in addr X+4 to D - add D to pack address
            0080 ed 04           STD        0x4,X								// store D in addr X+4 - store pack address
            0082 24 02           BCC        LAB_0086								// branch if carry clear to LAB_0086 - if no address overflow error - clear B & exit
            0084 6c 03           INC        0x3,X								// increase value in addr X+3 by 1 (otherwise increase topByte of pack address & exit)
                             LAB_0086                                        XREF[1]:     0082(j)  		// LAB_0086 - clear B & exit
            0086 5f              CLRB										// clear B
            0087 20 01           BRA        LAB_008a								// branch to LAB_008A 
                             LAB_0089                                        XREF[1]:     0077(j)  		// LAB_0089 - pull A & exit		
            0089 32              PULA										// pull A from stack
                             LAB_008a                          XREF[3]:     0061(j), 006b(j), 0087(j)  		// LAB_008A - error & exit
            008a 4f              CLRA										// clear A
            008b 18              XGDX										// exchange D and X
            008c 39              RTS										// return

You do not have the required permissions to view the files attached to this post.
Post Reply