1 /* memory.h: memory access routines
2    Copyright (c) 2003-2011 Philip Kendall
3 
4    $Id: memory.h 4724 2012-07-08 13:38:21Z fredm $
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License along
17    with this program; if not, write to the Free Software Foundation, Inc.,
18    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 
20    Author contact information:
21 
22    E-mail: philip-fuse@shadowmagic.org.uk
23 
24 */
25 
26 #ifndef FUSE_MEMORY_H
27 #define FUSE_MEMORY_H
28 
29 #include <libspectrum.h>
30 
31 /* Register a new memory source */
32 int memory_source_register( const char *description );
33 
34 /* Get the description for a given source */
35 const char *memory_source_description( int source );
36 
37 /* Get the source for a given description */
38 int memory_source_find( const char *description );
39 
40 /* Pre-created memory sources */
41 extern int memory_source_rom; /* System ROM */
42 extern int memory_source_ram; /* System RAM */
43 extern int memory_source_dock; /* Timex DOCK */
44 extern int memory_source_exrom; /* Timex EXROM */
45 extern int memory_source_any; /* Used by the debugger to signify an absolute address */
46 extern int memory_source_none; /* No memory attached here */
47 
48 typedef struct memory_page {
49 
50   libspectrum_byte *page;	/* The data for this page */
51   int writable;			/* Can we write to this data? */
52   int contended;		/* Are reads/writes to this page contended? */
53 
54   int source;	                /* Where did this page come from? */
55   int save_to_snapshot;         /* Set if this page should be saved snapshots
56                                    (set only if this page would not normally be
57                                     saved; things like RAM are always saved) */
58 
59   int page_num;			/* Which page from the source */
60   libspectrum_word offset;	/* How far into the page this chunk starts */
61 
62 } memory_page;
63 
64 /* A memory page will be 1 << (this many) bytes in size
65    ie 12 => 4 Kb, 13 => 8 Kb, 14 => 16 Kb
66  */
67 #define MEMORY_PAGE_SIZE_LOGARITHM 12
68 
69 /* The actual size of a memory page */
70 #define MEMORY_PAGE_SIZE ( 1 << MEMORY_PAGE_SIZE_LOGARITHM )
71 
72 /* The mask to use to select the bits within a page */
73 #define MEMORY_PAGE_SIZE_MASK ( MEMORY_PAGE_SIZE - 1 )
74 
75 /* The number of memory pages in 64K
76    This calculation is equivalent to 2^16 / MEMORY_PAGE_SIZE */
77 #define MEMORY_PAGES_IN_64K ( 1 << ( 16 - MEMORY_PAGE_SIZE_LOGARITHM ) )
78 
79 /* The number of memory pages in 16K */
80 #define MEMORY_PAGES_IN_16K ( 1 << ( 14 - MEMORY_PAGE_SIZE_LOGARITHM ) )
81 
82 /* The number of memory pages in 8K */
83 #define MEMORY_PAGES_IN_8K ( 1 << ( 13 - MEMORY_PAGE_SIZE_LOGARITHM ) )
84 
85 /* The number of memory pages in 4K */
86 #define MEMORY_PAGES_IN_4K ( 1 << ( 12 - MEMORY_PAGE_SIZE_LOGARITHM ) )
87 
88 /* Each RAM chunk accessible by the Z80 */
89 extern memory_page memory_map_read[MEMORY_PAGES_IN_64K];
90 extern memory_page memory_map_write[MEMORY_PAGES_IN_64K];
91 
92 /* The number of 16Kb RAM pages we support: 1040 Kb needed for the Pentagon 1024 */
93 #define SPECTRUM_RAM_PAGES 65
94 
95 /* The maximum number of 16Kb ROMs we support */
96 #define SPECTRUM_ROM_PAGES 4
97 
98 extern memory_page memory_map_ram[SPECTRUM_RAM_PAGES * MEMORY_PAGES_IN_16K];
99 extern memory_page memory_map_rom[SPECTRUM_ROM_PAGES * MEMORY_PAGES_IN_16K];
100 
101 /* Which RAM page contains the current screen */
102 extern int memory_current_screen;
103 
104 /* Which bits to look at when working out where the screen is */
105 extern libspectrum_word memory_screen_mask;
106 
107 void memory_init( void );
108 void memory_end( void );
109 libspectrum_byte *memory_pool_allocate( size_t length );
110 libspectrum_byte *memory_pool_allocate_persistent( size_t length,
111                                                    int persistent );
112 void memory_pool_free( void );
113 
114 /* Map in alternate bank if ROMCS is set */
115 void memory_romcs_map( void );
116 
117 /* Have we loaded any custom ROMs? */
118 int memory_custom_rom( void );
119 
120 /* Reset any memory configuration that may have changed in the machine
121    configuration */
122 void memory_reset( void );
123 
124 /* Set contention for 16K of RAM */
125 void memory_ram_set_16k_contention( int page_num, int contended );
126 
127 /* Map 16K of memory */
128 void memory_map_16k( libspectrum_word address, memory_page source[],
129   int page_num );
130 
131 /* Map 8K of memory */
132 void memory_map_8k( libspectrum_word address, memory_page source[],
133   int page_num );
134 
135 /* Map one page of memory */
136 void memory_map_page( memory_page *source[], int page_num );
137 
138 /* Page in from /ROMCS */
139 void memory_map_romcs( memory_page source[] );
140 
141 /* Page in 8K from /ROMCS */
142 void memory_map_romcs_8k( libspectrum_word address, memory_page source[] );
143 
144 /* Page in 4K from /ROMCS */
145 void memory_map_romcs_4k( libspectrum_word address, memory_page source[] );
146 
147 libspectrum_byte readbyte( libspectrum_word address );
148 
149 /* Use a macro for performance in the main core, but a function for
150    flexibility in the core tester */
151 
152 #ifndef CORETEST
153 
154 #define readbyte_internal( address ) \
155   memory_map_read[ (libspectrum_word)(address) >> MEMORY_PAGE_SIZE_LOGARITHM ].page[ (address) & MEMORY_PAGE_SIZE_MASK ]
156 
157 #else				/* #ifndef CORETEST */
158 
159 libspectrum_byte readbyte_internal( libspectrum_word address );
160 
161 #endif				/* #ifndef CORETEST */
162 
163 void writebyte( libspectrum_word address, libspectrum_byte b );
164 void writebyte_internal( libspectrum_word address, libspectrum_byte b );
165 
166 typedef void (*memory_display_dirty_fn)( libspectrum_word address,
167                                          libspectrum_byte b );
168 extern memory_display_dirty_fn memory_display_dirty;
169 
170 void memory_display_dirty_sinclair( libspectrum_word address,
171                                     libspectrum_byte b );
172 void memory_display_dirty_pentagon_16_col( libspectrum_word address,
173                                            libspectrum_byte b );
174 
175 #endif				/* #ifndef FUSE_MEMORY_H */
176