Swapping bits in bytes in a file - Page 1
Forum section: electronics / projects

author: Alex Eisenhut
author_rank: Super Contributor
timestamp: January 11, 2020, 04:16:38 pm
content: I am working on an old Commodore compatible floppy drive. The manufacturer swapped data bits around on the motherboard so that Commodore ROMs don't work directly.Is there a utility or something that can read in a binary file, swap two bits around and output the swapped byte into a new file?Worst case I guess I can do it in Excel if I can get ASCII hex data.

author: BrianHG
author_rank: Super Contributor
timestamp: January 11, 2020, 05:11:31 pm
content: This editor has some pretty bit manipulation capabilities:https://www.hhdsoftware.com/free-hex-editorThough I see reverse bits and rotate left and right, cycling through a pattern of these 3 may allow you to achieve the correct bit swapping you require.

author: NiHaoMike
author_rank: Super Contributor
timestamp: January 11, 2020, 05:45:21 pm
content: It would be trivial to program in Python. Learn how to (make sure the guide you use is Python 3, since Python 2 is obsolete) and you'll wonder why you didn't start learning it earlier.

author: Benta
author_rank: Super Contributor
timestamp: January 11, 2020, 05:47:33 pm
content: Wouldn't it be easier to swap the two lines to the ROM on the PCB? (cut 'n jumper).

author: amyk
author_rank: Super Contributor
timestamp: January 11, 2020, 08:48:21 pm
content: It's around a dozen lines of C... if you specify how you want the bits to be swapped I can probably write it for you in a few minutes.

author: mariush
author_rank: Super Contributor
timestamp: January 11, 2020, 10:24:31 pm
content: Here's a php script that does it, just wrote it right now in the last 5 minutes :Save code below in a folder with the .php extension (paste in notepad, save as and select "All Files" at file type, enter name with .php extension) then put the file you want modified in same folder as input.binDownload php from php.net and run php.exe c:\path\to\script.php and it will produce$byte = flipbits($byte,0,7);that line swaps bit 0 with bit 7 ... you can change the 0 and 7 with whatever you want. You can also have consecutive lines (ex swap 0,7 then swap 1,6 ... to have 2 pairs of bits swapped.Code:<?php// Opens input.bin , flips bits in every byte and saves to output.binfunctionflipbits($value,$first,$second) {$bits= array();$bitstring=str_pad(decbin($value),8,'0',STR_PAD_LEFT);for ($i=0;$i<8;$i++)$bits[$i] =substr($bitstring,$i,1);$temp=$bits[$first];$bits[$first] =$bits[$second];$bits[$second] =$temp;$bitstring='';for ($i=0;$i<8;$i++)$bitstring.=$bits[$i];returnbindec($bitstring);}$input=file_get_contents(__DIR__.'/input.bin');$h=fopen(__DIR__.'/output.bin','wb');for ($i=0;$i<strlen($input);$i++) {$byte=ord(substr($input,$i,1));// call the function every time you need to flip a bits// ex flip bit 0 with bit 7$byte=flipbits($byte,0,7);// repeat as neededfwrite($h,chr($byte));}fclose($h);echo"Done. Saved to output.bin";?>

author: Alex Eisenhut
author_rank: Super Contributor
timestamp: January 12, 2020, 09:55:20 pm
content: Thanks, I have studied the drive more closely and it came in at least two variants, one with 16K of ROM in one chip and the other split across two 8K chips.I have the two chip version, and splitting the 16K ROM into two 8K images doesn't work.It turns out the data bits are scrambled differently across the ROMs in the two chip version.I'll try that PHP thing soon.

author: Alex Eisenhut
author_rank: Super Contributor
timestamp: January 12, 2020, 09:57:02 pm
content: Quote from: Benta on January 11, 2020, 05:47:33 pmIt might get to that, the PCB actually has solder jumpers already there but I don't know what they do yet. They mixed up the data bits differently across the two ROMs.

author: Nominal Animal
author_rank: Super Contributor
timestamp: January 12, 2020, 11:05:27 pm
content: Here's a quick Python3 skeleton for bit mapping:Code:#!/usr/bin/env python3 -B# -*- coding: utf-8 -*-from sys import stdin, stdout, stderr, argv, exitdef bytefilter(source, output, mapping, chunk=2097152):while True:try:data = source.read(chunk)except BlockingIOError:returnif len(data) < 1:returnoutput.write(data.translate(mapping))def bitremap(byte, form):result = 0for i in range(0, 8):dstbit = 7 - isrcbit = int(form)if (byte & (1 << srcbit)):result |= 1 << dstbitreturn resultif __name__ == '__main__':if len(argv) != 4:stderr.write("\n")stderr.write("Usage: %s INPUTFILE OUTPUTFILE BITPATTERN\n" % argv)stderr.write("\n")stderr.write("For no translation, use bitpattern 76543210.\n")stderr.write("\n")exit(1)if len(argv) != 8 or len(argv.rstrip("01234567")) != 0:stderr.write("%s: Invalid bit pattern.\n" % argv)exit(1)mapping = b''for i in range(0, 256):mapping += b'%c' % bitremap(i, argv)try:source = open(argv, mode='rb')except FileNotFoundError:stderr.write("%s: No such file.\n" % argv)exit(1)output = open(argv, mode='wb')bytefilter(source, output, mapping)Run it without parameters to see usage. Simply put, it takes an input filename, and output filename, and the 8-digit bit pattern to use.Normal bit pattern is 76543210. If you wish to swap the second bit (bit 1) and fourth bit (bit 3), use 76541230.Essentially, the third parameter tells how the bits in the input bytes are mapped to the output file bytes.It does not stop you from doing silly things, like 77777701, which uses the highest bit in input bytes for all but the two lowest bits, and swaps those two lowest bits.The way this Python program works, is by constructing a 256-byte lookup table. The bitremap() function transforms one numeric value using the form string; it is called once for each possible byte value, to construct the lookup table. The Python .translate() method does the lookup efficiently.

author: Alex Eisenhut
author_rank: Super Contributor
timestamp: January 13, 2020, 11:57:01 pm
content: Looks like I'm not the only one who came across this scrambling problemhttps://www.commodoreserver.com/PublicDiskDetails.asp?DID=DFF943F2D52D40EE8D73DD950E5F02EBSomeone wrote a scrambler program that runs on the 64... Hilarious.