*.swp
+*.o
*.bin
*.img
+*.pgm
+*.log
+*.rle
+dis
+rle/rle
+rle/unrle
dd if=/dev/zero of=$@ bs=512 count=2880
dd if=$< of=$@ bs=512 conv=notrunc
-$(bin): bootsplash.asm
+$(bin): bootsplash.asm nuclear.rle
nasm -f bin -o $@ $<
+nuclear.rle: nuclear.img
+ cat $< | rle/rle >$@ 2>rle.log
+
.PHONY: run
run: $(img)
qemu-system-i386 -fda $<
.PHONY: debug
debug: $(img)
qemu-system-i386 -S -s -fda $<
+
+.PHONY: disasm
+disasm: $(bin)
+ ndisasm -o 0x7c00 $< >dis
xor ax, ax
mov es, ax
+ mov ds, ax
mov ax, str_booting
call printstr
.hang: hlt
jmp .hang
+ ; splash screen effect
splash:
mov ax, 13h
int 10h
mov ax, 0a000h
mov es, ax
xor di, di
- mov cx, 32000
- mov ax, 0505h
- rep stosw
+
+ mov ax, pic
+ shr ax, 4
+ mov ds, ax
+ xor si, si
+
+ mov cx, 64000
+ call decode_rle
call waitkey
mov ax, 3
int 10h
+ ret
+
+ ; decode RLE from ds:si to es:di, cx: number of decoded bytes (0 means 65536)
+ ; - high bit set for the repetition count, followed by a value byte to
+ ; be repeated N times
+ ; - high bit not set for raw data that should be copied directly
+decode_rle:
+ mov al, [si]
+ inc si
+ mov bl, 1 ; default to "copy once" for raw values
+ test al, 0x80 ; test the high bit to see if it's a count or a raw value
+ jz .copy
+ ; it's a count, clear the high bit, and read the next byte for the value
+ and al, 0x7f
+ mov bl, al
+ mov al, [si]
+ inc si
+.copy: mov [es:di], al
+ inc di
+ dec cx ; decrement decoded bytes counter
+ jz .end ; as soon as it reaches 0, bail
+ dec bl
+ jnz .copy
+ jmp decode_rle
+.end: ret
+
waitkey:
in al, 64h
in al, 60h
ret
+ ; data
+ align 16
+pic: incbin "nuclear.rle"
+
stage2_end:
; vi:set ft=nasm:
--- /dev/null
+all: rle unrle
+
+rle: rle.o
+ $(CC) -o $@ $< $(LDFLAGS)
+
+unrle: unrle.o
+ $(CC) -o $@ $< $(LDFLAGS)
+
+clean:
+ $(RM) rle.o
+ $(RM) rle
+ $(RM) unrle.o
+ $(RM) unrle
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+
+void emit(int c, int count);
+
+int main(void)
+{
+ int c, lastc, count;
+
+ lastc = -1;
+ count = 0;
+
+ while((c = getchar()) != -1) {
+ if(c == lastc && count < 127) {
+ count++;
+ } else {
+ emit(lastc, count);
+ count = 1;
+ lastc = c;
+ }
+ }
+ emit(lastc, count);
+
+ return 0;
+}
+
+void emit(int c, int count)
+{
+ if(count <= 0 || c < 0) return;
+
+ fprintf(stderr, "emit(%d, %d) -> ", c, count);
+ if(count > 2 || (c & 0x80)) {
+ fprintf(stderr, "%02x %02x\n", (unsigned int)count | 0x80, (unsigned int)c);
+ putchar(count | 0x80);
+ putchar(c);
+ } else {
+ while(count--) {
+ fprintf(stderr, "%02x\n", (unsigned int)c & 0x7f);
+ putchar(c);
+ }
+ }
+}
--- /dev/null
+#include <stdio.h>
+
+int main(void)
+{
+ int c, count, rawbytes = 0;
+
+ printf("P5\n320 200\n255\n");
+
+ while((c = getchar()) != -1) {
+ if(c & 0x80) {
+ count = c & 0x7f;
+ if((c = getchar()) == -1) {
+ fprintf(stderr, "Unexpected EOF while decoding RLE data\n");
+ return 1;
+ }
+ rawbytes += count;
+ while(count--) putchar(c);
+ } else {
+ rawbytes++;
+ putchar(c);
+ }
+ }
+
+ fprintf(stderr, "decoded (raw) size: %d bytes\n", rawbytes);
+ return 0;
+}