IT BOOTS!!!! Well, os6 images, anyway.

This commit is contained in:
Jeroen Domburg 2017-03-07 00:06:22 +08:00
parent cec9a2763d
commit 7732b2b049
6 changed files with 84 additions and 45 deletions

46
emu.c
View File

@ -20,6 +20,24 @@ unsigned char *macRam;
int rom_remap, video_remap=0, audio_remap=0; int rom_remap, video_remap=0, audio_remap=0;
void m68k_instruction() {
unsigned int pc=m68k_get_reg(NULL, M68K_REG_PC);
int ok=0;
if (pc < 0x400000) {
if (rom_remap) {
ok=1;
}
} else if (pc >= 0x400000 && pc<0x500000) {
ok=1;
}
if (!ok) return;
pc&=0x1FFFF;
if (pc==0x7DCC) printf("Mon: SCSIReadSectors\n");
if (pc==0x7E4C) printf("Mon: SCSIReadSectors exit OK\n");
if (pc==0x7E56) printf("Mon: SCSIReadSectors exit FAIL\n");
}
unsigned int m68k_read_memory_8(unsigned int address) { unsigned int m68k_read_memory_8(unsigned int address) {
unsigned int ret; unsigned int ret;
unsigned int pc=m68k_get_reg(NULL, M68K_REG_PC); unsigned int pc=m68k_get_reg(NULL, M68K_REG_PC);
@ -35,6 +53,7 @@ unsigned int m68k_read_memory_8(unsigned int address) {
int romAdr=address-0x400000; int romAdr=address-0x400000;
if (romAdr>=TME_ROMSIZE) { if (romAdr>=TME_ROMSIZE) {
printf("PC %x:Huh? Read from ROM mirror (%x)\n", pc, address); printf("PC %x:Huh? Read from ROM mirror (%x)\n", pc, address);
ret=(address>>12); // ROM checks for same contents at 20000 and 40000 to determine if SCSI is present
} else { } else {
ret=macRom[romAdr&(TME_ROMSIZE-1)]; ret=macRom[romAdr&(TME_ROMSIZE-1)];
} }
@ -43,7 +62,7 @@ unsigned int m68k_read_memory_8(unsigned int address) {
} else if (address >= 0xc00000 && address < 0xe00000) { } else if (address >= 0xc00000 && address < 0xe00000) {
ret=iwmRead((address>>9)&0xf); ret=iwmRead((address>>9)&0xf);
} else if (address >= 0x580000 && address < 0x600000) { } else if (address >= 0x580000 && address < 0x600000) {
ret=ncrRead((address>>4)&0x7, (address>>7)&1); ret=ncrRead((address>>4)&0x7, (address>>9)&1);
} else { } else {
printf("PC %x: Read from %x\n", pc, address); printf("PC %x: Read from %x\n", pc, address);
ret=0xff; ret=0xff;
@ -54,8 +73,8 @@ unsigned int m68k_read_memory_8(unsigned int address) {
void m68k_write_memory_8(unsigned int address, unsigned int value) { void m68k_write_memory_8(unsigned int address, unsigned int value) {
unsigned int pc=m68k_get_reg(NULL, M68K_REG_PC); unsigned int pc=m68k_get_reg(NULL, M68K_REG_PC);
if (address < 0x400000 && !rom_remap) { if (address < 0x400000) {
macRam[address & (TME_RAMSIZE-1)]=value; if (!rom_remap) macRam[address & (TME_RAMSIZE-1)]=value;
} else if (address >= 0x600000 && address < 0xA00000) { } else if (address >= 0x600000 && address < 0xA00000) {
macRam[(address-0x600000) & (TME_RAMSIZE-1)]=value; macRam[(address-0x600000) & (TME_RAMSIZE-1)]=value;
} else if (address >= 0xE80000 && address < 0xf00000) { } else if (address >= 0xE80000 && address < 0xf00000) {
@ -63,7 +82,7 @@ void m68k_write_memory_8(unsigned int address, unsigned int value) {
} else if (address >= 0xc00000 && address < 0xe00000) { } else if (address >= 0xc00000 && address < 0xe00000) {
iwmWrite((address>>9)&0xf, value); iwmWrite((address>>9)&0xf, value);
} else if (address >= 0x580000 && address < 0x600000) { } else if (address >= 0x580000 && address < 0x600000) {
ncrWrite((address>>4)&0x7, (address>>7)&1, value); ncrWrite((address>>4)&0x7, (address>>9)&1, value);
} else { } else {
printf("PC %x: Write to %x: %x\n", pc, address, value); printf("PC %x: Write to %x: %x\n", pc, address, value);
} }
@ -83,27 +102,28 @@ void printFps() {
oldtv.tv_usec=tv.tv_usec; oldtv.tv_usec=tv.tv_usec;
} }
#define GRAN 100
void tmeStartEmu(void *rom) { void tmeStartEmu(void *rom) {
int ca1=0, ca2=0; int ca1=0, ca2=0;
int x, frame=0; int x, frame=0;
macRom=rom; macRom=rom;
macRam=malloc(TME_RAMSIZE); macRam=malloc(TME_RAMSIZE);
for (int x=0; x<TME_RAMSIZE; x++) macRam[x]=0xaa; for (int x=0; x<TME_RAMSIZE; x++) macRam[x]=0;
rom_remap=1; rom_remap=1;
SCSIDevice *hd=hdCreate("hd.img"); SCSIDevice *hd=hdCreate("hd.img");
ncrRegisterDevice(6, hd); ncrRegisterDevice(6, hd);
viaClear(VIA_PORTA, 0x7F); viaClear(VIA_PORTA, 0x7F);
viaSet(VIA_PORTA, 0x80); viaSet(VIA_PORTA, 0x80);
viaClear(VIA_PORTA, 0xFF);
viaSet(VIA_PORTB, (1<<3));
m68k_init(); m68k_init();
m68k_set_cpu_type(M68K_CPU_TYPE_68000); m68k_set_cpu_type(M68K_CPU_TYPE_68000);
m68k_pulse_reset(); m68k_pulse_reset();
dispInit(); dispInit();
while(1) { while(1) {
for (x=0; x<8000000/60; x+=GRAN) { for (x=0; x<8000000/60; x+=10) {
m68k_execute(GRAN); m68k_execute(10);
viaStep(GRAN); viaStep(1); //should run at 783.36KHz
} }
dispDraw(&macRam[video_remap?TME_SCREENBUF_ALT:TME_SCREENBUF]); dispDraw(&macRam[video_remap?TME_SCREENBUF_ALT:TME_SCREENBUF]);
frame++; frame++;
@ -150,16 +170,12 @@ void m68k_write_memory_16(unsigned int address, unsigned int value) {
m68k_write_memory_8(address+1, value&0xff); m68k_write_memory_8(address+1, value&0xff);
} }
void m68k_int_ack(int irq) {
//Mac has level interrupts; no ack. Fake by raising the irq as soon as
//it's serviced.
m68k_set_irq(irq);
}
void viaCbPortAWrite(unsigned int val) { void viaCbPortAWrite(unsigned int val) {
int oldRomRemap=rom_remap;
video_remap=(val&(1<<6))?1:0; video_remap=(val&(1<<6))?1:0;
rom_remap=(val&(1<<4))?1:0; rom_remap=(val&(1<<4))?1:0;
audio_remap=(val&(1<<3))?1:0; audio_remap=(val&(1<<3))?1:0;
if (oldRomRemap!=rom_remap) printf("ROM REMAP %d\n", rom_remap);
} }
void viaCbPortBWrite(unsigned int val) { void viaCbPortBWrite(unsigned int val) {

6
hd.c
View File

@ -26,14 +26,15 @@ const uint8_t inq_resp[95]={
static int hdScsiCmd(SCSITransferData *data, unsigned int cmd, unsigned int len, unsigned int lba, void *arg) { static int hdScsiCmd(SCSITransferData *data, unsigned int cmd, unsigned int len, unsigned int lba, void *arg) {
int ret=0; int ret=0;
HdPriv *hd=(HdPriv*)arg; HdPriv *hd=(HdPriv*)arg;
for (int x=0; x<32; x++) printf("%02X ", data->cmd[x]); // for (int x=0; x<32; x++) printf("%02X ", data->cmd[x]);
printf("\n"); // printf("\n");
if (cmd==0x8 || cmd==0x28) { //read if (cmd==0x8 || cmd==0x28) { //read
fseek(hd->f, lba*512, SEEK_SET); fseek(hd->f, lba*512, SEEK_SET);
fread(data->data, 512, len, hd->f); fread(data->data, 512, len, hd->f);
printf("HD: Read %d bytes.\n", len*512); printf("HD: Read %d bytes.\n", len*512);
ret=len*512; ret=len*512;
} else if (cmd==0x12) { //inquiry } else if (cmd==0x12) { //inquiry
printf("HD: Inquery\n");
memcpy(data->data, inq_resp, sizeof(inq_resp)); memcpy(data->data, inq_resp, sizeof(inq_resp));
return 95; return 95;
} else if (cmd==0x25) { //read capacity } else if (cmd==0x25) { //read capacity
@ -47,6 +48,7 @@ static int hdScsiCmd(SCSITransferData *data, unsigned int cmd, unsigned int len,
data->data[6]=2; //512 data->data[6]=2; //512
data->data[7]=0; data->data[7]=0;
ret=8; ret=8;
printf("HD: Read capacity (%d)\n", lbacnt);
} else { } else {
printf("********** hdScsiCmd: unrecognized command %x\n", cmd); printf("********** hdScsiCmd: unrecognized command %x\n", cmd);
} }

View File

@ -87,7 +87,7 @@
* If off, all interrupts will be autovectored and all interrupt requests will * If off, all interrupts will be autovectored and all interrupt requests will
* auto-clear when the interrupt is serviced. * auto-clear when the interrupt is serviced.
*/ */
#define M68K_EMULATE_INT_ACK OPT_ON #define M68K_EMULATE_INT_ACK OPT_OFF
#define M68K_INT_ACK_CALLBACK(A) m68k_int_ack(A) #define M68K_INT_ACK_CALLBACK(A) m68k_int_ack(A)
@ -131,8 +131,8 @@
/* If ON, CPU will call the instruction hook callback before every /* If ON, CPU will call the instruction hook callback before every
* instruction. * instruction.
*/ */
#define M68K_INSTRUCTION_HOOK OPT_OFF #define M68K_INSTRUCTION_HOOK OPT_SPECIFY_HANDLER
#define M68K_INSTRUCTION_CALLBACK() your_instruction_hook_function() #define M68K_INSTRUCTION_CALLBACK() m68k_instruction()
/* If ON, the CPU will emulate the 4-byte prefetch queue of a real 68000 */ /* If ON, the CPU will emulate the 4-byte prefetch queue of a real 68000 */

60
ncr.c
View File

@ -91,19 +91,25 @@ static void parseScsiCmd(int isRead) {
uint8_t *buf=ncr.data.cmd; uint8_t *buf=ncr.data.cmd;
int cmd=buf[0]; int cmd=buf[0];
int lba, len, ctrl; int lba, len, ctrl;
if (cmd<0x20) { int group=(cmd>>5);
if (group==0) { //6-byte command
lba=buf[3]|(buf[2]<<8)|((buf[1]&0x1F)<<16); lba=buf[3]|(buf[2]<<8)|((buf[1]&0x1F)<<16);
len=buf[4]; len=buf[4];
if (len==0) len=256;
ctrl=buf[5]; ctrl=buf[5];
} else if (cmd<0x60) { for (int x=0; x<6; x++) printf("%02X ", buf[x]);
printf("\n");
} else if (group==1 || group==2) { //10-byte command
lba=buf[5]|(buf[4]<<8)|(buf[3]<<16)|(buf[2]<<24); lba=buf[5]|(buf[4]<<8)|(buf[3]<<16)|(buf[2]<<24);
len=buf[8]|(buf[7]<<8); len=buf[8]|(buf[7]<<8);
ctrl=buf[9]; ctrl=buf[9];
for (int x=0; x<10; x++) printf("%02X ", buf[x]);
printf("\n");
} else { } else {
printf("SCSI: UNSUPPORTED CMD %x\n", cmd); printf("SCSI: UNSUPPORTED CMD %x\n", cmd);
return; return;
} }
printf("SCSI: CMD %x LBA %x LEN %x CTRL %x\n", cmd, lba, len, ctrl); // printf("SCSI: CMD %x LBA %x LEN %x CTRL %x\n", cmd, lba, len, ctrl);
if (ncr.dev[ncr.selected]) { if (ncr.dev[ncr.selected]) {
ncr.datalen=ncr.dev[ncr.selected]->scsiCmd(&ncr.data, cmd, len, lba, ncr.dev[ncr.selected]->arg); ncr.datalen=ncr.dev[ncr.selected]->scsiCmd(&ncr.data, cmd, len, lba, ncr.dev[ncr.selected]->arg);
} }
@ -112,21 +118,22 @@ static void parseScsiCmd(int isRead) {
unsigned int ncrRead(unsigned int addr, unsigned int dack) { unsigned int ncrRead(unsigned int addr, unsigned int dack) {
unsigned int pc=m68k_get_reg(NULL, M68K_REG_PC); unsigned int pc=m68k_get_reg(NULL, M68K_REG_PC);
unsigned int ret=0; unsigned int ret=0;
if (addr==0) { if (ncr.mode&MODE_DMA && dack) {
if (ncr.mode&MODE_DMA) { if (ncr.tcr&TCR_IO) {
if (ncr.tcr&TCR_IO) { if (ncr.bufpos!=ncr.bufmax) ncr.din=ncr.buf[ncr.bufpos++];
if (ncr.bufpos!=ncr.bufmax) ncr.din=ncr.buf[ncr.bufpos++]; // printf("Send next byte dma %d/%d\n", ncr.bufpos, ncr.datalen);
// printf("Send next byte dma %d/%d\n", ncr.bufpos, ncr.datalen);
}
} }
}
if (addr==0) {
ret=ncr.din; ret=ncr.din;
// printf("READ BYTE %02X dack=%d\n", ret, dack);
} else if (addr==1) { } else if (addr==1) {
// /rst s s /ack /bsy /sel /atn databus // /rst s s /ack /bsy /sel /atn databus
ret=ncr.inicmd; ret=ncr.inicmd;
if (ncr.state==ST_ARB) { if (ncr.state==ST_ARB) {
ret|=INIR_AIP; ret|=INIR_AIP;
//We don't have a timer... just set arb to be done right now. //We don't have a timer... just set arb to be done right now.
ncr.state=ST_ARBDONE; if (ncr.dev[ncr.selected]) ncr.state=ST_ARBDONE;
} }
} else if (addr==2) { } else if (addr==2) {
ret=ncr.mode; ret=ncr.mode;
@ -136,8 +143,11 @@ unsigned int ncrRead(unsigned int addr, unsigned int dack) {
ret=0; ret=0;
if (ncr.inicmd&INI_RST) ret|=SSR_RST; if (ncr.inicmd&INI_RST) ret|=SSR_RST;
if (ncr.inicmd&INI_BSY) ret|=SSR_BSY; if (ncr.inicmd&INI_BSY) ret|=SSR_BSY;
if (ncr.inicmd&INI_SEL) ret|=SSR_SEL; // if (ncr.inicmd&INI_SEL) ret|=SSR_SEL;
if (ncr.dev[ncr.selected] && (ncr.state==ST_SELDONE || ncr.state==ST_DATA)) { if (ncr.tcr&TCR_IO) ret|=SSR_IO;
if (ncr.tcr&TCR_CD) ret|=SSR_CD;
if (ncr.tcr&TCR_MSG) ret|=SSR_MSG;
if (ncr.dev[ncr.selected] && (ncr.state==ST_SELDONE)) {
// ret|=SSR_REQ; // ret|=SSR_REQ;
ret|=SSR_BSY; ret|=SSR_BSY;
} }
@ -146,22 +156,24 @@ unsigned int ncrRead(unsigned int addr, unsigned int dack) {
ret|=SSR_REQ; ret|=SSR_REQ;
} }
} }
if (ncr.state==ST_ARB) return 0x40;
} else if (addr==5) { } else if (addr==5) {
ret=BSR_PHASEMATCH; ret=BSR_PHASEMATCH;
if (ncr.mode&MODE_DMA) { if (ncr.mode&MODE_DMA) {
ret|=BSR_DMARQ; ret|=BSR_DMARQ;
if (ncr.bufpos<ncr.datalen) { if (ncr.bufpos>=ncr.datalen) {
} else {
printf("End of DMA reached: bufpos %d datalen %d\n", ncr.bufpos, ncr.datalen); printf("End of DMA reached: bufpos %d datalen %d\n", ncr.bufpos, ncr.datalen);
ret|=BSR_EODMA; ret|=BSR_EODMA;
} }
} }
} else if (addr==6) { } else if (addr==6) {
ret=ncr.din; ret=ncr.din;
// printf("READ BYTE (NCR addr6) %02X dack=%d\n", ret, dack);
} else if (addr==7) { } else if (addr==7) {
printf("!UNIMPLEMENTED!\n"); printf("!UNIMPLEMENTED!\n");
} }
// printf("%08X SCSI: read %d (%s) val %x (dack %d), cur st %s\n", pc, addr, regNamesR[addr], ret, dack, stateNames[ncr.state]); // printf("%08X SCSI: (dack %d), cur st %s read %s (reg %d) = %x \n",
// pc, dack, stateNames[ncr.state], regNamesR[addr], addr, ret);
return ret; return ret;
} }
@ -169,16 +181,20 @@ unsigned int ncrRead(unsigned int addr, unsigned int dack) {
void ncrWrite(unsigned int addr, unsigned int dack, unsigned int val) { void ncrWrite(unsigned int addr, unsigned int dack, unsigned int val) {
unsigned int pc=m68k_get_reg(NULL, M68K_REG_PC); unsigned int pc=m68k_get_reg(NULL, M68K_REG_PC);
if (addr==0) { if (addr==0) {
if (ncr.mode&MODE_DMA && dack) {
printf("UNSUPPORTED: dma write\n");
}
ncr.dout=val; ncr.dout=val;
ncr.din=val;
} else if (addr==1) { } else if (addr==1) {
if ((val&INI_SEL) && (val&INI_DBUS) && (val&INI_BSY) && ncr.state==ST_ARBDONE) { if ((val&INI_SEL) && (val&INI_DBUS) && (val&INI_BSY) && (ncr.state==ST_ARBDONE || ncr.state==ST_ARB)) {
ncr.state=ST_SELECT; ncr.state=ST_SELECT;
if (ncr.dout==0x81) ncr.selected=0; if (ncr.dout==0x81) ncr.selected=0;
if (ncr.dout==0x82) ncr.selected=1; if (ncr.dout==0x82) ncr.selected=1;
if (ncr.dout==0x84) ncr.selected=2; if (ncr.dout==0x84) ncr.selected=2;
if (ncr.dout==0x88) ncr.selected=3; if (ncr.dout==0x88) ncr.selected=3;
if (ncr.dout==0x80) ncr.selected=4; if (ncr.dout==0x90) ncr.selected=4;
if (ncr.dout==0x90) ncr.selected=5; if (ncr.dout==0xA0) ncr.selected=5;
if (ncr.dout==0xC0) ncr.selected=6; if (ncr.dout==0xC0) ncr.selected=6;
printf("Selected dev: %d (val %x)\n", ncr.selected, ncr.dout); printf("Selected dev: %d (val %x)\n", ncr.selected, ncr.dout);
} }
@ -212,6 +228,7 @@ void ncrWrite(unsigned int addr, unsigned int dack, unsigned int val) {
ncr.inicmd|=val&0x9f; ncr.inicmd|=val&0x9f;
} else if (addr==2) { } else if (addr==2) {
ncr.mode=val; ncr.mode=val;
if (((val&1)==0) && ncr.state==ST_ARB) ncr.state=ST_IDLE;
if (val&1) ncr.state=ST_ARB; if (val&1) ncr.state=ST_ARB;
} else if (addr==3) { } else if (addr==3) {
if (ncr.tcr!=(val&0xf)) { if (ncr.tcr!=(val&0xf)) {
@ -224,6 +241,9 @@ void ncrWrite(unsigned int addr, unsigned int dack, unsigned int val) {
//Start of data in phase //Start of data in phase
parseScsiCmd(0); parseScsiCmd(0);
} }
if ((ncr.tcr&0x7)==TCR_IO) {
printf("Data Out finished: Host read %d/%d bytes.\n", ncr.bufpos, ncr.datalen);
}
ncr.bufpos=0; ncr.bufpos=0;
int type=val&(TCR_MSG|TCR_CD); int type=val&(TCR_MSG|TCR_CD);
if (type==0) { if (type==0) {
@ -245,7 +265,7 @@ void ncrWrite(unsigned int addr, unsigned int dack, unsigned int val) {
} }
ncr.tcr=val&0xf; ncr.tcr=val&0xf;
} else if (addr==4) { } else if (addr==4) {
printf("!UNIMPLEMENTED! selenable, todo\n"); if (val!=0) printf("!UNIMPLEMENTED! selenable (val %x), todo\n", val);
} else if (addr==5) { } else if (addr==5) {
printf("!UNIMPLEMENTED!\n"); printf("!UNIMPLEMENTED!\n");
} else if (addr==6) { } else if (addr==6) {
@ -253,7 +273,7 @@ void ncrWrite(unsigned int addr, unsigned int dack, unsigned int val) {
} else if (addr==7) { } else if (addr==7) {
//Start DMA. We already do this using the mode bit. //Start DMA. We already do this using the mode bit.
} }
// printf("%08X SCSI: write %d (%s) val %x (dack %d), cur state %s\n", pc, addr, regNamesW[addr], val, dack, stateNames[ncr.state]); printf("%08X SCSI: (dack %d), cur state %s %02x to %s (reg %d)\n", pc, dack, stateNames[ncr.state], val, regNamesW[addr], addr);
} }
void ncrRegisterDevice(int id, SCSIDevice* dev){ void ncrRegisterDevice(int id, SCSIDevice* dev){

4
ncr.h
View File

@ -3,9 +3,9 @@
#include <stdint.h> #include <stdint.h>
typedef struct { typedef struct {
uint8_t cmd[128]; uint8_t cmd[256];
uint8_t data[1024*1024]; uint8_t data[1024*1024];
uint8_t msg[2]; uint8_t msg[128];
int cmdlen; int cmdlen;
int datalen; int datalen;
int msglen; int msglen;

7
via.c
View File

@ -55,13 +55,14 @@ void viaClear(int no, int mask) {
void viaStep(int clockcycles) { void viaStep(int clockcycles) {
while(clockcycles--) { while(clockcycles--) {
if ((via.timer2!=0) || (via.acr&(1<<6))) via.timer2--; if (via.timer1==1) {
if (via.timer1==0) {
via.ifr|=IFR_T1; via.ifr|=IFR_T1;
via.timer1=via.latch1; via.timer1=via.latch1;
} }
if ((via.timer2!=0) || (via.acr&(1<<5))) via.timer2--; if ((via.timer1!=0) || (via.acr&(1<<6))) via.timer1--;
via.timer2--;
if (via.timer2==0) { if (via.timer2==0) {
//Actually shouldn't be set when timer2 gets 0 a 2nd time... ahwell.
via.ifr|=IFR_T2; via.ifr|=IFR_T2;
} }
} }