ZXNet эхоконференция «zxnet.pc»
тема: ULA в EmuzWin
от: Владимир Кладов
кому: All
дата: 19 Jan 2007
Hello, boo_boo
у меня на асме написан код, который отвечает за декодирование ULA. Asm свой, но
смысл понять можно.
это - код макросов для эмуляции задержек и ULA.
┌─- CODE ───
///////////////////////////////////////////////////////////////////////////////
/
// // // ////
// // // // //
// // // // //
// // // // //
// // // ////////
// // // // //
///////// //////////// // //
///////////////////////////////////////////////////////////////////////////////
/
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 //-------------------------------------\n
// цикл вывода байтов
@@_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 //-------------------------------------\n
// цикл вывода байтов
@@_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
└── CODE ───
продолжение следует...
|