PDA

Просмотр полной версии : насчет эмуляции ULA



boo_boo
19.01.2007, 01:55
во многих эмулях практикуется такой подход к эмуляции ULA-видеоконтроллера: после того, как процессор исполнит очередную команду, берется кол-во тактов, затраченное на эту команду, и выполняется соответствующий обьем отрисовки ULA.
к примеру: некий PUSH занял 11 тактов, стало быть (в случае прямого хода луча) ULA рисует 22 точки. и так далее.
НО -- ведь если у нас машина с раздельными полями памяти, ULA и Z80 обращаются к данным одновременно, то есть может возникнуть ситуация, когда PUSH положил на стек, находящийся в экранной памяти, старший байт слова, тем временем ULA считала байт по предыдущему адресу, а затем PUSH положил и младший байт, но ULA уже ускакала вперед, и на экран таким образом попал только старший байт слова, которое клал на стек PUSH.
в упомянутом выше алгоритме эмуляции это не будет учтено, на экран попадут оба байта, то есть, строго говоря, такая эмуляция некорректна.

прав ли я?

Titus
19.01.2007, 03:28
Да, ты прав, такая эмуляция не вполне корректна :v2_tong2:

Lethargeek
19.01.2007, 05:52
Давно уже пора полноценно эмулировать не только проц "изнутри" да юлу, но и шину (потактовое состояние). И всякие "девайсоплагины" будет проще прикручивать. Правда, эмуль тормознутый получится... но это ничего, у винтела дури хватает. ;)

NovaStorm
19.01.2007, 08:05
Потактово это конечно хорошо, да и дури хватит(а при хорошей архитектуре эмуля может и лучше будет), но вот инфы по интимным делам железа внутри команд надо будет ещё поискать...

Vladimir Kladov
19.01.2007, 14:19
в каких это - многих? у меня в процессе выполнения команды НА КАЖДОМ ЦИКЛЕ строится видеолуч, например. И я уверен, что так же делается во всех эмуляторах, работающих с ULA (а не с рассыпухой). Иначе это уже не мультиколор, а частичный мультиколор.

Инфы - море. Идите на worldofspectrum, там все лежит, и даже обновляется.

boo_boo
19.01.2007, 15:36
Давно уже пора полноценно эмулировать не только проц "изнутри" да юлу, но и шину (потактовое состояние). И всякие "девайсоплагины" будет проще прикручивать. Правда, эмуль тормознутый получится... но это ничего, у винтела дури хватает. ;) попробую, глянем, сколько там у винтела дури :rolleyes:

Потактово это конечно хорошо, да и дури хватит(а при хорошей архитектуре эмуля может и лучше будет), но вот инфы по интимным делам железа внутри команд надо будет ещё поискать... по каким "делам внутри команд"?

в каких это - многих? у меня в процессе выполнения команды НА КАЖДОМ ЦИКЛЕ строится видеолуч, например. И я уверен, что так же делается во всех эмуляторах, работающих с ULA (а не с рассыпухой). Иначе это уже не мультиколор, а частичный мультиколор.ну у тебя я не смотрел, сорцы-то закрыты :rolleyes:
в zemu, в глюкалке с точностью до опкода ULA работает. в US все кошерно.
а у тебя как это реализовано? жестко на каждом такте дергается ULA, или как в US -- после записи в видеопамять/порт?

NovaStorm
19.01.2007, 16:57
Интим - это например LDIR,условные переходы и вообще что-то более-менее "сложное". Порядок изменения этоми инструкциями регистров разнится на клонах Z80, да на разных по технологии изготовления Z80. Для точной эмуляции, нужно было бы выбирать конкретный проц.

Vladimir Kladov
19.01.2007, 19:03
у меня на асме написан код, который отвечает за декодирование ULA. Asm свой, но смысл понять можно.

это - код макросов для эмуляции задержек и ULA.


////////////////////////////////////////////////////////////////////////////////

// // // ////
// // // // //
// // // // //
// // // // //
// // // ////////
// // // // //
///////// //////////// // //

////////////////////////////////////////////////////////////////////////////////

MC_VIDEO_SCREEN_READY MACRO
// буфер заполнен, вывод экрана и другие действия
MOV EAX, [VideoOutObj]

// вывод экрана
LEAVE_MMX
PUSH ECX
PUSH EAX
XOR B[&ZX].Reg_F, flag_N
XCHG D[MC_Screen_Buffer_Pos], EDI
.IF AntiSlowDown and 0
MOV EDI, 71690+256
.ENDIF
MOV D[&ZX].TactCount, EDI
SUB D[&ZX].TactCount, $100
MOV [&ZX].Reg_PC, BX
CALL VideoOutObj_FrameReady
XCHG [MC_Screen_Buffer_Pos], EDI
.IF Gfx256
MOV D[GfxVideoTarget], VideoOutObj_GfxPixels
MOV D[ScreenAttrTarget], VideoOutObj_ScreenAttrs
.ENDIF
POP EAX
MOV DL, 1 // ManageFlash = TRUE
CALL VideoOutObj_ScreenReady
POP ECX
ENTER_MMX
XOR EDI, EDI
END //MC_VIDEO_SCREEN_READY

//************************************************** ****************************
ULA_unit MACRO Flag=YES
.IF MultiColor

.IF AntiSlowDown
CMP D[&ZX].AntiSlow_HaltDetected, 0
JZ @@ULA_antislow1_&&
CMP D[&ZX].AntiSlow_HaltDetected, 8
JB @@ULA_antislow_end&&
// halt detected, ...
@@ULA_antislow1_&&: // нет halt'ов, только in-ы
CMP EDI, 71680
JAE LONG @@ULA_end_all&&
XCHG EDI, [MC_Screen_Buffer_Pos]
CMP EDI, MC_Screen_Buffer_Size
XCHG EDI, [MC_Screen_Buffer_Pos]
JAE LONG @@ULA_end_all&&
@@ULA_antislow_end&&:
.ENDIF

.IF PrepareVideo
LEA ECX, [EDI-256]
.IF UlaBuffer > 0
ADD ECX, UlaBuffer
.ENDIF
SUB ECX, [ULA_TCounter0]
JLE LONG @@_ULA_end&&
SHR ECX, 2
JZ LONG @@_ULA_end&&

MOV EDX, ECX
SHL EDX, 2
ADD [ULA_TCounter0], EDX

// CL = число байтов для отображения > 0
XCHG EDI, [MC_Screen_Buffer_Pos]
.IF "&Flag" = "YES"
MOV [&ZX].Reg_F, AH // если будет вызван FrameReady,
// то нужно текущее состояние Reg_F для TimeStamper-а
.ENDIF
PUSH EAX //-------------------------------------\

// цикл вывода байтов
@@_ULAout_loop&&:

.IF AntiSlowDown
CMP EDI, MC_Screen_Buffer_Size
JAE LONG @@_ULAfin&&
.ENDIF
// первым сохраняем текущий BorderColor и видеорежим
MOV DL, [&ZX].BorderColor
MOV DH, [&ZX].VideoMode
MOV [EDI*4+2+MC_Screen_Buffer], DX

.IF Gfx256 = 0 OR GfxDraw = 0
.IF GigaScreen
MOV [EDI*4+2+MC_Screen_Buffer_Giga], DL
//int 3
.ENDIF
.ENDIF

// продолжаем цепочку бордюра
MOV DX, [&ZX].BorderColorNext
MOV [&ZX].BorderColor, DX
AND B[&ZX].BorderColorNxt2, $F


.IF Gfx256 AND GfxDraw //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// в режиме мультиколора с включенным Gfx надо
// пересылать Gfx-данные, которых в 8 раз больше
MOVSX EAX, W[EDI*2+MC_Screen_Table_Pixels]
//ADD EAX, EAX
SHL EAX, 3
JS SHORT @@_ULA_8pixels_stored&&
ADD EAX, [GFXVidAddress] // откуда брать 8 байтов
XCHG ESI, EAX
XCHG EDI, [GfxVideoTarget]
MOVSD
MOVSD
XCHG EDI, [GfxVideoTarget]
XCHG ESI, EAX
// теперь нужен еще атрибут, хотя и Gfx-режим
// берем байт атрибутов
MOVZX EAX, W[EDI*2+MC_Screen_Table_Attrs]
DEC EAX
JZ LONG @@_ULA_8pixels_stored&&

ADD EAX, [&ZX].VideoBaseAddr
MOVZX EDX, B[EAX]
MOV DH, [&ZX].Flash
MOV AL, B[EDX+GfxAttrConvertTable]

XCHG EDI, [ScreenAttrTarget]
STOSB
XCHG EDI, [ScreenAttrTarget]

.ELSE Gfx256 = 0 OR GfxDraw = 0 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// берем байт атрибутов
MOVZX EAX, W[EDI*2+MC_Screen_Table_Attrs]
DEC EAX
JZ LONG @@_ULA_8pixels_stored&&

// проверяем эффект "снег"
CMP B[&ZX].SnowEffect, 0
JZ SHORT @@_ULAload_data&&

MOV AL, B[&ZX].TactRCount
AND AL, $7F
OR AL, [&ZX].Reg_R_7

ADD EAX, [&ZX].VideoBaseAddr
MOVZX EDX, B[EAX]
MOV DH, [&ZX].Flash
MOV DL, B[EDX+AttrConvertTable]

// берем очередной байт 8 пикселов
MOVZX EAX, W[EDI*2+MC_Screen_Table_Pixels]

MOV AL, B[&ZX].TactRCount
AND AL, $7F
OR AL, [&ZX].Reg_R_7

ADD EAX, [VideoBaseAddr]
MOV DH, B[EAX]

MOV W[EDI*4+MC_Screen_Buffer], DX

JMP SHORT @@_ULA_8pixels_stored&&

@@_ULAload_data&&:

ADD EAX, [&ZX].VideoBaseAddr
MOVZX EDX, B[EAX]
MOV DH, [&ZX].Flash
MOV DL, B[EDX+AttrConvertTable]

// берем очередной байт 8 пикселов
MOVZX EAX, W[EDI*2+MC_Screen_Table_Pixels]
ADD EAX, [&ZX].VideoBaseAddr
MOV DH, B[EAX]

MOV W[EDI*4+MC_Screen_Buffer], DX

.IF GigaScreen // для GigaScreen, то же самое для альтернативного экрана:
MOVZX EAX, W[EDI*2+MC_Screen_Table_Attrs]
DEC EAX
JZ SHORT @@_ULA_8pixels_stored&&

ADD EAX, [&ZX].AltVideoBaseAddr
MOVZX EDX, B[EAX]
MOV DH, [&ZX].Flash
MOV DL, B[EDX+AttrConvertTable]
// берем очередной байт 8 пикселов
MOVZX EAX, W[EDI*2+MC_Screen_Table_Pixels]
ADD EAX, [&ZX].AltVideoBaseAddr
MOV DH, B[EAX]

MOV W[EDI*4+MC_Screen_Buffer_Giga], DX
.ENDIF //GigaScreen

.ENDIF //not Gfx256 ~~~~~~~~~~~~~~~~~~~~~~~~~

@@_ULA_8pixels_stored&&:
INC EDI
.IF RZX_play = 0
CMP EDI, BytesInFrame
JB LONG @@_ULAnext&&

.IF AntiSlowDown
// CMP BX, $4000
// JAE @@ULA_AntiSlow_ScreenReady&&
// MC_VIDEO_SCREEN_READY
//@@ULA_AntiSlow_ScreenReady&&:
.ELSE
MC_VIDEO_SCREEN_READY
.ENDIF
@@ULA_skipscreen&&:

CMP B[&ZX].StopOnEndOfFrame, 0
JZ SHORT @@_ULAnext&&
MOV D[&ZX].JumpPt, StopExec
.ELSE
CMP EDI, BytesInFrame
JB SHORT @@_ULAnext&&

DEC EDI
.ENDIF RZX_play = 0

@@_ULAnext&&:
DEC ECX
JG @@_ULAout_loop&&
//LOOP @@_ULAout_loop&&

@@_ULAfin&&:
POP EAX

XCHG EDI, [MC_Screen_Buffer_Pos] // EDI = TactCounter+256

@@_ULA_end&&:
.ELSE //not PrepareVideo
LEA ECX, [EDI-256]
.IF UlaBuffer > 0
ADD ECX, UlaBuffer
.ENDIF

SUB ECX, [ULA_TCounter0]
JLE LONG @@_ULAnovideo_end&&
SHR ECX, 2
JZ LONG @@_ULAnovideo_end&&

MOV EDX, ECX
SHL EDX, 2
ADD [ULA_TCounter0], EDX

// CL = число байтов для "отображения" > 0
XCHG EDI, [MC_Screen_Buffer_Pos]
.IF "&Flag" = "YES"
MOV [&ZX].Reg_F, AH // если будет вызван FrameReady,
// то нужно текущее состояние Reg_F для TimeStamper-а
.ENDIF
PUSH EAX //-------------------------------------\

// цикл вывода байтов
@@_ULAnovideo_out_loop&&:

INC EDI
.IF RZX_play = 0
CMP EDI, BytesInFrame
JB SHORT @@_ULAnovideo_next&&

.IF AntiSlowDown
// CMP EBX, $4000
// JAE @@ULA_AntiSlow_ScreenReady1_&&
// MC_VIDEO_SCREEN_READY
//@@ULA_AntiSlow_ScreenReady1_&&:
.ELSE
MC_VIDEO_SCREEN_READY
.ENDIF

CMP B[&ZX].StopOnEndOfFrame, 0
JZ SHORT @@_ULAnovideo_next&&
MOV D[&ZX].JumpPt, StopExec
.ELSE
CMP EDI, BytesInFrame
JB SHORT @@_ULAnovideo_next&&

DEC EDI
.ENDIF RZX_play = 0

@@_ULAnovideo_next&&:
DEC ECX
JG @@_ULAnovideo_out_loop&&
//LOOP @@_ULAnovideo_out_loop&&

POP EAX

XCHG EDI, [MC_Screen_Buffer_Pos] // EDI = TactCounter+256

@@_ULAnovideo_end&&:
.ENDIF //PrepareVideo
@@ULA_end_all&&:
.ENDIF //MultiColor
END //ULA_unit

продолжение следует...

Vladimir Kladov
19.01.2007, 19:04
макросы, продолжение:



//************************************************** ****************************
Delay MACRO Time, Mem, Temp=D
.IF MultiColor
.IF AntiSlowDown
CMP EDI, 71690
JB @@Delay1_&&
.IF &Time > 1
ADD EDI, &Time
.ELSEIF &Time = 1
INC EDI
.ENDIF
JMP SHORT @@DelayEnd&&
@@Delay1_&&:
.ENDIF
.IF NoDelay = 0
MOVZX E&Temp.X, &Mem.H
MOV &Temp.H, [&ZX].CurRAMBank
MOVZX E&Temp.X, B[E&Temp.X+MC_Contended_Mem_Table]
ADD EDI, D[EDI*8+E&Temp.X+MC_Contended_Delay_Table]
.IF &Time > 2
ADD EDI, &Time-1
.ELSEIF &Time = 2
INC EDI
.ENDIF
.ELSE NoDelay
.IF &Time > 1
ADD EDI, &Time
.ELSEIF &Time = 1
INC EDI
.ENDIF
.ENDIF
.IF AntiSlowDown
@@DelayEnd&&:
.ENDIF
.ENDIF
END //MACRO Delay

//************************************************** ****************************
DelayMore MACRO Time=1, Temp=D, Count=1
.IF MultiColor
.IF AntiSlowDown
CMP EDI, 71690
JB @@DelayMore1_&&
.IF &Time * &Count > 1
ADD EDI, &Time * &Count
.ELSEIF &Time * &Count = 1
INC EDI
.ENDIF
JMP SHORT @@DelayMoreEnd&&
@@DelayMore1_&&:
.ENDIF
.IF NoDelay = 0
.REPEAT &Count
ADD EDI, D[EDI*8+E&Temp.X+MC_Contended_Delay_Table]
.IF &Time > 2
ADD EDI, &Time-1
.ELSEIF &Time = 2
INC EDI
.ENDIF
.ENDREP
.ELSE NoDelay
.IF &Time * &Count > 1
ADD EDI, &Time * &Count
.ELSEIF &Time * &Count = 1
INC EDI
.ENDIF
.ENDIF
.IF AntiSlowDown
@@DelayMoreEnd&&:
.ENDIF
.ENDIF
END //MACRO DelayMore

//************************************************** ****************************
outDelay MACRO Port, Temp=D, io=
.IF MultiColor
.IF NoDelay = 0
.IF "&io" = ""
//--------------
MOVZX EDX, &Port.H
MOV &Temp.H, [&ZX].CurRAMBank
MOVZX E&Temp.X, B[E&Temp.X+MC_Contended_Mem_Table]
TEST &Port.L, 1
JZ SHORT @@_outFE&&
// N:4 or C:1 C:1 C:1 C:1
XOR &Temp.L, 4
JNZ SHORT @@_outN4&&

.IF AntiSlowDown
CMP EDI, 71690
JB @@outDelay1_&&
ADD EDI, 4
JMP SHORT @@_outN4&&
@@outDelay1_&&:
.ENDIF
ADD EDI, D[EDI*8+4+MC_Contended_Delay_Table]
ADD EDI, D[EDI*8+4+MC_Contended_Delay_Table]
ADD EDI, D[EDI*8+4+MC_Contended_Delay_Table]
ADD EDI, D[EDI*8+4+MC_Contended_Delay_Table]

@@_outN4&&:
ADD EDI, E&Temp.X
JMP SHORT @@_end_out_contention&&

@@_outFE&&:
xor &Temp.L, 4
JNZ SHORT @@_outN1C3_&&
.IF AntiSlowDown
CMP EDI, 71690
JAE @@_outN1C3_&&
.ENDIF
ADD EDI, D[EDI*8+4+MC_Contended_Delay_Table]
DEC EDI
@@_outN1C3_&&:
INC EDI
.IF AntiSlowDown
CMP EDI, 71690
JB @@outDelay3_&&
ADD EDI, 3
JMP SHORT @@_end_out_contention&&
@@outDelay3_&&:
.ENDIF
ADD EDI, D[EDI*8+4+MC_Contended_Delay_Table]
ADD EDI, 3-1
@@_end_out_contention&&:
//--------------
.ELSE
//--------------
.IF AntiSlowDown
CMP EDI, 71690
JAE @@outDelay5&&
.ENDIF
MOVZX E&Temp.X, &Port.H
MOV &Temp.H, [&ZX].CurRAMBank
MOVZX E&Temp.X, B[E&Temp.X+MC_Contended_Mem_Table]
TEST &Port.L, 1
JNZ SHORT @@outDelay4&&
MOV &Temp.L, 4
@@outDelay4&&:
ADD EDI, D[EDI*8+E&Temp.X+MC_Contended_Delay_Table]
ADD EDI, &io-1
@@outDelay5&&:
//--------------
.ENDIF
.ELSE NoDelay
.IF "&io" = ""
ADD EDI, 4
.ELSEIF &io > 1
ADD EDI, &io
.ELSEIF &io = 1
INC EDI
.ENDIF
.ENDIF
.ENDIF //MultiColor
END //MACRO outDelay

//************************************************** ****************************
inDelay MACRO Port, Temp=D
.IF MultiColor <> 0
.IF NoDelay = 0
MOVZX E&Temp.X, &Port.H
MOV &Temp.H, [&ZX].CurRAMBank
MOVZX E&Temp.X, B[E&Temp.X+MC_Contended_Mem_Table]
TEST &Port.L, 1
JZ SHORT @@_inFE&&
// bit 0 of port addr set - N:4 or C:1 C:1 C:1 C:1
XOR &Temp.L, 4
JNZ SHORT @@_inN4&&

.IF AntiSlowDown
CMP EDI, 71690
JB @@inDelay1_&&
ADD EDI, 4
JMP SHORT @@_inN4&&
@@inDelay1_&&:
.ENDIF
ADD EDI, D[EDI*8+4+MC_Contended_Delay_Table]
ADD EDI, D[EDI*8+4+MC_Contended_Delay_Table]
ADD EDI, D[EDI*8+4+MC_Contended_Delay_Table]
ADD EDI, D[EDI*8+4+MC_Contended_Delay_Table]
@@_inN4&&:
ADD EDI, E&Temp.X
JMP SHORT @@_end_in_contention&&

@@_inFE&&:
.IF AntiSlowDown
CMP EDI, 71690
JAE @@_end_in_contention&&
.ENDIF
XOR &Temp.L, 4
JnZ SHORT @@_inN1C3_&&
ADD EDI, D[EDI*8+4+MC_Contended_Delay_Table]
DEC EDI
@@_inN1C3_&&:
INC EDI
ADD EDI, D[EDI*8+4+MC_Contended_Delay_Table]
ADD EDI, 3-1
@@_end_in_contention&&:
.ELSE NoDelay
ADD EDI, 4
.ENDIF
.ENDIF //MultiColor
//--------------
END //MACRO inDelay

//************************************************** ****************************

ioDelay MACRO Port, Temp
.IF MultiColor
.IF NoDelay = 0
.IF AntiSlowDown
CMP EDI, 71690
JAE @@ioDelayEnd&&
.ENDIF
MOVZX E&Temp.X, &Port.H
MOV &Temp.H, [&ZX].CurRAMBank
MOVZX E&Temp.X, B[E&Temp.X+MC_Contended_Mem_Table]
TEST &Port.L, 1
JNZ SHORT @@ioDelay1_&&
MOV &Temp.L, 4
@@ioDelay1_&&:
ADD EDI, D[EDI*8+ECX+MC_Contended_Delay_Table]
.IF AntiSlowDown
@@ioDelayEnd&&:
.ENDIF
.ELSE NoDelay
//ADD EDI, 4
.ENDIF

.ENDIF
END //MACRO ioDelay



и еще чуть-чуть...

Vladimir Kladov
19.01.2007, 19:05
А вот это - реализация команд LDI/LDIR/LDD/LDDR. Разберитесь, если есть желание.


@@_ld&direction.r: // LDIR, LDDR
.IF (FastLDIR <> 0) and ("&LDIRHL" <> "")
CMP B[&ZX].DebuggerVisible, 0
JNZ @@_ld&direction.r_usual

MOVZX ECX, W[&ZX].Regs.Reg_BC
DEC ECX
JZ @@_ld&direction.r_usual
MOVZX EDX, W[&ZX].Regs.Reg_DE
MOV ECX, EBX
DEC CX
CMP CX, DX
JZ @@_ld&direction.r_usual
.if MemPtrNew
MOV [&ZX].reg_Hidden, CH
.endif
DEC CX
CMP CX, DX
JZ @@_ld&direction.r_usual
MOV EBX, ECX
PUSH EAX
.IF "&LDIRHL" = "BX"
PUSH EBX
.ENDIF
MOVZX &ELDIRHL, W[&ZX].Regs.Reg_HL
.IF GeneralSnd
ADD D[&ZX].TStatesToExecute, 16
.ENDIF
.IF MultiColor
MOV [&ZX].TempFlip, EDI
ADD D[&ZX].TempFlip, 256
.ENDIF
JMP SHORT @@_ld&direction.r_fast_next

@@_ld&direction.r_fast_loop:
.IF RZX_play
ADD D[&ZX].NumFetches, 2
.ELSEIF GeneralSnd
INC D[&ZX].NumFetches
.ENDIF

.IF MultiColor
ADD B[&ZX].TactRCount, 2
.IF NoDelay
ADD EDI, 8
.ELSEIF "&LDIRHL" = "BX"
POP EAX
PUSH EAX
Delay Time=4, Mem=A, Temp=C
INC AX
Delay Time=4, Mem=A, Temp=C
.ELSE
Delay Time=4, Mem=B, Temp=C
INC BX
Delay Time=4, Mem=B, Temp=C
DEC BX
.ENDIF
.ELSEIF MultiColor = 0
ADD D[&ZX].TactRCount, $100002
AND W[&ZX].TactRCount, $7F
.ENDIF

@@_ld&direction.r_fast_next:
.IF "&LDIRHL" = "BX"
Delay Time=3, Mem=B, Temp=C
GetMem1 Dest=AL, Addr=B, Temp=C, Gfx=mm0
.ELSE
MOV EAX, &ELDIRHL
Delay Time=3, Mem=A, Temp=C
GetMem1 Dest=AL, Addr=A, Temp=C, Gfx=mm0
.ENDIF
.IF Plus3 or NoDelay
Delay Time=5, Mem=D, Temp=C // задержка DE wr:5
.ELSE
Delay Time=3, Mem=D, Temp=C // задержка DE wr:3
DelayMore Temp=C, Count=2
.ENDIF
PutMem Addr=D, Reg=AL, Temp=C, Gfx=mm0
DEC W[&ZX].Regs.Reg_BC
JZ @@_ld&direction.r_fast_end_incRegs

.IF "&direction" = "i"
INC DX
INC &LDIRHL
.IF "&LDIRHL" = "BX"
CMP DX, [ESP]
.ELSE
AND &ELDIRHL, $FFFF
CMP DX, BX
.ENDIF
JZ SHORT @@_ld&direction.r_fast_fin
.IF MultiColor
CMP EDI, 60000
JGE SHORT @@_ld&direction.r_fast_fin
.ENDIF
.ELSE
DEC DX
DEC &LDIRHL
DEC DX
.IF "&LDIRHL" = "BX"
CMP DX, [ESP]
.ELSE
AND &ELDIRHL, $FFFF
CMP DX, BX
.ENDIF
JZ SHORT @@_ld&direction.r_fast_fin_INCDX
.IF MultiColor
CMP EDI, 60000
JGE SHORT @@_ld&direction.r_fast_fin_INCDX
.ENDIF
INC DX
.ENDIF

.IF MultiColor = 0
ADD W[&ZX].TactRCount + 2, 5
JS SHORT @@_ld&direction.r_fast_fin
.ELSE
.IF Plus3 or NoDelay
Delay Time=5, Mem=D, Temp=C // дополнительно 5 задержек DE:1
.ELSE
Delay Time=1, Mem=D, Temp=C // дополнительно 5 задержек DE:1
DelayMore Temp=C, Count=4
.ENDIF
.ENDIF

.IF GeneralSnd
SUB [&ZX].TStatesToExecute, 21
CMP [&ZX].TStatesToExecute, 21
JG @@_ld&direction.r_fast_loop
MOV ECX, [&ZX].NumFetches
CMP ECX, [&ZX].MaxFetches
JGE @@_ld&direction.r_fast_fin
.ELSEIF RZX_play
MOV ECX, [&ZX].NumFetches
CMP ECX, [&ZX].MaxFetches
JGE @@_ld&direction.r_fast_fin
.IF MultiColor
CMP B[EDI+MC_IntSignal_Table], 0
JNZ SHORT @@_ld&direction.r_fast_fin
.ENDIF
.ELSE
.IF MultiColor
CMP B[EDI+MC_IntSignal_Table], 0
JNZ SHORT @@_ld&direction.r_fast_fin
CMP EDI, [&ZX].TempFlip
JGE SHORT @@_ld&direction.r_fast_fin
.ELSE
.ENDIF
.ENDIF
JMP LONG @@_ld&direction.r_fast_loop

@@_ld&direction.r_fast_fin_INCDX:
INC DX
@@_ld&direction.r_fast_fin: // завершаем цикл быстрого LDIR по разным причинам,
// кроме исчерпания Reg_BC
MOV ECX, &ELDIRHL
MOV [&ZX].Regs.Reg_HL, CX
MOV [&ZX].Regs.Reg_DE, DX
.IF "&LDIRHL" = "BX"
POP EBX
.ENDIF
POP ECX
MOV AH, CH

ADD AL, [&ZX].Reg_A // !!! формируем флажки X и Y !!!
.IF LDIR_BY_TABLE
AND EAX, $FFFF
MOV AX, W[EAX*2+Table_LDIR1]
.ELSE
// !!! формируем флажки X и Y !!!
MOV CL, AL
AND CL, 2
SAL CL, 4
AND AL, $F
OR AL, CL //-------------------------------
AND AH, not flag_H
.ENDIF
OR AH, flag_N or flag_P
NextInstr

@@_ld&direction.r_fast_end_incRegs: // завершение быстрого LDIR по исчерпании Reg_BC
.IF "&direction" = "i"
INC DX
INC &LDIRHL
.ELSE
DEC DX
DEC &LDIRHL
.ENDIF

@@_ld&direction.r_fast_end: // завершение быстрого LDIR по исчерпании Reg_BC
.IF GeneralSnd
ADD D[&ZX].TStatesToExecute, 5
.ENDIF
MOV ECX, &ELDIRHL
MOV [&ZX].Regs.Reg_HL, CX
MOV [&ZX].Regs.Reg_DE, DX
.IF "&LDIRHL" = "BX"
POP EBX
.ENDIF
POP ECX
MOV AH, CH

ADD AL, [&ZX].Reg_A // !!! формируем флажки X и Y !!!
.IF LDIR_BY_TABLE
AND EAX, $FFFF
MOV AX, W[EAX*2+Table_LDIR1]
.ELSE
// !!! формируем флажки X и Y !!!
MOV CL, AL
AND CL, 2
SAL CL, 4
AND AL, $F
OR AL, CL //-------------------------------
AND AH, not (flag_P or flag_H)
.ENDIF
OR AH, flag_N
INC BX
INC BX
NextInstr

.ENDIF

@@_ld&direction.r_usual:
INC_TactRCount Value=5, ReturnTStates=16, ReturnPC=2, ReturnR=2, ReturnFetches=1
MOVZX ECX, W[&ZX].Regs.reg_HL
Delay Time=3, Mem=C // задержка HL:3
GetMem1 Dest=AL, Addr=C, Gfx=mm0
MOVZX ECX, W[&ZX].Regs.reg_DE
.IF Plus3 or NoDelay
Delay Time=5, Mem=C // задержка DE wr:5
.ELSE
Delay Time=3, Mem=C // задержка DE wr:3
DelayMore Count=2
.ENDIF
PutMem Addr=C, Reg=AL, Gfx=mm0
ADD AL, [&ZX].Reg_A // !!! формируем флажки X и Y !!!
.IF LDIR_BY_TABLE
AND EAX, $FFFF
MOV AX, W[EAX*2+Table_LDIR1]
.ELSE
// !!! формируем флажки X и Y !!!
MOV CL, AL
AND CL, 2
SAL CL, 4
AND AL, $F
OR AL, CL //-------------------------------
AND AH, not (flag_P or flag_H)
OR AH, flag_N
.ENDIF
MOVZX EDX, W[&ZX].Regs.reg_DE
.IF "&direction" = "i"
INC W[&ZX].Regs.reg_HL
INC W[&ZX].Regs.reg_DE
.ELSE
DEC W[&ZX].Regs.reg_HL
DEC W[&ZX].Regs.reg_DE
.ENDIF
DEC W[&ZX].Regs.reg_BC
JZ SHORT @@ld&direction.r_exit
.IF Plus3 or NoDelay
Delay Time=5, Mem=D // дополнительно 5 задержек DE:1
.ELSE
Delay Time=1, Mem=D // дополнительно 5 задержек DE:1
DelayMore Count=4
.ENDIF
OR AH, flag_P
DEC BX
.if MemPtrNew
MOV [&ZX].reg_Hidden, BH
.endif
DEC BX
@@ld&direction.r_exit:
NextInstr
.ENDFOR //direction


я жебил, я не шерхан, хавал жёваны штаны...

Titus
19.01.2007, 22:10
Интим - это например LDIR,условные переходы и вообще что-то более-менее "сложное". Порядок изменения этоми инструкциями регистров разнится на клонах Z80, да на разных по технологии изготовления Z80.

Бездоказательно, весьма бездоказательно... :v2_wink2:

Error404
19.01.2007, 22:45
Цитата:
Сообщение от NovaStorm
Интим - это например LDIR,условные переходы и вообще что-то более-менее "сложное". Порядок изменения этоми инструкциями регистров разнится на клонах Z80, да на разных по технологии изготовления Z80.


Бездоказательно, весьма бездоказательно...

Я тут гонял zexall на нескольких эмуляторах z80 - результат удручающий. А он еще не самое полное тестирование проводит...

boo_boo
20.01.2007, 01:25
Интим - это например LDIR,условные переходы и вообще что-то более-менее "сложное". Порядок изменения этоми инструкциями регистров разнится на клонах Z80, да на разных по технологии изготовления Z80. Для точной эмуляции, нужно было бы выбирать конкретный проц. это только пресловутого MEMPTR касается, а с ним уже ясно все (http://zx.pk.ru/showpost.php?p=44058&postcount=150). насчет разных технологий и странных клонов ходят слухи, но конкретных экземпляров пока не выявлено. если у тебя есть -- давай сюда :v2_smile:

Я тут гонял zexall на нескольких эмуляторах z80 - результат удручающий. А он еще не самое полное тестирование проводит... конечно. но, к счастью с хардовым Z80 все куда приятней :) есть небольшая разница (см ссылку выше) но в целом один хрен :) так что это скорей показатель недоделанности некоторых эмуляторов