prodos: more work on 2mg support

This commit is contained in:
Vince Weaver 2024-07-16 14:14:30 -04:00
parent b2c41d2927
commit b19ac206b7
8 changed files with 283 additions and 201 deletions

View File

@ -8,20 +8,20 @@ LINKER_SCRIPTS = ../../linker_scripts/
CADIUS = ~/research/apple2/cadius/bin/release/cadius
PRODOSDIR = ../../utils/prodos-utils/
PRODOS = ../../utils/prodos-utils/prodos
PRODOS_RAW = ../../utils/prodos-utils/prodos_raw
all: riven_disk00.dsk \
riven_disk01.dsk \
riven_disk39.dsk riven_disk40.dsk riven_disk41.dsk \
riven_disk43.dsk \
riven_hgr.po
riven_hgr.2mg
# Note: cadius, put #XXYYYY after filename for type/value
riven_hgr.po: disk01_files/LEVEL_ARRIVAL prorwts_ca65.o
$(PRODOSDIR)/mkprodosfs riven_hgr.po -n Riven
####
prorwts_ca65.o: prorwts_ca65.s
ca65 -o prorwts_ca65.o prorwts_ca65.s -l prorwts_ca65.lst
#prorwts_ca65.o: prorwts_ca65.s
# ca65 -o prorwts_ca65.o prorwts_ca65.s -l prorwts_ca65.lst
###
@ -376,3 +376,18 @@ submit: riven_disk00.dsk riven_disk01.dsk \
zip riven_hgr.zip riven_disk00.dsk riven_disk01.dsk \
riven_disk39.dsk \
riven_disk40.dsk riven_disk41.dsk riven_disk43.dsk
####
riven_hgr.2mg: PROBOOTHD disk01_files/LEVEL_ARRIVAL
$(PRODOSDIR)/mkprodosfs riven_hgr.2mg -n Riven -b 65535 -2
$(PRODOS_RAW) riven_hgr.2mg 0 0 PROBOOTHD
###
PROBOOTHD: proboothd.o
ld65 -o PROBOOTHD proboothd.o -C $(LINKER_SCRIPTS)/apple2_800.inc
proboothd.o: proboothd.s
ca65 -o proboothd.o proboothd.s -l proboothd.lst

View File

@ -4,10 +4,16 @@ KEYPRESS = $C000
KEYRESET = $C010
;; SOFT SWITCHES
CLR80COL = $C000 ; PAGE1/PAGE2 normal
SET80COL = $C001 ; PAGE1/PAGE2 switches PAGE1 in Aux instead
EIGHTYCOLOFF = $C00C
CLR80COL = $C000 ; (w) PAGE1/PAGE2 normal
SET80COL = $C001 ; (w) PAGE1/PAGE2 switches PAGE1 in Aux instead
READMAINMEM = $C002 ; (w) to read from main mem ($0200..$BFFF)
READAUXMEM = $C003 ; (w) to read from aux mem ($0200..$BFFF)
WRITEMAINMEM = $C004 ; (w) to write to main mem ($0200..$BFFF)
WRITEAUXMEM = $C005 ; (w)to write to aux mem ($0200..$BFFF)
SETSTDZP = $C008 ; (w) to use main mem stack/zp ($00FF-$01FF)
EIGHTYCOLOFF = $C00C ; (w) use 40 cols / exit DHGR
EIGHTYCOLON = $C00D
PRIMARYCHARSET = $C00E ; (w) to disable mousetext
TBCOLOR = $C022 ; IIgs text foreground / background colors
NEWVIDEO = $C029 ; IIgs graphics modes
SPEAKER = $C030
@ -23,48 +29,41 @@ LORES = $C056 ; Enable LORES graphics
HIRES = $C057 ; Enable HIRES graphics
AN3 = $C05E ; Annunciator 3
PADDLE_BUTTON0 = $C061
PADDL0 = $C064
PTRIG = $C070
;; BASIC ROUTINES
; $C081 for setting language card
; $C082 for setting READ_ROM_NOWRITE
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
ROM_TEXT2COPY = $F962 ;; iigs
TEXT = $FB36
GR = $FB40
TABV = $FB5B ;; VTAB to A
ROM_MACHINEID = $FBB3 ;; iigs
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
CROUT1 = $FD8B
SETINV = $FE80 ;; INVERSE
SETNORM = $FE84 ;; NORMAL
COUT = $FDED ;; output A to screen
COUT1 = $FDF0 ;; output A to screen
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
ROM_TEXT2COPY = $F962 ; iigs
INIT_TEXT = $FB2F ; set lo-res/page1 and call text
TEXT = $FB36
GR = $FB40
TABV = $FB5B ; VTAB to A
ROM_MACHINEID = $FBB3 ; iigs
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
CROUT1 = $FD8B
SETINV = $FE80 ; INVERSE
SETNORM = $FE84 ; NORMAL
COUT = $FDED ; output A to screen
COUT1 = $FDF0 ; output A to screen
SETKBD = $FE89 ; set input to keyboard
SETVID = $FE93 ; set output to video screen
COLOR_BLACK = 0
COLOR_RED = 1

View File

@ -7,19 +7,21 @@ all: prodos mkprodosfs prodos_cat text_to_prodos
###
prodos: prodos.o \
prodos_read.o \
prodos_readwrite.o \
prodos_catalog.o \
prodos_dump.o \
prodos_volume_bitmap.o \
prodos_voldir.o \
prodos_time.o
prodos_time.o \
prodos_2mg.o
$(CC) -o prodos prodos.o \
prodos_read.o \
prodos_readwrite.o \
prodos_catalog.o \
prodos_dump.o \
prodos_volume_bitmap.o \
prodos_voldir.o \
prodos_time.o $(LFLAGS)
prodos_time.o \
prodos_2mg.o $(LFLAGS)
prodos.o: prodos.c prodos.h
$(CC) $(CFLAGS) -g -c prodos.c
@ -50,17 +52,22 @@ text_to_prodos.o: text_to_prodos.c
###
mkprodosfs: mkprodosfs.o prodos_read.o prodos_volume_bitmap.o \
prodos_voldir.o prodos_time.o
mkprodosfs: mkprodosfs.o prodos_readwrite.o prodos_volume_bitmap.o \
prodos_voldir.o prodos_time.o prodos_2mg.o
$(CC) $(LFLAGS) -o mkprodosfs mkprodosfs.o \
prodos_read.o prodos_volume_bitmap.o \
prodos_voldir.o prodos_time.o
prodos_readwrite.o prodos_volume_bitmap.o \
prodos_voldir.o prodos_time.o prodos_2mg.o
mkprodosfs.o: mkprodosfs.c prodos.h
$(CC) $(CFLAGS) -c mkprodosfs.c
###
prodos_2mg.o: prodos_2mg.c prodos.h
$(CC) $(CFLAGS) -c prodos_2mg.c
###
prodos_volume_bitmap.o: prodos_volume_bitmap.c prodos.h
$(CC) $(CFLAGS) -c prodos_volume_bitmap.c
@ -76,8 +83,8 @@ prodos_dump.o: prodos_dump.c prodos.h
###
prodos_read.o: prodos_read.c prodos.h
$(CC) $(CFLAGS) -c prodos_read.c
prodos_readwrite.o: prodos_readwrite.c prodos.h
$(CC) $(CFLAGS) -c prodos_readwrite.c
###

View File

@ -50,7 +50,7 @@ int main(int argc, char **argv) {
int interleave=PRODOS_INTERLEAVE_PRODOS;
int num_voldirs=4,num_bitmaps,num_bitmap_blocks,ones_to_write;
int make_2mg_header=0;
char header_2mg[64];
unsigned char header_2mg[64];
strncpy(volname,"EMPTY",6);
volname_len=strlen(volname);
@ -130,53 +130,8 @@ int main(int argc, char **argv) {
voldir.interleave=interleave;
if (make_2mg_header) {
memset(header_2mg,0,64);
header_2mg[0]='2';
header_2mg[1]='I';
header_2mg[2]='M';
header_2mg[3]='G';
header_2mg[4]='V';
header_2mg[5]='M';
header_2mg[6]='W';
header_2mg[7]='!';
header_2mg[8]=0x40; /* header size (64 bytes) */
header_2mg[9]=0x00;
header_2mg[10]=1;
header_2mg[11]=0; /* version number */
header_2mg[12]=1; /* prodos sector order */
header_2mg[13]=0;
header_2mg[14]=0;
header_2mg[15]=0;
header_2mg[16]=0; /* flags */
header_2mg[17]=0; /* flags */
header_2mg[18]=0; /* flags */
header_2mg[19]=0; /* flags */
header_2mg[20]=num_blocks%256; /* prodos blocks */
header_2mg[21]=num_blocks/256;
header_2mg[22]=0;
header_2mg[23]=0;
header_2mg[24]=0x40; /* offset to disk data */
header_2mg[25]=0;
header_2mg[26]=0;
header_2mg[27]=0;
int data_bytes=num_blocks*512;
/* bytes of disk data */
header_2mg[28]=(data_bytes&0xff);
header_2mg[29]=(data_bytes>>8)&0xff;
header_2mg[30]=(data_bytes>>16)&0xff;
header_2mg[31]=(data_bytes>>24)&0xff;
/* we don't set any of the additional fields */
create_2mg_header(header_2mg,num_blocks);
write(fd,header_2mg,64);

View File

@ -1087,6 +1087,9 @@ int main(int argc, char **argv) {
int address=0, length=0;
struct voldir_t voldir;
int dir_block;
unsigned char header[64];
int result,num_blocks;
/* Check command line arguments */
while ((c = getopt (argc, argv,"a:i:l:t:dhvxy"))!=-1) {
@ -1151,115 +1154,29 @@ int main(int argc, char **argv) {
return -1;
}
if (debug) {
printf("checking extension: %s\n",&image[strlen(image)-4]);
}
/* Try to autodetect if 2mg format */
read(prodos_fd,header,64);
result=read_2mg_header(header,&num_blocks,&interleave,
&image_offset,debug);
if (result==PRODOS_ERROR_BAD_MAGIC) {
/* not 2mg, try to guess otherwise */
/* Try to autodetect interleave based on filename */
if (strlen(image)>4) {
if (!strncmp(&image[strlen(image)-4],".dsk",4)) {
if (debug) printf("Detected DOS33 interleave\n");
interleave=PRODOS_INTERLEAVE_DOS33;
if (debug) {
printf("checking extension: %s\n",&image[strlen(image)-4]);
}
/* FIXME: detect this based on magic number */
else if (!strncmp(&image[strlen(image)-4],".2mg",4)) {
/* Try to autodetect interleave based on filename */
if (strlen(image)>4) {
unsigned char header[64];
int image_format;
read(prodos_fd,header,64);
image_offset= (header[24])|
(header[25]<<8)|
(header[26]<<16)|
(header[27]<<24);
image_format=(header[12])|
(header[13]<<8)|
(header[14]<<16)|
(header[15]<<24);
if (image_format==0) {
if (!strncmp(&image[strlen(image)-4],".dsk",4)) {
if (debug) printf("Detected DOS33 interleave\n");
interleave=PRODOS_INTERLEAVE_DOS33;
}
else if (image_format==1) {
else if (!strncmp(&image[strlen(image)-3],".po",3)) {
if (debug) printf("Detected ProDOS interleave\n");
interleave=PRODOS_INTERLEAVE_PRODOS;
}
else {
fprintf(stderr,"Unsupported 2MG format\n");
return -1;
}
if (debug) {
char string[5];
printf("Detected 2MG format\n");
memcpy(string,header,4);
string[4]=0;
printf("magic: %s\n",string);
memcpy(string,header+4,4);
string[4]=0;
printf("creator: %s\n",string);
printf("Header size: %d\n",
(header[8]|(header[9]<<8)));
printf("Version: %d\n",
(header[10]|(header[11]<<8)));
printf("Flags: $%X\n",
(header[16])|
(header[17]<<8)|
(header[18]<<16)|
(header[19]<<24));
int prodos_blocks=
(header[20])|
(header[21]<<8)|
(header[22]<<16)|
(header[23]<<24);
printf("ProDOS blocks: $%X (%d)\n",
prodos_blocks,prodos_blocks);
printf("Image offset: $%X\n",image_offset);
printf("Bytes of data: %d\n",
(header[28])|
(header[29]<<8)|
(header[30]<<16)|
(header[31]<<24));
printf("Offset to comment: $%X\n",
(header[32])|
(header[33]<<8)|
(header[34]<<16)|
(header[35]<<24));
printf("Length of comment: %d\n",
(header[36])|
(header[37]<<8)|
(header[38]<<16)|
(header[39]<<24));
printf("Offset to creator comment: $%X\n",
(header[40])|
(header[41]<<8)|
(header[42]<<16)|
(header[43]<<24));
printf("Length of creator comment: %d\n",
(header[44])|
(header[45]<<8)|
(header[46]<<16)|
(header[47]<<24));
}
}
}

View File

@ -37,6 +37,11 @@
#define PRODOS_ACCESS_WRITE 0x02
#define PRODOS_ACCESS_READ 0x01
/* error values */
#define PRODOS_OK 0
#define PRODOS_ERROR_BAD_MAGIC 1
#define PRODOS_ERROR_INTERLEAVE 2
struct voldir_t {
int fd;
int interleave;
@ -126,3 +131,8 @@ int prodos_read_voldir(struct voldir_t *voldir);
/* prodos_time.c */
int prodos_time(time_t t);
/* prodos_2mg.c */
int create_2mg_header(unsigned char *header_2mg,int num_blocks);
int read_2mg_header(unsigned char *header_2mg,int *num_blocks,
int *interleave,int *offset,int debug);

View File

@ -0,0 +1,179 @@
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "prodos.h"
/* https://gswv.apple2.org.za/a2zine/Docs/DiskImage_2MG_Info.txt */
int create_2mg_header(unsigned char *header_2mg,int num_blocks) {
int data_bytes=num_blocks*512;
/* clear all to zero */
memset(header_2mg,0,64);
/* magic number */
header_2mg[0]='2';
header_2mg[1]='I';
header_2mg[2]='M';
header_2mg[3]='G';
/* our creation tool magic */
header_2mg[4]='V';
header_2mg[5]='M';
header_2mg[6]='W';
header_2mg[7]='!';
/* header size (64 bytes) */
header_2mg[8]=0x40;
header_2mg[9]=0x00;
/* version number */
header_2mg[10]=1;
header_2mg[11]=0;
/* prodos sector order */
/* TODO: should be configurable */
header_2mg[12]=1;
header_2mg[13]=0;
header_2mg[14]=0;
header_2mg[15]=0;
/* flags */
/* TODO: we should implement these for floppy images */
header_2mg[16]=0;
header_2mg[17]=0;
header_2mg[18]=0;
header_2mg[19]=0;
/* prodos blocks */
header_2mg[20]=num_blocks%256;
header_2mg[21]=num_blocks/256;
header_2mg[22]=0;
header_2mg[23]=0;
/* offset to disk data */
header_2mg[24]=0x40;
header_2mg[25]=0;
header_2mg[26]=0;
header_2mg[27]=0;
/* bytes of disk data */
header_2mg[28]=(data_bytes&0xff);
header_2mg[29]=(data_bytes>>8)&0xff;
header_2mg[30]=(data_bytes>>16)&0xff;
header_2mg[31]=(data_bytes>>24)&0xff;
/* we don't set any of the additional fields */
return 0;
}
int read_2mg_header(unsigned char *header_2mg,
int *num_blocks,
int *interleave,
int *offset,
int debug) {
int image_format;
unsigned char magic[4];
memcpy(magic,&header_2mg[0],4);
if (memcmp(magic,"2IMG",4)!=0) {
if (debug) printf("Unknown magic %c%c%c%c\n",
magic[0],magic[1],magic[2],magic[3]);
return -PRODOS_ERROR_BAD_MAGIC;
}
*num_blocks= (header_2mg[20])|
(header_2mg[21]<<8)|
(header_2mg[22]<<16)|
(header_2mg[23]<<24);
*offset= (header_2mg[24])|
(header_2mg[25]<<8)|
(header_2mg[26]<<16)|
(header_2mg[27]<<24);
image_format=(header_2mg[12])|
(header_2mg[13]<<8)|
(header_2mg[14]<<16)|
(header_2mg[15]<<24);
if (image_format==0) {
*interleave=PRODOS_INTERLEAVE_DOS33;
}
else if (image_format==1) {
*interleave=PRODOS_INTERLEAVE_PRODOS;
}
else {
fprintf(stderr,"Unsupported 2MG format\n");
return -PRODOS_ERROR_INTERLEAVE;
}
if (debug) {
printf("Detected 2MG format\n");
printf("magic: %c%c%c%c\n",
header_2mg[0],
header_2mg[1],
header_2mg[2],
header_2mg[3]);
printf("creator: %c%c%c%c\n",
header_2mg[4],
header_2mg[5],
header_2mg[6],
header_2mg[7]);
printf("Header size: %d\n",(header_2mg[8]|(header_2mg[9]<<8)));
printf("Version: %d\n",(header_2mg[10]|(header_2mg[11]<<8)));
printf("Flags: $%X\n",(header_2mg[16])|
(header_2mg[17]<<8)|
(header_2mg[18]<<16)|
(header_2mg[19]<<24));
printf("ProDOS blocks: $%X (%d)\n",
*num_blocks,*num_blocks);
printf("Image offset: $%X\n",*offset);
printf("Bytes of data: %d\n",
(header_2mg[28])|
(header_2mg[29]<<8)|
(header_2mg[30]<<16)|
(header_2mg[31]<<24));
printf("Offset to comment: $%X\n",
(header_2mg[32])|
(header_2mg[33]<<8)|
(header_2mg[34]<<16)|
(header_2mg[35]<<24));
printf("Length of comment: %d\n",
(header_2mg[36])|
(header_2mg[37]<<8)|
(header_2mg[38]<<16)|
(header_2mg[39]<<24));
printf("Offset to creator comment: $%X\n",
(header_2mg[40])|
(header_2mg[41]<<8)|
(header_2mg[42]<<16)|
(header_2mg[43]<<24));
printf("Length of creator comment: %d\n",
(header_2mg[44])|
(header_2mg[45]<<8)|
(header_2mg[46]<<16)|
(header_2mg[47]<<24));
}
return 0;
}