mirror of https://github.com/JorjBauer/aiie.git
Added 32MB hard drive support in slot 7; moved clock to slot 5.
This commit is contained in:
parent
a22f44a535
commit
0fecbd3956
|
@ -6,5 +6,6 @@ parallel.rom
|
||||||
apple/applemmu-rom.h
|
apple/applemmu-rom.h
|
||||||
apple/diskii-rom.h
|
apple/diskii-rom.h
|
||||||
apple/parallel-rom.h
|
apple/parallel-rom.h
|
||||||
|
apple/hd32-rom.h
|
||||||
aiie-sdl
|
aiie-sdl
|
||||||
mockingboard-d.rom
|
mockingboard-d.rom
|
||||||
|
|
8
Makefile
8
Makefile
|
@ -6,11 +6,11 @@ CXXFLAGS=-Wall -I .. -I . -I apple -I sdl -I/usr/local/include/SDL2 -O3 -g
|
||||||
|
|
||||||
TSRC=cpu.cpp util/testharness.cpp
|
TSRC=cpu.cpp util/testharness.cpp
|
||||||
|
|
||||||
COMMONOBJS=cpu.o apple/appledisplay.o apple/applekeyboard.o apple/applemmu.o apple/applevm.o apple/diskii.o apple/nibutil.o RingBuffer.o globals.o apple/parallelcard.o apple/fx80.o lcg.o
|
COMMONOBJS=cpu.o apple/appledisplay.o apple/applekeyboard.o apple/applemmu.o apple/applevm.o apple/diskii.o apple/nibutil.o RingBuffer.o globals.o apple/parallelcard.o apple/fx80.o lcg.o apple/hd32.o
|
||||||
|
|
||||||
SDLOBJS=sdl/sdl-speaker.o sdl/sdl-display.o sdl/sdl-keyboard.o sdl/sdl-paddles.o sdl/sdl-filemanager.o sdl/aiie.o sdl/sdl-printer.o sdl/sdl-clock.o
|
SDLOBJS=sdl/sdl-speaker.o sdl/sdl-display.o sdl/sdl-keyboard.o sdl/sdl-paddles.o sdl/sdl-filemanager.o sdl/aiie.o sdl/sdl-printer.o sdl/sdl-clock.o
|
||||||
|
|
||||||
ROMS=apple/applemmu-rom.h apple/diskii-rom.h apple/parallel-rom.h
|
ROMS=apple/applemmu-rom.h apple/diskii-rom.h apple/parallel-rom.h apple/hd32-rom.h
|
||||||
|
|
||||||
all: sdl
|
all: sdl
|
||||||
|
|
||||||
|
@ -25,8 +25,8 @@ test: $(TSRC)
|
||||||
g++ $(CXXFLAGS) -DEXIT_ON_ILLEGAL -DVERBOSE_CPU_ERRORS -DTESTHARNESS -DVERBOSETEST $(TSRC) -o testharness.verbose
|
g++ $(CXXFLAGS) -DEXIT_ON_ILLEGAL -DVERBOSE_CPU_ERRORS -DTESTHARNESS -DVERBOSETEST $(TSRC) -o testharness.verbose
|
||||||
g++ $(CXXFLAGS) -DEXIT_ON_ILLEGAL -DVERBOSE_CPU_ERRORS -DTESTHARNESS -DEXTENDEDTEST $(TSRC) -o testharness.extended
|
g++ $(CXXFLAGS) -DEXIT_ON_ILLEGAL -DVERBOSE_CPU_ERRORS -DTESTHARNESS -DEXTENDEDTEST $(TSRC) -o testharness.extended
|
||||||
|
|
||||||
roms: apple2e.rom disk.rom parallel.rom
|
roms: apple2e.rom disk.rom parallel.rom HDDRVR.BIN
|
||||||
./util/genrom.pl apple2e.rom disk.rom parallel.rom
|
./util/genrom.pl apple2e.rom disk.rom parallel.rom HDDRVR.BIN
|
||||||
|
|
||||||
apple/applemmu-rom.h: roms
|
apple/applemmu-rom.h: roms
|
||||||
|
|
||||||
|
|
|
@ -25,11 +25,14 @@ AppleVM::AppleVM()
|
||||||
|
|
||||||
#ifdef TEENSYDUINO
|
#ifdef TEENSYDUINO
|
||||||
teensyClock = new TeensyClock((AppleMMU *)mmu);
|
teensyClock = new TeensyClock((AppleMMU *)mmu);
|
||||||
((AppleMMU *)mmu)->setSlot(7, teensyClock);
|
((AppleMMU *)mmu)->setSlot(5, teensyClock);
|
||||||
#else
|
#else
|
||||||
sdlClock = new SDLClock((AppleMMU *)mmu);
|
sdlClock = new SDLClock((AppleMMU *)mmu);
|
||||||
((AppleMMU *)mmu)->setSlot(7, sdlClock);
|
((AppleMMU *)mmu)->setSlot(5, sdlClock);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
hd32 = new HD32((AppleMMU *)mmu);
|
||||||
|
((AppleMMU *)mmu)->setSlot(7, hd32);
|
||||||
}
|
}
|
||||||
|
|
||||||
AppleVM::~AppleVM()
|
AppleVM::~AppleVM()
|
||||||
|
@ -98,6 +101,16 @@ void AppleVM::insertDisk(uint8_t drivenum, const char *filename, bool drawIt)
|
||||||
disk6->insertDisk(drivenum, filename, drawIt);
|
disk6->insertDisk(drivenum, filename, drawIt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppleVM::ejectHD(uint8_t drivenum)
|
||||||
|
{
|
||||||
|
hd32->ejectDisk(drivenum);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppleVM::insertHD(uint8_t drivenum, const char *filename)
|
||||||
|
{
|
||||||
|
hd32->insertDisk(drivenum, filename);
|
||||||
|
}
|
||||||
|
|
||||||
VMKeyboard * AppleVM::getKeyboard()
|
VMKeyboard * AppleVM::getKeyboard()
|
||||||
{
|
{
|
||||||
return keyboard;
|
return keyboard;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "appledisplay.h"
|
#include "appledisplay.h"
|
||||||
#include "diskii.h"
|
#include "diskii.h"
|
||||||
|
#include "hd32.h"
|
||||||
#include "vmkeyboard.h"
|
#include "vmkeyboard.h"
|
||||||
#include "parallelcard.h"
|
#include "parallelcard.h"
|
||||||
#ifdef TEENSYDUINO
|
#ifdef TEENSYDUINO
|
||||||
|
@ -29,9 +30,13 @@ class AppleVM : public VM {
|
||||||
void ejectDisk(uint8_t drivenum);
|
void ejectDisk(uint8_t drivenum);
|
||||||
void insertDisk(uint8_t drivenum, const char *filename, bool drawIt = true);
|
void insertDisk(uint8_t drivenum, const char *filename, bool drawIt = true);
|
||||||
|
|
||||||
|
void ejectHD(uint8_t drivenum);
|
||||||
|
void insertHD(uint8_t drivenum, const char *filename);
|
||||||
|
|
||||||
virtual VMKeyboard *getKeyboard();
|
virtual VMKeyboard *getKeyboard();
|
||||||
|
|
||||||
DiskII *disk6;
|
DiskII *disk6;
|
||||||
|
HD32 *hd32;
|
||||||
protected:
|
protected:
|
||||||
VMKeyboard *keyboard;
|
VMKeyboard *keyboard;
|
||||||
ParallelCard *parallel;
|
ParallelCard *parallel;
|
||||||
|
|
|
@ -0,0 +1,261 @@
|
||||||
|
#include "hd32.h"
|
||||||
|
|
||||||
|
/* AppleWin 32-MB hard drive emulation.
|
||||||
|
*
|
||||||
|
* cf. https://github.com/AppleWin/AppleWin/tree/master/firmware/HDD
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* General interface is outlined in
|
||||||
|
* https://github.com/AppleWin/AppleWin/blob/master/source/Harddisk.cpp
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef TEENSYDUINO
|
||||||
|
#include <Arduino.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "applemmu.h" // for FLOATING
|
||||||
|
|
||||||
|
#include "globals.h"
|
||||||
|
|
||||||
|
#include "hd32-rom.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define DEVICE_OK 0x00
|
||||||
|
#define DEVICE_UNKNOWN_ERROR 0x28
|
||||||
|
#define DEVICE_IO_ERROR 0x27
|
||||||
|
|
||||||
|
// Switches...
|
||||||
|
#define HD32_EXEC_RETSTAT 0x0
|
||||||
|
#define HD32_STATUS 0x1
|
||||||
|
#define HD32_COMMAND 0x2
|
||||||
|
#define HD32_UNITNUM 0x3
|
||||||
|
#define HD32_LBBUF 0x4
|
||||||
|
#define HD32_HBBUF 0x5
|
||||||
|
#define HD32_LBBLOCKNUM 0x6
|
||||||
|
#define HD32_HBBLOCKNUM 0x7
|
||||||
|
#define HD32_NEXTBYTE 0x8
|
||||||
|
|
||||||
|
// Commands
|
||||||
|
#define CMD_STATUS 0x0
|
||||||
|
#define CMD_READ 0x1
|
||||||
|
#define CMD_WRITE 0x2
|
||||||
|
#define CMD_FORMAT 0x3
|
||||||
|
|
||||||
|
HD32::HD32(AppleMMU *mmu)
|
||||||
|
{
|
||||||
|
this->mmu = mmu;
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
HD32::~HD32()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void HD32::Reset()
|
||||||
|
{
|
||||||
|
enabled = 1;
|
||||||
|
|
||||||
|
fd[0] = fd[1] = -1;
|
||||||
|
errorState[0] = errorState[1] = 0;
|
||||||
|
memBlock[0] = memBlock[1] = 0;
|
||||||
|
diskBlock[0] = diskBlock[1] = 0;
|
||||||
|
driveSelected = 0;
|
||||||
|
command = CMD_STATUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t HD32::readSwitches(uint8_t s)
|
||||||
|
{
|
||||||
|
uint8_t ret = DEVICE_OK;
|
||||||
|
|
||||||
|
if (!enabled)
|
||||||
|
return DEVICE_IO_ERROR;
|
||||||
|
|
||||||
|
switch (s) {
|
||||||
|
case HD32_EXEC_RETSTAT:
|
||||||
|
switch (command) {
|
||||||
|
case CMD_STATUS:
|
||||||
|
// set ret to DEVICE_IO_ERROR & set error state=true if no image loaded
|
||||||
|
if (fd[driveSelected] == -1) {
|
||||||
|
// Nothing inserted
|
||||||
|
ret = DEVICE_IO_ERROR;
|
||||||
|
errorState[driveSelected] = 1;
|
||||||
|
} else {
|
||||||
|
ret = DEVICE_OK;
|
||||||
|
errorState[driveSelected] = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_READ:
|
||||||
|
// FIXME: if diskblock[selectedDrive] >= disk image size, set/return io error
|
||||||
|
errorState[driveSelected] = 0;
|
||||||
|
ret = DEVICE_OK;
|
||||||
|
|
||||||
|
cursor[driveSelected] = diskBlock[driveSelected] * 512; // sectors are 512 bytes
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_WRITE:
|
||||||
|
// FIXME: if diskblock[selectedDrive] >= disk image size, set/return io error
|
||||||
|
if (!writeBlockToSelectedDrive()){
|
||||||
|
ret = DEVICE_IO_ERROR;
|
||||||
|
errorState[driveSelected] = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_FORMAT:
|
||||||
|
// Currently ignored. FIXME: make this zero out a 32MB file?
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
errorState[driveSelected] = 1;
|
||||||
|
ret = DEVICE_UNKNOWN_ERROR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HD32_STATUS:
|
||||||
|
ret = errorState[driveSelected];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HD32_COMMAND:
|
||||||
|
ret = command;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HD32_UNITNUM:
|
||||||
|
ret = unitSelected;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HD32_LBBUF:
|
||||||
|
ret = memBlock[driveSelected] & 0x00FF;
|
||||||
|
break;
|
||||||
|
case HD32_HBBUF:
|
||||||
|
ret = ((memBlock[driveSelected] & 0xFF00) >> 8);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HD32_LBBLOCKNUM:
|
||||||
|
ret = diskBlock[driveSelected] & 0x00FF;
|
||||||
|
break;
|
||||||
|
case HD32_HBBLOCKNUM:
|
||||||
|
ret = ((diskBlock[driveSelected] & 0xFF00) >> 8);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HD32_NEXTBYTE:
|
||||||
|
ret = readNextByteFromSelectedDrive();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HD32::writeSwitches(uint8_t s, uint8_t v)
|
||||||
|
{
|
||||||
|
if (!enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (s) {
|
||||||
|
case HD32_COMMAND:
|
||||||
|
command = v;
|
||||||
|
break;
|
||||||
|
case HD32_UNITNUM:
|
||||||
|
unitSelected = v;
|
||||||
|
// FIXME: verify slot#?
|
||||||
|
driveSelected = (v & 0x80) ? 1 : 0;
|
||||||
|
break;
|
||||||
|
case HD32_LBBUF:
|
||||||
|
memBlock[driveSelected] = (memBlock[driveSelected] & 0xFF00) | v;
|
||||||
|
break;
|
||||||
|
case HD32_HBBUF:
|
||||||
|
memBlock[driveSelected] = (memBlock[driveSelected] & 0x00FF) | (v << 8);
|
||||||
|
break;
|
||||||
|
case HD32_LBBLOCKNUM:
|
||||||
|
diskBlock[driveSelected] = (diskBlock[driveSelected] & 0xFF00) | v;
|
||||||
|
break;
|
||||||
|
case HD32_HBBLOCKNUM:
|
||||||
|
diskBlock[driveSelected] = (diskBlock[driveSelected] & 0x00FF) | (v << 8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HD32::loadROM(uint8_t *toWhere)
|
||||||
|
{
|
||||||
|
#ifdef TEENSYDUINO
|
||||||
|
Serial.println("loading HD32 rom");
|
||||||
|
for (uint16_t i=0; i<=0xFF; i++) {
|
||||||
|
toWhere[i] = pgm_read_byte(&romData[i]);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
printf("loading HD32 rom\n");
|
||||||
|
memcpy(toWhere, romData, 256);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t HD32::readNextByteFromSelectedDrive()
|
||||||
|
{
|
||||||
|
// FIXME: assumes file is open & cursor is valid
|
||||||
|
|
||||||
|
uint8_t v;
|
||||||
|
|
||||||
|
v = g_filemanager->readByteAt(fd[driveSelected], cursor[driveSelected]);
|
||||||
|
// FIXME: error handling
|
||||||
|
|
||||||
|
cursor[driveSelected]++;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HD32::writeBlockToSelectedDrive()
|
||||||
|
{
|
||||||
|
// FIXME: assumes file is open & cursor is valid
|
||||||
|
// FIXME: need a better filemanager interface that holds the file open
|
||||||
|
|
||||||
|
for (uint16_t i=0; i<512; i++) {
|
||||||
|
uint8_t b = mmu->read(memBlock[driveSelected] + i);
|
||||||
|
if (!g_filemanager->writeByteAt(fd[driveSelected], b, diskBlock[driveSelected] * 512 + i)) {
|
||||||
|
// FIXME
|
||||||
|
#ifndef TEENSYDUINO
|
||||||
|
printf("ERROR: failed to write to hd file? errno %d\n", errno);
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HD32::setEnabled(uint8_t e)
|
||||||
|
{
|
||||||
|
enabled = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *HD32::diskName(int8_t num)
|
||||||
|
{
|
||||||
|
if (fd[num] != -1)
|
||||||
|
return g_filemanager->fileName(fd[num]);
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void HD32::insertDisk(int8_t driveNum, const char *filename)
|
||||||
|
{
|
||||||
|
ejectDisk(driveNum);
|
||||||
|
fd[driveNum] = g_filemanager->openFile(filename);
|
||||||
|
errorState[driveNum] = 0;
|
||||||
|
enabled = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HD32::ejectDisk(int8_t driveNum)
|
||||||
|
{
|
||||||
|
if (fd[driveNum] != -1) {
|
||||||
|
g_filemanager->closeFile(fd[driveNum]);
|
||||||
|
fd[driveNum] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
#ifndef __HD32_H
|
||||||
|
#define __HD32_H
|
||||||
|
|
||||||
|
#ifdef TEENSYDUINO
|
||||||
|
#include <Arduino.h>
|
||||||
|
#else
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "filemanager.h"
|
||||||
|
#include "applemmu.h"
|
||||||
|
#include "Slot.h"
|
||||||
|
|
||||||
|
#include "RingBuffer.h"
|
||||||
|
|
||||||
|
class HD32 : public Slot {
|
||||||
|
public:
|
||||||
|
HD32(AppleMMU *mmu);
|
||||||
|
virtual ~HD32();
|
||||||
|
|
||||||
|
virtual void Reset(); // used by BIOS cold-boot
|
||||||
|
virtual uint8_t readSwitches(uint8_t s);
|
||||||
|
virtual void writeSwitches(uint8_t s, uint8_t v);
|
||||||
|
virtual void loadROM(uint8_t *toWhere);
|
||||||
|
|
||||||
|
void setEnabled(uint8_t e);
|
||||||
|
|
||||||
|
void insertDisk(int8_t driveNum, const char *filename);
|
||||||
|
void ejectDisk(int8_t driveNum);
|
||||||
|
|
||||||
|
const char *diskName(int8_t num);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint8_t readNextByteFromSelectedDrive();
|
||||||
|
bool writeBlockToSelectedDrive();
|
||||||
|
|
||||||
|
private:
|
||||||
|
AppleMMU *mmu;
|
||||||
|
|
||||||
|
uint8_t driveSelected; // 0 or 1
|
||||||
|
uint8_t unitSelected; // b7 = drive#; b6..4 = slot#; b3..0 = ?
|
||||||
|
uint8_t command; // CMD_*; FIXME, make enum
|
||||||
|
|
||||||
|
uint8_t enabled;
|
||||||
|
|
||||||
|
uint8_t errorState[2]; // status of last operation
|
||||||
|
uint16_t memBlock[2]; // ??
|
||||||
|
uint16_t diskBlock[2]; // currently selected block
|
||||||
|
|
||||||
|
int8_t fd[2];
|
||||||
|
uint32_t cursor[2]; // seek position on the given file handle
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -24,6 +24,9 @@ class FileManager {
|
||||||
virtual bool readBlock(int8_t fd, uint8_t *toWhere, bool isNib = false) = 0;
|
virtual bool readBlock(int8_t fd, uint8_t *toWhere, bool isNib = false) = 0;
|
||||||
virtual bool writeBlock(int8_t fd, uint8_t *fromWhere, bool isNib = false) = 0;
|
virtual bool writeBlock(int8_t fd, uint8_t *fromWhere, bool isNib = false) = 0;
|
||||||
virtual bool writeTrack(int8_t fd, uint8_t *fromWhere, bool isNib = false) = 0;
|
virtual bool writeTrack(int8_t fd, uint8_t *fromWhere, bool isNib = false) = 0;
|
||||||
|
|
||||||
|
virtual uint8_t readByteAt(int8_t fd, uint32_t pos) = 0;
|
||||||
|
virtual bool writeByteAt(int8_t fd, uint8_t v, uint32_t pos) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
23
sdl/aiie.cpp
23
sdl/aiie.cpp
|
@ -32,6 +32,9 @@ int send_rst = 0;
|
||||||
|
|
||||||
pthread_t cpuThreadID;
|
pthread_t cpuThreadID;
|
||||||
|
|
||||||
|
char disk1name[256] = "\0";
|
||||||
|
char disk2name[256] = "\0";
|
||||||
|
|
||||||
void sigint_handler(int n)
|
void sigint_handler(int n)
|
||||||
{
|
{
|
||||||
send_rst = 1;
|
send_rst = 1;
|
||||||
|
@ -133,7 +136,7 @@ static void *cpu_thread(void *dummyptr) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (send_rst) {
|
if (send_rst) {
|
||||||
#if 1
|
#if 0
|
||||||
printf("Sending reset\n");
|
printf("Sending reset\n");
|
||||||
g_cpu->Reset();
|
g_cpu->Reset();
|
||||||
|
|
||||||
|
@ -142,7 +145,17 @@ static void *cpu_thread(void *dummyptr) {
|
||||||
//g_vm->Reset();
|
//g_vm->Reset();
|
||||||
//g_cpu->Reset();
|
//g_cpu->Reset();
|
||||||
//((AppleVM *)g_vm)->insertDisk(0, "disks/DIAGS.DSK");
|
//((AppleVM *)g_vm)->insertDisk(0, "disks/DIAGS.DSK");
|
||||||
|
#else
|
||||||
|
// Swap disks
|
||||||
|
if (disk1name[0] && disk2name[0]) {
|
||||||
|
printf("Swapping disks\n");
|
||||||
|
|
||||||
|
printf("Inserting disk %s in drive 1\n", disk2name);
|
||||||
|
((AppleVM *)g_vm)->insertDisk(0, disk2name);
|
||||||
|
printf("Inserting disk %s in drive 2\n", disk1name);
|
||||||
|
((AppleVM *)g_vm)->insertDisk(1, disk1name);
|
||||||
|
}
|
||||||
|
/*
|
||||||
#else
|
#else
|
||||||
MMU *mmu = g_vm->getMMU();
|
MMU *mmu = g_vm->getMMU();
|
||||||
|
|
||||||
|
@ -169,6 +182,7 @@ static void *cpu_thread(void *dummyptr) {
|
||||||
mmu->write(0x23, 24);
|
mmu->write(0x23, 24);
|
||||||
mmu->write(0x33, '>');
|
mmu->write(0x33, '>');
|
||||||
mmu->write(0x48, 0); // from 0xfb2f: part of text init
|
mmu->write(0x48, 0); // from 0xfb2f: part of text init
|
||||||
|
*/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
send_rst = 0;
|
send_rst = 0;
|
||||||
|
@ -214,12 +228,17 @@ int main(int argc, char *argv[])
|
||||||
if (argc >= 2) {
|
if (argc >= 2) {
|
||||||
printf("Inserting disk %s\n", argv[1]);
|
printf("Inserting disk %s\n", argv[1]);
|
||||||
((AppleVM *)g_vm)->insertDisk(0, argv[1]);
|
((AppleVM *)g_vm)->insertDisk(0, argv[1]);
|
||||||
|
strcpy(disk1name, argv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc == 3) {
|
if (argc == 3) {
|
||||||
printf("Inserting disk %s\n", argv[2]);
|
printf("Inserting disk %s\n", argv[2]);
|
||||||
((AppleVM *)g_vm)->insertDisk(1, argv[2]);
|
((AppleVM *)g_vm)->insertDisk(1, argv[2]);
|
||||||
|
strcpy(disk2name, argv[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: fixed test disk...
|
||||||
|
((AppleVM *)g_vm)->insertHD(0, "hd32.img");
|
||||||
|
|
||||||
nonblock(NB_ENABLE);
|
nonblock(NB_ENABLE);
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ void SDLClock::writeSwitches(uint8_t s, uint8_t v)
|
||||||
// printf("unimplemented write to the clock - 0x%X\n", v);
|
// printf("unimplemented write to the clock - 0x%X\n", v);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: this assumes slot #7
|
// FIXME: this assumes slot #5
|
||||||
void SDLClock::loadROM(uint8_t *toWhere)
|
void SDLClock::loadROM(uint8_t *toWhere)
|
||||||
{
|
{
|
||||||
memset(toWhere, 0xEA, 256); // fill the page with NOPs
|
memset(toWhere, 0xEA, 256); // fill the page with NOPs
|
||||||
|
@ -98,9 +98,9 @@ void SDLClock::loadROM(uint8_t *toWhere)
|
||||||
toWhere[0x06] = 0x70; // BVS
|
toWhere[0x06] = 0x70; // BVS
|
||||||
|
|
||||||
// Pad out those bytes so they will return control well. The program
|
// Pad out those bytes so they will return control well. The program
|
||||||
// at c700 becomes
|
// at c500 becomes
|
||||||
//
|
//
|
||||||
// C700: PHP ; push to stack
|
// C500: PHP ; push to stack
|
||||||
// NOP ; filler (filled in by memory clear)
|
// NOP ; filler (filled in by memory clear)
|
||||||
// PLP ; pop from stack
|
// PLP ; pop from stack
|
||||||
// RTS ; return
|
// RTS ; return
|
||||||
|
@ -112,19 +112,19 @@ void SDLClock::loadROM(uint8_t *toWhere)
|
||||||
|
|
||||||
// And it needs a small routing here to read/write it:
|
// And it needs a small routing here to read/write it:
|
||||||
// 0x08: read
|
// 0x08: read
|
||||||
toWhere[0x08] = 0x4C; // JMP $C710
|
toWhere[0x08] = 0x4C; // JMP $C510
|
||||||
toWhere[0x09] = 0x10;
|
toWhere[0x09] = 0x10;
|
||||||
toWhere[0x0A] = 0xC7;
|
toWhere[0x0A] = 0xC5;
|
||||||
|
|
||||||
// 0x0b: write
|
// 0x0b: write
|
||||||
toWhere[0x0B] = 0x8D; // STA $C0F0 (slot 7's first switch)
|
toWhere[0x0B] = 0x8D; // STA $C0D0 (slot 5's first switch)
|
||||||
toWhere[0x0C] = 0xF0;
|
toWhere[0x0C] = 0xD0;
|
||||||
toWhere[0x0D] = 0xC0;
|
toWhere[0x0D] = 0xC0;
|
||||||
toWhere[0x0E] = 0x60; // RTS
|
toWhere[0x0E] = 0x60; // RTS
|
||||||
|
|
||||||
// simple read
|
// simple read
|
||||||
toWhere[0x10] = 0xAD; // LDA $C0F0 (slot 7's first switch)
|
toWhere[0x10] = 0xAD; // LDA $C0D0 (slot 5's first switch)
|
||||||
toWhere[0x11] = 0xF0;
|
toWhere[0x11] = 0xD0;
|
||||||
toWhere[0x12] = 0xC0;
|
toWhere[0x12] = 0xC0;
|
||||||
toWhere[0x13] = 0x60; // RTS
|
toWhere[0x13] = 0x60; // RTS
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include "sdl-filemanager.h"
|
#include "sdl-filemanager.h"
|
||||||
|
|
||||||
|
@ -187,3 +188,51 @@ bool SDLFileManager::writeTrack(int8_t fd, uint8_t *fromWhere, bool isNib)
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t SDLFileManager::readByteAt(int8_t fd, uint32_t pos)
|
||||||
|
{
|
||||||
|
if (fd < 0 || fd >= numCached)
|
||||||
|
return -1; // FIXME: error handling?
|
||||||
|
|
||||||
|
if (cachedNames[fd][0] == 0)
|
||||||
|
return -1; // FIXME: error handling?
|
||||||
|
|
||||||
|
uint8_t v = 0;
|
||||||
|
|
||||||
|
// open, seek, read, close.
|
||||||
|
bool ret = false;
|
||||||
|
int ffd = open(cachedNames[fd], O_RDONLY);
|
||||||
|
if (ffd) {
|
||||||
|
lseek(ffd, pos, SEEK_SET);
|
||||||
|
ret = (read(ffd, &v, 1) == 1);
|
||||||
|
close(ffd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
printf("ERROR reading: %d\n", errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: error handling?
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDLFileManager::writeByteAt(int8_t fd, uint8_t v, uint32_t pos)
|
||||||
|
{
|
||||||
|
if (fd < 0 || fd >= numCached)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (cachedNames[fd][0] == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// open, seek, write, close.
|
||||||
|
bool ret = false;
|
||||||
|
int ffd = open(cachedNames[fd], O_WRONLY);
|
||||||
|
if (ffd) {
|
||||||
|
lseek(ffd, pos, SEEK_SET);
|
||||||
|
ret = (write(ffd, &v, 1) == 1);
|
||||||
|
close(ffd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,9 @@ class SDLFileManager : public FileManager {
|
||||||
virtual bool writeBlock(int8_t fd, uint8_t *fromWhere, bool isNib = false);
|
virtual bool writeBlock(int8_t fd, uint8_t *fromWhere, bool isNib = false);
|
||||||
virtual bool writeTrack(int8_t fd, uint8_t *fromWhere, bool isNib = false);
|
virtual bool writeTrack(int8_t fd, uint8_t *fromWhere, bool isNib = false);
|
||||||
|
|
||||||
|
virtual uint8_t readByteAt(int8_t fd, uint32_t pos);
|
||||||
|
virtual bool writeByteAt(int8_t fd, uint8_t v, uint32_t pos);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int8_t numCached;
|
int8_t numCached;
|
||||||
char cachedNames[MAXFILES][MAXPATH];
|
char cachedNames[MAXFILES][MAXPATH];
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
../apple/hd32-rom.h
|
|
@ -0,0 +1 @@
|
||||||
|
../apple/hd32.cpp
|
|
@ -0,0 +1 @@
|
||||||
|
../apple/hd32.h
|
|
@ -81,7 +81,7 @@ void TeensyClock::writeSwitches(uint8_t s, uint8_t v)
|
||||||
// printf("unimplemented write to the clock - 0x%X\n", v);
|
// printf("unimplemented write to the clock - 0x%X\n", v);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: this assumes slot #7
|
// FIXME: this assumes slot #5
|
||||||
void TeensyClock::loadROM(uint8_t *toWhere)
|
void TeensyClock::loadROM(uint8_t *toWhere)
|
||||||
{
|
{
|
||||||
memset(toWhere, 0xEA, 256); // fill the page with NOPs
|
memset(toWhere, 0xEA, 256); // fill the page with NOPs
|
||||||
|
@ -93,9 +93,9 @@ void TeensyClock::loadROM(uint8_t *toWhere)
|
||||||
toWhere[0x06] = 0x70; // BVS
|
toWhere[0x06] = 0x70; // BVS
|
||||||
|
|
||||||
// Pad out those bytes so they will return control well. The program
|
// Pad out those bytes so they will return control well. The program
|
||||||
// at c700 becomes
|
// at c500 becomes
|
||||||
//
|
//
|
||||||
// C700: PHP ; push to stack
|
// C500: PHP ; push to stack
|
||||||
// NOP ; filler (filled in by memory clear)
|
// NOP ; filler (filled in by memory clear)
|
||||||
// PLP ; pop from stack
|
// PLP ; pop from stack
|
||||||
// RTS ; return
|
// RTS ; return
|
||||||
|
@ -107,19 +107,19 @@ void TeensyClock::loadROM(uint8_t *toWhere)
|
||||||
|
|
||||||
// And it needs a small routing here to read/write it:
|
// And it needs a small routing here to read/write it:
|
||||||
// 0x08: read
|
// 0x08: read
|
||||||
toWhere[0x08] = 0x4C; // JMP $C710
|
toWhere[0x08] = 0x4C; // JMP $C510
|
||||||
toWhere[0x09] = 0x10;
|
toWhere[0x09] = 0x10;
|
||||||
toWhere[0x0A] = 0xC7;
|
toWhere[0x0A] = 0xC5;
|
||||||
|
|
||||||
// 0x0b: write
|
// 0x0b: write
|
||||||
toWhere[0x0B] = 0x8D; // STA $C0F0 (slot 7's first switch)
|
toWhere[0x0B] = 0x8D; // STA $C0D0 (slot 5's first switch)
|
||||||
toWhere[0x0C] = 0xF0;
|
toWhere[0x0C] = 0xD0;
|
||||||
toWhere[0x0D] = 0xC0;
|
toWhere[0x0D] = 0xC0;
|
||||||
toWhere[0x0E] = 0x60; // RTS
|
toWhere[0x0E] = 0x60; // RTS
|
||||||
|
|
||||||
// simple read
|
// simple read
|
||||||
toWhere[0x10] = 0xAD; // LDA $C0F0 (slot 7's first switch)
|
toWhere[0x10] = 0xAD; // LDA $C0D0 (slot 5's first switch)
|
||||||
toWhere[0x11] = 0xF0;
|
toWhere[0x11] = 0xD0;
|
||||||
toWhere[0x12] = 0xC0;
|
toWhere[0x12] = 0xC0;
|
||||||
toWhere[0x13] = 0x60; // RTS
|
toWhere[0x13] = 0x60; // RTS
|
||||||
}
|
}
|
||||||
|
|
|
@ -273,3 +273,54 @@ bool TeensyFileManager::writeTrack(int8_t fd, uint8_t *fromWhere, bool isNib)
|
||||||
return (v == (isNib ? 0x1a00 : (256*16)));
|
return (v == (isNib ? 0x1a00 : (256*16)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t TeensyFileManager::readByteAt(int8_t fd, uint32_t pos)
|
||||||
|
{
|
||||||
|
// open, seek, read, close.
|
||||||
|
if (fd < 0 || fd >= numCached)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (cachedNames[fd][0] == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// open, seek, read, close.
|
||||||
|
TCHAR buf[MAXPATH];
|
||||||
|
char2tchar(cachedNames[fd], MAXPATH, buf);
|
||||||
|
FRESULT rc = f_open(&fil, (TCHAR*) buf, FA_READ);
|
||||||
|
if (rc) {
|
||||||
|
Serial.println("readByteAt: failed to open");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = f_lseek(&fil, pos);
|
||||||
|
if (rc) {
|
||||||
|
Serial.println("readByteAt: seek failed");
|
||||||
|
f_close(&fil);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint8_t b;
|
||||||
|
UINT v;
|
||||||
|
f_read(&fil, &b, 1, &v);
|
||||||
|
f_close(&fil);
|
||||||
|
return (v == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TeensyFileManager::writeByteAt(int8_t fd, uint8_t v, uint32_t pos)
|
||||||
|
{
|
||||||
|
// open, seek, write, close.
|
||||||
|
if (fd < 0 || fd >= numCached)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (cachedNames[fd][0] == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// open, seek, write, close.
|
||||||
|
TCHAR buf[MAXPATH];
|
||||||
|
char2tchar(cachedNames[fd], MAXPATH, buf);
|
||||||
|
FRESULT rc = f_open(&fil, (TCHAR*) buf, FA_WRITE);
|
||||||
|
rc = f_lseek(&fil, pos);
|
||||||
|
UINT ret;
|
||||||
|
f_write(&fil, &v, 1, &ret);
|
||||||
|
f_close(&fil);
|
||||||
|
return (ret == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,9 @@ class TeensyFileManager : public FileManager {
|
||||||
virtual bool writeBlock(int8_t fd, uint8_t *fromWhere, bool isNib = false);
|
virtual bool writeBlock(int8_t fd, uint8_t *fromWhere, bool isNib = false);
|
||||||
virtual bool writeTrack(int8_t fd, uint8_t *fromWhere, bool isNib = false);
|
virtual bool writeTrack(int8_t fd, uint8_t *fromWhere, bool isNib = false);
|
||||||
|
|
||||||
|
virtual uint8_t readByteAt(int8_t fd, uint32_t pos);
|
||||||
|
virtual bool writeByteAt(int8_t fd, uint8_t v, uint32_t pos);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int8_t numCached;
|
int8_t numCached;
|
||||||
char cachedNames[MAXFILES][MAXPATH];
|
char cachedNames[MAXFILES][MAXPATH];
|
||||||
|
|
|
@ -6,14 +6,17 @@ use warnings;
|
||||||
my $romfile = shift || die "Must provide the path to an Apple //e ROM image";
|
my $romfile = shift || die "Must provide the path to an Apple //e ROM image";
|
||||||
my $diskrom = shift || die "Must also provide the path to an Apple //e Disk II ROM image";
|
my $diskrom = shift || die "Must also provide the path to an Apple //e Disk II ROM image";
|
||||||
my $parallelrom = shift || die "Must also provide the path to an Apple // parallel card ROM image";
|
my $parallelrom = shift || die "Must also provide the path to an Apple // parallel card ROM image";
|
||||||
|
my $hdrom = shift || die "Must also provide the path to the AppleWin HDDRVR.BIN";
|
||||||
|
|
||||||
validate($romfile, 32768, "an Apple //e ROM image");
|
validate($romfile, 32768, "an Apple //e ROM image");
|
||||||
validate($diskrom, 256, "a DiskII ROM image");
|
validate($diskrom, 256, "a DiskII ROM image");
|
||||||
validate($parallelrom, 256, "a parallel card ROM image");
|
validate($parallelrom, 256, "a parallel card ROM image");
|
||||||
|
validate($hdrom, 256, "HDDRVR.BIN from AppleWin");
|
||||||
|
|
||||||
dumpRom($romfile, "apple/applemmu-rom.h", "romData", 32768);
|
dumpRom($romfile, "apple/applemmu-rom.h", "romData", 32768);
|
||||||
dumpRom($diskrom, "apple/diskii-rom.h", "romData", 256);
|
dumpRom($diskrom, "apple/diskii-rom.h", "romData", 256);
|
||||||
dumpRom($parallelrom, "apple/parallel-rom.h", "romData", 256);
|
dumpRom($parallelrom, "apple/parallel-rom.h", "romData", 256);
|
||||||
|
dumpRom($hdrom, "apple/hd32-rom.h", "romData", 256);
|
||||||
exit 0;
|
exit 0;
|
||||||
|
|
||||||
sub validate {
|
sub validate {
|
||||||
|
|
Loading…
Reference in New Issue