/
EndingPatch.ts
105 lines (94 loc) · 3.07 KB
/
EndingPatch.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/*
* Copyright (C) 2016 Klaus Reimer <k@ailis.de>
* See LICENSE.md for licensing information.
*/
import { BinaryReader } from "../io/BinaryReader";
import { COLOR_PALETTE } from "../image/colors";
/**
* Image update patch.
*/
export class EndingPatch {
/** The image offset to update. */
private offset: number;
/** The patch data (Four bytes with eight 4-bit colors). */
private data: number[];
/**
* Creates a new update patch,
*
* @param offset The image update offset.
* @param data The patch data (Four bytes with eight 4-bit colors).
*/
private constructor(offset: number, data: number[]) {
this.offset = offset;
this.data = data;
}
/**
* Returns the raw offset to update. This is the raw offset value from the END.CPA file measured in 8 byte
* blocks relative to a 320 pixels wide screen. Too complex to use. So it's recommended to use the
* [[getX]]() and [[getY]]() methods which converts this offset into pixel coordinates relative to
* the image. Or use the [[getOffset]]() method which returns the offset byte address in the image data.
*
* @return The raw image update offset.
*/
public getRawOffset(): number {
return this.offset;
}
/**
* Returns the byte offset in the image data array to update.
*
* @return The byte offset in the image data array to update.
*/
public getOffset(): number {
return this.getY() * 144 + (this.getX() >> 1);
}
/**
* The horizontal update position in pixels relative to the image.
*
* @return The horizontal update position.
*/
public getX(): number {
return this.offset * 8 % 320;
}
/**
* The vertical update position in pixels relative to the image.
*
* @return The vertical update position.
*/
public getY(): number {
return (this.offset * 8 / 320) | 0;
}
/**
* Returns the patch data to apply to the image. Always four bytes with eight 4-bit colors.
*
* @return The patch data.
*/
public getData(): number[] {
return this.data.slice();
}
/**
* Returns the RGBA color at the specified position.
*
* @param x The horizontal pixel position.
* @return The RGBA color at the specified position.
*/
public getColor(x: number): number {
const pixelTuple = this.data[x >> 1];
const pixel = x & 1 ? pixelTuple & 0xf : pixelTuple >> 4;
return COLOR_PALETTE[pixel];
}
/**
* Reads an update patch from the given reader. If end of animation update block is reached then `null` is
* returned.
*
* @param reader The reader to read the update patch from.
* @return The read update patch or null if end of update block is reached.
*/
public static read(reader: BinaryReader): EndingPatch | null {
const offset = reader.readUint16();
if (offset === 0xffff) {
return null;
}
const pixels = reader.readUint8s(4);
return new EndingPatch(offset, pixels);
}
}