📄 tvcode.asm
字号:
; we need to reset the position every time to set a known reference.
; This is done by entering mode 0 and back (if in modes 1-6), or
; entering mode 1 and back (if in mode 0).
or dx, dx ; check if mode 0
mov dx, 0 ; assume reset with mode 0
jnz SetTVMode_ResetPos ; skip if wasn't mode 0
inc dx ; reset with mode 1, not mode 0
SetTVMode_ResetPos:
call LoadDisplayMode ; Load mode 0 or mode 1
pop dx ; restore original mode
LoadDisplayMode:
mov cl, CH7002_DISPLAY_MODE
call OEMSetTVRegister
clc
elseif CH7003
; 7003
push dx ; save dx
; 1st load common values
lea si, CH7003_tab_common ; point to common table
call OEMSetTVRegMulti ; set common values
; mode specific stuff
pop dx ; restore input
push dx ; save again
lea di, ch7003_ntsc_modes ; assume ntsc
.if (dl & 80h) ; pal?
lea di,ch7003_pal_modes ; yes
.endif
mov bx, dx ; get to bx
and bx, 03h ; isolate
shl bx, 1 ; *2 for word access
mov si, cs:[di+bx] ; get mode table
call OEMSetTVRegMulti ; set values
pop dx ; retsore input
; set timings
lea di, NTSC_Timings
.IF (dl & 80h)
lea di, PAL_Timings
.ENDIF
mov bl, dl
and bx, 0003h
; Generate offset into timing table
mov al, SIZE VIDEO_TIMINGS
mul bl
add di, ax
push cs
pop es
mov ax, 4F14h ; Set timings
mov bx, 0103h
int 10h
clc
ELSE
stc
ENDIF
ret
VIDEO_TIMINGS struc
fpResolution DB ?
fpControl DB ?
fpDither DB ?
fpClockFreq DB ?
fpHtotal DB ?
fpVtotal DB ?
fpHsyncStart DB ?
fpHsyncEnd DB ?
fpVsyncStart DB ?
fpVsyncEnd DB ?
crtHsyncStart DB ?
crtHsyncEnd DB ?
crtVsyncStart DB ?
crtVsyncEnd DB ?
VIDEO_TIMINGS ENDS
tblFLATPANEL label BYTE
VIDEO_TIMINGS <00h, 031h, 000h, 50, 014h, 02Dh, 002h, 00Eh, 009h, 00Bh, 002h, 00Eh, 00Ah, 00Ch > ; 640x480
VIDEO_TIMINGS <01h, 031h, 000h, 80, 020h, 01Ch, 005h, 015h, 000h, 004h, 005h, 015h, 00Bh, 00Fh > ; 800x600
;**************************************************************************
;* NTSC TIMINGS
;**************************************************************************
IF ch7002
DB 6 ; NTSC - 800 x 600 under
DB 6 ; NTSC - 800 x 600 over
DB 3 ; NTSC - 640 x 480 underscan
DB 2 ; NTSC - 640 x 480 overscan
ENDIF
NTSC_Timings:
IF CH7003
; 640x480 NTSC Overscan
VIDEO_TIMINGS <20h, 031h, 000h, 51, 014h, 02Dh, 005h, 00Fh, 007h, 00Ah, 005h, 00Fh, 007h, 00Ah >
; 640x480 NTSC Underscan
VIDEO_TIMINGS <20h, 031h, 000h, 56, 012h, 078h, 005h, 00Fh, 03Ch, 03Fh, 005h, 00Fh, 03Ch, 03Fh >
; 800x600 NTSC Overscan
VIDEO_TIMINGS <21h, 031h, 000h, 87, 01Eh, 064h, 005h, 015h, 032h, 035h, 005h, 015h, 032h, 035h >
; 800x600 NTSC Underscan
VIDEO_TIMINGS <21h, 031h, 000h, 87, 01Eh, 064h, 005h, 015h, 032h, 035h, 005h, 015h, 032h, 035h >
ENDIF
IF CH7002
; 640x480 NTSC Overscan
VIDEO_TIMINGS <00h, 031h, 000h, 51, 014h, 02Dh, 005h, 00Fh, 007h, 00Ah, 005h, 00Fh, 007h, 00Ah >
; 640x480 NTSC Underscan
VIDEO_TIMINGS <00h, 031h, 000h, 56, 012h, 078h, 005h, 00Fh, 03Ch, 03Fh, 005h, 00Fh, 03Ch, 03Fh >
; 800x600 NTSC Underscan
VIDEO_TIMINGS <01h, 031h, 000h, 87, 01Eh, 064h, 005h, 015h, 032h, 035h, 005h, 015h, 032h, 035h >
ENDIF
IF AITECH
; 640x480 NTSC Overscan - 2 Hsyncs per Vsync for NTSC
VIDEO_TIMINGS <00h, 031h, 000h, 50, 014h, 02Dh, 002h, 00Dh, 009h, 00Bh, 002h, 00Bh, 003h, 005h >
; 640x480 NTSC Underscan - Same as overscan - 2 Hsyncs per Vsync for NTSC
VIDEO_TIMINGS <00h, 031h, 000h, 50, 014h, 02Dh, 002h, 00Dh, 009h, 00Bh, 002h, 00Bh, 003h, 005h >
; 800x600 NTSC Underscan ### NOT USED- MEANING NOT VALID ###
VIDEO_TIMINGS <01h, 031h, 000h, 80, 020h, 01Ch, 005h, 015h, 000h, 004h, 005h, 015h, 00Bh, 00Fh >
ENDIF
;**************************************************************************
;* PAL TIMINGS
;**************************************************************************
IF ch7002
DB 0 ; PAL - 800 x 600 under
DB 0 ; PAL - 800 x 600 over
DB 1 ; PAL - 640 x 480 underscan
DB 4 ; PAL - 640 x 480 overscan
ENDIF
PAL_Timings:
IF CH7003
; 640x480 PAL Overscan
VIDEO_TIMINGS <20h, 031h, 000h, 50, 014h, 091h, 005h, 00Fh, 048h, 04Bh, 005h, 00Fh, 048h, 04Bh >
; 640x480 PAL Underscan
VIDEO_TIMINGS <20h, 031h, 000h, 50, 014h, 091h, 005h, 00Fh, 048h, 04Bh, 005h, 00Fh, 048h, 04Bh >
; 800x600 PAL Overscan
VIDEO_TIMINGS <21h, 031h, 000h, 71, 012h, 096h, 001h, 00Ah, 04Bh, 04Eh, 001h, 00Ah, 04Bh, 04Eh >
; 800x600 PAL Underscan
VIDEO_TIMINGS <21h, 031h, 000h, 71, 012h, 096h, 001h, 00Ah, 04Bh, 04Eh, 001h, 00Ah, 04Bh, 04Eh >
ENDIF
IF CH7002
; 640x480 PAL Overscan
VIDEO_TIMINGS <00h, 031h, 000h, 50, 014h, 091h, 005h, 00Fh, 048h, 04Bh, 005h, 00Fh, 048h, 04Bh >
; 640x480 PAL Underscan
VIDEO_TIMINGS <00h, 031h, 000h, 50, 014h, 091h, 005h, 00Fh, 048h, 04Bh, 005h, 00Fh, 048h, 04Bh >
; 800x600 PAL Underscan
VIDEO_TIMINGS <01h, 031h, 000h, 71, 012h, 096h, 001h, 00Ah, 04Bh, 04Eh, 001h, 00Ah, 04Bh, 04Eh >
ENDIF
IF AITECH
; 640x480 PAL Overscan- 7 Hsyncs per Vsync for PAL
VIDEO_TIMINGS <00h, 031h, 000h, 50, 015h, 091h, 002h, 00Eh, 038h, 03Fh, 004h, 00Ch, 034h, 03Ah >
; 640x480 PAL Underscan - Same as overscan - 7 Hsyncs per Vsync for PAL
VIDEO_TIMINGS <00h, 031h, 000h, 50, 015h, 091h, 002h, 00Eh, 038h, 03Fh, 004h, 00Ch, 034h, 03Ah >
; 800x600 PAL Underscan ### NOT USED - MEANING NOT VALID ###
VIDEO_TIMINGS <01h, 031h, 000h, 80, 020h, 01Ch, 005h, 015h, 000h, 004h, 005h, 015h, 00Bh, 00Fh >
ENDIF
Set_TV_Mode ENDP
;**************************************************************************
;*
;* Adjust_TV_Position
;*
;* This routine adjusts the registers on the TV support chip. It is
;* called when an application is centering the image for a certain
;* mode.
;*
;* Entry:
;* CH = 02
;* DL = new signed absolute horizontal position (positive left)
;* DH = new signed absolute vertical position (positive down)
;*
;* Exit:
;* Destroys:
;*
;**************************************************************************
Adjust_TV_Position PROC NEAR
IF CH7002
; GET CURRENT POSITION VALUES
; For CH7002, we need relative values.
push dx ; save new position
; Get current TV position
mov ax, 4F14h ; Geode video BIOS extensions
mov bx, 0206h ; Query TV position
int 10h ; current position returned in CX
pop dx ; restore new position
push dx
sub dl, cl ; relative X
sub dh, ch ; relative Y
call AdjustTVRelativePosition
pop dx
clc
ENDIF ; CH7002
IF CH7003
push cx ; save cx
; push dx ; save input
; ; get current mode
; mov ax, 04f14h ; Geode video BIOS extensions
; mov bx, 0006h ; get mode
; int 10h ; call videobios
; pop dx ; restore input
; push cx ; save mode
; HPR is 9 bits - each bit moves 4 pixels
; just use the value for now
push dx ; save input
mov cl, CH7003_HPR
call OEMSetTVRegister
pop dx ; restore input
; VPR is 9 bits -each bit is 2 lines
; max value is PAL-312 ntsc-262
; so lets just use the value for now
pop dx
push dx
xchg dh, dl ; get vert
mov cl, CH7003_VPR
call OEMSetTVRegister
pop dx ; restore input
; pop cx ; get mode back
pop cx ; restore cx
clc ; clear carry
ENDIF ; CH7003
ret
Adjust_TV_Position ENDP
;**************************************************************************
;*
;* AdjustTVRelativePosition
;*
;* This routine adjusts the position if the TV image
;*
;* Entry:
;* If Chrontel CH7002:
;* DL = signed horizontal adjustment (positive left)
;* DH = signed vertical adjustment (positive down)
;*
;* Exit:
;* Destroys:
;*
;**************************************************************************
IF CH7002
AdjustTVRelativePosition PROC NEAR
mov ax, dx ; copy adjustment
TVPos_loop:
test ah, 07Fh
jz SHORT TVPos_horz
test ah, 080h
jnz SHORT TVPos_up
; MOVE DOWN
dec ah
mov dl, CH7002_POSITION_DOWN
jmp SHORT TVPos_set
TVPos_up:
; MOVE UP
inc ah
mov dl, CH7002_POSITION_UP
jmp SHORT TVPos_set
TVPos_horz:
test al, 07Fh
jz SHORT TVPos_done
test al, 080h
jnz SHORT TVPos_left
; MOVE RIGHT
dec al
mov dl, CH7002_POSITION_RIGHT
jmp SHORT TVPos_set
TVPos_left:
; MOVE LEFT
inc al
mov dl, CH7002_POSITION_LEFT
TVPos_set:
push ax ; save position
mov cl,CH7002_POSITION_CONTROL
call OEMSetTVRegister ; move screen image
mov cl, CH7002_POSITION_CONTROL
mov dl, CH7002_POSITION_NONE ; normal register value
call OEMSetTVRegister ; set register back to normal
pop ax ; restore position
jmp TVPos_loop ; branch back for more
TVPos_done:
clc
ret
AdjustTVRelativePosition ENDP
ENDIF ; CH7002
;**************************************************************************
;*
;* Adjust_TV_Brightness
;*
;* Entry:
;* CH = 03
;* DL = brightness
;*
;* Exit:
;*
;* Destroys:
;*
;**************************************************************************
Adjust_TV_Brightness PROC NEAR
IF CH7003
; SET THE "BLACK LEVEL" REGISTER ON THE CH7003
; 7003 range is 51-208
; input is 0-255
; mutlipy by 157 and divide by 255 then add 51 to scale
mov al, dl ; get value
mov bl, 157
mul bl ; multiply by 157
; ah is result / 255
add ah, 51 ; add offset
mov dl, ah ; to dl
mov cl, CH7003_BLR ; CH7003 register
call OEMSetTVRegister ; write CH7003 register
ENDIF
IF CH7002
; SET THE "BLACK LEVEL" REGISTER ON THE CH7002
shr dl, 2 ; scale down by 4 (0-63)
add dl, 52 ; add base (52-115)
mov cl, CH7002_BLACK_LEVEL ; CH7002 register
call OEMSetTVRegister ; write CH7002 register
ENDIF
clc
ret
Adjust_TV_Brightness ENDP
;**************************************************************************
;*
;* Adjust_TV_Output
;*
;* Entry:
;* CH = 04
;* DL = Bit 0: Enable S-video output
;* Bit 1: Enable composite output
;* Bit 2: Enable contrast circuitry
;*
;* Exit:
;*
;* Destroys:
;*
;**************************************************************************
Adjust_TV_Output PROC NEAR
IF CH7003
; SET THE "POWER Management" REGISTER ON THE CH7003
; test cl, 4h ; check contrast bit
; jz TVOut_10
; or dl, 80h ; set contrast enhancement
;TVOut_10:
mov cl, dl ; copy input parameter
mov dl, CH7003_PMR_POWER_DOWN ; assume power down
and cl, 3 ; keep lower 2 bits
jz TVOut_20 ; done if power down
mov dl, CH7003_PMR_ON ; assume both on
cmp cl, 3 ; check if both on
je TVOut_20 ; jump if both on
mov dl, CH7003_PMR_S_VID_OFF ; assume S-video off
cmp cl, 2 ; check if S-video off
je TVOut_20 ; jump if S-video off
mov dl, CH7003_PMR_COMP_OFF ; must be composite off
TVOut_20:
mov cl, CH7003_PMR
call OEMSetTVRegister ; set outputs
ENDIF
IF CH7002
; SET THE "MISC CONTROL" REGISTER ON THE CH7002
mov cl, dl ; copy input parameter
mov dl, 01 ; assume power down
test cl, 4h ; check contrast bit
jz TVOut_10
or dl, 80h ; set contrast enhancement
TVOut_10:
and cl, 3 ; keep lower 2 bits
jz TVOut_20 ; done if power down
or dl, 3 ; assume both on
cmp cl, 3 ; check if both on
je TVOut_20 ; jump if both on
and dl, 0FEh ; assume S-video off
cmp cl, 2 ; check if S-video off
je TVOut_20 ; jump if S-video off
and dl, 0FCh ; must be composite off
TVOut_20:
mov cl, CH7002_MISC_CONTROL
call OEMSetTVRegister ; move screen image
ENDIF
clc
ret
Adjust_TV_Output ENDP
;**************************************************************************
;*
;* Reset_Encoder
;*
;* This routine resets the encoder after changing modes, if needed.
;*
;* Entry:
;* CH = 05
;*
;* Exit:
;* Destroys:
;*
;**************************************************************************
Reset_Encoder PROC NEAR
IF CH7002
;Chrontel has suggested a workaround to a bug in their hardware that causes
;the TV display to go B&W periodically when changing modes. They suggest
;that whenever the TV display mode is changed or the video signal source is
;changed between S-video and Composite, that we do the following in our
;code:
;1. At the very end of the configuration routine, write all 0s to Register 3
;(Sampling Delay Register).
;2. Next write a value of 15 (all 1s ?) to the same register.
;3. Repeat steps 1 and 2 approximately 15 times.
;
;Apparently, flipping all of these bits over and over causes their PLLs in
;the color burst circuitry to resynchronize.
; LOOP 15 TIMES - Do 'F' then '0' to leave at default '0' value.
; MAKE SURE POWER SET TO S-VIDEO AND COMPOSITE
mov cx, 15
reset_loop:
push cx
mov cl, CH7002_SAMPLE_DELAY ; CH7002 register
mov dl, 0 ; register value
call OEMSetTVRegister ; set sense high
mov cl, CH7002_SAMPLE_DELAY ; CH7002 register
mov dl, 0Fh ; register value
call OEMSetTVRegister ; set sense high
pop cx
dec cx
jnz reset_loop
mov cl, CH7002_SAMPLE_DELAY
mov dl, CH7002_SAMPLE_DEFAULT
call OEMSetTVRegister
ENDIF
clc
ret
Reset_Encoder ENDP
;**************************************************************************
;*
;* Return_DDC2_Status
;*
;* Note that the DDC2 supported bit should only be set if the monitor
;* acknowledges an access to A0h across the I2C bus.
;*
;* Entry:
;* CH = 10h
;*
;* Exit:
;* CF set if DDC2 supported
;*
;* Destroys:
;*
;**************************************************************************
Return_DDC2_Status PROC NEAR
mov cx, 8
DDCStatus_loop:
push cx
; START CONDITION
mov si, SELECT_DDC
call StartCondition
; WRITE DATA VALUES
mov bl, 0A0h
call OEMSetI2CData
pop cx
jz SHORT DDCStatus_yes ; branch if ack = 0
loop DDCStatus_loop
clc ; DDC2 not supported
ret
DDCStatus_yes:
stc ; DDC2 supported
ret
Return_DDC2_Status ENDP
;**************************************************************************
;*
;* Return_DDC2_Information
;*
;* This routine reads DDC data from the monitor.
;*
;* Entry:
;* CH = 11h
;* ES:DI = DDC data buffer
;*
;* Exit:
;* ES:DI = data stored in DDC buffer
;*
;* Destroys:
;* AX, BX, CX, DX.
;* SI must be preserved.
;*
;**************************************************************************
Return_DDC2_Information PROC NEAR
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -