1 /*****************************************************************************/
5 /* Memory subsystem for the 6502 simulator */
9 /* (C) 2002 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@cc65.org */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
49 /*****************************************************************************/
51 /*****************************************************************************/
55 static void MemWrite (unsigned Addr, unsigned char Val);
56 /* Write one byte to the memory cell */
58 static unsigned char MemRead (unsigned Attr);
59 /* Read one memory cell */
63 /*****************************************************************************/
65 /*****************************************************************************/
70 #define RA_READFUNC_MASK 0x000F /* Up to 16 read functions */
71 #define RA_WRITEFUNC_MASK 0x00F0 /* Up to 16 write functions */
72 #define RA_INITIALIZED 0x0100 /* Memory cell is initialized */
73 #define RA_WPROT 0x0200 /* Memory cell is write protected */
75 /* Defines reader and writer functions */
76 #define RA_READFUNC_SHIFT 0
77 #define RA_WRITEFUNC_SHIFT 4
78 #define RA_READFUNC_MAX 16
79 #define RA_WRITEFUNC_MAX 16
81 /* Read/write function declarations */
82 typedef unsigned char (*ReadFunc) (unsigned Addr);
83 typedef void (*WriteFunc) (unsigned Addr, unsigned char Val);
84 static Collection ReadFuncs = STATIC_COLLECTION_INITIALIZER;
85 static Collection WriteFuncs = STATIC_COLLECTION_INITIALIZER;
87 /* Memory attributes and the memory */
88 static unsigned short MemAttr[0x10000];
89 static unsigned char Mem[0x10000];
93 /*****************************************************************************/
94 /* Internal functions */
95 /*****************************************************************************/
99 static void MemWrite (unsigned Addr, unsigned char Val)
100 /* Write one byte to the memory cell */
102 if (MemAttr[Addr] & RA_WPROT) {
103 Warning ("Writing to write protected memory at $%04X", Addr);
106 MemAttr[Addr] |= RA_INITIALIZED;
111 static unsigned char MemRead (unsigned Addr)
112 /* Read one memory cell */
114 if ((MemAttr[Addr] & RA_INITIALIZED) == 0) {
115 /* We're reading a memory cell that was never written */
116 Warning ("Reading from uninitialized memory at $%04X", Addr);
123 /*****************************************************************************/
125 /*****************************************************************************/
129 void MemWriteByte (unsigned Addr, unsigned char Val)
130 /* Write a byte to a memory location */
132 /* Get the writer function */
133 unsigned WI = (MemAttr[Addr] & RA_WRITEFUNC_MASK) >> RA_WRITEFUNC_SHIFT;
134 WriteFunc WF = CollAt (&WriteFuncs, WI);
136 /* Call the writer function */
142 unsigned char MemReadByte (unsigned Addr)
143 /* Read a byte from a memory location */
145 /* Get the reader function */
146 unsigned RI = (MemAttr[Addr] & RA_READFUNC_MASK) >> RA_READFUNC_SHIFT;
147 ReadFunc RF = CollAt (&ReadFuncs, RI);
149 /* Call the reader function */
155 unsigned MemReadWord (unsigned Addr)
156 /* Read a word from a memory location */
158 unsigned W = MemReadByte (Addr++);
159 return (W | (MemReadByte (Addr) << 8));
164 unsigned MemReadZPWord (unsigned char Addr)
165 /* Read a word from the zero page. This function differs from ReadMemW in that
166 * the read will always be in the zero page, even in case of an address
170 unsigned W = MemReadByte (Addr++);
171 return (W | (MemReadByte (Addr) << 8));
176 void MemLoad (const char* Filename, unsigned Addr, unsigned Size)
177 /* Load the contents of the given file into the RAM at the given address.
178 * If Size is not zero, we will read exactly Size bytes from the file and
179 * consider it an error if this is not possible. The memory attributes
180 * for the range is set to initialized.
183 unsigned BytesToRead;
188 FILE* F = fopen (Filename, "rb");
190 Error ("Cannot open `%s': %s", Filename, strerror (errno));
193 /* Set the number of bytes to read */
194 BytesToRead = 0x10000 - Addr;
196 CHECK (Size <= BytesToRead); /* Must not exceed RAM */
200 /* Read data from the file */
201 BytesRead = fread (Mem + Addr, 1, BytesToRead, F);
203 Error ("Error reading from `%s': %s", Filename, strerror (errno));
205 if (Size > 0 && BytesRead != Size) {
206 Error ("Cannot read %u bytes from `%s'", Size, Filename);
209 /* Close the file. Ignore errors, we were just reading. */
212 /* Set the memory attribute for the range to initialized */
213 for (I = 0; I < BytesRead; ++I) {
214 MemAttr[Addr+I] |= RA_INITIALIZED;
221 /* Initialize the memory subsystem */
225 /* Clear the memory and it's attributes. Writing zeroes to the
226 * attribute array will cause any special flags to be reset and
227 * the default read and write functions to be used.
229 for (I = 0; I < sizeof (Mem) / sizeof (Mem[0]); ++I) {
232 for (I = 0; I < sizeof (MemAttr) / sizeof (MemAttr[0]); ++I) {
236 /* Add the default reader and writer functions to the collection */
237 CollAppend (&ReadFuncs, MemRead);
238 CollAppend (&WriteFuncs, MemWrite);
240 MemWriteByte (0xFFFC, 0x00);
241 MemWriteByte (0xFFFD, 0x02);