Тяжела и неказиста жизнь советского артиста (c) Для начала сделать бы клавиатуру и видео...
Вид для печати
Тяжела и неказиста жизнь советского артиста (c) Для начала сделать бы клавиатуру и видео...
Описание матрицы нашлось в исходниках BIOS -- TBL_KBDP.ASM и SCANINT2.ASM, опрос делается по таймеру (канал 1 заведен на IRQ6). Разумеется, у Поиска-91 матрица немного другая.
http://img-fotki.yandex.ru/get/9150/...428e358_XL.png
В комментарии к исходникам упоминается нечто по имени ИНТЕК. Что это?
Код:; -- таблица клавиш для ИНТЕК ( по новому ГОСТу )
; бит 7 - признак необходимости инвертирования SHIFT
;----------------------------------------------------------------------------
; ------------нет спецсимволов--- SHIFT1 ----SHIFT2-----позиция в матрице--
; ИНТЕК ПОИСК
LN_KEY1 DB 80H+09H, 04H, 80H+29H ; 1/12 1 4/7
На досуге ковырялся с PCem... Хочется все-таки сделать эмулятор с соблюдением тактов 8088, чтоб по скорости было максимально похоже на Поиск. Ну и чтоб работал "честно", то есть рисовал все символы программно, как это делает реал.
Пытался впилить в него обработку NMI. BTW, обработки NMI практически ни у кого нет, ни у fake86, ни у PCE. Вообще, хорошо если TRAP (int 1) обрабатывают, некоторые и на него забивают. Ввел несколько переменных и флагов:
Дальше vid_cga.c. Откуда-то скопипастил такую процедуру установки графического режима в CGA через порты. В качестве аргумента (mode) - 0x1E это по идее 640x400, 0x2E - это 320x200.Код:// POISK variables
uint16_t p28h; // port 28 value
uint8_t nmi_enabled; // NMI enabled ?
uint8_t nmi_int_now=0; // force NMI
uint8_t in_nmi=0; // in NMI?
uint8_t p6Ah,p68h; // port 6Ah and port 68h
Процедура обработки порта 68. Смотрит, не сменился ли режим, если сменился - устанавливает новый. Также устанавливает флаг разрешения или запрещения NMI.Код:static int mode_graph[] = {0x38, 0x28, 0x2D, 0x0A, 0x7F, 0x06,
0x64, 0x70, 2, 1, 6, 7,0, 0, 0, 0};
void set_poisk_mode(uint8_t mode)
#define MODE_REG 0x3d8
#define VID_DISABLE 0
#define ADDRESS_REG 0x3d4
#define REGISTER_PORT 0x3d5
{
int loop_count = 0;
cga_out(MODE_REG,VID_DISABLE); /*disable video signal */
for( ; loop_count < 0x0e; ++loop_count) {
cga_out( ADDRESS_REG, loop_count ); /* set up CRT register */
cga_out( REGISTER_PORT, mode_graph[loop_count]); /* write to reg */
}
cga_out( MODE_REG, mode); /* switch in mode now */;
}
При возникновении NMI в порт 28 должно находится смещение, куда произошла запись:Код:void poisk_out(uint16_t addr, uint8_t val)
{
uint8_t b;
uint8_t tmp_b;
switch (addr)
{
case 0x68:
p68h = val;
b = 0x2e; //320x200
if (val & 0x80) b = 0x1e; //hires
if (poisk_mode != b)
{
poisk_mode = b;
set_poisk_mode(b);
pclog("POISK set mode %02X: \n",b);
}
if (!(val & 8))
{
nmi_enabled = 1;
pclog("[poisk] NMI enable\n");
}
else
{
nmi_enabled = 0;
pclog("[poisk] NMI disable\n");
}
pclog("POISK 68h value: %02X cgamode: %02X cgacol: %02X\n",val,tmp_b,b);
return;
case 0x6A:
p6Ah = val;
val = p68h;
// TO DO:
return;
}
}
uint8_t poisk_in(uint16_t addr)
{
switch (addr)
{
case 0x68:
return p68h;
case 0x6A:
return p6Ah;
}
return 0xFF;
}
Дальше, установил новые хендлеры для портов:Код:uint16_t p28h_in(uint16_t addr)
{
switch (addr)
{
case 0x28:
{
pclog("[poisk] IN 0x28h = %04X\n",(p28h) & 0xFF);
return ((p28h) & 0xFF);
}
case 0x29:
{
pclog("[poisk] IN 0x29h = %04X\n",(p28h>>8) & 0xFF);
return ((p28h>>8) & 0xFF);
}
}
}
Если что-то пишет в видео-память, проверить разрешены ли NMI, если разрешены - запомнить смещение куда произошла запись (для обработки 28 порта) и установить флаг вызова NMI.Код:io_sethandler(0x0068, 0x0002, poisk_in, NULL, NULL, poisk_out, NULL, NULL);
io_sethandler(0x006A, 0x0002, poisk_in, NULL, NULL, poisk_out, NULL, NULL);
io_sethandler(0x0028, 0x0002, p28h_in, NULL, NULL, NULL, NULL, NULL);
Дальше в x86.c обработку NMI сделал по аналогии обработки IRQ с PIC, вставил такой текст:Код:void cga_write(uint32_t addr, uint8_t val)
{
// pclog("CGA_WRITE %04X %02X\n", addr, val);
vram[addr&0x3FFF]=val;
charbuffer[ ((int)(((dispontime - vidtime) * 2) / CGACONST)) & 0xfc] = val;
charbuffer[(((int)(((dispontime - vidtime) * 2) / CGACONST)) & 0xfc) | 1] = val;
cycles -= 4;
p28h = addr&0x3FFF;
if (nmi_enabled == 1)
{
flags&=~I_FLAG;
nmi_int_now = 1;
}
}
Пока результата никакого.Код:if (nmi_int_now && !in_nmi && !ssegs && !noint) // NMI interrupt
{
pclog("NMI INT NOW\n");
//if (ssegs) ss=oldss;
// if (inhlt) pc++;
writememw(ss,((SP-2)&0xFFFF),flags|0xF000);
writememw(ss,((SP-4)&0xFFFF),CS);
writememw(ss,((SP-6)&0xFFFF),pc);
SP-=6;
addr=2<<2;
flags&=~I_FLAG;
flags&=~T_FLAG;
pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
FETCHCLEAR();
inint=1;
nmi_int_now=0;
in_nmi=1;
cycles-=72;
}
Tronix, огромное Вам спасибо за habrapost!
Предлагаю не распылять усилия и пилить таки MESS, в нем заметно больше готовых запчастей.
Пока что безуспешно борюсь с эмуляцией клавиатуры -- алфавитные клавиши работают нормально, но прочие посылают весьма странные сканкоды.
Кто-нибудь помнит, как выглядел 4-тый нортон на Поиске? С цветами не совсем понятно. У меня в эмуляторе получилось вот так:
Привет!
Вместо Зелёного берюзовый!!!
Да, если смотреть на палитру 1 в графическом режиме это цвет cyan (0x01), или light cyan