mirror of
https://github.com/Spritetm/minimacplus.git
synced 2024-11-18 15:05:13 +00:00
Add rtc; fix via int (hackily). We have got a no disk error now!
This commit is contained in:
parent
5e88ad2df0
commit
460baa1a7b
4
Makefile
4
Makefile
@ -1,8 +1,8 @@
|
||||
TARGET:=tme
|
||||
MUSASHI_GEN_SRC:=musashi/m68kops.c musashi/m68kopac.c musashi/m68kopdm.c musashi/m68kopnz.c
|
||||
OBJ:=$(MUSASHI_GEN_SRC:%.x=%.o) musashi/m68kcpu.o main.o emu.o disp.o iwm.o via.o
|
||||
OBJ:=$(MUSASHI_GEN_SRC:%.x=%.o) musashi/m68kcpu.o main.o emu.o disp.o iwm.o via.o rtc.o
|
||||
#musashi/m68kdasm.o
|
||||
CFLAGS=-Wall -I. -I./musashi -ggdb `sdl2-config --cflags`
|
||||
CFLAGS=-Wall -I. -I./musashi -Og -ggdb `sdl2-config --cflags`
|
||||
LDFLAGS=`sdl2-config --libs`
|
||||
|
||||
$(TARGET): $(OBJ)
|
||||
|
55
emu.c
55
emu.c
@ -5,11 +5,13 @@
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include "config.h"
|
||||
#include "m68k.h"
|
||||
#include "disp.h"
|
||||
#include "iwm.h"
|
||||
#include "via.h"
|
||||
#include "rtc.h"
|
||||
|
||||
unsigned char *macRom;
|
||||
unsigned char *macRam;
|
||||
@ -33,7 +35,7 @@ unsigned int m68k_read_memory_8(unsigned int address) {
|
||||
ret=macRom[romAdr&(TME_ROMSIZE-1)];
|
||||
// rom_remap=0; //HACK
|
||||
} else if (address >= 0xE80000 && address < 0xf00000) {
|
||||
ret=viaRead((address>>8)&0xf);
|
||||
ret=viaRead((address>>9)&0xf);
|
||||
} else if (address >= 0xc00000 && address < 0xe00000) {
|
||||
ret=iwmRead((address>>9)&0xf);
|
||||
} else {
|
||||
@ -51,7 +53,7 @@ void m68k_write_memory_8(unsigned int address, unsigned int value) {
|
||||
} else if (address >= 0x600000 && address < 0xA00000) {
|
||||
macRam[address & (TME_RAMSIZE-1)]=value;
|
||||
} else if (address >= 0xE80000 && address < 0xf00000) {
|
||||
viaWrite((address>>8)&0xf, value);
|
||||
viaWrite((address>>9)&0xf, value);
|
||||
} else if (address >= 0xc00000 && address < 0xe00000) {
|
||||
iwmWrite((address>>9)&0xf, value);
|
||||
} else {
|
||||
@ -59,24 +61,58 @@ void m68k_write_memory_8(unsigned int address, unsigned int value) {
|
||||
}
|
||||
}
|
||||
|
||||
//Should be called every second.
|
||||
void printFps() {
|
||||
struct timeval tv;
|
||||
static struct timeval oldtv;
|
||||
gettimeofday(&tv, NULL);
|
||||
if (oldtv.tv_sec!=0) {
|
||||
long msec=(tv.tv_sec-oldtv.tv_sec)*1000;
|
||||
msec+=(tv.tv_usec-oldtv.tv_usec)/1000;
|
||||
printf("Speed: %d%%\n", 100000/msec);
|
||||
}
|
||||
oldtv.tv_sec=tv.tv_sec;
|
||||
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]=x;
|
||||
rom_remap=1;
|
||||
viaClear(VIA_PORTA, 0x7F);
|
||||
viaSet(VIA_PORTA, 0x80);
|
||||
m68k_init();
|
||||
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
|
||||
m68k_pulse_reset();
|
||||
dispInit();
|
||||
while(1) {
|
||||
m68k_execute(8000000/60);
|
||||
for (x=0; x<8000000/60; x+=GRAN) {
|
||||
m68k_execute(GRAN);
|
||||
viaStep(GRAN);
|
||||
}
|
||||
dispDraw(&macRam[video_remap?0x12700:0x1A700]);
|
||||
// printf("Int!\n");
|
||||
// m68k_set_irq(2);
|
||||
frame++;
|
||||
ca1^=1;
|
||||
viaControlWrite(VIA_CA1, ca1);
|
||||
if (frame>=60) {
|
||||
ca2^=1;
|
||||
viaControlWrite(VIA_CA2, ca2);
|
||||
rtcTick();
|
||||
frame=0;
|
||||
printFps();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void viaIrq(int req) {
|
||||
// printf("IRQ %d\n", req);
|
||||
m68k_set_irq(req?1:0);
|
||||
}
|
||||
|
||||
//Mac uses an 68008, which has an external 16-bit bus. Hence, it should be okay to do everything using 16-bit
|
||||
//reads/writes.
|
||||
@ -104,6 +140,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) {
|
||||
video_remap=(val&(1<<6))?1:0;
|
||||
rom_remap=(val&(1<<4))?1:0;
|
||||
@ -111,5 +153,8 @@ void viaCbPortAWrite(unsigned int val) {
|
||||
}
|
||||
|
||||
void viaCbPortBWrite(unsigned int val) {
|
||||
int b;
|
||||
b=rtcCom(val&4, val&1, val&2);
|
||||
if (b) viaSet(VIA_PORTB, 1); else viaClear(VIA_PORTB, 1);
|
||||
}
|
||||
|
||||
|
4
m68kconf.h
Executable file → Normal file
4
m68kconf.h
Executable file → Normal file
@ -87,8 +87,8 @@
|
||||
* 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_OFF
|
||||
#define M68K_INT_ACK_CALLBACK(A) your_int_ack_handler_function(A)
|
||||
#define M68K_EMULATE_INT_ACK OPT_ON
|
||||
#define M68K_INT_ACK_CALLBACK(A) m68k_int_ack(A)
|
||||
|
||||
|
||||
/* If ON, CPU will call the breakpoint acknowledge callback when it encounters
|
||||
|
48
rtc.c
Normal file
48
rtc.c
Normal file
@ -0,0 +1,48 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
int lastClkVal;
|
||||
int pos;
|
||||
uint8_t cmd;
|
||||
uint8_t mem[32];
|
||||
} Rtc;
|
||||
|
||||
static Rtc rtc;
|
||||
|
||||
void rtcTick() {
|
||||
int x;
|
||||
for (x=0; x<3; x++) {
|
||||
rtc.mem[x]++;
|
||||
if (rtc.mem[x]!=0) return;
|
||||
}
|
||||
}
|
||||
|
||||
int rtcCom(int en, int dat, int clk) {
|
||||
int ret=0;
|
||||
clk=clk?1:0;
|
||||
if (en) {
|
||||
rtc.pos=0;
|
||||
rtc.cmd=0;
|
||||
} else {
|
||||
if (clk!=rtc.lastClkVal && !clk) {
|
||||
if (rtc.pos<8 || (rtc.pos<16 && ((rtc.cmd&0x8000)==0)) ) {
|
||||
if (dat) rtc.cmd|=(1<<(15-rtc.pos));
|
||||
} else if (rtc.cmd&0x8000) {
|
||||
if (rtc.pos==8) {
|
||||
rtc.cmd|=rtc.mem[(rtc.cmd&0x7C00)>>10];
|
||||
}
|
||||
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;
|
||||
printf("RTC/PRAM CMD %x\n", rtc.cmd);
|
||||
}
|
||||
rtc.pos++;
|
||||
printf("RTC/PRAM pos %d CMD %x\n", rtc.pos, rtc.cmd);
|
||||
}
|
||||
}
|
||||
rtc.lastClkVal=clk;
|
||||
return ret;
|
||||
}
|
||||
|
156
via.c
156
via.c
@ -5,22 +5,124 @@
|
||||
|
||||
void viaCbPortAWrite(unsigned int val);
|
||||
void viaCbPortBWrite(unsigned int val);
|
||||
void viaIrq();
|
||||
|
||||
#define IFR_IRQ (1<<7)
|
||||
#define IFR_T1 (1<<6)
|
||||
#define IFR_T2 (1<<5)
|
||||
#define IFR_CB1 (1<<4)
|
||||
#define IFR_CB2 (1<<3)
|
||||
#define IFR_SR (1<<2)
|
||||
#define IFR_CA1 (1<<1)
|
||||
#define IFR_CA2 (1<<0)
|
||||
|
||||
#define PCR_NEG 0
|
||||
#define PCR_NEG_NOCLR 1
|
||||
#define PCR_POS 2
|
||||
#define PCR_POS_NOCLR 3
|
||||
#define PCR_HANDSHAKE 4
|
||||
#define PCR_PULSEOUT 5
|
||||
#define PCR_MAN_LO 6
|
||||
#define PCR_MAN_HI 7
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t ddra;
|
||||
uint8_t ddrb;
|
||||
uint8_t ddra, ddrb;
|
||||
uint8_t ina, inb;
|
||||
uint8_t outa, outb;
|
||||
uint16_t timer1, timer2;
|
||||
uint16_t latch1, latch2;
|
||||
uint8_t ifr, ier;
|
||||
uint8_t pcr, acr;
|
||||
uint8_t controlin[2];
|
||||
} Via;
|
||||
|
||||
static Via via;
|
||||
|
||||
static const char* const viaRegNames[]={
|
||||
"ORB", "ORA", "DDRB", "DDRA", "T1C-L", "T1C-H", "T1L-L", "T1L-H", "T2L-L",
|
||||
"T2C-H", "SR", "ACR", "PCR", "IFR", "IER", "ORA-NC"
|
||||
};
|
||||
|
||||
|
||||
void viaSet(int no, int mask) {
|
||||
if (no==VIA_PORTA) via.ina|=mask; else via.inb|=mask;
|
||||
}
|
||||
|
||||
void viaClear(int no, int mask) {
|
||||
if (no==VIA_PORTA) via.ina&=~mask; else via.inb&=~mask;
|
||||
}
|
||||
|
||||
void viaStep(int clockcycles) {
|
||||
while(clockcycles--) {
|
||||
if ((via.timer2!=0) || (via.acr&(1<<6))) via.timer2--;
|
||||
if (via.timer1==0) {
|
||||
via.ifr|=IFR_T1;
|
||||
via.timer1=via.latch1;
|
||||
}
|
||||
if ((via.timer2!=0) || (via.acr&(1<<5))) via.timer2--;
|
||||
if (via.timer2==0) {
|
||||
via.ifr|=IFR_T2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void viaCheckIrq() {
|
||||
static int oldmint=0;
|
||||
int mint=(via.ifr&via.ier)&0x7F;
|
||||
if (mint) {
|
||||
via.ifr|=IFR_IRQ;
|
||||
viaIrq(1);
|
||||
// printf("VIA: Raised IRQ because masked if is %x\n", mint);
|
||||
} else if (!mint) {
|
||||
if (via.ifr&IFR_IRQ) viaIrq(0);
|
||||
via.ifr&=~IFR_IRQ;
|
||||
}
|
||||
}
|
||||
|
||||
static int pcrFor(int no) {
|
||||
const int shift[]={0, 1, 4, 5};
|
||||
const int mask[]={1, 3, 1, 3};
|
||||
int pcr=(via.pcr>>shift[no])&mask[no];
|
||||
if (no&1) {
|
||||
if (pcr) return PCR_NEG; else return PCR_POS;
|
||||
} else {
|
||||
return pcr;
|
||||
}
|
||||
}
|
||||
|
||||
static void accessPort(int no) {
|
||||
via.ifr&=~(no?IFR_CB1:IFR_CA1);
|
||||
int pcrca2=pcrFor(no?VIA_CB2:VIA_CA2);
|
||||
if (pcrca2==PCR_NEG || pcrca2==PCR_POS) {
|
||||
via.ifr&=~(no?IFR_CB2:IFR_CA2);
|
||||
}
|
||||
viaCheckIrq();
|
||||
}
|
||||
|
||||
void viaControlWrite(int no, int val) {
|
||||
const int ifbits[]={IFR_CA1, IFR_CA2, IFR_CB1, IFR_CB2};
|
||||
int pcr=pcrFor(no);
|
||||
if (val) val=1;
|
||||
if (via.controlin[no]!=val) {
|
||||
if ( ((pcr==PCR_NEG || pcr==PCR_NEG_NOCLR) && !val) ||
|
||||
((pcr==PCR_POS || pcr==PCR_POS_NOCLR) && val) ) {
|
||||
via.ifr|=ifbits[no];
|
||||
viaCheckIrq();
|
||||
}
|
||||
}
|
||||
via.controlin[no]=val;
|
||||
}
|
||||
|
||||
void viaWrite(unsigned int addr, unsigned int val) {
|
||||
if (addr==0x0) {
|
||||
//ORB
|
||||
viaCbPortBWrite(val);
|
||||
accessPort(1);
|
||||
} else if (addr==0x1) {
|
||||
//ORA
|
||||
viaCbPortAWrite(val);
|
||||
accessPort(0);
|
||||
} else if (addr==0x2) {
|
||||
//DDRB
|
||||
via.ddrb=val;
|
||||
@ -29,30 +131,56 @@ void viaWrite(unsigned int addr, unsigned int val) {
|
||||
via.ddra=val;
|
||||
} else if (addr==0x4) {
|
||||
//T1L-L
|
||||
via.latch1=(via.latch1&0xff00)|val;
|
||||
} else if (addr==0x5) {
|
||||
//T1C-H
|
||||
via.latch1=(via.latch1&0x00ff)|(val<<8);
|
||||
via.timer1=via.latch1;
|
||||
via.ifr&=~IFR_T1;
|
||||
viaCheckIrq();
|
||||
} else if (addr==0x6) {
|
||||
//T1L-L
|
||||
via.latch1=(via.latch1&0xff00)|val;
|
||||
} else if (addr==0x7) {
|
||||
//T1L-H
|
||||
via.latch1=(via.latch1&0x00ff)|(val<<8);
|
||||
via.ifr&=~IFR_T1;
|
||||
viaCheckIrq();
|
||||
} else if (addr==0x8) {
|
||||
//T2L-l
|
||||
via.latch2=val;
|
||||
} else if (addr==0x9) {
|
||||
//T2C-H
|
||||
via.timer2=via.latch2|(val<<8);
|
||||
via.ifr&=~IFR_T2;
|
||||
viaCheckIrq();
|
||||
} else if (addr==0xa) {
|
||||
//SR
|
||||
printf("6522: Unimplemented: Write %x to SR?\n", val);
|
||||
} else if (addr==0xb) {
|
||||
//ACR
|
||||
via.acr=val;
|
||||
} else if (addr==0xc) {
|
||||
//PCR
|
||||
via.pcr=val;
|
||||
} else if (addr==0xd) {
|
||||
//IFR
|
||||
via.ifr&=~val;
|
||||
viaCheckIrq();
|
||||
} else if (addr==0xe) {
|
||||
//IER
|
||||
if (val&0x80) {
|
||||
via.ier|=val;
|
||||
} else {
|
||||
via.ier&=~val;
|
||||
}
|
||||
via.ier&=0x7f;
|
||||
viaCheckIrq();
|
||||
} else if (addr==0xf) {
|
||||
//ORA
|
||||
viaCbPortAWrite(val);
|
||||
}
|
||||
printf("VIA write %x val %x\n", addr, val);
|
||||
// printf("VIA write %s val %x\n", viaRegNames[addr], val);
|
||||
}
|
||||
|
||||
|
||||
@ -61,8 +189,12 @@ unsigned int viaRead(unsigned int addr) {
|
||||
unsigned int val=0;
|
||||
if (addr==0x0) {
|
||||
//ORB
|
||||
val=via.inb;
|
||||
accessPort(1);
|
||||
} else if (addr==0x1) {
|
||||
//ORA
|
||||
val=via.ina;
|
||||
accessPort(0);
|
||||
} else if (addr==0x2) {
|
||||
//DDRB
|
||||
val=via.ddrb;
|
||||
@ -71,29 +203,45 @@ unsigned int viaRead(unsigned int addr) {
|
||||
val=via.ddra;
|
||||
} else if (addr==0x4) {
|
||||
//T1L-L
|
||||
val=via.timer1&0xff;
|
||||
via.ifr&=~IFR_T1;
|
||||
viaCheckIrq();
|
||||
} else if (addr==0x5) {
|
||||
//T1C-H
|
||||
val=via.timer1>>8;
|
||||
} else if (addr==0x6) {
|
||||
//T1L-L
|
||||
val=via.latch1&0xff;
|
||||
} else if (addr==0x7) {
|
||||
//T1L-H
|
||||
val=via.latch1&0xff;
|
||||
} else if (addr==0x8) {
|
||||
//T2L-l
|
||||
val=via.timer2&0xff;
|
||||
via.ifr&=~IFR_T2;
|
||||
viaCheckIrq();
|
||||
} else if (addr==0x9) {
|
||||
//T2C-H
|
||||
val=via.timer2>>8;
|
||||
} else if (addr==0xa) {
|
||||
//SR
|
||||
printf("6522: Unimplemented: Read from SR?\n");
|
||||
} else if (addr==0xb) {
|
||||
//ACR
|
||||
val=via.acr;
|
||||
} else if (addr==0xc) {
|
||||
//PCR
|
||||
val=via.pcr;
|
||||
} else if (addr==0xd) {
|
||||
//IFR
|
||||
val=via.ifr;
|
||||
} else if (addr==0xe) {
|
||||
//IER
|
||||
val=via.ier;
|
||||
} else if (addr==0xf) {
|
||||
//ORA
|
||||
val=via.ina;
|
||||
}
|
||||
printf("PC %x VIA read %x val %x\n", pc, addr, val);
|
||||
// printf("PC %x VIA read %s val %x\n", pc, viaRegNames[addr], val);
|
||||
return val;
|
||||
}
|
||||
|
13
via.h
13
via.h
@ -1,2 +1,15 @@
|
||||
|
||||
#define VIA_CA1 0
|
||||
#define VIA_CA2 1
|
||||
#define VIA_CB1 2
|
||||
#define VIA_CB2 3
|
||||
|
||||
#define VIA_PORTA 0
|
||||
#define VIA_PORTB 1
|
||||
|
||||
void viaWrite(unsigned int addr, unsigned int val);
|
||||
unsigned int viaRead(unsigned int addr);
|
||||
void viaControlWrite(int no, int val);
|
||||
void viaStep(int clockcycles);
|
||||
void viaSet(int no, int mask);
|
||||
void viaClear(int no, int mask);
|
||||
|
Loading…
Reference in New Issue
Block a user