• Please review our updated Terms and Rules here

VGA timing for NTSC output with Mode X?

PgrAm

Experienced Member
Joined
Sep 28, 2011
Messages
276
Location
Toronto, Canada
Hey all,

I've been experimenting with getting a VGA card to produce an NTSC compatible signal, right now I'm using a box called TelevEyes. The box came with a little program to reprogram the VGA registers to output a 15khz signal, I have also tried using a utility called VGATV. The only problem is when a program (such as the game I'm working on), tries to mess with the vertical timing to change the resolution, strange things start happening. This then raises the question, is it possible to output a 320x240 mode-X signal to an NTSC television?

Since mode-X is at 60hz, the same as NTSC, I didn't think that this would be a problem. Unfortunately when I run the TV display program then try to set Mode X, I get a rapidly rolling image, so something is up with the vertical timing.

Here is my code for setting 320x240@60Hz mode X:

Code:
		out16(SC_INDEX, 0x0600 | MEMORY_MODE); // set mode to unchained

		out16(SC_INDEX, 0x100); //synchronous reset for safety
		out16(SC_INDEX, 0x300); //undo reset
		
		out16(CRTC_INDEX, 0x2c00 | V_RETRACE_END); // turn off write protect
		out16(CRTC_INDEX, 0x0000 | UNDERLINE_LOCATION); // turn off dword mode
		out16(CRTC_INDEX, 0xe300 | MODE_CONTROL);		// turn on byte mode

		//Set the vertical resolution to 240
		out16(CRTC_INDEX, 0x0d00 | V_TOTAL);
		out16(CRTC_INDEX, 0x3e00 | OVERFLOW_VGA);
		out16(CRTC_INDEX, 0xea00 | V_RETRACE_START);
		out16(CRTC_INDEX, 0xac00 | V_RETRACE_END);
		out16(CRTC_INDEX, 0xdf00 | V_DISPLAY_END);
		out16(CRTC_INDEX, 0xe700 | V_BLANK_START);
		out16(CRTC_INDEX, 0x0600 | V_BLANK_END);

Does anyone know how I might be able to either make my code play nice with the TV utility or set my own mode for 320x240@60Hz on a TV? The issue is clearly when I mess with the vertical timing, if I keep the resolution at 320x200 it works fine.
 
The "televeyes" and other cheap vga-to-TV boxes were very dumb (no framebuffer) so they relied on the host computer to set the correct card values to produce 15.7 KHz/60Hz output. The TSRs you mentioned (VGATV, etc.) work by hooking INT 10h calls and, rather than let the BIOS set up the mode, the TSR does it instead. That said, I have one of these and I remember running Doom (unchained 320x200) on a TV, which might have worked if Doom set 320x200 by first doing an int 10h and then reprogramming some registers. Memory is hazy on this specific point.

For 320x240, your challenge is to figure out how to get as close to 15.7 KHz / 60 Hz as possible manually. "Proper" 320x240 unchained was most commonly done as follows:

Code:
; This file was taken from Michael Abrash' XSHARP package, a library
; for programming mode X (320x240x256).

; Mode X (320x240, 256 colors) mode set routine. Works on all VGAs.
; C near-callable as:
;       void Set320x240Mode(void);
; Tested with TASM 2.0.
; Modified from public-domain mode set code by John Bridges.

SC_INDEX equ    03c4h   ;Sequence Controller Index
CRTC_INDEX equ  03d4h   ;CRT Controller Index
MISC_OUTPUT equ 03c2h   ;Miscellaneous Output register
SCREEN_SEG equ  0a000h  ;segment of display memory in mode X

        .model  small
        .data
; Index/data pairs for CRT Controller registers that differ between
; mode 13h and mode X.
CRTParms label  word
        dw      00d06h  ;vertical total
        dw      03e07h  ;overflow (bit 8 of vertical counts)
        dw      04109h  ;cell height (2 to double-scan)
        dw      0ea10h  ;v sync start
        dw      0ac11h  ;v sync end and protect cr0-cr7
        dw      0df12h  ;vertical displayed
        dw      00014h  ;turn off dword mode
        dw      0e715h  ;v blank start
        dw      00616h  ;v blank end
        dw      0e317h  ;turn on byte mode
CRT_PARM_LENGTH equ     (($-CRTParms)/2)

        .code
        public  _Set320x240Mode
_Set320x240Mode proc    near
        push    bp      ;preserve caller's stack frame
        push    si      ;preserve C register vars
        push    di      ; (don't count on BIOS preserving anything)

        mov     ax,13h  ;let the BIOS set standard 256-color
        int     10h     ; mode (320x200 linear)

        mov     dx,SC_INDEX
        mov     ax,0604h
        out     dx,ax   ;disable chain4 mode
        mov     ax,0100h
        out     dx,ax   ;synchronous reset while switching clocks

        mov     dx,MISC_OUTPUT
        mov     al,0e7h
        out     dx,al   ;select 28 MHz dot clock & 60 Hz scanning rate

        mov     dx,SC_INDEX
        mov     ax,0300h
        out     dx,ax   ;undo reset (restart sequencer)

        mov     dx,CRTC_INDEX ;reprogram the CRT Controller
        mov     al,11h  ;VSync End reg contains register write
        out     dx,al   ; protect bit
        inc     dx      ;CRT Controller Data register
        in      al,dx   ;get current VSync End register setting
        and     al,7fh  ;remove write protect on various
        out     dx,al   ; CRTC registers
        dec     dx      ;CRT Controller Index
        cld
        mov     si,offset CRTParms ;point to CRT parameter table
        mov     cx,CRT_PARM_LENGTH ;# of table entries
SetCRTParmsLoop:
        lodsw           ;get the next CRT Index/Data pair
        out     dx,ax   ;set the next CRT Index/Data pair
        loop    SetCRTParmsLoop

        mov     dx,SC_INDEX
        mov     ax,0f02h
        out     dx,ax   ;enable writes to all four planes
        mov     ax,SCREEN_SEG ;now clear all display memory, 8 pixels
        mov     es,ax         ; at a time
        sub     di,di   ;point ES:DI to display memory
        sub     ax,ax   ;clear to zero-value pixels
        mov     cx,8000h ;# of words in display memory
        rep     stosw   ;clear all of display memory

        pop     di      ;restore C register vars
        pop     si
        pop     bp      ;restore caller's stack frame
        ret
_Set320x240Mode endp
        end

Try these register values vs. the truncated ones you listed. No guarantees.

All this being said, I seem to recall we covered this in DemoNews at some point (not in my VGA tweaks articles, but a guest writer). You may want to grab all 150 issues and check the "programming" sections out. I'll also see if I have a register dump in my archives that solves this problem.
 
Thanks Trixter,

I've been looking at some of the issues of DemoNews there's quite a few of them so this may take some time. Found plenty of cool stuff already in those issues so it definitely hasn't been a waste of time! The values in my code look truncated because I used some macros for clarity, perhaps I should have defined them in my snippet, but I actually derived the values from the Michael Abrash code that you posted.
 
Basically got it working, the line counts just need to be about half of what they would be with regular Mode-X.
P1030764.jpg

There is some over scan but I think that's just the TV, I'm gonna try on my other Sony monitor which has adjustable height and see if everything is being displayed.

I'm gonna do some more work to see if I can automatically detect if the registers have been messed with by a TSR and adjust to my special mode.
 
Hmm detection seems not to be as simple as I thought, I figured I could just check after setting mode 13 to see if the scan double bit was set (bit 7 of the max scan line register), however this bit never seems to be set, tested on real hardware and in dosbox. I would have expected it to be set whenever the registers havent been messed with by a special program.

Code:
out8(0x3D4, 0x09); //CRTC index for MAXIMUM_SCAN_LINE
if(!(in8(0x3D5) & 0x80)) //if bit 7 is not set, then scan double is off, we must be displaying on a 15khz display
{
//set special TV mode
}
else
{
//set "normal" mode X
}
 
IIRC that bit was only used in compatibility modes (meaning, you'll see it set if you initialize a CGA mode, but not regular VGA).

Sorry I can't be of more help, I'm spinning 50 plates at the moment...
 
No worries I found a register to check that works.

Checking if the horizontal total register is 0x6B will tell you if an NTSC conversion TSR is installed, works with VGATV and TE.COM
 
Back
Top