apple2ix/src/asm386/display.S

1216 lines
36 KiB
ArmAsm

/*
* Apple // emulator for Linux:
* Functions for low-level framebuffer output.
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#define __ASSEMBLY__
#include "apple2.h"
#include "video/video.h"
#include "cpu.h"
#include "misc.h"
/* -------------------------------------------------------------------------
Graphics routines.
Care has been taken to isolate the dimension-dependent (320x200 vs 640x400)
routines.
------------------------------------------------------------------------- */
#ifdef _640x400
#define Font SN(video__wider_font)
#define Font80 SN(video__font)
#else /* !_640x400 */
#define Font SN(video__font)
#endif /* !_640x400 */
/* -------------------------------------------------------------------------
* Plot exatly 7 pixels from FROM to TO.
* ecx: scratch
* ------------------------------------------------------------------------- */
#define Plot7Pixels(FROM,TO)\
movl (FROM), %ecx; /* long -> GM */ \
movl %ecx, (TO); \
addl $4, FROM; /* inc pointers */ \
addl $4, TO; \
movw (FROM), %cx; /* word -> GM */ \
movw %cx, (TO); \
addl $2, FROM; /* inc pointers */ \
addl $2, TO; \
movb (FROM), %cl; /* byte -> GM */ \
movb %cl, (TO);
#ifdef _640x400
#define LoadHiresTableRef(TABLE)\
leal SN(video__wider_hires_##TABLE), %ebx;\
shll $4, %eax;/* *16 */\
addl %eax, %ebx;
/* -------------------------------------------------------------------------
* Plot a normal swath of pixels.
* For 640x400 this is 2 rows of 14 pixels.
* ebx: from table
* eax: to graphics memory
* ------------------------------------------------------------------------- */
#define PlotPixels\
PlotPixels640\
subl $12, %ebx;\
addl $SCANWIDTH-12, %eax;\
PlotPixels640\
subl $SCANWIDTH, %eax;\
addl $1, %eax;
#define PlotPixels640\
movl (%ebx), %ecx; /* long -> GM */ \
movl %ecx, (%eax); \
addl $4, %eax; /* inc pointers */ \
addl $4, %ebx; \
movl (%ebx), %ecx; /* long -> GM */ \
movl %ecx, (%eax); \
addl $4, %eax; /* inc pointers */ \
addl $4, %ebx; \
movl (%ebx), %ecx; /* long -> GM */ \
movl %ecx, (%eax); \
addl $4, %eax; /* inc pointers */ \
addl $4, %ebx; \
movw (%ebx), %cx; /* word -> GM */ \
movw %cx, (%eax);
/* -------------------------------------------------------------------------
* Plot a dynamically interpolated swath of pixels.
* For 640x400 this is 2 rows of 18 pixels.
* ebx: from table
* eax: to graphics memory
* ecx: scratch
* ------------------------------------------------------------------------- */
#define PlotPixelsExtra\
subl $2, %eax;\
pushl %edx;\
xorl %edx, %edx;\
PlotPixelsExtraRow;\
addl $SCANWIDTH-18, %eax;\
subl $9, %ebx;\
PlotPixelsExtraRow;\
popl %edx;
#define PlotPixelsExtraRow\
movb $9, %dl;\
1: movb (%ebx), %cl;\
movb %cl, %ch;\
movw %cx, (%eax);\
incl %ebx;\
addl $2, %eax;\
decb %dl;\
jnz 1b;
/* -------------------------------------------------------------------------
* Plot an 80 column character row. We can do this only in 640x400 resolution.
* For 640x400 this is 2 rows of 7 pixels.
* esi: from table
* eax: to graphics memory
* ------------------------------------------------------------------------- */
#define PlotCharacter80Row\
Plot7Pixels(%esi,%eax);\
addl $ SCANWIDTH-6, %eax;/* Go to next row */\
subl $6, %esi;\
Plot7Pixels(%esi,%eax);\
/* -------------------------------------------------------------------------
* Plot a 40 column character row.
* For 640x400 this is 2 rows of 14 pixels.
* esi: from table
* eax: to graphics memory
* ------------------------------------------------------------------------- */
#define PlotCharacter40Row\
PlotCharacter40Row640\
subl $12, %esi;\
addl $ SCANWIDTH-12, %eax;\
PlotCharacter40Row640\
addl $2, %esi;
#define PlotCharacter40Row640\
movl (%esi), %ecx; \
movl %ecx, (%eax); \
addl $4, %esi; \
addl $4, %eax; \
movl (%esi), %ecx; \
movl %ecx, (%eax); \
addl $4, %esi; \
addl $4, %eax; \
movl (%esi), %ecx; \
movl %ecx, (%eax); \
addl $4, %esi; \
addl $4, %eax; \
movw (%esi), %cx; \
movw %cx, (%eax);
/* -------------------------------------------------------------------------
* Plot a 40 column row of lores graphics.
* For 640x400 this is 2 rows of 14 pixels.
* esi: from table
* eax: to graphics memory
* ------------------------------------------------------------------------- */
#define PlotBlockRow \
PlotBlockRow640 \
addl $ SCANWIDTH-12, %eax; \
PlotBlockRow640
#define PlotBlockRow640\
movl %edx, (%eax); \
addl $4, %eax; \
movl %edx, (%eax); \
addl $4, %eax; \
movl %edx, (%eax); \
addl $4, %eax; \
movw %dx, (%eax);
/* -------------------------------------------------------------------------
* Get the adjancent color bytes in memory.
* For 640x400 mode, we need to remember to move around by a factor of 2.
* ebx: graphics memory index
* eax: temp buffer for comparison
* ------------------------------------------------------------------------- */
#define GrabAdjGMBytes\
subl $3, %ebx;\
movw (%ebx), %cx;\
movw %cx, (%eax); /* GM -> temp */\
addl $9, %eax;\
addl $18, %ebx;\
movw (%ebx), %cx;\
movw %cx, (%eax); /* GM -> temp */\
decl %eax;
/* -------------------------------------------------------------------------
* Plots a normalized byte of dhires color directly into graphics memory.
* eax: graphics memory index
* ebx: dhires_colors index
* edx: scratch
* ------------------------------------------------------------------------- */
#define PlotDHiresByte\
movb SN(video__dhires2)(,%ebx,1), %dl;\
movb %dl, %dh;\
shll $16, %edx;\
movb SN(video__dhires1)(,%ebx,1), %dl;\
movb %dl, %dh;\
movl %edx, (%eax);\
movl %edx, SCANWIDTH(%eax);\
addl $4, %eax;
#define PlotDHiresFirstByte\
subl $4, %eax;\
PlotDHiresByte
#else /* if ! _640x400 */
#define LoadHiresTableRef(TABLE)\
leal SN(video__hires_##TABLE)(,%eax,8), %ebx;
/* -------------------------------------------------------------------------
* Plot a normal swath of pixels.
* For 320x200 this is exactly 7 pixels.
* ebx: from table
* eax: to graphics memory
* ------------------------------------------------------------------------- */
#define PlotPixels\
Plot7Pixels(%ebx,%eax)
#define PlotCharacter40Row \
Plot7Pixels(%esi,%eax)
#define PlotBlockRow \
movl %edx, (%eax); \
addl $4, %eax; \
movw %dx, (%eax); \
addl $2, %eax; \
movb %dl, (%eax);
/* -------------------------------------------------------------------------
* Plot a dynamically interpolated swath of pixels
* For 320x200 this is exactly 9 pixels.
* ebx: from table
* eax: to graphics memory
* ecx: scratch
* ------------------------------------------------------------------------- */
#define PlotPixelsExtra\
decl %eax;\
movl (%ebx), %ecx;\
movl %ecx, (%eax);\
addl $4, %eax;\
addl $4, %ebx;\
movl (%ebx), %ecx;\
movl %ecx, (%eax);\
addl $4, %eax;\
addl $4, %ebx;\
movb (%ebx), %cl;\
movb %cl, (%eax);
/* -------------------------------------------------------------------------
* Get the adjancent color bytes in memory.
* ebx: graphics memory index
* eax: temp buffer for comparison
* ------------------------------------------------------------------------- */
#define GrabAdjGMBytes\
subl $2, %ebx;\
movw (%ebx), %cx;\
movw %cx, (%eax); /* GM -> temp */\
addl $9, %eax;\
addl $9, %ebx;\
movw (%ebx), %cx;\
movw %cx, (%eax); /* GM -> temp */\
decl %eax;
/* -------------------------------------------------------------------------
* Plots a normalized byte of dhires color directly into graphics memory.
* eax: graphics memory index
* ebx: dhires_colors index
* edx: scratch
* ------------------------------------------------------------------------- */
#define PlotDHiresByte \
movb SN(video__dhires1)(,%ebx,1), %dl; \
movb SN(video__dhires2)(,%ebx,1), %dh; \
movw %dx, (%eax); \
addl $2, %eax;
#define PlotDHiresFirstByte\
subl $2, %eax;\
PlotDHiresByte
#endif/*_640x400*/
/* -------------------------------------------------------------------------
* Calculate the graphics memory offset based on EffectiveAddr.
* BASE 0x2000, 0x4000
* PTR register to store the offset
* ------------------------------------------------------------------------- */
#define CalcHiresGM(BASE,PTR,GM)\
movl EffectiveAddr_E, %ecx; /* ecx = mem addrs */ \
subw BASE, EffectiveAddr; /* - graphics base */ \
movl SN(video__screen_addresses) \
(,EffectiveAddr_E,4), PTR; /* PTR = GM offset */ \
movl %ecx, EffectiveAddr_E; /* + graphics base */ \
addl SN(GM), PTR; /* PTR += GM base */
/* -------------------------------------------------------------------------
* PlotByte - macro to plot a hires byte into graphics memory.
* BASE = 0x2000,0x4000.
* TABLE = expanded_col_hires_even, expanded_col_hires_odd.
* OPP_TABLE = opposite table
* INTERP_COLOR = video__even_colors, video__odd_colors
* ALT_INTERP_COLOR = opposite colors
* ------------------------------------------------------------------------- */
#define PlotByte(BASE,X,TABLE,OPP_TABLE,INTERP_COLOR,ALT_INTERP_COLOR,GM)\
pushl %eax; /* save regs */ \
pushl %ebx; \
pushl %ecx; \
\
xorb %ah, %ah; /* clear noise */ \
testb $0xFF, SN(video__strictcolors); \
jnz PB_dynamic##X; /* dynamic color mode */\
LoadHiresTableRef(TABLE);\
CalcHiresGM(BASE,%eax,GM); /* eax = GM */\
PlotPixels; /* temp -> GM */\
jmp PB_exit##X;\
\
PB_dynamic##X:\
leal SN(video__hires_##TABLE)(,%eax,8), %ebx;\
leal SN(temp), %eax; /* eax = temp */\
addl $2, %eax;\
Plot7Pixels(%ebx,%eax); /* 7bytes -> temp+2 */\
\
subl $8, %eax;\
CalcHiresGM(BASE,%ebx,GM); /* ebx = GM */\
/* copy adjacent color bytes into temp array */\
GrabAdjGMBytes;\
\
/* calculate dynamic colors in temp array */\
DynamicCalculateColor(X,OPP_TABLE,INTERP_COLOR,ALT_INTERP_COLOR);\
PB_plot_dynamic##X:\
leal SN(temp), %ebx; /* ebx = temp */\
incl %ebx;\
CalcHiresGM(BASE,%eax,GM); /* eax = GM */\
PlotPixelsExtra /* temp -> GM: 1 + 7 + 1 */\
PB_exit##X:\
popl %ecx; /* restore regs */ \
popl %ebx; \
popl %eax;
/* -------------------------------------------------------------------------
* Dynamic calculation of color at the edges of bytes.
* ------------------------------------------------------------------------- */
#define DynamicCalculateColor(X,OPP_TABLE,INTERP_COLOR,ALT_INTERP_COLOR);\
movw (%eax), %cx; \
testb $0xFF, %ch; /* check right color */ \
jz PB_next0##X; /* right black, do other end */ \
movw SN(apple_ii_64k)(,EffectiveAddr_E,1), %cx;\
andb $1, %ch; \
jz PB_black0##X; /* right black */ \
andb $0x40, %cl; \
jz PB_black0##X; /* inside black, right colored */ \
movw $0x3737, (%eax); /* edge is white (#55) */ \
jmp PB_next0##X; \
PB_black0##X: \
movzwl SN(apple_ii_64k)(,EffectiveAddr_E,1), %ecx;\
movb %ch, %cl; \
xorb %ch, %ch; \
leal SN(video__hires_##OPP_TABLE) \
(,%ecx,8), %ebx; \
incl %eax; \
movb (%ebx), %cl; \
movb %cl, (%eax); \
decl %eax; \
PB_next0##X: \
decw EffectiveAddr; /* previous byte */ \
subl $7, %eax; /* left edge of byte */ \
movb (%eax), %cl; \
testb $0xFF, %cl; /* check left color */ \
jz PB_next1##X; /* left black, done */ \
movw SN(apple_ii_64k)(,EffectiveAddr_E,1), %cx;\
andb $0x40, %cl; \
jz PB_black1##X; /* left black */ \
andb $0x1, %ch; \
jz PB_black1##X; /* left colored, inside black */ \
movw $0x3737, (%eax); /* edge is white (#55) */ \
jmp PB_next1##X; \
PB_black1##X: \
movzbl SN(apple_ii_64k)(,EffectiveAddr_E,1), %ecx;\
leal SN(video__hires_##OPP_TABLE) \
(,%ecx,8), %ebx; \
addl $6, %ebx; \
movb (%ebx), %cl; \
movb %cl, (%eax); \
PB_next1##X: \
incw EffectiveAddr; \
/* do extra calculation for interpolated colors */ \
cmpb $2, SN(video__strictcolors); \
jne PB_plot_dynamic##X; \
\
decw EffectiveAddr; \
CalculateInterpColor(X,2,ALT_INTERP_COLOR); \
PB_next2##X: \
incw EffectiveAddr; \
incl %eax; \
CalculateInterpColor(X,3,INTERP_COLOR); \
PB_next3##X: \
addl $6, %eax; \
CalculateInterpColor(X,4,INTERP_COLOR); \
PB_next4##X: \
incw EffectiveAddr; \
incl %eax; \
CalculateInterpColor(X,5,ALT_INTERP_COLOR); \
PB_next5##X: \
decw EffectiveAddr;
/* -------------------------------------------------------------------------
* Calculates the color at the edge of interpolated bytes.
* Done 4 times in little endian order (...7 0...7 0...)
* ------------------------------------------------------------------------- */
#define CalculateInterpColor(X,Y,INTERP_COLOR) \
testb $0xFF, (%eax); \
jnz PB_next##Y##X; /* not black, next */ \
movw (%eax), %cx; /* off+1 in %ch */ \
testb $0xFF, %ch; \
jz PB_next##Y##X; /* off+1 is black, next */ \
movb -1(%eax), %cl; /* off-1 in %cl */ \
testb $0xFF, %cl; \
jz PB_next##Y##X; /* off-1 is black, next */ \
cmpb $55, %cl; /* off-1 is white? */ \
je PB_white0##X##Y; \
movb %cl, (%eax); /* store non-white */ \
jmp PB_next##Y##X; /* next */ \
PB_white0##X##Y: \
cmpb $55, %ch; /* off+1 is white? */ \
je PB_white##X##Y; \
movb %ch, (%eax); /* store non-white */ \
jmp PB_next##Y##X; /* next */ \
PB_white##X##Y: /* both sides are white */ \
movzbl SN(apple_ii_64k)(,EffectiveAddr_E,1), %ecx;\
shrb $7, %cl; \
movb SN(INTERP_COLOR)(,%ecx,1), %bl; \
movb %bl, (%eax);
/* -------------------------------------------------------------------------
* compeletely update all the hires/dhires page rows.
* X=0,1
* OFFSET=0x2027,0x4027 (page 1, 2)
* ------------------------------------------------------------------------- */
#define UpdateHiresRows(PRE,X,OFFSET) \
update_hires_rows_##X: \
movl $20, %ecx; /* ECX: 40 column counter */ \
movl %ebx, %edx; /* EBX: pixel row counter */ \
shrb $3, %dl; /* normalize to 0 - 23 */ \
/* EDI: row offset */ \
movw SN(video__line_offset)(,%edx,2), \
EffectiveAddr; \
movl %ebx, %edx; \
andb $0x7, %dl; \
shlw $10, %dx; /* EDX: offset range 0 - 1C00 */ \
addw OFFSET, %dx; /* add base end-row offset */ \
addw %dx, EffectiveAddr; /* EDI: mem address */ \
update_hires_columns_##X: \
movb SN(apple_ii_64k)(,EffectiveAddr_E,1), %al;\
cmpw $159, %bx; /* mixed mode boundary */ \
jg update_hires_mixed_##X; \
call SN(PRE##odd##X##); \
decw EffectiveAddr; /* previous address */ \
movb SN(apple_ii_64k)(,EffectiveAddr_E,1), %al;\
call SN(PRE##even##X##); \
jmp update_hires_cont_##X; \
update_hires_mixed_##X: \
call SN(PRE##odd##X##_mixed); \
decw EffectiveAddr; /* previous address */ \
movb SN(apple_ii_64k)(,EffectiveAddr_E,1), %al;\
call SN(PRE##even##X##_mixed); \
update_hires_cont_##X: \
decw EffectiveAddr; /* previous address */ \
decb %cl; /* dec column counter */ \
jnz update_hires_columns_##X; \
decw %bx; /* dec row */ \
jns update_hires_rows_##X;
/* -------------------------------------------------------------------------
* compeletely update all the text page rows.
* X=0,1
* OFF=0x427,0x827 (page 1, 2)
* ------------------------------------------------------------------------- */
#define UpdateRows(PRE,X,OFFSET) \
update_rows_##X: \
movl $39, %ecx; \
movw SN(video__line_offset)(,%ebx,2), \
EffectiveAddr; \
addw OFFSET, EffectiveAddr; \
update_columns_##X: \
movb SN(apple_ii_64k)(,EffectiveAddr_E,1), %al;\
cmpb $19, %bl; \
jg update_mixed_##X; \
call SN(PRE##text##X); \
jmp update_cont_##X; \
update_mixed_##X: \
call SN(PRE##text##X##_mixed); \
update_cont_##X: \
decw %di; \
decb %cl; \
jns update_columns_##X; \
decb %bl; \
jns update_rows_##X;
/* -------------------------------------------------------------------------
* Plot a full double hires color byte into GM
* OFF 0x2000, 0x4000
* PROBLEMS:
* graphics artifiacts are not implemented correctly.
* ------------------------------------------------------------------------- */
#define PlotDHires(OFF,X,GM) \
pushl %eax; /* save regs */ \
pushl %ebx; \
pushl %ecx; \
pushl %edx; \
pushl EffectiveAddr_E; \
\
andw $0xFFFF, EffectiveAddr; /* erase offset */ \
btr $0, EffectiveAddr_E; /* normalize */ \
movl EffectiveAddr_E, %ecx; /* ecx = mem addrs */ \
subw OFF, EffectiveAddr; /* - graphics base */ \
movl SN(video__screen_addresses) \
(,EffectiveAddr_E,4), %eax; /* eax = GM offset */ \
movb SN(video__columns) \
(,EffectiveAddr_E,1), %bl; \
addl SN(GM), %eax; /* eax += GM base */ \
\
leal SN(apple_ii_64k), EffectiveAddr_E;\
addl %ecx, EffectiveAddr_E; \
movl EffectiveAddr_E, %ecx; \
addl $BANK2, %ecx; \
\
testb $0xFF, %bl; \
jz plot_dhires##X##_cont; \
movzbl -1(EffectiveAddr_E), %ebx; \
movb 0(%ecx), %bh; \
btr $7, %ebx; \
shrb $3, %bl; \
shlb $4, %bh; \
orb %bh, %bl; \
xorb %bh, %bh; \
PlotDHiresFirstByte \
\
plot_dhires##X##_cont: \
movl %ecx, %edx; \
movb 2(%edx), %cl; \
shll $28, %ecx; \
\
movzbl 1(EffectiveAddr_E), %ebx; \
btr $7, %ebx; /* erase msb */ \
shll $21, %ebx; \
orl %ebx, %ecx; \
\
movzbl 1(%edx), %ebx; \
btr $7, %ebx; /* erase msb */ \
shll $14, %ebx; \
orl %ebx, %ecx; \
\
movzbl 0(EffectiveAddr_E), %ebx; \
btr $7, %ebx; /* erase msb */ \
shll $7, %ebx; \
orl %ebx, %ecx; \
\
movzbl 0(%edx), %ebx; \
btr $7, %ebx; /* erase msb */ \
orl %ebx, %ecx; \
/* 00000001 11111122 22222333 3333xxxx */ \
\
PlotDHiresByte \
shrl $4, %ecx; \
movb %cl, %bl; \
PlotDHiresByte \
shrl $4, %ecx; \
movb %cl, %bl; \
PlotDHiresByte \
shrl $4, %ecx; \
movb %cl, %bl; \
PlotDHiresByte \
shrl $4, %ecx; \
movb %cl, %bl; \
PlotDHiresByte \
shrl $4, %ecx; \
movb %cl, %bl; \
PlotDHiresByte \
shrl $4, %ecx; \
movb %cl, %bl; \
PlotDHiresByte \
popl EffectiveAddr_E; \
andl $0xFFFF, EffectiveAddr_E;/* for safety */ \
popl %edx; \
popl %ecx; /* restore regs */ \
popl %ebx; \
popl %eax; \
ret;
/* -------------------------------------------------------------------------
* setup to plot the text/lores stuff.
* eax: graphics memory pointer
* ------------------------------------------------------------------------- */
#define PlotTextPagePre(OFF,GM,PAGE)\
pushal; /*Save everything -MUST BE MATCHED!*/\
xorb %ah, %ah;\
movl %eax, %esi; /*ESI=EAX=Chr code*/\
subw OFF, EffectiveAddr; /*Normalize scrn addr*/\
/*Compute row*/\
movl SN(video__screen_addresses)(,EffectiveAddr_E,4), %eax;\
addl SN(GM), %eax; /*Graphic addr*/
/* -------------------------------------------------------------------------
* Common code for plotting an 80 column character.
* Only 640x400 resolution can do this.
* eax: graphics memory pointer
* esi: precalculated font pointer
* OFF 0x400, 0x800
* PAGE 0, 1
* ------------------------------------------------------------------------- */
#define Plot80Character(TAG,OFF,GM,PAGE)\
PlotTextPagePre(OFF,GM,PAGE)/* does a pushal */\
plot_80character_correct_page##TAG:\
addw %bx, %ax; /*screen offset*/\
shll $6, %esi; /* * 64 = 8cols * 8rows*/\
addl $ Font80, %esi; /*Font addr*/\
\
PlotCharacter80Row;\
addl $2, %esi;\
addl $ SCANWIDTH-6, %eax; /*Go to next row*/\
\
PlotCharacter80Row;\
addl $2, %esi;\
addl $ SCANWIDTH-6, %eax; /*Go to next row*/\
\
PlotCharacter80Row;\
addl $2, %esi;\
addl $ SCANWIDTH-6, %eax; /*Go to next row*/\
\
PlotCharacter80Row;\
addl $2, %esi;\
addl $ SCANWIDTH-6, %eax; /*Go to next row*/\
\
PlotCharacter80Row;\
addl $2, %esi;\
addl $ SCANWIDTH-6, %eax; /*Go to next row*/\
\
PlotCharacter80Row;\
addl $2, %esi;\
addl $ SCANWIDTH-6, %eax; /*Go to next row*/\
\
PlotCharacter80Row;\
addl $2, %esi;\
addl $ SCANWIDTH-6, %eax; /*Go to next row*/\
\
PlotCharacter80Row;\
\
popal; /* MATCHES pushal from PlotTextPagePre */
/* -----------------------------------------------------------------
* Scan through video memory (text & graphics) and call the updating
* routines. Depending on softswitch settings, either text or
* graphics, page 1 or 2 will be rendered.
* This is called on exit from menu screens, etc.
* ebx: number of rows (counting down)
* ----------------------------------------------------------------- */
E(video_redraw)
pushal
/* Temporarily reset some softswitches. This ensures a
* proper update in the case where the video addresses
* are pointed at auxillary memory, yet a non-80col mode is
* in use.
*/
pushl SN(softswitches)
andl $~(SS_TEXTWRT|SS_HGRWRT|SS_RAMWRT),SN(softswitches)
xorl %eax, %eax
xorl %edi, %edi
/* 24 rows text/lores page 0 */
movl $23, %ebx
UpdateRows(iie_soft_write_,0,$0x427)
/* 24 rows text/lores page 1 */
movl $23, %ebx
UpdateRows(iie_soft_write_,1,$0x827)
/* 192 rows hires page 0 */
movl $191, %ebx
UpdateHiresRows(iie_soft_write_,0,$0x2027)
/* 192 rows hires page 1 */
movl $191, %ebx
UpdateHiresRows(iie_soft_write_,1,$0x4027)
popl SN(softswitches)
popal
ret
/******************************************/
E(video__write_text0)
movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1)
testl $SS_TEXT, SN(softswitches) # Text mode?
jnz plot_character0
testl $SS_HIRES, SN(softswitches) # lores mode?
jz plot_block0
ret
E(video__write_text0_mixed)
movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1)
testl $(SS_TEXT|SS_MIXED), SN(softswitches)
# Text or mixed mode?
jnz plot_character0
testl $SS_HIRES, SN(softswitches) # Not hires mode?
jz plot_block0
ret
E(video__write_text1)
movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1)
testl $SS_TEXT, SN(softswitches)
jnz plot_character1
testl $SS_HIRES, SN(softswitches) # lores mode?
jz plot_block1
ret
E(video__write_text1_mixed)
movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1)
testl $(SS_TEXT|SS_MIXED), SN(softswitches)
# Text or mixed mode?
jnz plot_character1
testl $SS_HIRES, SN(softswitches) # Not hires mode?
jz plot_block1
ret
/* video__write_2e_text0 - handle text page //e specific */
E(video__write_2e_text0)
addl SN(base_textwrt), EffectiveAddr_E
movb %al, (EffectiveAddr_E)
subl SN(base_textwrt), EffectiveAddr_E
iie_soft_write_text0:
testl $SS_TEXT, SN(softswitches) # Text mode?
jz iie_write_lores0 # graphics
testl $SS_80COL, SN(softswitches)
jnz plot_80character0 # 80 col text
testl $SS_TEXTWRT, SN(softswitches)
jnz ram_nop # NOP (in auxram)
jmp plot_character0 # 40 col text
iie_write_lores0:
testl $(SS_HIRES|SS_TEXTWRT), SN(softswitches)
jz plot_block0 # lores & 80col
ret
/* video__write_2e_text0_mixed - handle mixed text page //e specific */
E(video__write_2e_text0_mixed)
addl SN(base_textwrt), EffectiveAddr_E
movb %al, (EffectiveAddr_E)
subl SN(base_textwrt), EffectiveAddr_E
iie_soft_write_text0_mixed:
testl $(SS_TEXT|SS_MIXED), SN(softswitches)
jz iie_write_lores0
testl $SS_80COL, SN(softswitches)
jnz plot_80character0
testl $SS_TEXTWRT, SN(softswitches)
jnz ram_nop # NOP (in auxram)
jmp plot_character0 # 40 col text
/* video__write_2e_text1 - handle text page1 //e specific */
E(video__write_2e_text1)
addl SN(base_ramwrt), EffectiveAddr_E
movb %al, (EffectiveAddr_E)
subl SN(base_ramwrt), EffectiveAddr_E
iie_soft_write_text1:
testl $SS_TEXT, SN(softswitches) # Text mode?
jz iie_write_lores1 # graphics
testl $SS_80COL, SN(softswitches)
jnz plot_80character1 # 80 col text
testl $SS_RAMWRT, SN(softswitches)
jnz ram_nop # NOP (in auxram)
jmp plot_character1 # 40 col text
iie_write_lores1:
testl $(SS_HIRES|SS_RAMWRT), SN(softswitches)
jz plot_block1 # lores & main bank
ret
/* video__write_2e_text1_mixed - handle mixed page 1 //e specific */
E(video__write_2e_text1_mixed)
addl SN(base_ramwrt), EffectiveAddr_E
movb %al, (EffectiveAddr_E)
subl SN(base_ramwrt), EffectiveAddr_E
iie_soft_write_text1_mixed:
testl $(SS_TEXT|SS_MIXED), SN(softswitches)
jz iie_write_lores1
testl $SS_80COL, SN(softswitches)
jnz plot_80character1
testl $SS_RAMWRT, SN(softswitches)
jnz ram_nop # NOP (in auxram)
jmp plot_character1 # 40 col text
E(video__write_even0)
movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1)
testl $SS_TEXT, SN(softswitches) # Text mode?
jnz ram_nop
testl $SS_HIRES, SN(softswitches) # hires mode?
jnz plot_even_byte0
ret
E(video__write_even0_mixed)
movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1)
testl $(SS_TEXT|SS_MIXED), SN(softswitches)
jnz ram_nop # Text/mixed mode?
testl $SS_HIRES, SN(softswitches) # hires mode?
jnz plot_even_byte0
ret
E(video__write_odd0)
movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1)
testl $SS_TEXT, SN(softswitches) # Text mode?
jnz ram_nop
testl $SS_HIRES, SN(softswitches) # hires mode?
jnz plot_odd_byte0
ret
E(video__write_odd0_mixed)
movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1)
testl $(SS_TEXT|SS_MIXED), SN(softswitches)
jnz ram_nop # Text/mixed mode?
testl $SS_HIRES, SN(softswitches) # hires mode?
jnz plot_odd_byte0
ret
/* video__write_2e_even0 - handle hires page //e specific */
E(video__write_2e_even0)
addl SN(base_hgrwrt), EffectiveAddr_E
movb %al, (EffectiveAddr_E)
subl SN(base_hgrwrt), EffectiveAddr_E
iie_soft_write_even0:
testl $SS_TEXT, SN(softswitches)
jnz ram_nop # text
testl $SS_HIRES, SN(softswitches) # hires mode?
jz ram_nop # lores
testl $SS_80COL, SN(softswitches)
jz 1f # not dhires
testl $SS_DHIRES, SN(softswitches)# dhires mode?
jnz iie_plot_dhires0 # dhires
1: testl $SS_HGRWRT, SN(softswitches)
jnz ram_nop # in auxram
jmp plot_even_byte0 # plot hires
/* video__write_2e_even0_mixed - handle mixed hires page //e specific */
E(video__write_2e_even0_mixed)
addl SN(base_hgrwrt), EffectiveAddr_E
movb %al, (EffectiveAddr_E)
subl SN(base_hgrwrt), EffectiveAddr_E
iie_soft_write_even0_mixed:
testl $(SS_TEXT|SS_MIXED), SN(softswitches)
jnz ram_nop # text/mix
testl $SS_HIRES, SN(softswitches) # hires mode?
jz ram_nop # lores
testl $SS_80COL, SN(softswitches)
jz 1f # not dhires
testl $SS_DHIRES, SN(softswitches)# dhires mode?
jnz iie_plot_dhires0 # dhires
1: testl $SS_HGRWRT, SN(softswitches)
jnz ram_nop # in auxram
jmp plot_even_byte0 # plot hires
/* video__write_2e_odd0 - handle hires page //e specific */
E(video__write_2e_odd0)
addl SN(base_hgrwrt), EffectiveAddr_E
movb %al, (EffectiveAddr_E)
subl SN(base_hgrwrt), EffectiveAddr_E
iie_soft_write_odd0:
testl $SS_TEXT, SN(softswitches) # Text mode?
jnz ram_nop # text
testl $SS_HIRES, SN(softswitches) # hires mode?
jz ram_nop # lores
testl $SS_80COL, SN(softswitches)
jz 1f # not dhires
testl $SS_DHIRES, SN(softswitches)# dhires mode?
jnz iie_plot_dhires0 # dhires
1: testl $SS_HGRWRT, SN(softswitches)
jnz ram_nop # in auxram
jmp plot_odd_byte0 # plot hires
/* video__write_2e_odd0_mixed - handle mixed hires page //e specific */
E(video__write_2e_odd0_mixed)
addl SN(base_hgrwrt), EffectiveAddr_E
movb %al, (EffectiveAddr_E)
subl SN(base_hgrwrt), EffectiveAddr_E
iie_soft_write_odd0_mixed:
testl $(SS_TEXT|SS_MIXED), SN(softswitches)
jnz ram_nop # text/mix
testl $SS_HIRES, SN(softswitches) # hires mode?
jz ram_nop # lores
testl $SS_80COL, SN(softswitches)
jz 1f # not dhires
testl $SS_DHIRES, SN(softswitches) # dhires mode?
jnz iie_plot_dhires0 # dhires
1: testl $SS_HGRWRT, SN(softswitches)
jnz ram_nop # in auxram
jmp plot_odd_byte0 # plot hires
E(video__write_even1)
movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1)
testl $SS_TEXT, SN(softswitches) # Text mode?
jnz ram_nop
testl $SS_HIRES, SN(softswitches) # hires mode?
jnz plot_even_byte1
ret
E(video__write_even1_mixed)
movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1)
testl $SS_TEXT|SS_MIXED, SN(softswitches)
jnz ram_nop # text/mixed
testl $SS_HIRES, SN(softswitches) # hires mode?
jnz plot_even_byte1
ret
E(video__write_odd1)
movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1)
testl $SS_TEXT, SN(softswitches) # Text mode?
jnz ram_nop
testl $SS_HIRES, SN(softswitches) # hires mode?
jnz plot_odd_byte1
ret
E(video__write_odd1_mixed)
movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1)
testl $(SS_TEXT|SS_MIXED), SN(softswitches)
jnz ram_nop # text/mixed
testl $SS_HIRES, SN(softswitches) # hires mode?
jnz plot_odd_byte1
ret
/* video__write_2e_even1 - write hires page1 //e specific */
E(video__write_2e_even1)
addl SN(base_ramwrt), EffectiveAddr_E
movb %al, (EffectiveAddr_E)
subl SN(base_ramwrt), EffectiveAddr_E
iie_soft_write_even1:
testl $SS_TEXT, SN(softswitches) # Text mode?
jnz ram_nop # text
testl $SS_HIRES, SN(softswitches) # hires mode?
jz ram_nop # lores
testl $SS_80COL, SN(softswitches)
jz 1f # not dhires
testl $SS_DHIRES, SN(softswitches) # dhires mode?
jnz iie_plot_dhires1 # dhires
1: testl $SS_RAMWRT, SN(softswitches)
jnz ram_nop # in auxram
jmp plot_even_byte1 # plot hires
/* video__write_2e_even1_mixed - write hires page1 //e specific */
E(video__write_2e_even1_mixed)
addl SN(base_ramwrt), EffectiveAddr_E
movb %al, (EffectiveAddr_E)
subl SN(base_ramwrt), EffectiveAddr_E
iie_soft_write_even1_mixed:
testl $(SS_TEXT|SS_MIXED), SN(softswitches)
jnz ram_nop # text/mix
testl $SS_HIRES, SN(softswitches) # hires mode?
jz ram_nop # lores
testl $SS_80COL, SN(softswitches)
jz 1f # not dhires
testl $SS_DHIRES, SN(softswitches)# dhires mode?
jnz iie_plot_dhires1 # dhires
1: testl $SS_RAMWRT, SN(softswitches)
jnz ram_nop # in auxram
jmp plot_even_byte1 # plot hires
/* video__write_2e_odd1 - write hires page1 //e specific */
E(video__write_2e_odd1)
addl SN(base_ramwrt), EffectiveAddr_E
movb %al, (EffectiveAddr_E)
subl SN(base_ramwrt), EffectiveAddr_E
iie_soft_write_odd1:
testl $SS_TEXT, SN(softswitches) # Text mode?
jnz ram_nop # text
testl $SS_HIRES, SN(softswitches) # hires mode?
jz ram_nop # lores
testl $SS_80COL, SN(softswitches)
jz 1f # not dhires
testl $SS_DHIRES, SN(softswitches)# dhires mode?
jnz iie_plot_dhires1 # dhires
1: testl $SS_RAMWRT, SN(softswitches)
jnz ram_nop # in auxram
_iie_plot_hires_page1_odd:
jmp plot_odd_byte1 # plot hires
/* video__write_2e_odd1_mixed - write hires page1 //e specific */
E(video__write_2e_odd1_mixed)
addl SN(base_ramwrt), EffectiveAddr_E
movb %al, (EffectiveAddr_E)
subl SN(base_ramwrt), EffectiveAddr_E
iie_soft_write_odd1_mixed:
testl $(SS_TEXT|SS_MIXED), SN(softswitches)
jnz ram_nop # text/mix
testl $SS_HIRES, SN(softswitches) # hires mode?
jz ram_nop # lores
testl $SS_80COL, SN(softswitches)
jz 1f # not dhires
testl $SS_DHIRES, SN(softswitches)# dhires mode?
jnz iie_plot_dhires1 # dhires
1: testl $SS_RAMWRT, SN(softswitches)
jnz ram_nop # in auxram
jmp plot_odd_byte1 # plot hires
.align 4
iie_plot_dhires0:
PlotDHires($0x2000,0,video__fb1)
ret
iie_plot_dhires1:
PlotDHires($0x4000,1,video__fb2)
ret
#ifdef _640x400
.align 4
plot_80character0:
pushl %ebx
pushl EffectiveAddr_E
orl $0x10000, EffectiveAddr_E # aux ram
movl $0, %ebx # +0 screen offset
movb SN(apple_ii_64k)(,EffectiveAddr_E,1), %al
andl $0xFFFF, EffectiveAddr_E
Plot80Character(0a,$0x400,video__fb1,$0)
popl EffectiveAddr_E # main ram
movl $7, %ebx # +7 screen offset
movb SN(apple_ii_64k)(,EffectiveAddr_E,1), %al
Plot80Character(0b,$0x400,video__fb1,$0)
popl %ebx
ret
.align 4
plot_80character1:
pushl %ebx
pushl EffectiveAddr_E
orl $0x10000, EffectiveAddr_E # aux ram
movl $0, %ebx # +0 screen offset
movb SN(apple_ii_64k)(,EffectiveAddr_E,1), %al
andl $0xFFFF, EffectiveAddr_E
Plot80Character(1a,$0x800,video__fb2,$1)
popl EffectiveAddr_E # main ram
movl $7, %ebx # +7 screen offset
movb SN(apple_ii_64k)(,EffectiveAddr_E,1), %al
Plot80Character(1b,$0x800,video__fb2,$1)
popl %ebx
ret
#else /* !640x400 resolution is not sufficient for 80 column */
.align 4
plot_80character0:
andl $0xFFFF, EffectiveAddr_E/* for safety */
ret
.align 4
plot_80character1:
andl $0xFFFF, EffectiveAddr_E/* for safety */
ret
#endif /* _640x400 */
/* plot character on first text page */
.align 4
plot_character0:
PlotTextPagePre($0x400,video__fb1,$0)
plot_character_correct_page:
#ifdef _640x400
shll $7, %esi # * 128
#else
shll $6, %esi # * 64
#endif
addl $ Font, %esi # Font addr
PlotCharacter40Row
addl $2, %esi;
addl $ SCANSTEP, %eax # Go to next row
PlotCharacter40Row
addl $2, %esi;
addl $ SCANSTEP, %eax # Go to next row
PlotCharacter40Row
addl $2, %esi;
addl $ SCANSTEP, %eax # Go to next row
PlotCharacter40Row
addl $2, %esi;
addl $ SCANSTEP, %eax # Go to next row
PlotCharacter40Row
addl $2, %esi;
addl $ SCANSTEP, %eax # Go to next row
PlotCharacter40Row
addl $2, %esi;
addl $ SCANSTEP, %eax # Go to next row
PlotCharacter40Row
addl $2, %esi;
addl $ SCANSTEP, %eax # Go to next row
PlotCharacter40Row
popal
ret
/* plot character on second text page */
.align 4
plot_character1:
PlotTextPagePre($0x800,video__fb2,$1)
jmp plot_character_correct_page # same as page 0
/* plot lores block first page */
plot_block0:
PlotTextPagePre($0x400,video__fb1,$0)
plot_block_correct_page:
movw %si, %dx # Compute color
andb $0x0F, %dl
shlb $4, %dl
movb %dl, %dh
shll $16, %edx
movw %si, %dx
andb $0x0F, %dl
shlb $4, %dl
movb %dl, %dh
PlotBlockRow
addl $ SCANSTEP, %eax # Go to next row
PlotBlockRow
addl $ SCANSTEP, %eax # Go to next row
PlotBlockRow
addl $ SCANSTEP, %eax # Go to next row
PlotBlockRow
addl $ SCANSTEP, %eax # Go to next row
movw %si, %dx # Compute color
andb $0xF0, %dl
movb %dl, %dh
shll $16, %edx
movw %si, %dx
andb $0xF0, %dl
movb %dl, %dh
PlotBlockRow
addl $ SCANSTEP, %eax # Go to next row
PlotBlockRow
addl $ SCANSTEP, %eax # Go to next row
PlotBlockRow
addl $ SCANSTEP, %eax # Go to next row
PlotBlockRow
popal
ret
.align 4
plot_block1:
PlotTextPagePre($0x800,video__fb2,$1)
jmp plot_block_correct_page
/* plot even column hires byte on page 0 */
.align 4
plot_even_byte0:
PlotByte($0x2000,0,even,odd,video__even_colors,video__odd_colors,video__fb1)
ret
/* plot odd column hires byte on page 0 */
.align 4
plot_odd_byte0:
PlotByte($0x2000,1,odd,even,video__odd_colors,video__even_colors,video__fb1)
ret
/* plot even column hires byte on page 1 */
.align 4
plot_even_byte1:
PlotByte($0x4000,2,even,odd,video__even_colors,video__odd_colors,video__fb2)
ret
/* plot odd column hires byte on page 1 */
.align 4
plot_odd_byte1:
PlotByte($0x4000,3,odd,even,video__odd_colors,video__even_colors,video__fb2)
ret