1
0
mirror of https://github.com/mist64/perfect6502.git synced 2024-06-08 12:29:28 +00:00
perfect6502/perfect6502.c

740 lines
15 KiB
C
Raw Normal View History

2010-09-22 07:35:22 +00:00
//#define DEBUG
2010-09-22 15:25:34 +00:00
int verbose = 0;
2010-09-22 05:14:57 +00:00
2010-09-22 01:51:38 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned char uint8_t;
2010-09-22 05:14:57 +00:00
typedef unsigned short uint16_t;
2010-09-22 01:51:38 +00:00
typedef int BOOL;
2010-09-22 22:57:00 +00:00
typedef uint16_t nodenum_t;
2010-09-22 23:02:36 +00:00
typedef uint16_t transnum_t;
typedef uint16_t count_t;
typedef uint8_t state_t;
2010-09-22 22:57:00 +00:00
2010-09-22 01:51:38 +00:00
#define NO 0
#define YES 1
#include "segdefs.h"
#include "transdefs.h"
#include "nodenames.h"
#define ngnd vss
#define npwr vcc
enum {
STATE_VCC,
2010-09-22 17:37:35 +00:00
STATE_PU,
2010-09-22 01:51:38 +00:00
STATE_FH,
2010-09-22 17:37:35 +00:00
STATE_GND,
STATE_FL,
2010-09-22 01:51:38 +00:00
STATE_PD,
};
2010-09-22 17:37:35 +00:00
#define MAX_HIGH STATE_FH /* VCC, PU and FH are considered high */
2010-09-22 07:35:22 +00:00
#define NODES 1725
#define TRANSISTORS 3510
BOOL nodes_pullup[NODES];//XXX no idea why this array overflows!!
BOOL nodes_pulldown[NODES];
state_t nodes_state[NODES];
nodenum_t nodes_gates[NODES][NODES];
nodenum_t nodes_c1c2s[NODES][2*NODES];
count_t nodes_gatecount[NODES];
count_t nodes_c1c2count[NODES];
2010-09-22 01:51:38 +00:00
transnum_t transistors_name[TRANSISTORS];
nodenum_t transistors_gate[TRANSISTORS];
nodenum_t transistors_c1[TRANSISTORS];
nodenum_t transistors_c2[TRANSISTORS];
2010-09-22 05:14:57 +00:00
int transistors_on[TRANSISTORS/sizeof(int)+1];
void
set_transistors_on(transnum_t t, BOOL state)
{
if (state)
transistors_on[t>>5] |= 1 << (t & 31);
else
transistors_on[t>>5] &= ~(1 << (t & 31));
}
BOOL
get_transistors_on(transnum_t t)
{
return (transistors_on[t>>5] >> (t & 31)) & 1;
}
2010-09-22 01:51:38 +00:00
uint8_t memory[65536];
int cycle;
2010-09-22 10:05:49 +00:00
uint8_t A, X, Y, S, P;
uint16_t PC;
BOOL N, Z, C;
2010-09-22 01:51:38 +00:00
void
setupNodesAndTransistors()
2010-09-22 01:51:38 +00:00
{
2010-09-22 23:02:36 +00:00
count_t i;
2010-09-22 01:51:38 +00:00
for (i = 0; i < sizeof(segdefs)/sizeof(*segdefs); i++) {
nodes_pullup[i] = segdefs[i];
nodes_state[i] = STATE_FL;
nodes_gatecount[i] = 0;
nodes_c1c2count[i] = 0;
2010-09-22 01:51:38 +00:00
}
for (i = 0; i < sizeof(transdefs)/sizeof(*transdefs); i++) {
2010-09-22 22:57:00 +00:00
nodenum_t gate = transdefs[i].gate;
nodenum_t c1 = transdefs[i].c1;
nodenum_t c2 = transdefs[i].c2;
transistors_name[i] = i;
transistors_gate[i] = gate;
transistors_c1[i] = c1;
transistors_c2[i] = c2;
nodes_gates[gate][nodes_gatecount[gate]++] = i;
nodes_c1c2s[c1][nodes_c1c2count[c1]++] = i;
nodes_c1c2s[c2][nodes_c1c2count[c2]++] = i;
2010-09-22 01:51:38 +00:00
}
}
2010-09-22 05:14:57 +00:00
#ifdef DEBUG
void
2010-09-22 23:02:36 +00:00
printarray(nodenum_t *array, count_t count)
2010-09-22 05:14:57 +00:00
{
2010-09-22 23:02:36 +00:00
count_t i;
2010-09-22 05:14:57 +00:00
for (i = 0; i < count; i++)
printf("%d ", array[i]);
printf("\n");
}
#endif
2010-09-22 22:57:00 +00:00
nodenum_t group[NODES];
2010-09-22 23:02:36 +00:00
count_t groupcount;
int groupbitmap[NODES/sizeof(int)+1];
2010-09-22 22:38:56 +00:00
2010-09-22 01:51:38 +00:00
BOOL
2010-09-23 02:53:11 +00:00
groupContains(nodenum_t el)
2010-09-22 01:51:38 +00:00
{
2010-09-22 22:51:14 +00:00
return (groupbitmap[el>>5] >> (el & 31)) & 1;
2010-09-22 01:51:38 +00:00
}
2010-09-22 18:00:45 +00:00
typedef struct {
2010-09-22 22:57:00 +00:00
nodenum_t *list;
2010-09-22 23:02:36 +00:00
count_t count;
int *bitmap;
2010-09-22 18:00:45 +00:00
} list_t;
list_t recalc;
BOOL
2010-09-22 22:57:00 +00:00
recalcListContains(nodenum_t el)
2010-09-22 18:00:45 +00:00
{
return (recalc.bitmap[el>>5] >> (el & 31)) & 1;
2010-09-22 18:00:45 +00:00
}
2010-09-22 22:57:00 +00:00
void addNodeToGroup(nodenum_t i);
2010-09-22 01:51:38 +00:00
void
2010-09-22 23:02:36 +00:00
addNodeTransistor(nodenum_t node, transnum_t t)
2010-09-22 01:51:38 +00:00
{
/* if the transistor does not connect c1 and c2, we stop here */
if (!get_transistors_on(t))
2010-09-22 01:51:38 +00:00
return;
if (transistors_c1[t] == node)
addNodeToGroup(transistors_c2[t]);
else
addNodeToGroup(transistors_c1[t]);
2010-09-22 01:51:38 +00:00
}
void
2010-09-22 22:57:00 +00:00
addNodeToGroup(nodenum_t i)
2010-09-22 01:51:38 +00:00
{
2010-09-23 02:53:11 +00:00
if (groupContains(i))
2010-09-22 01:51:38 +00:00
return;
2010-09-22 18:06:15 +00:00
group[groupcount++] = i;
2010-09-22 22:51:14 +00:00
groupbitmap[i>>5] |= 1 << (i & 31);
if (i == ngnd || i == npwr)
2010-09-22 01:51:38 +00:00
return;
for (count_t t = 0; t < nodes_c1c2count[i]; t++)
addNodeTransistor(i, nodes_c1c2s[i][t]);
2010-09-22 01:51:38 +00:00
}
2010-09-23 02:59:33 +00:00
// 1. if there is a pullup node, it's STATE_PU
// 2. if there is a pulldown node, it's STATE_PD
// (if both 1 and 2 are true, the first pullup or pulldown wins, with
// a statistical advantage towards STATE_PU
// 3. otherwise, if there is an FH node, it's STATE_FH
// 4. otherwise, it's STATE_FL (if there is an FL node, which is always the case)
2010-09-22 23:02:36 +00:00
state_t
2010-09-22 18:06:15 +00:00
getNodeValue()
2010-09-22 01:51:38 +00:00
{
2010-09-23 02:53:11 +00:00
if (groupContains(ngnd))
2010-09-22 01:51:38 +00:00
return STATE_GND;
2010-09-23 02:53:11 +00:00
if (groupContains(npwr))
2010-09-22 01:51:38 +00:00
return STATE_VCC;
2010-09-23 02:59:33 +00:00
state_t flstate = STATE_FL;
for (count_t i = 0; i < groupcount; i++) {
2010-09-22 22:57:00 +00:00
nodenum_t nn = group[i];
if (nodes_pullup[nn])
2010-09-22 01:51:38 +00:00
return STATE_PU;
if (nodes_pulldown[nn])
2010-09-22 01:51:38 +00:00
return STATE_PD;
if (nodes_state[nn] == STATE_FH)
2010-09-22 01:51:38 +00:00
flstate = STATE_FH;
}
return flstate;
}
2010-09-22 05:14:57 +00:00
void
2010-09-22 22:57:00 +00:00
addRecalcNode(nodenum_t nn)
2010-09-22 05:14:57 +00:00
{
2010-09-23 06:44:32 +00:00
/* no need to analyze VCC or GND */
2010-09-22 18:00:45 +00:00
if (nn == ngnd || nn == npwr)
2010-09-22 05:14:57 +00:00
return;
2010-09-23 06:44:32 +00:00
/* we already know about this node */
2010-09-22 18:00:45 +00:00
if (recalcListContains(nn))
2010-09-22 05:14:57 +00:00
return;
2010-09-23 06:44:32 +00:00
/* add node to list */
2010-09-22 18:06:15 +00:00
recalc.list[recalc.count++] = nn;
recalc.bitmap[nn>>5] |= 1 << (nn & 31);
2010-09-22 05:14:57 +00:00
}
void
2010-09-22 22:57:00 +00:00
floatnode(nodenum_t nn)
2010-09-22 05:14:57 +00:00
{
2010-09-23 06:44:32 +00:00
/* VCC and GND are constant */
2010-09-22 17:37:35 +00:00
if (nn == ngnd || nn == npwr)
2010-09-22 05:14:57 +00:00
return;
2010-09-23 06:44:32 +00:00
state_t state = nodes_state[nn];
2010-09-23 06:44:32 +00:00
2010-09-22 17:37:35 +00:00
if (state == STATE_GND || state == STATE_PD)
nodes_state[nn] = STATE_FL;
2010-09-23 06:44:32 +00:00
2010-09-22 17:37:35 +00:00
if (state == STATE_VCC || state == STATE_PU)
nodes_state[nn] = STATE_FH;
2010-09-22 05:14:57 +00:00
}
BOOL
2010-09-22 22:57:00 +00:00
isNodeHigh(nodenum_t nn)
2010-09-22 05:14:57 +00:00
{
#ifdef DEBUG
2010-09-22 07:25:32 +00:00
printf("%s nn=%d state=%d\n", __func__, nn, nodes[nn].state);
2010-09-22 17:37:35 +00:00
printf("%s nn=%d res=%d\n", __func__, nn, nodes[nn].state <= MAX_HIGH);
2010-09-22 05:14:57 +00:00
#endif
return nodes_state[nn] <= MAX_HIGH;
2010-09-22 05:14:57 +00:00
}
void
2010-09-22 23:02:36 +00:00
recalcTransistor(transnum_t tn)
2010-09-22 05:14:57 +00:00
{
2010-09-23 06:44:32 +00:00
/* if the gate is high, the transistor should be on */
BOOL on = isNodeHigh(transistors_gate[tn]);
2010-09-23 06:44:32 +00:00
/* no change? nothing to do! */
if (on == get_transistors_on(tn))
2010-09-22 17:00:22 +00:00
return;
2010-09-23 06:44:32 +00:00
set_transistors_on(tn, on);
2010-09-23 06:44:32 +00:00
/* if the transistor is off, both nodes are floating */
2010-09-22 17:00:22 +00:00
if (!on) {
floatnode(transistors_c1[tn]);
floatnode(transistors_c2[tn]);
2010-09-22 17:00:22 +00:00
}
2010-09-23 06:44:32 +00:00
/* next time, we'll have to look at both nodes behind the transistor */
addRecalcNode(transistors_c1[tn]);
addRecalcNode(transistors_c2[tn]);
2010-09-22 05:14:57 +00:00
}
2010-09-22 01:51:38 +00:00
void
2010-09-22 22:57:00 +00:00
recalcNode(nodenum_t node)
2010-09-22 01:51:38 +00:00
{
2010-09-22 18:06:15 +00:00
if (node == ngnd || node == npwr)
2010-09-22 01:51:38 +00:00
return;
2010-09-22 18:06:15 +00:00
groupcount = 0;
2010-09-22 22:46:11 +00:00
bzero(groupbitmap, sizeof(groupbitmap));
2010-09-23 03:28:00 +00:00
/*
* get all nodes that are connected through
* transistors, starting with this one
*/
2010-09-22 18:06:15 +00:00
addNodeToGroup(node);
2010-09-22 01:51:38 +00:00
2010-09-23 03:28:00 +00:00
/* get the state of the group */
2010-09-22 23:02:36 +00:00
state_t newv = getNodeValue();
2010-09-23 03:28:00 +00:00
/*
* now all nodes in this group are in this state,
2010-09-23 06:44:32 +00:00
* - all transistors switched by nodes the group
* need to be recalculated
* - all nodes behind the transistor are collected
* and must be looked at in the next run
2010-09-23 03:28:00 +00:00
*/
for (count_t i = 0; i < groupcount; i++) {
nodes_state[group[i]] = newv;
2010-09-23 03:28:00 +00:00
for (count_t t = 0; t < nodes_gatecount[group[i]]; t++)
recalcTransistor(nodes_gates[group[i]][t]);
2010-09-22 05:14:57 +00:00
}
2010-09-22 01:51:38 +00:00
}
2010-09-23 06:44:32 +00:00
/*
* NOTE: "list" as provided by the caller must
* at least be able to hold NODES elements!
*/
2010-09-22 01:51:38 +00:00
void
2010-09-22 23:02:36 +00:00
recalcNodeList(nodenum_t *list, count_t count)
2010-09-22 01:51:38 +00:00
{
2010-09-23 06:44:32 +00:00
/* storage for secondary list and two sets of bitmaps */
2010-09-22 22:57:00 +00:00
nodenum_t list1[NODES];
int bitmap1[NODES/sizeof(int)+1];
int bitmap2[NODES/sizeof(int)+1];
2010-09-22 18:00:45 +00:00
2010-09-23 06:44:32 +00:00
/* the nodes we are working with */
2010-09-22 18:00:45 +00:00
list_t current;
current.list = list;
current.count = count;
current.bitmap = bitmap2;
2010-09-23 06:44:32 +00:00
/* the nodes we are collecting for the next run */
2010-09-22 18:00:45 +00:00
recalc.list = list1;
recalc.bitmap = bitmap1;
2010-09-23 02:53:11 +00:00
for (int j = 0; j < 100; j++) { // loop limiter
if (!current.count)
return;
2010-09-23 06:44:32 +00:00
/* clear secondary list */
2010-09-23 02:41:12 +00:00
bzero(recalc.bitmap, sizeof(*recalc.bitmap)*NODES/sizeof(int));
recalc.count = 0;
2010-09-22 18:00:45 +00:00
2010-09-23 06:44:32 +00:00
/*
* for all nodes, follow their paths through
* turned-on transistors, find the state of the
* path and assign it to all nodes, and re-evaluate
* all transistors controlled by this path, collecting
* all nodes that changed because of it for the next run
*/
2010-09-23 02:53:11 +00:00
for (count_t i = 0; i < current.count; i++)
2010-09-22 18:00:45 +00:00
recalcNode(current.list[i]);
2010-09-23 06:44:32 +00:00
/*
* make the secondary list our primary list, use
* the data storage of the primary list as the
* secondary list
*/
2010-09-23 02:53:11 +00:00
list_t tmp = current;
current = recalc;
recalc = tmp;
2010-09-22 01:51:38 +00:00
}
}
void
recalcAllNodes()
{
2010-09-22 22:57:00 +00:00
nodenum_t list[NODES];
2010-09-23 06:44:32 +00:00
for (count_t i = 0; i < NODES; i++)
2010-09-22 05:14:57 +00:00
list[i] = i;
2010-09-22 07:35:22 +00:00
recalcNodeList(list, NODES);
2010-09-22 01:51:38 +00:00
}
2010-09-23 02:41:12 +00:00
static inline void
setNode(nodenum_t nn, BOOL state)
2010-09-22 01:51:38 +00:00
{
2010-09-23 02:41:12 +00:00
nodes_pullup[nn] = state;
nodes_pulldown[nn] = !state;
2010-09-22 22:57:00 +00:00
nodenum_t list[NODES];
2010-09-22 07:35:22 +00:00
list[0] = nn;
recalcNodeList(list, 1);
2010-09-22 01:51:38 +00:00
}
void
2010-09-23 02:41:12 +00:00
setLow(nodenum_t nn)
2010-09-22 01:51:38 +00:00
{
2010-09-23 02:41:12 +00:00
setNode(nn, 0);
2010-09-22 01:51:38 +00:00
}
2010-09-22 15:25:34 +00:00
void
2010-09-23 02:41:12 +00:00
setHigh(nodenum_t nn)
2010-09-22 15:25:34 +00:00
{
2010-09-23 02:41:12 +00:00
setNode(nn, 1);
2010-09-22 15:25:34 +00:00
}
2010-09-23 06:56:23 +00:00
/************************************************************
*
* Address Bus and Data Bus Interface
*
************************************************************/
2010-09-23 06:44:32 +00:00
/* the nodes that make the data bus */
const nodenum_t dbnodes[8] = { db0, db1, db2, db3, db4, db5, db6, db7 };
2010-09-23 02:47:31 +00:00
2010-09-22 05:14:57 +00:00
void
writeDataBus(uint8_t x)
2010-09-22 01:51:38 +00:00
{
2010-09-23 02:47:31 +00:00
for (int i = 0; i < 8; i++) {
2010-09-23 06:44:32 +00:00
nodenum_t nn = dbnodes[i];
2010-09-23 02:47:31 +00:00
nodes_pulldown[nn] = !(x & 1);
nodes_pullup[nn] = x & 1;
2010-09-22 05:14:57 +00:00
x >>= 1;
}
2010-09-23 06:44:32 +00:00
2010-09-23 06:56:23 +00:00
/* recalc all nodes connected starting from the data bus */
2010-09-23 06:44:32 +00:00
nodenum_t list[NODES];
bcopy(dbnodes, list, sizeof(dbnodes));
recalcNodeList(list, 8);
2010-09-22 05:14:57 +00:00
}
uint8_t mRead(uint16_t a)
{
2010-09-22 15:25:34 +00:00
if (verbose)
printf("PEEK($%04X) = $%02X\n", a, memory[a]);
2010-09-22 05:14:57 +00:00
return memory[a];
}
uint16_t
readAddressBus()
{
return (isNodeHigh(ab0) << 0) |
(isNodeHigh(ab1) << 1) |
(isNodeHigh(ab2) << 2) |
(isNodeHigh(ab3) << 3) |
(isNodeHigh(ab4) << 4) |
(isNodeHigh(ab5) << 5) |
(isNodeHigh(ab6) << 6) |
(isNodeHigh(ab7) << 7) |
(isNodeHigh(ab8) << 8) |
(isNodeHigh(ab9) << 9) |
(isNodeHigh(ab10) << 10) |
(isNodeHigh(ab11) << 11) |
(isNodeHigh(ab12) << 12) |
(isNodeHigh(ab13) << 13) |
(isNodeHigh(ab14) << 14) |
(isNodeHigh(ab15) << 15);
2010-09-22 01:51:38 +00:00
}
2010-09-22 05:14:57 +00:00
uint8_t
readDataBus()
{
return (isNodeHigh(db0) << 0) |
(isNodeHigh(db1) << 1) |
(isNodeHigh(db2) << 2) |
(isNodeHigh(db3) << 3) |
(isNodeHigh(db4) << 4) |
(isNodeHigh(db5) << 5) |
(isNodeHigh(db6) << 6) |
(isNodeHigh(db7) << 7);
}
void
mWrite(uint16_t a, uint8_t d)
{
2010-09-22 15:25:34 +00:00
if (verbose)
printf("POKE $%04X, $%02X\n", a, d);
2010-09-22 05:14:57 +00:00
memory[a] = d;
2010-09-22 01:51:38 +00:00
}
2010-09-23 06:56:23 +00:00
/************************************************************
*
* Tracing/Debugging
*
************************************************************/
2010-09-22 05:14:57 +00:00
uint8_t
readA()
{
return (isNodeHigh(a0) << 0) |
(isNodeHigh(a1) << 1) |
(isNodeHigh(a2) << 2) |
(isNodeHigh(a3) << 3) |
(isNodeHigh(a4) << 4) |
(isNodeHigh(a5) << 5) |
(isNodeHigh(a6) << 6) |
(isNodeHigh(a7) << 7);
}
uint8_t
readX()
{
return (isNodeHigh(x0) << 0) |
(isNodeHigh(x1) << 1) |
(isNodeHigh(x2) << 2) |
(isNodeHigh(x3) << 3) |
(isNodeHigh(x4) << 4) |
(isNodeHigh(x5) << 5) |
(isNodeHigh(x6) << 6) |
(isNodeHigh(x7) << 7);
}
uint8_t
readY()
{
return (isNodeHigh(y0) << 0) |
(isNodeHigh(y1) << 1) |
(isNodeHigh(y2) << 2) |
(isNodeHigh(y3) << 3) |
(isNodeHigh(y4) << 4) |
(isNodeHigh(y5) << 5) |
(isNodeHigh(y6) << 6) |
(isNodeHigh(y7) << 7);
}
uint8_t
readP()
{
return (isNodeHigh(p0) << 0) |
(isNodeHigh(p1) << 1) |
(isNodeHigh(p2) << 2) |
(isNodeHigh(p3) << 3) |
(isNodeHigh(p4) << 4) |
(isNodeHigh(p5) << 5) |
(isNodeHigh(p6) << 6) |
(isNodeHigh(p7) << 7);
}
2010-09-22 15:25:34 +00:00
uint8_t
readNOTIR()
{
return (isNodeHigh(notir0) << 0) |
(isNodeHigh(notir1) << 1) |
(isNodeHigh(notir2) << 2) |
(isNodeHigh(notir3) << 3) |
(isNodeHigh(notir4) << 4) |
(isNodeHigh(notir5) << 5) |
(isNodeHigh(notir6) << 6) |
(isNodeHigh(notir7) << 7);
}
2010-09-22 05:14:57 +00:00
uint8_t
readSP()
{
return (isNodeHigh(s0) << 0) |
(isNodeHigh(s1) << 1) |
(isNodeHigh(s2) << 2) |
(isNodeHigh(s3) << 3) |
(isNodeHigh(s4) << 4) |
(isNodeHigh(s5) << 5) |
(isNodeHigh(s6) << 6) |
(isNodeHigh(s7) << 7);
}
uint8_t
readPCL()
{
return (isNodeHigh(pcl0) << 0) |
(isNodeHigh(pcl1) << 1) |
(isNodeHigh(pcl2) << 2) |
(isNodeHigh(pcl3) << 3) |
(isNodeHigh(pcl4) << 4) |
(isNodeHigh(pcl5) << 5) |
(isNodeHigh(pcl6) << 6) |
(isNodeHigh(pcl7) << 7);
}
uint8_t
readPCH()
{
return (isNodeHigh(pch0) << 0) |
(isNodeHigh(pch1) << 1) |
(isNodeHigh(pch2) << 2) |
(isNodeHigh(pch3) << 3) |
(isNodeHigh(pch4) << 4) |
(isNodeHigh(pch5) << 5) |
(isNodeHigh(pch6) << 6) |
(isNodeHigh(pch7) << 7);
}
uint16_t
readPC()
{
return (readPCH() << 8) | readPCL();
2010-09-22 01:51:38 +00:00
}
void
chipStatus()
{
2010-09-22 15:25:34 +00:00
printf("halfcyc:%d phi0:%d AB:%04X D:%02X RnW:%d PC:%04X A:%02X X:%02X Y:%02X SP:%02X P:%02X IR:%02X\n",
2010-09-22 05:14:57 +00:00
cycle,
isNodeHigh(clk0),
readAddressBus(),
readDataBus(),
isNodeHigh(rw),
readPC(),
readA(),
readX(),
readY(),
readSP(),
2010-09-22 15:25:34 +00:00
readP(),
readNOTIR() ^ 0xFF);
2010-09-22 01:51:38 +00:00
}
2010-09-23 06:56:23 +00:00
/************************************************************
*
* Main CLock Loop
*
************************************************************/
2010-09-22 01:51:38 +00:00
void
halfStep()
{
2010-09-23 06:56:23 +00:00
BOOL clk = isNodeHigh(clk0);
setNode(clk0, !clk);
if (clk && isNodeHigh(rw))
writeDataBus(mRead(readAddressBus()));
if (!clk && !isNodeHigh(rw))
mWrite(readAddressBus(), readDataBus());
2010-09-22 01:51:38 +00:00
}
2010-09-23 06:56:23 +00:00
/************************************************************
*
2010-09-23 07:45:42 +00:00
* Interface to OS Library Code / Monitor
2010-09-23 06:56:23 +00:00
*
************************************************************/
2010-09-22 01:51:38 +00:00
void
2010-09-23 07:45:42 +00:00
init_monitor()
2010-09-22 01:51:38 +00:00
{
2010-09-23 07:45:42 +00:00
FILE *f;
f = fopen("cbmbasic.bin", "r");
fread(memory + 0xA000, 1, 17591, f);
fclose(f);
for (uint16_t addr = 0xFF90; addr < 0xFFF3; addr += 3) {
memory[addr+0] = 0x4C;
memory[addr+1] = 0x00;
memory[addr+2] = 0xF8;
2010-09-22 01:51:38 +00:00
}
2010-09-23 07:45:42 +00:00
memory[0xf000] = 0x20;
memory[0xf001] = 0x94;
memory[0xf002] = 0xE3;
memory[0xfffc] = 0x00;
memory[0xfffd] = 0xF0;
2010-09-22 01:51:38 +00:00
}
void
2010-09-23 07:45:42 +00:00
handle_monitor()
2010-09-22 01:51:38 +00:00
{
2010-09-22 15:25:34 +00:00
PC = readPC();
if (PC >= 0xFF90 && ((PC - 0xFF90) % 3 == 0) && isNodeHigh(clk0)) {
2010-09-22 15:25:34 +00:00
A = readA();
X = readX();
Y = readY();
S = readSP();
P = readP();
N = P >> 7;
Z = (P >> 1) & 1;
C = P & 1;
kernal_dispatch();
P &= 0x7C; // clear N, Z, C
P |= (N << 7) | (Z << 1) | C;
2010-09-22 15:25:34 +00:00
/*
LDA #P
PHA
LDA #A
LDX #X
LDY #Y
PLP
RTS
//XXX we could do RTI instead, but RTI is broken!
2010-09-22 15:25:34 +00:00
*/
memory[0xf800] = 0xA9;
memory[0xf801] = P;
memory[0xf802] = 0x48;
memory[0xf803] = 0xA9;
memory[0xf804] = A;
memory[0xf805] = 0xA2;
memory[0xf806] = X;
memory[0xf807] = 0xA0;
memory[0xf808] = Y;
memory[0xf809] = 0x28;
memory[0xf80a] = 0x60;
2010-09-22 15:25:34 +00:00
}
2010-09-22 01:51:38 +00:00
}
2010-09-23 07:45:42 +00:00
/************************************************************
*
* Initialization
*
************************************************************/
2010-09-22 01:51:38 +00:00
void
2010-09-23 07:45:42 +00:00
initChip()
2010-09-22 01:51:38 +00:00
{
2010-09-23 07:45:42 +00:00
for (nodenum_t nn = 0; nn < NODES; nn++)
nodes_state[nn] = STATE_FL;
nodes_state[ngnd] = STATE_GND;
nodes_state[npwr] = STATE_VCC;
for (transnum_t tn = 0; tn < TRANSISTORS; tn++)
set_transistors_on(tn, NO);
setLow(res);
setLow(clk0);
setHigh(rdy);
setLow(so);
setHigh(irq);
setHigh(nmi);
recalcAllNodes();
/* hold RESET for 8 cycles to finish executing instruction */
for (int i = 0; i < 16; i++)
setNode(clk0, !(i & 1));
setHigh(res);
cycle = 0;
2010-09-22 01:51:38 +00:00
}
void
2010-09-23 07:45:42 +00:00
step()
{
halfStep();
cycle++;
if (verbose)
chipStatus();
handle_monitor();
}
void
steps()
2010-09-22 01:51:38 +00:00
{
2010-09-22 05:14:57 +00:00
#ifdef DEBUG
printf("%s\n", __func__);
#endif
2010-09-23 07:45:42 +00:00
for (;;)
step();
2010-09-22 01:51:38 +00:00
}
void
setup()
{
setupNodesAndTransistors();
2010-09-22 01:51:38 +00:00
initChip();
2010-09-23 07:45:42 +00:00
init_monitor();
steps();
2010-09-22 01:51:38 +00:00
}
int
main()
{
setup();
return 0;
}