From a4cc3ad3504d634e379369862c9f9fd8eed379f3 Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Thu, 16 May 2024 01:43:09 -0400 Subject: Add Jindrich Kubec's tools. --- jindroush/Makefile | 62 ++ jindroush/README.txt | 37 ++ jindroush/acvt/Makefile | 52 ++ jindroush/acvt/acvt.cpp | 216 +++++++ jindroush/acvt/pub.def | 31 + jindroush/acvt/readme.txt | 152 +++++ jindroush/acvt/switches.def | 64 +++ jindroush/adir/Makefile | 52 ++ jindroush/adir/adir.cpp | 494 ++++++++++++++++ jindroush/adir/pub.def | 31 + jindroush/adir/readme.txt | 112 ++++ jindroush/adir/switches.def | 64 +++ jindroush/aext/Makefile | 49 ++ jindroush/aext/aext.cpp | 280 +++++++++ jindroush/aext/pub.def | 31 + jindroush/aext/readme.txt | 76 +++ jindroush/aext/switches.def | 25 + jindroush/bas2boot/Makefile | 59 ++ jindroush/bas2boot/bas2boot.asm | 169 ++++++ jindroush/bas2boot/bas2boot.boo | Bin 0 -> 256 bytes jindroush/bas2boot/bas2boot.cpp | 286 ++++++++++ jindroush/bas2boot/pub.def | 31 + jindroush/bas2boot/readme.txt | 72 +++ jindroush/bas2boot/switches.def | 32 ++ jindroush/chkbas/Makefile | 61 ++ jindroush/chkbas/basic.h | 152 +++++ jindroush/chkbas/basic_tb.h | 223 ++++++++ jindroush/chkbas/basic_xe.h | 219 +++++++ jindroush/chkbas/basic_xl.h | 213 +++++++ jindroush/chkbas/carray.cpp | 158 +++++ jindroush/chkbas/carray.h | 49 ++ jindroush/chkbas/chkbas.cpp | 1009 ++++++++++++++++++++++++++++++++ jindroush/chkbas/listbas | 1 + jindroush/chkbas/pub.def | 31 + jindroush/chkbas/readme.txt | 87 +++ jindroush/chkbas/strlwr.cpp | 11 + jindroush/chkbas/switches.def | 34 ++ jindroush/chkexe/Makefile | 55 ++ jindroush/chkexe/chkexe.cpp | 504 ++++++++++++++++ jindroush/chkexe/pub.def | 31 + jindroush/chkexe/readme.txt | 100 ++++ jindroush/chkexe/switches.def | 21 + jindroush/chkrom/Makefile | 56 ++ jindroush/chkrom/chkrom.cpp | 119 ++++ jindroush/chkrom/pub.def | 31 + jindroush/chkrom/readme.txt | 56 ++ jindroush/chkrom/switches.def | 5 + jindroush/gpl.txt | 339 +++++++++++ jindroush/include/adsk.h | 75 +++ jindroush/include/adsk_atr.h | 38 ++ jindroush/include/adsk_dcm.h | 72 +++ jindroush/include/adsk_di.h | 38 ++ jindroush/include/adsk_scp.h | 37 ++ jindroush/include/adsk_xfd.h | 38 ++ jindroush/include/at_dis.h | 25 + jindroush/include/autil.h | 35 ++ jindroush/include/cdisk.h | 95 ++++ jindroush/include/cdsk.h | 72 +++ jindroush/include/cdsk_atr.h | 38 ++ jindroush/include/cdsk_dcm.h | 72 +++ jindroush/include/cdsk_scp.h | 37 ++ jindroush/include/cdsk_xfd.h | 38 ++ jindroush/include/cfile.h | 54 ++ jindroush/include/cfs.h | 65 +++ jindroush/include/cfs_b2b.h | 42 ++ jindroush/include/cfs_boot.h | 42 ++ jindroush/include/cfs_dos2.h | 67 +++ jindroush/include/cfs_dos3.h | 59 ++ jindroush/include/cfs_dosm.h | 66 +++ jindroush/include/cfs_doss.h | 70 +++ jindroush/include/cfs_howf.h | 43 ++ jindroush/include/cfs_jonw.h | 43 ++ jindroush/include/cfs_kboo.h | 42 ++ jindroush/include/cfs_robc.h | 43 ++ jindroush/include/cgenfile.h | 55 ++ jindroush/include/cobj.h | 34 ++ jindroush/include/cprefile.h | 56 ++ jindroush/include/errbase.h | 26 + jindroush/include/jintypes.h | 95 ++++ jindroush/lib/Makefile | 23 + jindroush/lib/adsk.cpp | 319 +++++++++++ jindroush/lib/adsk_atr.cpp | 483 ++++++++++++++++ jindroush/lib/adsk_dcm.cpp | 764 +++++++++++++++++++++++++ jindroush/lib/adsk_di.cpp | 271 +++++++++ jindroush/lib/adsk_scp.cpp | 281 +++++++++ jindroush/lib/adsk_xfd.cpp | 327 +++++++++++ jindroush/lib/at_dis.cpp | 1201 +++++++++++++++++++++++++++++++++++++++ jindroush/lib/autil.cpp | 139 +++++ jindroush/lib/cdisk.cpp | 276 +++++++++ jindroush/lib/cdsk.cpp | 115 ++++ jindroush/lib/cdsk_atr.cpp | 439 ++++++++++++++ jindroush/lib/cdsk_dcm.cpp | 762 +++++++++++++++++++++++++ jindroush/lib/cdsk_scp.cpp | 279 +++++++++ jindroush/lib/cdsk_xfd.cpp | 334 +++++++++++ jindroush/lib/cfile.cpp | 139 +++++ jindroush/lib/cfs.cpp | 69 +++ jindroush/lib/cfs_b2b.cpp | 156 +++++ jindroush/lib/cfs_boot.cpp | 128 +++++ jindroush/lib/cfs_dos2.cpp | 224 ++++++++ jindroush/lib/cfs_dos3.cpp | 209 +++++++ jindroush/lib/cfs_dosm.cpp | 240 ++++++++ jindroush/lib/cfs_doss.cpp | 383 +++++++++++++ jindroush/lib/cfs_howf.cpp | 209 +++++++ jindroush/lib/cfs_jonw.cpp | 204 +++++++ jindroush/lib/cfs_kboo.cpp | 148 +++++ jindroush/lib/cfs_robc.cpp | 231 ++++++++ jindroush/lib/cgenfile.cpp | 95 ++++ jindroush/lib/cobj.cpp | 23 + jindroush/lib/cprefile.cpp | 153 +++++ jindroush/man/Makefile | 12 + jindroush/man/acvt.1 | 116 ++++ jindroush/man/acvt.rst | 77 +++ jindroush/man/adir.1 | 141 +++++ jindroush/man/adir.rst | 89 +++ jindroush/man/aext.1 | 55 ++ jindroush/man/aext.rst | 24 + jindroush/man/bas2boot.1 | 84 +++ jindroush/man/bas2boot.rst | 53 ++ jindroush/man/chkbas.1 | 155 +++++ jindroush/man/chkbas.rst | 118 ++++ jindroush/man/chkexe.1 | 86 +++ jindroush/man/chkexe.rst | 55 ++ jindroush/man/chkrom.1 | 90 +++ jindroush/man/chkrom.rst | 51 ++ jindroush/man/manftr.rst | 21 + jindroush/man/manhdr.rst | 7 + jindroush/switches.pl | 322 +++++++++++ 127 files changed, 17834 insertions(+) create mode 100644 jindroush/Makefile create mode 100644 jindroush/README.txt create mode 100644 jindroush/acvt/Makefile create mode 100644 jindroush/acvt/acvt.cpp create mode 100644 jindroush/acvt/pub.def create mode 100644 jindroush/acvt/readme.txt create mode 100644 jindroush/acvt/switches.def create mode 100644 jindroush/adir/Makefile create mode 100644 jindroush/adir/adir.cpp create mode 100644 jindroush/adir/pub.def create mode 100644 jindroush/adir/readme.txt create mode 100644 jindroush/adir/switches.def create mode 100644 jindroush/aext/Makefile create mode 100644 jindroush/aext/aext.cpp create mode 100644 jindroush/aext/pub.def create mode 100644 jindroush/aext/readme.txt create mode 100644 jindroush/aext/switches.def create mode 100644 jindroush/bas2boot/Makefile create mode 100644 jindroush/bas2boot/bas2boot.asm create mode 100644 jindroush/bas2boot/bas2boot.boo create mode 100644 jindroush/bas2boot/bas2boot.cpp create mode 100644 jindroush/bas2boot/pub.def create mode 100644 jindroush/bas2boot/readme.txt create mode 100644 jindroush/bas2boot/switches.def create mode 100644 jindroush/chkbas/Makefile create mode 100644 jindroush/chkbas/basic.h create mode 100644 jindroush/chkbas/basic_tb.h create mode 100644 jindroush/chkbas/basic_xe.h create mode 100644 jindroush/chkbas/basic_xl.h create mode 100644 jindroush/chkbas/carray.cpp create mode 100644 jindroush/chkbas/carray.h create mode 100644 jindroush/chkbas/chkbas.cpp create mode 120000 jindroush/chkbas/listbas create mode 100644 jindroush/chkbas/pub.def create mode 100644 jindroush/chkbas/readme.txt create mode 100644 jindroush/chkbas/strlwr.cpp create mode 100644 jindroush/chkbas/switches.def create mode 100644 jindroush/chkexe/Makefile create mode 100644 jindroush/chkexe/chkexe.cpp create mode 100644 jindroush/chkexe/pub.def create mode 100644 jindroush/chkexe/readme.txt create mode 100644 jindroush/chkexe/switches.def create mode 100644 jindroush/chkrom/Makefile create mode 100644 jindroush/chkrom/chkrom.cpp create mode 100644 jindroush/chkrom/pub.def create mode 100644 jindroush/chkrom/readme.txt create mode 100644 jindroush/chkrom/switches.def create mode 100644 jindroush/gpl.txt create mode 100644 jindroush/include/adsk.h create mode 100644 jindroush/include/adsk_atr.h create mode 100644 jindroush/include/adsk_dcm.h create mode 100644 jindroush/include/adsk_di.h create mode 100644 jindroush/include/adsk_scp.h create mode 100644 jindroush/include/adsk_xfd.h create mode 100644 jindroush/include/at_dis.h create mode 100644 jindroush/include/autil.h create mode 100644 jindroush/include/cdisk.h create mode 100644 jindroush/include/cdsk.h create mode 100644 jindroush/include/cdsk_atr.h create mode 100644 jindroush/include/cdsk_dcm.h create mode 100644 jindroush/include/cdsk_scp.h create mode 100644 jindroush/include/cdsk_xfd.h create mode 100644 jindroush/include/cfile.h create mode 100644 jindroush/include/cfs.h create mode 100644 jindroush/include/cfs_b2b.h create mode 100644 jindroush/include/cfs_boot.h create mode 100644 jindroush/include/cfs_dos2.h create mode 100644 jindroush/include/cfs_dos3.h create mode 100644 jindroush/include/cfs_dosm.h create mode 100644 jindroush/include/cfs_doss.h create mode 100644 jindroush/include/cfs_howf.h create mode 100644 jindroush/include/cfs_jonw.h create mode 100644 jindroush/include/cfs_kboo.h create mode 100644 jindroush/include/cfs_robc.h create mode 100644 jindroush/include/cgenfile.h create mode 100644 jindroush/include/cobj.h create mode 100644 jindroush/include/cprefile.h create mode 100644 jindroush/include/errbase.h create mode 100644 jindroush/include/jintypes.h create mode 100644 jindroush/lib/Makefile create mode 100644 jindroush/lib/adsk.cpp create mode 100644 jindroush/lib/adsk_atr.cpp create mode 100644 jindroush/lib/adsk_dcm.cpp create mode 100644 jindroush/lib/adsk_di.cpp create mode 100644 jindroush/lib/adsk_scp.cpp create mode 100644 jindroush/lib/adsk_xfd.cpp create mode 100644 jindroush/lib/at_dis.cpp create mode 100644 jindroush/lib/autil.cpp create mode 100644 jindroush/lib/cdisk.cpp create mode 100644 jindroush/lib/cdsk.cpp create mode 100644 jindroush/lib/cdsk_atr.cpp create mode 100644 jindroush/lib/cdsk_dcm.cpp create mode 100644 jindroush/lib/cdsk_scp.cpp create mode 100644 jindroush/lib/cdsk_xfd.cpp create mode 100644 jindroush/lib/cfile.cpp create mode 100644 jindroush/lib/cfs.cpp create mode 100644 jindroush/lib/cfs_b2b.cpp create mode 100644 jindroush/lib/cfs_boot.cpp create mode 100644 jindroush/lib/cfs_dos2.cpp create mode 100644 jindroush/lib/cfs_dos3.cpp create mode 100644 jindroush/lib/cfs_dosm.cpp create mode 100644 jindroush/lib/cfs_doss.cpp create mode 100644 jindroush/lib/cfs_howf.cpp create mode 100644 jindroush/lib/cfs_jonw.cpp create mode 100644 jindroush/lib/cfs_kboo.cpp create mode 100644 jindroush/lib/cfs_robc.cpp create mode 100644 jindroush/lib/cgenfile.cpp create mode 100644 jindroush/lib/cobj.cpp create mode 100644 jindroush/lib/cprefile.cpp create mode 100644 jindroush/man/Makefile create mode 100644 jindroush/man/acvt.1 create mode 100644 jindroush/man/acvt.rst create mode 100644 jindroush/man/adir.1 create mode 100644 jindroush/man/adir.rst create mode 100644 jindroush/man/aext.1 create mode 100644 jindroush/man/aext.rst create mode 100644 jindroush/man/bas2boot.1 create mode 100644 jindroush/man/bas2boot.rst create mode 100644 jindroush/man/chkbas.1 create mode 100644 jindroush/man/chkbas.rst create mode 100644 jindroush/man/chkexe.1 create mode 100644 jindroush/man/chkexe.rst create mode 100644 jindroush/man/chkrom.1 create mode 100644 jindroush/man/chkrom.rst create mode 100644 jindroush/man/manftr.rst create mode 100644 jindroush/man/manhdr.rst create mode 100644 jindroush/switches.pl (limited to 'jindroush') diff --git a/jindroush/Makefile b/jindroush/Makefile new file mode 100644 index 0000000..0a11a8f --- /dev/null +++ b/jindroush/Makefile @@ -0,0 +1,62 @@ +# Unified Makefile for Jindroush's various Atari 8-bit utilities + +DESTDIR= +PREFIX=/usr/local +BINDIR=$(PREFIX)/bin +DOCDIR=$(PREFIX)/share/doc/jindroush_atari8_utils + +MANDIR=$(PREFIX)/share/man +MAN1DIR=$(MANDIR)/man1 + +GZIP_MAN=y +RST2MAN=rst2man + +BINS=acvt adir aext bas2boot chkbas chkexe chkrom + +# The -Wno-write-strings prevents hundreds of "ISO C++ forbids +# converting a string to 'char*'" warnings. Eventually will fix. +W=-Wall -Wno-write-strings + +all: libs manpages + for i in $(BINS); do \ + make -C $$i COPT="$(COPT) $(W)" ; \ + done + +manpages: + make -C man + +libs: + make -C lib COPT="$(COPT) $(W)" + +clean: + make -C lib clean + for i in $(BINS); do \ + make -C $$i clean ; \ + done + +install: all + mkdir -p $(DESTDIR)/$(BINDIR) $(DESTDIR)/$(DOCDIR) ; \ + cp README.txt $(DESTDIR)/$(DOCDIR)/README_jindroush.txt ; \ + cp gpl.txt $(DESTDIR)/$(DOCDIR)/gpl.txt ; \ + for i in $(BINS); do \ + strip $$i/$$i ; \ + cp $$i/$$i $(DESTDIR)/$(BINDIR)/$$i ; \ + chown root.root $$i/$$i $(DESTDIR)/$(BINDIR)/$$i 2>/dev/null || true ; \ + chmod 755 $(DESTDIR)/$(BINDIR)/$$i ; \ + cp $$i/readme.txt $(DESTDIR)/$(DOCDIR)/$$i.txt ; \ + chown root.root $(DESTDIR)/$(DOCDIR)/$$i.txt 2>/dev/null || true ; \ + chmod 644 $(DESTDIR)/$(DOCDIR)/$$i.txt ; \ + done ; \ + mkdir -p $(DESTDIR)/$(MAN1DIR) ; \ + for i in $(BINS); do \ + cp man/$$i.1 $(DESTDIR)/$(MAN1DIR) ; \ + chown root.root $(DESTDIR)/$(MAN1DIR)/$$i.1 2>/dev/null || true ; \ + chmod 644 $(DESTDIR)/$(MAN1DIR)/$$i.1 ; \ + [ "$(GZIP_MAN)" = "y" ] && gzip -f $(DESTDIR)/$(MAN1DIR)/$$i.1 ; \ + done + ln -sf chkbas $(DESTDIR)$(BINDIR)/listbas + if [ "$(GZIP_MAN)" = "y" ]; then \ + ln -sf chkbas.1.gz $(DESTDIR)$(MAN1DIR)/listbas.1.gz ; \ + else \ + ln -sf chkbas.1 $(DESTDIR)$(MAN1DIR)/listbas.1 ; \ + fi diff --git a/jindroush/README.txt b/jindroush/README.txt new file mode 100644 index 0000000..31d9af9 --- /dev/null +++ b/jindroush/README.txt @@ -0,0 +1,37 @@ +This is a collection of GPL'ed Atari 8-bit tools developed by +Jindroush, AKA Jindrich Kubec. The original site has gone offline, but +there's a copy at archive.org: + +http://web.archive.org/web/20010412172202/http://www.asw.cz/~kubecj/asoft.htm + +The utilities are: + +acvt - converts disk images between xfd, atr, dcm, and other formats. +adir - extracts files from disk images, supports lots of formats. +aext - extracts segments from .xex files as blocks of raw data. +bas2boot - converts Atari BASIC files to bootable disk images. +chkbas - checks and lists tokenized Atari BASIC files. +chkexe - lists and optionally disassembles segments in a .xex file. +chkrom - checks and disassembles Atari 8K and 16K cartridge images. + +Originally, these were published separately. This collection was +put together by B. Watson . The only changes +I've made to Jindroush's code: + +- The common code from each source .zip file has been collected + in the lib/ directory, and the Makefiles were modified to + use this library. + +- switches.pl: changed a "char *" to a "const char *" to avoid + g++ warnings. + +- All instances of open() that create files originally created them + with mode 0600; changed this to 0666 (which will still be affected + by the user's umask). + +- Added "listbas" symlink, to save typing "chkbas -short" over and over + again. + +- adir's -dir option now creates the directory if it doesn't exist. + +- Wrote man pages for all the utilities. diff --git a/jindroush/acvt/Makefile b/jindroush/acvt/Makefile new file mode 100644 index 0000000..498e2fc --- /dev/null +++ b/jindroush/acvt/Makefile @@ -0,0 +1,52 @@ +#===================================================================== +PRGNAME = acvt + +DESTDIR= +PREFIX=/usr + +LDLIBS=-L../lib -ljindroush +INCPATH=-I../include + +all: release + +release: + @$(MAKE) $(PRGNAME) CFLAGS="-c -O2 -Wall -D__CDISK_SAVE__" LDFLAGS="" + @echo RELEASE: Compiled. + +rel_strip: release + @strip $(PRGNAME) + +install: rel_strip + cp $(PRGNAME) $(DESTDIR)/$(PREFIX)/bin/ + @echo RELEASE: Installed. + +debug: + @$(MAKE) $(PRGNAME) CFLAGS="-c -g -Wall -D_DEBUG -D__CDISK_SAVE__" LDFLAGS="-g" + @echo DEBUG: Compiled. + +clean: + rm -rf *.o $(PRGNAME) $(PRGNAME).exe switches.cpp + @echo DEBUG: Cleaned. + + +OBJECTS = acvt.o + +#===================================================================== +CXX = g++ +LD = g++ +CPPFLAGS=$(COPT) +COPT=-O2 + +#===================================================================== + +$(PRGNAME) : $(OBJECTS) + $(LD) $(LDFLAGS) $(OBJECTS) $(LDLIBS) -o $(PRGNAME) + +%.o : %.cpp switches.cpp + $(CXX) $(INCPATH) $(CPPFLAGS) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(INCPATH) $(CPPFLAGS) $(CFLAGS) $< -o $@ + +switches.cpp : switches.def ../switches.pl + perl ../switches.pl $< $@ diff --git a/jindroush/acvt/acvt.cpp b/jindroush/acvt/acvt.cpp new file mode 100644 index 0000000..857da5b --- /dev/null +++ b/jindroush/acvt/acvt.cpp @@ -0,0 +1,216 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "pub.def" +#include "jintypes.h" +#include "autil.h" +#include "adsk.h" + +BOOL Convert( char* szInFile, char* szOutFile ); + +DISK_TYPE g_dtypeIn = DISK_AUTO; +DISK_TYPE g_dtypeOut = DISK_ATR; + +BOOL g_bVerbose = FALSE; +BOOL g_bBatchMode = FALSE; +BOOL g_bRepairAuto = FALSE; +BOOL g_bRepair = TRUE; +BOOL g_bFirstErrStop = FALSE; +BOOL g_bOverWrite = FALSE; +BOOL g_bTestOnly = FALSE; +BOOL g_bForceClassic = FALSE; + +#define SHEADER PRG_NAME " v" PRG_VERSION " (c) " PRG_COPYRIGHT " " PRG_AUTHOR "\n" + +#define HEADER SHEADER \ + PRG_DESC "\n" \ + " Latest version can be found at " PRG_URL "\n" \ + " Published under GPL. See GPL.TXT.\n\n" + +#define USAGE HEADER "Usage: " PRG_NAME " " PRG_USAGE + +#include "switches.cpp" + +int main(int argc,char *argv[]) +{ + setbuf( stdout, NULL ); + setbuf( stderr, NULL ); + + if ( !SWITCHES_Init( &argc, argv ) ) + return 1; + + if ( argc < 2 ) + { + SWFN_HELP( USAGE ); + return 1; + } + + fprintf( stderr, SHEADER ); + + BOOL bRet = FALSE; + + char szOutFile[ 255 ]; + + if ( g_bBatchMode ) + { + argc--; + argv++; + + while( argc-- ) + { + char* szInFile = *(argv++); + GuessBestFnameFromPC( szOutFile, szInFile, GetDiskTypeExt( g_dtypeOut ) ); + bRet = Convert( szInFile, szOutFile ); + printf( "\n" ); + + if ( !bRet && g_bFirstErrStop ) + break; + } + + } + else + { + char* szInFile = argv[ 1 ]; + + if ( argc >= 3 ) + { + strcpy( szOutFile, argv[ 2 ] ); + } + else + { + GuessBestFnameFromPC( szOutFile, szInFile, GetDiskTypeExt( g_dtypeOut ) ); + } + + bRet = Convert( szInFile, szOutFile ); + } + + if ( bRet && !g_bTestOnly ) + printf ( "Done.\n" ); + + return bRet ? 0 : 1; +} + +BOOL Convert( char* szInFile, char* szOutFile ) +{ + ADisk* pDiskIn = NULL; + ADisk* pDiskOut = NULL; + + DISKINIT_RETCODE ret; + + g_dtypeIn = DISK_ATR; + if ( DI_RET_CONTINUE == ( ret = InitializeDisk( &pDiskIn, DISK_ATR, szInFile, FALSE, g_bRepair, g_bRepairAuto ) ) ) + { + g_dtypeIn = DISK_DI; + if ( DI_RET_CONTINUE == ( ret = InitializeDisk( &pDiskIn, DISK_DI, szInFile, FALSE, g_bRepair, g_bRepairAuto ) ) ) + { + g_dtypeIn = DISK_DCM; + if ( DI_RET_CONTINUE == ( ret = InitializeDisk( &pDiskIn, DISK_DCM, szInFile, FALSE, g_bRepair, g_bRepairAuto ) ) ) + { + g_dtypeIn = DISK_SCP; + if ( DI_RET_CONTINUE == ( ret = InitializeDisk( &pDiskIn, DISK_SCP, szInFile, FALSE, g_bRepair, g_bRepairAuto ) ) ) + { + g_dtypeIn = DISK_XFD; + if ( DI_RET_CONTINUE == ( ret = InitializeDisk( &pDiskIn, DISK_XFD, szInFile, FALSE, g_bRepair, g_bRepairAuto ) ) ) + { + printf( "Unable to determine format of disk image '%s'!\n", szInFile ); + return FALSE; + } + } + } + } + } + + if ( ret == DI_RET_CANT_CONTINUE ) + return FALSE; + + printf( "Input file '%s' (%s)\n", szInFile, GetDiskTypeName( g_dtypeIn ) ); + + if ( g_bVerbose ) + { + DISK_GEOMETRY* pgeo = pDiskIn->GetGeometry(); + printf( "Sides: %d\n", pgeo->iSides ); + printf( "Tracks: %d\n", pgeo->iTracks ); + printf( "SecPerTrack: %d\n", pgeo->iSectorsPerTrack ); + printf( "BytesPerSec: %d\n", pgeo->iBytesPerSector ); + printf( "Sectors: %d\n", pgeo->iSectors ); + } + + if ( g_bTestOnly ) + { + printf( "File loaded OK.\n" ); + delete pDiskIn; + return TRUE; + } + + switch( g_dtypeOut ) + { + case DISK_ATR: + pDiskOut = new CAtr(); + break; + + case DISK_XFD: + pDiskOut = new CXfd(); + break; + + case DISK_DI: + pDiskOut = new CDi(); + break; + + case DISK_SCP: + pDiskOut = new CScp(); + break; + + case DISK_DCM: + pDiskOut = new CDcm(); + break; + + default: + break; + } + + if ( !pDiskOut ) + { + fprintf( stderr, "Can't create such image!\n" ); + return FALSE; + } + + DISK_GEOMETRY* pgeo = pDiskIn->GetGeometry(); + DISK_GEOMETRY forced; + + memcpy( &forced, pgeo, sizeof( DISK_GEOMETRY ) ); + + if ( g_bForceClassic ) + ForceClassicSize( &forced ); + + //duplicating the image + pDiskOut->Duplicate( pDiskIn, &forced ); + + printf( "Output file '%s' (%s)\n", szOutFile, GetDiskTypeName( g_dtypeOut ) ); + + //and save it in new format + if ( !pDiskOut->Save( szOutFile, g_bOverWrite ) ) + { + printf( "Error! %s\n", pDiskOut->GetLastError() ); + delete pDiskIn; + delete pDiskOut; + return FALSE; + } + + delete pDiskIn; + delete pDiskOut; + + return TRUE; +} + diff --git a/jindroush/acvt/pub.def b/jindroush/acvt/pub.def new file mode 100644 index 0000000..5068092 --- /dev/null +++ b/jindroush/acvt/pub.def @@ -0,0 +1,31 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#define PRG_NAME "acvt" +#define PRG_VERSION "1.07" +#define PRG_COPYRIGHT "2000-2001" +#define PRG_UNDERGPL "1" +#define PRG_AUTHOR "Jindrich Kubec " + +#define PRG_URL "http://www.asw.cz/~kubecj" + +#define PRG_DESC "Converts between XFD-SCP-ATR-DCM-DI formats." +#define PRG_USAGE "[options] sourcefile [destfile]" + +#define PRG_ARCH "PC" +#define PRG_TOOLS "PERL" + +#define PRG_SRCS "!GENERATED!" +#define PRG_BINS "rel/acvt.exe" diff --git a/jindroush/acvt/readme.txt b/jindroush/acvt/readme.txt new file mode 100644 index 0000000..e2b41d5 --- /dev/null +++ b/jindroush/acvt/readme.txt @@ -0,0 +1,152 @@ +Acvt v1.07 (c) 2000-2001 Jindrich Kubec +Latest version can be found at http://www.asw.cz/~kubecj + +This program is provided 'as is', no warranty will be taken +for any damage caused by it or by any use of it. + +The whole package is placed under the GNU Public License, for further +information on redistribution see the included file "GPL.TXT". + + +Description: +------------ +Converts between XFD-SCP-ATR-DCM-DI formats. +ATR - SIO2PC images +XFD - XFormer images +DCM - DiskCommunicator images +SCP - SpartaDos SCOPY images +DI - XL/ST link / XLDJ disk images + +It's replacement for DOS version of Steven Tucker's Imagic. +It's in fact better because: +1) It's free. +2) It comes with source. +3) Therefore it could be ported to another architectures. +4) Contains less bugs. (Hope so.) +5) Can repair some invalid images. +6) Now also supports DI file format. + +Thanks go to: +Ernest Schreurs for his DiskCommunicator dissection and paper about DCM format. +Chad Wagner for DCMtoATR utility (DCM driver is still loosely based on his + code). +Burian brothers for lots of DI files. + + +Usage: +------ +Acvt [options] sourcefile [destfile] + +sourcefile is Atari disk image (ATR,XFD,SCP,DCM,DI). + +destfile is output disk image. If omitted, output filename is created + automatically. + +-xfd -atr -scp -dcm -di options are output type modes. Default is -atr. + +-batchmode: turns on multi file processing mode. Only input files are specified + on command-line (Unix-like compatible regexp expressions are allowed when + compiled under DJGPP). Output filenames are created automatically. + +-autorepair: automatically determines the best repair method. + +-norepair: doesn't ask for repair options and considers input file invalid. + +-errstop: in batch mode ends on first error encountered. + +-over: overwrites existing files. Otherwise returns an error. + +-test: only loads input images and displays their state. + +-classic: forces to create 'classic' Atari disk sizes. + + +History: +-------- +Date, Author, Version +5/22/1999, kubecj, 0.10 +First version + +5/25/1999, kubecj, 0.15 +SCP save added + +5/29/1999, kubecj, 0.20 +DCM save added, decompression corrected + +5/30/1999, kubecj, 0.30 +Code cleanup + +6/1/1999, kubecj, 0.35 +Invalid DD ATR repair added + +6/2/1999, kubecj, 0.40 +Invalid DD XFD repair added +Invalid ATR length repair added +Added cached read for DCM decompression + +6/3/1999, kubecj, 0.42 +Code cleanup + +6/4/1999, kubecj, 0.43 +Added checks for DCM decompression +Check for multi-arc + +6/5/1999, kubecj, 1.00 +First public version + +6/10/1999, kubecj, 1.01 +Compatibility macros & valid archive :) + +6/11/1999, kubecj, 1.02 +Repaired repairing ;) + +6/13/1999, kubecj, 1.03 +Changed switches processing + +10/10/1999, kubecj, 1.04 +Only changed generation of archive, new version to avoid version checking +problems. + +6/6/2000, kubecj, 1.05 +Minor bugfix concerning repairing. +Added -classic commandline switch to force to create 'classic' disk sizes. + +2/26/2001, kubecj, 1.06 +Added DI file format. Its support is just a beta! + +3/8/2001, kubecj, 1.07 +Handling of double sided diskettes in DI format. + + +To Do: +------ +Maybe check pass count in DCM images? +Better handling of DI files. + + +Known Bugs: +----------- +DCM record 0x42 is not decompressed, code is present, but commented out and + untested. I need some sample first. + +DI files are really an educated guess. There are many 'white places' for me. +I need the description of the disk format. + +Function for actual conversion is stupid. In fact in order to convert ATR to + XFD there is created Atr object, loaded in, and same Xfd object is created and + all the data are duplicated. With 16MB SpartaDOS Atr images it's simply too + much. + + +Compiling Tools: +---------------- +For scripts: Perl. +URL: http://www.perl.com + +For PC executables: DJGPP. +Sources were written/tested on GCC/Intel only. There should be only +minor problems to port it to different architectures/environments. +Makefile should need only minor changes. +URL: http://www.delorie.com + + diff --git a/jindroush/acvt/switches.def b/jindroush/acvt/switches.def new file mode 100644 index 0000000..763907b --- /dev/null +++ b/jindroush/acvt/switches.def @@ -0,0 +1,64 @@ +v +verbose output +=g_bVerbose = TRUE; += + +atr, a +output is ATR +=g_dtypeOut = DISK_ATR; += + +di +output is DI +=g_dtypeOut = DISK_DI; += + +xfd, x +output is XFD +=g_dtypeOut = DISK_XFD; += + +scp, s +output is SCP +=g_dtypeOut = DISK_SCP; += + +dcm, d +output is DCM +=g_dtypeOut = DISK_DCM; += + +batch, batchmode, b +batch mode +=g_bBatchMode = TRUE; += + +errstop +in batchmode stop on first error +=g_bFirstErrStop = TRUE; += + +over, overwrite +turns on file overwriting +=g_bOverWrite = TRUE; += + +autorepair +auto repair mode +=g_bRepairAuto = TRUE; += + +norepair +don't repair +=g_bRepair = FALSE; += + +test +only test input files +=g_bTestOnly = TRUE; += + +classic +force to create 'classic' disk formats +=g_bForceClassic = TRUE; += diff --git a/jindroush/adir/Makefile b/jindroush/adir/Makefile new file mode 100644 index 0000000..284add5 --- /dev/null +++ b/jindroush/adir/Makefile @@ -0,0 +1,52 @@ +#===================================================================== +PRGNAME = adir + +DESTDIR= +PREFIX=/usr + +LDLIBS=-L../lib -ljindroush +INCPATH=-I../include + +all: release + +release: + @$(MAKE) $(PRGNAME) CFLAGS="-c -O2 -Wall -D__CDISK_SAVE__" LDFLAGS="" + @echo RELEASE: Compiled. + +rel_strip: release + @strip $(PRGNAME) + +install: rel_strip + cp $(PRGNAME) $(DESTDIR)/$(PREFIX)/bin/ + @echo RELEASE: Installed. + +debug: + @$(MAKE) $(PRGNAME) CFLAGS="-c -g -Wall -D_DEBUG -D__CDISK_SAVE__" LDFLAGS="-g" + @echo DEBUG: Compiled. + +clean: + rm -rf *.o $(PRGNAME) $(PRGNAME).exe switches.cpp + @echo DEBUG: Cleaned. + + +OBJECTS = adir.o + +#===================================================================== +CXX = g++ +LD = g++ +CPPFLAGS=$(COPT) +COPT=-O2 + +#===================================================================== + +$(PRGNAME) : $(OBJECTS) + $(LD) $(LDFLAGS) $(OBJECTS) $(LDLIBS) -o $(PRGNAME) + +%.o : %.cpp switches.cpp + $(CXX) $(INCPATH) $(CPPFLAGS) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(INCPATH) $(CPPFLAGS) $(CFLAGS) $< -o $@ + +switches.cpp : switches.def ../switches.pl + perl ../switches.pl $< $@ diff --git a/jindroush/adir/adir.cpp b/jindroush/adir/adir.cpp new file mode 100644 index 0000000..7dceb01 --- /dev/null +++ b/jindroush/adir/adir.cpp @@ -0,0 +1,494 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include + +#include "jintypes.h" +#include + +#include "pub.def" + +#include "adsk.h" + +#include "cfs.h" +#include "cfs_dos2.h" +#include "cfs_dos3.h" +#include "cfs_dosm.h" +#include "cfs_doss.h" +#include "cfs_kboo.h" +#include "cfs_b2b.h" +#include "cfs_jonw.h" +#include "cfs_howf.h" +#include "cfs_robc.h" +#include "cfs_boot.h" + +typedef enum +{ + DOS_AUTO, + DOS_2, + DOS_3, + DOS_MY, + DOS_SP, + DOS_KBOOT, + DOS_B2B, + DOS_JONW, + DOS_HOWF, + DOS_ROBC, + DOS_BOOT, +} DOS_TYPE; + +void ReadDir( char* szDirName, CDirEntry* pEntry ); +BOOL CheckMask( char* szFname, char* szMask ); +void MakePath( char* szDest, char* szDir, char* szFileName ); +BOOL InitializeFs( DOS_TYPE dostype, BOOL bVerbose ); +// BOOL SWFN_DOST( void* ); +char* GetFSName( DOS_TYPE dostype ); + +BOOL g_bIsMyDos = FALSE; +BOOL g_bToLower = FALSE; +BOOL g_bVerbose = FALSE; +BOOL g_bListOnly = TRUE; +BOOL g_bRepairAuto = TRUE; + +DOS_TYPE g_dostype = DOS_AUTO; +DISK_TYPE g_dtypeIn = DISK_AUTO; + +char g_szMask[ 256 ] = "*"; +char g_szPath[ 256 ] = "."; + +ADisk* g_pDisk; +CFs* g_pFs; + +#define SHEADER PRG_NAME " v" PRG_VERSION " (c) " PRG_COPYRIGHT " " PRG_AUTHOR "\n" + +#define HEADER SHEADER \ + PRG_DESC "\n" \ + " Latest version can be found at " PRG_URL "\n" \ + " Published under GPL. See GPL.TXT.\n\n" + +#define USAGE HEADER "Usage: " PRG_NAME " " PRG_USAGE + +#include "switches.cpp" + +int main(int argc,char *argv[]) +{ + setbuf( stdout, NULL ); + setbuf( stderr, NULL ); + + if ( !SWITCHES_Init( &argc, argv ) ) + return 1; + + if ( argc < 2 ) + { + SWFN_HELP( USAGE ); + return 1; + } + + fprintf( stderr, SHEADER ); + + char* szInfile = argv[ 1 ]; + + if ( argc >= 3 ) + { + strcpy( g_szMask, argv[ 2 ] ); + } + + DISKINIT_RETCODE ret; + g_dtypeIn = DISK_ATR; + if ( DI_RET_CONTINUE == ( ret = InitializeDisk( &g_pDisk, DISK_ATR, szInfile, FALSE, TRUE, g_bRepairAuto ) ) ) + { + g_dtypeIn = DISK_DI; + if ( DI_RET_CONTINUE == ( ret = InitializeDisk( &g_pDisk, DISK_DI, szInfile, FALSE, FALSE, FALSE ) ) ) + { + g_dtypeIn = DISK_DCM; + if ( DI_RET_CONTINUE == ( ret = InitializeDisk( &g_pDisk, DISK_DCM, szInfile, FALSE, FALSE, FALSE ) ) ) + { + g_dtypeIn = DISK_SCP; + if ( DI_RET_CONTINUE == ( ret = InitializeDisk( &g_pDisk, DISK_SCP, szInfile, FALSE, FALSE, FALSE ) ) ) + { + g_dtypeIn = DISK_XFD; + if ( DI_RET_CONTINUE == ( ret = InitializeDisk( &g_pDisk, DISK_XFD, szInfile, FALSE, TRUE, g_bRepairAuto ) ) ) + { + printf( "Unable to determine format of disk image '%s'!\n", szInfile ); + return FALSE; + } + } + } + } + } + + if ( ret == DI_RET_CANT_CONTINUE ) + return 1; + + printf( "Input file '%s' (%s)\n", szInfile, GetDiskTypeName( g_dtypeIn ) ); + + + if ( g_dostype == DOS_AUTO ) + { + DOS_TYPE bestfs = DOS_AUTO; + int iBest = 100; + + printf( "Checking '%s' for possible filesystems:\n", argv[1] ); + + if ( InitializeFs( DOS_SP, FALSE ) ) + { + if ( iBest > g_pFs->GetInvalidPercent() ) + { + bestfs = DOS_SP; + iBest = g_pFs->GetInvalidPercent(); + } + delete g_pFs; + } + + if ( InitializeFs( DOS_ROBC, FALSE ) ) + { + if ( iBest > g_pFs->GetInvalidPercent() ) + { + bestfs = DOS_ROBC; + iBest = g_pFs->GetInvalidPercent(); + } + delete g_pFs; + } + + if ( InitializeFs( DOS_MY, FALSE ) ) + { + if ( iBest > g_pFs->GetInvalidPercent() ) + { + bestfs = DOS_MY; + iBest = g_pFs->GetInvalidPercent(); + } + delete g_pFs; + } + + if ( InitializeFs( DOS_2, FALSE ) ) + { + if ( iBest > g_pFs->GetInvalidPercent() ) + { + bestfs = DOS_2; + iBest = g_pFs->GetInvalidPercent(); + } + delete g_pFs; + + } + + if ( InitializeFs( DOS_KBOOT, FALSE ) ) + { + if ( iBest > g_pFs->GetInvalidPercent() ) + { + bestfs = DOS_KBOOT; + iBest = g_pFs->GetInvalidPercent(); + } + delete g_pFs; + } + + if ( InitializeFs( DOS_B2B, FALSE ) ) + { + if ( iBest > g_pFs->GetInvalidPercent() ) + { + bestfs = DOS_B2B; + iBest = g_pFs->GetInvalidPercent(); + } + delete g_pFs; + } + + if ( InitializeFs( DOS_JONW, FALSE ) ) + { + if ( iBest > g_pFs->GetInvalidPercent() ) + { + bestfs = DOS_JONW; + iBest = g_pFs->GetInvalidPercent(); + } + delete g_pFs; + } + + if ( InitializeFs( DOS_HOWF, FALSE ) ) + { + if ( iBest > g_pFs->GetInvalidPercent() ) + { + bestfs = DOS_HOWF; + iBest = g_pFs->GetInvalidPercent(); + } + delete g_pFs; + } + + if ( InitializeFs( DOS_3, FALSE ) ) + { + if ( iBest > g_pFs->GetInvalidPercent() ) + { + bestfs = DOS_3; + iBest = g_pFs->GetInvalidPercent(); + } + delete g_pFs; + } + + if ( ( bestfs == DOS_AUTO ) || iBest ) + { + fprintf( stderr, "\nUnable to guess best filesystem (Best was %s: %d%%). Exiting.\n", GetFSName( bestfs ), iBest ); + delete g_pDisk; + return 1; + } + else + { + printf( "\nBest guess:\n" ); + + if ( !InitializeFs( bestfs, TRUE ) ) + { + delete g_pDisk; + return 1; + } + } + + } + else + { + if ( !InitializeFs( g_dostype, TRUE ) ) + { + delete g_pDisk; + return 1; + } + } + + CDirEntry* pEntry = g_pFs->GetRoot(); + + if ( !pEntry ) + { + fprintf( stderr, "No files found!\n" ); + delete g_pFs; + delete g_pDisk; + return 1; + } + + { + struct stat sbuf; + if(stat(g_szPath, &sbuf) != 0) + mkdir(g_szPath, 0777); + } + ReadDir( NULL, pEntry ); + + delete g_pFs; + delete g_pDisk; + + return 0; +} + +BOOL InitializeFs( DOS_TYPE dostype, BOOL bVerbose ) +{ + switch( dostype ) + { + case DOS_2: + g_pFs = new CDos2(); + break; + + case DOS_3: + g_pFs = new CDos3(); + break; + + case DOS_MY: + g_pFs = new CDosM(); + break; + + case DOS_SP: + g_pFs = new CDosS(); + break; + + case DOS_KBOOT: + g_pFs = new CKBoot(); + break; + + case DOS_B2B: + g_pFs = new CBas2Boot(); + break; + + case DOS_JONW: + g_pFs = new CJonw(); + break; + + case DOS_HOWF: + g_pFs = new CHowf(); + break; + + case DOS_ROBC: + g_pFs = new CRobc(); + break; + + case DOS_BOOT: + g_pFs = new CBoot(); + break; + + default: + if ( bVerbose ) + fprintf( stderr, "Invalid filesystem specified!\n" ); + return FALSE; + } + + if ( !g_pFs ) + { + if ( bVerbose ) + fprintf( stderr, "Can't initialize filesystem driver!\n" ); + return FALSE; + } + + if ( !g_pFs->Mount( g_pDisk ) ) + { + if ( bVerbose ) + fprintf( stderr, "Mount failed because:\n%s\n", g_pFs->GetLastError() ); + delete g_pFs; + return FALSE; + } + + printf( "Mounting as %s: Invalid %d%%\n", GetFSName( dostype ), g_pFs->GetInvalidPercent() ); + + return TRUE; +} + +void ReadDir( char* szDirName, CDirEntry* pEntry ) +{ + char szCurrEntryName[ 256 ]; + + do + { + strcpy( szCurrEntryName, pEntry->m_szFname ); + + char szFullAtariPath[ 256 ]; + + if ( szDirName ) + MakePath( szFullAtariPath, szDirName, szCurrEntryName ); + else + strcpy( szFullAtariPath, szCurrEntryName ); + + char szFullOsPath[ 256 ]; + MakePath( szFullOsPath, g_szPath, szFullAtariPath ); + + if ( CheckMask( szCurrEntryName, g_szMask ) ) + { + + if ( pEntry->m_dwFlags & DIRE_SUBDIR ) + { + if ( !g_bListOnly ) + { + printf( "Creating dir %s\n", szCurrEntryName ); + mkdir( szFullOsPath, 0777 ); + } + + if ( pEntry->m_pSubdir ) + ReadDir( szFullAtariPath, pEntry->m_pSubdir ); + + } + else + { + printf( "%s %s ", pEntry->m_szAscData, szFullAtariPath ); + + if ( !g_bListOnly ) + { + BOOL bRes = g_pFs->ExportFile( szFullOsPath, pEntry ); + + if ( bRes ) + { + printf( "exported\n" ); + } + else + { + printf( "invalid because:\n%s\n", g_pFs->GetLastError() ); + } + } + else + { + printf( "\n" ); + } + } + } + + pEntry = pEntry->m_pNext; + + } while( pEntry ); + + return; +} + +BOOL CheckMask( char* szFname, char* szMask ) +{ + return fnmatch( szMask, szFname, FNM_NOESCAPE ) ? FALSE : TRUE; +} + +void MakePath( char* szDest, char* szDir, char* szFileName ) +{ + int iLength; + + if ( szDest != szDir ) + strcpy ( szDest, szDir ); + + iLength = strlen( szDest ); + + if ( iLength ) + { + if ( szDest[ iLength - 1 ] != '/' ) + { + szDest[ iLength + 1 ] = '\0'; + szDest[ iLength ] = '/'; + } + } + strcat( szDest, szFileName ); +} + +/* +BOOL SWFN_DOST( void* p ) +{ + g_dostype = (DOS_TYPE)(int)p; + + return TRUE; +} +*/ + +//returns ptr to filesystem name +char* GetFSName( DOS_TYPE dostype ) +{ + switch( dostype ) + { + case DOS_2: + return "Dos2"; + + case DOS_3: + return "Dos3"; + + case DOS_MY: + return "MyDos"; + + case DOS_SP: + return "SpartaDos"; + + case DOS_KBOOT: + return "KBoot"; + + case DOS_B2B: + return "Bas2Boot"; + + case DOS_HOWF: + return "HowFen"; + + case DOS_ROBC: + return "RobC"; + + case DOS_BOOT: + return "Boot"; + + case DOS_JONW: + return "JonW"; + + default: + return "None"; + } +} + +//returns ptr to disk type name diff --git a/jindroush/adir/pub.def b/jindroush/adir/pub.def new file mode 100644 index 0000000..6ec4a31 --- /dev/null +++ b/jindroush/adir/pub.def @@ -0,0 +1,31 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#define PRG_NAME "adir" +#define PRG_VERSION "0.67" +#define PRG_COPYRIGHT "1999-2001" +#define PRG_UNDERGPL "1" +#define PRG_AUTHOR "Jindrich Kubec " + +#define PRG_URL "http://www.asw.cz/~kubecj" + +#define PRG_DESC "Extracts files from Atari disk images." +#define PRG_USAGE "[options] sourcefile [mask]" + +#define PRG_ARCH "PC" +#define PRG_TOOLS "PERL" + +#define PRG_SRCS "!GENERATED!" +#define PRG_BINS "rel/adir.exe" diff --git a/jindroush/adir/readme.txt b/jindroush/adir/readme.txt new file mode 100644 index 0000000..520c067 --- /dev/null +++ b/jindroush/adir/readme.txt @@ -0,0 +1,112 @@ +Adir v0.67 (c) 1999-2001 Jindrich Kubec +Latest version can be found at http://www.asw.cz/~kubecj + +This program is provided 'as is', no warranty will be taken +for any damage caused by it or by any use of it. + +The whole package is placed under the GNU Public License, for further +information on redistribution see the included file "GPL.TXT". + + +Description: +------------ +Extracts files from Atari disk images. +Originally based on ATR2UNIX from Preston Crow, now rewritten totally using +virtual CFs and CDisk classes. + +Currently supported are: +Atari DOS 2.0/2.5 and compatibles +Atari DOS 3.0 +MyDOS +Sparta DOS and compatibles (BeWe) +K-Boot images +HowFen DOS +JonW multiboot +RobC multiboot +Bas2Boot images +boot images (extracts boot sector only) + +Adir tries to guess the best filesystem. Could be of course overriden by +switch. + + +Usage: +------ +Adir [options] sourcefile [mask] + +sourcefile is Atari disk image. + +-? prints switches + + +History: +-------- +Date, Author, Version +4/5/1999, kubecj, 0.10 +First version + +5/11/1999, kubecj, 0.20 +Added DOS3 filesystem + +5/17/1999, kubecj, 0.30 +Added SpartaDos filesystem + +5/22/1999, kubecj, 0.40 +Added KBoot filesystem + +5/23/1999, kubecj, 0.50 +Added SCP & DCM disk drivers + +6/3/1999, kubecj, 0.55 +Disk drivers synchronized + +6/11/1999, kubecj, 0.60 +Added HowFen Dos filesystem + +6/12/1999, kubecj, 0.61 +Added Boot filesystem (virtual) + +10/10/1999, kubecj, 0.62 +Changed switches processing. + +3/30/2000, kubecj, 0.63 +Added autorepair. +Added Bas2Boot filesystem. + +2/26/2001, kubecj, 0.64 +Added handling of DI files. + +3/1/2001, kubecj, 0.65 +Compatibility macros for big-endian systems. + +3/8/2001, kubecj, 0.66 +Double side support for DI files. + +6/12/2001, kubecj, 0.67 +Added RobC fs. + + +To Do: +------ +Add other file systems. (DOS4) +Add volume information (useful for Sparta only?) +Add write capability (after a long time). + + +Known Bugs: +----------- +None. + + +Compiling Tools: +---------------- +For scripts: Perl. +URL: http://www.perl.com + +For PC executables: DJGPP. +Sources were written/tested on GCC/Intel only. There should be only +minor problems to port it to different architectures/environments. +Makefile should need only minor changes. +URL: http://www.delorie.com + + diff --git a/jindroush/adir/switches.def b/jindroush/adir/switches.def new file mode 100644 index 0000000..fe61c43 --- /dev/null +++ b/jindroush/adir/switches.def @@ -0,0 +1,64 @@ +dos2 +mount as Dos2 +=g_dostype = DOS_2; += + +dos3 +mount as Dos3 +=g_dostype = DOS_3; += + +mydos, dosm +mount as MyDos +=g_dostype = DOS_MY; += + +spdos, sparta, doss +mount as SpartaDos +=g_dostype = DOS_SP; += + +kboot +mount as Kboot +=g_dostype = DOS_KBOOT; += + +bas2boot, b2b +mount as Bas2Boot +=g_dostype = DOS_B2B; += + +jonw +mount as JonW +=g_dostype = DOS_JONW; += + +robc +mount as RobC +=g_dostype = DOS_ROBC; += + +howf, howfen +mount as HowFen Dos +=g_dostype = DOS_HOWF; += + +boot +mount as boot +=g_dostype = DOS_BOOT; += + +e +export files +=g_bListOnly = FALSE; += + +dir +export to directory +path=bRet = SWFN_GETPATH( g_szPath ); += + +dontrepair +don't repair invalid files automatically +=g_bRepairAuto = FALSE; += diff --git a/jindroush/aext/Makefile b/jindroush/aext/Makefile new file mode 100644 index 0000000..4d016e6 --- /dev/null +++ b/jindroush/aext/Makefile @@ -0,0 +1,49 @@ +#===================================================================== +PRGNAME = aext + +DESTDIR= +PREFIX=/usr + +LDLIBS=-L../lib -ljindroush +INCPATH=-I../include + +all: $(PRGNAME) + +release: + @$(MAKE) $(PRGNAME) CFLAGS="-c -O2 -Wall -D__CDISK_SAVE__" LDFLAGS="" + @echo RELEASE: Compiled. + +rel_strip: release + @strip $(PRGNAME) + +install: rel_strip + cp $(PRGNAME) $(DESTDIR)/$(PREFIX)/bin/ + @echo RELEASE: Installed. + +debug: + @$(MAKE) $(PRGNAME) CFLAGS="-c -g -Wall -D_DEBUG -D__CDISK_SAVE__" LDFLAGS="-g" + @echo DEBUG: Compiled. + +clean: + rm -rf *.o $(PRGNAME) $(PRGNAME).exe switches.cpp + @echo DEBUG: Cleaned. + + +OBJECTS = aext.o + +#===================================================================== +CXX = g++ +LD = g++ +CPPFLAGS=$(COPT) +COPT=-O2 + +#===================================================================== + +$(PRGNAME) : $(OBJECTS) + $(LD) $(LDFLAGS) $(OBJECTS) $(LDLIBS) -o $(PRGNAME) + +%.o : %.cpp switches.cpp + $(CXX) $(INCPATH) $(CPPFLAGS) -c $< -o $@ + +switches.cpp : switches.def ../switches.pl + perl ../switches.pl $< $@ diff --git a/jindroush/aext/aext.cpp b/jindroush/aext/aext.cpp new file mode 100644 index 0000000..75c94c3 --- /dev/null +++ b/jindroush/aext/aext.cpp @@ -0,0 +1,280 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "pub.def" +#include "jintypes.h" + +int g_iBlkEnd = 0; +int g_iBlkStart = 0; +int g_iBlkLength = 0; +int g_iBlkBase = 0; + +char szStart[ MAX_PATH ]; +char szEnd[ MAX_PATH ]; +char szLength[ MAX_PATH ]; + +BOOL g_bStartUsed = FALSE; +BOOL g_bEndUsed = FALSE; +BOOL g_bLenUsed = FALSE; + +int g_bOutputIsAtari = FALSE; +int g_bUseBase = FALSE; + +#define SHEADER PRG_NAME " v" PRG_VERSION " (c) " PRG_COPYRIGHT " " PRG_AUTHOR "\n" + +#define HEADER SHEADER \ + PRG_DESC "\n" \ + " Latest version can be found at " PRG_URL "\n" \ + " Published under GPL. See GPL.TXT.\n\n" + +#define USAGE HEADER "Usage: " PRG_NAME " " PRG_USAGE + +#include "switches.cpp" + +int ToNum( char*, int ); + +int main( int argc, char *argv[] ) +{ + setbuf( stdout, NULL ); + setbuf( stderr, NULL ); + + if ( !SWITCHES_Init( &argc, argv ) ) + return 1; + + if ( argc < 2 ) + { + SWFN_HELP( USAGE ); + return 1; + } + + fprintf( stderr, SHEADER ); + + char* szInfile = argv[ 1 ]; + + char szOutfile[ MAX_PATH ]; + + if ( argc >= 3 ) + { + strcpy( szOutfile, argv[ 2 ] ); + } + else + { + strcpy( szOutfile, "prg.axe" ); + } + + int hIn = open( szInfile, O_RDONLY | O_BINARY ); + + if ( hIn == -1 ) + { + fprintf( stderr, "Can't open infile '%s'!\n", szInfile ); + return -1; + } + + if( g_bStartUsed ) + { + g_iBlkStart = ToNum( szStart, 1 ); + } + + if( g_bEndUsed ) + { + g_iBlkEnd = ToNum( szEnd, 1 ); + } + + if( g_bLenUsed ) + { + g_iBlkLength = ToNum( szLength, 0 ); + } + + LONG lLen = lseek( hIn, 0, SEEK_END ); + lseek( hIn, 0, SEEK_SET ); + + if( g_bEndUsed && g_iBlkEnd < 1 ) + { + g_iBlkEnd = lLen - 1 + g_iBlkEnd; + } + + if( g_bStartUsed ) + { + if ( g_bEndUsed ) + { + g_iBlkLength = g_iBlkEnd - g_iBlkStart + 1; + } + else + { + //START & ? + if ( g_bLenUsed ) + { + //start & length + g_iBlkEnd = g_iBlkStart + g_iBlkLength - 1; + } + else + { + //start & nothing + g_iBlkEnd = lLen - 1; + g_iBlkLength = g_iBlkEnd - g_iBlkStart + 1; + } + } + + } + else if( g_bEndUsed ) + { + if( g_bLenUsed ) + { + //end & length + g_iBlkStart = g_iBlkEnd - g_iBlkLength + 1; + } + else + { + //end only + g_iBlkStart = 0; + g_iBlkLength = g_iBlkEnd - g_iBlkStart + 1; + } + } + else + { + if( g_bLenUsed ) + { + //length only + g_iBlkStart = 0; + g_iBlkEnd = g_iBlkStart + g_iBlkLength - 1; + } + else + { + //nothing + g_iBlkStart = 0; + g_iBlkLength = lLen; + g_iBlkEnd = g_iBlkStart + g_iBlkLength - 1; + } + } + + if( ( g_iBlkStart < 0 ) || ( g_iBlkStart >= lLen ) ) + { + fprintf( stderr, "Invalid start ptr!\n" ); + close( hIn ); + return -1; + } + + if( ( g_iBlkEnd < 0 ) || ( g_iBlkEnd >= lLen ) || ( g_iBlkEnd < g_iBlkStart ) ) + { + fprintf( stderr, "Invalid end ptr!\n" ); + close( hIn ); + return -1; + } + + int iBlkStartM = g_iBlkStart; + int iBlkEndM = g_iBlkEnd; + + if( g_bUseBase ) + { + iBlkStartM = g_iBlkBase; + iBlkEndM = g_iBlkBase + g_iBlkLength - 1; + } + + if ( ( ( iBlkEndM >= 0x10000 ) || ( iBlkStartM >= 0x10000 ) ) && g_bOutputIsAtari ) + { + fprintf( stderr, "End goes past end of RAM in real Atari!\n" ); + close( hIn ); + return -1; + } + + int hOut = open( szOutfile, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, 0666 ); + + if ( hOut == -1 ) + { + fprintf( stderr, "Can't open outfile '%s'!\n", szOutfile ); + close( hIn ); + return -1; + } + + #define BUFLEN 0x10000 + + BYTE* pbtPtr = new BYTE [ BUFLEN ]; + lseek( hIn, g_iBlkStart, SEEK_SET ); + + if ( g_bOutputIsAtari ) + { + WORD wStart = iBlkStartM; + WORD wEnd = iBlkEndM; + + BYTE btPom = 0xFF; + write( hOut, &btPom, 1 ); + write( hOut, &btPom, 1 ); + + btPom = wStart & 0xFF; + write( hOut, &btPom, 1 ); + + btPom = wStart >> 8; + write( hOut, &btPom, 1 ); + + btPom = wEnd & 0xFF; + write( hOut, &btPom, 1 ); + + btPom = wEnd >> 8; + write( hOut, &btPom, 1 ); + } + + int iLeft = g_iBlkLength; + + while( iLeft ) + { + int iReadNow = iLeft > BUFLEN ? BUFLEN : iLeft; + read( hIn, pbtPtr, iReadNow ); + write( hOut, pbtPtr, iReadNow ); + iLeft -= iReadNow; + } + + close( hOut ); + close( hIn ); + + printf( "Done!\n" ); + + return 0; +} + +int ToNum( char* szString, int iOffs ) +{ + BOOL bSec = FALSE; + + if( *szString == 's' ) + { + bSec = TRUE; + szString++; + } + + int iNum; + sscanf( szString, "%X", &iNum ); + + if( bSec ) + { + if( iNum < iOffs ) + { + printf( "Incorrect sector number %s\n", szString ); + return -1; + } + + iNum -= iOffs; + iNum *= 0x80; + + if( iOffs ) + { + //begin & end + iNum += 0x10; + } + + //whole code assumes SD ATR file!!! + } + + return iNum; +} diff --git a/jindroush/aext/pub.def b/jindroush/aext/pub.def new file mode 100644 index 0000000..19e525e --- /dev/null +++ b/jindroush/aext/pub.def @@ -0,0 +1,31 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#define PRG_NAME "aext" +#define PRG_VERSION "1.02" +#define PRG_COPYRIGHT "1998-2002" +#define PRG_UNDERGPL "1" +#define PRG_AUTHOR "Jindrich Kubec " + +#define PRG_URL "http://www.asw.cz/~kubecj" + +#define PRG_DESC "Atari file extractor." +#define PRG_USAGE "[options] infile [outfile]" + +#define PRG_ARCH "PC" +#define PRG_TOOLS "PERL" + +#define PRG_SRCS "!GENERATED!" +#define PRG_BINS "rel/aext.exe" diff --git a/jindroush/aext/readme.txt b/jindroush/aext/readme.txt new file mode 100644 index 0000000..f73b129 --- /dev/null +++ b/jindroush/aext/readme.txt @@ -0,0 +1,76 @@ +AExt v1.02 (c) 1998-2002 Jindrich Kubec +Latest version can be found at http://www.asw.cz/~kubecj + +This program is provided 'as is', no warranty will be taken +for any damage caused by it or by any use of it. + +The whole package is placed under the GNU Public License, for further +information on redistribution see the included file "GPL.TXT". + + +Description: +------------ +Atari file extractor. +This is just simple utility for extracting binary block in binary/atari binary +block formats. + + +Usage: +------ +AExt [options] infile [outfile] + +If outfile is not specified, prg.axe is assumed. + +-s, -e, -n specify start, end or length parameters of block in hexadecimal + numbers. + +-oa creates atari binary block (start, end, data). + +-base is used with -oa to create based binary block. (The number specifies + start address of block). + + +History: +-------- +Date, Author, Version +8/19/1999, kubecj, 0.10 +First version. + +10/10/1999, kubecj, 0.11 +New archive processing, version incremented to avoid version problems. + +10/10/1999, kubecj, 1.00 +First release. + +12/10/2001, kubecj, 1.01 +Large block processing. +-e 0 means end ptr now. + +1/23/2002, kubecj, 1.02 +Added useful single density extracting parameters. Now include 's' as first +character in a number, e.g. -s s06 means start from sixth sector. By definition +works only on ATR files with 0x80 long sectors. + + +To Do: +------ +Nothing. + + +Known Bugs: +----------- +None. + + +Compiling Tools: +---------------- +For scripts: Perl. +URL: http://www.perl.com + +For PC executables: DJGPP. +Sources were written/tested on GCC/Intel only. There should be only +minor problems to port it to different architectures/environments. +Makefile should need only minor changes. +URL: http://www.delorie.com + + diff --git a/jindroush/aext/switches.def b/jindroush/aext/switches.def new file mode 100644 index 0000000..1bcb33b --- /dev/null +++ b/jindroush/aext/switches.def @@ -0,0 +1,25 @@ +e, end +end +hexnum= bRet = SWFN_GETPATH( szEnd );g_bEndUsed = TRUE; += + +s, start +start +hexnum=bRet = SWFN_GETPATH( szStart );g_bStartUsed = TRUE; += + +n, length +length +hexnum=bRet = SWFN_GETPATH( szLength );g_bLenUsed = TRUE; += + +oa, atari +output is Atari block +=g_bOutputIsAtari = TRUE; += + +base +base +hexnum=bRet = SWFN_NUMH( &g_iBlkBase ); +=g_bUseBase = TRUE; += diff --git a/jindroush/bas2boot/Makefile b/jindroush/bas2boot/Makefile new file mode 100644 index 0000000..9c3a3de --- /dev/null +++ b/jindroush/bas2boot/Makefile @@ -0,0 +1,59 @@ +#===================================================================== +PRGNAME = bas2boot + +all: $(PRGNAME) + +release: + @$(MAKE) $(PRGNAME) CFLAGS="-c -O2 -Wall -D__CDISK_SAVE__ -D__CDISK_NOLOAD__" LDFLAGS="" + @echo RELEASE: Compiled. + +rel_strip: + @strip $(PRGNAME).exe + +rel_inst: + @copy $(PRGNAME).exe $(ATAROOT)\\bin + @copy bas2boot.boo $(ATAROOT)\\bin + @echo RELEASE: Installed. + +debug: + @$(MAKE) $(PRGNAME) CFLAGS="-c -g -Wall -D_DEBUG -D__CDISK_SAVE__ -D__CDISK_NOLOAD__" LDFLAGS="-g" + @echo DEBUG: Compiled. + +clean: + rm -f *.o + rm -f $(PRGNAME) + rm -f $(PRGNAME).exe + rm -f switches.cpp + rm -rf rel + @echo DEBUG: Cleaned. + +#===================================================================== +INCLUDES = makefile \ + switches.def \ + pub.def + + +OBJECTS = bas2boot.o \ + +#===================================================================== +CC = g++ +LD = g++ +LDLIBS = -lm -L../lib -ljindroush +CPPFLAGS=-I../include -D__CDISK_SAVE__ $(COPT) +COPT=-O2 + +#===================================================================== + +$(PRGNAME): $(OBJECTS) bas2boot.boo + $(LD) $(LDFLAGS) $(OBJECTS) $(LDLIBS) -o $(PRGNAME) + +bas2boot.o: bas2boot.cpp switches.cpp + +%.o: %.cpp $(INCLUDES) + $(CC) $(CPPFLAGS) -c $< -o $@ + +switches.cpp: switches.def ../switches.pl + perl ../switches.pl $< $@ + +bas2boot.boo: bas2boot.asm + dasm $< -o$@ -f3 diff --git a/jindroush/bas2boot/bas2boot.asm b/jindroush/bas2boot/bas2boot.asm new file mode 100644 index 0000000..af7752a --- /dev/null +++ b/jindroush/bas2boot/bas2boot.asm @@ -0,0 +1,169 @@ +;Boot stub for loading BASIC programs from short ATR files. +;(c) 1998-1999 Jindrich Kubec + +; 20070524 bkw: modified to assemble with dasm + processor 6502 + +SIOV = $E459 + +DOSVEC = $0A +RAMTOP = $6A +LOMEM = $80 +BOOT = $09 +BASICF = $03F8 +PORTB = $D301 + +EOPEN = $EF94 + +BAS_CONT = $A97A +BAS_EXEC = $B755 + +LOADER_START = $0700 +LOADER_END = $0800 + +BASMEMSTART = $0700 + +BASPTRSLEN = $0E +BASPTRSSTART = LOADER_END - BASPTRSLEN + + org LOADER_START + +BOOTST: .byte 0 + .byte (ENDBOOT-BOOTST+127)/128 + .WORD *-2 + .WORD MAIN_BEG + + CLC +RTS_INSTR: RTS + + ;used for extractor +ORI_LEN: .WORD 0 + +MAIN_BEG: + LDX #
header + JSR $C642 + + LDX #padding + JSR $C642 + + ;copy pointers to correct area, add $700 + LDX #BASPTRSLEN - 1 +SETVECT: CLC + LDA BASPTRSSTART,X + ADC #>BASMEMSTART + STA LOMEM,X + DEX + LDA BASPTRSSTART,X + STA LOMEM,X + DEX + BPL SETVECT + + LDA #$31 ;D + STA $300 + LDA #$01 ;1 + STA $301 + LDA #$52 ;read + STA $302 + LDA #$80 ;$80 bytes + STA $308 + LDA #$00 + STA $309 + STA $30B + + LDA $82 ;buffer address + STA $304 + LDA $83 + STA $305 + + ;starting sector + LDA # ( (ENDBOOT-BOOTST+127)/128 ) +1 + STA $30A +SIO_CONT: + LDA #$40 ;read + STA $303 + + JSR SIOV + LDA $303 + CMP #$01 + BEQ NOERR + JSR $C63E +AGAIN: JMP AGAIN ;dynamic halt + + ;move buffer pointer +NOERR: + + ;LDA $304 + ;CLC + ;ADC $308 + ;STA $304 + ;LDA $305 + ;ADC $309 + ;STA $305 + + ;this does the same as the above, but is shorter + CLC + LDX #$FE +LP0: LDA $304 - $FE,X + ADC $308 - $FE,X + STA $304 - $FE,X + INX + BNE LP0 + + ;increment sector number + INC $30A + BNE NX1 + INC $30B +NX1: + ;decrement number of sectors to load + LDA SECTORS + BNE NX2 + DEC SECTORS+1 + BMI BAS_RUN +NX2: DEC SECTORS + JMP SIO_CONT + +BAS_RUN: LDX #$FF + TXS + + LDA #$0A + STA $C9 + LDA #$00 + STA BOOT + STA BASICF + + ;turn on basic + LDA #$FD + STA PORTB + + ;set stack + LDA #>BAS_CONT + PHA + LDA #BAS_EXEC + PHA + LDA #= 3 ) + { + strcpy( szOutFile, argv[ 2 ] ); + } + else + { + GuessBestFnameFromPC( szOutFile, szInFile, GetDiskTypeExt( g_dtypeOut ) ); + } + + ADisk* pDisk = NULL; + switch( g_dtypeOut ) + { + case DISK_ATR: + pDisk = new CAtr(); + break; + + case DISK_XFD: + pDisk = new CXfd(); + break; + + case DISK_SCP: + pDisk = new CScp(); + break; + + case DISK_DCM: + pDisk = new CDcm(); + break; + + case DISK_DI: + pDisk = new CDi(); + break; + + default: + break; + } + + if ( !pDisk ) + { + printf( "Can't create such image!\n" ); + return FALSE; + } + + //reads boot stub + char szBootName[ MAX_STRING ]; + strcpy( szBootName, argv[ 0 ] ); + char* szWhere = strrchr( szBootName, '/' ); + + if ( szWhere ) + szWhere++; + else + szWhere = szBootName; + + strcpy( szWhere, "bas2boot.boo" ); + + CFile cf; + + if ( !cf.Open( szBootName ) ) + { + printf( "Can't open boot image: %s\n", szBootName ); + return 1; + } + + long lBootLen = cf.GetLength(); + + if ( lBootLen % 0x80 ) + { + printf( "Invalid boot image: %s\n", szBootName ); + cf.Close(); + return 1; + } + + BYTE* pbtBoot = new BYTE [ lBootLen ]; + + cf.Read( pbtBoot, lBootLen ); + + cf.Close(); + + int iBootSectors = lBootLen / 0x80; + + if ( pbtBoot[ 1 ] != iBootSectors ) + { + printf( "Invalid boot image: %s\nSize mismatch.\n", szBootName ); + cf.Close(); + delete [] pbtBoot; + return 1; + } + + //open basic file + if ( !cf.Open( szInFile ) ) + { + printf( "Can't open source file '%s'!\n", szInFile ); + return 1; + } + + long lBasicLen = cf.GetLength(); + + //set real length in header + pbtBoot[ 8 ] = lBasicLen & 0xFF; + pbtBoot[ 9 ] = lBasicLen >> 8; + + lBasicLen -= BAS_HEAD_SIZE; + + int iBasicSectors = ( lBasicLen + 0x7F ) / 0x80; + + //load and relocate basic header + BASHEAD head; + head.w1 = cf.readLEw(); + head.w2 = cf.readLEw() - head.w1; + head.w3 = cf.readLEw() - head.w1; + head.w4 = cf.readLEw() - head.w1; + head.w5 = cf.readLEw() - head.w1; + head.w6 = cf.readLEw() - head.w1; + head.w7 = cf.readLEw() - head.w1; + + BYTE* pbtHd = pbtBoot + lBootLen - BAS_HEAD_SIZE - 2; + + *( pbtHd++ ) = ( iBasicSectors - 1 ) & 0xFF; + *( pbtHd++ ) = ( iBasicSectors - 1 ) >>8; + + *( pbtHd++ ) = head.w1 & 0xFF; + *( pbtHd++ ) = head.w1 >> 8; + + *( pbtHd++ ) = head.w2 & 0xFF; + *( pbtHd++ ) = head.w2 >> 8; + + *( pbtHd++ ) = head.w3 & 0xFF; + *( pbtHd++ ) = head.w3 >> 8; + + *( pbtHd++ ) = head.w4 & 0xFF; + *( pbtHd++ ) = head.w4 >> 8; + + *( pbtHd++ ) = head.w5 & 0xFF; + *( pbtHd++ ) = head.w5 >> 8; + + *( pbtHd++ ) = head.w6 & 0xFF; + *( pbtHd++ ) = head.w6 >> 8; + + *( pbtHd++ ) = head.w7 & 0xFF; + *( pbtHd++ ) = head.w7 >> 8; + + //find empty space at the end of boot + BYTE* pbtString = pbtBoot + lBootLen - BAS_HEAD_SIZE - 2 - 2; + BYTE* pbtStringEnd = pbtString; + + while( *pbtString == 0x20 ) + pbtString--; + + pbtString++; + + int iStringLen = pbtStringEnd - pbtString; + + //put the message there + memcpy( pbtString, szMessage, iStringLen + 1 ); + + //read basic program + BYTE* pbtBas = new BYTE [ iBasicSectors * 0x80 ]; + memset( pbtBas, 0, iBasicSectors * 0x80 ); + + cf.Read( pbtBas, lBasicLen ); + + cf.Close(); + + //format disk + DISK_GEOMETRY dg; + + if ( g_bClassic ) + ForceClassicSize( iBasicSectors + iBootSectors, 0x80, &dg ); + else + GuessClassicSizes( iBasicSectors + iBootSectors, 0x80, &dg ); + + if ( !pDisk->Format( &dg ) ) + { + delete pDisk; + delete[] pbtBoot; + delete [] pbtBas; + return 1; + } + + //write boot & body + pDisk->WriteSectors( 1, pbtBoot, iBootSectors ); + pDisk->WriteSectors( 1 + iBootSectors, pbtBas, iBasicSectors ); + + //save it to disk + if ( !pDisk->Save( szOutFile, FALSE ) ) + { + printf( "Error! %s\n", pDisk->GetLastError() ); + delete pDisk; + delete [] pbtBoot; + delete [] pbtBas; + return 1; + } + + delete pDisk; + + delete [] pbtBoot; + delete [] pbtBas; + + printf( "Written to %s (%s)\n", szOutFile, GetDiskTypeName( g_dtypeOut ) ); + + return 0; +} + diff --git a/jindroush/bas2boot/pub.def b/jindroush/bas2boot/pub.def new file mode 100644 index 0000000..0993bbd --- /dev/null +++ b/jindroush/bas2boot/pub.def @@ -0,0 +1,31 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#define PRG_NAME "bas2boot" +#define PRG_VERSION "1.02" +#define PRG_COPYRIGHT "1998-2001" +#define PRG_UNDERGPL "1" +#define PRG_AUTHOR "Jindrich Kubec " + +#define PRG_URL "http://www.asw.cz/~kubecj" + +#define PRG_DESC "Converts Basic files to disk images." +#define PRG_USAGE "[options] basicfile [diskfile]" + +#define PRG_ARCH "PC ATARI" +#define PRG_TOOLS "PERL" + +#define PRG_SRCS "!GENERATED!" +#define PRG_BINS "rel/bas2boot.exe rel/bas2boot.boo" diff --git a/jindroush/bas2boot/readme.txt b/jindroush/bas2boot/readme.txt new file mode 100644 index 0000000..010d3fc --- /dev/null +++ b/jindroush/bas2boot/readme.txt @@ -0,0 +1,72 @@ +Bas2Boot v1.02 (c) 1998-2001 Jindrich Kubec +Latest version can be found at http://www.asw.cz/~kubecj + +This program is provided 'as is', no warranty will be taken +for any damage caused by it or by any use of it. + +The whole package is placed under the GNU Public License, for further +information on redistribution see the included file "GPL.TXT". + + +Description: +------------ +Converts Basic files to disk images. + + + +Usage: +------ +Bas2Boot [options] basicfile [diskfile] + +basicfile is source basic filename. + +diskfile is output filename. If not specified it's guessed from input filename. + +-atr -xfd -scp -dcm -di specify output file format. Default is ATR. + +-long forces to use 'classic' disk sizes (SD,DD,ED) + +-message text -sets message displayed while loading program + + +History: +-------- +Date, Author, Version +4/5/1999, kubecj, 0.92 +First version + +6/14/1999, kubecj, 1.00 +First public version + +10/10/1999, kubecj, 1.01 +Only version number increment because of different archive processing. + +2/26/2001, kubecj, 1.02 +Added DI file format. + + +To Do: +------ +Nothing. + + +Known Bugs: +----------- +None. + + +Compiling Tools: +---------------- +For scripts: Perl. +URL: http://www.perl.com + +For PC executables: DJGPP. +Sources were written/tested on GCC/Intel only. There should be only +minor problems to port it to different architectures/environments. +Makefile should need only minor changes. +URL: http://www.delorie.com + +For Atari assembler sources: XA65 assembler. +URL: http://stockholm.ptloma.edu/cbm/xa/. + + diff --git a/jindroush/bas2boot/switches.def b/jindroush/bas2boot/switches.def new file mode 100644 index 0000000..417e1d4 --- /dev/null +++ b/jindroush/bas2boot/switches.def @@ -0,0 +1,32 @@ +atr, a +output is ATR +=g_dtypeOut = DISK_ATR; += + +xfd, x +output is XFD +=g_dtypeOut = DISK_XFD; += + +scp, s +output is SCP +=g_dtypeOut = DISK_SCP; +=g_bClassic = TRUE; += + +dcm, d +output is DCM +=g_dtypeOut = DISK_DCM; +=g_bClassic = TRUE; += + +long, classic +output has 'classic' size +=g_bClassic = TRUE; += + +message, mess, text +message to display while loading +text=SWFN_GETPATH( g_szMessage ); += + diff --git a/jindroush/chkbas/Makefile b/jindroush/chkbas/Makefile new file mode 100644 index 0000000..18b1d75 --- /dev/null +++ b/jindroush/chkbas/Makefile @@ -0,0 +1,61 @@ +#===================================================================== +PRGNAME = chkbas + +all: $(PRGNAME) + +release: + @$(MAKE) $(PRGNAME) CFLAGS="-c -O2 -Wall" LDFLAGS="" + @echo RELEASE: Compiled. + +rel_strip: + @strip $(PRGNAME).exe + +rel_inst: + @copy $(PRGNAME).exe $(ATAROOT)\\bin + @echo RELEASE: Installed. + +debug: + @$(MAKE) $(PRGNAME) CFLAGS="-c -g -Wall -D_DEBUG" LDFLAGS="-g" + @echo DEBUG: Compiled. + +clean: + rm -f *.o + rm -f $(PRGNAME) + rm -f $(PRGNAME).exe + rm -f switches.cpp + rm -rf rel + @echo DEBUG: Cleaned. + +#===================================================================== +INCLUDES = makefile \ + basic.h \ + basic_tb.h \ + basic_xl.h \ + basic_xe.h \ + carray.h \ + wintypes.h + + +OBJECTS = chkbas.o \ + carray.o \ + strlwr.o + +#===================================================================== +CC = g++ +LD = g++ +LDLIBS = -lm -L../lib -ljindroush +CPPFLAGS=-I../include $(COPT) +COPT=-O2 + +#===================================================================== + +$(PRGNAME) : $(OBJECTS) + $(LD) $(LDFLAGS) $(OBJECTS) $(LDLIBS) -o $(PRGNAME) + +chkbas.o: chkbas.cpp switches.cpp + +%.o:%.cpp $(INCLUDES) switches.cpp + $(CC) $(CPPFLAGS) $(CFLAGS) $< -o $@ + +switches.cpp : switches.def ../switches.pl + @perl ../switches.pl $< $@ diff --git a/jindroush/chkbas/basic.h b/jindroush/chkbas/basic.h new file mode 100644 index 0000000..6fe96fc --- /dev/null +++ b/jindroush/chkbas/basic.h @@ -0,0 +1,152 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +char* aCmdsBasic[] = +{ + "REM", //00 + "DATA", //01 + "INPUT", //02 + "COLOR", //03 + "LIST", //04 + "ENTER", //05 + "LET", //06 + "IF", //07 + "FOR", //08 + "NEXT", //09 + "GOTO", //0a + "GO TO", //0b + "GOSUB", //0c + "TRAP", //0d + "BYE", //0e + "CONT", //0f + "COM", //10 + "CLOSE", //11 + "CLR", //12 + "DEG", //13 + "DIM", //14 + "END", //15 + "NEW", //16 + "OPEN", //17 + "LOAD", //18 + "SAVE", //19 + "STATUS", //1a + "NOTE", //1b + "POINT", //1c + "XIO", //1d + "ON", //1e + "POKE", //1f + "PRINT", //20 + "RAD", //21 + "READ", //22 + "RESTORE", //23 + "RETURN", //24 + "RUN", //25 + "STOP", //26 + "POP", //27 + "?", //28 + "GET", //29 + "PUT", //2a + "GRAPHICS", //2b + "PLOT", //2c + "POSITION", //2d + "DOS", //2e + "DRAWTO", //2f + "SETCOLOR", //30 + "LOCATE", //31 + "SOUND", //32 + "LPRINT", //33 + "CSAVE", //34 + "CLOAD", //35 + "", //36 silent let + "ERROR -", //37 last Atari Basic command +}; + +char* aOpsBasic[] = { + "NCONST", //0E + "SCONST", //0F + "NOUSE", //10 + "NOUSE", //11 + ",", //12 + "$", //13 + ":", //14 + ";", //15 + "EOL", //16 + " GOTO ", //17 + " GOSUB ", //18 + " TO ", //19 + " STEP ", //1A + " THEN ", //1B + "#", //1C + "<=", //1D + "<>", //1E + ">=", //1F + "<", //20 + ">", //21 + "=", //22 + "^", //23 + "*", //24 + "+", //25 + "-", //26 + "/", //27 + " NOT ", //28 + " OR ", //29 + " AND ", //2A + "(", //2B + ")", //2C + "=", //2D + "=", //2E + "<=", //2F + "<>", //30 + ">=", //31 + "<", //32 + ">", //33 + "=", //34 + "+", //35 + "-", //36 + "(", //37 + "(", //38 + "(", //39 + "(", //3A + "(", //3B + ",", //3C + "STR$", //3D + "CHR$", //3E + "USR", //3F + "ASC", //40 + "VAL", //41 + "LEN", //42 + "ADR", //43 + "ATN", //44 + "COS", //45 + "PEEK", //46 + "SIN", //47 + "RND", //48 + "FRE", //49 + "EXP", //4A + "LOG", //4B + "CLOG", //4C + "SQR", //4D + "SGN", //4E + "ABS", //4F + "INT", //50 + "PADDLE", //51 + "STICK", //52 + "PTRIG", //53 + "STRIG", //54 last Atari Basic +}; + +#define BASIC_CMD_NUM ( sizeof( aCmdsBasic ) / sizeof( aCmdsBasic[ 0 ] ) ) +#define BASIC_OPS_NUM ( sizeof( aOpsBasic ) / sizeof( aOpsBasic[ 0 ] ) ) + diff --git a/jindroush/chkbas/basic_tb.h b/jindroush/chkbas/basic_tb.h new file mode 100644 index 0000000..8547948 --- /dev/null +++ b/jindroush/chkbas/basic_tb.h @@ -0,0 +1,223 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +char* aCmdsTBasic[] = +{ + "REM", //00 + "DATA", //01 + "INPUT", //02 + "COLOR", //03 + "LIST", //04 + "ENTER", //05 + "LET", //06 + "IF", //07 + "FOR", //08 + "NEXT", //09 + "GOTO", //0a + "GO TO", //0b + "GOSUB", //0c + "TRAP", //0d + "BYE", //0e + "CONT", //0f + "COM", //10 + "CLOSE", //11 + "CLR", //12 + "DEG", //13 + "DIM", //14 + "END", //15 + "NEW", //16 + "OPEN", //17 + "LOAD", //18 + "SAVE", //19 + "STATUS", //1a + "NOTE", //1b + "POINT", //1c + "XIO", //1d + "ON", //1e + "POKE", //1f + "PRINT", //20 + "RAD", //21 + "READ", //22 + "RESTORE", //23 + "RETURN", //24 + "RUN", //25 + "STOP", //26 + "POP", //27 + "?", //28 + "GET", //29 + "PUT", //2a + "GRAPHICS", //2b + "PLOT", //2c + "POSITION", //2d + "DOS", //2e + "DRAWTO", //2f + "SETCOLOR", //30 + "LOCATE", //31 + "SOUND", //32 + "LPRINT", //33 + "CSAVE", //34 + "CLOAD", //35 + "", //36 silent let + "ERROR -", //37 last Atari Basic command + "DPOKE", //38 + "MOVE", //39 + "-MOVE", //3A + "*F", //3B + "REPEAT", //3C + "UNTIL", //3D + "WHILE", //3E + "WEND", //3F + "ELSE", //40 + "ENDIF", //41 + "BPUT", //42 + "BGET", //43 + "FILLTO", //44 + "DO", //45 + "LOOP", //46 + "EXIT", //47 + "DIR", //48 + "LOCK", //49 + "UNLOCK", //4A + "RENAME", //4B + "DELETE", //4C + "PAUSE", //4D + "TIME$=", //4E + "PROC", //4F + "EXEC", //50 + "ENDPROC", //51 + "FCOLOR", //52 + "*L", //53 + "------------------------------", //54 + "RENUM", //55 + "DEL", //56 + "DUMP", //57 + "TRACE", //58 + "TEXT", //59 + "BLOAD", //5A + "BRUN", //5B + "GO#", //5C + "#", //5D + "*B", //5E + "PAINT", //5F + "CLS", //60 + "DSOUND", //61 + "CIRCLE", //62 + "\%PUT", //63 + "\%GET", //64 +}; + +char* aOpsTBasic[] = { + "NHCONST", //0D + "NCONST", //0E + "SCONST", //0F + "NOUSE", //10 + "NOUSE", //11 + ",", //12 + "$", //13 + ":", //14 + ";", //15 + "EOL", //16 + " GOTO ", //17 + " GOSUB ", //18 + " TO ", //19 + " STEP ", //1A + " THEN ", //1B + "#", //1C + "<=", //1D + "<>", //1E + ">=", //1F + "<", //20 + ">", //21 + "=", //22 + "^", //23 + "*", //24 + "+", //25 + "-", //26 + "/", //27 + " NOT ", //28 + " OR ", //29 + " AND ", //2A + "(", //2B + ")", //2C + "=", //2D + "=", //2E + "<=", //2F + "<>", //30 + ">=", //31 + "<", //32 + ">", //33 + "=", //34 + "+", //35 + "-", //36 + "(", //37 + "(", //38 + "(", //39 + "(", //3A + "(", //3B + ",", //3C + "STR$", //3D + "CHR$", //3E + "USR", //3F + "ASC", //40 + "VAL", //41 + "LEN", //42 + "ADR", //43 + "ATN", //44 + "COS", //45 + "PEEK", //46 + "SIN", //47 + "RND", //48 + "FRE", //49 + "EXP", //4A + "LOG", //4B + "CLOG", //4C + "SQR", //4D + "SGN", //4E + "ABS", //4F + "INT", //50 + "PADDLE", //51 + "STICK", //52 + "PTRIG", //53 + "STRIG", //54 last Atari Basic + "DPEEK", //55 + "&", //56 + "!", //57 + "INSTR", //58 + "INKEY$", //59 + " EXOR ", //5A + "HEX$", //5B + "DEC", //5C + " DIV ", //5D + "FRAC", //5E + "TIME$", //5F + "TIME", //60 + " MOD ", //61 + " EXEC ", //62 + "RND", //63 + "RAND", //64 + "TRUNC", //65 + "%0", //66 + "%1", //67 + "%2", //68 + "%3", //69 + " GO# ", //6A + "UINSTR", //6B + "ERR", //6C + "ERL", //6D +}; + +#define TBASIC_CMD_NUM ( sizeof( aCmdsTBasic ) / sizeof( aCmdsTBasic[ 0 ] ) ) +#define TBASIC_OPS_NUM ( sizeof( aOpsTBasic ) / sizeof( aOpsTBasic[ 0 ] ) ) + diff --git a/jindroush/chkbas/basic_xe.h b/jindroush/chkbas/basic_xe.h new file mode 100644 index 0000000..fc86131 --- /dev/null +++ b/jindroush/chkbas/basic_xe.h @@ -0,0 +1,219 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +char* aCmdsBasicXe[] = +{ + "REM", //00 + "DATA", //01 + "INPUT", //02 + "COLOR", //03 + "LIST", //04 + "ENTER", //05 + "LET", //06 + "IF", //07 + "FOR", //08 + "NEXT", //09 + "GOTO", //0a + "GO TO", //0b + "GOSUB", //0c + "TRAP", //0d + "BYE", //0e + "CONT", //0f + "COM", //10 + "CLOSE", //11 + "CLR", //12 + "DEG", //13 + "DIM", //14 + "END", //15 + "NEW", //16 + "OPEN", //17 + "LOAD", //18 + "SAVE", //19 + "STATUS", //1a + "NOTE", //1b + "POINT", //1c + "XIO", //1d + "ON", //1e + "POKE", //1f + "PRINT", //20 + "RAD", //21 + "READ", //22 + "RESTORE", //23 + "RETURN", //24 + "RUN", //25 + "STOP", //26 + "POP", //27 + "?", //28 + "GET", //29 + "PUT", //2a + "GRAPHICS", //2b + "PLOT", //2c + "POSITION", //2d + "DOS", //2e + "DRAWTO", //2f + "SETCOLOR", //30 + "LOCATE", //31 + "SOUND", //32 + "LPRINT", //33 + "CSAVE", //34 + "CLOAD", //35 + "", //36 silent let + "ERROR -", //37 last Atari Basic command + + "WHILE", //38 + "ENDWHILE", //39 + "TRACEOFF", //3A + "TRACE", //3B + "ELSE", //3C + "ENDIF", //3D + "DPOKE", //3E + "LOMEM", //3F + "DEL", //40 + "RPUT", //41 + "RGET", //42 + "BPUT", //43 + "BGET", //44 + "TAB", //45 + "CP", //46 + "ERASE", //47 + "PROTECT", //48 + "UNPROTECT", //49 + "DIR", //4A + "RENAME", //4B + "MOVE", //4C + "MISSILE", //4D + "PMCLR", //4E + "PMCOLOR", //4F + "PMGRAPHICS", //50 + "PMMOVE", //51 + "PMWIDTH", //52 + "SET", //53 + "LVAR", //54 + "RENUM", //55 + "FAST", //56 + "LOCAL", //57 + "EXTEND", //58 + "PROCEDURE", //59 + "?5A?", //5A + "CALL", //5B + "SORTUP", //5C + "SORTDOWN", //5D + "EXIT", //5E + "NUM", //5F + "HITCLR", //60 + "INVERSE", //61 + "NORMAL", //62 + "BLOAD", //63 + "BSAVE", //64 +}; + +char* aOpsBasicXe[] = { + "NHCONST", //0D + "NCONST", //0E + "SCONST", //0F + "NOUSE", //10 + "NOUSE", //11 + ",", //12 + "$", //13 + ":", //14 + ";", //15 + "EOL", //16 + " GOTO ", //17 + " GOSUB ", //18 + " TO ", //19 + " STEP ", //1A + " THEN ", //1B + "#", //1C + "<=", //1D + "<>", //1E + ">=", //1F + "<", //20 + ">", //21 + "=", //22 + "^", //23 + "*", //24 + "+", //25 + "-", //26 + "/", //27 + " NOT ", //28 + " OR ", //29 + " AND ", //2A + "(", //2B + ")", //2C + "=", //2D + "=", //2E + "<=", //2F + "<>", //30 + ">=", //31 + "<", //32 + ">", //33 + "=", //34 + "+", //35 + "-", //36 + "(", //37 + "(", //38 + "(", //39 + "(", //3A + "(", //3B + ",", //3C + "STR$", //3D + "CHR$", //3E + "USR", //3F + "ASC", //40 + "VAL", //41 + "LEN", //42 + "ADR", //43 + "ATN", //44 + "COS", //45 + "PEEK", //46 + "SIN", //47 + "RND", //48 + "FRE", //49 + "EXP", //4A + "LOG", //4B + "CLOG", //4C + "SQR", //4D + "SGN", //4E + "ABS", //4F + "INT", //50 + "PADDLE", //51 + "STICK", //52 + "PTRIG", //53 + "STRIG", //54 last Atari Basic + " USING ", //55 + "%", //56 + "!", //57 + "&", //58 + ";", //59 + "BUMP(", //5A + "FIND(", //5B + "HEX$", //5C + "RANDOM(", //5D + "DPEEK", //5E + "SYS", //5F + "VSTICK", //60 + "HSTICK", //61 + "PMADR", //62 + "ERR", //63 + "TAB", //64 + "PEN", //65 + "LEFT$", //66 + "RIGHT$", //67 + "MID$", //68 +}; + +#define BASICXE_CMD_NUM ( sizeof( aCmdsBasicXe ) / sizeof( aCmdsBasicXe[ 0 ] ) ) +#define BASICXE_OPS_NUM ( sizeof( aOpsBasicXe ) / sizeof( aOpsBasicXe[ 0 ] ) ) + diff --git a/jindroush/chkbas/basic_xl.h b/jindroush/chkbas/basic_xl.h new file mode 100644 index 0000000..a97f8a7 --- /dev/null +++ b/jindroush/chkbas/basic_xl.h @@ -0,0 +1,213 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#define BXL_EXTEND 0x5A + +char* aCmdsBasicXl[] = +{ + "REM", //00 + "DATA", //01 + "INPUT", //02 + "COLOR", //03 + "LIST", //04 + "ENTER", //05 + "LET", //06 + "IF", //07 + "FOR", //08 + "NEXT", //09 + "GOTO", //0a + "GO TO", //0b + "GOSUB", //0c + "TRAP", //0d + "BYE", //0e + "CONT", //0f + "COM", //10 + "CLOSE", //11 + "CLR", //12 + "DEG", //13 + "DIM", //14 + "END", //15 + "NEW", //16 + "OPEN", //17 + "LOAD", //18 + "SAVE", //19 + "STATUS", //1a + "NOTE", //1b + "POINT", //1c + "XIO", //1d + "ON", //1e + "POKE", //1f + "PRINT", //20 + "RAD", //21 + "READ", //22 + "RESTORE", //23 + "RETURN", //24 + "RUN", //25 + "STOP", //26 + "POP", //27 + "?", //28 + "GET", //29 + "PUT", //2a + "GRAPHICS", //2b + "PLOT", //2c + "POSITION", //2d + "DOS", //2e + "DRAWTO", //2f + "SETCOLOR", //30 + "LOCATE", //31 + "SOUND", //32 + "LPRINT", //33 + "CSAVE", //34 + "CLOAD", //35 + "", //36 silent let + "ERROR -", //37 last Atari Basic command + + "WHILE", //38 + "ENDWHILE", //39 + "TRACEOFF", //3A + "TRACE", //3B + "ELSE", //3C + "ENDIF", //3D + "DPOKE", //3E + "LOMEM", //3F + "DEL", //40 + "RPUT", //41 + "RGET", //42 + "BPUT", //43 + "BGET", //44 + "TAB", //45 + "CP", //46 + "ERASE", //47 + "PROTECT", //48 + "UNPROTECT", //49 + "DIR", //4A + "RENAME", //4B + "MOVE", //4C + "MISSILE", //4D + "PMCLR", //4E + "PMCOLOR", //4F + "PMGRAPHICS", //50 + "PMMOVE", //51 + "PMWIDTH", //52 + "SET", //53 + "LVAR", //54 + "RENUM", //55 + "FAST", //56 + "NUM", //57 + "END", //58 + + "?59?", //59 + "BXL_EXTEND", //5A + +}; + +char* aOpsBasicXl[] = { + "NHCONST", //0D + "NCONST", //0E + "SCONST", //0F + "NOUSE", //10 + "NOUSE", //11 + ",", //12 + "$", //13 + ":", //14 + ";", //15 + "EOL", //16 + " GOTO ", //17 + " GOSUB ", //18 + " TO ", //19 + " STEP ", //1A + " THEN ", //1B + "#", //1C + "<=", //1D + "<>", //1E + ">=", //1F + "<", //20 + ">", //21 + "=", //22 + "^", //23 + "*", //24 + "+", //25 + "-", //26 + "/", //27 + " NOT ", //28 + " OR ", //29 + " AND ", //2A + "(", //2B + ")", //2C + "=", //2D + "=", //2E + "<=", //2F + "<>", //30 + ">=", //31 + "<", //32 + ">", //33 + "=", //34 + "+", //35 + "-", //36 + "(", //37 + "(", //38 + "(", //39 + "(", //3A + "(", //3B + ",", //3C + "STR$", //3D + "CHR$", //3E + "USR", //3F + "ASC", //40 + "VAL", //41 + "LEN", //42 + "ADR", //43 + "ATN", //44 + "COS", //45 + "PEEK", //46 + "SIN", //47 + "RND", //48 + "FRE", //49 + "EXP", //4A + "LOG", //4B + "CLOG", //4C + "SQR", //4D + "SGN", //4E + "ABS", //4F + "INT", //50 + "PADDLE", //51 + "STICK", //52 + "PTRIG", //53 + "STRIG", //54 last Atari Basic + " USING ", //55 + "%", //56 + "!", //57 + "&", //58 + ";", //59 + "BUMP(", //5A + "FIND(", //5B + "HEX$", //5C + "RANDOM(", //5D + "DPEEK", //5E + "SYS", //5F + "VSTICK", //60 + "HSTICK", //61 + "PMADR", //62 + "ERR", //63 + "TAB", //64 + "PEN", //65 + "LEFT$", //66 + "RIGHT$", //67 + "MID$", //68 +}; + +#define BASICXL_CMD_NUM ( sizeof( aCmdsBasicXl ) / sizeof( aCmdsBasicXl[ 0 ] ) ) +#define BASICXL_OPS_NUM ( sizeof( aOpsBasicXl ) / sizeof( aOpsBasicXl[ 0 ] ) ) + diff --git a/jindroush/chkbas/carray.cpp b/jindroush/chkbas/carray.cpp new file mode 100644 index 0000000..212b0f3 --- /dev/null +++ b/jindroush/chkbas/carray.cpp @@ -0,0 +1,158 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "carray.h" + +//constructs new object - 0 size +CArray::CArray() +{ + m_iAllocatedBlocks = 0; + m_iArrayItems = 0; + m_pFirstBlock = NULL; +} + +//destructor calls destroy +CArray::~CArray() +{ + Destroy(); +} + +//destructs all sub array blocks +void CArray::Destroy() +{ + if ( m_iAllocatedBlocks ) + { + SubArray* pCurr = m_pFirstBlock; + SubArray* pNext; + + while ( pCurr ) + { + pNext = pCurr->pNext; + delete pCurr; + pCurr = pNext; + } + } + + m_iAllocatedBlocks = 0; + m_iArrayItems = 0; + m_pFirstBlock = NULL; +} + +//deletes last item +BOOL CArray::DeleteLast() +{ + m_iArrayItems--; + return TRUE; +} + +//gets value from array +void* CArray::GetAt( int iItem ) +{ + if ( ( iItem + 1 ) > m_iArrayItems ) + return NULL; + + int iBlockNeeded = iItem / CARRAY_SUB_SIZE; + + int iBlockCurr = 0; + + SubArray* pCurr = m_pFirstBlock; + + while( iBlockCurr < iBlockNeeded ) + { + pCurr = pCurr->pNext; + iBlockCurr++; + + if ( !pCurr ) + return NULL; + } + + return pCurr->array[ iItem % CARRAY_SUB_SIZE ]; +} + +//sets array's value - must exist before +BOOL CArray::SetAt( int iItem, void* pPtr ) +{ + if ( ( iItem + 1 ) > m_iArrayItems ) + return FALSE; + + int iBlockNeeded = iItem / CARRAY_SUB_SIZE; + + int iBlockCurr = 0; + + SubArray* pCurr = m_pFirstBlock; + + while( iBlockCurr < iBlockNeeded ) + { + pCurr = pCurr->pNext; + iBlockCurr++; + if ( !pCurr ) + return FALSE; + } + + pCurr->array[ iItem % CARRAY_SUB_SIZE ] = pPtr; + return TRUE; +} + +//adds array's value +BOOL CArray::Add( void* pPtr ) +{ + if ( ((( m_iArrayItems ) / CARRAY_SUB_SIZE ) + 1 ) > m_iAllocatedBlocks ) + { + //if we need new block, we try to add them + if ( !AddNewBlock() ) + return FALSE; + } + + m_iArrayItems++; + + if ( !SetAt( m_iArrayItems - 1, pPtr ) ) + { + m_iArrayItems--; + return FALSE; + } + + return TRUE; + +} + +//adds new sub array block +BOOL CArray::AddNewBlock() +{ + SubArray* pCurr = m_pFirstBlock; + SubArray* pNext = m_pFirstBlock; + + //find end + while ( pNext ) + { + pCurr = pNext; + pNext = pCurr->pNext; + } + + if ( !( pNext = new SubArray ) ) + return FALSE; + + memset( pNext, 0, sizeof( SubArray) ); + + if ( !m_pFirstBlock ) + m_pFirstBlock = pNext; + else + pCurr->pNext = pNext; + + m_iAllocatedBlocks++; + + return TRUE; +} + + diff --git a/jindroush/chkbas/carray.h b/jindroush/chkbas/carray.h new file mode 100644 index 0000000..9779cad --- /dev/null +++ b/jindroush/chkbas/carray.h @@ -0,0 +1,49 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "jintypes.h" + +#ifndef __CARRAY_H__ +#define __CARRAY_H__ + +#define CARRAY_SUB_SIZE 16 + +typedef struct sa +{ + struct sa* pPrev; + struct sa* pNext; + void* array[ CARRAY_SUB_SIZE ]; + +} SubArray; + +class CArray +{ +public: + CArray(); + ~CArray(); + void* GetAt( int ); + BOOL SetAt( int, void* ); + int GetSize() { return m_iArrayItems; }; + BOOL Add( void* ); + BOOL DeleteLast(); + void Destroy(); +private: + BOOL AddNewBlock(); + int m_iAllocatedBlocks; + int m_iArrayItems; + SubArray * m_pFirstBlock; +}; + +#endif diff --git a/jindroush/chkbas/chkbas.cpp b/jindroush/chkbas/chkbas.cpp new file mode 100644 index 0000000..a1ad505 --- /dev/null +++ b/jindroush/chkbas/chkbas.cpp @@ -0,0 +1,1009 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "jintypes.h" +#include +#include +#include +#include +#include "carray.h" +#include "cfile.h" + +#include "pub.def" + +#include "basic.h" +#include "basic_tb.h" +#include "basic_xl.h" +#include "basic_xe.h" + +extern void strlwr(char *); + +typedef enum +{ + BASIC = 0, //standard basic + BASIC_TB = 1, //Turbo Basic + BASIC_XL = 2, //OSS Basic XL + BASIC_XE = 3, //OSS Basic XE + BASIC_XEX = 4 //OSS Basic XE in extended mode +} BASIC_TYPE; + +typedef struct +{ + char** ppCommands; //array of commands + char** ppOperands; //array of operands + + int iCmdNum; //number of commands + int iOpNum; //number of operands + int iOpFirst; //first operand +} LANGDESC; + +LANGDESC langtbl[] = +{ + { aCmdsBasic, aOpsBasic, BASIC_CMD_NUM, BASIC_OPS_NUM, 0x0E }, + { aCmdsTBasic, aOpsTBasic, TBASIC_CMD_NUM, TBASIC_OPS_NUM, 0x0D }, + { aCmdsBasicXl, aOpsBasicXl, BASICXL_CMD_NUM, BASICXL_OPS_NUM, 0x0D }, + { aCmdsBasicXe, aOpsBasicXe, BASICXE_CMD_NUM, BASICXE_OPS_NUM, 0x0D }, + { aCmdsBasicXe, aOpsBasicXe, BASICXE_CMD_NUM, BASICXE_OPS_NUM, 0x0D }, +}; + +#define OP_NHCONST 0x0D +#define OP_NCONST 0x0E +#define OP_SCONST 0x0F +#define OP_EOL 0x16 + +#define VART_SCALAR 0x00 + +#define VART_ARRAYU 0x40 +#define VART_ARRAY 0x41 + +#define VART_STRINGU 0x80 +#define VART_STRING 0x81 + +#define VART_STRINGAU 0x90 +#define VART_STRINGA 0x91 + +#define VART_PROC 0xC1 +#define VART_LABEL 0xC2 + +#define SHEADER PRG_NAME " v" PRG_VERSION " (c) " PRG_COPYRIGHT " " PRG_AUTHOR "\n" + +#define HEADER SHEADER \ + PRG_DESC "\n" \ + " Latest version can be found at " PRG_URL "\n" \ + " Published under GPL. See GPL.TXT.\n" \ + " Thanks to Russ Gilbert for his SALVAGE programs.\n\n" + +#define USAGE HEADER "Usage: " PRG_NAME " " PRG_USAGE + +BOOL GenCode( CFile* pcf, DWORD dwStart, DWORD dwEnd ); +BOOL GenLineCode( CFile* pcf, DWORD dwEnd ); +BOOL GenCmdCode( CFile* pcf, DWORD dwLineStart, DWORD dwLineEnd ); +BOOL GenOpsCode( CFile* pcf, DWORD dwTokEnd ); +double ReadAtariBCD( CFile* pcf ); + +BOOL Vars_Load( CFile* pcf, WORD wVNT, WORD wVNTL, WORD wVVT, WORD NV ); +void Var_Get( char* szRet, int iNum ); +void Vars_Destroy(); + +FILE* g_fout = NULL; +CArray g_aVariables; //array of variables + +BOOL g_bVerbose = FALSE; //verbose output +BOOL g_bAtariOut = FALSE; //atari output +BOOL g_bExtOut = TRUE; //extended output +BOOL g_bHasErrors = FALSE; //decode error flag +BOOL g_bNoInverse = FALSE; //don't emit inverse +BASIC_TYPE g_Type = BASIC; //basic type. Default is Atari Basic + +char** g_aBasicCmds; //array of commands +char** g_aBasicOps; //array of operands +int g_iCmdNum; //number of commands +int g_iOpsNum; //number of operands +int g_iOpFirst; //first operand + +#include "switches.cpp" + +int main( int argc, char* argv[] ) +{ + setbuf( stdout, NULL ); + setbuf( stderr, NULL ); + + if ( !SWITCHES_Init( &argc, argv ) ) + return 1; + + if(strstr(argv[0], "listbas")) + g_bExtOut = FALSE; + + if ( argc < 2 ) + { + SWFN_HELP( USAGE ); + return 1; + } + + if ( g_bExtOut ) + fprintf( stderr, SHEADER "\n" ); + else + fprintf( stderr, HEADER ); + + char* szInfile = argv[ 1 ]; + char* szOutfile = NULL; + + if ( argc > 2 ) + szOutfile = argv[ 2 ]; + + CFile cf; + + if ( !cf.Open( szInfile ) ) + { + fprintf( stderr, "Can't open input file '%s'\n", szInfile ); + return 1; + } + + if ( szOutfile ) + { + if( g_bAtariOut ) + g_fout = fopen( szOutfile, "wb" ); //opening as binary because of + //atascii + else + g_fout = fopen( szOutfile, "wt" ); + } + + if ( !g_fout ) + g_fout = stdout; + + //Don't emit additional info if you are in Atari mode + if ( g_bAtariOut ) + g_bExtOut = FALSE; + + if ( g_bExtOut ) + { + fprintf( g_fout, HEADER ); + fprintf( g_fout, "Input file: %s\n\n", szInfile ); + } + + //initialize globals depending on language set + g_aBasicCmds = langtbl[ g_Type ].ppCommands; + g_aBasicOps = langtbl[ g_Type ].ppOperands; + g_iCmdNum = langtbl[ g_Type ].iCmdNum; + g_iOpsNum = langtbl[ g_Type ].iOpNum; + g_iOpFirst = langtbl[ g_Type ].iOpFirst; + + DWORD dwFileLen = cf.GetLength(); + + //read head + WORD wLOMEM = cf.readLEw(); + WORD wVNT = cf.readLEw(); + WORD wVNTE = cf.readLEw(); + WORD wVVT = cf.readLEw(); + WORD wSTMTAB = cf.readLEw(); + WORD wSTMCUR = cf.readLEw(); + WORD wSTARP = cf.readLEw(); + + if( ( wLOMEM == 0x00DD ) && ( g_Type == BASIC_XE ) ) + { + //extended mode of Basic XE + wLOMEM = 0; + g_Type = BASIC_XEX; + } + + WORD wCOR = wVNT - wLOMEM - 0x0E; + + wVNT -= wCOR; + wVNTE -= wCOR; + wVVT -= wCOR; + wSTMTAB -= wCOR; + wSTMCUR -= wCOR; + wSTARP -= wCOR; + + WORD wVNTL = wVNTE - wVNT + 1; + WORD wVVTE = wSTMTAB - 1; + WORD wVVTL = wVVTE - wVVT + 1; + WORD NV = wVVTL / 8; + + WORD wCodeLen = wSTMCUR - wSTMTAB; + WORD wCodeLenCur = wSTARP - wSTMCUR; + + long lLenDiff = (long)dwFileLen - (long)wSTARP; + + if ( g_bExtOut ) + { + fprintf( g_fout, "Constants & pointers:\n" ); + fprintf( g_fout, "Start of Name Table (VNT) : %04X\n", wVNT ); + fprintf( g_fout, "End of Name Table (VNTE) : %04X\n", wVNTE ); + fprintf( g_fout, "Lenght of Name Table (VNTL) : %04X\n", wVNTL ); + + fprintf( g_fout, "Start of Variable Table (VVT) : %04X\n", wVVT ); + fprintf( g_fout, "End of Variable Table (VVTE) : %04X\n", wVVTE ); + fprintf( g_fout, "Length of Variable Table (VVTL) : %04X\n", wVVTL ); + + fprintf( g_fout, "Number of Variables (NV) : %04X\n", NV ); + + fprintf( g_fout, "Start of Code (STMTAB): %04X\n", wSTMTAB ); + fprintf( g_fout, "Length of Code : %04X\n", wCodeLen ); + fprintf( g_fout, "Current command (STMCUR): %04X\n", wSTMCUR ); + fprintf( g_fout, "Length of current command : %04X\n", wCodeLenCur ); + fprintf( g_fout, "First byte after program (STARP) : %04X\n", wSTARP ); + + if( g_Type != BASIC_XEX ) + { + fprintf( g_fout, "Length of file : %04lX\n", dwFileLen ); + fprintf( g_fout, "File len difference : %08lX\n", (DWORD)lLenDiff ); + } + fputc( '\n', g_fout ); + } + + //records must be 8 bytes long + if ( NV * 8 != wVVTL ) + { + fprintf( stderr, "Variable Table Length Mismatch!\n" ); + return 1; + } + + if ( lLenDiff <0 ) + { + fprintf( stderr, "File Length Incorrect!\n" ); + return 1; + } + + if ( !Vars_Load( &cf, wVNT, wVNTL, wVVT, NV ) ) + return 1; + + if ( g_bExtOut ) + { + fprintf( g_fout, "Main code starts here:\n" ); + } + + GenCode( &cf, wSTMTAB, wSTMCUR ); + + if ( g_bExtOut ) + { + fputc( '\n', g_fout ); + + fprintf( g_fout, "Immediate code starts here:\n" ); + GenCode( &cf, wSTMCUR, wSTARP ); + fputc( '\n', g_fout ); + } + else + { + cf.Seek( wSTARP, SEEK_SET ); + } + + //if extended mode of Basic XE + if( g_Type == BASIC_XEX ) + { + //code is stored in 4 extended memory banks + for( int iBank = 0; iBank < 4; iBank++ ) + { + //read the end of code in bank + WORD wLen = cf.readLEw(); + + //because bank starts at 0x4000, the value must be GE + if( wLen < 0x4000 ) + { + fprintf( stderr, "Bank end too low! %04X\n", wLen ); + g_bHasErrors = TRUE; + break; + } + + wLen -= 0x4000; + + if ( g_bExtOut ) + { + fprintf( g_fout, "\nBank %d code:\n", iBank ); + } + + if ( wLen ) + { + //if we have anything to process, we do so + long lNow = cf.Tell(); + GenCode( &cf, lNow, lNow + wLen ); + } + else + { + //else we skip one byte (error in BXE?) in empty bank + cf.skip( 1 ); + } + + if ( g_bExtOut ) + { + fputc( '\n', g_fout ); + } + } + } + + cf.Close(); + + if ( g_bHasErrors ) + fprintf( stderr, "File may contain some errors!\n" ); + + if ( g_fout != stdout ) + fclose( g_fout ); + + fprintf( stderr, "Done!\n" ); + + Vars_Destroy(); + + return 0; +} + +BOOL GenCode( CFile* pcf, DWORD dwStart, DWORD dwEnd ) +{ + pcf->Seek( dwStart, SEEK_SET ); + + //going thru the bank + while( pcf->Tell() < (long)dwEnd ) + { + //generating line + if ( !GenLineCode( pcf, dwEnd ) ) + { + g_bHasErrors = TRUE; + return FALSE; + } + + //output the correct line terminator + if ( g_bAtariOut ) + fputc( 0x9B, g_fout ); + else + fputc( '\n', g_fout ); + } + + return TRUE; +} + +BOOL GenLineCode( CFile* pcf, DWORD dwEnd ) +{ + DWORD dwLineStart = pcf->Tell(); + + //some debug info + if ( g_bVerbose ) + fprintf( g_fout, "[O:%08lX]", dwLineStart ); + + //line number + WORD wLineNum = pcf->readLEw(); + + //end of line + BYTE btLEnd = pcf->readb(); + DWORD dwLineEnd = dwLineStart + btLEnd; + + //don't print immediate line in BASIC XE extended (already filtered in + // other versions + + if( g_Type == BASIC_XEX ) + { + if( wLineNum == 0x8000 ) + { + pcf->Seek( dwLineEnd, SEEK_SET ); + return TRUE; + } + } + + fprintf( g_fout, "%d ", wLineNum ); + + if ( g_bVerbose ) + { + fprintf( g_fout, "[S:%04lX E:%04lX]", dwLineStart, dwLineEnd ); + } + + //if the line goes the end of buffer, croak + if ( ( dwLineStart > dwEnd ) || ( dwLineEnd > dwEnd ) ) + { + fprintf( g_fout, "***Line size mismatch. (%04lX-%04lX)\n", dwLineEnd, dwEnd ); + return FALSE; + } + + //and generate the output for commands + while( pcf->Tell() < (long)dwLineEnd ) + { + if ( !GenCmdCode( pcf, dwLineStart, dwLineEnd ) ) + return FALSE; + } + + return TRUE; +} + +BOOL GenCmdCode( CFile* pcf, DWORD dwLineStart, DWORD dwLineEnd ) +{ + //end of token + BYTE btTEnd = pcf->readb(); + + DWORD dwTokStart = pcf->Tell(); + DWORD dwTokEnd = dwLineStart + btTEnd; + + if ( g_bVerbose ) + { + fprintf( g_fout, "[C:%04lX E:%04lX]", dwTokStart, dwTokEnd ); + } + + //could this ever happen? + if ( dwTokStart >= dwTokEnd ) + { + fprintf( g_fout, "***Command size problem!\n" ); + return FALSE; + } + + //if token goes behind the eol + if ( dwTokEnd > dwLineEnd ) + { + fprintf( g_fout, "***Command size mismatch. (%04lX-%04lX)\n", dwTokEnd, dwLineEnd ); + return FALSE; + } + + //which token + BYTE btTok = pcf->readb(); + + //token buffer + char szTok[ 50 ]; + + //if known token + if ( btTok < g_iCmdNum ) + { + //sub table for BXL extended commands + if( ( btTok == BXL_EXTEND ) && ( g_Type == BASIC_XL ) ) + { + BYTE btTok = pcf->readb(); + + switch( btTok ) + { + case 0x10: + strcpy( szTok, "LOCAL" ); + break; + + case 0x11: + strcpy( szTok, "EXIT" ); + break; + + case 0x12: + strcpy( szTok, "PROCEDURE" ); + break; + + case 0x13: + strcpy( szTok, "CALL" ); + break; + + case 0x14: + strcpy( szTok, "SORTUP" ); + break; + + case 0x15: + strcpy( szTok, "SORTDOWN" ); + break; + + default: + sprintf( szTok, "EXTEND?%02X", btTok ); + g_bHasErrors = TRUE; + break; + + } + } + else + strcpy( szTok, g_aBasicCmds[ btTok ] ); + } + else + { + sprintf( szTok, "COM%02X", btTok ); + fprintf( stderr, "Unknown command %02X!!!\n", btTok ); + g_bHasErrors = TRUE; + } + + if ( *szTok ) + { + //lower case for some dialects + if( ( g_Type == BASIC_XL ) || ( g_Type == BASIC_XE ) || ( g_Type == BASIC_XEX ) ) + { + strlwr( szTok + 1 ); + } + + fprintf( g_fout, "%s ", szTok ); + } + + //special handling for REM & DATA (first two statements) + if ( btTok < 2 ) + { + BYTE c; + + int iSecure = 0x100; + + for( ;; ) + { + c = pcf->readb(); + + if ( c == 0x9B ) + break; + + if ( g_bNoInverse ) + c &= 0x7F; + + fputc( c, g_fout ); + + iSecure--; + + if( !iSecure ) + { + fprintf( stderr, "Runaway in Rem/Data code!\n" ); + return FALSE; + } + } + + return TRUE; + + } + + //generate operands for remain of command + while( pcf->Tell() < (long)dwTokEnd ) + { + if ( !GenOpsCode( pcf, dwTokEnd ) ) + return FALSE; + } + + return TRUE; +} + +BOOL GenOpsCode( CFile* pcf, DWORD dwTokEnd ) +{ + //get operand + BYTE btTok = pcf->readb(); + + if ( btTok == OP_EOL ) + { + //new line + return TRUE; + } + + if ( btTok == OP_NCONST ) + { + //bcd num + + fprintf( g_fout, "%.10g", ReadAtariBCD( pcf ) ); + + return TRUE; + } + + if ( btTok == OP_NHCONST ) + { + if ( g_Type == BASIC_TB ) + { + //hex num TBASIC + fprintf( g_fout, "$%X", (unsigned short)ReadAtariBCD( pcf ) ); + return TRUE; + } + + if( ( g_Type == BASIC_XL ) || ( g_Type == BASIC_XE ) || ( g_Type == BASIC_XEX ) ) + { + //hex num BASIC XL + WORD wNum = (unsigned short)ReadAtariBCD( pcf ); + + if( wNum > 0xFF ) + fprintf( g_fout, "$%04X", wNum ); + else + fprintf( g_fout, "$%02X", wNum ); + + return TRUE; + } + } + + if ( btTok == OP_SCONST ) + { + //string + BYTE c; + + BYTE btLen = pcf->readb(); + + fprintf( g_fout, "\"" ); + while( btLen-- ) + { + c = pcf->readb(); + + if ( c == 0x9B ) + { + break; + } + + //is this for TBASIC only? + if ( c == '\"' ) + { + fprintf( g_fout, "\"\"" ); + } + else + fputc( c, g_fout ); + + } + fprintf( g_fout, "\"" ); + return TRUE; + } + + //and now for variables + if ( btTok & 0x80 ) + { + char szPom[ 255 ]; + + Var_Get( szPom, btTok & 0x7F ); + + if( ( g_Type == BASIC_XL ) || ( g_Type == BASIC_XE ) || ( g_Type == BASIC_XEX ) ) + { + strlwr( szPom + 1 ); + } + + fprintf( g_fout, szPom ); + + return TRUE; + } + + //func or op + if ( ( btTok < g_iOpFirst ) || ( btTok - g_iOpFirst + 1 > (BYTE)g_iOpsNum ) ) + { + fprintf( g_fout, "UNKOP%02X", btTok ); + fprintf( stderr, "Unknown operand %02X!!!\n", btTok ); + g_bHasErrors = TRUE; + } + else + { + char szPom[ 100 ]; + strcpy( szPom, g_aBasicOps[ btTok - g_iOpFirst ] ); + + if( ( g_Type == BASIC_XL ) || ( g_Type == BASIC_XE ) || ( g_Type == BASIC_XEX ) ) + { + strlwr( szPom + 1 ); + } + + fprintf( g_fout, "%s", szPom ); + } + + return TRUE; + +} + +//code for reading Atari BCD format +double ReadAtariBCD( CFile* pcf ) +{ + double dRes = 0; + + //reads exponent + BYTE btExp = pcf->readb(); + + int iExp; + + if ( !btExp ) + { + //if Exp==0, we're skipping it! (silently!) + iExp = 0; + pcf->skip( 5 ); + } + else + { + //compute exponent + iExp = ( btExp - 68 ) * 2; + + int i = 5; + + //read 5 pairs of numbers and combine 'em + while ( i-- ) + { + BYTE btPom = pcf->readb(); + + BYTE btNum = ( btPom >> 4 ) * 10 + ( btPom &0xf ); + + dRes *= 100; + dRes += btNum; + } + + } + + dRes *= pow( 10, iExp ); + + return dRes; +} + +BOOL Vars_Load( CFile* pcf, WORD wVNT, WORD wVNTL, WORD wVVT, WORD NV ) +{ + char szVarTemp[ 256 ]; + char szVarGen[ 256 ]; + + char* pStr = NULL; + + BOOL bTog = FALSE; + + pcf->Seek( wVNT, SEEK_SET ); + + for( int i = 0; i < wVNTL; i++ ) + { + if ( !pStr ) + pStr = szVarTemp; + + char c = pcf->readb(); + + if ( c & 0x80 ) + { + c &= 0x7F; + bTog = TRUE; + } + + *( pStr++ ) = c; + *pStr = '\0'; + + //this is for correcting the runaway + if ( pStr - szVarTemp > 254 ) + { + *szVarTemp = '\0'; + bTog = TRUE; + } + + if ( bTog ) + { + int iVar = g_aVariables.GetSize(); + + sprintf( szVarGen, "VAR%d", iVar ); + + pStr = szVarTemp; + + int iLength = strlen( szVarTemp ); + + if ( iLength ) + { + for( int i = 0; i < iLength; i++ ) + { + if ( !isprint( *( pStr++ ) ) ) + { + strcpy( szVarTemp, szVarGen ); + break; + } + } + + if ( iVar ) + { + for( int i = 0; i < iVar; i++ ) + { + if( !strcmp( (char*)g_aVariables.GetAt( i ), szVarTemp ) ) + { + fprintf( g_fout, "Dupped varname: %s\n", szVarTemp ); + strcpy( szVarTemp, szVarGen ); + break; + } + } + } + + } + else + { + strcpy( szVarTemp, szVarGen ); + } + + pStr = new char [ strlen( szVarTemp ) + 1 ]; + + if ( pStr ) + { + strcpy( pStr, szVarTemp ); + g_aVariables.Add( pStr ); + } + else + { + printf( "Not enough memory!\n" ); + return FALSE; + } + + bTog = FALSE; + pStr = NULL; + } + } + + if ( g_bExtOut ) + { + fprintf( g_fout, "Variable table:\n" ); + } + + pcf->Seek( wVVT, SEEK_SET ); + + for( int i = 0 ; i < NV; i++ ) + { + BYTE btType = pcf->readb(); + BYTE btNumber = pcf->readb(); + + char* szType; + + char szText[ 50 ]; + + switch( btType ) + { + case VART_SCALAR: + { + szType = "SCALAR "; + sprintf( szText, "%.10g", ReadAtariBCD( pcf ) ); + break; + } + + case VART_ARRAYU: + { + szType = "ARRAYu "; + char* szP = szText; + szP += sprintf( szP, "SPoff: %04X ", pcf->readLEw() ); + szP += sprintf( szP, "Dim1: %d ", pcf->readLEw() ); + szP += sprintf( szP, "Dim2: %d ", pcf->readLEw() ); + break; + } + + case VART_ARRAY: + { + szType = "ARRAY "; + char* szP = szText; + szP += sprintf( szP, "SPoff: %04X ", pcf->readLEw() ); + szP += sprintf( szP, "Dim1: %d ", pcf->readLEw() ); + szP += sprintf( szP, "Dim2: %d ", pcf->readLEw() ); + break; + } + + case VART_STRINGAU: + { + //BASIC_XL / XE + szType = "STRINGAu"; + char* szP = szText; + szP += sprintf( szP, "SPoff: %04X ", pcf->readLEw() ); + szP += sprintf( szP, "Dim1: %d ", pcf->readLEw() ); + szP += sprintf( szP, "Dim2: %d ", pcf->readLEw() ); + break; + } + + case VART_STRINGA: + { + //BASIC_XL / XE + szType = "STRINGA "; + char* szP = szText; + szP += sprintf( szP, "SPoff: %04X ", pcf->readLEw() ); + szP += sprintf( szP, "Dim1: %d ", pcf->readLEw() ); + szP += sprintf( szP, "Dim2: %d ", pcf->readLEw() ); + break; + } + + case VART_STRINGU: + { + szType = "STRINGu "; + char* szP = szText; + szP += sprintf( szP, "SPoff: %04X ", pcf->readLEw() ); + szP += sprintf( szP, "Len: %d ", pcf->readLEw() ); + szP += sprintf( szP, "Dim: %d ", pcf->readLEw() ); + break; + } + + case VART_STRING: + { + szType = "STRING "; + char* szP = szText; + szP += sprintf( szP, "SPoff: %04X ", pcf->readLEw() ); + szP += sprintf( szP, "Len: %d ", pcf->readLEw() ); + szP += sprintf( szP, "Dim: %d ", pcf->readLEw() ); + break; + } + + case VART_PROC: + { + //TBASIC + szType = "PROC "; + char* szP = szText; + for( int i = 0 ; i < 6; i++ ) + { + szP += sprintf( szP, "%02X ", pcf->readb() ); + } + break; + } + + case VART_LABEL: + { + //TBASIC + szType = "LABEL "; + char* szP = szText; + for( int i = 0 ; i < 6; i++ ) + { + szP += sprintf( szP, "%02X ", pcf->readb() ); + } + break; + } + + default: + { + szType = "UNKNOWN "; + char* szP = szText; + for( int i = 0 ; i < 6; i++ ) + { + szP += sprintf( szP, "%02X ", pcf->readb() ); + } + g_bHasErrors = TRUE; + } + } + + char szName[ 255 ]; + Var_Get( szName, btNumber ); + + char cLastChar = szName[ strlen( szName ) - 1 ]; + + switch( btType ) + { + case VART_STRING: + case VART_STRINGU: + { + if ( cLastChar != '$' ) + { + strcat( szName, "$" ); + char* szStr = new char [ strlen( szName ) + 1 ]; + strcpy( szStr, szName ); + char* szOld = (char*) g_aVariables.GetAt( btNumber ); + + if ( szOld ) + delete [] szOld; + + g_aVariables.SetAt( btNumber, szStr ); + + } + + break; + } + + case VART_ARRAY: + case VART_ARRAYU: + { + if ( cLastChar == '(' ) + { + szName[ strlen( szName ) - 1 ] = '\0'; + char* szStr = new char [ strlen( szName ) + 1 ]; + strcpy( szStr, szName ); + char* szOld = (char*) g_aVariables.GetAt( btNumber ); + + if ( szOld ) + delete [] szOld; + + g_aVariables.SetAt( btNumber, szStr ); + + } + + break; + } + + } + + if ( g_bExtOut ) + { + fprintf( g_fout, "%04X %s (%02X) %02X: %s %s\n", + i+1, + szType, + btType, + btNumber, + szText, + szName ); + } + + } + + if ( g_bExtOut ) + fputc( '\n', g_fout ); + + return TRUE; +} + +void Var_Get( char* szRet, int iNum ) +{ + char* szVar = (char*) g_aVariables.GetAt( iNum ); + + if ( szVar ) + strcpy( szRet, szVar ); + else + sprintf( szRet, "VAR%d", iNum ); +} + +void Vars_Destroy() +{ + for( int i = 0; i < g_aVariables.GetSize(); i++ ) + { + if ( g_aVariables.GetAt( i ) ) + delete [] ( char* ) g_aVariables.GetAt( i ); + } +} + diff --git a/jindroush/chkbas/listbas b/jindroush/chkbas/listbas new file mode 120000 index 0000000..8b02192 --- /dev/null +++ b/jindroush/chkbas/listbas @@ -0,0 +1 @@ +chkbas \ No newline at end of file diff --git a/jindroush/chkbas/pub.def b/jindroush/chkbas/pub.def new file mode 100644 index 0000000..790db8c --- /dev/null +++ b/jindroush/chkbas/pub.def @@ -0,0 +1,31 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#define PRG_NAME "chkbas" +#define PRG_VERSION "1.10" +#define PRG_COPYRIGHT "1999-2001" +#define PRG_UNDERGPL "1" +#define PRG_AUTHOR "Jindrich Kubec " + +#define PRG_URL "http://www.asw.cz/~kubecj" + +#define PRG_DESC "Atari Basic/Turbo Basic/Basic XL/Basic XE decompiler." +#define PRG_USAGE "[options] sourcefile [lstfile]" + +#define PRG_ARCH "PC" +#define PRG_TOOLS "PERL" + +#define PRG_SRCS "!GENERATED!" +#define PRG_BINS "rel/chkbas.exe" diff --git a/jindroush/chkbas/readme.txt b/jindroush/chkbas/readme.txt new file mode 100644 index 0000000..a9a1b86 --- /dev/null +++ b/jindroush/chkbas/readme.txt @@ -0,0 +1,87 @@ +ChkBas v1.10 (c) 1999-2001 Jindrich Kubec +Latest version can be found at http://www.asw.cz/~kubecj + +This program is provided 'as is', no warranty will be taken +for any damage caused by it or by any use of it. + +The whole package is placed under the GNU Public License, for further +information on redistribution see the included file "GPL.TXT". + + +Description: +------------ +Atari Basic/Turbo Basic/Basic XL/Basic XE decompiler. + + + +Usage: +------ +ChkBas [options] sourcefile [lstfile] + +sourcefile is Atari basic file. + +lstfile is output text file + +-atari - exports source only in Atari format +-short - exports source only in PC format +-verbose - prints verbose information +-tbs - decodes Turbo Basic file +-bxl - decodes Basic XL file +-bxe - decodes Basic XE file + +The export is by default more verbose and in PC format. + + +History: +-------- +Date, Author, Version +4/5/1999, kubecj, 0.90 +First version + +4/20/1999, kubecj, 1.00 +First public version + +4/20/1999, kubecj, 1.01 +BCD error bugfix + +7/7/1999, kubecj, 1.02 +Atari output file bugfix (it did break lines on 0x0A char) + +9/5/1999, kubecj, 1.03 +'Hacked' variable table bugfix (overflow when filled with chars under 0x80) + +10/10/1999, kubecj, 1.04 +Changed switches processing. + +7/5/2001, kubecj, 1.05 +Added Basic XL. + +7/6/2001, kubecj, 1.06 +Added Basic XE. + +7/7/2001, kubecj, 1.10 +Added Basic XE extended mode. Code cleanup. + + +To Do: +------ +Add other basic dialects? + + +Known Bugs: +----------- +None. + + +Compiling Tools: +---------------- +For scripts: Perl. +URL: http://www.perl.com + +For PC executables: DJGPP. +Sources were written/tested on GCC/Intel only. There should be only +minor problems to port it to different architectures/environments. +Makefile should need only minor changes. +URL: http://www.delorie.com + + diff --git a/jindroush/chkbas/strlwr.cpp b/jindroush/chkbas/strlwr.cpp new file mode 100644 index 0000000..10c3f84 --- /dev/null +++ b/jindroush/chkbas/strlwr.cpp @@ -0,0 +1,11 @@ +#include + +// 20070524 bkw: Linux and POSIX lack the DOS/Windows strlwr() function, +// so here's an implementation. + +void strlwr(char *s) { + while(*s) { + *s = tolower(*s); + s++; + } +} diff --git a/jindroush/chkbas/switches.def b/jindroush/chkbas/switches.def new file mode 100644 index 0000000..bb09a46 --- /dev/null +++ b/jindroush/chkbas/switches.def @@ -0,0 +1,34 @@ +verbose, v +verbose info +=g_bVerbose = TRUE; += + +atari +Atari output file (only lst is created) +=g_bAtariOut = TRUE; += + +short +PC - lst only output (full output otherwise) +=g_bExtOut = FALSE; += + +noinverse +no inverse characters in DATA or REMs +=g_bNoInverse = TRUE; += + +bxl +Basic XL +=g_Type = BASIC_XL; += + +bxe +Basic XE +=g_Type = BASIC_XE; += + +tbs +Turbo Basic +=g_Type = BASIC_TB; += diff --git a/jindroush/chkexe/Makefile b/jindroush/chkexe/Makefile new file mode 100644 index 0000000..04ef5f7 --- /dev/null +++ b/jindroush/chkexe/Makefile @@ -0,0 +1,55 @@ +#===================================================================== +PRGNAME = chkexe + +all: $(PRGNAME) + +release: + @$(MAKE) $(PRGNAME) CFLAGS="-c -O2 -Wall" LDFLAGS="" + @echo RELEASE: Compiled. + +rel_strip: + @strip $(PRGNAME).exe + +rel_inst: + @copy $(PRGNAME).exe $(ATAROOT)\\bin + @echo RELEASE: Installed. + +debug: + @$(MAKE) $(PRGNAME) CFLAGS="-c -g -Wall -D_DEBUG" LDFLAGS="-g" + @echo DEBUG: Compiled. + +clean: + rm -f *.o + rm -f $(PRGNAME) + rm -f $(PRGNAME).exe + rm -f switches.cpp + rm -rf rel + @echo DEBUG: Cleaned. + +#===================================================================== +INCLUDES = makefile \ + switches.def \ + pub.def + + +OBJECTS = chkexe.o + +#===================================================================== +CC = g++ +LD = g++ +LDLIBS = -lm -L../lib -ljindroush +CPPFLAGS=-I../include $(COPT) +COPT=-O2 + +#===================================================================== + +$(PRGNAME) : $(OBJECTS) + $(LD) $(LDFLAGS) $(OBJECTS) $(LDLIBS) -o $(PRGNAME) + +chkexe.o: switches.cpp + +%.o : %.cpp $(INCLUDES) switches.cpp + $(CC) $(CPPFLAGS) -c $< -o $@ + +switches.cpp : switches.def ../switches.pl + perl ../switches.pl $< $@ diff --git a/jindroush/chkexe/chkexe.cpp b/jindroush/chkexe/chkexe.cpp new file mode 100644 index 0000000..4d651f0 --- /dev/null +++ b/jindroush/chkexe/chkexe.cpp @@ -0,0 +1,504 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "pub.def" + +#include "jintypes.h" + +#include "at_dis.h" +#include "cfile.h" + +#define AT_HEADER 0xFFFF + +#define AT_RUNL 0x02E0 +#define AT_RUNH 0x02E1 +#define AT_RUNPREV ( AT_RUNL - 1 ) + +#define AT_INITL 0x02E2 +#define AT_INITH 0x02E3 +#define AT_INITPAST ( AT_INITH + 1 ) + +#define AT_HWSTART 0xD000 +#define AT_HWEND 0xD7FF + +typedef struct block +{ + struct block *pNext; + WORD wBlkStart; + WORD wBlkEnd; +} FILE_BLOCK; + + +BOOL BlockRead( CFile&, CFile& ); +void BlockInsert( WORD, WORD ); +void BlocksWrite( CFile& ); +void PrintOffset( CFile& ); +void BlockDisassemble( WORD, WORD ); + +FILE_BLOCK *g_pBlocks = NULL; +BYTE *g_pbtPool; +BOOL g_bHasRunAddress = FALSE; +LONG g_lFileLen; +BOOL g_bDisassemble = FALSE; +BOOL g_bSilent = FALSE; +BOOL g_bIsNotOk = TRUE; +BOOL g_bSplit = FALSE; +BOOL g_bOut = FALSE; + +WORD g_iSplitNum = 0; + +WORD g_wGapFill = 0; + +char* g_szInfile = NULL; +char* g_szOutfile = NULL; + +#define SHEADER PRG_NAME " v" PRG_VERSION " (c) " PRG_COPYRIGHT " " PRG_AUTHOR "\n" + +#define HEADER SHEADER \ + PRG_DESC "\n" \ + " Latest version can be found at " PRG_URL "\n" \ + " Published under GPL. See GPL.TXT.\n\n" + +#define USAGE HEADER "Usage: " PRG_NAME " " PRG_USAGE + +#include "switches.cpp" + +int main (int argc,char *argv[]) +{ + setbuf( stdout, NULL ); + setbuf( stderr, NULL ); + + if ( !SWITCHES_Init( &argc, argv ) ) + return 1; + + if ( ( argc < 2 ) ) + { + SWFN_HELP( USAGE ); + return 1; + } + + fprintf( stderr, SHEADER ); + + g_szInfile = argv[ 1 ]; + + if ( argc == 3 ) + g_szOutfile = argv[ 2 ]; + + CFile cfIn; + CFile cfOut; + + if ( !cfIn.Open( g_szInfile ) ) + { + fprintf( stderr, "Unable to open file\n\n%s", g_szInfile ); + return -1; + } + + if ( AT_HEADER != cfIn.readLEw() ) + { + printf( "%s: Not an Atari 8-bit binary load format file\n", g_szInfile ); + cfIn.Close(); + return -1; + } + + if ( g_bSilent ) + printf( "%s: ", g_szInfile ); + else + printf( "Binary file: %s\n", g_szInfile ); + + if ( argc > 2 ) + { + if ( !cfOut.Create( g_szOutfile ) ) + { + fprintf( stderr, "Unable to open file\n\n%s", g_szOutfile ); + return -1; + } + g_bOut = TRUE; + } + + if ( g_bOut ) + { + cfOut.writeLEw( AT_HEADER ); + } + + g_pbtPool = new BYTE [ 0x10000 ]; + memset( g_pbtPool,0, 0x10000 ); + + if ( !g_pbtPool ) + { + fprintf( stderr, "Unable to allocate memory for address space.\n" ); + return -1; + } + + g_lFileLen = cfIn.GetLength(); + + cfIn.Seek( 2, SEEK_SET ); + + while ( cfIn.Tell() < g_lFileLen ) + { + if ( ( g_bIsNotOk = !BlockRead( cfIn, cfOut ) ) ) + break; + } + + cfIn.Close(); + + if ( g_bHasRunAddress ) + BlockInsert( AT_RUNL, AT_RUNH ); + + if ( g_bOut ) + { + BlocksWrite( cfOut ); // Write all blocks since last init + cfOut.Close(); + } + + delete [] g_pbtPool; + + if ( !g_bIsNotOk ) + printf( "Ok!\n" ); + + return 0; +} + + +BOOL BlockRead( CFile& cfIn, CFile& cfOut ) +{ + WORD wBlkStart; + WORD wBlkEnd; + WORD wBlkLen; + + do + { + PrintOffset( cfIn ); + + if ( cfIn.Tell() >= g_lFileLen ) + { + printf( "Error: Unexpected end of file\n" ); + return FALSE; + } + + wBlkStart = cfIn.readLEw(); + + if ( wBlkStart == AT_HEADER ) + { + if ( !g_bSilent ) + printf( " : Unexpected second 0xffff format header\n" ); + } + + } while ( wBlkStart == AT_HEADER ); + + if ( cfIn.Tell() >= g_lFileLen ) + { + printf( "Error: Unexpected end of file in load range start address\n" ); + return FALSE; + } + + wBlkEnd = cfIn.readLEw(); + + wBlkLen = wBlkEnd - wBlkStart + 1; + + if ( cfIn.Tell() >= g_lFileLen ) + { + printf( "Error: Unexpected end of file in load range end address\n" ); + return FALSE; + } + + if ( ( wBlkStart == wBlkEnd ) && ( ( wBlkStart >> 8 ) == ( wBlkStart & 0xFF ) ) ) + { + WORD wLen = g_lFileLen - cfIn.Tell() + 4; + + //garbage was limited to be max $500 long, run address must exist! + if ( ( wLen < 0x500 ) && ( wBlkStart ) ) + { + printf( "Error: Apparent garbage fill at end of file (%04X bytes)\n", wLen ); + return FALSE; + } + + } + + if ( wBlkEnd < wBlkStart ) + { + if ( !g_bSilent ) + printf( "Block: %04X-%04X (%04X)\n", wBlkStart, wBlkEnd, wBlkLen ); + + printf( "Error: %ld bytes in file after invalid load range\n", g_lFileLen - cfIn.Tell() ); + return FALSE; + } + + if ( g_lFileLen < cfIn.Tell() + wBlkLen ) + { + if ( !g_bSilent ) + printf( "Block: %04X-%04X (%04X)\n", wBlkStart, wBlkEnd, wBlkLen ); + + printf( "Error: Truncated file: missing data in load block (%04lX bytes missing)\n", cfIn.Tell() + wBlkLen - g_lFileLen ); + return FALSE; + } + + // Read in the data for this block + cfIn.Read( &g_pbtPool[wBlkStart], wBlkLen ); + + // Check for run address + if ( wBlkStart <= AT_RUNH && wBlkStart + wBlkLen >= AT_RUNL ) + { + if (wBlkStart==AT_RUNH || wBlkStart+wBlkLen==AT_RUNL) + { + if ( !g_bSilent ) + printf( " : Partial run address\n" ); + } + if ( g_bHasRunAddress ) + if ( !g_bSilent ) + printf( " : Unexpected second run address\n" ); + + g_bHasRunAddress = TRUE; + + if ( !g_bSilent ) + printf( "Run : %04X\n", g_pbtPool[ AT_RUNL ] + 256 * g_pbtPool[ AT_RUNH ] ); + + if ( ( wBlkStart >= AT_RUNL ) && ( wBlkEnd <= AT_RUNH ) ) + return TRUE; + + // Other data in this block + if ( wBlkStart == AT_RUNL || wBlkStart == AT_RUNH ) + { + // Run and init in the same block--split + wBlkStart = AT_INITL; + wBlkLen = wBlkEnd - wBlkStart + 1; + } + else if ( wBlkEnd == AT_RUNL || wBlkEnd==AT_RUNH) + { + // other stuff before the run address--split + wBlkEnd = AT_RUNPREV; + wBlkLen = wBlkEnd - wBlkStart + 1; + } + else + { + // Run address in the middle of the block + if ( !g_bSilent ) + printf( "Block: %04X-%04X (%04X)\n", wBlkStart, AT_RUNPREV, AT_RUNPREV - wBlkStart + 1 ); + + BlockInsert( wBlkStart, AT_RUNPREV ); + wBlkStart = AT_INITL; + wBlkLen = wBlkEnd - wBlkStart + 1; + } + } + + // Check for init address + // We know there's nothing before the address in the block, + // as we would have split it off above as a run address. + if ( wBlkStart <= AT_INITH && wBlkStart + wBlkLen >= AT_INITL ) + { + if ( wBlkStart == AT_INITH || wBlkStart + wBlkLen == AT_INITL ) + { + if ( !g_bSilent ) + printf( " : Partial init address\n" ); + } + if ( !g_bSilent ) + printf( "Init : %04X\n", g_pbtPool[ AT_INITL ] + 256 * g_pbtPool[ AT_INITH ] ); + + // Other data in this block? + if ( wBlkEnd > AT_INITH ) + { + // More stuff past init--split + if ( !g_bSilent ) + printf( "Block: %04X-%04X (%04X)\n", AT_INITPAST, wBlkEnd, wBlkLen ); + + BlockInsert( AT_INITPAST, wBlkEnd ); + wBlkEnd = AT_INITH; + wBlkLen = wBlkEnd - wBlkStart + 1; + } + + BlockInsert( wBlkStart, wBlkEnd ); + + if ( g_bDisassemble ) + BlockDisassemble( wBlkStart, wBlkEnd ); + + // Write everything out to avoid cross-init merges + BlocksWrite( cfOut ); + return TRUE; + } + + // Print data block load message + if ( !g_bSilent ) + printf( "Block: %04X-%04X (%04X)\n", wBlkStart, wBlkEnd, wBlkLen ); + + if ( ( !wBlkStart ) && ( !wBlkEnd ) ) + return TRUE; + + BlockInsert( wBlkStart, wBlkEnd ); + + if ( g_bDisassemble ) + BlockDisassemble( wBlkStart, wBlkEnd ); + + return TRUE; +} + + +void BlockInsert(WORD wBlkStart,WORD wBlkEnd) +{ + if ( g_bSplit ) + { + char szPom[ 255 ]; + sprintf( szPom, "blk%04X.blk", g_iSplitNum ); + + CFile cf; + if ( cf.Create( szPom ) ) + { + cf.writeLEw( AT_HEADER ); + cf.writeLEw( wBlkStart ); + cf.writeLEw( wBlkEnd ); + cf.Write( g_pbtPool + wBlkStart, wBlkEnd - wBlkStart + 1 ); + cf.Close(); + } + + g_iSplitNum++; + } + + FILE_BLOCK *b,*bp; + + bp = NULL; // previous block + b = g_pBlocks; + + while( b ) + { + //this fills the ultra short blks + if ( ( ( b->wBlkEnd + 1 ) >= 0x400 ) && ( b->wBlkStart < 0xC000 ) ) + { + if ( ( b->wBlkEnd + 1 ) < wBlkStart ) + { + if ( ( wBlkStart - ( b->wBlkEnd + 1 ) ) < g_wGapFill ) + { + if ( !g_bSilent ) + printf( "\t\tBlock merges with a previous block (gap fill)\n" ); + + b->wBlkEnd = wBlkEnd; + return; + } + } + + } + + // Check for merge + if ( b->wBlkEnd + 1 == wBlkStart ) + { + if ( !g_bSilent ) + printf( "\t\tBlock merges with a previous block\n" ); + + b->wBlkEnd = wBlkEnd; + return; + } + if ( b->wBlkStart - 1 == wBlkEnd ) + { + if ( !g_bSilent ) + printf( "\t\tBlock merges with a previous block (unexpected ordering)\n" ); + + b->wBlkStart = wBlkStart; + return; + } + // Check for overlap + if ( b->wBlkStart <= wBlkStart && wBlkEnd <= b->wBlkEnd ) + { + if ( !g_bSilent ) + printf( "\t\tWarning: Completely overlaps a previous block--merged\n" ); + + return; + } + if (b->wBlkStart <= wBlkEnd && b->wBlkStart >= wBlkStart) + { + b->wBlkStart = wBlkStart; + if (b->wBlkEndwBlkEnd = wBlkEnd; + if ( !g_bSilent ) + printf( "\t\tWarning: Partially overlaps a previous block--merged\n" ); + + return; + } + if ( b->wBlkEnd <= wBlkEnd && b->wBlkEnd >= wBlkStart ) + { + b->wBlkEnd = wBlkEnd; + + if ( b->wBlkStart > wBlkStart ) + b->wBlkStart = wBlkStart; + + if ( !g_bSilent ) + printf( "\t\tWarning: Partially overlaps a previous block--merged\n" ); + + return; + } + bp = b; + b = b->pNext; + } + + // Add this block to the end of the list + b = new FILE_BLOCK; + + if( !b ) + { + fprintf(stderr,"Unable to alloc memory--aborted\n" ); + } + + b->wBlkStart = wBlkStart; + b->wBlkEnd = wBlkEnd; + b->pNext = NULL; + + if (bp) + bp->pNext = b; + else + g_pBlocks = b; +} + + +void BlocksWrite( CFile& cf ) +{ + FILE_BLOCK* b; + FILE_BLOCK* bp; + + b = g_pBlocks; + while (b) + { + if ( g_bOut) + { + cf.writeLEw( b->wBlkStart ); + cf.writeLEw( b->wBlkEnd ); + + cf.Write( &g_pbtPool[ b->wBlkStart ], b->wBlkEnd - b->wBlkStart + 1 ); + } + bp = b; // To allow free call after last use + b = b->pNext; + delete bp; + } + g_pBlocks = NULL; +} + + +void BlockDisassemble(WORD wBlkStart,WORD wBlkEnd) +{ + //don't disassemble run & init block + if ( ( wBlkStart >= AT_RUNL ) && ( wBlkEnd <= AT_INITH ) ) + goto BDEND; + + //don't disassemble hw addresses + if ( ( wBlkStart >= AT_HWSTART ) && ( wBlkEnd <= AT_HWEND ) ) + goto BDEND; + + OutputBlockDiss( g_pbtPool + wBlkStart, wBlkStart, wBlkEnd ); + +BDEND: + printf( "\n" ); + return; +} + +void PrintOffset( CFile& cf ) +{ + if ( !g_bSilent ) + printf( "[%04lX] ", cf.Tell() ); +} + diff --git a/jindroush/chkexe/pub.def b/jindroush/chkexe/pub.def new file mode 100644 index 0000000..eb3d2fb --- /dev/null +++ b/jindroush/chkexe/pub.def @@ -0,0 +1,31 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#define PRG_NAME "chkexe" +#define PRG_VERSION "2.62" +#define PRG_COPYRIGHT "1998-1999" +#define PRG_UNDERGPL "1" +#define PRG_AUTHOR "Jindrich Kubec " + +#define PRG_URL "http://www.asw.cz/~kubecj" + +#define PRG_DESC "Atari executable checker/decompiler." +#define PRG_USAGE "[options] sourcefile [destfile]" + +#define PRG_ARCH "PC" +#define PRG_TOOLS "PERL" + +#define PRG_SRCS "!GENERATED!" +#define PRG_BINS "rel/chkexe.exe" diff --git a/jindroush/chkexe/readme.txt b/jindroush/chkexe/readme.txt new file mode 100644 index 0000000..7d92c8f --- /dev/null +++ b/jindroush/chkexe/readme.txt @@ -0,0 +1,100 @@ +ChkExe v2.62 (c) 1998-1999 Jindrich Kubec +Latest version can be found at http://www.asw.cz/~kubecj + +This program is provided 'as is', no warranty will be taken +for any damage caused by it or by any use of it. + +The whole package is placed under the GNU Public License, for further +information on redistribution see the included file "GPL.TXT". + + +Description: +------------ +Atari executable checker/decompiler. +Based on Preston Crow's binload utility. Better command line switches, +better disassembler and gap filing. + +Disassembler is only very simple - single pass, no data recognition. + + +Usage: +------ +ChkExe [options] sourcefile [destfile] + +sourcefile is Atari DOS exe file. + +destfile is optional output file with changed blocks. + +gaps is for changing the size of maximum 'gap' fill. It's the destination + of two blocks under which blocks will be 'glued' together by zeroes. + +silent outputs only OK/errors + +split creates also blkXXXX.blk files with only one block inside + +d creates also disassembly of each block + + +History: +-------- +Date, Author, Version +6/2/1995, crow, 1.00 +Initial public release + +6/4/1995, crow, 2.00 +Create fixed version of the file + +6/7/1995, crow, 2.10 +Use separate functions +Merge overlapping and adjacent blocks + +6/9/1995, cmwagner, 2.20 +Ported to MS-DOS machines, should compile and work under +MS-DOS,compile in COMPACT model. + +11/11/1995, cmwagner, 2.30 +Added d switch, which allow disassembly of blocks to stdout +disassemble_block() function added, outins() function added, instable[] added + +11/16/1995, cmwagner, 2.40 +Fixed bogus operands on output when operands extend beyond +end of block, just puts out a bogus instruction symbol now (???). + +9/24/1998, kubecj, 2.50 +Modularized, added symbol resolving in disassembler +Added -silent switch for batch processing +Added gap filling +Rewritten in CPP under DJGPP only, no portability + +7/7/1999, kubecj, 2.60 +Added file blocks splitting + +8/20/1999, kubecj, 2.61 +Fixed signedness bug concerning branches :( + +10/10/1999, kubecj, 2.62 +Changed switches processing. + + +To Do: +------ +Maybe better disassembler. + + +Known Bugs: +----------- +None. + + +Compiling Tools: +---------------- +For scripts: Perl. +URL: http://www.perl.com + +For PC executables: DJGPP. +Sources were written/tested on GCC/Intel only. There should be only +slight problems to port it to different architectures/environments. +Makefile should need only slight changes. +URL: http://www.delorie.com + + diff --git a/jindroush/chkexe/switches.def b/jindroush/chkexe/switches.def new file mode 100644 index 0000000..4c2bf20 --- /dev/null +++ b/jindroush/chkexe/switches.def @@ -0,0 +1,21 @@ +d, dis +disassembles +=g_bDisassemble = TRUE; += + +silent, s +silent operation +=g_bSilent = TRUE; += + +gaps +length of gap fill (hexadecimal) +=int iTemp; +hexnum=bRet = SWFN_NUMH( &iTemp ); +=g_wGapFill = iTemp; += + +split +split into blocks +=g_bSplit = TRUE; += diff --git a/jindroush/chkrom/Makefile b/jindroush/chkrom/Makefile new file mode 100644 index 0000000..19bf6f4 --- /dev/null +++ b/jindroush/chkrom/Makefile @@ -0,0 +1,56 @@ +#===================================================================== +PRGNAME = chkrom + +all: $(PRGNAME) + +release: + @$(MAKE) $(PRGNAME) CFLAGS="-c -O2 -Wall" LDFLAGS="" + @echo RELEASE: Compiled. + +rel_strip: + @strip $(PRGNAME).exe + +rel_inst: + @copy $(PRGNAME).exe $(ATAROOT)\\bin + @echo RELEASE: Installed. + +debug: + @$(MAKE) $(PRGNAME) CFLAGS="-c -g -Wall -D_DEBUG" LDFLAGS="-g" + @echo DEBUG: Compiled. + +clean: + rm -f *.o + rm -f $(PRGNAME) + rm -f $(PRGNAME).exe + rm -f switches.cpp + rm -rf rel + @echo DEBUG: Cleaned. + +#===================================================================== +INCLUDES = makefile \ + pub.def \ + switches.def + + +OBJECTS = chkrom.o + +#===================================================================== +CC = g++ +LD = g++ +LDLIBS = -lm -L../lib -ljindroush +CPPFLAGS=-I../include $(COPT) +COPT=-O2 + +#===================================================================== + +$(PRGNAME) : $(OBJECTS) + $(LD) $(LDFLAGS) $(OBJECTS) $(LDLIBS) -o $(PRGNAME) + +chkrom.o: chkrom.cpp switches.cpp + +%.o : %.cpp $(INCLUDES) + $(CC) $(CPPFLAGS) -c $< -o $@ + +switches.cpp : switches.def ../switches.pl + perl ../switches.pl $< $@ + diff --git a/jindroush/chkrom/chkrom.cpp b/jindroush/chkrom/chkrom.cpp new file mode 100644 index 0000000..32c8979 --- /dev/null +++ b/jindroush/chkrom/chkrom.cpp @@ -0,0 +1,119 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +//#include +#include "pub.def" +#include "jintypes.h" +#include "at_dis.h" + +BOOL g_bDisassemble = FALSE; + +int hIn = -1; + +char* g_szInfile = NULL; + +#define SHEADER PRG_NAME " v" PRG_VERSION " (c) " PRG_COPYRIGHT " " PRG_AUTHOR "\n" + +#define HEADER SHEADER \ + PRG_DESC "\n" \ + " Latest version can be found at " PRG_URL "\n" \ + " Published under GPL. See GPL.TXT.\n\n" + +#define USAGE HEADER "Usage: " PRG_NAME " " PRG_USAGE + +#include "switches.cpp" + +int main (int argc,char *argv[]) +{ + setbuf( stdout, NULL ); + setbuf( stderr, NULL ); + + if ( !SWITCHES_Init( &argc, argv ) ) + return 1; + + if ( argc < 2 ) + { + SWFN_HELP( USAGE ); + return 1; + } + + fprintf( stderr, SHEADER ); + + g_szInfile = argv[ 1 ]; + + hIn = open( g_szInfile, O_RDONLY | O_BINARY ); + + if ( hIn == -1 ) + { + fprintf(stderr, "Unable to open file\n\n%s", g_szInfile ); + exit( 1 ); + } + + LONG lFileLen = lseek( hIn, 0, SEEK_END ); + + lseek( hIn, 0, SEEK_SET ); + + if ( ( lFileLen != 0x2000 ) && ( lFileLen != 0x4000 ) ) + { + printf( "%s: Unknown ROM size\n", g_szInfile ); + close( hIn ); + exit( 1 ); + } + + printf( "ROM file: %s\n", g_szInfile ); + + BYTE pbtMem[ 0x4000 ]; + + read( hIn, pbtMem, lFileLen ); + + WORD wInit = pbtMem[ lFileLen - 2 ] + ( pbtMem[ lFileLen - 1 ] << 8 ); + WORD wFlags = pbtMem[ lFileLen - 4 ] + ( pbtMem[ lFileLen - 3 ] << 8 ); + WORD wRun = pbtMem[ lFileLen - 6 ] + ( pbtMem[ lFileLen - 5 ] << 8 ); + + WORD wStart = ( lFileLen == 0x2000 ) ? 0xA000 : 0x8000; + + printf( "Init Addr :%04X\n", wInit ); + printf( "Run Addr :%04X\n", wRun ); + printf( "Flags :%04X ( ", wFlags ); + + if ( wFlags & 0x0400 ) + { + printf( "INIT&RUN " ); + } + else + printf( "INIT " ); + + if ( wFlags & 0x0100 ) + printf( "BOOT " ); + + if ( wFlags & 0x8000 ) + printf( "TESTMOD " ); + + printf( ")\n" ); + + if ( g_bDisassemble ) + { + printf( "\n" ); + OutputBlockDiss( pbtMem, wStart, wStart + lFileLen - 1 - 6 ); + printf( "\n" ); + } + + printf( "Ok!\n" ); + + close( hIn ); + + return 0; +} + diff --git a/jindroush/chkrom/pub.def b/jindroush/chkrom/pub.def new file mode 100644 index 0000000..f888d12 --- /dev/null +++ b/jindroush/chkrom/pub.def @@ -0,0 +1,31 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#define PRG_NAME "chkrom" +#define PRG_VERSION "1.00" +#define PRG_COPYRIGHT "1998-1999" +#define PRG_UNDERGPL "1" +#define PRG_AUTHOR "Jindrich Kubec " + +#define PRG_URL "http://www.asw.cz/~kubecj" + +#define PRG_DESC "Atari cartridge ROM 8/16 decompiler." +#define PRG_USAGE "[options] sourcefile" + +#define PRG_ARCH "PC" +#define PRG_TOOLS "PERL" + +#define PRG_SRCS "!GENERATED!" +#define PRG_BINS "rel/chkrom.exe" diff --git a/jindroush/chkrom/readme.txt b/jindroush/chkrom/readme.txt new file mode 100644 index 0000000..7f3c12b --- /dev/null +++ b/jindroush/chkrom/readme.txt @@ -0,0 +1,56 @@ +ChkRom v1.00 (c) 1998-1999 Jindrich Kubec +Latest version can be found at http://www.asw.cz/~kubecj + +This program is provided 'as is', no warranty will be taken +for any damage caused by it or by any use of it. + +The whole package is placed under the GNU Public License, for further +information on redistribution see the included file "GPL.TXT". + + +Description: +------------ +Atari cartridge ROM 8/16 decompiler. + + + +Usage: +------ +ChkRom [options] sourcefile + +sourcefile is Atari ROM image. + + +History: +-------- +Date, Author, Version +4/5/1999, kubecj, 0.95 +First version + +10/10/1999, kubecj, 1.00 +Changed switches processing. +First release. + + +To Do: +------ +Maybe better disassembler. + + +Known Bugs: +----------- +None. + + +Compiling Tools: +---------------- +For scripts: Perl. +URL: http://www.perl.com + +For PC executables: DJGPP. +Sources were written/tested on GCC/Intel only. There should be only +slight problems to port it to different architectures/environments. +Makefile should need only slight changes. +URL: http://www.delorie.com + + diff --git a/jindroush/chkrom/switches.def b/jindroush/chkrom/switches.def new file mode 100644 index 0000000..827d5b4 --- /dev/null +++ b/jindroush/chkrom/switches.def @@ -0,0 +1,5 @@ +d, dis, disassemble +disassemble +=g_bDisassemble = TRUE; += + diff --git a/jindroush/gpl.txt b/jindroush/gpl.txt new file mode 100644 index 0000000..a43ea21 --- /dev/null +++ b/jindroush/gpl.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/jindroush/include/adsk.h b/jindroush/include/adsk.h new file mode 100644 index 0000000..6786d8a --- /dev/null +++ b/jindroush/include/adsk.h @@ -0,0 +1,75 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __ADSK_H__ +#define __ADSK_H__ + +#include "jintypes.h" +#include "cobj.h" +#include "cdsk.h" + +#define MAX_ATARI_SECTOR_LEN 0x100 + +typedef enum +{ + DISK_AUTO, + DISK_ATR, + DISK_ATRb, + DISK_XFD, + DISK_XFDb, + DISK_SCP, + DISK_DCM, + DISK_DI +} DISK_TYPE; + +typedef enum +{ + DI_RET_OK, + DI_RET_CANT_CONTINUE, + DI_RET_CONTINUE +} DISKINIT_RETCODE; + +class ADisk : public CDisk +{ +public: + ADisk(); + ~ADisk(); + + BOOL ReadSectors( void*, int, int ); + BOOL WriteSectors( int, void*, int ); + + int GetBootSectorCount(); + int GetBootSectorSize(); + BOOL GetBootSector( BYTE* ); +}; + +void GuessClassicSizes( int, int, DISK_GEOMETRY* ); +void ForceClassicSize( int, int, DISK_GEOMETRY* ); +void ForceClassicSize( DISK_GEOMETRY* ); + +char* GetDiskTypeName( DISK_TYPE disktype ); +char* GetDiskTypeExt( DISK_TYPE disktype ); + +DISKINIT_RETCODE InitializeDisk( ADisk**, DISK_TYPE, char*, BOOL bVerbose, BOOL, BOOL ); + + +#include "adsk_atr.h" +#include "adsk_xfd.h" +#include "adsk_scp.h" +#include "adsk_dcm.h" +#include "adsk_di.h" + +#endif //_ADSK_H__ + diff --git a/jindroush/include/adsk_atr.h b/jindroush/include/adsk_atr.h new file mode 100644 index 0000000..189b030 --- /dev/null +++ b/jindroush/include/adsk_atr.h @@ -0,0 +1,38 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CATR_H__ +#define __CATR_H__ + +#include "jintypes.h" +#include "errbase.h" +#include "adsk.h" + +#define CATR_FORMAT_VIOLATED ( CATR_BASE + 0 ) + +class CAtr : public ADisk +{ +public: + CAtr(); + ~CAtr(); + + BOOL Load( char*, BOOL = FALSE, BOOL = FALSE ); + + BOOL Save( char*, BOOL ); +private: +}; + +#endif + diff --git a/jindroush/include/adsk_dcm.h b/jindroush/include/adsk_dcm.h new file mode 100644 index 0000000..4e5ca3e --- /dev/null +++ b/jindroush/include/adsk_dcm.h @@ -0,0 +1,72 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CDCM_H__ +#define __CDCM_H__ + +#include "errbase.h" +#include "jintypes.h" +#include "adsk.h" +#include "cfile.h" +#include "cprefile.h" + +#define CDCM_FORMAT_VIOLATED ( CDCM_BASE + 0 ) + +class CDcm : public ADisk +{ +public: + CDcm(); + ~CDcm(); + + BOOL Load( char*, BOOL = FALSE, BOOL = FALSE ); + + BOOL Save( char*, BOOL ); + +private: + + BOOL DecodeRec41( CGenFile& ); + BOOL DecodeRec42( CGenFile& ); + BOOL DecodeRec43( CGenFile& ); + BOOL DecodeRec44( CGenFile& ); + BOOL DecodeRec46( CGenFile& ); + BOOL DecodeRec47( CGenFile& ); + BOOL DecodeRecFA( CGenFile& ); + WORD ReadOffset( CGenFile& ); + + void EncodeRec41( BYTE*, int*, BYTE*, BYTE*, int ); + void EncodeRec43( BYTE*, int*, BYTE*, int ); + void EncodeRec44( BYTE*, int*, BYTE*, BYTE*, int ); + + void EncodeRec45(); + void EncodeRec46(); + void EncodeRec( BOOL ); + void EncodeRecFA( BOOL, int, int, int ); + + BOOL m_bLastPass; + BYTE m_abtCurrBuff[ 0x100 ]; + BYTE m_abtPrevBuff[ 0x100 ]; + int m_iSectorSize; + WORD m_wCurrentSector; + long m_lFileLength; + BOOL m_bAlreadyFormatted; + + + BYTE* m_pbtCurr; + BYTE* m_pbtPass; + BYTE* m_pbtLastRec; +}; + +#endif + diff --git a/jindroush/include/adsk_di.h b/jindroush/include/adsk_di.h new file mode 100644 index 0000000..fb1a527 --- /dev/null +++ b/jindroush/include/adsk_di.h @@ -0,0 +1,38 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CDI_H__ +#define __CDI_H__ + +#include "jintypes.h" +#include "errbase.h" +#include "adsk.h" + +#define CDI_FORMAT_VIOLATED ( CDI_BASE + 0 ) + +class CDi : public ADisk +{ +public: + CDi(); + ~CDi(); + + BOOL Load( char*, BOOL = FALSE, BOOL = FALSE ); + + BOOL Save( char*, BOOL ); +private: +}; + +#endif + diff --git a/jindroush/include/adsk_scp.h b/jindroush/include/adsk_scp.h new file mode 100644 index 0000000..933fc68 --- /dev/null +++ b/jindroush/include/adsk_scp.h @@ -0,0 +1,37 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CSCP_H__ +#define __CSCP_H__ + +#include "jintypes.h" +#include "adsk.h" + +#define CSCP_FORMAT_VIOLATED ( CSCP_BASE + 0 ) + +class CScp : public ADisk +{ +public: + CScp(); + ~CScp(); + + BOOL Load( char*, BOOL = FALSE, BOOL = FALSE ); + BOOL Save( char*, BOOL ); + +private: +}; + +#endif + diff --git a/jindroush/include/adsk_xfd.h b/jindroush/include/adsk_xfd.h new file mode 100644 index 0000000..1870b70 --- /dev/null +++ b/jindroush/include/adsk_xfd.h @@ -0,0 +1,38 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CXFD_H__ +#define __CXFD_H__ + +#include "jintypes.h" +#include "adsk.h" +#include "errbase.h" + +#define CXFD_FORMAT_VIOLATED ( CXFD_BASE + 0 ) + +class CXfd : public ADisk +{ +public: + CXfd(); + ~CXfd(); + + BOOL Load( char*, BOOL = FALSE, BOOL = FALSE ); + BOOL Save( char*, BOOL ); + +private: +}; + +#endif + diff --git a/jindroush/include/at_dis.h b/jindroush/include/at_dis.h new file mode 100644 index 0000000..c489e60 --- /dev/null +++ b/jindroush/include/at_dis.h @@ -0,0 +1,25 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __AT_DIS_H__ +#define __AT_DIS_H__ + +#include "jintypes.h" + +void OutputBlockDiss( BYTE*, WORD, WORD ); +char* SymbolFind( WORD, BOOL ); + +#endif + diff --git a/jindroush/include/autil.h b/jindroush/include/autil.h new file mode 100644 index 0000000..66c569c --- /dev/null +++ b/jindroush/include/autil.h @@ -0,0 +1,35 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __AUTIL_H__ +#define __AUTIL_H__ + +#include "jintypes.h" + +void ADos2MsDos( char*, char* ); +void GuessBestFnameFromPC( char* szDest, char* szSrc, char* szExt, char* szAdd = NULL ); +void GuessBestFnameFromAtari( char* szDest, char* szSrc, char* szExt ); + +BOOL IsBlockEmpty( BYTE*, int ); + +#define MGET_B( p ) ( *(p++ ) ); +#define MGET_LEW( p ) ( *p + ((*(p+1) ) <<8) ),p+=2; +#define MGET_BEW( p ) ( *(p+1) + ((*(p) ) <<8) ),p+=2; + +#define MREAD_B( p ) ( *p ); +#define MREAD_LEW( p ) ( *p + ((*(p+1) ) <<8) ); +#define MREAD_BEW( p ) ( *(p+1) + ((*(p) ) <<8) ); + +#endif diff --git a/jindroush/include/cdisk.h b/jindroush/include/cdisk.h new file mode 100644 index 0000000..4542ccd --- /dev/null +++ b/jindroush/include/cdisk.h @@ -0,0 +1,95 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CDISK_H__ +#define __CDISK_H__ + +#include "jintypes.h" +#include "cobj.h" + +#define CDISK_ERROR_CANT_OPEN ( CDISK_BASE + 0 ) + +typedef enum +{ + DISK_AUTO, + DISK_ATR, + DISK_ATRb, + DISK_XFD, + DISK_XFDb, + DISK_SCP, + DISK_DCM +} DISK_TYPE; + +typedef enum +{ + DI_RET_OK, + DI_RET_CANT_CONTINUE, + DI_RET_CONTINUE +} DISKINIT_RETCODE; + +typedef struct +{ + int iSides; + int iTracks; + int iSectorsPerTrack; + int iBytesPerSector; + int iSectors; +} DISK_GEOMETRY; + +class CDisk : public CObj +{ +public: + CDisk(); + virtual ~CDisk(); + + virtual BOOL Load( char*, BOOL = FALSE, BOOL = FALSE ) = 0; + + #ifdef __CDISK_WRITE__ + virtual BOOL Save( char*, BOOL ) = 0; + #endif + + BOOL Format( DISK_GEOMETRY* ); + + DISK_GEOMETRY* GetGeometry() { return &m_geometry; }; + int GetSectorSize() { return m_geometry.iBytesPerSector; }; + int GetSectorCount() { return m_geometry.iSectors; }; + + BOOL ReadSector( void*, int ); + BOOL WriteSector( int, void* ); + + BOOL ReadSectors( void*, int, int ); + BOOL WriteSectors( int, void*, int ); + + BOOL Duplicate( CDisk* ); + + char* GetImageName() { return m_szFname; }; + +protected: + DISK_GEOMETRY m_geometry; + BOOL m_bOpened; + BYTE *m_pbtMemory; + int m_iAllocated; + + char m_szFname[ 255 ]; +}; + +void GuessClassicSizes( int, int, DISK_GEOMETRY* ); + +char* GetDiskTypeName( DISK_TYPE disktype ); +char* GetDiskTypeExt( DISK_TYPE disktype ); + +DISKINIT_RETCODE InitializeDisk( CDisk**, DISK_TYPE, char*, BOOL bVerbose, BOOL, BOOL ); + +#endif diff --git a/jindroush/include/cdsk.h b/jindroush/include/cdsk.h new file mode 100644 index 0000000..50461e2 --- /dev/null +++ b/jindroush/include/cdsk.h @@ -0,0 +1,72 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CDISK_H__ +#define __CDISK_H__ + +#include "jintypes.h" +#include "cobj.h" + +#define CDISK_ERROR_CANT_OPEN ( CDISK_BASE + 0 ) + +typedef struct +{ + int iSides; + int iTracks; + int iSectorsPerTrack; + int iBytesPerSector; + int iSectors; +} DISK_GEOMETRY; + +class CDisk : public CObj +{ +public: + CDisk(); + virtual ~CDisk(); + + #ifndef __CDISK_NOLOAD__ + virtual BOOL Load( char*, BOOL = FALSE, BOOL = FALSE ) = 0; + #endif + + #ifdef __CDISK_SAVE__ + virtual BOOL Save( char*, BOOL ) = 0; + #endif + + BOOL Format( DISK_GEOMETRY* ); + + DISK_GEOMETRY* GetGeometry() { return &m_geometry; }; + int GetSectorSize() { return m_geometry.iBytesPerSector; }; + int GetSectorCount() { return m_geometry.iSectors; }; + + BOOL ReadSector( void*, int ); + BOOL WriteSector( int, void* ); + + BOOL Duplicate( CDisk*, DISK_GEOMETRY* = NULL ); + + char* GetImageName() { return m_szFname; }; + +protected: + DISK_GEOMETRY m_geometry; + BOOL m_bHasData; + BYTE *m_pbtMemory; + int m_iAllocated; + + char m_szFname[ 255 ]; + + int m_iMaxSectorWritten; + +}; + +#endif diff --git a/jindroush/include/cdsk_atr.h b/jindroush/include/cdsk_atr.h new file mode 100644 index 0000000..3f4ac11 --- /dev/null +++ b/jindroush/include/cdsk_atr.h @@ -0,0 +1,38 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CATR_H__ +#define __CATR_H__ + +#include "jintypes.h" +#include "errbase.h" +#include "cdisk.h" + +#define CATR_FORMAT_VIOLATED ( CATR_BASE + 0 ) + +class CAtr : public CDisk +{ +public: + CAtr(); + ~CAtr(); + + BOOL Load( char*, BOOL = FALSE, BOOL = FALSE ); + + BOOL Save( char*, BOOL ); +private: +}; + +#endif + diff --git a/jindroush/include/cdsk_dcm.h b/jindroush/include/cdsk_dcm.h new file mode 100644 index 0000000..c891852 --- /dev/null +++ b/jindroush/include/cdsk_dcm.h @@ -0,0 +1,72 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CDCM_H__ +#define __CDCM_H__ + +#include "errbase.h" +#include "jintypes.h" +#include "cdisk.h" +#include "cfile.h" +#include "cprefile.h" + +#define CDCM_FORMAT_VIOLATED ( CDCM_BASE + 0 ) + +class CDcm : public CDisk +{ +public: + CDcm(); + ~CDcm(); + + BOOL Load( char*, BOOL = FALSE, BOOL = FALSE ); + + BOOL Save( char*, BOOL ); + +private: + + BOOL DecodeRec41( CGenFile& ); + BOOL DecodeRec42( CGenFile& ); + BOOL DecodeRec43( CGenFile& ); + BOOL DecodeRec44( CGenFile& ); + BOOL DecodeRec46( CGenFile& ); + BOOL DecodeRec47( CGenFile& ); + BOOL DecodeRecFA( CGenFile& ); + WORD ReadOffset( CGenFile& ); + + void EncodeRec41( BYTE*, int*, BYTE*, BYTE*, int ); + void EncodeRec43( BYTE*, int*, BYTE*, int ); + void EncodeRec44( BYTE*, int*, BYTE*, BYTE*, int ); + + void EncodeRec45(); + void EncodeRec46(); + void EncodeRec( BOOL ); + void EncodeRecFA( BOOL, int, int, int ); + + BOOL m_bLastPass; + BYTE m_abtCurrBuff[ 0x100 ]; + BYTE m_abtPrevBuff[ 0x100 ]; + int m_iSectorSize; + WORD m_wCurrentSector; + long m_lFileLength; + BOOL m_bAlreadyFormatted; + + + BYTE* m_pbtCurr; + BYTE* m_pbtPass; + BYTE* m_pbtLastRec; +}; + +#endif + diff --git a/jindroush/include/cdsk_scp.h b/jindroush/include/cdsk_scp.h new file mode 100644 index 0000000..7d43f6b --- /dev/null +++ b/jindroush/include/cdsk_scp.h @@ -0,0 +1,37 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CSCP_H__ +#define __CSCP_H__ + +#include "jintypes.h" +#include "cdisk.h" + +#define CSCP_FORMAT_VIOLATED ( CSCP_BASE + 0 ) + +class CScp : public CDisk +{ +public: + CScp(); + ~CScp(); + + BOOL Load( char*, BOOL = FALSE, BOOL = FALSE ); + BOOL Save( char*, BOOL ); + +private: +}; + +#endif + diff --git a/jindroush/include/cdsk_xfd.h b/jindroush/include/cdsk_xfd.h new file mode 100644 index 0000000..3acadc5 --- /dev/null +++ b/jindroush/include/cdsk_xfd.h @@ -0,0 +1,38 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CXFD_H__ +#define __CXFD_H__ + +#include "jintypes.h" +#include "cdisk.h" +#include "errbase.h" + +#define CXFD_FORMAT_VIOLATED ( CXFD_BASE + 0 ) + +class CXfd : public CDisk +{ +public: + CXfd(); + ~CXfd(); + + BOOL Load( char*, BOOL = FALSE, BOOL = FALSE ); + BOOL Save( char*, BOOL ); + +private: +}; + +#endif + diff --git a/jindroush/include/cfile.h b/jindroush/include/cfile.h new file mode 100644 index 0000000..4f65e9e --- /dev/null +++ b/jindroush/include/cfile.h @@ -0,0 +1,54 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "jintypes.h" +#include "cgenfile.h" + +#ifndef __CFILE_H__ +#define __CFILE_H__ + + +class CFile : public CGenFile +{ +public: + CFile(); + ~CFile(); + + BOOL Open( char* ); + BOOL Create( char* ); + + BOOL Read( void*, int, int* = NULL ); + BOOL Write( void*, int, int* = NULL ); + + BOOL Seek( long, int ); + long GetLength() { return m_lLength; }; + DWORD GetLastError() { return m_dwLastError; }; + void Close(); + + BOOL IsDirty() { return m_bIsDirty; }; + +private: + BOOL m_bOpened; + BOOL m_bIsDirty; + + int m_hFile; + + DWORD m_dwLastError; + + LONG m_lLength; + +}; + +#endif //__CFILE_H__ diff --git a/jindroush/include/cfs.h b/jindroush/include/cfs.h new file mode 100644 index 0000000..c7b1651 --- /dev/null +++ b/jindroush/include/cfs.h @@ -0,0 +1,65 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CFS_H__ +#define __CFS_H__ + +#include "adsk.h" +#include "cobj.h" + +#define DIRE_DELETED 0x00000001 +#define DIRE_SUBDIR 0x00000002 + +class CDirEntry +{ +public: + CDirEntry(); + ~CDirEntry(); + + char m_szFname[ 256 ]; + char m_szAscData[ 256 ]; + DWORD m_dwFlags; + CDirEntry* m_pSubdir; + CDirEntry* m_pNext; + CDirEntry* m_pPrev; +}; + +class CFs : public CObj +{ +public: + + CFs(); + virtual ~CFs(); + + virtual BOOL Mount( ADisk* ) = 0; + virtual void Dismount() = 0; + virtual BOOL ExportFile( char*, CDirEntry* ) = 0; + CDirEntry* GetRoot() { return m_pRoot; }; + + int GetInvalidPercent() { return (m_iFilesInvalid+m_iFilesValid) ? ( m_iFilesInvalid * 100 ) / ( m_iFilesValid + m_iFilesInvalid ) : 0; }; + + void DeleteList( CDirEntry* ); + +protected: + int m_iFilesValid; + int m_iFilesInvalid; + + + CDirEntry* m_pRoot; + ADisk* m_pDisk; +}; + +#endif + diff --git a/jindroush/include/cfs_b2b.h b/jindroush/include/cfs_b2b.h new file mode 100644 index 0000000..2b838bb --- /dev/null +++ b/jindroush/include/cfs_b2b.h @@ -0,0 +1,42 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CBAS2BOOT_H__ +#define __CBAS2BOOT_H__ + +#include "jintypes.h" +#include "cfs.h" + +class CBas2BootDirEntry : public CDirEntry +{ +public: + DWORD m_dwFileLen; +}; + +class CBas2Boot : public CFs +{ +public: + CBas2Boot(); + ~CBas2Boot(); + + BOOL Mount( ADisk* ); + void Dismount(); + BOOL ExportFile( char*, CDirEntry* ); + +private: + CBas2BootDirEntry* CreateEntry(); +}; + +#endif diff --git a/jindroush/include/cfs_boot.h b/jindroush/include/cfs_boot.h new file mode 100644 index 0000000..e440e67 --- /dev/null +++ b/jindroush/include/cfs_boot.h @@ -0,0 +1,42 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CBOOT_H__ +#define __CBOOT_H__ + +#include "jintypes.h" +#include "cfs.h" + +class CBootDirEntry : public CDirEntry +{ +public: + int m_iSectorCount; +}; + +class CBoot : public CFs +{ +public: + CBoot(); + ~CBoot(); + + BOOL Mount( ADisk* ); + void Dismount(); + BOOL ExportFile( char*, CDirEntry* ); + +private: + CBootDirEntry* CreateEntry(); +}; + +#endif diff --git a/jindroush/include/cfs_dos2.h b/jindroush/include/cfs_dos2.h new file mode 100644 index 0000000..867755d --- /dev/null +++ b/jindroush/include/cfs_dos2.h @@ -0,0 +1,67 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CDOS2_H__ +#define __CDOS2_H__ + +#include "jintypes.h" +#include "cfs.h" + +#pragma pack(1) +typedef struct +{ + BYTE btFlags; + WORD wSecCount; //Number of sectors in file + WORD wSecStart; //First sector in file + CHAR acAtariName[11]; +} DOS2_DIRENT; + +#pragma pack() + +//flags bits: +// 0x80 7->deleted +// 0x40 6->in use +// 0x20 5->locked +// 0x10 4->mydos subdir +// 0x08 3-> +// 0x04 2-> +// 0x02 1-> +// 0x01 0->write open + +class CDos2DirEntry : public CDirEntry +{ +public: + WORD m_wFileNumber; + BYTE m_btFlags; + WORD m_wSecCount; //Number of sectors in file + WORD m_wSecStart; //First sector in file +}; + +class CDos2 : public CFs +{ +public: + CDos2(); + ~CDos2(); + + BOOL Mount( ADisk* ); + void Dismount(); + BOOL ExportFile( char*, CDirEntry* ); + +private: + CDos2DirEntry* CreateEntry( DOS2_DIRENT*, WORD ); + +}; + +#endif diff --git a/jindroush/include/cfs_dos3.h b/jindroush/include/cfs_dos3.h new file mode 100644 index 0000000..9e7133a --- /dev/null +++ b/jindroush/include/cfs_dos3.h @@ -0,0 +1,59 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CDOS3_H__ +#define __CDOS3_H__ + +#include "jintypes.h" +#include "cfs.h" + +#pragma pack(1) +typedef struct +{ + BYTE btFlags; + CHAR acAtariName[11]; + BYTE btSecCount; + BYTE btSecStart; + WORD wFileLen; +} DOS3_DIRENT; + +#pragma pack() + +class CDos3DirEntry : public CDirEntry +{ +public: + BYTE m_btSecStart; + BYTE m_btSecCount; + BYTE m_btFlags; + WORD m_wFileLen; +}; + +class CDos3 : public CFs +{ +public: + CDos3(); + ~CDos3(); + + BOOL Mount( ADisk* ); + void Dismount(); + BOOL ExportFile( char*, CDirEntry* ); + +private: + CDos3DirEntry* CreateEntry( DOS3_DIRENT* ); + + BYTE m_abtFat[ 0x0100 ]; +}; + +#endif diff --git a/jindroush/include/cfs_dosm.h b/jindroush/include/cfs_dosm.h new file mode 100644 index 0000000..9ef9262 --- /dev/null +++ b/jindroush/include/cfs_dosm.h @@ -0,0 +1,66 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CDOSM_H__ +#define __CDOSM_H__ + +#include "jintypes.h" +#include "cfs.h" + +#pragma pack(1) +typedef struct +{ + BYTE btFlags; + WORD wSecCount; //Number of sectors in file + WORD wSecStart; //First sector in file + CHAR acAtariName[11]; +} DOSM_DIRENT; + +#pragma pack() + +//flags bits: +// 0x80 7->deleted +// 0x40 6->in use +// 0x20 5->locked +// 0x10 4->mydos subdir +// 0x08 3-> +// 0x04 2-> +// 0x02 1-> +// 0x01 0->write open + +class CDosMDirEntry : public CDirEntry +{ +public: + BYTE m_btFlags; + WORD m_wSecCount; //Number of sectors in file + WORD m_wSecStart; //First sector in file +}; + +class CDosM : public CFs +{ +public: + CDosM(); + ~CDosM(); + + BOOL Mount( ADisk* ); + void Dismount(); + BOOL ExportFile( char*, CDirEntry* ); + BOOL ReadDir( int, CDosMDirEntry** ); + +private: + CDosMDirEntry* CreateEntry( DOSM_DIRENT* ); +}; + +#endif diff --git a/jindroush/include/cfs_doss.h b/jindroush/include/cfs_doss.h new file mode 100644 index 0000000..31b5124 --- /dev/null +++ b/jindroush/include/cfs_doss.h @@ -0,0 +1,70 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CDOSS_H__ +#define __CDOSS_H__ + +#include "jintypes.h" +#include "cfs.h" + +#pragma pack(1) +typedef struct +{ + BYTE btFlags; + WORD wSector; + WORD wSizeLo; + BYTE btSizeHi; + CHAR acAtariName[11]; + BYTE btDay; + BYTE btMonth; + BYTE btYear; + BYTE btHour; + BYTE btMinute; + BYTE btSecond; +} DOSS_DIRENT; + +#pragma pack() + +class CDosSDirEntry : public CDirEntry +{ +public: + BYTE m_btFlags; + int m_iLength; + int m_iLinkSector; +}; + +class CDosS : public CFs +{ +public: + CDosS(); + ~CDosS(); + + BOOL Mount( ADisk* ); + void Dismount(); + BOOL ExportFile( char*, CDirEntry* ); + BOOL ReadDir( int, CDosSDirEntry** ); + +private: + CDosSDirEntry* CreateEntry( DOSS_DIRENT* ); + int GetSectorLinkEntry( int, int ); + + BYTE* MapFile( int, int ); + void UnMapFile( BYTE* ); + + WORD m_wMainDirStart; + WORD m_wSectorSize; +}; + +#endif diff --git a/jindroush/include/cfs_howf.h b/jindroush/include/cfs_howf.h new file mode 100644 index 0000000..9705ad9 --- /dev/null +++ b/jindroush/include/cfs_howf.h @@ -0,0 +1,43 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CHOWF_H__ +#define __CHOWF_H__ + +#include "jintypes.h" +#include "cfs.h" + +class CHowfDirEntry : public CDirEntry +{ +public: + int m_iStartSec; + int m_iSecCount; +}; + +class CHowf : public CFs +{ +public: + CHowf(); + ~CHowf(); + + BOOL Mount( ADisk* ); + void Dismount(); + BOOL ExportFile( char*, CDirEntry* ); + +private: + CHowfDirEntry* CreateEntry( WORD, BYTE* ); +}; + +#endif diff --git a/jindroush/include/cfs_jonw.h b/jindroush/include/cfs_jonw.h new file mode 100644 index 0000000..6131c76 --- /dev/null +++ b/jindroush/include/cfs_jonw.h @@ -0,0 +1,43 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CJONW_H__ +#define __CJONW_H__ + +#include "jintypes.h" +#include "cfs.h" + +class CJonwDirEntry : public CDirEntry +{ +public: + int m_iStartSec; + int m_iSecCount; +}; + +class CJonw : public CFs +{ +public: + CJonw(); + ~CJonw(); + + BOOL Mount( ADisk* ); + void Dismount(); + BOOL ExportFile( char*, CDirEntry* ); + +private: + CJonwDirEntry* CreateEntry( BYTE, WORD, BYTE* ); +}; + +#endif diff --git a/jindroush/include/cfs_kboo.h b/jindroush/include/cfs_kboo.h new file mode 100644 index 0000000..c0df3e1 --- /dev/null +++ b/jindroush/include/cfs_kboo.h @@ -0,0 +1,42 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CKBOOT_H__ +#define __CKBOOT_H__ + +#include "jintypes.h" +#include "cfs.h" + +class CKBootDirEntry : public CDirEntry +{ +public: + DWORD m_dwFileLen; +}; + +class CKBoot : public CFs +{ +public: + CKBoot(); + ~CKBoot(); + + BOOL Mount( ADisk* ); + void Dismount(); + BOOL ExportFile( char*, CDirEntry* ); + +private: + CKBootDirEntry* CreateEntry(); +}; + +#endif diff --git a/jindroush/include/cfs_robc.h b/jindroush/include/cfs_robc.h new file mode 100644 index 0000000..1e4b412 --- /dev/null +++ b/jindroush/include/cfs_robc.h @@ -0,0 +1,43 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __CROBC_H__ +#define __CROBC_H__ + +#include "jintypes.h" +#include "cfs.h" + +class CRobcDirEntry : public CDirEntry +{ +public: + int m_iStartSec; + int m_iSecCount; +}; + +class CRobc : public CFs +{ +public: + CRobc(); + ~CRobc(); + + BOOL Mount( ADisk* ); + void Dismount(); + BOOL ExportFile( char*, CDirEntry* ); + +private: + CRobcDirEntry* CreateEntry( BYTE, WORD, BYTE* ); +}; + +#endif diff --git a/jindroush/include/cgenfile.h b/jindroush/include/cgenfile.h new file mode 100644 index 0000000..c97e214 --- /dev/null +++ b/jindroush/include/cgenfile.h @@ -0,0 +1,55 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "jintypes.h" + +#ifndef __CGENFILE_H__ +#define __CGENFILE_H__ + +class CGenFile +{ +public: + virtual ~CGenFile() {}; + + virtual BOOL Read( void*, int, int* = NULL ) = 0; + virtual BOOL Write( void*, int, int* = NULL ) = 0; + + virtual BOOL Seek( long, int ) = 0; + + virtual void Close() = 0; + + void writeb( BYTE ); + void writeLEw( WORD ); + void writeBEw( WORD ); + void writeLEdw( DWORD ); + + BYTE readb(); + WORD readLEw(); + WORD readBEw(); + DWORD readLEdw(); + + WORD readw(); + DWORD readd(); + + BOOL skip( long ); + + long Tell(); + + LONG m_lCurrPtr; + +private: +}; + +#endif diff --git a/jindroush/include/cobj.h b/jindroush/include/cobj.h new file mode 100644 index 0000000..0d39ea9 --- /dev/null +++ b/jindroush/include/cobj.h @@ -0,0 +1,34 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __COBJ_H__ +#define __COBJ_H__ + +#include "jintypes.h" + +class CObj +{ +public: + CObj(); + const char* GetLastError( char* p = NULL ) { if ( p ) strcpy( p, m_szLastError ); return m_szLastError; }; + void SetLastError( char* p ) { strcpy( m_szLastError, p ); }; + int GetErrorCode() { return m_iErrorCode; }; + +protected: + char m_szLastError[ 4096 ]; + int m_iErrorCode; +}; + +#endif diff --git a/jindroush/include/cprefile.h b/jindroush/include/cprefile.h new file mode 100644 index 0000000..1e748bb --- /dev/null +++ b/jindroush/include/cprefile.h @@ -0,0 +1,56 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "jintypes.h" +#include "cgenfile.h" + +#ifndef __CPREFILE_H__ +#define __CPREFILE_H__ + + +class CPreFile : public CGenFile +{ +public: + CPreFile(); + ~CPreFile(); + + BOOL Open( CGenFile*, int ); + + BOOL Read( void*, int, int* = NULL ); + BOOL Write( void*, int, int* = NULL ); + + BOOL Seek( long, int ); + long GetLength() { return m_lLength; }; + DWORD GetLastError() { return m_dwLastError; }; + void Close(); + +private: + BOOL PreRead(); + + BOOL m_bOpened; + + DWORD m_dwLastError; + + long m_lCacheStartOffset; + long m_lCacheEndOffset; + + long m_lLength; + BYTE* m_pbtCache; + long m_lCacheLen; + + CGenFile* m_pcf; +}; + +#endif //__CPreFILE_H__ diff --git a/jindroush/include/errbase.h b/jindroush/include/errbase.h new file mode 100644 index 0000000..8c16c0c --- /dev/null +++ b/jindroush/include/errbase.h @@ -0,0 +1,26 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __ERRBASE_H__ +#define __ERRBASE_H__ + +#define CDISK_BASE 0x1000 +#define CATR_BASE 0x2000 +#define CDCM_BASE 0x3000 +#define CSCP_BASE 0x4000 +#define CXFD_BASE 0x5000 +#define CDI_BASE 0x6000 + +#endif diff --git a/jindroush/include/jintypes.h b/jindroush/include/jintypes.h new file mode 100644 index 0000000..fab787a --- /dev/null +++ b/jindroush/include/jintypes.h @@ -0,0 +1,95 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef __WINTYPES_H__ +#define __WINTYPES_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#ifndef MAX_PATH +#define MAX_PATH 256 +#endif + +#ifdef __DJGPP__ + #include + #include + #include + #include +#else + #define tell(x) lseek(x,0,SEEK_CUR) + #define _fixpath(x,y) strcpy(y,x) + #define getch() getchar() + +#endif + +#ifndef _WINDOWS +typedef int BOOL; +#define TRUE ( 1==1 ) +#define FALSE ( !TRUE ) + +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; + +typedef unsigned char UBYTE; +typedef unsigned short UWORD; +typedef unsigned long UDWORD; + +typedef char CHAR; +typedef long LONG; +typedef short SHORT; + +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef unsigned long ULONG; + +typedef char SBYTE; +typedef short SWORD; +typedef long SDWORD; + +typedef WORD WCHAR; +typedef CHAR TCHAR; + +// typedef WORD wchar_t; + +typedef const char* LPCSTR; +typedef const WCHAR* LPCWSTR; +typedef const TCHAR* LPCTSTR; + +typedef TCHAR* LPTSTR; +typedef CHAR LPSTR; + +#define PASCAL pascal +#else + +#include +#endif + +#endif // diff --git a/jindroush/lib/Makefile b/jindroush/lib/Makefile new file mode 100644 index 0000000..bafe06c --- /dev/null +++ b/jindroush/lib/Makefile @@ -0,0 +1,23 @@ +OBJS=adsk.o adsk_atr.o adsk_dcm.o adsk_di.o \ + adsk_scp.o adsk_xfd.o at_dis.o autil.o \ + cdsk.o cdsk_atr.o cdsk_dcm.o cdsk_scp.o \ + cdsk_xfd.o cfile.o cgenfile.o cobj.o cprefile.o \ + cdisk.o cfs.o cfs_b2b.o cfs_boot.o cfs_dos2.o \ + cfs_dos3.o cfs_dosm.o cfs_doss.o cfs_howf.o \ + cfs_jonw.o cfs_kboo.o cfs_robc.o + +COPT=-O2 +CXX=g++ +CXXFLAGS=$(COPT) -D__CDISK_SAVE__ -D__CDISK_WRITE__ + +all: libjindroush.a + +libjindroush.a: $(OBJS) + ar r libjindroush.a $(OBJS) + ranlib libjindroush.a + +clean: + rm -f *.o *.a + +%.o : %.cpp + $(CXX) -I../include $(CXXFLAGS) -c $< diff --git a/jindroush/lib/adsk.cpp b/jindroush/lib/adsk.cpp new file mode 100644 index 0000000..e5d0b5a --- /dev/null +++ b/jindroush/lib/adsk.cpp @@ -0,0 +1,319 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "adsk.h" + +ADisk::ADisk() : CDisk() +{ + #ifdef _MEMORY_DUMP_ + printf( "ADisk constructed: %p\n", this ); + #endif +} + +ADisk::~ADisk() +{ + #ifdef _MEMORY_DUMP_ + printf( "ADisk destructed: %p\n", this ); + #endif +} + +void GuessClassicSizes( int iSectors, int iSectorSize, DISK_GEOMETRY* pGeometry ) +{ + pGeometry->iSides = 1; + pGeometry->iBytesPerSector = iSectorSize; + + pGeometry->iTracks = 1; + pGeometry->iSectorsPerTrack = iSectors; + + switch( iSectors ) + { + case 720: + switch( iSectorSize ) + { + case 0x80: + pGeometry->iTracks = 40; + pGeometry->iSectorsPerTrack = 18; + break; + + case 0x100: + pGeometry->iTracks = 40; + pGeometry->iSectorsPerTrack = 18; + break; + } + break; + + case 1040: + pGeometry->iTracks = 40; + pGeometry->iSectorsPerTrack = 26; + break; + + } + +} + +void ForceClassicSize( DISK_GEOMETRY* pGeometry ) +{ + ForceClassicSize( pGeometry->iSectors, pGeometry->iBytesPerSector, pGeometry ); +} + +void ForceClassicSize( int iSectors, int iSectorSize, DISK_GEOMETRY* pGeometry ) +{ + pGeometry->iSides = 1; + pGeometry->iBytesPerSector = iSectorSize; + + pGeometry->iTracks = 1; + pGeometry->iSectorsPerTrack = iSectors; + + switch( iSectorSize ) + { + case 0x80: + if ( iSectors <= 720 ) + { + pGeometry->iTracks = 40; + pGeometry->iSectorsPerTrack = 18; + } + else if ( ( iSectors > 720 ) && ( iSectors <= 1040 ) ) + { + pGeometry->iTracks = 40; + pGeometry->iSectorsPerTrack = 26; + } + else + { + GuessClassicSizes( iSectors, iSectorSize, pGeometry ); + } + break; + + case 0x100: + default: + if ( iSectors <= 720 ) + { + pGeometry->iTracks = 40; + pGeometry->iSectorsPerTrack = 18; + } + else + { + GuessClassicSizes( iSectors, iSectorSize, pGeometry ); + } + break; + } + + switch( iSectors ) + { + case 720: + switch( iSectorSize ) + { + case 0x80: + pGeometry->iTracks = 40; + pGeometry->iSectorsPerTrack = 18; + break; + + case 0x100: + pGeometry->iTracks = 40; + pGeometry->iSectorsPerTrack = 18; + break; + } + break; + + case 1040: + pGeometry->iTracks = 40; + pGeometry->iSectorsPerTrack = 26; + break; + + } + +} + + +//returns ptr to disk type name +char* GetDiskTypeName( DISK_TYPE disktype ) +{ + switch( disktype ) + { + case DISK_XFD: + return "XFD"; + + case DISK_ATR: + return "ATR"; + + case DISK_XFDb: + return "XFDb"; + + case DISK_ATRb: + return "ATRb"; + + case DISK_DCM: + return "DCM"; + + case DISK_SCP: + return "SCP"; + + case DISK_DI: + return "DI"; + + default: + return "None"; + } +} + +//returns ptr to disk type extension +char* GetDiskTypeExt( DISK_TYPE disktype ) +{ + switch( disktype ) + { + case DISK_XFD: + case DISK_XFDb: + return "xfd"; + + case DISK_ATR: + case DISK_ATRb: + return "atr"; + + case DISK_DCM: + return "dcm"; + + case DISK_SCP: + return "scp"; + + case DISK_DI: + return "di"; + + default: + return "xxx"; + } +} + +#ifndef __CDISK_NOLOAD__ +DISKINIT_RETCODE InitializeDisk( ADisk** ppDisk, DISK_TYPE disktype, char* szFname, BOOL bVerbose, BOOL bRepair, BOOL bRepairAuto ) +{ + switch( disktype ) + { + case DISK_ATR: + *ppDisk = new CAtr(); + break; + + case DISK_SCP: + *ppDisk = new CScp(); + break; + + case DISK_DCM: + *ppDisk = new CDcm(); + break; + + case DISK_XFD: + *ppDisk = new CXfd(); + break; + + case DISK_DI: + *ppDisk = new CDi(); + break; + + default: + if ( bVerbose ) + fprintf( stderr, "Invalid disk type specified!\n" ); + return DI_RET_CANT_CONTINUE; + } + + if ( !*ppDisk ) + { + if ( bVerbose ) + fprintf( stderr, "Can't initialize disk driver!\n" ); + return DI_RET_CONTINUE; + } + + if ( !(*ppDisk)->Load( szFname, bRepair, bRepairAuto ) ) + { + int iError = (*ppDisk)->GetErrorCode(); + + DISKINIT_RETCODE ret = DI_RET_CONTINUE; + + switch( iError ) + { + case CATR_FORMAT_VIOLATED: + case CXFD_FORMAT_VIOLATED: + case CDISK_ERROR_CANT_OPEN: + case CDCM_FORMAT_VIOLATED: + case CSCP_FORMAT_VIOLATED: + case CDI_FORMAT_VIOLATED: + ret = DI_RET_CANT_CONTINUE; + break; + } + + if ( bVerbose || ( ret == DI_RET_CANT_CONTINUE ) ) + { + printf( "Input file '%s' ", szFname ); + printf( "(%s)\n", GetDiskTypeName( disktype ) ); + printf( "Load failed because:\n%s\n", (*ppDisk)->GetLastError() ); + } + if ( ret != DI_RET_OK ) + { + delete *ppDisk; + return ret; + } + } + + return DI_RET_OK; +} +#endif + +BOOL ADisk::ReadSectors( void* pBuf, int iStartSec, int iSecs ) +{ + while( iSecs ) + { + if ( !ReadSector( pBuf, iStartSec ) ) + return FALSE; + + pBuf = (BYTE*)pBuf + ( ( iStartSec <= 3 ) ? 0x80 :m_geometry.iBytesPerSector ); + iStartSec++; + iSecs--; + } + + return TRUE; +} + +BOOL ADisk::WriteSectors( int iStartSec, void* pBuf, int iSecs ) +{ + while( iSecs ) + { + if ( !WriteSector( iStartSec, pBuf ) ) + return FALSE; + + pBuf = (BYTE*)pBuf + ( ( iStartSec <= 3 ) ? 0x80 :m_geometry.iBytesPerSector ); + iStartSec++; + iSecs--; + } + + return TRUE; +} + +int ADisk::GetBootSectorCount() +{ + return m_pbtMemory[ 1 ]; +} + +int ADisk::GetBootSectorSize() +{ + int iSecCount = GetBootSectorCount(); + + if ( iSecCount > 3 ) + return ( ( iSecCount - 3 ) * GetSectorSize() + 0x180 ); + else + return iSecCount * 0x80; +} + +BOOL ADisk::GetBootSector( BYTE* pbtData ) +{ + return ReadSectors( pbtData, 1, GetBootSectorCount() ); +} + diff --git a/jindroush/lib/adsk_atr.cpp b/jindroush/lib/adsk_atr.cpp new file mode 100644 index 0000000..ad7dce6 --- /dev/null +++ b/jindroush/lib/adsk_atr.cpp @@ -0,0 +1,483 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "adsk_atr.h" +#include "autil.h" +#include "cfile.h" + +#define ATR_MAGIC 0x0296 + +typedef struct +{ + WORD wMagic; + WORD wPars; + WORD wSecSize; + BYTE btParHigh; + DWORD dwCRC; + DWORD dwUnused; + BYTE btFlags; + +} ATRhead; + +#define ATR_HEAD_LEN 0x10 + +CAtr::CAtr() : ADisk() +{ + #ifdef _MEMORY_DUMP_ + printf( "CAtr constructed: %p\n", this ); + #endif +} + +CAtr::~CAtr() +{ + #ifdef _MEMORY_DUMP_ + printf( "CAtr destructed: %p\n", this ); + #endif +} + +typedef enum +{ + LOAD_OK, + LOAD_BAD_DD_1, + LOAD_BAD_DD_2, + LOAD_BAD_DD_3, + LOAD_PAD +} LOAD_VARIANT; + +#ifndef __CDISK_NOLOAD__ +BOOL CAtr::Load( char* szFname, BOOL bRepair, BOOL bRepairAuto ) +{ + LOAD_VARIANT load_method = LOAD_OK; + + m_iErrorCode = 0; + + int iFirstSectorsSize = 0x80; + + CFile cf; + + if ( !cf.Open( szFname ) ) + { + sprintf( m_szLastError, "ATR: Can't open '%s'", szFname ); + m_iErrorCode = CDISK_ERROR_CANT_OPEN; + return FALSE; + } + + strcpy( m_szFname, szFname ); + + ATRhead head; + + head.wMagic = cf.readLEw(); + head.wPars = cf.readLEw(); + head.wSecSize = cf.readLEw(); + head.btParHigh = cf.readb(); + head.dwCRC = cf.readLEdw(); + head.dwUnused = cf.readLEdw(); + head.btFlags = cf.readb(); + + if ( head.wMagic != ATR_MAGIC ) + { + sprintf( m_szLastError, "ATR: File '%s' is not an ATR file!", szFname ); + return FALSE; + } + + LONG lFileLen = cf.GetLength(); + cf.Seek( ATR_HEAD_LEN, SEEK_SET ); + + switch( head.wSecSize ) + { + case 0x80: + case 0x100: + break; + + default: + { + sprintf( m_szLastError, "ATR: Invalid sector size: %04X", head.wSecSize ); + return FALSE; + } + } + + DWORD dwPars = head.wPars | ( head.btParHigh << 16 ); + + int iSectors = ( dwPars * 0x10 ) / head.wSecSize; + + //BOOL bReadOnly = (head.btFlags & 1) ? TRUE : FALSE; + + if ( head.wSecSize == 0x100 ) + { + //if ( dwPars % head.wSecSize ) + if ( ( dwPars * 0x10 ) % head.wSecSize ) + { + iSectors = ( ( dwPars * 0x10 - 0x180 ) / head.wSecSize ) + 3; + } + else + { + sprintf( m_szLastError, "ATR: Format violated. First three sectors are not $80 long!" ); + m_iErrorCode = CATR_FORMAT_VIOLATED; + + #ifdef __CDISK_NOREPAIR__ + return FALSE; + #else + if ( !bRepair ) + { + return FALSE; + } + else + { + BYTE abtBuff[ 0x100 ]; + + memset( abtBuff, 0, 0x100 ); + + int iM1zeroes = 3; + int iM2zeroes = 3; + int iM3zeroes = 3; + + cf.Seek( ATR_HEAD_LEN + ( 0x02 - 1 ) * 0x80, SEEK_SET ); + cf.Read( abtBuff, 0x80 ); + + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + iM1zeroes--; + + cf.Seek( ATR_HEAD_LEN + ( 0x04 - 1 ) * 0x80, SEEK_SET ); + cf.Read( abtBuff, 0x80 ); + + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + { + iM1zeroes--; + iM2zeroes--; + } + + cf.Seek( ATR_HEAD_LEN + ( 0x05 - 1 ) * 0x80, SEEK_SET ); + cf.Read( abtBuff, 0x80 ); + + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + iM2zeroes--; + + cf.Seek( ATR_HEAD_LEN + ( 0x06 - 1 ) * 0x80, SEEK_SET ); + cf.Read( abtBuff, 0x80 ); + + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + { + iM1zeroes--; + iM2zeroes--; + } + + cf.Seek( -0x180, SEEK_END ); + cf.Read( abtBuff, 0x80 ); + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + iM3zeroes--; + + cf.Read( abtBuff, 0x80 ); + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + iM3zeroes--; + + cf.Read( abtBuff, 0x80 ); + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + iM3zeroes--; + + if ( !iM1zeroes ) + { + load_method = LOAD_BAD_DD_1; + } + else if ( !iM2zeroes ) + { + load_method = LOAD_BAD_DD_2; + } + else if ( !iM3zeroes ) + { + load_method = LOAD_BAD_DD_3; + } + + if ( !bRepairAuto ) + { + printf( "Invalid DD ATR file encountered.\n" ); + printf( "Choose repair method:\n" ); + printf( "1) Sector, gap, sector, gap, sector, gap, data\n" ); + printf( "2) Three sectors, three empty sectors, data\n" ); + printf( "3) Data, three empty sectors\n" ); + printf( "4) Don't repair\n" ); + + switch( load_method ) + { + case LOAD_BAD_DD_1: + printf( "(Method 1 looks best)\n" ); + break; + + case LOAD_BAD_DD_2: + printf( "(Method 2 looks best)\n" ); + break; + + case LOAD_BAD_DD_3: + printf( "(Method 3 looks best)\n" ); + break; + + default: + break; + } + + int iMethod; + + printf( "\n" ); + do + { + iMethod = getch() - '0'; + } while( ( iMethod < 1 ) || ( iMethod > 4 ) ); + + switch( iMethod ) + { + case 1: + load_method = LOAD_BAD_DD_1; + break; + case 2: + load_method = LOAD_BAD_DD_2; + break; + case 3: + load_method = LOAD_BAD_DD_3; + break; + default: + case 4: + return FALSE; + break; + } + } + else + { + if ( load_method == LOAD_OK ) + load_method = LOAD_BAD_DD_1; + } + + + cf.Seek( ATR_HEAD_LEN, SEEK_SET ); + + switch( load_method ) + { + case LOAD_BAD_DD_1: + case LOAD_BAD_DD_2: + case LOAD_BAD_DD_3: + iFirstSectorsSize = 0x100; + break; + + default: + break; + + } + + } //end of repair + + #endif + } + } + + LONG lTotalComputedLen = (LONG) ( ( iSectors - 3 ) * head.wSecSize + ATR_HEAD_LEN + 3 * iFirstSectorsSize ); + + if ( lTotalComputedLen != lFileLen ) + { + sprintf( m_szLastError, "ATR: Invalid length! %08lX <> %08lX (%08X)", lTotalComputedLen, lFileLen, iSectors ); + m_iErrorCode = CATR_FORMAT_VIOLATED; + + #ifdef __CDISK_NOREPAIR__ + return FALSE; + #else + if ( !bRepair || ( load_method != LOAD_OK ) ) + return FALSE; + else + { + if ( !bRepairAuto ) + { + printf( "ATR with invalid length encountered.\n" ); + printf( "Should be: $%08lX. Is: $%08lX.\n", lTotalComputedLen, lFileLen ); + printf( "Choose:\n" ); + printf( "1) Change file length (shorten/pad)\n" ); + printf( "2) Change header info\n" ); + printf( "3) Don't repair\n" ); + + int iMethod; + + do + { + iMethod = getch() - '0'; + } while( ( iMethod < 1 ) || ( iMethod > 3 ) ); + + switch( iMethod ) + { + case 1: + load_method = LOAD_PAD; + break; + + case 2: + load_method = LOAD_OK; + if ( lFileLen > 0x180 ) + { + iSectors = ( ( lFileLen - 0x180 ) / head.wSecSize ) + 3; + } + else + { + iSectors = lFileLen / 0x80; + } + + break; + + default: + case 3: + return FALSE; + break; + } + } + else + { + if ( load_method == LOAD_OK ) + load_method = LOAD_PAD; + } + + } + #endif + + } + + DISK_GEOMETRY dg; + + GuessClassicSizes( iSectors, head.wSecSize, &dg ); + + if ( !Format( &dg ) ) + return FALSE; + + BYTE abtBuff[ 0x100 ]; + memset( abtBuff, 0, 0x100 ); + + for( int i = 0; i < iSectors; i++ ) + { + switch( load_method ) + { + default: + case LOAD_OK: + cf.Read( abtBuff, ( i < 3 ) ? 0x80 : head.wSecSize ); + break; + + case LOAD_PAD: + memset( abtBuff, 0, 0x100 ); + cf.Read( abtBuff, ( i < 3 ) ? 0x80 : head.wSecSize ); + break; + + case LOAD_BAD_DD_1: + if ( i < 3 ) + { + cf.Read( abtBuff, 0x80 ); + cf.Seek( 0x80, SEEK_CUR ); + } + else + cf.Read( abtBuff, 0x100 ); + break; + + case LOAD_BAD_DD_2: + if ( i < 3 ) + { + cf.Read( abtBuff, 0x80 ); + + if ( i == 2 ) + cf.Seek( 0x180, SEEK_CUR ); + } + else + cf.Read( abtBuff, 0x100 ); + + break; + + case LOAD_BAD_DD_3: + if ( i < 3 ) + cf.Read( abtBuff, 0x80 ); + else + cf.Read( abtBuff, 0x100 ); + + break; + } + + WriteSector( i + 1, abtBuff ); + } + + cf.Close(); + return TRUE; + +} + +#endif + +#ifdef __CDISK_SAVE__ + +BOOL CAtr::Save( char* szOutFile, BOOL bOverWrite ) +{ + CFile cf; + + if ( !bOverWrite && !access( szOutFile, F_OK ) ) + { + sprintf( m_szLastError, "ATR: File already exists! '%s'", szOutFile ); + return FALSE; + } + + if ( !cf.Create( szOutFile ) ) + { + sprintf( m_szLastError, "ATR: Can't create '%s'", szOutFile ); + return FALSE; + } + + ATRhead head; + memset( &head, 0, sizeof( ATRhead ) ); + + head.wMagic = ATR_MAGIC; + head.wSecSize = m_geometry.iBytesPerSector; + + BOOL bReadOnly = TRUE; + head.btFlags |= ( bReadOnly ) ? 0x01 : 0x00; + + DWORD dwLength = 0; + + dwLength = 0x180 + ( m_geometry.iSectors - 3 ) * m_geometry.iBytesPerSector; + + dwLength >>= 4; + + head.wPars = dwLength & 0xFFFF; + head.btParHigh = dwLength >> 0x10; + + cf.writeLEw( head.wMagic ); + cf.writeLEw( head.wPars ); + cf.writeLEw( head.wSecSize ); + cf.writeb( head.btParHigh ); + cf.writeLEdw( head.dwCRC ); + cf.writeLEdw( head.dwUnused ); + cf.writeb( head.btFlags ); + + BYTE abtBuff[ 0x100 ]; + + for( WORD i = 1; i <= m_geometry.iSectors; i++ ) + { + ReadSector( abtBuff, i ); + + int iToWrite = ( i <= 3 ) ? 0x80: m_geometry.iBytesPerSector; + + int iWritten; + + if ( !cf.Write( abtBuff, iToWrite, &iWritten ) || ( iToWrite != iWritten ) ) + { + sprintf( m_szLastError, "ATR: Can't write!" ); + cf.Close(); + unlink( szOutFile ); + return FALSE; + + } + } + + cf.Close(); + + return TRUE; +} + +#endif //__CDISK_WRITE__ diff --git a/jindroush/lib/adsk_dcm.cpp b/jindroush/lib/adsk_dcm.cpp new file mode 100644 index 0000000..d664761 --- /dev/null +++ b/jindroush/lib/adsk_dcm.cpp @@ -0,0 +1,764 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "adsk_dcm.h" +#include "cfile.h" +#include "cprefile.h" +#include "autil.h" + +//#define _DCM_DUMP_ + +#define DCM_CHANGE_BEGIN 0x41 //Change only start of sector +#define DCM_DOS_SECTOR 0x42 //128 byte compressed sector +#define DCM_COMPRESSED 0x43 //Uncompressed/compressed pairs +#define DCM_CHANGE_END 0x44 //Change only end of sector +#define DCM_PASS_END 0x45 //End of pass +#define DCM_SAME_AS_BEFORE 0x46 //Same as previous non-zero +#define DCM_UNCOMPRESSED 0x47 //Uncompressed sector + +#define DCM_HEADER_SINGLE 0xFA +#define DCM_HEADER_MULTI 0xF9 + +#define DCM_DENSITY_SD 0 //Single density, 90K +#define DCM_DENSITY_DD 1 //Double density, 180K +#define DCM_DENSITY_ED 2 //Enhanced density, 130K + +CDcm::CDcm() : ADisk() +{ + #ifdef _MEMORY_DUMP_ + printf( "CDcm constructed: %p\n", this ); + #endif +} + +CDcm::~CDcm() +{ + #ifdef _MEMORY_DUMP_ + printf( "CDcm destructed: %p\n", this ); + #endif +} + +#ifndef __CDISK_NOLOAD__ +BOOL CDcm::Load( char* szFname, BOOL, BOOL ) +{ + BYTE btArcType = 0; //Block type for first block + BYTE btBlkType; //Current block type + + m_bAlreadyFormatted = FALSE; + m_bLastPass = FALSE; + m_wCurrentSector = 0; + + CFile cfo; + CPreFile cf; + + if ( !cfo.Open( szFname ) ) + { + sprintf( m_szLastError, "DCM: Can't open '%s'", szFname ); + m_iErrorCode = CDISK_ERROR_CANT_OPEN; + return FALSE; + } + + strcpy( m_szFname, szFname ); + + cf.Open( &cfo, 20 ); + + m_lFileLength = cf.GetLength(); + + for(;;) //outpass + { + if ( cf.Tell() >= m_lFileLength ) + { + if ( ( !m_bLastPass ) && ( btArcType == DCM_HEADER_MULTI ) ) + { + sprintf( m_szLastError,"DCM: Multi-part archive error.\n" \ + "To process these files, you must first combine the files into a single file." ); + m_iErrorCode = CDCM_FORMAT_VIOLATED; + return FALSE; + } + } + + btArcType = cf.readb(); + + switch( btArcType ) + { + case DCM_HEADER_MULTI: + case DCM_HEADER_SINGLE: + if ( !DecodeRecFA( cf ) ) + return FALSE; + break; + + default: + sprintf( m_szLastError, "DCM: %02X is an unknown header block.\n", btArcType ); + return FALSE; + } + + for(;;) //inpass + { + btBlkType = cf.readb(); + + if ( btBlkType == DCM_PASS_END ) + break; + + if ( cf.Tell() >= m_lFileLength ) + { + sprintf( m_szLastError, "DCM: EOF before end block." ); + m_iErrorCode = CDCM_FORMAT_VIOLATED; + return FALSE; + } + + BOOL bRes = TRUE; + + *m_szLastError = '\0'; + switch( btBlkType & 0x7F ) + { + case DCM_CHANGE_BEGIN: + bRes = DecodeRec41( cf ); + break; + + case DCM_DOS_SECTOR: + bRes = DecodeRec42( cf ); + break; + + case DCM_COMPRESSED: + bRes = DecodeRec43( cf ); + break; + + case DCM_CHANGE_END: + bRes = DecodeRec44( cf ); + break; + + case DCM_SAME_AS_BEFORE: + //not needed + //bRes = DecodeRec46( cf ); + break; + + case DCM_UNCOMPRESSED: + bRes = DecodeRec47( cf ); + break; + + default: + { + switch( btBlkType ) + { + case DCM_HEADER_MULTI: + case DCM_HEADER_SINGLE: + sprintf( m_szLastError, "DCM: Trying to start section but last section never had " + "an end section block."); + break; + + default: + sprintf( m_szLastError, "DCM: %02X is an unknown block type. File may be " + "corrupt.",btBlkType); + break; + } + + m_iErrorCode = CDCM_FORMAT_VIOLATED; + return FALSE; + } + } + + if ( !bRes ) + { + sprintf( m_szLastError, "DCM: Block %02X decode error!", btBlkType ); + m_iErrorCode = CDCM_FORMAT_VIOLATED; + return FALSE; + } + + if ( !WriteSector( m_wCurrentSector, m_abtCurrBuff ) ) + return FALSE; + + if ( btBlkType & 0x80 ) + m_wCurrentSector++; + else + m_wCurrentSector = cf.readLEw(); + + } //infinite for (inpass) + + //End block + if ( m_bLastPass ) + break; + + } //infinite for (outpass) + + cf.Close(); + cfo.Close(); + return TRUE; + +} + +BOOL CDcm::DecodeRec41( CGenFile& cf ) +{ + #ifdef _DCM_DUMP_ + printf( "dec41: %08lX\n", cf.Tell() - 1 ); + #endif + + int iOffset = cf.readb(); + BYTE* pbt = m_abtCurrBuff + iOffset; + + do + { + *( pbt-- ) = cf.readb(); + } while( iOffset-- ); + + return TRUE; +} + +BOOL CDcm::DecodeRec42( CGenFile& cf ) +{ + #ifdef _DCM_DUMP_ + printf( "dec42: %08lX\n", cf.Tell() - 1 ); + #endif + + sprintf( m_szLastError, "DCM: Record type 0x42 untested. Uncomment?" ); + return FALSE; + + //TODO: uncomment later! + //cf.Read( m_abtCurrBuff + 123, 5 ); + //memset( m_abtCurrBuff, m_abtCurrBuff[ 123 ], 123 ); + //return TRUE; +} + +BOOL CDcm::DecodeRec43( CGenFile& cf ) +{ + #ifdef _DCM_DUMP_ + printf( "dec43: %08lX\n", cf.Tell() - 1 ); + #endif + + BYTE* pbtP = m_abtCurrBuff; + BYTE* pbtE; + + BYTE* pbtEnd = m_abtCurrBuff + m_iSectorSize; + + do + { + //uncompressed string + if ( pbtP != m_abtCurrBuff ) + pbtE = m_abtCurrBuff + ReadOffset( cf ); + else + pbtE = m_abtCurrBuff + cf.readb(); + + if ( pbtE < pbtP ) + return FALSE; + + #ifdef _DCM_DUMP_ + printf( "dec43: uncst: %p %p %ld\n", pbtP, pbtE, pbtE - pbtP ); + #endif + + if ( pbtE != pbtP ) + { + cf.Read( pbtP, pbtE - pbtP ); + pbtP = pbtE; + } + + if ( pbtP >= pbtEnd ) + break; + + //rle compressed string + pbtE = m_abtCurrBuff + ReadOffset( cf ); + BYTE c = cf.readb(); + + #ifdef _DCM_DUMP_ + printf( "dec43: cst: %p %p %ld\n", pbtP, pbtE, pbtE - pbtP ); + #endif + + if ( pbtE < pbtP ) + return FALSE; + + memset( pbtP, c, pbtE - pbtP ); + pbtP = pbtE; + + } while( pbtP < pbtEnd ); + + return TRUE; +} + +BOOL CDcm::DecodeRec44( CGenFile& cf ) +{ + #ifdef _DCM_DUMP_ + printf( "dec44: %08lX\n", cf.Tell() - 1 ); + #endif + + int iOffset = ReadOffset( cf ); + + cf.Read( m_abtCurrBuff + iOffset, m_iSectorSize - iOffset ); + + return TRUE; +} + +BOOL CDcm::DecodeRec46( CGenFile& cf ) +{ + #ifdef _DCM_DUMP_ + printf( "dec46: %08lX\n", cf.Tell() - 1 ); + #endif + + return TRUE; +} + +BOOL CDcm::DecodeRec47( CGenFile& cf ) +{ + #ifdef _DCM_DUMP_ + printf( "dec47: %08lX\n", cf.Tell() - 1 ); + #endif + + //TODO: Is this TRUE or NOT??? + //cf.Read( m_abtCurrBuff, ( m_wCurrentSector < 4 ? 128 : m_iSectorSize ) ); + + cf.Read( m_abtCurrBuff, m_iSectorSize ); + return TRUE; +} + +BOOL CDcm::DecodeRecFA( CGenFile& cf ) +{ + #ifdef _DCM_DUMP_ + printf( "decFA: %08lX\n", cf.Tell() - 1 ); + #endif + + BYTE btPom = cf.readb(); + + BYTE btDensity = ( btPom >> 5 ) & 0x03; + //BYTE btPass = btPom & 0x1F; + m_bLastPass = ( btPom & 0x80 ) ? TRUE : FALSE; + + int iSpT; + int iTracks; + + switch( btDensity ) + { + case DCM_DENSITY_SD: + iTracks = 40; + iSpT = 18; + m_iSectorSize = 128; + break; + + case DCM_DENSITY_DD: + iTracks = 40; + iSpT = 18; + m_iSectorSize = 256; + break; + + case DCM_DENSITY_ED: + iTracks = 40; + iSpT = 26; + m_iSectorSize = 128; + break; + + default: + sprintf( m_szLastError,"DCM: Density type unknown (%02X)\n", btDensity ); + return FALSE; + } + + if ( !m_bAlreadyFormatted ) + { + DISK_GEOMETRY dg; + dg.iSides = 1; + dg.iTracks = iTracks; + dg.iSectorsPerTrack = iSpT; + dg.iBytesPerSector = m_iSectorSize; + + if ( !Format( &dg ) ) + return FALSE; + + m_bAlreadyFormatted = TRUE; + } + + m_wCurrentSector = cf.readLEw(); + + return TRUE; +} + +WORD CDcm::ReadOffset( CGenFile& cf ) +{ + BYTE bt = cf.readb(); + + return( bt ? bt : 256 ); +} +#endif + +#ifdef __CDISK_SAVE__ + +BOOL CDcm::Save( char* szOutFile, BOOL bOverWrite ) +{ + if ( !bOverWrite && !access( szOutFile, F_OK ) ) + { + sprintf( m_szLastError, "DCM: File already exists! '%s'", szOutFile ); + return FALSE; + } + + int iDensity = -1; + m_iSectorSize = m_geometry.iBytesPerSector; + + if ( m_iSectorSize == 0x80 ) + { + if ( m_geometry.iTracks == 40 ) + { + if ( m_geometry.iSectorsPerTrack == 18 ) + iDensity = DCM_DENSITY_SD; + + if ( m_geometry.iSectorsPerTrack == 26 ) + iDensity = DCM_DENSITY_ED; + } + } + + if ( m_iSectorSize == 0x100 ) + { + if ( ( m_geometry.iSectorsPerTrack == 18 ) && + ( m_geometry.iTracks == 40 ) ) + iDensity = DCM_DENSITY_DD; + } + + if ( iDensity == - 1 ) + { + sprintf( m_szLastError, "DCM: Can't work with such density!" ); + return FALSE; + } + + int iPass = 1; + + m_pbtPass = new BYTE [ 0x6500 ]; + + CFile cf; + + if ( !cf.Create( szOutFile ) ) + { + sprintf( m_szLastError, "DCM: Can't create '%s'", szOutFile ); + delete [] m_pbtPass; + return FALSE; + } + + int iFirstSector = 0; + int iPrevSector = 0; + int iCurrentSector = 1; + + memset( m_abtPrevBuff, 0, m_iSectorSize ); + + EncodeRecFA( FALSE, iPass, iDensity, iFirstSector ); + + //here should be other compression + + while( iCurrentSector <= m_geometry.iSectors ) + { + iFirstSector = 0; + + while( ( m_pbtCurr - m_pbtPass ) < 0x5EFD ) + { + if ( iCurrentSector > m_geometry.iSectors ) + break; + + ReadSector( m_abtCurrBuff, iCurrentSector ); + + BOOL bSkip = IsBlockEmpty( m_abtCurrBuff, m_iSectorSize ); + + //first non empty sector is marked as first, what a surprise! :) + if ( !bSkip && !iFirstSector ) + { + iFirstSector = iCurrentSector; + iPrevSector = iCurrentSector; + } + + //if just skipped, increment sector + if ( bSkip ) + { + iCurrentSector++; + } + else + { + //if there is a gap, write sector number + if ( ( iCurrentSector - iPrevSector ) > 1 ) + { + *( m_pbtCurr++ ) = iCurrentSector; + *( m_pbtCurr++ ) = iCurrentSector >> 8; + } + else + { + //else mark previous record + *m_pbtLastRec |= 0x80; + } + + //first sector could be encoded with only some data + if ( iCurrentSector == iFirstSector ) + EncodeRec( TRUE ); + else + { + //if are same, encode as record 46 + if ( !memcmp( m_abtPrevBuff, m_abtCurrBuff, m_iSectorSize ) ) + EncodeRec46(); + else + EncodeRec( FALSE ); + } + + //store this sector as previous + memcpy( m_abtPrevBuff, m_abtCurrBuff, m_iSectorSize ); + + //and move pointers + iPrevSector = iCurrentSector; + iCurrentSector++; + } + + } + + //mark previous sector + *m_pbtLastRec |= 0x80; + + //encode end + EncodeRec45(); + + BYTE* pEnd = m_pbtCurr; + + //change beginning block + if ( iCurrentSector > m_geometry.iSectors ) + EncodeRecFA( TRUE, iPass, iDensity, iFirstSector ); + else + EncodeRecFA( FALSE, iPass, iDensity, iFirstSector ); + + //and write whole pass + + if ( ( pEnd - m_pbtPass ) > 0x6000 ) + { + sprintf( m_szLastError, "DCM: Internal error! Pass too long!" ); + delete [] m_pbtPass; + cf.Close(); + unlink( szOutFile ); + return FALSE; + } + + if ( !cf.Write( m_pbtPass, pEnd - m_pbtPass ) ) + { + sprintf( m_szLastError, "DCM: Can't write!" ); + delete [] m_pbtPass; + cf.Close(); + unlink( szOutFile ); + return FALSE; + } + + iPass++; + } + + cf.Close(); + + delete [] m_pbtPass; + + return TRUE; +} + +void CDcm::EncodeRecFA( BOOL bLast, int iPass, int iDensity, int iFirstSec ) +{ + m_pbtCurr = m_pbtPass; + + #ifdef _DCM_DUMP_ + printf( "ERFA: %08lX\n", m_pbtCurr - m_pbtPass ); + #endif + + m_pbtLastRec = m_pbtCurr; + + BYTE btType = bLast ? 0x80 : 0; + + btType |= ( iDensity & 3 ) << 5; + + btType |= ( iPass & 0x1F ); + + *( m_pbtCurr++ ) = DCM_HEADER_SINGLE; + *( m_pbtCurr++ ) = btType; + *( m_pbtCurr++ ) = iFirstSec; + *( m_pbtCurr++ ) = iFirstSec >> 8; + +} + +void CDcm::EncodeRec45() +{ + #ifdef _DCM_DUMP_ + printf( "ER45: %08lX\n", m_pbtCurr - m_pbtPass ); + #endif + + m_pbtLastRec = m_pbtCurr; + *( m_pbtCurr++ ) = DCM_PASS_END; +} + +void CDcm::EncodeRec46() +{ + #ifdef _DCM_DUMP_ + printf( "ER46: %08lX\n", m_pbtCurr - m_pbtPass ); + #endif + + m_pbtLastRec = m_pbtCurr; + *( m_pbtCurr++ ) = DCM_SAME_AS_BEFORE; +} + +void CDcm::EncodeRec( BOOL bIsFirstSector ) +{ + #ifdef _DCM_DUMP_ + printf( "ER: %08lX\n", m_pbtCurr - m_pbtPass ); + #endif + + m_pbtLastRec = m_pbtCurr; + + BYTE abtBuff41[ 0x300 ]; + BYTE abtBuff43[ 0x300 ]; + BYTE abtBuff44[ 0x300 ]; + BYTE* abtBuff47 = m_abtCurrBuff; + + int iEnd41 = 0x300; + int iEnd43 = 0x300; + int iEnd44 = 0x300; + + int iBestMethod = DCM_UNCOMPRESSED; + int iBestEnd = m_iSectorSize; + BYTE* pbtBest = abtBuff47; + + EncodeRec43( abtBuff43, &iEnd43, m_abtCurrBuff, m_iSectorSize ); + + if ( !bIsFirstSector ) + { + EncodeRec41( abtBuff41, &iEnd41, m_abtCurrBuff, m_abtPrevBuff, m_iSectorSize ); + EncodeRec44( abtBuff44, &iEnd44, m_abtCurrBuff, m_abtPrevBuff, m_iSectorSize ); + } + + if ( iEnd41 < iBestEnd ) + { + iBestMethod = DCM_CHANGE_BEGIN; + iBestEnd = iEnd41; + pbtBest = abtBuff41; + } + + if ( iEnd43 < iBestEnd ) + { + iBestMethod = DCM_COMPRESSED; + iBestEnd = iEnd43; + pbtBest = abtBuff43; + } + + if ( iEnd44 < iBestEnd ) + { + iBestMethod = DCM_CHANGE_END; + iBestEnd = iEnd44; + pbtBest = abtBuff44; + } + + *( m_pbtCurr++ ) = iBestMethod; + memcpy( m_pbtCurr, pbtBest, iBestEnd ); + m_pbtCurr += iBestEnd; +} + +void CDcm::EncodeRec41( BYTE* pbtDest, int* piDestLen, BYTE* pbtSrc, BYTE* pbtSrcOld, int iSrcLen ) +{ + BYTE* pbtS = pbtSrc + iSrcLen - 1; + pbtSrcOld += iSrcLen - 1; + + BYTE* pbtD = pbtDest; + + for( int i = 0; i < iSrcLen; i++ ) + { + if ( *( pbtS-- ) != * ( pbtSrcOld-- ) ) + break; + } + + pbtS++; + + *( pbtD++ ) = pbtS - pbtSrc; + + int iBytes = pbtS - pbtSrc + 1; + + while( iBytes-- ) + { + *( pbtD++ ) = *( pbtS-- ); + } + + *piDestLen = pbtD - pbtDest; +} + +void CDcm::EncodeRec43( BYTE* pbtDest, int* piDestLen, BYTE* pbtSrc, int iSrcLen ) +{ + BYTE* pbtEnd = pbtSrc + iSrcLen; + BYTE* pbtCur = pbtSrc; + + BYTE* pbtD = pbtDest; + + while( pbtCur < pbtEnd ) + { + BOOL bFound = FALSE; + + for( BYTE* pbtNow = pbtCur; pbtNow < ( pbtEnd - 2 ); pbtNow++ ) + { + + if ( ( *pbtNow == *(pbtNow+1) ) && ( *pbtNow == *(pbtNow+2) ) ) + { + int iUnc = pbtNow - pbtCur; + + *( pbtD ++ ) = pbtNow - pbtSrc; + if ( iUnc ) + { + memcpy( pbtD, pbtCur, iUnc ); + pbtD += iUnc; + } + + BYTE bt = *pbtNow; + BYTE*p; + for( p = pbtNow + 1; p < pbtEnd; p++ ) + { + if ( *p != bt ) + break; + } + + if ( p > pbtEnd ) + p = pbtEnd; + + *( pbtD++ ) = p - pbtSrc; + *( pbtD++ ) = bt; + + pbtCur = p; + bFound = TRUE; + break; + } + } + + if ( ( pbtCur >= pbtEnd - 2 ) || !bFound ) + { + if ( pbtCur < pbtEnd ) + { + *( pbtD++ ) = iSrcLen; + memcpy( pbtD, pbtCur, pbtEnd - pbtCur ); + pbtD += pbtEnd - pbtCur; + } + + break; + } + + } + + *piDestLen = pbtD - pbtDest; +} + +void CDcm::EncodeRec44( BYTE* pbtDest, int* piDestLen, BYTE* pbtSrc, BYTE* pbtSrcOld, int iSrcLen ) +{ + BYTE* pbtS = pbtSrc; + BYTE* pbtEnd = pbtSrc + iSrcLen; + + BYTE* pbtD = pbtDest; + + for( int i = 0; i < iSrcLen; i++ ) + { + if ( *( pbtS++ ) != * ( pbtSrcOld++ ) ) + break; + } + + pbtS--; + + *( pbtD++ ) = pbtS - pbtSrc; + memcpy( pbtD, pbtS, pbtEnd - pbtS ); + pbtD += pbtEnd - pbtS; + + *piDestLen = pbtD - pbtDest; +} + +#endif // __CDISK_SAVE__ + diff --git a/jindroush/lib/adsk_di.cpp b/jindroush/lib/adsk_di.cpp new file mode 100644 index 0000000..b49bb9d --- /dev/null +++ b/jindroush/lib/adsk_di.cpp @@ -0,0 +1,271 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "adsk_di.h" +#include "autil.h" +#include "cfile.h" + +BYTE di_crc( BYTE* pbt, int iLen ) +{ + WORD crc = 0; + + while( iLen-- ) + { + crc += *( pbt++ ); + if( crc >= 0x100 ) + crc -= 0xFF; + } + + return crc; +} + +CDi::CDi() : ADisk() +{ + #ifdef _MEMORY_DUMP_ + printf( "CDi constructed: %p\n", this ); + #endif +} + +CDi::~CDi() +{ + #ifdef _MEMORY_DUMP_ + printf( "CDi destructed: %p\n", this ); + #endif +} + +#ifndef __CDISK_NOLOAD__ +BOOL CDi::Load( char* szFname, BOOL bRepair, BOOL bRepairAuto ) +{ + m_iErrorCode = 0; + + CFile cf; + if ( !cf.Open( szFname ) ) + { + sprintf( m_szLastError, "DI: Can't open '%s'", szFname ); + m_iErrorCode = CDISK_ERROR_CANT_OPEN; + return FALSE; + } + + strcpy( m_szFname, szFname ); + + WORD wMagic = cf.readLEw(); + + if ( wMagic != 18756 ) //'DI' + { + sprintf( m_szLastError, "DI: File '%s' is not an DI file!", szFname ); + return FALSE; + } + + BYTE btVerLo = cf.readb(); + BYTE btVerHi = cf.readb(); + + if( ( btVerLo != 0x20 ) || ( btVerHi != 0x02 ) ) + { + sprintf( m_szLastError, "DI: The file '%s' has strange version!\n" + "This program can't work with it now.\n" + "Send the file for the analysis.", szFname ); + m_iErrorCode = CDI_FORMAT_VIOLATED; + return FALSE; + } + + int iMax = 200; + while( iMax-- ) + { + if( ! cf.readb() ) + break; + } + + if( !iMax ) + { + sprintf( m_szLastError, "DI: Runaway in header ('%s')", szFname ); + m_iErrorCode = CDI_FORMAT_VIOLATED; + return FALSE; + } + + //todo: this need the documentation! Is it number of sides? + //BYTE btUnk1 = + cf.readb(); + + BYTE btTracks = cf.readb(); + WORD wSectorsPerTrack = cf.readBEw(); + + //todo: are these the flags? + //WORD wUnk2 = + //cf.readBEw(); + BYTE btSides = cf.readb() + 1; + cf.readb(); + + WORD wSectorSize = cf.readBEw(); + + //todo: and what about this? + //BYTE btUnk3 = + cf.readb(); + + switch( wSectorSize ) + { + case 0x80: + case 0x100: + break; + + default: + { + sprintf( m_szLastError, "DI: Invalid sector size: %04X", wSectorSize ); + m_iErrorCode = CDI_FORMAT_VIOLATED; + return FALSE; + } + } + + DISK_GEOMETRY dg; + + dg.iSides = btSides; + dg.iTracks = btTracks; + dg.iSectorsPerTrack = wSectorsPerTrack; + dg.iBytesPerSector = wSectorSize; + + if ( !Format( &dg ) ) + return FALSE; + + BYTE abtBuff[ 0x100 ]; + memset( abtBuff, 0, 0x100 ); + + int iSectors = m_geometry.iSectors; + + BYTE* pBuf = new BYTE[ iSectors ]; + cf.Read( pBuf, iSectors ); + + BYTE* p = pBuf; + + for( int i = 0; i < iSectors; i++ ) + { + if( *p ) + { + int iSecSize = ( i < 3 ) ? 0x80 : wSectorSize; + + int iRead; + + cf.Read( abtBuff, iSecSize, &iRead ); + + if ( iRead != iSecSize ) + { + sprintf( m_szLastError, "DI: Read error. File truncated?" ); + delete [] pBuf; + cf.Close(); + m_iErrorCode = CDI_FORMAT_VIOLATED; + return FALSE; + } + + BYTE crc = di_crc( abtBuff, iSecSize ); + + if( *p != crc ) + { + sprintf( m_szLastError, "DI: Sector checksum failed: Sector %d Given: %02X Computed: %02X", i + 1, *p, crc ); + delete [] pBuf; + cf.Close(); + m_iErrorCode = CDI_FORMAT_VIOLATED; + return FALSE; + } + + WriteSector( i + 1, abtBuff ); + } + p++; + } + + delete [] pBuf; + + cf.Close(); + return TRUE; + +} + +#endif + +#ifdef __CDISK_SAVE__ + +char szDIhd[] = "Jindroush's DI class v1.00"; +//char szDIhd[] = "XL/ST-link 2.2.0› "; + +BOOL CDi::Save( char* szOutFile, BOOL bOverWrite ) +{ + if( ( m_geometry.iTracks > 0xFF ) || + ( m_geometry.iSectorsPerTrack > 0xFFFF ) || + ( m_geometry.iSides > 2 ) ) + { + sprintf( m_szLastError, "DI: Can't create such file! Is it possible? :-)" ); + return FALSE; + } + + CFile cf; + + if ( !bOverWrite && !access( szOutFile, F_OK ) ) + { + sprintf( m_szLastError, "DI: File already exists! '%s'", szOutFile ); + return FALSE; + } + + if ( !cf.Create( szOutFile ) ) + { + sprintf( m_szLastError, "DI: Can't create '%s'", szOutFile ); + return FALSE; + } + + cf.writeb( 'D' ); + cf.writeb( 'I' ); + cf.writeb( 0x20 ); + cf.writeb( 0x02 ); + + cf.Write( szDIhd, strlen( szDIhd ) + 1 ); + + cf.writeb( 1 ); + cf.writeb( m_geometry.iTracks ); + cf.writeBEw( m_geometry.iSectorsPerTrack ); + cf.writeb( m_geometry.iSides - 1 ); + cf.writeb( 0 ); + cf.writeBEw( m_geometry.iBytesPerSector ); + cf.writeb( 0 ); + + BYTE abtBuff[ 0x100 ]; + memset( abtBuff, 0, 0x100 ); + + BYTE* pBuf = new BYTE[ m_geometry.iSectors ]; + + for( int i = 0; i < m_geometry.iSectors; i++ ) + { + int iSecSize = ( i < 3 ) ? 0x80 : m_geometry.iBytesPerSector; + + ReadSector( abtBuff, i + 1 ); + pBuf[ i ] = di_crc( abtBuff, iSecSize ); + } + + cf.Write( pBuf, m_geometry.iSectors ); + + for( int i = 0; i < m_geometry.iSectors; i++ ) + { + int iSecSize = ( i < 3 ) ? 0x80 : m_geometry.iBytesPerSector; + + ReadSector( abtBuff, i + 1 ); + if( pBuf[ i ] || !IsBlockEmpty( abtBuff, iSecSize ) ) + { + cf.Write( abtBuff, iSecSize ); + } + } + + delete [] pBuf; + + cf.Close(); + + return TRUE; +} + +#endif //__CDISK_WRITE__ diff --git a/jindroush/lib/adsk_scp.cpp b/jindroush/lib/adsk_scp.cpp new file mode 100644 index 0000000..51d3dae --- /dev/null +++ b/jindroush/lib/adsk_scp.cpp @@ -0,0 +1,281 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "adsk_scp.h" +#include "autil.h" +#include "cfile.h" + +#define SCP_MAGIC 0xFDFD + +CScp::CScp() : ADisk() +{ + #ifdef _MEMORY_DUMP_ + printf( "CScp constructed: %p\n", this ); + #endif +} + +CScp::~CScp() +{ + #ifdef _MEMORY_DUMP_ + printf( "CScp destructed: %p\n", this ); + #endif +} + +#ifndef __CDISK_NOLOAD__ +BOOL CScp::Load( char* szFname, BOOL, BOOL ) +{ + WORD wMagic; + BYTE btSectorSize; + BYTE btTracks; + BYTE btSectorsPerTrack; + + CFile cf; + + if( !cf.Open( szFname ) ) + { + sprintf( m_szLastError, "SCP: Can't open '%s'", szFname ); + return FALSE; + } + + strcpy( m_szFname, szFname ); + + wMagic = cf.readLEw(); + + if ( wMagic != SCP_MAGIC ) + { + sprintf( m_szLastError, "SCP: File '%s' is not an SCP file!", szFname ); + return FALSE; + } + + btSectorSize = cf.readb(); + btTracks = cf.readb(); + btSectorsPerTrack = cf.readb(); + + int iSectorSize; + + switch( btSectorSize ) + { + case 0x80: + iSectorSize = 0x80; + break; + + case 0x00: + iSectorSize = 0x100; + break; + + default: + { + sprintf( m_szLastError, "SCP: Invalid sector size: %02X", btSectorSize ); + return FALSE; + } + } + + DISK_GEOMETRY dg; + dg.iSides = 1; + dg.iTracks = btTracks; + dg.iSectorsPerTrack = btSectorsPerTrack; + dg.iBytesPerSector = iSectorSize; + + if ( !Format( &dg ) ) + return FALSE; + + BYTE *pbtTable = new BYTE [ btSectorsPerTrack * btTracks ]; + + if ( ! pbtTable ) + { + sprintf( m_szLastError, "SCP: Not enough memory for sector table!" ); + return FALSE; + } + + if ( !cf.Read( pbtTable, btSectorsPerTrack * btTracks ) ) + { + sprintf( m_szLastError, "SCP: Can't read sector table!" ); + return FALSE; + } + + BYTE abtBuff[ 0x100 ]; + memset( abtBuff, 0, 0x100 ); + + BYTE* pbtPtr = pbtTable; + + for( int iTrack = 0; iTrack < btTracks; iTrack++ ) + { + for( int iSector = 0; iSector < btSectorsPerTrack; iSector++ ) + { + if ( *pbtPtr ) + { + int iNowRead; + + if ( !iTrack && ( iSector < 3 ) ) + iNowRead = 0x80; + else + iNowRead = iSectorSize; + + int iReallyRead; + + if ( !cf.Read( abtBuff, iNowRead, &iReallyRead ) || ( iNowRead != iReallyRead ) ) + { + delete [] pbtTable; + sprintf( m_szLastError, "SCP: Image broken!" ); + return FALSE; + } + + if ( !WriteSector( *pbtPtr + iTrack* btSectorsPerTrack, abtBuff ) ) + { + delete [] pbtTable; + return FALSE; + } + + } + pbtPtr++; + } + + } + + delete [] pbtTable; + + cf.Close(); + return TRUE; + +} +#endif + +#ifdef __CDISK_SAVE__ + +BOOL CScp::Save( char* szOutFile, BOOL bOverWrite ) +{ + if ( !bOverWrite && !access( szOutFile, F_OK ) ) + { + sprintf( m_szLastError, "SCP: File already exists! '%s'", szOutFile ); + return FALSE; + } + + BYTE btSize; + BYTE btTracks; + BYTE btSpT; + + switch ( m_geometry.iBytesPerSector ) + { + case 0x80: + btSize = 0x80; + break; + + case 0x100: + default: + btSize = 0x00; + break; + } + + BOOL bGood = FALSE; + + btTracks = m_geometry.iTracks; + btSpT = m_geometry.iSectorsPerTrack; + + if ( ( m_geometry.iTracks == 40 ) && ( m_geometry.iSectorsPerTrack == 18 ) ) + bGood = TRUE; + + if ( ( m_geometry.iTracks == 40 ) && ( m_geometry.iSectorsPerTrack == 26 ) ) + bGood = TRUE; + + if ( !bGood ) + { + sprintf( m_szLastError, "SCP: Can't export, because of invalid disk size!" ); + return FALSE; + } + + int iMapSize = m_geometry.iTracks * m_geometry.iSectorsPerTrack; + + BYTE* pMap = new BYTE [ iMapSize ]; + + if ( !pMap ) + { + sprintf( m_szLastError, "SCP: Can't allocate memory for map!" ); + return FALSE; + } + + memset( pMap, 0, iMapSize ); + + + CFile cf; + + if ( !cf.Create( szOutFile ) ) + { + sprintf( m_szLastError, "SCP: Can't create '%s'", szOutFile ); + delete [] pMap; + return FALSE; + } + + WORD wMagic = SCP_MAGIC; + + cf.writeLEw( wMagic ); + cf.writeb( btSize ); + cf.writeb( btTracks ); + cf.writeb( btSpT ); + + cf.Seek( iMapSize, SEEK_CUR ); + + BYTE abtBuff[ 0x100 ]; + + int iSectors = m_geometry.iSectors; + + for( int i = 0; i < iSectors; i++ ) + { + if ( !ReadSector( abtBuff, i + 1 ) ) + { + delete [] pMap; + cf.Close(); + unlink( szOutFile ); + return FALSE; + } + + int iBytesNow = ( i < 3 ) ? 0x80 : m_geometry.iBytesPerSector; + + if ( !IsBlockEmpty( abtBuff, iBytesNow ) ) + { + int iWritten; + if ( !cf.Write( abtBuff, iBytesNow, &iWritten ) || ( iBytesNow != iWritten ) ) + { + sprintf( m_szLastError, "SCP: Error writing to '%s'", szOutFile ); + delete [] pMap; + cf.Close( ); + unlink( szOutFile ); + return FALSE; + + } + + pMap[ i ] = ( i % btSpT ) + 1; + } + } + + cf.Seek( 5, SEEK_SET ); + + if ( !cf.Write( pMap, iMapSize ) ) + { + sprintf( m_szLastError, "SCP: Can't write!" ); + delete [] pMap; + cf.Close( ); + unlink( szOutFile ); + return FALSE; + + } + + delete [] pMap; + + cf.Close(); + + return TRUE; +} + +#endif //__CDISK_SAVE__ diff --git a/jindroush/lib/adsk_xfd.cpp b/jindroush/lib/adsk_xfd.cpp new file mode 100644 index 0000000..870a59b --- /dev/null +++ b/jindroush/lib/adsk_xfd.cpp @@ -0,0 +1,327 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "adsk_xfd.h" +#include "autil.h" +#include "cfile.h" + +CXfd::CXfd() : ADisk() +{ + #ifdef _MEMORY_DUMP_ + printf( "CXfd constructed: %p\n", this ); + #endif +} + +CXfd::~CXfd() +{ + #ifdef _MEMORY_DUMP_ + printf( "CXfd destructed: %p\n", this ); + #endif +} + +typedef enum +{ + LOAD_OK, + LOAD_BAD_DD_1, + LOAD_BAD_DD_2, + LOAD_BAD_DD_3 +} LOAD_VARIANT; + +#ifndef __CDISK_NOLOAD__ +BOOL CXfd::Load( char* szFname, BOOL bRepair, BOOL bRepairAuto ) +{ + LOAD_VARIANT load_method = LOAD_OK; + + CFile cf; + + if ( !cf.Open( szFname ) ) + { + sprintf( m_szLastError, "XFD: Can't open '%s'", szFname ); + return FALSE; + } + + strcpy( m_szFname, szFname ); + + LONG lFileLen = cf.GetLength(); + + int iSecs; + int iSecSize; + + if ( lFileLen % 0x80 ) + { + sprintf( m_szLastError, "XFD: Strange length!" ); + cf.Close(); + return FALSE; + } + + if ( ( lFileLen / 0x80 ) > 1040 ) + { + iSecSize = 0x100; + + iSecs = ( ( lFileLen - 0x180 ) / 0x100 ) + 3; + } + else + { + iSecSize = 0x80; + iSecs = lFileLen / 0x80; + } + + if ( ( ( ( iSecs - 3 ) * iSecSize ) + 0x180 ) != lFileLen ) + { + sprintf( m_szLastError, "XFD: Format violated: (%08lX != %08X)", lFileLen, iSecs * iSecSize ); + m_iErrorCode = CXFD_FORMAT_VIOLATED; + + #ifdef __CDISK_NOREPAIR__ + cf.Close(); + return FALSE; + + #else + if ( !bRepair ) + { + cf.Close(); + return FALSE; + } + else + { + iSecs = lFileLen / iSecSize; + BYTE abtBuff[ 0x100 ]; + + memset( abtBuff, 0, 0x100 ); + + int iM1zeroes = 3; + int iM2zeroes = 3; + int iM3zeroes = 3; + + cf.Seek( ( 0x02 - 1 ) * 0x80, SEEK_SET ); + cf.Read( abtBuff, 0x80 ); + + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + iM1zeroes--; + + cf.Seek( ( 0x04 - 1 ) * 0x80, SEEK_SET ); + cf.Read( abtBuff, 0x80 ); + + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + { + iM1zeroes--; + iM2zeroes--; + } + + cf.Seek( ( 0x05 - 1 ) * 0x80, SEEK_SET ); + cf.Read( abtBuff, 0x80 ); + + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + iM2zeroes--; + + cf.Seek( ( 0x06 - 1 ) * 0x80, SEEK_SET ); + cf.Read( abtBuff, 0x80 ); + + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + { + iM1zeroes--; + iM2zeroes--; + } + + cf.Seek( -0x180, SEEK_END ); + cf.Read( abtBuff, 0x80 ); + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + iM3zeroes--; + + cf.Read( abtBuff, 0x80 ); + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + iM3zeroes--; + + cf.Read( abtBuff, 0x80 ); + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + iM3zeroes--; + + if ( !iM1zeroes ) + { + load_method = LOAD_BAD_DD_1; + } + else if ( !iM2zeroes ) + { + load_method = LOAD_BAD_DD_2; + } + else if ( !iM3zeroes ) + { + load_method = LOAD_BAD_DD_3; + } + + if ( !bRepairAuto ) + { + printf( "Invalid DD ATR file encountered.\n" ); + printf( "Choose repair method:\n" ); + printf( "1) Sector, gap, sector, gap, sector, gap, data\n" ); + printf( "2) Three sectors, three empty sectors, data\n" ); + printf( "3) Data, three empty sectors\n" ); + printf( "4) Don't repair\n" ); + + switch( load_method ) + { + case LOAD_BAD_DD_1: + printf( "(Method 1 looks best)\n" ); + break; + + case LOAD_BAD_DD_2: + printf( "(Method 2 looks best)\n" ); + break; + + case LOAD_BAD_DD_3: + printf( "(Method 3 looks best)\n" ); + break; + + default: + break; + } + + int iMethod; + + printf( "\n" ); + do + { + iMethod = getch() - '0'; + } while( ( iMethod < 1 ) || ( iMethod > 4 ) ); + + if ( iMethod == 4 ) + { + cf.Close(); + return FALSE; + } + } + else + { + if ( load_method == LOAD_OK ) + load_method = LOAD_BAD_DD_1; + } + + cf.Seek( 0, SEEK_SET ); + } + #endif + } + + DISK_GEOMETRY dg; + + GuessClassicSizes( iSecs, iSecSize, &dg ); + + if ( !Format( &dg ) ) + { + cf.Close(); + return FALSE; + } + + BYTE abtBuff[ 0x100 ]; + memset( abtBuff, 0, 0x100 ); + + for( int i = 0; i < iSecs; i++ ) + { + switch( load_method ) + { + default: + case LOAD_OK: + cf.Read( abtBuff, ( i < 3 ) ? 0x80 : iSecSize ); + break; + + case LOAD_BAD_DD_1: + if ( i < 3 ) + { + cf.Read( abtBuff, 0x80 ); + cf.Seek( 0x80, SEEK_CUR ); + } + else + cf.Read( abtBuff, 0x100 ); + break; + + case LOAD_BAD_DD_2: + if ( i < 3 ) + { + cf.Read( abtBuff, 0x80 ); + + if ( i == 2 ) + cf.Seek( 0x180, SEEK_CUR ); + } + else + cf.Read( abtBuff, 0x100 ); + + break; + + case LOAD_BAD_DD_3: + if ( i < 3 ) + cf.Read( abtBuff, 0x80 ); + else + cf.Read( abtBuff, 0x100 ); + + break; + } + + if ( !WriteSector( i + 1, abtBuff ) ) + { + cf.Close(); + return FALSE; + } + } + + cf.Close(); + return TRUE; + +} +#endif + + +#ifdef __CDISK_SAVE__ + +BOOL CXfd::Save( char* szOutFile, BOOL bOverWrite ) +{ + CFile cf; + + if ( !bOverWrite && !access( szOutFile, F_OK ) ) + { + sprintf( m_szLastError, "XFD: File already exists! '%s'", szOutFile ); + return FALSE; + } + + if ( !cf.Create( szOutFile ) ) + { + sprintf( m_szLastError, "XFD: Can't create '%s'", szOutFile ); + return FALSE; + } + + BYTE abtBuff[ 0x100 ]; + + for( WORD i = 1; i <= m_geometry.iSectors; i++ ) + { + if ( !ReadSector( abtBuff, i ) ) + return FALSE; + + int iToWrite = ( i <= 3 ) ? 0x80: m_geometry.iBytesPerSector; + + int iWritten; + + if ( !cf.Write( abtBuff, iToWrite, &iWritten ) || ( iWritten != iToWrite ) ) + { + sprintf( m_szLastError, "XFD: Can't write!" ); + cf.Close(); + unlink( szOutFile ); + return FALSE; + } + + } + + cf.Close(); + + return TRUE; +} + +#endif //__CDISK_SAVE__ diff --git a/jindroush/lib/at_dis.cpp b/jindroush/lib/at_dis.cpp new file mode 100644 index 0000000..e799258 --- /dev/null +++ b/jindroush/lib/at_dis.cpp @@ -0,0 +1,1201 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "jintypes.h" +#include "at_dis.h" + +struct +{ + char *instruct; + int length; + int branch; + int immed; + int write; +} instable[] = +{ + { "BRK", 0, 0, 1, 0 }, //00 + { "ORA\t(*,X)", 1, 0, 0, 0 }, //01 + { "???", 0, 0, 1, 0 }, //02 + { "???", 0, 0, 1, 0 }, //03 + { "???", 0, 0, 1, 0 }, //04 + { "ORA\t*", 1, 0, 0, 0 }, //05 + { "ASL\t*", 1, 0, 0, 0 }, //06 + { "???", 0, 0, 1, 0 }, //07 + { "PHP", 0, 0, 1, 0 }, //08 + { "ORA\t#*", 1, 0, 1, 0 }, //09 + { "ASL", 0, 0, 1, 0 }, //0A + { "???", 0, 0, 1, 0 }, //0B + { "???", 0, 0, 1, 0 }, //0C + { "ORA\t*", 2, 0, 0, 0 }, //0D + { "ASL\t*", 2, 0, 0, 0 }, //0E + { "???", 0, 0, 1, 0 }, //0F + { "BPL\t$*", 1, 1, 1, 0 }, //10 + { "ORA\t(*),Y", 1, 0, 0, 0 }, //11 + { "???", 0, 0, 1, 0 }, //12 + { "???", 0, 0, 1, 0 }, //13 + { "???", 0, 0, 1, 0 }, //14 + { "ORA\t*,X", 1, 0, 0, 0 }, //15 + { "ASL\t*,X", 1, 0, 0, 0 }, //16 + { "???", 0, 0, 1, 0 }, //17 + { "CLC", 0, 0, 1, 0 }, //18 + { "ORA\t*,Y", 2, 0, 0, 0 }, //19 + { "???", 0, 0, 1, 0 }, //1A + { "???", 0, 0, 1, 0 }, //1B + { "???", 0, 0, 1, 0 }, //1C + { "ORA\t*,X", 2, 0, 0, 0 }, //1D + { "ASL\t*,X", 2, 0, 0, 0 }, //1E + { "???", 0, 0, 1, 0 }, //1F + { "JSR\t*", 2, 0, 0, 0 }, //20 + { "AND\t(*,X)", 1, 0, 0, 0 }, //21 + { "???", 0, 0, 1, 0 }, //22 + { "???", 0, 0, 1, 0 }, //23 + { "BIT\t*", 1, 0, 0, 0 }, //24 + { "AND\t*", 1, 0, 0, 0 }, //25 + { "ROL\t*", 1, 0, 0, 0 }, //26 + { "???", 0, 0, 1, 0 }, //27 + { "PLP", 0, 0, 1, 0 }, //28 + { "AND\t#*", 1, 0, 1, 0 }, //29 + { "ROL", 0, 0, 1, 0 }, //2A + { "???", 0, 0, 1, 0 }, //2B + { "BIT\t*", 2, 0, 0, 0 }, //2C + { "AND\t*", 2, 0, 0, 0 }, //2D + { "ROL\t*", 2, 0, 0, 0 }, //2E + { "???", 0, 0, 1, 0 }, //2F + { "BMI\t$*", 1, 1, 1, 0 }, //30 + { "AND\t(*),Y", 1, 0, 0, 0 }, //31 + { "???", 0, 0, 1, 0 }, //32 + { "???", 0, 0, 1, 0 }, //33 + { "???", 0, 0, 1, 0 }, //34 + { "AND\t*,X", 1, 0, 0, 0 }, //35 + { "ROL\t*,X", 1, 0, 0, 0 }, //36 + { "???", 0, 0, 1, 0 }, //37 + { "SEC", 0, 0, 1, 0 }, //38 + { "AND\t*,Y", 2, 0, 0, 0 }, //39 + { "???", 0, 0, 1, 0 }, //3A + { "???", 0, 0, 1, 0 }, //3B + { "???", 0, 0, 1, 0 }, //3C + { "AND\t*,X", 2, 0, 0, 0 }, //3D + { "ROL\t*,X", 2, 0, 0, 0 }, //3E + { "???", 0, 0, 1, 0 }, //3F + { "RTI", 0, 0, 1, 0 }, //40 + { "EOR\t(*,X)", 1, 0, 0, 0 }, //41 + { "???", 0, 0, 1, 0 }, //42 + { "???", 0, 0, 1, 0 }, //43 + { "???", 0, 0, 1, 0 }, //44 + { "EOR\t*", 1, 0, 0, 0 }, //45 + { "LSR\t*", 1, 0, 0, 0 }, //46 + { "???", 0, 0, 1, 0 }, //47 + { "PHA", 0, 0, 1, 0 }, //48 + { "EOR\t#*", 1, 0, 1, 0 }, //49 + { "LSR", 0, 0, 1, 0 }, //4A + { "???", 0, 0, 1, 0 }, //4B + { "JMP\t*", 2, 0, 0, 0 }, //4C + { "EOR\t*", 2, 0, 0, 0 }, //4D + { "LSR\t*", 2, 0, 0, 0 }, //4E + { "???", 0, 0, 1, 0 }, //4F + { "BVC\t$*", 1, 1, 1, 0 }, //50 + { "EOR\t(*),Y", 1, 0, 0, 0 }, //51 + { "???", 0, 0, 1, 0 }, //52 + { "???", 0, 0, 1, 0 }, //53 + { "???", 0, 0, 1, 0 }, //54 + { "EOR\t*,X", 1, 0, 0, 0 }, //55 + { "LSR\t*,X", 1, 0, 0, 0 }, //56 + { "???", 0, 0, 1, 0 }, //57 + { "CLI", 0, 0, 1, 0 }, //58 + { "EOR\t*,Y", 2, 0, 0, 0 }, //59 + { "???", 0, 0, 1, 0 }, //5A + { "???", 0, 0, 1, 0 }, //5B + { "???", 0, 0, 1, 0 }, //5C + { "EOR\t*,X", 2, 0, 0, 0 }, //5D + { "LSR\t*,X", 2, 0, 0, 0 }, //5E + { "???", 0, 0, 1, 0 }, //5F + { "RTS", 0, 0, 1, 0 }, //60 + { "ADC\t(*,X)", 1, 0, 0, 0 }, //61 + { "???", 0, 0, 1, 0 }, //62 + { "???", 0, 0, 1, 0 }, //63 + { "???", 0, 0, 1, 0 }, //64 + { "ADC\t*", 1, 0, 0, 0 }, //65 + { "ROR\t*", 1, 0, 0, 0 }, //66 + { "???", 0, 0, 1, 0 }, //67 + { "PLA", 0, 0, 1, 0 }, //68 + { "ADC\t#*", 1, 0, 1, 0 }, //69 + { "ROR", 0, 0, 1, 0 }, //6A + { "???", 0, 0, 1, 0 }, //6B + { "JMP\t(*)", 2, 0, 0, 0 }, //6C + { "ADC\t*", 2, 0, 0, 0 }, //6D + { "ROR\t*", 2, 0, 0, 0 }, //6E + { "???", 0, 0, 1, 0 }, //6F + { "BVS\t$*", 1, 1, 1, 0 }, //70 + { "ADC\t(*),Y", 1, 0, 0, 0 }, //71 + { "???", 0, 0, 1, 0 }, //72 + { "???", 0, 0, 1, 0 }, //73 + { "???", 0, 0, 1, 0 }, //74 + { "ADC\t*,X", 1, 0, 0, 0 }, //75 + { "ROR\t*,X", 1, 0, 0, 0 }, //76 + { "???", 0, 0, 1, 0 }, //77 + { "SEI", 0, 0, 1, 0 }, //78 + { "ADC\t*,Y", 2, 0, 0, 0 }, //79 + { "???", 0, 0, 1, 0 }, //7A + { "???", 0, 0, 1, 0 }, //7B + { "SKW", 1, 0, 1, 0 }, //7C + { "ADC\t*,X", 2, 0, 1, 0 }, //7D + { "ROR\t*,X", 2, 0, 1, 0 }, //7E + { "???", 0, 0, 1, 0 }, //7F + { "???", 0, 0, 1, 0 }, //80 + { "STA\t(*,X)", 1, 0, 0, 1 }, //81 + { "???", 0, 0, 1, 0 }, //82 + { "???", 0, 0, 1, 0 }, //83 + { "STY\t*", 1, 0, 0, 1 }, //84 + { "STA\t*", 1, 0, 0, 1 }, //85 + { "STX\t*", 1, 0, 0, 1 }, //86 + { "???", 0, 0, 1, 0 }, //87 + { "DEY", 0, 0, 1, 0 }, //88 + { "???", 0, 0, 1, 0 }, //89 + { "TXA", 0, 0, 1, 0 }, //8A + { "???", 0, 0, 1, 0 }, //8B + { "STY\t*", 2, 0, 0, 1 }, //8C + { "STA\t*", 2, 0, 0, 1 }, //8D + { "STX\t*", 2, 0, 0, 1 }, //8E + { "???", 0, 0, 1, 0 }, //8F + { "BCC\t$*", 1, 1, 1, 0 }, //90 + { "STA\t(*),Y", 1, 0, 0, 1 }, //91 + { "???", 0, 0, 1, 0 }, //92 + { "???", 0, 0, 1, 0 }, //93 + { "STY\t*,X", 1, 0, 0, 1 }, //94 + { "STA\t*,X", 1, 0, 0, 1 }, //95 + { "STX\t*,Y", 1, 0, 0, 1 }, //96 + { "???", 0, 0, 1, 0 }, //97 + { "TYA", 0, 0, 1, 0 }, //98 + { "STA\t*,Y", 2, 0, 0, 1 }, //99 + { "TXS", 0, 0, 1, 0 }, //9A + { "???", 0, 0, 1, 0 }, //9B + { "???", 0, 0, 1, 0 }, //9C + { "STA\t*,X", 2, 0, 0, 1 }, //9D + { "???", 0, 0, 1, 0 }, //9E + { "???", 0, 0, 1, 0 }, //9F + { "LDY\t#*", 1, 0, 1, 0 }, //A0 + { "LDA\t(*,X)", 1, 0, 0, 0 }, //A1 + { "LDX\t#*", 1, 0, 1, 0 }, //A2 + { "???", 0, 0, 1, 0 }, //A3 + { "LDY\t*", 1, 0, 0, 0 }, //A4 + { "LDA\t*", 1, 0, 0, 0 }, //A5 + { "LDX\t*", 1, 0, 0, 0 }, //A6 + { "???", 0, 0, 1, 0 }, //A7 + { "TAY", 0, 0, 1, 0 }, //A8 + { "LDA\t#*", 1, 0, 1, 0 }, //A9 + { "TAX", 0, 0, 1, 0 }, //AA + { "???", 0, 0, 1, 0 }, //AB + { "LDY\t*", 2, 0, 0, 0 }, //AC + { "LDA\t*", 2, 0, 0, 0 }, //AD + { "LDX\t*", 2, 0, 0, 0 }, //AE + { "???", 0, 0, 1, 0 }, //AF + { "BCS\t$*", 1, 1, 1, 0 }, //B0 + { "LDA\t(*),Y", 1, 0, 0, 0 }, //B1 + { "???", 0, 0, 1, 0 }, //B2 + { "???", 0, 0, 1, 0 }, //B3 + { "LDY\t*,X", 1, 0, 0, 0 }, //B4 + { "LDA\t*,X", 1, 0, 0, 0 }, //B5 + { "LDX\t*,Y", 1, 0, 0, 0 }, //B6 + { "???", 0, 0, 1, 0 }, //B7 + { "CLV", 0, 0, 1, 0 }, //B8 + { "LDA\t*,Y", 2, 0, 0, 0 }, //B9 + { "TSX", 0, 0, 1, 0 }, //BA + { "???", 0, 0, 1, 0 }, //BB + { "LDY\t*,X", 2, 0, 0, 0 }, //BC + { "LDA\t*,X", 2, 0, 0, 0 }, //BD + { "LDX\t*,Y", 2, 0, 0, 0 }, //BE + { "???", 0, 0, 1, 0 }, //BF + { "CPY\t#*", 1, 0, 1, 0 }, //C0 + { "CMP\t(*,X)", 1, 0, 0, 0 }, //C1 + { "???", 0, 0, 1, 0 }, //C2 + { "???", 0, 0, 1, 0 }, //C3 + { "CPY\t*", 1, 0, 0, 0 }, //C4 + { "CMP\t*", 1, 0, 0, 0 }, //C5 + { "DEC\t*", 1, 0, 0, 0 }, //C6 + { "???", 0, 0, 1, 0 }, //C7 + { "INY", 0, 0, 1, 0 }, //C8 + { "CMP\t#*", 1, 0, 1, 0 }, //C9 + { "DEX", 0, 0, 1, 0 }, //CA + { "???", 0, 0, 1, 0 }, //CB + { "CPY\t*", 2, 0, 0, 0 }, //CC + { "CMP\t*", 2, 0, 0, 0 }, //CD + { "DEC\t*", 2, 0, 0, 0 }, //CE + { "???", 0, 0, 1, 0 }, //CF + { "BNE\t$*", 1, 1, 1, 0 }, //D0 + { "CMP\t(*),Y", 1, 0, 0, 0 }, //D1 + { "???", 0, 0, 1, 0 }, //D2 + { "???", 0, 0, 1, 0 }, //D3 + { "???", 0, 0, 1, 0 }, //D4 + { "CMP\t*,X", 1, 0, 0, 0 }, //D5 + { "DEC\t*,X", 1, 0, 0, 0 }, //D6 + { "???", 0, 0, 1, 0 }, //D7 + { "CLD", 0, 0, 1, 0 }, //D8 + { "CMP\t*,Y", 2, 0, 0, 0 }, //D9 + { "???", 0, 0, 1, 0 }, //DA + { "???", 0, 0, 1, 0 }, //DB + { "???", 0, 0, 1, 0 }, //DC + { "CMP\t*,X", 2, 0, 0, 0 }, //DD + { "DEC\t*,X", 2, 0, 0, 0 }, //DE + { "???", 0, 0, 1, 0 }, //DF + { "CPX\t#*", 1, 0, 1, 0 }, //E0 + { "SBC\t(*,X)", 1, 0, 0, 0 }, //E1 + { "???", 0, 0, 1, 0 }, //E2 + { "???", 0, 0, 1, 0 }, //E3 + { "CPX\t*", 1, 0, 0, 0 }, //E4 + { "SBC\t*", 1, 0, 0, 0 }, //E5 + { "INC\t*", 1, 0, 0, 0 }, //E6 + { "???", 0, 0, 1, 0 }, //E7 + { "INX", 0, 0, 1, 0 }, //E8 + { "SBC\t#*", 1, 0, 1, 0 }, //E9 + { "NOP", 0, 0, 1, 0 }, //EA + { "???", 0, 0, 1, 0 }, //EB + { "CPX\t*", 2, 0, 0, 0 }, //EC + { "SBC\t*", 2, 0, 0, 0 }, //ED + { "INC\t*", 2, 0, 0, 0 }, //EE + { "???", 0, 0, 1, 0 }, //EF + { "BEQ\t$*", 1, 1, 1, 0 }, //F0 + { "SBC\t(*),Y", 1, 0, 0, 0 }, //F1 + { "???", 0, 0, 1, 0 }, //F2 + { "???", 0, 0, 1, 0 }, //F3 + { "???", 0, 0, 1, 0 }, //F4 + { "SBC\t*,X", 1, 0, 0, 0 }, //F5 + { "INC\t*,X", 1, 0, 0, 0 }, //F6 + { "???", 0, 0, 1, 0 }, //F7 + { "SED", 0, 0, 1, 0 }, //F8 + { "SBC\t*,Y", 2, 0, 0, 0 }, //F9 + { "???", 0, 0, 1, 0 }, //FA + { "???", 0, 0, 1, 0 }, //FB + { "???", 0, 0, 1, 0 }, //FC + { "SBC\t*,X", 2, 0, 0, 0 }, //FD + { "INC\t*,X", 2, 0, 0, 0 }, //FE + { "???", 0, 0, 1, 0 }, //FF + { "\0", 0, 0, 1, 0 } +}; + +typedef struct +{ + char* name; + WORD addr; +} symtable_rec; + +symtable_rec symtable[] = { + { "NGFLAG", 0x0001 }, + { "CASINI", 0x0002 }, + { "CASINI+1", 0x0003 }, + { "RAMLO", 0x0004 }, + { "RAMLO+1", 0x0005 }, + { "TRAMSZ", 0x0006 }, + { "CMCMD", 0x0007 }, + { "WARMST", 0x0008 }, + { "BOOT", 0x0009 }, + { "DOSVEC", 0x000A }, + { "DOSVEC+1", 0x000B }, + { "DOSINI", 0x000C }, + { "DOSINI+1", 0x000D }, + { "APPMHI", 0x000E }, + { "APPMHI+1", 0x000F }, + { "POKMSK", 0x0010 }, + { "BRKKEY", 0x0011 }, + { "RTCLOK", 0x0012 }, + { "RTCLOK+1", 0x0013 }, + { "RTCLOK+2", 0x0014 }, + { "BUFADR", 0x0015 }, + { "BUFADR+1", 0x0016 }, + { "ICCOMT", 0x0017 }, + { "DSKFMS", 0x0018 }, + { "DSKFMS+1", 0x0019 }, + { "DSKUTL", 0x001A }, + { "DSKUTL+1", 0x001B }, + { "ABUFPT", 0x001C }, + { "ABUFPT+1", 0x001D }, + { "ABUFPT+2", 0x001E }, + { "ABUFPT+3", 0x001F }, + { "ICHIDZ", 0x0020 }, + { "ICDNOZ", 0x0021 }, + { "ICCOMZ", 0x0022 }, + { "ICSTAZ", 0x0023 }, + { "ICBALZ", 0x0024 }, + { "ICBAHZ", 0x0025 }, + { "ICPTLZ", 0x0026 }, + { "ICPTHZ", 0x0027 }, + { "ICBLLZ", 0x0028 }, + { "ICBLHZ", 0x0029 }, + { "ICAX1Z", 0x002A }, + { "ICAX2Z", 0x002B }, + { "ICAX3Z", 0x002C }, + { "ICAX4Z", 0x002D }, + { "ICAX5Z", 0x002E }, + { "ICAX6Z", 0x002F }, + { "STATUS", 0x0030 }, + { "CHKSUM", 0x0031 }, + { "BUFRLO", 0x0032 }, + { "BUFRHI", 0x0033 }, + { "BFENLO", 0x0034 }, + { "BFENHI", 0x0035 }, + { "LTEMP", 0x0036 }, + { "LTEMP+1", 0x0037 }, + { "BUFRFL", 0x0038 }, + { "RECVDN", 0x0039 }, + { "XMTDON", 0x003A }, + { "CHKSNT", 0x003B }, + { "NOCKSM", 0x003C }, + { "BPTR", 0x003D }, + { "FTYPE", 0x003E }, + { "FEOF", 0x003F }, + { "FREQ", 0x0040 }, + { "SOUNDR", 0x0041 }, + { "CRITIC", 0x0042 }, + { "FMSZPG", 0x0043 }, + { "FMSZPG+1", 0x0044 }, + { "FMSZPG+2", 0x0045 }, + { "FMSZPG+3", 0x0046 }, + { "FMSZPG+4", 0x0047 }, + { "FMSZPG+5", 0x0048 }, + { "FMSZPG+6", 0x0049 }, + { "ZCHAIN", 0x004A }, + { "ZCHAIN+1", 0x004B }, + { "DSTAT", 0x004C }, + { "ATRACT", 0x004D }, + { "DRKMSK", 0x004E }, + { "COLRSH", 0x004F }, + { "TEMP", 0x0050 }, + { "HOLD1", 0x0051 }, + { "LMARGN", 0x0052 }, + { "RMARGN", 0x0053 }, + { "ROWCRS", 0x0054 }, + { "COLCRS", 0x0055 }, + { "COLCRS+1", 0x0056 }, + { "DINDEX", 0x0057 }, + { "SAVMSC", 0x0058 }, + { "SAVMSC+1", 0x0059 }, + { "OLDROW", 0x005A }, + { "OLDCOL", 0x005B }, + { "OLDCOL+1", 0x005C }, + { "OLDCHR", 0x005D }, + { "OLDADR", 0x005E }, + { "OLDADR+1", 0x005F }, + { "FKDEF", 0x0060 }, + { "FKDEF+1", 0x0061 }, + { "PALNTS", 0x0062 }, + { "LOGCOL", 0x0063 }, + { "ADRESS", 0x0064 }, + { "ADRESS+1", 0x0065 }, + { "MLTTMP", 0x0066 }, + { "MLTTMP+1", 0x0067 }, + { "SAVADR", 0x0068 }, + { "SAVADR+1", 0x0069 }, + { "RAMTOP", 0x006A }, + { "BUFCNT", 0x006B }, + { "BUFSTR", 0x006C }, + { "BUFSTR+1", 0x006D }, + { "BITMSK", 0x006E }, + { "SHFAMT", 0x006F }, + { "ROWAC", 0x0070 }, + { "ROWAC+1", 0x0071 }, + { "COLAC", 0x0072 }, + { "COLAC+1", 0x0073 }, + { "ENDPT", 0x0074 }, + { "ENDPT+1", 0x0075 }, + { "DELTAR", 0x0076 }, + { "DELTAC", 0x0077 }, + { "DELTAC+1", 0x0078 }, + { "KEYDEF", 0x0079 }, + { "KEYDEF+1", 0x007A }, + { "SWPFLG", 0x007B }, + { "HOLDCH", 0x007C }, + { "INSDAT", 0x007D }, + { "COUNTR", 0x007E }, + { "COUNTR+1", 0x007F }, + { "LOMEM", 0x0080 }, + { "LOMEM+1", 0x0081 }, + { "VNTP", 0x0082 }, + { "VNTP+1", 0x0083 }, + { "VNTD", 0x0084 }, + { "VNTD+1", 0x0085 }, + { "VVTP", 0x0086 }, + { "VVTP+1", 0x0087 }, + { "STMTAB", 0x0088 }, + { "STMTAB+1", 0x0089 }, + { "STMCUR", 0x008A }, + { "STMCUR+1", 0x008B }, + { "STARP", 0x008C }, + { "STARP+1", 0x008D }, + { "RUNSTK", 0x008E }, + { "RUNSTK+1", 0x008F }, + { "TOPSTK", 0x0090 }, + { "TOPSTK+1", 0x0091 }, + { "MEOLFLG", 0x0092 }, + { "POKADR", 0x0095 }, + { "POKADR+1", 0x0096 }, + { "DATAD", 0x00B6 }, + { "DATALN", 0x00B7 }, + { "DATALN+1", 0x00B8 }, + { "STOPLN", 0x00BA }, + { "STOPLN+1", 0x00BB }, + { "SAVCUR", 0x00BE }, + { "IOCMD", 0x00C0 }, + { "IODVC", 0x00C1 }, + { "PROMPT", 0x00C2 }, + { "ERRSAVE", 0x00C3 }, + { "COLOUR", 0x00C8 }, + { "PTABW", 0x00C9 }, + { "LOADFLG", 0x00CA }, + { "FR0", 0x00D4 }, + { "FR0+1", 0x00D5 }, + { "FR0+2", 0x00D6 }, + { "FR0+3", 0x00D7 }, + { "FR0+4", 0x00D8 }, + { "FR0+5", 0x00D9 }, + { "FRE", 0x00DA }, + { "FRE+1", 0x00DB }, + { "FRE+2", 0x00DC }, + { "FRE+3", 0x00DD }, + { "FRE+4", 0x00DE }, + { "FRE+5", 0x00DF }, + { "FR1", 0x00E0 }, + { "FR1+1", 0x00E1 }, + { "FR1+2", 0x00E2 }, + { "FR1+3", 0x00E3 }, + { "FR1+4", 0x00E4 }, + { "FR1+5", 0x00E5 }, + { "FR2", 0x00E6 }, + { "FR2+1", 0x00E7 }, + { "FR2+2", 0x00E8 }, + { "FR2+3", 0x00E9 }, + { "FR2+4", 0x00EA }, + { "FR2+5", 0x00EB }, + { "FRX", 0x00EC }, + { "EEXP", 0x00ED }, + { "NSIGN", 0x00EE }, + { "ESIGN", 0x00EF }, + { "FCHRFLG", 0x00F0 }, + { "DIGRT", 0x00F1 }, + { "CIX", 0x00F2 }, + { "INBUFF", 0x00F3 }, + { "INBUFF+1", 0x00F4 }, + { "ZTEMP1", 0x00F5 }, + { "ZTEMP1+1", 0x00F6 }, + { "ZTEMP4", 0x00F7 }, + { "ZTEMP4+1", 0x00F8 }, + { "ZTEMP3", 0x00F9 }, + { "ZTEMP3+1", 0x00FA }, + { "RADFLG", 0x00FB }, + { "FLPTR", 0x00FC }, + { "FLPTR+1", 0x00FD }, + { "FPTR2", 0x00FE }, + { "FPTR2+1", 0x00FF }, + + { "VDSLST", 0x0200 }, + { "VDSLST+1", 0x0201 }, + { "VPRCED", 0x0202 }, + { "VPRCED+1", 0x0203 }, + { "VINTER", 0x0204 }, + { "VINTER+1", 0x0205 }, + { "VBREAK", 0x0206 }, + { "VBREAK+1", 0x0207 }, + { "VKEYBD", 0x0208 }, + { "VKEYBD+1", 0x0209 }, + { "VSERIN", 0x020A }, + { "VSERIN+1", 0x020B }, + { "VSEROR", 0x020C }, + { "VSEROR+1", 0x020D }, + { "VSEROC", 0x020E }, + { "VSEROC+1", 0x020F }, + { "VTIMR1", 0x0210 }, + { "VTIMR1+1", 0x0211 }, + { "VTIMR2", 0x0212 }, + { "VTIMR2+1", 0x0213 }, + { "VTIMR4", 0x0214 }, + { "VTIMR4+1", 0x0215 }, + { "VIMIRQ", 0x0216 }, + { "VIMIRQ+1", 0x0217 }, + { "CDTMV1", 0x0218 }, + { "CDTMV1+1", 0x0219 }, + { "CDTMV2", 0x021A }, + { "CDTMV2+1", 0x021B }, + { "CDTMV3", 0x021C }, + { "CDTMV3+1", 0x021D }, + { "CDTMV4", 0x021E }, + { "CDTMV4+1", 0x021F }, + { "CDTMV5", 0x0220 }, + { "CDTMV5+1", 0x0221 }, + { "VVBLKI", 0x0222 }, + { "VVBLKI+1", 0x0223 }, + { "VVBLKD", 0x0224 }, + { "VVBLKD+1", 0x0225 }, + { "CDTMA1", 0x0226 }, + { "CDTMA1+1", 0x0227 }, + { "CDTMA2", 0x0228 }, + { "CDTMA2+1", 0x0229 }, + { "CDTMF3", 0x022A }, + { "SRTIMR", 0x022B }, + { "CDTMF4", 0x022C }, + { "INTEMP", 0x022D }, + { "CDTMF5", 0x022E }, + { "SDMCTL", 0x022F }, + { "SDLSTL", 0x0230 }, + { "SDLSTH", 0x0231 }, + { "SSKCTL", 0x0232 }, + { "SPARE", 0x0233 }, + { "LPENH", 0x0234 }, + { "LPENV", 0x0235 }, + { "BRKKY", 0x0236 }, + { "BRKKY+1", 0x0237 }, + { "VPIRQ", 0x0238 }, + { "VPIRQ+1", 0x0239 }, + { "CDEVIC", 0x023A }, + { "CCOMND", 0x023B }, + { "CAUX1", 0x023C }, + { "CAUX2", 0x023D }, + { "TMPSIO", 0x023E }, + { "ERRFLG", 0x023F }, + { "DFLAGS", 0x0240 }, + { "DBSECT", 0x0241 }, + { "BOOTAD", 0x0242 }, + { "BOOTAD+1", 0x0243 }, + { "COLDST", 0x0244 }, + { "RECLEN", 0x0245 }, + { "DSKTIM", 0x0246 }, + { "PDVMSK", 0x0247 }, + { "SHPDVS", 0x0248 }, + { "PDMSK", 0x0249 }, + { "RELADR", 0x024A }, + { "RELADR+1", 0x024B }, + { "PPTMPA", 0x024C }, + { "PPTMPX", 0x024D }, + { "CHSALT", 0x026B }, + { "VSFLAG", 0x026C }, + { "KEYDIS", 0x026D }, + { "FINE", 0x026E }, + { "GPRIOR", 0x026F }, + { "PADDL0", 0x0270 }, + { "PADDL1", 0x0271 }, + { "PADDL2", 0x0272 }, + { "PADDL3", 0x0273 }, + { "PADDL4", 0x0274 }, + { "PADDL5", 0x0275 }, + { "PADDL6", 0x0276 }, + { "PADDL7", 0x0277 }, + { "STICK0", 0x0278 }, + { "STICK1", 0x0279 }, + { "STICK2", 0x027A }, + { "STICK3", 0x027B }, + { "PTRIG0", 0x027C }, + { "PTRIG1", 0x027D }, + { "PTRIG2", 0x027E }, + { "PTRIG3", 0x027F }, + { "PTRIG4", 0x0280 }, + { "PTRIG5", 0x0281 }, + { "PTRIG6", 0x0282 }, + { "PTRIG7", 0x0283 }, + { "STRIG0", 0x0284 }, + { "STRIG1", 0x0285 }, + { "STRIG2", 0x0286 }, + { "STRIG3", 0x0287 }, + { "HIBYTE", 0x0288 }, + { "WMODE", 0x0289 }, + { "BLIM", 0x028A }, + { "IMASK", 0x028B }, + { "JVECK", 0x028C }, + { "NEWADR", 0x028E }, + { "TXTROW", 0x0290 }, + { "TXTCOL", 0x0291 }, + { "TXTCOL+1", 0x0292 }, + { "TINDEX", 0x0293 }, + { "TXTMSC", 0x0294 }, + { "TXTMSC+1", 0x0295 }, + { "TXTOLD", 0x0296 }, + { "TXTOLD+1", 0x0297 }, + { "TXTOLD+2", 0x0298 }, + { "TXTOLD+3", 0x0299 }, + { "TXTOLD+4", 0x029A }, + { "TXTOLD+5", 0x029B }, + { "CRETRY", 0x029C }, + { "HOLD3", 0x029D }, + { "SUBTMP", 0x029E }, + { "HOLD2", 0x029F }, + { "DMASK", 0x02A0 }, + { "TMPLBT", 0x02A1 }, + { "ESCFLG", 0x02A2 }, + { "TABMAP", 0x02A3 }, + { "TABMAP+1", 0x02A4 }, + { "TABMAP+2", 0x02A5 }, + { "TABMAP+3", 0x02A6 }, + { "TABMAP+4", 0x02A7 }, + { "TABMAP+5", 0x02A8 }, + { "TABMAP+6", 0x02A9 }, + { "TABMAP+7", 0x02AA }, + { "TABMAP+8", 0x02AB }, + { "TABMAP+9", 0x02AC }, + { "TABMAP+A", 0x02AD }, + { "TABMAP+B", 0x02AE }, + { "TABMAP+C", 0x02AF }, + { "TABMAP+D", 0x02B0 }, + { "TABMAP+E", 0x02B1 }, + { "LOGMAP", 0x02B2 }, + { "LOGMAP+1", 0x02B3 }, + { "LOGMAP+2", 0x02B4 }, + { "LOGMAP+3", 0x02B5 }, + { "INVFLG", 0x02B6 }, + { "FILFLG", 0x02B7 }, + { "TMPROW", 0x02B8 }, + { "TMPCOL", 0x02B9 }, + { "TMPCOL+1", 0x02BA }, + { "SCRFLG", 0x02BB }, + { "HOLD4", 0x02BC }, + { "DRETRY", 0x02BD }, + { "SHFLOC", 0x02BE }, + { "BOTSCR", 0x02BF }, + { "PCOLR0", 0x02C0 }, + { "PCOLR1", 0x02C1 }, + { "PCOLR2", 0x02C2 }, + { "PCOLR3", 0x02C3 }, + { "COLOR0", 0x02C4 }, + { "COLOR1", 0x02C5 }, + { "COLOR2", 0x02C6 }, + { "COLOR3", 0x02C7 }, + { "COLOR4", 0x02C8 }, + { "RUNADR", 0x02C9 }, + { "RUNADR+1", 0x02CA }, + { "HIUSED", 0x02CB }, + { "HIUSED+1", 0x02CC }, + { "ZHIUSE", 0x02CD }, + { "ZHIUSE+1", 0x02CE }, + { "GBYTEA", 0x02CF }, + { "GBYTEA+1", 0x02D0 }, + { "LOADAD", 0x02D1 }, + { "LOADAD+1", 0x02D2 }, + { "ZLOADA", 0x02D3 }, + { "ZLOADA+1", 0x02D4 }, + { "DSCTLN", 0x02D5 }, + { "DSCTLN+1", 0x02D6 }, + { "ACMISR", 0x02D7 }, + { "ACMISR+1", 0x02D8 }, + { "KRPDER", 0x02D9 }, + { "KEYREP", 0x02DA }, + { "NOCLIK", 0x02DB }, + { "HELPFG", 0x02DC }, + { "DMASAV", 0x02DD }, + { "PBPNT", 0x02DE }, + { "PBUFSZ", 0x02DF }, + { "RUNAD", 0x02E0 }, + { "RUNAD+1", 0x02E1 }, + { "INITAD", 0x02E2 }, + { "INITAD+1", 0x02E3 }, + { "RAMSIZ", 0x02E4 }, + { "MEMTOP", 0x02E5 }, + { "MEMTOP+1", 0x02E6 }, + { "MEMLO", 0x02E7 }, + { "MEMLO+1", 0x02E8 }, + { "HNDLOD", 0x02E9 }, + { "DVSTAT", 0x02EA }, + { "DVSTAT+1", 0x02EB }, + { "DVSTAT+2", 0x02EC }, + { "DVSTAT+3", 0x02ED }, + { "CBAUDL", 0x02EE }, + { "CBAUDH", 0x02EF }, + { "CRSINH", 0x02F0 }, + { "KEYDEL", 0x02F1 }, + { "CH1", 0x02F2 }, + { "CHACT", 0x02F3 }, + { "CHBAS", 0x02F4 }, + { "NEWROW", 0x02F5 }, + { "NEWCOL", 0x02F6 }, + { "NEWCOL+1", 0x02F7 }, + { "ROWINC", 0x02F8 }, + { "COLINC", 0x02F9 }, + { "CHAR", 0x02FA }, + { "ATACHR", 0x02FB }, + { "CH", 0x02FC }, + { "FILDAT", 0x02FD }, + { "DSPFLG", 0x02FE }, + { "SSFLAG", 0x02FF }, + + + { "DDEVIC", 0x0300 }, + { "DUNIT", 0x0301 }, + { "DCOMND", 0x0302 }, + { "DSTATS", 0x0303 }, + { "DBUFLO", 0x0304 }, + { "DBUFHI", 0x0305 }, + { "DTIMLO", 0x0306 }, + { "DUNUSE", 0x0307 }, + { "DBYTLO", 0x0308 }, + { "DBYTHI", 0x0309 }, + { "DAUX1", 0x030A }, + { "DAUX2", 0x030B }, + { "TIMER1", 0x030C }, + { "TIMER1+1", 0x030D }, + { "ADDCOR", 0x030E }, + { "CASFLG", 0x030F }, + { "TIMER2", 0x0310 }, + { "TIMER2+1", 0x0311 }, + { "TEMP1", 0x0312 }, + { "TEMP1+1", 0x0313 }, + { "TEMP2", 0x0314 }, + { "TEMP3", 0x0315 }, + { "SAVIO", 0x0316 }, + { "TIMFLG", 0x0317 }, + { "STACKP", 0x0318 }, + { "TSTAT", 0x0319 }, + { "HATABS", 0x031A }, /*HATABS 1-34*/ + { "PUTBT1", 0x033D }, + { "PUTBT2", 0x033E }, + { "PUTBT3", 0x033F }, + { "B0-ICHID", 0x0340 }, + { "B0-ICDNO", 0x0341 }, + { "B0-ICCOM", 0x0342 }, + { "B0-ICSTA", 0x0343 }, + { "B0-ICBAL", 0x0344 }, + { "B0-ICBAH", 0x0345 }, + { "B0-ICPTL", 0x0346 }, + { "B0-ICPTH", 0x0347 }, + { "B0-ICBLL", 0x0348 }, + { "B0-ICBLH", 0x0349 }, + { "B0-ICAX1", 0x034A }, + { "B0-ICAX2", 0x034B }, + { "B0-ICAX3", 0x034C }, + { "B0-ICAX4", 0x034D }, + { "B0-ICAX5", 0x034E }, + { "B0-ICAX6", 0x034F }, + { "B1-ICHID", 0x0350 }, + { "B1-ICDNO", 0x0351 }, + { "B1-ICCOM", 0x0352 }, + { "B1-ICSTA", 0x0353 }, + { "B1-ICBAL", 0x0354 }, + { "B1-ICBAH", 0x0355 }, + { "B1-ICPTL", 0x0356 }, + { "B1-ICPTH", 0x0357 }, + { "B1-ICBLL", 0x0358 }, + { "B1-ICBLH", 0x0359 }, + { "B1-ICAX1", 0x035A }, + { "B1-ICAX2", 0x035B }, + { "B1-ICAX3", 0x035C }, + { "B1-ICAX4", 0x035D }, + { "B1-ICAX5", 0x035E }, + { "B1-ICAX6", 0x035F }, + { "B2-ICHID", 0x0360 }, + { "B2-ICDNO", 0x0361 }, + { "B2-ICCOM", 0x0362 }, + { "B2-ICSTA", 0x0363 }, + { "B2-ICBAL", 0x0364 }, + { "B2-ICBAH", 0x0365 }, + { "B2-ICPTL", 0x0366 }, + { "B2-ICPTH", 0x0367 }, + { "B2-ICBLL", 0x0368 }, + { "B2-ICBLH", 0x0369 }, + { "B2-ICAX1", 0x036A }, + { "B2-ICAX2", 0x036B }, + { "B2-ICAX3", 0x036C }, + { "B2-ICAX4", 0x036D }, + { "B2-ICAX5", 0x036E }, + { "B2-ICAX6", 0x036F }, + { "B3-ICHID", 0x0370 }, + { "B3-ICDNO", 0x0371 }, + { "B3-ICCOM", 0x0372 }, + { "B3-ICSTA", 0x0373 }, + { "B3-ICBAL", 0x0374 }, + { "B3-ICBAH", 0x0375 }, + { "B3-ICPTL", 0x0376 }, + { "B3-ICPTH", 0x0377 }, + { "B3-ICBLL", 0x0378 }, + { "B3-ICBLH", 0x0379 }, + { "B3-ICAX1", 0x037A }, + { "B3-ICAX2", 0x037B }, + { "B3-ICAX3", 0x037C }, + { "B3-ICAX4", 0x037D }, + { "B3-ICAX5", 0x037E }, + { "B3-ICAX6", 0x037F }, + { "B4-ICHID", 0x0380 }, + { "B4-ICDNO", 0x0381 }, + { "B4-ICCOM", 0x0382 }, + { "B4-ICSTA", 0x0383 }, + { "B4-ICBAL", 0x0384 }, + { "B4-ICBAH", 0x0385 }, + { "B4-ICPTL", 0x0386 }, + { "B4-ICPTH", 0x0387 }, + { "B4-ICBLL", 0x0388 }, + { "B4-ICBLH", 0x0389 }, + { "B4-ICAX1", 0x038A }, + { "B4-ICAX2", 0x038B }, + { "B4-ICAX3", 0x038C }, + { "B4-ICAX4", 0x038D }, + { "B4-ICAX5", 0x038E }, + { "B4-ICAX6", 0x038F }, + { "B5-ICHID", 0x0390 }, + { "B5-ICDNO", 0x0391 }, + { "B5-ICCOM", 0x0392 }, + { "B5-ICSTA", 0x0393 }, + { "B5-ICBAL", 0x0394 }, + { "B5-ICBAH", 0x0395 }, + { "B5-ICPTL", 0x0396 }, + { "B5-ICPTH", 0x0397 }, + { "B5-ICBLL", 0x0398 }, + { "B5-ICBLH", 0x0399 }, + { "B5-ICAX1", 0x039A }, + { "B5-ICAX2", 0x039B }, + { "B5-ICAX3", 0x039C }, + { "B5-ICAX4", 0x039D }, + { "B5-ICAX5", 0x039E }, + { "B5-ICAX6", 0x039F }, + { "B6-ICHID", 0x03A0 }, + { "B6-ICDNO", 0x03A1 }, + { "B6-ICCOM", 0x03A2 }, + { "B6-ICSTA", 0x03A3 }, + { "B6-ICBAL", 0x03A4 }, + { "B6-ICBAH", 0x03A5 }, + { "B6-ICPTL", 0x03A6 }, + { "B6-ICPTH", 0x03A7 }, + { "B6-ICBLL", 0x03A8 }, + { "B6-ICBLH", 0x03A9 }, + { "B6-ICAX1", 0x03AA }, + { "B6-ICAX2", 0x03AB }, + { "B6-ICAX3", 0x03AC }, + { "B6-ICAX4", 0x03AD }, + { "B6-ICAX5", 0x03AE }, + { "B6-ICAX6", 0x03AF }, + { "B7-ICHID", 0x03B0 }, + { "B7-ICDNO", 0x03B1 }, + { "B7-ICCOM", 0x03B2 }, + { "B7-ICSTA", 0x03B3 }, + { "B7-ICBAL", 0x03B4 }, + { "B7-ICBAH", 0x03B5 }, + { "B7-ICPTL", 0x03B6 }, + { "B7-ICPTH", 0x03B7 }, + { "B7-ICBLL", 0x03B8 }, + { "B7-ICBLH", 0x03B9 }, + { "B7-ICAX1", 0x03BA }, + { "B7-ICAX2", 0x03BB }, + { "B7-ICAX3", 0x03BC }, + { "B7-ICAX4", 0x03BD }, + { "B7-ICAX5", 0x03BE }, + { "B7-ICAX6", 0x03BF }, + { "PRNBUF", 0x03C0 }, /*PRNBUF 1-39 */ + { "SUPERF", 0x03E8 }, + { "CKEY", 0x03E9 }, + { "CASSBT", 0x03EA }, + { "CARTCK", 0x03EB }, + { "DERRF", 0x03EC }, + { "ACMVAR", 0x03ED }, /*ACMVAR 1-10*/ + { "BASICF", 0x03F8 }, + { "MINTLK", 0x03F9 }, + { "GINTLK", 0x03FA }, + { "CHLINK", 0x03FB }, + { "CHLINK+1", 0x03FC }, + { "CASBUF", 0x03FD }, + + { "M0PF", 0xD000 }, + { "HPOSP0", 0xD000 }, + { "M1PF", 0xD001 }, + { "HPOSP1", 0xD001 }, + { "M2PF", 0xD002 }, + { "HPOSP2", 0xD002 }, + { "M3PF", 0xD003 }, + { "HPOSP3", 0xD003 }, + { "P0PF", 0xD004 }, + { "HPOSM0", 0xD004 }, + { "P1PF", 0xD005 }, + { "HPOSM1", 0xD005 }, + { "P2PF", 0xD006 }, + { "HPOSM2", 0xD006 }, + { "P3PF", 0xD007 }, + { "HPOSM3", 0xD007 }, + { "M0PL", 0xD008 }, + { "SIZEP0", 0xD008 }, + { "M1PL", 0xD009 }, + { "SIZEP1", 0xD009 }, + { "M2PL", 0xD00A }, + { "HPOSP2", 0xD00A }, + { "M3PL", 0xD00B }, + { "HPOSP3", 0xD00B }, + { "P0PL", 0xD00C }, + { "SIZEM", 0xD00C }, + { "P1PL", 0xD00D }, + { "GRAFP0", 0xD00D }, + { "P2PL", 0xD00E }, + { "GRAFP1", 0xD00E }, + { "P3PL", 0xD00F }, + { "GRAFP2", 0xD00F }, + { "TRIG0", 0xD010 }, + { "GRAFP3", 0xD010 }, + { "TRIG1", 0xD011 }, + { "GRAFM", 0xD011 }, + { "TRIG2", 0xD012 }, + { "COLPM0", 0xD012 }, + { "TRIG3", 0xD013 }, + { "COLPM1", 0xD013 }, + { "PAL", 0xD014 }, + { "COLPM2", 0xD014 }, + { "COLPM3", 0xD015 }, + { "COLPF0", 0xD016 }, + { "COLPF1", 0xD017 }, + { "COLPF2", 0xD018 }, + { "COLPF3", 0xD019 }, + { "COLBK", 0xD01A }, + { "PRIOR", 0xD01B }, + { "VDELAY", 0xD01C }, + { "GRACTL", 0xD01D }, + { "HITCLR", 0xD01E }, + { "CONSOL", 0xD01F }, + + { "POT0", 0xD200 }, + { "AUDF1", 0xD200 }, + { "POT1", 0xD201 }, + { "AUDC1", 0xD201 }, + { "POT2", 0xD202 }, + { "AUDF2", 0xD202 }, + { "POT3", 0xD203 }, + { "AUDC2", 0xD203 }, + { "POT4", 0xD204 }, + { "AUDF3", 0xD204 }, + { "POT5", 0xD205 }, + { "AUDC3", 0xD205 }, + { "POT6", 0xD206 }, + { "AUDF4", 0xD206 }, + { "POT7", 0xD207 }, + { "AUDC4", 0xD207 }, + { "ALLPOT", 0xD208 }, + { "AUDCTL", 0xD208 }, + { "KBCODE", 0xD209 }, + { "STIMER", 0xD209 }, + { "RANDOM", 0xD20A }, + { "SKREST", 0xD20A }, + { "POTGO", 0xD20B }, + { "SERIN", 0xD20D }, + { "SEROUT", 0xD20D }, + { "IRQST", 0xD20E }, + { "IRQEN", 0xD20E }, + { "SKSTAT", 0xD20F }, + { "SKCTL", 0xD20F }, + + { "PORTA", 0xD300 }, + { "PORTB", 0xD301 }, + { "PACTL", 0xD302 }, + { "PBCTL", 0xD303 }, + + { "DMACTL", 0xD400 }, + { "CHACTL", 0xD401 }, + { "DLISTL", 0xD402 }, + { "DLISTH", 0xD403 }, + { "HSCROL", 0xD404 }, + { "VSCROL", 0xD405 }, + { "PMBASE", 0xD407 }, + { "CHBASE", 0xD409 }, + { "WSYNC", 0xD40A }, + { "VCOUNT", 0xD40B }, + { "PENH", 0xD40C }, + { "PENL", 0xD40D }, + { "NMIEN", 0xD40E }, + { "NMIST", 0xD40F }, + { "NMIRES", 0xD40F }, + + { "AFP", 0xD800 }, + { "FASC", 0xD8E6 }, + { "IFP", 0xD9AA }, + { "FPI", 0xD9D2 }, + { "ZPRO", 0xDA44 }, + { "ZF1", 0xDA46 }, + { "FSUB", 0xDA60 }, + { "FADD", 0xDA66 }, + { "FMUL", 0xDADB }, + { "FDIV", 0xDB28 }, + { "PLYEVL", 0xDD40 }, + { "FLD0R", 0xDD89 }, + { "FLD0R", 0xDD8D }, + { "FLD1R", 0xDD98 }, + { "FLD1P", 0xDD9C }, + { "FST0R", 0xDDA7 }, + { "FST0P", 0xDDAB }, + { "FMOVE", 0xDDB6 }, + { "EXP", 0xDDC0 }, + { "EXP10", 0xDDCC }, + { "LOG", 0xDECD }, + { "LOG10", 0xDED1 }, + + { "DSKINV", 0xE453 }, + { "CIOV", 0xE456 }, + { "SIOV", 0xE459 }, + { "SETVBV", 0xE45C }, + { "SYSVBV", 0xE45F }, + { "XITVBV", 0xE462 }, + { "SIOINV", 0xE465 }, + { "SENDEV", 0xE468 }, + { "INTINV", 0xE46B }, + { "CIOINV", 0xE46E }, + { "SELFSV", 0xE471 }, + { "WARMSV", 0xE474 }, + { "COLDSV", 0xE477 }, + { "RBLOKV", 0xE47A }, + { "CSOPIV", 0xE47D }, + { "PUPDIV", 0xE480 }, + { "SELFTSV", 0xE483 }, + { "PENTV", 0xE486 }, + { "PHUNLV", 0xE489 }, + { "PHINIV", 0xE48C }, + { "GPDVV", 0xE48F } +}; + +int symtable_size=sizeof(symtable)/sizeof(symtable_rec); + + +void OutputBlockDiss( BYTE* pbtBlock, WORD wOffset, WORD wEnd ) +{ + WORD wPC_curr = 0; + WORD wPC_end = wEnd - wOffset; + WORD wInsLen = 0; + WORD wInsCode = 0; + BOOL bInsIncomplete = FALSE; + + while ( wPC_curr <= wPC_end ) + { + wInsCode = pbtBlock[ wPC_curr ]; + wInsLen = instable[ wInsCode ].length; + + printf("%04X ", wPC_curr + wOffset ); + + if ( wPC_curr + wInsLen > wPC_end ) + { + wInsLen = wPC_end - wPC_curr; + bInsIncomplete = TRUE; + } + + for ( int i = 0; i <= wInsLen; i++ ) + { + printf("%02X ", pbtBlock[ wPC_curr + i ] ); + } + + for ( int i = 0; i < ( 3 - wInsLen ); i++ ) + { + printf(" "); + } + + char obuf[256]; + char *p; + + char* szSymbol = NULL; + + strcpy( obuf, instable[ wInsCode ].instruct ); + + for (p = obuf; *p; p++) + { + if (*p == '*') + { + *p = '\0'; + p++; + break; + } + } + + if ( !instable[ pbtBlock[ wPC_curr ] ].length ) + { + printf( "%s\n", instable[pbtBlock[wPC_curr]].instruct ); + } + else + { + if ( bInsIncomplete ) + { + printf( "!!!\n" ); + break; + } + + printf( "%s",obuf ); + + if ( instable[wInsCode].branch ) + { + int uPdata = (int) (signed char)pbtBlock[ wPC_curr + 1 ]; + printf( "%04X", wPC_curr + 2 + uPdata + wOffset ); + } + else + { + if ( instable[wInsCode].length == 1 ) + { + WORD wAddr = (BYTE)pbtBlock[ wPC_curr + 1 ]; + + if ( !instable[ wInsCode ].immed ) + szSymbol = SymbolFind( wAddr, instable[ wInsCode ].write ? TRUE : FALSE ); + + printf( "$%02X", wAddr ); + + } + else if ( instable[wInsCode].length == 2 ) + { + WORD wAddr = (WORD) pbtBlock[ wPC_curr + 1 ] | + (WORD)( pbtBlock[ wPC_curr + 2 ] << 8 ); + + if ( !instable[ wInsCode ].immed ) + szSymbol = SymbolFind( wAddr, instable[ wInsCode ].write ? TRUE : FALSE ); + + printf( "$%04X", wAddr ); + + } + } + + if ( szSymbol ) + printf("%s\t;%s\n", p, szSymbol ); + else + printf("%s\n",p); + } + + wPC_curr += ( wInsLen + 1 ); + } + +} + +char* SymbolFind( WORD addr, BOOL bWrite ) +{ + int lo = 0; + int mi = 0; + int hi = symtable_size - 1; + + while ( lo < hi ) + { + mi = ( lo + hi ) / 2; + + if ( symtable[ mi ].addr == addr ) + { + break; + } + else + { + if ( symtable[ mi ].addr > addr ) + hi=mi; + else + lo=mi+1; + } + } + + if ( symtable[mi].addr == addr ) + { + if ( mi>0 && symtable[mi-1].addr == addr ) + { + mi--; + } + + if ( bWrite ) + { + if ( mi < symtable_size - 1 ) + if ( symtable[ mi + 1 ].addr == addr ) + mi++; + } + + return symtable[ mi ].name; + } + + else + return NULL; +} + + + diff --git a/jindroush/lib/autil.cpp b/jindroush/lib/autil.cpp new file mode 100644 index 0000000..3afc782 --- /dev/null +++ b/jindroush/lib/autil.cpp @@ -0,0 +1,139 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "autil.h" + +void Peecize( char* szPC, char* szAtari ); + +//converts 8+3 Atari fname to it's PC equivalent +void ADos2MsDos( char* szMsDos, char* szADos ) +{ + char szName[ 9 ]; + strncpy( szName, szADos, 8 ); + szName[ 8 ] = '\0'; + + char szExt[ 4 ]; + strncpy( szExt, szADos + 8, 3 ); + szExt[ 3 ] = '\0'; + + Peecize( szName, szName ); + Peecize( szExt, szExt ); + + if ( !*szName ) + strcpy( szName, "out" ); + + strcpy( szMsDos, szName ); + + if ( *szExt ) + { + strcat( szMsDos, "." ); + strcat( szMsDos, szExt ); + } +} + +//kind of 'good-for-dos' filter +void Peecize( char* szPC, char* szAtari ) +{ + int iLen = strlen( szAtari ); + + while( iLen-- ) + { + //filter off the inverse chars + char c = *( szAtari++ ) & 0x7F; + + //filter spaces + if ( c == ' ' ) + continue; + + //filter unprintables + if ( !isprint( c ) ) + c = '_'; + + //filter other 'ugly' characters :) + switch( c ) + { + case '*': + case ':': + case '\"': + case ',': + case '.': + case '|': + case '?': + case '/': + case '\\': + c = '_'; + break; + } + + *( szPC++ ) = c; + } + + *szPC = '\0'; +} + + +//converts any Atari name to it's PC equivalent +void GuessBestFnameFromAtari( char* szDest, char* szSrc, char* szExt ) +{ + char szTemp[ 255 ]; + Peecize( szTemp, szSrc ); + GuessBestFnameFromPC( szDest, szTemp, szExt ); +} + +//changes file extension +void GuessBestFnameFromPC( char* szDest, char* szSrc, char* szExt, char* szAdd ) +{ + char szTemp[ 255 ]; + + char szGoodSrc[ 255 ]; + + _fixpath( szSrc, szGoodSrc ); + + char* szSl = strrchr( szGoodSrc, '/' ); + + if ( szSl ) + strcpy( szTemp, szSl + 1 ); + else + strcpy( szTemp, szGoodSrc ); + + char* szDot = strrchr( szTemp, '.' ); + + if ( szDot ) + *szDot = '\0'; + + if ( !strlen( szTemp ) ) + strcpy( szTemp, "out" ); + + strcpy( szDest, szTemp ); + + if ( szAdd ) + strcat( szDest, szAdd ); + + strcat( szDest, "." ); + strcat( szDest, szExt ); +} + +//is memory block empty? +BOOL IsBlockEmpty( BYTE* p, int iLen ) +{ + while( iLen-- ) + { + if ( *( p++ ) ) + return FALSE; + } + + return TRUE; +} + diff --git a/jindroush/lib/cdisk.cpp b/jindroush/lib/cdisk.cpp new file mode 100644 index 0000000..74ee067 --- /dev/null +++ b/jindroush/lib/cdisk.cpp @@ -0,0 +1,276 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cdisk.h" +#include "cdsk_atr.h" +#include "cdsk_xfd.h" +#include "cdsk_dcm.h" +#include "cdsk_scp.h" + + +CDisk::CDisk() +{ + m_bOpened = FALSE; + m_pbtMemory = NULL; + + #ifdef _MEMORY_DUMP_ + printf( "CDisk constructed: %08X\n", this ); + #endif +} + +CDisk::~CDisk() +{ + if ( m_pbtMemory ) + { + delete [] m_pbtMemory; + m_pbtMemory = NULL; + } + + #ifdef _MEMORY_DUMP_ + printf( "CDisk destructed: %08X\n", this ); + #endif +} + +BOOL CDisk::Duplicate( CDisk* pDisk ) +{ + if ( !Format( & ( pDisk->m_geometry ) ) ) + return FALSE; + + memcpy( m_pbtMemory, pDisk->m_pbtMemory, pDisk->m_iAllocated ); + return TRUE; +} + +BOOL CDisk::Format( DISK_GEOMETRY* pgeo ) +{ + int iSectors = pgeo->iSides * pgeo->iTracks * pgeo->iSectorsPerTrack; + + if ( m_pbtMemory ) + delete [] m_pbtMemory; + + m_iAllocated = iSectors * pgeo->iBytesPerSector; + m_pbtMemory = new BYTE [ m_iAllocated ]; + + if ( !m_pbtMemory ) + { + sprintf( m_szLastError, "DISK: Can't format - Not enough memory!" ); + return FALSE; + } + + memset( m_pbtMemory, 0, m_iAllocated ); + + m_geometry.iSides = pgeo->iSides; + m_geometry.iTracks = pgeo->iTracks; + m_geometry.iSectorsPerTrack = pgeo->iSectorsPerTrack; + m_geometry.iBytesPerSector = pgeo->iBytesPerSector; + m_geometry.iSectors = iSectors; + + return TRUE; +} + +BOOL CDisk::ReadSector( void* pBuf, int iStartSec ) +{ + if ( iStartSec && ( iStartSec <= m_geometry.iSectors ) ) + memcpy( pBuf, m_pbtMemory + ( iStartSec - 1 ) * m_geometry.iBytesPerSector, m_geometry.iBytesPerSector ); + else + { + sprintf( m_szLastError, "DISK: Reading non-existent sector: %04X", iStartSec ); + return FALSE; + } + + return TRUE; +} + +BOOL CDisk::ReadSectors( void* pBuf, int iStartSec, int iSecs ) +{ + while( iSecs ) + { + if ( !ReadSector( pBuf, iStartSec ) ) + return FALSE; + + iStartSec++; + iSecs--; + pBuf = (BYTE*)pBuf + m_geometry.iBytesPerSector; + } + + return TRUE; +} + +BOOL CDisk::WriteSector( int iStartSec, void* pBuf ) +{ + //printf( " ws: %d ", iStartSec ); + if ( iStartSec && ( iStartSec <= m_geometry.iSectors ) ) + memcpy( m_pbtMemory + ( iStartSec - 1 ) * m_geometry.iBytesPerSector, pBuf, m_geometry.iBytesPerSector ); + else + { + sprintf( m_szLastError, "DISK: Writing non-existent sector: %04X", iStartSec ); + return FALSE; + } + + return TRUE; +} + +void GuessClassicSizes( int iSectors, int iSectorSize, DISK_GEOMETRY* pGeometry ) +{ + pGeometry->iSides = 1; + pGeometry->iBytesPerSector = iSectorSize; + + pGeometry->iTracks = 1; + pGeometry->iSectorsPerTrack = iSectors; + + switch( iSectors ) + { + case 720: + switch( iSectorSize ) + { + case 0x80: + pGeometry->iTracks = 40; + pGeometry->iSectorsPerTrack = 18; + break; + + case 0x100: + pGeometry->iTracks = 40; + pGeometry->iSectorsPerTrack = 18; + break; + } + break; + + case 1040: + pGeometry->iTracks = 40; + pGeometry->iSectorsPerTrack = 26; + break; + + } + +} + +//returns ptr to disk type name +char* GetDiskTypeName( DISK_TYPE disktype ) +{ + switch( disktype ) + { + case DISK_XFD: + return "XFD"; + + case DISK_ATR: + return "ATR"; + + case DISK_XFDb: + return "XFDb"; + + case DISK_ATRb: + return "ATRb"; + + case DISK_DCM: + return "DCM"; + + case DISK_SCP: + return "SCP"; + + default: + return "None"; + } +} + +//returns ptr to disk type extension +char* GetDiskTypeExt( DISK_TYPE disktype ) +{ + switch( disktype ) + { + case DISK_XFD: + case DISK_XFDb: + return "xfd"; + + case DISK_ATR: + case DISK_ATRb: + return "atr"; + + case DISK_DCM: + return "dcm"; + + case DISK_SCP: + return "scp"; + + default: + return "xxx"; + } +} + +DISKINIT_RETCODE InitializeDisk( CDisk** ppDisk, DISK_TYPE disktype, char* szFname, BOOL bVerbose, BOOL bRepair, BOOL bRepairAuto ) +{ + switch( disktype ) + { + case DISK_ATR: + *ppDisk = new CAtr(); + break; + + case DISK_SCP: + *ppDisk = new CScp(); + break; + + case DISK_DCM: + *ppDisk = new CDcm(); + break; + + case DISK_XFD: + *ppDisk = new CXfd(); + break; + + default: + if ( bVerbose ) + fprintf( stderr, "Invalid disk type specified!\n" ); + return DI_RET_CANT_CONTINUE; + } + + if ( !*ppDisk ) + { + if ( bVerbose ) + fprintf( stderr, "Can't initialize disk driver!\n" ); + return DI_RET_CONTINUE; + } + + if ( !(*ppDisk)->Load( szFname, bRepair, bRepairAuto ) ) + { + int iError = (*ppDisk)->GetErrorCode(); + + DISKINIT_RETCODE ret = DI_RET_CONTINUE; + + switch( iError ) + { + case CATR_FORMAT_VIOLATED: + case CXFD_FORMAT_VIOLATED: + case CDISK_ERROR_CANT_OPEN: + case CDCM_FORMAT_VIOLATED: + case CSCP_FORMAT_VIOLATED: + ret = DI_RET_CANT_CONTINUE; + break; + } + + if ( bVerbose || ( ret == DI_RET_CANT_CONTINUE ) ) + { + printf( "Input file '%s' ", szFname ); + printf( "(%s)\n", GetDiskTypeName( disktype ) ); + printf( "Load failed because:\n%s\n", (*ppDisk)->GetLastError() ); + } + if ( ret != DI_RET_OK ) + { + delete *ppDisk; + return ret; + } + } + + return DI_RET_OK; +} + + diff --git a/jindroush/lib/cdsk.cpp b/jindroush/lib/cdsk.cpp new file mode 100644 index 0000000..cc905f6 --- /dev/null +++ b/jindroush/lib/cdsk.cpp @@ -0,0 +1,115 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cdsk.h" + +CDisk::CDisk() +{ + m_bHasData = FALSE; + m_pbtMemory = NULL; + + m_iMaxSectorWritten = 0; + + #ifdef _MEMORY_DUMP_ + printf( "CDisk constructed: %p\n", this ); + #endif +} + +CDisk::~CDisk() +{ + if ( m_pbtMemory ) + { + delete [] m_pbtMemory; + m_pbtMemory = NULL; + } + + #ifdef _MEMORY_DUMP_ + printf( "CDisk destructed: %p\n", this ); + #endif +} + +BOOL CDisk::Duplicate( CDisk* pDisk, DISK_GEOMETRY* pGeoForced ) +{ + DISK_GEOMETRY* pGeo = pGeoForced; + if ( !pGeo ) + pGeo = &( pDisk->m_geometry ); + + if ( !Format( pGeo ) ) + return FALSE; + + memcpy( m_pbtMemory, pDisk->m_pbtMemory, pDisk->m_iAllocated ); + m_iMaxSectorWritten = pDisk->m_iMaxSectorWritten; + return TRUE; +} + +BOOL CDisk::Format( DISK_GEOMETRY* pgeo ) +{ + m_iMaxSectorWritten = 0; + + int iSectors = pgeo->iSides * pgeo->iTracks * pgeo->iSectorsPerTrack; + + if ( m_pbtMemory ) + delete [] m_pbtMemory; + + m_iAllocated = iSectors * pgeo->iBytesPerSector; + m_pbtMemory = new BYTE [ m_iAllocated ]; + + if ( !m_pbtMemory ) + { + sprintf( m_szLastError, "DISK: Can't format - Not enough memory!" ); + return FALSE; + } + + memset( m_pbtMemory, 0, m_iAllocated ); + + m_geometry.iSides = pgeo->iSides; + m_geometry.iTracks = pgeo->iTracks; + m_geometry.iSectorsPerTrack = pgeo->iSectorsPerTrack; + m_geometry.iBytesPerSector = pgeo->iBytesPerSector; + m_geometry.iSectors = iSectors; + + return TRUE; +} + +BOOL CDisk::ReadSector( void* pBuf, int iStartSec ) +{ + if ( iStartSec && ( iStartSec <= m_geometry.iSectors ) ) + memcpy( pBuf, m_pbtMemory + ( iStartSec - 1 ) * m_geometry.iBytesPerSector, m_geometry.iBytesPerSector ); + else + { + sprintf( m_szLastError, "DISK: Reading non-existent sector: %04X", iStartSec ); + return FALSE; + } + + return TRUE; +} + +BOOL CDisk::WriteSector( int iStartSec, void* pBuf ) +{ + //printf( " ws: %d ", iStartSec ); + if ( iStartSec && ( iStartSec <= m_geometry.iSectors ) ) + memcpy( m_pbtMemory + ( iStartSec - 1 ) * m_geometry.iBytesPerSector, pBuf, m_geometry.iBytesPerSector ); + else + { + sprintf( m_szLastError, "DISK: Writing non-existent sector: %04X", iStartSec ); + return FALSE; + } + + if ( iStartSec > m_iMaxSectorWritten ) + m_iMaxSectorWritten = iStartSec; + + return TRUE; +} + diff --git a/jindroush/lib/cdsk_atr.cpp b/jindroush/lib/cdsk_atr.cpp new file mode 100644 index 0000000..a472561 --- /dev/null +++ b/jindroush/lib/cdsk_atr.cpp @@ -0,0 +1,439 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cdsk_atr.h" +#include "autil.h" +#include "cfile.h" + +#define ATR_MAGIC 0x0296 + +typedef struct +{ + WORD wMagic; + WORD wPars; + WORD wSecSize; + BYTE btParHigh; + DWORD dwCRC; + DWORD dwUnused; + BYTE btFlags; + +} ATRhead; + +#define ATR_HEAD_LEN 0x10 + +CAtr::CAtr() : CDisk() +{ + #ifdef _MEMORY_DUMP_ + printf( "CAtr constructed: %08X\n", this ); + #endif +} + +CAtr::~CAtr() +{ + #ifdef _MEMORY_DUMP_ + printf( "CAtr destructed: %08X\n", this ); + #endif +} + +typedef enum +{ + LOAD_OK, + LOAD_BAD_DD_1, + LOAD_BAD_DD_2, + LOAD_BAD_DD_3, + LOAD_PAD +} LOAD_VARIANT; + +BOOL CAtr::Load( char* szFname, BOOL bRepair, BOOL bRepairAuto ) +{ + LOAD_VARIANT load_method = LOAD_OK; + + m_iErrorCode = 0; + + int iFirstSectorsSize = 0x80; + + CFile cf; + + if ( !cf.Open( szFname ) ) + { + sprintf( m_szLastError, "ATR: Can't open '%s'", szFname ); + m_iErrorCode = CDISK_ERROR_CANT_OPEN; + return FALSE; + } + + strcpy( m_szFname, szFname ); + + ATRhead head; + + head.wMagic = cf.readLEw(); + head.wPars = cf.readLEw(); + head.wSecSize = cf.readLEw(); + head.btParHigh = cf.readb(); + head.dwCRC = cf.readLEdw(); + head.dwUnused = cf.readLEdw(); + head.btFlags = cf.readb(); + + if ( head.wMagic != ATR_MAGIC ) + { + sprintf( m_szLastError, "ATR: File '%s' is not an ATR file!", szFname ); + return FALSE; + } + + LONG lFileLen = cf.GetLength(); + cf.Seek( ATR_HEAD_LEN, SEEK_SET ); + + switch( head.wSecSize ) + { + case 0x80: + case 0x100: + break; + + default: + { + sprintf( m_szLastError, "ATR: Invalid sector size: %04X", head.wSecSize ); + return FALSE; + } + } + + DWORD dwPars = head.wPars | ( head.btParHigh << 16 ); + + int iSectors = ( dwPars * 0x10 ) / head.wSecSize; + + //BOOL bReadOnly = (head.btFlags & 1) ? TRUE : FALSE; + + if ( head.wSecSize == 0x100 ) + { + //if ( dwPars % head.wSecSize ) + if ( ( dwPars * 0x10 ) % head.wSecSize ) + { + iSectors = ( ( dwPars * 0x10 - 0x180 ) / head.wSecSize ) + 3; + } + else + { + sprintf( m_szLastError, "ATR: Format violated. First three sectors are not $80 long!" ); + m_iErrorCode = CATR_FORMAT_VIOLATED; + + if ( !bRepair ) + { + return FALSE; + } + else + { + BYTE abtBuff[ 0x100 ]; + + memset( abtBuff, 0, 0x100 ); + + int iM1zeroes = 3; + int iM2zeroes = 3; + int iM3zeroes = 3; + + cf.Seek( ATR_HEAD_LEN + ( 0x02 - 1 ) * 0x80, SEEK_SET ); + cf.Read( abtBuff, 0x80 ); + + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + iM1zeroes--; + + cf.Seek( ATR_HEAD_LEN + ( 0x04 - 1 ) * 0x80, SEEK_SET ); + cf.Read( abtBuff, 0x80 ); + + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + { + iM1zeroes--; + iM2zeroes--; + } + + cf.Seek( ATR_HEAD_LEN + ( 0x05 - 1 ) * 0x80, SEEK_SET ); + cf.Read( abtBuff, 0x80 ); + + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + iM2zeroes--; + + cf.Seek( ATR_HEAD_LEN + ( 0x06 - 1 ) * 0x80, SEEK_SET ); + cf.Read( abtBuff, 0x80 ); + + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + { + iM1zeroes--; + iM2zeroes--; + } + + cf.Seek( -0x180, SEEK_END ); + cf.Read( abtBuff, 0x80 ); + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + iM3zeroes--; + + cf.Read( abtBuff, 0x80 ); + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + iM3zeroes--; + + cf.Read( abtBuff, 0x80 ); + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + iM3zeroes--; + + if ( !iM1zeroes ) + { + load_method = LOAD_BAD_DD_1; + } + else if ( !iM2zeroes ) + { + load_method = LOAD_BAD_DD_2; + } + else if ( !iM3zeroes ) + { + load_method = LOAD_BAD_DD_3; + } + + if ( !bRepairAuto ) + { + printf( "Invalid DD ATR file encountered.\n" ); + printf( "Choose repair method:\n" ); + printf( "1) Sector, gap, sector, gap, sector, gap, data\n" ); + printf( "2) Three sectors, three empty sectors, data\n" ); + printf( "3) Data, three empty sectors\n" ); + printf( "4) Don't repair\n" ); + + switch( load_method ) + { + case LOAD_BAD_DD_1: + printf( "(Method 1 looks best)\n" ); + break; + + case LOAD_BAD_DD_2: + printf( "(Method 2 looks best)\n" ); + break; + + case LOAD_BAD_DD_3: + printf( "(Method 3 looks best)\n" ); + break; + + default: + break; + } + + int iMethod; + + printf( "\n" ); + do + { + iMethod = getch() - '0'; + } while( ( iMethod < 1 ) || ( iMethod > 4 ) ); + + if ( iMethod == 4 ) + { + return FALSE; + } + } + else + { + if ( load_method == LOAD_OK ) + load_method = LOAD_BAD_DD_1; + } + + + cf.Seek( ATR_HEAD_LEN, SEEK_SET ); + + switch( load_method ) + { + case LOAD_BAD_DD_1: + case LOAD_BAD_DD_2: + case LOAD_BAD_DD_3: + iFirstSectorsSize = 0x100; + break; + + default: + break; + + } + + } //end of repair + + } + } + + LONG lTotalComputedLen = (LONG) ( ( iSectors - 3 ) * head.wSecSize + ATR_HEAD_LEN + 3 * iFirstSectorsSize ); + + if ( lTotalComputedLen != lFileLen ) + { + sprintf( m_szLastError, "ATR: Invalid length! %08lX <> %08lX (%08X)", lTotalComputedLen, lFileLen, iSectors ); + m_iErrorCode = CATR_FORMAT_VIOLATED; + + if ( !bRepair || ( load_method != LOAD_OK ) ) + return FALSE; + else + { + if ( !bRepairAuto ) + { + printf( "ATR with invalid length encountered.\n" ); + printf( "Should be: $%08lX. Is: $%08lX.\n", lTotalComputedLen, lFileLen ); + printf( "Choose:\n" ); + printf( "1) Repair (shorten/pad)\n" ); + printf( "2) Don't repair\n" ); + + int iMethod; + + do + { + iMethod = getch() - '0'; + } while( ( iMethod < 1 ) || ( iMethod > 2 ) ); + + if ( iMethod == 2 ) + return FALSE; + + load_method = LOAD_PAD; + } + else + { + if ( load_method == LOAD_OK ) + load_method = LOAD_PAD; + } + + } + + } + + DISK_GEOMETRY dg; + + GuessClassicSizes( iSectors, head.wSecSize, &dg ); + + if ( !Format( &dg ) ) + return FALSE; + + BYTE abtBuff[ 0x100 ]; + memset( abtBuff, 0, 0x100 ); + + for( int i = 0; i < iSectors; i++ ) + { + switch( load_method ) + { + default: + case LOAD_OK: + cf.Read( abtBuff, ( i < 3 ) ? 0x80 : head.wSecSize ); + break; + + case LOAD_PAD: + memset( abtBuff, 0, 0x100 ); + cf.Read( abtBuff, ( i < 3 ) ? 0x80 : head.wSecSize ); + break; + + case LOAD_BAD_DD_1: + if ( i < 3 ) + { + cf.Read( abtBuff, 0x80 ); + cf.Seek( 0x80, SEEK_CUR ); + } + else + cf.Read( abtBuff, 0x100 ); + break; + + case LOAD_BAD_DD_2: + if ( i < 3 ) + { + cf.Read( abtBuff, 0x80 ); + + if ( i == 2 ) + cf.Seek( 0x180, SEEK_CUR ); + } + else + cf.Read( abtBuff, 0x100 ); + + break; + + case LOAD_BAD_DD_3: + if ( i < 3 ) + cf.Read( abtBuff, 0x80 ); + else + cf.Read( abtBuff, 0x100 ); + + break; + } + + WriteSector( i + 1, abtBuff ); + } + + cf.Close(); + return TRUE; + +} + +#ifdef __CDISK_WRITE__ + +BOOL CAtr::Save( char* szOutFile, BOOL bOverWrite ) +{ + CFile cf; + + if ( !bOverWrite && !access( szOutFile, F_OK ) ) + { + sprintf( m_szLastError, "ATR: File already exists! '%s'", szOutFile ); + return FALSE; + } + + if ( !cf.Create( szOutFile ) ) + { + sprintf( m_szLastError, "ATR: Can't create '%s'", szOutFile ); + return FALSE; + } + + ATRhead head; + memset( &head, 0, sizeof( ATRhead ) ); + + head.wMagic = ATR_MAGIC; + head.wSecSize = m_geometry.iBytesPerSector; + + BOOL bReadOnly = TRUE; + head.btFlags |= ( bReadOnly ) ? 0x01 : 0x00; + + DWORD dwLength = 0; + + dwLength = 0x180 + ( m_geometry.iSectors - 3 ) * m_geometry.iBytesPerSector; + + dwLength >>= 4; + + head.wPars = dwLength & 0xFFFF; + head.btParHigh = dwLength >> 0x10; + + cf.writeLEw( head.wMagic ); + cf.writeLEw( head.wPars ); + cf.writeLEw( head.wSecSize ); + cf.writeb( head.btParHigh ); + cf.writeLEdw( head.dwCRC ); + cf.writeLEdw( head.dwUnused ); + cf.writeb( head.btFlags ); + + BYTE abtBuff[ 0x100 ]; + + for( WORD i = 1; i <= m_geometry.iSectors; i++ ) + { + ReadSector( abtBuff, i ); + + int iToWrite = ( i <= 3 ) ? 0x80: m_geometry.iBytesPerSector; + + int iWritten; + + if ( !cf.Write( abtBuff, iToWrite, &iWritten ) || ( iToWrite != iWritten ) ) + { + sprintf( m_szLastError, "ATR: Can't write!" ); + cf.Close(); + unlink( szOutFile ); + return FALSE; + + } + } + + cf.Close(); + + return TRUE; +} + +#endif //__CDISK_WRITE__ diff --git a/jindroush/lib/cdsk_dcm.cpp b/jindroush/lib/cdsk_dcm.cpp new file mode 100644 index 0000000..06ec1a3 --- /dev/null +++ b/jindroush/lib/cdsk_dcm.cpp @@ -0,0 +1,762 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cdsk_dcm.h" +#include "cfile.h" +#include "cprefile.h" +#include "autil.h" + +//#define _DCM_DUMP_ + +#define DCM_CHANGE_BEGIN 0x41 //Change only start of sector +#define DCM_DOS_SECTOR 0x42 //128 byte compressed sector +#define DCM_COMPRESSED 0x43 //Uncompressed/compressed pairs +#define DCM_CHANGE_END 0x44 //Change only end of sector +#define DCM_PASS_END 0x45 //End of pass +#define DCM_SAME_AS_BEFORE 0x46 //Same as previous non-zero +#define DCM_UNCOMPRESSED 0x47 //Uncompressed sector + +#define DCM_HEADER_SINGLE 0xFA +#define DCM_HEADER_MULTI 0xF9 + +#define DCM_DENSITY_SD 0 //Single density, 90K +#define DCM_DENSITY_DD 1 //Double density, 180K +#define DCM_DENSITY_ED 2 //Enhanced density, 130K + +CDcm::CDcm() : CDisk() +{ + #ifdef _MEMORY_DUMP_ + printf( "CDcm constructed: %08X\n", this ); + #endif +} + +CDcm::~CDcm() +{ + #ifdef _MEMORY_DUMP_ + printf( "CDcm destructed: %08X\n", this ); + #endif +} + +BOOL CDcm::Load( char* szFname, BOOL, BOOL ) +{ + BYTE btArcType = 0; //Block type for first block + BYTE btBlkType; //Current block type + + m_bAlreadyFormatted = FALSE; + m_bLastPass = FALSE; + m_wCurrentSector = 0; + + CFile cfo; + CPreFile cf; + + if ( !cfo.Open( szFname ) ) + { + sprintf( m_szLastError, "DCM: Can't open '%s'", szFname ); + m_iErrorCode = CDISK_ERROR_CANT_OPEN; + return FALSE; + } + + strcpy( m_szFname, szFname ); + + cf.Open( &cfo, 20 ); + + m_lFileLength = cf.GetLength(); + + for(;;) //outpass + { + if ( cf.Tell() >= m_lFileLength ) + { + if ( ( !m_bLastPass ) && ( btArcType == DCM_HEADER_MULTI ) ) + { + sprintf( m_szLastError,"DCM: Multi-part archive error.\n" \ + "To process these files, you must first combine the files into a single file." ); + m_iErrorCode = CDCM_FORMAT_VIOLATED; + return FALSE; + } + } + + btArcType = cf.readb(); + + switch( btArcType ) + { + case DCM_HEADER_MULTI: + case DCM_HEADER_SINGLE: + if ( !DecodeRecFA( cf ) ) + return FALSE; + break; + + default: + sprintf( m_szLastError, "DCM: %02X is an unknown header block.\n", btArcType ); + return FALSE; + } + + for(;;) //inpass + { + btBlkType = cf.readb(); + + if ( btBlkType == DCM_PASS_END ) + break; + + if ( cf.Tell() >= m_lFileLength ) + { + sprintf( m_szLastError, "DCM: EOF before end block." ); + m_iErrorCode = CDCM_FORMAT_VIOLATED; + return FALSE; + } + + BOOL bRes = TRUE; + + *m_szLastError = '\0'; + switch( btBlkType & 0x7F ) + { + case DCM_CHANGE_BEGIN: + bRes = DecodeRec41( cf ); + break; + + case DCM_DOS_SECTOR: + bRes = DecodeRec42( cf ); + break; + + case DCM_COMPRESSED: + bRes = DecodeRec43( cf ); + break; + + case DCM_CHANGE_END: + bRes = DecodeRec44( cf ); + break; + + case DCM_SAME_AS_BEFORE: + //not needed + //bRes = DecodeRec46( cf ); + break; + + case DCM_UNCOMPRESSED: + bRes = DecodeRec47( cf ); + break; + + default: + { + switch( btBlkType ) + { + case DCM_HEADER_MULTI: + case DCM_HEADER_SINGLE: + sprintf( m_szLastError, "DCM: Trying to start section but last section never had " + "an end section block."); + break; + + default: + sprintf( m_szLastError, "DCM: %02X is an unknown block type. File may be " + "corrupt.",btBlkType); + break; + } + + m_iErrorCode = CDCM_FORMAT_VIOLATED; + return FALSE; + } + } + + if ( !bRes ) + { + sprintf( m_szLastError, "DCM: Block %02X decode error!", btBlkType ); + m_iErrorCode = CDCM_FORMAT_VIOLATED; + return FALSE; + } + + if ( !WriteSector( m_wCurrentSector, m_abtCurrBuff ) ) + return FALSE; + + if ( btBlkType & 0x80 ) + m_wCurrentSector++; + else + m_wCurrentSector = cf.readLEw(); + + } //infinite for (inpass) + + //End block + if ( m_bLastPass ) + break; + + } //infinite for (outpass) + + cf.Close(); + cfo.Close(); + return TRUE; + +} + +BOOL CDcm::DecodeRec41( CGenFile& cf ) +{ + #ifdef _DCM_DUMP_ + printf( "dec41: %08lX\n", cf.Tell() - 1 ); + #endif + + int iOffset = cf.readb(); + BYTE* pbt = m_abtCurrBuff + iOffset; + + do + { + *( pbt-- ) = cf.readb(); + } while( iOffset-- ); + + return TRUE; +} + +BOOL CDcm::DecodeRec42( CGenFile& cf ) +{ + #ifdef _DCM_DUMP_ + printf( "dec42: %08lX\n", cf.Tell() - 1 ); + #endif + + sprintf( m_szLastError, "DCM: Record type 0x42 untested. Uncomment?" ); + return FALSE; + + //TODO: uncomment later! + //cf.Read( m_abtCurrBuff + 123, 5 ); + //memset( m_abtCurrBuff, m_abtCurrBuff[ 123 ], 123 ); + //return TRUE; +} + +BOOL CDcm::DecodeRec43( CGenFile& cf ) +{ + #ifdef _DCM_DUMP_ + printf( "dec43: %08lX\n", cf.Tell() - 1 ); + #endif + + BYTE* pbtP = m_abtCurrBuff; + BYTE* pbtE; + + BYTE* pbtEnd = m_abtCurrBuff + m_iSectorSize; + + do + { + //uncompressed string + if ( pbtP != m_abtCurrBuff ) + pbtE = m_abtCurrBuff + ReadOffset( cf ); + else + pbtE = m_abtCurrBuff + cf.readb(); + + if ( pbtE < pbtP ) + return FALSE; + + #ifdef _DCM_DUMP_ + printf( "dec43: uncst: %p %p %ld\n", pbtP, pbtE, pbtE - pbtP ); + #endif + + if ( pbtE != pbtP ) + { + cf.Read( pbtP, pbtE - pbtP ); + pbtP = pbtE; + } + + if ( pbtP >= pbtEnd ) + break; + + //rle compressed string + pbtE = m_abtCurrBuff + ReadOffset( cf ); + BYTE c = cf.readb(); + + #ifdef _DCM_DUMP_ + printf( "dec43: cst: %p %p %ld\n", pbtP, pbtE, pbtE - pbtP ); + #endif + + if ( pbtE < pbtP ) + return FALSE; + + memset( pbtP, c, pbtE - pbtP ); + pbtP = pbtE; + + } while( pbtP < pbtEnd ); + + return TRUE; +} + +BOOL CDcm::DecodeRec44( CGenFile& cf ) +{ + #ifdef _DCM_DUMP_ + printf( "dec44: %08lX\n", cf.Tell() - 1 ); + #endif + + int iOffset = ReadOffset( cf ); + + cf.Read( m_abtCurrBuff + iOffset, m_iSectorSize - iOffset ); + + return TRUE; +} + +BOOL CDcm::DecodeRec46( CGenFile& cf ) +{ + #ifdef _DCM_DUMP_ + printf( "dec46: %08lX\n", cf.Tell() - 1 ); + #endif + + return TRUE; +} + +BOOL CDcm::DecodeRec47( CGenFile& cf ) +{ + #ifdef _DCM_DUMP_ + printf( "dec47: %08lX\n", cf.Tell() - 1 ); + #endif + + //TODO: Is this TRUE or NOT??? + //cf.Read( m_abtCurrBuff, ( m_wCurrentSector < 4 ? 128 : m_iSectorSize ) ); + + cf.Read( m_abtCurrBuff, m_iSectorSize ); + return TRUE; +} + +BOOL CDcm::DecodeRecFA( CGenFile& cf ) +{ + #ifdef _DCM_DUMP_ + printf( "decFA: %08lX\n", cf.Tell() - 1 ); + #endif + + BYTE btPom = cf.readb(); + + BYTE btDensity = ( btPom >> 5 ) & 0x03; + //BYTE btPass = btPom & 0x1F; + m_bLastPass = ( btPom & 0x80 ) ? TRUE : FALSE; + + int iSpT; + int iTracks; + + switch( btDensity ) + { + case DCM_DENSITY_SD: + iTracks = 40; + iSpT = 18; + m_iSectorSize = 128; + break; + + case DCM_DENSITY_DD: + iTracks = 40; + iSpT = 18; + m_iSectorSize = 256; + break; + + case DCM_DENSITY_ED: + iTracks = 40; + iSpT = 26; + m_iSectorSize = 128; + break; + + default: + sprintf( m_szLastError,"DCM: Density type unknown (%02X)\n", btDensity ); + return FALSE; + } + + if ( !m_bAlreadyFormatted ) + { + DISK_GEOMETRY dg; + dg.iSides = 1; + dg.iTracks = iTracks; + dg.iSectorsPerTrack = iSpT; + dg.iBytesPerSector = m_iSectorSize; + + if ( !Format( &dg ) ) + return FALSE; + + m_bAlreadyFormatted = TRUE; + } + + m_wCurrentSector = cf.readLEw(); + + return TRUE; +} + +WORD CDcm::ReadOffset( CGenFile& cf ) +{ + BYTE bt = cf.readb(); + + return( bt ? bt : 256 ); +} + +#ifdef __CDISK_WRITE__ + +BOOL CDcm::Save( char* szOutFile, BOOL bOverWrite ) +{ + if ( !bOverWrite && !access( szOutFile, F_OK ) ) + { + sprintf( m_szLastError, "DCM: File already exists! '%s'", szOutFile ); + return FALSE; + } + + int iDensity = -1; + m_iSectorSize = m_geometry.iBytesPerSector; + + if ( m_iSectorSize == 0x80 ) + { + if ( m_geometry.iTracks == 40 ) + { + if ( m_geometry.iSectorsPerTrack == 18 ) + iDensity = DCM_DENSITY_SD; + + if ( m_geometry.iSectorsPerTrack == 26 ) + iDensity = DCM_DENSITY_ED; + } + } + + if ( m_iSectorSize == 0x100 ) + { + if ( ( m_geometry.iSectorsPerTrack == 18 ) && + ( m_geometry.iTracks == 40 ) ) + iDensity = DCM_DENSITY_DD; + } + + if ( iDensity == - 1 ) + { + sprintf( m_szLastError, "DCM: Can't work with such density!" ); + return FALSE; + } + + int iPass = 1; + + m_pbtPass = new BYTE [ 0x6500 ]; + + CFile cf; + + if ( !cf.Create( szOutFile ) ) + { + sprintf( m_szLastError, "DCM: Can't create '%s'", szOutFile ); + delete [] m_pbtPass; + return FALSE; + } + + int iFirstSector = 0; + int iPrevSector = 0; + int iCurrentSector = 1; + + memset( m_abtPrevBuff, 0, m_iSectorSize ); + + EncodeRecFA( FALSE, iPass, iDensity, iFirstSector ); + + //here should be other compression + + while( iCurrentSector <= m_geometry.iSectors ) + { + iFirstSector = 0; + + while( ( m_pbtCurr - m_pbtPass ) < 0x5EFD ) + { + if ( iCurrentSector > m_geometry.iSectors ) + break; + + ReadSector( m_abtCurrBuff, iCurrentSector ); + + BOOL bSkip = IsBlockEmpty( m_abtCurrBuff, m_iSectorSize ); + + //first non empty sector is marked as first, what a surprise! :) + if ( !bSkip && !iFirstSector ) + { + iFirstSector = iCurrentSector; + iPrevSector = iCurrentSector; + } + + //if just skipped, increment sector + if ( bSkip ) + { + iCurrentSector++; + } + else + { + //if there is a gap, write sector number + if ( ( iCurrentSector - iPrevSector ) > 1 ) + { + *( m_pbtCurr++ ) = iCurrentSector; + *( m_pbtCurr++ ) = iCurrentSector >> 8; + } + else + { + //else mark previous record + *m_pbtLastRec |= 0x80; + } + + //first sector could be encoded with only some data + if ( iCurrentSector == iFirstSector ) + EncodeRec( TRUE ); + else + { + //if are same, encode as record 46 + if ( !memcmp( m_abtPrevBuff, m_abtCurrBuff, m_iSectorSize ) ) + EncodeRec46(); + else + EncodeRec( FALSE ); + } + + //store this sector as previous + memcpy( m_abtPrevBuff, m_abtCurrBuff, m_iSectorSize ); + + //and move pointers + iPrevSector = iCurrentSector; + iCurrentSector++; + } + + } + + //mark previous sector + *m_pbtLastRec |= 0x80; + + //encode end + EncodeRec45(); + + BYTE* pEnd = m_pbtCurr; + + //change beginning block + if ( iCurrentSector > m_geometry.iSectors ) + EncodeRecFA( TRUE, iPass, iDensity, iFirstSector ); + else + EncodeRecFA( FALSE, iPass, iDensity, iFirstSector ); + + //and write whole pass + + if ( ( pEnd - m_pbtPass ) > 0x6000 ) + { + sprintf( m_szLastError, "DCM: Internal error! Pass too long!" ); + delete [] m_pbtPass; + cf.Close(); + unlink( szOutFile ); + return FALSE; + } + + if ( !cf.Write( m_pbtPass, pEnd - m_pbtPass ) ) + { + sprintf( m_szLastError, "DCM: Can't write!" ); + delete [] m_pbtPass; + cf.Close(); + unlink( szOutFile ); + return FALSE; + } + + iPass++; + } + + cf.Close(); + + delete [] m_pbtPass; + + return TRUE; +} + +void CDcm::EncodeRecFA( BOOL bLast, int iPass, int iDensity, int iFirstSec ) +{ + m_pbtCurr = m_pbtPass; + + #ifdef _DCM_DUMP_ + printf( "ERFA: %08lX\n", m_pbtCurr - m_pbtPass ); + #endif + + m_pbtLastRec = m_pbtCurr; + + BYTE btType = bLast ? 0x80 : 0; + + btType |= ( iDensity & 3 ) << 5; + + btType |= ( iPass & 0x1F ); + + *( m_pbtCurr++ ) = DCM_HEADER_SINGLE; + *( m_pbtCurr++ ) = btType; + *( m_pbtCurr++ ) = iFirstSec; + *( m_pbtCurr++ ) = iFirstSec >> 8; + +} + +void CDcm::EncodeRec45() +{ + #ifdef _DCM_DUMP_ + printf( "ER45: %08lX\n", m_pbtCurr - m_pbtPass ); + #endif + + m_pbtLastRec = m_pbtCurr; + *( m_pbtCurr++ ) = DCM_PASS_END; +} + +void CDcm::EncodeRec46() +{ + #ifdef _DCM_DUMP_ + printf( "ER46: %08lX\n", m_pbtCurr - m_pbtPass ); + #endif + + m_pbtLastRec = m_pbtCurr; + *( m_pbtCurr++ ) = DCM_SAME_AS_BEFORE; +} + +void CDcm::EncodeRec( BOOL bIsFirstSector ) +{ + #ifdef _DCM_DUMP_ + printf( "ER: %08lX\n", m_pbtCurr - m_pbtPass ); + #endif + + m_pbtLastRec = m_pbtCurr; + + BYTE abtBuff41[ 0x300 ]; + BYTE abtBuff43[ 0x300 ]; + BYTE abtBuff44[ 0x300 ]; + BYTE* abtBuff47 = m_abtCurrBuff; + + int iEnd41 = 0x300; + int iEnd43 = 0x300; + int iEnd44 = 0x300; + + int iBestMethod = DCM_UNCOMPRESSED; + int iBestEnd = m_iSectorSize; + BYTE* pbtBest = abtBuff47; + + EncodeRec43( abtBuff43, &iEnd43, m_abtCurrBuff, m_iSectorSize ); + + if ( !bIsFirstSector ) + { + EncodeRec41( abtBuff41, &iEnd41, m_abtCurrBuff, m_abtPrevBuff, m_iSectorSize ); + EncodeRec44( abtBuff44, &iEnd44, m_abtCurrBuff, m_abtPrevBuff, m_iSectorSize ); + } + + if ( iEnd41 < iBestEnd ) + { + iBestMethod = DCM_CHANGE_BEGIN; + iBestEnd = iEnd41; + pbtBest = abtBuff41; + } + + if ( iEnd43 < iBestEnd ) + { + iBestMethod = DCM_COMPRESSED; + iBestEnd = iEnd43; + pbtBest = abtBuff43; + } + + if ( iEnd44 < iBestEnd ) + { + iBestMethod = DCM_CHANGE_END; + iBestEnd = iEnd44; + pbtBest = abtBuff44; + } + + *( m_pbtCurr++ ) = iBestMethod; + memcpy( m_pbtCurr, pbtBest, iBestEnd ); + m_pbtCurr += iBestEnd; +} + +void CDcm::EncodeRec41( BYTE* pbtDest, int* piDestLen, BYTE* pbtSrc, BYTE* pbtSrcOld, int iSrcLen ) +{ + BYTE* pbtS = pbtSrc + iSrcLen - 1; + pbtSrcOld += iSrcLen - 1; + + BYTE* pbtD = pbtDest; + + for( int i = 0; i < iSrcLen; i++ ) + { + if ( *( pbtS-- ) != * ( pbtSrcOld-- ) ) + break; + } + + pbtS++; + + *( pbtD++ ) = pbtS - pbtSrc; + + int iBytes = pbtS - pbtSrc + 1; + + while( iBytes-- ) + { + *( pbtD++ ) = *( pbtS-- ); + } + + *piDestLen = pbtD - pbtDest; +} + +void CDcm::EncodeRec43( BYTE* pbtDest, int* piDestLen, BYTE* pbtSrc, int iSrcLen ) +{ + BYTE* pbtEnd = pbtSrc + iSrcLen; + BYTE* pbtCur = pbtSrc; + + BYTE* pbtD = pbtDest; + + while( pbtCur < pbtEnd ) + { + BOOL bFound = FALSE; + + for( BYTE* pbtNow = pbtCur; pbtNow < ( pbtEnd - 2 ); pbtNow++ ) + { + + if ( ( *pbtNow == *(pbtNow+1) ) && ( *pbtNow == *(pbtNow+2) ) ) + { + int iUnc = pbtNow - pbtCur; + + *( pbtD ++ ) = pbtNow - pbtSrc; + if ( iUnc ) + { + memcpy( pbtD, pbtCur, iUnc ); + pbtD += iUnc; + } + + BYTE bt = *pbtNow; + BYTE*p; + for( p = pbtNow + 1; p < pbtEnd; p++ ) + { + if ( *p != bt ) + break; + } + + if ( p > pbtEnd ) + p = pbtEnd; + + *( pbtD++ ) = p - pbtSrc; + *( pbtD++ ) = bt; + + pbtCur = p; + bFound = TRUE; + break; + } + } + + if ( ( pbtCur >= pbtEnd - 2 ) || !bFound ) + { + if ( pbtCur < pbtEnd ) + { + *( pbtD++ ) = iSrcLen; + memcpy( pbtD, pbtCur, pbtEnd - pbtCur ); + pbtD += pbtEnd - pbtCur; + } + + break; + } + + } + + *piDestLen = pbtD - pbtDest; +} + +void CDcm::EncodeRec44( BYTE* pbtDest, int* piDestLen, BYTE* pbtSrc, BYTE* pbtSrcOld, int iSrcLen ) +{ + BYTE* pbtS = pbtSrc; + BYTE* pbtEnd = pbtSrc + iSrcLen; + + BYTE* pbtD = pbtDest; + + for( int i = 0; i < iSrcLen; i++ ) + { + if ( *( pbtS++ ) != * ( pbtSrcOld++ ) ) + break; + } + + pbtS--; + + *( pbtD++ ) = pbtS - pbtSrc; + memcpy( pbtD, pbtS, pbtEnd - pbtS ); + pbtD += pbtEnd - pbtS; + + *piDestLen = pbtD - pbtDest; +} + +#endif // __CDISK_WRITE__ + diff --git a/jindroush/lib/cdsk_scp.cpp b/jindroush/lib/cdsk_scp.cpp new file mode 100644 index 0000000..eb2e0f2 --- /dev/null +++ b/jindroush/lib/cdsk_scp.cpp @@ -0,0 +1,279 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cdsk_scp.h" +#include "autil.h" +#include "cfile.h" + +#define SCP_MAGIC 0xFDFD + +CScp::CScp() : CDisk() +{ + #ifdef _MEMORY_DUMP_ + printf( "CScp constructed: %08X\n", this ); + #endif +} + +CScp::~CScp() +{ + #ifdef _MEMORY_DUMP_ + printf( "CScp destructed: %08X\n", this ); + #endif +} + +BOOL CScp::Load( char* szFname, BOOL, BOOL ) +{ + WORD wMagic; + BYTE btSectorSize; + BYTE btTracks; + BYTE btSectorsPerTrack; + + CFile cf; + + if( !cf.Open( szFname ) ) + { + sprintf( m_szLastError, "SCP: Can't open '%s'", szFname ); + return FALSE; + } + + strcpy( m_szFname, szFname ); + + wMagic = cf.readLEw(); + + if ( wMagic != SCP_MAGIC ) + { + sprintf( m_szLastError, "SCP: File '%s' is not an SCP file!", szFname ); + return FALSE; + } + + btSectorSize = cf.readb(); + btTracks = cf.readb(); + btSectorsPerTrack = cf.readb(); + + int iSectorSize; + + switch( btSectorSize ) + { + case 0x80: + iSectorSize = 0x80; + break; + + case 0x00: + iSectorSize = 0x100; + break; + + default: + { + sprintf( m_szLastError, "SCP: Invalid sector size: %02X", btSectorSize ); + return FALSE; + } + } + + DISK_GEOMETRY dg; + dg.iSides = 1; + dg.iTracks = btTracks; + dg.iSectorsPerTrack = btSectorsPerTrack; + dg.iBytesPerSector = iSectorSize; + + if ( !Format( &dg ) ) + return FALSE; + + BYTE *pbtTable = new BYTE [ btSectorsPerTrack * btTracks ]; + + if ( ! pbtTable ) + { + sprintf( m_szLastError, "SCP: Not enough memory for sector table!" ); + return FALSE; + } + + if ( !cf.Read( pbtTable, btSectorsPerTrack * btTracks ) ) + { + sprintf( m_szLastError, "SCP: Can't read sector table!" ); + return FALSE; + } + + BYTE abtBuff[ 0x100 ]; + memset( abtBuff, 0, 0x100 ); + + BYTE* pbtPtr = pbtTable; + + for( int iTrack = 0; iTrack < btTracks; iTrack++ ) + { + for( int iSector = 0; iSector < btSectorsPerTrack; iSector++ ) + { + if ( *pbtPtr ) + { + int iNowRead; + + if ( !iTrack && ( iSector < 3 ) ) + iNowRead = 0x80; + else + iNowRead = iSectorSize; + + int iReallyRead; + + if ( !cf.Read( abtBuff, iNowRead, &iReallyRead ) || ( iNowRead != iReallyRead ) ) + { + delete [] pbtTable; + sprintf( m_szLastError, "SCP: Image broken!" ); + return FALSE; + } + + if ( !WriteSector( *pbtPtr + iTrack* btSectorsPerTrack, abtBuff ) ) + { + delete [] pbtTable; + return FALSE; + } + + } + pbtPtr++; + } + + } + + delete [] pbtTable; + + cf.Close(); + return TRUE; + +} + +#ifdef __CDISK_WRITE__ + +BOOL CScp::Save( char* szOutFile, BOOL bOverWrite ) +{ + if ( !bOverWrite && !access( szOutFile, F_OK ) ) + { + sprintf( m_szLastError, "SCP: File already exists! '%s'", szOutFile ); + return FALSE; + } + + BYTE btSize; + BYTE btTracks; + BYTE btSpT; + + switch ( m_geometry.iBytesPerSector ) + { + case 0x80: + btSize = 0x80; + break; + + case 0x100: + default: + btSize = 0x00; + break; + } + + BOOL bGood = FALSE; + + btTracks = m_geometry.iTracks; + btSpT = m_geometry.iSectorsPerTrack; + + if ( ( m_geometry.iTracks == 40 ) && ( m_geometry.iSectorsPerTrack == 18 ) ) + bGood = TRUE; + + if ( ( m_geometry.iTracks == 40 ) && ( m_geometry.iSectorsPerTrack == 26 ) ) + bGood = TRUE; + + if ( !bGood ) + { + sprintf( m_szLastError, "SCP: Can't export, because of invalid disk size!" ); + return FALSE; + } + + int iMapSize = m_geometry.iTracks * m_geometry.iSectorsPerTrack; + + BYTE* pMap = new BYTE [ iMapSize ]; + + if ( !pMap ) + { + sprintf( m_szLastError, "SCP: Can't allocate memory for map!" ); + return FALSE; + } + + memset( pMap, 0, iMapSize ); + + + CFile cf; + + if ( !cf.Create( szOutFile ) ) + { + sprintf( m_szLastError, "SCP: Can't create '%s'", szOutFile ); + delete [] pMap; + return FALSE; + } + + WORD wMagic = SCP_MAGIC; + + cf.writeLEw( wMagic ); + cf.writeb( btSize ); + cf.writeb( btTracks ); + cf.writeb( btSpT ); + + cf.Seek( iMapSize, SEEK_CUR ); + + BYTE abtBuff[ 0x100 ]; + + int iSectors = m_geometry.iSectors; + + for( int i = 0; i < iSectors; i++ ) + { + if ( !ReadSector( abtBuff, i + 1 ) ) + { + delete [] pMap; + cf.Close(); + unlink( szOutFile ); + return FALSE; + } + + int iBytesNow = ( i < 3 ) ? 0x80 : m_geometry.iBytesPerSector; + + if ( !IsBlockEmpty( abtBuff, iBytesNow ) ) + { + int iWritten; + if ( !cf.Write( abtBuff, iBytesNow, &iWritten ) || ( iBytesNow != iWritten ) ) + { + sprintf( m_szLastError, "SCP: Error writing to '%s'", szOutFile ); + delete [] pMap; + cf.Close( ); + unlink( szOutFile ); + return FALSE; + + } + + pMap[ i ] = ( i % btSpT ) + 1; + } + } + + cf.Seek( 5, SEEK_SET ); + + if ( !cf.Write( pMap, iMapSize ) ) + { + sprintf( m_szLastError, "SCP: Can't write!" ); + delete [] pMap; + cf.Close( ); + unlink( szOutFile ); + return FALSE; + + } + + delete [] pMap; + + cf.Close(); + + return TRUE; +} + +#endif //__CDISK_WRITE__ diff --git a/jindroush/lib/cdsk_xfd.cpp b/jindroush/lib/cdsk_xfd.cpp new file mode 100644 index 0000000..aecaeb2 --- /dev/null +++ b/jindroush/lib/cdsk_xfd.cpp @@ -0,0 +1,334 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cdsk_xfd.h" +#include "autil.h" +#include "cfile.h" + +CXfd::CXfd() : CDisk() +{ + #ifdef _MEMORY_DUMP_ + printf( "CXfd constructed: %08X\n", this ); + #endif +} + +CXfd::~CXfd() +{ + #ifdef _MEMORY_DUMP_ + printf( "CXfd destructed: %08X\n", this ); + #endif +} + +typedef enum +{ + LOAD_OK, + LOAD_BAD_DD_1, + LOAD_BAD_DD_2, + LOAD_BAD_DD_3 +} LOAD_VARIANT; + +BOOL CXfd::Load( char* szFname, BOOL bRepair, BOOL bRepairAuto ) +{ + LOAD_VARIANT load_method = LOAD_OK; + + int iFirstSectorsSize = 0x80; + + CFile cf; + + if ( !cf.Open( szFname ) ) + { + sprintf( m_szLastError, "XFD: Can't open '%s'", szFname ); + return FALSE; + } + + strcpy( m_szFname, szFname ); + + LONG lFileLen = cf.GetLength(); + + int iSecs; + int iSecSize; + + if ( lFileLen % 0x80 ) + { + sprintf( m_szLastError, "XFD: Strange length!" ); + cf.Close(); + return FALSE; + } + + if ( ( lFileLen / 0x80 ) > 1040 ) + { + iSecSize = 0x100; + + iSecs = ( ( lFileLen - 0x180 ) / 0x100 ) + 3; + } + else + { + iSecSize = 0x80; + iSecs = lFileLen / 0x80; + } + + if ( ( ( ( iSecs - 3 ) * iSecSize ) + 0x180 ) != lFileLen ) + { + sprintf( m_szLastError, "XFD: Format violated: (%08lX != %08X)", lFileLen, iSecs * iSecSize ); + m_iErrorCode = CXFD_FORMAT_VIOLATED; + + if ( !bRepair ) + { + cf.Close(); + return FALSE; + } + else + { + iSecs = lFileLen / iSecSize; + BYTE abtBuff[ 0x100 ]; + + memset( abtBuff, 0, 0x100 ); + + int iM1zeroes = 3; + int iM2zeroes = 3; + int iM3zeroes = 3; + + cf.Seek( ( 0x02 - 1 ) * 0x80, SEEK_SET ); + cf.Read( abtBuff, 0x80 ); + + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + iM1zeroes--; + + cf.Seek( ( 0x04 - 1 ) * 0x80, SEEK_SET ); + cf.Read( abtBuff, 0x80 ); + + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + { + iM1zeroes--; + iM2zeroes--; + } + + cf.Seek( ( 0x05 - 1 ) * 0x80, SEEK_SET ); + cf.Read( abtBuff, 0x80 ); + + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + iM2zeroes--; + + cf.Seek( ( 0x06 - 1 ) * 0x80, SEEK_SET ); + cf.Read( abtBuff, 0x80 ); + + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + { + iM1zeroes--; + iM2zeroes--; + } + + cf.Seek( -0x180, SEEK_END ); + cf.Read( abtBuff, 0x80 ); + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + iM3zeroes--; + + cf.Read( abtBuff, 0x80 ); + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + iM3zeroes--; + + cf.Read( abtBuff, 0x80 ); + if ( IsBlockEmpty( abtBuff, 0x80 ) ) + iM3zeroes--; + + if ( !iM1zeroes ) + { + load_method = LOAD_BAD_DD_1; + } + else if ( !iM2zeroes ) + { + load_method = LOAD_BAD_DD_2; + } + else if ( !iM3zeroes ) + { + load_method = LOAD_BAD_DD_3; + } + + if ( !bRepairAuto ) + { + printf( "Invalid DD ATR file encountered.\n" ); + printf( "Choose repair method:\n" ); + printf( "1) Sector, gap, sector, gap, sector, gap, data\n" ); + printf( "2) Three sectors, three empty sectors, data\n" ); + printf( "3) Data, three empty sectors\n" ); + printf( "4) Don't repair\n" ); + + switch( load_method ) + { + case LOAD_BAD_DD_1: + printf( "(Method 1 looks best)\n" ); + break; + + case LOAD_BAD_DD_2: + printf( "(Method 2 looks best)\n" ); + break; + + case LOAD_BAD_DD_3: + printf( "(Method 3 looks best)\n" ); + break; + + default: + break; + } + + int iMethod; + + printf( "\n" ); + do + { + iMethod = getch() - '0'; + } while( ( iMethod < 1 ) || ( iMethod > 4 ) ); + + if ( iMethod == 4 ) + { + cf.Close(); + return FALSE; + } + } + else + { + if ( load_method == LOAD_OK ) + load_method = LOAD_BAD_DD_1; + } + + cf.Seek( 0, SEEK_SET ); + + switch( load_method ) + { + case LOAD_BAD_DD_1: + case LOAD_BAD_DD_2: + iFirstSectorsSize = 0x100; + break; + + default: + break; + + } + + + } + } + + DISK_GEOMETRY dg; + + GuessClassicSizes( iSecs, iSecSize, &dg ); + + if ( !Format( &dg ) ) + { + cf.Close(); + return FALSE; + } + + BYTE abtBuff[ 0x100 ]; + memset( abtBuff, 0, 0x100 ); + + for( int i = 0; i < iSecs; i++ ) + { + switch( load_method ) + { + default: + case LOAD_OK: + cf.Read( abtBuff, ( i < 3 ) ? 0x80 : iSecSize ); + break; + + case LOAD_BAD_DD_1: + if ( i < 3 ) + { + cf.Read( abtBuff, 0x80 ); + cf.Seek( 0x80, SEEK_CUR ); + } + else + cf.Read( abtBuff, 0x100 ); + break; + + case LOAD_BAD_DD_2: + if ( i < 3 ) + { + cf.Read( abtBuff, 0x80 ); + + if ( i == 2 ) + cf.Seek( 0x180, SEEK_CUR ); + } + else + cf.Read( abtBuff, 0x100 ); + + break; + + case LOAD_BAD_DD_3: + if ( i < 3 ) + cf.Read( abtBuff, 0x80 ); + else + cf.Read( abtBuff, 0x100 ); + + break; + } + + if ( !WriteSector( i + 1, abtBuff ) ) + { + cf.Close(); + return FALSE; + } + } + + cf.Close(); + return TRUE; + +} + +#ifdef __CDISK_WRITE__ + +BOOL CXfd::Save( char* szOutFile, BOOL bOverWrite ) +{ + CFile cf; + + if ( !bOverWrite && !access( szOutFile, F_OK ) ) + { + sprintf( m_szLastError, "XFD: File already exists! '%s'", szOutFile ); + return FALSE; + } + + if ( !cf.Create( szOutFile ) ) + { + sprintf( m_szLastError, "XFD: Can't create '%s'", szOutFile ); + return FALSE; + } + + BYTE abtBuff[ 0x100 ]; + + for( WORD i = 1; i <= m_geometry.iSectors; i++ ) + { + if ( !ReadSector( abtBuff, i ) ) + return FALSE; + + int iToWrite = ( i <= 3 ) ? 0x80: m_geometry.iBytesPerSector; + + int iWritten; + + if ( !cf.Write( abtBuff, iToWrite, &iWritten ) || ( iWritten != iToWrite ) ) + { + sprintf( m_szLastError, "XFD: Can't write!" ); + cf.Close(); + unlink( szOutFile ); + return FALSE; + } + + } + + cf.Close(); + + return TRUE; +} + +#endif //__CDISK_WRITE__ diff --git a/jindroush/lib/cfile.cpp b/jindroush/lib/cfile.cpp new file mode 100644 index 0000000..97a78d2 --- /dev/null +++ b/jindroush/lib/cfile.cpp @@ -0,0 +1,139 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cfile.h" + +CFile::CFile() +{ + m_bOpened = FALSE; + m_hFile = 0; + m_bIsDirty = FALSE; +} + +CFile::~CFile() +{ + Close(); +} + +//opens file for reading, binary +BOOL CFile::Open( char* szName ) +{ + if ( m_bOpened ) + return FALSE; + + m_hFile = open( szName, O_BINARY | O_RDONLY ); + + if ( m_hFile == -1 ) + { + m_hFile = 0; + + //printf( "CFile::Open %s Err:%d\n", szName, errno ); + + return FALSE; + } + + m_bOpened = TRUE; + + m_lLength = lseek( m_hFile, 0, SEEK_END ); + lseek( m_hFile, 0, SEEK_SET ); + + return TRUE; + +} + +//creates new file, opened for rdwr, binary, deletes existing +BOOL CFile::Create( char* szName ) +{ + if ( m_bOpened ) + return FALSE; + + m_bIsDirty = FALSE; + m_hFile = open( szName, O_BINARY | O_RDWR | O_CREAT | O_TRUNC, 0666 ); + + if ( m_hFile == -1 ) + { + m_hFile = 0; + return FALSE; + } + + m_bOpened = TRUE; + + m_lLength = lseek( m_hFile, 0, SEEK_END ); + lseek( m_hFile, 0, SEEK_SET ); + + return TRUE; + +} + +//reads iBytesToRead bytes to buffer +BOOL CFile::Read( void* pBuff, int iBytesToRead, int* piBytesRead ) +{ + if ( !m_bOpened ) + return FALSE; + + m_bIsDirty = FALSE; + int iBytesRead = read( m_hFile, pBuff, iBytesToRead ); + + if ( piBytesRead ) + *piBytesRead = iBytesRead; + + if ( -1 == iBytesRead ) + return FALSE; + + m_lCurrPtr = tell( m_hFile ); + + return TRUE; +} + +//writes iBytesToWrite from buffer +//TODO:check for file being opened for writing +BOOL CFile::Write( void* pBuff, int iBytesToWrite, int* piBytesWritten ) +{ + if ( !m_bOpened ) + return FALSE; + + int iBytesWritten = write( m_hFile, pBuff, iBytesToWrite ); + + if ( piBytesWritten ) + *piBytesWritten = iBytesWritten; + + if ( -1 == iBytesWritten ) + return FALSE; + + m_lCurrPtr = tell( m_hFile ); + m_bIsDirty = TRUE; + + return TRUE; +} + +//seek +BOOL CFile::Seek( long lPos, int iType ) +{ + m_lCurrPtr = lseek( m_hFile, lPos, iType ); + + return TRUE; +} + +//closes the file +void CFile::Close() +{ + if ( m_hFile ) + close( m_hFile ); + + m_bIsDirty = FALSE; + m_hFile = 0; + m_bOpened = FALSE; +} + diff --git a/jindroush/lib/cfs.cpp b/jindroush/lib/cfs.cpp new file mode 100644 index 0000000..17de630 --- /dev/null +++ b/jindroush/lib/cfs.cpp @@ -0,0 +1,69 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cfs.h" + +CDirEntry::CDirEntry() +{ + *m_szFname = '\0'; + *m_szAscData = '\0'; + m_dwFlags = 0; + m_pSubdir = NULL; + m_pNext = NULL; + m_pPrev = NULL; + + #ifdef _MEMORY_DUMP_ + printf( "CDirEntry constructed: %08X\n", this ); + #endif +} + +CDirEntry::~CDirEntry() +{ + #ifdef _MEMORY_DUMP_ + printf( "CDirEntry destructed: %08X\n", this ); + #endif +} + +CFs::CFs() +{ + #ifdef _MEMORY_DUMP_ + printf( "CFs constructed: %08X\n", this ); + #endif +} + +CFs::~CFs() +{ + #ifdef _MEMORY_DUMP_ + printf( "CFs destructed: %08X\n", this ); + #endif +} + +void CFs::DeleteList( CDirEntry* pList ) +{ + CDirEntry* pCurr = pList; + CDirEntry* pNext; + + while( pCurr ) + { + if ( pCurr->m_pSubdir ) + DeleteList( pCurr->m_pSubdir ); + + pNext = pCurr->m_pNext; + delete pCurr; + + pCurr = pNext; + } +} + diff --git a/jindroush/lib/cfs_b2b.cpp b/jindroush/lib/cfs_b2b.cpp new file mode 100644 index 0000000..8b62ded --- /dev/null +++ b/jindroush/lib/cfs_b2b.cpp @@ -0,0 +1,156 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cfs_b2b.h" +#include "autil.h" + +CBas2Boot::CBas2Boot() : CFs() +{ + #ifdef _MEMORY_DUMP_ + printf( "CBas2Boot constructed: %08X\n", this ); + #endif +} + +CBas2Boot::~CBas2Boot() +{ + Dismount(); + #ifdef _MEMORY_DUMP_ + printf( "CBas2Boot destructed: %08X\n", this ); + #endif +} + +BOOL CBas2Boot::Mount( ADisk* pDisk ) +{ + m_iFilesValid = 0; + m_iFilesInvalid = 0; + m_pDisk = pDisk; + m_pRoot = NULL; + + if ( m_pDisk->GetSectorSize() != 0x80 ) + { + sprintf( m_szLastError, "BAS2BOOT: Can't process DD disk!" ); + return FALSE; + } + + m_pRoot = CreateEntry(); + + return m_pRoot ? TRUE : FALSE; +} + +void CBas2Boot::Dismount() +{ + DeleteList( m_pRoot ); +} + +CBas2BootDirEntry* CBas2Boot::CreateEntry() +{ + CBas2BootDirEntry* pE = new CBas2BootDirEntry(); + + if ( !pE ) + return NULL; + + BYTE abtSec[ 0x100 ]; + + if ( !m_pDisk->ReadSector( abtSec, 1 ) ) + { + sprintf( m_szLastError, "BAS2BOOT: Can't read boot sector because\n%s", m_pDisk->GetLastError() ); + delete pE; + return NULL; + } + + pE->m_dwFileLen = abtSec[ 8 ] + ( abtSec[ 9 ] << 8 ); + + if ( !m_pDisk->ReadSector( abtSec, 2 ) ) + { + sprintf( m_szLastError, "BAS2BOOT: Can't read boot sector because\n%s", m_pDisk->GetLastError() ); + delete pE; + return NULL; + } + + int iSectors = ( ( pE->m_dwFileLen - 0x0E + 0x7F ) / 0x80 ); + int iStoredSectors = abtSec[ 0x70 ] + ( abtSec[ 0x71 ] << 8 ); + + if ( ( iSectors - 1 ) != iStoredSectors ) + { + sprintf( m_szLastError, "BAS2BOOT: Not a Bas2Boot image or invalid! (%d<>%d)", iSectors - 1, iStoredSectors ); + delete pE; + return NULL; + } + + + if ( ( iSectors + 2 ) > m_pDisk->GetSectorCount() ) + { + sprintf( m_szLastError, "BAS2BOOT: Not a Bas2Boot image or invalid! (%d<>%d)", iSectors + 2, m_pDisk->GetSectorCount() ); + delete pE; + return NULL; + } + + sprintf( pE->m_szAscData, "%06lX", pE->m_dwFileLen ); + + GuessBestFnameFromPC( pE->m_szFname, m_pDisk->GetImageName(), "bas" ); + + return pE; +} + +BOOL CBas2Boot::ExportFile( char* szOutFile, CDirEntry* pDirE ) +{ + int hOutfile = -1; + + if ( szOutFile ) + { + hOutfile = open( szOutFile, O_BINARY | O_CREAT | O_TRUNC | O_WRONLY, 0666 ); + + if ( -1 == hOutfile ) + { + sprintf( m_szLastError, "BAS2BOOT: Unable to create file '%s'!", szOutFile ); + return FALSE; + } + } + + DWORD dwFileLen = ((CBas2BootDirEntry*)pDirE) ->m_dwFileLen; + + BYTE abtBuff[ 0x80 ]; + + int iSector = 3; + + m_pDisk->ReadSector( abtBuff, 2 ); + if ( -1 != hOutfile ) + write( hOutfile, abtBuff + 0x72, 0x0E ); + + dwFileLen -= 0xE; + + while( dwFileLen ) + { + WORD wToCopy = ( dwFileLen < 0x80 ) ? dwFileLen : 0x80; + + if ( !m_pDisk->ReadSector( abtBuff, iSector ) ) + { + sprintf( m_szLastError, "BAS2BOOT: Can't read sector because\n%s", m_pDisk->GetLastError() ); + return FALSE; + } + + if ( -1 != hOutfile ) + write( hOutfile, abtBuff, wToCopy ); + + dwFileLen -= wToCopy; + iSector++; + + } + if ( -1 != hOutfile ) + close( hOutfile ); + + return TRUE; +} + diff --git a/jindroush/lib/cfs_boot.cpp b/jindroush/lib/cfs_boot.cpp new file mode 100644 index 0000000..b1279ac --- /dev/null +++ b/jindroush/lib/cfs_boot.cpp @@ -0,0 +1,128 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cfs_boot.h" +#include "autil.h" +#include "adsk_xfd.h" + +CBoot::CBoot() : CFs() +{ + #ifdef _MEMORY_DUMP_ + printf( "CBoot constructed: %08X\n", this ); + #endif +} + +CBoot::~CBoot() +{ + Dismount(); + #ifdef _MEMORY_DUMP_ + printf( "CBoot destructed: %08X\n", this ); + #endif +} + +BOOL CBoot::Mount( ADisk* pDisk ) +{ + m_iFilesValid = 0; + m_iFilesInvalid = 0; + m_pDisk = pDisk; + m_pRoot = NULL; + + m_pRoot = CreateEntry(); + + return m_pRoot ? TRUE : FALSE; +} + +void CBoot::Dismount() +{ + DeleteList( m_pRoot ); +} + +CBootDirEntry* CBoot::CreateEntry() +{ + CBootDirEntry* pE = new CBootDirEntry(); + + if ( !pE ) + return NULL; + + pE->m_iSectorCount = m_pDisk->GetBootSectorCount(); + + if ( pE->m_iSectorCount > m_pDisk->GetSectorCount() ) + { + sprintf( m_szLastError, "BOOT: Overlaps end of file!" ); + delete pE; + return NULL; + } + + sprintf( pE->m_szAscData, "%08X", pE->m_iSectorCount ); + + GuessBestFnameFromPC( pE->m_szFname, m_pDisk->GetImageName(), "xfd", "_boot" ); + + return pE; +} + +BOOL CBoot::ExportFile( char* szOutFile, CDirEntry* pDirE ) +{ + if ( !szOutFile ) + return TRUE; + + CXfd newdisk; + + DISK_GEOMETRY dg; + + int iSecCount = ((CBootDirEntry*)pDirE)->m_iSectorCount; + + dg.iSides = 1; + dg.iTracks = 1; + dg.iSectorsPerTrack = iSecCount; + dg.iBytesPerSector = 0x80; + + if ( !newdisk.Format( &dg ) ) + { + sprintf( m_szLastError, "BOOT: File '%s' can't create because\n%s", szOutFile, newdisk.GetLastError() ); + return FALSE; + } + + int iStartSec = 1; + int iCurrSec = 1; + + BYTE abtBuff[ MAX_ATARI_SECTOR_LEN ]; + + while( iSecCount ) + { + if( !m_pDisk->ReadSector( abtBuff, iStartSec++ ) ) + { + sprintf( m_szLastError, "BOOT: File '%s' can't create because\n%s", szOutFile, m_pDisk->GetLastError() ); + return FALSE; + } + + if ( !newdisk.WriteSector( iCurrSec++, abtBuff ) ) + { + sprintf( m_szLastError, "BOOT: File '%s' can't create because\n%s", szOutFile, newdisk.GetLastError() ); + return FALSE; + } + + iSecCount--; + } + + if ( !newdisk.Save( szOutFile, FALSE ) ) + { + sprintf( m_szLastError, "BOOT: File '%s' can't create because\n%s", szOutFile, newdisk.GetLastError() ); + return FALSE; + } + + + return TRUE; +} + diff --git a/jindroush/lib/cfs_dos2.cpp b/jindroush/lib/cfs_dos2.cpp new file mode 100644 index 0000000..81a8037 --- /dev/null +++ b/jindroush/lib/cfs_dos2.cpp @@ -0,0 +1,224 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cfs_dos2.h" +#include "autil.h" + +#define ROOT_DIR 361 + +CDos2::CDos2() : CFs() +{ + #ifdef _MEMORY_DUMP_ + printf( "CDos2 constructed: %08X\n", this ); + #endif +} + +CDos2::~CDos2() +{ + Dismount(); + #ifdef _MEMORY_DUMP_ + printf( "CDos2 destructed: %08X\n", this ); + #endif +} + +BOOL CDos2::Mount( ADisk* pDisk ) +{ + m_iFilesValid = 0; + m_iFilesInvalid = 0; + + m_pDisk = pDisk; + m_pRoot = NULL; + + DOS2_DIRENT dire; + + WORD wEntry = 0; + + CDos2DirEntry* pPrev = NULL; + + do + { + BYTE abtSec[ 0x100 ]; + + if ( !m_pDisk->ReadSector( abtSec, ROOT_DIR + ( wEntry / 8 ) ) ) + { + sprintf( m_szLastError, "DOS2: Can't read directory entry %04X because\n%s", wEntry, m_pDisk->GetLastError() ); + return FALSE; + } + + //this is not endian-safe + //memcpy( &dire, abtSec + ( wEntry % 8) * sizeof( DOS2_DIRENT ), sizeof( DOS2_DIRENT ) ); + BYTE* pTmp = abtSec + ( wEntry % 8) * sizeof( DOS2_DIRENT ); + dire.btFlags = MGET_B( pTmp ); + dire.wSecCount = MGET_LEW( pTmp ); + dire.wSecStart = MGET_LEW( pTmp ); + memcpy( dire.acAtariName, pTmp, 11 ); + + if ( !dire.btFlags ) + break; + + CDos2DirEntry* pE = CreateEntry( &dire, wEntry ); + + if ( pE && ! ( pE->m_dwFlags & DIRE_DELETED ) ) + { + if ( m_pRoot ) + { + pPrev->m_pNext = pE; + pE->m_pPrev = pPrev; + pPrev = pE; + } + else + { + m_pRoot = pE; + pPrev = pE; + } + + } + + wEntry++; + + } while( dire.btFlags && ( wEntry < 64 ) ); + + return TRUE; +} + +void CDos2::Dismount() +{ + DeleteList( m_pRoot ); +} + +CDos2DirEntry* CDos2::CreateEntry( DOS2_DIRENT* pDire, WORD wEntry ) +{ + CDos2DirEntry* pE = new CDos2DirEntry(); + + if ( !pE ) + { + sprintf( m_szLastError, "DOS2: Can't allocate memory for directory!" ); + return NULL; + } + + if ( pDire->btFlags == 0x80 ) + { + pE->m_dwFlags |= DIRE_DELETED; + } + + ADos2MsDos( pE->m_szFname, pDire->acAtariName ); + + sprintf( pE->m_szAscData, "%02X %04X %04X", pDire->btFlags, pDire->wSecStart, pDire->wSecCount ); + + pE->m_wFileNumber = wEntry; + pE->m_btFlags = pDire->btFlags; + pE->m_wSecStart = pDire->wSecStart; + pE->m_wSecCount = pDire->wSecCount; + + if ( pE->m_dwFlags & DIRE_DELETED ) + { + } + else if ( ExportFile( NULL, pE ) ) + m_iFilesValid++; + else + m_iFilesInvalid++; + + return pE; +} + +BOOL CDos2::ExportFile( char* szOutFile, CDirEntry* pDirE ) +{ + int hOutfile = -1; + + if ( szOutFile ) + { + hOutfile = open( szOutFile, O_BINARY | O_CREAT | O_TRUNC | O_WRONLY, 0666 ); + + if ( -1 == hOutfile ) + { + sprintf( m_szLastError, "DOS2: Unable to create file '%s'!", szOutFile ); + return FALSE; + } + } + + BYTE abtBuff[ 0x0100 ]; + + WORD wSector = ((CDos2DirEntry*)pDirE ) -> m_wSecStart; + WORD wCount = ((CDos2DirEntry*)pDirE ) -> m_wSecCount; + WORD wSectorSize = m_pDisk->GetSectorSize(); + WORD wFileNumber = ((CDos2DirEntry*)pDirE ) -> m_wFileNumber; + + abtBuff[ wSectorSize - 1 ] = 0; + + while( wCount ) + { + if ( wSector < 1 ) + { + sprintf( m_szLastError, "DOS2: Corrupted file '%s' (invalid sector %04X)", szOutFile, wSector ); + return FALSE; + } + + if ( ( abtBuff[ wSectorSize - 1 ] & 0x80 ) && ( wSectorSize == 0x80 ) ) + { + sprintf( m_szLastError, "DOS2: Corrupted file '%s' (unexpected EOF)", szOutFile ); + return FALSE; + } + + if ( !m_pDisk->ReadSector( abtBuff, wSector ) ) + { + sprintf( m_szLastError, "DOS2: Corrupted file '%s'\n%s\n", szOutFile, m_pDisk->GetLastError() ); + return FALSE; + } + + /* + if ( -1 != hOutfile ) + { + printf( "%04X/%04X %02X | %02X %02X %02X\n", + wSector, + wCount, + wFileNumber, + abtBuff[ wSectorSize - 3 ], + abtBuff[ wSectorSize - 2 ], + abtBuff[ wSectorSize - 1 ] ); + } + */ + + wSector = abtBuff[ wSectorSize - 2 ] + ( 0x03 & abtBuff[ wSectorSize - 3 ] ) * 0x100; + + if ( ( abtBuff[ wSectorSize-3 ] >> 2 ) != wFileNumber ) + { + WORD wFN = abtBuff[ wSectorSize - 3 ] >> 2; + + sprintf( m_szLastError, "DOS2: Corrupted file '%s' (167: file number mismatch [%04X != %04X])", szOutFile, wFileNumber, wFN ); + return FALSE; + } + + + if ( -1 != hOutfile ) + write( hOutfile, abtBuff, abtBuff[ wSectorSize - 1 ] ); + + wCount--; + } + + if ( ((CDos2DirEntry*)pDirE ) -> m_wSecCount ) + { + if ( ! ( abtBuff[ wSectorSize - 1 ] & 128 ) && ( wSectorSize == 128 ) && wSector) + { + sprintf( m_szLastError, "DOS2: Corrupted file '%s' (expected EOF, code %02X, next sector %04X)", szOutFile, abtBuff[ wSectorSize - 1 ], wSector ); + return FALSE; + } + } + + if ( -1 != hOutfile ) + close( hOutfile ); + + return TRUE; +} + diff --git a/jindroush/lib/cfs_dos3.cpp b/jindroush/lib/cfs_dos3.cpp new file mode 100644 index 0000000..2eca4b2 --- /dev/null +++ b/jindroush/lib/cfs_dos3.cpp @@ -0,0 +1,209 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cfs_dos3.h" +#include "autil.h" + +#define ROOT_DIR 0x10 +#define FAT 0x18 + +CDos3::CDos3() : CFs() +{ + #ifdef _MEMORY_DUMP_ + printf( "CDos3 constructed: %08X\n", this ); + #endif +} + +CDos3::~CDos3() +{ + Dismount(); + #ifdef _MEMORY_DUMP_ + printf( "CDos3 destructed: %08X\n", this ); + #endif +} + +BOOL CDos3::Mount( ADisk* pDisk ) +{ + m_iFilesValid = 0; + m_iFilesInvalid = 0; + m_pDisk = pDisk; + m_pRoot = NULL; + + if ( m_pDisk->GetSectorSize() != 0x80 ) + { + sprintf( m_szLastError, "DOS3: Can't process DD disk!" ); + return FALSE; + } + + CDos3DirEntry* pPrev = NULL; + + DOS3_DIRENT dire; + + WORD wEntry = 1; + + if ( !pDisk->ReadSector( m_abtFat, FAT ) ) + { + sprintf( m_szLastError, "DOS3: Can't read FAT sector because\n%s", m_pDisk->GetLastError() ); + return FALSE; + } + + do + { + BYTE abtSec[ 0x100 ]; + + if ( !pDisk->ReadSector( abtSec, ROOT_DIR + ( wEntry / 8 ) ) ) + { + sprintf( m_szLastError, "DOS3: Can't read directory entry %04X because\n%s", wEntry, m_pDisk->GetLastError() ); + return FALSE; + } + + memcpy( &dire, abtSec + ( wEntry % 8) * sizeof( DOS3_DIRENT ), sizeof( DOS3_DIRENT ) ); + + if ( !dire.btFlags ) + break; + + CDos3DirEntry* pE = CreateEntry( &dire ); + + if ( pE && ! ( pE->m_dwFlags & DIRE_DELETED ) ) + { + if ( m_pRoot ) + { + pPrev->m_pNext = pE; + pE->m_pPrev = pPrev; + pPrev = pE; + } + else + { + m_pRoot = pE; + pPrev = pE; + } + + } + + wEntry++; + + } while( dire.btFlags ); + + return TRUE; +} + +void CDos3::Dismount() +{ + DeleteList( m_pRoot ); +} + +CDos3DirEntry* CDos3::CreateEntry( DOS3_DIRENT* pDire ) +{ + CDos3DirEntry* pE = new CDos3DirEntry(); + + if ( !pE ) + return NULL; + + if ( pDire->btFlags == 0x80 ) + { + pE->m_dwFlags |= DIRE_DELETED; + } + + ADos2MsDos( pE->m_szFname, pDire->acAtariName ); + + //sprintf( pE->m_szAscData, "%02X %02X %02X %04X", pDire->btSecStart, pDire->btSecCount, pDire->btFlags, pDire->wFileLen ); + sprintf( pE->m_szAscData, "%02X %04X", pDire->btFlags, pDire->wFileLen ); + + pE->m_btSecStart = pDire->btSecStart; + pE->m_btSecCount = pDire->btSecCount; + pE->m_btFlags = pDire->btFlags; + pE->m_wFileLen = pDire->wFileLen; + + if ( pE->m_dwFlags & DIRE_DELETED ) + { + } + else if ( ExportFile( NULL, pE ) ) + m_iFilesValid++; + else + m_iFilesInvalid++; + + return pE; +} + +BOOL CDos3::ExportFile( char* szOutFile, CDirEntry* pDirE ) +{ + int hOutfile = -1; + + if ( szOutFile ) + { + hOutfile = open( szOutFile, O_BINARY | O_CREAT | O_TRUNC | O_WRONLY, 0666 ); + + if ( -1 == hOutfile ) + { + sprintf( m_szLastError, "DOS3: Unable to create file '%s'!", szOutFile ); + return FALSE; + } + } + + BYTE abtBuff[ 0x80 * 8 ]; + + BYTE btSecCount = ((CDos3DirEntry*)pDirE) ->m_btSecCount; + BYTE btSector = ((CDos3DirEntry*)pDirE) ->m_btSecStart; + WORD wFileLen = ((CDos3DirEntry*)pDirE) ->m_wFileLen; + + while( btSecCount ) + { + WORD wToCopy = ( wFileLen < 0x400 ) ? wFileLen : 0x400; + + if ( !m_pDisk->ReadSectors( abtBuff, ( btSector * 8 ) + FAT + 1, 8 ) ) + { + { + sprintf( m_szLastError, "DOS3: Corrupted file '%s'\n%s\n", szOutFile, m_pDisk->GetLastError() ); + return FALSE; + } + } + + if ( -1 != hOutfile ) + write( hOutfile, abtBuff, wToCopy ); + + btSecCount--; + wFileLen -= wToCopy; + + btSector = m_abtFat[ btSector ]; + + if ( wToCopy == 0x400 ) + { + if ( btSector >= 0xFD ) + { + sprintf( m_szLastError, "DOS3: Corrupted file '%s' (unexpected EOF)", szOutFile ); + return FALSE; + } + + } + else + { + if ( btSector != 0xFD ) + { + sprintf( m_szLastError, "DOS3: Corrupted file '%s' (missed EOF) %02X", szOutFile, btSector ); + return FALSE; + } + + } + + + } + + + if ( -1 != hOutfile ) + close( hOutfile ); + + return TRUE; +} + diff --git a/jindroush/lib/cfs_dosm.cpp b/jindroush/lib/cfs_dosm.cpp new file mode 100644 index 0000000..96c04fb --- /dev/null +++ b/jindroush/lib/cfs_dosm.cpp @@ -0,0 +1,240 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cfs_dosm.h" +#include "autil.h" + +#define ROOT_DIR 361 + +CDosM::CDosM() : CFs() +{ + #ifdef _MEMORY_DUMP_ + printf( "CDosM constructed: %08X\n", this ); + #endif +} + +CDosM::~CDosM() +{ + Dismount(); + #ifdef _MEMORY_DUMP_ + printf( "CDosM destructed: %08X\n", this ); + #endif +} + +BOOL CDosM::Mount( ADisk* pDisk ) +{ + m_iFilesValid = 0; + m_iFilesInvalid = 0; + + m_pDisk = pDisk; + m_pRoot = NULL; + + return ReadDir( ROOT_DIR, (CDosMDirEntry**)&m_pRoot ); +} + +BOOL CDosM::ReadDir( int iSector, CDosMDirEntry** ppRoot ) +{ + DOSM_DIRENT dire; + + WORD wEntry = 0; + + CDosMDirEntry* pPrev = NULL; + + do + { + BYTE abtSec[ 0x100 ]; + + //printf( "reading sec %d\n", iSector + ( wEntry / 8 ) ); + + if ( !m_pDisk->ReadSector( abtSec, iSector + ( wEntry / 8 ) ) ) + { + sprintf( m_szLastError, "DOSM: Can't read directory entry %04X because\n%s", wEntry, m_pDisk->GetLastError() ); + return FALSE; + } + + //this is not endian-safe + //memcpy( &dire, abtSec + ( wEntry % 8) * sizeof( DOSM_DIRENT ), sizeof( DOSM_DIRENT ) ); + BYTE* pTmp = abtSec + ( wEntry % 8) * sizeof( DOSM_DIRENT ); + dire.btFlags = MGET_B( pTmp ); + dire.wSecCount = MGET_LEW( pTmp ); + dire.wSecStart = MGET_LEW( pTmp ); + memcpy( dire.acAtariName, pTmp, 11 ); + + //printf( "%p %p %04X %02X\n", pTmp, abtSec, wEntry, dire.btFlags ); + + if ( !dire.btFlags ) + break; + + CDosMDirEntry* pE = CreateEntry( &dire ); + + if ( pE && ! ( pE->m_dwFlags & DIRE_DELETED ) ) + { + if ( *ppRoot ) + { + pPrev->m_pNext = pE; + pE->m_pPrev = pPrev; + pPrev = pE; + } + else + { + *ppRoot = pE; + pPrev = pE; + } + + } + + wEntry++; + + } while( dire.btFlags && ( wEntry < 64 ) ); + + return TRUE; +} + +void CDosM::Dismount() +{ + DeleteList( m_pRoot ); +} + +CDosMDirEntry* CDosM::CreateEntry( DOSM_DIRENT* pDire ) +{ + CDosMDirEntry* pE = new CDosMDirEntry(); + + if ( !pE ) + { + sprintf( m_szLastError, "DOSM: Can't allocate memory for directory!" ); + return NULL; + } + + if ( pDire->btFlags == 0x80 ) + { + pE->m_dwFlags |= DIRE_DELETED; + } + + ADos2MsDos( pE->m_szFname, pDire->acAtariName ); + + sprintf( pE->m_szAscData, "%02X %04X %04X", pDire->btFlags, pDire->wSecStart, pDire->wSecCount ); + //printf( "%02X %04X %04X %s\n", pDire->btFlags, pDire->wSecStart, pDire->wSecCount, pE->m_szFname ); + + pE->m_btFlags = pDire->btFlags; + pE->m_wSecStart = pDire->wSecStart; + pE->m_wSecCount = pDire->wSecCount; + + if ( pDire->btFlags == 0x10 ) + { + pE->m_dwFlags |= DIRE_SUBDIR; + + BOOL bRes = ReadDir( pE->m_wSecStart, (CDosMDirEntry**)&pE->m_pSubdir ); + + if ( !bRes ) + return NULL; + } + else + { + if ( pE->m_dwFlags & DIRE_DELETED ) + { + } + else if ( ExportFile( NULL, pE ) ) + { + m_iFilesValid++; + } + else + { + m_iFilesInvalid++; + } + } + + return pE; +} + +BOOL CDosM::ExportFile( char* szOutFile, CDirEntry* pDirE ) +{ + int hOutfile = -1; + + if ( szOutFile ) + { + hOutfile = open( szOutFile, O_BINARY | O_CREAT | O_TRUNC | O_WRONLY, 0666 ); + + if ( -1 == hOutfile ) + { + sprintf( m_szLastError, "DOSM: Unable to create file '%s'!", szOutFile ); + return FALSE; + } + } + + BYTE abtBuff[ 0x0100 ]; + + WORD wSector = ((CDosMDirEntry*)pDirE ) -> m_wSecStart; + WORD wCount = ((CDosMDirEntry*)pDirE ) -> m_wSecCount; + WORD wSectorSize = m_pDisk->GetSectorSize(); + + abtBuff[ wSectorSize - 1 ] = 0; + + while( wCount ) + { + if ( wSector < 1 ) + { + sprintf( m_szLastError, "DOSM: Corrupted file '%s' (invalid sector %04X)", szOutFile, wSector ); + return FALSE; + } + + if ( ( abtBuff[ wSectorSize - 1 ] & 0x80 ) && ( wSectorSize == 0x80 ) ) + { + sprintf( m_szLastError, "DOSM: Corrupted file '%s' (unexpected EOF)", szOutFile ); + return FALSE; + } + + if ( !m_pDisk->ReadSector( abtBuff, wSector ) ) + { + sprintf( m_szLastError, "DOSM: Corrupted file '%s'\n%s\n", szOutFile, m_pDisk->GetLastError() ); + return FALSE; + } + +// if ( -1 != hOutfile ) +// { +// printf( "%04X/%04X | %02X %02X %02X\n", +// wSector, +// wCount, +// abtBuff[ wSectorSize - 3 ], +// abtBuff[ wSectorSize - 2 ], +// abtBuff[ wSectorSize - 1 ] ); +// } + + //originally, there was 0x07 as a mask, but megaimages were not working with it + if ( m_pDisk->GetSectorCount() > 943 ) + wSector = abtBuff[ wSectorSize - 2 ] + ( (WORD)abtBuff[ wSectorSize - 3 ] & 0xff ) * 0x100; + else + wSector = abtBuff[ wSectorSize - 2 ] + ( 0x03 & (WORD)abtBuff[ wSectorSize - 3 ] ) * 0x100; + + if ( -1 != hOutfile ) + write( hOutfile, abtBuff, abtBuff[ wSectorSize - 1 ] ); + + wCount--; + } + + if ( ((CDosMDirEntry*)pDirE ) -> m_wSecCount ) + { + if ( ! ( abtBuff[ wSectorSize - 1 ] & 128 ) && ( wSectorSize == 128 ) && wSector) + { + sprintf( m_szLastError, "DOSM: Corrupted file '%s' (expected EOF, code %02X, next sector %04X)", szOutFile, abtBuff[ wSectorSize - 1 ], wSector ); + return FALSE; + } + } + + if ( -1 != hOutfile ) + close( hOutfile ); + + return TRUE; +} + diff --git a/jindroush/lib/cfs_doss.cpp b/jindroush/lib/cfs_doss.cpp new file mode 100644 index 0000000..42092ec --- /dev/null +++ b/jindroush/lib/cfs_doss.cpp @@ -0,0 +1,383 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cfs_doss.h" +#include "autil.h" + +#define SP3TOLONG(dire) ( ( dire.btSizeHi << 16 ) + dire.wSizeLo ) + +CDosS::CDosS() : CFs() +{ + #ifdef _MEMORY_DUMP_ + printf( "CDosS constructed: %08X\n", this ); + #endif +} + +CDosS::~CDosS() +{ + Dismount(); + #ifdef _MEMORY_DUMP_ + printf( "CDosS destructed: %08X\n", this ); + #endif +} + +BOOL CDosS::Mount( ADisk* pDisk ) +{ + m_iFilesValid = 0; + m_iFilesInvalid = 0; + + m_pDisk = pDisk; + m_pRoot = NULL; + + if ( m_pDisk->GetBootSectorCount() != 3 ) + { + sprintf( m_szLastError, "DOSS: Strange boot sector!" ); + return FALSE; + } + + int iSize = m_pDisk->GetBootSectorSize(); + + BYTE* pBoot = new BYTE [ iSize ]; + + if ( !pBoot ) + { + sprintf( m_szLastError, "DOSS: Not enough memory to allocate boot sector!" ); + return FALSE; + } + + if ( !m_pDisk->GetBootSector( pBoot ) ) + { + sprintf( m_szLastError, "DOSS: Can't read boot sector because\n%s", m_pDisk->GetLastError() ); + delete [] pBoot; + return FALSE; + } + + BYTE btSpDosIdent = pBoot[ 7 ]; + + if ( btSpDosIdent != 0x80 ) + { + sprintf( m_szLastError, "DOSS: Mismatched boot." ); + delete [] pBoot; + return FALSE; + } + + m_wMainDirStart = pBoot[ 9 ] + ( pBoot[ 10 ] << 8 ); + //WORD wSectors = pBoot[ 11 ] + ( pBoot[ 12 ] << 8 ); + //WORD wFreeSectors = pBoot[ 13 ] + ( pBoot[ 14 ] << 8 ); + //BYTE btBitmapSectors = pBoot[ 15 ]; + //WORD wFirstBitmapSector = pBoot[ 16 ] + ( pBoot[ 17 ] << 8 ); + //WORD wFreeDataSector = pBoot[ 18 ] + ( pBoot[ 19 ] << 8 ); + //WORD wFreeDirSector = pBoot[ 20 ] + ( pBoot[ 21 ] << 8 ); + //22-29 volume name + + switch( pBoot[ 31 ] ) + { + case 0: + m_wSectorSize = 0x100; + break; + + case 0x80: + m_wSectorSize = 0x80; + break; + + default: + { + sprintf( m_szLastError, "DOSS: Unknown sector size %02X!", pBoot[ 31 ] ); + delete [] pBoot; + return FALSE; + } + + } + + //BYTE btVersion = pBoot[ 32 ]; + //BYTE btSeqNumber = pBoot[ 38 ]; + //BYTE btRndNumber = pBoot[ 39 ]; + //WORD wDosBootStart = pBoot[ 40 ] + ( pBoot[ 41 ] << 8 ); + + delete [] pBoot; + + return ReadDir( m_wMainDirStart, (CDosSDirEntry**)&m_pRoot ); +} + +int CDosS::GetSectorLinkEntry( int iLink, int iSec ) +{ + WORD awSector[ 0x80 ]; + + int iCurrLink = iLink; + + int iDivisor = 0; + switch( m_wSectorSize ) + { + case 0x80: + iDivisor = 0x3E; + break; + + case 0x100: + iDivisor = 0x7E; + break; + + default: + return 0; + + } + + int iSecNeeded = ( iSec / iDivisor ) + 1; + + do + { + if ( !m_pDisk->ReadSector( awSector, iCurrLink ) ) + { + sprintf( m_szLastError, "DOSS: Can't read link sector because\n%s", m_pDisk->GetLastError() ); + return 0; + } + + iSecNeeded--; + //not endian-safe + //iCurrLink = awSector[ 0 ]; + iCurrLink = MREAD_LEW( (BYTE*)awSector ); + if ( iSec >= iDivisor ) + iSec -= iDivisor; + + } while( iSecNeeded ); + + //not endian-safe + //return awSector[ iSec + 2 ]; + return MREAD_LEW( (BYTE*)(awSector + iSec + 2 )); +} + +BOOL CDosS::ReadDir( int iSectorLink, CDosSDirEntry** ppRoot ) +{ + DOSS_DIRENT dire; + + BYTE abtSector[ 0x100 ]; + + int iSector = GetSectorLinkEntry( iSectorLink, 0 ); + + if ( !m_pDisk->ReadSector( abtSector, iSector ) ) + { + sprintf( m_szLastError, "DOSS: Can't read dir because\n%s", m_pDisk->GetLastError() ); + return FALSE; + } + + //not endian safe + //memcpy( &dire, abtSector, sizeof( DOSS_DIRENT ) ); + BYTE* pTmp = abtSector; + dire.btFlags = MGET_B( pTmp ); + dire.wSector = MGET_LEW( pTmp ); + dire.wSizeLo = MGET_LEW( pTmp ); + dire.btSizeHi = MGET_B( pTmp ); + memcpy( dire.acAtariName, pTmp, 11 ); pTmp+= 11; + memcpy( &dire.btDay, pTmp, 6 ); //dirty hack, copying last 6 byte values + + int iDirLen = SP3TOLONG( dire ); + BYTE* pDir = MapFile( iSectorLink, iDirLen ); + if ( !pDir ) + return FALSE; + + int iEntries = iDirLen / sizeof( DOSS_DIRENT ); + + //if ( iDirLen != iEntries * (int)sizeof( DOSS_DIRENT ) ) + //{ + // UnMapFile( pDir ); + // sprintf( m_szLastError, "DOSS: Dir size mismatch! (%04X<>%04X)\n", + // iDirLen, + // iEntries * (int)sizeof( DOSS_DIRENT ) + // ); + // return FALSE; + //} + + CDosSDirEntry* pPrev = NULL; + + for( int i = 1; i < iEntries; i++ ) + { + + DOSS_DIRENT dire2; + BYTE* pTmp = pDir + i * sizeof( DOSS_DIRENT ); + dire2.btFlags = MGET_B( pTmp ); + dire2.wSector = MGET_LEW( pTmp ); + dire2.wSizeLo = MGET_LEW( pTmp ); + dire2.btSizeHi = MGET_B( pTmp ); + memcpy( dire2.acAtariName, pTmp, 11 ); pTmp+= 11; + memcpy( &dire2.btDay, pTmp, 6 ); //dirty hack, copying last 6 byte values + + CDosSDirEntry* pE = CreateEntry( &dire2 ); + + if ( pE && ! ( pE->m_dwFlags & DIRE_DELETED ) ) + { + if ( *ppRoot ) + { + pPrev->m_pNext = pE; + pE->m_pPrev = pPrev; + pPrev = pE; + } + else + { + *ppRoot = pE; + pPrev = pE; + } + + } + + } + + UnMapFile( pDir ); + + return TRUE; +} + +void CDosS::Dismount() +{ + DeleteList( m_pRoot ); +} + +CDosSDirEntry* CDosS::CreateEntry( DOSS_DIRENT* pDire ) +{ + CDosSDirEntry* pE = new CDosSDirEntry(); + + if ( !pE ) + { + sprintf( m_szLastError, "DOSS: Can't allocate memory for directory!" ); + return NULL; + } + + ADos2MsDos( pE->m_szFname, pDire->acAtariName ); + + sprintf( pE->m_szAscData, "%02X %04X %02X%04X %02d-%02d-19%02d %2d:%02d.%02d", + pDire->btFlags, + pDire->wSector, + pDire->btSizeHi, + pDire->wSizeLo, + pDire->btMonth, + pDire->btDay, + pDire->btYear, + pDire->btHour, + pDire->btMinute, + pDire->btSecond + ); + + pE->m_iLength = ( pDire->btSizeHi << 16 ) + pDire->wSizeLo; + pE->m_iLinkSector = pDire->wSector; + + if ( pDire->btFlags == 0x10 ) + { + pE->m_dwFlags |= DIRE_DELETED; + } + + if ( ! ( pDire->btFlags && 0x08 ) ) + { + pE->m_dwFlags |= DIRE_DELETED; + } + + if ( pDire->btFlags & 0x20 ) + { + pE->m_dwFlags |= DIRE_SUBDIR; + + BOOL bRes = ReadDir( pE->m_iLinkSector, (CDosSDirEntry**)&pE->m_pSubdir ); + + if ( !bRes ) + { + delete pE; + return NULL; + } + } + else + { + if ( pE->m_dwFlags & DIRE_DELETED ) + { + } + else if ( ExportFile( NULL, pE ) ) + m_iFilesValid++; + else + m_iFilesInvalid++; + } + + return pE; +} + +BOOL CDosS::ExportFile( char* szOutFile, CDirEntry* pDirE ) +{ + int hOutfile = -1; + + if ( szOutFile ) + { + hOutfile = open( szOutFile, O_BINARY | O_CREAT | O_TRUNC | O_WRONLY, 0666 ); + + if ( -1 == hOutfile ) + { + sprintf( m_szLastError, "DOSS: Unable to create file '%s'!", szOutFile ); + return FALSE; + } + } + + int iLinkSector = ((CDosSDirEntry*)pDirE ) -> m_iLinkSector; + int iLength = ((CDosSDirEntry*)pDirE ) -> m_iLength; + + BYTE* pDir = MapFile( iLinkSector, iLength ); + + if ( !pDir ) + { + return FALSE; + } + + if ( -1 != hOutfile ) + write( hOutfile, pDir, iLength ); + + UnMapFile( pDir ); + + if ( -1 != hOutfile ) + close( hOutfile ); + + return TRUE; +} + +BYTE* CDosS::MapFile( int iLinkSector, int iLength ) +{ + BYTE* pBuff = new BYTE [ iLength ]; + + if ( !pBuff ) + return NULL; + + int iLogSector = 0; + + BYTE abtBuff[ 0x100 ]; + BYTE * p = pBuff; + + while( iLength ) + { + int iToCopy = ( iLength > m_wSectorSize ) ? m_wSectorSize : iLength; + + int iSector = GetSectorLinkEntry( iLinkSector, iLogSector ); + + if ( !m_pDisk->ReadSector( abtBuff, iSector ) ) + { + sprintf( m_szLastError, "DOSS: Can't read file sector because\n%s", m_pDisk->GetLastError() ); + delete [] pBuff; + return 0; + } + + memcpy( p, abtBuff, iToCopy ); + iLength -= iToCopy; + p += iToCopy; + iLogSector++; + } + + return pBuff; +} + +void CDosS::UnMapFile( BYTE * pBuff ) +{ + if ( pBuff ) + delete [] pBuff; +} diff --git a/jindroush/lib/cfs_howf.cpp b/jindroush/lib/cfs_howf.cpp new file mode 100644 index 0000000..2fa71ae --- /dev/null +++ b/jindroush/lib/cfs_howf.cpp @@ -0,0 +1,209 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cfs_howf.h" +#include "autil.h" +#include "adsk_atr.h" + +#define HOWF_MAX_NAME 32 +#define HOWF_REASONABLE_NAME ( HOWF_MAX_NAME - 7 ) + +CHowf::CHowf() : CFs() +{ + #ifdef _MEMORY_DUMP_ + printf( "CHowf constructed: %08X\n", this ); + #endif +} + +CHowf::~CHowf() +{ + Dismount(); + #ifdef _MEMORY_DUMP_ + printf( "CHowf destructed: %08X\n", this ); + #endif +} + +BOOL CHowf::Mount( ADisk* pDisk ) +{ + m_iFilesValid = 0; + m_iFilesInvalid = 0; + m_pDisk = pDisk; + m_pRoot = NULL; + + if ( m_pDisk->GetSectorSize() != 0x80 ) + { + sprintf( m_szLastError, "HOWF: Can't process DD disk!" ); + return FALSE; + } + + switch( m_pDisk->GetBootSectorCount() ) + { + case 0x0A: + break; + + default: + { + sprintf( m_szLastError, "HOWF: Can't identify disk as a HowFen menu!" ); + return FALSE; + } + } + + CHowfDirEntry* pPrev = NULL; + + BYTE abtSec[ 0xA * 0x80 ]; + + if ( !m_pDisk->ReadSectors( abtSec, 0x1, 0xA ) ) + { + sprintf( m_szLastError, "HOWF: Can't read directory because\n%s", m_pDisk->GetLastError() ); + return FALSE; + } + + BYTE* pbtName = abtSec + 0x89; + BYTE* abtStartSecLo = abtSec + 0x32A; + BYTE* abtStartSecHi = abtSec + 0x33E; + + BYTE btRecords = abtSec[ 0x329 ]; + + for( int i = 0; i < btRecords; i++ ) + { + WORD wStartSec = *abtStartSecLo + ( *abtStartSecHi << 8 ); + + if ( !wStartSec ) + break; + + CHowfDirEntry* pE = CreateEntry( wStartSec, pbtName ); + + if ( m_pRoot ) + { + pPrev->m_pNext = pE; + pE->m_pPrev = pPrev; + pPrev = pE; + } + else + { + m_pRoot = pE; + pPrev = pE; + } + + abtStartSecLo++; + abtStartSecHi++; + pbtName += HOWF_MAX_NAME; + } + + return TRUE; +} + +void CHowf::Dismount() +{ + DeleteList( m_pRoot ); +} + +CHowfDirEntry* CHowf::CreateEntry( WORD wStartSec, BYTE* btName ) +{ + CHowfDirEntry* pE = new CHowfDirEntry(); + + if ( !pE ) + return NULL; + + pE->m_iStartSec = wStartSec; + + sprintf( pE->m_szAscData, "%04X", wStartSec ); + + char szTemp[ HOWF_REASONABLE_NAME + 1 ]; + memcpy( szTemp, (char*)btName + 3, HOWF_REASONABLE_NAME ); + szTemp[ HOWF_REASONABLE_NAME ] = '\0'; + + for( int i = 0; i < HOWF_REASONABLE_NAME; i++ ) + { + char c = szTemp[ i ]; + if ( ( c >= 0x00 ) && ( c <= 0x40 ) ) + c += 0x20; + + szTemp[ i ] = c; + } + + GuessBestFnameFromAtari( pE->m_szFname, szTemp, "atr" ); + + if ( ExportFile( NULL, pE ) ) + m_iFilesValid++; + else + m_iFilesInvalid++; + + return pE; +} + +BOOL CHowf::ExportFile( char* szOutFile, CDirEntry* pDirE ) +{ + int iSecCount; + int iStartSec = ((CHowfDirEntry*)pDirE) ->m_iStartSec; + + BYTE abtBuff[ 0x80 ]; + + m_pDisk->ReadSector( abtBuff, iStartSec ); + + iSecCount = abtBuff[1]; + + if ( ( iStartSec + iSecCount - 1 ) > m_pDisk->GetSectorCount() ) + { + sprintf( m_szLastError, "HOWF: File '%s' goes past last sector!", szOutFile ); + return FALSE; + } + + if ( !szOutFile ) + return TRUE; + + CAtr newdisk; + + DISK_GEOMETRY dg; + + dg.iSides = 1; + dg.iTracks = 1; + dg.iSectorsPerTrack = iSecCount; + dg.iBytesPerSector = 0x80; + + if ( !newdisk.Format( &dg ) ) + { + sprintf( m_szLastError, "HOWF: File '%s' can't create because\n%s", szOutFile, newdisk.GetLastError() ); + return FALSE; + } + + int iCurrSec = 1; + + while( iSecCount ) + { + if( !m_pDisk->ReadSector( abtBuff, iStartSec++ ) ) + { + sprintf( m_szLastError, "HOWF: File '%s' can't create because\n%s", szOutFile, m_pDisk->GetLastError() ); + return FALSE; + } + + if ( !newdisk.WriteSector( iCurrSec++, abtBuff ) ) + { + sprintf( m_szLastError, "HOWF: File '%s' can't create because\n%s", szOutFile, newdisk.GetLastError() ); + return FALSE; + } + + iSecCount--; + } + + if ( !newdisk.Save( szOutFile, FALSE ) ) + { + sprintf( m_szLastError, "HOWF: File '%s' can't create because\n%s", szOutFile, newdisk.GetLastError() ); + return FALSE; + } + + return TRUE; +} + diff --git a/jindroush/lib/cfs_jonw.cpp b/jindroush/lib/cfs_jonw.cpp new file mode 100644 index 0000000..6517bee --- /dev/null +++ b/jindroush/lib/cfs_jonw.cpp @@ -0,0 +1,204 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cfs_jonw.h" +#include "autil.h" +#include "adsk_atr.h" + +#define JONW_MAX_NAME 20 + +CJonw::CJonw() : CFs() +{ + #ifdef _MEMORY_DUMP_ + printf( "CJonw constructed: %08X\n", this ); + #endif +} + +CJonw::~CJonw() +{ + Dismount(); + #ifdef _MEMORY_DUMP_ + printf( "CJonw destructed: %08X\n", this ); + #endif +} + +BOOL CJonw::Mount( ADisk* pDisk ) +{ + m_iFilesValid = 0; + m_iFilesInvalid = 0; + m_pDisk = pDisk; + m_pRoot = NULL; + + if ( m_pDisk->GetSectorSize() != 0x80 ) + { + sprintf( m_szLastError, "JONW: Can't process DD disk!" ); + return FALSE; + } + + switch( m_pDisk->GetBootSectorCount() ) + { + case 0x28: + case 0x29: + case 0x2F: + break; + + default: + { + sprintf( m_szLastError, "JONW: Can't identify disk as a JonW menu!" ); + return FALSE; + } + } + + CJonwDirEntry* pPrev = NULL; + + BYTE abtSec[ 0x100 ]; + + if ( !m_pDisk->ReadSectors( abtSec, 0x30, 2 ) ) + { + sprintf( m_szLastError, "JONW: Can't read directory because\n%s", m_pDisk->GetLastError() ); + return FALSE; + } + + BYTE* abtSecCounts = abtSec; + BYTE* abtStartSecLo = abtSec + 10; + BYTE* abtStartSecHi = abtSec + 20; + BYTE* pbtName = abtSec + 30; + + for( int i = 0; i < 10; i++ ) + { + if ( ! *abtSecCounts ) + break; + + CJonwDirEntry* pE = CreateEntry( *abtSecCounts, *abtStartSecLo + ( *abtStartSecHi << 8 ), pbtName ); + + if ( m_pRoot ) + { + pPrev->m_pNext = pE; + pE->m_pPrev = pPrev; + pPrev = pE; + } + else + { + m_pRoot = pE; + pPrev = pE; + } + + abtSecCounts++; + abtStartSecLo++; + abtStartSecHi++; + pbtName += JONW_MAX_NAME; + } + + return TRUE; +} + +void CJonw::Dismount() +{ + DeleteList( m_pRoot ); +} + +CJonwDirEntry* CJonw::CreateEntry( BYTE btSecCount, WORD wStartSec, BYTE* btName ) +{ + CJonwDirEntry* pE = new CJonwDirEntry(); + + if ( !pE ) + return NULL; + + pE->m_iStartSec = wStartSec; + pE->m_iSecCount = btSecCount; + + sprintf( pE->m_szAscData, "%04X %02X", wStartSec, btSecCount ); + + char szTemp[ 21 ]; + strncpy( szTemp, (char*)btName, 20 ); + szTemp[ 20 ] = '\0'; + + GuessBestFnameFromAtari( pE->m_szFname, szTemp, "atr" ); + + if ( ExportFile( NULL, pE ) ) + m_iFilesValid++; + else + m_iFilesInvalid++; + + return pE; +} + +BOOL CJonw::ExportFile( char* szOutFile, CDirEntry* pDirE ) +{ + int iSecCount = ((CJonwDirEntry*)pDirE) ->m_iSecCount; + int iStartSec = ((CJonwDirEntry*)pDirE) ->m_iStartSec; + + BYTE abtBuff[ 0x80 ]; + + if ( ( iStartSec + iSecCount - 1 ) > m_pDisk->GetSectorCount() ) + { + sprintf( m_szLastError, "JONW: File '%s' goes past last sector!", szOutFile ); + return FALSE; + } + + m_pDisk->ReadSector( abtBuff, iStartSec ); + + if ( abtBuff[ 1 ] != iSecCount ) + { + sprintf( m_szLastError, "JONW: File '%s' Mismatched length (%d<>%d)!", szOutFile, abtBuff[ 1 ], iSecCount ); + return FALSE; + } + + if ( !szOutFile ) + return TRUE; + + CAtr newdisk; + + DISK_GEOMETRY dg; + + dg.iSides = 1; + dg.iTracks = 1; + dg.iSectorsPerTrack = iSecCount; + dg.iBytesPerSector = 0x80; + + if ( !newdisk.Format( &dg ) ) + { + sprintf( m_szLastError, "JONW: File '%s' can't create because\n%s", szOutFile, newdisk.GetLastError() ); + return FALSE; + } + + int iCurrSec = 1; + + while( iSecCount ) + { + if( !m_pDisk->ReadSector( abtBuff, iStartSec++ ) ) + { + sprintf( m_szLastError, "JONW: File '%s' can't create because\n%s", szOutFile, m_pDisk->GetLastError() ); + return FALSE; + } + + if ( !newdisk.WriteSector( iCurrSec++, abtBuff ) ) + { + sprintf( m_szLastError, "JONW: File '%s' can't create because\n%s", szOutFile, newdisk.GetLastError() ); + return FALSE; + } + + iSecCount--; + } + + if ( !newdisk.Save( szOutFile, FALSE ) ) + { + sprintf( m_szLastError, "JONW: File '%s' can't create because\n%s", szOutFile, newdisk.GetLastError() ); + return FALSE; + } + + return TRUE; +} + diff --git a/jindroush/lib/cfs_kboo.cpp b/jindroush/lib/cfs_kboo.cpp new file mode 100644 index 0000000..526e9a6 --- /dev/null +++ b/jindroush/lib/cfs_kboo.cpp @@ -0,0 +1,148 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cfs_kboo.h" +#include "autil.h" + +CKBoot::CKBoot() : CFs() +{ + #ifdef _MEMORY_DUMP_ + printf( "CKBoot constructed: %08X\n", this ); + #endif +} + +CKBoot::~CKBoot() +{ + Dismount(); + #ifdef _MEMORY_DUMP_ + printf( "CKBoot destructed: %08X\n", this ); + #endif +} + +BOOL CKBoot::Mount( ADisk* pDisk ) +{ + m_iFilesValid = 0; + m_iFilesInvalid = 0; + m_pDisk = pDisk; + m_pRoot = NULL; + + if ( m_pDisk->GetSectorSize() != 0x80 ) + { + sprintf( m_szLastError, "KBOOT: Can't process DD disk!" ); + return FALSE; + } + + m_pRoot = CreateEntry(); + + return m_pRoot ? TRUE : FALSE; +} + +void CKBoot::Dismount() +{ + DeleteList( m_pRoot ); +} + +CKBootDirEntry* CKBoot::CreateEntry() +{ + CKBootDirEntry* pE = new CKBootDirEntry(); + + if ( !pE ) + return NULL; + + BYTE abtSec[ 0x100 ]; + + if ( !m_pDisk->ReadSector( abtSec, 1 ) ) + { + sprintf( m_szLastError, "KBOOT: Can't read boot sector because\n%s", m_pDisk->GetLastError() ); + delete pE; + return NULL; + } + + pE->m_dwFileLen = abtSec[ 9 ] + ( abtSec[ 10 ] << 8 ) + ( abtSec[ 11 ] << 16 ); + + if ( !m_pDisk->ReadSector( abtSec, 4 ) ) + { + sprintf( m_szLastError, "KBOOT: Can't read first post boot sector because\n%s", m_pDisk->GetLastError() ); + delete pE; + return NULL; + } + + if ( ( abtSec[ 0 ] != 0xFF ) || ( abtSec[ 1 ] != 0xFF ) ) + { + sprintf( m_szLastError, "KBOOT: Not a KBoot image!" ); + delete pE; + return NULL; + } + + int iSectors = 3 + ( ( pE->m_dwFileLen + 0x7F ) / 0x80 ); + + if ( iSectors > m_pDisk->GetSectorCount() ) + { + sprintf( m_szLastError, "KBOOT: Not a KBoot image or invalid! (%d<>%d)", iSectors, m_pDisk->GetSectorCount() ); + delete pE; + return NULL; + } + + sprintf( pE->m_szAscData, "%06lX", pE->m_dwFileLen ); + + GuessBestFnameFromPC( pE->m_szFname, m_pDisk->GetImageName(), "axe" ); + + return pE; +} + +BOOL CKBoot::ExportFile( char* szOutFile, CDirEntry* pDirE ) +{ + int hOutfile = -1; + + if ( szOutFile ) + { + hOutfile = open( szOutFile, O_BINARY | O_CREAT | O_TRUNC | O_WRONLY, 0666 ); + + if ( -1 == hOutfile ) + { + sprintf( m_szLastError, "KBOOT: Unable to create file '%s'!", szOutFile ); + return FALSE; + } + } + + DWORD dwFileLen = ((CKBootDirEntry*)pDirE) ->m_dwFileLen; + + BYTE abtBuff[ 0x80 ]; + + int iSector = 4; + + while( dwFileLen ) + { + WORD wToCopy = ( dwFileLen < 0x80 ) ? dwFileLen : 0x80; + + if ( !m_pDisk->ReadSector( abtBuff, iSector ) ) + { + sprintf( m_szLastError, "KBOOT: Can't read sector because\n%s", m_pDisk->GetLastError() ); + return FALSE; + } + + if ( -1 != hOutfile ) + write( hOutfile, abtBuff, wToCopy ); + + dwFileLen -= wToCopy; + iSector++; + + } + if ( -1 != hOutfile ) + close( hOutfile ); + + return TRUE; +} + diff --git a/jindroush/lib/cfs_robc.cpp b/jindroush/lib/cfs_robc.cpp new file mode 100644 index 0000000..089b4bc --- /dev/null +++ b/jindroush/lib/cfs_robc.cpp @@ -0,0 +1,231 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cfs_robc.h" +#include "autil.h" +#include "adsk_atr.h" + +#define ROBC_MAX_NAME 20 + +CRobc::CRobc() : CFs() +{ + #ifdef _MEMORY_DUMP_ + printf( "CRobc constructed: %08X\n", this ); + #endif +} + +CRobc::~CRobc() +{ + Dismount(); + #ifdef _MEMORY_DUMP_ + printf( "CRobc destructed: %08X\n", this ); + #endif +} + +BOOL CRobc::Mount( ADisk* pDisk ) +{ + m_iFilesValid = 0; + m_iFilesInvalid = 0; + m_pDisk = pDisk; + m_pRoot = NULL; + + if ( m_pDisk->GetSectorSize() != 0x80 ) + { + sprintf( m_szLastError, "ROBC: Can't process DD disk!" ); + return FALSE; + } + + switch( m_pDisk->GetBootSectorCount() ) + { + case 0x04: + break; + + default: + { + sprintf( m_szLastError, "ROBC: Can't identify disk as a RobC menu!" ); + return FALSE; + } + } + + CRobcDirEntry* pPrev = NULL; + + BYTE abtSec[ 0x180 ]; + + if ( !m_pDisk->ReadSectors( abtSec, 0x02, 3 ) ) + { + sprintf( m_szLastError, "ROBC: Can't read directory because\n%s", m_pDisk->GetLastError() ); + return FALSE; + } + + BYTE* abtStartSecLo = abtSec + 0x77; + BYTE* abtStartSecHi = abtSec + 0x6E; + BYTE* pbtName = abtSec + 0xB9; + + for( int i = 0; i < 10; i++ ) + { + WORD wSec = *abtStartSecLo + ( *abtStartSecHi << 8 ); + + //printf( "%d) %04X\n", i, wSec ); + + if ( ! wSec ) + continue; + + BYTE abtLocSec[ 0x80 ]; + BYTE btSecCount; + + if( !m_pDisk->ReadSector( abtLocSec, wSec ) ) + { + sprintf( m_szLastError, "ROBC: Can't read dir entry %d!", i ); + return FALSE; + } + + btSecCount = abtLocSec[ 1 ]; + + if ( ! btSecCount ) + break; + + CRobcDirEntry* pE = CreateEntry( btSecCount, wSec, pbtName + 2 ); + + if ( m_pRoot ) + { + pPrev->m_pNext = pE; + pE->m_pPrev = pPrev; + pPrev = pE; + } + else + { + m_pRoot = pE; + pPrev = pE; + } + + abtStartSecLo++; + abtStartSecHi++; + pbtName += ROBC_MAX_NAME; + } + + return TRUE; +} + +void CRobc::Dismount() +{ + DeleteList( m_pRoot ); +} + +CRobcDirEntry* CRobc::CreateEntry( BYTE btSecCount, WORD wStartSec, BYTE* btName ) +{ + CRobcDirEntry* pE = new CRobcDirEntry(); + + if ( !pE ) + return NULL; + + pE->m_iStartSec = wStartSec; + pE->m_iSecCount = btSecCount; + + sprintf( pE->m_szAscData, "%04X %02X", wStartSec, btSecCount ); + + char szTemp[ ROBC_MAX_NAME + 1 - 2 ]; + memcpy( szTemp, btName, ROBC_MAX_NAME - 2 ); + szTemp[ ROBC_MAX_NAME - 2 ] = '\0'; + + //printf( "%s\n", szTemp ); + + char* szT = szTemp; + + while( *szT ) + { + *szT &= 0x7F; + *szT -= 0x20; + szT++; + } + + GuessBestFnameFromAtari( pE->m_szFname, szTemp, "atr" ); + + //printf( "%s\n", pE->m_szFname ); + + if ( ExportFile( NULL, pE ) ) + m_iFilesValid++; + else + m_iFilesInvalid++; + + return pE; +} + +BOOL CRobc::ExportFile( char* szOutFile, CDirEntry* pDirE ) +{ + int iSecCount = ((CRobcDirEntry*)pDirE) ->m_iSecCount; + int iStartSec = ((CRobcDirEntry*)pDirE) ->m_iStartSec; + + BYTE abtBuff[ 0x80 ]; + + if ( ( iStartSec + iSecCount - 1 ) > m_pDisk->GetSectorCount() ) + { + sprintf( m_szLastError, "ROBC: File '%s' goes past last sector!", szOutFile ); + return FALSE; + } + + m_pDisk->ReadSector( abtBuff, iStartSec ); + + if ( abtBuff[ 1 ] != iSecCount ) + { + sprintf( m_szLastError, "ROBC: File '%s' Mismatched length (%d<>%d)!", szOutFile, abtBuff[ 1 ], iSecCount ); + return FALSE; + } + + if ( !szOutFile ) + return TRUE; + + CAtr newdisk; + + DISK_GEOMETRY dg; + + dg.iSides = 1; + dg.iTracks = 1; + dg.iSectorsPerTrack = iSecCount; + dg.iBytesPerSector = 0x80; + + if ( !newdisk.Format( &dg ) ) + { + sprintf( m_szLastError, "ROBC: File '%s' can't create because\n%s", szOutFile, newdisk.GetLastError() ); + return FALSE; + } + + int iCurrSec = 1; + + while( iSecCount ) + { + if( !m_pDisk->ReadSector( abtBuff, iStartSec++ ) ) + { + sprintf( m_szLastError, "ROBC: File '%s' can't create because\n%s", szOutFile, m_pDisk->GetLastError() ); + return FALSE; + } + + if ( !newdisk.WriteSector( iCurrSec++, abtBuff ) ) + { + sprintf( m_szLastError, "ROBC: File '%s' can't create because\n%s", szOutFile, newdisk.GetLastError() ); + return FALSE; + } + + iSecCount--; + } + + if ( !newdisk.Save( szOutFile, FALSE ) ) + { + sprintf( m_szLastError, "ROBC: File '%s' can't create because\n%s", szOutFile, newdisk.GetLastError() ); + return FALSE; + } + + return TRUE; +} + diff --git a/jindroush/lib/cgenfile.cpp b/jindroush/lib/cgenfile.cpp new file mode 100644 index 0000000..66d678d --- /dev/null +++ b/jindroush/lib/cgenfile.cpp @@ -0,0 +1,95 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cgenfile.h" + +//writes little-endian dword +void CGenFile::writeLEdw( DWORD dwT ) +{ + writeb( dwT & 0xFF ); + writeb( ( dwT >> 8 ) & 0xFF ); + writeb( ( dwT >>16 ) & 0xFF ); + writeb( ( dwT >>24 ) & 0xFF ); +} + +//writes little-endian word +void CGenFile::writeLEw( WORD wT ) +{ + writeb( wT & 0xFF ); + writeb( ( wT >> 8 ) & 0xFF ); +} + +void CGenFile::writeBEw( WORD wT ) +{ + writeb( ( wT >> 8 ) & 0xFF ); + writeb( wT & 0xFF ); +} + +//reads little-endian word +WORD CGenFile::readLEw() +{ + WORD wT; + wT = readb(); + wT |= readb() << 8; + return wT; +} + +WORD CGenFile::readBEw() +{ + WORD wT; + wT = readb() << 8; + wT |= readb(); + return wT; +} + + +//reads little-endian dword +DWORD CGenFile::readLEdw() +{ + DWORD dwT; + dwT = readb(); + dwT |= readb() << 8; + dwT |= readb() << 16; + dwT |= readb() << 24; + + return dwT; +} + +//writes byte +void CGenFile::writeb( BYTE btT ) +{ + Write( &btT, 1, NULL ); +} + +//reads byte +BYTE CGenFile::readb() +{ + BYTE btPom; + Read( &btPom, 1, NULL ); + return btPom; +} + +//skips part of file +BOOL CGenFile::skip( long lSkip ) +{ + return Seek( lSkip, SEEK_CUR ); +} + +//gets current value of pointer +long CGenFile::Tell() +{ + return m_lCurrPtr; +} + diff --git a/jindroush/lib/cobj.cpp b/jindroush/lib/cobj.cpp new file mode 100644 index 0000000..9c2a6c6 --- /dev/null +++ b/jindroush/lib/cobj.cpp @@ -0,0 +1,23 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cobj.h" + +CObj::CObj() +{ + *m_szLastError = '\0'; + m_iErrorCode = 0; +} + diff --git a/jindroush/lib/cprefile.cpp b/jindroush/lib/cprefile.cpp new file mode 100644 index 0000000..b96cdfe --- /dev/null +++ b/jindroush/lib/cprefile.cpp @@ -0,0 +1,153 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "cprefile.h" + +CPreFile::CPreFile() +{ + m_lCacheStartOffset = -1; + m_lCacheEndOffset = -1; + m_bOpened = FALSE; + m_pbtCache = NULL; +} + +CPreFile::~CPreFile() +{ + Close(); +} + +BOOL CPreFile::Open( CGenFile* pcf, int iCacheSizeKB ) +{ + m_lCacheLen = 1024 * iCacheSizeKB; + + if ( m_bOpened ) + return FALSE; + + m_pcf = pcf; + + m_pcf->Seek( 0, SEEK_END ); + + m_lLength = m_pcf->Tell(); + + if ( m_lLength < m_lCacheLen ) + { + m_lCacheLen = m_lLength; + } + + if ( ! ( m_pbtCache = new BYTE [ m_lCacheLen ] ) ) + return FALSE; + + m_pcf->Seek( 0, SEEK_SET ); + + m_lCurrPtr = 0; + + m_bOpened = TRUE; + + PreRead(); + + return TRUE; + +} + +BOOL CPreFile::PreRead() +{ + m_pcf->Seek( m_lCurrPtr, SEEK_SET ); + m_lCacheStartOffset = m_lCurrPtr; + m_lCacheEndOffset = m_lCacheStartOffset + m_lCacheLen - 1; + + m_pcf->Read( m_pbtCache, m_lCacheLen ); + + return TRUE; +} + +BOOL CPreFile::Read( void* pBuff, int iLen, int* piLen ) +{ + if ( !m_bOpened ) + return FALSE; + + if ( m_lCurrPtr > m_lLength ) + return FALSE; + + if ( iLen >= m_lCacheLen ) + { + m_pcf->Seek( m_lCurrPtr, SEEK_SET ); + if ( !m_pcf->Read( pBuff, iLen, piLen ) ) + return FALSE; + + m_lCurrPtr = m_pcf->Tell(); + m_lCacheEndOffset = -1; + return TRUE; + } + + if ( ( m_lCurrPtr < m_lCacheStartOffset ) || ( m_lCurrPtr > m_lCacheEndOffset ) ) + PreRead(); + + long lReadEnd = m_lCurrPtr + iLen - 1; + + if ( lReadEnd >= m_lCacheEndOffset ) + { + m_pcf->Seek( m_lCurrPtr, SEEK_SET ); + if ( !m_pcf->Read( pBuff, iLen, piLen ) ) + return FALSE; + + m_lCurrPtr = m_pcf->Tell(); + m_lCacheEndOffset = -1; + + return TRUE; + } + + memcpy( pBuff, m_pbtCache + m_lCurrPtr - m_lCacheStartOffset, iLen ); + m_lCurrPtr += iLen; + + return TRUE; +} + +BOOL CPreFile::Write( void* pBuff, int iLen, int* piLen ) +{ + return FALSE; +} + +BOOL CPreFile::Seek( long lPos, int iType ) +{ + + switch( iType ) + { + case SEEK_SET: + m_lCurrPtr = lPos; + break; + + case SEEK_CUR: + m_lCurrPtr += lPos; + break; + + case SEEK_END: + m_lCurrPtr = m_lLength - lPos; + break; + + } + return TRUE; +} + +void CPreFile::Close() +{ + m_bOpened = FALSE; + + if ( m_pbtCache ) + delete [] m_pbtCache; + + m_pbtCache = NULL; + m_lCurrPtr = 0; +} + diff --git a/jindroush/man/Makefile b/jindroush/man/Makefile new file mode 100644 index 0000000..bfe47c0 --- /dev/null +++ b/jindroush/man/Makefile @@ -0,0 +1,12 @@ +DESTDIR= +PREFIX=/usr/local +MANDIR=$(PREFIX)/man +MAN1DIR=$(MANDIR)/man1 +GZIP_MAN=y +RST2MAN=rst2man +MANS=acvt.1 adir.1 aext.1 bas2boot.1 chkbas.1 chkexe.1 chkrom.1 + +all: $(MANS) + +%.1: %.rst manhdr.rst manftr.rst + $(RST2MAN) $< > $@ diff --git a/jindroush/man/acvt.1 b/jindroush/man/acvt.1 new file mode 100644 index 0000000..4336fe7 --- /dev/null +++ b/jindroush/man/acvt.1 @@ -0,0 +1,116 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "ACVT" 1 "2024-05-16" "1.07" "Jindroush's Atari 8-bit tools" +.SH NAME +acvt \- convert between Atari 8-bit disk image formats +.SH SYNOPSIS +.sp +acvt [\fB\-xfd\fP | \fB\-atr\fP | \fB\-scp\fP | \fB\-dcm\fP | \fB\-di\fP] [\fB\-batchmode\fP] [\fB\-autorepair\fP] [\fB\-norepair\fP] [\fB\-errstop\fP] [\fB\-over\fP] [\fB\-test\fP] [\fB\-classic\fP] \fIinput\-file\fP [\fIoutput\-file\fP] +.SH DESCRIPTION +.sp +\fBacvt\fP converts Atari 8\-bit images between various formats. It can +also repair some kinds of problems with broken/corrupted images. +.sp +Supported formats are: +.INDENT 0.0 +.INDENT 3.5 +.INDENT 0.0 +.TP +.B ATR +Originally defined by SIOPC; the modern standard format. +.TP +.B XFD +Originally defined by the XFormer emulator; raw images. +.TP +.B DCM +DiskComm (Disk Communicator) images. +.TP +.B SCP +SpartaDOS SCOPY images. +.TP +.B DI +XL/ST link / XLDJ disk images. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +If no \fIoutput\-file\fP is given, the filename is created automatically by +replacing the filename extension (e.g. \fIfoo.xfd\fP becomes \fIfoo.atr\fP). +.sp +If the output file already exists, it will not be overwritten unless +the \fB\-over\fP option is given. +.sp +If the input file is invalid, \fBacvt\fP may prompt for a repair method. +.SH OPTIONS +.INDENT 0.0 +.TP +.B \fB\-xfd\fP, \fB\-atr\fP, \fB\-scp\fP, \fB\-dcm\fP, \fB\-di\fP +Output disk image format. Default is \fB\-atr\fP\&. +.TP +.B \fB\-batchmode\fP +Multi\-file processing mode. Only input files are specified on command\-line. +Regular expressions are allowed. Output filenames are created automatically. +.TP +.B \fB\-autorepair\fP +Automatically determines the best repair method (rather than prompting). +.TP +.B \fB\-norepair\fP +Doesn\(aqt ask for repair options and considers input file invalid if it needs repair. +.TP +.B \fB\-errstop\fP +In batch mode, exits on the first error encountered. +.TP +.B \fB\-over\fP +Overwrites existing files. +.TP +.B \fB\-test\fP +Load input images and display their state, but do not write output. +.TP +.B \fB\-classic\fP +Force output to be one of the classic Atari disk sizes (90K, 128K, 180K). +.UNINDENT +.SH COPYRIGHT +.sp +This utility is released under the GNU General Public License. +.SH AUTHORS +.sp +This utility was written by Jindrich Kubec, AKA Jindroush. +.sp +This page was written by B. Watson <\fI\%urchlay@slackware.uk\fP>. +.SH SEE ALSO +.sp +\fBacvt\fP(1), +\fBaext\fP(1), +\fBbas2boot\fP(1), +\fBchkbas\fP(1), +\fBchkexe\fP(1), +\fBchkrom\fP(1). +.\" Generated by docutils manpage writer. +. diff --git a/jindroush/man/acvt.rst b/jindroush/man/acvt.rst new file mode 100644 index 0000000..925ffbc --- /dev/null +++ b/jindroush/man/acvt.rst @@ -0,0 +1,77 @@ +.. |version| replace:: 1.07 + +==== +acvt +==== + +---------------------------------------------- +convert between Atari 8-bit disk image formats +---------------------------------------------- + +.. include:: manhdr.rst + +SYNOPSIS +======== + +acvt [**-xfd** | **-atr** | **-scp** | **-dcm** | **-di**] [**-batchmode**] [**-autorepair**] [**-norepair**] [**-errstop**] [**-over**] [**-test**] [**-classic**] *input-file* [*output-file*] + +DESCRIPTION +=========== + +**acvt** converts Atari 8-bit images between various formats. It can +also repair some kinds of problems with broken/corrupted images. + +Supported formats are: + + ATR + Originally defined by SIOPC; the modern standard format. + + XFD + Originally defined by the XFormer emulator; raw images. + + DCM + DiskComm (Disk Communicator) images. + + SCP + SpartaDOS SCOPY images. + + DI + XL/ST link / XLDJ disk images. + +If no *output-file* is given, the filename is created automatically by +replacing the filename extension (e.g. *foo.xfd* becomes *foo.atr*). + +If the output file already exists, it will not be overwritten unless +the **-over** option is given. + +If the input file is invalid, **acvt** may prompt for a repair method. + +OPTIONS +======= + +**-xfd**, **-atr**, **-scp**, **-dcm**, **-di** + Output disk image format. Default is **-atr**. + +**-batchmode** + Multi-file processing mode. Only input files are specified on command-line. + Regular expressions are allowed. Output filenames are created automatically. + +**-autorepair** + Automatically determines the best repair method (rather than prompting). + +**-norepair** + Doesn't ask for repair options and considers input file invalid if it needs repair. + +**-errstop** + In batch mode, exits on the first error encountered. + +**-over** + Overwrites existing files. + +**-test** + Load input images and display their state, but do not write output. + +**-classic** + Force output to be one of the classic Atari disk sizes (90K, 128K, 180K). + +.. include:: manftr.rst diff --git a/jindroush/man/adir.1 b/jindroush/man/adir.1 new file mode 100644 index 0000000..8250225 --- /dev/null +++ b/jindroush/man/adir.1 @@ -0,0 +1,141 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "ADIR" 1 "2024-05-16" "0.67" "Jindroush's Atari 8-bit tools" +.SH NAME +adir \- list and extract files from Atari 8-bit disk images +.SH SYNOPSIS +.sp +adir [ [\fB\-help*] | [\fP\-dos2** | [\fB\-dos3\fP] | [\fB\-mydos\fP] | [\fB\-spdos\fP] | [\fB\-kboot\fP] | [\fB\-bas2boot\fP ] | [\fB\-jonw\fP] | [\fB\-robc\fP] | [\fB\-howf\fP] | [\fB\-boot] ] [\fP\-e**] [\fB\-dir\fP \fIpath\fP] [\fB\-dontrepair\fP] \fBdisk\-image\fP [\fBmask\fP] +.SH DESCRIPTION +.sp +\fBadir\fP lists and extracts the files contained in an Atari 8\-bit +disk image. Many Atari DOS and DOS\-like filesystems are supported, +and disk images can be in various formats. +.sp +The image types supported are: +.INDENT 0.0 +.INDENT 3.5 +.INDENT 0.0 +.TP +.B ATR +Originally defined by SIOPC; the modern standard format. +.TP +.B XFD +Originally defined by the XFormer emulator; raw images. +.TP +.B DCM +DiskComm (Disk Communicator) images. +.TP +.B SCP +SpartaDOS SCOPY images. +.TP +.B DI +XL/ST link / XLDJ disk images. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +The image type is autodetected; there are no options to override the +detection. +.sp +The filesystems supported are: +.INDENT 0.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +Atari DOS 2.0/2.5 and compatibles +.IP \(bu 2 +Atari DOS 3.0 +.IP \(bu 2 +MyDOS +.IP \(bu 2 +Sparta DOS and compatibles (BeWe, RealDOS) +.IP \(bu 2 +K\-Boot images +.IP \(bu 2 +HowFen DOS +.IP \(bu 2 +JonW multiboot +.IP \(bu 2 +RobC multiboot +.IP \(bu 2 +Bas2Boot images +.IP \(bu 2 +boot images (extracts boot sector only) +.UNINDENT +.UNINDENT +.UNINDENT +.sp +By default, \fBadir\fP attempts to autodetect the filesystem type, but it can +be set explicitly by one of the options, below. +.sp +\fBmask\fP is a wildcard mask of filenames to extract. Note that +it\(aqs case\-sensitive, meaning it generally will have to be given in +uppercase since most Atari filesystems don\(aqt support lowercase. +.SH OPTIONS +.INDENT 0.0 +.TP +.B \fB\-dos2\fP, \fB\-dos3\fP, \fB\-mydos\fP, \fB\-spdos\fP, \fB\-kboot\fP, \fB\-bas2boot\fP, \fB\-jonw\fP, \fB\-robc\fP, \fB\-howf\fP, \fB\-boot\fP +Set the filesystem type (see list, above). +.TP +.B \fB\-e\fP +Extracts files from the image. If a wildcard \fBmask\fP is given, +files matching the wildcard will be listed (and extracted, with +\fB\-e\fP). Without a \fBmask\fP, all files on the image will be +listed/extracted. +.TP +.B \fB\-dir\fP \fIpath\fP +Write extracted files to this directory, which will be created if it +doesn\(aqt already exist. Default is "." (the current directory). +.TP +.B \fB\-dontrepair\fP +Don\(aqt attempt to automatically repair invalid files. +.UNINDENT +.SH EXIT STATUS +.sp +Zero for success, non\-zero for failure. +.SH COPYRIGHT +.sp +This utility is released under the GNU General Public License. +.SH AUTHORS +.sp +This utility was written by Jindrich Kubec, AKA Jindroush. +.sp +This page was written by B. Watson <\fI\%urchlay@slackware.uk\fP>. +.SH SEE ALSO +.sp +\fBacvt\fP(1), +\fBaext\fP(1), +\fBbas2boot\fP(1), +\fBchkbas\fP(1), +\fBchkexe\fP(1), +\fBchkrom\fP(1). +.\" Generated by docutils manpage writer. +. diff --git a/jindroush/man/adir.rst b/jindroush/man/adir.rst new file mode 100644 index 0000000..eff5911 --- /dev/null +++ b/jindroush/man/adir.rst @@ -0,0 +1,89 @@ +.. |version| replace:: 0.67 + +==== +adir +==== + +--------------------------------------------------- +list and extract files from Atari 8-bit disk images +--------------------------------------------------- + +.. include:: manhdr.rst + +SYNOPSIS +======== + +adir [ [**-help*] | [**-dos2** | [**-dos3**] | [**-mydos**] | [**-spdos**] | [**-kboot**] | [**-bas2boot** ] | [**-jonw**] | [**-robc**] | [**-howf**] | [**-boot] ] [**-e**] [**-dir** *path*] [**-dontrepair**] **disk-image** [**mask**] + +DESCRIPTION +=========== + +**adir** lists and extracts the files contained in an Atari 8-bit +disk image. Many Atari DOS and DOS-like filesystems are supported, +and disk images can be in various formats. + +The image types supported are: + + ATR + Originally defined by SIOPC; the modern standard format. + + XFD + Originally defined by the XFormer emulator; raw images. + + DCM + DiskComm (Disk Communicator) images. + + SCP + SpartaDOS SCOPY images. + + DI + XL/ST link / XLDJ disk images. + +The image type is autodetected; there are no options to override the +detection. + +The filesystems supported are: + + - Atari DOS 2.0/2.5 and compatibles + - Atari DOS 3.0 + - MyDOS + - Sparta DOS and compatibles (BeWe, RealDOS) + - K-Boot images + - HowFen DOS + - JonW multiboot + - RobC multiboot + - Bas2Boot images + - boot images (extracts boot sector only) + +By default, **adir** attempts to autodetect the filesystem type, but it can +be set explicitly by one of the options, below. + +**mask** is a wildcard mask of filenames to extract. Note that +it's case-sensitive, meaning it generally will have to be given in +uppercase since most Atari filesystems don't support lowercase. + +OPTIONS +======= + +**-dos2**, **-dos3**, **-mydos**, **-spdos**, **-kboot**, **-bas2boot**, **-jonw**, **-robc**, **-howf**, **-boot** + Set the filesystem type (see list, above). + +**-e** + Extracts files from the image. If a wildcard **mask** is given, + files matching the wildcard will be listed (and extracted, with + **-e**). Without a **mask**, all files on the image will be + listed/extracted. + +**-dir** *path* + Write extracted files to this directory, which will be created if it + doesn't already exist. Default is "." (the current directory). + +**-dontrepair** + Don't attempt to automatically repair invalid files. + +EXIT STATUS +=========== + +Zero for success, non-zero for failure. + +.. include:: manftr.rst diff --git a/jindroush/man/aext.1 b/jindroush/man/aext.1 new file mode 100644 index 0000000..534c2da --- /dev/null +++ b/jindroush/man/aext.1 @@ -0,0 +1,55 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "AEXT" 1 "2024-05-16" "1.02" "Jindroush's Atari 8-bit tools" +.SH NAME +aext \- extract binary blocks from Atari 8-bit disk images +.SH SYNOPSIS +.sp +aext [\fB\-s\fP \fIstart\fP] [\fB\-e\fP \fIend\fP] [\fB\-l\fP \fIlength\fP] [\fB\-oa\fP] [\fB\-base\fP] \fBinput\-file\fP [\fBoutput\-file\fP] +.SH DESCRIPTION +.SH OPTIONS +.SH COPYRIGHT +.sp +This utility is released under the GNU General Public License. +.SH AUTHORS +.sp +This utility was written by Jindrich Kubec, AKA Jindroush. +.sp +This page was written by B. Watson <\fI\%urchlay@slackware.uk\fP>. +.SH SEE ALSO +.sp +\fBacvt\fP(1), +\fBaext\fP(1), +\fBbas2boot\fP(1), +\fBchkbas\fP(1), +\fBchkexe\fP(1), +\fBchkrom\fP(1). +.\" Generated by docutils manpage writer. +. diff --git a/jindroush/man/aext.rst b/jindroush/man/aext.rst new file mode 100644 index 0000000..ed8fb98 --- /dev/null +++ b/jindroush/man/aext.rst @@ -0,0 +1,24 @@ +.. |version| replace:: 1.02 + +==== +aext +==== + +-------------------------------------------------- +extract binary blocks from Atari 8-bit disk images +-------------------------------------------------- + +.. include:: manhdr.rst + +SYNOPSIS +======== + +aext [**-s** *start*] [**-e** *end*] [**-l** *length*] [**-oa**] [**-base**] **input-file** [**output-file**] + +DESCRIPTION +=========== + +OPTIONS +======= + +.. include:: manftr.rst diff --git a/jindroush/man/bas2boot.1 b/jindroush/man/bas2boot.1 new file mode 100644 index 0000000..7e838db --- /dev/null +++ b/jindroush/man/bas2boot.1 @@ -0,0 +1,84 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "BAS2BOOT" 1 "2024-05-16" "1.0.2" "Jindroush's Atari 8-bit tools" +.SH NAME +bas2boot \- make a bootable Atari 8-bit disk image of a BASIC program +.SH SYNOPSIS +.sp +bas2boot [\fB\-atr\fP | \fB\-xfd\fP | \fB\-scp\fP | \fB\-dcm\fP | \fB\-di\fP] [\fB\-long\fP] [\fB\-message\fP \fItext\fP] \fBbasic\-file\fP [\fBoutput\-disk\-image\fP] +.SH DESCRIPTION +.sp +\fBbas2boot\fP creates an Atari 8\-bit disk image that consists of a boot +loader followed by a tokenized Atari BASIC program. When the disk is +booted on the Atari, the BASIC program is loaded into memory and run. +.sp +There is no DOS on the disk; the BASIC program won\(aqt be able to use +the D: devices. +.sp +The bootloader will enable BASIC if possible (600XL, 800XL, all +XEs). Otherwise (400/800/1200XL), the Atari BASIC cartridge must be +inserted. The bootloader doesn\(aqt work with other BASICs like BASIC XL, +TurboBASIC, etc. +.SH OPTIONS +.INDENT 0.0 +.TP +.B \fB\-atr\fP \fB\-xfd\fP \fB\-scp\fP \fB\-dcm\fP \fB\-di\fP +Set the output image type. Default: \fB\-atr\fP\&. Note that the image +type is \fInot\fP affected by the filename extension (the default +is still \fB\-atr\fP even with a file called \fIoutput.xfd\fP). +.TP +.B \fB\-long\fP +Use \(aqclassic\(aq disk size (single density, 90KB). Default is to create a +short ATR file consisting only of the sectors used. +.TP +.B \fB\-message\fP \fItext\fP +Sets message displayed while the program is loading. +.UNINDENT +.SH EXIT STATUS +.sp +Zero for success, non\-zero for failure. +.SH COPYRIGHT +.sp +This utility is released under the GNU General Public License. +.SH AUTHORS +.sp +This utility was written by Jindrich Kubec, AKA Jindroush. +.sp +This page was written by B. Watson <\fI\%urchlay@slackware.uk\fP>. +.SH SEE ALSO +.sp +\fBacvt\fP(1), +\fBaext\fP(1), +\fBbas2boot\fP(1), +\fBchkbas\fP(1), +\fBchkexe\fP(1), +\fBchkrom\fP(1). +.\" Generated by docutils manpage writer. +. diff --git a/jindroush/man/bas2boot.rst b/jindroush/man/bas2boot.rst new file mode 100644 index 0000000..c5273e6 --- /dev/null +++ b/jindroush/man/bas2boot.rst @@ -0,0 +1,53 @@ +.. |version| replace:: 1.0.2 + +======== +bas2boot +======== + +--------------------------------------------------------- +make a bootable Atari 8-bit disk image of a BASIC program +--------------------------------------------------------- + +.. include:: manhdr.rst + +SYNOPSIS +======== + +bas2boot [**-atr** | **-xfd** | **-scp** | **-dcm** | **-di**] [**-long**] [**-message** *text*] **basic-file** [**output-disk-image**] + +DESCRIPTION +=========== + +**bas2boot** creates an Atari 8-bit disk image that consists of a boot +loader followed by a tokenized Atari BASIC program. When the disk is +booted on the Atari, the BASIC program is loaded into memory and run. + +There is no DOS on the disk; the BASIC program won't be able to use +the D: devices. + +The bootloader will enable BASIC if possible (600XL, 800XL, all +XEs). Otherwise (400/800/1200XL), the Atari BASIC cartridge must be +inserted. The bootloader doesn't work with other BASICs like BASIC XL, +TurboBASIC, etc. + +OPTIONS +======= + +**-atr** **-xfd** **-scp** **-dcm** **-di** + Set the output image type. Default: **-atr**. Note that the image + type is *not* affected by the filename extension (the default + is still **-atr** even with a file called *output.xfd*). + +**-long** + Use 'classic' disk size (single density, 90KB). Default is to create a + short ATR file consisting only of the sectors used. + +**-message** *text* + Sets message displayed while the program is loading. + +EXIT STATUS +=========== + +Zero for success, non-zero for failure. + +.. include:: manftr.rst diff --git a/jindroush/man/chkbas.1 b/jindroush/man/chkbas.1 new file mode 100644 index 0000000..1069d6c --- /dev/null +++ b/jindroush/man/chkbas.1 @@ -0,0 +1,155 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "CHKBAS" 1 "2024-05-16" "1.10" "Jindroush's Atari 8-bit tools" +.SH NAME +chkbas \- check and detokenize Atari BASIC SAVEd files +.SH SYNOPSIS +.sp +chkbas [\fB\-atari\fP] [\fB\-short\fP] [\fB\-verbose\fP] [\fB\-noinverse\fP] [\fB\-tbs\fP | \fB\-bxl\fP | \fB\-bxe\fP] \fBbasic\-file\fP [\fBoutput\-file\fP] +.sp +listbas [\fB\-atari\fP] [\fB\-verbose\fP] [\fB\-noinverse\fP] [\fB\-tbs\fP | \fB\-bxl\fP | \fB\-bxe\fP] \fBbasic\-file\fP [\fBoutput\-file\fP] +.SH DESCRIPTION +.sp +\fBchkbas\fP detokenizes Atari 8\-bit BASIC SAVEd files. It lists the BASIC +code in human\-readable form, and gives some other useful information +about the program. +.sp +\fBbasic\-file\fP is an Atari BASIC, TurboBASIC, BASIC XL, or BASIC +XE program. Output will go to \fBoutput\-file\fP, if given; otherwise, +standard output. If \fBbasic\-file\fP is anything other than standard +Atari BASIC, the BASIC dialect must be specified (see \fBOPTIONS\fP, +below). +.sp +\fBlistbas\fP is simply an alias for \fBchkbas \-short\fP\&. +.sp +Sample run, with no options: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ chkbas HELLO.BAS +chkbas v1.10 (c) 1999\-2001 Jindrich Kubec + +chkbas v1.10 (c) 1999\-2001 Jindrich Kubec +Atari Basic/Turbo Basic/Basic XL/Basic XE decompiler. + Latest version can be found at http://www.asw.cz/~kubecj + Published under GPL. See GPL.TXT. + Thanks to Russ Gilbert for his SALVAGE programs. + +Input file: HELLO.BAS + +Constants & pointers: +Start of Name Table (VNT) : 000E +End of Name Table (VNTE) : 0011 +Lenght of Name Table (VNTL) : 0004 +Start of Variable Table (VVT) : 0012 +End of Variable Table (VVTE) : 0021 +Length of Variable Table (VVTL) : 0010 +Number of Variables (NV) : 0002 +Start of Code (STMTAB): 0022 +Length of Code : 004E +Current command (STMCUR): 0070 +Length of current command : 0013 +First byte after program (STARP) : 0083 +Length of file : 0083 +File len difference : 00000000 + +Variable table: +0001 STRING (81) 00: SPoff: 0000 Len: 5 Dim: 10 A$ +0002 SCALAR (00) 01: 11 I + +Main code starts here: +10 DIM A$(10) +20 A$="HELLO" +30 FOR I=1 TO 10 +40 ? A$;" WORLD!" +50 NEXT I + +Immediate code starts here: +32768 SAVE "H:HELLO.BAS" + +Done! +.ft P +.fi +.UNINDENT +.UNINDENT +.SH OPTIONS +.SS Input Options +.INDENT 0.0 +.TP +.B \fB\-tbs\fP +Treat input as a Turbo BASIC program. +.TP +.B \fB\-bxl\fP +Treat input as a BASIC XL program. +.TP +.B \fB\-bxe\fP +Treat input as a BASIC XE program, which may or may not be EXTENDed +with code in the extra XE banks. +.UNINDENT +.SS Output Options +.INDENT 0.0 +.TP +.B \fB\-atari\fP +Output only the program listing, with lines terminated by Atari +EOL characters (\fB$9B\fP). +.TP +.B \fB\-short\fP +Output only the program listing, with lines terminated by the +system default newline character(s), e.g. \fBn\fP on UNIX\-like OSes, +\fBrn\fP on MS\-DOS or Windows. This is the default for \fBlistbas\fP\&. +.TP +.B \fB\-verbose\fP +Program listing will be interspersed with per\-line and per\-statement +low\-level information. This option is probably most useful for debugging +\fBchkbas\fP itself. +.UNINDENT +.SH EXIT STATUS +.sp +Zero for success, non\-zero for failure. +.SH COPYRIGHT +.sp +This utility is released under the GNU General Public License. +.SH AUTHORS +.sp +This utility was written by Jindrich Kubec, AKA Jindroush. +.sp +This page was written by B. Watson <\fI\%urchlay@slackware.uk\fP>. +.SH SEE ALSO +.sp +\fBacvt\fP(1), +\fBaext\fP(1), +\fBbas2boot\fP(1), +\fBchkbas\fP(1), +\fBchkexe\fP(1), +\fBchkrom\fP(1). +.\" Generated by docutils manpage writer. +. diff --git a/jindroush/man/chkbas.rst b/jindroush/man/chkbas.rst new file mode 100644 index 0000000..2f9e6b7 --- /dev/null +++ b/jindroush/man/chkbas.rst @@ -0,0 +1,118 @@ +.. |version| replace:: 1.10 + +====== +chkbas +====== + +-------------------------------------------- +check and detokenize Atari BASIC SAVEd files +-------------------------------------------- + +.. include:: manhdr.rst + +SYNOPSIS +======== + +chkbas [**-atari**] [**-short**] [**-verbose**] [**-noinverse**] [**-tbs** | **-bxl** | **-bxe**] **basic-file** [**output-file**] + +listbas [**-atari**] [**-verbose**] [**-noinverse**] [**-tbs** | **-bxl** | **-bxe**] **basic-file** [**output-file**] + +DESCRIPTION +=========== + +**chkbas** detokenizes Atari 8-bit BASIC SAVEd files. It lists the BASIC +code in human-readable form, and gives some other useful information +about the program. + +**basic-file** is an Atari BASIC, TurboBASIC, BASIC XL, or BASIC +XE program. Output will go to **output-file**, if given; otherwise, +standard output. If **basic-file** is anything other than standard +Atari BASIC, the BASIC dialect must be specified (see **OPTIONS**, +below). + +**listbas** is simply an alias for **chkbas -short**. + +Sample run, with no options:: + + $ chkbas HELLO.BAS + chkbas v1.10 (c) 1999-2001 Jindrich Kubec + + chkbas v1.10 (c) 1999-2001 Jindrich Kubec + Atari Basic/Turbo Basic/Basic XL/Basic XE decompiler. + Latest version can be found at http://www.asw.cz/~kubecj + Published under GPL. See GPL.TXT. + Thanks to Russ Gilbert for his SALVAGE programs. + + Input file: HELLO.BAS + + Constants & pointers: + Start of Name Table (VNT) : 000E + End of Name Table (VNTE) : 0011 + Lenght of Name Table (VNTL) : 0004 + Start of Variable Table (VVT) : 0012 + End of Variable Table (VVTE) : 0021 + Length of Variable Table (VVTL) : 0010 + Number of Variables (NV) : 0002 + Start of Code (STMTAB): 0022 + Length of Code : 004E + Current command (STMCUR): 0070 + Length of current command : 0013 + First byte after program (STARP) : 0083 + Length of file : 0083 + File len difference : 00000000 + + Variable table: + 0001 STRING (81) 00: SPoff: 0000 Len: 5 Dim: 10 A$ + 0002 SCALAR (00) 01: 11 I + + Main code starts here: + 10 DIM A$(10) + 20 A$="HELLO" + 30 FOR I=1 TO 10 + 40 ? A$;" WORLD!" + 50 NEXT I + + Immediate code starts here: + 32768 SAVE "H:HELLO.BAS" + + Done! + +OPTIONS +======= + +Input Options +------------- + +**-tbs** + Treat input as a Turbo BASIC program. + +**-bxl** + Treat input as a BASIC XL program. + +**-bxe** + Treat input as a BASIC XE program, which may or may not be EXTENDed + with code in the extra XE banks. + +Output Options +-------------- + +**-atari** + Output only the program listing, with lines terminated by Atari + EOL characters (**$9B**). + +**-short** + Output only the program listing, with lines terminated by the + system default newline character(s), e.g. **\n** on UNIX-like OSes, + **\r\n** on MS-DOS or Windows. This is the default for **listbas**. + +**-verbose** + Program listing will be interspersed with per-line and per-statement + low-level information. This option is probably most useful for debugging + **chkbas** itself. + +EXIT STATUS +=========== + +Zero for success, non-zero for failure. + +.. include:: manftr.rst diff --git a/jindroush/man/chkexe.1 b/jindroush/man/chkexe.1 new file mode 100644 index 0000000..c266a03 --- /dev/null +++ b/jindroush/man/chkexe.1 @@ -0,0 +1,86 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "CHKEXE" 1 "2024-05-16" "2.62" "Jindroush's Atari 8-bit tools" +.SH NAME +chkexe \- check and/or disassemble Atari 8-bit executables +.SH SYNOPSIS +.sp +chkexe [\fB\-gaps\fP \fIgap\-size\fP] [\fB\-silent\fP] [\fB\-split\fP] [\fB\-d\fP] \fBxex\-file\fP [\fBoutput\-file\fP] +.SH DESCRIPTION +.sp +\fBchkexe\fP reads an Atari 8\-bit executable (aka XEX file) and prints a +list of segments, each with their start and end address. Run and init +addresses are decoded. +.sp +If no \fBoutput\-file\fP is given, \fBchkexe\fP simply prints the results of +its analysis. With an \fBoutput\-file\fP, a possibly modified copy of the +XEX file is created: Adjacent blocks (e.g. a block ending at $1FFF, +followed by a block beginning at $2000) will be combined. The \fB\-gaps\fP +option can be used to control the threshold for combining blocks. +.SH OPTIONS +.INDENT 0.0 +.TP +.B \fB\-gaps\fP \fIgap\-size\fP +Blocks less than \fIgap\-size\fP bytes apart will be combined. Default: \fI0\fP\&. +.TP +.B \fB\-silent\fP +Don\(aqt print informational messages. +.TP +.B \fB\-split\fP +Split multi\-segment executables into one file per segment. The output +files will be called \fIblkNNNN.blk\fP, where \fINNNN\fP is the block number in +hexadecimal. These files are standard Atari executables, with \fI$FFFF\fP +headers. +.TP +.B \fB\-d\fP +Disassemble each block. The disassembler is very simple: single pass, +no attempt to recognize data blocks. +.UNINDENT +.SH EXIT STATUS +.sp +Zero for success, non\-zero for failure. +.SH COPYRIGHT +.sp +This utility is released under the GNU General Public License. +.SH AUTHORS +.sp +This utility was written by Jindrich Kubec, AKA Jindroush. +.sp +This page was written by B. Watson <\fI\%urchlay@slackware.uk\fP>. +.SH SEE ALSO +.sp +\fBacvt\fP(1), +\fBaext\fP(1), +\fBbas2boot\fP(1), +\fBchkbas\fP(1), +\fBchkexe\fP(1), +\fBchkrom\fP(1). +.\" Generated by docutils manpage writer. +. diff --git a/jindroush/man/chkexe.rst b/jindroush/man/chkexe.rst new file mode 100644 index 0000000..91c65ab --- /dev/null +++ b/jindroush/man/chkexe.rst @@ -0,0 +1,55 @@ +.. |version| replace:: 2.62 + +====== +chkexe +====== + +------------------------------------------------ +check and/or disassemble Atari 8-bit executables +------------------------------------------------ + +.. include:: manhdr.rst + +SYNOPSIS +======== + +chkexe [**-gaps** *gap-size*] [**-silent**] [**-split**] [**-d**] **xex-file** [**output-file**] + +DESCRIPTION +=========== + +**chkexe** reads an Atari 8-bit executable (aka XEX file) and prints a +list of segments, each with their start and end address. Run and init +addresses are decoded. + +If no **output-file** is given, **chkexe** simply prints the results of +its analysis. With an **output-file**, a possibly modified copy of the +XEX file is created: Adjacent blocks (e.g. a block ending at $1FFF, +followed by a block beginning at $2000) will be combined. The **-gaps** +option can be used to control the threshold for combining blocks. + +OPTIONS +======= + +**-gaps** *gap-size* + Blocks less than *gap-size* bytes apart will be combined. Default: *0*. + +**-silent** + Don't print informational messages. + +**-split** + Split multi-segment executables into one file per segment. The output + files will be called *blkNNNN.blk*, where *NNNN* is the block number in + hexadecimal. These files are standard Atari executables, with *$FFFF* + headers. + +**-d** + Disassemble each block. The disassembler is very simple: single pass, + no attempt to recognize data blocks. + +EXIT STATUS +=========== + +Zero for success, non-zero for failure. + +.. include:: manftr.rst diff --git a/jindroush/man/chkrom.1 b/jindroush/man/chkrom.1 new file mode 100644 index 0000000..772f7b8 --- /dev/null +++ b/jindroush/man/chkrom.1 @@ -0,0 +1,90 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "CHKROM" 1 "2024-05-16" "1.00" "Jindroush's Atari 8-bit tools" +.SH NAME +chkrom \- check or disassemble 8K or 16K Atari 8-bit cartridge images +.SH SYNOPSIS +.sp +chkrom [\fB\-disassemble\fP] \fBrom\-image\fP +.SH DESCRIPTION +.sp +\fBchkrom\fP reads a \fIraw\fP Atari 8\-bit ROM image (not a \fB\&.car\fP file) +and prints the run address, init address, and the decoded flags in the +cartridge options byte. +.sp +Sample run: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ chkrom basic.rom +chkrom v1.00 (c) 1998\-1999 Jindrich Kubec +ROM file: basic.rom +Init Addr :BFF0 +Run Addr :A000 +Flags :0500 ( INIT&RUN BOOT ) +Ok! +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +\fBchkrom\fP only supports images exactly 8KB (8192 bytes) or 16KB +(16384 bytes). Bankswitched cartridge aren\(aqt supported. If you get +"Unknown ROM size", make sure you\(aqre using a raw image. If it\(aqs a +\fB\&.car\fP image, use \fBcart2rom\fP(1) to make a raw image of it. +.SH OPTIONS +.INDENT 0.0 +.TP +.B \fB\-disassemble\fP +Prints a disassembly of the entire cartridge. +.UNINDENT +.SH EXIT STATUS +.sp +Zero for success, non\-zero for failure. +.SH COPYRIGHT +.sp +This utility is released under the GNU General Public License. +.SH AUTHORS +.sp +This utility was written by Jindrich Kubec, AKA Jindroush. +.sp +This page was written by B. Watson <\fI\%urchlay@slackware.uk\fP>. +.SH SEE ALSO +.sp +\fBacvt\fP(1), +\fBaext\fP(1), +\fBbas2boot\fP(1), +\fBchkbas\fP(1), +\fBchkexe\fP(1), +\fBchkrom\fP(1). +.\" Generated by docutils manpage writer. +. diff --git a/jindroush/man/chkrom.rst b/jindroush/man/chkrom.rst new file mode 100644 index 0000000..5db1b15 --- /dev/null +++ b/jindroush/man/chkrom.rst @@ -0,0 +1,51 @@ +.. |version| replace:: 1.00 + +====== +chkrom +====== + +----------------------------------------------------------- +check or disassemble 8K or 16K Atari 8-bit cartridge images +----------------------------------------------------------- + +.. include:: manhdr.rst + +SYNOPSIS +======== + +chkrom [**-disassemble**] **rom-image** + +DESCRIPTION +=========== + +**chkrom** reads a *raw* Atari 8-bit ROM image (not a **.car** file) +and prints the run address, init address, and the decoded flags in the +cartridge options byte. + +Sample run:: + + $ chkrom basic.rom + chkrom v1.00 (c) 1998-1999 Jindrich Kubec + ROM file: basic.rom + Init Addr :BFF0 + Run Addr :A000 + Flags :0500 ( INIT&RUN BOOT ) + Ok! + +**chkrom** only supports images exactly 8KB (8192 bytes) or 16KB +(16384 bytes). Bankswitched cartridge aren't supported. If you get +"Unknown ROM size", make sure you're using a raw image. If it's a +**.car** image, use **cart2rom**\(1) to make a raw image of it. + +OPTIONS +======= + +**-disassemble** + Prints a disassembly of the entire cartridge. + +EXIT STATUS +=========== + +Zero for success, non-zero for failure. + +.. include:: manftr.rst diff --git a/jindroush/man/manftr.rst b/jindroush/man/manftr.rst new file mode 100644 index 0000000..192a1b4 --- /dev/null +++ b/jindroush/man/manftr.rst @@ -0,0 +1,21 @@ +COPYRIGHT +========= + +This utility is released under the GNU General Public License. + +AUTHORS +======= + +This utility was written by Jindrich Kubec, AKA Jindroush. + +This page was written by B. Watson . + +SEE ALSO +======== + +**acvt**\(1), +**aext**\(1), +**bas2boot**\(1), +**chkbas**\(1), +**chkexe**\(1), +**chkrom**\(1). diff --git a/jindroush/man/manhdr.rst b/jindroush/man/manhdr.rst new file mode 100644 index 0000000..b3db233 --- /dev/null +++ b/jindroush/man/manhdr.rst @@ -0,0 +1,7 @@ +.. |date| date:: + +:Manual section: 1 +:Manual group: Jindroush's Atari 8-bit tools +:Date: |date| +:Version: |version| + diff --git a/jindroush/switches.pl b/jindroush/switches.pl new file mode 100644 index 0000000..71f78be --- /dev/null +++ b/jindroush/switches.pl @@ -0,0 +1,322 @@ +$infile = "switches.def"; +$outfile = "switches.cpp"; + +if ( @ARGV ) +{ + $infile = shift @ARGV; +} + +if ( @ARGV ) +{ + $outfile = shift @ARGV; +} + +############################################################################ +## Script for generating switches.cpp +## +############################################################################ + +open INFILE, $infile or die; +@inf = ; +close INFILE; + +unshift @inf, "="; +unshift @inf, "=bRet = SWFN_HELP( USAGE );"; +unshift @inf, "this help"; +unshift @inf, "help, ?"; + +push @out, < $longest ); +} + +$longest += 2 + 9; +foreach $line ( @help ) +{ + my ( $switch, $desc, $par ) = split( /\|/, $line, 3 ); + + my $len = length( $switch ) + length( $par ); + + my $l = "printf( \"-$switch"; + + if ( $par ) + { + $l .= " $par"; + } + + $l .= ' ' x ( $longest - length( $l ) ); + + $l .= " -$desc\\n\" );\n"; + + push @helpf, $l; + +} + +unshift @out, @helpf; + +unshift @out, <$outfile"; + +print OUTFILE "//THIS IS A GENERATED FILE. DO NOT EDIT!!!\n"; +print OUTFILE "//EDIT $infile INSTEAD!\n\n"; + +$indent = 0; + +$bigline = join( '', @out ); +@out = split( /\n/, $bigline ); + +foreach $line ( @out ) +{ + $indent-- if ( $line =~ /}/ ); + + print OUTFILE "\t" x $indent, $line, "\n"; + + $indent++ if ( $line =~ /{/ ); + +} + +close OUTFILE; + +sub switch() +{ + my $switch_desc = ""; + + my $switches_names = shift @inf; + my $switches_desc = shift @inf; + + chomp $switches_desc; + + my @switches = split( /,/, $switches_names ); + + foreach $switch ( @switches ) + { + $switch =~ s/\s+$//; + $switch =~ s/^\s+//; + + if ( defined ( $SWITCHES{ $switch } ) ) + { + die "Duplicate switch $switch"; + } + + $SWITCHES{ $switch } = 1; + + } + + $switches_count = @switches; + + $switch_desc = $switches[ 0 ] . "|" . $switches_desc . "|"; + + push @out, "if ("; + + my @asc; + + foreach $switch (@switches ) + { + push @asc, "!strcmp( m_szSwitch, \"$switch\" )"; + } + + push @out, join( " || ", @asc ); + + push @out, ")"; + + push @out, "\n{\n"; + + my @switch_pars = (); + + for(;;) + { + my $par_desc = shift @inf; + + my ( $par, $code ) = split( /=/, $par_desc, 2 ); + + $par =~ s/\s+$//; + $par =~ s/^\s+//; + + $code =~ s/\s+$//; + $code =~ s/^\s+//; + + last if ( !$par && !$code ); + + if ( $code =~ /(SWFN_\w+)/ ) + { + $CODE_INCLUDE{ $1 } = 1; + } + + if ( $par ) + { + push @switch_pars, $par; + } + + push @out, $code . "\n"; + } + + push @out, "continue;\n"; + + $switch_desc .= join( ' ', @switch_pars ); + + push @help, $switch_desc; + + push @out, "}\n"; + +} -- cgit v1.2.3