From: John Tsiombikas Date: Tue, 15 Dec 2020 02:13:28 +0000 (+0200) Subject: RLE blitter, plus RLE encoding and decoding tools X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=bootsplash;a=commitdiff_plain;h=5731d2abe8e8c4b838f8d1b0eefdc25754f6ad78 RLE blitter, plus RLE encoding and decoding tools --- diff --git a/.gitignore b/.gitignore index d9e3493..492e4f8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,10 @@ *.swp +*.o *.bin *.img +*.pgm +*.log +*.rle +dis +rle/rle +rle/unrle diff --git a/Makefile b/Makefile index a9d1f17..2ae07cf 100644 --- a/Makefile +++ b/Makefile @@ -5,9 +5,12 @@ $(img): $(bin) 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 $< @@ -15,3 +18,7 @@ run: $(img) .PHONY: debug debug: $(img) qemu-system-i386 -S -s -fda $< + +.PHONY: disasm +disasm: $(bin) + ndisasm -o 0x7c00 $< >dis diff --git a/bootsplash.asm b/bootsplash.asm index e8c4cc7..a6a552a 100644 --- a/bootsplash.asm +++ b/bootsplash.asm @@ -61,6 +61,7 @@ stage2_start: xor ax, ax mov es, ax + mov ds, ax mov ax, str_booting call printstr @@ -69,6 +70,7 @@ stage2_start: .hang: hlt jmp .hang + ; splash screen effect splash: mov ax, 13h int 10h @@ -76,14 +78,45 @@ splash: 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 @@ -92,6 +125,10 @@ waitkey: in al, 60h ret + ; data + align 16 +pic: incbin "nuclear.rle" + stage2_end: ; vi:set ft=nasm: diff --git a/rle/Makefile b/rle/Makefile new file mode 100644 index 0000000..1d50a5b --- /dev/null +++ b/rle/Makefile @@ -0,0 +1,13 @@ +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 diff --git a/rle/rle.c b/rle/rle.c new file mode 100644 index 0000000..4acb24c --- /dev/null +++ b/rle/rle.c @@ -0,0 +1,42 @@ +#include +#include + +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); + } + } +} diff --git a/rle/unrle.c b/rle/unrle.c new file mode 100644 index 0000000..7f70edd --- /dev/null +++ b/rle/unrle.c @@ -0,0 +1,26 @@ +#include + +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; +}