1 /*
2 * SPDX-License-Identifier: GPL-2.0-or-later
3 *
4 * Copyright (C) 2019-2021 The DOSBox Staging Team
5 * Copyright (C) 2002-2021 The DOSBox Team
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21
22 #ifndef DOSBOX_MEM_H
23 #define DOSBOX_MEM_H
24
25 #include "dosbox.h"
26
27 #include "mem_host.h"
28 #include "mem_unaligned.h"
29 #include "types.h"
30
31 typedef uint32_t PhysPt;
32 typedef uint8_t *HostPt;
33 typedef uint32_t RealPt;
34 typedef int32_t MemHandle;
35
36 #define MEM_PAGESIZE 4096
37
38 extern HostPt MemBase;
39 HostPt GetMemBase();
40
41 bool MEM_A20_Enabled();
42 void MEM_A20_Enable(bool enable);
43
44 /* Memory management / EMS mapping */
45 HostPt MEM_GetBlockPage();
46 Bitu MEM_FreeTotal(); // Free 4 KiB pages
47 Bitu MEM_FreeLargest(); // Largest free 4 KiB pages block
48 Bitu MEM_TotalPages(); // Total amount of 4 KiB pages
49 Bitu MEM_AllocatedPages(MemHandle handle); // amount of allocated pages of handle
50 MemHandle MEM_AllocatePages(Bitu pages, bool sequence);
51 MemHandle MEM_GetNextFreePage();
52 PhysPt MEM_AllocatePage();
53 void MEM_ReleasePages(MemHandle handle);
54 bool MEM_ReAllocatePages(MemHandle &handle, Bitu pages, bool sequence);
55 void MEM_RemoveEMSPageFrame();
56 void MEM_PreparePCJRCartRom();
57
58 MemHandle MEM_NextHandle(MemHandle handle);
59 MemHandle MEM_NextHandleAt(MemHandle handle, Bitu where);
60
var_write(uint8_t * var,uint8_t val)61 static inline void var_write(uint8_t *var, uint8_t val)
62 {
63 host_writeb(var, val);
64 }
65
var_write(uint16_t * var,uint16_t val)66 static inline void var_write(uint16_t *var, uint16_t val)
67 {
68 host_writew((HostPt)var, val);
69 }
70
var_write(uint32_t * var,uint32_t val)71 static inline void var_write(uint32_t *var, uint32_t val)
72 {
73 host_writed((HostPt)var, val);
74 }
75
var_read(uint16_t * var)76 static inline uint16_t var_read(uint16_t *var)
77 {
78 return host_readw((HostPt)var);
79 }
80
var_read(uint32_t * var)81 static inline uint32_t var_read(uint32_t *var)
82 {
83 return host_readd((HostPt)var);
84 }
85
86 /* The Following six functions are slower but they recognize the paged memory
87 * system */
88
89 uint8_t mem_readb(PhysPt pt);
90 uint16_t mem_readw(PhysPt pt);
91 uint32_t mem_readd(PhysPt pt);
92
93 void mem_writeb(PhysPt pt, uint8_t val);
94 void mem_writew(PhysPt pt, uint16_t val);
95 void mem_writed(PhysPt pt, uint32_t val);
96
phys_writeb(PhysPt addr,uint8_t val)97 static inline void phys_writeb(PhysPt addr, uint8_t val)
98 {
99 host_writeb(MemBase + addr, val);
100 }
101
phys_writew(PhysPt addr,uint16_t val)102 static inline void phys_writew(PhysPt addr, uint16_t val)
103 {
104 host_writew(MemBase + addr, val);
105 }
106
phys_writed(PhysPt addr,uint32_t val)107 static inline void phys_writed(PhysPt addr, uint32_t val)
108 {
109 host_writed(MemBase + addr, val);
110 }
111
phys_readb(PhysPt addr)112 static inline uint8_t phys_readb(PhysPt addr)
113 {
114 return host_readb(MemBase + addr);
115 }
116
phys_readw(PhysPt addr)117 static inline uint16_t phys_readw(PhysPt addr)
118 {
119 return host_readw(MemBase + addr);
120 }
121
phys_readd(PhysPt addr)122 static inline uint32_t phys_readd(PhysPt addr)
123 {
124 return host_readd(MemBase + addr);
125 }
126
127 /* These don't check for alignment, better be sure it's correct */
128
129 void MEM_BlockWrite(PhysPt pt, const void *data, size_t size);
130 void MEM_BlockRead(PhysPt pt, void *data, Bitu size);
131 void MEM_BlockCopy(PhysPt dest, PhysPt src, Bitu size);
132 void MEM_StrCopy(PhysPt pt, char *data, Bitu size);
133
134 void mem_memcpy(PhysPt dest, PhysPt src, Bitu size);
135 Bitu mem_strlen(PhysPt pt);
136 void mem_strcpy(PhysPt dest, PhysPt src);
137
138 /* The following functions are all shortcuts to the above functions using
139 * physical addressing */
140
real_readb(uint16_t seg,uint16_t off)141 static inline uint8_t real_readb(uint16_t seg, uint16_t off)
142 {
143 const auto base = static_cast<uint32_t>(seg << 4);
144 return mem_readb(base + off);
145 }
146
real_readw(uint16_t seg,uint16_t off)147 static inline uint16_t real_readw(uint16_t seg, uint16_t off)
148 {
149 const auto base = static_cast<uint32_t>(seg << 4);
150 return mem_readw(base + off);
151 }
152
real_readd(uint16_t seg,uint16_t off)153 static inline uint32_t real_readd(uint16_t seg, uint16_t off)
154 {
155 const auto base = static_cast<uint32_t>(seg << 4);
156 return mem_readd(base + off);
157 }
158
real_writeb(uint16_t seg,uint16_t off,uint8_t val)159 static inline void real_writeb(uint16_t seg, uint16_t off, uint8_t val)
160 {
161 const auto base = static_cast<uint32_t>(seg << 4);
162 mem_writeb(base + off, val);
163 }
164
real_writew(uint16_t seg,uint16_t off,uint16_t val)165 static inline void real_writew(uint16_t seg, uint16_t off, uint16_t val)
166 {
167 const auto base = static_cast<uint32_t>(seg << 4);
168 mem_writew(base + off, val);
169 }
170
real_writed(uint16_t seg,uint16_t off,uint32_t val)171 static inline void real_writed(uint16_t seg, uint16_t off, uint32_t val)
172 {
173 const auto base = static_cast<uint32_t>(seg << 4);
174 mem_writed(base + off, val);
175 }
176
RealSeg(RealPt pt)177 static inline uint16_t RealSeg(RealPt pt)
178 {
179 return pt >> 16;
180 }
181
RealOff(RealPt pt)182 static inline uint16_t RealOff(RealPt pt)
183 {
184 return static_cast<uint16_t>(pt & 0xffff);
185 }
186
Real2Phys(RealPt pt)187 static inline PhysPt Real2Phys(RealPt pt)
188 {
189 const auto base = static_cast<uint32_t>(RealSeg(pt) << 4);
190 return base + RealOff(pt);
191 }
192
PhysMake(uint16_t seg,uint16_t off)193 static inline PhysPt PhysMake(uint16_t seg, uint16_t off)
194 {
195 const auto base = static_cast<uint32_t>(seg << 4);
196 return base + off;
197 }
198
RealMake(uint16_t seg,uint16_t off)199 static inline RealPt RealMake(uint16_t seg, uint16_t off)
200 {
201 const auto base = static_cast<uint32_t>(seg << 16);
202 return base + off;
203 }
204
RealSetVec(uint8_t vec,RealPt pt)205 static inline void RealSetVec(uint8_t vec, RealPt pt)
206 {
207 const auto target = static_cast<uint16_t>(vec << 2);
208 mem_writed(target, pt);
209 }
210
211 // TODO: consider dropping this function. The three places where it's called all
212 // ignore the 3rd updated parameter.
RealSetVec(uint8_t vec,RealPt pt,RealPt & old)213 static inline void RealSetVec(uint8_t vec, RealPt pt, RealPt &old)
214 {
215 const auto target = static_cast<uint16_t>(vec << 2);
216 old = mem_readd(target);
217 mem_writed(target, pt);
218 }
219
RealGetVec(uint8_t vec)220 static inline RealPt RealGetVec(uint8_t vec)
221 {
222 const auto target = static_cast<uint16_t>(vec << 2);
223 return mem_readd(target);
224 }
225
226 #endif
227