mirror of
https://github.com/Spritetm/minimacplus.git
synced 2024-11-24 23:32:22 +00:00
IT BOOTS!!!! Well, os6 images, anyway.
This commit is contained in:
parent
cec9a2763d
commit
7732b2b049
46
emu.c
46
emu.c
@ -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
6
hd.c
@ -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);
|
||||
}
|
||||
|
@ -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
60
ncr.c
@ -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
4
ncr.h
@ -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
7
via.c
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user