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