From: Brett Gordon Date: Sun, 3 Jul 2016 16:50:19 +0000 (-0400) Subject: Init commit, in working state. X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=c8ffd83014b49414cdbcd7c5e874cdce67e3950c;p=FUZIX.git Init commit, in working state. --- diff --git a/Applications/fview/Makefile.6809 b/Applications/fview/Makefile.6809 new file mode 100644 index 00000000..5e39f2ac --- /dev/null +++ b/Applications/fview/Makefile.6809 @@ -0,0 +1,38 @@ +PLATFORM = 6809 +CC = m6809-unknown-gcc +# These are wrappers for lwasm and lwar +ASM = m6809-unknown-as +AR = m6809-unknown-ar +LINKER = lwlink +CFLAGS = -I../../Library/include -I../../Library/include/6502 +LINKER_OPT = --format=raw -L../../Library/libs -lc6809 +LIBGCCDIR = $(dir $(shell $(CC) -print-libgcc-file-name)) +LINKER_OPT += -L$(LIBGCCDIR) -lgcc +LINKER_OPT += --script=../util/$(TARGET).link +ASM_OPT = -o +CRT0 = ../../Library/libs/crt0_6809.o + +.SUFFIXES: .c .o + + +SRCS = fview.c + +OBJS = $(SRCS:.c=.o) + +APPS = $(OBJS:.o=) + +all: $(APPS) size.report + +$(APPS): $(CRT0) + +$(APPS): %: %.o + $(LINKER) -o $@ $(LINKER_OPT) $^ + +size.report: $(APPS) + ls -l $^ > $@ + +clean: + rm -f $(OBJS) $(APPS) $(SRCS:.c=) core *~ *.asm *.lst *.sym *.map *.noi *.lk *.ihx *.tmp *.bin size.report + +rmbak: + rm -f *~ core diff --git a/Applications/fview/fview.c b/Applications/fview/fview.c new file mode 100644 index 00000000..1c741986 --- /dev/null +++ b/Applications/fview/fview.c @@ -0,0 +1,338 @@ +#include +#include +#include +#include +#include +#include +#include + +struct bmp_header { + char header[2]; + uint32_t size; + uint16_t res1; + uint16_t res2; + uint32_t offset; +}; + +struct bmp_dib { + uint32_t size; + uint32_t width; + uint32_t height; + uint16_t planes; + uint16_t bpp; + uint32_t comp; + uint32_t dsize; + int32_t hres; + int32_t vres; + uint32_t colors; +}; + +struct bmp_palette { + uint8_t blue; + uint8_t green; + uint8_t red; + uint8_t zero; +}; + +struct box { + uint16_t size; + uint16_t y; + uint16_t x; + uint16_t h; + uint16_t w; +}; + +struct display entry_disp; /* state of display on program entry */ +struct display disp; /* general struct for noodling */ +uint8_t *lbuf; /* bmp line buffer */ +uint8_t *obuf; /* output line buffer to tty dev */ +struct bmp_palette *pal; /* table of palette entries */ +int16_t *error1; /* error buffer 1 */ +int16_t *error2; /* error buffer 2 */ +int16_t *err_cur; /* ptr to current line's errors */ +int16_t *err_next; /* ptr to next line's errors */ + +#ifndef LITTLE_ENDIAN +uint16_t swizzle16( uint16_t d ){ + return d << 8 | d >> 8 ; +} + + +uint32_t swizzle32( uint32_t d ){ + return d >> 24 | + ( d >> 8 ) & 0xff00 | + ( d << 8 ) & 0xff0000 | + ( d << 24 ); +} +#endif + +void println( uint8_t *buf){ + int i; + for( i=0; i<42; i++){ + printf("%.2x ", buf[i] ); + } + printf("\n"); +} + + +/* scan the tty driver's nodes. Pick the one that gives us the most resolution at 1bpp, and can do a direct WRITE ioctl */ +int scan_modes(void) { + int i = 0; + unsigned maxres=0; + int ret=0; + unsigned res; + + /* get state, info */ + if (ioctl(1, GFXIOC_GETINFO, &entry_disp) < 0) + return -1; + if (ioctl(1, GFXIOC_GETINFO, &disp) < 0) + return -1; + for(; 1; i++) { + disp.mode = i; + if (ioctl(1, GFXIOC_GETMODE, &disp) < 0) + break; + if( ! (disp.commands & GFX_WRITE) ) continue; + if( ! (disp.format & FMT_MONO_WB) ) continue; + if( disp.width != 256 ) continue; + res = disp.width * disp.height; + if( res > maxres ){ + maxres = res; + ret=i; + } + } + return ret; +} + +void exit_err_mess( char *mess ){ + fprintf( stderr, mess ); + fputc( '\n', stderr ); + exit(1); +} + +uint8_t intensity( struct bmp_palette *p ){ + uint16_t c; + c = (p->red * 2); + c += (p->green * 5); + c += p->blue; + return c/8; +} + +/* This exchanges our error buffers - creating a 2 line-element ring buffer */ +void flip_err( void ){ + if( err_cur == error1 ){ + err_cur = error2; + err_next = error1; + } + else{ + err_cur = error1; + err_next = error2; + } +} + +void fs_dist( int16_t e, uint16_t i ){ + /* distribute error */ + err_cur[ i + 1 ] = e * 7 ; + err_next[ i - 1 ] += e * 3 ; + err_next[ i ] += e * 5 ; + err_next[ i + 1 ] += e ; +} + + +/* Tranlate a line worth of 8 bpp source data to 1 bpp */ +void bpp8( void ){ + int i,j,c,x,e; + int erri=1; + uint8_t *out = obuf+sizeof(struct box); + uint8_t *in = lbuf; + flip_err(); + memset( err_next, 0, 516 ); + for( i=0; i<32; i++){ + c=0; + for( j=0; j<8; j++ ){ + c = c << 1; + x= intensity( &(pal[*in++]) ) + err_cur[ erri ]/16; + if( x > 127 ){ + c++; + e=x-256; + } + else{ + e=x; + } + fs_dist( e, erri ); + erri++; + } + *out++ = c; + } + +} + + +void bpp4( void ){ + int i,j,k,c,x,e; + int erri=1; + uint8_t *out = obuf+sizeof(struct box); + uint8_t *in = lbuf; + uint8_t pix[2]; + flip_err(); + memset( err_next, 0, 516 ); + for( i=0; i<32; i++){ + c=0; + for( j=0; j<4; j++ ){ + pix[0]= *in >> 4; + pix[1]= *in++ & 0xf; + for( k=0; k<2; k++ ){ + /* first nibble of in */ + c = c << 1; + x = intensity( &(pal[ pix[k] ]) ) + err_cur[ erri ]/16; + if( x > 127 ){ + c++; + e=x-256; + } + else{ + e=x; + } + fs_dist( e, erri ); + erri++; + } + } + *out++ = c; + } + +} + +int main( int argc, char *argv[] ) +{ + int fd,ret; + struct bmp_header h; + struct bmp_dib d; + int rsize; + struct box *lbox; + int i,j; + + + if( argc<2 ) + exit_err_mess("usage: fview file"); + + fd=open( argv[1], O_RDONLY ); + if( fd<0 ) + exit_err_mess("error opening bitmap"); + + /* get file header */ + ret = read( fd, &h, sizeof(h) ); + /* swizzle bitmap fields */ +#ifndef LITTLE_ENDIAN + h.size = swizzle32( h.size ); + h.offset = swizzle32( h.offset ); +#endif + + /* get dib header */ + ret = read( fd, &d, sizeof(d) ); + /* swizzle its fields */ +#ifndef LITTLE_ENDIAN + d.size = swizzle32( d.size ); + d.width = swizzle32( d.width ); + d.height = swizzle32( d.height ); + d.planes = swizzle16( d.planes ); + d.bpp = swizzle16( d.bpp ); + d.comp = swizzle32( d.comp ); + d.dsize = swizzle32( d.dsize ); + /* -- skip swizzling some unused data -- */ + d.colors = swizzle32( d.colors ); +#endif + + /* get pallete table */ + if( lseek( fd, sizeof(h)+d.size, SEEK_SET ) < 0 ) + exit_err_mess("seek error in palette table"); + pal=malloc( sizeof(struct bmp_palette)*d.colors ); + if( pal == NULL ) + exit_err_mess("cannot malloc pallete buffer"); + ret= read( fd, pal, sizeof(struct bmp_palette)*d.colors); + if( ret != sizeof(struct bmp_palette)*d.colors ) + exit_err_mess("read error loading palette"); + + /* Allocate dithering error buffers */ + /* fixme: need to check for malloc errors */ + error1 = calloc( 256 + 2, sizeof( int16_t ) ); + error2 = calloc( 256 + 2, sizeof( int16_t ) ); + if( error1 == NULL | error2 == NULL ) + exit_err_mess("cannot alloc dither buffers"); + flip_err(); + + + printf("header: %c%c\n", h.header[0], h.header[1] ); + printf("width: %d, height: %d\n", (uint16_t)d.width, (uint16_t)d.height ); + printf("bpp: %d\n", d.bpp ); + printf("pallete entries: %d\n", (uint16_t)d.colors ); + + + rsize = (( d.bpp * d.width + 31 ) / 32 ) * 4; + + /* fixme: what if bmp width < screen width ? */ + lbuf=malloc( rsize ); + if( lbuf == NULL ) + exit_err_mess("cannot malloc line buffer"); + + obuf=malloc( disp.width / 8 + sizeof(struct box) ); + if( obuf == NULL ) + exit_err_mess("cannot malloc dev buffer"); + + lbox=(struct box *)obuf; + + + if( lseek( fd, h.offset, SEEK_SET)<0 ) + exit_err_mess("seek error in bitmap file"); + + lbox->size = 40; + lbox->x = 0; + lbox->h = 1; + lbox->w = 32; + + /* set video mode */ + + disp.mode=scan_modes(); + if( disp.mode < 0 ) + exit_err_mess("No suitable graphics mode found"); + + if( ioctl( 1, GFXIOC_SETMODE, &disp ) < 0 ) + exit_err_mess("Cannot set graphics mode"); + + + /* loop */ + for( i=disp.height-1; i>-1; i-- ){ + /* get a line from the file */ + ret=read( fd, lbuf, rsize ); + if( ret < rsize ) { + printf("file read error: %d\n", ret ); + goto leave; + } + /* pixate the transels here */ + switch( d.bpp ){ + case 1: + memcpy( obuf+sizeof(struct box), lbuf, 32 ); + break; + case 4: + bpp4(); + break; + case 8: + bpp8(); + break; + default: + printf("unsupported bpp.\n"); + goto leave; + } + /* output line to video device */ + lbox->y = i; + ret=ioctl( 0, GFXIOC_WRITE, obuf ); + if( ret < 0 ){ + printf("dev write error: %d\n", ret ); + goto leave; + } + } + + getchar(); + leave: + /* unset video mode */ + ioctl( 1, GFXIOC_SETMODE, &entry_disp ); + + exit(0); +} diff --git a/Applications/fview/test.bmp b/Applications/fview/test.bmp new file mode 100644 index 00000000..be108e5b Binary files /dev/null and b/Applications/fview/test.bmp differ diff --git a/Applications/fview/test2.bmp b/Applications/fview/test2.bmp new file mode 100644 index 00000000..93ab5edd Binary files /dev/null and b/Applications/fview/test2.bmp differ diff --git a/Applications/fview/test3.bmp b/Applications/fview/test3.bmp new file mode 100644 index 00000000..99964a7f Binary files /dev/null and b/Applications/fview/test3.bmp differ