2019-02-25 23:42:47 +00:00
|
|
|
#include "AppleIISd.h"
|
|
|
|
|
2020-10-03 09:30:57 +00:00
|
|
|
#include <assert.h>
|
2019-02-24 10:24:04 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <conio.h>
|
2020-10-03 09:30:57 +00:00
|
|
|
#include <string.h>
|
2019-02-24 10:24:04 +00:00
|
|
|
#include <apple2enh.h>
|
|
|
|
|
2020-08-30 12:07:27 +00:00
|
|
|
// Binary can't be larger than 2k
|
|
|
|
#define BUFFER_SIZE 2048
|
2019-03-04 21:01:07 +00:00
|
|
|
#define BIN_FILE_NAME "AppleIISd.bin"
|
|
|
|
|
2019-02-25 23:42:47 +00:00
|
|
|
typedef enum
|
|
|
|
{
|
2019-03-04 21:01:07 +00:00
|
|
|
STATE_0, // pipe
|
|
|
|
STATE_1, // slash
|
|
|
|
STATE_2, // hyphen
|
|
|
|
STATE_3, // backslash
|
2019-02-25 23:42:47 +00:00
|
|
|
|
2020-08-30 12:07:27 +00:00
|
|
|
STATE_LAST // don't use
|
2019-02-25 23:42:47 +00:00
|
|
|
} STATE_CURSOR_T;
|
|
|
|
|
2019-03-04 21:01:07 +00:00
|
|
|
const char state_char[STATE_LAST] = { '|', '/', '-', '\\' };
|
2020-10-03 09:30:57 +00:00
|
|
|
static uint8 buffer[BUFFER_SIZE];
|
2019-03-04 21:00:36 +00:00
|
|
|
|
2020-10-01 14:35:55 +00:00
|
|
|
static void writeChip(const uint8* pSource, volatile uint8* pDest, uint16 length);
|
|
|
|
static boolean verifyChip(const uint8* pSource, volatile uint8* pDest, uint16 length);
|
|
|
|
static void printStatus(uint8 percentage);
|
2019-02-25 23:42:47 +00:00
|
|
|
|
2019-02-24 10:24:04 +00:00
|
|
|
int main()
|
|
|
|
{
|
2020-06-04 09:49:56 +00:00
|
|
|
int retval = 1;
|
2019-02-24 10:24:04 +00:00
|
|
|
FILE* pFile;
|
|
|
|
char slotNum;
|
2020-06-04 09:49:56 +00:00
|
|
|
boolean erase = FALSE;
|
|
|
|
uint16 fileSize = 0;
|
2019-02-24 10:24:04 +00:00
|
|
|
|
2019-02-25 23:42:47 +00:00
|
|
|
APPLE_II_SD_T* pAIISD = (APPLE_II_SD_T*)SLOT_IO_START;
|
2020-08-30 12:07:27 +00:00
|
|
|
volatile uint8* pSlotRom = SLOT_ROM_START;
|
2020-12-21 14:12:15 +00:00
|
|
|
volatile uint8 dummy;
|
2019-02-25 23:42:47 +00:00
|
|
|
|
2019-03-07 20:29:29 +00:00
|
|
|
videomode(VIDEOMODE_40COL);
|
2019-02-25 23:42:47 +00:00
|
|
|
clrscr();
|
2020-10-03 09:30:57 +00:00
|
|
|
cprintf("AppleIISd firmware flasher V1.2\r\n");
|
2020-06-04 09:49:56 +00:00
|
|
|
cprintf("(c) 2019-2020 Florian Reitz\r\n\r\n");
|
2020-10-03 09:30:57 +00:00
|
|
|
|
2019-02-24 10:24:04 +00:00
|
|
|
// ask for slot
|
|
|
|
cursor(1); // enable blinking cursor
|
|
|
|
cprintf("Slot number (1-7): ");
|
2019-03-04 21:01:07 +00:00
|
|
|
cscanf("%c", &slotNum);
|
|
|
|
slotNum -= 0x30;
|
|
|
|
cursor(0); // disable blinking cursor
|
2019-02-24 10:24:04 +00:00
|
|
|
|
2020-06-04 09:49:56 +00:00
|
|
|
if(slotNum == 0)
|
|
|
|
{
|
|
|
|
// erase device
|
|
|
|
erase = TRUE;
|
|
|
|
// ask for slot
|
|
|
|
cursor(1); // enable blinking cursor
|
|
|
|
cprintf("Erase device in slot number (1-7): ");
|
|
|
|
cscanf("%c", &slotNum);
|
|
|
|
slotNum -= 0x30;
|
|
|
|
cursor(0); // disable blinking cursor
|
|
|
|
}
|
|
|
|
|
2019-02-24 10:24:04 +00:00
|
|
|
// check if slot is valid
|
|
|
|
if((slotNum < 1) || (slotNum > 7))
|
|
|
|
{
|
2019-03-04 21:01:07 +00:00
|
|
|
cprintf("\r\nInvalid slot number!");
|
2019-03-07 20:29:29 +00:00
|
|
|
cgetc();
|
2019-02-24 10:24:04 +00:00
|
|
|
return 1; // failure
|
|
|
|
}
|
|
|
|
|
2019-03-04 21:00:36 +00:00
|
|
|
((uint8*)pAIISD) += slotNum << 4;
|
2019-02-25 23:42:47 +00:00
|
|
|
pSlotRom += slotNum << 8;
|
|
|
|
|
2020-06-04 09:49:56 +00:00
|
|
|
if(erase)
|
2019-02-24 10:24:04 +00:00
|
|
|
{
|
2020-08-30 12:07:27 +00:00
|
|
|
fileSize = BUFFER_SIZE;
|
2020-10-03 09:30:57 +00:00
|
|
|
memset(buffer, 0, sizeof(buffer));
|
2020-06-04 09:49:56 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// open file
|
|
|
|
pFile = fopen(BIN_FILE_NAME, "rb");
|
|
|
|
if(pFile)
|
2019-03-04 21:00:36 +00:00
|
|
|
{
|
2020-06-04 09:49:56 +00:00
|
|
|
// read buffer
|
|
|
|
fileSize = fread(buffer, 1, sizeof(buffer), pFile);
|
|
|
|
fclose(pFile);
|
|
|
|
pFile = NULL;
|
2019-02-24 10:24:04 +00:00
|
|
|
|
2020-08-30 12:07:27 +00:00
|
|
|
if(fileSize != BUFFER_SIZE)
|
2019-03-05 19:41:36 +00:00
|
|
|
{
|
2020-06-04 09:49:56 +00:00
|
|
|
cprintf("\r\nWrong file size: %d\r\n", fileSize);
|
2019-03-05 19:41:36 +00:00
|
|
|
}
|
2019-03-04 21:00:36 +00:00
|
|
|
}
|
|
|
|
else
|
2019-02-25 23:42:47 +00:00
|
|
|
{
|
2020-06-04 09:49:56 +00:00
|
|
|
cprintf("\r\nCan't open %s file\r\n", BIN_FILE_NAME);
|
|
|
|
fileSize = 0;
|
2019-02-25 23:42:47 +00:00
|
|
|
}
|
2019-02-24 10:24:04 +00:00
|
|
|
}
|
2020-06-04 09:49:56 +00:00
|
|
|
|
2020-08-30 12:07:27 +00:00
|
|
|
if(fileSize == BUFFER_SIZE)
|
2019-02-24 10:24:04 +00:00
|
|
|
{
|
2020-06-04 09:49:56 +00:00
|
|
|
// enable write
|
|
|
|
pAIISD->status.pgmen = 1;
|
|
|
|
|
|
|
|
// write to SLOTROM
|
|
|
|
cprintf("\r\n\r\nFlashing SLOTROM: ");
|
2020-10-01 14:35:55 +00:00
|
|
|
writeChip(buffer, pSlotRom, 256);
|
2020-12-21 14:12:15 +00:00
|
|
|
|
2020-10-03 09:30:57 +00:00
|
|
|
cprintf("\r\nVerifying SLOTROM: ");
|
2020-10-01 14:35:55 +00:00
|
|
|
if(verifyChip(buffer, pSlotRom, 256))
|
2020-06-04 09:49:56 +00:00
|
|
|
{
|
2020-12-21 14:12:15 +00:00
|
|
|
// write to EXT_ROM
|
2020-10-03 09:30:57 +00:00
|
|
|
cprintf("\r\n\r\nFlashing EXTROM: ");
|
2020-12-21 14:12:15 +00:00
|
|
|
|
|
|
|
// clear CFFF and dummy read to enable correct EXT_ROM
|
|
|
|
dummy = *CFFF;
|
|
|
|
dummy = *pSlotRom;
|
|
|
|
|
2020-10-01 14:35:55 +00:00
|
|
|
writeChip(buffer + 256, EXT_ROM_START, fileSize - 256);
|
|
|
|
cprintf("\r\nVerifying EXTROM: ");
|
2020-12-21 14:12:15 +00:00
|
|
|
|
|
|
|
dummy = *CFFF;
|
|
|
|
dummy = *pSlotRom;
|
|
|
|
|
2020-10-01 14:35:55 +00:00
|
|
|
if(verifyChip(buffer + 256, EXT_ROM_START, fileSize - 256))
|
2020-06-04 09:49:56 +00:00
|
|
|
{
|
|
|
|
cprintf("\r\n\r\nFlashing finished!\n");
|
|
|
|
retval = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// disable write
|
|
|
|
pAIISD->status.pgmen = 0;
|
2019-02-24 10:24:04 +00:00
|
|
|
}
|
|
|
|
|
2019-03-07 20:29:29 +00:00
|
|
|
cgetc();
|
2019-03-05 19:41:36 +00:00
|
|
|
return retval;
|
2019-02-24 10:24:04 +00:00
|
|
|
}
|
|
|
|
|
2020-10-01 14:35:55 +00:00
|
|
|
static void writeChip(const uint8* pSource, volatile uint8* pDest, uint16 length)
|
2019-02-25 23:42:47 +00:00
|
|
|
{
|
2019-03-04 21:00:36 +00:00
|
|
|
uint32 i;
|
2020-08-30 12:07:27 +00:00
|
|
|
volatile uint8 readData;
|
2019-03-05 19:41:36 +00:00
|
|
|
|
2019-02-25 23:42:47 +00:00
|
|
|
for(i=0; i<length; i++)
|
|
|
|
{
|
2020-10-03 09:30:57 +00:00
|
|
|
pDest[i] = pSource[i];
|
2019-03-07 20:29:29 +00:00
|
|
|
printStatus((i * 100u / length) + 1);
|
|
|
|
|
2020-05-05 16:48:03 +00:00
|
|
|
// wait for write cycle
|
|
|
|
do
|
|
|
|
{
|
2020-10-03 09:30:57 +00:00
|
|
|
readData = pDest[i];
|
2020-05-05 16:48:03 +00:00
|
|
|
}
|
2020-10-03 09:30:57 +00:00
|
|
|
while((readData & 0x80) != (pSource[i] & 0x80));
|
2020-10-01 14:35:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static boolean verifyChip(const uint8* pSource, volatile uint8* pDest, uint16 length)
|
|
|
|
{
|
|
|
|
uint32 i;
|
|
|
|
|
|
|
|
for(i=0; i<length; i++)
|
|
|
|
{
|
|
|
|
printStatus((i * 100u / length) + 1);
|
|
|
|
|
2020-10-03 09:30:57 +00:00
|
|
|
if(pDest[i] != pSource[i])
|
2019-02-25 23:42:47 +00:00
|
|
|
{
|
2019-03-05 19:41:36 +00:00
|
|
|
// verification not successful
|
2020-10-03 09:30:57 +00:00
|
|
|
cprintf("\r\n\r\n!!! Verification failed at %p !!!\r\n", &pDest[i]);
|
|
|
|
cprintf("Was 0x%02hhX, should be 0x%02hhX\r\n", pDest[i], pSource[i]);
|
2019-03-05 19:41:36 +00:00
|
|
|
return FALSE;
|
2019-02-25 23:42:47 +00:00
|
|
|
}
|
|
|
|
}
|
2019-03-05 19:41:36 +00:00
|
|
|
|
|
|
|
return TRUE;
|
2019-02-25 23:42:47 +00:00
|
|
|
}
|
|
|
|
|
2020-10-01 14:35:55 +00:00
|
|
|
static void printStatus(uint8 percentage)
|
2019-02-25 23:42:47 +00:00
|
|
|
{
|
|
|
|
static STATE_CURSOR_T state = STATE_0;
|
2019-03-04 21:00:36 +00:00
|
|
|
uint8 wait = 0;
|
|
|
|
uint8 x = wherex();
|
2019-03-04 21:01:07 +00:00
|
|
|
char cState = (percentage < 100) ? state_char[state] : ' ';
|
|
|
|
|
2019-03-07 20:29:29 +00:00
|
|
|
cprintf("% 3hhu%% %c", percentage, cState);
|
2019-02-25 23:42:47 +00:00
|
|
|
gotox(x);
|
2019-02-24 10:24:04 +00:00
|
|
|
|
2019-02-25 23:42:47 +00:00
|
|
|
state++;
|
|
|
|
if(state == STATE_LAST)
|
|
|
|
{
|
|
|
|
state = STATE_0;
|
|
|
|
}
|
|
|
|
}
|