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;
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 ret;
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;
if (romAdr>=TME_ROMSIZE) {
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 {
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) {
ret=iwmRead((address>>9)&0xf);
} else if (address >= 0x580000 && address < 0x600000) {
ret=ncrRead((address>>4)&0x7, (address>>7)&1);
ret=ncrRead((address>>4)&0x7, (address>>9)&1);
} else {
printf("PC %x: Read from %x\n", pc, address);
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) {
unsigned int pc=m68k_get_reg(NULL, M68K_REG_PC);
if (address < 0x400000 && !rom_remap) {
macRam[address & (TME_RAMSIZE-1)]=value;
if (address < 0x400000) {
if (!rom_remap) macRam[address & (TME_RAMSIZE-1)]=value;
} else if (address >= 0x600000 && address < 0xA00000) {
macRam[(address-0x600000) & (TME_RAMSIZE-1)]=value;
} 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) {
iwmWrite((address>>9)&0xf, value);
} else if (address >= 0x580000 && address < 0x600000) {
ncrWrite((address>>4)&0x7, (address>>7)&1, value);
ncrWrite((address>>4)&0x7, (address>>9)&1, value);
} else {
printf("PC %x: Write to %x: %x\n", pc, address, value);
}
@ -83,27 +102,28 @@ void printFps() {
oldtv.tv_usec=tv.tv_usec;
}
#define GRAN 100
void tmeStartEmu(void *rom) {
int ca1=0, ca2=0;
int x, frame=0;
macRom=rom;
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;
SCSIDevice *hd=hdCreate("hd.img");
ncrRegisterDevice(6, hd);
viaClear(VIA_PORTA, 0x7F);
viaSet(VIA_PORTA, 0x80);
viaClear(VIA_PORTA, 0xFF);
viaSet(VIA_PORTB, (1<<3));
m68k_init();
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
m68k_pulse_reset();
dispInit();
while(1) {
for (x=0; x<8000000/60; x+=GRAN) {
m68k_execute(GRAN);
viaStep(GRAN);
for (x=0; x<8000000/60; x+=10) {
m68k_execute(10);
viaStep(1); //should run at 783.36KHz
}
dispDraw(&macRam[video_remap?TME_SCREENBUF_ALT:TME_SCREENBUF]);
frame++;
@ -150,16 +170,12 @@ void m68k_write_memory_16(unsigned int address, unsigned int value) {
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) {
int oldRomRemap=rom_remap;
video_remap=(val&(1<<6))?1:0;
rom_remap=(val&(1<<4))?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) {

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) {
int ret=0;
HdPriv *hd=(HdPriv*)arg;
for (int x=0; x<32; x++) printf("%02X ", data->cmd[x]);
printf("\n");
// for (int x=0; x<32; x++) printf("%02X ", data->cmd[x]);
// printf("\n");
if (cmd==0x8 || cmd==0x28) { //read
fseek(hd->f, lba*512, SEEK_SET);
fread(data->data, 512, len, hd->f);
printf("HD: Read %d bytes.\n", len*512);
ret=len*512;
} else if (cmd==0x12) { //inquiry
printf("HD: Inquery\n");
memcpy(data->data, inq_resp, sizeof(inq_resp));
return 95;
} 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[7]=0;
ret=8;
printf("HD: Read capacity (%d)\n", lbacnt);
} else {
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
* 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)
@ -131,8 +131,8 @@
/* If ON, CPU will call the instruction hook callback before every
* instruction.
*/
#define M68K_INSTRUCTION_HOOK OPT_OFF
#define M68K_INSTRUCTION_CALLBACK() your_instruction_hook_function()
#define M68K_INSTRUCTION_HOOK OPT_SPECIFY_HANDLER
#define M68K_INSTRUCTION_CALLBACK() m68k_instruction()
/* 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;
int cmd=buf[0];
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);
len=buf[4];
if (len==0) len=256;
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);
len=buf[8]|(buf[7]<<8);
ctrl=buf[9];
for (int x=0; x<10; x++) printf("%02X ", buf[x]);
printf("\n");
} else {
printf("SCSI: UNSUPPORTED CMD %x\n", cmd);
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]) {
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 pc=m68k_get_reg(NULL, M68K_REG_PC);
unsigned int ret=0;
if (addr==0) {
if (ncr.mode&MODE_DMA) {
if (ncr.tcr&TCR_IO) {
if (ncr.bufpos!=ncr.bufmax) ncr.din=ncr.buf[ncr.bufpos++];
// printf("Send next byte dma %d/%d\n", ncr.bufpos, ncr.datalen);
}
if (ncr.mode&MODE_DMA && dack) {
if (ncr.tcr&TCR_IO) {
if (ncr.bufpos!=ncr.bufmax) ncr.din=ncr.buf[ncr.bufpos++];
// printf("Send next byte dma %d/%d\n", ncr.bufpos, ncr.datalen);
}
}
if (addr==0) {
ret=ncr.din;
// printf("READ BYTE %02X dack=%d\n", ret, dack);
} else if (addr==1) {
// /rst s s /ack /bsy /sel /atn databus
ret=ncr.inicmd;
if (ncr.state==ST_ARB) {
ret|=INIR_AIP;
//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) {
ret=ncr.mode;
@ -136,8 +143,11 @@ unsigned int ncrRead(unsigned int addr, unsigned int dack) {
ret=0;
if (ncr.inicmd&INI_RST) ret|=SSR_RST;
if (ncr.inicmd&INI_BSY) ret|=SSR_BSY;
if (ncr.inicmd&INI_SEL) ret|=SSR_SEL;
if (ncr.dev[ncr.selected] && (ncr.state==ST_SELDONE || ncr.state==ST_DATA)) {
// if (ncr.inicmd&INI_SEL) ret|=SSR_SEL;
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_BSY;
}
@ -146,22 +156,24 @@ unsigned int ncrRead(unsigned int addr, unsigned int dack) {
ret|=SSR_REQ;
}
}
if (ncr.state==ST_ARB) return 0x40;
} else if (addr==5) {
ret=BSR_PHASEMATCH;
if (ncr.mode&MODE_DMA) {
ret|=BSR_DMARQ;
if (ncr.bufpos<ncr.datalen) {
} else {
if (ncr.bufpos>=ncr.datalen) {
printf("End of DMA reached: bufpos %d datalen %d\n", ncr.bufpos, ncr.datalen);
ret|=BSR_EODMA;
}
}
} else if (addr==6) {
ret=ncr.din;
// printf("READ BYTE (NCR addr6) %02X dack=%d\n", ret, dack);
} else if (addr==7) {
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;
}
@ -169,16 +181,20 @@ unsigned int ncrRead(unsigned int addr, unsigned int dack) {
void ncrWrite(unsigned int addr, unsigned int dack, unsigned int val) {
unsigned int pc=m68k_get_reg(NULL, M68K_REG_PC);
if (addr==0) {
if (ncr.mode&MODE_DMA && dack) {
printf("UNSUPPORTED: dma write\n");
}
ncr.dout=val;
ncr.din=val;
} 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;
if (ncr.dout==0x81) ncr.selected=0;
if (ncr.dout==0x82) ncr.selected=1;
if (ncr.dout==0x84) ncr.selected=2;
if (ncr.dout==0x88) ncr.selected=3;
if (ncr.dout==0x80) ncr.selected=4;
if (ncr.dout==0x90) ncr.selected=5;
if (ncr.dout==0x90) ncr.selected=4;
if (ncr.dout==0xA0) ncr.selected=5;
if (ncr.dout==0xC0) ncr.selected=6;
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;
} else if (addr==2) {
ncr.mode=val;
if (((val&1)==0) && ncr.state==ST_ARB) ncr.state=ST_IDLE;
if (val&1) ncr.state=ST_ARB;
} else if (addr==3) {
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
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;
int type=val&(TCR_MSG|TCR_CD);
if (type==0) {
@ -245,7 +265,7 @@ void ncrWrite(unsigned int addr, unsigned int dack, unsigned int val) {
}
ncr.tcr=val&0xf;
} else if (addr==4) {
printf("!UNIMPLEMENTED! selenable, todo\n");
if (val!=0) printf("!UNIMPLEMENTED! selenable (val %x), todo\n", val);
} else if (addr==5) {
printf("!UNIMPLEMENTED!\n");
} else if (addr==6) {
@ -253,7 +273,7 @@ void ncrWrite(unsigned int addr, unsigned int dack, unsigned int val) {
} else if (addr==7) {
//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){

4
ncr.h
View File

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

7
via.c
View File

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