trunk/src/mame/video/c45.c
| r29457 | r29458 | |
| 46 | 46 | const device_type NAMCO_C45_ROAD = &device_creator<namco_c45_road_device>; |
| 47 | 47 | |
| 48 | 48 | |
| 49 | | const gfx_layout namco_c45_road_device::s_tile_layout = |
| 49 | const gfx_layout namco_c45_road_device::tilelayout = |
| 50 | 50 | { |
| 51 | 51 | ROAD_TILE_SIZE, ROAD_TILE_SIZE, |
| 52 | | ROAD_TILE_COUNT_MAX, |
| 52 | RGN_FRAC(1,1), |
| 53 | 53 | 2, |
| 54 | 54 | { 0, 8 }, |
| 55 | | {// x offset |
| 56 | | 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, |
| 57 | | 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 |
| 58 | | }, |
| 59 | | {// y offset |
| 60 | | 0x000,0x020,0x040,0x060,0x080,0x0a0,0x0c0,0x0e0, |
| 61 | | 0x100,0x120,0x140,0x160,0x180,0x1a0,0x1c0,0x1e0 |
| 62 | | }, |
| 55 | { STEP8(0, 1), STEP8(16, 1) }, |
| 56 | { STEP16(0, 32) }, |
| 63 | 57 | 0x200 // offset to next tile |
| 64 | 58 | }; |
| 65 | 59 | |
| 60 | |
| 61 | GFXDECODE_MEMBER( namco_c45_road_device::gfxinfo ) |
| 62 | GFXDECODE_DEVICE_RAM( "tileram", 0, tilelayout, 0xf00, 64 ) |
| 63 | GFXDECODE_END |
| 64 | |
| 65 | |
| 66 | DEVICE_ADDRESS_MAP_START(map, 16, namco_c45_road_device) |
| 67 | AM_RANGE(0x00000, 0x0ffff) AM_RAM_WRITE(tilemap_w) AM_SHARE("tmapram") |
| 68 | AM_RANGE(0x10000, 0x1f9ff) AM_RAM_WRITE(tileram_w) AM_SHARE("tileram") |
| 69 | AM_RANGE(0x1fa00, 0x1ffff) AM_RAM AM_SHARE("lineram") |
| 70 | ADDRESS_MAP_END |
| 71 | |
| 72 | |
| 66 | 73 | //------------------------------------------------- |
| 67 | 74 | // namco_c45_road_device -- constructor |
| 68 | 75 | //------------------------------------------------- |
| 69 | 76 | |
| 70 | 77 | namco_c45_road_device::namco_c45_road_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 71 | 78 | : device_t(mconfig, NAMCO_C45_ROAD, "Namco C45 Road", tag, owner, clock, "namco_c45_road", __FILE__), |
| 72 | | m_transparent_color(~0), |
| 73 | | m_tilemap(NULL), |
| 74 | | m_gfxdecode(*this, "gfxdecode"), |
| 75 | | m_palette(*this) |
| 79 | device_gfx_interface(mconfig, *this, gfxinfo), |
| 80 | device_memory_interface(mconfig, *this), |
| 81 | m_space_config("c45", ENDIANNESS_BIG, 16, 17, 0, address_map_delegate(FUNC(namco_c45_road_device::map), this)), |
| 82 | m_tmapram(*this, "tmapram"), |
| 83 | m_tileram(*this, "tileram"), |
| 84 | m_lineram(*this, "lineram"), |
| 85 | m_transparent_color(~0) |
| 76 | 86 | { |
| 77 | 87 | } |
| 78 | 88 | |
| 89 | |
| 90 | |
| 91 | // We need these trampolines for now because uplift_submaps() |
| 92 | // can't deal with address maps that contain RAM. |
| 93 | // We need to explicitly use device_memory_interface::space() |
| 94 | // because read/write handlers have a parameter called 'space' |
| 95 | |
| 79 | 96 | //------------------------------------------------- |
| 80 | | // read -- read from RAM |
| 97 | // read -- CPU read from our address space |
| 81 | 98 | //------------------------------------------------- |
| 82 | 99 | |
| 83 | 100 | READ16_MEMBER( namco_c45_road_device::read ) |
| 84 | 101 | { |
| 85 | | return m_ram[offset]; |
| 102 | return device_memory_interface::space().read_word(offset*2); |
| 86 | 103 | } |
| 87 | 104 | |
| 88 | 105 | |
| 89 | 106 | //------------------------------------------------- |
| 90 | | // write -- write to RAM |
| 107 | // write -- CPU write to our address space |
| 91 | 108 | //------------------------------------------------- |
| 92 | 109 | |
| 93 | 110 | WRITE16_MEMBER( namco_c45_road_device::write ) |
| 94 | 111 | { |
| 95 | | COMBINE_DATA(&m_ram[offset]); |
| 112 | device_memory_interface::space().write_word(offset*2, data, mem_mask); |
| 113 | } |
| 96 | 114 | |
| 97 | | // first half maps to the tilemap |
| 98 | | if (offset < 0x10000/2) |
| 99 | | m_tilemap->mark_tile_dirty(offset); |
| 100 | 115 | |
| 101 | | // second half maps to the gfx elements |
| 102 | | else |
| 103 | | { |
| 104 | | offset -= 0x10000/2; |
| 105 | | m_gfxdecode->gfx(0)->mark_dirty(offset / WORDS_PER_ROAD_TILE); |
| 106 | | } |
| 116 | //------------------------------------------------- |
| 117 | // tilemap_w -- write to tilemap RAM |
| 118 | //------------------------------------------------- |
| 119 | |
| 120 | WRITE16_MEMBER( namco_c45_road_device::tilemap_w ) |
| 121 | { |
| 122 | COMBINE_DATA(&m_tmapram[offset]); |
| 123 | m_tilemap->mark_tile_dirty(offset); |
| 107 | 124 | } |
| 108 | 125 | |
| 109 | 126 | |
| 110 | 127 | //------------------------------------------------- |
| 128 | // tileram_w -- write to tile RAM |
| 129 | //------------------------------------------------- |
| 130 | |
| 131 | WRITE16_MEMBER( namco_c45_road_device::tileram_w ) |
| 132 | { |
| 133 | COMBINE_DATA(&m_tileram[offset]); |
| 134 | gfx(0)->mark_dirty(offset / WORDS_PER_ROAD_TILE); |
| 135 | } |
| 136 | |
| 137 | |
| 138 | //------------------------------------------------- |
| 111 | 139 | // draw -- render to the target bitmap |
| 112 | 140 | //------------------------------------------------- |
| 113 | 141 | |
| r29457 | r29458 | |
| 115 | 143 | { |
| 116 | 144 | const UINT8 *clut = (const UINT8 *)memregion("clut")->base(); |
| 117 | 145 | bitmap_ind16 &source_bitmap = m_tilemap->pixmap(); |
| 118 | | unsigned yscroll = m_ram[0x1fdfe/2]; |
| 146 | unsigned yscroll = m_lineram[0x3fe/2]; |
| 119 | 147 | |
| 120 | 148 | // loop over scanlines |
| 121 | 149 | for (int y = cliprect.min_y; y <= cliprect.max_y; y++) |
| 122 | 150 | { |
| 123 | 151 | // skip if we are not the right priority |
| 124 | | int screenx = m_ram[0x1fa00/2 + y + 15]; |
| 152 | int screenx = m_lineram[y + 15]; |
| 125 | 153 | if (pri != ((screenx & 0xf000) >> 12)) |
| 126 | 154 | continue; |
| 127 | 155 | |
| 128 | 156 | // skip if we don't have a valid zoom factor |
| 129 | | unsigned zoomx = m_ram[0x1fe00/2 + y + 15] & 0x3ff; |
| 157 | unsigned zoomx = m_lineram[0x400/2 + y + 15] & 0x3ff; |
| 130 | 158 | if (zoomx == 0) |
| 131 | 159 | continue; |
| 132 | 160 | |
| 133 | 161 | // skip if we don't have a valid source increment |
| 134 | | unsigned sourcey = m_ram[0x1fc00/2 + y + 15] + yscroll; |
| 162 | unsigned sourcey = m_lineram[0x200/2 + y + 15] + yscroll; |
| 135 | 163 | const UINT16 *source_gfx = &source_bitmap.pix(sourcey & (ROAD_TILEMAP_HEIGHT - 1)); |
| 136 | 164 | unsigned dsourcex = (ROAD_TILEMAP_WIDTH << 16) / zoomx; |
| 137 | 165 | if (dsourcex == 0) |
| r29457 | r29458 | |
| 171 | 199 | while (numpixels-- > 0) |
| 172 | 200 | { |
| 173 | 201 | int pen = source_gfx[sourcex >> 16]; |
| 174 | | if (m_palette->pen_indirect(pen) != m_transparent_color) |
| 202 | if (palette()->pen_indirect(pen) != m_transparent_color) |
| 175 | 203 | { |
| 176 | 204 | if (clut != NULL) |
| 177 | 205 | pen = (pen & ~0xff) | clut[pen & 0xff]; |
| r29457 | r29458 | |
| 202 | 230 | |
| 203 | 231 | void namco_c45_road_device::device_start() |
| 204 | 232 | { |
| 205 | | if(!m_gfxdecode->started()) |
| 206 | | throw device_missing_dependencies(); |
| 207 | | |
| 208 | | // create a gfx_element describing the road graphics |
| 209 | | m_gfxdecode->set_gfx(0, global_alloc(gfx_element(m_palette, s_tile_layout, 0x10000 + (UINT8 *)&m_ram[0], NATIVE_ENDIAN_VALUE_LE_BE(8,0), 0x3f, 0xf00))); |
| 210 | | |
| 211 | 233 | // create a tilemap for the road |
| 212 | | m_tilemap = &machine().tilemap().create(m_gfxdecode, tilemap_get_info_delegate(FUNC(namco_c45_road_device::get_road_info), this), |
| 234 | m_tilemap = &machine().tilemap().create(*this, tilemap_get_info_delegate(FUNC(namco_c45_road_device::get_road_info), this), |
| 213 | 235 | TILEMAP_SCAN_ROWS, ROAD_TILE_SIZE, ROAD_TILE_SIZE, ROAD_COLS, ROAD_ROWS); |
| 214 | 236 | } |
| 215 | 237 | |
| 216 | | MACHINE_CONFIG_FRAGMENT( namco_c45_road ) |
| 217 | | MCFG_GFXDECODE_ADD("gfxdecode", "^palette", empty) // FIXME |
| 218 | | MACHINE_CONFIG_END |
| 219 | | //------------------------------------------------- |
| 220 | | // device_mconfig_additions - return a pointer to |
| 221 | | // the device's machine fragment |
| 222 | | //------------------------------------------------- |
| 223 | 238 | |
| 224 | | machine_config_constructor namco_c45_road_device::device_mconfig_additions() const |
| 225 | | { |
| 226 | | return MACHINE_CONFIG_NAME( namco_c45_road ); |
| 227 | | } |
| 228 | | |
| 229 | 239 | //------------------------------------------------- |
| 230 | | // device_stop -- device shutdown |
| 240 | // memory_space_config - return a description of |
| 241 | // any address spaces owned by this device |
| 231 | 242 | //------------------------------------------------- |
| 232 | 243 | |
| 233 | | void namco_c45_road_device::device_stop() |
| 244 | const address_space_config *namco_c45_road_device::memory_space_config(address_spacenum spacenum) const |
| 234 | 245 | { |
| 246 | return (spacenum == AS_0) ? &m_space_config : NULL; |
| 235 | 247 | } |
| 236 | 248 | |
| 237 | 249 | |
| r29457 | r29458 | |
| 243 | 255 | { |
| 244 | 256 | // ------xx xxxxxxxx tile number |
| 245 | 257 | // xxxxxx-- -------- palette select |
| 246 | | UINT16 data = m_ram[tile_index]; |
| 258 | UINT16 data = m_tmapram[tile_index]; |
| 247 | 259 | int tile = data & 0x3ff; |
| 248 | 260 | int color = data >> 10; |
| 249 | 261 | SET_TILE_INFO_MEMBER(0, tile, color, 0); |
| 250 | 262 | } |
| 251 | | |
| 252 | | //------------------------------------------------- |
| 253 | | // static_set_palette_tag: Set the tag of the |
| 254 | | // palette device |
| 255 | | //------------------------------------------------- |
| 256 | | |
| 257 | | void namco_c45_road_device::static_set_palette_tag(device_t &device, const char *tag) |
| 258 | | { |
| 259 | | downcast<namco_c45_road_device &>(device).m_palette.set_tag(tag); |
| 260 | | } |
trunk/src/mame/video/c45.h
| r29457 | r29458 | |
| 11 | 11 | #define MCFG_NAMCO_C45_ROAD_ADD(_tag) \ |
| 12 | 12 | MCFG_DEVICE_ADD(_tag, NAMCO_C45_ROAD, 0) |
| 13 | 13 | |
| 14 | | #define MCFG_NAMCO_C45_ROAD_PALETTE(_palette_tag) \ |
| 15 | | namco_c45_road_device::static_set_palette_tag(*device, "^" _palette_tag); |
| 16 | 14 | |
| 17 | | |
| 18 | 15 | //************************************************************************** |
| 19 | 16 | // TYPE DEFINITIONS |
| 20 | 17 | //************************************************************************** |
| r29457 | r29458 | |
| 22 | 19 | |
| 23 | 20 | // ======================> namco_c45_road_device |
| 24 | 21 | |
| 25 | | class namco_c45_road_device : public device_t |
| 22 | class namco_c45_road_device : public device_t, public device_gfx_interface, public device_memory_interface |
| 26 | 23 | { |
| 27 | 24 | // constants |
| 28 | 25 | static const int ROAD_COLS = 64; |
| r29457 | r29458 | |
| 30 | 27 | static const int ROAD_TILE_SIZE = 16; |
| 31 | 28 | static const int ROAD_TILEMAP_WIDTH = ROAD_TILE_SIZE * ROAD_COLS; |
| 32 | 29 | static const int ROAD_TILEMAP_HEIGHT = ROAD_TILE_SIZE * ROAD_ROWS; |
| 33 | | static const int ROAD_TILE_COUNT_MAX = 0xfa00 / 0x40; // 0x3e8 |
| 34 | 30 | static const int WORDS_PER_ROAD_TILE = 0x40/2; |
| 31 | static const gfx_layout tilelayout; |
| 35 | 32 | |
| 36 | 33 | public: |
| 37 | 34 | // construction/destruction |
| 38 | 35 | namco_c45_road_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 39 | 36 | |
| 40 | | static void static_set_palette_tag(device_t &device, const char *tag); |
| 37 | DECLARE_ADDRESS_MAP(map, 16); |
| 41 | 38 | |
| 42 | 39 | // read/write handlers |
| 43 | 40 | DECLARE_READ16_MEMBER( read ); |
| 44 | 41 | DECLARE_WRITE16_MEMBER( write ); |
| 45 | 42 | |
| 46 | | // optional information overrides |
| 47 | | virtual machine_config_constructor device_mconfig_additions() const; |
| 48 | | |
| 49 | 43 | // C45 Land (Road) Emulation |
| 50 | 44 | void set_transparent_color(pen_t pen) { m_transparent_color = pen; } |
| 51 | 45 | void draw(bitmap_ind16 &bitmap, const rectangle &cliprect, int pri); |
| r29457 | r29458 | |
| 53 | 47 | protected: |
| 54 | 48 | // device-level overrides |
| 55 | 49 | virtual void device_start(); |
| 56 | | virtual void device_stop(); |
| 50 | virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const; |
| 57 | 51 | |
| 52 | private: |
| 58 | 53 | // internal helpers |
| 54 | DECLARE_GFXDECODE_MEMBER(gfxinfo); |
| 55 | DECLARE_WRITE16_MEMBER( tilemap_w ); |
| 56 | DECLARE_WRITE16_MEMBER( tileram_w ); |
| 59 | 57 | TILE_GET_INFO_MEMBER( get_road_info ); |
| 60 | 58 | |
| 61 | 59 | // internal state |
| 62 | | pen_t m_transparent_color; |
| 63 | | tilemap_t * m_tilemap; |
| 64 | | UINT16 m_ram[0x20000/2]; // at 0x880000 in Final Lap; at 0xa00000 in Lucky&Wild |
| 65 | | |
| 66 | | static const gfx_layout s_tile_layout; |
| 67 | | required_device<gfxdecode_device> m_gfxdecode; |
| 68 | | required_device<palette_device> m_palette; |
| 60 | address_space_config m_space_config; |
| 61 | required_shared_ptr<UINT16> m_tmapram; |
| 62 | required_shared_ptr<UINT16> m_tileram; |
| 63 | required_shared_ptr<UINT16> m_lineram; |
| 64 | pen_t m_transparent_color; |
| 65 | tilemap_t * m_tilemap; |
| 69 | 66 | }; |
| 70 | 67 | |
| 71 | 68 | |
trunk/src/emu/memory.c
| r29457 | r29458 | |
| 1886 | 1886 | adjust_addresses(entry->m_bytestart, entry->m_byteend, entry->m_bytemask, entry->m_bytemirror); |
| 1887 | 1887 | |
| 1888 | 1888 | // if we have a share entry, add it to our map |
| 1889 | | if (entry->m_share != NULL) |
| 1889 | if (entry->m_sharetag != NULL) |
| 1890 | 1890 | { |
| 1891 | 1891 | // if we can't find it, add it to our map |
| 1892 | 1892 | astring fulltag; |
| 1893 | | if (manager().m_sharelist.find(device().siblingtag(fulltag, entry->m_share).cstr()) == NULL) |
| 1893 | if (manager().m_sharelist.find(entry->m_sharebase->subtag(fulltag, entry->m_sharetag).cstr()) == NULL) |
| 1894 | 1894 | { |
| 1895 | 1895 | VPRINTF(("Creating share '%s' of length 0x%X\n", fulltag.cstr(), entry->m_byteend + 1 - entry->m_bytestart)); |
| 1896 | 1896 | memory_share *share = global_alloc(memory_share(m_map->m_databits, entry->m_byteend + 1 - entry->m_bytestart, endianness())); |
| r29457 | r29458 | |
| 1910 | 1910 | } |
| 1911 | 1911 | |
| 1912 | 1912 | // validate adjusted addresses against implicit regions |
| 1913 | | if (entry->m_region != NULL && entry->m_share == NULL) |
| 1913 | if (entry->m_region != NULL && entry->m_sharetag == NULL) |
| 1914 | 1914 | { |
| 1915 | 1915 | // determine full tag |
| 1916 | 1916 | astring fulltag; |
| r29457 | r29458 | |
| 2224 | 2224 | for (address_map_entry *entry = m_map->m_entrylist.first(); entry != NULL; entry = entry->next()) |
| 2225 | 2225 | { |
| 2226 | 2226 | // if we haven't assigned this block yet, see if we have a mapped shared pointer for it |
| 2227 | | if (entry->m_memory == NULL && entry->m_share != NULL) |
| 2227 | if (entry->m_memory == NULL && entry->m_sharetag != NULL) |
| 2228 | 2228 | { |
| 2229 | 2229 | astring fulltag; |
| 2230 | | memory_share *share = manager().m_sharelist.find(device().siblingtag(fulltag, entry->m_share).cstr()); |
| 2230 | memory_share *share = manager().m_sharelist.find(entry->m_sharebase->subtag(fulltag, entry->m_sharetag).cstr()); |
| 2231 | 2231 | if (share != NULL && share->ptr() != NULL) |
| 2232 | 2232 | { |
| 2233 | 2233 | entry->m_memory = share->ptr(); |
| 2234 | | VPRINTF(("memory range %08X-%08X -> shared_ptr '%s' [%p]\n", entry->m_addrstart, entry->m_addrend, entry->m_share, entry->m_memory)); |
| 2234 | VPRINTF(("memory range %08X-%08X -> shared_ptr '%s' [%p]\n", entry->m_addrstart, entry->m_addrend, entry->m_sharetag, entry->m_memory)); |
| 2235 | 2235 | } |
| 2236 | 2236 | else |
| 2237 | 2237 | { |
| 2238 | | VPRINTF(("memory range %08X-%08X -> shared_ptr '%s' but not found\n", entry->m_addrstart, entry->m_addrend, entry->m_share)); |
| 2238 | VPRINTF(("memory range %08X-%08X -> shared_ptr '%s' but not found\n", entry->m_addrstart, entry->m_addrend, entry->m_sharetag)); |
| 2239 | 2239 | } |
| 2240 | 2240 | } |
| 2241 | 2241 | |
| r29457 | r29458 | |
| 2247 | 2247 | } |
| 2248 | 2248 | |
| 2249 | 2249 | // if we're the first match on a shared pointer, assign it now |
| 2250 | | if (entry->m_memory != NULL && entry->m_share != NULL) |
| 2250 | if (entry->m_memory != NULL && entry->m_sharetag != NULL) |
| 2251 | 2251 | { |
| 2252 | 2252 | astring fulltag; |
| 2253 | | memory_share *share = manager().m_sharelist.find(device().siblingtag(fulltag, entry->m_share).cstr()); |
| 2253 | memory_share *share = manager().m_sharelist.find(entry->m_sharebase->subtag(fulltag, entry->m_sharetag).cstr()); |
| 2254 | 2254 | if (share != NULL && share->ptr() == NULL) |
| 2255 | 2255 | { |
| 2256 | 2256 | share->set_ptr(entry->m_memory); |
| 2257 | | VPRINTF(("setting shared_ptr '%s' = %p\n", entry->m_share, entry->m_memory)); |
| 2257 | VPRINTF(("setting shared_ptr '%s' = %p\n", entry->m_sharetag, entry->m_memory)); |
| 2258 | 2258 | } |
| 2259 | 2259 | } |
| 2260 | 2260 | |
| r29457 | r29458 | |
| 2801 | 2801 | bool address_space::needs_backing_store(const address_map_entry *entry) |
| 2802 | 2802 | { |
| 2803 | 2803 | // if we are sharing, and we don't have a pointer yet, create one |
| 2804 | | if (entry->m_share != NULL) |
| 2804 | if (entry->m_sharetag != NULL) |
| 2805 | 2805 | { |
| 2806 | 2806 | astring fulltag; |
| 2807 | | memory_share *share = manager().m_sharelist.find(device().siblingtag(fulltag, entry->m_share).cstr()); |
| 2807 | memory_share *share = manager().m_sharelist.find(entry->m_sharebase->subtag(fulltag, entry->m_sharetag).cstr()); |
| 2808 | 2808 | if (share != NULL && share->ptr() == NULL) |
| 2809 | 2809 | return true; |
| 2810 | 2810 | } |