src/mess/video/hd66421.c
| r882 | r883 | |
| 1 | | /*
|
| 2 | | |
| 3 | | Hitachi HD66421 LCD Controller/Driver
|
| 4 | | |
| 5 | | (c) 2001-2007 Tim Schuerewegen
|
| 6 | | |
| 7 | | */
|
| 8 | | |
| 9 | | #include "hd66421.h"
|
| 10 | | |
| 11 | | #define LOG_LEVEL 1
|
| 12 | | #define _logerror(level,...) if (LOG_LEVEL > level) logerror(__VA_ARGS__)
|
| 13 | | |
| 14 | | //#define BRIGHTNESS_DOES_NOT_WORK
|
| 15 | | |
| 16 | | #define HD66421_RAM_SIZE (HD66421_WIDTH * HD66421_HEIGHT / 4) // 2-bits per pixel
|
| 17 | | |
| 18 | | // R0 - control register 1
|
| 19 | | #define LCD_R0_RMW 0x80 // read-modify-write mode
|
| 20 | | #define LCD_R0_DISP 0x40 // display on/off
|
| 21 | | #define LCD_R0_STBY 0x20 // standby (internal operation and power circuit halt)
|
| 22 | | #define LCD_R0_PWR 0x10
|
| 23 | | #define LCD_R0_AMP 0x08
|
| 24 | | #define LCD_R0_REV 0x04 // reverse
|
| 25 | | #define LCD_R0_HOLT 0x02
|
| 26 | | #define LCD_R0_ADC 0x01
|
| 27 | | |
| 28 | | // R1 - control register 2
|
| 29 | | #define LCD_R1_BIS1 0x80 // bias ratio (bit 1)
|
| 30 | | #define LCD_R1_BIS0 0x40 // bias ratio (bit 0)
|
| 31 | | #define LCD_R1_WLS 0x20
|
| 32 | | #define LCD_R1_GRAY 0x10 // grayscale palette 4/32
|
| 33 | | #define LCD_R1_DTY1 0x08 // display duty cycle (bit 1)
|
| 34 | | #define LCD_R1_DTY0 0x04 // display duty cycle (bit 0)
|
| 35 | | #define LCD_R1_INC 0x02
|
| 36 | | #define LCD_R1_BLK 0x01 // blink function
|
| 37 | | |
| 38 | | // register 0 to 16
|
| 39 | | #define LCD_REG_CONTROL_1 0x00 // control register 1
|
| 40 | | #define LCD_REG_CONTROL_2 0x01 // control register 2
|
| 41 | | #define LCD_REG_ADDR_X 0x02 // x address register
|
| 42 | | #define LCD_REG_ADDR_Y 0x03 // y address register
|
| 43 | | #define LCD_REG_RAM 0x04 // display ram access register
|
| 44 | | #define LCD_REG_START_Y 0x05 // display start line register
|
| 45 | | #define LCD_REG_BLINK_START 0x06 // blink start line register
|
| 46 | | #define LCD_REG_BLINK_END 0x07 // blink end line register
|
| 47 | | #define LCD_REG_BLINK_1 0x08 // blink register 1
|
| 48 | | #define LCD_REG_BLINK_2 0x09 // blink register 2
|
| 49 | | #define LCD_REG_BLINK_3 0x0A // blink register 3
|
| 50 | | #define LCD_REG_PARTIAL 0x0B // partial display block register
|
| 51 | | #define LCD_REG_COLOR_1 0x0C // gray scale palette 1 (0,0)
|
| 52 | | #define LCD_REG_COLOR_2 0x0D // gray scale palette 2 (0,1)
|
| 53 | | #define LCD_REG_COLOR_3 0x0E // gray scale palette 3 (1,0)
|
| 54 | | #define LCD_REG_COLOR_4 0x0F // gray scale palette 4 (1,1)
|
| 55 | | #define LCD_REG_CONTRAST 0x10 // contrast control register
|
| 56 | | #define LCD_REG_PLANE 0x11 // plane selection register
|
| 57 | | |
| 58 | | typedef struct
|
| 59 | | {
|
| 60 | | UINT8 idx, dat[32]; // index and data registers
|
| 61 | | UINT8 *ram; // display ram
|
| 62 | | UINT32 pos; // current position in ram
|
| 63 | | } HD66421;
|
| 64 | | |
| 65 | | static HD66421 lcd;
|
| 66 | | |
| 67 | | UINT8 hd66421_reg_idx_r( void)
|
| 68 | | {
|
| 69 | | _logerror( 2, "hd66421_reg_idx_r\n");
|
| 70 | | return lcd.idx;
|
| 71 | | }
|
| 72 | | |
| 73 | | void hd66421_reg_idx_w( UINT8 data)
|
| 74 | | {
|
| 75 | | _logerror( 2, "hd66421_reg_idx_w (%02X)\n", data);
|
| 76 | | lcd.idx = data;
|
| 77 | | }
|
| 78 | | |
| 79 | | UINT8 hd66421_reg_dat_r( void)
|
| 80 | | {
|
| 81 | | _logerror( 2, "hd66421_reg_dat_r\n");
|
| 82 | | return lcd.dat[lcd.idx];
|
| 83 | | }
|
| 84 | | |
| 85 | | void hd66421_reg_dat_w( UINT8 data)
|
| 86 | | {
|
| 87 | | _logerror( 2, "hd66421_reg_dat_w (%02X)\n", data);
|
| 88 | | lcd.dat[lcd.idx] = data;
|
| 89 | | switch (lcd.idx)
|
| 90 | | {
|
| 91 | | case LCD_REG_ADDR_Y : lcd.pos = data * HD66421_WIDTH / 4; break;
|
| 92 | | case LCD_REG_RAM : lcd.ram[lcd.pos++] = data; break;
|
| 93 | | }
|
| 94 | | }
|
| 95 | | |
| 96 | | INLINE void hd66421_plot_pixel( bitmap_t *bitmap, int x, int y, UINT32 color)
|
| 97 | | {
|
| 98 | | *BITMAP_ADDR16( bitmap, y, x) = (UINT16)color;
|
| 99 | | }
|
| 100 | | |
| 101 | | PALETTE_INIT( hd66421 )
|
| 102 | | {
|
| 103 | | int i;
|
| 104 | | _logerror( 0, "palette_init_hd66421\n");
|
| 105 | | // init palette
|
| 106 | | for (i=0;i<4;i++)
|
| 107 | | {
|
| 108 | | palette_set_color( machine, i, RGB_WHITE);
|
| 109 | | #ifndef BRIGHTNESS_DOES_NOT_WORK
|
| 110 | | palette_set_brightness( machine, i, 1.0 * i / (4 - 1));
|
| 111 | | #endif
|
| 112 | | colortable[i] = i;
|
| 113 | | }
|
| 114 | | }
|
| 115 | | |
| 116 | | void hd66421_state_save( void)
|
| 117 | | {
|
| 118 | | const char *name = "hd66421";
|
| 119 | | state_save_register_item( name, 0, lcd.idx);
|
| 120 | | state_save_register_item_array( name, 0, lcd.dat);
|
| 121 | | state_save_register_item( name, 0, lcd.pos);
|
| 122 | | state_save_register_item_pointer( name, 0, lcd.ram, HD66421_RAM_SIZE);
|
| 123 | | }
|
| 124 | | |
| 125 | | VIDEO_START( hd66421 )
|
| 126 | | {
|
| 127 | | _logerror( 0, "video_start_hd66421\n");
|
| 128 | | memset( &lcd, 0, sizeof( lcd));
|
| 129 | | lcd.ram = auto_malloc( HD66421_RAM_SIZE);
|
| 130 | | hd66421_state_save();
|
| 131 | | }
|
| 132 | | |
| 133 | | VIDEO_UPDATE( hd66421 )
|
| 134 | | {
|
| 135 | | pen_t pen[4];
|
| 136 | | int i;
|
| 137 | | _logerror( 1, "video_update_hd66421\n");
|
| 138 | | // update palette
|
| 139 | | for (i=0;i<4;i++)
|
| 140 | | {
|
| 141 | | double bright;
|
| 142 | | int temp;
|
| 143 | | temp = 31 - (lcd.dat[LCD_REG_COLOR_1+i] - lcd.dat[LCD_REG_CONTRAST] + 0x03);
|
| 144 | | if (temp < 0) temp = 0;
|
| 145 | | if (temp > 31) temp = 31;
|
| 146 | | bright = 1.0 * temp / 31;
|
| 147 | | pen[i] = Machine->pens[i];
|
| 148 | | #ifdef BRIGHTNESS_DOES_NOT_WORK
|
| 149 | | palette_set_color( machine, pen[i], 255 * bright, 255 * bright, 255 * bright);
|
| 150 | | #else
|
| 151 | | palette_set_brightness( machine, pen[i], bright);
|
| 152 | | #endif
|
| 153 | | }
|
| 154 | | // draw bitmap (bottom to top)
|
| 155 | | if (lcd.dat[0] & LCD_R0_DISP)
|
| 156 | | {
|
| 157 | | int x, y;
|
| 158 | | x = 0;
|
| 159 | | y = HD66421_HEIGHT - 1;
|
| 160 | | for (i=0;i<HD66421_RAM_SIZE;i++)
|
| 161 | | {
|
| 162 | | hd66421_plot_pixel( bitmap, x++, y, pen[(lcd.ram[i] >> 6) & 3]);
|
| 163 | | hd66421_plot_pixel( bitmap, x++, y, pen[(lcd.ram[i] >> 4) & 3]);
|
| 164 | | hd66421_plot_pixel( bitmap, x++, y, pen[(lcd.ram[i] >> 2) & 3]);
|
| 165 | | hd66421_plot_pixel( bitmap, x++, y, pen[(lcd.ram[i] >> 0) & 3]);
|
| 166 | | if (x >= HD66421_WIDTH)
|
| 167 | | {
|
| 168 | | x = 0;
|
| 169 | | y = y - 1;
|
| 170 | | }
|
| 171 | | }
|
| 172 | | }
|
| 173 | | else
|
| 174 | | {
|
| 175 | | rectangle rect;
|
| 176 | | rect.min_x = 0;
|
| 177 | | rect.max_x = HD66421_WIDTH - 1;
|
| 178 | | rect.min_y = 0;
|
| 179 | | rect.max_y = HD66421_HEIGHT - 1;
|
| 180 | | fillbitmap( bitmap, get_white_pen( machine), &rect);
|
| 181 | | }
|
| 182 | | // flags
|
| 183 | | return 0;
|
| 184 | | }
|
| 1 | /* |
| 2 | |
| 3 | Hitachi HD66421 LCD Controller/Driver |
| 4 | |
| 5 | (c) 2001-2007 Tim Schuerewegen |
| 6 | |
| 7 | */ |
| 8 | |
| 9 | #include "hd66421.h" |
| 10 | |
| 11 | #define LOG_LEVEL 1 |
| 12 | #define _logerror(level,...) if (LOG_LEVEL > level) logerror(__VA_ARGS__) |
| 13 | |
| 14 | //#define BRIGHTNESS_DOES_NOT_WORK |
| 15 | |
| 16 | #define HD66421_RAM_SIZE (HD66421_WIDTH * HD66421_HEIGHT / 4) // 2-bits per pixel |
| 17 | |
| 18 | // R0 - control register 1 |
| 19 | #define LCD_R0_RMW 0x80 // read-modify-write mode |
| 20 | #define LCD_R0_DISP 0x40 // display on/off |
| 21 | #define LCD_R0_STBY 0x20 // standby (internal operation and power circuit halt) |
| 22 | #define LCD_R0_PWR 0x10 |
| 23 | #define LCD_R0_AMP 0x08 |
| 24 | #define LCD_R0_REV 0x04 // reverse |
| 25 | #define LCD_R0_HOLT 0x02 |
| 26 | #define LCD_R0_ADC 0x01 |
| 27 | |
| 28 | // R1 - control register 2 |
| 29 | #define LCD_R1_BIS1 0x80 // bias ratio (bit 1) |
| 30 | #define LCD_R1_BIS0 0x40 // bias ratio (bit 0) |
| 31 | #define LCD_R1_WLS 0x20 |
| 32 | #define LCD_R1_GRAY 0x10 // grayscale palette 4/32 |
| 33 | #define LCD_R1_DTY1 0x08 // display duty cycle (bit 1) |
| 34 | #define LCD_R1_DTY0 0x04 // display duty cycle (bit 0) |
| 35 | #define LCD_R1_INC 0x02 |
| 36 | #define LCD_R1_BLK 0x01 // blink function |
| 37 | |
| 38 | // register 0 to 16 |
| 39 | #define LCD_REG_CONTROL_1 0x00 // control register 1 |
| 40 | #define LCD_REG_CONTROL_2 0x01 // control register 2 |
| 41 | #define LCD_REG_ADDR_X 0x02 // x address register |
| 42 | #define LCD_REG_ADDR_Y 0x03 // y address register |
| 43 | #define LCD_REG_RAM 0x04 // display ram access register |
| 44 | #define LCD_REG_START_Y 0x05 // display start line register |
| 45 | #define LCD_REG_BLINK_START 0x06 // blink start line register |
| 46 | #define LCD_REG_BLINK_END 0x07 // blink end line register |
| 47 | #define LCD_REG_BLINK_1 0x08 // blink register 1 |
| 48 | #define LCD_REG_BLINK_2 0x09 // blink register 2 |
| 49 | #define LCD_REG_BLINK_3 0x0A // blink register 3 |
| 50 | #define LCD_REG_PARTIAL 0x0B // partial display block register |
| 51 | #define LCD_REG_COLOR_1 0x0C // gray scale palette 1 (0,0) |
| 52 | #define LCD_REG_COLOR_2 0x0D // gray scale palette 2 (0,1) |
| 53 | #define LCD_REG_COLOR_3 0x0E // gray scale palette 3 (1,0) |
| 54 | #define LCD_REG_COLOR_4 0x0F // gray scale palette 4 (1,1) |
| 55 | #define LCD_REG_CONTRAST 0x10 // contrast control register |
| 56 | #define LCD_REG_PLANE 0x11 // plane selection register |
| 57 | |
| 58 | typedef struct |
| 59 | { |
| 60 | UINT8 idx, dat[32]; // index and data registers |
| 61 | UINT8 *ram; // display ram |
| 62 | UINT32 pos; // current position in ram |
| 63 | } HD66421; |
| 64 | |
| 65 | static HD66421 lcd; |
| 66 | |
| 67 | UINT8 hd66421_reg_idx_r( void) |
| 68 | { |
| 69 | _logerror( 2, "hd66421_reg_idx_r\n"); |
| 70 | return lcd.idx; |
| 71 | } |
| 72 | |
| 73 | void hd66421_reg_idx_w( UINT8 data) |
| 74 | { |
| 75 | _logerror( 2, "hd66421_reg_idx_w (%02X)\n", data); |
| 76 | lcd.idx = data; |
| 77 | } |
| 78 | |
| 79 | UINT8 hd66421_reg_dat_r( void) |
| 80 | { |
| 81 | _logerror( 2, "hd66421_reg_dat_r\n"); |
| 82 | return lcd.dat[lcd.idx]; |
| 83 | } |
| 84 | |
| 85 | void hd66421_reg_dat_w( UINT8 data) |
| 86 | { |
| 87 | _logerror( 2, "hd66421_reg_dat_w (%02X)\n", data); |
| 88 | lcd.dat[lcd.idx] = data; |
| 89 | switch (lcd.idx) |
| 90 | { |
| 91 | case LCD_REG_ADDR_Y : lcd.pos = data * HD66421_WIDTH / 4; break; |
| 92 | case LCD_REG_RAM : lcd.ram[lcd.pos++] = data; break; |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | INLINE void hd66421_plot_pixel( bitmap_t *bitmap, int x, int y, UINT32 color) |
| 97 | { |
| 98 | *BITMAP_ADDR16( bitmap, y, x) = (UINT16)color; |
| 99 | } |
| 100 | |
| 101 | PALETTE_INIT( hd66421 ) |
| 102 | { |
| 103 | int i; |
| 104 | _logerror( 0, "palette_init_hd66421\n"); |
| 105 | // init palette |
| 106 | for (i=0;i<4;i++) |
| 107 | { |
| 108 | palette_set_color( machine, i, RGB_WHITE); |
| 109 | #ifndef BRIGHTNESS_DOES_NOT_WORK |
| 110 | palette_set_brightness( machine, i, 1.0 * i / (4 - 1)); |
| 111 | #endif |
| 112 | colortable[i] = i; |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | void hd66421_state_save( void) |
| 117 | { |
| 118 | const char *name = "hd66421"; |
| 119 | state_save_register_item( name, 0, lcd.idx); |
| 120 | state_save_register_item_array( name, 0, lcd.dat); |
| 121 | state_save_register_item( name, 0, lcd.pos); |
| 122 | state_save_register_item_pointer( name, 0, lcd.ram, HD66421_RAM_SIZE); |
| 123 | } |
| 124 | |
| 125 | VIDEO_START( hd66421 ) |
| 126 | { |
| 127 | _logerror( 0, "video_start_hd66421\n"); |
| 128 | memset( &lcd, 0, sizeof( lcd)); |
| 129 | lcd.ram = auto_malloc( HD66421_RAM_SIZE); |
| 130 | hd66421_state_save(); |
| 131 | } |
| 132 | |
| 133 | VIDEO_UPDATE( hd66421 ) |
| 134 | { |
| 135 | pen_t pen[4]; |
| 136 | int i; |
| 137 | _logerror( 1, "video_update_hd66421\n"); |
| 138 | // update palette |
| 139 | for (i=0;i<4;i++) |
| 140 | { |
| 141 | double bright; |
| 142 | int temp; |
| 143 | temp = 31 - (lcd.dat[LCD_REG_COLOR_1+i] - lcd.dat[LCD_REG_CONTRAST] + 0x03); |
| 144 | if (temp < 0) temp = 0; |
| 145 | if (temp > 31) temp = 31; |
| 146 | bright = 1.0 * temp / 31; |
| 147 | pen[i] = Machine->pens[i]; |
| 148 | #ifdef BRIGHTNESS_DOES_NOT_WORK |
| 149 | palette_set_color( machine, pen[i], 255 * bright, 255 * bright, 255 * bright); |
| 150 | #else |
| 151 | palette_set_brightness( machine, pen[i], bright); |
| 152 | #endif |
| 153 | } |
| 154 | // draw bitmap (bottom to top) |
| 155 | if (lcd.dat[0] & LCD_R0_DISP) |
| 156 | { |
| 157 | int x, y; |
| 158 | x = 0; |
| 159 | y = HD66421_HEIGHT - 1; |
| 160 | for (i=0;i<HD66421_RAM_SIZE;i++) |
| 161 | { |
| 162 | hd66421_plot_pixel( bitmap, x++, y, pen[(lcd.ram[i] >> 6) & 3]); |
| 163 | hd66421_plot_pixel( bitmap, x++, y, pen[(lcd.ram[i] >> 4) & 3]); |
| 164 | hd66421_plot_pixel( bitmap, x++, y, pen[(lcd.ram[i] >> 2) & 3]); |
| 165 | hd66421_plot_pixel( bitmap, x++, y, pen[(lcd.ram[i] >> 0) & 3]); |
| 166 | if (x >= HD66421_WIDTH) |
| 167 | { |
| 168 | x = 0; |
| 169 | y = y - 1; |
| 170 | } |
| 171 | } |
| 172 | } |
| 173 | else |
| 174 | { |
| 175 | rectangle rect; |
| 176 | rect.min_x = 0; |
| 177 | rect.max_x = HD66421_WIDTH - 1; |
| 178 | rect.min_y = 0; |
| 179 | rect.max_y = HD66421_HEIGHT - 1; |
| 180 | fillbitmap( bitmap, get_white_pen( machine), &rect); |
| 181 | } |
| 182 | // flags |
| 183 | return 0; |
| 184 | } |
src/mess/machine/pcf8593.c
| r882 | r883 | |
| 1 | | /*
|
| 2 | | |
| 3 | | Philips PCF8593 CMOS clock/calendar circuit
|
| 4 | | |
| 5 | | (c) 2001-2007 Tim Schuerewegen
|
| 6 | | |
| 7 | | */
|
| 8 | | |
| 9 | | #include "pcf8593.h"
|
| 10 | | |
| 11 | | #include <time.h>
|
| 12 | | |
| 13 | | #define LOG_LEVEL 1
|
| 14 | | #define _logerror(level,...) if (LOG_LEVEL > level) logerror(__VA_ARGS__)
|
| 15 | | |
| 16 | | #define RTC_MODE_NONE 0
|
| 17 | | #define RTC_MODE_SEND 1
|
| 18 | | #define RTC_MODE_RECV 2
|
| 19 | | |
| 20 | | // get/set date
|
| 21 | | #define RTC_GET_DATE_YEAR ((rtc.data[5] >> 6) & 3)
|
| 22 | | #define RTC_SET_DATE_YEAR(x) rtc.data[5] = (rtc.data[5] & 0x3F) | (((x) % 4) << 6)
|
| 23 | | #define RTC_GET_DATE_MONTH bcd_to_dec( rtc.data[6])
|
| 24 | | #define RTC_SET_DATE_MONTH(x) rtc.data[6] = dec_to_bcd( x)
|
| 25 | | #define RTC_GET_DATE_DAY (bcd_to_dec( rtc.data[5] & 0x3F))
|
| 26 | | #define RTC_SET_DATE_DAY(x) rtc.data[5] = (rtc.data[5] & 0xC0) | dec_to_bcd( x)
|
| 27 | | |
| 28 | | // get/set time
|
| 29 | | #define RTC_GET_TIME_HOUR bcd_to_dec( rtc.data[4])
|
| 30 | | #define RTC_SET_TIME_HOUR(x) rtc.data[4] = dec_to_bcd( x)
|
| 31 | | #define RTC_GET_TIME_MINUTE bcd_to_dec( rtc.data[3])
|
| 32 | | #define RTC_SET_TIME_MINUTE(x) rtc.data[3] = dec_to_bcd( x)
|
| 33 | | #define RTC_GET_TIME_SECOND bcd_to_dec( rtc.data[2])
|
| 34 | | #define RTC_SET_TIME_SECOND(x) rtc.data[2] = dec_to_bcd( x)
|
| 35 | | |
| 36 | | static void pcf8593_clear_buffer_rx( void);
|
| 37 | | static TIMER_CALLBACK( pcf8593_timer_callback );
|
| 38 | | |
| 39 | | typedef struct
|
| 40 | | {
|
| 41 | | UINT8 *data;
|
| 42 | | UINT32 size;
|
| 43 | | int pin_scl, pin_sda, inp;
|
| 44 | | bool active;
|
| 45 | | int bits;
|
| 46 | | UINT8 data_recv_index, data_recv[50];
|
| 47 | | UINT8 mode, pos;
|
| 48 | | mame_timer *timer;
|
| 49 | | } PCF8593;
|
| 50 | | |
| 51 | | static PCF8593 rtc;
|
| 52 | | |
| 53 | | void pcf8593_init( void)
|
| 54 | | {
|
| 55 | | _logerror( 0, "pcf8593_init\n");
|
| 56 | | memset( &rtc, 0, sizeof( rtc));
|
| 57 | | rtc.size = 16;
|
| 58 | | rtc.data = malloc( rtc.size);
|
| 59 | | rtc.timer = mame_timer_alloc( pcf8593_timer_callback );
|
| 60 | | mame_timer_adjust( rtc.timer, MAME_TIME_IN_SEC(1), 0, MAME_TIME_IN_SEC(1));
|
| 61 | | pcf8593_reset();
|
| 62 | | }
|
| 63 | | |
| 64 | | void pcf8593_exit( void)
|
| 65 | | {
|
| 66 | | _logerror( 0, "pcf8593_exit\n");
|
| 67 | | free( rtc.data);
|
| 68 | | }
|
| 69 | | |
| 70 | | void pcf8593_reset( void)
|
| 71 | | {
|
| 72 | | _logerror( 0, "pcf8593_reset\n");
|
| 73 | | rtc.pin_scl = 1;
|
| 74 | | rtc.pin_sda = 1;
|
| 75 | | rtc.active = FALSE;
|
| 76 | | rtc.inp = 0;
|
| 77 | | rtc.mode = RTC_MODE_RECV;
|
| 78 | | rtc.bits = 0;
|
| 79 | | pcf8593_clear_buffer_rx();
|
| 80 | | rtc.pos = 0;
|
| 81 | | }
|
| 82 | | |
| 83 | | void pcf8593_pin_scl( int data)
|
| 84 | | {
|
| 85 | | // send bit
|
| 86 | | if ((rtc.active) && (!rtc.pin_scl) && (data))
|
| 87 | | {
|
| 88 | | switch (rtc.mode)
|
| 89 | | {
|
| 90 | | // HOST -> RTC
|
| 91 | | case RTC_MODE_RECV :
|
| 92 | | {
|
| 93 | | // get bit
|
| 94 | | if (rtc.pin_sda) rtc.data_recv[rtc.data_recv_index] = rtc.data_recv[rtc.data_recv_index] | (0x80 >> rtc.bits);
|
| 95 | | rtc.bits++;
|
| 96 | | // bit 9 = end
|
| 97 | | if (rtc.bits > 8)
|
| 98 | | {
|
| 99 | | _logerror( 2, "pcf8593_write_byte(%02X)\n", rtc.data_recv[rtc.data_recv_index]);
|
| 100 | | // enter receive mode when 1st byte = 0xA3
|
| 101 | | if ((rtc.data_recv[0] == 0xA3) && (rtc.data_recv_index == 0))
|
| 102 | | {
|
| 103 | | rtc.mode = RTC_MODE_SEND;
|
| 104 | | }
|
| 105 | | // A2 + xx = "read from pos xx" command
|
| 106 | | if ((rtc.data_recv[0] == 0xA2) && (rtc.data_recv_index == 1))
|
| 107 | | {
|
| 108 | | rtc.pos = rtc.data_recv[1];
|
| 109 | | }
|
| 110 | | // A2 + xx + .. = write byte
|
| 111 | | if ((rtc.data_recv[0] == 0xA2) && (rtc.data_recv_index >= 2))
|
| 112 | | {
|
| 113 | | UINT8 rtc_pos, rtc_val;
|
| 114 | | rtc_pos = rtc.data_recv[1] + (rtc.data_recv_index - 2);
|
| 115 | | rtc_val = rtc.data_recv[rtc.data_recv_index];
|
| 116 | | //if (rtc_pos == 0) rtc_val = rtc_val & 3; // what is this doing here?
|
| 117 | | rtc.data[rtc_pos] = rtc_val;
|
| 118 | | }
|
| 119 | | // next byte
|
| 120 | | rtc.bits = 0;
|
| 121 | | rtc.data_recv_index++;
|
| 122 | | }
|
| 123 | | }
|
| 124 | | break;
|
| 125 | | // RTC -> HOST
|
| 126 | | case RTC_MODE_SEND :
|
| 127 | | {
|
| 128 | | // set bit
|
| 129 | | rtc.inp = (rtc.data[rtc.pos] >> (7 - rtc.bits)) & 1;
|
| 130 | | rtc.bits++;
|
| 131 | | // bit 9 = end
|
| 132 | | if (rtc.bits > 8)
|
| 133 | | {
|
| 134 | | _logerror( 2, "pcf8593_read_byte(%02X)\n", rtc.data[rtc.pos]);
|
| 135 | | // end ?
|
| 136 | | if (rtc.pin_sda)
|
| 137 | | {
|
| 138 | | _logerror( 2, "pcf8593 end\n");
|
| 139 | | rtc.mode = RTC_MODE_RECV;
|
| 140 | | pcf8593_clear_buffer_rx();
|
| 141 | | }
|
| 142 | | // next byte
|
| 143 | | rtc.bits = 0;
|
| 144 | | rtc.pos++;
|
| 145 | | }
|
| 146 | | }
|
| 147 | | break;
|
| 148 | | }
|
| 149 | | }
|
| 150 | | // save scl
|
| 151 | | rtc.pin_scl = data;
|
| 152 | | }
|
| 153 | | |
| 154 | | void pcf8593_pin_sda_w( int data)
|
| 155 | | {
|
| 156 | | // clock is high
|
| 157 | | if (rtc.pin_scl)
|
| 158 | | {
|
| 159 | | // log init I2C
|
| 160 | | if (data) _logerror( 1, "pcf8593 init i2c\n");
|
| 161 | | // start condition (high to low when clock is high)
|
| 162 | | if ((!data) && (rtc.pin_sda))
|
| 163 | | {
|
| 164 | | _logerror( 1, "pcf8593 start condition\n");
|
| 165 | | rtc.active = TRUE;
|
| 166 | | rtc.bits = 0;
|
| 167 | | rtc.data_recv_index = 0;
|
| 168 | | pcf8593_clear_buffer_rx();
|
| 169 | | //rtc.pos = 0;
|
| 170 | | }
|
| 171 | | // stop condition (low to high when clock is high)
|
| 172 | | if ((data) && (!rtc.pin_sda))
|
| 173 | | {
|
| 174 | | _logerror( 1, "pcf8593 stop condition\n");
|
| 175 | | rtc.active = FALSE;
|
| 176 | | }
|
| 177 | | }
|
| 178 | | // save sda
|
| 179 | | rtc.pin_sda = data;
|
| 180 | | }
|
| 181 | | |
| 182 | | int pcf8593_pin_sda_r( void)
|
| 183 | | {
|
| 184 | | return rtc.inp;
|
| 185 | | }
|
| 186 | | |
| 187 | | void pcf8593_clear_buffer_rx( void)
|
| 188 | | {
|
| 189 | | memset( &rtc.data_recv[0], 0, sizeof( rtc.data_recv));
|
| 190 | | rtc.data_recv_index = 0;
|
| 191 | | }
|
| 192 | | |
| 193 | | static UINT8 dec_to_bcd( UINT8 data)
|
| 194 | | {
|
| 195 | | return ((data / 10) << 4) | ((data % 10) << 0);
|
| 196 | | }
|
| 197 | | |
| 198 | | static UINT8 bcd_to_dec( UINT8 data)
|
| 199 | | {
|
| 200 | | if ((data & 0x0F) >= 0x0A) data = data - 0x0A + 0x10;
|
| 201 | | if ((data & 0xF0) >= 0xA0) data = data - 0xA0;
|
| 202 | | return (data & 0x0F) + (((data & 0xF0) >> 4) * 10);
|
| 203 | | }
|
| 204 | | |
| 205 | | void pcf8593_set_time( int hour, int minute, int second)
|
| 206 | | {
|
| 207 | | RTC_SET_TIME_HOUR( hour);
|
| 208 | | RTC_SET_TIME_MINUTE( minute);
|
| 209 | | RTC_SET_TIME_SECOND( second);
|
| 210 | | rtc.data[1] = 0; // hundreds of a seconds
|
| 211 | | }
|
| 212 | | |
| 213 | | void pcf8593_set_date( int year, int month, int day)
|
| 214 | | {
|
| 215 | | RTC_SET_DATE_YEAR( year);
|
| 216 | | RTC_SET_DATE_MONTH( month);
|
| 217 | | RTC_SET_DATE_DAY( day);
|
| 218 | | }
|
| 219 | | |
| 220 | | static int get_days_in_month( int year, int month)
|
| 221 | | {
|
| 222 | | static const int table[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
| 223 | | if ((month == 2) && ((year & 0x03) == 0)) return 29;
|
| 224 | | return table[month-1];
|
| 225 | | }
|
| 226 | | |
| 227 | | static TIMER_CALLBACK( pcf8593_timer_callback )
|
| 228 | | {
|
| 229 | | int value;
|
| 230 | | _logerror( 2, "pcf8593_timer_callback (%d)\n", param);
|
| 231 | | // check if counting is enabled
|
| 232 | | if (rtc.data[0] & 0x80) return;
|
| 233 | | // increment second
|
| 234 | | value = RTC_GET_TIME_SECOND;
|
| 235 | | if (value < 59)
|
| 236 | | {
|
| 237 | | RTC_SET_TIME_SECOND( value + 1);
|
| 238 | | }
|
| 239 | | else
|
| 240 | | {
|
| 241 | | RTC_SET_TIME_SECOND( 0);
|
| 242 | | // increment minute
|
| 243 | | value = RTC_GET_TIME_MINUTE;
|
| 244 | | if (value < 59)
|
| 245 | | {
|
| 246 | | RTC_SET_TIME_MINUTE( value + 1);
|
| 247 | | }
|
| 248 | | else
|
| 249 | | {
|
| 250 | | RTC_SET_TIME_MINUTE( 0);
|
| 251 | | // increment hour
|
| 252 | | value = RTC_GET_TIME_HOUR;
|
| 253 | | if (value < 23)
|
| 254 | | {
|
| 255 | | RTC_SET_TIME_HOUR( value + 1);
|
| 256 | | }
|
| 257 | | else
|
| 258 | | {
|
| 259 | | RTC_SET_TIME_HOUR( 0);
|
| 260 | | // increment day
|
| 261 | | value = RTC_GET_DATE_DAY;
|
| 262 | | if (value < get_days_in_month( RTC_GET_DATE_YEAR, RTC_GET_DATE_MONTH))
|
| 263 | | {
|
| 264 | | RTC_SET_DATE_DAY( value + 1);
|
| 265 | | }
|
| 266 | | else
|
| 267 | | {
|
| 268 | | RTC_SET_DATE_DAY( 1);
|
| 269 | | // increase month
|
| 270 | | value = RTC_GET_DATE_MONTH;
|
| 271 | | if (value < 12)
|
| 272 | | {
|
| 273 | | RTC_SET_DATE_MONTH( value + 1);
|
| 274 | | }
|
| 275 | | else
|
| 276 | | {
|
| 277 | | RTC_SET_DATE_MONTH( 1);
|
| 278 | | // increase year
|
| 279 | | RTC_SET_DATE_YEAR( RTC_GET_DATE_YEAR + 1);
|
| 280 | | }
|
| 281 | | }
|
| 282 | | }
|
| 283 | | }
|
| 284 | | }
|
| 285 | | }
|
| 286 | | |
| 287 | | void pcf8593_load( mame_file *file)
|
| 288 | | {
|
| 289 | | mame_system_time systime;
|
| 290 | | _logerror( 0, "pcf8593_load (%p)\n", file);
|
| 291 | | mame_fread( file, rtc.data, rtc.size);
|
| 292 | | mame_get_current_datetime( Machine, &systime);
|
| 293 | | pcf8593_set_date( systime.local_time.year, systime.local_time.month + 1, systime.local_time.mday);
|
| 294 | | pcf8593_set_time( systime.local_time.hour, systime.local_time.minute, systime.local_time.second);
|
| 295 | | }
|
| 296 | | |
| 297 | | void pcf8593_save( mame_file *file)
|
| 298 | | {
|
| 299 | | _logerror( 0, "pcf8593_save (%p)\n", file);
|
| 300 | | mame_fwrite( file, rtc.data, rtc.size);
|
| 301 | | }
|
| 302 | | |
| 303 | | /*
|
| 304 | | NVRAM_HANDLER( pcf8593 )
|
| 305 | | {
|
| 306 | | _logerror( 0, "nvram_handler_pcf8593 (%p/%d)\n", file, read_or_write);
|
| 307 | | if (read_or_write)
|
| 308 | | {
|
| 309 | | pcf8593_save( file);
|
| 310 | | }
|
| 311 | | else
|
| 312 | | {
|
| 313 | | if (file)
|
| 314 | | {
|
| 315 | | pcf8593_load( file);
|
| 316 | | }
|
| 317 | | else
|
| 318 | | {
|
| 319 | | memset( rtc.data, 0, rtc.size);
|
| 320 | | }
|
| 321 | | }
|
| 322 | | }
|
| 323 | | */
|
| 1 | /* |
| 2 | |
| 3 | Philips PCF8593 CMOS clock/calendar circuit |
| 4 | |
| 5 | (c) 2001-2007 Tim Schuerewegen |
| 6 | |
| 7 | */ |
| 8 | |
| 9 | #include "pcf8593.h" |
| 10 | |
| 11 | #include <time.h> |
| 12 | |
| 13 | #define LOG_LEVEL 1 |
| 14 | #define _logerror(level,...) if (LOG_LEVEL > level) logerror(__VA_ARGS__) |
| 15 | |
| 16 | #define RTC_MODE_NONE 0 |
| 17 | #define RTC_MODE_SEND 1 |
| 18 | #define RTC_MODE_RECV 2 |
| 19 | |
| 20 | // get/set date |
| 21 | #define RTC_GET_DATE_YEAR ((rtc.data[5] >> 6) & 3) |
| 22 | #define RTC_SET_DATE_YEAR(x) rtc.data[5] = (rtc.data[5] & 0x3F) | (((x) % 4) << 6) |
| 23 | #define RTC_GET_DATE_MONTH bcd_to_dec( rtc.data[6]) |
| 24 | #define RTC_SET_DATE_MONTH(x) rtc.data[6] = dec_to_bcd( x) |
| 25 | #define RTC_GET_DATE_DAY (bcd_to_dec( rtc.data[5] & 0x3F)) |
| 26 | #define RTC_SET_DATE_DAY(x) rtc.data[5] = (rtc.data[5] & 0xC0) | dec_to_bcd( x) |
| 27 | |
| 28 | // get/set time |
| 29 | #define RTC_GET_TIME_HOUR bcd_to_dec( rtc.data[4]) |
| 30 | #define RTC_SET_TIME_HOUR(x) rtc.data[4] = dec_to_bcd( x) |
| 31 | #define RTC_GET_TIME_MINUTE bcd_to_dec( rtc.data[3]) |
| 32 | #define RTC_SET_TIME_MINUTE(x) rtc.data[3] = dec_to_bcd( x) |
| 33 | #define RTC_GET_TIME_SECOND bcd_to_dec( rtc.data[2]) |
| 34 | #define RTC_SET_TIME_SECOND(x) rtc.data[2] = dec_to_bcd( x) |
| 35 | |
| 36 | static void pcf8593_clear_buffer_rx( void); |
| 37 | static TIMER_CALLBACK( pcf8593_timer_callback ); |
| 38 | |
| 39 | typedef struct |
| 40 | { |
| 41 | UINT8 *data; |
| 42 | UINT32 size; |
| 43 | int pin_scl, pin_sda, inp; |
| 44 | bool active; |
| 45 | int bits; |
| 46 | UINT8 data_recv_index, data_recv[50]; |
| 47 | UINT8 mode, pos; |
| 48 | mame_timer *timer; |
| 49 | } PCF8593; |
| 50 | |
| 51 | static PCF8593 rtc; |
| 52 | |
| 53 | void pcf8593_init( void) |
| 54 | { |
| 55 | _logerror( 0, "pcf8593_init\n"); |
| 56 | memset( &rtc, 0, sizeof( rtc)); |
| 57 | rtc.size = 16; |
| 58 | rtc.data = malloc( rtc.size); |
| 59 | rtc.timer = mame_timer_alloc( pcf8593_timer_callback ); |
| 60 | mame_timer_adjust( rtc.timer, MAME_TIME_IN_SEC(1), 0, MAME_TIME_IN_SEC(1)); |
| 61 | pcf8593_reset(); |
| 62 | } |
| 63 | |
| 64 | void pcf8593_exit( void) |
| 65 | { |
| 66 | _logerror( 0, "pcf8593_exit\n"); |
| 67 | free( rtc.data); |
| 68 | } |
| 69 | |
| 70 | void pcf8593_reset( void) |
| 71 | { |
| 72 | _logerror( 0, "pcf8593_reset\n"); |
| 73 | rtc.pin_scl = 1; |
| 74 | rtc.pin_sda = 1; |
| 75 | rtc.active = FALSE; |
| 76 | rtc.inp = 0; |
| 77 | rtc.mode = RTC_MODE_RECV; |
| 78 | rtc.bits = 0; |
| 79 | pcf8593_clear_buffer_rx(); |
| 80 | rtc.pos = 0; |
| 81 | } |
| 82 | |
| 83 | void pcf8593_pin_scl( int data) |
| 84 | { |
| 85 | // send bit |
| 86 | if ((rtc.active) && (!rtc.pin_scl) && (data)) |
| 87 | { |
| 88 | switch (rtc.mode) |
| 89 | { |
| 90 | // HOST -> RTC |
| 91 | case RTC_MODE_RECV : |
| 92 | { |
| 93 | // get bit |
| 94 | if (rtc.pin_sda) rtc.data_recv[rtc.data_recv_index] = rtc.data_recv[rtc.data_recv_index] | (0x80 >> rtc.bits); |
| 95 | rtc.bits++; |
| 96 | // bit 9 = end |
| 97 | if (rtc.bits > 8) |
| 98 | { |
| 99 | _logerror( 2, "pcf8593_write_byte(%02X)\n", rtc.data_recv[rtc.data_recv_index]); |
| 100 | // enter receive mode when 1st byte = 0xA3 |
| 101 | if ((rtc.data_recv[0] == 0xA3) && (rtc.data_recv_index == 0)) |
| 102 | { |
| 103 | rtc.mode = RTC_MODE_SEND; |
| 104 | } |
| 105 | // A2 + xx = "read from pos xx" command |
| 106 | if ((rtc.data_recv[0] == 0xA2) && (rtc.data_recv_index == 1)) |
| 107 | { |
| 108 | rtc.pos = rtc.data_recv[1]; |
| 109 | } |
| 110 | // A2 + xx + .. = write byte |
| 111 | if ((rtc.data_recv[0] == 0xA2) && (rtc.data_recv_index >= 2)) |
| 112 | { |
| 113 | UINT8 rtc_pos, rtc_val; |
| 114 | rtc_pos = rtc.data_recv[1] + (rtc.data_recv_index - 2); |
| 115 | rtc_val = rtc.data_recv[rtc.data_recv_index]; |
| 116 | //if (rtc_pos == 0) rtc_val = rtc_val & 3; // what is this doing here? |
| 117 | rtc.data[rtc_pos] = rtc_val; |
| 118 | } |
| 119 | // next byte |
| 120 | rtc.bits = 0; |
| 121 | rtc.data_recv_index++; |
| 122 | } |
| 123 | } |
| 124 | break; |
| 125 | // RTC -> HOST |
| 126 | case RTC_MODE_SEND : |
| 127 | { |
| 128 | // set bit |
| 129 | rtc.inp = (rtc.data[rtc.pos] >> (7 - rtc.bits)) & 1; |
| 130 | rtc.bits++; |
| 131 | // bit 9 = end |
| 132 | if (rtc.bits > 8) |
| 133 | { |
| 134 | _logerror( 2, "pcf8593_read_byte(%02X)\n", rtc.data[rtc.pos]); |
| 135 | // end ? |
| 136 | if (rtc.pin_sda) |
| 137 | { |
| 138 | _logerror( 2, "pcf8593 end\n"); |
| 139 | rtc.mode = RTC_MODE_RECV; |
| 140 | pcf8593_clear_buffer_rx(); |
| 141 | } |
| 142 | // next byte |
| 143 | rtc.bits = 0; |
| 144 | rtc.pos++; |
| 145 | } |
| 146 | } |
| 147 | break; |
| 148 | } |
| 149 | } |
| 150 | // save scl |
| 151 | rtc.pin_scl = data; |
| 152 | } |
| 153 | |
| 154 | void pcf8593_pin_sda_w( int data) |
| 155 | { |
| 156 | // clock is high |
| 157 | if (rtc.pin_scl) |
| 158 | { |
| 159 | // log init I2C |
| 160 | if (data) _logerror( 1, "pcf8593 init i2c\n"); |
| 161 | // start condition (high to low when clock is high) |
| 162 | if ((!data) && (rtc.pin_sda)) |
| 163 | { |
| 164 | _logerror( 1, "pcf8593 start condition\n"); |
| 165 | rtc.active = TRUE; |
| 166 | rtc.bits = 0; |
| 167 | rtc.data_recv_index = 0; |
| 168 | pcf8593_clear_buffer_rx(); |
| 169 | //rtc.pos = 0; |
| 170 | } |
| 171 | // stop condition (low to high when clock is high) |
| 172 | if ((data) && (!rtc.pin_sda)) |
| 173 | { |
| 174 | _logerror( 1, "pcf8593 stop condition\n"); |
| 175 | rtc.active = FALSE; |
| 176 | } |
| 177 | } |
| 178 | // save sda |
| 179 | rtc.pin_sda = data; |
| 180 | } |
| 181 | |
| 182 | int pcf8593_pin_sda_r( void) |
| 183 | { |
| 184 | return rtc.inp; |
| 185 | } |
| 186 | |
| 187 | void pcf8593_clear_buffer_rx( void) |
| 188 | { |
| 189 | memset( &rtc.data_recv[0], 0, sizeof( rtc.data_recv)); |
| 190 | rtc.data_recv_index = 0; |
| 191 | } |
| 192 | |
| 193 | static UINT8 dec_to_bcd( UINT8 data) |
| 194 | { |
| 195 | return ((data / 10) << 4) | ((data % 10) << 0); |
| 196 | } |
| 197 | |
| 198 | static UINT8 bcd_to_dec( UINT8 data) |
| 199 | { |
| 200 | if ((data & 0x0F) >= 0x0A) data = data - 0x0A + 0x10; |
| 201 | if ((data & 0xF0) >= 0xA0) data = data - 0xA0; |
| 202 | return (data & 0x0F) + (((data & 0xF0) >> 4) * 10); |
| 203 | } |
| 204 | |
| 205 | void pcf8593_set_time( int hour, int minute, int second) |
| 206 | { |
| 207 | RTC_SET_TIME_HOUR( hour); |
| 208 | RTC_SET_TIME_MINUTE( minute); |
| 209 | RTC_SET_TIME_SECOND( second); |
| 210 | rtc.data[1] = 0; // hundreds of a seconds |
| 211 | } |
| 212 | |
| 213 | void pcf8593_set_date( int year, int month, int day) |
| 214 | { |
| 215 | RTC_SET_DATE_YEAR( year); |
| 216 | RTC_SET_DATE_MONTH( month); |
| 217 | RTC_SET_DATE_DAY( day); |
| 218 | } |
| 219 | |
| 220 | static int get_days_in_month( int year, int month) |
| 221 | { |
| 222 | static const int table[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
| 223 | if ((month == 2) && ((year & 0x03) == 0)) return 29; |
| 224 | return table[month-1]; |
| 225 | } |
| 226 | |
| 227 | static TIMER_CALLBACK( pcf8593_timer_callback ) |
| 228 | { |
| 229 | int value; |
| 230 | _logerror( 2, "pcf8593_timer_callback (%d)\n", param); |
| 231 | // check if counting is enabled |
| 232 | if (rtc.data[0] & 0x80) return; |
| 233 | // increment second |
| 234 | value = RTC_GET_TIME_SECOND; |
| 235 | if (value < 59) |
| 236 | { |
| 237 | RTC_SET_TIME_SECOND( value + 1); |
| 238 | } |
| 239 | else |
| 240 | { |
| 241 | RTC_SET_TIME_SECOND( 0); |
| 242 | // increment minute |
| 243 | value = RTC_GET_TIME_MINUTE; |
| 244 | if (value < 59) |
| 245 | { |
| 246 | RTC_SET_TIME_MINUTE( value + 1); |
| 247 | } |
| 248 | else |
| 249 | { |
| 250 | RTC_SET_TIME_MINUTE( 0); |
| 251 | // increment hour |
| 252 | value = RTC_GET_TIME_HOUR; |
| 253 | if (value < 23) |
| 254 | { |
| 255 | RTC_SET_TIME_HOUR( value + 1); |
| 256 | } |
| 257 | else |
| 258 | { |
| 259 | RTC_SET_TIME_HOUR( 0); |
| 260 | // increment day |
| 261 | value = RTC_GET_DATE_DAY; |
| 262 | if (value < get_days_in_month( RTC_GET_DATE_YEAR, RTC_GET_DATE_MONTH)) |
| 263 | { |
| 264 | RTC_SET_DATE_DAY( value + 1); |
| 265 | } |
| 266 | else |
| 267 | { |
| 268 | RTC_SET_DATE_DAY( 1); |
| 269 | // increase month |
| 270 | value = RTC_GET_DATE_MONTH; |
| 271 | if (value < 12) |
| 272 | { |
| 273 | RTC_SET_DATE_MONTH( value + 1); |
| 274 | } |
| 275 | else |
| 276 | { |
| 277 | RTC_SET_DATE_MONTH( 1); |
| 278 | // increase year |
| 279 | RTC_SET_DATE_YEAR( RTC_GET_DATE_YEAR + 1); |
| 280 | } |
| 281 | } |
| 282 | } |
| 283 | } |
| 284 | } |
| 285 | } |
| 286 | |
| 287 | void pcf8593_load( mame_file *file) |
| 288 | { |
| 289 | mame_system_time systime; |
| 290 | _logerror( 0, "pcf8593_load (%p)\n", file); |
| 291 | mame_fread( file, rtc.data, rtc.size); |
| 292 | mame_get_current_datetime( Machine, &systime); |
| 293 | pcf8593_set_date( systime.local_time.year, systime.local_time.month + 1, systime.local_time.mday); |
| 294 | pcf8593_set_time( systime.local_time.hour, systime.local_time.minute, systime.local_time.second); |
| 295 | } |
| 296 | |
| 297 | void pcf8593_save( mame_file *file) |
| 298 | { |
| 299 | _logerror( 0, "pcf8593_save (%p)\n", file); |
| 300 | mame_fwrite( file, rtc.data, rtc.size); |
| 301 | } |
| 302 | |
| 303 | /* |
| 304 | NVRAM_HANDLER( pcf8593 ) |
| 305 | { |
| 306 | _logerror( 0, "nvram_handler_pcf8593 (%p/%d)\n", file, read_or_write); |
| 307 | if (read_or_write) |
| 308 | { |
| 309 | pcf8593_save( file); |
| 310 | } |
| 311 | else |
| 312 | { |
| 313 | if (file) |
| 314 | { |
| 315 | pcf8593_load( file); |
| 316 | } |
| 317 | else |
| 318 | { |
| 319 | memset( rtc.data, 0, rtc.size); |
| 320 | } |
| 321 | } |
| 322 | } |
| 323 | */ |
src/mess/machine/at45dbxx.c
| r882 | r883 | |
| 1 | | /*
|
| 2 | | |
| 3 | | Atmel Serial DataFlash
|
| 4 | | |
| 5 | | (c) 2001-2007 Tim Schuerewegen
|
| 6 | | |
| 7 | | AT45DB041 - 528 KByte
|
| 8 | | AT45DB081 - 1056 KByte
|
| 9 | | AT45DB161 - 2112 KByte
|
| 10 | | |
| 11 | | */
|
| 12 | | |
| 13 | | #include "at45dbxx.h"
|
| 14 | | |
| 15 | | #define LOG_LEVEL 1
|
| 16 | | #define _logerror(level,...) if (LOG_LEVEL > level) logerror(__VA_ARGS__)
|
| 17 | | |
| 18 | | #define FLASH_CMD_52 0x52
|
| 19 | | #define FLASH_CMD_57 0x57
|
| 20 | | #define FLASH_CMD_60 0x60
|
| 21 | | #define FLASH_CMD_82 0x82
|
| 22 | | |
| 23 | | #define FLASH_MODE_XX 0 // unknown
|
| 24 | | #define FLASH_MODE_SI 1 // input
|
| 25 | | #define FLASH_MODE_SO 2 // output
|
| 26 | | |
| 27 | | typedef struct
|
| 28 | | {
|
| 29 | | int cs; // chip select
|
| 30 | | int sck; // serial clock
|
| 31 | | int si; // serial input
|
| 32 | | int so; // serial output
|
| 33 | | int wp; // write protect
|
| 34 | | int reset; // reset
|
| 35 | | int busy; // busy
|
| 36 | | } AT45DBXX_PINS;
|
| 37 | | |
| 38 | | typedef struct
|
| 39 | | {
|
| 40 | | UINT8 data[8], size;
|
| 41 | | } AT45DBXX_CMD;
|
| 42 | | |
| 43 | | typedef struct
|
| 44 | | {
|
| 45 | | UINT8 *data;
|
| 46 | | UINT32 size, pos;
|
| 47 | | } AT45DBXX_IO;
|
| 48 | | |
| 49 | | typedef struct
|
| 50 | | {
|
| 51 | | UINT8 *data;
|
| 52 | | UINT32 size;
|
| 53 | | UINT32 pages, page_size;
|
| 54 | | UINT8 mode, status, devid, *buffer1, *buffer2;
|
| 55 | | AT45DBXX_PINS pin;
|
| 56 | | UINT8 si_byte, si_bits, so_byte, so_bits;
|
| 57 | | AT45DBXX_CMD cmd;
|
| 58 | | AT45DBXX_IO io;
|
| 59 | | } AT45DBXX;
|
| 60 | | |
| 61 | | static AT45DBXX flash;
|
| 62 | | |
| 63 | | void at45dbxx_state_save( void);
|
| 64 | | |
| 65 | | void at45dbxx_init( int type)
|
| 66 | | {
|
| 67 | | _logerror( 0, "at45dbxx_init (%d)\n", type);
|
| 68 | | memset( &flash, 0, sizeof( flash));
|
| 69 | | switch (type)
|
| 70 | | {
|
| 71 | | case AT45DB041 : flash.pages = 2048; flash.page_size = 264; flash.devid = 0x18; break;
|
| 72 | | case AT45DB081 : flash.pages = 4096; flash.page_size = 264; flash.devid = 0x20; break;
|
| 73 | | case AT45DB161 : flash.pages = 4096; flash.page_size = 528; flash.devid = 0x28; break;
|
| 74 | | }
|
| 75 | | flash.size = flash.pages * flash.page_size;
|
| 76 | | flash.data = (UINT8*)malloc( flash.size);
|
| 77 | | flash.buffer1 = (UINT8*)malloc( flash.page_size);
|
| 78 | | flash.buffer2 = (UINT8*)malloc( flash.page_size);
|
| 79 | | at45dbxx_state_save();
|
| 80 | | }
|
| 81 | | |
| 82 | | void at45dbxx_exit( void)
|
| 83 | | {
|
| 84 | | _logerror( 0, "at45dbxx_exit\n");
|
| 85 | | free( flash.buffer2);
|
| 86 | | free( flash.buffer1);
|
| 87 | | free( flash.data);
|
| 88 | | }
|
| 89 | | |
| 90 | | void at45dbxx_reset( void)
|
| 91 | | {
|
| 92 | | _logerror( 1, "at45dbxx_reset\n");
|
| 93 | | // mode
|
| 94 | | flash.mode = FLASH_MODE_SI;
|
| 95 | | // command
|
| 96 | | memset( &flash.cmd.data[0], 0, sizeof( flash.cmd.data));
|
| 97 | | flash.cmd.size = 0;
|
| 98 | | // input/output
|
| 99 | | flash.io.data = NULL;
|
| 100 | | flash.io.size = 0;
|
| 101 | | flash.io.pos = 0;
|
| 102 | | // pins
|
| 103 | | flash.pin.cs = 0;
|
| 104 | | flash.pin.sck = 0;
|
| 105 | | flash.pin.si = 0;
|
| 106 | | flash.pin.so = 0;
|
| 107 | | flash.pin.wp = 0;
|
| 108 | | flash.pin.reset = 0;
|
| 109 | | flash.pin.busy = 0;
|
| 110 | | // output
|
| 111 | | flash.so_byte = 0;
|
| 112 | | flash.so_bits = 0;
|
| 113 | | // input
|
| 114 | | flash.si_byte = 0;
|
| 115 | | flash.si_bits = 0;
|
| 116 | | }
|
| 117 | | |
| 118 | | void at45dbxx_state_save( void)
|
| 119 | | {
|
| 120 | | const char *name = "at45dbxx";
|
| 121 | | // data
|
| 122 | | state_save_register_item_pointer( name, 0, flash.data, flash.size);
|
| 123 | | // pins
|
| 124 | | state_save_register_item( name, 0, flash.pin.cs);
|
| 125 | | state_save_register_item( name, 0, flash.pin.sck);
|
| 126 | | state_save_register_item( name, 0, flash.pin.si);
|
| 127 | | state_save_register_item( name, 0, flash.pin.so);
|
| 128 | | state_save_register_item( name, 0, flash.pin.wp);
|
| 129 | | state_save_register_item( name, 0, flash.pin.reset);
|
| 130 | | state_save_register_item( name, 0, flash.pin.busy);
|
| 131 | | }
|
| 132 | | |
| 133 | | UINT8 at45dbxx_read_byte( void)
|
| 134 | | {
|
| 135 | | UINT8 data;
|
| 136 | | // check mode
|
| 137 | | if ((flash.mode != FLASH_MODE_SO) || (!flash.io.data)) return 0;
|
| 138 | | // read byte
|
| 139 | | data = flash.io.data[flash.io.pos++];
|
| 140 | | _logerror( 2, "at45dbxx_read_byte (%02X) (%03d/%03d)\n", data, flash.io.pos, flash.io.size);
|
| 141 | | if (flash.io.pos == flash.io.size) flash.io.pos = 0;
|
| 142 | | return data;
|
| 143 | | }
|
| 144 | | |
| 145 | | void flash_set_io( UINT8* data, UINT32 size, UINT32 pos)
|
| 146 | | {
|
| 147 | | flash.io.data = data;
|
| 148 | | flash.io.size = size;
|
| 149 | | flash.io.pos = pos;
|
| 150 | | }
|
| 151 | | |
| 152 | | UINT32 flash_get_page_addr( void)
|
| 153 | | {
|
| 154 | | switch (flash.devid)
|
| 155 | | {
|
| 156 | | case 0x18 : return ((flash.cmd.data[1] & 0x0F) << 7) | ((flash.cmd.data[2] & 0xFE) >> 1);
|
| 157 | | case 0x20 : return ((flash.cmd.data[1] & 0x1F) << 7) | ((flash.cmd.data[2] & 0xFE) >> 1);
|
| 158 | | case 0x28 : return ((flash.cmd.data[1] & 0x3F) << 6) | ((flash.cmd.data[2] & 0xFC) >> 2);
|
| 159 | | default : return 0;
|
| 160 | | }
|
| 161 | | }
|
| 162 | | |
| 163 | | UINT32 flash_get_byte_addr( void)
|
| 164 | | {
|
| 165 | | switch (flash.devid)
|
| 166 | | {
|
| 167 | | case 0x18 : // fall-through
|
| 168 | | case 0x20 : return ((flash.cmd.data[2] & 0x01) << 8) | ((flash.cmd.data[3] & 0xFF) >> 0);
|
| 169 | | case 0x28 : return ((flash.cmd.data[2] & 0x03) << 8) | ((flash.cmd.data[3] & 0xFF) >> 0);
|
| 170 | | default : return 0;
|
| 171 | | }
|
| 172 | | }
|
| 173 | | |
| 174 | | void at45dbxx_write_byte( UINT8 data)
|
| 175 | | {
|
| 176 | | // check mode
|
| 177 | | if (flash.mode != FLASH_MODE_SI) return;
|
| 178 | | // process byte
|
| 179 | | if (flash.cmd.size < 8)
|
| 180 | | {
|
| 181 | | UINT8 opcode;
|
| 182 | | _logerror( 2, "at45dbxx_write_byte (%02X)\n", data);
|
| 183 | | // add to command buffer
|
| 184 | | flash.cmd.data[flash.cmd.size++] = data;
|
| 185 | | // check opcode
|
| 186 | | opcode = flash.cmd.data[0];
|
| 187 | | switch (opcode)
|
| 188 | | {
|
| 189 | | // status register read
|
| 190 | | case FLASH_CMD_57 :
|
| 191 | | {
|
| 192 | | // 8 bits command
|
| 193 | | if (flash.cmd.size == 1)
|
| 194 | | {
|
| 195 | | _logerror( 1, "at45dbxx opcode %02X - status register read\n", opcode);
|
| 196 | | flash.status = (flash.status & 0xC7) | flash.devid; // 80 = busy / 40 = compare fail
|
| 197 | | flash_set_io( &flash.status, 1, 0);
|
| 198 | | flash.mode = FLASH_MODE_SO;
|
| 199 | | flash.cmd.size = 8;
|
| 200 | | }
|
| 201 | | }
|
| 202 | | break;
|
| 203 | | // main memory page to buffer 1 compare
|
| 204 | | case FLASH_CMD_60 :
|
| 205 | | {
|
| 206 | | // 8 bits command + 4 bits reserved + 11 bits page address + 9 bits don't care
|
| 207 | | if (flash.cmd.size == 4)
|
| 208 | | {
|
| 209 | | UINT32 page;
|
| 210 | | UINT8 comp;
|
| 211 | | page = flash_get_page_addr();
|
| 212 | | _logerror( 1, "at45dbxx opcode %02X - main memory page to buffer 1 compare [%04X]\n", opcode, page);
|
| 213 | | comp = memcmp( flash.data + page * flash.page_size, flash.buffer1, flash.page_size) == 0 ? 0 : 1;
|
| 214 | | if (comp) flash.status |= 0x40; else flash.status &= ~0x40;
|
| 215 | | _logerror( 1, "at45dbxx page compare %s\n", comp ? "failure" : "success");
|
| 216 | | flash.mode = FLASH_MODE_SI;
|
| 217 | | flash.cmd.size = 8;
|
| 218 | | }
|
| 219 | | }
|
| 220 | | break;
|
| 221 | | // main memory page read
|
| 222 | | case FLASH_CMD_52 :
|
| 223 | | {
|
| 224 | | // 8 bits command + 4 bits reserved + 11 bits page address + 9 bits buffer address + 32 bits don't care
|
| 225 | | if (flash.cmd.size == 8)
|
| 226 | | {
|
| 227 | | UINT32 page, byte;
|
| 228 | | page = flash_get_page_addr();
|
| 229 | | byte = flash_get_byte_addr();
|
| 230 | | _logerror( 1, "at45dbxx opcode %02X - main memory page read [%04X/%04X]\n", opcode, page, byte);
|
| 231 | | flash_set_io( flash.data + page * flash.page_size, flash.page_size, byte);
|
| 232 | | flash.mode = FLASH_MODE_SO;
|
| 233 | | flash.cmd.size = 8;
|
| 234 | | }
|
| 235 | | }
|
| 236 | | break;
|
| 237 | | // main memory page program through buffer 1
|
| 238 | | case FLASH_CMD_82 :
|
| 239 | | {
|
| 240 | | // 8 bits command + 4 bits reserved + 11 bits page address + 9 bits buffer address
|
| 241 | | if (flash.cmd.size == 4)
|
| 242 | | {
|
| 243 | | UINT32 page, byte;
|
| 244 | | page = flash_get_page_addr();
|
| 245 | | byte = flash_get_byte_addr();
|
| 246 | | _logerror( 1, "at45dbxx opcode %02X - main memory page program through buffer 1 [%04X/%04X]\n",opcode, page, byte);
|
| 247 | | flash_set_io( flash.buffer1, flash.page_size, byte);
|
| 248 | | memset( flash.buffer1, 0xFF, flash.page_size);
|
| 249 | | flash.mode = FLASH_MODE_SI;
|
| 250 | | flash.cmd.size = 8;
|
| 251 | | }
|
| 252 | | }
|
| 253 | | break;
|
| 254 | | // other
|
| 255 | | default :
|
| 256 | | {
|
| 257 | | _logerror( 1, "at45dbxx opcode %02X - unknown\n", opcode);
|
| 258 | | flash.cmd.data[0] = 0;
|
| 259 | | flash.cmd.size = 0;
|
| 260 | | }
|
| 261 | | break;
|
| 262 | | }
|
| 263 | | }
|
| 264 | | else
|
| 265 | | {
|
| 266 | | _logerror( 2, "at45dbxx_write_byte (%02X) (%03d/%03d)\n", data, flash.io.pos + 1, flash.io.size);
|
| 267 | | // store byte
|
| 268 | | flash.io.data[flash.io.pos] = data;
|
| 269 | | flash.io.pos++;
|
| 270 | | if (flash.io.pos == flash.io.size) flash.io.pos = 0;
|
| 271 | | }
|
| 272 | | }
|
| 273 | | |
| 274 | | int at45dbxx_pin_so( void)
|
| 275 | | {
|
| 276 | | if (flash.pin.cs == 0) return 0;
|
| 277 | | return flash.pin.so;
|
| 278 | | }
|
| 279 | | |
| 280 | | void at45dbxx_pin_si( int data)
|
| 281 | | {
|
| 282 | | if (flash.pin.cs == 0) return;
|
| 283 | | flash.pin.si = data;
|
| 284 | | }
|
| 285 | | |
| 286 | | void at45dbxx_pin_cs( int data)
|
| 287 | | {
|
| 288 | | // check if changed
|
| 289 | | if (flash.pin.cs == data) return;
|
| 290 | | // cs low-to-high
|
| 291 | | if (data != 0)
|
| 292 | | {
|
| 293 | | // complete program command
|
| 294 | | if ((flash.cmd.size >= 4) && (flash.cmd.data[0] == FLASH_CMD_82))
|
| 295 | | {
|
| 296 | | UINT32 page, byte;
|
| 297 | | page = flash_get_page_addr();
|
| 298 | | byte = flash_get_byte_addr();
|
| 299 | | _logerror( 1, "at45dbxx - program data stored in buffer 1 into selected page in main memory [%04X/%04X]\n", page, byte);
|
| 300 | | memcpy( flash.data + page * flash.page_size, flash.buffer1, flash.page_size);
|
| 301 | | }
|
| 302 | | // reset
|
| 303 | | at45dbxx_reset();
|
| 304 | | }
|
| 305 | | // save cs
|
| 306 | | flash.pin.cs = data;
|
| 307 | | }
|
| 308 | | |
| 309 | | void at45dbxx_pin_sck( int data)
|
| 310 | | {
|
| 311 | | // check if changed
|
| 312 | | if (flash.pin.sck == data) return;
|
| 313 | | // sck high-to-low
|
| 314 | | if (data == 0)
|
| 315 | | {
|
| 316 | | // output (part 1)
|
| 317 | | if (flash.so_bits == 8)
|
| 318 | | {
|
| 319 | | flash.so_bits = 0;
|
| 320 | | flash.so_byte = at45dbxx_read_byte();
|
| 321 | | }
|
| 322 | | // input
|
| 323 | | if (flash.pin.si) flash.si_byte = flash.si_byte | (1 << flash.si_bits);
|
| 324 | | flash.si_bits++;
|
| 325 | | if (flash.si_bits == 8)
|
| 326 | | {
|
| 327 | | flash.si_bits = 0;
|
| 328 | | at45dbxx_write_byte( flash.si_byte);
|
| 329 | | flash.si_byte = 0;
|
| 330 | | }
|
| 331 | | // output (part 2)
|
| 332 | | flash.pin.so = (flash.so_byte >> flash.so_bits) & 1;
|
| 333 | | flash.so_bits++;
|
| 334 | | }
|
| 335 | | // save sck
|
| 336 | | flash.pin.sck = data;
|
| 337 | | }
|
| 338 | | |
| 339 | | void at45dbxx_load( mame_file *file)
|
| 340 | | {
|
| 341 | | _logerror( 0, "at45dbxx_load (%p)\n", file);
|
| 342 | | mame_fread( file, flash.data, flash.size);
|
| 343 | | }
|
| 344 | | |
| 345 | | void at45dbxx_save( mame_file *file)
|
| 346 | | {
|
| 347 | | _logerror( 0, "at45dbxx_save (%p)\n", file);
|
| 348 | | mame_fwrite( file, flash.data, flash.size);
|
| 349 | | }
|
| 350 | | |
| 351 | | /*
|
| 352 | | NVRAM_HANDLER( at45dbxx )
|
| 353 | | {
|
| 354 | | _logerror( 0, "nvram_handler_at45dbxx (%p/%d)\n", file, read_or_write);
|
| 355 | | if (read_or_write)
|
| 356 | | {
|
| 357 | | at45dbxx_save( file);
|
| 358 | | }
|
| 359 | | else
|
| 360 | | {
|
| 361 | | if (file)
|
| 362 | | {
|
| 363 | | at45dbxx_load( file);
|
| 364 | | }
|
| 365 | | else
|
| 366 | | {
|
| 367 | | memset( flash.data, 0xFF, flash.size);
|
| 368 | | }
|
| 369 | | }
|
| 370 | | }
|
| 371 | | */
|
| 1 | /* |
| 2 | |
| 3 | Atmel Serial DataFlash |
| 4 | |
| 5 | (c) 2001-2007 Tim Schuerewegen |
| 6 | |
| 7 | AT45DB041 - 528 KByte |
| 8 | AT45DB081 - 1056 KByte |
| 9 | AT45DB161 - 2112 KByte |
| 10 | |
| 11 | */ |
| 12 | |
| 13 | #include "at45dbxx.h" |
| 14 | |
| 15 | #define LOG_LEVEL 1 |
| 16 | #define _logerror(level,...) if (LOG_LEVEL > level) logerror(__VA_ARGS__) |
| 17 | |
| 18 | #define FLASH_CMD_52 0x52 |
| 19 | #define FLASH_CMD_57 0x57 |
| 20 | #define FLASH_CMD_60 0x60 |
| 21 | #define FLASH_CMD_82 0x82 |
| 22 | |
| 23 | #define FLASH_MODE_XX 0 // unknown |
| 24 | #define FLASH_MODE_SI 1 // input |
| 25 | #define FLASH_MODE_SO 2 // output |
| 26 | |
| 27 | typedef struct |
| 28 | { |
| 29 | int cs; // chip select |
| 30 | int sck; // serial clock |
| 31 | int si; // serial input |
| 32 | int so; // serial output |
| 33 | int wp; // write protect |
| 34 | int reset; // reset |
| 35 | int busy; // busy |
| 36 | } AT45DBXX_PINS; |
| 37 | |
| 38 | typedef struct |
| 39 | { |
| 40 | UINT8 data[8], size; |
| 41 | } AT45DBXX_CMD; |
| 42 | |
| 43 | typedef struct |
| 44 | { |
| 45 | UINT8 *data; |
| 46 | UINT32 size, pos; |
| 47 | } AT45DBXX_IO; |
| 48 | |
| 49 | typedef struct |
| 50 | { |
| 51 | UINT8 *data; |
| 52 | UINT32 size; |
| 53 | UINT32 pages, page_size; |
| 54 | UINT8 mode, status, devid, *buffer1, *buffer2; |
| 55 | AT45DBXX_PINS pin; |
| 56 | UINT8 si_byte, si_bits, so_byte, so_bits; |
| 57 | AT45DBXX_CMD cmd; |
| 58 | AT45DBXX_IO io; |
| 59 | } AT45DBXX; |
| 60 | |
| 61 | static AT45DBXX flash; |
| 62 | |
| 63 | void at45dbxx_state_save( void); |
| 64 | |
| 65 | void at45dbxx_init( int type) |
| 66 | { |
| 67 | _logerror( 0, "at45dbxx_init (%d)\n", type); |
| 68 | memset( &flash, 0, sizeof( flash)); |
| 69 | switch (type) |
| 70 | { |
| 71 | case AT45DB041 : flash.pages = 2048; flash.page_size = 264; flash.devid = 0x18; break; |
| 72 | case AT45DB081 : flash.pages = 4096; flash.page_size = 264; flash.devid = 0x20; break; |
| 73 | case AT45DB161 : flash.pages = 4096; flash.page_size = 528; flash.devid = 0x28; break; |
| 74 | } |
| 75 | flash.size = flash.pages * flash.page_size; |
| 76 | flash.data = (UINT8*)malloc( flash.size); |
| 77 | flash.buffer1 = (UINT8*)malloc( flash.page_size); |
| 78 | flash.buffer2 = (UINT8*)malloc( flash.page_size); |
| 79 | at45dbxx_state_save(); |
| 80 | } |
| 81 | |
| 82 | void at45dbxx_exit( void) |
| 83 | { |
| 84 | _logerror( 0, "at45dbxx_exit\n"); |
| 85 | free( flash.buffer2); |
| 86 | free( flash.buffer1); |
| 87 | free( flash.data); |
| 88 | } |
| 89 | |
| 90 | void at45dbxx_reset( void) |
| 91 | { |
| 92 | _logerror( 1, "at45dbxx_reset\n"); |
| 93 | // mode |
| 94 | flash.mode = FLASH_MODE_SI; |
| 95 | // command |
| 96 | memset( &flash.cmd.data[0], 0, sizeof( flash.cmd.data)); |
| 97 | flash.cmd.size = 0; |
| 98 | // input/output |
| 99 | flash.io.data = NULL; |
| 100 | flash.io.size = 0; |
| 101 | flash.io.pos = 0; |
| 102 | // pins |
| 103 | flash.pin.cs = 0; |
| 104 | flash.pin.sck = 0; |
| 105 | flash.pin.si = 0; |
| 106 | flash.pin.so = 0; |
| 107 | flash.pin.wp = 0; |
| 108 | flash.pin.reset = 0; |
| 109 | flash.pin.busy = 0; |
| 110 | // output |
| 111 | flash.so_byte = 0; |
| 112 | flash.so_bits = 0; |
| 113 | // input |
| 114 | flash.si_byte = 0; |
| 115 | flash.si_bits = 0; |
| 116 | } |
| 117 | |
| 118 | void at45dbxx_state_save( void) |
| 119 | { |
| 120 | const char *name = "at45dbxx"; |
| 121 | // data |
| 122 | state_save_register_item_pointer( name, 0, flash.data, flash.size); |
| 123 | // pins |
| 124 | state_save_register_item( name, 0, flash.pin.cs); |
| 125 | state_save_register_item( name, 0, flash.pin.sck); |
| 126 | state_save_register_item( name, 0, flash.pin.si); |
| 127 | state_save_register_item( name, 0, flash.pin.so); |
| 128 | state_save_register_item( name, 0, flash.pin.wp); |
| 129 | state_save_register_item( name, 0, flash.pin.reset); |
| 130 | state_save_register_item( name, 0, flash.pin.busy); |
| 131 | } |
| 132 | |
| 133 | UINT8 at45dbxx_read_byte( void) |
| 134 | { |
| 135 | UINT8 data; |
| 136 | // check mode |
| 137 | if ((flash.mode != FLASH_MODE_SO) || (!flash.io.data)) return 0; |
| 138 | // read byte |
| 139 | data = flash.io.data[flash.io.pos++]; |
| 140 | _logerror( 2, "at45dbxx_read_byte (%02X) (%03d/%03d)\n", data, flash.io.pos, flash.io.size); |
| 141 | if (flash.io.pos == flash.io.size) flash.io.pos = 0; |
| 142 | return data; |
| 143 | } |
| 144 | |
| 145 | void flash_set_io( UINT8* data, UINT32 size, UINT32 pos) |
| 146 | { |
| 147 | flash.io.data = data; |
| 148 | flash.io.size = size; |
| 149 | flash.io.pos = pos; |
| 150 | } |
| 151 | |
| 152 | UINT32 flash_get_page_addr( void) |
| 153 | { |
| 154 | switch (flash.devid) |
| 155 | { |
| 156 | case 0x18 : return ((flash.cmd.data[1] & 0x0F) << 7) | ((flash.cmd.data[2] & 0xFE) >> 1); |
| 157 | case 0x20 : return ((flash.cmd.data[1] & 0x1F) << 7) | ((flash.cmd.data[2] & 0xFE) >> 1); |
| 158 | case 0x28 : return ((flash.cmd.data[1] & 0x3F) << 6) | ((flash.cmd.data[2] & 0xFC) >> 2); |
| 159 | default : return 0; |
| 160 | } |
| 161 | } |
| 162 | |
| 163 | UINT32 flash_get_byte_addr( void) |
| 164 | { |
| 165 | switch (flash.devid) |
| 166 | { |
| 167 | case 0x18 : // fall-through |
| 168 | case 0x20 : return ((flash.cmd.data[2] & 0x01) << 8) | ((flash.cmd.data[3] & 0xFF) >> 0); |
| 169 | case 0x28 : return ((flash.cmd.data[2] & 0x03) << 8) | ((flash.cmd.data[3] & 0xFF) >> 0); |
| 170 | default : return 0; |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | void at45dbxx_write_byte( UINT8 data) |
| 175 | { |
| 176 | // check mode |
| 177 | if (flash.mode != FLASH_MODE_SI) return; |
| 178 | // process byte |
| 179 | if (flash.cmd.size < 8) |
| 180 | { |
| 181 | UINT8 opcode; |
| 182 | _logerror( 2, "at45dbxx_write_byte (%02X)\n", data); |
| 183 | // add to command buffer |
| 184 | flash.cmd.data[flash.cmd.size++] = data; |
| 185 | // check opcode |
| 186 | opcode = flash.cmd.data[0]; |
| 187 | switch (opcode) |
| 188 | { |
| 189 | // status register read |
| 190 | case FLASH_CMD_57 : |
| 191 | { |
| 192 | // 8 bits command |
| 193 | if (flash.cmd.size == 1) |
| 194 | { |
| 195 | _logerror( 1, "at45dbxx opcode %02X - status register read\n", opcode); |
| 196 | flash.status = (flash.status & 0xC7) | flash.devid; // 80 = busy / 40 = compare fail |
| 197 | flash_set_io( &flash.status, 1, 0); |
| 198 | flash.mode = FLASH_MODE_SO; |
| 199 | flash.cmd.size = 8; |
| 200 | } |
| 201 | } |
| 202 | break; |
| 203 | // main memory page to buffer 1 compare |
| 204 | case FLASH_CMD_60 : |
| 205 | { |
| 206 | // 8 bits command + 4 bits reserved + 11 bits page address + 9 bits don't care |
| 207 | if (flash.cmd.size == 4) |
| 208 | { |
| 209 | UINT32 page; |
| 210 | UINT8 comp; |
| 211 | page = flash_get_page_addr(); |
| 212 | _logerror( 1, "at45dbxx opcode %02X - main memory page to buffer 1 compare [%04X]\n", opcode, page); |
| 213 | comp = memcmp( flash.data + page * flash.page_size, flash.buffer1, flash.page_size) == 0 ? 0 : 1; |
| 214 | if (comp) flash.status |= 0x40; else flash.status &= ~0x40; |
| 215 | _logerror( 1, "at45dbxx page compare %s\n", comp ? "failure" : "success"); |
| 216 | flash.mode = FLASH_MODE_SI; |
| 217 | flash.cmd.size = 8; |
| 218 | } |
| 219 | } |
| 220 | break; |
| 221 | // main memory page read |
| 222 | case FLASH_CMD_52 : |
| 223 | { |
| 224 | // 8 bits command + 4 bits reserved + 11 bits page address + 9 bits buffer address + 32 bits don't care |
| 225 | if (flash.cmd.size == 8) |
| 226 | { |
| 227 | UINT32 page, byte; |
| 228 | page = flash_get_page_addr(); |
| 229 | byte = flash_get_byte_addr(); |
| 230 | _logerror( 1, "at45dbxx opcode %02X - main memory page read [%04X/%04X]\n", opcode, page, byte); |
| 231 | flash_set_io( flash.data + page * flash.page_size, flash.page_size, byte); |
| 232 | flash.mode = FLASH_MODE_SO; |
| 233 | flash.cmd.size = 8; |
| 234 | } |
| 235 | } |
| 236 | break; |
| 237 | // main memory page program through buffer 1 |
| 238 | case FLASH_CMD_82 : |
| 239 | { |
| 240 | // 8 bits command + 4 bits reserved + 11 bits page address + 9 bits buffer address |
| 241 | if (flash.cmd.size == 4) |
| 242 | { |
| 243 | UINT32 page, byte; |
| 244 | page = flash_get_page_addr(); |
| 245 | byte = flash_get_byte_addr(); |
| 246 | _logerror( 1, "at45dbxx opcode %02X - main memory page program through buffer 1 [%04X/%04X]\n",opcode, page, byte); |
| 247 | flash_set_io( flash.buffer1, flash.page_size, byte); |
| 248 | memset( flash.buffer1, 0xFF, flash.page_size); |
| 249 | flash.mode = FLASH_MODE_SI; |
| 250 | flash.cmd.size = 8; |
| 251 | } |
| 252 | } |
| 253 | break; |
| 254 | // other |
| 255 | default : |
| 256 | { |
| 257 | _logerror( 1, "at45dbxx opcode %02X - unknown\n", opcode); |
| 258 | flash.cmd.data[0] = 0; |
| 259 | flash.cmd.size = 0; |
| 260 | } |
| 261 | break; |
| 262 | } |
| 263 | } |
| 264 | else |
| 265 | { |
| 266 | _logerror( 2, "at45dbxx_write_byte (%02X) (%03d/%03d)\n", data, flash.io.pos + 1, flash.io.size); |
| 267 | // store byte |
| 268 | flash.io.data[flash.io.pos] = data; |
| 269 | flash.io.pos++; |
| 270 | if (flash.io.pos == flash.io.size) flash.io.pos = 0; |
| 271 | } |
| 272 | } |
| 273 | |
| 274 | int at45dbxx_pin_so( void) |
| 275 | { |
| 276 | if (flash.pin.cs == 0) return 0; |
| 277 | return flash.pin.so; |
| 278 | } |
| 279 | |
| 280 | void at45dbxx_pin_si( int data) |
| 281 | { |
| 282 | if (flash.pin.cs == 0) return; |
| 283 | flash.pin.si = data; |
| 284 | } |
| 285 | |
| 286 | void at45dbxx_pin_cs( int data) |
| 287 | { |
| 288 | // check if changed |
| 289 | if (flash.pin.cs == data) return; |
| 290 | // cs low-to-high |
| 291 | if (data != 0) |
| 292 | { |
| 293 | // complete program command |
| 294 | if ((flash.cmd.size >= 4) && (flash.cmd.data[0] == FLASH_CMD_82)) |
| 295 | { |
| 296 | UINT32 page, byte; |
| 297 | page = flash_get_page_addr(); |
| 298 | byte = flash_get_byte_addr(); |
| 299 | _logerror( 1, "at45dbxx - program data stored in buffer 1 into selected page in main memory [%04X/%04X]\n", page, byte); |
| 300 | memcpy( flash.data + page * flash.page_size, flash.buffer1, flash.page_size); |
| 301 | } |
| 302 | // reset |
| 303 | at45dbxx_reset(); |
| 304 | } |
| 305 | // save cs |
| 306 | flash.pin.cs = data; |
| 307 | } |
| 308 | |
| 309 | void at45dbxx_pin_sck( int data) |
| 310 | { |
| 311 | // check if changed |
| 312 | if (flash.pin.sck == data) return; |
| 313 | // sck high-to-low |
| 314 | if (data == 0) |
| 315 | { |
| 316 | // output (part 1) |
| 317 | if (flash.so_bits == 8) |
| 318 | { |
| 319 | flash.so_bits = 0; |
| 320 | flash.so_byte = at45dbxx_read_byte(); |
| 321 | } |
| 322 | // input |
| 323 | if (flash.pin.si) flash.si_byte = flash.si_byte | (1 << flash.si_bits); |
| 324 | flash.si_bits++; |
| 325 | if (flash.si_bits == 8) |
| 326 | { |
| 327 | flash.si_bits = 0; |
| 328 | at45dbxx_write_byte( flash.si_byte); |
| 329 | flash.si_byte = 0; |
| 330 | } |
| 331 | // output (part 2) |
| 332 | flash.pin.so = (flash.so_byte >> flash.so_bits) & 1; |
| 333 | flash.so_bits++; |
| 334 | } |
| 335 | // save sck |
| 336 | flash.pin.sck = data; |
| 337 | } |
| 338 | |
| 339 | void at45dbxx_load( mame_file *file) |
| 340 | { |
| 341 | _logerror( 0, "at45dbxx_load (%p)\n", file); |
| 342 | mame_fread( file, flash.data, flash.size); |
| 343 | } |
| 344 | |
| 345 | void at45dbxx_save( mame_file *file) |
| 346 | { |
| 347 | _logerror( 0, "at45dbxx_save (%p)\n", file); |
| 348 | mame_fwrite( file, flash.data, flash.size); |
| 349 | } |
| 350 | |
| 351 | /* |
| 352 | NVRAM_HANDLER( at45dbxx ) |
| 353 | { |
| 354 | _logerror( 0, "nvram_handler_at45dbxx (%p/%d)\n", file, read_or_write); |
| 355 | if (read_or_write) |
| 356 | { |
| 357 | at45dbxx_save( file); |
| 358 | } |
| 359 | else |
| 360 | { |
| 361 | if (file) |
| 362 | { |
| 363 | at45dbxx_load( file); |
| 364 | } |
| 365 | else |
| 366 | { |
| 367 | memset( flash.data, 0xFF, flash.size); |
| 368 | } |
| 369 | } |
| 370 | } |
| 371 | */ |
src/mess/machine/amigacd.c
| r882 | r883 | |
| 1 | | /***************************************************************************
|
| 2 | | |
| 3 | | Amiga cdrom controller emulation
|
| 4 | |
|
| 5 | | Notes:
|
| 6 | | Many thanks to Toni Willem for all the help and information about the
|
| 7 | | DMAC controller.
|
| 8 | | |
| 9 | | ***************************************************************************/
|
| 10 | | |
| 11 | | #include "mame.h"
|
| 12 | | #include "driver.h"
|
| 13 | | #include "amiga.h"
|
| 14 | | #include "amigacd.h"
|
| 15 | | #include "machine/6526cia.h"
|
| 16 | | #include "machine/wd33c93.h"
|
| 17 | | #include "tpi6525.h"
|
| 18 | | #include "matsucd.h"
|
| 19 | | |
| 20 | | #define VERBOSE_DMAC 0
|
| 21 | | |
| 22 | | #if VERBOSE_DMAC
|
| 23 | | #define LOG logerror
|
| 24 | | #else
|
| 25 | | INLINE void dummy_log( const char *a, ... ) {}
|
| 26 | | #define LOG dummy_log
|
| 27 | | #endif
|
| 28 | | |
| 29 | | /* constants */
|
| 30 | | #define CD_SECTOR_TIME (1000/((300*1024)/2048)) /* 2X CDROM sector time in msec (300KBps) */
|
| 31 | | |
| 32 | | /***************************************************************************
|
| 33 | | |
| 34 | | DMAC
|
| 35 | |
|
| 36 | | ***************************************************************************/
|
| 37 | | |
| 38 | | /*
|
| 39 | | * value to go into DAWR
|
| 40 | | */
|
| 41 | | #define DAWR_ATZSC 3 /* according to A3000T service-manual */
|
| 42 | | |
| 43 | | /*
|
| 44 | | * bits defined for CNTR
|
| 45 | | */
|
| 46 | | #define CNTR_TCEN (1<<7) /* Terminal Count Enable */
|
| 47 | | #define CNTR_PREST (1<<6) /* Perp Reset (not implemented :-((( ) */
|
| 48 | | #define CNTR_PDMD (1<<5) /* Perp Device Mode Select (1=SCSI,0=XT/AT) */
|
| 49 | | #define CNTR_INTEN (1<<4) /* Interrupt Enable */
|
| 50 | | #define CNTR_DDIR (1<<3) /* Device Direction. 1==rd host, wr to perp */
|
| 51 | | |
| 52 | | /*
|
| 53 | | * bits defined for ISTR
|
| 54 | | */
|
| 55 | | #define ISTR_INTX (1<<8) /* XT/AT Interrupt pending */
|
| 56 | | #define ISTR_INT_F (1<<7) /* Interrupt Follow */
|
| 57 | | #define ISTR_INTS (1<<6) /* SCSI Peripheral Interrupt */
|
| 58 | | #define ISTR_E_INT (1<<5) /* End-Of-Process Interrupt */
|
| 59 | | #define ISTR_INT_P (1<<4) /* Interrupt Pending */
|
| 60 | | #define ISTR_UE_INT (1<<3) /* Under-Run FIFO Error Interrupt */
|
| 61 | | #define ISTR_OE_INT (1<<2) /* Over-Run FIFO Error Interrupt */
|
| 62 | | #define ISTR_FF_FLG (1<<1) /* FIFO-Full Flag */
|
| 63 | | #define ISTR_FE_FLG (1<<0) /* FIFO-Empty Flag */
|
| 64 | | |
| 65 | | typedef struct
|
| 66 | | {
|
| 67 | | UINT16 istr; /* Interrupt Status Register (R) */
|
| 68 | | UINT16 cntr; /* Control Register (RW) */
|
| 69 | | UINT32 wtc; /* Word Transfer Count Register (RW) */
|
| 70 | | UINT32 acr; /* Address Count Register (RW) */
|
| 71 | | UINT16 dawr; /* DACK Width Register (W) */
|
| 72 | | mame_timer *dma_timer;
|
| 73 | | } _dmac_data;
|
| 74 | | |
| 75 | | static _dmac_data dmac_data;
|
| 76 | | |
| 77 | | static void check_interrupts( void )
|
| 78 | | {
|
| 79 | | /* if interrupts are disabled, bail */
|
| 80 | | if ( (dmac_data.cntr & CNTR_INTEN) == 0 )
|
| 81 | | return;
|
| 82 | |
|
| 83 | | /* if no interrupts are pending, bail */
|
| 84 | | if ( (dmac_data.istr & ISTR_INT_P) == 0 )
|
| 85 | | return;
|
| 86 | |
|
| 87 | | /* otherwise, generate the IRQ */
|
| 88 | | amiga_custom_w(REG_INTREQ, 0x8000 | INTENA_PORTS, 0);
|
| 89 | | }
|
| 90 | | |
| 91 | | static TIMER_CALLBACK(dmac_dma_proc)
|
| 92 | | {
|
| 93 | | while( dmac_data.wtc > 0 )
|
| 94 | | {
|
| 95 | | UINT16 dat16;
|
| 96 | | UINT8 dat8;
|
| 97 | | |
| 98 | | if ( matsucd_get_next_byte( &dat8 ) < 0 )
|
| 99 | | break;
|
| 100 | | |
| 101 | | dat16 = dat8;
|
| 102 | |
|
| 103 | | if ( matsucd_get_next_byte( &dat8 ) < 0 )
|
| 104 | | break;
|
| 105 | | |
| 106 | | dat16 <<= 8;
|
| 107 | | dat16 |= dat8;
|
| 108 | | |
| 109 | | amiga_chip_ram_w(dmac_data.acr, dat16);
|
| 110 | | |
| 111 | | dmac_data.acr += 2;
|
| 112 | | dmac_data.wtc--;
|
| 113 | | }
|
| 114 | |
|
| 115 | | if ( dmac_data.wtc > 0 )
|
| 116 | | {
|
| 117 | | matsucd_read_next_block();
|
| 118 | | mame_timer_adjust( dmac_data.dma_timer, MAME_TIME_IN_MSEC( CD_SECTOR_TIME ), 0, time_zero );
|
| 119 | | }
|
| 120 | | else
|
| 121 | | {
|
| 122 | | dmac_data.istr |= ISTR_INT_P | ISTR_E_INT;
|
| 123 | | check_interrupts();
|
| 124 | | }
|
| 125 | | }
|
| 126 | | |
| 127 | | static READ16_HANDLER( amiga_dmac_r )
|
| 128 | | {
|
| 129 | | offset &= 0xff;
|
| 130 | | |
| 131 | | switch( offset )
|
| 132 | | {
|
| 133 | | case 0x20:
|
| 134 | | {
|
| 135 | | UINT8 v = dmac_data.istr;
|
| 136 | | LOG( "DMAC: PC=%08x - ISTR Read(%04x)\n", activecpu_get_pc(), dmac_data.istr );
|
| 137 | |
|
| 138 | | dmac_data.istr &= ~0x0f;
|
| 139 | | return v;
|
| 140 | | }
|
| 141 | | break;
|
| 142 | | |
| 143 | | case 0x21:
|
| 144 | | {
|
| 145 | | LOG( "DMAC: PC=%08x - CNTR Read(%04x)\n", activecpu_get_pc(), dmac_data.cntr );
|
| 146 | | return dmac_data.cntr;
|
| 147 | | }
|
| 148 | | break;
|
| 149 | | |
| 150 | | case 0x40: /* wtc hi */
|
| 151 | | {
|
| 152 | | LOG( "DMAC: PC=%08x - WTC HI Read\n", activecpu_get_pc() );
|
| 153 | | return (dmac_data.wtc >> 16);
|
| 154 | | }
|
| 155 | | break;
|
| 156 | |
|
| 157 | | case 0x41: /* wtc lo */
|
| 158 | | {
|
| 159 | | LOG( "DMAC: PC=%08x - WTC LO Read\n", activecpu_get_pc() );
|
| 160 | | return dmac_data.wtc;
|
| 161 | | }
|
| 162 | | break;
|
| 163 | | |
| 164 | | case 0x42: /* acr hi */
|
| 165 | | {
|
| 166 | | LOG( "DMAC: PC=%08x - ACR HI Read\n", activecpu_get_pc() );
|
| 167 | | return (dmac_data.acr >> 16);
|
| 168 | | }
|
| 169 | | break;
|
| 170 | |
|
| 171 | | case 0x43: /* acr lo */
|
| 172 | | {
|
| 173 | | LOG( "DMAC: PC=%08x - ACR LO Read\n", activecpu_get_pc() );
|
| 174 | | return dmac_data.acr;
|
| 175 | | }
|
| 176 | | break;
|
| 177 | | |
| 178 | | case 0x48: /* wd33c93 SCSI expansion */
|
| 179 | | case 0x49:
|
| 180 | | {
|
| 181 | | LOG( "DMAC: PC=%08x - WD33C93 Read(%d)\n", activecpu_get_pc(), offset & 1 );
|
| 182 | | return 0x00; /* Not available without SCSI expansion */
|
| 183 | | }
|
| 184 | | break;
|
| 185 | | |
| 186 | | case 0x50:
|
| 187 | | {
|
| 188 | | LOG( "DMAC: PC=%08x - CDROM RESP Read\n", activecpu_get_pc() );
|
| 189 | | return matsucd_response_r();
|
| 190 | | }
|
| 191 | | break;
|
| 192 | | |
| 193 | | case 0x51: /* XT IO */
|
| 194 | | case 0x52:
|
| 195 | | case 0x53:
|
| 196 | | {
|
| 197 | | LOG( "DMAC: PC=%08x - XT IO Read(%d)\n", activecpu_get_pc(), (offset & 3)-1 );
|
| 198 | | return 0xff;
|
| 199 | | }
|
| 200 | | break;
|
| 201 | | |
| 202 | | case 0x58: /* TPI6525 */
|
| 203 | | case 0x59:
|
| 204 | | case 0x5A:
|
| 205 | | case 0x5B:
|
| 206 | | case 0x5C:
|
| 207 | | case 0x5D:
|
| 208 | | case 0x5E:
|
| 209 | | case 0x5F:
|
| 210 | | case 0x60:
|
| 211 | | case 0x61:
|
| 212 | | case 0x62:
|
| 213 | | case 0x63:
|
| 214 | | case 0x64:
|
| 215 | | case 0x65:
|
| 216 | | case 0x66:
|
| 217 | | case 0x67:
|
| 218 | | {
|
| 219 | | LOG( "DMAC: PC=%08x - TPI6525 Read(%d)\n", activecpu_get_pc(), (offset - 0x58) );
|
| 220 | | return tpi6525_0_port_r(offset - 0x58);
|
| 221 | | }
|
| 222 | | break;
|
| 223 | | |
| 224 | | case 0x70: /* DMA start strobe */
|
| 225 | | {
|
| 226 | | LOG( "DMAC: PC=%08x - DMA Start Strobe\n", activecpu_get_pc() );
|
| 227 | | mame_timer_adjust( dmac_data.dma_timer, MAME_TIME_IN_MSEC( CD_SECTOR_TIME ), 0, time_zero );
|
| 228 | | }
|
| 229 | | break;
|
| 230 | | |
| 231 | | case 0x71: /* DMA stop strobe */
|
| 232 | | {
|
| 233 | | LOG( "DMAC: PC=%08x - DMA Stop Strobe\n", activecpu_get_pc() );
|
| 234 | | mame_timer_reset( dmac_data.dma_timer, time_never );
|
| 235 | | }
|
| 236 | | break;
|
| 237 | | |
| 238 | | case 0x72: /* Clear IRQ strobe */
|
| 239 | | {
|
| 240 | | LOG( "DMAC: PC=%08x - IRQ Clear Strobe\n", activecpu_get_pc() );
|
| 241 | | dmac_data.istr &= ~ISTR_INT_P;
|
| 242 | | }
|
| 243 | | break;
|
| 244 | | |
| 245 | | case 0x74: /* Flush strobe */
|
| 246 | | {
|
| 247 | | LOG( "DMAC: PC=%08x - Flush Strobe\n", activecpu_get_pc() );
|
| 248 | | dmac_data.istr |= ISTR_FE_FLG;
|
| 249 | | }
|
| 250 | | break;
|
| 251 | | |
| 252 | | default:
|
| 253 | | logerror( "DMAC-READ: PC=%08x, offset = %02x\n", activecpu_get_pc(), offset );
|
| 254 | | break;
|
| 255 | | }
|
| 256 | |
|
| 257 | | return 0;
|
| 258 | | }
|
| 259 | | |
| 260 | | static WRITE16_HANDLER( amiga_dmac_w )
|
| 261 | | {
|
| 262 | | offset &= 0xff;
|
| 263 | | |
| 264 | | switch( offset )
|
| 265 | | {
|
| 266 | | case 0x21: /* control write */
|
| 267 | | {
|
| 268 | | LOG( "DMAC: PC=%08x - CNTR Write(%04x)\n", activecpu_get_pc(), data );
|
| 269 | | dmac_data.cntr = data;
|
| 270 | | check_interrupts();
|
| 271 | | }
|
| 272 | | break;
|
| 273 | | |
| 274 | | case 0x40: /* wtc hi */
|
| 275 | | {
|
| 276 | | LOG( "DMAC: PC=%08x - WTC HI Write - data = %04x\n", activecpu_get_pc(), data );
|
| 277 | | dmac_data.wtc &= 0x0000ffff;
|
| 278 | | dmac_data.wtc |= ((UINT32)data) << 16;
|
| 279 | | }
|
| 280 | | break;
|
| 281 | |
|
| 282 | | case 0x41: /* wtc lo */
|
| 283 | | {
|
| 284 | | LOG( "DMAC: PC=%08x - WTC LO Write - data = %04x\n", activecpu_get_pc(), data );
|
| 285 | | dmac_data.wtc &= 0xffff0000;
|
| 286 | | dmac_data.wtc |= data;
|
| 287 | | }
|
| 288 | | break;
|
| 289 | | |
| 290 | | case 0x42: /* acr hi */
|
| 291 | | {
|
| 292 | | LOG( "DMAC: PC=%08x - ACR HI Write - data = %04x\n", activecpu_get_pc(), data );
|
| 293 | | dmac_data.acr &= 0x0000ffff;
|
| 294 | | dmac_data.acr |= ((UINT32)data) << 16;
|
| 295 | | }
|
| 296 | | break;
|
| 297 | |
|
| 298 | | case 0x43: /* acr lo */
|
| 299 | | {
|
| 300 | | LOG( "DMAC: PC=%08x - ACR LO Write - data = %04x\n", activecpu_get_pc(), data );
|
| 301 | | dmac_data.acr &= 0xffff0000;
|
| 302 | | dmac_data.acr |= data;
|
| 303 | | }
|
| 304 | | break;
|
| 305 | | |
| 306 | | case 0x47: /* dawr */
|
| 307 | | {
|
| 308 | | LOG( "DMAC: PC=%08x - DAWR Write - data = %04x\n", activecpu_get_pc(), data );
|
| 309 | | dmac_data.dawr = data;
|
| 310 | | }
|
| 311 | | break;
|
| 312 | | |
| 313 | | case 0x48: /* wd33c93 SCSI expansion */
|
| 314 | | case 0x49:
|
| 315 | | {
|
| 316 | | LOG( "DMAC: PC=%08x - WD33C93 Write(%d) - data = %04x\n", activecpu_get_pc(), offset & 1, data );
|
| 317 | | /* Not available without SCSI expansion */
|
| 318 | | }
|
| 319 | | break;
|
| 320 | | |
| 321 | | case 0x50:
|
| 322 | | {
|
| 323 | | LOG( "DMAC: PC=%08x - CDROM CMD Write - data = %04x\n", activecpu_get_pc(), data );
|
| 324 | | matsucd_command_w( data );
|
| 325 | | }
|
| 326 | | break;
|
| 327 | | |
| 328 | | case 0x58: /* TPI6525 */
|
| 329 | | case 0x59:
|
| 330 | | case 0x5A:
|
| 331 | | case 0x5B:
|
| 332 | | case 0x5C:
|
| 333 | | case 0x5D:
|
| 334 | | case 0x5E:
|
| 335 | | case 0x5F:
|
| 336 | | case 0x60:
|
| 337 | | case 0x61:
|
| 338 | | case 0x62:
|
| 339 | | case 0x63:
|
| 340 | | case 0x64:
|
| 341 | | case 0x65:
|
| 342 | | case 0x66:
|
| 343 | | case 0x67:
|
| 344 | | {
|
| 345 | | LOG( "DMAC: PC=%08x - TPI6525 Write(%d) - data = %04x\n", activecpu_get_pc(), (offset - 0x58), data );
|
| 346 | | tpi6525_0_port_w(offset - 0x58, data);
|
| 347 | | }
|
| 348 | | break;
|
| 349 | | |
| 350 | | case 0x70: /* DMA start strobe */
|
| 351 | | {
|
| 352 | | LOG( "DMAC: PC=%08x - DMA Start Strobe\n", activecpu_get_pc() );
|
| 353 | | mame_timer_adjust( dmac_data.dma_timer, MAME_TIME_IN_MSEC( CD_SECTOR_TIME ), 0, time_zero );
|
| 354 | | }
|
| 355 | | break;
|
| 356 | | |
| 357 | | case 0x71: /* DMA stop strobe */
|
| 358 | | {
|
| 359 | | LOG( "DMAC: PC=%08x - DMA Stop Strobe\n", activecpu_get_pc() );
|
| 360 | | mame_timer_reset( dmac_data.dma_timer, time_never );
|
| 361 | | }
|
| 362 | | break;
|
| 363 | | |
| 364 | | case 0x72: /* Clear IRQ strobe */
|
| 365 | | {
|
| 366 | | LOG( "DMAC: PC=%08x - IRQ Clear Strobe\n", activecpu_get_pc() );
|
| 367 | | dmac_data.istr &= ~ISTR_INT_P;
|
| 368 | | }
|
| 369 | | break;
|
| 370 | | |
| 371 | | case 0x74: /* Flush Strobe */
|
| 372 | | {
|
| 373 | | LOG( "DMAC: PC=%08x - Flush Strobe\n", activecpu_get_pc() );
|
| 374 | | dmac_data.istr |= ISTR_FE_FLG;
|
| 375 | | }
|
| 376 | | break;
|
| 377 | | |
| 378 | | default:
|
| 379 | | logerror( "DMAC-WRITE: PC=%08x, offset = %02x, data = %04x\n", activecpu_get_pc(), offset, data );
|
| 380 | | break;
|
| 381 | | }
|
| 382 | | }
|
| 383 | | |
| 384 | | /***************************************************************************
|
| 385 | | |
| 386 | | Autoconfig
|
| 387 | |
|
| 388 | | ***************************************************************************/
|
| 389 | | |
| 390 | | static void dmac_install(offs_t base)
|
| 391 | | {
|
| 392 | | memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, base, base + 0xFFFF, 0, 0, amiga_dmac_r);
|
| 393 | | memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, base, base + 0xFFFF, 0, 0, amiga_dmac_w);
|
| 394 | | }
|
| 395 | | |
| 396 | | static void dmac_uninstall(offs_t base)
|
| 397 | | {
|
| 398 | | memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, base, base + 0xFFFF, 0, 0, MRA16_UNMAP);
|
| 399 | | memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, base, base + 0xFFFF, 0, 0, MWA16_UNMAP);
|
| 400 | | }
|
| 401 | | |
| 402 | | static amiga_autoconfig_device dmac_device =
|
| 403 | | {
|
| 404 | | 0, /* link into free memory list */
|
| 405 | | 0, /* ROM vector offset valid */
|
| 406 | | 0, /* multiple devices on card */
|
| 407 | | 1, /* number of 64k pages */
|
| 408 | | 3, /* product number (DMAC) */
|
| 409 | | 0, /* prefer 8MB address space */
|
| 410 | | 0, /* can be shut up */
|
| 411 | | 0x0202, /* manufacturers number (Commodore) */
|
| 412 | | 0, /* serial number */
|
| 413 | | 0, /* ROM vector offset */
|
| 414 | | NULL, /* interrupt control read */
|
| 415 | | NULL, /* interrupt control write */
|
| 416 | | dmac_install, /* memory installation */
|
| 417 | | dmac_uninstall /* memory uninstallation */
|
| 418 | | };
|
| 419 | | |
| 420 | | /***************************************************************************
|
| 421 | | |
| 422 | | TPI6525
|
| 423 | |
|
| 424 | | ***************************************************************************/
|
| 425 | | |
| 426 | | static int tp6525_portc_r( void )
|
| 427 | | {
|
| 428 | | int ret = 0;
|
| 429 | |
|
| 430 | | if ( (tpi6525[0].c.ddr & 0x04) == 0 ) /* if pin 2 is set to input */
|
| 431 | | {
|
| 432 | | ret |= matsucd_stch_r() ? 0x00 : 0x04; /* read status change signal */
|
| 433 | | }
|
| 434 | |
|
| 435 | | if ( (tpi6525[0].c.ddr & 0x08) == 0 ) /* if pin 3 is set to input */
|
| 436 | | ret |= matsucd_sten_r() ? 0x08 : 0x00; /* read enable signal */
|
| 437 | |
|
| 438 | | return ret;
|
| 439 | | }
|
| 440 | | |
| 441 | | static void tp6525_portb_w( int data )
|
| 442 | | {
|
| 443 | | if ( tpi6525[0].b.ddr & 0x01 ) /* if pin 0 is set to output */
|
| 444 | | matsucd_cmd_w( data & 1 ); /* write to the /CMD signal */
|
| 445 | |
|
| 446 | | if ( tpi6525[0].b.ddr & 0x02 ) /* if pin 1 is set to output */
|
| 447 | | matsucd_enable_w( data & 2 ); /* write to the /ENABLE signal */
|
| 448 | | }
|
| 449 | | |
| 450 | | static mame_timer *tp6525_delayed_timer;
|
| 451 | | |
| 452 | | static TIMER_CALLBACK(tp6525_delayed_irq)
|
| 453 | | {
|
| 454 | | (void)param;
|
| 455 | |
|
| 456 | | if ( (CUSTOM_REG(REG_INTREQ) & INTENA_PORTS) == 0 )
|
| 457 | | {
|
| 458 | | amiga_custom_w(REG_INTREQ, 0x8000 | INTENA_PORTS, 0);
|
| 459 | | }
|
| 460 | | else
|
| 461 | | {
|
| 462 | | mame_timer_adjust( tp6525_delayed_timer, MAME_TIME_IN_MSEC(1), 0, time_zero );
|
| 463 | | }
|
| 464 | | }
|
| 465 | | |
| 466 | | static void tp6525_irq( int level )
|
| 467 | | {
|
| 468 | | LOG( "TPI6525 Interrupt: level = %d\n", level);
|
| 469 | |
|
| 470 | | if ( level )
|
| 471 | | {
|
| 472 | | if ( (CUSTOM_REG(REG_INTREQ) & INTENA_PORTS) == 0 )
|
| 473 | | {
|
| 474 | | amiga_custom_w(REG_INTREQ, 0x8000 | INTENA_PORTS, 0);
|
| 475 | | }
|
| 476 | | else
|
| 477 | | {
|
| 478 | | /* we *have to* deliver the irq, so if we can't, delay it and try again later */
|
| 479 | | mame_timer_adjust( tp6525_delayed_timer, MAME_TIME_IN_MSEC(1), 0, time_zero );
|
| 480 | | }
|
| 481 | | }
|
| 482 | | }
|
| 483 | | |
| 484 | | static void cdrom_status_enabled( int level )
|
| 485 | | {
|
| 486 | | /* PC3 on the 6525 */
|
| 487 | | tpi6525_0_irq3_level( level );
|
| 488 | | }
|
| 489 | | |
| 490 | | static void cdrom_status_change( int level )
|
| 491 | | {
|
| 492 | | /* invert */
|
| 493 | | level = level ? 0 : 1;
|
| 494 | |
|
| 495 | | /* PC2 on the 6525 */
|
| 496 | | tpi6525_0_irq2_level( level );
|
| 497 | | }
|
| 498 | | |
| 499 | | static void cdrom_subcode_ready( int level )
|
| 500 | | {
|
| 501 | | /* PC1 on the 6525 */
|
| 502 | | tpi6525_0_irq1_level( level );
|
| 503 | | }
|
| 504 | | |
| 505 | | void amigacd_init( void )
|
| 506 | | {
|
| 507 | | /* initialize the dmac */
|
| 508 | | memset( &dmac_data, 0, sizeof( dmac_data ) );
|
| 509 | |
|
| 510 | | dmac_data.dma_timer = mame_timer_alloc(dmac_dma_proc);
|
| 511 | | tp6525_delayed_timer = mame_timer_alloc(tp6525_delayed_irq);
|
| 512 | |
|
| 513 | | /* initialize the 6525 TPI */
|
| 514 | | tpi6525_0_reset();
|
| 515 | |
|
| 516 | | tpi6525[0].a.read = NULL;
|
| 517 | | tpi6525[0].b.read = NULL;
|
| 518 | | tpi6525[0].c.read = tp6525_portc_r;
|
| 519 | |
|
| 520 | | tpi6525[0].a.output = NULL;
|
| 521 | | tpi6525[0].b.output = tp6525_portb_w;
|
| 522 | | tpi6525[0].c.output = NULL;
|
| 523 | |
|
| 524 | | tpi6525[0].interrupt.output = tp6525_irq;
|
| 525 | | tpi6525[0].ca.output = NULL;
|
| 526 | | tpi6525[0].cb.output = NULL;
|
| 527 | |
|
| 528 | | /* initialize the cdrom */
|
| 529 | | matsucd_init();
|
| 530 | | matsucd_set_status_enabled_callback( cdrom_status_enabled );
|
| 531 | | matsucd_set_status_changed_callback( cdrom_status_change );
|
| 532 | | matsucd_set_subcode_ready_callback( cdrom_subcode_ready );
|
| 533 | |
|
| 534 | | /* set up DMAC with autoconfig */
|
| 535 | | amiga_add_autoconfig( &dmac_device );
|
| 536 | | }
|
| 1 | /*************************************************************************** |
| 2 | |
| 3 | Amiga cdrom controller emulation |
| 4 | |
| 5 | Notes: |
| 6 | Many thanks to Toni Willem for all the help and information about the |
| 7 | DMAC controller. |
| 8 | |
| 9 | ***************************************************************************/ |
| 10 | |
| 11 | #include "mame.h" |
| 12 | #include "driver.h" |
| 13 | #include "amiga.h" |
| 14 | #include "amigacd.h" |
| 15 | #include "machine/6526cia.h" |
| 16 | #include "machine/wd33c93.h" |
| 17 | #include "tpi6525.h" |
| 18 | #include "matsucd.h" |
| 19 | |
| 20 | #define VERBOSE_DMAC 0 |
| 21 | |
| 22 | #if VERBOSE_DMAC |
| 23 | #define LOG logerror |
| 24 | #else |
| 25 | INLINE void dummy_log( const char *a, ... ) {} |
| 26 | #define LOG dummy_log |
| 27 | #endif |
| 28 | |
| 29 | /* constants */ |
| 30 | #define CD_SECTOR_TIME (1000/((300*1024)/2048)) /* 2X CDROM sector time in msec (300KBps) */ |
| 31 | |
| 32 | /*************************************************************************** |
| 33 | |
| 34 | DMAC |
| 35 | |
| 36 | ***************************************************************************/ |
| 37 | |
| 38 | /* |
| 39 | * value to go into DAWR |
| 40 | */ |
| 41 | #define DAWR_ATZSC 3 /* according to A3000T service-manual */ |
| 42 | |
| 43 | /* |
| 44 | * bits defined for CNTR |
| 45 | */ |
| 46 | #define CNTR_TCEN (1<<7) /* Terminal Count Enable */ |
| 47 | #define CNTR_PREST (1<<6) /* Perp Reset (not implemented :-((( ) */ |
| 48 | #define CNTR_PDMD (1<<5) /* Perp Device Mode Select (1=SCSI,0=XT/AT) */ |
| 49 | #define CNTR_INTEN (1<<4) /* Interrupt Enable */ |
| 50 | #define CNTR_DDIR (1<<3) /* Device Direction. 1==rd host, wr to perp */ |
| 51 | |
| 52 | /* |
| 53 | * bits defined for ISTR |
| 54 | */ |
| 55 | #define ISTR_INTX (1<<8) /* XT/AT Interrupt pending */ |
| 56 | #define ISTR_INT_F (1<<7) /* Interrupt Follow */ |
| 57 | #define ISTR_INTS (1<<6) /* SCSI Peripheral Interrupt */ |
| 58 | #define ISTR_E_INT (1<<5) /* End-Of-Process Interrupt */ |
| 59 | #define ISTR_INT_P (1<<4) /* Interrupt Pending */ |
| 60 | #define ISTR_UE_INT (1<<3) /* Under-Run FIFO Error Interrupt */ |
| 61 | #define ISTR_OE_INT (1<<2) /* Over-Run FIFO Error Interrupt */ |
| 62 | #define ISTR_FF_FLG (1<<1) /* FIFO-Full Flag */ |
| 63 | #define ISTR_FE_FLG (1<<0) /* FIFO-Empty Flag */ |
| 64 | |
| 65 | typedef struct |
| 66 | { |
| 67 | UINT16 istr; /* Interrupt Status Register (R) */ |
| 68 | UINT16 cntr; /* Control Register (RW) */ |
| 69 | UINT32 wtc; /* Word Transfer Count Register (RW) */ |
| 70 | UINT32 acr; /* Address Count Register (RW) */ |
| 71 | UINT16 dawr; /* DACK Width Register (W) */ |
| 72 | mame_timer *dma_timer; |
| 73 | } _dmac_data; |
| 74 | |
| 75 | static _dmac_data dmac_data; |
| 76 | |
| 77 | static void check_interrupts( void ) |
| 78 | { |
| 79 | /* if interrupts are disabled, bail */ |
| 80 | if ( (dmac_data.cntr & CNTR_INTEN) == 0 ) |
| 81 | return; |
| 82 | |
| 83 | /* if no interrupts are pending, bail */ |
| 84 | if ( (dmac_data.istr & ISTR_INT_P) == 0 ) |
| 85 | return; |
| 86 | |
| 87 | /* otherwise, generate the IRQ */ |
| 88 | amiga_custom_w(REG_INTREQ, 0x8000 | INTENA_PORTS, 0); |
| 89 | } |
| 90 | |
| 91 | static TIMER_CALLBACK(dmac_dma_proc) |
| 92 | { |
| 93 | while( dmac_data.wtc > 0 ) |
| 94 | { |
| 95 | UINT16 dat16; |
| 96 | UINT8 dat8; |
| 97 | |
| 98 | if ( matsucd_get_next_byte( &dat8 ) < 0 ) |
| 99 | break; |
| 100 | |
| 101 | dat16 = dat8; |
| 102 | |
| 103 | if ( matsucd_get_next_byte( &dat8 ) < 0 ) |
| 104 | break; |
| 105 | |
| 106 | dat16 <<= 8; |
| 107 | dat16 |= dat8; |
| 108 | |
| 109 | amiga_chip_ram_w(dmac_data.acr, dat16); |
| 110 | |
| 111 | dmac_data.acr += 2; |
| 112 | dmac_data.wtc--; |
| 113 | } |
| 114 | |
| 115 | if ( dmac_data.wtc > 0 ) |
| 116 | { |
| 117 | matsucd_read_next_block(); |
| 118 | mame_timer_adjust( dmac_data.dma_timer, MAME_TIME_IN_MSEC( CD_SECTOR_TIME ), 0, time_zero ); |
| 119 | } |
| 120 | else |
| 121 | { |
| 122 | dmac_data.istr |= ISTR_INT_P | ISTR_E_INT; |
| 123 | check_interrupts(); |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | static READ16_HANDLER( amiga_dmac_r ) |
| 128 | { |
| 129 | offset &= 0xff; |
| 130 | |
| 131 | switch( offset ) |
| 132 | { |
| 133 | case 0x20: |
| 134 | { |
| 135 | UINT8 v = dmac_data.istr; |
| 136 | LOG( "DMAC: PC=%08x - ISTR Read(%04x)\n", activecpu_get_pc(), dmac_data.istr ); |
| 137 | |
| 138 | dmac_data.istr &= ~0x0f; |
| 139 | return v; |
| 140 | } |
| 141 | break; |
| 142 | |
| 143 | case 0x21: |
| 144 | { |
| 145 | LOG( "DMAC: PC=%08x - CNTR Read(%04x)\n", activecpu_get_pc(), dmac_data.cntr ); |
| 146 | return dmac_data.cntr; |
| 147 | } |
| 148 | break; |
| 149 | |
| 150 | case 0x40: /* wtc hi */ |
| 151 | { |
| 152 | LOG( "DMAC: PC=%08x - WTC HI Read\n", activecpu_get_pc() ); |
| 153 | return (dmac_data.wtc >> 16); |
| 154 | } |
| 155 | break; |
| 156 | |
| 157 | case 0x41: /* wtc lo */ |
| 158 | { |
| 159 | LOG( "DMAC: PC=%08x - WTC LO Read\n", activecpu_get_pc() ); |
| 160 | return dmac_data.wtc; |
| 161 | } |
| 162 | break; |
| 163 | |
| 164 | case 0x42: /* acr hi */ |
| 165 | { |
| 166 | LOG( "DMAC: PC=%08x - ACR HI Read\n", activecpu_get_pc() ); |
| 167 | return (dmac_data.acr >> 16); |
| 168 | } |
| 169 | break; |
| 170 | |
| 171 | case 0x43: /* acr lo */ |
| 172 | { |
| 173 | LOG( "DMAC: PC=%08x - ACR LO Read\n", activecpu_get_pc() ); |
| 174 | return dmac_data.acr; |
| 175 | } |
| 176 | break; |
| 177 | |
| 178 | case 0x48: /* wd33c93 SCSI expansion */ |
| 179 | case 0x49: |
| 180 | { |
| 181 | LOG( "DMAC: PC=%08x - WD33C93 Read(%d)\n", activecpu_get_pc(), offset & 1 ); |
| 182 | return 0x00; /* Not available without SCSI expansion */ |
| 183 | } |
| 184 | break; |
| 185 | |
| 186 | case 0x50: |
| 187 | { |
| 188 | LOG( "DMAC: PC=%08x - CDROM RESP Read\n", activecpu_get_pc() ); |
| 189 | return matsucd_response_r(); |
| 190 | } |
| 191 | break; |
| 192 | |
| 193 | case 0x51: /* XT IO */ |
| 194 | case 0x52: |
| 195 | case 0x53: |
| 196 | { |
| 197 | LOG( "DMAC: PC=%08x - XT IO Read(%d)\n", activecpu_get_pc(), (offset & 3)-1 ); |
| 198 | return 0xff; |
| 199 | } |
| 200 | break; |
| 201 | |
| 202 | case 0x58: /* TPI6525 */ |
| 203 | case 0x59: |
| 204 | case 0x5A: |
| 205 | case 0x5B: |
| 206 | case 0x5C: |
| 207 | case 0x5D: |
| 208 | case 0x5E: |
| 209 | case 0x5F: |
| 210 | case 0x60: |
| 211 | case 0x61: |
| 212 | case 0x62: |
| 213 | case 0x63: |
| 214 | case 0x64: |
| 215 | case 0x65: |
| 216 | case 0x66: |
| 217 | case 0x67: |
| 218 | { |
| 219 | LOG( "DMAC: PC=%08x - TPI6525 Read(%d)\n", activecpu_get_pc(), (offset - 0x58) ); |
| 220 | return tpi6525_0_port_r(offset - 0x58); |
| 221 | } |
| 222 | break; |
| 223 | |
| 224 | case 0x70: /* DMA start strobe */ |
| 225 | { |
| 226 | LOG( "DMAC: PC=%08x - DMA Start Strobe\n", activecpu_get_pc() ); |
| 227 | mame_timer_adjust( dmac_data.dma_timer, MAME_TIME_IN_MSEC( CD_SECTOR_TIME ), 0, time_zero ); |
| 228 | } |
| 229 | break; |
| 230 | |
| 231 | case 0x71: /* DMA stop strobe */ |
| 232 | { |
| 233 | LOG( "DMAC: PC=%08x - DMA Stop Strobe\n", activecpu_get_pc() ); |
| 234 | mame_timer_reset( dmac_data.dma_timer, time_never ); |
| 235 | } |
| 236 | break; |
| 237 | |
| 238 | case 0x72: /* Clear IRQ strobe */ |
| 239 | { |
| 240 | LOG( "DMAC: PC=%08x - IRQ Clear Strobe\n", activecpu_get_pc() ); |
| 241 | dmac_data.istr &= ~ISTR_INT_P; |
| 242 | } |
| 243 | break; |
| 244 | |
| 245 | case 0x74: /* Flush strobe */ |
| 246 | { |
| 247 | LOG( "DMAC: PC=%08x - Flush Strobe\n", activecpu_get_pc() ); |
| 248 | dmac_data.istr |= ISTR_FE_FLG; |
| 249 | } |
| 250 | break; |
| 251 | |
| 252 | default: |
| 253 | logerror( "DMAC-READ: PC=%08x, offset = %02x\n", activecpu_get_pc(), offset ); |
| 254 | break; |
| 255 | } |
| 256 | |
| 257 | return 0; |
| 258 | } |
| 259 | |
| 260 | static WRITE16_HANDLER( amiga_dmac_w ) |
| 261 | { |
| 262 | offset &= 0xff; |
| 263 | |
| 264 | switch( offset ) |
| 265 | { |
| 266 | case 0x21: /* control write */ |
| 267 | { |
| 268 | LOG( "DMAC: PC=%08x - CNTR Write(%04x)\n", activecpu_get_pc(), data ); |
| 269 | dmac_data.cntr = data; |
| 270 | check_interrupts(); |
| 271 | } |
| 272 | break; |
| 273 | |
| 274 | case 0x40: /* wtc hi */ |
| 275 | { |
| 276 | LOG( "DMAC: PC=%08x - WTC HI Write - data = %04x\n", activecpu_get_pc(), data ); |
| 277 | dmac_data.wtc &= 0x0000ffff; |
| 278 | dmac_data.wtc |= ((UINT32)data) << 16; |
| 279 | } |
| 280 | break; |
| 281 | |
| 282 | case 0x41: /* wtc lo */ |
| 283 | { |
| 284 | LOG( "DMAC: PC=%08x - WTC LO Write - data = %04x\n", activecpu_get_pc(), data ); |
| 285 | dmac_data.wtc &= 0xffff0000; |
| 286 | dmac_data.wtc |= data; |
| 287 | } |
| 288 | break; |
| 289 | |
| 290 | case 0x42: /* acr hi */ |
| 291 | { |
| 292 | LOG( "DMAC: PC=%08x - ACR HI Write - data = %04x\n", activecpu_get_pc(), data ); |
| 293 | dmac_data.acr &= 0x0000ffff; |
| 294 | dmac_data.acr |= ((UINT32)data) << 16; |
| 295 | } |
| 296 | break; |
| 297 | |
| 298 | case 0x43: /* acr lo */ |
| 299 | { |
| 300 | LOG( "DMAC: PC=%08x - ACR LO Write - data = %04x\n", activecpu_get_pc(), data ); |
| 301 | dmac_data.acr &= 0xffff0000; |
| 302 | dmac_data.acr |= data; |
| 303 | } |
| 304 | break; |
| 305 | |
| 306 | case 0x47: /* dawr */ |
| 307 | { |
| 308 | LOG( "DMAC: PC=%08x - DAWR Write - data = %04x\n", activecpu_get_pc(), data ); |
| 309 | dmac_data.dawr = data; |
| 310 | } |
| 311 | break; |
| 312 | |
| 313 | case 0x48: /* wd33c93 SCSI expansion */ |
| 314 | case 0x49: |
| 315 | { |
| 316 | LOG( "DMAC: PC=%08x - WD33C93 Write(%d) - data = %04x\n", activecpu_get_pc(), offset & 1, data ); |
| 317 | /* Not available without SCSI expansion */ |
| 318 | } |
| 319 | break; |
| 320 | |
| 321 | case 0x50: |
| 322 | { |
| 323 | LOG( "DMAC: PC=%08x - CDROM CMD Write - data = %04x\n", activecpu_get_pc(), data ); |
| 324 | matsucd_command_w( data ); |
| 325 | } |
| 326 | break; |
| 327 | |
| 328 | case 0x58: /* TPI6525 */ |
| 329 | case 0x59: |
| 330 | case 0x5A: |
| 331 | case 0x5B: |
| 332 | case 0x5C: |
| 333 | case 0x5D: |
| 334 | case 0x5E: |
| 335 | case 0x5F: |
| 336 | case 0x60: |
| 337 | case 0x61: |
| 338 | case 0x62: |
| 339 | case 0x63: |
| 340 | case 0x64: |
| 341 | case 0x65: |
| 342 | case 0x66: |
| 343 | case 0x67: |
| 344 | { |
| 345 | LOG( "DMAC: PC=%08x - TPI6525 Write(%d) - data = %04x\n", activecpu_get_pc(), (offset - 0x58), data ); |
| 346 | tpi6525_0_port_w(offset - 0x58, data); |
| 347 | } |
| 348 | break; |
| 349 | |
| 350 | case 0x70: /* DMA start strobe */ |
| 351 | { |
| 352 | LOG( "DMAC: PC=%08x - DMA Start Strobe\n", activecpu_get_pc() ); |
| 353 | mame_timer_adjust( dmac_data.dma_timer, MAME_TIME_IN_MSEC( CD_SECTOR_TIME ), 0, time_zero ); |
| 354 | } |
| 355 | break; |
| 356 | |
| 357 | case 0x71: /* DMA stop strobe */ |
| 358 | { |
| 359 | LOG( "DMAC: PC=%08x - DMA Stop Strobe\n", activecpu_get_pc() ); |
| 360 | mame_timer_reset( dmac_data.dma_timer, time_never ); |
| 361 | } |
| 362 | break; |
| 363 | |
| 364 | case 0x72: /* Clear IRQ strobe */ |
| 365 | { |
| 366 | LOG( "DMAC: PC=%08x - IRQ Clear Strobe\n", activecpu_get_pc() ); |
| 367 | dmac_data.istr &= ~ISTR_INT_P; |
| 368 | } |
| 369 | break; |
| 370 | |
| 371 | case 0x74: /* Flush Strobe */ |
| 372 | { |
| 373 | LOG( "DMAC: PC=%08x - Flush Strobe\n", activecpu_get_pc() ); |
| 374 | dmac_data.istr |= ISTR_FE_FLG; |
| 375 | } |
| 376 | break; |
| 377 | |
| 378 | default: |
| 379 | logerror( "DMAC-WRITE: PC=%08x, offset = %02x, data = %04x\n", activecpu_get_pc(), offset, data ); |
| 380 | break; |
| 381 | } |
| 382 | } |
| 383 | |
| 384 | /*************************************************************************** |
| 385 | |
| 386 | Autoconfig |
| 387 | |
| 388 | ***************************************************************************/ |
| 389 | |
| 390 | static void dmac_install(offs_t base) |
| 391 | { |
| 392 | memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, base, base + 0xFFFF, 0, 0, amiga_dmac_r); |
| 393 | memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, base, base + 0xFFFF, 0, 0, amiga_dmac_w); |
| 394 | } |
| 395 | |
| 396 | static void dmac_uninstall(offs_t base) |
| 397 | { |
| 398 | memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, base, base + 0xFFFF, 0, 0, MRA16_UNMAP); |
| 399 | memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, base, base + 0xFFFF, 0, 0, MWA16_UNMAP); |
| 400 | } |
| 401 | |
| 402 | static amiga_autoconfig_device dmac_device = |
| 403 | { |
| 404 | 0, /* link into free memory list */ |
| 405 | 0, /* ROM vector offset valid */ |
| 406 | 0, /* multiple devices on card */ |
| 407 | 1, /* number of 64k pages */ |
| 408 | 3, /* product number (DMAC) */ |
| 409 | 0, /* prefer 8MB address space */ |
| 410 | 0, /* can be shut up */ |
| 411 | 0x0202, /* manufacturers number (Commodore) */ |
| 412 | 0, /* serial number */ |
| 413 | 0, /* ROM vector offset */ |
| 414 | NULL, /* interrupt control read */ |
| 415 | NULL, /* interrupt control write */ |
| 416 | dmac_install, /* memory installation */ |
| 417 | dmac_uninstall /* memory uninstallation */ |
| 418 | }; |
| 419 | |
| 420 | /*************************************************************************** |
| 421 | |
| 422 | TPI6525 |
| 423 | |
| 424 | ***************************************************************************/ |
| 425 | |
| 426 | static int tp6525_portc_r( void ) |
| 427 | { |
| 428 | int ret = 0; |
| 429 | |
| 430 | if ( (tpi6525[0].c.ddr & 0x04) == 0 ) /* if pin 2 is set to input */ |
| 431 | { |
| 432 | ret |= matsucd_stch_r() ? 0x00 : 0x04; /* read status change signal */ |
| 433 | } |
| 434 | |
| 435 | if ( (tpi6525[0].c.ddr & 0x08) == 0 ) /* if pin 3 is set to input */ |
| 436 | ret |= matsucd_sten_r() ? 0x08 : 0x00; /* read enable signal */ |
| 437 | |
| 438 | return ret; |
| 439 | } |
| 440 | |
| 441 | static void tp6525_portb_w( int data ) |
| 442 | { |
| 443 | if ( tpi6525[0].b.ddr & 0x01 ) /* if pin 0 is set to output */ |
| 444 | matsucd_cmd_w( data & 1 ); /* write to the /CMD signal */ |
| 445 | |
| 446 | if ( tpi6525[0].b.ddr & 0x02 ) /* if pin 1 is set to output */ |
| 447 | matsucd_enable_w( data & 2 ); /* write to the /ENABLE signal */ |
| 448 | } |
| 449 | |
| 450 | static mame_timer *tp6525_delayed_timer; |
| 451 | |
| 452 | static TIMER_CALLBACK(tp6525_delayed_irq) |
| 453 | { |
| 454 | (void)param; |
| 455 | |
| 456 | if ( (CUSTOM_REG(REG_INTREQ) & INTENA_PORTS) == 0 ) |
| 457 | { |
| 458 | amiga_custom_w(REG_INTREQ, 0x8000 | INTENA_PORTS, 0); |
| 459 | } |
| 460 | else |
| 461 | { |
| 462 | mame_timer_adjust( tp6525_delayed_timer, MAME_TIME_IN_MSEC(1), 0, time_zero ); |
| 463 | } |
| 464 | } |
| 465 | |
| 466 | static void tp6525_irq( int level ) |
| 467 | { |
| 468 | LOG( "TPI6525 Interrupt: level = %d\n", level); |
| 469 | |
| 470 | if ( level ) |
| 471 | { |
| 472 | if ( (CUSTOM_REG(REG_INTREQ) & INTENA_PORTS) == 0 ) |
| 473 | { |
| 474 | amiga_custom_w(REG_INTREQ, 0x8000 | INTENA_PORTS, 0); |
| 475 | } |
| 476 | else |
| 477 | { |
| 478 | /* we *have to* deliver the irq, so if we can't, delay it and try again later */ |
| 479 | mame_timer_adjust( tp6525_delayed_timer, MAME_TIME_IN_MSEC(1), 0, time_zero ); |
| 480 | } |
| 481 | } |
| 482 | } |
| 483 | |
| 484 | static void cdrom_status_enabled( int level ) |
| 485 | { |
| 486 | /* PC3 on the 6525 */ |
| 487 | tpi6525_0_irq3_level( level ); |
| 488 | } |
| 489 | |
| 490 | static void cdrom_status_change( int level ) |
| 491 | { |
| 492 | /* invert */ |
| 493 | level = level ? 0 : 1; |
| 494 | |
| 495 | /* PC2 on the 6525 */ |
| 496 | tpi6525_0_irq2_level( level ); |
| 497 | } |
| 498 | |
| 499 | static void cdrom_subcode_ready( int level ) |
| 500 | { |
| 501 | /* PC1 on the 6525 */ |
| 502 | tpi6525_0_irq1_level( level ); |
| 503 | } |
| 504 | |
| 505 | void amigacd_init( void ) |
| 506 | { |
| 507 | /* initialize the dmac */ |
| 508 | memset( &dmac_data, 0, sizeof( dmac_data ) ); |
| 509 | |
| 510 | dmac_data.dma_timer = mame_timer_alloc(dmac_dma_proc); |
| 511 | tp6525_delayed_timer = mame_timer_alloc(tp6525_delayed_irq); |
| 512 | |
| 513 | /* initialize the 6525 TPI */ |
| 514 | tpi6525_0_reset(); |
| 515 | |
| 516 | tpi6525[0].a.read = NULL; |
| 517 | tpi6525[0].b.read = NULL; |
| 518 | tpi6525[0].c.read = tp6525_portc_r; |
| 519 | |
| 520 | tpi6525[0].a.output = NULL; |
| 521 | tpi6525[0].b.output = tp6525_portb_w; |
| 522 | tpi6525[0].c.output = NULL; |
| 523 | |
| 524 | tpi6525[0].interrupt.output = tp6525_irq; |
| 525 | tpi6525[0].ca.output = NULL; |
| 526 | tpi6525[0].cb.output = NULL; |
| 527 | |
| 528 | /* initialize the cdrom */ |
| 529 | matsucd_init(); |
| 530 | matsucd_set_status_enabled_callback( cdrom_status_enabled ); |
| 531 | matsucd_set_status_changed_callback( cdrom_status_change ); |
| 532 | matsucd_set_subcode_ready_callback( cdrom_subcode_ready ); |
| 533 | |
| 534 | /* set up DMAC with autoconfig */ |
| 535 | amiga_add_autoconfig( &dmac_device ); |
| 536 | } |
src/mess/machine/sst39vfx.c
| r882 | r883 | |
| 1 | | /*
|
| 2 | | |
| 3 | | SST Multi-Purpose Flash (MPF)
|
| 4 | | |
| 5 | | (c) 2001-2007 Tim Schuerewegen
|
| 6 | | |
| 7 | | SST39VF020 - 256 KByte
|
| 8 | | SST39VF400A - 512 Kbyte
|
| 9 | | |
| 10 | | */
|
| 11 | | |
| 12 | | #include "sst39vfx.h"
|
| 13 | | |
| 14 | | #define LOG_LEVEL 1
|
| 15 | | #define _logerror(level,...) if (LOG_LEVEL > level) logerror(__VA_ARGS__)
|
| 16 | | |
| 17 | | typedef struct
|
| 18 | | {
|
| 19 | | UINT8 *data;
|
| 20 | | UINT32 size;
|
| 21 | | UINT8 swap;
|
| 22 | | } SST39VFX;
|
| 23 | | |
| 24 | | static SST39VFX flash;
|
| 25 | | |
| 26 | | void sst39vfx_state_save( void);
|
| 27 | | |
| 28 | | void sst39vfx_init( int type, int cpu_datawidth, int cpu_endianess)
|
| 29 | | {
|
| 30 | | _logerror( 0, "sst39vfx_init (%d)\n", type);
|
| 31 | | memset( &flash, 0, sizeof( flash));
|
| 32 | | switch (type)
|
| 33 | | {
|
| 34 | | case SST39VF020 : flash.size = 256 * 1024; break;
|
| 35 | | case SST39VF400A : flash.size = 512 * 1024; break;
|
| 36 | | }
|
| 37 | | flash.data = (UINT8*)malloc( flash.size);
|
| 38 | | #ifdef LSB_FIRST
|
| 39 | | if (cpu_endianess != CPU_IS_LE) flash.swap = cpu_datawidth / 8; else flash.swap = 0;
|
| 40 | | #else
|
| 41 | | if (cpu_endianess != CPU_IS_BE) flash.swap = cpu_datawidth / 8; else flash.swap = 0;
|
| 42 | | #endif
|
| 43 | | sst39vfx_state_save();
|
| 44 | | }
|
| 45 | | |
| 46 | | void sst39vfx_exit( void)
|
| 47 | | {
|
| 48 | | _logerror( 0, "sst39vfx_exit\n");
|
| 49 | | free( flash.data);
|
| 50 | | }
|
| 51 | | |
| 52 | | void sst39vfx_reset( void)
|
| 53 | | {
|
| 54 | | _logerror( 0, "sst39vfx_reset\n");
|
| 55 | | }
|
| 56 | | |
| 57 | | void sst39vfx_state_save( void)
|
| 58 | | {
|
| 59 | | const char *name = "sst39vfx";
|
| 60 | | state_save_register_item_pointer( name, 0, flash.data, flash.size);
|
| 61 | | state_save_register_item( name, 0, flash.swap);
|
| 62 | | }
|
| 63 | | |
| 64 | | UINT8* sst39vfx_get_base( void)
|
| 65 | | {
|
| 66 | | return flash.data;
|
| 67 | | }
|
| 68 | | |
| 69 | | UINT32 sst39vfx_get_size( void)
|
| 70 | | {
|
| 71 | | return flash.size;
|
| 72 | | }
|
| 73 | | |
| 74 | | /*
|
| 75 | | #define OFFSET_SWAP(offset,width) (offset & (~(width - 1))) | (width - 1 - (offset & (width - 1)))
|
| 76 | | */
|
| 77 | | |
| 78 | | /*
|
| 79 | | READ8_HANDLER( sst39vfx_r )
|
| 80 | | {
|
| 81 | | _logerror( 1, "sst39vfx_r (%08X)\n", offset);
|
| 82 | | if (flash.swap) offset = OFFSET_SWAP( offset, flash.swap);
|
| 83 | | return flash.data[offset];
|
| 84 | | }
|
| 85 | | */
|
| 86 | | |
| 87 | | /*
|
| 88 | | WRITE8_HANDLER( sst39vfx_w )
|
| 89 | | {
|
| 90 | | _logerror( 1, "sst39vfx_w (%08X/%02X)\n", offset, data);
|
| 91 | | if (flash.swap) offset = OFFSET_SWAP( offset, flash.swap);
|
| 92 | | flash.data[offset] = data;
|
| 93 | | }
|
| 94 | | */
|
| 95 | | |
| 96 | | void sst39vfx_swap( void)
|
| 97 | | {
|
| 98 | | int i, j;
|
| 99 | | UINT8 *base, temp[8];
|
| 100 | | base = flash.data;
|
| 101 | | for (i=0;i<flash.size;i+=flash.swap)
|
| 102 | | {
|
| 103 | | memcpy( temp, base, flash.swap);
|
| 104 | | for (j=flash.swap-1;j>=0;j--) *base++ = temp[j];
|
| 105 | | }
|
| 106 | | }
|
| 107 | | |
| 108 | | void sst39vfx_load( mame_file *file)
|
| 109 | | {
|
| 110 | | _logerror( 0, "sst39vfx_load (%p)\n", file);
|
| 111 | | mame_fread( file, flash.data, flash.size);
|
| 112 | | if (flash.swap) sst39vfx_swap();
|
| 113 | | }
|
| 114 | | |
| 115 | | void sst39vfx_save( mame_file *file)
|
| 116 | | {
|
| 117 | | _logerror( 0, "sst39vfx_save (%p)\n", file);
|
| 118 | | if (flash.swap) sst39vfx_swap();
|
| 119 | | mame_fwrite( file, flash.data, flash.size);
|
| 120 | | if (flash.swap) sst39vfx_swap();
|
| 121 | | }
|
| 122 | | |
| 123 | | /*
|
| 124 | | NVRAM_HANDLER( sst39vfx )
|
| 125 | | {
|
| 126 | | _logerror( 0, "nvram_handler_sst39vfx (%p/%d)\n", file, read_or_write);
|
| 127 | | if (read_or_write)
|
| 128 | | {
|
| 129 | | sst39vfx_save( file);
|
| 130 | | }
|
| 131 | | else
|
| 132 | | {
|
| 133 | | if (file)
|
| 134 | | {
|
| 135 | | sst39vfx_load( file);
|
| 136 | | }
|
| 137 | | else
|
| 138 | | {
|
| 139 | | memset( flash.data, 0xFF, flash.size);
|
| 140 | | }
|
| 141 | | }
|
| 142 | | }
|
| 143 | | */
|
| 1 | /* |
| 2 | |
| 3 | SST Multi-Purpose Flash (MPF) |
| 4 | |
| 5 | (c) 2001-2007 Tim Schuerewegen |
| 6 | |
| 7 | SST39VF020 - 256 KByte |
| 8 | SST39VF400A - 512 Kbyte |
| 9 | |
| 10 | */ |
| 11 | |
| 12 | #include "sst39vfx.h" |
| 13 | |
| 14 | #define LOG_LEVEL 1 |
| 15 | #define _logerror(level,...) if (LOG_LEVEL > level) logerror(__VA_ARGS__) |
| 16 | |
| 17 | typedef struct |
| 18 | { |
| 19 | UINT8 *data; |
| 20 | UINT32 size; |
| 21 | UINT8 swap; |
| 22 | } SST39VFX; |
| 23 | |
| 24 | static SST39VFX flash; |
| 25 | |
| 26 | void sst39vfx_state_save( void); |
| 27 | |
| 28 | void sst39vfx_init( int type, int cpu_datawidth, int cpu_endianess) |
| 29 | { |
| 30 | _logerror( 0, "sst39vfx_init (%d)\n", type); |
| 31 | memset( &flash, 0, sizeof( flash)); |
| 32 | switch (type) |
| 33 | { |
| 34 | case SST39VF020 : flash.size = 256 * 1024; break; |
| 35 | case SST39VF400A : flash.size = 512 * 1024; break; |
| 36 | } |
| 37 | flash.data = (UINT8*)malloc( flash.size); |
| 38 | #ifdef LSB_FIRST |
| 39 | if (cpu_endianess != CPU_IS_LE) flash.swap = cpu_datawidth / 8; else flash.swap = 0; |
| 40 | #else |
| 41 | if (cpu_endianess != CPU_IS_BE) flash.swap = cpu_datawidth / 8; else flash.swap = 0; |
| 42 | #endif |
| 43 | sst39vfx_state_save(); |
| 44 | } |
| 45 | |
| 46 | void sst39vfx_exit( void) |
| 47 | { |
| 48 | _logerror( 0, "sst39vfx_exit\n"); |
| 49 | free( flash.data); |
| 50 | } |
| 51 | |
| 52 | void sst39vfx_reset( void) |
| 53 | { |
| 54 | _logerror( 0, "sst39vfx_reset\n"); |
| 55 | } |
| 56 | |
| 57 | void sst39vfx_state_save( void) |
| 58 | { |
| 59 | const char *name = "sst39vfx"; |
| 60 | state_save_register_item_pointer( name, 0, flash.data, flash.size); |
| 61 | state_save_register_item( name, 0, flash.swap); |
| 62 | } |
| 63 | |
| 64 | UINT8* sst39vfx_get_base( void) |
| 65 | { |
| 66 | return flash.data; |
| 67 | } |
| 68 | |
| 69 | UINT32 sst39vfx_get_size( void) |
| 70 | { |
| 71 | return flash.size; |
| 72 | } |
| 73 | |
| 74 | /* |
| 75 | #define OFFSET_SWAP(offset,width) (offset & (~(width - 1))) | (width - 1 - (offset & (width - 1))) |
| 76 | */ |
| 77 | |
| 78 | /* |
| 79 | READ8_HANDLER( sst39vfx_r ) |
| 80 | { |
| 81 | _logerror( 1, "sst39vfx_r (%08X)\n", offset); |
| 82 | if (flash.swap) offset = OFFSET_SWAP( offset, flash.swap); |
| 83 | return flash.data[offset]; |
| 84 | } |
| 85 | */ |
| 86 | |
| 87 | /* |
| 88 | WRITE8_HANDLER( sst39vfx_w ) |
| 89 | { |
| 90 | _logerror( 1, "sst39vfx_w (%08X/%02X)\n", offset, data); |
| 91 | if (flash.swap) offset = OFFSET_SWAP( offset, flash.swap); |
| 92 | flash.data[offset] = data; |
| 93 | } |
| 94 | */ |
| 95 | |
| 96 | void sst39vfx_swap( void) |
| 97 | { |
| 98 | int i, j; |
| 99 | UINT8 *base, temp[8]; |
| 100 | base = flash.data; |
| 101 | for (i=0;i<flash.size;i+=flash.swap) |
| 102 | { |
| 103 | memcpy( temp, base, flash.swap); |
| 104 | for (j=flash.swap-1;j>=0;j--) *base++ = temp[j]; |
| 105 | } |
| 106 | } |
| 107 | |
| 108 | void sst39vfx_load( mame_file *file) |
| 109 | { |
| 110 | _logerror( 0, "sst39vfx_load (%p)\n", file); |
| 111 | mame_fread( file, flash.data, flash.size); |
| 112 | if (flash.swap) sst39vfx_swap(); |
| 113 | } |
| 114 | |
| 115 | void sst39vfx_save( mame_file *file) |
| 116 | { |
| 117 | _logerror( 0, "sst39vfx_save (%p)\n", file); |
| 118 | if (flash.swap) sst39vfx_swap(); |
| 119 | mame_fwrite( file, flash.data, flash.size); |
| 120 | if (flash.swap) sst39vfx_swap(); |
| 121 | } |
| 122 | |
| 123 | /* |
| 124 | NVRAM_HANDLER( sst39vfx ) |
| 125 | { |
| 126 | _logerror( 0, "nvram_handler_sst39vfx (%p/%d)\n", file, read_or_write); |
| 127 | if (read_or_write) |
| 128 | { |
| 129 | sst39vfx_save( file); |
| 130 | } |
| 131 | else |
| 132 | { |
| 133 | if (file) |
| 134 | { |
| 135 | sst39vfx_load( file); |
| 136 | } |
| 137 | else |
| 138 | { |
| 139 | memset( flash.data, 0xFF, flash.size); |
| 140 | } |
| 141 | } |
| 142 | } |
| 143 | */ |
src/mess/machine/matsucd.c
| r882 | r883 | |
| 1 | | /***************************************************************************
|
| 2 | | |
| 3 | | Matsushita/Panasonic CDR521/522 type CDROM drive emulation
|
| 4 | |
|
| 5 | | Notes:
|
| 6 | | This version implements the drive found in Amiga CDTV. There are
|
| 7 | | different drives supporting this command-set (look in the sbpcd driver
|
| 8 | | in Linux for examples). Most drives support the exact same command
|
| 9 | | structure, but the command numbers differ. Eventually this driver
|
| 10 | | can be expanded with support for the other drives as needed.
|
| 11 | | |
| 12 | | ***************************************************************************/
|
| 13 | | |
| 14 | | #include "mame.h"
|
| 15 | | #include "driver.h"
|
| 16 | | #include "devices/chd_cd.h"
|
| 17 | | #include "sound/cdda.h"
|
| 18 | | |
| 19 | | |
| 20 | | #define MATSU_STATUS_READY ( 1 << 0 ) /* driver ready */
|
| 21 | | #define MATSU_STATUS_DOORLOCKED ( 1 << 1 ) /* door locked */
|
| 22 | | #define MATSU_STATUS_PLAYING ( 1 << 2 ) /* drive playing */
|
| 23 | | #define MATSU_STATUS_SUCCESS ( 1 << 3 ) /* last command was succesful */
|
| 24 | | #define MATSU_STATUS_ERROR ( 1 << 4 ) /* last command failed */
|
| 25 | | #define MATSU_STATUS_MOTOR ( 1 << 5 ) /* spinning */
|
| 26 | | #define MATSU_STATUS_MEDIA ( 1 << 6 ) /* media present (in caddy or tray) */
|
| 27 | | #define MATSU_STATUS_DOORCLOSED ( 1 << 7 ) /* tray status */
|
| 28 | | |
| 29 | | typedef struct
|
| 30 | | {
|
| 31 | | UINT8 enabled; /* /ENABLE - Unit enabled */
|
| 32 | | UINT8 cmd_signal; /* /CMD - Command mode */
|
| 33 | | UINT8 stch_signal; /* /STCH - Status Changed */
|
| 34 | | UINT8 sten_signal; /* /STEN - Status Enabled */
|
| 35 | | UINT8 scor_signal; /* /STEN - Subcode Ready */
|
| 36 | | UINT8 input[16];
|
| 37 | | UINT8 input_pos;
|
| 38 | | UINT8 output[16];
|
| 39 | | UINT8 output_pos;
|
| 40 | | UINT8 output_len;
|
| 41 | | UINT8 status;
|
| 42 | | UINT8 motor;
|
| 43 | | UINT16 sector_size;
|
| 44 | | UINT32 lba;
|
| 45 | | UINT16 num_blocks;
|
| 46 | | UINT16 xfer_offset;
|
| 47 | | UINT8 sector_buffer[CD_MAX_SECTOR_DATA];
|
| 48 | | UINT8 cdda_set;
|
| 49 | | void (*sten_cb)( int level ); /* Status enabled callback */
|
| 50 | | void (*stch_cb)( int level ); /* Status changed callback */
|
| 51 | | void (*scor_cb)( int level ); /* Subcode ready callback */
|
| 52 | | cdrom_file *cdrom;
|
| 53 | | mame_timer *frame_timer;
|
| 54 | | } matsucd;
|
| 55 | | |
| 56 | | static matsucd cd;
|
| 57 | | |
| 58 | | #define MSF2LBA(msf) (((msf >> 16) & 0xff) * 60 * 75 + ((msf >> 8) & 0xff) * 75 + ((msf >> 0) & 0xff))
|
| 59 | | #define LBA2MSF(lba) (((lba / (75 * 60)) << 16) | (((lba / 75) % 60) << 8) | (lba % 75))
|
| 60 | | |
| 61 | | static TIMER_CALLBACK(matsu_subcode_proc);
|
| 62 | | |
| 63 | | void matsucd_init( void )
|
| 64 | | {
|
| 65 | | memset(&cd, 0, sizeof( matsucd ) );
|
| 66 | |
|
| 67 | | cd.cdrom = mess_cd_get_cdrom_file_by_number(0);
|
| 68 | |
|
| 69 | | cd.frame_timer = mame_timer_alloc(matsu_subcode_proc);
|
| 70 | |
|
| 71 | | cd.stch_signal = 1;
|
| 72 | | }
|
| 73 | | |
| 74 | | void matsucd_set_status_enabled_callback( void (*sten_cb)( int level ) )
|
| 75 | | {
|
| 76 | | /* add the callback for status enabled signal */
|
| 77 | | cd.sten_cb = sten_cb;
|
| 78 | | }
|
| 79 | | |
| 80 | | void matsucd_set_status_changed_callback( void (*stch_cb)( int level ) )
|
| 81 | | {
|
| 82 | | /* add the callback for status changed signal */
|
| 83 | | cd.stch_cb = stch_cb;
|
| 84 | | }
|
| 85 | | |
| 86 | | void matsucd_set_subcode_ready_callback( void (*scor_cb)( int level ) )
|
| 87 | | {
|
| 88 | | /* add the callback for subcode ready signal */
|
| 89 | | cd.scor_cb = scor_cb;
|
| 90 | | }
|
| 91 | | |
| 92 | | static int matsucd_getsector_type( void )
|
| 93 | | {
|
| 94 | | switch( cd.sector_size )
|
| 95 | | {
|
| 96 | | case 2048: return CD_TRACK_MODE1; break;
|
| 97 | | case 2324: return CD_TRACK_MODE2_FORM2; break;
|
| 98 | | case 2336: return CD_TRACK_MODE2; break;
|
| 99 | | case 2352: return CD_TRACK_MODE2_RAW; break;
|
| 100 | | |
| 101 | | default: logerror( "MATSUCD: Sector size %d unsupported!\n", cd.sector_size ); break;
|
| 102 | | }
|
| 103 | |
|
| 104 | | return CD_TRACK_RAW_DONTCARE;
|
| 105 | | }
|
| 106 | | |
| 107 | | void matsucd_read_next_block( void )
|
| 108 | | {
|
| 109 | | cd.xfer_offset = 0;
|
| 110 | |
|
| 111 | | if ( cd.num_blocks )
|
| 112 | | {
|
| 113 | | cd.lba++;
|
| 114 | | cd.num_blocks--;
|
| 115 | | |
| 116 | | if (!cdrom_read_data(cd.cdrom, cd.lba, cd.sector_buffer, matsucd_getsector_type()))
|
| 117 | | {
|
| 118 | | logerror( "MATSUCD - Warning: Read error on CD!\n" );
|
| 119 | | }
|
| 120 | | }
|
| 121 | | }
|
| 122 | | |
| 123 | | int matsucd_get_next_byte( UINT8 *data )
|
| 124 | | {
|
| 125 | | /* no more data to read on this sector */
|
| 126 | | if ( cd.xfer_offset >= cd.sector_size )
|
| 127 | | return -1;
|
| 128 | |
|
| 129 | | if ( data )
|
| 130 | | *data = cd.sector_buffer[cd.xfer_offset++];
|
| 131 | |
|
| 132 | | return 0;
|
| 133 | | }
|
| 134 | | |
| 135 | | static void matsucd_cdda_stop( void )
|
| 136 | | {
|
| 137 | | int cddanum = cdda_num_from_cdrom(cd.cdrom);
|
| 138 | |
|
| 139 | | if (cddanum != -1)
|
| 140 | | {
|
| 141 | | cdda_stop_audio(cddanum);
|
| 142 | | mame_timer_reset( cd.frame_timer, time_never );
|
| 143 | | }
|
| 144 | | }
|
| 145 | | |
| 146 | | static void matsucd_cdda_play( UINT32 lba, UINT32 num_blocks )
|
| 147 | | {
|
| 148 | | int cddanum = cdda_num_from_cdrom(cd.cdrom);
|
| 149 | | if (cddanum != -1)
|
| 150 | | {
|
| 151 | | cdda_start_audio(cddanum, lba, num_blocks);
|
| 152 | | mame_timer_adjust( cd.frame_timer, MAME_TIME_IN_HZ( 75 ), 0, time_zero );
|
| 153 | | }
|
| 154 | | }
|
| 155 | | |
| 156 | | static void matsucd_cdda_pause( int pause )
|
| 157 | | {
|
| 158 | | int cddanum = cdda_num_from_cdrom(cd.cdrom);
|
| 159 | | if (cddanum != -1)
|
| 160 | | {
|
| 161 | | cdda_pause_audio(cddanum, pause);
|
| 162 | | |
| 163 | | if ( pause )
|
| 164 | | {
|
| 165 | | mame_timer_reset( cd.frame_timer, time_never );
|
| 166 | | }
|
| 167 | | else
|
| 168 | | {
|
| 169 | | mame_timer_adjust( cd.frame_timer, MAME_TIME_IN_HZ( 75 ), 0, time_zero );
|
| 170 | | }
|
| 171 | | }
|
| 172 | | }
|
| 173 | | |
| 174 | | static UINT8 matsucd_cdda_getstatus( UINT32 *lba )
|
| 175 | | {
|
| 176 | | int cddanum = cdda_num_from_cdrom(cd.cdrom);
|
| 177 | |
|
| 178 | | if ( lba ) *lba = 0;
|
| 179 | |
|
| 180 | | if (cddanum != -1)
|
| 181 | | {
|
| 182 | | if (cdda_audio_active(cddanum))
|
| 183 | | {
|
| 184 | | if ( lba ) *lba = cdda_get_audio_lba(cddanum);
|
| 185 | | |
| 186 | | if (cdda_audio_paused(cddanum))
|
| 187 | | {
|
| 188 | | return 0x12; /* audio paused */
|
| 189 | | }
|
| 190 | | else
|
| 191 | | {
|
| 192 | | return 0x11; /* audio in progress */
|
| 193 | | }
|
| 194 | | }
|
| 195 | | else if (cdda_audio_ended(cddanum))
|
| 196 | | {
|
| 197 | | return 0x13; /* audio ended */
|
| 198 | | }
|
| 199 | | }
|
| 200 | |
|
| 201 | | return 0x15; /* no audio status */
|
| 202 | | }
|
| 203 | | |
| 204 | | void matsucd_enable_w( int level )
|
| 205 | | {
|
| 206 | | cd.enabled = ( level ) ? 0 : 1;
|
| 207 | | }
|
| 208 | | |
| 209 | | void matsucd_cmd_w( int level )
|
| 210 | | {
|
| 211 | | cd.cmd_signal = ( level ) ? 0 : 1;
|
| 212 | | }
|
| 213 | | |
| 214 | | int matsucd_stch_r( void )
|
| 215 | | {
|
| 216 | | return cd.stch_signal ? 0 : 1;
|
| 217 | | }
|
| 218 | | |
| 219 | | int matsucd_sten_r( void )
|
| 220 | | {
|
| 221 | | return cd.sten_signal ? 0 : 1;
|
| 222 | | }
|
| 223 | | |
| 224 | | int matsucd_scor_r( void )
|
| 225 | | {
|
| 226 | | return cd.scor_signal ? 0 : 1;
|
| 227 | | }
|
| 228 | | |
| 229 | | static void update_status_enable( int level )
|
| 230 | | {
|
| 231 | | cd.sten_signal = level;
|
| 232 | |
|
| 233 | | if ( cd.sten_cb )
|
| 234 | | {
|
| 235 | | (*cd.sten_cb)(cd.sten_signal);
|
| 236 | | }
|
| 237 | | }
|
| 238 | | |
| 239 | | static void update_status_changed( int level )
|
| 240 | | {
|
| 241 | | cd.stch_signal = level;
|
| 242 | |
|
| 243 | | if ( cd.stch_cb )
|
| 244 | | {
|
| 245 | | (*cd.stch_cb)(cd.stch_signal);
|
| 246 | | }
|
| 247 | | }
|
| 248 | | |
| 249 | | static void update_subcode_ready( int level )
|
| 250 | | {
|
| 251 | | cd.scor_signal = level;
|
| 252 | |
|
| 253 | | if ( cd.scor_cb )
|
| 254 | | {
|
| 255 | | (*cd.scor_cb)(cd.scor_signal);
|
| 256 | | }
|
| 257 | | }
|
| 258 | | |
| 259 | | static TIMER_CALLBACK(matsucd_set_status_end)
|
| 260 | | {
|
| 261 | | update_status_changed( 1 );
|
| 262 | | }
|
| 263 | | |
| 264 | | static void matsucd_set_status( UINT8 status )
|
| 265 | | {
|
| 266 | | if ( status != cd.status )
|
| 267 | | {
|
| 268 | | cd.status = status;
|
| 269 | | |
| 270 | | if ( cd.stch_signal != 0 )
|
| 271 | | {
|
| 272 | | update_status_changed( 0 );
|
| 273 | | mame_timer_set( MAME_TIME_IN_MSEC(1), 0, matsucd_set_status_end );
|
| 274 | | }
|
| 275 | | }
|
| 276 | | }
|
| 277 | | |
| 278 | | static TIMER_CALLBACK(matsu_subcode_proc)
|
| 279 | | {
|
| 280 | | int cddanum = cdda_num_from_cdrom(cd.cdrom);
|
| 281 | |
|
| 282 | | (void)param;
|
| 283 | |
|
| 284 | | if (cddanum != -1)
|
| 285 | | {
|
| 286 | | UINT8 s = matsucd_cdda_getstatus(NULL);
|
| 287 | | UINT8 newstatus = cd.status;
|
| 288 | | |
| 289 | | if ( s == 0x11 || s == 0x12 )
|
| 290 | | {
|
| 291 | | if ( s == 0x11 )
|
| 292 | | {
|
| 293 | | update_subcode_ready( 1 );
|
| 294 | | update_subcode_ready( 0 );
|
| 295 | | }
|
| 296 | |
|
| 297 | | newstatus |= MATSU_STATUS_PLAYING;
|
| 298 | |
|
| 299 | | mame_timer_adjust( cd.frame_timer, MAME_TIME_IN_HZ( 75 ), 0, time_zero );
|
| 300 | | }
|
| 301 | | else
|
| 302 | | {
|
| 303 | | newstatus &= ~MATSU_STATUS_PLAYING;
|
| 304 | | }
|
| 305 | | |
| 306 | | matsucd_set_status( newstatus );
|
| 307 | | }
|
| 308 | | }
|
| 309 | | |
| 310 | | static void matsucd_command_error( void )
|
| 311 | | {
|
| 312 | | UINT8 newstatus = cd.status;
|
| 313 | | |
| 314 | | newstatus &= ~MATSU_STATUS_SUCCESS;
|
| 315 | | newstatus |= MATSU_STATUS_ERROR;
|
| 316 | |
|
| 317 | | matsucd_set_status( newstatus );
|
| 318 | | }
|
| 319 | | |
| 320 | | static void matsucd_complete_cmd( UINT8 len )
|
| 321 | | {
|
| 322 | | UINT8 newstatus = cd.status;
|
| 323 | |
|
| 324 | | cd.input_pos = 0;
|
| 325 | | cd.output_pos = 0;
|
| 326 | | cd.output_len = len;
|
| 327 | |
|
| 328 | | newstatus &= ~MATSU_STATUS_ERROR;
|
| 329 | | newstatus |= MATSU_STATUS_SUCCESS;
|
| 330 | |
|
| 331 | | matsucd_set_status( newstatus );
|
| 332 | |
|
| 333 | | update_status_enable( 1 );
|
| 334 | | update_status_enable( 0 );
|
| 335 | | }
|
| 336 | | |
| 337 | | UINT8 matsucd_response_r( void )
|
| 338 | | {
|
| 339 | | UINT8 v = cd.output[cd.output_pos++];
|
| 340 | |
|
| 341 | | if ( cd.output_pos < cd.output_len )
|
| 342 | | {
|
| 343 | | update_status_enable( 1 );
|
| 344 | | update_status_enable( 0 );
|
| 345 | | }
|
| 346 | |
|
| 347 | | return v;
|
| 348 | | }
|
| 349 | | |
| 350 | | void matsucd_command_w( UINT8 data )
|
| 351 | | {
|
| 352 | | UINT8 cmd;
|
| 353 | |
|
| 354 | | /* make sure we're enabled */
|
| 355 | | if ( cd.enabled == 0 )
|
| 356 | | return;
|
| 357 | |
|
| 358 | | /* make sure /CMD is asserted */
|
| 359 | | if ( cd.cmd_signal == 0 )
|
| 360 | | return;
|
| 361 | |
|
| 362 | | if ( cd.cdda_set == 0 )
|
| 363 | | {
|
| 364 | | if ( cd.cdrom )
|
| 365 | | cdda_set_cdrom(0, cd.cdrom);
|
| 366 | | |
| 367 | | cd.cdda_set = 1;
|
| 368 | | }
|
| 369 | |
|
| 370 | | cd.input[cd.input_pos++] = data;
|
| 371 | | |
| 372 | | cmd = cd.input[0];
|
| 373 | |
|
| 374 | | switch( cmd )
|
| 375 | | {
|
| 376 | | case 0x01: /* seek */
|
| 377 | | {
|
| 378 | | if ( cd.input_pos < 7 )
|
| 379 | | return;
|
| 380 | | |
| 381 | | /* stop CDDA audio if necessary */
|
| 382 | | matsucd_cdda_stop();
|
| 383 | |
|
| 384 | | cd.motor = 1;
|
| 385 | | |
| 386 | | memset( cd.output, 0, 6 );
|
| 387 | | matsucd_complete_cmd( 0 );
|
| 388 | | }
|
| 389 | | break;
|
| 390 | | |
| 391 | | case 0x02: /* read sectors */
|
| 392 | | {
|
| 393 | | if ( cd.input_pos < 7 )
|
| 394 | | return;
|
| 395 | |
|
| 396 | | /* stop CDDA audio if necessary */
|
| 397 | | matsucd_cdda_stop();
|
| 398 | | |
| 399 | | /* LBA */
|
| 400 | | cd.lba = cd.input[1];
|
| 401 | | cd.lba <<= 8;
|
| 402 | | cd.lba |= cd.input[2];
|
| 403 | | cd.lba <<= 8;
|
| 404 | | cd.lba |= cd.input[3];
|
| 405 | |
|
| 406 | | /* Number of blocks */
|
| 407 | | cd.num_blocks = cd.input[4];
|
| 408 | | cd.num_blocks <<= 8;
|
| 409 | | cd.num_blocks |= cd.input[5];
|
| 410 | |
|
| 411 | | /* Reset transfer count */
|
| 412 | | cd.xfer_offset = 0;
|
| 413 | |
|
| 414 | | /* go ahead and cache the first block */
|
| 415 | | if (!cdrom_read_data(cd.cdrom, cd.lba, cd.sector_buffer, matsucd_getsector_type()))
|
| 416 | | {
|
| 417 | | logerror( "MATSUCD - Warning: Read error on CD!\n" );
|
| 418 | | matsucd_command_error();
|
| 419 | | return;
|
| 420 | | }
|
| 421 | |
|
| 422 | | cd.motor = 1;
|
| 423 | | |
| 424 | | memset( cd.output, 0, 6 );
|
| 425 | | matsucd_complete_cmd( 0 );
|
| 426 | | }
|
| 427 | | break;
|
| 428 | | |
| 429 | | case 0x04: /* motor on */
|
| 430 | | {
|
| 431 | | if ( cd.input_pos < 7 )
|
| 432 | | return;
|
| 433 | | |
| 434 | | cd.motor = 1;
|
| 435 | | |
| 436 | | memset( cd.output, 0, 6 );
|
| 437 | | matsucd_complete_cmd( 0 );
|
| 438 | | }
|
| 439 | | break;
|
| 440 | | |
| 441 | | case 0x05: /* motor off */
|
| 442 | | {
|
| 443 | | if ( cd.input_pos < 7 )
|
| 444 | | return;
|
| 445 | | |
| 446 | | /* stop CDDA audio if necessary */
|
| 447 | | matsucd_cdda_stop();
|
| 448 | |
|
| 449 | | cd.motor = 0;
|
| 450 | | |
| 451 | | memset( cd.output, 0, 6 );
|
| 452 | | matsucd_complete_cmd( 0 );
|
| 453 | | }
|
| 454 | | break;
|
| 455 | | |
| 456 | | case 0x09: /* play audio cd, LBA mode */
|
| 457 | | {
|
| 458 | | UINT32 lba, numblocks;
|
| 459 | |
|
| 460 | | if ( cd.input_pos < 7 )
|
| 461 | | return;
|
| 462 | |
|
| 463 | | lba = cd.input[1];
|
| 464 | | lba <<= 8;
|
| 465 | | lba |= cd.input[2];
|
| 466 | | lba <<= 8;
|
| 467 | | lba |= cd.input[3];
|
| 468 | |
|
| 469 | | numblocks = cd.input[4];
|
| 470 | | numblocks <<= 8;
|
| 471 | | numblocks |= cd.input[5];
|
| 472 | | numblocks <<= 8;
|
| 473 | | numblocks |= cd.input[6];
|
| 474 | |
|
| 475 | | matsucd_cdda_play( lba, numblocks );
|
| 476 | |
|
| 477 | | cd.motor = 1;
|
| 478 | | |
| 479 | | memset( cd.output, 0, 6 );
|
| 480 | | matsucd_complete_cmd( 0 );
|
| 481 | | }
|
| 482 | | break;
|
| 483 | | |
| 484 | | case 0x0a: /* play audio cd, MSF mode */
|
| 485 | | {
|
| 486 | | UINT32 start, end, lba_start, lba_end;
|
| 487 | |
|
| 488 | | if ( cd.input_pos < 7 )
|
| 489 | | return;
|
| 490 | |
|
| 491 | | start = cd.input[1];
|
| 492 | | start <<= 8;
|
| 493 | | start |= cd.input[2];
|
| 494 | | start <<= 8;
|
| 495 | | start |= cd.input[3];
|
| 496 | |
|
| 497 | | end = cd.input[4];
|
| 498 | | end <<= 8;
|
| 499 | | end |= cd.input[5];
|
| 500 | | end <<= 8;
|
| 501 | | end |= cd.input[6];
|
| 502 | |
|
| 503 | | lba_start = MSF2LBA( start );
|
| 504 | | lba_end = MSF2LBA( end );
|
| 505 | |
|
| 506 | | if ( end == 0xffffff )
|
| 507 | | {
|
| 508 | | lba_end = cdrom_get_track_start(cd.cdrom,cdrom_get_last_track(cd.cdrom)-1);
|
| 509 | | lba_end += cdrom_get_toc(cd.cdrom)->tracks[cdrom_get_last_track(cd.cdrom)-1].frames;
|
| 510 | | }
|
| 511 | |
|
| 512 | | if ( lba_end <= lba_start )
|
| 513 | | {
|
| 514 | | matsucd_cdda_stop();
|
| 515 | | }
|
| 516 | | else
|
| 517 | | {
|
| 518 | | matsucd_cdda_play( lba_start, lba_end - lba_start );
|
| 519 | | cd.motor = 1;
|
| 520 | | }
|
| 521 | |
|
| 522 | | memset( cd.output, 0, 6 );
|
| 523 | | matsucd_complete_cmd( 0 );
|
| 524 | | }
|
| 525 | | break;
|
| 526 | | |
| 527 | | case 0x0b: /* play audio track and index */
|
| 528 | | {
|
| 529 | | UINT8 track_start = cd.input[1];
|
| 530 | | UINT8 index_start = cd.input[2];
|
| 531 | | UINT8 track_end = cd.input[3];
|
| 532 | | UINT8 index_end = cd.input[4];
|
| 533 | | UINT32 lba_start, lba_end;
|
| 534 | |
|
| 535 | | /* TODO: Add index support once the CDDA engine supports it */
|
| 536 | | (void)index_start;
|
| 537 | | (void)index_end;
|
| 538 | |
|
| 539 | | /* sanitize values */
|
| 540 | | if ( track_start == 0 ) track_start++;
|
| 541 | | if ( track_end > cdrom_get_last_track(cd.cdrom) )
|
| 542 | | track_end = cdrom_get_last_track(cd.cdrom);
|
| 543 | | |
| 544 | | /* find the start and stop positions */
|
| 545 | | lba_start = cdrom_get_track_start(cd.cdrom,track_start-1);
|
| 546 | | lba_end = cdrom_get_track_start(cd.cdrom,track_end-1);
|
| 547 | |
|
| 548 | | lba_end += cdrom_get_toc(cd.cdrom)->tracks[track_end-1].frames;
|
| 549 | |
|
| 550 | | if ( lba_end <= lba_start )
|
| 551 | | {
|
| 552 | | matsucd_cdda_stop();
|
| 553 | | }
|
| 554 | | else
|
| 555 | | {
|
| 556 | | matsucd_cdda_play( lba_start, lba_end - lba_start );
|
| 557 | | cd.motor = 1;
|
| 558 | | }
|
| 559 | |
|
| 560 | | memset( cd.output, 0, 6 );
|
| 561 | | matsucd_complete_cmd( 0 );
|
| 562 | | }
|
| 563 | | break;
|
| 564 | | |
| 565 | | case 0x81: /* status read */
|
| 566 | | {
|
| 567 | | UINT8 newstatus = cd.status;
|
| 568 | |
|
| 569 | | newstatus &= MATSU_STATUS_SUCCESS | MATSU_STATUS_ERROR | MATSU_STATUS_PLAYING;
|
| 570 | | newstatus |= MATSU_STATUS_READY;
|
| 571 | |
|
| 572 | | if (cd.cdrom)
|
| 573 | | {
|
| 574 | | newstatus |= MATSU_STATUS_MEDIA;
|
| 575 | | }
|
| 576 | |
|
| 577 | | if (cd.motor)
|
| 578 | | newstatus |= MATSU_STATUS_MOTOR;
|
| 579 | |
|
| 580 | | cd.output[0] = newstatus;
|
| 581 | |
|
| 582 | | matsucd_set_status( newstatus );
|
| 583 | |
|
| 584 | | matsucd_complete_cmd( 1 );
|
| 585 | | }
|
| 586 | | break;
|
| 587 | | |
| 588 | | case 0x82: /* error read */
|
| 589 | | {
|
| 590 | | if ( cd.input_pos < 7 )
|
| 591 | | return;
|
| 592 | |
|
| 593 | | memset( cd.output, 0, 6 );
|
| 594 | | matsucd_complete_cmd( 6 );
|
| 595 | | }
|
| 596 | | break;
|
| 597 | | |
| 598 | | case 0x84: /* set mode */
|
| 599 | | {
|
| 600 | | if ( cd.input_pos < 7 )
|
| 601 | | return;
|
| 602 | | |
| 603 | | cd.sector_size = cd.input[2];
|
| 604 | | cd.sector_size <<= 8;
|
| 605 | | cd.sector_size |= cd.input[3];
|
| 606 | |
|
| 607 | | memset( cd.output, 0, 6 );
|
| 608 | | matsucd_complete_cmd( 0 );
|
| 609 | | }
|
| 610 | | break;
|
| 611 | | |
| 612 | | case 0x87: /* read SUBQ */
|
| 613 | | {
|
| 614 | | int msfmode;
|
| 615 | | UINT32 lba;
|
| 616 | | UINT8 track;
|
| 617 | | |
| 618 | | if ( cd.input_pos < 7 )
|
| 619 | | return;
|
| 620 | |
|
| 621 | | msfmode = (cd.input[1] & 0x02) ? 1 : 0;
|
| 622 | | |
| 623 | | memset( cd.output, 0, 13 );
|
| 624 | |
|
| 625 | | cd.output[0] = matsucd_cdda_getstatus( &lba );
|
| 626 | |
|
| 627 | | if ( lba > 0 )
|
| 628 | | {
|
| 629 | | UINT32 disk_pos;
|
| 630 | | UINT32 track_pos;
|
| 631 | | |
| 632 | | track = cdrom_get_track(cd.cdrom, lba);
|
| 633 | | |
| 634 | | cd.output[1] = cdrom_get_adr_control(cd.cdrom, track);
|
| 635 | | cd.output[2] = track+1;
|
| 636 | | cd.output[3] = 0; /* index */
|
| 637 | |
|
| 638 | | disk_pos = lba;
|
| 639 | | if ( msfmode ) disk_pos = LBA2MSF(disk_pos);
|
| 640 | |
|
| 641 | | cd.output[4] = (disk_pos >> 24) & 0xff;
|
| 642 | | cd.output[5] = (disk_pos >> 16) & 0xff;
|
| 643 | | cd.output[6] = (disk_pos >> 8) & 0xff;
|
| 644 | | cd.output[7] = (disk_pos) & 0xff;
|
| 645 | |
|
| 646 | | track_pos = lba - cdrom_get_track_start(cd.cdrom, track);
|
| 647 | | if ( msfmode ) track_pos = LBA2MSF(track_pos);
|
| 648 | |
|
| 649 | | cd.output[8] = (track_pos >> 24) & 0xff;
|
| 650 | | cd.output[9] = (track_pos >> 16) & 0xff;
|
| 651 | | cd.output[10] = (track_pos >> 8) & 0xff;
|
| 652 | | cd.output[11] = (track_pos) & 0xff;
|
| 653 | |
|
| 654 | | /* TODO: UPC flag at offset 12 */
|
| 655 | | cd.output[12] = 0;
|
| 656 | | }
|
| 657 | |
|
| 658 | | matsucd_complete_cmd( 13 );
|
| 659 | | }
|
| 660 | | break;
|
| 661 | | |
| 662 | | case 0x89: /* read disk info */
|
| 663 | | {
|
| 664 | | UINT32 end;
|
| 665 | |
|
| 666 | | if ( cd.input_pos < 7 )
|
| 667 | | return;
|
| 668 | |
|
| 669 | | memset( cd.output, 0, 5 );
|
| 670 | |
|
| 671 | | cd.output[0] = cdrom_get_last_track(cd.cdrom) ? 1 : 0;
|
| 672 | | cd.output[1] = cdrom_get_last_track(cd.cdrom);
|
| 673 | | end = cdrom_get_track_start(cd.cdrom,cd.output[1]-1);
|
| 674 | | end += cdrom_get_toc(cd.cdrom)->tracks[cd.output[1]-1].frames;
|
| 675 | | end = LBA2MSF(end);
|
| 676 | | cd.output[2] = (end >> 16) & 0xff;
|
| 677 | | cd.output[3] = (end >> 8) & 0xff;
|
| 678 | | cd.output[4] = (end) & 0xff;
|
| 679 | |
|
| 680 | | matsucd_complete_cmd( 5 );
|
| 681 | | }
|
| 682 | | break;
|
| 683 | | |
| 684 | | case 0x8a: /* read toc */
|
| 685 | | {
|
| 686 | | UINT8 track;
|
| 687 | | int msfmode;
|
| 688 | | UINT32 track_start;
|
| 689 | |
|
| 690 | | if ( cd.input_pos < 7 )
|
| 691 | | return;
|
| 692 | |
|
| 693 | | /* stop CDDA audio if necessary */
|
| 694 | | matsucd_cdda_stop();
|
| 695 | | |
| 696 | | track = cd.input[2];
|
| 697 | | msfmode = (cd.input[1] & 0x02) ? 1 : 0;
|
| 698 | | |
| 699 | | if ( cd.cdrom == NULL )
|
| 700 | | {
|
| 701 | | logerror( "MATSUCD - Warning: Reading TOC without a CD!\n" );
|
| 702 | | matsucd_command_error();
|
| 703 | | return;
|
| 704 | | }
|
| 705 | |
|
| 706 | | if ( track > cdrom_get_last_track(cd.cdrom) )
|
| 707 | | {
|
| 708 | | logerror( "MATSUCD - Warning: Reading invalid track entry from TOC!\n" );
|
| 709 | | matsucd_command_error();
|
| 710 | | return;
|
| 711 | | }
|
| 712 | |
|
| 713 | | memset( cd.output, 0, 7 );
|
| 714 | |
|
| 715 | | track_start = cdrom_get_track_start(cd.cdrom, track > 0 ? (track-1) : track );
|
| 716 | | if ( msfmode ) track_start = LBA2MSF( track_start );
|
| 717 | | |
| 718 | | cd.output[1] = cdrom_get_adr_control(cd.cdrom, track > 0 ? (track-1) : track);
|
| 719 | | cd.output[2] = track;
|
| 720 | | cd.output[3] = (track == 0 ) ? cdrom_get_last_track(cd.cdrom) : 0;
|
| 721 | | cd.output[4] = (track_start >> 24) & 0xff;
|
| 722 | | cd.output[5] = (track_start >> 16) & 0xff;
|
| 723 | | cd.output[6] = (track_start >> 8) & 0xff;
|
| 724 | | cd.output[7] = (track_start) & 0xff;
|
| 725 | |
|
| 726 | | cd.motor = 1;
|
| 727 | |
|
| 728 | | matsucd_complete_cmd( 8 );
|
| 729 | | }
|
| 730 | | break;
|
| 731 | | |
| 732 | | case 0x8b: /* pause audio */
|
| 733 | | {
|
| 734 | | if ( cd.input_pos < 7 )
|
| 735 | | return;
|
| 736 | |
|
| 737 | | matsucd_cdda_pause( (cd.input[1] == 0) ? 1 : 0 );
|
| 738 | | memset( cd.output, 0, 7 );
|
| 739 | | matsucd_complete_cmd( 0 );
|
| 740 | | }
|
| 741 | | break;
|
| 742 | | |
| 743 | | case 0xa3: /* front panel */
|
| 744 | | {
|
| 745 | | if ( cd.input_pos < 7 )
|
| 746 | | return;
|
| 747 | |
|
| 748 | | /* TODO: ??? */
|
| 749 | | |
| 750 | | memset( cd.output, 0, 7 );
|
| 751 | | matsucd_complete_cmd( 0 );
|
| 752 | | }
|
| 753 | | break;
|
| 754 | | |
| 755 | | default:
|
| 756 | | logerror( "MATSUCD: Unknown/inimplemented command %08x\n", cmd );
|
| 757 | | break;
|
| 758 | | }
|
| 759 | | }
|
| 1 | /*************************************************************************** |
| 2 | |
| 3 | Matsushita/Panasonic CDR521/522 type CDROM drive emulation |
| 4 | |
| 5 | Notes: |
| 6 | This version implements the drive found in Amiga CDTV. There are |
| 7 | different drives supporting this command-set (look in the sbpcd driver |
| 8 | in Linux for examples). Most drives support the exact same command |
| 9 | structure, but the command numbers differ. Eventually this driver |
| 10 | can be expanded with support for the other drives as needed. |
| 11 | |
| 12 | ***************************************************************************/ |
| 13 | |
| 14 | #include "mame.h" |
| 15 | #include "driver.h" |
| 16 | #include "devices/chd_cd.h" |
| 17 | #include "sound/cdda.h" |
| 18 | |
| 19 | |
| 20 | #define MATSU_STATUS_READY ( 1 << 0 ) /* driver ready */ |
| 21 | #define MATSU_STATUS_DOORLOCKED ( 1 << 1 ) /* door locked */ |
| 22 | #define MATSU_STATUS_PLAYING ( 1 << 2 ) /* drive playing */ |
| 23 | #define MATSU_STATUS_SUCCESS ( 1 << 3 ) /* last command was succesful */ |
| 24 | #define MATSU_STATUS_ERROR ( 1 << 4 ) /* last command failed */ |
| 25 | #define MATSU_STATUS_MOTOR ( 1 << 5 ) /* spinning */ |
| 26 | #define MATSU_STATUS_MEDIA ( 1 << 6 ) /* media present (in caddy or tray) */ |
| 27 | #define MATSU_STATUS_DOORCLOSED ( 1 << 7 ) /* tray status */ |
| 28 | |
| 29 | typedef struct |
| 30 | { |
| 31 | UINT8 enabled; /* /ENABLE - Unit enabled */ |
| 32 | UINT8 cmd_signal; /* /CMD - Command mode */ |
| 33 | UINT8 stch_signal; /* /STCH - Status Changed */ |
| 34 | UINT8 sten_signal; /* /STEN - Status Enabled */ |
| 35 | UINT8 scor_signal; /* /STEN - Subcode Ready */ |
| 36 | UINT8 input[16]; |
| 37 | UINT8 input_pos; |
| 38 | UINT8 output[16]; |
| 39 | UINT8 output_pos; |
| 40 | UINT8 output_len; |
| 41 | UINT8 status; |
| 42 | UINT8 motor; |
| 43 | UINT16 sector_size; |
| 44 | UINT32 lba; |
| 45 | UINT16 num_blocks; |
| 46 | UINT16 xfer_offset; |
| 47 | UINT8 sector_buffer[CD_MAX_SECTOR_DATA]; |
| 48 | UINT8 cdda_set; |
| 49 | void (*sten_cb)( int level ); /* Status enabled callback */ |
| 50 | void (*stch_cb)( int level ); /* Status changed callback */ |
| 51 | void (*scor_cb)( int level ); /* Subcode ready callback */ |
| 52 | cdrom_file *cdrom; |
| 53 | mame_timer *frame_timer; |
| 54 | } matsucd; |
| 55 | |
| 56 | static matsucd cd; |
| 57 | |
| 58 | #define MSF2LBA(msf) (((msf >> 16) & 0xff) * 60 * 75 + ((msf >> 8) & 0xff) * 75 + ((msf >> 0) & 0xff)) |
| 59 | #define LBA2MSF(lba) (((lba / (75 * 60)) << 16) | (((lba / 75) % 60) << 8) | (lba % 75)) |
| 60 | |
| 61 | static TIMER_CALLBACK(matsu_subcode_proc); |
| 62 | |
| 63 | void matsucd_init( void ) |
| 64 | { |
| 65 | memset(&cd, 0, sizeof( matsucd ) ); |
| 66 | |
| 67 | cd.cdrom = mess_cd_get_cdrom_file_by_number(0); |
| 68 | |
| 69 | cd.frame_timer = mame_timer_alloc(matsu_subcode_proc); |
| 70 | |
| 71 | cd.stch_signal = 1; |
| 72 | } |
| 73 | |
| 74 | void matsucd_set_status_enabled_callback( void (*sten_cb)( int level ) ) |
| 75 | { |
| 76 | /* add the callback for status enabled signal */ |
| 77 | cd.sten_cb = sten_cb; |
| 78 | } |
| 79 | |
| 80 | void matsucd_set_status_changed_callback( void (*stch_cb)( int level ) ) |
| 81 | { |
| 82 | /* add the callback for status changed signal */ |
| 83 | cd.stch_cb = stch_cb; |
| 84 | } |
| 85 | |
| 86 | void matsucd_set_subcode_ready_callback( void (*scor_cb)( int level ) ) |
| 87 | { |
| 88 | /* add the callback for subcode ready signal */ |
| 89 | cd.scor_cb = scor_cb; |
| 90 | } |
| 91 | |
| 92 | static int matsucd_getsector_type( void ) |
| 93 | { |
| 94 | switch( cd.sector_size ) |
| 95 | { |
| 96 | case 2048: return CD_TRACK_MODE1; break; |
| 97 | case 2324: return CD_TRACK_MODE2_FORM2; break; |
| 98 | case 2336: return CD_TRACK_MODE2; break; |
| 99 | case 2352: return CD_TRACK_MODE2_RAW; break; |
| 100 | |
| 101 | default: logerror( "MATSUCD: Sector size %d unsupported!\n", cd.sector_size ); break; |
| 102 | } |
| 103 | |
| 104 | return CD_TRACK_RAW_DONTCARE; |
| 105 | } |
| 106 | |
| 107 | void matsucd_read_next_block( void ) |
| 108 | { |
| 109 | cd.xfer_offset = 0; |
| 110 | |
| 111 | if ( cd.num_blocks ) |
| 112 | { |
| 113 | cd.lba++; |
| 114 | cd.num_blocks--; |
| 115 | |
| 116 | if (!cdrom_read_data(cd.cdrom, cd.lba, cd.sector_buffer, matsucd_getsector_type())) |
| 117 | { |
| 118 | logerror( "MATSUCD - Warning: Read error on CD!\n" ); |
| 119 | } |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | int matsucd_get_next_byte( UINT8 *data ) |
| 124 | { |
| 125 | /* no more data to read on this sector */ |
| 126 | if ( cd.xfer_offset >= cd.sector_size ) |
| 127 | return -1; |
| 128 | |
| 129 | if ( data ) |
| 130 | *data = cd.sector_buffer[cd.xfer_offset++]; |
| 131 | |
| 132 | return 0; |
| 133 | } |
| 134 | |
| 135 | static void matsucd_cdda_stop( void ) |
| 136 | { |
| 137 | int cddanum = cdda_num_from_cdrom(cd.cdrom); |
| 138 | |
| 139 | if (cddanum != -1) |
| 140 | { |
| 141 | cdda_stop_audio(cddanum); |
| 142 | mame_timer_reset( cd.frame_timer, time_never ); |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | static void matsucd_cdda_play( UINT32 lba, UINT32 num_blocks ) |
| 147 | { |
| 148 | int cddanum = cdda_num_from_cdrom(cd.cdrom); |
| 149 | if (cddanum != -1) |
| 150 | { |
| 151 | cdda_start_audio(cddanum, lba, num_blocks); |
| 152 | mame_timer_adjust( cd.frame_timer, MAME_TIME_IN_HZ( 75 ), 0, time_zero ); |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | static void matsucd_cdda_pause( int pause ) |
| 157 | { |
| 158 | int cddanum = cdda_num_from_cdrom(cd.cdrom); |
| 159 | if (cddanum != -1) |
| 160 | { |
| 161 | cdda_pause_audio(cddanum, pause); |
| 162 | |
| 163 | if ( pause ) |
| 164 | { |
| 165 | mame_timer_reset( cd.frame_timer, time_never ); |
| 166 | } |
| 167 | else |
| 168 | { |
| 169 | mame_timer_adjust( cd.frame_timer, MAME_TIME_IN_HZ( 75 ), 0, time_zero ); |
| 170 | } |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | static UINT8 matsucd_cdda_getstatus( UINT32 *lba ) |
| 175 | { |
| 176 | int cddanum = cdda_num_from_cdrom(cd.cdrom); |
| 177 | |
| 178 | if ( lba ) *lba = 0; |
| 179 | |
| 180 | if (cddanum != -1) |
| 181 | { |
| 182 | if (cdda_audio_active(cddanum)) |
| 183 | { |
| 184 | if ( lba ) *lba = cdda_get_audio_lba(cddanum); |
| 185 | |
| 186 | if (cdda_audio_paused(cddanum)) |
| 187 | { |
| 188 | return 0x12; /* audio paused */ |
| 189 | } |
| 190 | else |
| 191 | { |
| 192 | return 0x11; /* audio in progress */ |
| 193 | } |
| 194 | } |
| 195 | else if (cdda_audio_ended(cddanum)) |
| 196 | { |
| 197 | return 0x13; /* audio ended */ |
| 198 | } |
| 199 | } |
| 200 | |
| 201 | return 0x15; /* no audio status */ |
| 202 | } |
| 203 | |
| 204 | void matsucd_enable_w( int level ) |
| 205 | { |
| 206 | cd.enabled = ( level ) ? 0 : 1; |
| 207 | } |
| 208 | |
| 209 | void matsucd_cmd_w( int level ) |
| 210 | { |
| 211 | cd.cmd_signal = ( level ) ? 0 : 1; |
| 212 | } |
| 213 | |
| 214 | int matsucd_stch_r( void ) |
| 215 | { |
| 216 | return cd.stch_signal ? 0 : 1; |
| 217 | } |
| 218 | |
| 219 | int matsucd_sten_r( void ) |
| 220 | { |
| 221 | return cd.sten_signal ? 0 : 1; |
| 222 | } |
| 223 | |
| 224 | int matsucd_scor_r( void ) |
| 225 | { |
| 226 | return cd.scor_signal ? 0 : 1; |
| 227 | } |
| 228 | |
| 229 | static void update_status_enable( int level ) |
| 230 | { |
| 231 | cd.sten_signal = level; |
| 232 | |
| 233 | if ( cd.sten_cb ) |
| 234 | { |
| 235 | (*cd.sten_cb)(cd.sten_signal); |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | static void update_status_changed( int level ) |
| 240 | { |
| 241 | cd.stch_signal = level; |
| 242 | |
| 243 | if ( cd.stch_cb ) |
| 244 | { |
| 245 | (*cd.stch_cb)(cd.stch_signal); |
| 246 | } |
| 247 | } |
| 248 | |
| 249 | static void update_subcode_ready( int level ) |
| 250 | { |
| 251 | cd.scor_signal = level; |
| 252 | |
| 253 | if ( cd.scor_cb ) |
| 254 | { |
| 255 | (*cd.scor_cb)(cd.scor_signal); |
| 256 | } |
| 257 | } |
| 258 | |
| 259 | static TIMER_CALLBACK(matsucd_set_status_end) |
| 260 | { |
| 261 | update_status_changed( 1 ); |
| 262 | } |
| 263 | |
| 264 | static void matsucd_set_status( UINT8 status ) |
| 265 | { |
| 266 | if ( status != cd.status ) |
| 267 | { |
| 268 | cd.status = status; |
| 269 | |
| 270 | if ( cd.stch_signal != 0 ) |
| 271 | { |
| 272 | update_status_changed( 0 ); |
| 273 | mame_timer_set( MAME_TIME_IN_MSEC(1), 0, matsucd_set_status_end ); |
| 274 | } |
| 275 | } |
| 276 | } |
| 277 | |
| 278 | static TIMER_CALLBACK(matsu_subcode_proc) |
| 279 | { |
| 280 | int cddanum = cdda_num_from_cdrom(cd.cdrom); |
| 281 | |
| 282 | (void)param; |
| 283 | |
| 284 | if (cddanum != -1) |
| 285 | { |
| 286 | UINT8 s = matsucd_cdda_getstatus(NULL); |
| 287 | UINT8 newstatus = cd.status; |
| 288 | |
| 289 | if ( s == 0x11 || s == 0x12 ) |
| 290 | { |
| 291 | if ( s == 0x11 ) |
| 292 | { |
| 293 | update_subcode_ready( 1 ); |
| 294 | update_subcode_ready( 0 ); |
| 295 | } |
| 296 | |
| 297 | newstatus |= MATSU_STATUS_PLAYING; |
| 298 | |
| 299 | mame_timer_adjust( cd.frame_timer, MAME_TIME_IN_HZ( 75 ), 0, time_zero ); |
| 300 | } |
| 301 | else |
| 302 | { |
| 303 | newstatus &= ~MATSU_STATUS_PLAYING; |
| 304 | } |
| 305 | |
| 306 | matsucd_set_status( newstatus ); |
| 307 | } |
| 308 | } |
| 309 | |
| 310 | static void matsucd_command_error( void ) |
| 311 | { |
| 312 | UINT8 newstatus = cd.status; |
| 313 | |
| 314 | newstatus &= ~MATSU_STATUS_SUCCESS; |
| 315 | newstatus |= MATSU_STATUS_ERROR; |
| 316 | |
| 317 | matsucd_set_status( newstatus ); |
| 318 | } |
| 319 | |
| 320 | static void matsucd_complete_cmd( UINT8 len ) |
| 321 | { |
| 322 | UINT8 newstatus = cd.status; |
| 323 | |
| 324 | cd.input_pos = 0; |
| 325 | cd.output_pos = 0; |
| 326 | cd.output_len = len; |
| 327 | |
| 328 | newstatus &= ~MATSU_STATUS_ERROR; |
| 329 | newstatus |= MATSU_STATUS_SUCCESS; |
| 330 | |
| 331 | matsucd_set_status( newstatus ); |
| 332 | |
| 333 | update_status_enable( 1 ); |
| 334 | update_status_enable( 0 ); |
| 335 | } |
| 336 | |
| 337 | UINT8 matsucd_response_r( void ) |
| 338 | { |
| 339 | UINT8 v = cd.output[cd.output_pos++]; |
| 340 | |
| 341 | if ( cd.output_pos < cd.output_len ) |
| 342 | { |
| 343 | update_status_enable( 1 ); |
| 344 | update_status_enable( 0 ); |
| 345 | } |
| 346 | |
| 347 | return v; |
| 348 | } |
| 349 | |
| 350 | void matsucd_command_w( UINT8 data ) |
| 351 | { |
| 352 | UINT8 cmd; |
| 353 | |
| 354 | /* make sure we're enabled */ |
| 355 | if ( cd.enabled == 0 ) |
| 356 | return; |
| 357 | |
| 358 | /* make sure /CMD is asserted */ |
| 359 | if ( cd.cmd_signal == 0 ) |
| 360 | return; |
| 361 | |
| 362 | if ( cd.cdda_set == 0 ) |
| 363 | { |
| 364 | if ( cd.cdrom ) |
| 365 | cdda_set_cdrom(0, cd.cdrom); |
| 366 | |
| 367 | cd.cdda_set = 1; |
| 368 | } |
| 369 | |
| 370 | cd.input[cd.input_pos++] = data; |
| 371 | |
| 372 | cmd = cd.input[0]; |
| 373 | |
| 374 | switch( cmd ) |
| 375 | { |
| 376 | case 0x01: /* seek */ |
| 377 | { |
| 378 | if ( cd.input_pos < 7 ) |
| 379 | return; |
| 380 | |
| 381 | /* stop CDDA audio if necessary */ |
| 382 | matsucd_cdda_stop(); |
| 383 | |
| 384 | cd.motor = 1; |
| 385 | |
| 386 | memset( cd.output, 0, 6 ); |
| 387 | matsucd_complete_cmd( 0 ); |
| 388 | } |
| 389 | break; |
| 390 | |
| 391 | case 0x02: /* read sectors */ |
| 392 | { |
| 393 | if ( cd.input_pos < 7 ) |
| 394 | return; |
| 395 | |
| 396 | /* stop CDDA audio if necessary */ |
| 397 | matsucd_cdda_stop(); |
| 398 | |
| 399 | /* LBA */ |
| 400 | cd.lba = cd.input[1]; |
| 401 | cd.lba <<= 8; |
| 402 | cd.lba |= cd.input[2]; |
| 403 | cd.lba <<= 8; |
| 404 | cd.lba |= cd.input[3]; |
| 405 | |
| 406 | /* Number of blocks */ |
| 407 | cd.num_blocks = cd.input[4]; |
| 408 | cd.num_blocks <<= 8; |
| 409 | cd.num_blocks |= cd.input[5]; |
| 410 | |
| 411 | /* Reset transfer count */ |
| 412 | cd.xfer_offset = 0; |
| 413 | |
| 414 | /* go ahead and cache the first block */ |
| 415 | if (!cdrom_read_data(cd.cdrom, cd.lba, cd.sector_buffer, matsucd_getsector_type())) |
| 416 | { |
| 417 | logerror( "MATSUCD - Warning: Read error on CD!\n" ); |
| 418 | matsucd_command_error(); |
| 419 | return; |
| 420 | } |
| 421 | |
| 422 | cd.motor = 1; |
| 423 | |
| 424 | memset( cd.output, 0, 6 ); |
| 425 | matsucd_complete_cmd( 0 ); |
| 426 | } |
| 427 | break; |
| 428 | |
| 429 | case 0x04: /* motor on */ |
| 430 | { |
| 431 | if ( cd.input_pos < 7 ) |
| 432 | return; |
| 433 | |
| 434 | cd.motor = 1; |
| 435 | |
| 436 | memset( cd.output, 0, 6 ); |
| 437 | matsucd_complete_cmd( 0 ); |
| 438 | } |
| 439 | break; |
| 440 | |
| 441 | case 0x05: /* motor off */ |
| 442 | { |
| 443 | if ( cd.input_pos < 7 ) |
| 444 | return; |
| 445 | |
| 446 | /* stop CDDA audio if necessary */ |
| 447 | matsucd_cdda_stop(); |
| 448 | |
| 449 | cd.motor = 0; |
| 450 | |
| 451 | memset( cd.output, 0, 6 ); |
| 452 | matsucd_complete_cmd( 0 ); |
| 453 | } |
| 454 | break; |
| 455 | |
| 456 | case 0x09: /* play audio cd, LBA mode */ |
| 457 | { |
| 458 | UINT32 lba, numblocks; |
| 459 | |
| 460 | if ( cd.input_pos < 7 ) |
| 461 | return; |
| 462 | |
| 463 | lba = cd.input[1]; |
| 464 | lba <<= 8; |
| 465 | lba |= cd.input[2]; |
| 466 | lba <<= 8; |
| 467 | lba |= cd.input[3]; |
| 468 | |
| 469 | numblocks = cd.input[4]; |
| 470 | numblocks <<= 8; |
| 471 | numblocks |= cd.input[5]; |
| 472 | numblocks <<= 8; |
| 473 | numblocks |= cd.input[6]; |
| 474 | |
| 475 | matsucd_cdda_play( lba, numblocks ); |
| 476 | |
| 477 | cd.motor = 1; |
| 478 | |
| 479 | memset( cd.output, 0, 6 ); |
| 480 | matsucd_complete_cmd( 0 ); |
| 481 | } |
| 482 | break; |
| 483 | |
| 484 | case 0x0a: /* play audio cd, MSF mode */ |
| 485 | { |
| 486 | UINT32 start, end, lba_start, lba_end; |
| 487 | |
| 488 | if ( cd.input_pos < 7 ) |
| 489 | return; |
| 490 | |
| 491 | start = cd.input[1]; |
| 492 | start <<= 8; |
| 493 | start |= cd.input[2]; |
| 494 | start <<= 8; |
| 495 | start |= cd.input[3]; |
| 496 | |
| 497 | end = cd.input[4]; |
| 498 | end <<= 8; |
| 499 | end |= cd.input[5]; |
| 500 | end <<= 8; |
| 501 | end |= cd.input[6]; |
| 502 | |
| 503 | lba_start = MSF2LBA( start ); |
| 504 | lba_end = MSF2LBA( end ); |
| 505 | |
| 506 | if ( end == 0xffffff ) |
| 507 | { |
| 508 | lba_end = cdrom_get_track_start(cd.cdrom,cdrom_get_last_track(cd.cdrom)-1); |
| 509 | lba_end += cdrom_get_toc(cd.cdrom)->tracks[cdrom_get_last_track(cd.cdrom)-1].frames; |
| 510 | } |
| 511 | |
| 512 | if ( lba_end <= lba_start ) |
| 513 | { |
| 514 | matsucd_cdda_stop(); |
| 515 | } |
| 516 | else |
| 517 | { |
| 518 | matsucd_cdda_play( lba_start, lba_end - lba_start ); |
| 519 | cd.motor = 1; |
| 520 | } |
| 521 | |
| 522 | memset( cd.output, 0, 6 ); |
| 523 | matsucd_complete_cmd( 0 ); |
| 524 | } |
| 525 | break; |
| 526 | |
| 527 | case 0x0b: /* play audio track and index */ |
| 528 | { |
| 529 | UINT8 track_start = cd.input[1]; |
| 530 | UINT8 index_start = cd.input[2]; |
| 531 | UINT8 track_end = cd.input[3]; |
| 532 | UINT8 index_end = cd.input[4]; |
| 533 | UINT32 lba_start, lba_end; |
| 534 | |
| 535 | /* TODO: Add index support once the CDDA engine supports it */ |
| 536 | (void)index_start; |
| 537 | (void)index_end; |
| 538 | |
| 539 | /* sanitize values */ |
| 540 | if ( track_start == 0 ) track_start++; |
| 541 | if ( track_end > cdrom_get_last_track(cd.cdrom) ) |
| 542 | track_end = cdrom_get_last_track(cd.cdrom); |
| 543 | |
| 544 | /* find the start and stop positions */ |
| 545 | lba_start = cdrom_get_track_start(cd.cdrom,track_start-1); |
| 546 | lba_end = cdrom_get_track_start(cd.cdrom,track_end-1); |
| 547 | |
| 548 | lba_end += cdrom_get_toc(cd.cdrom)->tracks[track_end-1].frames; |
| 549 | |
| 550 | if ( lba_end <= lba_start ) |
| 551 | { |
| 552 | matsucd_cdda_stop(); |
| 553 | } |
| 554 | else |
| 555 | { |
| 556 | matsucd_cdda_play( lba_start, lba_end - lba_start ); |
| 557 | cd.motor = 1; |
| 558 | } |
| 559 | |
| 560 | memset( cd.output, 0, 6 ); |
| 561 | matsucd_complete_cmd( 0 ); |
| 562 | } |
| 563 | break; |
| 564 | |
| 565 | case 0x81: /* status read */ |
| 566 | { |
| 567 | UINT8 newstatus = cd.status; |
| 568 | |
| 569 | newstatus &= MATSU_STATUS_SUCCESS | MATSU_STATUS_ERROR | MATSU_STATUS_PLAYING; |
| 570 | newstatus |= MATSU_STATUS_READY; |
| 571 | |
| 572 | if (cd.cdrom) |
| 573 | { |
| 574 | newstatus |= MATSU_STATUS_MEDIA; |
| 575 | } |
| 576 | |
| 577 | if (cd.motor) |
| 578 | newstatus |= MATSU_STATUS_MOTOR; |
| 579 | |
| 580 | cd.output[0] = newstatus; |
| 581 | |
| 582 | matsucd_set_status( newstatus ); |
| 583 | |
| 584 | matsucd_complete_cmd( 1 ); |
| 585 | } |
| 586 | break; |
| 587 | |
| 588 | case 0x82: /* error read */ |
| 589 | { |
| 590 | if ( cd.input_pos < 7 ) |
| 591 | return; |
| 592 | |
| 593 | memset( cd.output, 0, 6 ); |
| 594 | matsucd_complete_cmd( 6 ); |
| 595 | } |
| 596 | break; |
| 597 | |
| 598 | case 0x84: /* set mode */ |
| 599 | { |
| 600 | if ( cd.input_pos < 7 ) |
| 601 | return; |
| 602 | |
| 603 | cd.sector_size = cd.input[2]; |
| 604 | cd.sector_size <<= 8; |
| 605 | cd.sector_size |= cd.input[3]; |
| 606 | |
| 607 | memset( cd.output, 0, 6 ); |
| 608 | matsucd_complete_cmd( 0 ); |
| 609 | } |
| 610 | break; |
| 611 | |
| 612 | case 0x87: /* read SUBQ */ |
| 613 | { |
| 614 | int msfmode; |
| 615 | UINT32 lba; |
| 616 | UINT8 track; |
| 617 | |
| 618 | if ( cd.input_pos < 7 ) |
| 619 | return; |
| 620 | |
| 621 | msfmode = (cd.input[1] & 0x02) ? 1 : 0; |
| 622 | |
| 623 | memset( cd.output, 0, 13 ); |
| 624 | |
| 625 | cd.output[0] = matsucd_cdda_getstatus( &lba ); |
| 626 | |
| 627 | if ( lba > 0 ) |
| 628 | { |
| 629 | UINT32 disk_pos; |
| 630 | UINT32 track_pos; |
| 631 | |
| 632 | track = cdrom_get_track(cd.cdrom, lba); |
| 633 | |
| 634 | cd.output[1] = cdrom_get_adr_control(cd.cdrom, track); |
| 635 | cd.output[2] = track+1; |
| 636 | cd.output[3] = 0; /* index */ |
| 637 | |
| 638 | disk_pos = lba; |
| 639 | if ( msfmode ) disk_pos = LBA2MSF(disk_pos); |
| 640 | |
| 641 | cd.output[4] = (disk_pos >> 24) & 0xff; |
| 642 | cd.output[5] = (disk_pos >> 16) & 0xff; |
| 643 | cd.output[6] = (disk_pos >> 8) & 0xff; |
| 644 | cd.output[7] = (disk_pos) & 0xff; |
| 645 | |
| 646 | track_pos = lba - cdrom_get_track_start(cd.cdrom, track); |
| 647 | if ( msfmode ) track_pos = LBA2MSF(track_pos); |
| 648 | |
| 649 | cd.output[8] = (track_pos >> 24) & 0xff; |
| 650 | cd.output[9] = (track_pos >> 16) & 0xff; |
| 651 | cd.output[10] = (track_pos >> 8) & 0xff; |
| 652 | cd.output[11] = (track_pos) & 0xff; |
| 653 | |
| 654 | /* TODO: UPC flag at offset 12 */ |
| 655 | cd.output[12] = 0; |
| 656 | } |
| 657 | |
| 658 | matsucd_complete_cmd( 13 ); |
| 659 | } |
| 660 | break; |
| 661 | |
| 662 | case 0x89: /* read disk info */ |
| 663 | { |
| 664 | UINT32 end; |
| 665 | |
| 666 | if ( cd.input_pos < 7 ) |
| 667 | return; |
| 668 | |
| 669 | memset( cd.output, 0, 5 ); |
| 670 | |
| 671 | cd.output[0] = cdrom_get_last_track(cd.cdrom) ? 1 : 0; |
| 672 | cd.output[1] = cdrom_get_last_track(cd.cdrom); |
| 673 | end = cdrom_get_track_start(cd.cdrom,cd.output[1]-1); |
| 674 | end += cdrom_get_toc(cd.cdrom)->tracks[cd.output[1]-1].frames; |
| 675 | end = LBA2MSF(end); |
| 676 | cd.output[2] = (end >> 16) & 0xff; |
| 677 | cd.output[3] = (end >> 8) & 0xff; |
| 678 | cd.output[4] = (end) & 0xff; |
| 679 | |
| 680 | matsucd_complete_cmd( 5 ); |
| 681 | } |
| 682 | break; |
| 683 | |
| 684 | case 0x8a: /* read toc */ |
| 685 | { |
| 686 | UINT8 track; |
| 687 | int msfmode; |
| 688 | UINT32 track_start; |
| 689 | |
| 690 | if ( cd.input_pos < 7 ) |
| 691 | return; |
| 692 | |
| 693 | /* stop CDDA audio if necessary */ |
| 694 | matsucd_cdda_stop(); |
| 695 | |
| 696 | track = cd.input[2]; |
| 697 | msfmode = (cd.input[1] & 0x02) ? 1 : 0; |
| 698 | |
| 699 | if ( cd.cdrom == NULL ) |
| 700 | { |
| 701 | logerror( "MATSUCD - Warning: Reading TOC without a CD!\n" ); |
| 702 | matsucd_command_error(); |
| 703 | return; |
| 704 | } |
| 705 | |
| 706 | if ( track > cdrom_get_last_track(cd.cdrom) ) |
| 707 | { |
| 708 | logerror( "MATSUCD - Warning: Reading invalid track entry from TOC!\n" ); |
| 709 | matsucd_command_error(); |
| 710 | return; |
| 711 | } |
| 712 | |
| 713 | memset( cd.output, 0, 7 ); |
| 714 | |
| 715 | track_start = cdrom_get_track_start(cd.cdrom, track > 0 ? (track-1) : track ); |
| 716 | if ( msfmode ) track_start = LBA2MSF( track_start ); |
| 717 | |
| 718 | cd.output[1] = cdrom_get_adr_control(cd.cdrom, track > 0 ? (track-1) : track); |
| 719 | cd.output[2] = track; |
| 720 | cd.output[3] = (track == 0 ) ? cdrom_get_last_track(cd.cdrom) : 0; |
| 721 | cd.output[4] = (track_start >> 24) & 0xff; |
| 722 | cd.output[5] = (track_start >> 16) & 0xff; |
| 723 | cd.output[6] = (track_start >> 8) & 0xff; |
| 724 | cd.output[7] = (track_start) & 0xff; |
| 725 | |
| 726 | cd.motor = 1; |
| 727 | |
| 728 | matsucd_complete_cmd( 8 ); |
| 729 | } |
| 730 | break; |
| 731 | |
| 732 | case 0x8b: /* pause audio */ |
| 733 | { |
| 734 | if ( cd.input_pos < 7 ) |
| 735 | return; |
| 736 | |
| 737 | matsucd_cdda_pause( (cd.input[1] == 0) ? 1 : 0 ); |
| 738 | memset( cd.output, 0, 7 ); |
| 739 | matsucd_complete_cmd( 0 ); |
| 740 | } |
| 741 | break; |
| 742 | |
| 743 | case 0xa3: /* front panel */ |
| 744 | { |
| 745 | if ( cd.input_pos < 7 ) |
| 746 | return; |
| 747 | |
| 748 | /* TODO: ??? */ |
| 749 | |
| 750 | memset( cd.output, 0, 7 ); |
| 751 | matsucd_complete_cmd( 0 ); |
| 752 | } |
| 753 | break; |
| 754 | |
| 755 | default: |
| 756 | logerror( "MATSUCD: Unknown/inimplemented command %08x\n", cmd ); |
| 757 | break; |
| 758 | } |
| 759 | } |
src/mess/machine/cybiko.c
| r882 | r883 | |
| 1 | | /*
|
| 2 | | |
| 3 | | Cybiko Wireless Inter-tainment System
|
| 4 | | |
| 5 | | (c) 2001-2007 Tim Schuerewegen
|
| 6 | | |
| 7 | | Cybiko Classic (V1)
|
| 8 | | Cybiko Classic (V2)
|
| 9 | | Cybiko Xtreme
|
| 10 | | |
| 11 | | */
|
| 12 | | |
| 13 | | #include "includes/cybiko.h"
|
| 14 | | |
| 15 | | #include "cpu/h8s2xxx/h8s2xxx.h"
|
| 16 | | #include "video/hd66421.h"
|
| 17 | | #include "sound/speaker.h"
|
| 18 | | #include "machine/pcf8593.h"
|
| 19 | | #include "machine/at45dbxx.h"
|
| 20 | | #include "machine/sst39vfx.h"
|
| 21 | | #include "debugger.h"
|
| 22 | | |
| 23 | | #define LOG_LEVEL 1
|
| 24 | | #define _logerror(level,...) if (LOG_LEVEL > level) logerror(__VA_ARGS__)
|
| 25 | | |
| 26 | | /////////////////////////
|
| 27 | | // FUNCTION PROTOTYPES //
|
| 28 | | /////////////////////////
|
| 29 | | |
| 30 | | #define MACHINE_STOP(name) \
|
| 31 | | void machine_stop_##name( running_machine *machine)
|
| 32 | | |
| 33 | | // machine stop
|
| 34 | | MACHINE_STOP( cybikov1 );
|
| 35 | | MACHINE_STOP( cybikov2 );
|
| 36 | | MACHINE_STOP( cybikoxt );
|
| 37 | | |
| 38 | | // rs232
|
| 39 | | void cybiko_rs232_init( void);
|
| 40 | | void cybiko_rs232_exit( void);
|
| 41 | | void cybiko_rs232_reset( void);
|
| 42 | | |
| 43 | | ////////////////////////
|
| 44 | | // DRIVER INIT & EXIT //
|
| 45 | | ////////////////////////
|
| 46 | | |
| 47 | | static void init_ram_handler( offs_t start, offs_t size, offs_t mirror)
|
| 48 | | {
|
| 49 | | memory_install_read_handler( 0, ADDRESS_SPACE_PROGRAM, start, start + size - 1, 0, mirror - size, STATIC_BANK1);
|
| 50 | | memory_install_write_handler( 0, ADDRESS_SPACE_PROGRAM, start, start + size - 1, 0, mirror - size, STATIC_BANK1);
|
| 51 | | memory_set_bankptr( 1, mess_ram);
|
| 52 | | }
|
| 53 | | |
| 54 | | DRIVER_INIT( cybikov1 )
|
| 55 | | {
|
| 56 | | _logerror( 0, "init_cybikov1\n");
|
| 57 | | init_ram_handler( 0x200000, mess_ram_size, 0x200000);
|
| 58 | | }
|
| 59 | | |
| 60 | | DRIVER_INIT( cybikov2 )
|
| 61 | | {
|
| 62 | | _logerror( 0, "init_cybikov2\n");
|
| 63 | | init_ram_handler( 0x200000, mess_ram_size, 0x200000);
|
| 64 | | }
|
| 65 | | |
| 66 | | DRIVER_INIT( cybikoxt )
|
| 67 | | {
|
| 68 | | _logerror( 0, "init_cybikoxt\n");
|
| 69 | | init_ram_handler( 0x400000, mess_ram_size, 0x200000);
|
| 70 | | }
|
| 71 | | |
| 72 | | ////////////////////
|
| 73 | | // NVRAM HANDLERS //
|
| 74 | | ////////////////////
|
| 75 | | |
| 76 | | /*
|
| 77 | | NVRAM_HANDLER( cybikov1 )
|
| 78 | | {
|
| 79 | | _logerror( 0, "nvram_handler_cybikov1 (%p/%d)\n", file, read_or_write);
|
| 80 | | nvram_handler_at45dbxx( machine, file, read_or_write);
|
| 81 | | nvram_handler_pcf8593( machine, file, read_or_write);
|
| 82 | | }
|
| 83 | | */
|
| 84 | | |
| 85 | | /*
|
| 86 | | NVRAM_HANDLER( cybikov2 )
|
| 87 | | {
|
| 88 | | _logerror( 0, "nvram_handler_cybikov2 (%p/%d)\n", file, read_or_write);
|
| 89 | | nvram_handler_at45dbxx( machine, file, read_or_write);
|
| 90 | | nvram_handler_sst39vfx( machine, file, read_or_write);
|
| 91 | | nvram_handler_pcf8593( machine, file, read_or_write);
|
| 92 | | }
|
| 93 | | */
|
| 94 | | |
| 95 | | /*
|
| 96 | | NVRAM_HANDLER( cybikoxt )
|
| 97 | | {
|
| 98 | | _logerror( 0, "nvram_handler_cybikoxt (%p/%d)\n", file, read_or_write);
|
| 99 | | nvram_handler_sst39vfx( machine, file, read_or_write);
|
| 100 | | nvram_handler_pcf8593( machine, file, read_or_write);
|
| 101 | | }
|
| 102 | | */
|
| 103 | | |
| 104 | | ///////////////////
|
| 105 | | // MACHINE START //
|
| 106 | | ///////////////////
|
| 107 | | |
| 108 | | static mame_file *nvram_system_fopen( running_machine *machine, UINT32 openflags, const char *name)
|
| 109 | | {
|
| 110 | | astring *fname;
|
| 111 | | file_error filerr;
|
| 112 | | mame_file *file;
|
| 113 | | fname = astring_assemble_4( astring_alloc(), machine->gamedrv->name, PATH_SEPARATOR, name, ".nv");
|
| 114 | | filerr = mame_fopen( SEARCHPATH_NVRAM, astring_c( fname), openflags, &file);
|
| 115 | | astring_free( fname);
|
| 116 | | return (filerr == FILERR_NONE) ? file : NULL;
|
| 117 | | }
|
| 118 | | |
| 119 | | typedef void (nvram_load_func)( mame_file *file);
|
| 120 | | |
| 121 | | static int nvram_system_load( running_machine *machine, const char *name, nvram_load_func _nvram_load, int required)
|
| 122 | | {
|
| 123 | | mame_file *file;
|
| 124 | | file = nvram_system_fopen( machine, OPEN_FLAG_READ, name);
|
| 125 | | if (!file)
|
| 126 | | {
|
| 127 | | if (required) mame_printf_error( "nvram load failed (%s)\n", name);
|
| 128 | | return FALSE;
|
| 129 | | }
|
| 130 | | _nvram_load( file);
|
| 131 | | mame_fclose( file);
|
| 132 | | return TRUE;
|
| 133 | | }
|
| 134 | | |
| 135 | | typedef void (nvram_save_func)( mame_file *file);
|
| 136 | | |
| 137 | | static int nvram_system_save( running_machine *machine, const char *name, nvram_save_func _nvram_save)
|
| 138 | | {
|
| 139 | | mame_file *file;
|
| 140 | | file = nvram_system_fopen( machine, OPEN_FLAG_CREATE | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE_PATHS, name);
|
| 141 | | if (!file)
|
| 142 | | {
|
| 143 | | mame_printf_error( "nvram save failed (%s)\n", name);
|
| 144 | | return FALSE;
|
| 145 | | }
|
| 146 | | _nvram_save( file);
|
| 147 | | mame_fclose( file);
|
| 148 | | return TRUE;
|
| 149 | | }
|
| 150 | | |
| 151 | | MACHINE_START( cybikov1 )
|
| 152 | | {
|
| 153 | | _logerror( 0, "machine_start_cybikov1\n");
|
| 154 | | // real-time clock
|
| 155 | | pcf8593_init();
|
| 156 | | nvram_system_load( machine, "rtc", pcf8593_load, 0);
|
| 157 | | // serial dataflash
|
| 158 | | at45dbxx_init( AT45DB041);
|
| 159 | | nvram_system_load( machine, "flash1", &at45dbxx_load, 1);
|
| 160 | | // serial port
|
| 161 | | cybiko_rs232_init();
|
| 162 | | // other
|
| 163 | | add_exit_callback( machine, machine_stop_cybikov1);
|
| 164 | | }
|
| 165 | | |
| 166 | | MACHINE_START( cybikov2 )
|
| 167 | | {
|
| 168 | | _logerror( 0, "machine_start_cybikov2\n");
|
| 169 | | // real-time clock
|
| 170 | | pcf8593_init();
|
| 171 | | nvram_system_load( machine, "rtc", pcf8593_load, 0);
|
| 172 | | // serial dataflash
|
| 173 | | at45dbxx_init( AT45DB041);
|
| 174 | | nvram_system_load( machine, "flash1", &at45dbxx_load, 1);
|
| 175 | | // multi-purpose flash
|
| 176 | | sst39vfx_init( SST39VF020, 16, CPU_IS_BE);
|
| 177 | | nvram_system_load( machine, "flash2", &sst39vfx_load, 1);
|
| 178 | | memory_set_bankptr( 2, sst39vfx_get_base());
|
| 179 | | // serial port
|
| 180 | | cybiko_rs232_init();
|
| 181 | | // other
|
| 182 | | add_exit_callback( machine, machine_stop_cybikov2);
|
| 183 | | }
|
| 184 | | |
| 185 | | MACHINE_START( cybikoxt )
|
| 186 | | {
|
| 187 | | _logerror( 0, "machine_start_cybikoxt\n");
|
| 188 | | // real-time clock
|
| 189 | | pcf8593_init();
|
| 190 | | nvram_system_load( machine, "rtc", pcf8593_load, 0);
|
| 191 | | // multi-purpose flash
|
| 192 | | sst39vfx_init( SST39VF400A, 16, CPU_IS_BE);
|
| 193 | | nvram_system_load( machine, "flash1", &sst39vfx_load, 1);
|
| 194 | | memory_set_bankptr( 2, sst39vfx_get_base());
|
| 195 | | // serial port
|
| 196 | | cybiko_rs232_init();
|
| 197 | | // other
|
| 198 | | add_exit_callback( machine, machine_stop_cybikoxt);
|
| 199 | | }
|
| 200 | | |
| 201 | | ///////////////////
|
| 202 | | // MACHINE RESET //
|
| 203 | | ///////////////////
|
| 204 | | |
| 205 | | MACHINE_RESET( cybikov1 )
|
| 206 | | {
|
| 207 | | _logerror( 0, "machine_reset_cybikov1\n");
|
| 208 | | pcf8593_reset();
|
| 209 | | at45dbxx_reset();
|
| 210 | | cybiko_rs232_reset();
|
| 211 | | }
|
| 212 | | |
| 213 | | MACHINE_RESET( cybikov2 )
|
| 214 | | {
|
| 215 | | _logerror( 0, "machine_reset_cybikov2\n");
|
| 216 | | pcf8593_reset();
|
| 217 | | at45dbxx_reset();
|
| 218 | | sst39vfx_reset();
|
| 219 | | cybiko_rs232_reset();
|
| 220 | | }
|
| 221 | | |
| 222 | | MACHINE_RESET( cybikoxt )
|
| 223 | | {
|
| 224 | | _logerror( 0, "machine_reset_cybikoxt\n");
|
| 225 | | pcf8593_reset();
|
| 226 | | sst39vfx_reset();
|
| 227 | | cybiko_rs232_reset();
|
| 228 | | }
|
| 229 | | |
| 230 | | //////////////////
|
| 231 | | // MACHINE STOP //
|
| 232 | | //////////////////
|
| 233 | | |
| 234 | | MACHINE_STOP( cybikov1 )
|
| 235 | | {
|
| 236 | | _logerror( 0, "machine_stop_cybikov1\n");
|
| 237 | | // real-time clock
|
| 238 | | nvram_system_save( machine, "rtc", pcf8593_save);
|
| 239 | | pcf8593_exit();
|
| 240 | | // serial dataflash
|
| 241 | | nvram_system_save( machine, "flash1", &at45dbxx_save);
|
| 242 | | at45dbxx_exit();
|
| 243 | | // serial port
|
| 244 | | cybiko_rs232_exit();
|
| 245 | | }
|
| 246 | | |
| 247 | | MACHINE_STOP( cybikov2 )
|
| 248 | | {
|
| 249 | | _logerror( 0, "machine_stop_cybikov2\n");
|
| 250 | | // real-time clock
|
| 251 | | nvram_system_save( machine, "rtc", pcf8593_save);
|
| 252 | | pcf8593_exit();
|
| 253 | | // serial dataflash
|
| 254 | | nvram_system_save( machine, "flash1", &at45dbxx_save);
|
| 255 | | at45dbxx_exit();
|
| 256 | | // multi-purpose flash
|
| 257 | | nvram_system_save( machine, "flash2", &sst39vfx_save);
|
| 258 | | sst39vfx_exit();
|
| 259 | | // serial port
|
| 260 | | cybiko_rs232_exit();
|
| 261 | | }
|
| 262 | | |
| 263 | | MACHINE_STOP( cybikoxt )
|
| 264 | | {
|
| 265 | | _logerror( 0, "machine_stop_cybikoxt\n");
|
| 266 | | // real-time clock
|
| 267 | | nvram_system_save( machine, "rtc", pcf8593_save);
|
| 268 | | pcf8593_exit();
|
| 269 | | // multi-purpose flash
|
| 270 | | nvram_system_save( machine, "flash1", &sst39vfx_save);
|
| 271 | | sst39vfx_exit();
|
| 272 | | // serial port
|
| 273 | | cybiko_rs232_exit();
|
| 274 | | }
|
| 275 | | |
| 276 | | ///////////
|
| 277 | | // RS232 //
|
| 278 | | ///////////
|
| 279 | | |
| 280 | | typedef struct
|
| 281 | | {
|
| 282 | | int sck; // serial clock
|
| 283 | | int txd; // transmit data
|
| 284 | | int rxd; // receive data
|
| 285 | | } CYBIKO_RS232_PINS;
|
| 286 | | |
| 287 | | typedef struct
|
| 288 | | {
|
| 289 | | CYBIKO_RS232_PINS pin;
|
| 290 | | UINT8 rx_bits, rx_byte, tx_byte, tx_bits;
|
| 291 | | } CYBIKO_RS232;
|
| 292 | | |
| 293 | | static CYBIKO_RS232 rs232;
|
| 294 | | |
| 295 | | void cybiko_rs232_init( void)
|
| 296 | | {
|
| 297 | | _logerror( 0, "cybiko_rs232_init\n");
|
| 298 | | memset( &rs232, 0, sizeof( rs232));
|
| 299 | | // timer_pulse( TIME_IN_HZ( 10), 0, rs232_timer_callback);
|
| 300 | | }
|
| 301 | | |
| 302 | | void cybiko_rs232_exit( void)
|
| 303 | | {
|
| 304 | | _logerror( 0, "cybiko_rs232_exit\n");
|
| 305 | | }
|
| 306 | | |
| 307 | | void cybiko_rs232_reset( void)
|
| 308 | | {
|
| 309 | | _logerror( 0, "cybiko_rs232_reset\n");
|
| 310 | | }
|
| 311 | | |
| 312 | | void cybiko_rs232_write_byte( UINT8 data)
|
| 313 | | {
|
| 314 | | #if 0
|
| 315 | | printf( "%c", data);
|
| 316 | | #endif
|
| 317 | | }
|
| 318 | | |
| 319 | | void cybiko_rs232_pin_sck( int data)
|
| 320 | | {
|
| 321 | | _logerror( 3, "cybiko_rs232_pin_sck (%d)\n", data);
|
| 322 | | // clock high-to-low
|
| 323 | | if ((rs232.pin.sck == 1) && (data == 0))
|
| 324 | | {
|
| 325 | | // transmit
|
| 326 | | if (rs232.pin.txd) rs232.tx_byte = rs232.tx_byte | (1 << rs232.tx_bits);
|
| 327 | | rs232.tx_bits++;
|
| 328 | | if (rs232.tx_bits == 8)
|
| 329 | | {
|
| 330 | | rs232.tx_bits = 0;
|
| 331 | | cybiko_rs232_write_byte( rs232.tx_byte);
|
| 332 | | rs232.tx_byte = 0;
|
| 333 | | }
|
| 334 | | // receive
|
| 335 | | rs232.pin.rxd = (rs232.rx_byte >> rs232.rx_bits) & 1;
|
| 336 | | rs232.rx_bits++;
|
| 337 | | if (rs232.rx_bits == 8)
|
| 338 | | {
|
| 339 | | rs232.rx_bits = 0;
|
| 340 | | rs232.rx_byte = 0;
|
| 341 | | }
|
| 342 | | }
|
| 343 | | // save sck
|
| 344 | | rs232.pin.sck = data;
|
| 345 | | }
|
| 346 | | |
| 347 | | void cybiko_rs232_pin_txd( int data)
|
| 348 | | {
|
| 349 | | _logerror( 3, "cybiko_rs232_pin_txd (%d)\n", data);
|
| 350 | | rs232.pin.txd = data;
|
| 351 | | }
|
| 352 | | |
| 353 | | int cybiko_rs232_pin_rxd( void)
|
| 354 | | {
|
| 355 | | _logerror( 3, "cybiko_rs232_pin_rxd\n");
|
| 356 | | return rs232.pin.rxd;
|
| 357 | | }
|
| 358 | | |
| 359 | | int cybiko_rs232_rx_queue( void)
|
| 360 | | {
|
| 361 | | return 0;
|
| 362 | | }
|
| 363 | | |
| 364 | | /////////////////////////
|
| 365 | | // READ/WRITE HANDLERS //
|
| 366 | | /////////////////////////
|
| 367 | | |
| 368 | | READ16_HANDLER( cybiko_lcd_r )
|
| 369 | | {
|
| 370 | | UINT16 data = 0;
|
| 371 | | if ACCESSING_MSB16 data = data | (hd66421_reg_idx_r() << 8);
|
| 372 | | if ACCESSING_LSB16 data = data | (hd66421_reg_dat_r() << 0);
|
| 373 | | return data;
|
| 374 | | }
|
| 375 | | |
| 376 | | WRITE16_HANDLER( cybiko_lcd_w )
|
| 377 | | {
|
| 378 | | if ACCESSING_MSB16 hd66421_reg_idx_w( (data >> 8) & 0xFF);
|
| 379 | | if ACCESSING_LSB16 hd66421_reg_dat_w( (data >> 0) & 0xFF);
|
| 380 | | }
|
| 381 | | |
| 382 | | READ8_HANDLER( cybiko_key_r_byte )
|
| 383 | | {
|
| 384 | | UINT8 data = 0xFF;
|
| 385 | | int i;
|
| 386 | | _logerror( 2, "cybiko_key_r_byte (%08X)\n", offset);
|
| 387 | | // A11
|
| 388 | | if (!(offset & (1 << 11))) data &= 0xFE;
|
| 389 | | // A1 .. A9
|
| 390 | | for (i=1;i<10;i++) if (!(offset & (1 << i))) data &= readinputport( i - 1);
|
| 391 | | // A0
|
| 392 | | if (!(offset & (1 << 0))) data |= 0xFF;
|
| 393 | | //
|
| 394 | | return data;
|
| 395 | | }
|
| 396 | | |
| 397 | | READ16_HANDLER( cybiko_key_r )
|
| 398 | | {
|
| 399 | | UINT16 data = 0;
|
| 400 | | _logerror( 2, "cybiko_key_r (%08X/%04X)\n", offset, mem_mask);
|
| 401 | | if ACCESSING_MSB16 data = data | (cybiko_key_r_byte( offset * 2 + 0) << 8);
|
| 402 | | if ACCESSING_LSB16 data = data | (cybiko_key_r_byte( offset * 2 + 1) << 0);
|
| 403 | | _logerror( 2, "%04X\n", data);
|
| 404 | | return data;
|
| 405 | | }
|
| 406 | | |
| 407 | | READ8_HANDLER( cybiko_io_reg_r )
|
| 408 | | {
|
| 409 | | UINT8 data = 0;
|
| 410 | | _logerror( 2, "cybiko_io_reg_r (%08X)\n", offset);
|
| 411 | | switch (offset)
|
| 412 | | {
|
| 413 | | // keyboard
|
| 414 | | case H8S_IO_PORT1 :
|
| 415 | | {
|
| 416 | | //if (readinputport(0) & 0x02) data = data | 0x08; else data = data & (~0x08); // "esc" key
|
| 417 | | data = data | 0x08;
|
| 418 | | }
|
| 419 | | break;
|
| 420 | | // serial dataflash
|
| 421 | | case H8S_IO_PORT3 : if (at45dbxx_pin_so()) data = data | H8S_P3_RXD1; break;
|
| 422 | | // rs232
|
| 423 | | case H8S_IO_PORT5 : if (cybiko_rs232_pin_rxd()) data = data | H8S_P5_RXD2; break;
|
| 424 | | // real-time clock
|
| 425 | | case H8S_IO_PORTF :
|
| 426 | | {
|
| 427 | | data = H8S_PF_PF2;
|
| 428 | | if (pcf8593_pin_sda_r()) data |= H8S_PF_PF0;
|
| 429 | | }
|
| 430 | | break;
|
| 431 | | // serial 2
|
| 432 | | case H8S_IO_SSR2 :
|
| 433 | | {
|
| 434 | | if (cybiko_rs232_rx_queue()) data = data | H8S_SSR_RDRF;
|
| 435 | | }
|
| 436 | | break;
|
| 437 | | }
|
| 438 | | return data;
|
| 439 | | }
|
| 440 | | |
| 441 | | WRITE8_HANDLER( cybiko_io_reg_w )
|
| 442 | | {
|
| 443 | | _logerror( 2, "cybiko_io_reg_w (%08X/%02X)\n", offset, data);
|
| 444 | | switch (offset)
|
| 445 | | {
|
| 446 | | // speaker
|
| 447 | | case H8S_IO_P1DR : speaker_level_w( 0, (data & H8S_P1_TIOCB1) ? 1 : 0); break;
|
| 448 | | // serial dataflash
|
| 449 | | case H8S_IO_P3DR :
|
| 450 | | {
|
| 451 | | at45dbxx_pin_cs ( (data & H8S_P3_SCK0) ? 0 : 1);
|
| 452 | | at45dbxx_pin_si ( (data & H8S_P3_TXD1) ? 1 : 0);
|
| 453 | | at45dbxx_pin_sck( (data & H8S_P3_SCK1) ? 1 : 0);
|
| 454 | | }
|
| 455 | | break;
|
| 456 | | // rs232
|
| 457 | | case H8S_IO_P5DR :
|
| 458 | | {
|
| 459 | | cybiko_rs232_pin_txd( (data & H8S_P5_TXD2) ? 1 : 0);
|
| 460 | | cybiko_rs232_pin_sck( (data & H8S_P5_SCK2) ? 1 : 0);
|
| 461 | | }
|
| 462 | | break;
|
| 463 | | // real-time clock
|
| 464 | | case H8S_IO_PFDR : pcf8593_pin_scl( (data & H8S_PF_PF1) ? 1 : 0); break;
|
| 465 | | case H8S_IO_PFDDR : pcf8593_pin_sda_w( (data & H8S_PF_PF0) ? 0 : 1); break;
|
| 466 | | }
|
| 467 | | }
|
| 468 | | |
| 469 | | READ8_HANDLER( cybikov1_io_reg_r )
|
| 470 | | {
|
| 471 | | _logerror( 2, "cybikov1_io_reg_r (%08X)\n", offset);
|
| 472 | | return cybiko_io_reg_r( offset);
|
| 473 | | }
|
| 474 | | |
| 475 | | READ8_HANDLER( cybikov2_io_reg_r )
|
| 476 | | {
|
| 477 | | _logerror( 2, "cybikov2_io_reg_r (%08X)\n", offset);
|
| 478 | | return cybiko_io_reg_r( offset);
|
| 479 | | }
|
| 480 | | |
| 481 | | READ8_HANDLER( cybikoxt_io_reg_r )
|
| 482 | | {
|
| 483 | | UINT8 data = 0;
|
| 484 | | _logerror( 2, "cybikoxt_io_reg_r (%08X)\n", offset);
|
| 485 | | switch (offset)
|
| 486 | | {
|
| 487 | | // rs232
|
| 488 | | case H8S_IO_PORT3 : if (cybiko_rs232_pin_rxd()) data = data | H8S_P3_RXD1; break;
|
| 489 | | // default
|
| 490 | | default : data = cybiko_io_reg_r( offset);
|
| 491 | | }
|
| 492 | | return data;
|
| 493 | | }
|
| 494 | | |
| 495 | | WRITE8_HANDLER( cybikov1_io_reg_w )
|
| 496 | | {
|
| 497 | | _logerror( 2, "cybikov1_io_reg_w (%08X/%02X)\n", offset, data);
|
| 498 | | cybiko_io_reg_w( offset, data);
|
| 499 | | }
|
| 500 | | |
| 501 | | WRITE8_HANDLER( cybikov2_io_reg_w )
|
| 502 | | {
|
| 503 | | _logerror( 2, "cybikov2_io_reg_w (%08X/%02X)\n", offset, data);
|
| 504 | | cybiko_io_reg_w( offset, data);
|
| 505 | | }
|
| 506 | | |
| 507 | | WRITE8_HANDLER( cybikoxt_io_reg_w )
|
| 508 | | {
|
| 509 | | _logerror( 2, "cybikoxt_io_reg_w (%08X/%02X)\n", offset, data);
|
| 510 | | switch (offset)
|
| 511 | | {
|
| 512 | | // rs232
|
| 513 | | case H8S_IO_P3DR :
|
| 514 | | {
|
| 515 | | cybiko_rs232_pin_txd( (data & H8S_P3_TXD1) ? 1 : 0);
|
| 516 | | cybiko_rs232_pin_sck( (data & H8S_P3_SCK1) ? 1 : 0);
|
| 517 | | }
|
| 518 | | break;
|
| 519 | | // default
|
| 520 | | default : cybiko_io_reg_w( offset, data);
|
| 521 | | }
|
| 522 | | }
|
| 523 | | |
| 524 | | // Cybiko Xtreme writes following byte pairs to 0x200003/0x200000
|
| 525 | | // 00/01, 00/C0, 0F/32, 0D/03, 0B/03, 09/50, 07/D6, 05/00, 04/00, 20/00, 23/08, 27/01, 2F/08, 2C/02, 2B/08, 28/01
|
| 526 | | // 04/80, 05/02, 00/C8, 00/C8, 00/C0, 1B/2C, 00/01, 00/C0, 1B/6C, 0F/10, 0D/07, 0B/07, 09/D2, 07/D6, 05/00, 04/00,
|
| 527 | | // 20/00, 23/08, 27/01, 2F/08, 2C/02, 2B/08, 28/01, 37/08, 34/04, 33/08, 30/03, 04/80, 05/02, 1B/6C, 00/C8
|
| 528 | | WRITE16_HANDLER( cybiko_unk1_w )
|
| 529 | | {
|
| 530 | | if ACCESSING_MSB16 logerror( "[%08X] <- %02X\n", 0x200000 + offset * 2 + 0, (data >> 8) & 0xFF);
|
| 531 | | if ACCESSING_LSB16 logerror( "[%08X] <- %02X\n", 0x200000 + offset * 2 + 1, (data >> 0) & 0xFF);
|
| 532 | | }
|
| 533 | | |
| 534 | | READ16_HANDLER( cybiko_unk2_r )
|
| 535 | | {
|
| 536 | | switch (offset << 1)
|
| 537 | | {
|
| 538 | | case 0x000 : return 0xBA0B; break; // magic (part 1)
|
| 539 | | case 0x002 : return 0xAB15; break; // magic (part 2)
|
| 540 | | case 0x004 : return (0x07 << 8) | (0x07 ^0xFF); break; // brightness (or contrast) & value xor FF
|
| 541 | | // case 0x006 : return 0x2B57; break; // do not show "Free Games and Applications at www.cybiko.com" screen
|
| 542 | | case 0x008 : return 0xDEBA; break; // enable debug output
|
| 543 | | case 0x016 : return 0x5000 | 0x03FF; break; // ?
|
| 544 | | case 0x7FC : return 0x22A1; break; // crc32 (part 1)
|
| 545 | | case 0x7FE : return 0x8728; break; // crc32 (part 2)
|
| 546 | | default : return 0xFFFF; break;
|
| 547 | | }
|
| 548 | | }
|
| 1 | /* |
| 2 | |
| 3 | Cybiko Wireless Inter-tainment System |
| 4 | |
| 5 | (c) 2001-2007 Tim Schuerewegen |
| 6 | |
| 7 | Cybiko Classic (V1) |
| 8 | Cybiko Classic (V2) |
| 9 | Cybiko Xtreme |
| 10 | |
| 11 | */ |
| 12 | |
| 13 | #include "includes/cybiko.h" |
| 14 | |
| 15 | #include "cpu/h8s2xxx/h8s2xxx.h" |
| 16 | #include "video/hd66421.h" |
| 17 | #include "sound/speaker.h" |
| 18 | #include "machine/pcf8593.h" |
| 19 | #include "machine/at45dbxx.h" |
| 20 | #include "machine/sst39vfx.h" |
| 21 | #include "debugger.h" |
| 22 | |
| 23 | #define LOG_LEVEL 1 |
| 24 | #define _logerror(level,...) if (LOG_LEVEL > level) logerror(__VA_ARGS__) |
| 25 | |
| 26 | ///////////////////////// |
| 27 | // FUNCTION PROTOTYPES // |
| 28 | ///////////////////////// |
| 29 | |
| 30 | #define MACHINE_STOP(name) \ |
| 31 | void machine_stop_##name( running_machine *machine) |
| 32 | |
| 33 | // machine stop |
| 34 | MACHINE_STOP( cybikov1 ); |
| 35 | MACHINE_STOP( cybikov2 ); |
| 36 | MACHINE_STOP( cybikoxt ); |
| 37 | |
| 38 | // rs232 |
| 39 | void cybiko_rs232_init( void); |
| 40 | void cybiko_rs232_exit( void); |
| 41 | void cybiko_rs232_reset( void); |
| 42 | |
| 43 | //////////////////////// |
| 44 | // DRIVER INIT & EXIT // |
| 45 | //////////////////////// |
| 46 | |
| 47 | static void init_ram_handler( offs_t start, offs_t size, offs_t mirror) |
| 48 | { |
| 49 | memory_install_read_handler( 0, ADDRESS_SPACE_PROGRAM, start, start + size - 1, 0, mirror - size, STATIC_BANK1); |
| 50 | memory_install_write_handler( 0, ADDRESS_SPACE_PROGRAM, start, start + size - 1, 0, mirror - size, STATIC_BANK1); |
| 51 | memory_set_bankptr( 1, mess_ram); |
| 52 | } |
| 53 | |
| 54 | DRIVER_INIT( cybikov1 ) |
| 55 | { |
| 56 | _logerror( 0, "init_cybikov1\n"); |
| 57 | init_ram_handler( 0x200000, mess_ram_size, 0x200000); |
| 58 | } |
| 59 | |
| 60 | DRIVER_INIT( cybikov2 ) |
| 61 | { |
| 62 | _logerror( 0, "init_cybikov2\n"); |
| 63 | init_ram_handler( 0x200000, mess_ram_size, 0x200000); |
| 64 | } |
| 65 | |
| 66 | DRIVER_INIT( cybikoxt ) |
| 67 | { |
| 68 | _logerror( 0, "init_cybikoxt\n"); |
| 69 | init_ram_handler( 0x400000, mess_ram_size, 0x200000); |
| 70 | } |
| 71 | |
| 72 | //////////////////// |
| 73 | // NVRAM HANDLERS // |
| 74 | //////////////////// |
| 75 | |
| 76 | /* |
| 77 | NVRAM_HANDLER( cybikov1 ) |
| 78 | { |
| 79 | _logerror( 0, "nvram_handler_cybikov1 (%p/%d)\n", file, read_or_write); |
| 80 | nvram_handler_at45dbxx( machine, file, read_or_write); |
| 81 | nvram_handler_pcf8593( machine, file, read_or_write); |
| 82 | } |
| 83 | */ |
| 84 | |
| 85 | /* |
| 86 | NVRAM_HANDLER( cybikov2 ) |
| 87 | { |
| 88 | _logerror( 0, "nvram_handler_cybikov2 (%p/%d)\n", file, read_or_write); |
| 89 | nvram_handler_at45dbxx( machine, file, read_or_write); |
| 90 | nvram_handler_sst39vfx( machine, file, read_or_write); |
| 91 | nvram_handler_pcf8593( machine, file, read_or_write); |
| 92 | } |
| 93 | */ |
| 94 | |
| 95 | /* |
| 96 | NVRAM_HANDLER( cybikoxt ) |
| 97 | { |
| 98 | _logerror( 0, "nvram_handler_cybikoxt (%p/%d)\n", file, read_or_write); |
| 99 | nvram_handler_sst39vfx( machine, file, read_or_write); |
| 100 | nvram_handler_pcf8593( machine, file, read_or_write); |
| 101 | } |
| 102 | */ |
| 103 | |
| 104 | /////////////////// |
| 105 | // MACHINE START // |
| 106 | /////////////////// |
| 107 | |
| 108 | static mame_file *nvram_system_fopen( running_machine *machine, UINT32 openflags, const char *name) |
| 109 | { |
| 110 | astring *fname; |
| 111 | file_error filerr; |
| 112 | mame_file *file; |
| 113 | fname = astring_assemble_4( astring_alloc(), machine->gamedrv->name, PATH_SEPARATOR, name, ".nv"); |
| 114 | filerr = mame_fopen( SEARCHPATH_NVRAM, astring_c( fname), openflags, &file); |
| 115 | astring_free( fname); |
| 116 | return (filerr == FILERR_NONE) ? file : NULL; |
| 117 | } |
| 118 | |
| 119 | typedef void (nvram_load_func)( mame_file *file); |
| 120 | |
| 121 | static int nvram_system_load( running_machine *machine, const char *name, nvram_load_func _nvram_load, int required) |
| 122 | { |
| 123 | mame_file *file; |
| 124 | file = nvram_system_fopen( machine, OPEN_FLAG_READ, name); |
| 125 | if (!file) |
| 126 | { |
| 127 | if (required) mame_printf_error( "nvram load failed (%s)\n", name); |
| 128 | return FALSE; |
| 129 | } |
| 130 | _nvram_load( file); |
| 131 | mame_fclose( file); |
| 132 | return TRUE; |
| 133 | } |
| 134 | |
| 135 | typedef void (nvram_save_func)( mame_file *file); |
| 136 | |
| 137 | static int nvram_system_save( running_machine *machine, const char *name, nvram_save_func _nvram_save) |
| 138 | { |
| 139 | mame_file *file; |
| 140 | file = nvram_system_fopen( machine, OPEN_FLAG_CREATE | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE_PATHS, name); |
| 141 | if (!file) |
| 142 | { |
| 143 | mame_printf_error( "nvram save failed (%s)\n", name); |
| 144 | return FALSE; |
| 145 | } |
| 146 | _nvram_save( file); |
| 147 | mame_fclose( file); |
| 148 | return TRUE; |
| 149 | } |
| 150 | |
| 151 | MACHINE_START( cybikov1 ) |
| 152 | { |
| 153 | _logerror( 0, "machine_start_cybikov1\n"); |
| 154 | // real-time clock |
| 155 | pcf8593_init(); |
| 156 | nvram_system_load( machine, "rtc", pcf8593_load, 0); |
| 157 | // serial dataflash |
| 158 | at45dbxx_init( AT45DB041); |
| 159 | nvram_system_load( machine, "flash1", &at45dbxx_load, 1); |
| 160 | // serial port |
| 161 | cybiko_rs232_init(); |
| 162 | // other |
| 163 | add_exit_callback( machine, machine_stop_cybikov1); |
| 164 | } |
| 165 | |
| 166 | MACHINE_START( cybikov2 ) |
| 167 | { |
| 168 | _logerror( 0, "machine_start_cybikov2\n"); |
| 169 | // real-time clock |
| 170 | pcf8593_init(); |
| 171 | nvram_system_load( machine, "rtc", pcf8593_load, 0); |
| 172 | // serial dataflash |
| 173 | at45dbxx_init( AT45DB041); |
| 174 | nvram_system_load( machine, "flash1", &at45dbxx_load, 1); |
| 175 | // multi-purpose flash |
| 176 | sst39vfx_init( SST39VF020, 16, CPU_IS_BE); |
| 177 | nvram_system_load( machine, "flash2", &sst39vfx_load, 1); |
| 178 | memory_set_bankptr( 2, sst39vfx_get_base()); |
| 179 | // serial port |
| 180 | cybiko_rs232_init(); |
| 181 | // other |
| 182 | add_exit_callback( machine, machine_stop_cybikov2); |
| 183 | } |
| 184 | |
| 185 | MACHINE_START( cybikoxt ) |
| 186 | { |
| 187 | _logerror( 0, "machine_start_cybikoxt\n"); |
| 188 | // real-time clock |
| 189 | pcf8593_init(); |
| 190 | nvram_system_load( machine, "rtc", pcf8593_load, 0); |
| 191 | // multi-purpose flash |
| 192 | sst39vfx_init( SST39VF400A, 16, CPU_IS_BE); |
| 193 | nvram_system_load( machine, "flash1", &sst39vfx_load, 1); |
| 194 | memory_set_bankptr( 2, sst39vfx_get_base()); |
| 195 | // serial port |
| 196 | cybiko_rs232_init(); |
| 197 | // other |
| 198 | add_exit_callback( machine, machine_stop_cybikoxt); |
| 199 | } |
| 200 | |
| 201 | /////////////////// |
| 202 | // MACHINE RESET // |
| 203 | /////////////////// |
| 204 | |
| 205 | MACHINE_RESET( cybikov1 ) |
| 206 | { |
| 207 | _logerror( 0, "machine_reset_cybikov1\n"); |
| 208 | pcf8593_reset(); |
| 209 | at45dbxx_reset(); |
| 210 | cybiko_rs232_reset(); |
| 211 | } |
| 212 | |
| 213 | MACHINE_RESET( cybikov2 ) |
| 214 | { |
| 215 | _logerror( 0, "machine_reset_cybikov2\n"); |
| 216 | pcf8593_reset(); |
| 217 | at45dbxx_reset(); |
| 218 | sst39vfx_reset(); |
| 219 | cybiko_rs232_reset(); |
| 220 | } |
| 221 | |
| 222 | MACHINE_RESET( cybikoxt ) |
| 223 | { |
| 224 | _logerror( 0, "machine_reset_cybikoxt\n"); |
| 225 | pcf8593_reset(); |
| 226 | sst39vfx_reset(); |
| 227 | cybiko_rs232_reset(); |
| 228 | } |
| 229 | |
| 230 | ////////////////// |
| 231 | // MACHINE STOP // |
| 232 | ////////////////// |
| 233 | |
| 234 | MACHINE_STOP( cybikov1 ) |
| 235 | { |
| 236 | _logerror( 0, "machine_stop_cybikov1\n"); |
| 237 | // real-time clock |
| 238 | nvram_system_save( machine, "rtc", pcf8593_save); |
| 239 | pcf8593_exit(); |
| 240 | // serial dataflash |
| 241 | nvram_system_save( machine, "flash1", &at45dbxx_save); |
| 242 | at45dbxx_exit(); |
| 243 | // serial port |
| 244 | cybiko_rs232_exit(); |
| 245 | } |
| 246 | |
| 247 | MACHINE_STOP( cybikov2 ) |
| 248 | { |
| 249 | _logerror( 0, "machine_stop_cybikov2\n"); |
| 250 | // real-time clock |
| 251 | nvram_system_save( machine, "rtc", pcf8593_save); |
| 252 | pcf8593_exit(); |
| 253 | // serial dataflash |
| 254 | nvram_system_save( machine, "flash1", &at45dbxx_save); |
| 255 | at45dbxx_exit(); |
| 256 | // multi-purpose flash |
| 257 | nvram_system_save( machine, "flash2", &sst39vfx_save); |
| 258 | sst39vfx_exit(); |
| 259 | // serial port |
| 260 | cybiko_rs232_exit(); |
| 261 | } |
| 262 | |
| 263 | MACHINE_STOP( cybikoxt ) |
| 264 | { |
| 265 | _logerror( 0, "machine_stop_cybikoxt\n"); |
| 266 | // real-time clock |
| 267 | nvram_system_save( machine, "rtc", pcf8593_save); |
| 268 | pcf8593_exit(); |
| 269 | // multi-purpose flash |
| 270 | nvram_system_save( machine, "flash1", &sst39vfx_save); |
| 271 | sst39vfx_exit(); |
| 272 | // serial port |
| 273 | cybiko_rs232_exit(); |
| 274 | } |
| 275 | |
| 276 | /////////// |
| 277 | // RS232 // |
| 278 | /////////// |
| 279 | |
| 280 | typedef struct |
| 281 | { |
| 282 | int sck; // serial clock |
| 283 | int txd; // transmit data |
| 284 | int rxd; // receive data |
| 285 | } CYBIKO_RS232_PINS; |
| 286 | |
| 287 | typedef struct |
| 288 | { |
| 289 | CYBIKO_RS232_PINS pin; |
| 290 | UINT8 rx_bits, rx_byte, tx_byte, tx_bits; |
| 291 | } CYBIKO_RS232; |
| 292 | |
| 293 | static CYBIKO_RS232 rs232; |
| 294 | |
| 295 | void cybiko_rs232_init( void) |
| 296 | { |
| 297 | _logerror( 0, "cybiko_rs232_init\n"); |
| 298 | memset( &rs232, 0, sizeof( rs232)); |
| 299 | // timer_pulse( TIME_IN_HZ( 10), 0, rs232_timer_callback); |
| 300 | } |
| 301 | |
| 302 | void cybiko_rs232_exit( void) |
| 303 | { |
| 304 | _logerror( 0, "cybiko_rs232_exit\n"); |
| 305 | } |
| 306 | |
| 307 | void cybiko_rs232_reset( void) |
| 308 | { |
| 309 | _logerror( 0, "cybiko_rs232_reset\n"); |
| 310 | } |
| 311 | |
| 312 | void cybiko_rs232_write_byte( UINT8 data) |
| 313 | { |
| 314 | #if 0 |
| 315 | printf( "%c", data); |
| 316 | #endif |
| 317 | } |
| 318 | |
| 319 | void cybiko_rs232_pin_sck( int data) |
| 320 | { |
| 321 | _logerror( 3, "cybiko_rs232_pin_sck (%d)\n", data); |
| 322 | // clock high-to-low |
| 323 | if ((rs232.pin.sck == 1) && (data == 0)) |
| 324 | { |
| 325 | // transmit |
| 326 | if (rs232.pin.txd) rs232.tx_byte = rs232.tx_byte | (1 << rs232.tx_bits); |
| 327 | rs232.tx_bits++; |
| 328 | if (rs232.tx_bits == 8) |
| 329 | { |
| 330 | rs232.tx_bits = 0; |
| 331 | cybiko_rs232_write_byte( rs232.tx_byte); |
| 332 | rs232.tx_byte = 0; |
| 333 | } |
| 334 | // receive |
| 335 | rs232.pin.rxd = (rs232.rx_byte >> rs232.rx_bits) & 1; |
| 336 | rs232.rx_bits++; |
| 337 | if (rs232.rx_bits == 8) |
| 338 | { |
| 339 | rs232.rx_bits = 0; |
| 340 | rs232.rx_byte = 0; |
| 341 | } |
| 342 | } |
| 343 | // save sck |
| 344 | rs232.pin.sck = data; |
| 345 | } |
| 346 | |
| 347 | void cybiko_rs232_pin_txd( int data) |
| 348 | { |
| 349 | _logerror( 3, "cybiko_rs232_pin_txd (%d)\n", data); |
| 350 | rs232.pin.txd = data; |
| 351 | } |
| 352 | |
| 353 | int cybiko_rs232_pin_rxd( void) |
| 354 | { |
| 355 | _logerror( 3, "cybiko_rs232_pin_rxd\n"); |
| 356 | return rs232.pin.rxd; |
| 357 | } |
| 358 | |
| 359 | int cybiko_rs232_rx_queue( void) |
| 360 | { |
| 361 | return 0; |
| 362 | } |
| 363 | |
| 364 | ///////////////////////// |
| 365 | // READ/WRITE HANDLERS // |
| 366 | ///////////////////////// |
| 367 | |
| 368 | READ16_HANDLER( cybiko_lcd_r ) |
| 369 | { |
| 370 | UINT16 data = 0; |
| 371 | if ACCESSING_MSB16 data = data | (hd66421_reg_idx_r() << 8); |
| 372 | if ACCESSING_LSB16 data = data | (hd66421_reg_dat_r() << 0); |
| 373 | return data; |
| 374 | } |
| 375 | |
| 376 | WRITE16_HANDLER( cybiko_lcd_w ) |
| 377 | { |
| 378 | if ACCESSING_MSB16 hd66421_reg_idx_w( (data >> 8) & 0xFF); |
| 379 | if ACCESSING_LSB16 hd66421_reg_dat_w( (data >> 0) & 0xFF); |
| 380 | } |
| 381 | |
| 382 | READ8_HANDLER( cybiko_key_r_byte ) |
| 383 | { |
| 384 | UINT8 data = 0xFF; |
| 385 | int i; |
| 386 | _logerror( 2, "cybiko_key_r_byte (%08X)\n", offset); |
| 387 | // A11 |
| 388 | if (!(offset & (1 << 11))) data &= 0xFE; |
| 389 | // A1 .. A9 |
| 390 | for (i=1;i<10;i++) if (!(offset & (1 << i))) data &= readinputport( i - 1); |
| 391 | // A0 |
| 392 | if (!(offset & (1 << 0))) data |= 0xFF; |
| 393 | // |
| 394 | return data; |
| 395 | } |
| 396 | |
| 397 | READ16_HANDLER( cybiko_key_r ) |
| 398 | { |
| 399 | UINT16 data = 0; |
| 400 | _logerror( 2, "cybiko_key_r (%08X/%04X)\n", offset, mem_mask); |
| 401 | if ACCESSING_MSB16 data = data | (cybiko_key_r_byte( offset * 2 + 0) << 8); |
| 402 | if ACCESSING_LSB16 data = data | (cybiko_key_r_byte( offset * 2 + 1) << 0); |
| 403 | _logerror( 2, "%04X\n", data); |
| 404 | return data; |
| 405 | } |
| 406 | |
| 407 | READ8_HANDLER( cybiko_io_reg_r ) |
| 408 | { |
| 409 | UINT8 data = 0; |
| 410 | _logerror( 2, "cybiko_io_reg_r (%08X)\n", offset); |
| 411 | switch (offset) |
| 412 | { |
| 413 | // keyboard |
| 414 | case H8S_IO_PORT1 : |
| 415 | { |
| 416 | //if (readinputport(0) & 0x02) data = data | 0x08; else data = data & (~0x08); // "esc" key |
| 417 | data = data | 0x08; |
| 418 | } |
| 419 | break; |
| 420 | // serial dataflash |
| 421 | case H8S_IO_PORT3 : if (at45dbxx_pin_so()) data = data | H8S_P3_RXD1; break; |
| 422 | // rs232 |
| 423 | case H8S_IO_PORT5 : if (cybiko_rs232_pin_rxd()) data = data | H8S_P5_RXD2; break; |
| 424 | // real-time clock |
| 425 | case H8S_IO_PORTF : |
| 426 | { |
| 427 | data = H8S_PF_PF2; |
| 428 | if (pcf8593_pin_sda_r()) data |= H8S_PF_PF0; |
| 429 | } |
| 430 | break; |
| 431 | // serial 2 |
| 432 | case H8S_IO_SSR2 : |
| 433 | { |
| 434 | if (cybiko_rs232_rx_queue()) data = data | H8S_SSR_RDRF; |
| 435 | } |
| 436 | break; |
| 437 | } |
| 438 | return data; |
| 439 | } |
| 440 | |
| 441 | WRITE8_HANDLER( cybiko_io_reg_w ) |
| 442 | { |
| 443 | _logerror( 2, "cybiko_io_reg_w (%08X/%02X)\n", offset, data); |
| 444 | switch (offset) |
| 445 | { |
| 446 | // speaker |
| 447 | case H8S_IO_P1DR : speaker_level_w( 0, (data & H8S_P1_TIOCB1) ? 1 : 0); break; |
| 448 | // serial dataflash |
| 449 | case H8S_IO_P3DR : |
| 450 | { |
| 451 | at45dbxx_pin_cs ( (data & H8S_P3_SCK0) ? 0 : 1); |
| 452 | at45dbxx_pin_si ( (data & H8S_P3_TXD1) ? 1 : 0); |
| 453 | at45dbxx_pin_sck( (data & H8S_P3_SCK1) ? 1 : 0); |
| 454 | } |
| 455 | break; |
| 456 | // rs232 |
| 457 | case H8S_IO_P5DR : |
| 458 | { |
| 459 | cybiko_rs232_pin_txd( (data & H8S_P5_TXD2) ? 1 : 0); |
| 460 | cybiko_rs232_pin_sck( (data & H8S_P5_SCK2) ? 1 : 0); |
| 461 | } |
| 462 | break; |
| 463 | // real-time clock |
| 464 | case H8S_IO_PFDR : pcf8593_pin_scl( (data & H8S_PF_PF1) ? 1 : 0); break; |
| 465 | case H8S_IO_PFDDR : pcf8593_pin_sda_w( (data & H8S_PF_PF0) ? 0 : 1); break; |
| 466 | } |
| 467 | } |
| 468 | |
| 469 | READ8_HANDLER( cybikov1_io_reg_r ) |
| 470 | { |
| 471 | _logerror( 2, "cybikov1_io_reg_r (%08X)\n", offset); |
| 472 | return cybiko_io_reg_r( offset); |
| 473 | } |
| 474 | |
| 475 | READ8_HANDLER( cybikov2_io_reg_r ) |
| 476 | { |
| 477 | _logerror( 2, "cybikov2_io_reg_r (%08X)\n", offset); |
| 478 | return cybiko_io_reg_r( offset); |
| 479 | } |
| 480 | |
| 481 | READ8_HANDLER( cybikoxt_io_reg_r ) |
| 482 | { |
| 483 | UINT8 data = 0; |
| 484 | _logerror( 2, "cybikoxt_io_reg_r (%08X)\n", offset); |
| 485 | switch (offset) |
| 486 | { |
| 487 | // rs232 |
| 488 | case H8S_IO_PORT3 : if (cybiko_rs232_pin_rxd()) data = data | H8S_P3_RXD1; break; |
| 489 | // default |
| 490 | default : data = cybiko_io_reg_r( offset); |
| 491 | } |
| 492 | return data; |
| 493 | } |
| 494 | |
| 495 | WRITE8_HANDLER( cybikov1_io_reg_w ) |
| 496 | { |
| 497 | _logerror( 2, "cybikov1_io_reg_w (%08X/%02X)\n", offset, data); |
| 498 | cybiko_io_reg_w( offset, data); |
| 499 | } |
| 500 | |
| 501 | WRITE8_HANDLER( cybikov2_io_reg_w ) |
| 502 | { |
| 503 | _logerror( 2, "cybikov2_io_reg_w (%08X/%02X)\n", offset, data); |
| 504 | cybiko_io_reg_w( offset, data); |
| 505 | } |
| 506 | |
| 507 | WRITE8_HANDLER( cybikoxt_io_reg_w ) |
| 508 | { |
| 509 | _logerror( 2, "cybikoxt_io_reg_w (%08X/%02X)\n", offset, data); |
| 510 | switch (offset) |
| 511 | { |
| 512 | // rs232 |
| 513 | case H8S_IO_P3DR : |
| 514 | { |
| 515 | cybiko_rs232_pin_txd( (data & H8S_P3_TXD1) ? 1 : 0); |
| 516 | cybiko_rs232_pin_sck( (data & H8S_P3_SCK1) ? 1 : 0); |
| 517 | } |
| 518 | break; |
| 519 | // default |
| 520 | default : cybiko_io_reg_w( offset, data); |
| 521 | } |
| 522 | } |
| 523 | |
| 524 | // Cybiko Xtreme writes following byte pairs to 0x200003/0x200000 |
| 525 | // 00/01, 00/C0, 0F/32, 0D/03, 0B/03, 09/50, 07/D6, 05/00, 04/00, 20/00, 23/08, 27/01, 2F/08, 2C/02, 2B/08, 28/01 |
| 526 | // 04/80, 05/02, 00/C8, 00/C8, 00/C0, 1B/2C, 00/01, 00/C0, 1B/6C, 0F/10, 0D/07, 0B/07, 09/D2, 07/D6, 05/00, 04/00, |
| 527 | // 20/00, 23/08, 27/01, 2F/08, 2C/02, 2B/08, 28/01, 37/08, 34/04, 33/08, 30/03, 04/80, 05/02, 1B/6C, 00/C8 |
| 528 | WRITE16_HANDLER( cybiko_unk1_w ) |
| 529 | { |
| 530 | if ACCESSING_MSB16 logerror( "[%08X] <- %02X\n", 0x200000 + offset * 2 + 0, (data >> 8) & 0xFF); |
| 531 | if ACCESSING_LSB16 logerror( "[%08X] <- %02X\n", 0x200000 + offset * 2 + 1, (data >> 0) & 0xFF); |
| 532 | } |
| 533 | |
| 534 | READ16_HANDLER( cybiko_unk2_r ) |
| 535 | { |
| 536 | switch (offset << 1) |
| 537 | { |
| 538 | case 0x000 : return 0xBA0B; break; // magic (part 1) |
| 539 | case 0x002 : return 0xAB15; break; // magic (part 2) |
| 540 | case 0x004 : return (0x07 << 8) | (0x07 ^0xFF); break; // brightness (or contrast) & value xor FF |
| 541 | // case 0x006 : return 0x2B57; break; // do not show "Free Games and Applications at www.cybiko.com" screen |
| 542 | case 0x008 : return 0xDEBA; break; // enable debug output |
| 543 | case 0x016 : return 0x5000 | 0x03FF; break; // ? |
| 544 | case 0x7FC : return 0x22A1; break; // crc32 (part 1) |
| 545 | case 0x7FE : return 0x8728; break; // crc32 (part 2) |
| 546 | default : return 0xFFFF; break; |
| 547 | } |
| 548 | } |
src/mess/drivers/cybiko.c
| r882 | r883 | |
| 1 | | /*
|
| 2 | | |
| 3 | | Cybiko Wireless Inter-tainment System
|
| 4 | | |
| 5 | | (c) 2001-2007 Tim Schuerewegen
|
| 6 | | |
| 7 | | Cybiko Classic (V1)
|
| 8 | | Cybiko Classic (V2)
|
| 9 | | Cybiko Xtreme
|
| 10 | | |
| 11 | | */
|
| 12 | | |
| 13 | | #include "includes/cybiko.h"
|
| 14 | | |
| 15 | | #include "driver.h"
|
| 16 | | #include "cpu/h8s2xxx/h8s2xxx.h"
|
| 17 | | #include "video/hd66421.h"
|
| 18 | | #include "inputx.h"
|
| 19 | | #include "cybiko.lh"
|
| 20 | | |
| 21 | | // +------------------------------------------------------+
|
| 22 | | // | Cybiko Classic (CY6411) | V2 |
|
| 23 | | // +------------------------------------------------------+
|
| 24 | | // | - CYBIKO | CY-OS 1.1.7 | 6432241M04FA | 0028R JAPAN |
|
| 25 | | // | - SST 39VF020 | 90-4C-WH | 0012175-D |
|
| 26 | | // | - ATMEL 0027 | AT90S2313-4SC |
|
| 27 | | // | - ATMEL | AT45DB041A | TC | 0027 |
|
| 28 | | // | - RF2915 | RFMD0028 | 0F540BT |
|
| 29 | | // | - EliteMT | LP62S2048X-70LLT | 0026B H4A27HA |
|
| 30 | | // | - MP02AB | LMX2315 | TMD |
|
| 31 | | // +------------------------------------------------------+
|
| 32 | | |
| 33 | | // +------------------------------------------------------+
|
| 34 | | // | Cybiko Xtreme (CY44802) |
|
| 35 | | // +------------------------------------------------------+
|
| 36 | | // | - CYBIKO | CYBOOT 1.5A | HD6432323G03F | 0131 JAPAN |
|
| 37 | | // | - SST 39VF400A | 70-4C-EK |
|
| 38 | | // | - ATMEL 0033 | AT90S2313-4SC |
|
| 39 | | // | - SAMSUNG 129 | K4F171612D-TL60 |
|
| 40 | | // | - 2E16AB | USBN9604-28M | NSC00A1 |
|
| 41 | | // +------------------------------------------------------+
|
| 42 | | |
| 43 | | // +------------------------------------------------------+
|
| 44 | | // | Cybiko MP3 Player (CY65P10) |
|
| 45 | | // +------------------------------------------------------+
|
| 46 | | // | - H8S/2246 | 0G1 | HD6472246FA20 | JAPAN |
|
| 47 | | // | - MICRONAS | DAC3550A C2 | 0394 22 HM U | 089472.000 |
|
| 48 | | // | - 2E08AJ | USBN9603-28M | NSC99A1 |
|
| 49 | | // +------------------------------------------------------+
|
| 50 | | |
| 51 | | ///////////////////////////
|
| 52 | | // ADDRESS MAP - PROGRAM //
|
| 53 | | ///////////////////////////
|
| 54 | | |
| 55 | | #define AM_RANGE_SL( start, length) \
|
| 56 | | AM_RANGE( start, start + length - 1)
|
| 57 | | |
| 58 | | // 512 kbyte ram + no memory mapped flash
|
| 59 | | ADDRESS_MAP_START( cybikov1_mem, ADDRESS_SPACE_PROGRAM, 16 )
|
| 60 | | AM_RANGE_SL( 0x000000, 0x008000) AM_ROM
|
| 61 | | // AM_RANGE_SL( 0x200000, 0x080000) AM_RAM AM_MIRROR( 0x180000)
|
| 62 | | AM_RANGE_SL( 0x600000, 0x000002) AM_READWRITE( cybiko_lcd_r, cybiko_lcd_w)
|
| 63 | | AM_RANGE_SL( 0xE00000, 0x008000) AM_READ( cybiko_key_r)
|
| 64 | | ADDRESS_MAP_END
|
| 65 | | |
| 66 | | // +-------------------------------------+
|
| 67 | | // | Cybiko Classic (V2) - Memory Map |
|
| 68 | | // +-------------------------------------+
|
| 69 | | // | 000000 - 007FFF | rom |
|
| 70 | | // | 008000 - 00FFFF | 17 51 17 51 .. |
|
| 71 | | // | 010000 - 0FFFFF | flash mirror |
|
| 72 | | // | 100000 - 13FFFF | flash |
|
| 73 | | // | 140000 - 1FFFFF | flash mirror |
|
| 74 | | // | 200000 - 23FFFF | ram |
|
| 75 | | // | 240000 - 3FFFFF | ram mirror |
|
| 76 | | // | 400000 - 5FFFFF | FF FF FF FF .. |
|
| 77 | | // | 600000 - 600001 | lcd |
|
| 78 | | // | 600002 - DFFFFF | FF FF FF FF .. |
|
| 79 | | // | E00000 - FFDBFF | keyboard |
|
| 80 | | // | FFDC00 - FFFFFF | onchip ram & regs |
|
| 81 | | // +-------------------------------------+
|
| 82 | | |
| 83 | | // 256 kbyte ram + 256 kbyte memory mapped flash
|
| 84 | | ADDRESS_MAP_START( cybikov2_mem, ADDRESS_SPACE_PROGRAM, 16 )
|
| 85 | | AM_RANGE_SL( 0x000000, 0x008000) AM_ROM
|
| 86 | | AM_RANGE_SL( 0x100000, 0x040000) AM_READ( MRA16_BANK2) AM_MIRROR( 0x0C0000)
|
| 87 | | // AM_RANGE_SL( 0x200000, 0x040000) AM_RAM AM_MIRROR( 0x1C0000)
|
| 88 | | AM_RANGE_SL( 0x600000, 0x000002) AM_READWRITE( cybiko_lcd_r, cybiko_lcd_w)
|
| 89 | | AM_RANGE_SL( 0xE00000, 0x1FDC00) AM_READ( cybiko_key_r)
|
| 90 | | ADDRESS_MAP_END
|
| 91 | | |
| 92 | | // 2048? kbyte ram + 512 kbyte memory mapped flash
|
| 93 | | ADDRESS_MAP_START( cybikoxt_mem, ADDRESS_SPACE_PROGRAM, 16 )
|
| 94 | | AM_RANGE_SL( 0x000000, 0x008000) AM_ROM
|
| 95 | | AM_RANGE_SL( 0x100000, 0x000002) AM_READWRITE( cybiko_lcd_r, cybiko_lcd_w)
|
| 96 | | AM_RANGE_SL( 0x200000, 0x000004) AM_WRITE( cybiko_unk1_w)
|
| 97 | | // AM_RANGE_SL( 0x400000, 0x200000) AM_RAM
|
| 98 | | AM_RANGE_SL( 0x600000, 0x080000) AM_READ( MRA16_BANK2)
|
| 99 | | AM_RANGE_SL( 0x7FF800, 0x000800) AM_READ( cybiko_unk2_r)
|
| 100 | | AM_RANGE_SL( 0xE00000, 0x1FDC00) AM_READ( cybiko_key_r)
|
| 101 | | ADDRESS_MAP_END
|
| 102 | | |
| 103 | | //////////////////////
|
| 104 | | // ADDRESS MAP - IO //
|
| 105 | | //////////////////////
|
| 106 | | |
| 107 | | ADDRESS_MAP_START( cybikov1_io, ADDRESS_SPACE_IO, 8 )
|
| 108 | | AM_RANGE( 0xFFFE40, 0xFFFFFF) AM_READWRITE( cybikov1_io_reg_r, cybikov1_io_reg_w)
|
| 109 | | ADDRESS_MAP_END
|
| 110 | | |
| 111 | | ADDRESS_MAP_START( cybikov2_io, ADDRESS_SPACE_IO, 8 )
|
| 112 | | AM_RANGE( 0xFFFE40, 0xFFFFFF) AM_READWRITE( cybikov2_io_reg_r, cybikov2_io_reg_w)
|
| 113 | | ADDRESS_MAP_END
|
| 114 | | |
| 115 | | ADDRESS_MAP_START( cybikoxt_io, ADDRESS_SPACE_IO, 8 )
|
| 116 | | AM_RANGE( 0xFFFE40, 0xFFFFFF) AM_READWRITE( cybikoxt_io_reg_r, cybikoxt_io_reg_w)
|
| 117 | | ADDRESS_MAP_END
|
| 118 | | |
| 119 | | /////////////////
|
| 120 | | // INPUT PORTS //
|
| 121 | | /////////////////
|
| 122 | | |
| 123 | | #define CYBIKO_PORT_BIT_K( mask) \
|
| 124 | | PORT_BIT( mask, IP_ACTIVE_LOW, IPT_KEYBOARD)
|
| 125 | | |
| 126 | | #define CYBIKO_PORT_BIT_U( mask) \
|
| 127 | | PORT_BIT( mask, IP_ACTIVE_LOW, IPT_UNUSED)
|
| 128 | | |
| 129 | | INPUT_PORTS_START( cybiko)
|
| 130 | | PORT_START // A1
|
| 131 | | CYBIKO_PORT_BIT_K( 0x01) PORT_NAME( "F7" ) PORT_CODE( KEYCODE_F7 ) PORT_CHAR( UCHAR_MAMEKEY( F7 ))
|
| 132 | | CYBIKO_PORT_BIT_K( 0x02) PORT_NAME( "Esc" ) PORT_CODE( KEYCODE_ESC ) PORT_CHAR( UCHAR_MAMEKEY( ESC ))
|
| 133 | | CYBIKO_PORT_BIT_K( 0x04) PORT_NAME( "Del" ) PORT_CODE( KEYCODE_DEL ) PORT_CHAR( UCHAR_MAMEKEY( DEL ))
|
| 134 | | CYBIKO_PORT_BIT_K( 0x08) PORT_NAME( "Left" ) PORT_CODE( KEYCODE_LEFT ) PORT_CHAR( UCHAR_MAMEKEY( LEFT ))
|
| 135 | | CYBIKO_PORT_BIT_K( 0x10) PORT_NAME( "Q" ) PORT_CODE( KEYCODE_Q ) PORT_CHAR( 'Q' )
|
| 136 | | CYBIKO_PORT_BIT_K( 0x20) PORT_NAME( "A" ) PORT_CODE( KEYCODE_A ) PORT_CHAR( 'A' )
|
| 137 | | CYBIKO_PORT_BIT_K( 0x40) PORT_NAME( "`" ) PORT_CHAR( '`' )
|
| 138 | | CYBIKO_PORT_BIT_K( 0x80) PORT_NAME( "Shift" ) PORT_CODE( KEYCODE_LSHIFT ) PORT_CHAR( UCHAR_SHIFT_1 )
|
| 139 | | PORT_START // A2
|
| 140 | | CYBIKO_PORT_BIT_K( 0x01) PORT_NAME( "F6" ) PORT_CODE( KEYCODE_F6 ) PORT_CHAR( UCHAR_MAMEKEY( F6 ))
|
| 141 | | CYBIKO_PORT_BIT_K( 0x02) PORT_NAME( "Up" ) PORT_CODE( KEYCODE_UP ) PORT_CHAR( UCHAR_MAMEKEY( UP ))
|
| 142 | | CYBIKO_PORT_BIT_K( 0x04) PORT_NAME( "Ins" ) PORT_CODE( KEYCODE_INSERT ) PORT_CHAR( UCHAR_MAMEKEY( INSERT))
|
| 143 | | CYBIKO_PORT_BIT_K( 0x08) PORT_NAME( "2 @" ) PORT_CODE( KEYCODE_2 ) PORT_CHAR( '2' ) PORT_CHAR( '@')
|
| 144 | | CYBIKO_PORT_BIT_K( 0x10) PORT_NAME( "W" ) PORT_CODE( KEYCODE_W ) PORT_CHAR( 'W' )
|
| 145 | | CYBIKO_PORT_BIT_K( 0x20) PORT_NAME( "S" ) PORT_CODE( KEYCODE_S ) PORT_CHAR( 'S' )
|
| 146 | | CYBIKO_PORT_BIT_K( 0x40) PORT_NAME( "Z" ) PORT_CODE( KEYCODE_Z ) PORT_CHAR( 'Z' )
|
| 147 | | CYBIKO_PORT_BIT_K( 0x80) PORT_NAME( "Fn" ) PORT_CODE( KEYCODE_LCONTROL ) PORT_CHAR( UCHAR_SHIFT_2 )
|
| 148 | | PORT_START // A3
|
| 149 | | CYBIKO_PORT_BIT_K( 0x01) PORT_NAME( "F5" ) PORT_CODE( KEYCODE_F5 ) PORT_CHAR( UCHAR_MAMEKEY( F5 ))
|
| 150 | | CYBIKO_PORT_BIT_K( 0x02) PORT_NAME( "F3" ) PORT_CODE( KEYCODE_F3 ) PORT_CHAR( UCHAR_MAMEKEY( F3 ))
|
| 151 | | CYBIKO_PORT_BIT_K( 0x04) PORT_NAME( "Space" ) PORT_CODE( KEYCODE_SPACE ) PORT_CHAR( ' ' )
|
| 152 | | CYBIKO_PORT_BIT_K( 0x08) PORT_NAME( "3 #" ) PORT_CODE( KEYCODE_3 ) PORT_CHAR( '3' ) PORT_CHAR( '#')
|
| 153 | | CYBIKO_PORT_BIT_K( 0x10) PORT_NAME( "E" ) PORT_CODE( KEYCODE_E ) PORT_CHAR( 'E' )
|
| 154 | | CYBIKO_PORT_BIT_K( 0x20) PORT_NAME( "D" ) PORT_CODE( KEYCODE_D ) PORT_CHAR( 'D' )
|
| 155 | | CYBIKO_PORT_BIT_K( 0x40) PORT_NAME( "X" ) PORT_CODE( KEYCODE_X ) PORT_CHAR( 'X' )
|
| 156 | | CYBIKO_PORT_BIT_K( 0x80) PORT_NAME( "Help" ) PORT_CODE( KEYCODE_END ) PORT_CHAR( UCHAR_MAMEKEY( END ))
|
| 157 | | PORT_START // A4
|
| 158 | | CYBIKO_PORT_BIT_K( 0x01) PORT_NAME( "F4" ) PORT_CODE( KEYCODE_F4 ) PORT_CHAR( UCHAR_MAMEKEY( F4 ))
|
| 159 | | CYBIKO_PORT_BIT_K( 0x02) PORT_NAME( "1 !" ) PORT_CODE( KEYCODE_1 ) PORT_CHAR( '1' ) PORT_CHAR( '!')
|
| 160 | | CYBIKO_PORT_BIT_K( 0x04) PORT_NAME( "Tab" ) PORT_CODE( KEYCODE_TAB ) PORT_CHAR( 9 )
|
| 161 | | CYBIKO_PORT_BIT_K( 0x08) PORT_NAME( "4 $" ) PORT_CODE( KEYCODE_4 ) PORT_CHAR( '4' ) PORT_CHAR( '$')
|
| 162 | | CYBIKO_PORT_BIT_K( 0x10) PORT_NAME( "R" ) PORT_CODE( KEYCODE_R ) PORT_CHAR( 'R' )
|
| 163 | | CYBIKO_PORT_BIT_K( 0x20) PORT_NAME( "F" ) PORT_CODE( KEYCODE_F ) PORT_CHAR( 'F' )
|
| 164 | | CYBIKO_PORT_BIT_K( 0x40) PORT_NAME( "C" ) PORT_CODE( KEYCODE_C ) PORT_CHAR( 'C' )
|
| 165 | | CYBIKO_PORT_BIT_K( 0x80) PORT_NAME( "[ {" ) PORT_CODE( KEYCODE_OPENBRACE ) PORT_CHAR( '[' )
|
| 166 | | PORT_START // A5
|
| 167 | | CYBIKO_PORT_BIT_K( 0x01) PORT_NAME( "Right" ) PORT_CODE( KEYCODE_RIGHT ) PORT_CHAR( UCHAR_MAMEKEY( RIGHT ))
|
| 168 | | CYBIKO_PORT_BIT_K( 0x02) PORT_NAME( "Down" ) PORT_CODE( KEYCODE_DOWN ) PORT_CHAR( UCHAR_MAMEKEY( DOWN ))
|
| 169 | | CYBIKO_PORT_BIT_K( 0x04) PORT_NAME( "Select") PORT_CODE( KEYCODE_HOME ) PORT_CHAR( UCHAR_MAMEKEY( HOME ))
|
| 170 | | CYBIKO_PORT_BIT_K( 0x08) PORT_NAME( "5 %" ) PORT_CODE( KEYCODE_5 ) PORT_CHAR( '5' ) PORT_CHAR( '%')
|
| 171 | | CYBIKO_PORT_BIT_K( 0x10) PORT_NAME( "T" ) PORT_CODE( KEYCODE_T ) PORT_CHAR( 'T' )
|
| 172 | | CYBIKO_PORT_BIT_K( 0x20) PORT_NAME( "G" ) PORT_CODE( KEYCODE_G ) PORT_CHAR( 'G' )
|
| 173 | | CYBIKO_PORT_BIT_K( 0x40) PORT_NAME( "V" ) PORT_CODE( KEYCODE_V ) PORT_CHAR( 'V' )
|
| 174 | | CYBIKO_PORT_BIT_K( 0x80) PORT_NAME( "] }" ) PORT_CODE( KEYCODE_CLOSEBRACE) PORT_CHAR( ']' )
|
| 175 | | PORT_START // A6
|
| 176 | | CYBIKO_PORT_BIT_K( 0x01) PORT_NAME( "F2" ) PORT_CODE( KEYCODE_F2 ) PORT_CHAR( UCHAR_MAMEKEY( F2 ))
|
| 177 | | CYBIKO_PORT_BIT_K( 0x02) PORT_NAME( "; :" ) PORT_CODE( KEYCODE_COLON ) PORT_CHAR( ';' ) PORT_CHAR( ':')
|
| 178 | | CYBIKO_PORT_BIT_K( 0x04) PORT_NAME( "Enter" ) PORT_CODE( KEYCODE_ENTER ) PORT_CHAR( 13 )
|
| 179 | | CYBIKO_PORT_BIT_K( 0x08) PORT_NAME( "6 ^" ) PORT_CODE( KEYCODE_6 ) PORT_CHAR( '6' )
|
| 180 | | CYBIKO_PORT_BIT_K( 0x10) PORT_NAME( "Y" ) PORT_CODE( KEYCODE_Y ) PORT_CHAR( 'Y' )
|
| 181 | | CYBIKO_PORT_BIT_K( 0x20) PORT_NAME( "H" ) PORT_CODE( KEYCODE_H ) PORT_CHAR( 'H' )
|
| 182 | | CYBIKO_PORT_BIT_K( 0x40) PORT_NAME( "B" ) PORT_CODE( KEYCODE_B ) PORT_CHAR( 'B' )
|
| 183 | | CYBIKO_PORT_BIT_K( 0x80) PORT_NAME( "\\ |" ) PORT_CODE( KEYCODE_BACKSLASH ) PORT_CHAR( '\\' ) PORT_CHAR( '|')
|
| 184 | | PORT_START // A7
|
| 185 | | CYBIKO_PORT_BIT_K( 0x01) PORT_NAME( "F1" ) PORT_CODE( KEYCODE_F1 ) PORT_CHAR( UCHAR_MAMEKEY( F1 ))
|
| 186 | | CYBIKO_PORT_BIT_K( 0x02) PORT_NAME( "/ ?" ) PORT_CODE( KEYCODE_SLASH ) PORT_CHAR( '/' ) PORT_CHAR( '?')
|
| 187 | | CYBIKO_PORT_BIT_K( 0x04) PORT_NAME( "BkSp" ) PORT_CODE( KEYCODE_BACKSPACE ) PORT_CHAR( 8 )
|
| 188 | | CYBIKO_PORT_BIT_K( 0x08) PORT_NAME( "7 &" ) PORT_CODE( KEYCODE_7 ) PORT_CHAR( '7' ) PORT_CHAR( '&')
|
| 189 | | CYBIKO_PORT_BIT_K( 0x10) PORT_NAME( "U" ) PORT_CODE( KEYCODE_U ) PORT_CHAR( 'U' )
|
| 190 | | CYBIKO_PORT_BIT_K( 0x20) PORT_NAME( "J" ) PORT_CODE( KEYCODE_J ) PORT_CHAR( 'J' )
|
| 191 | | CYBIKO_PORT_BIT_K( 0x40) PORT_NAME( "N" ) PORT_CODE( KEYCODE_N ) PORT_CHAR( 'N' )
|
| 192 | | CYBIKO_PORT_BIT_U( 0x80)
|
| 193 | | PORT_START // A8
|
| 194 | | CYBIKO_PORT_BIT_K( 0x01) PORT_NAME( "- _" ) PORT_CODE( KEYCODE_MINUS ) PORT_CHAR( '-' ) PORT_CHAR( '_')
|
| 195 | | CYBIKO_PORT_BIT_K( 0x02) PORT_NAME( ". >" ) PORT_CHAR( '.' ) PORT_CHAR( '>')
|
| 196 | | CYBIKO_PORT_BIT_K( 0x04) PORT_NAME( "0 )" ) PORT_CODE( KEYCODE_0 ) PORT_CHAR( '0' ) PORT_CHAR( ')')
|
| 197 | | CYBIKO_PORT_BIT_K( 0x08) PORT_NAME( "8 *" ) PORT_CODE( KEYCODE_8 ) PORT_CHAR( '8' ) PORT_CHAR( '*')
|
| 198 | | CYBIKO_PORT_BIT_K( 0x10) PORT_NAME( "I" ) PORT_CODE( KEYCODE_I ) PORT_CHAR( 'I' )
|
| 199 | | CYBIKO_PORT_BIT_K( 0x20) PORT_NAME( "K" ) PORT_CODE( KEYCODE_K ) PORT_CHAR( 'K' )
|
| 200 | | CYBIKO_PORT_BIT_K( 0x40) PORT_NAME( "M" ) PORT_CODE( KEYCODE_M ) PORT_CHAR( 'M' )
|
| 201 | | CYBIKO_PORT_BIT_U( 0x80)
|
| 202 | | PORT_START // A9
|
| 203 | | CYBIKO_PORT_BIT_K( 0x01) PORT_NAME( "' \"" ) PORT_CODE( KEYCODE_QUOTE ) PORT_CHAR( '\'' ) PORT_CHAR( '"')
|
| 204 | | CYBIKO_PORT_BIT_K( 0x02) PORT_NAME( "= +" ) PORT_CODE( KEYCODE_EQUALS ) PORT_CHAR( '=' ) PORT_CHAR( '+')
|
| 205 | | CYBIKO_PORT_BIT_K( 0x04) PORT_NAME( "9 (" ) PORT_CODE( KEYCODE_9 ) PORT_CHAR( '9' ) PORT_CHAR( '(')
|
| 206 | | CYBIKO_PORT_BIT_K( 0x08) PORT_NAME( "P" ) PORT_CODE( KEYCODE_P ) PORT_CHAR( 'P' )
|
| 207 | | CYBIKO_PORT_BIT_K( 0x10) PORT_NAME( "O" ) PORT_CODE( KEYCODE_O ) PORT_CHAR( 'O' )
|
| 208 | | CYBIKO_PORT_BIT_K( 0x20) PORT_NAME( "L" ) PORT_CODE( KEYCODE_L ) PORT_CHAR( 'L' )
|
| 209 | | CYBIKO_PORT_BIT_K( 0x40) PORT_NAME( ", <" ) PORT_CODE( KEYCODE_COMMA ) PORT_CHAR( ',' ) PORT_CHAR( '<')
|
| 210 | | CYBIKO_PORT_BIT_U( 0x80)
|
| 211 | | INPUT_PORTS_END
|
| 212 | | |
| 213 | | /////////
|
| 214 | | // ROM //
|
| 215 | | /////////
|
| 216 | | |
| 217 | | ROM_START( cybikov1 )
|
| 218 | | ROM_REGION( 0x8000, REGION_CPU1, 0)
|
| 219 | | ROM_LOAD( "cyrom112.bin", 0, 0x8000, CRC(9E1F1A0F) SHA1(6FC08DE6B2C67D884EC78F748E4A4BAD27EE8045))
|
| 220 | | ROM_END
|
| 221 | | |
| 222 | | ROM_START( cybikov2 )
|
| 223 | | ROM_REGION( 0x8000, REGION_CPU1, 0)
|
| 224 | | ROM_LOAD( "cyrom117.bin", 0, 0x8000, CRC(268DA7BF) SHA1(135EAF9E3905E69582AABD9B06BC4DE0A66780D5))
|
| 225 | | ROM_END
|
| 226 | | |
| 227 | | ROM_START( cybikoxt )
|
| 228 | | ROM_REGION( 0x8000, REGION_CPU1, 0)
|
| 229 | | ROM_LOAD( "cyrom150.bin", 0, 0x8000, CRC(18B9B21F) SHA1(28868D6174EB198A6CEC6C3C70B6E494517229B9))
|
| 230 | | ROM_END
|
| 231 | | |
| 232 | | ///////////////////
|
| 233 | | // SYSTEM CONFIG //
|
| 234 | | ///////////////////
|
| 235 | | |
| 236 | | SYSTEM_CONFIG_START( cybikov1 )
|
| 237 | | CONFIG_RAM_DEFAULT( 512 * 1024)
|
| 238 | | CONFIG_RAM( 1024 * 1024)
|
| 239 | | SYSTEM_CONFIG_END
|
| 240 | | |
| 241 | | SYSTEM_CONFIG_START( cybikov2 )
|
| 242 | | CONFIG_RAM_DEFAULT( 256 * 1024)
|
| 243 | | CONFIG_RAM( 512 * 1024)
|
| 244 | | CONFIG_RAM( 1024 * 1024)
|
| 245 | | SYSTEM_CONFIG_END
|
| 246 | | |
| 247 | | SYSTEM_CONFIG_START( cybikoxt )
|
| 248 | | CONFIG_RAM_DEFAULT( 2048 * 1024)
|
| 249 | | SYSTEM_CONFIG_END
|
| 250 | | |
| 251 | | ////////////////////
|
| 252 | | // MACHINE DRIVER //
|
| 253 | | ////////////////////
|
| 254 | | |
| 255 | | MACHINE_DRIVER_START( cybikov1 )
|
| 256 | | // cpu
|
| 257 | | MDRV_CPU_ADD_TAG( "main", H8S2241, 11059200)
|
| 258 | | MDRV_CPU_PROGRAM_MAP( cybikov1_mem, 0)
|
| 259 | | MDRV_CPU_IO_MAP( cybikov1_io, 0)
|
| 260 | | // screen
|
| 261 | | MDRV_SCREEN_REFRESH_RATE( 60)
|
| 262 | | MDRV_SCREEN_FORMAT( BITMAP_FORMAT_INDEXED16)
|
| 263 | | MDRV_SCREEN_SIZE( HD66421_WIDTH, HD66421_HEIGHT)
|
| 264 | | MDRV_SCREEN_VISIBLE_AREA( 0, HD66421_WIDTH - 1, 0, HD66421_HEIGHT - 1)
|
| 265 | | // video
|
| 266 | | MDRV_VIDEO_ATTRIBUTES( VIDEO_TYPE_RASTER)
|
| 267 | | MDRV_PALETTE_LENGTH( 4)
|
| 268 | | MDRV_COLORTABLE_LENGTH( 4)
|
| 269 | | MDRV_PALETTE_INIT( hd66421)
|
| 270 | | MDRV_VIDEO_START( hd66421)
|
| 271 | | MDRV_VIDEO_UPDATE( hd66421)
|
| 272 | | MDRV_DEFAULT_LAYOUT( layout_cybiko)
|
| 273 | | // sound
|
| 274 | | MDRV_SPEAKER_STANDARD_MONO( "mono")
|
| 275 | | MDRV_SOUND_ADD_TAG( "speaker", SPEAKER, 0)
|
| 276 | | MDRV_SOUND_ROUTE( ALL_OUTPUTS, "mono", 1.00)
|
| 277 | | // machine
|
| 278 | | MDRV_MACHINE_START( cybikov1)
|
| 279 | | MDRV_MACHINE_RESET( cybikov1)
|
| 280 | | // non-volatile ram
|
| 281 | | // MDRV_NVRAM_HANDLER( cybikov1)
|
| 282 | | MACHINE_DRIVER_END
|
| 283 | | |
| 284 | | MACHINE_DRIVER_START( cybikov2 )
|
| 285 | | // import
|
| 286 | | MDRV_IMPORT_FROM( cybikov1)
|
| 287 | | // cpu
|
| 288 | | MDRV_CPU_REPLACE( "main", H8S2246, 11059200)
|
| 289 | | MDRV_CPU_PROGRAM_MAP( cybikov2_mem, 0)
|
| 290 | | MDRV_CPU_IO_MAP( cybikov2_io, 0)
|
| 291 | | // machine
|
| 292 | | MDRV_MACHINE_START( cybikov2)
|
| 293 | | MDRV_MACHINE_RESET( cybikov2)
|
| 294 | | // non-volatile ram
|
| 295 | | // MDRV_NVRAM_HANDLER( cybikov2)
|
| 296 | | MACHINE_DRIVER_END
|
| 297 | | |
| 298 | | MACHINE_DRIVER_START( cybikoxt )
|
| 299 | | // import
|
| 300 | | MDRV_IMPORT_FROM( cybikov1)
|
| 301 | | // cpu
|
| 302 | | MDRV_CPU_REPLACE( "main", H8S2323, 18432000)
|
| 303 | | MDRV_CPU_PROGRAM_MAP( cybikoxt_mem, 0)
|
| 304 | | MDRV_CPU_IO_MAP( cybikoxt_io, 0)
|
| 305 | | // sound
|
| 306 | | MDRV_SPEAKER_REMOVE( "mono")
|
| 307 | | MDRV_SOUND_REMOVE( "speaker")
|
| 308 | | // machine
|
| 309 | | MDRV_MACHINE_START( cybikoxt)
|
| 310 | | MDRV_MACHINE_RESET( cybikoxt)
|
| 311 | | // non-volatile ram
|
| 312 | | // MDRV_NVRAM_HANDLER( cybikoxt)
|
| 313 | | MACHINE_DRIVER_END
|
| 314 | | |
| 315 | | //////////////
|
| 316 | | // COMPUTER //
|
| 317 | | //////////////
|
| 318 | | |
| 319 | | // YEAR - NAME - PARENT - BIOS - COMPAT - MACHINE - INPUT - INIT - CONFIG - COMPANY - FULLNAME - FLAGS
|
| 320 | | COMPB( 2000, cybikov1, 0, 0, 0, cybikov1, cybiko, cybikov1, cybikov1, "Cybiko, Inc.", "Cybiko Classic (V1)", GAME_IMPERFECT_SOUND)
|
| 321 | | COMPB( 2000, cybikov2, cybikov1, 0, 0, cybikov2, cybiko, cybikov2, cybikov2, "Cybiko, Inc.", "Cybiko Classic (V2)", GAME_IMPERFECT_SOUND)
|
| 322 | | COMPB( 2001, cybikoxt, cybikov1, 0, 0, cybikoxt, cybiko, cybikoxt, cybikoxt, "Cybiko, Inc.", "Cybiko Xtreme", GAME_NO_SOUND | GAME_NOT_WORKING)
|
| 1 | /* |
| 2 | |
| 3 | Cybiko Wireless Inter-tainment System |
| 4 | |
| 5 | (c) 2001-2007 Tim Schuerewegen |
| 6 | |
| 7 | Cybiko Classic (V1) |
| 8 | Cybiko Classic (V2) |
| 9 | Cybiko Xtreme |
| 10 | |
| 11 | */ |
| 12 | |
| 13 | #include "includes/cybiko.h" |
| 14 | |
| 15 | #include "driver.h" |
| 16 | #include "cpu/h8s2xxx/h8s2xxx.h" |
| 17 | #include "video/hd66421.h" |
| 18 | #include "inputx.h" |
| 19 | #include "cybiko.lh" |
| 20 | |
| 21 | // +------------------------------------------------------+ |
| 22 | // | Cybiko Classic (CY6411) | V2 | |
| 23 | // +------------------------------------------------------+ |
| 24 | // | - CYBIKO | CY-OS 1.1.7 | 6432241M04FA | 0028R JAPAN | |
| 25 | // | - SST 39VF020 | 90-4C-WH | 0012175-D | |
| 26 | // | - ATMEL 0027 | AT90S2313-4SC | |
| 27 | // | - ATMEL | AT45DB041A | TC | 0027 | |
| 28 | // | - RF2915 | RFMD0028 | 0F540BT | |
| 29 | // | - EliteMT | LP62S2048X-70LLT | 0026B H4A27HA | |
| 30 | // | - MP02AB | LMX2315 | TMD | |
| 31 | // +------------------------------------------------------+ |
| 32 | |
| 33 | // +------------------------------------------------------+ |
| 34 | // | Cybiko Xtreme (CY44802) | |
| 35 | // +------------------------------------------------------+ |
| 36 | // | - CYBIKO | CYBOOT 1.5A | HD6432323G03F | 0131 JAPAN | |
| 37 | // | - SST 39VF400A | 70-4C-EK | |
| 38 | // | - ATMEL 0033 | AT90S2313-4SC | |
| 39 | // | - SAMSUNG 129 | K4F171612D-TL60 | |
| 40 | // | - 2E16AB | USBN9604-28M | NSC00A1 | |
| 41 | // +------------------------------------------------------+ |
| 42 | |
| 43 | // +------------------------------------------------------+ |
| 44 | // | Cybiko MP3 Player (CY65P10) | |
| 45 | // +------------------------------------------------------+ |
| 46 | // | - H8S/2246 | 0G1 | HD6472246FA20 | JAPAN | |
| 47 | // | - MICRONAS | DAC3550A C2 | 0394 22 HM U | 089472.000 | |
| 48 | // | - 2E08AJ | USBN9603-28M | NSC99A1 | |
| 49 | // +------------------------------------------------------+ |
| 50 | |
| 51 | /////////////////////////// |
| 52 | // ADDRESS MAP - PROGRAM // |
| 53 | /////////////////////////// |
| 54 | |
| 55 | #define AM_RANGE_SL( start, length) \ |
| 56 | AM_RANGE( start, start + length - 1) |
| 57 | |
| 58 | // 512 kbyte ram + no memory mapped flash |
| 59 | ADDRESS_MAP_START( cybikov1_mem, ADDRESS_SPACE_PROGRAM, 16 ) |
| 60 | AM_RANGE_SL( 0x000000, 0x008000) AM_ROM |
| 61 | // AM_RANGE_SL( 0x200000, 0x080000) AM_RAM AM_MIRROR( 0x180000) |
| 62 | AM_RANGE_SL( 0x600000, 0x000002) AM_READWRITE( cybiko_lcd_r, cybiko_lcd_w) |
| 63 | AM_RANGE_SL( 0xE00000, 0x008000) AM_READ( cybiko_key_r) |
| 64 | ADDRESS_MAP_END |
| 65 | |
| 66 | // +-------------------------------------+ |
| 67 | // | Cybiko Classic (V2) - Memory Map | |
| 68 | // +-------------------------------------+ |
| 69 | // | 000000 - 007FFF | rom | |
| 70 | // | 008000 - 00FFFF | 17 51 17 51 .. | |
| 71 | // | 010000 - 0FFFFF | flash mirror | |
| 72 | // | 100000 - 13FFFF | flash | |
| 73 | // | 140000 - 1FFFFF | flash mirror | |
| 74 | // | 200000 - 23FFFF | ram | |
| 75 | // | 240000 - 3FFFFF | ram mirror | |
| 76 | // | 400000 - 5FFFFF | FF FF FF FF .. | |
| 77 | // | 600000 - 600001 | lcd | |
| 78 | // | 600002 - DFFFFF | FF FF FF FF .. | |
| 79 | // | E00000 - FFDBFF | keyboard | |
| 80 | // | FFDC00 - FFFFFF | onchip ram & regs | |
| 81 | // +-------------------------------------+ |
| 82 | |
| 83 | // 256 kbyte ram + 256 kbyte memory mapped flash |
| 84 | ADDRESS_MAP_START( cybikov2_mem, ADDRESS_SPACE_PROGRAM, 16 ) |
| 85 | AM_RANGE_SL( 0x000000, 0x008000) AM_ROM |
| 86 | AM_RANGE_SL( 0x100000, 0x040000) AM_READ( MRA16_BANK2) AM_MIRROR( 0x0C0000) |
| 87 | // AM_RANGE_SL( 0x200000, 0x040000) AM_RAM AM_MIRROR( 0x1C0000) |
| 88 | AM_RANGE_SL( 0x600000, 0x000002) AM_READWRITE( cybiko_lcd_r, cybiko_lcd_w) |
| 89 | AM_RANGE_SL( 0xE00000, 0x1FDC00) AM_READ( cybiko_key_r) |
| 90 | ADDRESS_MAP_END |
| 91 | |
| 92 | // 2048? kbyte ram + 512 kbyte memory mapped flash |
| 93 | ADDRESS_MAP_START( cybikoxt_mem, ADDRESS_SPACE_PROGRAM, 16 ) |
| 94 | AM_RANGE_SL( 0x000000, 0x008000) AM_ROM |
| 95 | AM_RANGE_SL( 0x100000, 0x000002) AM_READWRITE( cybiko_lcd_r, cybiko_lcd_w) |
| 96 | AM_RANGE_SL( 0x200000, 0x000004) AM_WRITE( cybiko_unk1_w) |
| 97 | // AM_RANGE_SL( 0x400000, 0x200000) AM_RAM |
| 98 | AM_RANGE_SL( 0x600000, 0x080000) AM_READ( MRA16_BANK2) |
| 99 | AM_RANGE_SL( 0x7FF800, 0x000800) AM_READ( cybiko_unk2_r) |
| 100 | AM_RANGE_SL( 0xE00000, 0x1FDC00) AM_READ( cybiko_key_r) |
| 101 | ADDRESS_MAP_END |
| 102 | |
| 103 | ////////////////////// |
| 104 | // ADDRESS MAP - IO // |
| 105 | ////////////////////// |
| 106 | |
| 107 | ADDRESS_MAP_START( cybikov1_io, ADDRESS_SPACE_IO, 8 ) |
| 108 | AM_RANGE( 0xFFFE40, 0xFFFFFF) AM_READWRITE( cybikov1_io_reg_r, cybikov1_io_reg_w) |
| 109 | ADDRESS_MAP_END |
| 110 | |
| 111 | ADDRESS_MAP_START( cybikov2_io, ADDRESS_SPACE_IO, 8 ) |
| 112 | AM_RANGE( 0xFFFE40, 0xFFFFFF) AM_READWRITE( cybikov2_io_reg_r, cybikov2_io_reg_w) |
| 113 | ADDRESS_MAP_END |
| 114 | |
| 115 | ADDRESS_MAP_START( cybikoxt_io, ADDRESS_SPACE_IO, 8 ) |
| 116 | AM_RANGE( 0xFFFE40, 0xFFFFFF) AM_READWRITE( cybikoxt_io_reg_r, cybikoxt_io_reg_w) |
| 117 | ADDRESS_MAP_END |
| 118 | |
| 119 | ///////////////// |
| 120 | // INPUT PORTS // |
| 121 | ///////////////// |
| 122 | |
| 123 | #define CYBIKO_PORT_BIT_K( mask) \ |
| 124 | PORT_BIT( mask, IP_ACTIVE_LOW, IPT_KEYBOARD) |
| 125 | |
| 126 | #define CYBIKO_PORT_BIT_U( mask) \ |
| 127 | PORT_BIT( mask, IP_ACTIVE_LOW, IPT_UNUSED) |
| 128 | |
| 129 | INPUT_PORTS_START( cybiko) |
| 130 | PORT_START // A1 |
| 131 | CYBIKO_PORT_BIT_K( 0x01) PORT_NAME( "F7" ) PORT_CODE( KEYCODE_F7 ) PORT_CHAR( UCHAR_MAMEKEY( F7 )) |
| 132 | CYBIKO_PORT_BIT_K( 0x02) PORT_NAME( "Esc" ) PORT_CODE( KEYCODE_ESC ) PORT_CHAR( UCHAR_MAMEKEY( ESC )) |
| 133 | CYBIKO_PORT_BIT_K( 0x04) PORT_NAME( "Del" ) PORT_CODE( KEYCODE_DEL ) PORT_CHAR( UCHAR_MAMEKEY( DEL )) |
| 134 | CYBIKO_PORT_BIT_K( 0x08) PORT_NAME( "Left" ) PORT_CODE( KEYCODE_LEFT ) PORT_CHAR( UCHAR_MAMEKEY( LEFT )) |
| 135 | CYBIKO_PORT_BIT_K( 0x10) PORT_NAME( "Q" ) PORT_CODE( KEYCODE_Q ) PORT_CHAR( 'Q' ) |
| 136 | CYBIKO_PORT_BIT_K( 0x20) PORT_NAME( "A" ) PORT_CODE( KEYCODE_A ) PORT_CHAR( 'A' ) |
| 137 | CYBIKO_PORT_BIT_K( 0x40) PORT_NAME( "`" ) PORT_CHAR( '`' ) |
| 138 | CYBIKO_PORT_BIT_K( 0x80) PORT_NAME( "Shift" ) PORT_CODE( KEYCODE_LSHIFT ) PORT_CHAR( UCHAR_SHIFT_1 ) |
| 139 | PORT_START // A2 |
| 140 | CYBIKO_PORT_BIT_K( 0x01) PORT_NAME( "F6" ) PORT_CODE( KEYCODE_F6 ) PORT_CHAR( UCHAR_MAMEKEY( F6 )) |
| 141 | CYBIKO_PORT_BIT_K( 0x02) PORT_NAME( "Up" ) PORT_CODE( KEYCODE_UP ) PORT_CHAR( UCHAR_MAMEKEY( UP )) |
| 142 | CYBIKO_PORT_BIT_K( 0x04) PORT_NAME( "Ins" ) PORT_CODE( KEYCODE_INSERT ) PORT_CHAR( UCHAR_MAMEKEY( INSERT)) |
| 143 | CYBIKO_PORT_BIT_K( 0x08) PORT_NAME( "2 @" ) PORT_CODE( KEYCODE_2 ) PORT_CHAR( '2' ) PORT_CHAR( '@') |
| 144 | CYBIKO_PORT_BIT_K( 0x10) PORT_NAME( "W" ) PORT_CODE( KEYCODE_W ) PORT_CHAR( 'W' ) |
| 145 | CYBIKO_PORT_BIT_K( 0x20) PORT_NAME( "S" ) PORT_CODE( KEYCODE_S ) PORT_CHAR( 'S' ) |
| 146 | CYBIKO_PORT_BIT_K( 0x40) PORT_NAME( "Z" ) PORT_CODE( KEYCODE_Z ) PORT_CHAR( 'Z' ) |
| 147 | CYBIKO_PORT_BIT_K( 0x80) PORT_NAME( "Fn" ) PORT_CODE( KEYCODE_LCONTROL ) PORT_CHAR( UCHAR_SHIFT_2 ) |
| 148 | PORT_START // A3 |
| 149 | CYBIKO_PORT_BIT_K( 0x01) PORT_NAME( "F5" ) PORT_CODE( KEYCODE_F5 ) PORT_CHAR( UCHAR_MAMEKEY( F5 )) |
| 150 | CYBIKO_PORT_BIT_K( 0x02) PORT_NAME( "F3" ) PORT_CODE( KEYCODE_F3 ) PORT_CHAR( UCHAR_MAMEKEY( F3 )) |
| 151 | CYBIKO_PORT_BIT_K( 0x04) PORT_NAME( "Space" ) PORT_CODE( KEYCODE_SPACE ) PORT_CHAR( ' ' ) |
| 152 | CYBIKO_PORT_BIT_K( 0x08) PORT_NAME( "3 #" ) PORT_CODE( KEYCODE_3 ) PORT_CHAR( '3' ) PORT_CHAR( '#') |
| 153 | CYBIKO_PORT_BIT_K( 0x10) PORT_NAME( "E" ) PORT_CODE( KEYCODE_E ) PORT_CHAR( 'E' ) |
| 154 | CYBIKO_PORT_BIT_K( 0x20) PORT_NAME( "D" ) PORT_CODE( KEYCODE_D ) PORT_CHAR( 'D' ) |
| 155 | CYBIKO_PORT_BIT_K( 0x40) PORT_NAME( "X" ) PORT_CODE( KEYCODE_X ) PORT_CHAR( 'X' ) |
| 156 | CYBIKO_PORT_BIT_K( 0x80) PORT_NAME( "Help" ) PORT_CODE( KEYCODE_END ) PORT_CHAR( UCHAR_MAMEKEY( END )) |
| 157 | PORT_START // A4 |
| 158 | CYBIKO_PORT_BIT_K( 0x01) PORT_NAME( "F4" ) PORT_CODE( KEYCODE_F4 ) PORT_CHAR( UCHAR_MAMEKEY( F4 )) |
| 159 | CYBIKO_PORT_BIT_K( 0x02) PORT_NAME( "1 !" ) PORT_CODE( KEYCODE_1 ) PORT_CHAR( '1' ) PORT_CHAR( '!') |
| 160 | CYBIKO_PORT_BIT_K( 0x04) PORT_NAME( "Tab" ) PORT_CODE( KEYCODE_TAB ) PORT_CHAR( 9 ) |
| 161 | CYBIKO_PORT_BIT_K( 0x08) PORT_NAME( "4 $" ) PORT_CODE( KEYCODE_4 ) PORT_CHAR( '4' ) PORT_CHAR( '$') |
| 162 | CYBIKO_PORT_BIT_K( 0x10) PORT_NAME( "R" ) PORT_CODE( KEYCODE_R ) PORT_CHAR( 'R' ) |
| 163 | CYBIKO_PORT_BIT_K( 0x20) PORT_NAME( "F" ) PORT_CODE( KEYCODE_F ) PORT_CHAR( 'F' ) |
| 164 | CYBIKO_PORT_BIT_K( 0x40) PORT_NAME( "C" ) PORT_CODE( KEYCODE_C ) PORT_CHAR( 'C' ) |
| 165 | CYBIKO_PORT_BIT_K( 0x80) PORT_NAME( "[ {" ) PORT_CODE( KEYCODE_OPENBRACE ) PORT_CHAR( '[' ) |
| 166 | PORT_START // A5 |
| 167 | CYBIKO_PORT_BIT_K( 0x01) PORT_NAME( "Right" ) PORT_CODE( KEYCODE_RIGHT ) PORT_CHAR( UCHAR_MAMEKEY( RIGHT )) |
| 168 | CYBIKO_PORT_BIT_K( 0x02) PORT_NAME( "Down" ) PORT_CODE( KEYCODE_DOWN ) PORT_CHAR( UCHAR_MAMEKEY( DOWN )) |
| 169 | CYBIKO_PORT_BIT_K( 0x04) PORT_NAME( "Select") PORT_CODE( KEYCODE_HOME ) PORT_CHAR( UCHAR_MAMEKEY( HOME )) |
| 170 | CYBIKO_PORT_BIT_K( 0x08) PORT_NAME( "5 %" ) PORT_CODE( KEYCODE_5 ) PORT_CHAR( '5' ) PORT_CHAR( '%') |
| 171 | CYBIKO_PORT_BIT_K( 0x10) PORT_NAME( "T" ) PORT_CODE( KEYCODE_T ) PORT_CHAR( 'T' ) |
| 172 | CYBIKO_PORT_BIT_K( 0x20) PORT_NAME( "G" ) PORT_CODE( KEYCODE_G ) PORT_CHAR( 'G' ) |
| 173 | CYBIKO_PORT_BIT_K( 0x40) PORT_NAME( "V" ) PORT_CODE( KEYCODE_V ) PORT_CHAR( 'V' ) |
| 174 | CYBIKO_PORT_BIT_K( 0x80) PORT_NAME( "] }" ) PORT_CODE( KEYCODE_CLOSEBRACE) PORT_CHAR( ']' ) |
| 175 | PORT_START // A6 |
| 176 | CYBIKO_PORT_BIT_K( 0x01) PORT_NAME( "F2" ) PORT_CODE( KEYCODE_F2 ) PORT_CHAR( UCHAR_MAMEKEY( F2 )) |
| 177 | CYBIKO_PORT_BIT_K( 0x02) PORT_NAME( "; :" ) PORT_CODE( KEYCODE_COLON ) PORT_CHAR( ';' ) PORT_CHAR( ':') |
| 178 | CYBIKO_PORT_BIT_K( 0x04) PORT_NAME( "Enter" ) PORT_CODE( KEYCODE_ENTER ) PORT_CHAR( 13 ) |
| 179 | CYBIKO_PORT_BIT_K( 0x08) PORT_NAME( "6 ^" ) PORT_CODE( KEYCODE_6 ) PORT_CHAR( '6' ) |
| 180 | CYBIKO_PORT_BIT_K( 0x10) PORT_NAME( "Y" ) PORT_CODE( KEYCODE_Y ) PORT_CHAR( 'Y' ) |
| 181 | CYBIKO_PORT_BIT_K( 0x20) PORT_NAME( "H" ) PORT_CODE( KEYCODE_H ) PORT_CHAR( 'H' ) |
| 182 | CYBIKO_PORT_BIT_K( 0x40) PORT_NAME( "B" ) PORT_CODE( KEYCODE_B ) PORT_CHAR( 'B' ) |
| 183 | CYBIKO_PORT_BIT_K( 0x80) PORT_NAME( "\\ |" ) PORT_CODE( KEYCODE_BACKSLASH ) PORT_CHAR( '\\' ) PORT_CHAR( '|') |
| 184 | PORT_START // A7 |
| 185 | CYBIKO_PORT_BIT_K( 0x01) PORT_NAME( "F1" ) PORT_CODE( KEYCODE_F1 ) PORT_CHAR( UCHAR_MAMEKEY( F1 )) |
| 186 | CYBIKO_PORT_BIT_K( 0x02) PORT_NAME( "/ ?" ) PORT_CODE( KEYCODE_SLASH ) PORT_CHAR( '/' ) PORT_CHAR( '?') |
| 187 | CYBIKO_PORT_BIT_K( 0x04) PORT_NAME( "BkSp" ) PORT_CODE( KEYCODE_BACKSPACE ) PORT_CHAR( 8 ) |
| 188 | CYBIKO_PORT_BIT_K( 0x08) PORT_NAME( "7 &" ) PORT_CODE( KEYCODE_7 ) PORT_CHAR( '7' ) PORT_CHAR( '&') |
| 189 | CYBIKO_PORT_BIT_K( 0x10) PORT_NAME( "U" ) PORT_CODE( KEYCODE_U ) PORT_CHAR( 'U' ) |
| 190 | CYBIKO_PORT_BIT_K( 0x20) PORT_NAME( "J" ) PORT_CODE( KEYCODE_J ) PORT_CHAR( 'J' ) |
| 191 | CYBIKO_PORT_BIT_K( 0x40) PORT_NAME( "N" ) PORT_CODE( KEYCODE_N ) PORT_CHAR( 'N' ) |
| 192 | CYBIKO_PORT_BIT_U( 0x80) |
| 193 | PORT_START // A8 |
| 194 | CYBIKO_PORT_BIT_K( 0x01) PORT_NAME( "- _" ) PORT_CODE( KEYCODE_MINUS ) PORT_CHAR( '-' ) PORT_CHAR( '_') |
| 195 | CYBIKO_PORT_BIT_K( 0x02) PORT_NAME( ". >" ) PORT_CHAR( '.' ) PORT_CHAR( '>') |
| 196 | CYBIKO_PORT_BIT_K( 0x04) PORT_NAME( "0 )" ) PORT_CODE( KEYCODE_0 ) PORT_CHAR( '0' ) PORT_CHAR( ')') |
| 197 | CYBIKO_PORT_BIT_K( 0x08) PORT_NAME( "8 *" ) PORT_CODE( KEYCODE_8 ) PORT_CHAR( '8' ) PORT_CHAR( '*') |
| 198 | CYBIKO_PORT_BIT_K( 0x10) PORT_NAME( "I" ) PORT_CODE( KEYCODE_I ) PORT_CHAR( 'I' ) |
| 199 | CYBIKO_PORT_BIT_K( 0x20) PORT_NAME( "K" ) PORT_CODE( KEYCODE_K ) PORT_CHAR( 'K' ) |
| 200 | CYBIKO_PORT_BIT_K( 0x40) PORT_NAME( "M" ) PORT_CODE( KEYCODE_M ) PORT_CHAR( 'M' ) |
| 201 | CYBIKO_PORT_BIT_U( 0x80) |
| 202 | PORT_START // A9 |
| 203 | CYBIKO_PORT_BIT_K( 0x01) PORT_NAME( "' \"" ) PORT_CODE( KEYCODE_QUOTE ) PORT_CHAR( '\'' ) PORT_CHAR( '"') |
| 204 | CYBIKO_PORT_BIT_K( 0x02) PORT_NAME( "= +" ) PORT_CODE( KEYCODE_EQUALS ) PORT_CHAR( '=' ) PORT_CHAR( '+') |
| 205 | CYBIKO_PORT_BIT_K( 0x04) PORT_NAME( "9 (" ) PORT_CODE( KEYCODE_9 ) PORT_CHAR( '9' ) PORT_CHAR( '(') |
| 206 | CYBIKO_PORT_BIT_K( 0x08) PORT_NAME( "P" ) PORT_CODE( KEYCODE_P ) PORT_CHAR( 'P' ) |
| 207 | CYBIKO_PORT_BIT_K( 0x10) PORT_NAME( "O" ) PORT_CODE( KEYCODE_O ) PORT_CHAR( 'O' ) |
| 208 | CYBIKO_PORT_BIT_K( 0x20) PORT_NAME( "L" ) PORT_CODE( KEYCODE_L ) PORT_CHAR( 'L' ) |
| 209 | CYBIKO_PORT_BIT_K( 0x40) PORT_NAME( ", <" ) PORT_CODE( KEYCODE_COMMA ) PORT_CHAR( ',' ) PORT_CHAR( '<') |
| 210 | CYBIKO_PORT_BIT_U( 0x80) |
| 211 | INPUT_PORTS_END |
| 212 | |
| 213 | ///////// |
| 214 | // ROM // |
| 215 | ///////// |
| 216 | |
| 217 | ROM_START( cybikov1 ) |
| 218 | ROM_REGION( 0x8000, REGION_CPU1, 0) |
| 219 | ROM_LOAD( "cyrom112.bin", 0, 0x8000, CRC(9E1F1A0F) SHA1(6FC08DE6B2C67D884EC78F748E4A4BAD27EE8045)) |
| 220 | ROM_END |
| 221 | |
| 222 | ROM_START( cybikov2 ) |
| 223 | ROM_REGION( 0x8000, REGION_CPU1, 0) |
| 224 | ROM_LOAD( "cyrom117.bin", 0, 0x8000, CRC(268DA7BF) SHA1(135EAF9E3905E69582AABD9B06BC4DE0A66780D5)) |
| 225 | ROM_END |
| 226 | |
| 227 | ROM_START( cybikoxt ) |
| 228 | ROM_REGION( 0x8000, REGION_CPU1, 0) |
| 229 | ROM_LOAD( "cyrom150.bin", 0, 0x8000, CRC(18B9B21F) SHA1(28868D6174EB198A6CEC6C3C70B6E494517229B9)) |
| 230 | ROM_END |
| 231 | |
| 232 | /////////////////// |
| 233 | // SYSTEM CONFIG // |
| 234 | /////////////////// |
| 235 | |
| 236 | SYSTEM_CONFIG_START( cybikov1 ) |
| 237 | CONFIG_RAM_DEFAULT( 512 * 1024) |
| 238 | CONFIG_RAM( 1024 * 1024) |
| 239 | SYSTEM_CONFIG_END |
| 240 | |
| 241 | SYSTEM_CONFIG_START( cybikov2 ) |
| 242 | CONFIG_RAM_DEFAULT( 256 * 1024) |
| 243 | CONFIG_RAM( 512 * 1024) |
| 244 | CONFIG_RAM( 1024 * 1024) |
| 245 | SYSTEM_CONFIG_END |
| 246 | |
| 247 | SYSTEM_CONFIG_START( cybikoxt ) |
| 248 | CONFIG_RAM_DEFAULT( 2048 * 1024) |
| 249 | SYSTEM_CONFIG_END |
| 250 | |
| 251 | //////////////////// |
| 252 | // MACHINE DRIVER // |
| 253 | //////////////////// |
| 254 | |
| 255 | MACHINE_DRIVER_START( cybikov1 ) |
| 256 | // cpu |
| 257 | MDRV_CPU_ADD_TAG( "main", H8S2241, 11059200) |
| 258 | MDRV_CPU_PROGRAM_MAP( cybikov1_mem, 0) |
| 259 | MDRV_CPU_IO_MAP( cybikov1_io, 0) |
| 260 | // screen |
| 261 | MDRV_SCREEN_REFRESH_RATE( 60) |
| 262 | MDRV_SCREEN_FORMAT( BITMAP_FORMAT_INDEXED16) |
| 263 | MDRV_SCREEN_SIZE( HD66421_WIDTH, HD66421_HEIGHT) |
| 264 | MDRV_SCREEN_VISIBLE_AREA( 0, HD66421_WIDTH - 1, 0, HD66421_HEIGHT - 1) |
| 265 | // video |
| 266 | MDRV_VIDEO_ATTRIBUTES( VIDEO_TYPE_RASTER) |
| 267 | MDRV_PALETTE_LENGTH( 4) |
| 268 | MDRV_COLORTABLE_LENGTH( 4) |
| 269 | MDRV_PALETTE_INIT( hd66421) |
| 270 | MDRV_VIDEO_START( hd66421) |
| 271 | MDRV_VIDEO_UPDATE( hd66421) |
| 272 | MDRV_DEFAULT_LAYOUT( layout_cybiko) |
| 273 | // sound |
| 274 | MDRV_SPEAKER_STANDARD_MONO( "mono") |
| 275 | MDRV_SOUND_ADD_TAG( "speaker", SPEAKER, 0) |
| 276 | MDRV_SOUND_ROUTE( ALL_OUTPUTS, "mono", 1.00) |
| 277 | // machine |
| 278 | MDRV_MACHINE_START( cybikov1) |
| 279 | MDRV_MACHINE_RESET( cybikov1) |
| 280 | // non-volatile ram |
| 281 | // MDRV_NVRAM_HANDLER( cybikov1) |
| 282 | MACHINE_DRIVER_END |
| 283 | |
| 284 | MACHINE_DRIVER_START( cybikov2 ) |
| 285 | // import |
| 286 | MDRV_IMPORT_FROM( cybikov1) |
| 287 | // cpu |
| 288 | MDRV_CPU_REPLACE( "main", H8S2246, 11059200) |
| 289 | MDRV_CPU_PROGRAM_MAP( cybikov2_mem, 0) |
| 290 | MDRV_CPU_IO_MAP( cybikov2_io, 0) |
| 291 | // machine |
| 292 | MDRV_MACHINE_START( cybikov2) |
| 293 | MDRV_MACHINE_RESET( cybikov2) |
| 294 | // non-volatile ram |
| 295 | // MDRV_NVRAM_HANDLER( cybikov2) |
| 296 | MACHINE_DRIVER_END |
| 297 | |
| 298 | MACHINE_DRIVER_START( cybikoxt ) |
| 299 | // import |
| 300 | MDRV_IMPORT_FROM( cybikov1) |
| 301 | // cpu |
| 302 | MDRV_CPU_REPLACE( "main", H8S2323, 18432000) |
| 303 | MDRV_CPU_PROGRAM_MAP( cybikoxt_mem, 0) |
| 304 | MDRV_CPU_IO_MAP( cybikoxt_io, 0) |
| 305 | // sound |
| 306 | MDRV_SPEAKER_REMOVE( "mono") |
| 307 | MDRV_SOUND_REMOVE( "speaker") |
| 308 | // machine |
| 309 | MDRV_MACHINE_START( cybikoxt) |
| 310 | MDRV_MACHINE_RESET( cybikoxt) |
| 311 | // non-volatile ram |
| 312 | // MDRV_NVRAM_HANDLER( cybikoxt) |
| 313 | MACHINE_DRIVER_END |
| 314 | |
| 315 | ////////////// |
| 316 | // COMPUTER // |
| 317 | ////////////// |
| 318 | |
| 319 | // YEAR - NAME - PARENT - BIOS - COMPAT - MACHINE - INPUT - INIT - CONFIG - COMPANY - FULLNAME - FLAGS |
| 320 | COMPB( 2000, cybikov1, 0, 0, 0, cybikov1, cybiko, cybikov1, cybikov1, "Cybiko, Inc.", "Cybiko Classic (V1)", GAME_IMPERFECT_SOUND) |
| 321 | COMPB( 2000, cybikov2, cybikov1, 0, 0, cybikov2, cybiko, cybikov2, cybikov2, "Cybiko, Inc.", "Cybiko Classic (V2)", GAME_IMPERFECT_SOUND) |
| 322 | COMPB( 2001, cybikoxt, cybikov1, 0, 0, cybikoxt, cybiko, cybikoxt, cybikoxt, "Cybiko, Inc.", "Cybiko Xtreme", GAME_NO_SOUND | GAME_NOT_WORKING) |