mirror of
https://github.com/Spritetm/minimacplus.git
synced 2024-06-03 06:29:43 +00:00
LocalTalk LLAP now works. Implemented this as a dummy network which responds with an ack to each enq, which coincidentally makes the Mac hang...
This commit is contained in:
parent
6d04d3b857
commit
c59ce7fbb0
|
@ -4,7 +4,7 @@ TARGET:=tme
|
|||
MUSASHI_GEN_SRC:=musashi/m68kopac.c musashi/m68kopdm.c musashi/m68kopnz.c
|
||||
MUSASHI_OP_PREGEN_SRC:=musashi/m68kops_pre.c
|
||||
OBJ:=$(MUSASHI_GEN_SRC:%.x=%.o) $(MUSASHI_OP_PREGEN_SRC:%.x=%.o) musashi/m68kcpu.o sdl/main.o sdl/disp.o sdl/hd.o \
|
||||
emu.o iwm.o via.o rtc.o ncr.o scc.o mouse.o hostbuild/espspiramemu.o
|
||||
emu.o iwm.o via.o rtc.o ncr.o scc.o mouse.o hostbuild/espspiramemu.o hexdump.o localtalk.o
|
||||
#musashi/m68kdasm.o
|
||||
CFLAGS=-Wall -I. -I./musashi -I./hostbuild -Og -ggdb `sdl2-config --cflags`
|
||||
LDFLAGS=`sdl2-config --libs`
|
||||
|
|
|
@ -458,11 +458,11 @@ void tmeStartEmu(void *rom) {
|
|||
printf("Creating HD and registering it...\n");
|
||||
SCSIDevice *hd=hdCreate("hd.img");
|
||||
ncrRegisterDevice(6, hd);
|
||||
printf("Initializing m68k...\n");
|
||||
viaClear(VIA_PORTA, 0x7F);
|
||||
viaSet(VIA_PORTA, 0x80);
|
||||
viaClear(VIA_PORTA, 0xFF);
|
||||
viaSet(VIA_PORTB, (1<<3));
|
||||
sccInit();
|
||||
printf("Initializing m68k...\n");
|
||||
m68k_init();
|
||||
printf("Setting CPU type and resetting...");
|
||||
|
@ -475,6 +475,7 @@ void tmeStartEmu(void *rom) {
|
|||
for (x=0; x<8000000/60; x+=10) {
|
||||
m68k_execute(10);
|
||||
viaStep(1); //should run at 783.36KHz
|
||||
sccTick();
|
||||
m++;
|
||||
if (m>=1000) {
|
||||
int r=mouseTick();
|
||||
|
|
64
components/tme/hexdump.c
Normal file
64
components/tme/hexdump.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
//Utility function to perform hexdumps in the default format of the bsd hexdump utility
|
||||
//(C) 2017 Jeroen Domburg <jeroen at spritesmods dot com>
|
||||
//This file is public domain where possible or CC0-licensed where not.
|
||||
//CC0: https://creativecommons.org/share-your-work/public-domain/cc0/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void hexdumpFrom(void *mem, int len, int adrStart) {
|
||||
uint8_t *data=(uint8_t*)mem;
|
||||
int pos=0;
|
||||
while (pos<len) {
|
||||
//Print address
|
||||
printf("%08x", pos+adrStart);
|
||||
//Print hex bytes
|
||||
for (int i=0; i<16; i++) {
|
||||
if ((i&7)==0) printf(" ");
|
||||
if (pos+i<len) {
|
||||
printf(" %02x", data[pos+i]);
|
||||
} else {
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
//Print ASCII bytes
|
||||
printf(" |");
|
||||
for (int i=0; i<16; i++) {
|
||||
//Abort if at end
|
||||
if (pos+i>=len) break;
|
||||
//Print if printable
|
||||
if (isprint((int)data[pos+i])) {
|
||||
printf("%c", data[pos+i]);
|
||||
} else {
|
||||
printf(".");
|
||||
}
|
||||
}
|
||||
printf("|\n");
|
||||
pos+=16;
|
||||
}
|
||||
printf("%08x\n", adrStart+len);
|
||||
}
|
||||
|
||||
|
||||
void hexdump(void *mem, int len) {
|
||||
hexdumpFrom(mem, len, 0);
|
||||
}
|
||||
|
||||
|
||||
//Uncomment the following line and compile 'gcc -o hexdump hexdump.c' to create a barebones hexdump utility that
|
||||
//reads stdin and dumps the hex content of it to stdout
|
||||
//#define TESTCASE
|
||||
|
||||
#ifdef TESTCASE
|
||||
#include <stdlib.h>
|
||||
int main(int argc, char **argv) {
|
||||
char buff[1024];
|
||||
int adr=0;
|
||||
if (argc>1) adr=strtol(argv[1], NULL, 0);
|
||||
int i=0;
|
||||
int ch;
|
||||
while ((ch=getchar())!=EOF) buff[i++]=ch;
|
||||
hexdumpFrom(buff, i, adr);
|
||||
}
|
||||
#endif
|
7
components/tme/hexdump.h
Normal file
7
components/tme/hexdump.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#ifndef HEXDUMP_H
|
||||
#define HEXDUMP_H
|
||||
|
||||
void hexdump(void *mem, int len);
|
||||
void hexdumpFrom(void *mem, int len, int addrFrom);
|
||||
|
||||
#endif
|
18
components/tme/localtalk.c
Normal file
18
components/tme/localtalk.c
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "hexdump.h"
|
||||
#include "scc.h"
|
||||
|
||||
void localtalkSend(uint8_t *data, int len) {
|
||||
uint8_t resp[128];
|
||||
if (data[2]==0x81) {
|
||||
resp[0]=data[1];
|
||||
resp[1]=data[0];
|
||||
resp[2]=0x82;
|
||||
sccRecv(1, resp, 3);
|
||||
printf("LocalTalk: Sent ack\n");
|
||||
} else {
|
||||
printf("LocalTalk... errm... dunno what to do with this (cmd=%x).\n", data[2]);
|
||||
}
|
||||
}
|
7
components/tme/localtalk.h
Normal file
7
components/tme/localtalk.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#ifndef LOCALTALK_H
|
||||
#define LOCALTALK_H
|
||||
|
||||
void localtalkSend(uint8_t *data, int len);
|
||||
|
||||
|
||||
#endif
|
|
@ -19,6 +19,8 @@ void rtcTick() {
|
|||
}
|
||||
}
|
||||
|
||||
extern void saveRtcMem(char *mem);
|
||||
|
||||
int rtcCom(int en, int dat, int clk) {
|
||||
int ret=0;
|
||||
clk=clk?1:0;
|
||||
|
@ -35,7 +37,10 @@ int rtcCom(int en, int dat, int clk) {
|
|||
}
|
||||
ret=((rtc.cmd&(1<<(15-rtc.pos)))?1:0);
|
||||
} else if (rtc.pos==15) {
|
||||
if ((rtc.cmd&0x8000)==0) rtc.mem[(rtc.cmd&0x7C00)>>10]=rtc.cmd&0xff;
|
||||
if ((rtc.cmd&0x8000)==0) {
|
||||
rtc.mem[(rtc.cmd&0x7C00)>>10]=rtc.cmd&0xff;
|
||||
saveRtcMem(rtc.mem);
|
||||
}
|
||||
printf("RTC/PRAM CMD %x\n", rtc.cmd);
|
||||
}
|
||||
rtc.pos++;
|
||||
|
@ -45,3 +50,6 @@ int rtcCom(int en, int dat, int clk) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
void rtcInit(char *mem) {
|
||||
memcpy(rtc.mem, mem, 32);
|
||||
}
|
||||
|
|
|
@ -2,23 +2,40 @@
|
|||
#include <stdint.h>
|
||||
#include "scc.h"
|
||||
#include "m68k.h"
|
||||
#include "hexdump.h"
|
||||
#include "localtalk.h"
|
||||
|
||||
/*
|
||||
THis is an extremely minimal SCC implementation: it only somewhat implements the interrupt mechanism for the
|
||||
Emulation of the Zilog 8530 SCC.
|
||||
|
||||
This is an extremely minimal SCC implementation: it only somewhat implements the interrupt mechanism for the
|
||||
DCD pins because that is what is needed for the mouse to work.
|
||||
*/
|
||||
|
||||
|
||||
void sccIrq(int ena);
|
||||
|
||||
#define BUFLEN 8192
|
||||
|
||||
typedef struct {
|
||||
int dcd;
|
||||
int cts;
|
||||
int wr1;
|
||||
int sdlcaddr;
|
||||
int wr15;
|
||||
int hunting;
|
||||
int txTimer;
|
||||
uint8_t txData[BUFLEN];
|
||||
uint8_t rxData[BUFLEN];
|
||||
int txPos, rxPos, rxLen;
|
||||
int rxDelay;
|
||||
} SccChan;
|
||||
|
||||
typedef struct {
|
||||
int regptr;
|
||||
int intpending;
|
||||
int intpendingOld;
|
||||
int dcd[2];
|
||||
int cts[2];
|
||||
int wr1[2];
|
||||
int wr15[2];
|
||||
SccChan chan[2];
|
||||
} Scc;
|
||||
|
||||
static Scc scc;
|
||||
|
@ -40,8 +57,9 @@ static Scc scc;
|
|||
#define SCC_WR3_CHA_TX (1<<4)
|
||||
#define SCC_WR3_CHA_RX (1<<5)
|
||||
|
||||
|
||||
static void raiseInt(int chan) {
|
||||
if ((scc.wr1[chan]&1) && (scc.intpending&(~scc.intpendingOld))) {
|
||||
if ((scc.chan[chan].wr1&1) && (scc.intpending&(~scc.intpendingOld))) {
|
||||
scc.intpendingOld=scc.intpending;
|
||||
// printf("SCC int, pending %x\n", scc.intpending);
|
||||
sccIrq(1);
|
||||
|
@ -50,18 +68,59 @@ static void raiseInt(int chan) {
|
|||
|
||||
void sccSetDcd(int chan, int val) {
|
||||
val=val?1:0;
|
||||
if (scc.dcd[chan]!=val) {
|
||||
if (scc.chan[chan].dcd!=val) {
|
||||
if (chan==SCC_CHANA) {
|
||||
if (scc.chan[SCC_CHANA].wr15&SCC_WR15_DCD) {
|
||||
scc.intpending|=SCC_WR3_CHA_EXT;
|
||||
raiseInt(SCC_CHANA);
|
||||
}
|
||||
} else {
|
||||
if (scc.chan[SCC_CHANB].wr15&SCC_WR15_DCD) {
|
||||
scc.intpending|=SCC_WR3_CHB_EXT;
|
||||
raiseInt(SCC_CHANB);
|
||||
}
|
||||
}
|
||||
if ((scc.intpending&SCC_WR3_CHA_EXT) && (scc.wr15[SCC_CHANA]&SCC_WR15_DCD)) raiseInt(SCC_CHANA);
|
||||
if ((scc.intpending&SCC_WR3_CHB_EXT) && (scc.wr15[SCC_CHANB]&SCC_WR15_DCD)) raiseInt(SCC_CHANB);
|
||||
if ((scc.intpending&SCC_WR3_CHA_EXT) && (scc.wr15[SCC_CHANA]&SCC_WR15_CTS)) raiseInt(SCC_CHANA);
|
||||
if ((scc.intpending&SCC_WR3_CHB_EXT) && (scc.wr15[SCC_CHANB]&SCC_WR15_CTS)) raiseInt(SCC_CHANB);
|
||||
scc.dcd[chan]=val;
|
||||
}
|
||||
scc.chan[chan].dcd=val;
|
||||
}
|
||||
|
||||
void sccTxFinished(int chan) {
|
||||
hexdump(scc.chan[chan].txData, scc.chan[chan].txPos);
|
||||
localtalkSend(scc.chan[chan].txData, scc.chan[chan].txPos);
|
||||
scc.chan[chan].txPos=0;
|
||||
scc.chan[chan].hunting=1;
|
||||
}
|
||||
|
||||
void sccRecv(int chan, uint8_t *data, int len) {
|
||||
memcpy(scc.chan[chan].rxData, data, len);
|
||||
scc.chan[chan].rxData[len]=0xA5; //crc1
|
||||
scc.chan[chan].rxData[len+1]=0xA5; //crc2
|
||||
scc.chan[chan].rxData[len+2]=0; //abort
|
||||
scc.chan[chan].rxLen=len+3;
|
||||
scc.chan[chan].rxDelay=30;
|
||||
}
|
||||
|
||||
static void triggerRx(int chan) {
|
||||
if (!scc.chan[chan].hunting) return;
|
||||
printf("Receiving:\n");
|
||||
hexdump(scc.chan[chan].rxData, scc.chan[chan].rxLen);
|
||||
if (scc.chan[chan].rxData[0]==0xFF || scc.chan[chan].rxData[0]==scc.chan[chan].sdlcaddr) {
|
||||
scc.chan[chan].rxPos=0;
|
||||
//Sync int
|
||||
if (scc.chan[chan].wr15&SCC_WR15_SYNC) {
|
||||
scc.intpending|=(chan?SCC_WR3_CHA_EXT:SCC_WR3_CHB_EXT);
|
||||
raiseInt(chan);
|
||||
}
|
||||
//RxD int
|
||||
int rxintena=scc.chan[chan].wr1&0x18;
|
||||
if (rxintena==0x10 || rxintena==0x08) {
|
||||
scc.intpending|=(chan?SCC_WR3_CHA_RX:SCC_WR3_CHB_RX);
|
||||
raiseInt(chan);
|
||||
}
|
||||
scc.chan[chan].hunting=0;
|
||||
} else {
|
||||
scc.chan[chan].rxLen=0;
|
||||
}
|
||||
}
|
||||
|
||||
void sccWrite(unsigned int addr, unsigned int val) {
|
||||
|
@ -75,6 +134,7 @@ void sccWrite(unsigned int addr, unsigned int val) {
|
|||
reg=scc.regptr;
|
||||
scc.regptr=0;
|
||||
}
|
||||
|
||||
if (reg==0) {
|
||||
scc.regptr=val&0x7;
|
||||
if ((val&0x38)==0x8) scc.regptr|=8;
|
||||
|
@ -82,12 +142,31 @@ void sccWrite(unsigned int addr, unsigned int val) {
|
|||
scc.intpending=0;
|
||||
scc.intpendingOld=0;
|
||||
}
|
||||
} else if (reg==1) {
|
||||
scc.wr1[chan]=val;
|
||||
} else if (reg==15) {
|
||||
scc.wr15[chan]=val;
|
||||
if ((val&0x38)==0x18) {
|
||||
//SCC abort: parse whatever we sent
|
||||
printf("SCC ABORT: Sent data\n");
|
||||
sccTxFinished(chan);
|
||||
}
|
||||
// printf("SCC: write to addr %x chan %d reg %d val %x\n", addr, chan, reg, val);
|
||||
if ((val&0xc0)==0xC0) {
|
||||
//reset tx underrun latch
|
||||
if (scc.chan[chan].txTimer==0) scc.chan[chan].txTimer=-1;
|
||||
}
|
||||
} else if (reg==1) {
|
||||
scc.chan[chan].wr1=val;
|
||||
} else if (reg==3) {
|
||||
//bitsperchar1, bitsperchar0, autoenables, enterhuntmode, rxcrcen, addresssearch, synccharloadinh, rxena
|
||||
//autoenable: cts = tx ena, dcd = rx ena
|
||||
if (val&0x10) scc.chan[chan].hunting=1;
|
||||
} else if (reg==6) {
|
||||
scc.chan[chan].sdlcaddr=val;
|
||||
} else if (reg==8) {
|
||||
scc.chan[chan].txData[scc.chan[chan].txPos++]=val;
|
||||
printf("TX! Pos %d\n", scc.chan[chan].txPos);
|
||||
scc.chan[chan].txTimer+=30;
|
||||
} else if (reg==15) {
|
||||
scc.chan[chan].wr15=val;
|
||||
}
|
||||
printf("SCC: write to addr %x chan %d reg %d val %x\n", addr, chan, reg, val);
|
||||
}
|
||||
|
||||
|
||||
|
@ -103,11 +182,17 @@ unsigned int sccRead(unsigned int addr) {
|
|||
scc.regptr=0;
|
||||
}
|
||||
if (reg==0) {
|
||||
val=(1<<2);
|
||||
if (scc.dcd[chan]) val|=(1<<3);
|
||||
if (scc.cts[chan]) val|=(1<<5);
|
||||
val=(1<<2); //tx buffer always empty
|
||||
if (scc.chan[chan].rxLen && !scc.chan[chan].rxDelay) val|=(1<<0);
|
||||
if (scc.chan[chan].txTimer==0) val|=(1<<6);
|
||||
if (scc.chan[chan].dcd) val|=(1<<3);
|
||||
if (scc.chan[chan].cts) val|=(1<<5);
|
||||
if (scc.chan[chan].hunting) val|=(1<<4);
|
||||
if (scc.chan[chan].rxPos==scc.chan[chan].rxLen-1) val|=(1<<7); //abort
|
||||
} else if (reg==1) {
|
||||
val=scc.wr1[chan];
|
||||
//EndOfFrame, CRCErr, RXOverrun, ParityErr, Residue0, Residue1, Residue2, AllSent
|
||||
val=0x7; //residue code 011, all sent
|
||||
if (scc.chan[chan].rxPos==scc.chan[chan].rxLen-2) val|=(1<<7); //end of frame
|
||||
} else if (reg==2 && chan==SCC_CHANB) {
|
||||
//We assume this also does an intack.
|
||||
int rsn=0;
|
||||
|
@ -124,10 +209,60 @@ unsigned int sccRead(unsigned int addr) {
|
|||
if (scc.intpending&0x07) raiseInt(SCC_CHANB);
|
||||
} else if (reg==3) {
|
||||
if (chan==SCC_CHANA) val=scc.intpending; else val=0;
|
||||
} else if (reg==15) {
|
||||
val=scc.wr15[chan];
|
||||
} else if (reg==8) {
|
||||
//rx buffer
|
||||
if (scc.chan[chan].rxLen && !scc.chan[chan].rxDelay) {
|
||||
val=scc.chan[chan].rxData[scc.chan[chan].rxPos++];
|
||||
if (scc.chan[chan].rxPos==scc.chan[chan].rxLen) {
|
||||
scc.chan[chan].rxLen=0;
|
||||
} else {
|
||||
int rxintena=scc.chan[chan].wr1&0x18;
|
||||
if (rxintena==0x10) {
|
||||
scc.intpending|=(chan?SCC_WR3_CHA_RX:SCC_WR3_CHB_RX);
|
||||
raiseInt(chan);
|
||||
}
|
||||
// printf("SCC: read from chan %d reg %d val %x\n", chan, reg, val);
|
||||
}
|
||||
if (scc.chan[chan].rxPos==scc.chan[chan].rxLen-1) scc.chan[chan].hunting=1;
|
||||
if (scc.chan[chan].rxPos==scc.chan[chan].rxLen-1 && scc.chan[chan].wr15&SCC_WR15_BREAK) {
|
||||
scc.intpending|=(chan?SCC_WR3_CHA_EXT:SCC_WR3_CHB_EXT);
|
||||
raiseInt(chan);
|
||||
}
|
||||
} else {
|
||||
val=0;
|
||||
}
|
||||
} else if (reg==10) {
|
||||
//Misc status (mostly SDLC)
|
||||
val=0;
|
||||
} else if (reg==15) {
|
||||
val=scc.chan[chan].wr15;
|
||||
}
|
||||
printf("SCC: read from chan %d reg %d val %x\n", chan, reg, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
//Called at about 800KHz
|
||||
void sccTick() {
|
||||
for (int n=0; n<2; n++) {
|
||||
if (scc.chan[n].txTimer>0) {
|
||||
scc.chan[n].txTimer--;
|
||||
if (scc.chan[n].txTimer==0) {
|
||||
printf("Tx buffer empty: Sent data\n");
|
||||
sccTxFinished(n);
|
||||
}
|
||||
}
|
||||
if (scc.chan[n].rxDelay!=0) {
|
||||
scc.chan[n].rxDelay--;
|
||||
if (scc.chan[n].rxDelay==0) {
|
||||
triggerRx(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sccInit() {
|
||||
sccSetDcd(1, 1);
|
||||
sccSetDcd(2, 1);
|
||||
scc.chan[0].txTimer=-1;
|
||||
scc.chan[1].txTimer=-1;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,4 +5,7 @@
|
|||
void sccWrite(unsigned int addr, unsigned int val);
|
||||
unsigned int sccRead(unsigned int addr);
|
||||
void sccSetDcd(int chan, int val);
|
||||
void sccInit();
|
||||
void sccTick();
|
||||
void sccRecv(int chan, uint8_t *data, int len);
|
||||
|
||||
|
|
|
@ -21,7 +21,22 @@ static void *loadRom(char *file) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
void saveRtcMem(char *data) {
|
||||
FILE *f=fopen("pram.dat", "wb");
|
||||
if (f!=NULL) {
|
||||
fwrite(data, 32, 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
void *rom=loadRom("rom.bin");
|
||||
FILE *f=fopen("pram.dat", "r");
|
||||
if (f!=NULL) {
|
||||
char data[32];
|
||||
fread(data, 32, 1, f);
|
||||
rtcInit(data);
|
||||
fclose(f);
|
||||
}
|
||||
tmeStartEmu(rom);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user