diff --git a/graphics/dgr_viewer/Makefile b/graphics/dgr_viewer/Makefile index d654835c..b1e1b3ca 100644 --- a/graphics/dgr_viewer/Makefile +++ b/graphics/dgr_viewer/Makefile @@ -1,25 +1,21 @@ include ../../Makefile.inc DOS33 = ../../utils/dos33fs-utils/dos33 -PNG2GR = ../../utils/gr-utils/png2gr -PNG2RLE = ../../utils/gr-utils/png2rle +PNG2DGR = ../../utils/gr-utils/png2dgr TOKENIZE = ../../utils/asoft_basic-utils/tokenize_asoft -all: dgr_view.dsk - - -dgr_view.dsk: $(DOS33) DGR_VIEW - cp empty.dsk dgr_view.dsk - $(DOS33) -y dgr_view.dsk BSAVE -a 0x1000 DGR_VIEW +all: make_dgr_viewer ### -DGR_VIEW: dgr_view.o - ld65 -o DGR_VIEW dgr_view.o -C ../../linker_scripts/apple2_1000.inc +make_dgr_viewer: make_dgr_viewer.o + $(CC) $(LFLAGS) -o make_dgr_viewer make_dgr_viewer.o -dgr_view.o: dgr_view.s - ca65 -o dgr_view.o dgr_view.s -l dgr_view.lst +make_dgr_viewer.o: make_dgr_viewer.c + $(CC) $(CFLAGS) -c make_dgr_viewer.c + +### clean: - rm -f *~ *.o DGR_VIEW *.lst + rm -f *~ *.o DGR_VIEW *.lst make_dgr_viewer diff --git a/graphics/dgr_viewer/dlores_main.s b/graphics/dgr_viewer/dlores_main.s new file mode 100644 index 00000000..971caf9e --- /dev/null +++ b/graphics/dgr_viewer/dlores_main.s @@ -0,0 +1,171 @@ +; VMW Productions DGR/ZX02 viewer + +; by Vince `deater` Weaver + + +.include "zp.inc" +.include "hardware.inc" + +WHICH = $E0 + +dgr_start: + + ;=================== + ; Init RTS disk code + ;=================== + + jsr rts_init + + ;=================== + ; set graphics mode + ;=================== + jsr HOME + + lda SET_GR ; graphics + lda LORES ; lores + sta SET80COL ; enable 80-column hardware + lda FULLGR ; mixset + sta CLRAN3 ; enable double-wide graphics + + sta EIGHTYSTOREON ; PAGE2 remaps MAIN:page1 writes to AUX:page1 + + + lda #0 + sta WHICH + + ;=================== + ; Load graphics + ;=================== +load_loop: + + ;============================= + + ldx WHICH + + lda main_filenames_low,X + sta OUTL + lda main_filenames_high,X + sta OUTH + + lda aux_filenames_low,X + sta INL + lda aux_filenames_high,X + sta INH + + jsr load_image + +wait_until_keypress: + lda KEYBOARD ; 4 + bpl wait_until_keypress ; 3 + bit KEYRESET ; clear the keyboard buffer + + cmp #$88 ; left button + bne inc_which + + dec WHICH + bpl which_ok + + ldx #(MAX_FILES-1) + bne store_which ; bra + +inc_which: + inc WHICH + ldx WHICH + cpx #MAX_FILES + bcc which_ok ; blt + + + ldx #0 +store_which: + stx WHICH + +which_ok: + jmp load_loop + + + ;========================== + ; Load Image + ;=========================== + +load_image: + + bit PAGE1 + + jsr opendir_filename ; open and read entire file into memory + + lda #<$A000 + sta zx_src_l+1 + + lda #>$A000 + sta zx_src_h+1 + + lda #$0c + + jsr zx02_full_decomp + + jsr copy_to_400 ; try to avoid holes + + bit PAGE2 + + lda INL + sta OUTL + lda INH + sta OUTH + + jsr opendir_filename ; open and read entire file into memory + + lda #<$A000 + sta zx_src_l+1 + + lda #>$A000 + sta zx_src_h+1 + + lda #$0c + + jsr zx02_full_decomp + + jsr copy_to_400 ; try to avoid holes + + rts + + + + ;========================= + ; copy to 400 + ;========================= +copy_to_400: + + + ldx #119 +looper1: + lda $c00,X + sta $400,X + + lda $c80,X + sta $480,X + + lda $d00,X + sta $500,X + + lda $d80,X + sta $580,X + + lda $e00,X + sta $600,X + + lda $e80,X + sta $680,X + + lda $f00,X + sta $700,X + + lda $f80,X + sta $780,X + dex + bpl looper1 + + rts + + + .include "zx02_optim.s" + .include "rts.s" diff --git a/graphics/dgr_viewer/empty.dsk b/graphics/dgr_viewer/empty.dsk deleted file mode 100644 index b34eb519..00000000 Binary files a/graphics/dgr_viewer/empty.dsk and /dev/null differ diff --git a/graphics/dgr_viewer/hardware.inc b/graphics/dgr_viewer/hardware.inc new file mode 100644 index 00000000..94a29e53 --- /dev/null +++ b/graphics/dgr_viewer/hardware.inc @@ -0,0 +1,92 @@ +; HARDWARE LOCATIONS / SOFT SWITCHES + +KEYBOARD = $C000 ; (read) most recent keypress +EIGHTYSTOREOFF = $C000 ; (write) turn off 80store +EIGHTYSTOREON = $C001 ; (write) page2 means 400/2000 write to aux mem + +CLR80COL = $C00C ; (write) set 40-column +SET80COL = $C00D ; (write) set 80-column + +KEYRESET = $C010 ; clear keyboard strobe + +SPEAKER = $C030 +SET_GR = $C050 +SET_TEXT = $C051 +FULLGR = $C052 +TEXTGR = $C053 +PAGE1 = $C054 +PAGE2 = $C055 +LORES = $C056 ; Enable LORES graphics +HIRES = $C057 ; Enable HIRES graphics +CLRAN3 = $C05E ; Annunciator 3 + ; (read/write) if 80 col mode, enable double graphics +SETAN3 = $C05F ; (read/write) if 80 col mode, enable single-graphics + +PADDLE_BUTTON0 = $C061 +PADDL0 = $C064 +PTRIG = $C070 + +; Language card +; C080 +; C08B + +;; BASIC ROUTINES + +;NORMAL = $F273 + +;; MONITOR ROUTINES + +;HLINE = $F819 ;; HLINE Y,$2C at A +;VLINE = $F828 ;; VLINE A,$2D at Y +;CLRSCR = $F832 ;; Clear low-res screen +;CLRTOP = $F836 ;; clear only top of low-res screen +;SETCOL = $F864 ;; COLOR=A +;TEXT = $FB36 +;TABV = $FB5B ;; VTAB to A +;BELL = $FBDD ;; ring the bell +;BASCALC= $FBC1 ;; +;VTAB = $FC22 ;; VTAB to CV +HOME = $FC58 ;; Clear the text screen +WAIT = $FCA8 ;; delay 1/2(26+27A+5A^2) us +;SETINV = $FE80 ;; INVERSE +;SETNORM= $FE84 ;; NORMAL +;COUT = $FDED ;; output A to screen +;COUT1 = $FDF0 ;; output A to screen + + + + + + +COLOR_BLACK = 0 +COLOR_RED = 1 +COLOR_DARKBLUE = 2 +COLOR_PURPLE = 3 +COLOR_DARKGREEN = 4 +COLOR_GREY = 5 +COLOR_MEDIUMBLUE = 6 +COLOR_LIGHTBLUE = 7 +COLOR_BROWN = 8 +COLOR_ORANGE = 9 +COLOR_GREY2 = 10 +COLOR_PINK = 11 +COLOR_LIGHTGREEN = 12 +COLOR_YELLOW = 13 +COLOR_AQUA = 14 +COLOR_WHITE = 15 + +COLOR_BOTH_BLACK = $00 +COLOR_BOTH_RED = $11 +COLOR_BOTH_DARKBLUE = $22 +COLOR_BOTH_DARKGREEN = $44 +COLOR_BOTH_GREY = $55 +COLOR_BOTH_MEDIUMBLUE = $66 +COLOR_BOTH_LIGHTBLUE = $77 +COLOR_BOTH_BROWN = $88 +COLOR_BOTH_ORANGE = $99 +COLOR_BOTH_PINK = $BB +COLOR_BOTH_LIGHTGREEN = $CC +COLOR_BOTH_YELLOW = $DD +COLOR_BOTH_AQUA = $EE +COLOR_BOTH_WHITE = $FF + diff --git a/graphics/dgr_viewer/hello.bas b/graphics/dgr_viewer/hello.bas new file mode 100644 index 00000000..7d0951c7 --- /dev/null +++ b/graphics/dgr_viewer/hello.bas @@ -0,0 +1,4 @@ + 5 HOME + 10 PRINT "SIMPLE DOUBLE-LORES IMAGE VIEWER" + 20 PRINT CHR$(4)+"BRUN DLORES" + diff --git a/graphics/dgr_viewer/make_dgr_viewer.c b/graphics/dgr_viewer/make_dgr_viewer.c new file mode 100644 index 00000000..34770a6d --- /dev/null +++ b/graphics/dgr_viewer/make_dgr_viewer.c @@ -0,0 +1,283 @@ + +#include +#include +#include +#include + +#define MAX_FILES 1024 + +static char *png_filenames[MAX_FILES]; +static char *zx02_aux_filenames[MAX_FILES]; +static char *zx02_main_filenames[MAX_FILES]; +static char *labels[MAX_FILES]; + +/* Format: + +file_label FILE.ZX02 file.png + +*/ + +int main(int argc, char **argv) { + + char *result; + char string[BUFSIZ]; + int num_files=0; + int i,j,count,line=0; + char temp_png[BUFSIZ]; + char temp_zx02[BUFSIZ]; + char temp_label[BUFSIZ]; + char s_filename[BUFSIZ]; + char filename_base[BUFSIZ]; + char temp[BUFSIZ]; + + FILE *sss; + + /******************************************/ + /* parse command line */ + /******************************************/ + + if (argc>1) { + strcpy(filename_base,argv[1]); + } + else { + strcpy(filename_base,"dlores_plain"); + } + sprintf(s_filename,"%s.s",filename_base); + + /******************************************/ + /* scan in data */ + /******************************************/ + + while(1) { + line++; + result=fgets(string,BUFSIZ,stdin); + if (result==NULL) { + break; + } + if (result[0]=='#') continue; + + count=sscanf(string,"%s %s %s",temp_label,temp_zx02,temp_png); + if (count!=3) { + fprintf(stderr,"WARNING! weird input line %d (%d)\n",line,count); + fprintf(stderr,"\t%s",string); + } + else { + labels[num_files]=strdup(temp_label); + png_filenames[num_files]=strdup(temp_png); + + sprintf(temp,"%s.AUX.ZX02",temp_zx02); + zx02_aux_filenames[num_files]=strdup(temp); + + sprintf(temp,"%s.MAIN.ZX02",temp_zx02); + zx02_main_filenames[num_files]=strdup(temp); + + num_files++; + if (num_files>=MAX_FILES) { + fprintf(stderr,"ERROR! Too many files!\n"); + exit(-1); + } + } + } + + if (num_files==0) { + fprintf(stderr,"ERROR! No files found!\n"); + exit(-1); + } + + /******************************************/ + /* generate S file */ + /******************************************/ + + sss=fopen(s_filename,"w"); + if (sss==NULL) { + fprintf(stderr,"ERRROR opening %s\n",s_filename); + exit(-1); + } + + + fprintf(sss,"; Some nice double lores images\n\n"); + fprintf(sss,".include \"../dlores_main.s\"\n\n"); + fprintf(sss,"MAX_FILES = %d\n\n",num_files); + + fprintf(sss,"main_filenames_low:\n"); + for(i=0;i%s_filename_main\n",labels[i]); + } + fprintf(sss,"\n"); + + fprintf(sss,"aux_filenames_low:\n"); + for(i=0;i%s_filename_aux\n",labels[i]); + } + fprintf(sss,"\n"); + + fprintf(sss,"; filename to open is 30-character Apple text:\n"); + + for(i=0;i HELLO\n\n"); + + fprintf(sss,"####\n\n"); + + fprintf(sss,"%s.dsk:\tHELLO DLORES\\\n",filename_base); + for(i=0;i>1 a=3c c=0 + ; a=1e c=0 + ; a=0f c=0 + ; a=07 c=1 + bne L2 ; if a!=0 goto l2 + tya ; if a==0, a=y + sta nibtbl, x ; write out to table + iny ; increment y +L3: inx ; increment x x=4, a=0f + bpl L1 ; loop while high bit not set + + rts + + +;======================================================= +;======================================================= +;======================================================= + + ; filename in OUTL:OUTH + +opendir_filename: + + ; clear out the filename with $A0 (space) + + lda #filename + sta namhi + + ldy #29 +wipe_filename_loop: + lda #$A0 + sta (namlo),Y + dey + bpl wipe_filename_loop + + ldy #0 +copy_filename_loop: + lda (OUTL),Y + beq copy_filename_done + sta (namlo),Y + iny + bne copy_filename_loop + +copy_filename_done: + + ; fallthrough + +;======================================================= +;======================================================= +;======================================================= + + ;=========================== + ; opendir + ;=========================== + + ; turn on drive and read volume table of contents +opendir: +mlsmc01:lda $c0e9 ; turn slot#6 drive on + ldx #0 + stx adrlo ; zero out adrlo + stx secsize ; zero out secsize + lda #$11 ; a=$11 (VTOC) + jsr readdirsec +firstent: + + lda dirbuf+1 + + ; lock if entry not found +entry_not_found: + beq entry_not_found + + ; read directory sector + + ldx dirbuf+2 + jsr seekread1 + ldy #7 ;number of directory entries in a sector + ldx #$2b ;offset of filename in directory entry +nextent: + tya + pha ; was **phy** + txa + pha ; was **phx** + ldy #$1d + + ; match name backwards (slower but smaller) + +L4: + lda (namlo), y + cmp dirbuf, x + beq foundname + pla + + ; move to next directory in this block, if possible + + clc + adc #$23 + tax + pla + tay ; was **ply** + dey + bne nextent + beq firstent ; was **bra** + +foundname: + dex + dey + bpl L4 + pla + tay ; was **ply** + pla + + ; read track/sector list + + lda dirbuf-32, y + ldx dirbuf-31, y + jsr seekread1 + + ; read load offset and length info only, initially + + lda #filbuf + jsr seekread + + ; reduce load offset by 4, to account for offset and length + + sec + lda filbuf + sbc #4 + sta adrlo + + lda filbuf+1 + sbc #0 + sta adrhi + + ; save on stack bytes that will be overwritten by extra read + + ldy #3 +L5: + lda (adrlo), y + pha + dey + bpl L5 + + lda adrhi + pha + lda adrlo + pha + + ; increase load size by 4, to account for offst and length + + lda filbuf+2 + sta ldsizel ; store out raw size + + adc #3 + sta sizelo + sta secsize + + lda filbuf+3 + sta ldsizeh ; store out raw size + + adc #0 + sta sizehi + sta ldsizeh + beq readfirst + lda #0 ; was **stz secsize** + sta secsize + +readfirst: + ldy #$0c + + ; read a file sector + +readnext: + tya + pha + lda dirbuf, y ; A = track + ldx dirbuf+1, y ; x = sector + jsr seekread1 + pla + tay + + ; if low count is non-zero then we are done + ; (can happen only for partial last block) + + lda secsize + bne readdone + + ; continue if more than $100 bytes left + + dec sizehi + bne L6 + + ; set read size to min(length, $100) + + lda sizelo + beq readdone + sta secsize +L6: + inc adrhi + iny + iny + bne readnext + + ; save current address for after t/s read + + lda adrhi + pha + lda adrlo + pha + lda #0 + sta adrlo ; was **stz adrlo** + + ; read next track/sector sector + + lda dirbuf+1 + ldx dirbuf+2 + jsr readdirsec + clc + + ; restore current address +readdone: + pla +; sta adrhi +; pla + sta adrlo ; code originally had this backwards + pla + sta adrhi + bcc readfirst + +mlsmc02:lda $c0e8 + + ; restore from stack bytes that were overwritten by extra read + + ldx #3 + ldy #0 +L7: + pla + sta (adrlo), y + iny + dex + bpl L7 + rts + + + ;====================== + ; readdirsec + ;====================== + ; a = track? + ; x = sector? +readdirsec: + ldy #>dirbuf +seekread: + sty adrhi +seekread1: + sta phase + lda sectbl, x + sta reqsec + jsr readadr + + ; if track does not match, then seek + + cpx phase + beq checksec + jsr seek + + + ;========================================= + ; re merge in with qkumba's recent changes + ; to fix seek problem? + ;========================================= + + ; [re-]read sector + +re_read_addr: + jsr readadr +checksec: + cmp reqsec + bne re_read_addr + + ;========================= + ; read sector data + ;========================= + +readdata: + jsr readd5aa + eor #$ad ; zero A if match + bne re_read_addr + +L12: +mlsmc03:ldx $c0ec ; read until valid data (high bit set) + bpl L12 + eor nibtbl-$80, x + sta bit2tbl-$aa, y + iny + bne L12 +L13: +mlsmc04:ldx $c0ec ; read until valid data (high bit set) + bpl L13 + eor nibtbl-$80, x + sta (adrlo), y ; the real address + iny + cpy secsize + bne L13 + ldy #0 +L14: + ldx #$a9 +L15: + inx + beq L14 + lda (adrlo), y + lsr bit2tbl-$aa, x + rol + lsr bit2tbl-$aa, x + rol + sta (adrlo), y + iny + cpy secsize + bne L15 + rts + + ; no tricks here, just the regular stuff + + ;======================= + ; readaddr -- read the address field + ;======================= + ; Find address field, put track in cutrk, sector in tmpsec + +readadr: + jsr readd5aa + cmp #$96 + bne readadr + ldy #3 ; three? + ; first read volume/volume + ; then track/track + ; then sector/sector? +adr_read_two_bytes: + tax + jsr readnib + rol + sta tmpsec + jsr readnib + and tmpsec + dey + bne adr_read_two_bytes + rts + + ;======================== + ; make sure we see the $D5 $AA pattern + +readd5aa: +L16: + jsr readnib +L17: + cmp #$d5 + bne L16 + jsr readnib + cmp #$aa + bne L17 + tay ; we need Y=#$AA later + +readnib: +mlsmc05:lda $c0ec ; read until valid (high bit set) + bpl readnib + +seekret: + rts + + ;===================== + ; SEEK + ;===================== + ; current track in X? + ; desired track in phase + +seek: + ldy #0 + sty step + asl phase ; multiply by two + txa ; current track? + asl ; mul by two +copy_cur: + tax + sta tmptrk + sec + sbc phase + beq L22 + bcs L18 + eor #$ff + inx + bcc L19 +L18: + sbc #1 + dex +L19: + cmp step + bcc L20 + lda step +L20: + cmp #8 + bcs L21 + tay + sec +L21: + txa + pha + ldx step1, y +L22: + php + bne L24 +L23: + clc + lda tmptrk + ldx step2, y +L24: + stx tmpsec + and #3 + rol + tax + lsr +mlsmc06:lda $c0e0, x +L25: + ldx #$12 +L26: + dex + bpl L26 + dec tmpsec + bne L25 + bcs L23 + plp + beq seekret + pla + inc step + bne copy_cur + + +step1: .byte $01, $30, $28, $24, $20, $1e, $1d, $1c +step2: .byte $70, $2c, $26, $22, $1f, $1e, $1d, $1c + +sectbl: .byte $00,$0d,$0b,$09,$07,$05,$03,$01,$0e,$0c,$0a,$08,$06,$04,$02,$0f + + +; From $BA96 of DOS33 +nibtbl: .res 128 ; = * +; .byte $00,$01,$98,$99,$02,$03,$9C,$04 ; $BA96 ; 00 +; .byte $05,$06,$A0,$A1,$A2,$A4,$A4,$A5 ; $BA9E ; 08 +; .byte $07,$08,$A8,$A9,$AA,$09,$0A,$0B ; $BAA6 ; 10 +; .byte $0C,$0D,$B0,$B1,$0E,$0F,$10,$11 ; $BAAE ; 18 +; .byte $12,$13,$B8,$14,$15,$16,$17,$18 ; $BAB6 ; 20 +; .byte $19,$1A,$C0,$C1,$C2,$C3,$C4,$C5 ; $BABE ; 28 +; .byte $C6,$C7,$C8,$C9,$CA,$1B,$CC,$1C ; $BAC6 ; 30 +; .byte $1D,$1E,$D0,$D1,$D2,$1E,$D4,$D5 ; $BACE ; 38 +; .byte $20,$21,$D8,$22,$23,$24,$25,$26 ; $BAD6 ; 40 +; .byte $27,$28,$E0,$E1,$E2,$E3,$E4,$29 ; $BADE ; 48 +; .byte $2A,$2B,$E8,$2C,$2D,$2E,$2F,$30 ; $BAE6 ; 50 +; .byte $31,$32,$F0,$F1,$33,$34,$35,$36 ; $BAEE ; 58 +; .byte $37,$38,$F8,$39,$3A,$3B,$3C,$3D ; $BAF6 ; 60 +; .byte $3E,$3F,$13,$00,$01,$02,$01,$00 ; $BAFE ; 68 +; .byte $00,$00,$00,$00,$00,$00,$00,$00 +; .byte $00,$00,$00,$00,$00,$00,$00,$00 + + +bit2tbl: .res 86 ; = nibtbl+128 +filbuf: .res 4 ; = bit2tbl+86 + ;dataend = filbuf+4 + diff --git a/graphics/dgr_viewer/zp.inc b/graphics/dgr_viewer/zp.inc index 560c6311..03664348 100644 --- a/graphics/dgr_viewer/zp.inc +++ b/graphics/dgr_viewer/zp.inc @@ -1,197 +1,42 @@ -.define EQU = +;; ZX0 addresses -;; Zero page monitor routines addresses - -WNDLFT EQU $20 -WNDWDTH EQU $21 -WNDTOP EQU $22 -WNDBTM EQU $23 -CH EQU $24 -CV EQU $25 -GBASL EQU $26 -GBASH EQU $27 -BASL EQU $28 -BASH EQU $29 -H2 EQU $2C -V2 EQU $2D -MASK EQU $2E -COLOR EQU $30 -INVFLG EQU $32 - -; More zero-page addresses -; we try not to conflict with anything DOS, MONITOR or BASIC related - -COLOR1 EQU $E0 -COLOR2 EQU $E1 -MATCH EQU $E2 -XX EQU $E3 -YY EQU $E4 -YADD EQU $E5 -LOOP EQU $E6 -MEMPTRL EQU $E7 -MEMPTRH EQU $E8 -NAMEL EQU $E9 -NAMEH EQU $EA -NAMEX EQU $EB -CHAR EQU $EC -DISP_PAGE EQU $ED -DRAW_PAGE EQU $EE - -FIRST EQU $F0 -LASTKEY EQU $F1 -PADDLE_STATUS EQU $F2 -XPOS EQU $F3 -YPOS EQU $F4 -TEMP EQU $FA -RUN EQU $FA -TEMP2 EQU $FB -TEMPY EQU $FB -INL EQU $FC -INH EQU $FD -OUTL EQU $FE -OUTH EQU $FF - - -;; Flying Routine Only - -TURNING EQU $60 -;SCREEN_X EQU $61 ; not used? -SCREEN_Y EQU $62 -ANGLE EQU $63 -HORIZ_SCALE_I EQU $64 -HORIZ_SCALE_F EQU $65 -FACTOR_I EQU $66 -FACTOR_F EQU $67 -DX_I EQU $68 -DX_F EQU $69 -SPACEX_I EQU $6A -SPACEX_F EQU $6B -CX_I EQU $6C -CX_F EQU $6D -DY_I EQU $6E -DY_F EQU $6F -SPACEY_I EQU $70 -SPACEY_F EQU $71 -CY_I EQU $72 -CY_F EQU $73 -TEMP_I EQU $74 -TEMP_F EQU $75 -DISTANCE_I EQU $76 -DISTANCE_F EQU $77 -SPACEZ_I EQU $78 -SPACEZ_F EQU $79 -DRAW_SPLASH EQU $7A -SPEED EQU $7B -SPLASH_COUNT EQU $7C -OVER_LAND EQU $7D -NUM1L EQU $7E -NUM1H EQU $7F -NUM2L EQU $80 -NUM2H EQU $81 -RESULT EQU $82 ; 83,84,85 -NEGATE EQU $86 ; UNUSED? -LAST_SPACEX_I EQU $87 -LAST_SPACEY_I EQU $88 -LAST_MAP_COLOR EQU $89 -DRAW_SKY EQU $8A -COLOR_MASK EQU $8B - -SHIPY EQU $E4 - -;; World Map Only - -ODD EQU $7B -DIRECTION EQU $7C -REFRESH EQU $7D -ON_BIRD EQU $7E -MOVED EQU $7F -STEPS EQU $80 -TFV_X EQU $81 -TFV_Y EQU $82 -NEWX EQU $83 -NEWY EQU $84 -MAP_X EQU $85 -GROUND_COLOR EQU $86 +ZX0_src = $00 +ZX0_dst = $02 +offset = $04 +bitr = $06 +pntr = $07 +WHICH_LOAD = $09 +CURRENT_DISK = $0A -KEYPRESS EQU $C000 -KEYRESET EQU $C010 + adrlo = $26 ; constant from boot prom + adrhi = $27 ; constant from boot prom + tmpsec = $3c ; constant from boot prom + reqsec = $3d ; constant from boot prom + sizelo = $44 + sizehi = $45 + secsize = $46 -;; SOFT SWITCHES -CLR80STORE EQU $C000 ; PAGE0/PAGE1 normal -SET80STORE EQU $C001 ; PAGE0/PAGE1 switches PAGE0 in Aux instead -EIGHTYCOL EQU $C00D -SET_GR EQU $C050 -SET_TEXT EQU $C051 -FULLGR EQU $C052 -TEXTGR EQU $C053 -PAGE0 EQU $C054 -PAGE1 EQU $C055 -LORES EQU $C056 ; Enable LORES graphics -HIRES EQU $C057 ; Enable HIRES graphics -AN3 EQU $C05E ; Annunciator 3 + INL = $EE + INH = $EF -PADDLE_BUTTON0 EQU $C061 -PADDL0 EQU $C064 -PTRIG EQU $C070 + ldsizel = $f0 + ldsizeh = $f1 -;; BASIC ROUTINES + namlo = $fb + namhi = $fc + step = $fd ; state for stepper motor + tmptrk = $fe ; temporary copy of current track + phase = $ff ; current phase for /seek -NORMAL EQU $F273 + -;; MONITOR ROUTINES + TEMPY = $fa -HLINE EQU $F819 ;; HLINE Y,$2C at A -VLINE EQU $F828 ;; VLINE A,$2D at Y -CLRSCR EQU $F832 ;; Clear low-res screen -CLRTOP EQU $F836 ;; clear only top of low-res screen -SETCOL EQU $F864 ;; COLOR=A -TEXT EQU $FB36 -TABV EQU $FB5B ;; VTAB to A -BASCALC EQU $FBC1 ;; -VTAB EQU $FC22 ;; VTAB to CV -HOME EQU $FC58 ;; Clear the text screen -WAIT EQU $FCA8 ;; delay 1/2(26+27A+5A^2) us -SETINV EQU $FE80 ;; INVERSE -SETNORM EQU $FE84 ;; NORMAL -COUT EQU $FDED ;; output A to screen -COUT1 EQU $FDF0 ;; output A to screen + OUTL = $fe ; for picking filename + OUTH = $ff - - - -COLOR_BLACK EQU 0 -COLOR_RED EQU 1 -COLOR_DARKBLUE EQU 2 -COLOR_PURPLE EQU 3 -COLOR_DARKGREEN EQU 4 -COLOR_GREY EQU 5 -COLOR_MEDIUMBLUE EQU 6 -COLOR_LIGHTBLUE EQU 7 -COLOR_BROWN EQU 8 -COLOR_ORANGE EQU 9 -COLOR_GREY2 EQU 10 -COLOR_PINK EQU 11 -COLOR_LIGHTGREEN EQU 12 -COLOR_YELLOW EQU 13 -COLOR_AQUA EQU 14 -COLOR_WHITE EQU 15 - -COLOR_BOTH_RED EQU $11 -COLOR_BOTH_DARKBLUE EQU $22 -COLOR_BOTH_DARKGREEN EQU $44 -COLOR_BOTH_GREY EQU $55 -COLOR_BOTH_MEDIUMBLUE EQU $66 -COLOR_BOTH_LIGHTBLUE EQU $77 -COLOR_BOTH_BROWN EQU $88 -COLOR_BOTH_ORANGE EQU $99 -COLOR_BOTH_LIGHTGREEN EQU $CC -COLOR_BOTH_YELLOW EQU $DD -COLOR_BOTH_WHITE EQU $FF - -AUX_BOTH_MEDIUMBLUE EQU $33 ; 0011 0011 -AUX_BOTH_GREY EQU $AA ; 1010 1010 diff --git a/graphics/dgr_viewer/zx02_optim.s b/graphics/dgr_viewer/zx02_optim.s new file mode 100644 index 00000000..5eebc2e0 --- /dev/null +++ b/graphics/dgr_viewer/zx02_optim.s @@ -0,0 +1,159 @@ +; De-compressor for ZX02 files +; ---------------------------- +; +; Decompress ZX02 data (6502 optimized format), optimized for speed and size +; 138 bytes code, 58.0 cycles/byte in test file. +; +; Compress with: +; zx02 input.bin output.zx0 +; +; (c) 2022 DMSC +; Code under MIT license, see LICENSE file. + + +;ZP=$80 + +;offset = ZP+0 +;ZX0_src = ZP+2 +;ZX0_dst = ZP+4 +;bitr = ZP+6 +;pntr = ZP+7 + + ; Initial values for offset, source, destination and bitr +;zx0_ini_block: +; .byte $00, $00, comp_data, out_addr, $80 + +;-------------------------------------------------- +; Decompress ZX0 data (6502 optimized format) + +zx02_full_decomp: +; ; Get initialization block +; ldy #7 +; +;copy_init: lda zx0_ini_block-1, y +; sta offset-1, y +; dey +; bne copy_init + + + sta ZX0_dst+1 ; page to output to in A +zx_src_l: + ldy #$dd + sty ZX0_src +zx_src_h: + ldy #$dd + sty ZX0_src+1 + ldy #$80 + sty bitr + ldy #0 + sty offset + sty offset+1 + sty ZX0_dst ; always on even page + +; Decode literal: Ccopy next N bytes from compressed file +; Elias(length) byte[1] byte[2] ... byte[N] +decode_literal: + jsr get_elias + +cop0: lda (ZX0_src), y + inc ZX0_src + bne plus1 + inc ZX0_src+1 +plus1: sta (ZX0_dst),y + inc ZX0_dst + bne plus2 + inc ZX0_dst+1 +plus2: dex + bne cop0 + + asl bitr + bcs dzx0s_new_offset + +; Copy from last offset (repeat N bytes from last offset) +; Elias(length) + jsr get_elias +dzx0s_copy: + lda ZX0_dst + sbc offset ; C=0 from get_elias + sta pntr + lda ZX0_dst+1 + sbc offset+1 + sta pntr+1 + +cop1: + lda (pntr), y + inc pntr + bne plus3 + inc pntr+1 +plus3: sta (ZX0_dst),y + inc ZX0_dst + bne plus4 + inc ZX0_dst+1 +plus4: dex + bne cop1 + + asl bitr + bcc decode_literal + +; Copy from new offset (repeat N bytes from new offset) +; Elias(MSB(offset)) LSB(offset) Elias(length-1) +dzx0s_new_offset: + ; Read elias code for high part of offset + jsr get_elias + beq exit ; Read a 0, signals the end + ; Decrease and divide by 2 + dex + txa + lsr ; @ + sta offset+1 + + ; Get low part of offset, a literal 7 bits + lda (ZX0_src), y + inc ZX0_src + bne plus5 + inc ZX0_src+1 +plus5: + ; Divide by 2 + ror ; @ + sta offset + + ; And get the copy length. + ; Start elias reading with the bit already in carry: + ldx #1 + jsr elias_skip1 + + inx + bcc dzx0s_copy + +; Read an elias-gamma interlaced code. +; ------------------------------------ +get_elias: + ; Initialize return value to #1 + ldx #1 + bne elias_start + +elias_get: ; Read next data bit to result + asl bitr + rol ; @ + tax + +elias_start: + ; Get one bit + asl bitr + bne elias_skip1 + + ; Read new bit from stream + lda (ZX0_src), y + inc ZX0_src + bne plus6 + inc ZX0_src+1 +plus6: ;sec ; not needed, C=1 guaranteed from last bit + rol ;@ + sta bitr + +elias_skip1: + txa + bcs elias_get + ; Got ending bit, stop reading +exit: + rts diff --git a/graphics/gr_viewer/lores_main.s b/graphics/gr_viewer/lores_main.s index 4c511d94..a0d80602 100644 --- a/graphics/gr_viewer/lores_main.s +++ b/graphics/gr_viewer/lores_main.s @@ -76,7 +76,7 @@ which_ok: ;=========================== load_image: - bit PAGE1 + bit PAGE2 jsr opendir_filename ; open and read entire file into memory diff --git a/graphics/gr_viewer/rts.s b/graphics/gr_viewer/rts.s index 4aa41375..e07ad543 100644 --- a/graphics/gr_viewer/rts.s +++ b/graphics/gr_viewer/rts.s @@ -9,7 +9,7 @@ ; Loads file contents to addr from filesystem ; also stores filesize in ldsizel:ldsizeh - dirbuf = $900 + dirbuf = $6000 ; note, don't put this immediately below ; the value being read as destaddr-4 ; is temporarily overwritten during read diff --git a/graphics/hgr_viewer/palette/make_pal.c b/graphics/hgr_viewer/palette/make_pal.c index 5fc15b3f..4c5eeb17 100644 --- a/graphics/hgr_viewer/palette/make_pal.c +++ b/graphics/hgr_viewer/palette/make_pal.c @@ -24,7 +24,7 @@ static int pal_rgb[6][3]={ int main(int argc, char **argv) { - int which=4; + int which=3; int c,x; int r,g,b; @@ -37,17 +37,17 @@ int main(int argc, char **argv) { if (gradient[x][c]==0) { } if (gradient[x][c]==1) { - r=r+(pal_rgb[which][0]*pal_rgb[which][0]); - g=g+(pal_rgb[which][1]*pal_rgb[which][1]); - b=b+(pal_rgb[which][2]*pal_rgb[which][2]); + r=r+2*(pal_rgb[which][0]*pal_rgb[which][0]); + g=g+2*(pal_rgb[which][1]*pal_rgb[which][1]); + b=b+2*(pal_rgb[which][2]*pal_rgb[which][2]); } if (gradient[x][c]==2) { - r=r+(0xff*0xff); - g=g+(0xff*0xff); - b=b+(0xff*0xff); + r=r+2*(0xff*0xff); + g=g+2*(0xff*0xff); + b=b+2*(0xff*0xff); } } - printf("%d %d %d\n",(int)sqrt(r/16.0),(int)sqrt(g/16.0),(int)sqrt(b/16.0)); + printf("%d %d %d\n",(int)sqrt(r/32.0),(int)sqrt(g/32.0),(int)sqrt(b/32.0)); } return 0; } diff --git a/utils/gr-utils/Makefile b/utils/gr-utils/Makefile index b77cd741..ff25ef1f 100644 --- a/utils/gr-utils/Makefile +++ b/utils/gr-utils/Makefile @@ -4,7 +4,7 @@ CFLAGS = -g -Wall -O2 all: text2gr png2gr png2gr_text png2rle png2lz4 png_to_40x48d png_to_40x96 \ png2sixbitmap png2six80 png2sixrle png2fourrle png2sixrle2 png_16x16 \ - png2raw png2sprites gr2png + png2raw png2sprites gr2png dgr2png png2dgr ### @@ -31,6 +31,15 @@ png2gr.o: png2gr.c loadpng.h ### +png2dgr: png2dgr.o loadpng.o + $(CC) $(LFLAGS) -o png2dgr png2dgr.o loadpng.o -lpng + +png2dgr.o: png2dgr.c loadpng.h + $(CC) $(CFLAGS) -c png2dgr.c + + +### + png2sprites: png2sprites.o loadpng.o $(CC) $(LFLAGS) -o png2sprites png2sprites.o loadpng.o -lpng @@ -149,12 +158,21 @@ gr2png: gr2png.o gr2png.o: gr2png.c $(CC) $(CFLAGS) -c gr2png.c +### + +dgr2png: dgr2png.o + $(CC) $(LFLAGS) -o dgr2png dgr2png.o -lpng + +dgr2png.o: dgr2png.c + $(CC) $(CFLAGS) -c dgr2png.c + + ### install: - cp png2gr png2gr_text png2rle png2lz4 png_to_40x48d png_to_40x96 png2sixbitmap png2sixrle png2sixrle2 png2fourrle png2six80 png_16x16 png2raw png2sprites gr2png$(INSTALL_LOC) + cp png2gr png2gr_text png2rle png2lz4 png_to_40x48d png_to_40x96 png2sixbitmap png2sixrle png2sixrle2 png2fourrle png2six80 png_16x16 png2raw png2sprites gr2png dgr2png png2dgr $(INSTALL_LOC) clean: - rm -f *~ *.o png2gr png2gr_text png2rle png2lz4 png_to_40x48d png_to_40x96 png2sixbitmap png2sixrle png2fourrle png2sixrle2 png2six80 text2gr pnglarge2rle png_16x16 png2raw png2sprites gr2png + rm -f *~ *.o png2gr png2gr_text png2rle png2lz4 png_to_40x48d png_to_40x96 png2sixbitmap png2sixrle png2fourrle png2sixrle2 png2six80 text2gr pnglarge2rle png_16x16 png2raw png2sprites gr2png dgr2png png2dgr diff --git a/utils/gr-utils/loadpng.c b/utils/gr-utils/loadpng.c index 4686f56b..cab061e1 100644 --- a/utils/gr-utils/loadpng.c +++ b/utils/gr-utils/loadpng.c @@ -117,8 +117,14 @@ int loadpng(char *filename, unsigned char **image_ptr, int *xsize, int *ysize, yadd=1; } else if (width==80) { - *xsize=40; - xadd=2; + if (png_type==PNG_NO_ADJUST) { + *xsize=80; + xadd=1; + } + else { + *xsize=40; + xadd=2; + } yadd=1; } else if (width==280) { @@ -136,7 +142,7 @@ int loadpng(char *filename, unsigned char **image_ptr, int *xsize, int *ysize, return -1; } - if (png_type==PNG_WHOLETHING) { + if ((png_type==PNG_WHOLETHING) || (png_type==PNG_NO_ADJUST)) { *ysize=height; ystart=0; yadd*=2; diff --git a/utils/gr-utils/loadpng.h b/utils/gr-utils/loadpng.h index e4728866..5bf5d324 100644 --- a/utils/gr-utils/loadpng.h +++ b/utils/gr-utils/loadpng.h @@ -2,6 +2,7 @@ #define PNG_ODDLINES 1 #define PNG_EVENLINES 2 #define PNG_RAW 3 +#define PNG_NO_ADJUST 4 int loadpng(char *filename, unsigned char **image_ptr, int *xsize, int *ysize, int png_type); diff --git a/utils/gr-utils/png2dgr.c b/utils/gr-utils/png2dgr.c new file mode 100644 index 00000000..017227fc --- /dev/null +++ b/utils/gr-utils/png2dgr.c @@ -0,0 +1,116 @@ +/* Convert 80x48 png image to two files to be loaded as Apple II DGR */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "loadpng.h" + + +static short gr_offsets[]={ + 0x400,0x480,0x500,0x580,0x600,0x680,0x700,0x780, + 0x428,0x4a8,0x528,0x5a8,0x628,0x6a8,0x728,0x7a8, + 0x450,0x4d0,0x550,0x5d0,0x650,0x6d0,0x750,0x7d0, +}; + +/* in even colors in AUX mem the colors are rotated right by one */ +/* for some reason */ +static unsigned char aux_colors[]={ + 0, /* 0000 -> 0000 */ + 8, /* 0001 -> 1000 */ + 1, /* 0010 -> 0001 */ + 9, /* 0011 -> 1001 */ + 2, /* 0100 -> 0010 */ + 10, /* 0101 -> 1010 */ + 3, /* 0110 -> 0011 */ + 11, /* 0111 -> 1011 */ + 4, /* 1000 -> 0100 */ + 12, /* 1001 -> 1100 */ + 5, /* 1010 -> 0101 */ + 13, /* 1011 -> 1101 */ + 6, /* 1100 -> 0110 */ + 14, /* 1101 -> 1110 */ + 7, /* 1110 -> 0111 */ + 15 /* 1111 -> 1111 */ +}; +/* Converts a PNG to a GR file you can BLOAD to 0x400 */ +/* HOWEVER you *never* want to do this in real life */ +/* as it will clobber important values in the memory holes */ + +int main(int argc, char **argv) { + + int row=0; + int col=0; + int x; + int temp_low,temp_high,temp_color; + + unsigned char aux_buffer[1024]; + unsigned char main_buffer[1024]; + + unsigned char *image; + int xsize,ysize; + FILE *aux_outfile; + FILE *main_outfile; + + char aux_filename[BUFSIZ]; + char main_filename[BUFSIZ]; + + + if (argc<3) { + fprintf(stderr,"Usage:\t%s INFILE OUTFILE_BASE\n\n",argv[0]); + exit(-1); + } + + sprintf(aux_filename,"%s.aux",argv[2]); + sprintf(main_filename,"%s.main",argv[2]); + + aux_outfile=fopen(aux_filename,"w"); + if (aux_outfile==NULL) { + fprintf(stderr,"Error! Could not open %s\n",aux_filename); + exit(-1); + } + + main_outfile=fopen(main_filename,"w"); + if (main_outfile==NULL) { + fprintf(stderr,"Error! Could not open %s\n",main_filename); + exit(-1); + } + + + if (loadpng(argv[1],&image,&xsize,&ysize,PNG_NO_ADJUST)<0) { + fprintf(stderr,"Error loading png!\n"); + exit(-1); + } + + fprintf(stderr,"Loaded image %d by %d\n",xsize,ysize); + + memset(main_buffer,0,1024); + memset(aux_buffer,0,1024); + + for(row=0;row<24;row++) { + for(col=0;col<40;col++) { + /* note, the aux bytes are rotated right by 1 (!?) */ + temp_low=(image[row*xsize+(col*2)])&0xf; + temp_high=(image[row*xsize+(col*2)]>>4)&0xf; + temp_color=(aux_colors[temp_high]<<4)| + (aux_colors[temp_low]); + + aux_buffer[(gr_offsets[row]-0x400)+col]=temp_color; + main_buffer[(gr_offsets[row]-0x400)+col]= + image[row*xsize+(col*2)+1]; + } + } + + for(x=0;x<1024;x++) fputc( aux_buffer[x],aux_outfile); + for(x=0;x<1024;x++) fputc( main_buffer[x],main_outfile); + + fclose(aux_outfile); + fclose(main_outfile); + + return 0; +}