Unfinished Bitness

Finishing bits of technology, vintage and new.

  • About
  • Contact

Asus WRT Router Icons

Posted by Ripdubski on 2020.09.12
Posted in: General, Router. Tagged: ASUSWRT. 1 Comment

Asus routers come with a handful of icons available to tag your devices.  This visual cue in the list of online devices can speed identification.  While there are a lot of Apple devices present, it is missing a few.  In addition it is missing some for home automation, connected devices, and security.

I wanted to have all the devices have icons that look like they were part of Asus WRT.  To start I grabbed a screenshot of the available device icons:

 

From this image I was able to find the fill color and icon color.  The fill color is #798D94, or RGB (121,141,148):

 

The border and drawing color is #2F383B , or RGB (47,56,59):

I then used Pixelmator Pro to create a transparent background image sized at 640 x 640 pixels.

From there a drew a box with rounded corners (150 px radius), with a stroke of 22 px solid line on the inside using the border/draw color of the Asus images, and a fill color matching the fill color of the Asus images.

I saved this as a template, and exported it as a PNG.  Basically it’s a blank icon:

 

Then I found icons I could use, and altered the color to match the border/draw color of the Asus images.  If the images were much smaller than my 640 pixel blank, I shrunk the blank so it was just bigger than the icon.  Once the blank and icon matched sizing, I copied the icon into the blank.  Then I shrank the image to 128 x 128 pixels, and exported it to PNG.

Now I have Apple TV and Apple Watch icons, and a few others.  Here are the ones I created:

 

I created several others as well including a garage door, scale, security, doorbell, thermostat, bed, nas drive, and voip phone.

The links on the images above should take you to the full size image should you want to save them and use them.

 

Enjoy.

Share this:

  • Click to email a link to a friend (Opens in new window)
  • Click to share on Facebook (Opens in new window)
  • Click to share on LinkedIn (Opens in new window)
  • Click to share on Pinterest (Opens in new window)
  • Click to share on Pocket (Opens in new window)
  • Click to share on Reddit (Opens in new window)
  • Click to share on Twitter (Opens in new window)

Like this:

Like Loading...

DOS Batch Helper Redux, Part 3

Posted by Ripdubski on 2019.10.20
Posted in: MSDOS, Programming. Tagged: Batch, Menu. Leave a comment

The A-Batch code post.  As stated in the previous post, the code could definitely use some sanity checks on parameters. There is also room for some optimizations throughout, and removal of a couple of magic numbers. As it stands it works for what I need it to do.  The source is fairly well documented.  If you want further clarification on something, email or leave a comment.

Attached to this post is the Turbo C source code and executable.  The attachment is a zip file.  It was renamed to “.odt” to pass upload restrictions.  Rename it with a “.zip” extension and extract.  It has two files in it:

  • ABATCH.C
  • ABATCH.EXE

The 32 bit CRC checksum (cksum -o 3) of the file is (download link next to checksum):

3183384630 14242 ABatch-Zip.odt

 

Following is the source code listing.

/* ----------------------------------------------------------------------
// File.......: ABATCH.PRG
// Author.....: Ripdubski (inverseatascii@icloud.com)
// Date.......: 2019.10.10
// Description: 2019 re-creation of A-Batch written by myself in the
//              early 1990's whose source was lost.
//              A Batch script helper for displaying nice screens.
// Notes......:
// Revised....:
// ---------------------------------------------------------------------- */

/* ---------- Includes ---------- */
#include 
#include 
#include 
#include 
#include 
#include 


/* ---------- Definitions ---------- */
#define AB_VERSION "2.00"

/* Error codes */
#define AB_ERR_NONE       0
#define AB_ERR_BADSYNTAX  100
#define AB_ERR_BADCMD     101
#define AB_ERR_MISSING    200

/* Commands */
#define AB_CMD_BACK    "back"
#define AB_CMD_BOX     "box"
#define AB_CMD_CLS     "cls"
#define AB_CMD_GOXY    "goxy"
#define AB_CMD_HELP    "help"
#define AB_CMD_TEXT    "text"
#define AB_CMD_TITLE   "title"
#define AB_CMD_VERSION "version"
#define AB_CMD_WAIT    "wait"

/* Box border styles */
#define AB_STYLE_BACK   "back"
#define AB_STYLE_SINGLE "single"
#define AB_STYLE_DOUBLE "double"
#define AB_STYLE_BLOCK  "block"
#define AB_STYLE_FAT    "fat"
#define AB_STYLE_SD     "sd"
#define AB_STYLE_DS     "ds"
#define AB_STYLE_NONE   "none"

/* Color names */
#define AB_COLOR_BLACK    "black"
#define AB_COLOR_BLUE     "blue"
#define AB_COLOR_GREEN    "green"
#define AB_COLOR_CYAN     "cyan"
#define AB_COLOR_RED      "red"
#define AB_COLOR_MAGENTA  "magenta"
#define AB_COLOR_BROWN    "brown"
#define AB_COLOR_LGRAY    "lgray"
#define AB_COLOR_DGRAY    "dgray"
#define AB_COLOR_LBLUE    "lblue"
#define AB_COLOR_LGREEN   "lgreen"
#define AB_COLOR_LCYAN    "lcyan"
#define AB_COLOR_LRED     "lred"
#define AB_COLOR_LMAGENTA "lmagenta"
#define AB_COLOR_YELLOW   "yellow"
#define AB_COLOR_WHITE    "white"
#define AB_COLOR_BLINK    "blink"

/* Box character locations in the box character string */
#define AB_BOXCH_TL  0
#define AB_BOXCH_TR  2
#define AB_BOXCH_TM  1
#define AB_BOXCH_BL  6
#define AB_BOXCH_BR  4
#define AB_BOXCH_BM  5
#define AB_BOXCH_ML  3
#define AB_BOXCH_MR  7
#define AB_BOXCH_MM  8

/* Title ornament locations in the ornament character string */
#define AB_ORNCH_L 0
#define AB_ORNCH_R 1


/* ---------- Prototypes ---------- */
void idself(void);
int transcolor(char *);
void cmd_text(char *, int, int, char *, char *);
int main(int, char *[]);


/* ---------- Functions ---------- */

/* ----------------------------------------------------------------------
// Func.......: void idself(void)
// Description: Outputs program identifier
// Parameters.: n/a
// Returns....: n/a
// ---------------------------------------------------------------------- */
void idself(void)
{
    printf("A-Batch, version %s\nCopyright (c) 2019   Ripdubski   All Rights Reserved.\n", AB_VERSION);
}


/* ----------------------------------------------------------------------
// Func.......: int transcolor(char *cName)
// Description: Translates named color to color attribute value
// Parameters.: cName = color name
// Returns....: color attribute value (number)
// ---------------------------------------------------------------------- */
int transcolor(char *cName)
{
    int iColor = 0;

    /* Decide which color value to return */
    if (stricmp(cName, AB_COLOR_BLACK) == 0) iColor =    0;
    if (stricmp(cName, AB_COLOR_BLUE) == 0) iColor =     1;
    if (stricmp(cName, AB_COLOR_GREEN) == 0) iColor =    2;
    if (stricmp(cName, AB_COLOR_CYAN) == 0) iColor =     3;
    if (stricmp(cName, AB_COLOR_RED) == 0) iColor =      4;
    if (stricmp(cName, AB_COLOR_MAGENTA) == 0) iColor =  5;
    if (stricmp(cName, AB_COLOR_BROWN) == 0) iColor =    6;
    if (stricmp(cName, AB_COLOR_LGRAY) == 0) iColor =    7;
    if (stricmp(cName, AB_COLOR_DGRAY) == 0) iColor =    8;
    if (stricmp(cName, AB_COLOR_LBLUE) == 0) iColor =    9;
    if (stricmp(cName, AB_COLOR_LGREEN) == 0) iColor =   10;
    if (stricmp(cName, AB_COLOR_LCYAN) == 0) iColor =    11;
    if (stricmp(cName, AB_COLOR_LRED) == 0) iColor =     12;
    if (stricmp(cName, AB_COLOR_LMAGENTA) == 0) iColor = 13;
    if (stricmp(cName, AB_COLOR_YELLOW) == 0) iColor =   14;
    if (stricmp(cName, AB_COLOR_WHITE) == 0) iColor =    15;
    if (stricmp(cName, AB_COLOR_BLINK) == 0) iColor =    128;

    return(iColor);
}


/* ----------------------------------------------------------------------
// Func.......: void cmd_text(char *cStr, int iX, int iY, char *cFC, char *cBC)
// Description: Routine to output text and preserve text attributes
// Parameters.: cStr = string of text to display
//              iX = X coordinate to display at
//              iY = Y coordinate to display at
//              cFC = foreground color of text
//              cBC = background color of text
// Returns....: n/a
// ---------------------------------------------------------------------- */
void cmd_text(char *cStr, int iX, int iY, char *cFC, char *cBC)
{
    struct text_info sText;

    /* Save old mode */
    gettextinfo(&sText);

    /* Set text forground and background color */
    textcolor(transcolor(cFC));
    textbackground(transcolor(cBC));

    /* Output text at location */
    gotoxy(iX,iY);
    cputs(cStr);

    /* Restore text attributes */
    textattr(sText.attribute);
}


/* ----------------------------------------------------------------------
// Func.......: int main(int argc, char *argv[])
// Description: Main routine
// Parameters.: argc = number of command line arguments
//              argv = array of command line arguments
// Returns....: errorcode (can be tested/checked from BATCH script)
// ---------------------------------------------------------------------- */
int main(int argc, char *argv[])
{
    /* Default return value to badcmd, set as needed throughout */
    int iCnt, iLp, iRet = AB_ERR_BADCMD, iX = 0, iY = 0, iW = 0, iH = 0;
    /* Strings for box drawing */
    char cBoxBack[11] =   { 176,176,176,176,176,176,176,176,176,'\0' };
    char cBoxSingle[11] = { 218,196,191,179,217,196,192,179,32,'\0' };
    char cBoxDouble[11] = { 201,205,187,186,188,205,200,186,32,'\0' };
    char cBoxBlock[11] =  { 219,219,219,219,219,219,219,219,32,'\0' };
    char cBoxFat[11] =    { 220,220,220,222,223,223,223,221,32,'\0' };
    char cBoxSD[11] =     { 214,196,183,186,189,196,211,186,32,'\0' };
    char cBoxDS[11] =     { 213,205,184,179,190,205,212,179,32,'\0' };
    char cBoxNone[11] =   { 32,32,32,32,32,32,32,32,32,'\0' };
    char *cBox;  
    /* Strings for title ornaments */
    char cOrnSingle[4] = { 180,195,'\0' };
    char cOrnDouble[4] = { 181,198,'\0' };
    char cOrnBlock[4]  = { 221,222,'\0' };
    char cOrnFat[4]    = { 221,222,'\0' };
    char cOrnSD[4]     = { 180,195,'\0' };
    char cOrnDS[4]     = { 181,198,'\0' };
    char cOrnNone[4]   = { ' ',' ','\0' };
    char *cOrn;
    /* Temp buffers for building output */
    char cLine[81] = "", cMiddle[81] = "", cChL, cChM, cChR;

    /* Set actual argument count */
    iCnt = argc - 1;

    /* Check for proper syntax */
    if ((iCnt < 2) | (stricmp(argv[1], AB_CMD_HELP) == 0)) {
        idself();

	printf("Syntax: ascreen command parameters\n");
        printf("        commands: back style fc bc = draw background (style=back or 3 chars)\n");
        printf("                  box x y w h style fc bc = draw box in style at x y\n");
        printf("                  cls = clear screen and home cursor\n");
        printf("                  goxy x y = move cursor to x,y\n");
        printf("                  help = syntax\n");
        printf("                  text x y \"text\" fc bc = output \"text\" at x y\n");
        printf("                  title x y \"text\" fc bc style fc bc = box title\n");
        printf("                  wait n = wait n seconds\n");
        printf("                  version = version information\n");
        printf("        x y expressed in base 1\n");
        printf("        styles: single, double, block, fat, SD, DS, none, back (back only)\n");
        printf("        colors: black, blue, green, cyan, red, magenta, brown, lgray,\n");
        printf("                dgray, lblue, lgreen, lcyan, lred, lmagenta, yellow, white\n");

	exit(AB_ERR_BADSYNTAX);
    }

    /* Decide on command and take action */

    /* Output text in specific style at specific location */
    if (stricmp(argv[1], AB_CMD_TEXT) == 0) {
	if (iCnt < 6) {
	    iRet = AB_ERR_MISSING;
	} else {
	    /* text x y fc bc string */
            /* Grab x, y */
	    iX = atoi(argv[2]);
            iY = atoi(argv[3]);

            cmd_text(argv[6], iX, iY, argv[4], argv[5]);
            iRet = AB_ERR_NONE;
	}
    }
    /* Draw specific sized box in specific style at specific location */
    if (stricmp(argv[1], AB_CMD_BOX) == 0) {
	if (iCnt < 8) {
	    iRet = AB_ERR_MISSING;
	} else {
	    /* box x y w h style fc bc */
            /* Grab x, y, width, and height */
	    iX = atoi(argv[2]);
	    iY = atoi(argv[3]);
	    iW = atoi(argv[4]);
	    iH = atoi(argv[5]);

            /* Set build string based on selection type */
            if (stricmp(argv[6], AB_STYLE_BACK) == 0)   cBox = cBoxBack;
            if (stricmp(argv[6], AB_STYLE_SINGLE) == 0) cBox = cBoxSingle;
            if (stricmp(argv[6], AB_STYLE_DOUBLE) == 0) cBox = cBoxDouble;
            if (stricmp(argv[6], AB_STYLE_BLOCK) == 0)  cBox = cBoxBlock;
            if (stricmp(argv[6], AB_STYLE_FAT) == 0)    cBox = cBoxFat;
            if (stricmp(argv[6], AB_STYLE_SD) == 0)     cBox = cBoxSD;
            if (stricmp(argv[6], AB_STYLE_DS) == 0)     cBox = cBoxDS;
            if (stricmp(argv[6], AB_STYLE_NONE) == 0)   cBox = cBoxNone;

            /* Build box line by line and output */
            for (iLp = 1; iLp <= iH; iLp++) {
                /* Determine line characters based on line number */
                if (iLp == 1) {
                    cChL = cBox[AB_BOXCH_TL];
                    cChR = cBox[AB_BOXCH_TR];
                    cChM = cBox[AB_BOXCH_TM];
                } else {
                    if (iLp == iH) {
                        cChL = cBox[AB_BOXCH_BL];
                        cChR = cBox[AB_BOXCH_BR];
                        cChM = cBox[AB_BOXCH_BM];
                    } else {
                        cChL = cBox[AB_BOXCH_ML];
                        cChR = cBox[AB_BOXCH_MR];
                        cChM = cBox[AB_BOXCH_MM];
                    }
                }

                /* Create middle portion of line, then build entire line */
                memset(cMiddle, cChM, iW - 2);
                cMiddle[iW] = '\0';
                sprintf(cLine, "%c%s%c", cChL, cMiddle, cChR);

                /* Output the line */
                cmd_text(cLine, iX, iY + (iLp - 1), argv[7], argv[8]);
            }

            iRet = AB_ERR_NONE;
	}
    }
    /* Add title to box using blended delimiters */
    if (stricmp(argv[1], AB_CMD_TITLE) == 0) {
	if (iCnt < 9) {
	    iRet = AB_ERR_MISSING;
	} else {
	    /* title x y text fc bc style fc bc */
            /* Grab x, y, width, and height */
	    iX = atoi(argv[2]);
	    iY = atoi(argv[3]);

            /* Set build string based on selection type */
            if (stricmp(argv[7], AB_STYLE_SINGLE) == 0) cBox = cOrnSingle;
            if (stricmp(argv[7], AB_STYLE_DOUBLE) == 0) cBox = cOrnDouble;
            if (stricmp(argv[7], AB_STYLE_BLOCK) == 0)  cBox = cOrnBlock;
            if (stricmp(argv[7], AB_STYLE_FAT) == 0)    cBox = cOrnFat;
            if (stricmp(argv[7], AB_STYLE_SD) == 0)     cBox = cOrnSD;
            if (stricmp(argv[7], AB_STYLE_DS) == 0)     cBox = cOrnDS;
            if (stricmp(argv[7], AB_STYLE_NONE) == 0)   cBox = cOrnNone;

            /* Get ornaments */
            cChL = cBox[AB_ORNCH_L];
            cChR = cBox[AB_ORNCH_R];

            /* Create and output left and right ornaments */
            sprintf(cLine, "%c", cChL);
            cmd_text(cLine, iX, iY, argv[8], argv[9]);
            sprintf(cLine, "%c", cChR);
            cmd_text(cLine, iX + strlen(argv[4]) + 3, iY, argv[8], argv[9]);
            sprintf(cLine, " %s ", argv[4]);
            cmd_text(cLine, iX + 1, iY, argv[5], argv[6]);

            iRet = AB_ERR_NONE;
	}
    }
    /* Goto X Y (cursor) screen coordinates */
    if (stricmp(argv[1], AB_CMD_GOXY) == 0) {
	if (iCnt < 3) {
	    iRet = AB_ERR_MISSING;
	} else {
	    /* goxy x y */
	    iX = atoi(argv[2]);
	    iY = atoi(argv[3]);
	    gotoxy(iX, iY);

            iRet = AB_ERR_NONE;
	}
    }
    /* Wait number of seconds */
    if (stricmp(argv[1], AB_CMD_WAIT) == 0) {
	if (iCnt < 2) {
	    iRet = AB_ERR_MISSING;
	} else {
	    /* wait secs */
	    iX = atoi(argv[2]);
	    sleep(iX);

            iRet = AB_ERR_NONE;
        }
    }
    /* Draw background filling entire screen */
    if (stricmp(argv[1], AB_CMD_BACK) == 0) {
	if (iCnt < 4) {
	    iRet = AB_ERR_MISSING;
	} else {
	    /* back style fc bc */

            /* Set build string based on selection type - only back supported */
            if (stricmp(argv[2], AB_STYLE_BACK) == 0) {
                cBox = cBoxBack;
            } else {
                cBox = argv[2];   /* custom string (3 char minimum: LMR) */
            }

            /* Get background characters - only need first three */
            cChL = cBox[AB_BOXCH_TL];
            cChR = cBox[AB_BOXCH_TR];
            cChM = cBox[AB_BOXCH_TM];

            /* Create middle portion of line, then build entire line */
            memset(cMiddle, cChM, 78);
            cMiddle[79] = '\0';
            sprintf(cLine, "%c%s%c", cChL, cMiddle, cChR);

            /* Output line by line and output */
            for (iLp = 1; iLp <= 24; iLp++) {
                cmd_text(cLine, 1, iLp, argv[3], argv[4]);

                /* If line 24, write line, push down, return to 24 and write line -
                   prevent trailing cursor wrap. */
                if (iLp == 24) {
                    gotoxy(1, 24);
                    insline();
                    gotoxy(1, 24);
                    cmd_text(cLine, 1, iLp, argv[3], argv[4]);
                    gotoxy(1, 24);
                }
            }

            iRet = AB_ERR_NONE;
	}
    }
    /* Clear Le Screen :D - not really needed, implemented as first parser test */
    if (stricmp(argv[1], AB_CMD_CLS) == 0) {
	clrscr();

        iRet = AB_ERR_NONE;
    }
    /* Version information */
    if (stricmp(argv[1], AB_CMD_VERSION) == 0) {
	idself();

        iRet = AB_ERR_NONE;
   }

    /* Were done, exit with errorcode */
    return(iRet);
}

 

Share this:

  • Click to email a link to a friend (Opens in new window)
  • Click to share on Facebook (Opens in new window)
  • Click to share on LinkedIn (Opens in new window)
  • Click to share on Pinterest (Opens in new window)
  • Click to share on Pocket (Opens in new window)
  • Click to share on Reddit (Opens in new window)
  • Click to share on Twitter (Opens in new window)

Like this:

Like Loading...

DOS Batch Helper Redux, Part 2

Posted by Ripdubski on 2019.10.15
Posted in: MSDOS, Programming. Tagged: Batch, Menu. Leave a comment

In the last post I said I would dive into the code in the next post, but I want to present the batch code changes from the original batch menu, and the revised batch menu using A-Batch first.  The next post will be a code post.

Old DOS Batch Menu

As a reminder, here is the old DOS batch menu:

DOS Choice menu

 

And here is the DOS batch code that presents it and gets the choice.  I won’t go into the code branching because its irrelevant for menu purposes here:

@echo off
cls
echo.
echo Choose:
echo.
echo 1 - Clipper 5.3
echo 2 - FoxPro 2.5
echo 3 - FoxPro 2.6a
echo 4 - Turbo C
echo 5 - Borland C++
echo 6 - Turbo BASIC 1.1
echo 7 - Power BASIC 3.5
echo X - Exit to DOS

choice /c:1234567X /n

 

New DOS A-Batch Menu

Now, here is the new DOS batch menu using A-Batch:

A-Batch menu

 

And here is the DOS batch code the presents it and gets the choice:

@echo off
abatch cls
abatch back back lgray black
abatch box 1 1 80 3 single white green
abatch text 31 2 white green "B O O T M E N U"
abatch box 20 8 40 12 double white blue
abatch title 35 8 "Choose" yellow blue double white blue
abatch text 30 10 lgray blue "1 - Clipper 5.3"
abatch text 30 11 lgray blue "2 - FoxPro 2.5"
abatch text 30 12 lgray blue "3 - FoxPro 2.6a"
abatch text 30 13 lgray blue "4 - Turbo C"
abatch text 30 14 lgray blue "5 - Borland C++"
abatch text 30 15 lgray blue "6 - Turbo BASIC 1.1"
abatch text 30 16 lgray blue "7 - Power BASIC 3.5"
abatch text 30 17 lgray blue "X - Exit to DOS"
abatch goxy 30 18

choice /c:1234567X /n

 

The line count increase to display the nicer menu is only 3.  That last line with the command “goxy 30 18” isn’t required.  I added it just to move the cursor under the choice column.  The remainder of both scripts is the same, some ERRORLEVEL checking and branching to execute specific commands for each choice.

 

Next post will be A-Batch code.

Share this:

  • Click to email a link to a friend (Opens in new window)
  • Click to share on Facebook (Opens in new window)
  • Click to share on LinkedIn (Opens in new window)
  • Click to share on Pinterest (Opens in new window)
  • Click to share on Pocket (Opens in new window)
  • Click to share on Reddit (Opens in new window)
  • Click to share on Twitter (Opens in new window)

Like this:

Like Loading...

DOS Batch Helper Redux, Part 1

Posted by Ripdubski on 2019.10.14
Posted in: MSDOS, Programming. Tagged: Batch, Menu. Leave a comment

Back in the early 1990’s when I was programming professionally for a living, I was always tinkering around with little utility programs to help myself.  One area of interest was enhancing batch file screen formatting abilities.  I wanted to see menu screens with color and boxes, etc.  While there were programs you could buy to do this, I never wanted to buy one because none worked exactly like I wanted them to though some were very close.  And why buy something when I could write it myself.  So that’s just what I did, it was small, used no memory, and worked well.  In the years that passed, over time I lost all the source code for it, and everything else I ever wrote, most likely by deletion thinking I didn’t need it anymore.  Whats a hard copy?  😀 Fast forward many years, and I find myself wishing I still had it.

First, a little backstory that led to this project.

I first learned relational databases with Ashton Tate dBase III+. I then migrated to FoxPro when it came out.  The natural progression was then to Clipper.  I programmed in Clipper for many years starting with the Summer 87 version and ending with the 5.2 version.  Since late 2018 I’ve been re-learning Clipper 5 and the language additions version 5.3 brought, and have written a few programs that I use regularly now.  Clipper is a fun language to program in!  I’ll be detailing at least one of them in a series of future posts.  Since Clipper is a DOS based programming language I naturally use a DOS virtual machine.  I’ve also been learning the later versions of FoxPro (not the Windows versions).  All of these need different DOS environments setup (include paths, binary paths, library paths, environment variables, etc).  Because of that I setup a crude text based menu asking which environment to setup when I start the DOS virtual machine.  Example:

DOS Choice menu

I’ve been using this crude menu for a long time now and each time I see it I get disappointed.  I toyed around with making this nicer using WordPerfect Office, which I used at one of my employers in the past.  I also tried several menuing programs.  None work like I want them to.  Recalling what my former A-Batch helper did and wishing I still had it, I set out to re-create it.  I have now completed it after just a few evenings of work.

The original version was written in Microsoft C, which I no longer have access to, nor do I own a copy.  I do own a copy of Borlands Turbo C, one of the first C compilers I bought for DOS.  I used Mark Williams C on the Atari ST prior, and some version on the Apple Macintosh in college.  I’ve slept a few times since I last programmed in C, but still remember much of it.  I thought recreating A-Batch would be a great opportunity to brush those skills off.  Since I own a copy of Turbo C, that’s what I set out to do it in.

Now the backstory is out of the way, lets get into the project.  This post will detail what A-Batch is designed to do, how I plan on using it, and it’s features.  The next one will feature the source.

I designed A-Batch as a DOS batch file helper.  It’s primary purpose is to output screen elements with different colors.  To that end there are a few primitives A-Batch provides:

  • Cursor Positioning
  • Boxes
  • Text

I purposely did not design it as a script/file command interpreter.  In other words I don’t want it to read from a file and process all the lines like an interpreted language.  I want it to process one command and exit, returning control back to the batch file.  This approach is not as fast as being fully interpreted, but works for my needs in the simplest form possible.  With this approach I can call A-Batch as needed during the batch file execution lifetime.  With the original version, I had constructed some elaborate multi-screen menus.  Here is an example of the same menu as above, but using my new version of A-Batch to make it more elegant:

A-Batch menu

Much nicer!

The overall usage will be to call A-Batch several times to draw a menu presentation screen.   Example: draw a box, display some text or a box title, then display some more text, all with custom colors and styling elements (borders) where applicable.

I came up with a short list of commands I remember the original A-Batch having:

  • goto x,y
  • draw box
  • show text
  • set background

From there, I settled on the actual command names A-Batch will recognize, and added some additional commands:

  • back = draw background by filling screen using given characters in given color
  • box = draw box at x,y with given width, height using given style in given color
  • cls = clear screen
  • goxy = move cursor to x,y coordinate
  • help = display help/syntax
  • text = display text at x,y in given color
  • title = display box title at x,y with given ornamentation characters in given color
  • version = display program version information
  • wait = pause execution for given number of seconds

Once I had the command list defined (minus help and version), I defined the syntax for each, with each parameter being required.  If a parameter is not present, the command is not executed:

back style fc bc

  • style is the background style passed as a string of 3 characters (left, middle, right).  One character would do, but I implemented it using some of the same constructs used by the box routine, thus the left and right characters are used for the left and right sides (column 1 and 80 respectively).  I may re-address this implementation later, but it works for now.  The default style is “back” which is a string of character 176.
  • fc is the foreground color.  Supported values are: black, blue, green, cyan, red, magenta, brown, lgray, dgray, lblue, lgreen, lcyan, lred, lmagenta, yellow, and white. *
  • bc is the background color.  Supported values are: black, blue, green, cyan, red, magenta, brown, lgray, dgray, lblue, lgreen, lcyan, lred, lmagenta, yellow, and white. *

 

box x y w h style fc bc

  • x is the column for the left side of the box.  Expressed from 1 to 80.
  • y is the row for the top of the box.  Expressed from 1 to 25.
  • w is the width of the box.  Not the end column, the actual width!  Expressed as a number.
  • h is the height of the box.  Not the bottom row, the actual height!  Expressed as a number.
  • style is the border style passed as a string of 10 characters, using same syntax as Clipper (top left, top middle, top right, middle left, bottom right, bottom middle, bottom left, middle right, middle middle, filler).  Supported values are predefined with options of:
    • single = single line border all around with, space as filler
    • double = double line border all around, with space as filler
    • block = full block border all around, with space as filler
    • fat = half block border all around, with space as filler
    • sd = single line border on top and bottom, double line border on left and right, with space as filler
    • ds = double line border on top and bottom, single line border on left and right, with space as filler
    • none = space as border all around, with space as filler
  • fc is the foreground color.  Supported values are: black, blue, green, cyan, red, magenta, brown, lgray, dgray, lblue, lgreen, lcyan, lred, lmagenta, yellow, and white. *
  • bc is the background color.  Supported values are: black, blue, green, cyan, red, magenta, brown, lgray, dgray, lblue, lgreen, lcyan, lred, lmagenta, yellow, and white. *

 

cls

No parameters.  It just clears the screen.  Not really needed since the DOS “cls” command does the same thing.  It was an easy first command to implement to test the parser.

 

goxy x y

  • x is the column to move the cursor to.  Expressed as a number from 1 to 80.
  • y is the row to move the cursor to.  Expressed as a number from 1 to 25.

 

help

No parameters.  It just displays the usage syntax.  This is also presented if no parameters are passed to A-Batch.

 

text x y “text” fc bc

  • x is the column to display the text at.  Expressed as a number from 1 to 80.
  • y is the row to display the text on.  Expressed as a number from 1 to 25.
  • “text” is the text to display.  If there are spaces it should be enclosed in double quotes.
  • fc is the foreground color.  Supported values are: black, blue, green, cyan, red, magenta, brown, lgray, dgray, lblue, lgreen, lcyan, lred, lmagenta, yellow, and white. *
  • bc is the background color.  Supported values are: black, blue, green, cyan, red, magenta, brown, lgray, dgray, lblue, lgreen, lcyan, lred, lmagenta, yellow, and white. *

 

title x y “text” fct bct style fco bco

This command will automatically add a space before and after the title text to separate it from the surrounding ornaments.  I may rethink this later.

  • x is the column to display the title text at.  Expressed as a number from 1 to 80.
  • y is the row to display the title text on.  Expressed as a number from 1 to 25.
  • “text” is the title text to display.  If there are spaces it should be enclosed in double quotes.
  • fct is the foreground color of the title text.  Supported values are: black, blue, green, cyan, red, magenta, brown, lgray, dgray, lblue, lgreen, lcyan, lred, lmagenta, yellow, and white. *
  • bct is the background color of the title text.  Supported values are: black, blue, green, cyan, red, magenta, brown, lgray, dgray, lblue, lgreen, lcyan, lred, lmagenta, yellow, and white. *
  • style is the border style passed as a string of 10 characters, using same syntax as Clipper (top left, top middle, top right, middle left, bottom right, bottom middle, bottom left, middle right, middle middle, filler).  Supported values are predefined with options of:
    • single = single line border all around with, space as filler
    • double = double line border all around, with space as filler
    • block = full block border all around, with space as filler
    • fat = half block border all around, with space as filler
    • sd = single line border on top and bottom, double line border on left and right, with space as filler
    • ds = double line border on top and bottom, single line border on left and right, with space as filler
    • none = space as border all around, with space as filler
  • fco is the foreground color of the title ornaments.  Supported values are: black, blue, green, cyan, red, magenta, brown, lgray, dgray, lblue, lgreen, lcyan, lred, lmagenta, yellow, and white. *
  • bco is the background color of the title ornaments.  Supported values are: black, blue, green, cyan, red, magenta, brown, lgray, dgray, lblue, lgreen, lcyan, lred, lmagenta, yellow, and white. *

 

version

No parameters.  It just displays the program version information.

 

wait n

  • n is the number of seconds to delay

 

* For colors, “blink” is also valid, but not yet implemented.

One thing I will be adding is some auto-centering by means of specific passed values to trigger the ability.  Another feature I will add is a get key routine, which will disable the cursor, get a key from a valid list without echo, then re-enable the cursor, and return the value back as an error code so it can be tested in the batch file.  Once these are in place I will have completely recreated the original A-Batch.  I may have uploaded the original to CompuServe or some BBS’s at some point.  If you stumble on this post and have a copy of my original non-commercial A-Batch, please forward it to me.

In its current form there isn’t any sanity checking on the parameters passed to the commands.  You can overwrite the screen boundaries, supply invalid coordinates, etc.  I may add some of these checks later.  For now I’m not worried about it since this is primary for me to use.

In the next post I will present the source code and walk through it.

 

Share this:

  • Click to email a link to a friend (Opens in new window)
  • Click to share on Facebook (Opens in new window)
  • Click to share on LinkedIn (Opens in new window)
  • Click to share on Pinterest (Opens in new window)
  • Click to share on Pocket (Opens in new window)
  • Click to share on Reddit (Opens in new window)
  • Click to share on Twitter (Opens in new window)

Like this:

Like Loading...

iTunes Missing Feature – Library Statistics

Posted by Ripdubski on 2018.05.04
Posted in: Programming. Tagged: CSS, HTML, iTunes, Javascript, Statistics. 7 Comments

Version update at this new post: https://unfinishedbitness.info/2020/12/06/itunes-missing-feature-library-statistics-revised/

Love it or hate it.  Those are the only two terms I hear from people about iTunes.  This article isn’t going to debate the pro’s and con’s of using iTunes.  No matter which camp you are in, there is one undeniably missing feature – library statistics.  With statistics generated from your library, you can learn a few things about yourself.  I’ve used a couple of tools in the past, and even tried some different library management software that include some basic statistics.  None kept my attention for various reasons ranging from size, ease of use, Java requirements, or simply not enough detail. This article explores the implementation of a standalone statistics generator that meets my needs.

To create this application, which I have called iStats, I had only a few requirements:

  • Must be pleasing to look at (nice colorful graphs).
  • Must be quick (short run time).
  • Must be easy to invoke (as easy as launching a program).

With that in mind, I thought about writing it in several different languages.  In the end I decided that simpler was better, so why not write it in Javascript which can be encapsulated in a single html file.  This would allow double clicking the html file to launch it.  At the same time, I could brush up on my Javascript, learn about HTML5, and learn a charting library.

The tools and resources I used:

  • Atom editor – Very extensible, very easy to use. (https://atom.io)
  • Javascript – Interprested programming language that runs within web browser (https://en.wikipedia.org/wiki/JavaScript) (https://www.w3schools.com/Js/)
  • HTML5 – HyperText Markup Language (https://www.w3schools.com/html/html5_intro.asp)
  • CSS – Cascading Style Sheets (https://www.w3schools.com/Css/)
  • chart.js – Charting library (http://www.chartjs.org)
  • list.js – List library (http://listjs.com)

That most difficult part of the entire project was learning chart.js and configuring the graphs.  While the documentation is good, there is room for improvement in a few areas.  The CSS, Javascript, and HTML5 code are all enclosed in a single html file: “iStats.html”.  This file has a reference to pull in chart.js and list.js.

The application once launched:

Use the “Choose file” button to open a native file selector.  Locate and select the iTunes library XML file (“iTunes Music Library.xml” on a Mac):

Once selected, the application then processes the file, and updates the Document Object Model (DOM – https://www.w3schools.com/js/js_htmldom.asp) with the graph data.  You won’t see any screen updates.  This is due to how Javascript works within the browser.  Any changes in the DOM are rendered in the browser window when the Javascript completes.

Reading a file in the local file system from the browser via Javascript was a bit tricky.  This relies on the Javascript FileReader (https://developer.mozilla.org/en-US/docs/Web/API/FileReader) object.  If your browser doesn’t support the API call (or its disabled), then iStats won’t work. It uses the FileReader readAsText method to read the XML file, then parses it one line at a time.

Once processing is complete, about 10 seconds for my library of 6,700 songs, the page is rendered.  At the top are three list sections.  These were generated into the DOM using the “list.js” library.  The first (leftmost) column are the overall library statistics.  The second (middle) column are the statistics related to play counts.  The third (right) column are statistics related to skip counts.  The lists are ordered such that related items are on the same row:

The remainder of the page is consumed by graphs.  A few examples follow.  At the bottom of this article is a PDF of an entire iStats page where you can see all the graphs, and the iStats source code.

Notice the call out here.  Hovering over a bar on the graph shows the exact value:

This happens to be the last graph of the page.  It shows a timestamp of when the page was generated:

Example PDF of entire iStats output:

https://unfinishedbitness.files.wordpress.com/2018/05/istats-report.pdf

To use iStats, simply extract the linked zip file.  To make things easy, a copy of chart.js and list.js is included (distributed via MIT License), but you should download them yourself.  For your own sanity, review the Javascript source in the “iStats.html” file so you can see there is no funny business going on.  It reads the XML file, and updates the html page DOM, thats it.

The code could stand to be tightened up.  There is plenty of room for code re-use.  I got it to the point where it does what I want and works, but I haven’t cleaned it up.  iStats is being released under the Simplified BSD License.  Feel free to use, modify and improve.

Link to the zip file containing everything you need (hosted at Google Drive): iStats.zip

Version update at this new post: https://unfinishedbitness.info/2020/12/06/itunes-missing-feature-library-statistics-revised/

Share this:

  • Click to email a link to a friend (Opens in new window)
  • Click to share on Facebook (Opens in new window)
  • Click to share on LinkedIn (Opens in new window)
  • Click to share on Pinterest (Opens in new window)
  • Click to share on Pocket (Opens in new window)
  • Click to share on Reddit (Opens in new window)
  • Click to share on Twitter (Opens in new window)

Like this:

Like Loading...

Taming iOS Launcher

Posted by Ripdubski on 2018.04.02
Posted in: iOS. Tagged: iOS Launcher. Leave a comment

I’ve been using an iPhone since the 3GS was released.  At the beginning of 2018, with 3 years on my existing iPhone, I experimented with an Android phone.  This turned out to be a little difficult for daily use, mainly in synchronization, because I use Mac computers.  Mixing the two platform eco systems is possible, but it’s not exactly easy.  I also had constant issues with car connectivity that I won’t go into here.  For me, it didn’t always “just work”, unlike my iOS experiences.  It is entirely possible some or all of the issues were caused by the low end Android hardware I used during the experiment.

Fast foward a bit.  One thing I have always not liked about iOS is having to swipe across multiple pages to find the app I want to launch.  Over the years I tried all kinds of organization techniques, including folders, with nothing really being ideal for me.  With Android you can completely replace the app launcher, and just about any other core component for that matter.  When I was experimenting with Android I ran across a launcher called Smart Launcher (https://play.google.com/store/apps/details?id=ginlemon.flowerfree&ref=producthunt).

I really like how Smart Launcher works.  It takes all your apps and categorizes them for you (which you can fine tune), and places a shortcut bar (or dock) on the side of the screen.  From that, you tap a category, then you tap the app you want to open.  Simple two tap access to everything, and no swiping!  Sample screen shot of Smart Launcher on Android (with Utilities category opened):

After completing my experiment, I set about making my iOS experience similar.  I initially moved all app other than the core phone/communication apps from the primary home screen.  Then I created folders for different categories of apps, like Utilities, Web, Games, etc.  Then I moved these folders to the left side of the screen, and organized the core phone/communication apps on the left side. For this to work effectively you need enough core apps on the screen to push at least one icon into the bottom row, otherwise one or more of the icons will in the left most column.  And you need to limit the folder contents to 9 apps, or you’ll have to swipe left/right inside folders.  Screen shot:

From this newly organized screen I can now tap any of the core phone/communication apps for instant one tap access, or tap a folder and then tap the item inside for simple two tap access.  Open folders appear like this:

I did end up with some overflow onto a second screen.  These are apps that I rarely if ever use such as Compass, AirPort Utility, Files, Find iPhone, and Find Friends.  So I typically will never need to swipe over to that screen.

I’ve been using this setup for a couple of months now, and will likely never go back to any previous method.  It works well.

Share this:

  • Click to email a link to a friend (Opens in new window)
  • Click to share on Facebook (Opens in new window)
  • Click to share on LinkedIn (Opens in new window)
  • Click to share on Pinterest (Opens in new window)
  • Click to share on Pocket (Opens in new window)
  • Click to share on Reddit (Opens in new window)
  • Click to share on Twitter (Opens in new window)

Like this:

Like Loading...

10 Line Database – Atari Style

Posted by Ripdubski on 2017.06.11
Posted in: Atari, Programming. Tagged: 10 Line, 8 bit, BASIC, database. Leave a comment

Many people take part in annual 10 liner contests where they write BASIC programs that are no more than 10 lines long.  Most of these, if not all, are games.  I thought it would be interesting to see if the same could be done for some productivity software.  I chose to build database software.  It may not be elegent or efficient, but that is not the point.  The point is making something functional using only 10 lines of BASIC code!

I’ve been working on this on and off for a couple of years.  I chose to implement it on the Atari 8 bit.  To make it especially challenging I chose Atari BASIC (revision C) as the dialect.  I didn’t set out to make it challenging, it just turned out that way.  Other BASIC’s such as Turbo BASIC, BASIC XL, and Microsoft BASIC (to name a few) are much more powerful.

There are several challenges with Atari BASIC.  The most significant is the lack of in ELSE clause for IF constructs.  This means conditional logic constructs need more lines of code than conventionally necessary – and thats a problem when you only have 10 lines to work with.

So far, I’m on my fourth version of the software, and FINALLY, it is showing results.  Each version I looked at different implementation techniques for data storage.

Currently, there is a preset number of fields (5), present length (25 characters), and a maximum of 255 records.  This means each record is 125 bytes.  125 bytes times 255 records is 31875 bytes (right at 32K).

Here are some screenshots of the software in action.  The first is of a new database being created, a record being added, the records being listed, and the database being saved at exit:

 

The next shows the database being loaded, the records being listed, and the database being saved at exit:

 

The last shows the hex dump of the database file on disk:

 

Now I just need to figure out the delete with just 1 line.  I’ll post the source once I finish, or maybe after I enter the next contest.

 

Share this:

  • Click to email a link to a friend (Opens in new window)
  • Click to share on Facebook (Opens in new window)
  • Click to share on LinkedIn (Opens in new window)
  • Click to share on Pinterest (Opens in new window)
  • Click to share on Pocket (Opens in new window)
  • Click to share on Reddit (Opens in new window)
  • Click to share on Twitter (Opens in new window)

Like this:

Like Loading...

Action! – The Library

Posted by Ripdubski on 2017.04.12
Posted in: Atari, Programming. Tagged: 8 bit, Action!. 1 Comment

A few people have been following the Action! posts and attempted to compile the code only to find there were some missing unpublished routines (unfinished bits 😉 ).  The routines do in fact exist.  I thought I had published all of it in pieces, apparently not.  Attached here is the complete library.  You will need to remove the .ODT file extension leaving just .ATR.  It is NOT an ODT file, WordPress wouldn’t allow the ATR file type.

Download: ActionLibrary10.atr.odt

Hopefully it helps you.

 

Share this:

  • Click to email a link to a friend (Opens in new window)
  • Click to share on Facebook (Opens in new window)
  • Click to share on LinkedIn (Opens in new window)
  • Click to share on Pinterest (Opens in new window)
  • Click to share on Pocket (Opens in new window)
  • Click to share on Reddit (Opens in new window)
  • Click to share on Twitter (Opens in new window)

Like this:

Like Loading...

Automated Offsite Backup

Posted by Ripdubski on 2017.02.26
Posted in: NAS. Tagged: Cloud Sync, DiskStation, Dropbox, DSM, Synology. 1 Comment

In my previous post “Backing Up The Backups” I mentioned I would cover how I push my backups to an offsite location to cover a physical loss scenario (fire, theft, etc).  This post explains how to setup Cloud Sync on a Synology DiskStation to push data to Dropbox.

I have a directory on my Synology Disk Station NAS which is periodically synced to an offsite source.  In my case, I’m using Dropbox, but there are several you can choose from.  I’m not worried about the security.  Dropbox has good security, encryption, and two factor authentication.  On top of that, the files I push to Dropbox are already in an archived,  compressed, and encrypted form (with a very long key).  So even if my Dropbox were compromised, the files are useless to anyone.

First, you must install Cloud Sync.  You will need version 6 or higher of DSM software in order to do this.  Some older DiskStations do not support the newest version.  Go to the Package Manager, and install it.  Once installed, the menu will have an icon for it (in green below):

syn0csmenu

 

Open Cloud Sync, and select the Dropbox provider (or other if you prefer):

syn1provider

 

Define the appropriate settings which include the source location on the NAS, and the destination folder in DropBox (or whatever provider you chose).  You need to also specify the sync type.  I chose a one way sync (from NAS to Dropbox) since I am using it as an offsite backup.  If you want additional encryption, tick the checkbox.  Then click the Next button:

syn2dropboxsynctasksetting

 

Here you confirm the settings.  Click the Advanced Settings button before clicking Next:

syn31dropboxconfirm

 

In the advanced settings, validate all the files types you will be syncing are checked.  You may have to add any file extensions that are not present.  Since I’m uploading an archived, compressed, and encrypted file, I just needed to ensure that single file extension was present.   When satisfied, click OK, then when back on the Confirm Settings window, click Next:

syn32dropboxconfirmadv

 

If the sync task was added successfully, you will get confirmation.  Just click OK to acknowledge:

syn33dropboxcongrats

 

Now you can see the defined Cloud Sync tasks.  The new one is probably running.  You can tell a task is running if it has a blue circle next to the provider on the left.  Clicking on a provider will show you detailed status:

syn41dropboxsyncing

 

If you click on the Task List tab, you will see what tasks are defined and their status.  From here you can also, add, edit, and delete tasks for the provider:

syn42dropboxtasks

 

If you click on the Settings tab, you can view or change the provider name, set the frequency it checks for changes, and define bandwidth throttling:

syn43dropboxsettingspolling

 

When all the tasks for a provider are complete, if will have a green check next it, and on its detail status:

syn50uptodate

 

One thing to note here.  If you don’t have enough online storage at one provider, you can setup syncs to multiple providers, and carefully define which NAS directories are synced to them in order to spread the data across providers.  In my case, I have enough space at Dropbox to meet my needs.

 

Share this:

  • Click to email a link to a friend (Opens in new window)
  • Click to share on Facebook (Opens in new window)
  • Click to share on LinkedIn (Opens in new window)
  • Click to share on Pinterest (Opens in new window)
  • Click to share on Pocket (Opens in new window)
  • Click to share on Reddit (Opens in new window)
  • Click to share on Twitter (Opens in new window)

Like this:

Like Loading...

Mac OS X Native VDI Image Mounts

Posted by Ripdubski on 2017.02.06
Posted in: Apple, OSX. Tagged: Mount, Native, VDI Image, Virtual Hard Disk, VirtualBox. 3 Comments

Overview

This will demonstrate how to mount a VirtualBox VDI hard disk image natively in Mac OS X. Why? It’s a convenient way to add and remove files in the VDI image. With some creativity you could also create a backup of the files inside the VDI image, rather than just the image itself. To do this, I will use the Mac OS X utility hdiutil. No additional software is required.

First, a standard disclaimer! By following this procedure your data is at risk! You accept ALL risk by following this procedure. You are not forced to do this. When in doubt, make a backup of the original VDI image first. If you are not comfortable using the Mac OS X command line, do not attempt!

Second, you will most likely only want to use this with statically sized VDI files, and not the dynamically sized ones – especially if you are going to write to the image!

Third, make sure the virtual host the VDI image is attached to, is NOT running!

How To

OS X’s hdituil can mount the images natively.  However, the VDI image header includes information that hdiutil doesnt want. You will need to find the start location of the data. From the OS X command line, change to the directory where the VDI is stored.  Quick and dirty, you can use hexdump. Or you can find the header size by examining the 4 bytes at 0x158 (344), in this case the bytes are in reverse order (00 00 20 00).

Visual hex dump:

>$ hexdump -C ./DOSTools.vdi | more
00000000 3c 3c 3c 20 4f 72 61 63 6c 65 20 56 4d 20 56 69 |<<< Oracle VM Vi|
00000010 72 74 75 61 6c 42 6f 78 20 44 69 73 6b 20 49 6d |rtualBox Disk Im|
00000020 61 67 65 20 3e 3e 3e 0a 00 00 00 00 00 00 00 00 |age >>>.........|
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000040 7f 10 da be 01 00 01 00 90 01 00 00 01 00 00 00 |................|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000150 00 00 00 00 00 00 10 00 00 00 20 00 00 00 00 00 |.......... .....|
00000160 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 |................|
00000170 00 00 40 06 00 00 00 00 00 00 10 00 00 00 00 00 |..@.............|
00000180 64 00 00 00 16 00 00 00 66 b0 36 e4 f3 25 5f 44 |d.......f.6..%_D|
00000190 b8 c3 c4 b9 0c 66 c4 46 38 87 9b c2 5e 40 2a 49 |.....f.F8...^@*I|
000001a0 82 1f 79 be 28 b4 13 47 00 00 00 00 00 00 00 00 |..y.(..G........|
000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001c0 00 00 00 00 00 00 00 00 cb 00 00 00 10 00 00 00 |................|
000001d0 3f 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 |?...............|
000001e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00100000 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 |................|
00100010 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 |................|
00100020 08 00 00 00 09 00 00 00 0a 00 00 00 0b 00 00 00 |................|
00100030 0c 00 00 00 0d 00 00 00 0e 00 00 00 0f 00 00 00 |................|
00100040 10 00 00 00 11 00 00 00 12 00 00 00 13 00 00 00 |................|
00100050 14 00 00 00 15 00 00 00 ff ff ff ff ff ff ff ff |................|
00100060 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
00100190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00200000 fa 33 c0 8e d0 bc 00 7c 8b f4 50 07 50 1f fb fc |.3.....|..P.P...|
00200010 bf 00 06 b9 00 01 f2 a5 ea 1d 06 00 00 be be 07 |................|
00200020 b3 04 80 3c 80 74 0e 80 3c 00 75 1c 83 c6 10 fe |...<.t..<.u.....|
00200030 cb 75 ef cd 18 8b 14 8b 4c 02 8b ee 83 c6 10 fe |.u......L.......|
00200040 cb 74 1a 80 3c 00 74 f4 be 8b 06 ac 3c 00 74 0b |.t..<.t.....<.t.|
00200050 56 bb 07 00 b4 0e cd 10 5e eb f0 eb fe bf 05 00 |V.......^.......|
00200060 bb 00 7c b8 01 02 57 cd 13 5f 73 0c 33 c0 cd 13 |..|...W.._s.3...|
00200070 4f 75 ed be a3 06 eb d3 be c2 06 bf fe 7d 81 3d |Ou...........}.=|
00200080 55 aa 75 c7 8b f5 ea 00 7c 00 00 49 6e 76 61 6c |U.u.....|..Inval|
00200090 69 64 20 70 61 72 74 69 74 69 6f 6e 20 74 61 62 |id partition tab|
002000a0 6c 65 00 45 72 72 6f 72 20 6c 6f 61 64 69 6e 67 |le.Error loading|
002000b0 20 6f 70 65 72 61 74 69 6e 67 20 73 79 73 74 65 | operating syste|
002000c0 6d 00 4d 69 73 73 69 6e 67 20 6f 70 65 72 61 74 |m.Missing operat|
002000d0 69 6e 67 20 73 79 73 74 65 6d 00 00 00 00 00 00 |ing system......|
002000e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|

Data bytes show that data starts at 0x200000, and is confirmed visually.
hdiutil attach requires start offset definition in sectors. Divide byte offset by sector size to get sector number. 0x200000 (2097152) / 0x200 (512) = 0x1000 (4096).

Create a symlink to the VDI image since hdiutil doesn’t like the vdi extension:

>$ ln -s DOSTools.vdi DOSTools.img

Verify the symlink was created correctly (not required):

>$ ls -al
total 65592
drwx------ 8 user staff 272 Feb 1 20:57 .
drwxr-xr-x 5 user staff 170 Jan 31 22:46 ..
-rw------- 1 user staff 10319 Feb 1 00:06 DOS 6.22.vbox
-rw------- 1 user staff 10319 Feb 1 00:06 DOS 6.22.vbox-prev
-rwx------ 1 user staff 8388608 Feb 1 00:06 DOS 6.22.vdi
lrwxr-xr-x 1 user staff 12 Feb 1 20:57 DOSTools.img -> DOSTools.vdi
-rwx------ 1 user staff 25165824 Feb 1 00:06 DOSTools.vdi
drwx------ 6 user staff 204 Jan 31 23:53 Logs

Mount the image using Mac OS X hdiutil command using the hdid agent, and the data start offset calculated previously (0x1000). Remove the -readonly parameter if you want to write to the image:

>$ hdiutil attach -agent hdid -section 0x1000 -readonly DOSTools.img
/dev/disk2 FDisk_partition_scheme 
/dev/disk2s1 DOS_FAT_16 /Volumes/TOOLS

Now access it as needed.  You can see the two directories in my image (UTILS and APPS):

>$ ls -al /Volumes/TOOLS
total 40
drwxrwxrwx@ 1 user staff 16384 Jan 31 13:17 .
drwxrwxrwt@ 4 root admin 136 Feb 1 20:58 ..
drwxrwxrwx 1 user staff 2048 Jan 31 13:28 UTILS
drwxrwxrwx 1 user staff 2048 Jan 31 13:22 APPS

When done, unmount the image:

>$ hdiutil detach /dev/disk2
"disk2" unmounted.
"disk2" ejected.

 

Share this:

  • Click to email a link to a friend (Opens in new window)
  • Click to share on Facebook (Opens in new window)
  • Click to share on LinkedIn (Opens in new window)
  • Click to share on Pinterest (Opens in new window)
  • Click to share on Pocket (Opens in new window)
  • Click to share on Reddit (Opens in new window)
  • Click to share on Twitter (Opens in new window)

Like this:

Like Loading...

Posts navigation

← Older Entries
Newer Entries →
  • Follow Unfinished Bitness on WordPress.com
  • Enter your email address to follow this blog and receive notifications of new posts by email.

    Join 36 other followers

  • Recent Posts

    • Action! Graphics 0 Text Highlight
    • Modern MacOS App for Retro BBS’ing
    • Splunking Apple Music Library
    • Action! String Padding
    • Action! String Trimming
  • Categories

    • Apple
    • Atari
    • Audio
    • BBS
    • Bookmarks
    • DD-WRT
    • General
    • Google
    • iOS
    • MSDOS
    • NAS
    • Notes
    • OSX
    • Programming
    • Router
    • Security
  • Tags

    1Password 8 bit 12v 110v 6502 Action! Alpine Assembly Atari 400 Atari 800 Atari XE Atari XL BASIC Bookmarks boombox BootScript Car Audio CDA7893 CIO CX430 DD-WRT Delicious DHCP DiskStation DNSMasq EverNote Fitbit fitness ghetto-blaster Google GTO605C HTTP Server iCloud instruction IOCB iOS iTunes JBL Local DNS Mac OSX Mac OS X Migrate One online Opcode OSX Perl SimpleNote Synology Windows
  • Archives

    • June 2022
    • December 2021
    • February 2021
    • December 2020
    • September 2020
    • October 2019
    • May 2018
    • April 2018
    • June 2017
    • April 2017
    • February 2017
    • December 2016
    • September 2016
    • August 2016
    • July 2016
    • June 2016
    • May 2016
    • April 2016
    • September 2015
    • August 2015
    • July 2015
    • May 2015
    • April 2015
    • March 2015
    • February 2015
    • January 2015
    • December 2014
    • November 2014
    • October 2014
    • September 2014
    • August 2014
    • July 2014
    • June 2014
    • May 2014
    • April 2014
    • March 2014
    • February 2014
    • December 2013
    • October 2013
    • June 2013
    • May 2013
    • March 2013
    • February 2013
    • January 2013
  • Meta

    • Register
    • Log in
    • Entries feed
    • Comments feed
    • WordPress.com
Blog at WordPress.com.
Unfinished Bitness
Blog at WordPress.com.
  • Follow Following
    • Unfinished Bitness
    • Join 36 other followers
    • Already have a WordPress.com account? Log in now.
    • Unfinished Bitness
    • Customize
    • Follow Following
    • Sign up
    • Log in
    • Report this content
    • View site in Reader
    • Manage subscriptions
    • Collapse this bar
 

Loading Comments...
 

    %d bloggers like this: