~ubuntu-branches/ubuntu/raring/mame/raring-proposed

« back to all changes in this revision

Viewing changes to mess/src/mess/machine/pce.c

  • Committer: Package Import Robot
  • Author(s): Jordi Mallach, Jordi Mallach, Emmanuel Kasper
  • Date: 2011-12-19 22:56:27 UTC
  • mfrom: (0.1.2)
  • Revision ID: package-import@ubuntu.com-20111219225627-ub5oga1oys4ogqzm
Tags: 0.144-1
[ Jordi Mallach ]
* Fix syntax errors in DEP5 copyright file (lintian).
* Use a versioned copyright Format specification field.
* Update Vcs-* URLs.
* Move transitional packages to the new metapackages section, and make
  them priority extra.
* Remove references to GNU/Linux and MESS sources from copyright.
* Add build variables for s390x.
* Use .xz tarballs as it cuts 4MB for the upstream sources.
* Add nplayers.ini as a patch. Update copyright file to add CC-BY-SA-3.0.

[ Emmanuel Kasper ]
* New upstream release. Closes: #651538.
* Add Free Desktop compliant png icons of various sizes taken from
  the hydroxygen iconset
* Mess is now built from a new source package, to avoid possible source
  incompatibilities between mame and the mess overlay.
* Mame-tools are not built from the mame source package anymore, but
  from the mess source package

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/************************************************************
2
 
 
3
 
PC Engine CD HW notes:
4
 
 
5
 
CD Interface Register 0x00 - CDC status
6
 
x--- ---- busy signal
7
 
-x-- ---- request signal
8
 
---x ---- cd signal
9
 
---- x--- i/o signal
10
 
 
11
 
CD Interface Register 0x03 - BRAM lock / CD status
12
 
-x-- ---- acknowledge signal
13
 
--x- ---- done signal
14
 
---x ---- bram signal
15
 
---- x--- ADPCM 2
16
 
---- -x-- ADPCM 1
17
 
---- --x- CDDA left/right speaker select
18
 
 
19
 
CD Interface Register 0x05 - CD-DA Volume low 8-bit port
20
 
 
21
 
CD Interface Register 0x06 - CD-DA Volume high 8-bit port
22
 
 
23
 
CD Interface Register 0x07 - BRAM unlock / CD status
24
 
x--- ---- Enables BRAM
25
 
 
26
 
CD Interface Register 0x0c - ADPCM status
27
 
x--- ---- ADPCM is reading data
28
 
---- x--- ADPCM playback (0) stopped (1) currently playing
29
 
---- -x-- pending ADPCM data write
30
 
---- ---x ADPCM playback (1) stopped (0) currently playing
31
 
 
32
 
CD Interface Register 0x0d - ADPCM address control
33
 
x--- ---- ADPCM reset
34
 
-x-- ---- ADPCM play
35
 
--x- ---- ADPCM repeat
36
 
---x ---- ADPCM set length
37
 
---- x--- ADPCM set read address
38
 
---- --xx ADPCM set write address
39
 
(note: some games reads bit 5 and wants it to be low otherwise they hangs, surely NOT an ADPCM repeat flag read because it doesn't make sense)
40
 
 
41
 
CD Interface Register 0x0e - ADPCM playback rate
42
 
 
43
 
CD Interface Register 0x0f - ADPCM fade in/out register
44
 
---- xxxx command setting:
45
 
0x00 ADPCM/CD-DA Fade-in
46
 
0x01 CD-DA fade-in
47
 
0x08 CD-DA fade-out (short) ADPCM fade-in
48
 
0x09 CD-DA fade-out (long)
49
 
0x0a ADPCM fade-out (long)
50
 
0x0c CD-DA fade-out (short) ADPCM fade-in
51
 
0x0d CD-DA fade-out (short)
52
 
0x0e ADPCM fade-out (short)
53
 
 
54
 
*************************************************************/
55
 
 
56
 
#include "emu.h"
57
 
#include "coreutil.h"
58
 
#include "cpu/h6280/h6280.h"
59
 
#include "includes/pce.h"
60
 
#include "imagedev/chd_cd.h"
61
 
#include "sound/msm5205.h"
62
 
#include "sound/cdda.h"
63
 
#include "hashfile.h"
64
 
 
65
 
 
66
 
#define PCE_BRAM_SIZE                           0x800
67
 
#define PCE_ADPCM_RAM_SIZE                      0x10000
68
 
#define PCE_ACARD_RAM_SIZE                      0x200000
69
 
#define PCE_CD_COMMAND_BUFFER_SIZE      0x100
70
 
 
71
 
#define PCE_CD_IRQ_TRANSFER_READY               0x40
72
 
#define PCE_CD_IRQ_TRANSFER_DONE                0x20
73
 
#define PCE_CD_IRQ_SAMPLE_FULL_PLAY             0x08
74
 
#define PCE_CD_IRQ_SAMPLE_HALF_PLAY             0x04
75
 
 
76
 
#define PCE_CD_ADPCM_PLAY_FLAG          0x08
77
 
#define PCE_CD_ADPCM_STOP_FLAG          0x01
78
 
 
79
 
#define PCE_CD_DATA_FRAMES_PER_SECOND   75
80
 
 
81
 
enum {
82
 
        PCE_CD_CDDA_OFF=0,
83
 
        PCE_CD_CDDA_PLAYING,
84
 
        PCE_CD_CDDA_PAUSED
85
 
};
86
 
 
87
 
 
88
 
/* CD Unit RAM */
89
 
 
90
 
/* MSM5205 ADPCM decoder definition */
91
 
static void pce_cd_msm5205_int(device_t *device);
92
 
const msm5205_interface pce_cd_msm5205_interface = {
93
 
        pce_cd_msm5205_int,     /* interrupt function */
94
 
        MSM5205_S48_4B          /* 1/48 prescaler, 4bit data */
95
 
};
96
 
 
97
 
 
98
 
/* joystick related data*/
99
 
 
100
 
#define JOY_CLOCK   0x01
101
 
#define JOY_RESET   0x02
102
 
 
103
 
 
104
 
/* prototypes */
105
 
static void pce_cd_init( running_machine &machine );
106
 
static void pce_cd_set_irq_line( running_machine &machine, int num, int state );
107
 
static TIMER_CALLBACK( pce_cd_adpcm_dma_timer_callback );
108
 
static TIMER_CALLBACK( pce_cd_cdda_fadeout_callback );
109
 
static TIMER_CALLBACK( pce_cd_cdda_fadein_callback );
110
 
static TIMER_CALLBACK( pce_cd_adpcm_fadeout_callback );
111
 
static TIMER_CALLBACK( pce_cd_adpcm_fadein_callback );
112
 
 
113
 
static WRITE8_HANDLER( pce_sf2_banking_w )
114
 
{
115
 
        memory_set_bankptr( space->machine(), "bank2", space->machine().region("user1")->base() + offset * 0x080000 + 0x080000 );
116
 
        memory_set_bankptr( space->machine(), "bank3", space->machine().region("user1")->base() + offset * 0x080000 + 0x088000 );
117
 
        memory_set_bankptr( space->machine(), "bank4", space->machine().region("user1")->base() + offset * 0x080000 + 0x0D0000 );
118
 
}
119
 
 
120
 
static WRITE8_HANDLER( pce_cartridge_ram_w )
121
 
{
122
 
        pce_state *state = space->machine().driver_data<pce_state>();
123
 
        state->m_cartridge_ram[offset] = data;
124
 
}
125
 
 
126
 
DEVICE_IMAGE_LOAD(pce_cart)
127
 
{
128
 
        pce_state *state = image.device().machine().driver_data<pce_state>();
129
 
        UINT32 size;
130
 
        int split_rom = 0, offset = 0;
131
 
        const char *extrainfo = NULL;
132
 
        unsigned char *ROM;
133
 
        logerror("*** DEVICE_IMAGE_LOAD(pce_cart) : %s\n", image.filename());
134
 
 
135
 
        /* open file to get size */
136
 
        ROM = image.device().machine().region("user1")->base();
137
 
 
138
 
        if (image.software_entry() == NULL)
139
 
                size = image.length();
140
 
        else
141
 
                size = image.get_software_region_length("rom");
142
 
 
143
 
        /* handle header accordingly */
144
 
        if ((size / 512) & 1)
145
 
        {
146
 
                logerror("*** DEVICE_IMAGE_LOAD(pce_cart) : Header present\n");
147
 
                size -= 512;
148
 
                offset = 512;
149
 
        }
150
 
 
151
 
        if (size > PCE_ROM_MAXSIZE)
152
 
                size = PCE_ROM_MAXSIZE;
153
 
 
154
 
        if (image.software_entry() == NULL)
155
 
        {
156
 
                image.fseek(offset, SEEK_SET);
157
 
                image.fread( ROM, size);
158
 
                extrainfo = hashfile_extrainfo(image);
159
 
        }
160
 
        else
161
 
                memcpy(ROM, image.get_software_region("rom") + offset, size);
162
 
 
163
 
        if (extrainfo)
164
 
        {
165
 
                logerror("extrainfo: %s\n", extrainfo);
166
 
                if (strstr(extrainfo, "ROM_SPLIT"))
167
 
                        split_rom = 1;
168
 
        }
169
 
 
170
 
        if (ROM[0x1fff] < 0xe0)
171
 
        {
172
 
                int i;
173
 
                UINT8 decrypted[256];
174
 
 
175
 
                logerror( "*** DEVICE_IMAGE_LOAD(pce_cart) : ROM image seems encrypted, decrypting...\n" );
176
 
 
177
 
                /* Initialize decryption table */
178
 
                for (i = 0; i < 256; i++)
179
 
                        decrypted[i] = ((i & 0x01) << 7) | ((i & 0x02) << 5) | ((i & 0x04) << 3) | ((i & 0x08) << 1) | ((i & 0x10) >> 1) | ((i & 0x20 ) >> 3) | ((i & 0x40) >> 5) | ((i & 0x80) >> 7);
180
 
 
181
 
                /* Decrypt ROM image */
182
 
                for (i = 0; i < size; i++)
183
 
                        ROM[i] = decrypted[ROM[i]];
184
 
        }
185
 
 
186
 
        /* check if we're dealing with a split rom image */
187
 
        if (size == 384 * 1024)
188
 
        {
189
 
                split_rom = 1;
190
 
                /* Mirror the upper 128KB part of the image */
191
 
                memcpy(ROM + 0x060000, ROM + 0x040000, 0x020000);       /* Set up 060000 - 07FFFF mirror */
192
 
        }
193
 
 
194
 
        /* set up the memory for a split rom image */
195
 
        if (split_rom)
196
 
        {
197
 
                logerror("Split rom detected, setting up memory accordingly\n");
198
 
                /* Set up ROM address space as follows:          */
199
 
                /* 000000 - 03FFFF : ROM data 000000 - 03FFFF    */
200
 
                /* 040000 - 07FFFF : ROM data 000000 - 03FFFF    */
201
 
                /* 080000 - 0BFFFF : ROM data 040000 - 07FFFF    */
202
 
                /* 0C0000 - 0FFFFF : ROM data 040000 - 07FFFF    */
203
 
                memcpy(ROM + 0x080000, ROM + 0x040000, 0x040000);       /* Set up 080000 - 0BFFFF region */
204
 
                memcpy(ROM + 0x0C0000, ROM + 0x040000, 0x040000);       /* Set up 0C0000 - 0FFFFF region */
205
 
                memcpy(ROM + 0x040000, ROM, 0x040000);          /* Set up 040000 - 07FFFF region */
206
 
        }
207
 
        else
208
 
        {
209
 
                /* mirror 256KB rom data */
210
 
                if (size <= 0x040000)
211
 
                        memcpy(ROM + 0x040000, ROM, 0x040000);
212
 
 
213
 
                /* mirror 512KB rom data */
214
 
                if (size <= 0x080000)
215
 
                        memcpy(ROM + 0x080000, ROM, 0x080000);
216
 
        }
217
 
 
218
 
        memory_set_bankptr(image.device().machine(), "bank1", ROM);
219
 
        memory_set_bankptr(image.device().machine(), "bank2", ROM + 0x080000);
220
 
        memory_set_bankptr(image.device().machine(), "bank3", ROM + 0x088000);
221
 
        memory_set_bankptr(image.device().machine(), "bank4", ROM + 0x0d0000);
222
 
 
223
 
        /* Check for Street fighter 2 */
224
 
        if (size == PCE_ROM_MAXSIZE)
225
 
        {
226
 
                image.device().machine().device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x01ff0, 0x01ff3, FUNC(pce_sf2_banking_w));
227
 
        }
228
 
 
229
 
        /* Check for Populous */
230
 
        if (!memcmp(ROM + 0x1F26, "POPULOUS", 8))
231
 
        {
232
 
                state->m_cartridge_ram = auto_alloc_array(image.device().machine(), UINT8, 0x8000);
233
 
                memory_set_bankptr(image.device().machine(), "bank2", state->m_cartridge_ram);
234
 
                image.device().machine().device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x080000, 0x087FFF, FUNC(pce_cartridge_ram_w));
235
 
        }
236
 
 
237
 
        /* Check for CD system card */
238
 
        state->m_sys3_card = 0;
239
 
        if (!memcmp(ROM + 0x3FFB6, "PC Engine CD-ROM SYSTEM", 23))
240
 
        {
241
 
                /* Check if 192KB additional system card ram should be used */
242
 
                if(!memcmp(ROM + 0x29D1, "VER. 3.", 7))                 { state->m_sys3_card = 1; } // JP version
243
 
                else if(!memcmp(ROM + 0x29C4, "VER. 3.", 7 ))   { state->m_sys3_card = 3; } // US version
244
 
 
245
 
                if(state->m_sys3_card)
246
 
                {
247
 
                        state->m_cartridge_ram = auto_alloc_array(image.device().machine(), UINT8, 0x30000);
248
 
                        memory_set_bankptr(image.device().machine(), "bank4", state->m_cartridge_ram);
249
 
                        image.device().machine().device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x0D0000, 0x0FFFFF, FUNC(pce_cartridge_ram_w));
250
 
                        image.device().machine().device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x080000, 0x087FFF, FUNC(pce_cd_acard_wram_r),FUNC(pce_cd_acard_wram_w));
251
 
                }
252
 
        }
253
 
        return 0;
254
 
}
255
 
 
256
 
#ifdef MESS
257
 
DRIVER_INIT( pce )
258
 
{
259
 
        pce_state *state = machine.driver_data<pce_state>();
260
 
        state->m_io_port_options = PCE_JOY_SIG | CONST_SIG;
261
 
}
262
 
#endif
263
 
 
264
 
DRIVER_INIT( tg16 )
265
 
{
266
 
        pce_state *state = machine.driver_data<pce_state>();
267
 
        state->m_io_port_options = TG_16_JOY_SIG | CONST_SIG;
268
 
}
269
 
 
270
 
DRIVER_INIT( sgx )
271
 
{
272
 
        pce_state *state = machine.driver_data<pce_state>();
273
 
        state->m_io_port_options = PCE_JOY_SIG | CONST_SIG;
274
 
}
275
 
 
276
 
MACHINE_START( pce )
277
 
{
278
 
        pce_cd_init( machine );
279
 
}
280
 
 
281
 
#ifdef MESS
282
 
MACHINE_RESET( pce )
283
 
{
284
 
        pce_state *state = machine.driver_data<pce_state>();
285
 
        pce_cd_t &pce_cd = state->m_cd;
286
 
        int joy_i;
287
 
 
288
 
        for (joy_i = 0; joy_i < 5; joy_i++)
289
 
                state->m_joy_6b_packet[joy_i] = 0;
290
 
 
291
 
        pce_cd.adpcm_read_buf = 0;
292
 
        pce_cd.adpcm_write_buf = 0;
293
 
 
294
 
        // TODO: add CD-DA stop command here
295
 
 
296
 
        pce_cd.regs[0x0c] |= PCE_CD_ADPCM_STOP_FLAG;
297
 
        pce_cd.regs[0x0c] &= ~PCE_CD_ADPCM_PLAY_FLAG;
298
 
        //pce_cd.regs[0x03] = (pce_cd.regs[0x03] & ~0x0c) | (PCE_CD_SAMPLE_STOP_PLAY);
299
 
 
300
 
        /* Note: Arcade Card BIOS contents are the same as System 3, only internal HW differs.
301
 
       We use a category to select between modes (some games can be run in either S-CD or A-CD modes) */
302
 
        state->m_acard = input_port_read(machine, "A_CARD") & 1;
303
 
}
304
 
 
305
 
/* todo: how many input ports does the PCE have? */
306
 
WRITE8_HANDLER ( pce_joystick_w )
307
 
{
308
 
        pce_state *state = space->machine().driver_data<pce_state>();
309
 
        int joy_i;
310
 
        UINT8 joy_type = input_port_read(space->machine(),"JOY_TYPE");
311
 
 
312
 
        h6280io_set_buffer(&space->device(), data);
313
 
 
314
 
    /* bump counter on a low-to-high transition of bit 1 */
315
 
    if ((!state->m_joystick_data_select) && (data & JOY_CLOCK))
316
 
    {
317
 
        state->m_joystick_port_select = (state->m_joystick_port_select + 1) & 0x07;
318
 
    }
319
 
 
320
 
    /* do we want buttons or direction? */
321
 
    state->m_joystick_data_select = data & JOY_CLOCK;
322
 
 
323
 
    /* clear counter if bit 2 is set */
324
 
    if (data & JOY_RESET)
325
 
    {
326
 
                state->m_joystick_port_select = 0;
327
 
 
328
 
                for (joy_i = 0; joy_i < 5; joy_i++)
329
 
                {
330
 
                        if (((joy_type >> (joy_i*2)) & 3) == 2)
331
 
                        state->m_joy_6b_packet[joy_i] ^= 1;
332
 
                }
333
 
    }
334
 
}
335
 
 
336
 
READ8_HANDLER ( pce_joystick_r )
337
 
{
338
 
        pce_state *state = space->machine().driver_data<pce_state>();
339
 
        static const char *const joyname[4][5] = {
340
 
                { "JOY_P1", "JOY_P2", "JOY_P3", "JOY_P4", "JOY_P5" },
341
 
                { },
342
 
                { "JOY6B_P1", "JOY6B_P2", "JOY6B_P3", "JOY6B_P4", "JOY6B_P5" },
343
 
                { }
344
 
        };
345
 
        UINT8 joy_type = input_port_read(space->machine(), "JOY_TYPE");
346
 
        UINT8 ret, data;
347
 
 
348
 
        if (state->m_joystick_port_select <= 4)
349
 
        {
350
 
                switch((joy_type >> (state->m_joystick_port_select*2)) & 3)
351
 
                {
352
 
                        case 0: //2-buttons pad
353
 
                                data = input_port_read(space->machine(), joyname[0][state->m_joystick_port_select]);
354
 
                                break;
355
 
                        case 2: //6-buttons pad
356
 
                                /*
357
 
                Two packets:
358
 
                1st packet: directions + I, II, Run, Select
359
 
                2nd packet: 6 buttons "header" (high 4 bits active low) + III, IV, V, VI
360
 
                Note that six buttons pad just doesn't work with (almost?) every single 2-button-only games, it's really just an after-thought and it is like this
361
 
                on real HW.
362
 
                */
363
 
                                data = input_port_read(space->machine(), joyname[2][state->m_joystick_port_select]) >> (state->m_joy_6b_packet[state->m_joystick_port_select]*8);
364
 
                                break;
365
 
                        default:
366
 
                                data = 0xff;
367
 
                                break;
368
 
                }
369
 
        }
370
 
        else
371
 
                data = 0xff;
372
 
 
373
 
 
374
 
        if (state->m_joystick_data_select)
375
 
                data >>= 4;
376
 
 
377
 
        ret = (data & 0x0f) | state->m_io_port_options;
378
 
#ifdef UNIFIED_PCE
379
 
        ret &= ~0x40;
380
 
#endif
381
 
 
382
 
        return (ret);
383
 
}
384
 
#endif
385
 
NVRAM_HANDLER( pce )
386
 
{
387
 
        pce_state *state = machine.driver_data<pce_state>();
388
 
        pce_cd_t &pce_cd = state->m_cd;
389
 
        if (read_or_write)
390
 
        {
391
 
                file->write(pce_cd.bram, PCE_BRAM_SIZE);
392
 
        }
393
 
        else
394
 
        {
395
 
                /* load battery backed memory from disk */
396
 
                if (file)
397
 
                        file->read(pce_cd.bram, PCE_BRAM_SIZE);
398
 
        }
399
 
}
400
 
 
401
 
static void pce_set_cd_bram( running_machine &machine )
402
 
{
403
 
        pce_state *state = machine.driver_data<pce_state>();
404
 
        pce_cd_t &pce_cd = state->m_cd;
405
 
        memory_set_bankptr( machine, "bank10", pce_cd.bram + ( pce_cd.bram_locked ? PCE_BRAM_SIZE : 0 ) );
406
 
}
407
 
 
408
 
static void adpcm_stop(running_machine &machine)
409
 
{
410
 
        pce_state *state = machine.driver_data<pce_state>();
411
 
        pce_cd_t &pce_cd = state->m_cd;
412
 
        pce_cd.regs[0x0c] |= PCE_CD_ADPCM_STOP_FLAG;
413
 
        pce_cd.regs[0x0c] &= ~PCE_CD_ADPCM_PLAY_FLAG;
414
 
        //pce_cd.regs[0x03] = (pce_cd.regs[0x03] & ~0x0c) | (PCE_CD_SAMPLE_STOP_PLAY);
415
 
        pce_cd_set_irq_line( machine, PCE_CD_IRQ_SAMPLE_FULL_PLAY, ASSERT_LINE );
416
 
        pce_cd.regs[0x0d] &= ~0x60;
417
 
        pce_cd.msm_idle = 1;
418
 
}
419
 
 
420
 
static void adpcm_play(running_machine &machine)
421
 
{
422
 
        pce_state *state = machine.driver_data<pce_state>();
423
 
        pce_cd_t &pce_cd = state->m_cd;
424
 
        pce_cd.regs[0x0c] &= ~PCE_CD_ADPCM_STOP_FLAG;
425
 
        pce_cd.regs[0x0c] |= PCE_CD_ADPCM_PLAY_FLAG;
426
 
        pce_cd_set_irq_line( machine, PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE );
427
 
        pce_cd.regs[0x03] = (pce_cd.regs[0x03] & ~0x0c);
428
 
        pce_cd.msm_idle = 0;
429
 
}
430
 
 
431
 
 
432
 
/* Callback for new data from the MSM5205.
433
 
  The PCE cd unit actually divides the clock signal supplied to
434
 
  the MSM5205. Currently we can only use static clocks for the
435
 
  MSM5205.
436
 
 */
437
 
static void pce_cd_msm5205_int(device_t *device)
438
 
{
439
 
        pce_state *state = device->machine().driver_data<pce_state>();
440
 
        pce_cd_t &pce_cd = state->m_cd;
441
 
        UINT8 msm_data;
442
 
 
443
 
//  popmessage("%08x %08x %08x %02x %02x",pce_cd.msm_start_addr,pce_cd.msm_end_addr,pce_cd.msm_half_addr,pce_cd.regs[0x0c],pce_cd.regs[0x0d]);
444
 
 
445
 
        if ( pce_cd.msm_idle )
446
 
                return;
447
 
 
448
 
        /* Supply new ADPCM data */
449
 
        msm_data = (pce_cd.msm_nibble) ? (pce_cd.adpcm_ram[pce_cd.msm_start_addr] & 0x0f) : ((pce_cd.adpcm_ram[pce_cd.msm_start_addr] & 0xf0) >> 4);
450
 
 
451
 
        msm5205_data_w(device, msm_data);
452
 
        pce_cd.msm_nibble ^= 1;
453
 
 
454
 
        if(pce_cd.msm_nibble == 0)
455
 
        {
456
 
                pce_cd.msm_start_addr++;
457
 
 
458
 
                if(pce_cd.msm_start_addr == pce_cd.msm_half_addr)
459
 
                {
460
 
                        //pce_cd_set_irq_line( device->machine(), PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE );
461
 
                        //pce_cd_set_irq_line( device->machine(), PCE_CD_IRQ_SAMPLE_HALF_PLAY, ASSERT_LINE );
462
 
                }
463
 
 
464
 
                if(pce_cd.msm_start_addr > pce_cd.msm_end_addr)
465
 
                {
466
 
                        //pce_cd_set_irq_line( device->machine(), PCE_CD_IRQ_SAMPLE_HALF_PLAY, CLEAR_LINE );
467
 
                        //pce_cd_set_irq_line( device->machine(), PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE );
468
 
                        adpcm_stop(device->machine());
469
 
                        msm5205_reset_w(device, 1);
470
 
                }
471
 
        }
472
 
}
473
 
 
474
 
#define SCSI_STATUS_OK                  0x00
475
 
#define SCSI_CHECK_CONDITION    0x02
476
 
 
477
 
static void pce_cd_reply_status_byte( pce_state *state, UINT8 status )
478
 
{
479
 
        pce_cd_t &pce_cd = state->m_cd;
480
 
logerror("Setting CD in reply_status_byte\n");
481
 
        pce_cd.scsi_CD = pce_cd.scsi_IO = pce_cd.scsi_REQ = 1;
482
 
        pce_cd.scsi_MSG = 0;
483
 
        pce_cd.message_after_status = 1;
484
 
        pce_cd.status_sent = pce_cd.message_sent = 0;
485
 
 
486
 
        if ( status == SCSI_STATUS_OK )
487
 
        {
488
 
                pce_cd.regs[0x01] = 0x00;
489
 
        }
490
 
        else
491
 
        {
492
 
                pce_cd.regs[0x01] = 0x01;
493
 
        }
494
 
}
495
 
 
496
 
/* 0x00 - TEST UNIT READY */
497
 
static void pce_cd_test_unit_ready( running_machine &machine )
498
 
{
499
 
        pce_state *state = machine.driver_data<pce_state>();
500
 
        pce_cd_t &pce_cd = state->m_cd;
501
 
        logerror("test unit ready\n");
502
 
        if ( pce_cd.cd )
503
 
        {
504
 
                logerror( "Sending STATUS_OK status\n" );
505
 
                pce_cd_reply_status_byte( state, SCSI_STATUS_OK );
506
 
        }
507
 
        else
508
 
        {
509
 
                logerror( "Sending CHECK_CONDITION status\n" );
510
 
                pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
511
 
        }
512
 
}
513
 
 
514
 
/* 0x08 - READ (6) */
515
 
static void pce_cd_read_6( running_machine &machine )
516
 
{
517
 
        pce_state *state = machine.driver_data<pce_state>();
518
 
        pce_cd_t &pce_cd = state->m_cd;
519
 
        UINT32 frame = ( ( pce_cd.command_buffer[1] & 0x1F ) << 16 ) | ( pce_cd.command_buffer[2] << 8 ) | pce_cd.command_buffer[3];
520
 
        UINT32 frame_count = pce_cd.command_buffer[4];
521
 
 
522
 
        /* Check for presence of a CD */
523
 
        if ( ! pce_cd.cd )
524
 
        {
525
 
                pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
526
 
                return;
527
 
        }
528
 
 
529
 
        if ( pce_cd.cdda_status != PCE_CD_CDDA_OFF )
530
 
        {
531
 
                pce_cd.cdda_status = PCE_CD_CDDA_OFF;
532
 
                cdda_stop_audio( machine.device( "cdda" ) );
533
 
                pce_cd.end_mark = 0;
534
 
        }
535
 
 
536
 
        pce_cd.current_frame = frame;
537
 
        pce_cd.end_frame = frame + frame_count;
538
 
 
539
 
        if ( frame_count == 0 )
540
 
        {
541
 
                /* Star Breaker uses this */
542
 
                popmessage("Read Sector frame count == 0, contact MESSdev");
543
 
                pce_cd_reply_status_byte( state, SCSI_STATUS_OK );
544
 
        }
545
 
        else
546
 
        {
547
 
                pce_cd.data_timer->adjust(attotime::from_hz( PCE_CD_DATA_FRAMES_PER_SECOND ), 0, attotime::from_hz( PCE_CD_DATA_FRAMES_PER_SECOND ));
548
 
        }
549
 
}
550
 
 
551
 
/* 0xD8 - SET AUDIO PLAYBACK START POSITION (NEC) */
552
 
static void pce_cd_nec_set_audio_start_position( running_machine &machine )
553
 
{
554
 
        pce_state *state = machine.driver_data<pce_state>();
555
 
        pce_cd_t &pce_cd = state->m_cd;
556
 
        UINT32  frame = 0;
557
 
 
558
 
        if ( ! pce_cd.cd )
559
 
        {
560
 
                /* Throw some error here */
561
 
                pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
562
 
                return;
563
 
        }
564
 
 
565
 
        switch( pce_cd.command_buffer[9] & 0xC0 )
566
 
        {
567
 
        case 0x00:
568
 
                popmessage("CD-DA set start mode 0x00, contact MESSdev");
569
 
                frame = ( pce_cd.command_buffer[3] << 16 ) | ( pce_cd.command_buffer[4] << 8 ) | pce_cd.command_buffer[5];
570
 
                break;
571
 
        case 0x40:
572
 
        {
573
 
                UINT8 m,s,f;
574
 
 
575
 
                m = bcd_2_dec( pce_cd.command_buffer[2]);
576
 
                s = bcd_2_dec( pce_cd.command_buffer[3]);
577
 
                f = bcd_2_dec( pce_cd.command_buffer[4]);
578
 
 
579
 
                frame = f + 75 * (s + m * 60);
580
 
                if(frame >= 525) // TODO: seven seconds gap? O_o
581
 
                        frame -= 525;
582
 
                break;
583
 
        }
584
 
        case 0x80:
585
 
                frame = pce_cd.toc->tracks[ bcd_2_dec( pce_cd.command_buffer[2] ) - 1 ].physframeofs;
586
 
                break;
587
 
        default:
588
 
                popmessage("CD-DA set start mode 0xc0, contact MESSdev");
589
 
                //assert( NULL == pce_cd_nec_set_audio_start_position );
590
 
                break;
591
 
        }
592
 
 
593
 
        pce_cd.current_frame = frame;
594
 
 
595
 
        if ( pce_cd.cdda_status == PCE_CD_CDDA_PAUSED )
596
 
        {
597
 
                pce_cd.cdda_status = PCE_CD_CDDA_OFF;
598
 
                cdda_stop_audio( machine.device( "cdda" ) );
599
 
                pce_cd.end_frame = pce_cd.last_frame;
600
 
                pce_cd.end_mark = 0;
601
 
        }
602
 
        else
603
 
        {
604
 
                if(pce_cd.command_buffer[1] & 0x03)
605
 
                {
606
 
                        pce_cd.cdda_status = PCE_CD_CDDA_PLAYING;
607
 
                        pce_cd.end_frame = pce_cd.last_frame; //get the end of the CD
608
 
                        cdda_start_audio( machine.device( "cdda" ), pce_cd.current_frame, pce_cd.end_frame - pce_cd.current_frame );
609
 
                        pce_cd.cdda_play_mode = (pce_cd.command_buffer[1] & 0x02) ? 2 : 3; // mode 2 sets IRQ at end
610
 
                        pce_cd.end_mark =  (pce_cd.command_buffer[1] & 0x02) ? 1 : 0;
611
 
                }
612
 
                else
613
 
                {
614
 
                        pce_cd.cdda_status = PCE_CD_CDDA_PLAYING;
615
 
                        pce_cd.end_frame = pce_cd.toc->tracks[ cdrom_get_track(pce_cd.cd, pce_cd.current_frame) + 1 ].physframeofs; //get the end of THIS track
616
 
                        cdda_start_audio( machine.device( "cdda" ), pce_cd.current_frame, pce_cd.end_frame - pce_cd.current_frame );
617
 
                        pce_cd.end_mark = 0;
618
 
                        pce_cd.cdda_play_mode = 3;
619
 
                }
620
 
        }
621
 
 
622
 
        pce_cd_reply_status_byte( state, SCSI_STATUS_OK );
623
 
        pce_cd_set_irq_line( machine, PCE_CD_IRQ_TRANSFER_DONE, ASSERT_LINE );
624
 
}
625
 
 
626
 
/* 0xD9 - SET AUDIO PLAYBACK END POSITION (NEC) */
627
 
static void pce_cd_nec_set_audio_stop_position( running_machine &machine )
628
 
{
629
 
        pce_state *state = machine.driver_data<pce_state>();
630
 
        pce_cd_t &pce_cd = state->m_cd;
631
 
        UINT32  frame = 0;
632
 
 
633
 
        if ( ! pce_cd.cd )
634
 
        {
635
 
                /* Throw some error here */
636
 
                pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
637
 
                return;
638
 
        }
639
 
 
640
 
        switch( pce_cd.command_buffer[9] & 0xC0 )
641
 
        {
642
 
        case 0x00:
643
 
                popmessage("CD-DA set end mode 0x00, contact MESSdev");
644
 
                frame = ( pce_cd.command_buffer[3] << 16 ) | ( pce_cd.command_buffer[4] << 8 ) | pce_cd.command_buffer[5];
645
 
                break;
646
 
        case 0x40:
647
 
        {
648
 
                UINT8 m,s,f;
649
 
 
650
 
                m = bcd_2_dec( pce_cd.command_buffer[2]);
651
 
                s = bcd_2_dec( pce_cd.command_buffer[3]);
652
 
                f = bcd_2_dec( pce_cd.command_buffer[4]);
653
 
 
654
 
                frame = f + 75 * (s + m * 60);
655
 
                if(frame >= 525) // TODO: seven seconds gap? O_o
656
 
                        frame -= 525;
657
 
                break;
658
 
        }
659
 
        case 0x80:
660
 
                frame = pce_cd.toc->tracks[ bcd_2_dec( pce_cd.command_buffer[2] ) - 1 ].physframeofs;
661
 
                break;
662
 
        default:
663
 
                popmessage("CD-DA set end mode 0xc0, contact MESSdev");
664
 
                //assert( NULL == pce_cd_nec_set_audio_start_position );
665
 
                break;
666
 
        }
667
 
 
668
 
        pce_cd.end_frame = frame;
669
 
        pce_cd.cdda_play_mode = pce_cd.command_buffer[1] & 0x03;
670
 
 
671
 
        if ( pce_cd.cdda_play_mode )
672
 
        {
673
 
                if ( pce_cd.cdda_status == PCE_CD_CDDA_PAUSED )
674
 
                {
675
 
                        cdda_pause_audio( machine.device( "cdda" ), 0 );
676
 
                }
677
 
                else
678
 
                {
679
 
                        cdda_start_audio( machine.device( "cdda" ), pce_cd.current_frame, pce_cd.end_frame - pce_cd.current_frame );
680
 
                        pce_cd.end_mark = 1;
681
 
                }
682
 
                pce_cd.cdda_status = PCE_CD_CDDA_PLAYING;
683
 
        }
684
 
        else
685
 
        {
686
 
                pce_cd.cdda_status = PCE_CD_CDDA_OFF;
687
 
                cdda_stop_audio( machine.device( "cdda" ) );
688
 
                pce_cd.end_frame = pce_cd.last_frame;
689
 
                pce_cd.end_mark = 0;
690
 
//      assert( NULL == pce_cd_nec_set_audio_stop_position );
691
 
        }
692
 
 
693
 
        pce_cd_reply_status_byte( state, SCSI_STATUS_OK );
694
 
        pce_cd_set_irq_line( machine, PCE_CD_IRQ_TRANSFER_DONE, ASSERT_LINE );
695
 
}
696
 
 
697
 
/* 0xDA - PAUSE (NEC) */
698
 
static void pce_cd_nec_pause( running_machine &machine )
699
 
{
700
 
        pce_state *state = machine.driver_data<pce_state>();
701
 
        pce_cd_t &pce_cd = state->m_cd;
702
 
 
703
 
        /* If no cd mounted throw an error */
704
 
        if ( ! pce_cd.cd )
705
 
        {
706
 
                pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
707
 
                return;
708
 
        }
709
 
 
710
 
        /* If there was no cdda playing, throw an error */
711
 
        if ( pce_cd.cdda_status == PCE_CD_CDDA_OFF )
712
 
        {
713
 
                pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
714
 
                return;
715
 
        }
716
 
 
717
 
        pce_cd.cdda_status = PCE_CD_CDDA_PAUSED;
718
 
        pce_cd.current_frame = cdda_get_audio_lba( machine.device( "cdda" ) );
719
 
        cdda_pause_audio( machine.device( "cdda" ), 1 );
720
 
        pce_cd_reply_status_byte( state, SCSI_STATUS_OK );
721
 
}
722
 
 
723
 
/* 0xDD - READ SUBCHANNEL Q (NEC) */
724
 
static void pce_cd_nec_get_subq( running_machine &machine )
725
 
{
726
 
        pce_state *state = machine.driver_data<pce_state>();
727
 
        pce_cd_t &pce_cd = state->m_cd;
728
 
        /* WP - I do not have access to chds with subchannel information yet, so I'm faking something here */
729
 
        UINT32 msf_abs, msf_rel, track, frame;
730
 
 
731
 
        if ( ! pce_cd.cd )
732
 
        {
733
 
                /* Throw some error here */
734
 
                pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
735
 
                return;
736
 
        }
737
 
 
738
 
        frame = pce_cd.current_frame;
739
 
 
740
 
        switch( pce_cd.cdda_status )
741
 
        {
742
 
        case PCE_CD_CDDA_PAUSED:
743
 
                pce_cd.data_buffer[0] = 2;
744
 
                frame = cdda_get_audio_lba( machine.device( "cdda" ) );
745
 
                break;
746
 
        case PCE_CD_CDDA_PLAYING:
747
 
                pce_cd.data_buffer[0] = 0;
748
 
                frame = cdda_get_audio_lba( machine.device( "cdda" ) );
749
 
                break;
750
 
        default:
751
 
                pce_cd.data_buffer[0] = 3;
752
 
                break;
753
 
        }
754
 
 
755
 
        msf_abs = lba_to_msf( frame );
756
 
        track = cdrom_get_track( pce_cd.cd, frame );
757
 
        msf_rel = lba_to_msf( frame - cdrom_get_track_start( pce_cd.cd, track ) );
758
 
 
759
 
        pce_cd.data_buffer[1] = 0;
760
 
        pce_cd.data_buffer[2] = dec_2_bcd( track+1 );           /* track */
761
 
        pce_cd.data_buffer[3] = 1;                                                      /* index */
762
 
        pce_cd.data_buffer[4] = ( msf_rel >> 16 ) & 0xFF;       /* M (relative) */
763
 
        pce_cd.data_buffer[5] = ( msf_rel >> 8 ) & 0xFF;        /* S (relative) */
764
 
        pce_cd.data_buffer[6] = msf_rel & 0xFF;                         /* F (relative) */
765
 
        pce_cd.data_buffer[7] = ( msf_abs >> 16 ) & 0xFF;       /* M (absolute) */
766
 
        pce_cd.data_buffer[8] = ( msf_abs >> 8 ) & 0xFF;        /* S (absolute) */
767
 
        pce_cd.data_buffer[9] = msf_abs & 0xFF;                         /* F (absolute) */
768
 
        pce_cd.data_buffer_size = 10;
769
 
 
770
 
        pce_cd.data_buffer_index = 0;
771
 
        pce_cd.data_transferred = 1;
772
 
        pce_cd.scsi_IO = 1;
773
 
        pce_cd.scsi_CD = 0;
774
 
}
775
 
 
776
 
/* 0xDE - GET DIR INFO (NEC) */
777
 
static void pce_cd_nec_get_dir_info( running_machine &machine )
778
 
{
779
 
        pce_state *state = machine.driver_data<pce_state>();
780
 
        pce_cd_t &pce_cd = state->m_cd;
781
 
        UINT32 frame, msf, track = 0;
782
 
        const cdrom_toc *toc;
783
 
        logerror("nec get dir info\n");
784
 
 
785
 
        if ( ! pce_cd.cd )
786
 
        {
787
 
                /* Throw some error here */
788
 
                pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
789
 
        }
790
 
 
791
 
        toc = cdrom_get_toc( pce_cd.cd );
792
 
 
793
 
        switch( pce_cd.command_buffer[1] )
794
 
        {
795
 
        case 0x00:              /* Get first and last track numbers */
796
 
                pce_cd.data_buffer[0] = dec_2_bcd(1);
797
 
                pce_cd.data_buffer[1] = dec_2_bcd(toc->numtrks);
798
 
                pce_cd.data_buffer_size = 2;
799
 
                break;
800
 
        case 0x01:              /* Get total disk size in MSF format */
801
 
                frame = toc->tracks[toc->numtrks-1].physframeofs;
802
 
                frame += toc->tracks[toc->numtrks-1].frames;
803
 
                msf = lba_to_msf( frame + 150 );
804
 
 
805
 
                pce_cd.data_buffer[0] = ( msf >> 16 ) & 0xFF;   /* M */
806
 
                pce_cd.data_buffer[1] = ( msf >> 8 ) & 0xFF;    /* S */
807
 
                pce_cd.data_buffer[2] = msf & 0xFF;                             /* F */
808
 
                pce_cd.data_buffer_size = 3;
809
 
                break;
810
 
        case 0x02:              /* Get track information */
811
 
                if ( pce_cd.command_buffer[2] == 0xAA )
812
 
                {
813
 
                        frame = toc->tracks[toc->numtrks-1].physframeofs;
814
 
                        frame += toc->tracks[toc->numtrks-1].frames;
815
 
                        pce_cd.data_buffer[3] = 0x04;   /* correct? */
816
 
                } else
817
 
                {
818
 
                        track = MAX( bcd_2_dec( pce_cd.command_buffer[2] ), 1 );
819
 
                        frame = toc->tracks[track-1].physframeofs;
820
 
                        pce_cd.data_buffer[3] = ( toc->tracks[track-1].trktype == CD_TRACK_AUDIO ) ? 0x00 : 0x04;
821
 
                }
822
 
                logerror("track = %d, frame = %d\n", track, frame );
823
 
                msf = lba_to_msf( frame + 150 );
824
 
                pce_cd.data_buffer[0] = ( msf >> 16 ) & 0xFF;   /* M */
825
 
                pce_cd.data_buffer[1] = ( msf >> 8 ) & 0xFF;    /* S */
826
 
                pce_cd.data_buffer[2] = msf & 0xFF;                             /* F */
827
 
                pce_cd.data_buffer_size = 4;
828
 
                break;
829
 
        default:
830
 
//      assert( pce_cd_nec_get_dir_info == NULL );  // Not implemented yet
831
 
                break;
832
 
        }
833
 
 
834
 
        pce_cd.data_buffer_index = 0;
835
 
        pce_cd.data_transferred = 1;
836
 
        pce_cd.scsi_IO = 1;
837
 
        pce_cd.scsi_CD = 0;
838
 
}
839
 
 
840
 
static void pce_cd_end_of_list( running_machine &machine )
841
 
{
842
 
        pce_state *state = machine.driver_data<pce_state>();
843
 
        pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
844
 
}
845
 
 
846
 
static void pce_cd_handle_data_output( running_machine &machine )
847
 
{
848
 
        pce_state *state = machine.driver_data<pce_state>();
849
 
        pce_cd_t &pce_cd = state->m_cd;
850
 
        static const struct {
851
 
                UINT8   command_byte;
852
 
                UINT8   command_size;
853
 
                void    (*command_handler)(running_machine &machine);
854
 
        } pce_cd_commands[] = {
855
 
                { 0x00, 6, pce_cd_test_unit_ready },                            /* TEST UNIT READY */
856
 
                { 0x08, 6, pce_cd_read_6 },                                                     /* READ (6) */
857
 
                { 0xD8,10, pce_cd_nec_set_audio_start_position },       /* NEC SET AUDIO PLAYBACK START POSITION */
858
 
                { 0xD9,10, pce_cd_nec_set_audio_stop_position },        /* NEC SET AUDIO PLAYBACK END POSITION */
859
 
                { 0xDA,10, pce_cd_nec_pause },                                          /* NEC PAUSE */
860
 
                { 0xDD,10, pce_cd_nec_get_subq },                                       /* NEC GET SUBCHANNEL Q */
861
 
                { 0xDE,10, pce_cd_nec_get_dir_info },                           /* NEC GET DIR INFO */
862
 
                { 0xFF, 1, pce_cd_end_of_list }                                         /* end of list marker */
863
 
        };
864
 
 
865
 
        if ( pce_cd.scsi_REQ && pce_cd.scsi_ACK )
866
 
        {
867
 
                /* Command byte received */
868
 
                logerror( "Command byte $%02X received\n", pce_cd.regs[0x01] );
869
 
 
870
 
                /* Check for buffer overflow */
871
 
                assert( pce_cd.command_buffer_index < PCE_CD_COMMAND_BUFFER_SIZE );
872
 
 
873
 
                pce_cd.command_buffer[pce_cd.command_buffer_index] = pce_cd.regs[0x01];
874
 
                pce_cd.command_buffer_index++;
875
 
                pce_cd.scsi_REQ = 0;
876
 
        }
877
 
 
878
 
        if ( ! pce_cd.scsi_REQ && ! pce_cd.scsi_ACK && pce_cd.command_buffer_index )
879
 
        {
880
 
                int i = 0;
881
 
 
882
 
                logerror( "Check if command done\n" );
883
 
 
884
 
                for( i = 0; pce_cd.command_buffer[0] > pce_cd_commands[i].command_byte; i++ );
885
 
 
886
 
                /* Check for unknown commands */
887
 
                if ( pce_cd.command_buffer[0] != pce_cd_commands[i].command_byte )
888
 
                {
889
 
                        logerror("Unrecognized command: %02X\n", pce_cd.command_buffer[0] );
890
 
                        if(pce_cd.command_buffer[0] == 0x03)
891
 
                                popmessage("CD command 0x03 issued (Request Sense), contact MESSdev");
892
 
                }
893
 
                assert( pce_cd.command_buffer[0] == pce_cd_commands[i].command_byte );
894
 
 
895
 
                if ( pce_cd.command_buffer_index == pce_cd_commands[i].command_size )
896
 
                {
897
 
                        (pce_cd_commands[i].command_handler)( machine );
898
 
                        pce_cd.command_buffer_index = 0;
899
 
                }
900
 
                else
901
 
                {
902
 
                        pce_cd.scsi_REQ = 1;
903
 
                }
904
 
        }
905
 
}
906
 
 
907
 
static void pce_cd_handle_data_input( running_machine &machine )
908
 
{
909
 
        pce_state *state = machine.driver_data<pce_state>();
910
 
        pce_cd_t &pce_cd = state->m_cd;
911
 
        if ( pce_cd.scsi_CD )
912
 
        {
913
 
                /* Command / Status byte */
914
 
                if ( pce_cd.scsi_REQ && pce_cd.scsi_ACK )
915
 
                {
916
 
                        logerror( "status sent\n" );
917
 
                        pce_cd.scsi_REQ = 0;
918
 
                        pce_cd.status_sent = 1;
919
 
                }
920
 
 
921
 
                if ( ! pce_cd.scsi_REQ && ! pce_cd.scsi_ACK && pce_cd.status_sent )
922
 
                {
923
 
                        pce_cd.status_sent = 0;
924
 
                        if ( pce_cd.message_after_status )
925
 
                        {
926
 
                                logerror( "message after status\n" );
927
 
                                pce_cd.message_after_status = 0;
928
 
                                pce_cd.scsi_MSG = pce_cd.scsi_REQ = 1;
929
 
                                pce_cd.regs[0x01] = 0;
930
 
                        }
931
 
                }
932
 
        }
933
 
        else
934
 
        {
935
 
                /* Data */
936
 
                if ( pce_cd.scsi_REQ && pce_cd.scsi_ACK )
937
 
                {
938
 
                        pce_cd.scsi_REQ = 0;
939
 
                }
940
 
 
941
 
                if ( ! pce_cd.scsi_REQ && ! pce_cd.scsi_ACK )
942
 
                {
943
 
                        if ( pce_cd.data_buffer_index == pce_cd.data_buffer_size )
944
 
                        {
945
 
                                pce_cd_set_irq_line( machine, PCE_CD_IRQ_TRANSFER_READY, CLEAR_LINE );
946
 
                                if ( pce_cd.data_transferred )
947
 
                                {
948
 
                                        pce_cd.data_transferred = 0;
949
 
                                        pce_cd_reply_status_byte( state, SCSI_STATUS_OK );
950
 
                                        pce_cd_set_irq_line( machine, PCE_CD_IRQ_TRANSFER_DONE, ASSERT_LINE );
951
 
                                }
952
 
                        }
953
 
                        else
954
 
                        {
955
 
                                logerror("Transfer byte from offset %d\n", pce_cd.data_buffer_index);
956
 
                                pce_cd.regs[0x01] = pce_cd.data_buffer[pce_cd.data_buffer_index];
957
 
                                pce_cd.data_buffer_index++;
958
 
                                pce_cd.scsi_REQ = 1;
959
 
                        }
960
 
                }
961
 
        }
962
 
}
963
 
 
964
 
static void pce_cd_handle_message_output( pce_state *state )
965
 
{
966
 
        pce_cd_t &pce_cd = state->m_cd;
967
 
        if ( pce_cd.scsi_REQ && pce_cd.scsi_ACK )
968
 
        {
969
 
                pce_cd.scsi_REQ = 0;
970
 
        }
971
 
}
972
 
 
973
 
static void pce_cd_handle_message_input( pce_state *state )
974
 
{
975
 
        pce_cd_t &pce_cd = state->m_cd;
976
 
        if ( pce_cd.scsi_REQ && pce_cd.scsi_ACK )
977
 
        {
978
 
                pce_cd.scsi_REQ = 0;
979
 
                pce_cd.message_sent = 1;
980
 
        }
981
 
 
982
 
        if ( ! pce_cd.scsi_REQ && ! pce_cd.scsi_ACK && pce_cd.message_sent )
983
 
        {
984
 
                pce_cd.message_sent = 0;
985
 
                pce_cd.scsi_BSY = 0;
986
 
        }
987
 
}
988
 
 
989
 
/* Update internal CD statuses */
990
 
static void pce_cd_update( running_machine &machine )
991
 
{
992
 
        pce_state *state = machine.driver_data<pce_state>();
993
 
        pce_cd_t &pce_cd = state->m_cd;
994
 
        /* Check for reset of CD unit */
995
 
        if ( pce_cd.scsi_RST != pce_cd.scsi_last_RST )
996
 
        {
997
 
                if ( pce_cd.scsi_RST )
998
 
                {
999
 
                        logerror("Performing CD reset\n");
1000
 
                        /* Reset internal data */
1001
 
                        pce_cd.scsi_BSY = pce_cd.scsi_SEL = pce_cd.scsi_CD = pce_cd.scsi_IO = 0;
1002
 
                        pce_cd.scsi_MSG = pce_cd.scsi_REQ = pce_cd.scsi_ATN = 0;
1003
 
                        pce_cd.cd_motor_on = 0;
1004
 
                        pce_cd.selected = 0;
1005
 
                        pce_cd.cdda_status = PCE_CD_CDDA_OFF;
1006
 
                        cdda_stop_audio( machine.device( "cdda" ) );
1007
 
                        pce_cd.adpcm_dma_timer->adjust(attotime::never); // stop ADPCM DMA here
1008
 
                }
1009
 
                pce_cd.scsi_last_RST = pce_cd.scsi_RST;
1010
 
        }
1011
 
 
1012
 
        /* Check if bus can be freed */
1013
 
        if ( ! pce_cd.scsi_SEL && ! pce_cd.scsi_BSY && pce_cd.selected )
1014
 
        {
1015
 
                logerror( "freeing bus\n" );
1016
 
                pce_cd.selected = 0;
1017
 
                pce_cd.scsi_CD = pce_cd.scsi_MSG = pce_cd.scsi_IO = pce_cd.scsi_REQ = 0;
1018
 
                pce_cd_set_irq_line( machine, PCE_CD_IRQ_TRANSFER_DONE, CLEAR_LINE );
1019
 
        }
1020
 
 
1021
 
        /* Select the CD device */
1022
 
        if ( pce_cd.scsi_SEL )
1023
 
        {
1024
 
                if ( ! pce_cd.selected )
1025
 
                {
1026
 
                        pce_cd.selected = 1;
1027
 
                        logerror("Setting CD in device selection\n");
1028
 
                        pce_cd.scsi_BSY = pce_cd.scsi_REQ = pce_cd.scsi_CD = 1;
1029
 
                        pce_cd.scsi_MSG = pce_cd.scsi_IO = 0;
1030
 
                }
1031
 
        }
1032
 
 
1033
 
        if ( pce_cd.scsi_ATN )
1034
 
        {
1035
 
        }
1036
 
        else
1037
 
        {
1038
 
                /* Check for data and pessage phases */
1039
 
                if ( pce_cd.scsi_BSY )
1040
 
                {
1041
 
                        if ( pce_cd.scsi_MSG )
1042
 
                        {
1043
 
                                /* message phase */
1044
 
                                if ( pce_cd.scsi_IO )
1045
 
                                {
1046
 
                                        pce_cd_handle_message_input(state);
1047
 
                                }
1048
 
                                else
1049
 
                                {
1050
 
                                        pce_cd_handle_message_output(state);
1051
 
                                }
1052
 
                        }
1053
 
                        else
1054
 
                        {
1055
 
                                /* data phase */
1056
 
                                if ( pce_cd.scsi_IO )
1057
 
                                {
1058
 
                                        /* Reading data from target */
1059
 
                                        pce_cd_handle_data_input( machine );
1060
 
                                }
1061
 
                                else
1062
 
                                {
1063
 
                                        /* Sending data to target */
1064
 
                                        pce_cd_handle_data_output( machine );
1065
 
                                }
1066
 
                        }
1067
 
                }
1068
 
        }
1069
 
 
1070
 
        /* FIXME: presumably CD-DA needs an irq interface for this */
1071
 
        if(cdda_audio_ended(machine.device("cdda")) && pce_cd.end_mark == 1)
1072
 
        {
1073
 
                switch(pce_cd.cdda_play_mode & 3)
1074
 
                {
1075
 
                        case 1: cdda_start_audio( machine.device( "cdda" ), pce_cd.current_frame, pce_cd.end_frame - pce_cd.current_frame ); pce_cd.end_mark = 1; break; //play with repeat
1076
 
                        case 2: pce_cd_set_irq_line( machine, PCE_CD_IRQ_TRANSFER_DONE, ASSERT_LINE ); pce_cd.end_mark = 0; break; //irq when finished
1077
 
                        case 3: pce_cd.end_mark = 0; break; //play without repeat
1078
 
                }
1079
 
        }
1080
 
}
1081
 
 
1082
 
static void pce_cd_set_irq_line( running_machine &machine, int num, int state )
1083
 
{
1084
 
        pce_state *drvstate = machine.driver_data<pce_state>();
1085
 
        pce_cd_t &pce_cd = drvstate->m_cd;
1086
 
        switch( num )
1087
 
        {
1088
 
        case PCE_CD_IRQ_TRANSFER_DONE:
1089
 
                if ( state == ASSERT_LINE )
1090
 
                {
1091
 
                        pce_cd.regs[0x03] |= PCE_CD_IRQ_TRANSFER_DONE;
1092
 
                }
1093
 
                else
1094
 
                {
1095
 
                        pce_cd.regs[0x03] &= ~ PCE_CD_IRQ_TRANSFER_DONE;
1096
 
                }
1097
 
                break;
1098
 
        case PCE_CD_IRQ_TRANSFER_READY:
1099
 
                if ( state == ASSERT_LINE )
1100
 
                {
1101
 
                        pce_cd.regs[0x03] |= PCE_CD_IRQ_TRANSFER_READY;
1102
 
                }
1103
 
                else
1104
 
                {
1105
 
                        pce_cd.regs[0x03] &= ~ PCE_CD_IRQ_TRANSFER_READY;
1106
 
                }
1107
 
                break;
1108
 
        case PCE_CD_IRQ_SAMPLE_FULL_PLAY:
1109
 
                if ( state == ASSERT_LINE )
1110
 
                {
1111
 
                        pce_cd.regs[0x03] |= PCE_CD_IRQ_SAMPLE_FULL_PLAY;
1112
 
                        //printf("x %02x %02x\n",pce_cd.regs[0x02],pce_cd.regs[0x03]);
1113
 
                }
1114
 
                else
1115
 
                {
1116
 
                        pce_cd.regs[0x03] &= ~ PCE_CD_IRQ_SAMPLE_FULL_PLAY;
1117
 
                }
1118
 
                break;
1119
 
        case PCE_CD_IRQ_SAMPLE_HALF_PLAY:
1120
 
                if ( state == ASSERT_LINE )
1121
 
                {
1122
 
                        pce_cd.regs[0x03] |= PCE_CD_IRQ_SAMPLE_HALF_PLAY;
1123
 
                        //printf("y %02x %02x\n",pce_cd.regs[0x02],pce_cd.regs[0x03]);
1124
 
                }
1125
 
                else
1126
 
                {
1127
 
                        pce_cd.regs[0x03] &= ~ PCE_CD_IRQ_SAMPLE_HALF_PLAY;
1128
 
                }
1129
 
                break;
1130
 
        default:
1131
 
                break;
1132
 
        }
1133
 
 
1134
 
        if ( pce_cd.regs[0x02] & pce_cd.regs[0x03] & ( PCE_CD_IRQ_TRANSFER_DONE | PCE_CD_IRQ_TRANSFER_READY | PCE_CD_IRQ_SAMPLE_HALF_PLAY | PCE_CD_IRQ_SAMPLE_FULL_PLAY) )
1135
 
        {
1136
 
                cputag_set_input_line(machine, "maincpu", 1, ASSERT_LINE );
1137
 
        }
1138
 
        else
1139
 
        {
1140
 
                cputag_set_input_line(machine, "maincpu", 1, CLEAR_LINE );
1141
 
        }
1142
 
}
1143
 
 
1144
 
static TIMER_CALLBACK( pce_cd_data_timer_callback )
1145
 
{
1146
 
        pce_state *state = machine.driver_data<pce_state>();
1147
 
        pce_cd_t &pce_cd = state->m_cd;
1148
 
        if ( pce_cd.data_buffer_index == pce_cd.data_buffer_size )
1149
 
        {
1150
 
                /* Read next data sector */
1151
 
                logerror("read sector %d\n", pce_cd.current_frame );
1152
 
                if ( ! cdrom_read_data( pce_cd.cd, pce_cd.current_frame, pce_cd.data_buffer, CD_TRACK_MODE1 ) )
1153
 
                {
1154
 
                        logerror("Mode1 CD read failed for frame #%d\n", pce_cd.current_frame );
1155
 
                }
1156
 
                else
1157
 
                {
1158
 
                        logerror("Succesfully read mode1 frame #%d\n", pce_cd.current_frame );
1159
 
                }
1160
 
 
1161
 
                pce_cd.data_buffer_index = 0;
1162
 
                pce_cd.data_buffer_size = 2048;
1163
 
                pce_cd.current_frame++;
1164
 
 
1165
 
                pce_cd.scsi_IO = 1;
1166
 
                pce_cd.scsi_CD = 0;
1167
 
 
1168
 
                if ( pce_cd.current_frame == pce_cd.end_frame )
1169
 
                {
1170
 
                        /* We are done, disable the timer */
1171
 
                        logerror("Last frame read from CD\n");
1172
 
                        pce_cd.data_transferred = 1;
1173
 
                        pce_cd.data_timer->adjust(attotime::never);
1174
 
                }
1175
 
                else
1176
 
                {
1177
 
                        pce_cd.data_transferred = 0;
1178
 
                }
1179
 
        }
1180
 
}
1181
 
 
1182
 
static void pce_cd_init( running_machine &machine )
1183
 
{
1184
 
        pce_state *state = machine.driver_data<pce_state>();
1185
 
        pce_cd_t &pce_cd = state->m_cd;
1186
 
        cdrom_image_device *device;
1187
 
 
1188
 
        /* Initialize pce_cd struct */
1189
 
        memset( &pce_cd, 0, sizeof(pce_cd) );
1190
 
 
1191
 
        /* Initialize BRAM */
1192
 
        pce_cd.bram = auto_alloc_array(machine, UINT8, PCE_BRAM_SIZE * 2 );
1193
 
        memset( pce_cd.bram, 0, PCE_BRAM_SIZE );
1194
 
        memset( pce_cd.bram + PCE_BRAM_SIZE, 0xFF, PCE_BRAM_SIZE );
1195
 
        pce_cd.bram_locked = 1;
1196
 
        pce_set_cd_bram(machine);
1197
 
 
1198
 
        /* set up adpcm related things */
1199
 
        pce_cd.adpcm_ram = auto_alloc_array(machine, UINT8, PCE_ADPCM_RAM_SIZE );
1200
 
        memset( pce_cd.adpcm_ram, 0, PCE_ADPCM_RAM_SIZE );
1201
 
        pce_cd.adpcm_clock_divider = 1;
1202
 
        msm5205_change_clock_w(machine.device("msm5205"), (PCE_CD_CLOCK / 6) / pce_cd.adpcm_clock_divider);
1203
 
 
1204
 
        /* Set up cd command buffer */
1205
 
        pce_cd.command_buffer = auto_alloc_array(machine, UINT8, PCE_CD_COMMAND_BUFFER_SIZE );
1206
 
        memset( pce_cd.command_buffer, 0, PCE_CD_COMMAND_BUFFER_SIZE );
1207
 
        pce_cd.command_buffer_index = 0;
1208
 
 
1209
 
        /* Set up Arcade Card RAM buffer */
1210
 
        pce_cd.acard_ram = auto_alloc_array(machine, UINT8, PCE_ACARD_RAM_SIZE );
1211
 
        memset( pce_cd.acard_ram, 0, PCE_ACARD_RAM_SIZE );
1212
 
 
1213
 
        pce_cd.data_buffer = auto_alloc_array(machine, UINT8, 8192 );
1214
 
        memset( pce_cd.data_buffer, 0, 8192 );
1215
 
        pce_cd.data_buffer_size = 0;
1216
 
        pce_cd.data_buffer_index = 0;
1217
 
 
1218
 
        pce_cd.subcode_buffer = auto_alloc_array(machine, UINT8, 96 );
1219
 
 
1220
 
        device = machine.device<cdrom_image_device>("cdrom");
1221
 
        if ( device )
1222
 
        {
1223
 
                pce_cd.cd = device->get_cdrom_file();
1224
 
                if ( pce_cd.cd )
1225
 
                {
1226
 
                        pce_cd.toc = cdrom_get_toc( pce_cd.cd );
1227
 
                        cdda_set_cdrom( machine.device("cdda"), pce_cd.cd );
1228
 
                        pce_cd.last_frame = cdrom_get_track_start( pce_cd.cd, cdrom_get_last_track( pce_cd.cd ) - 1 );
1229
 
                        pce_cd.last_frame += pce_cd.toc->tracks[ cdrom_get_last_track( pce_cd.cd ) - 1 ].frames;
1230
 
                        pce_cd.end_frame = pce_cd.last_frame;
1231
 
                }
1232
 
        }
1233
 
 
1234
 
        pce_cd.data_timer = machine.scheduler().timer_alloc(FUNC(pce_cd_data_timer_callback));
1235
 
        pce_cd.data_timer->adjust(attotime::never);
1236
 
        pce_cd.adpcm_dma_timer = machine.scheduler().timer_alloc(FUNC(pce_cd_adpcm_dma_timer_callback));
1237
 
        pce_cd.adpcm_dma_timer->adjust(attotime::never);
1238
 
 
1239
 
        pce_cd.cdda_fadeout_timer = machine.scheduler().timer_alloc(FUNC(pce_cd_cdda_fadeout_callback));
1240
 
        pce_cd.cdda_fadeout_timer->adjust(attotime::never);
1241
 
        pce_cd.cdda_fadein_timer = machine.scheduler().timer_alloc(FUNC(pce_cd_cdda_fadein_callback));
1242
 
        pce_cd.cdda_fadein_timer->adjust(attotime::never);
1243
 
 
1244
 
        pce_cd.adpcm_fadeout_timer = machine.scheduler().timer_alloc(FUNC(pce_cd_adpcm_fadeout_callback));
1245
 
        pce_cd.adpcm_fadeout_timer->adjust(attotime::never);
1246
 
        pce_cd.adpcm_fadein_timer = machine.scheduler().timer_alloc(FUNC(pce_cd_adpcm_fadein_callback));
1247
 
        pce_cd.adpcm_fadein_timer->adjust(attotime::never);
1248
 
}
1249
 
 
1250
 
WRITE8_HANDLER( pce_cd_bram_w )
1251
 
{
1252
 
        pce_state *state = space->machine().driver_data<pce_state>();
1253
 
        pce_cd_t &pce_cd = state->m_cd;
1254
 
        if ( ! pce_cd.bram_locked )
1255
 
        {
1256
 
                pce_cd.bram[ offset ] = data;
1257
 
        }
1258
 
}
1259
 
 
1260
 
static void pce_cd_set_adpcm_ram_byte(running_machine &machine, UINT8 val)
1261
 
{
1262
 
        pce_state *state = machine.driver_data<pce_state>();
1263
 
        pce_cd_t &pce_cd = state->m_cd;
1264
 
        if(pce_cd.adpcm_write_buf > 0)
1265
 
        {
1266
 
                pce_cd.adpcm_write_buf--;
1267
 
        }
1268
 
        else
1269
 
        {
1270
 
                pce_cd.adpcm_ram[pce_cd.adpcm_write_ptr] = val;
1271
 
                pce_cd.adpcm_write_ptr = ((pce_cd.adpcm_write_ptr + 1) & 0xffff);
1272
 
                //TODO: length + 1
1273
 
        }
1274
 
}
1275
 
 
1276
 
static TIMER_CALLBACK( pce_cd_cdda_fadeout_callback )
1277
 
{
1278
 
        pce_state *state = machine.driver_data<pce_state>();
1279
 
        pce_cd_t &pce_cd = state->m_cd;
1280
 
        pce_cd.cdda_volume-= 0.1;
1281
 
 
1282
 
        if(pce_cd.cdda_volume <= 0)
1283
 
        {
1284
 
                pce_cd.cdda_volume = 0.0;
1285
 
                cdda_set_volume(machine.device("cdda"), 0.0);
1286
 
                pce_cd.cdda_fadeout_timer->adjust(attotime::never);
1287
 
        }
1288
 
        else
1289
 
        {
1290
 
                cdda_set_volume(machine.device("cdda"), pce_cd.cdda_volume);
1291
 
                pce_cd.cdda_fadeout_timer->adjust(attotime::from_usec(param), param);
1292
 
        }
1293
 
}
1294
 
 
1295
 
static TIMER_CALLBACK( pce_cd_cdda_fadein_callback )
1296
 
{
1297
 
        pce_state *state = machine.driver_data<pce_state>();
1298
 
        pce_cd_t &pce_cd = state->m_cd;
1299
 
        pce_cd.cdda_volume+= 0.1;
1300
 
 
1301
 
        if(pce_cd.cdda_volume >= 100.0)
1302
 
        {
1303
 
                pce_cd.cdda_volume = 100.0;
1304
 
                cdda_set_volume(machine.device("cdda"), 100.0);
1305
 
                pce_cd.cdda_fadein_timer->adjust(attotime::never);
1306
 
        }
1307
 
        else
1308
 
        {
1309
 
                cdda_set_volume(machine.device("cdda"), pce_cd.cdda_volume);
1310
 
                pce_cd.cdda_fadein_timer->adjust(attotime::from_usec(param), param);
1311
 
        }
1312
 
}
1313
 
 
1314
 
static TIMER_CALLBACK( pce_cd_adpcm_fadeout_callback )
1315
 
{
1316
 
        pce_state *state = machine.driver_data<pce_state>();
1317
 
        pce_cd_t &pce_cd = state->m_cd;
1318
 
        pce_cd.adpcm_volume-= 0.1;
1319
 
 
1320
 
        if(pce_cd.adpcm_volume <= 0)
1321
 
        {
1322
 
                pce_cd.adpcm_volume = 0.0;
1323
 
                msm5205_set_volume(machine.device("msm5205"), 0.0);
1324
 
                pce_cd.adpcm_fadeout_timer->adjust(attotime::never);
1325
 
        }
1326
 
        else
1327
 
        {
1328
 
                msm5205_set_volume(machine.device("msm5205"), pce_cd.adpcm_volume);
1329
 
                pce_cd.adpcm_fadeout_timer->adjust(attotime::from_usec(param), param);
1330
 
        }
1331
 
}
1332
 
 
1333
 
static TIMER_CALLBACK( pce_cd_adpcm_fadein_callback )
1334
 
{
1335
 
        pce_state *state = machine.driver_data<pce_state>();
1336
 
        pce_cd_t &pce_cd = state->m_cd;
1337
 
        pce_cd.adpcm_volume+= 0.1;
1338
 
 
1339
 
        if(pce_cd.adpcm_volume >= 100.0)
1340
 
        {
1341
 
                pce_cd.adpcm_volume = 100.0;
1342
 
                msm5205_set_volume(machine.device("msm5205"), 100.0);
1343
 
                pce_cd.adpcm_fadein_timer->adjust(attotime::never);
1344
 
        }
1345
 
        else
1346
 
        {
1347
 
                msm5205_set_volume(machine.device("msm5205"), pce_cd.adpcm_volume);
1348
 
                pce_cd.adpcm_fadein_timer->adjust(attotime::from_usec(param), param);
1349
 
        }
1350
 
}
1351
 
 
1352
 
 
1353
 
WRITE8_HANDLER( pce_cd_intf_w )
1354
 
{
1355
 
        pce_state *state = space->machine().driver_data<pce_state>();
1356
 
        pce_cd_t &pce_cd = state->m_cd;
1357
 
        pce_cd_update(space->machine());
1358
 
 
1359
 
        if(offset & 0x200 && state->m_sys3_card && state->m_acard) // route Arcade Card handling ports
1360
 
                return pce_cd_acard_w(space,offset,data);
1361
 
 
1362
 
        logerror("%04X: write to CD interface offset %02X, data %02X\n", cpu_get_pc(&space->device()), offset, data );
1363
 
 
1364
 
        switch( offset & 0xf )
1365
 
        {
1366
 
        case 0x00:      /* CDC status */
1367
 
                /* select device (which bits??) */
1368
 
                pce_cd.scsi_SEL = 1;
1369
 
                pce_cd_update(space->machine());
1370
 
                pce_cd.scsi_SEL = 0;
1371
 
                pce_cd.adpcm_dma_timer->adjust(attotime::never); // stop ADPCM DMA here
1372
 
                /* any write here clears CD transfer irqs */
1373
 
                pce_cd.regs[0x03] &= ~0x70;
1374
 
                cputag_set_input_line(space->machine(), "maincpu", 1, CLEAR_LINE );
1375
 
                break;
1376
 
        case 0x01:      /* CDC command / status / data */
1377
 
                break;
1378
 
        case 0x02:      /* ADPCM / CD control / IRQ enable/disable */
1379
 
                                /* bit 6 - transfer ready irq */
1380
 
                                /* bit 5 - transfer done irq */
1381
 
                                /* bit 4 - ?? irq */
1382
 
                                /* bit 3 - ?? irq */
1383
 
                                /* bit 2 - ?? irq */
1384
 
                pce_cd.scsi_ACK = data & 0x80;
1385
 
                /* Don't set or reset any irq lines, but just verify the current state */
1386
 
                pce_cd_set_irq_line( space->machine(), 0, 0 );
1387
 
                break;
1388
 
        case 0x03:      /* BRAM lock / CD status / IRQ - Read Only register */
1389
 
                break;
1390
 
        case 0x04:      /* CD reset */
1391
 
                pce_cd.scsi_RST = data & 0x02;
1392
 
                break;
1393
 
        case 0x05:      /* Convert PCM data / PCM data */
1394
 
        case 0x06:      /* PCM data */
1395
 
                break;
1396
 
        case 0x07:      /* BRAM unlock / CD status */
1397
 
                if ( data & 0x80 )
1398
 
                {
1399
 
                        pce_cd.bram_locked = 0;
1400
 
                        pce_set_cd_bram(space->machine());
1401
 
                }
1402
 
                break;
1403
 
        case 0x08:      /* ADPCM address (LSB) / CD data */
1404
 
                break;
1405
 
        case 0x09:      /* ADPCM address (MSB) */
1406
 
                break;
1407
 
        case 0x0A:      /* ADPCM RAM data port */
1408
 
                pce_cd_set_adpcm_ram_byte(space->machine(), data);
1409
 
                break;
1410
 
        case 0x0B:      /* ADPCM DMA control */
1411
 
                if ( data & 0x03 )
1412
 
                {
1413
 
                        /* Start CD to ADPCM transfer */
1414
 
                        pce_cd.adpcm_dma_timer->adjust(attotime::from_hz( PCE_CD_DATA_FRAMES_PER_SECOND * 2048 ), 0, attotime::from_hz( PCE_CD_DATA_FRAMES_PER_SECOND * 2048 ) );
1415
 
                        pce_cd.regs[0x0c] |= 4;
1416
 
                }
1417
 
                break;
1418
 
        case 0x0C:      /* ADPCM status */
1419
 
                break;
1420
 
        case 0x0D:      /* ADPCM address control */
1421
 
                if ( ( pce_cd.regs[0x0D] & 0x80 ) && ! ( data & 0x80 ) ) // ADPCM reset
1422
 
                {
1423
 
                        /* Reset ADPCM hardware */
1424
 
                        pce_cd.adpcm_read_ptr = 0;
1425
 
                        pce_cd.adpcm_write_ptr = 0;
1426
 
                        pce_cd.msm_start_addr = 0;
1427
 
                        pce_cd.msm_end_addr = 0;
1428
 
                        pce_cd.msm_half_addr = 0;
1429
 
                        pce_cd.msm_nibble = 0;
1430
 
                        adpcm_stop(space->machine());
1431
 
                        msm5205_reset_w( space->machine().device( "msm5205"), 1 );
1432
 
                }
1433
 
 
1434
 
                if(data & 0x20)
1435
 
                        pce_cd.msm_half_addr = (pce_cd.adpcm_read_ptr + (pce_cd.adpcm_length / ((data & 0x40) ? 2 : 1))) & 0xffff;
1436
 
 
1437
 
                if ( ( data & 0x40) && ((pce_cd.regs[0x0D] & 0x40) == 0) ) // ADPCM play
1438
 
                {
1439
 
                        pce_cd.msm_start_addr = (pce_cd.adpcm_read_ptr);
1440
 
                        pce_cd.msm_end_addr = (pce_cd.adpcm_read_ptr + pce_cd.adpcm_length) & 0xffff;
1441
 
                        pce_cd.msm_nibble = 0;
1442
 
                        adpcm_play(space->machine());
1443
 
                        msm5205_reset_w( space->machine().device( "msm5205"), 0 );
1444
 
 
1445
 
                        //popmessage("%08x %08x",pce_cd.adpcm_read_ptr,pce_cd.adpcm_length);
1446
 
                }
1447
 
                else if ( (data & 0x40) == 0 )
1448
 
                {
1449
 
                        /* used by Buster Bros to cancel an in-flight sample */
1450
 
                        adpcm_stop(space->machine());
1451
 
                        msm5205_reset_w( space->machine().device( "msm5205"), 1 );
1452
 
                }
1453
 
 
1454
 
                if ( data & 0x10 ) //ADPCM set length
1455
 
                {
1456
 
                        pce_cd.adpcm_length = ( pce_cd.regs[0x09] << 8 ) | pce_cd.regs[0x08];
1457
 
                }
1458
 
                if ( data & 0x08 ) //ADPCM set read address
1459
 
                {
1460
 
                        pce_cd.adpcm_read_ptr = ( pce_cd.regs[0x09] << 8 ) | pce_cd.regs[0x08];
1461
 
                        pce_cd.adpcm_read_buf = 2;
1462
 
                }
1463
 
                if ( ( data & 0x02 ) == 0x02 ) //ADPCM set write address
1464
 
                {
1465
 
                        pce_cd.adpcm_write_ptr = ( pce_cd.regs[0x09] << 8 ) | pce_cd.regs[0x08];
1466
 
                        pce_cd.adpcm_write_buf = data & 1;
1467
 
                }
1468
 
                break;
1469
 
        case 0x0E:      /* ADPCM playback rate */
1470
 
                pce_cd.adpcm_clock_divider = 0x10 - ( data & 0x0F );
1471
 
                msm5205_change_clock_w(space->machine().device("msm5205"), (PCE_CD_CLOCK / 6) / pce_cd.adpcm_clock_divider);
1472
 
                break;
1473
 
        case 0x0F:      /* ADPCM and CD audio fade timer */
1474
 
                /* TODO: timers needs HW tests */
1475
 
                if(pce_cd.regs[0xf] != data)
1476
 
                {
1477
 
                        switch(data & 0xf)
1478
 
                        {
1479
 
                                case 0x00: //CD-DA / ADPCM enable (100 msecs)
1480
 
                                        pce_cd.cdda_volume = 0.0;
1481
 
                                        pce_cd.cdda_fadein_timer->adjust(attotime::from_usec(100), 100);
1482
 
                                        pce_cd.adpcm_volume = 0.0;
1483
 
                                        pce_cd.adpcm_fadein_timer->adjust(attotime::from_usec(100), 100);
1484
 
                                        pce_cd.cdda_fadeout_timer->adjust(attotime::never);
1485
 
                                        pce_cd.adpcm_fadeout_timer->adjust(attotime::never);
1486
 
                                        break;
1487
 
                                case 0x01: //CD-DA enable (100 msecs)
1488
 
                                        pce_cd.cdda_volume = 0.0;
1489
 
                                        pce_cd.cdda_fadein_timer->adjust(attotime::from_usec(100), 100);
1490
 
                                        pce_cd.cdda_fadeout_timer->adjust(attotime::never);
1491
 
                                        break;
1492
 
                                case 0x08: //CD-DA short (1500 msecs) fade out / ADPCM enable
1493
 
                                        pce_cd.cdda_volume = 100.0;
1494
 
                                        pce_cd.cdda_fadeout_timer->adjust(attotime::from_usec(1500), 1500);
1495
 
                                        pce_cd.adpcm_volume = 0.0;
1496
 
                                        pce_cd.adpcm_fadein_timer->adjust(attotime::from_usec(100), 100);
1497
 
                                        pce_cd.cdda_fadein_timer->adjust(attotime::never);
1498
 
                                        pce_cd.adpcm_fadeout_timer->adjust(attotime::never);
1499
 
                                        break;
1500
 
                                case 0x09: //CD-DA long (5000 msecs) fade out
1501
 
                                        pce_cd.cdda_volume = 100.0;
1502
 
                                        pce_cd.cdda_fadeout_timer->adjust(attotime::from_usec(5000), 5000);
1503
 
                                        pce_cd.cdda_fadein_timer->adjust(attotime::never);
1504
 
                                        break;
1505
 
                                case 0x0a: //ADPCM long (5000 msecs) fade out
1506
 
                                        pce_cd.adpcm_volume = 100.0;
1507
 
                                        pce_cd.adpcm_fadeout_timer->adjust(attotime::from_usec(5000), 5000);
1508
 
                                        pce_cd.adpcm_fadein_timer->adjust(attotime::never);
1509
 
                                        break;
1510
 
                                case 0x0c: //CD-DA short (1500 msecs) fade out / ADPCM enable
1511
 
                                        pce_cd.cdda_volume = 100.0;
1512
 
                                        pce_cd.cdda_fadeout_timer->adjust(attotime::from_usec(1500), 1500);
1513
 
                                        pce_cd.adpcm_volume = 0.0;
1514
 
                                        pce_cd.adpcm_fadein_timer->adjust(attotime::from_usec(100), 100);
1515
 
                                        pce_cd.cdda_fadein_timer->adjust(attotime::never);
1516
 
                                        pce_cd.adpcm_fadeout_timer->adjust(attotime::never);
1517
 
                                        break;
1518
 
                                case 0x0d: //CD-DA short (1500 msecs) fade out
1519
 
                                        pce_cd.cdda_volume = 100.0;
1520
 
                                        pce_cd.cdda_fadeout_timer->adjust(attotime::from_usec(1500), 1500);
1521
 
                                        pce_cd.cdda_fadein_timer->adjust(attotime::never);
1522
 
                                        break;
1523
 
                                case 0x0e: //ADPCM short (1500 msecs) fade out
1524
 
                                        pce_cd.adpcm_volume = 100.0;
1525
 
                                        pce_cd.adpcm_fadeout_timer->adjust(attotime::from_usec(1500), 1500);
1526
 
                                        pce_cd.adpcm_fadein_timer->adjust(attotime::never);
1527
 
                                        break;
1528
 
                                default:
1529
 
                                        popmessage("CD-DA / ADPCM Fade effect mode %02x, contact MESSdev",data & 0x0f);
1530
 
                                        break;
1531
 
                        }
1532
 
                }
1533
 
                break;
1534
 
        default:
1535
 
                return;
1536
 
        }
1537
 
        pce_cd.regs[offset & 0xf] = data;
1538
 
        pce_cd_update(space->machine());
1539
 
}
1540
 
 
1541
 
static TIMER_CALLBACK( pce_cd_clear_ack )
1542
 
{
1543
 
        pce_state *state = machine.driver_data<pce_state>();
1544
 
        pce_cd_t &pce_cd = state->m_cd;
1545
 
        pce_cd_update(machine);
1546
 
        pce_cd.scsi_ACK = 0;
1547
 
        pce_cd_update(machine);
1548
 
        if ( pce_cd.scsi_CD )
1549
 
        {
1550
 
                pce_cd.regs[0x0B] &= 0xFE;
1551
 
        }
1552
 
}
1553
 
 
1554
 
static UINT8 pce_cd_get_cd_data_byte(running_machine &machine)
1555
 
{
1556
 
        pce_state *state = machine.driver_data<pce_state>();
1557
 
        pce_cd_t &pce_cd = state->m_cd;
1558
 
        UINT8 data = pce_cd.regs[0x01];
1559
 
        if ( pce_cd.scsi_REQ && ! pce_cd.scsi_ACK && ! pce_cd.scsi_CD )
1560
 
        {
1561
 
                if ( pce_cd.scsi_IO )
1562
 
                {
1563
 
                        pce_cd.scsi_ACK = 1;
1564
 
                        machine.scheduler().timer_set(machine.device<cpu_device>("maincpu")->cycles_to_attotime(15), FUNC(pce_cd_clear_ack));
1565
 
                }
1566
 
        }
1567
 
        return data;
1568
 
}
1569
 
 
1570
 
 
1571
 
static TIMER_CALLBACK( pce_cd_adpcm_dma_timer_callback )
1572
 
{
1573
 
        pce_state *state = machine.driver_data<pce_state>();
1574
 
        pce_cd_t &pce_cd = state->m_cd;
1575
 
        if ( pce_cd.scsi_REQ && ! pce_cd.scsi_ACK && ! pce_cd.scsi_CD && pce_cd.scsi_IO  )
1576
 
        {
1577
 
                pce_cd.adpcm_ram[pce_cd.adpcm_write_ptr] = pce_cd_get_cd_data_byte(machine);
1578
 
                pce_cd.adpcm_write_ptr = ( pce_cd.adpcm_write_ptr + 1 ) & 0xFFFF;
1579
 
 
1580
 
                pce_cd.regs[0x0c] &= ~4;
1581
 
        }
1582
 
}
1583
 
 
1584
 
static UINT8 pce_cd_get_adpcm_ram_byte(running_machine &machine)
1585
 
{
1586
 
        pce_state *state = machine.driver_data<pce_state>();
1587
 
        pce_cd_t &pce_cd = state->m_cd;
1588
 
        if(pce_cd.adpcm_read_buf > 0)
1589
 
        {
1590
 
                pce_cd.adpcm_read_buf--;
1591
 
                return 0;
1592
 
        }
1593
 
        else
1594
 
        {
1595
 
                UINT8 res;
1596
 
 
1597
 
                res = pce_cd.adpcm_ram[pce_cd.adpcm_read_ptr];
1598
 
                pce_cd.adpcm_read_ptr = ((pce_cd.adpcm_read_ptr + 1) & 0xffff);
1599
 
 
1600
 
                return res;
1601
 
        }
1602
 
}
1603
 
 
1604
 
READ8_HANDLER( pce_cd_intf_r )
1605
 
{
1606
 
        pce_state *state = space->machine().driver_data<pce_state>();
1607
 
        pce_cd_t &pce_cd = state->m_cd;
1608
 
        UINT8 data = pce_cd.regs[offset & 0x0F];
1609
 
 
1610
 
        pce_cd_update(space->machine());
1611
 
 
1612
 
        if(offset & 0x200 && state->m_sys3_card && state->m_acard) // route Arcade Card handling ports
1613
 
                return pce_cd_acard_r(space,offset);
1614
 
 
1615
 
        logerror("%04X: read from CD interface offset %02X\n", cpu_get_pc(&space->device()), offset );
1616
 
 
1617
 
        if((offset & 0xc0) == 0xc0 && state->m_sys3_card) //System 3 Card header handling
1618
 
        {
1619
 
                switch(offset & 0xcf)
1620
 
                {
1621
 
                        case 0xc1: return 0xaa;
1622
 
                        case 0xc2: return 0x55;
1623
 
                        case 0xc3: return 0x00;
1624
 
                        case 0xc5: return (state->m_sys3_card & 2) ? 0x55 : 0xaa;
1625
 
                        case 0xc6: return (state->m_sys3_card & 2) ? 0xaa : 0x55;
1626
 
                        case 0xc7: return 0x03;
1627
 
                }
1628
 
        }
1629
 
 
1630
 
        switch( offset & 0xf )
1631
 
        {
1632
 
        case 0x00:      /* CDC status */
1633
 
                data &= 0x07;
1634
 
                data |= pce_cd.scsi_BSY ? 0x80 : 0;
1635
 
                data |= pce_cd.scsi_REQ ? 0x40 : 0;
1636
 
                data |= pce_cd.scsi_MSG ? 0x20 : 0;
1637
 
                data |= pce_cd.scsi_CD  ? 0x10 : 0;
1638
 
                data |= pce_cd.scsi_IO  ? 0x08 : 0;
1639
 
                break;
1640
 
        case 0x01:      /* CDC command / status / data */
1641
 
                break;
1642
 
        case 0x02:      /* ADPCM / CD control */
1643
 
                break;
1644
 
        case 0x03:      /* BRAM lock / CD status */
1645
 
                /* bit 4 set when CD motor is on */
1646
 
                /* bit 2 set when less than half of the ADPCM data is remaining ?? */
1647
 
                pce_cd.bram_locked = 1;
1648
 
                pce_set_cd_bram(space->machine());
1649
 
                data = data & 0x6E;
1650
 
                data |= ( pce_cd.cd_motor_on ? 0x10 : 0 );
1651
 
                pce_cd.regs[0x03] ^= 0x02;                      /* TODO: get rid of this hack */
1652
 
                break;
1653
 
        case 0x04:      /* CD reset */
1654
 
                break;
1655
 
        case 0x05:      /* Convert PCM data / PCM data */
1656
 
        case 0x06:      /* PCM data */
1657
 
                break;
1658
 
        case 0x07:      /* BRAM unlock / CD status */
1659
 
                data = ( pce_cd.bram_locked ? ( data & 0x7F ) : ( data | 0x80 ) );
1660
 
                break;
1661
 
        case 0x08:      /* ADPCM address (LSB) / CD data */
1662
 
                data = pce_cd_get_cd_data_byte(space->machine());
1663
 
                break;
1664
 
        case 0x0A:      /* ADPCM RAM data port */
1665
 
                data = pce_cd_get_adpcm_ram_byte(space->machine());
1666
 
                break;
1667
 
        case 0x0B:      /* ADPCM DMA control */
1668
 
                break;
1669
 
        case 0x0C:      /* ADPCM status */
1670
 
                break;
1671
 
        case 0x0D:      /* ADPCM address control */
1672
 
                break;
1673
 
        /* These are read-only registers */
1674
 
        case 0x09:      /* ADPCM address (MSB) */
1675
 
        case 0x0E:      /* ADPCM playback rate */
1676
 
        case 0x0F:      /* ADPCM and CD audio fade timer */
1677
 
                return 0;
1678
 
        default:
1679
 
                data = 0xFF;
1680
 
                break;
1681
 
        }
1682
 
 
1683
 
        return data;
1684
 
}
1685
 
 
1686
 
 
1687
 
/*
1688
 
 
1689
 
PC Engine Arcade Card emulation
1690
 
 
1691
 
*/
1692
 
 
1693
 
READ8_HANDLER( pce_cd_acard_r )
1694
 
{
1695
 
        pce_state *state = space->machine().driver_data<pce_state>();
1696
 
        pce_cd_t &pce_cd = state->m_cd;
1697
 
        UINT8 r_num;
1698
 
 
1699
 
        if((offset & 0x2e0) == 0x2e0)
1700
 
        {
1701
 
                switch(offset & 0x2ef)
1702
 
                {
1703
 
                        case 0x2e0: return (pce_cd.acard_shift >> 0)  & 0xff;
1704
 
                        case 0x2e1: return (pce_cd.acard_shift >> 8)  & 0xff;
1705
 
                        case 0x2e2: return (pce_cd.acard_shift >> 16) & 0xff;
1706
 
                        case 0x2e3: return (pce_cd.acard_shift >> 24) & 0xff;
1707
 
                        case 0x2e4: return (pce_cd.acard_shift_reg);
1708
 
                        case 0x2e5: return pce_cd.acard_latch;
1709
 
                        case 0x2ee: return 0x10;
1710
 
                        case 0x2ef: return 0x51;
1711
 
                }
1712
 
 
1713
 
                return 0;
1714
 
        }
1715
 
 
1716
 
        r_num = (offset & 0x30) >> 4;
1717
 
 
1718
 
        switch(offset & 0x0f)
1719
 
        {
1720
 
                case 0x00:
1721
 
                case 0x01:
1722
 
                {
1723
 
                        UINT8 res;
1724
 
                        if(pce_cd.acard_ctrl[r_num] & 2)
1725
 
                                res = pce_cd.acard_ram[(pce_cd.acard_base_addr[r_num] + pce_cd.acard_addr_offset[r_num]) & 0x1fffff];
1726
 
                        else
1727
 
                                res = pce_cd.acard_ram[pce_cd.acard_base_addr[r_num] & 0x1fffff];
1728
 
 
1729
 
                        if(pce_cd.acard_ctrl[r_num] & 0x1)
1730
 
                        {
1731
 
                                if(pce_cd.acard_ctrl[r_num] & 0x10)
1732
 
                                {
1733
 
                                        pce_cd.acard_base_addr[r_num] += pce_cd.acard_addr_inc[r_num];
1734
 
                                        pce_cd.acard_base_addr[r_num] &= 0xffffff;
1735
 
                                }
1736
 
                                else
1737
 
                                {
1738
 
                                        pce_cd.acard_addr_offset[r_num] += pce_cd.acard_addr_inc[r_num];
1739
 
                                }
1740
 
                        }
1741
 
 
1742
 
                        return res;
1743
 
                }
1744
 
                case 0x02: return (pce_cd.acard_base_addr[r_num] >> 0) & 0xff;
1745
 
                case 0x03: return (pce_cd.acard_base_addr[r_num] >> 8) & 0xff;
1746
 
                case 0x04: return (pce_cd.acard_base_addr[r_num] >> 16) & 0xff;
1747
 
                case 0x05: return (pce_cd.acard_addr_offset[r_num] >> 0) & 0xff;
1748
 
                case 0x06: return (pce_cd.acard_addr_offset[r_num] >> 8) & 0xff;
1749
 
                case 0x07: return (pce_cd.acard_addr_inc[r_num] >> 0) & 0xff;
1750
 
                case 0x08: return (pce_cd.acard_addr_inc[r_num] >> 8) & 0xff;
1751
 
                case 0x09: return pce_cd.acard_ctrl[r_num];
1752
 
                default:   return 0;
1753
 
        }
1754
 
 
1755
 
        return 0;
1756
 
}
1757
 
 
1758
 
WRITE8_HANDLER( pce_cd_acard_w )
1759
 
{
1760
 
        pce_state *state = space->machine().driver_data<pce_state>();
1761
 
        pce_cd_t &pce_cd = state->m_cd;
1762
 
        UINT8 w_num;
1763
 
 
1764
 
        if((offset & 0x2e0) == 0x2e0)
1765
 
        {
1766
 
                switch(offset & 0x0f)
1767
 
                {
1768
 
                        case 0: pce_cd.acard_shift = (data & 0xff) | (pce_cd.acard_shift & 0xffffff00); break;
1769
 
                        case 1: pce_cd.acard_shift = (data << 8)   | (pce_cd.acard_shift & 0xffff00ff); break;
1770
 
                        case 2: pce_cd.acard_shift = (data << 16)  | (pce_cd.acard_shift & 0xff00ffff); break;
1771
 
                        case 3: pce_cd.acard_shift = (data << 24)  | (pce_cd.acard_shift & 0x00ffffff); break;
1772
 
                        case 4:
1773
 
                                {
1774
 
                                        pce_cd.acard_shift_reg = data & 0x0f;
1775
 
 
1776
 
                                        if(pce_cd.acard_shift_reg != 0)
1777
 
                                        {
1778
 
                                                 pce_cd.acard_shift = (pce_cd.acard_shift_reg < 8) ?
1779
 
                                                                                        (pce_cd.acard_shift << pce_cd.acard_shift_reg)
1780
 
                                                                                        : (pce_cd.acard_shift >> (16 - pce_cd.acard_shift_reg));
1781
 
                                        }
1782
 
                                }
1783
 
                                break;
1784
 
                        case 5: pce_cd.acard_latch = data; break;
1785
 
                }
1786
 
        }
1787
 
        else
1788
 
        {
1789
 
                w_num = (offset & 0x30) >> 4;
1790
 
 
1791
 
                switch(offset & 0x0f)
1792
 
                {
1793
 
                        case 0x00:
1794
 
                        case 0x01:
1795
 
                                if(pce_cd.acard_ctrl[w_num] & 2)
1796
 
                                        pce_cd.acard_ram[(pce_cd.acard_base_addr[w_num] + pce_cd.acard_addr_offset[w_num]) & 0x1fffff] = data;
1797
 
                                else
1798
 
                                        pce_cd.acard_ram[pce_cd.acard_base_addr[w_num] & 0x1FFFFF] = data;
1799
 
 
1800
 
                                if(pce_cd.acard_ctrl[w_num] & 0x1)
1801
 
                                {
1802
 
                                        if(pce_cd.acard_ctrl[w_num] & 0x10)
1803
 
                                        {
1804
 
                                                pce_cd.acard_base_addr[w_num] += pce_cd.acard_addr_inc[w_num];
1805
 
                                                pce_cd.acard_base_addr[w_num] &= 0xffffff;
1806
 
                                        }
1807
 
                                        else
1808
 
                                        {
1809
 
                                                pce_cd.acard_addr_offset[w_num] += pce_cd.acard_addr_inc[w_num];
1810
 
                                        }
1811
 
                                }
1812
 
 
1813
 
                                break;
1814
 
 
1815
 
                        case 0x02: pce_cd.acard_base_addr[w_num] = (data & 0xff) | (pce_cd.acard_base_addr[w_num] & 0xffff00);  break;
1816
 
                        case 0x03: pce_cd.acard_base_addr[w_num] = (data << 8) | (pce_cd.acard_base_addr[w_num] & 0xff00ff);            break;
1817
 
                        case 0x04: pce_cd.acard_base_addr[w_num] = (data << 16) | (pce_cd.acard_base_addr[w_num] & 0x00ffff);   break;
1818
 
                        case 0x05: pce_cd.acard_addr_offset[w_num] = (data & 0xff) | (pce_cd.acard_addr_offset[w_num] & 0xff00);        break;
1819
 
                        case 0x06:
1820
 
                                pce_cd.acard_addr_offset[w_num] = (data << 8) | (pce_cd.acard_addr_offset[w_num] & 0x00ff);
1821
 
 
1822
 
                                if((pce_cd.acard_ctrl[w_num] & 0x60) == 0x40)
1823
 
                                {
1824
 
                                        pce_cd.acard_base_addr[w_num] += pce_cd.acard_addr_offset[w_num] + ((pce_cd.acard_ctrl[w_num] & 0x08) ? 0xff0000 : 0);
1825
 
                                        pce_cd.acard_base_addr[w_num] &= 0xffffff;
1826
 
                                }
1827
 
                                break;
1828
 
                        case 0x07: pce_cd.acard_addr_inc[w_num] = (data & 0xff) | (pce_cd.acard_addr_inc[w_num] & 0xff00);              break;
1829
 
                        case 0x08: pce_cd.acard_addr_inc[w_num] = (data << 8) | (pce_cd.acard_addr_inc[w_num] & 0x00ff);                        break;
1830
 
                        case 0x09: pce_cd.acard_ctrl[w_num] = data & 0x7f;                                                                                              break;
1831
 
                        case 0x0a:
1832
 
                                if((pce_cd.acard_ctrl[w_num] & 0x60) == 0x60)
1833
 
                                {
1834
 
                                        pce_cd.acard_base_addr[w_num] += pce_cd.acard_addr_offset[w_num];
1835
 
                                        pce_cd.acard_base_addr[w_num] &= 0xffffff;
1836
 
                                }
1837
 
                                break;
1838
 
                }
1839
 
        }
1840
 
}
1841
 
 
1842
 
READ8_HANDLER( pce_cd_acard_wram_r )
1843
 
{
1844
 
        return pce_cd_intf_r(space,0x200 | (offset & 0x6000) >> 9);
1845
 
}
1846
 
 
1847
 
WRITE8_HANDLER( pce_cd_acard_wram_w )
1848
 
{
1849
 
        pce_cd_intf_w(space,0x200 | (offset & 0x6000) >> 9,data);
1850
 
}
1851