HP Forums
Hand Held Products 71M/M eprom carrier question - Printable Version

+- HP Forums (https://www.hpmuseum.org/forum)
+-- Forum: HP Calculators (and very old HP Computers) (/forum-3.html)
+--- Forum: General Forum (/forum-4.html)
+--- Thread: Hand Held Products 71M/M eprom carrier question (/thread-15181.html)

Pages: 1 2

RE: Hand Held Products 71M/M eprom carrier question - cmurillo - 09-08-2020 05:32 PM

Richard: I used this program to convert a ROM dump into an intel hex file suitable for burning an EPROM. It is a one-off thing and has no error checking; it hasn't been cleaned up either, but it did the job for me.

/* dmp2hex.c : convert a nibble dump from the HP-71B DUMPROM BASIC program
into an intel HEX format file. Syntax is
$ dmp2hex infile.dmp > outfile.hex

The output is appropriate to burn an EPROM for the
Hand Held Products 71M/M EPROM carrier for the card reader slot.

A rom dump is just the nibbles in the Saturn cpu memory map
in order of increasing address (as returned by PEEK$), in the
form of a text file with 64 characters per line, each character
the ASCII hex digit {0-9, A-F} for each nibble.
But the data in the EPROM differs from this in that the most
significant nibble in each byte is the higher-addressed nible
in the memory map, and also in that the data is negated in the
ROM. Thus, a 16 nibble sequence in a ROM such as


must be coded in the EPROM like these eight consecutive bytes

C4 22 22 12 B1 B9 AD CE DF

That is, C is the 1-complement of 3, 4 is the 1-complement of B,
2 is the 1-complement of the fourth nibble in the sequence (a D)
and so on.

Carlos E. Murillo-Sanchez 2020-06-15. Just a quick hack
without much error checking.

Version 1.0

#include <stdio.h>
#include <string.h>

unsigned char hex2nibble(unsigned char a)
{ unsigned char b;
if (a >= 48 & a <= 57) {
b = a - 48;
else if ( a >= 65 & a <= 70) {
b = a - 55;
else if ( a>= 97 & a <= 102 ) {
b = a - 87;
else {
fprintf(stderr, "Invalid ASCII character representation of hex value %s\n", a);
return b;

unsigned char nibble2hex(unsigned char a)
{ unsigned char b;
b = a & 0x0F;
if (b < 10) {
b = b + 0x30;
b = b + 55;
return b;

main (argc, argv, envp)
int argc;
char **argv;
char **envp;
char *ifile;
char *program;
FILE *fp;
unsigned char linein[66];
unsigned char nibbles[64];
unsigned char bytes[16];
unsigned char hexnibbles[64];
unsigned char hexbytes[64];
unsigned char tmpchar1, tmpchar2, tmpchar3, tmpchar4;
int lines, i, j, k;

program = strrchr (argv[0], '/');
if (argc < 2) {
printf("\nUsage: %s inputfile.dmp > outputfile.hex\n\n", program);
return 0;

fp = fopen(argv[1], "r");
if (fp == 0) {
printf("%s: Could not open %s file for input.\n", program, argv[1]);
return 1;

/*count the lines*/
lines = 0;
while (fscanf(fp, "%s", linein) == 1) {
if (strlen(linein) > 0) {

/* do actual processing */
fp = fopen(argv[1], "r");

/* First write header of hex file */

/* Then write data */
k = 0;
while (fscanf(fp, "%s", linein) == 1) {
/* Convert string of ascii hex values of nibbles into bytes */
for (i=0; i<64; i++) {
nibbles[i] = hex2nibble(linein[i]);

/* swap and complement every two nibbles */
for (i=0; i<32; i++) {
tmpchar1 = nibbles[2*i];
tmpchar2 = nibbles[2*i+1];
tmpchar1 = (~tmpchar1) & 0x0F;
tmpchar2 = (~tmpchar2) & 0x0F;
nibbles[2*i] = tmpchar2;
nibbles[2*i+1] = tmpchar1;

/* Convert to string of hex values */
for (i=0; i<64; i++) {
hexbytes[i] = nibble2hex(nibbles[i]);
/* Output two lines of intel hex file format */
for (i=0; i<2; i++) {
tmpchar1 = (unsigned char) ((16*k) & 0xFF);
tmpchar1 = tmpchar1 + (unsigned char) ( k / 16);
tmpchar1 = tmpchar1 + 16;
tmpchar2 = (unsigned char) ( k / 16 );
tmpchar3 = nibble2hex(tmpchar2 >> 4);
tmpchar4 = nibble2hex(tmpchar2);
printf("%c%c", tmpchar3, tmpchar4);
tmpchar2 = (unsigned char) ((16*k) & 0xFF);
tmpchar3 = nibble2hex(tmpchar2 >> 4);
tmpchar4 = nibble2hex(tmpchar2);
printf("%c%c", tmpchar3, tmpchar4);

for (j=0; j<16; j++) {
printf("%c%c", hexbytes[32*i+2*j], hexbytes[32*i+2*j+1]);
tmpchar2 = 16*nibbles[32*i+2*j] + nibbles[32*i+2*j+1];
tmpchar1 = tmpchar1 + tmpchar2;
tmpchar1 = ~tmpchar1 + 1;
tmpchar2 = tmpchar1 >> 4;
printf("%c%c\n", nibble2hex(tmpchar2), nibble2hex(tmpchar1));
return 0;

RE: Hand Held Products 71M/M eprom carrier question - J-F Garnier - 09-08-2020 06:54 PM

(09-08-2020 01:20 PM)coitboy2000 Wrote:  I thought there may have been an easier way on the PC and one that does not require the forth rom. Can the procedure be done using emu71 ?

Of course there is a simple way, using Emu71. And it's more fun and in the spirit of the HP-71B system :-)

The Intel hex format was commonly used at the time when the EPROM programmers were linked by RS232. Now, most modern programmers accept raw binary files (mine does), I guess this is what you are using too since you spoke about a .bin file coming from Emu71.

In that case, the nibbles are already in the right order in the .bin file, it is just needed to complement the bytes.

The following HP-71B/Emu71 program does it using the DOSLINK device (use ILPer with the HP-71B or Emu71/Win), it reads the input file bytes, complement them and write them back to the output file.
In Emu71/DOS, the DOSLINK input and output files are hardcoded as emu_in.dat and emu_out.dat so copy your source .bin file to emu_in.dat; in ILper you can choose the files.

10 ! 
20 ! uses COMP$ from STRBOOL or ULIB52 LEXs
30 DIM A$[256]
60 FOR I=1 TO 128
80 ENTER :D USING "#,256A";A$
90 OUTPUT :D USING "#,256A";COMP$(A$)
100 NEXT I
110 CLEAR :D

If you don't have or don't want to load the STRBOOL or ULIB52 LEX, you can replace the COMP$ keyword with a loop to complement each byte of A$ with something like:
But COMP$ is much faster.


RE: Hand Held Products 71M/M eprom carrier question - coitboy2000 - 09-08-2020 10:17 PM

Thanks everyone. That's 3 different ways to try. I will give them all a go Smile

I made myself an eprom burner using an arduino mega some voltage regulators and transistors and modified some code from the internet for the 27c256. I might try and incorporate the invert and bit flipping.



RE: Hand Held Products 71M/M eprom carrier question - rprosperi - 09-09-2020 01:16 AM

Wow, several very different options to choose from. Smile

Personally, I like JFG's solution best, because:

- It's 71-based
- It's short, clear and easy to use
- It uses the loop and :DOSLINK to read/update the file in place.


Thanks JFG.

p.s. Also because I can understand this solution; the other 2, not so much without huge amounts of time - not justified for a 1-off.

RE: Hand Held Products 71M/M eprom carrier question - Albert Chan - 09-09-2020 03:56 AM

(09-08-2020 05:32 PM)Albert Chan Wrote:  > echo 0:B3DDDDDEE4642513 | sed -f swap_flip.sed
0: C4 22 22 12 B1 B9 AD CE

Here is the equivalent Python code.
This work slightly better, and handled 'colon-less' format correctly.

> echo B3DDDDDEE4642513 | python swap_flip.py
C4 22 22 12 B1 B9 AD CE

import sys, string
flip = string.maketrans('0123456789ABCDEFabcdef','FEDCBA9876543210543210')

for line in sys.stdin:
    i, j = line.find(':'), line.find('  ')
    s = line[i+1:j].translate(flip, ' ')    # flipped hexdigits only
    print line[:i+1], ' '.join(s[i:i-2:-1] for i in range(1-len(s),0,2))

RE: Hand Held Products 71M/M eprom carrier question - coitboy2000 - 09-09-2020 12:12 PM

Success!! Thanks everyone. The three methods all work, no surprises. The Sed script is almost "instant".


RE: Hand Held Products 71M/M eprom carrier question - coitboy2000 - 09-17-2020 12:16 PM

For anyone einterested, after some experimentation the code below works for me.


using System;
using System.IO;

namespace ConsoleApp4
    class Program
        const string fileName = @"C:\Users\user\Desktop\HP-71B\Eprom Image Files\math2b5.bin";
        const string fileName2 = @"C:\Users\user\Desktop\HP-71B\Eprom Image Files\eprom2.bin";
        static void Main(string[] args)
            byte[] buff = File.ReadAllBytes(fileName);
            var len = (int)buff.Length;
            using (BinaryWriter writer = new BinaryWriter(File.Open(fileName2, FileMode.Create)))
                for (int ix = 0; ix < len; ix ++)
                    buff[ix] = (byte)(~buff[ix]);
                    int value = buff[ix];
                    value = value ^ 1;

RE: Hand Held Products 71M/M eprom carrier question - grsbanks - 09-18-2020 08:31 AM

Would you mind sticking that in "code" tags so that the indentation isn't lost?

RE: Hand Held Products 71M/M eprom carrier question - Hiwi - 03-20-2023 11:17 AM

this is a very old thread but i can add something to our knowledge base.
I have a HHP 32KRam/32KEprom cardreader module.

I am burning my eproms with a china clone willem programmer PCB V5 which i was using for programming PIC's and EEPROM's before.

The free software is Version 0.96 and has a feature to invert the bytes of the romfile just by a simple click from the options menu.

This works without any problems.

I have programmed many eproms until now and had no problems with CMOS or NMOS Version they work all and never failed.