	Page	58,132
	Title	ANTIC.ASM	ANTIC emulator
;******************************************************************************
;
;   Name:	ANTIC
;
;   Group:	Emulator
;
;   Revision:	0.00
;
;   Date:  07-13-94
;
;   Author: Michael Munoz
;
;******************************************************************************
;
;  Module Functional Description:
;
;	These routines simulate all of the atari playfield graphics.
;	All of the CITA graphics modes have been implemented.  I do
; 	no know how to implement the GITA grpahics modes.
;	Each routine is listed by its OS graphics mode number,
;	i.e. Antic_mode2 is the OS graphics mode 2 (Basic mode 0).
;
;******************************************************************************
;
;  Changes:
;
;    DATE     REVISION				DESCRIPTION
;  --------   --------	-------------------------------------------------------
;
;******************************************************************************
	Page
;
;  Public Declarations
;
	Public	Antic_Update
	Public	Antic_Blank
	Public	Antic_Jmp
	Public	Antic_mode2
	Public	Antic_mode3
	Public	Antic_mode4
	Public	Antic_mode5
	Public	Antic_mode6
	Public	Antic_mode7
	Public	Antic_mode8
	Public	Antic_mode9
	Public	Antic_modeA
	Public	Antic_modeB
	Public	Antic_modeC
	Public	Antic_modeD
	Public	Antic_modeE
	Public	Antic_modeF
	Public	Antic_dlist
	Public	Antic_dinstr
	Public	Antic_pc
	Public	Antic_evcount
	Public	Antic_memscan
	Public	Antic_wait
	Public	Antic_sc
	Public	Antic_dliflag
	Public	Video_Pntr_Cur
	Public	Video_Pntr_Old
	Public	sTOP
	Public	sBOT
	Public	instr_count
	Public	Hsync
;  External Declarations
;
	Extrn	nmi_flag:Byte
	Extrn	COUNT_Table:Byte
	Extrn	Flag_Encode:Byte
	Extrn	Exit:Near
;
;  Define any include files needed
;
	Include 	Macros.inc	; Include the macro definitions
	Include 	Equates.inc	; Include the equate definitions
	Include		Atari.inc	; Atari equates

; Local	MACROS

;
; The DLITEST macro is used to determine whether we need call
; the display list interrupt routine.  If a DLI is required
; a flag is set and tested in Hardware_Update() in Hardware.asm
;
DLITEST	macro
	local No_DLI
	mov	bl,cs:Antic_dinstr	; ***bl is dinstr***
	test	bl,B7			; DLI enabled?
	je	No_DLI
	mov	di,LB_NMIEN		; nmi enabled?
	mov	al,Antic_ram[di]
	test	al,80h
	je	No_DLI
	mov	di,NMIST                ; update NMI status
	mov	Byte Ptr [di],80h	; set msb
	mov	cs:[nmi_flag],1		; set dli flag
No_DLI:
	endm
;
;  Determines the width of the screen, and saves any overscan in
;  Antic_Overscan.
;
GET_OVERSCAN macro SHIFT
	mov	di,LB_DMACTL		; short address for dmactl register
	mov	al,Antic_ram[di]	; get dmactl from antic ram
; Get the size of the screen > 320 (ignore narrow playfield)
	and	al,B0			; get wide playfield bit
	shl	al,SHIFT+1		; get size of block for the mode
	shr	al,1
	xor	ah,ah
	mov	cs:Antic_Overscan,ax	; save overscan
	endm
;
; Tests to see if memory scan counter needs to be reloaded
; and reloads if required.
;
RELOAD	macro
local _No_Reload
; get the address of the Atari display data
	mov	si,cs:Antic_memscan	; get display memory address
	; Assume dinstr is in bl
	test	bl,B6			; do we need to reload memscan?
	je     	_No_Reload		; no, take jmp
	mov	di,cs:Antic_pc		; get current dlist counter
	inc	di			; get next byte
	mov	si,[di]			; get memory pointer in si
	inc	di			; point to current dlist byte
	mov	cs:Antic_pc,di		; save current instruction count
_No_Reload:
	mov	cs:Antic_Old_memscan,si
	endm
;
; This macro updates the extended vertical scan counter
; and performs a test for display list interrupt
;
EVC_UPDATE macro SC
local On_Screen
local Off_Display
local	_No_Reload
	DLITEST
	; update scan count here so that we know that current scan line
	; for PM graphics which are done after playfield graphics.
	mov	ax,cs:Antic_evcount     ; Update antic vertical line counter
	add	ax,cs:Antic_sc		; add previous scan line count
	mov	cs:Antic_evcount,ax	; save back in cs:Antic_evcount
	cmp	ax,cs:sTOP		; past top of display?
	jl	Off_Display
	cmp	ax,sBOT			; last displayed horizontal line
	jbe	On_Screen		; current scan line within display
Off_Display:
	test	bl,B6			; do we need to reload memscan?
	je     	_No_Reload		; no, take jmp
	mov	di,cs:Antic_pc		; get current dlist counter
	mov	si,[di+1]		; get memory pointer in si
	mov	cs:Antic_memscan,si
	add	cs:Antic_pc,2
_No_Reload:
	mov	cs:Antic_sc,SC
	inc	cs:Antic_pc		; point to next instruction
	popa
	ret
On_Screen:
	endm

;
; The Get_Colors macro reads the colors from the atari ram and
; orders the colors in a more useable fashion in COLOR_TABLE
;
;   uses bp, al and di

Get_Colors	macro
	mov	di,LB_COLBK
	mov	al,Gita_ram[di]
	mov	bx,0
	mov	cs:COLOR_TABLE[bx],al
	mov	di,LB_COLPF0
	mov	al,Gita_ram[di]
	inc	bx
	mov	cs:COLOR_TABLE[bx],al
	inc	di
	mov	al,Gita_ram[di]
	inc	bx
	mov	cs:COLOR_TABLE[bx],al
	inc	di
	mov	al,Gita_ram[di]
	inc	bx
	mov	cs:COLOR_TABLE[bx],al
	inc	di
	mov	al,Gita_ram[di]
	inc	bx
	mov	cs:COLOR_TABLE[bx],al
	endm
;
; The Write_Color macro is used in graphics mode d
; Write color uses  al, di and dx
Write_Color_2	macro
	mov	bh,cs:COLOR_TABLE[bp]	; convert to a color
	mov	es:[di],bh		; write color to screen
	inc	di
	mov	es:[di],bh		; write color to screen again
	inc	di
	endm

;
; The Write_Color_4 macro is used in graphics mode A
; Write color uses  al, di and dx
Write_Color_4	macro
	mov	bh,cs:COLOR_TABLE[bp]	; convert to a color
	mov	es:[di],bh		; write color to screen
	inc	di
	mov	es:[di],bh		; write color to screen again
	inc	di
	mov	es:[di],bh		; write color to screen
	inc	di
	mov	es:[di],bh		; write color to screen again
	inc	di
	endm
;
; The Write_Color_8 macro is used in graphics mode 8
; Write color uses  al, di and dx
Write_Color_8	macro
	mov	bh,cs:COLOR_TABLE[bp]	; convert to a color
	mov	es:[di],bh		; write color to screen
	inc	di
	mov	es:[di],bh		; write color to screen again
	inc	di
	mov	es:[di],bh		; write color to screen
	inc	di
	mov	es:[di],bh		; write color to screen again
	inc	di
	mov	es:[di],bh		; write color to screen
	inc	di
	mov	es:[di],bh		; write color to screen again
	inc	di
	mov	es:[di],bh		; write color to screen
	inc	di
	mov	es:[di],bh		; write color to screen again
	inc	di
	endm


	.286c				; Include 80286 instructions
	Page
;
;  Define the emulator code segment
;
Emulate Segment Word Public 'EMULATE'   ; Emulator code segment
	Assume	cs:Emulate, ds:Nothing, es:Nothing
	even

;Memory for ANTIC
instr_count	DW	128d		; Number of 6502 clocks before the
					; next Hardware update
Hsync		DW	128d
sTOP		DW	32d  		; top of screen
sBOT		DW	224d		; bottom of screen
Video_Pntr_Cur	DW	0		; points to next screen location
Video_Pntr_Old	DW	0		; Old screen position
Antic_dlist	DW	0		; display list address
Antic_dinstr	DB	0		; current DL instruction
Antic_pc	DW	0		; current DL program counter
Antic_evcount	DW	0		; current vertical count
Antic_memscan	DW	0		; memory location of display
Antic_Old_memscan	DW	0
Antic_Overscan	DW	0
Antic_wait	DB	0		; wait for vsync flag
Antic_sc	DW	0		;
Antic_dliflag	DB	0               ; dli interrupt requested?
ch1		DB	0               ; holds
Antic_shift	DW	?
index_k		DW	?		; used for looping
index_i		DW	?
index_j		DW	?
temp		DW	?

; Table of current colors
 COLOR_TABLE	EQU	This Byte
	DB 	0
	DB	0
	DB	0
	DB	0
	DB	0

	Subttl	ANTIC_blank
	Page	+
;******************************************************************************
;
;	ANTIC_blank
;
;	Registers on Entry:
;
;	       none
;
;	Registers on Exit:
;
;		ax,cx  - restored
;
;	Function:
;
;	Increments the vertical counter to simulate adding blank lines
;	on the screen.
;
;******************************************************************************
		Even			; Force procedure to even address

Antic_Blank  Proc Near
	push	cx
	; checks for a display list instruction request
	; and get the current display instruction in bl.
	DLITEST
	; get background color
	mov	di,LB_COLBK
	mov	cl,Gita_ram[di]
	mov	ch,cl
	; Update scan line
	mov	ax,cs:Antic_evcount	; get current scan line
	add	ax,cs:Antic_sc
	mov	cs:Antic_evcount,ax	; updata evcount
	; determine number of blank lines
	shr	bl,4			; move upper fours bits
	and	bl,07h			;get lower three bits
	inc	bl			;add one
	; save number of blank lines in Antic_sc for Player_Missle()
	xor	bh,bh			; make a word
	mov	cs:Antic_sc,bx		; save the number of blank lines
	; See if blank lines cross the top of the IBM display
	add	ax,bx			; add number of blank lines
	sub	ax,cs:sTOP		; less top of screen
	; if ax = Antic_evcount + Antic_sc - sTOP is negative or zero
	jle	Not_On_Screen
	cmp	bx,ax			; get smaller of two in bx
	jge	Smaller_ax
	mov	ax,bx
Smaller_ax:
	; get current video pointer
	mov	di,cs:Video_Pntr_Cur
	; save as old pointer for Player_Missle() in Gita.asm
	mov	cs:Video_Pntr_Old,di
Blank_Loop:
	mov	bx,160d
Blank_Pixel_Loop:
	mov	Word Ptr es:[di],cx		; write blank
	add	di,2
	dec	bx
	jne	Blank_Pixel_Loop
	dec	ax
	jne	Blank_Loop
	mov	cs:Video_Pntr_Cur,di		;update video pointer
Not_On_Screen:
	mov	ax,cs:Hsync
	shl	ax,3				; assume 8 scan lines
	mov     cs:instr_count,ax		; cs:Hsync*number of blank lines

	inc	cs:Antic_pc			; get next disp. intsruction
	pop	cx
	ret
 Antic_Blank  ENDP

	Subttl	ANTIC_JMP
	Page	+
;******************************************************************************
;
;	ANTIC_JMP
;
;	Registers on Entry:
;
;	       none
;
;	Registers on Exit:
;
;		ax,di  - restored
;
;	Function:
;
;	Reloads the the display list address and sets the
;	Antic_wait (wait for vertical blank) flag if
;	required.
;
;******************************************************************************
		Even			; Force procedure to even address
Antic_Jmp    Proc Near
	; checks for a display list instruction request
	; and get the current display instruction in bl.
	DLITEST
;   this mode reloads the display list address
	mov	di,cs:Antic_pc		; get Antic program counter
	inc	di			; point to next byte
	mov	al,[di]			; get lo byte of display list addr
	inc	di			; point to next byte
	mov	ah,[di]			; get hi byte of display list addr
	mov	cs:Antic_dlist,ax	; update display list
	; update scan count
	mov	cs:Antic_sc,0           ; Player_Missle() will not display
					; anything this time.
	mov	ax,cs:Hsync             ; Run Hardware_update after
	mov     cs:instr_count,ax	; next scan line.
	; see if wait for vertical blank
	test	bl,B6
	je	No_JVB
	mov	cs:Antic_wait,1		; set wait for vert. blank flag
	; clear to end of IBM display
	mov	di,Video_Pntr_Cur
Clear_Loop:
	cmp	di,0fa00h			; max display
	jae	Clear_Loop_Done
	mov	Word Ptr es:[di],0
	add	di,2
	jmp	Clear_Loop
Clear_Loop_Done:
	mov	Video_Pntr_Cur,0
	mov	Video_Pntr_Old,0
No_JVB:
	ret
 Antic_Jmp    ENDP
	Subttl	ANTIC_mode2
	Page	+
;******************************************************************************
;
;	ANTIC_mode2
;		40 text characters each 8x8 pixels
;		2 colors
;
;	Registers on Entry:
;
;	       none
;
;	Registers on Exit:
;		none.
;
;	Register Usage:
;		bl	- display list instruction
;		bh	- character control
;		si 	- memory scan address (atari display data)
;		dl	- pfcol1 (foreground color)
;		dh	- pfcol2 (background color)
;		bp	- character table base address
;
;	Comments:
;
;	Vertical and horizontal scrolling is not implemented
;
;******************************************************************************
		Even			; Force procedure to even address
Antic_mode2  Proc Near
	pusha			; save all registers
	EVC_UPDATE 8		; update vert. scan counter
	RELOAD			; see if we need to update memscan
	GET_OVERSCAN 2		; determine value of horizontal overscan
				; either 0 or 4
; get the color values
	mov	di,LB_COLPF1		; read value for color pf1
	mov	dl,Gita_ram[di]		; dl = colpf1
	inc	di                      ; address of COLPF2
	mov	dh,Gita_ram[di]  	; dh = colpf2


; Get the character table address
	mov	di,LB_CHBASE		; get chbase address
	mov	ah,Antic_ram[di]	; get character base
	xor	al,al			; starts on 256 boundry
	mov	bp,ax			; save base in bp

; Save current IBM screen location for Player_Missle in Gita.asm
	mov	ax,Video_Pntr_Cur
	mov	Video_Pntr_Old,ax

; Get the character control value
	mov	di,LB_CHACTL		; get chactl address
	mov	bh,Antic_ram[di]	; keep in value bh

; start 8 vertical scan line loop
	mov	index_k,0		; initialize to zero

Start_K_Loop:
	mov	si,cs:Antic_Old_memscan	; get start of char. memory
	add	si,cs:Antic_Overscan	; add overscan value

; Read in 40 characters
	mov	index_i,40d		; 8 bytes per character

Build_Character:
	mov	bl,[si]		; save character name in bl
	inc	si		; inc memscan to point to next character
	mov	al,bl		; copy character name to al
	and	ax,07fh		; strip of special display bit
	shl	ax,3		; 8 bytes per char. so mult. char. name by 8
	add	ax,index_k	; point to current row in char. table
	mov	di,ax		; copy character table offset to di
	mov	ah,ds:[bp][di]	; get char. display data from table
				; point to by bp

	test	bl,B7			; test char. name, special bit set?
	je	Not_Special		; no, take jmp
	test	bh,B0			; do we want to blank the char.?
	je	No_Blank                ; no, try inverse
	mov	ah,0			; blank character
No_Blank:
	test	bh,B1			; inverse video?
	je	No_Inverse              ; no, display character
	not	ah			; do inverse video
No_Inverse:
Not_Special:
	mov	ch1,ah			; save display byte in ch1

	mov	di,Video_Pntr_Cur       ; get the current IBM screen location

	mov	cx,8h			; use cx as a pixel loop counter
Pixel_Loop:
	mov	es:[di],dh	; es points to IBM display
				; write the background color
	rol	ch1,1		; get display bit into carry
	jnc	Disp_Color2	; if zero do nothing since we have already
				; displayed the background color
	mov	es:[di],dl	; otherwise display foreground color
Disp_Color2:
	inc	di		; point to next IBM screen location
	loopne  Pixel_Loop	; dec cx and jmp if cx not equal to zero

	mov	Video_Pntr_Cur,di	; update the video pointer
	dec	index_i			; increment loop counter
	je	Next_Char_Disp		; no, get next scan line
	jmp	Build_Character		; no, continue
Next_Char_Disp:
	inc	index_k		; increment the char. counter
	cmp	index_k,8d	; see if we have display all 8 scan lines
	je	Loop_K_End	; see if we are finished
	jmp  	Start_K_Loop    ; display the next scan line
Loop_K_End:

; Account for wide playfield in display data memory
	add	si,cs:Antic_Overscan	; For wide screens adjust for overscan
	mov	cs:Antic_memscan,si	; save data pointer for next time

	inc	cs:Antic_pc	;point to next display list instruction

Antic_Mode2_Done:
	mov	Antic_sc,8	; Tell GITA how many scan lines were painted
; compute number of 6502 clock cycle until next hardware update
	mov	ax,cs:Hsync
	shl	ax,3
	mov     cs:instr_count,ax
	popa			; restore all registers
	ret
Antic_mode2  ENDP
	Subttl	ANTIC_mode3
	Page	+
;******************************************************************************
;
;	ANTIC_mode3
;       	40 text characters each 10x8 pixels
;               2 colors
;
;	Registers on Entry:
;
;	       none
;
;	Registers on Exit:
;              none
;
;	Register Usage:
;		bl	- display list instruction
;		bh	- character control
;		si 	- memory scan address (atari display data)
;		dl	- pfcol1 (foreground color)
;		dh	- pfcol2 (background color)
;		bp	- character table base address
;
;******************************************************************************
		Even			; Force procedure to even address
Antic_mode3  Proc Near
	pusha                   ; save all registers
	EVC_UPDATE 10		; update extended vert. counter
	RELOAD			; see if we need to reload memscan
	GET_OVERSCAN 2		; see if we are using the wide screen mode

	mov	di,LB_CHACTL		; get chactl address
	mov	bh,Antic_ram[di]	; keep in value bh

; Get color values
	mov	di,LB_COLPF1		; get pointer to color PF1
	mov	dl,Gita_ram[di]		; dl = colpf1
	inc	di                      ; get pointer to color PF2
	mov	dh,Gita_ram[di]  	; dh = colpf2

; Get character base
	mov	di,LB_CHBASE		; get chbase address
	mov	ah,Antic_ram[di]	; get character base
	xor	al,al			; starts on 256 boundry
	mov	bp,ax			; save base in bp


; precompute partial display address
	mov	ax,Video_Pntr_Cur	; get a pointer to the IBM display
	mov	Video_Pntr_Old,ax	; save for use by GITA
	mov	di,ax                   ; get a copy of the pointer in di

	mov	cx,640d		; write two blank lines each 320 pixels
Blank_2:
	mov	es:[di],dh	; es: accesses the Video ram
	inc	di		; point to next display location
	loopne	Blank_2	        ;loop until all 320 blank pixels are displayed

	mov     Video_Pntr_Cur,di	; save new IBM screen position

; start 10 vertical scan line loop
; the character is 10 scan lines high
	mov	index_k,1		; skip first two lines

Start_K_Loop_3:
	; reload memscan at start of each display row
	mov	si,Antic_Old_memscan	; get start of char. memory

; Critical timing loop. Read in 40 characters
	mov	index_i,0h		; 8 bytes per character (4)

Build_Character_3:
; cs:Antic_dinstr is no longer needed so we can use the bl register
	mov	bl,[si]			; save atascii in bl
	inc	si			; inc memscan
	mov	ax,index_k		; get current index
	and	ax,7			; modulo 8
	mov	cs:temp,ax		; save in temp
	mov	al,bl			; get atascii (2)
	and	ax,07fh			; strip of special bit (4)
	shl	ax,3			; 8 bytes per character (*8) (8)
	add	ax,cs:temp		; point to current row (3)
	mov	di,ax			; use index register (2)
	mov	ah,ds:[bp][di]		; character at [CHBASE+ch*8+cx] (21)

	test	bl,B7			; special bit set? (4)
	je	Not_Special_3		; no, take jmp (4,16)
	test	bh,B0			; blank ?  (4)
	je	No_Blank_3                ; no, try inverse (4,16)
	mov	ah,0			; blank character (4)
No_Blank_3:
	test	bh,B1			; inverse video? (4)
	je	No_Inverse_3            ; no, display character (4,16)
	not	ah			; do inverse video (2)
No_Inverse_3:
Not_Special_3:
	mov	ch1,ah			; save display byte

	mov	di,Video_Pntr_Cur

	mov	cx,8h
Pixel_Loop_3:
	mov	es:[di],dh
	rol	ch1,1			; get pixel value
	jnc	Disp_Color3		; diplay background color
	mov	es:[di],dl		; use color2
Disp_Color3:
	inc	di			;
	loopne  Pixel_Loop_3

	mov	Video_Pntr_Cur,di
	inc	index_i			; increment loop counter
	cmp	index_i,40d		; displayed all 40 bytes?
	je	Next_Char_Disp_3		; yes, get next scan line
	jmp	Build_Character_3		; no, continue
Next_Char_Disp_3:
	inc	index_k			; increment the char. counter
	cmp	index_k,9d		; 8 scan lines are done here
	je	Loop_K_End_3
	jmp  	Start_K_Loop_3
Loop_K_End_3:

	add	si,cs:Antic_Overscan
	mov	cs:Antic_memscan,si		; save for next time
	inc	cs:Antic_pc			; point to next instruction
Antic_Mode3_Done:
	mov	Antic_sc,10d
; compute number of 6502 clock cycle until next hardware update
	mov	ax,cs:Hsync
	mov	cx,ax
	shl	ax,3
	shl	cx,1
	add	ax,cx
	mov     cs:instr_count,ax
	popa				; restore all registers
	ret
 Antic_mode3  ENDP

	Subttl	ANTIC_mode4
	Page	+
;******************************************************************************
;
;	ANTIC_mode4
;		40 characters each 8x8 pixels
;		5 colors
;
;	Registers on Entry:
;
;	       none
;
;	Registers on Exit:
;		none
;
;	Register Usage:
;		bl	- display list instruction
;		si 	- memory scan address (atari display data)
;		dx	- character table base address
;
;******************************************************************************
		Even			; Force procedure to even address
Antic_mode4  Proc Near
	pusha
	EVC_UPDATE 8			; update event counter
	RELOAD
	GET_OVERSCAN 2

	; character map address
	mov	di,LB_CHBASE		; get chbase address
	mov	ah,Antic_ram[di]	; get character base
	xor	al,al			; starts on 256 boundry
	mov	dx,ax			; save base in dx


; get current IBM screen location
	mov	ax,Video_Pntr_Cur
	; Video_pntr_Old is used in PM graphics
	mov	Video_Pntr_Old,ax

; start 8 vertical scan line loop
	mov	index_k,0		; initialize to zero
Start_K_Loop_4:
	mov	si,Antic_Old_memscan	; get start of char. memory

; Critical timing loop. Read in 40 characters
	mov	cx,40d		; 8 bytes per character (4)

Build_Character_4:
; cs:Antic_dinstr is no longer needed so we can use the bl register
	Get_Colors			; macro to load color table
	mov	bl,[si]			; save atascii in bl
	inc	si			; inc memscan
	mov	al,bl			; get atascii (2)
	and	ax,07fh			; strip of special bit (4)
	shl	ax,3			; 8 bytes per cahracter (*8) (8)
	add	ax,index_k		; point to current row (3)
	mov	di,ax			; use index register (2)
	mov	bp,dx
	mov	ah,ds:[bp][di]		; character at [CHBASE+ch*8+cx] (21)
	mov	ch1,ah			; save display byte

	test	bl,B7			; special bit set? (4)
	je	Not_Special_4		; no, take jmp (4,16)
	mov	di,4
	mov	al,cs:COLOR_TABLE[di]
	mov	cs:COLOR_TABLE[di-1],al	; use colorpf3 insread of colorpf2
Not_Special_4:
	;get current location of the IBM screen into di
	mov	di,Video_Pntr_Cur

; Write one bytes worth of graphics data to the IBM screen
	mov	al,ch1			; get the graphics data byte in ax
	xor	ah,ah			; make a word
	mov	bp,ax			; copy ax
	shr	bp,6			; get lefmost two bits
	Write_Color_2			; macro to write the data to display
	mov	bp,ax                   ; uses bh, dx, di
	shr	bp,4
	and	bp,03h
	Write_Color_2
	mov	bp,ax
	shr	bp,2
	and	bp,03h
	Write_Color_2
	mov	bp,ax
	and	bp,03h
	Write_Color_2

	mov	Video_Pntr_Cur,di
	dec	cx				; increment loop counter
	je	Next_Char_Disp_4		; yes, get next scan line
	jmp	Build_Character_4		; no, continue
Next_Char_Disp_4:
;	add	si,overscan		; add and overscan bytes

	inc	index_k			; increment the char. counter
	cmp	index_k,8d		; 8 scan lines are done here
	je	Loop_K_End_4
	jmp  	Start_K_Loop_4
Loop_K_End_4:

	add	si,cs:Antic_Overscan
	mov	cs:Antic_memscan,si		; save for next time
	inc	cs:Antic_pc			; point to next instruction
Antic_Mode4_Done:
	mov	Antic_sc,8
	mov	ax,cs:Hsync
	shl	ax,3			; cs:Hsync*16*8
	mov     cs:instr_count,ax
	popa				; restore all registers
	ret
 Antic_mode4  ENDP

	Subttl	ANTIC_mode5
	Page	+
;******************************************************************************
;
;	ANTIC_mode5
;		40 characters each 16x8 pixels
;		5 colors
;
;	Registers on Entry:
;
;	       none
;
;	Registers on Exit:
;
;		none
;
;	Register Usage:
;		bl	- display list instruction
;		si 	- memory scan address (atari display data)
;		dx	- character table base address
;
;******************************************************************************
		Even			; Force procedure to even address
Antic_mode5  Proc Near
	pusha
	EVC_UPDATE 16			; update event counter
	RELOAD
	GET_OVERSCAN 2

	; character map address
	mov	di,LB_CHBASE		; get chbase address
	mov	dh,Antic_ram[di]	; get character base
	xor	dl,dl			; starts on 256 boundry


; get current IBM screen location
	mov	ax,Video_Pntr_Cur
	; Video_pntr_Old is used in PM graphics
	mov	Video_Pntr_Old,ax

; start 8 vertical scan line loop
	mov	index_k,0		; initialize to zero
	mov	index_i,2		; double scan
Start_K_Loop_5:
	mov	si,Antic_Old_memscan	; get start of char. memory

; Critical timing loop. Read in 40 characters
	mov	cx,40d		; 8 bytes per character (4)

Build_Character_5:
; cs:Antic_dinstr is no longer needed so we can use the bl register
	Get_Colors			; macro to load color table
	mov	bl,[si]			; save atascii in bl
	inc	si			; inc memscan
	mov	al,bl			; get atascii (2)
	and	ax,07fh			; strip of special bit (4)
	shl	ax,3			; 8 bytes per cahracter (*8) (8)
	add	ax,index_k		; point to current row (3)
	mov	di,ax			; use index register (2)
	mov	bp,dx
	mov	ah,ds:[bp][di]		; character at [CHBASE+ch*8+cx] (21)
	mov	ch1,ah			; save display byte

	test	bl,B7			; special bit set? (4)
	je	Not_Special_5		; no, take jmp (4,16)
	mov	di,4
	mov	al,cs:COLOR_TABLE[di]
	mov	cs:COLOR_TABLE[di-1],al	; use colorpf3 insread of colorpf2
Not_Special_5:
	;get current location of the IBM screen into di
	mov	di,Video_Pntr_Cur

; Write one bytes worth of graphics data to the IBM screen
	mov	al,ch1			; get the graphics data byte in ax
	xor	ah,ah			; make a word
	mov	bp,ax			; copy ax
	shr	bp,6			; get lefmost two bits
	Write_Color_2			; macro to write the data to display
	mov	bp,ax                   ; uses bh, dx, di
	shr	bp,4
	and	bp,03h
	Write_Color_2
	mov	bp,ax
	shr	bp,2
	and	bp,03h
	Write_Color_2
	mov	bp,ax
	and	bp,03h
	Write_Color_2

	mov	Video_Pntr_Cur,di
	dec	cx			; increment loop counter
	je	Next_Char_Disp_5		; yes, get next scan line
	jmp	Build_Character_5		; no, continue
Next_Char_Disp_5:
;	add	si,overscan		; add and overscan bytes

	dec	index_i
	je	Displayed_two		; display two scan lines the same
	jmp	Start_K_Loop_5
Displayed_two:
	mov	index_i,2		; double scan
	inc	index_k			; increment the char. counter
	cmp	index_k,8d		; 8 scan lines are done here
	je	Loop_K_End_5
	jmp  	Start_K_Loop_5
Loop_K_End_5:

	add	si,cs:Antic_Overscan
	mov	cs:Antic_memscan,si		; save for next time
	inc	cs:Antic_pc			; point to next instruction
Antic_Mode5_Done:
	mov	Antic_sc,16d
	mov	ax,cs:Hsync
	shl	ax,4			; cs:Hsync*16*16
	mov     cs:instr_count,ax
	popa				; restore all registers
	ret
 Antic_mode5  ENDP

	Subttl	ANTIC_mode6
	Page	+
;******************************************************************************
;
;	ANTIC_mode6
;		20 characters each 8x16 pixels
;		5 colors
;
;	Registers on Entry:
;
;	       none
;
;	Registers on Exit:
;
;		ax   - destroyed
;		di   - destroyed
;
;	Register Usage:
;		bl	- display list instruction
;		si 	- memory scan address (atari display data)
;		dx	- character table base address
;
;******************************************************************************
		Even			; Force procedure to even address
Antic_mode6  Proc Near
	pusha
	EVC_UPDATE 8			; update event counter
	RELOAD
	GET_OVERSCAN 1

	; character map address
	mov	di,LB_CHBASE		; get chbase address
	mov	ah,Antic_ram[di]	; get character base
	xor	al,al			; starts on 256 boundry
	mov	dx,ax			; save base in dx


; get current IBM screen location
	mov	ax,Video_Pntr_Cur
	; Video_pntr_Old is used in PM graphics
	mov	Video_Pntr_Old,ax

; start 8 vertical scan line loop
	mov	index_k,0		; initialize to zero
Start_K_Loop_6:
	mov	si,Antic_Old_memscan	; get start of char. memory

; Critical timing loop. Read in 40 characters
	mov	cx,20d		; 8 bytes per character (4)

Build_Character_6:
; cs:Antic_dinstr is no longer needed so we can use the bl register
	Get_Colors			; macro to load color table
	mov	bl,[si]			; save atascii in bl
	inc	si			; inc memscan
	mov	al,bl			; get atascii (2)
	and	ax,03fh			; strip of special bit (4)
	shl	ax,3			; 8 bytes per character (*8) (8)
	add	ax,index_k		; point to current row (3)
	mov	di,ax			; use index register (2)
	mov	bp,dx
	mov	ah,ds:[bp][di]		; character at [CHBASE+ch*8+cx] (21)
	mov	ch1,ah			; save display byte

Not_Special_6:
	;get current location of the IBM screen into di
	mov	di,Video_Pntr_Cur

	mov	index_i,8
Pixel_Loop_6:
; Write one bytes worth of graphics data to the IBM screen
	mov	al,bl			; get the color data
	xor	ah,ah			; make a word
	mov	bp,ax			; copy ax
	shr	bp,6			; get lefmost two bits
	inc	bp			; get higher set of colors
	rol	ch1,1			; get data bit
	jc	Use_Colors_6
	mov	bp,0			; use background color
Use_Colors_6:
	Write_Color_2
	dec 	index_i
	jne	Pixel_Loop_6

	mov	Video_Pntr_Cur,di
	dec	cx				; increment loop counter
	je	Next_Char_Disp_6		; yes, get next scan line
	jmp	Build_Character_6		; no, continue
Next_Char_Disp_6:
;	add	si,overscan		; add and overscan bytes

	inc	index_k			; increment the char. counter
	cmp	index_k,8d		; 8 scan lines are done here
	je	Loop_K_End_6
	jmp  	Start_K_Loop_6
Loop_K_End_6:

	add	si,cs:Antic_Overscan
	mov	cs:Antic_memscan,si		; save for next time
	inc	cs:Antic_pc			; point to next instruction
Antic_Mode6_Done:
	mov	Antic_sc,8
	mov	ax,cs:Hsync
	shl	ax,3			; cs:Hsync*16*8
	mov     cs:instr_count,ax
	popa				; restore all registers
	ret
 Antic_mode6  ENDP

	Subttl	ANTIC_mode7
	Page	+
;******************************************************************************
;
;	ANTIC_mode7
;		20 characters each 16x16 pixels
;		5 colors
;
;	Registers on Entry:
;
;	       none
;
;	Registers on Exit:
;
;		ax   - destroyed
;		di   - destroyed
;
;	Register Usage:
;		bl	- display list instruction
;		si 	- memory scan address (atari display data)
;		dx	- character table base address
;
;******************************************************************************
		Even			; Force procedure to even address
Antic_mode7  Proc Near
	pusha
	EVC_UPDATE 16			; update event counter
	RELOAD
	GET_OVERSCAN 1

	; character map address
	mov	di,LB_CHBASE		; get chbase address
	mov	ah,Antic_ram[di]	; get character base
	xor	al,al			; starts on 256 boundry
	mov	dx,ax			; save base in dx


; get current IBM screen location
	mov	ax,Video_Pntr_Cur
	; Video_pntr_Old is used in PM graphics
	mov	Video_Pntr_Old,ax

; start 8 vertical scan line loop
	mov	index_k,0		; initialize to zero
	mov	index_j,2
Start_K_Loop_7:
	mov	si,Antic_Old_memscan	; get start of char. memory

; Critical timing loop. Read in 40 characters
	mov	cx,20d		; 8 bytes per character (4)

Build_Character_7:
; cs:Antic_dinstr is no longer needed so we can use the bl register
	Get_Colors			; macro to load color table
	mov	bl,[si]			; save atascii in bl
	inc	si			; inc memscan
	mov	al,bl			; get atascii (2)
	and	ax,03fh			; strip of special bit (4)
	shl	ax,3			; 8 bytes per character (*8) (8)
	add	ax,index_k		; point to current row (3)
	mov	di,ax			; use index register (2)
	mov	bp,dx
	mov	ah,ds:[bp][di]		; character at [CHBASE+ch*8+cx] (21)
	mov	ch1,ah			; save display byte

Not_Special_7:
	;get current location of the IBM screen into di
	mov	di,Video_Pntr_Cur

	mov	index_i,8
Pixel_Loop_7:
; Write one bytes worth of graphics data to the IBM screen
	mov	al,bl			; get the color data
	xor	ah,ah			; make a word
	mov	bp,ax			; copy ax
	shr	bp,6			; get lefmost two bits
	inc	bp			; get higher set of colors
	rol	ch1,1			; get data bit
	jc	Use_Colors_7
	mov	bp,0			; use background color
Use_Colors_7:
	Write_Color_2
	dec 	index_i
	jne	Pixel_Loop_7

	mov	Video_Pntr_Cur,di
	dec	cx				; increment loop counter
	je	Next_Char_Disp_7		; yes, get next scan line
	jmp	Build_Character_7		; no, continue
Next_Char_Disp_7:
;	add	si,overscan		; add and overscan bytes
	dec	index_j
	je	Double_Scan_Done_7
	jmp	Start_K_Loop_7
Double_Scan_Done_7:
	mov	index_j,2
	inc	index_k			; increment the char. counter
	cmp	index_k,8d		; 8 scan lines are done here
	je	Loop_K_End_7
	jmp  	Start_K_Loop_7
Loop_K_End_7:

	add	si,cs:Antic_Overscan
	mov	cs:Antic_memscan,si		; save for next time
	inc	cs:Antic_pc			; point to next instruction
Antic_Mode7_Done:
	mov	Antic_sc,16
	mov	ax,cs:Hsync
	shl	ax,4			; cs:Hsync*16*16
	mov     cs:instr_count,ax
	popa				; restore all registers
	ret
 Antic_mode7  ENDP

;******************************************************************************
;
;	ANTIC_mode8
;		Graphics mode block size 8x8
;		4 colors
;
;	Registers on Entry:
;
;	       none
;
;	Registers on Exit:
;
;		ax   - destroyed
;		di   - destroyed
;
;******************************************************************************
 Antic_mode8  Proc Near
	pusha
	EVC_UPDATE 8			; update event counter
	RELOAD
	GET_OVERSCAN 0

; get colors and store in COLOR_TABLE
	 Get_Colors			; CX, AL, DI ARE USED

	 ; There are 320 pixels per vertical IBM display line
	 ; so 320 bytes x current vertical scan line gives the
	 ; IBM video memory offset for the current display line

; precompute partial display address
	mov	ax,Video_Pntr_Cur
	mov	Video_Pntr_Old,ax

	 ; do eight scan lines in this loop
	mov	cx,10d			; initialize to zero
	mov	index_k,8		; do this loop 8 times
	mov	di,Video_Pntr_Cur       ; get IBM screen location

Start_K_Loop_8:

; get current atari screen memory byte
	mov	bl,[si]			; save graphics data in bl
	inc	si			; point to graphics next byte

; Write one bytes worth of graphics data to the IBM screen
	mov	al,bl			; get the graphics data byte in ax
	xor	ah,ah			; make a word
	mov	bp,ax			; copy ax
	shr	bp,6			; get lefmost two bits
	Write_Color_8			; macro to write the data to display
	mov	bp,ax                   ; uses bh, dx, di
	shr	bp,4
	and	bp,03h
	Write_Color_8
	mov	bp,ax
	shr	bp,2
	and	bp,03h
	Write_Color_8
	mov	bp,ax
	and	bp,03h
	Write_Color_8

	dec	cx			; decrement the char. counter
	jne	Continue_Loop_8		;
	mov	cx,10d			; reset bytes/per scan line counter
	dec     index_k
	je	Loop_K_End_8
	mov	si,cs:Antic_Old_memscan	; reload memory scan counter
Continue_Loop_8:
	jmp  	Start_K_Loop_8
Loop_K_End_8:
	mov	Video_Pntr_Cur,di

	add	si,cs:Antic_Overscan
	mov	cs:Antic_memscan,si	; save for next time
	inc	cs:Antic_pc		; point to next instruction
Antic_Mode8_Done:
	mov	Antic_sc,8
	mov	ax,cs:Hsync
	shl	ax,3			; cs:Hsync*16*8
	mov     cs:instr_count,ax
	popa				; restore all registers
	ret
 Antic_mode8  ENDP

;******************************************************************************
;
;	ANTIC_mode9
;
;	Registers on Entry:
;
;	       none
;
;	Registers on Exit:
;
;		ax   - destroyed
;		di   - destroyed
;
;******************************************************************************
 Antic_mode9  Proc Near
	pusha
	EVC_UPDATE 4			; update event counter
	RELOAD
	GET_OVERSCAN 0

; get colors and store in COLOR_TABLE
	mov	di,LB_COLPF0
	mov	dl,Gita_ram[di]	; dl = colpf0
	mov	di,LB_COLBK
	mov	dh,Gita_ram[di]  	; dh = colbk

	mov	cs:Antic_memscan,si

	 ; There are 320 pixels per vertical IBM display line
	 ; so 320 bytes x current vertical scan line gives the
	 ; IBM video memory offset for the current display line

; precompute partial display address
	mov	ax,Video_Pntr_Cur
	mov	Video_Pntr_Old,ax

	 ; do eight scan lines in this loop
	mov	cx,10d			; initialize to zero
	mov	index_k,4		; do this loop 8 times
	mov	di,Video_Pntr_Cur       ; get IBM screen location

Start_K_Loop_9:

; get current atari screen memory byte
	mov	bl,[si]			; save graphics data in bl
	inc	si			; point to graphics next byte

; Write one bytes worth of graphics data to the IBM screen
	mov	ah,bl			; get the graphics data byte in ax

	mov	index_i,8
Loop_i_9:
	mov	es:[di],dh
	mov	es:[di+1],dh
	mov	es:[di+2],dh
	mov	es:[di+3],dh
	rol	ax,1			; get pixel value
	jnc	Disp_Color9		; diplay background color
	mov	es:[di],dl		; use color2
	mov	es:[di+1],dl
	mov	es:[di+2],dl
	mov	es:[di+3],dl
Disp_Color9:
	add	di,4
	dec	index_i
	jne	Loop_i_9

	dec	cx			; decrement the b/s counter
	jne	Continue_Loop_9		;
	mov	cx,10d			; reset bytes/per scan line counter
	dec     index_k			; dec display scan line count
	je	Loop_K_End_9
	mov	si,cs:Antic_memscan	; reload memory scan counter
Continue_Loop_9:
	jmp  	Start_K_Loop_9
Loop_K_End_9:
	mov	Video_Pntr_Cur,di

	add	si,cs:Antic_Overscan
	mov	cs:Antic_memscan,si	; save for next time
	inc	cs:Antic_pc		; point to next instruction
Antic_Mode9_Done:
	mov	Antic_sc,4
	mov	ax,cs:Hsync
	shl	ax,2			; cs:Hsync*16*4
	mov     cs:instr_count,ax
	popa				; restore all registers
	ret
 Antic_mode9  ENDP

;******************************************************************************
;
;	ANTIC_modeA
;
;	Registers on Entry:
;
;	       none
;
;	Registers on Exit:
;
;		ax   - destroyed
;		di   - destroyed
;
;******************************************************************************
 Antic_modeA  Proc Near
	pusha
	EVC_UPDATE 4			; update event counter
	RELOAD
	GET_OVERSCAN 1

; get colors and store in COLOR_TABLE
	 Get_Colors			; CX, AL, DI ARE USED

	mov	cs:Antic_memscan,si

	 ; There are 320 pixels per vertical IBM display line
	 ; so 320 bytes x current vertical scan line gives the
	 ; IBM video memory offset for the current display line

; precompute partial display address
	mov	ax,Video_Pntr_Cur
	mov	Video_Pntr_Old,ax

	 ; do eight scan lines in this loop
	mov	cx,20d			; initialize to zero
	mov	index_k,4		; do this loop 8 times
	mov	di,Video_Pntr_Cur       ; get IBM screen location

Start_K_Loop_A:

; get current atari screen memory byte
	mov	bl,[si]			; save graphics data in bl
	inc	si			; point to graphics next byte

; Write one bytes worth of graphics data to the IBM screen
	mov	al,bl			; get the graphics data byte in ax
	xor	ah,ah			; make a word
	mov	bp,ax			; copy ax
	shr	bp,6			; get lefmost two bits
	Write_Color_4			; macro to write the data to display
	mov	bp,ax                   ; uses bh, dx, di
	shr	bp,4
	and	bp,03h
	Write_Color_4
	mov	bp,ax
	shr	bp,2
	and	bp,03h
	Write_Color_4
	mov	bp,ax
	and	bp,03h
	Write_Color_4

	dec	cx			; decrement the char. counter
	jne	Continue_Loop_A		;
	mov	cx,20d			; reset bytes/per scan line counter
	dec     index_k
	je	Loop_K_End_A
	mov	si,cs:Antic_memscan	; reload memory scan counter
Continue_Loop_A:
	jmp  	Start_K_Loop_A
Loop_K_End_A:
	mov	Video_Pntr_Cur,di

	add	si,cs:Antic_Overscan
	mov	cs:Antic_memscan,si	; save for next time
	inc	cs:Antic_pc		; point to next instruction
Antic_ModeA_Done:
	mov	Antic_sc,4
	mov	ax,cs:Hsync
	shl	ax,2			; cs:Hsync*16*4
	mov     cs:instr_count,ax
	popa				; restore all registers
	ret
 Antic_modeA  ENDP

;******************************************************************************
;
;	ANTIC_modeB
;
;	Registers on Entry:
;
;	       none
;
;	Registers on Exit:
;
;		ax   - destroyed
;		di   - destroyed
;
;******************************************************************************
 Antic_modeB  Proc Near
	pusha
	EVC_UPDATE 2			; update event counter
	RELOAD
	GET_OVERSCAN 1

; get colors and store in COLOR_TABLE
	mov	di,LB_COLPF0
	mov	dl,Gita_ram[di]	; dl = colpf0
	mov	di,LB_COLBK
	mov	dh,Gita_ram[di]  	; dh = colbk

	mov	cs:Antic_memscan,si

	 ; There are 320 pixels per vertical IBM display line
	 ; so 320 bytes x current vertical scan line gives the
	 ; IBM video memory offset for the current display line

; precompute partial display address
	mov	ax,Video_Pntr_Cur
	mov	Video_Pntr_Old,ax

	 ; do eight scan lines in this loop
	mov	cx,20d			; initialize to zero
	mov	index_k,2		; do this loop 2 times
	mov	di,Video_Pntr_Cur       ; get IBM screen location

Start_K_Loop_B:

; get current atari screen memory byte
	mov	bl,[si]			; save graphics data in bl
	inc	si			; point to graphics next byte

; Write one bytes worth of graphics data to the IBM screen
	mov	ah,bl			; get the graphics data byte in ax

	mov	index_i,8
Loop_i_B:
	mov	es:[di],dh
	mov	es:[di+1],dh
	rol	ax,1			; get pixel value
	jnc	Disp_ColorB		; diplay background color
	mov	es:[di],dl		; use color2
	mov	es:[di+1],dl
Disp_ColorB:
	add	di,2
	dec	index_i
	jne	Loop_i_B

	dec	cx			; decrement the b/s counter
	jne	Continue_Loop_B		;
	mov	cx,20d			; reset bytes/per scan line counter
	dec     index_k			; dec display scan line count
	je	Loop_K_End_B
	mov	si,cs:Antic_memscan	; reload memory scan counter
Continue_Loop_B:
	jmp  	Start_K_Loop_B
Loop_K_End_B:
	mov	Video_Pntr_Cur,di

	add	si,cs:Antic_Overscan
	mov	cs:Antic_memscan,si	; save for next time
	inc	cs:Antic_pc		; point to next instruction
Antic_ModeB_Done:
	mov	Antic_sc,2
	mov	ax,cs:Hsync
	shl	ax,1			; cs:Hsync*16*2
	mov     cs:instr_count,ax
	popa				; restore all registers
	ret
 Antic_modeB  ENDP

;******************************************************************************
;
;	ANTIC_modeC
;
;	Registers on Entry:
;
;	       none
;
;	Registers on Exit:
;
;		ax   - destroyed
;		di   - destroyed
;
;******************************************************************************
 Antic_modeC  Proc Near
	pusha
	EVC_UPDATE 1			; update event counter
	RELOAD
	GET_OVERSCAN 2

; get colors and store in COLOR_TABLE
	mov	di,LB_COLPF0
	mov	dl,Gita_ram[di]	; dl = colpf0
	mov	di,LB_COLBK
	mov	dh,Gita_ram[di]  	; dh = colbk

	mov	cs:Antic_memscan,si

; precompute partial display address

	 ; There are 320 pixels per vertical IBM display line
	 ; so 320 bytes x current vertical scan line gives the
	 ; IBM video memory offset for the current display line

; precompute partial display address
	mov	ax,Video_Pntr_Cur
	mov	Video_Pntr_Old,ax

	 ; do eight scan lines in this loop
	mov	cx,20d			; initialize to zero
	mov	di,Video_Pntr_Cur       ; get IBM screen location

Start_K_Loop_C:

; get current atari screen memory byte
	mov	bl,[si]			; save graphics data in bl
	inc	si			; point to graphics next byte

; Write one bytes worth of graphics data to the IBM screen
	mov	ah,bl			; get the graphics data byte in ax

	mov	index_i,8
Loop_i_C:
	mov	es:[di],dh
	mov	es:[di+1],dh
	rol	ax,1			; get pixel value
	jnc	Disp_ColorC		; diplay background color
	mov	es:[di],dl		; use color2
	mov	es:[di+1],dl
Disp_ColorC:
	add	di,2
	dec	index_i
	jne	Loop_i_C

	dec	cx			; decrement the b/s counter
	jne	Start_K_Loop_C		;
Loop_K_End_C:

	mov	Video_Pntr_Cur,di

	add	si,cs:Antic_Overscan
	mov	cs:Antic_memscan,si	; save for next time
	inc	cs:Antic_pc		; point to next instruction
Antic_ModeC_Done:
	mov	Antic_sc,1
	mov	ax,cs:Hsync
	mov     cs:instr_count,ax
	popa				; restore all registers
	ret
 Antic_modeC  ENDP


	Subttl	ANTIC_modeD
	Page	+
;******************************************************************************
;
;	ANTIC_modeD   160x96x4
;
;	Registers on Entry:
;
;	       none
;
;	Registers on Exit:
;		none
;
;******************************************************************************
		Even			; Force procedure to even address
Antic_modeD  Proc Near
	pusha
	EVC_UPDATE 2			; update event counter
	RELOAD
	GET_OVERSCAN 2

; get colors and store in COLOR_TABLE
	 Get_Colors			; CX, AL, DI ARE USED

	mov	cs:Antic_memscan,si

	 ; There are 320 poxels per vertical IBM display line
	 ; so 320 bytes x current vertical scan line gives the
	 ; IBM video memory offset for the current display line

; precompute partial display address
	mov	ax,Video_Pntr_Cur
	mov	Video_Pntr_Old,ax

	 ; do two scan lines in this loop
	mov	cx,0		; initialize to zero

	mov	di,Video_Pntr_Cur

Start_K_Loop_D:

; get current atari screen memory byte
	mov	bl,[si]			; save graphics in bl
	inc	si			; point to next byte

; Write one bytes worth of graphics data to the IBM screen
	mov	al,bl			; get the graphics data byte in ax
	xor	ah,ah			; make a word
	mov	bp,ax			; copy ax
	shr	bp,6			; get lefmost two bits
	Write_Color_2			; macro to write the data to display
	mov	bp,ax                   ; uses bh, dx, di
	shr	bp,4
	and	bp,03h
	Write_Color_2
	mov	bp,ax
	shr	bp,2
	and	bp,03h
	Write_Color_2
	mov	bp,ax
	and	bp,03h
	Write_Color_2

	inc	cx			; increment the char. counter
	cmp	cx,40d			; two scan lines
	jne	Continue_Loop_D		;
	mov	si,cs:Antic_memscan
Continue_Loop_D:
	cmp	cx,80d
	je	Loop_K_End_D
	jmp  	Start_K_Loop_D
Loop_K_End_D:
	mov	Video_Pntr_Cur,di

	add	si,cs:Antic_Overscan
	mov	cs:Antic_memscan,si	; save for next time
	inc	cs:Antic_pc		; point to next instruction
Antic_ModeD_Done:
	mov	Antic_sc,2
	mov	ax,cs:Hsync
	shl	ax,1			; cs:Hsync*16*2
	mov     cs:instr_count,ax
	popa				; restore all registers
	ret
Antic_modeD  ENDP

;******************************************************************************
;
;	ANTIC_modeE   160x191x4
;
;	Registers on Entry:
;
;	       none
;
;	Registers on Exit:
;		none
;
;******************************************************************************
		Even			; Force procedure to even address
Antic_modeE  Proc Near
	pusha
	EVC_UPDATE 1			; update event counter
	RELOAD
	GET_OVERSCAN 2

; get colors and store in COLOR_TABLE
	 Get_Colors			; CX, AL, DI ARE USED

	mov	cs:Antic_memscan,si

	 ; There are 320 poxels per vertical IBM display line
	 ; so 320 bytes x current vertical scan line gives the
	 ; IBM video memory offset for the current display line

; precompute partial display address
	mov	ax,Video_Pntr_Cur
	mov	Video_Pntr_Old,ax

	 ; do two scan lines in this loop
	mov	cx,0		; initialize to zero

	mov	di,Video_Pntr_Cur

Start_K_Loop_E:

; get current atari screen memory byte
	mov	bl,[si]			; save graphics in bl
	inc	si			; point to next byte

; Write one bytes worth of graphics data to the IBM screen
	mov	al,bl			; get the graphics data byte in ax
	xor	ah,ah			; make a word
	mov	bp,ax			; copy ax
	shr	bp,6			; get lefmost two bits
	Write_Color_2			; macro to write the data to display
	mov	bp,ax                   ; uses bh, dx, di
	shr	bp,4
	and	bp,03h
	Write_Color_2
	mov	bp,ax
	shr	bp,2
	and	bp,03h
	Write_Color_2
	mov	bp,ax
	and	bp,03h
	Write_Color_2

	inc	cx			; increment the char. counter
	cmp	cx,40d			; two scan lines
	jne	Start_K_Loop_E		;

	mov	Video_Pntr_Cur,di

	add	si,cs:Antic_Overscan
	mov	cs:Antic_memscan,si	; save for next time
	inc	cs:Antic_pc		; point to next instruction
Antic_ModeE_Done:
	mov	Antic_sc,1
	mov	ax,cs:Hsync
	mov     cs:instr_count,ax
	popa				; restore all registers
	ret
 Antic_modeE  ENDP

;******************************************************************************
;
;	ANTIC_modeF
;
;	Registers on Entry:
;
;	       none
;
;	Registers on Exit:
;
;		ax   - destroyed
;		di   - destroyed
;
;******************************************************************************
 Antic_modeF  Proc Near
	pusha
	EVC_UPDATE 1			; update event counter
	mov	bl,cs:Antic_dinstr	; bl is dinstr (display list instruc.)

	; All of these tests take time, for speed these may be deleted
	; at the cost of ocasionally running into a error in the display.
	mov	di,LB_DMACTL		; short address for dmactl register
	mov	al,Antic_ram[di]	; get dmactl from antic ram
	test	al,B1			; playfield enabled?
	jne	Get_Overscan_F    	; yes, continue
	jmp	Antic_ModeF_Done	; no, exit
Get_Overscan_F:
	mov	si,cs:Antic_memscan	; get display memory address
	test	bl,B6			; do we need to reload memscan?
	je     	No_Reload_F		; no, take jmp
	mov	di,cs:Antic_pc		; get current dlist counter
	inc	di			; get next byte
	mov	si,[di]			; get memory pointer in si
	inc	di			; point to current dlist byte
	mov	cs:Antic_pc,di		; save current instruction count

No_Reload_F:

; get colors and store in COLOR_TABLE
	mov	di,LB_COLPF1
	mov	dl,Gita_ram[di]	; dl = colpf0
	mov	di,LB_COLPF2
	mov	dh,Gita_ram[di]  	; dh = colpf1

	mov	cs:Antic_memscan,si

	 ; There are 320 pixels per vertical IBM display line
	 ; so 320 bytes x current vertical scan line gives the
	 ; IBM video memory offset for the current display line

; precompute partial display address
	mov	ax,Video_Pntr_Cur
	mov	Video_Pntr_Old,ax

	 ; do eight scan lines in this loop
	mov	cx,40d			; initialize to zero
	mov	di,Video_Pntr_Cur       ; get IBM screen location

Start_K_Loop_F:

; get current atari screen memory byte
	mov	bl,[si]			; save graphics data in bl
	inc	si			; point to graphics next byte

; Write one bytes worth of graphics data to the IBM screen
	mov	ah,bl			; get the graphics data byte in ax

	mov	index_i,8
Loop_i_F:
	mov	es:[di],dh
	rol	ax,1			; get pixel value
	jnc	Disp_ColorF		; diplay background color
	mov	es:[di],dl		; use color2
Disp_ColorF:
	inc	di
	dec	index_i
	jne	Loop_i_F

	dec	cx			; decrement the b/s counter
	jne	Start_K_Loop_F		;
Loop_K_Fnd_F:

	mov	Video_Pntr_Cur,di

	add	si,cs:Antic_Overscan
	mov	cs:Antic_memscan,si	; save for next time
	inc	cs:Antic_pc		; point to next instruction
Antic_ModeF_Done:
	mov	Antic_sc,1
	mov	ax,cs:Hsync
	mov     cs:instr_count,ax
	popa				; restore all registers
	ret
 Antic_modeF  ENDP


;******************************************************************************
;
;	Update Antic pseudo registers
;
;	Entry:
;	al: data
;       di: EA
;
;	uses: di,ax
;******************************************************************************
 Antic_Update	Proc	Near
	cmp	di,NMIRES		;reset nmi status?
	jne	Not_nmireset            ;no
	mov	Word Ptr [di], 0     ;reset status
	ret
 Not_nmireset:
	cmp	di,WSYNC                ;wait for cs:Hsync?
	jne	Not_wsync               ;no
	mov	bp,30
;	mov	bp,cs:Hsync		; force harware update
;	shl	bp,5
	ret
 Not_wsync:
	cmp	di,DLISTH		;are we updating dlist
	je	Is_dlist		;yes
	cmp	di,DLISTL               ;check both high and low addresses
	je	Is_dlist                ;yes
	jmp	Antic_update_exit	;no dlist update
 Is_dlist:
	mov	[di],al			;save to atari ram
	push	ax
	mov	di,DLISTH		;
	mov	ah,ds:[di]              ;get dlist high value in ah
	mov	di,DLISTL		;
	mov	al,ds:[di]              ;get dlist low value in al
	mov	cs:Antic_dlist,ax		;save in cs:Antic_dlist
	pop	ax
 Antic_update_exit:
	and	di,01fh			;update antic ram space...
	mov	Antic_ram[di],al		;just in case
	ret
 Antic_Update	Endp

;*****************************************************************************
;
;	Define the end of the Emulator Code Segment
;
;******************************************************************************
Emulate Ends
	End				; End of the Hardware module
