Programming the CRT January 11, 1994 $Source: /u/cyliax/Projects/030/Doc/Prog/crt.ms,v $ The display is implemented using a PC compatible VGA display adapter. Although it is capable of supporting several display formats, we will only concern ourselves with the CRT emulation mode. In this mode, the VGA controller emulates a PC CGA display which is based around the MC6845 CRT controller. The CGA display system is made up of 3 significant parts, the display memory, the CRT controller and the display monitor. The display memory is memory that can be accessed by both the CRT controller and a host processor. The host processor will load the data that is to be displayed on the display into the display memory. It has read and write access to this memory. The CRT controller reads this memory and converts the characters to dot pat- terns (using a character map) that will be displayed on the display. The CRT controller has only read access to the display memory. The CRT controller has several device regis- ters that control the display parameters, i.e. how many columns or rows to be displayed, a display start register and a cursor register. To display information on the display, we only need to know about the memory start regis- ter, the cursor register and the display memory map. The display memory map is organized as 16bit memory words of 16K word length. The memory start register defines which 16bit word which is at the top left hand corner of the display. The memory then increases left to right and top to bottom. I.e. the top left corner has offset 0 from the start register and the bottom right hand corner has location (25*80) = 2000 (7d0h). The cursor register defines at which word location the cursor is to be visible on the display. If the cursor location is outside the active display area, no cursor will be displayed. addr display memory (active region at 2000h-27cfh) 0000 |-------| | | 2000 |-------|<-start memory 204f | |<-last character on first line 2050 | |<-first character on second line | | 27cf |-------|<-last character on last line | | 3fff |-------| Each word in the display is divided into a display code January 11, 1994 - 2 - byte and a attribute byte. The display code is the index into the character map used by the CRT controller. Usually, 20h-7fh correspond to the ASCII character map, where 0-1fh and 80-ffh are defined as special codes. The attribute code encodes what foreground and background colors the character is displayed in and whether it blinks or not. The normal attribute code is 7h (white foreground, black background, non blinking). word -> ccccccccaaaaaaaa cccccccc = display code (0-ffh) aaaaaaaa = attribute code (0-ffh) The host processor "sees" the display memory as a sequence of bytes with the character code first and the attribute code second. The display memory is normally mapped at 7f7b8000->7f7fffff. This memory can be written to and read from at any time. Remember to use "word" addresses in the CRT controllers registers and "byte" addresses when addressing display memory directly. I.e. the display memory address of 7f7ba000h as seen by the host processor is really 1000h as seen by the CRT controller. Here is a subroutine that will display the display/attribute code in d0.w at offset d1.w on the display. It does not modify the cursor or memory start register. crtmem equ $7f7b8000 * display memory crtidx equ $7f6003d4 * CRT index register crtdat equ $7f6004d5 * CRT data register crtshi equ $c * hi byte of memory start crtslo equ $d * lo byte of memory start * display d0.w at d1.w on the display, d2 and a0 are used crtdisplay: clr.l d2 * clear d2 move.b #crtshi,crtidx * get memory start from CRT one byte move.b crtdat,d2 * at a time lsl.w #8,d2 * move.b #crtslo,crtidx * or.b crtdat,d2 * add.w d1,d2 * absolute word address in display region lsl.l #1,d2 * convert to byte address (times 2) move.l #$crtmem,a0 * get display memory address move.w d0,(a0,d2) * store display and attribute in display mem. rts January 11, 1994