ULA in EmuzWin
ZXNet echo conference «zxnet.pc»
From Vladimir Kladov → To All 19 January 2007
Hello, boo_boo
I have written code on ASMA that is responsible for decoding ULA. Asm yours, but
the meaning can be understood.
this is macro code for emulating delays and ULAs.
┌─- CODE ───
////////////////////////////////////////////////////////////////////////////
/
// // // ////
// // // // //
// // // // //
// // // // //
// // // ////////
// // // // //
///////// //////////// // //
////////////////////////////////////////////////////////////////////////////
/
MC_VIDEO_SCREEN_READY MACRO
// buffer is full, screen output and other actions
MOV EAX, [VideoOutObj]
// screen output
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 EAXMOV 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 AntiSlowDownCMP EDI, MC_Screen_Buffer_Size
JAE LONG @@_ULAfin&&
.ENDIF
// first save the current BorderColor and video mode
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
// continue the border chain
MOV DX, [&ZX].BorderColorNext
MOV [&ZX].BorderColor, DX
AND B[&ZX].BorderColorNxt2, $F
.IF Gfx256 AND GfxDraw //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// in multicolor mode with Gfx enabled you need
// send Gfx data, which is 8 times more
MOVSX EAX, W[EDI*2+MC_Screen_Table_Pixels]
//ADD EAX, EAX
SHL EAX, 3
JS SHORT @@_ULA_8pixels_stored&&
ADD EAX, [GFXVidAddress] // where to get 8 bytes from
XCHG ESI, EAX
XCHG EDI, [GfxVideoTarget]
MOVSD
MOVSD
XCHG EDI, [GfxVideoTarget]
XCHG ESI, EAX
// now we need another attribute, although Gfx mode
// take the attribute byte
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]
STOSBXCHG EDI, [ScreenAttrTarget]
.ELSE Gfx256 = 0 OR GfxDraw = 0 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// берем барибутов
MOVZX EAX, W[EDI*2+MC_Screen_Table_Attrs]
DEC EAX
JZ LONG @@_ULA_8pixels_stored&&
// Consonant "snake"
CMP B[&ZX].SnowEffect,0
JZ SHORT @@_UNAload_data&&
MOV AL, B[&ZX].TactRCount
AND ALL, $7F
OR AL, [&ZX].Reg_R_7
ADD EAX, [&ZX].VideoBaseAddr
MOVZX EDX, B[EAX]
MOV DH, [&ZX].Flash
MOV DL, B[EDX+AttrConvertTable]
// slightly less than 8 minutes
MOVZX EAX, W[EDI*2+MC_Screen_Table_Pixels]
MOV AL, B[&ZX].TactRCount
AND ALL, $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_storage&&
@@_ULAload_data&&:
ADD EAX, [&ZX].VideoBaseAddr
MOVZX EDX, B[EAX]
MOV DH, [&ZX].Flash
MOV DL, B[EDX+AttrConvertTable]
// slightly less than 8 minutes
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 // Meaning GigaScreen, please refer to the following screen:
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, 2JZ LONG @@_ULAnovideo_end&&
MOV EDX, ECX
SHL EDX, 2
ADD [ULA_TCounter0], EDX
// CL = number of bytes to "display" > 0
XCHG EDI, [MC_Screen_Buffer_Pos]
.IF "&Flag" = "YES"
MOV [&ZX].Reg_F, AH // if FrameReady is called,
// then we need the current state of Reg_F for
TimeStamper
.ENDIF
PUSH EAX //---------------------------------------\n
// byte output loop
@@_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 ───
to be continued...