src/mess/video/ef9345.c
| r9546 | r9547 | |
| 21 | 21 | #define MODE12x80 3 |
| 22 | 22 | #define MODE16x40 4 |
| 23 | 23 | |
| 24 | | typedef struct _ef9345_t ef9345_t; |
| 25 | | struct _ef9345_t |
| 24 | //************************************************************************** |
| 25 | // GLOBAL VARIABLES |
| 26 | //************************************************************************** |
| 27 | |
| 28 | // devices |
| 29 | const device_type EF9345 = ef9345_device_config::static_alloc_device_config; |
| 30 | |
| 31 | // default address map |
| 32 | static ADDRESS_MAP_START( ef9345, 0, 8 ) |
| 33 | AM_RANGE(0x0000, 0x3fff) AM_RAM |
| 34 | ADDRESS_MAP_END |
| 35 | |
| 36 | //************************************************************************** |
| 37 | // device configuration |
| 38 | //************************************************************************** |
| 39 | |
| 40 | //------------------------------------------------- |
| 41 | // ef9345_device_config - constructor |
| 42 | //------------------------------------------------- |
| 43 | |
| 44 | ef9345_device_config::ef9345_device_config( const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock ): |
| 45 | device_config( mconfig, static_alloc_device_config, "ef9345", tag, owner, clock), |
| 46 | device_config_memory_interface(mconfig, *this), |
| 47 | m_space_config("videoram", ENDIANNESS_LITTLE, 8, 16, 0, NULL, *ADDRESS_MAP_NAME(ef9345)) |
| 26 | 48 | { |
| 27 | | screen_device *screen; //screen we are acting on |
| 49 | } |
| 28 | 50 | |
| 29 | | UINT8 bf; //busy flag |
| 30 | | UINT8 char_mode; //40 or 80 chars for line |
| 31 | | UINT8* charset; //charset |
| 32 | | UINT8 ram[0x4000]; //16Ko (logique) pour 8Ko (physique) |
| 33 | | UINT8 acc_char[0x2000]; //8Ko (logique) polices accentuees |
| 34 | | UINT8 registers[8]; //registers R0-R7 |
| 35 | | UINT8 state; //status register |
| 36 | | UINT8 TGS,MAT,PAT,DOR,ROR; //registres acces indirect |
| 37 | | UINT8 border[80]; //caractere du cadre |
| 38 | | UINT8 *block; //pointeur block courant |
| 39 | | UINT8 *char_ptr[16]; //pointeurs polices de caracteres |
| 40 | | UINT16 blink; //etat du clignotement |
| 41 | | UINT8 dial; //cadran en cours d'affichage |
| 42 | | UINT16 last_dial[40]; //dernier cadran affiche |
| 43 | | UINT8 latchc0; //couleur c0 latchee |
| 44 | | UINT16 latchm; //attribut m(conceal) latche |
| 45 | | UINT16 latchi; //attribut i(insert) latche |
| 46 | | UINT16 latchu; //attribut u(underline) latche |
| 47 | 51 | |
| 48 | | bitmap_t *screen_out; |
| 52 | //------------------------------------------------- |
| 53 | // static_alloc_device_config - allocate a new |
| 54 | // configuration object |
| 55 | //------------------------------------------------- |
| 49 | 56 | |
| 50 | | emu_timer *busy_timer; |
| 51 | | emu_timer *blink_timer; |
| 52 | | }; |
| 57 | device_config *ef9345_device_config::static_alloc_device_config( const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock ) |
| 58 | { |
| 59 | return global_alloc( ef9345_device_config( mconfig, tag, owner, clock ) ); |
| 60 | } |
| 53 | 61 | |
| 54 | | static TIMER_CALLBACK( ef9345_done ); |
| 55 | 62 | |
| 63 | //------------------------------------------------- |
| 64 | // alloc_device - allocate a new device object |
| 65 | //------------------------------------------------- |
| 56 | 66 | |
| 57 | | INLINE _ef9345_t *get_safe_token(running_device *device) |
| 67 | device_t *ef9345_device_config::alloc_device( running_machine &machine ) const |
| 58 | 68 | { |
| 59 | | assert(device != NULL); |
| 60 | | assert(device->type() == EF9345); |
| 61 | | return (_ef9345_t *)downcast<legacy_device_base *>(device)->token(); |
| 69 | return auto_alloc( &machine, ef9345_device( machine, *this ) ); |
| 62 | 70 | } |
| 63 | 71 | |
| 64 | | /*------------------------------------------------- |
| 65 | | set busy flag and timer to clear it |
| 66 | | -------------------------------------------------*/ |
| 67 | | static void set_busy_flag(ef9345_t *ef9345, int period) |
| 72 | //------------------------------------------------- |
| 73 | // memory_space_config - return a description of |
| 74 | // any address spaces owned by this device |
| 75 | //------------------------------------------------- |
| 76 | |
| 77 | const address_space_config *ef9345_device_config::memory_space_config(int spacenum) const |
| 68 | 78 | { |
| 69 | | ef9345->bf = 1; |
| 79 | return (spacenum == 0) ? &m_space_config : NULL; |
| 80 | } |
| 70 | 81 | |
| 71 | | timer_adjust_oneshot(ef9345->busy_timer, ATTOTIME_IN_USEC(period), 0); |
| 82 | //------------------------------------------------- |
| 83 | // device_config_complete - perform any |
| 84 | // operations now that the configuration is |
| 85 | // complete |
| 86 | //------------------------------------------------- |
| 87 | |
| 88 | void ef9345_device_config::device_config_complete() |
| 89 | { |
| 90 | // inherit a copy of the static data |
| 91 | const ef9345_interface *intf = reinterpret_cast<const ef9345_interface *>(static_config()); |
| 92 | |
| 93 | if (intf != NULL) |
| 94 | { |
| 95 | *static_cast<ef9345_interface *>(this) = *intf; |
| 96 | } |
| 97 | // or initialize to defaults if none provided |
| 98 | else |
| 99 | { |
| 100 | screen_tag = NULL; |
| 101 | } |
| 72 | 102 | } |
| 73 | 103 | |
| 74 | | /*------------------------------------------------- |
| 75 | | draw a char in 40 char line mode |
| 76 | | -------------------------------------------------*/ |
| 77 | | void draw_char_40(ef9345_t *ef9345, UINT8 *c, int x, int y) |
| 104 | |
| 105 | //************************************************************************** |
| 106 | // INLINE HELPERS |
| 107 | //************************************************************************** |
| 108 | |
| 109 | // calculate the internal RAM offset |
| 110 | inline UINT16 ef9345_device::indexram(UINT8 r) |
| 78 | 111 | { |
| 79 | | UINT16 i, j; |
| 112 | UINT8 x = registers[r]; |
| 113 | UINT8 y = registers[r - 1]; |
| 114 | if (y < 8) |
| 115 | y &= 1; |
| 116 | return ((x&0x3f) | ((x & 0x40) << 6) | ((x & 0x80) << 4) | ((y & 0x1f) << 6) | ((y & 0x20) << 8)); |
| 117 | } |
| 80 | 118 | |
| 81 | | /* verify size limit */ |
| 82 | | if (y * 10 >= ef9345->screen->height() || x * 8 >= ef9345->screen->width()) |
| 83 | | return; |
| 119 | // calculate the internal ROM offset |
| 120 | inline UINT16 ef9345_device::indexrom(UINT8 r) |
| 121 | { |
| 122 | UINT8 x = registers[r]; |
| 123 | UINT8 y = registers[r - 1]; |
| 124 | if (y < 8) |
| 125 | y &= 1; |
| 126 | return((x&0x3f)|((x&0x40)<<6)|((x&0x80)<<4)|((y&0x1f)<<6)); |
| 127 | } |
| 84 | 128 | |
| 85 | | for(i = 0; i < 10; i++) |
| 86 | | for(j = 0; j < 8; j++) |
| 87 | | *BITMAP_ADDR16(ef9345->screen_out, y * 10 + i, x * 8 + j) = c[8 * i + j] & 0x07; |
| 129 | // increment x |
| 130 | inline void ef9345_device::inc_x(UINT8 r) |
| 131 | { |
| 132 | UINT8 i = (registers[r] & 0x3f) + 1; |
| 133 | if (i > 39) |
| 134 | { |
| 135 | i -= 40; |
| 136 | state |= 0x40; |
| 137 | } |
| 138 | registers[r] = (registers[r] & 0xc0) | i; |
| 88 | 139 | } |
| 89 | 140 | |
| 90 | | /*------------------------------------------------- |
| 91 | | draw a char in 80 char line mode |
| 92 | | -------------------------------------------------*/ |
| 93 | | void draw_char_80(ef9345_t *ef9345, UINT8 *c, int x, int y) |
| 141 | // increment y |
| 142 | inline void ef9345_device::inc_y(UINT8 r) |
| 94 | 143 | { |
| 95 | | int i, j; |
| 144 | UINT8 i = (registers[r] & 0x1f) + 1; |
| 145 | if (i > 31) |
| 146 | i -= 24; |
| 147 | registers[r] = (registers[r] & 0xe0) | i; |
| 148 | } |
| 96 | 149 | |
| 97 | | /* verify size limit */ |
| 98 | | if (y * 10 >= ef9345->screen->height() || x * 6 >= ef9345->screen->width()) |
| 99 | | return; |
| 100 | 150 | |
| 101 | | for(i = 0; i < 10; i++) |
| 102 | | for(j = 0; j < 6; j++) |
| 103 | | *BITMAP_ADDR16(ef9345->screen_out, y * 10 + i, x * 6 + j) = c[6 * i + j] & 0x07; |
| 151 | //************************************************************************** |
| 152 | // live device |
| 153 | //************************************************************************** |
| 154 | |
| 155 | //------------------------------------------------- |
| 156 | // ef9345_device - constructor |
| 157 | //------------------------------------------------- |
| 158 | |
| 159 | ef9345_device::ef9345_device( running_machine &_machine, const ef9345_device_config &config ) : |
| 160 | device_t(_machine, config), |
| 161 | device_memory_interface(_machine, config, *this), |
| 162 | m_config(config) |
| 163 | { |
| 104 | 164 | } |
| 105 | 165 | |
| 166 | //------------------------------------------------- |
| 167 | // device_start - device-specific startup |
| 168 | //------------------------------------------------- |
| 106 | 169 | |
| 107 | | /*------------------------------------------------- |
| 108 | | set then ef9345 mode |
| 109 | | -------------------------------------------------*/ |
| 110 | | void set_ef9345_mode(ef9345_t *ef9345) |
| 170 | void ef9345_device::device_start() |
| 111 | 171 | { |
| 112 | | UINT8 i; |
| 113 | | ef9345->char_mode = ((ef9345->PAT & 0x80) >> 5) | ((ef9345->TGS & 0xc0) >> 6); |
| 114 | | UINT16 new_width = (ef9345->char_mode == MODE12x80 || ef9345->char_mode == MODE8x80) ? 492 : 336; |
| 172 | screen = machine->device<screen_device>(m_config.screen_tag); |
| 115 | 173 | |
| 116 | | if (ef9345->screen->width() != new_width) |
| 117 | | { |
| 118 | | rectangle visarea = ef9345->screen->visible_area(); |
| 119 | | visarea.max_x = new_width - 1; |
| 174 | assert(screen != NULL); |
| 120 | 175 | |
| 121 | | ef9345->screen->configure(new_width, ef9345->screen->height(), visarea, ef9345->screen->frame_period().attoseconds); |
| 122 | | } |
| 176 | m_busy_timer = device_timer_alloc(*this, BUSY_TIMER); |
| 177 | m_blink_timer = device_timer_alloc(*this, BLINKING_TIMER); |
| 123 | 178 | |
| 124 | | //couleur de bordure |
| 125 | | for(i = 0; i < 80; i++) |
| 126 | | ef9345->border[i] = ef9345->MAT & 0x07; |
| 179 | videoram = space(0); |
| 180 | charset = region(); |
| 127 | 181 | |
| 128 | | //polices (avec ram 8K) |
| 129 | | ef9345->char_ptr[0x08] = ef9345->ram + ((ef9345->DOR & 0x07) << 11); //G'0 |
| 130 | | ef9345->char_ptr[0x09] = ef9345->char_ptr[0x08]; //G'0 underlined |
| 131 | | ef9345->char_ptr[0x0a] = ef9345->ram + ((ef9345->DOR & 0x30) << 8); //G'10 |
| 132 | | ef9345->char_ptr[0x0b] = ef9345->char_ptr[0x0a] + 0x800; //G'11 |
| 133 | | ef9345->char_ptr[0x0c] = ef9345->ram; //Quadrichrome |
| 134 | | ef9345->char_ptr[0x0d] = ef9345->char_ptr[0x0c]; |
| 135 | | ef9345->char_ptr[0x0e] = ef9345->char_ptr[0x0c]; |
| 136 | | ef9345->char_ptr[0x0f] = ef9345->char_ptr[0x0c]; |
| 182 | screen_out = auto_bitmap_alloc(machine, 496, screen->height() , BITMAP_FORMAT_INDEXED16); |
| 137 | 183 | |
| 138 | | //adresse block memoire courant |
| 139 | | i = ((ef9345->ROR & 0xf0) >> 4) | ((ef9345->ROR & 0x40) >> 5) | ((ef9345->ROR & 0x20) >> 3); |
| 140 | | ef9345->block = ef9345->ram + 0x800 * (i & 0x0c); |
| 184 | timer_adjust_periodic(m_blink_timer, ATTOTIME_IN_MSEC(500), 0, ATTOTIME_IN_MSEC(500)); |
| 185 | |
| 186 | init_accented_chars(); |
| 187 | |
| 188 | state_save_register_device_item_array(this, 0, border); |
| 189 | state_save_register_device_item_array(this, 0, registers); |
| 190 | state_save_register_device_item_array(this, 0, last_dial); |
| 191 | state_save_register_device_item_array(this, 0, ram_base); |
| 192 | state_save_register_device_item(this, 0, bf); |
| 193 | state_save_register_device_item(this, 0, char_mode); |
| 194 | state_save_register_device_item(this, 0, state); |
| 195 | state_save_register_device_item(this, 0, TGS); |
| 196 | state_save_register_device_item(this, 0, MAT); |
| 197 | state_save_register_device_item(this, 0, PAT); |
| 198 | state_save_register_device_item(this, 0, DOR); |
| 199 | state_save_register_device_item(this, 0, ROR); |
| 200 | state_save_register_device_item(this, 0, block); |
| 201 | state_save_register_device_item(this, 0, blink); |
| 202 | state_save_register_device_item(this, 0, latchc0); |
| 203 | state_save_register_device_item(this, 0, latchm); |
| 204 | state_save_register_device_item(this, 0, latchi); |
| 205 | state_save_register_device_item(this, 0, latchu); |
| 206 | |
| 207 | state_save_register_device_item_bitmap(this, 0, screen_out); |
| 141 | 208 | } |
| 142 | 209 | |
| 143 | | /*------------------------------------------------- |
| 144 | | Initialize the ef9345 char_ptr |
| 145 | | -------------------------------------------------*/ |
| 146 | | void init_char_prt(ef9345_t *ef9345) |
| 210 | //------------------------------------------------- |
| 211 | // device_reset - device-specific reset |
| 212 | //------------------------------------------------- |
| 213 | void ef9345_device::device_reset() |
| 147 | 214 | { |
| 148 | | int i, j; |
| 149 | | //polices accentuees |
| 150 | | for(j = 0; j < 0x10; j++) |
| 151 | | for(i = 0; i < 0x200; i++) |
| 152 | | ef9345->acc_char[(j << 9) + i] = ef9345->charset[0x0600 + i]; |
| 215 | TGS = MAT = PAT = DOR = ROR = 0; |
| 216 | state = 0; |
| 217 | bf = 0; |
| 218 | block = 0; |
| 219 | blink = 0; |
| 220 | latchc0 = 0; |
| 221 | latchm = 0; |
| 222 | latchi = 0; |
| 223 | latchu = 0; |
| 224 | char_mode = 0; |
| 153 | 225 | |
| 154 | | for(j = 0; j < 0x200; j += 0x40) |
| 155 | | for(i = 0; i < 4; i++) |
| 156 | | { |
| 157 | | ef9345->acc_char[0x0200 + j + i + 4] |= 0x1c; //tilde |
| 158 | | ef9345->acc_char[0x0400 + j + i + 4] |= 0x10; //aigu |
| 159 | | ef9345->acc_char[0x0400 + j + i + 8] |= 0x08; //aigu |
| 160 | | ef9345->acc_char[0x0600 + j + i + 4] |= 0x04; //grave |
| 161 | | ef9345->acc_char[0x0600 + j + i + 8] |= 0x08; //grave |
| 226 | memset(last_dial, 0, ARRAY_LENGTH(last_dial) * sizeof(UINT8)); |
| 227 | memset(registers, 0, ARRAY_LENGTH(registers) * sizeof(UINT8)); |
| 228 | memset(border, 0, ARRAY_LENGTH(border) * sizeof(UINT8)); |
| 229 | memset(border, 0, ARRAY_LENGTH(ram_base) * sizeof(UINT16)); |
| 162 | 230 | |
| 163 | | ef9345->acc_char[0x0a00 + j + i + 4] |= 0x1c; //tilde |
| 164 | | ef9345->acc_char[0x0c00 + j + i + 4] |= 0x10; //aigu |
| 165 | | ef9345->acc_char[0x0c00 + j + i + 8] |= 0x08; //aigu |
| 166 | | ef9345->acc_char[0x0e00 + j + i + 4] |= 0x04; //grave |
| 167 | | ef9345->acc_char[0x0e00 + j + i + 8] |= 0x08; //grave |
| 231 | bitmap_fill(screen_out, NULL, 0); |
| 168 | 232 | |
| 169 | | ef9345->acc_char[0x1200 + j + i + 4] |= 0x08; //point |
| 170 | | ef9345->acc_char[0x1400 + j + i + 4] |= 0x14; //trema |
| 171 | | ef9345->acc_char[0x1600 + j + i + 32] |= 0x08; //cedille |
| 172 | | ef9345->acc_char[0x1600 + j + i + 36] |= 0x04; //cedille |
| 233 | set_video_mode(); |
| 234 | } |
| 173 | 235 | |
| 174 | | ef9345->acc_char[0x1a00 + j + i + 4] |= 0x08; //point |
| 175 | | ef9345->acc_char[0x1c00 + j + i + 4] |= 0x14; //trema |
| 176 | | ef9345->acc_char[0x1e00 + j + i + 32] |= 0x08; //cedille |
| 177 | | ef9345->acc_char[0x1e00 + j + i + 36] |= 0x04; //cedille |
| 178 | | } |
| 236 | //------------------------------------------------- |
| 237 | // device_timer - handler timer events |
| 238 | //------------------------------------------------- |
| 239 | void ef9345_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |
| 240 | { |
| 241 | switch(id) |
| 242 | { |
| 243 | case BUSY_TIMER: |
| 244 | bf = 0; |
| 245 | break; |
| 179 | 246 | |
| 180 | | //initialisation des pointeurs de polices fixes |
| 181 | | ef9345->char_ptr[0x00] = ef9345->charset; //G0 |
| 182 | | ef9345->char_ptr[0x01] = ef9345->charset + 0x0800; //G0 underlined |
| 183 | | ef9345->char_ptr[0x02] = ef9345->charset + 0x1000; //G11 |
| 184 | | ef9345->char_ptr[0x03] = ef9345->charset + 0x1800; //G10 |
| 185 | | ef9345->char_ptr[0x04] = ef9345->acc_char; //G20 |
| 186 | | ef9345->char_ptr[0x05] = ef9345->acc_char + 0x0800; //G20 underlined |
| 187 | | ef9345->char_ptr[0x06] = ef9345->acc_char + 0x1000; //G21 |
| 188 | | ef9345->char_ptr[0x07] = ef9345->acc_char + 0x1800; //G21 underlined |
| 247 | case BLINKING_TIMER: |
| 248 | blink = !blink; |
| 249 | break; |
| 250 | } |
| 189 | 251 | } |
| 190 | 252 | |
| 191 | 253 | |
| 192 | | /* calculate the internal RAM offset */ |
| 193 | | UINT16 indexram(ef9345_t *ef9345, UINT8 r) |
| 254 | // set busy flag and timer to clear it |
| 255 | void ef9345_device::set_busy_flag(int period) |
| 194 | 256 | { |
| 195 | | UINT8 x, y; |
| 196 | | x = ef9345->registers[r]; |
| 197 | | y = ef9345->registers[r - 1]; |
| 198 | | if(y < 8) |
| 199 | | y &= 1; |
| 200 | | return ((x&0x3f) | ((x & 0x40) << 6) | ((x & 0x80) << 4) | ((y & 0x1f) << 6) | ((y & 0x20) << 8)); |
| 257 | bf = 1; |
| 258 | timer_adjust_oneshot(m_busy_timer, ATTOTIME_IN_USEC(period), 0); |
| 201 | 259 | } |
| 202 | 260 | |
| 203 | | /* calculate the internal ROM offset */ |
| 204 | | UINT16 indexrom(ef9345_t *ef9345, int r) |
| 261 | // draw a char in 40 char line mode |
| 262 | void ef9345_device::draw_char_40(UINT8 *c, UINT16 x, UINT16 y) |
| 205 | 263 | { |
| 206 | | UINT8 x, y; |
| 207 | | x = ef9345->registers[r]; |
| 208 | | y = ef9345->registers[r - 1]; |
| 209 | | if(y < 8) |
| 210 | | y &= 1; |
| 211 | | return((x&0x3f)|((x&0x40)<<6)|((x&0x80)<<4)|((y&0x1f)<<6)); |
| 264 | //verify size limit |
| 265 | if (y * 10 >= screen->height() || x * 8 >= screen->width()) |
| 266 | return; |
| 267 | |
| 268 | for(int i = 0; i < 10; i++) |
| 269 | for(int j = 0; j < 8; j++) |
| 270 | *BITMAP_ADDR16(screen_out, y * 10 + i, x * 8 + j) = c[8 * i + j] & 0x07; |
| 212 | 271 | } |
| 213 | 272 | |
| 214 | | //calcul de l'adresse du caractere x, y dans le block courant |
| 215 | | int indexblock(ef9345_t *ef9345, int x, int y) |
| 273 | // draw a char in 80 char line mode |
| 274 | void ef9345_device::draw_char_80(UINT8 *c, UINT16 x, UINT16 y) |
| 216 | 275 | { |
| 217 | | int i, j; |
| 218 | | i = x; |
| 219 | | j = (y == 0) ? ((ef9345->TGS & 0x20) >> 5) : ((ef9345->ROR & 0x1f) + y - 1); |
| 220 | | //partie droite d'un caractere en double largeur en mode 40 caracteres |
| 221 | | if((ef9345->TGS & 0x80) == 0) if(x > 0) |
| 222 | | { |
| 223 | | if(ef9345->last_dial[x - 1] == 1) i--; //colonne precedente |
| 224 | | if(ef9345->last_dial[x - 1] == 4) i--; //colonne precedente |
| 225 | | if(ef9345->last_dial[x - 1] == 5) i--; //colonne precedente |
| 226 | | } |
| 276 | // verify size limit |
| 277 | if (y * 10 >= screen->height() || x * 6 >= screen->width()) |
| 278 | return; |
| 227 | 279 | |
| 228 | | return 0x40 * j + i; |
| 280 | for(int i = 0; i < 10; i++) |
| 281 | for(int j = 0; j < 6; j++) |
| 282 | *BITMAP_ADDR16(screen_out, y * 10 + i, x * 6 + j) = c[6 * i + j] & 0x07; |
| 229 | 283 | } |
| 230 | 284 | |
| 231 | | // Increment X |
| 232 | | void inc_x(ef9345_t *ef9345, int r) |
| 285 | |
| 286 | // set then ef9345 mode |
| 287 | void ef9345_device::set_video_mode(void) |
| 233 | 288 | { |
| 234 | | int i; |
| 235 | | i = (ef9345->registers[r] & 0x3f) + 1; |
| 236 | | if(i > 39) |
| 289 | char_mode = ((PAT & 0x80) >> 5) | ((TGS & 0xc0) >> 6); |
| 290 | UINT16 new_width = (char_mode == MODE12x80 || char_mode == MODE8x80) ? 492 : 336; |
| 291 | |
| 292 | if (screen->width() != new_width) |
| 237 | 293 | { |
| 238 | | i -= 40; |
| 239 | | ef9345->state |= 0x40; |
| 294 | rectangle visarea = screen->visible_area(); |
| 295 | visarea.max_x = new_width - 1; |
| 296 | |
| 297 | screen->configure(new_width, screen->height(), visarea, screen->frame_period().attoseconds); |
| 240 | 298 | } |
| 241 | | ef9345->registers[r] = (ef9345->registers[r] & 0xc0) | i; |
| 299 | |
| 300 | //border color |
| 301 | memset(border, MAT & 0x07, ARRAY_LENGTH(border)); |
| 302 | |
| 303 | //set the base for the videoram charset |
| 304 | ram_base[0] = ((DOR & 0x07) << 11); |
| 305 | ram_base[1] = ram_base[0]; |
| 306 | ram_base[2] = ((DOR & 0x30) << 8); |
| 307 | ram_base[3] = ram_base[2] + 0x0800; |
| 308 | |
| 309 | //address of the current memory block |
| 310 | block = 0x0800 * ((((ROR & 0xf0) >> 4) | ((ROR & 0x40) >> 5) | ((ROR & 0x20) >> 3)) & 0x0c); |
| 242 | 311 | } |
| 243 | 312 | |
| 244 | | // Increment Y |
| 245 | | void inc_y(ef9345_t *ef9345, int r) |
| 313 | // initialize the ef9345 accented chars |
| 314 | void ef9345_device::init_accented_chars(void) |
| 246 | 315 | { |
| 247 | | int i; |
| 248 | | i = (ef9345->registers[r] & 0x1f) + 1; |
| 249 | | if(i > 31) |
| 250 | | i -= 24; |
| 251 | | ef9345->registers[r] = (ef9345->registers[r] & 0xe0) | i; |
| 316 | UINT16 i, j; |
| 317 | for(j = 0; j < 0x10; j++) |
| 318 | for(i = 0; i < 0x200; i++) |
| 319 | acc_char[(j << 9) + i] = charset->u8(0x0600 + i); |
| 320 | |
| 321 | for(j = 0; j < 0x200; j += 0x40) |
| 322 | for(i = 0; i < 4; i++) |
| 323 | { |
| 324 | acc_char[0x0200 + j + i + 4] |= 0x1c; //tilde |
| 325 | acc_char[0x0400 + j + i + 4] |= 0x10; //acute |
| 326 | acc_char[0x0400 + j + i + 8] |= 0x08; //acute |
| 327 | acc_char[0x0600 + j + i + 4] |= 0x04; //grave |
| 328 | acc_char[0x0600 + j + i + 8] |= 0x08; //grave |
| 329 | |
| 330 | acc_char[0x0a00 + j + i + 4] |= 0x1c; //tilde |
| 331 | acc_char[0x0c00 + j + i + 4] |= 0x10; //acute |
| 332 | acc_char[0x0c00 + j + i + 8] |= 0x08; //acute |
| 333 | acc_char[0x0e00 + j + i + 4] |= 0x04; //grave |
| 334 | acc_char[0x0e00 + j + i + 8] |= 0x08; //grave |
| 335 | |
| 336 | acc_char[0x1200 + j + i + 4] |= 0x08; //point |
| 337 | acc_char[0x1400 + j + i + 4] |= 0x14; //trema |
| 338 | acc_char[0x1600 + j + i + 32] |= 0x08; //cedilla |
| 339 | acc_char[0x1600 + j + i + 36] |= 0x04; //cedilla |
| 340 | |
| 341 | acc_char[0x1a00 + j + i + 4] |= 0x08; //point |
| 342 | acc_char[0x1c00 + j + i + 4] |= 0x14; //trema |
| 343 | acc_char[0x1e00 + j + i + 32] |= 0x08; //cedilla |
| 344 | acc_char[0x1e00 + j + i + 36] |= 0x04; //cedilla |
| 345 | } |
| 252 | 346 | } |
| 253 | 347 | |
| 254 | | // Determination du cadran a afficher |
| 255 | | void Cadran(ef9345_t *ef9345, int x, int attrib) |
| 348 | // read a char in charset or in videoram |
| 349 | UINT8 ef9345_device::read_char(UINT8 index, UINT16 addr) |
| 256 | 350 | { |
| 257 | | while(1) |
| 258 | | { |
| 259 | | if(x > 0) |
| 260 | | if(ef9345->last_dial[x-1] == 1) |
| 261 | | {ef9345->dial = 2; break;} //cadran haut droit |
| 262 | | if(x > 0) |
| 263 | | if(ef9345->last_dial[x-1] == 5) |
| 264 | | {ef9345->dial = 10; break;} //moitie droite |
| 265 | | if(ef9345->last_dial[x] == 1) |
| 266 | | {ef9345->dial = 4; break;} //cadran bas gauche |
| 267 | | if(ef9345->last_dial[x] == 2) |
| 268 | | {ef9345->dial = 8; break;} //dial bas droit |
| 269 | | if(ef9345->last_dial[x] == 3) |
| 270 | | {ef9345->dial = 12; break;} //moitie basse |
| 271 | | if(attrib == 1) |
| 272 | | {ef9345->dial = 5; break;} //moitie gauche |
| 273 | | if(attrib == 2) |
| 274 | | {ef9345->dial = 3; break;} //moitie haute |
| 275 | | if(attrib == 3) |
| 276 | | {ef9345->dial = 1; break;} //dial haut gauche |
| 277 | | ef9345->dial = 0; break; //caractere complet |
| 278 | | } |
| 279 | | ef9345->last_dial[x] = ef9345->dial; |
| 351 | if (index < 0x04) |
| 352 | return charset->u8(0x0800*index + addr); |
| 353 | else if (index < 0x08) |
| 354 | return acc_char[0x0800*(index&3) + addr]; |
| 355 | else if (index < 0x0c) |
| 356 | return videoram->read_byte(ram_base[index-8] + addr); |
| 357 | else |
| 358 | return videoram->read_byte(addr); |
| 280 | 359 | } |
| 281 | 360 | |
| 282 | | // zoom sur une partie d'un caractere |
| 283 | | void zoom(ef9345_t *ef9345, UINT8 *pix, int n) |
| 361 | // calculate the dial position of the char |
| 362 | UINT8 ef9345_device::get_dial(UINT8 x, UINT8 attrib) |
| 284 | 363 | { |
| 285 | | //pix est le tableau des pixels (8x10=80) |
| 286 | | //n definit la zone (zoomx2y2 pour cadran, zoomx2 ou zoomy2 pour moitie) |
| 287 | | //cadran haut-gauche=1, haut-droit=2, bas-gauche=4, bas-droite=8 |
| 288 | | //moitie haute=3, basse=12, gauche=5, droite=10 |
| 289 | | int i, j; |
| 290 | | if((n & 0x0a) == 0) |
| 364 | if (x > 0 && last_dial[x-1] == 1) //top right |
| 365 | last_dial[x] = 2; |
| 366 | else if (x > 0 && last_dial[x-1] == 5) //half right |
| 367 | last_dial[x] = 10; |
| 368 | else if (last_dial[x] == 1) //bottom left |
| 369 | last_dial[x] = 4; |
| 370 | else if (last_dial[x] == 2) //bottom right |
| 371 | last_dial[x] = 8; |
| 372 | else if (last_dial[x] == 3) //lower half |
| 373 | last_dial[x] = 12; |
| 374 | else if (attrib == 1) //Left half |
| 375 | last_dial[x] = 5; |
| 376 | else if (attrib == 2) //half high |
| 377 | last_dial[x] = 3; |
| 378 | else if (attrib == 3) //top left |
| 379 | last_dial[x] = 1; |
| 380 | else //none |
| 381 | last_dial[x] = 0; |
| 382 | |
| 383 | return last_dial[x]; |
| 384 | } |
| 385 | |
| 386 | // zoom the char |
| 387 | void ef9345_device::zoom(UINT8 *pix, UINT16 n) |
| 388 | { |
| 389 | UINT8 i, j; |
| 390 | if ((n & 0x0a) == 0) |
| 291 | 391 | for(i = 0; i < 80; i += 8) // 1, 4, 5 |
| 292 | 392 | for(j = 7; j > 0; j--) |
| 293 | 393 | pix[i + j] = pix[i + j / 2]; |
| 294 | 394 | |
| 295 | | if((n & 0x05) == 0) |
| 395 | if ((n & 0x05) == 0) |
| 296 | 396 | for(i = 0; i < 80; i += 8) // 2, 8, 10 |
| 297 | 397 | for(j =0 ; j < 7; j++) |
| 298 | 398 | pix[i + j] = pix[i + 4 + j / 2]; |
| 299 | 399 | |
| 300 | | if((n & 0x0c) == 0) |
| 400 | if ((n & 0x0c) == 0) |
| 301 | 401 | for(i = 0; i < 8; i++) // 1, 2, 3 |
| 302 | 402 | for(j = 9; j > 0; j--) |
| 303 | 403 | pix[i + 8 * j] = pix[i + 8 * (j / 2)]; |
| 304 | | if((n & 0x03) == 0) |
| 404 | |
| 405 | if ((n & 0x03) == 0) |
| 305 | 406 | for(i = 0; i < 8; i++) // 4, 8, 12 |
| 306 | 407 | for(j = 0; j < 9; j++) |
| 307 | 408 | pix[i + 8 * j] = pix[i + 40 + 8 * (j / 2)]; |
| 308 | 409 | } |
| 309 | 410 | |
| 310 | | // Display bichrome character (40 columns) |
| 311 | | void Bichrome40(ef9345_t *ef9345, UINT8 *matrice, int iblock, int x, int y, int c0, int c1, int insert, int flash, int conceal, int negative, int underline) |
| 411 | |
| 412 | // calculate the address of the char x,y |
| 413 | UINT16 ef9345_device::indexblock(UINT16 x, UINT16 y) |
| 312 | 414 | { |
| 313 | | UINT8 i, j, pix[80]; |
| 415 | UINT16 i = x, j; |
| 416 | j = (y == 0) ? ((TGS & 0x20) >> 5) : ((ROR & 0x1f) + y - 1); |
| 314 | 417 | |
| 315 | | if(flash && ef9345->PAT & 0x40 && ef9345->blink) |
| 316 | | c1 = c0; //flash |
| 317 | | if(conceal && ef9345->PAT & 0x08) |
| 318 | | c1 = c0; //conceal |
| 319 | | if(negative) //negative |
| 418 | //right side of a double width character |
| 419 | if ((TGS & 0x80) == 0 && x > 0) |
| 320 | 420 | { |
| 421 | if (last_dial[x - 1] == 1) i--; |
| 422 | if (last_dial[x - 1] == 4) i--; |
| 423 | if (last_dial[x - 1] == 5) i--; |
| 424 | } |
| 425 | |
| 426 | return 0x40 * j + i; |
| 427 | } |
| 428 | |
| 429 | // draw bichrome character (40 columns) |
| 430 | void ef9345_device::bichrome40(UINT8 type, UINT16 address, UINT8 dial, UINT16 iblock, UINT16 x, UINT16 y, UINT8 c0, UINT8 c1, UINT8 insert, UINT8 flash, UINT8 hided, UINT8 negative, UINT8 underline) |
| 431 | { |
| 432 | UINT16 i; |
| 433 | UINT8 pix[80]; |
| 434 | |
| 435 | if (flash && PAT & 0x40 && blink) |
| 436 | c1 = c0; //flash |
| 437 | if (hided && PAT & 0x08) |
| 438 | c1 = c0; //hided |
| 439 | if (negative) //negative |
| 440 | { |
| 321 | 441 | i = c1; |
| 322 | 442 | c1 = c0; |
| 323 | 443 | c0 = i; |
| 324 | 444 | } |
| 325 | | //? v?rifier cf instructions en commentaires ci-dessous : insert = 0 ou 1 ?? |
| 326 | | if((ef9345->PAT & 0x30) == 0x30) |
| 327 | | insert = 0; //active area mark |
| 328 | | if(insert == 0) |
| 329 | | c1 += 8; //couleur etendue foreground |
| 330 | | if((ef9345->PAT & 0x30) == 0x00) |
| 331 | | insert = 1; //inlay |
| 332 | | if(insert == 0) |
| 333 | | c0 += 8; //couleur etendue background |
| 334 | 445 | |
| 446 | if ((PAT & 0x30) == 0x30) |
| 447 | insert = 0; //active area mark |
| 448 | if (insert == 0) |
| 449 | c1 += 8; //foreground color |
| 450 | if ((PAT & 0x30) == 0x00) |
| 451 | insert = 1; //insert mode |
| 452 | if (insert == 0) |
| 453 | c0 += 8; //background color |
| 335 | 454 | |
| 336 | | //affichage du curseur |
| 337 | | i = (ef9345->registers[6] & 0x1f); |
| 338 | | if(i < 8) |
| 455 | //draw the cursor |
| 456 | i = (registers[6] & 0x1f); |
| 457 | if (i < 8) |
| 339 | 458 | i &= 1; |
| 340 | 459 | |
| 341 | | if(iblock == 0x40 * i + (ef9345->registers[7] & 0x3f)) //position du curseur |
| 460 | if (iblock == 0x40 * i + (registers[7] & 0x3f)) //cursor position |
| 342 | 461 | { |
| 343 | | //affichage du curseur si ef9345->MAT 6 est positionne |
| 344 | | //le clignotement depend de ef9345->MAT 5, la forme depend de ef9345->MAT 4 |
| 345 | | switch(ef9345->MAT & 0x70) |
| 462 | switch(MAT & 0x70) |
| 346 | 463 | { |
| 347 | | case 0x40: //00 = fixed complemented |
| 464 | case 0x40: //00 = fixed complemented |
| 348 | 465 | c0 = (23 - c0) & 15; |
| 349 | 466 | c1 = (23 - c1) & 15; |
| 350 | 467 | break; |
| 351 | | case 0x50: //01 = fixed underlined |
| 468 | case 0x50: //01 = fixed underlined |
| 352 | 469 | underline = 1; |
| 353 | 470 | break; |
| 354 | | case 0x60: //10 = flash complemented |
| 355 | | if(ef9345->blink) |
| 471 | case 0x60: //10 = flash complemented |
| 472 | if (blink) |
| 356 | 473 | { |
| 357 | 474 | c0 = (23 - c0) & 15; |
| 358 | 475 | c1 = (23 - c1) & 15; |
| 359 | 476 | } |
| 360 | 477 | break; |
| 361 | | case 0x70: //11 = flash underlined |
| 362 | | if(ef9345->blink) |
| 478 | case 0x70: //11 = flash underlined |
| 479 | if (blink) |
| 363 | 480 | underline = 1; |
| 364 | 481 | break; |
| 365 | 482 | } |
| 366 | 483 | } |
| 367 | 484 | |
| 368 | | //initialisation du tableau des pixels du caractere |
| 369 | | j = 0; |
| 370 | | |
| 371 | | for(i = 0; i < 10; i++) |
| 485 | // generate the pixel table |
| 486 | for(i = 0; i < 40; i+=4) |
| 372 | 487 | { |
| 373 | | pix[j++] = (*(matrice + 4 * i) & 0x01) ? c1 : c0; |
| 374 | | pix[j++] = (*(matrice + 4 * i) & 0x02) ? c1 : c0; |
| 375 | | pix[j++] = (*(matrice + 4 * i) & 0x04) ? c1 : c0; |
| 376 | | pix[j++] = (*(matrice + 4 * i) & 0x08) ? c1 : c0; |
| 377 | | pix[j++] = (*(matrice + 4 * i) & 0x10) ? c1 : c0; |
| 378 | | pix[j++] = (*(matrice + 4 * i) & 0x20) ? c1 : c0; |
| 379 | | pix[j++] = (*(matrice + 4 * i) & 0x40) ? c1 : c0; |
| 380 | | pix[j++] = (*(matrice + 4 * i) & 0x80) ? c1 : c0; |
| 488 | UINT8 ch = read_char(type, address + i); |
| 381 | 489 | |
| 490 | for (UINT8 b=0; b<8; b++) |
| 491 | pix[i*2 + b] = (ch & (1<<b)) ? c1 : c0; |
| 382 | 492 | } |
| 383 | 493 | |
| 384 | | //caractere souligne |
| 385 | | if(underline) |
| 386 | | for(j = 72; j < 80; j++) |
| 387 | | pix[j] = c1; |
| 494 | //draw the underline |
| 495 | if (underline) |
| 496 | memset(&pix[72], c1, 8); |
| 388 | 497 | |
| 389 | | //affichage en fonction du cadran |
| 390 | | //remarque : la double hauteur par le bit 7 du registre ef9345->MAT |
| 391 | | //est prise en UINT8ge par la fonction d'affichage de l'ecran |
| 392 | | //voir Displayscreen() dans le module de traitement de la video |
| 393 | | if(ef9345->dial > 0) |
| 394 | | zoom(ef9345, pix, ef9345->dial); |
| 498 | if (dial > 0) |
| 499 | zoom(pix, dial); |
| 395 | 500 | |
| 396 | 501 | //doubles the height of the char |
| 397 | | if (ef9345->MAT & 0x80) |
| 398 | | zoom(ef9345, pix, (y & 0x01) ? 0x0c : 0x03); |
| 502 | if (MAT & 0x80) |
| 503 | zoom(pix, (y & 0x01) ? 0x0c : 0x03); |
| 399 | 504 | |
| 400 | | draw_char_40(ef9345, pix, x + 1 , y + 1); |
| 505 | draw_char_40(pix, x + 1 , y + 1); |
| 401 | 506 | } |
| 402 | 507 | |
| 403 | | // Display quadrichrome character (40 columns) |
| 404 | | void Quadrichrome40(ef9345_t *ef9345, int c, int b, int a, int x, int y) |
| 508 | // draw quadrichrome character (40 columns) |
| 509 | void ef9345_device::quadrichrome40(UINT8 c, UINT8 b, UINT8 a, UINT16 x, UINT16 y) |
| 405 | 510 | { |
| 406 | 511 | //C0-6= character code |
| 407 | 512 | //B0= insert not yet implemented !!! |
| r9546 | r9547 | |
| 412 | 517 | |
| 413 | 518 | UINT8 i, j, n, col[8], pix[80]; |
| 414 | 519 | UINT8 lowresolution = (b & 0x02) >> 1, ramx, ramy, ramblock; |
| 415 | | UINT8 *ramindex; |
| 416 | | //pas de double hauteur ou largeur pour les quadrichromes |
| 417 | | ef9345->last_dial[x] = 0; |
| 418 | | //color table initialization (seules les couleurs 0-3 sont utilis?es) |
| 419 | | j = 1; n = 0; |
| 420 | | for(i = 0; i < 4; i++) |
| 421 | | col[i] = 7; //blanc par defaut |
| 520 | UINT16 ramindex; |
| 422 | 521 | |
| 423 | | for(i = 0; i < 8; i++) |
| 522 | //quadrichrome don't suppor double size |
| 523 | last_dial[x] = 0; |
| 524 | |
| 525 | //initialize the color table |
| 526 | for(j = 1, n = 0, i = 0; i < 8; i++) |
| 424 | 527 | { |
| 425 | | if(a & j) |
| 426 | | col[n++] = i; |
| 528 | col[n++] = (a & j) ? i : 7; |
| 427 | 529 | j <<= 1; |
| 428 | 530 | } |
| 429 | 531 | |
| 430 | | //find block number i in ram |
| 532 | //find block number in ram |
| 431 | 533 | ramblock = 0; |
| 432 | | if(b & 0x20) ramblock |= 4; //B5 |
| 433 | | if(b & 0x08) ramblock |= 2; //B3 |
| 434 | | if(b & 0x10) ramblock |= 1; //B4 |
| 534 | if (b & 0x20) ramblock |= 4; //B5 |
| 535 | if (b & 0x08) ramblock |= 2; //B3 |
| 536 | if (b & 0x10) ramblock |= 1; //B4 |
| 435 | 537 | |
| 436 | 538 | //find character address in ram |
| 437 | | ramx = c & 0x03; ramy =(c & 0x7f) >> 2; |
| 438 | | ramindex = ef9345->char_ptr[0x0c] + 0x800 * ramblock + 0x40 * ramy + ramx; |
| 439 | | if(lowresolution) ramindex += 5 * (b & 0x04); |
| 539 | ramx = c & 0x03; |
| 540 | ramy =(c & 0x7f) >> 2; |
| 541 | ramindex = 0x0800 * ramblock + 0x40 * ramy + ramx; |
| 542 | if (lowresolution) ramindex += 5 * (b & 0x04); |
| 440 | 543 | |
| 441 | 544 | //fill pixel table |
| 442 | | j = 0; for(i = 0; i < 10; i++) |
| 545 | for(i = 0, j = 0; i < 10; i++) |
| 443 | 546 | { |
| 444 | | pix[j] = pix[j + 1] = col[(*(ramindex + 4 * (i >> lowresolution)) & 0x03) >> 0]; j += 2; |
| 445 | | pix[j] = pix[j + 1] = col[(*(ramindex + 4 * (i >> lowresolution)) & 0x0c) >> 2]; j += 2; |
| 446 | | pix[j] = pix[j + 1] = col[(*(ramindex + 4 * (i >> lowresolution)) & 0x30) >> 4]; j += 2; |
| 447 | | pix[j] = pix[j + 1] = col[(*(ramindex + 4 * (i >> lowresolution)) & 0xc0) >> 6]; j += 2; |
| 547 | UINT8 ch = read_char(0x0c, ramindex + 4 * (i >> lowresolution)); |
| 548 | pix[j] = pix[j + 1] = col[(ch & 0x03) >> 0]; j += 2; |
| 549 | pix[j] = pix[j + 1] = col[(ch & 0x0c) >> 2]; j += 2; |
| 550 | pix[j] = pix[j + 1] = col[(ch & 0x30) >> 4]; j += 2; |
| 551 | pix[j] = pix[j + 1] = col[(ch & 0xc0) >> 6]; j += 2; |
| 448 | 552 | } |
| 449 | 553 | |
| 450 | | draw_char_40(ef9345, pix, x + 1, y + 1); |
| 554 | draw_char_40(pix, x + 1, y + 1); |
| 451 | 555 | } |
| 452 | 556 | |
| 453 | | // Display bichrome character (80 columns) |
| 454 | | void Bichrome80(ef9345_t *ef9345, int c, int a, int x, int y) |
| 557 | // draw bichrome character (80 columns) |
| 558 | void ef9345_device::bichrome80(UINT8 c, UINT8 a, UINT16 x, UINT16 y) |
| 455 | 559 | { |
| 456 | | UINT8 pix[60]; //tableau des pixels a afficher |
| 457 | | int i, j, d, c0, c1; |
| 458 | | c1 = (a & 1) ? (ef9345->DOR >> 4) & 7 : ef9345->DOR & 7; //foreground color = ef9345->DOR |
| 459 | | c0 = ef9345->MAT & 7; //background color = ef9345->MAT |
| 560 | UINT8 c0, c1, pix[60]; |
| 561 | UINT16 i, j, d; |
| 562 | |
| 563 | c1 = (a & 1) ? (DOR >> 4) & 7 : DOR & 7; //foreground color = DOR |
| 564 | c0 = MAT & 7; //background color = MAT |
| 565 | |
| 460 | 566 | switch(c & 0x80) |
| 461 | 567 | { |
| 462 | 568 | case 0: //alphanumeric G0 set |
| r9546 | r9547 | |
| 465 | 571 | //A2: F = flash |
| 466 | 572 | //A3: N = negative |
| 467 | 573 | //C0-6: character code |
| 468 | | j = 0; |
| 469 | | if(a & 4) if(ef9345->PAT & 0x40) if(ef9345->blink) c1 = c0; //flash |
| 470 | | if(a & 8) {i = c1; c1 = c0; c0 = i;} //couleurs en mode inverse |
| 471 | | d = ((c & 0x7f) >> 2) * 0x40 + (c & 0x03); //deplacement dans table police |
| 472 | | for(i = 0; i < 10; i++) |
| 574 | |
| 575 | if ((a & 4) && (PAT & 0x40) && (blink)) |
| 576 | c1 = c0; //flash |
| 577 | if (a & 8) //negative |
| 473 | 578 | { |
| 474 | | pix[j++] = (*(ef9345->charset + d + 4 * i) & 0x01) ? c1 : c0; pix[j++] = (*(ef9345->charset + d + 4 * i) & 0x02) ? c1 : c0; |
| 475 | | pix[j++] = (*(ef9345->charset + d + 4 * i) & 0x04) ? c1 : c0; pix[j++] = (*(ef9345->charset + d + 4 * i) & 0x08) ? c1 : c0; |
| 476 | | pix[j++] = (*(ef9345->charset + d + 4 * i) & 0x10) ? c1 : c0; pix[j++] = (*(ef9345->charset + d + 4 * i) & 0x20) ? c1 : c0; |
| 579 | i = c1; |
| 580 | c1 = c0; |
| 581 | c0 = i; |
| 477 | 582 | } |
| 478 | | if(a & 2) for(j = 54; j < 60; j++) pix[j] = c1; //underline |
| 583 | |
| 584 | d = ((c & 0x7f) >> 2) * 0x40 + (c & 0x03); //char position |
| 585 | |
| 586 | for(i=0, j=0; i < 10; i++) |
| 587 | { |
| 588 | UINT8 ch = read_char(0, d + 4 * i); |
| 589 | for (UINT8 b=0; b<6; b++) |
| 590 | pix[j++] = (ch & (1<<b)) ? c1 : c0; |
| 591 | } |
| 592 | |
| 593 | //draw the underline |
| 594 | if (a & 2) |
| 595 | memset(&pix[54], c1, 6); |
| 596 | |
| 479 | 597 | break; |
| 480 | 598 | default: //dedicated mosaic set |
| 481 | 599 | //A0: D = color set |
| r9546 | r9547 | |
| 491 | 609 | pix[39] = (a & 0x02) ? c1 : c0; |
| 492 | 610 | pix[48] = (a & 0x04) ? c1 : c0; |
| 493 | 611 | pix[51] = (a & 0x08) ? c1 : c0; |
| 612 | |
| 494 | 613 | for(i = 0; i < 60; i += 12) |
| 495 | 614 | { |
| 496 | 615 | pix[i + 6] = pix[i]; |
| 497 | 616 | pix[i + 9] = pix[i + 3]; |
| 498 | 617 | } |
| 618 | |
| 499 | 619 | for(i = 0; i < 60; i += 3) |
| 500 | 620 | pix[i + 2] = pix[i + 1] = pix[i]; |
| 621 | |
| 501 | 622 | break; |
| 502 | 623 | } |
| 503 | | draw_char_80(ef9345, pix, x, y); |
| 624 | |
| 625 | draw_char_80(pix, x, y); |
| 504 | 626 | } |
| 505 | 627 | |
| 506 | | |
| 507 | | // Affichage d'un caractere 16 bits 40 colonnes |
| 508 | | void makechar_16x40(ef9345_t *ef9345, int x, int y) |
| 628 | // generate 16 bits 40 columns char |
| 629 | void ef9345_device::makechar_16x40(UINT16 x, UINT16 y) |
| 509 | 630 | { |
| 510 | | int i, a, b, type, c0, c1, f, m, n, u, iblock; |
| 511 | | UINT8* matrice; |
| 631 | UINT8 a, b, c0, c1, i, f, m, n, u, type, dial; |
| 632 | UINT16 address, iblock; |
| 512 | 633 | |
| 513 | | //recherche des octets b, a (precedent si double largeur) |
| 514 | | iblock = (ef9345->MAT & 0x80 && y > 1) ? indexblock(ef9345, x, y / 2) : indexblock(ef9345, x, y); |
| 515 | | a = ef9345->block[iblock]; |
| 516 | | b = ef9345->block[iblock + 0x800]; |
| 634 | iblock = (MAT & 0x80 && y > 1) ? indexblock(x, y / 2) : indexblock(x, y); |
| 635 | a = videoram->read_byte(block + iblock); |
| 636 | b = videoram->read_byte(block + iblock + 0x0800); |
| 517 | 637 | |
| 518 | | //determination attribut HL et numero du cadran a afficher |
| 519 | | Cadran(ef9345, x, (a & 0x80) ? 0 : (((a & 0x20) >> 5) | ((a & 0x10) >> 3))); |
| 638 | dial = get_dial(x, (a & 0x80) ? 0 : (((a & 0x20) >> 5) | ((a & 0x10) >> 3))); |
| 520 | 639 | |
| 521 | | //adresse de la matrice de definition du caractere |
| 640 | //type and address of the char |
| 522 | 641 | type = ((b & 0x80) >> 4) | ((a & 0x80) >> 6); |
| 523 | | matrice = ef9345->char_ptr[type] + ((b & 0x7f) >> 2) * 0x40 + (b & 0x03); |
| 524 | | if((b & 0xe0) == 0x80) |
| 525 | | matrice = ef9345->char_ptr[0x03]; //negative space |
| 642 | address = ((b & 0x7f) >> 2) * 0x40 + (b & 0x03); |
| 526 | 643 | |
| 527 | | //attributs latches |
| 528 | | if(x == 0) ef9345->latchm = ef9345->latchi = ef9345->latchu = ef9345->latchc0 = 0; |
| 529 | | if(type == 4) {ef9345->latchm = b & 1; ef9345->latchi = (b & 2) >> 1; ef9345->latchu = (b & 4) >> 2;} |
| 530 | | if(a & 0x80) ef9345->latchc0 = (a & 0x70) >> 4; |
| 644 | //negative space |
| 645 | if ((b & 0xe0) == 0x80) |
| 646 | { |
| 647 | address = 0; |
| 648 | type = 3; |
| 649 | } |
| 531 | 650 | |
| 532 | | //attributs du caractere |
| 533 | | c0 = ef9345->latchc0; //background |
| 651 | //reset attributes latch |
| 652 | if (x == 0) |
| 653 | latchm = latchi = latchu = latchc0 = 0; |
| 654 | |
| 655 | if (type == 4) |
| 656 | { |
| 657 | latchm = b & 1; |
| 658 | latchi = (b & 2) >> 1; |
| 659 | latchu = (b & 4) >> 2; |
| 660 | } |
| 661 | |
| 662 | if (a & 0x80) |
| 663 | latchc0 = (a & 0x70) >> 4; |
| 664 | |
| 665 | //char attributes |
| 666 | c0 = latchc0; //background |
| 534 | 667 | c1 = a & 0x07; //foreground |
| 535 | | i = ef9345->latchi; //insert mode |
| 668 | i = latchi; //insert mode |
| 536 | 669 | f = (a & 0x08) >> 3; //flash |
| 537 | | m = ef9345->latchm; //conceal |
| 670 | m = latchm; //hided |
| 538 | 671 | n = (a & 0x80) ? 0: ((a & 0x40) >> 6); //negative |
| 539 | | u = ef9345->latchu; //underline |
| 672 | u = latchu; //underline |
| 540 | 673 | |
| 541 | | //affichage |
| 542 | | Bichrome40(ef9345, matrice, iblock, x, y, c0, c1, i, f, m, n, u); |
| 674 | bichrome40(type, address, dial, iblock, x, y, c0, c1, i, f, m, n, u); |
| 543 | 675 | } |
| 544 | 676 | |
| 545 | | // Affichage d'un caractere 24 bits 40 colonnes |
| 546 | | void makechar_24x40(ef9345_t *ef9345, int x, int y) |
| 677 | // generate 24 bits 40 columns char |
| 678 | void ef9345_device::makechar_24x40(UINT16 x, UINT16 y) |
| 547 | 679 | { |
| 548 | | int i, a, b, c, c0, c1, f, m, n, u, iblock; |
| 549 | | UINT8* matrice; |
| 680 | UINT8 a, b, c, c0, c1, i, f, m, n, u, type, dial; |
| 681 | UINT16 address, iblock; |
| 550 | 682 | |
| 551 | | //recherche des octets c, b, a |
| 552 | | iblock = (ef9345->MAT & 0x80 && y > 1) ? indexblock(ef9345,x, y / 2) : indexblock(ef9345, x, y); |
| 553 | | c = ef9345->block[iblock]; b = ef9345->block[iblock + 0x800]; a = ef9345->block[iblock + 0x1000]; |
| 554 | | if((b & 0xc0) == 0xc0) {Quadrichrome40(ef9345, c, b, a, x, y); return;} |
| 683 | iblock = (MAT & 0x80 && y > 1) ? indexblock(x, y / 2) : indexblock(x, y); |
| 684 | c = videoram->read_byte(block + iblock); |
| 685 | b = videoram->read_byte(block + iblock + 0x0800); |
| 686 | a = videoram->read_byte(block + iblock + 0x1000); |
| 555 | 687 | |
| 556 | | //determination attribut HL et numero du cadran a afficher |
| 557 | | Cadran(ef9345, x, (b & 0x02) + ((b & 0x08) >> 3)); |
| 688 | if ((b & 0xc0) == 0xc0) |
| 689 | { |
| 690 | quadrichrome40(c, b, a, x, y); |
| 691 | return; |
| 692 | } |
| 558 | 693 | |
| 559 | | //adresse de la matrice de definition du caractere |
| 560 | | matrice = ef9345->char_ptr[(b & 0xf0) >> 4] + ((c & 0x7f) >> 2) * 0x40 + (c & 0x03); |
| 694 | dial = get_dial(x, (b & 0x02) + ((b & 0x08) >> 3)); |
| 561 | 695 | |
| 562 | | //attributs du caractere |
| 563 | | c0 = a & 0x07; //background |
| 564 | | c1 = (a & 0x70) >> 4; //foreground |
| 565 | | i = b & 0x01; //insert |
| 566 | | f = (a & 0x08) >> 3; //flash |
| 567 | | m = (b & 0x04) >> 2; //conceal |
| 568 | | n = (a & 0x80) >> 7; //negative |
| 569 | | u = (((b & 0x60) == 0) || ((b & 0xc0) == 0x40)) ? ((b & 0x10) >> 4) : 0; |
| 696 | //type and address of the char |
| 697 | address = ((c & 0x7f) >> 2) * 0x40 + (c & 0x03); |
| 698 | type = (b & 0xf0) >> 4; |
| 570 | 699 | |
| 571 | | //affichage |
| 572 | | Bichrome40(ef9345, matrice, iblock, x, y, c0, c1, i, f, m, n, u); |
| 700 | //char attributes |
| 701 | c0 = a & 0x07; //background |
| 702 | c1 = (a & 0x70) >> 4; //foreground |
| 703 | i = b & 0x01; //insert |
| 704 | f = (a & 0x08) >> 3; //flash |
| 705 | m = (b & 0x04) >> 2; //hided |
| 706 | n = ((a & 0x80) >> 7); //negative |
| 707 | u = (((b & 0x60) == 0) || ((b & 0xc0) == 0x40)) ? ((b & 0x10) >> 4) : 0; //underline |
| 708 | |
| 709 | bichrome40(type, address, dial, iblock, x, y, c0, c1, i, f, m, n, u); |
| 573 | 710 | } |
| 574 | 711 | |
| 712 | // generate 12 bits 80 columns char |
| 713 | void ef9345_device::makechar_12x80(UINT16 x, UINT16 y) |
| 714 | { |
| 715 | UINT16 iblock = indexblock(x, y); |
| 716 | bichrome80(videoram->read_byte(block + iblock), (videoram->read_byte(block + iblock + 0x1000) >> 4) & 0x0f, 2 * x + 1, y + 1); |
| 717 | bichrome80(videoram->read_byte(block + iblock + 0x0800), videoram->read_byte(block + iblock + 0x1000) & 0x0f, 2 * x + 2, y + 1); |
| 718 | } |
| 575 | 719 | |
| 576 | | // Affichage de deux caracteres 12 bits 80 colonnes |
| 577 | | void makechar_12x80(ef9345_t *ef9345, int x, int y) |
| 720 | void ef9345_device::draw_border(UINT16 line) |
| 578 | 721 | { |
| 579 | | int iblock; |
| 580 | | iblock = indexblock(ef9345, x, y); |
| 581 | | Bichrome80(ef9345, ef9345->block[iblock], (ef9345->block[iblock + 0x1000] >> 4) & 0x0f, 2 * x + 1, y + 1); |
| 582 | | Bichrome80(ef9345, ef9345->block[iblock + 0x800], ef9345->block[iblock + 0x1000] & 0x0f, 2 * x + 2, y + 1); |
| 722 | if (char_mode == MODE12x80 || char_mode == MODE8x80) |
| 723 | for(int i = 0; i < 82; i++) |
| 724 | draw_char_80(border, i, line); |
| 725 | else |
| 726 | for(int i = 0; i < 42; i++) |
| 727 | draw_char_40(border, i, line); |
| 583 | 728 | } |
| 584 | 729 | |
| 585 | | void makechar(ef9345_t *ef9345, int x, int y) |
| 730 | void ef9345_device::makechar(UINT16 x, UINT16 y) |
| 586 | 731 | { |
| 587 | | switch (ef9345->char_mode) |
| 732 | switch (char_mode) |
| 588 | 733 | { |
| 589 | 734 | case MODE24x40: |
| 590 | | makechar_24x40(ef9345, x, y); |
| 735 | makechar_24x40(x, y); |
| 591 | 736 | break; |
| 592 | 737 | case MODEVAR40: |
| 593 | | //TODO |
| 594 | | break; |
| 595 | 738 | case MODE8x80: |
| 596 | | //TODO |
| 739 | logerror("Unemulated EF9345 mode: %02x\n", char_mode); |
| 597 | 740 | break; |
| 598 | 741 | case MODE12x80: |
| 599 | | makechar_12x80(ef9345, x, y); |
| 742 | makechar_12x80(x, y); |
| 600 | 743 | break; |
| 601 | 744 | case MODE16x40: |
| 602 | | makechar_16x40(ef9345, x, y); |
| 745 | makechar_16x40(x, y); |
| 603 | 746 | break; |
| 604 | 747 | default: |
| 748 | logerror("Unknown EF9345 mode: %02x\n", char_mode); |
| 605 | 749 | break; |
| 606 | 750 | } |
| 607 | 751 | } |
| 608 | 752 | |
| 609 | | // Lecture-ecriture en memoire EF9345 |
| 610 | | void OCTwrite(ef9345_t *ef9345, int r, int i) |
| 753 | // Execute EF9345 command |
| 754 | void ef9345_device::ef9345_exec(UINT8 cmd) |
| 611 | 755 | { |
| 612 | | set_busy_flag(ef9345, 4); |
| 613 | | ef9345->ram[indexram(ef9345, r)] = ef9345->registers[1]; |
| 614 | | if(i == 0) return; |
| 615 | | inc_x(ef9345, r); |
| 616 | | if((ef9345->registers[r] & 0x3f) == 0 && r == 7) |
| 617 | | inc_y(ef9345, 6); |
| 618 | | } |
| 619 | | void OCTread(ef9345_t *ef9345, int r, int i) |
| 620 | | { |
| 621 | | set_busy_flag(ef9345, 4.5); |
| 622 | | ef9345->registers[1] = ef9345->ram[indexram(ef9345, r)]; |
| 623 | | if(i == 0) return; |
| 624 | | inc_x(ef9345, r); |
| 756 | state = 0; |
| 757 | if ((registers[5] & 0x3f) == 39) state |= 0x10; //S4(LXa) set |
| 758 | if ((registers[7] & 0x3f) == 39) state |= 0x20; //S5(LXm) set |
| 625 | 759 | |
| 626 | | if((ef9345->registers[r] & 0x3f) == 0 && r == 7) |
| 627 | | inc_y(ef9345, 6); //increment |
| 628 | | } |
| 760 | UINT16 a = indexram(7); |
| 629 | 761 | |
| 630 | | void KRGwrite(ef9345_t *ef9345, int i) //mode 40 caracteres 16 bits |
| 631 | | { |
| 632 | | int a = indexram(ef9345, 7); |
| 633 | | set_busy_flag(ef9345, 5.5); |
| 634 | | ef9345->ram[a] = ef9345->registers[1]; |
| 635 | | ef9345->ram[a + 0x0800] = ef9345->registers[2]; |
| 636 | | if(i) inc_x(ef9345, 7); |
| 637 | | } |
| 638 | | void KRGread(ef9345_t *ef9345, int i) |
| 639 | | { |
| 640 | | int a = indexram(ef9345, 7); |
| 762 | switch(cmd) |
| 763 | { |
| 764 | case 0x00: //KRF: R1,R2,R3->ram |
| 765 | case 0x01: //KRF: R1,R2,R3->ram + increment |
| 766 | set_busy_flag(4); |
| 767 | videoram->write_byte(a, registers[1]); |
| 768 | videoram->write_byte(a + 0x0800, registers[2]); |
| 769 | videoram->write_byte(a + 0x1000, registers[3]); |
| 770 | if (cmd&1) inc_x(7); |
| 771 | break; |
| 772 | case 0x02: //KRG: R1,R2->ram |
| 773 | case 0x03: //KRG: R1,R2->ram + increment |
| 774 | set_busy_flag(5.5); |
| 775 | videoram->write_byte(a, registers[1]); |
| 776 | videoram->write_byte(a + 0x0800, registers[2]); |
| 777 | if (cmd&1) inc_x(7); |
| 778 | break; |
| 779 | case 0x08: //KRF: ram->R1,R2,R3 |
| 780 | case 0x09: //KRF: ram->R1,R2,R3 + increment |
| 781 | set_busy_flag(7.5); |
| 782 | registers[1] = videoram->read_byte(a); |
| 783 | registers[2] = videoram->read_byte(a + 0x0800); |
| 784 | registers[3] = videoram->read_byte(a + 0x1000); |
| 785 | if (cmd&1) inc_x(7); |
| 786 | break; |
| 787 | case 0x0a: //KRG: ram->R1,R2 |
| 788 | case 0x0b: //KRG: ram->R1,R2 + increment |
| 789 | set_busy_flag(7.5); |
| 790 | registers[1] = videoram->read_byte(a); |
| 791 | registers[2] = videoram->read_byte(a + 0x0800); |
| 792 | if (cmd&1) inc_x(7); |
| 793 | break; |
| 794 | case 0x30: //OCT: R1->RAM, main pointer |
| 795 | case 0x31: //OCT: R1->RAM, main pointer + inc |
| 796 | set_busy_flag(4); |
| 797 | videoram->write_byte(indexram(7), registers[1]); |
| 641 | 798 | |
| 642 | | set_busy_flag(ef9345, 7.5); |
| 643 | | ef9345->registers[1] = ef9345->ram[a]; |
| 644 | | ef9345->registers[2] = ef9345->ram[a + 0x0800]; |
| 645 | | if(i) inc_x(ef9345, 7); |
| 646 | | } |
| 799 | if (cmd&1) |
| 800 | { |
| 801 | inc_x(7); |
| 802 | if ((registers[7] & 0x3f) == 0) |
| 803 | inc_y(6); |
| 804 | } |
| 805 | break; |
| 806 | case 0x34: //OCT: R1->RAM, aux pointer |
| 807 | case 0x35: //OCT: R1->RAM, aux pointer + inc |
| 808 | set_busy_flag(4); |
| 809 | videoram->write_byte(indexram(5), registers[1]); |
| 647 | 810 | |
| 648 | | void KRFwrite(ef9345_t *ef9345, int i) //mode 40 caracteres 24 bits |
| 649 | | { |
| 650 | | int a = indexram(ef9345, 7); |
| 811 | if (cmd&1) |
| 812 | inc_x(5); |
| 813 | break; |
| 814 | case 0x38: //OCT: RAM->R1, main pointer |
| 815 | case 0x39: //OCT: RAM->R1, main pointer + inc |
| 816 | set_busy_flag(4.5); |
| 817 | registers[1] = videoram->read_byte(indexram(7)); |
| 651 | 818 | |
| 652 | | set_busy_flag(ef9345, 4); |
| 653 | | ef9345->ram[a] = ef9345->registers[1]; |
| 654 | | ef9345->ram[a + 0x0800] = ef9345->registers[2]; |
| 655 | | ef9345->ram[a + 0x1000] = ef9345->registers[3]; |
| 656 | | if(i) inc_x(ef9345, 7); |
| 657 | | } |
| 819 | if (cmd&1) |
| 820 | { |
| 821 | inc_x(7); |
| 658 | 822 | |
| 659 | | void KRFread(ef9345_t *ef9345, int i) |
| 660 | | { |
| 661 | | int a = indexram(ef9345, 7); |
| 823 | if ((registers[7] & 0x3f) == 0) |
| 824 | inc_y(6); |
| 825 | } |
| 826 | break; |
| 827 | case 0x3c: //OCT: RAM->R1, aux pointer |
| 828 | case 0x3d: //OCT: RAM->R1, aux pointer + inc |
| 829 | set_busy_flag(4.5); |
| 830 | registers[1] = videoram->read_byte(indexram(5)); |
| 662 | 831 | |
| 663 | | set_busy_flag(ef9345, 7.5); |
| 664 | | ef9345->registers[1] = ef9345->ram[a]; |
| 665 | | ef9345->registers[2] = ef9345->ram[a + 0x0800]; |
| 666 | | ef9345->registers[3] = ef9345->ram[a + 0x1000]; |
| 667 | | if(i) inc_x(ef9345, 7); |
| 668 | | } |
| 832 | if (cmd&1) |
| 833 | inc_x(5); |
| 834 | break; |
| 835 | case 0x50: //KRL: 80 UINT8 - 12 bits write |
| 836 | case 0x51: //KRL: 80 UINT8 - 12 bits write + inc |
| 837 | set_busy_flag(12.5); |
| 838 | videoram->write_byte(a, registers[1]); |
| 839 | switch((a / 0x0800) & 1) |
| 840 | { |
| 841 | case 0: |
| 842 | { |
| 843 | UINT8 tmp_data = videoram->read_byte(a + 0x1000); |
| 844 | videoram->write_byte(a + 0x1000, (tmp_data & 0x0f) | (registers[3] & 0xf0)); |
| 845 | break; |
| 846 | } |
| 847 | case 1: |
| 848 | { |
| 849 | UINT8 tmp_data = videoram->read_byte(a + 0x0800); |
| 850 | videoram->write_byte(a + 0x0800, (tmp_data & 0xf0) | (registers[3] & 0x0f)); |
| 851 | break; |
| 852 | } |
| 853 | } |
| 854 | if (cmd&1) |
| 855 | { |
| 856 | if ((registers[7] & 0x80) == 0x00) {registers[7] |= 0x80; return;} |
| 857 | registers[7] &= 0x80; |
| 858 | inc_x(7); |
| 859 | } |
| 860 | break; |
| 861 | case 0x58: //KRL: 80 UINT8 - 12 bits read |
| 862 | case 0x59: //KRL: 80 UINT8 - 12 bits read + inc |
| 863 | set_busy_flag(11.5); |
| 864 | registers[1] = videoram->read_byte(a); |
| 865 | switch((a / 0x0800) & 1) |
| 866 | { |
| 867 | case 0: |
| 868 | registers[3] = videoram->read_byte(a + 0x1000); |
| 869 | break; |
| 870 | case 1: |
| 871 | registers[3] = videoram->read_byte(a + 0x0800); |
| 872 | break; |
| 873 | } |
| 874 | if (cmd&1) |
| 875 | { |
| 876 | if ((registers[7] & 0x80) == 0x00) |
| 877 | { |
| 878 | registers[7] |= 0x80; |
| 879 | break;; |
| 880 | } |
| 881 | registers[7] &= 0x80; |
| 882 | inc_x(7); |
| 883 | } |
| 884 | break; |
| 885 | case 0x80: //IND: R1->ROM (impossible ?) |
| 886 | break; |
| 887 | case 0x81: //IND: R1->TGS |
| 888 | case 0x82: //IND: R1->MAT |
| 889 | case 0x83: //IND: R1->PAT |
| 890 | case 0x84: //IND: R1->DOR |
| 891 | case 0x87: //IND: R1->ROR |
| 892 | set_busy_flag(2); |
| 893 | switch(cmd&7) |
| 894 | { |
| 895 | case 1: TGS = registers[1]; break; |
| 896 | case 2: MAT = registers[1]; break; |
| 897 | case 3: PAT = registers[1]; break; |
| 898 | case 4: DOR = registers[1]; break; |
| 899 | case 7: ROR = registers[1]; break; |
| 900 | } |
| 901 | set_video_mode(); |
| 902 | state &= 0x8f; //reset S4(LXa), S5(LXm), S6(Al) |
| 903 | break; |
| 904 | case 0x88: //IND: ROM->R1 |
| 905 | case 0x89: //IND: TGS->R1 |
| 906 | case 0x8a: //IND: MAT->R1 |
| 907 | case 0x8b: //IND: PAT->R1 |
| 908 | case 0x8c: //IND: DOR->R1 |
| 909 | case 0x8f: //IND: ROR->R1 |
| 910 | set_busy_flag(3.5); |
| 911 | switch(cmd&7) |
| 912 | { |
| 913 | case 0: registers[1] = charset->u8(indexrom(7) & 0x1fff); |
| 914 | case 1: registers[1] = TGS; break; |
| 915 | case 2: registers[1] = MAT; break; |
| 916 | case 3: registers[1] = PAT; break; |
| 917 | case 4: registers[1] = DOR; break; |
| 918 | case 7: registers[1] = ROR; break; |
| 919 | } |
| 920 | state &= 0x8f; //reset S4(LXa), S5(LXm), S6(Al) |
| 921 | break; |
| 922 | case 0x90: //NOP: no operation |
| 923 | case 0x91: //NOP: no operation |
| 924 | case 0x95: //VRM: vertical sync mask reset |
| 925 | case 0x99: //VSM: vertical sync mask set |
| 926 | break; |
| 927 | case 0xb0: //INY: increment Y |
| 928 | set_busy_flag(2); |
| 929 | inc_y(6); |
| 930 | state &= 0x8f; //reset S4(LXa), S5(LXm), S6(Al) |
| 931 | break; |
| 932 | case 0xd5: //MVB: move buffer MP->AP stop |
| 933 | case 0xd6: //MVB: move buffer MP->AP nostop |
| 934 | case 0xd9: //MVB: move buffer AP->MP stop |
| 935 | case 0xda: //MVB: move buffer AP->MP nostop |
| 936 | case 0xe5: //MVD: move double buffer MP->AP stop |
| 937 | case 0xe6: //MVD: move double buffer MP->AP nostop |
| 938 | case 0xe9: //MVD: move double buffer AP->MP stop |
| 939 | case 0xea: //MVD: move double buffer AP->MP nostop |
| 940 | case 0xf5: //MVT: move triple buffer MP->AP stop |
| 941 | case 0xf6: //MVT: move triple buffer MP->AP nostop |
| 942 | case 0xf9: //MVT: move triple buffer AP->MP stop |
| 943 | case 0xfa: //MVT: move triple buffer AP->MP nostop |
| 944 | { |
| 945 | UINT16 i, a1, a2; |
| 946 | UINT8 n = (cmd>>4) - 0x0c; |
| 947 | UINT8 r1 = (cmd&0x04) ? 7 : 5; |
| 948 | UINT8 r2 = (cmd&0x04) ? 5 : 7; |
| 949 | int busy = 2; |
| 669 | 950 | |
| 670 | | void KRLwrite(ef9345_t *ef9345, int i) //mode 80 caracteres 12 bits |
| 671 | | { |
| 672 | | int a = indexram(ef9345, 7); |
| 951 | for(i = 0; i < 1280; i++) |
| 952 | { |
| 953 | a1 = indexram(r1); a2 = indexram(r2); |
| 954 | videoram->write_byte(a2, videoram->read_byte(a1)); |
| 673 | 955 | |
| 674 | | set_busy_flag(ef9345, 12.5); |
| 675 | | ef9345->ram[a] = ef9345->registers[1]; |
| 676 | | switch((a / 0x800) & 1) |
| 677 | | { |
| 678 | | case 0: ef9345->ram[a + 0x1000] &= 0x0f; |
| 679 | | ef9345->ram[a + 0x1000] |= (ef9345->registers[3] & 0xf0); break; |
| 680 | | case 1: ef9345->ram[a + 0x0800] &= 0xf0; |
| 681 | | ef9345->ram[a + 0x0800] |= (ef9345->registers[3] & 0x0f); break; |
| 682 | | } |
| 683 | | if(i) |
| 684 | | { |
| 685 | | if((ef9345->registers[7] & 0x80) == 0x00) {ef9345->registers[7] |= 0x80; return;} |
| 686 | | ef9345->registers[7] &= 0x80; |
| 687 | | inc_x(ef9345, 7); |
| 688 | | } |
| 689 | | } |
| 956 | if (n > 1) videoram->write_byte(a2 + 0x0800, videoram->read_byte(a1 + 0x0800)); |
| 957 | if (n > 2) videoram->write_byte(a2 + 0x1000, videoram->read_byte(a1 + 0x1000)); |
| 690 | 958 | |
| 691 | | void KRLread(ef9345_t *ef9345, int i) |
| 692 | | { |
| 693 | | int a = indexram(ef9345, 7); |
| 959 | inc_x(r1); |
| 960 | inc_x(r2); |
| 961 | if ((registers[5] & 0x3f) == 0 && (cmd&1)) |
| 962 | break; |
| 694 | 963 | |
| 695 | | set_busy_flag(ef9345, 11.5); |
| 696 | | ef9345->registers[1] = ef9345->ram[a]; |
| 697 | | switch((a / 0x800) & 1) |
| 698 | | { |
| 699 | | case 0: ef9345->registers[3] = ef9345->ram[a + 0x1000]; break; |
| 700 | | case 1: ef9345->registers[3] = ef9345->ram[a + 0x0800]; break; |
| 701 | | } |
| 702 | | if(i) |
| 703 | | { |
| 704 | | if((ef9345->registers[7] & 0x80) == 0x00) {ef9345->registers[7] |= 0x80; return;} |
| 705 | | ef9345->registers[7] &= 0x80; |
| 706 | | inc_x(ef9345, 7); |
| 707 | | } |
| 708 | | } |
| 964 | if ((registers[7] & 0x3f) == 0) |
| 965 | { |
| 966 | if (cmd&1) |
| 967 | break; |
| 968 | else |
| 969 | inc_y(6); |
| 970 | } |
| 709 | 971 | |
| 710 | | // Move buffer |
| 711 | | void MVB(ef9345_t *ef9345, int n, int r1, int r2, int s) |
| 712 | | { |
| 713 | | //s=1 pour mode normal, s=0 pour remplir tout le buffer |
| 714 | | int i, a1, a2; |
| 715 | | |
| 716 | | set_busy_flag(ef9345, 2); |
| 717 | | for(i = 0; i < 1280; i++) |
| 718 | | { |
| 719 | | a1 = indexram(ef9345, r1); a2 = indexram(ef9345, r2); |
| 720 | | ef9345->ram[a2] = ef9345->ram[a1]; //ef9345_cycle += 16 * n; |
| 721 | | if(n > 1) ef9345->ram[a2 + 0x0800] = ef9345->ram[a1 + 0x0800]; |
| 722 | | if(n > 2) ef9345->ram[a2 + 0x1000] = ef9345->ram[a1 + 0x1000]; |
| 723 | | inc_x(ef9345, r1); inc_x(ef9345, r2); |
| 724 | | if((ef9345->registers[5] & 0x3f) == 0) {if(s) break;} |
| 725 | | if((ef9345->registers[7] & 0x3f) == 0) {if(s) break; else inc_y(ef9345, 6);} |
| 972 | busy += 4 * n; |
| 973 | } |
| 974 | state &= 0x8f; //reset S4(LXa), S5(LXm), S6(Al) |
| 975 | set_busy_flag(busy); |
| 976 | } |
| 977 | break; |
| 978 | case 0x05: //CLF: Clear page 24 bits |
| 979 | case 0x07: //CLG: Clear page 16 bits |
| 980 | case 0x40: //KRC: R1 -> ram |
| 981 | case 0x41: //KRC: R1 -> ram + inc |
| 982 | case 0x48: //KRC: 80 characters - 8 bits |
| 983 | case 0x49: //KRC: 80 characters - 8 bits |
| 984 | default: |
| 985 | logerror("Unemulated EF9345 cmd: %02x\n", cmd); |
| 726 | 986 | } |
| 727 | | ef9345->state &= 0x8f; //reset S4(LXa), S5(LXm), S6(Al) |
| 728 | 987 | } |
| 729 | 988 | |
| 730 | | // Increment registre R6 |
| 731 | | void INY(ef9345_t *ef9345) |
| 732 | | { |
| 733 | | set_busy_flag(ef9345, 2); |
| 734 | | inc_y(ef9345, 6); |
| 735 | | ef9345->state &= 0x8f; //reset S4(LXa), S5(LXm), S6(Al) |
| 736 | | } |
| 737 | 989 | |
| 738 | | // Lecture/Ecriture des registres indirects |
| 739 | | void INDwrite(ef9345_t *ef9345, int x) |
| 740 | | { |
| 741 | | set_busy_flag(ef9345, 2); |
| 742 | | switch(x) |
| 743 | | { |
| 744 | | case 1: ef9345->TGS = ef9345->registers[1]; break; |
| 745 | | case 2: ef9345->MAT = ef9345->registers[1]; break; |
| 746 | | case 3: ef9345->PAT = ef9345->registers[1]; break; |
| 747 | | case 4: ef9345->DOR = ef9345->registers[1]; break; |
| 748 | | case 7: ef9345->ROR = ef9345->registers[1]; break; |
| 749 | | } |
| 750 | | set_ef9345_mode(ef9345); |
| 751 | | ef9345->state &= 0x8f; //reset S4(LXa), S5(LXm), S6(Al) |
| 752 | | } |
| 753 | | |
| 754 | | void INDread(ef9345_t *ef9345, int x) |
| 755 | | { |
| 756 | | set_busy_flag(ef9345, 3.5); |
| 757 | | switch(x) |
| 758 | | { |
| 759 | | case 0: ef9345->registers[1] = ef9345->charset[indexrom(ef9345, 7) & 0x1fff]; break; |
| 760 | | case 1: ef9345->registers[1] = ef9345->TGS; break; |
| 761 | | case 2: ef9345->registers[1] = ef9345->MAT; break; |
| 762 | | case 3: ef9345->registers[1] = ef9345->PAT; break; |
| 763 | | case 4: ef9345->registers[1] = ef9345->DOR; break; |
| 764 | | case 7: ef9345->registers[1] = ef9345->ROR; break; |
| 765 | | case 8: ef9345->registers[1] = ef9345->ROR; break; |
| 766 | | } |
| 767 | | ef9345->state &= 0x8f; //reset S4(LXa), S5(LXm), S6(Al) |
| 768 | | } |
| 769 | | |
| 770 | | // Execute EF9345 command |
| 771 | | void ef9345_exec(ef9345_t *ef9345, UINT8 cmd) |
| 772 | | { |
| 773 | | ef9345->state = 0; |
| 774 | | if((ef9345->registers[5] & 0x3f) == 39) ef9345->state |= 0x10; //S4(LXa) set |
| 775 | | if((ef9345->registers[7] & 0x3f) == 39) ef9345->state |= 0x20; //S5(LXm) set |
| 776 | | |
| 777 | | switch(cmd) |
| 778 | | { |
| 779 | | case 0x00: KRFwrite(ef9345, 0); break; //KRF: R1,R2,R3->ram |
| 780 | | case 0x01: KRFwrite(ef9345, 1); break; //KRF: R1,R2,R3->ram + increment |
| 781 | | case 0x02: KRGwrite(ef9345, 0); break; //KRG: R1,R2->ram |
| 782 | | case 0x03: KRGwrite(ef9345, 1); break; //KRG: R1,R2->ram + increment |
| 783 | | case 0x05: break; //CLF: Clear page 24 bits |
| 784 | | case 0x07: break; //CLG: Clear page 16 bits |
| 785 | | case 0x08: KRFread(ef9345, 0); break; //KRF: ram->R1,R2,R3 |
| 786 | | case 0x09: KRFread(ef9345, 1); break; //KRF: ram->R1,R2,R3 + increment |
| 787 | | case 0x0a: KRGread(ef9345, 0); break; //KRG: ram->R1,R2 |
| 788 | | case 0x0b: KRGread(ef9345, 1); break; //KRG: ram->R1,R2 + increment |
| 789 | | case 0x30: OCTwrite(ef9345, 7, 0); break; //OCT: R1->RAM, main pointer |
| 790 | | case 0x31: OCTwrite(ef9345, 7, 1); break; //OCT: R1->RAM, main pointer + inc |
| 791 | | case 0x34: OCTwrite(ef9345, 5, 0); break; //OCT: R1->RAM, aux pointer |
| 792 | | case 0x35: OCTwrite(ef9345, 5, 1); break; //OCT: R1->RAM, aux pointer + inc |
| 793 | | case 0x38: OCTread(ef9345, 7, 0); break; //OCT: RAM->R1, main pointer |
| 794 | | case 0x39: OCTread(ef9345, 7, 1); break; //OCT: RAM->R1, main pointer + inc |
| 795 | | case 0x3c: OCTread(ef9345, 5, 0); break; //OCT: RAM->R1, aux pointer |
| 796 | | case 0x3d: OCTread(ef9345, 5, 1); break; //OCT: RAM->R1, aux pointer + inc |
| 797 | | case 0x40: break; //KRC: R1 -> ram |
| 798 | | case 0x41: break; //KRC: R1 -> ram + inc |
| 799 | | case 0x48: break; //KRC: 80 characters - 8 bits |
| 800 | | case 0x49: break; //KRC: 80 characters - 8 bits |
| 801 | | case 0x50: KRLwrite(ef9345, 0); break; //KRL: 80 UINT8 - 12 bits write |
| 802 | | case 0x51: KRLwrite(ef9345, 1); break; //KRL: 80 UINT8 - 12 bits write + inc |
| 803 | | case 0x58: KRLread(ef9345, 0); break; //KRL: 80 UINT8 - 12 bits read |
| 804 | | case 0x59: KRLread(ef9345, 1); break; //KRL: 80 UINT8 - 12 bits read + inc |
| 805 | | case 0x80: break; //IND: R1->ROM (impossible ?) |
| 806 | | case 0x81: INDwrite(ef9345, 1); break; //IND: R1->ef9345->TGS |
| 807 | | case 0x82: INDwrite(ef9345, 2); break; //IND: R1->ef9345->MAT |
| 808 | | case 0x83: INDwrite(ef9345, 3); break; //IND: R1->ef9345->PAT |
| 809 | | case 0x84: INDwrite(ef9345, 4); break; //IND: R1->ef9345->DOR |
| 810 | | case 0x87: INDwrite(ef9345, 7); break; //IND: R1->ef9345->ROR |
| 811 | | case 0x88: INDread(ef9345, 0); break; //IND: ROM->R1 |
| 812 | | case 0x89: INDread(ef9345, 1); break; //IND: ef9345->TGS->R1 |
| 813 | | case 0x8a: INDread(ef9345, 2); break; //IND: ef9345->MAT->R1 |
| 814 | | case 0x8b: INDread(ef9345, 3); break; //IND: ef9345->PAT->R1 |
| 815 | | case 0x8c: INDread(ef9345, 4); break; //IND: ef9345->DOR->R1 |
| 816 | | case 0x8f: INDread(ef9345, 7); break; //IND: ef9345->ROR->R1 |
| 817 | | case 0x90: break; //NOP: no operation |
| 818 | | case 0x91: break; //NOP: no operation |
| 819 | | case 0x95: break; //VRM: vertical sync mask reset |
| 820 | | case 0x99: break; //VSM: vertical sync mask set |
| 821 | | case 0xb0: INY(ef9345); break; //INY: increment Y |
| 822 | | case 0xd5: MVB(ef9345, 1, 7, 5, 1); break; //MVB: move buffer MP->AP stop |
| 823 | | case 0xd6: MVB(ef9345, 1, 7, 5, 0); break; //MVB: move buffer MP->AP nostop |
| 824 | | case 0xd9: MVB(ef9345, 1, 5, 7, 1); break; //MVB: move buffer AP->MP stop |
| 825 | | case 0xda: MVB(ef9345, 1, 5, 7, 0); break; //MVB: move buffer AP->MP nostop |
| 826 | | case 0xe5: MVB(ef9345, 2, 7, 5, 1); break; //MVD: move double buffer MP->AP stop |
| 827 | | case 0xe6: MVB(ef9345, 2, 7, 5, 0); break; //MVD: move double buffer MP->AP nostop |
| 828 | | case 0xe9: MVB(ef9345, 2, 5, 7, 1); break; //MVD: move double buffer AP->MP stop |
| 829 | | case 0xea: MVB(ef9345, 2, 5, 7, 0); break; //MVD: move double buffer AP->MP nostop |
| 830 | | case 0xf5: MVB(ef9345, 3, 7, 5, 1); break; //MVT: move triple buffer MP->AP stop |
| 831 | | case 0xf6: MVB(ef9345, 3, 7, 5, 0); break; //MVT: move triple buffer MP->AP nostop |
| 832 | | case 0xf9: MVB(ef9345, 3, 5, 7, 1); break; //MVT: move triple buffer AP->MP stop |
| 833 | | case 0xfa: MVB(ef9345, 3, 5, 7, 0); break; //MVT: move triple buffer AP->MP nostop |
| 834 | | default: logerror("Unemulated EF9345 cmd: %02x\n", cmd); |
| 835 | | } |
| 836 | | } |
| 837 | | |
| 838 | | |
| 839 | 990 | /************************************************************** |
| 840 | 991 | EF9345 interface |
| 841 | 992 | **************************************************************/ |
| 842 | 993 | |
| 843 | | void video_update_ef9345(running_device *device, bitmap_t *bitmap, const rectangle *cliprect) |
| 994 | void ef9345_device::video_update(bitmap_t *bitmap, const rectangle *cliprect) |
| 844 | 995 | { |
| 845 | | ef9345_t *ef9345 = get_safe_token(device); |
| 846 | | copybitmap(bitmap, ef9345->screen_out, 0, 0, 0, 0, cliprect); |
| 996 | copybitmap(bitmap, screen_out, 0, 0, 0, 0, cliprect); |
| 847 | 997 | } |
| 848 | 998 | |
| 849 | | |
| 850 | | READ8_DEVICE_HANDLER ( ef9345_r ) |
| 999 | void ef9345_device::update_scanline(UINT16 scanline) |
| 851 | 1000 | { |
| 852 | | ef9345_t *ef9345 = get_safe_token(device); |
| 1001 | UINT16 i; |
| 853 | 1002 | |
| 854 | | if(offset & 7) |
| 855 | | return ef9345->registers[offset & 7]; |
| 856 | | |
| 857 | | if(ef9345->bf) |
| 858 | | ef9345->state |= 0x80; |
| 859 | | else |
| 860 | | ef9345->state &= 0x7f; |
| 861 | | |
| 862 | | return ef9345->state; |
| 863 | | } |
| 864 | | |
| 865 | | |
| 866 | | WRITE8_DEVICE_HANDLER ( ef9345_w ) |
| 867 | | { |
| 868 | | ef9345_t *ef9345 = get_safe_token(device); |
| 869 | | |
| 870 | | ef9345->registers[offset & 7] = data; |
| 871 | | |
| 872 | | if(offset & 8) |
| 873 | | ef9345_exec(ef9345, ef9345->registers[0] & 0xff); |
| 874 | | } |
| 875 | | |
| 876 | | |
| 877 | | static TIMER_CALLBACK( ef9345_done ) |
| 878 | | { |
| 879 | | running_device *device = (running_device *)ptr; |
| 880 | | ef9345_t *ef9345 = get_safe_token(device); |
| 881 | | |
| 882 | | ef9345->bf = 0; |
| 883 | | } |
| 884 | | |
| 885 | | void draw_border(ef9345_t *ef9345, UINT8 line) |
| 886 | | { |
| 887 | | UINT8 i; |
| 888 | | |
| 889 | | if (ef9345->char_mode == MODE12x80 || ef9345->char_mode == MODE8x80) |
| 890 | | for(i = 0; i < 82; i++) |
| 891 | | draw_char_80(ef9345, ef9345->border, i, line); |
| 892 | | else |
| 893 | | for(i = 0; i < 42; i++) |
| 894 | | draw_char_40(ef9345, ef9345->border, i, line); |
| 895 | | } |
| 896 | | |
| 897 | | void ef9345_scanline(running_device *device, UINT16 scanline) |
| 898 | | { |
| 899 | | ef9345_t *ef9345 = get_safe_token(device); |
| 900 | | UINT8 i; |
| 901 | | |
| 902 | 1003 | if (scanline == 250) |
| 903 | | ef9345->state &= 0xfb; |
| 1004 | state &= 0xfb; |
| 904 | 1005 | |
| 905 | | set_busy_flag(ef9345, 104); |
| 1006 | set_busy_flag(104); |
| 906 | 1007 | |
| 907 | | if (ef9345->char_mode == MODE12x80 || ef9345->char_mode == MODE8x80) |
| 1008 | if (char_mode == MODE12x80 || char_mode == MODE8x80) |
| 908 | 1009 | { |
| 909 | | draw_char_80(ef9345, ef9345->border, 0, (scanline / 10) + 1); |
| 910 | | draw_char_80(ef9345, ef9345->border, 81, (scanline / 10) + 1); |
| 1010 | draw_char_80(border, 0, (scanline / 10) + 1); |
| 1011 | draw_char_80(border, 81, (scanline / 10) + 1); |
| 911 | 1012 | } |
| 912 | 1013 | else |
| 913 | 1014 | { |
| 914 | | draw_char_40(ef9345, ef9345->border, 0, (scanline / 10) + 1); |
| 915 | | draw_char_40(ef9345, ef9345->border, 41, (scanline / 10) + 1); |
| 1015 | draw_char_40(border, 0, (scanline / 10) + 1); |
| 1016 | draw_char_40(border, 41, (scanline / 10) + 1); |
| 916 | 1017 | } |
| 917 | 1018 | |
| 918 | | if(scanline == 0) |
| 1019 | if (scanline == 0) |
| 919 | 1020 | { |
| 920 | | ef9345->state |= 0x04; |
| 921 | | draw_border(ef9345, 0); |
| 922 | | if(ef9345->PAT & 1) |
| 1021 | state |= 0x04; |
| 1022 | draw_border(0); |
| 1023 | if (PAT & 1) |
| 923 | 1024 | for(i = 0; i < 40; i++) |
| 924 | | makechar(ef9345, i, (scanline / 10)); |
| 1025 | makechar(i, (scanline / 10)); |
| 925 | 1026 | else |
| 926 | 1027 | for(i = 0; i < 42; i++) |
| 927 | | draw_char_40(ef9345, ef9345->border, i, 1); |
| 1028 | draw_char_40(border, i, 1); |
| 928 | 1029 | } |
| 929 | | else if(scanline < 120) |
| 1030 | else if (scanline < 120) |
| 930 | 1031 | { |
| 931 | | if(ef9345->PAT & 2) |
| 1032 | if (PAT & 2) |
| 932 | 1033 | for(i = 0; i < 40; i++) |
| 933 | | makechar(ef9345, i, (scanline / 10)); |
| 1034 | makechar(i, (scanline / 10)); |
| 934 | 1035 | else |
| 935 | | draw_border(ef9345, scanline / 10); |
| 1036 | draw_border(scanline / 10); |
| 936 | 1037 | } |
| 937 | | else if(scanline < 250) |
| 1038 | else if (scanline < 250) |
| 938 | 1039 | { |
| 939 | | if(ef9345->PAT & 4) |
| 1040 | if (PAT & 4) |
| 940 | 1041 | for(i = 0; i < 40; i++) |
| 941 | | makechar(ef9345, i, (scanline / 10)); |
| 1042 | makechar(i, (scanline / 10)); |
| 942 | 1043 | else |
| 943 | | draw_border(ef9345, scanline / 10); |
| 1044 | draw_border(scanline / 10); |
| 944 | 1045 | |
| 945 | | if(scanline == 240) |
| 946 | | draw_border(ef9345, 26); |
| 1046 | if (scanline == 240) |
| 1047 | draw_border(26); |
| 947 | 1048 | } |
| 948 | 1049 | } |
| 949 | 1050 | |
| 950 | | |
| 951 | | static TIMER_CALLBACK( blinking ) |
| 1051 | READ8_MEMBER( ef9345_device::data_r ) |
| 952 | 1052 | { |
| 953 | | running_device *device = (running_device *)ptr; |
| 954 | | ef9345_t *ef9345 = get_safe_token(device); |
| 1053 | if (offset & 7) |
| 1054 | return registers[offset & 7]; |
| 955 | 1055 | |
| 956 | | ef9345->blink = (!ef9345->blink) & 0x01; |
| 957 | | } |
| 1056 | if (bf) |
| 1057 | state |= 0x80; |
| 1058 | else |
| 1059 | state &= 0x7f; |
| 958 | 1060 | |
| 959 | | |
| 960 | | /*------------------------------------------------- |
| 961 | | DEVICE_RESET( ef9345 ) |
| 962 | | -------------------------------------------------*/ |
| 963 | | static DEVICE_RESET( ef9345 ) |
| 964 | | { |
| 965 | | ef9345_t *ef9345 = get_safe_token(device); |
| 966 | | |
| 967 | | ef9345->TGS = 0; |
| 968 | | ef9345->MAT = 0; |
| 969 | | ef9345->PAT = 0; |
| 970 | | ef9345->DOR = 0; |
| 971 | | ef9345->ROR = 0; |
| 972 | | ef9345->state = 0; |
| 973 | | ef9345->bf = 0; |
| 974 | | ef9345->blink = 0; |
| 975 | | ef9345->dial = 0; |
| 976 | | ef9345->latchc0 = 0; |
| 977 | | ef9345->latchm = 0; |
| 978 | | ef9345->latchi = 0; |
| 979 | | ef9345->latchu = 0; |
| 980 | | ef9345->char_mode = 0; |
| 981 | | |
| 982 | | memset(ef9345->last_dial, 0, sizeof(ef9345->last_dial)); |
| 983 | | memset(ef9345->ram, 0, sizeof(ef9345->ram)); |
| 984 | | memset(ef9345->registers, 0, sizeof(ef9345->registers)); |
| 985 | | memset(ef9345->border, 0, sizeof(ef9345->border)); |
| 986 | | |
| 987 | | bitmap_fill(ef9345->screen_out, NULL, 0); |
| 988 | | |
| 989 | | set_ef9345_mode(ef9345); |
| 1061 | return state; |
| 990 | 1062 | } |
| 991 | 1063 | |
| 992 | | |
| 993 | | /*------------------------------------------------- |
| 994 | | DEVICE_START( ef9345 ) |
| 995 | | -------------------------------------------------*/ |
| 996 | | static DEVICE_START( ef9345 ) |
| 1064 | WRITE8_MEMBER( ef9345_device::data_w ) |
| 997 | 1065 | { |
| 998 | | ef9345_t *ef9345 = get_safe_token(device); |
| 999 | | const ef9345_config *config = (ef9345_config*)device->baseconfig().static_config(); |
| 1066 | registers[offset & 7] = data; |
| 1000 | 1067 | |
| 1001 | | /* validate arguments */ |
| 1002 | | assert(device != NULL); |
| 1003 | | |
| 1004 | | ef9345->charset = memory_region(device->machine, config->charset); |
| 1005 | | |
| 1006 | | ef9345->screen = device->machine->device<screen_device>(config->screen_tag); |
| 1007 | | assert(ef9345->screen != NULL); |
| 1008 | | |
| 1009 | | ef9345->busy_timer = timer_alloc(device->machine, ef9345_done, (void *)device); |
| 1010 | | ef9345->blink_timer = timer_alloc(device->machine, blinking, (void *)device); |
| 1011 | | |
| 1012 | | ef9345->screen_out = auto_bitmap_alloc(device->machine, 496, ef9345->screen->height() , BITMAP_FORMAT_INDEXED16); |
| 1013 | | |
| 1014 | | timer_adjust_periodic(ef9345->blink_timer, ATTOTIME_IN_MSEC(500), 0, ATTOTIME_IN_MSEC(500)); |
| 1015 | | |
| 1016 | | init_char_prt(ef9345); |
| 1017 | | |
| 1018 | | state_save_register_device_item_array(device, 0, ef9345->ram); |
| 1019 | | state_save_register_device_item_array(device, 0, ef9345->border); |
| 1020 | | state_save_register_device_item_array(device, 0, ef9345->registers); |
| 1021 | | state_save_register_device_item_array(device, 0, ef9345->last_dial); |
| 1022 | | |
| 1023 | | state_save_register_device_item(device, 0, ef9345->bf); |
| 1024 | | state_save_register_device_item(device, 0, ef9345->char_mode); |
| 1025 | | state_save_register_device_item(device, 0, ef9345->state); |
| 1026 | | state_save_register_device_item(device, 0, ef9345->TGS); |
| 1027 | | state_save_register_device_item(device, 0, ef9345->MAT); |
| 1028 | | state_save_register_device_item(device, 0, ef9345->PAT); |
| 1029 | | state_save_register_device_item(device, 0, ef9345->DOR); |
| 1030 | | state_save_register_device_item(device, 0, ef9345->ROR); |
| 1031 | | state_save_register_device_item(device, 0, ef9345->blink); |
| 1032 | | state_save_register_device_item(device, 0, ef9345->dial); |
| 1033 | | state_save_register_device_item(device, 0, ef9345->latchc0); |
| 1034 | | state_save_register_device_item(device, 0, ef9345->latchm); |
| 1035 | | state_save_register_device_item(device, 0, ef9345->latchi); |
| 1036 | | state_save_register_device_item(device, 0, ef9345->latchu); |
| 1037 | | |
| 1038 | | state_save_register_device_item_bitmap(device, 0, ef9345->screen_out); |
| 1068 | if (offset & 8) |
| 1069 | ef9345_exec(registers[0] & 0xff); |
| 1039 | 1070 | } |
| 1040 | | |
| 1041 | | DEVICE_GET_INFO( ef9345 ) |
| 1042 | | { |
| 1043 | | switch (state) |
| 1044 | | { |
| 1045 | | /* --- the following bits of info are returned as 64-bit signed integers --- */ |
| 1046 | | case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(ef9345_t); break; |
| 1047 | | case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(ef9345_config); break; |
| 1048 | | |
| 1049 | | /* --- the following bits of info are returned as pointers to data or functions --- */ |
| 1050 | | case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(ef9345); break; |
| 1051 | | case DEVINFO_FCT_STOP: /* Nothing */ break; |
| 1052 | | case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(ef9345); break; |
| 1053 | | case DEVINFO_PTR_ROM_REGION: /* Nothing */ break; |
| 1054 | | |
| 1055 | | /* --- the following bits of info are returned as NULL-terminated strings --- */ |
| 1056 | | case DEVINFO_STR_NAME: strcpy(info->s, "SGS Thomson EF9345"); break; |
| 1057 | | case DEVINFO_STR_FAMILY: strcpy(info->s, "EF9345"); break; |
| 1058 | | case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break; |
| 1059 | | case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; |
| 1060 | | case DEVINFO_STR_CREDITS: strcpy(info->s, "Daniel Coulom"); break; |
| 1061 | | } |
| 1062 | | } |
| 1063 | | |
| 1064 | | DEFINE_LEGACY_DEVICE(EF9345, ef9345); |