summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/tools/imgtool/modules/hp48.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mess/tools/imgtool/modules/hp48.c')
-rw-r--r--src/mess/tools/imgtool/modules/hp48.c739
1 files changed, 0 insertions, 739 deletions
diff --git a/src/mess/tools/imgtool/modules/hp48.c b/src/mess/tools/imgtool/modules/hp48.c
deleted file mode 100644
index e54908c9c1e..00000000000
--- a/src/mess/tools/imgtool/modules/hp48.c
+++ /dev/null
@@ -1,739 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Antoine Mine
-/****************************************************************************
-
- hp48.c
-
- Memory cards for HP48 SX/GX
-
- Antoine Mine' 2014
-
-*****************************************************************************
-*/
-
-/*
- HP memory cards can contain two kinds of objects:
- - attached libraries
- - backup objects (encapsulating any kind of object)
-
- Attached libraries appear with a LIB attribute in imgtool's listing, and in
- the global "LIBRARY" menu on the HP48.
- Backup objects appear with a BAK attribute in imgtool's listing, and
- in the relevant "PORTS" menu on the HP48.
-
- Currently, we only support storing host files into backup objects and
- retreiving backup objects into files.
- For attached library objects in the memory card, we only show their name, but
- cannot retrieve their contents.
-
- To install a library contained in a host file, copy it with imgtool to
- the card; it creates a backup object visible in the "PORTS" menu;
- then evalue the object, store it into some port (e.g, 0 STO),
- turn off the HP48 and back on; the library should now be attached and
- visible in the "LIBRARY" menu.
- (The process is similar to installing a library from a file you get
- from the serial interface.)
-*/
-
-
-/*
- HP memory cards have size from 32 KB to 4096 KB.
- However, cards with size greater than 128 KB are seen as multiple ports of
- size 128 KB on the HP48 GX. In imgtool, we see them as distinct 128 KB
- partitions.
- Unfortunately, at the moment, partitions do not seem to be supported in the
- command-line tool...
- */
-
-
-/*
- Here is the format of backup objects (addresses are in 4-bit nibbles):
-
- offset field size value
- 0 prolog 5 02B62 prolog for overall backup object
- 5 size 5 len total size in nibble without prolog
- 10 name length 2 nbcar object name, in characters
- 12 name 2*nbcar -
- 12+2*nbcar name length 2 nbcar same value as name length at 10
- 14+2*nbcar object - -
- len-5 prolog 5 02911 prolog for inlined system integer
- len - 1 0
- len+1 CRC 4 - CRC from 5 to len
-
- total length: len+4
-
- i.e., the backup object is a container containing the object name
- and two objects: the backuped object itself and a system integer
- that contains the CRC.
-
- HP48 host files start with a "HPHP48-X" header (where X can be any
- single letter, which denotes a ROM revision and, implicitly, whether
- the program is for the S/SX or the G/GX family).
- When storing a file to the memory card, we strip the header and
- embed the object into a backup object with the correct CRC.
- When copying from the memory card to a host file, we extract the object
- from the backup container, stripping its CRC, and add the HPHP48-X header.
-
- */
-
-
-
-
-
-/*****************************************************************************
- Includes
-*****************************************************************************/
-
-#include "imgtool.h"
-
-
-
-/*****************************************************************************
- Data structures
-*****************************************************************************/
-
-
-struct hp48_card
-{
- imgtool_stream *stream;
- int modified;
-
- /* size, in bytes of card data: from 32 KB to 4 MB */
- int size;
-
- /* we store each nibble (4-bit) into its own byte, for simpler addressing;
- hence, data has 2*size
- */
- UINT8* data;
-
-};
-
-struct hp48_partition
-{
- /* pointer to the beginning of the partition inside the hp48_card */
- UINT8* data;
-
- /* size, in bytes (128 KB or less) */
- int size;
-
-};
-
-struct hp48_directory
-{
- int pos;
-};
-
-
-#define PROLOG_BACKUP 0x02B62
-#define PROLOG_LIBRARY 0x02B40
-#define PROLOG_SYSINT 0x02911
-
-/* memory cards are composed solely of libraries and backup objects */
-#define IS_OBJECT(prolog) ((prolog) == PROLOG_LIBRARY || (prolog) == PROLOG_BACKUP)
-
-/* host files begin with this prefix (up to the last letter) */
-static const char* hp48_prefix = "HPHP48-R";
-
-
-
-static OPTION_GUIDE_START( hp48_create_optionguide )
- OPTION_INT('S', "size", "Size in KB" )
-OPTION_GUIDE_END
-
-/* size in KB, 128 KB being the default */
-static const char hp48_create_optionspec[] = "S32/64/[128]/256/512/1024/2048/4096";
-
-
-
-/*****************************************************************************
- Utility functions
-*****************************************************************************/
-
-
-/* byes to nibbles */
-static void unpack(UINT8* dst, UINT8* src, int nsize)
-{
- int i;
-
- if ( nsize & 1 )
- {
- dst[nsize-1] = src[nsize/2] & 0xf;
- }
-
- for ( i = nsize/2-1; i >= 0; i-- )
- {
- dst[2*i+1] = src[i] >> 4;
- dst[2*i ] = src[i] & 0xf;
- }
-}
-
-/* nibbles to bytes */
-static void pack(UINT8* dst, UINT8* src, int nsize)
-{
- int i;
-
- for ( i = 0 ; i < nsize/2; i++ )
- {
- dst[i] = (src[2*i] & 0xf) | (src[2*i+1] << 4);
- }
-
- if ( nsize & 1 )
- {
- dst[nsize/2] = src[nsize-1] & 0xf;
- }
- }
-
-
-static int read20(UINT8* data)
-{
- return data[0] | (data[1] << 4) | (data[2] << 8) | (data[3] << 12) | (data[4] << 16);
-}
-
-static int read8(UINT8* data)
-{
- return data[0] | (data[1] << 4);
-}
-
-static void readstring(char* dst, UINT8* data, int nb)
-{
- int i;
- for ( i = 0; i < nb; i++ )
- {
- dst[i] = read8( data + 2*i );
- }
- dst[nb] = 0;
-}
-
-static void write20(UINT8* data, int v)
-{
- data[0] = v & 0xf;
- data[1] = (v >> 4) & 0xf;
- data[2] = (v >> 8) & 0xf;
- data[3] = (v >> 12) & 0xf;
- data[4] = (v >> 16) & 0xf;
-}
-
-static void write8(UINT8* data, int v)
-{
- data[0] = v & 0xf;
- data[1] = (v >> 4) & 0xf;
-}
-
-static void writestring(UINT8* data, const char* str, int nb)
-{
- int i;
- for ( i = 0; i < nb; i++ )
- {
- write8( data + 2*i, str[i] );
- }
-}
-
-
-/* go to the end, return its offset */
-static int find_end(hp48_partition* p)
-{
- int pos = 0;
- while (1)
- {
- if ( pos + 10 > 2*p->size) break;
-
- int prolog = read20( p->data + pos );
- if ( !IS_OBJECT( prolog )) break;
-
- pos += read20( p->data + pos + 5 ) + 5;
- }
-
- if ( pos > 2*p->size ) pos = 2*p->size;
- return pos;
-}
-
-
-/* find the backup object with the given name, returns its offset or -1 (not found) */
-static int find_file(hp48_partition* p, const char* filename, int *ptotalsize, int* pstart, int* pcontentsize)
-{
- UINT8* data = p->data;
- int pos = 0;
-
- /* find file */
- while (1)
- {
- if ( pos + 10 > 2*p->size) return -1;
-
- /* get prolog */
- int prolog = read20( data+pos );
- if ( !IS_OBJECT(prolog)) return -1;
-
- /* get size */
- int totalsize = read20( data+pos+5 );
- if ( totalsize < 14) return -1;
- if ( pos + 5 + totalsize > 2*p->size ) return -1;
-
- if ( prolog == PROLOG_BACKUP )
- {
- /* get name */
- int namelen = read8( data + pos + 10 );
- char name[257];
- if ( 9 + 2*namelen > totalsize ) return -1;
- readstring( name, data + pos + 12, namelen );
-
- /* check name */
- if ( !strcmp( name, filename ) )
- {
- /* found! */
- if ( ptotalsize ) *ptotalsize = totalsize;
- if ( pstart ) *pstart = pos + 14 + 2*namelen;
- if ( pcontentsize ) *pcontentsize = totalsize - (9 + 2*namelen);
- return pos;
- }
- else
- {
- /* skip */
- pos += totalsize + 5;
- }
- }
- else
- {
- /* skip */
- pos += totalsize + 5;
- }
-
- }
-
- // never executed
- //return -1;
-}
-
-
-/* CRC computing.
- This is the same CRC that is computed by the HP48 hardware.
- */
-static UINT16 crc(UINT8* data, int len)
-{
- UINT16 crc = 0;
- int i;
-
- for ( i = 0; i < len; i++ )
- {
- crc = (crc >> 4) ^ (((crc ^ data[i]) & 0xf) * 0x1081);
- }
-
- return crc;
-}
-
-
-
-/*****************************************************************************
- Imgtool functions
-*****************************************************************************/
-
-
-static imgtoolerr_t hp48_open(imgtool_image *img, imgtool_stream *stream)
-{
- hp48_card* c = (hp48_card*) imgtool_image_extra_bytes( img );
- int size = stream_size( stream );
-
- /* check that size is a power of 2 between 32 KB and 4 MG */
- if ( (size < 32 * 1024) ||
- (size > 4 * 1024 * 1024) ||
- (size & (size-1)) )
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- /* store info */
- c->stream = stream;
- c->modified = 0;
- c->size = size;
- c->data = (UINT8*) malloc( 2 * size );
- if ( !c->data )
- {
- return IMGTOOLERR_READERROR;
- }
-
- /* fully load image */
- stream_seek( stream, 0, SEEK_SET );
- if ( stream_read( stream, c->data, size ) < size )
- {
- return IMGTOOLERR_READERROR;
- }
- unpack( c->data, c->data, 2 * size );
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t hp48_create(imgtool_image* img,
- imgtool_stream *stream,
- option_resolution *opts)
-{
- hp48_card* c = (hp48_card*) imgtool_image_extra_bytes( img );
- int size;
-
- size = option_resolution_lookup_int(opts, 'S');
-
- c->stream = stream;
- c->modified = 1;
- c->size = size * 1024;
- c->data = (UINT8*) malloc( 2 * c->size );
- if ( !c->data )
- {
- return IMGTOOLERR_READERROR;
- }
-
- /* zeroing the image seems fine */
- memset( c->data, 0, 2 * c->size );
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static void hp48_close(imgtool_image *img)
-{
- hp48_card* c = (hp48_card*) imgtool_image_extra_bytes( img );
-
- if ( c->modified )
- {
- /* save image */
- pack( c->data, c->data, 2 * c->size );
- stream_seek( c->stream, 0, SEEK_SET );
- stream_write( c->stream, c->data, c->size );
- }
-
- /* clean up */
- free( c->data );
- stream_close( c->stream );
-}
-
-
-
-/* each 128 KB chunk is a distinct partition */
-#define MAX_PORT_SIZE (128*1024)
-
-void hp48_partition_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info);
-
-static imgtoolerr_t hp48_list_partitions(imgtool_image *img,
- imgtool_partition_info *partitions,
- size_t len)
-{
- hp48_card* c = (hp48_card*) imgtool_image_extra_bytes( img );
-
- int i;
- for ( i = 0; i < len && i * MAX_PORT_SIZE < c->size ; i++ )
- {
- /* offset and size in bytes */
- partitions[i].base_block = i * MAX_PORT_SIZE;
- partitions[i].block_count = c->size - partitions[i].base_block;
- if ( partitions[i].block_count > MAX_PORT_SIZE )
- {
- partitions[i].block_count = MAX_PORT_SIZE;
- }
-
- partitions[i].get_info = hp48_partition_get_info;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t hp48_open_partition(imgtool_partition *part,
- UINT64 first_block, UINT64 block_count)
-{
- imgtool_image* img = imgtool_partition_image( part );
- hp48_card* c = (hp48_card*) imgtool_image_extra_bytes( img );
- hp48_partition* p = (hp48_partition*) imgtool_partition_extra_bytes( part );
-
- if ( first_block + block_count > c->size )
- return IMGTOOLERR_INVALIDPARTITION;
-
- /* store partition position */
- p->data = c->data + first_block;
- p->size = block_count;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t hp48_beginenum(imgtool_directory *enumeration,
- const char *path)
-{
- hp48_directory* d = (hp48_directory*) imgtool_directory_extrabytes( enumeration );
-
- d->pos = 0;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t hp48_nextenum(imgtool_directory *enumeration,
- imgtool_dirent *ent)
-{
- imgtool_partition *part = imgtool_directory_partition( enumeration );
- //imgtool_image* img = imgtool_partition_image( part );
- //hp48_card* c = (hp48_card*) imgtool_image_extra_bytes( img );
- hp48_partition* p = (hp48_partition*) imgtool_partition_extra_bytes( part );
- hp48_directory* d = (hp48_directory*) imgtool_directory_extrabytes( enumeration );
-
- UINT8* data = p->data;
- int pos = d->pos;
-
- if ( pos < 0 || pos+12 > 2*p->size )
- {
- ent->eof = 1;
- return IMGTOOLERR_SUCCESS;
- }
-
- int prolog = read20( data+pos );
-
- if ( IS_OBJECT(prolog) )
- {
- pos += 5;
- int totalsize = read20( data+pos );
- pos += 5;
-
- int namelen = read8( data+pos );
- pos += 2;
- if ( (pos + 2*namelen > 2*p->size) ||
- (namelen >= sizeof(ent->filename)) )
- {
- ent->eof = 1;
- return IMGTOOLERR_CORRUPTFILE;
- }
- readstring( ent->filename, data+pos, namelen );
-
- /* compute size in bytes, removing name, length & CRC fields */
- ent->filesize = ((totalsize - 19 - 2*namelen) + 1) / 2;
-
- switch (prolog)
- {
- case PROLOG_LIBRARY: strncpy( ent->attr, "LIB", sizeof(ent->attr) ); break;
- case PROLOG_BACKUP: strncpy( ent->attr, "BAK", sizeof(ent->attr) ); break;
- default: strncpy( ent->attr, "?", sizeof(ent->attr) );
- }
-
- d->pos = d->pos + totalsize + 5;
- }
- else
- {
- /* 0 or unknown object => end */
- ent->eof = 1;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t hp48_freespace(imgtool_partition *part, UINT64 *size)
-{
- //imgtool_image* img = imgtool_partition_image( part );
- //hp48_card* c = (hp48_card*) imgtool_image_extra_bytes( img );
- hp48_partition* p = (hp48_partition*) imgtool_partition_extra_bytes( part );
-
- *size = p->size - (find_end(p)+1)/2;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t hp48_readfile(imgtool_partition *part,
- const char *filename,
- const char *fork,
- imgtool_stream *destf)
-{
- //imgtool_image* img = imgtool_partition_image( part );
- //hp48_card* c = (hp48_card*) imgtool_image_extra_bytes( img );
- hp48_partition* p = (hp48_partition*) imgtool_partition_extra_bytes( part );
-
- /* find entry */
- int totalsize, start, size;
- int pos = find_file(p, filename, &totalsize, &start, &size);
- if ( pos == -1 )
- {
- return IMGTOOLERR_FILENOTFOUND;
- }
-
- /* CRC check */
- UINT16 objcrc = read20( p->data + pos + totalsize ) >> 4;
- UINT16 mycrc = crc( p->data + pos + 5, totalsize - 4);
- if ( objcrc != mycrc )
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- size -= 10;
-
- /* save header */
- stream_write( destf, hp48_prefix, 8);
-
- /* save contents to host file */
- int bytesize = (size + 1) / 2;
- UINT8* buf = (UINT8*) malloc( bytesize );
- if (!buf)
- {
- return IMGTOOLERR_FILENOTFOUND;
- }
- pack( buf, p->data + start, size );
- stream_write( destf, buf, bytesize );
- free( buf );
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t hp48_deletefile(imgtool_partition *part,
- const char *filename)
-{
- imgtool_image* img = imgtool_partition_image( part );
- hp48_card* c = (hp48_card*) imgtool_image_extra_bytes( img );
- hp48_partition* p = (hp48_partition*) imgtool_partition_extra_bytes( part );
-
- /* find entry */
- int totalsize;
- int pos = find_file(p, filename, &totalsize, NULL, NULL );
- if ( pos == -1 )
- {
- return IMGTOOLERR_FILENOTFOUND;
- }
-
- /* move */
- totalsize += 5;
- memmove( p->data+pos, p->data+pos+totalsize, 2*p->size-(pos+totalsize) );
- memset( p->data + 2*p->size-totalsize, 0, totalsize);
- c->modified = 1;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t hp48_writefile(imgtool_partition *part,
- const char *filename,
- const char *fork,
- imgtool_stream *sourcef,
- option_resolution *opts)
-{
- imgtool_image* img = imgtool_partition_image( part );
- hp48_card* c = (hp48_card*) imgtool_image_extra_bytes( img );
- hp48_partition* p = (hp48_partition*) imgtool_partition_extra_bytes( part );
-
- /* check header */
- char head[8];
- stream_read( sourcef, head, 8 );
- if ( memcmp( head, hp48_prefix, 7) )
- {
- return IMGTOOLERR_READERROR;
- }
-
- /* ensure that the file does not exist */
- /* TODO: resize the existing file instead, to keep it in place? */
- hp48_deletefile( part, filename );
-
- /* goto end */
- //UINT8* data = p->data;
- int pos = find_end(p);
-
- int len = strlen( filename );
- if ( len > 255 ) len = 255;
-
- /* check size */
- int filesize = stream_size( sourcef ) - 8;
- if ( pos + 2*filesize + 24 + 2*len > 2 * p->size )
- {
- return IMGTOOLERR_NOSPACE;
- }
-
- /* load file */
- UINT8* buf = (UINT8*) malloc( filesize );
- if ( !buf ) return IMGTOOLERR_NOSPACE;
- stream_read( sourcef, buf, filesize );
-
- /* store backup object */
- int org = pos;
- int totalsize = 2*filesize + 19 + 2*len;
- write20( p->data+pos, PROLOG_BACKUP );
- pos +=5;
- write20( p->data+pos, totalsize );
- pos +=5;
- write8( p->data+pos, len );
- pos += 2;
- writestring( p->data+pos, filename, len );
- pos += 2*len;
- write8( p->data+pos, len );
- pos += 2;
- unpack( p->data+pos, buf, 2*filesize );
- pos += 2*filesize;
-
- /* store crc */
- write20( p->data+pos, PROLOG_SYSINT );
- pos += 5;
- p->data[pos] = 0;
- write20( p->data+pos, crc(p->data+org+5, totalsize-4) << 4 );
-
- free(buf);
-
- c->modified = 1;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-
-/*****************************************************************************
- Imgtool module declaration
-*****************************************************************************/
-
-
-
-void hp48_partition_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "hp48"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "HP48 SX/GX memory card"); break;
- case IMGTOOLINFO_STR_FILE: strcpy(info->s = imgtool_temp_str(), __FILE__); break;
- case IMGTOOLINFO_STR_FILE_EXTENSIONS: strcpy(info->s = imgtool_temp_str(), "crd"); break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_OPEN_PARTITION: info->open_partition = hp48_open_partition; break;
- case IMGTOOLINFO_PTR_CLOSE: info->close = hp48_close; break;
- case IMGTOOLINFO_PTR_BEGIN_ENUM: info->begin_enum = hp48_beginenum; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = hp48_nextenum; break;
- case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = hp48_freespace; break;
- case IMGTOOLINFO_PTR_READ_FILE: info->read_file = hp48_readfile; break;
- case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = hp48_writefile; break;
- case IMGTOOLINFO_PTR_DELETE_FILE: info->delete_file = hp48_deletefile; break;
-
- case IMGTOOLINFO_INT_PARTITION_EXTRA_BYTES: info->i = sizeof(hp48_partition); break;
- case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(hp48_directory); break;
-
- }
-}
-
-void hp48_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "hp48"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "HP48 SX/GX memory card"); break;
- case IMGTOOLINFO_STR_FILE: strcpy(info->s = imgtool_temp_str(), __FILE__); break;
- case IMGTOOLINFO_STR_FILE_EXTENSIONS: strcpy(info->s = imgtool_temp_str(), "crd"); break;
- case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC: strcpy(info->s = imgtool_temp_str(), hp48_create_optionspec); break;
-
- case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = hp48_create_optionguide; break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_OPEN: info->open = hp48_open; break;
- case IMGTOOLINFO_PTR_CREATE: info->create = hp48_create; break;
- case IMGTOOLINFO_PTR_CLOSE: info->close = hp48_close; break;
- case IMGTOOLINFO_PTR_LIST_PARTITIONS: info->list_partitions = hp48_list_partitions; break;
-
- case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES: info->i = sizeof(hp48_card); break;
- }
-}