📄 irobot.c
字号:
/***************************************************************************
machine.c
Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
I/O ports)
***************************************************************************/
#include "driver.h"
#include "cpuintrf.h"
extern void run_video(void);
extern void irobot_poly_clear(void);
extern int irvg_running;
unsigned char *irobot_nvRAM;
extern unsigned char *comRAM1,*comRAM2,*mbRAM,*mbROM;
static unsigned char irobot_control_num = 0;
static unsigned char irobot_statwr;
static unsigned char irobot_out0;
static unsigned char irobot_outx,irobot_mpage;
unsigned char irobot_comswap;
unsigned char irobot_bufsel;
unsigned char irobot_alphamap;
/* I-Robot Mathbox
Based on 4 2901 chips slice processors connected to form a 16-bit ALU
Microcode roms:
6N: bits 0..3: Address of ALU A register
5P: bits 0..3: Address of ALU B register
6M: bits 0..3: ALU Function bits 5..8
7N: bits 0..3: ALU Function bits 1..4
8N: bits 0,1: Memory write timing
bit 2: Hardware multiply mode
bit 3: ALU Function bit 0
6P: bits 0,1: Direct addressing bits 0,1
bits 2,3: Jump address bits 0,1
8M: bits 0..3: Jump address bits 6..9
9N: bits 0..3: Jump address bits 2..5
8P: bits 0..3: Memory address bits 2..5
9M: bit 0: Shift control
bits 1..3: Jump type
0 = No Jump
1 = On carry
2 = On zero
3 = On positive
4 = On negative
5 = Unconditional
6 = Jump to Subroutine
7 = Return from Subroutine
7M: Bit 0: Mathbox memory enable
Bit 1: Latch data to address bus
Bit 2: Carry in select
Bit 3: Carry in value
(if 2,3 = 11 then mathbox is done)
9P: Bit 0: Hardware divide enable
Bits 1,2: Memory select
Bit 3: Memory R/W
7P: Bits 0,1: Direct addressing bits 6,7
Bits 2,3: Unused
*/
/* Mathbox variable */
int irmb_running;
static int irmb_PC;
static int irmb_oldPC;
static unsigned int irmb_Q;
static unsigned int irmb_F;
static unsigned int irmb_Y;
static unsigned int irmb_regs[16];
static unsigned int irmb_stack[16];
static int irmb_sp;
static unsigned int irmb_pmadd;
static unsigned int irmb_latch;
static unsigned char irmb_nflag;
static unsigned char irmb_vflag;
static unsigned char irmb_cflag;
static unsigned char irmb_zflag;
static unsigned char irmb_CI;
#define FL_MULT 0x01
#define FL_shift 0x02
#define FL_MBMEMDEC 0x04
#define FL_ADDEN 0x08
#define FL_DPSEL 0x10
#define FL_carry 0x20
#define FL_DIV 0x40
#define FL_MBRW 0x80
/* flags:
0: MULT
1: Shift control
2: MBMEMDEC
3: ADDEN
4: DPSEL
5: Carry
6: DIV
7: MBR/W
*/
typedef struct {
unsigned char areg;
unsigned char breg;
int func;
unsigned int flags;
unsigned char diradd;
int nxtadd;
unsigned char mab;
unsigned char jtype;
unsigned char ramsel;
} irmb_ops;
irmb_ops mbops[1024];
int irmb_exec(void);
unsigned int irmb_din(void) {
unsigned int d=0;
unsigned int ad;
int diren;
if (!(mbops[irmb_PC].flags & FL_MBMEMDEC) && (mbops[irmb_PC].flags & FL_MBRW)) {
if (mbops[irmb_PC].ramsel == 0) { /* DIREN = 1 */
diren = 1;
ad = mbops[irmb_PC].mab << 2;
ad = ad | (mbops[irmb_PC].diradd & 0xC0);
ad = ad | (irmb_latch & 0x1000);
}
else { /* DIREN = 0 */
diren = 0;
ad = irmb_latch & 0x1FF8;
ad = ad | (irmb_pmadd & 0x04);
}
if (mbops[irmb_PC].ramsel & 0x02)
ad = ad | (irmb_pmadd & 0x03);
else
ad = ad | (mbops[irmb_PC].diradd & 0x03);
if (diren == 1 || (irmb_latch & 0x6000) == 0) { /* MB RAM read */
ad = (ad & 0xFFF) << 1;
d = (mbRAM[ad] << 8) | mbRAM[ad+1];
}
else { /* MB ROM read */
ad = (ad & 0x1FFF) << 1;
if (irmb_latch & 0x4000) { /* CEMATH = 1 */
if (irmb_latch & 0x2000)
d = (mbROM[ad+0x8000] << 8) | mbROM[ad+0x8001];
else
d = (mbROM[ad+0x4000] << 8) | mbROM[ad+0x4001];
}
else { /* CEMATH = 0 */
d = (mbROM[ad] << 8) | mbROM[ad+1];
}
}
}
return d;
}
void irmb_dout(unsigned int d) {
unsigned int ad;
int diren;
/* Write to video com ram */
if (mbops[irmb_PC].ramsel == 3) {
ad = irmb_latch & 0x1FF8;
ad = ad | (irmb_pmadd & 0x07);
ad = (ad & 0x7FF) << 1;
if (irobot_comswap) {
comRAM2[ad] = (d & 0xFF00) >> 8;
comRAM2[ad+1] = d & 0x00FF;
}
else {
comRAM1[ad] = (d & 0xFF00) >> 8;
comRAM1[ad+1] = d & 0x00FF;
}
}
/* Write to mathox ram */
if (!(mbops[irmb_PC].flags & FL_MBMEMDEC)) {
if (mbops[irmb_PC].ramsel == 0) { /* DIREN = 1 */
diren = 1;
ad = mbops[irmb_PC].mab << 2;
ad = ad | (mbops[irmb_PC].diradd & 0xC0);
ad = ad | (irmb_latch & 0x1000);
}
else { /* DIREN = 0 */
diren = 0;
ad = irmb_latch & 0x1FF8;
ad = ad | (irmb_pmadd & 0x04);
}
if (mbops[irmb_PC].ramsel & 0x02)
ad = ad | (irmb_pmadd & 0x03);
else
ad = ad | (mbops[irmb_PC].diradd & 0x03);
ad = (ad & 0xFFF) << 1;
if (diren == 1 || (irmb_latch & 0x6000) == 0) { /* MB RAM write */
mbRAM[ad] = (d & 0xFF00) >> 8;
mbRAM[ad+1] = (d & 0x00FF);
}
}
}
/* Convert microcode roms to a more usable form */
void load_oproms(void) {
int i;
unsigned char *MB = Machine->memory_region[2];
for (i=0; i<1024; i++) {
mbops[i].areg = MB[0xC000 + i] & 0x0F;
mbops[i].breg = MB[0xC400 + i] & 0x0F;
mbops[i].func = (MB[0xC800 + i] & 0x0F) << 5;
mbops[i].func |= ((MB[0xCC00 +i] & 0x0F) << 1);
mbops[i].func |= (MB[0xD000 + i] & 0x08) >> 3;
mbops[i].flags = (MB[0xD000 + i] & 0x04) >> 2;
mbops[i].nxtadd = (MB[0xD400 + i] & 0x0C) >> 2;
mbops[i].diradd = MB[0xD400 +i] & 0x03;
mbops[i].nxtadd |= ((MB[0xD800 + i] & 0x0F) << 6);
mbops[i].nxtadd |= ((MB[0xDC00 + i] & 0x0F) << 2);
mbops[i].mab = (MB[0xE000 + i] & 0x0F);
mbops[i].jtype = (MB[0xE400 + i] & 0x0E) >> 1;
mbops[i].flags |= (MB[0xE400 + i] & 0x01) << 1;
mbops[i].flags |= (MB[0xE800 + i] & 0x0F) << 2;
mbops[i].flags |= (MB[0xEC00 + i] & 0x01) << 6;
mbops[i].flags |= (MB[0xEC00 + i] & 0x08) << 4;
mbops[i].ramsel = (MB[0xEC00 + i] & 0x06) >> 1;
mbops[i].diradd |= (MB[0xF000 + i] & 0x03) << 6;
}
}
/* Init mathbox (only called once) */
void irmb_init(void) {
int i;
for(i=0; i<16; i++) {
irmb_regs[i]=0x00;
irmb_stack[i]=0x00;
}
irmb_PC=irmb_Q=irmb_F=irmb_Y=irmb_sp=0;
irmb_nflag=irmb_cflag=irmb_zflag=0;
irmb_pmadd=0;
irmb_running=0;
irmb_oldPC=0;
load_oproms();
}
/* Run mathbox */
void irmb_run(void) {
int i;
irmb_oldPC=irmb_PC=irmb_sp=i=0;
while (!i) {
i = irmb_exec();
}
}
/* Execute instruction */
void do_jump(void) {
irmb_PC = mbops[irmb_PC].nxtadd;
}
int irmb_exec(void) {
int fu;
unsigned int R,S,F;
unsigned int MDB;
unsigned long result;
result = 0;
R=S=F=0;
/* Get function code */
fu = mbops[irmb_PC].func;
/* Check for done */
if ((mbops[irmb_PC].flags & FL_DPSEL) && (mbops[irmb_PC].flags & FL_carry)) {
return 1;
}
/* Modify function for MULT */
if (!(mbops[irmb_oldPC].flags & FL_MULT)) {
fu = fu ^ 0x02;
}
else {
if (!(irmb_Q & 0x01)) {
fu = fu | 0x02;
}
else {
fu = fu ^ 0x02;
}
}
/* Modify function for DIV */
if ((mbops[irmb_oldPC].flags & FL_DIV) || irmb_nflag) {
fu = fu ^ 0x08;
}
if (!(mbops[irmb_oldPC].flags & FL_DIV) && !irmb_nflag) {
fu = fu | 0x08;
}
/* Get registers to work on */
switch (fu & 0x07) {
case 0:
R = irmb_regs[mbops[irmb_PC].areg];
S = irmb_Q;
break;
case 1:
R = irmb_regs[mbops[irmb_PC].areg];
S = irmb_regs[mbops[irmb_PC].breg];
break;
case 2:
R = 0;
S = irmb_Q;
break;
case 3:
R = 0;
S = irmb_regs[mbops[irmb_PC].breg];
break;
case 4:
R = 0;
S = irmb_regs[mbops[irmb_PC].areg];
break;
case 5:
R = irmb_din();
S = irmb_regs[mbops[irmb_PC].areg];
break;
case 6:
R = irmb_din();
S = irmb_Q;
break;
case 7:
R = irmb_din();
S = 0;
break;
}
/* determine carry in */
irmb_CI=0;
if (mbops[irmb_PC].flags & FL_DPSEL) {
irmb_CI = irmb_cflag;
}
else {
if (mbops[irmb_PC].flags & FL_carry) irmb_CI = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -