1216 lines
36 KiB
ArmAsm
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
|
|
|