dgr_viewer: double lo-res is a pain

did finally figure out what was going on

the aux pages are rotated by nybble
This commit is contained in:
Vince Weaver 2023-05-07 14:55:55 -04:00
parent 59095129e3
commit 30825d0fdf
16 changed files with 1460 additions and 212 deletions

View File

@ -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

View File

@ -0,0 +1,171 @@
; VMW Productions DGR/ZX02 viewer
; by Vince `deater` Weaver <vince@deater.net>
.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"

Binary file not shown.

View File

@ -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

View File

@ -0,0 +1,4 @@
5 HOME
10 PRINT "SIMPLE DOUBLE-LORES IMAGE VIEWER"
20 PRINT CHR$(4)+"BRUN DLORES"

View File

@ -0,0 +1,283 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#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<num_files;i++) {
fprintf(sss,"\t.byte <%s_filename_main\n",labels[i]);
}
fprintf(sss,"\n");
fprintf(sss,"main_filenames_high:\n");
for(i=0;i<num_files;i++) {
fprintf(sss,"\t.byte >%s_filename_main\n",labels[i]);
}
fprintf(sss,"\n");
fprintf(sss,"aux_filenames_low:\n");
for(i=0;i<num_files;i++) {
fprintf(sss,"\t.byte <%s_filename_aux\n",labels[i]);
}
fprintf(sss,"\n");
fprintf(sss,"aux_filenames_high:\n");
for(i=0;i<num_files;i++) {
fprintf(sss,"\t.byte >%s_filename_aux\n",labels[i]);
}
fprintf(sss,"\n");
fprintf(sss,"; filename to open is 30-character Apple text:\n");
for(i=0;i<num_files;i++) {
fprintf(sss,"%s_filename_main:\t; %s\n",labels[i],zx02_main_filenames[i]);
fprintf(sss,"\t.byte ");
for(j=0;j<strlen(zx02_main_filenames[i]);j++) {
if (j!=0) fprintf(sss,",");
fprintf(sss,"\'%c\'|$80",zx02_main_filenames[i][j]);
}
fprintf(sss,",$00\n\n");
fprintf(sss,"%s_filename_aux:\t; %s\n",labels[i],zx02_aux_filenames[i]);
fprintf(sss,"\t.byte ");
for(j=0;j<strlen(zx02_aux_filenames[i]);j++) {
if (j!=0) fprintf(sss,",");
fprintf(sss,"\'%c\'|$80",zx02_aux_filenames[i][j]);
}
fprintf(sss,",$00\n\n");
}
fclose(sss);
/******************************************/
/* generate Makefile */
/******************************************/
/* don't over-write as a precaution */
if (access("Makefile", F_OK) == 0) {
fprintf(stderr,"Makefile already exists! Out of caution giving up.\n");
exit(-1);
}
sss=fopen("Makefile","w");
if (sss==NULL) {
fprintf(stderr,"ERRROR opening Makefile\n");
exit(-1);
}
fprintf(sss,"include ../../../Makefile.inc\n\n");
fprintf(sss,"ZX02 = ~/research/6502_compression/zx02.git/build/zx02\n");
fprintf(sss,"PNG_TO_DGR = ../../../utils/gr-utils/png2dgr\n");
fprintf(sss,"LINKER_SCRIPTS = ../../../linker_scripts\n");
fprintf(sss,"DOS33 = ../../../utils/dos33fs-utils/dos33\n");
fprintf(sss,"EMPTY_DISK = ../../../empty_disk/empty.dsk\n");
fprintf(sss,"TOKENIZE = ../../../utils/asoft_basic-utils/tokenize_asoft\n");
fprintf(sss,"\n");
fprintf(sss,"all:\t%s.dsk\n\n",filename_base);
fprintf(sss,"####\n\n");
fprintf(sss,"DLORES:\t%s.o\n",filename_base);
fprintf(sss,"\tld65 -o DLORES %s.o -C $(LINKER_SCRIPTS)/apple2_1000.inc\n\n",filename_base);
fprintf(sss,"%s.o:\t%s.s ../dlores_main.s ../zx02_optim.s \\\n",filename_base,filename_base);
fprintf(sss,"\t\t../zp.inc ../hardware.inc\n");
fprintf(sss,"\tca65 -o %s.o %s.s -l %s.lst\n",filename_base,filename_base,filename_base);
fprintf(sss,"####\n\n");
fprintf(sss,"HELLO:\t../hello.bas\n");
fprintf(sss,"\t$(TOKENIZE) < ../hello.bas > HELLO\n\n");
fprintf(sss,"####\n\n");
fprintf(sss,"%s.dsk:\tHELLO DLORES\\\n",filename_base);
for(i=0;i<num_files;i++) {
fprintf(sss,"\t\t%s.gr.main.zx02 %s.gr.aux.zx02",
png_filenames[i],png_filenames[i]);
if (i!=(num_files-1)) {
fprintf(sss,"\\");
}
fprintf(sss,"\n");
}
fprintf(sss,"\tcp $(EMPTY_DISK) %s.dsk\n",filename_base);
fprintf(sss,"\t$(DOS33) -y %s.dsk SAVE A HELLO\n",filename_base);
fprintf(sss,"\t$(DOS33) -y %s.dsk BSAVE -a 0x1000 DLORES\n",filename_base);
for(i=0;i<num_files;i++) {
fprintf(sss,"\t$(DOS33) -y %s.dsk BSAVE -a 0xa000 %s.gr.main.zx02 %s\n",
filename_base,
png_filenames[i],zx02_main_filenames[i]);
fprintf(sss,"\t$(DOS33) -y %s.dsk BSAVE -a 0xa000 %s.gr.aux.zx02 %s\n",
filename_base,
png_filenames[i],zx02_aux_filenames[i]);
}
fprintf(sss,"####\n\n");
fprintf(sss,"clean:\n");
fprintf(sss,"\trm -f *~ *.o *.lst\n\n");
fclose(sss);
/******************************************/
/* generate Makefile.graphics */
/******************************************/
sss=fopen("Makefile.graphics","w");
if (sss==NULL) {
fprintf(stderr,"ERRROR opening Makefile\n");
exit(-1);
}
fprintf(sss,"include ../../../Makefile.inc\n\n");
fprintf(sss,"ZX02 = ~/research/6502_compression/zx02.git/build/zx02\n");
fprintf(sss,"PNG_TO_DGR = ../../../utils/gr-utils/png2dgr\n");
fprintf(sss,"LINKER_SCRIPTS = ../../../linker_scripts\n");
fprintf(sss,"DOS33 = ../../../utils/dos33fs-utils/dos33\n");
fprintf(sss,"EMPTY_DISK = ../../../empty_disk/empty.dsk\n");
fprintf(sss,"TOKENIZE = ../../../utils/asoft_basic-utils/tokenize_asoft\n");
fprintf(sss,"\n");
fprintf(sss,"all:\\\n");
for(i=0;i<num_files;i++) {
fprintf(sss,"\t\t%s.gr.main.zx02 %s.gr.aux.zx02 ",
png_filenames[i],png_filenames[i]);
if (i!=(num_files-1)) {
fprintf(sss,"\\");
}
fprintf(sss,"\n");
}
// fprintf(sss,"\tcp $(EMPTY_DISK) %s.dsk\n",filename_base);
// fprintf(sss,"\t$(DOS33) -y %s.dsk SAVE A HELLO\n",filename_base);
// fprintf(sss,"\t$(DOS33) -y %s.dsk BSAVE -a 0x0c00 LORES\n",filename_base);
// for(i=0;i<num_files;i++) {
// fprintf(sss,"\t$(DOS33) -y %s.dsk BSAVE -a 0xa000 %s.gr.zx02 %s\n",
// filename_base,
// png_filenames[i],zx02_filenames[i]);
// }
for(i=0;i<num_files;i++) {
fprintf(sss,"\n####\n\n");
fprintf(sss,"%s.gr.main.zx02:\t%s.gr.main\n",png_filenames[i],png_filenames[i]);
fprintf(sss,"\t$(ZX02) %s.gr.main %s.gr.main.zx02\n",png_filenames[i],png_filenames[i]);
fprintf(sss,"\n");
fprintf(sss,"%s.gr.aux.zx02:\t%s.gr.aux\n",png_filenames[i],png_filenames[i]);
fprintf(sss,"\t$(ZX02) %s.gr.aux %s.gr.aux.zx02\n",png_filenames[i],png_filenames[i]);
fprintf(sss,"\n");
fprintf(sss,"%s.gr.main:\t%s.png\n",png_filenames[i],png_filenames[i]);
fprintf(sss,"\t$(PNG_TO_DGR) %s.png %s.gr\n",png_filenames[i],png_filenames[i]);
fprintf(sss,"\n");
fprintf(sss,"%s.gr.aux:\t%s.png\n",png_filenames[i],png_filenames[i]);
fprintf(sss,"\t$(PNG_TO_DGR) %s.png %s.gr\n",png_filenames[i],png_filenames[i]);
fprintf(sss,"\n");
}
fprintf(sss,"####\n\n");
fprintf(sss,"clean:\n");
fprintf(sss,"\trm -f *~ *.o *.lst\n\n");
fclose(sss);
return 0;
}

557
graphics/dgr_viewer/rts.s Normal file
View File

@ -0,0 +1,557 @@
; read any file slot 6 version
; based on FASTLD6 and RTS copyright (c) Peter Ferrie 2011-2013,2018
; modified to assembled with ca65 -- vmw
; added code to patch it to run from current disk slot -- vmw
; USAGE:
; file to load in namlo:namhi
; Loads file contents to addr from filesystem
; also stores filesize in ldsizel:ldsizeh
dirbuf = $6000
; note, don't put this immediately below
; the value being read as destaddr-4
; is temporarily overwritten during read
; process
;======================
; filename to open is 30-character Apple text:
filename:
.byte $A0,$A0,$A0,$A0,$A0,$A0,$A0,$A0
.byte $A0,$A0,$A0,$A0,$A0,$A0,$A0,$A0
.byte $A0,$A0,$A0,$A0,$A0,$A0,$A0,$A0
.byte $A0,$A0,$A0,$A0,$A0,$A0
;=======================================================
;=======================================================
;=======================================================
;unhook DOS and build nibble table
rts_init:
; patch to use current drive
; locate input paramater list
jsr $3E3
; result is in A:Y
sta $FF
sty $FE
ldy #1
lda ($FE),y
; list+1 should have slot<<8
ora #$80 ; add in $80
; c0e0
sta mlsmc06+1
; c0e8
clc
adc #8
sta mlsmc02+1
; c0e9
clc
adc #1
sta mlsmc01+1
; c0ec
clc
adc #3
sta mlsmc03+1
sta mlsmc04+1
sta mlsmc05+1
jsr $fe93 ; clear COUT
jsr $fe89 ; clear KEYIN
;========================
; Create nibble table
; Note: the table starts 16 bytes in, and is sparse
; so it doesn't entirely look like the DOS33 table at
ldy #0
ldx #3
L1: stx $3c ; store tempx (3?)
txa ; a=x (a=3)
asl ; a*=2 (a=6)
bit $3c ; a&tempx, set N/V (a=6)
beq L3 ; if 0, skip to L3
ora $3c ; a|=tempx (a=7)
eor #$ff ; a=~a (a=f8)
and #$7e ; a&=0x7e 0111 1110 (a=78)
L2: bcs L3 ; this set way back at asl??
lsr ; a>>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 namlo
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
sta adrlo
lda #4
sta secsize
lda dirbuf+12
ldx dirbuf+13
ldy #>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

View File

@ -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

View File

@ -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, >comp_data, <out_addr, >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

View File

@ -76,7 +76,7 @@ which_ok:
;===========================
load_image:
bit PAGE1
bit PAGE2
jsr opendir_filename ; open and read entire file into memory

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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);

116
utils/gr-utils/png2dgr.c Normal file
View File

@ -0,0 +1,116 @@
/* Convert 80x48 png image to two files to be loaded as Apple II DGR */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#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;
}