For some reason before continuing to the `BitmapToData` function, I decided to
focus on finding out which activityType the PrintPreviewActivity class had, and
this lead to nothing, just half a day of my live wasted.
While searching for that, I discovered the class `com.Utils.PrinterModel` and
the util class for creating the `PrinterModel`s - `com.Utils.PrintModelUtils`.
The former held every possible attribute for a printer and the latter creates a
PrinterModel instance presumably for every model, supported by the app.
In `PrinterModel` there was a big function that just assigns certain fields to
its arguments, and it was called in `PrintModelUtils` for each model. The
function looks like this:
```java
public DataBean(String str, int i, int i2, int i3, int i4, int i5, String str2,boolean z, int i6, int i7, int i8, int i9, boolean z2, int i10, int i11, int i12, int i13, int i14, int i15, boolean z3, boolean z4, boolean z5, booleanz6, String str3, int i16, int i17) {
this.grayPrint = false;
this.grayThinEneragy = 0;
this.grayModerationEneragy = 0;
this.grayDeepenEneragy = 0;
this.slowInterval = 0;
this.grayImageSpeed = 40;
this.grayScale = 1.0d;
this.showElectricityModel = 0;
this.addMorPix = true;
this.A4XII = false;
this.tattooPaper = false;
this.tattooSpeed = 0;
this.tattooEnergy = 0;
this.addMorePixNum = -1;
this.d1key = "";
this.useNewActivation = false;
this.lzoVersion = "";
this.labelDevice = false;
this.labelDeviceSize = 0.0f;
this.autoLabelCheck = false;
this.corePrint = false;
this.modelNo = str;
this.model = i;
this.size = i2;
this.paperSize = i3;
this.printSize = i4;
this.oneLength = i5;
this.headName = str2;
this.canChangeMTU = z;
this.devdpi = i6;
this.imgPrintSpeed = i7;
this.textPrintSpeed = i8;
this.imgMTU = i9;
this.newCompress = z2;
this.paperNum = i10;
this.interval = i11;
this.thinEneragy = i12;
this.moderationEneragy = i13;
this.deepenEneragy = i14;
this.textEneragy = i15;
this.hasId = z3;
this.useSPP = z4;
this.newFormat = z5;
this.canPrintLabel = z6;
this.labelValue = str3;
this.backPaperNum = i16;
this.detectionValue = i17;
}
```
I noticed that in `PrintModelUtils` there were two printers with the name "X6" -
one was `x6` and one was `x6_n`. I mentally noted that fact and coppied the x6
function call above the DataBean function in a seperate file. Then I created
this **legendary** vim macro:
```
0f(l"ddt,xxj0f(ldw"edt,xxjvi{:s/^Re;/^Rd;^M?{k0
```
It takes each argument and replaces it, so I had a file with all the model's
characteristics. (See [x6_n.java](reverse_engineering/x6_n.java))
## 5. Finally in the right direction
I began reading the function `BitmapToData()` in
`com.lib.blueUtils.PrintDataUtils`. In there I discovered the command for
getting the printer's status (0x`51 78 A3 00 01 00 00 00 FF`). The function did
other things, but it lead me to `eachLinePixToCmdB()`. That method also wasn't
decompiled, but I assumed the grayscale variant `eachLinePixToCmdGray()`, which
was, would be similar, so I started reading that. After a little reading I
realised that their logic was definitely not the same so for the second time I
started reading java pseudo-bytecode line-by-line with a second vim window open
for notes about what each "variable" (register) contained at any given moment.
When in the first few lines of the function I saw the line width getting divided
by 8, I knew I was in the right place.
## 6. Discovering packets (commands)
I slowly discovered several packet types:
- enerAgy: 0x`51 78 AF 00 02 00 <energy_low><energy_high><crc> FF`
- printType: 0x`51 78 BE 00 01 00 <type><crc> FF`, where the types are:
-`0x00` for Image
-`0x01` for Text
-`0x02` for Tattoo (which I ignored since my printer doesn't support it)