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