1 /*
2  * Z80SIM  -  a Z80-CPU simulator
3  *
4  * Copyright (C) 2016-2019 by Udo Munk
5  *
6  * This module implements memory management for an Altair 8800 system
7  *
8  * History:
9  * 22-NOV-2016 stuff moved to here and implemented as inline functions
10  * 02-FEB-2017 initialise ROM with 0xff
11  * 13-JUN-2017 added Tarbell bootstrap ROM
12  * 16-AUG-2017 overworked memrdr()
13  * 07-MAY-2018 added memory configuratione needed by apple monitor
14  * 11-JUN-2018 fixed bug in Tarbell ROM mapping
15  * 21-AUG-2018 improved memory configuration
16  ' 04-NOV-2019 add functions for direct memory access
17  */
18 
19 extern void init_memory(void), init_rom(void);
20 extern int wait_step(void);
21 extern void wait_int_step(void);
22 extern BYTE memory[], mem_wp;
23 extern int p_tab[];
24 extern BYTE tarbell_rom[];
25 extern int tarbell_rom_enabled, tarbell_rom_active;
26 
27 #define MEM_RW		0	/* memory is readable and writeable */
28 #define MEM_RO		1	/* memory is read-only */
29 #define MEM_WPROT	2	/* memory is write protected */
30 #define MEM_NONE	3	/* no memory available */
31 
32 /*
33  * configuration for MAXSEG memory segments
34  */
35 #define MAXSEG	6
36 
37 struct memmap {
38 	int type;	/* type of memory pages */
39 	BYTE spage;	/* start page of segment */
40 	BYTE size;	/* size of segment in pages */
41 };
42 
43 extern struct memmap memconf[MAXSEG];
44 
45 /*
46  * memory access for the CPU cores
47  */
memwrt(WORD addr,BYTE data)48 static inline void memwrt(WORD addr, BYTE data)
49 {
50 	cpu_bus &= ~(CPU_WO | CPU_MEMR);
51 
52 	fp_clock++;
53 	fp_led_address = addr;
54 	fp_led_data = 0xff;
55 	fp_sampleData();
56 	wait_step();
57 
58 	if (p_tab[addr >> 8] == MEM_RW) {
59 		memory[addr] = data;
60 		mem_wp = 0;
61 	}
62 }
63 
memrdr(WORD addr)64 static inline BYTE memrdr(WORD addr)
65 {
66 	register BYTE data;
67 
68 	if (tarbell_rom_active && tarbell_rom_enabled) {
69 		if (addr <= 0x001f) {
70 			data = tarbell_rom[addr];
71 		} else {
72 			if (p_tab[addr >> 8] != MEM_NONE)
73 				data = memory[addr];
74 			else
75 				data = 0xff;
76 			tarbell_rom_active = 0;
77 		}
78 	} else {
79 		if (p_tab[addr >> 8] != MEM_NONE)
80 			data = memory[addr];
81 		else
82 			data = 0xff;
83 	}
84 
85 	cpu_bus |= CPU_WO | CPU_MEMR;
86 
87 	fp_clock++;
88 	fp_led_address = addr;
89 	fp_led_data = data;
90 	fp_sampleData();
91 	wait_step();
92 
93 	return(data);
94 }
95 
96 /*
97  * memory access for DMA devices which request bus from CPU
98  */
dma_read(WORD addr)99 static inline BYTE dma_read(WORD addr)
100 {
101 	if (tarbell_rom_active && tarbell_rom_enabled) {
102 		if (addr <= 0x001f)
103 			return(tarbell_rom[addr]);
104 		else
105 			tarbell_rom_active = 0;
106 	}
107 
108 	if (p_tab[addr >> 8] != MEM_NONE)
109 		return(memory[addr]);
110 	else
111 		return(0xff);
112 }
113 
dma_write(WORD addr,BYTE data)114 static inline void dma_write(WORD addr, BYTE data)
115 {
116 	if (p_tab[addr >> 8] == MEM_RW)
117 		memory[addr] = data;
118 }
119 
120 /*
121  * direct memory access for simulation frame, video logic, etc.
122  */
getmem(WORD addr)123 static inline BYTE getmem(WORD addr)
124 {
125 	if (tarbell_rom_active && tarbell_rom_enabled) {
126 		if (addr <= 0x001f)
127 			return(tarbell_rom[addr]);
128 	}
129 
130 	if (p_tab[addr >> 8] != MEM_NONE)
131 		return(memory[addr]);
132 	else
133 		return(0xff);
134 }
135 
putmem(WORD addr,BYTE data)136 static inline void putmem(WORD addr, BYTE data)
137 {
138 	memory[addr] = data;
139 }
140 
141 /*
142  * memory read for frontpanel logic
143  */
fp_read(WORD addr)144 static inline BYTE fp_read(WORD addr)
145 {
146 	if (tarbell_rom_active && tarbell_rom_enabled) {
147 		if (addr <= 0x001f)
148 			return(tarbell_rom[addr]);
149 		else
150 			tarbell_rom_active = 0;
151 	}
152 
153 	if (p_tab[addr >> 8] != MEM_NONE)
154 		return(memory[addr]);
155 	else
156 		return(0xff);
157 }
158 
159 /*
160  * return memory base pointer for the simulation frame
161  */
mem_base(void)162 static inline BYTE *mem_base(void)
163 {
164 	return(&memory[0]);
165 }
166