trunk/src/mame/machine/snes7110.c
| r20880 | r20881 | |
| 15 | 15 | ***************************************************************************/ |
| 16 | 16 | |
| 17 | 17 | |
| 18 | | static const UINT32 spc7110_decomp_buffer_size = 64; |
| 18 | #define SPC7110_DECOMP_BUFFER_SIZE 64 |
| 19 | 19 | |
| 20 | 20 | static const UINT8 spc7110_evolution_table[53][4] = |
| 21 | 21 | { |
| r20880 | r20881 | |
| 118 | 118 | { 31, 31 }, |
| 119 | 119 | }; |
| 120 | 120 | |
| 121 | | struct SPC7110Decomp |
| 121 | class SPC7110Decomp |
| 122 | 122 | { |
| 123 | | running_machine &machine() const { assert(m_machine != NULL); return *m_machine; } |
| 123 | public: |
| 124 | SPC7110Decomp(running_machine &machine, UINT32 size); |
| 124 | 125 | |
| 125 | | running_machine *m_machine; |
| 126 | running_machine &machine() const { return m_machine; } |
| 126 | 127 | |
| 127 | | UINT32 decomp_mode; |
| 128 | | UINT32 decomp_offset; |
| 128 | void init(running_machine &machine, UINT8 *ROM, UINT32 mode, UINT32 offset, UINT32 index); |
| 129 | void reset(); |
| 130 | |
| 131 | UINT8 read(UINT8 *ROM); |
| 132 | void write(UINT8 data); |
| 133 | void mode0(UINT8 init, UINT8 *ROM); |
| 134 | void mode1(UINT8 init, UINT8 *ROM); |
| 135 | void mode2(UINT8 init, UINT8 *ROM); |
| 129 | 136 | |
| 130 | | UINT8 *decomp_buffer; |
| 131 | | UINT32 decomp_buffer_rdoffset; |
| 132 | | UINT32 decomp_buffer_wroffset; |
| 133 | | UINT32 decomp_buffer_length; |
| 137 | UINT8 dataread(UINT8 *ROM); |
| 138 | UINT8 probability(UINT32 n); |
| 139 | UINT8 next_lps(UINT32 n); |
| 140 | UINT8 next_mps(UINT32 n); |
| 141 | UINT8 toggle_invert(UINT32 n); |
| 142 | UINT32 morton_2x8(UINT32 data); |
| 143 | UINT32 morton_4x8(UINT32 data); |
| 134 | 144 | |
| 145 | UINT32 m_decomp_mode; |
| 146 | UINT32 m_decomp_offset; |
| 147 | |
| 148 | UINT8 *m_decomp_buffer; |
| 149 | UINT32 m_decomp_buffer_rdoffset; |
| 150 | UINT32 m_decomp_buffer_wroffset; |
| 151 | UINT32 m_decomp_buffer_length; |
| 152 | |
| 135 | 153 | struct ContextState |
| 136 | 154 | { |
| 137 | 155 | UINT8 index; |
| 138 | 156 | UINT8 invert; |
| 139 | | } context[32]; |
| 157 | } m_context[32]; |
| 140 | 158 | |
| 141 | | UINT32 morton16[2][256]; |
| 142 | | UINT32 morton32[4][256]; |
| 159 | UINT32 m_morton16[2][256]; |
| 160 | UINT32 m_morton32[4][256]; |
| 143 | 161 | |
| 144 | | UINT32 rom_size; |
| 162 | |
| 163 | private: |
| 164 | running_machine& m_machine; |
| 165 | UINT32 m_rom_size; |
| 145 | 166 | }; |
| 146 | 167 | |
| 147 | | static SPC7110Decomp* SPC7110Decomp_ctor(running_machine &machine, UINT32 size); |
| 148 | | static void SPC7110Decomp_reset(SPC7110Decomp *thisptr); |
| 149 | | static void SPC7110Decomp_init(SPC7110Decomp *thisptr, running_machine &machine, UINT32 mode, UINT32 offset, UINT32 index); |
| 150 | | static UINT8 SPC7110Decomp_read(SPC7110Decomp *thisptr); |
| 151 | | static void SPC7110Decomp_write(SPC7110Decomp *thisptr, UINT8 data); |
| 152 | | static UINT8 SPC7110Decomp_dataread(SPC7110Decomp *thisptr); |
| 153 | | static void SPC7110Decomp_mode0(SPC7110Decomp *thisptr, UINT8 init); |
| 154 | | static void SPC7110Decomp_mode1(SPC7110Decomp *thisptr, UINT8 init); |
| 155 | | static void SPC7110Decomp_mode2(SPC7110Decomp *thisptr, UINT8 init); |
| 156 | | static UINT8 SPC7110Decomp_probability(SPC7110Decomp *thisptr, UINT32 n); |
| 157 | | static UINT8 SPC7110Decomp_next_lps(SPC7110Decomp *thisptr, UINT32 n); |
| 158 | | static UINT8 SPC7110Decomp_next_mps(SPC7110Decomp *thisptr, UINT32 n); |
| 159 | | static UINT8 SPC7110Decomp_toggle_invert(SPC7110Decomp *thisptr, UINT32 n); |
| 160 | | static UINT32 SPC7110Decomp_morton_2x8(SPC7110Decomp *thisptr, UINT32 data); |
| 161 | | static UINT32 SPC7110Decomp_morton_4x8(SPC7110Decomp *thisptr, UINT32 data); |
| 162 | | |
| 163 | | static SPC7110Decomp* SPC7110Decomp_ctor(running_machine &machine, UINT32 size) |
| 168 | SPC7110Decomp::SPC7110Decomp(running_machine &machine, UINT32 size) |
| 169 | : m_machine(machine), |
| 170 | m_rom_size(size) |
| 164 | 171 | { |
| 165 | | UINT32 i; |
| 166 | | SPC7110Decomp* newclass = (SPC7110Decomp*)auto_alloc_array(machine, UINT8, sizeof(SPC7110Decomp)); |
| 167 | | newclass->decomp_buffer = (UINT8*)auto_alloc_array(machine, UINT8, spc7110_decomp_buffer_size); |
| 168 | | SPC7110Decomp_reset(newclass); |
| 172 | m_decomp_buffer = (UINT8*)auto_alloc_array(machine, UINT8, SPC7110_DECOMP_BUFFER_SIZE); |
| 173 | reset(); |
| 169 | 174 | |
| 170 | | for(i = 0; i < 256; i++) |
| 175 | for (int i = 0; i < 256; i++) |
| 171 | 176 | { |
| 172 | 177 | #define map(x, y) (((i >> x) & 1) << y) |
| 173 | 178 | //2x8-bit |
| 174 | | newclass->morton16[1][i] = map(7, 15) + map(6, 7) + map(5, 14) + map(4, 6) |
| 175 | | + map(3, 13) + map(2, 5) + map(1, 12) + map(0, 4); |
| 176 | | newclass->morton16[0][i] = map(7, 11) + map(6, 3) + map(5, 10) + map(4, 2) |
| 177 | | + map(3, 9) + map(2, 1) + map(1, 8) + map(0, 0); |
| 179 | m_morton16[1][i] = map(7, 15) + map(6, 7) + map(5, 14) + map(4, 6) |
| 180 | + map(3, 13) + map(2, 5) + map(1, 12) + map(0, 4); |
| 181 | m_morton16[0][i] = map(7, 11) + map(6, 3) + map(5, 10) + map(4, 2) |
| 182 | + map(3, 9) + map(2, 1) + map(1, 8) + map(0, 0); |
| 178 | 183 | //4x8-bit |
| 179 | | newclass->morton32[3][i] = map(7, 31) + map(6, 23) + map(5, 15) + map(4, 7) |
| 180 | | + map(3, 30) + map(2, 22) + map(1, 14) + map(0, 6); |
| 181 | | newclass->morton32[2][i] = map(7, 29) + map(6, 21) + map(5, 13) + map(4, 5) |
| 182 | | + map(3, 28) + map(2, 20) + map(1, 12) + map(0, 4); |
| 183 | | newclass->morton32[1][i] = map(7, 27) + map(6, 19) + map(5, 11) + map(4, 3) |
| 184 | | + map(3, 26) + map(2, 18) + map(1, 10) + map(0, 2); |
| 185 | | newclass->morton32[0][i] = map(7, 25) + map(6, 17) + map(5, 9) + map(4, 1) |
| 186 | | + map(3, 24) + map(2, 16) + map(1, 8) + map(0, 0); |
| 184 | m_morton32[3][i] = map(7, 31) + map(6, 23) + map(5, 15) + map(4, 7) |
| 185 | + map(3, 30) + map(2, 22) + map(1, 14) + map(0, 6); |
| 186 | m_morton32[2][i] = map(7, 29) + map(6, 21) + map(5, 13) + map(4, 5) |
| 187 | + map(3, 28) + map(2, 20) + map(1, 12) + map(0, 4); |
| 188 | m_morton32[1][i] = map(7, 27) + map(6, 19) + map(5, 11) + map(4, 3) |
| 189 | + map(3, 26) + map(2, 18) + map(1, 10) + map(0, 2); |
| 190 | m_morton32[0][i] = map(7, 25) + map(6, 17) + map(5, 9) + map(4, 1) |
| 191 | + map(3, 24) + map(2, 16) + map(1, 8) + map(0, 0); |
| 187 | 192 | #undef map |
| 188 | 193 | } |
| 189 | | |
| 190 | | newclass->rom_size = size; |
| 191 | | |
| 192 | | return newclass; |
| 193 | 194 | } |
| 194 | 195 | |
| 195 | | static void SPC7110Decomp_reset(SPC7110Decomp *thisptr) |
| 196 | void SPC7110Decomp::reset() |
| 196 | 197 | { |
| 197 | 198 | //mode 3 is invalid; this is treated as a special case to always return 0x00 |
| 198 | 199 | //set to mode 3 so that reading decomp port before starting first decomp will return 0x00 |
| 199 | | thisptr->decomp_mode = 3; |
| 200 | m_decomp_mode = 3; |
| 200 | 201 | |
| 201 | | thisptr->decomp_buffer_rdoffset = 0; |
| 202 | | thisptr->decomp_buffer_wroffset = 0; |
| 203 | | thisptr->decomp_buffer_length = 0; |
| 202 | m_decomp_buffer_rdoffset = 0; |
| 203 | m_decomp_buffer_wroffset = 0; |
| 204 | m_decomp_buffer_length = 0; |
| 204 | 205 | } |
| 205 | 206 | |
| 206 | | static void SPC7110Decomp_init(SPC7110Decomp *thisptr, running_machine &machine, UINT32 mode, UINT32 offset, UINT32 index) |
| 207 | void SPC7110Decomp::init(running_machine &machine, UINT8 *ROM, UINT32 mode, UINT32 offset, UINT32 index) |
| 207 | 208 | { |
| 208 | | UINT32 i; |
| 209 | m_decomp_mode = mode; |
| 210 | m_decomp_offset = offset; |
| 209 | 211 | |
| 210 | | thisptr->m_machine = &machine; |
| 212 | m_decomp_buffer_rdoffset = 0; |
| 213 | m_decomp_buffer_wroffset = 0; |
| 214 | m_decomp_buffer_length = 0; |
| 211 | 215 | |
| 212 | | thisptr->decomp_mode = mode; |
| 213 | | thisptr->decomp_offset = offset; |
| 214 | | |
| 215 | | thisptr->decomp_buffer_rdoffset = 0; |
| 216 | | thisptr->decomp_buffer_wroffset = 0; |
| 217 | | thisptr->decomp_buffer_length = 0; |
| 218 | | |
| 219 | 216 | //reset context states |
| 220 | | for(i = 0; i < 32; i++) |
| 217 | for (int i = 0; i < 32; i++) |
| 221 | 218 | { |
| 222 | | thisptr->context[i].index = 0; |
| 223 | | thisptr->context[i].invert = 0; |
| 219 | m_context[i].index = 0; |
| 220 | m_context[i].invert = 0; |
| 224 | 221 | } |
| 225 | 222 | |
| 226 | | switch(thisptr->decomp_mode) |
| 223 | switch (m_decomp_mode) |
| 227 | 224 | { |
| 228 | | case 0: SPC7110Decomp_mode0(thisptr, 1); break; |
| 229 | | case 1: SPC7110Decomp_mode1(thisptr, 1); break; |
| 230 | | case 2: SPC7110Decomp_mode2(thisptr, 1); break; |
| 225 | case 0: mode0(1, ROM); break; |
| 226 | case 1: mode1(1, ROM); break; |
| 227 | case 2: mode2(1, ROM); break; |
| 231 | 228 | } |
| 232 | 229 | |
| 233 | 230 | //decompress up to requested output data index |
| 234 | | while(index--) |
| 231 | while (index--) |
| 235 | 232 | { |
| 236 | | SPC7110Decomp_read(thisptr); |
| 233 | read(ROM); |
| 237 | 234 | } |
| 238 | 235 | } |
| 239 | 236 | |
| 240 | | static UINT8 SPC7110Decomp_read(SPC7110Decomp *thisptr) |
| 237 | UINT8 SPC7110Decomp::read(UINT8 *ROM) |
| 241 | 238 | { |
| 242 | 239 | UINT8 data; |
| 243 | 240 | |
| 244 | | if(thisptr->decomp_buffer_length == 0) { |
| 245 | | //decompress at least (spc7110_decomp_buffer_size / 2) bytes to the buffer |
| 246 | | switch(thisptr->decomp_mode) { |
| 241 | if (m_decomp_buffer_length == 0) |
| 242 | { |
| 243 | //decompress at least (SPC7110_DECOMP_BUFFER_SIZE / 2) bytes to the buffer |
| 244 | switch (m_decomp_mode) |
| 245 | { |
| 247 | 246 | case 0: |
| 248 | | SPC7110Decomp_mode0(thisptr, 0); |
| 247 | mode0(0, ROM); |
| 249 | 248 | break; |
| 250 | 249 | |
| 251 | 250 | case 1: |
| 252 | | SPC7110Decomp_mode1(thisptr, 0); |
| 251 | mode1(0, ROM); |
| 253 | 252 | break; |
| 254 | 253 | |
| 255 | 254 | case 2: |
| 256 | | SPC7110Decomp_mode2(thisptr, 0); |
| 255 | mode2(0, ROM); |
| 257 | 256 | break; |
| 258 | 257 | |
| 259 | 258 | default: |
| r20880 | r20881 | |
| 261 | 260 | } |
| 262 | 261 | } |
| 263 | 262 | |
| 264 | | data = thisptr->decomp_buffer[thisptr->decomp_buffer_rdoffset++]; |
| 265 | | thisptr->decomp_buffer_rdoffset &= spc7110_decomp_buffer_size - 1; |
| 266 | | thisptr->decomp_buffer_length--; |
| 263 | data = m_decomp_buffer[m_decomp_buffer_rdoffset++]; |
| 264 | m_decomp_buffer_rdoffset &= SPC7110_DECOMP_BUFFER_SIZE - 1; |
| 265 | m_decomp_buffer_length--; |
| 267 | 266 | return data; |
| 268 | 267 | } |
| 269 | 268 | |
| 270 | | static void SPC7110Decomp_write(SPC7110Decomp *thisptr, UINT8 data) |
| 269 | void SPC7110Decomp::write(UINT8 data) |
| 271 | 270 | { |
| 272 | | thisptr->decomp_buffer[thisptr->decomp_buffer_wroffset++] = data; |
| 273 | | thisptr->decomp_buffer_wroffset &= spc7110_decomp_buffer_size - 1; |
| 274 | | thisptr->decomp_buffer_length++; |
| 271 | m_decomp_buffer[m_decomp_buffer_wroffset++] = data; |
| 272 | m_decomp_buffer_wroffset &= SPC7110_DECOMP_BUFFER_SIZE - 1; |
| 273 | m_decomp_buffer_length++; |
| 275 | 274 | } |
| 276 | 275 | |
| 277 | | static UINT8 SPC7110Decomp_dataread(SPC7110Decomp *thisptr) |
| 276 | UINT8 SPC7110Decomp::dataread(UINT8 *ROM) |
| 278 | 277 | { |
| 279 | | UINT8 *ROM = thisptr->machine().root_device().memregion("cart")->base(); |
| 280 | | UINT32 size = thisptr->rom_size - 0x100000; |
| 281 | | while(thisptr->decomp_offset >= size) |
| 278 | UINT32 size = m_rom_size - 0x100000; |
| 279 | while (m_decomp_offset >= size) |
| 282 | 280 | { |
| 283 | | thisptr->decomp_offset -= size; |
| 281 | m_decomp_offset -= size; |
| 284 | 282 | } |
| 285 | | return ROM[0x100000 + thisptr->decomp_offset++]; |
| 283 | return ROM[0x100000 + m_decomp_offset++]; |
| 286 | 284 | } |
| 287 | 285 | |
| 288 | | static void SPC7110Decomp_mode0(SPC7110Decomp *thisptr, UINT8 init) |
| 286 | void SPC7110Decomp::mode0(UINT8 init, UINT8 *ROM) |
| 289 | 287 | { |
| 290 | 288 | static UINT8 val, in, span; |
| 291 | 289 | static INT32 out, inverts, lps, in_count; |
| 292 | 290 | |
| 293 | | if(init == 1) |
| 291 | if (init == 1) |
| 294 | 292 | { |
| 295 | 293 | out = inverts = lps = 0; |
| 296 | 294 | span = 0xff; |
| 297 | | val = SPC7110Decomp_dataread(thisptr); |
| 298 | | in = SPC7110Decomp_dataread(thisptr); |
| 295 | val = dataread(ROM); |
| 296 | in = dataread(ROM); |
| 299 | 297 | in_count = 8; |
| 300 | 298 | return; |
| 301 | 299 | } |
| 302 | 300 | |
| 303 | | while(thisptr->decomp_buffer_length < (spc7110_decomp_buffer_size >> 1)) |
| 301 | while (m_decomp_buffer_length < (SPC7110_DECOMP_BUFFER_SIZE >> 1)) |
| 304 | 302 | { |
| 305 | | UINT32 bit; |
| 306 | | for(bit = 0; bit < 8; bit++) |
| 303 | for (int bit = 0; bit < 8; bit++) |
| 307 | 304 | { |
| 308 | 305 | //get context |
| 309 | 306 | UINT8 mask = (1 << (bit & 3)) - 1; |
| 310 | 307 | UINT8 con = mask + ((inverts & mask) ^ (lps & mask)); |
| 311 | 308 | UINT32 prob, mps, flag_lps; |
| 312 | 309 | UINT32 shift = 0; |
| 313 | | if(bit > 3) |
| 310 | if (bit > 3) |
| 314 | 311 | { |
| 315 | 312 | con += 15; |
| 316 | 313 | } |
| 317 | 314 | |
| 318 | 315 | //get prob and mps |
| 319 | | prob = SPC7110Decomp_probability(thisptr, con); |
| 320 | | mps = (((out >> 15) & 1) ^ thisptr->context[con].invert); |
| 316 | prob = probability(con); |
| 317 | mps = (((out >> 15) & 1) ^ m_context[con].invert); |
| 321 | 318 | |
| 322 | 319 | //get bit |
| 323 | | if(val <= span - prob) //mps |
| 320 | if (val <= span - prob) //mps |
| 324 | 321 | { |
| 325 | 322 | span = span - prob; |
| 326 | 323 | out = (out << 1) + mps; |
| r20880 | r20881 | |
| 335 | 332 | } |
| 336 | 333 | |
| 337 | 334 | //renormalize |
| 338 | | while(span < 0x7f) |
| 335 | while (span < 0x7f) |
| 339 | 336 | { |
| 340 | 337 | shift++; |
| 341 | 338 | |
| r20880 | r20881 | |
| 343 | 340 | val = (val << 1) + (in >> 7); |
| 344 | 341 | |
| 345 | 342 | in <<= 1; |
| 346 | | if(--in_count == 0) |
| 343 | if (--in_count == 0) |
| 347 | 344 | { |
| 348 | | in = SPC7110Decomp_dataread(thisptr); |
| 345 | in = dataread(ROM); |
| 349 | 346 | in_count = 8; |
| 350 | 347 | } |
| 351 | 348 | } |
| 352 | 349 | |
| 353 | 350 | //update processing info |
| 354 | 351 | lps = (lps << 1) + flag_lps; |
| 355 | | inverts = (inverts << 1) + thisptr->context[con].invert; |
| 352 | inverts = (inverts << 1) + m_context[con].invert; |
| 356 | 353 | |
| 357 | 354 | //update context state |
| 358 | | if(flag_lps & SPC7110Decomp_toggle_invert(thisptr, con)) |
| 355 | if (flag_lps & toggle_invert(con)) |
| 359 | 356 | { |
| 360 | | thisptr->context[con].invert ^= 1; |
| 357 | m_context[con].invert ^= 1; |
| 361 | 358 | } |
| 362 | | if(flag_lps) |
| 359 | if (flag_lps) |
| 363 | 360 | { |
| 364 | | thisptr->context[con].index = SPC7110Decomp_next_lps(thisptr, con); |
| 361 | m_context[con].index = next_lps(con); |
| 365 | 362 | } |
| 366 | | else if(shift) |
| 363 | else if (shift) |
| 367 | 364 | { |
| 368 | | thisptr->context[con].index = SPC7110Decomp_next_mps(thisptr, con); |
| 365 | m_context[con].index = next_mps(con); |
| 369 | 366 | } |
| 370 | 367 | } |
| 371 | 368 | |
| 372 | 369 | //save byte |
| 373 | | SPC7110Decomp_write(thisptr, out); |
| 370 | write(out); |
| 374 | 371 | } |
| 375 | 372 | } |
| 376 | 373 | |
| 377 | | static void SPC7110Decomp_mode1(SPC7110Decomp *thisptr, UINT8 init) |
| 374 | void SPC7110Decomp::mode1(UINT8 init, UINT8 *ROM) |
| 378 | 375 | { |
| 379 | 376 | static INT32 pixelorder[4], realorder[4]; |
| 380 | 377 | static UINT8 in, val, span; |
| 381 | 378 | static INT32 out, inverts, lps, in_count; |
| 382 | 379 | |
| 383 | | if(init == 1) |
| 380 | if (init == 1) |
| 384 | 381 | { |
| 385 | | UINT32 i; |
| 386 | | for(i = 0; i < 4; i++) |
| 382 | for (int i = 0; i < 4; i++) |
| 387 | 383 | { |
| 388 | 384 | pixelorder[i] = i; |
| 389 | 385 | } |
| 390 | 386 | out = inverts = lps = 0; |
| 391 | 387 | span = 0xff; |
| 392 | | val = SPC7110Decomp_dataread(thisptr); |
| 393 | | in = SPC7110Decomp_dataread(thisptr); |
| 388 | val = dataread(ROM); |
| 389 | in = dataread(ROM); |
| 394 | 390 | in_count = 8; |
| 395 | 391 | return; |
| 396 | 392 | } |
| 397 | 393 | |
| 398 | | while(thisptr->decomp_buffer_length < (spc7110_decomp_buffer_size >> 1)) |
| 394 | while (m_decomp_buffer_length < (SPC7110_DECOMP_BUFFER_SIZE >> 1)) |
| 399 | 395 | { |
| 400 | 396 | UINT16 data; |
| 401 | | UINT32 pixel; |
| 402 | | for(pixel = 0; pixel < 8; pixel++) |
| 397 | for (int pixel = 0; pixel < 8; pixel++) |
| 403 | 398 | { |
| 404 | 399 | //get first symbol context |
| 405 | 400 | UINT32 a = ((out >> (1 * 2)) & 3); |
| 406 | 401 | UINT32 b = ((out >> (7 * 2)) & 3); |
| 407 | 402 | UINT32 c = ((out >> (8 * 2)) & 3); |
| 408 | 403 | UINT32 con = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c); |
| 409 | | UINT32 bit; |
| 410 | 404 | |
| 411 | 405 | //update pixel order |
| 412 | 406 | UINT32 m, n; |
| 413 | | for(m = 0; m < 4; m++) |
| 407 | for (m = 0; m < 4; m++) |
| 414 | 408 | { |
| 415 | | if(pixelorder[m] == a) |
| 409 | if (pixelorder[m] == a) |
| 416 | 410 | { |
| 417 | 411 | break; |
| 418 | 412 | } |
| 419 | 413 | } |
| 420 | | for(n = m; n > 0; n--) |
| 414 | for (n = m; n > 0; n--) |
| 421 | 415 | { |
| 422 | 416 | pixelorder[n] = pixelorder[n - 1]; |
| 423 | 417 | } |
| 424 | 418 | pixelorder[0] = a; |
| 425 | 419 | |
| 426 | 420 | //calculate the real pixel order |
| 427 | | for(m = 0; m < 4; m++) |
| 421 | for (m = 0; m < 4; m++) |
| 428 | 422 | { |
| 429 | 423 | realorder[m] = pixelorder[m]; |
| 430 | 424 | } |
| 431 | 425 | |
| 432 | 426 | //rotate reference pixel c value to top |
| 433 | | for(m = 0; m < 4; m++) |
| 427 | for (m = 0; m < 4; m++) |
| 434 | 428 | { |
| 435 | | if(realorder[m] == c) |
| 429 | if (realorder[m] == c) |
| 436 | 430 | { |
| 437 | 431 | break; |
| 438 | 432 | } |
| 439 | 433 | } |
| 440 | | for(n = m; n > 0; n--) |
| 434 | for (n = m; n > 0; n--) |
| 441 | 435 | { |
| 442 | 436 | realorder[n] = realorder[n - 1]; |
| 443 | 437 | } |
| 444 | 438 | realorder[0] = c; |
| 445 | 439 | |
| 446 | 440 | //rotate reference pixel b value to top |
| 447 | | for(m = 0; m < 4; m++) |
| 441 | for (m = 0; m < 4; m++) |
| 448 | 442 | { |
| 449 | | if(realorder[m] == b) |
| 443 | if (realorder[m] == b) |
| 450 | 444 | { |
| 451 | 445 | break; |
| 452 | 446 | } |
| 453 | 447 | } |
| 454 | | for(n = m; n > 0; n--) |
| 448 | for (n = m; n > 0; n--) |
| 455 | 449 | { |
| 456 | 450 | realorder[n] = realorder[n - 1]; |
| 457 | 451 | } |
| 458 | 452 | realorder[0] = b; |
| 459 | 453 | |
| 460 | 454 | //rotate reference pixel a value to top |
| 461 | | for(m = 0; m < 4; m++) |
| 455 | for (m = 0; m < 4; m++) |
| 462 | 456 | { |
| 463 | | if(realorder[m] == a) |
| 457 | if (realorder[m] == a) |
| 464 | 458 | { |
| 465 | 459 | break; |
| 466 | 460 | } |
| 467 | 461 | } |
| 468 | | for(n = m; n > 0; n--) |
| 462 | for (n = m; n > 0; n--) |
| 469 | 463 | { |
| 470 | 464 | realorder[n] = realorder[n - 1]; |
| 471 | 465 | } |
| 472 | 466 | realorder[0] = a; |
| 473 | 467 | |
| 474 | 468 | //get 2 symbols |
| 475 | | for(bit = 0; bit < 2; bit++) |
| 469 | for (int bit = 0; bit < 2; bit++) |
| 476 | 470 | { |
| 477 | 471 | //get prob |
| 478 | | UINT32 prob = SPC7110Decomp_probability(thisptr, con); |
| 472 | UINT32 prob = probability(con); |
| 479 | 473 | UINT32 shift = 0; |
| 480 | 474 | |
| 481 | 475 | //get symbol |
| 482 | 476 | UINT32 flag_lps; |
| 483 | | if(val <= span - prob) //mps |
| 477 | if (val <= span - prob) //mps |
| 484 | 478 | { |
| 485 | 479 | span = span - prob; |
| 486 | 480 | flag_lps = 0; |
| r20880 | r20881 | |
| 493 | 487 | } |
| 494 | 488 | |
| 495 | 489 | //renormalize |
| 496 | | while(span < 0x7f) |
| 490 | while (span < 0x7f) |
| 497 | 491 | { |
| 498 | 492 | shift++; |
| 499 | 493 | |
| r20880 | r20881 | |
| 501 | 495 | val = (val << 1) + (in >> 7); |
| 502 | 496 | |
| 503 | 497 | in <<= 1; |
| 504 | | if(--in_count == 0) |
| 498 | if (--in_count == 0) |
| 505 | 499 | { |
| 506 | | in = SPC7110Decomp_dataread(thisptr); |
| 500 | in = dataread(ROM); |
| 507 | 501 | in_count = 8; |
| 508 | 502 | } |
| 509 | 503 | } |
| 510 | 504 | |
| 511 | 505 | //update processing info |
| 512 | 506 | lps = (lps << 1) + flag_lps; |
| 513 | | inverts = (inverts << 1) + thisptr->context[con].invert; |
| 507 | inverts = (inverts << 1) + m_context[con].invert; |
| 514 | 508 | |
| 515 | 509 | //update context state |
| 516 | | if(flag_lps & SPC7110Decomp_toggle_invert(thisptr, con)) |
| 510 | if (flag_lps & toggle_invert(con)) |
| 517 | 511 | { |
| 518 | | thisptr->context[con].invert ^= 1; |
| 512 | m_context[con].invert ^= 1; |
| 519 | 513 | } |
| 520 | | if(flag_lps) |
| 514 | if (flag_lps) |
| 521 | 515 | { |
| 522 | | thisptr->context[con].index = SPC7110Decomp_next_lps(thisptr, con); |
| 516 | m_context[con].index = next_lps(con); |
| 523 | 517 | } |
| 524 | | else if(shift) |
| 518 | else if (shift) |
| 525 | 519 | { |
| 526 | | thisptr->context[con].index = SPC7110Decomp_next_mps(thisptr, con); |
| 520 | m_context[con].index = next_mps(con); |
| 527 | 521 | } |
| 528 | 522 | |
| 529 | 523 | //get next context |
| r20880 | r20881 | |
| 536 | 530 | } |
| 537 | 531 | |
| 538 | 532 | //turn pixel data into bitplanes |
| 539 | | data = SPC7110Decomp_morton_2x8(thisptr, out); |
| 540 | | SPC7110Decomp_write(thisptr, data >> 8); |
| 541 | | SPC7110Decomp_write(thisptr, data >> 0); |
| 533 | data = morton_2x8(out); |
| 534 | write(data >> 8); |
| 535 | write(data >> 0); |
| 542 | 536 | } |
| 543 | 537 | } |
| 544 | 538 | |
| 545 | | static void SPC7110Decomp_mode2(SPC7110Decomp *thisptr, UINT8 init) |
| 539 | void SPC7110Decomp::mode2(UINT8 init, UINT8 *ROM) |
| 546 | 540 | { |
| 547 | 541 | static INT32 pixelorder[16], realorder[16]; |
| 548 | 542 | static UINT8 bitplanebuffer[16], buffer_index; |
| 549 | 543 | static UINT8 in, val, span; |
| 550 | 544 | static INT32 out0, out1, inverts, lps, in_count; |
| 551 | 545 | |
| 552 | | if(init == 1) |
| 546 | if (init == 1) |
| 553 | 547 | { |
| 554 | | UINT32 i; |
| 555 | | for(i = 0; i < 16; i++) |
| 548 | for (int i = 0; i < 16; i++) |
| 556 | 549 | { |
| 557 | 550 | pixelorder[i] = i; |
| 558 | 551 | } |
| 559 | 552 | buffer_index = 0; |
| 560 | 553 | out0 = out1 = inverts = lps = 0; |
| 561 | 554 | span = 0xff; |
| 562 | | val = SPC7110Decomp_dataread(thisptr); |
| 563 | | in = SPC7110Decomp_dataread(thisptr); |
| 555 | val = dataread(ROM); |
| 556 | in = dataread(ROM); |
| 564 | 557 | in_count = 8; |
| 565 | 558 | return; |
| 566 | 559 | } |
| 567 | 560 | |
| 568 | | while(thisptr->decomp_buffer_length < (spc7110_decomp_buffer_size >> 1)) |
| 561 | while (m_decomp_buffer_length < (SPC7110_DECOMP_BUFFER_SIZE >> 1)) |
| 569 | 562 | { |
| 570 | 563 | UINT32 data; |
| 571 | | UINT32 pixel; |
| 572 | | for(pixel = 0; pixel < 8; pixel++) |
| 564 | for (int pixel = 0; pixel < 8; pixel++) |
| 573 | 565 | { |
| 574 | 566 | //get first symbol context |
| 575 | 567 | UINT32 a = ((out0 >> (0 * 4)) & 15); |
| r20880 | r20881 | |
| 577 | 569 | UINT32 c = ((out1 >> (0 * 4)) & 15); |
| 578 | 570 | UINT32 con = 0; |
| 579 | 571 | UINT32 refcon = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c); |
| 580 | | UINT32 bit; |
| 581 | 572 | |
| 582 | 573 | //update pixel order |
| 583 | 574 | UINT32 m, n; |
| 584 | | for(m = 0; m < 16; m++) |
| 575 | for (m = 0; m < 16; m++) |
| 585 | 576 | { |
| 586 | | if(pixelorder[m] == a) |
| 577 | if (pixelorder[m] == a) |
| 587 | 578 | { |
| 588 | 579 | break; |
| 589 | 580 | } |
| 590 | 581 | } |
| 591 | | for(n = m; n > 0; n--) |
| 582 | for (n = m; n > 0; n--) |
| 592 | 583 | { |
| 593 | 584 | pixelorder[n] = pixelorder[n - 1]; |
| 594 | 585 | } |
| 595 | 586 | pixelorder[0] = a; |
| 596 | 587 | |
| 597 | 588 | //calculate the real pixel order |
| 598 | | for(m = 0; m < 16; m++) |
| 589 | for (m = 0; m < 16; m++) |
| 599 | 590 | { |
| 600 | 591 | realorder[m] = pixelorder[m]; |
| 601 | 592 | } |
| 602 | 593 | |
| 603 | 594 | //rotate reference pixel c value to top |
| 604 | | for(m = 0; m < 16; m++) |
| 595 | for (m = 0; m < 16; m++) |
| 605 | 596 | { |
| 606 | | if(realorder[m] == c) |
| 597 | if (realorder[m] == c) |
| 607 | 598 | { |
| 608 | 599 | break; |
| 609 | 600 | } |
| 610 | 601 | } |
| 611 | | for(n = m; n > 0; n--) |
| 602 | for (n = m; n > 0; n--) |
| 612 | 603 | { |
| 613 | 604 | realorder[n] = realorder[n - 1]; |
| 614 | 605 | } |
| 615 | 606 | realorder[0] = c; |
| 616 | 607 | |
| 617 | 608 | //rotate reference pixel b value to top |
| 618 | | for(m = 0; m < 16; m++) |
| 609 | for (m = 0; m < 16; m++) |
| 619 | 610 | { |
| 620 | | if(realorder[m] == b) |
| 611 | if (realorder[m] == b) |
| 621 | 612 | { |
| 622 | 613 | break; |
| 623 | 614 | } |
| 624 | 615 | } |
| 625 | | for(n = m; n > 0; n--) |
| 616 | for (n = m; n > 0; n--) |
| 626 | 617 | { |
| 627 | 618 | realorder[n] = realorder[n - 1]; |
| 628 | 619 | } |
| 629 | 620 | realorder[0] = b; |
| 630 | 621 | |
| 631 | 622 | //rotate reference pixel a value to top |
| 632 | | for(m = 0; m < 16; m++) |
| 623 | for (m = 0; m < 16; m++) |
| 633 | 624 | { |
| 634 | | if(realorder[m] == a) |
| 625 | if (realorder[m] == a) |
| 635 | 626 | { |
| 636 | 627 | break; |
| 637 | 628 | } |
| 638 | 629 | } |
| 639 | | for(n = m; n > 0; n--) |
| 630 | for (n = m; n > 0; n--) |
| 640 | 631 | { |
| 641 | 632 | realorder[n] = realorder[n - 1]; |
| 642 | 633 | } |
| 643 | 634 | realorder[0] = a; |
| 644 | 635 | |
| 645 | 636 | //get 4 symbols |
| 646 | | for(bit = 0; bit < 4; bit++) |
| 637 | for (int bit = 0; bit < 4; bit++) |
| 647 | 638 | { |
| 648 | 639 | UINT32 invertbit, shift; |
| 649 | 640 | |
| 650 | 641 | //get prob |
| 651 | | UINT32 prob = SPC7110Decomp_probability(thisptr, con); |
| 642 | UINT32 prob = probability(con); |
| 652 | 643 | |
| 653 | 644 | //get symbol |
| 654 | 645 | UINT32 flag_lps; |
| 655 | | if(val <= span - prob) //mps |
| 646 | if (val <= span - prob) //mps |
| 656 | 647 | { |
| 657 | 648 | span = span - prob; |
| 658 | 649 | flag_lps = 0; |
| r20880 | r20881 | |
| 666 | 657 | |
| 667 | 658 | //renormalize |
| 668 | 659 | shift = 0; |
| 669 | | while(span < 0x7f) |
| 660 | while (span < 0x7f) |
| 670 | 661 | { |
| 671 | 662 | shift++; |
| 672 | 663 | |
| r20880 | r20881 | |
| 674 | 665 | val = (val << 1) + (in >> 7); |
| 675 | 666 | |
| 676 | 667 | in <<= 1; |
| 677 | | if(--in_count == 0) |
| 668 | if (--in_count == 0) |
| 678 | 669 | { |
| 679 | | in = SPC7110Decomp_dataread(thisptr); |
| 670 | in = dataread(ROM); |
| 680 | 671 | in_count = 8; |
| 681 | 672 | } |
| 682 | 673 | } |
| 683 | 674 | |
| 684 | 675 | //update processing info |
| 685 | 676 | lps = (lps << 1) + flag_lps; |
| 686 | | invertbit = thisptr->context[con].invert; |
| 677 | invertbit = m_context[con].invert; |
| 687 | 678 | inverts = (inverts << 1) + invertbit; |
| 688 | 679 | |
| 689 | 680 | //update context state |
| 690 | | if(flag_lps & SPC7110Decomp_toggle_invert(thisptr, con)) |
| 681 | if (flag_lps & toggle_invert(con)) |
| 691 | 682 | { |
| 692 | | thisptr->context[con].invert ^= 1; |
| 683 | m_context[con].invert ^= 1; |
| 693 | 684 | } |
| 694 | | if(flag_lps) |
| 685 | if (flag_lps) |
| 695 | 686 | { |
| 696 | | thisptr->context[con].index = SPC7110Decomp_next_lps(thisptr, con); |
| 687 | m_context[con].index = next_lps(con); |
| 697 | 688 | } |
| 698 | | else if(shift) |
| 689 | else if (shift) |
| 699 | 690 | { |
| 700 | | thisptr->context[con].index = SPC7110Decomp_next_mps(thisptr, con); |
| 691 | m_context[con].index = next_mps(con); |
| 701 | 692 | } |
| 702 | 693 | |
| 703 | 694 | //get next context |
| r20880 | r20881 | |
| 711 | 702 | } |
| 712 | 703 | |
| 713 | 704 | //convert pixel data into bitplanes |
| 714 | | data = SPC7110Decomp_morton_4x8(thisptr, out0); |
| 715 | | SPC7110Decomp_write(thisptr, data >> 24); |
| 716 | | SPC7110Decomp_write(thisptr, data >> 16); |
| 705 | data = morton_4x8(out0); |
| 706 | write(data >> 24); |
| 707 | write(data >> 16); |
| 717 | 708 | bitplanebuffer[buffer_index++] = data >> 8; |
| 718 | 709 | bitplanebuffer[buffer_index++] = data >> 0; |
| 719 | 710 | |
| 720 | | if(buffer_index == 16) |
| 711 | if (buffer_index == 16) |
| 721 | 712 | { |
| 722 | | UINT32 i; |
| 723 | | for(i = 0; i < 16; i++) |
| 713 | for (int i = 0; i < 16; i++) |
| 724 | 714 | { |
| 725 | | SPC7110Decomp_write(thisptr, bitplanebuffer[i]); |
| 715 | write(bitplanebuffer[i]); |
| 726 | 716 | } |
| 727 | 717 | buffer_index = 0; |
| 728 | 718 | } |
| 729 | 719 | } |
| 730 | 720 | } |
| 731 | 721 | |
| 732 | | static UINT8 SPC7110Decomp_probability(SPC7110Decomp *thisptr, UINT32 n) |
| 722 | UINT8 SPC7110Decomp::probability(UINT32 n) |
| 733 | 723 | { |
| 734 | | return spc7110_evolution_table[thisptr->context[n].index][0]; |
| 724 | return spc7110_evolution_table[m_context[n].index][0]; |
| 735 | 725 | } |
| 736 | 726 | |
| 737 | | static UINT8 SPC7110Decomp_next_lps(SPC7110Decomp *thisptr, UINT32 n) |
| 727 | UINT8 SPC7110Decomp::next_lps(UINT32 n) |
| 738 | 728 | { |
| 739 | | return spc7110_evolution_table[thisptr->context[n].index][1]; |
| 729 | return spc7110_evolution_table[m_context[n].index][1]; |
| 740 | 730 | } |
| 741 | 731 | |
| 742 | | static UINT8 SPC7110Decomp_next_mps(SPC7110Decomp *thisptr, UINT32 n) |
| 732 | UINT8 SPC7110Decomp::next_mps(UINT32 n) |
| 743 | 733 | { |
| 744 | | return spc7110_evolution_table[thisptr->context[n].index][2]; |
| 734 | return spc7110_evolution_table[m_context[n].index][2]; |
| 745 | 735 | } |
| 746 | 736 | |
| 747 | | static UINT8 SPC7110Decomp_toggle_invert(SPC7110Decomp *thisptr, UINT32 n) |
| 737 | UINT8 SPC7110Decomp::toggle_invert(UINT32 n) |
| 748 | 738 | { |
| 749 | | return spc7110_evolution_table[thisptr->context[n].index][3]; |
| 739 | return spc7110_evolution_table[m_context[n].index][3]; |
| 750 | 740 | } |
| 751 | 741 | |
| 752 | | static UINT32 SPC7110Decomp_morton_2x8(SPC7110Decomp *thisptr, UINT32 data) |
| 742 | UINT32 SPC7110Decomp::morton_2x8(UINT32 data) |
| 753 | 743 | { |
| 754 | 744 | //reverse morton lookup: de-interleave two 8-bit values |
| 755 | 745 | //15, 13, 11, 9, 7, 5, 3, 1 -> 15- 8 |
| 756 | 746 | //14, 12, 10, 8, 6, 4, 2, 0 -> 7- 0 |
| 757 | | return thisptr->morton16[0][(data >> 0) & 255] + thisptr->morton16[1][(data >> 8) & 255]; |
| 747 | return m_morton16[0][(data >> 0) & 255] + m_morton16[1][(data >> 8) & 255]; |
| 758 | 748 | } |
| 759 | 749 | |
| 760 | | static UINT32 SPC7110Decomp_morton_4x8(SPC7110Decomp *thisptr, UINT32 data) |
| 750 | UINT32 SPC7110Decomp::morton_4x8(UINT32 data) |
| 761 | 751 | { |
| 762 | 752 | //reverse morton lookup: de-interleave four 8-bit values |
| 763 | 753 | //31, 27, 23, 19, 15, 11, 7, 3 -> 31-24 |
| 764 | 754 | //30, 26, 22, 18, 14, 10, 6, 2 -> 23-16 |
| 765 | 755 | //29, 25, 21, 17, 13, 9, 5, 1 -> 15- 8 |
| 766 | 756 | //28, 24, 20, 16, 12, 8, 4, 0 -> 7- 0 |
| 767 | | return thisptr->morton32[0][(data >> 0) & 255] + thisptr->morton32[1][(data >> 8) & 255] |
| 768 | | + thisptr->morton32[2][(data >> 16) & 255] + thisptr->morton32[3][(data >> 24) & 255]; |
| 757 | return m_morton32[0][(data >> 0) & 255] + m_morton32[1][(data >> 8) & 255] |
| 758 | + m_morton32[2][(data >> 16) & 255] + m_morton32[3][(data >> 24) & 255]; |
| 769 | 759 | } |
| 770 | 760 | |
| 771 | 761 | static void spc7110_mmio_write(running_machine &machine, UINT32 addr, UINT8 data); |
| r20880 | r20881 | |
| 934 | 924 | |
| 935 | 925 | snes_spc7110.size = state->m_cart_size; |
| 936 | 926 | |
| 937 | | snes_spc7110.decomp = SPC7110Decomp_ctor(machine, snes_spc7110.size); |
| 927 | snes_spc7110.decomp = auto_alloc(machine, SPC7110Decomp(machine, snes_spc7110.size)); |
| 938 | 928 | } |
| 939 | 929 | |
| 940 | 930 | static void spc7110rtc_init(running_machine& machine) |
| r20880 | r20881 | |
| 953 | 943 | static UINT32 spc7110_datarom_addr(UINT32 addr) |
| 954 | 944 | { |
| 955 | 945 | UINT32 size = snes_spc7110.size - 0x100000; |
| 956 | | while(addr >= size) |
| 946 | while (addr >= size) |
| 957 | 947 | { |
| 958 | 948 | addr -= size; |
| 959 | 949 | } |
| r20880 | r20881 | |
| 1087 | 1077 | counter--; |
| 1088 | 1078 | snes_spc7110.r4809 = counter; |
| 1089 | 1079 | snes_spc7110.r480a = counter >> 8; |
| 1090 | | return SPC7110Decomp_read(snes_spc7110.decomp); |
| 1080 | return snes_spc7110.decomp->read(ROM); |
| 1091 | 1081 | } |
| 1092 | 1082 | case 0x4801: return snes_spc7110.r4801; |
| 1093 | 1083 | case 0x4802: return snes_spc7110.r4802; |
| r20880 | r20881 | |
| 1116 | 1106 | UINT8 data; |
| 1117 | 1107 | UINT32 address, adjust, adjustaddr; |
| 1118 | 1108 | |
| 1119 | | if(snes_spc7110.r481x != 0x07) return 0x00; |
| 1109 | if (snes_spc7110.r481x != 0x07) return 0x00; |
| 1120 | 1110 | |
| 1121 | 1111 | address = spc7110_data_pointer(); |
| 1122 | 1112 | adjust = spc7110_data_adjust(); |
| 1123 | | if(snes_spc7110.r4818 & 8) |
| 1113 | if (snes_spc7110.r4818 & 8) |
| 1124 | 1114 | { |
| 1125 | 1115 | adjust = (INT16)adjust; //16-bit sign extend |
| 1126 | 1116 | } |
| 1127 | 1117 | |
| 1128 | 1118 | adjustaddr = address; |
| 1129 | | if(snes_spc7110.r4818 & 2) |
| 1119 | if (snes_spc7110.r4818 & 2) |
| 1130 | 1120 | { |
| 1131 | 1121 | adjustaddr += adjust; |
| 1132 | 1122 | spc7110_set_data_adjust(adjust + 1); |
| 1133 | 1123 | } |
| 1134 | 1124 | |
| 1135 | 1125 | data = ROM[spc7110_datarom_addr(adjustaddr)]; |
| 1136 | | if(!(snes_spc7110.r4818 & 2)) |
| 1126 | if (!(snes_spc7110.r4818 & 2)) |
| 1137 | 1127 | { |
| 1138 | 1128 | UINT32 increment = (snes_spc7110.r4818 & 1) ? spc7110_data_increment() : 1; |
| 1139 | | if(snes_spc7110.r4818 & 4) |
| 1129 | if (snes_spc7110.r4818 & 4) |
| 1140 | 1130 | { |
| 1141 | 1131 | increment = (INT16)increment; //16-bit sign extend |
| 1142 | 1132 | } |
| 1143 | 1133 | |
| 1144 | | if((snes_spc7110.r4818 & 16) == 0) |
| 1134 | if ((snes_spc7110.r4818 & 16) == 0) |
| 1145 | 1135 | { |
| 1146 | 1136 | spc7110_set_data_pointer(address + increment); |
| 1147 | 1137 | } |
| r20880 | r20881 | |
| 1165 | 1155 | { |
| 1166 | 1156 | UINT8 data; |
| 1167 | 1157 | UINT32 address, adjust; |
| 1168 | | if(snes_spc7110.r481x != 0x07) |
| 1158 | if (snes_spc7110.r481x != 0x07) |
| 1169 | 1159 | { |
| 1170 | 1160 | return 0x00; |
| 1171 | 1161 | } |
| 1172 | 1162 | |
| 1173 | 1163 | address = spc7110_data_pointer(); |
| 1174 | 1164 | adjust = spc7110_data_adjust(); |
| 1175 | | if(snes_spc7110.r4818 & 8) |
| 1165 | if (snes_spc7110.r4818 & 8) |
| 1176 | 1166 | { |
| 1177 | 1167 | adjust = (INT16)adjust; //16-bit sign extend |
| 1178 | 1168 | } |
| 1179 | 1169 | |
| 1180 | 1170 | data = ROM[spc7110_datarom_addr(address + adjust)]; |
| 1181 | | if((snes_spc7110.r4818 & 0x60) == 0x60) |
| 1171 | if ((snes_spc7110.r4818 & 0x60) == 0x60) |
| 1182 | 1172 | { |
| 1183 | | if((snes_spc7110.r4818 & 16) == 0) |
| 1173 | if ((snes_spc7110.r4818 & 16) == 0) |
| 1184 | 1174 | { |
| 1185 | 1175 | spc7110_set_data_pointer(address + adjust); |
| 1186 | 1176 | } |
| r20880 | r20881 | |
| 1286 | 1276 | + (ROM[address + 2] << 8) |
| 1287 | 1277 | + (ROM[address + 3] << 0); |
| 1288 | 1278 | |
| 1289 | | SPC7110Decomp_init(snes_spc7110.decomp, machine, mode, offset, (snes_spc7110.r4805 + (snes_spc7110.r4806 << 8)) << mode); |
| 1279 | snes_spc7110.decomp->init(machine, ROM, mode, offset, (snes_spc7110.r4805 + (snes_spc7110.r4806 << 8)) << mode); |
| 1290 | 1280 | snes_spc7110.r480c = 0x80; |
| 1291 | 1281 | } |
| 1292 | 1282 | break; |
| r20880 | r20881 | |
| 1308 | 1298 | { |
| 1309 | 1299 | snes_spc7110.r4814 = data; |
| 1310 | 1300 | snes_spc7110.r4814_latch = 1; |
| 1311 | | if(!snes_spc7110.r4815_latch) |
| 1301 | if (!snes_spc7110.r4815_latch) |
| 1312 | 1302 | { |
| 1313 | 1303 | break; |
| 1314 | 1304 | } |
| 1315 | | if(!(snes_spc7110.r4818 & 2)) |
| 1305 | if (!(snes_spc7110.r4818 & 2)) |
| 1316 | 1306 | { |
| 1317 | 1307 | break; |
| 1318 | 1308 | } |
| 1319 | | if(snes_spc7110.r4818 & 0x10) |
| 1309 | if (snes_spc7110.r4818 & 0x10) |
| 1320 | 1310 | { |
| 1321 | 1311 | break; |
| 1322 | 1312 | } |
| 1323 | 1313 | |
| 1324 | | if((snes_spc7110.r4818 & 0x60) == 0x20) |
| 1314 | if ((snes_spc7110.r4818 & 0x60) == 0x20) |
| 1325 | 1315 | { |
| 1326 | 1316 | UINT32 increment = spc7110_data_adjust() & 0xff; |
| 1327 | | if(snes_spc7110.r4818 & 8) |
| 1317 | if (snes_spc7110.r4818 & 8) |
| 1328 | 1318 | { |
| 1329 | 1319 | increment = (INT8)increment; //8-bit sign extend |
| 1330 | 1320 | } |
| 1331 | 1321 | spc7110_set_data_pointer(spc7110_data_pointer() + increment); |
| 1332 | 1322 | } |
| 1333 | | else if((snes_spc7110.r4818 & 0x60) == 0x40) |
| 1323 | else if ((snes_spc7110.r4818 & 0x60) == 0x40) |
| 1334 | 1324 | { |
| 1335 | 1325 | UINT32 increment = spc7110_data_adjust(); |
| 1336 | | if(snes_spc7110.r4818 & 8) |
| 1326 | if (snes_spc7110.r4818 & 8) |
| 1337 | 1327 | { |
| 1338 | 1328 | increment = (INT16)increment; //16-bit sign extend |
| 1339 | 1329 | } |
| r20880 | r20881 | |
| 1346 | 1336 | { |
| 1347 | 1337 | snes_spc7110.r4815 = data; |
| 1348 | 1338 | snes_spc7110.r4815_latch = 1; |
| 1349 | | if(!snes_spc7110.r4814_latch) |
| 1339 | if (!snes_spc7110.r4814_latch) |
| 1350 | 1340 | { |
| 1351 | 1341 | break; |
| 1352 | 1342 | } |
| 1353 | | if(!(snes_spc7110.r4818 & 2)) |
| 1343 | if (!(snes_spc7110.r4818 & 2)) |
| 1354 | 1344 | { |
| 1355 | 1345 | break; |
| 1356 | 1346 | } |
| 1357 | | if(snes_spc7110.r4818 & 0x10) |
| 1347 | if (snes_spc7110.r4818 & 0x10) |
| 1358 | 1348 | { |
| 1359 | 1349 | break; |
| 1360 | 1350 | } |
| 1361 | 1351 | |
| 1362 | | if((snes_spc7110.r4818 & 0x60) == 0x20) |
| 1352 | if ((snes_spc7110.r4818 & 0x60) == 0x20) |
| 1363 | 1353 | { |
| 1364 | 1354 | UINT32 increment = spc7110_data_adjust() & 0xff; |
| 1365 | | if(snes_spc7110.r4818 & 8) |
| 1355 | if (snes_spc7110.r4818 & 8) |
| 1366 | 1356 | { |
| 1367 | 1357 | increment = (INT8)increment; //8-bit sign extend |
| 1368 | 1358 | } |
| 1369 | 1359 | spc7110_set_data_pointer(spc7110_data_pointer() + increment); |
| 1370 | 1360 | } |
| 1371 | | else if((snes_spc7110.r4818 & 0x60) == 0x40) |
| 1361 | else if ((snes_spc7110.r4818 & 0x60) == 0x40) |
| 1372 | 1362 | { |
| 1373 | 1363 | UINT32 increment = spc7110_data_adjust(); |
| 1374 | | if(snes_spc7110.r4818 & 8) |
| 1364 | if (snes_spc7110.r4818 & 8) |
| 1375 | 1365 | { |
| 1376 | 1366 | increment = (INT16)increment; //16-bit sign extend |
| 1377 | 1367 | } |
| r20880 | r20881 | |
| 1384 | 1374 | case 0x4817: snes_spc7110.r4817 = data; break; |
| 1385 | 1375 | case 0x4818: |
| 1386 | 1376 | { |
| 1387 | | if(snes_spc7110.r481x != 0x07) |
| 1377 | if (snes_spc7110.r481x != 0x07) |
| 1388 | 1378 | break; |
| 1389 | 1379 | |
| 1390 | 1380 | snes_spc7110.r4818 = data; |
| r20880 | r20881 | |
| 1405 | 1395 | { |
| 1406 | 1396 | snes_spc7110.r4825 = data; |
| 1407 | 1397 | |
| 1408 | | if(snes_spc7110.r482e & 1) |
| 1398 | if (snes_spc7110.r482e & 1) |
| 1409 | 1399 | { |
| 1410 | 1400 | //signed 16-bit x 16-bit multiplication |
| 1411 | 1401 | INT16 r0 = (INT16)(snes_spc7110.r4824 + (snes_spc7110.r4825 << 8)); |
| r20880 | r20881 | |
| 1439 | 1429 | { |
| 1440 | 1430 | snes_spc7110.r4827 = data; |
| 1441 | 1431 | |
| 1442 | | if(snes_spc7110.r482e & 1) |
| 1432 | if (snes_spc7110.r482e & 1) |
| 1443 | 1433 | { |
| 1444 | 1434 | //signed 32-bit x 16-bit division |
| 1445 | 1435 | INT32 dividend = (INT32)(snes_spc7110.r4820 + (snes_spc7110.r4821 << 8) + (snes_spc7110.r4822 << 16) + (snes_spc7110.r4823 << 24)); |
| r20880 | r20881 | |
| 1448 | 1438 | INT32 quotient; |
| 1449 | 1439 | INT16 remainder; |
| 1450 | 1440 | |
| 1451 | | if(divisor) |
| 1441 | if (divisor) |
| 1452 | 1442 | { |
| 1453 | 1443 | quotient = (INT32)(dividend / divisor); |
| 1454 | 1444 | remainder = (INT32)(dividend % divisor); |
| r20880 | r20881 | |
| 1477 | 1467 | UINT32 quotient; |
| 1478 | 1468 | UINT16 remainder; |
| 1479 | 1469 | |
| 1480 | | if(divisor) |
| 1470 | if (divisor) |
| 1481 | 1471 | { |
| 1482 | 1472 | quotient = (UINT32)(dividend / divisor); |
| 1483 | 1473 | remainder = (UINT16)(dividend % divisor); |
| r20880 | r20881 | |
| 1628 | 1618 | } |
| 1629 | 1619 | |
| 1630 | 1620 | //disable timer |
| 1631 | | if((data & 2) && !(snes_spc7110.rtc_ram[15] & 2)) |
| 1621 | if ((data & 2) && !(snes_spc7110.rtc_ram[15] & 2)) |
| 1632 | 1622 | spc7110_update_time(machine, 0); |
| 1633 | 1623 | } |
| 1634 | 1624 | |
trunk/src/mame/machine/snessdd1.c
| r20880 | r20881 | |
| 8 | 8 | |
| 9 | 9 | ***************************************************************************/ |
| 10 | 10 | |
| 11 | | static UINT8 sdd1_read(running_machine& machine, UINT32 addr); |
| 12 | 11 | |
| 12 | #define SSD1_ADD(addr)\ |
| 13 | mmc[(addr >> 20) & 3] + (addr & 0x0fffff) |
| 14 | |
| 13 | 15 | class SDD1_IM //Input Manager |
| 14 | 16 | { |
| 15 | 17 | public: |
| 16 | | SDD1_IM(running_machine &machine) |
| 17 | | : m_machine(machine) { } |
| 18 | 18 | |
| 19 | | running_machine &machine() const { return m_machine; } |
| 19 | UINT32 m_byte_ptr; |
| 20 | UINT8 m_bit_count; |
| 20 | 21 | |
| 21 | | UINT32 byte_ptr; |
| 22 | | UINT8 bit_count; |
| 23 | | |
| 24 | | private: |
| 25 | | running_machine& m_machine; |
| 22 | void IM_prepareDecomp(UINT32 in_buf); |
| 23 | UINT8 IM_getCodeword(UINT8 *ROM, UINT32 *mmc, const UINT8 code_len); |
| 26 | 24 | }; |
| 27 | 25 | |
| 28 | | static void SDD1_IM_prepareDecomp(SDD1_IM* thisptr, UINT32 in_buf) |
| 26 | void SDD1_IM::IM_prepareDecomp(UINT32 in_buf) |
| 29 | 27 | { |
| 30 | | thisptr->byte_ptr = in_buf; |
| 31 | | thisptr->bit_count = 4; |
| 28 | m_byte_ptr = in_buf; |
| 29 | m_bit_count = 4; |
| 32 | 30 | } |
| 33 | 31 | |
| 34 | | static UINT8 SDD1_IM_getCodeword(SDD1_IM* thisptr, const UINT8 code_len) |
| 32 | UINT8 SDD1_IM::IM_getCodeword(UINT8 *ROM, UINT32 *mmc, const UINT8 code_len) |
| 35 | 33 | { |
| 36 | | UINT8 codeword; |
| 34 | UINT8 codeword = ROM[SSD1_ADD(m_byte_ptr)] << m_bit_count; |
| 37 | 35 | |
| 38 | | codeword = sdd1_read(thisptr->machine(), thisptr->byte_ptr) << thisptr->bit_count; |
| 36 | ++m_bit_count; |
| 39 | 37 | |
| 40 | | ++thisptr->bit_count; |
| 41 | | |
| 42 | 38 | if (codeword & 0x80) |
| 43 | 39 | { |
| 44 | | codeword |= sdd1_read(thisptr->machine(), thisptr->byte_ptr + 1) >> (9 - thisptr->bit_count); |
| 45 | | thisptr->bit_count += code_len; |
| 40 | codeword |= ROM[SSD1_ADD(m_byte_ptr + 1)] >> (9 - m_bit_count); |
| 41 | m_bit_count += code_len; |
| 46 | 42 | } |
| 47 | 43 | |
| 48 | | if (thisptr->bit_count & 0x08) |
| 44 | if (m_bit_count & 0x08) |
| 49 | 45 | { |
| 50 | | thisptr->byte_ptr++; |
| 51 | | thisptr->bit_count &= 0x07; |
| 46 | m_byte_ptr++; |
| 47 | m_bit_count &= 0x07; |
| 52 | 48 | } |
| 53 | 49 | |
| 54 | 50 | return codeword; |
| r20880 | r20881 | |
| 57 | 53 | class SDD1_GCD //Golomb-Code Decoder |
| 58 | 54 | { |
| 59 | 55 | public: |
| 60 | | SDD1_GCD(running_machine &machine, SDD1_IM* associatedIM) |
| 61 | | : IM(associatedIM), |
| 62 | | m_machine(machine) { } |
| 56 | SDD1_GCD(SDD1_IM* associatedIM) |
| 57 | : m_IM(associatedIM) { } |
| 63 | 58 | |
| 64 | | running_machine &machine() const { return m_machine; } |
| 59 | SDD1_IM* m_IM; |
| 65 | 60 | |
| 66 | | SDD1_IM* IM; |
| 67 | | |
| 68 | | private: |
| 69 | | running_machine& m_machine; |
| 61 | void GCD_getRunCount(UINT8 *ROM, UINT32 *mmc, UINT8 code_num, UINT8* MPScount, UINT8* LPSind); |
| 70 | 62 | }; |
| 71 | 63 | |
| 72 | | static void SDD1_GCD_getRunCount(SDD1_GCD* thisptr, UINT8 code_num, UINT8* MPScount, UINT8* LPSind) |
| 64 | void SDD1_GCD::GCD_getRunCount(UINT8 *ROM, UINT32 *mmc, UINT8 code_num, UINT8* MPScount, UINT8* LPSind) |
| 73 | 65 | { |
| 74 | 66 | const UINT8 run_count[] = |
| 75 | 67 | { |
| r20880 | r20881 | |
| 107 | 99 | 0x70, 0x30, 0x50, 0x10, 0x60, 0x20, 0x40, 0x00, |
| 108 | 100 | }; |
| 109 | 101 | |
| 110 | | UINT8 codeword = SDD1_IM_getCodeword(thisptr->IM, code_num); |
| 102 | UINT8 codeword = m_IM->IM_getCodeword(ROM, mmc, code_num); |
| 111 | 103 | |
| 112 | 104 | if (codeword & 0x80) |
| 113 | 105 | { |
| r20880 | r20881 | |
| 123 | 115 | class SDD1_BG // Bits Generator |
| 124 | 116 | { |
| 125 | 117 | public: |
| 126 | | SDD1_BG(running_machine &machine, SDD1_GCD* associatedGCD, UINT8 code) |
| 127 | | : code_num(code), |
| 128 | | GCD(associatedGCD), |
| 129 | | m_machine(machine) { } |
| 118 | SDD1_BG(SDD1_GCD* associatedGCD, UINT8 code) |
| 119 | : m_code_num(code), |
| 120 | m_GCD(associatedGCD) { } |
| 130 | 121 | |
| 131 | | running_machine &machine() const { return m_machine; } |
| 122 | UINT8 m_code_num; |
| 123 | UINT8 m_MPScount; |
| 124 | UINT8 m_LPSind; |
| 125 | SDD1_GCD* m_GCD; |
| 132 | 126 | |
| 133 | | UINT8 code_num; |
| 134 | | UINT8 MPScount; |
| 135 | | UINT8 LPSind; |
| 136 | | SDD1_GCD* GCD; |
| 137 | | |
| 138 | | public: |
| 139 | | running_machine& m_machine; |
| 127 | void BG_prepareDecomp(); |
| 128 | UINT8 BG_getBit(UINT8 *ROM, UINT32 *mmc, UINT8* endOfRun); |
| 140 | 129 | } ; |
| 141 | 130 | |
| 142 | | static void SDD1_BG_prepareDecomp(SDD1_BG* thisptr) |
| 131 | void SDD1_BG::BG_prepareDecomp() |
| 143 | 132 | { |
| 144 | | thisptr->MPScount = 0; |
| 145 | | thisptr->LPSind = 0; |
| 133 | m_MPScount = 0; |
| 134 | m_LPSind = 0; |
| 146 | 135 | } |
| 147 | 136 | |
| 148 | | static UINT8 SDD1_BG_getBit(SDD1_BG* thisptr, UINT8* endOfRun) |
| 137 | UINT8 SDD1_BG::BG_getBit(UINT8 *ROM, UINT32 *mmc, UINT8* endOfRun) |
| 149 | 138 | { |
| 150 | 139 | UINT8 bit; |
| 151 | 140 | |
| 152 | | if (!(thisptr->MPScount || thisptr->LPSind)) |
| 141 | if (!(m_MPScount || m_LPSind)) |
| 153 | 142 | { |
| 154 | | SDD1_GCD_getRunCount(thisptr->GCD, thisptr->code_num, &(thisptr->MPScount), &(thisptr->LPSind)); |
| 143 | m_GCD->GCD_getRunCount(ROM, mmc, m_code_num, &(m_MPScount), &(m_LPSind)); |
| 155 | 144 | } |
| 156 | 145 | |
| 157 | | if (thisptr->MPScount) |
| 146 | if (m_MPScount) |
| 158 | 147 | { |
| 159 | 148 | bit = 0; |
| 160 | | thisptr->MPScount--; |
| 149 | m_MPScount--; |
| 161 | 150 | } |
| 162 | 151 | else |
| 163 | 152 | { |
| 164 | 153 | bit = 1; |
| 165 | | thisptr->LPSind = 0; |
| 154 | m_LPSind = 0; |
| 166 | 155 | } |
| 167 | 156 | |
| 168 | | if (thisptr->MPScount || thisptr->LPSind) |
| 157 | if (m_MPScount || m_LPSind) |
| 169 | 158 | { |
| 170 | 159 | (*endOfRun) = 0; |
| 171 | 160 | } |
| r20880 | r20881 | |
| 185 | 174 | UINT8 nextIfLPS; |
| 186 | 175 | }; |
| 187 | 176 | |
| 188 | | static const SDD1_PEM_state SDD1_PEM_evolution_table[33] = |
| 177 | static const SDD1_PEM_state PEM_evolution_table[33] = |
| 189 | 178 | { |
| 190 | 179 | { 0,25,25}, |
| 191 | 180 | { 0, 2, 1}, |
| r20880 | r20881 | |
| 231 | 220 | class SDD1_PEM //Probability Estimation Module |
| 232 | 221 | { |
| 233 | 222 | public: |
| 234 | | SDD1_PEM(running_machine& machine, |
| 235 | | SDD1_BG* associatedBG0, SDD1_BG* associatedBG1, |
| 236 | | SDD1_BG* associatedBG2, SDD1_BG* associatedBG3, |
| 237 | | SDD1_BG* associatedBG4, SDD1_BG* associatedBG5, |
| 238 | | SDD1_BG* associatedBG6, SDD1_BG* associatedBG7) |
| 239 | | : m_machine(machine) |
| 223 | SDD1_PEM( |
| 224 | SDD1_BG* associatedBG0, SDD1_BG* associatedBG1, |
| 225 | SDD1_BG* associatedBG2, SDD1_BG* associatedBG3, |
| 226 | SDD1_BG* associatedBG4, SDD1_BG* associatedBG5, |
| 227 | SDD1_BG* associatedBG6, SDD1_BG* associatedBG7) |
| 240 | 228 | { |
| 241 | | BG[0] = associatedBG0; |
| 242 | | BG[1] = associatedBG1; |
| 243 | | BG[2] = associatedBG2; |
| 244 | | BG[3] = associatedBG3; |
| 245 | | BG[4] = associatedBG4; |
| 246 | | BG[5] = associatedBG5; |
| 247 | | BG[6] = associatedBG6; |
| 248 | | BG[7] = associatedBG7; |
| 229 | m_BG[0] = associatedBG0; |
| 230 | m_BG[1] = associatedBG1; |
| 231 | m_BG[2] = associatedBG2; |
| 232 | m_BG[3] = associatedBG3; |
| 233 | m_BG[4] = associatedBG4; |
| 234 | m_BG[5] = associatedBG5; |
| 235 | m_BG[6] = associatedBG6; |
| 236 | m_BG[7] = associatedBG7; |
| 249 | 237 | } |
| 250 | 238 | |
| 251 | | running_machine &machine() const { return m_machine; } |
| 239 | SDD1_PEM_ContextInfo m_contextInfo[32]; |
| 240 | SDD1_BG* m_BG[8]; |
| 252 | 241 | |
| 253 | | SDD1_PEM_ContextInfo contextInfo[32]; |
| 254 | | SDD1_BG* BG[8]; |
| 255 | | |
| 256 | | private: |
| 257 | | running_machine& m_machine; |
| 242 | void PEM_prepareDecomp(); |
| 243 | UINT8 PEM_getBit(UINT8 *ROM, UINT32 *mmc, UINT8 context); |
| 258 | 244 | } ; |
| 259 | 245 | |
| 260 | | static void SDD1_PEM_prepareDecomp(SDD1_PEM* thisptr) |
| 246 | void SDD1_PEM::PEM_prepareDecomp() |
| 261 | 247 | { |
| 262 | | UINT8 i; |
| 263 | | for(i = 0; i < 32; i++) |
| 248 | for (int i = 0; i < 32; i++) |
| 264 | 249 | { |
| 265 | | thisptr->contextInfo[i].status = 0; |
| 266 | | thisptr->contextInfo[i].MPS = 0; |
| 250 | m_contextInfo[i].status = 0; |
| 251 | m_contextInfo[i].MPS = 0; |
| 267 | 252 | } |
| 268 | 253 | } |
| 269 | 254 | |
| 270 | | static UINT8 SDD1_PEM_getBit(SDD1_PEM* thisptr, UINT8 context) |
| 255 | UINT8 SDD1_PEM::PEM_getBit(UINT8 *ROM, UINT32 *mmc, UINT8 context) |
| 271 | 256 | { |
| 272 | 257 | UINT8 endOfRun; |
| 273 | 258 | UINT8 bit; |
| 274 | 259 | |
| 275 | | SDD1_PEM_ContextInfo *pContInfo = &(thisptr->contextInfo)[context]; |
| 260 | SDD1_PEM_ContextInfo *pContInfo = &(m_contextInfo)[context]; |
| 276 | 261 | UINT8 currStatus = pContInfo->status; |
| 277 | | const SDD1_PEM_state* pState = &(SDD1_PEM_evolution_table[currStatus]); |
| 262 | const SDD1_PEM_state* pState = &(PEM_evolution_table[currStatus]); |
| 278 | 263 | UINT8 currentMPS = pContInfo->MPS; |
| 279 | 264 | |
| 280 | | bit = SDD1_BG_getBit(thisptr->BG[pState->code_num], &endOfRun); |
| 265 | bit = m_BG[pState->code_num]->BG_getBit(ROM, mmc, &endOfRun); |
| 281 | 266 | |
| 282 | 267 | if (endOfRun) |
| 283 | 268 | { |
| r20880 | r20881 | |
| 301 | 286 | class SDD1_CM |
| 302 | 287 | { |
| 303 | 288 | public: |
| 304 | | SDD1_CM(running_machine& machine, SDD1_PEM* associatedPEM) |
| 305 | | : PEM(associatedPEM), |
| 306 | | m_machine(machine) { } |
| 289 | SDD1_CM(SDD1_PEM* associatedPEM) |
| 290 | : m_PEM(associatedPEM) { } |
| 307 | 291 | |
| 308 | | running_machine &machine() const { return m_machine; } |
| 292 | UINT8 m_bitplanesInfo; |
| 293 | UINT8 m_contextBitsInfo; |
| 294 | UINT8 m_bit_number; |
| 295 | UINT8 m_currBitplane; |
| 296 | UINT16 m_prevBitplaneBits[8]; |
| 297 | SDD1_PEM* m_PEM; |
| 309 | 298 | |
| 310 | | UINT8 bitplanesInfo; |
| 311 | | UINT8 contextBitsInfo; |
| 312 | | UINT8 bit_number; |
| 313 | | UINT8 currBitplane; |
| 314 | | UINT16 prevBitplaneBits[8]; |
| 315 | | SDD1_PEM* PEM; |
| 316 | | |
| 317 | | private: |
| 318 | | running_machine& m_machine; |
| 299 | void CM_prepareDecomp(UINT8 *ROM, UINT32 *mmc, UINT32 first_byte); |
| 300 | UINT8 CM_getBit(UINT8 *ROM, UINT32 *mmc); |
| 319 | 301 | } ; |
| 320 | 302 | |
| 321 | | static void SDD1_CM_prepareDecomp(SDD1_CM* thisptr, UINT32 first_byte) |
| 303 | void SDD1_CM::CM_prepareDecomp(UINT8 *ROM, UINT32 *mmc, UINT32 first_byte) |
| 322 | 304 | { |
| 323 | 305 | INT32 i = 0; |
| 324 | | thisptr->bitplanesInfo = sdd1_read(thisptr->machine(), first_byte) & 0xc0; |
| 325 | | thisptr->contextBitsInfo = sdd1_read(thisptr->machine(), first_byte) & 0x30; |
| 326 | | thisptr->bit_number = 0; |
| 306 | m_bitplanesInfo = ROM[SSD1_ADD(first_byte)] & 0xc0; |
| 307 | m_contextBitsInfo = ROM[SSD1_ADD(first_byte)] & 0x30; |
| 308 | m_bit_number = 0; |
| 327 | 309 | for (i = 0; i < 8; i++) |
| 328 | 310 | { |
| 329 | | thisptr->prevBitplaneBits[i] = 0; |
| 311 | m_prevBitplaneBits[i] = 0; |
| 330 | 312 | } |
| 331 | | switch(thisptr->bitplanesInfo) |
| 313 | switch (m_bitplanesInfo) |
| 332 | 314 | { |
| 333 | 315 | case 0x00: |
| 334 | | thisptr->currBitplane = 1; |
| 316 | m_currBitplane = 1; |
| 335 | 317 | break; |
| 336 | 318 | case 0x40: |
| 337 | | thisptr->currBitplane = 7; |
| 319 | m_currBitplane = 7; |
| 338 | 320 | break; |
| 339 | 321 | case 0x80: |
| 340 | | thisptr->currBitplane = 3; |
| 322 | m_currBitplane = 3; |
| 341 | 323 | break; |
| 342 | 324 | } |
| 343 | 325 | } |
| 344 | 326 | |
| 345 | | static UINT8 SDD1_CM_getBit(SDD1_CM* thisptr) |
| 327 | UINT8 SDD1_CM::CM_getBit(UINT8 *ROM, UINT32 *mmc) |
| 346 | 328 | { |
| 347 | 329 | UINT8 currContext; |
| 348 | 330 | UINT16 *context_bits; |
| 349 | 331 | UINT8 bit = 0; |
| 350 | 332 | |
| 351 | | switch (thisptr->bitplanesInfo) |
| 333 | switch (m_bitplanesInfo) |
| 352 | 334 | { |
| 353 | 335 | case 0x00: |
| 354 | | thisptr->currBitplane ^= 0x01; |
| 336 | m_currBitplane ^= 0x01; |
| 355 | 337 | break; |
| 356 | 338 | case 0x40: |
| 357 | | thisptr->currBitplane ^= 0x01; |
| 358 | | if (!(thisptr->bit_number & 0x7f)) |
| 359 | | { |
| 360 | | thisptr->currBitplane = ((thisptr->currBitplane + 2) & 0x07); |
| 361 | | } |
| 339 | m_currBitplane ^= 0x01; |
| 340 | if (!(m_bit_number & 0x7f)) |
| 341 | m_currBitplane = ((m_currBitplane + 2) & 0x07); |
| 362 | 342 | break; |
| 363 | 343 | case 0x80: |
| 364 | | thisptr->currBitplane ^= 0x01; |
| 365 | | if (!(thisptr->bit_number & 0x7f)) |
| 366 | | { |
| 367 | | thisptr->currBitplane ^= 0x02; |
| 368 | | } |
| 344 | m_currBitplane ^= 0x01; |
| 345 | if (!(m_bit_number & 0x7f)) |
| 346 | m_currBitplane ^= 0x02; |
| 369 | 347 | break; |
| 370 | 348 | case 0xc0: |
| 371 | | thisptr->currBitplane = thisptr->bit_number & 0x07; |
| 349 | m_currBitplane = m_bit_number & 0x07; |
| 372 | 350 | break; |
| 373 | 351 | } |
| 374 | 352 | |
| 375 | | context_bits = &(thisptr->prevBitplaneBits)[thisptr->currBitplane]; |
| 353 | context_bits = &(m_prevBitplaneBits)[m_currBitplane]; |
| 376 | 354 | |
| 377 | | currContext = (thisptr->currBitplane & 0x01) << 4; |
| 378 | | switch (thisptr->contextBitsInfo) |
| 355 | currContext = (m_currBitplane & 0x01) << 4; |
| 356 | switch (m_contextBitsInfo) |
| 379 | 357 | { |
| 380 | 358 | case 0x00: |
| 381 | 359 | currContext |= ((*context_bits & 0x01c0) >> 5) | (*context_bits & 0x0001); |
| r20880 | r20881 | |
| 391 | 369 | break; |
| 392 | 370 | } |
| 393 | 371 | |
| 394 | | bit = SDD1_PEM_getBit(thisptr->PEM, currContext); |
| 372 | bit = m_PEM->PEM_getBit(ROM, mmc, currContext); |
| 395 | 373 | |
| 396 | 374 | *context_bits <<= 1; |
| 397 | 375 | *context_bits |= bit; |
| 398 | 376 | |
| 399 | | thisptr->bit_number++; |
| 377 | m_bit_number++; |
| 400 | 378 | |
| 401 | 379 | return bit; |
| 402 | 380 | } |
| r20880 | r20881 | |
| 404 | 382 | class SDD1_OL |
| 405 | 383 | { |
| 406 | 384 | public: |
| 407 | | SDD1_OL(running_machine& machine, SDD1_CM* associatedCM) |
| 408 | | : CM(associatedCM), |
| 409 | | m_machine(machine) { } |
| 385 | SDD1_OL(SDD1_CM* associatedCM) |
| 386 | : m_CM(associatedCM) { } |
| 410 | 387 | |
| 411 | | running_machine &machine() const { return m_machine; } |
| 388 | UINT8 m_bitplanesInfo; |
| 389 | UINT16 m_length; |
| 390 | UINT8* m_buffer; |
| 391 | SDD1_CM* m_CM; |
| 412 | 392 | |
| 413 | | UINT8 bitplanesInfo; |
| 414 | | UINT16 length; |
| 415 | | UINT8* buffer; |
| 416 | | SDD1_CM* CM; |
| 417 | | |
| 418 | | private: |
| 419 | | running_machine& m_machine; |
| 393 | void OL_prepareDecomp(UINT8 *ROM, UINT32 *mmc, UINT32 first_byte, UINT16 out_len, UINT8 *out_buf); |
| 394 | void OL_launch(UINT8 *ROM, UINT32 *mmc); |
| 420 | 395 | } ; |
| 421 | 396 | |
| 422 | | static void SDD1_OL_prepareDecomp(SDD1_OL* thisptr, UINT32 first_byte, UINT16 out_len, UINT8 *out_buf) |
| 397 | void SDD1_OL::OL_prepareDecomp(UINT8 *ROM, UINT32 *mmc, UINT32 first_byte, UINT16 out_len, UINT8 *out_buf) |
| 423 | 398 | { |
| 424 | | thisptr->bitplanesInfo = sdd1_read(thisptr->machine(), first_byte) & 0xc0; |
| 425 | | thisptr->length = out_len; |
| 426 | | thisptr->buffer = out_buf; |
| 399 | m_bitplanesInfo = ROM[SSD1_ADD(first_byte)] & 0xc0; |
| 400 | m_length = out_len; |
| 401 | m_buffer = out_buf; |
| 427 | 402 | } |
| 428 | 403 | |
| 429 | | static void SDD1_OL_launch(SDD1_OL* thisptr) |
| 404 | void SDD1_OL::OL_launch(UINT8 *ROM, UINT32 *mmc) |
| 430 | 405 | { |
| 431 | 406 | UINT8 i; |
| 432 | 407 | UINT8 register1 = 0, register2 = 0; |
| 433 | 408 | |
| 434 | | switch(thisptr->bitplanesInfo) |
| 409 | switch (m_bitplanesInfo) |
| 435 | 410 | { |
| 436 | 411 | case 0x00: |
| 437 | 412 | case 0x40: |
| r20880 | r20881 | |
| 439 | 414 | i = 1; |
| 440 | 415 | do |
| 441 | 416 | { // if length == 0, we output 2^16 bytes |
| 442 | | if(!i) |
| 417 | if (!i) |
| 443 | 418 | { |
| 444 | | *(thisptr->buffer++) = register2; |
| 419 | *(m_buffer++) = register2; |
| 445 | 420 | i = ~i; |
| 446 | 421 | } |
| 447 | 422 | else |
| 448 | 423 | { |
| 449 | | for(register1 = register2 = 0, i = 0x80; i; i >>= 1) |
| 424 | for (register1 = register2 = 0, i = 0x80; i; i >>= 1) |
| 450 | 425 | { |
| 451 | | if(SDD1_CM_getBit(thisptr->CM)) |
| 452 | | { |
| 426 | if (m_CM->CM_getBit(ROM, mmc)) |
| 453 | 427 | register1 |= i; |
| 454 | | } |
| 455 | | if(SDD1_CM_getBit(thisptr->CM)) |
| 456 | | { |
| 428 | |
| 429 | if (m_CM->CM_getBit(ROM, mmc)) |
| 457 | 430 | register2 |= i; |
| 458 | | } |
| 459 | 431 | } |
| 460 | | *(thisptr->buffer++) = register1; |
| 432 | *(m_buffer++) = register1; |
| 461 | 433 | } |
| 462 | | } while(--(thisptr->length)); |
| 434 | } while (--(m_length)); |
| 463 | 435 | break; |
| 464 | 436 | case 0xc0: |
| 465 | 437 | do |
| 466 | 438 | { |
| 467 | | for(register1 = 0, i = 0x01; i; i <<= 1) |
| 439 | for (register1 = 0, i = 0x01; i; i <<= 1) |
| 468 | 440 | { |
| 469 | | if(SDD1_CM_getBit(thisptr->CM)) |
| 441 | if (m_CM->CM_getBit(ROM, mmc)) |
| 470 | 442 | { |
| 471 | 443 | register1 |= i; |
| 472 | 444 | } |
| 473 | 445 | } |
| 474 | | *(thisptr->buffer++) = register1; |
| 475 | | } while(--(thisptr->length)); |
| 446 | *(m_buffer++) = register1; |
| 447 | } while (--(m_length)); |
| 476 | 448 | break; |
| 477 | 449 | } |
| 478 | 450 | } |
| r20880 | r20881 | |
| 484 | 456 | |
| 485 | 457 | running_machine &machine() const { return m_machine; } |
| 486 | 458 | |
| 487 | | SDD1_IM* IM; |
| 488 | | SDD1_GCD* GCD; |
| 489 | | SDD1_BG* BG0; SDD1_BG* BG1; SDD1_BG* BG2; SDD1_BG* BG3; |
| 490 | | SDD1_BG* BG4; SDD1_BG* BG5; SDD1_BG* BG6; SDD1_BG* BG7; |
| 491 | | SDD1_PEM* PEM; |
| 492 | | SDD1_CM* CM; |
| 493 | | SDD1_OL* OL; |
| 459 | SDD1_IM* m_IM; |
| 460 | SDD1_GCD* m_GCD; |
| 461 | SDD1_BG* m_BG0; SDD1_BG* m_BG1; SDD1_BG* m_BG2; SDD1_BG* m_BG3; |
| 462 | SDD1_BG* m_BG4; SDD1_BG* m_BG5; SDD1_BG* m_BG6; SDD1_BG* m_BG7; |
| 463 | SDD1_PEM* m_PEM; |
| 464 | SDD1_CM* m_CM; |
| 465 | SDD1_OL* m_OL; |
| 494 | 466 | |
| 467 | void SDD1emu_decompress(UINT8 *ROM, UINT32 *mmc, UINT32 in_buf, UINT16 out_len, UINT8 *out_buf); |
| 468 | |
| 495 | 469 | private: |
| 496 | 470 | running_machine& m_machine; |
| 497 | 471 | }; |
| r20880 | r20881 | |
| 499 | 473 | SDD1emu::SDD1emu(running_machine &machine) |
| 500 | 474 | : m_machine(machine) |
| 501 | 475 | { |
| 502 | | IM = auto_alloc(machine, SDD1_IM(machine)); |
| 503 | | GCD = auto_alloc(machine, SDD1_GCD(machine, IM)); |
| 504 | | BG0 = auto_alloc(machine, SDD1_BG(machine, GCD, 0)); |
| 505 | | BG1 = auto_alloc(machine, SDD1_BG(machine, GCD, 1)); |
| 506 | | BG2 = auto_alloc(machine, SDD1_BG(machine, GCD, 2)); |
| 507 | | BG3 = auto_alloc(machine, SDD1_BG(machine, GCD, 3)); |
| 508 | | BG4 = auto_alloc(machine, SDD1_BG(machine, GCD, 4)); |
| 509 | | BG5 = auto_alloc(machine, SDD1_BG(machine, GCD, 5)); |
| 510 | | BG6 = auto_alloc(machine, SDD1_BG(machine, GCD, 6)); |
| 511 | | BG7 = auto_alloc(machine, SDD1_BG(machine, GCD, 7)); |
| 512 | | PEM = auto_alloc(machine, SDD1_PEM(machine, BG0, BG1, BG2, BG3, |
| 513 | | BG4, BG5, BG6, BG7)); |
| 514 | | CM = auto_alloc(machine, SDD1_CM(machine, PEM)); |
| 515 | | OL = auto_alloc(machine, SDD1_OL(machine, CM)); |
| 476 | m_IM = auto_alloc(machine, SDD1_IM()); |
| 477 | m_GCD = auto_alloc(machine, SDD1_GCD(m_IM)); |
| 478 | m_BG0 = auto_alloc(machine, SDD1_BG(m_GCD, 0)); |
| 479 | m_BG1 = auto_alloc(machine, SDD1_BG(m_GCD, 1)); |
| 480 | m_BG2 = auto_alloc(machine, SDD1_BG(m_GCD, 2)); |
| 481 | m_BG3 = auto_alloc(machine, SDD1_BG(m_GCD, 3)); |
| 482 | m_BG4 = auto_alloc(machine, SDD1_BG(m_GCD, 4)); |
| 483 | m_BG5 = auto_alloc(machine, SDD1_BG(m_GCD, 5)); |
| 484 | m_BG6 = auto_alloc(machine, SDD1_BG(m_GCD, 6)); |
| 485 | m_BG7 = auto_alloc(machine, SDD1_BG(m_GCD, 7)); |
| 486 | m_PEM = auto_alloc(machine, SDD1_PEM(m_BG0, m_BG1, m_BG2, m_BG3, |
| 487 | m_BG4, m_BG5, m_BG6, m_BG7)); |
| 488 | m_CM = auto_alloc(machine, SDD1_CM(m_PEM)); |
| 489 | m_OL = auto_alloc(machine, SDD1_OL(m_CM)); |
| 516 | 490 | } |
| 517 | 491 | |
| 518 | | static void SDD1emu_decompress(SDD1emu* thisptr, UINT32 in_buf, UINT16 out_len, UINT8 *out_buf) |
| 492 | void SDD1emu::SDD1emu_decompress(UINT8 *ROM, UINT32 *mmc, UINT32 in_buf, UINT16 out_len, UINT8 *out_buf) |
| 519 | 493 | { |
| 520 | | SDD1_IM_prepareDecomp(thisptr->IM, in_buf); |
| 521 | | SDD1_BG_prepareDecomp(thisptr->BG0); |
| 522 | | SDD1_BG_prepareDecomp(thisptr->BG1); |
| 523 | | SDD1_BG_prepareDecomp(thisptr->BG2); |
| 524 | | SDD1_BG_prepareDecomp(thisptr->BG3); |
| 525 | | SDD1_BG_prepareDecomp(thisptr->BG4); |
| 526 | | SDD1_BG_prepareDecomp(thisptr->BG5); |
| 527 | | SDD1_BG_prepareDecomp(thisptr->BG6); |
| 528 | | SDD1_BG_prepareDecomp(thisptr->BG7); |
| 529 | | SDD1_PEM_prepareDecomp(thisptr->PEM); |
| 530 | | SDD1_CM_prepareDecomp(thisptr->CM, in_buf); |
| 531 | | SDD1_OL_prepareDecomp(thisptr->OL, in_buf, out_len, out_buf); |
| 494 | m_IM->IM_prepareDecomp(in_buf); |
| 495 | m_BG0->BG_prepareDecomp(); |
| 496 | m_BG1->BG_prepareDecomp(); |
| 497 | m_BG2->BG_prepareDecomp(); |
| 498 | m_BG3->BG_prepareDecomp(); |
| 499 | m_BG4->BG_prepareDecomp(); |
| 500 | m_BG5->BG_prepareDecomp(); |
| 501 | m_BG6->BG_prepareDecomp(); |
| 502 | m_BG7->BG_prepareDecomp(); |
| 503 | m_PEM->PEM_prepareDecomp(); |
| 504 | m_CM->CM_prepareDecomp(ROM, mmc, in_buf); |
| 505 | m_OL->OL_prepareDecomp(ROM, mmc, in_buf, out_len, out_buf); |
| 532 | 506 | |
| 533 | | SDD1_OL_launch(thisptr->OL); |
| 507 | m_OL->OL_launch(ROM, mmc); |
| 534 | 508 | } |
| 535 | 509 | |
| 536 | 510 | struct snes_sdd1_t |
| r20880 | r20881 | |
| 559 | 533 | |
| 560 | 534 | static void sdd1_init(running_machine& machine) |
| 561 | 535 | { |
| 562 | | UINT8 i; |
| 563 | | |
| 564 | 536 | snes_sdd1.sdd1_enable = 0x00; |
| 565 | 537 | snes_sdd1.xfer_enable = 0x00; |
| 566 | 538 | |
| r20880 | r20881 | |
| 569 | 541 | snes_sdd1.mmc[2] = 2 << 20; |
| 570 | 542 | snes_sdd1.mmc[3] = 3 << 20; |
| 571 | 543 | |
| 572 | | for(i = 0; i < 8; i++) |
| 544 | for (int i = 0; i < 8; i++) |
| 573 | 545 | { |
| 574 | 546 | snes_sdd1.dma[i].addr = 0; |
| 575 | 547 | snes_sdd1.dma[i].size = 0; |
| r20880 | r20881 | |
| 585 | 557 | { |
| 586 | 558 | addr &= 0xffff; |
| 587 | 559 | |
| 588 | | if((addr & 0x4380) == 0x4300) |
| 560 | if ((addr & 0x4380) == 0x4300) |
| 589 | 561 | { |
| 590 | 562 | return snes_r_io(space, addr & 0x7f); |
| 591 | 563 | } |
| r20880 | r20881 | |
| 609 | 581 | { |
| 610 | 582 | addr &= 0xffff; |
| 611 | 583 | |
| 612 | | if((addr & 0x4380) == 0x4300) |
| 584 | if ((addr & 0x4380) == 0x4300) |
| 613 | 585 | { |
| 614 | 586 | UINT8 channel = (addr >> 4) & 7; |
| 615 | 587 | switch(addr & 15) |
| r20880 | r20881 | |
| 664 | 636 | { |
| 665 | 637 | unsigned char *ROM = machine.root_device().memregion("cart")->base(); |
| 666 | 638 | |
| 667 | | if(snes_sdd1.sdd1_enable & snes_sdd1.xfer_enable) |
| 639 | if (snes_sdd1.sdd1_enable & snes_sdd1.xfer_enable) |
| 668 | 640 | { |
| 669 | 641 | // at least one channel has S-DD1 decompression enabled... |
| 670 | | UINT32 i; |
| 671 | | for(i = 0; i < 8; i++) |
| 642 | for (int i = 0; i < 8; i++) |
| 672 | 643 | { |
| 673 | | if(snes_sdd1.sdd1_enable & snes_sdd1.xfer_enable & (1 << i)) |
| 644 | if (snes_sdd1.sdd1_enable & snes_sdd1.xfer_enable & (1 << i)) |
| 674 | 645 | { |
| 675 | 646 | // S-DD1 always uses fixed transfer mode, so address will not change during transfer |
| 676 | | if((addr + 0xc00000) == snes_sdd1.dma[i].addr) |
| 647 | if ((addr + 0xc00000) == snes_sdd1.dma[i].addr) |
| 677 | 648 | { |
| 678 | 649 | UINT8 data; |
| 679 | | if(!snes_sdd1.buffer.ready) |
| 650 | if (!snes_sdd1.buffer.ready) |
| 680 | 651 | { |
| 681 | 652 | UINT8 temp; |
| 682 | 653 | // first byte read for channel performs full decompression. |
| r20880 | r20881 | |
| 688 | 659 | // so temporarily disable decompression mode for decompress() call. |
| 689 | 660 | temp = snes_sdd1.sdd1_enable; |
| 690 | 661 | snes_sdd1.sdd1_enable = 0; |
| 691 | | SDD1emu_decompress(snes_sdd1.sdd1emu, addr, snes_sdd1.buffer.size, snes_sdd1.buffer.data); |
| 662 | snes_sdd1.sdd1emu->SDD1emu_decompress(ROM, snes_sdd1.mmc, addr, snes_sdd1.buffer.size, snes_sdd1.buffer.data); |
| 692 | 663 | snes_sdd1.sdd1_enable = temp; |
| 693 | 664 | |
| 694 | 665 | snes_sdd1.buffer.ready = 1; |
| r20880 | r20881 | |
| 696 | 667 | |
| 697 | 668 | // fetch a decompressed byte; once buffer is depleted, disable channel and invalidate buffer |
| 698 | 669 | data = snes_sdd1.buffer.data[(UINT16)snes_sdd1.buffer.offset++]; |
| 699 | | if(snes_sdd1.buffer.offset >= snes_sdd1.buffer.size) |
| 670 | if (snes_sdd1.buffer.offset >= snes_sdd1.buffer.size) |
| 700 | 671 | { |
| 701 | 672 | snes_sdd1.buffer.ready = 0; |
| 702 | 673 | snes_sdd1.xfer_enable &= ~(1 << i); |